mirror of
https://github.com/wiidev/usbloadergx.git
synced 2024-11-22 19:29:18 +01:00
6850d68074
*Added proper deinitialize of usb before starting game / exiting app. This is supposed to fix Blackops multiplayer mode (Did not test it. I don't have that game.) *Added Wii message board update (Playlog) (thanks to dkosmari for a starting point). This feature can be enabled/disabled in the global settings. Default is ON. *Removed unused sources.
160 lines
3.3 KiB
C++
160 lines
3.3 KiB
C++
#include <malloc.h>
|
|
#include <stdio.h>
|
|
#include "usbloader/disc.h"
|
|
#include "usbloader/wbfs.h"
|
|
#include "utils/uncompress.h"
|
|
#include "OpeningBNR.hpp"
|
|
|
|
typedef struct _IMD5Header
|
|
{
|
|
u32 fcc;
|
|
u32 filesize;
|
|
u8 zeroes[8];
|
|
u8 crypto[16];
|
|
} __attribute__((packed)) IMD5Header;
|
|
|
|
typedef struct _U8Header
|
|
{
|
|
u32 fcc;
|
|
u32 rootNodeOffset;
|
|
u32 headerSize;
|
|
u32 dataOffset;
|
|
u8 zeroes[16];
|
|
} __attribute__((packed)) U8Header;
|
|
|
|
typedef struct _U8Entry
|
|
{
|
|
struct
|
|
{
|
|
u32 fileType :8;
|
|
u32 nameOffset :24;
|
|
};
|
|
u32 fileOffset;
|
|
union
|
|
{
|
|
u32 fileLength;
|
|
u32 numEntries;
|
|
};
|
|
} __attribute__( ( packed ) ) U8Entry;
|
|
|
|
|
|
static inline const char * u8Filename(const U8Entry *fst, int i)
|
|
{
|
|
return (char *) (fst + fst[0].numEntries) + fst[i].nameOffset;
|
|
}
|
|
|
|
BNRInstance * BNRInstance::instance = NULL;
|
|
|
|
OpeningBNR::OpeningBNR()
|
|
: imetHdr(0)
|
|
{
|
|
memset(gameID, 0, sizeof(gameID));
|
|
}
|
|
|
|
OpeningBNR::~OpeningBNR()
|
|
{
|
|
if(imetHdr)
|
|
free(imetHdr);
|
|
}
|
|
|
|
bool OpeningBNR::Load(const u8 * discid)
|
|
{
|
|
if(!discid)
|
|
return false;
|
|
|
|
if(memcmp(gameID, discid, 6) == 0)
|
|
return true;
|
|
|
|
if(imetHdr)
|
|
free(imetHdr);
|
|
imetHdr = NULL;
|
|
snprintf(gameID, sizeof(gameID), (const char *) discid);
|
|
|
|
wbfs_disc_t *disc = WBFS_OpenDisc((u8 *) gameID);
|
|
if (!disc)
|
|
return false;
|
|
|
|
wiidisc_t *wdisc = wd_open_disc((int(*)(void *, u32, u32, void *)) wbfs_disc_read, disc);
|
|
if (!wdisc)
|
|
{
|
|
WBFS_CloseDisc(disc);
|
|
return false;
|
|
}
|
|
|
|
imetHdr = (IMETHeader*) wd_extract_file(wdisc, ALL_PARTITIONS, (char *) "opening.bnr");
|
|
|
|
wd_close_disc(wdisc);
|
|
WBFS_CloseDisc(disc);
|
|
|
|
if(!imetHdr)
|
|
return false;
|
|
|
|
if (imetHdr->fcc != 'IMET')
|
|
{
|
|
free(imetHdr);
|
|
imetHdr = NULL;
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
const u16 * OpeningBNR::GetIMETTitle(int lang)
|
|
{
|
|
if(!imetHdr || lang < 0 || lang >= 10)
|
|
return NULL;
|
|
|
|
if(imetHdr->names[lang][0] == 0)
|
|
lang = CONF_LANG_ENGLISH;
|
|
|
|
return imetHdr->names[lang];
|
|
}
|
|
|
|
const u8 * OpeningBNR::GetBannerSound(u32 * size)
|
|
{
|
|
if(!imetHdr)
|
|
return NULL;
|
|
|
|
const U8Header *bnrArcHdr = (U8Header *) (imetHdr + 1);
|
|
const U8Entry *fst = (const U8Entry *) (((const u8 *) bnrArcHdr) + bnrArcHdr->rootNodeOffset);
|
|
|
|
u32 i;
|
|
for (i = 1; i < fst[0].numEntries; ++i)
|
|
if (fst[i].fileType == 0 && strcasecmp(u8Filename(fst, i), "sound.bin") == 0) break;
|
|
|
|
if (i >= fst[0].numEntries)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
const u8 *sound_bin = ((const u8 *) bnrArcHdr) + fst[i].fileOffset;
|
|
if (((IMD5Header *) sound_bin)->fcc != 'IMD5')
|
|
{
|
|
return NULL;
|
|
}
|
|
const u8 *soundChunk = sound_bin + sizeof(IMD5Header);
|
|
u32 soundChunkSize = fst[i].fileLength - sizeof(IMD5Header);
|
|
|
|
if (*((u32*) soundChunk) == 'LZ77')
|
|
{
|
|
u32 uncSize = 0;
|
|
u8 * uncompressed_data = uncompressLZ77(soundChunk, soundChunkSize, &uncSize);
|
|
if (!uncompressed_data)
|
|
{
|
|
return NULL;
|
|
}
|
|
if (size) *size = uncSize;
|
|
|
|
return uncompressed_data;
|
|
}
|
|
|
|
u8 *out = (u8 *) malloc(soundChunkSize);
|
|
if (out)
|
|
{
|
|
memcpy(out, soundChunk, soundChunkSize);
|
|
if (size) *size = soundChunkSize;
|
|
}
|
|
|
|
return out;
|
|
}
|