mirror of https://github.com/PrimeDecomp/prime.git
Match and link hw_aramdma
This commit is contained in:
parent
4baceece91
commit
87bb2a9e7d
|
@ -946,7 +946,7 @@ LIBS = [
|
|||
["musyx/runtime/snd_midictrl", False],
|
||||
["musyx/runtime/snd_service", True],
|
||||
["musyx/runtime/hardware", True],
|
||||
"musyx/runtime/hw_aramdma",
|
||||
["musyx/runtime/hw_aramdma", True],
|
||||
["musyx/runtime/dsp_import", True],
|
||||
["musyx/runtime/hw_dolphin", True],
|
||||
["musyx/runtime/hw_memory", True],
|
||||
|
|
|
@ -39,7 +39,12 @@ void ARQInit(void);
|
|||
void ARQReset(void);
|
||||
void ARQPostRequest(ARQRequest* task, u32 owner, u32 type, u32 priority, u32 source, u32 dest,
|
||||
u32 length, ARQCallback callback);
|
||||
void ARQRemoveRequest(ARQRequest* task);
|
||||
void ARQRemoveOwnerRequest(u32 owner);
|
||||
void ARQFlushQueue(void);
|
||||
void ARQSetChunkSize(u32 size);
|
||||
u32 ARQGetChunkSize(void);
|
||||
BOOL ARQCheckInit(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -0,0 +1,342 @@
|
|||
#include "musyx/musyx_priv.h"
|
||||
#include <dolphin/ar.h>
|
||||
#include <dolphin/arq.h>
|
||||
#include <dolphin/os.h>
|
||||
|
||||
typedef struct ARAMTransferJob {
|
||||
// total size: 0x28
|
||||
ARQRequest arq; // offset 0x0, size 0x20
|
||||
void (*callback)(unsigned long); // offset 0x20, size 0x4
|
||||
unsigned long user; // offset 0x24, size 0x4
|
||||
} ARAMTransferJob;
|
||||
|
||||
typedef struct ARAMTransferQueue {
|
||||
// total size: 0x284
|
||||
ARAMTransferJob queue[16]; // offset 0x0, size 0x280
|
||||
vu8 write; // offset 0x280, size 0x1
|
||||
vu8 valid; // offset 0x281, size 0x1
|
||||
} ARAMTransferQueue;
|
||||
|
||||
typedef struct STREAM_BUFFER {
|
||||
// total size: 0x10
|
||||
struct STREAM_BUFFER* next; // offset 0x0, size 0x4
|
||||
unsigned long aram; // offset 0x4, size 0x4
|
||||
unsigned long length; // offset 0x8, size 0x4
|
||||
unsigned long allocLength; // offset 0xC, size 0x4
|
||||
} STREAM_BUFFER;
|
||||
|
||||
static unsigned long aramTop; // size: 0x4
|
||||
static unsigned long aramWrite; // size: 0x4
|
||||
static unsigned long aramStream; // size: 0x4
|
||||
static void* (*aramUploadCallback)(unsigned long, unsigned long); // size: 0x4
|
||||
static unsigned long aramUploadChunkSize; // size: 0x4
|
||||
|
||||
static ARAMTransferQueue aramQueueLo;
|
||||
static ARAMTransferQueue aramQueueHi;
|
||||
|
||||
static STREAM_BUFFER aramStreamBuffers[64];
|
||||
static STREAM_BUFFER* aramUsedStreamBuffers;
|
||||
static STREAM_BUFFER* aramFreeStreamBuffers;
|
||||
static STREAM_BUFFER* aramIdleStreamBuffers;
|
||||
|
||||
static void InitStreamBuffers();
|
||||
|
||||
static void aramQueueInit() {
|
||||
aramQueueLo.write = aramQueueLo.valid = 0;
|
||||
aramQueueHi.write = aramQueueHi.valid = 0;
|
||||
}
|
||||
|
||||
static void aramQueueCallback(unsigned long ptr) {
|
||||
u32 i; // r31
|
||||
ARQRequest* arq; // r29
|
||||
ARAMTransferQueue* aramQueue; // r30
|
||||
|
||||
arq = (ARQRequest*)ptr;
|
||||
if (arq->priority == 1) {
|
||||
aramQueue = &aramQueueHi;
|
||||
} else {
|
||||
aramQueue = &aramQueueLo;
|
||||
}
|
||||
|
||||
for (i = 0; i < 16; ++i) {
|
||||
if (arq == &aramQueue->queue[i].arq && aramQueue->queue[i].callback) {
|
||||
aramQueue->queue[i].callback(aramQueue->queue[i].user);
|
||||
}
|
||||
}
|
||||
|
||||
--aramQueue->valid;
|
||||
}
|
||||
|
||||
void aramUploadData(void* mram, unsigned long aram, unsigned long len, unsigned long highPrio,
|
||||
void (*callback)(unsigned long), unsigned long user) {
|
||||
ARAMTransferQueue* aramQueue; // r31
|
||||
int old; // r30
|
||||
|
||||
aramQueue = highPrio != 0 ? &aramQueueHi : &aramQueueLo;
|
||||
|
||||
for (;;) {
|
||||
old = OSDisableInterrupts();
|
||||
if (aramQueue->valid < 16) {
|
||||
aramQueue->queue[aramQueue->write].arq.owner = 42;
|
||||
aramQueue->queue[aramQueue->write].arq.type = 0;
|
||||
aramQueue->queue[aramQueue->write].arq.priority = highPrio != 0 ? 1 : 0;
|
||||
aramQueue->queue[aramQueue->write].arq.source = (u32)mram;
|
||||
aramQueue->queue[aramQueue->write].arq.dest = aram;
|
||||
aramQueue->queue[aramQueue->write].arq.length = len;
|
||||
aramQueue->queue[aramQueue->write].arq.callback = aramQueueCallback;
|
||||
aramQueue->queue[aramQueue->write].callback = callback;
|
||||
aramQueue->queue[aramQueue->write].user = user;
|
||||
ARQPostRequest(&aramQueue->queue[aramQueue->write].arq,
|
||||
aramQueue->queue[aramQueue->write].arq.owner,
|
||||
aramQueue->queue[aramQueue->write].arq.type,
|
||||
aramQueue->queue[aramQueue->write].arq.priority,
|
||||
aramQueue->queue[aramQueue->write].arq.source,
|
||||
aramQueue->queue[aramQueue->write].arq.dest,
|
||||
aramQueue->queue[aramQueue->write].arq.length,
|
||||
aramQueue->queue[aramQueue->write].arq.callback);
|
||||
++aramQueue->valid;
|
||||
aramQueue->write = (aramQueue->write + 1) % 16;
|
||||
OSRestoreInterrupts(old);
|
||||
return;
|
||||
}
|
||||
OSRestoreInterrupts(old);
|
||||
}
|
||||
}
|
||||
|
||||
void aramSyncTransferQueue() {
|
||||
while (aramQueueLo.valid != 0) {
|
||||
}
|
||||
}
|
||||
|
||||
void aramInit(unsigned long length) {
|
||||
signed short* tmpMem; // r30
|
||||
unsigned long i; // r29
|
||||
unsigned long aramBase; // r28
|
||||
#line 173
|
||||
MUSY_ASSERT_MSG(length > sizeof(s16) * 640, "ARAM size is too small");
|
||||
|
||||
aramBase = ARGetBaseAddress();
|
||||
|
||||
tmpMem = (s16*)salMalloc(sizeof(s16) * 640);
|
||||
#line 182
|
||||
MUSY_ASSERT_MSG(tmpMem != NULL, "Could not allocate temporary storage");
|
||||
|
||||
for (i = 0; i < 640; ++i) {
|
||||
tmpMem[i] = 0;
|
||||
}
|
||||
|
||||
DCFlushRange(tmpMem, sizeof(s16) * 640);
|
||||
aramQueueInit();
|
||||
aramUploadData(tmpMem, aramBase, sizeof(s16) * 640, 0, NULL, 0);
|
||||
aramSyncTransferQueue();
|
||||
salFree(tmpMem);
|
||||
aramTop = aramBase + length;
|
||||
if (aramTop > ARGetSize()) {
|
||||
aramTop = ARGetSize();
|
||||
}
|
||||
|
||||
aramWrite = aramBase + sizeof(s16) * 640;
|
||||
aramUploadCallback = NULL;
|
||||
InitStreamBuffers();
|
||||
#if _DEBUG
|
||||
OSReport("MusyX ARAM handler initialized\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
void aramExit() {}
|
||||
|
||||
unsigned long aramGetZeroBuffer() { return ARGetBaseAddress(); }
|
||||
|
||||
void aramSetUploadCallback(void* (*callback)(unsigned long, unsigned long),
|
||||
unsigned long chunckSize) {
|
||||
unsigned long acs; // r30
|
||||
|
||||
if (callback != NULL) {
|
||||
chunckSize = (chunckSize + 31) & ~31;
|
||||
acs = ARQGetChunkSize();
|
||||
aramUploadChunkSize = chunckSize < acs ? acs : chunckSize;
|
||||
}
|
||||
|
||||
aramUploadCallback = callback;
|
||||
}
|
||||
|
||||
void* aramStoreData(void* src, unsigned long len) {
|
||||
unsigned long addr; // r26
|
||||
void* buffer; // r27
|
||||
unsigned long blkSize; // r30
|
||||
len = (len + 31) & ~31;
|
||||
#line 266
|
||||
MUSY_ASSERT_MSG(aramWrite + len <= aramStream, "Data will not fit in remaining ARAM space");
|
||||
addr = aramWrite;
|
||||
if (aramUploadCallback == NULL) {
|
||||
#line 276
|
||||
MUSY_ASSERT_MSG(!((u32)src & 31), "MRAM address is not aligned properly");
|
||||
DCFlushRange(src, len);
|
||||
aramUploadData(src, aramWrite, len, 0, NULL, 0);
|
||||
aramWrite += len;
|
||||
return (void*)addr;
|
||||
}
|
||||
|
||||
while (len != 0) {
|
||||
blkSize = len >= aramUploadChunkSize ? aramUploadChunkSize : len;
|
||||
buffer = (void*)aramUploadCallback((u32)src, blkSize);
|
||||
#line 297
|
||||
MUSY_ASSERT_MSG(!((u32)buffer & 31), "MRAM address is not aligned properly");
|
||||
DCFlushRange(buffer, blkSize);
|
||||
aramUploadData(buffer, aramWrite, blkSize, 0, NULL, 0);
|
||||
len -= blkSize;
|
||||
aramWrite += blkSize;
|
||||
src = (void*)((u32)src + blkSize);
|
||||
}
|
||||
|
||||
return (void*)addr;
|
||||
}
|
||||
|
||||
void aramRemoveData(void* aram, unsigned long len) {
|
||||
len = (len + 31) & ~31;
|
||||
aramWrite -= len;
|
||||
#line 328
|
||||
MUSY_ASSERT_MSG((u32)aram == aramWrite,
|
||||
"Current ARAM address does not match originally allocated one");
|
||||
}
|
||||
|
||||
static void InitStreamBuffers() {
|
||||
unsigned long i; // r31
|
||||
aramUsedStreamBuffers = NULL;
|
||||
aramFreeStreamBuffers = NULL;
|
||||
aramIdleStreamBuffers = aramStreamBuffers;
|
||||
for (i = 1; i < 64; ++i) {
|
||||
aramStreamBuffers[i - 1].next = &aramStreamBuffers[i];
|
||||
}
|
||||
aramStreamBuffers[i - 1].next = NULL;
|
||||
aramStream = aramTop;
|
||||
}
|
||||
|
||||
unsigned char aramAllocateStreamBuffer(unsigned long len) {
|
||||
STREAM_BUFFER* sb; // r30
|
||||
STREAM_BUFFER* oSb; // r31
|
||||
STREAM_BUFFER* lastSb; // r28
|
||||
u32 minLen; // r27
|
||||
|
||||
len = (len + 31) & ~31;
|
||||
lastSb = oSb = NULL;
|
||||
minLen = -1;
|
||||
|
||||
for (sb = aramFreeStreamBuffers; sb != NULL; sb = sb->next) {
|
||||
if (sb->allocLength == len) {
|
||||
oSb = sb;
|
||||
break;
|
||||
}
|
||||
|
||||
if (sb->allocLength > len && minLen > sb->allocLength) {
|
||||
oSb = sb;
|
||||
minLen = sb->allocLength;
|
||||
}
|
||||
lastSb = sb;
|
||||
}
|
||||
|
||||
if (oSb == NULL) {
|
||||
if (aramIdleStreamBuffers != NULL && aramStream - len >= aramWrite) {
|
||||
oSb = aramIdleStreamBuffers;
|
||||
aramIdleStreamBuffers = oSb->next;
|
||||
oSb->allocLength = len;
|
||||
oSb->length = len;
|
||||
aramStream -= len;
|
||||
oSb->aram = aramStream;
|
||||
oSb->next = aramUsedStreamBuffers;
|
||||
aramUsedStreamBuffers = oSb;
|
||||
}
|
||||
} else {
|
||||
if (lastSb != NULL) {
|
||||
lastSb->next = oSb->next;
|
||||
} else {
|
||||
aramFreeStreamBuffers = oSb->next;
|
||||
}
|
||||
|
||||
oSb->length = len;
|
||||
oSb->next = aramUsedStreamBuffers;
|
||||
aramUsedStreamBuffers = oSb;
|
||||
}
|
||||
|
||||
if (oSb == NULL) {
|
||||
#if _DEBUG
|
||||
OSReport("No stream buffer slots available or ARAM.\n\n");
|
||||
#endif
|
||||
return 0xFF;
|
||||
}
|
||||
|
||||
return (oSb - aramStreamBuffers);
|
||||
}
|
||||
|
||||
unsigned long aramGetStreamBufferAddress(unsigned char id, unsigned long* len) {
|
||||
#line 467
|
||||
MUSY_ASSERT_MSG(id != 0xFF, "Stream buffer ID is invalid");
|
||||
|
||||
if (len != NULL) {
|
||||
*len = aramStreamBuffers[id].length;
|
||||
}
|
||||
|
||||
return aramStreamBuffers[id].aram;
|
||||
}
|
||||
|
||||
void aramFreeStreamBuffer(unsigned char id) {
|
||||
struct STREAM_BUFFER* fSb; // r30
|
||||
struct STREAM_BUFFER* sb; // r31
|
||||
struct STREAM_BUFFER* lastSb; // r29
|
||||
struct STREAM_BUFFER* nextSb; // r27
|
||||
unsigned long minAddr; // r28
|
||||
|
||||
MUSY_ASSERT_MSG(id != 0xFF, "Stream buffer ID is invalid");
|
||||
fSb = &aramStreamBuffers[id];
|
||||
lastSb = NULL;
|
||||
sb = aramUsedStreamBuffers;
|
||||
|
||||
while (sb != NULL) {
|
||||
if (sb == fSb) {
|
||||
if (lastSb != NULL) {
|
||||
lastSb->next = fSb->next;
|
||||
} else {
|
||||
aramUsedStreamBuffers = fSb->next;
|
||||
}
|
||||
break;
|
||||
} else {
|
||||
lastSb = sb;
|
||||
sb = sb->next;
|
||||
}
|
||||
}
|
||||
|
||||
if (fSb->aram == aramStream) {
|
||||
fSb->next = aramIdleStreamBuffers;
|
||||
aramIdleStreamBuffers = fSb;
|
||||
minAddr = -1;
|
||||
sb = aramUsedStreamBuffers;
|
||||
while (sb != NULL) {
|
||||
if (sb->aram <= minAddr) {
|
||||
minAddr = sb->aram;
|
||||
}
|
||||
sb = sb->next;
|
||||
}
|
||||
|
||||
lastSb = NULL;
|
||||
sb = aramFreeStreamBuffers;
|
||||
while (sb != NULL) {
|
||||
nextSb = sb->next;
|
||||
if (sb->aram < minAddr) {
|
||||
if (lastSb != NULL) {
|
||||
lastSb->next = sb->next;
|
||||
} else {
|
||||
aramFreeStreamBuffers = sb->next;
|
||||
}
|
||||
|
||||
sb->next = aramIdleStreamBuffers;
|
||||
aramIdleStreamBuffers = sb;
|
||||
}
|
||||
sb = nextSb;
|
||||
}
|
||||
|
||||
aramStream = minAddr != -1 ? minAddr : aramTop;
|
||||
return;
|
||||
}
|
||||
fSb->next = aramFreeStreamBuffers;
|
||||
aramFreeStreamBuffers = fSb;
|
||||
}
|
Loading…
Reference in New Issue