This commit is contained in:
Nayla Hanegan 2025-01-07 17:41:52 -05:00
commit 512e9e3fbc
27 changed files with 488 additions and 307 deletions

View file

@ -0,0 +1,24 @@
function(dolphin_inject_version_info target)
set(INFO_PLIST_PATH "$<TARGET_BUNDLE_DIR:${target}>/Contents/Info.plist")
add_custom_command(TARGET ${target}
POST_BUILD
COMMAND /usr/libexec/PlistBuddy -c
"Delete :CFBundleShortVersionString"
"${INFO_PLIST_PATH}"
|| true
COMMAND /usr/libexec/PlistBuddy -c
"Delete :CFBundleLongVersionString"
"${INFO_PLIST_PATH}"
|| true
COMMAND /usr/libexec/PlistBuddy -c
"Delete :CFBundleVersion"
"${INFO_PLIST_PATH}"
|| true
COMMAND /usr/libexec/PlistBuddy -c
"Merge '${CMAKE_BINARY_DIR}/Source/Core/VersionInfo.plist'"
"${INFO_PLIST_PATH}")
endfunction()

View file

@ -65,6 +65,5 @@ endfunction()
configure_source_file("Source/Core/Common/scmrev.h") configure_source_file("Source/Core/Common/scmrev.h")
if(APPLE) if(APPLE)
configure_source_file("Source/Core/DolphinQt/Info.plist") configure_source_file("Source/Core/VersionInfo.plist")
configure_source_file("Source/Core/MacUpdater/Info.plist")
endif() endif()

View file

@ -783,14 +783,9 @@ if (NOT EXISTS ${CMAKE_CURRENT_BINARY_DIR}/Source/Core/Common/scmrev.h)
endif() endif()
if(APPLE) if(APPLE)
file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/Source/Core/DolphinQt) file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/Source/Core)
if (NOT EXISTS ${CMAKE_CURRENT_BINARY_DIR}/Source/Core/DolphinQt/Info.plist) if (NOT EXISTS ${CMAKE_CURRENT_BINARY_DIR}/Source/Core/VersionInfo.plist)
file(TOUCH ${CMAKE_CURRENT_BINARY_DIR}/Source/Core/DolphinQt/Info.plist) file(TOUCH ${CMAKE_CURRENT_BINARY_DIR}/Source/Core/VersionInfo.plist)
endif()
file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/Source/Core/MacUpdater)
if (NOT EXISTS ${CMAKE_CURRENT_BINARY_DIR}/Source/Core/MacUpdater/Info.plist)
file(TOUCH ${CMAKE_CURRENT_BINARY_DIR}/Source/Core/MacUpdater/Info.plist)
endif() endif()
endif() endif()

View file

@ -239,9 +239,9 @@ C20C5B48 00000001
3A000000 00000000 3A000000 00000000
C20C2708 00000001 C20C2708 00000001
38600000 00000000 38600000 00000000
C20A9E08 00000004 C20A9E08 00000005
3C60817F 6063FFFC 3C60817F 6063FFFC
80830000 2C040001 A0830000 2C040001
41820008 1FDE0003 41820008 1FDE0003
3C800000 90830000 3C800000 90830000
60000000 00000000 60000000 00000000
@ -949,7 +949,7 @@ B09C002E 3B7B0002
83810010 83A10014 83810010 83A10014
83C10018 83E1001C 83C10018 83E1001C
38210010 00000000 38210010 00000000
C204BF38 00000008 C20A85F8 00000008
3FA08024 63BDD5F8 3FA08024 63BDD5F8
3C600001 60630025 3C600001 60630025
A8AD8BA8 2C050000 A8AD8BA8 2C050000

View file

@ -1462,25 +1462,28 @@ $Minigame Deletion - Cash Flow [Tabitha]
002305A4 000000FF 002305A4 000000FF
00230CD4 000000FF 00230CD4 000000FF
$Minigame Deletion - Cashapult ➜ Jump The Gun [Tabitha] $Minigame Deletion - Cashapult [Tabitha]
00231316 000000FF 00231316 000000FF
$Minigame Deletion - Money Belts ➜ Throw Me a Bone [Tabitha] $Minigame Deletion - Money Belts [Tabitha]
00230966 000000FF 00230966 000000FF
$Minigame Deletion - Pitifall ➜ Cog Jog [Tabitha] $Minigame Deletion - Pitifall [Tabitha]
00231962 000000FF 00231962 000000FF
$Minigame Deletion - Trap Ease Artist ➜ What Goes Up... [Tabitha] $Minigame Deletion - Pop Star [Tabitha]
00230CCA 000000FF
$Minigame Deletion - Trap Ease Artist [Tabitha]
0023086E 000000FF 0023086E 000000FF
$Minigame Deletion - Trick or Tree ➜ Boo'd Off the Stage [Tabitha] $Minigame Deletion - Trick or Tree [Tabitha]
00231CC6 000000FF 00231CC6 000000FF
$Minigame Deletion - Tricky Tires ➜ Cannonball Fun [Tabitha] $Minigame Deletion - Tricky Tires [Tabitha]
00230396 000000FF 00230396 000000FF
$Minigame Deletion - Wrasslin' Rapids ➜ Hyper Sniper [Tabitha] $Minigame Deletion - Wrasslin' Rapids [Tabitha]
00231DBE 000000FF 00231DBE 000000FF
$Orbs - Disable ALL Orbs [gamemasterplc] $Orbs - Disable ALL Orbs [gamemasterplc]

View file

@ -1459,28 +1459,28 @@ $Minigame - Vine Country - DK is Faster [gamemasterplc]
044E5EE4 3803FFFE 044E5EE4 3803FFFE
E2000001 80008000 E2000001 80008000
$Minigame Deletion - Bridge Work ➜ Mad Props $Minigame Deletion - Bridge Works [Tabitha]
0025B722 000000FF 0025B722 000000FF
$Minigame Deletion - Cointagious ➜ Take Me Ohm $Minigame Deletion - Cointagious [Tabitha]
00259FE2 000000FF 00259FE2 000000FF
$Minigame Deletion - Fish & Cheeps ➜ Weight for It $Minigame Deletion - Fish & Cheeps [Tabitha]
0025BB02 000000FF 0025BB02 000000FF
$Minigame Deletion - Flashfright ➜ Think Tank $Minigame Deletion - Flashfright [Tabitha]
0025AA0E 000000FF 0025AA0E 000000FF
$Minigame Deletion - Gimme a Sign ➜ Royal Rumpus $Minigame Deletion - Gimme a Sign [Tabitha]
0025B6A6 000000FF 0025B6A6 000000FF
$Minigame Deletion - Light Speed ➜ Camp Ukiki $Minigame Deletion - Light Speed [Tabitha]
0025BA0A 000000FF 0025BA0A 000000FF
$Minigame Deletion - Spin Doctor ➜ Hip Hop Drop $Minigame Deletion - Spin Doctor [Tabitha]
0025B79E 000000FF 0025B79E 000000FF
$Minigame Deletion - Warp Pipe Dreams ➜ Apes of Wrath $Minigame Deletion - Warp Pipe Dreams [Tabitha]
0025B3BE 000000FF 0025B3BE 000000FF
$Music - Disables Music [Ralf] $Music - Disables Music [Ralf]

View file

