mirror of
https://gitlab.com/Nanolx/homebrewfilter.git
synced 2025-02-04 11:56:34 +01:00
added HBF-Installer to GIT
This commit is contained in:
parent
4cd74c3b37
commit
c271b85907
137
installer/Makefile
Normal file
137
installer/Makefile
Normal file
@ -0,0 +1,137 @@
|
||||
#---------------------------------------------------------------------------------
|
||||
# Clear the implicit built in rules
|
||||
#---------------------------------------------------------------------------------
|
||||
.SUFFIXES:
|
||||
#---------------------------------------------------------------------------------
|
||||
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 := boot
|
||||
BUILD := build
|
||||
SOURCES := source \
|
||||
source/Network \
|
||||
../svnrev
|
||||
DATA := data
|
||||
INCLUDES :=
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# options for code generation
|
||||
#---------------------------------------------------------------------------------
|
||||
|
||||
CFLAGS = -g -O2 -Wall $(MACHDEP) $(INCLUDE)
|
||||
CXXFLAGS = $(CFLAGS)
|
||||
|
||||
LDFLAGS = -g $(MACHDEP) -Wl,-Map,$(notdir $@).map
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# any extra libraries we wish to link with the project
|
||||
#---------------------------------------------------------------------------------
|
||||
LIBS := -lwiiuse -lbte -logc -lm
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# 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 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)/*.*)))
|
||||
WADFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.wad*)))
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# 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).dol
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
run:
|
||||
wiiload $(TARGET).dol
|
||||
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
else
|
||||
|
||||
DEPENDS := $(OFILES:.o=.d)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# main targets
|
||||
#---------------------------------------------------------------------------------
|
||||
$(OUTPUT).dol: $(OUTPUT).elf
|
||||
$(OUTPUT).elf: $(OFILES)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# This rule links in binary data with extension
|
||||
#---------------------------------------------------------------------------------
|
||||
%.wad.o : %.wad
|
||||
@echo $(notdir $<)
|
||||
@bin2s -a 32 $< | $(AS) -o $(@)
|
||||
|
||||
-include $(DEPENDS)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
endif
|
||||
#---------------------------------------------------------------------------------
|
BIN
installer/WadMii.exe
Normal file
BIN
installer/WadMii.exe
Normal file
Binary file not shown.
122
installer/source/Network/dns.c
Normal file
122
installer/source/Network/dns.c
Normal file
@ -0,0 +1,122 @@
|
||||
#include "dns.h"
|
||||
|
||||
/**
|
||||
* Resolves a domainname to an ip address
|
||||
* It makes use of net_gethostbyname from libogc, which in turn makes use of a Wii BIOS function
|
||||
* Just like the net_gethostbyname function this function is NOT threadsafe!
|
||||
*
|
||||
* @param char* The domain name to resolve
|
||||
* @return u32 The ipaddress represented by four bytes inside an u32 (in network order)
|
||||
*/
|
||||
u32 getipbyname(char *domain)
|
||||
{
|
||||
//Care should be taken when using net_gethostbyname,
|
||||
//it returns a static buffer which makes it not threadsafe
|
||||
//TODO: implement some locking mechanism to make below code atomic
|
||||
struct hostent *host = net_gethostbyname(domain);
|
||||
|
||||
if(host == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 *ip = (u32*)host->h_addr_list[0];
|
||||
return *ip;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//Defines how many DNS entries should be cached by getipbynamecached()
|
||||
#define MAX_DNS_CACHE_ENTRIES 20
|
||||
|
||||
//The cache is defined as a linked list,
|
||||
//The last resolved domain name will always be at the front
|
||||
//This will allow heavily used domainnames to always stay cached
|
||||
struct dnsentry {
|
||||
char *domain;
|
||||
u32 ip;
|
||||
struct dnsentry *nextnode;
|
||||
} ;
|
||||
|
||||
static struct dnsentry *firstdnsentry = NULL;
|
||||
static int dnsentrycount = 0;
|
||||
|
||||
/**
|
||||
* Performs the same function as getipbyname(),
|
||||
* except that it will prevent extremely expensive net_gethostbyname() calls by caching the result
|
||||
*/
|
||||
u32 getipbynamecached(char *domain)
|
||||
{
|
||||
//Search if this domainname is already cached
|
||||
struct dnsentry *node = firstdnsentry;
|
||||
struct dnsentry *previousnode = NULL;
|
||||
|
||||
while(node != NULL)
|
||||
{
|
||||
if(strcmp(node->domain, domain) == 0)
|
||||
{
|
||||
//DNS node found in the cache, move it to the front of the list
|
||||
if(previousnode != NULL)
|
||||
previousnode->nextnode = node->nextnode;
|
||||
|
||||
if(node != firstdnsentry)
|
||||
node->nextnode = firstdnsentry;
|
||||
firstdnsentry = node;
|
||||
|
||||
return node->ip;
|
||||
}
|
||||
//Go to the next element in the list
|
||||
previousnode = node;
|
||||
node = node->nextnode;
|
||||
}
|
||||
u32 ip = getipbyname(domain);
|
||||
|
||||
//No cache of this domain could be found, create a cache node and add it to the front of the cache
|
||||
struct dnsentry *newnode = malloc(sizeof(struct dnsentry));
|
||||
if(newnode == NULL) {
|
||||
return ip;
|
||||
}
|
||||
|
||||
newnode->ip = ip;
|
||||
newnode->domain = malloc(strlen(domain)+1);
|
||||
if(newnode->domain == NULL)
|
||||
{
|
||||
free(newnode);
|
||||
return ip;
|
||||
}
|
||||
strcpy(newnode->domain, domain);
|
||||
|
||||
newnode->nextnode = firstdnsentry;
|
||||
firstdnsentry = newnode;
|
||||
dnsentrycount++;
|
||||
|
||||
//If the cache grows too big delete the last (and probably least important) node of the list
|
||||
if(dnsentrycount > MAX_DNS_CACHE_ENTRIES)
|
||||
{
|
||||
struct dnsentry *node = firstdnsentry;
|
||||
struct dnsentry *previousnode = NULL;
|
||||
|
||||
//Fetch the last two elements of the list
|
||||
while(node->nextnode != NULL)
|
||||
{
|
||||
previousnode = node;
|
||||
node = node->nextnode;
|
||||
}
|
||||
|
||||
if(node == NULL)
|
||||
{
|
||||
printf("Configuration error, MAX_DNS_ENTRIES reached while the list is empty\n");
|
||||
exit(1);
|
||||
} else if(previousnode == NULL)
|
||||
{
|
||||
firstdnsentry = NULL;
|
||||
} else {
|
||||
previousnode->nextnode = NULL;
|
||||
}
|
||||
|
||||
free(node->domain);
|
||||
free(node);
|
||||
dnsentrycount--;
|
||||
}
|
||||
|
||||
return newnode->ip;
|
||||
}
|
23
installer/source/Network/dns.h
Normal file
23
installer/source/Network/dns.h
Normal file
@ -0,0 +1,23 @@
|
||||
#ifndef _DNS_H_
|
||||
#define _DNS_H_
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h> //usleep
|
||||
|
||||
#include <network.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
u32 getipbyname(char *domain);
|
||||
u32 getipbynamecached(char *domain);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _DNS_H_ */
|
256
installer/source/Network/http.c
Normal file
256
installer/source/Network/http.c
Normal file
@ -0,0 +1,256 @@
|
||||
#include "http.h"
|
||||
|
||||
/**
|
||||
* Emptyblock is a statically defined variable for functions to return if they are unable
|
||||
* to complete a request
|
||||
*/
|
||||
const struct block emptyblock = {0, NULL};
|
||||
|
||||
//The maximum amount of bytes to send per net_write() call
|
||||
#define NET_BUFFER_SIZE 1024
|
||||
|
||||
// Write our message to the server
|
||||
static s32 send_message(s32 server, char *msg) {
|
||||
s32 bytes_transferred = 0;
|
||||
s32 remaining = strlen(msg);
|
||||
while (remaining) {
|
||||
if ((bytes_transferred = net_write(server, msg, remaining > NET_BUFFER_SIZE ? NET_BUFFER_SIZE : remaining)) > 0) {
|
||||
remaining -= bytes_transferred;
|
||||
usleep (20 * 1000);
|
||||
} else if (bytes_transferred < 0) {
|
||||
return bytes_transferred;
|
||||
} else {
|
||||
return -ENODATA;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Connect to a remote server via TCP on a specified port
|
||||
*
|
||||
* @param u32 ip address of the server to connect to
|
||||
* @param u32 the port to connect to on the server
|
||||
* @return s32 The connection to the server (negative number if connection could not be established)
|
||||
*/
|
||||
static s32 server_connect(u32 ipaddress, u32 socket_port) {
|
||||
//Initialize socket
|
||||
s32 connection = net_socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
|
||||
if (connection < 0) return connection;
|
||||
|
||||
struct sockaddr_in connect_addr;
|
||||
memset(&connect_addr, 0, sizeof(connect_addr));
|
||||
connect_addr.sin_family = AF_INET;
|
||||
connect_addr.sin_port = socket_port;
|
||||
connect_addr.sin_addr.s_addr= ipaddress;
|
||||
|
||||
//Attemt to open the socket
|
||||
if (net_connect(connection, (struct sockaddr*)&connect_addr, sizeof(connect_addr)) == -1) {
|
||||
net_close(connection);
|
||||
return -1;
|
||||
}
|
||||
return connection;
|
||||
}
|
||||
|
||||
//The amount of memory in bytes reserved initially to store the HTTP response in
|
||||
//Be careful in increasing this number, reading from a socket on the Wii
|
||||
//will fail if you request more than 20k or so
|
||||
#define HTTP_BUFFER_SIZE 1024 * 5
|
||||
|
||||
//The amount of memory the buffer should expanded with if the buffer is full
|
||||
#define HTTP_BUFFER_GROWTH 1024 * 5
|
||||
|
||||
/**
|
||||
* This function reads all the data from a connection into a buffer which it returns.
|
||||
* It will return an empty buffer if something doesn't go as planned
|
||||
*
|
||||
* @param s32 connection The connection identifier to suck the response out of
|
||||
* @return block A 'block' struct (see http.h) in which the buffer is located
|
||||
*/
|
||||
struct block read_message(s32 connection)
|
||||
{
|
||||
//Create a block of memory to put in the response
|
||||
struct block buffer;
|
||||
buffer.data = malloc(HTTP_BUFFER_SIZE);
|
||||
buffer.size = HTTP_BUFFER_SIZE;
|
||||
|
||||
if(buffer.data == NULL) {
|
||||
return emptyblock;
|
||||
}
|
||||
|
||||
//The offset variable always points to the first byte of memory that is free in the buffer
|
||||
u32 offset = 0;
|
||||
|
||||
while(1)
|
||||
{
|
||||
//Fill the buffer with a new batch of bytes from the connection,
|
||||
//starting from where we left of in the buffer till the end of the buffer
|
||||
s32 bytes_read = net_read(connection, buffer.data + offset, buffer.size - offset);
|
||||
|
||||
//Anything below 0 is an error in the connection
|
||||
if(bytes_read < 0)
|
||||
{
|
||||
//printf("Connection error from net_read() Errorcode: %i\n", bytes_read);
|
||||
return emptyblock;
|
||||
}
|
||||
|
||||
//No more bytes were read into the buffer,
|
||||
//we assume this means the HTTP response is done
|
||||
if(bytes_read == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
offset += bytes_read;
|
||||
|
||||
//Check if we have enough buffer left over,
|
||||
//if not expand it with an additional HTTP_BUFFER_GROWTH worth of bytes
|
||||
if(offset >= buffer.size)
|
||||
{
|
||||
buffer.size += HTTP_BUFFER_GROWTH;
|
||||
buffer.data = realloc(buffer.data, buffer.size);
|
||||
|
||||
if(buffer.data == NULL)
|
||||
{
|
||||
return emptyblock;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//At the end of above loop offset should be precisely the amount of bytes that were read from the connection
|
||||
buffer.size = offset;
|
||||
|
||||
//Shrink the size of the buffer so the data fits exactly in it
|
||||
realloc(buffer.data, buffer.size);
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Downloads the contents of a URL to memory
|
||||
* This method is not threadsafe (because networking is not threadsafe on the Wii)
|
||||
*/
|
||||
struct block downloadfile(const char *url)
|
||||
{
|
||||
//Check if the url starts with "http://", if not it is not considered a valid url
|
||||
if(strncmp(url, "http://", strlen("http://")) != 0)
|
||||
{
|
||||
//printf("URL '%s' doesn't start with 'http://'\n", url);
|
||||
return emptyblock;
|
||||
}
|
||||
|
||||
//Locate the path part of the url by searching for '/' past "http://"
|
||||
char *path = strchr(url + strlen("http://"), '/');
|
||||
|
||||
//At the very least the url has to end with '/', ending with just a domain is invalid
|
||||
if(path == NULL)
|
||||
{
|
||||
//printf("URL '%s' has no PATH part\n", url);
|
||||
return emptyblock;
|
||||
}
|
||||
|
||||
//Extract the domain part out of the url
|
||||
int domainlength = path - url - strlen("http://");
|
||||
|
||||
if(domainlength == 0)
|
||||
{
|
||||
//printf("No domain part in URL '%s'\n", url);
|
||||
return emptyblock;
|
||||
}
|
||||
|
||||
char domain[domainlength + 1];
|
||||
strncpy(domain, url + strlen("http://"), domainlength);
|
||||
domain[domainlength] = '\0';
|
||||
|
||||
//Parsing of the URL is done, start making an actual connection
|
||||
u32 ipaddress = getipbynamecached(domain);
|
||||
|
||||
if(ipaddress == 0)
|
||||
{
|
||||
//printf("\ndomain %s could not be resolved", domain);
|
||||
return emptyblock;
|
||||
}
|
||||
|
||||
|
||||
s32 connection = server_connect(ipaddress, 80);
|
||||
|
||||
if(connection < 0) {
|
||||
//printf("Error establishing connection");
|
||||
return emptyblock;
|
||||
}
|
||||
|
||||
//Form a nice request header to send to the webserver
|
||||
char* headerformat = "GET %s HTTP/1.0\r\nHost: %s\r\nReferer: %s\r\nCache-Control: no-cache\r\n\r\n";
|
||||
char header[strlen(headerformat) + strlen(path) + strlen(domain)*2 + 1];
|
||||
sprintf(header, headerformat, path, domain, domain);
|
||||
|
||||
//Do the request and get the response
|
||||
send_message(connection, header);
|
||||
struct block response = read_message(connection);
|
||||
net_close(connection);
|
||||
|
||||
//Search for the 4-character sequence \r\n\r\n in the response which signals the start of the http payload (file)
|
||||
unsigned char *filestart = NULL;
|
||||
u32 filesize = 0;
|
||||
int i;
|
||||
for(i = 3; i < response.size; i++)
|
||||
{
|
||||
if(response.data[i] == '\n' &&
|
||||
response.data[i-1] == '\r' &&
|
||||
response.data[i-2] == '\n' &&
|
||||
response.data[i-3] == '\r' &&
|
||||
response.data[9] == 50 ) // hamachi-mp.bplaced.net / 50 vorhanden | 52 nicht vorhanden
|
||||
{
|
||||
filestart = response.data + i + 1;
|
||||
filesize = response.size - i - 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(filestart == NULL)
|
||||
{
|
||||
//printf("HTTP Response was without a file\n");
|
||||
free(response.data);
|
||||
return emptyblock;
|
||||
}
|
||||
|
||||
//Copy the file part of the response into a new memoryblock to return
|
||||
struct block file;
|
||||
file.data = malloc(filesize);
|
||||
file.size = filesize;
|
||||
|
||||
if(file.data == NULL)
|
||||
{
|
||||
//printf("No more memory to copy file from HTTP response\n");
|
||||
free(response.data);
|
||||
return emptyblock;
|
||||
}
|
||||
|
||||
memcpy(file.data, filestart, filesize);
|
||||
|
||||
//Dispose of the original response
|
||||
free(response.data);
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
|
||||
int network_read(int connection, u8 *buf, u32 len)
|
||||
{
|
||||
u32 read = 0;
|
||||
s32 ret = -1;
|
||||
|
||||
while (read < len)
|
||||
{
|
||||
ret = net_read(connection, buf + read, len - read);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (!ret)
|
||||
break;
|
||||
|
||||
read += ret;
|
||||
}
|
||||
|
||||
return read;
|
||||
}
|
31
installer/source/Network/http.h
Normal file
31
installer/source/Network/http.h
Normal file
@ -0,0 +1,31 @@
|
||||
#ifndef _HTTP_H_
|
||||
#define _HTTP_H_
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#include "dns.h"
|
||||
|
||||
/**
|
||||
* A simple structure to keep track of the size of a malloc()ated block of memory
|
||||
*/
|
||||
struct block
|
||||
{
|
||||
u32 size;
|
||||
unsigned char *data;
|
||||
};
|
||||
|
||||
extern const struct block emptyblock;
|
||||
|
||||
struct block downloadfile(const char *url);
|
||||
|
||||
int network_read(int connection, u8 *buf, u32 len);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _HTTP_H_ */
|
187
installer/source/Network/network.cpp
Normal file
187
installer/source/Network/network.cpp
Normal file
@ -0,0 +1,187 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2009
|
||||
* by Dimok
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any
|
||||
* damages arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any
|
||||
* purpose, including commercial applications, and to alter it and
|
||||
* redistribute it freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you
|
||||
* must not claim that you wrote the original software. If you use
|
||||
* this software in a product, an acknowledgment in the product
|
||||
* documentation would be appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and
|
||||
* must not be misrepresented as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*
|
||||
* networkops.cpp
|
||||
*
|
||||
* Network operations
|
||||
* for Wii-Xplorer 2009
|
||||
***************************************************************************/
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <ogcsys.h>
|
||||
#include <ogc/machine/processor.h>
|
||||
|
||||
#include "http.h"
|
||||
#include <malloc.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
//static NetReceiver Receiver;
|
||||
static bool networkinit = false;
|
||||
static bool networkerror = false;
|
||||
static char IP[16];
|
||||
static u8 * ThreadStack = NULL;
|
||||
static bool firstRun = false;
|
||||
|
||||
static lwp_t networkthread = LWP_THREAD_NULL;
|
||||
static bool networkHalt = true;
|
||||
static bool exitRequested = false;
|
||||
|
||||
/****************************************************************************
|
||||
* Initialize_Network
|
||||
***************************************************************************/
|
||||
void Initialize_Network(void)
|
||||
{
|
||||
if(networkinit)
|
||||
return;
|
||||
|
||||
s32 result;
|
||||
|
||||
result = if_config(IP, NULL, NULL, true);
|
||||
|
||||
if(result < 0) {
|
||||
networkinit = false;
|
||||
networkerror = true;
|
||||
return;
|
||||
}
|
||||
|
||||
networkinit = true;
|
||||
networkerror = false;
|
||||
return;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* DeInit_Network
|
||||
***************************************************************************/
|
||||
void DeInit_Network(void)
|
||||
{
|
||||
net_deinit();
|
||||
}
|
||||
/****************************************************************************
|
||||
* Check if network was initialised
|
||||
***************************************************************************/
|
||||
bool IsNetworkInit(void)
|
||||
{
|
||||
return networkinit;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Check that network has error
|
||||
***************************************************************************/
|
||||
bool IsNetworkError(void)
|
||||
{
|
||||
return networkerror;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Get network IP
|
||||
***************************************************************************/
|
||||
char * GetNetworkIP(void)
|
||||
{
|
||||
return IP;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* HaltNetwork
|
||||
***************************************************************************/
|
||||
void HaltNetworkThread()
|
||||
{
|
||||
networkHalt = true;
|
||||
|
||||
// wait for thread to finish
|
||||
while(!LWP_ThreadIsSuspended(networkthread))
|
||||
{
|
||||
usleep(100);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* ResumeNetworkThread
|
||||
***************************************************************************/
|
||||
void ResumeNetworkThread()
|
||||
{
|
||||
networkHalt = false;
|
||||
LWP_ResumeThread(networkthread);
|
||||
}
|
||||
|
||||
/*********************************************************************************
|
||||
* Networkthread for background network initialize and update check with idle prio
|
||||
*********************************************************************************/
|
||||
static void * networkinitcallback(void *arg)
|
||||
{
|
||||
while(!exitRequested)
|
||||
{
|
||||
if(networkHalt)
|
||||
{
|
||||
LWP_SuspendThread(networkthread);
|
||||
usleep(100);
|
||||
continue;
|
||||
}
|
||||
|
||||
if(!networkinit)
|
||||
Initialize_Network();
|
||||
|
||||
if(!firstRun)
|
||||
{
|
||||
LWP_SetThreadPriority(networkthread, 0);
|
||||
firstRun = true;
|
||||
}
|
||||
|
||||
usleep(200000);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* InitNetworkThread with priority 0 (idle)
|
||||
***************************************************************************/
|
||||
void InitNetworkThread()
|
||||
{
|
||||
ThreadStack = (u8 *) memalign(32, 16384);
|
||||
if(!ThreadStack)
|
||||
return;
|
||||
|
||||
LWP_CreateThread (&networkthread, networkinitcallback, NULL, ThreadStack, 16384, 30);
|
||||
ResumeNetworkThread();
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* ShutdownThread
|
||||
***************************************************************************/
|
||||
void ShutdownNetworkThread()
|
||||
{
|
||||
exitRequested = true;
|
||||
networkinit = false;
|
||||
networkerror = false;
|
||||
|
||||
if(networkthread != LWP_THREAD_NULL)
|
||||
{
|
||||
ResumeNetworkThread();
|
||||
LWP_JoinThread (networkthread, NULL);
|
||||
networkthread = LWP_THREAD_NULL;
|
||||
}
|
||||
|
||||
if(ThreadStack)
|
||||
free(ThreadStack);
|
||||
ThreadStack = NULL;
|
||||
}
|
39
installer/source/Network/network.h
Normal file
39
installer/source/Network/network.h
Normal file
@ -0,0 +1,39 @@
|
||||
/****************************************************************************
|
||||
* Copyright (C) 2010
|
||||
* by Dimok
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any
|
||||
* damages arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any
|
||||
* purpose, including commercial applications, and to alter it and
|
||||
* redistribute it freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you
|
||||
* must not claim that you wrote the original software. If you use
|
||||
* this software in a product, an acknowledgment in the product
|
||||
* documentation would be appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and
|
||||
* must not be misrepresented as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*
|
||||
* for WiiXplorer 2010
|
||||
***************************************************************************/
|
||||
#ifndef _NETWORKOPS_H_
|
||||
#define _NETWORKOPS_H_
|
||||
|
||||
void Initialize_Network(void);
|
||||
void DeInit_Network(void);
|
||||
bool IsNetworkInit(void);
|
||||
bool IsNetworkError(void);
|
||||
char * GetNetworkIP(void);
|
||||
void HaltNetworkThread();
|
||||
void ResumeNetworkThread();
|
||||
void InitNetworkThread();
|
||||
void ShutdownNetworkThread();
|
||||
|
||||
#endif
|
69
installer/source/RuntimeIOSPatch.c
Normal file
69
installer/source/RuntimeIOSPatch.c
Normal file
@ -0,0 +1,69 @@
|
||||
#include <gccore.h>
|
||||
#include <ogc/machine/processor.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "RuntimeIOSPatch.h"
|
||||
|
||||
#define MEM_PROT 0xD8B420A
|
||||
|
||||
const u8 isfs_permissions_old[] = { 0x42, 0x8B, 0xD0, 0x01, 0x25, 0x66 };
|
||||
const u8 isfs_permissions_patch[] = { 0x42, 0x8B, 0xE0, 0x01, 0x25, 0x66 };
|
||||
const u8 setuid_old[] = { 0xD1, 0x2A, 0x1C, 0x39 };
|
||||
const u8 setuid_patch[] = { 0x46, 0xC0 };
|
||||
const u8 es_identify_old[] = { 0x28, 0x03, 0xD1, 0x23 };
|
||||
const u8 es_identify_patch[] = { 0x00, 0x00 };
|
||||
const u8 hash_old[] = { 0x20, 0x07, 0x4B, 0x0B };
|
||||
const u8 hash_patch[] = { 0x00 };
|
||||
const u8 addticket_vers_check[] = { 0xD2, 0x01, 0x4E, 0x56 };
|
||||
const u8 addticket_patch[] = { 0xE0 };
|
||||
|
||||
u32 apply_patch(const char *name, const u8 *old, u32 old_size, const u8 *patch, u32 patch_size, u32 patch_offset)
|
||||
{
|
||||
// printf("Applying patch %s.....", name);
|
||||
u8 *ptr = (u8 *) 0x93400000;
|
||||
u32 i, found = 0;
|
||||
u8 *start;
|
||||
|
||||
while ((u32) ptr < (0x94000000 - old_size))
|
||||
{
|
||||
if(!memcmp(ptr, old, old_size))
|
||||
{
|
||||
found++;
|
||||
start = ptr + patch_offset;
|
||||
for (i = 0; i < patch_size; i++)
|
||||
*(start + i) = patch[i];
|
||||
ptr += patch_size;
|
||||
DCFlushRange((u8 *) (((u32) start) >> 5 << 5), (patch_size >> 5 << 5) + 64);
|
||||
}
|
||||
ptr++;
|
||||
}
|
||||
// if(found)
|
||||
// printf("Patched\n");
|
||||
// else
|
||||
// printf("\n");
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
u32 runtimePatchApply()
|
||||
{
|
||||
u32 count = 0;
|
||||
write16(MEM_PROT, 0);
|
||||
count += apply_patch("Trucha", hash_old,
|
||||
sizeof(hash_old), hash_patch, sizeof(hash_patch), 1);
|
||||
count += apply_patch("ES_Identify", es_identify_old,
|
||||
sizeof(es_identify_old), es_identify_patch, sizeof(es_identify_patch),
|
||||
2);
|
||||
count += apply_patch("NAND Permissions", isfs_permissions_old,
|
||||
sizeof(isfs_permissions_old), isfs_permissions_patch,
|
||||
sizeof(isfs_permissions_patch), 0);
|
||||
count += apply_patch("add ticket patch", addticket_vers_check,
|
||||
sizeof(addticket_vers_check), addticket_patch, sizeof(addticket_patch),
|
||||
0);
|
||||
count += apply_patch("ES_SetUID", setuid_old, sizeof(setuid_old),
|
||||
setuid_patch, sizeof(setuid_patch), 0);
|
||||
write16(MEM_PROT, 1);
|
||||
return count;
|
||||
}
|
14
installer/source/RuntimeIOSPatch.h
Normal file
14
installer/source/RuntimeIOSPatch.h
Normal file
@ -0,0 +1,14 @@
|
||||
#ifndef _RUNTIMEIOSPATCH_H_
|
||||
#define _RUNTIMEIOSPATCH_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
u32 runtimePatchApply();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
135
installer/source/getios.cpp
Normal file
135
installer/source/getios.cpp
Normal file
@ -0,0 +1,135 @@
|
||||
|
||||
#include <ogcsys.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <malloc.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
std::vector<int> ioslist;
|
||||
|
||||
// Check if this is an IOS stub (according to WiiBrew.org)
|
||||
bool IsKnownStub(u32 noIOS, s32 noRevision)
|
||||
{
|
||||
if (noIOS == 3 && noRevision == 65280) return true;
|
||||
if (noIOS == 4 && noRevision == 65280) return true;
|
||||
if (noIOS == 10 && noRevision == 768) return true;
|
||||
if (noIOS == 11 && noRevision == 256) return true;
|
||||
if (noIOS == 16 && noRevision == 512) return true;
|
||||
if (noIOS == 20 && noRevision == 256) return true;
|
||||
if (noIOS == 30 && noRevision == 2816) return true;
|
||||
if (noIOS == 40 && noRevision == 3072) return true;
|
||||
if (noIOS == 50 && noRevision == 5120) return true;
|
||||
if (noIOS == 51 && noRevision == 4864) return true;
|
||||
if (noIOS == 52 && noRevision == 5888) return true;
|
||||
if (noIOS == 60 && noRevision == 6400) return true;
|
||||
if (noIOS == 70 && noRevision == 6912) return true;
|
||||
if (noIOS == 222 && noRevision == 65280) return true;
|
||||
if (noIOS == 223 && noRevision == 65280) return true;
|
||||
if (noIOS == 249 && noRevision == 65280) return true;
|
||||
if (noIOS == 250 && noRevision == 65280) return true;
|
||||
if (noIOS == 254 && noRevision == 2) return true;
|
||||
if (noIOS == 254 && noRevision == 3) return true;
|
||||
if (noIOS == 254 && noRevision == 260) return true;
|
||||
|
||||
// BootMii As IOS is installed on IOS254 rev 31338
|
||||
if (noIOS == 254 && noRevision == 31338) return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool listIOS()
|
||||
{
|
||||
ioslist.clear();
|
||||
u32 nbTitles;
|
||||
if (ES_GetNumTitles(&nbTitles) < 0)
|
||||
return false;
|
||||
|
||||
// Allocate the memory for titles
|
||||
u64 *titles = (u64*)memalign(32, nbTitles*sizeof(u64));
|
||||
|
||||
if (titles == NULL)
|
||||
return false;
|
||||
|
||||
if (ES_GetTitles(titles, nbTitles) < 0)
|
||||
return false;
|
||||
|
||||
int i;
|
||||
u32 titleID;
|
||||
|
||||
// For each titles found
|
||||
for (i = 0; i < (signed)nbTitles; i++)
|
||||
{
|
||||
// Skip non-system titles
|
||||
if (titles[i] >> 32 != 1) continue;
|
||||
|
||||
// Skip the system menu
|
||||
titleID = titles[i] & 0xFFFFFFFF;
|
||||
|
||||
if (titleID == 2) continue;
|
||||
|
||||
// Skip BC, MIOS and possible other non-IOS titles
|
||||
if (titleID > 0xFF) continue;
|
||||
|
||||
// Skip the running IOS
|
||||
if (titleID == 0) continue;
|
||||
|
||||
// Skip bootmii IOS
|
||||
if (titleID == 254) continue;
|
||||
|
||||
// Check if this title is an IOS stub
|
||||
u32 tmdSize;
|
||||
tmd *iosTMD ATTRIBUTE_ALIGN(32);
|
||||
|
||||
// Get the stored TMD size for the title
|
||||
if (ES_GetStoredTMDSize(0x0000000100000000ULL | titleID, &tmdSize) < 0)
|
||||
return false;
|
||||
|
||||
signed_blob *iosTMDBuffer = (signed_blob *)memalign(32, (tmdSize+32)&(~31));
|
||||
memset(iosTMDBuffer, 0, tmdSize);
|
||||
|
||||
// Get the stored TMD for the title
|
||||
if (ES_GetStoredTMD(0x0000000100000000ULL | titleID, iosTMDBuffer, tmdSize) < 0)
|
||||
return false;
|
||||
|
||||
iosTMD = (tmd *)SIGNATURE_PAYLOAD(iosTMDBuffer);
|
||||
|
||||
free(iosTMDBuffer);
|
||||
|
||||
// Get the title version
|
||||
u8 noVersion = iosTMD->title_version;
|
||||
bool isStub = false;
|
||||
|
||||
// Check if this is an IOS stub (according to WiiBrew.org)
|
||||
if (IsKnownStub(titleID, iosTMD->title_version))
|
||||
isStub = true;
|
||||
else
|
||||
{
|
||||
// If the version is 00, it's probably a stub
|
||||
//
|
||||
// Stubs have these things in common:
|
||||
// - Title version is mostly 65280, or even better, the last 2 hexadecimal digits are 0;
|
||||
// - Stub have one app of their own (type 0x1) and 2 shared apps (type 0x8001).
|
||||
if (noVersion == 0)
|
||||
isStub = ((iosTMD->num_contents == 3) && (iosTMD->contents[0].type == 1 && iosTMD->contents[1].type == 0x8001 && iosTMD->contents[2].type == 0x8001));
|
||||
else
|
||||
isStub = false;
|
||||
}
|
||||
|
||||
if(!isStub)
|
||||
ioslist.push_back(titleID);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool getIOS(int ios)
|
||||
{
|
||||
|
||||
for(int i = 0; i < (signed)ioslist.size(); i++)
|
||||
{
|
||||
if(ioslist[i] == ios)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
7
installer/source/getios.h
Normal file
7
installer/source/getios.h
Normal file
@ -0,0 +1,7 @@
|
||||
#ifndef _GETIOS_H_
|
||||
#define _GETIOS_H_
|
||||
|
||||
bool listIOS();
|
||||
bool getIOS(int ios);
|
||||
|
||||
#endif
|
33
installer/source/main.cpp
Normal file
33
installer/source/main.cpp
Normal file
@ -0,0 +1,33 @@
|
||||
|
||||
#include <malloc.h>
|
||||
#include <wiiuse/wpad.h>
|
||||
|
||||
#include "RuntimeIOSPatch.h"
|
||||
#include "menu.h"
|
||||
#include "video.h"
|
||||
#include "wad.h"
|
||||
#include "Network/network.h"
|
||||
|
||||
#define HAVE_AHBPROT ((*(vu32*)0xcd800064 == 0xFFFFFFFF) ? 1 : 0)
|
||||
|
||||
//---------------------------------------------------------------------------------
|
||||
int main(int argc, char **argv) {
|
||||
//---------------------------------------------------------------------------------
|
||||
|
||||
// Initialise the video system
|
||||
InitNetworkThread();
|
||||
VIDEO_Init();
|
||||
Video_SetMode();
|
||||
|
||||
// This function initialises the attached controllers
|
||||
WPAD_Init();
|
||||
|
||||
if(HAVE_AHBPROT)
|
||||
runtimePatchApply();
|
||||
|
||||
menu();
|
||||
|
||||
SYS_ResetSystem(SYS_RETURNTOMENU, 0, 0);
|
||||
|
||||
return 0;
|
||||
}
|
429
installer/source/menu.cpp
Normal file
429
installer/source/menu.cpp
Normal file
@ -0,0 +1,429 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <gccore.h>
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
#include <wiiuse/wpad.h>
|
||||
|
||||
#include "getios.h"
|
||||
#include "menu.h"
|
||||
#include "video.h"
|
||||
#include "wad.h"
|
||||
#include "../../svnrev/svnrev.h"
|
||||
|
||||
using namespace std;
|
||||
std::vector<string> text1, text2, text3;
|
||||
|
||||
int startpos_x = 6;
|
||||
int startpos_y = 12;
|
||||
int menu_main_choice;
|
||||
|
||||
void show_menu_head()
|
||||
{
|
||||
Con_FgColor(6, 1);
|
||||
printf("\x1b[%i;%iH", startpos_x, startpos_y);
|
||||
printf("HBF installer v0.2");
|
||||
|
||||
Con_FgColor(7, 1);
|
||||
printf("\t\t\t\t\t(C) 2011");
|
||||
Con_FgColor(6, 1);
|
||||
printf(" hamachi-mp");
|
||||
}
|
||||
|
||||
void fill_menu_main()
|
||||
{
|
||||
text1.clear();
|
||||
stringstream buffer;
|
||||
buffer << "Install The Homebrew Filter rev" << SvnRev();
|
||||
text1.push_back(buffer.str());
|
||||
if(CheckAppFound(GetTitleID()))
|
||||
text1.push_back("Uninstall The Homebrew Filter");
|
||||
else
|
||||
text1.push_back("");
|
||||
text1.push_back("");
|
||||
text1.push_back("Copyright");
|
||||
text1.push_back("");
|
||||
text1.push_back("Exit");
|
||||
}
|
||||
|
||||
void fill_menu_install_uninstall()
|
||||
{
|
||||
text2.push_back("Yes, continue");
|
||||
text2.push_back("No, take me back");
|
||||
}
|
||||
|
||||
void fill_menu_copyright()
|
||||
{
|
||||
text3.push_back("Copyright (C) hamachi-mp");
|
||||
text3.push_back("");
|
||||
text3.push_back("Thanks to:");
|
||||
text3.push_back("\tTeam Twiizers");
|
||||
text3.push_back("\tdevkitPRO");
|
||||
text3.push_back("\tWaninkoko (WAD Manager)");
|
||||
text3.push_back("\tWiiCrazy/I.R.on (Crap Installer)");
|
||||
}
|
||||
|
||||
void menu()
|
||||
{
|
||||
mopen();
|
||||
ISFS_Initialize();
|
||||
listIOS();
|
||||
|
||||
fill_menu_main();
|
||||
fill_menu_install_uninstall();
|
||||
fill_menu_copyright();
|
||||
|
||||
menu_main_choice = text1.size() -1;
|
||||
/*
|
||||
int fgcolor = 3;
|
||||
int fgbold = 1;
|
||||
|
||||
printf("\x1b[1;0H");
|
||||
printf("fgcolor %i\n", fgcolor);
|
||||
printf("fgbold %i\n", fgbold);
|
||||
|
||||
Con_FgColor(fgcolor, fgbold);
|
||||
printf("test");
|
||||
|
||||
while(1)
|
||||
{
|
||||
WPAD_ScanPads();
|
||||
u32 pressed = WPAD_ButtonsDown(0);
|
||||
|
||||
if(pressed & WPAD_BUTTON_UP)
|
||||
{
|
||||
printf("test");
|
||||
}
|
||||
else if(pressed & WPAD_BUTTON_1)
|
||||
{
|
||||
fgcolor--;
|
||||
printf("\x1b[1;0H");
|
||||
Con_FgColor(7, 1);
|
||||
printf("fgcolor %i\n\n", fgcolor);
|
||||
Con_FgColor(fgcolor, fgbold);
|
||||
printf("test");
|
||||
}
|
||||
else if(pressed & WPAD_BUTTON_2)
|
||||
{
|
||||
fgcolor++;
|
||||
printf("\x1b[1;0H");
|
||||
Con_FgColor(7, 1);
|
||||
printf("fgcolor %i\n\n", fgcolor);
|
||||
Con_FgColor(fgcolor, fgbold);
|
||||
printf("test");
|
||||
}
|
||||
else if(pressed & WPAD_BUTTON_MINUS)
|
||||
{
|
||||
fgbold--;
|
||||
printf("\x1b[2;0H");
|
||||
Con_FgColor(7, 1);
|
||||
printf("fgbold %i\n", fgbold);
|
||||
Con_FgColor(fgcolor, fgbold);
|
||||
printf("test");
|
||||
}
|
||||
else if(pressed & WPAD_BUTTON_PLUS)
|
||||
{
|
||||
fgbold++;
|
||||
printf("\x1b[2;0H");
|
||||
Con_FgColor(7, 1);
|
||||
printf("fgbold %i\n", fgbold);
|
||||
Con_FgColor(fgcolor, fgbold);
|
||||
printf("test");
|
||||
}
|
||||
else if(pressed & WPAD_BUTTON_HOME)
|
||||
exit(0);
|
||||
}
|
||||
*/
|
||||
|
||||
int currentMenu = 0;
|
||||
while(currentMenu != MENU_EXIT)
|
||||
{
|
||||
switch (currentMenu)
|
||||
{
|
||||
case MENU_MAIN:
|
||||
currentMenu = menu_main(menu_main_choice);
|
||||
break;
|
||||
|
||||
case MENU_INSTALL:
|
||||
currentMenu = menu_install_uninstall(1);
|
||||
break;
|
||||
|
||||
case MENU_UNINSTALL:
|
||||
currentMenu = menu_install_uninstall(0);
|
||||
break;
|
||||
|
||||
case MENU_INSTALLING:
|
||||
currentMenu = menu_install();
|
||||
break;
|
||||
|
||||
case MENU_UNINSTALLING:
|
||||
currentMenu = menu_uninstall();
|
||||
break;
|
||||
|
||||
case MENU_COPYRIGHT:
|
||||
currentMenu = menu_copyright();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ISFS_Deinitialize();
|
||||
}
|
||||
|
||||
int menu_main(int scrollpos)
|
||||
{
|
||||
Con_Clear();
|
||||
|
||||
show_menu_head();
|
||||
fill_menu_main();
|
||||
if(text1[scrollpos] == "")
|
||||
scrollpos = text1.size() -1;
|
||||
|
||||
Con_FgColor(3, 1);
|
||||
printf("\x1b[%i;%iH", startpos_x +2, startpos_y);
|
||||
printf("Main Menu");
|
||||
|
||||
Con_FgColor(7, 1);
|
||||
for(int i=0; i < (signed)text1.size(); i++)
|
||||
{
|
||||
printf("\x1b[%i;%iH", startpos_x +4 +i, startpos_y +3);
|
||||
printf("%s", text1[i].c_str());
|
||||
}
|
||||
|
||||
bool scroll = true;
|
||||
while(1)
|
||||
{
|
||||
WPAD_ScanPads();
|
||||
u32 pressed = WPAD_ButtonsDown(0);
|
||||
|
||||
if ( pressed & WPAD_BUTTON_DOWN && scrollpos < (signed)text1.size() -1)
|
||||
{
|
||||
scrollpos++;
|
||||
while(text1[scrollpos] == "")
|
||||
scrollpos++;
|
||||
|
||||
scroll = true;
|
||||
}
|
||||
else if ( pressed & WPAD_BUTTON_UP && scrollpos != 0)
|
||||
{
|
||||
scrollpos--;
|
||||
while(text1[scrollpos] == "")
|
||||
scrollpos--;
|
||||
|
||||
scroll = true;
|
||||
}
|
||||
|
||||
if(scroll)
|
||||
{
|
||||
for(int i=0; i < (signed)text1.size(); i++)
|
||||
{
|
||||
printf("\x1b[%i;%iH", startpos_x +4 +i, startpos_y);
|
||||
if(i == scrollpos)
|
||||
printf(">>");
|
||||
else
|
||||
printf(" ");
|
||||
|
||||
}
|
||||
scroll = false;
|
||||
}
|
||||
|
||||
if( pressed & WPAD_BUTTON_A )
|
||||
{
|
||||
menu_main_choice = scrollpos;
|
||||
switch(scrollpos)
|
||||
{
|
||||
case 0:
|
||||
return MENU_INSTALL;
|
||||
|
||||
case 1:
|
||||
return MENU_UNINSTALL;
|
||||
|
||||
case 3:
|
||||
return MENU_COPYRIGHT;
|
||||
|
||||
default:
|
||||
return MENU_EXIT;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int menu_install_uninstall(int install)
|
||||
{
|
||||
Con_Clear();
|
||||
show_menu_head();
|
||||
|
||||
Con_FgColor(7, 1);
|
||||
printf("\x1b[%i;%iH", startpos_x +2, startpos_y);
|
||||
if(install)
|
||||
printf("Install The Homebrew Filter now");
|
||||
else
|
||||
printf("Uninstall The Homebrew Filter now");
|
||||
|
||||
for(int i=0; i < (signed)text2.size(); i++)
|
||||
{
|
||||
printf("\x1b[%i;%iH", startpos_x +4 +i, startpos_y +3);
|
||||
printf("%s", text2[i].c_str());
|
||||
}
|
||||
|
||||
int scrollpos = 1;
|
||||
bool scroll = true;
|
||||
while(1)
|
||||
{
|
||||
WPAD_ScanPads();
|
||||
u32 pressed = WPAD_ButtonsDown(0);
|
||||
|
||||
if ( pressed & WPAD_BUTTON_DOWN && scrollpos < (signed)text2.size() -1)
|
||||
{
|
||||
scrollpos++;
|
||||
scroll = true;
|
||||
}
|
||||
else if ( pressed & WPAD_BUTTON_UP && scrollpos != 0)
|
||||
{
|
||||
scrollpos--;
|
||||
scroll = true;
|
||||
}
|
||||
|
||||
if(scroll)
|
||||
{
|
||||
for(int i=0; i < (signed)text2.size(); i++)
|
||||
{
|
||||
printf("\x1b[%d;12H", startpos_x +4 +i);
|
||||
if(i == scrollpos)
|
||||
printf(">>");
|
||||
else
|
||||
printf(" ");
|
||||
|
||||
}
|
||||
scroll = false;
|
||||
}
|
||||
|
||||
if( pressed & WPAD_BUTTON_A )
|
||||
{
|
||||
switch(scrollpos)
|
||||
{
|
||||
case 0:
|
||||
if(install)
|
||||
return MENU_INSTALLING;
|
||||
else
|
||||
return MENU_UNINSTALLING;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
return MENU_MAIN;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int menu_install()
|
||||
{
|
||||
Con_Clear();
|
||||
show_menu_head();
|
||||
|
||||
Con_FgColor(7, 1);
|
||||
printf("\x1b[%i;%iH", startpos_x +2, startpos_y);
|
||||
printf("Installing The Homebrew Filter");
|
||||
|
||||
printf("\x1b[%i;%iH", startpos_x +4, startpos_y);
|
||||
if(Wad_InstallFromMemory(startpos_x, startpos_y) >= 0)
|
||||
{
|
||||
if(!getIOS(58))
|
||||
{
|
||||
s32 fd;
|
||||
u32 high = (u32)(GetTitleID() >> 32);
|
||||
u32 low = (u32)(GetTitleID() & 0xFFFFFFFF);
|
||||
|
||||
char filepath[ISFS_MAXPATH];
|
||||
sprintf(filepath, "/title/%08x/%08x/content/title.tmd", high, low);
|
||||
|
||||
static fstats filestats ATTRIBUTE_ALIGN(32);
|
||||
static u8 filearray[1024] ATTRIBUTE_ALIGN(32);
|
||||
|
||||
fd = ISFS_Open(filepath, ISFS_OPEN_READ);
|
||||
if (fd <= 0)
|
||||
ISFS_Close(fd);
|
||||
|
||||
ISFS_GetFileStats(fd, &filestats);
|
||||
ISFS_Read(fd, filearray, filestats.file_length);
|
||||
ISFS_Close(fd);
|
||||
|
||||
if(filestats.file_length >= 0)
|
||||
{
|
||||
fd = ISFS_Open(filepath, ISFS_OPEN_RW);
|
||||
|
||||
if(getIOS(61))
|
||||
filearray[395] = 61;
|
||||
else
|
||||
filearray[395] = IOS_GetVersion();
|
||||
|
||||
ISFS_Write(fd, filearray, sizeof( filearray ));
|
||||
ISFS_Close(fd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Con_FgColor(7, 1);
|
||||
printf("\x1b[%i;%iH", startpos_x +8, startpos_y);
|
||||
printf(">> Continue");
|
||||
|
||||
while(1)
|
||||
{
|
||||
WPAD_ScanPads();
|
||||
u32 pressed = WPAD_ButtonsDown(0);
|
||||
|
||||
if( pressed & WPAD_BUTTON_A )
|
||||
return MENU_MAIN;
|
||||
}
|
||||
}
|
||||
|
||||
int menu_uninstall()
|
||||
{
|
||||
Con_Clear();
|
||||
show_menu_head();
|
||||
|
||||
Con_FgColor(7, 1);
|
||||
printf("\x1b[%i;%iH", startpos_x +2, startpos_y);
|
||||
printf("Uninstalling The Homebrew Filter");
|
||||
|
||||
Wad_UninstallFromMemory(startpos_x, startpos_y);
|
||||
|
||||
Con_FgColor(7, 1);
|
||||
printf("\x1b[%i;%iH", startpos_x +8, startpos_y);
|
||||
printf(">> Continue");
|
||||
|
||||
while(1)
|
||||
{
|
||||
WPAD_ScanPads();
|
||||
u32 pressed = WPAD_ButtonsDown(0);
|
||||
|
||||
if( pressed & WPAD_BUTTON_A )
|
||||
return MENU_MAIN;
|
||||
}
|
||||
}
|
||||
|
||||
int menu_copyright()
|
||||
{
|
||||
Con_Clear();
|
||||
show_menu_head();
|
||||
|
||||
Con_FgColor(7, 1);
|
||||
|
||||
for(int i=0; i < (signed)text3.size(); i++)
|
||||
{
|
||||
printf("\x1b[%i;%iH", startpos_x +2 +i, startpos_y);
|
||||
printf("%s", text3[i].c_str());
|
||||
}
|
||||
|
||||
printf("\x1b[%i;%iH", startpos_x + text3.size() +3, startpos_y);
|
||||
printf(">> Continue");
|
||||
|
||||
while(1)
|
||||
{
|
||||
WPAD_ScanPads();
|
||||
u32 pressed = WPAD_ButtonsDown(0);
|
||||
|
||||
if( pressed & WPAD_BUTTON_A )
|
||||
return MENU_MAIN;
|
||||
}
|
||||
}
|
18
installer/source/menu.h
Normal file
18
installer/source/menu.h
Normal file
@ -0,0 +1,18 @@
|
||||
|
||||
void menu();
|
||||
int menu_main(int);
|
||||
int menu_install_uninstall(int);
|
||||
int menu_install();
|
||||
int menu_uninstall();
|
||||
int menu_copyright();
|
||||
|
||||
enum
|
||||
{
|
||||
MENU_EXIT = -1,
|
||||
MENU_MAIN,
|
||||
MENU_INSTALL,
|
||||
MENU_UNINSTALL,
|
||||
MENU_INSTALLING,
|
||||
MENU_UNINSTALLING,
|
||||
MENU_COPYRIGHT
|
||||
};
|
177
installer/source/sha1.c
Normal file
177
installer/source/sha1.c
Normal file
@ -0,0 +1,177 @@
|
||||
/*
|
||||
SHA-1 in C
|
||||
By Steve Reid <steve@edmweb.com>
|
||||
100% Public Domain
|
||||
|
||||
Test Vectors (from FIPS PUB 180-1)
|
||||
"abc"
|
||||
A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D
|
||||
"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
|
||||
84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1
|
||||
A million repetitions of "a"
|
||||
34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F
|
||||
*/
|
||||
|
||||
/* #define LITTLE_ENDIAN * This should be #define'd if true. */
|
||||
#define SHA1HANDSOFF
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "sha1.h"
|
||||
|
||||
#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
|
||||
|
||||
/* blk0() and blk() perform the initial expand. */
|
||||
/* I got the idea of expanding during the round function from SSLeay */
|
||||
#ifdef LITTLE_ENDIAN
|
||||
#define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \
|
||||
|(rol(block->l[i],8)&0x00FF00FF))
|
||||
#else
|
||||
#define blk0(i) block->l[i]
|
||||
#endif
|
||||
#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \
|
||||
^block->l[(i+2)&15]^block->l[i&15],1))
|
||||
|
||||
/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
|
||||
#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30);
|
||||
#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30);
|
||||
#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);
|
||||
#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30);
|
||||
#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);
|
||||
|
||||
typedef struct {
|
||||
unsigned long state[5];
|
||||
unsigned long count[2];
|
||||
unsigned char buffer[64];
|
||||
} SHA1_CTX;
|
||||
|
||||
|
||||
/* Hash a single 512-bit block. This is the core of the algorithm. */
|
||||
|
||||
void SHA1Transform(unsigned long state[5], unsigned char buffer[64])
|
||||
{
|
||||
unsigned long a, b, c, d, e;
|
||||
typedef union {
|
||||
unsigned char c[64];
|
||||
unsigned long l[16];
|
||||
} CHAR64LONG16;
|
||||
CHAR64LONG16* block;
|
||||
#ifdef SHA1HANDSOFF
|
||||
static unsigned char workspace[64];
|
||||
block = (CHAR64LONG16*)workspace;
|
||||
memcpy(block, buffer, 64);
|
||||
#else
|
||||
block = (CHAR64LONG16*)buffer;
|
||||
#endif
|
||||
/* Copy context->state[] to working vars */
|
||||
a = state[0];
|
||||
b = state[1];
|
||||
c = state[2];
|
||||
d = state[3];
|
||||
e = state[4];
|
||||
/* 4 rounds of 20 operations each. Loop unrolled. */
|
||||
R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);
|
||||
R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7);
|
||||
R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);
|
||||
R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15);
|
||||
R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
|
||||
R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
|
||||
R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
|
||||
R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
|
||||
R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
|
||||
R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
|
||||
R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
|
||||
R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
|
||||
R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
|
||||
R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
|
||||
R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
|
||||
R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
|
||||
R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
|
||||
R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
|
||||
R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
|
||||
R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
|
||||
/* Add the working vars back into context.state[] */
|
||||
state[0] += a;
|
||||
state[1] += b;
|
||||
state[2] += c;
|
||||
state[3] += d;
|
||||
state[4] += e;
|
||||
/* Wipe variables */
|
||||
a = b = c = d = e = 0;
|
||||
}
|
||||
|
||||
|
||||
/* SHA1Init - Initialize new context */
|
||||
|
||||
void SHA1Init(SHA1_CTX* context)
|
||||
{
|
||||
/* SHA1 initialization constants */
|
||||
context->state[0] = 0x67452301;
|
||||
context->state[1] = 0xEFCDAB89;
|
||||
context->state[2] = 0x98BADCFE;
|
||||
context->state[3] = 0x10325476;
|
||||
context->state[4] = 0xC3D2E1F0;
|
||||
context->count[0] = context->count[1] = 0;
|
||||
}
|
||||
|
||||
|
||||
/* Run your data through this. */
|
||||
|
||||
void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned int len)
|
||||
{
|
||||
unsigned int i, j;
|
||||
|
||||
j = (context->count[0] >> 3) & 63;
|
||||
if ((context->count[0] += len << 3) < (len << 3)) context->count[1]++;
|
||||
context->count[1] += (len >> 29);
|
||||
if ((j + len) > 63) {
|
||||
memcpy(&context->buffer[j], data, (i = 64-j));
|
||||
SHA1Transform(context->state, context->buffer);
|
||||
for ( ; i + 63 < len; i += 64) {
|
||||
SHA1Transform(context->state, &data[i]);
|
||||
}
|
||||
j = 0;
|
||||
}
|
||||
else i = 0;
|
||||
memcpy(&context->buffer[j], &data[i], len - i);
|
||||
}
|
||||
|
||||
|
||||
/* Add padding and return the message digest. */
|
||||
|
||||
void SHA1Final(unsigned char digest[20], SHA1_CTX* context)
|
||||
{
|
||||
unsigned long i, j;
|
||||
unsigned char finalcount[8];
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)]
|
||||
>> ((3-(i & 3)) * 8) ) & 255); /* Endian independent */
|
||||
}
|
||||
SHA1Update(context, (unsigned char *)"\200", 1);
|
||||
while ((context->count[0] & 504) != 448) {
|
||||
SHA1Update(context, (unsigned char *)"\0", 1);
|
||||
}
|
||||
SHA1Update(context, finalcount, 8); /* Should cause a SHA1Transform() */
|
||||
for (i = 0; i < 20; i++) {
|
||||
digest[i] = (unsigned char)
|
||||
((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
|
||||
}
|
||||
/* Wipe variables */
|
||||
i = j = 0;
|
||||
memset(context->buffer, 0, 64);
|
||||
memset(context->state, 0, 20);
|
||||
memset(context->count, 0, 8);
|
||||
memset(&finalcount, 0, 8);
|
||||
#ifdef SHA1HANDSOFF /* make SHA1Transform overwrite it's own static vars */
|
||||
SHA1Transform(context->state, context->buffer);
|
||||
#endif
|
||||
}
|
||||
|
||||
void SHA1(unsigned char *ptr, unsigned int size, unsigned char *outbuf) {
|
||||
SHA1_CTX ctx;
|
||||
|
||||
SHA1Init(&ctx);
|
||||
SHA1Update(&ctx, ptr, size);
|
||||
SHA1Final(outbuf, &ctx);
|
||||
}
|
6
installer/source/sha1.h
Normal file
6
installer/source/sha1.h
Normal file
@ -0,0 +1,6 @@
|
||||
#ifndef _SHA1_H_
|
||||
#define _SHA1_H_
|
||||
|
||||
void SHA1(unsigned char *, unsigned int, unsigned char *);
|
||||
|
||||
#endif
|
84
installer/source/title.c
Normal file
84
installer/source/title.c
Normal file
@ -0,0 +1,84 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
#include <malloc.h>
|
||||
#include <ogcsys.h>
|
||||
|
||||
#include "sha1.h"
|
||||
|
||||
#define round_up(x,n) (-(-(x) & -(n)))
|
||||
|
||||
s32 Title_ZeroSignature(signed_blob *p_sig)
|
||||
{
|
||||
u8 *ptr = (u8 *)p_sig;
|
||||
|
||||
/* Fill signature with zeroes */
|
||||
memset(ptr + 4, 0, SIGNATURE_SIZE(p_sig) - 4);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
s32 Title_FakesignTik(signed_blob *p_tik)
|
||||
{
|
||||
tik *tik_data = NULL;
|
||||
u16 fill;
|
||||
|
||||
/* Zero signature */
|
||||
Title_ZeroSignature(p_tik);
|
||||
|
||||
/* Ticket data */
|
||||
tik_data = (tik *)SIGNATURE_PAYLOAD(p_tik);
|
||||
|
||||
for (fill = 0; fill < USHRT_MAX; fill++) {
|
||||
sha1 hash;
|
||||
|
||||
/* Modify ticket padding field */
|
||||
tik_data->padding = fill;
|
||||
|
||||
/* Calculate hash */
|
||||
SHA1((u8 *)tik_data, sizeof(tik), hash);
|
||||
|
||||
/* Found valid hash */
|
||||
if (!hash[0])
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
11
installer/source/title.h
Normal file
11
installer/source/title.h
Normal file
@ -0,0 +1,11 @@
|
||||
#ifndef _TITLE_H_
|
||||
#define _TITLE_H_
|
||||
|
||||
/* Constants */
|
||||
#define BLOCK_SIZE 1024
|
||||
|
||||
/* Prototypes */
|
||||
s32 Title_FakesignTik(signed_blob *);
|
||||
s32 Title_GetTicketViews(u64, tikview **, u32 *);
|
||||
|
||||
#endif
|
139
installer/source/video.c
Normal file
139
installer/source/video.c
Normal file
@ -0,0 +1,139 @@
|
||||
#include <stdio.h>
|
||||
#include <ogcsys.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_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));
|
||||
|
||||
// Initialise the console, required for printf
|
||||
console_init(framebuffer,20,20,vmode->fbWidth,vmode->xfbHeight,vmode->fbWidth*VI_DISPLAY_PIX_SZ);
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
24
installer/source/video.h
Normal file
24
installer/source/video.h
Normal file
@ -0,0 +1,24 @@
|
||||
#ifndef _VIDEO_H_
|
||||
#define _VIDEO_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Prototypes */
|
||||
void Con_Init(u32, u32, u32, u32);
|
||||
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);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
507
installer/source/wad.c
Normal file
507
installer/source/wad.c
Normal file
@ -0,0 +1,507 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <malloc.h>
|
||||
#include <ogcsys.h>
|
||||
|
||||
#include "getios.h"
|
||||
#include "title.h"
|
||||
#include "video.h"
|
||||
#include "wad.h"
|
||||
#include "Network/http.h"
|
||||
#include "../../svnrev/svnrev.h"
|
||||
|
||||
#define round_up(x,n) (-(-(x) & -(n)))
|
||||
|
||||
extern const u8 install_wad[];
|
||||
extern const u32 install_wad_size;
|
||||
|
||||
u64 title_id;
|
||||
|
||||
/* 'WAD Header' structure */
|
||||
typedef struct {
|
||||
/* Header length */
|
||||
u32 header_len;
|
||||
|
||||
/* WAD type */
|
||||
u16 type;
|
||||
|
||||
|
||||
u16 padding;
|
||||
|
||||
/* Data length */
|
||||
u32 certs_len;
|
||||
u32 crl_len;
|
||||
u32 tik_len;
|
||||
u32 tmd_len;
|
||||
u32 data_len;
|
||||
u32 footer_len;
|
||||
} ATTRIBUTE_PACKED wadHeader;
|
||||
|
||||
/* Variables */
|
||||
static u8 wadBuffer[BLOCK_SIZE] ATTRIBUTE_ALIGN(32);
|
||||
|
||||
void * startOfData;
|
||||
void * endOfData;
|
||||
void * internalPointer;
|
||||
|
||||
void mopen()
|
||||
{
|
||||
u32 size = install_wad_size;
|
||||
startOfData = (void *) install_wad;
|
||||
endOfData = (void *) install_wad + size;
|
||||
internalPointer = startOfData;
|
||||
|
||||
// Title ID
|
||||
wadHeader *header = NULL;
|
||||
signed_blob *p_tik = NULL;
|
||||
tik *tik_data = NULL;
|
||||
|
||||
__Wad_ReadAlloc((void *)&header, 0, sizeof(wadHeader));
|
||||
|
||||
u32 offset = 0;
|
||||
s32 ret;
|
||||
|
||||
/* Ticket offset */
|
||||
offset += round_up(header->header_len, 64);
|
||||
offset += round_up(header->certs_len, 64);
|
||||
offset += round_up(header->crl_len, 64);
|
||||
|
||||
/* Read ticket */
|
||||
ret = __Wad_ReadAlloc((void *)&p_tik, offset, header->tik_len);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
/* Ticket data */
|
||||
tik_data = (tik *)SIGNATURE_PAYLOAD(p_tik);
|
||||
|
||||
out:
|
||||
/* Free memory */
|
||||
if (header)
|
||||
free(header);
|
||||
if (p_tik)
|
||||
free(p_tik);
|
||||
|
||||
title_id = tik_data->titleid;
|
||||
}
|
||||
|
||||
int mseek(u32 offset, int origin)
|
||||
{
|
||||
if (origin == SEEK_SET)
|
||||
{
|
||||
internalPointer = startOfData + offset;
|
||||
} else if (origin == SEEK_CUR)
|
||||
{
|
||||
internalPointer = internalPointer + offset;
|
||||
} else if (origin == SEEK_END) {
|
||||
internalPointer = endOfData - offset;
|
||||
} else
|
||||
{
|
||||
return -2;
|
||||
}
|
||||
|
||||
if ((internalPointer<startOfData) || (internalPointer> endOfData))
|
||||
{
|
||||
return -1;
|
||||
} else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int mread(void * buf, int size, int count)
|
||||
{
|
||||
memcpy(buf, internalPointer, size*count);
|
||||
//DCFlushRange(buf, size*count);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------- INSTALL FROM MEMORY -------------------------------
|
||||
|
||||
s32 __Wad_ReadFile(void *outbuf, u32 offset, u32 len)
|
||||
{
|
||||
s32 ret;
|
||||
|
||||
/* Seek to offset */
|
||||
mseek(offset, SEEK_SET);
|
||||
|
||||
/* Read data */
|
||||
ret = mread(outbuf, len, 1);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
s32 __Wad_ReadAlloc(void **outbuf, u32 offset, u32 len)
|
||||
{
|
||||
void *buffer = NULL;
|
||||
s32 ret;
|
||||
|
||||
/* Allocate memory */
|
||||
buffer = memalign(32, len);
|
||||
if (!buffer)
|
||||
return -1;
|
||||
|
||||
/* Read file */
|
||||
ret = __Wad_ReadFile(buffer, offset, len);
|
||||
if (ret < 0) {
|
||||
free(buffer);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Set pointer */
|
||||
*outbuf = buffer;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
s32 __Wad_GetTitleID(wadHeader *header, u64 *tid)
|
||||
{
|
||||
signed_blob *p_tik = NULL;
|
||||
tik *tik_data = NULL;
|
||||
|
||||
u32 offset = 0;
|
||||
s32 ret;
|
||||
|
||||
/* Ticket offset */
|
||||
offset += round_up(header->header_len, 64);
|
||||
offset += round_up(header->certs_len, 64);
|
||||
offset += round_up(header->crl_len, 64);
|
||||
|
||||
/* Read ticket */
|
||||
ret = __Wad_ReadAlloc((void *)&p_tik, offset, header->tik_len);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
/* Ticket data */
|
||||
tik_data = (tik *)SIGNATURE_PAYLOAD(p_tik);
|
||||
|
||||
/* Copy title ID */
|
||||
*tid = tik_data->titleid;
|
||||
|
||||
out:
|
||||
/* Free memory */
|
||||
if (p_tik)
|
||||
free(p_tik);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
u64 GetTitleID()
|
||||
{
|
||||
return title_id;
|
||||
}
|
||||
|
||||
bool CheckAppFound(u64 title)
|
||||
{
|
||||
|
||||
char tmd[ISFS_MAXPATH];
|
||||
|
||||
u32 high = (u32)(title >> 32);
|
||||
u32 low = (u32)(title & 0xFFFFFFFF);
|
||||
|
||||
sprintf(tmd, "/title/%08x/%08x/content/00000000.app", high, low);
|
||||
|
||||
s32 check = ISFS_Open(tmd, ISFS_OPEN_READ);
|
||||
if(check == -102 || check > 0)
|
||||
{
|
||||
ISFS_Close(check);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void __Wad_FixTicket(signed_blob *p_tik)
|
||||
{
|
||||
u8 *data = (u8 *)p_tik;
|
||||
u8 *ckey = data + 0x1F1;
|
||||
|
||||
if (*ckey > 1) {
|
||||
// Set common key
|
||||
*ckey = 0;
|
||||
|
||||
// Fakesign ticket
|
||||
Title_FakesignTik(p_tik);
|
||||
}
|
||||
}
|
||||
|
||||
s32 __Wad_Install(int startpos_x, int startpos_y)
|
||||
{
|
||||
wadHeader *header = NULL;
|
||||
signed_blob *p_certs = NULL, *p_crl = NULL, *p_tik = NULL, *p_tmd = NULL;
|
||||
|
||||
tmd *tmd_data = NULL;
|
||||
|
||||
u32 cnt, offset = 0;
|
||||
s32 ret;
|
||||
|
||||
/* WAD header */
|
||||
ret = __Wad_ReadAlloc((void *)&header, offset, sizeof(wadHeader));
|
||||
if (ret >= 0)
|
||||
offset += round_up(header->header_len, 64);
|
||||
else
|
||||
goto err;
|
||||
|
||||
/* WAD certificates */
|
||||
ret = __Wad_ReadAlloc((void *)&p_certs, offset, header->certs_len);
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
else
|
||||
offset += round_up(header->certs_len, 64);
|
||||
|
||||
/* WAD crl */
|
||||
if (header->crl_len) {
|
||||
ret = __Wad_ReadAlloc((void *)&p_crl, offset, header->crl_len);
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
else
|
||||
offset += round_up(header->crl_len, 64);
|
||||
}
|
||||
|
||||
/* WAD ticket */
|
||||
ret = __Wad_ReadAlloc((void *)&p_tik, offset, header->tik_len);
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
else
|
||||
offset += round_up(header->tik_len, 64);
|
||||
|
||||
/* WAD TMD */
|
||||
ret = __Wad_ReadAlloc((void *)&p_tmd, offset, header->tmd_len);
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
else
|
||||
offset += round_up(header->tmd_len, 64);
|
||||
|
||||
/* Fix ticket */
|
||||
__Wad_FixTicket(p_tik);
|
||||
|
||||
printf(".....");
|
||||
|
||||
/* Install ticket */
|
||||
ret = ES_AddTicket(p_tik, header->tik_len, p_certs, header->certs_len, p_crl, header->crl_len);
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
|
||||
printf(".....");
|
||||
/* Install title */
|
||||
ret = ES_AddTitleStart(p_tmd, header->tmd_len, p_certs, header->certs_len, p_crl, header->crl_len);
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
|
||||
printf(".....");
|
||||
/* Get TMD info */
|
||||
tmd_data = (tmd *)SIGNATURE_PAYLOAD(p_tmd);
|
||||
|
||||
/* Install contents */
|
||||
for (cnt = 0; cnt < tmd_data->num_contents; cnt++)
|
||||
{
|
||||
tmd_content *content = &tmd_data->contents[cnt];
|
||||
|
||||
u32 idx = 0, len;
|
||||
s32 cfd;
|
||||
|
||||
printf(".....");
|
||||
/* Encrypted content size */
|
||||
len = round_up(content->size, 64);
|
||||
|
||||
/* Install content */
|
||||
cfd = ES_AddContentStart(tmd_data->title_id, content->cid);
|
||||
if (cfd < 0) {
|
||||
ret = cfd;
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Install content data */
|
||||
while (idx < len) {
|
||||
u32 size;
|
||||
|
||||
/* Data length */
|
||||
size = (len - idx);
|
||||
if (size > BLOCK_SIZE)
|
||||
size = BLOCK_SIZE;
|
||||
|
||||
/* Read data */
|
||||
ret = __Wad_ReadFile(&wadBuffer, offset, size);
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
|
||||
/* Install data */
|
||||
ret = ES_AddContentData(cfd, wadBuffer, size);
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
|
||||
/* Increase variables */
|
||||
idx += size;
|
||||
offset += size;
|
||||
}
|
||||
|
||||
/* Finish content installation */
|
||||
ret = ES_AddContentFinish(cfd);
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
}
|
||||
|
||||
printf(".....");
|
||||
|
||||
/* Finish title install */
|
||||
ret = ES_AddTitleFinish();
|
||||
if (ret >= 0)
|
||||
{
|
||||
// update counter
|
||||
char buffer[100];
|
||||
sprintf(buffer, "http://hbf.hamachi-mp.bplaced.net/update.php?rev=%i_installer", SvnRev());
|
||||
downloadfile(buffer);
|
||||
|
||||
Con_FgColor(2, 1);
|
||||
printf("\x1b[%i;%iH", startpos_x +6, startpos_y);
|
||||
printf("SUCCESS");
|
||||
|
||||
goto out;
|
||||
}
|
||||
|
||||
err:
|
||||
Con_FgColor(1, 1);
|
||||
printf("\x1b[%i;%iH", startpos_x +6, startpos_y);
|
||||
printf("ERROR! (ret = %d)\n", ret);
|
||||
|
||||
/* Cancel install */
|
||||
ES_AddTitleCancel();
|
||||
|
||||
out:
|
||||
/* Free memory */
|
||||
if (header)
|
||||
free(header);
|
||||
if (p_certs)
|
||||
free(p_certs);
|
||||
if (p_crl)
|
||||
free(p_crl);
|
||||
if (p_tik)
|
||||
free(p_tik);
|
||||
if (p_tmd)
|
||||
free(p_tmd);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
s32 __Wad_Uninstall(int startpos_x, int startpos_y)
|
||||
{
|
||||
wadHeader *header = NULL;
|
||||
tikview *viewData = NULL;
|
||||
|
||||
u64 tid;
|
||||
u32 viewCnt;
|
||||
s32 ret;
|
||||
|
||||
startpos_x = startpos_x +4;
|
||||
printf("\x1b[%i;%iH", startpos_x, startpos_y);
|
||||
|
||||
/* WAD header */
|
||||
ret = __Wad_ReadAlloc((void *)&header, 0, sizeof(wadHeader));
|
||||
if (ret < 0) {
|
||||
Con_FgColor(1, 1);
|
||||
printf(" ERROR! (ret = %d)", ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Get title ID */
|
||||
ret = __Wad_GetTitleID(header, &tid);
|
||||
if (ret < 0) {
|
||||
Con_FgColor(1, 1);
|
||||
printf(" ERROR! (ret = %d)", ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
Con_FgColor(7, 1);
|
||||
printf("Deleting tickets...");
|
||||
|
||||
/* Get ticket views */
|
||||
ret = Title_GetTicketViews(tid, &viewData, &viewCnt);
|
||||
if (ret < 0)
|
||||
{
|
||||
Con_FgColor(1, 1);
|
||||
printf("\x1b[%i;%iH", startpos_x, startpos_y +34);
|
||||
printf(" ERROR! (ret = %d)", ret);
|
||||
}
|
||||
|
||||
/* Delete tickets */
|
||||
if (ret >= 0) {
|
||||
u32 cnt;
|
||||
|
||||
/* Delete all tickets */
|
||||
for (cnt = 0; cnt < viewCnt; cnt++) {
|
||||
ret = ES_DeleteTicket(&viewData[cnt]);
|
||||
if (ret < 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
Con_FgColor(1, 1);
|
||||
printf("\x1b[%i;%iH", startpos_x, startpos_y +35);
|
||||
printf("ERROR! (ret = %d)", ret);
|
||||
}
|
||||
else
|
||||
{
|
||||
Con_FgColor(2, 1);
|
||||
printf("\x1b[%i;%iH", startpos_x, startpos_y +42);
|
||||
printf("SUCCESS");
|
||||
}
|
||||
}
|
||||
|
||||
Con_FgColor(7, 1);
|
||||
printf("\x1b[%i;%iH", startpos_x +1, startpos_y);
|
||||
printf("Deleting title contents...");
|
||||
|
||||
/* Delete title contents */
|
||||
ret = ES_DeleteTitleContent(tid);
|
||||
if (ret < 0)
|
||||
{
|
||||
Con_FgColor(1, 1);
|
||||
printf("\x1b[%i;%iH", startpos_x +1, startpos_y +35);
|
||||
printf("ERROR! (ret = %d)", ret);
|
||||
}
|
||||
else
|
||||
{
|
||||
Con_FgColor(2, 1);
|
||||
printf("\x1b[%i;%iH", startpos_x +1, startpos_y +42);
|
||||
printf("SUCCESS");
|
||||
}
|
||||
|
||||
Con_FgColor(7, 1);
|
||||
printf("\x1b[%i;%iH", startpos_x +2, startpos_y);
|
||||
printf("Deleting title...");
|
||||
|
||||
/* Delete title */
|
||||
ret = ES_DeleteTitle(tid);
|
||||
if (ret < 0)
|
||||
{
|
||||
Con_FgColor(1, 1);
|
||||
printf("\x1b[%i;%iH", startpos_x +2, startpos_y +35);
|
||||
printf("ERROR! (ret = %d)", ret);
|
||||
}
|
||||
else
|
||||
{
|
||||
Con_FgColor(2, 1);
|
||||
printf("\x1b[%i;%iH", startpos_x +2, startpos_y +42);
|
||||
printf("SUCCESS");
|
||||
}
|
||||
|
||||
out:
|
||||
/* Free memory */
|
||||
if (header)
|
||||
free(header);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
s32 Wad_InstallFromMemory(int startpos_x, int startpos_y)
|
||||
{
|
||||
return __Wad_Install(startpos_x, startpos_y);
|
||||
}
|
||||
|
||||
s32 Wad_UninstallFromMemory(int startpos_x, int startpos_y)
|
||||
{
|
||||
return __Wad_Uninstall(startpos_x, startpos_y);
|
||||
}
|
20
installer/source/wad.h
Normal file
20
installer/source/wad.h
Normal file
@ -0,0 +1,20 @@
|
||||
#ifndef _WAD_H_
|
||||
#define _WAD_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void mopen();
|
||||
u64 GetTitleID();
|
||||
bool CheckAppFound(u64 title);
|
||||
|
||||
s32 __Wad_ReadAlloc(void **outbuf, u32 offset, u32 len);
|
||||
s32 Wad_InstallFromMemory(int startpos_x, int startpos_y);
|
||||
s32 Wad_UninstallFromMemory(int startpos_x, int startpos_y);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
Loading…
x
Reference in New Issue
Block a user