diff --git a/core/hw/aica/dsp.cpp b/core/hw/aica/dsp.cpp index 13f497b2f..fa0ba336a 100644 --- a/core/hw/aica/dsp.cpp +++ b/core/hw/aica/dsp.cpp @@ -1,4 +1,4 @@ -#include "dsp.h" +#include "dsp.h" #include "aica_mem.h" #include "hw/aica/aica_if.h" #include "oslib/oslib.h" @@ -22,6 +22,54 @@ DECL_ALIGN(4096) dsp_t dsp; +//float format is ? +u16 DYNACALL PACK(s32 val) +{ + u32 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 (u16)val; +} + +s32 DYNACALL UNPACK(u16 val) +{ + int sign,exponent,mantissa; + s32 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; +} + #if HOST_CPU == CPU_X86 && FEAT_DSPREC == DYNAREC_JIT #include "emitter/x86_emitter.h" @@ -32,38 +80,6 @@ const bool SUPPORT_NOFL=false; #pragma warning(disable:4311) -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 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; //MRQ set - unsigned int TABLE; //MRQ set - unsigned int MWT; //MRQ set - unsigned int MRD; //MRQ set - unsigned int MASA; //MRQ set - unsigned int ADREB; //MRQ set - unsigned int NXADR; //MRQ set -}; - - #define DYNBUF 0x10000 /* //#define USEFLOATPACK @@ -127,55 +143,6 @@ _negme: } }*/ -//float format is ? -static u16 DYNACALL PACK(s32 val) -{ - u32 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 (u16)val; -} - -static s32 DYNACALL UNPACK(u16 val) -{ - int sign,exponent,mantissa; - s32 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; -} - - void dsp_init() { memset(&dsp,0,sizeof(dsp)); @@ -187,7 +154,7 @@ void dsp_init() dsp.regs.MDEC_CT=1; - os_MakeExecutable(dsp.DynCode,sizeof(dsp.DynCode)); + //os_MakeExecutable(dsp.DynCode,sizeof(dsp.DynCode)); } void dsp_recompile(); void DecodeInst(u32 *IPtr,_INST *i) @@ -252,8 +219,8 @@ void _dsp_debug_step_end() verify(dsp.regs_init.TEMPS); verify(dsp.regs_init.EFREG); } -#define nwtn(x) verify(!dsp.regs_init.##x) -#define wtn(x) nwtn(x);dsp.regs_init.##x=true; +#define nwtn(x) verify(!dsp.regs_init.x) +#define wtn(x) nwtn(x);dsp.regs_init.x=true; //sign extend to 32 bits void dsp_rec_se(x86_block& x86e,x86_gpr_reg reg,u32 src_sz,u32 dst_sz=0xFF) @@ -864,10 +831,4 @@ void dsp_readmem(u32 addr) { //nothing ? :p } -#else - -void dsp_init() { } -void dsp_term() { } -void dsp_step() { } -void dsp_writenmem(u32 addr) { } -#endif \ No newline at end of file +#endif diff --git a/core/hw/aica/dsp.h b/core/hw/aica/dsp.h index e9e790d74..7f31d3709 100644 --- a/core/hw/aica/dsp.h +++ b/core/hw/aica/dsp.h @@ -8,9 +8,9 @@ struct dsp_t //buffered DSP state //24 bit wide - u32 TEMP[128]; + s32 TEMP[128]; //24 bit wide - u32 MEMS[32]; + s32 MEMS[32]; //20 bit wide s32 MIXS[16]; @@ -59,7 +59,7 @@ struct dsp_t u32 NOFL_2; }regs; //DEC counter :) - u32 DEC; + //u32 DEC; //various dsp regs signed int ACC; //26 bit @@ -81,6 +81,8 @@ struct dsp_t //EFREG *16 //EXTS *2 + // Interpreter flags + bool Stopped; //Dynarec flags bool dyndirty; @@ -92,4 +94,39 @@ extern dsp_t dsp; void dsp_init(); void dsp_term(); void dsp_step(); -void dsp_writenmem(u32 addr); \ No newline at end of file +void dsp_writenmem(u32 addr); + +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 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; //MRQ set + unsigned int TABLE; //MRQ set + unsigned int MWT; //MRQ set + unsigned int MRD; //MRQ set + unsigned int MASA; //MRQ set + unsigned int ADREB; //MRQ set + unsigned int NXADR; //MRQ set +}; + +void DecodeInst(u32 *IPtr,_INST *i); +u16 DYNACALL PACK(s32 val); +s32 DYNACALL UNPACK(u16 val); diff --git a/core/hw/aica/dsp_interp.cpp b/core/hw/aica/dsp_interp.cpp new file mode 100644 index 000000000..2185d330c --- /dev/null +++ b/core/hw/aica/dsp_interp.cpp @@ -0,0 +1,326 @@ +// +// Audio Overload SDK +// +// Copyright (c) 2007-2009 R. Belmont and Richard Bannister, and others. +// All rights reserved. +// +#include "dsp.h" +#include "aica_if.h" +#include "aica_mem.h" + +#if FEAT_DSPREC == DYNAREC_NONE + +void AICADSP_Init(struct dsp_t *DSP) +{ + memset(DSP, 0, sizeof(*DSP)); + DSP->RBL = 0x8000 - 1; + DSP->Stopped = 1; + dsp.regs.MDEC_CT = 1; +} + +void AICADSP_Step(struct dsp_t *DSP) +{ + s32 ACC = 0; //26 bit + s32 SHIFTED = 0; //24 bit + s32 X = 0; //24 bit + s32 Y = 0; //13 bit + s32 B = 0; //26 bit + s32 INPUTS = 0; //24 bit + s32 MEMVAL[4] = {0}; + s32 FRC_REG = 0; //13 bit + s32 Y_REG = 0; //24 bit + u32 ADDR = 0; + u32 ADRS_REG = 0; //13 bit + int step; + + memset(DSPData->EFREG, 0, sizeof(DSPData->EFREG)); + + if (DSP->Stopped) + return; + +#if 0 + int dump = 0; + FILE *f = NULL; + if (dump) + f = fopen("dsp.txt", "wt"); +#endif + + for (step = 0; step < 128; ++step) + { + u32 *IPtr = DSPData->MPRO + step * 4; + + u32 TRA = (IPtr[0] >> 9) & 0x7F; + u32 TWT = (IPtr[0] >> 8) & 0x01; + u32 TWA = (IPtr[0] >> 1) & 0x7F; + + u32 XSEL = (IPtr[1] >> 15) & 0x01; + u32 YSEL = (IPtr[1] >> 13) & 0x03; + u32 IRA = (IPtr[1] >> 7) & 0x3F; + u32 IWT = (IPtr[1] >> 6) & 0x01; + u32 IWA = (IPtr[1] >> 1) & 0x1F; + + u32 TABLE = (IPtr[2] >> 15) & 0x01; + u32 MWT = (IPtr[2] >> 14) & 0x01; + u32 MRD = (IPtr[2] >> 13) & 0x01; + u32 EWT = (IPtr[2] >> 12) & 0x01; + u32 EWA = (IPtr[2] >> 8) & 0x0F; + u32 ADRL = (IPtr[2] >> 7) & 0x01; + u32 FRCL = (IPtr[2] >> 6) & 0x01; + u32 SHIFT = (IPtr[2] >> 4) & 0x03; + u32 YRL = (IPtr[2] >> 3) & 0x01; + u32 NEGB = (IPtr[2] >> 2) & 0x01; + u32 ZERO = (IPtr[2] >> 1) & 0x01; + u32 BSEL = (IPtr[2] >> 0) & 0x01; + + u32 NOFL = (IPtr[3] >> 15) & 1; //???? + verify(!NOFL); + u32 COEF = step; + + u32 MASA = (IPtr[3] >> 9) & 0x3f; //??? + u32 ADREB = (IPtr[3] >> 8) & 0x1; + u32 NXADR = (IPtr[3] >> 7) & 0x1; + + // operations are done at 24 bit precision +#if 0 +#define DUMP(v) printf(" " #v ": %04X",v); + + printf("%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); + printf("\n"); +#endif + + // INPUTS RW + verify(IRA < 0x38); + if (IRA <= 0x1f) + INPUTS = DSP->MEMS[IRA]; + else if (IRA <= 0x2F) + INPUTS = DSP->MIXS[IRA - 0x20] << 4; // MIXS is 20 bit + else if (IRA <= 0x31) + INPUTS = DSPData->EXTS[IRA - 0x30] << 8; // EXTS is 16 bits + else + INPUTS = 0; + + INPUTS <<= 8; + INPUTS >>= 8; + + if (IWT) + { + DSP->MEMS[IWA] = MEMVAL[step & 3]; // MEMVAL was selected in previous MRD + // "When read and write are specified simultaneously in the same step for INPUTS, TEMP, etc., write is executed after read." + //if (IRA == IWA) + // INPUTS = MEMVAL[step & 3]; + } + + // Operand sel + // B + if (!ZERO) + { + if (BSEL) + B = ACC; + else + { + B = DSP->TEMP[(TRA + DSP->regs.MDEC_CT) & 0x7F]; + B <<= 8; //Sign extend + B >>= 8; + } + if (NEGB) + B = 0 - B; + } + else + B = 0; + + // X + if (XSEL) + X = INPUTS; + else + { + X = DSP->TEMP[(TRA + DSP->regs.MDEC_CT) & 0x7F]; + X <<= 8; + X >>= 8; + } + + // Y + if (YSEL == 0) + Y = FRC_REG; + else if (YSEL == 1) + Y = DSPData->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 + // There's a 1-step delay at the output of the X*Y + B adder. So we use the ACC value from the previous step. + if (SHIFT == 0) + { + SHIFTED = ACC >> 2; // 26 bits -> 24 bits + if (SHIFTED > 0x0007FFFF) + SHIFTED = 0x0007FFFF; + if (SHIFTED < (-0x00080000)) + SHIFTED = -0x00080000; + } + else if (SHIFT == 1) + { + SHIFTED = ACC >> 1; // 26 bits -> 24 bits and x2 scale + if (SHIFTED > 0x0007FFFF) + SHIFTED = 0x0007FFFF; + if (SHIFTED < (-0x00080000)) + SHIFTED = -0x00080000; + } + else if (SHIFT == 2) + { + SHIFTED = ACC >> 1; + SHIFTED <<= 8; + SHIFTED >>= 8; + } + else if (SHIFT == 3) + { + SHIFTED = ACC >> 2; + SHIFTED <<= 8; + SHIFTED >>= 8; + } + + // ACCUM + Y <<= 19; + Y >>= 19; + + s64 v = ((s64)X * (s64)Y) >> 10; // magic value from dynarec. 1 sign bit + 24-1 bits + 13-1 bits -> 26 bits? + v <<= 6; // 26 bits only + v >>= 6; + ACC = v + B; + ACC <<= 6; // 26 bits only + ACC >>= 6; + + if (TWT) + DSP->TEMP[(TWA + DSP->regs.MDEC_CT) & 0x7F] = SHIFTED; + + if (FRCL) + { + if (SHIFT == 3) + FRC_REG = SHIFTED & 0x0FFF; + else + FRC_REG = (SHIFTED >> 11) & 0x1FFF; + } + + if ((MRD || MWT) && (step & 1)) + { + ADDR = DSPData->MADRS[MASA]; + if (ADREB) + ADDR += ADRS_REG & 0x0FFF; + if (NXADR) + ADDR++; + if (!TABLE) + ADDR += DSP->regs.MDEC_CT; + if (!TABLE) + ADDR &= DSP->RBL; // RBL is ring buffer length - 1 + else + ADDR &= 0xFFFF; + // ADDR <<= 1; + // ADDR += DSP->RBP << 13; + // MEMVAL = DSP->AICARAM[ADDR >> 1]; + ADDR <<= 1; // Word -> byte address + ADDR += DSP->RBP; // RBP is already a byte address + if (MRD) // memory only allowed on odd. DoA inserts NOPs on even + { + if (NOFL) + MEMVAL[(step + 2) & 3] = (*(s16 *)&aica_ram[ADDR]) << 8; + else + MEMVAL[(step + 2) & 3] = UNPACK(*(u16 *)&aica_ram[ADDR]); + } + if (MWT) + { + // FIXME We should wait for the next step to copy stuff to SRAM (same as read) + if (NOFL) + *(s16 *)&aica_ram[ADDR] = SHIFTED >> 8; + else + *(u16 *)&aica_ram[ADDR] = PACK(SHIFTED); + } + } + + if (ADRL) + { + if (SHIFT == 3) + ADRS_REG = (SHIFTED >> 12) & 0xFFF; + else + ADRS_REG = (INPUTS >> 16); + } + + if (EWT) + // 4 ???? + DSPData->EFREG[EWA] += SHIFTED >> 4; // dynarec uses = instead of += + + } + --DSP->regs.MDEC_CT; + if (dsp.regs.MDEC_CT == 0) + dsp.regs.MDEC_CT = dsp.RBL + 1; // RBL is ring buffer length - 1 + +// memset(DSP->MIXS, 0, sizeof(DSP->MIXS)); +// if(f) +// fclose(f); +} + +void AICADSP_Start(struct dsp_t *DSP) +{ + dsp.Stopped = 1; + for (int i = 127; i >= 0; --i) + { + u32 *IPtr = DSPData->MPRO + i * 4; + + if (IPtr[0] != 0 || IPtr[1] != 0 || IPtr[2 ]!= 0 || IPtr[3] != 0) + { + DSP->Stopped = 0; + //printf("DSP: starting %d steps\n", i + 1); + + break; + } + } +} + +void dsp_init() +{ + AICADSP_Init(&dsp); + AICADSP_Start(&dsp); +} + +void dsp_term() +{ + dsp.Stopped = 1; +} + +void dsp_step() +{ + AICADSP_Step(&dsp); +} + +void dsp_writenmem(u32 addr) +{ + if (addr >= 0x3400 && addr < 0x3C00) + { + AICADSP_Start(&dsp); + } + else if (addr >= 0x4000 && addr < 0x4400) + { + // TODO proper sharing of memory with sh4 through DSPData + memset(dsp.TEMP, 0, sizeof(dsp.TEMP)); + } + else if (addr >= 0x4400 && addr < 0x4500) + { + // TODO proper sharing of memory with sh4 through DSPData + memset(dsp.MEMS, 0, sizeof(dsp.MEMS)); + } +} + +#endif diff --git a/core/hw/aica/sgc_if.cpp b/core/hw/aica/sgc_if.cpp index d6b570494..f02771120 100755 --- a/core/hw/aica/sgc_if.cpp +++ b/core/hw/aica/sgc_if.cpp @@ -1,4 +1,4 @@ -#include "sgc_if.h" +#include "sgc_if.h" #include "dsp.h" #include "aica_mem.h" #include "hw/aica/aica_if.h" @@ -1359,8 +1359,16 @@ void AICA_Sample() { VOLPAN(EXTS0L,dsp_out_vol[16].EFSDL,dsp_out_vol[16].EFPAN,mixl,mixr); VOLPAN(EXTS0R,dsp_out_vol[17].EFSDL,dsp_out_vol[17].EFPAN,mixl,mixr); + + DSPData->EXTS[0] = EXTS0L; + DSPData->EXTS[1] = EXTS0R; } - if (settings.aica.DSPEnabled) + else + { + DSPData->EXTS[0] = 0; + DSPData->EXTS[1] = 0; + } + //if (settings.aica.DSPEnabled) { dsp_step();