Browse Source

Import original LazyUSF into code base, for debugging and comparison.

master
parent
commit
8859e9a83c
100 changed files with 12315 additions and 833 deletions
  1. +431
    -833
      Frameworks/lazyusf/lazyusf.xcodeproj/project.pbxproj
  2. +89
    -0
      Frameworks/lazyusf/lazyusf/audio.c
  3. +12
    -0
      Frameworks/lazyusf/lazyusf/audio.h
  4. +271
    -0
      Frameworks/lazyusf/lazyusf/audiolib.c
  5. +60
    -0
      Frameworks/lazyusf/lazyusf/audiolib.h
  6. +63
    -0
      Frameworks/lazyusf/lazyusf/config.h
  7. +604
    -0
      Frameworks/lazyusf/lazyusf/cpu.c
  8. +95
    -0
      Frameworks/lazyusf/lazyusf/cpu.h
  9. +161
    -0
      Frameworks/lazyusf/lazyusf/cpu_hle.c
  10. +27
    -0
      Frameworks/lazyusf/lazyusf/cpu_hle.h
  11. +180
    -0
      Frameworks/lazyusf/lazyusf/dma.c
  12. +34
    -0
      Frameworks/lazyusf/lazyusf/dma.h
  13. +158
    -0
      Frameworks/lazyusf/lazyusf/exception.c
  14. +75
    -0
      Frameworks/lazyusf/lazyusf/exception.h
  15. +799
    -0
      Frameworks/lazyusf/lazyusf/interpreter_cpu.c
  16. +37
    -0
      Frameworks/lazyusf/lazyusf/interpreter_cpu.h
  17. +1342
    -0
      Frameworks/lazyusf/lazyusf/interpreter_ops.c
  18. +206
    -0
      Frameworks/lazyusf/lazyusf/interpreter_ops.h
  19. +37
    -0
      Frameworks/lazyusf/lazyusf/main.c
  20. +6
    -0
      Frameworks/lazyusf/lazyusf/main.h
  21. +839
    -0
      Frameworks/lazyusf/lazyusf/memory.c
  22. +64
    -0
      Frameworks/lazyusf/lazyusf/memory.h
  23. +274
    -0
      Frameworks/lazyusf/lazyusf/opcode.h
  24. +285
    -0
      Frameworks/lazyusf/lazyusf/os.c
  25. +89
    -0
      Frameworks/lazyusf/lazyusf/os.h
  26. +99
    -0
      Frameworks/lazyusf/lazyusf/pif.c
  27. +29
    -0
      Frameworks/lazyusf/lazyusf/pif.h
  28. +145
    -0
      Frameworks/lazyusf/lazyusf/registers.c
  29. +378
    -0
      Frameworks/lazyusf/lazyusf/registers.h
  30. +270
    -0
      Frameworks/lazyusf/lazyusf/resampler.c
  31. +40
    -0
      Frameworks/lazyusf/lazyusf/resampler.h
  32. +11
    -0
      Frameworks/lazyusf/lazyusf/rsp.h
  33. +0
    -0
      Frameworks/lazyusf/lazyusf/rsp/bench.c
  34. +0
    -0
      Frameworks/lazyusf/lazyusf/rsp/config.h
  35. +495
    -0
      Frameworks/lazyusf/lazyusf/rsp/execute.h
  36. +0
    -0
      Frameworks/lazyusf/lazyusf/rsp/matrix.h
  37. +109
    -0
      Frameworks/lazyusf/lazyusf/rsp/rsp.c
  38. +118
    -0
      Frameworks/lazyusf/lazyusf/rsp/rsp.h
  39. +1558
    -0
      Frameworks/lazyusf/lazyusf/rsp/su.h
  40. +0
    -0
      Frameworks/lazyusf/lazyusf/rsp/vu/cf.h
  41. +403
    -0
      Frameworks/lazyusf/lazyusf/rsp/vu/clamp.h
  42. +0
    -0
      Frameworks/lazyusf/lazyusf/rsp/vu/divrom.h
  43. +0
    -0
      Frameworks/lazyusf/lazyusf/rsp/vu/shuffle.h
  44. +0
    -0
      Frameworks/lazyusf/lazyusf/rsp/vu/vabs.h
  45. +0
    -0
      Frameworks/lazyusf/lazyusf/rsp/vu/vadd.h
  46. +0
    -0
      Frameworks/lazyusf/lazyusf/rsp/vu/vaddc.h
  47. +0
    -0
      Frameworks/lazyusf/lazyusf/rsp/vu/vand.h
  48. +0
    -0
      Frameworks/lazyusf/lazyusf/rsp/vu/vch.h
  49. +0
    -0
      Frameworks/lazyusf/lazyusf/rsp/vu/vcl.h
  50. +0
    -0
      Frameworks/lazyusf/lazyusf/rsp/vu/vcr.h
  51. +0
    -0
      Frameworks/lazyusf/lazyusf/rsp/vu/veq.h
  52. +0
    -0
      Frameworks/lazyusf/lazyusf/rsp/vu/vge.h
  53. +0
    -0
      Frameworks/lazyusf/lazyusf/rsp/vu/vlt.h
  54. +0
    -0
      Frameworks/lazyusf/lazyusf/rsp/vu/vmacf.h
  55. +0
    -0
      Frameworks/lazyusf/lazyusf/rsp/vu/vmacq.h
  56. +0
    -0
      Frameworks/lazyusf/lazyusf/rsp/vu/vmacu.h
  57. +0
    -0
      Frameworks/lazyusf/lazyusf/rsp/vu/vmadh.h
  58. +0
    -0
      Frameworks/lazyusf/lazyusf/rsp/vu/vmadl.h
  59. +0
    -0
      Frameworks/lazyusf/lazyusf/rsp/vu/vmadm.h
  60. +0
    -0
      Frameworks/lazyusf/lazyusf/rsp/vu/vmadn.h
  61. +0
    -0
      Frameworks/lazyusf/lazyusf/rsp/vu/vmov.h
  62. +0
    -0
      Frameworks/lazyusf/lazyusf/rsp/vu/vmrg.h
  63. +0
    -0
      Frameworks/lazyusf/lazyusf/rsp/vu/vmudh.h
  64. +0
    -0
      Frameworks/lazyusf/lazyusf/rsp/vu/vmudl.h
  65. +0
    -0
      Frameworks/lazyusf/lazyusf/rsp/vu/vmudm.h
  66. +0
    -0
      Frameworks/lazyusf/lazyusf/rsp/vu/vmudn.h
  67. +0
    -0
      Frameworks/lazyusf/lazyusf/rsp/vu/vmulf.h
  68. +0
    -0
      Frameworks/lazyusf/lazyusf/rsp/vu/vmulu.h
  69. +0
    -0
      Frameworks/lazyusf/lazyusf/rsp/vu/vnand.h
  70. +0
    -0
      Frameworks/lazyusf/lazyusf/rsp/vu/vne.h
  71. +0
    -0
      Frameworks/lazyusf/lazyusf/rsp/vu/vnop.h
  72. +0
    -0
      Frameworks/lazyusf/lazyusf/rsp/vu/vnor.h
  73. +0
    -0
      Frameworks/lazyusf/lazyusf/rsp/vu/vnxor.h
  74. +0
    -0
      Frameworks/lazyusf/lazyusf/rsp/vu/vor.h
  75. +0
    -0
      Frameworks/lazyusf/lazyusf/rsp/vu/vrcp.h
  76. +0
    -0
      Frameworks/lazyusf/lazyusf/rsp/vu/vrcph.h
  77. +0
    -0
      Frameworks/lazyusf/lazyusf/rsp/vu/vrcpl.h
  78. +0
    -0
      Frameworks/lazyusf/lazyusf/rsp/vu/vrsq.h
  79. +0
    -0
      Frameworks/lazyusf/lazyusf/rsp/vu/vrsqh.h
  80. +0
    -0
      Frameworks/lazyusf/lazyusf/rsp/vu/vrsql.h
  81. +90
    -0
      Frameworks/lazyusf/lazyusf/rsp/vu/vsaw.h
  82. +0
    -0
      Frameworks/lazyusf/lazyusf/rsp/vu/vsub.h
  83. +0
    -0
      Frameworks/lazyusf/lazyusf/rsp/vu/vsubc.h
  84. +0
    -0
      Frameworks/lazyusf/lazyusf/rsp/vu/vu.h
  85. +0
    -0
      Frameworks/lazyusf/lazyusf/rsp/vu/vxor.h
  86. +46
    -0
      Frameworks/lazyusf/lazyusf/rsp_hle/msvc-compat/our-stdbool.h
  87. +195
    -0
      Frameworks/lazyusf/lazyusf/tlb.c
  88. +105
    -0
      Frameworks/lazyusf/lazyusf/tlb.h
  89. +72
    -0
      Frameworks/lazyusf/lazyusf/types.h
  90. +339
    -0
      Frameworks/lazyusf/lazyusf/usf.c
  91. +81
    -0
      Frameworks/lazyusf/lazyusf/usf.h
  92. +164
    -0
      Frameworks/lazyusf/lazyusf/usf_internal.h
  93. +1250
    -0
      Frameworks/lazyusf2/lazyusf2.xcodeproj/project.pbxproj
  94. +80
    -0
      Frameworks/lazyusf2/lazyusf2.xcodeproj/xcshareddata/xcschemes/lazyusf2.xcscheme
  95. +0
    -0
      Frameworks/lazyusf2/lazyusf2/ai/ai_controller.c
  96. +0
    -0
      Frameworks/lazyusf2/lazyusf2/ai/ai_controller.h
  97. +0
    -0
      Frameworks/lazyusf2/lazyusf2/api/api_export.ver
  98. +0
    -0
      Frameworks/lazyusf2/lazyusf2/api/callbacks.c
  99. +0
    -0
      Frameworks/lazyusf2/lazyusf2/api/callbacks.h
  100. +0
    -0
      Frameworks/lazyusf2/lazyusf2/api/m64p_common.h

