Updated DSP-1 emulation

This commit is contained in:
pagefault
2003-03-04 19:26:12 +00:00
parent bfc42536d2
commit 365807dac5
2 changed files with 95 additions and 72 deletions

View File

@@ -16,15 +16,11 @@
//Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#ifdef __LINUX__
#include "../gblhdr.h"
#else
#include <stdio.h>
#include <stdarg.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>
#endif
//#define DebugDSP1
// uncomment some lines to test
@@ -82,21 +78,19 @@ void Stop_Log(void)
#endif
/***************************************************************************\
* Math tables *
\***************************************************************************/
double *CosTable2;
double *SinTable2;
#define INCR 2048
#define Angle(x) (((x)/(65536/INCR)) & (INCR-1))
#define Cos(x) ((double) CosTable2[x])
#define Sin(x) ((double) SinTable2[x])
// gcc warning fix
#ifdef PI
#undef PI
#endif
#define PI 3.14159265358979323846264338327
double CosTable2[INCR];
double SinTable2[INCR];
double Atan(double x)
{
@@ -231,7 +225,6 @@ void C4Op0D()
C41FXVal=(short)(((double)C41FXVal*tanval)*0.98);
}
/***************************************************************************\
* DSP1 code *
\***************************************************************************/
@@ -241,8 +234,8 @@ void InitDSP(void)
{
#ifdef __OPT__
unsigned int i;
CosTable2 = (double *)malloc(INCR*sizeof(double));
SinTable2 = (double *)malloc(INCR*sizeof(double));
// CosTable2 = (double *) malloc(INCR*sizeof(double));
// SinTable2 = (double *) malloc(INCR*sizeof(double));
for (i=0; i<INCR; i++){
CosTable2[i] = (cos((double)(2*PI*i/INCR)));
SinTable2[i] = (sin((double)(2*PI*i/INCR)));
@@ -254,13 +247,16 @@ void InitDSP(void)
}
short Op00Multiplicand;
short Op00Multiplier;
short Op00Result;
short Op00Multiplicand; // int16
short Op00Multiplier; // int16
short Op00Result; // int16
void DSPOp00()
{
Op00Result=Op00Multiplicand*Op00Multiplier/32768;
// Use the shift 15, don't divide by 32768, it doesn't round the same.
// This expression is bit accurate to DSP1B on MSVC 6.
Op00Result=Op00Multiplicand*Op00Multiplier >> 15;
#ifdef DebugDSP1
Log_Message("OP00 MULT %d*%d/32768=%d",Op00Multiplicand,Op00Multiplier,Op00Result);
#endif
@@ -274,23 +270,28 @@ float Op10Temp;
void DSPOp10()
{
// Hard to get bit accurate here but it's very close...
// within 2 lsb's on the coefficient of the DSP1B. Emu is more accurate.
if (Op10Coefficient == 0) {
Op10CoefficientR = 0x7fff; // DSP1B - Strange but true
Op10ExponentR = 0x002f;
} else {
Op10ExponentR = -Op10Exponent;
Op10Temp = Op10Coefficient / 32768.0;
if (Op10Temp == 0) {
Op10CoefficientR = 0;
} else
Op10Temp = (float)(Op10Coefficient / 32768.0);
Op10Temp = 1/Op10Temp;
if (Op10Temp > 0)
while (Op10Temp >= 1.0) {
Op10Temp=Op10Temp/2.0;
Op10Temp = (float)(Op10Temp/2.0);
Op10ExponentR++;
}
else
while (Op10Temp<-1.0) {
Op10Temp=Op10Temp/2.0;
while (Op10Temp <= -1.0) {
Op10Temp=(float)(Op10Temp/2.0);
Op10ExponentR++;
}
Op10CoefficientR = Op10Temp*32768;
Op10CoefficientR = (short)(Op10Temp*32768);
}
#ifdef DebugDSP1
Log_Message("OP10 INV %d*2^%d = %d*2^%d", Op10Coefficient, Op10Exponent, Op10CoefficientR, Op10ExponentR);
#endif
@@ -298,7 +299,7 @@ void DSPOp10()
short Op04Angle;
unsigned short Op04Radius;
short Op04Radius; // This is signed
short Op04Sin;
short Op04Cos;
@@ -326,8 +327,8 @@ void DSPOp04()
angle = Op04Angle*2*PI/65536.0;
Op04Sin = sin(angle) * Op04Radius;
Op04Cos = cos(angle) * Op04Radius;
Op04Sin = (short)(sin(angle) * Op04Radius);
Op04Cos = (short)(cos(angle) * Op04Radius);
#ifdef DebugDSP1
Log_Message("OP04 Angle:%d Radius:%d",(Op04Angle/256)&255,Op04Radius);
@@ -345,8 +346,8 @@ short Op0CY2;
#ifdef __OPT0C__
void DSPOp0C()
{
Op0CX2=(Op0CX1*Cos(Angle(Op0CA))+Op0CY1*Sin(Angle(Op0CA)));
Op0CY2=(Op0CX1*-Sin(Angle(Op0CA))+Op0CY1*Cos(Angle(Op0CA)));
Op0CX2=(short)((Op0CX1*Cos(Angle(Op0CA))+Op0CY1*Sin(Angle(Op0CA))));
Op0CY2=(short)((Op0CX1*-Sin(Angle(Op0CA))+Op0CY1*Cos(Angle(Op0CA))));
#ifdef DebugDSP1
Log_Message("OP0C Angle:%d X:%d Y:%d CX:%d CY:%d",(Op0CA/256)&255,Op0CX1,Op0CY1,Op0CX2,Op0CY2);
#endif
@@ -500,7 +501,7 @@ void DSPOp02()
CenterY = (cos(NAasB)*ViewerZc*CXdistance)+ViewerYc;
if (CenterY<-32768) CenterY = -32768; if (CenterY>32767) CenterY=32767;
TValDebug = (NAzsB*65536/6.28);
TValDebug = (short)((NAzsB*65536/6.28));
TValDebug2 = ScrDispl;
// if (Op02CY < 0) {Op02CYSup = Op02CY/256; Op02CY = 0;}
@@ -713,6 +714,7 @@ double ObjPX2;
double ObjPY2;
double ObjPZ2;
double DivideOp06;
double d;
int Temp;
int tanval2;
@@ -752,7 +754,16 @@ void DSPOp06()
{
Op06H=(short)(-ObjPX2*Op02LES/-(ObjPZ2)); //-ObjPX2*256/-ObjPZ2;
Op06V=(short)(-ObjPY2*Op02LES/-(ObjPZ2)); //-ObjPY2*256/-ObjPZ2;
Op06S=(unsigned short)(256*(double)Op02LES/-ObjPZ2);
d=(double)Op02LES;
d*=256.0;
d/=(-ObjPZ2);
if(d>65535.0)
d=65535.0;
else if(d<0.0)
d=0.0;
Op06S=(unsigned short)d;
//Op06S=(unsigned short)(256*(double)Op02LES/-ObjPZ2);
//Op06S=(unsigned short)((double)(256.0*((double)Op02LES)/(-ObjPZ2)));
}
else
{
@@ -803,7 +814,15 @@ void DSPOp06()
{
Op06H=(short)(-ObjPX2*Op02LES/-(ObjPZ2)); //-ObjPX2*256/-ObjPZ2;
Op06V=(short)(-ObjPY2*Op02LES/-(ObjPZ2)); //-ObjPY2*256/-ObjPZ2;
Op06S=(unsigned short)(256*(double)Op02LES/-ObjPZ2);
double d=(double)Op02LES;
d*=256.0;
d/=(-ObjPZ2);
if(d>65535.0)
d=65535.0;
else if(d<0.0)
d=0.0;
Op06S=(unsigned short)d;
// Op06S=(unsigned short)(256*(double)Op02LES/-ObjPZ2);
}
else
{
@@ -1291,8 +1310,8 @@ void DSPOp0E()
RVPos = Op0EV;
RHPos = Op0EH;
GetRXYPos();
Op0EX = RXRes;
Op0EY = RYRes;
Op0EX = (short)(RXRes);
Op0EY = (short)(RYRes);
#ifdef DebugDSP1
Log_Message("OP0E COORDINATE H:%d V:%d X:%d Y:%d",Op0EH,Op0EV,Op0EX,Op0EY);
@@ -1314,7 +1333,7 @@ short Op2BS;
void DSPOp0B()
{
Op0BS = (Op0BX*matrixA[0][0]+Op0BY*matrixA2[0][1]+Op0BZ*matrixA2[0][2]);
Op0BS = (short)((Op0BX*matrixA[0][0]+Op0BY*matrixA2[0][1]+Op0BZ*matrixA2[0][2]));
#ifdef DebugDSP1
Log_Message("OP0B");
#endif
@@ -1322,7 +1341,7 @@ void DSPOp0B()
void DSPOp1B()
{
Op1BS = (Op1BX*matrixA2[0][0]+Op1BY*matrixA2[0][1]+Op1BZ*matrixA2[0][2]);
Op1BS = (short)((Op1BX*matrixA2[0][0]+Op1BY*matrixA2[0][1]+Op1BZ*matrixA2[0][2]));
#ifdef DebugDSP1
Log_Message("OP1B X: %d Y: %d Z: %d S: %d",Op1BX,Op1BY,Op1BZ,Op1BS);
Log_Message(" MX: %d MY: %d MZ: %d Scale: %d",(short)(matrixA2[0][0]*100),(short)(matrixA2[0][1]*100),(short)(matrixA2[0][2]*100),(short)(sc2*100));
@@ -1332,7 +1351,7 @@ void DSPOp1B()
void DSPOp2B()
{
Op2BS = (Op2BX*matrixA3[0][0]+Op2BY*matrixA3[0][1]+Op2BZ*matrixA3[0][2]);
Op2BS = (short)((Op2BX*matrixA3[0][0]+Op2BY*matrixA3[0][1]+Op2BZ*matrixA3[0][2]));
#ifdef DebugDSP1
Log_Message("OP2B");
#endif
@@ -1343,6 +1362,8 @@ long Op08Size;
void DSPOp08()
{
// This is bit accurate to DSP1B when compiled with VC 6 on a P4
Op08Size=(Op08X*Op08X+Op08Y*Op08Y+Op08Z*Op08Z)*2;
Op08Ll = Op08Size&0xFFFF;
Op08Lh = (Op08Size>>16) & 0xFFFF;
@@ -1356,12 +1377,12 @@ short Op18X,Op18Y,Op18Z,Op18R,Op18D;
void DSPOp18()
{
double x,y,z,r;
// This is bit accurate to DSP1B when compiled with VC6 on a P4
int x,y,z,r; // int32
x=Op18X; y=Op18Y; z=Op18Z; r=Op18R;
r = (x*x+y*y+z*z-r*r);
if (r>32767) r=32767;
if (r<-32768) r=-32768;
Op18D=(short)r;
Op18D=(short) (r >> 15);
#ifdef DebugDSP1
Log_Message("OP18 X: %d Y: %d Z: %d R: %D DIFF %d",Op18X,Op18Y,Op18Z,Op18D);
#endif
@@ -1374,6 +1395,9 @@ short Op28R;
void DSPOp28()
{
// This works pretty good until r overflows from 0x7fff, then it goes to h*ll.
// Hopefully games don't count on overflow cases matching the DSP
Op28R=(short)sqrt(Op28X*Op28X+Op28Y*Op28Y+Op28Z*Op28Z);
#ifdef DebugDSP1
Log_Message("OP28 X:%d Y:%d Z:%d",Op28X,Op28Y,Op28Z);
@@ -1381,8 +1405,7 @@ void DSPOp28()
#endif
}
short Op1CAZ;
unsigned short Op1CX,Op1CY,Op1CZ;
short Op1CX,Op1CY,Op1CZ;
short Op1CXBR,Op1CYBR,Op1CZBR,Op1CXAR,Op1CYAR,Op1CZAR;
short Op1CX1;
short Op1CY1;
@@ -1400,17 +1423,17 @@ void DSPOp1C()
za = Angle(Op1CZ);
// rotate around Z
Op1CX1=(Op1CXBR*Cos(za)+Op1CYBR*Sin(za));
Op1CY1=(Op1CXBR*-Sin(za)+Op1CYBR*Cos(za));
Op1CX1=(short)((Op1CXBR*Cos(za)+Op1CYBR*Sin(za)));
Op1CY1=(short)((Op1CXBR*-Sin(za)+Op1CYBR*Cos(za)));
Op1CZ1=Op1CZBR;
// rotate around Y
Op1CX2=(Op1CX1*Cos(ya)+Op1CZ1*-Sin(ya));
Op1CX2=(short)((Op1CX1*Cos(ya)+Op1CZ1*-Sin(ya)));
Op1CY2=Op1CY1;
Op1CZ2=(Op1CX1*Sin(ya)+Op1CZ1*Cos(ya));
Op1CZ2=(short)((Op1CX1*Sin(ya)+Op1CZ1*Cos(ya)));
// rotate around X
Op1CXAR=Op1CX2;
Op1CYAR=(Op1CY2*Cos(xa)+Op1CZ2*Sin(xa));
Op1CZAR=(Op1CY2*-Sin(xa)+Op1CZ2*Cos(xa));
Op1CYAR=(short)((Op1CY2*Cos(xa)+Op1CZ2*Sin(xa)));
Op1CZAR=(short)((Op1CY2*-Sin(xa)+Op1CZ2*Cos(xa)));
#ifdef DebugDSP1
Log_Message("OP1C Apply Matrix CX:%d CY:%d CZ",Op1CXAR,Op1CYAR,Op1CZAR);
@@ -1420,9 +1443,10 @@ void DSPOp1C()
void DSPOp1C()
{
double ya,xa,za;
ya = Op1CX/65536.0*PI*2;
xa = Op1CY/65536.0*PI*2;
za = Op1CZ/65536.0*PI*2;
ya = Op1CX/32768.0*PI;
xa = Op1CY/32768.0*PI;
za = Op1CZ/32768.0*PI;
// rotate around Z
Op1CX1=(Op1CXBR*cos(za)+Op1CYBR*sin(za));
Op1CY1=(Op1CXBR*-sin(za)+Op1CYBR*cos(za));
@@ -1440,6 +1464,7 @@ void DSPOp1C()
Log_Message("OP1C Apply Matrix CX:%d CY:%d CZ",Op1CXAR,Op1CYAR,Op1CZAR);
#endif
}
#endif
// Op 0F = Test DSP1 RAM

View File

@@ -24,7 +24,7 @@ EXTSYM KeyRewind
EXTSYM xa,timer2upd,prevoamptr,ReadHead
EXTSYM prevedi,SA1xpc,SA1RAMArea,sa1dmaptr
EXTSYM DSP1COp,C4WFXVal,C41FXVal,Op00Multiplicand,Op10Coefficient,Op04Angle
EXTSYM Op08X,Op18X,Op28X,Op0CA,Op1CAZ,Op02FX,Op0AVS,Op06X,Op0DX,Op03F,Op14Zr
EXTSYM Op08X,Op18X,Op28X,Op0CA,Op02FX,Op0AVS,Op06X,Op0DX,Op03F,Op14Zr
EXTSYM Op0EH,DSP1Type,Op01m
EXTSYM Voice0Status
EXTSYM UpdateDPage
@@ -547,7 +547,6 @@ NEWSYM BackupCVFrame
BackupCVMacB Op18X,5*4+128
BackupCVMacB Op28X,4*4+128
BackupCVMacB Op0CA,5*4+128
BackupCVMacB Op1CAZ,15*4+128
BackupCVMacB Op02FX,11*4+3*4+28*8+128
BackupCVMacB Op0AVS,5*4+14*8+128
BackupCVMacB Op06X,6*4+10*8+4+128
@@ -642,7 +641,6 @@ NEWSYM RestoreCVFrame
BackupCVRMacB Op18X,5*4+128
BackupCVRMacB Op28X,4*4+128
BackupCVRMacB Op0CA,5*4+128
BackupCVRMacB Op1CAZ,15*4+128
BackupCVRMacB Op02FX,11*4+3*4+28*8+128
BackupCVRMacB Op0AVS,5*4+14*8+128
BackupCVRMacB Op06X,6*4+10*8+4+128