add Waninkoko nand-loader source

This commit is contained in:
Christopher Roy Bratusek 2012-12-08 20:53:27 +01:00
parent f66ea08af1
commit c2319b529d
31 changed files with 8463 additions and 0 deletions

136
nand-loader/Makefile Normal file
View File

@ -0,0 +1,136 @@
#---------------------------------------------------------------------------------
# Clear the implicit built in rules
#---------------------------------------------------------------------------------
.SUFFIXES:
DEVKITPRO = /opt/devkitPPC
DEVKITPPC = /opt/devkitPPC
#---------------------------------------------------------------------------------
ifeq ($(strip $(DEVKITPPC)),)
$(error "Please set DEVKITPPC in your environment. export DEVKITPPC=<path to>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 source/libpng/pngu
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 := $(CURDIR)
#---------------------------------------------------------------------------------
# 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
#---------------------------------------------------------------------------------

29
nand-loader/README.txt Executable file
View File

@ -0,0 +1,29 @@
+---------------------------------+
| [+] 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.

BIN
nand-loader/data/background Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

BIN
nand-loader/data/error Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

BIN
nand-loader/data/loading Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

BIN
nand-loader/lib/libpng.a Normal file

Binary file not shown.

345
nand-loader/rvl.ld Normal file
View File

@ -0,0 +1,345 @@
/*
* 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);

93
nand-loader/source/asm.h Normal file
View File

@ -0,0 +1,93 @@
#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

219
nand-loader/source/config.c Normal file
View File

@ -0,0 +1,219 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ogcsys.h>
#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 },
};
/* 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();
}

View File

@ -0,0 +1,25 @@
#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;
};
/* NANDLoader configuration */
extern struct config loaderCfg;
/* Prototypes */
s32 Config_Read(void);
s32 Config_Write(void);
void Config_Menu(void);
#endif

87
nand-loader/source/gui.c Normal file
View File

@ -0,0 +1,87 @@
#include <stdio.h>
#include <stdlib.h>
#include <ogcsys.h>
#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);
}

10
nand-loader/source/gui.h Normal file
View File