+ 431
- 833
Frameworks/lazyusf/lazyusf.xcodeproj/project.pbxproj
File diff suppressed because it is too large
View File


+ 89
- 0
Frameworks/lazyusf/lazyusf/audio.c View File

@@ -0,0 +1,89 @@
#include "usf.h"
#include "memory.h"
#include "audio.h"
#include <stdlib.h>
#include <stdio.h>
#include "usf_internal.h"
void AddBuffer(usf_state_t *state, unsigned char *buf, unsigned int length) {
unsigned int i, do_max;
int16_t * sample_buffer = state->sample_buffer;
if(!state->cpu_running)
return;
do_max = length >> 2;
if ( do_max > state->sample_buffer_count )
do_max = (unsigned int) state->sample_buffer_count;
if ( sample_buffer )
for (i = 0; i < do_max; ++i)
{
*sample_buffer++ = ((int16_t*)buf)[1];
*sample_buffer++ = ((int16_t*)buf)[0];
buf += 4;
}
else
buf += 4 * do_max;
state->sample_buffer_count -= do_max;
state->sample_buffer = sample_buffer;
length -= do_max << 2;
if ( length )
{
sample_buffer = state->samplebuf;
do_max = length >> 2;
for (i = 0; i < do_max; ++i)
{
*sample_buffer++ = ((int16_t*)buf)[1];
*sample_buffer++ = ((int16_t*)buf)[0];
buf += 4;
}
state->samples_in_buffer = do_max;
state->cpu_running = 0;
}
}
void AiLenChanged(usf_state_t * state) {
int32_t length = 0;
uint32_t address = (AI_DRAM_ADDR_REG & 0x00FFFFF8);
length = AI_LEN_REG & 0x3FFF8;
#ifdef DEBUG_INFO
fprintf(state->debug_log, "Audio DMA push: %d %d\n", AI_DRAM_ADDR_REG, length);
#endif
AddBuffer(state, state->RDRAM+address, length);
if(length && !(AI_STATUS_REG&0x80000000)) {
const float VSyncTiming = 789000.0f;
double BytesPerSecond = 48681812.0 / (AI_DACRATE_REG + 1) * 4;
double CountsPerSecond = (double)((((double)VSyncTiming) * (double)60.0)) * 2.0;
double CountsPerByte = (double)CountsPerSecond / (double)BytesPerSecond;
unsigned int IntScheduled = (unsigned int)((double)AI_LEN_REG * CountsPerByte);
ChangeTimer(state,AiTimer,IntScheduled);
}
if(state->enableFIFOfull) {
if(AI_STATUS_REG&0x40000000)
AI_STATUS_REG|=0x80000000;
}
AI_STATUS_REG|=0x40000000;
}
unsigned int AiReadLength(usf_state_t * state) {
AI_LEN_REG = 0;
return AI_LEN_REG;
}
void AiDacrateChanged(usf_state_t * state, unsigned int value) {
AI_DACRATE_REG = value;
state->SampleRate = 48681812 / (AI_DACRATE_REG + 1);
}

+ 12
- 0
Frameworks/lazyusf/lazyusf/audio.h View File

@@ -0,0 +1,12 @@
#ifndef _AUDIO_H_
#define _AUDIO_H_
#include "usf.h"
#include "cpu.h"
#include "memory.h"
uint32_t AiReadLength(usf_state_t *);
void AiLenChanged(usf_state_t *);
void AiDacrateChanged(usf_state_t *, uint32_t value);
#endif

+ 271
- 0
Frameworks/lazyusf/lazyusf/audiolib.c View File

@@ -0,0 +1,271 @@
#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;
}

+ 60
- 0
Frameworks/lazyusf/lazyusf/audiolib.h View File

@@ -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

+ 63
- 0
Frameworks/lazyusf/lazyusf/config.h View File

@@ -0,0 +1,63 @@
/* config.h. Generated from config.h.in by configure. */
/* config.h.in. Generated from configure.in by autoheader. */

/* Define to 1 if you have the <dlfcn.h> header file. */
#define HAVE_DLFCN_H 1

/* Define to 1 if you have the <inttypes.h> header file. */
#define HAVE_INTTYPES_H 1

/* Define to 1 if you have the <memory.h> header file. */
#define HAVE_MEMORY_H 1

/* Define to 1 if you have the <stdint.h> header file. */
#define HAVE_STDINT_H 1

/* Define to 1 if you have the <stdlib.h> header file. */
#define HAVE_STDLIB_H 1

/* Define to 1 if you have the <strings.h> header file. */
#define HAVE_STRINGS_H 1

/* Define to 1 if you have the <string.h> header file. */
#define HAVE_STRING_H 1

/* Define to 1 if you have the <sys/stat.h> header file. */
#define HAVE_SYS_STAT_H 1

/* Define to 1 if you have the <sys/types.h> header file. */
#define HAVE_SYS_TYPES_H 1

/* Define to 1 if you have the <unistd.h> header file. */
#define HAVE_UNISTD_H 1

/* Define to the sub-directory in which libtool stores uninstalled libraries.
*/
#define LT_OBJDIR ".libs/"

/* Name of package */
#define PACKAGE "lazyusf"

/* Define to the address where bug reports for this package should be sent. */
#define PACKAGE_BUGREPORT ""

/* Define to the full name of this package. */
#define PACKAGE_NAME "lazyusf"

/* Define to the full name and version of this package. */
#define PACKAGE_STRING "lazyusf 1.0.0"

/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "lazyusf"

/* Define to the version of this package. */
#define PACKAGE_VERSION "1.0.0"

/* Define to 1 if you have the ANSI C header files. */
#define STDC_HEADERS 1

/* Version number of package */
#define VERSION "1.0.0"

/* Define to 1 if the X Window System is missing or not being used. */
/* #undef X_DISPLAY_MISSING */

+ 604
- 0
Frameworks/lazyusf/lazyusf/cpu.c View File

