- Added support for arguments in app launch code

- Added XML stuff to parse the meta.xml file

Notes:
- To build.. this now requires the mxml lib
This commit is contained in:
0verjoY 2022-07-21 23:29:45 +02:00
parent da653aee36
commit 40ba5db3b3
8 changed files with 263 additions and 17 deletions

View File

@ -36,7 +36,7 @@ LDFLAGS = $(MACHDEP) -Wl,-Map,$(notdir $@).map
#---------------------------------------------------------------------------------
# any extra libraries we wish to link with the project
#---------------------------------------------------------------------------------
LIBS := -ltinysmb -lpng -lfat -lwiidrc -lwiiuse -lbte -logc -lm -lz -lwiilight
LIBS := -lmxml -ltinysmb -lpng -lfat -lwiidrc -lwiiuse -lbte -logc -lm -lz -lwiilight
#---------------------------------------------------------------------------------
# list of directories containing libraries, this must be the top level containing

Binary file not shown.

View File

@ -2,18 +2,21 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
#include <ogc/machine/processor.h>
#include <ogc/lwp_threads.h>
#include "fat.h"
#include "sys.h"
#include "wpad.h"
#include "appmetadata.h"
extern void __exception_closeall();
//struct __argv arguments;
//char* m_argv[MAX_ARGV];
//u8* m_Buffer = NULL;
struct __argv arguments;
char* m_argv[256];
u8* metaBuffer = NULL;
u32 metaSize = 0;
u8* appBuffer = NULL;
u32 appSize = 0;
@ -45,27 +48,48 @@ bool LoadApp(const char* path)
{
appBuffer = (u8*)0x92000000;
FILE* f = fopen(path, "rb");
char currentPath[256];
snprintf(currentPath, sizeof(currentPath), "%s/boot.dol", path);
FILE* f = fopen(currentPath, "rb");
if (f == NULL)
return false;
{
snprintf(currentPath, sizeof(currentPath), "%s/boot.elf", path);
f = fopen(currentPath, "rb");
if (f == NULL)
return false;
}
fseek(f, 0, SEEK_END);
u32 size = ftell(f);
appSize = ftell(f);
rewind(f);
if (size > 0x1000000)
if (appSize > 0x1000000)
{
fclose(f);
return false;
}
u32 ret = fread(appBuffer, 1, size, f);
DCFlushRange(appBuffer, (size + 31) & (~31));
u32 ret = fread(appBuffer, 1, appSize, f);
DCFlushRange(appBuffer, (appSize + 31) & (~31));
fclose(f);
return (ret == size);
snprintf(currentPath, sizeof(currentPath), "%s/meta.xml", path);
u16 argumentsSize = 0;
char* Arguments = LoadArguments(currentPath, &argumentsSize);
if (Arguments)
{
*(vu32*)0x91000000 = argumentsSize;
memcpy((void*)0x91000020, Arguments, argumentsSize);
DCFlushRange((u8*)0x91000020, argumentsSize);
free(Arguments);
}
return (ret == appSize);
}
u8* GetApp(u32* size)

180
source/appmetadata.c Normal file
View File

