diff --git a/.gitmodules b/.gitmodules
index 2dd1e55e8095..82a4f4bf24c6 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -50,3 +50,6 @@
[submodule "ext/naett"]
path = ext/naett
url = https://github.com/erkkah/naett.git
+[submodule "ext/libchdr"]
+ path = ext/libchdr
+ url = https://github.com/rtissera/libchdr.git
diff --git a/CMakeLists.txt b/CMakeLists.txt
index d36a7e4b7814..af616d3e2a9f 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -2317,7 +2317,9 @@ else()
include_directories(ext/zstd/lib)
endif()
-target_link_libraries(${CoreLibName} Common native kirk cityhash sfmt19937 xbrz xxhash rcheevos ${GlslangLibs}
+include_directories(ext/libchdr/include)
+
+target_link_libraries(${CoreLibName} Common native chdr kirk cityhash sfmt19937 xbrz xxhash rcheevos ${GlslangLibs}
${CoreExtraLibs} ${OPENGL_LIBRARIES} ${X11_LIBRARIES} ${CMAKE_DL_LIBS})
if(NOT HTTPS_NOT_AVAILABLE)
diff --git a/Common/Common.vcxproj.filters b/Common/Common.vcxproj.filters
index 288b7dc289e5..a0852244bacc 100644
--- a/Common/Common.vcxproj.filters
+++ b/Common/Common.vcxproj.filters
@@ -1073,6 +1073,9 @@
{34f45db9-5c08-49cb-b349-b9e760ce3213}
+
+ {b681797d-7747-487f-b448-5ef5b2d2805b}
+
diff --git a/Core/Core.vcxproj b/Core/Core.vcxproj
index cbba66cf140f..4b037a33843a 100644
--- a/Core/Core.vcxproj
+++ b/Core/Core.vcxproj
@@ -138,7 +138,7 @@
Level3
- ..\ffmpeg\WindowsInclude;..\ffmpeg\Windows\x86\include;../common;..;../ext/glew;../ext/snappy;../ext/libpng17;../ext/zlib;../ext;../ext/zstd/lib
+ ..\ffmpeg\WindowsInclude;..\ext\libchdr\include;..\ffmpeg\Windows\x86\include;../common;..;../ext/glew;../ext/snappy;../ext/libpng17;../ext/zlib;../ext;../ext/zstd/lib
_CRTDBG_MAP_ALLOC;USING_WIN_UI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;USE_FFMPEG;WITH_UPNP;WIN32;_ARCH_32=1;_M_IX86=1;_DEBUG;_LIB;_UNICODE;UNICODE;MINIUPNP_STATICLIB;ARMIPS_USE_STD_FILESYSTEM;%(PreprocessorDefinitions)
StreamingSIMDExtensions2
Precise
@@ -165,7 +165,7 @@
Level3
- ..\ffmpeg\WindowsInclude;..\ffmpeg\Windows\x86_64\include;../common;..;../ext/glew;../ext/snappy;../ext/libpng17;../ext/zlib;../ext;../ext/zstd/lib;../ext/zstd/lib
+ ..\ffmpeg\WindowsInclude;..\ext\libchdr\include;..\ffmpeg\Windows\x86_64\include;../common;..;../ext/glew;../ext/snappy;../ext/libpng17;../ext/zlib;../ext;../ext/zstd/lib;../ext/zstd/lib
_CRTDBG_MAP_ALLOC;USING_WIN_UI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;USE_FFMPEG;WITH_UPNP;WIN32;_ARCH_64=1;_M_X64=1;_DEBUG;_LIB;_UNICODE;UNICODE;MINIUPNP_STATICLIB;ARMIPS_USE_STD_FILESYSTEM;%(PreprocessorDefinitions)
NotSet
Precise
@@ -193,7 +193,7 @@
Level3
- ..\ffmpeg\WindowsInclude;..\ffmpeg\Windows\aarch64\include;../common;..;../ext/glew;../ext/snappy;../ext/libpng17;../ext/zlib;../ext;../ext/zstd/lib
+ ..\ffmpeg\WindowsInclude;..\ext\libchdr\include;..\ffmpeg\Windows\aarch64\include;../common;..;../ext/glew;../ext/snappy;../ext/libpng17;../ext/zlib;../ext;../ext/zstd/lib
_CRTDBG_MAP_ALLOC;USING_WIN_UI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;USE_FFMPEG;WITH_UPNP;WIN32;_ARCH_64=1;_DEBUG;_LIB;_UNICODE;UNICODE;ARMIPS_USE_STD_FILESYSTEM;%(PreprocessorDefinitions)
NotSet
Precise
@@ -221,7 +221,7 @@
Level3
- ..\ffmpeg\WindowsInclude;..\ffmpeg\Windows\arm\include;../common;..;../ext/glew;../ext/snappy;../ext/libpng17;../ext/zlib;../ext;../ext/zstd/lib
+ ..\ffmpeg\WindowsInclude;..\ext\libchdr\include;..\ffmpeg\Windows\arm\include;../common;..;../ext/glew;../ext/snappy;../ext/libpng17;../ext/zlib;../ext;../ext/zstd/lib
_CRTDBG_MAP_ALLOC;USING_WIN_UI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;USE_FFMPEG;WITH_UPNP;WIN32;_ARCH_32=1;_DEBUG;_LIB;_UNICODE;UNICODE;ARMIPS_USE_STD_FILESYSTEM;%(PreprocessorDefinitions)
NotSet
Precise
@@ -253,7 +253,7 @@
MaxSpeed
true
true
- ..\ffmpeg\WindowsInclude;..\ffmpeg\Windows\x86\include;../common;..;../ext/glew;../ext/snappy;../ext/libpng17;../ext/zlib;../ext;../ext/zstd/lib
+ ..\ffmpeg\WindowsInclude;..\ext\libchdr\include;..\ffmpeg\Windows\x86\include;../common;..;../ext/glew;../ext/snappy;../ext/libpng17;../ext/zlib;../ext;../ext/zstd/lib
false
StreamingSIMDExtensions2
Precise
@@ -286,7 +286,7 @@
MaxSpeed
true
true
- ..\ffmpeg\WindowsInclude;..\ffmpeg\Windows\x86_64\include;../common;..;../ext/glew;../ext/snappy;../ext/libpng17;../ext/zlib;../ext;../ext/zstd/lib;../ext/zstd/lib
+ ..\ffmpeg\WindowsInclude;..\ext\libchdr\include;..\ffmpeg\Windows\x86_64\include;../common;..;../ext/glew;../ext/snappy;../ext/libpng17;../ext/zlib;../ext;../ext/zstd/lib;../ext/zstd/lib
NotSet
Precise
false
@@ -321,7 +321,7 @@
MaxSpeed
true
true
- ..\ffmpeg\WindowsInclude;..\ffmpeg\Windows\aarch64\include;../common;..;../ext/glew;../ext/snappy;../ext/libpng17;../ext/zlib;../ext;../ext/zstd/lib
+ ..\ffmpeg\WindowsInclude;..\ext\libchdr\include;..\ffmpeg\Windows\aarch64\include;../common;..;../ext/glew;../ext/snappy;../ext/libpng17;../ext/zlib;../ext;../ext/zstd/lib
NotSet
Precise
false
@@ -356,7 +356,7 @@
MaxSpeed
true
true
- ..\ffmpeg\WindowsInclude;..\ffmpeg\Windows\arm\include;../common;..;../ext/glew;../ext/snappy;../ext/libpng17;../ext/zlib;../ext;../ext/zstd/lib
+ ..\ffmpeg\WindowsInclude;..\ext\libchdr\include;..\ffmpeg\Windows\arm\include;../common;..;../ext/glew;../ext/snappy;../ext/libpng17;../ext/zlib;../ext;../ext/zstd/lib
NotSet
Precise
false
@@ -1466,6 +1466,9 @@
{129e5e2b-39c1-4d84-96fe-dfd22dbb4a25}
+
+ {956f1f48-b612-46d8-89ee-96996dcd9383}
+
{d8a71225-178b-424e-96c1-cc3be2c1b047}
diff --git a/Core/FileSystems/BlockDevices.cpp b/Core/FileSystems/BlockDevices.cpp
index 05f3a87d1a4d..eaeb4c6261ee 100644
--- a/Core/FileSystems/BlockDevices.cpp
+++ b/Core/FileSystems/BlockDevices.cpp
@@ -24,8 +24,11 @@
#include "Common/System/OSD.h"
#include "Common/Log.h"
#include "Common/Swap.h"
+#include "Common/File/FileUtil.h"
+#include "Common/File/DirListing.h"
#include "Core/Loaders.h"
#include "Core/FileSystems/BlockDevices.h"
+#include "libchdr/chd.h"
extern "C"
{
@@ -37,19 +40,28 @@ extern "C"
std::mutex NPDRMDemoBlockDevice::mutex_;
BlockDevice *constructBlockDevice(FileLoader *fileLoader) {
- // Check for CISO
if (!fileLoader->Exists())
return nullptr;
- char buffer[4]{};
- size_t size = fileLoader->ReadAt(0, 1, 4, buffer);
- if (size == 4 && !memcmp(buffer, "CISO", 4))
+ char buffer[8]{};
+ size_t size = fileLoader->ReadAt(0, 1, 8, buffer);
+ if (size != 8) {
+ // Bad or empty file
+ return nullptr;
+ }
+
+ // Check for CISO
+ if (!memcmp(buffer, "CISO", 4)) {
return new CISOFileBlockDevice(fileLoader);
- if (size == 4 && !memcmp(buffer, "\x00PBP", 4)) {
+ } else if (!memcmp(buffer, "\x00PBP", 4)) {
uint32_t psarOffset = 0;
size = fileLoader->ReadAt(0x24, 1, 4, &psarOffset);
if (size == 4 && psarOffset < fileLoader->FileSize())
return new NPDRMDemoBlockDevice(fileLoader);
+ } else if (!memcmp(buffer, "MComprHD", 8)) {
+ return new CHDFileBlockDevice(fileLoader);
}
+
+ // Should be just a regular ISO. Let's open it as a plain block device and let the other systems take over.
return new FileBlockDevice(fileLoader);
}
@@ -519,3 +531,150 @@ bool NPDRMDemoBlockDevice::ReadBlock(int blockNumber, u8 *outPtr, bool uncached)
return true;
}
+
+/*
+ * CHD file
+ */
+static const UINT8 nullsha1[CHD_SHA1_BYTES] = { 0 };
+
+struct CHDImpl {
+ chd_file *chd = nullptr;
+ const chd_header *header = nullptr;
+};
+
+CHDFileBlockDevice::CHDFileBlockDevice(FileLoader *fileLoader)
+ : BlockDevice(fileLoader), impl_(new CHDImpl())
+{
+ Path paths[8];
+ paths[0] = fileLoader->GetPath();
+ int depth = 0;
+
+ /*
+ // TODO: Support parent/child CHD files.
+
+ // Default, in case of failure
+ numBlocks = 0;
+
+ chd_header childHeader;
+
+ chd_error err = chd_read_header(paths[0].c_str(), &childHeader);
+ if (err != CHDERR_NONE) {
+ ERROR_LOG(LOADER, "Error loading CHD header for '%s': %s", paths[0].c_str(), chd_error_string(err));
+ NotifyReadError();
+ return;
+ }
+
+ if (memcmp(nullsha1, childHeader.parentsha1, sizeof(childHeader.sha1)) != 0) {
+ chd_header parentHeader;
+
+ // Look for parent CHD in current directory
+ Path chdDir = paths[0].NavigateUp();
+
+ std::vector files;
+ if (File::GetFilesInDir(chdDir, &files)) {
+ parentHeader.length = 0;
+
+ for (const auto &file : files) {
+ std::string extension = file.fullName.GetFileExtension();
+ if (extension != ".chd") {
+ continue;
+ }
+
+ if (chd_read_header(filepath.c_str(), &parentHeader) == CHDERR_NONE &&
+ memcmp(parentHeader.sha1, childHeader.parentsha1, sizeof(parentHeader.sha1)) == 0) {
+ // ERROR_LOG(LOADER, "Checking '%s'", filepath.c_str());
+ paths[++depth] = filepath;
+ break;
+ }
+ }
+
+ // Check if parentHeader was opened
+ if (parentHeader.length == 0) {
+ ERROR_LOG(LOADER, "Error loading CHD '%s': parents not found", fileLoader->GetPath().c_str());
+ NotifyReadError();
+ return;
+ }
+ memcpy(childHeader.parentsha1, parentHeader.parentsha1, sizeof(childHeader.parentsha1));
+ } while (memcmp(nullsha1, childHeader.parentsha1, sizeof(childHeader.sha1)) != 0);
+ }
+ */
+
+ chd_file *parent = NULL;
+ chd_file *child = NULL;
+
+ FILE *file = File::OpenCFile(paths[depth], "rb");
+ if (!file) {
+ ERROR_LOG(LOADER, "Error opening CHD file '%s'", paths[depth].c_str());
+ NotifyReadError();
+ return;
+ }
+ chd_error err = chd_open_file(file, CHD_OPEN_READ, NULL, &child);
+ if (err != CHDERR_NONE) {
+ ERROR_LOG(LOADER, "Error loading CHD '%s': %s", paths[depth].c_str(), chd_error_string(err));
+ NotifyReadError();
+ return;
+ }
+
+ // We won't enter this loop until we enable the parent/child stuff above.
+ for (int d = depth - 1; d >= 0; d--) {
+ parent = child;
+ child = NULL;
+ // TODO: Use chd_open_file
+ err = chd_open(paths[d].c_str(), CHD_OPEN_READ, parent, &child);
+ if (err != CHDERR_NONE) {
+ ERROR_LOG(LOADER, "Error loading CHD '%s': %s", paths[d].c_str(), chd_error_string(err));
+ NotifyReadError();
+ return;
+ }
+ }
+ impl_->chd = child;
+
+ impl_->header = chd_get_header(impl_->chd);
+ readBuffer = new u8[impl_->header->hunkbytes];
+ currentHunk = -1;
+ blocksPerHunk = impl_->header->hunkbytes / impl_->header->unitbytes;
+ numBlocks = impl_->header->unitcount;
+}
+
+CHDFileBlockDevice::~CHDFileBlockDevice()
+{
+ if (numBlocks > 0) {
+ chd_close(impl_->chd);
+ delete[] readBuffer;
+ }
+}
+
+bool CHDFileBlockDevice::ReadBlock(int blockNumber, u8 *outPtr, bool uncached)
+{
+ if ((u32)blockNumber >= numBlocks) {
+ memset(outPtr, 0, GetBlockSize());
+ return false;
+ }
+ u32 hunk = blockNumber / blocksPerHunk;
+ u32 blockInHunk = blockNumber % blocksPerHunk;
+
+ if (currentHunk != hunk) {
+ chd_error err = chd_read(impl_->chd, hunk, readBuffer);
+ if (err != CHDERR_NONE) {
+ ERROR_LOG(LOADER, "CHD read failed: %d %d %s", blockNumber, hunk, chd_error_string(err));
+ NotifyReadError();
+ }
+ }
+ memcpy(outPtr, readBuffer + blockInHunk * impl_->header->unitbytes, GetBlockSize());
+
+ return true;
+}
+
+bool CHDFileBlockDevice::ReadBlocks(u32 minBlock, int count, u8 *outPtr) {
+ if (minBlock >= numBlocks) {
+ memset(outPtr, 0, GetBlockSize() * count);
+ return false;
+ }
+
+ for (int i = 0; i < count; i++) {
+ if (!ReadBlock(minBlock + i, outPtr + i * GetBlockSize())) {
+ return false;
+ }
+ }
+ return true;
+}
diff --git a/Core/FileSystems/BlockDevices.h b/Core/FileSystems/BlockDevices.h
index 3575d8cded8a..fd27f667fb91 100644
--- a/Core/FileSystems/BlockDevices.h
+++ b/Core/FileSystems/BlockDevices.h
@@ -130,5 +130,23 @@ class NPDRMDemoBlockDevice : public BlockDevice {
u8 *tempBuf;
};
+struct CHDImpl;
+
+class CHDFileBlockDevice : public BlockDevice {
+public:
+ CHDFileBlockDevice(FileLoader *fileLoader);
+ ~CHDFileBlockDevice();
+ bool ReadBlock(int blockNumber, u8 *outPtr, bool uncached = false) override;
+ bool ReadBlocks(u32 minBlock, int count, u8 *outPtr) override;
+ u32 GetNumBlocks() override { return numBlocks; }
+ bool IsDisc() override { return true; }
+
+private:
+ std::unique_ptr impl_;
+ u8 *readBuffer;
+ u32 currentHunk;
+ u32 blocksPerHunk;
+ u32 numBlocks;
+};
BlockDevice *constructBlockDevice(FileLoader *fileLoader);
diff --git a/Core/Loaders.cpp b/Core/Loaders.cpp
index 28190edd8080..6bb5f5d34365 100644
--- a/Core/Loaders.cpp
+++ b/Core/Loaders.cpp
@@ -94,6 +94,8 @@ IdentifiedFileType Identify_File(FileLoader *fileLoader, std::string *errorStrin
return IdentifiedFileType::PSP_ISO;
} else if (extension == ".cso") {
return IdentifiedFileType::PSP_ISO;
+ } else if (extension == ".chd") {
+ return IdentifiedFileType::PSP_ISO;
} else if (extension == ".ppst") {
return IdentifiedFileType::PPSSPP_SAVESTATE;
} else if (extension == ".ppdmp") {
diff --git a/Qt/QtMain.cpp b/Qt/QtMain.cpp
index 9991d78a18ed..7e7d57f480af 100644
--- a/Qt/QtMain.cpp
+++ b/Qt/QtMain.cpp
@@ -304,7 +304,7 @@ bool MainUI::HandleCustomEvent(QEvent *e) {
const char *filter = "All files (*.*)";
switch (fileType) {
case BrowseFileType::BOOTABLE:
- filter = "PSP ROMs (*.iso *.cso *.pbp *.elf *.zip *.ppdmp)";
+ filter = "PSP ROMs (*.iso *.cso *.chd *.pbp *.elf *.zip *.ppdmp)";
break;
case BrowseFileType::IMAGE:
filter = "Pictures (*.jpg *.png)";
diff --git a/Qt/mainwindow.cpp b/Qt/mainwindow.cpp
index 6f9722d4963b..1c3401ec0f64 100644
--- a/Qt/mainwindow.cpp
+++ b/Qt/mainwindow.cpp
@@ -125,7 +125,7 @@ void MainWindow::bootDone()
/* SIGNALS */
void MainWindow::loadAct()
{
- QString filename = QFileDialog::getOpenFileName(NULL, "Load File", g_Config.currentDirectory.c_str(), "PSP ROMs (*.pbp *.elf *.iso *.cso *.prx)");
+ QString filename = QFileDialog::getOpenFileName(NULL, "Load File", g_Config.currentDirectory.c_str(), "PSP ROMs (*.pbp *.elf *.iso *.cso *.chd *.prx)");
if (QFile::exists(filename))
{
QFileInfo info(filename);
@@ -255,7 +255,7 @@ void MainWindow::resetAct()
void MainWindow::switchUMDAct()
{
- QString filename = QFileDialog::getOpenFileName(NULL, "Switch UMD", g_Config.currentDirectory.c_str(), "PSP ROMs (*.pbp *.elf *.iso *.cso *.prx)");
+ QString filename = QFileDialog::getOpenFileName(NULL, "Switch UMD", g_Config.currentDirectory.c_str(), "PSP ROMs (*.pbp *.elf *.iso *.cso *.chd *.prx)");
if (QFile::exists(filename))
{
QFileInfo info(filename);
diff --git a/UI/MainScreen.cpp b/UI/MainScreen.cpp
index a90fef737473..6349daad3384 100644
--- a/UI/MainScreen.cpp
+++ b/UI/MainScreen.cpp
@@ -846,7 +846,7 @@ void GameBrowser::Refresh() {
}
} else if (!listingPending_) {
std::vector fileInfo;
- path_.GetListing(fileInfo, "iso:cso:pbp:elf:prx:ppdmp:");
+ path_.GetListing(fileInfo, "iso:cso:chd:pbp:elf:prx:ppdmp:");
for (size_t i = 0; i < fileInfo.size(); i++) {
bool isGame = !fileInfo[i].isDirectory;
bool isSaveData = false;
diff --git a/UI/RetroAchievementScreens.cpp b/UI/RetroAchievementScreens.cpp
index d8ebceb9ffc9..a92663d3f53a 100644
--- a/UI/RetroAchievementScreens.cpp
+++ b/UI/RetroAchievementScreens.cpp
@@ -516,7 +516,7 @@ void RenderAchievement(UIContext &dc, const rc_client_achievement_t *achievement
char cacheKey[256];
snprintf(cacheKey, sizeof(cacheKey), "ai:%s:%s", achievement->badge_name, iconState == RC_CLIENT_ACHIEVEMENT_STATE_UNLOCKED ? "unlocked" : "locked");
if (RC_OK == rc_client_achievement_get_image_url(achievement, iconState, temp, sizeof(temp))) {
- Achievements::DownloadImageIfMissing(cacheKey, std::move(std::string(temp)));
+ Achievements::DownloadImageIfMissing(cacheKey, std::string(temp));
if (g_iconCache.BindIconTexture(&dc, cacheKey)) {
dc.Draw()->DrawTexRect(Bounds(bounds.x + padding, bounds.y + padding, iconSpace, iconSpace), 0.0f, 0.0f, 1.0f, 1.0f, whiteAlpha(alpha));
}
@@ -560,7 +560,7 @@ void RenderGameAchievementSummary(UIContext &dc, const Bounds &bounds, float alp
char cacheKey[256];
snprintf(cacheKey, sizeof(cacheKey), "gi:%s", gameInfo->badge_name);
if (RC_OK == rc_client_game_get_image_url(gameInfo, url, sizeof(url))) {
- Achievements::DownloadImageIfMissing(cacheKey, std::move(std::string(url)));
+ Achievements::DownloadImageIfMissing(cacheKey, std::string(url));
if (g_iconCache.BindIconTexture(&dc, cacheKey)) {
dc.Draw()->DrawTexRect(Bounds(bounds.x, bounds.y, iconSpace, iconSpace), 0.0f, 0.0f, 1.0f, 1.0f, whiteAlpha(alpha));
}
@@ -660,7 +660,7 @@ void RenderLeaderboardEntry(UIContext &dc, const rc_client_leaderboard_entry_t *
snprintf(cacheKey, sizeof(cacheKey), "lbe:%s", entry->user);
char temp[512];
if (RC_OK == rc_client_leaderboard_entry_get_user_image_url(entry, temp, sizeof(temp))) {
- Achievements::DownloadImageIfMissing(cacheKey, std::move(std::string(temp)));
+ Achievements::DownloadImageIfMissing(cacheKey, std::string(temp));
if (g_iconCache.BindIconTexture(&dc, cacheKey)) {
dc.Draw()->DrawTexRect(Bounds(bounds.x + iconLeft, bounds.y + 4.0f, 64.0f, 64.0f), 0.0f, 0.0f, 1.0f, 1.0f, whiteAlpha(alpha));
}
diff --git a/UWP/CoreUWP/CoreUWP.vcxproj b/UWP/CoreUWP/CoreUWP.vcxproj
index d74fdbbb8d2f..4ea24c0ce377 100644
--- a/UWP/CoreUWP/CoreUWP.vcxproj
+++ b/UWP/CoreUWP/CoreUWP.vcxproj
@@ -66,7 +66,7 @@
false
false
pch.h
- ../../ffmpeg/Windows10/ARM/include;../../ffmpeg/WindowsInclude;../..;../../ext/native;../../ext/snappy;../../ext/libpng17;../../Common;../../ext/zlib;../../ext/zstd/lib;../../ext;../../ext/armips/;../../ext/armips/ext/filesystem/include/;../../ext/armips/ext/tinyformat/;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories)
+ ../../ext/libchdr/include;../../ffmpeg/Windows10/ARM/include;../../ffmpeg/WindowsInclude;../..;../../ext/native;../../ext/snappy;../../ext/libpng17;../../Common;../../ext/zlib;../../ext/zstd/lib;../../ext;../../ext/armips/;../../ext/armips/ext/filesystem/include/;../../ext/armips/ext/tinyformat/;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories)
USE_FFMPEG;WITH_UPNP;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;NOMINMAX;_ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE=1;ARMIPS_USE_STD_FILESYSTEM;%(ClCompile.PreprocessorDefinitions)
stdcpp17
@@ -82,7 +82,7 @@
false
false
pch.h
- ../../ffmpeg/Windows10/ARM64/include;../../ffmpeg/WindowsInclude;../..;../../ext/native;../../ext/snappy;../../ext/libpng17;../../Common;../../ext/zlib;../../ext/zstd/lib;../../ext;../../ext/armips/;../../ext/armips/ext/filesystem/include/;../../ext/armips/ext/tinyformat/;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories)
+ ../../ext/libchdr/include;../../ffmpeg/Windows10/ARM64/include;../../ffmpeg/WindowsInclude;../..;../../ext/native;../../ext/snappy;../../ext/libpng17;../../Common;../../ext/zlib;../../ext/zstd/lib;../../ext;../../ext/armips/;../../ext/armips/ext/filesystem/include/;../../ext/armips/ext/tinyformat/;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories)
USE_FFMPEG;WITH_UPNP;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;NOMINMAX;_ARM64_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE=1;ARMIPS_USE_STD_FILESYSTEM;%(ClCompile.PreprocessorDefinitions)
stdcpp17
@@ -98,7 +98,7 @@
false
false
pch.h
- ../../ffmpeg/Windows10/x64/include;../../ffmpeg/WindowsInclude;../..;../../ext/native;../../ext/snappy;../../ext/libpng17;../../Common;../../ext/zlib;../../ext/zstd/lib;../../ext;../../ext/armips/;../../ext/armips/ext/filesystem/include/;../../ext/armips/ext/tinyformat/;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories)
+ ../../ext/libchdr/include;../../ffmpeg/Windows10/x64/include;../../ffmpeg/WindowsInclude;../..;../../ext/native;../../ext/snappy;../../ext/libpng17;../../Common;../../ext/zlib;../../ext/zstd/lib;../../ext;../../ext/armips/;../../ext/armips/ext/filesystem/include/;../../ext/armips/ext/tinyformat/;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories)
USE_FFMPEG;WITH_UPNP;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;NOMINMAX;_UNICODE;UNICODE;ARMIPS_USE_STD_FILESYSTEM;%(PreprocessorDefinitions)
stdcpp17
@@ -1110,6 +1110,9 @@
{acb316ca-3ecb-48e5-be0a-91e72d5b0f12}
+
+ {191b6f52-ad66-4172-bd20-733eeeceef8c}
+
{d31fd4f0-53eb-477c-9dc7-149796f628e2}
diff --git a/UWP/PPSSPP_UWP.sln b/UWP/PPSSPP_UWP.sln
index 8571149bc01a..8f1c7d1ae8f7 100644
--- a/UWP/PPSSPP_UWP.sln
+++ b/UWP/PPSSPP_UWP.sln
@@ -36,6 +36,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cpu_features_UWP", "cpu_fea
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "rcheevos_UWP", "rcheevos_UWP\rcheevos_UWP.vcxproj", "{4C9D52D0-310A-4347-8991-E3788CB22169}"
EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libchdr_UWP", "libchdr_UWP\libchdr_UWP.vcxproj", "{191B6F52-AD66-4172-BD20-733EEECEEF8C}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|ARM = Debug|ARM
@@ -310,6 +312,24 @@ Global
{4C9D52D0-310A-4347-8991-E3788CB22169}.UWP Gold|ARM64.Build.0 = Release|ARM64
{4C9D52D0-310A-4347-8991-E3788CB22169}.UWP Gold|x64.ActiveCfg = Release|x64
{4C9D52D0-310A-4347-8991-E3788CB22169}.UWP Gold|x64.Build.0 = Release|x64
+ {191B6F52-AD66-4172-BD20-733EEECEEF8C}.Debug|ARM.ActiveCfg = Debug|ARM
+ {191B6F52-AD66-4172-BD20-733EEECEEF8C}.Debug|ARM.Build.0 = Debug|ARM
+ {191B6F52-AD66-4172-BD20-733EEECEEF8C}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {191B6F52-AD66-4172-BD20-733EEECEEF8C}.Debug|ARM64.Build.0 = Debug|ARM64
+ {191B6F52-AD66-4172-BD20-733EEECEEF8C}.Debug|x64.ActiveCfg = Debug|x64
+ {191B6F52-AD66-4172-BD20-733EEECEEF8C}.Debug|x64.Build.0 = Debug|x64
+ {191B6F52-AD66-4172-BD20-733EEECEEF8C}.Release|ARM.ActiveCfg = Release|ARM
+ {191B6F52-AD66-4172-BD20-733EEECEEF8C}.Release|ARM.Build.0 = Release|ARM
+ {191B6F52-AD66-4172-BD20-733EEECEEF8C}.Release|ARM64.ActiveCfg = Release|ARM64
+ {191B6F52-AD66-4172-BD20-733EEECEEF8C}.Release|ARM64.Build.0 = Release|ARM64
+ {191B6F52-AD66-4172-BD20-733EEECEEF8C}.Release|x64.ActiveCfg = Release|x64
+ {191B6F52-AD66-4172-BD20-733EEECEEF8C}.Release|x64.Build.0 = Release|x64
+ {191B6F52-AD66-4172-BD20-733EEECEEF8C}.UWP Gold|ARM.ActiveCfg = Release|ARM
+ {191B6F52-AD66-4172-BD20-733EEECEEF8C}.UWP Gold|ARM.Build.0 = Release|ARM
+ {191B6F52-AD66-4172-BD20-733EEECEEF8C}.UWP Gold|ARM64.ActiveCfg = Release|ARM64
+ {191B6F52-AD66-4172-BD20-733EEECEEF8C}.UWP Gold|ARM64.Build.0 = Release|ARM64
+ {191B6F52-AD66-4172-BD20-733EEECEEF8C}.UWP Gold|x64.ActiveCfg = Release|x64
+ {191B6F52-AD66-4172-BD20-733EEECEEF8C}.UWP Gold|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/UWP/libchdr_UWP/libchdr_UWP.vcxproj b/UWP/libchdr_UWP/libchdr_UWP.vcxproj
new file mode 100644
index 000000000000..afd6fb6a3194
--- /dev/null
+++ b/UWP/libchdr_UWP/libchdr_UWP.vcxproj
@@ -0,0 +1,104 @@
+
+
+
+
+ Debug
+ ARM
+
+
+ Debug
+ ARM64
+
+
+ Debug
+ x64
+
+
+ Release
+ ARM
+
+
+ Release
+ ARM64
+
+
+ Release
+ x64
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {191b6f52-ad66-4172-bd20-733eeeceef8c}
+ StaticLibrary
+ libchdr
+ en-US
+ 14.0
+ true
+ Windows Store
+ 10.0
+ 10.0.19041.0
+ 10.0
+ libchdr_UWP
+
+
+
+ StaticLibrary
+ true
+
+
+ StaticLibrary
+ false
+ false
+
+
+
+
+
+
+
+
+
+
+
+ false
+
+
+
+ false
+ false
+ ..\..\ext\zlib;..\..\ext\libchdr\include;..\..\ext\libchdr\deps\lzma-22.01\include;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories)
+ NotUsing
+ _7ZIP_ST;_CRT_SECURE_NO_WARNINGS;_UNICODE;UNICODE;%(PreprocessorDefinitions)
+
+
+ Console
+ false
+ false
+
+
+
+
+
+
\ No newline at end of file
diff --git a/UWP/libchdr_UWP/libchdr_UWP.vcxproj.filters b/UWP/libchdr_UWP/libchdr_UWP.vcxproj.filters
new file mode 100644
index 000000000000..7a49828f1d8b
--- /dev/null
+++ b/UWP/libchdr_UWP/libchdr_UWP.vcxproj.filters
@@ -0,0 +1,67 @@
+
+
+
+
+ {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
+ rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tga;tiff;tif;png;wav;mfcribbon-ms
+
+
+ {20de3681-6341-427f-a3a7-4ae259deb0b9}
+
+
+
+
+
+
+
+
+
+ lzma
+
+
+ lzma
+
+
+ lzma
+
+
+ lzma
+
+
+ lzma
+
+
+ lzma
+
+
+ lzma
+
+
+ lzma
+
+
+ lzma
+
+
+ lzma
+
+
+ lzma
+
+
+ lzma
+
+
+ lzma
+
+
+ lzma
+
+
+ lzma
+
+
+ lzma
+
+
+
\ No newline at end of file
diff --git a/Windows/PPSSPP.sln b/Windows/PPSSPP.sln
index de5d07692648..93a9d22c626a 100644
--- a/Windows/PPSSPP.sln
+++ b/Windows/PPSSPP.sln
@@ -93,6 +93,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cpu_features", "..\ext\cpu_
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "rcheevos", "..\ext\rcheevos-build\rcheevos.vcxproj", "{31694510-A8C0-40F6-B09B-E8DF825ADEFA}"
EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libchdr", "..\ext\libchdr.vcxproj", "{956F1F48-B612-46D8-89EE-96996DCD9383}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|ARM = Debug|ARM
@@ -395,6 +397,22 @@ Global
{31694510-A8C0-40F6-B09B-E8DF825ADEFA}.Release|Win32.Build.0 = Release|Win32
{31694510-A8C0-40F6-B09B-E8DF825ADEFA}.Release|x64.ActiveCfg = Release|x64
{31694510-A8C0-40F6-B09B-E8DF825ADEFA}.Release|x64.Build.0 = Release|x64
+ {956F1F48-B612-46D8-89EE-96996DCD9383}.Debug|ARM.ActiveCfg = Debug|ARM
+ {956F1F48-B612-46D8-89EE-96996DCD9383}.Debug|ARM.Build.0 = Debug|ARM
+ {956F1F48-B612-46D8-89EE-96996DCD9383}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {956F1F48-B612-46D8-89EE-96996DCD9383}.Debug|ARM64.Build.0 = Debug|ARM64
+ {956F1F48-B612-46D8-89EE-96996DCD9383}.Debug|Win32.ActiveCfg = Debug|Win32
+ {956F1F48-B612-46D8-89EE-96996DCD9383}.Debug|Win32.Build.0 = Debug|Win32
+ {956F1F48-B612-46D8-89EE-96996DCD9383}.Debug|x64.ActiveCfg = Debug|x64
+ {956F1F48-B612-46D8-89EE-96996DCD9383}.Debug|x64.Build.0 = Debug|x64
+ {956F1F48-B612-46D8-89EE-96996DCD9383}.Release|ARM.ActiveCfg = Release|ARM
+ {956F1F48-B612-46D8-89EE-96996DCD9383}.Release|ARM.Build.0 = Release|ARM
+ {956F1F48-B612-46D8-89EE-96996DCD9383}.Release|ARM64.ActiveCfg = Release|ARM64
+ {956F1F48-B612-46D8-89EE-96996DCD9383}.Release|ARM64.Build.0 = Release|ARM64
+ {956F1F48-B612-46D8-89EE-96996DCD9383}.Release|Win32.ActiveCfg = Release|Win32
+ {956F1F48-B612-46D8-89EE-96996DCD9383}.Release|Win32.Build.0 = Release|Win32
+ {956F1F48-B612-46D8-89EE-96996DCD9383}.Release|x64.ActiveCfg = Release|x64
+ {956F1F48-B612-46D8-89EE-96996DCD9383}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -412,6 +430,7 @@ Global
{8BFD8150-94D5-4BF9-8A50-7BD9929A0850} = {39FCACF8-10D9-4D8D-97AA-7507436AD932}
{C249F016-7F82-45CF-BB6E-0642A988C4D3} = {39FCACF8-10D9-4D8D-97AA-7507436AD932}
{31694510-A8C0-40F6-B09B-E8DF825ADEFA} = {39FCACF8-10D9-4D8D-97AA-7507436AD932}
+ {956F1F48-B612-46D8-89EE-96996DCD9383} = {39FCACF8-10D9-4D8D-97AA-7507436AD932}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {2FD47774-A031-48F4-B645-A49A3140A29B}
diff --git a/Windows/PPSSPP.vcxproj b/Windows/PPSSPP.vcxproj
index 881a31cab516..01128f75fbac 100644
--- a/Windows/PPSSPP.vcxproj
+++ b/Windows/PPSSPP.vcxproj
@@ -1721,6 +1721,9 @@
{edfa2e87-8ac1-4853-95d4-d7594ff81947}
+
+ {956f1f48-b612-46d8-89ee-96996dcd9383}
+
{3baae095-e0ab-4b0e-b5df-ce39c8ae31de}
diff --git a/Windows/main.cpp b/Windows/main.cpp
index 5149ebcc5370..04b89c7372c0 100644
--- a/Windows/main.cpp
+++ b/Windows/main.cpp
@@ -554,7 +554,7 @@ bool System_MakeRequest(SystemRequestType type, int requestId, const std::string
std::wstring filter;
switch (type) {
case BrowseFileType::BOOTABLE:
- filter = MakeFilter(L"All supported file types (*.iso *.cso *.pbp *.elf *.prx *.zip *.ppdmp)|*.pbp;*.elf;*.iso;*.cso;*.prx;*.zip;*.ppdmp|PSP ROMs (*.iso *.cso *.pbp *.elf *.prx)|*.pbp;*.elf;*.iso;*.cso;*.prx|Homebrew/Demos installers (*.zip)|*.zip|All files (*.*)|*.*||");
+ filter = MakeFilter(L"All supported file types (*.iso *.cso *.chd *.pbp *.elf *.prx *.zip *.ppdmp)|*.pbp;*.elf;*.iso;*.cso;*.chd;*.prx;*.zip;*.ppdmp|PSP ROMs (*.iso *.cso *.chd *.pbp *.elf *.prx)|*.pbp;*.elf;*.iso;*.cso;*.chd;*.prx|Homebrew/Demos installers (*.zip)|*.zip|All files (*.*)|*.*||");
break;
case BrowseFileType::INI:
filter = MakeFilter(L"Ini files (*.ini)|*.ini|All files (*.*)|*.*||");
diff --git a/android/ab.cmd b/android/ab.cmd
index f205269c8b95..412ba8263e09 100644
--- a/android/ab.cmd
+++ b/android/ab.cmd
@@ -11,5 +11,5 @@ copy ..\assets\*.meta assets\
copy ..\assets\*.wav assets\
SET NDK=C:\Android\sdk\ndk\21.3.6528147
REM SET NDK=C:\Android\ndk
-SET NDK_MODULE_PATH=..\ext;..\ext\native\ext
+SET NDK_MODULE_PATH=..\ext
%NDK%/ndk-build -j32 %*
diff --git a/android/jni/Android.mk b/android/jni/Android.mk
index 338d52baa0b2..c70bba4eb4ce 100644
--- a/android/jni/Android.mk
+++ b/android/jni/Android.mk
@@ -4,11 +4,45 @@ SRC := ../..
include $(CLEAR_VARS)
include $(LOCAL_PATH)/Locals.mk
+LOCAL_CFLAGS += -D_7ZIP_ST -D__SWITCH__
+
+LZMA_FILES := \
+ $(SRC)/ext/libchdr/deps/lzma-22.01/src/Alloc.c \
+ $(SRC)/ext/libchdr/deps/lzma-22.01/src/Bcj2.c \
+ $(SRC)/ext/libchdr/deps/lzma-22.01/src/Bcj2Enc.c \
+ $(SRC)/ext/libchdr/deps/lzma-22.01/src/Bra.c \
+ $(SRC)/ext/libchdr/deps/lzma-22.01/src/Bra86.c \
+ $(SRC)/ext/libchdr/deps/lzma-22.01/src/CpuArch.c \
+ $(SRC)/ext/libchdr/deps/lzma-22.01/src/Delta.c \
+ $(SRC)/ext/libchdr/deps/lzma-22.01/src/LzFind.c \
+ $(SRC)/ext/libchdr/deps/lzma-22.01/src/LzFindOpt.c \
+ $(SRC)/ext/libchdr/deps/lzma-22.01/src/LzmaDec.c \
+ $(SRC)/ext/libchdr/deps/lzma-22.01/src/LzmaEnc.c \
+ $(SRC)/ext/libchdr/deps/lzma-22.01/src/Lzma86Dec.c \
+ $(SRC)/ext/libchdr/deps/lzma-22.01/src/Lzma86Enc.c \
+ $(SRC)/ext/libchdr/deps/lzma-22.01/src/LzmaLib.c \
+ $(SRC)/ext/libchdr/deps/lzma-22.01/src/Sort.c
+
+CHDR_FILES := \
+ ${LZMA_FILES} \
+ $(SRC)/ext/libchdr/src/libchdr_bitstream.c \
+ $(SRC)/ext/libchdr/src/libchdr_cdrom.c \
+ $(SRC)/ext/libchdr/src/libchdr_chd.c \
+ $(SRC)/ext/libchdr/src/libchdr_flac.c \
+ $(SRC)/ext/libchdr/src/libchdr_huffman.c
+
+LOCAL_MODULE := libchdr
+LOCAL_SRC_FILES := $(CHDR_FILES)
+include $(BUILD_STATIC_LIBRARY)
+
+include $(CLEAR_VARS)
+include $(LOCAL_PATH)/Locals.mk
+
LOCAL_C_INCLUDES += \
$(LOCAL_PATH)/../../ext/cpu_features/include \
$(LOCAL_PATH)/../../ext/rcheevos/include
-LOCAL_CFLAGS += -DSTACK_LINE_READER_BUFFER_SIZE=1024 -DHAVE_DLFCN_H -DRC_DISABLE_LUA
+LOCAL_CFLAGS += -DSTACK_LINE_READER_BUFFER_SIZE=1024 -DHAVE_DLFCN_H -DRC_DISABLE_LUA -D_7ZIP_ST
# http://software.intel.com/en-us/articles/getting-started-on-optimizing-ndk-project-for-multiple-cpu-architectures
@@ -288,7 +322,7 @@ include $(BUILD_STATIC_LIBRARY)
# Next up, Core, GPU, and other core parts shared by headless.
include $(CLEAR_VARS)
include $(LOCAL_PATH)/Locals.mk
-LOCAL_WHOLE_STATIC_LIBRARIES += ppsspp_common
+LOCAL_WHOLE_STATIC_LIBRARIES += ppsspp_common libchdr
ifeq ($(TARGET_ARCH_ABI),x86_64)
ARCH_FILES := \
@@ -357,7 +391,7 @@ ARCH_FILES := \
Arm64EmitterTest.cpp
endif
-VULKAN_FILES := \
+GPU_VULKAN_FILES := \
$(SRC)/GPU/Vulkan/DrawEngineVulkan.cpp \
$(SRC)/GPU/Vulkan/FramebufferManagerVulkan.cpp \
$(SRC)/GPU/Vulkan/GPU_Vulkan.cpp \
@@ -370,7 +404,7 @@ VULKAN_FILES := \
EXEC_AND_LIB_FILES := \
$(ARCH_FILES) \
- $(VULKAN_FILES) \
+ $(GPU_VULKAN_FILES) \
$(SRC)/ext/xxhash.c \
TestRunner.cpp \
$(SRC)/Core/MIPS/MIPS.cpp.arm \
diff --git a/android/jni/Locals.mk b/android/jni/Locals.mk
index aa71119f3b71..e176a2bdc747 100644
--- a/android/jni/Locals.mk
+++ b/android/jni/Locals.mk
@@ -20,6 +20,8 @@ LOCAL_C_INCLUDES := \
$(LOCAL_PATH)/../../ext/armips \
$(LOCAL_PATH)/../../ext/armips/ext/filesystem/include \
$(LOCAL_PATH)/../../ext/armips/ext/tinyformat \
+ $(LOCAL_PATH)/../../ext/libchdr/deps/lzma-22.01/include \
+ $(LOCAL_PATH)/../../ext/libchdr/include \
$(LOCAL_PATH)
LOCAL_STATIC_LIBRARIES := libzip glslang-build miniupnp-build
diff --git a/ext/CMakeLists.txt b/ext/CMakeLists.txt
index 9bbb9b7a7452..1031f6edf91c 100644
--- a/ext/CMakeLists.txt
+++ b/ext/CMakeLists.txt
@@ -37,3 +37,5 @@ endif()
if(USE_DISCORD AND NOT IOS AND NOT LIBRETRO)
add_subdirectory(discord-rpc-build)
endif()
+
+add_subdirectory(libchdr-build)
diff --git a/ext/libchdr b/ext/libchdr
new file mode 160000
index 000000000000..9108f34a8922
--- /dev/null
+++ b/ext/libchdr
@@ -0,0 +1 @@
+Subproject commit 9108f34a892272f61c3ed3bff4bee728d4c1dd57
diff --git a/ext/libchdr-build/CMakeLists.txt b/ext/libchdr-build/CMakeLists.txt
new file mode 100644
index 000000000000..8b93aa42fe4d
--- /dev/null
+++ b/ext/libchdr-build/CMakeLists.txt
@@ -0,0 +1,38 @@
+cmake_minimum_required (VERSION 3.2.0)
+project (chdr)
+
+set(LZMA_DIR ../libchdr/deps/lzma-22.01/src)
+set(SRC_DIR ../libchdr/src)
+
+include_directories(../libchdr/deps/lzma-22.01/include)
+include_directories(../libchdr/include)
+
+add_definitions(-D_7ZIP_ST)
+
+# Hack - CpuArch.c has a workaround that we reuse.
+add_definitions(-D__SWITCH__)
+
+set(ALL_SOURCE_FILES
+ ${LZMA_DIR}/Alloc.c
+ ${LZMA_DIR}/Bcj2.c
+ ${LZMA_DIR}/Bcj2Enc.c
+ ${LZMA_DIR}/Bra.c
+ ${LZMA_DIR}/Bra86.c
+ ${LZMA_DIR}/CpuArch.c
+ ${LZMA_DIR}/Delta.c
+ ${LZMA_DIR}/LzFind.c
+ ${LZMA_DIR}/LzFindOpt.c
+ ${LZMA_DIR}/LzmaDec.c
+ ${LZMA_DIR}/LzmaEnc.c
+ ${LZMA_DIR}/Lzma86Dec.c
+ ${LZMA_DIR}/Lzma86Enc.c
+ ${LZMA_DIR}/LzmaLib.c
+ ${LZMA_DIR}/Sort.c
+ ${SRC_DIR}/libchdr_bitstream.c
+ ${SRC_DIR}/libchdr_cdrom.c
+ ${SRC_DIR}/libchdr_chd.c
+ ${SRC_DIR}/libchdr_flac.c
+ ${SRC_DIR}/libchdr_huffman.c
+ )
+
+add_library(chdr STATIC ${ALL_SOURCE_FILES})
diff --git a/ext/libchdr.vcxproj b/ext/libchdr.vcxproj
new file mode 100644
index 000000000000..89d56f3fbe2c
--- /dev/null
+++ b/ext/libchdr.vcxproj
@@ -0,0 +1,374 @@
+
+
+
+
+ Debug
+ ARM
+
+
+ Debug
+ ARM64
+
+
+ Debug
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ ARM
+
+
+ Release
+ ARM64
+
+
+ Release
+ Win32
+
+
+ Release
+ x64
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {956F1F48-B612-46D8-89EE-96996DCD9383}
+ Win32Proj
+ libchdr
+ libchdr_static
+ Unicode
+ StaticLibrary
+ $(SolutionDir)..\ext\libchdr\bin\$(Platform)_$(Configuration)\
+ $(SolutionDir)..\ext\libchdr\bin\obj\$(RootNamespace)_$(Platform)_$(Configuration)\
+ 10.0
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+ $(DefaultPlatformToolset)
+
+
+ true
+ $(DefaultPlatformToolset)
+
+
+ true
+ $(DefaultPlatformToolset)
+
+
+ true
+ $(DefaultPlatformToolset)
+
+
+ false
+ true
+ $(DefaultPlatformToolset)
+
+
+ false
+ true
+ $(DefaultPlatformToolset)
+
+
+ false
+ true
+ $(DefaultPlatformToolset)
+
+
+ false
+ true
+ $(DefaultPlatformToolset)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+ $(IncludePath);$(SolutionDir)..\ext\libchdr\include;$(UniversalCRT_IncludePath);
+ false
+
+
+ true
+ $(IncludePath);$(SolutionDir)..\ext\libchdr\include;$(UniversalCRT_IncludePath);
+ false
+
+
+ false
+ $(IncludePath);$(SolutionDir)..\ext\libchdr\include;$(UniversalCRT_IncludePath);
+ false
+
+
+ false
+ $(IncludePath);$(SolutionDir)..\ext\libchdr\include;$(UniversalCRT_IncludePath);
+ false
+
+
+
+ $(OutDir)$(TargetName).pdb
+
+
+
+
+
+
+ Level4
+ _7ZIP_ST;WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)
+ true
+ EnableFastChecks
+ MultiThreadedDebug
+ true
+ ProgramDatabase
+ false
+ libchdr\include;libchdr\deps\lzma-22.01\include;zlib;
+
+
+ Windows
+ true
+ MachineX86
+
+
+
+
+
+
+ Level4
+ _7ZIP_ST;WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)
+ EnableFastChecks
+ MultiThreadedDebug
+ true
+ ProgramDatabase
+ false
+ libchdr\include;libchdr\deps\lzma-22.01\include;zlib;
+
+
+ Windows
+ true
+
+
+
+
+
+
+ Level4
+ _7ZIP_ST;WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)
+ EnableFastChecks
+ MultiThreadedDebug
+ true
+ ProgramDatabase
+ false
+ libchdr\include;libchdr\deps\lzma-22.01\include;zlib;
+
+
+ Windows
+ true
+
+
+
+
+
+
+ Level4
+ _7ZIP_ST;WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)
+ EnableFastChecks
+ MultiThreadedDebug
+ true
+ ProgramDatabase
+ false
+ libchdr\include;libchdr\deps\lzma-22.01\include;zlib;
+
+
+ Windows
+ true
+
+
+
+
+ Level4
+
+
+ MaxSpeed
+ true
+ true
+ _7ZIP_ST;WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)
+ false
+ MultiThreaded
+ true
+ ProgramDatabase
+ AnySuitable
+ Speed
+ true
+ false
+ StreamingSIMDExtensions2
+ libchdr\include;libchdr\deps\lzma-22.01\include;zlib;
+
+
+ Windows
+ true
+ true
+ true
+ MachineX86
+
+
+
+
+ Level4
+
+
+ MaxSpeed
+ true
+ true
+ _7ZIP_ST;WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)
+ false
+ false
+ MultiThreaded
+ true
+ ProgramDatabase
+ false
+ true
+ AnySuitable
+ Speed
+ libchdr\include;libchdr\deps\lzma-22.01\include;zlib;
+
+
+ Windows
+ true
+ true
+ true
+
+
+
+
+ Level4
+
+
+ MaxSpeed
+ true
+ true
+ _7ZIP_ST;WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)
+ false
+ false
+ MultiThreaded
+ true
+ ProgramDatabase
+ false
+ true
+ AnySuitable
+ Speed
+ libchdr\include;libchdr\deps\lzma-22.01\include;zlib;
+
+
+ Windows
+ true
+ true
+ true
+
+
+
+
+ Level4
+
+
+ MaxSpeed
+ true
+ true
+ _7ZIP_ST;WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)
+ false
+ false
+ MultiThreaded
+ true
+ ProgramDatabase
+ false
+ true
+ AnySuitable
+ Speed
+ libchdr\include;libchdr\deps\lzma-22.01\include;zlib;
+
+
+ Windows
+ true
+ true
+ true
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ext/libchdr.vcxproj.filters b/ext/libchdr.vcxproj.filters
new file mode 100644
index 000000000000..d35dd7e48fb3
--- /dev/null
+++ b/ext/libchdr.vcxproj.filters
@@ -0,0 +1,72 @@
+
+
+
+
+
+
+
+
+
+ LZMA
+
+
+ LZMA
+
+
+ LZMA
+
+
+ LZMA
+
+
+ LZMA
+
+
+ LZMA
+
+
+ LZMA
+
+
+ LZMA
+
+
+ LZMA
+
+
+ LZMA
+
+
+ LZMA
+
+
+ LZMA
+
+
+ LZMA
+
+
+ LZMA
+
+
+ LZMA
+
+
+ LZMA
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {ff31581b-3ff9-4e39-bb96-2f662896cf70}
+
+
+
\ No newline at end of file
diff --git a/headless/Headless.vcxproj b/headless/Headless.vcxproj
index 65cc85d5b46c..b500d26de4eb 100644
--- a/headless/Headless.vcxproj
+++ b/headless/Headless.vcxproj
@@ -502,6 +502,9 @@
{edfa2e87-8ac1-4853-95d4-d7594ff81947}
+
+ {956f1f48-b612-46d8-89ee-96996dcd9383}
+
{3baae095-e0ab-4b0e-b5df-ce39c8ae31de}
diff --git a/libretro/Makefile.common b/libretro/Makefile.common
index 0168cd21e510..e8c6ed2d4113 100644
--- a/libretro/Makefile.common
+++ b/libretro/Makefile.common
@@ -226,6 +226,35 @@ SOURCES_C += \
COREFLAGS += -DSTACK_LINE_READER_BUFFER_SIZE=1024
COREFLAGS += -DHTTPS_NOT_AVAILABLE
+COREFLAGS += -D_7ZIP_ST
+INCFLAGS += -I$(EXTDIR)/libchdr/deps/lzma-22.01/include
+
+SOURCES_C += \
+ $(EXTDIR)/libchdr/deps/lzma-22.01/src/Alloc.c \
+ $(EXTDIR)/libchdr/deps/lzma-22.01/src/Bcj2.c \
+ $(EXTDIR)/libchdr/deps/lzma-22.01/src/Bcj2Enc.c \
+ $(EXTDIR)/libchdr/deps/lzma-22.01/src/Bra.c \
+ $(EXTDIR)/libchdr/deps/lzma-22.01/src/Bra86.c \
+ $(EXTDIR)/libchdr/deps/lzma-22.01/src/CpuArch.c \
+ $(EXTDIR)/libchdr/deps/lzma-22.01/src/Delta.c \
+ $(EXTDIR)/libchdr/deps/lzma-22.01/src/LzFind.c \
+ $(EXTDIR)/libchdr/deps/lzma-22.01/src/LzFindOpt.c \
+ $(EXTDIR)/libchdr/deps/lzma-22.01/src/LzmaDec.c \
+ $(EXTDIR)/libchdr/deps/lzma-22.01/src/LzmaEnc.c \
+ $(EXTDIR)/libchdr/deps/lzma-22.01/src/Lzma86Dec.c \
+ $(EXTDIR)/libchdr/deps/lzma-22.01/src/Lzma86Enc.c \
+ $(EXTDIR)/libchdr/deps/lzma-22.01/src/LzmaLib.c \
+ $(EXTDIR)/libchdr/deps/lzma-22.01/src/Sort.c
+
+INCFLAGS += -I$(EXTDIR)/libchdr/include
+
+SOURCES_C += \
+ $(EXTDIR)/libchdr/src/libchdr_bitstream.c \
+ $(EXTDIR)/libchdr/src/libchdr_cdrom.c \
+ $(EXTDIR)/libchdr/src/libchdr_chd.c \
+ $(EXTDIR)/libchdr/src/libchdr_flac.c \
+ $(EXTDIR)/libchdr/src/libchdr_huffman.c
+
ifeq ($(PLATFORM_EXT), android)
COREFLAGS += -DHAVE_DLFCN_H
else ifneq ($(PLATFORM_EXT), win32)
diff --git a/unittest/UnitTests.vcxproj b/unittest/UnitTests.vcxproj
index 7417f4f38b63..76ce39678097 100644
--- a/unittest/UnitTests.vcxproj
+++ b/unittest/UnitTests.vcxproj
@@ -420,6 +420,9 @@
{edfa2e87-8ac1-4853-95d4-d7594ff81947}
+
+ {956f1f48-b612-46d8-89ee-96996dcd9383}
+
{3baae095-e0ab-4b0e-b5df-ce39c8ae31de}