-completely new memory manager which should be faster and safer than the old one

-only use the internal wii aes hardware if we do have hardware access (should fix dolphin-emu and neek2o)
-(hopefully) made the gc installer and the wait message display safer
-code cleanup, removed some unneeded stuff
-increased our usable mem2 by 1mb
This commit is contained in:
fix94.1 2013-12-21 17:02:36 +00:00
parent 0509e80edd
commit 6b663fe2d9
21 changed files with 892 additions and 402 deletions

View File

@ -6,7 +6,7 @@
#include "memory/mem2.hpp" #include "memory/mem2.hpp"
#include "video.hpp" #include "video.hpp"
#include "pngu.h" #include "pngu.h"
#include "Gekko.h" #include "hw/Gekko.h"
#include "gecko/gecko.hpp" #include "gecko/gecko.hpp"
#include "loader/sys.h" #include "loader/sys.h"
#include "loader/utils.h" #include "loader/utils.h"
@ -526,8 +526,6 @@ void CVideo::_showWaitMessages(CVideo *m)
m->prepare(); m->prepare();
m->setup2DProjection(); m->setup2DProjection();
wiiLightSetLevel(0);
wiiLightOn();
//gprintf("Wait Message Thread: Start\nDelay: %d, Images: %d\n", waitFrames, m->m_waitMessages.size()); //gprintf("Wait Message Thread: Start\nDelay: %d, Images: %d\n", waitFrames, m->m_waitMessages.size());
while(m->m_showWaitMessage) while(m->m_showWaitMessage)
@ -558,7 +556,6 @@ void CVideo::_showWaitMessages(CVideo *m)
VIDEO_WaitVSync(); VIDEO_WaitVSync();
waitFrames--; waitFrames--;
} }
wiiLightOff();
//gprintf("Wait Message Thread: End\n"); //gprintf("Wait Message Thread: End\n");
m->m_showingWaitMessages = false; m->m_showingWaitMessages = false;
} }
@ -571,6 +568,7 @@ void CVideo::hideWaitMessage()
m_showWaitMessage = false; m_showWaitMessage = false;
if(waitThread != LWP_THREAD_NULL) if(waitThread != LWP_THREAD_NULL)
{ {
/* end animation */
if(LWP_ThreadIsSuspended(waitThread)) if(LWP_ThreadIsSuspended(waitThread))
LWP_ResumeThread(waitThread); LWP_ResumeThread(waitThread);
while(m_showingWaitMessages) while(m_showingWaitMessages)
@ -579,6 +577,8 @@ void CVideo::hideWaitMessage()
if(waitMessageStack != NULL) if(waitMessageStack != NULL)
MEM2_free(waitMessageStack); MEM2_free(waitMessageStack);
waitMessageStack = NULL; waitMessageStack = NULL;
/* end light thread */
wiiLightEndThread();
m_WaitThreadRunning = false; m_WaitThreadRunning = false;
} }
waitThread = LWP_THREAD_NULL; waitThread = LWP_THREAD_NULL;
@ -623,6 +623,10 @@ void CVideo::waitMessage(const vector<TexData> &tex, float delay)
waitMessage(m_waitMessages[0]); waitMessage(m_waitMessages[0]);
else if(m_waitMessages.size() > 1) else if(m_waitMessages.size() > 1)
{ {
/* changing light */
wiiLightSetLevel(0);
wiiLightStartThread();
/* onscreen animation */
m_showWaitMessage = true; m_showWaitMessage = true;
if(waitMessageStack == NULL) if(waitMessageStack == NULL)
waitMessageStack = (u8*)MEM2_memalign(32, waitMessageStackSize); waitMessageStack = (u8*)MEM2_memalign(32, waitMessageStackSize);

View File

@ -28,8 +28,6 @@
#include "Gekko.h" #include "Gekko.h"
#include "memory/memory.h" #include "memory/memory.h"
#define DISC_SLOT_LED 0x20
lwp_t light_thread = LWP_THREAD_NULL; lwp_t light_thread = LWP_THREAD_NULL;
void *light_loop(); void *light_loop();
@ -39,7 +37,18 @@ u8 light_level = 0;
struct timespec light_timeon; struct timespec light_timeon;
struct timespec light_timeoff; struct timespec light_timeoff;
// Wii disc slot light routines
void wiiLightOn() void wiiLightOn()
{
*HW_GPIOB_OUT |= DISC_SLOT_LED;
}
void wiiLightOff()
{
*HW_GPIOB_OUT &= ~DISC_SLOT_LED;
}
void wiiLightStartThread()
{ {
light_on = true; light_on = true;
light_level = 0; light_level = 0;
@ -47,13 +56,14 @@ void wiiLightOn()
LWP_CreateThread(&light_thread, light_loop, NULL, NULL, 0, LWP_PRIO_HIGHEST); LWP_CreateThread(&light_thread, light_loop, NULL, NULL, 0, LWP_PRIO_HIGHEST);
} }
void wiiLightOff() void wiiLightEndThread()
{ {
light_on = false; light_on = false;
light_level = 0; light_level = 0;
if(light_thread != LWP_THREAD_NULL)
LWP_JoinThread(light_thread, NULL); LWP_JoinThread(light_thread, NULL);
light_thread = LWP_THREAD_NULL; light_thread = LWP_THREAD_NULL;
*HW_GPIOB_OUT &= ~DISC_SLOT_LED; wiiLightOff();
} }
void wiiLightSetLevel(int level) void wiiLightSetLevel(int level)
@ -89,11 +99,11 @@ void *light_loop()
timeon = light_timeon; timeon = light_timeon;
timeoff = light_timeoff; timeoff = light_timeoff;
// Turn on the light and sleep for a bit // Turn on the light and sleep for a bit
*HW_GPIOB_OUT |= DISC_SLOT_LED; wiiLightOn();
nanosleep(&timeon); nanosleep(&timeon);
// Turn off the light (if required) and sleep for a bit // Turn off the light (if required) and sleep for a bit
if(timeoff.tv_nsec > 0) if(timeoff.tv_nsec > 0)
*HW_GPIOB_OUT &= ~DISC_SLOT_LED; wiiLightOff();
nanosleep(&timeoff); nanosleep(&timeoff);
} }
return NULL; return NULL;

View File