@@ -0,0 +1,604 @@
/*
* Project 64 - A Nintendo 64 emulator.
*
* (c) Copyright 2001 zilmar (zilmar@emulation64.com) and
* Jabo (jabo@emulation64.com).
*
* pj64 homepage: www.pj64.net
*
* Permission to use, copy, modify and distribute Project64 in both binary and
* source form, for non-commercial purposes, is hereby granted without fee,
* providing that this license information and copyright notice appear with
* all copies and any derived work.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event shall the authors be held liable for any damages
* arising from the use of this software.
*
* Project64 is freeware for PERSONAL USE only. Commercial users should
* seek permission of the copyright holders first. Commercial use includes
* charging money for Project64 or software derived from Project64.
*
* The copyright holders request that bug fixes and improvements to the code
* should be forwarded to them so if they want them.
*
*/
#include <stdint.h>
#include <string.h>
#include "main.h"
#include "cpu.h"
#include "usf.h"
#include "audio.h"
#include "registers.h"
#include "rsp.h"
#include "cpu_hle.h"
#include "usf_internal.h"
#include <stdlib.h>
void ChangeCompareTimer(usf_state_t * state) {
uint32_t NextCompare = COMPARE_REGISTER - COUNT_REGISTER;
if ((NextCompare & 0x80000000) != 0) { NextCompare = 0x7FFFFFFF; }
if (NextCompare == 0) { NextCompare = 0x1; }
ChangeTimer(state,CompareTimer,NextCompare);
}
void ChangeTimer(usf_state_t * state, int32_t Type, int32_t Value) {
if (Value == 0) {
state->Timers->NextTimer[Type] = 0;
state->Timers->Active[Type] = 0;
return;
}
state->Timers->NextTimer[Type] = Value - state->Timers->Timer;
state->Timers->Active[Type] = 1;
CheckTimer(state);
}
void CheckTimer (usf_state_t * state) {
int32_t count;
for (count = 0; count < MaxTimers; count++) {
if (!state->Timers->Active[count]) { continue; }
if (!(count == CompareTimer && state->Timers->NextTimer[count] == 0x7FFFFFFF)) {
state->Timers->NextTimer[count] += state->Timers->Timer;
}
}
state->Timers->CurrentTimerType = -1;
state->Timers->Timer = 0x7FFFFFFF;
for (count = 0; count < MaxTimers; count++) {
if (!state->Timers->Active[count]) { continue; }
if (state->Timers->NextTimer[count] >= state->Timers->Timer) { continue; }
state->Timers->Timer = state->Timers->NextTimer[count];
state->Timers->CurrentTimerType = count;
}
if (state->Timers->CurrentTimerType == -1) {
DisplayError(state, "No active timers ???\nEmulation Stopped");
StopEmulation(state);
}
for (count = 0; count < MaxTimers; count++) {
if (!state->Timers->Active[count]) { continue; }
if (!(count == CompareTimer && state->Timers->NextTimer[count] == 0x7FFFFFFF)) {
state->Timers->NextTimer[count] -= state->Timers->Timer;
}
}
if (state->Timers->NextTimer[CompareTimer] == 0x7FFFFFFF) {
uint32_t NextCompare = COMPARE_REGISTER - COUNT_REGISTER;
if ((NextCompare & 0x80000000) == 0 && NextCompare != 0x7FFFFFFF) {
ChangeCompareTimer(state);
}
}
}
void CloseCpu (usf_state_t * state) {
uint32_t count = 0;
if(!state->MemChunk) return;
if (!state->cpu_running) { return; }
state->cpu_running = 0;
for (count = 0; count < 3; count ++ ) {
state->CPU_Action->CloseCPU = 1;
state->CPU_Action->DoSomething = 1;
}
state->CPURunning = 0;
}
int32_t DelaySlotEffectsCompare (usf_state_t * state, uint32_t PC, uint32_t Reg1, uint32_t Reg2) {
OPCODE Command;
if (!r4300i_LW_VAddr(state, PC + 4, (uint32_t*)&Command.u.Hex)) {
return 1;
}
switch (Command.u.b.op) {
case R4300i_SPECIAL:
switch (Command.u.e.funct) {
case R4300i_SPECIAL_SLL:
case R4300i_SPECIAL_SRL:
case R4300i_SPECIAL_SRA:
case R4300i_SPECIAL_SLLV:
case R4300i_SPECIAL_SRLV:
case R4300i_SPECIAL_SRAV:
case R4300i_SPECIAL_MFHI:
case R4300i_SPECIAL_MTHI:
case R4300i_SPECIAL_MFLO:
case R4300i_SPECIAL_MTLO:
case R4300i_SPECIAL_DSLLV:
case R4300i_SPECIAL_DSRLV:
case R4300i_SPECIAL_DSRAV:
case R4300i_SPECIAL_ADD:
case R4300i_SPECIAL_ADDU:
case R4300i_SPECIAL_SUB:
case R4300i_SPECIAL_SUBU:
case R4300i_SPECIAL_AND:
case R4300i_SPECIAL_OR:
case R4300i_SPECIAL_XOR:
case R4300i_SPECIAL_NOR:
case R4300i_SPECIAL_SLT:
case R4300i_SPECIAL_SLTU:
case R4300i_SPECIAL_DADD:
case R4300i_SPECIAL_DADDU:
case R4300i_SPECIAL_DSUB:
case R4300i_SPECIAL_DSUBU:
case R4300i_SPECIAL_DSLL:
case R4300i_SPECIAL_DSRL:
case R4300i_SPECIAL_DSRA:
case R4300i_SPECIAL_DSLL32:
case R4300i_SPECIAL_DSRL32:
case R4300i_SPECIAL_DSRA32:
if (Command.u.e.rd == 0) { return 0; }
if (Command.u.e.rd == Reg1) { return 1; }
if (Command.u.e.rd == Reg2) { return 1; }
break;
case R4300i_SPECIAL_MULT:
case R4300i_SPECIAL_MULTU:
case R4300i_SPECIAL_DIV:
case R4300i_SPECIAL_DIVU:
case R4300i_SPECIAL_DMULT:
case R4300i_SPECIAL_DMULTU:
case R4300i_SPECIAL_DDIV:
case R4300i_SPECIAL_DDIVU:
break;
default:
return 1;
}
break;
case R4300i_CP0:
switch (Command.u.b.rs) {
case R4300i_COP0_MT: break;
case R4300i_COP0_MF:
if (Command.u.b.rt == 0) { return 0; }
if (Command.u.b.rt == Reg1) { return 1; }
if (Command.u.b.rt == Reg2) { return 1; }
break;
default:
if ( (Command.u.b.rs & 0x10 ) != 0 ) {
switch( state->Opcode.u.e.funct ) {
case R4300i_COP0_CO_TLBR: break;
case R4300i_COP0_CO_TLBWI: break;
case R4300i_COP0_CO_TLBWR: break;
case R4300i_COP0_CO_TLBP: break;
default:
return 1;
}
return 1;
}
}
break;
case R4300i_CP1:
switch (Command.u.f.fmt) {
case R4300i_COP1_MF:
if (Command.u.b.rt == 0) { return 0; }
if (Command.u.b.rt == Reg1) { return 1; }
if (Command.u.b.rt == Reg2) { return 1; }
break;
case R4300i_COP1_CF: break;
case R4300i_COP1_MT: break;
case R4300i_COP1_CT: break;
case R4300i_COP1_S: break;
case R4300i_COP1_D: break;
case R4300i_COP1_W: break;
case R4300i_COP1_L: break;
return 1;
}
break;
case R4300i_ANDI:
case R4300i_ORI:
case R4300i_XORI:
case R4300i_LUI:
case R4300i_ADDI:
case R4300i_ADDIU:
case R4300i_SLTI:
case R4300i_SLTIU:
case R4300i_DADDI:
case R4300i_DADDIU:
case R4300i_LB:
case R4300i_LH:
case R4300i_LW:
case R4300i_LWL:
case R4300i_LWR:
case R4300i_LDL:
case R4300i_LDR:
case R4300i_LBU:
case R4300i_LHU:
case R4300i_LD:
case R4300i_LWC1:
case R4300i_LDC1:
if (Command.u.b.rt == 0) { return 0; }
if (Command.u.b.rt == Reg1) { return 1; }
if (Command.u.b.rt == Reg2) { return 1; }
break;
case R4300i_CACHE: break;
case R4300i_SB: break;
case R4300i_SH: break;
case R4300i_SW: break;
case R4300i_SWR: break;
case R4300i_SWL: break;
case R4300i_SWC1: break;
case R4300i_SDC1: break;
case R4300i_SD: break;
default:
return 1;
}
return 0;
}
int32_t DelaySlotEffectsJump (usf_state_t * state, uint32_t JumpPC) {
OPCODE Command;
if (!r4300i_LW_VAddr(state, JumpPC, &Command.u.Hex)) { return 1; }
switch (Command.u.b.op) {
case R4300i_SPECIAL:
switch (Command.u.e.funct) {
case R4300i_SPECIAL_JR: return DelaySlotEffectsCompare(state,JumpPC,Command.u.b.rs,0);
case R4300i_SPECIAL_JALR: return DelaySlotEffectsCompare(state,JumpPC,Command.u.b.rs,31);
}
break;
case R4300i_REGIMM:
switch (Command.u.b.rt) {
case R4300i_REGIMM_BLTZ:
case R4300i_REGIMM_BGEZ:
case R4300i_REGIMM_BLTZL:
case R4300i_REGIMM_BGEZL:
case R4300i_REGIMM_BLTZAL:
case R4300i_REGIMM_BGEZAL:
return DelaySlotEffectsCompare(state,JumpPC,Command.u.b.rs,0);
}
break;
case R4300i_JAL:
case R4300i_SPECIAL_JALR: return DelaySlotEffectsCompare(state,JumpPC,31,0); break;
case R4300i_J: return 0;
case R4300i_BEQ:
case R4300i_BNE:
case R4300i_BLEZ:
case R4300i_BGTZ:
return DelaySlotEffectsCompare(state,JumpPC,Command.u.b.rs,Command.u.b.rt);
case R4300i_CP1:
switch (Command.u.f.fmt) {
case R4300i_COP1_BC:
switch (Command.u.f.ft) {
case R4300i_COP1_BC_BCF:
case R4300i_COP1_BC_BCT:
case R4300i_COP1_BC_BCFL:
case R4300i_COP1_BC_BCTL:
{
int32_t EffectDelaySlot;
OPCODE NewCommand;
if (!r4300i_LW_VAddr(state, JumpPC + 4, &NewCommand.u.Hex)) { return 1; }
EffectDelaySlot = 0;
if (NewCommand.u.b.op == R4300i_CP1) {
if (NewCommand.u.f.fmt == R4300i_COP1_S && (NewCommand.u.e.funct & 0x30) == 0x30 ) {
EffectDelaySlot = 1;
}
if (NewCommand.u.f.fmt == R4300i_COP1_D && (NewCommand.u.e.funct & 0x30) == 0x30 ) {
EffectDelaySlot = 1;
}
}
return EffectDelaySlot;
}
break;
}
break;
}
break;
case R4300i_BEQL:
case R4300i_BNEL:
case R4300i_BLEZL:
case R4300i_BGTZL:
return DelaySlotEffectsCompare(state,JumpPC,Command.u.b.rs,Command.u.b.rt);
}
return 1;
}
void DoSomething ( usf_state_t * state ) {
if (state->CPU_Action->CloseCPU) {
//StopEmulation();
state->cpu_running = 0;
//printf("Stopping?\n");
}
if (state->CPU_Action->CheckInterrupts) {
state->CPU_Action->CheckInterrupts = 0;
CheckInterrupts(state);
}
if (state->CPU_Action->DoInterrupt) {
state->CPU_Action->DoInterrupt = 0;
DoIntrException(state, 0);
}
state->CPU_Action->DoSomething = 0;
if (state->CPU_Action->DoInterrupt) { state->CPU_Action->DoSomething = 1; }
}
void InPermLoop ( usf_state_t * state ) {
// *** Changed ***/
if (state->CPU_Action->DoInterrupt) { return; }
/* Interrupts enabled */
if (( STATUS_REGISTER & STATUS_IE ) == 0 ) { goto InterruptsDisabled; }
if (( STATUS_REGISTER & STATUS_EXL ) != 0 ) { goto InterruptsDisabled; }
if (( STATUS_REGISTER & STATUS_ERL ) != 0 ) { goto InterruptsDisabled; }
if (( STATUS_REGISTER & 0xFF00) == 0) { goto InterruptsDisabled; }
/* check sound playing */
/* check RSP running */
/* check RDP running */
if (state->Timers->Timer >= 0) {
COUNT_REGISTER += state->Timers->Timer + 1;
state->Timers->Timer = -1;
}
return;
InterruptsDisabled:
DisplayError(state, "Stuck in Permanent Loop");
StopEmulation(state);
}
void ReadFromMem(const void * source, void * target, uint32_t length, uint32_t *offset) {
memcpy((uint8_t*)target,((uint8_t*)source)+*offset,length);
*offset+=length;
}
uint32_t Machine_LoadStateFromRAM(usf_state_t * state, void * savestatespace) {
uint8_t LoadHeader[0x40];
uint32_t Value, count, SaveRDRAMSize, offset=0;
ReadFromMem( savestatespace,&Value,sizeof(Value),&offset);
if (Value != 0x23D8A6C8) { return 0; }
ReadFromMem( savestatespace,&SaveRDRAMSize,sizeof(SaveRDRAMSize),&offset);
ReadFromMem( savestatespace,&LoadHeader,0x40,&offset);
state->Timers->CurrentTimerType = -1;
state->Timers->Timer = 0;
for (count = 0; count < MaxTimers; count ++) { state->Timers->Active[count] = 0; }
//fix rdram size
if (SaveRDRAMSize != state->RdramSize) {
// dothis :)
}
state->RdramSize = SaveRDRAMSize;
ReadFromMem( savestatespace,&Value,sizeof(Value),&offset);
ChangeTimer(state,ViTimer,Value);
ReadFromMem( savestatespace,&state->PROGRAM_COUNTER,sizeof(state->PROGRAM_COUNTER),&offset);
ReadFromMem( savestatespace,state->GPR,sizeof(int64_t)*32,&offset);
ReadFromMem( savestatespace,state->FPR,sizeof(int64_t)*32,&offset);
ReadFromMem( savestatespace,state->CP0,sizeof(uint32_t)*32,&offset);
ReadFromMem( savestatespace,state->FPCR,sizeof(uint32_t)*32,&offset);
ReadFromMem( savestatespace,&state->HI,sizeof(int64_t),&offset);
ReadFromMem( savestatespace,&state->LO,sizeof(int64_t),&offset);
ReadFromMem( savestatespace,state->RegRDRAM,sizeof(uint32_t)*10,&offset);
ReadFromMem( savestatespace,state->RegSP,sizeof(uint32_t)*10,&offset);
ReadFromMem( savestatespace,state->RegDPC,sizeof(uint32_t)*10,&offset);
ReadFromMem( savestatespace,state->RegMI,sizeof(uint32_t)*4,&offset);
ReadFromMem( savestatespace,state->RegVI,sizeof(uint32_t)*14,&offset);
ReadFromMem( savestatespace,state->RegAI,sizeof(uint32_t)*6,&offset);
ReadFromMem( savestatespace,state->RegPI,sizeof(uint32_t)*13,&offset);
ReadFromMem( savestatespace,state->RegRI,sizeof(uint32_t)*8,&offset);
ReadFromMem( savestatespace,state->RegSI,sizeof(uint32_t)*4,&offset);
ReadFromMem( savestatespace,state->tlb,sizeof(TLB)*32,&offset);
ReadFromMem( savestatespace,(uint8_t*)state->PIF_Ram,0x40,&offset);
ReadFromMem( savestatespace,state->RDRAM,SaveRDRAMSize,&offset);
ReadFromMem( savestatespace,state->DMEM,0x1000,&offset);
ReadFromMem( savestatespace,state->IMEM,0x1000,&offset);
state->CP0[32] = 0;
SetupTLB(state);
ChangeCompareTimer(state);
AI_STATUS_REG = 0;
AiDacrateChanged(state, AI_DACRATE_REG);
// StartAiInterrupt(state);
SetFpuLocations(state); // important if FR=1
return 1;
}
void StartEmulationFromSave ( usf_state_t * state, void * savestate ) {
uint32_t count = 0;
//printf("Starting generic Cpu\n");
//CloseCpu();
memset(state->N64MEM, 0, state->RdramSize);
memset(state->DMEM, 0, 0x1000);
memset(state->IMEM, 0, 0x1000);
memset(state->TLB_Map, 0, 0x100000 * sizeof(uintptr_t) + 0x10000);
memset(state->CPU_Action,0,sizeof(*state->CPU_Action));
state->WrittenToRom = 0;
InitilizeTLB(state);
SetupRegisters(state, state->Registers);
BuildInterpreter(state);
state->Timers->CurrentTimerType = -1;
state->Timers->Timer = 0;
for (count = 0; count < MaxTimers; count ++) { state->Timers->Active[count] = 0; }
ChangeTimer(state,ViTimer,5000);
ChangeCompareTimer(state);
state->ViFieldNumber = 0;
state->CPURunning = 1;
*state->WaitMode = 0;
init_rsp(state);
Machine_LoadStateFromRAM(state, savestate);
state->SampleRate = 48681812 / (AI_DACRATE_REG + 1);
if(state->enableFIFOfull) {
const float VSyncTiming = 789000.0f;
double BytesPerSecond = 48681812.0 / (AI_DACRATE_REG + 1) * 4;
double CountsPerSecond = (double)(((double)VSyncTiming) * (double)60.0);
double CountsPerByte = (double)CountsPerSecond / (double)BytesPerSecond;
uint32_t IntScheduled = (uint32_t)((double)AI_LEN_REG * CountsPerByte);
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){
if (state->OLD_VI_V_SYNC_REG != VI_V_SYNC_REG)
{
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) {
#ifdef DEBUG_INFO
fprintf(state->debug_log, "RSP Task:");
#endif
if ( ( SP_STATUS_REG & SP_STATUS_HALT ) == 0) {
if ( ( SP_STATUS_REG & SP_STATUS_BROKE ) == 0 ) {
uint32_t Task = *( uint32_t *)(state->DMEM + 0xFC0);
switch (Task) {
case 1: {
MI_INTR_REG |= 0x20;
SP_STATUS_REG |= (0x0203 );
if ((SP_STATUS_REG & SP_STATUS_INTR_BREAK) != 0 )
MI_INTR_REG |= 1;
#ifdef DEBUG_INFO
fprintf(state->debug_log, " DList - interrupts %d\n", MI_INTR_REG);
#endif
CheckInterrupts(state);
DPC_STATUS_REG &= ~0x0002;
return;
}
break;
case 2: {
#ifdef DEBUG_INFO
fprintf(state->debug_log, " AList");
#endif
break;
}
break;
default:
break;
}
real_run_rsp(state, 100);
SP_STATUS_REG |= (0x0203 );
if ((SP_STATUS_REG & SP_STATUS_INTR_BREAK) != 0 ) {
#ifdef DEBUG_INFO
fprintf(state->debug_log, " - interrupt");
#endif
MI_INTR_REG |= 1;
CheckInterrupts(state);
}
}
}
#ifdef DEBUG_INFO
fprintf(state->debug_log, "\n");
#endif
}
void TimerDone (usf_state_t * state) {
switch (state->Timers->CurrentTimerType) {
case CompareTimer:
if(state->enablecompare)
FAKE_CAUSE_REGISTER |= CAUSE_IP7;
CheckInterrupts(state);
ChangeCompareTimer(state);
break;
case ViTimer:
RefreshScreen(state);
MI_INTR_REG |= MI_INTR_VI;
CheckInterrupts(state);
*state->WaitMode=0;
break;
case AiTimer:
ChangeTimer(state,AiTimer,0);
AI_STATUS_REG=0;
state->AudioIntrReg|=4;
//CheckInterrupts(state);
break;
}
CheckTimer(state);
}

+ 95
- 0
Frameworks/lazyusf/lazyusf/cpu.h View File

@@ -0,0 +1,95 @@
/*
* Project 64 - A Nintendo 64 emulator.
*
* (c) Copyright 2001 zilmar (zilmar@emulation64.com) and
* Jabo (jabo@emulation64.com).
*
* pj64 homepage: www.pj64.net
*
* Permission to use, copy, modify and distribute Project64 in both binary and
* source form, for non-commercial purposes, is hereby granted without fee,
* providing that this license information and copyright notice appear with
* all copies and any derived work.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event shall the authors be held liable for any damages
* arising from the use of this software.
*
* Project64 is freeware for PERSONAL USE only. Commercial users should
* seek permission of the copyright holders first. Commercial use includes
* charging money for Project64 or software derived from Project64.
*
* The copyright holders request that bug fixes and improvements to the code
* should be forwarded to them so if they want them.
*
*/
#ifndef _CPU_H_
#define _CPU_H_
#include "interpreter_cpu.h"
#include "interpreter_ops.h"
#include "registers.h"
#include "tlb.h"
#include "memory.h"
#include "dma.h"
#include "exception.h"
#include "pif.h"
#include "opcode.h"
#include "usf.h"
typedef struct {
int32_t DoSomething;
int32_t CloseCPU;
int32_t CheckInterrupts;
int32_t DoInterrupt;
} CPU_ACTION;
#define MaxTimers 3
#define CompareTimer 0
#define ViTimer 1
#define AiTimer 2
typedef struct {
int32_t NextTimer[MaxTimers];
int32_t Active[MaxTimers];
int32_t CurrentTimerType;
int32_t Timer;
} SYSTEM_TIMERS;
void ChangeCompareTimer ( usf_state_t * );
void ChangeTimer ( usf_state_t *, int32_t Type, int32_t Value );
void CheckTimer ( usf_state_t * );
void CloseCpu ( usf_state_t * );
int32_t DelaySlotEffectsCompare ( usf_state_t *, uint32_t PC, uint32_t Reg1, uint32_t Reg2 );
int32_t DelaySlotEffectsJump ( usf_state_t *, uint32_t JumpPC);
void DoSomething ( usf_state_t * );
void InPermLoop ( usf_state_t * );
void InitiliazeCPUFlags ( usf_state_t * );
void RefreshScreen ( usf_state_t * );
void RunRsp ( usf_state_t * );
void StartEmulation ( usf_state_t * );
void TimerDone ( usf_state_t * );
void RecompileTimerDone ( usf_state_t * );
#define NORMAL 0
#define DO_DELAY_SLOT 1
#define DO_END_DELAY_SLOT 2
#define DELAY_SLOT 3
#define END_DELAY_SLOT 4
#define LIKELY_DELAY_SLOT 5
#define JUMP 6
#define DELAY_SLOT_DONE 7
#define LIKELY_DELAY_SLOT_DONE 8
#define END_BLOCK 9
enum SaveType {
Auto,
Eeprom_4K,
Eeprom_16K,
Sram,
FlashRam
};
void StartEmulationFromSave ( usf_state_t * state, void * savestate );
#endif

+ 161
- 0
Frameworks/lazyusf/lazyusf/cpu_hle.c View File

@@ -0,0 +1,161 @@
#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 sort_entrys(void * a, void * b)
{
_HLE_Entry * _a = (_HLE_Entry *)a;
_HLE_Entry * _b = (_HLE_Entry *)b;
return _b->used - _a->used;
}
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;
unsigned entries_used = 0;
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;
++entries_used;
break;
}
}
}
qsort(entries, numEntries, sizeof(*entries), sort_entrys);
state->cpu_hle_entry_count = entries_used;
//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;
unsigned numEntries = state->cpu_hle_entry_count;
for(i = 0; i < numEntries; i++) {
if(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;
}

+ 27
- 0
Frameworks/lazyusf/lazyusf/cpu_hle.h View File

@@ -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

+ 180
- 0
Frameworks/lazyusf/lazyusf/dma.c View File

@@ -0,0 +1,180 @@
/*
* Project 64 - A Nintendo 64 emulator.
*
* (c) Copyright 2001 zilmar (zilmar@emulation64.com) and
* Jabo (jabo@emulation64.com).
*
* pj64 homepage: www.pj64.net
*
* Permission to use, copy, modify and distribute Project64 in both binary and
* source form, for non-commercial purposes, is hereby granted without fee,
* providing that this license information and copyright notice appear with
* all copies and any derived work.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event shall the authors be held liable for any damages
* arising from the use of this software.
*
* Project64 is freeware for PERSONAL USE only. Commercial users should
* seek permission of the copyright holders first. Commercial use includes
* charging money for Project64 or software derived from Project64.
*
* The copyright holders request that bug fixes and improvements to the code
* should be forwarded to them so if they want them.
*
*/
#include <string.h>
#include "main.h"
#include "cpu.h"
#include "usf.h"
#include "usf_internal.h"
void PI_DMA_READ (usf_state_t * state) {
PI_STATUS_REG &= ~PI_STATUS_DMA_BUSY;
MI_INTR_REG |= MI_INTR_PI;
CheckInterrupts(state);
return;
}
void PI_DMA_WRITE (usf_state_t * state) {
uint32_t i;
PI_STATUS_REG |= PI_STATUS_DMA_BUSY;
if ( PI_DRAM_ADDR_REG + PI_WR_LEN_REG + 1 > state->RdramSize) {
PI_STATUS_REG &= ~PI_STATUS_DMA_BUSY;
MI_INTR_REG |= MI_INTR_PI;
CheckInterrupts(state);
return;
}
if ( PI_CART_ADDR_REG >= 0x08000000 && PI_CART_ADDR_REG <= 0x08010000) {
return;
}
if ( PI_CART_ADDR_REG >= 0x10000000 && PI_CART_ADDR_REG <= 0x1FBFFFFF) {
PI_CART_ADDR_REG -= 0x10000000;
for (i = 0; i < PI_WR_LEN_REG + 1; i ++) {
*(state->N64MEM+((PI_DRAM_ADDR_REG + i) ^ 3)) = *PageROM(state, (PI_CART_ADDR_REG + i) ^ 3);
}
PI_CART_ADDR_REG += 0x10000000;
PI_STATUS_REG &= ~PI_STATUS_DMA_BUSY;
MI_INTR_REG |= MI_INTR_PI;
CheckInterrupts(state);
CheckTimer(state);
return;
}
PI_STATUS_REG &= ~PI_STATUS_DMA_BUSY;
MI_INTR_REG |= MI_INTR_PI;
CheckInterrupts(state);
}
void SI_DMA_READ (usf_state_t * state) {
if ((int32_t)SI_DRAM_ADDR_REG > (int32_t)state->RdramSize) {
return;
}
PifRamRead(state);
SI_DRAM_ADDR_REG &= 0xFFFFFFF8;
if ((int32_t)SI_DRAM_ADDR_REG < 0) {
int32_t count, RdramPos;
RdramPos = (int32_t)SI_DRAM_ADDR_REG;
for (count = 0; count < 0x40; count++, RdramPos++) {
if (RdramPos < 0) { continue; }
state->N64MEM[RdramPos ^3] = state->PIF_Ram[count];
}
} else {
int32_t count, RdramPos;
RdramPos = (uint32_t)SI_DRAM_ADDR_REG;
for (count = 0; count < 0x40; count++, RdramPos++) {
if (RdramPos < 0) { continue; }
state->N64MEM[RdramPos ^3] = state->PIF_Ram[count];
}
}
MI_INTR_REG |= MI_INTR_SI;
SI_STATUS_REG |= SI_STATUS_INTERRUPT;
CheckInterrupts(state);
}
void SI_DMA_WRITE (usf_state_t * state) {
if ((int32_t)SI_DRAM_ADDR_REG > (int32_t)state->RdramSize) {
return;
}
SI_DRAM_ADDR_REG &= 0xFFFFFFF8;
if ((int32_t)SI_DRAM_ADDR_REG < 0) {
int32_t count, RdramPos;
RdramPos = (int32_t)SI_DRAM_ADDR_REG;
for (count = 0; count < 0x40; count++, RdramPos++) {
if (RdramPos < 0) { state->PIF_Ram[count] = 0; continue; }
state->PIF_Ram[count] = state->N64MEM[RdramPos ^3];
}
} else {
int32_t count, RdramPos;
RdramPos = (int32_t)SI_DRAM_ADDR_REG;
for (count = 0; count < 0x40; count++, RdramPos++) {
if (RdramPos < 0) { state->PIF_Ram[count] = 0; continue; }
state->PIF_Ram[count] = state->N64MEM[RdramPos ^3];
}
}
PifRamWrite(state);
MI_INTR_REG |= MI_INTR_SI;
SI_STATUS_REG |= SI_STATUS_INTERRUPT;
CheckInterrupts(state);
}
void SP_DMA_READ (usf_state_t * state) {
SP_DRAM_ADDR_REG &= 0x1FFFFFFF;
if (SP_DRAM_ADDR_REG > state->RdramSize) {
SP_DMA_BUSY_REG = 0;
SP_STATUS_REG &= ~SP_STATUS_DMA_BUSY;
return;
}
if (SP_RD_LEN_REG + 1 + (SP_MEM_ADDR_REG & 0xFFF) > 0x1000) {
return;
}
memcpy( state->DMEM + (SP_MEM_ADDR_REG & 0x1FFF), state->N64MEM + SP_DRAM_ADDR_REG,
SP_RD_LEN_REG + 1 );
SP_DMA_BUSY_REG = 0;
SP_STATUS_REG &= ~SP_STATUS_DMA_BUSY;
MI_INTR_REG &= ~MI_INTR_SP;
CheckInterrupts(state);
CheckTimer(state);
}
void SP_DMA_WRITE (usf_state_t * state) {
if (SP_DRAM_ADDR_REG > state->RdramSize) {
return;
}
if (SP_WR_LEN_REG + 1 + (SP_MEM_ADDR_REG & 0xFFF) > 0x1000) {
return;
}
memcpy( state->N64MEM + SP_DRAM_ADDR_REG, state->DMEM + (SP_MEM_ADDR_REG & 0x1FFF),
SP_WR_LEN_REG + 1);
SP_DMA_BUSY_REG = 0;
SP_STATUS_REG &= ~SP_STATUS_DMA_BUSY;
}

+ 34
- 0
Frameworks/lazyusf/lazyusf/dma.h View File

@@ -0,0 +1,34 @@
/*
* Project 64 - A Nintendo 64 emulator.
*
* (c) Copyright 2001 zilmar (zilmar@emulation64.com) and
* Jabo (jabo@emulation64.com).
*
* pj64 homepage: www.pj64.net
*
* Permission to use, copy, modify and distribute Project64 in both binary and
* source form, for non-commercial purposes, is hereby granted without fee,
* providing that this license information and copyright notice appear with
* all copies and any derived work.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event shall the authors be held liable for any damages
* arising from the use of this software.
*
* Project64 is freeware for PERSONAL USE only. Commercial users should
* seek permission of the copyright holders first. Commercial use includes
* charging money for Project64 or software derived from Project64.
*
* The copyright holders request that bug fixes and improvements to the code
* should be forwarded to them so if they want them.
*
*/
void PI_DMA_READ ( usf_state_t * );
void PI_DMA_WRITE ( usf_state_t * );
void SI_DMA_READ ( usf_state_t * );
void SI_DMA_WRITE ( usf_state_t * );
void SP_DMA_READ ( usf_state_t * );
void SP_DMA_WRITE ( usf_state_t * );

+ 158
- 0
Frameworks/lazyusf/lazyusf/exception.c View File

@@ -0,0 +1,158 @@
/*
* Project 64 - A Nintendo 64 emulator.
*
* (c) Copyright 2001 zilmar (zilmar@emulation64.com) and
* Jabo (jabo@emulation64.com).
*
* pj64 homepage: www.pj64.net
*
* Permission to use, copy, modify and distribute Project64 in both binary and
* source form, for non-commercial purposes, is hereby granted without fee,
* providing that this license information and copyright notice appear with
* all copies and any derived work.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event shall the authors be held liable for any damages
* arising from the use of this software.
*
* Project64 is freeware for PERSONAL USE only. Commercial users should
* seek permission of the copyright holders first. Commercial use includes
* charging money for Project64 or software derived from Project64.
*
* The copyright holders request that bug fixes and improvements to the code
* should be forwarded to them so if they want them.
*
*/
#include "main.h"
#include "cpu.h"
#include "usf_internal.h"
void CheckInterrupts ( usf_state_t * state ) {
MI_INTR_REG &= ~MI_INTR_AI;
MI_INTR_REG |= (state->AudioIntrReg & MI_INTR_AI);
#ifdef DEBUG_INFO
if (MI_INTR_REG)
fprintf(state->debug_log, "Interrupt %d - ", MI_INTR_REG);
#endif
if ((MI_INTR_MASK_REG & MI_INTR_REG) != 0) {
#ifdef DEBUG_INFO
fprintf(state->debug_log, "triggered\n");
#endif
FAKE_CAUSE_REGISTER |= CAUSE_IP2;
} else {
#ifdef DEBUG_INFO
if (MI_INTR_REG)
fprintf(state->debug_log, "masked\n");
#endif
FAKE_CAUSE_REGISTER &= ~CAUSE_IP2;
}
if (( STATUS_REGISTER & STATUS_IE ) == 0 ) { return; }
if (( STATUS_REGISTER & STATUS_EXL ) != 0 ) { return; }
if (( STATUS_REGISTER & STATUS_ERL ) != 0 ) { return; }
if (( STATUS_REGISTER & FAKE_CAUSE_REGISTER & 0xFF00) != 0) {
if (!state->CPU_Action->DoInterrupt) {
state->CPU_Action->DoSomething = 1;
state->CPU_Action->DoInterrupt = 1;
}
}
}
void DoAddressError ( usf_state_t * state, uint32_t DelaySlot, uint32_t BadVaddr, uint32_t FromRead) {
if (FromRead) {
CAUSE_REGISTER = EXC_RADE;
} else {
CAUSE_REGISTER = EXC_WADE;
}
BAD_VADDR_REGISTER = BadVaddr;
if (DelaySlot) {
CAUSE_REGISTER |= CAUSE_BD;
EPC_REGISTER = state->PROGRAM_COUNTER - 4;
} else {
EPC_REGISTER = state->PROGRAM_COUNTER;
}
STATUS_REGISTER |= STATUS_EXL;
state->PROGRAM_COUNTER = 0x80000180;
}
void DoBreakException ( usf_state_t * state, uint32_t DelaySlot) {
CAUSE_REGISTER = EXC_BREAK;
if (DelaySlot) {
CAUSE_REGISTER |= CAUSE_BD;
EPC_REGISTER = state->PROGRAM_COUNTER - 4;
} else {
EPC_REGISTER = state->PROGRAM_COUNTER;
}
STATUS_REGISTER |= STATUS_EXL;
state->PROGRAM_COUNTER = 0x80000180;
}
void DoCopUnusableException ( usf_state_t * state, uint32_t DelaySlot, uint32_t Coprocessor ) {
CAUSE_REGISTER = EXC_CPU;
if (Coprocessor == 1) { CAUSE_REGISTER |= 0x10000000; }
if (DelaySlot) {
CAUSE_REGISTER |= CAUSE_BD;
EPC_REGISTER = state->PROGRAM_COUNTER - 4;
} else {
EPC_REGISTER = state->PROGRAM_COUNTER;
}
STATUS_REGISTER |= STATUS_EXL;
state->PROGRAM_COUNTER = 0x80000180;
}
void DoIntrException ( usf_state_t * state, uint32_t DelaySlot ) {
if (( STATUS_REGISTER & STATUS_IE ) == 0 ) { return; }
if (( STATUS_REGISTER & STATUS_EXL ) != 0 ) { return; }
if (( STATUS_REGISTER & STATUS_ERL ) != 0 ) { return; }
CAUSE_REGISTER = FAKE_CAUSE_REGISTER;
CAUSE_REGISTER |= EXC_INT;
EPC_REGISTER = state->PROGRAM_COUNTER;
if (DelaySlot) {
CAUSE_REGISTER |= CAUSE_BD;
EPC_REGISTER -= 4;
}
STATUS_REGISTER |= STATUS_EXL;
state->PROGRAM_COUNTER = 0x80000180;
}
void DoTLBMiss ( usf_state_t * state, uint32_t DelaySlot, uint32_t BadVaddr ) {
CAUSE_REGISTER = EXC_RMISS;
BAD_VADDR_REGISTER = BadVaddr;
CONTEXT_REGISTER &= 0xFF80000F;
CONTEXT_REGISTER |= (BadVaddr >> 9) & 0x007FFFF0;
ENTRYHI_REGISTER = (BadVaddr & 0xFFFFE000);
if ((STATUS_REGISTER & STATUS_EXL) == 0) {
if (DelaySlot) {
CAUSE_REGISTER |= CAUSE_BD;
EPC_REGISTER = state->PROGRAM_COUNTER - 4;
} else {
EPC_REGISTER = state->PROGRAM_COUNTER;
}
if (AddressDefined(state, BadVaddr)) {
state->PROGRAM_COUNTER = 0x80000180;
} else {
state->PROGRAM_COUNTER = 0x80000000;
}
STATUS_REGISTER |= STATUS_EXL;
} else {
state->PROGRAM_COUNTER = 0x80000180;
}
}
void DoSysCallException ( usf_state_t * state, uint32_t DelaySlot) {
CAUSE_REGISTER = EXC_SYSCALL;
if (DelaySlot) {
CAUSE_REGISTER |= CAUSE_BD;
EPC_REGISTER = state->PROGRAM_COUNTER - 4;
} else {
EPC_REGISTER = state->PROGRAM_COUNTER;
}
STATUS_REGISTER |= STATUS_EXL;
state->PROGRAM_COUNTER = 0x80000180;
}

+ 75
- 0
Frameworks/lazyusf/lazyusf/exception.h View File

@@ -0,0 +1,75 @@
/*
* Project 64 - A Nintendo 64 emulator.
*
* (c) Copyright 2001 zilmar (zilmar@emulation64.com) and
* Jabo (jabo@emulation64.com).
*
* pj64 homepage: www.pj64.net
*
* Permission to use, copy, modify and distribute Project64 in both binary and
* source form, for non-commercial purposes, is hereby granted without fee,
* providing that this license information and copyright notice appear with
* all copies and any derived work.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event shall the authors be held liable for any damages
* arising from the use of this software.
*
* Project64 is freeware for PERSONAL USE only. Commercial users should
* seek permission of the copyright holders first. Commercial use includes
* charging money for Project64 or software derived from Project64.
*
* The copyright holders request that bug fixes and improvements to the code
* should be forwarded to them so if they want them.
*
*/
#define EXC_CODE(x) ((x)<<2)
#define EXC_INT EXC_CODE(0) /* interrupt */
#define EXC_MOD EXC_CODE(1) /* TLB mod */
#define EXC_RMISS EXC_CODE(2) /* Read TLB Miss */
#define EXC_WMISS EXC_CODE(3) /* Write TLB Miss */
#define EXC_RADE EXC_CODE(4) /* Read Address Error */
#define EXC_WADE EXC_CODE(5) /* Write Address Error */
#define EXC_IBE EXC_CODE(6) /* Instruction Bus Error */
#define EXC_DBE EXC_CODE(7) /* Data Bus Error */
#define EXC_SYSCALL EXC_CODE(8) /* SYSCALL */
#define EXC_BREAK EXC_CODE(9) /* BREAKpoint */
#define EXC_II EXC_CODE(10)/* Illegal Instruction */
#define EXC_CPU EXC_CODE(11)/* CoProcessor Unusable */
#define EXC_OV EXC_CODE(12)/* OVerflow */
#define EXC_TRAP EXC_CODE(13)/* Trap exception */
#define EXC_VCEI EXC_CODE(14)/* Virt. Coherency on Inst. fetch */
#define EXC_FPE EXC_CODE(15)/* Floating Point Exception */
#define EXC_WATCH EXC_CODE(23)/* Watchpoint reference */
#define EXC_VCED EXC_CODE(31)/* Virt. Coherency on data read */
#define Exception_Name(Except)\
(Except) == EXC_INT ? "interrupt" :\
(Except) == EXC_MOD ? "TLB mod" :\
(Except) == EXC_RMISS ? "Read TLB Miss" :\
(Except) == EXC_WMISS ? "Write TLB Miss" :\
(Except) == EXC_RADE ? "Read Address Error" :\
(Except) == EXC_WADE ? "Write Address Error" :\
(Except) == EXC_IBE ? "Instruction Bus Error" :\
(Except) == EXC_DBE ? "Data Bus Error" :\
(Except) == EXC_SYSCALL ? "SYSCALL" :\
(Except) == EXC_BREAK ? "Break" :\
(Except) == EXC_II ? "Illegal Instruction" :\
(Except) == EXC_CPU ? "CoProcessor Unusable" :\
(Except) == EXC_OV ? "OVerflow" :\
(Except) == EXC_TRAP ? "Trap exception" :\
(Except) == EXC_VCEI ? "Virt. Coherency on Inst. fetch" :\
(Except) == EXC_FPE ? "Floating Point Exception" :\
(Except) == EXC_WATCH ? "Watchpoint reference" :\
(Except) == EXC_VCED ? "Virt. Coherency on data read" :\
"Unkown"
void AiCheckInterrupts ( usf_state_t * );
void CheckInterrupts ( usf_state_t * );
void DoAddressError ( usf_state_t *, uint32_t DelaySlot, uint32_t BadVaddr, uint32_t FromRead );
void DoBreakException ( usf_state_t *, uint32_t DelaySlot );
void DoCopUnusableException ( usf_state_t *, uint32_t DelaySlot, uint32_t Coprocessor );
void DoIntrException ( usf_state_t *, uint32_t DelaySlot );
void DoTLBMiss ( usf_state_t *, uint32_t DelaySlot, uint32_t BadVaddr );
void DoSysCallException ( usf_state_t *, uint32_t DelaySlot);

+ 799
- 0
Frameworks/lazyusf/lazyusf/interpreter_cpu.c View File

@@ -0,0 +1,799 @@
/*
* Project 64 - A Nintendo 64 emulator.
*
* (c) Copyright 2001 zilmar (zilmar@emulation64.com) and
* Jabo (jabo@emulation64.com).
*
* pj64 homepage: www.pj64.net
*
* Permission to use, copy, modify and distribute Project64 in both binary and
* source form, for non-commercial purposes, is hereby granted without fee,
* providing that this license information and copyright notice appear with
* all copies and any derived work.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event shall the authors be held liable for any damages
* arising from the use of this software.
*
* Project64 is freeware for PERSONAL USE only. Commercial users should
* seek permission of the copyright holders first. Commercial use includes
* charging money for Project64 or software derived from Project64.
*
* The copyright holders request that bug fixes and improvements to the code
* should be forwarded to them so if they want them.
*
*/
#include <float.h>
#include "main.h"
#include "cpu.h"
#include "usf.h"
#include "memory.h"
#include "cpu_hle.h"
#include "usf_internal.h"
#include <stdio.h>
void (* R4300i_Opcode[64])(usf_state_t *);
void (* R4300i_Special[64])(usf_state_t *);
void (* R4300i_Regimm[32])(usf_state_t *);
void (* R4300i_CoP0[32])(usf_state_t *);
void (* R4300i_CoP0_Function[64])(usf_state_t *);
void (* R4300i_CoP1[32])(usf_state_t *);
void (* R4300i_CoP1_BC[32])(usf_state_t *);
void (* R4300i_CoP1_S[64])(usf_state_t *);
void (* R4300i_CoP1_D[64])(usf_state_t *);
void (* R4300i_CoP1_W[64])(usf_state_t *);
void (* R4300i_CoP1_L[64])(usf_state_t *);
void R4300i_opcode_SPECIAL (usf_state_t * state) {
R4300i_Special[ state->Opcode.u.e.funct ](state);
}
void R4300i_opcode_REGIMM (usf_state_t * state) {
R4300i_Regimm[ state->Opcode.u.b.rt ](state);
}
void R4300i_opcode_COP0 (usf_state_t * state) {
R4300i_CoP0[ state->Opcode.u.b.rs ](state);
}
void R4300i_opcode_COP0_CO (usf_state_t * state) {
R4300i_CoP0_Function[ state->Opcode.u.e.funct ](state);
}
void R4300i_opcode_COP1 (usf_state_t * state) {
R4300i_CoP1[ state->Opcode.u.f.fmt ](state);
}
void R4300i_opcode_COP1_BC (usf_state_t * state) {
R4300i_CoP1_BC[ state->Opcode.u.f.ft ](state);
}
void R4300i_opcode_COP1_S (usf_state_t * state) {
// controlfp(RoundingModel);
R4300i_CoP1_S[ state->Opcode.u.e.funct ](state);
}
void R4300i_opcode_COP1_D (usf_state_t * state) {
// controlfp(RoundingModel);
R4300i_CoP1_D[ state->Opcode.u.e.funct ](state);
}
void R4300i_opcode_COP1_W (usf_state_t * state) {
R4300i_CoP1_W[ state->Opcode.u.e.funct ](state);
}
void R4300i_opcode_COP1_L (usf_state_t * state) {
R4300i_CoP1_L[ state->Opcode.u.e.funct ](state);
}
void BuildInterpreter (usf_state_t * state) {
(void)state;
R4300i_Opcode[ 0] = R4300i_opcode_SPECIAL;
R4300i_Opcode[ 1] = R4300i_opcode_REGIMM;
R4300i_Opcode[ 2] = r4300i_J;
R4300i_Opcode[ 3] = r4300i_JAL;
R4300i_Opcode[ 4] = r4300i_BEQ;
R4300i_Opcode[ 5] = r4300i_BNE;
R4300i_Opcode[ 6] = r4300i_BLEZ;
R4300i_Opcode[ 7] = r4300i_BGTZ;
R4300i_Opcode[ 8] = r4300i_ADDI;
R4300i_Opcode[ 9] = r4300i_ADDIU;
R4300i_Opcode[10] = r4300i_SLTI;
R4300i_Opcode[11] = r4300i_SLTIU;
R4300i_Opcode[12] = r4300i_ANDI;
R4300i_Opcode[13] = r4300i_ORI;
R4300i_Opcode[14] = r4300i_XORI;
R4300i_Opcode[15] = r4300i_LUI;
R4300i_Opcode[16] = R4300i_opcode_COP0;
R4300i_Opcode[17] = R4300i_opcode_COP1;
R4300i_Opcode[18] = R4300i_UnknownOpcode;
R4300i_Opcode[19] = R4300i_UnknownOpcode;
R4300i_Opcode[20] = r4300i_BEQL;
R4300i_Opcode[21] = r4300i_BNEL;
R4300i_Opcode[22] = r4300i_BLEZL;
R4300i_Opcode[23] = r4300i_BGTZL;
R4300i_Opcode[24] = R4300i_UnknownOpcode;
R4300i_Opcode[25] = r4300i_DADDIU;
R4300i_Opcode[26] = r4300i_LDL;
R4300i_Opcode[27] = r4300i_LDR;
R4300i_Opcode[28] = R4300i_UnknownOpcode;
R4300i_Opcode[29] = R4300i_UnknownOpcode;
R4300i_Opcode[30] = R4300i_UnknownOpcode;
R4300i_Opcode[31] = R4300i_UnknownOpcode;
R4300i_Opcode[32] = r4300i_LB;
R4300i_Opcode[33] = r4300i_LH;
R4300i_Opcode[34] = r4300i_LWL;
R4300i_Opcode[35] = r4300i_LW;
R4300i_Opcode[36] = r4300i_LBU;
R4300i_Opcode[37] = r4300i_LHU;
R4300i_Opcode[38] = r4300i_LWR;
R4300i_Opcode[39] = r4300i_LWU;
R4300i_Opcode[40] = r4300i_SB;
R4300i_Opcode[41] = r4300i_SH;
R4300i_Opcode[42] = r4300i_SWL;
R4300i_Opcode[43] = r4300i_SW;
R4300i_Opcode[44] = r4300i_SDL;
R4300i_Opcode[45] = r4300i_SDR;
R4300i_Opcode[46] = r4300i_SWR;
R4300i_Opcode[47] = r4300i_CACHE;
R4300i_Opcode[48] = r4300i_LL;
R4300i_Opcode[49] = r4300i_LWC1;
R4300i_Opcode[50] = R4300i_UnknownOpcode;
R4300i_Opcode[51] = R4300i_UnknownOpcode;
R4300i_Opcode[52] = R4300i_UnknownOpcode;
R4300i_Opcode[53] = r4300i_LDC1;
R4300i_Opcode[54] = R4300i_UnknownOpcode;
R4300i_Opcode[55] = r4300i_LD;
R4300i_Opcode[56] = r4300i_SC;
R4300i_Opcode[57] = r4300i_SWC1;
R4300i_Opcode[58] = R4300i_UnknownOpcode;
R4300i_Opcode[59] = R4300i_UnknownOpcode;
R4300i_Opcode[60] = R4300i_UnknownOpcode;
R4300i_Opcode[61] = r4300i_SDC1;
R4300i_Opcode[62] = R4300i_UnknownOpcode;
R4300i_Opcode[63] = r4300i_SD;
R4300i_Special[ 0] = r4300i_SPECIAL_SLL;
R4300i_Special[ 1] = R4300i_UnknownOpcode;
R4300i_Special[ 2] = r4300i_SPECIAL_SRL;
R4300i_Special[ 3] = r4300i_SPECIAL_SRA;
R4300i_Special[ 4] = r4300i_SPECIAL_SLLV;
R4300i_Special[ 5] = R4300i_UnknownOpcode;
R4300i_Special[ 6] = r4300i_SPECIAL_SRLV;
R4300i_Special[ 7] = r4300i_SPECIAL_SRAV;
R4300i_Special[ 8] = r4300i_SPECIAL_JR;
R4300i_Special[ 9] = r4300i_SPECIAL_JALR;
R4300i_Special[10] = R4300i_UnknownOpcode;
R4300i_Special[11] = R4300i_UnknownOpcode;
R4300i_Special[12] = r4300i_SPECIAL_SYSCALL;
R4300i_Special[13] = r4300i_SPECIAL_BREAK;
R4300i_Special[14] = R4300i_UnknownOpcode;
R4300i_Special[15] = r4300i_SPECIAL_SYNC;
R4300i_Special[16] = r4300i_SPECIAL_MFHI;
R4300i_Special[17] = r4300i_SPECIAL_MTHI;
R4300i_Special[18] = r4300i_SPECIAL_MFLO;
R4300i_Special[19] = r4300i_SPECIAL_MTLO;
R4300i_Special[20] = r4300i_SPECIAL_DSLLV;
R4300i_Special[21] = R4300i_UnknownOpcode;
R4300i_Special[22] = r4300i_SPECIAL_DSRLV;
R4300i_Special[23] = r4300i_SPECIAL_DSRAV;
R4300i_Special[24] = r4300i_SPECIAL_MULT;
R4300i_Special[25] = r4300i_SPECIAL_MULTU;
R4300i_Special[26] = r4300i_SPECIAL_DIV;
R4300i_Special[27] = r4300i_SPECIAL_DIVU;
R4300i_Special[28] = r4300i_SPECIAL_DMULT;
R4300i_Special[29] = r4300i_SPECIAL_DMULTU;
R4300i_Special[30] = r4300i_SPECIAL_DDIV;
R4300i_Special[31] = r4300i_SPECIAL_DDIVU;
R4300i_Special[32] = r4300i_SPECIAL_ADD;
R4300i_Special[33] = r4300i_SPECIAL_ADDU;
R4300i_Special[34] = r4300i_SPECIAL_SUB;
R4300i_Special[35] = r4300i_SPECIAL_SUBU;
R4300i_Special[36] = r4300i_SPECIAL_AND;
R4300i_Special[37] = r4300i_SPECIAL_OR;
R4300i_Special[38] = r4300i_SPECIAL_XOR;
R4300i_Special[39] = r4300i_SPECIAL_NOR;
R4300i_Special[40] = R4300i_UnknownOpcode;
R4300i_Special[41] = R4300i_UnknownOpcode;
R4300i_Special[42] = r4300i_SPECIAL_SLT;
R4300i_Special[43] = r4300i_SPECIAL_SLTU;
R4300i_Special[44] = r4300i_SPECIAL_DADD;
R4300i_Special[45] = r4300i_SPECIAL_DADDU;
R4300i_Special[46] = r4300i_SPECIAL_DSUB;
R4300i_Special[47] = r4300i_SPECIAL_DSUBU;
R4300i_Special[48] = R4300i_UnknownOpcode;
R4300i_Special[49] = R4300i_UnknownOpcode;
R4300i_Special[50] = R4300i_UnknownOpcode;
R4300i_Special[51] = R4300i_UnknownOpcode;
R4300i_Special[52] = r4300i_SPECIAL_TEQ;
R4300i_Special[53] = R4300i_UnknownOpcode;
R4300i_Special[54] = R4300i_UnknownOpcode;
R4300i_Special[55] = R4300i_UnknownOpcode;
R4300i_Special[56] = r4300i_SPECIAL_DSLL;
R4300i_Special[57] = R4300i_UnknownOpcode;
R4300i_Special[58] = r4300i_SPECIAL_DSRL;
R4300i_Special[59] = r4300i_SPECIAL_DSRA;
R4300i_Special[60] = r4300i_SPECIAL_DSLL32;
R4300i_Special[61] = R4300i_UnknownOpcode;
R4300i_Special[62] = r4300i_SPECIAL_DSRL32;
R4300i_Special[63] = r4300i_SPECIAL_DSRA32;
R4300i_Regimm[ 0] = r4300i_REGIMM_BLTZ;
R4300i_Regimm[ 1] = r4300i_REGIMM_BGEZ;
R4300i_Regimm[ 2] = r4300i_REGIMM_BLTZL;
R4300i_Regimm[ 3] = r4300i_REGIMM_BGEZL;
R4300i_Regimm[ 4] = R4300i_UnknownOpcode;