diff --git a/Makefile b/Makefile
index 795229b9..374e9e4e 100644
--- a/Makefile
+++ b/Makefile
@@ -25,20 +25,20 @@ INCLUDES :=
# options for code generation
#---------------------------------------------------------------------------------
-CFLAGS = -g -O2 -Wall $(MACHDEP) $(INCLUDE)
+CFLAGS = -g -O3 -Wall $(MACHDEP) $(INCLUDE)
CXXFLAGS = $(CFLAGS)
#---------------------------------------------------------------------------------
# move loader to another location - THANKS CREDIAR - 0x81330000 for HBC
#---------------------------------------------------------------------------------
-LDFLAGS = -g $(MACHDEP) -Wl,-Map,$(notdir $@).map -Wl,--section-start,.init=0x81230000
-#LDFLAGS = -g $(MACHDEP) -Wl,-Map,$(notdir $@).map
+#LDFLAGS = -g $(MACHDEP) -Wl,-Map,$(notdir $@).map -Wl,--section-start,.init=0x81000000
+LDFLAGS = -g $(MACHDEP) -Wl,-Map,$(notdir $@).map
#LDFLAGS = -g $(MACHDEP) -Wl,-Map,$(notdir $@).map -Wl,--section-start,.init=0x80003f00
#---------------------------------------------------------------------------------
# any extra libraries we wish to link with the project
#---------------------------------------------------------------------------------
-LIBS := -lfat -lpngu -lpng -lz -lbte -logc -lm
+LIBS := -lfat -lntfs -lpng -lz -lbte -logc -lm
#---------------------------------------------------------------------------------
# list of directories containing libraries, this must be the top level containing
@@ -69,6 +69,8 @@ sFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.S)))
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
PNGFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.png)))
+DOLFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.dol)))
+ELFFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.elf)))
#---------------------------------------------------------------------------------
# use CXX for linking C++ projects, CC for standard C
@@ -82,7 +84,8 @@ endif
export OFILES := $(addsuffix .o,$(BINFILES)) \
$(CPPFILES:.cpp=.o) $(CFILES:.c=.o) \
$(sFILES:.s=.o) $(SFILES:.S=.o) \
- $(PNGFILES:.png=.png.o)
+ $(PNGFILES:.png=.png.o) $(addsuffix .o,$(DOLFILES)) \
+ $(addsuffix .o,$(ELFFILES))
#---------------------------------------------------------------------------------
# build a list of include paths
@@ -137,7 +140,15 @@ $(OUTPUT).elf: $(OFILES)
#---------------------------------------------------------------------------------
%.png.o : %.png
@echo $(notdir $<)
- $(bin2o)
+ @bin2s -a 32 $< | $(AS) -o $(@)
+
+%.dol.o : %.dol
+ @echo $(notdir $<)
+ @bin2s -a 32 $< | $(AS) -o $(@)
+
+%.elf.o : %.elf
+ @echo $(notdir $<)
+ @bin2s -a 32 $< | $(AS) -o $(@)
-include $(DEPENDS)
diff --git a/data/app_booter.dol b/data/app_booter.dol
new file mode 100644
index 00000000..62c156fe
Binary files /dev/null and b/data/app_booter.dol differ
diff --git a/forwarder.pnproj b/forwarder.pnproj
new file mode 100644
index 00000000..37bf9717
--- /dev/null
+++ b/forwarder.pnproj
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/forwarder.pnps b/forwarder.pnps
new file mode 100644
index 00000000..1697fa21
--- /dev/null
+++ b/forwarder.pnps
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/source/background_image.c b/source/background_image.c
new file mode 100644
index 00000000..efe6ce78
--- /dev/null
+++ b/source/background_image.c
@@ -0,0 +1,74 @@
+#include
+#include "pngu.h"
+#include "video.h"
+#include "filelist.h"
+
+static int imagewidth = 0;
+static int imageheight = 0;
+
+u8 * GetImageData()
+{
+ PNGUPROP imgProp;
+ IMGCTX ctx;
+ u8 * data = NULL;
+ int ret;
+
+ if(CONF_GetAspectRatio() == CONF_ASPECT_16_9)
+ ctx = PNGU_SelectImageFromBuffer(background169_png);
+ else
+ ctx = PNGU_SelectImageFromBuffer(background_png);
+
+
+ if (!ctx)
+ return NULL;
+
+ ret = PNGU_GetImageProperties(ctx, &imgProp);
+ if (ret != PNGU_OK)
+ return NULL;
+
+ imagewidth = imgProp.imgWidth;
+ imageheight = imgProp.imgHeight;
+
+ int len = ((((imgProp.imgWidth+3)>>2)*((imgProp.imgHeight+3)>>2)*32*2) + 31) & ~31;
+
+ data = (u8 *)memalign (32, len);
+
+ ret = PNGU_DecodeTo4x4RGBA8 (ctx, imgProp.imgWidth, imgProp.imgHeight, data, 255);
+
+ DCFlushRange(data, len);
+
+ PNGU_ReleaseImageContext(ctx);
+
+ return data;
+}
+
+void Background_Show(float x, float y, float z, u8 * data, float angle, float scaleX, float scaleY, u8 alpha)
+{
+ /* Draw image */
+ Menu_DrawImg(x, y, z, imagewidth, imageheight, data, angle, scaleX, scaleY, alpha);
+ Menu_Render();
+}
+
+void fadein(u8 * imgdata)
+{
+ int i;
+
+ /* fadein of image */
+ for(i = 0; i < 255; i = i+10)
+ {
+ if(i>255) i = 255;
+ Background_Show(0, 0, 0, imgdata, 0, 1, 1, i);
+ }
+}
+
+void fadeout(u8 * imgdata)
+{
+ int i;
+
+ /* fadeoout of image */
+ for(i = 255; i > 1; i = i-7)
+ {
+ if(i < 0) i = 0;
+ Background_Show(0, 0, 0, imgdata, 0, 1, 1, i);
+ }
+}
diff --git a/source/background_image.h b/source/background_image.h
new file mode 100644
index 00000000..d90830ff
--- /dev/null
+++ b/source/background_image.h
@@ -0,0 +1,9 @@
+#ifndef BACKGROUND_IMAGE_H_
+#define BACKGROUND_IMAGE_H_
+
+u8 * GetImageData();
+void Background_Show(float x, float y, float z, u8 * data, float angle, float scaleX, float scaleY, u8 alpha);
+void fadein(u8 * imgdata);
+void fadeout(u8 * imgdata);
+
+#endif
diff --git a/source/cfg.c b/source/cfg.c
index 85bc8a88..68fa241e 100644
--- a/source/cfg.c
+++ b/source/cfg.c
@@ -1,77 +1,77 @@
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include "cfg.h"
-
-char update_path[150];
-
-static char *cfg_name, *cfg_val;
-
-char* strcopy(char *dest, char *src, int size)
-{
- strncpy(dest,src,size);
- dest[size-1] = 0;
- return dest;
-}
-
-char* trimcopy(char *dest, char *src, int size)
-{
- int len;
- while (*src == ' ') src++;
- len = strlen(src);
- // trim trailing " \r\n"
- while (len > 0 && strchr(" \r\n", src[len-1])) len--;
- if (len >= size) len = size-1;
- strncpy(dest, src, len);
- dest[len] = 0;
- return dest;
-}
-
-void cfg_parseline(char *line, void (*set_func)(char*, char*))
-{
- // split name = value
- char tmp[200], name[100], val[100];
- strcopy(tmp, line, sizeof(tmp));
- char *eq = strchr(tmp, '=');
- if (!eq) return;
- *eq = 0;
- trimcopy(name, tmp, sizeof(name));
- trimcopy(val, eq+1, sizeof(val));
- //printf("CFG: %s = %s\n", name, val);
- set_func(name, val);
-}
-
-
-bool cfg_parsefile(char *fname, void (*set_func)(char*, char*))
-{
- FILE *f;
- char line[200];
-
- //printf("opening(%s)\n", fname);
- f = fopen(fname, "r");
- if (!f) {
- //printf("error opening(%s)\n", fname);
- return false;
- }
- while (fgets(line, sizeof(line), f)) {
- // lines starting with # are comments
- if (line[0] == '#') continue;
- cfg_parseline(line, set_func);
- }
- fclose(f);
- return true;
-}
-
-void cfg_set(char *name, char *val)
-{
- cfg_name = name;
- cfg_val = val;
- if (strcmp(name, "update_path") == 0) {
- strcopy(update_path, val, sizeof(update_path));
- }
-}
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "cfg.h"
+
+char update_path[150];
+
+static char *cfg_name, *cfg_val;
+
+char* strcopy(char *dest, char *src, int size)
+{
+ strncpy(dest,src,size);
+ dest[size-1] = 0;
+ return dest;
+}
+
+char* trimcopy(char *dest, char *src, int size)
+{
+ int len;
+ while (*src == ' ') src++;
+ len = strlen(src);
+ // trim trailing " \r\n"
+ while (len > 0 && strchr(" \r\n", src[len-1])) len--;
+ if (len >= size) len = size-1;
+ strncpy(dest, src, len);
+ dest[len] = 0;
+ return dest;
+}
+
+void cfg_parseline(char *line, void (*set_func)(char*, char*))
+{
+ // split name = value
+ char tmp[200], name[100], val[100];
+ strcopy(tmp, line, sizeof(tmp));
+ char *eq = strchr(tmp, '=');
+ if (!eq) return;
+ *eq = 0;
+ trimcopy(name, tmp, sizeof(name));
+ trimcopy(val, eq+1, sizeof(val));
+ //printf("CFG: %s = %s\n", name, val);
+ set_func(name, val);
+}
+
+
+bool cfg_parsefile(char *fname, void (*set_func)(char*, char*))
+{
+ FILE *f;
+ char line[200];
+
+ //printf("opening(%s)\n", fname);
+ f = fopen(fname, "r");
+ if (!f) {
+ //printf("error opening(%s)\n", fname);
+ return false;
+ }
+ while (fgets(line, sizeof(line), f)) {
+ // lines starting with # are comments
+ if (line[0] == '#') continue;
+ cfg_parseline(line, set_func);
+ }
+ fclose(f);
+ return true;
+}
+
+void cfg_set(char *name, char *val)
+{
+ cfg_name = name;
+ cfg_val = val;
+ if (strcmp(name, "update_path") == 0) {
+ strcopy(update_path, val, sizeof(update_path));
+ }
+}
diff --git a/source/devicemounter.c b/source/devicemounter.c
new file mode 100644
index 00000000..4d535598
--- /dev/null
+++ b/source/devicemounter.c
@@ -0,0 +1,120 @@
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "devicemounter.h"
+
+//these are the only stable and speed is good
+#define CACHE 8
+#define SECTORS 64
+
+typedef struct _PARTITION_RECORD {
+ u8 status; /* Partition status; see above */
+ u8 chs_start[3]; /* Cylinder-head-sector address to first block of partition */
+ u8 type; /* Partition type; see above */
+ u8 chs_end[3]; /* Cylinder-head-sector address to last block of partition */
+ u32 lba_start; /* Local block address to first sector of partition */
+ u32 block_count; /* Number of blocks in partition */
+} __attribute__((__packed__)) PARTITION_RECORD;
+
+
+typedef struct _MASTER_BOOT_RECORD {
+ u8 code_area[446]; /* Code area; normally empty */
+ PARTITION_RECORD partitions[4]; /* 4 primary partitions */
+ u16 signature; /* MBR signature; 0xAA55 */
+} __attribute__((__packed__)) MASTER_BOOT_RECORD;
+
+
+#define le32(i) (((((u32) i) & 0xFF) << 24) | ((((u32) i) & 0xFF00) << 8) | \
+ ((((u32) i) & 0xFF0000) >> 8) | ((((u32) i) & 0xFF000000) >> 24))
+
+int USBDevice_Init()
+{
+ time_t start = time(0);
+
+ while(start-time(0) < 10) // 10 sec
+ {
+ if(__io_usbstorage.startup() && __io_usbstorage.isInserted())
+ break;
+
+ usleep(200000); // 1/5 sec
+ }
+
+ if(!__io_usbstorage.startup() || !__io_usbstorage.isInserted())
+ return -1;
+
+ int i;
+ MASTER_BOOT_RECORD mbr;
+ char ntfsBootSector[512];
+
+ __io_usbstorage.readSectors(0, 1, &mbr);
+
+ for(i = 0; i < 4; ++i)
+ {
+ switch(mbr.partitions[i].type)
+ {
+ case 0x01:
+ case 0x04:
+ case 0x06:
+ case 0x0b:
+ case 0x0c:
+ case 0x0e:
+ fatMount(DeviceName[USB1+i], &__io_usbstorage, le32(mbr.partitions[i].lba_start), CACHE, SECTORS);
+ break;
+ case 0x07:
+ __io_usbstorage.readSectors(le32(mbr.partitions[i].lba_start), 1, ntfsBootSector);
+ if(strncmp(&ntfsBootSector[0x03], "NTFS", 4) == 0)
+ ntfsMount(DeviceName[USB1+i], &__io_usbstorage, le32(mbr.partitions[i].lba_start), CACHE, SECTORS, NTFS_SHOW_HIDDEN_FILES | NTFS_RECOVER | NTFS_IGNORE_CASE);
+ break;
+ default:
+ break;
+ }
+ }
+
+ return -1;
+}
+
+void USBDevice_deInit()
+{
+ int dev;
+ char Name[20];
+
+ for(dev = USB1; dev <= USB4; ++dev)
+ {
+ sprintf(Name, "%s:/", DeviceName[dev]);
+ fatUnmount(Name);
+ ntfsUnmount(Name, true);
+ }
+ //Let's not shutdown so it stays awake for the application
+ __io_usbstorage.shutdown();
+ USB_Deinitialize();
+}
+
+int SDCard_Init()
+{
+ if(!__io_wiisd.startup() || !__io_wiisd.isInserted())
+ return -1;
+
+ if (fatMount(DeviceName[SD], &__io_wiisd, 0, CACHE, SECTORS))
+ return 1;
+
+ return -1;
+}
+
+void SDCard_deInit()
+{
+ char Name[20];
+ sprintf(Name, "%s:/", DeviceName[SD]);
+ //closing all open Files write back the cache and then shutdown em!
+ fatUnmount(Name);
+ //Let's not shutdown so it stays awake for the application
+ __io_wiisd.shutdown();
+}
diff --git a/source/fatmounter.h b/source/devicemounter.h
similarity index 53%
rename from source/fatmounter.h
rename to source/devicemounter.h
index e2357020..c747b94a 100644
--- a/source/fatmounter.h
+++ b/source/devicemounter.h
@@ -1,19 +1,37 @@
-#ifndef _FATMOUNTER_H_
-#define _FATMOUNTER_H_
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
-int USBDevice_Init();
-void USBDevice_deInit();
-int isSdInserted();
-int SDCard_Init();
-void SDCard_deInit();
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
+#ifndef _FATMOUNTER_H_
+#define _FATMOUNTER_H_
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+enum
+{
+ SD = 0,
+ USB1,
+ USB2,
+ USB3,
+ USB4,
+ MAXDEVICES
+};
+
+static const char DeviceName[MAXDEVICES][6] =
+{
+ "sd",
+ "usb1",
+ "usb2",
+ "usb3",
+ "usb4"
+};
+
+int USBDevice_Init();
+void USBDevice_deInit();
+int SDCard_Init();
+void SDCard_deInit();
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/source/dolloader.c b/source/dolloader.c
index 7a6629d9..923e2cc1 100644
--- a/source/dolloader.c
+++ b/source/dolloader.c
@@ -1,54 +1,62 @@
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include "dolloader.h"
-
-typedef struct _dolheader {
- u32 text_pos[7];
- u32 data_pos[11];
- u32 text_start[7];
- u32 data_start[11];
- u32 text_size[7];
- u32 data_size[11];
- u32 bss_start;
- u32 bss_size;
- u32 entry_point;
-} dolheader;
-
-u32 load_dol_image (void *dolstart, struct __argv *argv) {
- u32 i;
- dolheader *dolfile;
-
- if (dolstart) {
- dolfile = (dolheader *) dolstart;
- for (i = 0; i < 7; i++) {
- if ((!dolfile->text_size[i]) || (dolfile->text_start[i] < 0x100)) continue;
- VIDEO_WaitVSync();
- ICInvalidateRange ((void *) dolfile->text_start[i],dolfile->text_size[i]);
- memmove ((void *) dolfile->text_start[i],dolstart+dolfile->text_pos[i],dolfile->text_size[i]);
- }
-
- for(i = 0; i < 11; i++) {
- if ((!dolfile->data_size[i]) || (dolfile->data_start[i] < 0x100)) continue;
- VIDEO_WaitVSync();
- memmove ((void *) dolfile->data_start[i],dolstart+dolfile->data_pos[i],dolfile->data_size[i]);
- DCFlushRangeNoSync ((void *) dolfile->data_start[i],dolfile->data_size[i]);
- }
-
- memset ((void *) dolfile->bss_start, 0, dolfile->bss_size);
- DCFlushRange((void *) dolfile->bss_start, dolfile->bss_size);
-
- if (argv && argv->argvMagic == ARGV_MAGIC) {
- void *new_argv = (void *)(dolfile->entry_point + 8);
- memmove(new_argv, argv, sizeof(*argv));
- DCFlushRange(new_argv, sizeof(*argv));
- }
- return dolfile->entry_point;
- }
- return 0;
-}
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "dolloader.h"
+
+typedef struct _dolheader {
+ u32 text_pos[7];
+ u32 data_pos[11];
+ u32 text_start[7];
+ u32 data_start[11];
+ u32 text_size[7];
+ u32 data_size[11];
+ u32 bss_start;
+ u32 bss_size;
+ u32 entry_point;
+} dolheader;
+
+u32 load_dol_image(const void *dolstart, struct __argv *argv)
+{
+ u32 i;
+ dolheader *dolfile;
+
+ if (dolstart)
+ {
+ dolfile = (dolheader *) dolstart;
+ for (i = 0; i < 7; i++)
+ {
+ if ((!dolfile->text_size[i]) || (dolfile->text_start[i] < 0x100))
+ continue;
+
+ VIDEO_WaitVSync();
+ memmove((void *) dolfile->text_start[i], dolstart + dolfile->text_pos[i], dolfile->text_size[i]);
+ DCFlushRange ((void *) dolfile->text_start[i], dolfile->text_size[i]);
+ ICInvalidateRange((void *) dolfile->text_start[i], dolfile->text_size[i]);
+ }
+
+ for (i = 0; i < 11; i++)
+ {
+ if ((!dolfile->data_size[i]) || (dolfile->data_start[i] < 0x100))
+ continue;
+
+ VIDEO_WaitVSync();
+ memmove((void *) dolfile->data_start[i], dolstart + dolfile->data_pos[i], dolfile->data_size[i]);
+ DCFlushRange((void *) dolfile->data_start[i],
+ dolfile->data_size[i]);
+ }
+
+ if (argv && argv->argvMagic == ARGV_MAGIC)
+ {
+ void *new_argv = (void *) (dolfile->entry_point + 8);
+ memmove(new_argv, argv, sizeof(*argv));
+ DCFlushRange(new_argv, sizeof(*argv));
+ }
+ return dolfile->entry_point;
+ }
+ return 0;
+}
diff --git a/source/dolloader.h b/source/dolloader.h
index 7dcc2921..e4c50820 100644
--- a/source/dolloader.h
+++ b/source/dolloader.h
@@ -1,23 +1,20 @@
-#ifndef _DOLLOADER_H_
-#define _DOLLOADER_H_
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
-// Apps goes here
-#define EXECUTABLE_MEM_ADDR 0x92000000
-/* dol header */
-
-extern void __exception_closeall();
-typedef void (*entrypoint) (void);
-
-u32 load_dol_image (void *dolstart, struct __argv *argv);
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
+#ifndef _DOLLOADER_H_
+#define _DOLLOADER_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define EXECUTABLE_MEM_ADDR 0x92000000
+
+extern void __exception_closeall();
+typedef void (*entrypoint) (void);
+
+u32 load_dol_image(const void *dolstart, struct __argv *argv);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/source/elf_abi.h b/source/elf_abi.h
deleted file mode 100644
index c9e705ef..00000000
--- a/source/elf_abi.h
+++ /dev/null
@@ -1,594 +0,0 @@
-/*
- * Copyright (c) 1995, 1996, 2001, 2002
- * Erik Theisen. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * This is the ELF ABI header file
- * formerly known as "elf_abi.h".
- */
-
-#ifndef _ELF_ABI_H
-#define _ELF_ABI_H
-
-#include
-
-/*
- * This version doesn't work for 64-bit ABIs - Erik.
- */
-
-/*
- * These typedefs need to be handled better.
- */
-typedef u32 Elf32_Addr; /* Unsigned program address */
-typedef u32 Elf32_Off; /* Unsigned file offset */
-typedef s32 Elf32_Sword; /* Signed large integer */
-typedef u32 Elf32_Word; /* Unsigned large integer */
-typedef u16 Elf32_Half; /* Unsigned medium integer */
-
-/* e_ident[] identification indexes */
-#define EI_MAG0 0 /* file ID */
-#define EI_MAG1 1 /* file ID */
-#define EI_MAG2 2 /* file ID */
-#define EI_MAG3 3 /* file ID */
-#define EI_CLASS 4 /* file class */
-#define EI_DATA 5 /* data encoding */
-#define EI_VERSION 6 /* ELF header version */
-#define EI_OSABI 7 /* OS/ABI specific ELF extensions */
-#define EI_ABIVERSION 8 /* ABI target version */
-#define EI_PAD 9 /* start of pad bytes */
-#define EI_NIDENT 16 /* Size of e_ident[] */
-
-/* e_ident[] magic number */
-#define ELFMAG0 0x7f /* e_ident[EI_MAG0] */
-#define ELFMAG1 'E' /* e_ident[EI_MAG1] */
-#define ELFMAG2 'L' /* e_ident[EI_MAG2] */
-#define ELFMAG3 'F' /* e_ident[EI_MAG3] */
-#define ELFMAG "\177ELF" /* magic */
-#define SELFMAG 4 /* size of magic */
-
-/* e_ident[] file class */
-#define ELFCLASSNONE 0 /* invalid */
-#define ELFCLASS32 1 /* 32-bit objs */
-#define ELFCLASS64 2 /* 64-bit objs */
-#define ELFCLASSNUM 3 /* number of classes */
-
-/* e_ident[] data encoding */
-#define ELFDATANONE 0 /* invalid */
-#define ELFDATA2LSB 1 /* Little-Endian */
-#define ELFDATA2MSB 2 /* Big-Endian */
-#define ELFDATANUM 3 /* number of data encode defines */
-
-/* e_ident[] OS/ABI specific ELF extensions */
-#define ELFOSABI_NONE 0 /* No extension specified */
-#define ELFOSABI_HPUX 1 /* Hewlett-Packard HP-UX */
-#define ELFOSABI_NETBSD 2 /* NetBSD */
-#define ELFOSABI_LINUX 3 /* Linux */
-#define ELFOSABI_SOLARIS 6 /* Sun Solaris */
-#define ELFOSABI_AIX 7 /* AIX */
-#define ELFOSABI_IRIX 8 /* IRIX */
-#define ELFOSABI_FREEBSD 9 /* FreeBSD */
-#define ELFOSABI_TRU64 10 /* Compaq TRU64 UNIX */
-#define ELFOSABI_MODESTO 11 /* Novell Modesto */
-#define ELFOSABI_OPENBSD 12 /* OpenBSD */
-/* 64-255 Architecture-specific value range */
-
-/* e_ident[] ABI Version */
-#define ELFABIVERSION 0
-
-/* e_ident */
-#define IS_ELF(ehdr) ((ehdr).e_ident[EI_MAG0] == ELFMAG0 && \
- (ehdr).e_ident[EI_MAG1] == ELFMAG1 && \
- (ehdr).e_ident[EI_MAG2] == ELFMAG2 && \
- (ehdr).e_ident[EI_MAG3] == ELFMAG3)
-
-/* ELF Header */
-typedef struct elfhdr{
- unsigned char e_ident[EI_NIDENT]; /* ELF Identification */
- Elf32_Half e_type; /* object file type */
- Elf32_Half e_machine; /* machine */
- Elf32_Word e_version; /* object file version */
- Elf32_Addr e_entry; /* virtual entry point */
- Elf32_Off e_phoff; /* program header table offset */
- Elf32_Off e_shoff; /* section header table offset */
- Elf32_Word e_flags; /* processor-specific flags */
- Elf32_Half e_ehsize; /* ELF header size */
- Elf32_Half e_phentsize; /* program header entry size */
- Elf32_Half e_phnum; /* number of program header entries */
- Elf32_Half e_shentsize; /* section header entry size */
- Elf32_Half e_shnum; /* number of section header entries */
- Elf32_Half e_shstrndx; /* section header table's "section
- header string table" entry offset */
-} Elf32_Ehdr;
-
-/* e_type */
-#define ET_NONE 0 /* No file type */
-#define ET_REL 1 /* relocatable file */
-#define ET_EXEC 2 /* executable file */
-#define ET_DYN 3 /* shared object file */
-#define ET_CORE 4 /* core file */
-#define ET_NUM 5 /* number of types */
-#define ET_LOOS 0xfe00 /* reserved range for operating */
-#define ET_HIOS 0xfeff /* system specific e_type */
-#define ET_LOPROC 0xff00 /* reserved range for processor */
-#define ET_HIPROC 0xffff /* specific e_type */
-
-/* e_machine */
-#define EM_NONE 0 /* No Machine */
-#define EM_M32 1 /* AT&T WE 32100 */
-#define EM_SPARC 2 /* SPARC */
-#define EM_386 3 /* Intel 80386 */
-#define EM_68K 4 /* Motorola 68000 */
-#define EM_88K 5 /* Motorola 88000 */
-#if 0
-#define EM_486 6 /* RESERVED - was Intel 80486 */
-#endif
-#define EM_860 7 /* Intel 80860 */
-#define EM_MIPS 8 /* MIPS R3000 Big-Endian only */
-#define EM_S370 9 /* IBM System/370 Processor */
-#define EM_MIPS_RS4_BE 10 /* MIPS R4000 Big-Endian */
-#if 0
-#define EM_SPARC64 11 /* RESERVED - was SPARC v9
- 64-bit unoffical */
-#endif
-/* RESERVED 11-14 for future use */
-#define EM_PARISC 15 /* HPPA */
-/* RESERVED 16 for future use */
-#define EM_VPP500 17 /* Fujitsu VPP500 */
-#define EM_SPARC32PLUS 18 /* Enhanced instruction set SPARC */
-#define EM_960 19 /* Intel 80960 */
-#define EM_PPC 20 /* PowerPC */
-#define EM_PPC64 21 /* 64-bit PowerPC */
-#define EM_S390 22 /* IBM System/390 Processor */
-/* RESERVED 23-35 for future use */
-#define EM_V800 36 /* NEC V800 */
-#define EM_FR20 37 /* Fujitsu FR20 */
-#define EM_RH32 38 /* TRW RH-32 */
-#define EM_RCE 39 /* Motorola RCE */
-#define EM_ARM 40 /* Advanced Risc Machines ARM */
-#define EM_ALPHA 41 /* Digital Alpha */
-#define EM_SH 42 /* Hitachi SH */
-#define EM_SPARCV9 43 /* SPARC Version 9 */
-#define EM_TRICORE 44 /* Siemens TriCore embedded processor */
-#define EM_ARC 45 /* Argonaut RISC Core */
-#define EM_H8_300 46 /* Hitachi H8/300 */
-#define EM_H8_300H 47 /* Hitachi H8/300H */
-#define EM_H8S 48 /* Hitachi H8S */
-#define EM_H8_500 49 /* Hitachi H8/500 */
-#define EM_IA_64 50 /* Intel Merced */
-#define EM_MIPS_X 51 /* Stanford MIPS-X */
-#define EM_COLDFIRE 52 /* Motorola Coldfire */
-#define EM_68HC12 53 /* Motorola M68HC12 */
-#define EM_MMA 54 /* Fujitsu MMA Multimedia Accelerator*/
-#define EM_PCP 55 /* Siemens PCP */
-#define EM_NCPU 56 /* Sony nCPU embeeded RISC */
-#define EM_NDR1 57 /* Denso NDR1 microprocessor */
-#define EM_STARCORE 58 /* Motorola Start*Core processor */
-#define EM_ME16 59 /* Toyota ME16 processor */
-#define EM_ST100 60 /* STMicroelectronic ST100 processor */
-#define EM_TINYJ 61 /* Advanced Logic Corp. Tinyj emb.fam*/
-#define EM_X86_64 62 /* AMD x86-64 */
-#define EM_PDSP 63 /* Sony DSP Processor */
-/* RESERVED 64,65 for future use */
-#define EM_FX66 66 /* Siemens FX66 microcontroller */
-#define EM_ST9PLUS 67 /* STMicroelectronics ST9+ 8/16 mc */
-#define EM_ST7 68 /* STmicroelectronics ST7 8 bit mc */
-#define EM_68HC16 69 /* Motorola MC68HC16 microcontroller */
-#define EM_68HC11 70 /* Motorola MC68HC11 microcontroller */
-#define EM_68HC08 71 /* Motorola MC68HC08 microcontroller */
-#define EM_68HC05 72 /* Motorola MC68HC05 microcontroller */
-#define EM_SVX 73 /* Silicon Graphics SVx */
-#define EM_ST19 74 /* STMicroelectronics ST19 8 bit mc */
-#define EM_VAX 75 /* Digital VAX */
-#define EM_CHRIS 76 /* Axis Communications embedded proc. */
-#define EM_JAVELIN 77 /* Infineon Technologies emb. proc. */
-#define EM_FIREPATH 78 /* Element 14 64-bit DSP Processor */
-#define EM_ZSP 79 /* LSI Logic 16-bit DSP Processor */
-#define EM_MMIX 80 /* Donald Knuth's edu 64-bit proc. */
-#define EM_HUANY 81 /* Harvard University mach-indep objs */
-#define EM_PRISM 82 /* SiTera Prism */
-#define EM_AVR 83 /* Atmel AVR 8-bit microcontroller */
-#define EM_FR30 84 /* Fujitsu FR30 */
-#define EM_D10V 85 /* Mitsubishi DV10V */
-#define EM_D30V 86 /* Mitsubishi DV30V */
-#define EM_V850 87 /* NEC v850 */
-#define EM_M32R 88 /* Mitsubishi M32R */
-#define EM_MN10300 89 /* Matsushita MN10200 */
-#define EM_MN10200 90 /* Matsushita MN10200 */
-#define EM_PJ 91 /* picoJava */
-#define EM_NUM 92 /* number of machine types */
-
-/* Version */
-#define EV_NONE 0 /* Invalid */
-#define EV_CURRENT 1 /* Current */
-#define EV_NUM 2 /* number of versions */
-
-/* Section Header */
-typedef struct {
- Elf32_Word sh_name; /* name - index into section header
- string table section */
- Elf32_Word sh_type; /* type */
- Elf32_Word sh_flags; /* flags */
- Elf32_Addr sh_addr; /* address */
- Elf32_Off sh_offset; /* file offset */
- Elf32_Word sh_size; /* section size */
- Elf32_Word sh_link; /* section header table index link */
- Elf32_Word sh_info; /* extra information */
- Elf32_Word sh_addralign; /* address alignment */
- Elf32_Word sh_entsize; /* section entry size */
-} Elf32_Shdr;
-
-/* Special Section Indexes */
-#define SHN_UNDEF 0 /* undefined */
-#define SHN_LORESERVE 0xff00 /* lower bounds of reserved indexes */
-#define SHN_LOPROC 0xff00 /* reserved range for processor */
-#define SHN_HIPROC 0xff1f /* specific section indexes */
-#define SHN_LOOS 0xff20 /* reserved range for operating */
-#define SHN_HIOS 0xff3f /* specific semantics */
-#define SHN_ABS 0xfff1 /* absolute value */
-#define SHN_COMMON 0xfff2 /* common symbol */
-#define SHN_XINDEX 0xffff /* Index is an extra table */
-#define SHN_HIRESERVE 0xffff /* upper bounds of reserved indexes */
-
-/* sh_type */
-#define SHT_NULL 0 /* inactive */
-#define SHT_PROGBITS 1 /* program defined information */
-#define SHT_SYMTAB 2 /* symbol table section */
-#define SHT_STRTAB 3 /* string table section */
-#define SHT_RELA 4 /* relocation section with addends*/
-#define SHT_HASH 5 /* symbol hash table section */
-#define SHT_DYNAMIC 6 /* dynamic section */
-#define SHT_NOTE 7 /* note section */
-#define SHT_NOBITS 8 /* no space section */
-#define SHT_REL 9 /* relation section without addends */
-#define SHT_SHLIB 10 /* reserved - purpose unknown */
-#define SHT_DYNSYM 11 /* dynamic symbol table section */
-#define SHT_INIT_ARRAY 14 /* Array of constructors */
-#define SHT_FINI_ARRAY 15 /* Array of destructors */
-#define SHT_PREINIT_ARRAY 16 /* Array of pre-constructors */
-#define SHT_GROUP 17 /* Section group */
-#define SHT_SYMTAB_SHNDX 18 /* Extended section indeces */
-#define SHT_NUM 19 /* number of section types */
-#define SHT_LOOS 0x60000000 /* Start OS-specific */
-#define SHT_HIOS 0x6fffffff /* End OS-specific */
-#define SHT_LOPROC 0x70000000 /* reserved range for processor */
-#define SHT_HIPROC 0x7fffffff /* specific section header types */
-#define SHT_LOUSER 0x80000000 /* reserved range for application */
-#define SHT_HIUSER 0xffffffff /* specific indexes */
-
-/* Section names */
-#define ELF_BSS ".bss" /* uninitialized data */
-#define ELF_COMMENT ".comment" /* version control information */
-#define ELF_DATA ".data" /* initialized data */
-#define ELF_DATA1 ".data1" /* initialized data */
-#define ELF_DEBUG ".debug" /* debug */
-#define ELF_DYNAMIC ".dynamic" /* dynamic linking information */
-#define ELF_DYNSTR ".dynstr" /* dynamic string table */
-#define ELF_DYNSYM ".dynsym" /* dynamic symbol table */
-#define ELF_FINI ".fini" /* termination code */
-#define ELF_FINI_ARRAY ".fini_array" /* Array of destructors */
-#define ELF_GOT ".got" /* global offset table */
-#define ELF_HASH ".hash" /* symbol hash table */
-#define ELF_INIT ".init" /* initialization code */
-#define ELF_INIT_ARRAY ".init_array" /* Array of constuctors */
-#define ELF_INTERP ".interp" /* Pathname of program interpreter */
-#define ELF_LINE ".line" /* Symbolic line numnber information */
-#define ELF_NOTE ".note" /* Contains note section */
-#define ELF_PLT ".plt" /* Procedure linkage table */
-#define ELF_PREINIT_ARRAY ".preinit_array" /* Array of pre-constructors */
-#define ELF_REL_DATA ".rel.data" /* relocation data */
-#define ELF_REL_FINI ".rel.fini" /* relocation termination code */
-#define ELF_REL_INIT ".rel.init" /* relocation initialization code */
-#define ELF_REL_DYN ".rel.dyn" /* relocaltion dynamic link info */
-#define ELF_REL_RODATA ".rel.rodata" /* relocation read-only data */
-#define ELF_REL_TEXT ".rel.text" /* relocation code */
-#define ELF_RODATA ".rodata" /* read-only data */
-#define ELF_RODATA1 ".rodata1" /* read-only data */
-#define ELF_SHSTRTAB ".shstrtab" /* section header string table */
-#define ELF_STRTAB ".strtab" /* string table */
-#define ELF_SYMTAB ".symtab" /* symbol table */
-#define ELF_SYMTAB_SHNDX ".symtab_shndx"/* symbol table section index */
-#define ELF_TBSS ".tbss" /* thread local uninit data */
-#define ELF_TDATA ".tdata" /* thread local init data */
-#define ELF_TDATA1 ".tdata1" /* thread local init data */
-#define ELF_TEXT ".text" /* code */
-
-/* Section Attribute Flags - sh_flags */
-#define SHF_WRITE 0x1 /* Writable */
-#define SHF_ALLOC 0x2 /* occupies memory */
-#define SHF_EXECINSTR 0x4 /* executable */
-#define SHF_MERGE 0x10 /* Might be merged */
-#define SHF_STRINGS 0x20 /* Contains NULL terminated strings */
-#define SHF_INFO_LINK 0x40 /* sh_info contains SHT index */
-#define SHF_LINK_ORDER 0x80 /* Preserve order after combining*/
-#define SHF_OS_NONCONFORMING 0x100 /* Non-standard OS specific handling */
-#define SHF_GROUP 0x200 /* Member of section group */
-#define SHF_TLS 0x400 /* Thread local storage */
-#define SHF_MASKOS 0x0ff00000 /* OS specific */
-#define SHF_MASKPROC 0xf0000000 /* reserved bits for processor */
- /* specific section attributes */
-
-/* Section Group Flags */
-#define GRP_COMDAT 0x1 /* COMDAT group */
-#define GRP_MASKOS 0x0ff00000 /* Mask OS specific flags */
-#define GRP_MASKPROC 0xf0000000 /* Mask processor specific flags */
-
-/* Symbol Table Entry */
-typedef struct elf32_sym {
- Elf32_Word st_name; /* name - index into string table */
- Elf32_Addr st_value; /* symbol value */
- Elf32_Word st_size; /* symbol size */
- unsigned char st_info; /* type and binding */
- unsigned char st_other; /* 0 - no defined meaning */
- Elf32_Half st_shndx; /* section header index */
-} Elf32_Sym;
-
-/* Symbol table index */
-#define STN_UNDEF 0 /* undefined */
-
-/* Extract symbol info - st_info */
-#define ELF32_ST_BIND(x) ((x) >> 4)
-#define ELF32_ST_TYPE(x) (((unsigned int) x) & 0xf)
-#define ELF32_ST_INFO(b,t) (((b) << 4) + ((t) & 0xf))
-#define ELF32_ST_VISIBILITY(x) ((x) & 0x3)
-
-/* Symbol Binding - ELF32_ST_BIND - st_info */
-#define STB_LOCAL 0 /* Local symbol */
-#define STB_GLOBAL 1 /* Global symbol */
-#define STB_WEAK 2 /* like global - lower precedence */
-#define STB_NUM 3 /* number of symbol bindings */
-#define STB_LOOS 10 /* reserved range for operating */
-#define STB_HIOS 12 /* system specific symbol bindings */
-#define STB_LOPROC 13 /* reserved range for processor */
-#define STB_HIPROC 15 /* specific symbol bindings */
-
-/* Symbol type - ELF32_ST_TYPE - st_info */
-#define STT_NOTYPE 0 /* not specified */
-#define STT_OBJECT 1 /* data object */
-#define STT_FUNC 2 /* function */
-#define STT_SECTION 3 /* section */
-#define STT_FILE 4 /* file */
-#define STT_NUM 5 /* number of symbol types */
-#define STT_TLS 6 /* Thread local storage symbol */
-#define STT_LOOS 10 /* reserved range for operating */
-#define STT_HIOS 12 /* system specific symbol types */
-#define STT_LOPROC 13 /* reserved range for processor */
-#define STT_HIPROC 15 /* specific symbol types */
-
-/* Symbol visibility - ELF32_ST_VISIBILITY - st_other */
-#define STV_DEFAULT 0 /* Normal visibility rules */
-#define STV_INTERNAL 1 /* Processor specific hidden class */
-#define STV_HIDDEN 2 /* Symbol unavailable in other mods */
-#define STV_PROTECTED 3 /* Not preemptible, not exported */
-
-
-/* Relocation entry with implicit addend */
-typedef struct
-{
- Elf32_Addr r_offset; /* offset of relocation */
- Elf32_Word r_info; /* symbol table index and type */
-} Elf32_Rel;
-
-/* Relocation entry with explicit addend */
-typedef struct
-{
- Elf32_Addr r_offset; /* offset of relocation */
- Elf32_Word r_info; /* symbol table index and type */
- Elf32_Sword r_addend;
-} Elf32_Rela;
-
-/* Extract relocation info - r_info */
-#define ELF32_R_SYM(i) ((i) >> 8)
-#define ELF32_R_TYPE(i) ((unsigned char) (i))
-#define ELF32_R_INFO(s,t) (((s) << 8) + (unsigned char)(t))
-
-/* Program Header */
-typedef struct {
- Elf32_Word p_type; /* segment type */
- Elf32_Off p_offset; /* segment offset */
- Elf32_Addr p_vaddr; /* virtual address of segment */
- Elf32_Addr p_paddr; /* physical address - ignored? */
- Elf32_Word p_filesz; /* number of bytes in file for seg. */
- Elf32_Word p_memsz; /* number of bytes in mem. for seg. */
- Elf32_Word p_flags; /* flags */
- Elf32_Word p_align; /* memory alignment */
-} Elf32_Phdr;
-
-/* Segment types - p_type */
-#define PT_NULL 0 /* unused */
-#define PT_LOAD 1 /* loadable segment */
-#define PT_DYNAMIC 2 /* dynamic linking section */
-#define PT_INTERP 3 /* the RTLD */
-#define PT_NOTE 4 /* auxiliary information */
-#define PT_SHLIB 5 /* reserved - purpose undefined */
-#define PT_PHDR 6 /* program header */
-#define PT_TLS 7 /* Thread local storage template */
-#define PT_NUM 8 /* Number of segment types */
-#define PT_LOOS 0x60000000 /* reserved range for operating */
-#define PT_HIOS 0x6fffffff /* system specific segment types */
-#define PT_LOPROC 0x70000000 /* reserved range for processor */
-#define PT_HIPROC 0x7fffffff /* specific segment types */
-
-/* Segment flags - p_flags */
-#define PF_X 0x1 /* Executable */
-#define PF_W 0x2 /* Writable */
-#define PF_R 0x4 /* Readable */
-#define PF_MASKOS 0x0ff00000 /* OS specific segment flags */
-#define PF_MASKPROC 0xf0000000 /* reserved bits for processor */
- /* specific segment flags */
-/* Dynamic structure */
-typedef struct
-{
- Elf32_Sword d_tag; /* controls meaning of d_val */
- union
- {
- Elf32_Word d_val; /* Multiple meanings - see d_tag */
- Elf32_Addr d_ptr; /* program virtual address */
- } d_un;
-} Elf32_Dyn;
-
-extern Elf32_Dyn _DYNAMIC[];
-
-/* Dynamic Array Tags - d_tag */
-#define DT_NULL 0 /* marks end of _DYNAMIC array */
-#define DT_NEEDED 1 /* string table offset of needed lib */
-#define DT_PLTRELSZ 2 /* size of relocation entries in PLT */
-#define DT_PLTGOT 3 /* address PLT/GOT */
-#define DT_HASH 4 /* address of symbol hash table */
-#define DT_STRTAB 5 /* address of string table */
-#define DT_SYMTAB 6 /* address of symbol table */
-#define DT_RELA 7 /* address of relocation table */
-#define DT_RELASZ 8 /* size of relocation table */
-#define DT_RELAENT 9 /* size of relocation entry */
-#define DT_STRSZ 10 /* size of string table */
-#define DT_SYMENT 11 /* size of symbol table entry */
-#define DT_INIT 12 /* address of initialization func. */
-#define DT_FINI 13 /* address of termination function */
-#define DT_SONAME 14 /* string table offset of shared obj */
-#define DT_RPATH 15 /* string table offset of library
- search path */
-#define DT_SYMBOLIC 16 /* start sym search in shared obj. */
-#define DT_REL 17 /* address of rel. tbl. w addends */
-#define DT_RELSZ 18 /* size of DT_REL relocation table */
-#define DT_RELENT 19 /* size of DT_REL relocation entry */
-#define DT_PLTREL 20 /* PLT referenced relocation entry */
-#define DT_DEBUG 21 /* bugger */
-#define DT_TEXTREL 22 /* Allow rel. mod. to unwritable seg */
-#define DT_JMPREL 23 /* add. of PLT's relocation entries */
-#define DT_BIND_NOW 24 /* Process relocations of object */
-#define DT_INIT_ARRAY 25 /* Array with addresses of init fct */
-#define DT_FINI_ARRAY 26 /* Array with addresses of fini fct */
-#define DT_INIT_ARRAYSZ 27 /* Size in bytes of DT_INIT_ARRAY */
-#define DT_FINI_ARRAYSZ 28 /* Size in bytes of DT_FINI_ARRAY */
-#define DT_RUNPATH 29 /* Library search path */
-#define DT_FLAGS 30 /* Flags for the object being loaded */
-#define DT_ENCODING 32 /* Start of encoded range */
-#define DT_PREINIT_ARRAY 32 /* Array with addresses of preinit fct*/
-#define DT_PREINIT_ARRAYSZ 33 /* size in bytes of DT_PREINIT_ARRAY */
-#define DT_NUM 34 /* Number used. */
-#define DT_LOOS 0x60000000 /* reserved range for OS */
-#define DT_HIOS 0x6fffffff /* specific dynamic array tags */
-#define DT_LOPROC 0x70000000 /* reserved range for processor */
-#define DT_HIPROC 0x7fffffff /* specific dynamic array tags */
-
-/* Dynamic Tag Flags - d_un.d_val */
-#define DF_ORIGIN 0x01 /* Object may use DF_ORIGIN */
-#define DF_SYMBOLIC 0x02 /* Symbol resolutions starts here */
-#define DF_TEXTREL 0x04 /* Object contains text relocations */
-#define DF_BIND_NOW 0x08 /* No lazy binding for this object */
-#define DF_STATIC_TLS 0x10 /* Static thread local storage */
-
-/* Standard ELF hashing function */
-unsigned long elf_hash(const unsigned char *name);
-
-#define ELF_TARG_VER 1 /* The ver for which this code is intended */
-
-/*
- * XXX - PowerPC defines really don't belong in here,
- * but we'll put them in for simplicity.
- */
-
-/* Values for Elf32/64_Ehdr.e_flags. */
-#define EF_PPC_EMB 0x80000000 /* PowerPC embedded flag */
-
-/* Cygnus local bits below */
-#define EF_PPC_RELOCATABLE 0x00010000 /* PowerPC -mrelocatable flag*/
-#define EF_PPC_RELOCATABLE_LIB 0x00008000 /* PowerPC -mrelocatable-lib
- flag */
-
-/* PowerPC relocations defined by the ABIs */
-#define R_PPC_NONE 0
-#define R_PPC_ADDR32 1 /* 32bit absolute address */
-#define R_PPC_ADDR24 2 /* 26bit address, 2 bits ignored. */
-#define R_PPC_ADDR16 3 /* 16bit absolute address */
-#define R_PPC_ADDR16_LO 4 /* lower 16bit of absolute address */
-#define R_PPC_ADDR16_HI 5 /* high 16bit of absolute address */
-#define R_PPC_ADDR16_HA 6 /* adjusted high 16bit */
-#define R_PPC_ADDR14 7 /* 16bit address, 2 bits ignored */
-#define R_PPC_ADDR14_BRTAKEN 8
-#define R_PPC_ADDR14_BRNTAKEN 9
-#define R_PPC_REL24 10 /* PC relative 26 bit */
-#define R_PPC_REL14 11 /* PC relative 16 bit */
-#define R_PPC_REL14_BRTAKEN 12
-#define R_PPC_REL14_BRNTAKEN 13
-#define R_PPC_GOT16 14
-#define R_PPC_GOT16_LO 15
-#define R_PPC_GOT16_HI 16
-#define R_PPC_GOT16_HA 17
-#define R_PPC_PLTREL24 18
-#define R_PPC_COPY 19
-#define R_PPC_GLOB_DAT 20
-#define R_PPC_JMP_SLOT 21
-#define R_PPC_RELATIVE 22
-#define R_PPC_LOCAL24PC 23
-#define R_PPC_UADDR32 24
-#define R_PPC_UADDR16 25
-#define R_PPC_REL32 26
-#define R_PPC_PLT32 27
-#define R_PPC_PLTREL32 28
-#define R_PPC_PLT16_LO 29
-#define R_PPC_PLT16_HI 30
-#define R_PPC_PLT16_HA 31
-#define R_PPC_SDAREL16 32
-#define R_PPC_SECTOFF 33
-#define R_PPC_SECTOFF_LO 34
-#define R_PPC_SECTOFF_HI 35
-#define R_PPC_SECTOFF_HA 36
-/* Keep this the last entry. */
-#define R_PPC_NUM 37
-
-/* The remaining relocs are from the Embedded ELF ABI, and are not
- in the SVR4 ELF ABI. */
-#define R_PPC_EMB_NADDR32 101
-#define R_PPC_EMB_NADDR16 102
-#define R_PPC_EMB_NADDR16_LO 103
-#define R_PPC_EMB_NADDR16_HI 104
-#define R_PPC_EMB_NADDR16_HA 105
-#define R_PPC_EMB_SDAI16 106
-#define R_PPC_EMB_SDA2I16 107
-#define R_PPC_EMB_SDA2REL 108
-#define R_PPC_EMB_SDA21 109 /* 16 bit offset in SDA */
-#define R_PPC_EMB_MRKREF 110
-#define R_PPC_EMB_RELSEC16 111
-#define R_PPC_EMB_RELST_LO 112
-#define R_PPC_EMB_RELST_HI 113
-#define R_PPC_EMB_RELST_HA 114
-#define R_PPC_EMB_BIT_FLD 115
-#define R_PPC_EMB_RELSDA 116 /* 16 bit relative offset in SDA */
-
-/* Diab tool relocations. */
-#define R_PPC_DIAB_SDA21_LO 180 /* like EMB_SDA21, but lower 16 bit */
-#define R_PPC_DIAB_SDA21_HI 181 /* like EMB_SDA21, but high 16 bit */
-#define R_PPC_DIAB_SDA21_HA 182 /* like EMB_SDA21, adjusted high 16 */
-#define R_PPC_DIAB_RELSDA_LO 183 /* like EMB_RELSDA, but lower 16 bit */
-#define R_PPC_DIAB_RELSDA_HI 184 /* like EMB_RELSDA, but high 16 bit */
-#define R_PPC_DIAB_RELSDA_HA 185 /* like EMB_RELSDA, adjusted high 16 */
-
-/* This is a phony reloc to handle any old fashioned TOC16 references
- that may still be in object files. */
-#define R_PPC_TOC16 255
-
-#endif /* _ELF_H */
-
diff --git a/source/elfloader.c b/source/elfloader.c
deleted file mode 100644
index 651a1eef..00000000
--- a/source/elfloader.c
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * Copyright (c) 2001 William L. Pitts
- * Modifications (c) 2004 Felix Domke
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are freely
- * permitted provided that the above copyright notice and this
- * paragraph and the following disclaimer are duplicated in all
- * such forms.
- *
- * This software is provided "AS IS" and without any express or
- * implied warranties, including, without limitation, the implied
- * warranties of merchantability and fitness for a particular
- * purpose.
- */
-
-#include
-#include
-
-#include
-
-#include "elf_abi.h"
-
-/* ======================================================================
- * Determine if a valid ELF image exists at the given memory location.
- * First looks at the ELF header magic field, the makes sure that it is
- * executable and makes sure that it is for a PowerPC.
- * ====================================================================== */
-s32 valid_elf_image (void *addr)
-{
- Elf32_Ehdr *ehdr; /* Elf header structure pointer */
-
- ehdr = (Elf32_Ehdr *) addr;
-
- if (!IS_ELF (*ehdr))
- return 0;
-
- if (ehdr->e_type != ET_EXEC)
- return -1;
-
- if (ehdr->e_machine != EM_PPC)
- return -1;
-
- return 1;
-}
-
-
-/* ======================================================================
- * A very simple elf loader, assumes the image is valid, returns the
- * entry point address.
- * ====================================================================== */
-u32 load_elf_image (void *addr)
-{
- Elf32_Ehdr *ehdr;
- Elf32_Shdr *shdr;
- u8 *strtab = 0;
- u8 *image;
- int i;
-
- ehdr = (Elf32_Ehdr *) addr;
- /* Find the section header string table for output info */
- shdr = (Elf32_Shdr *) (addr + ehdr->e_shoff +
- (ehdr->e_shstrndx * sizeof (Elf32_Shdr)));
-
- if (shdr->sh_type == SHT_STRTAB)
- strtab = (u8 *) (addr + shdr->sh_offset);
-
- /* Load each appropriate section */
- for (i = 0; i < ehdr->e_shnum; ++i) {
- shdr = (Elf32_Shdr *) (addr + ehdr->e_shoff +
- (i * sizeof (Elf32_Shdr)));
-
- if (!(shdr->sh_flags & SHF_ALLOC)
- || shdr->sh_addr == 0 || shdr->sh_size == 0) {
- continue;
- }
-
- shdr->sh_addr &= 0x3FFFFFFF;
- shdr->sh_addr |= 0x80000000;
-
- if (strtab) {
- /*printf ("%sing section %s @ 0x%08x (0x%08x bytes)\n",
- (shdr->sh_type == SHT_NOBITS) ?
- "clear" : "load",
- &strtab[shdr->sh_name],
- (u32) shdr->sh_addr,
- (u32) shdr->sh_size);*/
- }
-
- if (shdr->sh_type == SHT_NOBITS) {
- memset ((void *) shdr->sh_addr, 0, shdr->sh_size);
- } else {
- image = (u8 *) addr + shdr->sh_offset;
- memcpy ((void *) shdr->sh_addr,
- (const void *) image,
- shdr->sh_size);
- }
- DCFlushRangeNoSync ((void *) shdr->sh_addr, shdr->sh_size);
- }
-
- return (ehdr->e_entry & 0x3FFFFFFF) | 0x80000000;
-}
-
diff --git a/source/elfloader.h b/source/elfloader.h
deleted file mode 100644
index d378fe45..00000000
--- a/source/elfloader.h
+++ /dev/null
@@ -1,18 +0,0 @@
-#ifndef _ELFLOADER_H_
-#define _ELFLOADER_H_
-
-#include
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
-s32 valid_elf_image (void *addr);
-u32 load_elf_image (void *addr);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/source/fatmounter.c b/source/fatmounter.c
deleted file mode 100644
index 0009cefa..00000000
--- a/source/fatmounter.c
+++ /dev/null
@@ -1,184 +0,0 @@
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-//these are the only stable and speed is good
-#define CACHE 8
-#define SECTORS 64
-
-enum BPB {
- BPB_jmpBoot = 0x00,
- BPB_OEMName = 0x03,
- // BIOS Parameter Block
- BPB_bytesPerSector = 0x0B,
- BPB_sectorsPerCluster = 0x0D,
- BPB_reservedSectors = 0x0E,
- BPB_numFATs = 0x10,
- BPB_rootEntries = 0x11,
- BPB_numSectorsSmall = 0x13,
- BPB_mediaDesc = 0x15,
- BPB_sectorsPerFAT = 0x16,
- BPB_sectorsPerTrk = 0x18,
- BPB_numHeads = 0x1A,
- BPB_numHiddenSectors = 0x1C,
- BPB_numSectors = 0x20,
- // Ext BIOS Parameter Block for FAT16
- BPB_FAT16_driveNumber = 0x24,
- BPB_FAT16_reserved1 = 0x25,
- BPB_FAT16_extBootSig = 0x26,
- BPB_FAT16_volumeID = 0x27,
- BPB_FAT16_volumeLabel = 0x2B,
- BPB_FAT16_fileSysType = 0x36,
- // Bootcode
- BPB_FAT16_bootCode = 0x3E,
- // FAT32 extended block
- BPB_FAT32_sectorsPerFAT32 = 0x24,
- BPB_FAT32_extFlags = 0x28,
- BPB_FAT32_fsVer = 0x2A,
- BPB_FAT32_rootClus = 0x2C,
- BPB_FAT32_fsInfo = 0x30,
- BPB_FAT32_bkBootSec = 0x32,
- // Ext BIOS Parameter Block for FAT32
- BPB_FAT32_driveNumber = 0x40,
- BPB_FAT32_reserved1 = 0x41,
- BPB_FAT32_extBootSig = 0x42,
- BPB_FAT32_volumeID = 0x43,
- BPB_FAT32_volumeLabel = 0x47,
- BPB_FAT32_fileSysType = 0x52,
- // Bootcode
- BPB_FAT32_bootCode = 0x5A,
- BPB_bootSig_55 = 0x1FE,
- BPB_bootSig_AA = 0x1FF
-};
-
-static const char FAT_SIG[3] = {'F', 'A', 'T'};
-
-#define BYTES_PER_READ 512
-
-static bool _FAT_partition_isFAT(const DISC_INTERFACE* disc, sec_t startSector)
-{
- uint8_t sectorBuffer[BYTES_PER_READ] = {0};
- if (!disc->readSectors(startSector, 1, sectorBuffer)) {
- return false;
- }
- // Make sure it is a valid BPB
- if ( (sectorBuffer[BPB_bootSig_55] != 0x55) || (sectorBuffer[BPB_bootSig_AA] != 0xAA)) {
- return false;
- }
-
- // Now verify that this is indeed a FAT partition
- if (memcmp(sectorBuffer + BPB_FAT16_fileSysType, FAT_SIG, sizeof(FAT_SIG)) &&
- memcmp(sectorBuffer + BPB_FAT32_fileSysType, FAT_SIG, sizeof(FAT_SIG)))
- {
- return false;
- }
-
- // check again for the last two cases to make sure that we really have a FAT filesystem here
- // and won't corrupt any data
- if(memcmp(sectorBuffer + BPB_FAT16_fileSysType, "FAT", 3) != 0 && memcmp(sectorBuffer + BPB_FAT32_fileSysType, "FAT32", 5) != 0)
- {
- return false;
- }
- return true;
-}
-static inline uint32_t u8array_to_u32 (const uint8_t* item, int offset) {
- return ( item[offset] | (item[offset + 1] << 8) | (item[offset + 2] << 16) | (item[offset + 3] << 24));
-}
-
-sec_t GetFATPartition(const DISC_INTERFACE* disc)
-{
- int i;
- uint8_t sectorBuffer[BYTES_PER_READ] = {0};
- sec_t startSector = 0;
-
- if(!disc->startup())
- return 0;
-
- // Read first sector of disc
- if (!disc->readSectors(0, 1, sectorBuffer))
- startSector = 0;
-
- // Make sure it is a valid MBR or boot sector
- if ( (sectorBuffer[BPB_bootSig_55] != 0x55) || (sectorBuffer[BPB_bootSig_AA] != 0xAA))
- startSector = 0;
-
- if (!memcmp(sectorBuffer + BPB_FAT16_fileSysType, FAT_SIG, sizeof(FAT_SIG)))
- {
- // Check if there is a FAT string, which indicates this is a boot sector
- startSector = 0;
- }
- else if (!memcmp(sectorBuffer + BPB_FAT32_fileSysType, FAT_SIG, sizeof(FAT_SIG)))
- {
- // Check for FAT32
- startSector = 0;
- }
- else
- {
- // This is an MBR
- // Find first valid partition from MBR
- // First check for an active partition
- for (i=0x1BE; (i < 0x1FE) && (sectorBuffer[i] != 0x80); i+= 0x10);
- // If it find an active partition, check for FAT-Partition
- if ( i != 0x1FE && !_FAT_partition_isFAT(disc, u8array_to_u32(sectorBuffer, 0x8 + i)) )
- i = 0x1FE;
-
- // If it didn't find an active partition, search for any valid partition
- if (i == 0x1FE)
- {
- for (i=0x1BE; i < 0x1FE; i+= 0x10)
- {
- if ( sectorBuffer[i+0x04] != 0x00 && _FAT_partition_isFAT(disc, u8array_to_u32(sectorBuffer, 0x8 + i)) )
- break;
- }
- }
- if (i != 0x1FE)
- startSector = u8array_to_u32(sectorBuffer, 0x8 + i);;
- }
- disc->shutdown();
- return startSector;
-}
-
-int USBDevice_Init()
-{
- //closing all open Files write back the cache and then shutdown em!
- fatUnmount("USB:/");
- //right now mounts first FAT-partition
- if (fatMount("USB", &__io_usbstorage, GetFATPartition(&__io_usbstorage), CACHE, SECTORS)) {
- //try first mount with libogc
- return 1;
- }
- return -1;
-}
-
-void USBDevice_deInit()
-{
- //closing all open Files write back the cache and then shutdown em!
- fatUnmount("USB:/");
-}
-
-int isSdInserted()
-{
- return __io_wiisd.isInserted();
-}
-
-int SDCard_Init()
-{
- //closing all open Files write back the cache and then shutdown em!
- fatUnmount("SD:/");
- //right now mounts first FAT-partition
- if (fatMount("SD", &__io_wiisd, GetFATPartition(&__io_wiisd), CACHE, SECTORS))
- return 1;
- return -1;
-}
-
-void SDCard_deInit()
-{
- //closing all open Files write back the cache and then shutdown em!
- fatUnmount("SD:/");
-}
diff --git a/source/filelist.h b/source/filelist.h
index e0af26c3..6bc5a69b 100644
--- a/source/filelist.h
+++ b/source/filelist.h
@@ -1,20 +1,20 @@
-/****************************************************************************
- * libwiigui Template
- * Tantric 2009
- *
- * imagelist.h
- * Contains a list of all of the files in the images, fonts, sounds folders
- ***************************************************************************/
-
-#ifndef _FILELIST_H_
-#define _FILELIST_H_
-
-#include
-
-extern const u8 background_png[];
-extern const u32 background_png_size;
-
-extern const u8 background169_png[];
-extern const u32 background169_png_size;
-
-#endif
+/****************************************************************************
+ * filelist.h
+ * Contains a list of all of the files in the images, fonts, sounds folders
+ ***************************************************************************/
+
+#ifndef _FILELIST_H_
+#define _FILELIST_H_
+
+#include
+
+extern const u8 app_booter_dol[];
+extern const u32 app_booter_dol_size;
+
+extern const u8 background_png[];
+extern const u32 background_png_size;
+
+extern const u8 background169_png[];
+extern const u32 background169_png_size;
+
+#endif
diff --git a/source/main.c b/source/main.c
new file mode 100644
index 00000000..f87f3131
--- /dev/null
+++ b/source/main.c
@@ -0,0 +1,205 @@
+ /****************************************************************************
+ * Copyright 2009 The Lemon Man and thanks to luccax, Wiipower, Aurelio and crediar
+ * Copyright 2010 Dimok
+ *
+ * Original forwarder source by
+ *
+ * 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
+#include
+#include
+
+#include "video.h"
+#include "background_image.h"
+#include "dolloader.h"
+#include "filelist.h"
+#include "devicemounter.h"
+#include "cfg.h"
+
+void __exception_setreload(int t);
+
+static FILE * open_file(const char * dev, char * filepath)
+{
+ sprintf(filepath, "%s:/apps/usbloader_gx/boot.dol", dev);
+
+ FILE * exeFile = fopen(filepath ,"rb");
+ if (exeFile == NULL)
+ {
+ sprintf(filepath, "%s:/apps/usbloader_gx/boot.dol", dev);
+ exeFile = fopen(filepath ,"rb");
+ }
+ if (exeFile == NULL)
+ {
+ sprintf(filepath, "%s:/apps/usbloadergx/boot.dol", dev);
+ exeFile = fopen(filepath ,"rb");
+ }
+
+ return exeFile;
+}
+
+static bool FindConfigPath(const char * device, char *cfgpath)
+{
+ bool result = false;
+ sprintf(cfgpath, "%s:/config/GXGlobal.cfg", device);
+ result = cfg_parsefile(cfgpath, &cfg_set);
+
+ if(!result)
+ {
+ sprintf(cfgpath, "%s:/apps/usbloader_gx/GXGlobal.cfg", device);
+ result = cfg_parsefile(cfgpath, &cfg_set);
+ }
+ if(!result)
+ {
+ sprintf(cfgpath, "%s:/apps/usbloadergx/GXGlobal.cfg", device);
+ result = cfg_parsefile(cfgpath, &cfg_set);
+ }
+
+ return result;
+}
+
+int main(int argc, char **argv)
+{
+ u32 cookie;
+ FILE *exeFile = NULL;
+ void * exeBuffer = (void *)EXECUTABLE_MEM_ADDR;
+ u32 exeSize = 0;
+ u32 exeEntryPointAddress = 0;
+ entrypoint exeEntryPoint;
+ __exception_setreload(0);
+
+ /* int videomod */
+ InitVideo();
+ /* get imagedata */
+ u8 * imgdata = GetImageData();
+ fadein(imgdata);
+
+ char filepath[200];
+
+ // try SD Card First
+ SDCard_Init();
+
+ if(FindConfigPath(DeviceName[SD], filepath))
+ {
+ strcat(filepath, "boot.dol");
+ exeFile = fopen(filepath, "rb");
+ }
+ if(!exeFile)
+ exeFile = open_file(DeviceName[SD], filepath);
+ // if app not found on SD Card try USB
+ if (exeFile == NULL)
+ {
+ USBDevice_Init();
+ int dev;
+ for(dev = USB1; dev < MAXDEVICES; ++dev)
+ {
+ if(FindConfigPath(DeviceName[dev], filepath))
+ {
+ strcat(filepath, "boot.dol");
+ exeFile = fopen(filepath, "rb");
+ }
+ if(!exeFile)
+ exeFile = open_file(DeviceName[dev], filepath);
+ }
+ }
+
+ // if nothing found exiting
+ if (exeFile == NULL)
+ {
+ fadeout(imgdata);
+ fclose (exeFile);
+ SDCard_deInit();
+ USBDevice_deInit();
+ StopGX();
+ free(imgdata);
+ SYS_ResetSystem(SYS_RETURNTOMENU, 0, 0);
+ }
+
+ fseek (exeFile, 0, SEEK_END);
+ exeSize = ftell(exeFile);
+ rewind (exeFile);
+
+ if(fread (exeBuffer, 1, exeSize, exeFile) != exeSize)
+ {
+ fadeout(imgdata);
+ fclose (exeFile);
+ SDCard_deInit();
+ USBDevice_deInit();
+ StopGX();
+ free(imgdata);
+ SYS_ResetSystem(SYS_RETURNTOMENU, 0, 0);
+ }
+ fclose (exeFile);
+
+ /* load entry point */
+ struct __argv args;
+ bzero(&args, sizeof(args));
+ args.argvMagic = ARGV_MAGIC;
+ args.length = strlen(filepath) + 2;
+ args.commandLine = (char*)malloc(args.length);
+ if (!args.commandLine) SYS_ResetSystem(SYS_RETURNTOMENU, 0, 0);
+ strcpy(args.commandLine, filepath);
+ args.commandLine[args.length - 1] = '\0';
+ args.argc = 1;
+ args.argv = &args.commandLine;
+ args.endARGV = args.argv + 1;
+
+ u8 * appboot_buff = (u8 *) malloc(app_booter_dol_size);
+ if(!appboot_buff)
+ {
+ fadeout(imgdata);
+ SDCard_deInit();
+ USBDevice_deInit();
+ StopGX();
+ free(imgdata);
+ SYS_ResetSystem(SYS_RETURNTOMENU, 0, 0);
+ }
+
+ memcpy(appboot_buff, app_booter_dol, app_booter_dol_size);
+
+ exeEntryPointAddress = load_dol_image(appboot_buff, &args);
+
+ if(appboot_buff)
+ free(appboot_buff);
+
+ fadeout(imgdata);
+ SDCard_deInit();
+ USBDevice_deInit();
+ StopGX();
+ free(imgdata);
+
+ //! Reset HBC stub so we can leave correct from usb loader
+ memset((char *) 0x80001804, 0, 8);
+
+ if (exeEntryPointAddress == 0)
+ SYS_ResetSystem(SYS_RETURNTOMENU, 0, 0);
+
+ exeEntryPoint = (entrypoint) exeEntryPointAddress;
+ /* cleaning up and load dol */
+ SYS_ResetSystem(SYS_SHUTDOWN, 0, 0);
+ _CPU_ISR_Disable (cookie);
+ __exception_closeall ();
+ exeEntryPoint ();
+ _CPU_ISR_Restore (cookie);
+ return 0;
+}
diff --git a/source/main.cpp b/source/main.cpp
deleted file mode 100644
index 7750d15c..00000000
--- a/source/main.cpp
+++ /dev/null
@@ -1,233 +0,0 @@
-/*
- * loadMii loader v0.3
- * main.c
- * http://code.google.com/p/loadmii
- *
- * Copyright 2009 The Lemon Man
- * Thanks to luccax, Wiipower, Aurelio and crediar
- * GX added by dimok (thanks to Tantric)
- * usbGecko powered by Nuke
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301, USA.
- */
-
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include "pngu/pngu.h"
-#include "video.h"
-#include "filelist.h"
-#include "dolloader.h"
-#include "elfloader.h"
-#include "cfg.h"
-#include "fatmounter.h"
-
-
-static PNGUPROP imgProp;
-static IMGCTX ctx;
-
-
-u8 * GetImageData(void) {
-
- u8 * data = NULL;
-
- int ret;
-
- if (CONF_GetAspectRatio()) {
- ctx = PNGU_SelectImageFromBuffer(background169_png);
- if (!ctx)
- return NULL;
- } else {
- ctx = PNGU_SelectImageFromBuffer(background_png);
- if (!ctx)
- return NULL;
- }
-
- ret = PNGU_GetImageProperties(ctx, &imgProp);
- if (ret != PNGU_OK)
- return NULL;
-
- int len = imgProp.imgWidth * imgProp.imgHeight * 4;
-
- if(len%32) len += (32-len%32);
- data = (u8 *)memalign (32, len);
- ret = PNGU_DecodeTo4x4RGBA8 (ctx, imgProp.imgWidth, imgProp.imgHeight, data, 255);
- DCFlushRange(data, len);
-
- PNGU_ReleaseImageContext(ctx);
-
- return data;
-}
-
-void Background_Show(int x, int y, int z, u8 * data, int angle, int scaleX, int scaleY, int alpha)
-{
- /* Draw image */
- Menu_DrawImg(x, y, z, imgProp.imgWidth, imgProp.imgHeight, data, angle, scaleX, scaleY, alpha);
-}
-
-
-int main(int argc, char **argv)
-{
- u32 cookie;
- FILE *exeFile = NULL;
- void *exeBuffer = (void *)EXECUTABLE_MEM_ADDR;
- int exeSize = 0;
- u32 exeEntryPointAddress = 0;
- entrypoint exeEntryPoint;
- /* int videomod */
- InitVideo();
- /* get imagedata */
- u8 * imgdata = GetImageData();
- /* fadein of image */
- for(int i = 0; i < 255; i = i+10)
- {
- if(i>255) i = 255;
- Background_Show(0, 0, 0, imgdata, 0, 1, 1, i);
- Menu_Render();
- }
- /* check devices */
- SDCard_Init();
- USBDevice_Init();
-
- char cfgpath[256];
- bool result = false;
-
- sprintf(cfgpath, "SD:/config/GXGlobal.cfg");
- result = cfg_parsefile(cfgpath, &cfg_set);
- if(!result) //no cfg-File on SD: try USB:
- {
- sprintf(cfgpath, "USB:/config/GXGlobal.cfg");
- result = cfg_parsefile(cfgpath, &cfg_set);
- }
-
- if(result)
- {
- sprintf(cfgpath, "%sboot.dol", update_path);
- /* Open dol File and check exist */
- exeFile = fopen (cfgpath, "rb");
- if (exeFile==NULL)
- {
- sprintf(cfgpath, "%sboot.elf", update_path);
- exeFile = fopen (cfgpath,"rb");
- }
- if (exeFile==NULL)
- result = false;
- else
- result = true;
- }
-
- if(!result) // non cfg-File loaded or update_path not set
- {
- /* Open dol File and check exist */
- sprintf(cfgpath, "SD:/apps/usbloader_gx/boot.dol");
- exeFile = fopen (cfgpath ,"rb");
- if (exeFile==NULL)
- {
- sprintf(cfgpath, "SD:/apps/usbloader_gx/boot.elf");
- exeFile = fopen (cfgpath ,"rb");
- }
- if (exeFile==NULL)
- {
- sprintf(cfgpath, "USB:/apps/usbloader_gx/boot.dol");
- exeFile = fopen (cfgpath ,"rb");
- }
- if (exeFile==NULL)
- {
- sprintf(cfgpath, "USB:/apps/usbloader_gx/boot.elf");
- exeFile = fopen (cfgpath ,"rb");
- }
- // if nothing found exiting
- if (exeFile==NULL) {
- printf("\n\n\t\tCan't find DOL File...\n");
- Menu_Render();
- sleep(3);
- fclose (exeFile);
- SDCard_deInit();
- USBDevice_deInit();
- StopGX();
- SYS_ResetSystem(SYS_RETURNTOMENU, 0, 0);
- }
- }
-
- fseek (exeFile, 0, SEEK_END);
- exeSize = ftell(exeFile);
- fseek (exeFile, 0, SEEK_SET);
-
- if(fread (exeBuffer, 1, exeSize, exeFile) != (unsigned int) exeSize)
- {
- printf("\n\n\t\tCan't open DOL File...\n");
- Menu_Render();
- fclose (exeFile);
- sleep(3);
- SDCard_deInit();
- USBDevice_deInit();
- StopGX();
- SYS_ResetSystem(SYS_RETURNTOMENU, 0, 0);
- }
- fclose (exeFile);
-
- /* load entry point */
- struct __argv args;
- bzero(&args, sizeof(args));
- args.argvMagic = ARGV_MAGIC;
- args.length = strlen(cfgpath) + 2;
- args.commandLine = (char*)malloc(args.length);
- if (!args.commandLine) SYS_ResetSystem(SYS_RETURNTOMENU, 0, 0);
- strcpy(args.commandLine, cfgpath);
- args.commandLine[args.length - 1] = '\0';
- args.argc = 1;
- args.argv = &args.commandLine;
- args.endARGV = args.argv + 1;
-
- int ret = valid_elf_image(exeBuffer);
- if (ret == 1)
- exeEntryPointAddress = load_elf_image(exeBuffer);
- else
- exeEntryPointAddress = load_dol_image(exeBuffer, &args);
-
- /* fadeout of image */
- for(int i = 255; i > 1; i = i-7)
- {
- if(i < 0) i = 0;
- Background_Show(0, 0, 0, imgdata, 0, 1, 1, i);
- Menu_Render();
- }
- SDCard_deInit();
- USBDevice_deInit();
- StopGX();
- if (exeEntryPointAddress == 0) {
- printf("EntryPointAddress failed...\n");
- Menu_Render();
- sleep(3);
- fclose (exeFile);
- SDCard_deInit();
- USBDevice_deInit();
- StopGX();
- SYS_ResetSystem(SYS_RETURNTOMENU, 0, 0);;
- }
- exeEntryPoint = (entrypoint) exeEntryPointAddress;
- /* cleaning up and load dol */
- SYS_ResetSystem(SYS_SHUTDOWN, 0, 0);
- _CPU_ISR_Disable (cookie);
- __exception_closeall ();
- exeEntryPoint ();
- _CPU_ISR_Restore (cookie);
- return 0;
-}
diff --git a/source/pngu.c b/source/pngu.c
new file mode 100644
index 00000000..16cefd91
--- /dev/null
+++ b/source/pngu.c
@@ -0,0 +1,1306 @@
+/********************************************************************************************
+
+PNGU Version : 0.2a
+
+Coder : frontier
+
+More info : http://frontier-dev.net
+
+********************************************************************************************/
+#include
+#include
+#include "pngu.h"
+#include "png.h"
+
+
+// Constants
+#define PNGU_SOURCE_BUFFER 1
+#define PNGU_SOURCE_DEVICE 2
+
+#define _SHIFTL(v, s, w) \
+ ((PNGU_u32) (((PNGU_u32)(v) & ((0x01 << (w)) - 1)) << (s)))
+#define _SHIFTR(v, s, w) \
+ ((PNGU_u32)(((PNGU_u32)(v) >> (s)) & ((0x01 << (w)) - 1)))
+
+// 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;
+}
+
+// Coded by Tantric for libwiigui (http://code.google.com/p/libwiigui)
+int PNGU_EncodeFromRGB (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer, PNGU_u32 stride)
+{
+ png_uint_32 rowbytes;
+ PNGU_u32 y;
+
+ // 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 >>2) + 1) <<2; // Add extra padding so each row starts in a 4 byte boundary
+
+ ctx->img_data = malloc(rowbytes * height);
+ memset(ctx->img_data, 0, 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);
+ memset(ctx->row_pointers, 0, 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;
+ }
+
+ for (y = 0; y < height; ++y)
+ {
+ ctx->row_pointers[y] = buffer + (y * rowbytes);
+ }
+
+ // 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 ctx->cursor;
+}
+
+// Coded by Tantric for libwiigui (http://code.google.com/p/libwiigui)
+int PNGU_EncodeFromGXTexture (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer, PNGU_u32 stride)
+{
+ int res;
+ PNGU_u32 x,y, tmpy1, tmpy2, tmpyWid, tmpxy;
+
+ unsigned char * ptr = (unsigned char*)buffer;
+ unsigned char * tmpbuffer = (unsigned char *)malloc(width*height*3);
+ memset(tmpbuffer, 0, width*height*3);
+ png_uint_32 offset;
+
+ for(y=0; y < height; y++)
+ {
+ tmpy1 = y * 640*3;
+ tmpy2 = y%4 << 2;
+ tmpyWid = (((y >> 2)<<4)*width);
+
+ for(x=0; x < width; x++)
+ {
+ offset = tmpyWid + ((x >> 2)<<6) + ((tmpy2+ x%4 ) << 1);
+ tmpxy = x * 3 + tmpy1;
+
+ tmpbuffer[tmpxy ] = ptr[offset+1]; // R
+ tmpbuffer[tmpxy+1] = ptr[offset+32]; // G
+ tmpbuffer[tmpxy+2] = ptr[offset+33]; // B
+ }
+ }
+
+ res = PNGU_EncodeFromRGB (ctx, width, height, tmpbuffer, stride);
+ free(tmpbuffer);
+ return res;
+}
+
+// Coded by Crayon for GRRLIB (http://code.google.com/p/grrlib)
+int PNGU_EncodeFromEFB (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, PNGU_u32 stride)
+{
+ int res;
+ PNGU_u32 x,y, tmpy, tmpxy, regval, val;
+ unsigned char * tmpbuffer = (unsigned char *)malloc(width*height*3);
+ memset(tmpbuffer, 0, width*height*3);
+
+ for(y=0; y < height; y++)
+ {
+ tmpy = y * 640*3;
+ for(x=0; x < width; x++)
+ {
+ regval = 0xc8000000|(_SHIFTL(x,2,10));
+ regval = (regval&~0x3FF000)|(_SHIFTL(y,12,10));
+ val = *(PNGU_u32*)regval;
+ tmpxy = x * 3 + tmpy;
+ tmpbuffer[tmpxy ] = _SHIFTR(val,16,8); // R
+ tmpbuffer[tmpxy+1] = _SHIFTR(val,8,8); // G
+ tmpbuffer[tmpxy+2] = val&0xff; // B
+ }
+ }
+
+ res = PNGU_EncodeFromRGB (ctx, width, height, tmpbuffer, stride);
+ free(tmpbuffer);
+ return res;
+}
+
+
+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/pngu.h b/source/pngu.h
new file mode 100644
index 00000000..e1e20b6d
--- /dev/null
+++ b/source/pngu.h
@@ -0,0 +1,175 @@
+/********************************************************************************************
+
+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);
+
+int PNGU_EncodeFromRGB (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer, PNGU_u32 stride);
+int PNGU_EncodeFromGXTexture (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer, PNGU_u32 stride);
+int PNGU_EncodeFromEFB (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, 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/video.cpp b/source/video.c
similarity index 87%
rename from source/video.cpp
rename to source/video.c
index 7dac715c..80ae461e 100644
--- a/source/video.cpp
+++ b/source/video.c
@@ -20,6 +20,8 @@ static int whichfb = 0; // Switch
static GXRModeObj *vmode; // Menu video mode
static unsigned char gp_fifo[DEFAULT_FIFO_SIZE] ATTRIBUTE_ALIGN (32);
static Mtx GXmodelView2D;
+int screenwidth = 640;
+int screenheight = 480;
/****************************************************************************
* StartGX
@@ -105,7 +107,7 @@ ResetVideo_Menu()
guMtxTransApply (GXmodelView2D, GXmodelView2D, 0.0F, 0.0F, -200.0F);
GX_LoadPosMtxImm(GXmodelView2D,GX_PNMTX0);
- guOrtho(p,0,479,0,639,0,300);
+ guOrtho(p,0,screenheight-1,0,screenwidth-1,0,300);
GX_LoadProjectionMtx(p, GX_ORTHOGRAPHIC);
GX_SetViewport(0,0,vmode->fbWidth,vmode->efbHeight,0,1);
@@ -126,15 +128,54 @@ InitVideo ()
VIDEO_Init();
vmode = VIDEO_GetPreferredMode(NULL); // get default video mode
+ bool pal = false;
+
+ if (vmode == &TVPal528IntDf)
+ pal = true;
+
+ if (CONF_GetAspectRatio() == CONF_ASPECT_16_9)
+ {
+ screenwidth = 720;
+ vmode->fbWidth = 640;
+ vmode->efbHeight = 456;
+ vmode->viWidth = 686;
+
+ if (pal)
+ {
+ vmode->xfbHeight = 542;
+ vmode->viHeight = 542;
+ }
+ else
+ {
+ vmode->xfbHeight = 456;
+ vmode->viHeight = 456;
+ }
+ }
+ else
+ {
+ if (pal)
+ vmode = &TVPal574IntDfScale;
+
+ vmode->viWidth = 672;
+ }
+
+ if (pal)
+ {
+ vmode->viXOrigin = (VI_MAX_WIDTH_PAL - vmode->viWidth) / 2;
+ vmode->viYOrigin = (VI_MAX_HEIGHT_PAL - vmode->viHeight) / 2;
+ }
+ else
+ {
+ vmode->viXOrigin = (VI_MAX_WIDTH_NTSC - vmode->viWidth) / 2;
+ vmode->viYOrigin = (VI_MAX_HEIGHT_NTSC - vmode->viHeight) / 2;
+ }
+
VIDEO_Configure (vmode);
// Allocate the video buffers
xfb[0] = (u32 *) MEM_K0_TO_K1 (SYS_AllocateFramebuffer (vmode));
xfb[1] = (u32 *) MEM_K0_TO_K1 (SYS_AllocateFramebuffer (vmode));
- // A console is always useful while debugging
- console_init (xfb[0], 20, 64, vmode->fbWidth, vmode->xfbHeight, vmode->fbWidth * 2);
-
// Clear framebuffers etc.
VIDEO_ClearFrameBuffer (vmode, xfb[0], COLOR_BLACK);
VIDEO_ClearFrameBuffer (vmode, xfb[1], COLOR_BLACK);
@@ -237,4 +278,4 @@ void Menu_DrawImg(f32 xpos, f32 ypos, f32 zpos, u16 width, u16 height, u8 data[]
GX_SetTevOp (GX_TEVSTAGE0, GX_PASSCLR);
GX_SetVtxDesc (GX_VA_TEX0, GX_NONE);
-}
+}