Skip to content

Commit e8c7e9d

Browse files
authored
Merge branch 'main' into metal
2 parents c6e8b5c + b53b223 commit e8c7e9d

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

53 files changed

+999
-392
lines changed

.github/workflows/build.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ jobs:
3939
- name: "Install system dependencies"
4040
run: |
4141
sudo apt update -qq
42-
sudo apt install -y clang-15 cmake freeglut3-dev libgcrypt20-dev libglm-dev libgtk-3-dev libpulse-dev libsecret-1-dev libsystemd-dev libudev-dev nasm ninja-build
42+
sudo apt install -y clang-15 cmake freeglut3-dev libgcrypt20-dev libglm-dev libgtk-3-dev libpulse-dev libsecret-1-dev libsystemd-dev libudev-dev nasm ninja-build libbluetooth-dev
4343
4444
- name: "Setup cmake"
4545
uses: jwlawson/actions-setup-cmake@v2
@@ -96,7 +96,7 @@ jobs:
9696
- name: "Install system dependencies"
9797
run: |
9898
sudo apt update -qq
99-
sudo apt install -y clang-15 cmake freeglut3-dev libgcrypt20-dev libglm-dev libgtk-3-dev libpulse-dev libsecret-1-dev libsystemd-dev nasm ninja-build appstream
99+
sudo apt install -y clang-15 cmake freeglut3-dev libgcrypt20-dev libglm-dev libgtk-3-dev libpulse-dev libsecret-1-dev libsystemd-dev nasm ninja-build appstream libbluetooth-dev
100100
101101
- name: "Build AppImage"
102102
run: |

BUILD.md

+3-3
Original file line numberDiff line numberDiff line change
@@ -46,18 +46,18 @@ To compile Cemu, a recent enough compiler and STL with C++20 support is required
4646
### Dependencies
4747

4848
#### For Arch and derivatives:
49-
`sudo pacman -S --needed base-devel clang cmake freeglut git glm gtk3 libgcrypt libpulse libsecret linux-headers llvm nasm ninja systemd unzip zip`
49+
`sudo pacman -S --needed base-devel bluez-libs clang cmake freeglut git glm gtk3 libgcrypt libpulse libsecret linux-headers llvm nasm ninja systemd unzip zip`
5050

5151
#### For Debian, Ubuntu and derivatives:
52-
`sudo apt install -y cmake curl clang-15 freeglut3-dev git libgcrypt20-dev libglm-dev libgtk-3-dev libpulse-dev libsecret-1-dev libsystemd-dev libtool nasm ninja-build`
52+
`sudo apt install -y cmake curl clang-15 freeglut3-dev git libbluetooth-dev libgcrypt20-dev libglm-dev libgtk-3-dev libpulse-dev libsecret-1-dev libsystemd-dev libtool nasm ninja-build`
5353

5454
You may also need to install `libusb-1.0-0-dev` as a workaround for an issue with the vcpkg hidapi package.
5555