@ -27,9 +27,13 @@
extern "C" { extern "C" {
#endif #endif
static const u32 DISC_SLOT_LED = 0x20;
// Wii disc slot light routines // Wii disc slot light routines
void wiiLightOn(); void wiiLightOn();
void wiiLightOff(); void wiiLightOff();
void wiiLightStartThread();
void wiiLightEndThread();
void wiiLightSetLevel(int level); void wiiLightSetLevel(int level);
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -40,7 +40,7 @@ static u8 size_to_shift(u32 size)
wbfs_t *wbfs_open_hd(rw_sector_callback_t read_hdsector, rw_sector_callback_t write_hdsector, void *callback_data, int hd_sector_size, int num_hd_sector __attribute((unused)), int reset) wbfs_t *wbfs_open_hd(rw_sector_callback_t read_hdsector, rw_sector_callback_t write_hdsector, void *callback_data, int hd_sector_size, int num_hd_sector __attribute((unused)), int reset)
{ {
int i=num_hd_sector,ret; int i=num_hd_sector,ret;
u8 *ptr,*tmp_buffer = wbfs_ioalloc(hd_sector_size); u8 *ptr,*tmp_buffer = wbfs_malloc(hd_sector_size);
u8 part_table[16*4]; u8 part_table[16*4];
ret = read_hdsector(callback_data,0,1,tmp_buffer); ret = read_hdsector(callback_data,0,1,tmp_buffer);
if(ret) if(ret)
@ -57,11 +57,11 @@ wbfs_t *wbfs_open_hd(rw_sector_callback_t read_hdsector, rw_sector_callback_t wr
if (head->magic == wbfs_htonl(WBFS_MAGIC)) if (head->magic == wbfs_htonl(WBFS_MAGIC))
{ {
wbfs_t *p = wbfs_open_partition(read_hdsector, write_hdsector, callback_data, hd_sector_size, 0, part_lba,reset); wbfs_t *p = wbfs_open_partition(read_hdsector, write_hdsector, callback_data, hd_sector_size, 0, part_lba,reset);
wbfs_iofree(tmp_buffer); wbfs_free(tmp_buffer);
return p; return p;
} }
} }
wbfs_iofree(tmp_buffer); wbfs_free(tmp_buffer);
if(reset)// XXX make a empty hd partition.. if(reset)// XXX make a empty hd partition..
{ {
} }
@ -73,7 +73,7 @@ wbfs_t *wbfs_open_partition(rw_sector_callback_t read_hdsector, rw_sector_callba
{ {
wbfs_t *p = wbfs_malloc(sizeof(wbfs_t)); wbfs_t *p = wbfs_malloc(sizeof(wbfs_t));
wbfs_head_t *head = wbfs_ioalloc( hd_sector_size ? hd_sector_size : 512 ); wbfs_head_t *head = wbfs_malloc( hd_sector_size ? hd_sector_size : 512 );
//constants, but put here for consistancy //constants, but put here for consistancy
p->wii_sec_sz = 0x8000; p->wii_sec_sz = 0x8000;
@ -131,20 +131,20 @@ wbfs_t *wbfs_open_partition(rw_sector_callback_t read_hdsector, rw_sector_callba
else else
{ {
// init with all free blocks // init with all free blocks
p->freeblks = wbfs_ioalloc(ALIGN_LBA( p->n_wbfs_sec / 8)); p->freeblks = wbfs_malloc(ALIGN_LBA( p->n_wbfs_sec / 8));
wbfs_memset(p->freeblks, 0xff, p->n_wbfs_sec / 8); wbfs_memset(p->freeblks, 0xff, p->n_wbfs_sec / 8);
} }
p->max_disc = (p->freeblks_lba - 1) / (p->disc_info_sz >> p->hd_sec_sz_s); p->max_disc = (p->freeblks_lba - 1) / (p->disc_info_sz >> p->hd_sec_sz_s);
if(p->max_disc > p->hd_sec_sz - sizeof(wbfs_head_t)) if(p->max_disc > p->hd_sec_sz - sizeof(wbfs_head_t))
p->max_disc = p->hd_sec_sz - sizeof(wbfs_head_t); p->max_disc = p->hd_sec_sz - sizeof(wbfs_head_t);
p->tmp_buffer = wbfs_ioalloc(p->hd_sec_sz); p->tmp_buffer = wbfs_malloc(p->hd_sec_sz);
p->n_disc_open = 0; p->n_disc_open = 0;
return p; return p;
error: error:
wbfs_free(p); wbfs_free(p);
wbfs_iofree(head); wbfs_free(head);
return 0; return 0;
} }
@ -167,10 +167,10 @@ void wbfs_close(wbfs_t *p)
if(p->n_disc_open) if(p->n_disc_open)
ERROR("trying to close wbfs while discs still open\n"); ERROR("trying to close wbfs while discs still open\n");
wbfs_iofree(p->head); wbfs_free(p->head);
wbfs_iofree(p->tmp_buffer); wbfs_free(p->tmp_buffer);
if(p->freeblks) if(p->freeblks)
wbfs_iofree(p->freeblks); wbfs_free(p->freeblks);
wbfs_free(p); wbfs_free(p);
@ -195,7 +195,7 @@ wbfs_disc_t *wbfs_open_disc(wbfs_t* p, const u8 *discid)
ERROR("allocating memory\n"); ERROR("allocating memory\n");
d->p = p; d->p = p;
d->i = i; d->i = i;
d->header = wbfs_ioalloc(p->disc_info_sz); d->header = wbfs_malloc(p->disc_info_sz);
if(!d->header) if(!d->header)
ERROR("allocating memory\n"); ERROR("allocating memory\n");
p->read_hdsector(p->callback_data, p->part_lba + 1 + i * disc_info_sz_lba, disc_info_sz_lba, d->header); p->read_hdsector(p->callback_data, p->part_lba + 1 + i * disc_info_sz_lba, disc_info_sz_lba, d->header);
@ -209,13 +209,13 @@ wbfs_disc_t *wbfs_open_disc(wbfs_t* p, const u8 *discid)
return 0; return 0;
error: error:
if(d) wbfs_iofree(d); if(d) wbfs_free(d);
return 0; return 0;
} }
void wbfs_close_disc(wbfs_disc_t*d) void wbfs_close_disc(wbfs_disc_t*d)
{ {
d->p->n_disc_open --; d->p->n_disc_open --;
wbfs_iofree(d->header); wbfs_free(d->header);
wbfs_free(d); wbfs_free(d);
} }
// offset is pointing 32bit words to address the whole dvd, although len is in bytes // offset is pointing 32bit words to address the whole dvd, although len is in bytes
@ -349,10 +349,10 @@ u32 wbfs_get_disc_info(wbfs_t *p, u32 index,u8 *header,int header_size,u32 *size
memcpy(header, p->tmp_buffer, header_size); memcpy(header, p->tmp_buffer, header_size);
if(size) if(size)
{ {
u8 *header = wbfs_ioalloc(p->disc_info_sz); u8 *header = wbfs_malloc(p->disc_info_sz);
p->read_hdsector(p->callback_data, p->part_lba + 1 + i * disc_info_sz_lba, disc_info_sz_lba, header); p->read_hdsector(p->callback_data, p->part_lba + 1 + i * disc_info_sz_lba, disc_info_sz_lba, header);
u32 sec_used = wbfs_sector_used(p,(wbfs_disc_info_t *)header); u32 sec_used = wbfs_sector_used(p,(wbfs_disc_info_t *)header);
wbfs_iofree(header); wbfs_free(header);
*size = sec_used<<(p->wbfs_sec_sz_s-2); *size = sec_used<<(p->wbfs_sec_sz_s-2);
} }
return 0; return 0;
@ -367,7 +367,7 @@ static void load_freeblocks(wbfs_t *p)
if(p->freeblks) if(p->freeblks)
return; return;
// XXX should handle malloc error.. // XXX should handle malloc error..
p->freeblks = wbfs_ioalloc(ALIGN_LBA(p->n_wbfs_sec/8)); p->freeblks = wbfs_malloc(ALIGN_LBA(p->n_wbfs_sec/8));
p->read_hdsector(p->callback_data, p->part_lba + p->freeblks_lba, ALIGN_LBA(p->n_wbfs_sec / 8) >> p->hd_sec_sz_s, p->freeblks); p->read_hdsector(p->callback_data, p->part_lba + p->freeblks_lba, ALIGN_LBA(p->n_wbfs_sec / 8) >> p->hd_sec_sz_s, p->freeblks);
} }
@ -476,10 +476,10 @@ u32 wbfs_add_disc(wbfs_t *p, read_wiidisc_callback_t read_src_wii_disc, void *ca
load_freeblocks(p); load_freeblocks(p);
// build disc info // build disc info
info = wbfs_ioalloc(p->disc_info_sz); info = wbfs_malloc(p->disc_info_sz);
read_src_wii_disc(callback_data, 0, 0x100, info->disc_header_copy); read_src_wii_disc(callback_data, 0, 0x100, info->disc_header_copy);
copy_buffer = wbfs_ioalloc(p->wii_sec_sz); copy_buffer = wbfs_malloc(p->wii_sec_sz);
if(!copy_buffer) if(!copy_buffer)
ERROR("alloc memory\n"); ERROR("alloc memory\n");
tot = 0; tot = 0;
@ -568,9 +568,9 @@ error:
if(used) if(used)
wbfs_free(used); wbfs_free(used);
if(info) if(info)
wbfs_iofree(info); wbfs_free(info);
if(copy_buffer) if(copy_buffer)
wbfs_iofree(copy_buffer); wbfs_free(copy_buffer);
// init with all free blocks // init with all free blocks
return retval; return retval;
@ -622,7 +622,7 @@ u32 wbfs_size_disc(wbfs_t *p,read_wiidisc_callback_t read_src_wii_disc,
u32 wii_sec_per_wbfs_sect = 1 << (p->wbfs_sec_sz_s - p->wii_sec_sz_s); u32 wii_sec_per_wbfs_sect = 1 << (p->wbfs_sec_sz_s - p->wii_sec_sz_s);
wiidisc_t *d = 0; wiidisc_t *d = 0;
u8 *used = wbfs_ioalloc(p->n_wii_sec_per_disc); u8 *used = wbfs_malloc(p->n_wii_sec_per_disc);
if(!used) if(!used)
ERROR("unable to alloc memory\n"); ERROR("unable to alloc memory\n");

View File

@ -14,8 +14,22 @@
#include "loader/utils.h" #include "loader/utils.h"
#include "memory/mem2.hpp" #include "memory/mem2.hpp"
#define wbfs_fatal(x) do { gprintf(x); wd_last_error = 1; } while(0) #ifdef __cplusplus
#define wbfs_error(x) do { gprintf(x); wd_last_error = 2; } while(0) extern "C" {
#endif /* __cplusplus */
extern int wd_last_error;
static inline void wbfs_fatal(const char *x)
{
gprintf(x);
wd_last_error = 1;
}
static inline void wbfs_error(const char *x)
{
gprintf(x);
wd_last_error = 2;
}
static inline void *wbfs_malloc(size_t size) static inline void *wbfs_malloc(size_t size)
{ {
@ -29,8 +43,9 @@ static inline void wbfs_free(void *ptr)
MEM2_free(ptr); MEM2_free(ptr);
} }
#define wbfs_ioalloc(x) wbfs_malloc(x) #ifdef __cplusplus
#define wbfs_iofree(x) wbfs_free(x) }
#endif /* __cplusplus */
#define wbfs_be16(x) (*((u16*)(x))) #define wbfs_be16(x) (*((u16*)(x)))
#define wbfs_be32(x) (*((u32*)(x))) #define wbfs_be32(x) (*((u32*)(x)))

445
source/libwbfs/rijndael.c Normal file
View File

@ -0,0 +1,445 @@
/* Rijndael Block Cipher - rijndael.c
Written by Mike Scott 21st April 1999
mike@compapp.dcu.ie
Permission for free direct or derivative use is granted subject
to compliance with any conditions that the originators of the
algorithm place on its exploitation.
*/
#include <stdio.h>
#include <string.h>
#include "gecko/gecko.hpp"
#include "loader/utils.h"
#define u8 unsigned char /* 8 bits */
#define u32 unsigned long /* 32 bits */
#define u64 unsigned long long
/* rotates x one bit to the left */
#define ROTL(x) (((x)>>7)|((x)<<1))
/* Rotates 32-bit word left by 1, 2 or 3 byte */
#define ROTL8(x) (((x)<<8)|((x)>>24))
#define ROTL16(x) (((x)<<16)|((x)>>16))
#define ROTL24(x) (((x)<<24)|((x)>>8))
/* Fixed Data */
static u8 InCo[4] = { 0xB, 0xD, 0x9, 0xE }; /* Inverse Coefficients */
static u8 fbsub[256];
static u8 rbsub[256];
static u8 ptab[256], ltab[256];
static u32 ftable[256];
static u32 rtable[256];
static u32 rco[30];
/* Parameter-dependent data */
int Nk, Nb, Nr;
u8 fi[24], ri[24];
u32 fkey[120];
u32 rkey[120];
static u32 pack(u8 *b)
{ /* pack bytes into a 32-bit Word */
return ((u32 ) b[3] << 24) | ((u32 ) b[2] << 16) | ((u32 ) b[1] << 8) | (u32 ) b[0];
}
static void unpack(u32 a, u8 *b)
{ /* unpack bytes from a word */
b[0] = (u8 ) a;
b[1] = (u8 ) (a >> 8);
b[2] = (u8 ) (a >> 16);
b[3] = (u8 ) (a >> 24);
}
static u8 xtime(u8 a)
{
u8 b;
if (a & 0x80)
b = 0x1B;
else b = 0;
a <<= 1;
a ^= b;
return a;
}
static u8 bmul(u8 x, u8 y)
{ /* x.y= AntiLog(Log(x) + Log(y)) */
if (x && y)
return ptab[(ltab[x] + ltab[y]) % 255];
else return 0;
}
static u32 SubByte(u32 a)
{
u8 b[4];
unpack(a, b);
b[0] = fbsub[b[0]];
b[1] = fbsub[b[1]];
b[2] = fbsub[b[2]];
b[3] = fbsub[b[3]];
return pack(b);
}
static u8 product(u32 x, u32 y)
{ /* dot product of two 4-byte arrays */
u8 xb[4], yb[4];
unpack(x, xb);
unpack(y, yb);
return bmul(xb[0], yb[0]) ^ bmul(xb[1], yb[1]) ^ bmul(xb[2], yb[2]) ^ bmul(xb[3], yb[3]);
}
static u32 InvMixCol(u32 x)
{ /* matrix Multiplication */
u32 y, m;
u8 b[4];
m = pack(InCo);
b[3] = product(m, x);
m = ROTL24( m );
b[2] = product(m, x);
m = ROTL24( m );
b[1] = product(m, x);
m = ROTL24( m );
b[0] = product(m, x);
y = pack(b);
return y;
}
u8 ByteSub(u8 x)
{
u8 y = ptab[255 - ltab[x]]; /* multiplicative inverse */
x = y;
x = ROTL( x );
y ^= x;
x = ROTL( x );
y ^= x;
x = ROTL( x );
y ^= x;
x = ROTL( x );
y ^= x;
y ^= 0x63;
return y;
}
void gentables(void)
{ /* generate tables */
int i;
u8 y, b[4];
/* use 3 as primitive root to generate power and log tables */
ltab[0] = 0;
ptab[0] = 1;
ltab[1] = 0;
ptab[1] = 3;
ltab[3] = 1;
for (i = 2; i < 256; i++)
{
ptab[i] = ptab[i - 1] ^ xtime(ptab[i - 1]);
ltab[ptab[i]] = i;
}
/* affine transformation:- each bit is xored with itself shifted one bit */
fbsub[0] = 0x63;
rbsub[0x63] = 0;
for (i = 1; i < 256; i++)
{
y = ByteSub((u8 ) i);
fbsub[i] = y;
rbsub[y] = i;
}
for (i = 0, y = 1; i < 30; i++)
{
rco[i] = y;
y = xtime(y);
}
/* calculate forward and reverse tables */
for (i = 0; i < 256; i++)
{
y = fbsub[i];
b[3] = y ^ xtime(y);
b[2] = y;
b[1] = y;
b[0] = xtime(y);
ftable[i] = pack(b);
y = rbsub[i];
b[3] = bmul(InCo[0], y);
b[2] = bmul(InCo[1], y);
b[1] = bmul(InCo[2], y);
b[0] = bmul(InCo[3], y);
rtable[i] = pack(b);
}
}
void gkey(int nb, int nk, char *key)
{ /* blocksize=32*nb bits. Key=32*nk bits */
/* currently nb,bk = 4, 6 or 8 */
/* key comes as 4*Nk bytes */
/* Key Scheduler. Create expanded encryption key */
int i, j, k, m, N;
int C1, C2, C3;
u32 CipherKey[8];
Nb = nb;
Nk = nk;
/* Nr is number of rounds */
if (Nb >= Nk)
Nr = 6 + Nb;
else Nr = 6 + Nk;
C1 = 1;
if (Nb < 8)
{
C2 = 2;
C3 = 3;
}
else
{
C2 = 3;
C3 = 4;
}
/* pre-calculate forward and reverse increments */
for (m = j = 0; j < nb; j++, m += 3)
{
fi[m] = (j + C1) % nb;
fi[m + 1] = (j + C2) % nb;
fi[m + 2] = (j + C3) % nb;
ri[m] = (nb + j - C1) % nb;
ri[m + 1] = (nb + j - C2) % nb;
ri[m + 2] = (nb + j - C3) % nb;
}
N = Nb * (Nr + 1);
for (i = j = 0; i < Nk; i++, j += 4)
{
CipherKey[i] = pack((u8 *) &key[j]);
}
for (i = 0; i < Nk; i++)
fkey[i] = CipherKey[i];
for (j = Nk, k = 0; j < N; j += Nk, k++)
{
fkey[j] = fkey[j - Nk] ^ SubByte(ROTL24( fkey[j-1] )) ^ rco[k];
if (Nk <= 6)
{
for (i = 1; i < Nk && (i + j) < N; i++)
fkey[i + j] = fkey[i + j - Nk] ^ fkey[i + j - 1];
}
else
{
for (i = 1; i < 4 && (i + j) < N; i++)
fkey[i + j] = fkey[i + j - Nk] ^ fkey[i + j - 1];
if ((j + 4) < N) fkey[j + 4] = fkey[j + 4 - Nk] ^ SubByte(fkey[j + 3]);
for (i = 5; i < Nk && (i + j) < N; i++)
fkey[i + j] = fkey[i + j - Nk] ^ fkey[i + j - 1];
}
}
/* now for the expanded decrypt key in reverse order */
for (j = 0; j < Nb; j++)
rkey[j + N - Nb] = fkey[j];
for (i = Nb; i < N - Nb; i += Nb)
{
k = N - Nb - i;
for (j = 0; j < Nb; j++)
rkey[k + j] = InvMixCol(fkey[i + j]);
}
for (j = N - Nb; j < N; j++)
rkey[j - N + Nb] = fkey[j];
}
/* There is an obvious time/space trade-off possible here. *
* Instead of just one ftable[], I could have 4, the other *
* 3 pre-rotated to save the ROTL8, ROTL16 and ROTL24 overhead */
void encrypt(char *buff)
{
int i, j, k, m;
u32 a[8], b[8], *x, *y, *t;
for (i = j = 0; i < Nb; i++, j += 4)
{
a[i] = pack((u8 *) &buff[j]);
a[i] ^= fkey[i];
}
k = Nb;
x = a;
y = b;
/* State alternates between a and b */
for (i = 1; i < Nr; i++)
{ /* Nr is number of rounds. May be odd. */
/* if Nb is fixed - unroll this next
loop and hard-code in the values of fi[] */
for (m = j = 0; j < Nb; j++, m += 3)
{ /* deal with each 32-bit element of the State */
/* This is the time-critical bit */
y[j] = fkey[k++] ^ ftable[(u8 ) x[j]] ^ ROTL8( ftable[( u8 )( x[fi[m]] >> 8 )] )
^ ROTL16( ftable[( u8 )( x[fi[m+1]] >> 16 )] ) ^ ROTL24( ftable[x[fi[m+2]] >> 24] );
}
t = x;
x = y;
y = t; /* swap pointers */
}
/* Last Round - unroll if possible */
for (m = j = 0; j < Nb; j++, m += 3)
{
y[j] = fkey[k++] ^ (u32 ) fbsub[(u8 ) x[j]] ^ ROTL8( ( u32 )fbsub[( u8 )( x[fi[m]] >> 8 )] )
^ ROTL16( ( u32 )fbsub[( u8 )( x[fi[m+1]] >> 16 )] ) ^ ROTL24( ( u32 )fbsub[x[fi[m+2]] >> 24] );
}
for (i = j = 0; i < Nb; i++, j += 4)
{
unpack(y[i], (u8 *) &buff[j]);
x[i] = y[i] = 0; /* clean up stack */
}
return;
}
void decrypt(char *buff)
{
int i, j, k, m;
u32 a[8], b[8], *x, *y, *t;
for (i = j = 0; i < Nb; i++, j += 4)
{
a[i] = pack((u8 *) &buff[j]);
a[i] ^= rkey[i];
}
k = Nb;
x = a;
y = b;
/* State alternates between a and b */
for (i = 1; i < Nr; i++)
{ /* Nr is number of rounds. May be odd. */
/* if Nb is fixed - unroll this next
loop and hard-code in the values of ri[] */
for (m = j = 0; j < Nb; j++, m += 3)
{ /* This is the time-critical bit */
y[j] = rkey[k++] ^ rtable[(u8 ) x[j]] ^ ROTL8( rtable[( u8 )( x[ri[m]] >> 8 )] )
^ ROTL16( rtable[( u8 )( x[ri[m+1]] >> 16 )] ) ^ ROTL24( rtable[x[ri[m+2]] >> 24] );
}
t = x;
x = y;
y = t; /* swap pointers */
}
/* Last Round - unroll if possible */
for (m = j = 0; j < Nb; j++, m += 3)
{
y[j] = rkey[k++] ^ (u32 ) rbsub[(u8 ) x[j]] ^ ROTL8( ( u32 )rbsub[( u8 )( x[ri[m]] >> 8 )] )
^ ROTL16( ( u32 )rbsub[( u8 )( x[ri[m+1]] >> 16 )] ) ^ ROTL24( ( u32 )rbsub[x[ri[m+2]] >> 24] );
}
for (i = j = 0; i < Nb; i++, j += 4)
{
unpack(y[i], (u8 *) &buff[j]);
x[i] = y[i] = 0; /* clean up stack */
}
return;
}
void aes_set_key(const u8 *key)
{
gentables();
gkey(4, 4, (char*) key);
}
// CBC mode decryption
void aes_decrypt(u8 *iv, u8 *inbuf, u8 *outbuf, u64 len)
{
u8 block[16];
u32 blockno = 0, i;
//printf("aes_decrypt(%p, %p, %p, %lld)\n", iv, inbuf, outbuf, len);
for (blockno = 0; blockno <= (len / sizeof(block)); blockno++)
{
u32 fraction;
if (blockno == (len / sizeof(block))) // last block
{
fraction = len % sizeof(block);
if (fraction == 0) break;
memset(block, 0, sizeof(block));
}
else fraction = 16;
// debug_printf("block %d: fraction = %d\n", blockno, fraction);
memcpy(block, inbuf + blockno * sizeof(block), fraction);
decrypt((char*) block);
u8 *ctext_ptr;
if (blockno == 0)
ctext_ptr = iv;
else ctext_ptr = inbuf + (blockno - 1) * sizeof(block);
for (i = 0; i < fraction; i++)
outbuf[blockno * sizeof(block) + i] = ctext_ptr[i] ^ block[i];
// debug_printf("Block %d output: ", blockno);
// hexdump(outbuf + blockno*sizeof(block), 16);
}
}
// CBC mode encryption
void aes_encrypt(u8 *iv, u8 *inbuf, u8 *outbuf, u64 len)
{
u8 block[16];
u32 blockno = 0, i;
// debug_printf("aes_decrypt(%p, %p, %p, %lld)\n", iv, inbuf, outbuf, len);
for (blockno = 0; blockno <= (len / sizeof(block)); blockno++)
{
u32 fraction;
if (blockno == (len / sizeof(block))) // last block
{
fraction = len % sizeof(block);
if (fraction == 0) break;
memset(block, 0, sizeof(block));
}
else fraction = 16;
// debug_printf("block %d: fraction = %d\n", blockno, fraction);
memcpy(block, inbuf + blockno * sizeof(block), fraction);
for (i = 0; i < fraction; i++)
block[i] = inbuf[blockno * sizeof(block) + i] ^ iv[i];
encrypt((char*) block);
memcpy(iv, block, sizeof(block));
memcpy(outbuf + blockno * sizeof(block), block, sizeof(block));
// debug_printf("Block %d output: ", blockno);
// hexdump(outbuf + blockno*sizeof(block), 16);
}
}
// CBC mode decryption
#define WAD_BUF 0x10000
void aes_decrypt_partial(u8 *inbuf, u8 *outbuf, u8 block[16], u8 *ctext_ptr, u32 tmp_blockno)
{
memcpy(block, inbuf + tmp_blockno * 16, 16);
decrypt((char*)block);
u32 i;
for(i = 0; i < 16; i++)
outbuf[tmp_blockno * 16 + i] = ctext_ptr[i] ^ block[i];
}

View File

@ -6,6 +6,10 @@
#include "wiidisc.h" #include "wiidisc.h"
#include "hw/aes.h" #include "hw/aes.h"
#include "loader/nk.h" #include "loader/nk.h"
#include "loader/sys.h"
void aes_set_key(const u8 *key);
void aes_decrypt(u8 *iv, u8 *inbuf, u8 *outbuf, u64 len);
int wd_last_error = 0; int wd_last_error = 0;
@ -32,29 +36,40 @@ void decrypt_title_key(u8 *tik, u8 *title_key)
wbfs_memset(iv, 0, sizeof iv); wbfs_memset(iv, 0, sizeof iv);
wbfs_memcpy(iv, tik + 0x01dc, 8); wbfs_memcpy(iv, tik + 0x01dc, 8);
AES_ResetEngine();
//check byte 0x1f1 in ticket to determine whether or not to use Korean Common Key //check byte 0x1f1 in ticket to determine whether or not to use Korean Common Key
//if value = 0x01, use Korean Common Key, else just use regular one //if value = 0x01, use Korean Common Key, else just use regular one
if(Sys_HW_Access())
{
AES_ResetEngine();
AES_EnableDecrypt((tik[0x01f1] == 1) ? korean_key : common_key, iv); AES_EnableDecrypt((tik[0x01f1] == 1) ? korean_key : common_key, iv);
AES_Decrypt(tik + 0x01bf, title_key, 1); AES_Decrypt(tik + 0x01bf, title_key, 1);
} }
else
{
aes_set_key((tik[0x01f1] == 1) ? korean_key : common_key);
aes_decrypt(iv, tik + 0x01bf, title_key, 16);
}
}
static u32 _be32(const u8 *p) static u32 _be32(const u8 *p)
{ {
return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
} }
static void disc_read(wiidisc_t *d, u32 offset, u8 *data, u32 len) static int disc_read(wiidisc_t *d, u32 offset, u8 *data, u32 len)
{ {
if (data) if (data)
{ {
int ret = 0; int ret = 0;
if (len == 0) if (len == 0)
return; return -1;
ret = d->read(d->fp, offset, len, data); ret = d->read(d->fp, offset, len, data);
if(ret) if(ret)
{
wbfs_fatal("error reading disc\n"); wbfs_fatal("error reading disc\n");
return -1;
}
} }
if(d->sector_usage_table) if(d->sector_usage_table)
{ {
@ -66,35 +81,39 @@ static void disc_read(wiidisc_t *d, u32 offset, u8 *data, u32 len)
if (len > 0x8000) len -= 0x8000; if (len > 0x8000) len -= 0x8000;
} while(len > 0x8000); } while(len > 0x8000);
} }
return 0;
} }
static void partition_raw_read(wiidisc_t *d, u32 offset, u8 *data, u32 len) static int partition_raw_read(wiidisc_t *d, u32 offset, u8 *data, u32 len)
{ {
disc_read(d, d->partition_raw_offset + offset, data, len); return disc_read(d, d->partition_raw_offset + offset, data, len);
} }
static void partition_read_block(wiidisc_t *d, u32 blockno, u8 *block) static int partition_read_block(wiidisc_t *d, u32 blockno, u8 *block)
{ {
u8*raw = d->tmp_buffer; u8*raw = d->tmp_buffer;
u8 iv[16]; u8 iv[16];
u32 offset; u32 offset;
if (d->sector_usage_table) d->sector_usage_table[d->partition_block+blockno] = 1; if (d->sector_usage_table) d->sector_usage_table[d->partition_block+blockno] = 1;
offset = d->partition_data_offset + ((0x8000 >> 2) * blockno); offset = d->partition_data_offset + ((0x8000 >> 2) * blockno);
partition_raw_read(d,offset, raw, 0x8000); if(partition_raw_read(d,offset, raw, 0x8000) < 0)
return -1;
memcpy(iv, raw + 0x3d0, 16); memcpy(iv, raw + 0x3d0, 16);
// decrypt data // decrypt data
if(neek2o()) if(Sys_HW_Access())
{
NKAESDecryptBlock(raw, block);
}
else
{ {
AES_ResetEngine(); AES_ResetEngine();
AES_EnableDecrypt(d->disc_key, iv); AES_EnableDecrypt(d->disc_key, iv);
AES_Decrypt(raw + 0x400, block, 0x7c0); AES_Decrypt(raw + 0x400, block, 0x7c0);
} }
else
{
aes_set_key(d->disc_key);
aes_decrypt(iv, raw + 0x400, block, 0x7c00);
}
return 0;
} }
static void partition_read(wiidisc_t *d, u32 offset, u8 *data, u32 len, int fake) static void partition_read(wiidisc_t *d, u32 offset, u8 *data, u32 len, int fake)
@ -111,7 +130,8 @@ static void partition_read(wiidisc_t *d, u32 offset, u8 *data, u32 len, int fake
if (len_in_block > len) len_in_block = len; if (len_in_block > len) len_in_block = len;
if (!fake) if (!fake)
{ {
partition_read_block(d,offset / (0x7c00 >> 2), block); if(partition_read_block(d,offset / (0x7c00 >> 2), block) < 0)
break;
wbfs_memcpy(data, block + (offset_in_block << 2), len_in_block); wbfs_memcpy(data, block + (offset_in_block << 2), len_in_block);
} }
else d->sector_usage_table[d->partition_block + (offset / (0x7c00 >> 2))] = 1; else d->sector_usage_table[d->partition_block + (offset / (0x7c00 >> 2))] = 1;
@ -151,7 +171,7 @@ static u32 do_fst(wiidisc_t *d, u8 *fst, const char *names, u32 i)
offset = _be32(fst + 12 * i + 4); offset = _be32(fst + 12 * i + 4);
if (d->extract_pathname && strcasecmp(name, d->extract_pathname) == 0) if (d->extract_pathname && strcasecmp(name, d->extract_pathname) == 0)
{ {
d->extracted_buffer = wbfs_ioalloc(size); d->extracted_buffer = wbfs_malloc(size);
if (d->extracted_buffer != 0) if (d->extracted_buffer != 0)
{ {
d->extracted_size = size; d->extracted_size = size;
@ -165,13 +185,13 @@ static u32 do_fst(wiidisc_t *d, u8 *fst, const char *names, u32 i)
static void do_files(wiidisc_t*d) static void do_files(wiidisc_t*d)
{ {
u8 *b = wbfs_ioalloc(0x480); // XXX: determine actual header size u8 *b = wbfs_malloc(0x480); // XXX: determine actual header size
u32 dol_offset; u32 dol_offset;
u32 fst_offset; u32 fst_offset;
u32 fst_size; u32 fst_size;
u32 apl_offset; u32 apl_offset;
u32 apl_size; u32 apl_size;
u8 *apl_header = wbfs_ioalloc(0x20); u8 *apl_header = wbfs_malloc(0x20);
u8 *fst; u8 *fst;
u32 n_files; u32 n_files;
partition_read(d, 0, b, 0x480, 0); partition_read(d, 0, b, 0x480, 0);
@ -189,7 +209,7 @@ static void do_files(wiidisc_t*d)
if (fst_size) if (fst_size)
{ {
fst = wbfs_ioalloc(fst_size); fst = wbfs_malloc(fst_size);
if (fst == 0) if (fst == 0)
wbfs_fatal("malloc fst\n"); wbfs_fatal("malloc fst\n");
partition_read(d, fst_offset, fst, fst_size,0); partition_read(d, fst_offset, fst, fst_size,0);
@ -209,16 +229,16 @@ static void do_files(wiidisc_t*d)
if (12 * n_files <= fst_size) if (12 * n_files <= fst_size)
if (n_files > 1) do_fst(d, fst, (char *)fst + 12 * n_files, 0); if (n_files > 1) do_fst(d, fst, (char *)fst + 12 * n_files, 0);
if (fst != d->extracted_buffer) wbfs_iofree( fst ); if (fst != d->extracted_buffer) wbfs_free( fst );
} }
wbfs_iofree(b); wbfs_free(b);
wbfs_iofree(apl_header); wbfs_free(apl_header);
} }
static void do_partition(wiidisc_t*d) static void do_partition(wiidisc_t*d)
{ {
u8 *tik = wbfs_ioalloc(0x2a4); u8 *tik = wbfs_malloc(0x2a4);
u8 *b = wbfs_ioalloc(0x1c); u8 *b = wbfs_malloc(0x1c);
u64 tmd_offset; u64 tmd_offset;
u32 tmd_size; u32 tmd_size;
u8 *tmd; u8 *tmd;
@ -238,7 +258,7 @@ static void do_partition(wiidisc_t*d)
h3_offset = _be32(b + 0x10); h3_offset = _be32(b + 0x10);
d->partition_data_offset = _be32(b + 0x14); d->partition_data_offset = _be32(b + 0x14);
d->partition_block = (d->partition_raw_offset + d->partition_data_offset) >> 13; d->partition_block = (d->partition_raw_offset + d->partition_data_offset) >> 13;
tmd = wbfs_ioalloc(tmd_size); tmd = wbfs_malloc(tmd_size);
if (tmd == 0) if (tmd == 0)
wbfs_fatal("malloc tmd\n"); wbfs_fatal("malloc tmd\n");
partition_raw_read(d, tmd_offset, tmd, tmd_size); partition_raw_read(d, tmd_offset, tmd, tmd_size);
@ -249,24 +269,20 @@ static void do_partition(wiidisc_t*d)
d->extracted_size = tmd_size; d->extracted_size = tmd_size;
} }
cert = wbfs_ioalloc(cert_size); cert = wbfs_malloc(cert_size);
if (cert == 0) if (cert == 0)
wbfs_fatal("malloc cert\n"); wbfs_fatal("malloc cert\n");
partition_raw_read(d, cert_offset, cert, cert_size); partition_raw_read(d, cert_offset, cert, cert_size);
if(neek2o())
NKKeyCreate(tik);
else
decrypt_title_key(tik, d->disc_key); decrypt_title_key(tik, d->disc_key);
partition_raw_read(d, h3_offset, 0, 0x18000); partition_raw_read(d, h3_offset, 0, 0x18000);
wbfs_iofree(b); wbfs_free(b);
wbfs_iofree(tik); wbfs_free(tik);
wbfs_iofree(cert); wbfs_free(cert);
if(tmd != d->extracted_buffer) if(tmd != d->extracted_buffer)
wbfs_iofree( tmd ); wbfs_free( tmd );
do_files(d); do_files(d);
@ -285,21 +301,24 @@ static int test_parition_skip(u32 partition_type, partition_selector_t part_sel)
return (partition_type != part_sel); return (partition_type != part_sel);
} }
} }
static void do_disc(wiidisc_t *d) static void do_disc(wiidisc_t *d)
{ {
u8 *b = wbfs_ioalloc(0x100); u8 *b = wbfs_malloc(0x100);
if(b == NULL)
goto out;
u64 partition_offset[32]; // XXX: don't know the real maximum u64 partition_offset[32]; // XXX: don't know the real maximum
u64 partition_type[32]; // XXX: don't know the real maximum u64 partition_type[32]; // XXX: don't know the real maximum
u32 n_partitions; u32 n_partitions;
u32 magic; u32 magic;
u32 i; u32 i;
disc_read(d, 0, b, 0x100); if(disc_read(d, 0, b, 0x100) < 0)
goto out;
magic = _be32(b + 24); magic = _be32(b + 24);
if (magic != WII_MAGIC) if (magic != WII_MAGIC)
{ {
wbfs_iofree(b);
wbfs_error("not a wii disc"); wbfs_error("not a wii disc");
return ; goto out;
} }
disc_read(d, 0x40000 >> 2, b, 0x100); disc_read(d, 0x40000 >> 2, b, 0x100);
n_partitions = _be32(b); n_partitions = _be32(b);
@ -314,7 +333,8 @@ static void do_disc(wiidisc_t *d)
d->partition_raw_offset = partition_offset[i]; d->partition_raw_offset = partition_offset[i];
if (!test_parition_skip(partition_type[i], d->part_sel)) do_partition(d); if (!test_parition_skip(partition_type[i], d->part_sel)) do_partition(d);
} }
wbfs_iofree(b); out:
wbfs_free(b);
} }
wiidisc_t *wd_open_disc(read_wiidisc_callback_t read, void *fp) wiidisc_t *wd_open_disc(read_wiidisc_callback_t read, void *fp)
@ -325,19 +345,19 @@ wiidisc_t *wd_open_disc(read_wiidisc_callback_t read, void *fp)
d->read = read; d->read = read;
d->fp = fp; d->fp = fp;
d->part_sel = ALL_PARTITIONS; d->part_sel = ALL_PARTITIONS;
d->tmp_buffer = wbfs_ioalloc(0x8000); d->tmp_buffer = wbfs_malloc(0x8000);
d->tmp_buffer2 = wbfs_ioalloc(0x8000); d->tmp_buffer2 = wbfs_malloc(0x8000);
return d; return d;
} }
void wd_close_disc(wiidisc_t *d) void wd_close_disc(wiidisc_t *d)
{ {
wbfs_iofree(d->tmp_buffer); wbfs_free(d->tmp_buffer);
wbfs_free(d->tmp_buffer2); wbfs_free(d->tmp_buffer2);
wbfs_free(d); wbfs_free(d);
} }
// returns a buffer allocated with wbfs_ioalloc() or NULL if not found of alloc error // returns a buffer allocated with wbfs_malloc() or NULL if not found of alloc error
// XXX pathname not implemented. files are extracted by their name. // XXX pathname not implemented. files are extracted by their name.
// first file found with that name is returned. // first file found with that name is returned.
u8 *wd_extract_file(wiidisc_t *d, u32 *size, partition_selector_t partition_type, const char *pathname) u8 *wd_extract_file(wiidisc_t *d, u32 *size, partition_selector_t partition_type, const char *pathname)

