From 38b8a211aad8d2c485ccf0c0cbb58d965aac3483 Mon Sep 17 00:00:00 2001 From: notaz Date: Wed, 22 Nov 2023 00:02:50 +0200 Subject: [PATCH] apply cdrom volume in spu The previous sector delay thing breaks rhythm games. Also much easier to deal with timing in SPU code. --- frontend/plugin.c | 16 +------ libpcsxcore/cdrom.c | 90 ++++++++++++++++--------------------- libpcsxcore/decode_xa.h | 2 +- libpcsxcore/plugins.c | 8 +++- libpcsxcore/plugins.h | 8 ++-- plugins/dfsound/dma.h | 35 --------------- plugins/dfsound/externals.h | 18 +++----- plugins/dfsound/freeze.c | 6 +-- plugins/dfsound/psemuxa.h | 2 +- plugins/dfsound/spu.c | 20 +++++++-- plugins/dfsound/spu.h | 33 +++++++++----- plugins/dfsound/stdafx.h | 8 ++++ plugins/dfsound/xa.c | 60 ++++++++++++++++++++++--- plugins/spunull/spunull.c | 5 +++ 14 files changed, 169 insertions(+), 142 deletions(-) delete mode 100644 plugins/dfsound/dma.h diff --git a/frontend/plugin.c b/frontend/plugin.c index 88d756eb..c3c104af 100644 --- a/frontend/plugin.c +++ b/frontend/plugin.c @@ -46,20 +46,7 @@ static long CALLBACK CDRgetTE(unsigned char _, unsigned char *__, unsigned char static void CALLBACK GPUdisplayText(char *_) { return; } /* SPU */ -extern long CALLBACK SPUopen(void); -extern long CALLBACK SPUinit(void); -extern long CALLBACK SPUshutdown(void); -extern long CALLBACK SPUclose(void); -extern void CALLBACK SPUwriteRegister(unsigned long, unsigned short, unsigned int); -extern unsigned short CALLBACK SPUreadRegister(unsigned long, unsigned int); -extern void CALLBACK SPUwriteDMAMem(unsigned short *, int, unsigned int); -extern void CALLBACK SPUreadDMAMem(unsigned short *, int, unsigned int); -extern void CALLBACK SPUplayADPCMchannel(void *, unsigned int, int); -extern void CALLBACK SPUregisterCallback(void (*cb)(int)); -extern void CALLBACK SPUregisterScheduleCb(void (*cb)(unsigned int)); -extern long CALLBACK SPUfreeze(unsigned int, void *, unsigned int); -extern void CALLBACK SPUasync(unsigned int, unsigned int); -extern int CALLBACK SPUplayCDDAchannel(short *, int, unsigned int, int); +#include "../plugins/dfsound/spu.h" /* PAD */ static long CALLBACK PADinit(long _) { return 0; } @@ -191,6 +178,7 @@ static const struct { DIRECT_SPU(SPUregisterScheduleCb), DIRECT_SPU(SPUasync), DIRECT_SPU(SPUplayCDDAchannel), + DIRECT_SPU(SPUsetCDvol), /* PAD */ DIRECT_PAD(PADinit), DIRECT_PAD(PADshutdown), diff --git a/libpcsxcore/cdrom.c b/libpcsxcore/cdrom.c index 013be599..fac5fd39 100644 --- a/libpcsxcore/cdrom.c +++ b/libpcsxcore/cdrom.c @@ -633,7 +633,6 @@ static u32 cdrAlignTimingHack(u32 cycles) static void cdrUpdateTransferBuf(const u8 *buf); static void cdrReadInterrupt(void); static void cdrPrepCdda(s16 *buf, int samples); -static void cdrAttenuate(s16 *buf, int samples, int stereo); static void msfiAdd(u8 *msfi, u32 count) { @@ -693,9 +692,8 @@ void cdrPlayReadInterrupt(void) if (!cdr.IrqStat && (cdr.Mode & (MODE_AUTOPAUSE|MODE_REPORT))) cdrPlayInterrupt_Autopause(); - if (!cdr.Muted && cdr.Play && !Config.Cdda) { + if (cdr.Play && !Config.Cdda) { cdrPrepCdda(read_buf, CD_FRAMESIZE_RAW / 4); - cdrAttenuate(read_buf, CD_FRAMESIZE_RAW / 4, 1); SPU_playCDDAchannel(read_buf, CD_FRAMESIZE_RAW, psxRegs.cycle, 0); } @@ -933,6 +931,11 @@ void cdrInterrupt(void) { break; case CdlPause: + if (cdr.AdpcmActive) { + cdr.AdpcmActive = 0; + cdr.Xa.nsamples = 0; + SPU_playADPCMchannel(&cdr.Xa, psxRegs.cycle, 1); // flush adpcm + } StopCdda(); StopReading(); @@ -978,9 +981,11 @@ void cdrInterrupt(void) { StopReading(); SetPlaySeekRead(cdr.StatP, 0); cdr.LocL[0] = LOCL_INVALID; - cdr.Muted = FALSE; cdr.Mode = MODE_SIZE_2340; /* This fixes This is Football 2, Pooh's Party lockups */ cdr.DriveState = DRIVESTATE_PAUSED; + cdr.Muted = FALSE; + SPU_setCDvol(cdr.AttenuatorLeftToLeft, cdr.AttenuatorLeftToRight, + cdr.AttenuatorRightToLeft, cdr.AttenuatorRightToRight, psxRegs.cycle); second_resp_time = not_ready ? 70000 : 4100000; start_rotating = 1; break; @@ -992,10 +997,13 @@ void cdrInterrupt(void) { case CdlMute: cdr.Muted = TRUE; + SPU_setCDvol(0, 0, 0, 0, psxRegs.cycle); break; case CdlDemute: cdr.Muted = FALSE; + SPU_setCDvol(cdr.AttenuatorLeftToLeft, cdr.AttenuatorLeftToRight, + cdr.AttenuatorRightToLeft, cdr.AttenuatorRightToRight, psxRegs.cycle); break; case CdlSetfilter: @@ -1275,44 +1283,6 @@ static void cdrPrepCdda(s16 *buf, int samples) #endif } -static void cdrAttenuate(s16 *buf, int samples, int stereo) -{ - int i, l, r; - int ll = cdr.AttenuatorLeftToLeft; - int lr = cdr.AttenuatorLeftToRight; - int rl = cdr.AttenuatorRightToLeft; - int rr = cdr.AttenuatorRightToRight; - - if (lr == 0 && rl == 0 && 0x78 <= ll && ll <= 0x88 && 0x78 <= rr && rr <= 0x88) - return; - - if (!stereo && ll == 0x40 && lr == 0x40 && rl == 0x40 && rr == 0x40) - return; - - if (stereo) { - for (i = 0; i < samples; i++) { - l = buf[i * 2]; - r = buf[i * 2 + 1]; - l = (l * ll + r * rl) >> 7; - r = (r * rr + l * lr) >> 7; - ssat32_to_16(l); - ssat32_to_16(r); - buf[i * 2] = l; - buf[i * 2 + 1] = r; - } - } - else { - for (i = 0; i < samples; i++) { - l = buf[i]; - l = l * (ll + rl) >> 7; - //r = r * (rr + lr) >> 7; - ssat32_to_16(l); - //ssat32_to_16(r); - buf[i] = l; - } - } -} - static void cdrReadInterruptSetResult(unsigned char result) { if (cdr.IrqStat) { @@ -1346,6 +1316,7 @@ static void cdrReadInterrupt(void) int deliver_data = 1; u8 subqPos[3]; int read_ok; + int is_start; memcpy(subqPos, cdr.SetSectorPlay, sizeof(subqPos)); msfiAdd(subqPos, cdr.SubqForwardSectors); @@ -1407,12 +1378,10 @@ static void cdrReadInterrupt(void) if (Config.Xa) break; - if (!cdr.Muted && cdr.AdpcmActive) { - cdrAttenuate(cdr.Xa.pcm, cdr.Xa.nsamples, cdr.Xa.stereo); - SPU_playADPCMchannel(&cdr.Xa, psxRegs.cycle, 0); - } - // decode next - cdr.AdpcmActive = !xa_decode_sector(&cdr.Xa, buf + 4, !cdr.AdpcmActive); + is_start = !cdr.AdpcmActive; + cdr.AdpcmActive = !xa_decode_sector(&cdr.Xa, buf + 4, is_start); + if (cdr.AdpcmActive) + SPU_playADPCMchannel(&cdr.Xa, psxRegs.cycle, is_start); } while (0); if ((cdr.Mode & MODE_SF) && (subhdr->mode & 0x44) == 0x44) // according to nocash @@ -1567,6 +1536,7 @@ unsigned char cdrRead3(void) { void cdrWrite3(unsigned char rt) { const char *rnames[] = { "req", "ifl", "alr", "ava" }; (void)rnames; + u8 ll, lr, rl, rr; CDR_LOG_IO("cdr w3.%s: %02x\n", rnames[cdr.Ctrl & 3], rt); switch (cdr.Ctrl & 3) { @@ -1602,11 +1572,20 @@ void cdrWrite3(unsigned char rt) { cdr.AttenuatorLeftToRightT = rt; return; case 3: + if (rt & 0x01) + log_unhandled("Mute ADPCM?\n"); if (rt & 0x20) { - memcpy(&cdr.AttenuatorLeftToLeft, &cdr.AttenuatorLeftToLeftT, 4); - CDR_LOG("CD-XA Volume: %02x %02x | %02x %02x\n", - cdr.AttenuatorLeftToLeft, cdr.AttenuatorLeftToRight, - cdr.AttenuatorRightToLeft, cdr.AttenuatorRightToRight); + ll = cdr.AttenuatorLeftToLeftT; lr = cdr.AttenuatorLeftToRightT; + rl = cdr.AttenuatorRightToLeftT; rr = cdr.AttenuatorRightToRightT; + if (ll == cdr.AttenuatorLeftToLeft && + lr == cdr.AttenuatorLeftToRight && + rl == cdr.AttenuatorRightToLeft && + rr == cdr.AttenuatorRightToRight) + return; + cdr.AttenuatorLeftToLeftT = ll; cdr.AttenuatorLeftToRightT = lr; + cdr.AttenuatorRightToLeftT = rl; cdr.AttenuatorRightToRightT = rr; + CDR_LOG_I("CD-XA Volume: %02x %02x | %02x %02x\n", ll, lr, rl, rr); + SPU_setCDvol(ll, lr, rl, rr, psxRegs.cycle); } return; } @@ -1750,6 +1729,8 @@ void cdrReset() { cdr.AttenuatorLeftToRight = 0x00; cdr.AttenuatorRightToLeft = 0x00; cdr.AttenuatorRightToRight = 0x80; + SPU_setCDvol(cdr.AttenuatorLeftToLeft, cdr.AttenuatorLeftToRight, + cdr.AttenuatorRightToLeft, cdr.AttenuatorRightToRight, psxRegs.cycle); getCdInfo(); } @@ -1772,6 +1753,7 @@ int cdrFreeze(void *f, int Mode) { gzfreeze(&tmp, sizeof(tmp)); if (Mode == 0) { + u8 ll = 0, lr = 0, rl = 0, rr = 0; getCdInfo(); cdr.FifoOffset = tmp < DATA_SIZE ? tmp : DATA_SIZE; @@ -1794,6 +1776,10 @@ int cdrFreeze(void *f, int Mode) { if (!Config.Cdda) CDR_play(cdr.SetSectorPlay); } + if (!cdr.Muted) + ll = cdr.AttenuatorLeftToLeft, lr = cdr.AttenuatorLeftToLeft, + rl = cdr.AttenuatorRightToLeft, rr = cdr.AttenuatorRightToRight; + SPU_setCDvol(ll, lr, rl, rr, psxRegs.cycle); } return 0; diff --git a/libpcsxcore/decode_xa.h b/libpcsxcore/decode_xa.h index 54065356..2d85c931 100644 --- a/libpcsxcore/decode_xa.h +++ b/libpcsxcore/decode_xa.h @@ -30,7 +30,7 @@ typedef struct { s32 y0, y1; } ADPCM_Decode_t; -typedef struct { +typedef struct xa_decode { int freq; int nbits; int stereo; diff --git a/libpcsxcore/plugins.c b/libpcsxcore/plugins.c index 75e1f5fb..d7c2acb6 100644 --- a/libpcsxcore/plugins.c +++ b/libpcsxcore/plugins.c @@ -86,6 +86,7 @@ SPUregisterCallback SPU_registerCallback; SPUregisterScheduleCb SPU_registerScheduleCb; SPUasync SPU_async; SPUplayCDDAchannel SPU_playCDDAchannel; +SPUsetCDvol SPU_setCDvol; PADconfigure PAD1_configure; PADabout PAD1_about; @@ -179,7 +180,7 @@ static const char *err; #define LoadSym(dest, src, name, checkerr) { \ dest = (src)SysLoadSym(drv, name); \ - if (checkerr) { CheckErr(name); } else SysLibError(); \ + if (checkerr) { CheckErr(name); } \ } void *hGPUDriver = NULL; @@ -313,13 +314,15 @@ static int LoadCDRplugin(const char *CDRdll) { static void *hSPUDriver = NULL; static void CALLBACK SPU__registerScheduleCb(void (CALLBACK *cb)(unsigned int)) {} +static void CALLBACK SPU__setCDvol(unsigned char ll, unsigned char lr, + unsigned char rl, unsigned char rr, unsigned int cycle) {} #define LoadSpuSym1(dest, name) \ LoadSym(SPU_##dest, SPU##dest, name, TRUE); #define LoadSpuSym0(dest, name) \ LoadSym(SPU_##dest, SPU##dest, name, FALSE); \ - if (SPU_##dest == NULL) SPU_##dest = (SPU##dest) SPU__##dest; + if (SPU_##dest == NULL) SPU_##dest = SPU__##dest; #define LoadSpuSymN(dest, name) \ LoadSym(SPU_##dest, SPU##dest, name, FALSE); @@ -346,6 +349,7 @@ static int LoadSPUplugin(const char *SPUdll) { LoadSpuSym0(registerScheduleCb, "SPUregisterScheduleCb"); LoadSpuSymN(async, "SPUasync"); LoadSpuSymN(playCDDAchannel, "SPUplayCDDAchannel"); + LoadSpuSym0(setCDvol, "SPUsetCDvol"); return 0; } diff --git a/libpcsxcore/plugins.h b/libpcsxcore/plugins.h index 772452d0..5149d468 100644 --- a/libpcsxcore/plugins.h +++ b/libpcsxcore/plugins.h @@ -179,7 +179,7 @@ typedef struct { uint32_t PluginVersion; uint32_t Size; } SPUFreezeHdr_t; -typedef struct { +typedef struct SPUFreeze { unsigned char PluginName[8]; uint32_t PluginVersion; uint32_t Size; @@ -188,9 +188,10 @@ typedef struct { xa_decode_t xa; unsigned char *unused; } SPUFreeze_t; -typedef long (CALLBACK* SPUfreeze)(uint32_t, SPUFreeze_t *, uint32_t); -typedef void (CALLBACK* SPUasync)(uint32_t, uint32_t); +typedef long (CALLBACK* SPUfreeze)(unsigned int, struct SPUFreeze *, unsigned int); +typedef void (CALLBACK* SPUasync)(unsigned int, unsigned int); typedef int (CALLBACK* SPUplayCDDAchannel)(short *, int, unsigned int, int); +typedef void (CALLBACK* SPUsetCDvol)(unsigned char, unsigned char, unsigned char, unsigned char, unsigned int); // SPU function pointers extern SPUinit SPU_init; @@ -207,6 +208,7 @@ extern SPUregisterCallback SPU_registerCallback; extern SPUregisterScheduleCb SPU_registerScheduleCb; extern SPUasync SPU_async; extern SPUplayCDDAchannel SPU_playCDDAchannel; +extern SPUsetCDvol SPU_setCDvol; // PAD Functions typedef long (CALLBACK* PADconfigure)(void); diff --git a/plugins/dfsound/dma.h b/plugins/dfsound/dma.h deleted file mode 100644 index 4982432b..00000000 --- a/plugins/dfsound/dma.h +++ /dev/null @@ -1,35 +0,0 @@ -/*************************************************************************** - dma.h - description - ------------------- - begin : Wed May 15 2002 - copyright : (C) 2002 by Pete Bernert - email : BlackDove@addcom.de - ***************************************************************************/ - -/*************************************************************************** - * * - * This program 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 2 of the License, or * - * (at your option) any later version. See also the license.txt file for * - * additional informations. * - * * - ***************************************************************************/ - -//*************************************************************************// -// History of changes: -// -// 2002/05/15 - Pete -// - generic cleanup for the Peops release -// -//*************************************************************************// - -#ifndef __P_DMA_H__ -#define __P_DMA_H__ - -unsigned short CALLBACK SPUreadDMA(void); -void CALLBACK SPUreadDMAMem(unsigned short * pusPSXMem,int iSize); -void CALLBACK SPUwriteDMA(unsigned short val); -void CALLBACK SPUwriteDMAMem(unsigned short * pusPSXMem,int iSize); - -#endif /* __P_DMA_H__ */ diff --git a/plugins/dfsound/externals.h b/plugins/dfsound/externals.h index fef5f9cc..e85c191b 100644 --- a/plugins/dfsound/externals.h +++ b/plugins/dfsound/externals.h @@ -89,17 +89,6 @@ typedef struct /////////////////////////////////////////////////////////// -// Tmp Flags - -// used for debug channel muting -#define FLAG_MUTE 1 - -// used for simple interpolation -#define FLAG_IPOL0 2 -#define FLAG_IPOL1 4 - -/////////////////////////////////////////////////////////// - // MAIN CHANNEL STRUCT typedef struct { @@ -225,6 +214,10 @@ typedef struct int iLeftXAVol; int iRightXAVol; + struct { // channel volume in the cd controller + unsigned char ll, lr, rl, rr; // see cdr.Attenuator* in cdrom.c + } cdv; // applied on spu side for easier emulation + unsigned int last_keyon_cycles; union { @@ -289,4 +282,7 @@ void do_irq_io(int cycles_after); #endif +void FeedXA(const xa_decode_t *xap); +void FeedCDDA(unsigned char *pcm, int nBytes); + #endif /* __P_SOUND_EXTERNALS_H__ */ diff --git a/plugins/dfsound/freeze.c b/plugins/dfsound/freeze.c index 32c07dbd..f56c8834 100644 --- a/plugins/dfsound/freeze.c +++ b/plugins/dfsound/freeze.c @@ -107,7 +107,7 @@ typedef struct ADSRInfoEx_orig ADSRX; // next ADSR settings (will be moved to active on sample start) } SPUCHAN_orig; -typedef struct +typedef struct SPUFreeze { char szSPUName[8]; uint32_t ulFreezeVersion; @@ -236,8 +236,8 @@ static void load_register(unsigned long reg, unsigned int cycles) // SPUFREEZE: called by main emu on savestate load/save //////////////////////////////////////////////////////////////////////// -long CALLBACK SPUfreeze(uint32_t ulFreezeMode, SPUFreeze_t * pF, - uint32_t cycles) +long CALLBACK SPUfreeze(unsigned int ulFreezeMode, SPUFreeze_t * pF, + unsigned int cycles) { SPUOSSFreeze_t * pFO = NULL; int i; diff --git a/plugins/dfsound/psemuxa.h b/plugins/dfsound/psemuxa.h index 402d2733..11b748df 100644 --- a/plugins/dfsound/psemuxa.h +++ b/plugins/dfsound/psemuxa.h @@ -11,7 +11,7 @@ typedef struct int y0, y1; } ADPCM_Decode_t; -typedef struct +typedef struct xa_decode { int freq; int nbits; diff --git a/plugins/dfsound/spu.c b/plugins/dfsound/spu.c index 7501df8b..1cc1cbf9 100644 --- a/plugins/dfsound/spu.c +++ b/plugins/dfsound/spu.c @@ -27,6 +27,7 @@ #include "registers.h" #include "out.h" #include "spu_config.h" +#include "spu.h" #ifdef __arm__ #include "arm_features.h" @@ -835,7 +836,7 @@ static void do_channels(int ns_to) mix_chan(spu.SSumLR, ns_to, s_chan->iLeftVolume, s_chan->iRightVolume); } - MixXA(spu.SSumLR, RVB, ns_to, spu.decode_pos); + MixCD(spu.SSumLR, RVB, ns_to, spu.decode_pos); if (spu.rvb->StartAddr) { if (do_rvb) @@ -1112,7 +1113,7 @@ static void sync_worker_thread(int force) work = &worker->i[worker->i_reaped & WORK_I_MASK]; thread_work_wait_sync(work, force); - MixXA(work->SSumLR, RVB, work->ns_to, work->decode_pos); + MixCD(work->SSumLR, RVB, work->ns_to, work->decode_pos); do_samples_finish(work->SSumLR, work->ns_to, work->channels_silent, work->decode_pos); @@ -1351,11 +1352,13 @@ void CALLBACK SPUupdate(void) // XA AUDIO -void CALLBACK SPUplayADPCMchannel(xa_decode_t *xap, unsigned int cycle, int unused) +void CALLBACK SPUplayADPCMchannel(xa_decode_t *xap, unsigned int cycle, int is_start) { if(!xap) return; if(!xap->freq) return; // no xa freq ? bye + if (is_start) + spu.XAPlay = spu.XAFeed = spu.XAStart; if (spu.XAPlay == spu.XAFeed) do_samples(cycle, 1); // catch up to prevent source underflows later @@ -1376,6 +1379,17 @@ int CALLBACK SPUplayCDDAchannel(short *pcm, int nbytes, unsigned int cycle, int return 0; } +void CALLBACK SPUsetCDvol(unsigned char ll, unsigned char lr, + unsigned char rl, unsigned char rr, unsigned int cycle) +{ + if (spu.XAPlay != spu.XAFeed || spu.CDDAPlay != spu.CDDAFeed) + do_samples(cycle, 1); + spu.cdv.ll = ll; + spu.cdv.lr = lr; + spu.cdv.rl = rl; + spu.cdv.rr = rr; +} + // to be called after state load void ClearWorkingState(void) { diff --git a/plugins/dfsound/spu.h b/plugins/dfsound/spu.h index 810ec07d..d49d9033 100644 --- a/plugins/dfsound/spu.h +++ b/plugins/dfsound/spu.h @@ -18,18 +18,29 @@ #ifndef __P_SPU_H__ #define __P_SPU_H__ -#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ -#define HTOLE16(x) __builtin_bswap16(x) -#define LE16TOH(x) __builtin_bswap16(x) -#else -#define HTOLE16(x) (x) -#define LE16TOH(x) (x) -#endif +struct SPUFreeze; +struct xa_decode; -void ClearWorkingState(void); -void CALLBACK SPUplayADPCMchannel(xa_decode_t *xap, unsigned int cycle, int is_start); +long CALLBACK SPUopen(void); +long CALLBACK SPUinit(void); +long CALLBACK SPUshutdown(void); +long CALLBACK SPUclose(void); +void CALLBACK SPUwriteRegister(unsigned long, unsigned short, unsigned int); +unsigned short CALLBACK SPUreadRegister(unsigned long, unsigned int); +void CALLBACK SPUregisterCallback(void (*cb)(int)); +void CALLBACK SPUregisterScheduleCb(void (*cb)(unsigned int)); +long CALLBACK SPUfreeze(unsigned int, struct SPUFreeze *, unsigned int); +void CALLBACK SPUasync(unsigned int, unsigned int); + +void CALLBACK SPUreadDMAMem(unsigned short * pusPSXMem,int iSize,unsigned int cycles); +void CALLBACK SPUwriteDMAMem(unsigned short * pusPSXMem,int iSize,unsigned int cycles); + +void CALLBACK SPUplayADPCMchannel(struct xa_decode *xap, unsigned int cycle, int is_start); int CALLBACK SPUplayCDDAchannel(short *pcm, int bytes, unsigned int cycle, int is_start); -void FeedXA(const xa_decode_t *xap); -void FeedCDDA(unsigned char *pcm, int nBytes); +void CALLBACK SPUsetCDvol(unsigned char ll, unsigned char lr, + unsigned char rl, unsigned char rr, unsigned int cycle); + +// internal +void ClearWorkingState(void); #endif /* __P_SPU_H__ */ diff --git a/plugins/dfsound/stdafx.h b/plugins/dfsound/stdafx.h index 96335e38..ff082bc8 100644 --- a/plugins/dfsound/stdafx.h +++ b/plugins/dfsound/stdafx.h @@ -32,6 +32,14 @@ #define INLINE static inline #endif +#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ +#define HTOLE16(x) __builtin_bswap16(x) +#define LE16TOH(x) __builtin_bswap16(x) +#else +#define HTOLE16(x) (x) +#define LE16TOH(x) (x) +#endif + #include "psemuxa.h" #endif /* __P_STDAFX_H__ */ diff --git a/plugins/dfsound/xa.c b/plugins/dfsound/xa.c index b3ac01d9..e3a9fb61 100644 --- a/plugins/dfsound/xa.c +++ b/plugins/dfsound/xa.c @@ -39,13 +39,55 @@ static int gauss_window[8] = {0, 0, 0, 0, 0, 0, 0, 0}; // MIX XA & CDDA //////////////////////////////////////////////////////////////////////// -INLINE void MixXA(int *SSumLR, int *RVB, int ns_to, int decode_pos) +INLINE void SkipCD(int ns_to, int decode_pos) { int cursor = decode_pos; int ns; - short l, r; + + if(spu.XAPlay != spu.XAFeed) + { + for(ns = 0; ns < ns_to*2; ns += 2) + { + if(spu.XAPlay != spu.XAFeed) spu.XAPlay++; + if(spu.XAPlay == spu.XAEnd) spu.XAPlay=spu.XAStart; + + spu.spuMem[cursor] = 0; + spu.spuMem[cursor + 0x400/2] = 0; + cursor = (cursor + 1) & 0x1ff; + } + } + else if(spu.CDDAPlay != spu.CDDAFeed) + { + for(ns = 0; ns < ns_to*2; ns += 2) + { + if(spu.CDDAPlay != spu.CDDAFeed) spu.CDDAPlay++; + if(spu.CDDAPlay == spu.CDDAEnd) spu.CDDAPlay=spu.CDDAStart; + + spu.spuMem[cursor] = 0; + spu.spuMem[cursor + 0x400/2] = 0; + cursor = (cursor + 1) & 0x1ff; + } + } + spu.XALastVal = 0; +} + +INLINE void MixCD(int *SSumLR, int *RVB, int ns_to, int decode_pos) +{ + int vll = spu.iLeftXAVol * spu.cdv.ll >> 7; + int vrl = spu.iLeftXAVol * spu.cdv.rl >> 7; + int vlr = spu.iRightXAVol * spu.cdv.lr >> 7; + int vrr = spu.iRightXAVol * spu.cdv.rr >> 7; + int cursor = decode_pos; + int l1, r1, l, r; + int ns; uint32_t v = spu.XALastVal; + if ((vll | vlr | vrl | vrr) == 0) + { + SkipCD(ns_to, decode_pos); + return; + } + if(spu.XAPlay != spu.XAFeed || spu.XARepeat > 0) { if(spu.XAPlay == spu.XAFeed) @@ -56,8 +98,11 @@ INLINE void MixXA(int *SSumLR, int *RVB, int ns_to, int decode_pos) if(spu.XAPlay != spu.XAFeed) v=*spu.XAPlay++; if(spu.XAPlay == spu.XAEnd) spu.XAPlay=spu.XAStart; - l = ((int)(short)v * spu.iLeftXAVol) >> 15; - r = ((int)(short)(v >> 16) * spu.iLeftXAVol) >> 15; + l1 = (short)v, r1 = (short)(v >> 16); + l = (l1 * vll + r1 * vrl) >> 15; + r = (r1 * vrr + l1 * vlr) >> 15; + ssat32_to_16(l); + ssat32_to_16(r); if (spu.spuCtrl & CTRL_CD) { SSumLR[ns+0] += l; @@ -84,8 +129,11 @@ INLINE void MixXA(int *SSumLR, int *RVB, int ns_to, int decode_pos) if(spu.CDDAPlay != spu.CDDAFeed) v=*spu.CDDAPlay++; if(spu.CDDAPlay == spu.CDDAEnd) spu.CDDAPlay=spu.CDDAStart; - l = ((int)(short)v * spu.iLeftXAVol) >> 15; - r = ((int)(short)(v >> 16) * spu.iLeftXAVol) >> 15; + l1 = (short)v, r1 = (short)(v >> 16); + l = (l1 * vll + r1 * vrl) >> 15; + r = (r1 * vrr + l1 * vlr) >> 15; + ssat32_to_16(l); + ssat32_to_16(r); if (spu.spuCtrl & CTRL_CD) { SSumLR[ns+0] += l; diff --git a/plugins/spunull/spunull.c b/plugins/spunull/spunull.c index ece5db93..7f16ed5e 100644 --- a/plugins/spunull/spunull.c +++ b/plugins/spunull/spunull.c @@ -284,6 +284,11 @@ void CALLBACK SPUplayADPCMchannel(xa_decode_t *xap) { } +void CALLBACK SPUsetCDvol(unsigned char ll, unsigned char lr, + unsigned char rl, unsigned char rr, unsigned int cycle) +{ +} + //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// -- 2.39.2