mirror of
https://github.com/RetroDECK/Supermodel.git
synced 2024-11-22 22:05:38 +00:00
1135 lines
23 KiB
C++
1135 lines
23 KiB
C++
/**
|
|
** Supermodel
|
|
** A Sega Model 3 Arcade Emulator.
|
|
** Copyright 2011 Bart Trzynadlowski, Nik Henson
|
|
**
|
|
** This file is part of Supermodel.
|
|
**
|
|
** Supermodel is free software: you can redistribute it and/or modify it under
|
|
** the terms of the GNU General Public License as published by the Free
|
|
** Software Foundation, either version 3 of the License, or (at your option)
|
|
** any later version.
|
|
**
|
|
** Supermodel is distributed in the hope that it will be useful, but WITHOUT
|
|
** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
** FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
** more details.
|
|
**
|
|
** You should have received a copy of the GNU General Public License along
|
|
** with Supermodel. If not, see <http://www.gnu.org/licenses/>.
|
|
**/
|
|
|
|
/*
|
|
* SCSPDSP.cpp
|
|
*
|
|
* SCSP DSP emulation.
|
|
*/
|
|
|
|
#include "Supermodel.h"
|
|
#include "SCSPDSP.h"
|
|
//#include <assert.h>
|
|
#define assert(x) ; // disable assert() for releases
|
|
//#include <memory.h>
|
|
//#include <stdio.h>
|
|
//#include <malloc.h>
|
|
#include <cstdio>
|
|
#include <cstdlib>
|
|
#include <cstring>
|
|
|
|
#pragma warning(disable:4311)
|
|
|
|
#define DYNBUF 0x10000
|
|
|
|
//this doesn't work at all
|
|
//#define USEFLOATPACK
|
|
|
|
//the PACK func in asm plus mov [esi],ax
|
|
unsigned char PackFunc[]={0x8B,0xD8,0xA9,0x00,0x00,0x80,0x00,0x75,0x02,0xF7,0xD3,0xF7,0xD3,0x0F,0xBD,0xCB,
|
|
0xF7,0xD9,0xC1,0xE0,0x08,0x83,0xC1,0x16,0xD3,0xE0,0xC1,0xF8,0x13,0xC1,0xE1,0x0B,
|
|
0x25,0xFF,0x87,0x00,0x00,0x0B,0xC1,0x66,0x89,0x06};
|
|
unsigned char UnpackFunc[]={0x8B,0xD8,0x8B,0xC8,0x81,0xE3,0x00,0x80,0x00,0x00,0x25,0xFF,0x07,
|
|
0x00,0x00,0xC1,0xE9,0x0B,0xC1,0xE0,0x0B,0xC1,0xE3,0x08,0x83,0xE1,0x0F,0x0B,0xC3,
|
|
0xD1,0xEB,0x81,0xF3,0x00,0x00,0x40,0x00,0x0B,0xC3,0x83,0xC1,0x08,0xC1,0xE0,0x08,
|
|
0xD3,0xF8};
|
|
#if 0
|
|
unsigned short inline PACK(signed int val)
|
|
{
|
|
/* signed int v1=val;
|
|
int n=0;
|
|
while(((v1>>22)&1) == ((v1>>23)&1))
|
|
{
|
|
v1<<=1;
|
|
++n;
|
|
}
|
|
v1<<=8;
|
|
v1>>=11+8;
|
|
v1=(v1&(~0x7800))|(n<<11);
|
|
return v1;
|
|
*/
|
|
#ifdef USEFLOATPACK
|
|
unsigned short f;
|
|
__asm
|
|
{
|
|
mov eax,val
|
|
mov ebx,eax
|
|
test eax,0x00800000
|
|
jne negval
|
|
not ebx
|
|
negval: not ebx
|
|
bsr ecx,ebx
|
|
neg ecx
|
|
shl eax,8
|
|
add ecx,22
|
|
shl eax,cl
|
|
sar eax,8+11
|
|
shl ecx,11
|
|
and eax,~0x7800
|
|
or eax,ecx
|
|
mov f,ax
|
|
}
|
|
return f;
|
|
#else
|
|
|
|
//cut to 16 bits
|
|
unsigned int f=((unsigned int ) val)>>8;
|
|
return f;
|
|
#endif
|
|
}
|
|
|
|
signed int inline UNPACK(unsigned short val)
|
|
{
|
|
/* if(val)
|
|
int a=1;
|
|
unsigned int mant=val&0x7ff;
|
|
unsigned int exp=(val>>11)&0xf;
|
|
unsigned int sign=(val>>15)&1;
|
|
signed int r=0;
|
|
r|=mant<<11;
|
|
r|=sign<<23;
|
|
r|=(sign^1)<<22;
|
|
|
|
//signed int r=val<<8;
|
|
//if(r&0x00800000)
|
|
// r|=0xFF000000;
|
|
r<<=8;
|
|
r>>=8+exp;
|
|
return r;
|
|
*/
|
|
#ifdef USEFLOATPACK
|
|
signed int r;
|
|
__asm
|
|
{
|
|
xor eax,eax
|
|
mov ax,val
|
|
mov ebx,eax
|
|
mov ecx,eax
|
|
and ebx,0x8000
|
|
and eax,0x07ff
|
|
shr ecx,11
|
|
shl eax,11
|
|
shl ebx,8
|
|
and ecx,0xF
|
|
or eax,ebx
|
|
shr ebx,1
|
|
xor ebx,0x00400000
|
|
or eax,ebx
|
|
add ecx,8
|
|
shl eax,8
|
|
sar eax,cl
|
|
mov r,eax
|
|
}
|
|
#else
|
|
//unpack 16->24
|
|
signed int r=val<<8;
|
|
r<<=8;
|
|
r>>=8;
|
|
#endif
|
|
return r;
|
|
}
|
|
#else
|
|
|
|
static signed short PACK(signed int val)
|
|
{
|
|
unsigned int temp;
|
|
int sign,exponent,k;
|
|
|
|
sign = (val >> 23) & 0x1;
|
|
temp = (val ^ (val << 1)) & 0xFFFFFF;
|
|
exponent = 0;
|
|
for (k=0; k<12; k++)
|
|
{
|
|
if (temp & 0x800000)
|
|
break;
|
|
temp <<= 1;
|
|
exponent += 1;
|
|
}
|
|
if (exponent < 12)
|
|
val = (val << exponent) & 0x3FFFFF;
|
|
else
|
|
val <<= 11;
|
|
val >>= 11;
|
|
val |= sign << 15;
|
|
val |= exponent << 11;
|
|
|
|
return (unsigned short)val;
|
|
}
|
|
|
|
static signed int UNPACK(unsigned short val)
|
|
{
|
|
int sign,exponent,mantissa;
|
|
signed int uval;
|
|
|
|
sign = (val >> 15) & 0x1;
|
|
exponent = (val >> 11) & 0xF;
|
|
mantissa = val & 0x7FF;
|
|
uval = mantissa << 11;
|
|
if (exponent > 11)
|
|
exponent = 11;
|
|
else
|
|
uval |= (sign ^ 1) << 22;
|
|
uval |= sign << 23;
|
|
uval <<= 8;
|
|
uval >>= 8;
|
|
uval >>= exponent;
|
|
|
|
return uval;
|
|
}
|
|
#endif
|
|
|
|
void SCSPDSP_Init(_SCSPDSP *DSP)
|
|
{
|
|
memset(DSP,0,sizeof(_SCSPDSP));
|
|
DSP->RBL=0x8000;
|
|
DSP->Stopped=true;
|
|
}
|
|
#ifndef DYNDSP
|
|
void SCSPDSP_Step(_SCSPDSP *DSP)
|
|
{
|
|
if(DSP->Stopped)
|
|
return;
|
|
signed int ACC=0; //26 bit
|
|
signed int SHIFTED=0; //24 bit
|
|
signed int X=0; //24 bit
|
|
signed int Y=0; //13 bit
|
|
signed int B=0; //26 bit
|
|
signed int INPUTS=0; //24 bit
|
|
signed int MEMVAL=0;
|
|
signed int FRC_REG=0; //13 bit
|
|
signed int Y_REG=0; //24 bit
|
|
unsigned int ADDR=0;
|
|
unsigned int ADRS_REG=0; //13 bit
|
|
|
|
memset(DSP->EFREG,0,2*16);
|
|
int dump=0;
|
|
FILE *f=NULL;
|
|
if(dump)
|
|
f=fopen("dsp.txt","wt");
|
|
for(int step=0;step</*128*/DSP->LastStep;++step)
|
|
{
|
|
unsigned short *IPtr=&(DSP->MPRO[step*4]);
|
|
|
|
// if(IPtr[0]==0 && IPtr[1]==0 && IPtr[2]==0 && IPtr[3]==0)
|
|
// break;
|
|
|
|
unsigned int TRA=(IPtr[0]>>8)&0x7F;
|
|
unsigned int TWT=(IPtr[0]>>7)&0x01;
|
|
unsigned int TWA=(IPtr[0]>>0)&0x7F;
|
|
|
|
unsigned int XSEL=(IPtr[1]>>15)&0x01;
|
|
unsigned int YSEL=(IPtr[1]>>13)&0x03;
|
|
unsigned int IRA=(IPtr[1]>>6)&0x3F;
|
|
unsigned int IWT=(IPtr[1]>>5)&0x01;
|
|
unsigned int IWA=(IPtr[1]>>0)&0x1F;
|
|
|
|
unsigned int TABLE=(IPtr[2]>>15)&0x01;
|
|
unsigned int MWT=(IPtr[2]>>14)&0x01;
|
|
unsigned int MRD=(IPtr[2]>>13)&0x01;
|
|
unsigned int EWT=(IPtr[2]>>12)&0x01;
|
|
unsigned int EWA=(IPtr[2]>>8)&0x0F;
|
|
unsigned int ADRL=(IPtr[2]>>7)&0x01;
|
|
unsigned int FRCL=(IPtr[2]>>6)&0x01;
|
|
unsigned int SHIFT=(IPtr[2]>>4)&0x03;
|
|
unsigned int YRL=(IPtr[2]>>3)&0x01;
|
|
unsigned int NEGB=(IPtr[2]>>2)&0x01;
|
|
unsigned int ZERO=(IPtr[2]>>1)&0x01;
|
|
unsigned int BSEL=(IPtr[2]>>0)&0x01;
|
|
|
|
unsigned int NOFL=(IPtr[3]>>15)&1; //????
|
|
unsigned int COEF=(IPtr[3]>>9)&0x3f;
|
|
|
|
unsigned int MASA=(IPtr[3]>>2)&0x1f; //???
|
|
unsigned int ADREB=(IPtr[3]>>1)&0x1;
|
|
unsigned int NXADR=(IPtr[3]>>0)&0x1;
|
|
|
|
|
|
//operations are done at 24 bit precision
|
|
|
|
if(MASA)
|
|
int a=1;
|
|
if(NOFL)
|
|
int a=1;
|
|
|
|
int dump=0;
|
|
|
|
if(f)
|
|
{
|
|
#define DUMP(v) fprintf(f," " #v ": %04X",v);
|
|
|
|
fprintf(f,"%d: ",step);
|
|
DUMP(ACC);
|
|
DUMP(SHIFTED);
|
|
DUMP(X);
|
|
DUMP(Y);
|
|
DUMP(B);
|
|
DUMP(INPUTS);
|
|
DUMP(MEMVAL);
|
|
DUMP(FRC_REG);
|
|
DUMP(Y_REG);
|
|
DUMP(ADDR);
|
|
DUMP(ADRS_REG);
|
|
fprintf(f,"\n");
|
|
}
|
|
//INPUTS RW
|
|
assert(IRA<0x32);
|
|
if(IRA<=0x1f)
|
|
INPUTS=DSP->MEMS[IRA];
|
|
else if(IRA<=0x2F)
|
|
INPUTS=DSP->MIXS[IRA-0x20]; //MIXS is 24 bit
|
|
else if(IRA<=0x31)
|
|
INPUTS=DSP->EXTS[IRA-0x30];
|
|
else INPUTS=0;
|
|
|
|
INPUTS<<=8;
|
|
INPUTS>>=8;
|
|
//if(INPUTS&0x00800000)
|
|
// INPUTS|=0xFF000000;
|
|
|
|
if(IWT)
|
|
{
|
|
DSP->MEMS[IWA]=MEMVAL; //MEMVAL was selected in previous MRD
|
|
if(IRA==IWA)
|
|
INPUTS=MEMVAL;
|
|
}
|
|
|
|
//Operand sel
|
|
//B
|
|
if(!ZERO)
|
|
{
|
|
if(BSEL)
|
|
B=ACC;
|
|
else
|
|
{
|
|
B=DSP->TEMP[(TRA+DSP->DEC)&0x7F];
|
|
B<<=8;
|
|
B>>=8;
|
|
//if(B&0x00800000)
|
|
// B|=0xFF000000; //Sign extend
|
|
}
|
|
if(NEGB)
|
|
B=0-B;
|
|
}
|
|
else
|
|
B=0;
|
|
|
|
//X
|
|
if(XSEL)
|
|
X=INPUTS;
|
|
else
|
|
{
|
|
X=DSP->TEMP[(TRA+DSP->DEC)&0x7F];
|
|
X<<=8;
|
|
X>>=8;
|
|
//if(X&0x00800000)
|
|
// X|=0xFF000000;
|
|
}
|
|
|
|
//Y
|
|
if(YSEL==0)
|
|
Y=FRC_REG;
|
|
else if(YSEL==1)
|
|
Y=DSP->COEF[COEF]>>3; //COEF is 16 bits
|
|
else if(YSEL==2)
|
|
Y=(Y_REG>>11)&0x1FFF;
|
|
else if(YSEL==3)
|
|
Y=(Y_REG>>4)&0x0FFF;
|
|
|
|
if(YRL)
|
|
Y_REG=INPUTS;
|
|
|
|
//Shifter
|
|
if(SHIFT==0)
|
|
{
|
|
SHIFTED=ACC;
|
|
if(SHIFTED>0x007FFFFF)
|
|
SHIFTED=0x007FFFFF;
|
|
if(SHIFTED<(-0x00800000))
|
|
SHIFTED=-0x00800000;
|
|
}
|
|
else if(SHIFT==1)
|
|
{
|
|
SHIFTED=ACC*2;
|
|
if(SHIFTED>0x007FFFFF)
|
|
SHIFTED=0x007FFFFF;
|
|
if(SHIFTED<(-0x00800000))
|
|
SHIFTED=-0x00800000;
|
|
}
|
|
else if(SHIFT==2)
|
|
{
|
|
SHIFTED=ACC*2;
|
|
SHIFTED<<=8;
|
|
SHIFTED>>=8;
|
|
//SHIFTED&=0x00FFFFFF;
|
|
//if(SHIFTED&0x00800000)
|
|
// SHIFTED|=0xFF000000;
|
|
}
|
|
else if(SHIFT==3)
|
|
{
|
|
SHIFTED=ACC;
|
|
SHIFTED<<=8;
|
|
SHIFTED>>=8;
|
|
//SHIFTED&=0x00FFFFFF;
|
|
//if(SHIFTED&0x00800000)
|
|
// SHIFTED|=0xFF000000;
|
|
}
|
|
|
|
//ACCUM
|
|
Y<<=19;
|
|
Y>>=19;
|
|
//if(Y&0x1000)
|
|
// Y|=0xFFFFF000;
|
|
|
|
INT64 v=(((INT64) X*(INT64) Y)>>12);
|
|
ACC=(int) v+B;
|
|
|
|
if(TWT)
|
|
DSP->TEMP[(TWA+DSP->DEC)&0x7F]=SHIFTED;
|
|
|
|
if(FRCL)
|
|
{
|
|
if(SHIFT==3)
|
|
FRC_REG=SHIFTED&0x0FFF;
|
|
else
|
|
FRC_REG=(SHIFTED>>11)&0x1FFF;
|
|
}
|
|
|
|
if(MRD || MWT)
|
|
//if(0)
|
|
{
|
|
ADDR=DSP->MADRS[MASA];
|
|
if(!TABLE)
|
|
ADDR+=DSP->DEC;
|
|
if(ADREB)
|
|
ADDR+=ADRS_REG&0x0FFF;
|
|
if(NXADR)
|
|
ADDR++;
|
|
if(!TABLE)
|
|
ADDR&=DSP->RBL-1;
|
|
else
|
|
ADDR&=0xFFFF;
|
|
//ADDR<<=1;
|
|
//ADDR+=DSP->RBP<<13;
|
|
//MEMVAL=DSP->SCSPRAM[ADDR>>1];
|
|
ADDR+=DSP->RBP<<12;
|
|
|
|
if(MWT && (step&1))
|
|
{
|
|
if(NOFL)
|
|
DSP->SCSPRAM[ADDR]=SHIFTED>>8;
|
|
else
|
|
DSP->SCSPRAM[ADDR]=PACK(SHIFTED);
|
|
}
|
|
|
|
if(MRD && (step&1)) //memory only allowed on odd? DoA inserts NOPs on even
|
|
{
|
|
if(NOFL)
|
|
MEMVAL=DSP->SCSPRAM[ADDR]<<8;
|
|
else
|
|
MEMVAL=UNPACK(DSP->SCSPRAM[ADDR]);
|
|
if(MEMVAL)
|
|
int a=1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(ADRL)
|
|
{
|
|
if(SHIFT==3)
|
|
ADRS_REG=(SHIFTED>>12)&0xFFF;
|
|
else
|
|
ADRS_REG=(INPUTS>>16);
|
|
}
|
|
|
|
if(EWT)
|
|
DSP->EFREG[EWA]+=SHIFTED>>8;
|
|
|
|
}
|
|
--DSP->DEC;
|
|
memset(DSP->MIXS,0,4*16);
|
|
if(f)
|
|
fclose(f);
|
|
}
|
|
#else
|
|
|
|
FILE *f=NULL;
|
|
|
|
void SCSPDSP_Step(_SCSPDSP *DSP)
|
|
{
|
|
if(DSP->Stopped)
|
|
return;
|
|
|
|
memset(DSP->EFREG,0,2*16);
|
|
|
|
assert(DSP->DoSteps!=NULL);
|
|
|
|
int dump=0;
|
|
if(dump)
|
|
f=fopen("dsp2.txt","wt");
|
|
|
|
DSP->DoSteps();
|
|
|
|
if(f)
|
|
{
|
|
fclose(f);
|
|
f=NULL;
|
|
}
|
|
|
|
--DSP->DEC;
|
|
memset(DSP->MIXS,0,4*16);
|
|
|
|
}
|
|
|
|
void __fastcall dumpreg(_SCSPDSP *DSP)
|
|
{
|
|
static int n=0;
|
|
//f=fopen("dsp2.txt","a+t");
|
|
if(f)
|
|
{
|
|
#define DUMP(v) fprintf(f," " #v ": %04X",DSP->v);
|
|
|
|
fprintf(f,"%d: ",n++);
|
|
DUMP(ACC);
|
|
DUMP(SHIFTED);
|
|
DUMP(X);
|
|
DUMP(Y);
|
|
DUMP(B);
|
|
DUMP(INPUTS);
|
|
DUMP(MEMVAL);
|
|
DUMP(FRC_REG);
|
|
DUMP(Y_REG);
|
|
DUMP(ADDR);
|
|
DUMP(ADRS_REG);
|
|
fprintf(f,"\n");
|
|
}
|
|
}
|
|
|
|
#define EMIT8(x) *PtrInsts=x; ++PtrInsts;
|
|
#define EMIT16(x) *((unsigned short *) PtrInsts)=x; PtrInsts+=2;
|
|
#define EMIT32(x) *((unsigned int *) PtrInsts)=x; PtrInsts+=4;
|
|
|
|
#define MOV_EAXTOMEM(addr) EMIT8(0xA3); EMIT32((unsigned int) addr);
|
|
#define MOV_MEMTOEAX(addr) EMIT8(0xA1); EMIT32((unsigned int) addr);
|
|
#define MOV_MEMTOAX(addr) EMIT8(0x66); EMIT8(0xA1); EMIT32((unsigned int) addr);
|
|
#define MOV_MEMTOEBX(addr) EMIT8(0x8B); EMIT8(0x1D); EMIT32((unsigned int) addr);
|
|
#define ADD_MEMTOEAX(addr) EMIT8(0x03); EMIT8(0x05); EMIT32((unsigned int) addr);
|
|
#define ADD_EAXTOMEM(addr) EMIT8(0x01); EMIT8(0x05); EMIT32((unsigned int) addr);
|
|
#define ADD_AXTOMEM(addr) EMIT8(0x66); EMIT8(0x01); EMIT8(0x05); EMIT32((unsigned int) addr);
|
|
#define MOV_IMMTOEAX(imm) EMIT8(0xB8); EMIT32((unsigned int) imm);
|
|
#define MOV_IMMTOECX(imm) EMIT8(0xB9); EMIT32((unsigned int) imm);
|
|
#define ADD_IMMTOEAX(imm) EMIT8(0x05); EMIT32((unsigned int) imm);
|
|
#define ADD_EBXTOEAX() EMIT8(0x03); EMIT8(0xC3);
|
|
#define CMP_IMMTOEAX(imm) EMIT8(0x3D); EMIT32((unsigned int) imm);
|
|
#define MOV_0TOEAX() EMIT8(0x33); EMIT8(0xC0);
|
|
#define MOV_EAXTOEBX() EMIT8(0x8B); EMIT8(0xD8);
|
|
#define MOV_EAXTOECX() EMIT8(0x8B); EMIT8(0xC8);
|
|
#define NEG_EAX() EMIT8(0xF7); EMIT8(0xD8);
|
|
#define INC_EAX() EMIT8(0x40);
|
|
#define MOV_MEMEAXTOEAX() EMIT8(0x8b); EMIT8(0x00);
|
|
#define MOV_MEMEAXTOAX() EMIT8(0x66); EMIT8(0x8b); EMIT8(0x00);
|
|
#define MOV_EBXTOMEMEAX() EMIT8(0x89); EMIT8(0x18);
|
|
#define MOV_EAXTOMEMEBX() EMIT8(0x89); EMIT8(0x03);
|
|
#define MOV_AXTOMEMEBX() EMIT8(0x66); EMIT8(0x89); EMIT8(0x03);
|
|
#define SHL_EAX(count) EMIT8(0xC1); EMIT8(0xE0); EMIT8(count);
|
|
#define SHL_EBX(count) EMIT8(0xC1); EMIT8(0xE3); EMIT8(count);
|
|
#define SHL_EDX(count) EMIT8(0xC1); EMIT8(0xE2); EMIT8(count);
|
|
#define SHRD_EAX_EDX(count) EMIT8(0x0F); EMIT8(0xAC); EMIT8(0xD0); EMIT8(count);
|
|
#define SAR_EAX(count) EMIT8(0xC1); EMIT8(0xF8); EMIT8(count);
|
|
#define SHR_EAX(count) EMIT8(0xC1); EMIT8(0xE8); EMIT8(count);
|
|
#define AND_EAX(mask) EMIT8(0x25); EMIT32(mask);
|
|
#define AND_EBX(mask) EMIT8(0x81); EMIT8(0xE3); EMIT32(mask);
|
|
#define AND_EAX_EBX() EMIT8(0x23); EMIT8(0xC3);
|
|
#define DEC_EBX() EMIT8(0x4B);
|
|
#define OR_EAX_EDX() EMIT8(0x0B); EMIT8(0xC2);
|
|
#define ADD_EAX_ECX() EMIT8(0x03); EMIT8(0xC1);
|
|
#define IMUL_EAX_EBX() EMIT8(0xF7); EMIT8(0xEB);
|
|
//#define IMUL_EAX_EBX() EMIT8(0xF7); EMIT8(0xE3);
|
|
#define RET() EMIT8(0xC3);
|
|
#define PUSHA() EMIT8(0x51); EMIT8(0x52); EMIT8(0x53); EMIT8(0x56); //ecx edx ebx esi
|
|
#define POPA() EMIT8(0x5E); EMIT8(0x5B); EMIT8(0x5A); EMIT8(0x59); //esi ebx edx ecx
|
|
|
|
struct _INST
|
|
{
|
|
unsigned int TRA;
|
|
unsigned int TWT;
|
|
unsigned int TWA;
|
|
|
|
unsigned int XSEL;
|
|
unsigned int YSEL;
|
|
unsigned int IRA;
|
|
unsigned int IWT;
|
|
unsigned int IWA;
|
|
|
|
unsigned int TABLE;
|
|
unsigned int MWT;
|
|
unsigned int MRD;
|
|
unsigned int EWT;
|
|
unsigned int EWA;
|
|
unsigned int ADRL;
|
|
unsigned int FRCL;
|
|
unsigned int SHIFT;
|
|
unsigned int YRL;
|
|
unsigned int NEGB;
|
|
unsigned int ZERO;
|
|
unsigned int BSEL;
|
|
|
|
unsigned int NOFL;
|
|
unsigned int COEF;
|
|
|
|
unsigned int MASA;
|
|
unsigned int ADREB;
|
|
unsigned int NXADR;
|
|
};
|
|
|
|
void DecodeInst(unsigned short *IPtr,_INST *i)
|
|
{
|
|
i->TRA=(IPtr[0]>>8)&0x7F;
|
|
i->TWT=(IPtr[0]>>7)&0x01;
|
|
i->TWA=(IPtr[0]>>0)&0x7F;
|
|
|
|
i->XSEL=(IPtr[1]>>15)&0x01;
|
|
i->YSEL=(IPtr[1]>>13)&0x03;
|
|
i->IRA=(IPtr[1]>>6)&0x3F;
|
|
i->IWT=(IPtr[1]>>5)&0x01;
|
|
i->IWA=(IPtr[1]>>0)&0x1F;
|
|
|
|
i->TABLE=(IPtr[2]>>15)&0x01;
|
|
i->MWT=(IPtr[2]>>14)&0x01;
|
|
i->MRD=(IPtr[2]>>13)&0x01;
|
|
i->EWT=(IPtr[2]>>12)&0x01;
|
|
i->EWA=(IPtr[2]>>8)&0x0F;
|
|
i->ADRL=(IPtr[2]>>7)&0x01;
|
|
i->FRCL=(IPtr[2]>>6)&0x01;
|
|
i->SHIFT=(IPtr[2]>>4)&0x03;
|
|
i->YRL=(IPtr[2]>>3)&0x01;
|
|
i->NEGB=(IPtr[2]>>2)&0x01;
|
|
i->ZERO=(IPtr[2]>>1)&0x01;
|
|
i->BSEL=(IPtr[2]>>0)&0x01;
|
|
|
|
i->NOFL=(IPtr[3]>>15)&1; //????
|
|
i->COEF=(IPtr[3]>>9)&0x3f;
|
|
|
|
i->MASA=(IPtr[3]>>2)&0x1f; //???
|
|
i->ADREB=(IPtr[3]>>1)&0x1;
|
|
i->NXADR=(IPtr[3]>>0)&0x1;
|
|
}
|
|
|
|
#define USES_SHIFTED(inst) (inst.TWT || inst.FRCL || inst.MWT || inst.ADRL || inst.EWT)
|
|
|
|
void SCSPDSP_Recompile(_SCSPDSP *DSP)
|
|
{
|
|
if(DSP->DoSteps)
|
|
free(DSP->DoSteps);
|
|
DSP->DoSteps=(void (*)()) malloc(DYNBUF);
|
|
unsigned char *PtrInsts=(unsigned char *)DSP->DoSteps;
|
|
|
|
PUSHA();
|
|
|
|
for(int step=0;step</*128*/DSP->LastStep;++step)
|
|
{
|
|
unsigned short *IPtr=&(DSP->MPRO[step*4]);
|
|
_INST ThisInst,NextInst;
|
|
DecodeInst(IPtr,&ThisInst);
|
|
DecodeInst(IPtr+4,&NextInst);
|
|
|
|
|
|
|
|
EMIT8(0x90);
|
|
|
|
MOV_IMMTOECX(DSP);
|
|
MOV_IMMTOEAX(dumpreg);
|
|
EMIT8(0xFF); EMIT8(0xD0);
|
|
|
|
//INPUTS RW
|
|
assert(ThisInst.IRA<0x32);
|
|
if((ThisInst.XSEL || ThisInst.YRL || ThisInst.ADRL) || !DYNOPT)
|
|
{
|
|
if(ThisInst.IRA<=0x1f)
|
|
{
|
|
//INPUTS=DSP->MEMS[IRA];
|
|
MOV_MEMTOEAX(&(DSP->MEMS[ThisInst.IRA]));
|
|
SHL_EAX(8);
|
|
}
|
|
else if(ThisInst.IRA<=0x2F)
|
|
{
|
|
//INPUTS=DSP->MIXS[IRA-0x20]<<8; //MIXS is 16 bit
|
|
MOV_MEMTOEAX(&(DSP->MIXS[ThisInst.IRA-0x20]));
|
|
SHL_EAX(8);
|
|
}
|
|
else if(ThisInst.IRA<=0x31)
|
|
{
|
|
MOV_MEMTOEAX(&(DSP->EXTS[ThisInst.IRA-0x30]));
|
|
SHL_EAX(8);
|
|
}
|
|
else
|
|
{
|
|
MOV_0TOEAX();
|
|
}
|
|
SAR_EAX(8);
|
|
|
|
MOV_EAXTOMEM(&(DSP->INPUTS));
|
|
}
|
|
|
|
if(ThisInst.IWT)
|
|
{
|
|
MOV_MEMTOEAX(&DSP->MEMVAL);
|
|
MOV_EAXTOMEM(&DSP->MEMS[ThisInst.IWA]);
|
|
//DSP->MEMS[IWA]=MEMVAL; //MEMVAL was selected in previous MRD
|
|
if(ThisInst.IRA==ThisInst.IWA)
|
|
{
|
|
//INPUTS=MEMVAL;
|
|
MOV_EAXTOMEM(&DSP->INPUTS);
|
|
}
|
|
}
|
|
|
|
if((USES_SHIFTED(NextInst) || NextInst.BSEL) || !DYNOPT)
|
|
{
|
|
//Operand sel
|
|
//B
|
|
if(!ThisInst.ZERO)
|
|
{
|
|
if(ThisInst.BSEL)
|
|
{
|
|
//B=ACC;
|
|
MOV_MEMTOEAX(&DSP->ACC);
|
|
// MOV_EAXTOMEM(&DSP->B); //
|
|
}
|
|
else
|
|
{
|
|
MOV_IMMTOEAX(ThisInst.TRA);
|
|
ADD_MEMTOEAX(&(DSP->DEC));
|
|
AND_EAX(0x7F);
|
|
SHL_EAX(2);
|
|
ADD_IMMTOEAX(&(DSP->TEMP));
|
|
MOV_MEMEAXTOEAX();
|
|
SHL_EAX(8);
|
|
SAR_EAX(8);
|
|
// MOV_EAXTOMEM(&DSP->B); //
|
|
|
|
|
|
//B=DSP->TEMP[(TRA+DSP->DEC)&0x7F];
|
|
//B<<=8;
|
|
//B>>=8;
|
|
//if(B&0x00800000)
|
|
// B|=0xFF000000; //Sign extend
|
|
}
|
|
if(ThisInst.NEGB)
|
|
{
|
|
//B=0-B;
|
|
NEG_EAX();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
MOV_0TOEAX();
|
|
}
|
|
//MOV_EAXTOMEM(&DSP->B);
|
|
MOV_EAXTOECX();
|
|
|
|
//X
|
|
if(ThisInst.XSEL)
|
|
{
|
|
//X=INPUTS;
|
|
MOV_MEMTOEAX(&DSP->INPUTS);
|
|
// MOV_EAXTOMEM(&DSP->X); //
|
|
}
|
|
else
|
|
{
|
|
//X=DSP->TEMP[(TRA+DSP->DEC)&0x7F];
|
|
//X<<=8;
|
|
//X>>=8;
|
|
MOV_IMMTOEAX(ThisInst.TRA);
|
|
ADD_MEMTOEAX(&(DSP->DEC));
|
|
AND_EAX(0x7F);
|
|
SHL_EAX(2);
|
|
ADD_IMMTOEAX(&(DSP->TEMP));
|
|
MOV_MEMEAXTOEAX();
|
|
SHL_EAX(8);
|
|
SAR_EAX(8);
|
|
//if(X&0x00800000)
|
|
// X|=0xFF000000;
|
|
// MOV_EAXTOMEM(&DSP->X); //
|
|
}
|
|
MOV_EAXTOEBX();
|
|
}
|
|
|
|
|
|
//if(TWT || /*MRD ||*/ MWT || EWT || ADRL || FRCL)
|
|
if(USES_SHIFTED(ThisInst) || !DYNOPT)
|
|
{
|
|
if(ThisInst.SHIFT==0)
|
|
{
|
|
MOV_MEMTOEAX(&DSP->ACC);
|
|
CMP_IMMTOEAX(0x007FFFFF);
|
|
EMIT8(0x7E); EMIT8(0x05); //JLE
|
|
MOV_IMMTOEAX(0x007FFFFF);
|
|
CMP_IMMTOEAX(0xFF800000);
|
|
EMIT8(0x7D); EMIT8(0x05); //JGE
|
|
MOV_IMMTOEAX(0xFF800000);
|
|
|
|
|
|
//SHIFTED=ACC;
|
|
//if(SHIFTED>0x007FFFFF)
|
|
// SHIFTED=0x007FFFFF;
|
|
//if(SHIFTED<(-0x00800000))
|
|
// SHIFTED=-0x00800000;
|
|
}
|
|
else if(ThisInst.SHIFT==1)
|
|
{
|
|
//SHIFTED=ACC*2;
|
|
MOV_MEMTOEAX(&DSP->ACC);
|
|
SHL_EAX(1);
|
|
CMP_IMMTOEAX(0x007FFFFF);
|
|
EMIT8(0x7E); EMIT8(0x05); //JLE
|
|
MOV_IMMTOEAX(0x007FFFFF);
|
|
CMP_IMMTOEAX(0xFF800000);
|
|
EMIT8(0x7D); EMIT8(0x05); //JGE
|
|
MOV_IMMTOEAX(0xFF800000);
|
|
//if(SHIFTED>0x007FFFFF)
|
|
// SHIFTED=0x007FFFFF;
|
|
//if(SHIFTED<(-0x00800000))
|
|
// SHIFTED=-0x00800000;
|
|
}
|
|
else if(ThisInst.SHIFT==2)
|
|
{
|
|
//SHIFTED=ACC*2;
|
|
//SHIFTED<<=8;
|
|
//SHIFTED>>=8;
|
|
MOV_MEMTOEAX(&DSP->ACC);
|
|
SHL_EAX(9);
|
|
SAR_EAX(8);
|
|
//SHIFTED&=0x00FFFFFF;
|
|
//if(SHIFTED&0x00800000)
|
|
// SHIFTED|=0xFF000000;
|
|
}
|
|
else if(ThisInst.SHIFT==3)
|
|
{
|
|
//SHIFTED=ACC;
|
|
//SHIFTED<<=8;
|
|
//SHIFTED>>=8;
|
|
MOV_MEMTOEAX(&DSP->ACC);
|
|
SHL_EAX(8);
|
|
SAR_EAX(8);
|
|
//SHIFTED&=0x00FFFFFF;
|
|
//if(SHIFTED&0x00800000)
|
|
// SHIFTED|=0xFF000000;
|
|
}
|
|
MOV_EAXTOMEM(&DSP->SHIFTED);
|
|
}
|
|
|
|
if((USES_SHIFTED(NextInst) || NextInst.BSEL) || !DYNOPT)
|
|
{
|
|
//Y
|
|
if(ThisInst.YSEL==0)
|
|
{
|
|
//Y=FRC_REG;
|
|
MOV_MEMTOEAX(&DSP->FRC_REG);
|
|
}
|
|
else if(ThisInst.YSEL==1)
|
|
{
|
|
//MOV_0TOEAX();
|
|
MOV_MEMTOAX(&DSP->COEF[ThisInst.COEF]);
|
|
SAR_EAX(3);
|
|
//Y=DSP->COEF[COEF]>>3; //COEF is 16 bits
|
|
}
|
|
else if(ThisInst.YSEL==2)
|
|
{
|
|
//Y=(Y_REG>>11)&0x1FFF;
|
|
MOV_MEMTOEAX(&DSP->Y_REG);
|
|
SAR_EAX(11);
|
|
AND_EAX(0x1FFF);
|
|
}
|
|
else if(ThisInst.YSEL==3)
|
|
{
|
|
//Y=(Y_REG>>4)&0x0FFF;
|
|
MOV_MEMTOEAX(&DSP->Y_REG);
|
|
SAR_EAX(4);
|
|
AND_EAX(0x0FFF);
|
|
}
|
|
|
|
SHL_EAX(19);
|
|
SAR_EAX(19);
|
|
// MOV_EAXTOMEM(&DSP->Y); //
|
|
|
|
|
|
|
|
//X:EBX
|
|
//B:ECX
|
|
//Y:EAX
|
|
IMUL_EAX_EBX();
|
|
// SHR_EAX(12);
|
|
// SHL_EDX((32-12));
|
|
SHRD_EAX_EDX(12);
|
|
ADD_EAX_ECX();
|
|
|
|
MOV_EAXTOMEM(&DSP->ACC);
|
|
}
|
|
|
|
if(ThisInst.YRL)
|
|
{
|
|
MOV_MEMTOEAX(&DSP->INPUTS);
|
|
MOV_EAXTOMEM(&DSP->Y_REG);
|
|
//Y_REG=INPUTS;
|
|
}
|
|
|
|
if(ThisInst.TWT)
|
|
{
|
|
MOV_MEMTOEAX(&DSP->SHIFTED);
|
|
MOV_EAXTOEBX();
|
|
//DSP->TEMP[(TWA+DSP->DEC)&0x7F]=SHIFTED;
|
|
MOV_IMMTOEAX(ThisInst.TWA);
|
|
ADD_MEMTOEAX(&(DSP->DEC));
|
|
AND_EAX(0x7F);
|
|
SHL_EAX(2);
|
|
ADD_IMMTOEAX(&(DSP->TEMP));
|
|
MOV_EBXTOMEMEAX();
|
|
}
|
|
|
|
if(ThisInst.FRCL)
|
|
{
|
|
if(ThisInst.SHIFT==3)
|
|
{
|
|
//FRC_REG=SHIFTED&0x0FFF;
|
|
MOV_MEMTOEAX(&DSP->SHIFTED);
|
|
AND_EAX(0x0FFF);
|
|
MOV_EAXTOMEM(&DSP->FRC_REG);
|
|
}
|
|
else
|
|
{
|
|
//FRC_REG=(SHIFTED>>11)&0x1FFF;
|
|
MOV_MEMTOEAX(&DSP->SHIFTED);
|
|
SHR_EAX(11);
|
|
AND_EAX(0x1FFF);
|
|
MOV_EAXTOMEM(&DSP->FRC_REG);
|
|
}
|
|
}
|
|
|
|
//MEM
|
|
if(ThisInst.MRD || ThisInst.MWT)
|
|
//if(0)
|
|
{
|
|
MOV_0TOEAX();
|
|
MOV_MEMTOAX(&DSP->MADRS[ThisInst.MASA]);
|
|
//ADDR=DSP->MADRS[MASA];
|
|
if(!ThisInst.TABLE)
|
|
{
|
|
//ADDR+=DSP->DEC;
|
|
//ADD_MEMTOEAX(&DSP->DEC);
|
|
MOV_MEMTOEBX(&DSP->DEC);
|
|
ADD_EBXTOEAX();
|
|
}
|
|
if(ThisInst.ADREB)
|
|
{
|
|
MOV_MEMTOEBX(&(DSP->ADRS_REG));
|
|
AND_EBX(0x0FFF);
|
|
ADD_EBXTOEAX();
|
|
//ADDR+=ADRS_REG&0x0FFF;
|
|
}
|
|
if(ThisInst.NXADR)
|
|
{
|
|
//ADDR++;
|
|
INC_EAX();
|
|
}
|
|
if(!ThisInst.TABLE)
|
|
{
|
|
MOV_MEMTOEBX(&(DSP->RBL));
|
|
DEC_EBX();
|
|
//ADDR&=DSP->RBL-1;
|
|
AND_EAX_EBX();
|
|
|
|
//AND_EAX((DSP->RBL-1));
|
|
}
|
|
else
|
|
{
|
|
//ADDR&=0xFFFF;
|
|
AND_EAX(0xFFFF);
|
|
}
|
|
|
|
//ADDR+=DSP->RBP<<12;
|
|
MOV_MEMTOEBX(&(DSP->RBP));
|
|
SHL_EBX(12);
|
|
ADD_EBXTOEAX();
|
|
|
|
assert(!(ThisInst.MRD && ThisInst.MWT)); //this shouldn't happen, read & write in the same cycle
|
|
|
|
if(ThisInst.MWT && (step&1))
|
|
{
|
|
if(ThisInst.NOFL)
|
|
{
|
|
SHL_EAX(1);
|
|
ADD_IMMTOEAX(DSP->SCSPRAM);
|
|
MOV_EAXTOEBX();
|
|
MOV_MEMTOEAX(&DSP->SHIFTED);
|
|
SHR_EAX(8);
|
|
MOV_AXTOMEMEBX();
|
|
//DSP->SCSPRAM[ADDR]=SHIFTED>>8;
|
|
}
|
|
else
|
|
{
|
|
#ifdef USEFLOATPACK
|
|
SHL_EAX(1);
|
|
ADD_IMMTOEAX(DSP->SCSPRAM);
|
|
EMIT8(0x8B); EMIT8(0xF0); //mov esi,eax
|
|
MOV_MEMTOEAX(&DSP->SHIFTED);
|
|
SHR_EAX(8);
|
|
memcpy(PtrInsts,PackFunc,sizeof(PackFunc));
|
|
PtrInsts+=sizeof(PackFunc);
|
|
#else
|
|
SHL_EAX(1);
|
|
ADD_IMMTOEAX(DSP->SCSPRAM);
|
|
MOV_EAXTOEBX();
|
|
MOV_MEMTOEAX(&DSP->SHIFTED);
|
|
SHR_EAX(8);
|
|
MOV_AXTOMEMEBX();
|
|
#endif
|
|
//DSP->SCSPRAM[ADDR]=PACK(SHIFTED);
|
|
}
|
|
}
|
|
|
|
if(ThisInst.MRD && (step&1)) //memory only allowed on odd? DoA inserts NOPs on even
|
|
{
|
|
if(ThisInst.NOFL)
|
|
{
|
|
//MEMVAL=DSP->SCSPRAM[ADDR]<<8;
|
|
SHL_EAX(1);
|
|
ADD_IMMTOEAX(DSP->SCSPRAM);
|
|
MOV_MEMEAXTOAX();
|
|
SHL_EAX(8);
|
|
//MOV_EAXTOMEM(&DSP->MEMVAL);
|
|
}
|
|
else
|
|
{
|
|
//MEMVAL=UNPACK(DSP->SCSPRAM[ADDR]);
|
|
SHL_EAX(1);
|
|
ADD_IMMTOEAX(DSP->SCSPRAM);
|
|
MOV_MEMEAXTOAX();
|
|
#ifdef USEFLOATPACK
|
|
memcpy(PtrInsts,UnpackFunc,sizeof(UnpackFunc));
|
|
PtrInsts+=sizeof(UnpackFunc);
|
|
#else
|
|
SHL_EAX(16);
|
|
SAR_EAX(8);
|
|
#endif
|
|
MOV_EAXTOMEM(&DSP->MEMVAL);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
if(ThisInst.ADRL)
|
|
{
|
|
if(ThisInst.SHIFT==3)
|
|
{
|
|
MOV_MEMTOEAX(&DSP->SHIFTED);
|
|
SAR_EAX(12);
|
|
AND_EAX(0xFFF);
|
|
MOV_EAXTOMEM(&DSP->ADRS_REG);
|
|
//ADRS_REG=(SHIFTED>>12)&0xFFF;
|
|
}
|
|
else
|
|
{
|
|
MOV_MEMTOEAX(&DSP->INPUTS);
|
|
SAR_EAX(16);
|
|
MOV_EAXTOMEM(&DSP->ADRS_REG);
|
|
//ADRS_REG=(INPUTS>>16);
|
|
}
|
|
}
|
|
|
|
if(ThisInst.EWT)
|
|
{
|
|
MOV_MEMTOEAX(&DSP->SHIFTED);
|
|
SAR_EAX(8);
|
|
ADD_AXTOMEM(&DSP->EFREG[ThisInst.EWA]);
|
|
//DSP->EFREG[EWA]+=SHIFTED>>8;
|
|
}
|
|
// EMIT8(0x90);
|
|
// EMIT8(0xCC);
|
|
|
|
}
|
|
|
|
POPA();
|
|
|
|
RET();
|
|
|
|
FILE *f=fopen("dsp.rec","wb");
|
|
fwrite(DSP->DoSteps,1,PtrInsts-(unsigned char *)DSP->DoSteps,f);
|
|
fclose(f);
|
|
}
|
|
|
|
#endif
|
|
void SCSPDSP_SetSample(_SCSPDSP *DSP,signed int sample,int SEL,int MXL)
|
|
{
|
|
// if(MXL!=6)
|
|
// return;
|
|
//16 to 24
|
|
DSP->MIXS[SEL]+=sample<<(MXL+1)/*7*/;
|
|
// DSP->MIXS[SEL]+=sample<<7;
|
|
if(MXL)
|
|
{
|
|
int a=1;
|
|
if(MXL!=6)
|
|
int a=1;
|
|
}
|
|
|
|
}
|
|
|
|
void SCSPDSP_Start(_SCSPDSP *DSP)
|
|
{
|
|
int i;
|
|
DSP->Stopped=false;
|
|
for(i=127;i>=0;--i)
|
|
{
|
|
unsigned short *IPtr=&(DSP->MPRO[i*4]);
|
|
|
|
if(IPtr[0]!=0 || IPtr[1]!=0 || IPtr[2]!=0 || IPtr[3]!=0)
|
|
break;
|
|
}
|
|
DSP->LastStep=i+1;
|
|
|
|
/*
|
|
int test=0;
|
|
if(test)
|
|
{
|
|
//test
|
|
FILE *f1;
|
|
f1=fopen("MPRO","wb");
|
|
fwrite(DSP->MPRO,128*4*2,1,f1);
|
|
fwrite(DSP->COEF,64*2,1,f1);
|
|
fwrite(DSP->MADRS,32*2,1,f1);
|
|
fclose(f1);
|
|
}
|
|
*/
|
|
|
|
for(int t=0;t<0x10000;++t)
|
|
{
|
|
signed int unp=UNPACK(t);
|
|
unsigned short t2=PACK(unp);
|
|
if(t2!=t)
|
|
int a=1;
|
|
}
|
|
|
|
#ifdef DYNDSP
|
|
SCSPDSP_Recompile(DSP);
|
|
#endif
|
|
} |