saviine/src/game/rpx_rpl_table.c

211 lines
6.6 KiB
C

#include <string.h>
#include "rpx_rpl_table.h"
#include "kernel/kernel_functions.h"
#include "common/common.h"
//! static container holding our retain data
static unsigned char ucRpxData[0xffff];
static int iRpxRplCount = 0;
void rpxRplTableInit(void)
{
s_rpx_rpl *pRpxData = (s_rpx_rpl*)ucRpxData;
//! initialize the RPL/RPX table first entry to zero + 1 byte for name zero termination
//! just in case no RPL/RPX are found, though it wont boot then anyway
memset(pRpxData, 0, sizeof(s_rpx_rpl) + 1);
iRpxRplCount = 0;
}
s_rpx_rpl * rpxRplTableAddEntry(const char *name, int offset, int size, int is_rpx, int entry_index, s_mem_area* area)
{
// fill rpx/rpl entry
s_rpx_rpl * rpx_rpl_data = (s_rpx_rpl *)(ucRpxData);
// get to last entry
while(rpx_rpl_data->next) {
rpx_rpl_data = rpx_rpl_data->next;
}
// setup next entry on the previous one (only if it is not the first entry)
if(entry_index > 0) {
rpx_rpl_data->next = (s_rpx_rpl *)( ((u32)rpx_rpl_data) + sizeof(s_rpx_rpl) + strlen(rpx_rpl_data->name) + 1 );
rpx_rpl_data = rpx_rpl_data->next;
}
// setup current entry
rpx_rpl_data->area = area;
rpx_rpl_data->size = size;
rpx_rpl_data->offset = offset;
rpx_rpl_data->is_rpx = is_rpx;
rpx_rpl_data->next = 0;
strcpy(rpx_rpl_data->name, name);
iRpxRplCount++;
return rpx_rpl_data;
}
s_rpx_rpl* rpxRplTableGet(void)
{
return (s_rpx_rpl*)ucRpxData;
}
int rpxRplTableGetCount(void)
{
return iRpxRplCount;
}
s_mem_area *rpxRplTableGetNextFreeMemArea(u32 * mem_area_addr_start, u32 * mem_area_addr_end, u32 * mem_area_offset)
{
s_mem_area * mem_area = memoryGetAreaTable();
s_rpx_rpl *rpl_struct = rpxRplTableGet();
while(rpl_struct != 0)
{
// check if this entry was loaded into memory
if(rpl_struct->size == 0) {
// see if we find entries behind this one that was pre-loaded
rpl_struct = rpl_struct->next;
// entry was not loaded into memory -> skip it
continue;
}
// this entry has been loaded to memory, remember it's area
mem_area = rpl_struct->area;
int rpl_size = rpl_struct->size;
int rpl_offset = rpl_struct->offset;
// find the end of the entry and switch between areas if needed
while(mem_area && (u32)(rpl_offset + rpl_size) >= mem_area->size)
{
rpl_size -= mem_area->size - rpl_offset;
rpl_offset = 0;
mem_area = mem_area->next;
}
if(!mem_area)
return NULL;
// set new start, end and memory area offset
*mem_area_addr_start = mem_area->address;
*mem_area_addr_end = mem_area->address + mem_area->size;
*mem_area_offset = rpl_offset + rpl_size;
// see if we find entries behind this one that was pre-loaded
rpl_struct = rpl_struct->next;
}
return mem_area;
}
int rpxRplCopyDataToMem(s_rpx_rpl *rpx_rpl_struct, u32 fileOffset, const u8 *data, u32 dataSize)
{
s_mem_area *mem_area = rpx_rpl_struct->area;
u32 mem_area_addr_start = mem_area->address;
u32 mem_area_addr_end = mem_area_addr_start + mem_area->size;
u32 mem_area_offset = rpx_rpl_struct->offset;
// add to offset
mem_area_offset += fileOffset;
// skip position to the end of the fill
while ((mem_area_addr_start + mem_area_offset) >= mem_area_addr_end) // TODO: maybe >, not >=
{
// subtract what was in the offset left from last memory block
mem_area_offset = (mem_area_addr_start + mem_area_offset) - mem_area_addr_end;
mem_area = mem_area->next;
if(!mem_area)
return 0;
mem_area_addr_start = mem_area->address;
mem_area_addr_end = mem_area_addr_start + mem_area->size;
}
// copy to memory
u32 copiedBytes = 0;
while(copiedBytes < dataSize)
{
u32 blockSize = dataSize - copiedBytes;
u32 mem_area_addr_dest = mem_area_addr_start + mem_area_offset;
if((mem_area_addr_dest + blockSize) > mem_area_addr_end)
blockSize = mem_area_addr_end - mem_area_addr_dest;
if(blockSize == 0)
{
// Set next memory area
mem_area = mem_area->next;
if(!mem_area)
return 0;
mem_area_addr_start = mem_area->address;
mem_area_addr_end = mem_area->address + mem_area->size;
mem_area_offset = 0;
continue;
}
SC0x25_KernelCopyData(mem_area_addr_dest, (u32)&data[copiedBytes], blockSize);
mem_area_offset += blockSize;
copiedBytes += blockSize;
}
return copiedBytes;
}
int rpxRplCopyDataFromMem(s_rpx_rpl *rpx_rpl_struct, u32 fileOffset, u8 *data, u32 dataSize)
{
s_mem_area *mem_area = rpx_rpl_struct->area;
u32 mem_area_addr_start = mem_area->address;
u32 mem_area_addr_end = mem_area_addr_start + mem_area->size;
u32 mem_area_offset = rpx_rpl_struct->offset;
if(fileOffset > rpx_rpl_struct->size)
return 0;
if((fileOffset + dataSize) > rpx_rpl_struct->size)
dataSize = rpx_rpl_struct->size - fileOffset;
// add to offset
mem_area_offset += fileOffset;
// skip position to the end of the fill
while ((mem_area_addr_start + mem_area_offset) >= mem_area_addr_end) // TODO: maybe >, not >=
{
// subtract what was in the offset left from last memory block
mem_area_offset = (mem_area_addr_start + mem_area_offset) - mem_area_addr_end;
mem_area = mem_area->next;
if(!mem_area)
return 0;
mem_area_addr_start = mem_area->address;
mem_area_addr_end = mem_area_addr_start + mem_area->size;
}
// copy to memory
u32 copiedBytes = 0;
while(copiedBytes < dataSize)
{
u32 blockSize = dataSize - copiedBytes;
u32 mem_area_addr_dest = mem_area_addr_start + mem_area_offset;
if((mem_area_addr_dest + blockSize) > mem_area_addr_end)
blockSize = mem_area_addr_end - mem_area_addr_dest;
if(blockSize == 0)
{
// Set next memory area
mem_area = mem_area->next;
if(!mem_area)
return 0;
mem_area_addr_start = mem_area->address;
mem_area_addr_end = mem_area->address + mem_area->size;
mem_area_offset = 0;
continue;
}
SC0x25_KernelCopyData((u32)&data[copiedBytes], mem_area_addr_dest, blockSize);
mem_area_offset += blockSize;
copiedBytes += blockSize;
}
return copiedBytes;
}