mirror of
https://github.com/PCSX2/pcsx2.git
synced 2026-07-31 19:28:40 +02:00
Compare commits
@@ -118,7 +118,7 @@ jobs:
|
||||
message("::set-output name=timestamp::${current_date}")
|
||||
|
||||
- name: ccache cache files
|
||||
uses: actions/cache@v2.1.6
|
||||
uses: actions/cache@v2.1.7
|
||||
with:
|
||||
path: .ccache
|
||||
key: ${{ matrix.os }} ${{ matrix.platform }} ${{ matrix.compiler }}${{ matrix.detail }} ccache ${{ steps.ccache_cache_timestamp.outputs.timestamp }}
|
||||
|
||||
@@ -99,7 +99,7 @@ jobs:
|
||||
run: |
|
||||
# To save time, only brew update if running the install without it fails
|
||||
function do-install() {
|
||||
brew install sound-touch portaudio wxmac gtk+3 sdl2 libsamplerate
|
||||
brew install sound-touch portaudio wxwidgets sdl2 libsamplerate glib
|
||||
}
|
||||
if ! do-install; then
|
||||
brew update
|
||||
|
||||
@@ -33,7 +33,7 @@ jobs:
|
||||
# - https://github.community/t/github-actions-workflow-not-triggering-with-tag-push/17053/7
|
||||
- name: Bump Version and Push Tag
|
||||
id: tag_version
|
||||
uses: mathieudutour/github-tag-action@v5.6
|
||||
uses: mathieudutour/github-tag-action@v6.0
|
||||
with:
|
||||
github_token: ${{ secrets.BOT_PAT }}
|
||||
tag_prefix: v
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
*.txt
|
||||
@@ -0,0 +1,38 @@
|
||||
import os
|
||||
|
||||
relevant_categories = [
|
||||
"# Mac OS X",
|
||||
"# Linux"
|
||||
]
|
||||
|
||||
header_lines = []
|
||||
new_db_contents = []
|
||||
|
||||
def is_relevant_category(line):
|
||||
for category in relevant_categories:
|
||||
if category in line:
|
||||
return True
|
||||
return False
|
||||
|
||||
with open("./game_controller_db.txt") as file:
|
||||
lines = file.readlines()
|
||||
finished_header = False
|
||||
processing_section = False
|
||||
for line in lines:
|
||||
if finished_header is False:
|
||||
header_lines.append(line)
|
||||
if line == "\n":
|
||||
finished_header = True
|
||||
if processing_section and line == "\n":
|
||||
processing_section = False
|
||||
new_db_contents.append("\n")
|
||||
if is_relevant_category(line) and processing_section is False:
|
||||
processing_section = True
|
||||
new_db_contents.append(line)
|
||||
elif processing_section:
|
||||
new_db_contents.append(line)
|
||||
|
||||
os.remove("./game_controller_db.txt")
|
||||
with open("./game_controller_db.txt", "w") as f:
|
||||
f.writelines(header_lines)
|
||||
f.writelines(new_db_contents)
|
||||
@@ -37,11 +37,15 @@ mkdir -p squashfs-root/usr/share/icons && cp ./squashfs-root/PCSX2.png ./squashf
|
||||
mkdir -p squashfs-root/usr/share/icons/hicolor/scalable/apps && cp ./squashfs-root/PCSX2.png ./squashfs-root/usr/share/icons/hicolor/scalable/apps
|
||||
mkdir -p squashfs-root/usr/share/pixmaps && cp ./squashfs-root/PCSX2.png ./squashfs-root/usr/share/pixmaps
|
||||
mkdir -p squashfs-root/usr/lib/
|
||||
mkdir -p squashfs-root/usr/optional/libstdc++
|
||||
mkdir -p squashfs-root/usr/optional/libgcc_s
|
||||
cp ./.github/workflows/scripts/linux/AppRun "$GITHUB_WORKSPACE"/squashfs-root/AppRun
|
||||
curl -sSfL "https://github.com/AppImage/AppImageKit/releases/download/continuous/AppRun-$APPARCH" -o "$GITHUB_WORKSPACE"/squashfs-root/AppRun-patched
|
||||
curl -sSfL "https://github.com/darealshinji/AppImageKit-checkrt/releases/download/continuous/AppRun-patched-$APPARCH" -o "$GITHUB_WORKSPACE"/squashfs-root/AppRun-patched
|
||||
curl -sSfL "https://github.com/darealshinji/AppImageKit-checkrt/releases/download/continuous/exec-$APPARCH.so" -o "$GITHUB_WORKSPACE"/squashfs-root/usr/optional/exec.so
|
||||
chmod a+x ./squashfs-root/AppRun
|
||||
chmod a+x ./squashfs-root/runtime
|
||||
chmod a+x ./squashfs-root/AppRun-patched
|
||||
chmod a+x ./squashfs-root/usr/optional/exec.so
|
||||
echo "$name" > "$GITHUB_WORKSPACE"/squashfs-root/version.txt
|
||||
mkdir -p "$GITHUB_WORKSPACE"/squashfs-root/usr/bin/app
|
||||
cp -r "$GITHUB_WORKSPACE"/bin/Langs "$GITHUB_WORKSPACE"/squashfs-root/usr/bin/
|
||||
@@ -49,6 +53,8 @@ cp "$GITHUB_WORKSPACE"/bin/docs/{Configuration_Guide.pdf,PCSX2_FAQ.pdf} "$GITHUB
|
||||
cp "$GITHUB_WORKSPACE"/bin/cheats_ws.zip "$GITHUB_WORKSPACE"/squashfs-root/usr/bin/app
|
||||
cp ./bin/GameIndex.yaml "$GITHUB_WORKSPACE"/squashfs-root/usr/bin/app/GameIndex.yaml
|
||||
cp /usr/lib/$LIBARCH/libthai.so.0 "$GITHUB_WORKSPACE"/squashfs-root/usr/lib/
|
||||
cp --dereference /usr/lib/"$LIBARCH"/libstdc++.so.6 "$GITHUB_WORKSPACE"/squashfs-root/usr/optional/libstdc++/libstdc++.so.6
|
||||
cp --dereference /lib/"$LIBARCH"/libgcc_s.so.1 "$GITHUB_WORKSPACE"/squashfs-root/usr/optional/libgcc_s/libgcc_s.so.1
|
||||
export UPD_INFO="gh-releases-zsync|PCSX2|pcsx2|latest|$name.AppImage.zsync"
|
||||
export OUTPUT="$name.AppImage"
|
||||
/tmp/squashfs-root/AppRun --appdir="$GITHUB_WORKSPACE"/squashfs-root/ --plugin gtk -d "$GITHUB_WORKSPACE"/squashfs-root/PCSX2.desktop -i "$GITHUB_WORKSPACE"/squashfs-root/PCSX2.png --output appimage
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
set -e
|
||||
|
||||
if [ "${COMPILER}" = "gcc" ]; then
|
||||
export CC=gcc
|
||||
export CXX=g++
|
||||
export CC=gcc-10
|
||||
export CXX=g++-10
|
||||
else
|
||||
export CC=clang
|
||||
export CXX=clang++
|
||||
|
||||
@@ -6,100 +6,42 @@ set -e
|
||||
declare -a BUILD_PACKAGES=(
|
||||
"ccache"
|
||||
"cmake"
|
||||
"g++-8-multilib"
|
||||
"ninja-build"
|
||||
)
|
||||
|
||||
declare -a GCC_PACKAGES=(
|
||||
# Nothing Unique Needed
|
||||
)
|
||||
|
||||
declare -a CLANG_PACKAGES=(
|
||||
"clang-format"
|
||||
"clang-tidy"
|
||||
"clang-tools"
|
||||
"clang"
|
||||
"clangd-10"
|
||||
"libc++-dev"
|
||||
"libc++1"
|
||||
"libc++abi-dev"
|
||||
"libc++abi1"
|
||||
"libclang-dev"
|
||||
"libclang1"
|
||||
"liblldb-10-dev"
|
||||
"libllvm-10-ocaml-dev"
|
||||
"libomp-dev"
|
||||
"libomp5"
|
||||
"lld"
|
||||
"lldb"
|
||||
"llvm-dev"
|
||||
"llvm-runtime"
|
||||
"llvm"
|
||||
"python3-clang-10"
|
||||
)
|
||||
|
||||
# Packages - PCSX2
|
||||
declare -a PCSX2_PACKAGES=(
|
||||
"curl"
|
||||
"fuse"
|
||||
"gettext"
|
||||
"libaio-dev"
|
||||
"libasound2-dev"
|
||||
"libatk1.0-dev"
|
||||
"libatk-bridge2.0-dev"
|
||||
"libbz2-dev"
|
||||
"libcairo2-dev"
|
||||
"libcggl"
|
||||
"libdbus-1-dev"
|
||||
"libegl1-mesa-dev"
|
||||
"libfontconfig1-dev"
|
||||
"libgdk-pixbuf2.0-dev"
|
||||
"libgirepository-1.0-1"
|
||||
"libgl-dev"
|
||||
"libgl1-mesa-dev"
|
||||
"libgl1-mesa-dri"
|
||||
"libgl1"
|
||||
"libgles2-mesa-dev"
|
||||
"libglew-dev"
|
||||
"libglib2.0-dev"
|
||||
"libglu1-mesa-dev"
|
||||
"libglu1-mesa"
|
||||
"libglvnd-dev"
|
||||
"libglx-mesa0"
|
||||
"libglx0"
|
||||
"libgtk-3-dev"
|
||||
"libgtk2.0-dev"
|
||||
"libharfbuzz-dev"
|
||||
"libibus-1.0-dev"
|
||||
"libjack-jackd2-dev"
|
||||
"libjpeg-dev"
|
||||
"libllvm10"
|
||||
"liblzma-dev"
|
||||
"liblzma5"
|
||||
"libpango1.0-dev"
|
||||
"libpcap0.8-dev"
|
||||
"libpng-dev"
|
||||
"libportaudiocpp0"
|
||||
"libpulse-dev"
|
||||
"librsvg2-dev"
|
||||
"libsdl1.2-dev"
|
||||
"libsdl2-dev"
|
||||
"libsamplerate0-dev"
|
||||
"libsoundtouch-dev"
|
||||
"libwxgtk3.0-dev"
|
||||
"libwxgtk3.0-gtk3-0v5"
|
||||
"libwxgtk3.0-gtk3-dev"
|
||||
"libx11-xcb-dev"
|
||||
"libxext-dev"
|
||||
"libxft-dev"
|
||||
"libxml2-dev"
|
||||
"nvidia-cg-toolkit"
|
||||
"pkg-config"
|
||||
"portaudio19-dev"
|
||||
"python"
|
||||
"zlib1g-dev"
|
||||
)
|
||||
|
||||
if [ "${COMPILER}" = "gcc" ]; then
|
||||
BUILD_PACKAGES+=("g++-10-multilib")
|
||||
else
|
||||
BUILD_PACKAGES+=("clang-9")
|
||||
PCSX2_PACKAGES+=("libstdc++-10-dev")
|
||||
fi
|
||||
|
||||
# - https://github.com/actions/virtual-environments/blob/main/images/linux/Ubuntu2004-README.md
|
||||
ARCH=""
|
||||
echo "${PLATFORM}"
|
||||
@@ -111,41 +53,14 @@ fi
|
||||
sudo apt-get -qq update
|
||||
|
||||
# Install packages needed for building
|
||||
BUILD_PACKAGE_STR=""
|
||||
for i in "${BUILD_PACKAGES[@]}"; do
|
||||
BUILD_PACKAGE_STR="${BUILD_PACKAGE_STR} ${i}"
|
||||
done
|
||||
|
||||
if [ "${COMPILER}" = "gcc" ]; then
|
||||
for i in "${GCC_PACKAGES[@]}"; do
|
||||
BUILD_PACKAGE_STR="${BUILD_PACKAGE_STR} ${i}"
|
||||
done
|
||||
else
|
||||
for i in "${CLANG_PACKAGES[@]}"; do
|
||||
BUILD_PACKAGE_STR="${BUILD_PACKAGE_STR} ${i}"
|
||||
done
|
||||
fi
|
||||
|
||||
echo "Will install the following packages for building - ${BUILD_PACKAGE_STR}"
|
||||
echo "Will install the following packages for building - ${BUILD_PACKAGES[*]}"
|
||||
#sudo apt remove gcc-9 g++-9
|
||||
sudo apt-get -y install ${BUILD_PACKAGE_STR}
|
||||
|
||||
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-8 10
|
||||
sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-8 10
|
||||
sudo update-alternatives --install /usr/bin/cc cc /usr/bin/gcc 30
|
||||
sudo update-alternatives --install /usr/bin/c++ c++ /usr/bin/g++ 30
|
||||
sudo apt-get -y install "${BUILD_PACKAGES[@]}"
|
||||
|
||||
# Install packages needed by pcsx2
|
||||
PCSX2_PACKAGES_STR=""
|
||||
for i in "${PCSX2_PACKAGES[@]}"; do
|
||||
PCSX2_PACKAGES_STR="${PCSX2_PACKAGES_STR} ${i}${ARCH}"
|
||||
done
|
||||
if [ "${PLATFORM}" == "x86" ]; then
|
||||
echo "Installing workaround attempt"
|
||||
sudo apt-get -y install libgcc-s1:i386
|
||||
fi
|
||||
echo "Will install the following packages for pcsx2 - ${PCSX2_PACKAGES_STR}"
|
||||
sudo apt-get -y install ${PCSX2_PACKAGES_STR}
|
||||
PCSX2_PACKAGES=("${PCSX2_PACKAGES[@]/%/"${ARCH}"}")
|
||||
echo "Will install the following packages for pcsx2 - ${PCSX2_PACKAGES[*]}"
|
||||
sudo apt-get -y install "${PCSX2_PACKAGES[@]}"
|
||||
|
||||
cd /tmp
|
||||
curl -sSfLO https://github.com/NixOS/patchelf/releases/download/0.12/patchelf-0.12.tar.bz2
|
||||
|
||||
@@ -11,9 +11,21 @@ for (var i = 0; i < assets.length; i++) {
|
||||
continue;
|
||||
}
|
||||
if (asset.name.includes("windows")) {
|
||||
windowsAssetLinks += `- [${asset.name}](${asset.browser_download_url})\n`
|
||||
let friendlyName = asset.name;
|
||||
try {
|
||||
friendlyName = asset.name.split("windows-")[1].split(".7z")[0].replace("-", " ");
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
windowsAssetLinks += `- [${friendlyName}](${asset.browser_download_url})\n`
|
||||
} else if (asset.name.includes("linux")) {
|
||||
linuxAssetLinks += `- [${asset.name}](${asset.browser_download_url})\n`
|
||||
let friendlyName = asset.name;
|
||||
try {
|
||||
friendlyName = asset.name.split("linux-")[1].split(".AppImage")[0].replace("-", " ");
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
linuxAssetLinks += `- [${friendlyName}](${asset.browser_download_url})\n`
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +36,8 @@ const embed = new MessageEmbed()
|
||||
.addFields(
|
||||
{ name: 'Version', value: github.context.payload.release.tag_name, inline: true },
|
||||
{ name: 'Release Link', value: `[Github Release](${github.context.payload.release.html_url})`, inline: true },
|
||||
{ name: 'Installation Steps', value: '[See Here](https://github.com/PCSX2/pcsx2/wiki/Nightly-Build-Usage-Guide)', inline: true }
|
||||
{ name: 'Installation Steps', value: '[See Here](https://github.com/PCSX2/pcsx2/wiki/Nightly-Build-Usage-Guide)', inline: true },
|
||||
{ name: 'Included Changes', value: github.context.payload.release.body, inline: false }
|
||||
);
|
||||
|
||||
if (windowsAssetLinks != "") {
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
name: 🏭 Update Controller Database
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: "0 16 * * 1" # every monday @ 12pm EST - https://crontab.guru/#0_16_*_*_1
|
||||
|
||||
jobs:
|
||||
update-controller-db:
|
||||
if: github.repository == 'PCSX2/pcsx2'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Get Latest DB and Prepare DB File
|
||||
run: |
|
||||
cd .github/workflows/scripts/controller-db/
|
||||
wget -O game_controller_db.txt https://raw.githubusercontent.com/gabomdq/SDL_GameControllerDB/master/gamecontrollerdb.txt
|
||||
python ./update-db.py
|
||||
mv ./game_controller_db.txt ${{github.workspace}}/pcsx2/PAD/Linux/res/game_controller_db.txt
|
||||
|
||||
- name: Create Pull Request
|
||||
uses: peter-evans/create-pull-request@v3
|
||||
with:
|
||||
title: "pad-linux: Update to latest controller database"
|
||||
commit-message: "pad-linux: Update to latest controller database."
|
||||
committer: "PCSX2 Bot <PCSX2Bot@users.noreply.github.com>"
|
||||
author: "PCSX2 Bot <PCSX2Bot@users.noreply.github.com>"
|
||||
body: "Weekly automatic update of SDL Controller DB for Linux / Mac OS"
|
||||
reviewers: lightningterror
|
||||
@@ -1,23 +1,18 @@
|
||||
[submodule "3rdparty/xz/xz"]
|
||||
path = 3rdparty/xz/xz
|
||||
url = https://github.com/PCSX2/xz.git
|
||||
shallow = true
|
||||
[submodule "3rdparty/gtest"]
|
||||
path = 3rdparty/gtest
|
||||
url = https://github.com/google/googletest.git
|
||||
shallow = true
|
||||
[submodule "3rdparty/fmt/fmt"]
|
||||
path = 3rdparty/fmt/fmt
|
||||
url = https://github.com/fmtlib/fmt.git
|
||||
shallow = true
|
||||
[submodule "3rdparty/yaml-cpp/yaml-cpp"]
|
||||
path = 3rdparty/yaml-cpp/yaml-cpp
|
||||
url = https://github.com/jbeder/yaml-cpp.git
|
||||
shallow = true
|
||||
[submodule "3rdparty/libchdr/libchdr"]
|
||||
path = 3rdparty/libchdr/libchdr
|
||||
url = https://github.com/rtissera/libchdr.git
|
||||
shallow = true
|
||||
[submodule "3rdparty/wil"]
|
||||
path = 3rdparty/wil
|
||||
url = https://github.com/microsoft/wil.git
|
||||
|
||||
Vendored
+1
-1
Submodule 3rdparty/libchdr/libchdr updated: a17c0da7e9...5de1a59019
Vendored
+5
-14
@@ -1,19 +1,9 @@
|
||||
/*
|
||||
** Copyright (C) 2002-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
** Copyright (c) 2002-2016, Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
** All rights reserved.
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation; either version 2 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program; if not, write to the Free Software
|
||||
** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
|
||||
** This code is released under 2-clause BSD license. Please see the
|
||||
** file at : https://github.com/erikd/libsamplerate/blob/master/COPYING
|
||||
*/
|
||||
|
||||
/*
|
||||
@@ -38,6 +28,7 @@
|
||||
** following #pragma disables the warning.
|
||||
*/
|
||||
|
||||
|
||||
#pragma warning(disable: 4305)
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
|
||||
Vendored
+2
-2
@@ -2,7 +2,7 @@
|
||||
Version 2.1, February 1999
|
||||
|
||||
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
|
||||
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
@@ -117,7 +117,7 @@ be combined with the library in order to run.
|
||||
|
||||
0. This License Agreement applies to any software library or other
|
||||
program which contains a notice placed by the copyright holder or
|
||||
other authoried party saying it may be distributed under the terms of
|
||||
other authorized party saying it may be distributed under the terms of
|
||||
this Lesser General Public License (also called "this License").
|
||||
Each licensee is addressed as "you".
|
||||
|
||||
|
||||
Vendored
+949
-877
File diff suppressed because it is too large
Load Diff
@@ -170,6 +170,9 @@ public:
|
||||
/// allow trimming (downwards) amount of samples in pipeline.
|
||||
/// Returns adjusted amount of samples
|
||||
uint adjustAmountOfSamples(uint numSamples);
|
||||
|
||||
/// Add silence to end of buffer
|
||||
void addSilent(uint nSamples);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
+14
-7
@@ -121,10 +121,10 @@ namespace soundtouch
|
||||
|
||||
#endif
|
||||
|
||||
// If defined, allows the SIMD-optimized routines to take minor shortcuts
|
||||
// for improved performance. Undefine to require faithfully similar SIMD
|
||||
// calculations as in normal C implementation.
|
||||
#define SOUNDTOUCH_ALLOW_NONEXACT_SIMD_OPTIMIZATION 1
|
||||
// If defined, allows the SIMD-optimized routines to skip unevenly aligned
|
||||
// memory offsets that can cause performance penalty in some SIMD implementations.
|
||||
// Causes slight compromise in sound quality.
|
||||
// #define SOUNDTOUCH_ALLOW_NONEXACT_SIMD_OPTIMIZATION 1
|
||||
|
||||
|
||||
#ifdef SOUNDTOUCH_INTEGER_SAMPLES
|
||||
@@ -149,8 +149,9 @@ namespace soundtouch
|
||||
|
||||
// floating point samples
|
||||
typedef float SAMPLETYPE;
|
||||
// data type for sample accumulation: Use double to utilize full precision.
|
||||
typedef double LONG_SAMPLETYPE;
|
||||
// data type for sample accumulation: Use float also here to enable
|
||||
// efficient autovectorization
|
||||
typedef float LONG_SAMPLETYPE;
|
||||
|
||||
#ifdef SOUNDTOUCH_ALLOW_X86_OPTIMIZATIONS
|
||||
// Allow SSE optimizations
|
||||
@@ -159,7 +160,13 @@ namespace soundtouch
|
||||
|
||||
#endif // SOUNDTOUCH_INTEGER_SAMPLES
|
||||
|
||||
};
|
||||
#if ((SOUNDTOUCH_ALLOW_SSE) || (__SSE__) || (SOUNDTOUCH_USE_NEON))
|
||||
#if SOUNDTOUCH_ALLOW_NONEXACT_SIMD_OPTIMIZATION
|
||||
#define ST_SIMD_AVOID_UNALIGNED
|
||||
#endif
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
// define ST_NO_EXCEPTION_HANDLING switch to disable throwing std exceptions:
|
||||
// #define ST_NO_EXCEPTION_HANDLING 1
|
||||
|
||||
+2
-2
@@ -72,10 +72,10 @@ namespace soundtouch
|
||||
{
|
||||
|
||||
/// Soundtouch library version string
|
||||
#define SOUNDTOUCH_VERSION "2.1.2"
|
||||
#define SOUNDTOUCH_VERSION "2.3.1"
|
||||
|
||||
/// SoundTouch library version id
|
||||
#define SOUNDTOUCH_VERSION_ID (20102)
|
||||
#define SOUNDTOUCH_VERSION_ID (20301)
|
||||
|
||||
//
|
||||
// Available setting IDs for the 'setSetting' & 'get_setting' functions:
|
||||
|
||||
+3
-4
@@ -313,7 +313,7 @@ void BPMDetect::updateXCorr(int process_samples)
|
||||
#pragma omp parallel for
|
||||
for (offs = windowStart; offs < windowLen; offs ++)
|
||||
{
|
||||
double sum;
|
||||
float sum;
|
||||
int i;
|
||||
|
||||
sum = 0;
|
||||
@@ -341,7 +341,6 @@ void BPMDetect::updateBeatPos(int process_samples)
|
||||
// static double thr = 0.0003;
|
||||
double posScale = (double)this->decimateBy / (double)this->sampleRate;
|
||||
int resetDur = (int)(0.12 / posScale + 0.5);
|
||||
double corrScale = 1.0 / (double)(windowLen - windowStart);
|
||||
|
||||
// prescale pbuffer
|
||||
float tmp[XCORR_UPDATE_SEQUENCE / 2];
|
||||
@@ -353,7 +352,7 @@ void BPMDetect::updateBeatPos(int process_samples)
|
||||
#pragma omp parallel for
|
||||
for (int offs = windowStart; offs < windowLen; offs++)
|
||||
{
|
||||
double sum = 0;
|
||||
float sum = 0;
|
||||
for (int i = 0; i < process_samples; i++)
|
||||
{
|
||||
sum += tmp[i] * pBuffer[offs + i];
|
||||
@@ -562,7 +561,7 @@ float BPMDetect::getBpm()
|
||||
/// \return number of beats in the arrays.
|
||||
int BPMDetect::getBeats(float *pos, float *values, int max_num)
|
||||
{
|
||||
int num = beats.size();
|
||||
int num = (int)beats.size();
|
||||
if ((!pos) || (!values)) return num; // pos or values NULL, return just size
|
||||
|
||||
for (int i = 0; (i < num) && (i < max_num); i++)
|
||||
|
||||
@@ -265,3 +265,11 @@ uint FIFOSampleBuffer::adjustAmountOfSamples(uint numSamples)
|
||||
}
|
||||
return samplesInBuffer;
|
||||
}
|
||||
|
||||
|
||||
/// Add silence to end of buffer
|
||||
void FIFOSampleBuffer::addSilent(uint nSamples)
|
||||
{
|
||||
memset(ptrEnd(nSamples), 0, sizeof(SAMPLETYPE) * nSamples * channels);
|
||||
samplesInBuffer += nSamples;
|
||||
}
|
||||
|
||||
+44
-39
@@ -60,12 +60,14 @@ FIRFilter::FIRFilter()
|
||||
length = 0;
|
||||
lengthDiv8 = 0;
|
||||
filterCoeffs = NULL;
|
||||
filterCoeffsStereo = NULL;
|
||||
}
|
||||
|
||||
|
||||
FIRFilter::~FIRFilter()
|
||||
{
|
||||
delete[] filterCoeffs;
|
||||
delete[] filterCoeffsStereo;
|
||||
}
|
||||
|
||||
|
||||
@@ -78,35 +80,26 @@ uint FIRFilter::evaluateFilterStereo(SAMPLETYPE *dest, const SAMPLETYPE *src, ui
|
||||
// because division is much slower operation than multiplying.
|
||||
double dScaler = 1.0 / (double)resultDivider;
|
||||
#endif
|
||||
// hint compiler autovectorization that loop length is divisible by 8
|
||||
int ilength = length & -8;
|
||||
|
||||
assert(length != 0);
|
||||
assert(src != NULL);
|
||||
assert(dest != NULL);
|
||||
assert(filterCoeffs != NULL);
|
||||
assert((length != 0) && (length == ilength) && (src != NULL) && (dest != NULL) && (filterCoeffs != NULL));
|
||||
|
||||
end = 2 * (numSamples - length);
|
||||
end = 2 * (numSamples - ilength);
|
||||
|
||||
#pragma omp parallel for
|
||||
for (j = 0; j < end; j += 2)
|
||||
{
|
||||
const SAMPLETYPE *ptr;
|
||||
LONG_SAMPLETYPE suml, sumr;
|
||||
uint i;
|
||||
|
||||
suml = sumr = 0;
|
||||
ptr = src + j;
|
||||
|
||||
for (i = 0; i < length; i += 4)
|
||||
for (int i = 0; i < ilength; i ++)
|
||||
{
|
||||
// loop is unrolled by factor of 4 here for efficiency
|
||||
suml += ptr[2 * i + 0] * filterCoeffs[i + 0] +
|
||||
ptr[2 * i + 2] * filterCoeffs[i + 1] +
|
||||
ptr[2 * i + 4] * filterCoeffs[i + 2] +
|
||||
ptr[2 * i + 6] * filterCoeffs[i + 3];
|
||||
sumr += ptr[2 * i + 1] * filterCoeffs[i + 0] +
|
||||
ptr[2 * i + 3] * filterCoeffs[i + 1] +
|
||||
ptr[2 * i + 5] * filterCoeffs[i + 2] +
|
||||
ptr[2 * i + 7] * filterCoeffs[i + 3];
|
||||
suml += ptr[2 * i] * filterCoeffsStereo[2 * i];
|
||||
sumr += ptr[2 * i + 1] * filterCoeffsStereo[2 * i + 1];
|
||||
}
|
||||
|
||||
#ifdef SOUNDTOUCH_INTEGER_SAMPLES
|
||||
@@ -116,14 +109,11 @@ uint FIRFilter::evaluateFilterStereo(SAMPLETYPE *dest, const SAMPLETYPE *src, ui
|
||||
suml = (suml < -32768) ? -32768 : (suml > 32767) ? 32767 : suml;
|
||||
// saturate to 16 bit integer limits
|
||||
sumr = (sumr < -32768) ? -32768 : (sumr > 32767) ? 32767 : sumr;
|
||||
#else
|
||||
suml *= dScaler;
|
||||
sumr *= dScaler;
|
||||
#endif // SOUNDTOUCH_INTEGER_SAMPLES
|
||||
dest[j] = (SAMPLETYPE)suml;
|
||||
dest[j + 1] = (SAMPLETYPE)sumr;
|
||||
}
|
||||
return numSamples - length;
|
||||
return numSamples - ilength;
|
||||
}
|
||||
|
||||
|
||||
@@ -137,31 +127,28 @@ uint FIRFilter::evaluateFilterMono(SAMPLETYPE *dest, const SAMPLETYPE *src, uint
|
||||
double dScaler = 1.0 / (double)resultDivider;
|
||||
#endif
|
||||
|
||||
assert(length != 0);
|
||||
// hint compiler autovectorization that loop length is divisible by 8
|
||||
int ilength = length & -8;
|
||||
|
||||
end = numSamples - length;
|
||||
assert(ilength != 0);
|
||||
|
||||
end = numSamples - ilength;
|
||||
#pragma omp parallel for
|
||||
for (j = 0; j < end; j ++)
|
||||
for (j = 0; j < end; j ++)
|
||||
{
|
||||
const SAMPLETYPE *pSrc = src + j;
|
||||
LONG_SAMPLETYPE sum;
|
||||
uint i;
|
||||
int i;
|
||||
|
||||
sum = 0;
|
||||
for (i = 0; i < length; i += 4)
|
||||
for (i = 0; i < ilength; i ++)
|
||||
{
|
||||
// loop is unrolled by factor of 4 here for efficiency
|
||||
sum += pSrc[i + 0] * filterCoeffs[i + 0] +
|
||||
pSrc[i + 1] * filterCoeffs[i + 1] +
|
||||
pSrc[i + 2] * filterCoeffs[i + 2] +
|
||||
pSrc[i + 3] * filterCoeffs[i + 3];
|
||||
sum += pSrc[i] * filterCoeffs[i];
|
||||
}
|
||||
#ifdef SOUNDTOUCH_INTEGER_SAMPLES
|
||||
sum >>= resultDivFactor;
|
||||
// saturate to 16 bit integer limits
|
||||
sum = (sum < -32768) ? -32768 : (sum > 32767) ? 32767 : sum;
|
||||
#else
|
||||
sum *= dScaler;
|
||||
#endif // SOUNDTOUCH_INTEGER_SAMPLES
|
||||
dest[j] = (SAMPLETYPE)sum;
|
||||
}
|
||||
@@ -185,14 +172,18 @@ uint FIRFilter::evaluateFilterMulti(SAMPLETYPE *dest, const SAMPLETYPE *src, uin
|
||||
assert(filterCoeffs != NULL);
|
||||
assert(numChannels < 16);
|
||||
|
||||
end = numChannels * (numSamples - length);
|
||||
// hint compiler autovectorization that loop length is divisible by 8
|
||||
int ilength = length & -8;
|
||||
|
||||
end = numChannels * (numSamples - ilength);
|
||||
|
||||
#pragma omp parallel for
|
||||
for (j = 0; j < end; j += numChannels)
|
||||
{
|
||||
const SAMPLETYPE *ptr;
|
||||
LONG_SAMPLETYPE sums[16];
|
||||
uint c, i;
|
||||
uint c;
|
||||
int i;
|
||||
|
||||
for (c = 0; c < numChannels; c ++)
|
||||
{
|
||||
@@ -201,7 +192,7 @@ uint FIRFilter::evaluateFilterMulti(SAMPLETYPE *dest, const SAMPLETYPE *src, uin
|
||||
|
||||
ptr = src + j;
|
||||
|
||||
for (i = 0; i < length; i ++)
|
||||
for (i = 0; i < ilength; i ++)
|
||||
{
|
||||
SAMPLETYPE coef=filterCoeffs[i];
|
||||
for (c = 0; c < numChannels; c ++)
|
||||
@@ -215,13 +206,11 @@ uint FIRFilter::evaluateFilterMulti(SAMPLETYPE *dest, const SAMPLETYPE *src, uin
|
||||
{
|
||||
#ifdef SOUNDTOUCH_INTEGER_SAMPLES
|
||||
sums[c] >>= resultDivFactor;
|
||||
#else
|
||||
sums[c] *= dScaler;
|
||||
#endif // SOUNDTOUCH_INTEGER_SAMPLES
|
||||
dest[j+c] = (SAMPLETYPE)sums[c];
|
||||
}
|
||||
}
|
||||
return numSamples - length;
|
||||
return numSamples - ilength;
|
||||
}
|
||||
|
||||
|
||||
@@ -233,6 +222,13 @@ void FIRFilter::setCoefficients(const SAMPLETYPE *coeffs, uint newLength, uint u
|
||||
assert(newLength > 0);
|
||||
if (newLength % 8) ST_THROW_RT_ERROR("FIR filter length not divisible by 8");
|
||||
|
||||
#ifdef SOUNDTOUCH_FLOAT_SAMPLES
|
||||
// scale coefficients already here if using floating samples
|
||||
double scale = 1.0 / resultDivider;
|
||||
#else
|
||||
short scale = 1;
|
||||
#endif
|
||||
|
||||
lengthDiv8 = newLength / 8;
|
||||
length = lengthDiv8 * 8;
|
||||
assert(length == newLength);
|
||||
@@ -242,7 +238,16 @@ void FIRFilter::setCoefficients(const SAMPLETYPE *coeffs, uint newLength, uint u
|
||||
|
||||
delete[] filterCoeffs;
|
||||
filterCoeffs = new SAMPLETYPE[length];
|
||||
memcpy(filterCoeffs, coeffs, length * sizeof(SAMPLETYPE));
|
||||
delete[] filterCoeffsStereo;
|
||||
filterCoeffsStereo = new SAMPLETYPE[length*2];
|
||||
for (uint i = 0; i < length; i ++)
|
||||
{
|
||||
filterCoeffs[i] = (SAMPLETYPE)(coeffs[i] * scale);
|
||||
// create also stereo set of filter coefficients: this allows compiler
|
||||
// to autovectorize filter evaluation much more efficiently
|
||||
filterCoeffsStereo[2 * i] = (SAMPLETYPE)(coeffs[i] * scale);
|
||||
filterCoeffsStereo[2 * i + 1] = (SAMPLETYPE)(coeffs[i] * scale);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -57,6 +57,7 @@ protected:
|
||||
|
||||
// Memory for filter coefficients
|
||||
SAMPLETYPE *filterCoeffs;
|
||||
SAMPLETYPE *filterCoeffsStereo;
|
||||
|
||||
virtual uint evaluateFilterStereo(SAMPLETYPE *dest,
|
||||
const SAMPLETYPE *src,
|
||||
|
||||
@@ -41,7 +41,6 @@ namespace soundtouch
|
||||
class InterpolateCubic : public TransposerBase
|
||||
{
|
||||
protected:
|
||||
virtual void resetRegisters();
|
||||
virtual int transposeMono(SAMPLETYPE *dest,
|
||||
const SAMPLETYPE *src,
|
||||
int &srcSamples);
|
||||
@@ -56,6 +55,13 @@ protected:
|
||||
|
||||
public:
|
||||
InterpolateCubic();
|
||||
|
||||
virtual void resetRegisters();
|
||||
|
||||
int getLatency() const
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -142,7 +142,7 @@ int InterpolateLinearInteger::transposeMulti(SAMPLETYPE *dest, const SAMPLETYPE
|
||||
LONG_SAMPLETYPE temp, vol1;
|
||||
|
||||
assert(iFract < SCALE);
|
||||
vol1 = (SCALE - iFract);
|
||||
vol1 = (LONG_SAMPLETYPE)(SCALE - iFract);
|
||||
for (int c = 0; c < numChannels; c ++)
|
||||
{
|
||||
temp = vol1 * src[c] + iFract * src[c + numChannels];
|
||||
|
||||
+14
-4
@@ -45,8 +45,6 @@ protected:
|
||||
int iFract;
|
||||
int iRate;
|
||||
|
||||
virtual void resetRegisters();
|
||||
|
||||
virtual int transposeMono(SAMPLETYPE *dest,
|
||||
const SAMPLETYPE *src,
|
||||
int &srcSamples);
|
||||
@@ -60,6 +58,13 @@ public:
|
||||
/// Sets new target rate. Normal rate = 1.0, smaller values represent slower
|
||||
/// rate, larger faster rates.
|
||||
virtual void setRate(double newRate);
|
||||
|
||||
virtual void resetRegisters();
|
||||
|
||||
int getLatency() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -69,8 +74,6 @@ class InterpolateLinearFloat : public TransposerBase
|
||||
protected:
|
||||
double fract;
|
||||
|
||||
virtual void resetRegisters();
|
||||
|
||||
virtual int transposeMono(SAMPLETYPE *dest,
|
||||
const SAMPLETYPE *src,
|
||||
int &srcSamples);
|
||||
@@ -81,6 +84,13 @@ protected:
|
||||
|
||||
public:
|
||||
InterpolateLinearFloat();
|
||||
|
||||
virtual void resetRegisters();
|
||||
|
||||
int getLatency() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -46,7 +46,6 @@ namespace soundtouch
|
||||
class InterpolateShannon : public TransposerBase
|
||||
{
|
||||
protected:
|
||||
void resetRegisters();
|
||||
int transposeMono(SAMPLETYPE *dest,
|
||||
const SAMPLETYPE *src,
|
||||
int &srcSamples);
|
||||
@@ -61,6 +60,13 @@ protected:
|
||||
|
||||
public:
|
||||
InterpolateShannon();
|
||||
|
||||
void resetRegisters();
|
||||
|
||||
int getLatency() const
|
||||
{
|
||||
return 3;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
+3
-3
@@ -57,7 +57,7 @@ int PeakFinder::findTop(const float *data, int peakpos) const
|
||||
|
||||
refvalue = data[peakpos];
|
||||
|
||||
// seek within �10 points
|
||||
// seek within ±10 points
|
||||
start = peakpos - 10;
|
||||
if (start < minPos) start = minPos;
|
||||
end = peakpos + 10;
|
||||
@@ -142,7 +142,7 @@ int PeakFinder::findCrossingLevel(const float *data, float level, int peakpos, i
|
||||
peaklevel = data[peakpos];
|
||||
assert(peaklevel >= level);
|
||||
pos = peakpos;
|
||||
while ((pos >= minPos) && (pos < maxPos))
|
||||
while ((pos >= minPos) && (pos + direction < maxPos))
|
||||
{
|
||||
if (data[pos + direction] < level) return pos; // crossing found
|
||||
pos += direction;
|
||||
@@ -256,7 +256,7 @@ double PeakFinder::detectPeak(const float *data, int aminPos, int amaxPos)
|
||||
|
||||
// accept harmonic peak if
|
||||
// (a) it is found
|
||||
// (b) is within �4% of the expected harmonic interval
|
||||
// (b) is within ±4% of the expected harmonic interval
|
||||
// (c) has at least half x-corr value of the max. peak
|
||||
|
||||
double diff = harmonic * peaktmp / highPeak;
|
||||
|
||||
@@ -61,6 +61,7 @@ RateTransposer::RateTransposer() : FIFOProcessor(&outputBuffer)
|
||||
// Instantiates the anti-alias filter
|
||||
pAAFilter = new AAFilter(64);
|
||||
pTransposer = TransposerBase::newInstance();
|
||||
clear();
|
||||
}
|
||||
|
||||
|
||||
@@ -77,6 +78,7 @@ void RateTransposer::enableAAFilter(bool newMode)
|
||||
#ifndef SOUNDTOUCH_PREVENT_CLICK_AT_RATE_CROSSOVER
|
||||
// Disable Anti-alias filter if desirable to avoid click at rate change zero value crossover
|
||||
bUseAAFilter = newMode;
|
||||
clear();
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -192,6 +194,11 @@ void RateTransposer::clear()
|
||||
outputBuffer.clear();
|
||||
midBuffer.clear();
|
||||
inputBuffer.clear();
|
||||
pTransposer->resetRegisters();
|
||||
|
||||
// prefill buffer to avoid losing first samples at beginning of stream
|
||||
int prefill = getLatency();
|
||||
inputBuffer.addSilent(prefill);
|
||||
}
|
||||
|
||||
|
||||
@@ -209,7 +216,8 @@ int RateTransposer::isEmpty() const
|
||||
/// Return approximate initial input-output latency
|
||||
int RateTransposer::getLatency() const
|
||||
{
|
||||
return (bUseAAFilter) ? pAAFilter->getLength() : 0;
|
||||
return pTransposer->getLatency() +
|
||||
((bUseAAFilter) ? (pAAFilter->getLength() / 2) : 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
+3
-2
@@ -59,8 +59,6 @@ public:
|
||||
};
|
||||
|
||||
protected:
|
||||
virtual void resetRegisters() = 0;
|
||||
|
||||
virtual int transposeMono(SAMPLETYPE *dest,
|
||||
const SAMPLETYPE *src,
|
||||
int &srcSamples) = 0;
|
||||
@@ -83,6 +81,9 @@ public:
|
||||
virtual int transpose(FIFOSampleBuffer &dest, FIFOSampleBuffer &src);
|
||||
virtual void setRate(double newRate);
|
||||
virtual void setChannels(int channels);
|
||||
virtual int getLatency() const = 0;
|
||||
|
||||
virtual void resetRegisters() = 0;
|
||||
|
||||
// static factory function
|
||||
static TransposerBase *newInstance();
|
||||
|
||||
+70
-75
@@ -1,4 +1,4 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
///
|
||||
/// Sampled sound tempo changer/time stretch algorithm. Changes the sound tempo
|
||||
/// while maintaining the original pitch by using a time domain WSOLA-like
|
||||
@@ -54,7 +54,6 @@ using namespace soundtouch;
|
||||
|
||||
#define max(x, y) (((x) > (y)) ? (x) : (y))
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Constant definitions
|
||||
@@ -93,11 +92,6 @@ TDStretch::TDStretch() : FIFOProcessor(&outputBuffer)
|
||||
bAutoSeqSetting = true;
|
||||
bAutoSeekSetting = true;
|
||||
|
||||
maxnorm = 0;
|
||||
maxnormf = 1e8;
|
||||
|
||||
skipFract = 0;
|
||||
|
||||
tempo = 1.0f;
|
||||
setParameters(44100, DEFAULT_SEQUENCE_MS, DEFAULT_SEEKWINDOW_MS, DEFAULT_OVERLAP_MS);
|
||||
setTempo(1.0f);
|
||||
@@ -203,7 +197,7 @@ void TDStretch::overlapMono(SAMPLETYPE *pOutput, const SAMPLETYPE *pInput) const
|
||||
m1 = (SAMPLETYPE)0;
|
||||
m2 = (SAMPLETYPE)overlapLength;
|
||||
|
||||
for (i = 0; i < overlapLength ; i ++)
|
||||
for (i = 0; i < overlapLength ; i ++)
|
||||
{
|
||||
pOutput[i] = (pInput[i] * m1 + pMidBuffer[i] * m2 ) / overlapLength;
|
||||
m1 += 1;
|
||||
@@ -224,6 +218,9 @@ void TDStretch::clearInput()
|
||||
inputBuffer.clear();
|
||||
clearMidBuffer();
|
||||
isBeginning = true;
|
||||
maxnorm = 0;
|
||||
maxnormf = 1e8;
|
||||
skipFract = 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -311,13 +308,14 @@ int TDStretch::seekBestOverlapPositionFull(const SAMPLETYPE *refPos)
|
||||
bestCorr = (bestCorr + 0.1) * 0.75;
|
||||
|
||||
#pragma omp parallel for
|
||||
for (i = 1; i < seekLength; i ++)
|
||||
for (i = 1; i < seekLength; i ++)
|
||||
{
|
||||
double corr;
|
||||
// Calculates correlation value for the mixing position corresponding to 'i'
|
||||
#ifdef _OPENMP
|
||||
#if defined(_OPENMP) || defined(ST_SIMD_AVOID_UNALIGNED)
|
||||
// in parallel OpenMP mode, can't use norm accumulator version as parallel executor won't
|
||||
// iterate the loop in sequential order
|
||||
// in SIMD mode, avoid accumulator version to allow avoiding unaligned positions
|
||||
corr = calcCrossCorr(refPos + channels * i, pMidBuffer, norm);
|
||||
#else
|
||||
// In non-parallel version call "calcCrossCorrAccumulate" that is otherwise same
|
||||
@@ -675,23 +673,24 @@ void TDStretch::processSamples()
|
||||
// Adjust processing offset at beginning of track by not perform initial overlapping
|
||||
// and compensating that in the 'input buffer skip' calculation
|
||||
isBeginning = false;
|
||||
int skip = (int)(tempo * overlapLength + 0.5);
|
||||
int skip = (int)(tempo * overlapLength + 0.5 * seekLength + 0.5);
|
||||
|
||||
#ifdef SOUNDTOUCH_ALLOW_NONEXACT_SIMD_OPTIMIZATION
|
||||
#ifdef SOUNDTOUCH_ALLOW_SSE
|
||||
// if SSE mode, round the skip amount to value corresponding to aligned memory address
|
||||
if (channels == 1)
|
||||
{
|
||||
skip &= -4;
|
||||
}
|
||||
else if (channels == 2)
|
||||
{
|
||||
skip &= -2;
|
||||
}
|
||||
#endif
|
||||
#ifdef ST_SIMD_AVOID_UNALIGNED
|
||||
// in SIMD mode, round the skip amount to value corresponding to aligned memory address
|
||||
if (channels == 1)
|
||||
{
|
||||
skip &= -4;
|
||||
}
|
||||
else if (channels == 2)
|
||||
{
|
||||
skip &= -2;
|
||||
}
|
||||
#endif
|
||||
skipFract -= skip;
|
||||
assert(nominalSkip >= -skipFract);
|
||||
if (skipFract <= -nominalSkip)
|
||||
{
|
||||
skipFract = -nominalSkip;
|
||||
}
|
||||
}
|
||||
|
||||
// ... then copy sequence samples from 'inputBuffer' to output:
|
||||
@@ -818,7 +817,7 @@ void TDStretch::overlapStereo(short *poutput, const short *input) const
|
||||
short temp;
|
||||
int cnt2;
|
||||
|
||||
for (i = 0; i < overlapLength ; i ++)
|
||||
for (i = 0; i < overlapLength ; i ++)
|
||||
{
|
||||
temp = (short)(overlapLength - i);
|
||||
cnt2 = 2 * i;
|
||||
@@ -830,21 +829,19 @@ void TDStretch::overlapStereo(short *poutput, const short *input) const
|
||||
|
||||
// Overlaps samples in 'midBuffer' with the samples in 'input'. The 'Multi'
|
||||
// version of the routine.
|
||||
void TDStretch::overlapMulti(SAMPLETYPE *poutput, const SAMPLETYPE *input) const
|
||||
void TDStretch::overlapMulti(short *poutput, const short *input) const
|
||||
{
|
||||
SAMPLETYPE m1=(SAMPLETYPE)0;
|
||||
SAMPLETYPE m2;
|
||||
int i=0;
|
||||
short m1;
|
||||
int i = 0;
|
||||
|
||||
for (m2 = (SAMPLETYPE)overlapLength; m2; m2 --)
|
||||
for (m1 = 0; m1 < overlapLength; m1 ++)
|
||||
{
|
||||
short m2 = (short)(overlapLength - m1);
|
||||
for (int c = 0; c < channels; c ++)
|
||||
{
|
||||
poutput[i] = (input[i] * m1 + pMidBuffer[i] * m2) / overlapLength;
|
||||
i++;
|
||||
}
|
||||
|
||||
m1++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -889,20 +886,23 @@ double TDStretch::calcCrossCorr(const short *mixingPos, const short *compare, do
|
||||
unsigned long lnorm;
|
||||
int i;
|
||||
|
||||
#ifdef ST_SIMD_AVOID_UNALIGNED
|
||||
// in SIMD mode skip 'mixingPos' positions that aren't aligned to 16-byte boundary
|
||||
if (((ulongptr)mixingPos) & 15) return -1e50;
|
||||
#endif
|
||||
|
||||
// hint compiler autovectorization that loop length is divisible by 8
|
||||
int ilength = (channels * overlapLength) & -8;
|
||||
|
||||
corr = lnorm = 0;
|
||||
// Same routine for stereo and mono. For stereo, unroll loop for better
|
||||
// efficiency and gives slightly better resolution against rounding.
|
||||
// For mono it same routine, just unrolls loop by factor of 4
|
||||
for (i = 0; i < channels * overlapLength; i += 4)
|
||||
// Same routine for stereo and mono
|
||||
for (i = 0; i < ilength; i += 2)
|
||||
{
|
||||
corr += (mixingPos[i] * compare[i] +
|
||||
mixingPos[i + 1] * compare[i + 1]) >> overlapDividerBitsNorm; // notice: do intermediate division here to avoid integer overflow
|
||||
corr += (mixingPos[i + 2] * compare[i + 2] +
|
||||
mixingPos[i + 3] * compare[i + 3]) >> overlapDividerBitsNorm;
|
||||
mixingPos[i + 1] * compare[i + 1]) >> overlapDividerBitsNorm;
|
||||
lnorm += (mixingPos[i] * mixingPos[i] +
|
||||
mixingPos[i + 1] * mixingPos[i + 1]) >> overlapDividerBitsNorm; // notice: do intermediate division here to avoid integer overflow
|
||||
lnorm += (mixingPos[i + 2] * mixingPos[i + 2] +
|
||||
mixingPos[i + 3] * mixingPos[i + 3]) >> overlapDividerBitsNorm;
|
||||
mixingPos[i + 1] * mixingPos[i + 1]) >> overlapDividerBitsNorm;
|
||||
// do intermediate scalings to avoid integer overflow
|
||||
}
|
||||
|
||||
if (lnorm > maxnorm)
|
||||
@@ -925,9 +925,12 @@ double TDStretch::calcCrossCorr(const short *mixingPos, const short *compare, do
|
||||
double TDStretch::calcCrossCorrAccumulate(const short *mixingPos, const short *compare, double &norm)
|
||||
{
|
||||
long corr;
|
||||
unsigned long lnorm;
|
||||
long lnorm;
|
||||
int i;
|
||||
|
||||
// hint compiler autovectorization that loop length is divisible by 8
|
||||
int ilength = (channels * overlapLength) & -8;
|
||||
|
||||
// cancel first normalizer tap from previous round
|
||||
lnorm = 0;
|
||||
for (i = 1; i <= channels; i ++)
|
||||
@@ -936,15 +939,11 @@ double TDStretch::calcCrossCorrAccumulate(const short *mixingPos, const short *c
|
||||
}
|
||||
|
||||
corr = 0;
|
||||
// Same routine for stereo and mono. For stereo, unroll loop for better
|
||||
// efficiency and gives slightly better resolution against rounding.
|
||||
// For mono it same routine, just unrolls loop by factor of 4
|
||||
for (i = 0; i < channels * overlapLength; i += 4)
|
||||
// Same routine for stereo and mono.
|
||||
for (i = 0; i < ilength; i += 2)
|
||||
{
|
||||
corr += (mixingPos[i] * compare[i] +
|
||||
mixingPos[i + 1] * compare[i + 1]) >> overlapDividerBitsNorm; // notice: do intermediate division here to avoid integer overflow
|
||||
corr += (mixingPos[i + 2] * compare[i + 2] +
|
||||
mixingPos[i + 3] * compare[i + 3]) >> overlapDividerBitsNorm;
|
||||
mixingPos[i + 1] * compare[i + 1]) >> overlapDividerBitsNorm;
|
||||
}
|
||||
|
||||
// update normalizer with last samples of this round
|
||||
@@ -1045,27 +1044,24 @@ void TDStretch::calculateOverlapLength(int overlapInMsec)
|
||||
/// Calculate cross-correlation
|
||||
double TDStretch::calcCrossCorr(const float *mixingPos, const float *compare, double &anorm)
|
||||
{
|
||||
double corr;
|
||||
double norm;
|
||||
float corr;
|
||||
float norm;
|
||||
int i;
|
||||
|
||||
#ifdef ST_SIMD_AVOID_UNALIGNED
|
||||
// in SIMD mode skip 'mixingPos' positions that aren't aligned to 16-byte boundary
|
||||
if (((ulongptr)mixingPos) & 15) return -1e50;
|
||||
#endif
|
||||
|
||||
// hint compiler autovectorization that loop length is divisible by 8
|
||||
int ilength = (channels * overlapLength) & -8;
|
||||
|
||||
corr = norm = 0;
|
||||
// Same routine for stereo and mono. For Stereo, unroll by factor of 2.
|
||||
// For mono it's same routine yet unrollsd by factor of 4.
|
||||
for (i = 0; i < channels * overlapLength; i += 4)
|
||||
// Same routine for stereo and mono
|
||||
for (i = 0; i < ilength; i ++)
|
||||
{
|
||||
corr += mixingPos[i] * compare[i] +
|
||||
mixingPos[i + 1] * compare[i + 1];
|
||||
|
||||
norm += mixingPos[i] * mixingPos[i] +
|
||||
mixingPos[i + 1] * mixingPos[i + 1];
|
||||
|
||||
// unroll the loop for better CPU efficiency:
|
||||
corr += mixingPos[i + 2] * compare[i + 2] +
|
||||
mixingPos[i + 3] * compare[i + 3];
|
||||
|
||||
norm += mixingPos[i + 2] * mixingPos[i + 2] +
|
||||
mixingPos[i + 3] * mixingPos[i + 3];
|
||||
corr += mixingPos[i] * compare[i];
|
||||
norm += mixingPos[i] * mixingPos[i];
|
||||
}
|
||||
|
||||
anorm = norm;
|
||||
@@ -1076,7 +1072,7 @@ double TDStretch::calcCrossCorr(const float *mixingPos, const float *compare, do
|
||||
/// Update cross-correlation by accumulating "norm" coefficient by previously calculated value
|
||||
double TDStretch::calcCrossCorrAccumulate(const float *mixingPos, const float *compare, double &norm)
|
||||
{
|
||||
double corr;
|
||||
float corr;
|
||||
int i;
|
||||
|
||||
corr = 0;
|
||||
@@ -1087,14 +1083,13 @@ double TDStretch::calcCrossCorrAccumulate(const float *mixingPos, const float *c
|
||||
norm -= mixingPos[-i] * mixingPos[-i];
|
||||
}
|
||||
|
||||
// Same routine for stereo and mono. For Stereo, unroll by factor of 2.
|
||||
// For mono it's same routine yet unrollsd by factor of 4.
|
||||
for (i = 0; i < channels * overlapLength; i += 4)
|
||||
// hint compiler autovectorization that loop length is divisible by 8
|
||||
int ilength = (channels * overlapLength) & -8;
|
||||
|
||||
// Same routine for stereo and mono
|
||||
for (i = 0; i < ilength; i ++)
|
||||
{
|
||||
corr += mixingPos[i] * compare[i] +
|
||||
mixingPos[i + 1] * compare[i + 1] +
|
||||
mixingPos[i + 2] * compare[i + 2] +
|
||||
mixingPos[i + 3] * compare[i + 3];
|
||||
corr += mixingPos[i] * compare[i];
|
||||
}
|
||||
|
||||
// update normalizer with last samples of this round
|
||||
|
||||
+1
-1
@@ -80,7 +80,7 @@ double TDStretchSSE::calcCrossCorr(const float *pV1, const float *pV2, double &a
|
||||
// Compile-time define SOUNDTOUCH_ALLOW_NONEXACT_SIMD_OPTIMIZATION is provided
|
||||
// for choosing if this little cheating is allowed.
|
||||
|
||||
#ifdef SOUNDTOUCH_ALLOW_NONEXACT_SIMD_OPTIMIZATION
|
||||
#ifdef ST_SIMD_AVOID_UNALIGNED
|
||||
// Little cheating allowed, return valid correlation only for
|
||||
// aligned locations, meaning every second round for stereo sound.
|
||||
|
||||
|
||||
+6
-1
@@ -1319,7 +1319,7 @@ public:
|
||||
wxString(const wxStdWideString& str)
|
||||
{ assign(str.c_str(), str.length()); }
|
||||
#endif
|
||||
|
||||
#ifndef _WIN32 // PCSX2: We don't want to accidentally interpret utf-8 std::strings as something else!
|
||||
#if !wxUSE_UNICODE // ANSI build
|
||||
// FIXME-UTF8: do this in UTF8 build #if wxUSE_UTF8_LOCALE_ONLY, too
|
||||
wxString(const std::string& str) : m_impl(str) {}
|
||||
@@ -1327,6 +1327,7 @@ public:
|
||||
wxString(const std::string& str)
|
||||
{ assign(str.c_str(), str.length()); }
|
||||
#endif
|
||||
#endif
|
||||
#endif // wxUSE_STD_STRING
|
||||
|
||||
// Also always provide explicit conversions to std::[w]string in any case,
|
||||
@@ -1620,13 +1621,17 @@ public:
|
||||
// messages for the code which relies on implicit conversion to char* in
|
||||
// STL build
|
||||
#if !wxUSE_STD_STRING_CONV_IN_WXSTRING
|
||||
#ifndef _WIN32 // PCSX2: std::string conversion removal
|
||||
operator const char*() const { return c_str(); }
|
||||
#endif
|
||||
operator const wchar_t*() const { return c_str(); }
|
||||
|
||||
#ifndef _WIN32 // PCSX2: std::string conversion removal
|
||||
// implicit conversion to untyped pointer for compatibility with previous
|
||||
// wxWidgets versions: this is the same as conversion to const char * so it
|
||||
// may fail!
|
||||
operator const void*() const { return c_str(); }
|
||||
#endif
|
||||
#endif // !wxUSE_STD_STRING_CONV_IN_WXSTRING
|
||||
|
||||
// identical to c_str(), for MFC compatibility
|
||||
|
||||
+2
@@ -230,6 +230,7 @@ public:
|
||||
wxString GetString() const;
|
||||
|
||||
#if wxUSE_STD_STRING
|
||||
#ifndef _WIN32 // PCSX2: std::string conversion removal
|
||||
wxVariant(const std::string& val, const wxString& name = wxEmptyString);
|
||||
bool operator==(const std::string& value) const
|
||||
{ return operator==(wxString(value)); }
|
||||
@@ -238,6 +239,7 @@ public:
|
||||
wxVariant& operator=(const std::string& value)
|
||||
{ return operator=(wxString(value)); }
|
||||
operator std::string() const { return (operator wxString()).ToStdString(); }
|
||||
#endif
|
||||
|
||||
wxVariant(const wxStdWideString& val, const wxString& name = wxEmptyString);
|
||||
bool operator==(const wxStdWideString& value) const
|
||||
|
||||
@@ -981,11 +981,13 @@ wxVariant::wxVariant(const wxScopedWCharBuffer& val, const wxString& name)
|
||||
}
|
||||
|
||||
#if wxUSE_STD_STRING
|
||||
#ifndef _WIN32 // PCSX2: std::string conversion removal
|
||||
wxVariant::wxVariant(const std::string& val, const wxString& name)
|
||||
{
|
||||
m_refData = new wxVariantDataString(wxString(val));
|
||||
m_name = name;
|
||||
}
|
||||
#endif
|
||||
|
||||
wxVariant::wxVariant(const wxStdWideString& val, const wxString& name)
|
||||
{
|
||||
|
||||
Vendored
+47
@@ -0,0 +1,47 @@
|
||||
|
||||
Copyright (c) 2007 MITSUNARI Shigeo
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
Neither the name of the copyright owner nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
THE POSSIBILITY OF SUCH DAMAGE.
|
||||
-----------------------------------------------------------------------------
|
||||
ソースコード形式かバイナリ形式か、変更するかしないかを問わず、以下の条件を満た
|
||||
す場合に限り、再頒布および使用が許可されます。
|
||||
|
||||
ソースコードを再頒布する場合、上記の著作権表示、本条件一覧、および下記免責条項
|
||||
を含めること。
|
||||
バイナリ形式で再頒布する場合、頒布物に付属のドキュメント等の資料に、上記の著作
|
||||
権表示、本条件一覧、および下記免責条項を含めること。
|
||||
書面による特別の許可なしに、本ソフトウェアから派生した製品の宣伝または販売促進
|
||||
に、著作権者の名前またはコントリビューターの名前を使用してはならない。
|
||||
本ソフトウェアは、著作権者およびコントリビューターによって「現状のまま」提供さ
|
||||
れており、明示黙示を問わず、商業的な使用可能性、および特定の目的に対する適合性
|
||||
に関する暗黙の保証も含め、またそれに限定されない、いかなる保証もありません。
|
||||
著作権者もコントリビューターも、事由のいかんを問わず、 損害発生の原因いかんを
|
||||
問わず、かつ責任の根拠が契約であるか厳格責任であるか(過失その他の)不法行為で
|
||||
あるかを問わず、仮にそのような損害が発生する可能性を知らされていたとしても、
|
||||
本ソフトウェアの使用によって発生した(代替品または代用サービスの調達、使用の
|
||||
喪失、データの喪失、利益の喪失、業務の中断も含め、またそれに限定されない)直接
|
||||
損害、間接損害、偶発的な損害、特別損害、懲罰的損害、または結果損害について、
|
||||
一切責任を負わないものとします。
|
||||
Vendored
+985
-548
File diff suppressed because it is too large
Load Diff
+999
-645
File diff suppressed because it is too large
Load Diff
Vendored
+506
-199
@@ -1,36 +1,17 @@
|
||||
/* Copyright (c) 2007 MITSUNARI Shigeo
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright owner nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef XBYAK_XBYAK_UTIL_H_
|
||||
#define XBYAK_XBYAK_UTIL_H_
|
||||
|
||||
// We want to keep this file similar to the original xbyak
|
||||
// clang-format off
|
||||
#ifdef XBYAK_ONLY_CLASS_CPU
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <algorithm>
|
||||
#include <assert.h>
|
||||
#ifndef XBYAK_THROW
|
||||
#define XBYAK_THROW(x) ;
|
||||
#define XBYAK_THROW_RET(x, y) return y;
|
||||
#endif
|
||||
#else
|
||||
#include <string.h>
|
||||
|
||||
/**
|
||||
utility class and functions for Xbyak
|
||||
@@ -39,7 +20,13 @@
|
||||
@note this header is UNDER CONSTRUCTION!
|
||||
*/
|
||||
#include "xbyak.h"
|
||||
#endif // XBYAK_ONLY_CLASS_CPU
|
||||
|
||||
#if defined(__i386__) || defined(__x86_64__) || defined(_M_IX86) || defined(_M_X64)
|
||||
#define XBYAK_INTEL_CPU_SPECIFIC
|
||||
#endif
|
||||
|
||||
#ifdef XBYAK_INTEL_CPU_SPECIFIC
|
||||
#ifdef _MSC_VER
|
||||
#if (_MSC_VER < 1400) && defined(XBYAK32)
|
||||
static inline __declspec(naked) void __cpuid(int[4], int)
|
||||
@@ -78,35 +65,44 @@
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
extern "C" unsigned __int64 __xgetbv(int);
|
||||
#ifdef XBYAK_USE_VTUNE
|
||||
// -I /opt/intel/vtune_amplifier/include/ -L /opt/intel/vtune_amplifier/lib64 -ljitprofiling -ldl
|
||||
#include <jitprofiling.h>
|
||||
#ifdef _MSC_VER
|
||||
#pragma comment(lib, "libittnotify.lib")
|
||||
#endif
|
||||
#ifdef __linux__
|
||||
#include <dlfcn.h>
|
||||
#endif
|
||||
#endif
|
||||
#ifdef __linux__
|
||||
#define XBYAK_USE_PERF
|
||||
#endif
|
||||
|
||||
namespace Xbyak { namespace util {
|
||||
|
||||
/* GCC uses AVX/SSE4 operation to handle the uint64 type.
|
||||
*
|
||||
* It is quite annoying because the purpose of the code is to test the support
|
||||
* of AVX/SSEn
|
||||
*
|
||||
* So far, we don't need other ISA on i386 so I hacked the code to limit the
|
||||
* type to 32 bits. If we want to support AVX512 we might need to shuffle the
|
||||
* code a bit.
|
||||
*
|
||||
* Extra note: it would be waste to use AVX512 on 32 bits, registers are
|
||||
* limited to 8 instead of 32.
|
||||
*/
|
||||
typedef enum {
|
||||
SmtLevel = 1,
|
||||
CoreLevel = 2
|
||||
} IntelCpuTopologyLevel;
|
||||
|
||||
/**
|
||||
CPU detection class
|
||||
*/
|
||||
class Cpu {
|
||||
#ifdef XBYAK64
|
||||
uint64 type_;
|
||||
#else
|
||||
uint32 type_;
|
||||
#endif
|
||||
uint64_t type_;
|
||||
//system topology
|
||||
bool x2APIC_supported_;
|
||||
static const size_t maxTopologyLevels = 2;
|
||||
unsigned int numCores_[maxTopologyLevels];
|
||||
|
||||
static const unsigned int maxNumberCacheLevels = 10;
|
||||
unsigned int dataCacheSize_[maxNumberCacheLevels];
|
||||
unsigned int coresSharignDataCache_[maxNumberCacheLevels];
|
||||
unsigned int dataCacheLevels_;
|
||||
|
||||
unsigned int get32bitAsBE(const char *x) const
|
||||
{
|
||||
return x[0] | (x[1] << 8) | (x[2] << 16) | (x[3] << 24);
|
||||
@@ -117,7 +113,7 @@ class Cpu {
|
||||
}
|
||||
void setFamily()
|
||||
{
|
||||
unsigned int data[4];
|
||||
unsigned int data[4] = {};
|
||||
getCpuid(1, data);
|
||||
stepping = data[0] & mask(4);
|
||||
model = (data[0] >> 4) & mask(4);
|
||||
@@ -136,6 +132,96 @@ class Cpu {
|
||||
displayModel = model;
|
||||
}
|
||||
}
|
||||
unsigned int extractBit(unsigned int val, unsigned int base, unsigned int end)
|
||||
{
|
||||
return (val >> base) & ((1u << (end - base)) - 1);
|
||||
}
|
||||
void setNumCores()
|
||||
{
|
||||
if ((type_ & tINTEL) == 0) return;
|
||||
|
||||
unsigned int data[4] = {};
|
||||
|
||||
/* CAUTION: These numbers are configuration as shipped by Intel. */
|
||||
getCpuidEx(0x0, 0, data);
|
||||
if (data[0] >= 0xB) {
|
||||
/*
|
||||
if leaf 11 exists(x2APIC is supported),
|
||||
we use it to get the number of smt cores and cores on socket
|
||||
|
||||
leaf 0xB can be zeroed-out by a hypervisor
|
||||
*/
|
||||
x2APIC_supported_ = true;
|
||||
for (unsigned int i = 0; i < maxTopologyLevels; i++) {
|
||||
getCpuidEx(0xB, i, data);
|
||||
IntelCpuTopologyLevel level = (IntelCpuTopologyLevel)extractBit(data[2], 8, 15);
|
||||
if (level == SmtLevel || level == CoreLevel) {
|
||||
numCores_[level - 1] = extractBit(data[1], 0, 15);
|
||||
}
|
||||
}
|
||||
/*
|
||||
Fallback values in case a hypervisor has 0xB leaf zeroed-out.
|
||||
*/
|
||||
numCores_[SmtLevel - 1] = (std::max)(1u, numCores_[SmtLevel - 1]);
|
||||
numCores_[CoreLevel - 1] = (std::max)(numCores_[SmtLevel - 1], numCores_[CoreLevel - 1]);
|
||||
} else {
|
||||
/*
|
||||
Failed to deremine num of cores without x2APIC support.
|
||||
TODO: USE initial APIC ID to determine ncores.
|
||||
*/
|
||||
numCores_[SmtLevel - 1] = 0;
|
||||
numCores_[CoreLevel - 1] = 0;
|
||||
}
|
||||
|
||||
}
|
||||
void setCacheHierarchy()
|
||||
{
|
||||
if ((type_ & tINTEL) == 0) return;
|
||||
const unsigned int NO_CACHE = 0;
|
||||
const unsigned int DATA_CACHE = 1;
|
||||
// const unsigned int INSTRUCTION_CACHE = 2;
|
||||
const unsigned int UNIFIED_CACHE = 3;
|
||||
unsigned int smt_width = 0;
|
||||
unsigned int logical_cores = 0;
|
||||
unsigned int data[4] = {};
|
||||
|
||||
if (x2APIC_supported_) {
|
||||
smt_width = numCores_[0];
|
||||
logical_cores = numCores_[1];
|
||||
}
|
||||
|
||||
/*
|
||||
Assumptions:
|
||||
the first level of data cache is not shared (which is the
|
||||
case for every existing architecture) and use this to
|
||||
determine the SMT width for arch not supporting leaf 11.
|
||||
when leaf 4 reports a number of core less than numCores_
|
||||
on socket reported by leaf 11, then it is a correct number
|
||||
of cores not an upperbound.
|
||||
*/
|
||||
for (int i = 0; dataCacheLevels_ < maxNumberCacheLevels; i++) {
|
||||
getCpuidEx(0x4, i, data);
|
||||
unsigned int cacheType = extractBit(data[0], 0, 4);
|
||||
if (cacheType == NO_CACHE) break;
|
||||
if (cacheType == DATA_CACHE || cacheType == UNIFIED_CACHE) {
|
||||
unsigned int actual_logical_cores = extractBit(data[0], 14, 25) + 1;
|
||||
if (logical_cores != 0) { // true only if leaf 0xB is supported and valid
|
||||
actual_logical_cores = (std::min)(actual_logical_cores, logical_cores);
|
||||
}
|
||||
assert(actual_logical_cores != 0);
|
||||
dataCacheSize_[dataCacheLevels_] =
|
||||
(extractBit(data[1], 22, 31) + 1)
|
||||
* (extractBit(data[1], 12, 21) + 1)
|
||||
* (extractBit(data[1], 0, 11) + 1)
|
||||
* (data[2] + 1);
|
||||
if (cacheType == DATA_CACHE && smt_width == 0) smt_width = actual_logical_cores;
|
||||
assert(smt_width != 0);
|
||||
coresSharignDataCache_[dataCacheLevels_] = (std::max)(actual_logical_cores / smt_width, 1u);
|
||||
dataCacheLevels_++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
int model;
|
||||
int family;
|
||||
@@ -144,42 +230,76 @@ public:
|
||||
int extFamily;
|
||||
int displayFamily; // family + extFamily
|
||||
int displayModel; // model + extModel
|
||||
|
||||
unsigned int getNumCores(IntelCpuTopologyLevel level) const {
|
||||
if (!x2APIC_supported_) XBYAK_THROW_RET(ERR_X2APIC_IS_NOT_SUPPORTED, 0)
|
||||
switch (level) {
|
||||
case SmtLevel: return numCores_[level - 1];
|
||||
case CoreLevel: return numCores_[level - 1] / numCores_[SmtLevel - 1];
|
||||
default: XBYAK_THROW_RET(ERR_X2APIC_IS_NOT_SUPPORTED, 0)
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int getDataCacheLevels() const { return dataCacheLevels_; }
|
||||
unsigned int getCoresSharingDataCache(unsigned int i) const
|
||||
{
|
||||
if (i >= dataCacheLevels_) XBYAK_THROW_RET(ERR_BAD_PARAMETER, 0)
|
||||
return coresSharignDataCache_[i];
|
||||
}
|
||||
unsigned int getDataCacheSize(unsigned int i) const
|
||||
{
|
||||
if (i >= dataCacheLevels_) XBYAK_THROW_RET(ERR_BAD_PARAMETER, 0)
|
||||
return dataCacheSize_[i];
|
||||
}
|
||||
|
||||
/*
|
||||
data[] = { eax, ebx, ecx, edx }
|
||||
*/
|
||||
static inline void getCpuid(unsigned int eaxIn, unsigned int data[4])
|
||||
{
|
||||
#ifdef _MSC_VER
|
||||
#ifdef XBYAK_INTEL_CPU_SPECIFIC
|
||||
#ifdef _MSC_VER
|
||||
__cpuid(reinterpret_cast<int*>(data), eaxIn);
|
||||
#else
|
||||
#else
|
||||
__cpuid(eaxIn, data[0], data[1], data[2], data[3]);
|
||||
#endif
|
||||
#else
|
||||
(void)eaxIn;
|
||||
(void)data;
|
||||
#endif
|
||||
}
|
||||
static inline void getCpuidEx(unsigned int eaxIn, unsigned int ecxIn, unsigned int data[4])
|
||||
{
|
||||
#ifdef _MSC_VER
|
||||
#ifdef XBYAK_INTEL_CPU_SPECIFIC
|
||||
#ifdef _MSC_VER
|
||||
__cpuidex(reinterpret_cast<int*>(data), eaxIn, ecxIn);
|
||||
#else
|
||||
#else
|
||||
__cpuid_count(eaxIn, ecxIn, data[0], data[1], data[2], data[3]);
|
||||
#endif
|
||||
#else
|
||||
(void)eaxIn;
|
||||
(void)ecxIn;
|
||||
(void)data;
|
||||
#endif
|
||||
}
|
||||
static inline uint64 getXfeature()
|
||||
static inline uint64_t getXfeature()
|
||||
{
|
||||
#ifdef _MSC_VER
|
||||
return __xgetbv(0);
|
||||
#else
|
||||
#ifdef XBYAK_INTEL_CPU_SPECIFIC
|
||||
#ifdef _MSC_VER
|
||||
return _xgetbv(0);
|
||||
#else
|
||||
unsigned int eax, edx;
|
||||
// xgetvb is not support on gcc 4.2
|
||||
// __asm__ volatile("xgetbv" : "=a"(eax), "=d"(edx) : "c"(0));
|
||||
__asm__ volatile(".byte 0x0f, 0x01, 0xd0" : "=a"(eax), "=d"(edx) : "c"(0));
|
||||
return ((uint64)edx << 32) | eax;
|
||||
return ((uint64_t)edx << 32) | eax;
|
||||
#endif
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
#ifdef XBYAK64
|
||||
typedef uint64 Type;
|
||||
#else
|
||||
typedef uint32 Type;
|
||||
#endif
|
||||
typedef uint64_t Type;
|
||||
|
||||
static const Type NONE = 0;
|
||||
static const Type tMMX = 1 << 0;
|
||||
static const Type tMMX2 = 1 << 1;
|
||||
@@ -192,7 +312,6 @@ public:
|
||||
static const Type tSSE42 = 1 << 8;
|
||||
static const Type tPOPCNT = 1 << 9;
|
||||
static const Type tAESNI = 1 << 10;
|
||||
static const Type tSSE5 = 1 << 11;
|
||||
static const Type tOSXSAVE = 1 << 12;
|
||||
static const Type tPCLMULQDQ = 1 << 13;
|
||||
static const Type tAVX = 1 << 14;
|
||||
@@ -200,7 +319,6 @@ public:
|
||||
|
||||
static const Type t3DN = 1 << 16;
|
||||
static const Type tE3DN = 1 << 17;
|
||||
static const Type tSSE4a = 1 << 18;
|
||||
static const Type tRDTSCP = 1 << 19;
|
||||
static const Type tAVX2 = 1 << 20;
|
||||
static const Type tBMI1 = 1 << 21; // andn, bextr, blsi, blsmsk, blsr, tzcnt
|
||||
@@ -215,111 +333,184 @@ public:
|
||||
static const Type tADX = 1 << 28; // adcx, adox
|
||||
static const Type tRDSEED = 1 << 29; // rdseed
|
||||
static const Type tSMAP = 1 << 30; // stac
|
||||
#ifdef XBYAK64
|
||||
static const Type tHLE = uint64(1) << 31; // xacquire, xrelease, xtest
|
||||
static const Type tRTM = uint64(1) << 32; // xbegin, xend, xabort
|
||||
static const Type tF16C = uint64(1) << 33; // vcvtph2ps, vcvtps2ph
|
||||
static const Type tMOVBE = uint64(1) << 34; // mobve
|
||||
static const Type tAVX512F = uint64(1) << 35;
|
||||
static const Type tAVX512DQ = uint64(1) << 36;
|
||||
static const Type tAVX512IFMA = uint64(1) << 37;
|
||||
static const Type tAVX512PF = uint64(1) << 38;
|
||||
static const Type tAVX512ER = uint64(1) << 39;
|
||||
static const Type tAVX512CD = uint64(1) << 40;
|
||||
static const Type tAVX512BW = uint64(1) << 41;
|
||||
static const Type tAVX512VL = uint64(1) << 42;
|
||||
static const Type tAVX512VBMI = uint64(1) << 43;
|
||||
#endif
|
||||
static const Type tHLE = uint64_t(1) << 31; // xacquire, xrelease, xtest
|
||||
static const Type tRTM = uint64_t(1) << 32; // xbegin, xend, xabort
|
||||
static const Type tF16C = uint64_t(1) << 33; // vcvtph2ps, vcvtps2ph
|
||||
static const Type tMOVBE = uint64_t(1) << 34; // mobve
|
||||
static const Type tAVX512F = uint64_t(1) << 35;
|
||||
static const Type tAVX512DQ = uint64_t(1) << 36;
|
||||
static const Type tAVX512_IFMA = uint64_t(1) << 37;
|
||||
static const Type tAVX512IFMA = tAVX512_IFMA;
|
||||
static const Type tAVX512PF = uint64_t(1) << 38;
|
||||
static const Type tAVX512ER = uint64_t(1) << 39;
|
||||
static const Type tAVX512CD = uint64_t(1) << 40;
|
||||
static const Type tAVX512BW = uint64_t(1) << 41;
|
||||
static const Type tAVX512VL = uint64_t(1) << 42;
|
||||
static const Type tAVX512_VBMI = uint64_t(1) << 43;
|
||||
static const Type tAVX512VBMI = tAVX512_VBMI; // changed by Intel's manual
|
||||
static const Type tAVX512_4VNNIW = uint64_t(1) << 44;
|
||||
static const Type tAVX512_4FMAPS = uint64_t(1) << 45;
|
||||
static const Type tPREFETCHWT1 = uint64_t(1) << 46;
|
||||
static const Type tPREFETCHW = uint64_t(1) << 47;
|
||||
static const Type tSHA = uint64_t(1) << 48;
|
||||
static const Type tMPX = uint64_t(1) << 49;
|
||||
static const Type tAVX512_VBMI2 = uint64_t(1) << 50;
|
||||
static const Type tGFNI = uint64_t(1) << 51;
|
||||
static const Type tVAES = uint64_t(1) << 52;
|
||||
static const Type tVPCLMULQDQ = uint64_t(1) << 53;
|
||||
static const Type tAVX512_VNNI = uint64_t(1) << 54;
|
||||
static const Type tAVX512_BITALG = uint64_t(1) << 55;
|
||||
static const Type tAVX512_VPOPCNTDQ = uint64_t(1) << 56;
|
||||
static const Type tAVX512_BF16 = uint64_t(1) << 57;
|
||||
static const Type tAVX512_VP2INTERSECT = uint64_t(1) << 58;
|
||||
static const Type tAMX_TILE = uint64_t(1) << 59;
|
||||
static const Type tAMX_INT8 = uint64_t(1) << 60;
|
||||
static const Type tAMX_BF16 = uint64_t(1) << 61;
|
||||
static const Type tAVX_VNNI = uint64_t(1) << 62;
|
||||
static const Type tAVX512_FP16 = uint64_t(1) << 11;
|
||||
// 18, 63
|
||||
|
||||
Cpu()
|
||||
: type_(NONE)
|
||||
, x2APIC_supported_(false)
|
||||
, numCores_()
|
||||
, dataCacheSize_()
|
||||
, coresSharignDataCache_()
|
||||
, dataCacheLevels_(0)
|
||||
{
|
||||
unsigned int data[4];
|
||||
unsigned int data[4] = {};
|
||||
const unsigned int& EAX = data[0];
|
||||
const unsigned int& EBX = data[1];
|
||||
const unsigned int& ECX = data[2];
|
||||
const unsigned int& EDX = data[3];
|
||||
getCpuid(0, data);
|
||||
const unsigned int maxNum = data[0];
|
||||
const unsigned int maxNum = EAX;
|
||||
static const char intel[] = "ntel";
|
||||
static const char amd[] = "cAMD";
|
||||
if (data[2] == get32bitAsBE(amd)) {
|
||||
if (ECX == get32bitAsBE(amd)) {
|
||||
type_ |= tAMD;
|
||||
getCpuid(0x80000001, data);
|
||||
if (data[3] & (1U << 31)) type_ |= t3DN;
|
||||
if (data[3] & (1U << 15)) type_ |= tCMOV;
|
||||
if (data[3] & (1U << 30)) type_ |= tE3DN;
|
||||
if (data[3] & (1U << 22)) type_ |= tMMX2;
|
||||
if (data[3] & (1U << 27)) type_ |= tRDTSCP;
|
||||
}
|
||||
if (data[2] == get32bitAsBE(intel)) {
|
||||
type_ |= tINTEL;
|
||||
getCpuid(0x80000001, data);
|
||||
if (data[3] & (1U << 27)) type_ |= tRDTSCP;
|
||||
if (data[2] & (1U << 5)) type_ |= tLZCNT;
|
||||
}
|
||||
getCpuid(1, data);
|
||||
if (data[2] & (1U << 0)) type_ |= tSSE3;
|
||||
if (data[2] & (1U << 9)) type_ |= tSSSE3;
|
||||
if (data[2] & (1U << 19)) type_ |= tSSE41;
|
||||
if (data[2] & (1U << 20)) type_ |= tSSE42;
|
||||
#ifdef XBYAK64
|
||||
if (data[2] & (1U << 22)) type_ |= tMOVBE;
|
||||
if (data[2] & (1U << 29)) type_ |= tF16C;
|
||||
#endif
|
||||
if (data[2] & (1U << 23)) type_ |= tPOPCNT;
|
||||
if (data[2] & (1U << 25)) type_ |= tAESNI;
|
||||
if (data[2] & (1U << 1)) type_ |= tPCLMULQDQ;
|
||||
if (data[2] & (1U << 27)) type_ |= tOSXSAVE;
|
||||
if (data[2] & (1U << 30)) type_ |= tRDRAND;
|
||||
if (EDX & (1U << 31)) {
|
||||
type_ |= t3DN;
|
||||
// 3DNow! implies support for PREFETCHW on AMD
|
||||
type_ |= tPREFETCHW;
|
||||
}
|
||||
|
||||
if (data[3] & (1U << 15)) type_ |= tCMOV;
|
||||
if (data[3] & (1U << 23)) type_ |= tMMX;
|
||||
if (data[3] & (1U << 25)) type_ |= tMMX2 | tSSE;
|
||||
if (data[3] & (1U << 26)) type_ |= tSSE2;
|
||||
if (EDX & (1U << 29)) {
|
||||
// Long mode implies support for PREFETCHW on AMD
|
||||
type_ |= tPREFETCHW;
|
||||
}
|
||||
}
|
||||
if (ECX == get32bitAsBE(intel)) {
|
||||
type_ |= tINTEL;
|
||||
}
|
||||
|
||||
// Extended flags information
|
||||
getCpuid(0x80000000, data);
|
||||
if (EAX >= 0x80000001) {
|
||||
getCpuid(0x80000001, data);
|
||||
|
||||
if (EDX & (1U << 31)) type_ |= t3DN;
|
||||
if (EDX & (1U << 30)) type_ |= tE3DN;
|
||||
if (EDX & (1U << 27)) type_ |= tRDTSCP;
|
||||
if (EDX & (1U << 22)) type_ |= tMMX2;
|
||||
if (EDX & (1U << 15)) type_ |= tCMOV;
|
||||
if (ECX & (1U << 5)) type_ |= tLZCNT;
|
||||
if (ECX & (1U << 8)) type_ |= tPREFETCHW;
|
||||
}
|
||||
|
||||
getCpuid(1, data);
|
||||
if (ECX & (1U << 0)) type_ |= tSSE3;
|
||||
if (ECX & (1U << 9)) type_ |= tSSSE3;
|
||||
if (ECX & (1U << 19)) type_ |= tSSE41;
|
||||
if (ECX & (1U << 20)) type_ |= tSSE42;
|
||||
if (ECX & (1U << 22)) type_ |= tMOVBE;
|
||||
if (ECX & (1U << 23)) type_ |= tPOPCNT;
|
||||
if (ECX & (1U << 25)) type_ |= tAESNI;
|
||||
if (ECX & (1U << 1)) type_ |= tPCLMULQDQ;
|
||||
if (ECX & (1U << 27)) type_ |= tOSXSAVE;
|
||||
if (ECX & (1U << 30)) type_ |= tRDRAND;
|
||||
if (ECX & (1U << 29)) type_ |= tF16C;
|
||||
|
||||
if (EDX & (1U << 15)) type_ |= tCMOV;
|
||||
if (EDX & (1U << 23)) type_ |= tMMX;
|
||||
if (EDX & (1U << 25)) type_ |= tMMX2 | tSSE;
|
||||
if (EDX & (1U << 26)) type_ |= tSSE2;
|
||||
|
||||
if (type_ & tOSXSAVE) {
|
||||
// check XFEATURE_ENABLED_MASK[2:1] = '11b'
|
||||
uint64 bv = getXfeature();
|
||||
uint64_t bv = getXfeature();
|
||||
if ((bv & 6) == 6) {
|
||||
if (data[2] & (1U << 28)) type_ |= tAVX;
|
||||
if (data[2] & (1U << 12)) type_ |= tFMA;
|
||||
#ifdef XBYAK64
|
||||
if (((bv >> 5) & 7) == 7) {
|
||||
getCpuid(7, data);
|
||||
if (data[1] & (1U << 16)) type_ |= tAVX512F;
|
||||
if (ECX & (1U << 28)) type_ |= tAVX;
|
||||
if (ECX & (1U << 12)) type_ |= tFMA;
|
||||
// do *not* check AVX-512 state on macOS because it has on-demand AVX-512 support
|
||||
#if !defined(__APPLE__)
|
||||
if (((bv >> 5) & 7) == 7)
|
||||
#endif
|
||||
{
|
||||
getCpuidEx(7, 0, data);
|
||||
if (EBX & (1U << 16)) type_ |= tAVX512F;
|
||||
if (type_ & tAVX512F) {
|
||||
getCpuidEx(7, 0, data);
|
||||
if (data[1] & (1U << 17)) type_ |= tAVX512DQ;
|
||||
if (data[1] & (1U << 21)) type_ |= tAVX512IFMA;
|
||||
if (data[1] & (1U << 26)) type_ |= tAVX512PF;
|
||||
if (data[1] & (1U << 27)) type_ |= tAVX512ER;
|
||||
if (data[1] & (1U << 28)) type_ |= tAVX512CD;
|
||||
if (data[1] & (1U << 30)) type_ |= tAVX512BW;
|
||||
if (data[1] & (1U << 31)) type_ |= tAVX512VL;
|
||||
if (data[2] & (1U << 1)) type_ |= tAVX512VBMI;
|
||||
if (EBX & (1U << 17)) type_ |= tAVX512DQ;
|
||||
if (EBX & (1U << 21)) type_ |= tAVX512_IFMA;
|
||||
if (EBX & (1U << 26)) type_ |= tAVX512PF;
|
||||
if (EBX & (1U << 27)) type_ |= tAVX512ER;
|
||||
if (EBX & (1U << 28)) type_ |= tAVX512CD;
|
||||
if (EBX & (1U << 30)) type_ |= tAVX512BW;
|
||||
if (EBX & (1U << 31)) type_ |= tAVX512VL;
|
||||
if (ECX & (1U << 1)) type_ |= tAVX512_VBMI;
|
||||
if (ECX & (1U << 6)) type_ |= tAVX512_VBMI2;
|
||||
if (ECX & (1U << 8)) type_ |= tGFNI;
|
||||
if (ECX & (1U << 9)) type_ |= tVAES;
|
||||
if (ECX & (1U << 10)) type_ |= tVPCLMULQDQ;
|
||||
if (ECX & (1U << 11)) type_ |= tAVX512_VNNI;
|
||||
if (ECX & (1U << 12)) type_ |= tAVX512_BITALG;
|
||||
if (ECX & (1U << 14)) type_ |= tAVX512_VPOPCNTDQ;
|
||||
if (EDX & (1U << 2)) type_ |= tAVX512_4VNNIW;
|
||||
if (EDX & (1U << 3)) type_ |= tAVX512_4FMAPS;
|
||||
if (EDX & (1U << 8)) type_ |= tAVX512_VP2INTERSECT;
|
||||
if ((type_ & tAVX512BW) && (EDX & (1U << 23))) type_ |= tAVX512_FP16;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
if (maxNum >= 7) {
|
||||
getCpuidEx(7, 0, data);
|
||||
if (type_ & tAVX && data[1] & 0x20) type_ |= tAVX2;
|
||||
if (data[1] & (1U << 3)) type_ |= tBMI1;
|
||||
if (data[1] & (1U << 8)) type_ |= tBMI2;
|
||||
if (data[1] & (1U << 9)) type_ |= tENHANCED_REP;
|
||||
if (data[1] & (1U << 18)) type_ |= tRDSEED;
|
||||
if (data[1] & (1U << 19)) type_ |= tADX;
|
||||
if (data[1] & (1U << 20)) type_ |= tSMAP;
|
||||
#ifdef XBYAK64
|
||||
if (data[1] & (1U << 4)) type_ |= tHLE;
|
||||
if (data[1] & (1U << 11)) type_ |= tRTM;
|
||||
#endif
|
||||
const uint32_t maxNumSubLeaves = EAX;
|
||||
if (type_ & tAVX && (EBX & (1U << 5))) type_ |= tAVX2;
|
||||
if (EBX & (1U << 3)) type_ |= tBMI1;
|
||||
if (EBX & (1U << 8)) type_ |= tBMI2;
|
||||
if (EBX & (1U << 9)) type_ |= tENHANCED_REP;
|
||||
if (EBX & (1U << 18)) type_ |= tRDSEED;
|
||||
if (EBX & (1U << 19)) type_ |= tADX;
|
||||
if (EBX & (1U << 20)) type_ |= tSMAP;
|
||||
if (EBX & (1U << 4)) type_ |= tHLE;
|
||||
if (EBX & (1U << 11)) type_ |= tRTM;
|
||||
if (EBX & (1U << 14)) type_ |= tMPX;
|
||||
if (EBX & (1U << 29)) type_ |= tSHA;
|
||||
if (ECX & (1U << 0)) type_ |= tPREFETCHWT1;
|
||||
if (EDX & (1U << 24)) type_ |= tAMX_TILE;
|
||||
if (EDX & (1U << 25)) type_ |= tAMX_INT8;
|
||||
if (EDX & (1U << 22)) type_ |= tAMX_BF16;
|
||||
if (maxNumSubLeaves >= 1) {
|
||||
getCpuidEx(7, 1, data);
|
||||
if (EAX & (1U << 4)) type_ |= tAVX_VNNI;
|
||||
if (type_ & tAVX512F) {
|
||||
if (EAX & (1U << 5)) type_ |= tAVX512_BF16;
|
||||
}
|
||||
}
|
||||
}
|
||||
setFamily();
|
||||
setNumCores();
|
||||
setCacheHierarchy();
|
||||
}
|
||||
void putFamily()
|
||||
void putFamily() const
|
||||
{
|
||||
#ifndef XBYAK_ONLY_CLASS_CPU
|
||||
printf("family=%d, model=%X, stepping=%d, extFamily=%d, extModel=%X\n",
|
||||
family, model, stepping, extFamily, extModel);
|
||||
printf("display:family=%X, model=%X\n", displayFamily, displayModel);
|
||||
#endif
|
||||
}
|
||||
bool has(Type type) const
|
||||
{
|
||||
@@ -327,16 +518,22 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
#ifndef XBYAK_ONLY_CLASS_CPU
|
||||
class Clock {
|
||||
public:
|
||||
static inline uint64 getRdtsc()
|
||||
static inline uint64_t getRdtsc()
|
||||
{
|
||||
#ifdef _MSC_VER
|
||||
#ifdef XBYAK_INTEL_CPU_SPECIFIC
|
||||
#ifdef _MSC_VER
|
||||
return __rdtsc();
|
||||
#else
|
||||
#else
|
||||
unsigned int eax, edx;
|
||||
__asm__ volatile("rdtsc" : "=a"(eax), "=d"(edx));
|
||||
return ((uint64)edx << 32) | eax;
|
||||
return ((uint64_t)edx << 32) | eax;
|
||||
#endif
|
||||
#else
|
||||
// TODO: Need another impl of Clock or rdtsc-equivalent for non-x86 cpu
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
Clock()
|
||||
@@ -354,10 +551,10 @@ public:
|
||||
count_++;
|
||||
}
|
||||
int getCount() const { return count_; }
|
||||
uint64 getClock() const { return clock_; }
|
||||
uint64_t getClock() const { return clock_; }
|
||||
void clear() { count_ = 0; clock_ = 0; }
|
||||
private:
|
||||
uint64 clock_;
|
||||
uint64_t clock_;
|
||||
int count_;
|
||||
};
|
||||
|
||||
@@ -366,7 +563,7 @@ const int UseRCX = 1 << 6;
|
||||
const int UseRDX = 1 << 7;
|
||||
|
||||
class Pack {
|
||||
static const size_t maxTblNum = 10;
|
||||
static const size_t maxTblNum = 15;
|
||||
const Xbyak::Reg64 *tbl_[maxTblNum];
|
||||
size_t n_;
|
||||
public:
|
||||
@@ -375,9 +572,14 @@ public:
|
||||
Pack(const Pack& rhs)
|
||||
: n_(rhs.n_)
|
||||
{
|
||||
if (n_ > maxTblNum) throw Error(ERR_INTERNAL);
|
||||
for (size_t i = 0; i < n_; i++) tbl_[i] = rhs.tbl_[i];
|
||||
}
|
||||
Pack& operator=(const Pack& rhs)
|
||||
{
|
||||
n_ = rhs.n_;
|
||||
for (size_t i = 0; i < n_; i++) tbl_[i] = rhs.tbl_[i];
|
||||
return *this;
|
||||
}
|
||||
Pack(const Xbyak::Reg64& t0)
|
||||
{ n_ = 1; tbl_[0] = &t0; }
|
||||
Pack(const Xbyak::Reg64& t1, const Xbyak::Reg64& t0)
|
||||
@@ -400,9 +602,9 @@ public:
|
||||
{ n_ = 10; tbl_[0] = &t0; tbl_[1] = &t1; tbl_[2] = &t2; tbl_[3] = &t3; tbl_[4] = &t4; tbl_[5] = &t5; tbl_[6] = &t6; tbl_[7] = &t7; tbl_[8] = &t8; tbl_[9] = &t9; }
|
||||
Pack& append(const Xbyak::Reg64& t)
|
||||
{
|
||||
if (n_ == 10) {
|
||||
if (n_ == maxTblNum) {
|
||||
fprintf(stderr, "ERR Pack::can't append\n");
|
||||
throw Error(ERR_BAD_PARAMETER);
|
||||
XBYAK_THROW_RET(ERR_BAD_PARAMETER, *this)
|
||||
}
|
||||
tbl_[n_++] = &t;
|
||||
return *this;
|
||||
@@ -411,7 +613,7 @@ public:
|
||||
{
|
||||
if (n > maxTblNum) {
|
||||
fprintf(stderr, "ERR Pack::init bad n=%d\n", (int)n);
|
||||
throw Error(ERR_BAD_PARAMETER);
|
||||
XBYAK_THROW(ERR_BAD_PARAMETER)
|
||||
}
|
||||
n_ = n;
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
@@ -421,8 +623,8 @@ public:
|
||||
const Xbyak::Reg64& operator[](size_t n) const
|
||||
{
|
||||
if (n >= n_) {
|
||||
fprintf(stderr, "ERR Pack bad n=%d\n", (int)n);
|
||||
throw Error(ERR_BAD_PARAMETER);
|
||||
fprintf(stderr, "ERR Pack bad n=%d(%d)\n", (int)n, (int)n_);
|
||||
XBYAK_THROW_RET(ERR_BAD_PARAMETER, rax)
|
||||
}
|
||||
return *tbl_[n];
|
||||
}
|
||||
@@ -435,7 +637,7 @@ public:
|
||||
if (num == size_t(-1)) num = n_ - pos;
|
||||
if (pos + num > n_) {
|
||||
fprintf(stderr, "ERR Pack::sub bad pos=%d, num=%d\n", (int)pos, (int)num);
|
||||
throw Error(ERR_BAD_PARAMETER);
|
||||
XBYAK_THROW_RET(ERR_BAD_PARAMETER, Pack())
|
||||
}
|
||||
Pack pack;
|
||||
pack.n_ = num;
|
||||
@@ -463,6 +665,7 @@ class StackFrame {
|
||||
static const int rcxPos = 3;
|
||||
static const int rdxPos = 2;
|
||||
#endif
|
||||
static const int maxRegNum = 14; // maxRegNum = 16 - rsp - rax
|
||||
Xbyak::CodeGenerator *code_;
|
||||
int pNum_;
|
||||
int tNum_;
|
||||
@@ -472,7 +675,7 @@ class StackFrame {
|
||||
int P_;
|
||||
bool makeEpilog_;
|
||||
Xbyak::Reg64 pTbl_[4];
|
||||
Xbyak::Reg64 tTbl_[10];
|
||||
Xbyak::Reg64 tTbl_[maxRegNum];
|
||||
Pack p_;
|
||||
Pack t_;
|
||||
StackFrame(const StackFrame&);
|
||||
@@ -484,7 +687,7 @@ public:
|
||||
make stack frame
|
||||
@param sf [in] this
|
||||
@param pNum [in] num of function parameter(0 <= pNum <= 4)
|
||||
@param tNum [in] num of temporary register(0 <= tNum <= 10, with UseRCX, UseRDX)
|
||||
@param tNum [in] num of temporary register(0 <= tNum, with UseRCX, UseRDX) #{pNum + tNum [+rcx] + [rdx]} <= 14
|
||||
@param stackSizeByte [in] local stack size
|
||||
@param makeEpilog [in] automatically call close() if true
|
||||
|
||||
@@ -509,29 +712,19 @@ public:
|
||||
, t(t_)
|
||||
{
|
||||
using namespace Xbyak;
|
||||
if (pNum < 0 || pNum > 4) throw Error(ERR_BAD_PNUM);
|
||||
if (pNum < 0 || pNum > 4) XBYAK_THROW(ERR_BAD_PNUM)
|
||||
const int allRegNum = pNum + tNum_ + (useRcx_ ? 1 : 0) + (useRdx_ ? 1 : 0);
|
||||
if (allRegNum < pNum || allRegNum > 14) throw Error(ERR_BAD_TNUM);
|
||||
if (tNum_ < 0 || allRegNum > maxRegNum) XBYAK_THROW(ERR_BAD_TNUM)
|
||||
const Reg64& _rsp = code->rsp;
|
||||
const AddressFrame& _ptr = code->ptr;
|
||||
saveNum_ = (std::max)(0, allRegNum - noSaveNum);
|
||||
const int *tbl = getOrderTbl() + noSaveNum;
|
||||
P_ = saveNum_ + (stackSizeByte + 7) / 8;
|
||||
if (P_ > 0 && (P_ & 1) == 0) P_++; // here (rsp % 16) == 8, then increment P_ for 16 byte alignment
|
||||
for (int i = 0; i < saveNum_; i++) {
|
||||
code->push(Reg64(tbl[i]));
|
||||
}
|
||||
P_ = (stackSizeByte + 7) / 8;
|
||||
if (P_ > 0 && (P_ & 1) == (saveNum_ & 1)) P_++; // (rsp % 16) == 8, then increment P_ for 16 byte alignment
|
||||
P_ *= 8;
|
||||
if (P_ > 0) code->sub(_rsp, P_);
|
||||
#ifdef XBYAK64_WIN
|
||||
for (int i = 0; i < (std::min)(saveNum_, 4); i++) {
|
||||
code->mov(_ptr [_rsp + P_ + (i + 1) * 8], Reg64(tbl[i]));
|
||||
}
|
||||
for (int i = 4; i < saveNum_; i++) {
|
||||
code->mov(_ptr [_rsp + P_ - 8 * (saveNum_ - i)], Reg64(tbl[i]));
|
||||
}
|
||||
#else
|
||||
for (int i = 0; i < saveNum_; i++) {
|
||||
code->mov(_ptr [_rsp + P_ - 8 * (saveNum_ - i)], Reg64(tbl[i]));
|
||||
}
|
||||
#endif
|
||||
int pos = 0;
|
||||
for (int i = 0; i < pNum; i++) {
|
||||
pTbl_[i] = Xbyak::Reg64(getRegIdx(pos));
|
||||
@@ -552,36 +745,18 @@ public:
|
||||
{
|
||||
using namespace Xbyak;
|
||||
const Reg64& _rsp = code_->rsp;
|
||||
const AddressFrame& _ptr = code_->ptr;
|
||||
const int *tbl = getOrderTbl() + noSaveNum;
|
||||
#ifdef XBYAK64_WIN
|
||||
for (int i = 0; i < (std::min)(saveNum_, 4); i++) {
|
||||
code_->mov(Reg64(tbl[i]), _ptr [_rsp + P_ + (i + 1) * 8]);
|
||||
}
|
||||
for (int i = 4; i < saveNum_; i++) {
|
||||
code_->mov(Reg64(tbl[i]), _ptr [_rsp + P_ - 8 * (saveNum_ - i)]);
|
||||
}
|
||||
#else
|
||||
for (int i = 0; i < saveNum_; i++) {
|
||||
code_->mov(Reg64(tbl[i]), _ptr [_rsp + P_ - 8 * (saveNum_ - i)]);
|
||||
}
|
||||
#endif
|
||||
if (P_ > 0) code_->add(_rsp, P_);
|
||||
for (int i = 0; i < saveNum_; i++) {
|
||||
code_->pop(Reg64(tbl[saveNum_ - 1 - i]));
|
||||
}
|
||||
|
||||
if (callRet) code_->ret();
|
||||
}
|
||||
~StackFrame()
|
||||
{
|
||||
if (!makeEpilog_) return;
|
||||
try {
|
||||
close();
|
||||
} catch (std::exception& e) {
|
||||
printf("ERR:StackFrame %s\n", e.what());
|
||||
exit(1);
|
||||
} catch (...) {
|
||||
printf("ERR:StackFrame otherwise\n");
|
||||
exit(1);
|
||||
}
|
||||
close();
|
||||
}
|
||||
private:
|
||||
const int *getOrderTbl() const
|
||||
@@ -599,7 +774,7 @@ private:
|
||||
}
|
||||
int getRegIdx(int& pos) const
|
||||
{
|
||||
assert(pos < 14);
|
||||
assert(pos < maxRegNum);
|
||||
using namespace Xbyak;
|
||||
const int *tbl = getOrderTbl();
|
||||
int r = tbl[pos++];
|
||||
@@ -616,5 +791,137 @@ private:
|
||||
};
|
||||
#endif
|
||||
|
||||
class Profiler {
|
||||
int mode_;
|
||||
const char *suffix_;
|
||||
const void *startAddr_;
|
||||
#ifdef XBYAK_USE_PERF
|
||||
FILE *fp_;
|
||||
#endif
|
||||
public:
|
||||
enum {
|
||||
None = 0,
|
||||
Perf = 1,
|
||||
VTune = 2
|
||||
};
|
||||
Profiler()
|
||||
: mode_(None)
|
||||
, suffix_("")
|
||||
, startAddr_(0)
|
||||
#ifdef XBYAK_USE_PERF
|
||||
, fp_(0)
|
||||
#endif
|
||||
{
|
||||
}
|
||||
// append suffix to funcName
|
||||
void setNameSuffix(const char *suffix)
|
||||
{
|
||||
suffix_ = suffix;
|
||||
}
|
||||
void setStartAddr(const void *startAddr)
|
||||
{
|
||||
startAddr_ = startAddr;
|
||||
}
|
||||
void init(int mode)
|
||||
{
|
||||
mode_ = None;
|
||||
switch (mode) {
|
||||
default:
|
||||
case None:
|
||||
return;
|
||||
case Perf:
|
||||
#ifdef XBYAK_USE_PERF
|
||||
close();
|
||||
{
|
||||
const int pid = getpid();
|
||||
char name[128];
|
||||
snprintf(name, sizeof(name), "/tmp/perf-%d.map", pid);
|
||||
fp_ = fopen(name, "a+");
|
||||
if (fp_ == 0) {
|
||||
fprintf(stderr, "can't open %s\n", name);
|
||||
return;
|
||||
}
|
||||
}
|
||||
mode_ = Perf;
|
||||
#endif
|
||||
return;
|
||||
case VTune:
|
||||
#ifdef XBYAK_USE_VTUNE
|
||||
dlopen("dummy", RTLD_LAZY); // force to load dlopen to enable jit profiling
|
||||
if (iJIT_IsProfilingActive() != iJIT_SAMPLING_ON) {
|
||||
fprintf(stderr, "VTune profiling is not active\n");
|
||||
return;
|
||||
}
|
||||
mode_ = VTune;
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
}
|
||||
~Profiler()
|
||||
{
|
||||
close();
|
||||
}
|
||||
void close()
|
||||
{
|
||||
#ifdef XBYAK_USE_PERF
|
||||
if (fp_ == 0) return;
|
||||
fclose(fp_);
|
||||
fp_ = 0;
|
||||
#endif
|
||||
}
|
||||
void set(const char *funcName, const void *startAddr, size_t funcSize) const
|
||||
{
|
||||
if (mode_ == None) return;
|
||||
#if !defined(XBYAK_USE_PERF) && !defined(XBYAK_USE_VTUNE)
|
||||
(void)funcName;
|
||||
(void)startAddr;
|
||||
(void)funcSize;
|
||||
#endif
|
||||
#ifdef XBYAK_USE_PERF
|
||||
if (mode_ == Perf) {
|
||||
if (fp_ == 0) return;
|
||||
fprintf(fp_, "%llx %zx %s%s", (long long)startAddr, funcSize, funcName, suffix_);
|
||||
/*
|
||||
perf does not recognize the function name which is less than 3,
|
||||
so append '_' at the end of the name if necessary
|
||||
*/
|
||||
size_t n = strlen(funcName) + strlen(suffix_);
|
||||
for (size_t i = n; i < 3; i++) {
|
||||
fprintf(fp_, "_");
|
||||
}
|
||||
fprintf(fp_, "\n");
|
||||
fflush(fp_);
|
||||
}
|
||||
#endif
|
||||
#ifdef XBYAK_USE_VTUNE
|
||||
if (mode_ != VTune) return;
|
||||
char className[] = "";
|
||||
char fileName[] = "";
|
||||
iJIT_Method_Load jmethod = {};
|
||||
jmethod.method_id = iJIT_GetNewMethodID();
|
||||
jmethod.class_file_name = className;
|
||||
jmethod.source_file_name = fileName;
|
||||
jmethod.method_load_address = const_cast<void*>(startAddr);
|
||||
jmethod.method_size = funcSize;
|
||||
jmethod.line_number_size = 0;
|
||||
char buf[128];
|
||||
snprintf(buf, sizeof(buf), "%s%s", funcName, suffix_);
|
||||
jmethod.method_name = buf;
|
||||
iJIT_NotifyEvent(iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED, (void*)&jmethod);
|
||||
#endif
|
||||
}
|
||||
/*
|
||||
for continuous set
|
||||
funcSize = endAddr - <previous set endAddr>
|
||||
*/
|
||||
void set(const char *funcName, const void *endAddr)
|
||||
{
|
||||
set(funcName, startAddr_, (size_t)endAddr - (size_t)startAddr_);
|
||||
startAddr_ = endAddr;
|
||||
}
|
||||
};
|
||||
#endif // XBYAK_ONLY_CLASS_CPU
|
||||
|
||||
} } // end of util
|
||||
|
||||
#endif
|
||||
|
||||
@@ -15,7 +15,7 @@ The latest officially released stable version is version 1.6.0.
|
||||
|
||||
Installers and binaries for both Windows and Linux are available from [our website](https://pcsx2.net/download.html).
|
||||
|
||||
Development builds are also available from [our website](https://pcsx2.net/download/development.html).
|
||||
Development builds are also available from [Github](https://github.com/PCSX2/pcsx2/releases).
|
||||
|
||||
## System Requirements
|
||||
|
||||
|
||||
+589
-168
File diff suppressed because it is too large
Load Diff
@@ -121,15 +121,7 @@ endif()
|
||||
# It only cost several MB so disbable it by default
|
||||
option(CMAKE_BUILD_STRIP "Srip binaries to save a couple of MB (developer option)")
|
||||
|
||||
if(NOT DEFINED CMAKE_BUILD_PO)
|
||||
if(CMAKE_BUILD_TYPE STREQUAL "Release")
|
||||
set(CMAKE_BUILD_PO TRUE)
|
||||
message(STATUS "Enable the building of po files by default in ${CMAKE_BUILD_TYPE} build !!!")
|
||||
else()
|
||||
set(CMAKE_BUILD_PO FALSE)
|
||||
message(STATUS "Disable the building of po files by default in ${CMAKE_BUILD_TYPE} build !!!")
|
||||
endif()
|
||||
endif()
|
||||
option(CMAKE_BUILD_PO "Build po files (modifies git-tracked files)" OFF)
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# Select the architecture
|
||||
@@ -220,7 +212,9 @@ option(USE_PGO_OPTIMIZE "Enable PGO optimization (use profile)")
|
||||
|
||||
# Note1: Builtin strcmp/memcmp was proved to be slower on Mesa than stdlib version.
|
||||
# Note2: float operation SSE is impacted by the PCSX2 SSE configuration. In particular, flush to zero denormal.
|
||||
if(NOT MSVC)
|
||||
if(MSVC)
|
||||
add_compile_options("$<$<COMPILE_LANGUAGE:CXX>:/Zc:externConstexpr>")
|
||||
else()
|
||||
add_compile_options(-pipe -fvisibility=hidden -pthread -fno-builtin-strcmp -fno-builtin-memcmp -mfpmath=sse -fno-operator-names)
|
||||
endif()
|
||||
|
||||
@@ -328,9 +322,9 @@ endif()
|
||||
# MacOS-specific things
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
set(CMAKE_OSX_DEPLOYMENT_TARGET 10.9)
|
||||
set(CMAKE_OSX_DEPLOYMENT_TARGET 10.13)
|
||||
|
||||
if (APPLE AND ${CMAKE_OSX_DEPLOYMENT_TARGET} VERSION_LESS 10.14 AND NOT ${CMAKE_CXX_COMPILER_VERSION} VERSION_LESS 10)
|
||||
if (APPLE AND ${CMAKE_OSX_DEPLOYMENT_TARGET} VERSION_LESS 10.14 AND NOT ${CMAKE_CXX_COMPILER_VERSION} VERSION_LESS 9)
|
||||
# Older versions of the macOS stdlib don't have operator new(size_t, align_val_t)
|
||||
# Disable use of them with this flag
|
||||
# Not great, but also no worse that what we were getting before we turned on C++17
|
||||
|
||||
@@ -163,7 +163,9 @@ else()
|
||||
find_package(X11 REQUIRED)
|
||||
make_imported_target_if_missing(X11::X11 X11)
|
||||
endif()
|
||||
if(UNIX)
|
||||
if(APPLE)
|
||||
check_lib(GIO gio-2.0 gio/gio.h)
|
||||
elseif(UNIX)
|
||||
# Most plugins (if not all) and PCSX2 core need gtk2, so set the required flags
|
||||
if (GTK2_API)
|
||||
find_package(GTK2 REQUIRED gtk)
|
||||
|
||||
+2
-2
@@ -155,8 +155,8 @@ extern pxDoAssertFnType* pxDoAssert;
|
||||
#define pxAssertMsg(cond, msg) (likely(cond))
|
||||
#define pxAssertDev(cond, msg) (likely(cond))
|
||||
|
||||
#define pxAssumeMsg(cond, msg) (__assume(cond))
|
||||
#define pxAssumeDev(cond, msg) (__assume(cond))
|
||||
#define pxAssumeMsg(cond, msg) __assume(cond)
|
||||
#define pxAssumeDev(cond, msg) __assume(cond)
|
||||
|
||||
#define pxFail(msg) \
|
||||
do \
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2021 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
// An implementation of bit_cast until we get c++20
|
||||
|
||||
template<class T2, class T1>
|
||||
T2 bit_cast(const T1& src)
|
||||
{
|
||||
static_assert(sizeof(T2) == sizeof(T1), "bit_cast: types must be equal size");
|
||||
static_assert(std::is_pod<T1>::value, "bit_cast: source must be POD");
|
||||
static_assert(std::is_pod<T2>::value, "bit_cast: destination must be POD");
|
||||
T2 dst;
|
||||
memcpy(&dst, &src, sizeof(T2));
|
||||
return dst;
|
||||
}
|
||||
@@ -170,6 +170,11 @@ else()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (USE_GCC AND CMAKE_INTERPROCEDURAL_OPTIMIZATION)
|
||||
# GCC LTO doesn't work with asm statements
|
||||
set_source_files_properties(FastJmp.cpp PROPERTIES COMPILE_FLAGS -fno-lto)
|
||||
endif()
|
||||
|
||||
target_link_libraries(common PRIVATE ${LIBC_LIBRARIES} PUBLIC wxWidgets::all glad)
|
||||
target_compile_features(common PUBLIC cxx_std_17)
|
||||
target_include_directories(common PUBLIC ../3rdparty/include ../)
|
||||
|
||||
@@ -470,6 +470,28 @@ bool IConsoleWriter::Warning(const wxString fmt, ...) const
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IConsoleWriter::WriteLn(ConsoleColors color, const std::string& str) const
|
||||
{
|
||||
ConsoleColorScope cs(color);
|
||||
return WriteLn(str);
|
||||
}
|
||||
|
||||
bool IConsoleWriter::WriteLn(const std::string& str) const
|
||||
{
|
||||
DoWriteLn(_addIndentation(fromUTF8(str), conlog_Indent));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IConsoleWriter::Error(const std::string& str) const
|
||||
{
|
||||
return WriteLn(Color_StrongRed, str);
|
||||
}
|
||||
|
||||
bool IConsoleWriter::Warning(const std::string& str) const
|
||||
{
|
||||
return WriteLn(Color_StrongOrange, str);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// ConsoleColorScope / ConsoleIndentScope
|
||||
|
||||
@@ -125,6 +125,11 @@ struct IConsoleWriter
|
||||
bool WriteLn(const wxString fmt, ...) const;
|
||||
bool Error(const wxString fmt, ...) const;
|
||||
bool Warning(const wxString fmt, ...) const;
|
||||
|
||||
bool WriteLn(ConsoleColors color, const std::string& str) const;
|
||||
bool WriteLn(const std::string& str) const;
|
||||
bool Error(const std::string& str) const;
|
||||
bool Warning(const std::string& str) const;
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
|
||||
@@ -82,11 +82,7 @@ static u64 getthreadtime(thread_port_t thread)
|
||||
(u64)info.system_time.microseconds;
|
||||
}
|
||||
|
||||
// Returns the current timestamp (not relative to a real world clock) in
|
||||
// units of 100 nanoseconds. The weird units are to mirror the Windows
|
||||
// counterpart in WinThreads.cpp, which uses the GetThreadTimes() API. On
|
||||
// OSX/Darwin, this is only accurate up until 1ms (and possibly less), so
|
||||
// not very good.
|
||||
// Returns the current timestamp (not relative to a real world clock) in microseconds
|
||||
u64 Threading::GetThreadCpuTime()
|
||||
{
|
||||
// we could also use mach_thread_self() and mach_port_deallocate(), but
|
||||
@@ -95,7 +91,7 @@ u64 Threading::GetThreadCpuTime()
|
||||
// to be user-space instead. In contract,
|
||||
// pthread_mach_thread_np(pthread_self()) is entirely in user-space.
|
||||
u64 us = getthreadtime(pthread_mach_thread_np(pthread_self()));
|
||||
return us * 10ULL;
|
||||
return us;
|
||||
}
|
||||
|
||||
u64 Threading::pxThread::GetCpuTime() const
|
||||
@@ -109,7 +105,7 @@ u64 Threading::pxThread::GetCpuTime() const
|
||||
return 0;
|
||||
}
|
||||
|
||||
return getthreadtime((thread_port_t)m_native_id) * 10ULL;
|
||||
return getthreadtime((thread_port_t)m_native_id);
|
||||
}
|
||||
|
||||
void Threading::pxThread::_platform_specific_OnStartInThread()
|
||||
|
||||
@@ -270,6 +270,7 @@ extern const wxChar* __fastcall pxExpandMsg(const wxChar* message);
|
||||
extern const wxChar* __fastcall pxGetTranslation(const wxChar* message);
|
||||
extern bool pxIsEnglish(int id);
|
||||
|
||||
extern wxString fromUTF8(const std::string& str);
|
||||
extern wxString fromUTF8(const char* src);
|
||||
extern wxString fromAscii(const char* src);
|
||||
|
||||
|
||||
@@ -274,7 +274,7 @@ void IniLoader::Entry(const wxString& var, std::string& value, const std::string
|
||||
if (m_Config)
|
||||
{
|
||||
wxString temp;
|
||||
m_Config->Read(var, &temp, wxString(default_value));
|
||||
m_Config->Read(var, &temp, fromUTF8(default_value));
|
||||
value = temp.ToStdString();
|
||||
}
|
||||
else if (&value != &default_value)
|
||||
@@ -443,5 +443,5 @@ void IniSaver::Entry(const wxString& var, std::string& value, const std::string&
|
||||
{
|
||||
if (!m_Config)
|
||||
return;
|
||||
m_Config->Write(var, wxString(value));
|
||||
m_Config->Write(var, fromUTF8(value));
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ __noinline void memset_sse_a(void* dest, const size_t size)
|
||||
|
||||
if (data != 0)
|
||||
{
|
||||
static __aligned16 const u8 loadval[8] = {data, data, data, data, data, data, data, data};
|
||||
alignas(16) static const u8 loadval[8] = {data, data, data, data, data, data, data, data};
|
||||
srcreg = _mm_loadh_pi(_mm_load_ps((float*)loadval), (__m64*)loadval);
|
||||
}
|
||||
else
|
||||
|
||||
+93
-92
@@ -15,28 +15,27 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
// clang-format off
|
||||
|
||||
#ifdef __CYGWIN__
|
||||
#define __linux__
|
||||
#define __linux__
|
||||
#endif
|
||||
|
||||
// make sure __POSIX__ is defined for all systems where we assume POSIX
|
||||
// compliance
|
||||
#if defined(__linux__) || defined(__APPLE__) || defined(__unix__) || defined(__CYGWIN__) || defined(__LINUX__)
|
||||
#if !defined(__POSIX__)
|
||||
#define __POSIX__ 1
|
||||
#endif
|
||||
#ifndef __POSIX__
|
||||
#define __POSIX__ 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "Pcsx2Types.h"
|
||||
|
||||
#include "common/emitter/x86_intrin.h"
|
||||
|
||||
// Renamed ARRAYSIZE to ArraySize -- looks nice and gets rid of Windows.h conflicts (air)
|
||||
// Notes: I'd have used ARRAY_SIZE instead but ran into cross-platform lib conflicts with
|
||||
// that as well. >_<
|
||||
#ifndef ArraySize
|
||||
#define ArraySize(x) (sizeof(x) / sizeof((x)[0]))
|
||||
#endif
|
||||
// The C++ standard doesn't allow `offsetof` to be used on non-constant values (e.g. `offsetof(class, field[i])`)
|
||||
// Use this in those situations
|
||||
#define OFFSETOF(a, b) (reinterpret_cast<size_t>(&(static_cast<a*>(0)->b)))
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// Dev / Debug conditionals - Consts for using if() statements instead of uglier #ifdef.
|
||||
@@ -47,53 +46,37 @@
|
||||
// some tight loops it will likely make debug builds unusably slow.
|
||||
//
|
||||
#ifdef PCSX2_DEVBUILD
|
||||
static const bool IsDevBuild = true;
|
||||
static const bool IsDevBuild = true;
|
||||
#else
|
||||
static const bool IsDevBuild = false;
|
||||
static const bool IsDevBuild = false;
|
||||
#endif
|
||||
|
||||
#ifdef PCSX2_DEBUG
|
||||
static const bool IsDebugBuild = true;
|
||||
static const bool IsDebugBuild = true;
|
||||
#else
|
||||
static const bool IsDebugBuild = false;
|
||||
static const bool IsDebugBuild = false;
|
||||
#endif
|
||||
|
||||
#ifdef PCSX2_DEBUG
|
||||
#define pxDebugCode(code) code
|
||||
#define pxDebugCode(code) code
|
||||
#else
|
||||
#define pxDebugCode(code)
|
||||
#define pxDebugCode(code)
|
||||
#endif
|
||||
|
||||
#ifdef PCSX2_DEVBUILD
|
||||
#define pxDevelCode(code) code
|
||||
#define pxDevelCode(code) code
|
||||
#else
|
||||
#define pxDevelCode(code)
|
||||
#define pxDevelCode(code)
|
||||
#endif
|
||||
|
||||
#if defined(PCSX2_DEBUG) || defined(PCSX2_DEVBUILD)
|
||||
#define pxReleaseCode(code)
|
||||
#define pxNonReleaseCode(code) code
|
||||
#define pxReleaseCode(code)
|
||||
#define pxNonReleaseCode(code) code
|
||||
#else
|
||||
#define pxReleaseCode(code) code
|
||||
#define pxNonReleaseCode(code)
|
||||
#define pxReleaseCode(code) code
|
||||
#define pxNonReleaseCode(code)
|
||||
#endif
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// __aligned / __aligned16 / __pagealigned
|
||||
// --------------------------------------------------------------------------------------
|
||||
// GCC Warning! The GCC linker (LD) typically fails to assure alignment of class members.
|
||||
// If you want alignment to be assured, the variable must either be a member of a struct
|
||||
// or a static global.
|
||||
//
|
||||
// __pagealigned is equivalent to __aligned(0x1000), and is used to align a dynarec code
|
||||
// buffer to a page boundary (allows the use of execution-enabled mprotect).
|
||||
//
|
||||
// General Performance Warning: Any function that specifies alignment on a local (stack)
|
||||
// variable will have to align the stack frame on enter, and restore it on exit (adds
|
||||
// overhead). Furthermore, compilers cannot inline functions that have aligned local
|
||||
// vars. So use local var alignment with much caution.
|
||||
//
|
||||
|
||||
// Defines the memory page size for the target platform at compilation. All supported platforms
|
||||
// (which means Intel only right now) have a 4k granularity.
|
||||
#define PCSX2_PAGESIZE 0x1000
|
||||
@@ -104,27 +87,14 @@ static const int __pagesize = PCSX2_PAGESIZE;
|
||||
// --------------------------------------------------------------------------------------
|
||||
#ifdef _MSC_VER
|
||||
|
||||
// Using these breaks compat with VC2005; so we're not using it yet.
|
||||
//# define __pack_begin __pragma(pack(1))
|
||||
//# define __pack_end __pragma(pack())
|
||||
#define __noinline __declspec(noinline)
|
||||
#define __noreturn __declspec(noreturn)
|
||||
|
||||
// This is the 2005/earlier compatible packing define, which must be used in conjunction
|
||||
// with #ifdef _MSC_VER/#pragma pack() directives (ugly).
|
||||
#define __packed
|
||||
// Don't know if there are Visual C++ equivalents of these.
|
||||
#define likely(x) (!!(x))
|
||||
#define unlikely(x) (!!(x))
|
||||
|
||||
#define __aligned(alig) __declspec(align(alig))
|
||||
#define __aligned16 __declspec(align(16))
|
||||
#define __aligned32 __declspec(align(32))
|
||||
#define __pagealigned __declspec(align(PCSX2_PAGESIZE))
|
||||
|
||||
#define __noinline __declspec(noinline)
|
||||
#define __noreturn __declspec(noreturn)
|
||||
|
||||
// Don't know if there are Visual C++ equivalents of these.
|
||||
#define likely(x) (!!(x))
|
||||
#define unlikely(x) (!!(x))
|
||||
|
||||
#define CALLBACK __stdcall
|
||||
#define CALLBACK __stdcall
|
||||
|
||||
#else
|
||||
|
||||
@@ -132,41 +102,35 @@ static const int __pagesize = PCSX2_PAGESIZE;
|
||||
// GCC / Intel Compilers Section
|
||||
// --------------------------------------------------------------------------------------
|
||||
|
||||
#ifndef __packed
|
||||
#define __packed __attribute__((packed))
|
||||
#endif
|
||||
#ifndef __aligned
|
||||
#define __aligned(alig) __attribute__((aligned(alig)))
|
||||
#endif
|
||||
#define __aligned16 __attribute__((aligned(16)))
|
||||
#define __aligned32 __attribute__((aligned(32)))
|
||||
#define __pagealigned __attribute__((aligned(PCSX2_PAGESIZE)))
|
||||
#define __assume(cond) do { if (!(cond)) __builtin_unreachable(); } while(0)
|
||||
#define CALLBACK __attribute__((stdcall))
|
||||
|
||||
#define __assume(cond) ((void)0) // GCC has no equivalent for __assume
|
||||
#define CALLBACK __attribute__((stdcall))
|
||||
// Inlining note: GCC needs ((unused)) attributes defined on inlined functions to suppress
|
||||
// warnings when a static inlined function isn't used in the scope of a single file (which
|
||||
// happens *by design* like all the friggen time >_<)
|
||||
|
||||
// Inlining note: GCC needs ((unused)) attributes defined on inlined functions to suppress
|
||||
// warnings when a static inlined function isn't used in the scope of a single file (which
|
||||
// happens *by design* like all the friggen time >_<)
|
||||
|
||||
#ifndef __fastcall
|
||||
#define __fastcall __attribute__((fastcall))
|
||||
#endif
|
||||
#define __vectorcall __fastcall
|
||||
#define _inline __inline__ __attribute__((unused))
|
||||
#ifdef NDEBUG
|
||||
#define __forceinline __attribute__((always_inline, unused))
|
||||
#else
|
||||
#define __forceinline __attribute__((unused))
|
||||
#endif
|
||||
#ifndef __noinline
|
||||
#define __noinline __attribute__((noinline))
|
||||
#endif
|
||||
#ifndef __noreturn
|
||||
#define __noreturn __attribute__((noreturn))
|
||||
#endif
|
||||
#define likely(x) __builtin_expect(!!(x), 1)
|
||||
#define unlikely(x) __builtin_expect(!!(x), 0)
|
||||
#ifndef __fastcall
|
||||
#ifndef _M_X86_32
|
||||
#define __fastcall // Attribute not available, and x86_32 is pretty much the only cc that passes literally everything in registers
|
||||
#else
|
||||
#define __fastcall __attribute__((fastcall))
|
||||
#endif
|
||||
#endif
|
||||
#define __vectorcall __fastcall
|
||||
#define _inline __inline__ __attribute__((unused))
|
||||
#ifdef NDEBUG
|
||||
#define __forceinline __attribute__((always_inline, unused))
|
||||
#else
|
||||
#define __forceinline __attribute__((unused))
|
||||
#endif
|
||||
#ifndef __noinline
|
||||
#define __noinline __attribute__((noinline))
|
||||
#endif
|
||||
#ifndef __noreturn
|
||||
#define __noreturn __attribute__((noreturn))
|
||||
#endif
|
||||
#define likely(x) __builtin_expect(!!(x), 1)
|
||||
#define unlikely(x) __builtin_expect(!!(x), 0)
|
||||
#endif
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
@@ -181,11 +145,48 @@ static const int __pagesize = PCSX2_PAGESIZE;
|
||||
// environment.
|
||||
//
|
||||
#ifdef PCSX2_DEVBUILD
|
||||
#define __releaseinline
|
||||
#define __releaseinline
|
||||
#else
|
||||
#define __releaseinline __forceinline
|
||||
#define __releaseinline __forceinline
|
||||
#endif
|
||||
|
||||
#define __ri __releaseinline
|
||||
#define __fi __forceinline
|
||||
#define __fc __fastcall
|
||||
|
||||
// Makes sure that if anyone includes xbyak, it doesn't do anything bad
|
||||
#define XBYAK_ENABLE_OMITTED_OPERAND
|
||||
|
||||
#ifdef __x86_64__
|
||||
#define _M_AMD64
|
||||
#endif
|
||||
|
||||
#ifndef RESTRICT
|
||||
#ifdef __INTEL_COMPILER
|
||||
#define RESTRICT restrict
|
||||
#elif defined(_MSC_VER)
|
||||
#define RESTRICT __restrict
|
||||
#elif defined(__GNUC__)
|
||||
#define RESTRICT __restrict__
|
||||
#else
|
||||
#define RESTRICT
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef __has_attribute
|
||||
#define __has_attribute(x) 0
|
||||
#endif
|
||||
|
||||
#ifndef __has_builtin
|
||||
#define __has_builtin(x) 0
|
||||
#endif
|
||||
|
||||
#ifdef __cpp_constinit
|
||||
#define CONSTINIT constinit
|
||||
#elif __has_attribute(require_constant_initialization)
|
||||
#define CONSTINIT __attribute__((require_constant_initialization))
|
||||
#else
|
||||
#define CONSTINIT
|
||||
#endif
|
||||
|
||||
#define ASSERT assert
|
||||
|
||||
@@ -31,6 +31,11 @@ __fi wxString fromUTF8(const char* src)
|
||||
return wxString(src, wxMBConvUTF8());
|
||||
}
|
||||
|
||||
__fi wxString fromUTF8(const std::string& str)
|
||||
{
|
||||
return wxString(str.data(), wxMBConvUTF8(), str.size());
|
||||
}
|
||||
|
||||
__fi wxString fromAscii(const char* src)
|
||||
{
|
||||
return wxString::FromAscii(src);
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
|
||||
#pragma comment(lib, "User32.lib")
|
||||
|
||||
static __aligned16 LARGE_INTEGER lfreq;
|
||||
alignas(16) static LARGE_INTEGER lfreq;
|
||||
|
||||
void InitCPUTicks()
|
||||
{
|
||||
|
||||
@@ -100,6 +100,7 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="Align.h" />
|
||||
<ClInclude Include="BitCast.h" />
|
||||
<ClInclude Include="EmbeddedImage.h" />
|
||||
<ClInclude Include="boost_spsc_queue.hpp" />
|
||||
<ClInclude Include="FastJmp.h" />
|
||||
|
||||
@@ -291,6 +291,9 @@
|
||||
<ClInclude Include="WindowInfo.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="BitCast.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="GL\Context.h">
|
||||
<Filter>Header Files\GL</Filter>
|
||||
</ClInclude>
|
||||
|
||||
@@ -44,7 +44,7 @@ static __inline__ __attribute__((always_inline)) void cpuid(int CPUInfo[], const
|
||||
|
||||
using namespace x86Emitter;
|
||||
|
||||
__aligned16 x86capabilities x86caps;
|
||||
alignas(16) x86capabilities x86caps;
|
||||
|
||||
x86capabilities::x86capabilities()
|
||||
: isIdentified(false)
|
||||
@@ -87,7 +87,7 @@ void x86capabilities::SIMD_EstablishMXCSRmask()
|
||||
MXCSR_Mask.bitmask = 0xFFFF; // SSE2 features added
|
||||
}
|
||||
|
||||
__aligned16 u8 targetFXSAVE[512];
|
||||
alignas(16) u8 targetFXSAVE[512];
|
||||
|
||||
// Work for recent enough GCC/CLANG/MSVC 2012
|
||||
_fxsave(&targetFXSAVE);
|
||||
|
||||
@@ -209,4 +209,4 @@ union SSE_MXCSR
|
||||
extern SSE_MXCSR MXCSR_Mask;
|
||||
|
||||
|
||||
extern __aligned16 x86capabilities x86caps;
|
||||
alignas(16) extern x86capabilities x86caps;
|
||||
|
||||
@@ -1186,7 +1186,7 @@ const xRegister32
|
||||
xWrite8(0xC8 | to->Id);
|
||||
}
|
||||
|
||||
static __aligned16 u64 xmm_data[iREGCNT_XMM * 2];
|
||||
alignas(16) static u64 xmm_data[iREGCNT_XMM * 2];
|
||||
|
||||
__emitinline void xStoreReg(const xRegisterSSE& src)
|
||||
{
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
<PreprocessorDefinitions>PCSX2_DEBUG;PCSX2_DEVBUILD;_SECURE_SCL_=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
</Project>
|
||||
@@ -14,6 +14,7 @@
|
||||
<PreprocessorDefinitions>PCSX2_DEVEL;PCSX2_DEVBUILD;NDEBUG;_SECURE_SCL_=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
|
||||
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
</Project>
|
||||
@@ -19,6 +19,7 @@
|
||||
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
|
||||
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||
<FunctionLevelLinking>false</FunctionLevelLinking>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
<WholeProgramOptimization>false</WholeProgramOptimization>
|
||||
<StringPooling>true</StringPooling>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<EnableCOMDATFolding>false</EnableCOMDATFolding>
|
||||
|
||||
+81
-17
@@ -29,6 +29,10 @@
|
||||
#include "Elfheader.h"
|
||||
#include "ps2/BiosTools.h"
|
||||
|
||||
#ifndef DISABLE_RECORDING
|
||||
#include "Recording/InputRecording.h"
|
||||
#endif
|
||||
|
||||
// This typically reflects the Sony-assigned serial code for the Disc, if one exists.
|
||||
// (examples: SLUS-2113, etc).
|
||||
// If the disc is homebrew then it probably won't have a valid serial; in which case
|
||||
@@ -377,10 +381,10 @@ s32 cdvdWriteConfig(const u8* config)
|
||||
static MutexRecursive Mutex_NewDiskCB;
|
||||
|
||||
// Sets ElfCRC to the CRC of the game bound to the CDVD source.
|
||||
static __fi ElfObject* loadElf(const wxString filename)
|
||||
static __fi ElfObject* loadElf(const wxString filename, bool isPSXElf)
|
||||
{
|
||||
if (filename.StartsWith(L"host"))
|
||||
return new ElfObject(filename.After(':'), Path::GetFileSize(filename.After(':')));
|
||||
return new ElfObject(filename.After(':'), Path::GetFileSize(filename.After(':')), isPSXElf);
|
||||
|
||||
// Mimic PS2 behavior!
|
||||
// Much trial-and-error with changing the ISOFS and BOOT2 contents of an image have shown that
|
||||
@@ -404,7 +408,7 @@ static __fi ElfObject* loadElf(const wxString filename)
|
||||
|
||||
IsoFSCDVD isofs;
|
||||
IsoFile file(isofs, fixedname);
|
||||
return new ElfObject(fixedname, file);
|
||||
return new ElfObject(fixedname, file, isPSXElf);
|
||||
}
|
||||
|
||||
static __fi void _reloadElfInfo(wxString elfpath)
|
||||
@@ -423,8 +427,8 @@ static __fi void _reloadElfInfo(wxString elfpath)
|
||||
fname = elfpath.AfterLast(':');
|
||||
if (fname.Matches(L"????_???.??*"))
|
||||
DiscSerial = fname(0, 4) + L"-" + fname(5, 3) + fname(9, 2);
|
||||
std::unique_ptr<ElfObject> elfptr(loadElf(elfpath, false));
|
||||
|
||||
std::unique_ptr<ElfObject> elfptr(loadElf(elfpath));
|
||||
|
||||
elfptr->loadHeaders();
|
||||
ElfCRC = elfptr->getCRC();
|
||||
@@ -439,6 +443,36 @@ static __fi void _reloadElfInfo(wxString elfpath)
|
||||
// binary).
|
||||
}
|
||||
|
||||
|
||||
static __fi void _reloadPSXElfInfo(wxString elfpath)
|
||||
{
|
||||
// Now's a good time to reload the ELF info...
|
||||
ScopedLock locker(Mutex_NewDiskCB);
|
||||
|
||||
if (elfpath == LastELF)
|
||||
return;
|
||||
LastELF = elfpath;
|
||||
wxString fname = elfpath.AfterLast('\\');
|
||||
if (!fname)
|
||||
fname = elfpath.AfterLast('/');
|
||||
if (!fname)
|
||||
fname = elfpath.AfterLast(':');
|
||||
if (fname.Matches(L"????_???.??*"))
|
||||
DiscSerial = fname(0, 4) + L"-" + fname(5, 3) + fname(9, 2);
|
||||
|
||||
std::unique_ptr<ElfObject> elfptr(loadElf(elfpath, true));
|
||||
|
||||
ElfCRC = elfptr->getCRC();
|
||||
ElfTextRange = elfptr->getTextRange();
|
||||
Console.WriteLn(Color_StrongBlue, L"PSX ELF (%s) Game CRC = 0x%08X", WX_STR(elfpath), ElfCRC);
|
||||
|
||||
// Note: Do not load game database info here. This code is generic and called from
|
||||
// BIOS key encryption as well as eeloadReplaceOSDSYS. The first is actually still executing
|
||||
// BIOS code, and patches and cheats should not be applied yet. (they are applied when
|
||||
// eeGameStarting is invoked, which is when the VM starts executing the actual game ELF
|
||||
// binary).
|
||||
}
|
||||
|
||||
void cdvdReloadElfInfo(wxString elfoverride)
|
||||
{
|
||||
// called from context of executing VM code (recompilers), so we need to trap exceptions
|
||||
@@ -461,10 +495,11 @@ void cdvdReloadElfInfo(wxString elfoverride)
|
||||
// PCSX2 currently only recognizes *.elf executables in proper PS2 format.
|
||||
// To support different PSX titles in the console title and for savestates, this code bypasses all the detection,
|
||||
// simply using the exe name, stripped of problematic characters.
|
||||
wxString fname = elfpath.AfterLast('\\').AfterLast(':'); // Also catch elf paths which lack a backslash, and only have a colon.
|
||||
wxString fname2 = fname.BeforeFirst(';');
|
||||
DiscSerial = fname2;
|
||||
Console.SetTitle(DiscSerial);
|
||||
wxString fname = elfpath.AfterLast('\\').BeforeFirst('_');
|
||||
wxString fname2 = elfpath.AfterLast('_').BeforeFirst('.');
|
||||
wxString fname3 = elfpath.AfterLast('.').BeforeFirst(';');
|
||||
DiscSerial = fname + "-" + fname2 + fname3;
|
||||
_reloadPSXElfInfo(elfpath);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -780,6 +815,34 @@ void cdvdReset()
|
||||
cdvd.Action = cdvdAction_None;
|
||||
cdvd.ReadTime = cdvdBlockReadTime(MODE_DVDROM);
|
||||
|
||||
// If we are recording, always use the same RTC setting
|
||||
// for games that use the RTC to seed their RNG -- this is very important to be the same everytime!
|
||||
#ifndef DISABLE_RECORDING
|
||||
if (g_InputRecording.IsActive())
|
||||
{
|
||||
Console.WriteLn("Input Recording Active - Using Constant RTC of 04-03-2020 (DD-MM-YYYY)");
|
||||
// Why not just 0 everything? Some games apparently require the date to be valid in terms of when
|
||||
// the PS2 / Game actually came out. (MGS3). So set it to a value well beyond any PS2 game's release date.
|
||||
cdvd.RTC.second = 0;
|
||||
cdvd.RTC.minute = 0;
|
||||
cdvd.RTC.hour = 0;
|
||||
cdvd.RTC.day = 4;
|
||||
cdvd.RTC.month = 3;
|
||||
cdvd.RTC.year = 20;
|
||||
}
|
||||
else
|
||||
{
|
||||
// CDVD internally uses GMT+9. If you think the time's wrong, you're wrong.
|
||||
// Set up your time zone and winter/summer in the BIOS. No PS2 BIOS I know of features automatic DST.
|
||||
wxDateTime curtime(wxDateTime::GetTimeNow());
|
||||
cdvd.RTC.second = (u8)curtime.GetSecond();
|
||||
cdvd.RTC.minute = (u8)curtime.GetMinute();
|
||||
cdvd.RTC.hour = (u8)curtime.GetHour(wxDateTime::GMT9);
|
||||
cdvd.RTC.day = (u8)curtime.GetDay(wxDateTime::GMT9);
|
||||
cdvd.RTC.month = (u8)curtime.GetMonth(wxDateTime::GMT9) + 1; // WX returns Jan as "0"
|
||||
cdvd.RTC.year = (u8)(curtime.GetYear(wxDateTime::GMT9) - 2000);
|
||||
}
|
||||
#else
|
||||
// CDVD internally uses GMT+9. If you think the time's wrong, you're wrong.
|
||||
// Set up your time zone and winter/summer in the BIOS. No PS2 BIOS I know of features automatic DST.
|
||||
wxDateTime curtime(wxDateTime::GetTimeNow());
|
||||
@@ -789,6 +852,7 @@ void cdvdReset()
|
||||
cdvd.RTC.day = (u8)curtime.GetDay(wxDateTime::GMT9);
|
||||
cdvd.RTC.month = (u8)curtime.GetMonth(wxDateTime::GMT9) + 1; // WX returns Jan as "0"
|
||||
cdvd.RTC.year = (u8)(curtime.GetYear(wxDateTime::GMT9) - 2000);
|
||||
#endif
|
||||
|
||||
g_GameStarted = false;
|
||||
g_GameLoading = false;
|
||||
@@ -879,7 +943,7 @@ int cdvdReadSector()
|
||||
CDVD_LOG("SECTOR %d (BCR %x;%x)", cdvd.Sector, HW_DMA3_BCR_H16, HW_DMA3_BCR_L16);
|
||||
|
||||
bcr = (HW_DMA3_BCR_H16 * HW_DMA3_BCR_L16) * 4;
|
||||
if (bcr < cdvd.BlockSize)
|
||||
if (bcr < cdvd.BlockSize || !(HW_DMA3_CHCR & 0x01000000))
|
||||
{
|
||||
CDVD_LOG("READBLOCK: bcr < cdvd.BlockSize; %x < %x", bcr, cdvd.BlockSize);
|
||||
if (HW_DMA3_CHCR & 0x01000000)
|
||||
@@ -1179,7 +1243,7 @@ __fi void cdvdReadInterrupt()
|
||||
cdvd.Status = CDVD_STATUS_PAUSE;
|
||||
|
||||
cdvd.nCommand = 0;
|
||||
//DevCon.Warning("Scheduling interrupt in %d cycles", cdvd.ReadTime - (cdvd.BlockSize / 4));
|
||||
//DevCon.Warning("Scheduling interrupt in %d cycles", cdvd.ReadTime - ((cdvd.BlockSize / 4) * 12));
|
||||
// Timing issues on command end
|
||||
// Star Ocean (1.1 Japan) expects the DMA to end and interrupt at least 128 or more cycles before the CDVD command ends.
|
||||
// However the time required seems to increase slowly, so delaying the end of the command is not the solution.
|
||||
@@ -1190,7 +1254,7 @@ __fi void cdvdReadInterrupt()
|
||||
}
|
||||
else
|
||||
{
|
||||
CDVDREAD_INT((cdvd.BlockSize / 4));
|
||||
CDVDREAD_INT((cdvd.BlockSize / 4) * 12);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1198,9 +1262,9 @@ __fi void cdvdReadInterrupt()
|
||||
cdvd.Reading = 1;
|
||||
cdvd.RErr = DoCDVDreadTrack(cdvd.Sector, cdvd.ReadMode);
|
||||
if (cdvd.nextSectorsBuffered)
|
||||
CDVDREAD_INT((cdvd.BlockSize / 4));
|
||||
CDVDREAD_INT((cdvd.BlockSize / 4) * 12);
|
||||
else
|
||||
CDVDREAD_INT(cdvd.ReadTime + (cdvd.BlockSize / 4));
|
||||
CDVDREAD_INT(cdvd.ReadTime + ((cdvd.BlockSize / 4) * 12));
|
||||
}
|
||||
|
||||
// Returns the number of IOP cycles until the event completes.
|
||||
@@ -1274,16 +1338,16 @@ static uint cdvdStartSeek(uint newsector, CDVD_MODE_TYPE mode)
|
||||
if (psxRegs.interrupt & (1 << IopEvt_CdvdSectorReady))
|
||||
{
|
||||
//DevCon.Warning("coming back from ready sector early reducing %d cycles by %d cycles", seektime, psxRegs.cycle - psxRegs.sCycle[IopEvt_CdvdSectorReady]);
|
||||
seektime = (psxRegs.cycle - psxRegs.sCycle[IopEvt_CdvdSectorReady]) + (cdvd.BlockSize / 4);
|
||||
seektime = (psxRegs.cycle - psxRegs.sCycle[IopEvt_CdvdSectorReady]) + ((cdvd.BlockSize / 4) * 12);
|
||||
}
|
||||
else
|
||||
{
|
||||
CDVDSECTORREADY_INT(cdvd.ReadTime);
|
||||
seektime = cdvd.ReadTime + (cdvd.BlockSize / 4);
|
||||
seektime = cdvd.ReadTime + ((cdvd.BlockSize / 4) * 12);
|
||||
}
|
||||
}
|
||||
else
|
||||
seektime = (cdvd.BlockSize / 4);
|
||||
seektime = (cdvd.BlockSize / 4) * 12;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1299,7 +1363,7 @@ static uint cdvdStartSeek(uint newsector, CDVD_MODE_TYPE mode)
|
||||
//DevCon.Warning("%s rotational latency at sector %d is %d cycles", (cdvd.SpindlCtrl & CDVD_SPINDLE_CAV) ? "CAV" : "CLV", cdvd.SeekToSector, rotationalLatency);
|
||||
seektime += rotationalLatency + cdvd.ReadTime;
|
||||
CDVDSECTORREADY_INT(seektime);
|
||||
seektime += (cdvd.BlockSize / 4);
|
||||
seektime += (cdvd.BlockSize / 4) * 12;
|
||||
}
|
||||
return seektime;
|
||||
}
|
||||
|
||||
@@ -376,7 +376,7 @@ bool DoCDVDopen()
|
||||
return true;
|
||||
}
|
||||
|
||||
wxString somepick(Path::GetFilenameWithoutExt(m_SourceFilename[CurrentSourceType]));
|
||||
wxString somepick(Path::GetFilenameWithoutExt(fromUTF8(m_SourceFilename[CurrentSourceType])));
|
||||
//FWIW Disc serial availability doesn't seem reliable enough, sometimes it's there and sometime it's just null
|
||||
//Shouldn't the serial be available all time? Potentially need to look into Elfreloadinfo() reliability
|
||||
//TODO: Add extra fallback case for CRC.
|
||||
|
||||
@@ -1076,7 +1076,7 @@ void psxDma3(u32 madr, u32 bcr, u32 chcr)
|
||||
case 0x41000200:
|
||||
if (cdvd.WaitingDMA)
|
||||
{
|
||||
PSX_INT(IopEvt_CdvdRead, cdvd.BlockSize / 4); //Data should be already buffered so simulate DMA time
|
||||
PSX_INT(IopEvt_CdvdRead, (cdvd.BlockSize / 4) * 12); //Data should be already buffered so simulate DMA time
|
||||
}
|
||||
//SysPrintf("unhandled cdrom dma3: madr: %x, bcr: %x, chcr %x\n", madr, bcr, chcr);
|
||||
return;
|
||||
|
||||
@@ -48,7 +48,7 @@ bool ChdFileReader::Open2(const wxString& fileName)
|
||||
// TODO: Unicode correctness on Windows
|
||||
while (CHDERR_REQUIRES_PARENT == (error = chd_open(chds[chd_depth].c_str(), CHD_OPEN_READ, NULL, &child)))
|
||||
{
|
||||
if (chd_depth >= static_cast<int>(ArraySize(chds) - 1))
|
||||
if (chd_depth >= static_cast<int>(std::size(chds) - 1))
|
||||
{
|
||||
Console.Error(L"CDVD: chd_open hit recursion limit searching for parents");
|
||||
return false;
|
||||
|
||||
@@ -185,7 +185,7 @@ static wxString iso2indexname(const wxString& isoname)
|
||||
wxDirName appRoot = // TODO: have only one of this in PCSX2. Right now have few...
|
||||
(wxDirName)(wxFileName(wxStandardPaths::Get().GetExecutablePath()).GetPath());
|
||||
//TestTemplate(appRoot, isoname, false);
|
||||
return ApplyTemplate(L"gzip index", appRoot, EmuConfig.GzipIsoIndexTemplate, isoname, false);
|
||||
return ApplyTemplate(L"gzip index", appRoot, fromUTF8(EmuConfig.GzipIsoIndexTemplate), isoname, false);
|
||||
}
|
||||
|
||||
GzippedFileReader::GzippedFileReader(void)
|
||||
|
||||
@@ -134,13 +134,13 @@ void ThreadedFileReader::Loop()
|
||||
|
||||
ThreadedFileReader::Buffer* ThreadedFileReader::GetBlockPtr(const Chunk& block)
|
||||
{
|
||||
for (int i = 0; i < static_cast<int>(ArraySize(m_buffer)); i++)
|
||||
for (int i = 0; i < static_cast<int>(std::size(m_buffer)); i++)
|
||||
{
|
||||
u32 size = m_buffer[i].size.load(std::memory_order_relaxed);
|
||||
u64 offset = m_buffer[i].offset;
|
||||
if (size && offset <= block.offset && offset + size >= block.offset + block.length)
|
||||
{
|
||||
m_nextBuffer = (i + 1) % ArraySize(m_buffer);
|
||||
m_nextBuffer = (i + 1) % std::size(m_buffer);
|
||||
return m_buffer + i;
|
||||
}
|
||||
}
|
||||
@@ -166,7 +166,7 @@ ThreadedFileReader::Buffer* ThreadedFileReader::GetBlockPtr(const Chunk& block)
|
||||
{
|
||||
buf.offset = block.offset;
|
||||
buf.size.store(size, std::memory_order_release);
|
||||
m_nextBuffer = (m_nextBuffer + 1) % ArraySize(m_buffer);
|
||||
m_nextBuffer = (m_nextBuffer + 1) % std::size(m_buffer);
|
||||
return &buf;
|
||||
}
|
||||
return nullptr;
|
||||
@@ -214,9 +214,9 @@ bool ThreadedFileReader::TryCachedRead(void*& buffer, u64& offset, u32& size, co
|
||||
m_amtRead = 0;
|
||||
u64 end = 0;
|
||||
bool allDone = false;
|
||||
for (int i = 0; i < static_cast<int>(ArraySize(m_buffer) * 2); i++)
|
||||
for (int i = 0; i < static_cast<int>(std::size(m_buffer) * 2); i++)
|
||||
{
|
||||
Buffer& buf = m_buffer[i % ArraySize(m_buffer)];
|
||||
Buffer& buf = m_buffer[i % std::size(m_buffer)];
|
||||
u32 bufsize = buf.size.load(std::memory_order_acquire);
|
||||
if (!bufsize)
|
||||
continue;
|
||||
|
||||
+28
-22
@@ -182,7 +182,6 @@ set(pcsx2Sources
|
||||
set(pcsx2Headers
|
||||
AsyncFileReader.h
|
||||
Cache.h
|
||||
cheatscpp.h
|
||||
Common.h
|
||||
Config.h
|
||||
COP0.h
|
||||
@@ -214,6 +213,7 @@ set(pcsx2Headers
|
||||
MemoryTypes.h
|
||||
Patch.h
|
||||
PathDefs.h
|
||||
PCSX2Base.h
|
||||
PrecompiledHeader.h
|
||||
R3000A.h
|
||||
R5900Exceptions.h
|
||||
@@ -301,7 +301,6 @@ set(pcsx2SPU2Sources
|
||||
SPU2/spu2sys.cpp
|
||||
SPU2/Timestretcher.cpp
|
||||
SPU2/Wavedump_wav.cpp
|
||||
SPU2/WavFile.cpp
|
||||
)
|
||||
|
||||
if(TARGET PkgConfig::PORTAUDIO)
|
||||
@@ -493,7 +492,7 @@ if(WIN32)
|
||||
)
|
||||
|
||||
set(pcsx2PADHeaders
|
||||
PAD/Windows/PAD.h
|
||||
PAD/Gamepad.h
|
||||
PAD/Windows/PADConfig.h
|
||||
PAD/Windows/DeviceEnumerator.h
|
||||
PAD/Windows/Diagnostics.h
|
||||
@@ -558,12 +557,12 @@ else(WIN32)
|
||||
PAD/Linux/wx_dialog/GamepadConfiguration.cpp
|
||||
PAD/Linux/wx_dialog/JoystickConfiguration.cpp
|
||||
PAD/Linux/Config.cpp
|
||||
PAD/Linux/linux.cpp
|
||||
${CMAKE_BINARY_DIR}/pcsx2/PAD/Linux/resources_pad.cpp
|
||||
)
|
||||
|
||||
# PAD/Linux headers
|
||||
set(pcsx2PADHeaders
|
||||
PAD/Gamepad.h
|
||||
PAD/Linux/bitwise.h
|
||||
PAD/Linux/Config.h
|
||||
PAD/Linux/Device.h
|
||||
@@ -572,7 +571,6 @@ else(WIN32)
|
||||
PAD/Linux/SDL/joystick.h
|
||||
PAD/Linux/keyboard.h
|
||||
PAD/Linux/KeyStatus.h
|
||||
PAD/Linux/PAD.h
|
||||
PAD/Linux/state_management.h
|
||||
PAD/Linux/wx_dialog/opPanel.h
|
||||
PAD/Linux/wx_dialog/GamepadConfiguration.h
|
||||
@@ -620,6 +618,7 @@ set(pcsx2GSSources
|
||||
GS/GSLzma.cpp
|
||||
GS/GSPerfMon.cpp
|
||||
GS/GSPng.cpp
|
||||
GS/GSRingHeap.cpp
|
||||
GS/GSState.cpp
|
||||
GS/GSTables.cpp
|
||||
GS/GSUtil.cpp
|
||||
@@ -639,21 +638,12 @@ set(pcsx2GSSources
|
||||
GS/Renderers/HW/GSTextureCache.cpp
|
||||
GS/Renderers/SW/GSDrawScanline.cpp
|
||||
GS/Renderers/SW/GSDrawScanlineCodeGenerator.cpp
|
||||
GS/Renderers/SW/GSDrawScanlineCodeGenerator.x64.cpp
|
||||
GS/Renderers/SW/GSDrawScanlineCodeGenerator.x64.avx.cpp
|
||||
GS/Renderers/SW/GSDrawScanlineCodeGenerator.x64.avx2.cpp
|
||||
GS/Renderers/SW/GSDrawScanlineCodeGenerator.x86.cpp
|
||||
GS/Renderers/SW/GSDrawScanlineCodeGenerator.x86.avx.cpp
|
||||
GS/Renderers/SW/GSDrawScanlineCodeGenerator.x86.avx2.cpp
|
||||
GS/Renderers/SW/GSDrawScanlineCodeGenerator.all.cpp
|
||||
GS/Renderers/SW/GSNewCodeGenerator.cpp
|
||||
GS/Renderers/SW/GSRasterizer.cpp
|
||||
GS/Renderers/SW/GSRendererSW.cpp
|
||||
GS/Renderers/SW/GSSetupPrimCodeGenerator.cpp
|
||||
GS/Renderers/SW/GSSetupPrimCodeGenerator.x64.cpp
|
||||
GS/Renderers/SW/GSSetupPrimCodeGenerator.x64.avx.cpp
|
||||
GS/Renderers/SW/GSSetupPrimCodeGenerator.x64.avx2.cpp
|
||||
GS/Renderers/SW/GSSetupPrimCodeGenerator.x86.cpp
|
||||
GS/Renderers/SW/GSSetupPrimCodeGenerator.x86.avx.cpp
|
||||
GS/Renderers/SW/GSSetupPrimCodeGenerator.x86.avx2.cpp
|
||||
GS/Renderers/SW/GSSetupPrimCodeGenerator.all.cpp
|
||||
GS/Renderers/SW/GSTextureCacheSW.cpp
|
||||
GS/Renderers/SW/GSTextureSW.cpp
|
||||
GS/Renderers/OpenGL/GLLoader.cpp
|
||||
@@ -664,6 +654,7 @@ set(pcsx2GSSources
|
||||
GS/Renderers/OpenGL/GSTextureCacheOGL.cpp
|
||||
GS/Renderers/OpenGL/GSTextureOGL.cpp
|
||||
GS/Window/GSSetting.cpp
|
||||
GS/Window/GSwxDialog.cpp
|
||||
)
|
||||
|
||||
# GS headers
|
||||
@@ -678,13 +669,16 @@ set(pcsx2GSHeaders
|
||||
GS/GSDrawingContext.h
|
||||
GS/GSDrawingEnvironment.h
|
||||
GS/GSDump.h
|
||||
GS/GS_types.h
|
||||
GS/GS_codegen.h
|
||||
GS/GSExtra.h
|
||||
GS/GSGL.h
|
||||
GS/GSIntrin.h
|
||||
GS/GSRegs.h
|
||||
GS/GS.h
|
||||
GS/GSLocalMemory.h
|
||||
GS/GSLzma.h
|
||||
GS/GSPerfMon.h
|
||||
GS/GSPng.h
|
||||
GS/GSRingHeap.h
|
||||
GS/GSState.h
|
||||
GS/GSTables.h
|
||||
GS/GSThread_CXX11.h
|
||||
@@ -712,11 +706,14 @@ set(pcsx2GSHeaders
|
||||
GS/Renderers/HW/GSTextureCache.h
|
||||
GS/Renderers/HW/GSVertexHW.h
|
||||
GS/Renderers/SW/GSDrawScanlineCodeGenerator.h
|
||||
GS/Renderers/SW/GSDrawScanlineCodeGenerator.all.h
|
||||
GS/Renderers/SW/GSDrawScanline.h
|
||||
GS/Renderers/SW/GSNewCodeGenerator.h
|
||||
GS/Renderers/SW/GSRasterizer.h
|
||||
GS/Renderers/SW/GSRendererSW.h
|
||||
GS/Renderers/SW/GSScanlineEnvironment.h
|
||||
GS/Renderers/SW/GSSetupPrimCodeGenerator.h
|
||||
GS/Renderers/SW/GSSetupPrimCodeGenerator.all.h
|
||||
GS/Renderers/SW/GSTextureCacheSW.h
|
||||
GS/Renderers/SW/GSTextureSW.h
|
||||
GS/Renderers/SW/GSVertexSW.h
|
||||
@@ -731,7 +728,7 @@ set(pcsx2GSHeaders
|
||||
GS/Window/GSCaptureDlg.h
|
||||
GS/Window/GSDialog.h
|
||||
GS/Window/GSSetting.h
|
||||
GS/Window/GSSettingsDlg.h
|
||||
GS/Window/GSwxDialog.h
|
||||
)
|
||||
|
||||
if(WIN32)
|
||||
@@ -796,6 +793,7 @@ if(WIN32)
|
||||
)
|
||||
|
||||
list(APPEND pcsx2GSSources
|
||||
GS/Renderers/DX11/D3D.cpp
|
||||
GS/Renderers/DX11/GSDevice11.cpp
|
||||
GS/Renderers/DX11/GSRendererDX11.cpp
|
||||
GS/Renderers/DX11/GSTexture11.cpp
|
||||
@@ -803,9 +801,9 @@ if(WIN32)
|
||||
GS/Renderers/DX11/GSTextureFX11.cpp
|
||||
GS/Window/GSCaptureDlg.cpp
|
||||
GS/Window/GSDialog.cpp
|
||||
GS/Window/GSSettingsDlg.cpp
|
||||
)
|
||||
list(APPEND pcsx2GSHeaders
|
||||
GS/Renderers/DX11/D3D.h
|
||||
GS/Renderers/DX11/GSDevice11.h
|
||||
GS/Renderers/DX11/GSRendererDX11.h
|
||||
GS/Renderers/DX11/GSTexture11.h
|
||||
@@ -818,6 +816,7 @@ else(WIN32)
|
||||
SPU2/Linux/ConfigDebug.cpp
|
||||
SPU2/Linux/ConfigSoundTouch.cpp
|
||||
SPU2/Linux/Dialogs.cpp
|
||||
SPU2/WavFile.cpp
|
||||
SPU2/wx/wxConfig.cpp
|
||||
)
|
||||
list(APPEND pcsx2SPU2Headers
|
||||
@@ -894,7 +893,6 @@ else(WIN32)
|
||||
|
||||
list(APPEND pcsx2GSSources
|
||||
GS/GS_res.cpp
|
||||
GS/Window/GSLinuxDialog.cpp
|
||||
)
|
||||
|
||||
list(APPEND pcsx2GSHeaders
|
||||
@@ -969,6 +967,7 @@ set(pcsx2GuiSources
|
||||
gui/Debugger/CtrlDisassemblyView.cpp
|
||||
gui/Debugger/CtrlRegisterList.cpp
|
||||
gui/Debugger/CtrlMemView.cpp
|
||||
gui/Debugger/CtrlMemSearch.cpp
|
||||
gui/Debugger/DebuggerLists.cpp
|
||||
gui/Debugger/DisassemblyDialog.cpp
|
||||
gui/Debugger/DebugEvents.cpp
|
||||
@@ -1028,6 +1027,7 @@ set(pcsx2GuiHeaders
|
||||
gui/Debugger/BreakpointWindow.h
|
||||
gui/Debugger/CtrlDisassemblyView.h
|
||||
gui/Debugger/CtrlMemView.h
|
||||
gui/Debugger/CtrlMemSearch.h
|
||||
gui/Debugger/CtrlRegisterList.h
|
||||
gui/Debugger/DebugEvents.h
|
||||
gui/Debugger/DebuggerLists.h
|
||||
@@ -1468,6 +1468,12 @@ if(WIN32)
|
||||
opengl32.lib
|
||||
comsuppw.lib
|
||||
)
|
||||
elseif(APPLE)
|
||||
target_link_libraries(PCSX2_FLAGS INTERFACE
|
||||
PkgConfig::GIO
|
||||
PCAP::PCAP
|
||||
LibXml2::LibXml2
|
||||
)
|
||||
else()
|
||||
target_link_libraries(PCSX2_FLAGS INTERFACE
|
||||
GTK::gtk
|
||||
|
||||
+27
-19
@@ -120,14 +120,17 @@ public:
|
||||
auto* padding = new wxBoxSizer(wxVERTICAL);
|
||||
auto* top_box = new wxBoxSizer(wxVERTICAL);
|
||||
|
||||
int space = wxSizerFlags().Border().GetBorderInPixels();
|
||||
int two_space = wxSizerFlags().DoubleBorder().GetBorderInPixels();
|
||||
|
||||
// Ethernet section
|
||||
auto* eth_sizer = new wxStaticBoxSizer(wxVERTICAL, this, _("Ethernet"));
|
||||
|
||||
m_eth_enable = new wxCheckBox(this, wxID_ANY, _("Enabled"));
|
||||
eth_sizer->Add(m_eth_enable);
|
||||
eth_sizer->AddSpacer(5);
|
||||
eth_sizer->AddSpacer(space);
|
||||
|
||||
auto* eth_adapter_box = new wxGridBagSizer(5, 5);
|
||||
auto* eth_adapter_box = new wxGridBagSizer(space, space);
|
||||
for (const AdapterEntry& adapter : PCAPAdapter::GetAdapters())
|
||||
addAdapter(adapter);
|
||||
#ifdef _WIN32
|
||||
@@ -166,42 +169,44 @@ public:
|
||||
m_dns1_address .create(6, this, eth_adapter_box, _("DNS1 Address:"));
|
||||
m_dns2_address .create(7, this, eth_adapter_box, _("DNS2 Address:"));
|
||||
|
||||
eth_adapter_box->AddGrowableCol(1);
|
||||
eth_adapter_box->AddGrowableCol(2);
|
||||
eth_sizer->Add(eth_adapter_box, wxSizerFlags().Expand());
|
||||
|
||||
// HDD section
|
||||
auto* hdd_sizer = new wxStaticBoxSizer(wxVERTICAL, this, _("Hard Disk Drive"));
|
||||
|
||||
m_hdd_enable = new wxCheckBox(this, wxID_ANY, _("Enabled"));
|
||||
hdd_sizer->Add(m_hdd_enable);
|
||||
hdd_sizer->AddSpacer(5);
|
||||
|
||||
auto* hdd_grid = new wxFlexGridSizer(2, 0, 5);
|
||||
hdd_grid->AddGrowableCol(1);
|
||||
auto* hdd_file_label = new wxStaticText(this, wxID_ANY, _("HDD File:"));
|
||||
auto* hdd_file_label = new wxStaticText(this, wxID_ANY, _("HDD File"));
|
||||
m_hdd_file = new wxFilePickerCtrl(this, wxID_ANY, wxEmptyString, _("HDD image file"), "HDD|*.raw", wxDefaultPosition, wxDefaultSize, wxFLP_SAVE | wxFLP_USE_TEXTCTRL);
|
||||
hdd_grid->Add(hdd_file_label, wxSizerFlags().Centre().Right());
|
||||
hdd_grid->Add(m_hdd_file, wxSizerFlags().Expand());
|
||||
auto* hdd_size_label = new wxStaticText(this, wxID_ANY, _("HDD Size (GiB):"));
|
||||
auto* hdd_size_label = new wxStaticText(this, wxID_ANY, _("HDD Size (GiB)"));
|
||||
auto* hdd_size_box = new wxBoxSizer(wxHORIZONTAL);
|
||||
m_hdd_size_slider = new wxSlider(this, wxID_ANY, HDD_MIN_GB, HDD_MIN_GB, HDD_MAX_GB, wxDefaultPosition, wxDefaultSize, wxSL_HORIZONTAL | wxSL_MIN_MAX_LABELS | wxSL_AUTOTICKS);
|
||||
m_hdd_size_slider = new wxSlider(this, wxID_ANY, HDD_MIN_GB, HDD_MIN_GB, HDD_MAX_GB, wxDefaultPosition, wxDefaultSize, wxSL_HORIZONTAL | wxSL_AUTOTICKS);
|
||||
m_hdd_size_slider->SetPageSize(10);
|
||||
for (int i = 15; i < HDD_MAX_GB; i += 5)
|
||||
m_hdd_size_slider->SetTick(i);
|
||||
m_hdd_size_slider->SetTickFreq(10);
|
||||
m_hdd_size_spin = new wxSpinCtrl(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, HDD_MIN_GB, HDD_MAX_GB, HDD_MIN_GB);
|
||||
m_hdd_size_spin->SetSizeHints(m_hdd_size_spin->GetSizeFromTextSize(30));
|
||||
hdd_size_box->Add(m_hdd_size_slider, wxSizerFlags(1).Centre());
|
||||
hdd_size_box->AddSpacer(space);
|
||||
hdd_size_box->Add(m_hdd_size_spin, wxSizerFlags(0).Centre());
|
||||
hdd_grid->Add(hdd_size_label, wxSizerFlags().Centre().Right());
|
||||
hdd_grid->Add(hdd_size_box, wxSizerFlags().Expand());
|
||||
|
||||
hdd_sizer->Add(hdd_grid, wxSizerFlags().Expand());
|
||||
hdd_sizer->Add(m_hdd_enable);
|
||||
hdd_sizer->AddSpacer(two_space);
|
||||
hdd_sizer->Add(hdd_file_label, wxSizerFlags().Left());
|
||||
hdd_sizer->AddSpacer(space);
|
||||
hdd_sizer->Add(m_hdd_file, wxSizerFlags().Expand());
|
||||
hdd_sizer->AddSpacer(two_space);
|
||||
hdd_sizer->Add(hdd_size_label, wxSizerFlags().Left());
|
||||
hdd_sizer->AddSpacer(space);
|
||||
hdd_sizer->Add(hdd_size_box, wxSizerFlags().Expand());
|
||||
|
||||
top_box->Add(eth_sizer, wxSizerFlags().Expand());
|
||||
top_box->AddSpacer(space);
|
||||
top_box->Add(hdd_sizer, wxSizerFlags().Expand());
|
||||
top_box->AddSpacer(space);
|
||||
top_box->Add(CreateStdDialogButtonSizer(wxOK | wxCANCEL), wxSizerFlags().Right());
|
||||
|
||||
padding->Add(top_box, wxSizerFlags().Expand().Border(wxALL, 5));
|
||||
padding->Add(top_box, wxSizerFlags().Expand().Border());
|
||||
SetSizerAndFit(padding);
|
||||
SetMaxSize(wxSize(wxDefaultCoord, GetMinSize().y));
|
||||
|
||||
@@ -275,7 +280,7 @@ public:
|
||||
m_dns2_address .save(config.DNS2, config.AutoDNS2);
|
||||
|
||||
config.hddEnable = m_hdd_enable->GetValue();
|
||||
wxStrncpy(config.Hdd, m_hdd_file->GetPath(), ArraySize(config.Hdd) - 1);
|
||||
wxStrncpy(config.Hdd, m_hdd_file->GetPath(), std::size(config.Hdd) - 1);
|
||||
config.HddSize = m_hdd_size_spin->GetValue() * 1024;
|
||||
}
|
||||
|
||||
@@ -321,6 +326,9 @@ public:
|
||||
}
|
||||
m_eth_adapter->Set(options);
|
||||
m_eth_adapter->SetSelection(selection);
|
||||
// Update minimum sizes for the possibly increased dropdown size
|
||||
// Nothing else seems to update the minimum size of the window
|
||||
SetSizerAndFit(GetSizer(), false);
|
||||
}
|
||||
|
||||
void OnCheck(wxCommandEvent&)
|
||||
|
||||
@@ -43,10 +43,10 @@ void SaveDnsHosts()
|
||||
ScopedIniGroup iniEntry(ini, groupName);
|
||||
ConfigHost entry = config.EthHosts[i];
|
||||
|
||||
wxString url(entry.Url);
|
||||
wxString url(fromUTF8(entry.Url));
|
||||
ini.Entry(L"Url", url);
|
||||
//TODO UTF8(?)
|
||||
wxString desc(entry.Desc);
|
||||
wxString desc(fromUTF8(entry.Desc));
|
||||
ini.Entry(L"Desc", desc);
|
||||
|
||||
char addrBuff[INET_ADDRSTRLEN];
|
||||
|
||||
@@ -242,6 +242,11 @@ public:
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Write(const std::string& msg) const
|
||||
{
|
||||
return Write(fromUTF8(msg));
|
||||
}
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
|
||||
@@ -283,7 +283,7 @@ u64 R5900DebugInterface::read64(u32 address)
|
||||
|
||||
u128 R5900DebugInterface::read128(u32 address)
|
||||
{
|
||||
__aligned16 u128 result;
|
||||
alignas(16) u128 result;
|
||||
if (!isValidAddress(address) || address % 16)
|
||||
{
|
||||
result.hi = result.lo = -1;
|
||||
@@ -635,10 +635,7 @@ bool R5900DebugInterface::isValidAddress(u32 addr)
|
||||
case 0xA:
|
||||
case 0xB:
|
||||
// [ 8000_0000 - BFFF_FFFF ] kernel
|
||||
// We only need to access the EE kernel (which is 1 MB large)
|
||||
if (lopart < 0x100000)
|
||||
return true;
|
||||
break;
|
||||
return true;
|
||||
case 0xF:
|
||||
// [ 8000_0000 - BFFF_FFFF ] IOP or kernel stack
|
||||
if (lopart >= 0xfff8000)
|
||||
|
||||
+54
-52
@@ -9,30 +9,32 @@ urlcolor: "cyan"
|
||||
|
||||
## About the PCSX2 Project
|
||||
|
||||
### Question 1: What is the purpose of the PCSX2 project
|
||||
PCSX2 intends to emulate the PlayStation 2 console, allowing PS2 games to be played on a PC. This requires having an original PlayStation 2 console to supply a BIOS dump, and of course the original games to either be played directly off the disc, or be dumped and played as ISO images.
|
||||
### Question 1: What is the purpose of the PCSX2 project?
|
||||
PCSX2 intends to emulate the PlayStation 2 console, allowing PS2 games to be played on a computer. This requires having an original PlayStation 2 console to supply a BIOS dump and the original games, either to be played directly off the disc or to be dumped and played as ISO/CSO images.
|
||||
|
||||
### Question 2: Is PCSX2 open source
|
||||
PCSX2 is open source, licensed under the GNU General Public License, v3. [Source code is kept on GitHub](https://github.com/pcsx2/pcsx2).
|
||||
### Question 2: Is PCSX2 open source?
|
||||
PCSX2 is open source, licensed under the GNU Lesser General Public License v3.0. [Source code is kept on GitHub](https://github.com/pcsx2/pcsx2).
|
||||
|
||||
### Question 3: How can I help the project
|
||||
### Question 3: How can I help the project?
|
||||
There are a number of ways to help the project, whether it be bug reporting, game patching, or even writing code for the emulator itself. Some examples:
|
||||
|
||||
* Want to make changes to emulator code? [Check out the issue tracker](https://github.com/PCSX2/pcsx2/issues), or [fork the PCSX2 repository and work on your own ideas](https://github.com/PCSX2/pcsx2).
|
||||
* Want to patch games? [Check out the cheats and patches forum thread for inspiration](https://forums.pcsx2.net/Thread-Post-your-PCSX2-cheats-patches-here). There are other threads to find as well, [such as those dedicated to 60 FPS patches](https://forums.pcsx2.net/Thread-60-fps-codes) or [widescreen patches](https://forums.pcsx2.net/Thread-PCSX2-Widescreen-Game-Patches).
|
||||
* Want to report bugs you have discovered in your games? [Head over to the Bug Reporting section of the PCSX2 forums](https://forums.pcsx2.net/Forum-Bug-reporting). Also check out our [GitHub issue guidelines](https://github.com/PCSX2/pcsx2/wiki/How-to-create-useful-and-valid-issues) for info on how we handle GitHub issues.
|
||||
* Want to update us on the compatibility of your games? [Take a look at the Public Compatibility List on the PCSX2 forums](https://forums.pcsx2.net/Forum-Public-compatibility-list)
|
||||
* Want to improve the PCSX2 wiki? [Here is how to contribute](https://wiki.pcsx2.net/Help!_How_to_contribute_guide)
|
||||
|
||||
### Question 4: Is PCSX2 ready to run out-of-the-box
|
||||
No, PCSX2 is not ready to run immediately. First, you must dump your PlayStation 2 console's BIOS using the BIOS dumper. The BIOS dumper is [available on the PCSX2 website](https://pcsx2.net/download/releases/tools.html).
|
||||
### Question 4: Is PCSX2 ready to run out-of-the-box?
|
||||
No, first, you must dump your PlayStation 2 console's BIOS using the BIOS dumper. The BIOS dumper is [available on the PCSX2 website](https://pcsx2.net/download/releases/tools.html).
|
||||
|
||||
After dumping your PlayStation 2 console's BIOS, you may launch PCSX2, step through the first time setup wizard, and then begin playing.
|
||||
After dumping your PlayStation 2 console's BIOS and copying it to your computer, launch PCSX2, step through the first time setup wizard, and then you may begin playing.
|
||||
|
||||
<div class="page"/> <!-- Because PDFs are terrible -->
|
||||
|
||||
---
|
||||
## Technical Details of PCSX2
|
||||
|
||||
### Question 5: What are the PC requirements to use PCSX2
|
||||
### Question 5: What are the PC requirements to use PCSX2?
|
||||
|
||||
#### Minimum
|
||||
|
||||
@@ -50,50 +52,50 @@ After dumping your PlayStation 2 console's BIOS, you may launch PCSX2, step thro
|
||||
|
||||
*Note: Recommended GPU is based on 3x Internal, ~1080p resolution requirements. Higher resolutions will require stronger cards; 6x Internal, ~4K resolution will require a [PassMark G3D Mark](https://www.videocardbenchmark.net/high_end_gpus.html) rating around 12000 (GeForce GTX 1070 Ti). Just like CPU requirements, this is also highly game dependent. A quick reference for GPU **intensive games**: [Wiki](https://wiki.pcsx2.net/Category:GPU_intensive_games)*
|
||||
|
||||
### Question 6: How many CPU cores can PCSX2 use
|
||||
### Question 6: How many CPU cores can PCSX2 use?
|
||||
By default, PCSX2 uses two cores for emulation. Enabling the MTVU speedhack allows the PS2's VU1 coprocessor to run on a third core, which is safe for most games.
|
||||
|
||||
Software rendering in GSdx can be set to use as many or as few rendering threads as desired. We recommend using no more than 8, or the number of cores (including hyperthreads) that your CPU has, whichever is the lower number.
|
||||
Software rendering can be set to use as many or as few rendering threads as desired. We recommend using no more than 8, or the number of cores (including hyperthreads) that your CPU has, whichever is the lower number.
|
||||
|
||||
<div class="page"/> <!-- Because PDFs are terrible -->
|
||||
|
||||
### Question 7: Why isn't my CPU not using 100% of it's power
|
||||
### Question 7: Why isn't my CPU not using 100% of its power?
|
||||
The CPU load as reported in software such as Windows' Task Manager is usually a *summation* of CPU usage, across *all* cores. Software can only use the resources of the individual CPU cores it is actually running on, and cannot "borrow" CPU time from other cores.
|
||||
|
||||
### Question 8: Will SLI or Crossfire help with performance
|
||||
### Question 8: Will SLI or Crossfire help with performance?
|
||||
No. PCSX2 does not use or require SLI or Crossfire.
|
||||
|
||||
### Question 9: How do I check if a game is playable
|
||||
### Question 9: How do I check if a game is playable?
|
||||
The PCSX2 website has a [compatibility list](https://pcsx2.net/compatibility-list.html) with every game that has been tested.
|
||||
|
||||
### Question 10: Do PS1 (PSX) games work on PCSX2
|
||||
### Question 10: Do PS1 (PSX) games work on PCSX2?
|
||||
|
||||
#### If you want to enjoy your PS1 games without issues
|
||||
No, they will not work. Please use a proper PS1 emulator, such as Mednafen.
|
||||
#### If you want to enjoy your PS1 games without issues:
|
||||
No, they will not work without issues. Please use a proper PS1 emulator, such as Duckstation or Mednafen.
|
||||
|
||||
#### If you are a tinkerer and like to break things
|
||||
PS1 games may work on PCSX2, but compatibility is very limited. Specific settings are often required to get a game to boot, and there are other universal problems including missing and pitch shifted audio, and severe FMV corruption. A [forum thread for PS1 compatibility](https://forums.pcsx2.net/Thread-PSX-Mode-Unofficial-Compatibility-List) is tracking some fixes and compatibility reports.
|
||||
#### If you are a tinkerer and like to break things:
|
||||
PS1 games may work on PCSX2, but compatibility is very limited. Specific settings are often required to get a game to boot, and there are other universal problems including missing/pitch-shifted audio and severe FMV corruption. A [forum thread for PS1 compatibility](https://forums.pcsx2.net/Thread-PSX-Mode-Unofficial-Compatibility-List) is tracking some fixes and compatibility reports.
|
||||
|
||||
*While we encourage discussion about PS1 games and improving compatibility, bug reports are NOT being accepted for PS1 games. Any reports for PS1 games will be closed immediately as invalid.*
|
||||
|
||||
### Question 11: Why does my game not work like it did in an earlier PCSX2 version
|
||||
One change to the emulator may fix one game, but cause problems for another. If the issue is severe and not fixable with different settings, you can always revert back to the last known PCSX2 version to work, and report the build number that broke the game. [Development builds](https://pcsx2.net/download/development.html) are very helpful for finding the exact change that caused a regression.
|
||||
### Question 11: Why does my game not work like it did in an earlier PCSX2 version?
|
||||
Any change to the emulator may fix one game, but cause problems for another. If the issue is severe and not fixable with different settings, you can always revert back to the last known PCSX2 version to work, and report the build number that broke the game. [Development builds](https://pcsx2.net/download/development.html) are very helpful for finding the exact change that caused a regression.
|
||||
|
||||
### Question 12: Why is PCSX2 slow
|
||||
The PlayStation 2 is a complex console, and this complexity substantially raises the PC requirements to emulate it at full speed, accurately. [This forum thread](https://forums.pcsx2.net/Thread-Why-is-PCSX2-slow) helps explain some of the technical reasons behind it, and our current guidelines for PC requirements are listed above.
|
||||
### Question 12: Why is PCSX2 slow?
|
||||
The PlayStation 2 is a complex console, and this substantially raises the PC requirements to emulate it at full speed accurately. [This forum thread](https://forums.pcsx2.net/Thread-Why-is-PCSX2-slow) helps explain some of the technical reasons behind it, and our current guidelines for PC requirements are listed above.
|
||||
|
||||
### Question 13: Where do I get a PS2 BIOS
|
||||
### Question 13: Where do I get a PS2 BIOS?
|
||||
You have to dump the BIOS files from your PlayStation 2 console. There is a BIOS dumper tool [available on the PCSX2 website](https://pcsx2.net/download/releases/tools.html) to do this. If you need a guide, check the bottom of this FAQ for links to BIOS guides.
|
||||
|
||||
<div class="page"/> <!-- Because PDFs are terrible -->
|
||||
|
||||
### Question 14: Where do I get PS2 games
|
||||
### Question 14: Where do I get PS2 games?
|
||||
You can use games from your personal collection of discs, purchase them from local stores that resell old games, or look online at sites like eBay or Amazon.
|
||||
|
||||
### Question 15: Can I use PS2 discs directly with PCSX2
|
||||
### Question 15: Can I use PS2 discs directly with PCSX2?
|
||||
Yes. However, some games have speed problems, because unlike the PS2 which would constantly keep the disc spinning, PCSX2 will not do the same to your PC's disc drive. It is recommended to instead dump your games to ISO images. ImgBurn is a popular software to do this with, and we recommend [installing ImgBurn by using Ninite](https://ninite.com) to avoid any issues with the ImgBurn installer.
|
||||
|
||||
### Question 16: How do I play a game
|
||||
### Question 16: How do I play a game?
|
||||
If you are using an ISO image:
|
||||
|
||||
1) Click the CDVD menu
|
||||
@@ -104,21 +106,21 @@ If you are using an ISO image:
|
||||
|
||||
If you are using a disc:
|
||||
|
||||
1) Click the CDVD menu
|
||||
2) Check that "Plugin" mode is selected.
|
||||
3) Click "Plugin Menu", then "Plugin Settings". Verify your disc drive shows up in the menu.
|
||||
4) Click the System menu, then Boot CDVD.
|
||||
1) Click the CDVD menu
|
||||
2) Check that "Disc" mode is selected.
|
||||
3) Go to "Drive Selector", then select your drive.
|
||||
4) Click the System menu, then Boot CDVD.
|
||||
|
||||
### Question 17: What is the difference between Full and Fast boot
|
||||
Full boot will launch the PS2 BIOS, which will then launch the game. Some games need this for multi-language settings or times to work.
|
||||
### Question 17: What is Fast Boot?
|
||||
Normally, PCSX2 will launch the PS2 BIOS, which will then launch the game. Some games need this for multi-language settings or times to work.
|
||||
|
||||
Fast boot will directly mount and launch the game without first launching the PS2 BIOS. Though slightly faster, this may cause some multi-language games to boot into the wrong language, or games that use the clock to give inaccurate times.
|
||||
Fast Boot will directly mount and launch the game without first launching the PS2 BIOS. On versions 1.6 and below, this may cause some multi-language games to boot into the wrong language.
|
||||
|
||||
### Question 18: How do I compile the PCSX2 source code
|
||||
### Question 18: How do I compile the PCSX2 source code?
|
||||
* [Windows compile guide](https://wiki.pcsx2.net/PCSX2_Documentation/Compiling_on_Windows)
|
||||
* [Linux compile guide](https://wiki.pcsx2.net/PCSX2_Documentation/Compiling_on_Linux)
|
||||
|
||||
### Question 19: When will the next version be released
|
||||
### Question 19: When will the next version be released?
|
||||
It will be released when it is ready. Please don't waste your time and ours asking when.
|
||||
|
||||
<div class="page"/> <!-- Because PDFs are terrible -->
|
||||
@@ -126,25 +128,25 @@ It will be released when it is ready. Please don't waste your time and ours aski
|
||||
---
|
||||
## PCSX2 Configuration
|
||||
|
||||
### Question 20: How do I configure the emulator
|
||||
Refer to the Configuration_Guide.pdf (located in the same folder as this FAQ) for an initial setup guide and solution manual to some common known issues.
|
||||
### Question 20: How do I configure PCSX2?
|
||||
Refer to the Configuration_Guide.pdf (located in the same folder as this FAQ) for an initial setup guide and resolutions or workarounds to some common known issues.
|
||||
|
||||
### Question 21: Will framelimiter options increase my FPS
|
||||
The framelimiter has a few options that allow you to alter the pacing of your games. This will directly affect the game's speed itself, NOT your framerate. Useful for speeding through sections of games, or slowing down for precision.
|
||||
### Question 21: Will framelimiter options increase my FPS?
|
||||
The framelimiter has a few options that allow you to alter the pacing of your games. This will directly affect the game's speed itself, NOT your framerate, and can be useful for speeding through sections of games, or slowing down for precision.
|
||||
* Turbo (Tab): Bumps the framelimiter to 200%, allowing a game to run up to 2x faster than normal.
|
||||
* Slowmo (Shift + Tab): Drops the framelimiter to 50%, restricting a game to 0.5x its normal speed.
|
||||
* Framelimiter Disabled (F4): Completely disables the framelimiter. The game will run as fast as your PC can push it.
|
||||
|
||||
Some settings are greyed out; these are advanced counters that should only be modified by those who understand the effects they have on a game's playback speed and frame pacing.
|
||||
Some settings are greyed out. These are advanced counters that should only be modified by those who understand the effects they have on a game's playback speed and frame pacing.
|
||||
|
||||
### Question 22: What is the normal speed for a PlayStation 2 game
|
||||
### Question 22: What is the normal speed for a PlayStation 2 game?
|
||||
* NTSC games will play at 59.94 FPS
|
||||
* PAL games will play at 50 FPS
|
||||
* Keep in mind that there is a difference between the internal framerate (iFPS) and what PCSX2 shows as virtual framerate (vFPS).
|
||||
|
||||
These framerates are what the PlayStation 2 console would push to a real TV through its video cable. A game itself, typically, internally generates only half of those frames, and repeats frames to fill the gaps. This is why a "full speed" game may not "feel like 60 FPS". The console's "speed" (meaning AI, sound, physics, *everything*) is tied to the playback framerate, which is what PCSX2 reports as its "FPS".
|
||||
|
||||
### Question 23: What are Gamefixes
|
||||
### Question 23: What are Gamefixes?
|
||||
Gamefixes are specialized fixes built into PCSX2 for specific games. Gamefixes mostly fix core emulation problems that would crash or soft lock a game, rather than graphical or performance issues. By default, the "System > Automatic Gamefixes" option is enabled, meaning any games that need gamefixes will have them automatically applied, regardless of what gamefix settings you have enabled.
|
||||
|
||||
Most games will not need gamefixes, however if your game is having issues, you can try manually enabling them in Emulation Settings.
|
||||
@@ -153,29 +155,29 @@ Gamefixes are not FPS boosters; more often than not, they will degrade performan
|
||||
|
||||
<div class="page"/> <!-- Because PDFs are terrible -->
|
||||
|
||||
### Question 24: Are Speedhacks safe
|
||||
### Question 24: Are Speedhacks safe?
|
||||
As the name says, speedhacks are hacks to make things faster. They will speed up games, but risk causing stability problems or crashing some games. PCSX2 ships with some speedhacks enabled in the default "Safe" preset. This selection of speedhacks has been reviewed thoroughly and determined to be safe for nearly all games.
|
||||
|
||||
*Bug reports of issues caused by speedhacks will NOT be accepted, and will be immediately closed as invalid.*
|
||||
|
||||
### Question 25: What are all these EE/IOP and VU options
|
||||
### Question 25: What are all these EE/IOP and VU options?
|
||||
The PS2 EE, IOP and VU processors are substantially different from a PC CPU and require different rounding and clamping modes to do math accurately. Most games work fine on the default options, but some games might need a different setting. You can check the [PCSX2 Wiki](https://wiki.pcsx2.net/Category:Games) to see if your game needs an alternate setting, or check the [PCSX2 Forums](https://forums.pcsx2.net/) to see if anyone else has posted about it there.
|
||||
|
||||
### Question 26: What are PCSX2 plugins
|
||||
PCSX2 uses a plugin framework for various sections of the emulator. A plugin is a small, incomplete piece of software that, when plugged in to another piece of software, provides some sort of additional function. PCSX2 uses plugins for:
|
||||
### Question 26: What are PCSX2 plugins?
|
||||
Older versions of PCSX2 used a plugin framework for various sections of the emulator. A plugin is a small, incomplete piece of software that, when plugged in to another piece of software, provides some sort of additional function. PCSX2 used to use plugins for:
|
||||
* Video (GSdx)
|
||||
* Controls (Lilypad for Windows, OnePad for Linux)
|
||||
* USB (No plugin included)
|
||||
|
||||
Each plugin will have its own Plugin Settings menu, and can be found under the Config menu.
|
||||
In newer versions, these have been merged into the main emulator, and there is no longer a way to load external plugins.
|
||||
|
||||
### Question 27: Why is my sound garbled up
|
||||
### Question 27: Why is my sound garbled up?
|
||||
PCSX2's default audio playback mode is Timestretch, which will attempt to stretch sounds out when the emulator is unable to play at full speed, to fill the gaps in the sound playback and prevent even harsher stutters. If you are unable to get the game running at full speed or an acceptable speed where timestretching does not ruin the sound, you can try changing from Timestretch to Async, but this may break games.
|
||||
|
||||
### Question 28: Is my controller supported
|
||||
For Windows users running LilyPad, PCSX2 will ship with XInput bindings already created. This will automatically work with an Xbox One controller or any other XInput controller. Bindings can easily be made for DirectInput controllers, such as Xbox 360 controllers. PS3, PS4, or Switch Pro controllers should be set up using a compatibility software, such as Steam's Big Picture mode.
|
||||
### Question 28: Is my controller supported?
|
||||
For Windows users, PCSX2 will ship with XInput bindings already created. This will automatically work with an Xbox One controller or any other XInput controller. Bindings can easily be made for DirectInput and XInput controllers, such as Xbox 360 controllers. PS3, PS4, or Switch Pro controllers should be set up using third party compatibility software, such as Steam's Big Picture mode.
|
||||
|
||||
For Linux users running OnePad, PCSX2 will automatically detect and bind controls to any recognizable controller. If your controller is not automatically detected, you can try using Onepad Legacy to manually bind controls for it.
|
||||
For Linux users, PCSX2 will automatically detect and bind controls to any recognizable controller.
|
||||
|
||||
<div class="page"/> <!-- Because PDFs are terrible -->
|
||||
|
||||
|
||||
+9
-9
@@ -128,7 +128,7 @@ void iDumpRegisters(u32 startpc, u32 temp)
|
||||
__Log("ipu %x %x %x %x; bp: %x %x %x %x", psHu32(0x2000), psHu32(0x2010), psHu32(0x2020), psHu32(0x2030), g_BP.BP, g_BP.bufferhasnew, g_BP.FP, g_BP.IFC);
|
||||
__Log("gif: %x %x %x", psHu32(0x3000), psHu32(0x3010), psHu32(0x3020));
|
||||
|
||||
for(i = 0; i < ArraySize(dmacs); ++i) {
|
||||
for(i = 0; i < std::size(dmacs); ++i) {
|
||||
DMACh* p = (DMACh*)(&eeHw[dmacs[i]]);
|
||||
__Log("dma%d c%x m%x q%x t%x s%x", i, p->chcr._u32, p->madr, p->qwc, p->tadr, p->sadr);
|
||||
}
|
||||
@@ -297,7 +297,7 @@ void iDumpBlock( int startpc, u8 * ptr )
|
||||
|
||||
memzero(used);
|
||||
numused = 0;
|
||||
for(uint i = 0; i < ArraySize(s_pInstCache->regs); ++i) {
|
||||
for(uint i = 0; i < std::size(s_pInstCache->regs); ++i) {
|
||||
if( s_pInstCache->regs[i] & EEINST_USED ) {
|
||||
used[i] = 1;
|
||||
numused++;
|
||||
@@ -306,7 +306,7 @@ void iDumpBlock( int startpc, u8 * ptr )
|
||||
|
||||
memzero(fpuused);
|
||||
fpunumused = 0;
|
||||
for(uint i = 0; i < ArraySize(s_pInstCache->fpuregs); ++i) {
|
||||
for(uint i = 0; i < std::size(s_pInstCache->fpuregs); ++i) {
|
||||
if( s_pInstCache->fpuregs[i] & EEINST_USED ) {
|
||||
fpuused[i] = 1;
|
||||
fpunumused++;
|
||||
@@ -314,11 +314,11 @@ void iDumpBlock( int startpc, u8 * ptr )
|
||||
}
|
||||
|
||||
eff.Printf( " " );
|
||||
for(uint i = 0; i < ArraySize(s_pInstCache->regs); ++i) {
|
||||
for(uint i = 0; i < std::size(s_pInstCache->regs); ++i) {
|
||||
if( used[i] ) eff.Printf( "%2d ", i );
|
||||
}
|
||||
eff.Printf( "\n" );
|
||||
for(uint i = 0; i < ArraySize(s_pInstCache->fpuregs); ++i) {
|
||||
for(uint i = 0; i < std::size(s_pInstCache->fpuregs); ++i) {
|
||||
if( fpuused[i] ) eff.Printf( "%2d ", i );
|
||||
}
|
||||
|
||||
@@ -330,10 +330,10 @@ void iDumpBlock( int startpc, u8 * ptr )
|
||||
int count;
|
||||
EEINST* pcur;
|
||||
|
||||
for(uint i = 0; i < ArraySize(s_pInstCache->regs); ++i) {
|
||||
for(uint i = 0; i < std::size(s_pInstCache->regs); ++i) {
|
||||
if( used[i] ) fprintf(f, "%s ", disRNameGPR[i]);
|
||||
}
|
||||
for(uint i = 0; i < ArraySize(s_pInstCache->fpuregs); ++i) {
|
||||
for(uint i = 0; i < std::size(s_pInstCache->fpuregs); ++i) {
|
||||
if( fpuused[i] ) fprintf(f, "%s ", i<32?"FR":"FA");
|
||||
}
|
||||
fprintf(f, "\n");
|
||||
@@ -343,14 +343,14 @@ void iDumpBlock( int startpc, u8 * ptr )
|
||||
fprintf(f, "%2d: %2.2x ", i+1, pcur->info);
|
||||
|
||||
count = 1;
|
||||
for(uint j = 0; j < ArraySize(s_pInstCache->regs); j++) {
|
||||
for(uint j = 0; j < std::size(s_pInstCache->regs); j++) {
|
||||
if( used[j] ) {
|
||||
fprintf(f, "%2.2x%s", pcur->regs[j], ((count%8)&&count<numused)?"_":" ");
|
||||
++count;
|
||||
}
|
||||
}
|
||||
count = 1;
|
||||
for(uint j = 0; j < ArraySize(s_pInstCache->fpuregs); j++) {
|
||||
for(uint j = 0; j < std::size(s_pInstCache->fpuregs); j++) {
|
||||
if( fpuused[j] ) {
|
||||
fprintf(f, "%2.2x%s", pcur->fpuregs[j], ((count%8)&&count<fpunumused)?"_":" ");
|
||||
++count;
|
||||
|
||||
+11
-7
@@ -25,36 +25,40 @@ u32 ElfCRC;
|
||||
u32 ElfEntry;
|
||||
std::pair<u32,u32> ElfTextRange;
|
||||
wxString LastELF;
|
||||
bool isPSXElf;
|
||||
|
||||
// All of ElfObjects functions.
|
||||
ElfObject::ElfObject(const wxString& srcfile, IsoFile& isofile)
|
||||
ElfObject::ElfObject(const wxString& srcfile, IsoFile& isofile, bool isPSXElf)
|
||||
: data( wxULongLong(isofile.getLength()).GetLo(), L"ELF headers" )
|
||||
, proghead( NULL )
|
||||
, secthead( NULL )
|
||||
, filename( srcfile )
|
||||
, header( *(ELF_HEADER*)data.GetPtr() )
|
||||
{
|
||||
isCdvd = true;
|
||||
checkElfSize(data.GetSizeInBytes());
|
||||
readIso(isofile);
|
||||
initElfHeaders();
|
||||
initElfHeaders(isPSXElf);
|
||||
}
|
||||
|
||||
ElfObject::ElfObject( const wxString& srcfile, uint hdrsize )
|
||||
ElfObject::ElfObject( const wxString& srcfile, uint hdrsize, bool isPSXElf )
|
||||
: data( wxULongLong(hdrsize).GetLo(), L"ELF headers" )
|
||||
, proghead( NULL )
|
||||
, secthead( NULL )
|
||||
, filename( srcfile )
|
||||
, header( *(ELF_HEADER*)data.GetPtr() )
|
||||
{
|
||||
isCdvd = false;
|
||||
checkElfSize(data.GetSizeInBytes());
|
||||
readFile();
|
||||
initElfHeaders();
|
||||
initElfHeaders(isPSXElf);
|
||||
}
|
||||
|
||||
void ElfObject::initElfHeaders()
|
||||
void ElfObject::initElfHeaders(bool isPSXElf)
|
||||
{
|
||||
if (isPSXElf)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
DevCon.WriteLn( L"Initializing Elf: %d bytes", data.GetSizeInBytes());
|
||||
|
||||
if ( header.e_phnum > 0 )
|
||||
|
||||
+4
-10
@@ -19,12 +19,6 @@
|
||||
#include "CDVD/IsoFS/IsoFSCDVD.h"
|
||||
#include "CDVD/IsoFS/IsoFS.h"
|
||||
|
||||
#if 0
|
||||
//2002-09-20 (Florin)
|
||||
extern char args[256]; //to be filled by GUI
|
||||
extern unsigned int args_ptr;
|
||||
#endif
|
||||
|
||||
struct ELF_HEADER {
|
||||
u8 e_ident[16]; //0x7f,"ELF" (ELF file identifier)
|
||||
u16 e_type; //ELF type: 0=NONE, 1=REL, 2=EXEC, 3=SHARED, 4=CORE
|
||||
@@ -131,21 +125,20 @@ class ElfObject
|
||||
ELF_SHR* secthead;
|
||||
wxString filename;
|
||||
|
||||
void initElfHeaders();
|
||||
void initElfHeaders(bool isPSXElf);
|
||||
void readIso(IsoFile& file);
|
||||
void readFile();
|
||||
void checkElfSize(s64 elfsize);
|
||||
|
||||
public:
|
||||
bool isCdvd;
|
||||
ELF_HEADER& header;
|
||||
|
||||
// Destructor!
|
||||
// C++ does all the cleanup automagically for us.
|
||||
virtual ~ElfObject() = default;
|
||||
|
||||
ElfObject(const wxString& srcfile, IsoFile& isofile);
|
||||
ElfObject( const wxString& srcfile, uint hdrsize );
|
||||
ElfObject(const wxString& srcfile, IsoFile& isofile, bool isPSXElf);
|
||||
ElfObject( const wxString& srcfile, uint hdrsize, bool isPSXElf );
|
||||
|
||||
void loadProgramHeaders();
|
||||
void loadSectionHeaders();
|
||||
@@ -168,5 +161,6 @@ extern u32 ElfCRC;
|
||||
extern u32 ElfEntry;
|
||||
extern std::pair<u32,u32> ElfTextRange;
|
||||
extern wxString LastELF;
|
||||
extern bool isPSXElf;
|
||||
|
||||
#endif
|
||||
|
||||
+1
-2
@@ -18,7 +18,6 @@
|
||||
|
||||
#include <list>
|
||||
|
||||
#include "GS.h"
|
||||
#include "Gif_Unit.h"
|
||||
#include "Counters.h"
|
||||
#include "Config.h"
|
||||
@@ -26,7 +25,7 @@
|
||||
using namespace Threading;
|
||||
using namespace R5900;
|
||||
|
||||
__aligned16 u8 g_RealGSMem[Ps2MemSize::GSregs];
|
||||
alignas(16) u8 g_RealGSMem[Ps2MemSize::GSregs];
|
||||
|
||||
void gsSetVideoMode(GS_VideoMode mode)
|
||||
{
|
||||
|
||||
+2
-2
@@ -21,7 +21,7 @@
|
||||
#include "GS/GS.h"
|
||||
|
||||
extern double GetVerticalFrequency();
|
||||
extern __aligned16 u8 g_RealGSMem[Ps2MemSize::GSregs];
|
||||
alignas(16) extern u8 g_RealGSMem[Ps2MemSize::GSregs];
|
||||
|
||||
enum CSR_FifoState
|
||||
{
|
||||
@@ -483,7 +483,7 @@ struct MTGS_BufferedData
|
||||
}
|
||||
};
|
||||
|
||||
extern __aligned(32) MTGS_BufferedData RingBuffer;
|
||||
alignas(32) extern MTGS_BufferedData RingBuffer;
|
||||
|
||||
// FIXME: These belong in common with other memcpy tools. Will move them there later if no one
|
||||
// else beats me to it. --air
|
||||
|
||||
+78
-98
@@ -14,8 +14,10 @@
|
||||
*/
|
||||
|
||||
#include "PrecompiledHeader.h"
|
||||
#include "GS/Window/GSwxDialog.h"
|
||||
#include "GS.h"
|
||||
#include "GSUtil.h"
|
||||
#include "GSExtra.h"
|
||||
#include "Renderers/SW/GSRendererSW.h"
|
||||
#include "Renderers/Null/GSRendererNull.h"
|
||||
#include "Renderers/Null/GSDeviceNull.h"
|
||||
@@ -30,20 +32,11 @@
|
||||
|
||||
#include "Renderers/DX11/GSRendererDX11.h"
|
||||
#include "Renderers/DX11/GSDevice11.h"
|
||||
#include "Window/GSSettingsDlg.h"
|
||||
#include "GS/Renderers/DX11/D3D.h"
|
||||
|
||||
|
||||
static HRESULT s_hr = E_FAIL;
|
||||
|
||||
#else
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include <gtk/gtk.h>
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
#endif
|
||||
|
||||
extern bool RunLinuxDialog();
|
||||
|
||||
#endif
|
||||
|
||||
#include <fstream>
|
||||
@@ -54,7 +47,7 @@ extern bool RunLinuxDialog();
|
||||
#undef None
|
||||
|
||||
static GSRenderer* s_gs = NULL;
|
||||
static uint8* s_basemem = NULL;
|
||||
static u8* s_basemem = NULL;
|
||||
static int s_vsync = 0;
|
||||
static bool s_exclusive = true;
|
||||
static std::string s_renderer_name;
|
||||
@@ -67,7 +60,7 @@ static int s_new_gs_window_width = 0;
|
||||
static int s_new_gs_window_height = 0;
|
||||
#endif
|
||||
|
||||
void GSsetBaseMem(uint8* mem)
|
||||
void GSsetBaseMem(u8* mem)
|
||||
{
|
||||
s_basemem = mem;
|
||||
|
||||
@@ -156,7 +149,12 @@ int _GSopen(const WindowInfo& wi, const char* title, GSRendererType renderer, in
|
||||
renderer = static_cast<GSRendererType>(theApp.GetConfigI("Renderer"));
|
||||
#ifdef _WIN32
|
||||
if (renderer == GSRendererType::Default)
|
||||
renderer = GSUtil::GetBestRenderer();
|
||||
{
|
||||
if (D3D::ShouldPreferD3D())
|
||||
renderer = GSRendererType::DX1011_HW;
|
||||
else
|
||||
renderer = GSRendererType::OGL_HW;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -270,19 +268,19 @@ int _GSopen(const WindowInfo& wi, const char* title, GSRendererType renderer, in
|
||||
return 0;
|
||||
}
|
||||
|
||||
void GSosdLog(const char* utf8, uint32 color)
|
||||
void GSosdLog(const char* utf8, u32 color)
|
||||
{
|
||||
if (s_gs && s_gs->m_dev)
|
||||
s_gs->m_dev->m_osd.Log(utf8);
|
||||
}
|
||||
|
||||
void GSosdMonitor(const char* key, const char* value, uint32 color)
|
||||
void GSosdMonitor(const char* key, const char* value, u32 color)
|
||||
{
|
||||
if (s_gs && s_gs->m_dev)
|
||||
s_gs->m_dev->m_osd.Monitor(key, value);
|
||||
}
|
||||
|
||||
int GSopen2(const WindowInfo& wi, uint32 flags)
|
||||
int GSopen2(const WindowInfo& wi, u32 flags)
|
||||
{
|
||||
static bool stored_toggle_state = false;
|
||||
const bool toggle_state = !!(flags & 4);
|
||||
@@ -306,7 +304,12 @@ int GSopen2(const WindowInfo& wi, uint32 flags)
|
||||
const auto config_renderer = static_cast<GSRendererType>(theApp.GetConfigI("Renderer"));
|
||||
|
||||
if (current_renderer == config_renderer)
|
||||
current_renderer = GSUtil::GetBestRenderer();
|
||||
{
|
||||
if (D3D::ShouldPreferD3D())
|
||||
current_renderer = GSRendererType::DX1011_HW;
|
||||
else
|
||||
current_renderer = GSRendererType::OGL_HW;
|
||||
}
|
||||
else
|
||||
current_renderer = config_renderer;
|
||||
}
|
||||
@@ -342,7 +345,7 @@ void GSreset()
|
||||
}
|
||||
}
|
||||
|
||||
void GSgifSoftReset(uint32 mask)
|
||||
void GSgifSoftReset(u32 mask)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -353,7 +356,7 @@ void GSgifSoftReset(uint32 mask)
|
||||
}
|
||||
}
|
||||
|
||||
void GSwriteCSR(uint32 csr)
|
||||
void GSwriteCSR(u32 csr)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -364,7 +367,7 @@ void GSwriteCSR(uint32 csr)
|
||||
}
|
||||
}
|
||||
|
||||
void GSinitReadFIFO(uint8* mem)
|
||||
void GSinitReadFIFO(u8* mem)
|
||||
{
|
||||
GL_PERF("Init Read FIFO1");
|
||||
try
|
||||
@@ -380,7 +383,7 @@ void GSinitReadFIFO(uint8* mem)
|
||||
}
|
||||
}
|
||||
|
||||
void GSreadFIFO(uint8* mem)
|
||||
void GSreadFIFO(u8* mem)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -395,7 +398,7 @@ void GSreadFIFO(uint8* mem)
|
||||
}
|
||||
}
|
||||
|
||||
void GSinitReadFIFO2(uint8* mem, uint32 size)
|
||||
void GSinitReadFIFO2(u8* mem, u32 size)
|
||||
{
|
||||
GL_PERF("Init Read FIFO2");
|
||||
try
|
||||
@@ -411,7 +414,7 @@ void GSinitReadFIFO2(uint8* mem, uint32 size)
|
||||
}
|
||||
}
|
||||
|
||||
void GSreadFIFO2(uint8* mem, uint32 size)
|
||||
void GSreadFIFO2(u8* mem, u32 size)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -426,7 +429,7 @@ void GSreadFIFO2(uint8* mem, uint32 size)
|
||||
}
|
||||
}
|
||||
|
||||
void GSgifTransfer(const uint8* mem, uint32 size)
|
||||
void GSgifTransfer(const u8* mem, u32 size)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -437,33 +440,33 @@ void GSgifTransfer(const uint8* mem, uint32 size)
|
||||
}
|
||||
}
|
||||
|
||||
void GSgifTransfer1(uint8* mem, uint32 addr)
|
||||
void GSgifTransfer1(u8* mem, u32 addr)
|
||||
{
|
||||
try
|
||||
{
|
||||
s_gs->Transfer<0>(const_cast<uint8*>(mem) + addr, (0x4000 - addr) / 16);
|
||||
s_gs->Transfer<0>(const_cast<u8*>(mem) + addr, (0x4000 - addr) / 16);
|
||||
}
|
||||
catch (GSRecoverableError)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
void GSgifTransfer2(uint8* mem, uint32 size)
|
||||
void GSgifTransfer2(u8* mem, u32 size)
|
||||
{
|
||||
try
|
||||
{
|
||||
s_gs->Transfer<1>(const_cast<uint8*>(mem), size);
|
||||
s_gs->Transfer<1>(const_cast<u8*>(mem), size);
|
||||
}
|
||||
catch (GSRecoverableError)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
void GSgifTransfer3(uint8* mem, uint32 size)
|
||||
void GSgifTransfer3(u8* mem, u32 size)
|
||||
{
|
||||
try
|
||||
{
|
||||
s_gs->Transfer<2>(const_cast<uint8*>(mem), size);
|
||||
s_gs->Transfer<2>(const_cast<u8*>(mem), size);
|
||||
}
|
||||
catch (GSRecoverableError)
|
||||
{
|
||||
@@ -485,7 +488,7 @@ void GSvsync(int field)
|
||||
}
|
||||
}
|
||||
|
||||
uint32 GSmakeSnapshot(char* path)
|
||||
u32 GSmakeSnapshot(char* path)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -562,39 +565,12 @@ void GSconfigure()
|
||||
theApp.SetConfigDir();
|
||||
theApp.Init();
|
||||
|
||||
#ifdef _WIN32
|
||||
GSDialog::InitCommonControls();
|
||||
if (GSSettingsDlg().DoModal() == IDOK)
|
||||
{
|
||||
// Force a reload of the gs state
|
||||
theApp.SetCurrentRendererType(GSRendererType::Undefined);
|
||||
}
|
||||
|
||||
#elif defined(__APPLE__)
|
||||
// Rest of macOS UI doesn't use GTK so we need to init it now
|
||||
gtk_init(nullptr, nullptr);
|
||||
// GTK expects us to be using its event loop, rather than Cocoa's
|
||||
// If we call its stuff right now, it'll attempt to drain a static autorelease pool that was already drained by Cocoa (see https://github.com/GNOME/gtk/blob/8c1072fad1cb6a2e292fce2441b4a571f173ce0f/gdk/quartz/gdkeventloop-quartz.c#L640-L646)
|
||||
// We can convince it that touching that pool would be unsafe by running all GTK calls within a CFRunLoop
|
||||
// (Blocks submitted to the main queue by dispatch_async are run by its CFRunLoop)
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
if (RunLinuxDialog())
|
||||
{
|
||||
theApp.ReloadConfig();
|
||||
// Force a reload of the gs state
|
||||
theApp.SetCurrentRendererType(GSRendererType::Undefined);
|
||||
}
|
||||
});
|
||||
#else
|
||||
|
||||
if (RunLinuxDialog())
|
||||
if (RunwxDialog())
|
||||
{
|
||||
theApp.ReloadConfig();
|
||||
// Force a reload of the gs state
|
||||
theApp.SetCurrentRendererType(GSRendererType::Undefined);
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
catch (GSRecoverableError)
|
||||
{
|
||||
@@ -654,7 +630,7 @@ void GSendRecording()
|
||||
pt(" - Capture ended\n");
|
||||
}
|
||||
|
||||
void GSsetGameCRC(uint32 crc, int options)
|
||||
void GSsetGameCRC(u32 crc, int options)
|
||||
{
|
||||
s_gs->SetGameCRC(crc, options);
|
||||
}
|
||||
@@ -762,7 +738,10 @@ const std::string root_hw("/tmp/GS_HW_dump32/");
|
||||
|
||||
void* vmalloc(size_t size, bool code)
|
||||
{
|
||||
return VirtualAlloc(NULL, size, MEM_COMMIT | MEM_RESERVE, code ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE);
|
||||
void* ptr = VirtualAlloc(NULL, size, MEM_COMMIT | MEM_RESERVE, code ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE);
|
||||
if (!ptr)
|
||||
throw std::bad_alloc();
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void vmfree(void* ptr, size_t size)
|
||||
@@ -771,15 +750,15 @@ void vmfree(void* ptr, size_t size)
|
||||
}
|
||||
|
||||
static HANDLE s_fh = NULL;
|
||||
static uint8* s_Next[8];
|
||||
static u8* s_Next[8];
|
||||
|
||||
void* fifo_alloc(size_t size, size_t repeat)
|
||||
{
|
||||
ASSERT(s_fh == NULL);
|
||||
|
||||
if (repeat >= countof(s_Next))
|
||||
if (repeat >= std::size(s_Next))
|
||||
{
|
||||
fprintf(stderr, "Memory mapping overflow (%zu >= %u)\n", repeat, static_cast<unsigned>(countof(s_Next)));
|
||||
fprintf(stderr, "Memory mapping overflow (%zu >= %u)\n", repeat, static_cast<unsigned>(std::size(s_Next)));
|
||||
return vmalloc(size * repeat, false); // Fallback to default vmalloc
|
||||
}
|
||||
|
||||
@@ -795,8 +774,8 @@ void* fifo_alloc(size_t size, size_t repeat)
|
||||
void* fifo = MapViewOfFile(s_fh, FILE_MAP_ALL_ACCESS, 0, 0, size);
|
||||
for (size_t i = 1; i < repeat; i++)
|
||||
{
|
||||
void* base = (uint8*)fifo + size * i;
|
||||
s_Next[i] = (uint8*)MapViewOfFileEx(s_fh, FILE_MAP_ALL_ACCESS, 0, 0, size, base);
|
||||
void* base = (u8*)fifo + size * i;
|
||||
s_Next[i] = (u8*)MapViewOfFileEx(s_fh, FILE_MAP_ALL_ACCESS, 0, 0, size, base);
|
||||
errorID = ::GetLastError();
|
||||
if (s_Next[i] != base)
|
||||
{
|
||||
@@ -833,7 +812,7 @@ void fifo_free(void* ptr, size_t size, size_t repeat)
|
||||
|
||||
UnmapViewOfFile(ptr);
|
||||
|
||||
for (size_t i = 1; i < countof(s_Next); i++)
|
||||
for (size_t i = 1; i < std::size(s_Next); i++)
|
||||
{
|
||||
if (s_Next[i] != 0)
|
||||
{
|
||||
@@ -869,7 +848,10 @@ void* vmalloc(size_t size, bool code)
|
||||
#endif
|
||||
}
|
||||
|
||||
return mmap(NULL, size, prot, flags, -1, 0);
|
||||
void* ptr = mmap(NULL, size, prot, flags, -1, 0);
|
||||
if (ptr == MAP_FAILED)
|
||||
throw std::bad_alloc();
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void vmfree(void* ptr, size_t size)
|
||||
@@ -906,8 +888,8 @@ void* fifo_alloc(size_t size, size_t repeat)
|
||||
|
||||
for (size_t i = 1; i < repeat; i++)
|
||||
{
|
||||
void* base = (uint8*)fifo + size * i;
|
||||
uint8* next = (uint8*)mmap(base, size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED, s_shm_fd, 0);
|
||||
void* base = (u8*)fifo + size * i;
|
||||
u8* next = (u8*)mmap(base, size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED, s_shm_fd, 0);
|
||||
if (next != base)
|
||||
fprintf(stderr, "Fail to mmap contiguous segment\n");
|
||||
}
|
||||
@@ -1106,16 +1088,16 @@ void GSApp::Init()
|
||||
m_section = "Settings";
|
||||
|
||||
#ifdef _WIN32
|
||||
m_gs_renderers.push_back(GSSetting(static_cast<uint32>(GSRendererType::DX1011_HW), "Direct3D 11", ""));
|
||||
m_gs_renderers.push_back(GSSetting(static_cast<uint32>(GSRendererType::OGL_HW), "OpenGL", ""));
|
||||
m_gs_renderers.push_back(GSSetting(static_cast<uint32>(GSRendererType::OGL_SW), "Software", ""));
|
||||
m_gs_renderers.push_back(GSSetting(static_cast<u32>(GSRendererType::DX1011_HW), "Direct3D 11", ""));
|
||||
m_gs_renderers.push_back(GSSetting(static_cast<u32>(GSRendererType::OGL_HW), "OpenGL", ""));
|
||||
m_gs_renderers.push_back(GSSetting(static_cast<u32>(GSRendererType::OGL_SW), "Software", ""));
|
||||
#else // Linux
|
||||
m_gs_renderers.push_back(GSSetting(static_cast<uint32>(GSRendererType::OGL_HW), "OpenGL", ""));
|
||||
m_gs_renderers.push_back(GSSetting(static_cast<uint32>(GSRendererType::OGL_SW), "Software", ""));
|
||||
m_gs_renderers.push_back(GSSetting(static_cast<u32>(GSRendererType::OGL_HW), "OpenGL", ""));
|
||||
m_gs_renderers.push_back(GSSetting(static_cast<u32>(GSRendererType::OGL_SW), "Software", ""));
|
||||
#endif
|
||||
|
||||
// The null renderer goes third, it has use for benchmarking purposes in a release build
|
||||
m_gs_renderers.push_back(GSSetting(static_cast<uint32>(GSRendererType::Null), "Null", ""));
|
||||
m_gs_renderers.push_back(GSSetting(static_cast<u32>(GSRendererType::Null), "Null", ""));
|
||||
|
||||
m_gs_interlace.push_back(GSSetting(0, "None", ""));
|
||||
m_gs_interlace.push_back(GSSetting(1, "Weave tff", "saw-tooth"));
|
||||
@@ -1145,14 +1127,14 @@ void GSApp::Init()
|
||||
m_gs_dithering.push_back(GSSetting(2, "Unscaled", "Default"));
|
||||
m_gs_dithering.push_back(GSSetting(1, "Scaled", ""));
|
||||
|
||||
m_gs_bifilter.push_back(GSSetting(static_cast<uint32>(BiFiltering::Nearest), "Nearest", ""));
|
||||
m_gs_bifilter.push_back(GSSetting(static_cast<uint32>(BiFiltering::Forced_But_Sprite), "Bilinear", "Forced excluding sprite"));
|
||||
m_gs_bifilter.push_back(GSSetting(static_cast<uint32>(BiFiltering::Forced), "Bilinear", "Forced"));
|
||||
m_gs_bifilter.push_back(GSSetting(static_cast<uint32>(BiFiltering::PS2), "Bilinear", "PS2"));
|
||||
m_gs_bifilter.push_back(GSSetting(static_cast<u32>(BiFiltering::Nearest), "Nearest", ""));
|
||||
m_gs_bifilter.push_back(GSSetting(static_cast<u32>(BiFiltering::Forced_But_Sprite), "Bilinear", "Forced excluding sprite"));
|
||||
m_gs_bifilter.push_back(GSSetting(static_cast<u32>(BiFiltering::Forced), "Bilinear", "Forced"));
|
||||
m_gs_bifilter.push_back(GSSetting(static_cast<u32>(BiFiltering::PS2), "Bilinear", "PS2"));
|
||||
|
||||
m_gs_trifilter.push_back(GSSetting(static_cast<uint32>(TriFiltering::None), "None", "Default"));
|
||||
m_gs_trifilter.push_back(GSSetting(static_cast<uint32>(TriFiltering::PS2), "Trilinear", ""));
|
||||
m_gs_trifilter.push_back(GSSetting(static_cast<uint32>(TriFiltering::Forced), "Trilinear", "Ultra/Slow"));
|
||||
m_gs_trifilter.push_back(GSSetting(static_cast<u32>(TriFiltering::None), "None", "Default"));
|
||||
m_gs_trifilter.push_back(GSSetting(static_cast<u32>(TriFiltering::PS2), "Trilinear", ""));
|
||||
m_gs_trifilter.push_back(GSSetting(static_cast<u32>(TriFiltering::Forced), "Trilinear", "Ultra/Slow"));
|
||||
|
||||
m_gs_generic_list.push_back(GSSetting(-1, "Automatic", "Default"));
|
||||
m_gs_generic_list.push_back(GSSetting(0, "Force-Disabled", ""));
|
||||
@@ -1185,14 +1167,14 @@ void GSApp::Init()
|
||||
GSSetting(CRCHackLevel::Aggressive, "Aggressive", ""),
|
||||
};
|
||||
|
||||
m_gs_acc_blend_level.push_back(GSSetting(0, "None", "Fastest"));
|
||||
m_gs_acc_blend_level.push_back(GSSetting(0, "Minimum", "Fastest"));
|
||||
m_gs_acc_blend_level.push_back(GSSetting(1, "Basic", "Recommended"));
|
||||
m_gs_acc_blend_level.push_back(GSSetting(2, "Medium", ""));
|
||||
m_gs_acc_blend_level.push_back(GSSetting(3, "High", ""));
|
||||
m_gs_acc_blend_level.push_back(GSSetting(4, "Full", "Very Slow"));
|
||||
m_gs_acc_blend_level.push_back(GSSetting(5, "Ultra", "Ultra Slow"));
|
||||
|
||||
m_gs_acc_blend_level_d3d11.push_back(GSSetting(0, "None", "Fastest"));
|
||||
m_gs_acc_blend_level_d3d11.push_back(GSSetting(0, "Minimum", "Fastest"));
|
||||
m_gs_acc_blend_level_d3d11.push_back(GSSetting(1, "Basic", "Recommended"));
|
||||
m_gs_acc_blend_level_d3d11.push_back(GSSetting(2, "Medium", "Debug"));
|
||||
m_gs_acc_blend_level_d3d11.push_back(GSSetting(3, "High", "Debug"));
|
||||
@@ -1207,9 +1189,10 @@ void GSApp::Init()
|
||||
// Avoid to clutter the ini file with useless options
|
||||
#ifdef _WIN32
|
||||
// Per OS option.
|
||||
m_default_configuration["Adapter"] = "default";
|
||||
m_default_configuration["adapter_index"] = "0";
|
||||
m_default_configuration["CaptureFileName"] = "";
|
||||
m_default_configuration["CaptureVideoCodecDisplayName"] = "";
|
||||
m_default_configuration["debug_d3d"] = "0";
|
||||
m_default_configuration["dx_break_on_severity"] = "0";
|
||||
// D3D Blending option
|
||||
m_default_configuration["accurate_blending_unit_d3d11"] = "1";
|
||||
@@ -1226,7 +1209,7 @@ void GSApp::Init()
|
||||
m_default_configuration["capture_threads"] = "4";
|
||||
m_default_configuration["CaptureHeight"] = "480";
|
||||
m_default_configuration["CaptureWidth"] = "640";
|
||||
m_default_configuration["crc_hack_level"] = std::to_string(static_cast<int8>(CRCHackLevel::Automatic));
|
||||
m_default_configuration["crc_hack_level"] = std::to_string(static_cast<s8>(CRCHackLevel::Automatic));
|
||||
m_default_configuration["CrcHacksExclusions"] = "";
|
||||
m_default_configuration["debug_glsl_shader"] = "0";
|
||||
m_default_configuration["debug_opengl"] = "0";
|
||||
@@ -1235,7 +1218,7 @@ void GSApp::Init()
|
||||
m_default_configuration["dump"] = "0";
|
||||
m_default_configuration["extrathreads"] = "2";
|
||||
m_default_configuration["extrathreads_height"] = "4";
|
||||
m_default_configuration["filter"] = std::to_string(static_cast<int8>(BiFiltering::PS2));
|
||||
m_default_configuration["filter"] = std::to_string(static_cast<s8>(BiFiltering::PS2));
|
||||
m_default_configuration["force_texture_clear"] = "0";
|
||||
m_default_configuration["fxaa"] = "0";
|
||||
m_default_configuration["interlace"] = "7";
|
||||
@@ -1262,22 +1245,19 @@ void GSApp::Init()
|
||||
m_default_configuration["osd_monitor_enabled"] = "0";
|
||||
m_default_configuration["osd_max_log_messages"] = "2";
|
||||
m_default_configuration["override_geometry_shader"] = "-1";
|
||||
m_default_configuration["override_GL_ARB_compute_shader"] = "-1";
|
||||
m_default_configuration["override_GL_ARB_copy_image"] = "-1";
|
||||
m_default_configuration["override_GL_ARB_clear_texture"] = "-1";
|
||||
m_default_configuration["override_GL_ARB_clip_control"] = "-1";
|
||||
m_default_configuration["override_GL_ARB_direct_state_access"] = "-1";
|
||||
m_default_configuration["override_GL_ARB_draw_buffers_blend"] = "-1";
|
||||
m_default_configuration["override_GL_ARB_get_texture_sub_image"] = "-1";
|
||||
m_default_configuration["override_GL_ARB_gpu_shader5"] = "-1";
|
||||
m_default_configuration["override_GL_ARB_multi_bind"] = "-1";
|
||||
m_default_configuration["override_GL_ARB_shader_image_load_store"] = "-1";
|
||||
m_default_configuration["override_GL_ARB_shader_storage_buffer_object"] = "-1";
|
||||
m_default_configuration["override_GL_ARB_sparse_texture"] = "-1";
|
||||
m_default_configuration["override_GL_ARB_sparse_texture2"] = "-1";
|
||||
m_default_configuration["override_GL_ARB_texture_view"] = "-1";
|
||||
m_default_configuration["override_GL_ARB_vertex_attrib_binding"] = "-1";
|
||||
m_default_configuration["override_GL_ARB_texture_barrier"] = "-1";
|
||||
#ifdef GL_EXT_TEX_SUB_IMAGE
|
||||
m_default_configuration["override_GL_ARB_get_texture_sub_image"] = "-1";
|
||||
#endif
|
||||
m_default_configuration["paltex"] = "0";
|
||||
m_default_configuration["png_compression_level"] = std::to_string(Z_BEST_SPEED);
|
||||
m_default_configuration["preload_frame_with_gs_data"] = "0";
|
||||
@@ -1315,7 +1295,7 @@ void GSApp::Init()
|
||||
m_default_configuration["UserHacks_TCOffsetX"] = "0";
|
||||
m_default_configuration["UserHacks_TCOffsetY"] = "0";
|
||||
m_default_configuration["UserHacks_TextureInsideRt"] = "0";
|
||||
m_default_configuration["UserHacks_TriFilter"] = std::to_string(static_cast<int8>(TriFiltering::None));
|
||||
m_default_configuration["UserHacks_TriFilter"] = std::to_string(static_cast<s8>(TriFiltering::None));
|
||||
m_default_configuration["UserHacks_WildHack"] = "0";
|
||||
m_default_configuration["wrap_gs_mem"] = "0";
|
||||
m_default_configuration["vsync"] = "0";
|
||||
@@ -1392,7 +1372,7 @@ void GSApp::SetConfigDir()
|
||||
// core settings aren't populated yet, thus we do populate it if needed either when
|
||||
// opening GS settings or init -- govanify
|
||||
wxString iniName(L"GS.ini");
|
||||
m_ini = EmuFolders::Settings.Combine(iniName).GetFullPath();
|
||||
m_ini = EmuFolders::Settings.Combine(iniName).GetFullPath().ToUTF8();
|
||||
}
|
||||
|
||||
std::string GSApp::GetConfigS(const char* entry)
|
||||
@@ -1402,12 +1382,12 @@ std::string GSApp::GetConfigS(const char* entry)
|
||||
|
||||
if (def != m_default_configuration.end())
|
||||
{
|
||||
GetIniString(m_section.c_str(), entry, def->second.c_str(), buff, countof(buff), m_ini.c_str());
|
||||
GetIniString(m_section.c_str(), entry, def->second.c_str(), buff, std::size(buff), m_ini.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "Option %s doesn't have a default value\n", entry);
|
||||
GetIniString(m_section.c_str(), entry, "", buff, countof(buff), m_ini.c_str());
|
||||
GetIniString(m_section.c_str(), entry, "", buff, std::size(buff), m_ini.c_str());
|
||||
}
|
||||
|
||||
return {buff};
|
||||
|
||||
+24
-1688
File diff suppressed because it is too large
Load Diff
-215
@@ -97,130 +97,6 @@ IDR_FONT_ROBOTO RCDATA "res\\fonts-roboto\\Roboto-Regul
|
||||
// Dialog
|
||||
//
|
||||
|
||||
IDD_HACKS DIALOGEX 0, 0, 210, 289
|
||||
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "Advanced Settings & Hacks"
|
||||
FONT 8, "MS Shell Dlg", 400, 0, 0x1
|
||||
BEGIN
|
||||
// Rendering Hacks:
|
||||
GROUPBOX "Rendering Hacks",IDC_STATIC,7,7,196,114,0,WS_EX_TRANSPARENT
|
||||
// Column one - HW Hacks
|
||||
CONTROL "Auto Flush",IDC_AUTO_FLUSH_HW,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,19,55,8
|
||||
CONTROL "Disable Depth Emulation",IDC_TC_DEPTH,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,32,92,8
|
||||
CONTROL "Disable Safe Features",IDC_SAFE_FEATURES,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,45,85,8
|
||||
// Column two - HW hacks
|
||||
CONTROL "Fast Texture Invalidation",IDC_FAST_TC_INV,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,106,19,93,8
|
||||
CONTROL "Frame Buffer Conversion",IDC_CPU_FB_CONVERSION,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,106,32,93,8
|
||||
CONTROL "Memory Wrapping",IDC_MEMORY_WRAPPING,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,106,45,75,8
|
||||
CONTROL "Preload Frame Data",IDC_PRELOAD_GS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,106,58,80,8
|
||||
// Columns end
|
||||
//
|
||||
RTEXT "Half-screen Fix:",IDC_HALF_SCREEN_TS_TEXT,14,73,62,8
|
||||
COMBOBOX IDC_HALF_SCREEN_TS,80,70,116,63,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
|
||||
RTEXT "Trilinear Filtering:",IDC_TRI_FILTER_TEXT,16,88,60,8
|
||||
COMBOBOX IDC_TRI_FILTER,80,85,116,63,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
|
||||
RTEXT "Skipdraw Range:",IDC_SKIPDRAWHACK_TEXT,14,103,62,8
|
||||
EDITTEXT IDC_SKIPDRAWOFFSETEDIT,80,100,58,14,ES_RIGHT | ES_AUTOHSCROLL | ES_NUMBER
|
||||
CONTROL "",IDC_SKIPDRAWOFFSET,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS,0,0,11,14
|
||||
EDITTEXT IDC_SKIPDRAWHACKEDIT,138,100,58,14,ES_RIGHT | ES_AUTOHSCROLL | ES_NUMBER
|
||||
CONTROL "",IDC_SKIPDRAWHACK,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS,0,0,11,14
|
||||
// Upscaling Hacks:
|
||||
GROUPBOX "Upscaling Hacks",IDC_STATIC,7,124,196,75,0,WS_EX_TRANSPARENT
|
||||
CONTROL "Align Sprite",IDC_ALIGN_SPRITE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,136,55,8
|
||||
CONTROL "Merge Sprite",IDC_MERGE_PP_SPRITE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,71,136,55,8
|
||||
CONTROL "Wild Arms Offset",IDC_WILDHACK,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,130,136,70,8
|
||||
RTEXT "Half-pixel Offset:",IDC_OFFSETHACK_TEXT,14,151,62,8
|
||||
COMBOBOX IDC_OFFSETHACK,80,148,116,63,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
|
||||
RTEXT "Round Sprite:",IDC_ROUND_SPRITE_TEXT,30,166,46,8
|
||||
COMBOBOX IDC_ROUND_SPRITE,80,163,116,63,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
|
||||
RTEXT "Texture Offsets:",IDC_TCOFFSET_TEXT,14,181,62,8
|
||||
RTEXT "X:",IDC_TCOFFSETX_TEXT,81,181,10,8
|
||||
EDITTEXT IDC_TCOFFSETX2,94,178,44,14,ES_RIGHT | ES_AUTOHSCROLL | ES_NUMBER
|
||||
CONTROL "",IDC_TCOFFSETX,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS,0,0,11,14
|
||||
RTEXT "Y:",IDC_TCOFFSETY_TEXT,139,181,10,8
|
||||
EDITTEXT IDC_TCOFFSETY2,152,178,44,14,ES_RIGHT | ES_AUTOHSCROLL | ES_NUMBER
|
||||
CONTROL "",IDC_TCOFFSETY,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS,0,0,11,14
|
||||
// OpenGL Advanced Settings:
|
||||
GROUPBOX "OpenGL Advanced Settings",IDC_STATIC,7,202,196,61,0,WS_EX_TRANSPARENT
|
||||
RTEXT "Geometry Shader:",IDC_GEOMETRY_SHADER_TEXT,14,216,62,8
|
||||
COMBOBOX IDC_GEOMETRY_SHADER_OVERRIDE,80,213,116,63,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
|
||||
RTEXT "Image Load Store:",IDC_IMAGE_LOAD_STORE_TEXT,14,231,62,8
|
||||
COMBOBOX IDC_IMAGE_LOAD_STORE,80,228,116,63,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
|
||||
RTEXT "Sparse Texture:",IDC_SPARSE_TEXTURE_TEXT,14,246,62,8
|
||||
COMBOBOX IDC_SPARSE_TEXTURE,80,243,116,63,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
|
||||
// General Settings:
|
||||
DEFPUSHBUTTON "OK",IDOK,52,269,50,14
|
||||
DEFPUSHBUTTON "Cancel",IDCANCEL,108,269,50,14
|
||||
END
|
||||
|
||||
IDD_SHADER DIALOGEX 0, 0, 248, 230
|
||||
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "Shader Configuration"
|
||||
FONT 8, "MS Shell Dlg", 400, 0, 0x1
|
||||
BEGIN
|
||||
CONTROL "Texture Filtering of Display",IDC_LINEAR_PRESENT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,6,6,100,10
|
||||
CONTROL "FXAA Shader (PgUp)",IDC_FXAA,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,6,19,80,10
|
||||
CONTROL "Shade Boost",IDC_SHADEBOOST,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,6,32,90,10
|
||||
LTEXT "Shade Boost Brightness",IDC_BRIGHTNESS_TEXT,16,50,80,8
|
||||
CONTROL "",IDC_BRIGHTNESS_SLIDER,"msctls_trackbar32",TBS_BOTH | TBS_NOTICKS | WS_TABSTOP,95,48,122,15
|
||||
RTEXT "100",IDC_BRIGHTNESS_VALUE,221,50,12,8
|
||||
LTEXT "Shade Boost Contrast",IDC_CONTRAST_TEXT,16,75,80,8
|
||||
CONTROL "",IDC_CONTRAST_SLIDER,"msctls_trackbar32",TBS_BOTH | TBS_NOTICKS | WS_TABSTOP,95,73,122,15
|
||||
RTEXT "100",IDC_CONTRAST_VALUE,221,75,12,8
|
||||
LTEXT "Shade Boost Saturation",IDC_SATURATION_TEXT,16,100,80,8
|
||||
CONTROL "",IDC_SATURATION_SLIDER,"msctls_trackbar32",TBS_BOTH | TBS_NOTICKS | WS_TABSTOP,95,98,122,15
|
||||
RTEXT "100",IDC_SATURATION_VALUE,221,100,12,8
|
||||
CONTROL "External Shader (Home)",IDC_SHADER_FX,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,6,116,91,10
|
||||
LTEXT "External Shader",IDC_SHADER_FX_TEXT,16,131,75,8
|
||||
EDITTEXT IDC_SHADER_FX_EDIT,16,139,170,14,ES_AUTOHSCROLL
|
||||
PUSHBUTTON "Browse",IDC_SHADER_FX_BUTTON,196,139,37,14
|
||||
LTEXT "External Shader Config",IDC_SHADER_FX_CONF_TEXT,16,156,75,8
|
||||
PUSHBUTTON "Browse",IDC_SHADER_FX_CONF_BUTTON,196,164,37,14
|
||||
EDITTEXT IDC_SHADER_FX_CONF_EDIT,16,164,170,14,ES_AUTOHSCROLL
|
||||
COMBOBOX IDC_TVSHADER,75,184,98,118,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
|
||||
LTEXT "TV Shader:",IDC_STATIC,16,186,55,8
|
||||
DEFPUSHBUTTON "OK",IDOK,71,208,50,14
|
||||
DEFPUSHBUTTON "Cancel",IDCANCEL,127,208,50,14
|
||||
END
|
||||
|
||||
IDD_OSD DIALOGEX 0, 0, 210, 205
|
||||
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "OSD Configuration"
|
||||
FONT 8, "MS Shell Dlg", 400, 0, 0x1
|
||||
BEGIN
|
||||
// Enable/Disable
|
||||
CONTROL "Enable Statistics Monitor",IDC_OSD_MONITOR,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,16,7,88,10
|
||||
CONTROL "Enable Log",IDC_OSD_LOG,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,112,7,54,10
|
||||
// Font Settings
|
||||
GROUPBOX "Font",IDC_STATIC,7,20,196,100,0,WS_EX_TRANSPARENT
|
||||
LTEXT "Size:",IDC_OSD_SIZE_TEXT,16,34,25,8
|
||||
EDITTEXT IDC_OSD_SIZE_EDIT,112,31,83,14,ES_RIGHT | ES_AUTOHSCROLL | ES_NUMBER
|
||||
CONTROL "",IDC_OSD_SIZE,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS,0,0,11,14
|
||||
LTEXT "Red:",IDC_OSD_COLOR_RED_TEXT,16,51,25,8
|
||||
CONTROL "",IDC_OSD_COLOR_RED_SLIDER,"msctls_trackbar32",TBS_BOTH | TBS_NOTICKS | WS_TABSTOP,107,49,76,15
|
||||
RTEXT "255",IDC_OSD_COLOR_RED_AMOUNT,184,52,12,8
|
||||
LTEXT "Green:",IDC_OSD_COLOR_GREEN_TEXT,16,68,25,8
|
||||
CONTROL "",IDC_OSD_COLOR_GREEN_SLIDER,"msctls_trackbar32",TBS_BOTH | TBS_NOTICKS | WS_TABSTOP,107,66,76,15
|
||||
RTEXT "255",IDC_OSD_COLOR_GREEN_AMOUNT,184,69,12,8
|
||||
LTEXT "Blue:",IDC_OSD_COLOR_BLUE_TEXT,16,86,25,8
|
||||
CONTROL "",IDC_OSD_COLOR_BLUE_SLIDER,"msctls_trackbar32",TBS_BOTH | TBS_NOTICKS | WS_TABSTOP,107,83,76,15
|
||||
RTEXT "255",IDC_OSD_COLOR_BLUE_AMOUNT,184,86,12,8
|
||||
LTEXT "Opacity:",IDC_OSD_OPACITY_TEXT,16,104,50,8
|
||||
CONTROL "",IDC_OSD_OPACITY_SLIDER,"msctls_trackbar32",TBS_BOTH | TBS_NOTICKS | WS_TABSTOP,107,100,76,15
|
||||
RTEXT "100",IDC_OSD_OPACITY_AMOUNT,184,104,12,8
|
||||
// Log Settings
|
||||
GROUPBOX "Log Messages",IDC_STATIC,7,125,196,52,0,WS_EX_TRANSPARENT
|
||||
LTEXT "Timeout (seconds):",IDC_OSD_TIMEOUT_TEXT,16,139,75,8
|
||||
EDITTEXT IDC_OSD_TIMEOUT_EDIT,112,135,83,14,ES_RIGHT | ES_AUTOHSCROLL | ES_NUMBER
|
||||
CONTROL "", IDC_OSD_TIMEOUT,"msctls_updown32", UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS,0,0,11,14
|
||||
LTEXT "Max:",IDC_OSD_MAX_LOG_TEXT,16,158,25,8
|
||||
EDITTEXT IDC_OSD_MAX_LOG_EDIT,112,155,83,14,ES_RIGHT | ES_AUTOHSCROLL | ES_NUMBER
|
||||
CONTROL "", IDC_OSD_MAX_LOG,"msctls_updown32", UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS,0,0,11,14
|
||||
// OK/CANCEL
|
||||
DEFPUSHBUTTON "OK",IDOK,52,183,50,14
|
||||
DEFPUSHBUTTON "Cancel",IDCANCEL,108,183,50,14
|
||||
END
|
||||
|
||||
IDD_CAPTURE DIALOGEX 0, 0, 279, 71
|
||||
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "Capture settings"
|
||||
@@ -238,53 +114,6 @@ BEGIN
|
||||
COMBOBOX IDC_COLORSPACE,102,47,48,32,CBS_DROPDOWNLIST | WS_TABSTOP
|
||||
END
|
||||
|
||||
IDD_CONFIG DIALOGEX 0, 0, 242, 315
|
||||
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "Graphics Settings"
|
||||
FONT 8, "MS Shell Dlg", 400, 0, 0x1
|
||||
BEGIN
|
||||
// General Settings:
|
||||
LTEXT "Renderer:",IDC_STATIC,7,8,79,8
|
||||
COMBOBOX IDC_RENDERER,71,6,166,118,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
|
||||
LTEXT "Adapter:",IDC_ADAPTER_TEXT,7,23,79,8
|
||||
COMBOBOX IDC_ADAPTER,71,21,166,118,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
|
||||
LTEXT "Interlacing (F5):",IDC_INTERLACE_TEXT,7,38,55,8
|
||||
COMBOBOX IDC_INTERLACE,71,36,166,118,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
|
||||
LTEXT "Texture Filtering:",IDC_FILTER_TEXT,7,53,79,8
|
||||
COMBOBOX IDC_FILTER,71,51,166,63,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
|
||||
PUSHBUTTON "OSD Configuration",IDC_OSDBUTTON,11,274,108,14
|
||||
PUSHBUTTON "Shader Configuration",IDC_SHADEBUTTON,125,274,108,14
|
||||
DEFPUSHBUTTON "OK",IDOK,69,294,50,14
|
||||
PUSHBUTTON "Cancel",IDCANCEL,125,294,50,14
|
||||
GROUPBOX "Hardware Renderer Settings",IDC_STATIC,7,67,230,154,BS_CENTER
|
||||
CONTROL "Accurate DATE",IDC_ACCURATE_DATE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,77,63,10
|
||||
CONTROL "GPU Palette Conversion",IDC_PALTEX,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,93,87,10
|
||||
CONTROL "Conservative Buffer Allocation",IDC_CONSERVATIVE_FB,
|
||||
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,105,93,110,10
|
||||
LTEXT "Internal Resolution:",IDC_UPSCALE_MULTIPLIER_TEXT,23,109,79,8
|
||||
COMBOBOX IDC_UPSCALE_MULTIPLIER,105,107,127,98,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
|
||||
LTEXT "Anisotropic Filtering:",IDC_AFCOMBO_TEXT,23,125,79,8
|
||||
COMBOBOX IDC_AFCOMBO,105,123,127,118,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
|
||||
LTEXT "Dithering (PgDn):",IDC_DITHERING_TEXT,23,141,79,8
|
||||
COMBOBOX IDC_DITHERING,105,139,127,118,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
|
||||
LTEXT "Mipmapping (Ins):",IDC_MIPMAP_HW_TEXT,23,157,79,8
|
||||
COMBOBOX IDC_MIPMAP_HW,105,155,127,118,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
|
||||
LTEXT "CRC Hack Level:",IDC_CRC_LEVEL_TEXT,23,173,79,8
|
||||
COMBOBOX IDC_CRC_LEVEL,105,171,127,118,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
|
||||
LTEXT "Blending Accuracy:",IDC_ACCURATE_BLEND_UNIT_TEXT,23,189,79,8
|
||||
COMBOBOX IDC_ACCURATE_BLEND_UNIT,105,187,127,118,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
|
||||
COMBOBOX IDC_ACCURATE_BLEND_UNIT_D3D11,105,187,127,118,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
|
||||
CONTROL "Enable HW Hacks",IDC_HACKS_ENABLED,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,205,71,10
|
||||
PUSHBUTTON "Advanced Settings and Hacks",IDC_HACKSBUTTON,105,203,127,14
|
||||
GROUPBOX "Software Renderer Settings",IDC_STATIC,7,224,230,44,BS_CENTER
|
||||
CONTROL "Auto Flush",IDC_AUTO_FLUSH_SW,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,236,90,10
|
||||
CONTROL "Edge Anti-aliasing (Del)",IDC_AA1,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,125,236,90,10
|
||||
LTEXT "Rendering threads:",IDC_SWTHREADS_TEXT,125,252,65,8
|
||||
EDITTEXT IDC_SWTHREADS_EDIT,197,250,34,13,ES_AUTOHSCROLL | ES_NUMBER
|
||||
CONTROL "",IDC_SWTHREADS,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS,0,0,11,14
|
||||
CONTROL "Mipmapping",IDC_MIPMAP_SW,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,250,90,10
|
||||
END
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
@@ -294,37 +123,6 @@ END
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
GUIDELINES DESIGNINFO
|
||||
BEGIN
|
||||
IDD_HACKS, DIALOG
|
||||
BEGIN
|
||||
LEFTMARGIN, 7
|
||||
RIGHTMARGIN, 154
|
||||
VERTGUIDE, 14
|
||||
VERTGUIDE, 84
|
||||
VERTGUIDE, 88
|
||||
VERTGUIDE, 146
|
||||
TOPMARGIN, 7
|
||||
BOTTOMMARGIN, 229
|
||||
HORZGUIDE, 51
|
||||
HORZGUIDE, 64
|
||||
HORZGUIDE, 77
|
||||
END
|
||||
|
||||
IDD_SHADER, DIALOG
|
||||
BEGIN
|
||||
LEFTMARGIN, 6
|
||||
RIGHTMARGIN, 242
|
||||
TOPMARGIN, 7
|
||||
BOTTOMMARGIN, 244
|
||||
END
|
||||
|
||||
IDD_OSD, DIALOG
|
||||
BEGIN
|
||||
LEFTMARGIN, 6
|
||||
RIGHTMARGIN, 242
|
||||
TOPMARGIN, 7
|
||||
BOTTOMMARGIN, 244
|
||||
END
|
||||
|
||||
IDD_CAPTURE, DIALOG
|
||||
BEGIN
|
||||
VERTGUIDE, 6
|
||||
@@ -332,19 +130,6 @@ BEGIN
|
||||
VERTGUIDE, 271
|
||||
HORZGUIDE, 54
|
||||
END
|
||||
|
||||
IDD_CONFIG, DIALOG
|
||||
BEGIN
|
||||
LEFTMARGIN, 6
|
||||
RIGHTMARGIN, 237
|
||||
VERTGUIDE, 11
|
||||
VERTGUIDE, 22
|
||||
VERTGUIDE, 101
|
||||
VERTGUIDE, 105
|
||||
VERTGUIDE, 232
|
||||
TOPMARGIN, 6
|
||||
BOTTOMMARGIN, 367
|
||||
END
|
||||
END
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
||||
|
||||
@@ -18,10 +18,11 @@
|
||||
template <int i>
|
||||
class GSAlignedClass
|
||||
{
|
||||
public:
|
||||
GSAlignedClass() {}
|
||||
virtual ~GSAlignedClass() {}
|
||||
protected:
|
||||
GSAlignedClass() = default;
|
||||
~GSAlignedClass() = default;
|
||||
|
||||
public:
|
||||
void* operator new(size_t size)
|
||||
{
|
||||
return _aligned_malloc(size, i);
|
||||
@@ -32,6 +33,11 @@ public:
|
||||
_aligned_free(p);
|
||||
}
|
||||
|
||||
void* operator new(size_t size, void* ptr)
|
||||
{
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void* operator new[](size_t size)
|
||||
{
|
||||
return _aligned_malloc(size, i);
|
||||
|
||||
+80
-80
@@ -15,7 +15,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "GS.h"
|
||||
#include "GSRegs.h"
|
||||
#include "GSTables.h"
|
||||
#include "GSVector.h"
|
||||
|
||||
@@ -47,11 +47,11 @@ class GSBlock
|
||||
static const GSVector4i m_uw8hmask3;
|
||||
|
||||
public:
|
||||
template <int i, int alignment, uint32 mask>
|
||||
__forceinline static void WriteColumn32(uint8* RESTRICT dst, const uint8* RESTRICT src, int srcpitch)
|
||||
template <int i, int alignment, u32 mask>
|
||||
__forceinline static void WriteColumn32(u8* RESTRICT dst, const u8* RESTRICT src, int srcpitch)
|
||||
{
|
||||
const uint8* RESTRICT s0 = &src[srcpitch * 0];
|
||||
const uint8* RESTRICT s1 = &src[srcpitch * 1];
|
||||
const u8* RESTRICT s0 = &src[srcpitch * 0];
|
||||
const u8* RESTRICT s1 = &src[srcpitch * 1];
|
||||
|
||||
#if _M_SSE >= 0x501
|
||||
|
||||
@@ -173,12 +173,12 @@ public:
|
||||
}
|
||||
|
||||
template <int i, int alignment>
|
||||
__forceinline static void WriteColumn16(uint8* RESTRICT dst, const uint8* RESTRICT src, int srcpitch)
|
||||
__forceinline static void WriteColumn16(u8* RESTRICT dst, const u8* RESTRICT src, int srcpitch)
|
||||
{
|
||||
const uint8* RESTRICT s0 = &src[srcpitch * 0];
|
||||
const uint8* RESTRICT s1 = &src[srcpitch * 1];
|
||||
const u8* RESTRICT s0 = &src[srcpitch * 0];
|
||||
const u8* RESTRICT s1 = &src[srcpitch * 1];
|
||||
|
||||
// for(int j = 0; j < 16; j++) {((uint16*)s0)[j] = columnTable16[0][j]; ((uint16*)s1)[j] = columnTable16[1][j];}
|
||||
// for(int j = 0; j < 16; j++) {((u16*)s0)[j] = columnTable16[0][j]; ((u16*)s1)[j] = columnTable16[1][j];}
|
||||
|
||||
#if _M_SSE >= 0x501
|
||||
|
||||
@@ -247,7 +247,7 @@ public:
|
||||
}
|
||||
|
||||
template <int i, int alignment>
|
||||
__forceinline static void WriteColumn8(uint8* RESTRICT dst, const uint8* RESTRICT src, int srcpitch)
|
||||
__forceinline static void WriteColumn8(u8* RESTRICT dst, const u8* RESTRICT src, int srcpitch)
|
||||
{
|
||||
// TODO: read unaligned as WriteColumn32 does and try saving a few shuffles
|
||||
|
||||
@@ -310,7 +310,7 @@ public:
|
||||
}
|
||||
|
||||
template <int i, int alignment>
|
||||
__forceinline static void WriteColumn4(uint8* RESTRICT dst, const uint8* RESTRICT src, int srcpitch)
|
||||
__forceinline static void WriteColumn4(u8* RESTRICT dst, const u8* RESTRICT src, int srcpitch)
|
||||
{
|
||||
//printf("WriteColumn4\n");
|
||||
|
||||
@@ -345,8 +345,8 @@ public:
|
||||
((GSVector4i*)dst)[i * 4 + 3] = v3;
|
||||
}
|
||||
|
||||
template <int alignment, uint32 mask>
|
||||
static void WriteColumn32(int y, uint8* RESTRICT dst, const uint8* RESTRICT src, int srcpitch)
|
||||
template <int alignment, u32 mask>
|
||||
static void WriteColumn32(int y, u8* RESTRICT dst, const u8* RESTRICT src, int srcpitch)
|
||||
{
|
||||
switch ((y >> 1) & 3)
|
||||
{
|
||||
@@ -359,7 +359,7 @@ public:
|
||||
}
|
||||
|
||||
template <int alignment>
|
||||
static void WriteColumn16(int y, uint8* RESTRICT dst, const uint8* RESTRICT src, int srcpitch)
|
||||
static void WriteColumn16(int y, u8* RESTRICT dst, const u8* RESTRICT src, int srcpitch)
|
||||
{
|
||||
switch ((y >> 1) & 3)
|
||||
{
|
||||
@@ -372,7 +372,7 @@ public:
|
||||
}
|
||||
|
||||
template <int alignment>
|
||||
static void WriteColumn8(int y, uint8* RESTRICT dst, const uint8* RESTRICT src, int srcpitch)
|
||||
static void WriteColumn8(int y, u8* RESTRICT dst, const u8* RESTRICT src, int srcpitch)
|
||||
{
|
||||
switch ((y >> 2) & 3)
|
||||
{
|
||||
@@ -385,7 +385,7 @@ public:
|
||||
}
|
||||
|
||||
template <int alignment>
|
||||
static void WriteColumn4(int y, uint8* RESTRICT dst, const uint8* RESTRICT src, int srcpitch)
|
||||
static void WriteColumn4(int y, u8* RESTRICT dst, const u8* RESTRICT src, int srcpitch)
|
||||
{
|
||||
switch ((y >> 2) & 3)
|
||||
{
|
||||
@@ -397,8 +397,8 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
template <int alignment, uint32 mask>
|
||||
static void WriteBlock32(uint8* RESTRICT dst, const uint8* RESTRICT src, int srcpitch)
|
||||
template <int alignment, u32 mask>
|
||||
static void WriteBlock32(u8* RESTRICT dst, const u8* RESTRICT src, int srcpitch)
|
||||
{
|
||||
WriteColumn32<0, alignment, mask>(dst, src, srcpitch);
|
||||
src += srcpitch * 2;
|
||||
@@ -410,7 +410,7 @@ public:
|
||||
}
|
||||
|
||||
template <int alignment>
|
||||
static void WriteBlock16(uint8* RESTRICT dst, const uint8* RESTRICT src, int srcpitch)
|
||||
static void WriteBlock16(u8* RESTRICT dst, const u8* RESTRICT src, int srcpitch)
|
||||
{
|
||||
WriteColumn16<0, alignment>(dst, src, srcpitch);
|
||||
src += srcpitch * 2;
|
||||
@@ -422,7 +422,7 @@ public:
|
||||
}
|
||||
|
||||
template <int alignment>
|
||||
static void WriteBlock8(uint8* RESTRICT dst, const uint8* RESTRICT src, int srcpitch)
|
||||
static void WriteBlock8(u8* RESTRICT dst, const u8* RESTRICT src, int srcpitch)
|
||||
{
|
||||
WriteColumn8<0, alignment>(dst, src, srcpitch);
|
||||
src += srcpitch * 4;
|
||||
@@ -434,7 +434,7 @@ public:
|
||||
}
|
||||
|
||||
template <int alignment>
|
||||
static void WriteBlock4(uint8* RESTRICT dst, const uint8* RESTRICT src, int srcpitch)
|
||||
static void WriteBlock4(u8* RESTRICT dst, const u8* RESTRICT src, int srcpitch)
|
||||
{
|
||||
WriteColumn4<0, alignment>(dst, src, srcpitch);
|
||||
src += srcpitch * 4;
|
||||
@@ -446,7 +446,7 @@ public:
|
||||
}
|
||||
|
||||
template <int i>
|
||||
__forceinline static void ReadColumn32(const uint8* RESTRICT src, uint8* RESTRICT dst, int dstpitch)
|
||||
__forceinline static void ReadColumn32(const u8* RESTRICT src, u8* RESTRICT dst, int dstpitch)
|
||||
{
|
||||
#if _M_SSE >= 0x501
|
||||
|
||||
@@ -484,7 +484,7 @@ public:
|
||||
}
|
||||
|
||||
template <int i>
|
||||
__forceinline static void ReadColumn16(const uint8* RESTRICT src, uint8* RESTRICT dst, int dstpitch)
|
||||
__forceinline static void ReadColumn16(const u8* RESTRICT src, u8* RESTRICT dst, int dstpitch)
|
||||
{
|
||||
#if _M_SSE >= 0x501
|
||||
|
||||
@@ -526,10 +526,10 @@ public:
|
||||
}
|
||||
|
||||
template <int i>
|
||||
__forceinline static void ReadColumn8(const uint8* RESTRICT src, uint8* RESTRICT dst, int dstpitch)
|
||||
__forceinline static void ReadColumn8(const u8* RESTRICT src, u8* RESTRICT dst, int dstpitch)
|
||||
{
|
||||
|
||||
//for(int j = 0; j < 64; j++) ((uint8*)src)[j] = (uint8)j;
|
||||
//for(int j = 0; j < 64; j++) ((u8*)src)[j] = (u8)j;
|
||||
|
||||
#if 0 //_M_SSE >= 0x501
|
||||
|
||||
@@ -593,7 +593,7 @@ public:
|
||||
}
|
||||
|
||||
template <int i>
|
||||
__forceinline static void ReadColumn4(const uint8* RESTRICT src, uint8* RESTRICT dst, int dstpitch)
|
||||
__forceinline static void ReadColumn4(const u8* RESTRICT src, u8* RESTRICT dst, int dstpitch)
|
||||
{
|
||||
//printf("ReadColumn4\n");
|
||||
|
||||
@@ -628,7 +628,7 @@ public:
|
||||
GSVector4i::store<true>(&dst[dstpitch * 3], v3);
|
||||
}
|
||||
|
||||
static void ReadColumn32(int y, const uint8* RESTRICT src, uint8* RESTRICT dst, int dstpitch)
|
||||
static void ReadColumn32(int y, const u8* RESTRICT src, u8* RESTRICT dst, int dstpitch)
|
||||
{
|
||||
switch ((y >> 1) & 3)
|
||||
{
|
||||
@@ -640,7 +640,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
static void ReadColumn16(int y, const uint8* RESTRICT src, uint8* RESTRICT dst, int dstpitch)
|
||||
static void ReadColumn16(int y, const u8* RESTRICT src, u8* RESTRICT dst, int dstpitch)
|
||||
{
|
||||
switch ((y >> 1) & 3)
|
||||
{
|
||||
@@ -652,7 +652,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
static void ReadColumn8(int y, const uint8* RESTRICT src, uint8* RESTRICT dst, int dstpitch)
|
||||
static void ReadColumn8(int y, const u8* RESTRICT src, u8* RESTRICT dst, int dstpitch)
|
||||
{
|
||||
switch ((y >> 2) & 3)
|
||||
{
|
||||
@@ -664,7 +664,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
static void ReadColumn4(int y, const uint8* RESTRICT src, uint8* RESTRICT dst, int dstpitch)
|
||||
static void ReadColumn4(int y, const u8* RESTRICT src, u8* RESTRICT dst, int dstpitch)
|
||||
{
|
||||
switch ((y >> 2) & 3)
|
||||
{
|
||||
@@ -676,7 +676,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
static void ReadBlock32(const uint8* RESTRICT src, uint8* RESTRICT dst, int dstpitch)
|
||||
static void ReadBlock32(const u8* RESTRICT src, u8* RESTRICT dst, int dstpitch)
|
||||
{
|
||||
ReadColumn32<0>(src, dst, dstpitch);
|
||||
dst += dstpitch * 2;
|
||||
@@ -687,7 +687,7 @@ public:
|
||||
ReadColumn32<3>(src, dst, dstpitch);
|
||||
}
|
||||
|
||||
static void ReadBlock16(const uint8* RESTRICT src, uint8* RESTRICT dst, int dstpitch)
|
||||
static void ReadBlock16(const u8* RESTRICT src, u8* RESTRICT dst, int dstpitch)
|
||||
{
|
||||
ReadColumn16<0>(src, dst, dstpitch);
|
||||
dst += dstpitch * 2;
|
||||
@@ -698,7 +698,7 @@ public:
|
||||
ReadColumn16<3>(src, dst, dstpitch);
|
||||
}
|
||||
|
||||
static void ReadBlock8(const uint8* RESTRICT src, uint8* RESTRICT dst, int dstpitch)
|
||||
static void ReadBlock8(const u8* RESTRICT src, u8* RESTRICT dst, int dstpitch)
|
||||
{
|
||||
ReadColumn8<0>(src, dst, dstpitch);
|
||||
dst += dstpitch * 4;
|
||||
@@ -709,7 +709,7 @@ public:
|
||||
ReadColumn8<3>(src, dst, dstpitch);
|
||||
}
|
||||
|
||||
static void ReadBlock4(const uint8* RESTRICT src, uint8* RESTRICT dst, int dstpitch)
|
||||
static void ReadBlock4(const u8* RESTRICT src, u8* RESTRICT dst, int dstpitch)
|
||||
{
|
||||
ReadColumn4<0>(src, dst, dstpitch);
|
||||
dst += dstpitch * 4;
|
||||
@@ -720,7 +720,7 @@ public:
|
||||
ReadColumn4<3>(src, dst, dstpitch);
|
||||
}
|
||||
|
||||
__forceinline static void ReadBlock4P(const uint8* RESTRICT src, uint8* RESTRICT dst, int dstpitch)
|
||||
__forceinline static void ReadBlock4P(const u8* RESTRICT src, u8* RESTRICT dst, int dstpitch)
|
||||
{
|
||||
//printf("ReadBlock4P\n");
|
||||
|
||||
@@ -784,12 +784,12 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
__forceinline static void ReadBlock8HP(const uint8* RESTRICT src, uint8* RESTRICT dst, int dstpitch)
|
||||
__forceinline static void ReadBlock8HP(const u8* RESTRICT src, u8* RESTRICT dst, int dstpitch)
|
||||
{
|
||||
#if _M_SSE >= 0x501
|
||||
|
||||
uint8* RESTRICT d0 = &dst[dstpitch * 0];
|
||||
uint8* RESTRICT d1 = &dst[dstpitch * 4];
|
||||
u8* RESTRICT d0 = &dst[dstpitch * 0];
|
||||
u8* RESTRICT d1 = &dst[dstpitch * 4];
|
||||
|
||||
const GSVector8i* s = (const GSVector8i*)src;
|
||||
|
||||
@@ -855,12 +855,12 @@ public:
|
||||
#endif
|
||||
}
|
||||
|
||||
__forceinline static void ReadBlock4HLP(const uint8* RESTRICT src, uint8* RESTRICT dst, int dstpitch)
|
||||
__forceinline static void ReadBlock4HLP(const u8* RESTRICT src, u8* RESTRICT dst, int dstpitch)
|
||||
{
|
||||
#if _M_SSE >= 0x501
|
||||
|
||||
uint8* RESTRICT d0 = &dst[dstpitch * 0];
|
||||
uint8* RESTRICT d1 = &dst[dstpitch * 4];
|
||||
u8* RESTRICT d0 = &dst[dstpitch * 0];
|
||||
u8* RESTRICT d1 = &dst[dstpitch * 4];
|
||||
|
||||
const GSVector8i* s = (const GSVector8i*)src;
|
||||
|
||||
@@ -929,12 +929,12 @@ public:
|
||||
#endif
|
||||
}
|
||||
|
||||
__forceinline static void ReadBlock4HHP(const uint8* RESTRICT src, uint8* RESTRICT dst, int dstpitch)
|
||||
__forceinline static void ReadBlock4HHP(const u8* RESTRICT src, u8* RESTRICT dst, int dstpitch)
|
||||
{
|
||||
#if _M_SSE >= 0x501
|
||||
|
||||
uint8* RESTRICT d0 = &dst[dstpitch * 0];
|
||||
uint8* RESTRICT d1 = &dst[dstpitch * 4];
|
||||
u8* RESTRICT d0 = &dst[dstpitch * 0];
|
||||
u8* RESTRICT d1 = &dst[dstpitch * 4];
|
||||
|
||||
const GSVector8i* s = (const GSVector8i*)src;
|
||||
|
||||
@@ -1013,7 +1013,7 @@ public:
|
||||
}
|
||||
|
||||
template <bool AEM>
|
||||
static void ExpandBlock24(const uint32* RESTRICT src, uint8* RESTRICT dst, int dstpitch, const GIFRegTEXA& TEXA)
|
||||
static void ExpandBlock24(const u32* RESTRICT src, u8* RESTRICT dst, int dstpitch, const GIFRegTEXA& TEXA)
|
||||
{
|
||||
#if _M_SSE >= 0x501
|
||||
|
||||
@@ -1061,7 +1061,7 @@ public:
|
||||
}
|
||||
|
||||
template <bool AEM>
|
||||
static void ExpandBlock16(const uint16* RESTRICT src, uint8* RESTRICT dst, int dstpitch, const GIFRegTEXA& TEXA) // do not inline, uses too many xmm regs
|
||||
static void ExpandBlock16(const u16* RESTRICT src, u8* RESTRICT dst, int dstpitch, const GIFRegTEXA& TEXA) // do not inline, uses too many xmm regs
|
||||
{
|
||||
#if _M_SSE >= 0x501
|
||||
|
||||
@@ -1101,7 +1101,7 @@ public:
|
||||
#endif
|
||||
}
|
||||
|
||||
__forceinline static void ExpandBlock8_32(const uint8* RESTRICT src, uint8* RESTRICT dst, int dstpitch, const uint32* RESTRICT pal)
|
||||
__forceinline static void ExpandBlock8_32(const u8* RESTRICT src, u8* RESTRICT dst, int dstpitch, const u32* RESTRICT pal)
|
||||
{
|
||||
for (int j = 0; j < 16; j++, dst += dstpitch)
|
||||
{
|
||||
@@ -1109,7 +1109,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
__forceinline static void ExpandBlock8_16(const uint8* RESTRICT src, uint8* RESTRICT dst, int dstpitch, const uint32* RESTRICT pal)
|
||||
__forceinline static void ExpandBlock8_16(const u8* RESTRICT src, u8* RESTRICT dst, int dstpitch, const u32* RESTRICT pal)
|
||||
{
|
||||
for (int j = 0; j < 16; j++, dst += dstpitch)
|
||||
{
|
||||
@@ -1117,7 +1117,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
__forceinline static void ExpandBlock4_32(const uint8* RESTRICT src, uint8* RESTRICT dst, int dstpitch, const uint64* RESTRICT pal)
|
||||
__forceinline static void ExpandBlock4_32(const u8* RESTRICT src, u8* RESTRICT dst, int dstpitch, const u64* RESTRICT pal)
|
||||
{
|
||||
for (int j = 0; j < 16; j++, dst += dstpitch)
|
||||
{
|
||||
@@ -1125,7 +1125,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
__forceinline static void ExpandBlock4_16(const uint8* RESTRICT src, uint8* RESTRICT dst, int dstpitch, const uint64* RESTRICT pal)
|
||||
__forceinline static void ExpandBlock4_16(const u8* RESTRICT src, u8* RESTRICT dst, int dstpitch, const u64* RESTRICT pal)
|
||||
{
|
||||
for (int j = 0; j < 16; j++, dst += dstpitch)
|
||||
{
|
||||
@@ -1133,7 +1133,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
__forceinline static void ExpandBlock8H_32(uint32* RESTRICT src, uint8* RESTRICT dst, int dstpitch, const uint32* RESTRICT pal)
|
||||
__forceinline static void ExpandBlock8H_32(u32* RESTRICT src, u8* RESTRICT dst, int dstpitch, const u32* RESTRICT pal)
|
||||
{
|
||||
for (int j = 0; j < 8; j++, dst += dstpitch)
|
||||
{
|
||||
@@ -1144,7 +1144,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
__forceinline static void ExpandBlock8H_16(uint32* RESTRICT src, uint8* RESTRICT dst, int dstpitch, const uint32* RESTRICT pal)
|
||||
__forceinline static void ExpandBlock8H_16(u32* RESTRICT src, u8* RESTRICT dst, int dstpitch, const u32* RESTRICT pal)
|
||||
{
|
||||
for (int j = 0; j < 8; j++, dst += dstpitch)
|
||||
{
|
||||
@@ -1158,7 +1158,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
__forceinline static void ExpandBlock4HL_32(uint32* RESTRICT src, uint8* RESTRICT dst, int dstpitch, const uint32* RESTRICT pal)
|
||||
__forceinline static void ExpandBlock4HL_32(u32* RESTRICT src, u8* RESTRICT dst, int dstpitch, const u32* RESTRICT pal)
|
||||
{
|
||||
for (int j = 0; j < 8; j++, dst += dstpitch)
|
||||
{
|
||||
@@ -1169,7 +1169,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
__forceinline static void ExpandBlock4HL_16(uint32* RESTRICT src, uint8* RESTRICT dst, int dstpitch, const uint32* RESTRICT pal)
|
||||
__forceinline static void ExpandBlock4HL_16(u32* RESTRICT src, u8* RESTRICT dst, int dstpitch, const u32* RESTRICT pal)
|
||||
{
|
||||
for (int j = 0; j < 8; j++, dst += dstpitch)
|
||||
{
|
||||
@@ -1182,7 +1182,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
__forceinline static void ExpandBlock4HH_32(uint32* RESTRICT src, uint8* RESTRICT dst, int dstpitch, const uint32* RESTRICT pal)
|
||||
__forceinline static void ExpandBlock4HH_32(u32* RESTRICT src, u8* RESTRICT dst, int dstpitch, const u32* RESTRICT pal)
|
||||
{
|
||||
for (int j = 0; j < 8; j++, dst += dstpitch)
|
||||
{
|
||||
@@ -1193,7 +1193,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
__forceinline static void ExpandBlock4HH_16(uint32* RESTRICT src, uint8* RESTRICT dst, int dstpitch, const uint32* RESTRICT pal)
|
||||
__forceinline static void ExpandBlock4HH_16(u32* RESTRICT src, u8* RESTRICT dst, int dstpitch, const u32* RESTRICT pal)
|
||||
{
|
||||
for (int j = 0; j < 8; j++, dst += dstpitch)
|
||||
{
|
||||
@@ -1206,14 +1206,14 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
__forceinline static void UnpackAndWriteBlock24(const uint8* RESTRICT src, int srcpitch, uint8* RESTRICT dst)
|
||||
__forceinline static void UnpackAndWriteBlock24(const u8* RESTRICT src, int srcpitch, u8* RESTRICT dst)
|
||||
{
|
||||
#if _M_SSE >= 0x501
|
||||
|
||||
const uint8* RESTRICT s0 = &src[srcpitch * 0];
|
||||
const uint8* RESTRICT s1 = &src[srcpitch * 1];
|
||||
const uint8* RESTRICT s2 = &src[srcpitch * 2];
|
||||
const uint8* RESTRICT s3 = &src[srcpitch * 3];
|
||||
const u8* RESTRICT s0 = &src[srcpitch * 0];
|
||||
const u8* RESTRICT s1 = &src[srcpitch * 1];
|
||||
const u8* RESTRICT s2 = &src[srcpitch * 2];
|
||||
const u8* RESTRICT s3 = &src[srcpitch * 3];
|
||||
|
||||
GSVector8i v0, v1, v2, v3, v4, v5, v6;
|
||||
GSVector8i mask = GSVector8i::x00ffffff();
|
||||
@@ -1293,7 +1293,7 @@ public:
|
||||
#endif
|
||||
}
|
||||
|
||||
__forceinline static void UnpackAndWriteBlock8H(const uint8* RESTRICT src, int srcpitch, uint8* RESTRICT dst)
|
||||
__forceinline static void UnpackAndWriteBlock8H(const u8* RESTRICT src, int srcpitch, u8* RESTRICT dst)
|
||||
{
|
||||
|
||||
#if _M_SSE >= 0x501
|
||||
@@ -1367,13 +1367,13 @@ public:
|
||||
#endif
|
||||
}
|
||||
|
||||
__forceinline static void UnpackAndWriteBlock4HL(const uint8* RESTRICT src, int srcpitch, uint8* RESTRICT dst)
|
||||
__forceinline static void UnpackAndWriteBlock4HL(const u8* RESTRICT src, int srcpitch, u8* RESTRICT dst)
|
||||
{
|
||||
//printf("4HL\n");
|
||||
|
||||
if (0)
|
||||
{
|
||||
uint8* s = (uint8*)src;
|
||||
u8* s = (u8*)src;
|
||||
for (int j = 0; j < 8; j++, s += srcpitch)
|
||||
for (int i = 0; i < 4; i++)
|
||||
s[i] = (columnTable32[j][i * 2] & 0x0f) | (columnTable32[j][i * 2 + 1] << 4);
|
||||
@@ -1385,7 +1385,7 @@ public:
|
||||
GSVector8i v0, v1, v2, v3;
|
||||
GSVector8i mask(0x0f000000);
|
||||
|
||||
v6 = GSVector4i(*(uint32*)&src[srcpitch * 0], *(uint32*)&src[srcpitch * 2], *(uint32*)&src[srcpitch * 1], *(uint32*)&src[srcpitch * 3]);
|
||||
v6 = GSVector4i(*(u32*)&src[srcpitch * 0], *(u32*)&src[srcpitch * 2], *(u32*)&src[srcpitch * 1], *(u32*)&src[srcpitch * 3]);
|
||||
|
||||
v4 = v6.upl8(v6 >> 4);
|
||||
v5 = v6.uph8(v6 >> 4);
|
||||
@@ -1405,7 +1405,7 @@ public:
|
||||
|
||||
src += srcpitch * 4;
|
||||
|
||||
v6 = GSVector4i(*(uint32*)&src[srcpitch * 0], *(uint32*)&src[srcpitch * 2], *(uint32*)&src[srcpitch * 1], *(uint32*)&src[srcpitch * 3]);
|
||||
v6 = GSVector4i(*(u32*)&src[srcpitch * 0], *(u32*)&src[srcpitch * 2], *(u32*)&src[srcpitch * 1], *(u32*)&src[srcpitch * 3]);
|
||||
|
||||
v4 = v6.upl8(v6 >> 4);
|
||||
v5 = v6.uph8(v6 >> 4);
|
||||
@@ -1434,7 +1434,7 @@ public:
|
||||
|
||||
for (int i = 0; i < 2; i++, src += srcpitch * 4)
|
||||
{
|
||||
GSVector4i v(*(uint32*)&src[srcpitch * 0], *(uint32*)&src[srcpitch * 1], *(uint32*)&src[srcpitch * 2], *(uint32*)&src[srcpitch * 3]);
|
||||
GSVector4i v(*(u32*)&src[srcpitch * 0], *(u32*)&src[srcpitch * 1], *(u32*)&src[srcpitch * 2], *(u32*)&src[srcpitch * 3]);
|
||||
|
||||
v4 = v.upl8(v >> 4);
|
||||
v5 = v.uph8(v >> 4);
|
||||
@@ -1463,7 +1463,7 @@ public:
|
||||
#endif
|
||||
}
|
||||
|
||||
__forceinline static void UnpackAndWriteBlock4HH(const uint8* RESTRICT src, int srcpitch, uint8* RESTRICT dst)
|
||||
__forceinline static void UnpackAndWriteBlock4HH(const u8* RESTRICT src, int srcpitch, u8* RESTRICT dst)
|
||||
{
|
||||
|
||||
#if _M_SSE >= 0x501
|
||||
@@ -1472,7 +1472,7 @@ public:
|
||||
GSVector8i v0, v1, v2, v3;
|
||||
GSVector8i mask = GSVector8i::xf0000000();
|
||||
|
||||
v6 = GSVector4i(*(uint32*)&src[srcpitch * 0], *(uint32*)&src[srcpitch * 2], *(uint32*)&src[srcpitch * 1], *(uint32*)&src[srcpitch * 3]);
|
||||
v6 = GSVector4i(*(u32*)&src[srcpitch * 0], *(u32*)&src[srcpitch * 2], *(u32*)&src[srcpitch * 1], *(u32*)&src[srcpitch * 3]);
|
||||
|
||||
v4 = (v6 << 4).upl8(v6);
|
||||
v5 = (v6 << 4).uph8(v6);
|
||||
@@ -1492,7 +1492,7 @@ public:
|
||||
|
||||
src += srcpitch * 4;
|
||||
|
||||
v6 = GSVector4i(*(uint32*)&src[srcpitch * 0], *(uint32*)&src[srcpitch * 2], *(uint32*)&src[srcpitch * 1], *(uint32*)&src[srcpitch * 3]);
|
||||
v6 = GSVector4i(*(u32*)&src[srcpitch * 0], *(u32*)&src[srcpitch * 2], *(u32*)&src[srcpitch * 1], *(u32*)&src[srcpitch * 3]);
|
||||
|
||||
v4 = (v6 << 4).upl8(v6);
|
||||
v5 = (v6 << 4).uph8(v6);
|
||||
@@ -1521,7 +1521,7 @@ public:
|
||||
|
||||
for (int i = 0; i < 2; i++, src += srcpitch * 4)
|
||||
{
|
||||
GSVector4i v(*(uint32*)&src[srcpitch * 0], *(uint32*)&src[srcpitch * 1], *(uint32*)&src[srcpitch * 2], *(uint32*)&src[srcpitch * 3]);
|
||||
GSVector4i v(*(u32*)&src[srcpitch * 0], *(u32*)&src[srcpitch * 1], *(u32*)&src[srcpitch * 2], *(u32*)&src[srcpitch * 3]);
|
||||
|
||||
v4 = (v << 4).upl8(v);
|
||||
v5 = (v << 4).uph8(v);
|
||||
@@ -1551,7 +1551,7 @@ public:
|
||||
}
|
||||
|
||||
template <bool AEM>
|
||||
__forceinline static void ReadAndExpandBlock24(const uint8* RESTRICT src, uint8* RESTRICT dst, int dstpitch, const GIFRegTEXA& TEXA)
|
||||
__forceinline static void ReadAndExpandBlock24(const u8* RESTRICT src, u8* RESTRICT dst, int dstpitch, const GIFRegTEXA& TEXA)
|
||||
{
|
||||
#if _M_SSE >= 0x501
|
||||
|
||||
@@ -1628,7 +1628,7 @@ public:
|
||||
}
|
||||
|
||||
template <bool AEM>
|
||||
__forceinline static void ReadAndExpandBlock16(const uint8* RESTRICT src, uint8* RESTRICT dst, int dstpitch, const GIFRegTEXA& TEXA)
|
||||
__forceinline static void ReadAndExpandBlock16(const u8* RESTRICT src, u8* RESTRICT dst, int dstpitch, const GIFRegTEXA& TEXA)
|
||||
{
|
||||
#if _M_SSE >= 0x501
|
||||
|
||||
@@ -1656,16 +1656,16 @@ public:
|
||||
|
||||
#else
|
||||
|
||||
alignas(32) uint16 block[16 * 8];
|
||||
alignas(32) u16 block[16 * 8];
|
||||
|
||||
ReadBlock16(src, (uint8*)block, sizeof(block) / 8);
|
||||
ReadBlock16(src, (u8*)block, sizeof(block) / 8);
|
||||
|
||||
ExpandBlock16<AEM>(block, dst, dstpitch, TEXA);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
__forceinline static void ReadAndExpandBlock8_32(const uint8* RESTRICT src, uint8* RESTRICT dst, int dstpitch, const uint32* RESTRICT pal)
|
||||
__forceinline static void ReadAndExpandBlock8_32(const u8* RESTRICT src, u8* RESTRICT dst, int dstpitch, const u32* RESTRICT pal)
|
||||
{
|
||||
//printf("ReadAndExpandBlock8_32\n");
|
||||
|
||||
@@ -1714,7 +1714,7 @@ public:
|
||||
|
||||
// TODO: ReadAndExpandBlock8_16
|
||||
|
||||
__forceinline static void ReadAndExpandBlock4_32(const uint8* RESTRICT src, uint8* RESTRICT dst, int dstpitch, const uint64* RESTRICT pal)
|
||||
__forceinline static void ReadAndExpandBlock4_32(const u8* RESTRICT src, u8* RESTRICT dst, int dstpitch, const u64* RESTRICT pal)
|
||||
{
|
||||
//printf("ReadAndExpandBlock4_32\n");
|
||||
|
||||
@@ -1779,7 +1779,7 @@ public:
|
||||
|
||||
// TODO: ReadAndExpandBlock4_16
|
||||
|
||||
__forceinline static void ReadAndExpandBlock8H_32(const uint8* RESTRICT src, uint8* RESTRICT dst, int dstpitch, const uint32* RESTRICT pal)
|
||||
__forceinline static void ReadAndExpandBlock8H_32(const u8* RESTRICT src, u8* RESTRICT dst, int dstpitch, const u32* RESTRICT pal)
|
||||
{
|
||||
//printf("ReadAndExpandBlock8H_32\n");
|
||||
|
||||
@@ -1810,7 +1810,7 @@ public:
|
||||
|
||||
// TODO: ReadAndExpandBlock8H_16
|
||||
|
||||
__forceinline static void ReadAndExpandBlock4HL_32(const uint8* RESTRICT src, uint8* RESTRICT dst, int dstpitch, const uint32* RESTRICT pal)
|
||||
__forceinline static void ReadAndExpandBlock4HL_32(const u8* RESTRICT src, u8* RESTRICT dst, int dstpitch, const u32* RESTRICT pal)
|
||||
{
|
||||
//printf("ReadAndExpandBlock4HL_32\n");
|
||||
const GSVector4i* s = (const GSVector4i*)src;
|
||||
@@ -1840,7 +1840,7 @@ public:
|
||||
|
||||
// TODO: ReadAndExpandBlock4HL_16
|
||||
|
||||
__forceinline static void ReadAndExpandBlock4HH_32(const uint8* RESTRICT src, uint8* RESTRICT dst, int dstpitch, const uint32* RESTRICT pal)
|
||||
__forceinline static void ReadAndExpandBlock4HH_32(const u8* RESTRICT src, u8* RESTRICT dst, int dstpitch, const u32* RESTRICT pal)
|
||||
{
|
||||
//printf("ReadAndExpandBlock4HH_32\n");
|
||||
|
||||
|
||||
+10
-10
@@ -17,7 +17,7 @@
|
||||
#include "GSCapture.h"
|
||||
#include "GSPng.h"
|
||||
#include "GSUtil.h"
|
||||
#include "GS_types.h"
|
||||
#include "GSExtra.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
@@ -126,7 +126,7 @@ GSSource : public CBaseFilter, private CCritSec, public IGSSource
|
||||
vih.bmiHeader.biPlanes = 1;
|
||||
vih.bmiHeader.biBitCount = 16;
|
||||
vih.bmiHeader.biSizeImage = m_size.x * m_size.y * 2;
|
||||
mt.SetFormat((uint8*)&vih, sizeof(vih));
|
||||
mt.SetFormat((u8*)&vih, sizeof(vih));
|
||||
|
||||
m_mts.push_back(mt);
|
||||
|
||||
@@ -139,7 +139,7 @@ GSSource : public CBaseFilter, private CCritSec, public IGSSource
|
||||
vih.bmiHeader.biPlanes = 1;
|
||||
vih.bmiHeader.biBitCount = 32;
|
||||
vih.bmiHeader.biSizeImage = m_size.x * m_size.y * 4;
|
||||
mt.SetFormat((uint8*)&vih, sizeof(vih));
|
||||
mt.SetFormat((u8*)&vih, sizeof(vih));
|
||||
|
||||
if (colorspace == 1)
|
||||
m_mts.insert(m_mts.begin(), mt);
|
||||
@@ -272,8 +272,8 @@ public:
|
||||
|
||||
const CMediaType& mt = m_output->CurrentMediaType();
|
||||
|
||||
uint8* src = (uint8*)bits;
|
||||
uint8* dst = NULL;
|
||||
u8* src = (u8*)bits;
|
||||
u8* dst = NULL;
|
||||
|
||||
sample->GetPointer(&dst);
|
||||
|
||||
@@ -300,8 +300,8 @@ public:
|
||||
|
||||
for (int j = 0; j < h; j++, dst += dstpitch, src += srcpitch)
|
||||
{
|
||||
uint32* s = (uint32*)src;
|
||||
uint16* d = (uint16*)dst;
|
||||
u32* s = (u32*)src;
|
||||
u16* d = (u16*)dst;
|
||||
|
||||
for (int i = 0; i < w; i += 2)
|
||||
{
|
||||
@@ -314,7 +314,7 @@ public:
|
||||
|
||||
GSVector4 c = lo.hadd(hi) + offset;
|
||||
|
||||
*((uint32*)&d[i]) = GSVector4i(c).rgba32();
|
||||
*((u32*)&d[i]) = GSVector4i(c).rgba32();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -568,8 +568,8 @@ bool GSCapture::DeliverFrame(const void* bits, int pitch, bool rgba)
|
||||
#elif defined(__unix__)
|
||||
|
||||
std::string out_file = m_out_dir + format("/frame.%010d.png", m_frame);
|
||||
//GSPng::Save(GSPng::RGB_PNG, out_file, (uint8*)bits, m_size.x, m_size.y, pitch, m_compression_level);
|
||||
m_workers[m_frame % m_threads]->Push(std::make_shared<GSPng::Transaction>(GSPng::RGB_PNG, out_file, static_cast<const uint8*>(bits), m_size.x, m_size.y, pitch, m_compression_level));
|
||||
//GSPng::Save(GSPng::RGB_PNG, out_file, (u8*)bits, m_size.x, m_size.y, pitch, m_compression_level);
|
||||
m_workers[m_frame % m_threads]->Push(std::make_shared<GSPng::Transaction>(GSPng::RGB_PNG, out_file, static_cast<const u8*>(bits), m_size.x, m_size.y, pitch, m_compression_level));
|
||||
|
||||
m_frame++;
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ class GSCapture
|
||||
std::recursive_mutex m_lock;
|
||||
bool m_capturing;
|
||||
GSVector2i m_size;
|
||||
uint64 m_frame;
|
||||
u64 m_frame;
|
||||
std::string m_out_dir;
|
||||
int m_threads;
|
||||
|
||||
|
||||
+59
-82
@@ -16,17 +16,18 @@
|
||||
#include "PrecompiledHeader.h"
|
||||
#include "GSClut.h"
|
||||
#include "GSLocalMemory.h"
|
||||
#include "GSGL.h"
|
||||
|
||||
#define CLUT_ALLOC_SIZE (2 * 4096)
|
||||
|
||||
GSClut::GSClut(GSLocalMemory* mem)
|
||||
: m_mem(mem)
|
||||
{
|
||||
uint8* p = (uint8*)vmalloc(CLUT_ALLOC_SIZE, false);
|
||||
u8* p = (u8*)vmalloc(CLUT_ALLOC_SIZE, false);
|
||||
|
||||
m_clut = (uint16*)&p[0]; // 1k + 1k for mirrored area simulating wrapping memory
|
||||
m_buff32 = (uint32*)&p[2048]; // 1k
|
||||
m_buff64 = (uint64*)&p[4096]; // 2k
|
||||
m_clut = (u16*)&p[0]; // 1k + 1k for mirrored area simulating wrapping memory
|
||||
m_buff32 = (u32*)&p[2048]; // 1k
|
||||
m_buff64 = (u64*)&p[4096]; // 2k
|
||||
m_write.dirty = true;
|
||||
m_read.dirty = true;
|
||||
|
||||
@@ -107,7 +108,7 @@ void GSClut::Invalidate()
|
||||
m_write.dirty = true;
|
||||
}
|
||||
|
||||
void GSClut::Invalidate(uint32 block)
|
||||
void GSClut::Invalidate(u32 block)
|
||||
{
|
||||
if (block == m_write.TEX0.CBP)
|
||||
{
|
||||
@@ -158,113 +159,83 @@ void GSClut::Write(const GIFRegTEX0& TEX0, const GIFRegTEXCLUT& TEXCLUT)
|
||||
m_read.dirty = true;
|
||||
|
||||
(this->*m_wc[TEX0.CSM][TEX0.CPSM][TEX0.PSM])(TEX0, TEXCLUT);
|
||||
|
||||
// Mirror write to other half of buffer to simulate wrapping memory
|
||||
|
||||
int offset = (TEX0.CSA & (TEX0.CPSM < PSM_PSMCT16 ? 15 : 31)) * 16;
|
||||
|
||||
if (TEX0.PSM == PSM_PSMT8 || TEX0.PSM == PSM_PSMT8H)
|
||||
{
|
||||
int size = TEX0.CPSM < PSM_PSMCT16 ? 512 : 256;
|
||||
|
||||
memcpy(m_clut + 512 + offset, m_clut + offset, sizeof(*m_clut) * std::min(size, 512 - offset));
|
||||
memcpy(m_clut, m_clut + 512, sizeof(*m_clut) * std::max(0, size + offset - 512));
|
||||
}
|
||||
else
|
||||
{
|
||||
int size = 16;
|
||||
|
||||
memcpy(m_clut + 512 + offset, m_clut + offset, sizeof(*m_clut) * size);
|
||||
|
||||
if (TEX0.CPSM < PSM_PSMCT16)
|
||||
{
|
||||
memcpy(m_clut + 512 + 256 + offset, m_clut + 256 + offset, sizeof(*m_clut) * size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GSClut::WriteCLUT32_I8_CSM1(const GIFRegTEX0& TEX0, const GIFRegTEXCLUT& TEXCLUT)
|
||||
{
|
||||
ALIGN_STACK(32);
|
||||
//FIXME: Romance of the Three Kingdoms VIII text doesn't like the offset
|
||||
WriteCLUT_T32_I8_CSM1((uint32*)m_mem->BlockPtr32(0, 0, TEX0.CBP, 1), m_clut + ((TEX0.CSA & 15) << 4));
|
||||
WriteCLUT_T32_I8_CSM1((u32*)m_mem->BlockPtr32(0, 0, TEX0.CBP, 1), m_clut, (TEX0.CSA & 15));
|
||||
}
|
||||
|
||||
void GSClut::WriteCLUT32_I4_CSM1(const GIFRegTEX0& TEX0, const GIFRegTEXCLUT& TEXCLUT)
|
||||
{
|
||||
ALIGN_STACK(32);
|
||||
|
||||
WriteCLUT_T32_I4_CSM1((uint32*)m_mem->BlockPtr32(0, 0, TEX0.CBP, 1), m_clut + ((TEX0.CSA & 15) << 4));
|
||||
WriteCLUT_T32_I4_CSM1((u32*)m_mem->BlockPtr32(0, 0, TEX0.CBP, 1), m_clut + ((TEX0.CSA & 15) << 4));
|
||||
}
|
||||
|
||||
void GSClut::WriteCLUT16_I8_CSM1(const GIFRegTEX0& TEX0, const GIFRegTEXCLUT& TEXCLUT)
|
||||
{
|
||||
WriteCLUT_T16_I8_CSM1((uint16*)m_mem->BlockPtr16(0, 0, TEX0.CBP, 1), m_clut + (TEX0.CSA << 4));
|
||||
WriteCLUT_T16_I8_CSM1((u16*)m_mem->BlockPtr16(0, 0, TEX0.CBP, 1), m_clut + (TEX0.CSA << 4));
|
||||
}
|
||||
|
||||
void GSClut::WriteCLUT16_I4_CSM1(const GIFRegTEX0& TEX0, const GIFRegTEXCLUT& TEXCLUT)
|
||||
{
|
||||
WriteCLUT_T16_I4_CSM1((uint16*)m_mem->BlockPtr16(0, 0, TEX0.CBP, 1), m_clut + (TEX0.CSA << 4));
|
||||
WriteCLUT_T16_I4_CSM1((u16*)m_mem->BlockPtr16(0, 0, TEX0.CBP, 1), m_clut + (TEX0.CSA << 4));
|
||||
}
|
||||
|
||||
void GSClut::WriteCLUT16S_I8_CSM1(const GIFRegTEX0& TEX0, const GIFRegTEXCLUT& TEXCLUT)
|
||||
{
|
||||
WriteCLUT_T16_I8_CSM1((uint16*)m_mem->BlockPtr16S(0, 0, TEX0.CBP, 1), m_clut + (TEX0.CSA << 4));
|
||||
WriteCLUT_T16_I8_CSM1((u16*)m_mem->BlockPtr16S(0, 0, TEX0.CBP, 1), m_clut + (TEX0.CSA << 4));
|
||||
}
|
||||
|
||||
void GSClut::WriteCLUT16S_I4_CSM1(const GIFRegTEX0& TEX0, const GIFRegTEXCLUT& TEXCLUT)
|
||||
{
|
||||
WriteCLUT_T16_I4_CSM1((uint16*)m_mem->BlockPtr16S(0, 0, TEX0.CBP, 1), m_clut + (TEX0.CSA << 4));
|
||||
WriteCLUT_T16_I4_CSM1((u16*)m_mem->BlockPtr16S(0, 0, TEX0.CBP, 1), m_clut + (TEX0.CSA << 4));
|
||||
}
|
||||
|
||||
template <int n>
|
||||
void GSClut::WriteCLUT32_CSM2(const GIFRegTEX0& TEX0, const GIFRegTEXCLUT& TEXCLUT)
|
||||
{
|
||||
GSOffset* off = m_mem->GetOffset(TEX0.CBP, TEXCLUT.CBW, PSM_PSMCT32);
|
||||
GSOffset off = GSOffset::fromKnownPSM(TEX0.CBP, TEXCLUT.CBW, PSM_PSMCT32);
|
||||
auto pa = off.paMulti(m_mem->m_vm32, TEXCLUT.COU << 4, TEXCLUT.COV);
|
||||
|
||||
uint32* RESTRICT s = &m_mem->m_vm32[off->pixel.row[TEXCLUT.COV]];
|
||||
int* RESTRICT col = &off->pixel.col[0][TEXCLUT.COU << 4];
|
||||
|
||||
uint16* RESTRICT clut = m_clut + ((TEX0.CSA & 15) << 4);
|
||||
u16* RESTRICT clut = m_clut + ((TEX0.CSA & 15) << 4);
|
||||
|
||||
for (int i = 0; i < n; i++)
|
||||
{
|
||||
uint32 c = s[col[i]];
|
||||
u32 c = *pa.value(i);
|
||||
|
||||
clut[i] = (uint16)(c & 0xffff);
|
||||
clut[i + 256] = (uint16)(c >> 16);
|
||||
clut[i] = (u16)(c & 0xffff);
|
||||
clut[i + 256] = (u16)(c >> 16);
|
||||
}
|
||||
}
|
||||
|
||||
template <int n>
|
||||
void GSClut::WriteCLUT16_CSM2(const GIFRegTEX0& TEX0, const GIFRegTEXCLUT& TEXCLUT)
|
||||
{
|
||||
GSOffset* off = m_mem->GetOffset(TEX0.CBP, TEXCLUT.CBW, PSM_PSMCT16);
|
||||
GSOffset off = GSOffset::fromKnownPSM(TEX0.CBP, TEXCLUT.CBW, PSM_PSMCT16);
|
||||
auto pa = off.paMulti(m_mem->m_vm16, TEXCLUT.COU << 4, TEXCLUT.COV);
|
||||
|
||||
uint16* RESTRICT s = &m_mem->m_vm16[off->pixel.row[TEXCLUT.COV]];
|
||||
int* RESTRICT col = &off->pixel.col[0][TEXCLUT.COU << 4];
|
||||
|
||||
uint16* RESTRICT clut = m_clut + (TEX0.CSA << 4);
|
||||
u16* RESTRICT clut = m_clut + (TEX0.CSA << 4);
|
||||
|
||||
for (int i = 0; i < n; i++)
|
||||
{
|
||||
clut[i] = s[col[i]];
|
||||
clut[i] = *pa.value(i);
|
||||
}
|
||||
}
|
||||
|
||||
template <int n>
|
||||
void GSClut::WriteCLUT16S_CSM2(const GIFRegTEX0& TEX0, const GIFRegTEXCLUT& TEXCLUT)
|
||||
{
|
||||
GSOffset* off = m_mem->GetOffset(TEX0.CBP, TEXCLUT.CBW, PSM_PSMCT16S);
|
||||
GSOffset off = GSOffset::fromKnownPSM(TEX0.CBP, TEXCLUT.CBW, PSM_PSMCT16S);
|
||||
auto pa = off.paMulti(m_mem->m_vm16, TEXCLUT.COU << 4, TEXCLUT.COV);
|
||||
|
||||
uint16* RESTRICT s = &m_mem->m_vm16[off->pixel.row[TEXCLUT.COV]];
|
||||
int* RESTRICT col = &off->pixel.col[0][TEXCLUT.COU << 4];
|
||||
|
||||
uint16* RESTRICT clut = m_clut + (TEX0.CSA << 4);
|
||||
u16* RESTRICT clut = m_clut + (TEX0.CSA << 4);
|
||||
|
||||
for (int i = 0; i < n; i++)
|
||||
{
|
||||
clut[i] = s[col[i]];
|
||||
clut[i] = *pa.value(i);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -282,7 +253,7 @@ void GSClut::Read(const GIFRegTEX0& TEX0)
|
||||
m_read.TEX0 = TEX0;
|
||||
m_read.dirty = false;
|
||||
|
||||
uint16* clut = m_clut;
|
||||
u16* clut = m_clut;
|
||||
|
||||
if(TEX0.CPSM == PSM_PSMCT32 || TEX0.CPSM == PSM_PSMCT24)
|
||||
{
|
||||
@@ -331,7 +302,7 @@ void GSClut::Read32(const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA)
|
||||
m_read.dirty = false;
|
||||
m_read.adirty = true;
|
||||
|
||||
uint16* clut = m_clut;
|
||||
u16* clut = m_clut;
|
||||
|
||||
if (TEX0.CPSM == PSM_PSMCT32 || TEX0.CPSM == PSM_PSMCT24)
|
||||
{
|
||||
@@ -339,8 +310,7 @@ void GSClut::Read32(const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA)
|
||||
{
|
||||
case PSM_PSMT8:
|
||||
case PSM_PSMT8H:
|
||||
clut += (TEX0.CSA & 15) << 4; // disney golf title screen
|
||||
ReadCLUT_T32_I8(clut, m_buff32);
|
||||
ReadCLUT_T32_I8(clut, m_buff32, (TEX0.CSA & 15) << 4);
|
||||
break;
|
||||
case PSM_PSMT4:
|
||||
case PSM_PSMT4HL:
|
||||
@@ -348,7 +318,7 @@ void GSClut::Read32(const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA)
|
||||
clut += (TEX0.CSA & 15) << 4;
|
||||
// TODO: merge these functions
|
||||
ReadCLUT_T32_I4(clut, m_buff32);
|
||||
ExpandCLUT64_T32_I8(m_buff32, (uint64*)m_buff64); // sw renderer does not need m_buff64 anymore
|
||||
ExpandCLUT64_T32_I8(m_buff32, (u64*)m_buff64); // sw renderer does not need m_buff64 anymore
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -367,7 +337,7 @@ void GSClut::Read32(const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA)
|
||||
clut += TEX0.CSA << 4;
|
||||
// TODO: merge these functions
|
||||
Expand16(clut, m_buff32, 16, TEXA);
|
||||
ExpandCLUT64_T32_I8(m_buff32, (uint64*)m_buff64); // sw renderer does not need m_buff64 anymore
|
||||
ExpandCLUT64_T32_I8(m_buff32, (u64*)m_buff64); // sw renderer does not need m_buff64 anymore
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -443,20 +413,20 @@ void GSClut::GetAlphaMinMax32(int& amin_out, int& amax_out)
|
||||
|
||||
//
|
||||
|
||||
void GSClut::WriteCLUT_T32_I8_CSM1(const uint32* RESTRICT src, uint16* RESTRICT clut)
|
||||
void GSClut::WriteCLUT_T32_I8_CSM1(const u32* RESTRICT src, u16* RESTRICT clut, u16 offset)
|
||||
{
|
||||
// 4 blocks
|
||||
|
||||
for (int i = 0; i < 64; i += 16)
|
||||
// This is required when CSA is offset from the base of the CLUT so we point to the right data
|
||||
for (int i = offset; i < 16; i ++)
|
||||
{
|
||||
WriteCLUT_T32_I4_CSM1(&src[i + 0], &clut[i * 2 + 0]);
|
||||
WriteCLUT_T32_I4_CSM1(&src[i + 64], &clut[i * 2 + 16]);
|
||||
WriteCLUT_T32_I4_CSM1(&src[i + 128], &clut[i * 2 + 128]);
|
||||
WriteCLUT_T32_I4_CSM1(&src[i + 192], &clut[i * 2 + 144]);
|
||||
const int off = i << 4; // WriteCLUT_T32_I4_CSM1 loads 16 at a time
|
||||
// Source column
|
||||
const int s = clutTableT32I8[off & 0x70] | (off & 0x80);
|
||||
|
||||
WriteCLUT_T32_I4_CSM1(&src[s], &clut[off]);
|
||||
}
|
||||
}
|
||||
|
||||
__forceinline void GSClut::WriteCLUT_T32_I4_CSM1(const uint32* RESTRICT src, uint16* RESTRICT clut)
|
||||
__forceinline void GSClut::WriteCLUT_T32_I4_CSM1(const u32* RESTRICT src, u16* RESTRICT clut)
|
||||
{
|
||||
// 1 block
|
||||
|
||||
@@ -497,7 +467,7 @@ __forceinline void GSClut::WriteCLUT_T32_I4_CSM1(const uint32* RESTRICT src, uin
|
||||
#endif
|
||||
}
|
||||
|
||||
void GSClut::WriteCLUT_T16_I8_CSM1(const uint16* RESTRICT src, uint16* RESTRICT clut)
|
||||
void GSClut::WriteCLUT_T16_I8_CSM1(const u16* RESTRICT src, u16* RESTRICT clut)
|
||||
{
|
||||
// 2 blocks
|
||||
|
||||
@@ -522,7 +492,7 @@ void GSClut::WriteCLUT_T16_I8_CSM1(const uint16* RESTRICT src, uint16* RESTRICT
|
||||
}
|
||||
}
|
||||
|
||||
__forceinline void GSClut::WriteCLUT_T16_I4_CSM1(const uint16* RESTRICT src, uint16* RESTRICT clut)
|
||||
__forceinline void GSClut::WriteCLUT_T16_I4_CSM1(const u16* RESTRICT src, u16* RESTRICT clut)
|
||||
{
|
||||
// 1 block (half)
|
||||
|
||||
@@ -532,15 +502,22 @@ __forceinline void GSClut::WriteCLUT_T16_I4_CSM1(const uint16* RESTRICT src, uin
|
||||
}
|
||||
}
|
||||
|
||||
void GSClut::ReadCLUT_T32_I8(const uint16* RESTRICT clut, uint32* RESTRICT dst)
|
||||
void GSClut::ReadCLUT_T32_I8(const u16* RESTRICT clut, u32* RESTRICT dst, int offset)
|
||||
{
|
||||
// Okay this deserves a small explanation
|
||||
// T32 I8 can address up to 256 colors however the offset can be "more than zero" when reading
|
||||
// Previously I assumed that it would wrap around the end of the buffer to the beginning
|
||||
// but it turns out this is incorrect, the address doesn't mirror, it clamps to to the last offset,
|
||||
// probably though some sort of addressing mechanism then picks the color from the lower 0xF of the requested CLUT entry.
|
||||
// if we don't do this, the dirt on GTA SA goes transparent and actually cleans the car driving through dirt.
|
||||
for (int i = 0; i < 256; i += 16)
|
||||
{
|
||||
ReadCLUT_T32_I4(&clut[i], &dst[i]);
|
||||
// Min value + offet or Last CSA * 16 (240)
|
||||
ReadCLUT_T32_I4(&clut[std::min((i + offset), 240)], &dst[i]);
|
||||
}
|
||||
}
|
||||
|
||||
__forceinline void GSClut::ReadCLUT_T32_I4(const uint16* RESTRICT clut, uint32* RESTRICT dst)
|
||||
__forceinline void GSClut::ReadCLUT_T32_I4(const u16* RESTRICT clut, u32* RESTRICT dst)
|
||||
{
|
||||
GSVector4i* s = (GSVector4i*)clut;
|
||||
GSVector4i* d = (GSVector4i*)dst;
|
||||
@@ -559,7 +536,7 @@ __forceinline void GSClut::ReadCLUT_T32_I4(const uint16* RESTRICT clut, uint32*
|
||||
}
|
||||
|
||||
#if 0
|
||||
__forceinline void GSClut::ReadCLUT_T32_I4(const uint16* RESTRICT clut, uint32* RESTRICT dst32, uint64* RESTRICT dst64)
|
||||
__forceinline void GSClut::ReadCLUT_T32_I4(const u16* RESTRICT clut, u32* RESTRICT dst32, u64* RESTRICT dst64)
|
||||
{
|
||||
GSVector4i* s = (GSVector4i*)clut;
|
||||
GSVector4i* d32 = (GSVector4i*)dst32;
|
||||
@@ -585,7 +562,7 @@ __forceinline void GSClut::ReadCLUT_T32_I4(const uint16* RESTRICT clut, uint32*
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
void GSClut::ReadCLUT_T16_I8(const uint16* RESTRICT clut, uint32* RESTRICT dst)
|
||||
void GSClut::ReadCLUT_T16_I8(const u16* RESTRICT clut, u32* RESTRICT dst)
|
||||
{
|
||||
for(int i = 0; i < 256; i += 16)
|
||||
{
|
||||
@@ -595,7 +572,7 @@ void GSClut::ReadCLUT_T16_I8(const uint16* RESTRICT clut, uint32* RESTRICT dst)
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
__forceinline void GSClut::ReadCLUT_T16_I4(const uint16* RESTRICT clut, uint32* RESTRICT dst)
|
||||
__forceinline void GSClut::ReadCLUT_T16_I4(const u16* RESTRICT clut, u32* RESTRICT dst)
|
||||
{
|
||||
GSVector4i* s = (GSVector4i*)clut;
|
||||
GSVector4i* d = (GSVector4i*)dst;
|
||||
@@ -611,7 +588,7 @@ __forceinline void GSClut::ReadCLUT_T16_I4(const uint16* RESTRICT clut, uint32*
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
__forceinline void GSClut::ReadCLUT_T16_I4(const uint16* RESTRICT clut, uint32* RESTRICT dst32, uint64* RESTRICT dst64)
|
||||
__forceinline void GSClut::ReadCLUT_T16_I4(const u16* RESTRICT clut, u32* RESTRICT dst32, u64* RESTRICT dst64)
|
||||
{
|
||||
GSVector4i* s = (GSVector4i*)clut;
|
||||
GSVector4i* d32 = (GSVector4i*)dst32;
|
||||
@@ -637,7 +614,7 @@ __forceinline void GSClut::ReadCLUT_T16_I4(const uint16* RESTRICT clut, uint32*
|
||||
}
|
||||
#endif
|
||||
|
||||
void GSClut::ExpandCLUT64_T32_I8(const uint32* RESTRICT src, uint64* RESTRICT dst)
|
||||
void GSClut::ExpandCLUT64_T32_I8(const u32* RESTRICT src, u64* RESTRICT dst)
|
||||
{
|
||||
GSVector4i* s = (GSVector4i*)src;
|
||||
GSVector4i* d = (GSVector4i*)dst;
|
||||
@@ -680,7 +657,7 @@ __forceinline void GSClut::ExpandCLUT64_T32(const GSVector4i& hi, const GSVector
|
||||
}
|
||||
|
||||
#if 0
|
||||
void GSClut::ExpandCLUT64_T16_I8(const uint32* RESTRICT src, uint64* RESTRICT dst)
|
||||
void GSClut::ExpandCLUT64_T16_I8(const u32* RESTRICT src, u64* RESTRICT dst)
|
||||
{
|
||||
GSVector4i* s = (GSVector4i*)src;
|
||||
GSVector4i* d = (GSVector4i*)dst;
|
||||
@@ -729,7 +706,7 @@ CONSTINIT const GSVector4i GSClut::m_bm = GSVector4i::cxpr(0x00007c00);
|
||||
CONSTINIT const GSVector4i GSClut::m_gm = GSVector4i::cxpr(0x000003e0);
|
||||
CONSTINIT const GSVector4i GSClut::m_rm = GSVector4i::cxpr(0x0000001f);
|
||||
|
||||
void GSClut::Expand16(const uint16* RESTRICT src, uint32* RESTRICT dst, int w, const GIFRegTEXA& TEXA)
|
||||
void GSClut::Expand16(const u16* RESTRICT src, u32* RESTRICT dst, int w, const GIFRegTEXA& TEXA)
|
||||
{
|
||||
ASSERT((w & 7) == 0);
|
||||
|
||||
|
||||
+22
-22
@@ -15,7 +15,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "GS.h"
|
||||
#include "GSRegs.h"
|
||||
#include "GSVector.h"
|
||||
#include "GSTables.h"
|
||||
#include "GSAlignedClass.h"
|
||||
@@ -30,10 +30,10 @@ class alignas(32) GSClut : public GSAlignedClass<32>
|
||||
|
||||
GSLocalMemory* m_mem;
|
||||
|
||||
uint32 m_CBP[2];
|
||||
uint16* m_clut;
|
||||
uint32* m_buff32;
|
||||
uint64* m_buff64;
|
||||
u32 m_CBP[2];
|
||||
u16* m_clut;
|
||||
u32* m_buff32;
|
||||
u64* m_buff64;
|
||||
|
||||
struct alignas(32) WriteState
|
||||
{
|
||||
@@ -74,42 +74,42 @@ class alignas(32) GSClut : public GSAlignedClass<32>
|
||||
|
||||
void WriteCLUT_NULL(const GIFRegTEX0& TEX0, const GIFRegTEXCLUT& TEXCLUT);
|
||||
|
||||
static void WriteCLUT_T32_I8_CSM1(const uint32* RESTRICT src, uint16* RESTRICT clut);
|
||||
static void WriteCLUT_T32_I4_CSM1(const uint32* RESTRICT src, uint16* RESTRICT clut);
|
||||
static void WriteCLUT_T16_I8_CSM1(const uint16* RESTRICT src, uint16* RESTRICT clut);
|
||||
static void WriteCLUT_T16_I4_CSM1(const uint16* RESTRICT src, uint16* RESTRICT clut);
|
||||
static void ReadCLUT_T32_I8(const uint16* RESTRICT clut, uint32* RESTRICT dst);
|
||||
static void ReadCLUT_T32_I4(const uint16* RESTRICT clut, uint32* RESTRICT dst);
|
||||
//static void ReadCLUT_T32_I4(const uint16* RESTRICT clut, uint32* RESTRICT dst32, uint64* RESTRICT dst64);
|
||||
//static void ReadCLUT_T16_I8(const uint16* RESTRICT clut, uint32* RESTRICT dst);
|
||||
//static void ReadCLUT_T16_I4(const uint16* RESTRICT clut, uint32* RESTRICT dst);
|
||||
//static void ReadCLUT_T16_I4(const uint16* RESTRICT clut, uint32* RESTRICT dst32, uint64* RESTRICT dst64);
|
||||
static void WriteCLUT_T32_I8_CSM1(const u32* RESTRICT src, u16* RESTRICT clut, u16 offset);
|
||||
static void WriteCLUT_T32_I4_CSM1(const u32* RESTRICT src, u16* RESTRICT clut);
|
||||
static void WriteCLUT_T16_I8_CSM1(const u16* RESTRICT src, u16* RESTRICT clut);
|
||||
static void WriteCLUT_T16_I4_CSM1(const u16* RESTRICT src, u16* RESTRICT clut);
|
||||
static void ReadCLUT_T32_I8(const u16* RESTRICT clut, u32* RESTRICT dst, int offset);
|
||||
static void ReadCLUT_T32_I4(const u16* RESTRICT clut, u32* RESTRICT dst);
|
||||
//static void ReadCLUT_T32_I4(const u16* RESTRICT clut, u32* RESTRICT dst32, u64* RESTRICT dst64);
|
||||
//static void ReadCLUT_T16_I8(const u16* RESTRICT clut, u32* RESTRICT dst);
|
||||
//static void ReadCLUT_T16_I4(const u16* RESTRICT clut, u32* RESTRICT dst);
|
||||
//static void ReadCLUT_T16_I4(const u16* RESTRICT clut, u32* RESTRICT dst32, u64* RESTRICT dst64);
|
||||
public:
|
||||
static void ExpandCLUT64_T32_I8(const uint32* RESTRICT src, uint64* RESTRICT dst);
|
||||
static void ExpandCLUT64_T32_I8(const u32* RESTRICT src, u64* RESTRICT dst);
|
||||
|
||||
private:
|
||||
static void ExpandCLUT64_T32(const GSVector4i& hi, const GSVector4i& lo0, const GSVector4i& lo1, const GSVector4i& lo2, const GSVector4i& lo3, GSVector4i* dst);
|
||||
static void ExpandCLUT64_T32(const GSVector4i& hi, const GSVector4i& lo, GSVector4i* dst);
|
||||
//static void ExpandCLUT64_T16_I8(const uint32* RESTRICT src, uint64* RESTRICT dst);
|
||||
//static void ExpandCLUT64_T16_I8(const u32* RESTRICT src, u64* RESTRICT dst);
|
||||
static void ExpandCLUT64_T16(const GSVector4i& hi, const GSVector4i& lo0, const GSVector4i& lo1, const GSVector4i& lo2, const GSVector4i& lo3, GSVector4i* dst);
|
||||
static void ExpandCLUT64_T16(const GSVector4i& hi, const GSVector4i& lo, GSVector4i* dst);
|
||||
|
||||
static void Expand16(const uint16* RESTRICT src, uint32* RESTRICT dst, int w, const GIFRegTEXA& TEXA);
|
||||
static void Expand16(const u16* RESTRICT src, u32* RESTRICT dst, int w, const GIFRegTEXA& TEXA);
|
||||
|
||||
public:
|
||||
GSClut(GSLocalMemory* mem);
|
||||
virtual ~GSClut();
|
||||
|
||||
void Invalidate();
|
||||
void Invalidate(uint32 block);
|
||||
void Invalidate(u32 block);
|
||||
bool WriteTest(const GIFRegTEX0& TEX0, const GIFRegTEXCLUT& TEXCLUT);
|
||||
void Write(const GIFRegTEX0& TEX0, const GIFRegTEXCLUT& TEXCLUT);
|
||||
//void Read(const GIFRegTEX0& TEX0);
|
||||
void Read32(const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA);
|
||||
void GetAlphaMinMax32(int& amin, int& amax);
|
||||
|
||||
uint32 operator[](size_t i) const { return m_buff32[i]; }
|
||||
u32 operator[](size_t i) const { return m_buff32[i]; }
|
||||
|
||||
operator const uint32*() const { return m_buff32; }
|
||||
operator const uint64*() const { return m_buff64; }
|
||||
operator const u32*() const { return m_buff32; }
|
||||
operator const u64*() const { return m_buff64; }
|
||||
};
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
#include "PrecompiledHeader.h"
|
||||
#include "GSCodeBuffer.h"
|
||||
#include "GS_types.h"
|
||||
#include "GSExtra.h"
|
||||
|
||||
GSCodeBuffer::GSCodeBuffer(size_t blocksize)
|
||||
: m_blocksize(blocksize)
|
||||
@@ -42,14 +42,14 @@ void* GSCodeBuffer::GetBuffer(size_t size)
|
||||
|
||||
if (m_ptr == NULL || m_pos + size > m_blocksize)
|
||||
{
|
||||
m_ptr = (uint8*)vmalloc(m_blocksize, true);
|
||||
m_ptr = (u8*)vmalloc(m_blocksize, true);
|
||||
|
||||
m_pos = 0;
|
||||
|
||||
m_buffers.push_back(m_ptr);
|
||||
}
|
||||
|
||||
uint8* ptr = &m_ptr[m_pos];
|
||||
u8* ptr = &m_ptr[m_pos];
|
||||
|
||||
m_reserved = size;
|
||||
|
||||
|
||||
@@ -15,14 +15,12 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "GS_types.h"
|
||||
|
||||
class GSCodeBuffer
|
||||
{
|
||||
std::vector<void*> m_buffers;
|
||||
size_t m_blocksize;
|
||||
size_t m_pos, m_reserved;
|
||||
uint8* m_ptr;
|
||||
u8* m_ptr;
|
||||
|
||||
public:
|
||||
GSCodeBuffer(size_t blocksize = 4096 * 64); // 256k
|
||||
|
||||
+12
-11
@@ -14,10 +14,11 @@
|
||||
*/
|
||||
|
||||
#include "PrecompiledHeader.h"
|
||||
#include "GS.h"
|
||||
#include "GSCrc.h"
|
||||
#include "GSExtra.h"
|
||||
#include "GS.h"
|
||||
|
||||
CRC::Game CRC::m_games[] =
|
||||
const CRC::Game CRC::m_games[] =
|
||||
{
|
||||
// Note: IDs 0x7ACF7E03, 0x7D4EA48F, 0x37C53760 - shouldn't be added as it's from the multiloaders when packing games.
|
||||
{0x00000000, NoTitle, NoRegion, 0},
|
||||
@@ -505,7 +506,7 @@ CRC::Game CRC::m_games[] =
|
||||
{0xB1BE3E51, Whiplash, EU, 0},
|
||||
};
|
||||
|
||||
std::map<uint32, CRC::Game*> CRC::m_map;
|
||||
std::map<u32, const CRC::Game*> CRC::m_map;
|
||||
|
||||
std::string ToLower(std::string str)
|
||||
{
|
||||
@@ -517,14 +518,14 @@ std::string ToLower(std::string str)
|
||||
// The list is case insensitive and order insensitive.
|
||||
// E.g. Disable all CRC hacks: CrcHacksExclusions=all
|
||||
// E.g. Disable hacks for these CRCs: CrcHacksExclusions=0x0F0C4A9C, 0x0EE5646B, 0x7ACF7E03
|
||||
bool IsCrcExcluded(std::string exclusionList, uint32 crc)
|
||||
bool IsCrcExcluded(std::string exclusionList, u32 crc)
|
||||
{
|
||||
std::string target = format("0x%08x", crc);
|
||||
exclusionList = ToLower(exclusionList);
|
||||
return exclusionList.find(target) != std::string::npos || exclusionList.find("all") != std::string::npos;
|
||||
}
|
||||
|
||||
CRC::Game CRC::Lookup(uint32 crc)
|
||||
const CRC::Game& CRC::Lookup(u32 crc)
|
||||
{
|
||||
printf("GS Lookup CRC:%08X\n", crc);
|
||||
if (m_map.empty())
|
||||
@@ -533,20 +534,20 @@ CRC::Game CRC::Lookup(uint32 crc)
|
||||
if (exclusions.length() != 0)
|
||||
printf("GS: CrcHacksExclusions: %s\n", exclusions.c_str());
|
||||
int crcDups = 0;
|
||||
for (size_t i = 0; i < countof(m_games); i++)
|
||||
for (const Game& game : m_games)
|
||||
{
|
||||
if (!IsCrcExcluded(exclusions, m_games[i].crc))
|
||||
if (!IsCrcExcluded(exclusions, game.crc))
|
||||
{
|
||||
if (m_map[m_games[i].crc])
|
||||
if (m_map[game.crc])
|
||||
{
|
||||
printf("[FIXME] GS: Duplicate CRC: 0x%08X: (game-id/region-id) %d/%d overrides %d/%d\n", m_games[i].crc, m_games[i].title, m_games[i].region, m_map[m_games[i].crc]->title, m_map[m_games[i].crc]->region);
|
||||
printf("[FIXME] GS: Duplicate CRC: 0x%08X: (game-id/region-id) %d/%d overrides %d/%d\n", game.crc, game.title, game.region, m_map[game.crc]->title, m_map[game.crc]->region);
|
||||
crcDups++;
|
||||
}
|
||||
|
||||
m_map[m_games[i].crc] = &m_games[i];
|
||||
m_map[game.crc] = &game;
|
||||
}
|
||||
//else
|
||||
// printf( "GS: excluding CRC hack for 0x%08x\n", m_games[i].crc );
|
||||
// printf( "GS: excluding CRC hack for 0x%08x\n", game.crc );
|
||||
}
|
||||
if (crcDups)
|
||||
printf("[FIXME] GS: Duplicate CRC: Overall: %d\n", crcDups);
|
||||
|
||||
+7
-5
@@ -15,6 +15,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
|
||||
class CRC
|
||||
{
|
||||
public:
|
||||
@@ -170,16 +172,16 @@ public:
|
||||
|
||||
struct Game
|
||||
{
|
||||
uint32 crc;
|
||||
u32 crc;
|
||||
Title title;
|
||||
Region region;
|
||||
uint32 flags;
|
||||
u32 flags;
|
||||
};
|
||||
|
||||
private:
|
||||
static Game m_games[];
|
||||
static std::map<uint32, Game*> m_map;
|
||||
static const Game m_games[];
|
||||
static std::map<u32, const Game*> m_map;
|
||||
|
||||
public:
|
||||
static Game Lookup(uint32 crc);
|
||||
static const Game& Lookup(u32 crc);
|
||||
};
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
|
||||
#include "PrecompiledHeader.h"
|
||||
#include "GSDrawingContext.h"
|
||||
#include "GSGL.h"
|
||||
#include "GS.h"
|
||||
|
||||
static int findmax(int tl, int br, int limit, int wm, int minuv, int maxuv)
|
||||
@@ -55,7 +56,7 @@ static int findmax(int tl, int br, int limit, int wm, int minuv, int maxuv)
|
||||
|
||||
static int reduce(int uv, int size)
|
||||
{
|
||||
while (size > 3 && (1 << (size - 1)) >= uv + 1)
|
||||
while (size > 3 && (1 << (size - 1)) >= uv)
|
||||
{
|
||||
size--;
|
||||
}
|
||||
@@ -65,7 +66,7 @@ static int reduce(int uv, int size)
|
||||
|
||||
static int extend(int uv, int size)
|
||||
{
|
||||
while (size < 10 && (1 << size) < uv + 1)
|
||||
while (size < 10 && (1 << size) < uv)
|
||||
{
|
||||
size++;
|
||||
}
|
||||
@@ -98,7 +99,7 @@ GIFRegTEX0 GSDrawingContext::GetSizeFixedTEX0(const GSVector4& st, bool linear,
|
||||
uvf += GSVector4(-0.5f, 0.5f).xxyy();
|
||||
}
|
||||
|
||||
GSVector4i uv = GSVector4i(uvf.floor());
|
||||
GSVector4i uv = GSVector4i(uvf.floor().xyzw(uvf.ceil()));
|
||||
|
||||
uv.x = findmax(uv.x, uv.z, (1 << tw) - 1, wms, minu, maxu);
|
||||
uv.y = findmax(uv.y, uv.w, (1 << th) - 1, wmt, minv, maxv);
|
||||
@@ -153,7 +154,7 @@ void GSDrawingContext::ComputeFixedTEX0(const GSVector4& st)
|
||||
int maxu = (int)CLAMP.MAXU;
|
||||
int maxv = (int)CLAMP.MAXV;
|
||||
|
||||
GSVector4i uv = GSVector4i(st.floor());
|
||||
GSVector4i uv = GSVector4i(st.floor().xyzw(st.ceil()));
|
||||
|
||||
uv.x = findmax(uv.x, uv.z, (1 << TEX0.TW) - 1, wms, minu, maxu);
|
||||
uv.y = findmax(uv.y, uv.w, (1 << TEX0.TH) - 1, wmt, minv, maxv);
|
||||
|
||||
@@ -15,11 +15,10 @@
|
||||
|
||||
#pragma once
|
||||
#ifdef __clang__
|
||||
// Ignore format for this file, as it spams a lot of warnings about uint64 and %llu.
|
||||
// Ignore format for this file, as it spams a lot of warnings about u64 and %llu.
|
||||
#pragma clang diagnostic ignored "-Wformat"
|
||||
#endif
|
||||
|
||||
#include "GS.h"
|
||||
#include "GSLocalMemory.h"
|
||||
|
||||
class alignas(32) GSDrawingContext
|
||||
@@ -48,9 +47,9 @@ public:
|
||||
|
||||
struct
|
||||
{
|
||||
GSOffset* fb;
|
||||
GSOffset* zb;
|
||||
GSOffset* tex;
|
||||
GSOffset fb;
|
||||
GSOffset zb;
|
||||
GSOffset tex;
|
||||
GSPixelOffset* fzb;
|
||||
GSPixelOffset4* fzb4;
|
||||
} offset;
|
||||
@@ -102,10 +101,10 @@ public:
|
||||
{
|
||||
ASSERT(XYOFFSET.OFX <= 0xf800 && XYOFFSET.OFY <= 0xf800);
|
||||
|
||||
scissor.ex.u16[0] = (uint16)((SCISSOR.SCAX0 << 4) + XYOFFSET.OFX - 0x8000);
|
||||
scissor.ex.u16[1] = (uint16)((SCISSOR.SCAY0 << 4) + XYOFFSET.OFY - 0x8000);
|
||||
scissor.ex.u16[2] = (uint16)((SCISSOR.SCAX1 << 4) + XYOFFSET.OFX - 0x8000);
|
||||
scissor.ex.u16[3] = (uint16)((SCISSOR.SCAY1 << 4) + XYOFFSET.OFY - 0x8000);
|
||||
scissor.ex.U16[0] = (u16)((SCISSOR.SCAX0 << 4) + XYOFFSET.OFX - 0x8000);
|
||||
scissor.ex.U16[1] = (u16)((SCISSOR.SCAY0 << 4) + XYOFFSET.OFY - 0x8000);
|
||||
scissor.ex.U16[2] = (u16)((SCISSOR.SCAX1 << 4) + XYOFFSET.OFX - 0x8000);
|
||||
scissor.ex.U16[3] = (u16)((SCISSOR.SCAY1 << 4) + XYOFFSET.OFY - 0x8000);
|
||||
|
||||
scissor.ofex = GSVector4(
|
||||
(int)((SCISSOR.SCAX0 << 4) + XYOFFSET.OFX),
|
||||
|
||||
@@ -15,8 +15,6 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "GS.h"
|
||||
|
||||
class alignas(32) GSDrawingEnvironment
|
||||
{
|
||||
public:
|
||||
|
||||
+11
-10
@@ -15,6 +15,7 @@
|
||||
|
||||
#include "PrecompiledHeader.h"
|
||||
#include "GSDump.h"
|
||||
#include "GSExtra.h"
|
||||
|
||||
GSDumpBase::GSDumpBase(const std::string& fn)
|
||||
: m_frames(0)
|
||||
@@ -31,7 +32,7 @@ GSDumpBase::~GSDumpBase()
|
||||
fclose(m_gs);
|
||||
}
|
||||
|
||||
void GSDumpBase::AddHeader(uint32 crc, const freezeData& fd, const GSPrivRegSet* regs)
|
||||
void GSDumpBase::AddHeader(u32 crc, const freezeData& fd, const GSPrivRegSet* regs)
|
||||
{
|
||||
AppendRawData(&crc, 4);
|
||||
AppendRawData(&fd.size, 4);
|
||||
@@ -39,18 +40,18 @@ void GSDumpBase::AddHeader(uint32 crc, const freezeData& fd, const GSPrivRegSet*
|
||||
AppendRawData(regs, sizeof(*regs));
|
||||
}
|
||||
|
||||
void GSDumpBase::Transfer(int index, const uint8* mem, size_t size)
|
||||
void GSDumpBase::Transfer(int index, const u8* mem, size_t size)
|
||||
{
|
||||
if (size == 0)
|
||||
return;
|
||||
|
||||
AppendRawData(0);
|
||||
AppendRawData(static_cast<uint8>(index));
|
||||
AppendRawData(static_cast<u8>(index));
|
||||
AppendRawData(&size, 4);
|
||||
AppendRawData(mem, size);
|
||||
}
|
||||
|
||||
void GSDumpBase::ReadFIFO(uint32 size)
|
||||
void GSDumpBase::ReadFIFO(u32 size)
|
||||
{
|
||||
if (size == 0)
|
||||
return;
|
||||
@@ -69,7 +70,7 @@ bool GSDumpBase::VSync(int field, bool last, const GSPrivRegSet* regs)
|
||||
AppendRawData(regs, sizeof(*regs));
|
||||
|
||||
AppendRawData(1);
|
||||
AppendRawData(static_cast<uint8>(field));
|
||||
AppendRawData(static_cast<u8>(field));
|
||||
|
||||
if (last)
|
||||
m_extra_frames--;
|
||||
@@ -91,7 +92,7 @@ void GSDumpBase::Write(const void* data, size_t size)
|
||||
// GSDump implementation
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
GSDump::GSDump(const std::string& fn, uint32 crc, const freezeData& fd, const GSPrivRegSet* regs)
|
||||
GSDump::GSDump(const std::string& fn, u32 crc, const freezeData& fd, const GSPrivRegSet* regs)
|
||||
: GSDumpBase(fn + ".gs")
|
||||
{
|
||||
AddHeader(crc, fd, regs);
|
||||
@@ -102,7 +103,7 @@ void GSDump::AppendRawData(const void* data, size_t size)
|
||||
Write(data, size);
|
||||
}
|
||||
|
||||
void GSDump::AppendRawData(uint8 c)
|
||||
void GSDump::AppendRawData(u8 c)
|
||||
{
|
||||
Write(&c, 1);
|
||||
}
|
||||
@@ -111,7 +112,7 @@ void GSDump::AppendRawData(uint8 c)
|
||||
// GSDumpXz implementation
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
GSDumpXz::GSDumpXz(const std::string& fn, uint32 crc, const freezeData& fd, const GSPrivRegSet* regs)
|
||||
GSDumpXz::GSDumpXz(const std::string& fn, u32 crc, const freezeData& fd, const GSPrivRegSet* regs)
|
||||
: GSDumpBase(fn + ".gs.xz")
|
||||
{
|
||||
m_strm = LZMA_STREAM_INIT;
|
||||
@@ -150,7 +151,7 @@ void GSDumpXz::AppendRawData(const void* data, size_t size)
|
||||
Flush();
|
||||
}
|
||||
|
||||
void GSDumpXz::AppendRawData(uint8 c)
|
||||
void GSDumpXz::AppendRawData(u8 c)
|
||||
{
|
||||
m_in_buff.push_back(c);
|
||||
}
|
||||
@@ -170,7 +171,7 @@ void GSDumpXz::Flush()
|
||||
|
||||
void GSDumpXz::Compress(lzma_action action, lzma_ret expected_status)
|
||||
{
|
||||
std::vector<uint8> out_buff(1024 * 1024);
|
||||
std::vector<u8> out_buff(1024 * 1024);
|
||||
do
|
||||
{
|
||||
m_strm.next_out = out_buff.data();
|
||||
|
||||
+11
-10
@@ -15,7 +15,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "GS.h"
|
||||
#include "SaveState.h"
|
||||
#include "GSRegs.h"
|
||||
#include "Renderers/SW/GSVertexSW.h"
|
||||
#include <lzma.h>
|
||||
|
||||
@@ -45,28 +46,28 @@ class GSDumpBase
|
||||
FILE* m_gs;
|
||||
|
||||
protected:
|
||||
void AddHeader(uint32 crc, const freezeData& fd, const GSPrivRegSet* regs);
|
||||
void AddHeader(u32 crc, const freezeData& fd, const GSPrivRegSet* regs);
|
||||
void Write(const void* data, size_t size);
|
||||
|
||||
virtual void AppendRawData(const void* data, size_t size) = 0;
|
||||
virtual void AppendRawData(uint8 c) = 0;
|
||||
virtual void AppendRawData(u8 c) = 0;
|
||||
|
||||
public:
|
||||
GSDumpBase(const std::string& fn);
|
||||
virtual ~GSDumpBase();
|
||||
|
||||
void ReadFIFO(uint32 size);
|
||||
void Transfer(int index, const uint8* mem, size_t size);
|
||||
void ReadFIFO(u32 size);
|
||||
void Transfer(int index, const u8* mem, size_t size);
|
||||
bool VSync(int field, bool last, const GSPrivRegSet* regs);
|
||||
};
|
||||
|
||||
class GSDump final : public GSDumpBase
|
||||
{
|
||||
void AppendRawData(const void* data, size_t size) final;
|
||||
void AppendRawData(uint8 c) final;
|
||||
void AppendRawData(u8 c) final;
|
||||
|
||||
public:
|
||||
GSDump(const std::string& fn, uint32 crc, const freezeData& fd, const GSPrivRegSet* regs);
|
||||
GSDump(const std::string& fn, u32 crc, const freezeData& fd, const GSPrivRegSet* regs);
|
||||
virtual ~GSDump() = default;
|
||||
};
|
||||
|
||||
@@ -74,14 +75,14 @@ class GSDumpXz final : public GSDumpBase
|
||||
{
|
||||
lzma_stream m_strm;
|
||||
|
||||
std::vector<uint8> m_in_buff;
|
||||
std::vector<u8> m_in_buff;
|
||||
|
||||
void Flush();
|
||||
void Compress(lzma_action action, lzma_ret expected_status);
|
||||
void AppendRawData(const void* data, size_t size);
|
||||
void AppendRawData(uint8 c);
|
||||
void AppendRawData(u8 c);
|
||||
|
||||
public:
|
||||
GSDumpXz(const std::string& fn, uint32 crc, const freezeData& fd, const GSPrivRegSet* regs);
|
||||
GSDumpXz(const std::string& fn, u32 crc, const freezeData& fd, const GSPrivRegSet* regs);
|
||||
virtual ~GSDumpXz();
|
||||
};
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2021 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "GSVector.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
inline std::string convert_utf16_to_utf8(const std::wstring& utf16_string)
|
||||
{
|
||||
const int size = WideCharToMultiByte(CP_UTF8, 0, utf16_string.c_str(), utf16_string.size(), nullptr, 0, nullptr, nullptr);
|
||||
std::string converted_string(size, 0);
|
||||
WideCharToMultiByte(CP_UTF8, 0, utf16_string.c_str(), utf16_string.size(), converted_string.data(), converted_string.size(), nullptr, nullptr);
|
||||
return converted_string;
|
||||
}
|
||||
|
||||
inline std::wstring convert_utf8_to_utf16(const std::string& utf8_string)
|
||||
{
|
||||
int size = MultiByteToWideChar(CP_UTF8, 0, utf8_string.c_str(), -1, nullptr, 0);
|
||||
std::vector<wchar_t> converted_string(size);
|
||||
MultiByteToWideChar(CP_UTF8, 0, utf8_string.c_str(), -1, converted_string.data(), converted_string.size());
|
||||
return {converted_string.data()};
|
||||
}
|
||||
#endif
|
||||
|
||||
// _wfopen has to be used on Windows for pathnames containing non-ASCII characters.
|
||||
inline FILE* px_fopen(const std::string& filename, const std::string& mode)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
return _wfopen(convert_utf8_to_utf16(filename).c_str(), convert_utf8_to_utf16(mode).c_str());
|
||||
#else
|
||||
return fopen(filename.c_str(), mode.c_str());
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef ENABLE_ACCURATE_BUFFER_EMULATION
|
||||
static const GSVector2i default_rt_size(2048, 2048);
|
||||
#else
|
||||
static const GSVector2i default_rt_size(1280, 1024);
|
||||
#endif
|
||||
|
||||
// Helper path to dump texture
|
||||
extern const std::string root_sw;
|
||||
extern const std::string root_hw;
|
||||
|
||||
extern std::string format(const char* fmt, ...);
|
||||
|
||||
extern void* vmalloc(size_t size, bool code);
|
||||
extern void vmfree(void* ptr, size_t size);
|
||||
|
||||
extern void* fifo_alloc(size_t size, size_t repeat);
|
||||
extern void fifo_free(void* ptr, size_t size, size_t repeat);
|
||||
|
||||
// clang-format off
|
||||
|
||||
#ifdef __POSIX__
|
||||
#include <zlib.h>
|
||||
#else
|
||||
#include <zlib/zlib.h>
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define ALIGN_STACK(n) alignas(n) int dummy__; (void)dummy__;
|
||||
#else
|
||||
#ifdef __GNUC__
|
||||
// GCC removes the variable as dead code and generates some warnings.
|
||||
// Stack is automatically realigned due to SSE/AVX operations
|
||||
#define ALIGN_STACK(n) (void)0;
|
||||
#else
|
||||
// TODO Check clang behavior
|
||||
#define ALIGN_STACK(n) alignas(n) int dummy__;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_VTUNE
|
||||
#include "jitprofiling.h"
|
||||
#ifdef _WIN32
|
||||
#pragma comment(lib, "jitprofiling.lib")
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#define DIRECTORY_SEPARATOR '\\'
|
||||
#else
|
||||
#include <sys/stat.h> // mkdir
|
||||
#define DIRECTORY_SEPARATOR '/'
|
||||
#endif
|
||||
@@ -0,0 +1,67 @@
|
||||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2021 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Renderers/OpenGL/GLLoader.h"
|
||||
#include "GSExtra.h"
|
||||
|
||||
// Note: GL messages are present in common code, so in all renderers.
|
||||
|
||||
#define GL_INSERT(type, code, sev, ...) \
|
||||
do \
|
||||
if (glDebugMessageInsert) glDebugMessageInsert(GL_DEBUG_SOURCE_APPLICATION, type, code, sev, -1, format(__VA_ARGS__).c_str()); \
|
||||
while(0);
|
||||
|
||||
#if defined(_DEBUG)
|
||||
#define GL_CACHE(...) GL_INSERT(GL_DEBUG_TYPE_OTHER, 0xFEAD, GL_DEBUG_SEVERITY_NOTIFICATION, __VA_ARGS__)
|
||||
#else
|
||||
#define GL_CACHE(...) (void)(0);
|
||||
#endif
|
||||
|
||||
#if defined(ENABLE_TRACE_REG) && defined(_DEBUG)
|
||||
#define GL_REG(...) GL_INSERT(GL_DEBUG_TYPE_OTHER, 0xB0B0, GL_DEBUG_SEVERITY_NOTIFICATION, __VA_ARGS__)
|
||||
#else
|
||||
#define GL_REG(...) (void)(0);
|
||||
#endif
|
||||
|
||||
#if defined(ENABLE_EXTRA_LOG) && defined(_DEBUG)
|
||||
#define GL_DBG(...) GL_INSERT(GL_DEBUG_TYPE_OTHER, 0xD0D0, GL_DEBUG_SEVERITY_NOTIFICATION, __VA_ARGS__)
|
||||
#else
|
||||
#define GL_DBG(...) (void)(0);
|
||||
#endif
|
||||
|
||||
#if defined(ENABLE_OGL_DEBUG)
|
||||
struct GLAutoPop
|
||||
{
|
||||
~GLAutoPop()
|
||||
{
|
||||
if (glPopDebugGroup)
|
||||
glPopDebugGroup();
|
||||
}
|
||||
};
|
||||
|
||||
#define GL_PUSH_(...) do if (glPushDebugGroup) glPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 0xBAD, -1, format(__VA_ARGS__).c_str()); while(0);
|
||||
#define GL_PUSH(...) do if (glPushDebugGroup) glPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 0xBAD, -1, format(__VA_ARGS__).c_str()); while(0); GLAutoPop gl_auto_pop;
|
||||
#define GL_POP() do if (glPopDebugGroup) glPopDebugGroup(); while(0);
|
||||
#define GL_INS(...) GL_INSERT(GL_DEBUG_TYPE_ERROR, 0xDEAD, GL_DEBUG_SEVERITY_MEDIUM, __VA_ARGS__)
|
||||
#define GL_PERF(...) GL_INSERT(GL_DEBUG_TYPE_PERFORMANCE, 0xFEE1, GL_DEBUG_SEVERITY_NOTIFICATION, __VA_ARGS__)
|
||||
#else
|
||||
#define GL_PUSH_(...) (void)(0);
|
||||
#define GL_PUSH(...) (void)(0);
|
||||
#define GL_POP() (void)(0);
|
||||
#define GL_INS(...) (void)(0);
|
||||
#define GL_PERF(...) (void)(0);
|
||||
#endif
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user