apply cdrom volume in spu
authornotaz <notasas@gmail.com>
Tue, 21 Nov 2023 22:02:50 +0000 (00:02 +0200)
committernotaz <notasas@gmail.com>
Tue, 21 Nov 2023 23:08:25 +0000 (01:08 +0200)
The previous sector delay thing breaks rhythm games.
Also much easier to deal with timing in SPU code.

14 files changed:
frontend/plugin.c
libpcsxcore/cdrom.c
libpcsxcore/decode_xa.h
libpcsxcore/plugins.c
libpcsxcore/plugins.h
plugins/dfsound/dma.h [deleted file]
plugins/dfsound/externals.h
plugins/dfsound/freeze.c
plugins/dfsound/psemuxa.h
plugins/dfsound/spu.c
plugins/dfsound/spu.h
plugins/dfsound/stdafx.h
plugins/dfsound/xa.c
plugins/spunull/spunull.c

index 88d756e..c3c104a 100644 (file)
@@ -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),
index 013be59..fac5fd3 100644 (file)
@@ -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;
index 5406535..2d85c93 100644 (file)
@@ -30,7 +30,7 @@ typedef struct {
        s32     y0, y1;
 } ADPCM_Decode_t;
 
-typedef struct {
+typedef struct xa_decode {
        int                             freq;
        int                             nbits;
        int                             stereo;
index 75e1f5f..d7c2acb 100644 (file)
@@ -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;\r
 static void CALLBACK SPU__registerScheduleCb(void (CALLBACK *cb)(unsigned int)) {}\r
+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;
 }
index 772452d..5149d46 100644 (file)
@@ -179,7 +179,7 @@ typedef struct {
        uint32_t PluginVersion;\r
        uint32_t Size;\r
 } SPUFreezeHdr_t;\r
-typedef struct {\r
+typedef struct SPUFreeze {\r
        unsigned char PluginName[8];\r
        uint32_t PluginVersion;\r
        uint32_t Size;\r
@@ -188,9 +188,10 @@ typedef struct {
        xa_decode_t xa;\r
        unsigned char *unused;\r
 } SPUFreeze_t;\r
-typedef long (CALLBACK* SPUfreeze)(uint32_t, SPUFreeze_t *, uint32_t);\r
-typedef void (CALLBACK* SPUasync)(uint32_t, uint32_t);\r
+typedef long (CALLBACK* SPUfreeze)(unsigned int, struct SPUFreeze *, unsigned int);\r
+typedef void (CALLBACK* SPUasync)(unsigned int, unsigned int);\r
 typedef int  (CALLBACK* SPUplayCDDAchannel)(short *, int, unsigned int, int);\r
+typedef void (CALLBACK* SPUsetCDvol)(unsigned char, unsigned char, unsigned char, unsigned char, unsigned int);\r
 \r
 // SPU function pointers\r
 extern SPUinit             SPU_init;\r
@@ -207,6 +208,7 @@ extern SPUregisterCallback SPU_registerCallback;
 extern SPUregisterScheduleCb SPU_registerScheduleCb;\r
 extern SPUasync            SPU_async;\r
 extern SPUplayCDDAchannel  SPU_playCDDAchannel;\r
+extern SPUsetCDvol         SPU_setCDvol;\r
 \r
 // PAD Functions\r
 typedef long (CALLBACK* PADconfigure)(void);\r
diff --git a/plugins/dfsound/dma.h b/plugins/dfsound/dma.h
deleted file mode 100644 (file)
index 4982432..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-/***************************************************************************\r
-                            dma.h  -  description\r
-                             -------------------\r
-    begin                : Wed May 15 2002\r
-    copyright            : (C) 2002 by Pete Bernert\r
-    email                : BlackDove@addcom.de\r
- ***************************************************************************/\r
-\r
-/***************************************************************************\r
- *                                                                         *\r
- *   This program is free software; you can redistribute it and/or modify  *\r
- *   it under the terms of the GNU General Public License as published by  *\r
- *   the Free Software Foundation; either version 2 of the License, or     *\r
- *   (at your option) any later version. See also the license.txt file for *\r
- *   additional informations.                                              *\r
- *                                                                         *\r
- ***************************************************************************/\r
-\r
-//*************************************************************************//\r
-// History of changes:\r
-//\r
-// 2002/05/15 - Pete\r
-// - generic cleanup for the Peops release\r
-//\r
-//*************************************************************************//\r
-\r
-#ifndef __P_DMA_H__\r
-#define __P_DMA_H__\r
-\r
-unsigned short CALLBACK SPUreadDMA(void);\r
-void CALLBACK SPUreadDMAMem(unsigned short * pusPSXMem,int iSize);\r
-void CALLBACK SPUwriteDMA(unsigned short val);\r
-void CALLBACK SPUwriteDMAMem(unsigned short * pusPSXMem,int iSize);\r
-\r
-#endif /* __P_DMA_H__ */\r
index fef5f9c..e85c191 100644 (file)
@@ -89,17 +89,6 @@ typedef struct
               \r
 ///////////////////////////////////////////////////////////\r
 \r
-// Tmp Flags\r
-\r
-// used for debug channel muting\r
-#define FLAG_MUTE  1\r
-\r
-// used for simple interpolation\r
-#define FLAG_IPOL0 2\r
-#define FLAG_IPOL1 4\r
-\r
-///////////////////////////////////////////////////////////\r
-\r
 // MAIN CHANNEL STRUCT\r
 typedef struct\r
 {\r
@@ -225,6 +214,10 @@ typedef struct
  int             iLeftXAVol;\r
  int             iRightXAVol;\r
 \r
+ struct {                              // channel volume in the cd controller\r
+  unsigned char  ll, lr, rl, rr;       // see cdr.Attenuator* in cdrom.c\r
+ } cdv;                                // applied on spu side for easier emulation\r
+\r
  unsigned int    last_keyon_cycles;\r
 \r
  union {\r
@@ -289,4 +282,7 @@ void do_irq_io(int cycles_after);
 \r
 #endif\r
 \r
+void FeedXA(const xa_decode_t *xap);\r
+void FeedCDDA(unsigned char *pcm, int nBytes);\r
+\r
 #endif /* __P_SOUND_EXTERNALS_H__ */\r
index 32c07db..f56c883 100644 (file)
@@ -107,7 +107,7 @@ typedef struct
  ADSRInfoEx_orig   ADSRX;                              // next ADSR settings (will be moved to active on sample start)\r
 } SPUCHAN_orig;\r
 \r
-typedef struct\r
+typedef struct SPUFreeze\r
 {\r
  char          szSPUName[8];\r
  uint32_t ulFreezeVersion;\r
@@ -236,8 +236,8 @@ static void load_register(unsigned long reg, unsigned int cycles)
 // SPUFREEZE: called by main emu on savestate load/save\r
 ////////////////////////////////////////////////////////////////////////\r
 \r
-long CALLBACK SPUfreeze(uint32_t ulFreezeMode, SPUFreeze_t * pF,\r
- uint32_t cycles)\r
+long CALLBACK SPUfreeze(unsigned int ulFreezeMode, SPUFreeze_t * pF,\r
+ unsigned int cycles)\r
 {\r
  SPUOSSFreeze_t * pFO = NULL;\r
  int i;\r
index 402d273..11b748d 100644 (file)
@@ -11,7 +11,7 @@ typedef struct
        int     y0, y1;\r
 } ADPCM_Decode_t;\r
 \r
-typedef struct\r
+typedef struct xa_decode\r
 {                                                                   \r
        int                             freq;\r
        int                             nbits;\r
index 7501df8..1cc1cbf 100644 (file)
@@ -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)
 {
index 810ec07..d49d903 100644 (file)
 #ifndef __P_SPU_H__\r
 #define __P_SPU_H__\r
 \r
-#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__\r
-#define HTOLE16(x) __builtin_bswap16(x)\r
-#define LE16TOH(x) __builtin_bswap16(x)\r
-#else\r
-#define HTOLE16(x) (x)\r
-#define LE16TOH(x) (x)\r
-#endif\r
+struct SPUFreeze;\r
+struct xa_decode;\r
 \r
-void ClearWorkingState(void);\r
-void CALLBACK SPUplayADPCMchannel(xa_decode_t *xap, unsigned int cycle, int is_start);\r
+long CALLBACK SPUopen(void);\r
+long CALLBACK SPUinit(void);\r
+long CALLBACK SPUshutdown(void);\r
+long CALLBACK SPUclose(void);\r
+void CALLBACK SPUwriteRegister(unsigned long, unsigned short, unsigned int);\r
+unsigned short CALLBACK SPUreadRegister(unsigned long, unsigned int);\r
+void CALLBACK SPUregisterCallback(void (*cb)(int));\r
+void CALLBACK SPUregisterScheduleCb(void (*cb)(unsigned int));\r
+long CALLBACK SPUfreeze(unsigned int, struct SPUFreeze *, unsigned int);\r
+void CALLBACK SPUasync(unsigned int, unsigned int);\r
+\r
+void CALLBACK SPUreadDMAMem(unsigned short * pusPSXMem,int iSize,unsigned int cycles);\r
+void CALLBACK SPUwriteDMAMem(unsigned short * pusPSXMem,int iSize,unsigned int cycles);\r
+\r
+void CALLBACK SPUplayADPCMchannel(struct xa_decode *xap, unsigned int cycle, int is_start);\r
 int  CALLBACK SPUplayCDDAchannel(short *pcm, int bytes, unsigned int cycle, int is_start);\r
-void FeedXA(const xa_decode_t *xap);\r
-void FeedCDDA(unsigned char *pcm, int nBytes);\r
+void CALLBACK SPUsetCDvol(unsigned char ll, unsigned char lr,\r
+               unsigned char rl, unsigned char rr, unsigned int cycle);\r
+\r
+// internal\r
+void ClearWorkingState(void);\r
 \r
 #endif /* __P_SPU_H__ */\r
index 96335e3..ff082bc 100644 (file)
 #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__ */
index b3ac01d..e3a9fb6 100644 (file)
@@ -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;
index ece5db9..7f16ed5 100644 (file)
@@ -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)
+{
+}
+
 ////////////////////////////////////////////////////////////////////////
 
 ////////////////////////////////////////////////////////////////////////