mirror of
https://github.com/modmii/YAWM-ModMii-Edition.git
synced 2024-11-25 01:26:53 +01:00
- Added external app booter + code
- Added app load/launch code Notes: - Will add support for arguments later
This commit is contained in:
parent
167993c279
commit
0ed791842f
4
.gitignore
vendored
4
.gitignore
vendored
@ -3,3 +3,7 @@
|
||||
################################################################################
|
||||
|
||||
/.vs
|
||||
/source/boot/build/appboot.elf.map
|
||||
/source/boot/build
|
||||
/source/boot/appboot.elf
|
||||
/source/boot/appboot.dol
|
||||
|
6
Makefile
6
Makefile
@ -100,11 +100,13 @@ export OUTPUT := $(CURDIR)/$(TARGET)
|
||||
#---------------------------------------------------------------------------------
|
||||
$(BUILD):
|
||||
@[ -d $@ ] || mkdir -p $@
|
||||
@$(MAKE) --no-print-directory -s -C source/boot all
|
||||
@make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
clean:
|
||||
@echo clean ...
|
||||
@$(MAKE) --no-print-directory -s -C source/boot clean
|
||||
@rm -fr $(BUILD) $(OUTPUT).elf $(OUTPUT).dol
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
@ -139,6 +141,10 @@ $(OUTPUT).elf: $(OFILES)
|
||||
@echo $(notdir $<)
|
||||
$(bin2o)
|
||||
|
||||
%.bin.o : %.bin
|
||||
@echo $(notdir $<)
|
||||
$(bin2o)
|
||||
|
||||
-include $(DEPENDS)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
|
BIN
data/appboot.bin
Normal file
BIN
data/appboot.bin
Normal file
Binary file not shown.
93
source/appboot.c
Normal file
93
source/appboot.c
Normal file
@ -0,0 +1,93 @@
|
||||
#include <gccore.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ogc/machine/processor.h>
|
||||
#include <ogc/lwp_threads.h>
|
||||
|
||||
#include "fat.h"
|
||||
#include "sys.h"
|
||||
#include "wpad.h"
|
||||
|
||||
extern void __exception_closeall();
|
||||
|
||||
//struct __argv arguments;
|
||||
//char* m_argv[MAX_ARGV];
|
||||
//u8* m_Buffer = NULL;
|
||||
|
||||
u8* appBuffer = NULL;
|
||||
u32 appSize = 0;
|
||||
|
||||
typedef void (*entrypoint)();
|
||||
u32 appEntry = 0;
|
||||
|
||||
#include "appboot_bin.h"
|
||||
|
||||
static void Jump(entrypoint EntryPoint)
|
||||
{
|
||||
appEntry = (u32)EntryPoint;
|
||||
|
||||
u32 level = IRQ_Disable();
|
||||
__IOS_ShutdownSubsystems();
|
||||
__exception_closeall();
|
||||
__lwp_thread_closeall();
|
||||
asm volatile (
|
||||
"lis %r3, appEntry@h\n"
|
||||
"ori %r3, %r3, appEntry@l\n"
|
||||
"lwz %r3, 0(%r3)\n"
|
||||
"mtlr %r3\n"
|
||||
"blr\n"
|
||||
);
|
||||
IRQ_Restore(level);
|
||||
}
|
||||
|
||||
bool LoadApp(const char* path)
|
||||
{
|
||||
appBuffer = (u8*)0x92000000;
|
||||
|
||||
FILE* f = fopen(path, "rb");
|
||||
|
||||
if (f == NULL)
|
||||
return false;
|
||||
|
||||
fseek(f, 0, SEEK_END);
|
||||
u32 size = ftell(f);
|
||||
rewind(f);
|
||||
|
||||
if (size > 0x1000000)
|
||||
{
|
||||
fclose(f);
|
||||
return false;
|
||||
}
|
||||
|
||||
u32 ret = fread(appBuffer, 1, size, f);
|
||||
DCFlushRange(appBuffer, (size + 31) & (~31));
|
||||
|
||||
fclose(f);
|
||||
|
||||
return (ret == size);
|
||||
}
|
||||
|
||||
u8* GetApp(u32* size)
|
||||
{
|
||||
*size = appSize;
|
||||
return appBuffer;
|
||||
}
|
||||
|
||||
void LaunchApp(void)
|
||||
{
|
||||
entrypoint entry;
|
||||
|
||||
memcpy((u8*)0x93000000, appboot_bin, appboot_bin_size);
|
||||
DCFlushRange((u8*)0x93000000, appboot_bin_size);
|
||||
entry = (entrypoint)0x93000000;
|
||||
|
||||
u32 dumdum = 0;
|
||||
SYS_ResetSystem(SYS_SHUTDOWN, 0, 0);
|
||||
_CPU_ISR_Disable(dumdum);
|
||||
__exception_closeall();
|
||||
Jump(entry);
|
||||
_CPU_ISR_Restore(dumdum);
|
||||
|
||||
Sys_LoadMenu();
|
||||
}
|
8
source/appboot.h
Normal file
8
source/appboot.h
Normal file
@ -0,0 +1,8 @@
|
||||
#ifndef __APPBOOT_H__
|
||||
#define __APPBOOT_H__
|
||||
|
||||
bool LoadApp(const char* path);
|
||||
u8* GetApp(u32* size);
|
||||
void LaunchApp(void);
|
||||
|
||||
#endif
|
46
source/boot/Makefile
Normal file
46
source/boot/Makefile
Normal file
@ -0,0 +1,46 @@
|
||||
|
||||
PREFIX = $(DEVKITPPC)/bin/powerpc-eabi-
|
||||
|
||||
AR = $(PREFIX)ar
|
||||
AS = $(PREFIX)as
|
||||
CC = $(PREFIX)gcc
|
||||
CXX = $(PREFIX)g++
|
||||
LD = $(PREFIX)ld
|
||||
OBJCOPY = $(PREFIX)objcopy
|
||||
RANLIB = $(PREFIX)ranlib
|
||||
STRIP = $(PREFIX)strip
|
||||
|
||||
MACHDEP = -mcpu=750 -meabi -mhard-float
|
||||
CFLAGS = $(MACHDEP) -O0 -s -Werror -Wall -fdata-sections -ffunction-sections
|
||||
LDFLAGS = $(MACHDEP) -n -nostartfiles -nostdlib -Wl,--gc-sections,-T,openstub.ld -L.
|
||||
ASFLAGS = -D_LANGUAGE_ASSEMBLY -DHW_RVL
|
||||
|
||||
TARGET_LINKED = patcher.elf
|
||||
TARGET = ../../data/appboot.bin
|
||||
|
||||
CFILES = main.c utils.c loaddol.c loadelf.c
|
||||
OBJS = main.o utils.o loaddol.o loadelf.o
|
||||
|
||||
DEPDIR = .deps
|
||||
|
||||
LIBS =
|
||||
|
||||
all: $(TARGET)
|
||||
|
||||
%.o: %.s
|
||||
@$(CC) $(CFLAGS) $(DEFINES) $(ASFLAGS) -c $< -o $@
|
||||
|
||||
%.o: %.S
|
||||
@$(CC) $(CFLAGS) $(DEFINES) $(ASFLAGS) -c $< -o $@
|
||||
|
||||
%.o: %.c
|
||||
@$(CC) $(CFLAGS) $(DEFINES) -c $< -o $@
|
||||
|
||||
$(TARGET_LINKED): $(OBJS)
|
||||
@$(CC) -g -o $@ $(LDFLAGS) $(OBJS) $(LIBS)
|
||||
|
||||
$(TARGET): $(TARGET_LINKED)
|
||||
@$(OBJCOPY) -O binary -S $< $@
|
||||
|
||||
clean:
|
||||
@-$(RM) -rf $(TARGET_LINKED) $(OBJS) $(DEPDIR)
|
32
source/boot/loaddol.c
Normal file
32
source/boot/loaddol.c
Normal file
@ -0,0 +1,32 @@
|
||||
|
||||
#include "loaddol.h"
|
||||
|
||||
static void memcopy(void* address, void* buffer, u32 size)
|
||||
{
|
||||
_memcpy(address, buffer, size);
|
||||
sync_after_write(address, (size + 31) & (~31));
|
||||
}
|
||||
|
||||
u32 LoadDol(void* buffer)
|
||||
{
|
||||
u32 i;
|
||||
struct dolhdr* dol = (struct dolhdr*)buffer;
|
||||
|
||||
for (i = 0; i < 7; i++)
|
||||
{
|
||||
if (dol->sizeText[i] == 0)
|
||||
continue;
|
||||
|
||||
memcopy((void*)dol->addressText[i], buffer + dol->offsetText[i], dol->sizeText[i]);
|
||||
}
|
||||
|
||||
for (i = 0; i < 11; i++)
|
||||
{
|
||||
if (dol->sizeData[i] == 0)
|
||||
continue;
|
||||
|
||||
memcopy((void*)dol->addressData[i], buffer + dol->offsetData[i], dol->sizeData[i]);
|
||||
}
|
||||
|
||||
return dol->entrypoint;
|
||||
}
|
22
source/boot/loaddol.h
Normal file
22
source/boot/loaddol.h
Normal file
@ -0,0 +1,22 @@
|
||||
#ifndef __DOL_H__
|
||||
#define __DOL_H__
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
struct dolhdr
|
||||
{
|
||||
u32 offsetText[7];
|
||||
u32 offsetData[11];
|
||||
u32 addressText[7];
|
||||
u32 addressData[11];
|
||||
u32 sizeText[7];
|
||||
u32 sizeData[11];
|
||||
u32 addressBSS;
|
||||
u32 sizeBSS;
|
||||
u32 entrypoint;
|
||||
};
|
||||
|
||||
|
||||
u32 LoadDol(void* buffer);
|
||||
|
||||
#endif
|
52
source/boot/loadelf.c
Normal file
52
source/boot/loadelf.c
Normal file
@ -0,0 +1,52 @@
|
||||
|
||||
#include "loadelf.h"
|
||||
|
||||
bool ExecIsElf(void* address)
|
||||
{
|
||||
struct Elf32_Ehdr* ehdr = (struct Elf32_Ehdr*)address;
|
||||
|
||||
if (*(u8*)address + 0 != 0x7F || *(u8*)address + 1 != 'E' || *(u8*)address + 2 != 'L' || *(u8*)address + 3 != 'F')
|
||||
return false;
|
||||
|
||||
if (ehdr->e_type != 2) // Executable
|
||||
return false;
|
||||
|
||||
if (ehdr->e_machine != 20) // PowerPC
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
u32 LoadElf(void* address)
|
||||
{
|
||||
//u8* strtab = 0;
|
||||
//u8* image;
|
||||
int i;
|
||||
|
||||
struct Elf32_Ehdr* ehdr = (struct Elf32_Ehdr*)address;
|
||||
struct Elf32_Shdr* shdr = (struct Elf32_Shdr*)(address + ehdr->e_shoff + (ehdr->e_shstrndx * sizeof(struct Elf32_Shdr)));
|
||||
|
||||
//if (shdr->sh_type == SHT_STRTAB)
|
||||
// strtab = (u8*)(addr + shdr->sh_offset);
|
||||
|
||||
for (i = 0; i < ehdr->e_shnum; i++)
|
||||
{
|
||||
shdr = (struct Elf32_Shdr*)(address + ehdr->e_shoff + (i * sizeof(struct Elf32_Shdr)));
|
||||
|
||||
if (!(shdr->sh_flags & 0x02) || shdr->sh_addr == 0 || shdr->sh_size == 0)
|
||||
continue;
|
||||
|
||||
shdr->sh_addr &= 0x3FFFFFFF;
|
||||
shdr->sh_addr |= 0x80000000;
|
||||
|
||||
if (shdr->sh_type == 8)
|
||||
_memset32((void*)shdr->sh_addr, 0, shdr->sh_size);
|
||||
else
|
||||
_memcpy((void*)shdr->sh_addr, (void*)(address + shdr->sh_offset), shdr->sh_size);
|
||||
|
||||
sync_after_write((void*)shdr->sh_addr, (shdr->sh_size + 31) & (~31));
|
||||
|
||||
}
|
||||
|
||||
return (ehdr->e_entry & 0x3FFFFFFF) | 0x80000000;
|
||||
}
|
55
source/boot/loadelf.h
Normal file
55
source/boot/loadelf.h
Normal file
@ -0,0 +1,55 @@
|
||||
#ifndef __ELF_H__
|
||||
#define __ELF_H__
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
#define EI_NIDENT 16
|
||||
|
||||
struct Elf32_Ehdr
|
||||
{
|
||||
u8 e_ident[EI_NIDENT];
|
||||
u16 e_type;
|
||||
u16 e_machine;
|
||||
u32 e_version;
|
||||
u32 e_entry;
|
||||
u32 e_phoff;
|
||||
u32 e_shoff;
|
||||
u32 e_flags;
|
||||
u16 e_ehsize;
|
||||
u16 e_phentsize;
|
||||
u16 e_phnum;
|
||||
u16 e_shentsize;
|
||||
u16 e_shnum;
|
||||
u16 e_shstrndx;
|
||||
};
|
||||
|
||||
struct Elf32_Shdr
|
||||
{
|
||||
u32 sh_name;
|
||||
u32 sh_type;
|
||||
u32 sh_flags;
|
||||
u32 sh_addr;
|
||||
u32 sh_offset;
|
||||
u32 sh_size;
|
||||
u32 sh_link;
|
||||
u32 sh_info;
|
||||
u32 sh_addralign;
|
||||
u32 sh_entsize;
|
||||
};
|
||||
|
||||
struct Elf32_Phdr
|
||||
{
|
||||
u32 p_type;
|
||||
u32 p_offset;
|
||||
u32 p_vaddr;
|
||||
u32 p_paddr;
|
||||
u32 p_filesz;
|
||||
u32 p_memsz;
|
||||
u32 p_flags;
|
||||
u32 p_align;
|
||||
};
|
||||
|
||||
bool ExecIsElf(void* address);
|
||||
u32 LoadElf(void* address);
|
||||
|
||||
#endif
|
21
source/boot/main.c
Normal file
21
source/boot/main.c
Normal file
@ -0,0 +1,21 @@
|
||||
|
||||
#include "loaddol.h"
|
||||
#include "loadelf.h"
|
||||
|
||||
typedef void (*entrypoint)();
|
||||
|
||||
void _main(void)
|
||||
{
|
||||
void* buffer = (void*)0x92000000;
|
||||
entrypoint entry;
|
||||
|
||||
if (ExecIsElf(buffer))
|
||||
entry = (entrypoint)LoadElf(buffer);
|
||||
else
|
||||
entry = (entrypoint)LoadDol(buffer);
|
||||
|
||||
if (!entry)
|
||||
return;
|
||||
|
||||
entry();
|
||||
}
|
15
source/boot/openstub.ld
Normal file
15
source/boot/openstub.ld
Normal file
@ -0,0 +1,15 @@
|
||||
/*
|
||||
TinyLoad - a simple region free (original) game launcher in 4k
|
||||
|
||||
# This code is licensed to you under the terms of the GNU GPL, version 2;
|
||||
# see file COPYING or http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
|
||||
*/
|
||||
|
||||
OUTPUT_FORMAT("elf32-powerpc")
|
||||
OUTPUT_ARCH(powerpc:common)
|
||||
|
||||
ENTRY(_main)
|
||||
|
||||
SECTIONS {
|
||||
. = 0x93000000;
|
||||
}
|
77
source/boot/utils.c
Normal file
77
source/boot/utils.c
Normal file
@ -0,0 +1,77 @@
|
||||
#include "utils.h"
|
||||
|
||||
void sync_before_read(void *ptr, u32 len)
|
||||
{
|
||||
u32 a, b;
|
||||
|
||||
a = (u32)ptr & ~0x1f;
|
||||
b = ((u32)ptr + len + 0x1f) & ~0x1f;
|
||||
|
||||
for ( ; a < b; a += 32)
|
||||
asm("dcbi 0,%0" : : "b"(a) : "memory");
|
||||
|
||||
asm("sync ; isync");
|
||||
}
|
||||
|
||||
void sync_after_write(const void *ptr, u32 len)
|
||||
{
|
||||
u32 a, b;
|
||||
|
||||
a = (u32)ptr & ~0x1f;
|
||||
b = ((u32)ptr + len + 0x1f) & ~0x1f;
|
||||
|
||||
for ( ; a < b; a += 32)
|
||||
asm("dcbf 0,%0" : : "b"(a));
|
||||
|
||||
asm("sync ; isync");
|
||||
}
|
||||
|
||||
void _memcpy(void *ptr, const void *src, u32 size)
|
||||
{
|
||||
char *ptr2 = ptr;
|
||||
u32 bsize = size;
|
||||
const char* src2 = src;
|
||||
while(size--) *ptr2++ = *src2++;
|
||||
|
||||
sync_after_write(ptr, bsize);
|
||||
}
|
||||
|
||||
void _memset32(u32 *address, u32 data, u32 length)
|
||||
{
|
||||
while(length--)
|
||||
*address++ = data;
|
||||
}
|
||||
|
||||
int _memcmp(const void *s1, const void *s2, size_t n)
|
||||
{
|
||||
unsigned char *us1 = (unsigned char *) s1;
|
||||
unsigned char *us2 = (unsigned char *) s2;
|
||||
while(n-- != 0)
|
||||
{
|
||||
if (*us1 != *us2)
|
||||
return (*us1 < *us2) ? -1 : +1;
|
||||
us1++;
|
||||
us2++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t strnlen(const char *s, size_t count)
|
||||
{
|
||||
const char *sc;
|
||||
|
||||
for(sc = s; count-- && *sc != '\0'; ++sc)
|
||||
/* nothing */;
|
||||
return sc - s;
|
||||
}
|
||||
|
||||
inline void write32(u32 dest, u32 value)
|
||||
{
|
||||
*(u32*)dest = value;
|
||||
sync_after_write((void*)dest, 0x20);
|
||||
}
|
||||
|
||||
inline u32 read32(u32 src)
|
||||
{
|
||||
return *(u32*)src;
|
||||
}
|
46
source/boot/utils.h
Normal file
46
source/boot/utils.h
Normal file
@ -0,0 +1,46 @@
|
||||
#ifndef __UTILS_H__
|
||||
#define __UTILS_H__
|
||||
|
||||
typedef unsigned char u8;
|
||||
typedef unsigned char uint8_t;
|
||||
typedef unsigned short u16;
|
||||
typedef unsigned short uint16_t;
|
||||
typedef unsigned int u32;
|
||||
typedef unsigned long long u64;
|
||||
|
||||
typedef int bool;
|
||||
typedef unsigned int sec_t;
|
||||
|
||||
typedef signed char s8;
|
||||
typedef signed short s16;
|
||||
typedef signed int s32;
|
||||
typedef signed long long s64;
|
||||
|
||||
typedef volatile unsigned char vu8;
|
||||
typedef volatile unsigned short vu16;
|
||||
typedef volatile unsigned int vu32;
|
||||
typedef volatile unsigned long long vu64;
|
||||
|
||||
typedef volatile signed char vs8;
|
||||
typedef volatile signed short vs16;
|
||||
typedef volatile signed int vs32;
|
||||
typedef volatile signed long long vs64;
|
||||
|
||||
typedef s32 size_t;
|
||||
typedef u32 u_int32_t;
|
||||
|
||||
#define NULL ((void*)0)
|
||||
#define true 1
|
||||
#define false 0
|
||||
#define IsWiiU ((*(u32*)0xcd8005A0 >> 16 ) == 0xCAFE)
|
||||
|
||||
void sync_before_read(void* ptr, u32 len);
|
||||
void sync_after_write(const void* ptr, u32 len);
|
||||
void _memcpy(void *ptr, const void *src, u32 size);
|
||||
void _memset32(unsigned int *addr, unsigned int data, unsigned int count);
|
||||
int _memcmp(const void *s1, const void *s2, size_t n);
|
||||
size_t strnlen(const char *s, size_t count);
|
||||
void write32(u32 value, u32 dest);
|
||||
u32 read32(u32 src);
|
||||
|
||||
#endif
|
@ -30,6 +30,7 @@ int ReadConfigFile (char *configFilePath);
|
||||
int GetIntParam (char *inputStr);
|
||||
int GetStartupPath (char *startupPath, char *inputStr);
|
||||
int GetStringParam (char *outParam, char *inputStr, int maxChars);
|
||||
int LaunchApp(const char* path, bool external);
|
||||
|
||||
// Default password Up-Down-Left-Right-Up-Down
|
||||
//#define PASSWORD "UDLRUD"
|
||||
@ -215,7 +216,7 @@ int ReadConfigFile (char *configFilePath)
|
||||
fdev = &fdevList[2];
|
||||
ret = Fat_Mount(fdev);
|
||||
snprintf(path, sizeof(path), "%s%s", fdev->mount, configFilePath);
|
||||
snprintf(path, sizeof(path), "%s%s", fdev->mount, configFilePath);
|
||||
//snprintf(path, sizeof(path), "%s%s", fdev->mount, configFilePath);
|
||||
}
|
||||
|
||||
if (ret < 0)
|
||||
@ -237,7 +238,7 @@ int ReadConfigFile (char *configFilePath)
|
||||
{
|
||||
if (fgets (tmpStr, MAX_FILE_PATH_LEN, fptr) == NULL)
|
||||
done = 1;
|
||||
else if (isalpha(tmpStr[0]))
|
||||
else if (isalpha((int)tmpStr[0]))
|
||||
{
|
||||
// Get the password
|
||||
if (strncmp (tmpStr, "Password", 8) == 0)
|
||||
@ -378,14 +379,14 @@ int GetIntParam (char *inputStr)
|
||||
i++;
|
||||
|
||||
// Get to the first alpha numeric character
|
||||
while ((isdigit(inputStr [i]) == 0) && (i < len))
|
||||
while ((isdigit((int)inputStr[i]) == 0) && (i < len))
|
||||
{
|
||||
i++;
|
||||
}
|
||||
|
||||
// Get the string param
|
||||
int outCount = 0;
|
||||
while ((isdigit(inputStr [i])) && (i < len) && (outCount < 40))
|
||||
while ((isdigit((int)inputStr[i])) && (i < len) && (outCount < 40))
|
||||
{
|
||||
outParam [outCount++] = inputStr [i++];
|
||||
}
|
||||
@ -409,14 +410,14 @@ int GetStringParam (char *outParam, char *inputStr, int maxChars)
|
||||
i++;
|
||||
|
||||
// Get to the first alpha character
|
||||
while ((isalpha(inputStr [i]) == 0) && (i < len))
|
||||
while ((isalpha((int)inputStr[i]) == 0) && (i < len))
|
||||
{
|
||||
i++;
|
||||
}
|
||||
|
||||
// Get the string param
|
||||
int outCount = 0;
|
||||
while ((isalnum(inputStr [i])) && (i < len) && (outCount < maxChars))
|
||||
while ((isalnum((int)inputStr[i])) && (i < len) && (outCount < maxChars))
|
||||
{
|
||||
outParam [outCount++] = inputStr [i++];
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user