@ -0,0 +1,10 @@
#ifndef _GUI_H_
#define _GUI_H_
/* Prototypes */
void Gui_InitConsole(void);
void Gui_DrawBackground(void);
void Gui_DrawLoading(void);
void Gui_DrawError(void);
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,171 @@
/********************************************************************************************
PNGU Version : 0.2a
Coder : frontier
More info : http://frontier-dev.net
********************************************************************************************/
#ifndef __PNGU__
#define __PNGU__
// Return codes
#define PNGU_OK 0
#define PNGU_ODD_WIDTH 1
#define PNGU_ODD_STRIDE 2
#define PNGU_INVALID_WIDTH_OR_HEIGHT 3
#define PNGU_FILE_IS_NOT_PNG 4
#define PNGU_UNSUPPORTED_COLOR_TYPE 5
#define PNGU_NO_FILE_SELECTED 6
#define PNGU_CANT_OPEN_FILE 7
#define PNGU_CANT_READ_FILE 8
#define PNGU_LIB_ERROR 9
// Color types
#define PNGU_COLOR_TYPE_GRAY 1
#define PNGU_COLOR_TYPE_GRAY_ALPHA 2
#define PNGU_COLOR_TYPE_PALETTE 3
#define PNGU_COLOR_TYPE_RGB 4
#define PNGU_COLOR_TYPE_RGB_ALPHA 5
#define PNGU_COLOR_TYPE_UNKNOWN 6
#ifdef __cplusplus
extern "C" {
#endif
// Types
typedef unsigned char PNGU_u8;
typedef unsigned short PNGU_u16;
typedef unsigned int PNGU_u32;
typedef unsigned long long PNGU_u64;
typedef struct
{
PNGU_u8 r;
PNGU_u8 g;
PNGU_u8 b;
} PNGUCOLOR;
typedef struct
{
PNGU_u32 imgWidth; // In pixels
PNGU_u32 imgHeight; // In pixels
PNGU_u32 imgBitDepth; // In bitx
PNGU_u32 imgColorType; // PNGU_COLOR_TYPE_*
PNGU_u32 validBckgrnd; // Non zero if there is a background color
PNGUCOLOR bckgrnd; // Backgroun color
PNGU_u32 numTrans; // Number of transparent colors
PNGUCOLOR *trans; // Transparent colors
} PNGUPROP;
// Image context, always initialize with SelectImageFrom* and free with ReleaseImageContext
struct _IMGCTX;
typedef struct _IMGCTX *IMGCTX;
/****************************************************************************
* Pixel conversion *
****************************************************************************/
// Macro to convert RGB8 values to RGB565
#define PNGU_RGB8_TO_RGB565(r,g,b) ( ((((PNGU_u16) r) & 0xF8U) << 8) | ((((PNGU_u16) g) & 0xFCU) << 3) | (((PNGU_u16) b) >> 3) )
// Macro to convert RGBA8 values to RGB5A3
#define PNGU_RGB8_TO_RGB5A3(r,g,b,a) (PNGU_u16) (((a & 0xE0U) == 0xE0U) ? \
(0x8000U | ((((PNGU_u16) r) & 0xF8U) << 7) | ((((PNGU_u16) g) & 0xF8U) << 2) | (((PNGU_u16) b) >> 3)) : \
(((((PNGU_u16) a) & 0xE0U) << 7) | ((((PNGU_u16) r) & 0xF0U) << 4) | (((PNGU_u16) g) & 0xF0U) | ((((PNGU_u16) b) & 0xF0U) >> 4)))
// Function to convert two RGB8 values to YCbYCr
PNGU_u32 PNGU_RGB8_TO_YCbYCr (PNGU_u8 r1, PNGU_u8 g1, PNGU_u8 b1, PNGU_u8 r2, PNGU_u8 g2, PNGU_u8 b2);
// Function to convert an YCbYCr to two RGB8 values.
void PNGU_YCbYCr_TO_RGB8 (PNGU_u32 ycbycr, PNGU_u8 *r1, PNGU_u8 *g1, PNGU_u8 *b1, PNGU_u8 *r2, PNGU_u8 *g2, PNGU_u8 *b2);
/****************************************************************************
* Image context handling *
****************************************************************************/
// Selects a PNG file, previosly loaded into a buffer, and creates an image context for subsequent procesing.
IMGCTX PNGU_SelectImageFromBuffer (const void *buffer);
// Selects a PNG file, from any devoptab device, and creates an image context for subsequent procesing.
IMGCTX PNGU_SelectImageFromDevice (const char *filename);
// Frees resources associated with an image context. Always call this function when you no longer need the IMGCTX.
void PNGU_ReleaseImageContext (IMGCTX ctx);
/****************************************************************************
* Miscelaneous *
****************************************************************************/
// Retrieves info from selected PNG file, including image dimensions, color format, background and transparency colors.
int PNGU_GetImageProperties (IMGCTX ctx, PNGUPROP *fileproperties);
/****************************************************************************
* Image conversion *
****************************************************************************/
// Expands selected image into an YCbYCr buffer. You need to specify context, image dimensions,
// destination address and stride in pixels (stride = buffer width - image width).
int PNGU_DecodeToYCbYCr (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer, PNGU_u32 stride);
// Macro for decoding an image inside a buffer at given coordinates.
#define PNGU_DECODE_TO_COORDS_YCbYCr(ctx,coordX,coordY,imgWidth,imgHeight,bufferWidth,bufferHeight,buffer) \
\
PNGU_DecodeToYCbYCr (ctx, imgWidth, imgHeight, ((void *) buffer) + (coordY) * (bufferWidth) * 2 + \
(coordX) * 2, (bufferWidth) - (imgWidth))
// Expands selected image into a linear RGB565 buffer. You need to specify context, image dimensions,
// destination address and stride in pixels (stride = buffer width - image width).
int PNGU_DecodeToRGB565 (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer, PNGU_u32 stride);
// Macro for decoding an image inside a buffer at given coordinates.
#define PNGU_DECODE_TO_COORDS_RGB565(ctx,coordX,coordY,imgWidth,imgHeight,bufferWidth,bufferHeight,buffer) \
\
PNGU_DecodeToRGB565 (ctx, imgWidth, imgHeight, ((void *) buffer) + (coordY) * (bufferWidth) * 2 + \
(coordX) * 2, (bufferWidth) - (imgWidth))
// Expands selected image into a linear RGBA8 buffer. You need to specify context, image dimensions,
// destination address, stride in pixels and default alpha value, which is used if the source image
// doesn't have an alpha channel.
int PNGU_DecodeToRGBA8 (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer, PNGU_u32 stride, PNGU_u8 default_alpha);
// Macro for decoding an image inside a buffer at given coordinates.
#define PNGU_DECODE_TO_COORDS_RGBA8(ctx,coordX,coordY,imgWidth,imgHeight,default_alpha,bufferWidth,bufferHeight,buffer) \
\
PNGU_DecodeToRGBA8 (ctx, imgWidth, imgHeight, ((void *) buffer) + (coordY) * (bufferWidth) * 2 + \
(coordX) * 2, (bufferWidth) - (imgWidth), default_alpha)
// Expands selected image into a 4x4 tiled RGB565 buffer. You need to specify context, image dimensions
// and destination address.
int PNGU_DecodeTo4x4RGB565 (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer);
// Expands selected image into a 4x4 tiled RGB5A3 buffer. You need to specify context, image dimensions,
// destination address and default alpha value, which is used if the source image doesn't have an alpha channel.
int PNGU_DecodeTo4x4RGB5A3 (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer, PNGU_u8 default_alpha);
// Expands selected image into a 4x4 tiled RGBA8 buffer. You need to specify context, image dimensions,
// destination address and default alpha value, which is used if the source image doesn't have an alpha channel.
int PNGU_DecodeTo4x4RGBA8 (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer, PNGU_u8 default_alpha);
// Encodes an YCbYCr image in PNG format and stores it in the selected device or memory buffer. You need to
// specify context, image dimensions, destination address and stride in pixels (stride = buffer width - image width).
int PNGU_EncodeFromYCbYCr (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer, PNGU_u32 stride);
// Macro for encoding an image stored into an YCbYCr buffer at given coordinates.
#define PNGU_ENCODE_TO_COORDS_YCbYCr(ctx,coordX,coordY,imgWidth,imgHeight,bufferWidth,bufferHeight,buffer) \
\
PNGU_EncodeFromYCbYCr (ctx, imgWidth, imgHeight, ((void *) buffer) + (coordY) * (bufferWidth) * 2 + \
(coordX) * 2, (bufferWidth) - (imgWidth))
#ifdef __cplusplus
}
#endif
#endif

