diff --git a/YAWMM_DE/meta.xml b/YAWMM_DE/meta.xml
index 01fac2f..788a2ac 100644
--- a/YAWMM_DE/meta.xml
+++ b/YAWMM_DE/meta.xml
@@ -1,19 +1,19 @@
-
-
- Yet Another Wad Manager Mod - Deutsch
- rev5c
- various
- Installiere/Deinstalliere WADs
- Drücken Sie die Taste "A" zum (de)installieren von WADs.
- Wenn keine Datei markiert ist, erscheint das normale einzelne (De)Installations-Menü.
- Wenn mindestens eine Datei markiert ist, erscheint eine Liste im (De)Installations-Menü.
-
- Drücken Sie die "+"-Taste, um die ausgewählten WAD für die Batch-Installation zu (de)markieren
- Drücken Sie die "-"-Taste, um die ausgewählten WAD für die Batch-Deinstallation zu (de)markieren
- Drücken Sie die "1"-Taste, um in das Erweiterungs-Menü zu gelangen
-
- Ein "+" wird vor dem Namen der zu installierenden WAD angezeigt
- Ein "-" wird vor dem Namen der zu deinstallierenden WAD angezeigt
-
-
-
+
+
+ Yet Another Wad Manager Mod - Deutsch
+ rev5c
+ various
+ Installiere/Deinstalliere WADs
+ Drücken Sie die Taste "A" zum (de)installieren von WADs.
+ Wenn keine Datei markiert ist, erscheint das normale einzelne (De)Installations-Menü.
+ Wenn mindestens eine Datei markiert ist, erscheint eine Liste im (De)Installations-Menü.
+
+ Drücken Sie die "+"-Taste, um die ausgewählten WAD für die Batch-Installation zu (de)markieren
+ Drücken Sie die "-"-Taste, um die ausgewählten WAD für die Batch-Deinstallation zu (de)markieren
+ Drücken Sie die "1"-Taste, um in das Erweiterungs-Menü zu gelangen
+
+ Ein "+" wird vor dem Namen der zu installierenden WAD angezeigt
+ Ein "-" wird vor dem Namen der zu deinstallierenden WAD angezeigt
+
+
+
diff --git a/source/libpng/pngu/pngu.c b/source/libpng/pngu/pngu.c
index f98003b..2f6a3b2 100644
--- a/source/libpng/pngu/pngu.c
+++ b/source/libpng/pngu/pngu.c
@@ -1,1132 +1,1132 @@
-/********************************************************************************************
-
-PNGU Version : 0.2a
-
-Coder : frontier
-
-More info : http://frontier-dev.net
-
-********************************************************************************************/
-#include
-#include
-#include "pngu.h"
-#include
-
-
-// Constants
-#define PNGU_SOURCE_BUFFER 1
-#define PNGU_SOURCE_DEVICE 2
-
-
-// Prototypes of helper functions
-int pngu_info (IMGCTX ctx);
-int pngu_decode (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, PNGU_u32 stripAlpha);
-void pngu_free_info (IMGCTX ctx);
-void pngu_read_data_from_buffer (png_structp png_ptr, png_bytep data, png_size_t length);
-void pngu_write_data_to_buffer (png_structp png_ptr, png_bytep data, png_size_t length);
-void pngu_flush_data_to_buffer (png_structp png_ptr);
-int pngu_clamp (int value, int min, int max);
-
-
-// PNGU Image context struct
-struct _IMGCTX
-{
- int source;
- void *buffer;
- char *filename;
- PNGU_u32 cursor;
-
- PNGU_u32 propRead;
- PNGUPROP prop;
-
- PNGU_u32 infoRead;
- png_structp png_ptr;
- png_infop info_ptr;
- FILE *fd;
-
- png_bytep *row_pointers;
- png_bytep img_data;
-};
-
-
-// PNGU Implementation //
-
-IMGCTX PNGU_SelectImageFromBuffer (const void *buffer)
-{
- IMGCTX ctx = NULL;
-
- if (!buffer)
- return NULL;
-
- ctx = malloc (sizeof (struct _IMGCTX));
- if (!ctx)
- return NULL;
-
- ctx->buffer = (void *) buffer;
- ctx->source = PNGU_SOURCE_BUFFER;
- ctx->cursor = 0;
- ctx->filename = NULL;
- ctx->propRead = 0;
- ctx->infoRead = 0;
-
- return ctx;
-}
-
-
-IMGCTX PNGU_SelectImageFromDevice (const char *filename)
-{
- IMGCTX ctx = NULL;
-
- if (!filename)
- return NULL;
-
- ctx = malloc (sizeof (struct _IMGCTX));
- if (!ctx)
- return NULL;
-
- ctx->buffer = NULL;
- ctx->source = PNGU_SOURCE_DEVICE;
- ctx->cursor = 0;
-
- ctx->filename = malloc (strlen (filename) + 1);
- if (!ctx->filename)
- {
- free (ctx);
- return NULL;
- }
- strcpy(ctx->filename, filename);
-
- ctx->propRead = 0;
- ctx->infoRead = 0;
-
- return ctx;
-}
-
-
-void PNGU_ReleaseImageContext (IMGCTX ctx)
-{
- if (!ctx)
- return;
-
- if (ctx->filename)
- free (ctx->filename);
-
- if ((ctx->propRead) && (ctx->prop.trans))
- free (ctx->prop.trans);
-
- pngu_free_info (ctx);
-
- free (ctx);
-}
-
-
-int PNGU_GetImageProperties (IMGCTX ctx, PNGUPROP *imgprop)
-{
- int res;
-
- if (!ctx->propRead)
- {
- res = pngu_info (ctx);
- if (res != PNGU_OK)
- return res;
- }
-
- *imgprop = ctx->prop;
-
- return PNGU_OK;
-}
-
-
-int PNGU_DecodeToYCbYCr (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer, PNGU_u32 stride)
-{
- int result;
- PNGU_u32 x, y, buffWidth;
-
- // width needs to be divisible by two
- if (width % 2)
- return PNGU_ODD_WIDTH;
-
- // stride needs to be divisible by two
- if (stride % 2)
- return PNGU_ODD_STRIDE;
-
- result = pngu_decode (ctx, width, height, 1);
- if (result != PNGU_OK)
- return result;
-
- // Copy image to the output buffer
- buffWidth = (width + stride) / 2;
- for (y = 0; y < height; y++)
- for (x = 0; x < (width / 2); x++)
- ((PNGU_u32 *)buffer)[y*buffWidth+x] = PNGU_RGB8_TO_YCbYCr (*(ctx->row_pointers[y]+x*6), *(ctx->row_pointers[y]+x*6+1), *(ctx->row_pointers[y]+x*6+2),
- *(ctx->row_pointers[y]+x*6+3), *(ctx->row_pointers[y]+x*6+4), *(ctx->row_pointers[y]+x*6+5));
-
- // Free resources
- free (ctx->img_data);
- free (ctx->row_pointers);
-
- // Success
- return PNGU_OK;
-}
-
-
-int PNGU_DecodeToRGB565 (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer, PNGU_u32 stride)
-{
- int result;
- PNGU_u32 x, y, buffWidth;
-
- result = pngu_decode (ctx, width, height, 1);
- if (result != PNGU_OK)
- return result;
-
- buffWidth = width + stride;
-
- // Copy image to the output buffer
- for (y = 0; y < height; y++)
- for (x = 0; x < width; x++)
- ((PNGU_u16 *)buffer)[y*buffWidth+x] =
- (((PNGU_u16) (ctx->row_pointers[y][x*3] & 0xF8)) << 8) |
- (((PNGU_u16) (ctx->row_pointers[y][x*3+1] & 0xFC)) << 3) |
- (((PNGU_u16) (ctx->row_pointers[y][x*3+2] & 0xF8)) >> 3);
-
- // Free resources
- free (ctx->img_data);
- free (ctx->row_pointers);
-
- // Success
- return PNGU_OK;
-}
-
-
-int PNGU_DecodeToRGBA8 (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer, PNGU_u32 stride, PNGU_u8 default_alpha)
-{
- int result;
- PNGU_u32 x, y, buffWidth;
-
- result = pngu_decode (ctx, width, height, 0);
- if (result != PNGU_OK)
- return result;
-
- buffWidth = width + stride;
-
- // Check is source image has an alpha channel
- if ( (ctx->prop.imgColorType == PNGU_COLOR_TYPE_GRAY_ALPHA) || (ctx->prop.imgColorType == PNGU_COLOR_TYPE_RGB_ALPHA) )
- {
- // Alpha channel present, copy image to the output buffer
- for (y = 0; y < height; y++)
- memcpy (buffer + (y * buffWidth * 4), ctx->row_pointers[y], width * 4);
- }
- else
- {
- // No alpha channel present, copy image to the output buffer
- for (y = 0; y < height; y++)
- for (x = 0; x < width; x++)
- ((PNGU_u32 *)buffer)[y*buffWidth+x] =
- (((PNGU_u32) ctx->row_pointers[y][x*3]) << 24) |
- (((PNGU_u32) ctx->row_pointers[y][x*3+1]) << 16) |
- (((PNGU_u32) ctx->row_pointers[y][x*3+2]) << 8) |
- ((PNGU_u32) default_alpha);
- }
-
- // Free resources
- free (ctx->img_data);
- free (ctx->row_pointers);
-
- // Success
- return PNGU_OK;
-}
-
-
-int PNGU_DecodeTo4x4RGB565 (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer)
-{
- int result;
- PNGU_u32 x, y, qwidth, qheight;
-
- // width and height need to be divisible by four
- if ((width % 4) || (height % 4))
- return PNGU_INVALID_WIDTH_OR_HEIGHT;
-
- result = pngu_decode (ctx, width, height, 1);
- if (result != PNGU_OK)
- return result;
-
- // Copy image to the output buffer
- qwidth = width / 4;
- qheight = height / 4;
-
- for (y = 0; y < qheight; y++)
- for (x = 0; x < qwidth; x++)
- {
- int blockbase = (y * qwidth + x) * 4;
-
- PNGU_u64 field64 = *((PNGU_u64 *)(ctx->row_pointers[y*4]+x*12));
- PNGU_u64 field32 = (PNGU_u64) *((PNGU_u32 *)(ctx->row_pointers[y*4]+x*12+8));
- ((PNGU_u64 *) buffer)[blockbase] =
- (((field64 & 0xF800000000000000ULL) | ((field64 & 0xFC000000000000ULL) << 3) | ((field64 & 0xF80000000000ULL) << 5)) |
- (((field64 & 0xF800000000ULL) << 8) | ((field64 & 0xFC000000ULL) << 11) | ((field64 & 0xF80000ULL) << 13)) |
- (((field64 & 0xF800ULL) << 16) | ((field64 & 0xFCULL) << 19) | ((field32 & 0xF8000000ULL) >> 11)) |
- (((field32 & 0xF80000ULL) >> 8) | ((field32 & 0xFC00ULL) >> 5) | ((field32 & 0xF8ULL) >> 3)));
-
- field64 = *((PNGU_u64 *)(ctx->row_pointers[y*4+1]+x*12));
- field32 = (PNGU_u64) *((PNGU_u32 *)(ctx->row_pointers[y*4+1]+x*12+8));
- ((PNGU_u64 *) buffer)[blockbase+1] =
- (((field64 & 0xF800000000000000ULL) | ((field64 & 0xFC000000000000ULL) << 3) | ((field64 & 0xF80000000000ULL) << 5)) |
- (((field64 & 0xF800000000ULL) << 8) | ((field64 & 0xFC000000ULL) << 11) | ((field64 & 0xF80000ULL) << 13)) |
- (((field64 & 0xF800ULL) << 16) | ((field64 & 0xFCULL) << 19) | ((field32 & 0xF8000000ULL) >> 11)) |
- (((field32 & 0xF80000ULL) >> 8) | ((field32 & 0xFC00ULL) >> 5) | ((field32 & 0xF8ULL) >> 3)));
-
- field64 = *((PNGU_u64 *)(ctx->row_pointers[y*4+2]+x*12));
- field32 = (PNGU_u64) *((PNGU_u32 *)(ctx->row_pointers[y*4+2]+x*12+8));
- ((PNGU_u64 *) buffer)[blockbase+2] =
- (((field64 & 0xF800000000000000ULL) | ((field64 & 0xFC000000000000ULL) << 3) | ((field64 & 0xF80000000000ULL) << 5)) |
- (((field64 & 0xF800000000ULL) << 8) | ((field64 & 0xFC000000ULL) << 11) | ((field64 & 0xF80000ULL) << 13)) |
- (((field64 & 0xF800ULL) << 16) | ((field64 & 0xFCULL) << 19) | ((field32 & 0xF8000000ULL) >> 11)) |
- (((field32 & 0xF80000ULL) >> 8) | ((field32 & 0xFC00ULL) >> 5) | ((field32 & 0xF8ULL) >> 3)));
-
- field64 = *((PNGU_u64 *)(ctx->row_pointers[y*4+3]+x*12));
- field32 = (PNGU_u64) *((PNGU_u32 *)(ctx->row_pointers[y*4+3]+x*12+8));
- ((PNGU_u64 *) buffer)[blockbase+3] =
- (((field64 & 0xF800000000000000ULL) | ((field64 & 0xFC000000000000ULL) << 3) | ((field64 & 0xF80000000000ULL) << 5)) |
- (((field64 & 0xF800000000ULL) << 8) | ((field64 & 0xFC000000ULL) << 11) | ((field64 & 0xF80000ULL) << 13)) |
- (((field64 & 0xF800ULL) << 16) | ((field64 & 0xFCULL) << 19) | ((field32 & 0xF8000000ULL) >> 11)) |
- (((field32 & 0xF80000ULL) >> 8) | ((field32 & 0xFC00ULL) >> 5) | ((field32 & 0xF8ULL) >> 3)));
- }
-
- // Free resources
- free (ctx->img_data);
- free (ctx->row_pointers);
-
- // Success
- return PNGU_OK;
-}
-
-
-int PNGU_DecodeTo4x4RGB5A3 (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer, PNGU_u8 default_alpha)
-{
- int result;
- PNGU_u32 x, y, qwidth, qheight;
- PNGU_u64 alphaMask;
-
- // width and height need to be divisible by four
- if ((width % 4) || (height % 4))
- return PNGU_INVALID_WIDTH_OR_HEIGHT;
-
- result = pngu_decode (ctx, width, height, 0);
- if (result != PNGU_OK)
- return result;
-
- // Init some vars
- qwidth = width / 4;
- qheight = height / 4;
-
- // Check is source image has an alpha channel
- if ( (ctx->prop.imgColorType == PNGU_COLOR_TYPE_GRAY_ALPHA) || (ctx->prop.imgColorType == PNGU_COLOR_TYPE_RGB_ALPHA) )
- {
- // Alpha channel present, copy image to the output buffer
- for (y = 0; y < qheight; y++)
- for (x = 0; x < qwidth; x++)
- {
- int blockbase = (y * qwidth + x) * 4;
- PNGU_u64 tmp;
-
- PNGU_u64 fieldA = *((PNGU_u64 *)(ctx->row_pointers[y*4]+x*16));
- PNGU_u64 fieldB = *((PNGU_u64 *)(ctx->row_pointers[y*4]+x*16+8));
- // If first pixel is opaque set MSB to 1 and encode colors in RGB555, else set MSB to 0 and encode colors in ARGB3444
- if ((fieldA & 0xE000000000ULL) == 0xE000000000ULL)
- tmp = 0x8000000000000000ULL | ((fieldA & 0xF800000000000000ULL) >> 1) | ((fieldA & 0xF8000000000000ULL) << 2) | ((fieldA & 0xF80000000000ULL) << 5);
- else
- tmp = ((fieldA & 0xE000000000ULL) << 23) | ((fieldA & 0xF000000000000000ULL) >> 4) | (fieldA & 0xF0000000000000ULL) | ((fieldA & 0xF00000000000ULL) << 4);
-
- // If second pixel is opaque set MSB to 1 and encode colors in RGB555, else set MSB to 0 and encode colors in ARGB3444
- if ((fieldA & 0xE0ULL) == 0xE0ULL)
- tmp = tmp | 0x800000000000ULL | ((fieldA & 0xF8000000ULL) << 15) | ((fieldA & 0xF80000ULL) << 18) | ((fieldA & 0xF800ULL) << 21);
- else
- tmp = tmp | ((fieldA & 0xE0ULL) << 39) | ((fieldA & 0xF0000000ULL) << 12) | ((fieldA & 0xF00000ULL) << 16) | ((fieldA & 0xF000ULL) << 20);
-
- // If third pixel is opaque set MSB to 1 and encode colors in RGB555, else set MSB to 0 and encode colors in ARGB3444
- if ((fieldB & 0xE000000000ULL) == 0xE000000000ULL)
- tmp = tmp | 0x80000000ULL | ((fieldB & 0xF800000000000000ULL) >> 33) | ((fieldB & 0xF8000000000000ULL) >> 30) | ((fieldB & 0xF80000000000ULL) >> 27);
- else
- tmp = tmp | ((fieldB & 0xE000000000ULL) >> 9) | ((fieldB & 0xF000000000000000ULL) >> 36) | ((fieldB & 0xF0000000000000ULL) >> 32) | ((fieldB & 0xF00000000000ULL) >> 28);
-
- // If fourth pixel is opaque set MSB to 1 and encode colors in RGB555, else set MSB to 0 and encode colors in ARGB3444
- if ((fieldB & 0xE0ULL) == 0xE0ULL)
- tmp = tmp | 0x8000ULL | ((fieldB & 0xF8000000ULL) >> 17) | ((fieldB & 0xF80000ULL) >> 14) | ((fieldB & 0xF800ULL) >> 11);
- else
- tmp = tmp | ((fieldB & 0xE0ULL) << 7) | ((fieldB & 0xF0000000ULL) >> 20) | ((fieldB & 0xF00000ULL) >> 16) | ((fieldB & 0xF000ULL) >> 12);
- ((PNGU_u64 *) buffer)[blockbase] = tmp;
-
- fieldA = *((PNGU_u64 *)(ctx->row_pointers[y*4+1]+x*16));
- fieldB = *((PNGU_u64 *)(ctx->row_pointers[y*4+1]+x*16+8));
- if ((fieldA & 0xE000000000ULL) == 0xE000000000ULL)
- // Opaque pixel, so set MSB to 1 and encode colors in RGB555
- tmp = 0x8000000000000000ULL | ((fieldA & 0xF800000000000000ULL) >> 1) | ((fieldA & 0xF8000000000000ULL) << 2) | ((fieldA & 0xF80000000000ULL) << 5);
- else
- // Tranlucid pixel, so set MSB to 0 and encode colors in ARGB3444
- tmp = ((fieldA & 0xE000000000ULL) << 23) | ((fieldA & 0xF000000000000000ULL) >> 4) | (fieldA & 0xF0000000000000ULL) | ((fieldA & 0xF00000000000ULL) << 4);
-
- if ((fieldA & 0xE0ULL) == 0xE0ULL)
- // Opaque pixel, so set MSB to 1 and encode colors in RGB555
- tmp = tmp | 0x800000000000ULL | ((fieldA & 0xF8000000ULL) << 15) | ((fieldA & 0xF80000ULL) << 18) | ((fieldA & 0xF800ULL) << 21);
- else
- // Tranlucid pixel, so set MSB to 0 and encode colors in ARGB3444
- tmp = tmp | ((fieldA & 0xE0ULL) << 39) | ((fieldA & 0xF0000000ULL) << 12) | ((fieldA & 0xF00000ULL) << 16) | ((fieldA & 0xF000ULL) << 20);
-
- if ((fieldB & 0xE000000000ULL) == 0xE000000000ULL)
- // Opaque pixel, so set MSB to 1 and encode colors in RGB555
- tmp = tmp | 0x80000000ULL | ((fieldB & 0xF800000000000000ULL) >> 33) | ((fieldB & 0xF8000000000000ULL) >> 30) | ((fieldB & 0xF80000000000ULL) >> 27);
- else
- // Tranlucid pixel, so set MSB to 0 and encode colors in ARGB3444
- tmp = tmp | ((fieldB & 0xE000000000ULL) >> 9) | ((fieldB & 0xF000000000000000ULL) >> 36) | ((fieldB & 0xF0000000000000ULL) >> 32) | ((fieldB & 0xF00000000000ULL) >> 28);
-
- if ((fieldB & 0xE0ULL) == 0xE0ULL)
- // Opaque pixel, so set MSB to 1 and encode colors in RGB555
- tmp = tmp | 0x8000ULL | ((fieldB & 0xF8000000ULL) >> 17) | ((fieldB & 0xF80000ULL) >> 14) | ((fieldB & 0xF800ULL) >> 11);
- else
- // Tranlucid pixel, so set MSB to 0 and encode colors in ARGB3444
- tmp = tmp | ((fieldB & 0xE0ULL) << 7) | ((fieldB & 0xF0000000ULL) >> 20) | ((fieldB & 0xF00000ULL) >> 16) | ((fieldB & 0xF000ULL) >> 12);
- ((PNGU_u64 *) buffer)[blockbase+1] = tmp;
-
- fieldA = *((PNGU_u64 *)(ctx->row_pointers[y*4+2]+x*16));
- fieldB = *((PNGU_u64 *)(ctx->row_pointers[y*4+2]+x*16+8));
- if ((fieldA & 0xE000000000ULL) == 0xE000000000ULL)
- // Opaque pixel, so set MSB to 1 and encode colors in RGB555
- tmp = 0x8000000000000000ULL | ((fieldA & 0xF800000000000000ULL) >> 1) | ((fieldA & 0xF8000000000000ULL) << 2) | ((fieldA & 0xF80000000000ULL) << 5);
- else
- // Tranlucid pixel, so set MSB to 0 and encode colors in ARGB3444
- tmp = ((fieldA & 0xE000000000ULL) << 23) | ((fieldA & 0xF000000000000000ULL) >> 4) | (fieldA & 0xF0000000000000ULL) | ((fieldA & 0xF00000000000ULL) << 4);
-
- if ((fieldA & 0xE0ULL) == 0xE0ULL)
- // Opaque pixel, so set MSB to 1 and encode colors in RGB555
- tmp = tmp | 0x800000000000ULL | ((fieldA & 0xF8000000ULL) << 15) | ((fieldA & 0xF80000ULL) << 18) | ((fieldA & 0xF800ULL) << 21);
- else
- // Tranlucid pixel, so set MSB to 0 and encode colors in ARGB3444
- tmp = tmp | ((fieldA & 0xE0ULL) << 39) | ((fieldA & 0xF0000000ULL) << 12) | ((fieldA & 0xF00000ULL) << 16) | ((fieldA & 0xF000ULL) << 20);
-
- if ((fieldB & 0xE000000000ULL) == 0xE000000000ULL)
- // Opaque pixel, so set MSB to 1 and encode colors in RGB555
- tmp = tmp | 0x80000000ULL | ((fieldB & 0xF800000000000000ULL) >> 33) | ((fieldB & 0xF8000000000000ULL) >> 30) | ((fieldB & 0xF80000000000ULL) >> 27);
- else
- // Tranlucid pixel, so set MSB to 0 and encode colors in ARGB3444
- tmp = tmp | ((fieldB & 0xE000000000ULL) >> 9) | ((fieldB & 0xF000000000000000ULL) >> 36) | ((fieldB & 0xF0000000000000ULL) >> 32) | ((fieldB & 0xF00000000000ULL) >> 28);
-
- if ((fieldB & 0xE0ULL) == 0xE0ULL)
- // Opaque pixel, so set MSB to 1 and encode colors in RGB555
- tmp = tmp | 0x8000ULL | ((fieldB & 0xF8000000ULL) >> 17) | ((fieldB & 0xF80000ULL) >> 14) | ((fieldB & 0xF800ULL) >> 11);
- else
- // Tranlucid pixel, so set MSB to 0 and encode colors in ARGB3444
- tmp = tmp | ((fieldB & 0xE0ULL) << 7) | ((fieldB & 0xF0000000ULL) >> 20) | ((fieldB & 0xF00000ULL) >> 16) | ((fieldB & 0xF000ULL) >> 12);
- ((PNGU_u64 *) buffer)[blockbase+2] = tmp;
-
- fieldA = *((PNGU_u64 *)(ctx->row_pointers[y*4+3]+x*16));
- fieldB = *((PNGU_u64 *)(ctx->row_pointers[y*4+3]+x*16+8));
- if ((fieldA & 0xE000000000ULL) == 0xE000000000ULL)
- // Opaque pixel, so set MSB to 1 and encode colors in RGB555
- tmp = 0x8000000000000000ULL | ((fieldA & 0xF800000000000000ULL) >> 1) | ((fieldA & 0xF8000000000000ULL) << 2) | ((fieldA & 0xF80000000000ULL) << 5);
- else
- // Tranlucid pixel, so set MSB to 0 and encode colors in ARGB3444
- tmp = ((fieldA & 0xE000000000ULL) << 23) | ((fieldA & 0xF000000000000000ULL) >> 4) | (fieldA & 0xF0000000000000ULL) | ((fieldA & 0xF00000000000ULL) << 4);
-
- if ((fieldA & 0xE0ULL) == 0xE0ULL)
- // Opaque pixel, so set MSB to 1 and encode colors in RGB555
- tmp = tmp | 0x800000000000ULL | ((fieldA & 0xF8000000ULL) << 15) | ((fieldA & 0xF80000ULL) << 18) | ((fieldA & 0xF800ULL) << 21);
- else
- // Tranlucid pixel, so set MSB to 0 and encode colors in ARGB3444
- tmp = tmp | ((fieldA & 0xE0ULL) << 39) | ((fieldA & 0xF0000000ULL) << 12) | ((fieldA & 0xF00000ULL) << 16) | ((fieldA & 0xF000ULL) << 20);
-
- if ((fieldB & 0xE000000000ULL) == 0xE000000000ULL)
- // Opaque pixel, so set MSB to 1 and encode colors in RGB555
- tmp = tmp | 0x80000000ULL | ((fieldB & 0xF800000000000000ULL) >> 33) | ((fieldB & 0xF8000000000000ULL) >> 30) | ((fieldB & 0xF80000000000ULL) >> 27);
- else
- // Tranlucid pixel, so set MSB to 0 and encode colors in ARGB3444
- tmp = tmp | ((fieldB & 0xE000000000ULL) >> 9) | ((fieldB & 0xF000000000000000ULL) >> 36) | ((fieldB & 0xF0000000000000ULL) >> 32) | ((fieldB & 0xF00000000000ULL) >> 28);
-
- if ((fieldB & 0xE0ULL) == 0xE0ULL)
- // Opaque pixel, so set MSB to 1 and encode colors in RGB555
- tmp = tmp | 0x8000ULL | ((fieldB & 0xF8000000ULL) >> 17) | ((fieldB & 0xF80000ULL) >> 14) | ((fieldB & 0xF800ULL) >> 11);
- else
- // Tranlucid pixel, so set MSB to 0 and encode colors in ARGB3444
- tmp = tmp | ((fieldB & 0xE0ULL) << 7) | ((fieldB & 0xF0000000ULL) >> 20) | ((fieldB & 0xF00000ULL) >> 16) | ((fieldB & 0xF000ULL) >> 12);
- ((PNGU_u64 *) buffer)[blockbase+3] = tmp;
- }
- }
- else
- {
- // No alpha channel present, copy image to the output buffer
- default_alpha = (default_alpha >> 5);
- if (default_alpha == 7)
- {
- // The user wants an opaque texture, so set MSB to 1 and encode colors in RGB555
- alphaMask = 0x8000800080008000ULL;
-
- for (y = 0; y < qheight; y++)
- for (x = 0; x < qwidth; x++)
- {
- int blockbase = (y * qwidth + x) * 4;
-
- PNGU_u64 field64 = *((PNGU_u64 *)(ctx->row_pointers[y*4]+x*12));
- PNGU_u64 field32 = (PNGU_u64) *((PNGU_u32 *)(ctx->row_pointers[y*4]+x*12+8));
- ((PNGU_u64 *) buffer)[blockbase] =
- alphaMask | ((field64 & 0xF800000000000000ULL) >> 1) | ((field64 & 0xF8000000000000ULL) << 2) |
- ((field64 & 0xF80000000000ULL) << 5) | ((field64 & 0xF800000000ULL) << 7) | ((field64 & 0xF8000000ULL) << 10) |
- ((field64 & 0xF80000ULL) << 13) | ((field64 & 0xF800ULL) << 15) | ((field64 & 0xF8ULL) << 18) |
- ((field32 & 0xF8000000ULL) >> 11) | ((field32 & 0xF80000ULL) >> 9) | ((field32 & 0xF800ULL) >> 6) | ((field32 & 0xF8ULL) >> 3);
-
- field64 = *((PNGU_u64 *)(ctx->row_pointers[y*4+1]+x*12));
- field32 = (PNGU_u64) *((PNGU_u32 *)(ctx->row_pointers[y*4+1]+x*12+8));
- ((PNGU_u64 *) buffer)[blockbase+1] =
- alphaMask | ((field64 & 0xF800000000000000ULL) >> 1) | ((field64 & 0xF8000000000000ULL) << 2) |
- ((field64 & 0xF80000000000ULL) << 5) | ((field64 & 0xF800000000ULL) << 7) | ((field64 & 0xF8000000ULL) << 10) |
- ((field64 & 0xF80000ULL) << 13) | ((field64 & 0xF800ULL) << 15) | ((field64 & 0xF8ULL) << 18) |
- ((field32 & 0xF8000000ULL) >> 11) | ((field32 & 0xF80000ULL) >> 9) | ((field32 & 0xF800ULL) >> 6) | ((field32 & 0xF8ULL) >> 3);
-
- field64 = *((PNGU_u64 *)(ctx->row_pointers[y*4+2]+x*12));
- field32 = (PNGU_u64) *((PNGU_u32 *)(ctx->row_pointers[y*4+2]+x*12+8));
- ((PNGU_u64 *) buffer)[blockbase+2] =
- alphaMask | ((field64 & 0xF800000000000000ULL) >> 1) | ((field64 & 0xF8000000000000ULL) << 2) |
- ((field64 & 0xF80000000000ULL) << 5) | ((field64 & 0xF800000000ULL) << 7) | ((field64 & 0xF8000000ULL) << 10) |
- ((field64 & 0xF80000ULL) << 13) | ((field64 & 0xF800ULL) << 15) | ((field64 & 0xF8ULL) << 18) |
- ((field32 & 0xF8000000ULL) >> 11) | ((field32 & 0xF80000ULL) >> 9) | ((field32 & 0xF800ULL) >> 6) | ((field32 & 0xF8ULL) >> 3);
-
- field64 = *((PNGU_u64 *)(ctx->row_pointers[y*4+3]+x*12));
- field32 = (PNGU_u64) *((PNGU_u32 *)(ctx->row_pointers[y*4+3]+x*12+8));
- ((PNGU_u64 *) buffer)[blockbase+3] =
- alphaMask | ((field64 & 0xF800000000000000ULL) >> 1) | ((field64 & 0xF8000000000000ULL) << 2) |
- ((field64 & 0xF80000000000ULL) << 5) | ((field64 & 0xF800000000ULL) << 7) | ((field64 & 0xF8000000ULL) << 10) |
- ((field64 & 0xF80000ULL) << 13) | ((field64 & 0xF800ULL) << 15) | ((field64 & 0xF8ULL) << 18) |
- ((field32 & 0xF8000000ULL) >> 11) | ((field32 & 0xF80000ULL) >> 9) | ((field32 & 0xF800ULL) >> 6) | ((field32 & 0xF8ULL) >> 3);
- }
- }
- else
- {
- // The user wants a translucid texture, so set MSB to 0 and encode colors in ARGB3444
- default_alpha = (default_alpha << 4);
- alphaMask = (((PNGU_u64) default_alpha) << 56) | (((PNGU_u64) default_alpha) << 40) |
- (((PNGU_u64) default_alpha) << 24) | (((PNGU_u64) default_alpha) << 8);
-
- for (y = 0; y < qheight; y++)
- for (x = 0; x < qwidth; x++)
- {
- int blockbase = (y * qwidth + x) * 4;
-
- PNGU_u64 field64 = *((PNGU_u64 *)(ctx->row_pointers[y*4]+x*12));
- PNGU_u64 field32 = (PNGU_u64) *((PNGU_u32 *)(ctx->row_pointers[y*4]+x*12+8));
- ((PNGU_u64 *) buffer)[blockbase] =
- alphaMask | ((field64 & 0xF000000000000000ULL) >> 4) | (field64 & 0xF0000000000000ULL) | ((field64 & 0xF00000000000ULL) << 4) |
- ((field64 & 0xF000000000ULL) << 4) | ((field64 & 0xF0000000ULL) << 8) | ((field64 & 0xF00000ULL) << 12) |
- ((field64 & 0xF000ULL) << 12) | ((field64 & 0xF0ULL) << 16) | ((field32 & 0xF0000000ULL) >> 12) |
- ((field32 & 0xF00000ULL) >> 12) | ((field32 & 0xF000ULL) >> 8) | ((field32 & 0xF0ULL) >> 4);
-
- field64 = *((PNGU_u64 *)(ctx->row_pointers[y*4+1]+x*12));
- field32 = (PNGU_u64) *((PNGU_u32 *)(ctx->row_pointers[y*4+1]+x*12+8));
- ((PNGU_u64 *) buffer)[blockbase+1] =
- alphaMask | ((field64 & 0xF000000000000000ULL) >> 4) | (field64 & 0xF0000000000000ULL) | ((field64 & 0xF00000000000ULL) << 4) |
- ((field64 & 0xF000000000ULL) << 4) | ((field64 & 0xF0000000ULL) << 8) | ((field64 & 0xF00000ULL) << 12) |
- ((field64 & 0xF000ULL) << 12) | ((field64 & 0xF0ULL) << 16) | ((field32 & 0xF0000000ULL) >> 12) |
- ((field32 & 0xF00000ULL) >> 12) | ((field32 & 0xF000ULL) >> 8) | ((field32 & 0xF0ULL) >> 4);
-
- field64 = *((PNGU_u64 *)(ctx->row_pointers[y*4+2]+x*12));
- field32 = (PNGU_u64) *((PNGU_u32 *)(ctx->row_pointers[y*4+2]+x*12+8));
- ((PNGU_u64 *) buffer)[blockbase+2] =
- alphaMask | ((field64 & 0xF000000000000000ULL) >> 4) | (field64 & 0xF0000000000000ULL) | ((field64 & 0xF00000000000ULL) << 4) |
- ((field64 & 0xF000000000ULL) << 4) | ((field64 & 0xF0000000ULL) << 8) | ((field64 & 0xF00000ULL) << 12) |
- ((field64 & 0xF000ULL) << 12) | ((field64 & 0xF0ULL) << 16) | ((field32 & 0xF0000000ULL) >> 12) |
- ((field32 & 0xF00000ULL) >> 12) | ((field32 & 0xF000ULL) >> 8) | ((field32 & 0xF0ULL) >> 4);
-
- field64 = *((PNGU_u64 *)(ctx->row_pointers[y*4+3]+x*12));
- field32 = (PNGU_u64) *((PNGU_u32 *)(ctx->row_pointers[y*4+3]+x*12+8));
- ((PNGU_u64 *) buffer)[blockbase+3] =
- alphaMask | ((field64 & 0xF000000000000000ULL) >> 4) | (field64 & 0xF0000000000000ULL) | ((field64 & 0xF00000000000ULL) << 4) |
- ((field64 & 0xF000000000ULL) << 4) | ((field64 & 0xF0000000ULL) << 8) | ((field64 & 0xF00000ULL) << 12) |
- ((field64 & 0xF000ULL) << 12) | ((field64 & 0xF0ULL) << 16) | ((field32 & 0xF0000000ULL) >> 12) |
- ((field32 & 0xF00000ULL) >> 12) | ((field32 & 0xF000ULL) >> 8) | ((field32 & 0xF0ULL) >> 4);
- }
- }
- }
-
- // Free resources
- free (ctx->img_data);
- free (ctx->row_pointers);
-
- // Success
- return PNGU_OK;
-}
-
-
-int PNGU_DecodeTo4x4RGBA8 (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer, PNGU_u8 default_alpha)
-{
- int result;
- PNGU_u32 x, y, qwidth, qheight;
- PNGU_u64 alphaMask;
-
- // width and height need to be divisible by four
- if ((width % 4) || (height % 4))
- return PNGU_INVALID_WIDTH_OR_HEIGHT;
-
- result = pngu_decode (ctx, width, height, 0);
- if (result != PNGU_OK)
- return result;
-
- // Init some variables
- qwidth = width / 4;
- qheight = height / 4;
-
- // Check is source image has an alpha channel
- if ( (ctx->prop.imgColorType == PNGU_COLOR_TYPE_GRAY_ALPHA) || (ctx->prop.imgColorType == PNGU_COLOR_TYPE_RGB_ALPHA) )
- {
- // Alpha channel present, copy image to the output buffer
- for (y = 0; y < qheight; y++)
- for (x = 0; x < qwidth; x++)
- {
- int blockbase = (y * qwidth + x) * 8;
-
- PNGU_u64 fieldA = *((PNGU_u64 *)(ctx->row_pointers[y*4]+x*16));
- PNGU_u64 fieldB = *((PNGU_u64 *)(ctx->row_pointers[y*4]+x*16+8));
- ((PNGU_u64 *) buffer)[blockbase] =
- ((fieldA & 0xFF00000000ULL) << 24) | ((fieldA & 0xFF00000000000000ULL) >> 8) |
- ((fieldA & 0xFFULL) << 40) | ((fieldA & 0xFF000000ULL) << 8) |
- ((fieldB & 0xFF00000000ULL) >> 8) | ((fieldB & 0xFF00000000000000ULL) >> 40) |
- ((fieldB & 0xFFULL) << 8) | ((fieldB & 0xFF000000ULL) >> 24);
- ((PNGU_u64 *) buffer)[blockbase+4] =
- ((fieldA & 0xFFFF0000000000ULL) << 8) | ((fieldA & 0xFFFF00ULL) << 24) |
- ((fieldB & 0xFFFF0000000000ULL) >> 24) | ((fieldB & 0xFFFF00ULL) >> 8);
-
- fieldA = *((PNGU_u64 *)(ctx->row_pointers[y*4+1]+x*16));
- fieldB = *((PNGU_u64 *)(ctx->row_pointers[y*4+1]+x*16+8));
- ((PNGU_u64 *) buffer)[blockbase+1] =
- ((fieldA & 0xFF00000000ULL) << 24) | ((fieldA & 0xFF00000000000000ULL) >> 8) |
- ((fieldA & 0xFFULL) << 40) | ((fieldA & 0xFF000000ULL) << 8) |
- ((fieldB & 0xFF00000000ULL) >> 8) | ((fieldB & 0xFF00000000000000ULL) >> 40) |
- ((fieldB & 0xFFULL) << 8) | ((fieldB & 0xFF000000ULL) >> 24);
- ((PNGU_u64 *) buffer)[blockbase+5] =
- ((fieldA & 0xFFFF0000000000ULL) << 8) | ((fieldA & 0xFFFF00ULL) << 24) |
- ((fieldB & 0xFFFF0000000000ULL) >> 24) | ((fieldB & 0xFFFF00ULL) >> 8);
-
- fieldA = *((PNGU_u64 *)(ctx->row_pointers[y*4+2]+x*16));
- fieldB = *((PNGU_u64 *)(ctx->row_pointers[y*4+2]+x*16+8));
- ((PNGU_u64 *) buffer)[blockbase+2] =
- ((fieldA & 0xFF00000000ULL) << 24) | ((fieldA & 0xFF00000000000000ULL) >> 8) |
- ((fieldA & 0xFFULL) << 40) | ((fieldA & 0xFF000000ULL) << 8) |
- ((fieldB & 0xFF00000000ULL) >> 8) | ((fieldB & 0xFF00000000000000ULL) >> 40) |
- ((fieldB & 0xFFULL) << 8) | ((fieldB & 0xFF000000ULL) >> 24);
- ((PNGU_u64 *) buffer)[blockbase+6] =
- ((fieldA & 0xFFFF0000000000ULL) << 8) | ((fieldA & 0xFFFF00ULL) << 24) |
- ((fieldB & 0xFFFF0000000000ULL) >> 24) | ((fieldB & 0xFFFF00ULL) >> 8);
-
- fieldA = *((PNGU_u64 *)(ctx->row_pointers[y*4+3]+x*16));
- fieldB = *((PNGU_u64 *)(ctx->row_pointers[y*4+3]+x*16+8));
- ((PNGU_u64 *) buffer)[blockbase+3] =
- ((fieldA & 0xFF00000000ULL) << 24) | ((fieldA & 0xFF00000000000000ULL) >> 8) |
- ((fieldA & 0xFFULL) << 40) | ((fieldA & 0xFF000000ULL) << 8) |
- ((fieldB & 0xFF00000000ULL) >> 8) | ((fieldB & 0xFF00000000000000ULL) >> 40) |
- ((fieldB & 0xFFULL) << 8) | ((fieldB & 0xFF000000ULL) >> 24);
- ((PNGU_u64 *) buffer)[blockbase+7] =
- ((fieldA & 0xFFFF0000000000ULL) << 8) | ((fieldA & 0xFFFF00ULL) << 24) |
- ((fieldB & 0xFFFF0000000000ULL) >> 24) | ((fieldB & 0xFFFF00ULL) >> 8);
- }
- }
- else
- {
- // No alpha channel present, copy image to the output buffer
- alphaMask = (((PNGU_u64)default_alpha) << 56) | (((PNGU_u64)default_alpha) << 40) |
- (((PNGU_u64)default_alpha) << 24) | (((PNGU_u64)default_alpha) << 8);
-
- for (y = 0; y < qheight; y++)
- for (x = 0; x < qwidth; x++)
- {
- int blockbase = (y * qwidth + x) * 8;
-
- PNGU_u64 field64 = *((PNGU_u64 *)(ctx->row_pointers[y*4]+x*12));
- PNGU_u64 field32 = (PNGU_u64) *((PNGU_u32 *)(ctx->row_pointers[y*4]+x*12+8));
- ((PNGU_u64 *) buffer)[blockbase] =
- (((field64 & 0xFF00000000000000ULL) >> 8) | (field64 & 0xFF00000000ULL) |
- ((field64 & 0xFF00ULL) << 8) | ((field32 & 0xFF0000ULL) >> 16) | alphaMask);
- ((PNGU_u64 *) buffer)[blockbase+4] =
- (((field64 & 0xFFFF0000000000ULL) << 8) | ((field64 & 0xFFFF0000ULL) << 16) |
- ((field64 & 0xFFULL) << 24) | ((field32 & 0xFF000000ULL) >> 8) | (field32 & 0xFFFFULL));
-
- field64 = *((PNGU_u64 *)(ctx->row_pointers[y*4+1]+x*12));
- field32 = (PNGU_u64) *((PNGU_u32 *)(ctx->row_pointers[y*4+1]+x*12+8));
- ((PNGU_u64 *) buffer)[blockbase+1] =
- (((field64 & 0xFF00000000000000ULL) >> 8) | (field64 & 0xFF00000000ULL) |
- ((field64 & 0xFF00ULL) << 8) | ((field32 & 0xFF0000ULL) >> 16) | alphaMask);
- ((PNGU_u64 *) buffer)[blockbase+5] =
- (((field64 & 0xFFFF0000000000ULL) << 8) | ((field64 & 0xFFFF0000ULL) << 16) |
- ((field64 & 0xFFULL) << 24) | ((field32 & 0xFF000000ULL) >> 8) | (field32 & 0xFFFFULL));
-
- field64 = *((PNGU_u64 *)(ctx->row_pointers[y*4+2]+x*12));
- field32 = (PNGU_u64) *((PNGU_u32 *)(ctx->row_pointers[y*4+2]+x*12+8));
- ((PNGU_u64 *) buffer)[blockbase+2] =
- (((field64 & 0xFF00000000000000ULL) >> 8) | (field64 & 0xFF00000000ULL) |
- ((field64 & 0xFF00ULL) << 8) | ((field32 & 0xFF0000ULL) >> 16) | alphaMask);
- ((PNGU_u64 *) buffer)[blockbase+6] =
- (((field64 & 0xFFFF0000000000ULL) << 8) | ((field64 & 0xFFFF0000ULL) << 16) |
- ((field64 & 0xFFULL) << 24) | ((field32 & 0xFF000000ULL) >> 8) | (field32 & 0xFFFFULL));
-
- field64 = *((PNGU_u64 *)(ctx->row_pointers[y*4+3]+x*12));
- field32 = (PNGU_u64) *((PNGU_u32 *)(ctx->row_pointers[y*4+3]+x*12+8));
- ((PNGU_u64 *) buffer)[blockbase+3] =
- (((field64 & 0xFF00000000000000ULL) >> 8) | (field64 & 0xFF00000000ULL) |
- ((field64 & 0xFF00ULL) << 8) | ((field32 & 0xFF0000ULL) >> 16) | alphaMask);
- ((PNGU_u64 *) buffer)[blockbase+7] =
- (((field64 & 0xFFFF0000000000ULL) << 8) | ((field64 & 0xFFFF0000ULL) << 16) |
- ((field64 & 0xFFULL) << 24) | ((field32 & 0xFF000000ULL) >> 8) | (field32 & 0xFFFFULL));
- }
- }
-
- // Free resources
- free (ctx->img_data);
- free (ctx->row_pointers);
-
- // Success
- return PNGU_OK;
-}
-
-
-int PNGU_EncodeFromYCbYCr (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer, PNGU_u32 stride)
-{
- png_uint_32 rowbytes;
- PNGU_u32 x, y, buffWidth;
-
- // Erase from the context any readed info
- pngu_free_info (ctx);
- ctx->propRead = 0;
-
- // Check if the user has selected a file to write the image
- if (ctx->source == PNGU_SOURCE_BUFFER);
-
- else if (ctx->source == PNGU_SOURCE_DEVICE)
- {
- // Open file
- if (!(ctx->fd = fopen (ctx->filename, "wb")))
- return PNGU_CANT_OPEN_FILE;
- }
-
- else
- return PNGU_NO_FILE_SELECTED;
-
- // Allocation of libpng structs
- ctx->png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
- if (!(ctx->png_ptr))
- {
- if (ctx->source == PNGU_SOURCE_DEVICE)
- fclose (ctx->fd);
- return PNGU_LIB_ERROR;
- }
-
- ctx->info_ptr = png_create_info_struct (ctx->png_ptr);
- if (!(ctx->info_ptr))
- {
- png_destroy_write_struct (&(ctx->png_ptr), (png_infopp)NULL);
- if (ctx->source == PNGU_SOURCE_DEVICE)
- fclose (ctx->fd);
- return PNGU_LIB_ERROR;
- }
-
- if (ctx->source == PNGU_SOURCE_BUFFER)
- {
- // Installation of our custom data writer function
- ctx->cursor = 0;
- png_set_write_fn (ctx->png_ptr, ctx, pngu_write_data_to_buffer, pngu_flush_data_to_buffer);
- }
- else if (ctx->source == PNGU_SOURCE_DEVICE)
- {
- // Default data writer uses function fwrite, so it needs to use our FILE*
- png_init_io (ctx->png_ptr, ctx->fd);
- }
-
- // Setup output file properties
- png_set_IHDR (ctx->png_ptr, ctx->info_ptr, width, height, 8, PNG_COLOR_TYPE_RGB,
- PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
-
- // Allocate memory to store the image in RGB format
- rowbytes = width * 3;
- if (rowbytes % 4)
- rowbytes = ((rowbytes / 4) + 1) * 4; // Add extra padding so each row starts in a 4 byte boundary
-
- ctx->img_data = malloc (rowbytes * height);
- if (!ctx->img_data)
- {
- png_destroy_write_struct (&(ctx->png_ptr), (png_infopp)NULL);
- if (ctx->source == PNGU_SOURCE_DEVICE)
- fclose (ctx->fd);
- return PNGU_LIB_ERROR;
- }
-
- ctx->row_pointers = malloc (sizeof (png_bytep) * height);
- if (!ctx->row_pointers)
- {
- png_destroy_write_struct (&(ctx->png_ptr), (png_infopp)NULL);
- if (ctx->source == PNGU_SOURCE_DEVICE)
- fclose (ctx->fd);
- return PNGU_LIB_ERROR;
- }
-
- // Encode YCbYCr image into RGB8 format
- buffWidth = (width + stride) / 2;
- for (y = 0; y < height; y++)
- {
- ctx->row_pointers[y] = ctx->img_data + (y * rowbytes);
-
- for (x = 0; x < (width / 2); x++)
- PNGU_YCbYCr_TO_RGB8 ( ((PNGU_u32 *)buffer)[y*buffWidth+x],
- ((PNGU_u8 *) ctx->row_pointers[y]+x*6), ((PNGU_u8 *) ctx->row_pointers[y]+x*6+1),
- ((PNGU_u8 *) ctx->row_pointers[y]+x*6+2), ((PNGU_u8 *) ctx->row_pointers[y]+x*6+3),
- ((PNGU_u8 *) ctx->row_pointers[y]+x*6+4), ((PNGU_u8 *) ctx->row_pointers[y]+x*6+5) );
- }
-
- // Tell libpng where is our image data
- png_set_rows (ctx->png_ptr, ctx->info_ptr, ctx->row_pointers);
-
- // Write file header and image data
- png_write_png (ctx->png_ptr, ctx->info_ptr, PNG_TRANSFORM_IDENTITY, NULL);
-
- // Tell libpng we have no more data to write
- png_write_end (ctx->png_ptr, (png_infop) NULL);
-
- // Free resources
- free (ctx->img_data);
- free (ctx->row_pointers);
- png_destroy_write_struct (&(ctx->png_ptr), &(ctx->info_ptr));
- if (ctx->source == PNGU_SOURCE_DEVICE)
- fclose (ctx->fd);
-
- // Success
- return PNGU_OK;
-}
-
-
-// This function is taken from a libogc example
-PNGU_u32 PNGU_RGB8_TO_YCbYCr (PNGU_u8 r1, PNGU_u8 g1, PNGU_u8 b1, PNGU_u8 r2, PNGU_u8 g2, PNGU_u8 b2)
-{
- int y1, cb1, cr1, y2, cb2, cr2, cb, cr;
-
- y1 = (299 * r1 + 587 * g1 + 114 * b1) / 1000;
- cb1 = (-16874 * r1 - 33126 * g1 + 50000 * b1 + 12800000) / 100000;
- cr1 = (50000 * r1 - 41869 * g1 - 8131 * b1 + 12800000) / 100000;
-
- y2 = (299 * r2 + 587 * g2 + 114 * b2) / 1000;
- cb2 = (-16874 * r2 - 33126 * g2 + 50000 * b2 + 12800000) / 100000;
- cr2 = (50000 * r2 - 41869 * g2 - 8131 * b2 + 12800000) / 100000;
-
- cb = (cb1 + cb2) >> 1;
- cr = (cr1 + cr2) >> 1;
-
- return (PNGU_u32) ((y1 << 24) | (cb << 16) | (y2 << 8) | cr);
-}
-
-
-void PNGU_YCbYCr_TO_RGB8 (PNGU_u32 ycbycr, PNGU_u8 *r1, PNGU_u8 *g1, PNGU_u8 *b1, PNGU_u8 *r2, PNGU_u8 *g2, PNGU_u8 *b2)
-{
- PNGU_u8 *val = (PNGU_u8 *) &ycbycr;
- int r, g, b;
-
- r = 1.371f * (val[3] - 128);
- g = - 0.698f * (val[3] - 128) - 0.336f * (val[1] - 128);
- b = 1.732f * (val[1] - 128);
-
- *r1 = pngu_clamp (val[0] + r, 0, 255);
- *g1 = pngu_clamp (val[0] + g, 0, 255);
- *b1 = pngu_clamp (val[0] + b, 0, 255);
-
- *r2 = pngu_clamp (val[2] + r, 0, 255);
- *g2 = pngu_clamp (val[2] + g, 0, 255);
- *b2 = pngu_clamp (val[2] + b, 0, 255);
-}
-
-
-int pngu_info (IMGCTX ctx)
-{
- png_byte magic[8];
- png_uint_32 width;
- png_uint_32 height;
- png_color_16p background;
- png_bytep trans;
- png_color_16p trans_values;
- int scale, i;
-
- // Check if there is a file selected and if it is a valid .png
- if (ctx->source == PNGU_SOURCE_BUFFER)
- memcpy (magic, ctx->buffer, 8);
-
- else if (ctx->source == PNGU_SOURCE_DEVICE)
- {
- // Open file
- if (!(ctx->fd = fopen (ctx->filename, "rb")))
- return PNGU_CANT_OPEN_FILE;
-
- // Load first 8 bytes into magic buffer
- if (fread (magic, 1, 8, ctx->fd) != 8)
- {
- fclose (ctx->fd);
- return PNGU_CANT_READ_FILE;
- }
- }
-
- else
- return PNGU_NO_FILE_SELECTED;;
-
- if (png_sig_cmp(magic, 0, 8) != 0)
- {
- if (ctx->source == PNGU_SOURCE_DEVICE)
- fclose (ctx->fd);
- return PNGU_FILE_IS_NOT_PNG;
- }
-
- // Allocation of libpng structs
- ctx->png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
- if (!(ctx->png_ptr))
- {
- if (ctx->source == PNGU_SOURCE_DEVICE)
- fclose (ctx->fd);
- return PNGU_LIB_ERROR;
- }
-
- ctx->info_ptr = png_create_info_struct (ctx->png_ptr);
- if (!(ctx->info_ptr))
- {
- if (ctx->source == PNGU_SOURCE_DEVICE)
- fclose (ctx->fd);
- png_destroy_read_struct (&(ctx->png_ptr), (png_infopp)NULL, (png_infopp)NULL);
- return PNGU_LIB_ERROR;
- }
-
- if (ctx->source == PNGU_SOURCE_BUFFER)
- {
- // Installation of our custom data provider function
- ctx->cursor = 0;
- png_set_read_fn (ctx->png_ptr, ctx, pngu_read_data_from_buffer);
- }
- else if (ctx->source == PNGU_SOURCE_DEVICE)
- {
- // Default data provider uses function fread, so it needs to use our FILE*
- png_init_io (ctx->png_ptr, ctx->fd);
- png_set_sig_bytes (ctx->png_ptr, 8); // We have read 8 bytes already to check PNG authenticity
- }
-
- // Read png header
- png_read_info (ctx->png_ptr, ctx->info_ptr);
-
- // Query image properties if they have not been queried before
- if (!ctx->propRead)
- {
- png_get_IHDR(ctx->png_ptr, ctx->info_ptr, &width, &height,
- (int *) &(ctx->prop.imgBitDepth),
- (int *) &(ctx->prop.imgColorType),
- NULL, NULL, NULL);
-
- ctx->prop.imgWidth = width;
- ctx->prop.imgHeight = height;
- switch (ctx->prop.imgColorType)
- {
- case PNG_COLOR_TYPE_GRAY:
- ctx->prop.imgColorType = PNGU_COLOR_TYPE_GRAY;
- break;
- case PNG_COLOR_TYPE_GRAY_ALPHA:
- ctx->prop.imgColorType = PNGU_COLOR_TYPE_GRAY_ALPHA;
- break;
- case PNG_COLOR_TYPE_PALETTE:
- ctx->prop.imgColorType = PNGU_COLOR_TYPE_PALETTE;
- break;
- case PNG_COLOR_TYPE_RGB:
- ctx->prop.imgColorType = PNGU_COLOR_TYPE_RGB;
- break;
- case PNG_COLOR_TYPE_RGB_ALPHA:
- ctx->prop.imgColorType = PNGU_COLOR_TYPE_RGB_ALPHA;
- break;
- default:
- ctx->prop.imgColorType = PNGU_COLOR_TYPE_UNKNOWN;
- break;
- }
-
- // Constant used to scale 16 bit values to 8 bit values
- scale = 1;
- if (ctx->prop.imgBitDepth == 16)
- scale = 256;
-
- // Query background color, if any.
- ctx->prop.validBckgrnd = 0;
- if (((ctx->prop.imgColorType == PNGU_COLOR_TYPE_RGB) || (ctx->prop.imgColorType == PNGU_COLOR_TYPE_RGB_ALPHA)) &&
- (png_get_bKGD (ctx->png_ptr, ctx->info_ptr, &background)))
- {
- ctx->prop.validBckgrnd = 1;
- ctx->prop.bckgrnd.r = background->red / scale;
- ctx->prop.bckgrnd.g = background->green / scale;
- ctx->prop.bckgrnd.b = background->blue / scale;
- }
- else if (((ctx->prop.imgColorType == PNGU_COLOR_TYPE_GRAY) || (ctx->prop.imgColorType == PNGU_COLOR_TYPE_GRAY_ALPHA)) &&
- (png_get_bKGD (ctx->png_ptr, ctx->info_ptr, &background)))
- {
- ctx->prop.validBckgrnd = 1;
- ctx->prop.bckgrnd.r = ctx->prop.bckgrnd.g = ctx->prop.bckgrnd.b = background->gray / scale;
- }
-
- // Query list of transparent colors, if any.
- ctx->prop.numTrans = 0;
- ctx->prop.trans = NULL;
- if (((ctx->prop.imgColorType == PNGU_COLOR_TYPE_RGB) || (ctx->prop.imgColorType == PNGU_COLOR_TYPE_RGB_ALPHA)) &&
- (png_get_tRNS (ctx->png_ptr, ctx->info_ptr, &trans, (int *) &(ctx->prop.numTrans), &trans_values)))
- {
- if (ctx->prop.numTrans)
- {
- ctx->prop.trans = malloc (sizeof (PNGUCOLOR) * ctx->prop.numTrans);
- if (ctx->prop.trans)
- for (i = 0; i < ctx->prop.numTrans; i++)
- {
- ctx->prop.trans[i].r = trans_values[i].red / scale;
- ctx->prop.trans[i].g = trans_values[i].green / scale;
- ctx->prop.trans[i].b = trans_values[i].blue / scale;
- }
- else
- ctx->prop.numTrans = 0;
- }
- }
- else if (((ctx->prop.imgColorType == PNGU_COLOR_TYPE_GRAY) || (ctx->prop.imgColorType == PNGU_COLOR_TYPE_GRAY_ALPHA)) &&
- (png_get_tRNS (ctx->png_ptr, ctx->info_ptr, &trans, (int *) &(ctx->prop.numTrans), &trans_values)))
- {
- if (ctx->prop.numTrans)
- {
- ctx->prop.trans = malloc (sizeof (PNGUCOLOR) * ctx->prop.numTrans);
- if (ctx->prop.trans)
- for (i = 0; i < ctx->prop.numTrans; i++)
- ctx->prop.trans[i].r = ctx->prop.trans[i].g = ctx->prop.trans[i].b =
- trans_values[i].gray / scale;
- else
- ctx->prop.numTrans = 0;
- }
- }
-
- ctx->propRead = 1;
- }
-
- // Success
- ctx->infoRead = 1;
-
- return PNGU_OK;
-}
-
-
-int pngu_decode (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, PNGU_u32 stripAlpha)
-{
- png_uint_32 rowbytes;
- int i;
-
- // Read info if it hasn't been read before
- if (!ctx->infoRead)
- {
- i = pngu_info (ctx);
- if (i != PNGU_OK)
- return i;
- }
-
- // Check if the user has specified the real width and height of the image
- if ( (ctx->prop.imgWidth != width) || (ctx->prop.imgHeight != height) )
- return PNGU_INVALID_WIDTH_OR_HEIGHT;
-
- // Check if color type is supported by PNGU
- if ( (ctx->prop.imgColorType == PNGU_COLOR_TYPE_PALETTE) || (ctx->prop.imgColorType == PNGU_COLOR_TYPE_UNKNOWN) )
- return PNGU_UNSUPPORTED_COLOR_TYPE;
-
- // Scale 16 bit samples to 8 bit
- if (ctx->prop.imgBitDepth == 16)
- png_set_strip_16 (ctx->png_ptr);
-
- // Remove alpha channel if we don't need it
- if (stripAlpha && ((ctx->prop.imgColorType == PNGU_COLOR_TYPE_RGB_ALPHA) || (ctx->prop.imgColorType == PNGU_COLOR_TYPE_GRAY_ALPHA)))
- png_set_strip_alpha (ctx->png_ptr);
-
- // Expand 1, 2 and 4 bit samples to 8 bit
- if (ctx->prop.imgBitDepth < 8)
- png_set_packing (ctx->png_ptr);
-
- // Transform grayscale images to RGB
- if ( (ctx->prop.imgColorType == PNGU_COLOR_TYPE_GRAY) || (ctx->prop.imgColorType == PNGU_COLOR_TYPE_GRAY_ALPHA) )
- png_set_gray_to_rgb (ctx->png_ptr);
-
- // Flush transformations
- png_read_update_info (ctx->png_ptr, ctx->info_ptr);
-
- // Allocate memory to store the image
- rowbytes = png_get_rowbytes (ctx->png_ptr, ctx->info_ptr);
- if (rowbytes % 4)
- rowbytes = ((rowbytes / 4) + 1) * 4; // Add extra padding so each row starts in a 4 byte boundary
-
- ctx->img_data = malloc (rowbytes * ctx->prop.imgHeight);
- if (!ctx->img_data)
- {
- pngu_free_info (ctx);
- return PNGU_LIB_ERROR;
- }
-
- ctx->row_pointers = malloc (sizeof (png_bytep) * ctx->prop.imgHeight);
- if (!ctx->row_pointers)
- {
- free (ctx->img_data);
- pngu_free_info (ctx);
- return PNGU_LIB_ERROR;
- }
-
- for (i = 0; i < ctx->prop.imgHeight; i++)
- ctx->row_pointers[i] = ctx->img_data + (i * rowbytes);
-
- // Transform the image and copy it to our allocated memory
- png_read_image (ctx->png_ptr, ctx->row_pointers);
-
- // Free resources
- pngu_free_info (ctx);
-
- // Success
- return PNGU_OK;
-}
-
-
-void pngu_free_info (IMGCTX ctx)
-{
- if (ctx->infoRead)
- {
- if (ctx->source == PNGU_SOURCE_DEVICE)
- fclose (ctx->fd);
-
- png_destroy_read_struct (&(ctx->png_ptr), &(ctx->info_ptr), (png_infopp)NULL);
-
- ctx->infoRead = 0;
- }
-}
-
-
-// Custom data provider function used for reading from memory buffers.
-void pngu_read_data_from_buffer (png_structp png_ptr, png_bytep data, png_size_t length)
-{
- IMGCTX ctx = (IMGCTX) png_get_io_ptr (png_ptr);
- memcpy (data, ctx->buffer + ctx->cursor, length);
- ctx->cursor += length;
-}
-
-
-// Custom data writer function used for writing to memory buffers.
-void pngu_write_data_to_buffer (png_structp png_ptr, png_bytep data, png_size_t length)
-{
- IMGCTX ctx = (IMGCTX) png_get_io_ptr (png_ptr);
- memcpy (ctx->buffer + ctx->cursor, data, length);
- ctx->cursor += length;
-}
-
-
-// Custom data flusher function used for writing to memory buffers.
-void pngu_flush_data_to_buffer (png_structp png_ptr)
-{
- // Nothing to do here
-}
-
-
-// Function used in YCbYCr to RGB decoding
-int pngu_clamp (int value, int min, int max)
-{
- if (value < min)
- value = min;
- else if (value > max)
- value = max;
-
- return value;
-}
-
+/********************************************************************************************
+
+PNGU Version : 0.2a
+
+Coder : frontier
+
+More info : http://frontier-dev.net
+
+********************************************************************************************/
+#include
+#include
+#include "pngu.h"
+#include
+
+
+// Constants
+#define PNGU_SOURCE_BUFFER 1
+#define PNGU_SOURCE_DEVICE 2
+
+
+// Prototypes of helper functions
+int pngu_info (IMGCTX ctx);
+int pngu_decode (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, PNGU_u32 stripAlpha);
+void pngu_free_info (IMGCTX ctx);
+void pngu_read_data_from_buffer (png_structp png_ptr, png_bytep data, png_size_t length);
+void pngu_write_data_to_buffer (png_structp png_ptr, png_bytep data, png_size_t length);
+void pngu_flush_data_to_buffer (png_structp png_ptr);
+int pngu_clamp (int value, int min, int max);
+
+
+// PNGU Image context struct
+struct _IMGCTX
+{
+ int source;
+ void *buffer;
+ char *filename;
+ PNGU_u32 cursor;
+
+ PNGU_u32 propRead;
+ PNGUPROP prop;
+
+ PNGU_u32 infoRead;
+ png_structp png_ptr;
+ png_infop info_ptr;
+ FILE *fd;
+
+ png_bytep *row_pointers;
+ png_bytep img_data;
+};
+
+
+// PNGU Implementation //
+
+IMGCTX PNGU_SelectImageFromBuffer (const void *buffer)
+{
+ IMGCTX ctx = NULL;
+
+ if (!buffer)
+ return NULL;
+
+ ctx = malloc (sizeof (struct _IMGCTX));
+ if (!ctx)
+ return NULL;
+
+ ctx->buffer = (void *) buffer;
+ ctx->source = PNGU_SOURCE_BUFFER;
+ ctx->cursor = 0;
+ ctx->filename = NULL;
+ ctx->propRead = 0;
+ ctx->infoRead = 0;
+
+ return ctx;
+}
+
+
+IMGCTX PNGU_SelectImageFromDevice (const char *filename)
+{
+ IMGCTX ctx = NULL;
+
+ if (!filename)
+ return NULL;
+
+ ctx = malloc (sizeof (struct _IMGCTX));
+ if (!ctx)
+ return NULL;
+
+ ctx->buffer = NULL;
+ ctx->source = PNGU_SOURCE_DEVICE;
+ ctx->cursor = 0;
+
+ ctx->filename = malloc (strlen (filename) + 1);
+ if (!ctx->filename)
+ {
+ free (ctx);
+ return NULL;
+ }
+ strcpy(ctx->filename, filename);
+
+ ctx->propRead = 0;
+ ctx->infoRead = 0;
+
+ return ctx;
+}
+
+
+void PNGU_ReleaseImageContext (IMGCTX ctx)
+{
+ if (!ctx)
+ return;
+
+ if (ctx->filename)
+ free (ctx->filename);
+
+ if ((ctx->propRead) && (ctx->prop.trans))
+ free (ctx->prop.trans);
+
+ pngu_free_info (ctx);
+
+ free (ctx);
+}
+
+
+int PNGU_GetImageProperties (IMGCTX ctx, PNGUPROP *imgprop)
+{
+ int res;
+
+ if (!ctx->propRead)
+ {
+ res = pngu_info (ctx);
+ if (res != PNGU_OK)
+ return res;
+ }
+
+ *imgprop = ctx->prop;
+
+ return PNGU_OK;
+}
+
+
+int PNGU_DecodeToYCbYCr (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer, PNGU_u32 stride)
+{
+ int result;
+ PNGU_u32 x, y, buffWidth;
+
+ // width needs to be divisible by two
+ if (width % 2)
+ return PNGU_ODD_WIDTH;
+
+ // stride needs to be divisible by two
+ if (stride % 2)
+ return PNGU_ODD_STRIDE;
+
+ result = pngu_decode (ctx, width, height, 1);
+ if (result != PNGU_OK)
+ return result;
+
+ // Copy image to the output buffer
+ buffWidth = (width + stride) / 2;
+ for (y = 0; y < height; y++)
+ for (x = 0; x < (width / 2); x++)
+ ((PNGU_u32 *)buffer)[y*buffWidth+x] = PNGU_RGB8_TO_YCbYCr (*(ctx->row_pointers[y]+x*6), *(ctx->row_pointers[y]+x*6+1), *(ctx->row_pointers[y]+x*6+2),
+ *(ctx->row_pointers[y]+x*6+3), *(ctx->row_pointers[y]+x*6+4), *(ctx->row_pointers[y]+x*6+5));
+
+ // Free resources
+ free (ctx->img_data);
+ free (ctx->row_pointers);
+
+ // Success
+ return PNGU_OK;
+}
+
+
+int PNGU_DecodeToRGB565 (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer, PNGU_u32 stride)
+{
+ int result;
+ PNGU_u32 x, y, buffWidth;
+
+ result = pngu_decode (ctx, width, height, 1);
+ if (result != PNGU_OK)
+ return result;
+
+ buffWidth = width + stride;
+
+ // Copy image to the output buffer
+ for (y = 0; y < height; y++)
+ for (x = 0; x < width; x++)
+ ((PNGU_u16 *)buffer)[y*buffWidth+x] =
+ (((PNGU_u16) (ctx->row_pointers[y][x*3] & 0xF8)) << 8) |
+ (((PNGU_u16) (ctx->row_pointers[y][x*3+1] & 0xFC)) << 3) |
+ (((PNGU_u16) (ctx->row_pointers[y][x*3+2] & 0xF8)) >> 3);
+
+ // Free resources
+ free (ctx->img_data);
+ free (ctx->row_pointers);
+
+ // Success
+ return PNGU_OK;
+}
+
+
+int PNGU_DecodeToRGBA8 (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer, PNGU_u32 stride, PNGU_u8 default_alpha)
+{
+ int result;
+ PNGU_u32 x, y, buffWidth;
+
+ result = pngu_decode (ctx, width, height, 0);
+ if (result != PNGU_OK)
+ return result;
+
+ buffWidth = width + stride;
+
+ // Check is source image has an alpha channel
+ if ( (ctx->prop.imgColorType == PNGU_COLOR_TYPE_GRAY_ALPHA) || (ctx->prop.imgColorType == PNGU_COLOR_TYPE_RGB_ALPHA) )
+ {
+ // Alpha channel present, copy image to the output buffer
+ for (y = 0; y < height; y++)
+ memcpy (buffer + (y * buffWidth * 4), ctx->row_pointers[y], width * 4);
+ }
+ else
+ {
+ // No alpha channel present, copy image to the output buffer
+ for (y = 0; y < height; y++)
+ for (x = 0; x < width; x++)
+ ((PNGU_u32 *)buffer)[y*buffWidth+x] =
+ (((PNGU_u32) ctx->row_pointers[y][x*3]) << 24) |
+ (((PNGU_u32) ctx->row_pointers[y][x*3+1]) << 16) |
+ (((PNGU_u32) ctx->row_pointers[y][x*3+2]) << 8) |
+ ((PNGU_u32) default_alpha);
+ }
+
+ // Free resources
+ free (ctx->img_data);
+ free (ctx->row_pointers);
+
+ // Success
+ return PNGU_OK;
+}
+
+
+int PNGU_DecodeTo4x4RGB565 (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer)
+{
+ int result;
+ PNGU_u32 x, y, qwidth, qheight;
+
+ // width and height need to be divisible by four
+ if ((width % 4) || (height % 4))
+ return PNGU_INVALID_WIDTH_OR_HEIGHT;
+
+ result = pngu_decode (ctx, width, height, 1);
+ if (result != PNGU_OK)
+ return result;
+
+ // Copy image to the output buffer
+ qwidth = width / 4;
+ qheight = height / 4;
+
+ for (y = 0; y < qheight; y++)
+ for (x = 0; x < qwidth; x++)
+ {
+ int blockbase = (y * qwidth + x) * 4;
+
+ PNGU_u64 field64 = *((PNGU_u64 *)(ctx->row_pointers[y*4]+x*12));
+ PNGU_u64 field32 = (PNGU_u64) *((PNGU_u32 *)(ctx->row_pointers[y*4]+x*12+8));
+ ((PNGU_u64 *) buffer)[blockbase] =
+ (((field64 & 0xF800000000000000ULL) | ((field64 & 0xFC000000000000ULL) << 3) | ((field64 & 0xF80000000000ULL) << 5)) |
+ (((field64 & 0xF800000000ULL) << 8) | ((field64 & 0xFC000000ULL) << 11) | ((field64 & 0xF80000ULL) << 13)) |
+ (((field64 & 0xF800ULL) << 16) | ((field64 & 0xFCULL) << 19) | ((field32 & 0xF8000000ULL) >> 11)) |
+ (((field32 & 0xF80000ULL) >> 8) | ((field32 & 0xFC00ULL) >> 5) | ((field32 & 0xF8ULL) >> 3)));
+
+ field64 = *((PNGU_u64 *)(ctx->row_pointers[y*4+1]+x*12));
+ field32 = (PNGU_u64) *((PNGU_u32 *)(ctx->row_pointers[y*4+1]+x*12+8));
+ ((PNGU_u64 *) buffer)[blockbase+1] =
+ (((field64 & 0xF800000000000000ULL) | ((field64 & 0xFC000000000000ULL) << 3) | ((field64 & 0xF80000000000ULL) << 5)) |
+ (((field64 & 0xF800000000ULL) << 8) | ((field64 & 0xFC000000ULL) << 11) | ((field64 & 0xF80000ULL) << 13)) |
+ (((field64 & 0xF800ULL) << 16) | ((field64 & 0xFCULL) << 19) | ((field32 & 0xF8000000ULL) >> 11)) |
+ (((field32 & 0xF80000ULL) >> 8) | ((field32 & 0xFC00ULL) >> 5) | ((field32 & 0xF8ULL) >> 3)));
+
+ field64 = *((PNGU_u64 *)(ctx->row_pointers[y*4+2]+x*12));
+ field32 = (PNGU_u64) *((PNGU_u32 *)(ctx->row_pointers[y*4+2]+x*12+8));
+ ((PNGU_u64 *) buffer)[blockbase+2] =
+ (((field64 & 0xF800000000000000ULL) | ((field64 & 0xFC000000000000ULL) << 3) | ((field64 & 0xF80000000000ULL) << 5)) |
+ (((field64 & 0xF800000000ULL) << 8) | ((field64 & 0xFC000000ULL) << 11) | ((field64 & 0xF80000ULL) << 13)) |
+ (((field64 & 0xF800ULL) << 16) | ((field64 & 0xFCULL) << 19) | ((field32 & 0xF8000000ULL) >> 11)) |
+ (((field32 & 0xF80000ULL) >> 8) | ((field32 & 0xFC00ULL) >> 5) | ((field32 & 0xF8ULL) >> 3)));
+
+ field64 = *((PNGU_u64 *)(ctx->row_pointers[y*4+3]+x*12));
+ field32 = (PNGU_u64) *((PNGU_u32 *)(ctx->row_pointers[y*4+3]+x*12+8));
+ ((PNGU_u64 *) buffer)[blockbase+3] =
+ (((field64 & 0xF800000000000000ULL) | ((field64 & 0xFC000000000000ULL) << 3) | ((field64 & 0xF80000000000ULL) << 5)) |
+ (((field64 & 0xF800000000ULL) << 8) | ((field64 & 0xFC000000ULL) << 11) | ((field64 & 0xF80000ULL) << 13)) |
+ (((field64 & 0xF800ULL) << 16) | ((field64 & 0xFCULL) << 19) | ((field32 & 0xF8000000ULL) >> 11)) |
+ (((field32 & 0xF80000ULL) >> 8) | ((field32 & 0xFC00ULL) >> 5) | ((field32 & 0xF8ULL) >> 3)));
+ }
+
+ // Free resources
+ free (ctx->img_data);
+ free (ctx->row_pointers);
+
+ // Success
+ return PNGU_OK;
+}
+
+
+int PNGU_DecodeTo4x4RGB5A3 (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer, PNGU_u8 default_alpha)
+{
+ int result;
+ PNGU_u32 x, y, qwidth, qheight;
+ PNGU_u64 alphaMask;
+
+ // width and height need to be divisible by four
+ if ((width % 4) || (height % 4))
+ return PNGU_INVALID_WIDTH_OR_HEIGHT;
+
+ result = pngu_decode (ctx, width, height, 0);
+ if (result != PNGU_OK)
+ return result;
+
+ // Init some vars
+ qwidth = width / 4;
+ qheight = height / 4;
+
+ // Check is source image has an alpha channel
+ if ( (ctx->prop.imgColorType == PNGU_COLOR_TYPE_GRAY_ALPHA) || (ctx->prop.imgColorType == PNGU_COLOR_TYPE_RGB_ALPHA) )
+ {
+ // Alpha channel present, copy image to the output buffer
+ for (y = 0; y < qheight; y++)
+ for (x = 0; x < qwidth; x++)
+ {
+ int blockbase = (y * qwidth + x) * 4;
+ PNGU_u64 tmp;
+
+ PNGU_u64 fieldA = *((PNGU_u64 *)(ctx->row_pointers[y*4]+x*16));
+ PNGU_u64 fieldB = *((PNGU_u64 *)(ctx->row_pointers[y*4]+x*16+8));
+ // If first pixel is opaque set MSB to 1 and encode colors in RGB555, else set MSB to 0 and encode colors in ARGB3444
+ if ((fieldA & 0xE000000000ULL) == 0xE000000000ULL)
+ tmp = 0x8000000000000000ULL | ((fieldA & 0xF800000000000000ULL) >> 1) | ((fieldA & 0xF8000000000000ULL) << 2) | ((fieldA & 0xF80000000000ULL) << 5);
+ else
+ tmp = ((fieldA & 0xE000000000ULL) << 23) | ((fieldA & 0xF000000000000000ULL) >> 4) | (fieldA & 0xF0000000000000ULL) | ((fieldA & 0xF00000000000ULL) << 4);
+
+ // If second pixel is opaque set MSB to 1 and encode colors in RGB555, else set MSB to 0 and encode colors in ARGB3444
+ if ((fieldA & 0xE0ULL) == 0xE0ULL)
+ tmp = tmp | 0x800000000000ULL | ((fieldA & 0xF8000000ULL) << 15) | ((fieldA & 0xF80000ULL) << 18) | ((fieldA & 0xF800ULL) << 21);
+ else
+ tmp = tmp | ((fieldA & 0xE0ULL) << 39) | ((fieldA & 0xF0000000ULL) << 12) | ((fieldA & 0xF00000ULL) << 16) | ((fieldA & 0xF000ULL) << 20);
+
+ // If third pixel is opaque set MSB to 1 and encode colors in RGB555, else set MSB to 0 and encode colors in ARGB3444
+ if ((fieldB & 0xE000000000ULL) == 0xE000000000ULL)
+ tmp = tmp | 0x80000000ULL | ((fieldB & 0xF800000000000000ULL) >> 33) | ((fieldB & 0xF8000000000000ULL) >> 30) | ((fieldB & 0xF80000000000ULL) >> 27);
+ else
+ tmp = tmp | ((fieldB & 0xE000000000ULL) >> 9) | ((fieldB & 0xF000000000000000ULL) >> 36) | ((fieldB & 0xF0000000000000ULL) >> 32) | ((fieldB & 0xF00000000000ULL) >> 28);
+
+ // If fourth pixel is opaque set MSB to 1 and encode colors in RGB555, else set MSB to 0 and encode colors in ARGB3444
+ if ((fieldB & 0xE0ULL) == 0xE0ULL)
+ tmp = tmp | 0x8000ULL | ((fieldB & 0xF8000000ULL) >> 17) | ((fieldB & 0xF80000ULL) >> 14) | ((fieldB & 0xF800ULL) >> 11);
+ else
+ tmp = tmp | ((fieldB & 0xE0ULL) << 7) | ((fieldB & 0xF0000000ULL) >> 20) | ((fieldB & 0xF00000ULL) >> 16) | ((fieldB & 0xF000ULL) >> 12);
+ ((PNGU_u64 *) buffer)[blockbase] = tmp;
+
+ fieldA = *((PNGU_u64 *)(ctx->row_pointers[y*4+1]+x*16));
+ fieldB = *((PNGU_u64 *)(ctx->row_pointers[y*4+1]+x*16+8));
+ if ((fieldA & 0xE000000000ULL) == 0xE000000000ULL)
+ // Opaque pixel, so set MSB to 1 and encode colors in RGB555
+ tmp = 0x8000000000000000ULL | ((fieldA & 0xF800000000000000ULL) >> 1) | ((fieldA & 0xF8000000000000ULL) << 2) | ((fieldA & 0xF80000000000ULL) << 5);
+ else
+ // Tranlucid pixel, so set MSB to 0 and encode colors in ARGB3444
+ tmp = ((fieldA & 0xE000000000ULL) << 23) | ((fieldA & 0xF000000000000000ULL) >> 4) | (fieldA & 0xF0000000000000ULL) | ((fieldA & 0xF00000000000ULL) << 4);
+
+ if ((fieldA & 0xE0ULL) == 0xE0ULL)
+ // Opaque pixel, so set MSB to 1 and encode colors in RGB555
+ tmp = tmp | 0x800000000000ULL | ((fieldA & 0xF8000000ULL) << 15) | ((fieldA & 0xF80000ULL) << 18) | ((fieldA & 0xF800ULL) << 21);
+ else
+ // Tranlucid pixel, so set MSB to 0 and encode colors in ARGB3444
+ tmp = tmp | ((fieldA & 0xE0ULL) << 39) | ((fieldA & 0xF0000000ULL) << 12) | ((fieldA & 0xF00000ULL) << 16) | ((fieldA & 0xF000ULL) << 20);
+
+ if ((fieldB & 0xE000000000ULL) == 0xE000000000ULL)
+ // Opaque pixel, so set MSB to 1 and encode colors in RGB555
+ tmp = tmp | 0x80000000ULL | ((fieldB & 0xF800000000000000ULL) >> 33) | ((fieldB & 0xF8000000000000ULL) >> 30) | ((fieldB & 0xF80000000000ULL) >> 27);
+ else
+ // Tranlucid pixel, so set MSB to 0 and encode colors in ARGB3444
+ tmp = tmp | ((fieldB & 0xE000000000ULL) >> 9) | ((fieldB & 0xF000000000000000ULL) >> 36) | ((fieldB & 0xF0000000000000ULL) >> 32) | ((fieldB & 0xF00000000000ULL) >> 28);
+
+ if ((fieldB & 0xE0ULL) == 0xE0ULL)
+ // Opaque pixel, so set MSB to 1 and encode colors in RGB555
+ tmp = tmp | 0x8000ULL | ((fieldB & 0xF8000000ULL) >> 17) | ((fieldB & 0xF80000ULL) >> 14) | ((fieldB & 0xF800ULL) >> 11);
+ else
+ // Tranlucid pixel, so set MSB to 0 and encode colors in ARGB3444
+ tmp = tmp | ((fieldB & 0xE0ULL) << 7) | ((fieldB & 0xF0000000ULL) >> 20) | ((fieldB & 0xF00000ULL) >> 16) | ((fieldB & 0xF000ULL) >> 12);
+ ((PNGU_u64 *) buffer)[blockbase+1] = tmp;
+
+ fieldA = *((PNGU_u64 *)(ctx->row_pointers[y*4+2]+x*16));
+ fieldB = *((PNGU_u64 *)(ctx->row_pointers[y*4+2]+x*16+8));
+ if ((fieldA & 0xE000000000ULL) == 0xE000000000ULL)
+ // Opaque pixel, so set MSB to 1 and encode colors in RGB555
+ tmp = 0x8000000000000000ULL | ((fieldA & 0xF800000000000000ULL) >> 1) | ((fieldA & 0xF8000000000000ULL) << 2) | ((fieldA & 0xF80000000000ULL) << 5);
+ else
+ // Tranlucid pixel, so set MSB to 0 and encode colors in ARGB3444
+ tmp = ((fieldA & 0xE000000000ULL) << 23) | ((fieldA & 0xF000000000000000ULL) >> 4) | (fieldA & 0xF0000000000000ULL) | ((fieldA & 0xF00000000000ULL) << 4);
+
+ if ((fieldA & 0xE0ULL) == 0xE0ULL)
+ // Opaque pixel, so set MSB to 1 and encode colors in RGB555
+ tmp = tmp | 0x800000000000ULL | ((fieldA & 0xF8000000ULL) << 15) | ((fieldA & 0xF80000ULL) << 18) | ((fieldA & 0xF800ULL) << 21);
+ else
+ // Tranlucid pixel, so set MSB to 0 and encode colors in ARGB3444
+ tmp = tmp | ((fieldA & 0xE0ULL) << 39) | ((fieldA & 0xF0000000ULL) << 12) | ((fieldA & 0xF00000ULL) << 16) | ((fieldA & 0xF000ULL) << 20);
+
+ if ((fieldB & 0xE000000000ULL) == 0xE000000000ULL)
+ // Opaque pixel, so set MSB to 1 and encode colors in RGB555
+ tmp = tmp | 0x80000000ULL | ((fieldB & 0xF800000000000000ULL) >> 33) | ((fieldB & 0xF8000000000000ULL) >> 30) | ((fieldB & 0xF80000000000ULL) >> 27);
+ else
+ // Tranlucid pixel, so set MSB to 0 and encode colors in ARGB3444
+ tmp = tmp | ((fieldB & 0xE000000000ULL) >> 9) | ((fieldB & 0xF000000000000000ULL) >> 36) | ((fieldB & 0xF0000000000000ULL) >> 32) | ((fieldB & 0xF00000000000ULL) >> 28);
+
+ if ((fieldB & 0xE0ULL) == 0xE0ULL)
+ // Opaque pixel, so set MSB to 1 and encode colors in RGB555
+ tmp = tmp | 0x8000ULL | ((fieldB & 0xF8000000ULL) >> 17) | ((fieldB & 0xF80000ULL) >> 14) | ((fieldB & 0xF800ULL) >> 11);
+ else
+ // Tranlucid pixel, so set MSB to 0 and encode colors in ARGB3444
+ tmp = tmp | ((fieldB & 0xE0ULL) << 7) | ((fieldB & 0xF0000000ULL) >> 20) | ((fieldB & 0xF00000ULL) >> 16) | ((fieldB & 0xF000ULL) >> 12);
+ ((PNGU_u64 *) buffer)[blockbase+2] = tmp;
+
+ fieldA = *((PNGU_u64 *)(ctx->row_pointers[y*4+3]+x*16));
+ fieldB = *((PNGU_u64 *)(ctx->row_pointers[y*4+3]+x*16+8));
+ if ((fieldA & 0xE000000000ULL) == 0xE000000000ULL)
+ // Opaque pixel, so set MSB to 1 and encode colors in RGB555
+ tmp = 0x8000000000000000ULL | ((fieldA & 0xF800000000000000ULL) >> 1) | ((fieldA & 0xF8000000000000ULL) << 2) | ((fieldA & 0xF80000000000ULL) << 5);
+ else
+ // Tranlucid pixel, so set MSB to 0 and encode colors in ARGB3444
+ tmp = ((fieldA & 0xE000000000ULL) << 23) | ((fieldA & 0xF000000000000000ULL) >> 4) | (fieldA & 0xF0000000000000ULL) | ((fieldA & 0xF00000000000ULL) << 4);
+
+ if ((fieldA & 0xE0ULL) == 0xE0ULL)
+ // Opaque pixel, so set MSB to 1 and encode colors in RGB555
+ tmp = tmp | 0x800000000000ULL | ((fieldA & 0xF8000000ULL) << 15) | ((fieldA & 0xF80000ULL) << 18) | ((fieldA & 0xF800ULL) << 21);
+ else
+ // Tranlucid pixel, so set MSB to 0 and encode colors in ARGB3444
+ tmp = tmp | ((fieldA & 0xE0ULL) << 39) | ((fieldA & 0xF0000000ULL) << 12) | ((fieldA & 0xF00000ULL) << 16) | ((fieldA & 0xF000ULL) << 20);
+
+ if ((fieldB & 0xE000000000ULL) == 0xE000000000ULL)
+ // Opaque pixel, so set MSB to 1 and encode colors in RGB555
+ tmp = tmp | 0x80000000ULL | ((fieldB & 0xF800000000000000ULL) >> 33) | ((fieldB & 0xF8000000000000ULL) >> 30) | ((fieldB & 0xF80000000000ULL) >> 27);
+ else
+ // Tranlucid pixel, so set MSB to 0 and encode colors in ARGB3444
+ tmp = tmp | ((fieldB & 0xE000000000ULL) >> 9) | ((fieldB & 0xF000000000000000ULL) >> 36) | ((fieldB & 0xF0000000000000ULL) >> 32) | ((fieldB & 0xF00000000000ULL) >> 28);
+
+ if ((fieldB & 0xE0ULL) == 0xE0ULL)
+ // Opaque pixel, so set MSB to 1 and encode colors in RGB555
+ tmp = tmp | 0x8000ULL | ((fieldB & 0xF8000000ULL) >> 17) | ((fieldB & 0xF80000ULL) >> 14) | ((fieldB & 0xF800ULL) >> 11);
+ else
+ // Tranlucid pixel, so set MSB to 0 and encode colors in ARGB3444
+ tmp = tmp | ((fieldB & 0xE0ULL) << 7) | ((fieldB & 0xF0000000ULL) >> 20) | ((fieldB & 0xF00000ULL) >> 16) | ((fieldB & 0xF000ULL) >> 12);
+ ((PNGU_u64 *) buffer)[blockbase+3] = tmp;
+ }
+ }
+ else
+ {
+ // No alpha channel present, copy image to the output buffer
+ default_alpha = (default_alpha >> 5);
+ if (default_alpha == 7)
+ {
+ // The user wants an opaque texture, so set MSB to 1 and encode colors in RGB555
+ alphaMask = 0x8000800080008000ULL;
+
+ for (y = 0; y < qheight; y++)
+ for (x = 0; x < qwidth; x++)
+ {
+ int blockbase = (y * qwidth + x) * 4;
+
+ PNGU_u64 field64 = *((PNGU_u64 *)(ctx->row_pointers[y*4]+x*12));
+ PNGU_u64 field32 = (PNGU_u64) *((PNGU_u32 *)(ctx->row_pointers[y*4]+x*12+8));
+ ((PNGU_u64 *) buffer)[blockbase] =
+ alphaMask | ((field64 & 0xF800000000000000ULL) >> 1) | ((field64 & 0xF8000000000000ULL) << 2) |
+ ((field64 & 0xF80000000000ULL) << 5) | ((field64 & 0xF800000000ULL) << 7) | ((field64 & 0xF8000000ULL) << 10) |
+ ((field64 & 0xF80000ULL) << 13) | ((field64 & 0xF800ULL) << 15) | ((field64 & 0xF8ULL) << 18) |
+ ((field32 & 0xF8000000ULL) >> 11) | ((field32 & 0xF80000ULL) >> 9) | ((field32 & 0xF800ULL) >> 6) | ((field32 & 0xF8ULL) >> 3);
+
+ field64 = *((PNGU_u64 *)(ctx->row_pointers[y*4+1]+x*12));
+ field32 = (PNGU_u64) *((PNGU_u32 *)(ctx->row_pointers[y*4+1]+x*12+8));
+ ((PNGU_u64 *) buffer)[blockbase+1] =
+ alphaMask | ((field64 & 0xF800000000000000ULL) >> 1) | ((field64 & 0xF8000000000000ULL) << 2) |
+ ((field64 & 0xF80000000000ULL) << 5) | ((field64 & 0xF800000000ULL) << 7) | ((field64 & 0xF8000000ULL) << 10) |
+ ((field64 & 0xF80000ULL) << 13) | ((field64 & 0xF800ULL) << 15) | ((field64 & 0xF8ULL) << 18) |
+ ((field32 & 0xF8000000ULL) >> 11) | ((field32 & 0xF80000ULL) >> 9) | ((field32 & 0xF800ULL) >> 6) | ((field32 & 0xF8ULL) >> 3);
+
+ field64 = *((PNGU_u64 *)(ctx->row_pointers[y*4+2]+x*12));
+ field32 = (PNGU_u64) *((PNGU_u32 *)(ctx->row_pointers[y*4+2]+x*12+8));
+ ((PNGU_u64 *) buffer)[blockbase+2] =
+ alphaMask | ((field64 & 0xF800000000000000ULL) >> 1) | ((field64 & 0xF8000000000000ULL) << 2) |
+ ((field64 & 0xF80000000000ULL) << 5) | ((field64 & 0xF800000000ULL) << 7) | ((field64 & 0xF8000000ULL) << 10) |
+ ((field64 & 0xF80000ULL) << 13) | ((field64 & 0xF800ULL) << 15) | ((field64 & 0xF8ULL) << 18) |
+ ((field32 & 0xF8000000ULL) >> 11) | ((field32 & 0xF80000ULL) >> 9) | ((field32 & 0xF800ULL) >> 6) | ((field32 & 0xF8ULL) >> 3);
+
+ field64 = *((PNGU_u64 *)(ctx->row_pointers[y*4+3]+x*12));
+ field32 = (PNGU_u64) *((PNGU_u32 *)(ctx->row_pointers[y*4+3]+x*12+8));
+ ((PNGU_u64 *) buffer)[blockbase+3] =
+ alphaMask | ((field64 & 0xF800000000000000ULL) >> 1) | ((field64 & 0xF8000000000000ULL) << 2) |
+ ((field64 & 0xF80000000000ULL) << 5) | ((field64 & 0xF800000000ULL) << 7) | ((field64 & 0xF8000000ULL) << 10) |
+ ((field64 & 0xF80000ULL) << 13) | ((field64 & 0xF800ULL) << 15) | ((field64 & 0xF8ULL) << 18) |
+ ((field32 & 0xF8000000ULL) >> 11) | ((field32 & 0xF80000ULL) >> 9) | ((field32 & 0xF800ULL) >> 6) | ((field32 & 0xF8ULL) >> 3);
+ }
+ }
+ else
+ {
+ // The user wants a translucid texture, so set MSB to 0 and encode colors in ARGB3444
+ default_alpha = (default_alpha << 4);
+ alphaMask = (((PNGU_u64) default_alpha) << 56) | (((PNGU_u64) default_alpha) << 40) |
+ (((PNGU_u64) default_alpha) << 24) | (((PNGU_u64) default_alpha) << 8);
+
+ for (y = 0; y < qheight; y++)
+ for (x = 0; x < qwidth; x++)
+ {
+ int blockbase = (y * qwidth + x) * 4;
+
+ PNGU_u64 field64 = *((PNGU_u64 *)(ctx->row_pointers[y*4]+x*12));
+ PNGU_u64 field32 = (PNGU_u64) *((PNGU_u32 *)(ctx->row_pointers[y*4]+x*12+8));
+ ((PNGU_u64 *) buffer)[blockbase] =
+ alphaMask | ((field64 & 0xF000000000000000ULL) >> 4) | (field64 & 0xF0000000000000ULL) | ((field64 & 0xF00000000000ULL) << 4) |
+ ((field64 & 0xF000000000ULL) << 4) | ((field64 & 0xF0000000ULL) << 8) | ((field64 & 0xF00000ULL) << 12) |
+ ((field64 & 0xF000ULL) << 12) | ((field64 & 0xF0ULL) << 16) | ((field32 & 0xF0000000ULL) >> 12) |
+ ((field32 & 0xF00000ULL) >> 12) | ((field32 & 0xF000ULL) >> 8) | ((field32 & 0xF0ULL) >> 4);
+
+ field64 = *((PNGU_u64 *)(ctx->row_pointers[y*4+1]+x*12));
+ field32 = (PNGU_u64) *((PNGU_u32 *)(ctx->row_pointers[y*4+1]+x*12+8));
+ ((PNGU_u64 *) buffer)[blockbase+1] =
+ alphaMask | ((field64 & 0xF000000000000000ULL) >> 4) | (field64 & 0xF0000000000000ULL) | ((field64 & 0xF00000000000ULL) << 4) |
+ ((field64 & 0xF000000000ULL) << 4) | ((field64 & 0xF0000000ULL) << 8) | ((field64 & 0xF00000ULL) << 12) |
+ ((field64 & 0xF000ULL) << 12) | ((field64 & 0xF0ULL) << 16) | ((field32 & 0xF0000000ULL) >> 12) |
+ ((field32 & 0xF00000ULL) >> 12) | ((field32 & 0xF000ULL) >> 8) | ((field32 & 0xF0ULL) >> 4);
+
+ field64 = *((PNGU_u64 *)(ctx->row_pointers[y*4+2]+x*12));
+ field32 = (PNGU_u64) *((PNGU_u32 *)(ctx->row_pointers[y*4+2]+x*12+8));
+ ((PNGU_u64 *) buffer)[blockbase+2] =
+ alphaMask | ((field64 & 0xF000000000000000ULL) >> 4) | (field64 & 0xF0000000000000ULL) | ((field64 & 0xF00000000000ULL) << 4) |
+ ((field64 & 0xF000000000ULL) << 4) | ((field64 & 0xF0000000ULL) << 8) | ((field64 & 0xF00000ULL) << 12) |
+ ((field64 & 0xF000ULL) << 12) | ((field64 & 0xF0ULL) << 16) | ((field32 & 0xF0000000ULL) >> 12) |
+ ((field32 & 0xF00000ULL) >> 12) | ((field32 & 0xF000ULL) >> 8) | ((field32 & 0xF0ULL) >> 4);
+
+ field64 = *((PNGU_u64 *)(ctx->row_pointers[y*4+3]+x*12));
+ field32 = (PNGU_u64) *((PNGU_u32 *)(ctx->row_pointers[y*4+3]+x*12+8));
+ ((PNGU_u64 *) buffer)[blockbase+3] =
+ alphaMask | ((field64 & 0xF000000000000000ULL) >> 4) | (field64 & 0xF0000000000000ULL) | ((field64 & 0xF00000000000ULL) << 4) |
+ ((field64 & 0xF000000000ULL) << 4) | ((field64 & 0xF0000000ULL) << 8) | ((field64 & 0xF00000ULL) << 12) |
+ ((field64 & 0xF000ULL) << 12) | ((field64 & 0xF0ULL) << 16) | ((field32 & 0xF0000000ULL) >> 12) |
+ ((field32 & 0xF00000ULL) >> 12) | ((field32 & 0xF000ULL) >> 8) | ((field32 & 0xF0ULL) >> 4);
+ }
+ }
+ }
+
+ // Free resources
+ free (ctx->img_data);
+ free (ctx->row_pointers);
+
+ // Success
+ return PNGU_OK;
+}
+
+
+int PNGU_DecodeTo4x4RGBA8 (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer, PNGU_u8 default_alpha)
+{
+ int result;
+ PNGU_u32 x, y, qwidth, qheight;
+ PNGU_u64 alphaMask;
+
+ // width and height need to be divisible by four
+ if ((width % 4) || (height % 4))
+ return PNGU_INVALID_WIDTH_OR_HEIGHT;
+
+ result = pngu_decode (ctx, width, height, 0);
+ if (result != PNGU_OK)
+ return result;
+
+ // Init some variables
+ qwidth = width / 4;
+ qheight = height / 4;
+
+ // Check is source image has an alpha channel
+ if ( (ctx->prop.imgColorType == PNGU_COLOR_TYPE_GRAY_ALPHA) || (ctx->prop.imgColorType == PNGU_COLOR_TYPE_RGB_ALPHA) )
+ {
+ // Alpha channel present, copy image to the output buffer
+ for (y = 0; y < qheight; y++)
+ for (x = 0; x < qwidth; x++)
+ {
+ int blockbase = (y * qwidth + x) * 8;
+
+ PNGU_u64 fieldA = *((PNGU_u64 *)(ctx->row_pointers[y*4]+x*16));
+ PNGU_u64 fieldB = *((PNGU_u64 *)(ctx->row_pointers[y*4]+x*16+8));
+ ((PNGU_u64 *) buffer)[blockbase] =
+ ((fieldA & 0xFF00000000ULL) << 24) | ((fieldA & 0xFF00000000000000ULL) >> 8) |
+ ((fieldA & 0xFFULL) << 40) | ((fieldA & 0xFF000000ULL) << 8) |
+ ((fieldB & 0xFF00000000ULL) >> 8) | ((fieldB & 0xFF00000000000000ULL) >> 40) |
+ ((fieldB & 0xFFULL) << 8) | ((fieldB & 0xFF000000ULL) >> 24);
+ ((PNGU_u64 *) buffer)[blockbase+4] =
+ ((fieldA & 0xFFFF0000000000ULL) << 8) | ((fieldA & 0xFFFF00ULL) << 24) |
+ ((fieldB & 0xFFFF0000000000ULL) >> 24) | ((fieldB & 0xFFFF00ULL) >> 8);
+
+ fieldA = *((PNGU_u64 *)(ctx->row_pointers[y*4+1]+x*16));
+ fieldB = *((PNGU_u64 *)(ctx->row_pointers[y*4+1]+x*16+8));
+ ((PNGU_u64 *) buffer)[blockbase+1] =
+ ((fieldA & 0xFF00000000ULL) << 24) | ((fieldA & 0xFF00000000000000ULL) >> 8) |
+ ((fieldA & 0xFFULL) << 40) | ((fieldA & 0xFF000000ULL) << 8) |
+ ((fieldB & 0xFF00000000ULL) >> 8) | ((fieldB & 0xFF00000000000000ULL) >> 40) |
+ ((fieldB & 0xFFULL) << 8) | ((fieldB & 0xFF000000ULL) >> 24);
+ ((PNGU_u64 *) buffer)[blockbase+5] =
+ ((fieldA & 0xFFFF0000000000ULL) << 8) | ((fieldA & 0xFFFF00ULL) << 24) |
+ ((fieldB & 0xFFFF0000000000ULL) >> 24) | ((fieldB & 0xFFFF00ULL) >> 8);
+
+ fieldA = *((PNGU_u64 *)(ctx->row_pointers[y*4+2]+x*16));
+ fieldB = *((PNGU_u64 *)(ctx->row_pointers[y*4+2]+x*16+8));
+ ((PNGU_u64 *) buffer)[blockbase+2] =
+ ((fieldA & 0xFF00000000ULL) << 24) | ((fieldA & 0xFF00000000000000ULL) >> 8) |
+ ((fieldA & 0xFFULL) << 40) | ((fieldA & 0xFF000000ULL) << 8) |
+ ((fieldB & 0xFF00000000ULL) >> 8) | ((fieldB & 0xFF00000000000000ULL) >> 40) |
+ ((fieldB & 0xFFULL) << 8) | ((fieldB & 0xFF000000ULL) >> 24);
+ ((PNGU_u64 *) buffer)[blockbase+6] =
+ ((fieldA & 0xFFFF0000000000ULL) << 8) | ((fieldA & 0xFFFF00ULL) << 24) |
+ ((fieldB & 0xFFFF0000000000ULL) >> 24) | ((fieldB & 0xFFFF00ULL) >> 8);
+
+ fieldA = *((PNGU_u64 *)(ctx->row_pointers[y*4+3]+x*16));
+ fieldB = *((PNGU_u64 *)(ctx->row_pointers[y*4+3]+x*16+8));
+ ((PNGU_u64 *) buffer)[blockbase+3] =
+ ((fieldA & 0xFF00000000ULL) << 24) | ((fieldA & 0xFF00000000000000ULL) >> 8) |
+ ((fieldA & 0xFFULL) << 40) | ((fieldA & 0xFF000000ULL) << 8) |
+ ((fieldB & 0xFF00000000ULL) >> 8) | ((fieldB & 0xFF00000000000000ULL) >> 40) |
+ ((fieldB & 0xFFULL) << 8) | ((fieldB & 0xFF000000ULL) >> 24);
+ ((PNGU_u64 *) buffer)[blockbase+7] =
+ ((fieldA & 0xFFFF0000000000ULL) << 8) | ((fieldA & 0xFFFF00ULL) << 24) |
+ ((fieldB & 0xFFFF0000000000ULL) >> 24) | ((fieldB & 0xFFFF00ULL) >> 8);
+ }
+ }
+ else
+ {
+ // No alpha channel present, copy image to the output buffer
+ alphaMask = (((PNGU_u64)default_alpha) << 56) | (((PNGU_u64)default_alpha) << 40) |
+ (((PNGU_u64)default_alpha) << 24) | (((PNGU_u64)default_alpha) << 8);
+
+ for (y = 0; y < qheight; y++)
+ for (x = 0; x < qwidth; x++)
+ {
+ int blockbase = (y * qwidth + x) * 8;
+
+ PNGU_u64 field64 = *((PNGU_u64 *)(ctx->row_pointers[y*4]+x*12));
+ PNGU_u64 field32 = (PNGU_u64) *((PNGU_u32 *)(ctx->row_pointers[y*4]+x*12+8));
+ ((PNGU_u64 *) buffer)[blockbase] =
+ (((field64 & 0xFF00000000000000ULL) >> 8) | (field64 & 0xFF00000000ULL) |
+ ((field64 & 0xFF00ULL) << 8) | ((field32 & 0xFF0000ULL) >> 16) | alphaMask);
+ ((PNGU_u64 *) buffer)[blockbase+4] =
+ (((field64 & 0xFFFF0000000000ULL) << 8) | ((field64 & 0xFFFF0000ULL) << 16) |
+ ((field64 & 0xFFULL) << 24) | ((field32 & 0xFF000000ULL) >> 8) | (field32 & 0xFFFFULL));
+
+ field64 = *((PNGU_u64 *)(ctx->row_pointers[y*4+1]+x*12));
+ field32 = (PNGU_u64) *((PNGU_u32 *)(ctx->row_pointers[y*4+1]+x*12+8));
+ ((PNGU_u64 *) buffer)[blockbase+1] =
+ (((field64 & 0xFF00000000000000ULL) >> 8) | (field64 & 0xFF00000000ULL) |
+ ((field64 & 0xFF00ULL) << 8) | ((field32 & 0xFF0000ULL) >> 16) | alphaMask);
+ ((PNGU_u64 *) buffer)[blockbase+5] =
+ (((field64 & 0xFFFF0000000000ULL) << 8) | ((field64 & 0xFFFF0000ULL) << 16) |
+ ((field64 & 0xFFULL) << 24) | ((field32 & 0xFF000000ULL) >> 8) | (field32 & 0xFFFFULL));
+
+ field64 = *((PNGU_u64 *)(ctx->row_pointers[y*4+2]+x*12));
+ field32 = (PNGU_u64) *((PNGU_u32 *)(ctx->row_pointers[y*4+2]+x*12+8));
+ ((PNGU_u64 *) buffer)[blockbase+2] =
+ (((field64 & 0xFF00000000000000ULL) >> 8) | (field64 & 0xFF00000000ULL) |
+ ((field64 & 0xFF00ULL) << 8) | ((field32 & 0xFF0000ULL) >> 16) | alphaMask);
+ ((PNGU_u64 *) buffer)[blockbase+6] =
+ (((field64 & 0xFFFF0000000000ULL) << 8) | ((field64 & 0xFFFF0000ULL) << 16) |
+ ((field64 & 0xFFULL) << 24) | ((field32 & 0xFF000000ULL) >> 8) | (field32 & 0xFFFFULL));
+
+ field64 = *((PNGU_u64 *)(ctx->row_pointers[y*4+3]+x*12));
+ field32 = (PNGU_u64) *((PNGU_u32 *)(ctx->row_pointers[y*4+3]+x*12+8));
+ ((PNGU_u64 *) buffer)[blockbase+3] =
+ (((field64 & 0xFF00000000000000ULL) >> 8) | (field64 & 0xFF00000000ULL) |
+ ((field64 & 0xFF00ULL) << 8) | ((field32 & 0xFF0000ULL) >> 16) | alphaMask);
+ ((PNGU_u64 *) buffer)[blockbase+7] =
+ (((field64 & 0xFFFF0000000000ULL) << 8) | ((field64 & 0xFFFF0000ULL) << 16) |
+ ((field64 & 0xFFULL) << 24) | ((field32 & 0xFF000000ULL) >> 8) | (field32 & 0xFFFFULL));
+ }
+ }
+
+ // Free resources
+ free (ctx->img_data);
+ free (ctx->row_pointers);
+
+ // Success
+ return PNGU_OK;
+}
+
+
+int PNGU_EncodeFromYCbYCr (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer, PNGU_u32 stride)
+{
+ png_uint_32 rowbytes;
+ PNGU_u32 x, y, buffWidth;
+
+ // Erase from the context any readed info
+ pngu_free_info (ctx);
+ ctx->propRead = 0;
+
+ // Check if the user has selected a file to write the image
+ if (ctx->source == PNGU_SOURCE_BUFFER);
+
+ else if (ctx->source == PNGU_SOURCE_DEVICE)
+ {
+ // Open file
+ if (!(ctx->fd = fopen (ctx->filename, "wb")))
+ return PNGU_CANT_OPEN_FILE;
+ }
+
+ else
+ return PNGU_NO_FILE_SELECTED;
+
+ // Allocation of libpng structs
+ ctx->png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
+ if (!(ctx->png_ptr))
+ {
+ if (ctx->source == PNGU_SOURCE_DEVICE)
+ fclose (ctx->fd);
+ return PNGU_LIB_ERROR;
+ }
+
+ ctx->info_ptr = png_create_info_struct (ctx->png_ptr);
+ if (!(ctx->info_ptr))
+ {
+ png_destroy_write_struct (&(ctx->png_ptr), (png_infopp)NULL);
+ if (ctx->source == PNGU_SOURCE_DEVICE)
+ fclose (ctx->fd);
+ return PNGU_LIB_ERROR;
+ }
+
+ if (ctx->source == PNGU_SOURCE_BUFFER)
+ {
+ // Installation of our custom data writer function
+ ctx->cursor = 0;
+ png_set_write_fn (ctx->png_ptr, ctx, pngu_write_data_to_buffer, pngu_flush_data_to_buffer);
+ }
+ else if (ctx->source == PNGU_SOURCE_DEVICE)
+ {
+ // Default data writer uses function fwrite, so it needs to use our FILE*
+ png_init_io (ctx->png_ptr, ctx->fd);
+ }
+
+ // Setup output file properties
+ png_set_IHDR (ctx->png_ptr, ctx->info_ptr, width, height, 8, PNG_COLOR_TYPE_RGB,
+ PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
+
+ // Allocate memory to store the image in RGB format
+ rowbytes = width * 3;
+ if (rowbytes % 4)
+ rowbytes = ((rowbytes / 4) + 1) * 4; // Add extra padding so each row starts in a 4 byte boundary
+
+ ctx->img_data = malloc (rowbytes * height);
+ if (!ctx->img_data)
+ {
+ png_destroy_write_struct (&(ctx->png_ptr), (png_infopp)NULL);
+ if (ctx->source == PNGU_SOURCE_DEVICE)
+ fclose (ctx->fd);
+ return PNGU_LIB_ERROR;
+ }
+
+ ctx->row_pointers = malloc (sizeof (png_bytep) * height);
+ if (!ctx->row_pointers)
+ {
+ png_destroy_write_struct (&(ctx->png_ptr), (png_infopp)NULL);
+ if (ctx->source == PNGU_SOURCE_DEVICE)
+ fclose (ctx->fd);
+ return PNGU_LIB_ERROR;
+ }
+
+ // Encode YCbYCr image into RGB8 format
+ buffWidth = (width + stride) / 2;
+ for (y = 0; y < height; y++)
+ {
+ ctx->row_pointers[y] = ctx->img_data + (y * rowbytes);
+
+ for (x = 0; x < (width / 2); x++)
+ PNGU_YCbYCr_TO_RGB8 ( ((PNGU_u32 *)buffer)[y*buffWidth+x],
+ ((PNGU_u8 *) ctx->row_pointers[y]+x*6), ((PNGU_u8 *) ctx->row_pointers[y]+x*6+1),
+ ((PNGU_u8 *) ctx->row_pointers[y]+x*6+2), ((PNGU_u8 *) ctx->row_pointers[y]+x*6+3),
+ ((PNGU_u8 *) ctx->row_pointers[y]+x*6+4), ((PNGU_u8 *) ctx->row_pointers[y]+x*6+5) );
+ }
+
+ // Tell libpng where is our image data
+ png_set_rows (ctx->png_ptr, ctx->info_ptr, ctx->row_pointers);
+
+ // Write file header and image data
+ png_write_png (ctx->png_ptr, ctx->info_ptr, PNG_TRANSFORM_IDENTITY, NULL);
+
+ // Tell libpng we have no more data to write
+ png_write_end (ctx->png_ptr, (png_infop) NULL);
+
+ // Free resources
+ free (ctx->img_data);
+ free (ctx->row_pointers);
+ png_destroy_write_struct (&(ctx->png_ptr), &(ctx->info_ptr));
+ if (ctx->source == PNGU_SOURCE_DEVICE)
+ fclose (ctx->fd);
+
+ // Success
+ return PNGU_OK;
+}
+
+
+// This function is taken from a libogc example
+PNGU_u32 PNGU_RGB8_TO_YCbYCr (PNGU_u8 r1, PNGU_u8 g1, PNGU_u8 b1, PNGU_u8 r2, PNGU_u8 g2, PNGU_u8 b2)
+{
+ int y1, cb1, cr1, y2, cb2, cr2, cb, cr;
+
+ y1 = (299 * r1 + 587 * g1 + 114 * b1) / 1000;
+ cb1 = (-16874 * r1 - 33126 * g1 + 50000 * b1 + 12800000) / 100000;
+ cr1 = (50000 * r1 - 41869 * g1 - 8131 * b1 + 12800000) / 100000;
+
+ y2 = (299 * r2 + 587 * g2 + 114 * b2) / 1000;
+ cb2 = (-16874 * r2 - 33126 * g2 + 50000 * b2 + 12800000) / 100000;
+ cr2 = (50000 * r2 - 41869 * g2 - 8131 * b2 + 12800000) / 100000;
+
+ cb = (cb1 + cb2) >> 1;
+ cr = (cr1 + cr2) >> 1;
+
+ return (PNGU_u32) ((y1 << 24) | (cb << 16) | (y2 << 8) | cr);
+}
+
+
+void PNGU_YCbYCr_TO_RGB8 (PNGU_u32 ycbycr, PNGU_u8 *r1, PNGU_u8 *g1, PNGU_u8 *b1, PNGU_u8 *r2, PNGU_u8 *g2, PNGU_u8 *b2)
+{
+ PNGU_u8 *val = (PNGU_u8 *) &ycbycr;
+ int r, g, b;
+
+ r = 1.371f * (val[3] - 128);
+ g = - 0.698f * (val[3] - 128) - 0.336f * (val[1] - 128);
+ b = 1.732f * (val[1] - 128);
+
+ *r1 = pngu_clamp (val[0] + r, 0, 255);
+ *g1 = pngu_clamp (val[0] + g, 0, 255);
+ *b1 = pngu_clamp (val[0] + b, 0, 255);
+
+ *r2 = pngu_clamp (val[2] + r, 0, 255);
+ *g2 = pngu_clamp (val[2] + g, 0, 255);
+ *b2 = pngu_clamp (val[2] + b, 0, 255);
+}
+
+
+int pngu_info (IMGCTX ctx)
+{
+ png_byte magic[8];
+ png_uint_32 width;
+ png_uint_32 height;
+ png_color_16p background;
+ png_bytep trans;
+ png_color_16p trans_values;
+ int scale, i;
+
+ // Check if there is a file selected and if it is a valid .png
+ if (ctx->source == PNGU_SOURCE_BUFFER)
+ memcpy (magic, ctx->buffer, 8);
+
+ else if (ctx->source == PNGU_SOURCE_DEVICE)
+ {
+ // Open file
+ if (!(ctx->fd = fopen (ctx->filename, "rb")))
+ return PNGU_CANT_OPEN_FILE;
+
+ // Load first 8 bytes into magic buffer
+ if (fread (magic, 1, 8, ctx->fd) != 8)
+ {
+ fclose (ctx->fd);
+ return PNGU_CANT_READ_FILE;
+ }
+ }
+
+ else
+ return PNGU_NO_FILE_SELECTED;;
+
+ if (png_sig_cmp(magic, 0, 8) != 0)
+ {
+ if (ctx->source == PNGU_SOURCE_DEVICE)
+ fclose (ctx->fd);
+ return PNGU_FILE_IS_NOT_PNG;
+ }
+
+ // Allocation of libpng structs
+ ctx->png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
+ if (!(ctx->png_ptr))
+ {
+ if (ctx->source == PNGU_SOURCE_DEVICE)
+ fclose (ctx->fd);
+ return PNGU_LIB_ERROR;
+ }
+
+ ctx->info_ptr = png_create_info_struct (ctx->png_ptr);
+ if (!(ctx->info_ptr))
+ {
+ if (ctx->source == PNGU_SOURCE_DEVICE)
+ fclose (ctx->fd);
+ png_destroy_read_struct (&(ctx->png_ptr), (png_infopp)NULL, (png_infopp)NULL);
+ return PNGU_LIB_ERROR;
+ }
+
+ if (ctx->source == PNGU_SOURCE_BUFFER)
+ {
+ // Installation of our custom data provider function
+ ctx->cursor = 0;
+ png_set_read_fn (ctx->png_ptr, ctx, pngu_read_data_from_buffer);
+ }
+ else if (ctx->source == PNGU_SOURCE_DEVICE)
+ {
+ // Default data provider uses function fread, so it needs to use our FILE*
+ png_init_io (ctx->png_ptr, ctx->fd);
+ png_set_sig_bytes (ctx->png_ptr, 8); // We have read 8 bytes already to check PNG authenticity
+ }
+
+ // Read png header
+ png_read_info (ctx->png_ptr, ctx->info_ptr);
+
+ // Query image properties if they have not been queried before
+ if (!ctx->propRead)
+ {
+ png_get_IHDR(ctx->png_ptr, ctx->info_ptr, &width, &height,
+ (int *) &(ctx->prop.imgBitDepth),
+ (int *) &(ctx->prop.imgColorType),
+ NULL, NULL, NULL);
+
+ ctx->prop.imgWidth = width;
+ ctx->prop.imgHeight = height;
+ switch (ctx->prop.imgColorType)
+ {
+ case PNG_COLOR_TYPE_GRAY:
+ ctx->prop.imgColorType = PNGU_COLOR_TYPE_GRAY;
+ break;
+ case PNG_COLOR_TYPE_GRAY_ALPHA:
+ ctx->prop.imgColorType = PNGU_COLOR_TYPE_GRAY_ALPHA;
+ break;
+ case PNG_COLOR_TYPE_PALETTE:
+ ctx->prop.imgColorType = PNGU_COLOR_TYPE_PALETTE;
+ break;
+ case PNG_COLOR_TYPE_RGB:
+ ctx->prop.imgColorType = PNGU_COLOR_TYPE_RGB;
+ break;
+ case PNG_COLOR_TYPE_RGB_ALPHA:
+ ctx->prop.imgColorType = PNGU_COLOR_TYPE_RGB_ALPHA;
+ break;
+ default:
+ ctx->prop.imgColorType = PNGU_COLOR_TYPE_UNKNOWN;
+ break;
+ }
+
+ // Constant used to scale 16 bit values to 8 bit values
+ scale = 1;
+ if (ctx->prop.imgBitDepth == 16)
+ scale = 256;
+
+ // Query background color, if any.
+ ctx->prop.validBckgrnd = 0;
+ if (((ctx->prop.imgColorType == PNGU_COLOR_TYPE_RGB) || (ctx->prop.imgColorType == PNGU_COLOR_TYPE_RGB_ALPHA)) &&
+ (png_get_bKGD (ctx->png_ptr, ctx->info_ptr, &background)))
+ {
+ ctx->prop.validBckgrnd = 1;
+ ctx->prop.bckgrnd.r = background->red / scale;
+ ctx->prop.bckgrnd.g = background->green / scale;
+ ctx->prop.bckgrnd.b = background->blue / scale;
+ }
+ else if (((ctx->prop.imgColorType == PNGU_COLOR_TYPE_GRAY) || (ctx->prop.imgColorType == PNGU_COLOR_TYPE_GRAY_ALPHA)) &&
+ (png_get_bKGD (ctx->png_ptr, ctx->info_ptr, &background)))
+ {
+ ctx->prop.validBckgrnd = 1;
+ ctx->prop.bckgrnd.r = ctx->prop.bckgrnd.g = ctx->prop.bckgrnd.b = background->gray / scale;
+ }
+
+ // Query list of transparent colors, if any.
+ ctx->prop.numTrans = 0;
+ ctx->prop.trans = NULL;
+ if (((ctx->prop.imgColorType == PNGU_COLOR_TYPE_RGB) || (ctx->prop.imgColorType == PNGU_COLOR_TYPE_RGB_ALPHA)) &&
+ (png_get_tRNS (ctx->png_ptr, ctx->info_ptr, &trans, (int *) &(ctx->prop.numTrans), &trans_values)))
+ {
+ if (ctx->prop.numTrans)
+ {
+ ctx->prop.trans = malloc (sizeof (PNGUCOLOR) * ctx->prop.numTrans);
+ if (ctx->prop.trans)
+ for (i = 0; i < ctx->prop.numTrans; i++)
+ {
+ ctx->prop.trans[i].r = trans_values[i].red / scale;
+ ctx->prop.trans[i].g = trans_values[i].green / scale;
+ ctx->prop.trans[i].b = trans_values[i].blue / scale;
+ }
+ else
+ ctx->prop.numTrans = 0;
+ }
+ }
+ else if (((ctx->prop.imgColorType == PNGU_COLOR_TYPE_GRAY) || (ctx->prop.imgColorType == PNGU_COLOR_TYPE_GRAY_ALPHA)) &&
+ (png_get_tRNS (ctx->png_ptr, ctx->info_ptr, &trans, (int *) &(ctx->prop.numTrans), &trans_values)))
+ {
+ if (ctx->prop.numTrans)
+ {
+ ctx->prop.trans = malloc (sizeof (PNGUCOLOR) * ctx->prop.numTrans);
+ if (ctx->prop.trans)
+ for (i = 0; i < ctx->prop.numTrans; i++)
+ ctx->prop.trans[i].r = ctx->prop.trans[i].g = ctx->prop.trans[i].b =
+ trans_values[i].gray / scale;
+ else
+ ctx->prop.numTrans = 0;
+ }
+ }
+
+ ctx->propRead = 1;
+ }
+
+ // Success
+ ctx->infoRead = 1;
+
+ return PNGU_OK;
+}
+
+
+int pngu_decode (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, PNGU_u32 stripAlpha)
+{
+ png_uint_32 rowbytes;
+ int i;
+
+ // Read info if it hasn't been read before
+ if (!ctx->infoRead)
+ {
+ i = pngu_info (ctx);
+ if (i != PNGU_OK)
+ return i;
+ }
+
+ // Check if the user has specified the real width and height of the image
+ if ( (ctx->prop.imgWidth != width) || (ctx->prop.imgHeight != height) )
+ return PNGU_INVALID_WIDTH_OR_HEIGHT;
+
+ // Check if color type is supported by PNGU
+ if ( (ctx->prop.imgColorType == PNGU_COLOR_TYPE_PALETTE) || (ctx->prop.imgColorType == PNGU_COLOR_TYPE_UNKNOWN) )
+ return PNGU_UNSUPPORTED_COLOR_TYPE;
+
+ // Scale 16 bit samples to 8 bit
+ if (ctx->prop.imgBitDepth == 16)
+ png_set_strip_16 (ctx->png_ptr);
+
+ // Remove alpha channel if we don't need it
+ if (stripAlpha && ((ctx->prop.imgColorType == PNGU_COLOR_TYPE_RGB_ALPHA) || (ctx->prop.imgColorType == PNGU_COLOR_TYPE_GRAY_ALPHA)))
+ png_set_strip_alpha (ctx->png_ptr);
+
+ // Expand 1, 2 and 4 bit samples to 8 bit
+ if (ctx->prop.imgBitDepth < 8)
+ png_set_packing (ctx->png_ptr);
+
+ // Transform grayscale images to RGB
+ if ( (ctx->prop.imgColorType == PNGU_COLOR_TYPE_GRAY) || (ctx->prop.imgColorType == PNGU_COLOR_TYPE_GRAY_ALPHA) )
+ png_set_gray_to_rgb (ctx->png_ptr);
+
+ // Flush transformations
+ png_read_update_info (ctx->png_ptr, ctx->info_ptr);
+
+ // Allocate memory to store the image
+ rowbytes = png_get_rowbytes (ctx->png_ptr, ctx->info_ptr);
+ if (rowbytes % 4)
+ rowbytes = ((rowbytes / 4) + 1) * 4; // Add extra padding so each row starts in a 4 byte boundary
+
+ ctx->img_data = malloc (rowbytes * ctx->prop.imgHeight);
+ if (!ctx->img_data)
+ {
+ pngu_free_info (ctx);
+ return PNGU_LIB_ERROR;
+ }
+
+ ctx->row_pointers = malloc (sizeof (png_bytep) * ctx->prop.imgHeight);
+ if (!ctx->row_pointers)
+ {
+ free (ctx->img_data);
+ pngu_free_info (ctx);
+ return PNGU_LIB_ERROR;
+ }
+
+ for (i = 0; i < ctx->prop.imgHeight; i++)
+ ctx->row_pointers[i] = ctx->img_data + (i * rowbytes);
+
+ // Transform the image and copy it to our allocated memory
+ png_read_image (ctx->png_ptr, ctx->row_pointers);
+
+ // Free resources
+ pngu_free_info (ctx);
+
+ // Success
+ return PNGU_OK;
+}
+
+
+void pngu_free_info (IMGCTX ctx)
+{
+ if (ctx->infoRead)
+ {
+ if (ctx->source == PNGU_SOURCE_DEVICE)
+ fclose (ctx->fd);
+
+ png_destroy_read_struct (&(ctx->png_ptr), &(ctx->info_ptr), (png_infopp)NULL);
+
+ ctx->infoRead = 0;
+ }
+}
+
+
+// Custom data provider function used for reading from memory buffers.
+void pngu_read_data_from_buffer (png_structp png_ptr, png_bytep data, png_size_t length)
+{
+ IMGCTX ctx = (IMGCTX) png_get_io_ptr (png_ptr);
+ memcpy (data, ctx->buffer + ctx->cursor, length);
+ ctx->cursor += length;
+}
+
+
+// Custom data writer function used for writing to memory buffers.
+void pngu_write_data_to_buffer (png_structp png_ptr, png_bytep data, png_size_t length)
+{
+ IMGCTX ctx = (IMGCTX) png_get_io_ptr (png_ptr);
+ memcpy (ctx->buffer + ctx->cursor, data, length);
+ ctx->cursor += length;
+}
+
+
+// Custom data flusher function used for writing to memory buffers.
+void pngu_flush_data_to_buffer (png_structp png_ptr)
+{
+ // Nothing to do here
+}
+
+
+// Function used in YCbYCr to RGB decoding
+int pngu_clamp (int value, int min, int max)
+{
+ if (value < min)
+ value = min;
+ else if (value > max)
+ value = max;
+
+ return value;
+}
+
diff --git a/source/libpng/pngu/pngu.h b/source/libpng/pngu/pngu.h
index b5e172b..12c3ad4 100644
--- a/source/libpng/pngu/pngu.h
+++ b/source/libpng/pngu/pngu.h
@@ -1,171 +1,171 @@
-/********************************************************************************************
-
-PNGU Version : 0.2a
-
-Coder : frontier
-
-More info : http://frontier-dev.net
-
-********************************************************************************************/
-#ifndef __PNGU__
-#define __PNGU__
-
-// Return codes
-#define PNGU_OK 0
-#define PNGU_ODD_WIDTH 1
-#define PNGU_ODD_STRIDE 2
-#define PNGU_INVALID_WIDTH_OR_HEIGHT 3
-#define PNGU_FILE_IS_NOT_PNG 4
-#define PNGU_UNSUPPORTED_COLOR_TYPE 5
-#define PNGU_NO_FILE_SELECTED 6
-#define PNGU_CANT_OPEN_FILE 7
-#define PNGU_CANT_READ_FILE 8
-#define PNGU_LIB_ERROR 9
-
-// Color types
-#define PNGU_COLOR_TYPE_GRAY 1
-#define PNGU_COLOR_TYPE_GRAY_ALPHA 2
-#define PNGU_COLOR_TYPE_PALETTE 3
-#define PNGU_COLOR_TYPE_RGB 4
-#define PNGU_COLOR_TYPE_RGB_ALPHA 5
-#define PNGU_COLOR_TYPE_UNKNOWN 6
-
-
-#ifdef __cplusplus
- extern "C" {
-#endif
-
-// Types
-typedef unsigned char PNGU_u8;
-typedef unsigned short PNGU_u16;
-typedef unsigned int PNGU_u32;
-typedef unsigned long long PNGU_u64;
-
-typedef struct
-{
- PNGU_u8 r;
- PNGU_u8 g;
- PNGU_u8 b;
-} PNGUCOLOR;
-
-typedef struct
-{
- PNGU_u32 imgWidth; // In pixels
- PNGU_u32 imgHeight; // In pixels
- PNGU_u32 imgBitDepth; // In bitx
- PNGU_u32 imgColorType; // PNGU_COLOR_TYPE_*
- PNGU_u32 validBckgrnd; // Non zero if there is a background color
- PNGUCOLOR bckgrnd; // Backgroun color
- PNGU_u32 numTrans; // Number of transparent colors
- PNGUCOLOR *trans; // Transparent colors
-} PNGUPROP;
-
-// Image context, always initialize with SelectImageFrom* and free with ReleaseImageContext
-struct _IMGCTX;
-typedef struct _IMGCTX *IMGCTX;
-
-
-/****************************************************************************
-* Pixel conversion *
-****************************************************************************/
-
-// Macro to convert RGB8 values to RGB565
-#define PNGU_RGB8_TO_RGB565(r,g,b) ( ((((PNGU_u16) r) & 0xF8U) << 8) | ((((PNGU_u16) g) & 0xFCU) << 3) | (((PNGU_u16) b) >> 3) )
-
-// Macro to convert RGBA8 values to RGB5A3
-#define PNGU_RGB8_TO_RGB5A3(r,g,b,a) (PNGU_u16) (((a & 0xE0U) == 0xE0U) ? \
- (0x8000U | ((((PNGU_u16) r) & 0xF8U) << 7) | ((((PNGU_u16) g) & 0xF8U) << 2) | (((PNGU_u16) b) >> 3)) : \
- (((((PNGU_u16) a) & 0xE0U) << 7) | ((((PNGU_u16) r) & 0xF0U) << 4) | (((PNGU_u16) g) & 0xF0U) | ((((PNGU_u16) b) & 0xF0U) >> 4)))
-
-// Function to convert two RGB8 values to YCbYCr
-PNGU_u32 PNGU_RGB8_TO_YCbYCr (PNGU_u8 r1, PNGU_u8 g1, PNGU_u8 b1, PNGU_u8 r2, PNGU_u8 g2, PNGU_u8 b2);
-
-// Function to convert an YCbYCr to two RGB8 values.
-void PNGU_YCbYCr_TO_RGB8 (PNGU_u32 ycbycr, PNGU_u8 *r1, PNGU_u8 *g1, PNGU_u8 *b1, PNGU_u8 *r2, PNGU_u8 *g2, PNGU_u8 *b2);
-
-
-/****************************************************************************
-* Image context handling *
-****************************************************************************/
-
-// Selects a PNG file, previosly loaded into a buffer, and creates an image context for subsequent procesing.
-IMGCTX PNGU_SelectImageFromBuffer (const void *buffer);
-
-// Selects a PNG file, from any devoptab device, and creates an image context for subsequent procesing.
-IMGCTX PNGU_SelectImageFromDevice (const char *filename);
-
-// Frees resources associated with an image context. Always call this function when you no longer need the IMGCTX.
-void PNGU_ReleaseImageContext (IMGCTX ctx);
-
-
-/****************************************************************************
-* Miscelaneous *
-****************************************************************************/
-
-// Retrieves info from selected PNG file, including image dimensions, color format, background and transparency colors.
-int PNGU_GetImageProperties (IMGCTX ctx, PNGUPROP *fileproperties);
-
-
-/****************************************************************************
-* Image conversion *
-****************************************************************************/
-
-// Expands selected image into an YCbYCr buffer. You need to specify context, image dimensions,
-// destination address and stride in pixels (stride = buffer width - image width).
-int PNGU_DecodeToYCbYCr (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer, PNGU_u32 stride);
-
-// Macro for decoding an image inside a buffer at given coordinates.
-#define PNGU_DECODE_TO_COORDS_YCbYCr(ctx,coordX,coordY,imgWidth,imgHeight,bufferWidth,bufferHeight,buffer) \
- \
- PNGU_DecodeToYCbYCr (ctx, imgWidth, imgHeight, ((void *) buffer) + (coordY) * (bufferWidth) * 2 + \
- (coordX) * 2, (bufferWidth) - (imgWidth))
-
-// Expands selected image into a linear RGB565 buffer. You need to specify context, image dimensions,
-// destination address and stride in pixels (stride = buffer width - image width).
-int PNGU_DecodeToRGB565 (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer, PNGU_u32 stride);
-
-// Macro for decoding an image inside a buffer at given coordinates.
-#define PNGU_DECODE_TO_COORDS_RGB565(ctx,coordX,coordY,imgWidth,imgHeight,bufferWidth,bufferHeight,buffer) \
- \
- PNGU_DecodeToRGB565 (ctx, imgWidth, imgHeight, ((void *) buffer) + (coordY) * (bufferWidth) * 2 + \
- (coordX) * 2, (bufferWidth) - (imgWidth))
-
-// Expands selected image into a linear RGBA8 buffer. You need to specify context, image dimensions,
-// destination address, stride in pixels and default alpha value, which is used if the source image
-// doesn't have an alpha channel.
-int PNGU_DecodeToRGBA8 (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer, PNGU_u32 stride, PNGU_u8 default_alpha);
-
-// Macro for decoding an image inside a buffer at given coordinates.
-#define PNGU_DECODE_TO_COORDS_RGBA8(ctx,coordX,coordY,imgWidth,imgHeight,default_alpha,bufferWidth,bufferHeight,buffer) \
- \
- PNGU_DecodeToRGBA8 (ctx, imgWidth, imgHeight, ((void *) buffer) + (coordY) * (bufferWidth) * 2 + \
- (coordX) * 2, (bufferWidth) - (imgWidth), default_alpha)
-
-// Expands selected image into a 4x4 tiled RGB565 buffer. You need to specify context, image dimensions
-// and destination address.
-int PNGU_DecodeTo4x4RGB565 (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer);
-
-// Expands selected image into a 4x4 tiled RGB5A3 buffer. You need to specify context, image dimensions,
-// destination address and default alpha value, which is used if the source image doesn't have an alpha channel.
-int PNGU_DecodeTo4x4RGB5A3 (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer, PNGU_u8 default_alpha);
-
-// Expands selected image into a 4x4 tiled RGBA8 buffer. You need to specify context, image dimensions,
-// destination address and default alpha value, which is used if the source image doesn't have an alpha channel.
-int PNGU_DecodeTo4x4RGBA8 (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer, PNGU_u8 default_alpha);
-
-// Encodes an YCbYCr image in PNG format and stores it in the selected device or memory buffer. You need to
-// specify context, image dimensions, destination address and stride in pixels (stride = buffer width - image width).
-int PNGU_EncodeFromYCbYCr (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer, PNGU_u32 stride);
-
-// Macro for encoding an image stored into an YCbYCr buffer at given coordinates.
-#define PNGU_ENCODE_TO_COORDS_YCbYCr(ctx,coordX,coordY,imgWidth,imgHeight,bufferWidth,bufferHeight,buffer) \
- \
- PNGU_EncodeFromYCbYCr (ctx, imgWidth, imgHeight, ((void *) buffer) + (coordY) * (bufferWidth) * 2 + \
- (coordX) * 2, (bufferWidth) - (imgWidth))
-
-#ifdef __cplusplus
- }
-#endif
-
-#endif
-
+/********************************************************************************************
+
+PNGU Version : 0.2a
+
+Coder : frontier
+
+More info : http://frontier-dev.net
+
+********************************************************************************************/
+#ifndef __PNGU__
+#define __PNGU__
+
+// Return codes
+#define PNGU_OK 0
+#define PNGU_ODD_WIDTH 1
+#define PNGU_ODD_STRIDE 2
+#define PNGU_INVALID_WIDTH_OR_HEIGHT 3
+#define PNGU_FILE_IS_NOT_PNG 4
+#define PNGU_UNSUPPORTED_COLOR_TYPE 5
+#define PNGU_NO_FILE_SELECTED 6
+#define PNGU_CANT_OPEN_FILE 7
+#define PNGU_CANT_READ_FILE 8
+#define PNGU_LIB_ERROR 9
+
+// Color types
+#define PNGU_COLOR_TYPE_GRAY 1
+#define PNGU_COLOR_TYPE_GRAY_ALPHA 2
+#define PNGU_COLOR_TYPE_PALETTE 3
+#define PNGU_COLOR_TYPE_RGB 4
+#define PNGU_COLOR_TYPE_RGB_ALPHA 5
+#define PNGU_COLOR_TYPE_UNKNOWN 6
+
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+// Types
+typedef unsigned char PNGU_u8;
+typedef unsigned short PNGU_u16;
+typedef unsigned int PNGU_u32;
+typedef unsigned long long PNGU_u64;
+
+typedef struct
+{
+ PNGU_u8 r;
+ PNGU_u8 g;
+ PNGU_u8 b;
+} PNGUCOLOR;
+
+typedef struct
+{
+ PNGU_u32 imgWidth; // In pixels
+ PNGU_u32 imgHeight; // In pixels
+ PNGU_u32 imgBitDepth; // In bitx
+ PNGU_u32 imgColorType; // PNGU_COLOR_TYPE_*
+ PNGU_u32 validBckgrnd; // Non zero if there is a background color
+ PNGUCOLOR bckgrnd; // Backgroun color
+ PNGU_u32 numTrans; // Number of transparent colors
+ PNGUCOLOR *trans; // Transparent colors
+} PNGUPROP;
+
+// Image context, always initialize with SelectImageFrom* and free with ReleaseImageContext
+struct _IMGCTX;
+typedef struct _IMGCTX *IMGCTX;
+
+
+/****************************************************************************
+* Pixel conversion *
+****************************************************************************/
+
+// Macro to convert RGB8 values to RGB565
+#define PNGU_RGB8_TO_RGB565(r,g,b) ( ((((PNGU_u16) r) & 0xF8U) << 8) | ((((PNGU_u16) g) & 0xFCU) << 3) | (((PNGU_u16) b) >> 3) )
+
+// Macro to convert RGBA8 values to RGB5A3
+#define PNGU_RGB8_TO_RGB5A3(r,g,b,a) (PNGU_u16) (((a & 0xE0U) == 0xE0U) ? \
+ (0x8000U | ((((PNGU_u16) r) & 0xF8U) << 7) | ((((PNGU_u16) g) & 0xF8U) << 2) | (((PNGU_u16) b) >> 3)) : \
+ (((((PNGU_u16) a) & 0xE0U) << 7) | ((((PNGU_u16) r) & 0xF0U) << 4) | (((PNGU_u16) g) & 0xF0U) | ((((PNGU_u16) b) & 0xF0U) >> 4)))
+
+// Function to convert two RGB8 values to YCbYCr
+PNGU_u32 PNGU_RGB8_TO_YCbYCr (PNGU_u8 r1, PNGU_u8 g1, PNGU_u8 b1, PNGU_u8 r2, PNGU_u8 g2, PNGU_u8 b2);
+
+// Function to convert an YCbYCr to two RGB8 values.
+void PNGU_YCbYCr_TO_RGB8 (PNGU_u32 ycbycr, PNGU_u8 *r1, PNGU_u8 *g1, PNGU_u8 *b1, PNGU_u8 *r2, PNGU_u8 *g2, PNGU_u8 *b2);
+
+
+/****************************************************************************
+* Image context handling *
+****************************************************************************/
+
+// Selects a PNG file, previosly loaded into a buffer, and creates an image context for subsequent procesing.
+IMGCTX PNGU_SelectImageFromBuffer (const void *buffer);
+
+// Selects a PNG file, from any devoptab device, and creates an image context for subsequent procesing.
+IMGCTX PNGU_SelectImageFromDevice (const char *filename);
+
+// Frees resources associated with an image context. Always call this function when you no longer need the IMGCTX.
+void PNGU_ReleaseImageContext (IMGCTX ctx);
+
+
+/****************************************************************************
+* Miscelaneous *
+****************************************************************************/
+
+// Retrieves info from selected PNG file, including image dimensions, color format, background and transparency colors.
+int PNGU_GetImageProperties (IMGCTX ctx, PNGUPROP *fileproperties);
+
+
+/****************************************************************************
+* Image conversion *
+****************************************************************************/
+
+// Expands selected image into an YCbYCr buffer. You need to specify context, image dimensions,
+// destination address and stride in pixels (stride = buffer width - image width).
+int PNGU_DecodeToYCbYCr (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer, PNGU_u32 stride);
+
+// Macro for decoding an image inside a buffer at given coordinates.
+#define PNGU_DECODE_TO_COORDS_YCbYCr(ctx,coordX,coordY,imgWidth,imgHeight,bufferWidth,bufferHeight,buffer) \
+ \
+ PNGU_DecodeToYCbYCr (ctx, imgWidth, imgHeight, ((void *) buffer) + (coordY) * (bufferWidth) * 2 + \
+ (coordX) * 2, (bufferWidth) - (imgWidth))
+
+// Expands selected image into a linear RGB565 buffer. You need to specify context, image dimensions,
+// destination address and stride in pixels (stride = buffer width - image width).
+int PNGU_DecodeToRGB565 (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer, PNGU_u32 stride);
+
+// Macro for decoding an image inside a buffer at given coordinates.
+#define PNGU_DECODE_TO_COORDS_RGB565(ctx,coordX,coordY,imgWidth,imgHeight,bufferWidth,bufferHeight,buffer) \
+ \
+ PNGU_DecodeToRGB565 (ctx, imgWidth, imgHeight, ((void *) buffer) + (coordY) * (bufferWidth) * 2 + \
+ (coordX) * 2, (bufferWidth) - (imgWidth))
+
+// Expands selected image into a linear RGBA8 buffer. You need to specify context, image dimensions,
+// destination address, stride in pixels and default alpha value, which is used if the source image
+// doesn't have an alpha channel.
+int PNGU_DecodeToRGBA8 (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer, PNGU_u32 stride, PNGU_u8 default_alpha);
+
+// Macro for decoding an image inside a buffer at given coordinates.
+#define PNGU_DECODE_TO_COORDS_RGBA8(ctx,coordX,coordY,imgWidth,imgHeight,default_alpha,bufferWidth,bufferHeight,buffer) \
+ \
+ PNGU_DecodeToRGBA8 (ctx, imgWidth, imgHeight, ((void *) buffer) + (coordY) * (bufferWidth) * 2 + \
+ (coordX) * 2, (bufferWidth) - (imgWidth), default_alpha)
+
+// Expands selected image into a 4x4 tiled RGB565 buffer. You need to specify context, image dimensions
+// and destination address.
+int PNGU_DecodeTo4x4RGB565 (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer);
+
+// Expands selected image into a 4x4 tiled RGB5A3 buffer. You need to specify context, image dimensions,
+// destination address and default alpha value, which is used if the source image doesn't have an alpha channel.
+int PNGU_DecodeTo4x4RGB5A3 (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer, PNGU_u8 default_alpha);
+
+// Expands selected image into a 4x4 tiled RGBA8 buffer. You need to specify context, image dimensions,
+// destination address and default alpha value, which is used if the source image doesn't have an alpha channel.
+int PNGU_DecodeTo4x4RGBA8 (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer, PNGU_u8 default_alpha);
+
+// Encodes an YCbYCr image in PNG format and stores it in the selected device or memory buffer. You need to
+// specify context, image dimensions, destination address and stride in pixels (stride = buffer width - image width).
+int PNGU_EncodeFromYCbYCr (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer, PNGU_u32 stride);
+
+// Macro for encoding an image stored into an YCbYCr buffer at given coordinates.
+#define PNGU_ENCODE_TO_COORDS_YCbYCr(ctx,coordX,coordY,imgWidth,imgHeight,bufferWidth,bufferHeight,buffer) \
+ \
+ PNGU_EncodeFromYCbYCr (ctx, imgWidth, imgHeight, ((void *) buffer) + (coordY) * (bufferWidth) * 2 + \
+ (coordX) * 2, (bufferWidth) - (imgWidth))
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif
+
diff --git a/source/menu.c b/source/menu.c
index ec4babc..edc856e 100644
--- a/source/menu.c
+++ b/source/menu.c
@@ -365,8 +365,8 @@ void Menu_FatDevice(void)
return;
-err:
-
+err:
+
if(gConfig.fatDeviceIndex >= 0) gConfig.fatDeviceIndex = -1;
WiiLightControl (WII_LIGHT_OFF);
printf("\n");
diff --git a/source/usbstorage.c b/source/usbstorage.c
index 56e7f60..d0d3432 100644
--- a/source/usbstorage.c
+++ b/source/usbstorage.c
@@ -1,400 +1,400 @@
-/*-------------------------------------------------------------
-
-usbstorage_starlet.c -- USB mass storage support, inside starlet
-Copyright (C) 2009 Kwiirk
-
-If this driver is linked before libogc, this will replace the original
-usbstorage driver by svpe from libogc
-This software is provided 'as-is', without any express or implied
-warranty. In no event will the authors be held liable for any
-damages arising from the use of this software.
-
-Permission is granted to anyone to use this software for any
-purpose, including commercial applications, and to alter it and
-redistribute it freely, subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you
-must not claim that you wrote the original software. If you use
-this software in a product, an acknowledgment in the product
-documentation would be appreciated but is not required.
-
-2. Altered source versions must be plainly marked as such, and
-must not be misrepresented as being the original software.
-
-3. This notice may not be removed or altered from any source
-distribution.
-
--------------------------------------------------------------*/
-
-#include
-#include
-#include
-#include
-
-/* IOCTL commands */
-#define UMS_BASE (('U'<<24)|('M'<<16)|('S'<<8))
-#define USB_IOCTL_UMS_INIT (UMS_BASE+0x1)
-#define USB_IOCTL_UMS_GET_CAPACITY (UMS_BASE+0x2)
-#define USB_IOCTL_UMS_READ_SECTORS (UMS_BASE+0x3)
-#define USB_IOCTL_UMS_WRITE_SECTORS (UMS_BASE+0x4)
-#define USB_IOCTL_UMS_READ_STRESS (UMS_BASE+0x5)
-#define USB_IOCTL_UMS_SET_VERBOSE (UMS_BASE+0x6)
-#define USB_IOCTL_UMS_UNMOUNT (UMS_BASE+0x10)
-#define USB_IOCTL_UMS_WATCHDOG (UMS_BASE+0x80)
-
-#define WBFS_BASE (('W'<<24)|('F'<<16)|('S'<<8))
-#define USB_IOCTL_WBFS_OPEN_DISC (WBFS_BASE+0x1)
-#define USB_IOCTL_WBFS_READ_DISC (WBFS_BASE+0x2)
-#define USB_IOCTL_WBFS_READ_DEBUG (WBFS_BASE+0x3)
-#define USB_IOCTL_WBFS_SET_DEVICE (WBFS_BASE+0x4)
-#define USB_IOCTL_WBFS_SET_FRAGLIST (WBFS_BASE+0x5)
-
-#define UMS_HEAPSIZE 0x1000
-
-/* Variables */
-static char fs[] ATTRIBUTE_ALIGN(32) = "/dev/usb2";
-static char fs2[] ATTRIBUTE_ALIGN(32) = "/dev/usb/ehc";
-static char fs3[] ATTRIBUTE_ALIGN(32) = "/dev/usb/usb123";
-
-static s32 hid = -1, fd = -1;
-static u32 sector_size;
-
-s32 USBStorage_GetCapacity(u32 *_sector_size) {
- if (fd > 0) {
- s32 ret;
-
- ret = IOS_IoctlvFormat(hid, fd, USB_IOCTL_UMS_GET_CAPACITY, ":i", §or_size);
-
- if (ret && _sector_size)
- *_sector_size = sector_size;
-
- return ret;
- }
-
- return IPC_ENOENT;
-}
-
-s32 USBStorage_Init(void) {
- s32 ret;
-
- /* Already open */
- if (fd > 0)
- return 0;
-
- /* Create heap */
- if (hid < 0) {
- hid = iosCreateHeap(UMS_HEAPSIZE);
- if (hid < 0)
- return IPC_ENOMEM;
- }
-
- /* Open USB device */
- fd = IOS_Open(fs, 0);
- if (fd < 0)
- fd = IOS_Open(fs2, 0);
- if (fd < 0)
- fd = IOS_Open(fs3, 0);
- if (fd < 0)
- return fd;
-
- /* Initialize USB storage */
- ret = IOS_IoctlvFormat(hid, fd, USB_IOCTL_UMS_INIT, ":");
- if (ret<0) goto err;
-
- /* Get device capacity */
- ret = USBStorage_GetCapacity(NULL);
- if (!ret)
- goto err;
-
- return 0;
-
-err:
- /* Close USB device */
- if (fd > 0) {
- IOS_Close(fd);
- fd = -1;
- }
-
- return -1;
-}
-
-/** Hermes **/
-s32 USBStorage_Watchdog(u32 on_off) {
- if (fd >= 0) {
- s32 ret;
-
- ret = IOS_IoctlvFormat(hid, fd, USB_IOCTL_UMS_WATCHDOG, "i:", on_off);
-
- return ret;
- }
-
- return IPC_ENOENT;
-}
-
-s32 USBStorage_Umount(void) {
- if (fd >= 0) {
- s32 ret;
- ret = IOS_IoctlvFormat(hid, fd, USB_IOCTL_UMS_UNMOUNT, ":");
- return ret;
- }
-
- return IPC_ENOENT;
-}
-
-void USBStorage_Deinit(void) {
- /* Close USB device */
- if (fd > 0) {
- IOS_Close(fd);
- fd = -1;
- }
-}
-
-s32 USBStorage_ReadSectors(u32 sector, u32 numSectors, void *buffer) {
-
-// void *buf = (void *)buffer;
- u32 len = (sector_size * numSectors);
-
- s32 ret;
-
- /* Device not opened */
- if (fd < 0)
- return fd;
-
-
- ret = IOS_IoctlvFormat(hid, fd, USB_IOCTL_UMS_READ_SECTORS, "ii:d", sector, numSectors, buffer, len);
- return ret;
-}
-
-s32 USBStorage_WriteSectors(u32 sector, u32 numSectors, const void *buffer) {
- u32 len = (sector_size * numSectors);
-
- s32 ret;
-
- /* Device not opened */
- if (fd < 0)
- return fd;
-
- /* Write data */
- ret = IOS_IoctlvFormat(hid, fd, USB_IOCTL_UMS_WRITE_SECTORS, "ii:d", sector, numSectors, buffer, len);
-
- return ret;
-}
-
-static bool __io_usb_Startup(void)
-{
- return USBStorage_Init() >= 0;
-}
-
-static bool __io_usb_IsInserted(void)
-{
- s32 ret;
- if (fd < 0) return false;
- ret = USBStorage_GetCapacity(NULL);
- if (ret == 0) return false;
- return true;
-}
-
-bool __io_usb_ReadSectors(u32 sector, u32 count, void *buffer)
-{
- s32 ret = USBStorage_ReadSectors(sector, count, buffer);
- return ret > 0;
-}
-
-bool __io_usb_WriteSectors(u32 sector, u32 count, void *buffer)
-{
- s32 ret = USBStorage_WriteSectors(sector, count, buffer);
- return ret > 0;
-}
-
-static bool __io_usb_ClearStatus(void)
-{
- return true;
-}
-
-static bool __io_usb_Shutdown(void)
-{
- // do nothing
- return true;
-}
-
-static bool __io_usb_NOP(void)
-{
- // do nothing
- return true;
-}
-
-const DISC_INTERFACE __io_usbstorage_ro = {
- DEVICE_TYPE_WII_USB,
- FEATURE_MEDIUM_CANREAD | FEATURE_WII_USB,
- (FN_MEDIUM_STARTUP) &__io_usb_Startup,
- (FN_MEDIUM_ISINSERTED) &__io_usb_IsInserted,
- (FN_MEDIUM_READSECTORS) &__io_usb_ReadSectors,
- (FN_MEDIUM_WRITESECTORS) &__io_usb_NOP, //&__io_usb_WriteSectors,
- (FN_MEDIUM_CLEARSTATUS) &__io_usb_ClearStatus,
- (FN_MEDIUM_SHUTDOWN) &__io_usb_Shutdown
-};
-
-s32 USBStorage_WBFS_Open(char *buffer)
-{
- u32 len = 8;
-
- s32 ret;
-
- /* Device not opened */
- if (fd < 0)
- return fd;
-
- extern u32 wbfs_part_lba;
- u32 part = wbfs_part_lba;
-
- /* Read data */
- ret = IOS_IoctlvFormat(hid, fd, USB_IOCTL_WBFS_OPEN_DISC, "dd:", buffer, len, &part, 4);
-
- return ret;
-}
-
-// woffset is in 32bit words, len is in bytes
-s32 USBStorage_WBFS_Read(u32 woffset, u32 len, void *buffer)
-{
- s32 ret;
-
- USBStorage_Init();
- /* Device not opened */
- if (fd < 0)
- return fd;
-
- /* Read data */
- ret = IOS_IoctlvFormat(hid, fd, USB_IOCTL_WBFS_READ_DISC, "ii:d", woffset, len, buffer, len);
-
- return ret;
-}
-
-
-s32 USBStorage_WBFS_ReadDebug(u32 off, u32 size, void *buffer)
-{
- s32 ret;
-
- USBStorage_Init();
- /* Device not opened */
- if (fd < 0)
- return fd;
-
- /* Read data */
- ret = IOS_IoctlvFormat(hid, fd, USB_IOCTL_WBFS_READ_DEBUG, "ii:d", off, size, buffer, size);
-
- return ret;
-}
-
-
-s32 USBStorage_WBFS_SetDevice(int dev)
-{
- s32 ret;
- static s32 retval = 0;
- retval = 0;
- USBStorage_Init();
- // Device not opened
- if (fd < 0) return fd;
- // ioctl
- ret = IOS_IoctlvFormat(hid, fd, USB_IOCTL_WBFS_SET_DEVICE, "i:i", dev, &retval);
- if (retval) return retval;
- return ret;
-}
-
-s32 USBStorage_WBFS_SetFragList(void *p, int size)
-{
- s32 ret;
- USBStorage_Init();
- // Device not opened
- if (fd < 0) return fd;
- // ioctl
- ret = IOS_IoctlvFormat(hid, fd, USB_IOCTL_WBFS_SET_FRAGLIST, "d:", p, size);
- return ret;
-}
-
-#define DEVICE_TYPE_WII_UMS (('W'<<24)|('U'<<16)|('M'<<8)|'S')
-
-bool umsio_Startup() {
- return USBStorage_Init() == 0;
-}
-
-bool umsio_IsInserted() {
- return true; // allways true
-}
-
-bool umsio_ReadSectors(sec_t sector, sec_t numSectors, u8 *buffer) {
- u32 cnt = 0;
- s32 ret;
- /* Do reads */
- while (cnt < numSectors) {
- u32 sectors = (numSectors - cnt);
-
- /* Read sectors is too big */
- if (sectors > 32)
- sectors = 32;
-
- /* USB read */
- ret = USBStorage_ReadSectors(sector + cnt, sectors, &buffer[cnt*512]);
- if (ret < 0)
- return false;
-
- /* Increment counter */
- cnt += sectors;
- }
-
- return true;
-}
-
-bool umsio_WriteSectors(sec_t sector, sec_t numSectors, const u8* buffer) {
- u32 cnt = 0;
- s32 ret;
-
- /* Do writes */
- while (cnt < numSectors) {
- u32 sectors = (numSectors - cnt);
-
- /* Write sectors is too big */
- if (sectors > 32)
- sectors = 32;
-
- /* USB write */
- ret = USBStorage_WriteSectors(sector + cnt, sectors, &buffer[cnt * 512]);
- if (ret < 0)
- return false;
-
- /* Increment counter */
- cnt += sectors;
- }
-
- return true;
-}
-
-bool umsio_ClearStatus(void) {
- return true;
-}
-
-bool umsio_Shutdown() {
- USBStorage_Deinit();
- return true;
-}
-
-const DISC_INTERFACE __io_wiiums = {
- DEVICE_TYPE_WII_UMS,
- FEATURE_MEDIUM_CANREAD | FEATURE_MEDIUM_CANWRITE | FEATURE_WII_USB,
- (FN_MEDIUM_STARTUP) &umsio_Startup,
- (FN_MEDIUM_ISINSERTED) &umsio_IsInserted,
- (FN_MEDIUM_READSECTORS) &umsio_ReadSectors,
- (FN_MEDIUM_WRITESECTORS) &umsio_WriteSectors,
- (FN_MEDIUM_CLEARSTATUS) &umsio_ClearStatus,
- (FN_MEDIUM_SHUTDOWN) &umsio_Shutdown
-};
-
-const DISC_INTERFACE __io_wiiums_ro = {
- DEVICE_TYPE_WII_UMS,
- FEATURE_MEDIUM_CANREAD | FEATURE_MEDIUM_CANWRITE | FEATURE_WII_USB,
- (FN_MEDIUM_STARTUP) &umsio_Startup,
- (FN_MEDIUM_ISINSERTED) &umsio_IsInserted,
- (FN_MEDIUM_READSECTORS) &umsio_ReadSectors,
- (FN_MEDIUM_WRITESECTORS) &__io_usb_NOP,
- (FN_MEDIUM_CLEARSTATUS) &umsio_ClearStatus,
- (FN_MEDIUM_SHUTDOWN) &umsio_Shutdown
-};
+/*-------------------------------------------------------------
+
+usbstorage_starlet.c -- USB mass storage support, inside starlet
+Copyright (C) 2009 Kwiirk
+
+If this driver is linked before libogc, this will replace the original
+usbstorage driver by svpe from libogc
+This software is provided 'as-is', without any express or implied
+warranty. In no event will the authors be held liable for any
+damages arising from the use of this software.
+
+Permission is granted to anyone to use this software for any
+purpose, including commercial applications, and to alter it and
+redistribute it freely, subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you
+must not claim that you wrote the original software. If you use
+this software in a product, an acknowledgment in the product
+documentation would be appreciated but is not required.
+
+2. Altered source versions must be plainly marked as such, and
+must not be misrepresented as being the original software.
+
+3. This notice may not be removed or altered from any source
+distribution.
+
+-------------------------------------------------------------*/
+
+#include
+#include
+#include
+#include
+
+/* IOCTL commands */
+#define UMS_BASE (('U'<<24)|('M'<<16)|('S'<<8))
+#define USB_IOCTL_UMS_INIT (UMS_BASE+0x1)
+#define USB_IOCTL_UMS_GET_CAPACITY (UMS_BASE+0x2)
+#define USB_IOCTL_UMS_READ_SECTORS (UMS_BASE+0x3)
+#define USB_IOCTL_UMS_WRITE_SECTORS (UMS_BASE+0x4)
+#define USB_IOCTL_UMS_READ_STRESS (UMS_BASE+0x5)
+#define USB_IOCTL_UMS_SET_VERBOSE (UMS_BASE+0x6)
+#define USB_IOCTL_UMS_UNMOUNT (UMS_BASE+0x10)
+#define USB_IOCTL_UMS_WATCHDOG (UMS_BASE+0x80)
+
+#define WBFS_BASE (('W'<<24)|('F'<<16)|('S'<<8))
+#define USB_IOCTL_WBFS_OPEN_DISC (WBFS_BASE+0x1)
+#define USB_IOCTL_WBFS_READ_DISC (WBFS_BASE+0x2)
+#define USB_IOCTL_WBFS_READ_DEBUG (WBFS_BASE+0x3)
+#define USB_IOCTL_WBFS_SET_DEVICE (WBFS_BASE+0x4)
+#define USB_IOCTL_WBFS_SET_FRAGLIST (WBFS_BASE+0x5)
+
+#define UMS_HEAPSIZE 0x1000
+
+/* Variables */
+static char fs[] ATTRIBUTE_ALIGN(32) = "/dev/usb2";
+static char fs2[] ATTRIBUTE_ALIGN(32) = "/dev/usb/ehc";
+static char fs3[] ATTRIBUTE_ALIGN(32) = "/dev/usb/usb123";
+
+static s32 hid = -1, fd = -1;
+static u32 sector_size;
+
+s32 USBStorage_GetCapacity(u32 *_sector_size) {
+ if (fd > 0) {
+ s32 ret;
+
+ ret = IOS_IoctlvFormat(hid, fd, USB_IOCTL_UMS_GET_CAPACITY, ":i", §or_size);
+
+ if (ret && _sector_size)
+ *_sector_size = sector_size;
+
+ return ret;
+ }
+
+ return IPC_ENOENT;
+}
+
+s32 USBStorage_Init(void) {
+ s32 ret;
+
+ /* Already open */
+ if (fd > 0)
+ return 0;
+
+ /* Create heap */
+ if (hid < 0) {
+ hid = iosCreateHeap(UMS_HEAPSIZE);
+ if (hid < 0)
+ return IPC_ENOMEM;
+ }
+
+ /* Open USB device */
+ fd = IOS_Open(fs, 0);
+ if (fd < 0)
+ fd = IOS_Open(fs2, 0);
+ if (fd < 0)
+ fd = IOS_Open(fs3, 0);
+ if (fd < 0)
+ return fd;
+
+ /* Initialize USB storage */
+ ret = IOS_IoctlvFormat(hid, fd, USB_IOCTL_UMS_INIT, ":");
+ if (ret<0) goto err;
+
+ /* Get device capacity */
+ ret = USBStorage_GetCapacity(NULL);
+ if (!ret)
+ goto err;
+
+ return 0;
+
+err:
+ /* Close USB device */
+ if (fd > 0) {
+ IOS_Close(fd);
+ fd = -1;
+ }
+
+ return -1;
+}
+
+/** Hermes **/
+s32 USBStorage_Watchdog(u32 on_off) {
+ if (fd >= 0) {
+ s32 ret;
+
+ ret = IOS_IoctlvFormat(hid, fd, USB_IOCTL_UMS_WATCHDOG, "i:", on_off);
+
+ return ret;
+ }
+
+ return IPC_ENOENT;
+}
+
+s32 USBStorage_Umount(void) {
+ if (fd >= 0) {
+ s32 ret;
+ ret = IOS_IoctlvFormat(hid, fd, USB_IOCTL_UMS_UNMOUNT, ":");
+ return ret;
+ }
+
+ return IPC_ENOENT;
+}
+
+void USBStorage_Deinit(void) {
+ /* Close USB device */
+ if (fd > 0) {
+ IOS_Close(fd);
+ fd = -1;
+ }
+}
+
+s32 USBStorage_ReadSectors(u32 sector, u32 numSectors, void *buffer) {
+
+// void *buf = (void *)buffer;
+ u32 len = (sector_size * numSectors);
+
+ s32 ret;
+
+ /* Device not opened */
+ if (fd < 0)
+ return fd;
+
+
+ ret = IOS_IoctlvFormat(hid, fd, USB_IOCTL_UMS_READ_SECTORS, "ii:d", sector, numSectors, buffer, len);
+ return ret;
+}
+
+s32 USBStorage_WriteSectors(u32 sector, u32 numSectors, const void *buffer) {
+ u32 len = (sector_size * numSectors);
+
+ s32 ret;
+
+ /* Device not opened */
+ if (fd < 0)
+ return fd;
+
+ /* Write data */
+ ret = IOS_IoctlvFormat(hid, fd, USB_IOCTL_UMS_WRITE_SECTORS, "ii:d", sector, numSectors, buffer, len);
+
+ return ret;
+}
+
+static bool __io_usb_Startup(void)
+{
+ return USBStorage_Init() >= 0;
+}
+
+static bool __io_usb_IsInserted(void)
+{
+ s32 ret;
+ if (fd < 0) return false;
+ ret = USBStorage_GetCapacity(NULL);
+ if (ret == 0) return false;
+ return true;
+}
+
+bool __io_usb_ReadSectors(u32 sector, u32 count, void *buffer)
+{
+ s32 ret = USBStorage_ReadSectors(sector, count, buffer);
+ return ret > 0;
+}
+
+bool __io_usb_WriteSectors(u32 sector, u32 count, void *buffer)
+{
+ s32 ret = USBStorage_WriteSectors(sector, count, buffer);
+ return ret > 0;
+}
+
+static bool __io_usb_ClearStatus(void)
+{
+ return true;
+}
+
+static bool __io_usb_Shutdown(void)
+{
+ // do nothing
+ return true;
+}
+
+static bool __io_usb_NOP(void)
+{
+ // do nothing
+ return true;
+}
+
+const DISC_INTERFACE __io_usbstorage_ro = {
+ DEVICE_TYPE_WII_USB,
+ FEATURE_MEDIUM_CANREAD | FEATURE_WII_USB,
+ (FN_MEDIUM_STARTUP) &__io_usb_Startup,
+ (FN_MEDIUM_ISINSERTED) &__io_usb_IsInserted,
+ (FN_MEDIUM_READSECTORS) &__io_usb_ReadSectors,
+ (FN_MEDIUM_WRITESECTORS) &__io_usb_NOP, //&__io_usb_WriteSectors,
+ (FN_MEDIUM_CLEARSTATUS) &__io_usb_ClearStatus,
+ (FN_MEDIUM_SHUTDOWN) &__io_usb_Shutdown
+};
+
+s32 USBStorage_WBFS_Open(char *buffer)
+{
+ u32 len = 8;
+
+ s32 ret;
+
+ /* Device not opened */
+ if (fd < 0)
+ return fd;
+
+ extern u32 wbfs_part_lba;
+ u32 part = wbfs_part_lba;
+
+ /* Read data */
+ ret = IOS_IoctlvFormat(hid, fd, USB_IOCTL_WBFS_OPEN_DISC, "dd:", buffer, len, &part, 4);
+
+ return ret;
+}
+
+// woffset is in 32bit words, len is in bytes
+s32 USBStorage_WBFS_Read(u32 woffset, u32 len, void *buffer)
+{
+ s32 ret;
+
+ USBStorage_Init();
+ /* Device not opened */
+ if (fd < 0)
+ return fd;
+
+ /* Read data */
+ ret = IOS_IoctlvFormat(hid, fd, USB_IOCTL_WBFS_READ_DISC, "ii:d", woffset, len, buffer, len);
+
+ return ret;
+}
+
+
+s32 USBStorage_WBFS_ReadDebug(u32 off, u32 size, void *buffer)
+{
+ s32 ret;
+
+ USBStorage_Init();
+ /* Device not opened */
+ if (fd < 0)
+ return fd;
+
+ /* Read data */
+ ret = IOS_IoctlvFormat(hid, fd, USB_IOCTL_WBFS_READ_DEBUG, "ii:d", off, size, buffer, size);
+
+ return ret;
+}
+
+
+s32 USBStorage_WBFS_SetDevice(int dev)
+{
+ s32 ret;
+ static s32 retval = 0;
+ retval = 0;
+ USBStorage_Init();
+ // Device not opened
+ if (fd < 0) return fd;
+ // ioctl
+ ret = IOS_IoctlvFormat(hid, fd, USB_IOCTL_WBFS_SET_DEVICE, "i:i", dev, &retval);
+ if (retval) return retval;
+ return ret;
+}
+
+s32 USBStorage_WBFS_SetFragList(void *p, int size)
+{
+ s32 ret;
+ USBStorage_Init();
+ // Device not opened
+ if (fd < 0) return fd;
+ // ioctl
+ ret = IOS_IoctlvFormat(hid, fd, USB_IOCTL_WBFS_SET_FRAGLIST, "d:", p, size);
+ return ret;
+}
+
+#define DEVICE_TYPE_WII_UMS (('W'<<24)|('U'<<16)|('M'<<8)|'S')
+
+bool umsio_Startup() {
+ return USBStorage_Init() == 0;
+}
+
+bool umsio_IsInserted() {
+ return true; // allways true
+}
+
+bool umsio_ReadSectors(sec_t sector, sec_t numSectors, u8 *buffer) {
+ u32 cnt = 0;
+ s32 ret;
+ /* Do reads */
+ while (cnt < numSectors) {
+ u32 sectors = (numSectors - cnt);
+
+ /* Read sectors is too big */
+ if (sectors > 32)
+ sectors = 32;
+
+ /* USB read */
+ ret = USBStorage_ReadSectors(sector + cnt, sectors, &buffer[cnt*512]);
+ if (ret < 0)
+ return false;
+
+ /* Increment counter */
+ cnt += sectors;
+ }
+
+ return true;
+}
+
+bool umsio_WriteSectors(sec_t sector, sec_t numSectors, const u8* buffer) {
+ u32 cnt = 0;
+ s32 ret;
+
+ /* Do writes */
+ while (cnt < numSectors) {
+ u32 sectors = (numSectors - cnt);
+
+ /* Write sectors is too big */
+ if (sectors > 32)
+ sectors = 32;
+
+ /* USB write */
+ ret = USBStorage_WriteSectors(sector + cnt, sectors, &buffer[cnt * 512]);
+ if (ret < 0)
+ return false;
+
+ /* Increment counter */
+ cnt += sectors;
+ }
+
+ return true;
+}
+
+bool umsio_ClearStatus(void) {
+ return true;
+}
+
+bool umsio_Shutdown() {
+ USBStorage_Deinit();
+ return true;
+}
+
+const DISC_INTERFACE __io_wiiums = {
+ DEVICE_TYPE_WII_UMS,
+ FEATURE_MEDIUM_CANREAD | FEATURE_MEDIUM_CANWRITE | FEATURE_WII_USB,
+ (FN_MEDIUM_STARTUP) &umsio_Startup,
+ (FN_MEDIUM_ISINSERTED) &umsio_IsInserted,
+ (FN_MEDIUM_READSECTORS) &umsio_ReadSectors,
+ (FN_MEDIUM_WRITESECTORS) &umsio_WriteSectors,
+ (FN_MEDIUM_CLEARSTATUS) &umsio_ClearStatus,
+ (FN_MEDIUM_SHUTDOWN) &umsio_Shutdown
+};
+
+const DISC_INTERFACE __io_wiiums_ro = {
+ DEVICE_TYPE_WII_UMS,
+ FEATURE_MEDIUM_CANREAD | FEATURE_MEDIUM_CANWRITE | FEATURE_WII_USB,
+ (FN_MEDIUM_STARTUP) &umsio_Startup,
+ (FN_MEDIUM_ISINSERTED) &umsio_IsInserted,
+ (FN_MEDIUM_READSECTORS) &umsio_ReadSectors,
+ (FN_MEDIUM_WRITESECTORS) &__io_usb_NOP,
+ (FN_MEDIUM_CLEARSTATUS) &umsio_ClearStatus,
+ (FN_MEDIUM_SHUTDOWN) &umsio_Shutdown
+};
diff --git a/source/usbstorage.h b/source/usbstorage.h
index 47df60a..6c6cec5 100644
--- a/source/usbstorage.h
+++ b/source/usbstorage.h
@@ -1,9 +1,9 @@
-#ifndef _USBSTORAGE_H_
+#ifndef _USBSTORAGE_H_
#define _USBSTORAGE_H_
-
-#ifdef __cplusplus
-extern "C" {
-#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
/* Prototypes */
s32 USBStorage_GetCapacity(u32 *);
s32 USBStorage_Init(void);
@@ -11,7 +11,7 @@ extern "C" {
s32 USBStorage_Watchdog(u32 on_off);
s32 USBStorage_ReadSectors(u32, u32, void *);
s32 USBStorage_WriteSectors(u32, u32, const void *);
-
+
s32 USBStorage_WBFS_Open(char *buf_id);
s32 USBStorage_WBFS_Read(u32 woffset, u32 len, void *buffer);
s32 USBStorage_WBFS_ReadDebug(u32 off, u32 size, void *buffer);
@@ -23,5 +23,5 @@ extern "C" {
#ifdef __cplusplus
}
#endif
-
-#endif
+
+#endif
diff --git a/source/xyzzy.h b/source/xyzzy.h
index 23b7839..d347422 100644
--- a/source/xyzzy.h
+++ b/source/xyzzy.h
@@ -1,74 +1,74 @@
-typedef struct
-{
- u8 boot1_hash[20];
- u8 common_key[16];
- u32 ng_id;
- union {
- struct {
- u8 ng_priv[30];
- u8 _wtf1[18];
- };
- struct {
- u8 _wtf2[28];
- u8 nand_hmac[20];
- };
- };
- u8 nand_key[16];
- u8 rng_key[16];
- u32 unk1;
- u32 unk2; // 0x00000007
-} __attribute__((packed)) otp_t;
-
-typedef struct
-{
- u8 boot2version;
- u8 unknown1;
- u8 unknown2;
- u8 pad;
- u32 update_tag;
- u16 checksum;
-} __attribute__((packed)) eep_ctr_t;
-
-typedef struct
-{
- union {
- struct {
- u32 ms_id;
- u32 ca_id;
- u32 ng_key_id;
- u8 ng_sig[60];
- eep_ctr_t counters[2];
- u8 fill[0x18];
- u8 korean_key[16];
- };
- u8 data[256];
- };
-} __attribute__((packed)) seeprom_t;
-
-typedef struct {
- char text[0x100];
- u8 boot1Hash[20];
- u8 commonKey[16];
- u32 consoleID;
- union {
- struct {
- u8 privateKey[30];
- u8 _wtf1[18];
- };
- struct {
- u8 _wtf2[28];
- u8 nandHmac[20];
- };
- };
- u8 nandKey[16];
- u8 rngKey[16];
- u32 unk1;
- u32 unk2; // 0x00000007
- char blank[136];
- u32 ngKeyID;
- u8 ngSig[60];
- char blank2[440];
-
-} keys;
-
+typedef struct
+{
+ u8 boot1_hash[20];
+ u8 common_key[16];
+ u32 ng_id;
+ union {
+ struct {
+ u8 ng_priv[30];
+ u8 _wtf1[18];
+ };
+ struct {
+ u8 _wtf2[28];
+ u8 nand_hmac[20];
+ };
+ };
+ u8 nand_key[16];
+ u8 rng_key[16];
+ u32 unk1;
+ u32 unk2; // 0x00000007
+} __attribute__((packed)) otp_t;
+
+typedef struct
+{
+ u8 boot2version;
+ u8 unknown1;
+ u8 unknown2;
+ u8 pad;
+ u32 update_tag;
+ u16 checksum;
+} __attribute__((packed)) eep_ctr_t;
+
+typedef struct
+{
+ union {
+ struct {
+ u32 ms_id;
+ u32 ca_id;
+ u32 ng_key_id;
+ u8 ng_sig[60];
+ eep_ctr_t counters[2];
+ u8 fill[0x18];
+ u8 korean_key[16];
+ };
+ u8 data[256];
+ };
+} __attribute__((packed)) seeprom_t;
+
+typedef struct {
+ char text[0x100];
+ u8 boot1Hash[20];
+ u8 commonKey[16];
+ u32 consoleID;
+ union {
+ struct {
+ u8 privateKey[30];
+ u8 _wtf1[18];
+ };
+ struct {
+ u8 _wtf2[28];
+ u8 nandHmac[20];
+ };
+ };
+ u8 nandKey[16];
+ u8 rngKey[16];
+ u32 unk1;
+ u32 unk2; // 0x00000007
+ char blank[136];
+ u32 ngKeyID;
+ u8 ngSig[60];
+ char blank2[440];
+
+} keys;
+
int keydump();
\ No newline at end of file