5656
At Step 3 in [Build Cemu using cmake and clang](#build-cemu-using-cmake-and-clang), use the following command instead:
5757
`cmake -S . -B build -DCMAKE_BUILD_TYPE=release -DCMAKE_C_COMPILER=/usr/bin/clang-15 -DCMAKE_CXX_COMPILER=/usr/bin/clang++-15 -G Ninja -DCMAKE_MAKE_PROGRAM=/usr/bin/ninja`
5858

5959
#### For Fedora and derivatives:
60-
`sudo dnf install clang cmake cubeb-devel freeglut-devel git glm-devel gtk3-devel kernel-headers libgcrypt-devel libsecret-devel libtool libusb1-devel llvm nasm ninja-build perl-core systemd-devel zlib-devel zlib-static`
60+
`sudo dnf install bluez-libs clang cmake cubeb-devel freeglut-devel git glm-devel gtk3-devel kernel-headers libgcrypt-devel libsecret-devel libtool libusb1-devel llvm nasm ninja-build perl-core systemd-devel zlib-devel zlib-static`
6161

6262
### Build Cemu
6363

CMakeLists.txt

+7
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ endif()
9898
if (UNIX AND NOT APPLE)
9999
option(ENABLE_WAYLAND "Build with Wayland support" ON)
100100
option(ENABLE_FERAL_GAMEMODE "Enables Feral Interactive GameMode Support" ON)
101+
option(ENABLE_BLUEZ "Build with Bluez support" ON)
101102
endif()
102103

103104
if (APPLE)
@@ -189,6 +190,12 @@ if (UNIX AND NOT APPLE)
189190
endif()
190191
find_package(GTK3 REQUIRED)
191192

193+
if(ENABLE_BLUEZ)
194+
find_package(bluez REQUIRED)
195+
set(ENABLE_WIIMOTE ON)
196+
add_compile_definitions(HAS_BLUEZ)
197+
endif()
198+
192199
endif()
193200

194201
if (ENABLE_VULKAN)

bin/resources/ar/‏‏cemu.mo

79.9 KB
Binary file not shown.

bin/resources/de/cemu.mo

3.75 KB
Binary file not shown.

bin/resources/ru/cemu.mo

1.11 KB
Binary file not shown.

bin/resources/sv/cemu.mo

50.9 KB
Binary file not shown.

cmake/Findbluez.cmake

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# SPDX-FileCopyrightText: 2022 Andrea Pappacoda <[email protected]>
2+
# SPDX-License-Identifier: ISC
3+
4+
find_package(bluez CONFIG)
5+
if (NOT bluez_FOUND)
6+
find_package(PkgConfig)
7+
if (PKG_CONFIG_FOUND)
8+
pkg_search_module(bluez IMPORTED_TARGET GLOBAL bluez-1.0 bluez)
9+
if (bluez_FOUND)
10+
add_library(bluez::bluez ALIAS PkgConfig::bluez)
11+
endif ()
12+
endif ()
13+
endif ()
14+
15+
find_package_handle_standard_args(bluez
16+
REQUIRED_VARS
17+
bluez_LINK_LIBRARIES
18+
bluez_FOUND
19+
VERSION_VAR bluez_VERSION
20+
)

src/CMakeLists.txt

+2-2
Original file line numberDiff line numberDiff line change
@@ -82,8 +82,8 @@ if (MACOS_BUNDLE)
8282
set(MACOSX_BUNDLE_ICON_FILE "cemu.icns")
8383
set(MACOSX_BUNDLE_GUI_IDENTIFIER "info.cemu.Cemu")
8484
set(MACOSX_BUNDLE_BUNDLE_NAME "Cemu")
85-
set(MACOSX_BUNDLE_SHORT_VERSION_STRING ${CMAKE_PROJECT_VERSION})
86-
set(MACOSX_BUNDLE_BUNDLE_VERSION ${CMAKE_PROJECT_VERSION})
85+
set(MACOSX_BUNDLE_SHORT_VERSION_STRING "${EMULATOR_VERSION_MAJOR}.${EMULATOR_VERSION_MINOR}.${EMULATOR_VERSION_PATCH}")
86+
set(MACOSX_BUNDLE_BUNDLE_VERSION "${EMULATOR_VERSION_MAJOR}.${EMULATOR_VERSION_MINOR}.${EMULATOR_VERSION_PATCH}")
8787
set(MACOSX_BUNDLE_COPYRIGHT "Copyright © 2024 Cemu Project")
8888

8989
set(MACOSX_BUNDLE_CATEGORY "public.app-category.games")

src/Cafe/CMakeLists.txt

+7-1
Original file line numberDiff line numberDiff line change
@@ -594,6 +594,12 @@ set_property(TARGET CemuCafe PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CON
594594

595595
target_include_directories(CemuCafe PUBLIC "../")
596596

597+
if (glslang_VERSION VERSION_LESS "15.0.0")
598+
set(glslang_target "glslang::SPIRV")
599+
else()
600+
set(glslang_target "glslang")
601+
endif()
602+
597603
target_link_libraries(CemuCafe PRIVATE
598604
CemuAsm
599605
CemuAudio
@@ -609,7 +615,7 @@ target_link_libraries(CemuCafe PRIVATE
609615
Boost::nowide
610616
CURL::libcurl
611617
fmt::fmt
612-
glslang::SPIRV
618+
${glslang_target}
613619
ih264d
614620
OpenSSL::Crypto
615621
OpenSSL::SSL

src/Cafe/GraphicPack/GraphicPack2.cpp

+26-18
Original file line numberDiff line numberDiff line change
@@ -347,7 +347,7 @@ GraphicPack2::GraphicPack2(fs::path rulesPath, IniParser& rules)
347347
const auto preset_name = rules.FindOption("name");
348348
if (!preset_name)
349349
{
350-
cemuLog_log(LogType::Force, "Graphic pack \"{}\": Preset in line {} skipped because it has no name option defined", m_name, rules.GetCurrentSectionLineNumber());
350+
cemuLog_log(LogType::Force, "Graphic pack \"{}\": Preset in line {} skipped because it has no name option defined", GetNormalizedPathString(), rules.GetCurrentSectionLineNumber());
351351
continue;
352352
}
353353

@@ -371,7 +371,7 @@ GraphicPack2::GraphicPack2(fs::path rulesPath, IniParser& rules)
371371
}
372372
catch (const std::exception & ex)
373373
{
374-
cemuLog_log(LogType::Force, "Graphic pack \"{}\": Can't parse preset \"{}\": {}", m_name, *preset_name, ex.what());
374+
cemuLog_log(LogType::Force, "Graphic pack \"{}\": Can't parse preset \"{}\": {}", GetNormalizedPathString(), *preset_name, ex.what());
375375
}
376376
}
377377
else if (boost::iequals(currentSectionName, "RAM"))
@@ -385,7 +385,7 @@ GraphicPack2::GraphicPack2(fs::path rulesPath, IniParser& rules)
385385
{
386386
if (m_version <= 5)
387387
{
388-
cemuLog_log(LogType::Force, "Graphic pack \"{}\": [RAM] options are only available for graphic pack version 6 or higher", m_name, optionNameBuf);
388+
cemuLog_log(LogType::Force, "Graphic pack \"{}\": [RAM] options are only available for graphic pack version 6 or higher", GetNormalizedPathString(), optionNameBuf);
389389
throw std::exception();
390390
}
391391

@@ -395,12 +395,12 @@ GraphicPack2::GraphicPack2(fs::path rulesPath, IniParser& rules)
395395
{
396396
if (addrEnd <= addrStart)
397397
{
398-
cemuLog_log(LogType::Force, "Graphic pack \"{}\": start address (0x{:08x}) must be greater than end address (0x{:08x}) for {}", m_name, addrStart, addrEnd, optionNameBuf);
398+
cemuLog_log(LogType::Force, "Graphic pack \"{}\": start address (0x{:08x}) must be greater than end address (0x{:08x}) for {}", GetNormalizedPathString(), addrStart, addrEnd, optionNameBuf);
399399
throw std::exception();
400400
}
401401
else if ((addrStart & 0xFFF) != 0 || (addrEnd & 0xFFF) != 0)
402402
{
403-
cemuLog_log(LogType::Force, "Graphic pack \"{}\": addresses for %s are not aligned to 0x1000", m_name, optionNameBuf);
403+
cemuLog_log(LogType::Force, "Graphic pack \"{}\": addresses for %s are not aligned to 0x1000", GetNormalizedPathString(), optionNameBuf);
404404
throw std::exception();
405405
}
406406
else
@@ -410,7 +410,7 @@ GraphicPack2::GraphicPack2(fs::path rulesPath, IniParser& rules)
410410
}
411411
else
412412
{
413-
cemuLog_log(LogType::Force, "Graphic pack \"{}\": has invalid syntax for option {}", m_name, optionNameBuf);
413+
cemuLog_log(LogType::Force, "Graphic pack \"{}\": has invalid syntax for option {}", GetNormalizedPathString(), optionNameBuf);
414414
throw std::exception();
415415
}
416416
}
@@ -424,24 +424,32 @@ GraphicPack2::GraphicPack2(fs::path rulesPath, IniParser& rules)
424424
std::unordered_map<std::string, std::vector<PresetPtr>> tmp_map;
425425

426426
// all vars must be defined in the default preset vars before
427-
for (const auto& entry : m_presets)
427+
std::vector<std::pair<std::string, std::string>> mismatchingPresetVars;
428+
for (const auto& presetEntry : m_presets)
428429
{
429-
tmp_map[entry->category].emplace_back(entry);
430-
431-
for (auto& kv : entry->variables)
430+
tmp_map[presetEntry->category].emplace_back(presetEntry);
431+
432+
for (auto& presetVar : presetEntry->variables)
432433
{
433-
const auto it = m_preset_vars.find(kv.first);
434+
const auto it = m_preset_vars.find(presetVar.first);
434435
if (it == m_preset_vars.cend())
435436
{
436-
cemuLog_log(LogType::Force, "Graphic pack: \"{}\" contains preset variables which are not defined in the default section", m_name);
437-
throw std::exception();
437+
mismatchingPresetVars.emplace_back(presetEntry->name, presetVar.first);
438+
continue;
438439
}
439-
440440
// overwrite var type with default var type
441-
kv.second.first = it->second.first;
441+
presetVar.second.first = it->second.first;
442442
}
443443
}
444444

445+
if(!mismatchingPresetVars.empty())
446+
{
447+
cemuLog_log(LogType::Force, "Graphic pack \"{}\" contains preset variables which are not defined in the [Default] section:", GetNormalizedPathString());
448+
for (const auto& [presetName, varName] : mismatchingPresetVars)
449+
cemuLog_log(LogType::Force, "Preset: {} Variable: {}", presetName, varName);
450+
throw std::exception();
451+
}
452+
445453
// have first entry be default active for every category if no default= is set
446454
for(auto entry : get_values(tmp_map))
447455
{
@@ -471,22 +479,22 @@ GraphicPack2::GraphicPack2(fs::path rulesPath, IniParser& rules)
471479
auto& p2 = kv.second[i + 1];
472480
if (p1->variables.size() != p2->variables.size())
473481
{
474-
cemuLog_log(LogType::Force, "Graphic pack: \"{}\" contains inconsistent preset variables", m_name);
482+
cemuLog_log(LogType::Force, "Graphic pack: \"{}\" contains inconsistent preset variables", GetNormalizedPathString());
475483
throw std::exception();
476484
}
477485

478486
std::set<std::string> keys1(get_keys(p1->variables).begin(), get_keys(p1->variables).end());
479487
std::set<std::string> keys2(get_keys(p2->variables).begin(), get_keys(p2->variables).end());
480488
if (keys1 != keys2)
481489
{
482-
cemuLog_log(LogType::Force, "Graphic pack: \"{}\" contains inconsistent preset variables", m_name);
490+
cemuLog_log(LogType::Force, "Graphic pack: \"{}\" contains inconsistent preset variables", GetNormalizedPathString());
483491
throw std::exception();
484492
}
485493

486494
if(p1->is_default)
487495
{
488496
if(has_default)
489-
cemuLog_log(LogType::Force, "Graphic pack: \"{}\" has more than one preset with the default key set for the same category \"{}\"", m_name, p1->name);
497+
cemuLog_log(LogType::Force, "Graphic pack: \"{}\" has more than one preset with the default key set for the same category \"{}\"", GetNormalizedPathString(), p1->name);
490498
p1->active = true;
491499
has_default = true;
492500
}

src/Cafe/HW/Espresso/Debugger/Debugger.cpp

+28
Original file line numberDiff line numberDiff line change
@@ -447,6 +447,34 @@ bool debugger_hasPatch(uint32 address)
447447
return false;
448448
}
449449

450+
void debugger_removePatch(uint32 address)
451+
{
452+
for (sint32 i = 0; i < debuggerState.patches.size(); i++)
453+
{
454+
auto& patch = debuggerState.patches[i];
455+
if (address < patch->address || address >= (patch->address + patch->length))
456+
continue;
457+
MPTR startAddress = patch->address;
458+
MPTR endAddress = patch->address + patch->length;
459+
// remove any breakpoints overlapping with the patch
460+
for (auto& bp : debuggerState.breakpoints)
461+
{
462+
if (bp->address + 4 > startAddress && bp->address < endAddress)
463+
{
464+
bp->enabled = false;
465+
debugger_updateExecutionBreakpoint(bp->address);
466+
}
467+
}
468+
// restore original data
469+
memcpy(MEMPTR<void>(startAddress).GetPtr(), patch->origData.data(), patch->length);
470+
PPCRecompiler_invalidateRange(startAddress, endAddress);
471+
// remove patch
472+
delete patch;
473+
debuggerState.patches.erase(debuggerState.patches.begin() + i);
474+
return;
475+
}
476+
}
477+
450478
void debugger_stepInto(PPCInterpreter_t* hCPU, bool updateDebuggerWindow = true)
451479
{
452480
bool isRecEnabled = ppcRecompilerEnabled;

src/Cafe/HW/Espresso/Debugger/Debugger.h

+1
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ void debugger_updateExecutionBreakpoint(uint32 address, bool forceRestore = fals
114114

115115
void debugger_createPatch(uint32 address, std::span<uint8> patchData);
116116
bool debugger_hasPatch(uint32 address);
117+
void debugger_removePatch(uint32 address);
117118

118119
void debugger_forceBreak(); // force breakpoint at the next possible instruction
119120
bool debugger_isTrapped();

src/Cafe/HW/Latte/Core/LattePerformanceMonitor.h

+1
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ typedef struct
124124
LattePerfStatCounter numGraphicPipelines;
125125
LattePerfStatCounter numImages;
126126
LattePerfStatCounter numImageViews;
127+
LattePerfStatCounter numSamplers;
127128
LattePerfStatCounter numRenderPass;
128129
LattePerfStatCounter numFramebuffer;
129130

src/Cafe/HW/Latte/LegacyShaderDecompiler/LatteDecompiler.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,8 @@ bool LatteDecompiler_IsALUTransInstruction(bool isOP3, uint32 opcode)
370370
opcode == ALU_OP2_INST_LSHR_INT ||
371371
opcode == ALU_OP2_INST_MAX_INT ||
372372
opcode == ALU_OP2_INST_MIN_INT ||
373+
opcode == ALU_OP2_INST_MAX_UINT ||
374+
opcode == ALU_OP2_INST_MIN_UINT ||
373375
opcode == ALU_OP2_INST_MOVA_FLOOR ||
374376
opcode == ALU_OP2_INST_MOVA_INT ||
375377
opcode == ALU_OP2_INST_SETE_DX10 ||

src/Cafe/HW/Latte/LegacyShaderDecompiler/LatteDecompilerAnalyzer.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,8 @@ bool _isIntegerInstruction(const LatteDecompilerALUInstruction& aluInstruction)
140140
case ALU_OP2_INST_SUB_INT:
141141
case ALU_OP2_INST_MAX_INT:
142142
case ALU_OP2_INST_MIN_INT:
143+
case ALU_OP2_INST_MAX_UINT:
144+
case ALU_OP2_INST_MIN_UINT:
143145
case ALU_OP2_INST_SETE_INT:
144146
case ALU_OP2_INST_SETGT_INT:
145147
case ALU_OP2_INST_SETGE_INT:

src/Cafe/HW/Latte/LegacyShaderDecompiler/LatteDecompilerEmitGLSL.cpp

+12-8
Original file line numberDiff line numberDiff line change
@@ -1415,19 +1415,23 @@ void _emitALUOP2InstructionCode(LatteDecompilerShaderContext* shaderContext, Lat
14151415
}
14161416
else if( aluInstruction->opcode == ALU_OP2_INST_ADD_INT )
14171417
_emitALUOperationBinary<LATTE_DECOMPILER_DTYPE_SIGNED_INT>(shaderContext, aluInstruction, " + ");
1418-
else if( aluInstruction->opcode == ALU_OP2_INST_MAX_INT || aluInstruction->opcode == ALU_OP2_INST_MIN_INT )
1418+
else if( aluInstruction->opcode == ALU_OP2_INST_MAX_INT || aluInstruction->opcode == ALU_OP2_INST_MIN_INT ||
1419+
aluInstruction->opcode == ALU_OP2_INST_MAX_UINT || aluInstruction->opcode == ALU_OP2_INST_MIN_UINT)
14191420
{
14201421
// not verified
1422+
bool isUnsigned = aluInstruction->opcode == ALU_OP2_INST_MAX_UINT || aluInstruction->opcode == ALU_OP2_INST_MIN_UINT;
1423+
auto opType = isUnsigned ? LATTE_DECOMPILER_DTYPE_UNSIGNED_INT : LATTE_DECOMPILER_DTYPE_SIGNED_INT;
14211424
_emitInstructionOutputVariableName(shaderContext, aluInstruction);
1422-
if( aluInstruction->opcode == ALU_OP2_INST_MAX_INT )
1423-
src->add(" = max(");
1425+
src->add(" = ");
1426+
_emitTypeConversionPrefix(shaderContext, opType, outputType);
1427+
if( aluInstruction->opcode == ALU_OP2_INST_MAX_INT || aluInstruction->opcode == ALU_OP2_INST_MAX_UINT )
1428+
src->add("max(");
14241429
else
1425-
src->add(" = min(");
1426-
_emitTypeConversionPrefix(shaderContext, LATTE_DECOMPILER_DTYPE_SIGNED_INT, outputType);
1427-
_emitOperandInputCode(shaderContext, aluInstruction, 0, LATTE_DECOMPILER_DTYPE_SIGNED_INT);
1430+
src->add("min(");
1431+
_emitOperandInputCode(shaderContext, aluInstruction, 0, opType);
14281432
src->add(", ");
1429-
_emitOperandInputCode(shaderContext, aluInstruction, 1, LATTE_DECOMPILER_DTYPE_SIGNED_INT);
1430-
_emitTypeConversionSuffix(shaderContext, LATTE_DECOMPILER_DTYPE_SIGNED_INT, outputType);
1433+
_emitOperandInputCode(shaderContext, aluInstruction, 1, opType);
1434+
_emitTypeConversionSuffix(shaderContext, opType, outputType);
14311435
src->add(");" _CRLF);
14321436
}
14331437
else if( aluInstruction->opcode == ALU_OP2_INST_SUB_INT )

src/Cafe/HW/Latte/LegacyShaderDecompiler/LatteDecompilerInstructions.h

+2
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,8 @@
6060
#define ALU_OP2_INST_SUB_INT (0x035) // integer instruction
6161
#define ALU_OP2_INST_MAX_INT (0x036) // integer instruction
6262
#define ALU_OP2_INST_MIN_INT (0x037) // integer instruction
63+
#define ALU_OP2_INST_MAX_UINT (0x038) // integer instruction
64+
#define ALU_OP2_INST_MIN_UINT (0x039) // integer instruction
6365
#define ALU_OP2_INST_SETE_INT (0x03A) // integer instruction
6466
#define ALU_OP2_INST_SETGT_INT (0x03B) // integer instruction
6567
#define ALU_OP2_INST_SETGE_INT (0x03C) // integer instruction

0 commit comments

Comments
 (0)