mirror of
https://github.com/Fledge68/WiiFlow_Lite.git
synced 2024-12-28 12:51:52 +01:00
-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:
parent
0509e80edd
commit
6b663fe2d9
@ -6,7 +6,7 @@
|
||||
#include "memory/mem2.hpp"
|
||||
#include "video.hpp"
|
||||
#include "pngu.h"
|
||||
#include "Gekko.h"
|
||||
#include "hw/Gekko.h"
|
||||
#include "gecko/gecko.hpp"
|
||||
#include "loader/sys.h"
|
||||
#include "loader/utils.h"
|
||||
@ -526,8 +526,6 @@ void CVideo::_showWaitMessages(CVideo *m)
|
||||
|
||||
m->prepare();
|
||||
m->setup2DProjection();
|
||||
wiiLightSetLevel(0);
|
||||
wiiLightOn();
|
||||
|
||||
//gprintf("Wait Message Thread: Start\nDelay: %d, Images: %d\n", waitFrames, m->m_waitMessages.size());
|
||||
while(m->m_showWaitMessage)
|
||||
@ -558,7 +556,6 @@ void CVideo::_showWaitMessages(CVideo *m)
|
||||
VIDEO_WaitVSync();
|
||||
waitFrames--;
|
||||
}
|
||||
wiiLightOff();
|
||||
//gprintf("Wait Message Thread: End\n");
|
||||
m->m_showingWaitMessages = false;
|
||||
}
|
||||
@ -571,6 +568,7 @@ void CVideo::hideWaitMessage()
|
||||
m_showWaitMessage = false;
|
||||
if(waitThread != LWP_THREAD_NULL)
|
||||
{
|
||||
/* end animation */
|
||||
if(LWP_ThreadIsSuspended(waitThread))
|
||||
LWP_ResumeThread(waitThread);
|
||||
while(m_showingWaitMessages)
|
||||
@ -579,6 +577,8 @@ void CVideo::hideWaitMessage()
|
||||
if(waitMessageStack != NULL)
|
||||
MEM2_free(waitMessageStack);
|
||||
waitMessageStack = NULL;
|
||||
/* end light thread */
|
||||
wiiLightEndThread();
|
||||
m_WaitThreadRunning = false;
|
||||
}
|
||||
waitThread = LWP_THREAD_NULL;
|
||||
@ -623,6 +623,10 @@ void CVideo::waitMessage(const vector<TexData> &tex, float delay)
|
||||
waitMessage(m_waitMessages[0]);
|
||||
else if(m_waitMessages.size() > 1)
|
||||
{
|
||||
/* changing light */
|
||||
wiiLightSetLevel(0);
|
||||
wiiLightStartThread();
|
||||
/* onscreen animation */
|
||||
m_showWaitMessage = true;
|
||||
if(waitMessageStack == NULL)
|
||||
waitMessageStack = (u8*)MEM2_memalign(32, waitMessageStackSize);
|
||||
|
@ -28,8 +28,6 @@
|
||||
#include "Gekko.h"
|
||||
#include "memory/memory.h"
|
||||
|
||||
#define DISC_SLOT_LED 0x20
|
||||
|
||||
lwp_t light_thread = LWP_THREAD_NULL;
|
||||
|
||||
void *light_loop();
|
||||
@ -39,7 +37,18 @@ u8 light_level = 0;
|
||||
struct timespec light_timeon;
|
||||
struct timespec light_timeoff;
|
||||
|
||||
// Wii disc slot light routines
|
||||
void wiiLightOn()
|
||||
{
|
||||
*HW_GPIOB_OUT |= DISC_SLOT_LED;
|
||||
}
|
||||
|
||||
void wiiLightOff()
|
||||
{
|
||||
*HW_GPIOB_OUT &= ~DISC_SLOT_LED;
|
||||
}
|
||||
|
||||
void wiiLightStartThread()
|
||||
{
|
||||
light_on = true;
|
||||
light_level = 0;
|
||||
@ -47,13 +56,14 @@ void wiiLightOn()
|
||||
LWP_CreateThread(&light_thread, light_loop, NULL, NULL, 0, LWP_PRIO_HIGHEST);
|
||||
}
|
||||
|
||||
void wiiLightOff()
|
||||
void wiiLightEndThread()
|
||||
{
|
||||
light_on = false;
|
||||
light_level = 0;
|
||||
LWP_JoinThread(light_thread, NULL);
|
||||
if(light_thread != LWP_THREAD_NULL)
|
||||
LWP_JoinThread(light_thread, NULL);
|
||||
light_thread = LWP_THREAD_NULL;
|
||||
*HW_GPIOB_OUT &= ~DISC_SLOT_LED;
|
||||
wiiLightOff();
|
||||
}
|
||||
|
||||
void wiiLightSetLevel(int level)
|
||||
@ -89,11 +99,11 @@ void *light_loop()
|
||||
timeon = light_timeon;
|
||||
timeoff = light_timeoff;
|
||||
// Turn on the light and sleep for a bit
|
||||
*HW_GPIOB_OUT |= DISC_SLOT_LED;
|
||||
wiiLightOn();
|
||||
nanosleep(&timeon);
|
||||
// Turn off the light (if required) and sleep for a bit
|
||||
if(timeoff.tv_nsec > 0)
|
||||
*HW_GPIOB_OUT &= ~DISC_SLOT_LED;
|
||||
wiiLightOff();
|
||||
nanosleep(&timeoff);
|
||||
}
|
||||
return NULL;
|
@ -27,9 +27,13 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
static const u32 DISC_SLOT_LED = 0x20;
|
||||
|
||||
// Wii disc slot light routines
|
||||
void wiiLightOn();
|
||||
void wiiLightOff();
|
||||
void wiiLightStartThread();
|
||||
void wiiLightEndThread();
|
||||
void wiiLightSetLevel(int level);
|
||||
|
||||
#ifdef __cplusplus
|
@ -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)
|
||||
{
|
||||
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];
|
||||
ret = read_hdsector(callback_data,0,1,tmp_buffer);
|
||||
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))
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
wbfs_iofree(tmp_buffer);
|
||||
wbfs_free(tmp_buffer);
|
||||
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_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
|
||||
p->wii_sec_sz = 0x8000;
|
||||
@ -131,20 +131,20 @@ wbfs_t *wbfs_open_partition(rw_sector_callback_t read_hdsector, rw_sector_callba
|
||||
else
|
||||
{
|
||||
// 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);
|
||||
}
|
||||
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))
|
||||
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;
|
||||
return p;
|
||||
|
||||
error:
|
||||
wbfs_free(p);
|
||||
wbfs_iofree(head);
|
||||
wbfs_free(head);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -167,10 +167,10 @@ void wbfs_close(wbfs_t *p)
|
||||
if(p->n_disc_open)
|
||||
ERROR("trying to close wbfs while discs still open\n");
|
||||
|
||||
wbfs_iofree(p->head);
|
||||
wbfs_iofree(p->tmp_buffer);
|
||||
wbfs_free(p->head);
|
||||
wbfs_free(p->tmp_buffer);
|
||||
if(p->freeblks)
|
||||
wbfs_iofree(p->freeblks);
|
||||
wbfs_free(p->freeblks);
|
||||
|
||||
wbfs_free(p);
|
||||
|
||||
@ -195,7 +195,7 @@ wbfs_disc_t *wbfs_open_disc(wbfs_t* p, const u8 *discid)
|
||||
ERROR("allocating memory\n");
|
||||
d->p = p;
|
||||
d->i = i;
|
||||
d->header = wbfs_ioalloc(p->disc_info_sz);
|
||||
d->header = wbfs_malloc(p->disc_info_sz);
|
||||
if(!d->header)
|
||||
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);
|
||||
@ -209,13 +209,13 @@ wbfs_disc_t *wbfs_open_disc(wbfs_t* p, const u8 *discid)
|
||||
return 0;
|
||||
|
||||
error:
|
||||
if(d) wbfs_iofree(d);
|
||||
if(d) wbfs_free(d);
|
||||
return 0;
|
||||
}
|
||||
void wbfs_close_disc(wbfs_disc_t*d)
|
||||
{
|
||||
d->p->n_disc_open --;
|
||||
wbfs_iofree(d->header);
|
||||
wbfs_free(d->header);
|
||||
wbfs_free(d);
|
||||
}
|
||||
// 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);
|
||||
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);
|
||||
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);
|
||||
}
|
||||
return 0;
|
||||
@ -367,7 +367,7 @@ static void load_freeblocks(wbfs_t *p)
|
||||
if(p->freeblks)
|
||||
return;
|
||||
// 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);
|
||||
}
|
||||
|
||||
@ -476,10 +476,10 @@ u32 wbfs_add_disc(wbfs_t *p, read_wiidisc_callback_t read_src_wii_disc, void *ca
|
||||
load_freeblocks(p);
|
||||
|
||||
// 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);
|
||||
|
||||
copy_buffer = wbfs_ioalloc(p->wii_sec_sz);
|
||||
copy_buffer = wbfs_malloc(p->wii_sec_sz);
|
||||
if(!copy_buffer)
|
||||
ERROR("alloc memory\n");
|
||||
tot = 0;
|
||||
@ -568,9 +568,9 @@ error:
|
||||
if(used)
|
||||
wbfs_free(used);
|
||||
if(info)
|
||||
wbfs_iofree(info);
|
||||
wbfs_free(info);
|
||||
if(copy_buffer)
|
||||
wbfs_iofree(copy_buffer);
|
||||
wbfs_free(copy_buffer);
|
||||
|
||||
// init with all free blocks
|
||||
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);
|
||||
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)
|
||||
ERROR("unable to alloc memory\n");
|
||||
|
||||
|
@ -14,8 +14,22 @@
|
||||
#include "loader/utils.h"
|
||||
#include "memory/mem2.hpp"
|
||||
|
||||
#define wbfs_fatal(x) do { gprintf(x); wd_last_error = 1; } while(0)
|
||||
#define wbfs_error(x) do { gprintf(x); wd_last_error = 2; } while(0)
|
||||
#ifdef __cplusplus
|
||||
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)
|
||||
{
|
||||
@ -29,8 +43,9 @@ static inline void wbfs_free(void *ptr)
|
||||
MEM2_free(ptr);
|
||||
}
|
||||
|
||||
#define wbfs_ioalloc(x) wbfs_malloc(x)
|
||||
#define wbfs_iofree(x) wbfs_free(x)
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#define wbfs_be16(x) (*((u16*)(x)))
|
||||
#define wbfs_be32(x) (*((u32*)(x)))
|
||||
|
445
source/libwbfs/rijndael.c
Normal file
445
source/libwbfs/rijndael.c
Normal 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];
|
||||
}
|
@ -6,6 +6,10 @@
|
||||
#include "wiidisc.h"
|
||||
#include "hw/aes.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;
|
||||
|
||||
@ -32,11 +36,19 @@ void decrypt_title_key(u8 *tik, u8 *title_key)
|
||||
wbfs_memset(iv, 0, sizeof iv);
|
||||
wbfs_memcpy(iv, tik + 0x01dc, 8);
|
||||
|
||||
AES_ResetEngine();
|
||||
//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
|
||||
AES_EnableDecrypt((tik[0x01f1] == 1) ? korean_key : common_key, iv);
|
||||
AES_Decrypt(tik + 0x01bf, title_key, 1);
|
||||
if(Sys_HW_Access())
|
||||
{
|
||||
AES_ResetEngine();
|
||||
AES_EnableDecrypt((tik[0x01f1] == 1) ? korean_key : common_key, iv);
|
||||
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)
|
||||
@ -44,19 +56,22 @@ static u32 _be32(const u8 *p)
|
||||
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)
|
||||
{
|
||||
int ret = 0;
|
||||
if (len == 0)
|
||||
return;
|
||||
return -1;
|
||||
|
||||
ret = d->read(d->fp, offset, len, data);
|
||||
if(ret)
|
||||
{
|
||||
wbfs_fatal("error reading disc\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (d->sector_usage_table)
|
||||
if(d->sector_usage_table)
|
||||
{
|
||||
u32 blockno = offset >> 13;
|
||||
do
|
||||
@ -66,35 +81,39 @@ static void disc_read(wiidisc_t *d, u32 offset, u8 *data, u32 len)
|
||||
if (len > 0x8000) 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 iv[16];
|
||||
u32 offset;
|
||||
if (d->sector_usage_table) d->sector_usage_table[d->partition_block+blockno] = 1;
|
||||
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);
|
||||
|
||||
|
||||
// decrypt data
|
||||
if(neek2o())
|
||||
if(Sys_HW_Access())
|
||||
{
|
||||
NKAESDecryptBlock(raw, block);
|
||||
}
|
||||
else
|
||||
{
|
||||
AES_ResetEngine();
|
||||
AES_ResetEngine();
|
||||
AES_EnableDecrypt(d->disc_key, iv);
|
||||
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)
|
||||
@ -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 (!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);
|
||||
}
|
||||
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);
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
u8 *b = wbfs_ioalloc(0x480); // XXX: determine actual header size
|
||||
u8 *b = wbfs_malloc(0x480); // XXX: determine actual header size
|
||||
u32 dol_offset;
|
||||
u32 fst_offset;
|
||||
u32 fst_size;
|
||||
u32 apl_offset;
|
||||
u32 apl_size;
|
||||
u8 *apl_header = wbfs_ioalloc(0x20);
|
||||
u8 *apl_header = wbfs_malloc(0x20);
|
||||
u8 *fst;
|
||||
u32 n_files;
|
||||
partition_read(d, 0, b, 0x480, 0);
|
||||
@ -189,7 +209,7 @@ static void do_files(wiidisc_t*d)
|
||||
|
||||
if (fst_size)
|
||||
{
|
||||
fst = wbfs_ioalloc(fst_size);
|
||||
fst = wbfs_malloc(fst_size);
|
||||
if (fst == 0)
|
||||
wbfs_fatal("malloc fst\n");
|
||||
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 (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_iofree(apl_header);
|
||||
wbfs_free(b);
|
||||
wbfs_free(apl_header);
|
||||
}
|
||||
|
||||
static void do_partition(wiidisc_t*d)
|
||||
{
|
||||
u8 *tik = wbfs_ioalloc(0x2a4);
|
||||
u8 *b = wbfs_ioalloc(0x1c);
|
||||
u8 *tik = wbfs_malloc(0x2a4);
|
||||
u8 *b = wbfs_malloc(0x1c);
|
||||
u64 tmd_offset;
|
||||
u32 tmd_size;
|
||||
u8 *tmd;
|
||||
@ -238,7 +258,7 @@ static void do_partition(wiidisc_t*d)
|
||||
h3_offset = _be32(b + 0x10);
|
||||
d->partition_data_offset = _be32(b + 0x14);
|
||||
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)
|
||||
wbfs_fatal("malloc tmd\n");
|
||||
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;
|
||||
}
|
||||
|
||||
cert = wbfs_ioalloc(cert_size);
|
||||
cert = wbfs_malloc(cert_size);
|
||||
if (cert == 0)
|
||||
wbfs_fatal("malloc cert\n");
|
||||
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);
|
||||
|
||||
wbfs_iofree(b);
|
||||
wbfs_iofree(tik);
|
||||
wbfs_iofree(cert);
|
||||
wbfs_free(b);
|
||||
wbfs_free(tik);
|
||||
wbfs_free(cert);
|
||||
if(tmd != d->extracted_buffer)
|
||||
wbfs_iofree( tmd );
|
||||
wbfs_free( tmd );
|
||||
|
||||
do_files(d);
|
||||
|
||||
@ -284,22 +300,25 @@ static int test_parition_skip(u32 partition_type, partition_selector_t part_sel)
|
||||
default:
|
||||
return (partition_type != part_sel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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_type[32]; // XXX: don't know the real maximum
|
||||
u32 n_partitions;
|
||||
u32 magic;
|
||||
u32 i;
|
||||
disc_read(d, 0, b, 0x100);
|
||||
if(disc_read(d, 0, b, 0x100) < 0)
|
||||
goto out;
|
||||
magic = _be32(b + 24);
|
||||
if (magic != WII_MAGIC)
|
||||
{
|
||||
wbfs_iofree(b);
|
||||
wbfs_error("not a wii disc");
|
||||
return ;
|
||||
goto out;
|
||||
}
|
||||
disc_read(d, 0x40000 >> 2, b, 0x100);
|
||||
n_partitions = _be32(b);
|
||||
@ -314,7 +333,8 @@ static void do_disc(wiidisc_t *d)
|
||||
d->partition_raw_offset = partition_offset[i];
|
||||
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)
|
||||
@ -325,19 +345,19 @@ wiidisc_t *wd_open_disc(read_wiidisc_callback_t read, void *fp)
|
||||
d->read = read;
|
||||
d->fp = fp;
|
||||
d->part_sel = ALL_PARTITIONS;
|
||||
d->tmp_buffer = wbfs_ioalloc(0x8000);
|
||||
d->tmp_buffer2 = wbfs_ioalloc(0x8000);
|
||||
d->tmp_buffer = wbfs_malloc(0x8000);
|
||||
d->tmp_buffer2 = wbfs_malloc(0x8000);
|
||||
return 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);
|
||||
}
|
||||
|
||||
// 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.
|
||||
// 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)
|
||||
|
@ -36,7 +36,7 @@
|
||||
#include "devicemounter/DeviceHandler.hpp"
|
||||
#include "fileOps/fileOps.h"
|
||||
#include "gecko/gecko.hpp"
|
||||
#include "gui/Gekko.h"
|
||||
#include "hw/Gekko.h"
|
||||
#include "gui/text.hpp"
|
||||
#include "memory/mem2.hpp"
|
||||
#include "menu/menu.hpp"
|
||||
@ -69,7 +69,6 @@ void GCDump::__AnalizeMultiDisc()
|
||||
s32 GCDump::__DiscReadRaw(void *outbuf, u64 offset, u32 length)
|
||||
{
|
||||
length = ALIGN32(length);
|
||||
wiiLightSetLevel(255);
|
||||
wiiLightOn();
|
||||
while(1)
|
||||
{
|
||||
@ -179,7 +178,6 @@ bool GCDump::__WaitForDisc(u8 dsc, u32 msg)
|
||||
mainMenu.GC_Messenger(msg, dsc+1, minfo);
|
||||
while(1)
|
||||
{
|
||||
wiiLightSetLevel(255);
|
||||
wiiLightOn();
|
||||
usleep(1000000);
|
||||
wiiLightOff();
|
||||
@ -191,7 +189,6 @@ bool GCDump::__WaitForDisc(u8 dsc, u32 msg)
|
||||
|
||||
while(1)
|
||||
{
|
||||
wiiLightSetLevel(255);
|
||||
wiiLightOn();
|
||||
usleep(1000000);
|
||||
wiiLightOff();
|
||||
|
@ -29,12 +29,13 @@
|
||||
#include <malloc.h>
|
||||
|
||||
#include "nk.h"
|
||||
#include "sys.h"
|
||||
#include "armboot.h"
|
||||
#include "fileOps/fileOps.h"
|
||||
#include "memory/mem2.hpp"
|
||||
#include "gecko/gecko.hpp"
|
||||
|
||||
static u32 KeyID;
|
||||
//static u32 KeyID;
|
||||
bool checked = false;
|
||||
bool neek = false;
|
||||
u32 kernelSize = 0;
|
||||
@ -45,6 +46,8 @@ void check_neek2o(void)
|
||||
if(checked == true)
|
||||
return;
|
||||
checked = true;
|
||||
if(Sys_DolphinMode() == true)
|
||||
return;
|
||||
|
||||
s32 ESHandle = IOS_Open("/dev/es", 0);
|
||||
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);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
void NKKeyCreate(u8 *tik)
|
||||
{
|
||||
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_Close(ESHandle);
|
||||
}
|
||||
*/
|
@ -29,8 +29,8 @@ s32 Launch_nk(u64 TitleID, const char *nandpath, u64 ReturnTo);
|
||||
bool Load_Neek2o_Kernel();
|
||||
void check_neek2o(void);
|
||||
bool neek2o(void);
|
||||
void NKKeyCreate(u8 *TIK);
|
||||
void NKAESDecryptBlock(u8 *in, u8 *out);
|
||||
/*void NKKeyCreate(u8 *TIK);
|
||||
void NKAESDecryptBlock(u8 *in, u8 *out);*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -18,7 +18,10 @@
|
||||
#define FMT_llu "%llu"
|
||||
#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
|
||||
u64 OPT_split_size = (u64)4LL * 1024 * 1024 * 1024 - 32 * 1024;
|
||||
|
@ -205,5 +205,18 @@ bool Sys_DolphinMode(void)
|
||||
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 */
|
||||
s32 __IOS_LoadStartupIOS() { return 0; }
|
||||
|
@ -32,6 +32,7 @@ enum
|
||||
/* Prototypes */
|
||||
void Sys_Init(void);
|
||||
bool Sys_DolphinMode(void);
|
||||
bool Sys_HW_Access(void);
|
||||
bool Sys_Exiting(void);
|
||||
void Sys_Exit(void);
|
||||
void Sys_ExitTo(int);
|
||||
|
@ -2,25 +2,28 @@
|
||||
#include <malloc.h>
|
||||
#include <string.h>
|
||||
#include <ogc/system.h>
|
||||
#include <ogc/machine/processor.h>
|
||||
|
||||
#include "mem2.hpp"
|
||||
#include "mem2alloc.hpp"
|
||||
#include "mem_manager.hpp"
|
||||
#include "gecko/gecko.hpp"
|
||||
#include "loader/utils.h"
|
||||
|
||||
#define MEM2_PRIORITY_SIZE 0x1000
|
||||
static const u32 MEM2_PRIORITY_SIZE = 0x1000;
|
||||
|
||||
// Forbid the use of MEM2 through malloc
|
||||
u32 MALLOC_MEM2 = 0;
|
||||
|
||||
void *MEM1_lo_start = (void*)0x80004000;
|
||||
void *MEM1_lo_end = (void*)0x80620000;
|
||||
u8 *MEM1_lo_start = (u8*)0x80004000;
|
||||
u8 *MEM1_lo_end = (u8*)0x80620000;
|
||||
u8 *MEM1_lo_list = (u8*)0x93280000;
|
||||
|
||||
void *MEM2_start = (void*)0x90200000;
|
||||
void *MEM2_end = (void*)0x93100000;
|
||||
u8 *MEM2_start = (u8*)0x90200000;
|
||||
u8 *MEM2_end = (u8*)0x93200000;
|
||||
u8 *MEM2_list = (u8*)0x93200000;
|
||||
|
||||
static CMEM2Alloc g_mem1lo;
|
||||
static CMEM2Alloc g_mem2gp;
|
||||
MemManager g_mem1lo;
|
||||
MemManager g_mem2gp;
|
||||
|
||||
extern "C"
|
||||
{
|
||||
@ -34,23 +37,25 @@ extern __typeof(malloc_usable_size) __real_malloc_usable_size;
|
||||
|
||||
void MEM_init()
|
||||
{
|
||||
g_mem1lo.init(MEM1_lo_start, MEM1_lo_end); //about 6mb
|
||||
g_mem1lo.clear();
|
||||
MemMutexInit();
|
||||
|
||||
g_mem2gp.init(MEM2_start, MEM2_end); //about 47mb
|
||||
g_mem2gp.clear();
|
||||
g_mem1lo.Init(MEM1_lo_start, MEM1_lo_list, (u32)(MEM1_lo_end-MEM1_lo_start)); //about 6mb
|
||||
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)
|
||||
{
|
||||
return g_mem1lo.allocate(s);
|
||||
return g_mem1lo.Alloc(s);
|
||||
}
|
||||
|
||||
void MEM1_lo_free(void *p)
|
||||
{
|
||||
if(!p)
|
||||
return;
|
||||
g_mem1lo.release(p);
|
||||
g_mem1lo.Free(p);
|
||||
}
|
||||
|
||||
unsigned int MEM1_lo_freesize()
|
||||
@ -91,28 +96,28 @@ void MEM2_free(void *p)
|
||||
{
|
||||
if(!p)
|
||||
return;
|
||||
g_mem2gp.release(p);
|
||||
g_mem2gp.Free(p);
|
||||
}
|
||||
|
||||
void *MEM2_alloc(unsigned int s)
|
||||
{
|
||||
return g_mem2gp.allocate(s);
|
||||
return g_mem2gp.Alloc(s);
|
||||
}
|
||||
|
||||
/* Placeholder, will be needed with new memory manager */
|
||||
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)
|
||||
{
|
||||
return g_mem2gp.reallocate(p, s);
|
||||
return g_mem2gp.ReAlloc(p, s);
|
||||
}
|
||||
|
||||
unsigned int MEM2_usableSize(void *p)
|
||||
{
|
||||
return g_mem2gp.usableSize(p);
|
||||
return g_mem2gp.MemBlockSize(p);
|
||||
}
|
||||
|
||||
unsigned int MEM2_freesize()
|
||||
@ -125,7 +130,7 @@ void *__wrap_malloc(size_t size)
|
||||
void *p;
|
||||
if(size >= MEM2_PRIORITY_SIZE)
|
||||
{
|
||||
p = g_mem2gp.allocate(size);
|
||||
p = g_mem2gp.Alloc(size);
|
||||
if(p != 0)
|
||||
return p;
|
||||
return __real_malloc(size);
|
||||
@ -133,7 +138,7 @@ void *__wrap_malloc(size_t size)
|
||||
p = __real_malloc(size);
|
||||
if(p != 0)
|
||||
return p;
|
||||
return g_mem2gp.allocate(size);
|
||||
return g_mem2gp.Alloc(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;
|
||||
if((n * size) >= MEM2_PRIORITY_SIZE)
|
||||
{
|
||||
p = g_mem2gp.allocate(n * size);
|
||||
p = g_mem2gp.Alloc(n * size);
|
||||
if (p != 0)
|
||||
{
|
||||
memset(p, 0, n * size);
|
||||
@ -153,7 +158,7 @@ void *__wrap_calloc(size_t n, size_t size)
|
||||
p = __real_calloc(n, size);
|
||||
if (p != 0) return p;
|
||||
|
||||
p = g_mem2gp.allocate(n * size);
|
||||
p = g_mem2gp.Alloc(n * size);
|
||||
if (p != 0)
|
||||
memset(p, 0, n * size);
|
||||
return p;
|
||||
@ -166,7 +171,7 @@ void *__wrap_memalign(size_t a, size_t size)
|
||||
{
|
||||
if(a <= 32 && 32 % a == 0)
|
||||
{
|
||||
p = g_mem2gp.allocate(size);
|
||||
p = g_mem2gp.Alloc(size);
|
||||
if (p != 0)
|
||||
return p;
|
||||
}
|
||||
@ -176,7 +181,7 @@ void *__wrap_memalign(size_t a, size_t size)
|
||||
if(p != 0 || a > 32 || 32 % a != 0)
|
||||
return p;
|
||||
|
||||
return g_mem2gp.allocate(size);
|
||||
return g_mem2gp.Alloc(size);
|
||||
}
|
||||
|
||||
void __wrap_free(void *p)
|
||||
@ -187,9 +192,9 @@ void __wrap_free(void *p)
|
||||
if(((u32)p & 0x10000000) != 0)
|
||||
{
|
||||
//if(p > MEM2_start)
|
||||
g_mem2gp.release(p);
|
||||
g_mem2gp.Free(p);
|
||||
//else
|
||||
//g_mem2lo_gp.release(p);
|
||||
//g_mem2lo_gp.Free(p);
|
||||
}
|
||||
else
|
||||
MEM1_free(p);
|
||||
@ -201,7 +206,7 @@ void *__wrap_realloc(void *p, size_t size)
|
||||
// ptr from mem2
|
||||
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)
|
||||
return n;
|
||||
n = __real_malloc(size);
|
||||
@ -210,7 +215,7 @@ void *__wrap_realloc(void *p, size_t size)
|
||||
if(p != 0)
|
||||
{
|
||||
memcpy(n, p, MEM2_usableSize(p) < size ? MEM2_usableSize(p) : size);
|
||||
g_mem2gp.release(p);
|
||||
g_mem2gp.Free(p);
|
||||
}
|
||||
return n;
|
||||
}
|
||||
@ -218,7 +223,7 @@ void *__wrap_realloc(void *p, size_t size)
|
||||
n = __real_realloc(p, size);
|
||||
if(n != 0)
|
||||
return n;
|
||||
n = g_mem2gp.allocate(size);
|
||||
n = g_mem2gp.Alloc(size);
|
||||
if(n == 0)
|
||||
return 0;
|
||||
if(p != 0)
|
||||
@ -232,7 +237,7 @@ void *__wrap_realloc(void *p, size_t size)
|
||||
size_t __wrap_malloc_usable_size(void *p)
|
||||
{
|
||||
if(((u32)p & 0x10000000) != 0)
|
||||
return CMEM2Alloc::usableSize(p);
|
||||
return g_mem2gp.MemBlockSize(p);
|
||||
return __real_malloc_usable_size(p);
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
#define __MEM2_HPP
|
||||
|
@ -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);
|
||||
}
|
@ -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)
|
194
source/memory/mem_manager.cpp
Normal file
194
source/memory/mem_manager.cpp
Normal 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;
|
||||
}
|
51
source/memory/mem_manager.hpp
Normal file
51
source/memory/mem_manager.hpp
Normal 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
|
@ -14,7 +14,7 @@
|
||||
#include "channel/nand.hpp"
|
||||
#include "channel/nand_save.hpp"
|
||||
#include "gc/gc.hpp"
|
||||
#include "gui/Gekko.h"
|
||||
#include "hw/Gekko.h"
|
||||
#include "gui/GameTDB.hpp"
|
||||
#include "loader/alt_ios.h"
|
||||
#include "loader/cios.h"
|
||||
@ -255,7 +255,7 @@ void CMenu::init()
|
||||
m_cfg.getBool(CHANNEL_DOMAIN, "disable", true);
|
||||
/* Load cIOS Map */
|
||||
_installed_cios.clear();
|
||||
if(!neek2o())
|
||||
if(!neek2o() && !Sys_DolphinMode())
|
||||
_load_installed_cioses();
|
||||
else
|
||||
_installed_cios[CurrentIOS.Version] = CurrentIOS.Version;
|
||||
|
@ -21,7 +21,6 @@
|
||||
#include "gc/gcdisc.hpp"
|
||||
#include "gui/WiiMovie.hpp"
|
||||
#include "gui/GameTDB.hpp"
|
||||
#include "gui/Gekko.h"
|
||||
#include "homebrew/homebrew.h"
|
||||
#include "loader/alt_ios.h"
|
||||
#include "loader/wdvd.h"
|
||||
|
Loading…
Reference in New Issue
Block a user