@ -209,6 +209,9 @@ $QOL - Increased Text Display [Tabitha]
$QOL - Invert IR Stick for GameCube Mod [gamemasterplc] $QOL - Invert IR Stick for GameCube Mod [gamemasterplc]
04106A24 83DE6404 04106A24 83DE6404
04106A28 60000000 04106A28 60000000
04106AA4 C0428004
04106A74 C04282F0
$QOL - Remove Explanations [Rain] $QOL - Remove Explanations [Rain]
82200001 80228760 82200001 80228760

View file

@ -64,7 +64,7 @@ const Info<bool> GFX_CACHE_HIRES_TEXTURES{{System::GFX, "Settings", "CacheHiresT
const Info<bool> GFX_DUMP_EFB_TARGET{{System::GFX, "Settings", "DumpEFBTarget"}, false}; const Info<bool> GFX_DUMP_EFB_TARGET{{System::GFX, "Settings", "DumpEFBTarget"}, false};
const Info<bool> GFX_DUMP_XFB_TARGET{{System::GFX, "Settings", "DumpXFBTarget"}, false}; const Info<bool> GFX_DUMP_XFB_TARGET{{System::GFX, "Settings", "DumpXFBTarget"}, false};
const Info<bool> GFX_DUMP_FRAMES_AS_IMAGES{{System::GFX, "Settings", "DumpFramesAsImages"}, false}; const Info<bool> GFX_DUMP_FRAMES_AS_IMAGES{{System::GFX, "Settings", "DumpFramesAsImages"}, false};
const Info<bool> GFX_USE_FFV1{{System::GFX, "Settings", "UseFFV1"}, false}; const Info<bool> GFX_USE_LOSSLESS{{System::GFX, "Settings", "UseLossless"}, false};
const Info<std::string> GFX_DUMP_FORMAT{{System::GFX, "Settings", "DumpFormat"}, "avi"}; const Info<std::string> GFX_DUMP_FORMAT{{System::GFX, "Settings", "DumpFormat"}, "avi"};
const Info<std::string> GFX_DUMP_CODEC{{System::GFX, "Settings", "DumpCodec"}, ""}; const Info<std::string> GFX_DUMP_CODEC{{System::GFX, "Settings", "DumpCodec"}, ""};
const Info<std::string> GFX_DUMP_PIXEL_FORMAT{{System::GFX, "Settings", "DumpPixelFormat"}, ""}; const Info<std::string> GFX_DUMP_PIXEL_FORMAT{{System::GFX, "Settings", "DumpPixelFormat"}, ""};

View file

@ -63,7 +63,7 @@ extern const Info<bool> GFX_CACHE_HIRES_TEXTURES;
extern const Info<bool> GFX_DUMP_EFB_TARGET; extern const Info<bool> GFX_DUMP_EFB_TARGET;
extern const Info<bool> GFX_DUMP_XFB_TARGET; extern const Info<bool> GFX_DUMP_XFB_TARGET;
extern const Info<bool> GFX_DUMP_FRAMES_AS_IMAGES; extern const Info<bool> GFX_DUMP_FRAMES_AS_IMAGES;
extern const Info<bool> GFX_USE_FFV1; extern const Info<bool> GFX_USE_LOSSLESS;
extern const Info<std::string> GFX_DUMP_FORMAT; extern const Info<std::string> GFX_DUMP_FORMAT;
extern const Info<std::string> GFX_DUMP_CODEC; extern const Info<std::string> GFX_DUMP_CODEC;
extern const Info<std::string> GFX_DUMP_PIXEL_FORMAT; extern const Info<std::string> GFX_DUMP_PIXEL_FORMAT;

View file

@ -41,6 +41,7 @@ static void LoadFromDTM(Config::Layer* config_layer, Movie::DTMHeader* dtm)
else else
config_layer->Set(Config::MAIN_GC_LANGUAGE, static_cast<int>(dtm->language)); config_layer->Set(Config::MAIN_GC_LANGUAGE, static_cast<int>(dtm->language));
config_layer->Set(Config::SYSCONF_WIDESCREEN, dtm->bWidescreen); config_layer->Set(Config::SYSCONF_WIDESCREEN, dtm->bWidescreen);
config_layer->Set(Config::SYSCONF_COUNTRY, dtm->countryCode);
config_layer->Set(Config::GFX_HACK_EFB_ACCESS_ENABLE, dtm->bEFBAccessEnable); config_layer->Set(Config::GFX_HACK_EFB_ACCESS_ENABLE, dtm->bEFBAccessEnable);
config_layer->Set(Config::GFX_HACK_SKIP_EFB_COPY_TO_RAM, dtm->bSkipEFBCopyToRam); config_layer->Set(Config::GFX_HACK_SKIP_EFB_COPY_TO_RAM, dtm->bSkipEFBCopyToRam);
@ -69,6 +70,7 @@ void SaveToDTM(Movie::DTMHeader* dtm)
else else
dtm->language = Config::Get(Config::MAIN_GC_LANGUAGE); dtm->language = Config::Get(Config::MAIN_GC_LANGUAGE);
dtm->bWidescreen = Config::Get(Config::SYSCONF_WIDESCREEN); dtm->bWidescreen = Config::Get(Config::SYSCONF_WIDESCREEN);
dtm->countryCode = Config::Get(Config::SYSCONF_COUNTRY);
dtm->bEFBAccessEnable = Config::Get(Config::GFX_HACK_EFB_ACCESS_ENABLE); dtm->bEFBAccessEnable = Config::Get(Config::GFX_HACK_EFB_ACCESS_ENABLE);
dtm->bSkipEFBCopyToRam = Config::Get(Config::GFX_HACK_SKIP_EFB_COPY_TO_RAM); dtm->bSkipEFBCopyToRam = Config::Get(Config::GFX_HACK_SKIP_EFB_COPY_TO_RAM);

View file

@ -132,7 +132,8 @@ struct DTMHeader
bool bUseFMA; bool bUseFMA;
u8 GBAControllers; // GBA Controllers plugged in (the bits are ports 1-4) u8 GBAControllers; // GBA Controllers plugged in (the bits are ports 1-4)
bool bWidescreen; // true indicates SYSCONF aspect ratio is 16:9, false for 4:3 bool bWidescreen; // true indicates SYSCONF aspect ratio is 16:9, false for 4:3
std::array<u8, 6> reserved; // Padding for any new config options u8 countryCode; // SYSCONF country code
std::array<u8, 5> reserved; // Padding for any new config options
std::array<char, 40> discChange; // Name of iso file to switch to, for two disc games. std::array<char, 40> discChange; // Name of iso file to switch to, for two disc games.
std::array<u8, 20> revision; // Git hash std::array<u8, 20> revision; // Git hash
u32 DSPiromHash; u32 DSPiromHash;

View file

@ -355,8 +355,13 @@ protected:
Arm64Gen::ARM64Reg exit_address_after_return_reg = Arm64Gen::ARM64Reg::INVALID_REG); Arm64Gen::ARM64Reg exit_address_after_return_reg = Arm64Gen::ARM64Reg::INVALID_REG);
void WriteBLRExit(Arm64Gen::ARM64Reg dest); void WriteBLRExit(Arm64Gen::ARM64Reg dest);
Arm64Gen::FixupBranch JumpIfCRFieldBit(int field, int bit, bool jump_if_set); void GetCRFieldBit(int field, int bit, Arm64Gen::ARM64Reg out);
void SetCRFieldBit(int field, int bit, Arm64Gen::ARM64Reg in, bool negate = false);
void ClearCRFieldBit(int field, int bit);
void SetCRFieldBit(int field, int bit);
void FixGTBeforeSettingCRFieldBit(Arm64Gen::ARM64Reg reg); void FixGTBeforeSettingCRFieldBit(Arm64Gen::ARM64Reg reg);
Arm64Gen::FixupBranch JumpIfCRFieldBit(int field, int bit, bool jump_if_set);
void UpdateFPExceptionSummary(Arm64Gen::ARM64Reg fpscr); void UpdateFPExceptionSummary(Arm64Gen::ARM64Reg fpscr);
void UpdateRoundingMode(); void UpdateRoundingMode();

