Updated lazyusf
parent
55d6e5050c
commit
339ba527c5
|
@ -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 = "<group>"; };
|
||||
8319EF181A219846009DD5C4 /* cpu_hle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cpu_hle.h; sourceTree = "<group>"; };
|
||||
8319EF1B1A2198B9009DD5C4 /* os.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = os.c; sourceTree = "<group>"; };
|
||||
8319EF1C1A2198B9009DD5C4 /* os.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = os.h; sourceTree = "<group>"; };
|
||||
8319EF1F1A219BE7009DD5C4 /* audiolib.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = audiolib.c; sourceTree = "<group>"; };
|
||||
8319EF201A219BE7009DD5C4 /* audiolib.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = audiolib.h; sourceTree = "<group>"; };
|
||||
8378415418C6E56B002C4FE5 /* alist.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = alist.c; sourceTree = "<group>"; };
|
||||
8378415518C6E56B002C4FE5 /* alist.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = alist.h; sourceTree = "<group>"; };
|
||||
8378415618C6E56B002C4FE5 /* alist_audio.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = alist_audio.c; sourceTree = "<group>"; };
|
||||
|
@ -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 */,
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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
|
|
@ -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:
|
||||
|
|
|
@ -0,0 +1,148 @@
|
|||
#include <string.h>
|
||||
|
||||
#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;
|
||||
}
|
|
@ -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
|
|
@ -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); }
|
||||
|
||||
|
|
|
@ -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 );
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -0,0 +1,285 @@
|
|||
#include <string.h>
|
||||
|
||||
#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;
|
||||
}
|
|
@ -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
|
|
@ -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))
|
||||
|
|
Loading…
Reference in New Issue