#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; }