246
nand-loader/source/loader.c Normal file
View File

@ -0,0 +1,246 @@
#include <stdio.h>
#include <string.h>
#include <ogcsys.h>
#include "config.h"
#include "patches.h"
#include "video.h"
#include "wpad.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 *)(0x80000000), 0x3F00);
}
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);
}
}
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;
}

View File

@ -0,0 +1,8 @@
#ifndef _LOADER_H_
#define _LOADER_H_
/* Prototypes */
s32 Loader_Execute(void);
#endif

View File

@ -0,0 +1,78 @@
#include <stdio.h>
#include <unistd.h>
#include <ogcsys.h>
#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 */
Gui_DrawLoading();
/* Execute application */
Loader_Execute();
/* Draw error image */
Gui_DrawError();
/* Sleep */
sleep(RESTART_SECONDS);
/* Load System Menu */
Sys_LoadMenu();
return 0;
}

View File

@ -0,0 +1,126 @@
#include <stdio.h>
#include <string.h>
#include <ogcsys.h>
#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);
// }
// }

View File

@ -0,0 +1,7 @@
#ifndef _PATCHES_H_
#define _PATCHES_H_
/* Prototypes */
void Patch_VideoMode(u8 *, u32);
#endif

118
nand-loader/source/stub.S Normal file
View File

@ -0,0 +1,118 @@
.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

48
nand-loader/source/sys.c Normal file
View File

@ -0,0 +1,48 @@
#include <stdio.h>
#include <stdlib.h>
#include <ogcsys.h>
/* 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;
}

9
nand-loader/source/sys.h Normal file
View File

@ -0,0 +1,9 @@
#ifndef _SYS_H_
#define _SYS_H_
/* Prototypes */
void Sys_Init(void);
void Sys_LoadMenu(void);
s32 Sys_GetCerts(signed_blob **, u32 *);
#endif

256
nand-loader/source/title.c Executable file
View File

@ -0,0 +1,256 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
#include <ogcsys.h>
#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;
}

16
nand-loader/source/title.h Executable file
View File

@ -0,0 +1,16 @@
#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

View File

@ -0,0 +1,15 @@
#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

147
nand-loader/source/video.c Normal file
View File

@ -0,0 +1,147 @@
#include <stdio.h>
#include <ogcsys.h>
#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);
}

View File

@ -0,0 +1,20 @@
#ifndef _VIDEO_H_
#define _VIDEO_H_
#include "libpng/pngu/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

60
nand-loader/source/wpad.c Normal file
View File

@ -0,0 +1,60 @@
#include <stdio.h>
#include <ogcsys.h>
#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;
}

12
nand-loader/source/wpad.h Normal file
View File

@ -0,0 +1,12 @@
#ifndef _WPAD_H_
#define _WPAD_H_
#include <wiiuse/wpad.h>
/* Prototypes */
s32 Wpad_Init(void);
void Wpad_Disconnect(void);
u32 Wpad_GetButtons(void);
u32 Wpad_WaitButtons(void);
#endif