sm64/memory.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);
}