CfgUSBLoader/source/channel.c
2015-01-17 17:50:43 +00:00

367 lines
8.5 KiB
C

#include <gccore.h>
#include <string.h>
#include <malloc.h>
#include <stdio.h>
#include <dirent.h>
#include "isfs.h"
#include "channel.h"
#include "sys.h"
#include "nand.h"
#include "debug.h"
#include "util.h"
#include "disc.h"
#include "cfg.h"
#include "fileOps.h"
bool check_text(char *s)
{
int i = 0;
for(i=0; i < strlen(s); i++)
{
if (s[i] < 32 || s[i] > 165)
{
s[i] = '?';
//return false;
}
}
return true;
}
char *get_name_from_banner_buffer(u8 *buffer)
{
char *out;
u32 length;
u32 i = 0;
while (buffer[0x21 + i*2] != 0x00)
{
i++;
}
length = i;
if (length == 0)
return NULL;
out = allocate_memory(length+12);
if(out == NULL)
{
dbg_printf("Allocating memory for buffer failed\n");
return NULL;
}
memset(out, 0x00, length+12);
i = 0;
while (buffer[0x21 + i*2] != 0x00)
{
out[i] = (char) buffer[0x21 + i*2];
i++;
}
return out;
}
char *read_name_from_open_banner_app_file(FILE *fp)
{
u8 *buffer = NULL;
u32 filesize;
u8 imet[4] = {0x49, 0x4D, 0x45, 0x54};
if (fp == NULL)
{
return NULL;
}
filesize = 0x640; //dont need whole file first sector is more than enough
buffer = mem2_alloc(filesize);
fread(buffer, 1, filesize, fp);
if (memcmp((buffer+0x80), imet, 4) == 0)
{
char *out = get_name_from_banner_buffer((void *)((u32)buffer+208));
SAFE_FREE(buffer);
return out;
}
SAFE_FREE(buffer);
return NULL;
}
char *read_name_from_banner_app(u64 titleid)
{
u8 *buffer = NULL;
u32 filesize;
DIR *sdir;
FILE *fp;
struct dirent *entry;
static char path_buffer[255] ATTRIBUTE_ALIGN(32);
u8 imet[4] = {0x49, 0x4D, 0x45, 0x54};
sprintf(path_buffer, "%s/title/%08x/%08x/content", CFG.nand_emu_path, TITLE_UPPER(titleid), TITLE_LOWER(titleid));
dbg_printf("opendir(%s)\n", path_buffer);
sdir = opendir(path_buffer);
if (sdir) do {
entry = readdir(sdir);
if (entry)
{
if (!strncmp(entry->d_name, ".", 1) || !strncmp(entry->d_name, "..", 2))
{
continue;
}
sprintf(path_buffer, "%s/title/%08x/%08x/content/%s", CFG.nand_emu_path, TITLE_UPPER(titleid), TITLE_LOWER(titleid), entry->d_name);
dbg_printf("fopen(%s)\n", path_buffer);
fp = fopen(path_buffer, "rb");
if (fp == NULL)
{
continue;
}
fseek (fp, 0, SEEK_END);
filesize = ftell(fp);
fseek (fp, 0, SEEK_SET);
dbg_printf("filesize = %d\n", filesize);
filesize = 0x640; //dont need whole file first sector is more than enough
buffer = mem2_alloc(filesize);
fread(buffer, 1, filesize, fp);
dbg_printf("fclose\n");
fclose (fp);
if (memcmp((buffer+0x80), imet, 4) == 0)
{
dbg_printf("get_name_from_banner_buffer(%s)\n", entry->d_name);
char *out = get_name_from_banner_buffer((void *)((u32)buffer+208));
if (out == NULL)
{
SAFE_FREE(buffer);
closedir(sdir);
return NULL;
}
SAFE_FREE(buffer);
closedir(sdir);
return out;
}
SAFE_FREE(buffer);
}
} while (entry);
if (sdir) closedir(sdir);
dbg_printf("read_name_from_banner_app END\n");
return NULL;
}
char *read_name_from_banner_bin(u64 titleid)
{
char path[ISFS_MAXPATH] ATTRIBUTE_ALIGN(32);
u8 *buffer = NULL;
u32 filesize;
FILE *fp;
sprintf(path, "%s/title/%08x/%08x/data/banner.bin", CFG.nand_emu_path, TITLE_UPPER(titleid), TITLE_LOWER(titleid));
fp = fopen(path, "rb");
if (fp == NULL)
{
return NULL;
}
filesize = 0xff; //dont need whole file first sector is more than enough
buffer = mem2_alloc(filesize);
fread(buffer, 1, filesize, fp);
fclose (fp);
char *out = get_name_from_banner_buffer(buffer);
if (out == NULL)
{
SAFE_FREE(buffer);
return NULL;
}
SAFE_FREE(buffer);
return out;
}
// fp is an already open app file containing the name which is much faster or it may be NULL
char *get_channel_name(u64 titleid, FILE *fp)
{
char *temp = NULL;
u32 low;
low = TITLE_LOWER(titleid);
// TODO
// dbg_printf("Getting the name for: %08x...\n", titleid);
temp = read_name_from_open_banner_app_file(fp);
if (temp == NULL)
temp = read_name_from_banner_bin(titleid);
if (temp == NULL)
{
dbg_printf("read_name_from_banner_bin failed...\n");
temp = read_name_from_banner_app(titleid);
}
if (temp != NULL)
{
check_text(temp);
if (*(char *)&low == 'W')
{
return temp;
}
switch(low & 0xFF)
{
case 'E':
memcpy(temp+strlen(temp), " (NTSC-U)", 9);
break;
case 'P':
memcpy(temp+strlen(temp), " (PAL)", 6);
break;
case 'J':
memcpy(temp+strlen(temp), " (NTSC-J)", 9);
break;
case 'L':
memcpy(temp+strlen(temp), " (PAL)", 6);
break;
case 'N':
memcpy(temp+strlen(temp), " (NTSC-U)", 9);
break;
case 'M':
memcpy(temp+strlen(temp), " (PAL)", 6);
break;
case 'K':
memcpy(temp+strlen(temp), " (NTSC)", 7);
break;
default:
break;
}
}
if (temp == NULL)
{
temp = allocate_memory(6);
memset(temp, 0, 6);
memcpy(temp, (char *)(&low), 4);
}
// dbg_printf("Found name: %s...\n", temp);
return temp;
}
int CHANNEL_Banner(struct discHdr *hdr, SoundInfo *snd)
{
void *banner = NULL;
//dbg_printf("WBFS_Banner(%.6s %d %d)\n", discid, getSound, getTitle);
static char path_buffer[255] ATTRIBUTE_ALIGN(32);
snd->dsp_data = NULL;
u8 *buffer = NULL;
u32 filesize;
DIR *sdir;
FILE *fp;
struct dirent *entry;
u8 imet[4] = {0x49, 0x4D, 0x45, 0x54};
sprintf(path_buffer, "%s/title/00010001/%02x%02x%02x%02x/data/banner.bin", CFG.nand_emu_path, hdr->id[0], hdr->id[1], hdr->id[2], hdr->id[3]);
// TODO banner.bin appears to never have the required audio info someone else fix the code if it does
// until then changed it to always get the banner sound from the content dir
// instead of just when banner.bin dosent exist
// fp = fopen(path_buffer, "rb");
// if (fp == NULL)
// {
sprintf(path_buffer, "%s/title/00010001/%02x%02x%02x%02x/content", CFG.nand_emu_path, hdr->id[0], hdr->id[1], hdr->id[2], hdr->id[3]);
sdir = opendir(path_buffer);
if (sdir) {
do {
entry = readdir(sdir);
if (entry)
{
if (!strncmp(entry->d_name, ".", 1) || !strncmp(entry->d_name, "..", 2))
{
continue;
}
sprintf(path_buffer, "%s/title/00010001/%02x%02x%02x%02x/content/%s", CFG.nand_emu_path, hdr->id[0], hdr->id[1], hdr->id[2], hdr->id[3], entry->d_name);
fp = fopen(path_buffer, "rb");
if (fp == NULL)
{
continue;
}
fseek (fp, 0, SEEK_END);
filesize = ftell(fp);
fseek (fp, 0, SEEK_SET);
buffer = mem2_alloc(filesize);
if (buffer == NULL)
{
fclose (fp);
continue; //skip files bigger than memory
}
fread(buffer, 1, filesize, fp);
fclose (fp);
if (memcmp((buffer+0x80), imet, 4) == 0)
{
banner = mem2_alloc(filesize-0x40);
memcpy(banner, buffer+0x40, filesize-0x40);
SAFE_FREE(buffer);
break;
}
SAFE_FREE(buffer);
}
} while (entry);
closedir(sdir);
}
// } else {
// fseek (fp, 0, SEEK_END);
// filesize = ftell(fp);
// fseek (fp, 0, SEEK_SET);
// banner = mem2_alloc(filesize);
// fread(banner, 1, filesize, fp);
// fclose (fp);
// }
if (banner != NULL)
parse_banner_snd(banner, snd);
SAFE_FREE(banner);
return 0;
}
u64 getChannelSize(struct discHdr *hdr) {
static char path_buffer[255] ATTRIBUTE_ALIGN(32);
sprintf(path_buffer, "%s/title/00010001/%02x%02x%02x%02x", CFG.nand_emu_path, hdr->id[0], hdr->id[1], hdr->id[2], hdr->id[3]);
return fsop_GetFolderBytes(path_buffer);
}
u64 getChannelReqIos(struct discHdr *hdr) {
u64 ReqIos = 0;
static char path_buffer[255] ATTRIBUTE_ALIGN(32);
sprintf(path_buffer, "%s/title/00010001/%02x%02x%02x%02x/content/title.tmd", CFG.nand_emu_path, hdr->id[0], hdr->id[1], hdr->id[2], hdr->id[3]);
FILE *fp = fopen(path_buffer, "rb");
if (fp) {
fseek(fp, 0x184 , SEEK_SET);
fread(&(ReqIos), 8, 1, fp);
fclose(fp);
}
return ReqIos;
}
s32 Channel_RemoveGame(struct discHdr *hdr) {
static char path_buffer[255] ATTRIBUTE_ALIGN(32);
sprintf(path_buffer, "%s/ticket/00010001/%02x%02x%02x%02x.tik", CFG.nand_emu_path, hdr->id[0], hdr->id[1], hdr->id[2], hdr->id[3]);
remove(path_buffer);
sprintf(path_buffer, "%s/title/00010001/%02x%02x%02x%02x", CFG.nand_emu_path, hdr->id[0], hdr->id[1], hdr->id[2], hdr->id[3]);
fsop_deleteFolder(path_buffer);
return 0;
}