View file

@ -1128,47 +1128,85 @@ void JitArm64::addzex(UGeckoInstruction inst)
int a = inst.RA, d = inst.RD; int a = inst.RA, d = inst.RD;
switch (js.carryFlag) if (gpr.IsImm(a) && (gpr.GetImm(a) == 0 || HasConstantCarry()))
{ {
case CarryFlag::InPPCState: const u32 imm = gpr.GetImm(a);
{ const bool is_all_ones = imm == 0xFFFFFFFF;
const bool allocate_reg = d == a;
gpr.BindToRegister(d, allocate_reg);
switch (js.carryFlag)
{ {
auto WA = allocate_reg ? gpr.GetScopedReg() : Arm64GPRCache::ScopedARM64Reg(gpr.R(d)); case CarryFlag::InPPCState:
LDRB(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(xer_ca));
CARRY_IF_NEEDED(ADD, ADDS, gpr.R(d), gpr.R(a), WA);
}
ComputeCarry();
break;
}
case CarryFlag::InHostCarry:
{
gpr.BindToRegister(d, d == a);
CARRY_IF_NEEDED(ADC, ADCS, gpr.R(d), gpr.R(a), ARM64Reg::WZR);
ComputeCarry();
break;
}
case CarryFlag::ConstantTrue:
{
gpr.BindToRegister(d, d == a);
CARRY_IF_NEEDED(ADD, ADDS, gpr.R(d), gpr.R(a), 1);
ComputeCarry();
break;
}
case CarryFlag::ConstantFalse:
{
if (d != a)
{ {
gpr.BindToRegister(d, false); gpr.BindToRegister(d, false);
MOV(gpr.R(d), gpr.R(a)); LDRB(IndexType::Unsigned, gpr.R(d), PPC_REG, PPCSTATE_OFF(xer_ca));
ComputeCarry(false);
break;
}
case CarryFlag::InHostCarry:
{
gpr.BindToRegister(d, false);
CSET(gpr.R(d), CCFlags::CC_CS);
ComputeCarry(false);
break;
}
case CarryFlag::ConstantTrue:
{
gpr.SetImmediate(d, imm + 1);
ComputeCarry(is_all_ones);
break;
}
case CarryFlag::ConstantFalse:
{
gpr.SetImmediate(d, imm);
ComputeCarry(false);
break;
}
} }
ComputeCarry(false);
break;
} }
else
{
switch (js.carryFlag)
{
case CarryFlag::InPPCState:
{
const bool allocate_reg = d == a;
gpr.BindToRegister(d, allocate_reg);
{
auto WA = allocate_reg ? gpr.GetScopedReg() : Arm64GPRCache::ScopedARM64Reg(gpr.R(d));
LDRB(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(xer_ca));
CARRY_IF_NEEDED(ADD, ADDS, gpr.R(d), gpr.R(a), WA);
}
ComputeCarry();
break;
}
case CarryFlag::InHostCarry:
{
gpr.BindToRegister(d, d == a);
CARRY_IF_NEEDED(ADC, ADCS, gpr.R(d), gpr.R(a), ARM64Reg::WZR);
ComputeCarry();
break;
}
case CarryFlag::ConstantTrue:
{
gpr.BindToRegister(d, d == a);
CARRY_IF_NEEDED(ADD, ADDS, gpr.R(d), gpr.R(a), 1);
ComputeCarry();
break;
}
case CarryFlag::ConstantFalse:
{
if (d != a)
{
gpr.BindToRegister(d, false);
MOV(gpr.R(d), gpr.R(a));
}
ComputeCarry(false);
break;
}
}
} }
if (inst.Rc) if (inst.Rc)
@ -1216,40 +1254,62 @@ void JitArm64::subfex(UGeckoInstruction inst)
if (gpr.IsImm(a) && (mex || gpr.IsImm(b))) if (gpr.IsImm(a) && (mex || gpr.IsImm(b)))
{ {
u32 i = gpr.GetImm(a), j = mex ? -1 : gpr.GetImm(b); const u32 i = gpr.GetImm(a);
const u32 j = mex ? -1 : gpr.GetImm(b);
gpr.BindToRegister(d, false); const u32 imm = ~i + j;
const bool is_zero = imm == 0;
const bool is_all_ones = imm == 0xFFFFFFFF;
switch (js.carryFlag) switch (js.carryFlag)
{ {
case CarryFlag::InPPCState: case CarryFlag::InPPCState:
{ {
auto WA = gpr.GetScopedReg(); gpr.BindToRegister(d, false);
LDRB(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(xer_ca)); ARM64Reg RD = gpr.R(d);
ADDI2R(gpr.R(d), WA, ~i + j, gpr.R(d)); if (is_zero)
{
LDRB(IndexType::Unsigned, RD, PPC_REG, PPCSTATE_OFF(xer_ca));
}
else
{
auto WA = gpr.GetScopedReg();
LDRB(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(xer_ca));
ADDI2R(RD, WA, imm, RD);
}
break; break;
} }
case CarryFlag::InHostCarry: case CarryFlag::InHostCarry:
{ {
auto WA = gpr.GetScopedReg(); gpr.BindToRegister(d, false);
MOVI2R(WA, ~i + j); ARM64Reg RD = gpr.R(d);
ADC(gpr.R(d), WA, ARM64Reg::WZR); if (is_all_ones)
{
// RD = -1 + carry = carry ? 0 : -1
// CSETM sets the destination to -1 if the condition is true, 0
// otherwise. Hence, the condition must be carry clear.
CSETM(RD, CC_CC);
}
else
{
MOVI2R(RD, imm);
ADC(RD, RD, ARM64Reg::WZR);
}
break; break;
} }
case CarryFlag::ConstantTrue: case CarryFlag::ConstantTrue:
{ {
gpr.SetImmediate(d, ~i + j + 1); gpr.SetImmediate(d, imm + 1);
break; break;
} }
case CarryFlag::ConstantFalse: case CarryFlag::ConstantFalse:
{ {
gpr.SetImmediate(d, ~i + j); gpr.SetImmediate(d, imm);
break; break;
} }
} }
const bool must_have_carry = Interpreter::Helper_Carry(~i, j); const bool must_have_carry = Interpreter::Helper_Carry(~i, j);
const bool might_have_carry = (~i + j) == 0xFFFFFFFF; const bool might_have_carry = is_all_ones;
if (must_have_carry) if (must_have_carry)
{ {
@ -1337,39 +1397,49 @@ void JitArm64::subfzex(UGeckoInstruction inst)
int a = inst.RA, d = inst.RD; int a = inst.RA, d = inst.RD;
gpr.BindToRegister(d, d == a); if (gpr.IsImm(a) && HasConstantCarry())
{
const u32 imm = ~gpr.GetImm(a);
const u32 carry = js.carryFlag == CarryFlag::ConstantTrue;
gpr.SetImmediate(d, imm + carry);
ComputeCarry(Interpreter::Helper_Carry(imm, carry));
}
else
{
gpr.BindToRegister(d, d == a);
switch (js.carryFlag) switch (js.carryFlag)
{
case CarryFlag::InPPCState:
{
{ {
auto WA = gpr.GetScopedReg(); case CarryFlag::InPPCState:
LDRB(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(xer_ca)); {
MVN(gpr.R(d), gpr.R(a)); {
CARRY_IF_NEEDED(ADD, ADDS, gpr.R(d), gpr.R(d), WA); auto WA = gpr.GetScopedReg();
LDRB(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(xer_ca));
MVN(gpr.R(d), gpr.R(a));
CARRY_IF_NEEDED(ADD, ADDS, gpr.R(d), gpr.R(d), WA);
}
ComputeCarry();
break;
}
case CarryFlag::InHostCarry:
{
CARRY_IF_NEEDED(SBC, SBCS, gpr.R(d), ARM64Reg::WZR, gpr.R(a));
ComputeCarry();
break;
}
case CarryFlag::ConstantTrue:
{
CARRY_IF_NEEDED(NEG, NEGS, gpr.R(d), gpr.R(a));
ComputeCarry();
break;
}
case CarryFlag::ConstantFalse:
{
MVN(gpr.R(d), gpr.R(a));
ComputeCarry(false);
break;
}
} }
ComputeCarry();
break;
}
case CarryFlag::InHostCarry:
{
CARRY_IF_NEEDED(SBC, SBCS, gpr.R(d), ARM64Reg::WZR, gpr.R(a));
ComputeCarry();
break;
}
case CarryFlag::ConstantTrue:
{
CARRY_IF_NEEDED(NEG, NEGS, gpr.R(d), gpr.R(a));
ComputeCarry();
break;
}
case CarryFlag::ConstantFalse:
{
MVN(gpr.R(d), gpr.R(a));
ComputeCarry(false);
break;
}
} }
if (inst.Rc) if (inst.Rc)
@ -1436,40 +1506,66 @@ void JitArm64::addex(UGeckoInstruction inst)
if (gpr.IsImm(a) && (mex || gpr.IsImm(b))) if (gpr.IsImm(a) && (mex || gpr.IsImm(b)))
{ {
u32 i = gpr.GetImm(a), j = mex ? -1 : gpr.GetImm(b); const u32 i = gpr.GetImm(a), j = mex ? -1 : gpr.GetImm(b);
const u32 imm = i + j;
gpr.BindToRegister(d, false); const bool is_zero = imm == 0;
const bool is_all_ones = imm == 0xFFFFFFFF;
switch (js.carryFlag) switch (js.carryFlag)
{ {
case CarryFlag::InPPCState: case CarryFlag::InPPCState:
{ {
auto WA = gpr.GetScopedReg(); gpr.BindToRegister(d, false);
LDRB(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(xer_ca)); ARM64Reg RD = gpr.R(d);
ADDI2R(gpr.R(d), WA, i + j, gpr.R(d)); if (is_zero)
{
LDRB(IndexType::Unsigned, RD, PPC_REG, PPCSTATE_OFF(xer_ca));
}
else
{
auto WA = gpr.GetScopedReg();
LDRB(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(xer_ca));
ADDI2R(RD, WA, imm, RD);
}
break; break;
} }
case CarryFlag::InHostCarry: case CarryFlag::InHostCarry:
{ {
gpr.BindToRegister(d, false);
ARM64Reg RD = gpr.R(d); ARM64Reg RD = gpr.R(d);
MOVI2R(RD, i + j); if (is_zero)
ADC(RD, RD, ARM64Reg::WZR); {
// RD = 0 + carry = carry ? 1 : 0
CSET(RD, CC_CS);
}
else if (is_all_ones)
{
// RD = -1 + carry = carry ? 0 : -1
// Note that CSETM sets the destination to -1 if the condition is true,
// and 0 otherwise. Hence, the condition must be carry clear.
CSETM(RD, CC_CC);
}
else
{
MOVI2R(RD, imm);
ADC(RD, RD, ARM64Reg::WZR);
}
break; break;
} }
case CarryFlag::ConstantTrue: case CarryFlag::ConstantTrue:
{ {
gpr.SetImmediate(d, i + j + 1); gpr.SetImmediate(d, imm + 1);
break; break;
} }
case CarryFlag::ConstantFalse: case CarryFlag::ConstantFalse:
{ {
gpr.SetImmediate(d, i + j); gpr.SetImmediate(d, imm);
break; break;
} }
} }
const bool must_have_carry = Interpreter::Helper_Carry(i, j); const bool must_have_carry = Interpreter::Helper_Carry(i, j);
const bool might_have_carry = (i + j) == 0xFFFFFFFF; const bool might_have_carry = is_all_ones;
if (must_have_carry) if (must_have_carry)
{ {

View file

@ -817,9 +817,8 @@ void JitArm64::dcbx(UGeckoInstruction inst)
STR(IndexType::Unsigned, loop_counter, PPC_REG, PPCSTATE_OFF_SPR(SPR_CTR)); STR(IndexType::Unsigned, loop_counter, PPC_REG, PPCSTATE_OFF_SPR(SPR_CTR));
// downcount -= (WA * reg_cycle_count) // downcount -= (WA * reg_cycle_count)
MUL(WB, WA, reg_cycle_count); MSUB(reg_downcount, WA, reg_cycle_count, reg_downcount);
// ^ Note that this cannot overflow because it's limited by (downcount/cycle_count). // ^ Note that this cannot overflow because it's limited by (downcount/cycle_count).
SUB(reg_downcount, reg_downcount, WB);
STR(IndexType::Unsigned, reg_downcount, PPC_REG, PPCSTATE_OFF(downcount)); STR(IndexType::Unsigned, reg_downcount, PPC_REG, PPCSTATE_OFF(downcount));
SetJumpTarget(downcount_is_zero_or_negative); SetJumpTarget(downcount_is_zero_or_negative);

View file

@ -20,6 +20,144 @@
using namespace Arm64Gen; using namespace Arm64Gen;
void JitArm64::GetCRFieldBit(int field, int bit, ARM64Reg out)
{
ARM64Reg CR = gpr.CR(field);
ARM64Reg WCR = EncodeRegTo32(CR);
switch (bit)
{
case PowerPC::CR_SO_BIT: // check bit 59 set
UBFX(out, CR, PowerPC::CR_EMU_SO_BIT, 1);
break;
case PowerPC::CR_EQ_BIT: // check bits 31-0 == 0
CMP(WCR, ARM64Reg::WZR);
CSET(out, CC_EQ);
break;
case PowerPC::CR_GT_BIT: // check val > 0
CMP(CR, ARM64Reg::ZR);
CSET(out, CC_GT);
break;
case PowerPC::CR_LT_BIT: // check bit 62 set
UBFX(out, CR, PowerPC::CR_EMU_LT_BIT, 1);
break;
default:
ASSERT_MSG(DYNA_REC, false, "Invalid CR bit");
}
}
void JitArm64::SetCRFieldBit(int field, int bit, ARM64Reg in, bool negate)
{
gpr.BindCRToRegister(field, true);
ARM64Reg CR = gpr.CR(field);
if (bit != PowerPC::CR_GT_BIT)
FixGTBeforeSettingCRFieldBit(CR);
switch (bit)
{
case PowerPC::CR_SO_BIT: // set bit 59 to input
BFI(CR, in, PowerPC::CR_EMU_SO_BIT, 1);
if (negate)
EOR(CR, CR, LogicalImm(1ULL << PowerPC::CR_EMU_SO_BIT, GPRSize::B64));
break;
case PowerPC::CR_EQ_BIT: // clear low 32 bits, set bit 0 to !input
AND(CR, CR, LogicalImm(0xFFFF'FFFF'0000'0000, GPRSize::B64));
ORR(CR, CR, in);
if (!negate)
EOR(CR, CR, LogicalImm(1ULL << 0, GPRSize::B64));
break;
case PowerPC::CR_GT_BIT: // set bit 63 to !input
BFI(CR, in, 63, 1);
if (!negate)
EOR(CR, CR, LogicalImm(1ULL << 63, GPRSize::B64));
break;
case PowerPC::CR_LT_BIT: // set bit 62 to input
BFI(CR, in, PowerPC::CR_EMU_LT_BIT, 1);
if (negate)
EOR(CR, CR, LogicalImm(1ULL << PowerPC::CR_EMU_LT_BIT, GPRSize::B64));
break;
}
ORR(CR, CR, LogicalImm(1ULL << 32, GPRSize::B64));
}
void JitArm64::ClearCRFieldBit(int field, int bit)
{
gpr.BindCRToRegister(field, true);
ARM64Reg XA = gpr.CR(field);
switch (bit)
{
case PowerPC::CR_SO_BIT:
AND(XA, XA, LogicalImm(~(u64(1) << PowerPC::CR_EMU_SO_BIT), GPRSize::B64));
break;
case PowerPC::CR_EQ_BIT:
FixGTBeforeSettingCRFieldBit(XA);
ORR(XA, XA, LogicalImm(1, GPRSize::B64));
break;
case PowerPC::CR_GT_BIT:
ORR(XA, XA, LogicalImm(u64(1) << 63, GPRSize::B64));
break;
case PowerPC::CR_LT_BIT:
AND(XA, XA, LogicalImm(~(u64(1) << PowerPC::CR_EMU_LT_BIT), GPRSize::B64));
break;
}
}
void JitArm64::SetCRFieldBit(int field, int bit)
{
gpr.BindCRToRegister(field, true);
ARM64Reg XA = gpr.CR(field);
if (bit != PowerPC::CR_GT_BIT)
FixGTBeforeSettingCRFieldBit(XA);
switch (bit)
{
case PowerPC::CR_SO_BIT:
ORR(XA, XA, LogicalImm(u64(1) << PowerPC::CR_EMU_SO_BIT, GPRSize::B64));
break;
case PowerPC::CR_EQ_BIT:
AND(XA, XA, LogicalImm(0xFFFF'FFFF'0000'0000, GPRSize::B64));
break;
case PowerPC::CR_GT_BIT:
AND(XA, XA, LogicalImm(~(u64(1) << 63), GPRSize::B64));
break;
case PowerPC::CR_LT_BIT:
ORR(XA, XA, LogicalImm(u64(1) << PowerPC::CR_EMU_LT_BIT, GPRSize::B64));
break;
}
ORR(XA, XA, LogicalImm(u64(1) << 32, GPRSize::B64));
}
void JitArm64::FixGTBeforeSettingCRFieldBit(ARM64Reg reg)
{
// GT is considered unset if the internal representation is <= 0, or in other words,
// if the internal representation either has bit 63 set or has all bits set to zero.
// If all bits are zero and we set some bit that's unrelated to GT, we need to set bit 63 so GT
// doesn't accidentally become considered set. Gross but necessary; this can break actual games.
auto WA = gpr.GetScopedReg();
ARM64Reg XA = EncodeRegTo64(WA);
ORR(XA, reg, LogicalImm(1ULL << 63, GPRSize::B64));
CMP(reg, ARM64Reg::ZR);
CSEL(reg, reg, XA, CC_NEQ);
}
FixupBranch JitArm64::JumpIfCRFieldBit(int field, int bit, bool jump_if_set) FixupBranch JitArm64::JumpIfCRFieldBit(int field, int bit, bool jump_if_set)
{ {
ARM64Reg XA = gpr.CR(field); ARM64Reg XA = gpr.CR(field);
@ -42,19 +180,6 @@ FixupBranch JitArm64::JumpIfCRFieldBit(int field, int bit, bool jump_if_set)
} }
} }
void JitArm64::FixGTBeforeSettingCRFieldBit(Arm64Gen::ARM64Reg reg)
{
// GT is considered unset if the internal representation is <= 0, or in other words,
// if the internal representation either has bit 63 set or has all bits set to zero.
// If all bits are zero and we set some bit that's unrelated to GT, we need to set bit 63 so GT
// doesn't accidentally become considered set. Gross but necessary; this can break actual games.
auto WA = gpr.GetScopedReg();
ARM64Reg XA = EncodeRegTo64(WA);
ORR(XA, reg, LogicalImm(1ULL << 63, GPRSize::B64));
CMP(reg, ARM64Reg::ZR);
CSEL(reg, reg, XA, CC_NEQ);
}
void JitArm64::UpdateFPExceptionSummary(ARM64Reg fpscr) void JitArm64::UpdateFPExceptionSummary(ARM64Reg fpscr)
{ {
auto WA = gpr.GetScopedReg(); auto WA = gpr.GetScopedReg();
@ -468,72 +593,47 @@ void JitArm64::crXXX(UGeckoInstruction inst)
INSTRUCTION_START INSTRUCTION_START
JITDISABLE(bJITSystemRegistersOff); JITDISABLE(bJITSystemRegistersOff);
// Special case: crclr if (inst.CRBA == inst.CRBB)
if (inst.CRBA == inst.CRBB && inst.CRBA == inst.CRBD && inst.SUBOP10 == 193)
{ {
// Clear CR field bit switch (inst.SUBOP10)
int field = inst.CRBD >> 2;
int bit = 3 - (inst.CRBD & 3);
gpr.BindCRToRegister(field, true);
ARM64Reg XA = gpr.CR(field);
switch (bit)
{ {
case PowerPC::CR_SO_BIT: // crclr
AND(XA, XA, LogicalImm(~(u64(1) << PowerPC::CR_EMU_SO_BIT), GPRSize::B64)); case 129: // crandc: A && ~B => 0
break; case 193: // crxor: A ^ B => 0
{
case PowerPC::CR_EQ_BIT: ClearCRFieldBit(inst.CRBD >> 2, 3 - (inst.CRBD & 3));
FixGTBeforeSettingCRFieldBit(XA); return;
ORR(XA, XA, LogicalImm(1, GPRSize::B64)); }
break; // crset
case 289: // creqv: ~(A ^ B) => 1
case PowerPC::CR_GT_BIT: case 417: // crorc: A || ~B => 1
ORR(XA, XA, LogicalImm(u64(1) << 63, GPRSize::B64)); {
break; SetCRFieldBit(inst.CRBD >> 2, 3 - (inst.CRBD & 3));
return;
case PowerPC::CR_LT_BIT: }
AND(XA, XA, LogicalImm(~(u64(1) << PowerPC::CR_EMU_LT_BIT), GPRSize::B64)); case 257: // crand: A && B => A
break; case 449: // cror: A || B => A
{
auto WA = gpr.GetScopedReg();
ARM64Reg XA = EncodeRegTo64(WA);
GetCRFieldBit(inst.CRBA >> 2, 3 - (inst.CRBA & 3), XA);
SetCRFieldBit(inst.CRBD >> 2, 3 - (inst.CRBD & 3), XA, false);
return;
}
case 33: // crnor: ~(A || B) => ~A
case 225: // crnand: ~(A && B) => ~A
{
auto WA = gpr.GetScopedReg();
ARM64Reg XA = EncodeRegTo64(WA);
GetCRFieldBit(inst.CRBA >> 2, 3 - (inst.CRBA & 3), XA);
SetCRFieldBit(inst.CRBD >> 2, 3 - (inst.CRBD & 3), XA, true);
return;
}
} }
return;
} }
// Special case: crset // crnor or crnand
if (inst.CRBA == inst.CRBB && inst.CRBA == inst.CRBD && inst.SUBOP10 == 289) const bool negate_result = inst.SUBOP10 == 33 || inst.SUBOP10 == 225;
{
// SetCRFieldBit
int field = inst.CRBD >> 2;
int bit = 3 - (inst.CRBD & 3);
gpr.BindCRToRegister(field, true);
ARM64Reg XA = gpr.CR(field);
if (bit != PowerPC::CR_GT_BIT)
FixGTBeforeSettingCRFieldBit(XA);
switch (bit)
{
case PowerPC::CR_SO_BIT:
ORR(XA, XA, LogicalImm(u64(1) << PowerPC::CR_EMU_SO_BIT, GPRSize::B64));
break;
case PowerPC::CR_EQ_BIT:
AND(XA, XA, LogicalImm(0xFFFF'FFFF'0000'0000, GPRSize::B64));
break;
case PowerPC::CR_GT_BIT:
AND(XA, XA, LogicalImm(~(u64(1) << 63), GPRSize::B64));
break;
case PowerPC::CR_LT_BIT:
ORR(XA, XA, LogicalImm(u64(1) << PowerPC::CR_EMU_LT_BIT, GPRSize::B64));
break;
}
ORR(XA, XA, LogicalImm(u64(1) << 32, GPRSize::B64));
return;
}
auto WA = gpr.GetScopedReg(); auto WA = gpr.GetScopedReg();
ARM64Reg XA = EncodeRegTo64(WA); ARM64Reg XA = EncodeRegTo64(WA);
@ -541,106 +641,42 @@ void JitArm64::crXXX(UGeckoInstruction inst)
auto WB = gpr.GetScopedReg(); auto WB = gpr.GetScopedReg();
ARM64Reg XB = EncodeRegTo64(WB); ARM64Reg XB = EncodeRegTo64(WB);
// creqv or crnand or crnor GetCRFieldBit(inst.CRBA >> 2, 3 - (inst.CRBA & 3), XA);
bool negateA = inst.SUBOP10 == 289 || inst.SUBOP10 == 225 || inst.SUBOP10 == 33; GetCRFieldBit(inst.CRBB >> 2, 3 - (inst.CRBB & 3), XB);
// crandc or crorc or crnand or crnor
bool negateB =
inst.SUBOP10 == 129 || inst.SUBOP10 == 417 || inst.SUBOP10 == 225 || inst.SUBOP10 == 33;
// GetCRFieldBit
for (int i = 0; i < 2; i++)
{
int field = i ? inst.CRBB >> 2 : inst.CRBA >> 2;
int bit = i ? 3 - (inst.CRBB & 3) : 3 - (inst.CRBA & 3);
ARM64Reg out = i ? XB : XA;
bool negate = i ? negateB : negateA;
ARM64Reg XC = gpr.CR(field);
ARM64Reg WC = EncodeRegTo32(XC);
switch (bit)
{
case PowerPC::CR_SO_BIT: // check bit 59 set
UBFX(out, XC, PowerPC::CR_EMU_SO_BIT, 1);
if (negate)
EOR(out, out, LogicalImm(1, GPRSize::B64));
break;
case PowerPC::CR_EQ_BIT: // check bits 31-0 == 0
CMP(WC, ARM64Reg::WZR);
CSET(out, negate ? CC_NEQ : CC_EQ);
break;
case PowerPC::CR_GT_BIT: // check val > 0
CMP(XC, ARM64Reg::ZR);
CSET(out, negate ? CC_LE : CC_GT);
break;
case PowerPC::CR_LT_BIT: // check bit 62 set
UBFX(out, XC, PowerPC::CR_EMU_LT_BIT, 1);
if (negate)
EOR(out, out, LogicalImm(1, GPRSize::B64));
break;
default:
ASSERT_MSG(DYNA_REC, false, "Invalid CR bit");
}
}
// Compute combined bit // Compute combined bit
switch (inst.SUBOP10) switch (inst.SUBOP10)
{ {
case 33: // crnor: ~(A || B) == (~A && ~B) case 225: // crnand: ~(A && B)
case 129: // crandc: A && ~B
case 257: // crand: A && B case 257: // crand: A && B
AND(XA, XA, XB); AND(XA, XA, XB);
break; break;
case 129: // crandc: A && ~B
BIC(XA, XA, XB);
break;
case 193: // crxor: A ^ B case 193: // crxor: A ^ B
case 289: // creqv: ~(A ^ B) = ~A ^ B
EOR(XA, XA, XB); EOR(XA, XA, XB);
break; break;
case 225: // crnand: ~(A && B) == (~A || ~B) case 289: // creqv: ~(A ^ B) = A ^ ~B
case 417: // crorc: A || ~B EON(XA, XA, XB);
break;
case 33: // crnor: ~(A || B)
case 449: // cror: A || B case 449: // cror: A || B
ORR(XA, XA, XB); ORR(XA, XA, XB);
break; break;
case 417: // crorc: A || ~B
ORN(XA, XA, XB);
break;
} }
} }
// Store result bit in CRBD // Store result bit in CRBD
int field = inst.CRBD >> 2; SetCRFieldBit(inst.CRBD >> 2, 3 - (inst.CRBD & 3), XA, negate_result);
int bit = 3 - (inst.CRBD & 3);
gpr.BindCRToRegister(field, true);
ARM64Reg CR = gpr.CR(field);
if (bit != PowerPC::CR_GT_BIT)
FixGTBeforeSettingCRFieldBit(CR);
switch (bit)
{
case PowerPC::CR_SO_BIT: // set bit 59 to input
BFI(CR, XA, PowerPC::CR_EMU_SO_BIT, 1);
break;
case PowerPC::CR_EQ_BIT: // clear low 32 bits, set bit 0 to !input
AND(CR, CR, LogicalImm(0xFFFF'FFFF'0000'0000, GPRSize::B64));
EOR(XA, XA, LogicalImm(1, GPRSize::B64));
ORR(CR, CR, XA);
break;
case PowerPC::CR_GT_BIT: // set bit 63 to !input
EOR(XA, XA, LogicalImm(1, GPRSize::B64));
BFI(CR, XA, 63, 1);
break;
case PowerPC::CR_LT_BIT: // set bit 62 to input
BFI(CR, XA, PowerPC::CR_EMU_LT_BIT, 1);
break;
}
ORR(CR, CR, LogicalImm(1ULL << 32, GPRSize::B64));
} }
void JitArm64::mfcr(UGeckoInstruction inst) void JitArm64::mfcr(UGeckoInstruction inst)

View file

@ -110,7 +110,7 @@ JitBase::~JitBase()
CPUThreadConfigCallback::RemoveConfigChangedCallback(m_registered_config_callback_id); CPUThreadConfigCallback::RemoveConfigChangedCallback(m_registered_config_callback_id);
} }
bool JitBase::DoesConfigNeedRefresh() bool JitBase::DoesConfigNeedRefresh() const
{ {
return std::ranges::any_of(JIT_SETTINGS, [this](const auto& pair) { return std::ranges::any_of(JIT_SETTINGS, [this](const auto& pair) {
return this->*pair.first != Config::Get(*pair.second); return this->*pair.first != Config::Get(*pair.second);
@ -276,7 +276,7 @@ bool JitBase::CanMergeNextInstructions(int count) const
return true; return true;
} }
bool JitBase::ShouldHandleFPExceptionForInstruction(const PPCAnalyst::CodeOp* op) bool JitBase::ShouldHandleFPExceptionForInstruction(const PPCAnalyst::CodeOp* op) const
{ {
if (jo.fp_exceptions) if (jo.fp_exceptions)
return (op->opinfo->flags & FL_FLOAT_EXCEPTION) != 0; return (op->opinfo->flags & FL_FLOAT_EXCEPTION) != 0;

View file

@ -167,7 +167,7 @@ protected:
static const std::array<std::pair<bool JitBase::*, const Config::Info<bool>*>, 23> JIT_SETTINGS; static const std::array<std::pair<bool JitBase::*, const Config::Info<bool>*>, 23> JIT_SETTINGS;
bool DoesConfigNeedRefresh(); bool DoesConfigNeedRefresh() const;
void RefreshConfig(); void RefreshConfig();
void InitFastmemArena(); void InitFastmemArena();
@ -178,8 +178,16 @@ protected:
void CleanUpAfterStackFault(); void CleanUpAfterStackFault();
bool CanMergeNextInstructions(int count) const; bool CanMergeNextInstructions(int count) const;
bool HasConstantCarry() const
{
#ifdef _M_ARM_64
return js.carryFlag == CarryFlag::ConstantTrue || js.carryFlag == CarryFlag::ConstantFalse;
#else
return false;
#endif
}
bool ShouldHandleFPExceptionForInstruction(const PPCAnalyst::CodeOp* op); bool ShouldHandleFPExceptionForInstruction(const PPCAnalyst::CodeOp* op) const;
public: public:
explicit JitBase(Core::System& system); explicit JitBase(Core::System& system);

View file

@ -580,12 +580,11 @@ endif()
if(APPLE) if(APPLE)
include(BundleUtilities) include(BundleUtilities)
set(BUNDLE_PATH ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/DolphinQt.app)
# Ask for an application bundle. # Ask for an application bundle.
set_target_properties(dolphin-mpn PROPERTIES set_target_properties(dolphin-mpn PROPERTIES
MACOSX_BUNDLE true MACOSX_BUNDLE true
MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_BINARY_DIR}/Info.plist" MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/Info.plist.in"
XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY "" XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY ""
OUTPUT_NAME DolphinQt OUTPUT_NAME DolphinQt
) )
@ -622,6 +621,9 @@ if(APPLE)
source_group("Resources" FILES "${CMAKE_SOURCE_DIR}/Data/${res}") source_group("Resources" FILES "${CMAKE_SOURCE_DIR}/Data/${res}")
endforeach() endforeach()
include(DolphinInjectVersionInfo)
dolphin_inject_version_info(dolphin-emu)
# Copy MoltenVK into the bundle # Copy MoltenVK into the bundle
if(ENABLE_VULKAN) if(ENABLE_VULKAN)
if(USE_BUNDLED_MOLTENVK) if(USE_BUNDLED_MOLTENVK)
@ -656,7 +658,7 @@ if(APPLE)
COMMAND "${CMAKE_SOURCE_DIR}/Tools/mac-codesign.sh" COMMAND "${CMAKE_SOURCE_DIR}/Tools/mac-codesign.sh"
"-e" "${CMAKE_CURRENT_SOURCE_DIR}/DolphinEmu$<$<CONFIG:Debug>:Debug>.entitlements" "-e" "${CMAKE_CURRENT_SOURCE_DIR}/DolphinEmu$<$<CONFIG:Debug>:Debug>.entitlements"
"${MACOS_CODE_SIGNING_IDENTITY}" "${MACOS_CODE_SIGNING_IDENTITY}"
"${BUNDLE_PATH}" "$<TARGET_BUNDLE_DIR:dolphin-emu>"
) )
endif() endif()
else() else()

View file

@ -185,11 +185,13 @@ void AdvancedWidget::CreateWidgets()
dump_layout->addWidget(m_frame_dumps_resolution_type, 0, 1); dump_layout->addWidget(m_frame_dumps_resolution_type, 0, 1);
#if defined(HAVE_FFMPEG) #if defined(HAVE_FFMPEG)
m_dump_use_ffv1 = m_dump_use_lossless =
new ConfigBool(tr("Use Lossless Codec (FFV1)"), Config::GFX_USE_FFV1, m_game_layer); new ConfigBool(tr("Use Lossless Codec (Ut Video)"), Config::GFX_USE_LOSSLESS, m_game_layer);
m_dump_bitrate = new ConfigInteger(0, 1000000, Config::GFX_BITRATE_KBPS, m_game_layer, 1000); m_dump_bitrate = new ConfigInteger(0, 1000000, Config::GFX_BITRATE_KBPS, m_game_layer, 1000);
m_dump_bitrate->setEnabled(!m_dump_use_ffv1->isChecked()); m_dump_bitrate->setEnabled(!m_dump_use_lossless->isChecked());
dump_layout->addWidget(m_dump_use_ffv1, 1, 0);
dump_layout->addWidget(m_dump_use_lossless, 1, 0);
dump_layout->addWidget(new QLabel(tr("Bitrate (kbps):")), 2, 0); dump_layout->addWidget(new QLabel(tr("Bitrate (kbps):")), 2, 0);
dump_layout->addWidget(m_dump_bitrate, 2, 1); dump_layout->addWidget(m_dump_bitrate, 2, 1);
#endif #endif
@ -261,9 +263,8 @@ void AdvancedWidget::ConnectWidgets()
}); });
connect(m_enable_graphics_mods, &QCheckBox::toggled, this, connect(m_enable_graphics_mods, &QCheckBox::toggled, this,
[this](bool checked) { emit Settings::Instance().EnableGfxModsChanged(checked); }); [this](bool checked) { emit Settings::Instance().EnableGfxModsChanged(checked); });
#if defined(HAVE_FFMPEG) #if defined(HAVE_FFMPEG)
connect(m_dump_use_ffv1, &QCheckBox::toggled, this, connect(m_dump_use_lossless, &QCheckBox::toggled, this,
[this](bool checked) { m_dump_bitrate->setEnabled(!checked); }); [this](bool checked) { m_dump_bitrate->setEnabled(!checked); });
#endif #endif
} }
@ -391,8 +392,9 @@ void AdvancedWidget::AddDescriptions()
"possible input for external editing software.<br><br><dolphin_emphasis>If unsure, leave " "possible input for external editing software.<br><br><dolphin_emphasis>If unsure, leave "
"this at \"Aspect Ratio Corrected Internal Resolution\".</dolphin_emphasis>"); "this at \"Aspect Ratio Corrected Internal Resolution\".</dolphin_emphasis>");
#if defined(HAVE_FFMPEG) #if defined(HAVE_FFMPEG)
static const char TR_USE_FFV1_DESCRIPTION[] = static const char TR_USE_LOSSLESS_DESCRIPTION[] =
QT_TR_NOOP("Encodes frame dumps using the FFV1 codec.<br><br><dolphin_emphasis>If " QT_TR_NOOP("Encodes frame dumps using the Ut Video codec. If this option is unchecked, a "
"lossy Xvid codec will be used.<br><br><dolphin_emphasis>If "
"unsure, leave this unchecked.</dolphin_emphasis>"); "unsure, leave this unchecked.</dolphin_emphasis>");
#endif #endif
static const char TR_PNG_COMPRESSION_LEVEL_DESCRIPTION[] = static const char TR_PNG_COMPRESSION_LEVEL_DESCRIPTION[] =
@ -483,7 +485,7 @@ void AdvancedWidget::AddDescriptions()
m_enable_graphics_mods->SetDescription(tr(TR_LOAD_GRAPHICS_MODS_DESCRIPTION)); m_enable_graphics_mods->SetDescription(tr(TR_LOAD_GRAPHICS_MODS_DESCRIPTION));
m_frame_dumps_resolution_type->SetDescription(tr(TR_FRAME_DUMPS_RESOLUTION_TYPE_DESCRIPTION)); m_frame_dumps_resolution_type->SetDescription(tr(TR_FRAME_DUMPS_RESOLUTION_TYPE_DESCRIPTION));
#ifdef HAVE_FFMPEG #ifdef HAVE_FFMPEG
m_dump_use_ffv1->SetDescription(tr(TR_USE_FFV1_DESCRIPTION)); m_dump_use_lossless->SetDescription(tr(TR_USE_LOSSLESS_DESCRIPTION));
#endif #endif
m_png_compression_level->SetDescription(tr(TR_PNG_COMPRESSION_LEVEL_DESCRIPTION)); m_png_compression_level->SetDescription(tr(TR_PNG_COMPRESSION_LEVEL_DESCRIPTION));
m_enable_cropping->SetDescription(tr(TR_CROPPING_DESCRIPTION)); m_enable_cropping->SetDescription(tr(TR_CROPPING_DESCRIPTION));

View file

@ -60,7 +60,7 @@ private:
ConfigBool* m_dump_base_textures; ConfigBool* m_dump_base_textures;
// Frame dumping // Frame dumping
ConfigBool* m_dump_use_ffv1; ConfigBool* m_dump_use_lossless;
ConfigChoice* m_frame_dumps_resolution_type; ConfigChoice* m_frame_dumps_resolution_type;
ConfigInteger* m_dump_bitrate; ConfigInteger* m_dump_bitrate;
ConfigInteger* m_png_compression_level; ConfigInteger* m_png_compression_level;

View file

@ -39,12 +39,6 @@
<string>English</string> <string>English</string>
<key>CFBundlePackageType</key> <key>CFBundlePackageType</key>
<string>APPL</string> <string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>${DOLPHIN_WC_DESCRIBE}</string>
<key>CFBundleLongVersionString</key>
<string>${DOLPHIN_WC_REVISION}</string>
<key>CFBundleVersion</key>
<string>${DOLPHIN_VERSION_MAJOR}.${DOLPHIN_VERSION_MINOR}</string>
<key>NSHumanReadableCopyright</key> <key>NSHumanReadableCopyright</key>
<string>Licensed under GPL version 2 or later (GPLv2+)</string> <string>Licensed under GPL version 2 or later (GPLv2+)</string>
<key>LSApplicationCategoryType</key> <key>LSApplicationCategoryType</key>

View file

@ -16,7 +16,7 @@ add_dependencies(MacUpdater dolphin_scmrev)
set_target_properties(MacUpdater PROPERTIES set_target_properties(MacUpdater PROPERTIES
MACOSX_BUNDLE true MACOSX_BUNDLE true
MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_BINARY_DIR}/Info.plist" MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/Info.plist.in"
OUTPUT_NAME "Dolphin Updater") OUTPUT_NAME "Dolphin Updater")
target_compile_options(MacUpdater PRIVATE -x objective-c++) target_compile_options(MacUpdater PRIVATE -x objective-c++)
@ -53,6 +53,9 @@ foreach(sb ${STORYBOARDS})
COMMENT "Compiling Storyboard ${sb}...") COMMENT "Compiling Storyboard ${sb}...")
endforeach() endforeach()
include(DolphinInjectVersionInfo)
dolphin_inject_version_info(MacUpdater)
if(NOT SKIP_POSTPROCESS_BUNDLE) if(NOT SKIP_POSTPROCESS_BUNDLE)
# Update library references to make the bundle portable # Update library references to make the bundle portable
include(DolphinPostprocessBundle) include(DolphinPostprocessBundle)

View file

@ -16,10 +16,6 @@
<string>Dolphin Updater</string> <string>Dolphin Updater</string>
<key>CFBundlePackageType</key> <key>CFBundlePackageType</key>
<string>APPL</string> <string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>${DOLPHIN_WC_DESCRIBE}</string>
<key>CFBundleVersion</key>
<string>${DOLPHIN_VERSION_MAJOR}.${DOLPHIN_VERSION_MINOR}</string>
<key>LSMinimumSystemVersion</key> <key>LSMinimumSystemVersion</key>
<string>${CMAKE_OSX_DEPLOYMENT_TARGET}</string> <string>${CMAKE_OSX_DEPLOYMENT_TARGET}</string>
<key>NSHumanReadableCopyright</key> <key>NSHumanReadableCopyright</key>

View file

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<!-- This plist file is merged with the application's Info.plist to set its version info. -->
<key>CFBundleShortVersionString</key>
<string>${DOLPHIN_WC_DESCRIBE}</string>
<key>CFBundleLongVersionString</key>
<string>${DOLPHIN_WC_REVISION}</string>
<key>CFBundleVersion</key>
<string>${DOLPHIN_VERSION_MAJOR}.${DOLPHIN_VERSION_MINOR}</string>
</dict>
</plist>

View file

@ -217,7 +217,7 @@ bool FFMpegFrameDump::CreateVideoFile()
return false; return false;
} }
const std::string& codec_name = g_Config.bUseFFV1 ? "ffv1" : g_Config.sDumpCodec; const std::string& codec_name = g_Config.bUseLossless ? "utvideo" : g_Config.sDumpCodec;
AVCodecID codec_id = output_format->video_codec; AVCodecID codec_id = output_format->video_codec;