View File

@ -36,7 +36,7 @@
#include "devicemounter/DeviceHandler.hpp" #include "devicemounter/DeviceHandler.hpp"
#include "fileOps/fileOps.h" #include "fileOps/fileOps.h"
#include "gecko/gecko.hpp" #include "gecko/gecko.hpp"
#include "gui/Gekko.h" #include "hw/Gekko.h"
#include "gui/text.hpp" #include "gui/text.hpp"
#include "memory/mem2.hpp" #include "memory/mem2.hpp"
#include "menu/menu.hpp" #include "menu/menu.hpp"
@ -69,7 +69,6 @@ void GCDump::__AnalizeMultiDisc()
s32 GCDump::__DiscReadRaw(void *outbuf, u64 offset, u32 length) s32 GCDump::__DiscReadRaw(void *outbuf, u64 offset, u32 length)
{ {
length = ALIGN32(length); length = ALIGN32(length);
wiiLightSetLevel(255);
wiiLightOn(); wiiLightOn();
while(1) while(1)
{ {
@ -179,7 +178,6 @@ bool GCDump::__WaitForDisc(u8 dsc, u32 msg)
mainMenu.GC_Messenger(msg, dsc+1, minfo); mainMenu.GC_Messenger(msg, dsc+1, minfo);
while(1) while(1)
{ {
wiiLightSetLevel(255);
wiiLightOn(); wiiLightOn();
usleep(1000000); usleep(1000000);
wiiLightOff(); wiiLightOff();
@ -191,7 +189,6 @@ bool GCDump::__WaitForDisc(u8 dsc, u32 msg)
while(1) while(1)
{ {
wiiLightSetLevel(255);
wiiLightOn(); wiiLightOn();
usleep(1000000); usleep(1000000);
wiiLightOff(); wiiLightOff();

View File

@ -29,12 +29,13 @@
#include <malloc.h> #include <malloc.h>
#include "nk.h" #include "nk.h"
#include "sys.h"
#include "armboot.h" #include "armboot.h"
#include "fileOps/fileOps.h" #include "fileOps/fileOps.h"
#include "memory/mem2.hpp" #include "memory/mem2.hpp"
#include "gecko/gecko.hpp" #include "gecko/gecko.hpp"
static u32 KeyID; //static u32 KeyID;
bool checked = false; bool checked = false;
bool neek = false; bool neek = false;
u32 kernelSize = 0; u32 kernelSize = 0;
@ -45,6 +46,8 @@ void check_neek2o(void)
if(checked == true) if(checked == true)
return; return;
checked = true; checked = true;
if(Sys_DolphinMode() == true)
return;
s32 ESHandle = IOS_Open("/dev/es", 0); s32 ESHandle = IOS_Open("/dev/es", 0);
neek = (IOS_Ioctlv(ESHandle, 0xA2, 0, 0, NULL) == 0x666c6f77); neek = (IOS_Ioctlv(ESHandle, 0xA2, 0, 0, NULL) == 0x666c6f77);
@ -133,7 +136,7 @@ s32 Launch_nk(u64 TitleID, const char *nandpath, u64 ReturnTo)
MEM1_free(mini); MEM1_free(mini);
return 1; return 1;
} }
/*
void NKKeyCreate(u8 *tik) void NKKeyCreate(u8 *tik)
{ {
u32 *TKeyID = (u32*)MEM1_memalign(32, sizeof(u32)); u32 *TKeyID = (u32*)MEM1_memalign(32, sizeof(u32));
@ -185,3 +188,4 @@ void NKAESDecryptBlock(u8 *in, u8 *out)
IOS_Ioctlv(ESHandle, 0x2D, 3, 2, (ioctlv *)v); IOS_Ioctlv(ESHandle, 0x2D, 3, 2, (ioctlv *)v);
IOS_Close(ESHandle); IOS_Close(ESHandle);
} }
*/

View File

@ -29,8 +29,8 @@ s32 Launch_nk(u64 TitleID, const char *nandpath, u64 ReturnTo);
bool Load_Neek2o_Kernel(); bool Load_Neek2o_Kernel();
void check_neek2o(void); void check_neek2o(void);
bool neek2o(void); bool neek2o(void);
void NKKeyCreate(u8 *TIK); /*void NKKeyCreate(u8 *TIK);
void NKAESDecryptBlock(u8 *in, u8 *out); void NKAESDecryptBlock(u8 *in, u8 *out);*/
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -18,7 +18,10 @@
#define FMT_llu "%llu" #define FMT_llu "%llu"
#define FMT_lld "%lld" #define FMT_lld "%lld"
#define split_error(x) do { gprintf("\nsplit error: %s\n\n",x); } while(0) static inline void split_error(const char *x)
{
gprintf("\nsplit error: %s\n\n",x);
}
// 1 cluster less than 4gb // 1 cluster less than 4gb
u64 OPT_split_size = (u64)4LL * 1024 * 1024 * 1024 - 32 * 1024; u64 OPT_split_size = (u64)4LL * 1024 * 1024 * 1024 - 32 * 1024;

View File

@ -205,5 +205,18 @@ bool Sys_DolphinMode(void)
return DolphinMode; return DolphinMode;
} }
bool hw_check = false;
bool on_hw = false;
bool Sys_HW_Access(void)
{
if(hw_check == true)
return on_hw;
check_neek2o();
on_hw = AHBRPOT_Patched() && (!Sys_DolphinMode() && !neek2o());
hw_check = true;
return on_hw;
}
/* KILL IT */ /* KILL IT */
s32 __IOS_LoadStartupIOS() { return 0; } s32 __IOS_LoadStartupIOS() { return 0; }

View File

@ -32,6 +32,7 @@ enum
/* Prototypes */ /* Prototypes */
void Sys_Init(void); void Sys_Init(void);
bool Sys_DolphinMode(void); bool Sys_DolphinMode(void);
bool Sys_HW_Access(void);
bool Sys_Exiting(void); bool Sys_Exiting(void);
void Sys_Exit(void); void Sys_Exit(void);
void Sys_ExitTo(int); void Sys_ExitTo(int);

View File

@ -2,25 +2,28 @@
#include <malloc.h> #include <malloc.h>
#include <string.h> #include <string.h>
#include <ogc/system.h> #include <ogc/system.h>
#include <ogc/machine/processor.h>
#include "mem2.hpp" #include "mem2.hpp"
#include "mem2alloc.hpp" #include "mem_manager.hpp"
#include "gecko/gecko.hpp" #include "gecko/gecko.hpp"
#include "loader/utils.h" #include "loader/utils.h"
#define MEM2_PRIORITY_SIZE 0x1000 static const u32 MEM2_PRIORITY_SIZE = 0x1000;
// Forbid the use of MEM2 through malloc // Forbid the use of MEM2 through malloc
u32 MALLOC_MEM2 = 0; u32 MALLOC_MEM2 = 0;
void *MEM1_lo_start = (void*)0x80004000; u8 *MEM1_lo_start = (u8*)0x80004000;
void *MEM1_lo_end = (void*)0x80620000; u8 *MEM1_lo_end = (u8*)0x80620000;
u8 *MEM1_lo_list = (u8*)0x93280000;
void *MEM2_start = (void*)0x90200000; u8 *MEM2_start = (u8*)0x90200000;
void *MEM2_end = (void*)0x93100000; u8 *MEM2_end = (u8*)0x93200000;
u8 *MEM2_list = (u8*)0x93200000;
static CMEM2Alloc g_mem1lo; MemManager g_mem1lo;
static CMEM2Alloc g_mem2gp; MemManager g_mem2gp;
extern "C" extern "C"
{ {
@ -34,23 +37,25 @@ extern __typeof(malloc_usable_size) __real_malloc_usable_size;
void MEM_init() void MEM_init()
{ {
g_mem1lo.init(MEM1_lo_start, MEM1_lo_end); //about 6mb MemMutexInit();
g_mem1lo.clear();
g_mem2gp.init(MEM2_start, MEM2_end); //about 47mb g_mem1lo.Init(MEM1_lo_start, MEM1_lo_list, (u32)(MEM1_lo_end-MEM1_lo_start)); //about 6mb
g_mem2gp.clear(); g_mem1lo.ClearMem();
g_mem2gp.Init(MEM2_start, MEM2_list, (u32)(MEM2_end-MEM2_start)); //about 48mb
g_mem2gp.ClearMem();
} }
void *MEM1_lo_alloc(unsigned int s) void *MEM1_lo_alloc(unsigned int s)
{ {
return g_mem1lo.allocate(s); return g_mem1lo.Alloc(s);
} }
void MEM1_lo_free(void *p) void MEM1_lo_free(void *p)
{ {
if(!p) if(!p)
return; return;
g_mem1lo.release(p); g_mem1lo.Free(p);
} }
unsigned int MEM1_lo_freesize() unsigned int MEM1_lo_freesize()
@ -91,28 +96,28 @@ void MEM2_free(void *p)
{ {
if(!p) if(!p)
return; return;
g_mem2gp.release(p); g_mem2gp.Free(p);
} }
void *MEM2_alloc(unsigned int s) void *MEM2_alloc(unsigned int s)
{ {
return g_mem2gp.allocate(s); return g_mem2gp.Alloc(s);
} }
/* Placeholder, will be needed with new memory manager */ /* Placeholder, will be needed with new memory manager */
void *MEM2_memalign(unsigned int /* alignment */, unsigned int s) void *MEM2_memalign(unsigned int /* alignment */, unsigned int s)
{ {
return MEM2_alloc(s); return g_mem2gp.Alloc(s);
} }
void *MEM2_realloc(void *p, unsigned int s) void *MEM2_realloc(void *p, unsigned int s)
{ {
return g_mem2gp.reallocate(p, s); return g_mem2gp.ReAlloc(p, s);
} }
unsigned int MEM2_usableSize(void *p) unsigned int MEM2_usableSize(void *p)
{ {
return g_mem2gp.usableSize(p); return g_mem2gp.MemBlockSize(p);
} }
unsigned int MEM2_freesize() unsigned int MEM2_freesize()
@ -125,7 +130,7 @@ void *__wrap_malloc(size_t size)
void *p; void *p;
if(size >= MEM2_PRIORITY_SIZE) if(size >= MEM2_PRIORITY_SIZE)
{ {
p = g_mem2gp.allocate(size); p = g_mem2gp.Alloc(size);
if(p != 0) if(p != 0)
return p; return p;
return __real_malloc(size); return __real_malloc(size);
@ -133,7 +138,7 @@ void *__wrap_malloc(size_t size)
p = __real_malloc(size); p = __real_malloc(size);
if(p != 0) if(p != 0)
return p; return p;
return g_mem2gp.allocate(size); return g_mem2gp.Alloc(size);
} }
void *__wrap_calloc(size_t n, size_t size) void *__wrap_calloc(size_t n, size_t size)
@ -141,7 +146,7 @@ void *__wrap_calloc(size_t n, size_t size)
void *p; void *p;
if((n * size) >= MEM2_PRIORITY_SIZE) if((n * size) >= MEM2_PRIORITY_SIZE)
{ {
p = g_mem2gp.allocate(n * size); p = g_mem2gp.Alloc(n * size);
if (p != 0) if (p != 0)
{ {
memset(p, 0, n * size); memset(p, 0, n * size);
@ -153,7 +158,7 @@ void *__wrap_calloc(size_t n, size_t size)
p = __real_calloc(n, size); p = __real_calloc(n, size);
if (p != 0) return p; if (p != 0) return p;
p = g_mem2gp.allocate(n * size); p = g_mem2gp.Alloc(n * size);
if (p != 0) if (p != 0)
memset(p, 0, n * size); memset(p, 0, n * size);
return p; return p;
@ -166,7 +171,7 @@ void *__wrap_memalign(size_t a, size_t size)
{ {
if(a <= 32 && 32 % a == 0) if(a <= 32 && 32 % a == 0)
{ {
p = g_mem2gp.allocate(size); p = g_mem2gp.Alloc(size);
if (p != 0) if (p != 0)
return p; return p;
} }
@ -176,7 +181,7 @@ void *__wrap_memalign(size_t a, size_t size)
if(p != 0 || a > 32 || 32 % a != 0) if(p != 0 || a > 32 || 32 % a != 0)
return p; return p;
return g_mem2gp.allocate(size); return g_mem2gp.Alloc(size);
} }
void __wrap_free(void *p) void __wrap_free(void *p)
@ -187,9 +192,9 @@ void __wrap_free(void *p)
if(((u32)p & 0x10000000) != 0) if(((u32)p & 0x10000000) != 0)
{ {
//if(p > MEM2_start) //if(p > MEM2_start)
g_mem2gp.release(p); g_mem2gp.Free(p);
//else //else
//g_mem2lo_gp.release(p); //g_mem2lo_gp.Free(p);
} }
else else
MEM1_free(p); MEM1_free(p);
@ -201,7 +206,7 @@ void *__wrap_realloc(void *p, size_t size)
// ptr from mem2 // ptr from mem2
if(((u32)p & 0x10000000) != 0 || (p == 0 && size > MEM2_PRIORITY_SIZE)) if(((u32)p & 0x10000000) != 0 || (p == 0 && size > MEM2_PRIORITY_SIZE))
{ {
n = g_mem2gp.reallocate(p, size); n = g_mem2gp.ReAlloc(p, size);
if(n != 0) if(n != 0)
return n; return n;
n = __real_malloc(size); n = __real_malloc(size);
@ -210,7 +215,7 @@ void *__wrap_realloc(void *p, size_t size)
if(p != 0) if(p != 0)
{ {
memcpy(n, p, MEM2_usableSize(p) < size ? MEM2_usableSize(p) : size); memcpy(n, p, MEM2_usableSize(p) < size ? MEM2_usableSize(p) : size);
g_mem2gp.release(p); g_mem2gp.Free(p);
} }
return n; return n;
} }
@ -218,7 +223,7 @@ void *__wrap_realloc(void *p, size_t size)
n = __real_realloc(p, size); n = __real_realloc(p, size);
if(n != 0) if(n != 0)
return n; return n;
n = g_mem2gp.allocate(size); n = g_mem2gp.Alloc(size);
if(n == 0) if(n == 0)
return 0; return 0;
if(p != 0) if(p != 0)
@ -232,7 +237,7 @@ void *__wrap_realloc(void *p, size_t size)
size_t __wrap_malloc_usable_size(void *p) size_t __wrap_malloc_usable_size(void *p)
{ {
if(((u32)p & 0x10000000) != 0) if(((u32)p & 0x10000000) != 0)
return CMEM2Alloc::usableSize(p); return g_mem2gp.MemBlockSize(p);
return __real_malloc_usable_size(p); return __real_malloc_usable_size(p);
} }

View File

@ -1,5 +1,3 @@
// 1 MEM2 allocator, one for general purpose
// Aligned and padded to 32 bytes, as required by many functions
#ifndef __MEM2_HPP #ifndef __MEM2_HPP
#define __MEM2_HPP #define __MEM2_HPP

View File

@ -1,230 +0,0 @@
#include "mem2alloc.hpp"
#include <ogc/system.h>
#include <ogc/cache.h>
#include <algorithm>
#include <string.h>
#include "lockMutex.hpp"
#include "gecko/gecko.hpp"
void CMEM2Alloc::init(void *addr, void *end)
{
m_baseAddress = (SBlock *)(((u32)addr + 31) & ~31);
m_endAddress = (SBlock *)((u32)end & ~31);
LWP_MutexInit(&m_mutex, 0);
}
void CMEM2Alloc::cleanup(void)
{
LWP_MutexDestroy(m_mutex);
m_mutex = 0;
m_first = 0;
// Try to release the range we took through SYS functions
/*if (SYS_GetArena2Lo() == m_endAddress)
SYS_SetArena2Lo(m_baseAddress);*/
m_baseAddress = 0;
m_endAddress = 0;
}
void CMEM2Alloc::clear(void)
{
m_first = 0;
u32 Size = (u32)m_endAddress - (u32)m_baseAddress;
memset(m_baseAddress, 0, Size);
DCFlushRange(m_baseAddress, Size);
}
unsigned int CMEM2Alloc::usableSize(void *p)
{
return p == 0 ? 0 : ((SBlock *)p - 1)->s * sizeof (SBlock);
}
bool CMEM2Alloc::is_valid(const SBlock *block)
{
if((u32)block >= (u32)m_baseAddress && (u32)block < (u32)m_endAddress)
return true;
gprintf("WARNING: Found invalid memory location!\n");
return false;
}
void *CMEM2Alloc::allocate(unsigned int s)
{
if (s == 0)
s = 1;
//
LockMutex lock(m_mutex);
//
s = (s - 1) / sizeof (SBlock) + 1;
// First block
if (m_first == 0)
{
if (m_baseAddress + s + 1 >= m_endAddress)
return 0;
m_first = m_baseAddress;
m_first->next = 0;
m_first->prev = 0;
m_first->s = s;
m_first->f = false;
return (void *)(m_first + 1);
}
// Search for a free block
SBlock *i;
SBlock *j = m_first;
for (i = m_first; i != 0; i = i->next)
{
if (i->f && i->s >= s)
break;
j = i;
}
// Create a new block
if (i == 0)
{
i = j + j->s + 1;
if (i + s + 1 >= m_endAddress)
return 0;
j->next = i;
i->prev = j;
i->next = 0;
i->s = s;
i->f = false;
return (void *)(i + 1);
}
// Reuse a free block
i->f = false;
// Split it
if (i->s > s + 1)
{
j = i + s + 1;
j->f = true;
j->s = i->s - s - 1;
i->s = s;
j->next = i->next;
j->prev = i;
i->next = j;
if(j->next != 0 && is_valid(j->next))
j->next->prev = j;
}
return (void *)(i + 1);
}
void CMEM2Alloc::release(void *p)
{
if (p == 0)
return;
LockMutex lock(m_mutex);
SBlock *i = (SBlock *)p - 1;
i->f = true;
// If there are no other blocks following yet,
// set the remaining size to free size. - Dimok
if(i->next == 0)
i->s = m_endAddress - i - 1;
// Merge with previous block
if (i->prev != 0 && is_valid(i->prev) && is_valid(i->prev->next) && i->prev->f)
{
i = i->prev;
i->s += i->next->s + 1;
if(i->next->next != 0 && is_valid(i->next->next))
{
i->next = i->next->next;
i->next->prev = i;
}
}
// Merge with next block
if (i->next != 0 && is_valid(i->next) && i->next->f)
{
i->s += i->next->s + 1;
i->next = i->next->next;
if(i->next != 0 && is_valid(i->next))
i->next->prev = i;
}
}
void *CMEM2Alloc::reallocate(void *p, unsigned int s)
{
SBlock *i;
SBlock *j;
void *n;
if (s == 0)
s = 1;
if (p == 0)
return allocate(s);
i = (SBlock *)p - 1;
s = (s - 1) / sizeof (SBlock) + 1;
LockMutex lock(m_mutex);
//out of memory /* Dimok */
if (i + s + 1 >= m_endAddress)
{
return 0;
}
// Last block
if (i->next == 0 && i + s + 1 < m_endAddress)
{
i->s = s;
return p;
}
// Size <= current size + next block
if (i->next != 0 && is_valid(i->next) && i->s < s && i->next->f && i->s + i->next->s + 1 >= s)
{
// Merge
i->s += i->next->s + 1;
i->next = i->next->next;
if(i->next != 0 && is_valid(i->next))
i->next->prev = i;
}
// Size <= current size
if (i->s >= s)
{
// Split
if (i->s > s + 1)
{
j = i + s + 1;
j->f = true;
j->s = i->s - s - 1;
i->s = s;
j->next = i->next;
j->prev = i;
i->next = j;
if(j->next != 0 && is_valid(j->next))
j->next->prev = j;
}
return p;
}
// Size > current size
n = allocate(s * sizeof (SBlock));
if (n == 0)
return 0;
memcpy(n, p, i->s * sizeof (SBlock));
release(p);
return n;
}
unsigned int CMEM2Alloc::FreeSize()
{
LockMutex lock(m_mutex);
if (m_first == 0)
return (u32)m_endAddress - (u32)m_baseAddress;
SBlock *i;
unsigned int size = 0;
for(i = m_first; i != 0; i = i->next)
{
if(i->f && i->next != 0 && is_valid(i->next))
size += i->s;
else if(i->f && i->next == 0)
size += m_endAddress - i - 1;
else if(!i->f && i->next == 0)
size += m_endAddress - i - i->s - 1;
}
return size*sizeof(SBlock);
}

View File

@ -1,43 +0,0 @@
// MEM2 allocator
// Made as a class so i can have 2 sections, one being dedicated to the covers
#ifndef __MEM2ALLOC_HPP
#define __MEM2ALLOC_HPP
#include <ogc/mutex.h>
class CMEM2Alloc
{
public:
void *allocate(unsigned int s);
void release(void *p);
void *reallocate(void *p, unsigned int s);
void init(unsigned int size);
void init(void *addr, void *end);
void cleanup(void);
void clear(void);
static unsigned int usableSize(void *p);
void forceEndAddress(void *newAddr) { m_endAddress = (SBlock *)newAddr; }
void *getEndAddress(void) const { return m_endAddress; }
void info(void *&address, unsigned int &size) const { address = m_baseAddress; size = (const char *)m_endAddress - (const char *)m_baseAddress; }
unsigned int FreeSize();
//
CMEM2Alloc(void) : m_baseAddress(0), m_endAddress(0), m_first(0), m_mutex(0) { }
private:
struct SBlock
{
unsigned int s;
SBlock *next;
SBlock *prev;
bool f;
} __attribute__((aligned(32)));
bool is_valid(const SBlock *block);
SBlock *m_baseAddress;
SBlock *m_endAddress;
SBlock *m_first;
mutex_t m_mutex;
private:
CMEM2Alloc(const CMEM2Alloc &);
};
#endif // !defined(__MEM2ALLOC_HPP)

View File

@ -0,0 +1,194 @@
/****************************************************************************
* Copyright (C) 2013 FIX94
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
****************************************************************************/
#include <string.h>
#include <algorithm>
#include "mem_manager.hpp"
#include "gecko/gecko.hpp"
#include "loader/utils.h"
static mutex_t memMutex = 0;
static const u32 MEM_BLOCK_SIZE = 256;
void MemMutexInit()
{
LWP_MutexInit(&memMutex, 0);
}
void MemMutexDestroy()
{
LWP_MutexDestroy(memMutex);
memset(&memMutex, 0, sizeof(mutex_t));
}
MemManager::MemManager()
{
startAddr = NULL;
memList = NULL;
memListEnd = NULL;
memSize = 0;
}
void MemManager::Init(u8 *start, u8 *list, u32 size)
{
LWP_MutexLock(memMutex);
//gprintf("Init %x %i\n", memList, memSize);
startAddr = start;
memList = list;
memSize = ALIGN(MEM_BLOCK_SIZE, size) / MEM_BLOCK_SIZE;
memListEnd = list + memSize;
ICInvalidateRange(memList, memSize+1);
memset(memList, MEM_FREE , memSize);
memset(memListEnd, MEM_END, 1); //thats the +1
DCFlushRange(memList, memSize+1);
LWP_MutexUnlock(memMutex);
}
void MemManager::ClearMem()
{
LWP_MutexLock(memMutex);
//gprintf("ClearMem %x %i\n", startAddr, memSize * MEM_BLOCK_SIZE);
u32 MemFull = memSize * MEM_BLOCK_SIZE;
ICInvalidateRange(startAddr, MemFull);
memset(startAddr, 0, MemFull);
DCFlushRange(startAddr, MemFull);
LWP_MutexUnlock(memMutex);
}
void *MemManager::Alloc(u32 size)
{
size = ALIGN(MEM_BLOCK_SIZE, size) / MEM_BLOCK_SIZE;
if(size > memSize)
return NULL;
LWP_MutexLock(memMutex);
vu8 *tmp_block;
u32 blocksFree;
for(vu8 *block = memList; block < memListEnd; block++)
{
for( ; *block & (ALLOC_USED | ALLOC_END); block++) ;
blocksFree = 0;
for(tmp_block = block; *tmp_block == MEM_FREE; tmp_block++)
{
blocksFree++;
if(blocksFree == size)
{
u8 *addr = (u8*)block;
ICInvalidateRange(addr, blocksFree);
memset(addr, ALLOC_USED, blocksFree - 1); //start blocks
memset(addr + blocksFree - 1, ALLOC_END, 1); //end block
DCFlushRange(addr, blocksFree);
void *ptr = (void*)(startAddr + ((addr - memList)*MEM_BLOCK_SIZE));
//gprintf("Alloc %x mem, %i blocks\n", ptr, blocksFree);
LWP_MutexUnlock(memMutex);
return ptr;
}
}
block = tmp_block;
}
LWP_MutexUnlock(memMutex);
return NULL;
}
void MemManager::Free(void *mem)
{
vu8 *blockUsed = memList+(((u8*)mem-startAddr) / MEM_BLOCK_SIZE);
if(blockUsed < memList || blockUsed >= memListEnd || *blockUsed == 0)
return;
LWP_MutexLock(memMutex);
//gprintf("Free %x mem, %x block\n", mem, blockUsed);
u32 size = 0;
vu8 *tmp_block = blockUsed;
for( ; *tmp_block == ALLOC_USED; tmp_block++)
size++;
if(*tmp_block == ALLOC_END)
size++;
u8 *addr = (u8*)blockUsed;
ICInvalidateRange(addr, size);
memset(addr, MEM_FREE, size);
DCFlushRange(addr, size);
LWP_MutexUnlock(memMutex);
}
u32 MemManager::MemBlockSize(void *mem)
{
vu8 *blockUsed = memList+(((u8*)mem-startAddr) / MEM_BLOCK_SIZE);
if(blockUsed < memList || blockUsed >= memListEnd || *blockUsed == 0)
return 0;
LWP_MutexLock(memMutex);
u32 size = 0;
for( ; *blockUsed == ALLOC_USED; blockUsed++)
size++;
if(*blockUsed == ALLOC_END)
size++;
size *= MEM_BLOCK_SIZE;
LWP_MutexUnlock(memMutex);
return size;
}
u32 MemManager::FreeSize()
{
LWP_MutexLock(memMutex);
u32 free = 0;
for(vu8 *block = memList; block < memListEnd; block++)
{
for( ; *block == MEM_FREE; block++)
free++;
}
free *= MEM_BLOCK_SIZE;
LWP_MutexUnlock(memMutex);
return free;
}
void *MemManager::ReAlloc(void *mem, u32 size)
{
if(mem == NULL)
return Alloc(size);
//gprintf("Realloc %x, %i\n", mem, size);
void *new_m = Alloc(size);
if(new_m == NULL)
{
Free(mem);
return NULL;
}
const u32 copysize = std::min(MemBlockSize(mem), size);
LWP_MutexLock(memMutex);
memcpy(new_m, mem, copysize);
LWP_MutexUnlock(memMutex);
Free(mem);
return new_m;
}

View File

@ -0,0 +1,51 @@
/****************************************************************************
* Copyright (C) 2013 FIX94
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
****************************************************************************/
#ifndef _MEM_MANAGER_HPP_
#define _MEM_MANAGER_HPP_
#include <ogcsys.h>
#include <ogc/mutex.h>
enum mem_states
{
MEM_FREE = (1<<0),
ALLOC_USED = (1<<1),
ALLOC_END = (1<<2),
MEM_END = (1<<3),
};
class MemManager {
public:
MemManager();
void Init(u8 *start, u8 *list, u32 size);
void ClearMem();
void *Alloc(u32 size);
void Free(void *mem);
u32 MemBlockSize(void *mem);
u32 FreeSize();
void *ReAlloc(void *mem, u32 size);
private:
u8 *startAddr;
u8 *memList;
u8 *memListEnd;
u32 memSize;
};
void MemMutexInit();
void MemMutexDestroy();
#endif

View File

@ -14,7 +14,7 @@
#include "channel/nand.hpp" #include "channel/nand.hpp"
#include "channel/nand_save.hpp" #include "channel/nand_save.hpp"
#include "gc/gc.hpp" #include "gc/gc.hpp"
#include "gui/Gekko.h" #include "hw/Gekko.h"
#include "gui/GameTDB.hpp" #include "gui/GameTDB.hpp"
#include "loader/alt_ios.h" #include "loader/alt_ios.h"
#include "loader/cios.h" #include "loader/cios.h"
@ -255,7 +255,7 @@ void CMenu::init()
m_cfg.getBool(CHANNEL_DOMAIN, "disable", true); m_cfg.getBool(CHANNEL_DOMAIN, "disable", true);
/* Load cIOS Map */ /* Load cIOS Map */
_installed_cios.clear(); _installed_cios.clear();
if(!neek2o()) if(!neek2o() && !Sys_DolphinMode())
_load_installed_cioses(); _load_installed_cioses();
else else
_installed_cios[CurrentIOS.Version] = CurrentIOS.Version; _installed_cios[CurrentIOS.Version] = CurrentIOS.Version;

View File

@ -21,7 +21,6 @@
#include "gc/gcdisc.hpp" #include "gc/gcdisc.hpp"
#include "gui/WiiMovie.hpp" #include "gui/WiiMovie.hpp"
#include "gui/GameTDB.hpp" #include "gui/GameTDB.hpp"
#include "gui/Gekko.h"
#include "homebrew/homebrew.h" #include "homebrew/homebrew.h"
#include "loader/alt_ios.h" #include "loader/alt_ios.h"
#include "loader/wdvd.h" #include "loader/wdvd.h"