184 lines
5.1 KiB
C
184 lines
5.1 KiB
C
|
#include "global.h"
|
||
|
#include "dma3.h"
|
||
|
|
||
|
#define MAX_DMA_REQUESTS 128
|
||
|
|
||
|
#define DMA_REQUEST_COPY32 1
|
||
|
#define DMA_REQUEST_FILL32 2
|
||
|
#define DMA_REQUEST_COPY16 3
|
||
|
#define DMA_REQUEST_FILL16 4
|
||
|
|
||
|
struct Dma3Request
|
||
|
{
|
||
|
const u8 *src;
|
||
|
u8 *dest;
|
||
|
u16 size;
|
||
|
u16 mode;
|
||
|
u32 value;
|
||
|
};
|
||
|
|
||
|
static struct Dma3Request sDma3Requests[MAX_DMA_REQUESTS];
|
||
|
|
||
|
static vbool8 sDma3ManagerLocked;
|
||
|
static u8 sDma3RequestCursor;
|
||
|
|
||
|
void ClearDma3Requests(void)
|
||
|
{
|
||
|
int i;
|
||
|
|
||
|
sDma3ManagerLocked = TRUE;
|
||
|
sDma3RequestCursor = 0;
|
||
|
|
||
|
for (i = 0; i < MAX_DMA_REQUESTS; i++)
|
||
|
{
|
||
|
sDma3Requests[i].size = 0;
|
||
|
sDma3Requests[i].src = NULL;
|
||
|
sDma3Requests[i].dest = NULL;
|
||
|
}
|
||
|
|
||
|
sDma3ManagerLocked = FALSE;
|
||
|
}
|
||
|
|
||
|
void ProcessDma3Requests(void)
|
||
|
{
|
||
|
u16 bytesTransferred;
|
||
|
|
||
|
if (sDma3ManagerLocked)
|
||
|
return;
|
||
|
|
||
|
bytesTransferred = 0;
|
||
|
|
||
|
// as long as there are DMA requests to process (unless size or vblank is an issue), do not exit
|
||
|
while (sDma3Requests[sDma3RequestCursor].size != 0)
|
||
|
{
|
||
|
bytesTransferred += sDma3Requests[sDma3RequestCursor].size;
|
||
|
|
||
|
if (bytesTransferred > 40 * 1024)
|
||
|
return; // don't transfer more than 40 KiB
|
||
|
if (*(u8 *)REG_ADDR_VCOUNT > 224)
|
||
|
return; // we're about to leave vblank, stop
|
||
|
|
||
|
switch (sDma3Requests[sDma3RequestCursor].mode)
|
||
|
{
|
||
|
case DMA_REQUEST_COPY32: // regular 32-bit copy
|
||
|
Dma3CopyLarge32_(sDma3Requests[sDma3RequestCursor].src,
|
||
|
sDma3Requests[sDma3RequestCursor].dest,
|
||
|
sDma3Requests[sDma3RequestCursor].size);
|
||
|
break;
|
||
|
case DMA_REQUEST_FILL32: // repeat a single 32-bit value across RAM
|
||
|
Dma3FillLarge32_(sDma3Requests[sDma3RequestCursor].value,
|
||
|
sDma3Requests[sDma3RequestCursor].dest,
|
||
|
sDma3Requests[sDma3RequestCursor].size);
|
||
|
break;
|
||
|
case DMA_REQUEST_COPY16: // regular 16-bit copy
|
||
|
Dma3CopyLarge16_(sDma3Requests[sDma3RequestCursor].src,
|
||
|
sDma3Requests[sDma3RequestCursor].dest,
|
||
|
sDma3Requests[sDma3RequestCursor].size);
|
||
|
break;
|
||
|
case DMA_REQUEST_FILL16: // repeat a single 16-bit value across RAM
|
||
|
Dma3FillLarge16_(sDma3Requests[sDma3RequestCursor].value,
|
||
|
sDma3Requests[sDma3RequestCursor].dest,
|
||
|
sDma3Requests[sDma3RequestCursor].size);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
// Free the request
|
||
|
sDma3Requests[sDma3RequestCursor].src = NULL;
|
||
|
sDma3Requests[sDma3RequestCursor].dest = NULL;
|
||
|
sDma3Requests[sDma3RequestCursor].size = 0;
|
||
|
sDma3Requests[sDma3RequestCursor].mode = 0;
|
||
|
sDma3Requests[sDma3RequestCursor].value = 0;
|
||
|
sDma3RequestCursor++;
|
||
|
|
||
|
if (sDma3RequestCursor >= MAX_DMA_REQUESTS) // loop back to the first DMA request
|
||
|
sDma3RequestCursor = 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
s16 RequestDma3Copy(const void *src, void *dest, u16 size, u8 mode)
|
||
|
{
|
||
|
int cursor;
|
||
|
int i = 0;
|
||
|
|
||
|
sDma3ManagerLocked = TRUE;
|
||
|
cursor = sDma3RequestCursor;
|
||
|
|
||
|
while (i < MAX_DMA_REQUESTS)
|
||
|
{
|
||
|
if (sDma3Requests[cursor].size == 0) // an empty request was found.
|
||
|
{
|
||
|
sDma3Requests[cursor].src = src;
|
||
|
sDma3Requests[cursor].dest = dest;
|
||
|
sDma3Requests[cursor].size = size;
|
||
|
|
||
|
if (mode == 1)
|
||
|
sDma3Requests[cursor].mode = DMA_REQUEST_COPY32;
|
||
|
else
|
||
|
sDma3Requests[cursor].mode = DMA_REQUEST_COPY16;
|
||
|
|
||
|
sDma3ManagerLocked = FALSE;
|
||
|
return cursor;
|
||
|
}
|
||
|
if (++cursor >= MAX_DMA_REQUESTS) // loop back to start.
|
||
|
cursor = 0;
|
||
|
i++;
|
||
|
}
|
||
|
sDma3ManagerLocked = FALSE;
|
||
|
return -1; // no free DMA request was found
|
||
|
}
|
||
|
|
||
|
s16 RequestDma3Fill(s32 value, void *dest, u16 size, u8 mode)
|
||
|
{
|
||
|
int cursor;
|
||
|
int i = 0;
|
||
|
|
||
|
cursor = sDma3RequestCursor;
|
||
|
sDma3ManagerLocked = TRUE;
|
||
|
|
||
|
while (i < MAX_DMA_REQUESTS)
|
||
|
{
|
||
|
if (sDma3Requests[cursor].size == 0) // an empty request was found.
|
||
|
{
|
||
|
sDma3Requests[cursor].dest = dest;
|
||
|
sDma3Requests[cursor].size = size;
|
||
|
sDma3Requests[cursor].mode = mode;
|
||
|
sDma3Requests[cursor].value = value;
|
||
|
|
||
|
if(mode == 1)
|
||
|
sDma3Requests[cursor].mode = DMA_REQUEST_FILL32;
|
||
|
else
|
||
|
sDma3Requests[cursor].mode = DMA_REQUEST_FILL16;
|
||
|
|
||
|
sDma3ManagerLocked = FALSE;
|
||
|
return cursor;
|
||
|
}
|
||
|
if (++cursor >= MAX_DMA_REQUESTS) // loop back to start.
|
||
|
cursor = 0;
|
||
|
i++;
|
||
|
}
|
||
|
sDma3ManagerLocked = FALSE;
|
||
|
return -1; // no free DMA request was found
|
||
|
}
|
||
|
|
||
|
s16 CheckForSpaceForDma3Request(s16 index)
|
||
|
{
|
||
|
int i = 0;
|
||
|
|
||
|
if (index == -1) // check if all requests are free
|
||
|
{
|
||
|
while (i < MAX_DMA_REQUESTS)
|
||
|
{
|
||
|
if (sDma3Requests[i].size != 0)
|
||
|
return -1;
|
||
|
i++;
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
else // check the specified request
|
||
|
{
|
||
|
if (sDma3Requests[index].size != 0)
|
||
|
return -1;
|
||
|
return 0;
|
||
|
}
|
||
|
}
|