View file

@ -123,7 +123,7 @@ void VideoConfig::Refresh()
bDumpEFBTarget = Config::Get(Config::GFX_DUMP_EFB_TARGET); bDumpEFBTarget = Config::Get(Config::GFX_DUMP_EFB_TARGET);
bDumpXFBTarget = Config::Get(Config::GFX_DUMP_XFB_TARGET); bDumpXFBTarget = Config::Get(Config::GFX_DUMP_XFB_TARGET);
bDumpFramesAsImages = Config::Get(Config::GFX_DUMP_FRAMES_AS_IMAGES); bDumpFramesAsImages = Config::Get(Config::GFX_DUMP_FRAMES_AS_IMAGES);
bUseFFV1 = Config::Get(Config::GFX_USE_FFV1); bUseLossless = Config::Get(Config::GFX_USE_LOSSLESS);
sDumpFormat = Config::Get(Config::GFX_DUMP_FORMAT); sDumpFormat = Config::Get(Config::GFX_DUMP_FORMAT);
sDumpCodec = Config::Get(Config::GFX_DUMP_CODEC); sDumpCodec = Config::Get(Config::GFX_DUMP_CODEC);
sDumpPixelFormat = Config::Get(Config::GFX_DUMP_PIXEL_FORMAT); sDumpPixelFormat = Config::Get(Config::GFX_DUMP_PIXEL_FORMAT);

View file

@ -194,7 +194,7 @@ struct VideoConfig final
bool bDumpEFBTarget = false; bool bDumpEFBTarget = false;
bool bDumpXFBTarget = false; bool bDumpXFBTarget = false;
bool bDumpFramesAsImages = false; bool bDumpFramesAsImages = false;
bool bUseFFV1 = false; bool bUseLossless = false;
std::string sDumpCodec; std::string sDumpCodec;
std::string sDumpPixelFormat; std::string sDumpPixelFormat;
std::string sDumpEncoder; std::string sDumpEncoder;