379 lines
9.2 KiB
C
379 lines
9.2 KiB
C
#include "game/armem.h"
|
|
#include "game/data.h"
|
|
|
|
typedef struct armem_block {
|
|
/* 0x00 */ u8 flag;
|
|
/* 0x02 */ u16 dir;
|
|
/* 0x04 */ u32 amemptr;
|
|
/* 0x08 */ u32 size;
|
|
/* 0x0C */ struct armem_block *next;
|
|
} ARMemBlock; // Size 0x10
|
|
|
|
typedef struct ar_que_req {
|
|
/* 0x00 */ ARQRequest req;
|
|
/* 0x20 */ s32 dir;
|
|
/* 0x24 */ void *dst;
|
|
} ARQueReq; // Size 0x28
|
|
|
|
static void ArqCallBack(u32 pointerToARQRequest);
|
|
static void ArqCallBackAM(u32 pointerToARQRequest);
|
|
static void ArqCallBackAMFileRead(u32 pointerToARQRequest);
|
|
|
|
static s32 ATTRIBUTE_ALIGN(32) preLoadBuf[16];
|
|
static ARQueReq ARQueBuf[16];
|
|
static ARQRequest arqReq;
|
|
static ARMemBlock ARInfo[64];
|
|
|
|
static s32 ARBase;
|
|
static volatile s32 arqCnt;
|
|
static s16 arqIdx;
|
|
|
|
void HuARInit(void) {
|
|
s32 size;
|
|
s16 i;
|
|
|
|
if (!ARCheckInit()) {
|
|
ARInit(NULL, 0);
|
|
ARQInit();
|
|
}
|
|
for (i = 0; i < 64; i++) {
|
|
ARInfo[i].amemptr = 0;
|
|
}
|
|
#ifdef TARGET_PC
|
|
size = ARGetSize() - 0x20;
|
|
ARBase = 0x20;
|
|
#else
|
|
size = ARGetSize() - 0x808000;
|
|
ARBase = 0x808000;
|
|
#endif
|
|
ARInfo[0].amemptr = ARBase;
|
|
ARInfo[0].size = size;
|
|
ARInfo[0].flag = 0;
|
|
ARInfo[0].next = &ARInfo[1];
|
|
ARInfo[0].dir = 0xFFFF;
|
|
ARInfo[1].amemptr = -1;
|
|
ARInfo[1].size = 0;
|
|
ARInfo[1].flag = 1;
|
|
ARInfo[1].next = 0;
|
|
ARInfo[1].dir = 0xFFFF;
|
|
arqCnt = 0;
|
|
}
|
|
|
|
u32 HuARMalloc(u32 size) {
|
|
ARMemBlock *prev;
|
|
ARMemBlock *next;
|
|
ARMemBlock *curr;
|
|
s16 i;
|
|
|
|
size = OSRoundUp32B(size);
|
|
curr = prev = ARInfo;
|
|
while (curr->next != 0) {
|
|
if (curr->flag == 0 && curr->size >= size) {
|
|
break;
|
|
}
|
|
prev = curr;
|
|
curr = curr->next;
|
|
}
|
|
if (curr->next == 0) {
|
|
OSReport("Can't ARAM Allocated %x\n", size);
|
|
HuAMemDump();
|
|
return 0;
|
|
}
|
|
curr->flag = 1;
|
|
if (curr->size == size && prev != curr) {
|
|
curr->dir = 0xFFFF;
|
|
} else {
|
|
next = &ARInfo[1];
|
|
for (i = 0; i < 63; i++, next++) {
|
|
if (!next->amemptr) {
|
|
break;
|
|
}
|
|
}
|
|
if (i == 63) {
|
|
OSReport("Can't ARAM Allocated %x\n", size);
|
|
return 0;
|
|
}
|
|
next->next = curr->next;
|
|
curr->next = next;
|
|
next->size = curr->size - size;
|
|
next->amemptr = curr->amemptr + size;
|
|
curr->size = size;
|
|
curr->dir = next->dir = 0xFFFF;
|
|
next->flag = 0;
|
|
}
|
|
return curr->amemptr;
|
|
}
|
|
|
|
void HuARFree(u32 amemptr) {
|
|
ARMemBlock *prev;
|
|
ARMemBlock *next;
|
|
ARMemBlock *curr;
|
|
|
|
curr = prev = ARInfo;
|
|
while (curr->next) {
|
|
if (curr->amemptr == amemptr) {
|
|
break;
|
|
}
|
|
prev = curr;
|
|
curr = curr->next;
|
|
}
|
|
if (curr->flag != 0) {
|
|
if (!curr->next && curr->amemptr != amemptr) {
|
|
OSReport("Can't ARAM Free %x\n", amemptr);
|
|
return;
|
|
}
|
|
next = curr->next;
|
|
if (next->next && next->flag == 0) {
|
|
if (curr->amemptr > next->amemptr) {
|
|
curr->amemptr = next->amemptr;
|
|
}
|
|
curr->size += next->size;
|
|
curr->next = next->next;
|
|
next->amemptr = 0;
|
|
}
|
|
if (prev != curr && prev->next != 0 && prev->flag == 0) {
|
|
if (prev->amemptr > curr->amemptr) {
|
|
prev->amemptr = curr->amemptr;
|
|
}
|
|
prev->size += curr->size;
|
|
prev->next = curr->next;
|
|
curr->amemptr = 0;
|
|
}
|
|
curr->flag = 0;
|
|
curr->dir = 0xFFFF;
|
|
}
|
|
}
|
|
|
|
static u32 HuARSizeGet(u32 amemptr) {
|
|
ARMemBlock *curr;
|
|
ARMemBlock *prev;
|
|
|
|
curr = prev = ARInfo;
|
|
while (curr->next != 0) {
|
|
if (curr->amemptr == amemptr) {
|
|
break;
|
|
}
|
|
prev = curr;
|
|
curr = curr->next;
|
|
}
|
|
if (curr->next == 0 && curr->amemptr != amemptr) {
|
|
OSReport("Can't Find ARAM %x\n", amemptr);
|
|
return 0;
|
|
} else {
|
|
return curr->size;
|
|
}
|
|
}
|
|
|
|
static ARMemBlock *HuARInfoGet(u32 amemptr) {
|
|
ARMemBlock *curr;
|
|
ARMemBlock *prev;
|
|
|
|
curr = prev = ARInfo;
|
|
while (curr->next != 0) {
|
|
if (curr->amemptr == amemptr) {
|
|
break;
|
|
}
|
|
prev = curr;
|
|
curr = curr->next;
|
|
}
|
|
if (curr->next == 0 && curr->amemptr != amemptr) {
|
|
OSReport("Can't Find ARAM %x\n", amemptr);
|
|
return NULL;
|
|
} else {
|
|
return curr;
|
|
}
|
|
}
|
|
|
|
void HuAMemDump(void) {
|
|
ARMemBlock *curr;
|
|
|
|
OSReport("ARAM DUMP ======================\n");
|
|
OSReport("AMemPtr Stat Length\n");
|
|
for (curr = ARInfo; curr->next; curr = curr->next) {
|
|
OSReport("%08x:%04x,%08x,%08x\n", curr->amemptr, curr->flag, curr->size, curr->dir);
|
|
}
|
|
OSReport("%08x:%04x,%08x\n", curr->amemptr, curr->flag, curr->size);
|
|
OSReport("================================\n");
|
|
}
|
|
|
|
u32 HuAR_DVDtoARAM(u32 dir) {
|
|
DataReadStat *stat;
|
|
ARMemBlock *block;
|
|
u32 amemptr;
|
|
|
|
amemptr = HuARDirCheck(dir);
|
|
if (amemptr) {
|
|
return amemptr;
|
|
}
|
|
stat = HuDataDirRead(dir);
|
|
DirDataSize = OSRoundUp32B(DirDataSize);
|
|
amemptr = HuARMalloc(DirDataSize);
|
|
if (!amemptr) {
|
|
return 0;
|
|
}
|
|
block = HuARInfoGet(amemptr);
|
|
block->dir = (dir >> 16);
|
|
arqCnt++;
|
|
ARQPostRequest(&arqReq, 0x1234, 0, 0, (u32) stat->dir, amemptr, DirDataSize, ArqCallBack);
|
|
OSReport("ARAM Trans %x\n", amemptr);
|
|
while (HuARDMACheck());
|
|
HuDataDirClose(dir);
|
|
return amemptr;
|
|
}
|
|
|
|
static void ArqCallBack(u32 pointerToARQRequest) {
|
|
arqCnt--;
|
|
(void)pointerToARQRequest; // required to match (return?)
|
|
}
|
|
|
|
u32 HuAR_MRAMtoARAM(s32 dir) {
|
|
return HuAR_MRAMtoARAM2(HuDataGetDirPtr(dir));
|
|
}
|
|
|
|
u32 HuAR_MRAMtoARAM2(void *dir_ptr) {
|
|
ARMemBlock *block;
|
|
DataReadStat *status;
|
|
u32 size;
|
|
u32 amemptr;
|
|
|
|
status = HuDataGetStatus(dir_ptr);
|
|
amemptr = HuARDirCheck(status->dir_id << 16);
|
|
if (amemptr) {
|
|
return amemptr;
|
|
}
|
|
size = HuMemMemorySizeGet(dir_ptr);
|
|
size = OSRoundUp32B(size);
|
|
amemptr = HuARMalloc(size);
|
|
if (!amemptr) {
|
|
return 0;
|
|
}
|
|
block = HuARInfoGet(amemptr);
|
|
block->dir = status->dir_id;
|
|
arqCnt++;
|
|
ARQPostRequest(&arqReq, 0x1234, 0, 0, (u32)dir_ptr, amemptr, size, ArqCallBack);
|
|
return amemptr;
|
|
}
|
|
|
|
void HuAR_ARAMtoMRAM(u32 src) {
|
|
HuAR_ARAMtoMRAMNum(src, 0);
|
|
}
|
|
|
|
void *HuAR_ARAMtoMRAMNum(u32 src, s32 num) {
|
|
ARMemBlock *block;
|
|
s32 size;
|
|
void *dst;
|
|
|
|
block = HuARInfoGet(src);
|
|
if (HuDataReadChk(block->dir << 16) >= 0) {
|
|
return;
|
|
}
|
|
size = HuARSizeGet(src);
|
|
dst = HuMemDirectMallocNum(HEAP_DVD, size, num);
|
|
if (!dst) {
|
|
return 0;
|
|
}
|
|
DCFlushRangeNoSync(dst, size);
|
|
ARQueBuf[arqIdx].dir = (block->dir << 16);
|
|
ARQueBuf[arqIdx].dst = dst;
|
|
arqCnt++;
|
|
PPCSync();
|
|
ARQPostRequest(&ARQueBuf[arqIdx].req, 0x1234, 1, 0, src, (uintptr_t) dst, size, ArqCallBackAM);
|
|
arqIdx++;
|
|
arqIdx &= 0xF;
|
|
return dst;
|
|
}
|
|
|
|
static void ArqCallBackAM(u32 pointerToARQRequest) {
|
|
ARQueReq *req_ptr = (ARQueReq*) pointerToARQRequest;
|
|
|
|
arqCnt--;
|
|
HuDataDirSet(req_ptr->dst, req_ptr->dir);
|
|
}
|
|
|
|
s32 HuARDMACheck(void) {
|
|
return arqCnt;
|
|
}
|
|
|
|
u32 HuARDirCheck(u32 dir) {
|
|
ARMemBlock *curr;
|
|
|
|
curr = ARInfo;
|
|
dir >>= 16;
|
|
while (curr->next != 0) {
|
|
if (curr->flag == 1 && curr->dir == dir) {
|
|
return curr->amemptr;
|
|
}
|
|
curr = curr->next;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void HuARDirFree(u32 dir) {
|
|
ARMemBlock *curr;
|
|
|
|
curr = ARInfo;
|
|
dir >>= 16;
|
|
while (curr->next != 0) {
|
|
if (curr->dir == dir) {
|
|
HuARFree(curr->amemptr);
|
|
break;
|
|
}
|
|
curr = curr->next;
|
|
}
|
|
}
|
|
|
|
void *HuAR_ARAMtoMRAMFileRead(u32 dir, u32 num, HeapID heap) {
|
|
s32 *dir_data;
|
|
void *dst;
|
|
void *dvd_data;
|
|
u32 amem_src;
|
|
s32 count;
|
|
s32 size;
|
|
u32 amemptr;
|
|
|
|
if ((amemptr = HuARDirCheck(dir)) == 0) {
|
|
OSReport("Error: data none on ARAM %0x\n", dir);
|
|
HuAMemDump();
|
|
return 0;
|
|
}
|
|
DCInvalidateRange(&preLoadBuf, sizeof(preLoadBuf));
|
|
amem_src = amemptr + (u32)((u32)(((u16)dir + 1) * 4) & 0xFFFFFFFE0);
|
|
arqCnt++;
|
|
ARQPostRequest(&ARQueBuf[arqIdx].req, 0x1234, 1, 0, amem_src, (u32) &preLoadBuf, sizeof(preLoadBuf), ArqCallBackAMFileRead);
|
|
arqIdx++;
|
|
arqIdx &= 0xF;
|
|
while (HuARDMACheck());
|
|
dir_data = &preLoadBuf[(dir + 1) & 7];
|
|
count = dir_data[0];
|
|
amem_src = amemptr + (u32)(count & 0xFFFFFFFE0);
|
|
if (dir_data[1] - count < 0) {
|
|
size = (HuARSizeGet(amemptr) - count + 0x3F) & 0xFFFFFFFE0;
|
|
} else {
|
|
size = (dir_data[1] - count + 0x3F) & 0xFFFFFFFE0;
|
|
}
|
|
dvd_data = HuMemDirectMalloc(HEAP_DVD, size);
|
|
if (!dvd_data) {
|
|
return 0;
|
|
}
|
|
DCFlushRangeNoSync(dvd_data, size);
|
|
arqCnt++;
|
|
PPCSync();
|
|
ARQPostRequest(&ARQueBuf[arqIdx].req, 0x1234, 1, 0, amem_src, (u32) dvd_data, (u32) size, ArqCallBackAMFileRead);
|
|
arqIdx++;
|
|
arqIdx &= 0xF;
|
|
while (HuARDMACheck());
|
|
dir_data = (s32*) ((u8*) dvd_data + (count & 0x1F));
|
|
dst = HuMemDirectMallocNum(heap, (dir_data[0] + 1) & ~1, num);
|
|
if (!dst) {
|
|
return 0;
|
|
}
|
|
HuDecodeData(&dir_data[2], dst, dir_data[0], dir_data[1]);
|
|
HuMemDirectFree(dvd_data);
|
|
return dst;
|
|
}
|
|
|
|
static void ArqCallBackAMFileRead(u32 pointerToARQRequest) {
|
|
arqCnt--;
|
|
(void)pointerToARQRequest; // required to match (return?)
|
|
}
|