Skip to content

Commit b0a994d

Browse files
committed
Add iOS emulator volume controls
1 parent 3ff7668 commit b0a994d

5 files changed

Lines changed: 248 additions & 6 deletions

File tree

app/src/main/cpp/ARMSX2Bridge.h

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,10 @@ typedef void (^ARMSX2RetroAchievementsCompletion)(BOOL success, NSString * _Nonn
102102
+ (BOOL)isPerformanceOverlayVisible;
103103
+ (void)applyOsdPreset:(int)preset; // 0=off, 1=simple, 2=detail, 3=full
104104

105+
// Audio
106+
+ (int)emulatorVolumePercent;
107+
+ (void)setEmulatorVolumePercent:(int)value;
108+
105109
// ISO management
106110
+ (nullable NSString *)currentISOPath;
107111
+ (nullable NSString *)currentGameISOName;
@@ -137,13 +141,15 @@ typedef void (^ARMSX2RetroAchievementsCompletion)(BOOL success, NSString * _Nonn
137141
skipDrawStart:(int)skipDrawStart
138142
skipDrawEndOverride:(BOOL)skipDrawEndOverride
139143
skipDrawEnd:(int)skipDrawEnd
144+
volumeOverride:(BOOL)volumeOverride
145+
volumePercent:(int)volumePercent
140146
eeCoreType:(int)eeCoreType
141147
mtvu:(BOOL)mtvu
142148
enableCheats:(BOOL)enableCheats
143149
enablePatches:(BOOL)enablePatches
144150
enableGameFixes:(BOOL)enableGameFixes
145151
enableGameDBHardwareFixes:(BOOL)enableGameDBHardwareFixes
146-
NS_SWIFT_NAME(setGameSettings(forISO:enabled:upscaleMultiplier:aspectRatio:textureFiltering:hardwareMipmapping:blendingAccuracy:interlaceMode:trilinearFiltering:halfPixelOffset:roundSprite:alignSpriteOverride:alignSprite:mergeSpriteOverride:mergeSprite:wildArmsOffsetOverride:wildArmsOffset:textureOffsetXOverride:textureOffsetX:textureOffsetYOverride:textureOffsetY:skipDrawStartOverride:skipDrawStart:skipDrawEndOverride:skipDrawEnd:eeCoreType:mtvu:enableCheats:enablePatches:enableGameFixes:enableGameDBHardwareFixes:));
152+
NS_SWIFT_NAME(setGameSettings(forISO:enabled:upscaleMultiplier:aspectRatio:textureFiltering:hardwareMipmapping:blendingAccuracy:interlaceMode:trilinearFiltering:halfPixelOffset:roundSprite:alignSpriteOverride:alignSprite:mergeSpriteOverride:mergeSprite:wildArmsOffsetOverride:wildArmsOffset:textureOffsetXOverride:textureOffsetX:textureOffsetYOverride:textureOffsetY:skipDrawStartOverride:skipDrawStart:skipDrawEndOverride:skipDrawEnd:volumeOverride:volumePercent:eeCoreType:mtvu:enableCheats:enablePatches:enableGameFixes:enableGameDBHardwareFixes:));
147153
+ (void)setGameSettingsForCurrentGameWithEnabled:(BOOL)enabled
148154
upscaleMultiplier:(float)upscaleMultiplier
149155
aspectRatio:(nonnull NSString *)aspectRatio
@@ -168,13 +174,15 @@ typedef void (^ARMSX2RetroAchievementsCompletion)(BOOL success, NSString * _Nonn
168174
skipDrawStart:(int)skipDrawStart
169175
skipDrawEndOverride:(BOOL)skipDrawEndOverride
170176
skipDrawEnd:(int)skipDrawEnd
177+
volumeOverride:(BOOL)volumeOverride
178+
volumePercent:(int)volumePercent
171179
eeCoreType:(int)eeCoreType
172180
mtvu:(BOOL)mtvu
173181
enableCheats:(BOOL)enableCheats
174182
enablePatches:(BOOL)enablePatches
175183
enableGameFixes:(BOOL)enableGameFixes
176184
enableGameDBHardwareFixes:(BOOL)enableGameDBHardwareFixes
177-
NS_SWIFT_NAME(setGameSettingsForCurrentGame(enabled:upscaleMultiplier:aspectRatio:textureFiltering:hardwareMipmapping:blendingAccuracy:interlaceMode:trilinearFiltering:halfPixelOffset:roundSprite:alignSpriteOverride:alignSprite:mergeSpriteOverride:mergeSprite:wildArmsOffsetOverride:wildArmsOffset:textureOffsetXOverride:textureOffsetX:textureOffsetYOverride:textureOffsetY:skipDrawStartOverride:skipDrawStart:skipDrawEndOverride:skipDrawEnd:eeCoreType:mtvu:enableCheats:enablePatches:enableGameFixes:enableGameDBHardwareFixes:));
185+
NS_SWIFT_NAME(setGameSettingsForCurrentGame(enabled:upscaleMultiplier:aspectRatio:textureFiltering:hardwareMipmapping:blendingAccuracy:interlaceMode:trilinearFiltering:halfPixelOffset:roundSprite:alignSpriteOverride:alignSprite:mergeSpriteOverride:mergeSprite:wildArmsOffsetOverride:wildArmsOffset:textureOffsetXOverride:textureOffsetX:textureOffsetYOverride:textureOffsetY:skipDrawStartOverride:skipDrawStart:skipDrawEndOverride:skipDrawEnd:volumeOverride:volumePercent:eeCoreType:mtvu:enableCheats:enablePatches:enableGameFixes:enableGameDBHardwareFixes:));
178186
+ (nonnull NSString *)clearCacheForISO:(nonnull NSString *)isoName NS_SWIFT_NAME(clearCache(forISO:));
179187
+ (nonnull NSString *)deleteGameDataForISO:(nonnull NSString *)isoName NS_SWIFT_NAME(deleteGameData(forISO:));
180188
+ (BOOL)deleteISO:(nonnull NSString *)isoName deleteGameData:(BOOL)deleteGameData NS_SWIFT_NAME(deleteISO(_:deleteGameData:));

app/src/main/cpp/ARMSX2Bridge.mm

Lines changed: 83 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "SIO/Sio.h"
2222
#include "Counters.h"
2323
#include "GS/GSState.h"
24+
#include "SPU2/spu2.h"
2425
#include "GameList.h"
2526
#include "ps2/BiosTools.h"
2627
#include "pcsx2/Host.h"
@@ -71,6 +72,7 @@ @implementation ARMSX2BIOSInfo
7172
static NSString* const ARMSX2CompatibilityProfileCustom = @"custom";
7273
static constexpr int ARMSX2UseGlobalIntSentinel = -1;
7374
static constexpr int ARMSX2TriFilterUseGlobalSentinel = std::numeric_limits<int>::min();
75+
static constexpr int ARMSX2DefaultAudioVolumePercent = 100;
7476

7577
static int ARMSX2ClampInt(int value, int minValue, int maxValue)
7678
{
@@ -1427,6 +1429,10 @@ static void ARMSX2ApplyLiveFloatSetting(const char* section, const char* key, fl
14271429
const bool globalEnableGameDBHardwareFixes = g_p44_settings_interface ? !g_p44_settings_interface->GetBoolValue("EmuCore/GS", "UserHacks", false) : true;
14281430
const int globalEECoreType = g_p44_settings_interface ? g_p44_settings_interface->GetIntValue("EmuCore/CPU", "CoreType", 2) : 2;
14291431
const bool globalMTVU = g_p44_settings_interface ? g_p44_settings_interface->GetBoolValue("EmuCore/Speedhacks", "vuThread", true) : true;
1432+
const int globalVolumePercent = ARMSX2ClampInt(
1433+
g_p44_settings_interface ? g_p44_settings_interface->GetIntValue("SPU2/Output", "StandardVolume", ARMSX2DefaultAudioVolumePercent) : ARMSX2DefaultAudioVolumePercent,
1434+
0,
1435+
ARMSX2DefaultAudioVolumePercent);
14301436
return [@{
14311437
@"enabled": @NO,
14321438
@"path": @"",
@@ -1464,6 +1470,9 @@ static void ARMSX2ApplyLiveFloatSetting(const char* section, const char* key, fl
14641470
@"enableGameDBHardwareFixes": @(globalEnableGameDBHardwareFixes),
14651471
@"eeCoreType": @(globalEECoreType),
14661472
@"mtvu": @(globalMTVU),
1473+
@"globalVolumePercent": @(globalVolumePercent),
1474+
@"volumePercent": @(globalVolumePercent),
1475+
@"hasVolumeOverride": @NO,
14671476
} mutableCopy];
14681477
}
14691478

@@ -1519,9 +1528,20 @@ static void ARMSX2ApplyPerGameSettingsOverrides(NSMutableDictionary<NSString*, i
15191528
si.ContainsValue("EmuCore/GS", "UserHacks") ||
15201529
si.ContainsValue("EmuCore/CPU", "CoreType") ||
15211530
si.ContainsValue("EmuCore/CPU", "UseArm64Dynarec") ||
1522-
si.ContainsValue("EmuCore/Speedhacks", "vuThread");
1531+
si.ContainsValue("EmuCore/Speedhacks", "vuThread") ||
1532+
si.ContainsValue("SPU2/Output", "StandardVolume") ||
1533+
si.ContainsValue("SPU2/Output", "FastForwardVolume");
15231534

15241535
result[@"enabled"] = @(hasKnownOverride);
1536+
const bool hasStandardVolumeOverride = si.ContainsValue("SPU2/Output", "StandardVolume");
1537+
const bool hasFastForwardVolumeOverride = si.ContainsValue("SPU2/Output", "FastForwardVolume");
1538+
const bool hasVolumeOverride = hasStandardVolumeOverride || hasFastForwardVolumeOverride;
1539+
const int inheritedVolumePercent = [result[@"volumePercent"] intValue];
1540+
const int volumePercent = hasStandardVolumeOverride ?
1541+
si.GetIntValue("SPU2/Output", "StandardVolume", inheritedVolumePercent) :
1542+
(hasFastForwardVolumeOverride ? si.GetIntValue("SPU2/Output", "FastForwardVolume", inheritedVolumePercent) : inheritedVolumePercent);
1543+
result[@"hasVolumeOverride"] = @(hasVolumeOverride);
1544+
result[@"volumePercent"] = @(ARMSX2ClampInt(volumePercent, 0, ARMSX2DefaultAudioVolumePercent));
15251545
NSString* currentAspect = [result[@"aspectRatio"] isKindOfClass:NSString.class] ? result[@"aspectRatio"] : @"Auto 4:3/3:2";
15261546
result[@"upscaleMultiplier"] = @(si.GetFloatValue("EmuCore/GS", "upscale_multiplier", [result[@"upscaleMultiplier"] floatValue]));
15271547
result[@"aspectRatio"] = ARMSX2NSStringFromStdString(si.GetStringValue("EmuCore/GS", "AspectRatio", currentAspect.UTF8String));
@@ -1583,6 +1603,8 @@ static void ARMSX2WriteGameSettingsForIdentity(const std::string& serial,
15831603
int skipDrawStart,
15841604
BOOL skipDrawEndOverride,
15851605
int skipDrawEnd,
1606+
BOOL volumeOverride,
1607+
int volumePercent,
15861608
int eeCoreType,
15871609
BOOL mtvu,
15881610
BOOL enableCheats,
@@ -1658,6 +1680,15 @@ static void ARMSX2WriteGameSettingsForIdentity(const std::string& serial,
16581680
else
16591681
si.DeleteValue("EmuCore/GS", "UserHacks_SkipDraw_End");
16601682

1683+
if (volumeOverride) {
1684+
const int clampedVolumePercent = ARMSX2ClampInt(volumePercent, 0, ARMSX2DefaultAudioVolumePercent);
1685+
si.SetIntValue("SPU2/Output", "StandardVolume", clampedVolumePercent);
1686+
si.SetIntValue("SPU2/Output", "FastForwardVolume", clampedVolumePercent);
1687+
} else {
1688+
si.DeleteValue("SPU2/Output", "StandardVolume");
1689+
si.DeleteValue("SPU2/Output", "FastForwardVolume");
1690+
}
1691+
16611692
si.SetBoolValue("EmuCore", "EnableCheats", enableCheats);
16621693
si.SetBoolValue("EmuCore", "EnablePatches", enablePatches);
16631694
si.SetBoolValue("EmuCore", "EnableGameFixes", enableGameFixes);
@@ -1702,6 +1733,8 @@ static void ARMSX2WriteGameSettingsForIdentity(const std::string& serial,
17021733
si.DeleteValue("ARMSX2iOS/PerGame", "ManualMTVU");
17031734
si.DeleteValue("ARMSX2iOS/PerGame", "ManualMTVUVersion");
17041735
si.DeleteValue("EmuCore/Speedhacks", "vuThread");
1736+
si.DeleteValue("SPU2/Output", "StandardVolume");
1737+
si.DeleteValue("SPU2/Output", "FastForwardVolume");
17051738
si.RemoveEmptySections();
17061739
}
17071740

@@ -2231,6 +2264,8 @@ + (void)setGameSettingsForISO:(nonnull NSString *)isoName
22312264
skipDrawStart:(int)skipDrawStart
22322265
skipDrawEndOverride:(BOOL)skipDrawEndOverride
22332266
skipDrawEnd:(int)skipDrawEnd
2267+
volumeOverride:(BOOL)volumeOverride
2268+
volumePercent:(int)volumePercent
22342269
eeCoreType:(int)eeCoreType
22352270
mtvu:(BOOL)mtvu
22362271
enableCheats:(BOOL)enableCheats
@@ -2250,7 +2285,8 @@ + (void)setGameSettingsForISO:(nonnull NSString *)isoName
22502285
alignSprite, mergeSpriteOverride, mergeSprite, wildArmsOffsetOverride,
22512286
wildArmsOffset, textureOffsetXOverride, textureOffsetX,
22522287
textureOffsetYOverride, textureOffsetY, skipDrawStartOverride,
2253-
skipDrawStart, skipDrawEndOverride, skipDrawEnd, eeCoreType, mtvu,
2288+
skipDrawStart, skipDrawEndOverride, skipDrawEnd,
2289+
volumeOverride, volumePercent, eeCoreType, mtvu,
22542290
enableCheats, enablePatches, enableGameFixes, enableGameDBHardwareFixes);
22552291
}
22562292

@@ -2278,6 +2314,8 @@ + (void)setGameSettingsForCurrentGameWithEnabled:(BOOL)enabled
22782314
skipDrawStart:(int)skipDrawStart
22792315
skipDrawEndOverride:(BOOL)skipDrawEndOverride
22802316
skipDrawEnd:(int)skipDrawEnd
2317+
volumeOverride:(BOOL)volumeOverride
2318+
volumePercent:(int)volumePercent
22812319
eeCoreType:(int)eeCoreType
22822320
mtvu:(BOOL)mtvu
22832321
enableCheats:(BOOL)enableCheats
@@ -2303,7 +2341,8 @@ + (void)setGameSettingsForCurrentGameWithEnabled:(BOOL)enabled
23032341
alignSprite, mergeSpriteOverride, mergeSprite, wildArmsOffsetOverride,
23042342
wildArmsOffset, textureOffsetXOverride, textureOffsetX,
23052343
textureOffsetYOverride, textureOffsetY, skipDrawStartOverride,
2306-
skipDrawStart, skipDrawEndOverride, skipDrawEnd, eeCoreType, mtvu,
2344+
skipDrawStart, skipDrawEndOverride, skipDrawEnd,
2345+
volumeOverride, volumePercent, eeCoreType, mtvu,
23072346
enableCheats, enablePatches, enableGameFixes, enableGameDBHardwareFixes);
23082347

23092348
if (VMManager::HasValidVM()) {
@@ -2552,6 +2591,47 @@ + (void)applyOsdPreset:(int)preset {
25522591
EmuConfig.GS.OsdShowInputs = GSConfig.OsdShowInputs;
25532592
}
25542593

2594+
+ (int)emulatorVolumePercent {
2595+
const int value = g_p44_settings_interface ?
2596+
g_p44_settings_interface->GetIntValue("SPU2/Output", "StandardVolume", ARMSX2DefaultAudioVolumePercent) :
2597+
ARMSX2DefaultAudioVolumePercent;
2598+
return ARMSX2ClampInt(value, 0, ARMSX2DefaultAudioVolumePercent);
2599+
}
2600+
2601+
+ (void)setEmulatorVolumePercent:(int)value {
2602+
if (!g_p44_settings_interface)
2603+
return;
2604+
2605+
const int clampedValue = ARMSX2ClampInt(value, 0, ARMSX2DefaultAudioVolumePercent);
2606+
g_p44_settings_interface->SetIntValue("SPU2/Output", "StandardVolume", clampedValue);
2607+
g_p44_settings_interface->SetIntValue("SPU2/Output", "FastForwardVolume", clampedValue);
2608+
g_p44_settings_interface->Save();
2609+
2610+
if (!VMManager::HasValidVM())
2611+
return;
2612+
2613+
Host::RunOnCPUThread([clampedValue]() {
2614+
if (!VMManager::HasValidVM())
2615+
return;
2616+
2617+
const std::string serial = VMManager::GetDiscSerial();
2618+
const u32 crc = VMManager::GetDiscCRC();
2619+
if (crc != 0) {
2620+
INISettingsInterface si(VMManager::GetGameSettingsPath(serial, crc));
2621+
if (si.Load() &&
2622+
(si.ContainsValue("SPU2/Output", "StandardVolume") ||
2623+
si.ContainsValue("SPU2/Output", "FastForwardVolume"))) {
2624+
return;
2625+
}
2626+
}
2627+
2628+
const Pcsx2Config oldConfig(EmuConfig);
2629+
EmuConfig.SPU2.StandardVolume = clampedValue;
2630+
EmuConfig.SPU2.FastForwardVolume = clampedValue;
2631+
SPU2::CheckForConfigChanges(oldConfig);
2632+
}, false);
2633+
}
2634+
25552635
// ============================================================
25562636
// ISO / BIOS / Settings management
25572637
// ============================================================

app/src/main/swift/Models/SettingsStore.swift

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ final class SettingsStore: @unchecked Sendable {
6868
static let minFastForwardScalar: Float = 1.25
6969
static let maxFastForwardScalar: Float = 10.0
7070
static let defaultFastForwardScalar: Float = 2.0
71+
static let defaultEmulatorVolumePercent = 100
7172
static let textureOffsetRange = -4096...4096
7273
static let skipDrawRange = 0...5000
7374
static let defaultOsdPerformancePosition = 3
@@ -140,6 +141,17 @@ final class SettingsStore: @unchecked Sendable {
140141
ARMSX2Bridge.setINIFloat("Framerate", key: "TurboScalar", value: fastForwardScalar)
141142
}
142143
}
144+
var emulatorVolumePercent: Int {
145+
didSet {
146+
let normalized = Self.clampedEmulatorVolumePercent(emulatorVolumePercent)
147+
guard emulatorVolumePercent == normalized else {
148+
emulatorVolumePercent = normalized
149+
return
150+
}
151+
guard !suppressINIWrites else { return }
152+
ARMSX2Bridge.setEmulatorVolumePercent(Int32(normalized))
153+
}
154+
}
143155
var ntscFramerate: Float {
144156
didSet {
145157
guard !suppressINIWrites else { return }
@@ -597,6 +609,7 @@ final class SettingsStore: @unchecked Sendable {
597609
targetFPS = Self.targetFPS(fromNominalScalar: nominalScalar, baseFramerate: loadedNTSCFramerate)
598610
Self.sanitizeNominalScalarIfNeeded(nominalScalar)
599611
fastForwardScalar = Self.clampedSpeedScalar(ARMSX2Bridge.getINIFloat("Framerate", key: "TurboScalar", defaultValue: Self.defaultFastForwardScalar))
612+
emulatorVolumePercent = Self.clampedEmulatorVolumePercent(Int(ARMSX2Bridge.emulatorVolumePercent()))
600613
// Boot
601614
fastCDVD = ARMSX2Bridge.getINIBool("EmuCore/Speedhacks", key: "fastCDVD", defaultValue: false)
602615
// Advanced Speedhacks
@@ -728,6 +741,7 @@ final class SettingsStore: @unchecked Sendable {
728741
targetFPS = Self.targetFPS(fromNominalScalar: nominalScalar, baseFramerate: ntscFramerate)
729742
Self.sanitizeNominalScalarIfNeeded(nominalScalar)
730743
fastForwardScalar = Self.clampedSpeedScalar(ARMSX2Bridge.getINIFloat("Framerate", key: "TurboScalar", defaultValue: Self.defaultFastForwardScalar))
744+
emulatorVolumePercent = Self.clampedEmulatorVolumePercent(Int(ARMSX2Bridge.emulatorVolumePercent()))
731745
fastCDVD = ARMSX2Bridge.getINIBool("EmuCore/Speedhacks", key: "fastCDVD", defaultValue: false)
732746
eeCycleRate = Int(ARMSX2Bridge.getINIInt("EmuCore/Speedhacks", key: "EECycleRate", defaultValue: 0))
733747
vu1Instant = ARMSX2Bridge.getINIBool("EmuCore/Speedhacks", key: "vu1Instant", defaultValue: true)
@@ -851,6 +865,10 @@ final class SettingsStore: @unchecked Sendable {
851865
return min(max(stepped, minFastForwardScalar), maxFastForwardScalar)
852866
}
853867

868+
static func clampedEmulatorVolumePercent(_ value: Int) -> Int {
869+
min(max(value, 0), 100)
870+
}
871+
854872
private static func clampedAnalogStickScale(_ scale: Float) -> Float {
855873
guard scale.isFinite else { return 1.0 }
856874
return min(max(scale, 0.8), 1.6)
@@ -997,6 +1015,7 @@ final class SettingsStore: @unchecked Sendable {
9971015
fastForwardRuntimeEnabled = false
9981016
frameLimiterDisabledForFastForward = false
9991017
fastForwardScalar = Self.defaultFastForwardScalar
1018+
emulatorVolumePercent = Self.defaultEmulatorVolumePercent
10001019
ntscFramerate = 59.94
10011020
palFramerate = 50.0
10021021
fastCDVD = false

0 commit comments

Comments
 (0)