mirror of
https://github.com/Fledge68/WiiFlow_Lite.git
synced 2024-11-27 13:44:15 +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 "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);
|
||||||
|
@ -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;
|
||||||
LWP_JoinThread(light_thread, NULL);
|
if(light_thread != LWP_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;
|
@ -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
|
@ -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");
|
||||||
|
|
||||||
|
@ -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
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 "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,11 +36,19 @@ 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
|
||||||
AES_EnableDecrypt((tik[0x01f1] == 1) ? korean_key : common_key, iv);
|
if(Sys_HW_Access())
|
||||||
AES_Decrypt(tik + 0x01bf, title_key, 1);
|
{
|
||||||
|
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)
|
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];
|
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)
|
||||||
{
|
{
|
||||||
u32 blockno = offset >> 13;
|
u32 blockno = offset >> 13;
|
||||||
do
|
do
|
||||||
@ -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);
|
||||||
|
|
||||||
|
decrypt_title_key(tik, d->disc_key);
|
||||||
if(neek2o())
|
|
||||||
NKKeyCreate(tik);
|
|
||||||
else
|
|
||||||
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)
|
||||||
|
@ -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();
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
*/
|
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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; }
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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.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;
|
||||||
|
@ -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"
|
||||||
|
Loading…
Reference in New Issue
Block a user