mirror of
https://github.com/PCSX2/pcsx2.git
synced 2025-12-16 04:08:48 +00:00
Compare commits
5 Commits
2a1909e439
...
09715b10e0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
09715b10e0 | ||
|
|
7fab935c2d | ||
|
|
8328b4e278 | ||
|
|
77dd916a6b | ||
|
|
b1cc005316 |
File diff suppressed because it is too large
Load Diff
@ -9360,6 +9360,8 @@ TRANSLATE_NOOP("FullscreenUI", "Reset System");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Hardcore mode will not be enabled until the system is reset. Do you want to reset the system now?");
|
||||
TRANSLATE_NOOP("FullscreenUI", "This game has no achievements.");
|
||||
TRANSLATE_NOOP("FullscreenUI", "This game has no leaderboards.");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Failed to Load State");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Failed to Save State");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Game List");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Launch a game from images scanned from your game directories.");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Start Game");
|
||||
@ -9405,7 +9407,7 @@ TRANSLATE_NOOP("FullscreenUI", "Selects the color style to be used for Big Pictu
|
||||
TRANSLATE_NOOP("FullscreenUI", "When Big Picture mode is started, the game list will be displayed instead of the main menu.");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Show a save state selector UI when switching slots instead of showing a notification bubble.");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Background");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Select a custom background image to use in Big Picture Mode menus.");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Select a custom background image to use in Big Picture Mode menus.\n\nSupported formats: PNG, JPG, JPEG, BMP.");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Removes the custom background image.");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Sets the transparency of the custom background image.");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Select how to display the background image.");
|
||||
@ -9415,6 +9417,7 @@ TRANSLATE_NOOP("FullscreenUI", "Pauses the emulator when a game is started.");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Pauses the emulator when you minimize the window or switch to another application, and unpauses when you switch back.");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Pauses the emulator when a controller with bindings is disconnected.");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Pauses the emulator when you open the quick menu, and unpauses when you close it.");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Display a modal dialog when a save state load/save operation fails.");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Determines whether a prompt will be displayed to confirm shutting down the emulator/game when the hotkey is pressed.");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Automatically saves the emulator state when powering down or exiting. You can then resume directly from where you left off next time.");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Creates a backup copy of a save state if it already exists when the save is created. The backup copy has a .backup suffix");
|
||||
@ -9424,6 +9427,7 @@ TRANSLATE_NOOP("FullscreenUI", "Game Display");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Automatically switches to fullscreen mode when a game is started.");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Switches between full screen and windowed when the window is double-clicked.");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Hides the mouse pointer/cursor when the emulator is in fullscreen mode.");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Automatically starts Big Picture Mode instead of the regular Qt interface when PCSX2 launches.");
|
||||
TRANSLATE_NOOP("FullscreenUI", "On-Screen Display");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Determines how large the on-screen messages and monitors are.");
|
||||
TRANSLATE_NOOP("FullscreenUI", "%d%%");
|
||||
@ -9849,6 +9853,9 @@ TRANSLATE_NOOP("FullscreenUI", "Last Played: {}");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Size: {:.2f} MB");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Are you sure you want to reset the play time for '{}' ({})?\n\nYour current play time is {}.\n\nThis action cannot be undone.");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Login failed.\nError: {}\n\nPlease check your username and password, and try again.");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Failed to Load State From Backup Slot {}");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Failed to Load State From Slot {}");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Failed to Save State To Slot {}");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Left: ");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Top: ");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Right: ");
|
||||
@ -9882,13 +9889,14 @@ TRANSLATE_NOOP("FullscreenUI", "AMOLED");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Fit");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Fill");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Stretch");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Center");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Tile");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Enabled");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Disabled");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Top Left");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Top Center");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Top Right");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Center Left");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Center");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Center Right");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Bottom Left");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Bottom Center");
|
||||
@ -10108,6 +10116,7 @@ TRANSLATE_NOOP("FullscreenUI", "Pause On Start");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Pause On Focus Loss");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Pause On Controller Disconnection");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Pause On Menu");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Prompt On State Load/Save Failure");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Confirm Shutdown");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Save State On Shutdown");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Create Save State Backups");
|
||||
@ -10117,6 +10126,7 @@ TRANSLATE_NOOP("FullscreenUI", "Enable Discord Presence");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Start Fullscreen");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Double-Click Toggles Fullscreen");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Hide Cursor In Fullscreen");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Start Big Picture UI");
|
||||
TRANSLATE_NOOP("FullscreenUI", "OSD Scale");
|
||||
TRANSLATE_NOOP("FullscreenUI", "OSD Messages Position");
|
||||
TRANSLATE_NOOP("FullscreenUI", "OSD Performance Position");
|
||||
@ -10297,7 +10307,6 @@ TRANSLATE_NOOP("FullscreenUI", "Delete Save");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Close Menu");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Default Boot");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Delete State");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Failed to Load State");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Full Boot");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Reset Play Time");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Confirm Reset");
|
||||
|
||||
@ -200,7 +200,6 @@ void SPU2::DoFullDump()
|
||||
fprintf(dump, " - Sound Start Address: %x\n", Cores[c].Voices[v].StartA);
|
||||
fprintf(dump, " - Next Data Address: %x\n", Cores[c].Voices[v].NextA);
|
||||
fprintf(dump, " - Play Status: %s\n", (Cores[c].Voices[v].ADSR.Phase > 0) ? "Playing" : "Not Playing");
|
||||
fprintf(dump, " - Block Sample: %d\n", Cores[c].Voices[v].SCurrent);
|
||||
}
|
||||
fprintf(dump, "#### END OF DUMP.\n\n");
|
||||
}
|
||||
|
||||
@ -89,55 +89,13 @@ int g_counter_cache_ignores = 0;
|
||||
#define XAFLAG_LOOP (1ul << 1)
|
||||
#define XAFLAG_LOOP_START (1ul << 2)
|
||||
|
||||
static __forceinline s32 GetNextDataBuffered(V_Core& thiscore, uint voiceidx)
|
||||
static __forceinline void GetNextDataBuffered(V_Core& thiscore, uint voiceidx)
|
||||
{
|
||||
V_Voice& vc(thiscore.Voices[voiceidx]);
|
||||
|
||||
if ((vc.SCurrent & 3) == 0)
|
||||
if (vc.SBuffer == nullptr)
|
||||
{
|
||||
IncrementNextA(thiscore, voiceidx);
|
||||
|
||||
if ((vc.NextA & 7) == 0) // vc.SCurrent == 24 equivalent
|
||||
{
|
||||
if (vc.LoopFlags & XAFLAG_LOOP_END)
|
||||
{
|
||||
thiscore.Regs.ENDX |= (1 << voiceidx);
|
||||
vc.NextA = vc.LoopStartA | 1;
|
||||
if (!(vc.LoopFlags & XAFLAG_LOOP))
|
||||
{
|
||||
vc.Stop();
|
||||
|
||||
if (IsDevBuild)
|
||||
{
|
||||
if (SPU2::MsgVoiceOff())
|
||||
SPU2::ConLog("* SPU2: Voice Off by EndPoint: %d \n", voiceidx);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
vc.NextA++; // no, don't IncrementNextA here. We haven't read the header yet.
|
||||
}
|
||||
}
|
||||
|
||||
if (vc.SCurrent == 28)
|
||||
{
|
||||
vc.SCurrent = 0;
|
||||
|
||||
// We'll need the loop flags and buffer pointers regardless of cache status:
|
||||
|
||||
for (int i = 0; i < 2; i++)
|
||||
if (Cores[i].IRQEnable && Cores[i].IRQA == (vc.NextA & 0xFFFF8))
|
||||
SetIrqCall(i);
|
||||
|
||||
s16* memptr = GetMemPtr(vc.NextA & 0xFFFF8);
|
||||
vc.LoopFlags = *memptr >> 8; // grab loop flags from the upper byte.
|
||||
|
||||
if ((vc.LoopFlags & XAFLAG_LOOP_START) && !vc.LoopMode)
|
||||
{
|
||||
vc.LoopStartA = vc.NextA & 0xFFFF8;
|
||||
}
|
||||
|
||||
const int cacheIdx = vc.NextA / pcm_WordsPerBlock;
|
||||
const int cacheIdx = (vc.NextA & 0xFFFF8) / pcm_WordsPerBlock;
|
||||
PcmCacheEntry& cacheLine = pcm_cache_data[cacheIdx];
|
||||
vc.SBuffer = cacheLine.Sampledata;
|
||||
|
||||
@ -172,46 +130,18 @@ static __forceinline s32 GetNextDataBuffered(V_Core& thiscore, uint voiceidx)
|
||||
g_counter_cache_misses++;
|
||||
}
|
||||
|
||||
|
||||
s16* memptr = GetMemPtr(vc.NextA & 0xFFFF8);
|
||||
XA_decode_block(vc.SBuffer, memptr, vc.Prev1, vc.Prev2);
|
||||
}
|
||||
}
|
||||
|
||||
return vc.SBuffer[vc.SCurrent++];
|
||||
}
|
||||
|
||||
static __forceinline void GetNextDataDummy(V_Core& thiscore, uint voiceidx)
|
||||
{
|
||||
V_Voice& vc(thiscore.Voices[voiceidx]);
|
||||
|
||||
IncrementNextA(thiscore, voiceidx);
|
||||
|
||||
if ((vc.NextA & 7) == 0) // vc.SCurrent == 24 equivalent
|
||||
// Get the sample index for NextA, we have to subtract 1 to ignore the loop header
|
||||
int sampleIdx = ((vc.NextA % pcm_WordsPerBlock) - 1) * 4;
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
if (vc.LoopFlags & XAFLAG_LOOP_END)
|
||||
{
|
||||
thiscore.Regs.ENDX |= (1 << voiceidx);
|
||||
vc.NextA = vc.LoopStartA | 1;
|
||||
}
|
||||
else
|
||||
vc.NextA++; // no, don't IncrementNextA here. We haven't read the header yet.
|
||||
vc.DecodeFifo[(vc.DecPosWrite + i) % 32] = vc.SBuffer[sampleIdx + i];
|
||||
}
|
||||
|
||||
if (vc.SCurrent == 28)
|
||||
{
|
||||
for (int i = 0; i < 2; i++)
|
||||
if (Cores[i].IRQEnable && Cores[i].IRQA == (vc.NextA & 0xFFFF8))
|
||||
SetIrqCall(i);
|
||||
|
||||
vc.LoopFlags = *GetMemPtr(vc.NextA & 0xFFFF8) >> 8; // grab loop flags from the upper byte.
|
||||
|
||||
if ((vc.LoopFlags & XAFLAG_LOOP_START) && !vc.LoopMode)
|
||||
vc.LoopStartA = vc.NextA & 0xFFFF8;
|
||||
|
||||
vc.SCurrent = 0;
|
||||
}
|
||||
|
||||
vc.SP -= 0x1000 * (4 - (vc.SCurrent & 3));
|
||||
vc.SCurrent += 4 - (vc.SCurrent & 3);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
@ -237,6 +167,69 @@ static __forceinline StereoOut32 ApplyVolume(const StereoOut32& data, const V_Vo
|
||||
ApplyVolume(data.Right, volume.Right.Value));
|
||||
}
|
||||
|
||||
static __forceinline void UpdateBlockHeader(V_Core& thiscore, uint voiceidx)
|
||||
{
|
||||
V_Voice& vc(thiscore.Voices[voiceidx]);
|
||||
|
||||
for (int i = 0; i < 2; i++)
|
||||
if (Cores[i].IRQEnable && Cores[i].IRQA == (vc.NextA & 0xFFFF8))
|
||||
SetIrqCall(i);
|
||||
|
||||
s16* memptr = GetMemPtr(vc.NextA & 0xFFFF8);
|
||||
vc.LoopFlags = *memptr >> 8; // grab loop flags from the upper byte.
|
||||
|
||||
if ((vc.LoopFlags & XAFLAG_LOOP_START) && !vc.LoopMode)
|
||||
{
|
||||
vc.LoopStartA = vc.NextA & 0xFFFF8;
|
||||
}
|
||||
}
|
||||
|
||||
static __forceinline void DecodeSamples(uint coreidx, uint voiceidx)
|
||||
{
|
||||
V_Core& thiscore(Cores[coreidx]);
|
||||
V_Voice& vc(thiscore.Voices[voiceidx]);
|
||||
|
||||
// Update the block header on every audio frame
|
||||
UpdateBlockHeader(thiscore, voiceidx);
|
||||
|
||||
// When a voice is started at 0 pitch, NAX quickly advances to SSA + 5
|
||||
// So that would mean the decode buffer holds around 12 samples
|
||||
if (((int)(vc.DecPosWrite - vc.DecPosRead)) > 12) {
|
||||
// Sufficient data buffered
|
||||
return;
|
||||
}
|
||||
|
||||
if (vc.ADSR.Phase > V_ADSR::PHASE_STOPPED)
|
||||
{
|
||||
GetNextDataBuffered(thiscore, voiceidx);
|
||||
}
|
||||
|
||||
vc.DecPosWrite += 4;
|
||||
|
||||
IncrementNextA(thiscore, voiceidx);
|
||||
if ((vc.NextA & 7) == 0)
|
||||
{
|
||||
if (vc.LoopFlags & XAFLAG_LOOP_END)
|
||||
{
|
||||
thiscore.Regs.ENDX |= (1 << voiceidx);
|
||||
vc.NextA = vc.LoopStartA;
|
||||
if (!(vc.LoopFlags & XAFLAG_LOOP))
|
||||
{
|
||||
vc.Stop();
|
||||
|
||||
if (IsDevBuild)
|
||||
{
|
||||
if (SPU2::MsgVoiceOff())
|
||||
SPU2::ConLog("* SPU2: Voice Off by EndPoint: %d \n", voiceidx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
IncrementNextA(thiscore, voiceidx);
|
||||
vc.SBuffer = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
static void __forceinline UpdatePitch(uint coreidx, uint voiceidx)
|
||||
{
|
||||
V_Voice& vc(Cores[coreidx].Voices[voiceidx]);
|
||||
@ -278,33 +271,27 @@ static __forceinline void CalculateADSR(V_Core& thiscore, uint voiceidx)
|
||||
pxAssume(vc.ADSR.Value >= 0); // ADSR should never be negative...
|
||||
}
|
||||
|
||||
__forceinline static s32 GaussianInterpolate(s32 pv4, s32 pv3, s32 pv2, s32 pv1, s32 i)
|
||||
static __forceinline void ConsumeSamples(V_Core& thiscore, uint voiceidx)
|
||||
{
|
||||
s32 out = 0;
|
||||
out = (interpTable[i][0] * pv4) >> 15;
|
||||
out += (interpTable[i][1] * pv3) >> 15;
|
||||
out += (interpTable[i][2] * pv2) >> 15;
|
||||
out += (interpTable[i][3] * pv1) >> 15;
|
||||
V_Voice& vc(thiscore.Voices[voiceidx]);
|
||||
|
||||
return out;
|
||||
int consumed = vc.SP >> 12;
|
||||
vc.SP &= 0xfff;
|
||||
vc.DecPosRead += consumed;
|
||||
}
|
||||
|
||||
static __forceinline s32 GetVoiceValues(V_Core& thiscore, uint voiceidx)
|
||||
{
|
||||
V_Voice& vc(thiscore.Voices[voiceidx]);
|
||||
|
||||
while (vc.SP >= 0)
|
||||
{
|
||||
vc.PV4 = vc.PV3;
|
||||
vc.PV3 = vc.PV2;
|
||||
vc.PV2 = vc.PV1;
|
||||
vc.PV1 = GetNextDataBuffered(thiscore, voiceidx);
|
||||
vc.SP -= 0x1000;
|
||||
}
|
||||
int phase = (vc.SP & 0x0ff0) >> 4;
|
||||
s32 out = 0;
|
||||
out += (interpTable[phase][0] * vc.DecodeFifo[(vc.DecPosRead + 0) % 32]) >> 15;
|
||||
out += (interpTable[phase][1] * vc.DecodeFifo[(vc.DecPosRead + 1) % 32]) >> 15;
|
||||
out += (interpTable[phase][2] * vc.DecodeFifo[(vc.DecPosRead + 2) % 32]) >> 15;
|
||||
out += (interpTable[phase][3] * vc.DecodeFifo[(vc.DecPosRead + 3) % 32]) >> 15;
|
||||
|
||||
const s32 mu = vc.SP + 0x1000;
|
||||
|
||||
return GaussianInterpolate(vc.PV4, vc.PV3, vc.PV2, vc.PV1, (mu & 0x0ff0) >> 4);
|
||||
return out;
|
||||
}
|
||||
|
||||
// This is Dr. Hell's noise algorithm as implemented in pcsxr
|
||||
@ -382,21 +369,13 @@ static __forceinline StereoOut32 MixVoice(uint coreidx, uint voiceidx)
|
||||
V_Core& thiscore(Cores[coreidx]);
|
||||
V_Voice& vc(thiscore.Voices[voiceidx]);
|
||||
|
||||
// If this assertion fails, it mans SCurrent is being corrupted somewhere, or is not initialized
|
||||
// properly. Invalid values in SCurrent will cause errant IRQs and corrupted audio.
|
||||
pxAssertMsg((vc.SCurrent <= 28) && (vc.SCurrent != 0), "Current sample should always range from 1->28");
|
||||
|
||||
// Most games don't use much volume slide effects. So only call the UpdateVolume
|
||||
// methods when needed by checking the flag outside the method here...
|
||||
// (Note: Ys 6 : Ark of Nephistm uses these effects)
|
||||
|
||||
vc.Volume.Update();
|
||||
|
||||
// SPU2 Note: The spu2 continues to process voices for eternity, always, so we
|
||||
// have to run through all the motions of updating the voice regardless of it's
|
||||
// audible status. Otherwise IRQs might not trigger and emulation might fail.
|
||||
|
||||
UpdatePitch(coreidx, voiceidx);
|
||||
DecodeSamples(coreidx, voiceidx);
|
||||
|
||||
StereoOut32 voiceOut(0, 0);
|
||||
s32 Value = 0;
|
||||
@ -419,11 +398,14 @@ static __forceinline StereoOut32 MixVoice(uint coreidx, uint voiceidx)
|
||||
|
||||
voiceOut = ApplyVolume(StereoOut32(Value, Value), vc.Volume);
|
||||
}
|
||||
else
|
||||
{
|
||||
while (vc.SP >= 0)
|
||||
GetNextDataDummy(thiscore, voiceidx); // Dummy is enough
|
||||
}
|
||||
|
||||
// SPU2 Note: The spu2 continues to process voices for eternity, always, so we
|
||||
// have to run through all the motions of updating the voice regardless of it's
|
||||
// audible status. Otherwise IRQs might not trigger and emulation might fail.
|
||||
|
||||
UpdatePitch(coreidx, voiceidx);
|
||||
|
||||
ConsumeSamples(thiscore, voiceidx);
|
||||
|
||||
// Write-back of raw voice data (post ADSR applied)
|
||||
if (voiceidx == 1)
|
||||
@ -533,7 +515,8 @@ StereoOut32 V_Core::Mix(const VoiceMixSet& inVoices, const StereoOut32& Input, c
|
||||
return TD + ApplyVolume(RV, FxVol);
|
||||
}
|
||||
|
||||
static StereoOut32 DCFilter(StereoOut32 input) {
|
||||
static StereoOut32 DCFilter(StereoOut32 input)
|
||||
{
|
||||
// A simple DC blocking high-pass filter
|
||||
// Implementation from http://peabody.sapp.org/class/dmp2/lab/dcblock/
|
||||
// The magic number 0x7f5c is ceil(INT16_MAX * 0.995)
|
||||
@ -634,9 +617,9 @@ __forceinline void spu2Mix()
|
||||
if (SPU2::MsgCache())
|
||||
{
|
||||
SPU2::ConLog(" * SPU2 > CacheStats > Hits: %d Misses: %d Ignores: %d\n",
|
||||
g_counter_cache_hits,
|
||||
g_counter_cache_misses,
|
||||
g_counter_cache_ignores);
|
||||
g_counter_cache_hits,
|
||||
g_counter_cache_misses,
|
||||
g_counter_cache_ignores);
|
||||
}
|
||||
|
||||
g_counter_cache_hits =
|
||||
|
||||
@ -256,29 +256,16 @@ struct V_Voice
|
||||
// Sample pointer (19:12 bit fixed point)
|
||||
s32 SP;
|
||||
|
||||
// Sample pointer for Cubic Interpolation
|
||||
// Cubic interpolation mixes a sample behind Linear, so that it
|
||||
// can have sample data to either side of the end points from which
|
||||
// to extrapolate. This SP represents that late sample position.
|
||||
s32 SPc;
|
||||
|
||||
// Previous sample values - used for interpolation
|
||||
// Inverted order of these members to match the access order in the
|
||||
// code (might improve cache hits).
|
||||
s32 PV4;
|
||||
s32 PV3;
|
||||
s32 PV2;
|
||||
s32 PV1;
|
||||
|
||||
// Last outputted audio value, used for voice modulation.
|
||||
s32 OutX;
|
||||
s32 NextCrest; // temp value for Crest calculation
|
||||
|
||||
// SBuffer now points directly to an ADPCM cache entry.
|
||||
s16* SBuffer;
|
||||
|
||||
// sample position within the current decoded packet.
|
||||
s32 SCurrent;
|
||||
// Each voice has a buffer of decoded samples
|
||||
s32 DecodeFifo[32];
|
||||
u32 DecPosWrite;
|
||||
u32 DecPosRead;
|
||||
|
||||
// it takes a few ticks for voices to start on the real SPU2?
|
||||
void Start();
|
||||
|
||||
@ -181,7 +181,6 @@ void V_Core::Init(int index)
|
||||
VoiceGates[v].WetR = -1;
|
||||
|
||||
Voices[v].Volume = V_VolumeSlideLR(0, 0); // V_VolumeSlideLR::Max;
|
||||
Voices[v].SCurrent = 28;
|
||||
|
||||
Voices[v].ADSR.Counter = 0;
|
||||
Voices[v].ADSR.Value = 0;
|
||||
@ -190,6 +189,10 @@ void V_Core::Init(int index)
|
||||
Voices[v].NextA = 0x2801;
|
||||
Voices[v].StartA = 0x2800;
|
||||
Voices[v].LoopStartA = 0x2800;
|
||||
|
||||
memset(Voices[v].DecodeFifo, 0, sizeof(Voices[v].DecodeFifo));
|
||||
Voices[v].DecPosRead = 0;
|
||||
Voices[v].DecPosWrite = 0;
|
||||
}
|
||||
|
||||
DMAICounter = 0;
|
||||
@ -212,23 +215,18 @@ void V_Voice::Start()
|
||||
}
|
||||
|
||||
ADSR.Attack();
|
||||
SCurrent = 28;
|
||||
LoopMode = 0;
|
||||
|
||||
// When SP >= 0 the next sample will be grabbed, we don't want this to happen
|
||||
// instantly because in the case of pitch being 0 we want to delay getting
|
||||
// the next block header. This is a hack to work around the fact that unlike
|
||||
// the HW we don't update the block header on every cycle.
|
||||
SP = -1;
|
||||
SP = 0;
|
||||
|
||||
LoopFlags = 0;
|
||||
NextA = StartA | 1;
|
||||
Prev1 = 0;
|
||||
Prev2 = 0;
|
||||
|
||||
PV1 = PV2 = 0;
|
||||
PV3 = PV4 = 0;
|
||||
NextCrest = -0x8000;
|
||||
SBuffer = nullptr;
|
||||
DecPosRead = 0;
|
||||
DecPosWrite = 0;
|
||||
}
|
||||
|
||||
void V_Voice::Stop()
|
||||
@ -989,12 +987,10 @@ static void RegWrite_VoiceAddr(u16 value)
|
||||
// Wallace And Gromit: Curse Of The Were-Rabbit.
|
||||
|
||||
thisvoice.NextA = ((u32)(value & 0x0F) << 16) | (thisvoice.NextA & 0xFFF8) | 1;
|
||||
thisvoice.SCurrent = 28;
|
||||
break;
|
||||
|
||||
case 5:
|
||||
thisvoice.NextA = (thisvoice.NextA & 0x0F0000) | (value & 0xFFF8) | 1;
|
||||
thisvoice.SCurrent = 28;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1212,7 +1208,6 @@ static void RegWrite_Core(u16 value)
|
||||
for (uint v = 0; v < 24; ++v)
|
||||
{
|
||||
Cores[1].Voices[v].Volume = V_VolumeSlideLR(0, 0); // V_VolumeSlideLR::Max;
|
||||
Cores[1].Voices[v].SCurrent = 28;
|
||||
|
||||
Cores[1].Voices[v].ADSR.Value = 0;
|
||||
Cores[1].Voices[v].ADSR.Phase = 0;
|
||||
|
||||
@ -26,7 +26,7 @@ enum class FreezeAction
|
||||
// [SAVEVERSION+]
|
||||
// This informs the auto updater that the users savestates will be invalidated.
|
||||
|
||||
static const u32 g_SaveVersion = (0x9A55 << 16) | 0x0000;
|
||||
static const u32 g_SaveVersion = (0x9A57 << 16) | 0x0000;
|
||||
|
||||
|
||||
// the freezing data between submodules and core
|
||||
|
||||
Loading…
Reference in New Issue
Block a user