272 lines
6.7 KiB
C
272 lines
6.7 KiB
C
#include "usf.h"
|
|
#include "usf_internal.h"
|
|
|
|
#include "cpu_hle.h"
|
|
#include "audiolib.h"
|
|
#include "os.h"
|
|
|
|
#include "main.h"
|
|
#include "memory.h"
|
|
|
|
#define N64WORD(x) (*(uint32_t*)PageVRAM((x)))
|
|
#define N64HALF(x) (*(uint16_t*)PageVRAM((x)))
|
|
#define N64BYTE(x) (*(uint8_t*)PageVRAM((x)))
|
|
|
|
|
|
int alCopy(usf_state_t * state, int paddr) {
|
|
uint32_t source = (state->GPR[4].UW[0]);
|
|
uint32_t dest = (state->GPR[5].UW[0]);
|
|
uint32_t len = (state->GPR[6].UW[0]);
|
|
|
|
if(len&3)
|
|
DisplayError(state, "OMG!!!! - alCopy length & 3\n");
|
|
|
|
memcpyn642n64(state, dest, source, len);
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
|
|
int alLink(usf_state_t * state, int paddr) {
|
|
ALLink *element = (ALLink*)PageVRAM(state->GPR[4].UW[0]);
|
|
ALLink *after = (ALLink*)PageVRAM(state->GPR[5].UW[0]);
|
|
ALLink *afterNext;
|
|
|
|
element->next = after->next;
|
|
element->prev = state->GPR[5].UW[0];
|
|
|
|
if (after->next) {
|
|
afterNext = (ALLink*)PageVRAM(after->next);
|
|
afterNext->prev = state->GPR[4].UW[0];
|
|
}
|
|
|
|
after->next = state->GPR[4].UW[0];
|
|
return 1;
|
|
}
|
|
|
|
|
|
int alUnLink(usf_state_t * state, int paddr) {
|
|
ALLink *element = (ALLink*)PageVRAM(state->GPR[4].UW[0]);
|
|
ALLink *elementNext = (ALLink*)PageVRAM(element->next);
|
|
ALLink *elementPrev = (ALLink*)PageVRAM(element->prev);
|
|
// _asm int 3
|
|
|
|
if (element->next)
|
|
elementNext->prev = element->prev;
|
|
if (element->prev)
|
|
elementPrev->next = element->next;
|
|
return 1;
|
|
}
|
|
|
|
int alEvtqPostEvent(usf_state_t * state, int paddr) {
|
|
ALEventQueue *evtq;
|
|
ALEvent *events;
|
|
|
|
uint32_t A0 = state->GPR[4].UW[0];
|
|
uint32_t A1 = state->GPR[5].UW[0];
|
|
uint32_t DeltaTime = state->GPR[6].UW[0];
|
|
|
|
uint32_t nodeNext = 0;
|
|
uint32_t nextItem = 0;
|
|
uint32_t node = 0;
|
|
uint32_t nextDelta = 0;
|
|
uint32_t item = 0;
|
|
uint32_t postWhere = 0;
|
|
uint32_t NEXT = 0;
|
|
uint32_t nextItemDelta = 0;
|
|
|
|
evtq = (ALEventQueue *)PageVRAM(A0);
|
|
events = (ALEvent *)PageVRAM(A1);
|
|
//_asm int 3
|
|
|
|
NEXT = evtq->freeList.next;
|
|
|
|
if(NEXT == 0)
|
|
return 1;
|
|
|
|
//DisplayError("%08x", N64WORD(0x800533E4));
|
|
//cprintf("%08x\t%08x\n", N64WORD(0x800533D4), N64WORD(0x800533D8));
|
|
|
|
item = NEXT;
|
|
state->GPR[4].UW[0] = NEXT;
|
|
alUnLink(state, 0);
|
|
|
|
state->GPR[4].UW[0] = A1; state->GPR[5].UW[0] = NEXT + 0xC; state->GPR[6].UW[0] = 0x10;
|
|
alCopy(state, 0);
|
|
|
|
postWhere = (DeltaTime==0x7FFFFFFF)?1:0;
|
|
nodeNext = A0;
|
|
node = nodeNext + 8;
|
|
|
|
while(nodeNext !=0 ) {
|
|
nodeNext = *(uint32_t*)PageVRAM(node);
|
|
|
|
if(nodeNext != 0) {
|
|
nextDelta = *(uint32_t*)PageVRAM(nodeNext + 8);
|
|
nextItem = nodeNext;
|
|
if(DeltaTime < nextDelta) {
|
|
*(uint32_t*)PageVRAM(item + 8) = DeltaTime;
|
|
nextItemDelta = *(uint32_t*)PageVRAM(nextItem + 8);
|
|
*(uint32_t*)PageVRAM(nextItem + 8) = nextItemDelta - DeltaTime;
|
|
|
|
state->GPR[4].UW[0] = item; state->GPR[5].UW[0] = node;
|
|
alLink(state, 0);
|
|
return 1;
|
|
} else {
|
|
node = nodeNext;
|
|
DeltaTime -= nextDelta;
|
|
if(node == 0)
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
if(postWhere == 0)
|
|
*(uint32_t*)PageVRAM(item + 8) = DeltaTime;
|
|
else
|
|
*(uint32_t*)PageVRAM(item + 8) = 0;
|
|
|
|
|
|
state->GPR[4].UW[0] = item; state->GPR[5].UW[0] = node;
|
|
alLink(state, 0);
|
|
return 1;
|
|
}
|
|
|
|
int alEvtqPostEvent_Alt(usf_state_t * state, int paddr) {
|
|
return 0;
|
|
}
|
|
|
|
#ifndef MIN
|
|
#define MIN(a,b) (((a)<(b))?(a):(b))
|
|
#endif
|
|
|
|
uint32_t __nextSampleTime(usf_state_t * state, uint32_t driver, uint32_t *client) {
|
|
|
|
uint32_t c = 0;
|
|
int32_t deltaTime = 0x7FFFFFFF;
|
|
*client = 0;
|
|
|
|
for(c = N64WORD(driver); c != 0; c = N64WORD(c)) {
|
|
int samplesLeft = N64WORD(c + 0x10);
|
|
int curSamples = N64WORD(driver + 0x20);
|
|
if((samplesLeft - curSamples) < deltaTime) {
|
|
*client = c;
|
|
deltaTime = samplesLeft - curSamples;
|
|
}
|
|
}
|
|
|
|
return N64WORD((*client)+0x10);
|
|
}
|
|
|
|
int32_t _timeToSamplesNoRound(usf_state_t * state, long synth, long micros)
|
|
{
|
|
uint32_t outputRate = N64WORD(synth+0x44);
|
|
float tmp = ((float)micros) * outputRate / 1000000.0 + 0.5;
|
|
//DisplayError("Smaple rate is %d", outputRate);
|
|
|
|
return (int32_t)tmp;
|
|
}
|
|
|
|
uint32_t byteswap(char b[4] ) {
|
|
uint32_t out = 0;
|
|
out += b[3];
|
|
out += b[2] << 8;
|
|
out += b[1] << 16;
|
|
out += b[0] << 24;
|
|
return out;
|
|
}
|
|
|
|
int alAudioFrame(usf_state_t * state, int paddr) {
|
|
|
|
uint32_t alGlobals = 0;
|
|
uint32_t driver = 0, *paramSamples, *curSamples, client = 0, dl = 0;
|
|
uint32_t A0 = state->GPR[4].UW[0];
|
|
uint32_t A1 = state->GPR[5].UW[0];
|
|
uint32_t A2 = state->GPR[6].UW[0];
|
|
uint32_t outLen = state->GPR[7].UW[0];
|
|
uint32_t cmdlEnd = A0;
|
|
uint32_t lOutBuf = A2;
|
|
|
|
alGlobals = ((*(uint16_t*)PageRAM2(paddr + 0x8)) & 0xFFFF) << 16; //alGlobals->drvr
|
|
alGlobals += *(int16_t*)PageRAM2(paddr + 0xc);
|
|
//alGlobals = 0x80750C74;
|
|
driver = N64WORD(alGlobals);
|
|
paramSamples = (uint32_t*) PageVRAM(driver + 0x1c);
|
|
curSamples = (uint32_t*) PageVRAM(driver + 0x20);
|
|
|
|
if(N64WORD(driver) == 0) { // if(drvr->head == 0)
|
|
N64WORD(A1) = 0;
|
|
state->GPR[2].UW[0] = A0;
|
|
return 1;
|
|
}
|
|
|
|
for(*paramSamples = __nextSampleTime(state, driver, &client); (*paramSamples - *curSamples) < outLen; *paramSamples = __nextSampleTime(state, driver, &client)) {
|
|
int32_t *cSamplesLeft;
|
|
cSamplesLeft = (int32_t *) PageVRAM(client + 0x10);
|
|
*paramSamples &= ~0xf;
|
|
|
|
//run handler (not-HLE'd)
|
|
state->GPR[4].UW[0] = client;
|
|
RunFunction(state, N64WORD(client+0x8));
|
|
*cSamplesLeft += _timeToSamplesNoRound(state, driver, state->GPR[2].UW[0]);
|
|
}
|
|
|
|
*paramSamples &= ~0xf;
|
|
|
|
//give us some stack
|
|
state->GPR[0x1d].UW[0] -= 0x20;
|
|
N64WORD(state->GPR[0x1d].UW[0]+0x4) = 0; //tmp
|
|
|
|
while (outLen > 0) {
|
|
|
|
uint32_t maxOutSamples = 0, nOut = 0, cmdPtr = 0, output = 0, setParam = 0, handler = 0;
|
|
|
|
maxOutSamples = N64WORD(driver + 0x48);
|
|
nOut = MIN(maxOutSamples, outLen);
|
|
cmdPtr = cmdlEnd;//+8;
|
|
|
|
output = N64WORD(driver + 0x38);
|
|
setParam = N64WORD(output+8); // alSaveParam
|
|
|
|
state->GPR[4].DW = output;
|
|
state->GPR[5].DW = 0x6; // AL_FILTER_SET_DRAM
|
|
state->GPR[6].DW = lOutBuf;
|
|
RunFunction(state, setParam);
|
|
|
|
handler = N64WORD(output+4); // alSavePull
|
|
state->GPR[4].DW = output;
|
|
state->GPR[5].DW = state->GPR[0x1d].UW[0]+0x12; //&tmp
|
|
state->GPR[6].DW = nOut;
|
|
state->GPR[7].DW = *curSamples;
|
|
N64WORD(state->GPR[0x1d].UW[0]+0x10) = cmdPtr;
|
|
RunFunction(state, handler);
|
|
|
|
curSamples = (uint32_t *) PageVRAM(driver + 0x20);
|
|
|
|
cmdlEnd = state->GPR[2].UW[0];
|
|
outLen -= nOut;
|
|
lOutBuf += (nOut<<2);
|
|
*curSamples += nOut;
|
|
|
|
}
|
|
|
|
state->GPR[0x1d].UW[0] += 0x20;
|
|
|
|
N64WORD(A1) = (int32_t) ((cmdlEnd - A0) >> 3);
|
|
|
|
state->GPR[4].UW[0] = driver;
|
|
|
|
while( (dl = N64WORD(driver+0x14)) ) {
|
|
state->GPR[4].UW[0] = dl;
|
|
alUnLink(state, 0);
|
|
state->GPR[4].UW[0] = dl;
|
|
state->GPR[5].UW[0] = driver + 4;
|
|
alLink(state, 0);
|
|
}
|
|
|
|
state->GPR[2].UW[0] = cmdlEnd;
|
|
return 1;
|
|
}
|