daedalus/Source/SysPSP/PRX/MediaEngine/main.c
2019-05-16 18:27:05 -04:00

172 lines
3.2 KiB
C

#include <pspsdk.h>
#include <pspkernel.h>
#include <string.h>
#define VERS 1
#define REVS 0
PSP_MODULE_INFO("MediaEngine", 0x1006, VERS, REVS);
PSP_MAIN_THREAD_ATTR(0);
struct me_struct
{
int start;
int done;
int (*func)(int); // function ptr - func takes an int argument and returns int
int param; // function argument
int result; // function return value
int precache_len; // amount of space to invalidate before running func, -1 = all
void *precache_addr; // address of space to invalidate before running func
int postcache_len; // amount of space to flush after running func, -1 = all
void *postcache_addr; // address of space to flush after running func
unsigned int signals;
int init;
};
extern void me_stub(void);
extern void me_stub_end(void);
/*
* cache functions
*
*/
#define store_tag(index, hi, lo) __asm__ (".set push\n" \
".set noreorder\n" \
"mtc0 %0, $28\n" \
"mtc0 %1, $29\n" \
".set pop\n" \
::"r"(lo),"r"(hi)); \
__builtin_allegrex_cache(0x11, index);
void dcache_inv_all()
{
for(int i = 0; i < 16384; i += 64) {
store_tag(i, 0, 0);
__builtin_allegrex_cache(0x13, i);
__builtin_allegrex_cache(0x11, i);
}
}
void dcache_inv_range(void *addr, int size)
{
int i, j =(int)addr;
for(i = j; i < size+j; i += 64)
__builtin_allegrex_cache(0x19, i);
}
void dcache_wbinv_all()
{
for(int i = 0; i < 8192; i += 64)
{
__builtin_allegrex_cache(0x14, i);
__builtin_allegrex_cache(0x14, i);
}
}
void dcache_wbinv_range(void *addr, int size)
{
int i, j = (int)addr;
for(i = j; i < size+j; i += 64)
__builtin_allegrex_cache(0x1b, i);
}
static void me_loop(volatile struct me_struct *mei)
{
unsigned int k1;
k1 = pspSdkSetK1(0);
while (mei->init) // ME runs this loop until killed
{
while (mei->start == 0); // wait for function
mei->start = 0;
if (mei->precache_len)
{
dcache_inv_all();
}
mei->result = mei->func(mei->param); // run function
if (mei->postcache_len)
{
dcache_wbinv_all();
}
mei->done = 1;
}
pspSdkSetK1(k1);
while (1); // loop forever until ME reset
}
int InitME(volatile struct me_struct *mei)
{
unsigned int k1;
k1 = pspSdkSetK1(0);
if (mei == 0)
{
pspSdkSetK1(k1);
return -1;
}
// initialize the MediaEngine Instance
mei->start = 0;
mei->done = 1;
mei->func = 0;
mei->param = 0;
mei->result = 0;
mei->precache_len = 0;
mei->precache_addr = 0;
mei->postcache_len = 0;
mei->postcache_addr = 0;
mei->signals = 0;
mei->init = 1;
// start the MediaEngine
memcpy((void *)0xbfc00040, me_stub, (int)(me_stub_end - me_stub));
_sw((unsigned int)me_loop, 0xbfc00600); // k0
_sw((unsigned int)mei, 0xbfc00604); // a0
sceKernelDcacheWritebackAll();
sceSysregMeResetEnable();
sceSysregMeBusClockEnable();
sceSysregMeResetDisable();
pspSdkSetK1(k1);
return 0;
}
void KillME(volatile struct me_struct *mei)
{
unsigned int k1 = pspSdkSetK1(0);
if (mei == 0)
{
pspSdkSetK1(k1);
return;
}
mei->init = 0;
sceSysregMeResetEnable();
pspSdkSetK1(k1);
}
int module_start(SceSize args, void *argp)
{
return 0;
}
int module_stop()
{
return 0;
}