diff --git a/Frameworks/lazyusf/lazyusf.xcodeproj/project.pbxproj b/Frameworks/lazyusf/lazyusf.xcodeproj/project.pbxproj index bc21fbf60..2aeb39b70 100644 --- a/Frameworks/lazyusf/lazyusf.xcodeproj/project.pbxproj +++ b/Frameworks/lazyusf/lazyusf.xcodeproj/project.pbxproj @@ -7,6 +7,12 @@ objects = { /* Begin PBXBuildFile section */ + 8319EF191A219846009DD5C4 /* cpu_hle.c in Sources */ = {isa = PBXBuildFile; fileRef = 8319EF171A219846009DD5C4 /* cpu_hle.c */; }; + 8319EF1A1A219846009DD5C4 /* cpu_hle.h in Headers */ = {isa = PBXBuildFile; fileRef = 8319EF181A219846009DD5C4 /* cpu_hle.h */; }; + 8319EF1D1A2198B9009DD5C4 /* os.c in Sources */ = {isa = PBXBuildFile; fileRef = 8319EF1B1A2198B9009DD5C4 /* os.c */; }; + 8319EF1E1A2198B9009DD5C4 /* os.h in Headers */ = {isa = PBXBuildFile; fileRef = 8319EF1C1A2198B9009DD5C4 /* os.h */; }; + 8319EF211A219BE7009DD5C4 /* audiolib.c in Sources */ = {isa = PBXBuildFile; fileRef = 8319EF1F1A219BE7009DD5C4 /* audiolib.c */; }; + 8319EF221A219BE7009DD5C4 /* audiolib.h in Headers */ = {isa = PBXBuildFile; fileRef = 8319EF201A219BE7009DD5C4 /* audiolib.h */; }; 8378416A18C6E56B002C4FE5 /* alist.c in Sources */ = {isa = PBXBuildFile; fileRef = 8378415418C6E56B002C4FE5 /* alist.c */; }; 8378416B18C6E56B002C4FE5 /* alist.h in Headers */ = {isa = PBXBuildFile; fileRef = 8378415518C6E56B002C4FE5 /* alist.h */; }; 8378416C18C6E56B002C4FE5 /* alist_audio.c in Sources */ = {isa = PBXBuildFile; fileRef = 8378415618C6E56B002C4FE5 /* alist_audio.c */; }; @@ -110,6 +116,12 @@ /* End PBXBuildFile section */ /* Begin PBXFileReference section */ + 8319EF171A219846009DD5C4 /* cpu_hle.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cpu_hle.c; sourceTree = ""; }; + 8319EF181A219846009DD5C4 /* cpu_hle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cpu_hle.h; sourceTree = ""; }; + 8319EF1B1A2198B9009DD5C4 /* os.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = os.c; sourceTree = ""; }; + 8319EF1C1A2198B9009DD5C4 /* os.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = os.h; sourceTree = ""; }; + 8319EF1F1A219BE7009DD5C4 /* audiolib.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = audiolib.c; sourceTree = ""; }; + 8319EF201A219BE7009DD5C4 /* audiolib.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = audiolib.h; sourceTree = ""; }; 8378415418C6E56B002C4FE5 /* alist.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = alist.c; sourceTree = ""; }; 8378415518C6E56B002C4FE5 /* alist.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = alist.h; sourceTree = ""; }; 8378415618C6E56B002C4FE5 /* alist_audio.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = alist_audio.c; sourceTree = ""; }; @@ -287,6 +299,12 @@ 83C8B62B18AF57770071B040 /* lazyusf */ = { isa = PBXGroup; children = ( + 8319EF1F1A219BE7009DD5C4 /* audiolib.c */, + 8319EF201A219BE7009DD5C4 /* audiolib.h */, + 8319EF1B1A2198B9009DD5C4 /* os.c */, + 8319EF1C1A2198B9009DD5C4 /* os.h */, + 8319EF171A219846009DD5C4 /* cpu_hle.c */, + 8319EF181A219846009DD5C4 /* cpu_hle.h */, 8378415318C6E56B002C4FE5 /* rsp_hle */, 83C8B6FD18AF59E70071B040 /* lazyusf-Info.plist */, 83C8B65A18AF58080071B040 /* audio.h */, @@ -415,11 +433,13 @@ 83C8B6B918AF58080071B040 /* main.h in Headers */, 83C8B6F418AF58090071B040 /* rsp.h in Headers */, 8378417018C6E56B002C4FE5 /* arithmetics.h in Headers */, + 8319EF221A219BE7009DD5C4 /* audiolib.h in Headers */, 83C8B6C018AF58080071B040 /* registers.h in Headers */, 83C8B6BE18AF58080071B040 /* pif.h in Headers */, 83C8B6F618AF58090071B040 /* tlb.h in Headers */, 83C8B6F718AF58090071B040 /* types.h in Headers */, 83C8B6BB18AF58080071B040 /* memory.h in Headers */, + 8319EF1E1A2198B9009DD5C4 /* os.h in Headers */, 83C8B6BC18AF58080071B040 /* opcode.h in Headers */, 83C8B6B718AF58080071B040 /* interpreter_ops.h in Headers */, 83C8B6B318AF58080071B040 /* exception.h in Headers */, @@ -471,6 +491,7 @@ 83C8B6E918AF58080071B040 /* vrcp.h in Headers */, 83C8B6D318AF58080071B040 /* vlt.h in Headers */, 83C8B6C118AF58080071B040 /* config.h in Headers */, + 8319EF1A1A219846009DD5C4 /* cpu_hle.h in Headers */, 83C8B6DF18AF58080071B040 /* vmudm.h in Headers */, 83C8B6D818AF58080071B040 /* vmadl.h in Headers */, 83C8B6EB18AF58090071B040 /* vrcpl.h in Headers */, @@ -564,8 +585,11 @@ 83C8B6AE18AF58080071B040 /* cpu.c in Sources */, 83C8B6AB18AF58080071B040 /* audio.c in Sources */, 83A2249418CAC28500FE4173 /* hle.c in Sources */, + 8319EF191A219846009DD5C4 /* cpu_hle.c in Sources */, + 8319EF1D1A2198B9009DD5C4 /* os.c in Sources */, 8378416E18C6E56B002C4FE5 /* alist_naudio.c in Sources */, 83C8B6B218AF58080071B040 /* exception.c in Sources */, + 8319EF211A219BE7009DD5C4 /* audiolib.c in Sources */, 83C8B6BF18AF58080071B040 /* registers.c in Sources */, 83C8B6F918AF58090071B040 /* usf.c in Sources */, 83C8B6B818AF58080071B040 /* main.c in Sources */, diff --git a/Frameworks/lazyusf/lazyusf/audiolib.c b/Frameworks/lazyusf/lazyusf/audiolib.c new file mode 100644 index 000000000..f843b16ac --- /dev/null +++ b/Frameworks/lazyusf/lazyusf/audiolib.c @@ -0,0 +1,273 @@ +#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 + +int32_t __nextSampleTime(usf_state_t * state, int32_t driver, int32_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; +} + +int32_t byteswap(char b[4] ) { + int32_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) { + + ALPlayer *cl; + uint32_t alGlobals = 0; + uint32_t driver = 0, head = 0, deltaTime = 0, c = 0, *paramSamples, *curSamples, handler = 0, dl = 0; + int32_t client = 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) { + + int32_t maxOutSamples = 0, nOut = 0, cmdPtr = 0, output = 0, setParam = 0, handler = 0, tmp = 0x700000; + + 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; +} diff --git a/Frameworks/lazyusf/lazyusf/audiolib.h b/Frameworks/lazyusf/lazyusf/audiolib.h new file mode 100644 index 000000000..375e9b8cb --- /dev/null +++ b/Frameworks/lazyusf/lazyusf/audiolib.h @@ -0,0 +1,60 @@ +#ifndef _CPU_HLE_AUDIOLIB_ +#define _CPU_HLE_AUDIOLIB_ + + + +#include "cpu_hle.h" +#include "os.h" + +// a few of these structures/type were sequestered from SGI\Nindendo's code + +typedef struct ALLink_s { + uint32_t next; + uint32_t prev; +} ALLink; + +typedef struct { + ALLink freeList; + ALLink allocList; + int32_t eventCount; +} ALEventQueue; + + +typedef struct { + uint16_t type; + uint8_t msg[12]; +} ALEvent; + + +typedef struct { + ALLink node; + int32_t delta; //microtime + ALEvent event; +} ALEventListItem; + +int alCopy(usf_state_t *, int paddr); +int alLink(usf_state_t *, int paddr); +int alUnLink(usf_state_t *, int paddr); +int alEvtqPostEvent(usf_state_t *, int paddr) ; +int alEvtqPostEvent_Alt(usf_state_t *, int paddr); +int alAudioFrame(usf_state_t *, int paddr); + +// need to remove these + +typedef struct { + uint8_t *base; + uint8_t *cur; + int32_t len; + int32_t count; +} ALHeap; + +typedef struct ALPlayer_s { + struct ALPlayer_s *next; + void *clientData; + void *handler; + int32_t callTime; + int32_t samplesLeft; +} ALPlayer; + + +#endif diff --git a/Frameworks/lazyusf/lazyusf/cpu.c b/Frameworks/lazyusf/lazyusf/cpu.c index 66d430fd8..295299ff4 100644 --- a/Frameworks/lazyusf/lazyusf/cpu.c +++ b/Frameworks/lazyusf/lazyusf/cpu.c @@ -33,6 +33,7 @@ #include "audio.h" #include "registers.h" #include "rsp.h" +#include "cpu_hle.h" #include "usf_internal.h" @@ -478,12 +479,47 @@ void StartEmulationFromSave ( usf_state_t * state, void * savestate ) { ChangeTimer(state,AiTimer,IntScheduled); AI_STATUS_REG|=0x40000000; } + + state->OLD_VI_V_SYNC_REG = ~VI_V_SYNC_REG; + + CPUHLE_Scan(state); } void RefreshScreen (usf_state_t * state){ - ChangeTimer(state, ViTimer, 300000); - + if (state->OLD_VI_V_SYNC_REG != VI_V_SYNC_REG) + { + if (VI_V_SYNC_REG == 0) + { + state->VI_INTR_TIME = 500000; + } + else + { + state->VI_INTR_TIME = (VI_V_SYNC_REG + 1) * 1500; + if ((VI_V_SYNC_REG % 1) != 0) + { + state->VI_INTR_TIME -= 38; + } + } + } + + ChangeTimer(state,ViTimer,state->Timers->Timer + state->Timers->NextTimer[ViTimer] + state->VI_INTR_TIME); + + if ((VI_STATUS_REG & 0x10) != 0) + { + if (state->ViFieldNumber == 0) + { + state->ViFieldNumber = 1; + } + else + { + state->ViFieldNumber = 0; + } + } + else + { + state->ViFieldNumber = 0; + } } void RunRsp (usf_state_t * state) { @@ -533,7 +569,7 @@ void TimerDone (usf_state_t * state) { case CompareTimer: if(state->enablecompare) FAKE_CAUSE_REGISTER |= CAUSE_IP7; - //CheckInterrupts(); + CheckInterrupts(state); ChangeCompareTimer(state); break; case ViTimer: diff --git a/Frameworks/lazyusf/lazyusf/cpu_hle.c b/Frameworks/lazyusf/lazyusf/cpu_hle.c new file mode 100644 index 000000000..e08c4c71d --- /dev/null +++ b/Frameworks/lazyusf/lazyusf/cpu_hle.c @@ -0,0 +1,148 @@ +#include + +#include "usf.h" +#include "usf_internal.h" + +#include "cpu_hle.h" +#include "os.h" +#include "audiolib.h" + +// Nintendo 64 Standard (and non standard) library functions, for HLE + + +int numEntries = 0; + + + +_HLE_Entry entrys[] = { + {"__osEnqueueThread",0,20,{0x8C,0x98,0,0,0x8C,0xAF,0,4,0,0x80,0xC8,0x25,0x8F,0xE,0,4,1,0xCF,8,0x2A},0,0,__osEnqueueThread}, + + {"__osRestoreInt",0,28,{0x40,8,0x60,0 ,1,4,0x40,0x25,0x40,0x88,0x60,0,0,0,0,0,0,0,0,0,3,0xE0,0,8,0,0,0,0},0,0,__osRestoreInt}, + {"__osDisableInt",0,32,{0x40,8,0x60,0,0x24,1,0xFF,0xFE,1,1,0x48,0x24,0x40,0x89,0x60,0,0x31,2,0,1,0,0,0,0,3,0xE0,0,8,0,0,0,0},0,0,__osDisableInt}, +// {"osStartThread",0,32,{0x27,0xBD,0xFF,0xD8,0xAF,0xBF,0,0x1C,0xAF,0xA4,0,0x28,0xAF,0xB1,0,0x18,0xC,-1,-1,-1,0xAF,0xB0,0,0x14,0x8F,0xAE,0,0x28,0x24,1,0,1,0,0x40,0x80,0x25},0,0,osStartThread}, + //{"osPiStartDma",0,52,{0x27,0xBD,0xFF,0xD8,0x3C,0xE,-1,-1,0x8D,0xCE,-1,-1,0xAF,0xBF,0,0x1C,0xAF,0xA4,0,0x28,0xAF,0xA5,0,0x2C,0xAF,0xA6,0,0x30,0xAF,0xA7,0,0x34,0xAF,0xB1,0,0x18,0x15,0xC0,0,3,0xAF,0xB0,0,0x14,0x10,0,0,0x32,0x24,2,0xFF,0xFF},0,0,osPiStartDma} + //{"osRecvMesg",0,60,{0x27,0xBD,0xFF,0xD8,0xAF,0xBF,0,0x1C,0xAF,0xA4,0,0x28,0xAF,0xA5,0,0x2C,0xAF,0xA6,0,0x30,0xAF,0xB1,0,0x18,0xC,-1,-1,-1,0xAF,0xB0,0,0x14,0x8F,0xAE,0,0x28,0,0x40,0x80,0x25,0x8D,0xCF,0,8,0x15,0xE0,0,0x12,0,0,0,0,0x8f,0xb8,0,0x30,0x17,0,0,5},0,0,osRecvMesg}, + + {"saveThreadContext",0,32,{0x3C,5,-1,-1,0x8C,0xA5,-1,-1,0x40,8,0x60,0,0x8C,0xBB,0,0x18,0x35,8,0,2,0xAC,0xA8,1,0x18,0xFC,0xB0,0,0x98,0xFC,0xB1,0,0xA0},0,0,saveThreadContext}, + {"loadThreadContext",0,40,{0x3C,4,-1,-1,0xC,-1,-1,-1,0x24,0x84,-1,-1,0x3C,1,-1,-1,0xAC,0x22,-1,-1,0x24,8,0,4,0xA4,0x48,0,0x10,0,0x40,0xD0,0x25,0x3C,8,-1,-1,0x8F,0x5B,1,0x18},0,0,loadThreadContext}, + + + {"osSetIntMask",0,44,{0x40,0xC,0x60,0,0x31,0x82,0xFF,1,0x3C,8,-1,-1,0x25,8,-1,-1,0x8D,0xB,0,0,0x24,1,0xFF,0xFF,1,0x61,0x40,0x26,0x31,8,0xFF,0,0,0x48,0x10,0x25,0x3C,0xA,0xA4,0x30,0x8D,0x4A,0,0xC},0,0,osSetIntMask}, + {"osVirtualToPhysical",0,36,{0x27,0xBD,0xFF,0xE8,0xAF,0xA4,0,0x18,0x8F,0xAE,0,0x18,0x3C,1,0x80,0,0xAF,0xBF,0,0x14,1,0xC1,8,0x2B,0x14,0x20,0,7,0x3C,1,0xA0,0,1,0xC1,8,0x2B},0,0,osVirtualToPhysical}, + + + {"alCopy",0,32,{0,0x80,0x10,0x25,0,0xA0,0x18,0x25,0x18,0xC0,0,0x18,0,0,0x38,0x25,0x30,0xC5,0,3,0x10,0xA0,0,9,0,0xA0,0x20,0x25,0x90,0x4E,0,0},0,0,alCopy}, + {"alLink",0,28,{0x8C,0xAE,0,0,0xAC,0x85,0,4,0xAC,0x8E,0,0,0x8C,0xA2,0,0,0x10,0x40,0,2,0,0,0,0,0xAC,0x44,0,4},0,0,alLink}, + {"alUnlink",0,28,{0x8C,0x82,0,0,0x50,0x40,0,4,0x8C,0x82,0,4,0x8C,0x8E,0,4,0xAC,0x4E,0,4,0x8C,0x82,0,4,0x10,0x40,0,3},0,0,alUnLink}, + + {"osAiSetNextBuffer",0,32,{0x27,0xBD,0xFF,0xE0,0x3C,0xF,-1,-1,0x91,0xEF,-1,-1,0xAF,0xA4,0,0x20,0x8F,0xAE,0,0x20,0xAF,0xBF,0,0x14,0xAF,0xA5,0,0x24,0x11,0xE0,0,3},0,0,osAiSetNextBuffer}, + + {"alLink (DK64)",0,20,{0x8C,0xAE,0,0,0xAC,0x8E,0,0,0xAC,0x85,0,4,0x8C,0xAF,0,0,0x11,0xE0,0,3},0,0,alLink}, + {"alUnLink (DK64)",0,28,{0x8C,0x8E,0,0,0x11,0xC0,0,4,0,0,0,0,0x8C,0x8F,0,4,0x8C,0x98,0,0,0xAF,0xF,0,4,0x8C,0x99,0,4},0,0,alUnLink}, + + {"alEvtqPostEvent",0,64,{0x27,0xBD,0xFF,0xD0,0xAF,0xBF,0,0x14,0xAF,0xA4,0,0x30,0xAF,0xA5,0,0x34,0xAF,0xA0,0,0x20,0x24,4,0,1,0xC,-1,-1,-1,0xAF,0xA6,0,0x38,0x8F,0xAE,0,0x30,0x8F,0xA7,0,0x38,0,0x40,0x28,0x25,0x8D,0xC8,0,0,0x15,0,0,5,1,0,0x20,0x25,0xC,-1,-1,-1,0,0x40,0x20,0x25},0,0,alEvtqPostEvent}, + + {"alEvtqPostEvent (DK64)",0,64,{0x27,0xBD,0xFF,0xD0,0xAF,0xBF,0,0x14,0xAF,0xA4,0,0x30,0xAF,0xA5,0,0x34,0xAF,0xA6,0,0x38,0xAF,0xA0,0,0x20,0xC,-1,-1,-1,0x24,4,0,1,0xAF,0xA2,0,0x1C,0x8F,0xAE,0,0x30,0x8D,0xCF,0,0,0xAF,0xAF,0,0x2C,0x8F,0xB8,0,0x2C,0x17,0,0,5,0,0,0,0,0xC,-1,-1,-1,0x8F,0xA4,0,0x1C},0,0,alEvtqPostEvent}, + {"alEvtqPostEvent (CBFD)",0,56,{0x27,0xBD,0xFF,0xC0,0xAF,0xBF,0,0x14,0xAF,0xA4,0,0x40,0xAF,0xA5,0,0x44,0xAF,0xA6,0,0x48,0xAF,0xA7,0,0x4C,0xAF,0xA0,0,0x30,0x8F,0xAE,0,0x4C,0x31,0xCF,0,2,0x11,0xE0,0,4,0,0,0,0,0xC,-1,-1,-1,0x24,4,0,1,0xAF,0xA2,0,0x2C},0,0,alEvtqPostEvent}, + {"alEvtqPostEvent (BT)",0,60,{0x27,0xBD,0xFF,0xD0,0xAF,0xBF,0,0x14,0xAF,0xA4,0,0x30,0xAF,0xA5,0,0x34,0xAF,0xA6,0,0x38,0xAF,0xA7,0,0x3C,0xAF,0xA0,0,0x20,0xC,-1,-1,-1,0x24,4,0,1,0xAF,0xA2,0,0x1C,0x8F,0xAE,0,0x30,0x8D,0xCF,0,0,0xAF,0xAF,0,0x2C,0x8F,0xB8,0,0x2C,0x17,0,0,5},0,0,alEvtqPostEvent}, + + {"alAudioFrame",0,52,{0x27,0xBD,0xFF,0x48,0xAF,0xB1,0,0x30,0x3C,0x11,-1,-1,0x8E,0x31,0-1,-1,0xAF,0xBF,0,0x4C,0xAF,0xB7,0,0x48,0xAF,0xB6,0,0x44,0xAF,0xB5,0,0x40,0xAF,0xB4,0,0x3C,0xAF,0xB3,0,0x38,0xAF,0xB2,0,0x34,0xAF,0xB0,0,0x2C,0xF7,0xB6,0,0x20},0,0,alAudioFrame}, + + //{"alAudioFrame (DK64)",0,64,{0x27,0xBD,0xFF,0xC0,0xAF,0xBF,0,0x1C,0xAF,0xA4,0,0x40,0xAF,0xA5,0,0x44,0xAF,0xA6,0,0x48,0xAF,0xA7,0,0x4C,0xAF,0xB1,0,0x18,0xAF,0xB0,0,0x14,0xA7,0xA0,0,0x3A,0x8F,0xAE,0,0x40,0xAF,0xAE,0,0x34,0x8F,0xAF,0,0x48,0xAF,0xAF,0,0x28,0x3C,0x18,0x80,0x75,0x8F,0x18,0xC,0x74,0x8F,0x19,0,0},0,0,alAudioFrame}, + +}; +//int 0xA4,0xA6,0,0x38 + +//char foundlist[2048]; + +int CPUHLE_Scan(usf_state_t * state) +{ + int i = 0, j = 0; + unsigned char c = 0; + long d = 0; + int entrySize = 0; + int entry = 0; + void * address = 0; + int good = 1; //, needcomma = 0; + _HLE_Entry * entries; + + numEntries = sizeof(entrys) / sizeof(_HLE_Entry); + + entries = state->cpu_hle_entries = realloc( state->cpu_hle_entries, sizeof(entrys) ); + memcpy( entries, entrys, sizeof(entrys) ); + + //for(i=0; i < numEntries; i++) + // entries[i].used = 0; + + //memset(foundlist,0,2048); + + for(i=0; i < (state->RdramSize - 64); i+=4) { + + for(entry = 0; entry < numEntries; entry++) { + + if(entries[entry].used) + continue; + + good = 1; + entrySize = entries[entry].length; + + for(j=0; j < entrySize; j++) { + address = state->N64MEM + i + j; + //address = i; + c = *(unsigned char *)(address); + d = entries[entry].bytes[j^3]; + + if((c != d) && (d!=-1)) { + good = 0; + break; + } + } + + if(good == 1 && i< (state->RdramSize-64)) { + //char buf[256]; + //if(needcomma) { + // sprintf(buf,", %s", entries[entry].name); + //} else { + // sprintf(buf,"%s", entries[entry].name); + //} + + //needcomma = 1; + //strcat(foundlist,buf); + + entries[entry].used = 1; + entries[entry].phys = i; + break; + } + } + + } + + //printf("<--------------HLE Functions Found--------------->\n%s<------------------------------------------------>\n", foundlist); + //printf("HLE Functions found: %s\n", foundlist); + + return 0; +} + +int DoCPUHLE(usf_state_t * state, unsigned long loc) +{ + int i = 0; + uintptr_t real_addr = PageVRAM2(loc); + _HLE_Entry * entries = state->cpu_hle_entries; + + for(i = 0; i < numEntries; i++) { + + if(entries[i].used && (entries[i].phys == real_addr)) { + //printf("CPU HLEing using %d at %08x (phys: %08x) \"%s\"\n", entries[i].name, loc, entries[i].phys, entries[i].name); + + if(entries[i].location(state, entries[i].phys)) { + // printf("done\n"); + return 1; + } + else + return 0; + } + + } + + return 0; +} diff --git a/Frameworks/lazyusf/lazyusf/cpu_hle.h b/Frameworks/lazyusf/lazyusf/cpu_hle.h new file mode 100644 index 000000000..a2a0d6355 --- /dev/null +++ b/Frameworks/lazyusf/lazyusf/cpu_hle.h @@ -0,0 +1,27 @@ +#ifndef _CPU_HLE_ +#define _CPU_HLE_ + +#include "usf.h" +#include "cpu.h" +#include "interpreter_ops.h" +#include "memory.h" + +typedef struct { + char *name; + int num; + int length; + long bytes[80]; + int used; + int phys; + int (*location)(usf_state_t *, int); +} _HLE_Entry; + +int CPUHLE_Scan(usf_state_t *); +int DoCPUHLE(usf_state_t *, unsigned long loc); +//////////////////////////////////////////////////////////////////// +// OS Thread Stuff +// found this stuff in daedalus + + + +#endif diff --git a/Frameworks/lazyusf/lazyusf/interpreter_cpu.c b/Frameworks/lazyusf/lazyusf/interpreter_cpu.c index 0ec966d02..65b1d82f0 100644 --- a/Frameworks/lazyusf/lazyusf/interpreter_cpu.c +++ b/Frameworks/lazyusf/lazyusf/interpreter_cpu.c @@ -28,6 +28,7 @@ #include "cpu.h" #include "usf.h" #include "memory.h" +#include "cpu_hle.h" #include "usf_internal.h" @@ -679,6 +680,29 @@ void BuildInterpreter (usf_state_t * state) { } +void RunFunction(usf_state_t * state, uint32_t address) { + uint32_t oldPC = state->PROGRAM_COUNTER, oldRA = state->GPR[31].UW[0], la = state->NextInstruction; + int callStack = 0; + + state->NextInstruction = NORMAL; + state->PROGRAM_COUNTER = address; + + while( (state->PROGRAM_COUNTER != oldRA) || callStack) { + + if(state->PROGRAM_COUNTER == address) + callStack++; + + ExecuteInterpreterOpCode(state); + + if(state->PROGRAM_COUNTER == oldRA) + callStack--; + } + + state->PROGRAM_COUNTER = oldPC; + state->GPR[31].UW[0] = oldRA; + state->NextInstruction = la; +} + void ExecuteInterpreterOpCode (usf_state_t * state) { @@ -713,8 +737,13 @@ void ExecuteInterpreterOpCode (usf_state_t * state) { state->PROGRAM_COUNTER += 4; break; case JUMP: - state->PROGRAM_COUNTER = state->JumpToLocation; - state->NextInstruction = NORMAL; + if(!DoCPUHLE(state, state->JumpToLocation)) { + state->PROGRAM_COUNTER = state->JumpToLocation; + state->NextInstruction = NORMAL; + } else { + state->PROGRAM_COUNTER = state->GPR[31].UW[0]; + state->NextInstruction = NORMAL; + } if ((int32_t)state->Timers->Timer < 0) { TimerDone(state); } if (state->CPU_Action->DoSomething) { DoSomething(state); } diff --git a/Frameworks/lazyusf/lazyusf/interpreter_cpu.h b/Frameworks/lazyusf/lazyusf/interpreter_cpu.h index 70d9301bb..53dc69534 100644 --- a/Frameworks/lazyusf/lazyusf/interpreter_cpu.h +++ b/Frameworks/lazyusf/lazyusf/interpreter_cpu.h @@ -30,7 +30,7 @@ void ExecuteInterpreterOpCode ( usf_state_t * ); void StartInterpreterCPU ( usf_state_t * ); void TestInterpreterJump ( usf_state_t *, uint32_t PC, uint32_t TargetPC, int32_t Reg1, int32_t Reg2 ); - +void RunFunction( usf_state_t *, uint32_t address ); diff --git a/Frameworks/lazyusf/lazyusf/memory.c b/Frameworks/lazyusf/lazyusf/memory.c index 625a0dd15..444e501f8 100644 --- a/Frameworks/lazyusf/lazyusf/memory.c +++ b/Frameworks/lazyusf/lazyusf/memory.c @@ -157,6 +157,10 @@ void Release_Memory ( usf_state_t * state ) { if (state->MemChunk != 0) { large_free( state->MemChunk, 0x100000 * sizeof(uintptr_t) + 0x1D000 + state->RdramSize ); state->MemChunk=0; } + if(state->cpu_hle_entries) + free(state->cpu_hle_entries); + state->cpu_hle_entries = NULL; + if(state->savestatespace) free(state->savestatespace); state->savestatespace = NULL; @@ -813,3 +817,23 @@ uint32_t r4300i_SW_VAddr ( usf_state_t * state, uint32_t VAddr, uint32_t Value ) *(uint32_t *)address = Value; return 1; } + +void memcpyn642n64(usf_state_t * state, uint32_t dest, uint32_t src, uint32_t len) +{ + uint32_t i; + uint32_t temp; + + for (i = 0; i < len; i += 4) + { + uintptr_t dstAddr = state->TLB_Map[(dest + i) >> 12]; + uintptr_t srcAddr = state->TLB_Map[(src + i) >> 12]; + + if (srcAddr) + temp = *(uint32_t*)(srcAddr + src + i); + else + temp = 0; + + if (dstAddr) + *(uint32_t*)(dstAddr + dest + i) = temp; + } +} diff --git a/Frameworks/lazyusf/lazyusf/memory.h b/Frameworks/lazyusf/lazyusf/memory.h index e785c844b..294a509aa 100644 --- a/Frameworks/lazyusf/lazyusf/memory.h +++ b/Frameworks/lazyusf/lazyusf/memory.h @@ -31,6 +31,10 @@ #define ROM_IN_MAPSPACE +#define PageRAM2(x) (state->N64MEM+(x)) +#define PageVRAM(x) (state->TLB_Map[((x)&0xFFFFFFFF)>>12]+(x)) +#define PageVRAM2(x) (uint32_t)(PageVRAM(x)-(uintptr_t)state->N64MEM) + /* Memory Control */ int Allocate_Memory ( void * ); void Release_Memory ( usf_state_t * ); @@ -56,3 +60,5 @@ int32_t r4300i_SW_NonMemory ( usf_state_t *, uint32_t PAddr, uint32_t V uint32_t r4300i_SW_VAddr ( usf_state_t *, uint32_t VAddr, uint32_t Value ); uint8_t * PageROM(usf_state_t *, uint32_t addr); + +void memcpyn642n64(usf_state_t *, uint32_t dest, uint32_t src, uint32_t len); diff --git a/Frameworks/lazyusf/lazyusf/os.c b/Frameworks/lazyusf/lazyusf/os.c new file mode 100644 index 000000000..9dc713ee7 --- /dev/null +++ b/Frameworks/lazyusf/lazyusf/os.c @@ -0,0 +1,285 @@ +#include + +#include "usf.h" +#include "usf_internal.h" + +#include "os.h" +#include "cpu_hle.h" + +#include "audio.h" +#include "interpreter_cpu.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^3))) + +#define N64DWORD(addr) (((long long)N64WORD((addr))) << 32) + N64WORD((addr)+4); + + + +int __osRestoreInt(usf_state_t * state, int n) +{ + STATUS_REGISTER |= state->GPR[0x4].UW[0]; + return 1; +} + +int __osDisableInt(usf_state_t * state, int n) +{ + state->GPR[0x2].UW[0] = STATUS_REGISTER & 1; + STATUS_REGISTER &= 0xFFFFFFFE; + return 1; +} + + +void osEnqueueThread(usf_state_t * state, uint32_t osThreadQueueAddr, uint32_t threadVAddr) +{ + + OSThread *thread = (OSThread*) PageVRAM(threadVAddr); + OSThread *oldThread = (OSThread*) PageVRAM(osThreadQueueAddr); + OSThread *curThread = (OSThread*) PageVRAM(oldThread->next); + + while((int32_t)curThread->priority >= (int32_t)thread->priority) { + oldThread = curThread; + curThread = (OSThread*) PageVRAM(curThread->next); + } + + thread->next = oldThread->next; + oldThread->next = threadVAddr; + thread->queue = osThreadQueueAddr; +} + +int __osEnqueueThread(usf_state_t * state, int n) { + osEnqueueThread(state, state->GPR[4].UW[0],state->GPR[5].UW[0]); + return 1; +} + +int osStartThread(usf_state_t * state, int n) +{ + OSMesgQueue *osThreadQueue = NULL; + uint32_t osThreadQueueAddr = 0; + uint32_t oldStatus = STATUS_REGISTER & 1; + uint32_t osActiveThreadAddr = 0; + uint32_t osActiveThread = 0; + + OSThread *thread = (OSThread*)PageVRAM(state->GPR[4].UW[0]); + + STATUS_REGISTER &= 0xFFFFFFFE; + + osThreadQueueAddr = ((*(uint32_t*)PageRAM2(n + 0x40)) & 0xFFFF) << 16; + osThreadQueueAddr += *(int16_t*)PageRAM2(n + 0x50); + + osThreadQueue = (OSMesgQueue*) PageVRAM(osThreadQueueAddr); + + if(thread->state != 8 ) { + DisplayError(state, "OMG, thread state is not OS_STATE_WAITING!\n"); + return 0; + } + + thread->state = OS_STATE_RUNNABLE; + osEnqueueThread(state,osThreadQueueAddr,state->GPR[4].UW[0]); + + osActiveThreadAddr = ((*(uint32_t*)PageRAM2(n + 0xDC)) & 0xFFFF) << 16; + osActiveThreadAddr += *(int16_t*)PageRAM2(n + 0xE0); + + osActiveThread = *(uint32_t*)PageVRAM(osActiveThreadAddr); + + if(osActiveThread==0) { + DisplayError(state,"OMG, active thread is NULL!\n"); + return 0; + } + + STATUS_REGISTER |= oldStatus; +// CheckInterrupts(); + + return 1; +} + + +int osRecvMesg(usf_state_t * state, int n) +{ + //unsigned long devAddr = state->GPR[7].UW[0]; + //unsigned long vAddr = state->GPR[0x11].UW[0]; + //unsigned long nbytes = state->GPR[0x10].UW[0]; + + //unsigned long oldStatus = STATUS_REGISTER & 1; + + RunFunction(state, n | (state->PROGRAM_COUNTER & 0xF0000000)); + + //DisplayError("%08x\n%08x\n%08x",devAddr, vAddr, nbytes); + + return 1; +} + +// doesnt even use? +int osSetIntMask(usf_state_t * state, int paddr) { +#if 0 + uint32_t globalIntMask = 0; + uint32_t mask = STATUS_REGISTER & 0xFF01; + uint32_t interrupts = 0; + uint32_t intAddress = 0, newMask = 0, workMask = 0; + + uint32_t baseAddress = 0; + + globalIntMask = ((*(uint16_t*)PageRAM2(paddr + 0x8)) & 0xFFFF) << 16; + globalIntMask += *(uint16_t*)PageRAM2(paddr + 0xc); + globalIntMask = *(uint32_t*)PageVRAM(globalIntMask); + + interrupts = (globalIntMask ^ 0xffffffff) & 0xff00; + mask |= interrupts; + newMask = MI_INTR_MASK_REG; + + if(!newMask) + newMask = ((globalIntMask >> 16) ^ 0xFFFFFFFF) & 0x3F; + + mask |= (newMask << 16); + + baseAddress = ((*(uint16_t*)PageRAM2(paddr + 0x5C)) & 0xFFFF) << 16; + baseAddress += *(int16_t*)PageRAM2(paddr + 0x64); + baseAddress += ((state->GPR[4].UW[0] & 0x3F0000) & globalIntMask) >> 15;; + + MI_INTR_MASK_REG = *(uint16_t*)PageVRAM(baseAddress); + + state->STATUS_REGISTER = ((state->GPR[4].UW[0] & 0xff01) & (globalIntMask & 0xff00)) | (STATUS_REGISTER & 0xFFFF00FF); + +#endif + return 1; +} + + +int osVirtualToPhysical(usf_state_t * state, int paddr) { + uintptr_t address = 0; + uintptr_t vaddr = state->GPR[4].UW[0]; + + address = (state->TLB_Map[vaddr >> 12] + vaddr) - (uintptr_t)state->N64MEM; + + if(address < 0x800000) { + state->GPR[2].UW[0] = (uint32_t)address; + } else + state->GPR[2].UW[0] = 0xFFFFFFFF; + + return 1; +} + +int osAiSetNextBuffer(usf_state_t * state, int paddr) { + uint32_t var = 0, var2 = 0; + var = ((*(short*)PageRAM2(paddr + 0x4)) & 0xFFFF) << 16; + var += *(short*)PageRAM2(paddr + 0x8); + + var2 = N64WORD(var); + if(AI_CONTROL_REG & 0x80000000) + state->GPR[2].UW[0] = -1; + + AI_DRAM_ADDR_REG = state->GPR[4].UW[0]; + AI_LEN_REG = state->GPR[5].UW[0]&0x3FFF; + AiLenChanged(state); + state->GPR[2].UW[0] = 0; + return 1; +} + +int saveThreadContext(usf_state_t * state, int paddr) { +#if 0 + uint32_t OSThreadContextAddr = 0; + + OSThreadContextAddr = ((*(short*)PageRAM2(paddr)) & 0xFFFF) << 16; + OSThreadContextAddr += *(short*)PageRAM2(paddr + 0x4); + + OSThreadContextAddr = N64WORD(OSThreadContextAddr); + + if((PageVRAM2(OSThreadContextAddr) & 0xffff) > 0xFF00) { + DisplayError(state,"OMG! Too high!"); + return 0; + } +#endif + return 0; +} + +int loadThreadContext(usf_state_t * state, int paddr) { +#if 0 + uint32_t i = 0, OSThreadContextAddr = 0, T9 = 0, osOSThread = 0, Addr2 = 0, GlobalBitMask = 0, Tmp = 0; + uint32_t K0 = 0, K1 = 0, T0 = 0, R1 = 0, RCP = 0, intrList = 0; + OSThread t; + OSThreadContextAddr = ((*(short*)PageRAM2(paddr)) & 0xFFFF) << 16; + OSThreadContextAddr += *(short*)PageRAM2(paddr + 0x8); + + Addr2 = ((*(short*)PageRAM2(paddr + 0xC)) & 0xFFFF) << 16; + Addr2 += *(short*)PageRAM2(paddr + 0x10); + + GlobalBitMask = ((*(short*)PageRAM2(paddr + 0x20)) & 0xFFFF) << 16; + GlobalBitMask += *(short*)PageRAM2(paddr + 0x28); + GlobalBitMask = N64WORD(GlobalBitMask); + + intrList = ((*(short*)PageRAM2(paddr + 0x14C + 0x0)) & 0xFFFF) << 16; + intrList += *(short*)PageRAM2(paddr + 0x150 + 0x0); + + return 0; + + if((PageVRAM2(OSThreadContextAddr) & 0xffff) > 0xFE80) { + DisplayError(state, "OMG this number is too high!!!!\n"); + } + + osOSThread = N64WORD(OSThreadContextAddr); + T9 = N64WORD(osOSThread); + + N64WORD(OSThreadContextAddr) = T9; + N64WORD(Addr2) = osOSThread; + + N64WORD(osOSThread + 0x10) = OS_STATE_RUNNING; //T0 is globalbitmask + + K1 = N64WORD(osOSThread + 0x118); //osOSThread.context.k0 + + STATUS_REGISTER = (K1 & 0xFFFF00FF) | (GlobalBitMask & 0xFF00); + + for(i = 1; i <= 0x19; i++) { + state->GPR[i].DW = N64DWORD(osOSThread + 0x18 + (i * 8)); + } + + for(i = 0x1C; i <= 0x1F; i++) { + state->GPR[i].DW = N64DWORD(osOSThread + 0x8 + (i * 8)); + } + + state->LO.DW = N64DWORD(osOSThread + 0x108); + state->HI.DW = N64DWORD(osOSThread + 0x110); + + EPC_REGISTER = (uint32_t) N64WORD(osOSThread + 0x11C); + + state->FPCR[31] = (uint32_t) N64WORD(osOSThread + 0x12C); + + if(N64WORD(osOSThread + 0x18)) { + for(i = 0; i <= 30; i+=2) { + (*(uint64_t *)state->FPRDoubleLocation[i]) = N64DWORD(osOSThread + 0x130 + (i * 4)); + } + } else { + } + + state->GPR[0x1A].UW[0] = (uint32_t) osOSThread; + + RCP = N64WORD(osOSThread + 0x128); + + K0 = (intrList + ((RCP & (GlobalBitMask >> 16)) << 1)); + K1 = 0; + + r4300i_LH_VAddr(state, K0, &K1); + + // cheap hack? + //K1 = 0xAAA; + + SW_Register(0x0430000C, K1); + + NextInstruction = JUMP; + + if ((STATUS_REGISTER & STATUS_ERL) != 0) { + JumpToLocation = ERROREPC_REGISTER; + STATUS_REGISTER &= ~STATUS_ERL; + } else { + JumpToLocation = EPC_REGISTER; + STATUS_REGISTER &= ~STATUS_EXL; + } + + LLBit = 0; + CheckInterrupts(); +#endif + return 0; +} diff --git a/Frameworks/lazyusf/lazyusf/os.h b/Frameworks/lazyusf/lazyusf/os.h new file mode 100644 index 000000000..8ff0a697c --- /dev/null +++ b/Frameworks/lazyusf/lazyusf/os.h @@ -0,0 +1,89 @@ +#ifndef _CPU_HLE_OS_ +#define _CPU_HLE_OS_ + +#include "cpu_hle.h" + + +#pragma pack(1) + + +#define OS_STATE_STOPPED 1 +#define OS_STATE_RUNNABLE 2 +#define OS_STATE_RUNNING 4 +#define OS_STATE_WAITING 8 + +typedef uint32_t OSPri; +typedef uint32_t OSId; +typedef + union + { + struct + { + float f_odd; + float f_even; + } f; + double d; + } +__OSfp; + +typedef struct { + uint64_t at, v0, v1, a0, a1, a2, a3; + uint64_t t0, t1, t2, t3, t4, t5, t6, t7; + uint64_t s0, s1, s2, s3, s4, s5, s6, s7; + uint64_t t8, t9, gp, sp, s8, ra; + uint64_t lo, hi; + uint32_t sr, pc, cause, badvaddr, rcp; + uint32_t fpcsr; + __OSfp fp0, fp2, fp4, fp6, fp8, fp10, fp12, fp14; + __OSfp fp16, fp18, fp20, fp22, fp24, fp26, fp28, fp30; +} __OSThreadContext; + +typedef struct OSThread_s +{ + uint32_t next; // run/mesg queue link + OSPri priority; // run/mesg queue priority + uint32_t queue; // queue thread is on + uint32_t tlnext; // all threads queue link +#if 0 + uint16_t state; // OS_STATE_* + uint16_t flags; // flags for rmon +#endif + //swap these because of byteswapping + uint16_t flags; // flags for rmon + uint16_t state; // OS_STATE_* + OSId id; // id for debugging + int fp; // thread has used fp unit + __OSThreadContext context; // register/interrupt mask +} OSThread; + +typedef void * OSMesg; + +// +// Structure for message queue +// +typedef struct OSMesgQueue_s +{ + OSThread *mtqueue; // Queue to store threads blocked + // on empty mailboxes (receive) + OSThread *fullqueue; // Queue to store threads blocked + // on full mailboxes (send) + int32_t validCount; // Contains number of valid message + int32_t first; // Points to first valid message + int32_t msgCount; // Contains total # of messages + OSMesg *msg; // Points to message buffer array +} OSMesgQueue; + + +int __osRestoreInt(usf_state_t *, int n); +int __osDisableInt(usf_state_t *, int n); +int __osEnqueueThread(usf_state_t *, int n) ; + +int osStartThread(usf_state_t *, int n); +int osRecvMesg(usf_state_t *, int n); +int osSetIntMask(usf_state_t *, int paddr) ; +int osVirtualToPhysical(usf_state_t *, int paddr); +int osAiSetNextBuffer(usf_state_t *, int paddr); + +int saveThreadContext(usf_state_t *, int paddr); +int loadThreadContext(usf_state_t *, int paddr); +#endif diff --git a/Frameworks/lazyusf/lazyusf/usf_internal.h b/Frameworks/lazyusf/lazyusf/usf_internal.h index 2b8cb6742..0281f400f 100644 --- a/Frameworks/lazyusf/lazyusf/usf_internal.h +++ b/Frameworks/lazyusf/lazyusf/usf_internal.h @@ -3,6 +3,7 @@ #include "cpu.h" #include "rsp_hle/hle.h" +#include "cpu_hle.h" struct usf_state_helper { @@ -29,37 +30,37 @@ struct usf_state // which is indicated for allocation accounts for this // with two pages of padding. - short VR[32][8]; - short VACC[3][8]; + int16_t VR[32][8]; + int16_t VACC[3][8]; // RSP virtual registers, also needs alignment - int SR[32]; + int32_t SR[32]; // rsp/rsp.c, not necessarily in need of alignment RCPREG* CR[16]; // rsp/vu/cf.h, all need alignment - short ne[8]; /* $vco: high byte "NOTEQUAL" */ - short co[8]; /* $vco: low byte "carry/borrow in/out" */ - short clip[8]; /* $vcc: high byte (clip tests: VCL, VCH, VCR) */ - short comp[8]; /* $vcc: low byte (VEQ, VNE, VLT, VGE, VCL, VCH, VCR) */ - short vce[8]; /* $vce: vector compare extension register */ + int16_t ne[8]; /* $vco: high byte "NOTEQUAL" */ + int16_t co[8]; /* $vco: low byte "carry/borrow in/out" */ + int16_t clip[8]; /* $vcc: high byte (clip tests: VCL, VCH, VCR) */ + int16_t comp[8]; /* $vcc: low byte (VEQ, VNE, VLT, VGE, VCL, VCH, VCR) */ + int16_t vce[8]; /* $vce: vector compare extension register */ // All further members of the structure need not be aligned // rsp/vu/divrom.h - int DivIn; /* buffered numerator of division read from vector file */ - int DivOut; /* global division result set by VRCP/VRCPL/VRSQ/VRSQH */ + int32_t DivIn; /* buffered numerator of division read from vector file */ + int32_t DivOut; /* global division result set by VRCP/VRCPL/VRSQ/VRSQH */ #if (0) - int MovIn; /* We do not emulate this register (obsolete, for VMOV). */ + int32_t MovIn; /* We do not emulate this register (obsolete, for VMOV). */ #endif - int DPH; + int32_t DPH; // rsp/rsp.h - int stage; // unused since EMULATE_STATIC_PC is defined by default in rsp/config.h - int temp_PC; - short MFC0_count[32]; + int32_t stage; // unused since EMULATE_STATIC_PC is defined by default in rsp/config.h + int32_t temp_PC; + int16_t MFC0_count[32]; // rsp_hle struct hle_t hle; @@ -134,6 +135,10 @@ struct usf_state // tlb.c FASTTLB FastTlb[64]; TLB tlb[32]; + + uint32_t OLD_VI_V_SYNC_REG/* = 0*/, VI_INTR_TIME/* = 500000*/; + + _HLE_Entry * cpu_hle_entries; }; #define USF_STATE_HELPER ((usf_state_helper_t *)(state))