From 3e4ba63812ddf017c2f3a184a7e3604eaf2b68b4 Mon Sep 17 00:00:00 2001 From: Christopher Roy Bratusek Date: Sun, 14 Aug 2016 19:05:25 +0200 Subject: [PATCH] replace nand loader mod 1.1 with fix94's tiny vwii nand loader --- nand-loader | 1 + nand-loader/Makefile | 134 --- nand-loader/README | 29 - nand-loader/README.libogc | 1 - nand-loader/data/background | Bin 41921 -> 0 bytes nand-loader/data/error | Bin 5888 -> 0 bytes nand-loader/data/loading | Bin 5774 -> 0 bytes nand-loader/rvl.ld | 345 ------- nand-loader/source/asm.h | 93 -- nand-loader/source/config.c | 220 ----- nand-loader/source/config.h | 28 - nand-loader/source/gui.c | 87 -- nand-loader/source/gui.h | 10 - nand-loader/source/loader.c | 265 ------ nand-loader/source/loader.h | 8 - nand-loader/source/nandloader.c | 79 -- nand-loader/source/patches.c | 126 --- nand-loader/source/patches.h | 7 - nand-loader/source/pngu.c | 1561 ------------------------------- nand-loader/source/pngu.h | 181 ---- nand-loader/source/pngu_impl.h | 42 - nand-loader/source/stub.S | 118 --- nand-loader/source/sys.c | 48 - nand-loader/source/sys.h | 9 - nand-loader/source/title.c | 256 ----- nand-loader/source/title.h | 16 - nand-loader/source/tools.c | 252 ----- nand-loader/source/tools.h | 31 - nand-loader/source/utils.h | 15 - nand-loader/source/video.c | 147 --- nand-loader/source/video.h | 20 - nand-loader/source/wpad.c | 60 -- nand-loader/source/wpad.h | 12 - 33 files changed, 1 insertion(+), 4200 deletions(-) create mode 160000 nand-loader delete mode 100644 nand-loader/Makefile delete mode 100644 nand-loader/README delete mode 100644 nand-loader/README.libogc delete mode 100644 nand-loader/data/background delete mode 100644 nand-loader/data/error delete mode 100644 nand-loader/data/loading delete mode 100644 nand-loader/rvl.ld delete mode 100644 nand-loader/source/asm.h delete mode 100644 nand-loader/source/config.c delete mode 100644 nand-loader/source/config.h delete mode 100644 nand-loader/source/gui.c delete mode 100644 nand-loader/source/gui.h delete mode 100644 nand-loader/source/loader.c delete mode 100644 nand-loader/source/loader.h delete mode 100644 nand-loader/source/nandloader.c delete mode 100644 nand-loader/source/patches.c delete mode 100644 nand-loader/source/patches.h delete mode 100644 nand-loader/source/pngu.c delete mode 100644 nand-loader/source/pngu.h delete mode 100644 nand-loader/source/pngu_impl.h delete mode 100644 nand-loader/source/stub.S delete mode 100644 nand-loader/source/sys.c delete mode 100644 nand-loader/source/sys.h delete mode 100644 nand-loader/source/title.c delete mode 100644 nand-loader/source/title.h delete mode 100644 nand-loader/source/tools.c delete mode 100644 nand-loader/source/tools.h delete mode 100644 nand-loader/source/utils.h delete mode 100644 nand-loader/source/video.c delete mode 100644 nand-loader/source/video.h delete mode 100644 nand-loader/source/wpad.c delete mode 100644 nand-loader/source/wpad.h diff --git a/nand-loader b/nand-loader new file mode 160000 index 0000000..2eed1fa --- /dev/null +++ b/nand-loader @@ -0,0 +1 @@ +Subproject commit 2eed1fa0a5c88bda0c96d47cf31fcde88c6c344e diff --git a/nand-loader/Makefile b/nand-loader/Makefile deleted file mode 100644 index 652aaa6..0000000 --- a/nand-loader/Makefile +++ /dev/null @@ -1,134 +0,0 @@ -#--------------------------------------------------------------------------------- -# Clear the implicit built in rules -#--------------------------------------------------------------------------------- -.SUFFIXES: - -#--------------------------------------------------------------------------------- -ifeq ($(strip $(DEVKITPPC)),) -$(error "Please set DEVKITPPC in your environment. export DEVKITPPC=devkitPPC)") -endif - -include $(DEVKITPPC)/wii_rules - -#--------------------------------------------------------------------------------- -# TARGET is the name of the output -# BUILD is the directory where object files & intermediate files will be placed -# SOURCES is a list of directories containing source code -# INCLUDES is a list of directories containing extra header files -#--------------------------------------------------------------------------------- -TARGET := $(notdir $(CURDIR)) -BUILD := build -SOURCES := source -DATA := data -INCLUDES := - -#--------------------------------------------------------------------------------- -# options for code generation -#--------------------------------------------------------------------------------- - -CFLAGS = -O2 -mrvl -Wall $(MACHDEP) $(INCLUDE) -CXXFLAGS = $(CFLAGS) - -LDFLAGS = $(MACHDEP) -Wl,-Map,$(notdir $@).map - -#--------------------------------------------------------------------------------- -# any extra libraries we wish to link with the project -#--------------------------------------------------------------------------------- -LIBS := -lpng -lmodplay -lasnd -lwiiuse -lbte -logc -lm -lz - -#--------------------------------------------------------------------------------- -# list of directories containing libraries, this must be the top level containing -# include and lib -#--------------------------------------------------------------------------------- -LIBDIRS := - - -#--------------------------------------------------------------------------------- -# no real need to edit anything past this point unless you need to add additional -# rules for different file extensions -#--------------------------------------------------------------------------------- -ifneq ($(BUILD),$(notdir $(CURDIR))) -#--------------------------------------------------------------------------------- - -export TOPDIR := $(CURDIR) - -export OUTPUT := $(CURDIR)/$(TARGET) - -export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \ - $(foreach dir,$(DATA),$(CURDIR)/$(dir)) - -export DEPSDIR := $(CURDIR)/$(BUILD) - -#--------------------------------------------------------------------------------- -# automatically build a list of object files for our project -#--------------------------------------------------------------------------------- -CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) -CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) -sFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) -SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.S))) -BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) - -#--------------------------------------------------------------------------------- -# use CXX for linking C++ projects, CC for standard C -#--------------------------------------------------------------------------------- -ifeq ($(strip $(CPPFILES)),) - export LD := $(CC) -else - export LD := $(CXX) -endif - -export OFILES := $(addsuffix .o,$(BINFILES)) \ - $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) \ - $(sFILES:.s=.o) $(SFILES:.S=.o) - -#--------------------------------------------------------------------------------- -# build a list of include paths -#--------------------------------------------------------------------------------- -export INCLUDE := $(foreach dir,$(INCLUDES), -iquote $(CURDIR)/$(dir)) \ - $(foreach dir,$(LIBDIRS),-I$(dir)/include) \ - -I$(CURDIR)/$(BUILD) \ - -I$(LIBOGC_INC) - -#--------------------------------------------------------------------------------- -# build a list of library paths -#--------------------------------------------------------------------------------- -export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) \ - -L$(LIBOGC_LIB) - -export OUTPUT := $(CURDIR)/$(TARGET) -.PHONY: $(BUILD) clean - -#--------------------------------------------------------------------------------- -$(BUILD): - @[ -d $@ ] || mkdir -p $@ - @make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile - -#--------------------------------------------------------------------------------- -clean: - @echo clean ... - @rm -fr $(BUILD) $(OUTPUT).elf $(OUTPUT).bin - -#--------------------------------------------------------------------------------- -else - -DEPENDS := $(OFILES:.o=.d) - -#--------------------------------------------------------------------------------- -# main targets -#--------------------------------------------------------------------------------- -$(OUTPUT).bin: $(OUTPUT).elf -$(OUTPUT).elf: $(OFILES) - -#--------------------------------------------------------------------------------- -%.bin: - $(OBJCOPY) -O binary $^ $@ - -%.elf: - @echo linking ... $(notdir $@) - $(LD) -T ../rvl.ld $^ $(LDFLAGS) $(LIBPATHS) $(LIBS) -o $@ - --include $(DEPENDS) - -#--------------------------------------------------------------------------------- -endif -#--------------------------------------------------------------------------------- diff --git a/nand-loader/README b/nand-loader/README deleted file mode 100644 index 9dbb6dc..0000000 --- a/nand-loader/README +++ /dev/null @@ -1,29 +0,0 @@ -+---------------------------------+ -| [+] Custom NAND Loader v1.0 | -| developed by Waninkoko | -+---------------------------------+ -| wwww.teknoconsolas.es | -+---------------------------------+ - - -[ DESCRIPTION ]: - -- This is a custom NAND Loader for Wii channels. It is 100% legal and works - with homebrew and commercial channels. - - Also, it allows to configure the loading options for each channel. - - -[ NOTES ]; - -- If RESET button is held while booting the channel it will access - the configuration menu. - - -[ KUDOS ]: - -- Team Twiizers and devkitPRO devs. -- crediar. -- WiiGator. -- kwiirk. -- All the betatesters. diff --git a/nand-loader/README.libogc b/nand-loader/README.libogc deleted file mode 100644 index a2dfc2d..0000000 --- a/nand-loader/README.libogc +++ /dev/null @@ -1 +0,0 @@ -properly building this NAND-Loader does (still) require libogc from 2009 diff --git a/nand-loader/data/background b/nand-loader/data/background deleted file mode 100644 index 7714c7376debe38eb027b8e9ebe9e0891b888e34..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 41921 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 diff --git a/nand-loader/data/error b/nand-loader/data/error deleted file mode 100644 index 15c1075635ae289bc882411d998613b0dcfe35b8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5888 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 A_W%F@ diff --git a/nand-loader/data/loading b/nand-loader/data/loading deleted file mode 100644 index 5410cc77e173b30aff960f0367c73daf2dc39d48..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5774 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 diff --git a/nand-loader/rvl.ld b/nand-loader/rvl.ld deleted file mode 100644 index 9df04f4..0000000 --- a/nand-loader/rvl.ld +++ /dev/null @@ -1,345 +0,0 @@ -/* - * Linkscript for Wii - */ - -OUTPUT_FORMAT("elf32-powerpc", "elf32-powerpc", "elf32-powerpc"); -OUTPUT_ARCH(powerpc:common); -EXTERN(_stub_start); -ENTRY(_stub_start); - -SECTIONS -{ - /* DOL header (from TITANIK's GC docs) */ - /* default base address */ - off = 0; - - .header : AT(off) - { - /* 0000-001B Text[0..6] sections File Positions */ - LONG(stub_file_start); - LONG(text_file_start); - LONG(0); - LONG(0); - LONG(0); - LONG(0); - LONG(0); - - /* 001C-0047 Data[0..10] sections File Positions */ - LONG(data_file_start); - LONG(0); - LONG(0); - LONG(0); - LONG(0); - LONG(0); - LONG(0); - LONG(0); - LONG(0); - LONG(0); - LONG(0); - - /* 0048-0063 Text[0..6] sections Mem Address */ - LONG(stub_mem_start); - LONG(text_mem_start); - LONG(0); - LONG(0); - LONG(0); - LONG(0); - LONG(0); - - /* 0064-008F Data[0..10] sections Mem Address */ - LONG(data_mem_start); - LONG(0); - LONG(0); - LONG(0); - LONG(0); - LONG(0); - LONG(0); - LONG(0); - LONG(0); - LONG(0); - LONG(0); - - /* 0090-00AB Text[0..6] sections Sizes */ - LONG(stub_mem_size); - LONG(text_mem_size); - LONG(0); - LONG(0); - LONG(0); - LONG(0); - LONG(0); - - /* 00AC-00D7 Data[0..10] sections Sizes */ - LONG(data_mem_size); - LONG(0); - LONG(0); - LONG(0); - LONG(0); - LONG(0); - LONG(0); - LONG(0); - LONG(0); - LONG(0); - LONG(0); - - /* 00D8 BSS Mem address - 00DC BSS Size */ - LONG(bss_mem_start); - LONG(bss_mem_size); - - /* 00E0 Entry Point */ - LONG(ABSOLUTE(_stub_start)); - } - - . = 0x00003400; - off += 0x100; - - stub_mem_start = .; - stub_file_start = off; - - .stub : AT(off) - { - KEEP (*(.stub)) - . = 0x400; - } = 0 - - stub_mem_size = . - stub_mem_start; - off += stub_mem_size; - - . = 0x81330000; - - text_mem_start = .; - text_file_start = off; - - .init : AT(off) - { - KEEP (*crt0.o(*.init)) - KEEP (*(.init)) - } - - .text : - { - *(.text) - *(.text.*) - /* .gnu.warning sections are handled specially by elf32.em. */ - *(.gnu.warning) - *(.gnu.linkonce.t.*) - . = ALIGN(32); /* REQUIRED. LD is flaky without it. */ - } - - .fini : - { - KEEP (*(.fini)) - . = ALIGN(32); /* REQUIRED. LD is flaky without it. */ - } - - PROVIDE (__etext = .); - PROVIDE (_etext = .); - PROVIDE (etext = .); - - text_mem_size = . - text_mem_start; - off += text_mem_size; - - data_mem_start = .; - data_file_start = off; - - .data : AT(off) - { - *(.rodata) *(.rodata.*) *(.gnu.linkonce.r.*) - *(.rodata1) - *(.sdata2) *(.sdata2.*) *(.gnu.linkonce.s2.*) - *(.sbss2) *(.sbss2.*) *(.gnu.linkonce.sb2.*) - PROVIDE (__preinit_array_start = .); - *(.preinit_array) - PROVIDE (__preinit_array_end = .); - PROVIDE (__init_array_start = .); - *(.init_array) - PROVIDE (__init_array_end = .); - PROVIDE (__fini_array_start = .); - *(.fini_array) - PROVIDE (__fini_array_end = .); - - *(.data) - *(.data.*) - *(.gnu.linkonce.d.*) - SORT(CONSTRUCTORS) - . = ALIGN(32); /* REQUIRED. LD is flaky without it. */ - } - - .data1 : { *(.data1) } - .tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) } - .tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) } - .gcc_except_table : { *(.gcc_except_table) } - .fixup : { *(.fixup) } - .got1 : { *(.got1) } - .got2 : { *(.got2) } - .dynamic : { *(.dynamic) } - - .ctors : - { - /* gcc uses crtbegin.o to find the start of - the constructors, so we make sure it is - first. Because this is a wildcard, it - doesn't matter if the user does not - actually link against crtbegin.o; the - linker won't look for a file to match a - wildcard. The wildcard also means that it - doesn't matter which directory crtbegin.o - is in. */ - - KEEP (*crtbegin.o(.ctors)) - - /* We don't want to include the .ctor section from - from the crtend.o file until after the sorted ctors. - The .ctor section from the crtend file contains the - end of ctors marker and it must be last */ - - KEEP (*(EXCLUDE_FILE (*crtend.o ) .ctors)) - KEEP (*(SORT(.ctors.*))) - KEEP (*(.ctors)) - . = ALIGN(32); /* REQUIRED. LD is flaky without it. */ - } - - .dtors : - { - KEEP (*crtbegin.o(.dtors)) - KEEP (*(EXCLUDE_FILE (*crtend.o ) .dtors)) - KEEP (*(SORT(.dtors.*))) - KEEP (*(.dtors)) - . = ALIGN(32); /* REQUIRED. LD is flaky without it. */ - } - - .jcr : { KEEP (*(.jcr)) } - .got : { *(.got.plt) *(.got) } - - - /* We want the small data sections together, so single-instruction offsets - can access them all, and initialized data all before uninitialized, so - we can shorten the on-disk segment size. */ - - .sdata : - { - *(.sdata) - *(.sdata.*) - *(.gnu.linkonce.s.*) - . = ALIGN(32); /* REQUIRED. LD is flaky without it. */ - } - - _edata = .; - PROVIDE (edata = .); - - data_mem_size = . - data_mem_start; - off += data_mem_size; - - bss_mem_start = .; - bss_file_start = off; - - .sbss : AT(off) - { - __sbss_start = .; - PROVIDE (__sbss_start = .); - PROVIDE (___sbss_start = .); - *(.dynsbss) - *(.sbss) - *(.sbss.*) - *(.gnu.linkonce.sb.*) - *(.scommon) - PROVIDE (__sbss_end = .); - PROVIDE (___sbss_end = .); - . = ALIGN(32); /* REQUIRED. LD is flaky without it. */ - __sbss_end = .; - } - - .bss : - { - __bss_start = .; - PROVIDE (__bss_start = .); - *(.dynbss) - *(.bss) - *(.bss.*) - *(.gnu.linkonce.b.*) - *(COMMON) - /* Align here to ensure that the .bss section occupies space up to - _end. Align after .bss to ensure correct alignment even if the - .bss section disappears because there are no input sections. */ - - . = ALIGN(32); - - PROVIDE (__bss_end = .); - __bss_end = .; - } - - bss_mem_size = . - bss_mem_start; - - _end = .; - PROVIDE(end = .); - /* Stabs debugging sections. */ - .stab 0 : { *(.stab) } - .stabstr 0 : { *(.stabstr) } - .stab.excl 0 : { *(.stab.excl) } - .stab.exclstr 0 : { *(.stab.exclstr) } - .stab.index 0 : { *(.stab.index) } - .stab.indexstr 0 : { *(.stab.indexstr) } - .comment 0 : { *(.comment) } - /* DWARF debug sections. - Symbols in the DWARF debugging sections are relative to the beginning - of the section so we begin them at 0. */ - /* DWARF 1 */ - .debug 0 : { *(.debug) } - .line 0 : { *(.line) } - /* GNU DWARF 1 extensions */ - .debug_srcinfo 0 : { *(.debug_srcinfo) } - .debug_sfnames 0 : { *(.debug_sfnames) } - /* DWARF 1.1 and DWARF 2 */ - .debug_aranges 0 : { *(.debug_aranges) } - .debug_pubnames 0 : { *(.debug_pubnames) } - /* DWARF 2 */ - .debug_info 0 : { *(.debug_info) } - .debug_abbrev 0 : { *(.debug_abbrev) } - .debug_line 0 : { *(.debug_line) } - .debug_frame 0 : { *(.debug_frame) } - .debug_str 0 : { *(.debug_str) } - .debug_loc 0 : { *(.debug_loc) } - .debug_macinfo 0 : { *(.debug_macinfo) } - /* SGI/MIPS DWARF 2 extensions */ - .debug_weaknames 0 : { *(.debug_weaknames) } - .debug_funcnames 0 : { *(.debug_funcnames) } - .debug_typenames 0 : { *(.debug_typenames) } - .debug_varnames 0 : { *(.debug_varnames) } - /* These must appear regardless of . */ -} - -__isIPL = 0; -__stack_addr = (__bss_start + SIZEOF(.bss) + 0x20000 + 7) & (-8); -__stack_end = (__bss_start + SIZEOF(.bss)); -__intrstack_addr = (__stack_addr + 0x4000); -__intrstack_end = (__stack_addr); -__Arena1Lo = (__intrstack_addr + 31) & (-32); -__Arena1Hi = (0x816ffff0); -__Arena2Lo = (0x90002000); -__Arena2Hi = (0x933E0000); - -__gxregs = (__Arena1Hi + 31) & (-32); -__ipcbufferLo = (0x933e0000); -__ipcbufferHi = (0x93400000); - -/* for backward compatibility with old crt0 */ -PROVIDE (__stack = (0x816ffff0)); - -PROVIDE(__isIPL = __isIPL); -PROVIDE(__text_start = text_mem_start); -PROVIDE(__text_fstart = text_file_start); -PROVIDE(__data_start = data_mem_start); -PROVIDE(__data_fstart = data_file_start); -PROVIDE(__bss_start = bss_mem_start); -PROVIDE(__bss_fstart = bss_file_start); -PROVIDE(__stack_addr = __stack_addr); -PROVIDE(__stack_end = __stack_end); -PROVIDE(__intrstack_addr = __intrstack_addr); -PROVIDE(__intrstack_end = __intrstack_end); -PROVIDE(__Arena1Lo = __Arena1Lo); -PROVIDE(__Arena1Hi = __Arena1Hi); -PROVIDE(__Arena2Lo = __Arena2Lo); -PROVIDE(__Arena2Hi = __Arena2Hi); -PROVIDE(__ipcbufferLo = __ipcbufferLo); -PROVIDE(__ipcbufferHi = __ipcbufferHi); -PROVIDE(__gxregs = __gxregs); diff --git a/nand-loader/source/asm.h b/nand-loader/source/asm.h deleted file mode 100644 index 610d9c4..0000000 --- a/nand-loader/source/asm.h +++ /dev/null @@ -1,93 +0,0 @@ -#ifndef _ASM_H_ -#define _ASM_H_ - -/* Registers */ -#define r0 0 -#define r1 1 -#define r2 2 -#define r3 3 -#define r4 4 -#define r5 5 -#define r6 6 -#define r7 7 -#define r8 8 -#define r9 9 -#define r10 10 -#define r11 11 -#define r12 12 -#define r13 13 -#define r14 14 -#define r15 15 -#define r16 16 -#define r17 17 -#define r18 18 -#define r19 19 -#define r20 20 -#define r21 21 -#define r22 22 -#define r23 23 -#define r24 24 -#define r25 25 -#define r26 26 -#define r27 27 -#define r28 28 -#define r29 29 -#define r30 30 -#define r31 31 - - -/* BATs */ -#define IBAT0U 528 -#define IBAT0L 529 -#define IBAT1U 530 -#define IBAT1L 531 -#define IBAT2U 532 -#define IBAT2L 533 -#define IBAT3U 534 -#define IBAT3L 535 -#define IBAT4U 560 -#define IBAT4L 561 -#define IBAT5U 562 -#define IBAT5L 563 -#define IBAT6U 564 -#define IBAT6L 565 -#define IBAT7U 566 -#define IBAT7L 567 - -#define DBAT0U 536 -#define DBAT0L 537 -#define DBAT1U 538 -#define DBAT1L 539 -#define DBAT2U 540 -#define DBAT2L 541 -#define DBAT3U 542 -#define DBAT3L 543 -#define DBAT4U 568 -#define DBAT4L 569 -#define DBAT5U 570 -#define DBAT5L 571 -#define DBAT6U 572 -#define DBAT6L 573 -#define DBAT7U 574 -#define DBAT7L 575 - - -/* HIDs */ -#define HID0 1008 -#define HID1 1009 -#define HID2 920 -#define HID4 1011 - - -/* MSRs */ -#define MSR_RI 0x00000002 -#define MSR_DR 0x00000010 -#define MSR_IR 0x00000020 -#define MSR_IP 0x00000040 -#define MSR_SE 0x00000400 -#define MSR_ME 0x00001000 -#define MSR_FP 0x00002000 -#define MSR_POW 0x00004000 -#define MSR_EE 0x00008000 - -#endif diff --git a/nand-loader/source/config.c b/nand-loader/source/config.c deleted file mode 100644 index a2497ce..0000000 --- a/nand-loader/source/config.c +++ /dev/null @@ -1,220 +0,0 @@ -#include -#include -#include -#include - -#include "config.h" -#include "title.h" -#include "video.h" -#include "wpad.h" - -/* 'Menu' structure */ -struct menu { - /* Entry name */ - char *name; - - /* Entry value */ - bool *value; -}; - - -/* NANDLoader configuration */ -struct config loaderCfg ATTRIBUTE_ALIGN(32) = { 0 }; - -/* Config entries */ -struct menu entryList[] = { - { "Force PAL50", &loaderCfg.forcePal50 }, - { "Force PAL60", &loaderCfg.forcePal60 }, - { "Force NTSC", &loaderCfg.forceNtsc }, - { "Force HDTV", &loaderCfg.forceHdtv }, - { "Patch Video Mode", &loaderCfg.patchVmode }, - { "Show Splash", &loaderCfg.showSplash }, -}; - -/* Macros */ -#define NB_ENTRIES (sizeof(entryList) / sizeof(struct menu)) - - -void __Config_Credits(void) -{ - /* Clear console */ - Con_Clear(); - - /* Write credits */ - printf("[+] Custom NAND Loader for Wii\n\n"); - - printf(" developed by Waninkoko\n"); - printf(" www.teknoconsolas.es\n\n\n"); - - printf("[+] Thanks to all my betatesters:\n"); - printf(" - linkinworm\n"); - printf(" - hectorscasa\n"); - printf(" - SoraK05\n"); - printf(" - And the rest... ;-)\n\n"); - - printf("[+] Also kudos to:\n\n"); - printf(" - Team Twiizers\n"); - printf(" - SoftMii Team\n"); - printf(" - crediar\n"); - printf(" - WiiGator and kwiirk\n"); - printf(" - Teknoconsolas.es community\n\n"); - - printf("\n"); - printf("[+] Press any button to continue...\n"); - - /* Wait for any button */ - Wpad_WaitButtons(); -} - -s32 __Config_GetFilePath(char *outbuf) -{ - static char nandpath[ISFS_MAXPATH] ATTRIBUTE_ALIGN(32); - - u64 tid; - s32 ret; - - /* Get title ID */ - ret = ES_GetTitleID(&tid); - if (ret < 0) - return ret; - - /* Get data directory */ - ret = ES_GetDataDir(tid, nandpath); - if (ret < 0) - return ret; - - /* Generate filepath */ - sprintf(outbuf, "%s/nand.cfg", nandpath); - - return 0; -} - - -s32 Config_Read(void) -{ - char filepath[ISFS_MAXPATH]; - s32 fd, ret; - - /* Get config filepath */ - ret = __Config_GetFilePath(filepath); - if (ret < 0) - return ret; - - /* Open config file */ - fd = IOS_Open(filepath, ISFS_OPEN_READ); - if (fd < 0) - return fd; - - /* Read config */ - ret = IOS_Read(fd, &loaderCfg, sizeof(loaderCfg)); - - /* Close config file */ - IOS_Close(fd); - - return ret; -} - -s32 Config_Write(void) -{ - char filepath[ISFS_MAXPATH]; - s32 fd, ret; - - /* Get config filepath */ - ret = __Config_GetFilePath(filepath); - if (ret < 0) - return ret; - - /* Create config file */ - ISFS_CreateFile(filepath, 0, ISFS_OPEN_RW, ISFS_OPEN_READ, ISFS_OPEN_READ); - - /* Open config file */ - fd = IOS_Open(filepath, ISFS_OPEN_WRITE); - if (fd < 0) - return fd; - - /* Write config */ - ret = IOS_Write(fd, &loaderCfg, sizeof(loaderCfg)); - - /* Close config file */ - IOS_Close(fd); - - return ret; -} - -void Config_Menu(void) -{ - u32 var = 0; - s32 selected = 0; - - for (;;) { - u32 cnt; - - /* Clear console */ - Con_Clear(); - - for (cnt = 0; cnt < NB_ENTRIES; cnt++) { - struct menu *entry = &entryList[cnt]; - - /* Print entry */ - printf("\t%2s %-16s : %s\n", (selected == cnt) ? ">>" : " ", entry->name, (*entry->value) ? "Yes" : "No"); - } - - printf("\n"); - - printf("[+] Press UP/DOWN to move cursor.\n"); - printf(" Press LEFT/RIGHT to toggle option.\n\n"); - - printf(" Press A button to save and continue...\n"); - - u32 buttons = Wpad_WaitButtons(); - - /* UP/DOWN buttons */ - if (buttons & WPAD_BUTTON_UP) { - if ((--selected) <= -1) - selected = (NB_ENTRIES - 1); - } - if (buttons & WPAD_BUTTON_DOWN) { - if ((++selected) >= NB_ENTRIES) - selected = 0; - } - - /* LEFT/RIGHT buttons */ - if (buttons & (WPAD_BUTTON_LEFT | WPAD_BUTTON_RIGHT)) - *entryList[selected].value ^= 1; - - /* A button */ - if (buttons & WPAD_BUTTON_A) - break; - - - /* Easter Egg */ - if (buttons & WPAD_BUTTON_1) { - switch (var) { - case 0: - var++; - break; - case 3: - /* Show credits screen */ - __Config_Credits(); - - var = 0; - break; - default: - var = 0; - } - } - if (buttons & WPAD_BUTTON_2) { - switch (var) { - case 1: - case 2: - var++; - break; - default: - var = 0; - } - } - } - - /* Write configuration */ - Config_Write(); -} diff --git a/nand-loader/source/config.h b/nand-loader/source/config.h deleted file mode 100644 index 35d4be9..0000000 --- a/nand-loader/source/config.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef _CONFIG_H_ -#define _CONFIG_H_ - -/* 'Config' structure */ -struct config { - /* Video modes */ - bool forcePal50; - bool forcePal60; - bool forceNtsc; - bool forceHdtv; - - /* Video mode patching */ - bool patchVmode; - - /* Splash screen */ - bool showSplash; -}; - -/* NANDLoader configuration */ -extern struct config loaderCfg; - -/* Prototypes */ -s32 Config_Read(void); -s32 Config_Write(void); -void Config_Menu(void); - -#endif - diff --git a/nand-loader/source/gui.c b/nand-loader/source/gui.c deleted file mode 100644 index e811542..0000000 --- a/nand-loader/source/gui.c +++ /dev/null @@ -1,87 +0,0 @@ -#include -#include -#include - -#include "video.h" - -/* Constants */ -#define CONSOLE_XCOORD 20 -#define CONSOLE_YCOORD 100 -#define CONSOLE_WIDTH 350 -#define CONSOLE_HEIGHT 300 - -#define MSG_XCOORD 180 -#define MSG_YCOORD 190 - - -s32 __Gui_DrawPng(void *img, u32 x, u32 y) -{ - IMGCTX ctx = NULL; - PNGUPROP imgProp; - - s32 ret; - - /* Select PNG data */ - ctx = PNGU_SelectImageFromBuffer(img); - if (!ctx) { - ret = -1; - goto out; - } - - /* Get image properties */ - ret = PNGU_GetImageProperties(ctx, &imgProp); - if (ret != PNGU_OK) { - ret = -1; - goto out; - } - - /* Draw image */ - Video_DrawPng(ctx, imgProp, x, y); - - /* Success */ - ret = 0; - -out: - /* Free memory */ - if (ctx) - PNGU_ReleaseImageContext(ctx); - - return ret; -} - - -void Gui_InitConsole(void) -{ - /* Initialize console */ - Con_Init(CONSOLE_XCOORD, CONSOLE_YCOORD, CONSOLE_WIDTH, CONSOLE_HEIGHT); -} - -void Gui_DrawBackground(void) -{ - extern char bgData[]; - - /* Draw background */ - __Gui_DrawPng(bgData, 0, 0); -} - -void Gui_DrawLoading(void) -{ - extern char loadingImg[]; - - /* Clear screen */ - Video_Clear(COLOR_BLACK); - - /* Draw loading image */ - __Gui_DrawPng(loadingImg, MSG_XCOORD, MSG_YCOORD); -} - -void Gui_DrawError(void) -{ - extern char errorImg[]; - - /* Clear screen */ - Video_Clear(COLOR_BLACK); - - /* Draw error image */ - __Gui_DrawPng(errorImg, MSG_XCOORD, MSG_YCOORD); -} diff --git a/nand-loader/source/gui.h b/nand-loader/source/gui.h deleted file mode 100644 index f4ea218..0000000 --- a/nand-loader/source/gui.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef _GUI_H_ -#define _GUI_H_ - -/* Prototypes */ -void Gui_InitConsole(void); -void Gui_DrawBackground(void); -void Gui_DrawLoading(void); -void Gui_DrawError(void); - -#endif diff --git a/nand-loader/source/loader.c b/nand-loader/source/loader.c deleted file mode 100644 index b432e94..0000000 --- a/nand-loader/source/loader.c +++ /dev/null @@ -1,265 +0,0 @@ -#include -#include -#include -#include - -#include "config.h" -#include "patches.h" -#include "video.h" -#include "wpad.h" -#include "tools.h" - -/* DOL header structure */ -typedef struct { - u32 textoff[7]; - u32 dataoff[11]; - - u8 *textmem[7]; - u8 *datamem[11]; - - u32 textsize[7]; - u32 datasize[11]; - - u8 *bssmem; - u32 bsssize; - - u32 entry; - - u32 unused[7]; -} dolheader; - -/* Entry pointer */ -typedef void (*dolentry)(void); - -/* Constants */ -#define DOL_INDEX 1 - - -void __Loader_SetLowMem(void) -{ - /* Setup low memory */ - *(vu32*)0x800000F8 = 0x0E7BE2C0; - *(vu32*)0x800000FC = 0x2B73A840; - - /* Flush cache */ - DCFlushRange((void *)(0x800000F8), 0xFF); - - // Set the clock - settime(secs_to_ticks(time(NULL) - 946684800)); - - // Remove 002 error - *(u16 *)0x80003140 = 0x0038; - *(u16 *)0x80003142 = 0xffff; - *(u16 *)0x80003188 = 0x0038; - *(u16 *)0x8000318A = 0xffff; - - DCFlushRange((void*)0x80003140, 4); - DCFlushRange((void*)0x80003188, 4); -} - -void __Loader_SetVMode(u64 tid) -{ - GXRModeObj *vmode_ptr = NULL; - u32 vmode_reg; - - u32 progressive, tvmode; - - /* Get video mode configuration */ - progressive = (CONF_GetProgressiveScan() > 0) && VIDEO_HaveComponentCable(); - tvmode = CONF_GetVideo(); - - /* Select video mode */ - switch(tid & 0xFF) { - /* PAL */ - case 'P': - vmode_reg = (CONF_GetEuRGB60() > 0) ? 5 : 1; - - if (tvmode != CONF_VIDEO_PAL) { - vmode_reg = 5; - vmode_ptr = &TVNtsc480IntDf; - } - - break; - - /* NTSC or unknown */ - case 'E': - case 'J': - vmode_reg = 0; - - if (tvmode != CONF_VIDEO_NTSC) - vmode_ptr = &TVEurgb60Hz480IntDf; - - break; - - default: - vmode_reg = 0; - } - - /* Override video mode */ - if (loaderCfg.forcePal50) { - vmode_reg = 1; - vmode_ptr = &TVPal528IntDf; - } - - if (loaderCfg.forcePal60) { - vmode_reg = 5; - vmode_ptr = &TVEurgb60Hz480IntDf; - } - - if (loaderCfg.forceNtsc) { - vmode_reg = 0; - vmode_ptr = &TVNtsc480IntDf; - } - - if (loaderCfg.forceHdtv) { - vmode_reg = 0; - vmode_ptr = &TVNtsc480Prog; - } - - - /* Set video mode register */ - *(vu32 *)0x800000CC = vmode_reg; - - /* Set video mode */ - if (vmode_ptr) { - /* If progressive available, use it */ - if (progressive) - vmode_ptr = &TVNtsc480Prog; - - Video_Configure(vmode_ptr); - Video_Clear(COLOR_BLACK); - } - - // Anti-green screen fix - VIDEO_SetBlack(TRUE); - VIDEO_Flush(); - VIDEO_WaitVSync(); -} - - -void __Loader_PatchDol(u8 *buffer, u32 len) -{ - struct config *cfg = &loaderCfg; - - /* Video mode patching */ - if (cfg->patchVmode) - Patch_VideoMode(buffer, len); -} - -s32 __Loader_ReadDol(dolentry *p_entry) -{ - static dolheader dol ATTRIBUTE_ALIGN(32); - - u32 cnt; - s32 cfd = -1, ret; - - /* Open DOL file */ - cfd = ES_OpenContent(DOL_INDEX); - if (cfd < 0) - return cfd; - - /* Read DOL header */ - ret = ES_ReadContent(cfd, (u8 *)&dol, sizeof(dol)); - if (ret < 0) - goto out; - - /* Clear BSS */ - memset(dol.bssmem, 0, dol.bsssize); - - /* Read TEXT section */ - for (cnt = 0; cnt < 7; cnt++) { - u32 offset = dol.textoff[cnt]; - - if (offset >= sizeof(dol)) { - u8 *buffer = (u8 *)dol.textmem[cnt]; - u32 len = dol.textsize[cnt]; - - /* Seek */ - ES_SeekContent(cfd, offset, 0); - - /* Read */ - ret = ES_ReadContent(cfd, buffer, len); - if (ret < 0) - goto out; - - /* Patch */ - __Loader_PatchDol(buffer, len); - } - } - - /* Read DATA section */ - for (cnt = 0; cnt < 11; cnt++) { - u32 offset = dol.dataoff[cnt]; - - if (offset >= sizeof(dol)) { - u8 *buffer = (u8 *)dol.datamem[cnt]; - u32 len = dol.datasize[cnt]; - - /* Seek */ - ES_SeekContent(cfd, offset, 0); - - /* Read */ - ret = ES_ReadContent(cfd, buffer, len); - if (ret < 0) - goto out; - - /* Patch */ - __Loader_PatchDol(buffer, len); - } - } - - /* Set entry point */ - *p_entry = (dolentry)dol.entry; - -out: - /* Close DOL file */ - if (cfd >= 0) - ES_CloseContent(cfd); - - return ret; -} - -void __Loader_Shutdown(void) -{ - /* Deinitialize ISFS */ - ISFS_Deinitialize(); - - /* Shutdown IOS subsystems */ - SYS_ResetSystem(SYS_SHUTDOWN, 0, 0); -} - - -s32 Loader_Execute(void) -{ - dolentry p_entry = NULL; - - u64 tid; - s32 ret; - - /* Get title ID */ - ret = ES_GetTitleID(&tid); - if (ret < 0) - return ret; - - /* Load DOL */ - ret = __Loader_ReadDol(&p_entry); - if (ret < 0) - return ret; - - /* Set low memory */ - __Loader_SetLowMem(); - - /* Set video mode */ - __Loader_SetVMode(tid); - - /* Shutdown subsystems */ - __Loader_Shutdown(); - - /* Clear screen */ - Video_Clear(COLOR_BLACK); - - /* Jump to the entry point */ - p_entry(); - - return 0; -} diff --git a/nand-loader/source/loader.h b/nand-loader/source/loader.h deleted file mode 100644 index dd5457c..0000000 --- a/nand-loader/source/loader.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef _LOADER_H_ -#define _LOADER_H_ - -/* Prototypes */ -s32 Loader_Execute(void); - -#endif - diff --git a/nand-loader/source/nandloader.c b/nand-loader/source/nandloader.c deleted file mode 100644 index af67cdf..0000000 --- a/nand-loader/source/nandloader.c +++ /dev/null @@ -1,79 +0,0 @@ -#include -#include -#include - -#include "config.h" -#include "gui.h" -#include "loader.h" -#include "sys.h" -#include "video.h" -#include "wpad.h" - -/* Constans */ -#define RESTART_SECONDS 4 - - -/* Override IOS_LoadStartupIOS */ -s32 __IOS_LoadStartupIOS() { return 0; } - - -void Menu(void) -{ - /* Initialize Wiimote */ - Wpad_Init(); - - /* Draw background */ - Gui_DrawBackground(); - - /* Initialize console */ - Gui_InitConsole(); - - /* Configuration menu */ - Config_Menu(); - - /* Destroy console */ - Con_Destroy(); - - /* Disconnect Wiimote */ - Wpad_Disconnect(); -} - -int main(int argc, char **argv) -{ - s32 ret; - - /* Initialize subsystems */ - Sys_Init(); - - /* Set video mode */ - Video_SetMode(); - - /* Initialize ISFS */ - ISFS_Initialize(); - - /* Read config */ - Config_Read(); - - /* Config menu */ - ret = SYS_ResetButtonDown(); - if (ret) - Menu(); - - /* Draw loading image */ - if(loaderCfg.showSplash) - Gui_DrawLoading(); - - /* Execute application */ - Loader_Execute(); - - /* Draw error image */ - Gui_DrawError(); - - /* Sleep */ - sleep(RESTART_SECONDS); - - /* Load System Menu */ - Sys_LoadMenu(); - - return 0; -} diff --git a/nand-loader/source/patches.c b/nand-loader/source/patches.c deleted file mode 100644 index cd286b2..0000000 --- a/nand-loader/source/patches.c +++ /dev/null @@ -1,126 +0,0 @@ -#include -#include -#include - -#include "config.h" - -GXRModeObj *PAL2NTSC[] = { - &TVMpal480IntDf, &TVNtsc480IntDf, - &TVPal264Ds, &TVNtsc240Ds, - &TVPal264DsAa, &TVNtsc240DsAa, - &TVPal264Int, &TVNtsc240Int, - &TVPal264IntAa, &TVNtsc240IntAa, - &TVPal524IntAa, &TVNtsc480IntAa, - &TVPal528Int, &TVNtsc480IntAa, - &TVPal528IntDf, &TVNtsc480IntDf, - &TVPal574IntDfScale, &TVNtsc480IntDf, - &TVEurgb60Hz240Ds, &TVNtsc240Ds, - &TVEurgb60Hz240DsAa, &TVNtsc240DsAa, - &TVEurgb60Hz240Int, &TVNtsc240Int, - &TVEurgb60Hz240IntAa, &TVNtsc240IntAa, - &TVEurgb60Hz480Int, &TVNtsc480IntAa, - &TVEurgb60Hz480IntDf, &TVNtsc480IntDf, - &TVEurgb60Hz480IntAa, &TVNtsc480IntAa, - &TVEurgb60Hz480Prog, &TVNtsc480Prog, - &TVEurgb60Hz480ProgSoft,&TVNtsc480Prog, - &TVEurgb60Hz480ProgAa, &TVNtsc480Prog, - NULL, NULL -}; - -GXRModeObj *NTSC2PAL[] = { - &TVNtsc240Ds, &TVPal264Ds, - &TVNtsc240DsAa, &TVPal264DsAa, - &TVNtsc240Int, &TVPal264Int, - &TVNtsc240IntAa, &TVPal264IntAa, - &TVNtsc480IntDf, &TVPal528IntDf, - &TVNtsc480IntAa, &TVPal524IntAa, - &TVNtsc480Prog, &TVPal528IntDf, - NULL, NULL -}; - -GXRModeObj *NTSC2PAL60[]={ - &TVNtsc240Ds, &TVEurgb60Hz240Ds, - &TVNtsc240DsAa, &TVEurgb60Hz240DsAa, - &TVNtsc240Int, &TVEurgb60Hz240Int, - &TVNtsc240IntAa, &TVEurgb60Hz240IntAa, - &TVNtsc480IntDf, &TVEurgb60Hz480IntDf, - &TVNtsc480IntAa, &TVEurgb60Hz480IntAa, - &TVNtsc480Prog, &TVEurgb60Hz480Prog, - NULL, NULL -}; - - -void Patch_VideoMode(u8 *buffer, u32 len) -{ - GXRModeObj **table = NULL; - - u32 cnt, idx; - - /* Select conversion table */ - if (loaderCfg.forcePal50) - table = NTSC2PAL; - if (loaderCfg.forcePal60) - table = NTSC2PAL60; - if (loaderCfg.forceNtsc) - table = PAL2NTSC; - - /* No table selected */ - if (!table) - return; - - for (cnt = 0; cnt < len; cnt += 4) { - u8 *ptr = buffer + cnt; - - /* Search for video modes */ - for (idx = 0; table[idx]; idx += 2) { - /* Patch video mode */ - if (!memcmp(ptr, table[idx], sizeof(GXRModeObj))) - memcpy(ptr, table[idx+1], sizeof(GXRModeObj)); - } - } -} - -// void __Patch_VideoMode(u8 *buffer, u32 len) -// { -// const u8 pattern[] = { 0x54, 0x00, 0xFF, 0xFE }; -// -// u64 tid; -// u32 cnt; -// -// /* Get title ID */ -// ES_GetTitleID(&tid); -// -// for (cnt = 0; cnt < len; cnt += 4) { -// u32 *ptr = (u32 *)(buffer + cnt); -// -// /* Pattern found */ -// if (!memcmp(ptr, pattern, sizeof(pattern))) { -// u8 region = tid & 0xFF; -// -// /* USA region */ -// if (region == 'E') -// *ptr = 0x38000001; -// /* JAP region */ -// if (region == 'J') -// *ptr = 0x38000000; -// -// break; -// } -// } -// } -// -// -// void Patch_VideoMode(u8 *buffer, u32 len) -// { -// const u8 pattern[] = { 0x41, 0x82, 0x00, 0x0C, 0x41, 0x80, 0x00, 0x1C, 0x48, 0x00, 0x00, 0x18 }; -// -// u32 cnt; -// -// for (cnt = 0; cnt < len; cnt += 4) { -// u8 *ptr = buffer + cnt; -// -// /* Pattern found */ -// if (!memcmp(ptr, pattern, sizeof(pattern))) -// __Patch_VideoMode(ptr, len - cnt); -// } -// } diff --git a/nand-loader/source/patches.h b/nand-loader/source/patches.h deleted file mode 100644 index 78a271f..0000000 --- a/nand-loader/source/patches.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef _PATCHES_H_ -#define _PATCHES_H_ - -/* Prototypes */ -void Patch_VideoMode(u8 *, u32); - -#endif diff --git a/nand-loader/source/pngu.c b/nand-loader/source/pngu.c deleted file mode 100644 index 1bab952..0000000 --- a/nand-loader/source/pngu.c +++ /dev/null @@ -1,1561 +0,0 @@ -/******************************************************************************************** - -PNGU Version : 0.2a - -Coder : frontier - -More info : http://frontier-dev.net - -********************************************************************************************/ -#include -#include -#include -#include "png.h" -#include "pngu.h" -#include "pngu_impl.h" - -#ifndef SAFE_FREE -#define SAFE_FREE(p) if(p){free(p);p=NULL;} -#endif - -#if 0 -// moved to pngu_impl.h -// Constants -#define PNGU_SOURCE_BUFFER 1 -#define PNGU_SOURCE_DEVICE 2 - -// Prototypes of helper functions -int pngu_info (IMGCTX ctx); -int pngu_decode (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, PNGU_u32 stripAlpha); -int pngu_decode_add_alpha (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, PNGU_u32 stripAlpha, int force32bit); -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 buf_size; // buffer size - - 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; -}; -#endif - - -// PNGU Implementation // - -IMGCTX PNGU_SelectImageFromBufferX (const void *buffer, int size) -{ - IMGCTX ctx = NULL; - - if (!buffer) - return NULL; - - ctx = calloc (sizeof (struct _IMGCTX), 1); - 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; - ctx->buf_size = size; - - return ctx; -} - -IMGCTX PNGU_SelectImageFromBuffer (const void *buffer) -{ - return PNGU_SelectImageFromBufferX(buffer, 0); -} - - -IMGCTX PNGU_SelectImageFromDevice (const char *filename) -{ - IMGCTX ctx = NULL; - - if (!filename) - return NULL; - - ctx = calloc (sizeof (struct _IMGCTX), 1); - 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; -} - - -//######################################################################################## -//---------- Start CMPR added section --------------------------------------------------- -//######################################################################################## - -static inline PNGU_u16 rgb8ToRGB565(PNGU_u8 *color) -{ - return ((color[0] >> 3) << 11) | ((color[1] >> 2) << 5) | (color[2] >> 3); -} - -static int colorDistance(const PNGU_u8 *c0, const PNGU_u8 *c1) -{ - return (c1[0] - c0[0]) * (c1[0] - c0[0]) + (c1[1] - c0[1]) * (c1[1] - c0[1]) + (c1[2] - c0[2]) * (c1[2] - c0[2]); -} - -static void getBaseColors(PNGU_u8 *color0, PNGU_u8 *color1, const PNGU_u8 *srcBlock) -{ - int maxDistance = -1; - int i; - int j; - - for (i = 0; i < 15; ++i) - for (j = i + 1; j < 16; ++j) - { - int distance = colorDistance(srcBlock + i * 4, srcBlock + j * 4); - if (distance > maxDistance) - { - maxDistance = distance; - *(PNGU_u32 *)color0 = ((PNGU_u32 *)srcBlock)[i]; - *(PNGU_u32 *)color1 = ((PNGU_u32 *)srcBlock)[j]; - } - } - if (rgb8ToRGB565(color0) < rgb8ToRGB565(color1)) - { - PNGU_u32 tmp; - tmp = *(PNGU_u32 *)color0; - *(PNGU_u32 *)color0 = *(PNGU_u32 *)color1; - *(PNGU_u32 *)color1 = tmp; - } -} - -static PNGU_u32 colorIndices(const PNGU_u8 *color0, const PNGU_u8 *color1, const PNGU_u8 *srcBlock) -{ - PNGU_u16 colors[4][4]; - PNGU_u32 res = 0; - int i; - - // Make the 4 colors available in the block - colors[0][0] = (color0[0] & 0xF8) | (color0[0] >> 5); - colors[0][1] = (color0[1] & 0xFC) | (color0[1] >> 6); - colors[0][2] = (color0[2] & 0xF8) | (color0[2] >> 5); - colors[1][0] = (color1[0] & 0xF8) | (color1[0] >> 5); - colors[1][1] = (color1[1] & 0xFC) | (color1[1] >> 6); - colors[1][2] = (color1[2] & 0xF8) | (color1[2] >> 5); - colors[2][0] = (2 * colors[0][0] + 1 * colors[1][0]) / 3; - colors[2][1] = (2 * colors[0][1] + 1 * colors[1][1]) / 3; - colors[2][2] = (2 * colors[0][2] + 1 * colors[1][2]) / 3; - colors[3][0] = (1 * colors[0][0] + 2 * colors[1][0]) / 3; - colors[3][1] = (1 * colors[0][1] + 2 * colors[1][1]) / 3; - colors[3][2] = (1 * colors[0][2] + 2 * colors[1][2]) / 3; - for (i = 15; i >= 0; --i) - { - int c0 = srcBlock[i * 4 + 0]; - int c1 = srcBlock[i * 4 + 1]; - int c2 = srcBlock[i * 4 + 2]; - int d0 = abs(colors[0][0] - c0) + abs(colors[0][1] - c1) + abs(colors[0][2] - c2); - int d1 = abs(colors[1][0] - c0) + abs(colors[1][1] - c1) + abs(colors[1][2] - c2); - int d2 = abs(colors[2][0] - c0) + abs(colors[2][1] - c1) + abs(colors[2][2] - c2); - int d3 = abs(colors[3][0] - c0) + abs(colors[3][1] - c1) + abs(colors[3][2] - c2); - int b0 = d0 > d3; - int b1 = d1 > d2; - int b2 = d0 > d2; - int b3 = d1 > d3; - int b4 = d2 > d3; - int x0 = b1 & b2; - int x1 = b0 & b3; - int x2 = b0 & b4; - res |= (x2 | ((x0 | x1) << 1)) << ((15 - i) << 1); - } - return res; -} - -int PNGU_DecodeToCMPR_Trim(IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer) -{ - int result; - PNGU_u8 srcBlock[16 * 4]; - PNGU_u8 color0[4]; - PNGU_u8 color1[4]; - PNGU_u8 *outBuf = (PNGU_u8 *)buffer; - int ii; - int jj; - int k; - - //check for alpha channel - result = pngu_decode_add_alpha (ctx, width, height, 0, 1); - if (result != PNGU_OK) - return result; - - // trim down - width = width & ~7u; - height = height & ~7u; - - // Alpha channel present, copy image to the output buffer - for (jj = 0; jj < height; jj += 8) - for (ii = 0; ii < width; ii += 8) - for (k = 0; k < 4; ++k) - { - int j = jj + ((k >> 1) << 2); // jj + 0, jj + 0, jj + 4, jj + 4 - int i = ii + ((k & 1) << 2); // ii + 0, ii + 4, ii + 0, ii + 4 - memcpy(srcBlock, ctx->row_pointers[j] + i * 4, 16); - memcpy(srcBlock + 4 * 4, ctx->row_pointers[j + 1] + i * 4, 16); - memcpy(srcBlock + 8 * 4, ctx->row_pointers[j + 2] + i * 4, 16); - memcpy(srcBlock + 12 * 4, ctx->row_pointers[j + 3] + i * 4, 16); - getBaseColors(color0, color1, srcBlock); - *(PNGU_u16 *)outBuf = rgb8ToRGB565(color0); - outBuf += 2; - *(PNGU_u16 *)outBuf = rgb8ToRGB565(color1); - outBuf += 2; - *(PNGU_u32 *)outBuf = colorIndices(color0, color1, srcBlock); - outBuf += 4; - } - // Free resources - free (ctx->img_data); - free (ctx->row_pointers); - - // Success - return PNGU_OK; -} - - -// if width or height is not divisible by 8 -// then the remaining will be padded with last row/column -// buffer must be allocated with width and height rounded up - -int PNGU_DecodeToCMPR_Pad(IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer) -{ - int result; - PNGU_u8 srcBlock[16 * 4]; - PNGU_u8 color0[4]; - PNGU_u8 color1[4]; - PNGU_u8 *outBuf = (PNGU_u8 *)buffer; - int ii; - int jj; - int k; - - //check for alpha channel - result = pngu_decode_add_alpha (ctx, width, height, 0, 1); - if (result != PNGU_OK) - return result; - - // Alpha channel present, copy image to the output buffer - for (jj = 0; jj < height; jj += 8) { - for (ii = 0; ii < width; ii += 8) { - for (k = 0; k < 4; ++k) { - // k(i,j) - // 0(0,0) 1(4,0) - // 2(4,0) 3(4,4) - int i = ii + ((k & 1) << 2); // ii + 0, ii + 4, ii + 0, ii + 4 - int j = jj + ((k >> 1) << 2); // jj + 0, jj + 0, jj + 4, jj + 4 - int ny; // 4 lines - int px = 4; // num columns to copy - if (i >= width) i = width - 1; - if (i + px > width) px = width - i; - for (ny=0; ny<4; ny++) { - if (j >= height) j = height - 1; - memcpy(srcBlock + ny * 4 * 4, - ctx->row_pointers[j] + i * 4, px * 4); - if (px < 4) { - // repeat last column (4-px) times - int x = width - 1; - int nx; - for (nx = px; nx < 4; nx++) { - memcpy(srcBlock + ny * 4 * 4 + nx * 4, - ctx->row_pointers[j] + x * 4, 4); - } - } - j++; - } - getBaseColors(color0, color1, srcBlock); - *(PNGU_u16 *)outBuf = rgb8ToRGB565(color0); - outBuf += 2; - *(PNGU_u16 *)outBuf = rgb8ToRGB565(color1); - outBuf += 2; - *(PNGU_u32 *)outBuf = colorIndices(color0, color1, srcBlock); - outBuf += 4; - } - } - } - // Free resources - free (ctx->img_data); - free (ctx->row_pointers); - - // Success - return PNGU_OK; -} - -void ExtractBlock( PNGU_u8 *inPtr, int y, int x, PNGU_u32 width, int i, PNGU_u8 colorBlock[] ) { - PNGU_u32 offset; - PNGU_u8 r, g, b, a; - - offset = (((y >> 2)<<4)*width) + ((x >> 2)<<6) + ((((y&3) << 2) + (x&3) ) << 1); - //offset = (((y >> 2) << 4)*width) + ((x >> 2) << 6) + (((y % 4 << 2) + x % 4) << 1); - //get rgba values based on the RGBA8 offsets - a = *(inPtr+offset); - r = *(inPtr+offset+1); - g = *(inPtr+offset+32); - b = *(inPtr+offset+33); - colorBlock[i*4] = r; - colorBlock[i*4+1] = g; - colorBlock[i*4+2] = b; - colorBlock[i*4+3] = a; - -} - -/** - * by usptactical - * Converts a 4x4 RGBA8 image to CMPR. - */ -int PNGU_4x4RGBA8_To_CMPR(void *buf_rgb, PNGU_u32 width, PNGU_u32 height, void *buf_cmpr) -{ - PNGU_u8 srcBlock[16 * 4]; - PNGU_u8 color0[4]; - PNGU_u8 color1[4]; - PNGU_u8 *outBuf = (PNGU_u8 *)buf_cmpr; - PNGU_u8 *rgba = (PNGU_u8 *)buf_rgb; - int jj, ii, i, j, k; - - width = width & ~7u; - height = height & ~7u; - - // loop over blocks - //CMPR needs 4x4 block of pixels: - //image row 0: 0, 1, 2, 3 (first 16 block) - //image row 1: 0, 1, 2, 3 (second 16 block) - //image row 2: 0, 1, 2, 3 (third 16 block) - //image row 3: 0, 1, 2, 3 (last 16 block) - - //image row 0: 4, 5, 6, 7 (first 16 block) - //image row 1: 4, 5, 6, 7 (second 16 block) - //image row 2: 4, 5, 6, 7 (third 16 block) - //image row 3: 4, 5, 6, 7 (last 16 block) - - //image row 4: 0, 1, 2, 3 (first 16 block) - //image row 5: 0, 1, 2, 3 (second 16 block) - //image row 6: 0, 1, 2, 3 (third 16 block) - //image row 7: 0, 1, 2, 3 (last 16 block) - - //image row 4: 4, 5, 6, 7 (first 16 block) - //image row 5: 4, 5, 6, 7 (second 16 block) - //image row 6: 4, 5, 6, 7 (third 16 block) - //image row 7: 4, 5, 6, 7 (last 16 block) - - for(jj = 0; jj < height; jj += 8) - for(ii = 0; ii < width; ii += 8) - for (k=0; k < 4; k++) - { - j = jj + ((k >> 1) << 2); // jj + 0, jj + 0, jj + 4, jj + 4 - i = ii + ((k & 1) << 2); // ii + 0, ii + 4, ii + 0, ii + 4 - - ExtractBlock(rgba, j, i, width, 0, srcBlock); - ExtractBlock(rgba, j, i+1, width, 1, srcBlock); - ExtractBlock(rgba, j, i+2, width, 2, srcBlock); - ExtractBlock(rgba, j, i+3, width, 3, srcBlock); - - ExtractBlock(rgba, j+1, i, width, 4, srcBlock); - ExtractBlock(rgba, j+1, i+1, width, 5, srcBlock); - ExtractBlock(rgba, j+1, i+2, width, 6, srcBlock); - ExtractBlock(rgba, j+1, i+3, width, 7, srcBlock); - - ExtractBlock(rgba, j+2, i, width, 8, srcBlock); - ExtractBlock(rgba, j+2, i+1, width, 9, srcBlock); - ExtractBlock(rgba, j+2, i+2, width, 10, srcBlock); - ExtractBlock(rgba, j+2, i+3, width, 11, srcBlock); - - ExtractBlock(rgba, j+3, i, width, 12, srcBlock); - ExtractBlock(rgba, j+3, i+1, width, 13, srcBlock); - ExtractBlock(rgba, j+3, i+2, width, 14, srcBlock); - ExtractBlock(rgba, j+3, i+3, width, 15, srcBlock); - - getBaseColors(color0, color1, srcBlock); - *(PNGU_u16 *)outBuf = rgb8ToRGB565(color0); - outBuf += 2; - *(PNGU_u16 *)outBuf = rgb8ToRGB565(color1); - outBuf += 2; - *(PNGU_u32 *)outBuf = colorIndices(color0, color1, srcBlock); - outBuf += 4; - } - // Success - return PNGU_OK; -} - -// if width or height is not divisible by 8 -// then the remaining will be padded with last row/column -// buffer must be allocated with width and height rounded up -int PNGU_RGBA8_To_CMPR(void *buf_rgb, PNGU_u32 width, PNGU_u32 height, void *buf_cmpr) -{ - PNGU_u8 srcBlock[16 * 4]; - PNGU_u8 color0[4]; - PNGU_u8 color1[4]; - PNGU_u8 *src, *block; - PNGU_u8 *cmpr = (PNGU_u8 *)buf_cmpr; - PNGU_u8 *rgba = (PNGU_u8 *)buf_rgb; - int jj, ii, i, j, k; - int x, y; // counter - int px, py; // pixel coord - - for(jj = 0; jj < height; jj += 8) { - for(ii = 0; ii < width; ii += 8) { - for (k=0; k < 4; k++) { - i = ii + ((k & 1) << 2); // ii + 0, ii + 4, ii + 0, ii + 4 - j = jj + ((k >> 1) << 2); // jj + 0, jj + 0, jj + 4, jj + 4 - - block = srcBlock; - for (y=0; y<4; y++) { - py = j + y; - if (py >= height) py = height - 1; - src = rgba + py * width * 4; - for (x=0; x<4; x++) { - px = i + x; - if (px >= width) px = width - 1; - memcpy(block, src + px * 4, 4); - block += 4; - } - } - - getBaseColors(color0, color1, srcBlock); - *(PNGU_u16 *)cmpr = rgb8ToRGB565(color0); - cmpr += 2; - *(PNGU_u16 *)cmpr = rgb8ToRGB565(color1); - cmpr += 2; - *(PNGU_u32 *)cmpr = colorIndices(color0, color1, srcBlock); - cmpr += 4; - } - } - } - // Success - return PNGU_OK; -} - - -/** - * added by usptactical - * handles png error messages - */ -void user_error (png_structp png_ptr, png_const_charp c) -{ - longjmp(png_jmpbuf(png_ptr), 1); -} - - - -//######################################################################################## -//---------- End CMPR added section ----------------------------------------------------- -//######################################################################################## - - -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_add_alpha (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, PNGU_u32 stripAlpha, int force32bit) -{ - png_uint_32 rowbytes; - int i; - int chunk; - int rowsLeft; - png_bytep *curRow; - int mem_err = 0; - - - // 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; - - //************************************************* - //* added by usptactical to catch corrupted pngs * - jmp_buf save_jmp; - memcpy(save_jmp, png_jmpbuf(ctx->png_ptr), sizeof(save_jmp)); - if (setjmp(png_jmpbuf(ctx->png_ptr))) { - error: - memcpy(png_jmpbuf(ctx->png_ptr), save_jmp, sizeof(save_jmp)); - SAFE_FREE(ctx->row_pointers); - SAFE_FREE(ctx->img_data); - pngu_free_info (ctx); - //printf("*** This is a corrupted image!!\n"); sleep(5); - return (mem_err)?PNGU_LIB_ERROR:-666; - } - //override default error handler to suppress warning messages from libpng - png_set_error_fn (ctx->png_ptr, NULL, user_error, user_error); - //************************************************* - - // 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); - - // Transform RBG images to RGBA - if (force32bit && (ctx->prop.imgColorType == PNGU_COLOR_TYPE_GRAY || ctx->prop.imgColorType == PNGU_COLOR_TYPE_RGB)) - png_set_filler(ctx->png_ptr, 0xFF, PNG_FILLER_AFTER); - - // 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; - mem_err = 1; - goto 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; - mem_err = 1; - goto error; - } - - for (i = 0; i < (int)ctx->prop.imgHeight; i++) - ctx->row_pointers[i] = ctx->img_data + (i * rowbytes); - - // Transform the image and copy it to our allocated memory - if (png_get_interlace_type(ctx->png_ptr, ctx->info_ptr) != PNG_INTERLACE_NONE) - png_read_image (ctx->png_ptr, ctx->row_pointers); - else - { - rowsLeft = ctx->prop.imgHeight; - curRow = ctx->row_pointers; - while (rowsLeft > 0) - { - chunk = rowsLeft > 0x80 ? 0x80 : rowsLeft; - png_read_rows(ctx->png_ptr, curRow, NULL, chunk); - //usleep(1000); - curRow += chunk; - rowsLeft -= chunk; - } - } - - // restore default error handling - memcpy(png_jmpbuf(ctx->png_ptr), save_jmp, sizeof(save_jmp)); - - // Free resources - pngu_free_info (ctx); - - // Success - return PNGU_OK; -} - -int pngu_decode (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, PNGU_u32 stripAlpha) -{ - return pngu_decode_add_alpha(ctx, width, height, stripAlpha, 0); -} - - -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); - if (ctx->buf_size && (ctx->cursor + length > ctx->buf_size)) - { - static char err_str[40]; - snprintf(err_str, sizeof(err_str), "read error (%x/%x)", - ctx->cursor + length, ctx->buf_size); - png_error(png_ptr, err_str); - } - 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/nand-loader/source/pngu.h b/nand-loader/source/pngu.h deleted file mode 100644 index e979374..0000000 --- a/nand-loader/source/pngu.h +++ /dev/null @@ -1,181 +0,0 @@ -/******************************************************************************************** - -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); -IMGCTX PNGU_SelectImageFromBufferX (const void *buffer, int size); - -// 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) * 4 + \ - (coordX) * 4, (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); -// Compressed version (DXT1/CMPR) -int PNGU_DecodeToCMPR_Trim(IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer); -int PNGU_DecodeToCMPR_Pad(IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer); -int PNGU_4x4RGBA8_To_CMPR(void *buf_rgb, PNGU_u32 width, PNGU_u32 height, void *buf_cmpr); -int PNGU_RGBA8_To_CMPR(void *buf_rgb, PNGU_u32 width, PNGU_u32 height, void *buf_cmpr); - -// Expands selected image into a 4x4 tiled RGB5A3 buffer. You need to specify context, image dimensions, -// destination address and default alpha value, which is used if the source image doesn't have an alpha channel. -int PNGU_DecodeTo4x4RGB5A3 (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer, PNGU_u8 default_alpha); - -// Expands selected image into a 4x4 tiled RGBA8 buffer. You need to specify context, image dimensions, -// destination address and default alpha value, which is used if the source image doesn't have an alpha channel. -int PNGU_DecodeTo4x4RGBA8 (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer, PNGU_u8 default_alpha); - -// Encodes an YCbYCr image in PNG format and stores it in the selected device or memory buffer. You need to -// specify context, image dimensions, destination address and stride in pixels (stride = buffer width - image width). -int PNGU_EncodeFromYCbYCr (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer, PNGU_u32 stride); - -// Macro for encoding an image stored into an YCbYCr buffer at given coordinates. -#define PNGU_ENCODE_TO_COORDS_YCbYCr(ctx,coordX,coordY,imgWidth,imgHeight,bufferWidth,bufferHeight,buffer) \ - \ - PNGU_EncodeFromYCbYCr (ctx, imgWidth, imgHeight, ((void *) buffer) + (coordY) * (bufferWidth) * 2 + \ - (coordX) * 2, (bufferWidth) - (imgWidth)) - -PNGU_u8 * PNGU_DecodeTo4x4RGBA8_EX (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, int * dstWidth, int * dstHeight, PNGU_u8 *dstPtr); - -int PNGU_EncodeFromEFB (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, PNGU_u32 stride); - -#ifdef __cplusplus - } -#endif - -#endif - diff --git a/nand-loader/source/pngu_impl.h b/nand-loader/source/pngu_impl.h deleted file mode 100644 index 782e94d..0000000 --- a/nand-loader/source/pngu_impl.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef __PNGU_I__ -#define __PNGU_I__ - -#include "png.h" - -// Constants -#define PNGU_SOURCE_BUFFER 1 -#define PNGU_SOURCE_DEVICE 2 - -// Prototypes of helper functions -int pngu_info (IMGCTX ctx); -int pngu_decode (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, PNGU_u32 stripAlpha); -int pngu_decode_add_alpha (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, PNGU_u32 stripAlpha, int force32bit); -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 buf_size; // buffer size - - 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; -}; - -#endif diff --git a/nand-loader/source/stub.S b/nand-loader/source/stub.S deleted file mode 100644 index 756bf5a..0000000 --- a/nand-loader/source/stub.S +++ /dev/null @@ -1,118 +0,0 @@ - .rodata - - .globl bgData -bgData: - .incbin "../data/background" - - .globl loadingImg -loadingImg: - .incbin "../data/loading" - - .globl errorImg -errorImg: - .incbin "../data/error" - - - -#include "asm.h" - - .text - .section .stub - - .extern _start - .globl _stub_start -_stub_start: - lis r3, 0x0011 - ori r3, r3, 0x0C64 - mtspr HID0, r3 - isync - - li r4, 0x2000 - mtmsr r4 - - ori r3, r3, 0xC000 - mtspr HID0, r3 - isync - - li r0, 0 - mtspr IBAT0U, r0 - mtspr IBAT1U, r0 - mtspr IBAT2U, r0 - mtspr IBAT3U, r0 - mtspr IBAT4U, r0 - mtspr IBAT5U, r0 - mtspr DBAT0U, r0 - mtspr DBAT1U, r0 - mtspr DBAT2U, r0 - mtspr DBAT3U, r0 - mtspr DBAT4U, r0 - mtspr DBAT5U, r0 - isync - - lis r0, 0x8000 - mtsr 0, r0 - mtsr 1, r0 - mtsr 2, r0 - mtsr 3, r0 - mtsr 4, r0 - mtsr 5, r0 - mtsr 6, r0 - mtsr 7, r0 - mtsr 8, r0 - mtsr 9, r0 - mtsr 10, r0 - mtsr 11, r0 - mtsr 12, r0 - mtsr 13, r0 - mtsr 14, r0 - mtsr 15, r0 - isync - - li r3, 2 - lis r4, 0x8000 - ori r4, r4, 0x1FFF - mtspr DBAT0L, r3 - mtspr DBAT0U, r4 - isync - mtspr IBAT0L, r3 - mtspr IBAT0U, r4 - isync - - addis r3, r3, 0x1000 - addis r4, r4, 0x1000 - mtspr DBAT4L, r3 - mtspr DBAT4U, r4 - isync - mtspr IBAT4L, r3 - mtspr IBAT4U, r4 - isync - - li r3, 0x2A - lis r4, 0xC000 - ori r4, r4, 0x1FFF - mtspr DBAT1L, r3 - mtspr DBAT1U, r4 - isync - mtspr IBAT1L, r3 - mtspr IBAT1U, r4 - isync - - addis r3, r3, 0x1000 - addis r4, r4, 0x1000 - mtspr DBAT2L, r3 - mtspr DBAT2U, r4 - isync - mtspr IBAT2L, r3 - mtspr IBAT2U, r4 - isync - - li r3, 0 - mfmsr r3 - ori r3, r3, MSR_DR|MSR_IR - mtsrr1 r3 - - lis r3, _start@h - ori r3, r3, _start@l - mtsrr0 r3 - - rfi diff --git a/nand-loader/source/sys.c b/nand-loader/source/sys.c deleted file mode 100644 index 8a9e54b..0000000 --- a/nand-loader/source/sys.c +++ /dev/null @@ -1,48 +0,0 @@ -#include -#include -#include - -/* Constants */ -#define CERTS_LEN 0x280 - -/* Variables */ -static const char certs_fs[] ATTRIBUTE_ALIGN(32) = "/sys/cert.sys"; - - -void Sys_Init(void) -{ - /* Initialize video subsytem */ - VIDEO_Init(); -} - -void Sys_LoadMenu(void) -{ - /* Return to the Wii system menu */ - SYS_ResetSystem(SYS_RETURNTOMENU, 0, 0); -} - -s32 Sys_GetCerts(signed_blob **certs, u32 *len) -{ - static signed_blob certificates[CERTS_LEN] ATTRIBUTE_ALIGN(32); - - s32 fd, ret; - - /* Open certificates file */ - fd = IOS_Open(certs_fs, 1); - if (fd < 0) - return fd; - - /* Read certificates */ - ret = IOS_Read(fd, certificates, sizeof(certificates)); - - /* Close file */ - IOS_Close(fd); - - /* Set values */ - if (ret > 0) { - *certs = certificates; - *len = sizeof(certificates); - } - - return ret; -} diff --git a/nand-loader/source/sys.h b/nand-loader/source/sys.h deleted file mode 100644 index c1ac84c..0000000 --- a/nand-loader/source/sys.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef _SYS_H_ -#define _SYS_H_ - -/* Prototypes */ -void Sys_Init(void); -void Sys_LoadMenu(void); -s32 Sys_GetCerts(signed_blob **, u32 *); - -#endif diff --git a/nand-loader/source/title.c b/nand-loader/source/title.c deleted file mode 100644 index 0d05bd9..0000000 --- a/nand-loader/source/title.c +++ /dev/null @@ -1,256 +0,0 @@ -#include -#include -#include -#include -#include - -#include "utils.h" - - -s32 Title_GetList(u64 **outbuf, u32 *outlen) -{ - u64 *titles = NULL; - - u32 len, nb_titles; - s32 ret; - - /* Get number of titles */ - ret = ES_GetNumTitles(&nb_titles); - if (ret < 0) - return ret; - - /* Calculate buffer lenght */ - len = round_up(sizeof(u64) * nb_titles, 32); - - /* Allocate memory */ - titles = memalign(32, len); - if (!titles) - return -1; - - /* Get titles */ - ret = ES_GetTitles(titles, nb_titles); - if (ret < 0) - goto err; - - /* Set values */ - *outbuf = titles; - *outlen = nb_titles; - - return 0; - -err: - /* Free memory */ - if (titles) - free(titles); - - return ret; -} - -s32 Title_GetTicketViews(u64 tid, tikview **outbuf, u32 *outlen) -{ - tikview *views = NULL; - - u32 nb_views; - s32 ret; - - /* Get number of ticket views */ - ret = ES_GetNumTicketViews(tid, &nb_views); - if (ret < 0) - return ret; - - /* Allocate memory */ - views = (tikview *)memalign(32, sizeof(tikview) * nb_views); - if (!views) - return -1; - - /* Get ticket views */ - ret = ES_GetTicketViews(tid, views, nb_views); - if (ret < 0) - goto err; - - /* Set values */ - *outbuf = views; - *outlen = nb_views; - - return 0; - -err: - /* Free memory */ - if (views) - free(views); - - return ret; -} - -s32 Title_GetTMD(u64 tid, signed_blob **outbuf, u32 *outlen) -{ - void *p_tmd = NULL; - - u32 len; - s32 ret; - - /* Get TMD size */ - ret = ES_GetStoredTMDSize(tid, &len); - if (ret < 0) - return ret; - - /* Allocate memory */ - p_tmd = memalign(32, round_up(len, 32)); - if (!p_tmd) - return -1; - - /* Read TMD */ - ret = ES_GetStoredTMD(tid, p_tmd, len); - if (ret < 0) - goto err; - - /* Set values */ - *outbuf = p_tmd; - *outlen = len; - - return 0; - -err: - /* Free memory */ - if (p_tmd) - free(p_tmd); - - return ret; -} - -s32 Title_GetVersion(u64 tid, u16 *outbuf) -{ - signed_blob *p_tmd = NULL; - tmd *tmd_data = NULL; - - u32 len; - s32 ret; - - /* Get title TMD */ - ret = Title_GetTMD(tid, &p_tmd, &len); - if (ret < 0) - return ret; - - /* Retrieve TMD info */ - tmd_data = (tmd *)SIGNATURE_PAYLOAD(p_tmd); - - /* Set values */ - *outbuf = tmd_data->title_version; - - /* Free memory */ - free(p_tmd); - - return 0; -} - -s32 Title_GetSysVersion(u64 tid, u64 *outbuf) -{ - signed_blob *p_tmd = NULL; - tmd *tmd_data = NULL; - - u32 len; - s32 ret; - - /* Get title TMD */ - ret = Title_GetTMD(tid, &p_tmd, &len); - if (ret < 0) - return ret; - - /* Retrieve TMD info */ - tmd_data = (tmd *)SIGNATURE_PAYLOAD(p_tmd); - - /* Set values */ - *outbuf = tmd_data->sys_version; - - /* Free memory */ - free(p_tmd); - - return 0; -} - -s32 Title_GetSize(u64 tid, u32 *outbuf) -{ - signed_blob *p_tmd = NULL; - tmd *tmd_data = NULL; - - u32 cnt, len, size = 0; - s32 ret; - - /* Get title TMD */ - ret = Title_GetTMD(tid, &p_tmd, &len); - if (ret < 0) - return ret; - - /* Retrieve TMD info */ - tmd_data = (tmd *)SIGNATURE_PAYLOAD(p_tmd); - - /* Calculate title size */ - for (cnt = 0; cnt < tmd_data->num_contents; cnt++) { - tmd_content *content = &tmd_data->contents[cnt]; - - /* Add content size */ - size += content->size; - } - - /* Set values */ - *outbuf = size; - - /* Free memory */ - free(p_tmd); - - return 0; -} - -s32 Title_GetIOSVersions(u8 **outbuf, u32 *outlen) -{ - u8 *buffer = NULL; - u64 *list = NULL; - - u32 count, cnt, idx; - s32 ret; - - /* Get title list */ - ret = Title_GetList(&list, &count); - if (ret < 0) - return ret; - - /* Count IOS */ - for (cnt = idx = 0; idx < count; idx++) { - u32 tidh = (list[idx] >> 32); - u32 tidl = (list[idx] & 0xFFFFFFFF); - - /* Title is IOS */ - if ((tidh == 0x1) && (tidl >= 3) && (tidl <= 255)) - cnt++; - } - - /* Allocate memory */ - buffer = (u8 *)memalign(32, cnt); - if (!buffer) { - ret = -1; - goto out; - } - - /* Copy IOS */ - for (cnt = idx = 0; idx < count; idx++) { - u32 tidh = (list[idx] >> 32); - u32 tidl = (list[idx] & 0xFFFFFFFF); - - /* Title is IOS */ - if ((tidh == 0x1) && (tidl >= 3) && (tidl <= 255)) - buffer[cnt++] = (u8)(tidl & 0xFF); - } - - /* Set values */ - *outbuf = buffer; - *outlen = cnt; - - goto out; - -out: - /* Free memory */ - if (list) - free(list); - - return ret; -} diff --git a/nand-loader/source/title.h b/nand-loader/source/title.h deleted file mode 100644 index 5d1c573..0000000 --- a/nand-loader/source/title.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef _TITLE_H_ -#define _TITLE_H_ - -/* Constants */ -#define BLOCK_SIZE 1024 - -/* Prototypes */ -s32 Title_GetList(u64 **, u32 *); -s32 Title_GetTicketViews(u64, tikview **, u32 *); -s32 Title_GetTMD(u64, signed_blob **, u32 *); -s32 Title_GetVersion(u64, u16 *); -s32 Title_GetSysVersion(u64, u64 *); -s32 Title_GetSize(u64, u32 *); -s32 Title_GetIOSVersions(u8 **, u32 *); - -#endif diff --git a/nand-loader/source/tools.c b/nand-loader/source/tools.c deleted file mode 100644 index b9f8808..0000000 --- a/nand-loader/source/tools.c +++ /dev/null @@ -1,252 +0,0 @@ -/******************************************************************************* - * tools.c - * - * Copyright (c) 2009 The Lemon Man - * Copyright (c) 2009 Nicksasa - * Copyright (c) 2009 WiiPower - * - * Distributed under the terms of the GNU General Public License (v2) - * See http://www.gnu.org/licenses/gpl-2.0.txt for more info. - * - * Description: - * ----------- - * - ******************************************************************************/ - -#include -#include -#include -#include -#include -#include - -#include "tools.h" - -void printheadline() -{ - int rows, cols; - CON_GetMetrics(&cols, &rows); - - printf("TriiForce beta 7"); - - char buf[64]; - sprintf(buf, "IOS%u (Rev %u)\n", IOS_GetVersion(), IOS_GetRevision()); - printf("\x1B[%d;%dH", 0, cols-strlen(buf)-1); - printf(buf); -} - -void set_highlight(bool highlight) -{ - if (highlight) - { - printf("\x1b[%u;%um", 47, false); - printf("\x1b[%u;%um", 30, false); - } else - { - printf("\x1b[%u;%um", 37, false); - printf("\x1b[%u;%um", 40, false); - } -} - -void *allocate_memory(u32 size) -{ - return memalign(32, (size+31)&(~31) ); -} - -void Verify_Flags() -{ - if (Power_Flag) - { - WPAD_Shutdown(); - STM_ShutdownToStandby(); - } - if (Reset_Flag) - { - WPAD_Shutdown(); - STM_RebootSystem(); - } -} - - -void waitforbuttonpress(u32 *out, u32 *outGC) -{ - u32 pressed = 0; - u32 pressedGC = 0; - - while (true) - { - Verify_Flags(); - - WPAD_ScanPads(); - pressed = WPAD_ButtonsDown(0); - - PAD_ScanPads(); - pressedGC = PAD_ButtonsDown(0); - - if(pressed || pressedGC) - { - if (pressedGC) - { - // Without waiting you can't select anything - usleep (20000); - } - if (out) *out = pressed; - if (outGC) *outGC = pressedGC; - return; - } - } -} - - -s32 read_file(char *filepath, u8 **buffer, u32 *filesize) -{ - s32 Fd; - int ret; - - if (buffer == NULL) - { - printf("NULL Pointer\n"); - return -1; - } - - Fd = ISFS_Open(filepath, ISFS_OPEN_READ); - if (Fd < 0) - { - printf("ISFS_Open %s failed %d\n", filepath, Fd); - return Fd; - } - - fstats *status; - status = allocate_memory(sizeof(fstats)); - if (status == NULL) - { - printf("Out of memory for status\n"); - return -1; - } - - ret = ISFS_GetFileStats(Fd, status); - if (ret < 0) - { - printf("ISFS_GetFileStats failed %d\n", ret); - ISFS_Close(Fd); - free(status); - return -1; - } - - *buffer = allocate_memory(status->file_length); - if (*buffer == NULL) - { - printf("Out of memory for buffer\n"); - ISFS_Close(Fd); - free(status); - return -1; - } - - ret = ISFS_Read(Fd, *buffer, status->file_length); - if (ret < 0) - { - printf("ISFS_Read failed %d\n", ret); - ISFS_Close(Fd); - free(status); - free(*buffer); - return ret; - } - ISFS_Close(Fd); - - *filesize = status->file_length; - free(status); - - return 0; -} - -s32 identify(u64 titleid, u32 *ios) -{ - char filepath[ISFS_MAXPATH] ATTRIBUTE_ALIGN(0x20); - u8 *tmdBuffer = NULL; - u32 tmdSize; - u8 *tikBuffer = NULL; - u32 tikSize; - u8 *certBuffer = NULL; - u32 certSize; - - int ret; - - printf("Reading TMD..."); - fflush(stdout); - - sprintf(filepath, "/title/%08x/%08x/content/title.tmd", TITLE_UPPER(titleid), TITLE_LOWER(titleid)); - ret = read_file(filepath, &tmdBuffer, &tmdSize); - if (ret < 0) - { - printf("Reading TMD failed\n"); - return ret; - } - printf("done\n"); - - *ios = (u32)(tmdBuffer[0x18b]); - - printf("Reading ticket..."); - fflush(stdout); - - sprintf(filepath, "/ticket/%08x/%08x.tik", TITLE_UPPER(titleid), TITLE_LOWER(titleid)); - ret = read_file(filepath, &tikBuffer, &tikSize); - if (ret < 0) - { - printf("Reading ticket failed\n"); - free(tmdBuffer); - return ret; - } - printf("done\n"); - - printf("Reading certs..."); - fflush(stdout); - - sprintf(filepath, "/sys/cert.sys"); - ret = read_file(filepath, &certBuffer, &certSize); - if (ret < 0) - { - printf("Reading certs failed\n"); - free(tmdBuffer); - free(tikBuffer); - return ret; - } - printf("done\n"); - - printf("ES_Identify..."); - fflush(stdout); - - ret = ES_Identify((signed_blob*)certBuffer, certSize, (signed_blob*)tmdBuffer, tmdSize, (signed_blob*)tikBuffer, tikSize, NULL); - if (ret < 0) - { - switch(ret) - { - case ES_EINVAL: - printf("Error! ES_Identify (ret = %d;) Data invalid!\n", ret); - break; - case ES_EALIGN: - printf("Error! ES_Identify (ret = %d;) Data not aligned!\n", ret); - break; - case ES_ENOTINIT: - printf("Error! ES_Identify (ret = %d;) ES not initialized!\n", ret); - break; - case ES_ENOMEM: - printf("Error! ES_Identify (ret = %d;) No memory!\n", ret); - break; - default: - printf("Error! ES_Identify (ret = %d)\n", ret); - break; - } - free(tmdBuffer); - free(tikBuffer); - free(certBuffer); - return ret; - } - printf("done\n"); - - free(tmdBuffer); - free(tikBuffer); - free(certBuffer); - return 0; -} - - diff --git a/nand-loader/source/tools.h b/nand-loader/source/tools.h deleted file mode 100644 index b7532cc..0000000 --- a/nand-loader/source/tools.h +++ /dev/null @@ -1,31 +0,0 @@ -/******************************************************************************* - * tools.h - * - * Copyright (c) 2009 The Lemon Man - * Copyright (c) 2009 Nicksasa - * Copyright (c) 2009 WiiPower - * - * Distributed under the terms of the GNU General Public License (v2) - * See http://www.gnu.org/licenses/gpl-2.0.txt for more info. - * - * Description: - * ----------- - * - ******************************************************************************/ - -#define TITLE_UPPER(x) ((u32)((x) >> 32)) -#define TITLE_LOWER(x) ((u32)(x)) -#define TITLE_ID(x,y) (((u64)(x) << 32) | (y)) - -bool Power_Flag; -bool Reset_Flag; - -void *allocate_memory(u32 size); -s32 read_file(char *filepath, u8 **buffer, u32 *filesize); -s32 identify(u64 titleid, u32 *ios); -void set_highlight(bool highlight); -void waitforbuttonpress(u32 *out, u32 *outGC); -void printheadline(); - - - diff --git a/nand-loader/source/utils.h b/nand-loader/source/utils.h deleted file mode 100644 index 3a4862b..0000000 --- a/nand-loader/source/utils.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef _UTILS_H_ -#define _UTILS_H_ - -/* Constants */ -#define KB_SIZE 1024.0 -#define MB_SIZE 1048576.0 -#define GB_SIZE 1073741824.0 - -/* Macros */ -#define round_up(x,n) (-(-(x) & -(n))) - -/* Prototypes */ -u32 swap32(u32); - -#endif diff --git a/nand-loader/source/video.c b/nand-loader/source/video.c deleted file mode 100644 index 05ccd83..0000000 --- a/nand-loader/source/video.c +++ /dev/null @@ -1,147 +0,0 @@ -#include -#include - -#include "sys.h" -#include "video.h" - -/* Video variables */ -static void *framebuffer = NULL; -static GXRModeObj *vmode = NULL; - - -void Con_Init(u32 x, u32 y, u32 w, u32 h) -{ - /* Create console in the framebuffer */ - CON_InitEx(vmode, x, y, w, h); -} - -void Con_Destroy(void) -{ - /* Destroy console */ - VIDEO_SetPostRetraceCallback(NULL); -} - -void Con_Clear(void) -{ - /* Clear console */ - printf("\x1b[2J"); - fflush(stdout); -} - -void Con_ClearLine(void) -{ - s32 cols, rows; - u32 cnt; - - printf("\r"); - fflush(stdout); - - /* Get console metrics */ - CON_GetMetrics(&cols, &rows); - - /* Erase line */ - for (cnt = 1; cnt < cols; cnt++) { - printf(" "); - fflush(stdout); - } - - printf("\r"); - fflush(stdout); -} - -void Con_FgColor(u32 color, u8 bold) -{ - /* Set foreground color */ - printf("\x1b[%u;%um", color + 30, bold); - fflush(stdout); -} - -void Con_BgColor(u32 color, u8 bold) -{ - /* Set background color */ - printf("\x1b[%u;%um", color + 40, bold); - fflush(stdout); -} - -void Con_FillRow(u32 row, u32 color, u8 bold) -{ - s32 cols, rows; - u32 cnt; - - /* Set color */ - printf("\x1b[%u;%um", color + 40, bold); - fflush(stdout); - - /* Get console metrics */ - CON_GetMetrics(&cols, &rows); - - /* Save current row and col */ - printf("\x1b[s"); - fflush(stdout); - - /* Move to specified row */ - printf("\x1b[%u;0H", row); - fflush(stdout); - - /* Fill row */ - for (cnt = 0; cnt < cols; cnt++) { - printf(" "); - fflush(stdout); - } - - /* Load saved row and col */ - printf("\x1b[u"); - fflush(stdout); - - /* Set default color */ - Con_BgColor(0, 0); - Con_FgColor(7, 1); -} - -void Video_Configure(GXRModeObj *rmode) -{ - /* Configure the video subsystem */ - VIDEO_Configure(rmode); - - /* Setup video */ - VIDEO_SetBlack(FALSE); - VIDEO_Flush(); - VIDEO_WaitVSync(); - - if (rmode->viTVMode & VI_NON_INTERLACE) - VIDEO_WaitVSync(); -} - -void Video_SetMode(void) -{ - /* Select preferred video mode */ - vmode = VIDEO_GetPreferredMode(NULL); - - /* Allocate memory for the framebuffer */ - framebuffer = MEM_K0_TO_K1(SYS_AllocateFramebuffer(vmode)); - - /* Configure the video subsystem */ - VIDEO_Configure(vmode); - - /* Setup video */ - VIDEO_SetNextFramebuffer(framebuffer); - VIDEO_SetBlack(FALSE); - VIDEO_Flush(); - VIDEO_WaitVSync(); - - if (vmode->viTVMode & VI_NON_INTERLACE) - VIDEO_WaitVSync(); - - /* Clear the screen */ - Video_Clear(COLOR_BLACK); -} - -void Video_Clear(s32 color) -{ - VIDEO_ClearFrameBuffer(vmode, framebuffer, color); -} - -void Video_DrawPng(IMGCTX ctx, PNGUPROP imgProp, u16 x, u16 y) -{ - PNGU_DECODE_TO_COORDS_YCbYCr(ctx, x, y, imgProp.imgWidth, imgProp.imgHeight, vmode->fbWidth, vmode->xfbHeight, framebuffer); -} diff --git a/nand-loader/source/video.h b/nand-loader/source/video.h deleted file mode 100644 index 87c2fa9..0000000 --- a/nand-loader/source/video.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef _VIDEO_H_ -#define _VIDEO_H_ - -#include "pngu.h" - -/* Prototypes */ -void Con_Init(u32, u32, u32, u32); -void Con_Destroy(void); -void Con_Clear(void); -void Con_ClearLine(void); -void Con_FgColor(u32, u8); -void Con_BgColor(u32, u8); -void Con_FillRow(u32, u32, u8); - -void Video_Configure(GXRModeObj *); -void Video_SetMode(void); -void Video_Clear(s32); -void Video_DrawPng(IMGCTX, PNGUPROP, u16, u16); - -#endif diff --git a/nand-loader/source/wpad.c b/nand-loader/source/wpad.c deleted file mode 100644 index 8894fbb..0000000 --- a/nand-loader/source/wpad.c +++ /dev/null @@ -1,60 +0,0 @@ -#include -#include - -#include "sys.h" -#include "wpad.h" - -/* Constants */ -#define MAX_WIIMOTES 4 - - -s32 Wpad_Init(void) -{ - s32 ret; - - /* Initialize Wiimote subsystem */ - ret = WPAD_Init(); - if (ret < 0) - return ret; - - return ret; -} - -void Wpad_Disconnect(void) -{ - u32 cnt; - - /* Disconnect Wiimotes */ - for (cnt = 0; cnt < MAX_WIIMOTES; cnt++) - WPAD_Disconnect(cnt); - - /* Shutdown Wiimote subsystem */ - WPAD_Shutdown(); -} - -u32 Wpad_GetButtons(void) -{ - u32 buttons = 0, cnt; - - /* Scan pads */ - WPAD_ScanPads(); - - /* Get pressed buttons */ - for (cnt = 0; cnt < MAX_WIIMOTES; cnt++) - buttons |= WPAD_ButtonsDown(cnt); - - return buttons; -} - -u32 Wpad_WaitButtons(void) -{ - u32 buttons = 0; - - /* Wait for button pressing */ - while (!buttons) { - buttons = Wpad_GetButtons(); - VIDEO_WaitVSync(); - } - - return buttons; -} diff --git a/nand-loader/source/wpad.h b/nand-loader/source/wpad.h deleted file mode 100644 index 63053bb..0000000 --- a/nand-loader/source/wpad.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef _WPAD_H_ -#define _WPAD_H_ - -#include - -/* Prototypes */ -s32 Wpad_Init(void); -void Wpad_Disconnect(void); -u32 Wpad_GetButtons(void); -u32 Wpad_WaitButtons(void); - -#endif