Importing a bunch of code from Skarsnik sneshacking repo

This commit is contained in:
Justin Scofield
2022-06-11 10:06:54 -04:00
parent 31bf9dad4b
commit ce9ac5383e
8 changed files with 671 additions and 24 deletions

View 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;
}
}
}
}

View 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

View File

@@ -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

View File

@@ -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