1038 lines
27 KiB
C
1038 lines
27 KiB
C
/********************************************************************************
|
|
Ultra 64 MARIO Brothers
|
|
|
|
memory manager module
|
|
|
|
Copyright 1996 Nintendo co., ltd. All rights reserved
|
|
|
|
April 9, 1996
|
|
********************************************************************************/
|
|
|
|
#include "headers.h"
|
|
// #include <bstring.h>
|
|
|
|
|
|
#define MEMINFO 0
|
|
|
|
#define MM_ALLOC_FORE 0
|
|
#define MM_ALLOC_BACK 1
|
|
|
|
#define Limit64(n) ((uint)(n)&0xfffffff8)
|
|
#define Limit128(n) ((uint)(n)&0xfffffff0)
|
|
|
|
#define Align128(n) (((uint)(n)+15)&0xfffffff0)
|
|
#define Align64(n) (((uint)(n)+ 7)&0xfffffff8)
|
|
#define Align32(n) (((uint)(n)+ 3)&0xfffffffc)
|
|
#define Align16(n) (((uint)(n)+ 1)&0xfffffffe)
|
|
|
|
#define AddSize(a,s) (((uint)(a))+(s))
|
|
#define SubSize(a,s) (((uint)(a))-(s))
|
|
|
|
|
|
extern char _ULibSegmentRomStart[];
|
|
extern char _ULibSegmentRomEnd[];
|
|
|
|
extern void slidec(uchar *sou, uchar *des);
|
|
|
|
|
|
/*--------------------------------------------------------------------------------
|
|
* internal types.
|
|
*/
|
|
|
|
typedef struct fzoneMCB {
|
|
struct fzoneMCB *prev; /* pointer to the previous memory block */
|
|
struct fzoneMCB *next; /* pointer to the next memory block */
|
|
wlong pad;
|
|
} FZoneMCB;
|
|
|
|
typedef struct memFrame {
|
|
uint size; /* free memory size */
|
|
FZoneMCB *fore; /* fore-allocation pointer */
|
|
FZoneMCB *back; /* back-allocation pointer */
|
|
struct memFrame *frame; /* memory frame pointer */
|
|
} MemFrame;
|
|
|
|
typedef struct heapMCB {
|
|
struct heapMCB *link; /* pointer to the next free block */
|
|
ulong size; /* size of memory block */
|
|
} HeapMCB;
|
|
|
|
HeapPtr systemHeap; /* pointer to the system heap memory */
|
|
|
|
|
|
/*--------------------------------------------------------------------------------
|
|
* local works
|
|
*/
|
|
|
|
static uint segmentTable[NUM_SEGMENTS+16]; /* segment address table */
|
|
static uint fzoneSize; /* unused memory size */
|
|
static MemPtr fzoneHead; /* head of the free zone */
|
|
static MemPtr fzoneTail; /* tail of the free zone */
|
|
static FZoneMCB *fzoneForeptr; /* fore-allocation pointer */
|
|
static FZoneMCB *fzoneBackptr; /* back-allocation pointer */
|
|
static MemFrame *memoryFrame = NULL; /* memory frame pointer */
|
|
|
|
|
|
|
|
/*################################################################################
|
|
*
|
|
*
|
|
* RCP segment address oparations.
|
|
*
|
|
*/
|
|
|
|
/********************************************************************************/
|
|
/* */
|
|
/* Set RCP segment base address. */
|
|
/* */
|
|
/********************************************************************************/
|
|
extern uint
|
|
SetSegment(int number, void *cpuAddr)
|
|
{
|
|
segmentTable[number] = K0_TO_PHYS(cpuAddr);
|
|
|
|
return(segmentTable[number]);
|
|
}
|
|
/********************************************************************************/
|
|
/* */
|
|
/* Get RCP segment base address. */
|
|
/* */
|
|
/********************************************************************************/
|
|
extern void *
|
|
GetSegment(int number)
|
|
{
|
|
return((MemPtr)PHYS_TO_K0(segmentTable[number]));
|
|
}
|
|
/********************************************************************************/
|
|
/* */
|
|
/* Convert RCP segment address to CPU virtual address. */
|
|
/* */
|
|
/********************************************************************************/
|
|
extern void *
|
|
SegmentToVirtual(void *rcpAddr)
|
|
{
|
|
#undef SEGMENT_NUMBER
|
|
#define SEGMENT_NUMBER(x) ((u32)(x)>>24)
|
|
uint number = SEGMENT_NUMBER(rcpAddr);
|
|
uint offset = SEGMENT_OFFSET(rcpAddr);
|
|
|
|
return((char *)PHYS_TO_K0(segmentTable[number] + offset));
|
|
}
|
|
/********************************************************************************/
|
|
/* */
|
|
/* Convert CPU virtual address to RCP segment address. */
|
|
/* */
|
|
/********************************************************************************/
|
|
extern void *
|
|
VirtualToSegment(int number, void *cpuAddr)
|
|
{
|
|
uint offset = K0_TO_PHYS(cpuAddr) - segmentTable[number];
|
|
|
|
return((void *)SEGMENT_ADDR(number, offset));
|
|
}
|
|
/********************************************************************************/
|
|
/* */
|
|
/* Store segment data into the gfx list. */
|
|
/* */
|
|
/********************************************************************************/
|
|
extern void
|
|
StoreSegments(void)
|
|
{
|
|
int number;
|
|
|
|
for (number = 0; number < NUM_SEGMENTS; number++) {
|
|
gSPSegment(graphPtr++, number, segmentTable[number]);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*################################################################################
|
|
*
|
|
*
|
|
* The free zone managements.
|
|
*
|
|
*/
|
|
|
|
/********************************************************************************/
|
|
/* */
|
|
/* Initlaize the free zone. */
|
|
/* */
|
|
/********************************************************************************/
|
|
extern void
|
|
InitFreeZone(MemPtr topAddr, MemPtr btmAddr)
|
|
{
|
|
#define BIGGER_HEAP
|
|
#ifdef BIGGER_HEAP
|
|
extern int _DepthbufSegmentEnd;
|
|
topAddr = &_DepthbufSegmentEnd;
|
|
#endif
|
|
fzoneHead = (MemPtr)Align128(topAddr) + sizeof(FZoneMCB);
|
|
fzoneTail = (MemPtr)Limit128(btmAddr) - sizeof(FZoneMCB);
|
|
|
|
fzoneSize = fzoneTail - fzoneHead;
|
|
fzoneForeptr = (FZoneMCB *)(fzoneHead - sizeof(FZoneMCB));
|
|
fzoneBackptr = (FZoneMCB *)(fzoneTail );
|
|
|
|
fzoneForeptr->prev = NULL;
|
|
fzoneForeptr->next = NULL;
|
|
fzoneBackptr->prev = NULL;
|
|
fzoneBackptr->next = NULL;
|
|
|
|
#if MEMINFO
|
|
rmonpf((" : foreptr : backptr : free size : alloc size\n"));
|
|
rmonpf((" initial free zone: %08XH : %08XH : %08XH\n", fzoneForeptr, fzoneBackptr, fzoneSize));
|
|
#endif
|
|
}
|
|
/********************************************************************************/
|
|
/* */
|
|
/* Allocate a memory block from the free zone. */
|
|
/* */
|
|
/********************************************************************************/
|
|
extern void *
|
|
AllocFreeZone(uint size, int mode)
|
|
{
|
|
FZoneMCB *fzoneNextptr;
|
|
MemPtr allocMemory = NULL;
|
|
|
|
size = Align128(size) + sizeof(FZoneMCB);
|
|
|
|
if (0 < size && size <= fzoneSize) {
|
|
fzoneSize -= size;
|
|
|
|
if (mode == MM_ALLOC_FORE) {
|
|
fzoneNextptr = (FZoneMCB *)AddSize(fzoneForeptr,size);
|
|
fzoneForeptr->next = fzoneNextptr;
|
|
fzoneNextptr->prev = fzoneForeptr;
|
|
fzoneNextptr->next = NULL;
|
|
|
|
allocMemory = (MemPtr)(fzoneForeptr + 1);
|
|
fzoneForeptr = fzoneNextptr;
|
|
}
|
|
else {
|
|
fzoneNextptr = (FZoneMCB *)SubSize(fzoneBackptr,size);
|
|
fzoneBackptr->prev = fzoneNextptr;
|
|
fzoneNextptr->next = fzoneBackptr;
|
|
fzoneNextptr->prev = NULL;
|
|
|
|
fzoneBackptr = fzoneNextptr;
|
|
allocMemory = (MemPtr)(fzoneBackptr + 1);
|
|
}
|
|
}
|
|
|
|
#if MEMINFO
|
|
rmonpf((" alloc free zone: %08XH : %08XH : %08XH : %08XH\n", fzoneForeptr, fzoneBackptr, fzoneSize, size));
|
|
#endif
|
|
return(allocMemory);
|
|
}
|
|
/********************************************************************************/
|
|
/* */
|
|
/* Purge a memory block from the free zone. */
|
|
/* */
|
|
/********************************************************************************/
|
|
extern uint
|
|
PurgeFreeZone(void *address)
|
|
{
|
|
FZoneMCB *fzoneTop = (FZoneMCB *)SubSize(address,sizeof(FZoneMCB));
|
|
FZoneMCB *fzoneBottom = (FZoneMCB *)SubSize(address,sizeof(FZoneMCB));
|
|
|
|
if (fzoneBottom < fzoneForeptr) {
|
|
while (fzoneBottom->next != NULL) fzoneBottom = fzoneBottom->next;
|
|
|
|
fzoneForeptr = fzoneTop;
|
|
fzoneForeptr->next = NULL;
|
|
fzoneSize += (uint)fzoneBottom - (uint)fzoneForeptr;
|
|
}
|
|
else {
|
|
while (fzoneBottom->prev != NULL) fzoneBottom = fzoneBottom->prev;
|
|
|
|
fzoneBackptr = fzoneTop->next;
|
|
fzoneBackptr->prev = NULL;
|
|
fzoneSize += (uint)fzoneBackptr - (uint)fzoneBottom;
|
|
}
|
|
#if MEMINFO
|
|
rmonpf((" purge free zone: %08XH : %08XH : %08XH\n", fzoneForeptr, fzoneBackptr, fzoneSize));
|
|
#endif
|
|
return(fzoneSize);
|
|
}
|
|
/********************************************************************************/
|
|
/* */
|
|
/* Resize a last memory block in the free zone. */
|
|
/* */
|
|
/********************************************************************************/
|
|
extern void *
|
|
ResizeFreeZone(void *address, uint size)
|
|
{
|
|
MemPtr memory = NULL;
|
|
FZoneMCB *fzone = (FZoneMCB *)SubSize(address,sizeof(FZoneMCB));
|
|
|
|
if (fzone->next == fzoneForeptr) {
|
|
PurgeFreeZone(address);
|
|
memory = AllocFreeZone(size, MM_ALLOC_FORE);
|
|
}
|
|
#if MEMINFO
|
|
rmonpf((" resize free zone: %08XH : %08XH : %08XH : %08XH\n", fzoneForeptr, fzoneBackptr, fzoneSize, size));
|
|
#endif
|
|
return(memory);
|
|
}
|
|
/********************************************************************************/
|
|
/* */
|
|
/* Get free memory size. */
|
|
/* */
|
|
/********************************************************************************/
|
|
extern uint
|
|
FreeZoneSize(void)
|
|
{
|
|
return(fzoneSize - sizeof(FZoneMCB));
|
|
}
|
|
/********************************************************************************/
|
|
/* */
|
|
/* Link free sone memory. */
|
|
/* */
|
|
/********************************************************************************/
|
|
extern uint
|
|
LinkFreeZone(void)
|
|
{
|
|
MemFrame *frame = memoryFrame;
|
|
uint memsize = fzoneSize;
|
|
FZoneMCB *foreptr = fzoneForeptr;
|
|
FZoneMCB *backptr = fzoneBackptr;
|
|
|
|
memoryFrame = AllocFreeZone(sizeof(MemFrame), MM_ALLOC_FORE);
|
|
memoryFrame->size = memsize;
|
|
memoryFrame->fore = foreptr;
|
|
memoryFrame->back = backptr;
|
|
memoryFrame->frame = frame;
|
|
#if MEMINFO
|
|
rmonpf((" link free zone: %08XH : %08XH : %08XH\n", fzoneForeptr, fzoneBackptr, fzoneSize));
|
|
#endif
|
|
return(fzoneSize);
|
|
}
|
|
/********************************************************************************/
|
|
/* */
|
|
/* Unlink free sone memory. */
|
|
/* */
|
|
/********************************************************************************/
|
|
extern uint
|
|
UnlinkFreeZone(void)
|
|
{
|
|
fzoneSize = memoryFrame->size;
|
|
fzoneForeptr = memoryFrame->fore;
|
|
fzoneBackptr = memoryFrame->back;
|
|
memoryFrame = memoryFrame->frame;
|
|
#if MEMINFO
|
|
rmonpf((" unlink free zone: %08XH : %08XH : %08XH\n", fzoneForeptr, fzoneBackptr, fzoneSize));
|
|
#endif
|
|
return(fzoneSize);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*################################################################################
|
|
*
|
|
*
|
|
* Static data loaders.
|
|
*
|
|
*/
|
|
|
|
/********************************************************************************/
|
|
/* Read a data block from ROM. */
|
|
/********************************************************************************/
|
|
static void
|
|
ReadBlock(char *ramAddr, char *romStart, char *romEnd)
|
|
{
|
|
uint size = Align128(romEnd - romStart);
|
|
|
|
osInvalDCache(ramAddr, size);
|
|
|
|
while (size > 0) {
|
|
uint load = (size >= 0x1000) ? 0x1000 : size;
|
|
|
|
osPiStartDma(&dmaIOMessageBuf, OS_MESG_PRI_NORMAL, OS_READ, (ulong)romStart, ramAddr, load, &dmaMessageQ);
|
|
osRecvMesg(&dmaMessageQ, &dummyMessage, OS_MESG_BLOCK);
|
|
ramAddr += load;
|
|
romStart += load;
|
|
size -= load;
|
|
}
|
|
}
|
|
/********************************************************************************/
|
|
/* */
|
|
/* Load static data from ROM. */
|
|
/* */
|
|
/********************************************************************************/
|
|
extern MemPtr
|
|
LoadData(char *romStart, char *romEnd, int mode)
|
|
{
|
|
MemPtr ramAddr;
|
|
uint ramSize = Align128(romEnd - romStart);
|
|
|
|
|
|
if ((ramAddr = AllocFreeZone(ramSize, mode)) != NULL) {
|
|
ReadBlock(ramAddr, romStart, romEnd);
|
|
}
|
|
return(ramAddr);
|
|
}
|
|
/********************************************************************************/
|
|
/* */
|
|
/* Load static segment from ROM. */
|
|
/* */
|
|
/********************************************************************************/
|
|
extern MemPtr
|
|
LoadSegment(int number, char *romStart, char *romEnd, int mode)
|
|
{
|
|
MemPtr addr;
|
|
|
|
if ((addr = LoadData(romStart, romEnd, mode)) != NULL) {
|
|
SetSegment(number, addr);
|
|
}
|
|
return(addr);
|
|
}
|
|
/********************************************************************************/
|
|
/* */
|
|
/* Load program from ROM. */
|
|
/* */
|
|
/********************************************************************************/
|
|
extern MemPtr
|
|
LoadProgram(char *ramAddr, char *romStart, char *romEnd)
|
|
{
|
|
MemPtr alcAddr = NULL;
|
|
uint romsize = Align128( romEnd - romStart);
|
|
uint alcsize = Align128((char *)fzoneBackptr - ramAddr );
|
|
|
|
|
|
if (romsize <= alcsize) {
|
|
if ((alcAddr = AllocFreeZone(alcsize, MM_ALLOC_BACK)) != NULL) {
|
|
bzero(alcAddr, alcsize);
|
|
osWritebackDCacheAll();
|
|
|
|
ReadBlock(alcAddr, romStart, romEnd);
|
|
osInvalICache(alcAddr, alcsize);
|
|
osInvalDCache(alcAddr, alcsize);
|
|
}
|
|
}
|
|
else {
|
|
rmonpf(("program code load failed AD=%08X ROM=%08X ALC=%08X\n",ramAddr,romsize,alcsize));
|
|
}
|
|
return(alcAddr);
|
|
}
|
|
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
//
|
|
//
|
|
//
|
|
// Load compressed data from ROM for IRIX 5.3.
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////////
|
|
|
|
#if 1
|
|
/********************************************************************************/
|
|
/* */
|
|
/* Load compressed data from ROM. */
|
|
/* */
|
|
/********************************************************************************/
|
|
extern MemPtr
|
|
LoadCompressed(int number, char *romStart, char *romEnd)
|
|
{
|
|
MemPtr alcaddr = NULL;
|
|
uint romsize = Align128(romEnd - romStart);
|
|
MemPtr tempmem = AllocFreeZone(romsize, MM_ALLOC_BACK);
|
|
uint *alcsize = (uint *)(tempmem+4);
|
|
|
|
|
|
if (tempmem != NULL) {
|
|
ReadBlock(tempmem, romStart, romEnd);
|
|
|
|
if ((alcaddr = AllocFreeZone(*alcsize, MM_ALLOC_FORE)) != NULL) {
|
|
osSyncPrintf("start decompress\n");
|
|
slidec((uchar *)tempmem, (uchar *)alcaddr);
|
|
osSyncPrintf("end decompress\n");
|
|
SetSegment(number, alcaddr);
|
|
PurgeFreeZone(tempmem);
|
|
} else {
|
|
rmonpf(("compressed data load failed (ROM:$%08X RAM:$%08X)\n", romsize, *alcsize));
|
|
}
|
|
} else {
|
|
rmonpf(("size of compressed data is too big\n"));
|
|
}
|
|
return(alcaddr);
|
|
}
|
|
/********************************************************************************/
|
|
/* */
|
|
/* Load compressed texture data from ROM. */
|
|
/* */
|
|
/********************************************************************************/
|
|
extern MemPtr
|
|
LoadPressTexture(int number, char *romStart, char *romEnd)
|
|
{
|
|
MemPtr alcaddr = NULL;
|
|
uint romsize = Align128(romEnd - romStart);
|
|
MemPtr tempmem = AllocFreeZone(romsize, MM_ALLOC_BACK);
|
|
uint *alcsize = (uint *)(tempmem+4);
|
|
|
|
|
|
if (tempmem != NULL) {
|
|
ReadBlock(tempmem, romStart, romEnd);
|
|
slidec((uchar *)tempmem, (uchar *)textureMemory);
|
|
SetSegment(number, textureMemory);
|
|
PurgeFreeZone(tempmem);
|
|
} else {
|
|
rmonpf(("size of compressed data is too big\n"));
|
|
}
|
|
return((MemPtr)textureMemory);
|
|
}
|
|
#endif
|
|
|
|
#if 0
|
|
//////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
//
|
|
//
|
|
//
|
|
// Load compressed data from ROM for IRIX 6.x.
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////////
|
|
|
|
typedef struct {
|
|
ulong pressID1; /* compredd module ID 1 */
|
|
ulong pressID2; /* compredd module ID 2 */
|
|
ulong hdrsize; /* header size */
|
|
ulong romsize; /* module size of the ROM */
|
|
ulong ramsize; /* module size of the RAM */
|
|
ulong numglbs; /* number of global tables */
|
|
} PrsHeader;
|
|
|
|
typedef struct {
|
|
ulong value; /* global value */
|
|
ulong offset; /* offset from top of module */
|
|
} PrsGlobal;
|
|
|
|
/********************************************************************************/
|
|
/* */
|
|
/* Uncompress data. */
|
|
/* */
|
|
/********************************************************************************/
|
|
static void
|
|
Uncompress(char *source, char *destination)
|
|
{
|
|
int count;
|
|
PrsHeader * prsheader = (PrsHeader *)source;
|
|
PrsGlobal * glbtable = (PrsGlobal *)(source + sizeof(PrsHeader));
|
|
char * pressed = source + prsheader->hdrsize;
|
|
u32 bssSize = prsheader->ramsize - prsheader->romsize;
|
|
|
|
|
|
osInvalICache(destination, prsheader->ramsize);
|
|
osInvalDCache(destination, prsheader->ramsize);
|
|
slidstart(source + prsheader->hdrsize, destination);
|
|
|
|
for (count = 0; count < prsheader->numglbs; count++) {
|
|
*((u32 *)(destination + glbtable->offset)) = glbtable->value;
|
|
glbtable++;
|
|
}
|
|
if (bssSize > 0) bzero(destination + prsheader->romsize, bssSize);
|
|
osWritebackDCache(destination, prsheader->ramsize);
|
|
}
|
|
/********************************************************************************/
|
|
/* */
|
|
/* Load compressed data from ROM. */
|
|
/* */
|
|
/********************************************************************************/
|
|
extern MemPtr
|
|
LoadCompressed(int number, char *romStart, char *romEnd)
|
|
{
|
|
MemPtr alcaddr = NULL;
|
|
uint romsize = Align128(romEnd - romStart);
|
|
MemPtr tempmem = AllocFreeZone(romsize, MM_ALLOC_BACK);
|
|
uint alcsize;
|
|
|
|
|
|
if (tempmem != NULL) {
|
|
ReadBlock(tempmem, romStart, romEnd);
|
|
alcsize = ((PrsHeader *)tempmem)->ramsize;
|
|
|
|
if ((alcaddr = AllocFreeZone(alcsize, MM_ALLOC_FORE)) != NULL) {
|
|
osSyncPrintf("start decompress\n");
|
|
Uncompress(tempmem, alcaddr);
|
|
osSyncPrintf("end decompress\n");
|
|
SetSegment(number, alcaddr);
|
|
PurgeFreeZone(tempmem);
|
|
} else {
|
|
rmonpf(("compressed data load failed (ROM:$%08X RAM:$%08X)\n", romsize, alcsize));
|
|
}
|
|
} else {
|
|
rmonpf(("size of compressed data is too big\n"));
|
|
}
|
|
return(alcaddr);
|
|
}
|
|
/********************************************************************************/
|
|
/* */
|
|
/* Load compressed texture data from ROM. */
|
|
/* */
|
|
/********************************************************************************/
|
|
extern MemPtr
|
|
LoadPressTexture(int number, char *romStart, char *romEnd)
|
|
{
|
|
MemPtr alcaddr = NULL;
|
|
uint romsize = Align128(romEnd - romStart);
|
|
MemPtr tempmem = AllocFreeZone(romsize, MM_ALLOC_BACK);
|
|
|
|
|
|
if (tempmem != NULL) {
|
|
ReadBlock(tempmem, romStart, romEnd);
|
|
|
|
Uncompress(tempmem, (char *)textureMemory);
|
|
SetSegment(number, textureMemory);
|
|
PurgeFreeZone(tempmem);
|
|
} else {
|
|
rmonpf(("size of compressed data is too big\n"));
|
|
}
|
|
return((MemPtr)textureMemory);
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/********************************************************************************/
|
|
/* */
|
|
/* Load user library. */
|
|
/* */
|
|
/********************************************************************************/
|
|
extern void
|
|
LoadUserLibrary(void)
|
|
{
|
|
MemPtr ramAddr = (MemPtr)ULIBCODE_START;
|
|
uint ramSize = CPROGRAM_END - ULIBCODE_START;
|
|
uint romSize = Align128(_ULibSegmentRomEnd - _ULibSegmentRomStart);
|
|
|
|
|
|
bzero(ramAddr, ramSize);
|
|
osWritebackDCacheAll();
|
|
ReadBlock(ramAddr, _ULibSegmentRomStart, _ULibSegmentRomEnd);
|
|
osInvalICache(ramAddr, ramSize);
|
|
osInvalDCache(ramAddr, ramSize);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*################################################################################
|
|
*
|
|
*
|
|
* Arena memory management.
|
|
*
|
|
*/
|
|
|
|
/********************************************************************************/
|
|
/* */
|
|
/* Initialize the arena. */
|
|
/* */
|
|
/********************************************************************************/
|
|
extern ArenaPtr
|
|
InitArena(int size, int mode)
|
|
{
|
|
MemPtr memory;
|
|
ArenaPtr arena = NULL;
|
|
|
|
size = Align32(size);
|
|
|
|
if ((memory = AllocFreeZone(size + sizeof(ArenaRecord), mode)) != NULL) {
|
|
arena = (ArenaPtr)memory;
|
|
arena->size = size;
|
|
arena->used = 0;
|
|
arena->buff = memory + sizeof(ArenaRecord);
|
|
arena->free = memory + sizeof(ArenaRecord);
|
|
}
|
|
return(arena);
|
|
}
|
|
/********************************************************************************/
|
|
/* */
|
|
/* Allocate a memory block from the arena. */
|
|
/* */
|
|
/********************************************************************************/
|
|
extern void *
|
|
AllocArena(ArenaPtr arena, int size)
|
|
{
|
|
char *memory = NULL;
|
|
|
|
size = Align32(size);
|
|
|
|
if (0 < size && arena->used + size <= arena->size) {
|
|
memory = arena->free;
|
|
arena->free += size;
|
|
arena->used += size;
|
|
}
|
|
return(memory);
|
|
}
|
|
/********************************************************************************/
|
|
/* */
|
|
/* Resize a arena memory block. */
|
|
/* */
|
|
/********************************************************************************/
|
|
extern void *
|
|
ResizeArena(ArenaPtr arena, int size)
|
|
{
|
|
MemPtr memory;
|
|
|
|
size = Align32(size);
|
|
|
|
if ((memory = ResizeFreeZone(arena, size + sizeof(ArenaRecord))) != NULL) {
|
|
arena->size = size;
|
|
}
|
|
return(memory);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*################################################################################
|
|
*
|
|
*
|
|
* heap memory management.
|
|
*
|
|
*/
|
|
|
|
/********************************************************************************/
|
|
/* Print heap. (for debug) */
|
|
/********************************************************************************/
|
|
#if 0
|
|
static void
|
|
PrintHeap(HeapPtr heap)
|
|
{
|
|
HeapMCB *free = (HeapMCB *)heap->free;
|
|
|
|
rmonpf(("start print free heap\n"));
|
|
while (free != NULL) {
|
|
rmonpf(("%08XH - %08XH (%08XH)\n", free, AddSize(free,free->size-1), free->size));
|
|
free = free->link;
|
|
}
|
|
rmonpf(("end print free heap\n"));
|
|
}
|
|
#endif
|
|
/********************************************************************************/
|
|
/* Check heap. (for debug) */
|
|
/********************************************************************************/
|
|
#if 0
|
|
static void
|
|
CheckHeap(HeapPtr heap, MemPtr memory)
|
|
{
|
|
HeapMCB *free = (HeapMCB *)heap->free;
|
|
|
|
if (free != NULL) {
|
|
MemPtr next = (MemPtr)AddSize(free,free->size);
|
|
|
|
while (free->link != NULL) {
|
|
free = free->link;
|
|
if ((MemPtr)free == next) {
|
|
rmonpf(("heap broken (%08X , %08X) , %08X\n", heap->buff, heap->size, memory));
|
|
PrintHeap(heap);
|
|
for(;;);
|
|
}
|
|
next = (MemPtr)AddSize(free,free->size);
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
/********************************************************************************/
|
|
/* */
|
|
/* Initilaize the heap. */
|
|
/* */
|
|
/********************************************************************************/
|
|
extern HeapPtr
|
|
InitHeap(int size, int mode)
|
|
{
|
|
MemPtr memory;
|
|
HeapMCB *hmcb;
|
|
HeapPtr heap = NULL;
|
|
|
|
size = Align32(size);
|
|
|
|
if ((memory = AllocFreeZone(size + sizeof(HeapRecord), mode)) != NULL) {
|
|
heap = (HeapPtr)memory;
|
|
heap->size = size;
|
|
heap->buff = memory + sizeof(HeapRecord);
|
|
heap->free = memory + sizeof(HeapRecord);
|
|
|
|
hmcb = (HeapMCB *)heap->buff;
|
|
hmcb->link = NULL;
|
|
hmcb->size = heap->size;
|
|
}
|
|
// rmonpf(("Init heap\n"));
|
|
// PrintHeap(heap);
|
|
|
|
return(heap);
|
|
}
|
|
/********************************************************************************/
|
|
/* */
|
|
/* Allocate a memory block from the heap. */
|
|
/* */
|
|
/********************************************************************************/
|
|
extern void *
|
|
AllocHeap(HeapPtr heap, int memsize)
|
|
{
|
|
HeapMCB **freeblk = (HeapMCB **)&heap->free;
|
|
MemPtr memory = NULL;
|
|
|
|
|
|
memsize = Align32(memsize) + sizeof(HeapMCB);
|
|
|
|
while (*freeblk != NULL) {
|
|
if (memsize <= (*freeblk)->size) {
|
|
memory = (MemPtr)(*freeblk + 1);
|
|
|
|
if (((*freeblk)->size - memsize) <= sizeof(HeapMCB)) {
|
|
*freeblk = (*freeblk)->link;
|
|
}
|
|
else {
|
|
HeapMCB *newblk = (HeapMCB *)AddSize(*freeblk, memsize);
|
|
|
|
newblk->size = (*freeblk)->size - memsize;
|
|
newblk->link = (*freeblk)->link;
|
|
(*freeblk)->size = memsize;
|
|
*freeblk = newblk;
|
|
}
|
|
break;
|
|
}
|
|
freeblk = &(*freeblk)->link;
|
|
}
|
|
// rmonpf(("Alloc heap (%08XH , %08XH)\n", memory, memsize));
|
|
// PrintHeap(heap);
|
|
// CheckHeap(heap, memory);
|
|
return(memory);
|
|
}
|
|
/********************************************************************************/
|
|
/* */
|
|
/* Free a memory block. */
|
|
/* */
|
|
/********************************************************************************/
|
|
extern void *
|
|
FreeHeap(HeapPtr heap, void *memory)
|
|
{
|
|
HeapMCB *memblk = (HeapMCB *)memory - 1;
|
|
HeapMCB *freeblk = (HeapMCB *)heap->free;
|
|
|
|
if (heap->free == NULL) {
|
|
heap->free = (MemPtr)memblk;
|
|
memblk->link = NULL;
|
|
}
|
|
else if (memblk < (HeapMCB *)heap->free) {
|
|
if (heap->free == (MemPtr)AddSize(memblk, memblk->size)) {
|
|
memblk->size += freeblk->size;
|
|
memblk->link = freeblk->link;
|
|
heap->free = (MemPtr)memblk;
|
|
} else {
|
|
memblk->link = (HeapMCB *)heap->free;
|
|
heap->free = (MemPtr)memblk;
|
|
}
|
|
}
|
|
else {
|
|
while (freeblk->link != NULL) {
|
|
if (freeblk < memblk && memblk < freeblk->link) break;
|
|
freeblk = freeblk->link;
|
|
}
|
|
if (memblk == (HeapMCB *)AddSize(freeblk, freeblk->size)) {
|
|
freeblk->size += memblk->size;
|
|
memblk = freeblk;
|
|
} else {
|
|
memblk->link = freeblk->link;
|
|
freeblk->link = memblk;
|
|
}
|
|
if (memblk->link != NULL && memblk->link == (HeapMCB *)AddSize(memblk, memblk->size)) {
|
|
memblk->size += (memblk->link)->size;
|
|
memblk->link = (memblk->link)->link;
|
|
}
|
|
}
|
|
// rmonpf(("Free heap (%08XH , %08XH)\n", memory, ((HeapMCB *)memory-1)->size));
|
|
// CheckHeap(heap, memory);
|
|
// PrintHeap(heap);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*################################################################################
|
|
*
|
|
* Dynamic Memory management oparations
|
|
*
|
|
*/
|
|
|
|
/********************************************************************************/
|
|
/* */
|
|
/* Allocate dynamic memory block. */
|
|
/* */
|
|
/********************************************************************************/
|
|
extern void *
|
|
AllocDynamic(int size)
|
|
{
|
|
MemPtr memory = NULL;
|
|
|
|
size = Align64(size);
|
|
|
|
if ((blockPtr - size >= (MemPtr)graphPtr)) {
|
|
blockPtr -= size;
|
|
memory = blockPtr;
|
|
}
|
|
else {
|
|
rmonpf(("DYnamic memory overflow\n"));
|
|
}
|
|
return(memory);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*################################################################################
|
|
*
|
|
* Partial manager
|
|
*
|
|
*/
|
|
|
|
/********************************************************************************/
|
|
/* */
|
|
/* Load partition table. */
|
|
/* */
|
|
/********************************************************************************/
|
|
extern Partition *
|
|
LoadPartitionTable(MemPtr romAddr)
|
|
{
|
|
Partition *table;
|
|
int size;
|
|
|
|
|
|
table = (Partition *)LoadData(romAddr, romAddr+sizeof(ulong), MM_ALLOC_FORE);
|
|
size = table->nitems * 8 + 8;
|
|
|
|
PurgeFreeZone(table);
|
|
table = (Partition *)LoadData(romAddr, romAddr+size, MM_ALLOC_FORE);
|
|
|
|
table->topaddr = romAddr;
|
|
return(table);
|
|
}
|
|
/********************************************************************************/
|
|
/* */
|
|
/* Init partial data namagement record. */
|
|
/* */
|
|
/********************************************************************************/
|
|
extern void
|
|
InitPartial(PartialPtr partial, MemPtr romAddr, MemPtr buffer)
|
|
{
|
|
if (romAddr != NULL) partial->ptable = LoadPartitionTable(romAddr);
|
|
|
|
partial->last = NULL;
|
|
partial->buffer = buffer;
|
|
}
|
|
/********************************************************************************/
|
|
/* */
|
|
/* Read partial data. */
|
|
/* */
|
|
/********************************************************************************/
|
|
extern int
|
|
ReadPartialData(PartialPtr partial, int index)
|
|
{
|
|
int result = FALSE;
|
|
Partition *ptable = partial->ptable;
|
|
|
|
if (index < ptable->nitems) {
|
|
MemPtr addr = ptable->item[index].offset + ptable->topaddr;
|
|
int size = ptable->item[index].length;
|
|
|
|
if (addr != partial->last) {
|
|
ReadBlock(partial->buffer, addr, addr+size);
|
|
partial->last = addr;
|
|
result = TRUE;
|
|
}
|
|
}
|
|
return(result);
|
|
}
|