support for more pedantic, ANSI C rules

This commit is contained in:
RJ Swedlow 2013-08-26 23:03:02 -04:00
parent be355e4190
commit 46082660bc
10 changed files with 54 additions and 119 deletions

View File

@ -11,7 +11,7 @@ extern "C" {
#define PLUGIN_TYPE_CONTROLLER 4
struct HWND__ {int unused;};
typedef struct HWND__ *HWND; /* Use void pointers on GCC or old Windows. */
typedef struct HWND__ *HWND;
struct HINSTANCE__ {int unused;};
typedef struct HINSTANCE__ *HINSTANCE;
struct HMENU__ {int unused;};
@ -27,14 +27,14 @@ typedef struct {
/* If DLL supports memory these memory options then set them to TRUE or FALSE
if it does not support it */
int NormalMemory; /* a normal BYTE array */
int MemoryBswaped; /* a normal BYTE array where the memory has been pre
bswap on a dword (32 bits) boundry */
int MemoryBswaped; /* a normal BYTE array where the memory has been pre-
byte-swapped on a DWORD (32 bits) boundary */
} PLUGIN_INFO;
typedef struct {
HINSTANCE hInst;
int MemoryBswaped; /* If this is set to TRUE, then the memory has been pre
bswap on a dword (32 bits) boundry */
int MemoryBswaped; /* If this is set to TRUE, then the memory has been
pre-byte-swapped on a DWORD (32 bits) boundary */
unsigned char *RDRAM;
unsigned char *DMEM;
unsigned char *IMEM;
@ -87,7 +87,7 @@ typedef struct {
/* Menu */
/* Items should have an ID between 5001 and 5100 */
HMENU hRSPMenu;
void (*ProcessMenuItem) ( int ID );
void (*ProcessMenuItem)(int ID);
/* Break Points */
int UseBPoints;
@ -103,7 +103,6 @@ typedef struct {
/* RSP command Window */
void (*Enter_RSP_Commands_Window)(void);
} RSPDEBUG_INFO;
typedef struct {
@ -128,7 +127,7 @@ typedef struct {
/******************************************************************
Function: CloseDLL
Purpose: This function is called when the emulator is closing
down allowing the dll to de-initialise.
down allowing the DLL to de-initialise.
input: none
output: none
*******************************************************************/
@ -146,7 +145,7 @@ EXPORT void CALL DllAbout(HWND hParent);
/******************************************************************
Function: DllConfig
Purpose: This function is optional function that is provided
to allow the user to configure the dll
to allow the user to configure the DLL
input: a handle to the window that calls this function
output: none
*******************************************************************/
@ -155,7 +154,7 @@ EXPORT void CALL DllConfig(HWND hParent);
/******************************************************************
Function: DllTest
Purpose: This function is optional function that is provided
to allow the user to test the dll
to allow the user to test the DLL
input: a handle to the window that calls this function
output: none
*******************************************************************/
@ -163,22 +162,22 @@ EXPORT void CALL DllTest(HWND hParent);
/******************************************************************
Function: DoRspCycles
Purpose: This function is to allow the RSP to run in parrel with
the r4300 switching control back to the r4300 once the
function ends.
input: The number of cylces that is meant to be executed
Purpose: This function is to allow the RSP to run in parallel
with the r4300 switching control back to the r4300 once
the function ends.
input: The number of cycles that is meant to be executed
output: The number of cycles that was executed. This value can
be greater than the number of cycles that the RSP
should have performed.
(this value is ignored if the RSP is stoped)
(this value is ignored if the RSP is stopped)
*******************************************************************/
EXPORT unsigned int CALL DoRspCycles(unsigned int Cycles);
/******************************************************************
Function: GetDllInfo
Purpose: This function allows the emulator to gather information
about the dll by filling in the PluginInfo structure.
input: a pointer to a PLUGIN_INFO stucture that needs to be
about the DLL by filling in the PluginInfo structure.
input: a pointer to a PLUGIN_INFO structure that needs to be
filled by the function. (see def above)
output: none
*******************************************************************/
@ -187,9 +186,9 @@ EXPORT void CALL GetDllInfo(PLUGIN_INFO *PluginInfo);
/******************************************************************
Function: GetRspDebugInfo
Purpose: This function allows the emulator to gather information
about the debug capabilities of the dll by filling in
about the debug capabilities of the DLL by filling in
the DebugInfo structure.
input: a pointer to a RSPDEBUG_INFO stucture that needs to be
input: a pointer to a RSPDEBUG_INFO structure that needs to be
filled by the function. (see def above)
output: none
*******************************************************************/
@ -212,7 +211,7 @@ EXPORT void CALL InitiateRSP(RSP_INFO Rsp_Info, unsigned int *CycleCount);
Function: InitiateRSPDebugger
Purpose: This function is called when the DLL is started to give
information from the emulator that the n64 RSP
interface needs to intergrate the debugger with the
interface needs to integrate the debugger with the
rest of the emulator.
input: DebugInfo is passed to this function which is defined
above.
@ -232,4 +231,4 @@ EXPORT void CALL RomClosed(void);
}
#endif
#endif // __RSP_1_1_H__
#endif

View File

@ -13,80 +13,16 @@
* It's basically Microsoft's way of saying they're better than everyone.
*/
// #undef MINIMUM_MESSAGE_PRIORITY
/* Many people will have different uses for an RSP emulator.
* Some people only want to see message boxes for definite RSP LLE errors.
* Other people are interested in being notified of technical RSP oddities.
* I have standardized the following priority levels for message boxes:
* 0: Any and all message interrupts in this code will notify the user.
* 1: Interrupt SP emulation with messages of at least curious cases.
* 2: Draw message boxes for N64 situations *probably* unemulated.
* 3: Only notify the user of absolute problems in the emulator.
* 4: Disable all message printing (less CRT/USER32 lib dependency)
* (and also less interference with leisure of full-screen game play)
* This macro is mainly for maintainability as well as cross-OS portability
* by calling a custom method which uses the API-specific message print call.
* See the `void message()` for details on this centralized API invocation.
*/
// #undef EXTERN_COMMAND_LIST_GBI
/* If this is defined, the RSP never executes graphics tasks.
* Those will all be sent to the video plugin for simulation processing.
*/
// #undef EXTERN_COMMAND_LIST_ABI
/* If this is defined, the RSP never executes audio tasks; use audio plugin.
* Enabling both of these does not guarantee that the RSP will never execute.
*/
// #undef SEMAPHORE_LOCK_CORRECTIONS
/* The CPU-RSP semaphore is a lock defining synchronization with the host.
* As of the time in which bpoint reversed the RSP, host interpretation of
* this lock was incorrect. The problem has been inherent for a very long
* time until a rather recent update applied between Project64 1.7:2.0.
*
* If this is on, 1964 and Mupen64 will have no sound for [any?] games.
* It will be almost completely useless on Project64 1.6 or older.
* The exception is HLE audio, where it will work for almost every game.
*
* Keep this off when using audio LLE or playing games booting off the NUS-
* CIC-6105 chip (also uses the semaphore); keep it on with Project64 2.0.
*/
// #undef WAIT_FOR_CPU_HOST
/*
* Bad cycle timing on the part of the CPU host generally means that some
* SP tasks could be started and end up operating on non-up-to-date SP
* status register signal bits (SIG0:SIG7). Enable this setting to restart
* the RSP task after exceeding 10 counts of reading the SP status register
* from within the current task.
* This will work ONLY with Project64 2.0 at the moment (or some of 1.7.x).
*/
// #undef SP_EXECUTE_LOG
/* This is my mechanism to use file output of 32 bits per each SP operation.
* I use this in conjunction with my EXE to handle debug, but still checking
* every single frame even with file output turned off is ~1-2 VI/s slower.
*/
// #undef VU_EMULATE_SCALAR_ACCUMULATOR_READ
/* VSAW is the only RSP instruction that can access the vector accumulator
* elements directly. In the original RSP for Ultra64 this was supposed to
* be called `VSAR` "Vector Accumulator Read (and Write)". (The 'S' probably
* means "Scalar", if not "Select" or "Store".) Current RSP emulators agree
* that in VSAW, the accumulator is copied over to VR[vd], but there is a new
* step no emulator supports. In the original VSAR, that behavior is before
* VR[vs] is copied to those accumulator elements. By the time this opcode
* got renamed to "VSAW", however, the acknowledgement of this ceased to be.
*/
/* Choose whether to define, or keep undefined, the above macros. */
#define MINIMUM_MESSAGE_PRIORITY 1 // show most messages of RSP weirdness
#define MINIMUM_MESSAGE_PRIORITY 1
#define EXTERN_COMMAND_LIST_GBI
#define EXTERN_COMMAND_LIST_ABI
#define SEMAPHORE_LOCK_CORRECTIONS
#define WAIT_FOR_CPU_HOST
// #define SP_EXECUTE_LOG // For debugging only. Keep it off to free CPU.
// #define VU_EMULATE_SCALAR_ACCUMULATOR_READ // experimental but needs tests
#if (0)
#define SP_EXECUTE_LOG // For debugging only. Keep it off to free CPU.
#define VU_EMULATE_SCALAR_ACCUMULATOR_READ // experimental but needs tests
#endif
const char* DLL_name = "Iconoclast's SP Interpreter";

2
rsp.c
View File

@ -19,6 +19,7 @@ const char DLL_about[] =
"Helpful shenanigans: MarathonMan, dsx, and mudlord";
EXPORT void CALL DllAbout(HWND hParent)
{
hParent = NULL;
message(DLL_about, 3);
return;
}
@ -43,6 +44,7 @@ EXPORT void CALL DllConfig(HWND hParent)
FILE* test;
int cond;
hParent = NULL;
test = fopen("sp_cfgui.exe", "rb");
cond = (test == NULL);
fclose(test);

20
su/su.h
View File

@ -108,7 +108,7 @@ static void BREAK(void) /* 000000 ----- ----- ----- ----- 001101 */
/*** Scalar, Jump and Branch Operations ***/
#define SLOT_OFF 0x004
#define LINK_OFF 0x008
INLINE void B(signed int off18) /* MIPS assembly idiom "Unconditional Branch" */
void B(signed int off18) /* MIPS assembly idiom "Unconditional Branch" */
{
if (SR[0] == SR[0]) /* B is a pseudo-op-code for `BEQ $0, $0, offset`. */
{
@ -635,7 +635,7 @@ static void MTC0(void)
*RSP.MI_INTR_REG &= ~((SR[rt] & 0x00000008) >> 3); /* SP_CLR_INTR */
*RSP.MI_INTR_REG |= ((SR[rt] & 0x00000010) >> 4); /* SP_SET_INTR */
*RSP.SP_STATUS_REG |= (SR[rt] & 0x00000010) >> 4; /* int set halt */
//stage |= SR[rt] & 0x00000040; /// fix this shit???
/* stage |= SR[rt] & 0x00000040; */
*RSP.SP_STATUS_REG &= ~(!!(SR[rt] & 0x00000020) << 5);
*RSP.SP_STATUS_REG |= (!!(SR[rt] & 0x00000040) << 5);
*RSP.SP_STATUS_REG &= ~(!!(SR[rt] & 0x00000080) << 6);
@ -781,7 +781,7 @@ extern unsigned short* vCR[2];
extern unsigned char VCE;
#define VR_B(v, e) (*(unsigned char *)(((unsigned char *)(VR + v)) + MES(e)))
#define VR_S(v, e) (*(short *)((unsigned char *)(*(VR + v)) + ((e + 1) & ~1)))
// to-do: check this stupid thing for (unsigned char *)(VR+v) like above?
/* to-do: check this stupid thing for (unsigned char *)(VR+v) like above? */
static void MFC2(void)
{
const int rt = inst.R.rt;
@ -837,7 +837,7 @@ static void C2(void)
}
/*** Scalar, Coprocessor Operations (vector unit, scalar cache transfers) ***/
INLINE void LS_Group_I(int direction, int length)
void LS_Group_I(int direction, int length)
{ /* Group I vector loads and stores, as defined in SGI's patent. */
register unsigned long addr;
register int i;
@ -906,7 +906,7 @@ void LLV(void)
void LDV(void)
{
#if (1)
LS_Group_I(0, sizeof(long long) > 8 ? 8 : sizeof(long long));
LS_Group_I(0, 8);
return;
#else
register unsigned long addr;
@ -1053,7 +1053,7 @@ void SLV(void)
void SDV(void)
{
#if (1)
LS_Group_I(1, sizeof(long long) > 8 ? 8 : sizeof(long long));
LS_Group_I(1, 8);
return;
#else
0 = 0 / 0;
@ -1081,7 +1081,7 @@ void LPV(void)
b = addr & 07;
addr &= ~07;
switch (b)
{ /// to-do: vectorize shifts ???
{ /** to-do: vectorize shifts ??? **/
case 00:
VR[vt][07] = RSP.DMEM[addr + BES(0x007)] << 8;
VR[vt][06] = RSP.DMEM[addr + BES(0x006)] << 8;
@ -1183,7 +1183,7 @@ void LUV(void)
register unsigned long addr;
register int b;
const int vt = inst.R.rt;
int e = inst.R.sa >> 1; /// fixme >.<
int e = inst.R.sa >> 1; /* fixme >.< */
const signed int offset = -(inst.W & 0x00000040) | inst.R.func;
addr = (SR[inst.R.rs] + 8*offset) & 0x00000FFF;
@ -1197,7 +1197,7 @@ void LUV(void)
--e;
addr -= 16 * (e == 0x0);
++addr;
} /// to-do: this shit can't be straightforward, like SQV ?
} /* to-do: this shit can't be straightforward, like SQV ? */
return;
}
b = addr & 07;
@ -1718,7 +1718,7 @@ void LRV(void)
}
void SQV(void)
{
register int i;
register unsigned int i;
register unsigned long addr;
const int e = inst.R.sa >> 1;
const signed int offset = -(inst.W & 0x00000040) | inst.R.func;

View File

@ -2,7 +2,7 @@
static void VCL(int vd, int vs, int vt, int e)
{
const register unsigned short VCC_old = VCC;
register const unsigned short VCC_old = VCC;
int ge, le;
register int i;

View File

@ -4,7 +4,7 @@
* Note about VMACQ.
*
* Current implementation of VMACQ is experimental.
* It is the surviving op-code of the MPEG-DCT-designated RSP circutries.
* It is the surviving op-code of the MPEG-DCT-designated RSP circuitries.
* As such, for it to not be omitted, it is heavily modified from the actual.
*
* It was changed into this newer, archaic algorithm on the hardware.
@ -17,11 +17,11 @@ static void VMACQ(int vd, int vs, int vt, int e)
{
vt = vs = 0; /* ignored inputs */
message("VMACQ", 1); /* untested, any N64 ROMs use this?? */
for (e = 0; e < 8; e++)
if (VACC[e].DW & (32 << 16)) /* Bit 21 of acc must be nonzero. */
for (e = vt; e < 8; e++)
if (VACC[e].DW & (32 << 16)) /* Bit 21 of acc. must be nonzero. */
continue; /* VACC[e].DW += 0x000000000000; */
else
VACC[e].DW += (VACC[e].DW & 0x800000000000) ? +32 << 16 : -32 << 16;
VACC[e].DW += (VACC[e].s[HI] & 0x8000) ? +32 << 16 : -32 << 16;
for (e = 0; e < 8; e++) /* Sign-extend 48-bit to 64-bit supersets. */
VACC[e].HW[03] = (signed short)(VACC[e].s[HI]) >> 15;
SIGNED_CLAMP(VMUL_PTR, 2);

View File

@ -2,7 +2,7 @@
static void VNOP(int unused_sa, int unused_rd, int unused_rt, int unused)
{
unused_sa = unused_rd = unused_rt = unused = 0;
message("VNOP", 3);
unused = unused_rt = unused_rd = unused_sa = 1;
message("VNOP", unused);
return;
}

View File

@ -4,6 +4,6 @@ static void VRSQ(int vd, int de, int vt, int e)
{
e = vt = de = vd = 0;
message("VRSQ\nUnimplemented instruction.", 3);
DPH = 0;
DPH = e;
return;
}

View File

@ -8,10 +8,8 @@ static void VSAW(int vd, int vs, int vt, int e)
for (i = 0; i < 8; i++)
result[i] = VR[vs][i];
#else
vs = 0;
#endif
vt = 0;
vs = vt = 0;
/* Even though `vt` is ignored in VSAR, according to official sources as well
* as reversing, lots of games seem to specify it as nonzero, possibly to
* avoid register stalling or other VU hazards. Not really certain why yet.
@ -25,11 +23,11 @@ static void VSAW(int vd, int vs, int vt, int e)
if (e < 0)
{
message("VSAR\nInvalid mask.", 2);
for (i = 0; i < 8; i++)
for (i = vs; i < 8; i++)
VR_D(i) = 0x0000; /* override behavior (zilmar) */
}
else
for (i = 0; i < 8; i++)
for (i = vs; i < 8; i++)
VR_D(i) = VACC[i].s[e];
#ifdef VU_EMULATE_SCALAR_ACCUMULATOR_READ
e ^= 03;

View File

@ -120,7 +120,7 @@ int sub_mask[16] = {
0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7
};
INLINE void SHUFFLE_VECTOR(int vt, int e)
void SHUFFLE_VECTOR(int vt, int e)
{
register int i, j;
#if (0 == 0)
@ -198,7 +198,7 @@ static unsigned short zclamp[2][2] = {
};
*/
INLINE void SIGNED_CLAMP(short* VD, int mode)
void SIGNED_CLAMP(short* VD, int mode)
{
register int i;
@ -279,7 +279,7 @@ static void res_V(int vd, int rd, int rt, int e)
{
rt = rd = 0;
message("C2\nRESERVED", 2); /* uncertain how to handle reserved, untested */
for (e = 0; e < 8; e++)
for (e = rt; e < 8; e++)
VR_D(e) = 0x0000; /* override behavior (Michael Tedder) */
return;
}