@ -0,0 +1,180 @@
#include <mxml.h>
#include <malloc.h>
#include <string.h>
#include "appmetadata.h"
static char* GetStringValue(mxml_node_t* node, const char* element)
{
mxml_node_t* elementNode = mxmlFindElement(node, node, element, NULL, NULL, MXML_DESCEND_FIRST);
if (elementNode)
{
mxml_node_t* current = elementNode->child;
while (current && current->type != MXML_OPAQUE)
current = mxmlWalkNext(current, elementNode, MXML_NO_DESCEND);
if (current->type == MXML_OPAQUE)
return current->value.opaque;
}
return NULL;
}
static char* GetArgumentValue(mxml_node_t* node)
{
if (node)
{
mxml_node_t* current = node->child;
while (current && current->type != MXML_OPAQUE)
current = mxmlWalkNext(current, node, MXML_NO_DESCEND);
if (current->type == MXML_OPAQUE)
return current->value.opaque;
}
return NULL;
}
struct MetaData* LoadMetaData(const char* path)
{
FILE* f = fopen(path, "rb");
if (f == NULL)
return NULL;
mxml_node_t* meta = mxmlLoadFile(NULL, f, MXML_OPAQUE_CALLBACK);
fclose(f);
if (!meta)
return NULL;
mxml_node_t* app = mxmlFindElement(meta, meta, "app", NULL, NULL, MXML_DESCEND_FIRST);
if (!app)
{
mxmlDelete(meta);
return NULL;
}
struct MetaData* metaData = (struct MetaData*)malloc(sizeof(struct MetaData));
if (!metaData)
{
mxmlDelete(meta);
return NULL;
}
memset(metaData, 0, sizeof(struct MetaData));
metaData->name = strdup(GetStringValue(app, "name"));
metaData->coder = strdup(GetStringValue(app, "coder"));
metaData->version = strdup(GetStringValue(app, "version"));
metaData->shortDescription = strdup(GetStringValue(app, "short_description"));
metaData->longDescription = strdup(GetStringValue(app, "long_description"));
char release[40];
memset(release, 0, sizeof(release));
snprintf(release, sizeof(release), "%s", GetStringValue(app, "release_date"));
if (strlen(release) == 14)
snprintf(release, sizeof(release), "%c%c/%c%c/%c%c%c%c", release[4], release[5], release[6], release[7], release[0], release[1], release[2], release[3]);
else if (strlen(release) == 14)
snprintf(release, sizeof(release), "%c%c/%c%c%c%c", release[4], release[5], release[0], release[1], release[2], release[3]);
metaData->releaseDate = strdup(release);
mxmlDelete(meta);
return metaData;
}
void FreeMetaData(struct MetaData* metaData)
{
free(metaData->name);
free(metaData->coder);
free(metaData->version);
free(metaData->shortDescription);
free(metaData->longDescription);
free(metaData->releaseDate);
free(metaData);
}
char* LoadArguments(const char* path, u16* length)
{
FILE* f = fopen(path, "rb");
if (f == NULL)
return NULL;
mxml_node_t* meta = mxmlLoadFile(NULL, f, MXML_OPAQUE_CALLBACK);
fclose(f);
if (!meta)
return NULL;
mxml_node_t* app = mxmlFindElement(meta, meta, "app", NULL, NULL, MXML_DESCEND_FIRST);
if (!app)
{
mxmlDelete(meta);
return NULL;
}
app = mxmlFindElement(app, app, "arguments", NULL, NULL, MXML_DESCEND_FIRST);
if (!app)
{
mxmlDelete(meta);
return NULL;
}
mxml_node_t* arg;
u16 size = 0;
for (arg = mxmlFindElement(app, app, "arg", NULL, NULL, MXML_DESCEND_FIRST); arg != NULL; arg = mxmlFindElement(arg, app, "arg", NULL, NULL, MXML_NO_DESCEND))
{
char* current = GetArgumentValue(arg);
if (current)
{
if (size > 0)
size++;
size += strlen(current);
}
}
if (size == 0 || size > 1024)
{
mxmlDelete(meta);
return NULL;
}
size++;
char* argStr = malloc(size);
size = 0;
for (arg = mxmlFindElement(app, app, "arg", NULL, NULL, MXML_DESCEND_FIRST); arg != NULL; arg = mxmlFindElement(arg, app, "arg", NULL, NULL, MXML_NO_DESCEND))
{
char* current = GetArgumentValue(arg);
if (current)
{
if (size > 0)
{
argStr[size] = 0;
size++;
}
strcpy(argStr + size, current);
size += strlen(current);
}
}
argStr[size] = 0;
*length = size;
return argStr;
}

20
source/appmetadata.h Normal file
View File

@ -0,0 +1,20 @@
#ifndef __APPMETADATA_H__
#define __APPMETADATA_H__
#include <gctypes.h>
struct MetaData
{
char* name;
char* coder;
char* version;
char* shortDescription;
char* longDescription;
char* releaseDate;
};
struct MetaData* LoadMetaData(const char* path);
void FreeMetaData(struct MetaData* metaData);
char* LoadArguments(const char* path, u16* length);
#endif

View File

@ -19,16 +19,11 @@ bool ExecIsElf(void* address)
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)));

View File

@ -1,6 +1,7 @@
#include "loaddol.h"
#include "loadelf.h"
#include "utils.h"
typedef void (*entrypoint)();
@ -9,6 +10,8 @@ void _main(void)
void* buffer = (void*)0x92000000;
entrypoint entry;
u32 argumentsSize = *(vu32*)0x91000000;
if (ExecIsElf(buffer))
entry = (entrypoint)LoadElf(buffer);
else
@ -17,5 +20,21 @@ void _main(void)
if (!entry)
return;
if (argumentsSize > 0)
{
u32* ptr = (u32*)entry;
if (ptr[1] == 0x5F617267)
{
struct Arguments* argv = (struct Arguments*)&ptr[2];
argv->magic = 0x5F617267;
argv->cmdLine = (char*)0x91000020;
argv->length = argumentsSize;
sync_after_write(&ptr[2], 4);
}
}
entry();
}

View File

@ -29,6 +29,14 @@ typedef volatile signed long long vs64;
typedef s32 size_t;
typedef u32 u_int32_t;
struct Arguments
{
int magic;
char* cmdLine;
int length;
};
#define NULL ((void*)0)
#define true 1
#define false 0