mirror of
https://github.com/wiidev/usbloadergx.git
synced 2024-11-29 06:34:17 +01:00
64f8406b07
*updated libntfs (write fix) *updated libfat *lots of changes in the startup code, removed almost everything. This might cause problems for some drives at loading the gamelist and needs to be adjusted later but better this time. more cleanup is needed in main.cpp and will come. *using libogc sd/usb for config loading and reload to cIOS afterwards *added missing boothomebrew stuff pune forgot NOTE: From now on we will be doing a lot of revs which we won't be compiling and releasing. This revs are officially not available for public so don't making issues regarding those revs. Those will be closed right away. We need first to cleanup a lot of crap and update loader to new standards before releasing stuff again.
239 lines
4.5 KiB
C++
239 lines
4.5 KiB
C++
|
|
#include "mem2alloc.hpp"
|
|
|
|
#include <ogc/system.h>
|
|
#include <algorithm>
|
|
#include <string.h>
|
|
|
|
|
|
class LockMutex
|
|
{
|
|
mutex_t &m_mutex;
|
|
public:
|
|
LockMutex(mutex_t &m) : m_mutex(m) { LWP_MutexLock(m_mutex); }
|
|
~LockMutex(void) { LWP_MutexUnlock(m_mutex); }
|
|
};
|
|
|
|
void CMEM2Alloc::init(unsigned int size)
|
|
{
|
|
m_baseAddress = (SBlock *) (((u32)SYS_GetArena2Lo() + 31) & ~31);
|
|
m_endAddress = (SBlock *) ((char *)m_baseAddress + std::min(size * 0x100000, SYS_GetArena2Size() & ~31));
|
|
if (m_endAddress > (SBlock *) 0x93300000) //rest is reserved for usb/usb2/network and other stuff... (0xE0000 bytes)
|
|
m_endAddress = (SBlock *) 0x93300000;
|
|
SYS_SetArena2Lo(m_endAddress);
|
|
LWP_MutexInit(&m_mutex, 0);
|
|
}
|
|
|
|
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;
|
|
memset(m_baseAddress, 0, (u8 *)m_endAddress - (u8 *)m_endAddress);
|
|
}
|
|
|
|
unsigned int CMEM2Alloc::usableSize(void *p)
|
|
{
|
|
return p == 0 ? 0 : ((SBlock *)p - 1)->s * sizeof (SBlock);
|
|
}
|
|
|
|
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;
|
|
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)
|
|
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 && i->prev->f)
|
|
{
|
|
i = i->prev;
|
|
i->s += i->next->s + 1;
|
|
i->next = i->next->next;
|
|
if (i->next != 0)
|
|
i->next->prev = i;
|
|
}
|
|
// Merge with next block
|
|
if (i->next != 0 && i->next->f)
|
|
{
|
|
i->s += i->next->s + 1;
|
|
i->next = i->next->next;
|
|
if (i->next != 0)
|
|
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 && 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)
|
|
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)
|
|
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 (const char *) m_endAddress - (const char *) m_baseAddress;
|
|
|
|
SBlock *i;
|
|
unsigned int size = 0;
|
|
|
|
for(i = m_first; i != 0; i = i->next)
|
|
{
|
|
if(i->f && i->next != 0)
|
|
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);
|
|
}
|