mirror of
https://github.com/PCSX2/pcsx2.git
synced 2026-08-20 12:53:10 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fac171fa95 | ||
|
|
fa1b6493da | ||
|
|
e58766745c | ||
|
|
d8a9c5b479 | ||
|
|
9a4d8ba934 | ||
|
|
ab816543c8 | ||
|
|
37ccd81985 | ||
|
|
42dad4ade8 | ||
|
|
b2ac035862 | ||
|
|
f42d7eec74 | ||
|
|
e4ef41f86a | ||
|
|
103dd3954a | ||
|
|
2f9577a28e | ||
|
|
33ec4d9430 | ||
|
|
209f09ca7a | ||
|
|
2e6af75f1d | ||
|
|
f68122a380 | ||
|
|
d51bdccf7f | ||
|
|
7d8377b133 | ||
|
|
80d3a8a757 | ||
|
|
2e6c5cde29 | ||
|
|
0f2768dca4 | ||
|
|
d5be095482 | ||
|
|
b315625a94 | ||
|
|
6b51462fa0 | ||
|
|
373e698545 | ||
|
|
3b309c6d4e | ||
|
|
8e93e9f516 | ||
|
|
ac8582eca7 | ||
|
|
e6f72fdde7 | ||
|
|
9166218d07 | ||
|
|
c0b1bde94b | ||
|
|
756a679262 | ||
|
|
13b19b35c0 | ||
|
|
cadb70d1e4 | ||
|
|
4cb4844e8d | ||
|
|
556c7ca080 | ||
|
|
962db4bfc4 | ||
|
|
da651cabe4 | ||
|
|
e03076c6ff | ||
|
|
122968e63a | ||
|
|
6beac26727 | ||
|
|
3073281d13 | ||
|
|
0e0e23eefb | ||
|
|
bcec38bd97 | ||
|
|
bd706f99b2 | ||
|
|
501af632f7 | ||
|
|
a143122804 | ||
|
|
92aa426bba | ||
|
|
96a1ce2fb2 | ||
|
|
c203a09435 | ||
|
|
c4084b4162 | ||
|
|
2a7c948a57 | ||
|
|
46912595ea | ||
|
|
120ee6c673 | ||
|
|
112238fbd7 | ||
|
|
38e288ef6a | ||
|
|
35322cf49b | ||
|
|
8d44e1af0e | ||
|
|
16af078b3b | ||
|
|
3e968b4390 | ||
|
|
0029dac32d | ||
|
|
a083343c6e | ||
|
|
c277ee1d34 | ||
|
|
ebe8592a8d | ||
|
|
6c3e357d9e | ||
|
|
64455620e8 | ||
|
|
fc799778de | ||
|
|
e04e0e38d1 | ||
|
|
8d6569be95 | ||
|
|
8b086a3898 | ||
|
|
a4b8c33cf3 | ||
|
|
1d37ba47f4 | ||
|
|
8d480c28ce | ||
|
|
6e38f40f96 | ||
|
|
017c37f212 | ||
|
|
6eee4cb38a | ||
|
|
1f6a14261c | ||
|
|
14e8d840ff | ||
|
|
125b9ea1e1 | ||
|
|
e6b1e1948e | ||
|
|
ba1072f470 | ||
|
|
1fb29de082 | ||
|
|
f79e5ab559 | ||
|
|
c3a9fd469e | ||
|
|
c8abc909fa | ||
|
|
401a9f4c62 | ||
|
|
f1edb0c960 | ||
|
|
d73335e4d3 | ||
|
|
7a554be7a7 | ||
|
|
31b6ff6046 | ||
|
|
38ab0630e6 | ||
|
|
b5fa9deb30 | ||
|
|
4e8bae1703 | ||
|
|
464ce1c3cd | ||
|
|
bb55c320c1 | ||
|
|
af585bffa9 | ||
|
|
bde4868b67 | ||
|
|
3835fc5ad1 | ||
|
|
7b815b5f07 | ||
|
|
754c6126b1 |
@@ -84,7 +84,7 @@ jobs:
|
||||
runs-on: ${{ matrix.os }}
|
||||
continue-on-error: ${{ matrix.experimental }}
|
||||
# Set some sort of timeout in the event of run-away builds. We are limited on concurrent jobs so, get rid of them.
|
||||
timeout-minutes: 30
|
||||
timeout-minutes: 60
|
||||
|
||||
env:
|
||||
CCACHE_BASEDIR: ${{ github.workspace }}
|
||||
|
||||
@@ -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 wxwidgets sdl2 libsamplerate glib
|
||||
brew install sound-touch portaudio wxwidgets sdl2 libsamplerate
|
||||
}
|
||||
if ! do-install; then
|
||||
brew update
|
||||
|
||||
@@ -49,9 +49,8 @@ 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/
|
||||
cp -r "$GITHUB_WORKSPACE"/bin/resources "$GITHUB_WORKSPACE"/squashfs-root/usr/bin/app/
|
||||
cp "$GITHUB_WORKSPACE"/bin/docs/{Configuration_Guide.pdf,PCSX2_FAQ.pdf} "$GITHUB_WORKSPACE"/squashfs-root/usr/bin/app
|
||||
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
|
||||
|
||||
@@ -20,6 +20,7 @@ cmake \
|
||||
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-DPACKAGE_MODE=TRUE \
|
||||
-DWAYLAND_API=TRUE \
|
||||
-DDISABLE_ADVANCE_SIMD=TRUE \
|
||||
-DCMAKE_INSTALL_LIBDIR="/tmp/" \
|
||||
-DCMAKE_INSTALL_DATADIR="/tmp/" \
|
||||
|
||||
@@ -1,7 +1,14 @@
|
||||
import { MessageEmbed, WebhookClient } from "discord.js";
|
||||
import * as github from '@actions/github';
|
||||
|
||||
const assets = github.context.payload.release.assets;
|
||||
const releaseInfo = github.context.payload.release;
|
||||
|
||||
if (!releaseInfo.prerelease) {
|
||||
console.log("Not announcing - release was not a pre-release (aka a Nightly)");
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
const assets = releaseInfo.assets;
|
||||
let windowsAssetLinks = "";
|
||||
let linuxAssetLinks = "";
|
||||
|
||||
@@ -34,10 +41,10 @@ const embed = new MessageEmbed()
|
||||
.setColor('#FF8000')
|
||||
.setTitle('New PCSX2 Nightly Build Available!')
|
||||
.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: 'Version', value: releaseInfo.tag_name, inline: true },
|
||||
{ name: 'Release Link', value: `[Github Release](${releaseInfo.html_url})`, 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 }
|
||||
{ name: 'Included Changes', value: releaseInfo.body, inline: false }
|
||||
);
|
||||
|
||||
if (windowsAssetLinks != "") {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import yaml
|
||||
|
||||
# Assumes this is ran from the root of the repository
|
||||
file_path = "./bin/GameIndex.yaml"
|
||||
file_path = "./bin/resources/GameIndex.yaml"
|
||||
|
||||
# These settings have to be manually kept in sync with the emulator code unfortunately.
|
||||
# up to date validation should ALWAYS be provided via the application!
|
||||
|
||||
@@ -79,6 +79,7 @@ oprofile_data/
|
||||
/bin/PCSX2-linux.sh
|
||||
/bin/GS*.txt
|
||||
/bin/bios
|
||||
/bin/cache
|
||||
/bin/dumps
|
||||
/bin/help
|
||||
/bin/inis
|
||||
|
||||
+4
-13
@@ -1,13 +1,9 @@
|
||||
# Project Name
|
||||
project(Pcsx2)
|
||||
|
||||
# Debian-based distributions require at least 2.8.5 due to multiarch.
|
||||
# Bumping up to 3.0 seems reasonable at this point, and will let us modernize
|
||||
# things a bit.
|
||||
#
|
||||
# Setting it to a range tells it that it supports the features on the newer
|
||||
# versions as well, avoiding setting policies.
|
||||
cmake_minimum_required(VERSION 3.10...3.17)
|
||||
cmake_minimum_required(VERSION 3.11...3.22)
|
||||
|
||||
# Project Name
|
||||
project(Pcsx2)
|
||||
|
||||
# Variable to check that people use the good file
|
||||
set(TOP_CMAKE_WAS_SOURCED TRUE)
|
||||
@@ -58,11 +54,6 @@ endif()
|
||||
|
||||
# Install some files to ease package creation
|
||||
if(PACKAGE_MODE)
|
||||
if(NOT DISABLE_CHEATS_ZIP)
|
||||
INSTALL(FILES "${CMAKE_SOURCE_DIR}/bin/cheats_ws.zip" DESTINATION "${CMAKE_INSTALL_DATADIR}/PCSX2")
|
||||
endif()
|
||||
INSTALL(FILES "${CMAKE_SOURCE_DIR}/bin/GameIndex.yaml" DESTINATION "${CMAKE_INSTALL_DATADIR}/PCSX2")
|
||||
|
||||
# set categories depending on system/distribution in pcsx2.desktop
|
||||
if(openSUSE)
|
||||
set(PCSX2_MENU_CATEGORIES "System;Emulator;")
|
||||
|
||||
@@ -57,8 +57,6 @@ Sys_TakeSnapshot = F8
|
||||
Sys_RenderswitchToggle = F9
|
||||
|
||||
Sys_LoggingToggle = F10
|
||||
# The FreezeGS function is currently disabled internally.
|
||||
Sys_FreezeGS = F11
|
||||
Sys_RecordingToggle = F12
|
||||
|
||||
GSwindow_CycleAspectRatio = F6
|
||||
|
||||
@@ -48,6 +48,12 @@ PAPX-90223:
|
||||
PAPX-90231:
|
||||
name: "Kaitou Sly Cooper [Demo, Taikenban]"
|
||||
region: "NTSC-J"
|
||||
PAPX-90506:
|
||||
name: "Dark Chronicle[Demo, Taikenban]"
|
||||
region: "NTSC-J"
|
||||
compat: 5
|
||||
clampModes:
|
||||
eeClampMode: 3 # Fixes textbox.
|
||||
PAPX-90512:
|
||||
name: "Gran Turismo 4 - Toyota Prius [Trial]"
|
||||
region: "NTSC-J"
|
||||
@@ -1741,6 +1747,13 @@ SCED-53325:
|
||||
SCED-53348:
|
||||
name: "Official PlayStation 2 Magazine Demo 58" # French
|
||||
region: "PAL-F"
|
||||
SCED-53679:
|
||||
name: "Fire It Up Lads Demo"
|
||||
region: "PAL-E"
|
||||
patches:
|
||||
default:
|
||||
content: |-
|
||||
comment=- WRC Rally needs XGKick fix enabled
|
||||
SCED-53684:
|
||||
name: "SingStar '80s [Demo]"
|
||||
region: "PAL-E"
|
||||
@@ -2331,9 +2344,10 @@ SCES-51135:
|
||||
region: "PAL-M5"
|
||||
compat: 5
|
||||
roundModes:
|
||||
vuRoundMode: 0 # Fixes SPS.
|
||||
vuRoundMode: 1 # Fixes SPS.
|
||||
eeRoundMode: 0 # Fixes textures on the doors.
|
||||
clampModes:
|
||||
vuClampMode: 2 # Fix other SPS.
|
||||
vuClampMode: 0 # Fix other SPS.
|
||||
gameFixes:
|
||||
- VUKickstartHack # Fixes objects disappearing.
|
||||
SCES-51159:
|
||||
@@ -2364,6 +2378,8 @@ SCES-51190:
|
||||
name: "Dark Chronicle"
|
||||
region: "PAL-M5"
|
||||
compat: 5
|
||||
clampModes:
|
||||
eeClampMode: 3 # Fixes textbox.
|
||||
SCES-51224:
|
||||
name: "War of the Monsters"
|
||||
region: "PAL-E"
|
||||
@@ -2480,9 +2496,10 @@ SCES-51685:
|
||||
name: "Primal"
|
||||
region: "PAL-E-R"
|
||||
roundModes:
|
||||
vuRoundMode: 0 # Fixes SPS.
|
||||
vuRoundMode: 1 # Fixes SPS.
|
||||
eeRoundMode: 0 # Fixes textures on the doors.
|
||||
clampModes:
|
||||
vuClampMode: 2 # Fix other SPS.
|
||||
vuClampMode: 0 # Fix other SPS.
|
||||
gameFixes:
|
||||
- VUKickstartHack # Fixes objects disappearing.
|
||||
SCES-51706:
|
||||
@@ -3685,6 +3702,8 @@ SCKA-20014:
|
||||
name: "Dark Cloud 2"
|
||||
region: "NTSC-K"
|
||||
compat: 5
|
||||
clampModes:
|
||||
eeClampMode: 3 # Fixes textbox.
|
||||
SCKA-20015:
|
||||
name: "Time Crisis 3"
|
||||
region: "NTSC-K"
|
||||
@@ -4253,6 +4272,8 @@ SCPS-15032:
|
||||
SCPS-15033:
|
||||
name: "Dark Chronicle"
|
||||
region: "NTSC-J"
|
||||
clampModes:
|
||||
eeClampMode: 3 # Fixes textbox.
|
||||
SCPS-15034:
|
||||
name: "This is Football 2003"
|
||||
region: "NTSC-J"
|
||||
@@ -4739,6 +4760,8 @@ SCPS-19214:
|
||||
SCPS-19215:
|
||||
name: "Dark Chronicle [PlayStation 2 The Best]"
|
||||
region: "NTSC-J"
|
||||
clampModes:
|
||||
eeClampMode: 3 # Fixes textbox.
|
||||
SCPS-19251:
|
||||
name: "Wild ARMs - Alter Code F [PlayStation 2 The Best]"
|
||||
region: "NTSC-J"
|
||||
@@ -4798,6 +4821,8 @@ SCPS-19305:
|
||||
SCPS-19306:
|
||||
name: "Dark Chronicle [PlayStation 2 The Best]"
|
||||
region: "NTSC-J"
|
||||
clampModes:
|
||||
eeClampMode: 3 # Fixes textbox.
|
||||
SCPS-19307:
|
||||
name: "Popolocrois - The First Adventure [PlayStation 2 The Best]"
|
||||
region: "NTSC-J"
|
||||
@@ -5152,6 +5177,8 @@ SCPS-55047:
|
||||
SCPS-55048:
|
||||
name: "Dark Chronicle"
|
||||
region: "NTSC-J"
|
||||
clampModes:
|
||||
eeClampMode: 3 # Fixes textbox.
|
||||
SCPS-55049:
|
||||
name: "King of Fighters 2000, The"
|
||||
region: "NTSC-J"
|
||||
@@ -5415,9 +5442,10 @@ SCUS-97142:
|
||||
region: "NTSC-U"
|
||||
compat: 5
|
||||
roundModes:
|
||||
vuRoundMode: 0 # Fixes SPS.
|
||||
vuRoundMode: 1 # Fixes SPS.
|
||||
eeRoundMode: 0 # Fixes textures on the doors.
|
||||
clampModes:
|
||||
vuClampMode: 2 # Fix other SPS.
|
||||
vuClampMode: 0 # Fix other SPS.
|
||||
gameFixes:
|
||||
- VUKickstartHack # Fixes objects disappearing.
|
||||
SCUS-97144:
|
||||
@@ -5648,6 +5676,8 @@ SCUS-97213:
|
||||
name: "Dark Cloud 2"
|
||||
region: "NTSC-U"
|
||||
compat: 5
|
||||
clampModes:
|
||||
eeClampMode: 3 # Fixes textbox.
|
||||
SCUS-97214:
|
||||
name: "NCAA GameBreaker 2003"
|
||||
region: "NTSC-U"
|
||||
@@ -5684,9 +5714,10 @@ SCUS-97225:
|
||||
name: "Primal [Demo]"
|
||||
region: "NTSC-U"
|
||||
roundModes:
|
||||
vuRoundMode: 0 # Fixes SPS.
|
||||
vuRoundMode: 1 # Fixes SPS.
|
||||
eeRoundMode: 0 # Fixes textures on the doors.
|
||||
clampModes:
|
||||
vuClampMode: 2 # Fix other SPS.
|
||||
vuClampMode: 0 # Fix other SPS.
|
||||
gameFixes:
|
||||
- VUKickstartHack # Fixes objects disappearing.
|
||||
SCUS-97226:
|
||||
@@ -5698,6 +5729,8 @@ SCUS-97227:
|
||||
SCUS-97229:
|
||||
name: "Dark Cloud 2 [Demo]"
|
||||
region: "NTSC-U"
|
||||
clampModes:
|
||||
eeClampMode: 3 # Fixes textbox.
|
||||
SCUS-97230:
|
||||
name: "SOCOM - U.S. Navy SEALs (Online)"
|
||||
region: "NTSC-U"
|
||||
@@ -7053,6 +7086,8 @@ SLAJ-35003:
|
||||
SLED-50117:
|
||||
name: "Metal Gear Solid 2 - Sons of Liberty [Demo] [Zone of the Enders Bonus Disc]"
|
||||
region: "PAL-E"
|
||||
gameFixes:
|
||||
- EETimingHack # Fixes broken half-bottom artifacts.
|
||||
SLED-50359:
|
||||
name: "Devil May Cry [Demo]"
|
||||
region: "PAL-E"
|
||||
@@ -7997,12 +8032,18 @@ SLES-50383:
|
||||
name: "Metal Gear Solid 2 - Sons of Liberty"
|
||||
region: "PAL-M3"
|
||||
compat: 5
|
||||
gameFixes:
|
||||
- EETimingHack # Fixes broken half-bottom artifacts.
|
||||
SLES-50384:
|
||||
name: "Project Zero II"
|
||||
name: "Metal Gear Solid 2 - Sons of Liberty"
|
||||
region: "PAL-I"
|
||||
gameFixes:
|
||||
- EETimingHack # Fixes broken half-bottom artifacts.
|
||||
SLES-50385:
|
||||
name: "Metal Gear Solid 2 - Sons of Liberty"
|
||||
region: "PAL-S"
|
||||
gameFixes:
|
||||
- EETimingHack # Fixes broken half-bottom artifacts.
|
||||
SLES-50386:
|
||||
name: "Crash Bandicoot - Wrath of Cortex"
|
||||
region: "PAL-M6"
|
||||
@@ -9461,6 +9502,8 @@ SLES-51145:
|
||||
SLES-51150:
|
||||
name: "Scrabble Interactive - 2003 Edition"
|
||||
region: "PAL-M3"
|
||||
clampModes:
|
||||
vuClampMode: 0 # Fixes missing UI and game elements.
|
||||
SLES-51151:
|
||||
name: "NHL 2003"
|
||||
region: "PAL-M6"
|
||||
@@ -12407,6 +12450,8 @@ SLES-52710:
|
||||
SLES-52711:
|
||||
name: "Titeuf Mega Compet"
|
||||
region: "PAL-F"
|
||||
gameFixes:
|
||||
- GIFFIFOHack # Fixes corrupted textures.
|
||||
patches:
|
||||
958e5086:
|
||||
content: |-
|
||||
@@ -13090,6 +13135,14 @@ SLES-53021:
|
||||
SLES-53022:
|
||||
name: "ESPN NBA 2K5"
|
||||
region: "PAL-E"
|
||||
gameFixes:
|
||||
- SkipMPEGHack # Fixes videos.
|
||||
patches:
|
||||
CA37B42E:
|
||||
content: |-
|
||||
author=Prafull
|
||||
comment=fixes hang at start
|
||||
patch=1,EE,0034DA98,word,00000000
|
||||
SLES-53023:
|
||||
name: "RTL Ski Jump 2005"
|
||||
region: "PAL-E-G"
|
||||
@@ -13969,6 +14022,8 @@ SLES-53491:
|
||||
SLES-53492:
|
||||
name: "Total Overdose"
|
||||
region: "PAL-M5"
|
||||
gameFixes:
|
||||
- VUKickstartHack # Fixes SPS.
|
||||
SLES-53494:
|
||||
name: "Spongebob SquarePants - Lights, Camera, PANTS!"
|
||||
region: "PAL-E"
|
||||
@@ -14506,6 +14561,12 @@ SLES-53686:
|
||||
SLES-53687:
|
||||
name: "NBA 2K6"
|
||||
region: "PAL-M5"
|
||||
patches:
|
||||
04808D11:
|
||||
content: |-
|
||||
author=Prafull
|
||||
comment=fixes hang at start
|
||||
patch=1,EE,00441ff8,word,00000000
|
||||
SLES-53689:
|
||||
name: "World Poker Tour 2K6"
|
||||
region: "PAL-M3"
|
||||
@@ -14788,6 +14849,14 @@ SLES-53805:
|
||||
SLES-53809:
|
||||
name: "K-1 Premium Dynamite!!"
|
||||
region: "PAL-E"
|
||||
gameFixes:
|
||||
- XGKickHack # Fixes black and white fighters.
|
||||
patches:
|
||||
B6F9C8D3:
|
||||
content: |-
|
||||
comment=Fixes black screen in hardware mode.
|
||||
patch=1,EE,0030a420,word,0000948c
|
||||
patch=1,EE,0030a448,word,0000948c
|
||||
SLES-53810:
|
||||
name: "Sensible Soccer 2006"
|
||||
region: "PAL-M5"
|
||||
@@ -15599,6 +15668,12 @@ SLES-54209:
|
||||
SLES-54210:
|
||||
name: "NBA 2K7"
|
||||
region: "PAL-M5"
|
||||
patches:
|
||||
04808D11:
|
||||
content: |-
|
||||
author=Prafull
|
||||
comment=fixes hang at start
|
||||
patch=1,EE,0044f0f8,word,00000000
|
||||
SLES-54211:
|
||||
name: "NHL 2K7"
|
||||
region: "PAL-M5"
|
||||
@@ -18594,6 +18669,8 @@ SLES-82009:
|
||||
name: "Metal Gear Solid 2 - Substance"
|
||||
region: "PAL-M5"
|
||||
compat: 5
|
||||
gameFixes:
|
||||
- EETimingHack # Fixes broken half-bottom artifacts.
|
||||
SLES-82010:
|
||||
name: "Metal Gear Solid 2, Document of"
|
||||
region: "PAL-E"
|
||||
@@ -18844,6 +18921,11 @@ SLKA-25026:
|
||||
region: "NTSC-K"
|
||||
clampModes:
|
||||
vuClampMode: 2 # Fixes SPS in item menu.
|
||||
SLKA-25029:
|
||||
name: "MVP Baseball 2003"
|
||||
region: "NTSC-K"
|
||||
clampModes:
|
||||
vuClampMode: 3 # Fixes missing environment.
|
||||
SLKA-25030:
|
||||
name: "WWE SmackDown! Shut Your Mouth"
|
||||
region: "NTSC-K"
|
||||
@@ -18877,6 +18959,12 @@ SLKA-25043:
|
||||
name: "Virtua Fighter 4 - Evolution"
|
||||
region: "NTSC-K"
|
||||
compat: 5
|
||||
SLKA-25044:
|
||||
name: "Robotech: Battlecry"
|
||||
region: "NTSC-K"
|
||||
SLKA-25045:
|
||||
name: "The King of Fighters 2000"
|
||||
region: "NTSC-K"
|
||||
SLKA-25046:
|
||||
name: "Dragon Ball Z"
|
||||
region: "NTSC-K"
|
||||
@@ -19082,12 +19170,18 @@ SLKA-25202:
|
||||
memcardFilters:
|
||||
- "SLKA-25201"
|
||||
- "SLKA-25202"
|
||||
SLKA-25203:
|
||||
name: "World Soccer Winning Eleven 8 International"
|
||||
region: "NTSC-K"
|
||||
SLKA-25204:
|
||||
name: "Showdown - Legends of Wrestling"
|
||||
region: "NTSC-K"
|
||||
SLKA-25205:
|
||||
name: "Dragon Ball Z 3"
|
||||
region: "NTSC-K"
|
||||
SLKA-25206:
|
||||
name: "Burnout 3: Takedown"
|
||||
region: "NTSC-K"
|
||||
SLKA-25207:
|
||||
name: "Sakura Taisen V - Episode 0 - Samurai Girl of Wild"
|
||||
region: "NTSC-K"
|
||||
@@ -19195,6 +19289,9 @@ SLKA-25259:
|
||||
SLKA-25261:
|
||||
name: "Tsukiyo ni Saraba"
|
||||
region: "NTSC-K"
|
||||
SLKA-25262:
|
||||
name: "World Soccer Winning Eleven 8 International"
|
||||
region: "NTSC-K"
|
||||
SLKA-25263:
|
||||
name: "NanoBreaker"
|
||||
region: "NTSC-J"
|
||||
@@ -19336,6 +19433,9 @@ SLKA-25331:
|
||||
SLKA-25333:
|
||||
name: "Metal Slug Complete"
|
||||
region: "NTSC-K"
|
||||
SLKA-25335:
|
||||
name: "Shadow the Hedgehog"
|
||||
region: "NTSC-K"
|
||||
SLKA-25341:
|
||||
name: "Driver - Parallel Lines"
|
||||
region: "NTSC-K"
|
||||
@@ -19444,6 +19544,8 @@ SLKA-35001:
|
||||
name: "Metal Gear Solid 2 Substance"
|
||||
region: "NTSC-K"
|
||||
compat: 5
|
||||
gameFixes:
|
||||
- EETimingHack # Fixes broken half-bottom artifacts.
|
||||
SLKA-35003:
|
||||
name: "Sakura Taisen - Atsuki Chishioni"
|
||||
region: "NTSC-K"
|
||||
@@ -19557,6 +19659,9 @@ SLPM-55131:
|
||||
SLPM-55138:
|
||||
name: "Harukanaru Toki no Naka de - Yume no Ukihashi Special"
|
||||
region: "NTSC-J"
|
||||
SLPM-55146:
|
||||
name: "Jikkyou Powerful Pro Yakyuu 2009"
|
||||
region: "NTSC-J"
|
||||
SLPM-55148:
|
||||
name: "007: Nagusame no Houshuu"
|
||||
region: "NTSC-J"
|
||||
@@ -19665,6 +19770,11 @@ SLPM-60254:
|
||||
SLPM-60256:
|
||||
name: "Dengeki D73 demo"
|
||||
region: "NTSC-J"
|
||||
SLPM-60260:
|
||||
name: "D1 Professional Drift Grand Prix Series [Taikenban]"
|
||||
region: "NTSC-J"
|
||||
clampModes:
|
||||
eeClampMode: 3 # Fixes black void.
|
||||
SLPM-60262:
|
||||
name: "10th Anniversary Memorial Save Data [Disc 2]"
|
||||
region: "NTSC-J"
|
||||
@@ -20864,6 +20974,8 @@ SLPM-62485:
|
||||
SLPM-62486:
|
||||
name: "Chou Saisoku! Zokusha King B.U. [Simple Series DX]"
|
||||
region: "NTSC-J"
|
||||
clampModes:
|
||||
eeClampMode: 3 # Fixes white shadows.
|
||||
SLPM-62488:
|
||||
name: "Hot Gimmick Cosplay Mahjong"
|
||||
region: "NTSC-J"
|
||||
@@ -21135,6 +21247,14 @@ SLPM-62580:
|
||||
SLPM-62581:
|
||||
name: "K-1 Premium 2004 - Fighting Dynamite!!"
|
||||
region: "NTSC-J"
|
||||
gameFixes:
|
||||
- XGKickHack # Fixes black and white fighters.
|
||||
patches:
|
||||
0A1042EE:
|
||||
content: |-
|
||||
comment=Fixes black screen in hardware mode.
|
||||
patch=1,EE,00301de0,word,0000948c
|
||||
patch=1,EE,00301e08,word,0000948c
|
||||
SLPM-62582:
|
||||
name: "Slotter-Up Core 6"
|
||||
region: "NTSC-J"
|
||||
@@ -21977,9 +22097,13 @@ SLPM-65076:
|
||||
SLPM-65077:
|
||||
name: "Metal Gear Solid 2 - Sons of Liberty [Premium Package]"
|
||||
region: "NTSC-J"
|
||||
gameFixes:
|
||||
- EETimingHack # Fixes broken half-bottom artifacts.
|
||||
SLPM-65078:
|
||||
name: "Metal Gear Solid 2 - Sons of Liberty"
|
||||
region: "NTSC-J"
|
||||
gameFixes:
|
||||
- EETimingHack # Fixes broken half-bottom artifacts.
|
||||
SLPM-65080:
|
||||
name: "Tokimeki Memorial 3"
|
||||
region: "NTSC-J"
|
||||
@@ -24312,6 +24436,8 @@ SLPM-65862:
|
||||
SLPM-65863:
|
||||
name: "D1 Grand Prix Series - Professional Drift"
|
||||
region: "NTSC-J"
|
||||
clampModes:
|
||||
eeClampMode: 3 # Fixes black void.
|
||||
SLPM-65864:
|
||||
name: "Nobunaga no Yabou - Tenka Sousei [with Power-Up Kit]"
|
||||
region: "NTSC-J"
|
||||
@@ -24962,6 +25088,14 @@ SLPM-66077:
|
||||
name: "K-1 World Max 2005"
|
||||
region: "NTSC-J"
|
||||
compat: 5
|
||||
gameFixes:
|
||||
- XGKickHack # Fixes black and white fighters.
|
||||
patches:
|
||||
08E3C435:
|
||||
content: |-
|
||||
comment=Fixes black screen in hardware mode.
|
||||
patch=1,EE,003dfe60,word,0000948c
|
||||
patch=1,EE,003dfe88,word,0000948c
|
||||
SLPM-66078:
|
||||
name: "White Princess the Second"
|
||||
region: "NTSC-J"
|
||||
@@ -25646,6 +25780,13 @@ SLPM-66294:
|
||||
SLPM-66295:
|
||||
name: "Yamiyo ni Sasayaku - Tantei Sagara Kyouichirou [Limited Edition]"
|
||||
region: "NTSC-J"
|
||||
patches:
|
||||
23A9A026:
|
||||
content: |-
|
||||
author=PSI, Jelta
|
||||
// Game does weird stack manipulation, causing data sent to the IOP to be corrupted unless EE data cache is enabled.
|
||||
// This patch skips over the stack code, allowing the game to boot.
|
||||
patch=1,EE,00156888,word,10000003
|
||||
SLPM-66296:
|
||||
name: "Yamiyo ni Sasayaku - Tantei Sagara Kyouichirou"
|
||||
region: "NTSC-J"
|
||||
@@ -25842,6 +25983,8 @@ SLPM-66356:
|
||||
SLPM-66358:
|
||||
name: "Shinobido Takumi"
|
||||
region: "NTSC-J"
|
||||
clampModes:
|
||||
eeClampMode: 3 # Fixes crash after main menu.
|
||||
SLPM-66359:
|
||||
name: "Mutsu-boshi Kirari - Hoshifuru Miyako"
|
||||
region: "NTSC-J"
|
||||
@@ -25956,6 +26099,13 @@ SLPM-66398:
|
||||
SLPM-66399:
|
||||
name: "Samurai 7 [Limited Edition]"
|
||||
region: "NTSC-J"
|
||||
patches:
|
||||
836F4606:
|
||||
content: |-
|
||||
author=PSI, Jelta
|
||||
// Game does weird stack manipulation, causing data sent to the IOP to be corrupted unless EE data cache is enabled.
|
||||
// This patch skips over the stack code, allowing the game to boot.
|
||||
patch=1,EE,00157F78,word,10000003
|
||||
SLPM-66400:
|
||||
name: "Samurai 7"
|
||||
region: "NTSC-J"
|
||||
@@ -26123,6 +26273,12 @@ SLPM-66450:
|
||||
SLPM-66451:
|
||||
name: "Major League Baseball 2K6"
|
||||
region: "NTSC-J"
|
||||
patches:
|
||||
F0393708:
|
||||
content: |-
|
||||
author=Prafull
|
||||
comment=fixes hang at start
|
||||
patch=1,EE,0035d8b8,word,00000000
|
||||
SLPM-66452:
|
||||
name: "Kamaitachi no Yoru 3"
|
||||
region: "NTSC-J"
|
||||
@@ -26323,6 +26479,8 @@ SLPM-66502:
|
||||
SLPM-66503:
|
||||
name: "Metal Gear Solid 2 [Mega Hits]"
|
||||
region: "NTSC-J"
|
||||
gameFixes:
|
||||
- EETimingHack # Fixes broken half-bottom artifacts.
|
||||
SLPM-66504:
|
||||
name: "Onimusha 2 [Mega Hits]"
|
||||
region: "NTSC-J"
|
||||
@@ -27266,6 +27424,8 @@ SLPM-66791:
|
||||
SLPM-66792:
|
||||
name: "Metal Gear Solid 2 - Sons of Liberty [20th Anniversary Edition]"
|
||||
region: "NTSC-J"
|
||||
gameFixes:
|
||||
- EETimingHack # Fixes broken half-bottom artifacts.
|
||||
SLPM-66794:
|
||||
name: "Metal Gear Solid 3 - Snake Eater [20th Anniversary Edition]"
|
||||
region: "NTSC-J"
|
||||
@@ -27782,6 +27942,9 @@ SLPM-66978:
|
||||
name: "Persona 4 [Konami-style Special Edition]"
|
||||
region: "NTSC-J"
|
||||
compat: 5
|
||||
SLPM-66980:
|
||||
name: "Gin no Eclipse"
|
||||
region: "NTSC-J"
|
||||
SLPM-66987:
|
||||
name: "Kowloon Youma Gakuen Ki [Best Version]"
|
||||
region: "NTSC-J"
|
||||
@@ -27825,6 +27988,8 @@ SLPM-67000:
|
||||
SLPM-67002:
|
||||
name: "Metal Gear Solid 2 - Substance"
|
||||
region: "NTSC-J"
|
||||
gameFixes:
|
||||
- EETimingHack # Fixes broken half-bottom artifacts.
|
||||
SLPM-67003:
|
||||
name: "Sakura Taisen - Atsuki Chishioni"
|
||||
region: "NTSC-J"
|
||||
@@ -28374,6 +28539,8 @@ SLPS-20048:
|
||||
SLPS-20050:
|
||||
name: "Happy! Happy!! Boarders in Hokkaidou Rusutsu Resort"
|
||||
region: "NTSC-J"
|
||||
speedHacks:
|
||||
mvuFlagSpeedHack: 0 # Fixes graphical issues.
|
||||
SLPS-20051:
|
||||
name: "Hissatsu Pachinko Station V"
|
||||
region: "NTSC-J"
|
||||
@@ -28603,6 +28770,15 @@ SLPS-20187:
|
||||
name: "Black Matrix 2"
|
||||
region: "NTSC-J"
|
||||
compat: 5
|
||||
SLPS-20190:
|
||||
name: "Netsu Chu! Pro Yakyuu 2002"
|
||||
region: "NTSC-J"
|
||||
patches:
|
||||
78E100AD:
|
||||
content: |-
|
||||
author=Prafull
|
||||
comment=fixes hang before ingame
|
||||
patch=1,EE,001022c0,word,00000000
|
||||
SLPS-20194:
|
||||
name: "Underwater Unit"
|
||||
region: "NTSC-J"
|
||||
@@ -28690,7 +28866,7 @@ SLPS-20272:
|
||||
region: "NTSC-J"
|
||||
compat: 5
|
||||
SLPS-20273:
|
||||
name: "Netsu Chu! Pro Baseball 2003"
|
||||
name: "Netsu Chu! Pro Yakyuu 2003"
|
||||
region: "NTSC-J"
|
||||
patches:
|
||||
34fb1fb7:
|
||||
@@ -28776,8 +28952,14 @@ SLPS-20321:
|
||||
region: "NTSC-J"
|
||||
compat: 5
|
||||
SLPS-20322:
|
||||
name: "Netsu Chu! Pro Baseball 2003 Fall"
|
||||
name: "Netsu Chu! Pro Yakyuu 2003: Aki no Night Matsuri"
|
||||
region: "NTSC-J"
|
||||
patches:
|
||||
D3DAF7F4:
|
||||
content: |-
|
||||
author=Prafull
|
||||
comment=fixes hang before ingame
|
||||
patch=1,EE,00102398,word,00000000
|
||||
SLPS-20323:
|
||||
name: "Pochi to Nyaa"
|
||||
region: "NTSC-J"
|
||||
@@ -29098,6 +29280,12 @@ SLPS-20453:
|
||||
compat: 5
|
||||
gameFixes:
|
||||
- XGKickHack # Fixes black and white fighters.
|
||||
patches:
|
||||
602B7A48:
|
||||
content: |-
|
||||
comment=Fixes black screen in hardware mode.
|
||||
patch=1,EE,00336a20,word,0000948c
|
||||
patch=1,EE,00336a48,word,0000948c
|
||||
SLPS-20454:
|
||||
name: "Simple 2000 Series Vol.93 - The Right Brain Drill"
|
||||
region: "NTSC-J"
|
||||
@@ -30040,6 +30228,8 @@ SLPS-25250:
|
||||
SLPS-25251:
|
||||
name: "MVP Baseball 2003"
|
||||
region: "NTSC-J"
|
||||
clampModes:
|
||||
vuClampMode: 3 # Fixes missing environment.
|
||||
SLPS-25252:
|
||||
name: "Star wars - Jango Fett"
|
||||
region: "NTSC-J"
|
||||
@@ -31113,6 +31303,14 @@ SLPS-25577:
|
||||
SLPS-25578:
|
||||
name: "K-1 World Grand Prix 2005"
|
||||
region: "NTSC-J"
|
||||
gameFixes:
|
||||
- XGKickHack # Fixes black and white fighters.
|
||||
patches:
|
||||
F8664E20:
|
||||
content: |-
|
||||
comment=Fixes black screen in hardware mode.
|
||||
patch=1,EE,004269f0,word,0000948c
|
||||
patch=1,EE,00426a18,word,0000948c
|
||||
SLPS-25579:
|
||||
name: "Little Aid"
|
||||
region: "NTSC-J"
|
||||
@@ -33219,6 +33417,8 @@ SLUS-20144:
|
||||
name: "Metal Gear Solid 2 - Sons of Liberty"
|
||||
region: "NTSC-U"
|
||||
compat: 5
|
||||
gameFixes:
|
||||
- EETimingHack # Fixes broken half-bottom artifacts.
|
||||
SLUS-20145:
|
||||
name: "Ring of Red"
|
||||
region: "NTSC-U"
|
||||
@@ -34920,6 +35120,8 @@ SLUS-20554:
|
||||
name: "Metal Gear Solid 2 - Substance"
|
||||
region: "NTSC-U"
|
||||
compat: 5
|
||||
gameFixes:
|
||||
- EETimingHack # Fixes broken half-bottom artifacts.
|
||||
SLUS-20555:
|
||||
name: "Reel Fishing 3"
|
||||
region: "NTSC-U"
|
||||
@@ -35342,6 +35544,8 @@ SLUS-20649:
|
||||
SLUS-20650:
|
||||
name: "MVP Baseball 2003"
|
||||
region: "NTSC-U"
|
||||
clampModes:
|
||||
vuClampMode: 3 # Fixes missing environment.
|
||||
SLUS-20651:
|
||||
name: "NBA Street Vol. 2"
|
||||
region: "NTSC-U"
|
||||
@@ -38117,6 +38321,8 @@ SLUS-21283:
|
||||
name: "Total Overdose - A Gunslinger's Tale in Mexico"
|
||||
region: "NTSC-U"
|
||||
compat: 5
|
||||
gameFixes:
|
||||
- VUKickstartHack # Fixes SPS.
|
||||
SLUS-21284:
|
||||
name: "Nicktoons Unite!"
|
||||
region: "NTSC-U"
|
||||
@@ -38732,6 +38938,8 @@ SLUS-21416:
|
||||
name: "D1 Grand Prix"
|
||||
region: "NTSC-U"
|
||||
compat: 5
|
||||
clampModes:
|
||||
eeClampMode: 3 # Fixes black screen.
|
||||
SLUS-21417:
|
||||
name: "Xenosaga - Episode III - Also Sprach Zarathustra [Disc2of2]"
|
||||
region: "NTSC-U"
|
||||
@@ -39263,6 +39471,12 @@ SLUS-21560:
|
||||
SLUS-21561:
|
||||
name: "Major League Baseball 2K7"
|
||||
region: "NTSC-U"
|
||||
patches:
|
||||
73D6D171:
|
||||
content: |-
|
||||
author=Prafull
|
||||
comment=fixes hang at start
|
||||
patch=1,EE,003CDE10,word,00000000
|
||||
SLUS-21563:
|
||||
name: "Horsez"
|
||||
region: "NTSC-U"
|
||||
@@ -40561,6 +40775,12 @@ SLUS-21870:
|
||||
SLUS-21871:
|
||||
name: "Major League Baseball 2K9"
|
||||
region: "NTSC-U"
|
||||
patches:
|
||||
72905002:
|
||||
content: |-
|
||||
author=Prafull
|
||||
comment=fixes hang at start
|
||||
patch=1,EE,003CC5D8,word,00000000
|
||||
SLUS-21872:
|
||||
name: "MTV Pimp my Ride - Street Racing"
|
||||
region: "NTSC-U"
|
||||
@@ -40839,6 +41059,12 @@ SLUS-21944:
|
||||
SLUS-21945:
|
||||
name: "Major League Baseball 2K11"
|
||||
region: "NTSC-U"
|
||||
patches:
|
||||
3D621C56:
|
||||
content: |-
|
||||
author=By Prafull
|
||||
comment=fixes hang at start
|
||||
patch=1,EE,003CFE58,word,00000000
|
||||
SLUS-21946:
|
||||
name: "Madden NFL 12"
|
||||
region: "NTSC-U"
|
||||
@@ -40861,6 +41087,12 @@ SLUS-21950:
|
||||
SLUS-21951:
|
||||
name: "Major League Baseball 2K12"
|
||||
region: "NTSC-U"
|
||||
patches:
|
||||
C26C70A9:
|
||||
content: |-
|
||||
author=By Prafull
|
||||
comment=fixes hang at start
|
||||
patch=1,EE,003D4098,word,00000000
|
||||
SLUS-21954:
|
||||
name: "FIFA 13"
|
||||
region: "NTSC-U" # Latin America with En,Fr,Es
|
||||
@@ -41029,6 +41261,8 @@ SLUS-29003:
|
||||
name: "Metal Gear Solid 2 - Sons of Liberty [Demo]"
|
||||
region: "NTSC-U"
|
||||
compat: 5
|
||||
gameFixes:
|
||||
- EETimingHack # Fixes broken half-bottom artifacts.
|
||||
SLUS-29004:
|
||||
name: "Unison & Dead or Alive 2 Hardcore [Demo]"
|
||||
region: "NTSC-U"
|
||||
@@ -49,7 +49,7 @@ VS_OUTPUT vs_main(VS_INPUT input)
|
||||
return output;
|
||||
}
|
||||
|
||||
PS_OUTPUT ps_main0(PS_INPUT input)
|
||||
PS_OUTPUT ps_copy(PS_INPUT input)
|
||||
{
|
||||
PS_OUTPUT output;
|
||||
|
||||
@@ -58,7 +58,7 @@ PS_OUTPUT ps_main0(PS_INPUT input)
|
||||
return output;
|
||||
}
|
||||
|
||||
PS_OUTPUT ps_main7(PS_INPUT input)
|
||||
PS_OUTPUT ps_filter_transparency(PS_INPUT input)
|
||||
{
|
||||
PS_OUTPUT output;
|
||||
|
||||
@@ -95,7 +95,7 @@ float4 ps_scanlines(PS_INPUT input, int i)
|
||||
return sample_c(input.t) * saturate(mask[i] + 0.5f);
|
||||
}
|
||||
|
||||
uint ps_main1(PS_INPUT input) : SV_Target0
|
||||
uint ps_convert_rgba8_16bits(PS_INPUT input) : SV_Target0
|
||||
{
|
||||
float4 c = sample_c(input.t);
|
||||
|
||||
@@ -106,7 +106,7 @@ uint ps_main1(PS_INPUT input) : SV_Target0
|
||||
return (i.x & 0x001f) | (i.y & 0x03e0) | (i.z & 0x7c00) | (i.w & 0x8000);
|
||||
}
|
||||
|
||||
PS_OUTPUT ps_main2(PS_INPUT input)
|
||||
PS_OUTPUT ps_datm1(PS_INPUT input)
|
||||
{
|
||||
PS_OUTPUT output;
|
||||
|
||||
@@ -117,7 +117,7 @@ PS_OUTPUT ps_main2(PS_INPUT input)
|
||||
return output;
|
||||
}
|
||||
|
||||
PS_OUTPUT ps_main3(PS_INPUT input)
|
||||
PS_OUTPUT ps_datm0(PS_INPUT input)
|
||||
{
|
||||
PS_OUTPUT output;
|
||||
|
||||
@@ -128,7 +128,7 @@ PS_OUTPUT ps_main3(PS_INPUT input)
|
||||
return output;
|
||||
}
|
||||
|
||||
PS_OUTPUT ps_main4(PS_INPUT input)
|
||||
PS_OUTPUT ps_mod256(PS_INPUT input)
|
||||
{
|
||||
PS_OUTPUT output;
|
||||
|
||||
@@ -142,7 +142,7 @@ PS_OUTPUT ps_main4(PS_INPUT input)
|
||||
return output;
|
||||
}
|
||||
|
||||
PS_OUTPUT ps_main5(PS_INPUT input) // scanlines
|
||||
PS_OUTPUT ps_filter_scanlines(PS_INPUT input)
|
||||
{
|
||||
PS_OUTPUT output;
|
||||
|
||||
@@ -153,7 +153,7 @@ PS_OUTPUT ps_main5(PS_INPUT input) // scanlines
|
||||
return output;
|
||||
}
|
||||
|
||||
PS_OUTPUT ps_main6(PS_INPUT input) // diagonal
|
||||
PS_OUTPUT ps_filter_diagonal(PS_INPUT input)
|
||||
{
|
||||
PS_OUTPUT output;
|
||||
|
||||
@@ -164,7 +164,7 @@ PS_OUTPUT ps_main6(PS_INPUT input) // diagonal
|
||||
return output;
|
||||
}
|
||||
|
||||
PS_OUTPUT ps_main8(PS_INPUT input) // triangular
|
||||
PS_OUTPUT ps_filter_triangular(PS_INPUT input)
|
||||
{
|
||||
PS_OUTPUT output;
|
||||
|
||||
@@ -177,7 +177,7 @@ PS_OUTPUT ps_main8(PS_INPUT input) // triangular
|
||||
}
|
||||
|
||||
static const float PI = 3.14159265359f;
|
||||
PS_OUTPUT ps_main9(PS_INPUT input) // triangular
|
||||
PS_OUTPUT ps_filter_complex(PS_INPUT input) // triangular
|
||||
{
|
||||
PS_OUTPUT output;
|
||||
|
||||
@@ -191,13 +191,13 @@ PS_OUTPUT ps_main9(PS_INPUT input) // triangular
|
||||
return output;
|
||||
}
|
||||
|
||||
uint ps_main10(PS_INPUT input) : SV_Target0
|
||||
uint ps_convert_float32_32bits(PS_INPUT input) : SV_Target0
|
||||
{
|
||||
// Convert a FLOAT32 depth texture into a 32 bits UINT texture
|
||||
return uint(exp2(32.0f) * sample_c(input.t).r);
|
||||
}
|
||||
|
||||
PS_OUTPUT ps_main11(PS_INPUT input)
|
||||
PS_OUTPUT ps_convert_float32_rgba8(PS_INPUT input)
|
||||
{
|
||||
PS_OUTPUT output;
|
||||
|
||||
@@ -212,7 +212,7 @@ PS_OUTPUT ps_main11(PS_INPUT input)
|
||||
return output;
|
||||
}
|
||||
|
||||
PS_OUTPUT ps_main12(PS_INPUT input)
|
||||
PS_OUTPUT ps_convert_float16_rgb5a1(PS_INPUT input)
|
||||
{
|
||||
PS_OUTPUT output;
|
||||
|
||||
@@ -225,7 +225,7 @@ PS_OUTPUT ps_main12(PS_INPUT input)
|
||||
|
||||
return output;
|
||||
}
|
||||
float ps_main13(PS_INPUT input) : SV_Depth
|
||||
float ps_convert_rgba8_float32(PS_INPUT input) : SV_Depth
|
||||
{
|
||||
// Convert a RRGBA texture into a float depth texture
|
||||
// FIXME: I'm afraid of the accuracy
|
||||
@@ -234,7 +234,7 @@ float ps_main13(PS_INPUT input) : SV_Depth
|
||||
return dot(sample_c(input.t), bitSh);
|
||||
}
|
||||
|
||||
float ps_main14(PS_INPUT input) : SV_Depth
|
||||
float ps_convert_rgba8_float24(PS_INPUT input) : SV_Depth
|
||||
{
|
||||
// Same as above but without the alpha channel (24 bits Z)
|
||||
|
||||
@@ -244,7 +244,7 @@ float ps_main14(PS_INPUT input) : SV_Depth
|
||||
return dot(sample_c(input.t).rgb, bitSh);
|
||||
}
|
||||
|
||||
float ps_main15(PS_INPUT input) : SV_Depth
|
||||
float ps_convert_rgba8_float16(PS_INPUT input) : SV_Depth
|
||||
{
|
||||
// Same as above but without the A/B channels (16 bits Z)
|
||||
|
||||
@@ -255,7 +255,7 @@ float ps_main15(PS_INPUT input) : SV_Depth
|
||||
return dot(sample_c(input.t).rg, bitSh);
|
||||
}
|
||||
|
||||
float ps_main16(PS_INPUT input) : SV_Depth
|
||||
float ps_convert_rgb5a1_float16(PS_INPUT input) : SV_Depth
|
||||
{
|
||||
// Convert a RGB5A1 (saved as RGBA8) color to a 16 bit Z
|
||||
// FIXME: I'm afraid of the accuracy
|
||||
@@ -266,7 +266,7 @@ float ps_main16(PS_INPUT input) : SV_Depth
|
||||
return dot(float4(color), bitSh);
|
||||
}
|
||||
|
||||
PS_OUTPUT ps_main17(PS_INPUT input)
|
||||
PS_OUTPUT ps_convert_rgba_8i(PS_INPUT input)
|
||||
{
|
||||
PS_OUTPUT output;
|
||||
|
||||
@@ -358,7 +358,7 @@ PS_OUTPUT ps_main17(PS_INPUT input)
|
||||
}
|
||||
|
||||
// DUMMY
|
||||
PS_OUTPUT ps_main18(PS_INPUT input)
|
||||
PS_OUTPUT ps_yuv(PS_INPUT input)
|
||||
{
|
||||
PS_OUTPUT output;
|
||||
|
||||
@@ -367,11 +367,11 @@ PS_OUTPUT ps_main18(PS_INPUT input)
|
||||
return output;
|
||||
}
|
||||
|
||||
PS_OUTPUT ps_main19(PS_INPUT input)
|
||||
PS_OUTPUT ps_osd(PS_INPUT input)
|
||||
{
|
||||
PS_OUTPUT output;
|
||||
|
||||
output.c = input.c * float4(1.0, 1.0, 1.0, sample_c(input.t).r);
|
||||
output.c = input.c * float4(1.0, 1.0, 1.0, sample_c(input.t).a);
|
||||
|
||||
return output;
|
||||
}
|
||||
@@ -410,6 +410,23 @@ float4 fetch_red(int2 xy)
|
||||
return sample_p(rt.r) * 255.0f;
|
||||
}
|
||||
|
||||
float4 fetch_green(int2 xy)
|
||||
{
|
||||
float4 rt;
|
||||
|
||||
if ((PS_DEPTH_FMT == 1) || (PS_DEPTH_FMT == 2))
|
||||
{
|
||||
int depth = (fetch_raw_depth(xy) >> 8) & 0xFF;
|
||||
rt = (float4)(depth) / 255.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
rt = fetch_raw_color(xy);
|
||||
}
|
||||
|
||||
return sample_p(rt.g) * 255.0f;
|
||||
}
|
||||
|
||||
float4 fetch_blue(int2 xy)
|
||||
{
|
||||
float4 rt;
|
||||
@@ -427,12 +444,6 @@ float4 fetch_blue(int2 xy)
|
||||
return sample_p(rt.b) * 255.0f;
|
||||
}
|
||||
|
||||
float4 fetch_green(int2 xy)
|
||||
{
|
||||
float4 rt = fetch_raw_color(xy);
|
||||
return sample_p(rt.g) * 255.0f;
|
||||
}
|
||||
|
||||
float4 fetch_alpha(int2 xy)
|
||||
{
|
||||
float4 rt = fetch_raw_color(xy);
|
||||
+5
-8
@@ -52,8 +52,7 @@ layout(std140, binding = 15) uniform cb15
|
||||
|
||||
int EMODA;
|
||||
int EMODC;
|
||||
int _pad0;
|
||||
int _pad1;
|
||||
ivec2 pad_cb15;
|
||||
};
|
||||
#endif
|
||||
|
||||
@@ -63,7 +62,8 @@ layout(std140, binding = 20) uniform cb20
|
||||
vec2 VertexScale;
|
||||
vec2 VertexOffset;
|
||||
|
||||
vec4 TextureOffset;
|
||||
vec2 TextureScale;
|
||||
vec2 TextureOffset;
|
||||
|
||||
vec2 PointSize;
|
||||
uint MaxDepth;
|
||||
@@ -80,7 +80,7 @@ layout(std140, binding = 21) uniform cb21
|
||||
vec4 WH;
|
||||
|
||||
vec2 TA;
|
||||
float pad0_cb21;
|
||||
float MaxDepthPS;
|
||||
float Af;
|
||||
|
||||
uvec4 MskFix;
|
||||
@@ -91,12 +91,9 @@ layout(std140, binding = 21) uniform cb21
|
||||
|
||||
vec4 MinMax;
|
||||
|
||||
vec2 TextureScale;
|
||||
vec2 pad_cb21;
|
||||
vec2 TC_OffsetHack;
|
||||
|
||||
vec3 pad1_cb21;
|
||||
float MaxDepthPS;
|
||||
|
||||
mat4 DitherMatrix;
|
||||
};
|
||||
#endif
|
||||
@@ -42,7 +42,7 @@ in SHADER
|
||||
} PSin;
|
||||
|
||||
// Give a different name so I remember there is a special case!
|
||||
#if defined(ps_main1) || defined(ps_main10)
|
||||
#if defined(ps_convert_rgba8_16bits) || defined(ps_convert_float32_32bits)
|
||||
layout(location = 0) out uint SV_Target1;
|
||||
#else
|
||||
layout(location = 0) out vec4 SV_Target0;
|
||||
@@ -65,15 +65,15 @@ vec4 ps_crt(uint i)
|
||||
return sample_c() * clamp((mask[i] + 0.5f), 0.0f, 1.0f);
|
||||
}
|
||||
|
||||
#ifdef ps_main0
|
||||
void ps_main0()
|
||||
#ifdef ps_copy
|
||||
void ps_copy()
|
||||
{
|
||||
SV_Target0 = sample_c();
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_main1
|
||||
void ps_main1()
|
||||
#ifdef ps_convert_rgba8_16bits
|
||||
void ps_convert_rgba8_16bits()
|
||||
{
|
||||
// Input Color is RGBA8
|
||||
|
||||
@@ -117,16 +117,16 @@ void ps_main1()
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_main10
|
||||
void ps_main10()
|
||||
#ifdef ps_convert_float32_32bits
|
||||
void ps_convert_float32_32bits()
|
||||
{
|
||||
// Convert a GL_FLOAT32 depth texture into a 32 bits UINT texture
|
||||
SV_Target1 = uint(exp2(32.0f) * sample_c().r);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_main11
|
||||
void ps_main11()
|
||||
#ifdef ps_convert_float32_rgba8
|
||||
void ps_convert_float32_rgba8()
|
||||
{
|
||||
// Convert a GL_FLOAT32 depth texture into a RGBA color texture
|
||||
const vec4 bitSh = vec4(exp2(24.0f), exp2(16.0f), exp2(8.0f), exp2(0.0f));
|
||||
@@ -138,8 +138,8 @@ void ps_main11()
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_main12
|
||||
void ps_main12()
|
||||
#ifdef ps_convert_float16_rgb5a1
|
||||
void ps_convert_float16_rgb5a1()
|
||||
{
|
||||
// Convert a GL_FLOAT32 (only 16 lsb) depth into a RGB5A1 color texture
|
||||
const vec4 bitSh = vec4(exp2(32.0f), exp2(27.0f), exp2(22.0f), exp2(17.0f));
|
||||
@@ -150,8 +150,8 @@ void ps_main12()
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_main13
|
||||
void ps_main13()
|
||||
#ifdef ps_convert_rgba8_float32
|
||||
void ps_convert_rgba8_float32()
|
||||
{
|
||||
// Convert a RRGBA texture into a float depth texture
|
||||
// FIXME: I'm afraid of the accuracy
|
||||
@@ -160,8 +160,8 @@ void ps_main13()
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_main14
|
||||
void ps_main14()
|
||||
#ifdef ps_convert_rgba8_float24
|
||||
void ps_convert_rgba8_float24()
|
||||
{
|
||||
// Same as above but without the alpha channel (24 bits Z)
|
||||
|
||||
@@ -172,8 +172,8 @@ void ps_main14()
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_main15
|
||||
void ps_main15()
|
||||
#ifdef ps_convert_rgba8_float16
|
||||
void ps_convert_rgba8_float16()
|
||||
{
|
||||
// Same as above but without the A/B channels (16 bits Z)
|
||||
|
||||
@@ -184,8 +184,8 @@ void ps_main15()
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_main16
|
||||
void ps_main16()
|
||||
#ifdef ps_convert_rgb5a1_float16
|
||||
void ps_convert_rgb5a1_float16()
|
||||
{
|
||||
// Convert a RGB5A1 (saved as RGBA8) color to a 16 bit Z
|
||||
// FIXME: I'm afraid of the accuracy
|
||||
@@ -196,8 +196,8 @@ void ps_main16()
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_main17
|
||||
void ps_main17()
|
||||
#ifdef ps_convert_rgba_8i
|
||||
void ps_convert_rgba_8i()
|
||||
{
|
||||
|
||||
// Potential speed optimization. There is a high probability that
|
||||
@@ -278,15 +278,15 @@ void ps_main17()
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_main19
|
||||
void ps_main19()
|
||||
#ifdef ps_osd
|
||||
void ps_osd()
|
||||
{
|
||||
SV_Target0 = PSin.c * vec4(1.0, 1.0, 1.0, sample_c().r);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_main7
|
||||
void ps_main7()
|
||||
#ifdef ps_filter_transparency
|
||||
void ps_filter_transparency()
|
||||
{
|
||||
vec4 c = sample_c();
|
||||
|
||||
@@ -296,7 +296,7 @@ void ps_main7()
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_main5
|
||||
#ifdef ps_filter_scanlines
|
||||
vec4 ps_scanlines(uint i)
|
||||
{
|
||||
vec4 mask[2] =
|
||||
@@ -308,7 +308,7 @@ vec4 ps_scanlines(uint i)
|
||||
return sample_c() * clamp((mask[i] + 0.5f), 0.0f, 1.0f);
|
||||
}
|
||||
|
||||
void ps_main5() // scanlines
|
||||
void ps_filter_scanlines() // scanlines
|
||||
{
|
||||
highp uvec4 p = uvec4(gl_FragCoord);
|
||||
|
||||
@@ -318,8 +318,8 @@ void ps_main5() // scanlines
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_main6
|
||||
void ps_main6() // diagonal
|
||||
#ifdef ps_filter_diagonal
|
||||
void ps_filter_diagonal() // diagonal
|
||||
{
|
||||
highp uvec4 p = uvec4(gl_FragCoord);
|
||||
|
||||
@@ -329,8 +329,8 @@ void ps_main6() // diagonal
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_main8
|
||||
void ps_main8() // triangular
|
||||
#ifdef ps_filter_triangular
|
||||
void ps_filter_triangular() // triangular
|
||||
{
|
||||
highp uvec4 p = uvec4(gl_FragCoord);
|
||||
|
||||
@@ -340,8 +340,8 @@ void ps_main8() // triangular
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_main9
|
||||
void ps_main9()
|
||||
#ifdef ps_filter_complex
|
||||
void ps_filter_complex()
|
||||
{
|
||||
|
||||
const float PI = 3.14159265359f;
|
||||
@@ -362,8 +362,8 @@ void ps_main9()
|
||||
|
||||
// Used for DATE (stencil)
|
||||
// DATM == 1
|
||||
#ifdef ps_main2
|
||||
void ps_main2()
|
||||
#ifdef ps_datm1
|
||||
void ps_datm1()
|
||||
{
|
||||
if(sample_c().a < (127.5f / 255.0f)) // >= 0x80 pass
|
||||
discard;
|
||||
@@ -372,23 +372,23 @@ void ps_main2()
|
||||
|
||||
// Used for DATE (stencil)
|
||||
// DATM == 0
|
||||
#ifdef ps_main3
|
||||
void ps_main3()
|
||||
#ifdef ps_datm0
|
||||
void ps_datm0()
|
||||
{
|
||||
if((127.5f / 255.0f) < sample_c().a) // < 0x80 pass (== 0x80 should not pass)
|
||||
discard;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_main4
|
||||
void ps_main4()
|
||||
#ifdef ps_mod256
|
||||
void ps_mod256()
|
||||
{
|
||||
SV_Target0 = mod(round(sample_c() * 255.0f), 256.0f) / 255.0f;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_main18
|
||||
void ps_main18()
|
||||
#ifdef ps_yuv
|
||||
void ps_yuv()
|
||||
{
|
||||
vec4 i = sample_c();
|
||||
vec4 o;
|
||||
@@ -369,6 +369,17 @@ vec4 fetch_red()
|
||||
return sample_p(rt.r) * 255.0f;
|
||||
}
|
||||
|
||||
vec4 fetch_green()
|
||||
{
|
||||
#if PS_DEPTH_FMT == 1 || PS_DEPTH_FMT == 2
|
||||
int depth = (fetch_raw_depth() >> 8) & 0xFF;
|
||||
vec4 rt = vec4(depth) / 255.0f;
|
||||
#else
|
||||
vec4 rt = fetch_raw_color();
|
||||
#endif
|
||||
return sample_p(rt.g) * 255.0f;
|
||||
}
|
||||
|
||||
vec4 fetch_blue()
|
||||
{
|
||||
#if PS_DEPTH_FMT == 1 || PS_DEPTH_FMT == 2
|
||||
@@ -380,12 +391,6 @@ vec4 fetch_blue()
|
||||
return sample_p(rt.b) * 255.0f;
|
||||
}
|
||||
|
||||
vec4 fetch_green()
|
||||
{
|
||||
vec4 rt = fetch_raw_color();
|
||||
return sample_p(rt.g) * 255.0f;
|
||||
}
|
||||
|
||||
vec4 fetch_alpha()
|
||||
{
|
||||
vec4 rt = fetch_raw_color();
|
||||
@@ -24,8 +24,8 @@ const float exp_min32 = exp2(-32.0f);
|
||||
|
||||
void texture_coord()
|
||||
{
|
||||
vec2 uv = vec2(i_uv) - TextureOffset.xy;
|
||||
vec2 st = i_st - TextureOffset.xy;
|
||||
vec2 uv = vec2(i_uv) - TextureOffset;
|
||||
vec2 st = i_st - TextureOffset;
|
||||
|
||||
// Float coordinate
|
||||
VSout.t_float.xy = st;
|
||||
@@ -43,7 +43,6 @@ option(BUILD_REPLAY_LOADERS "Build GS replayer to ease testing (developer option
|
||||
# Path and lib option
|
||||
#-------------------------------------------------------------------------------
|
||||
option(PACKAGE_MODE "Use this option to ease packaging of PCSX2 (developer/distribution option)")
|
||||
option(DISABLE_CHEATS_ZIP "Disable including the cheats_ws.zip file")
|
||||
option(DISABLE_PCSX2_WRAPPER "Disable including the PCSX2-linux.sh file")
|
||||
option(DISABLE_SETCAP "Do not set files capabilities")
|
||||
option(XDG_STD "Use XDG standard path instead of the standard PCSX2 path")
|
||||
@@ -59,7 +58,7 @@ endif()
|
||||
if(PACKAGE_MODE)
|
||||
# Compile all source codes with those defines
|
||||
list(APPEND PCSX2_DEFS
|
||||
GAMEINDEX_DIR_COMPILATION=${CMAKE_INSTALL_FULL_DATADIR}/PCSX2
|
||||
PCSX2_APP_DATADIR="${CMAKE_INSTALL_FULL_DATADIR}/PCSX2"
|
||||
DOC_DIR_COMPILATION=${CMAKE_INSTALL_FULL_DOCDIR})
|
||||
endif()
|
||||
|
||||
@@ -73,7 +72,7 @@ endif()
|
||||
#-------------------------------------------------------------------------------
|
||||
option(USE_ASAN "Enable address sanitizer")
|
||||
|
||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang")
|
||||
set(USE_CLANG TRUE)
|
||||
message(STATUS "Building with Clang/LLVM.")
|
||||
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Intel")
|
||||
@@ -215,7 +214,10 @@ option(USE_PGO_OPTIMIZE "Enable PGO optimization (use profile)")
|
||||
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)
|
||||
add_compile_options(-pipe -fvisibility=hidden -pthread -fno-builtin-strcmp -fno-builtin-memcmp -mfpmath=sse)
|
||||
|
||||
# -fno-operator-names should only be for C++ files, not C files.
|
||||
add_compile_options($<$<COMPILE_LANGUAGE:CXX>:-fno-operator-names>)
|
||||
endif()
|
||||
|
||||
if(WIN32)
|
||||
|
||||
+38
-36
@@ -2,16 +2,13 @@
|
||||
#
|
||||
# This will define:
|
||||
#
|
||||
# WAYLAND_FOUND - True if Wayland is found
|
||||
# WAYLAND_LIBRARIES - Link these to use Wayland
|
||||
# WAYLAND_INCLUDE_DIR - Include directory for Wayland
|
||||
# WAYLAND_DEFINITIONS - Compiler flags for using Wayland
|
||||
# Wayland_FOUND - True if Wayland is found
|
||||
#
|
||||
# In addition the following more fine grained variables will be defined:
|
||||
#
|
||||
# WAYLAND_CLIENT_FOUND WAYLAND_CLIENT_INCLUDE_DIR WAYLAND_CLIENT_LIBRARIES
|
||||
# WAYLAND_SERVER_FOUND WAYLAND_SERVER_INCLUDE_DIR WAYLAND_SERVER_LIBRARIES
|
||||
# WAYLAND_EGL_FOUND WAYLAND_EGL_INCLUDE_DIR WAYLAND_EGL_LIBRARIES
|
||||
# The following imported targets:
|
||||
# Wayland::Client - Imported Client
|
||||
# Wayland::Server - Imported Server
|
||||
# Wayland::Egl - Imported Egl
|
||||
# Wayland::Cursor - Imported Cursor
|
||||
#
|
||||
# Copyright (c) 2013 Martin Gräßlin <mgraesslin@kde.org>
|
||||
#
|
||||
@@ -24,39 +21,44 @@ IF (NOT WIN32)
|
||||
SET(WAYLAND_FIND_QUIETLY TRUE)
|
||||
ENDIF ()
|
||||
|
||||
# Use pkg-config to get the directories and then use these values
|
||||
# in the FIND_PATH() and FIND_LIBRARY() calls
|
||||
FIND_PACKAGE(PkgConfig)
|
||||
PKG_CHECK_MODULES(PKG_WAYLAND QUIET wayland-client wayland-server wayland-egl wayland-cursor)
|
||||
FIND_PATH(WAYLAND_CLIENT_INCLUDE_DIR NAMES wayland-client.h)
|
||||
FIND_PATH(WAYLAND_SERVER_INCLUDE_DIR NAMES wayland-server.h)
|
||||
FIND_PATH(WAYLAND_EGL_INCLUDE_DIR NAMES wayland-egl.h)
|
||||
FIND_PATH(WAYLAND_CURSOR_INCLUDE_DIR NAMES wayland-cursor.h)
|
||||
|
||||
SET(WAYLAND_DEFINITIONS ${PKG_WAYLAND_CFLAGS})
|
||||
|
||||
FIND_PATH(WAYLAND_CLIENT_INCLUDE_DIR NAMES wayland-client.h HINTS ${PKG_WAYLAND_INCLUDE_DIRS})
|
||||
FIND_PATH(WAYLAND_SERVER_INCLUDE_DIR NAMES wayland-server.h HINTS ${PKG_WAYLAND_INCLUDE_DIRS})
|
||||
FIND_PATH(WAYLAND_EGL_INCLUDE_DIR NAMES wayland-egl.h HINTS ${PKG_WAYLAND_INCLUDE_DIRS})
|
||||
FIND_PATH(WAYLAND_CURSOR_INCLUDE_DIR NAMES wayland-cursor.h HINTS ${PKG_WAYLAND_INCLUDE_DIRS})
|
||||
|
||||
FIND_LIBRARY(WAYLAND_CLIENT_LIBRARIES NAMES wayland-client HINTS ${PKG_WAYLAND_LIBRARY_DIRS})
|
||||
FIND_LIBRARY(WAYLAND_SERVER_LIBRARIES NAMES wayland-server HINTS ${PKG_WAYLAND_LIBRARY_DIRS})
|
||||
FIND_LIBRARY(WAYLAND_EGL_LIBRARIES NAMES wayland-egl HINTS ${PKG_WAYLAND_LIBRARY_DIRS})
|
||||
FIND_LIBRARY(WAYLAND_CURSOR_LIBRARIES NAMES wayland-cursor HINTS ${PKG_WAYLAND_LIBRARY_DIRS})
|
||||
|
||||
set(WAYLAND_INCLUDE_DIR ${WAYLAND_CLIENT_INCLUDE_DIR} ${WAYLAND_SERVER_INCLUDE_DIR} ${WAYLAND_EGL_INCLUDE_DIR} ${WAYLAND_CURSOR_INCLUDE_DIR})
|
||||
|
||||
set(WAYLAND_LIBRARIES ${WAYLAND_CLIENT_LIBRARIES} ${WAYLAND_SERVER_LIBRARIES} ${WAYLAND_EGL_LIBRARIES} ${WAYLAND_CURSOR_LIBRARIES})
|
||||
|
||||
list(REMOVE_DUPLICATES WAYLAND_INCLUDE_DIR)
|
||||
FIND_LIBRARY(WAYLAND_CLIENT_LIBRARIES NAMES wayland-client)
|
||||
FIND_LIBRARY(WAYLAND_SERVER_LIBRARIES NAMES wayland-server)
|
||||
FIND_LIBRARY(WAYLAND_EGL_LIBRARIES NAMES wayland-egl)
|
||||
FIND_LIBRARY(WAYLAND_CURSOR_LIBRARIES NAMES wayland-cursor)
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
|
||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(WAYLAND_CLIENT DEFAULT_MSG WAYLAND_CLIENT_LIBRARIES WAYLAND_CLIENT_INCLUDE_DIR)
|
||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(WAYLAND_SERVER DEFAULT_MSG WAYLAND_SERVER_LIBRARIES WAYLAND_SERVER_INCLUDE_DIR)
|
||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(WAYLAND_EGL DEFAULT_MSG WAYLAND_EGL_LIBRARIES WAYLAND_EGL_INCLUDE_DIR)
|
||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(WAYLAND_CURSOR DEFAULT_MSG WAYLAND_CURSOR_LIBRARIES WAYLAND_CURSOR_INCLUDE_DIR)
|
||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(WAYLAND DEFAULT_MSG WAYLAND_LIBRARIES WAYLAND_INCLUDE_DIR)
|
||||
# FIND_PACKAGE_HANDLE_STANDARD_ARGS is just meant to find the main package and set package found. Not set variables or find individual libs
|
||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(Wayland REQUIRED_VARS
|
||||
WAYLAND_CLIENT_LIBRARIES WAYLAND_CLIENT_INCLUDE_DIR
|
||||
WAYLAND_SERVER_LIBRARIES WAYLAND_SERVER_INCLUDE_DIR
|
||||
WAYLAND_EGL_LIBRARIES WAYLAND_EGL_INCLUDE_DIR
|
||||
WAYLAND_CURSOR_LIBRARIES WAYLAND_CURSOR_INCLUDE_DIR
|
||||
)
|
||||
|
||||
if (WAYLAND_CLIENT_INCLUDE_DIR AND WAYLAND_CLIENT_LIBRARIES AND NOT TARGET Wayland::Client)
|
||||
add_library(Wayland::Client UNKNOWN IMPORTED)
|
||||
set_target_properties(Wayland::Client PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${WAYLAND_CLIENT_INCLUDE_DIR}" IMPORTED_LOCATION "${WAYLAND_CLIENT_LIBRARIES}")
|
||||
endif()
|
||||
if (WAYLAND_SERVER_INCLUDE_DIR AND WAYLAND_SERVER_LIBRARIES AND NOT TARGET Wayland::Server)
|
||||
add_library(Wayland::Server UNKNOWN IMPORTED)
|
||||
set_target_properties(Wayland::Server PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${WAYLAND_SERVER_INCLUDE_DIR}" IMPORTED_LOCATION "${WAYLAND_SERVER_LIBRARIES}")
|
||||
endif()
|
||||
if (WAYLAND_EGL_INCLUDE_DIR AND WAYLAND_EGL_LIBRARIES AND NOT TARGET Wayland::Egl)
|
||||
add_library(Wayland::Egl UNKNOWN IMPORTED)
|
||||
set_target_properties(Wayland::Egl PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${WAYLAND_EGL_INCLUDE_DIR}" IMPORTED_LOCATION "${WAYLAND_EGL_LIBRARIES}")
|
||||
endif()
|
||||
if (WAYLAND_CURSOR_INCLUDE_DIR AND WAYLAND_CURSOR_LIBRARIES AND NOT TARGET Wayland::Cursor)
|
||||
add_library(Wayland::Cursor UNKNOWN IMPORTED)
|
||||
set_target_properties(Wayland::Cursor PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${WAYLAND_CURSOR_INCLUDE_DIR}" IMPORTED_LOCATION "${WAYLAND_CURSOR_LIBRARIES}")
|
||||
endif()
|
||||
|
||||
MARK_AS_ADVANCED(
|
||||
WAYLAND_INCLUDE_DIR WAYLAND_LIBRARIES
|
||||
WAYLAND_CLIENT_INCLUDE_DIR WAYLAND_CLIENT_LIBRARIES
|
||||
WAYLAND_SERVER_INCLUDE_DIR WAYLAND_SERVER_LIBRARIES
|
||||
WAYLAND_EGL_INCLUDE_DIR WAYLAND_EGL_LIBRARIES
|
||||
|
||||
@@ -162,11 +162,7 @@ else()
|
||||
if(UNIX AND NOT APPLE)
|
||||
find_package(X11 REQUIRED)
|
||||
make_imported_target_if_missing(X11::X11 X11)
|
||||
endif()
|
||||
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)
|
||||
alias_library(GTK::gtk GTK2::gtk)
|
||||
|
||||
@@ -18,8 +18,8 @@
|
||||
|
||||
#if !defined(_WIN32)
|
||||
|
||||
#include "common/AlignedMalloc.h"
|
||||
#include "common/Assertions.h"
|
||||
#include "common/ScopedAlloc.h"
|
||||
|
||||
void* __fastcall _aligned_malloc(size_t size, size_t align)
|
||||
{
|
||||
|
||||
@@ -80,50 +80,57 @@ extern Fnptr_OutOfMemory pxDoOutOfMemory;
|
||||
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// BaseScopedAlloc
|
||||
// AlignedBuffer
|
||||
// --------------------------------------------------------------------------------------
|
||||
// Base class that allows various ScopedMalloc types to be passed to functions that act
|
||||
// on them.
|
||||
// A simple container class for an aligned allocation. By default, no bounds checking is
|
||||
// performed, and there is no option for enabling bounds checking. If bounds checking and
|
||||
// other features are needed, use the more robust SafeArray<> instead.
|
||||
//
|
||||
// Rationale: This class and the derived varieties are provided as a simple autonomous self-
|
||||
// destructing container for malloc. The entire class is almost completely dependency free,
|
||||
// and thus can be included everywhere and anywhere without dependency hassles.
|
||||
//
|
||||
template <typename T>
|
||||
class BaseScopedAlloc
|
||||
template <typename T, uint align>
|
||||
class AlignedBuffer
|
||||
{
|
||||
protected:
|
||||
T* m_buffer;
|
||||
uint m_size;
|
||||
static_assert(std::is_pod<T>::value, "Must use a POD type");
|
||||
|
||||
struct Deleter
|
||||
{
|
||||
void operator()(T* ptr)
|
||||
{
|
||||
_aligned_free(ptr);
|
||||
}
|
||||
};
|
||||
|
||||
std::unique_ptr<T[], Deleter> m_buffer;
|
||||
std::size_t m_size;
|
||||
|
||||
public:
|
||||
BaseScopedAlloc()
|
||||
AlignedBuffer(size_t size = 0)
|
||||
{
|
||||
m_buffer = NULL;
|
||||
m_size = 0;
|
||||
Alloc(size);
|
||||
}
|
||||
|
||||
virtual ~BaseScopedAlloc()
|
||||
{
|
||||
//pxAssert(m_buffer==NULL);
|
||||
}
|
||||
|
||||
public:
|
||||
size_t GetSize() const { return m_size; }
|
||||
size_t GetLength() const { return m_size; }
|
||||
|
||||
// Allocates the object to the specified size. If an existing allocation is in
|
||||
// place, it is freed and replaced with the new allocation, and all data is lost.
|
||||
// Parameter:
|
||||
// newSize - size of the new allocation, in elements (not bytes!). If the specified
|
||||
// size is 0, the the allocation is freed, same as calling Free().
|
||||
virtual void Alloc(size_t newsize) = 0;
|
||||
void Alloc(size_t newsize)
|
||||
{
|
||||
m_size = newsize;
|
||||
m_buffer.reset();
|
||||
if (!m_size)
|
||||
return;
|
||||
|
||||
// Re-sizes the allocation to the requested size, without any data loss.
|
||||
// Parameter:
|
||||
// newSize - size of the new allocation, in elements (not bytes!). If the specified
|
||||
// size is 0, the the allocation is freed, same as calling Free().
|
||||
virtual void Resize(size_t newsize) = 0;
|
||||
m_buffer.reset(reinterpret_cast<T*>(_aligned_malloc(this->m_size * sizeof(T), align)));
|
||||
if (!m_buffer)
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
|
||||
void Resize(size_t newsize)
|
||||
{
|
||||
m_buffer.reset(reinterpret_cast<T*>(pcsx2_aligned_realloc(m_buffer.release(), newsize * sizeof(T), align, m_size * sizeof(T))));
|
||||
m_size = newsize;
|
||||
|
||||
if (!m_buffer)
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
|
||||
void Free()
|
||||
{
|
||||
@@ -162,103 +169,3 @@ public:
|
||||
return m_buffer[idx];
|
||||
}
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// ScopedAlloc
|
||||
// --------------------------------------------------------------------------------------
|
||||
// A simple container class for a standard malloc allocation. By default, no bounds checking
|
||||
// is performed, and there is no option for enabling bounds checking. If bounds checking and
|
||||
// other features are needed, use the more robust SafeArray<> instead.
|
||||
//
|
||||
// See docs for BaseScopedAlloc for details and rationale.
|
||||
//
|
||||
template <typename T>
|
||||
class ScopedAlloc : public BaseScopedAlloc<T>
|
||||
{
|
||||
typedef BaseScopedAlloc<T> _parent;
|
||||
|
||||
public:
|
||||
ScopedAlloc(size_t size = 0)
|
||||
: _parent()
|
||||
{
|
||||
Alloc(size);
|
||||
}
|
||||
|
||||
virtual ~ScopedAlloc()
|
||||
{
|
||||
safe_free(this->m_buffer);
|
||||
}
|
||||
|
||||
virtual void Alloc(size_t newsize)
|
||||
{
|
||||
safe_free(this->m_buffer);
|
||||
this->m_size = newsize;
|
||||
if (!this->m_size)
|
||||
return;
|
||||
|
||||
this->m_buffer = (T*)malloc(this->m_size * sizeof(T));
|
||||
if (!this->m_buffer)
|
||||
throw Exception::OutOfMemory(L"ScopedAlloc");
|
||||
}
|
||||
|
||||
virtual void Resize(size_t newsize)
|
||||
{
|
||||
this->m_size = newsize;
|
||||
this->m_buffer = (T*)realloc(this->m_buffer, this->m_size * sizeof(T));
|
||||
|
||||
if (!this->m_buffer)
|
||||
throw Exception::OutOfMemory(L"ScopedAlloc::Resize");
|
||||
}
|
||||
|
||||
using _parent::operator[];
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// ScopedAlignedAlloc
|
||||
// --------------------------------------------------------------------------------------
|
||||
// A simple container class for an aligned allocation. By default, no bounds checking is
|
||||
// performed, and there is no option for enabling bounds checking. If bounds checking and
|
||||
// other features are needed, use the more robust SafeArray<> instead.
|
||||
//
|
||||
// See docs for BaseScopedAlloc for details and rationale.
|
||||
//
|
||||
template <typename T, uint align>
|
||||
class ScopedAlignedAlloc : public BaseScopedAlloc<T>
|
||||
{
|
||||
typedef BaseScopedAlloc<T> _parent;
|
||||
|
||||
public:
|
||||
ScopedAlignedAlloc(size_t size = 0)
|
||||
: _parent()
|
||||
{
|
||||
Alloc(size);
|
||||
}
|
||||
|
||||
virtual ~ScopedAlignedAlloc()
|
||||
{
|
||||
safe_aligned_free(this->m_buffer);
|
||||
}
|
||||
|
||||
virtual void Alloc(size_t newsize)
|
||||
{
|
||||
safe_aligned_free(this->m_buffer);
|
||||
this->m_size = newsize;
|
||||
if (!this->m_size)
|
||||
return;
|
||||
|
||||
this->m_buffer = (T*)_aligned_malloc(this->m_size * sizeof(T), align);
|
||||
if (!this->m_buffer)
|
||||
throw Exception::OutOfMemory(L"ScopedAlignedAlloc");
|
||||
}
|
||||
|
||||
virtual void Resize(size_t newsize)
|
||||
{
|
||||
this->m_buffer = (T*)pcsx2_aligned_realloc(this->m_buffer, newsize * sizeof(T), align, this->m_size * sizeof(T));
|
||||
this->m_size = newsize;
|
||||
|
||||
if (!this->m_buffer)
|
||||
throw Exception::OutOfMemory(L"ScopedAlignedAlloc::Resize");
|
||||
}
|
||||
|
||||
using _parent::operator[];
|
||||
};
|
||||
@@ -20,12 +20,14 @@ target_sources(common PRIVATE
|
||||
FastJmp.cpp
|
||||
GL/Context.cpp
|
||||
GL/StreamBuffer.cpp
|
||||
FileSystem.cpp
|
||||
IniInterface.cpp
|
||||
Mutex.cpp
|
||||
Misc.cpp
|
||||
PathUtils.cpp
|
||||
PrecompiledHeader.cpp
|
||||
Perf.cpp
|
||||
ProgressCallback.cpp
|
||||
pxStreams.cpp
|
||||
pxTranslate.cpp
|
||||
RwMutex.cpp
|
||||
@@ -33,6 +35,7 @@ target_sources(common PRIVATE
|
||||
SettingsWrapper.cpp
|
||||
StringHelpers.cpp
|
||||
StringUtil.cpp
|
||||
Timer.cpp
|
||||
ThreadTools.cpp
|
||||
WindowInfo.cpp
|
||||
emitter/bmi.cpp
|
||||
@@ -61,6 +64,7 @@ target_sources(common PRIVATE
|
||||
# x86emitter headers
|
||||
target_sources(common PRIVATE
|
||||
Align.h
|
||||
AlignedMalloc.h
|
||||
Assertions.h
|
||||
boost_spsc_queue.hpp
|
||||
Console.h
|
||||
@@ -68,6 +72,7 @@ target_sources(common PRIVATE
|
||||
EventSource.h
|
||||
Exceptions.h
|
||||
FastJmp.h
|
||||
FileSystem.h
|
||||
General.h
|
||||
GL/Context.h
|
||||
GL/StreamBuffer.h
|
||||
@@ -76,18 +81,19 @@ target_sources(common PRIVATE
|
||||
Path.h
|
||||
PageFaultSource.h
|
||||
PrecompiledHeader.h
|
||||
ProgressCallback.h
|
||||
pxForwardDefs.h
|
||||
pxStreams.h
|
||||
RedtapeWindows.h
|
||||
RwMutex.h
|
||||
SafeArray.h
|
||||
ScopedAlloc.h
|
||||
ScopedGuard.h
|
||||
ScopedPtrMT.h
|
||||
SettingsInterface.h
|
||||
SettingsWrapper.h
|
||||
StringHelpers.h
|
||||
StringUtil.h
|
||||
Timer.h
|
||||
Threading.h
|
||||
TraceLog.h
|
||||
WindowInfo.h
|
||||
|
||||
@@ -102,7 +102,7 @@
|
||||
pxAssert(EnumIsValid(id)); \
|
||||
} \
|
||||
\
|
||||
extern const wxChar* EnumToString(enumName id)
|
||||
extern const char* EnumToString(enumName id)
|
||||
|
||||
class pxEnumEnd_t
|
||||
{
|
||||
@@ -277,4 +277,4 @@ extern wxString fromAscii(const char* src);
|
||||
|
||||
#include "common/Assertions.h"
|
||||
#include "common/Exceptions.h"
|
||||
#include "common/ScopedAlloc.h"
|
||||
#include "common/AlignedMalloc.h"
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,162 @@
|
||||
/* 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 "Pcsx2Defs.h"
|
||||
#include <cstdio>
|
||||
#include <ctime>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#define FS_OSPATH_SEPARATOR_CHARACTER '\\'
|
||||
#define FS_OSPATH_SEPARATOR_STR "\\"
|
||||
#else
|
||||
#define FS_OSPATH_SEPARATOR_CHARACTER '/'
|
||||
#define FS_OSPATH_SEPARATOR_STR "/"
|
||||
#endif
|
||||
|
||||
enum FILESYSTEM_FILE_ATTRIBUTES
|
||||
{
|
||||
FILESYSTEM_FILE_ATTRIBUTE_DIRECTORY = 1,
|
||||
FILESYSTEM_FILE_ATTRIBUTE_READ_ONLY = 2,
|
||||
FILESYSTEM_FILE_ATTRIBUTE_COMPRESSED = 4,
|
||||
};
|
||||
|
||||
enum FILESYSTEM_FIND_FLAGS
|
||||
{
|
||||
FILESYSTEM_FIND_RECURSIVE = (1 << 0),
|
||||
FILESYSTEM_FIND_RELATIVE_PATHS = (1 << 1),
|
||||
FILESYSTEM_FIND_HIDDEN_FILES = (1 << 2),
|
||||
FILESYSTEM_FIND_FOLDERS = (1 << 3),
|
||||
FILESYSTEM_FIND_FILES = (1 << 4),
|
||||
FILESYSTEM_FIND_KEEP_ARRAY = (1 << 5),
|
||||
};
|
||||
|
||||
struct FILESYSTEM_STAT_DATA
|
||||
{
|
||||
std::time_t ModificationTime;
|
||||
s64 Size;
|
||||
u32 Attributes;
|
||||
};
|
||||
|
||||
struct FILESYSTEM_FIND_DATA
|
||||
{
|
||||
std::time_t ModificationTime;
|
||||
std::string FileName;
|
||||
s64 Size;
|
||||
u32 Attributes;
|
||||
};
|
||||
|
||||
namespace FileSystem
|
||||
{
|
||||
|
||||
using FindResultsArray = std::vector<FILESYSTEM_FIND_DATA>;
|
||||
|
||||
/// Builds a path relative to the specified file
|
||||
std::string BuildRelativePath(const std::string_view& filename, const std::string_view& new_filename);
|
||||
|
||||
/// Joins path components together, producing a new path.
|
||||
std::string JoinPath(const std::string_view& base, const std::string_view& next);
|
||||
|
||||
/// Sanitizes a filename for use in a filesystem.
|
||||
void SanitizeFileName(char* Destination, u32 cbDestination, const char* FileName, bool StripSlashes /* = true */);
|
||||
void SanitizeFileName(std::string& Destination, bool StripSlashes = true);
|
||||
|
||||
/// Returns true if the specified path is an absolute path (C:\Path on Windows or /path on Unix).
|
||||
bool IsAbsolutePath(const std::string_view& path);
|
||||
|
||||
/// Returns a view of the extension of a filename.
|
||||
std::string_view GetExtension(const std::string_view& path);
|
||||
|
||||
/// Removes the extension of a filename.
|
||||
std::string_view StripExtension(const std::string_view& path);
|
||||
|
||||
/// Replaces the extension of a filename with another.
|
||||
std::string ReplaceExtension(const std::string_view& path, const std::string_view& new_extension);
|
||||
|
||||
/// Returns the display name of a filename. Usually this is the same as the path.
|
||||
std::string GetDisplayNameFromPath(const std::string_view& path);
|
||||
|
||||
/// Returns the directory component of a filename.
|
||||
std::string_view GetPathDirectory(const std::string_view& path);
|
||||
|
||||
/// Returns the filename component of a filename.
|
||||
std::string_view GetFileNameFromPath(const std::string_view& path);
|
||||
|
||||
/// Returns the file title (less the extension and path) from a filename.
|
||||
std::string_view GetFileTitleFromPath(const std::string_view& path);
|
||||
|
||||
/// Returns a list of "root directories" (i.e. root/home directories on Linux, drive letters on Windows).
|
||||
std::vector<std::string> GetRootDirectoryList();
|
||||
|
||||
/// Search for files
|
||||
bool FindFiles(const char* path, const char* pattern, u32 flags, FindResultsArray* results);
|
||||
|
||||
/// Stat file
|
||||
bool StatFile(const char* path, struct stat* st);
|
||||
bool StatFile(std::FILE* fp, struct stat* st);
|
||||
bool StatFile(const char* path, FILESYSTEM_STAT_DATA* pStatData);
|
||||
bool StatFile(std::FILE* fp, FILESYSTEM_STAT_DATA* pStatData);
|
||||
s64 GetPathFileSize(const char* path);
|
||||
|
||||
/// File exists?
|
||||
bool FileExists(const char* path);
|
||||
|
||||
/// Directory exists?
|
||||
bool DirectoryExists(const char* path);
|
||||
|
||||
/// Delete file
|
||||
bool DeleteFilePath(const char* path);
|
||||
|
||||
/// Rename file
|
||||
bool RenamePath(const char* OldPath, const char* NewPath);
|
||||
|
||||
/// open files
|
||||
using ManagedCFilePtr = std::unique_ptr<std::FILE, void (*)(std::FILE*)>;
|
||||
ManagedCFilePtr OpenManagedCFile(const char* filename, const char* mode);
|
||||
std::FILE* OpenCFile(const char* filename, const char* mode);
|
||||
int FSeek64(std::FILE* fp, s64 offset, int whence);
|
||||
s64 FTell64(std::FILE* fp);
|
||||
s64 FSize64(std::FILE* fp);
|
||||
|
||||
int OpenFDFile(const char* filename, int flags, int mode);
|
||||
|
||||
std::optional<std::vector<u8>> ReadBinaryFile(const char* filename);
|
||||
std::optional<std::vector<u8>> ReadBinaryFile(std::FILE* fp);
|
||||
std::optional<std::string> ReadFileToString(const char* filename);
|
||||
std::optional<std::string> ReadFileToString(std::FILE* fp);
|
||||
bool WriteBinaryFile(const char* filename, const void* data, size_t data_length);
|
||||
bool WriteFileToString(const char* filename, const std::string_view& sv);
|
||||
|
||||
/// creates a directory in the local filesystem
|
||||
/// if the directory already exists, the return value will be true.
|
||||
/// if Recursive is specified, all parent directories will be created
|
||||
/// if they do not exist.
|
||||
bool CreateDirectoryPath(const char* path, bool recursive);
|
||||
|
||||
/// Returns the path to the current executable.
|
||||
std::string GetProgramPath();
|
||||
|
||||
/// Retrieves the current working directory.
|
||||
std::string GetWorkingDirectory();
|
||||
|
||||
/// Sets the current working directory. Returns true if successful.
|
||||
bool SetWorkingDirectory(const char* path);
|
||||
|
||||
}; // namespace FileSystem
|
||||
@@ -225,6 +225,8 @@ namespace Path
|
||||
extern wxString Combine(const wxString& srcPath, const wxString& srcFile);
|
||||
extern wxString Combine(const wxDirName& srcPath, const wxFileName& srcFile);
|
||||
extern wxString Combine(const wxString& srcPath, const wxDirName& srcFile);
|
||||
extern std::string CombineStdString(const wxDirName& srcPath, const std::string_view& srcFile);
|
||||
extern std::string CombineStdString(const std::string_view& srcPath, const std::string_view& srcFile);
|
||||
extern wxString ReplaceExtension(const wxString& src, const wxString& ext);
|
||||
extern wxString ReplaceFilename(const wxString& src, const wxString& newfilename);
|
||||
extern wxString GetFilename(const wxString& src);
|
||||
|
||||
@@ -149,6 +149,21 @@ wxString Path::Combine(const wxString& srcPath, const wxDirName& srcFile)
|
||||
return (wxDirName(srcPath) + srcFile).ToString();
|
||||
}
|
||||
|
||||
std::string Path::CombineStdString(const wxDirName& srcPath, const std::string_view& srcFile)
|
||||
{
|
||||
const wxString wxResult((srcPath + wxString::FromUTF8(srcFile.data(), srcFile.length())).GetFullPath());
|
||||
const wxCharBuffer wxBuf(wxResult.ToUTF8());
|
||||
return std::string(wxBuf.data(), wxBuf.length());
|
||||
}
|
||||
|
||||
std::string Path::CombineStdString(const std::string_view& srcPath, const std::string_view& srcFile)
|
||||
{
|
||||
const wxDirName srcPathDir(wxString::FromUTF8(srcPath.data(), srcPath.length()));
|
||||
const wxString wxResult((srcPathDir + wxString::FromUTF8(srcFile.data(), srcFile.length())).GetFullPath());
|
||||
const wxCharBuffer wxBuf(wxResult.ToUTF8());
|
||||
return std::string(wxBuf.data(), wxBuf.length());
|
||||
}
|
||||
|
||||
// Replaces the extension of the file with the one given.
|
||||
// This function works for path names as well as file names.
|
||||
wxString Path::ReplaceExtension(const wxString& src, const wxString& ext)
|
||||
|
||||
@@ -0,0 +1,248 @@
|
||||
/* 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/>.
|
||||
*/
|
||||
|
||||
#include "PrecompiledHeader.h"
|
||||
|
||||
#include "Assertions.h"
|
||||
#include "ProgressCallback.h"
|
||||
#include "StringUtil.h"
|
||||
#include "Console.h"
|
||||
#include <cmath>
|
||||
#include <cstdio>
|
||||
#include <limits>
|
||||
|
||||
ProgressCallback::~ProgressCallback() {}
|
||||
|
||||
void ProgressCallback::SetFormattedStatusText(const char* Format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, Format);
|
||||
const std::string str(StringUtil::StdStringFromFormatV(Format, ap));
|
||||
va_end(ap);
|
||||
|
||||
SetStatusText(str.c_str());
|
||||
}
|
||||
|
||||
void ProgressCallback::DisplayFormattedError(const char* format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, format);
|
||||
const std::string str(StringUtil::StdStringFromFormatV(format, ap));
|
||||
va_end(ap);
|
||||
|
||||
DisplayError(str.c_str());
|
||||
}
|
||||
|
||||
void ProgressCallback::DisplayFormattedWarning(const char* format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, format);
|
||||
const std::string str(StringUtil::StdStringFromFormatV(format, ap));
|
||||
va_end(ap);
|
||||
|
||||
DisplayWarning(str.c_str());
|
||||
}
|
||||
|
||||
void ProgressCallback::DisplayFormattedInformation(const char* format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, format);
|
||||
const std::string str(StringUtil::StdStringFromFormatV(format, ap));
|
||||
va_end(ap);
|
||||
|
||||
DisplayInformation(str.c_str());
|
||||
}
|
||||
|
||||
void ProgressCallback::DisplayFormattedDebugMessage(const char* format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, format);
|
||||
const std::string str(StringUtil::StdStringFromFormatV(format, ap));
|
||||
va_end(ap);
|
||||
|
||||
DisplayDebugMessage(str.c_str());
|
||||
}
|
||||
|
||||
void ProgressCallback::DisplayFormattedModalError(const char* format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, format);
|
||||
const std::string str(StringUtil::StdStringFromFormatV(format, ap));
|
||||
va_end(ap);
|
||||
|
||||
ModalError(str.c_str());
|
||||
}
|
||||
|
||||
bool ProgressCallback::DisplayFormattedModalConfirmation(const char* format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, format);
|
||||
const std::string str(StringUtil::StdStringFromFormatV(format, ap));
|
||||
va_end(ap);
|
||||
|
||||
return ModalConfirmation(str.c_str());
|
||||
}
|
||||
|
||||
void ProgressCallback::DisplayFormattedModalInformation(const char* format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, format);
|
||||
const std::string str(StringUtil::StdStringFromFormatV(format, ap));
|
||||
va_end(ap);
|
||||
|
||||
ModalInformation(str.c_str());
|
||||
}
|
||||
|
||||
class NullProgressCallbacks final : public ProgressCallback
|
||||
{
|
||||
public:
|
||||
void PushState() override {}
|
||||
void PopState() override {}
|
||||
|
||||
bool IsCancelled() const override { return false; }
|
||||
bool IsCancellable() const override { return false; }
|
||||
|
||||
void SetCancellable(bool cancellable) override {}
|
||||
void SetTitle(const char* title) override {}
|
||||
void SetStatusText(const char* statusText) override {}
|
||||
void SetProgressRange(u32 range) override {}
|
||||
void SetProgressValue(u32 value) override {}
|
||||
void IncrementProgressValue() override {}
|
||||
|
||||
void DisplayError(const char* message) override { Console.Error("%s", message); }
|
||||
void DisplayWarning(const char* message) override { Console.Warning("%s", message); }
|
||||
void DisplayInformation(const char* message) override { Console.WriteLn("%s", message); }
|
||||
void DisplayDebugMessage(const char* message) override { DevCon.WriteLn("%s", message); }
|
||||
|
||||
void ModalError(const char* message) override { Console.Error(message); }
|
||||
bool ModalConfirmation(const char* message) override
|
||||
{
|
||||
Console.WriteLn("%s", message);
|
||||
return false;
|
||||
}
|
||||
void ModalInformation(const char* message) override { Console.WriteLn("%s", message); }
|
||||
};
|
||||
|
||||
static NullProgressCallbacks s_nullProgressCallbacks;
|
||||
ProgressCallback* ProgressCallback::NullProgressCallback = &s_nullProgressCallbacks;
|
||||
|
||||
BaseProgressCallback::BaseProgressCallback()
|
||||
: m_cancellable(false)
|
||||
, m_cancelled(false)
|
||||
, m_progress_range(1)
|
||||
, m_progress_value(0)
|
||||
, m_base_progress_value(0)
|
||||
, m_saved_state(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
BaseProgressCallback::~BaseProgressCallback()
|
||||
{
|
||||
State* pNextState = m_saved_state;
|
||||
while (pNextState != NULL)
|
||||
{
|
||||
State* pCurrentState = pNextState;
|
||||
pNextState = pCurrentState->next_saved_state;
|
||||
delete pCurrentState;
|
||||
}
|
||||
}
|
||||
|
||||
void BaseProgressCallback::PushState()
|
||||
{
|
||||
State* pNewState = new State;
|
||||
pNewState->cancellable = m_cancellable;
|
||||
pNewState->status_text = m_status_text;
|
||||
pNewState->progress_range = m_progress_range;
|
||||
pNewState->progress_value = m_progress_value;
|
||||
pNewState->base_progress_value = m_base_progress_value;
|
||||
pNewState->next_saved_state = m_saved_state;
|
||||
m_saved_state = pNewState;
|
||||
}
|
||||
|
||||
void BaseProgressCallback::PopState()
|
||||
{
|
||||
pxAssert(m_saved_state);
|
||||
State* state = m_saved_state;
|
||||
m_saved_state = nullptr;
|
||||
|
||||
// impose the current position into the previous range
|
||||
const u32 new_progress_value =
|
||||
(m_progress_range != 0) ?
|
||||
static_cast<u32>(((float)m_progress_value / (float)m_progress_range) * (float)state->progress_range) :
|
||||
state->progress_value;
|
||||
|
||||
m_cancellable = state->cancellable;
|
||||
m_status_text = std::move(state->status_text);
|
||||
m_progress_range = state->progress_range;
|
||||
m_progress_value = new_progress_value;
|
||||
|
||||
m_base_progress_value = state->base_progress_value;
|
||||
m_saved_state = state->next_saved_state;
|
||||
delete state;
|
||||
}
|
||||
|
||||
bool BaseProgressCallback::IsCancelled() const
|
||||
{
|
||||
return m_cancelled;
|
||||
}
|
||||
|
||||
bool BaseProgressCallback::IsCancellable() const
|
||||
{
|
||||
return m_cancellable;
|
||||
}
|
||||
|
||||
void BaseProgressCallback::SetCancellable(bool cancellable)
|
||||
{
|
||||
m_cancellable = cancellable;
|
||||
}
|
||||
|
||||
void BaseProgressCallback::SetStatusText(const char* text)
|
||||
{
|
||||
m_status_text = text;
|
||||
}
|
||||
|
||||
void BaseProgressCallback::SetProgressRange(u32 range)
|
||||
{
|
||||
if (m_saved_state)
|
||||
{
|
||||
// impose the previous range on this range
|
||||
m_progress_range = m_saved_state->progress_range * range;
|
||||
m_base_progress_value = m_progress_value = m_saved_state->progress_value * range;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_progress_range = range;
|
||||
m_progress_value = 0;
|
||||
m_base_progress_value = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void BaseProgressCallback::SetProgressValue(u32 value)
|
||||
{
|
||||
m_progress_value = m_base_progress_value + value;
|
||||
}
|
||||
|
||||
void BaseProgressCallback::IncrementProgressValue()
|
||||
{
|
||||
SetProgressValue((m_progress_value - m_base_progress_value) + 1);
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
/* 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 "Pcsx2Defs.h"
|
||||
#include <string>
|
||||
|
||||
/**
|
||||
* Progress callbacks, abstracts a blocking operation and allows it to report progress
|
||||
* without having any dependency on the UI.
|
||||
*/
|
||||
|
||||
class ProgressCallback
|
||||
{
|
||||
public:
|
||||
virtual ~ProgressCallback();
|
||||
|
||||
virtual void PushState() = 0;
|
||||
virtual void PopState() = 0;
|
||||
|
||||
virtual bool IsCancelled() const = 0;
|
||||
virtual bool IsCancellable() const = 0;
|
||||
|
||||
virtual void SetCancellable(bool cancellable) = 0;
|
||||
|
||||
virtual void SetTitle(const char* title) = 0;
|
||||
virtual void SetStatusText(const char* text) = 0;
|
||||
virtual void SetProgressRange(u32 range) = 0;
|
||||
virtual void SetProgressValue(u32 value) = 0;
|
||||
virtual void IncrementProgressValue() = 0;
|
||||
|
||||
void SetFormattedStatusText(const char* Format, ...);
|
||||
|
||||
virtual void DisplayError(const char* message) = 0;
|
||||
virtual void DisplayWarning(const char* message) = 0;
|
||||
virtual void DisplayInformation(const char* message) = 0;
|
||||
virtual void DisplayDebugMessage(const char* message) = 0;
|
||||
|
||||
virtual void ModalError(const char* message) = 0;
|
||||
virtual bool ModalConfirmation(const char* message) = 0;
|
||||
virtual void ModalInformation(const char* message) = 0;
|
||||
|
||||
void DisplayFormattedError(const char* format, ...);
|
||||
void DisplayFormattedWarning(const char* format, ...);
|
||||
void DisplayFormattedInformation(const char* format, ...);
|
||||
void DisplayFormattedDebugMessage(const char* format, ...);
|
||||
void DisplayFormattedModalError(const char* format, ...);
|
||||
bool DisplayFormattedModalConfirmation(const char* format, ...);
|
||||
void DisplayFormattedModalInformation(const char* format, ...);
|
||||
|
||||
public:
|
||||
static ProgressCallback* NullProgressCallback;
|
||||
};
|
||||
|
||||
class BaseProgressCallback : public ProgressCallback
|
||||
{
|
||||
public:
|
||||
BaseProgressCallback();
|
||||
virtual ~BaseProgressCallback();
|
||||
|
||||
virtual void PushState() override;
|
||||
virtual void PopState() override;
|
||||
|
||||
virtual bool IsCancelled() const override;
|
||||
virtual bool IsCancellable() const override;
|
||||
|
||||
virtual void SetCancellable(bool cancellable) override;
|
||||
virtual void SetStatusText(const char* text) override;
|
||||
virtual void SetProgressRange(u32 range) override;
|
||||
virtual void SetProgressValue(u32 value) override;
|
||||
virtual void IncrementProgressValue() override;
|
||||
|
||||
protected:
|
||||
struct State
|
||||
{
|
||||
State* next_saved_state;
|
||||
std::string status_text;
|
||||
u32 progress_range;
|
||||
u32 progress_value;
|
||||
u32 base_progress_value;
|
||||
bool cancellable;
|
||||
};
|
||||
|
||||
bool m_cancellable;
|
||||
bool m_cancelled;
|
||||
std::string m_status_text;
|
||||
u32 m_progress_range;
|
||||
u32 m_progress_value;
|
||||
|
||||
u32 m_base_progress_value;
|
||||
|
||||
State* m_saved_state;
|
||||
};
|
||||
@@ -19,7 +19,7 @@
|
||||
#include <wx/tokenzr.h>
|
||||
#include "common/Dependencies.h"
|
||||
#include "common/SafeArray.h"
|
||||
#include "common/ScopedAlloc.h"
|
||||
#include "common/AlignedMalloc.h"
|
||||
|
||||
#if _WIN32
|
||||
#define WX_STR(str) (str.wc_str())
|
||||
@@ -132,7 +132,7 @@ struct ParsedAssignmentString
|
||||
// accepts Ascii/UTF8 only.
|
||||
//
|
||||
|
||||
typedef ScopedAlignedAlloc<char, 16> CharBufferType;
|
||||
typedef AlignedBuffer<char, 16> CharBufferType;
|
||||
// --------------------------------------------------------------------------------------
|
||||
// FastFormatAscii
|
||||
// --------------------------------------------------------------------------------------
|
||||
|
||||
@@ -0,0 +1,347 @@
|
||||
/* 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/>.
|
||||
*/
|
||||
|
||||
#include "PrecompiledHeader.h"
|
||||
|
||||
#include "Timer.h"
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
|
||||
#if defined(_WIN32)
|
||||
#include "RedtapeWindows.h"
|
||||
#elif defined(__APPLE__)
|
||||
#include <mach/mach_init.h>
|
||||
#include <mach/thread_act.h>
|
||||
#include <mach/mach_port.h>
|
||||
#else
|
||||
#include <pthread.h>
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
namespace Common
|
||||
{
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
static double s_counter_frequency;
|
||||
static bool s_counter_initialized = false;
|
||||
|
||||
Timer::Value Timer::GetCurrentValue()
|
||||
{
|
||||
// even if this races, it should still result in the same value..
|
||||
if (!s_counter_initialized)
|
||||
{
|
||||
LARGE_INTEGER Freq;
|
||||
QueryPerformanceFrequency(&Freq);
|
||||
s_counter_frequency = static_cast<double>(Freq.QuadPart) / 1000000000.0;
|
||||
s_counter_initialized = true;
|
||||
}
|
||||
|
||||
Timer::Value ReturnValue;
|
||||
QueryPerformanceCounter(reinterpret_cast<LARGE_INTEGER*>(&ReturnValue));
|
||||
return ReturnValue;
|
||||
}
|
||||
|
||||
double Timer::ConvertValueToNanoseconds(Timer::Value value)
|
||||
{
|
||||
return (static_cast<double>(value) / s_counter_frequency);
|
||||
}
|
||||
|
||||
double Timer::ConvertValueToMilliseconds(Timer::Value value)
|
||||
{
|
||||
return ((static_cast<double>(value) / s_counter_frequency) / 1000000.0);
|
||||
}
|
||||
|
||||
double Timer::ConvertValueToSeconds(Timer::Value value)
|
||||
{
|
||||
return ((static_cast<double>(value) / s_counter_frequency) / 1000000000.0);
|
||||
}
|
||||
|
||||
Timer::Value Timer::ConvertSecondsToValue(double s)
|
||||
{
|
||||
return static_cast<Value>((s * 1000000000.0) * s_counter_frequency);
|
||||
}
|
||||
|
||||
Timer::Value Timer::ConvertMillisecondsToValue(double ms)
|
||||
{
|
||||
return static_cast<Value>((ms * 1000000.0) * s_counter_frequency);
|
||||
}
|
||||
|
||||
Timer::Value Timer::ConvertNanosecondsToValue(double ns)
|
||||
{
|
||||
return static_cast<Value>(ns * s_counter_frequency);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
Timer::Value Timer::GetCurrentValue()
|
||||
{
|
||||
struct timespec tv;
|
||||
clock_gettime(CLOCK_MONOTONIC, &tv);
|
||||
return ((Value)tv.tv_nsec + (Value)tv.tv_sec * 1000000000);
|
||||
}
|
||||
|
||||
double Timer::ConvertValueToNanoseconds(Timer::Value value)
|
||||
{
|
||||
return static_cast<double>(value);
|
||||
}
|
||||
|
||||
double Timer::ConvertValueToMilliseconds(Timer::Value value)
|
||||
{
|
||||
return (static_cast<double>(value) / 1000000.0);
|
||||
}
|
||||
|
||||
double Timer::ConvertValueToSeconds(Timer::Value value)
|
||||
{
|
||||
return (static_cast<double>(value) / 1000000000.0);
|
||||
}
|
||||
|
||||
Timer::Value Timer::ConvertSecondsToValue(double s)
|
||||
{
|
||||
return static_cast<Value>(s * 1000000000.0);
|
||||
}
|
||||
|
||||
Timer::Value Timer::ConvertMillisecondsToValue(double ms)
|
||||
{
|
||||
return static_cast<Value>(ms * 1000000.0);
|
||||
}
|
||||
|
||||
Timer::Value Timer::ConvertNanosecondsToValue(double ns)
|
||||
{
|
||||
return static_cast<Value>(ns);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
Timer::Timer()
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
|
||||
void Timer::Reset()
|
||||
{
|
||||
m_tvStartValue = GetCurrentValue();
|
||||
}
|
||||
|
||||
double Timer::GetTimeSeconds() const
|
||||
{
|
||||
return ConvertValueToSeconds(GetCurrentValue() - m_tvStartValue);
|
||||
}
|
||||
|
||||
double Timer::GetTimeMilliseconds() const
|
||||
{
|
||||
return ConvertValueToMilliseconds(GetCurrentValue() - m_tvStartValue);
|
||||
}
|
||||
|
||||
double Timer::GetTimeNanoseconds() const
|
||||
{
|
||||
return ConvertValueToNanoseconds(GetCurrentValue() - m_tvStartValue);
|
||||
}
|
||||
|
||||
double Timer::GetTimeSecondsAndReset()
|
||||
{
|
||||
const Value value = GetCurrentValue();
|
||||
const double ret = ConvertValueToSeconds(value - m_tvStartValue);
|
||||
m_tvStartValue = value;
|
||||
return ret;
|
||||
}
|
||||
|
||||
double Timer::GetTimeMillisecondsAndReset()
|
||||
{
|
||||
const Value value = GetCurrentValue();
|
||||
const double ret = ConvertValueToMilliseconds(value - m_tvStartValue);
|
||||
m_tvStartValue = value;
|
||||
return ret;
|
||||
}
|
||||
|
||||
double Timer::GetTimeNanosecondsAndReset()
|
||||
{
|
||||
const Value value = GetCurrentValue();
|
||||
const double ret = ConvertValueToNanoseconds(value - m_tvStartValue);
|
||||
m_tvStartValue = value;
|
||||
return ret;
|
||||
}
|
||||
|
||||
ThreadCPUTimer::ThreadCPUTimer() = default;
|
||||
|
||||
ThreadCPUTimer::ThreadCPUTimer(ThreadCPUTimer&& move)
|
||||
: m_thread_handle(move.m_thread_handle)
|
||||
{
|
||||
move.m_thread_handle = nullptr;
|
||||
}
|
||||
|
||||
ThreadCPUTimer::~ThreadCPUTimer()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
CloseHandle(reinterpret_cast<HANDLE>(m_thread_handle));
|
||||
#endif
|
||||
}
|
||||
|
||||
ThreadCPUTimer& ThreadCPUTimer::operator=(ThreadCPUTimer&& move)
|
||||
{
|
||||
std::swap(m_thread_handle, move.m_thread_handle);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void ThreadCPUTimer::Reset()
|
||||
{
|
||||
m_start_value = GetCurrentValue();
|
||||
}
|
||||
|
||||
ThreadCPUTimer::Value ThreadCPUTimer::GetCurrentValue() const
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
FILETIME create, exit, user, kernel;
|
||||
if (!m_thread_handle || !GetThreadTimes((HANDLE)m_thread_handle, &create, &exit, &user, &kernel))
|
||||
return 0;
|
||||
|
||||
Value value = (static_cast<Value>(user.dwHighDateTime) << 32) | (static_cast<Value>(user.dwLowDateTime));
|
||||
value += (static_cast<Value>(kernel.dwHighDateTime) << 32) | (static_cast<Value>(kernel.dwLowDateTime));
|
||||
return value;
|
||||
#elif defined(__APPLE__)
|
||||
thread_basic_info_data_t info;
|
||||
mach_msg_type_number_t count = THREAD_BASIC_INFO_COUNT;
|
||||
|
||||
const kern_return_t kr = thread_info((mach_port_t) reinterpret_cast<uintptr_t>(m_thread_handle), THREAD_BASIC_INFO, (thread_info_t)&info, &count);
|
||||
if (kr != KERN_SUCCESS)
|
||||
return 0;
|
||||
|
||||
Value value = (static_cast<Value>(info.user_time.seconds) * 1000000) + (static_cast<Value>(info.user_time.microseconds));
|
||||
value += (static_cast<Value>(info.system_time.seconds) * 1000000) + (static_cast<Value>(info.system_time.microseconds));
|
||||
return value;
|
||||
#else
|
||||
clockid_t cid;
|
||||
if (!m_thread_handle || pthread_getcpuclockid((pthread_t)m_thread_handle, &cid) != 0)
|
||||
return 0;
|
||||
|
||||
struct timespec ts;
|
||||
if (clock_gettime(cid, &ts) != 0)
|
||||
return 0;
|
||||
|
||||
return (static_cast<Value>(ts.tv_nsec) + static_cast<Value>(ts.tv_sec) * 1000000000LL);
|
||||
#endif
|
||||
}
|
||||
|
||||
double ThreadCPUTimer::GetTimeSeconds() const
|
||||
{
|
||||
return ConvertValueToSeconds(GetCurrentValue() - m_start_value);
|
||||
}
|
||||
|
||||
double ThreadCPUTimer::GetTimeMilliseconds() const
|
||||
{
|
||||
return ConvertValueToMilliseconds(GetCurrentValue() - m_start_value);
|
||||
}
|
||||
|
||||
double ThreadCPUTimer::GetTimeNanoseconds() const
|
||||
{
|
||||
return ConvertValueToNanoseconds(GetCurrentValue() - m_start_value);
|
||||
}
|
||||
|
||||
void ThreadCPUTimer::GetUsageInSecondsAndReset(Value time_diff, double* usage_time, double* usage_percent)
|
||||
{
|
||||
const Value new_value = GetCurrentValue();
|
||||
const Value diff = new_value - m_start_value;
|
||||
m_start_value = new_value;
|
||||
|
||||
*usage_time = ConvertValueToSeconds(diff);
|
||||
*usage_percent = GetUtilizationPercentage(time_diff, diff);
|
||||
}
|
||||
|
||||
void ThreadCPUTimer::GetUsageInMillisecondsAndReset(Value time_diff, double* usage_time, double* usage_percent)
|
||||
{
|
||||
const Value new_value = GetCurrentValue();
|
||||
const Value diff = new_value - m_start_value;
|
||||
m_start_value = new_value;
|
||||
|
||||
*usage_time = ConvertValueToMilliseconds(diff);
|
||||
*usage_percent = GetUtilizationPercentage(time_diff, diff);
|
||||
}
|
||||
|
||||
void ThreadCPUTimer::GetUsageInNanosecondsAndReset(Value time_diff, double* usage_time, double* usage_percent)
|
||||
{
|
||||
const Value new_value = GetCurrentValue();
|
||||
const Value diff = new_value - m_start_value;
|
||||
m_start_value = new_value;
|
||||
|
||||
*usage_time = ConvertValueToNanoseconds(diff);
|
||||
*usage_percent = GetUtilizationPercentage(time_diff, diff);
|
||||
}
|
||||
|
||||
double ThreadCPUTimer::GetUtilizationPercentage(Timer::Value time_diff, Value cpu_time_diff)
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
return ((static_cast<double>(cpu_time_diff) * 10000.0) / (static_cast<double>(time_diff) / s_counter_frequency));
|
||||
#elif defined(__APPLE__)
|
||||
// microseconds, but time_tiff is in nanoseconds, so multiply by 1000 * 100
|
||||
return (static_cast<double>(cpu_time_diff) * 100000.0) / static_cast<double>(time_diff);
|
||||
#else
|
||||
// nanoseconds
|
||||
return (static_cast<double>(cpu_time_diff) * 100.0) / static_cast<double>(time_diff);
|
||||
#endif
|
||||
}
|
||||
|
||||
double ThreadCPUTimer::ConvertValueToSeconds(Value value)
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
// 100ns units
|
||||
return (static_cast<double>(value) / 10000000.0);
|
||||
#elif defined(__APPLE__)
|
||||
// microseconds
|
||||
return (static_cast<double>(value) / 1000000.0);
|
||||
#else
|
||||
// nanoseconds
|
||||
return (static_cast<double>(value) / 1000000000.0);
|
||||
#endif
|
||||
}
|
||||
|
||||
double ThreadCPUTimer::ConvertValueToMilliseconds(Value value)
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
return (static_cast<double>(value) / 10000.0);
|
||||
#elif defined(__APPLE__)
|
||||
return (static_cast<double>(value) / 1000.0);
|
||||
#else
|
||||
return (static_cast<double>(value) / 1000000.0);
|
||||
#endif
|
||||
}
|
||||
|
||||
double ThreadCPUTimer::ConvertValueToNanoseconds(Value value)
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
return (static_cast<double>(value) * 100.0);
|
||||
#elif defined(__APPLE__)
|
||||
return (static_cast<double>(value) * 1000.0);
|
||||
#else
|
||||
return static_cast<double>(value);
|
||||
#endif
|
||||
}
|
||||
|
||||
ThreadCPUTimer ThreadCPUTimer::GetForCallingThread()
|
||||
{
|
||||
ThreadCPUTimer ret;
|
||||
#if defined(_WIN32)
|
||||
ret.m_thread_handle = (void*)OpenThread(THREAD_QUERY_INFORMATION, FALSE, GetCurrentThreadId());
|
||||
#elif defined(__APPLE__)
|
||||
ret.m_thread_handle = reinterpret_cast<void*>((uintptr_t)mach_thread_self());
|
||||
#else
|
||||
ret.m_thread_handle = (void*)pthread_self();
|
||||
#endif
|
||||
ret.Reset();
|
||||
return ret;
|
||||
}
|
||||
|
||||
} // namespace Common
|
||||
@@ -0,0 +1,94 @@
|
||||
/* 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 <cstdint>
|
||||
|
||||
namespace Common
|
||||
{
|
||||
|
||||
class Timer
|
||||
{
|
||||
public:
|
||||
using Value = std::uint64_t;
|
||||
|
||||
Timer();
|
||||
|
||||
static Value GetCurrentValue();
|
||||
static double ConvertValueToSeconds(Value value);
|
||||
static double ConvertValueToMilliseconds(Value value);
|
||||
static double ConvertValueToNanoseconds(Value value);
|
||||
static Value ConvertSecondsToValue(double s);
|
||||
static Value ConvertMillisecondsToValue(double s);
|
||||
static Value ConvertNanosecondsToValue(double ns);
|
||||
|
||||
void Reset();
|
||||
void ResetTo(Value value) { m_tvStartValue = value; }
|
||||
|
||||
Value GetStartValue() const { return m_tvStartValue; }
|
||||
|
||||
double GetTimeSeconds() const;
|
||||
double GetTimeMilliseconds() const;
|
||||
double GetTimeNanoseconds() const;
|
||||
|
||||
double GetTimeSecondsAndReset();
|
||||
double GetTimeMillisecondsAndReset();
|
||||
double GetTimeNanosecondsAndReset();
|
||||
|
||||
private:
|
||||
Value m_tvStartValue;
|
||||
};
|
||||
|
||||
class ThreadCPUTimer
|
||||
{
|
||||
public:
|
||||
using Value = std::uint64_t;
|
||||
|
||||
ThreadCPUTimer();
|
||||
ThreadCPUTimer(ThreadCPUTimer&& move);
|
||||
ThreadCPUTimer(const ThreadCPUTimer&) = delete;
|
||||
~ThreadCPUTimer();
|
||||
|
||||
void Reset();
|
||||
void ResetTo(Value value) { m_start_value = value; }
|
||||
|
||||
Value GetStartValue() const { return m_start_value; }
|
||||
Value GetCurrentValue() const;
|
||||
|
||||
double GetTimeSeconds() const;
|
||||
double GetTimeMilliseconds() const;
|
||||
double GetTimeNanoseconds() const;
|
||||
|
||||
void GetUsageInSecondsAndReset(Value time_diff, double* usage_time, double* usage_percent);
|
||||
void GetUsageInMillisecondsAndReset(Value time_diff, double* usage_time, double* usage_percent);
|
||||
void GetUsageInNanosecondsAndReset(Value time_diff, double* usage_time, double* usage_percent);
|
||||
|
||||
static double GetUtilizationPercentage(Timer::Value time_diff, Value cpu_time_diff);
|
||||
|
||||
static double ConvertValueToSeconds(Value value);
|
||||
static double ConvertValueToMilliseconds(Value value);
|
||||
static double ConvertValueToNanoseconds(Value value);
|
||||
|
||||
static ThreadCPUTimer GetForCallingThread();
|
||||
|
||||
ThreadCPUTimer& operator=(const ThreadCPUTimer&) = delete;
|
||||
ThreadCPUTimer& operator=(ThreadCPUTimer&& move);
|
||||
|
||||
private:
|
||||
void* m_thread_handle = nullptr;
|
||||
Value m_start_value = 0;
|
||||
};
|
||||
|
||||
} // namespace Common
|
||||
@@ -1,4 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(SolutionDir)common\vsprops\BaseProjectConfig.props" />
|
||||
<Import Project="$(SolutionDir)common\vsprops\WinSDK.props" />
|
||||
@@ -52,11 +52,14 @@
|
||||
<ClCompile Include="GL\Context.cpp" />
|
||||
<ClCompile Include="GL\ContextWGL.cpp" />
|
||||
<ClCompile Include="GL\StreamBuffer.cpp" />
|
||||
<ClCompile Include="FileSystem.cpp" />
|
||||
<ClCompile Include="IniInterface.cpp" />
|
||||
<ClCompile Include="ProgressCallback.cpp" />
|
||||
<ClCompile Include="pxStreams.cpp" />
|
||||
<ClCompile Include="pxTranslate.cpp" />
|
||||
<ClCompile Include="StringUtil.cpp" />
|
||||
<ClCompile Include="SettingsWrapper.cpp" />
|
||||
<ClCompile Include="Timer.cpp" />
|
||||
<ClCompile Include="VirtualMemory.cpp" />
|
||||
<ClCompile Include="WindowInfo.cpp" />
|
||||
<ClCompile Include="x86\MemcpyFast.cpp" />
|
||||
@@ -100,6 +103,7 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="Align.h" />
|
||||
<ClInclude Include="AlignedMalloc.h" />
|
||||
<ClInclude Include="BitCast.h" />
|
||||
<ClInclude Include="EmbeddedImage.h" />
|
||||
<ClInclude Include="boost_spsc_queue.hpp" />
|
||||
@@ -107,7 +111,8 @@
|
||||
<ClInclude Include="GL\Context.h" />
|
||||
<ClInclude Include="GL\ContextWGL.h" />
|
||||
<ClInclude Include="GL\StreamBuffer.h" />
|
||||
<ClInclude Include="ScopedAlloc.h" />
|
||||
<ClInclude Include="FileSystem.h" />
|
||||
<ClInclude Include="ProgressCallback.h" />
|
||||
<ClInclude Include="ScopedGuard.h" />
|
||||
<ClInclude Include="StringUtil.h" />
|
||||
<ClInclude Include="SettingsInterface.h" />
|
||||
@@ -126,6 +131,7 @@
|
||||
<ClInclude Include="RedtapeWindows.h" />
|
||||
<ClInclude Include="SafeArray.h" />
|
||||
<ClInclude Include="StringHelpers.h" />
|
||||
<ClInclude Include="Timer.h" />
|
||||
<ClInclude Include="WindowInfo.h" />
|
||||
<ClInclude Include="wxBaseTools.h" />
|
||||
<ClInclude Include="Threading.h" />
|
||||
@@ -175,4 +181,4 @@
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
<Import Project="$(VCTargetsPath)\BuildCustomizations\masm.targets" />
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
|
||||
@@ -130,8 +130,23 @@
|
||||
<ClCompile Include="GL\StreamBuffer.cpp">
|
||||
<Filter>Source Files\GL</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="FileSystem.cpp">
|
||||
<Filter>Source Files\GL</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="StringUtil.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Timer.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ProgressCallback.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="AlignedMalloc.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Assertions.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
@@ -222,9 +237,6 @@
|
||||
<ClInclude Include="SafeArray.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="ScopedAlloc.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="emitter\implement\simd_arithmetic.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
@@ -282,9 +294,6 @@
|
||||
<ClInclude Include="SettingsWrapper.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="ScopedGuard.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Align.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
@@ -303,6 +312,24 @@
|
||||
<ClInclude Include="GL\StreamBuffer.h">
|
||||
<Filter>Header Files\GL</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="FileSystem.h">
|
||||
<Filter>Header Files\GL</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="StringUtil.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="ScopedGuard.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Timer.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="ProgressCallback.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="ScopedGuard.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
|
||||
@@ -21,23 +21,21 @@
|
||||
// AND'ing this mask against an MXCSR prior to LDMXCSR.
|
||||
SSE_MXCSR MXCSR_Mask;
|
||||
|
||||
const wxChar* EnumToString(SSE_RoundMode sse)
|
||||
const char* EnumToString(SSE_RoundMode sse)
|
||||
{
|
||||
switch (sse)
|
||||
{
|
||||
case SSEround_Nearest:
|
||||
return L"Nearest";
|
||||
return "Nearest";
|
||||
case SSEround_NegInf:
|
||||
return L"NegativeInfinity";
|
||||
return "NegativeInfinity";
|
||||
case SSEround_PosInf:
|
||||
return L"PositiveInfinity";
|
||||
return "PositiveInfinity";
|
||||
case SSEround_Chop:
|
||||
return L"Chop";
|
||||
return "Chop";
|
||||
default:
|
||||
return L"Invalid";
|
||||
return "Invalid";
|
||||
}
|
||||
|
||||
return L"Invalid";
|
||||
}
|
||||
|
||||
SSE_RoundMode SSE_MXCSR::GetRoundMode() const
|
||||
|
||||
+34
-33
@@ -24,21 +24,22 @@
|
||||
# include <aio.h>
|
||||
#endif
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
class AsyncFileReader
|
||||
{
|
||||
protected:
|
||||
AsyncFileReader() : m_dataoffset(0), m_blocksize(0) {}
|
||||
|
||||
wxString m_filename;
|
||||
std::string m_filename;
|
||||
|
||||
int m_dataoffset;
|
||||
uint m_blocksize;
|
||||
|
||||
public:
|
||||
virtual ~AsyncFileReader(void) {};
|
||||
virtual ~AsyncFileReader() {};
|
||||
|
||||
virtual bool Open(const wxString& fileName)=0;
|
||||
virtual bool Open(std::string fileName)=0;
|
||||
|
||||
virtual int ReadSync(void* pBuffer, uint sector, uint count)=0;
|
||||
|
||||
@@ -55,7 +56,7 @@ public:
|
||||
|
||||
uint GetBlockSize() const { return m_blocksize; }
|
||||
|
||||
const wxString& GetFilename() const
|
||||
const std::string& GetFilename() const
|
||||
{
|
||||
return m_filename;
|
||||
}
|
||||
@@ -86,22 +87,22 @@ class FlatFileReader : public AsyncFileReader
|
||||
|
||||
public:
|
||||
FlatFileReader(bool shareWrite = false);
|
||||
virtual ~FlatFileReader(void);
|
||||
virtual ~FlatFileReader() override;
|
||||
|
||||
virtual bool Open(const wxString& fileName);
|
||||
virtual bool Open(std::string fileName) override;
|
||||
|
||||
virtual int ReadSync(void* pBuffer, uint sector, uint count);
|
||||
virtual int ReadSync(void* pBuffer, uint sector, uint count) override;
|
||||
|
||||
virtual void BeginRead(void* pBuffer, uint sector, uint count);
|
||||
virtual int FinishRead(void);
|
||||
virtual void CancelRead(void);
|
||||
virtual void BeginRead(void* pBuffer, uint sector, uint count) override;
|
||||
virtual int FinishRead(void) override;
|
||||
virtual void CancelRead(void) override;
|
||||
|
||||
virtual void Close(void);
|
||||
virtual void Close(void) override;
|
||||
|
||||
virtual uint GetBlockCount(void) const;
|
||||
virtual uint GetBlockCount(void) const override;
|
||||
|
||||
virtual void SetBlockSize(uint bytes) { m_blocksize = bytes; }
|
||||
virtual void SetDataOffset(int bytes) { m_dataoffset = bytes; }
|
||||
virtual void SetBlockSize(uint bytes) override { m_blocksize = bytes; }
|
||||
virtual void SetDataOffset(int bytes) override { m_dataoffset = bytes; }
|
||||
};
|
||||
|
||||
class MultipartFileReader : public AsyncFileReader
|
||||
@@ -123,21 +124,21 @@ class MultipartFileReader : public AsyncFileReader
|
||||
|
||||
public:
|
||||
MultipartFileReader(AsyncFileReader* firstPart);
|
||||
virtual ~MultipartFileReader(void);
|
||||
virtual ~MultipartFileReader() override;
|
||||
|
||||
virtual bool Open(const wxString& fileName);
|
||||
virtual bool Open(std::string fileName) override;
|
||||
|
||||
virtual int ReadSync(void* pBuffer, uint sector, uint count);
|
||||
virtual int ReadSync(void* pBuffer, uint sector, uint count) override;
|
||||
|
||||
virtual void BeginRead(void* pBuffer, uint sector, uint count);
|
||||
virtual int FinishRead(void);
|
||||
virtual void CancelRead(void);
|
||||
virtual void BeginRead(void* pBuffer, uint sector, uint count) override;
|
||||
virtual int FinishRead(void) override;
|
||||
virtual void CancelRead(void) override;
|
||||
|
||||
virtual void Close(void);
|
||||
virtual void Close(void) override;
|
||||
|
||||
virtual uint GetBlockCount(void) const;
|
||||
virtual uint GetBlockCount(void) const override;
|
||||
|
||||
virtual void SetBlockSize(uint bytes);
|
||||
virtual void SetBlockSize(uint bytes) override;
|
||||
|
||||
static AsyncFileReader* DetectMultipart(AsyncFileReader* reader);
|
||||
};
|
||||
@@ -146,7 +147,7 @@ class BlockdumpFileReader : public AsyncFileReader
|
||||
{
|
||||
DeclareNoncopyableObject( BlockdumpFileReader );
|
||||
|
||||
wxFileInputStream* m_file;
|
||||
std::FILE* m_file;
|
||||
|
||||
// total number of blocks in the ISO image (including all parts)
|
||||
u32 m_blocks;
|
||||
@@ -159,20 +160,20 @@ class BlockdumpFileReader : public AsyncFileReader
|
||||
int m_lresult;
|
||||
|
||||
public:
|
||||
BlockdumpFileReader(void);
|
||||
virtual ~BlockdumpFileReader(void);
|
||||
BlockdumpFileReader();
|
||||
virtual ~BlockdumpFileReader() override;
|
||||
|
||||
virtual bool Open(const wxString& fileName);
|
||||
virtual bool Open(std::string fileName) override;
|
||||
|
||||
virtual int ReadSync(void* pBuffer, uint sector, uint count);
|
||||
virtual int ReadSync(void* pBuffer, uint sector, uint count) override;
|
||||
|
||||
virtual void BeginRead(void* pBuffer, uint sector, uint count);
|
||||
virtual int FinishRead(void);
|
||||
virtual void CancelRead(void);
|
||||
virtual void BeginRead(void* pBuffer, uint sector, uint count) override;
|
||||
virtual int FinishRead(void) override;
|
||||
virtual void CancelRead(void) override;
|
||||
|
||||
virtual void Close(void);
|
||||
virtual void Close(void) override;
|
||||
|
||||
virtual uint GetBlockCount(void) const;
|
||||
virtual uint GetBlockCount(void) const override;
|
||||
|
||||
static bool DetectBlockdump(AsyncFileReader* reader);
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include "AsyncFileReader.h"
|
||||
#include "IopCommon.h"
|
||||
#include "IsoFileFormats.h"
|
||||
#include "common/FileSystem.h"
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
@@ -59,48 +60,45 @@ BlockdumpFileReader::~BlockdumpFileReader(void)
|
||||
Close();
|
||||
}
|
||||
|
||||
bool BlockdumpFileReader::Open(const wxString& fileName)
|
||||
bool BlockdumpFileReader::Open(std::string fileName)
|
||||
{
|
||||
char buf[32];
|
||||
char signature[4];
|
||||
|
||||
m_filename = fileName;
|
||||
|
||||
m_file = new wxFileInputStream(m_filename);
|
||||
|
||||
m_file->SeekI(0);
|
||||
m_file->Read(buf, 4);
|
||||
|
||||
if (strncmp(buf, "BDV2", 4) != 0)
|
||||
m_filename = std::move(fileName);
|
||||
m_file = FileSystem::OpenCFile(m_filename.c_str(), "rb");
|
||||
if (!m_file || std::fread(signature, sizeof(signature), 1, m_file) != 1 || std::memcmp(signature, "BDV2", sizeof(signature)) != 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//m_flags = ISOFLAGS_BLOCKDUMP_V2;
|
||||
m_file->Read(&m_blocksize, sizeof(m_blocksize));
|
||||
m_file->Read(&m_blocks, sizeof(m_blocks));
|
||||
m_file->Read(&m_blockofs, sizeof(m_blockofs));
|
||||
if (std::fread(&m_blocksize, sizeof(m_blocksize), 1, m_file) != 1 ||
|
||||
std::fread(&m_blocks, sizeof(m_blocks), 1, m_file) != 1 ||
|
||||
std::fread(&m_blockofs, sizeof(m_blockofs), 1, m_file) != 1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
wxFileOffset flen = m_file->GetLength();
|
||||
static const wxFileOffset datalen = flen - BlockDumpHeaderSize;
|
||||
const s64 flen = FileSystem::FSize64(m_file);
|
||||
const s64 datalen = flen - BlockDumpHeaderSize;
|
||||
|
||||
pxAssert((datalen % (m_blocksize + 4)) == 0);
|
||||
|
||||
m_dtablesize = datalen / (m_blocksize + 4);
|
||||
m_dtable = std::unique_ptr<u32[]>(new u32[m_dtablesize]);
|
||||
m_dtable = std::make_unique<u32[]>(m_dtablesize);
|
||||
|
||||
m_file->SeekI(BlockDumpHeaderSize);
|
||||
if (FileSystem::FSeek64(m_file, BlockDumpHeaderSize, SEEK_SET) != 0)
|
||||
return false;
|
||||
|
||||
u32 bs = 1024 * 1024;
|
||||
u32 off = 0;
|
||||
u32 has = 0;
|
||||
int i = 0;
|
||||
|
||||
std::unique_ptr<u8[]> buffer(new u8[bs]);
|
||||
std::unique_ptr<u8[]> buffer = std::make_unique<u8[]>(bs);
|
||||
do
|
||||
{
|
||||
m_file->Read(buffer.get(), bs);
|
||||
has = m_file->LastRead();
|
||||
|
||||
has = static_cast<u32>(std::fread(buffer.get(), 1, bs, m_file));
|
||||
while (i < m_dtablesize && off < has)
|
||||
{
|
||||
m_dtable[i++] = *reinterpret_cast<u32*>(buffer.get() + off);
|
||||
@@ -132,15 +130,17 @@ int BlockdumpFileReader::ReadSync(void* pBuffer, uint lsn, uint count)
|
||||
// seek position ends up being based on (m_blocksize + 4) instead of just m_blocksize.
|
||||
|
||||
#ifdef PCSX2_DEBUG
|
||||
u32 check_lsn;
|
||||
m_file->SeekI(BlockDumpHeaderSize + (i * (m_blocksize + 4)));
|
||||
m_file->Read(&check_lsn, sizeof(check_lsn));
|
||||
u32 check_lsn = 0;
|
||||
FileSystem::FSeek64(m_file, BlockDumpHeaderSize + (i * (m_blocksize + 4)), SEEK_SET);
|
||||
std::fread(&check_lsn, sizeof(check_lsn), 1, m_file);
|
||||
pxAssert(check_lsn == lsn);
|
||||
#else
|
||||
m_file->SeekI(BlockDumpHeaderSize + (i * (m_blocksize + 4)) + 4);
|
||||
if (FileSystem::FSeek64(m_file, BlockDumpHeaderSize + (i * (m_blocksize + 4)) + 4, SEEK_SET) != 0)
|
||||
break;
|
||||
#endif
|
||||
|
||||
m_file->Read(dst, m_blocksize);
|
||||
if (std::fread(dst, m_blocksize, 1, m_file) != 1)
|
||||
break;
|
||||
|
||||
ok = true;
|
||||
break;
|
||||
@@ -178,7 +178,7 @@ void BlockdumpFileReader::Close(void)
|
||||
{
|
||||
if (m_file)
|
||||
{
|
||||
delete m_file;
|
||||
std::fclose(m_file);
|
||||
m_file = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
+67
-106
@@ -20,6 +20,8 @@
|
||||
#include <ctype.h>
|
||||
#include <wx/datetime.h>
|
||||
|
||||
#include "common/FileSystem.h"
|
||||
|
||||
#include "CdRom.h"
|
||||
#include "CDVD.h"
|
||||
#include "CDVD_internal.h"
|
||||
@@ -111,34 +113,28 @@ static int mg_BIToffset(u8* buffer)
|
||||
|
||||
static void cdvdGetMechaVer(u8* ver)
|
||||
{
|
||||
wxFileName mecfile(EmuConfig.FullpathToBios());
|
||||
mecfile.SetExt(L"mec");
|
||||
const wxString fname(mecfile.GetFullPath());
|
||||
|
||||
// Likely a bad idea to go further
|
||||
if (mecfile.IsDir())
|
||||
throw Exception::CannotCreateStream(fname);
|
||||
|
||||
|
||||
if (Path::GetFileSize(fname) < 4)
|
||||
std::string mecfile(FileSystem::ReplaceExtension(BiosPath, "mec"));
|
||||
auto fp = FileSystem::OpenManagedCFile(mecfile.c_str(), "rb");
|
||||
if (!fp || FileSystem::FSize64(fp.get()) < 4)
|
||||
{
|
||||
Console.Warning("MEC File Not Found, creating substitute...");
|
||||
|
||||
wxFFile fp(fname, L"wb");
|
||||
if (!fp.IsOpened())
|
||||
throw Exception::CannotCreateStream(fname);
|
||||
fp.reset();
|
||||
fp = FileSystem::OpenManagedCFile(mecfile.c_str(), "w+b");
|
||||
if (!fp)
|
||||
{
|
||||
Console.Error("Failed to read/write NVM/MEC file. Check your BIOS setup/permission settings.");
|
||||
return;
|
||||
}
|
||||
|
||||
u8 version[4] = {0x3, 0x6, 0x2, 0x0};
|
||||
fp.Write(version, sizeof(version));
|
||||
std::fwrite(version, sizeof(version), 1, fp.get());
|
||||
FileSystem::FSeek64(fp.get(), 0, SEEK_SET);
|
||||
}
|
||||
|
||||
wxFFile fp(fname, L"rb");
|
||||
if (!fp.IsOpened())
|
||||
throw Exception::CannotCreateStream(fname);
|
||||
|
||||
size_t ret = fp.Read(ver, 4);
|
||||
auto ret = std::fread(ver, 1, 4, fp.get());
|
||||
if (ret != 4)
|
||||
Console.Error(L"Failed to read from %s. Did only %zu/4 bytes", WX_STR(fname), ret);
|
||||
Console.Error("Failed to read from %s. Did only %zu/4 bytes", mecfile.c_str(), ret);
|
||||
}
|
||||
|
||||
NVMLayout* getNvmLayout()
|
||||
@@ -153,14 +149,10 @@ NVMLayout* getNvmLayout()
|
||||
return nvmLayout;
|
||||
}
|
||||
|
||||
static void cdvdCreateNewNVM(const wxString& filename)
|
||||
static void cdvdCreateNewNVM(std::FILE* fp)
|
||||
{
|
||||
wxFFile fp(filename, L"wb");
|
||||
if (!fp.IsOpened())
|
||||
throw Exception::CannotCreateStream(filename);
|
||||
|
||||
u8 zero[1024] = {0};
|
||||
fp.Write(zero, sizeof(zero));
|
||||
u8 zero[1024] = {};
|
||||
std::fwrite(zero, sizeof(zero), 1, fp);
|
||||
|
||||
// Write NVM ILink area with dummy data (Age of Empires 2)
|
||||
// Also write language data defaulting to English (Guitar Hero 2)
|
||||
@@ -168,36 +160,34 @@ static void cdvdCreateNewNVM(const wxString& filename)
|
||||
NVMLayout* nvmLayout = getNvmLayout();
|
||||
u8 ILinkID_Data[8] = {0x00, 0xAC, 0xFF, 0xFF, 0xFF, 0xFF, 0xB9, 0x86};
|
||||
|
||||
fp.Seek(*(s32*)(((u8*)nvmLayout) + offsetof(NVMLayout, ilinkId)));
|
||||
fp.Write(ILinkID_Data, sizeof(ILinkID_Data));
|
||||
std::fseek(fp, *(s32*)(((u8*)nvmLayout) + offsetof(NVMLayout, ilinkId)), SEEK_SET);
|
||||
std::fwrite(ILinkID_Data, sizeof(ILinkID_Data), 1, fp);
|
||||
|
||||
u8 biosLanguage[16];
|
||||
memcpy(biosLanguage, &biosLangDefaults[BiosRegion][0], 16);
|
||||
// Config sections first 16 bytes are generally blank expect the last byte which is PS1 mode stuff
|
||||
// So let's ignore that and just write the PS2 mode stuff
|
||||
fp.Seek(*(s32*)(((u8*)nvmLayout) + offsetof(NVMLayout, config1)) + 0x10);
|
||||
fp.Write(biosLanguage, sizeof(biosLanguage));
|
||||
|
||||
fp.Close();
|
||||
std::fseek(fp, *(s32*)(((u8*)nvmLayout) + offsetof(NVMLayout, config1)) + 0x10, SEEK_SET);
|
||||
std::fwrite(biosLanguage, sizeof(biosLanguage), 1, fp);
|
||||
}
|
||||
|
||||
// Throws Exception::CannotCreateStream if the file cannot be opened for reading, or cannot
|
||||
// be created for some reason.
|
||||
static void cdvdNVM(u8* buffer, int offset, size_t bytes, bool read)
|
||||
{
|
||||
wxFileName nvmfile(EmuConfig.FullpathToBios());
|
||||
nvmfile.SetExt(L"nvm");
|
||||
const wxString fname(nvmfile.GetFullPath());
|
||||
|
||||
// Likely a bad idea to go further
|
||||
if (nvmfile.IsDir())
|
||||
throw Exception::CannotCreateStream(fname);
|
||||
|
||||
if (Path::GetFileSize(fname) < 1024)
|
||||
std::string nvmfile(FileSystem::ReplaceExtension(BiosPath, "nvm"));
|
||||
auto fp = FileSystem::OpenManagedCFile(nvmfile.c_str(), "r+b");
|
||||
if (!fp || FileSystem::FSize64(fp.get()) < 1024)
|
||||
{
|
||||
Console.Warning("NVM File Not Found, creating substitute...");
|
||||
fp.reset();
|
||||
fp = FileSystem::OpenManagedCFile(nvmfile.c_str(), "w+b");
|
||||
if (!fp)
|
||||
{
|
||||
Console.Error("Failed to open NVM file '%s' for writing", nvmfile.c_str());
|
||||
if (read)
|
||||
std::memset(buffer, 0, bytes);
|
||||
return;
|
||||
}
|
||||
|
||||
cdvdCreateNewNVM(fname);
|
||||
cdvdCreateNewNVM(fp.get());
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -205,38 +195,28 @@ static void cdvdNVM(u8* buffer, int offset, size_t bytes, bool read)
|
||||
u8 zero[16] = {0};
|
||||
NVMLayout* nvmLayout = getNvmLayout();
|
||||
|
||||
wxFFile fp(fname, L"r+b");
|
||||
if (!fp.IsOpened())
|
||||
throw Exception::CannotCreateStream(fname);
|
||||
|
||||
fp.Seek(*(s32*)(((u8*)nvmLayout) + offsetof(NVMLayout, config1)) + 0x10);
|
||||
fp.Read(LanguageParams, 16);
|
||||
|
||||
fp.Close();
|
||||
|
||||
if (memcmp(LanguageParams, zero, sizeof(LanguageParams)) == 0)
|
||||
if (std::fseek(fp.get(), *(s32*)(((u8*)nvmLayout) + offsetof(NVMLayout, config1)) + 0x10, SEEK_SET) != 0 ||
|
||||
std::fread(LanguageParams, 16, 1, fp.get()) != 1 ||
|
||||
std::memcmp(LanguageParams, zero, sizeof(LanguageParams)) == 0)
|
||||
{
|
||||
Console.Warning("Language Parameters missing, filling in defaults");
|
||||
|
||||
cdvdCreateNewNVM(fname);
|
||||
FileSystem::FSeek64(fp.get(), 0, SEEK_SET);
|
||||
cdvdCreateNewNVM(fp.get());
|
||||
}
|
||||
}
|
||||
|
||||
wxFFile fp(fname, L"r+b");
|
||||
if (!fp.IsOpened())
|
||||
throw Exception::CannotCreateStream(fname);
|
||||
|
||||
fp.Seek(offset);
|
||||
std::fseek(fp.get(), offset, SEEK_SET);
|
||||
|
||||
size_t ret;
|
||||
if (read)
|
||||
ret = fp.Read(buffer, bytes);
|
||||
ret = std::fread(buffer, 1, bytes, fp.get());
|
||||
else
|
||||
ret = fp.Write(buffer, bytes);
|
||||
ret = std::fwrite(buffer, 1, bytes, fp.get());
|
||||
|
||||
if (ret != bytes)
|
||||
Console.Error(L"Failed to %s %s. Did only %zu/%zu bytes",
|
||||
read ? L"read from" : L"write to", WX_STR(fname), ret, bytes);
|
||||
read ? L"read from" : L"write to", nvmfile.c_str(), ret, bytes);
|
||||
}
|
||||
|
||||
static void cdvdReadNVM(u8* dst, int offset, int bytes)
|
||||
@@ -384,7 +364,7 @@ static MutexRecursive Mutex_NewDiskCB;
|
||||
static __fi ElfObject* loadElf(const wxString filename, bool isPSXElf)
|
||||
{
|
||||
if (filename.StartsWith(L"host"))
|
||||
return new ElfObject(filename.After(':'), Path::GetFileSize(filename.After(':')), isPSXElf);
|
||||
return new ElfObject(filename.After(':'), FileSystem::GetPathFileSize(filename.After(':').ToUTF8()), isPSXElf);
|
||||
|
||||
// Mimic PS2 behavior!
|
||||
// Much trial-and-error with changing the ISOFS and BOOT2 contents of an image have shown that
|
||||
@@ -1058,7 +1038,7 @@ __fi void cdvdActionInterrupt()
|
||||
cdvd.Spinning = true;
|
||||
cdvd.Ready |= CDVD_DRIVE_READY; //check (rama)
|
||||
cdvd.Sector = cdvd.SeekToSector;
|
||||
cdvd.Status = CDVD_STATUS_READ;
|
||||
cdvd.Status = CDVD_STATUS_PAUSE;
|
||||
cdvd.nextSectorsBuffered = 0;
|
||||
cdvd.triggerDataReady = true;
|
||||
CDVDSECTORREADY_INT(cdvd.ReadTime);
|
||||
@@ -1069,7 +1049,7 @@ __fi void cdvdActionInterrupt()
|
||||
cdvd.Spinning = true; //check (rama)
|
||||
cdvd.Ready |= CDVD_DRIVE_READY; //check (rama)
|
||||
cdvd.Sector = cdvd.SeekToSector;
|
||||
cdvd.Status = CDVD_STATUS_READ;
|
||||
cdvd.Status = CDVD_STATUS_PAUSE;
|
||||
cdvd.nextSectorsBuffered = 0;
|
||||
cdvd.triggerDataReady = true;
|
||||
CDVDSECTORREADY_INT(cdvd.ReadTime);
|
||||
@@ -1123,18 +1103,8 @@ __fi void cdvdSectorReady()
|
||||
}
|
||||
}
|
||||
|
||||
if (cdvd.nextSectorsBuffered == 16 && (cdvd.Ready & CDVD_DRIVE_READY))
|
||||
{
|
||||
cdvd.Status = CDVD_STATUS_PAUSE; // Needed here but could be smth else than Pause (rama)
|
||||
}
|
||||
else
|
||||
{
|
||||
if (cdvd.nextSectorsBuffered < 16)
|
||||
{
|
||||
CDVDSECTORREADY_INT(cdvd.ReadTime);
|
||||
cdvd.Status = CDVD_STATUS_READ;
|
||||
}
|
||||
}
|
||||
if (cdvd.nextSectorsBuffered < 16)
|
||||
CDVDSECTORREADY_INT(cdvd.ReadTime);
|
||||
}
|
||||
|
||||
// inlined due to being referenced in only one place.
|
||||
@@ -1159,14 +1129,10 @@ __fi void cdvdReadInterrupt()
|
||||
cdvd.Reading = 1;
|
||||
cdvd.Readed = 1;
|
||||
cdvd.Sector = cdvd.SeekToSector;
|
||||
CDVD_LOG("Cdvd Seek Complete > Scheduling block read interrupt at iopcycle=%8.8x.",
|
||||
psxRegs.cycle + cdvd.ReadTime);
|
||||
|
||||
CDVDREAD_INT(cdvd.ReadTime);
|
||||
cdvd.Status = CDVD_STATUS_READ;
|
||||
return;
|
||||
CDVD_LOG("Cdvd Seek Complete at iopcycle=%8.8x.", psxRegs.cycle);
|
||||
}
|
||||
else if (cdvd.Reading)
|
||||
|
||||
if (cdvd.Reading)
|
||||
{
|
||||
if (cdvd.RErr == 0)
|
||||
{
|
||||
@@ -1237,10 +1203,7 @@ __fi void cdvdReadInterrupt()
|
||||
iopIntcIrq(2);
|
||||
cdvd.Ready |= CDVD_DRIVE_READY;
|
||||
|
||||
if (cdvd.nextSectorsBuffered < 16)
|
||||
cdvd.Status = CDVD_STATUS_READ;
|
||||
else
|
||||
cdvd.Status = CDVD_STATUS_PAUSE;
|
||||
cdvd.Status = CDVD_STATUS_PAUSE;
|
||||
|
||||
cdvd.nCommand = 0;
|
||||
//DevCon.Warning("Scheduling interrupt in %d cycles", cdvd.ReadTime - ((cdvd.BlockSize / 4) * 12));
|
||||
@@ -1264,7 +1227,7 @@ __fi void cdvdReadInterrupt()
|
||||
if (cdvd.nextSectorsBuffered)
|
||||
CDVDREAD_INT((cdvd.BlockSize / 4) * 12);
|
||||
else
|
||||
CDVDREAD_INT(cdvd.ReadTime + ((cdvd.BlockSize / 4) * 12));
|
||||
CDVDREAD_INT((psxRegs.cycle - psxRegs.sCycle[IopEvt_CdvdSectorReady]) + ((cdvd.BlockSize / 4) * 12));
|
||||
}
|
||||
|
||||
// Returns the number of IOP cycles until the event completes.
|
||||
@@ -1274,6 +1237,7 @@ static uint cdvdStartSeek(uint newsector, CDVD_MODE_TYPE mode)
|
||||
|
||||
uint delta = abs((s32)(cdvd.SeekToSector - cdvd.Sector));
|
||||
uint seektime;
|
||||
bool isSeeking = cdvd.nCommand == N_CD_SEEK;
|
||||
|
||||
cdvd.Ready &= ~(CDVD_DRIVE_READY | CDVD_DRIVE_DATARDY);
|
||||
cdvd.Reading = 1;
|
||||
@@ -1311,6 +1275,7 @@ static uint cdvdStartSeek(uint newsector, CDVD_MODE_TYPE mode)
|
||||
CDVD_LOG("CdSeek Begin > to sector %d, from %d - delta=%d [FAST]", cdvd.SeekToSector, cdvd.Sector, delta);
|
||||
seektime = Cdvd_FastSeek_Cycles;
|
||||
}
|
||||
isSeeking = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1318,6 +1283,7 @@ static uint cdvdStartSeek(uint newsector, CDVD_MODE_TYPE mode)
|
||||
|
||||
// if delta > 0 it will read a new sector so the readInterrupt will account for this.
|
||||
seektime = 0;
|
||||
isSeeking = false;
|
||||
|
||||
if (delta == 0)
|
||||
{
|
||||
@@ -1342,12 +1308,11 @@ static uint cdvdStartSeek(uint newsector, CDVD_MODE_TYPE mode)
|
||||
}
|
||||
else
|
||||
{
|
||||
CDVDSECTORREADY_INT(cdvd.ReadTime);
|
||||
seektime = cdvd.ReadTime + ((cdvd.BlockSize / 4) * 12);
|
||||
delta = 1; // Forces it to use the rotational delay since we have no sectors buffered and it isn't buffering any.
|
||||
}
|
||||
}
|
||||
else
|
||||
seektime = (cdvd.BlockSize / 4) * 12;
|
||||
return (cdvd.BlockSize / 4) * 12;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1357,7 +1322,7 @@ static uint cdvdStartSeek(uint newsector, CDVD_MODE_TYPE mode)
|
||||
}
|
||||
|
||||
// Only do this on reads, the seek kind of accounts for this and then it reads the sectors after
|
||||
if (delta && cdvd.nCommand != N_CD_SEEK)
|
||||
if (delta && !isSeeking)
|
||||
{
|
||||
int rotationalLatency = cdvdRotationalLatency((CDVD_MODE_TYPE)cdvdIsDVD());
|
||||
//DevCon.Warning("%s rotational latency at sector %d is %d cycles", (cdvd.SpindlCtrl & CDVD_SPINDLE_CAV) ? "CAV" : "CLV", cdvd.SeekToSector, rotationalLatency);
|
||||
@@ -1365,6 +1330,9 @@ static uint cdvdStartSeek(uint newsector, CDVD_MODE_TYPE mode)
|
||||
CDVDSECTORREADY_INT(seektime);
|
||||
seektime += (cdvd.BlockSize / 4) * 12;
|
||||
}
|
||||
else
|
||||
CDVDSECTORREADY_INT(seektime);
|
||||
|
||||
return seektime;
|
||||
}
|
||||
|
||||
@@ -1642,7 +1610,7 @@ static void cdvdWrite04(u8 rt)
|
||||
cdvdSetIrq();
|
||||
cdvd.nCommand = 0;
|
||||
//After Pausing needs to buffer the next sector
|
||||
cdvd.Status = CDVD_STATUS_READ;
|
||||
cdvd.Status = CDVD_STATUS_PAUSE;
|
||||
cdvd.nextSectorsBuffered = 0;
|
||||
cdvd.triggerDataReady = true;
|
||||
CDVDSECTORREADY_INT(cdvd.ReadTime);
|
||||
@@ -1874,7 +1842,7 @@ static void cdvdWrite04(u8 rt)
|
||||
HW_DMA3_CHCR &= ~0x01000000;
|
||||
psxDmaInterrupt(3);
|
||||
//After reading the TOC it needs to go back to buffer the next sector
|
||||
cdvd.Status = CDVD_STATUS_READ;
|
||||
cdvd.Status = CDVD_STATUS_PAUSE;
|
||||
cdvd.nextSectorsBuffered = 0;
|
||||
cdvd.triggerDataReady = true;
|
||||
CDVDSECTORREADY_INT(cdvd.ReadTime);
|
||||
@@ -1891,7 +1859,7 @@ static void cdvdWrite04(u8 rt)
|
||||
cdvdSetIrq();
|
||||
cdvd.nCommand = 0;
|
||||
//After reading the key it needs to go back to buffer the next sector
|
||||
cdvd.Status = CDVD_STATUS_READ;
|
||||
cdvd.Status = CDVD_STATUS_PAUSE;
|
||||
cdvd.nextSectorsBuffered = 0;
|
||||
cdvd.triggerDataReady = true;
|
||||
CDVDSECTORREADY_INT(cdvd.ReadTime);
|
||||
@@ -1996,7 +1964,6 @@ static __fi void fail_pol_cal()
|
||||
|
||||
static void cdvdWrite16(u8 rt) // SCOMMAND
|
||||
{
|
||||
try
|
||||
{
|
||||
// cdvdTN diskInfo;
|
||||
// cdvdTD trackInfo;
|
||||
@@ -2655,12 +2622,6 @@ static void cdvdWrite16(u8 rt) // SCOMMAND
|
||||
cdvd.ParamP = 0;
|
||||
cdvd.ParamC = 0;
|
||||
}
|
||||
catch (Exception::CannotCreateStream&)
|
||||
{
|
||||
Cpu->ThrowException(Exception::RuntimeError()
|
||||
.SetDiagMsg(L"Failed to read/write NVM/MEC file.")
|
||||
.SetUserMsg(pxE(L"Failed to read/write NVM/MEC file. Check your BIOS setup/permission settings.")));
|
||||
}
|
||||
}
|
||||
|
||||
static __fi void cdvdWrite17(u8 rt)
|
||||
|
||||
+19
-13
@@ -33,6 +33,7 @@
|
||||
#include "IsoFS/IsoFSCDVD.h"
|
||||
#include "CDVDisoReader.h"
|
||||
|
||||
#include "common/FileSystem.h"
|
||||
#include "common/StringUtil.h"
|
||||
#include "DebugTools/SymbolMap.h"
|
||||
#include "Config.h"
|
||||
@@ -376,33 +377,33 @@ bool DoCDVDopen()
|
||||
return true;
|
||||
}
|
||||
|
||||
wxString somepick(Path::GetFilenameWithoutExt(fromUTF8(m_SourceFilename[CurrentSourceType])));
|
||||
std::string somepick(FileSystem::StripExtension(FileSystem::GetDisplayNameFromPath(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.
|
||||
if (somepick.IsEmpty() && !DiscSerial.IsEmpty())
|
||||
somepick = L"Untitled-" + DiscSerial;
|
||||
else if (somepick.IsEmpty())
|
||||
somepick = L"Untitled";
|
||||
if (somepick.empty() && !DiscSerial.IsEmpty())
|
||||
somepick = StringUtil::StdStringFromFormat("Untitled-%s", DiscSerial.ToUTF8().data());
|
||||
else if (somepick.empty())
|
||||
somepick = "Untitled";
|
||||
|
||||
if (EmuConfig.CurrentBlockdump.empty())
|
||||
EmuConfig.CurrentBlockdump = StringUtil::wxStringToUTF8String(wxGetCwd());
|
||||
EmuConfig.CurrentBlockdump = FileSystem::GetWorkingDirectory();
|
||||
|
||||
wxString temp(Path::Combine(StringUtil::UTF8StringToWxString(EmuConfig.CurrentBlockdump), somepick));
|
||||
std::string temp(Path::CombineStdString(EmuConfig.CurrentBlockdump, somepick));
|
||||
|
||||
#ifdef ENABLE_TIMESTAMPS
|
||||
wxDateTime curtime(wxDateTime::GetTimeNow());
|
||||
|
||||
temp += pxsFmt(L" (%04d-%02d-%02d %02d-%02d-%02d)",
|
||||
curtime.GetYear(), curtime.GetMonth(), curtime.GetDay(),
|
||||
curtime.GetHour(), curtime.GetMinute(), curtime.GetSecond());
|
||||
temp += StringUtil::StdStringFromFormat(" (%04d-%02d-%02d %02d-%02d-%02d)",
|
||||
curtime.GetYear(), curtime.GetMonth(), curtime.GetDay(),
|
||||
curtime.GetHour(), curtime.GetMinute(), curtime.GetSecond());
|
||||
#endif
|
||||
temp += L".dump";
|
||||
temp += ".dump";
|
||||
|
||||
cdvdTD td;
|
||||
CDVD->getTD(0, &td);
|
||||
|
||||
blockDumpFile.Create(temp, 2);
|
||||
blockDumpFile.Create(std::move(temp), 2);
|
||||
|
||||
if (blockDumpFile.IsOpened())
|
||||
{
|
||||
@@ -432,7 +433,12 @@ bool DoCDVDopen()
|
||||
void DoCDVDclose()
|
||||
{
|
||||
CheckNullCDVD();
|
||||
//blockDumpFile.Close();
|
||||
|
||||
#ifdef PCSX2_CORE
|
||||
// This was commented out, presumably because pausing/resuming in wx reopens CDVD.
|
||||
// This is a non-issue in Qt, so we'll leave it behind the ifdef.
|
||||
blockDumpFile.Close();
|
||||
#endif
|
||||
|
||||
if (CDVD->close != NULL)
|
||||
CDVD->close();
|
||||
|
||||
@@ -52,7 +52,7 @@ s32 CALLBACK ISOopen(const char* pTitle)
|
||||
|
||||
try
|
||||
{
|
||||
iso.Open(fromUTF8(pTitle));
|
||||
iso.Open(pTitle);
|
||||
}
|
||||
catch (BaseException& ex)
|
||||
{
|
||||
|
||||
@@ -16,71 +16,98 @@
|
||||
#include "PrecompiledHeader.h"
|
||||
#include "ChdFileReader.h"
|
||||
|
||||
#include "CDVD/CompressedFileReaderUtils.h"
|
||||
#include "common/FileSystem.h"
|
||||
#include "common/StringUtil.h"
|
||||
|
||||
#include <wx/dir.h>
|
||||
|
||||
bool ChdFileReader::CanHandle(const wxString& fileName)
|
||||
ChdFileReader::~ChdFileReader()
|
||||
{
|
||||
if (!wxFileName::FileExists(fileName) || !fileName.Lower().EndsWith(L".chd"))
|
||||
{
|
||||
Close();
|
||||
|
||||
for (std::FILE* fp : m_files)
|
||||
std::fclose(fp);
|
||||
}
|
||||
|
||||
bool ChdFileReader::CanHandle(const std::string& fileName, const std::string& displayName)
|
||||
{
|
||||
if (!StringUtil::EndsWith(displayName, ".chd"))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ChdFileReader::Open2(const wxString& fileName)
|
||||
static chd_error chd_open_wrapper(const char* filename, std::FILE** fp, int mode, chd_file* parent, chd_file** chd)
|
||||
{
|
||||
*fp = FileSystem::OpenCFile(filename, "rb");
|
||||
if (!*fp)
|
||||
return CHDERR_FILE_NOT_FOUND;
|
||||
|
||||
const chd_error err = chd_open_file(*fp, mode, parent, chd);
|
||||
if (err == CHDERR_NONE)
|
||||
return err;
|
||||
|
||||
std::fclose(*fp);
|
||||
*fp = nullptr;
|
||||
return err;
|
||||
}
|
||||
|
||||
bool ChdFileReader::Open2(std::string fileName)
|
||||
{
|
||||
Close2();
|
||||
|
||||
m_filename = fileName;
|
||||
m_filename = std::move(fileName);
|
||||
|
||||
chd_file* child = NULL;
|
||||
chd_file* parent = NULL;
|
||||
chd_file* child = nullptr;
|
||||
chd_file* parent = nullptr;
|
||||
std::FILE* fp = nullptr;
|
||||
chd_header header;
|
||||
chd_header parent_header;
|
||||
|
||||
wxString chds[8];
|
||||
chds[0] = fileName;
|
||||
std::string chds[8];
|
||||
chds[0] = m_filename;
|
||||
int chd_depth = 0;
|
||||
chd_error error;
|
||||
|
||||
// TODO: Unicode correctness on Windows
|
||||
while (CHDERR_REQUIRES_PARENT == (error = chd_open(chds[chd_depth].c_str(), CHD_OPEN_READ, NULL, &child)))
|
||||
std::string dirname;
|
||||
FileSystem::FindResultsArray results;
|
||||
|
||||
while (CHDERR_REQUIRES_PARENT == (error = chd_open_wrapper(chds[chd_depth].c_str(), &fp, CHD_OPEN_READ, NULL, &child)))
|
||||
{
|
||||
if (chd_depth >= static_cast<int>(std::size(chds) - 1))
|
||||
{
|
||||
Console.Error(L"CDVD: chd_open hit recursion limit searching for parents");
|
||||
Console.Error("CDVD: chd_open hit recursion limit searching for parents");
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO: This is still broken on Windows. Needs to be fixed in libchdr.
|
||||
if (chd_read_header(chds[chd_depth].c_str(), &header) != CHDERR_NONE)
|
||||
{
|
||||
Console.Error(L"CDVD: chd_open chd_read_header error: %s: %s", chd_error_string(error), WX_STR(chds[chd_depth]));
|
||||
Console.Error("CDVD: chd_open chd_read_header error: %s: %s", chd_error_string(error), chds[chd_depth].c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
bool found_parent = false;
|
||||
wxFileName wxfilename(chds[chd_depth]);
|
||||
wxString dir_path = wxfilename.GetPath();
|
||||
wxDir dir(dir_path);
|
||||
if (dir.IsOpened())
|
||||
dirname = FileSystem::GetPathDirectory(chds[chd_depth]);
|
||||
if (FileSystem::FindFiles(dirname.c_str(), "*.*", FILESYSTEM_FIND_FILES | FILESYSTEM_FIND_HIDDEN_FILES, &results))
|
||||
{
|
||||
wxString parent_fileName;
|
||||
bool cont = dir.GetFirst(&parent_fileName, wxString("*.") + wxfilename.GetExt(), wxDIR_FILES | wxDIR_HIDDEN);
|
||||
for (; cont; cont = dir.GetNext(&parent_fileName))
|
||||
for (const FILESYSTEM_FIND_DATA& fd : results)
|
||||
{
|
||||
parent_fileName = wxFileName(dir_path, parent_fileName).GetFullPath();
|
||||
if (chd_read_header(parent_fileName.c_str(), &parent_header) == CHDERR_NONE &&
|
||||
const std::string_view extension(FileSystem::GetExtension(fd.FileName));
|
||||
if (extension.empty() || StringUtil::Strncasecmp(extension.data(), "chd", 3) != 0)
|
||||
continue;
|
||||
|
||||
if (chd_read_header(fd.FileName.c_str(), &parent_header) == CHDERR_NONE &&
|
||||
memcmp(parent_header.sha1, header.parentsha1, sizeof(parent_header.sha1)) == 0)
|
||||
{
|
||||
found_parent = true;
|
||||
chds[++chd_depth] = wxString(parent_fileName);
|
||||
chds[++chd_depth] = std::move(fd.FileName);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!found_parent)
|
||||
{
|
||||
Console.Error(L"CDVD: chd_open no parent for: %s", WX_STR(chds[chd_depth]));
|
||||
Console.Error("CDVD: chd_open no parent for: %s", chds[chd_depth].c_str());
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -91,11 +118,17 @@ bool ChdFileReader::Open2(const wxString& fileName)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (child)
|
||||
{
|
||||
pxAssert(fp != nullptr);
|
||||
m_files.push_back(fp);
|
||||
}
|
||||
|
||||
for (int d = chd_depth - 1; d >= 0; d--)
|
||||
{
|
||||
parent = child;
|
||||
child = NULL;
|
||||
error = chd_open(chds[d].c_str(), CHD_OPEN_READ, parent, &child);
|
||||
error = chd_open_wrapper(chds[d].c_str(), &fp, CHD_OPEN_READ, parent, &child);
|
||||
if (error != CHDERR_NONE)
|
||||
{
|
||||
Console.Error(L"CDVD: chd_open return error: %s", chd_error_string(error));
|
||||
@@ -103,19 +136,17 @@ bool ChdFileReader::Open2(const wxString& fileName)
|
||||
chd_close(parent);
|
||||
return false;
|
||||
}
|
||||
|
||||
m_files.push_back(fp);
|
||||
}
|
||||
ChdFile = child;
|
||||
if (chd_read_header(chds[0].c_str(), &header) != CHDERR_NONE)
|
||||
{
|
||||
Console.Error(L"CDVD: chd_open chd_read_header error: %s: %s", chd_error_string(error), WX_STR(chds[0]));
|
||||
return false;
|
||||
}
|
||||
|
||||
file_size = static_cast<u64>(header.unitbytes) * header.unitcount;
|
||||
hunk_size = header.hunkbytes;
|
||||
const chd_header* chd_header = chd_get_header(ChdFile);
|
||||
file_size = static_cast<u64>(chd_header->unitbytes) * chd_header->unitcount;
|
||||
hunk_size = chd_header->hunkbytes;
|
||||
// CHD likes to use full 2448 byte blocks, but keeps the +24 offset of source ISOs
|
||||
// The rest of PCSX2 likes to use 2448 byte buffers, which can't fit that so trim blocks instead
|
||||
m_internalBlockSize = header.unitbytes;
|
||||
m_internalBlockSize = chd_header->unitbytes;
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -136,7 +167,7 @@ ThreadedFileReader::Chunk ChdFileReader::ChunkForOffset(u64 offset)
|
||||
return chunk;
|
||||
}
|
||||
|
||||
int ChdFileReader::ReadChunk(void *dst, s64 chunkID)
|
||||
int ChdFileReader::ReadChunk(void* dst, s64 chunkID)
|
||||
{
|
||||
if (chunkID < 0)
|
||||
return -1;
|
||||
|
||||
@@ -16,16 +16,17 @@
|
||||
#pragma once
|
||||
#include "ThreadedFileReader.h"
|
||||
#include "libchdr/chd.h"
|
||||
#include <vector>
|
||||
|
||||
class ChdFileReader : public ThreadedFileReader
|
||||
{
|
||||
DeclareNoncopyableObject(ChdFileReader);
|
||||
|
||||
public:
|
||||
virtual ~ChdFileReader(void) { Close(); };
|
||||
virtual ~ChdFileReader() override;;
|
||||
|
||||
static bool CanHandle(const wxString& fileName);
|
||||
bool Open2(const wxString& fileName) override;
|
||||
static bool CanHandle(const std::string& fileName, const std::string& displayName);
|
||||
bool Open2(std::string fileName) override;
|
||||
|
||||
Chunk ChunkForOffset(u64 offset) override;
|
||||
int ReadChunk(void *dst, s64 blockID) override;
|
||||
@@ -38,4 +39,5 @@ private:
|
||||
chd_file* ChdFile;
|
||||
u64 file_size;
|
||||
u32 hunk_size;
|
||||
std::vector<std::FILE*> m_files;
|
||||
};
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
void ChunksCache::SetLimit(uint megabytes)
|
||||
{
|
||||
m_limit = (PX_off_t)megabytes * 1024 * 1024;
|
||||
m_limit = (s64)megabytes * 1024 * 1024;
|
||||
MatchLimit();
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ void ChunksCache::MatchLimit(bool removeAll)
|
||||
}
|
||||
}
|
||||
|
||||
void ChunksCache::Take(void* pMallocedSrc, PX_off_t offset, int length, int coverage)
|
||||
void ChunksCache::Take(void* pMallocedSrc, s64 offset, int length, int coverage)
|
||||
{
|
||||
m_entries.push_front(new CacheEntry(pMallocedSrc, offset, length, coverage));
|
||||
m_size += length;
|
||||
@@ -42,7 +42,7 @@ void ChunksCache::Take(void* pMallocedSrc, PX_off_t offset, int length, int cove
|
||||
}
|
||||
|
||||
// By design, succeed only if the entire request is in a single cached chunk
|
||||
int ChunksCache::Read(void* pDest, PX_off_t offset, int length)
|
||||
int ChunksCache::Read(void* pDest, s64 offset, int length)
|
||||
{
|
||||
for (auto it = m_entries.begin(); it != m_entries.end(); it++)
|
||||
{
|
||||
|
||||
@@ -30,11 +30,11 @@ public:
|
||||
void SetLimit(uint megabytes);
|
||||
void Clear() { MatchLimit(true); };
|
||||
|
||||
void Take(void* pMallocedSrc, PX_off_t offset, int length, int coverage);
|
||||
int Read(void* pDest, PX_off_t offset, int length);
|
||||
void Take(void* pMallocedSrc, s64 offset, int length, int coverage);
|
||||
int Read(void* pDest, s64 offset, int length);
|
||||
|
||||
static int CopyAvailable(void* pSrc, PX_off_t srcOffset, int srcSize,
|
||||
void* pDst, PX_off_t dstOffset, int maxCopySize)
|
||||
static int CopyAvailable(void* pSrc, s64 srcOffset, int srcSize,
|
||||
void* pDst, s64 dstOffset, int maxCopySize)
|
||||
{
|
||||
int available = CLAMP(maxCopySize, 0, (int)(srcOffset + srcSize - dstOffset));
|
||||
memcpy(pDst, (char*)pSrc + (dstOffset - srcOffset), available);
|
||||
@@ -45,7 +45,7 @@ private:
|
||||
class CacheEntry
|
||||
{
|
||||
public:
|
||||
CacheEntry(void* pMallocedSrc, PX_off_t offset, int length, int coverage)
|
||||
CacheEntry(void* pMallocedSrc, s64 offset, int length, int coverage)
|
||||
: data(pMallocedSrc)
|
||||
, offset(offset)
|
||||
, coverage(coverage)
|
||||
@@ -58,15 +58,15 @@ private:
|
||||
};
|
||||
|
||||
void* data;
|
||||
PX_off_t offset;
|
||||
s64 offset;
|
||||
int coverage;
|
||||
int size;
|
||||
};
|
||||
|
||||
std::list<CacheEntry*> m_entries;
|
||||
void MatchLimit(bool removeAll = false);
|
||||
PX_off_t m_size;
|
||||
PX_off_t m_limit;
|
||||
s64 m_size;
|
||||
s64 m_limit;
|
||||
};
|
||||
|
||||
#undef CLAMP
|
||||
|
||||
@@ -19,19 +19,27 @@
|
||||
#include "ChdFileReader.h"
|
||||
#include "CsoFileReader.h"
|
||||
#include "GzippedFileReader.h"
|
||||
#include "common/FileSystem.h"
|
||||
#include <cctype>
|
||||
|
||||
// CompressedFileReader factory.
|
||||
AsyncFileReader* CompressedFileReader::GetNewReader(const wxString& fileName)
|
||||
AsyncFileReader* CompressedFileReader::GetNewReader(const std::string& fileName)
|
||||
{
|
||||
if (ChdFileReader::CanHandle(fileName))
|
||||
if (!FileSystem::FileExists(fileName.c_str()))
|
||||
return nullptr;
|
||||
|
||||
std::string displayName(FileSystem::GetDisplayNameFromPath(fileName));
|
||||
std::transform(displayName.begin(), displayName.end(), displayName.begin(), tolower);
|
||||
|
||||
if (ChdFileReader::CanHandle(fileName, displayName))
|
||||
{
|
||||
return new ChdFileReader();
|
||||
}
|
||||
if (GzippedFileReader::CanHandle(fileName))
|
||||
if (GzippedFileReader::CanHandle(fileName, displayName))
|
||||
{
|
||||
return new GzippedFileReader();
|
||||
}
|
||||
if (CsoFileReader::CanHandle(fileName))
|
||||
if (CsoFileReader::CanHandle(fileName, displayName))
|
||||
{
|
||||
return new CsoFileReader();
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <string>
|
||||
|
||||
// Factory - creates an AsyncFileReader derived instance which can read a compressed file
|
||||
class CompressedFileReader
|
||||
@@ -23,7 +24,7 @@ public:
|
||||
// If no matching handler is found, NULL is returned.
|
||||
// The returned instance still needs ->Open(filename) before usage.
|
||||
// Open(filename) may still fail.
|
||||
static AsyncFileReader* GetNewReader(const wxString& fileName);
|
||||
static AsyncFileReader* GetNewReader(const std::string& fileName);
|
||||
|
||||
private:
|
||||
virtual ~CompressedFileReader() = 0;
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2014 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 "common/Pcsx2Types.h"
|
||||
|
||||
/////////// Some complementary utilities for zlib_indexed.c //////////
|
||||
|
||||
// This is ugly, but it's hard to find something which will work/compile for both
|
||||
// windows and *nix and work with non-english file names.
|
||||
// Maybe some day we'll convert all file related ops to wxWidgets, which means also the
|
||||
// instances at zlib_indexed.h (which use plain stdio FILE*)
|
||||
#ifdef _WIN32
|
||||
#define PX_wfilename(name_wxstr) (name_wxstr.wc_str())
|
||||
#define PX_fopen_rb(name_wxstr) (_wfopen(PX_wfilename(name_wxstr), L"rb"))
|
||||
#else
|
||||
#define PX_wfilename(name_wxstr) (name_wxstr.mbc_str())
|
||||
#define PX_fopen_rb(name_wxstr) (fopen(PX_wfilename(name_wxstr), "rb"))
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#define PX_fseeko _fseeki64
|
||||
#define PX_ftello _ftelli64
|
||||
#define PX_off_t s64 /* __int64 */
|
||||
#else
|
||||
#define PX_fseeko fseeko
|
||||
#define PX_ftello ftello
|
||||
#define PX_off_t off_t
|
||||
#endif
|
||||
|
||||
/////////// End of complementary utilities for zlib_indexed.c //////////
|
||||
@@ -15,9 +15,10 @@
|
||||
|
||||
#include "PrecompiledHeader.h"
|
||||
#include "AsyncFileReader.h"
|
||||
#include "CompressedFileReaderUtils.h"
|
||||
#include "CsoFileReader.h"
|
||||
#include "common/Pcsx2Types.h"
|
||||
#include "common/FileSystem.h"
|
||||
#include "common/StringUtil.h"
|
||||
#ifdef __POSIX__
|
||||
#include <zlib.h>
|
||||
#else
|
||||
@@ -39,12 +40,12 @@ struct CsoHeader
|
||||
|
||||
static const u32 CSO_READ_BUFFER_SIZE = 256 * 1024;
|
||||
|
||||
bool CsoFileReader::CanHandle(const wxString& fileName)
|
||||
bool CsoFileReader::CanHandle(const std::string& fileName, const std::string& displayName)
|
||||
{
|
||||
bool supported = false;
|
||||
if (wxFileName::FileExists(fileName) && fileName.Lower().EndsWith(L".cso"))
|
||||
if (StringUtil::EndsWith(displayName, ".cso"))
|
||||
{
|
||||
FILE* fp = PX_fopen_rb(fileName);
|
||||
FILE* fp = FileSystem::OpenCFile(fileName.c_str(), "rb");
|
||||
CsoHeader hdr;
|
||||
if (fp)
|
||||
{
|
||||
@@ -67,17 +68,17 @@ bool CsoFileReader::ValidateHeader(const CsoHeader& hdr)
|
||||
}
|
||||
if (hdr.ver > 1)
|
||||
{
|
||||
Console.Error(L"Only CSOv1 files are supported.");
|
||||
Console.Error("Only CSOv1 files are supported.");
|
||||
return false;
|
||||
}
|
||||
if ((hdr.frame_size & (hdr.frame_size - 1)) != 0)
|
||||
{
|
||||
Console.Error(L"CSO frame size must be a power of two.");
|
||||
Console.Error("CSO frame size must be a power of two.");
|
||||
return false;
|
||||
}
|
||||
if (hdr.frame_size < 2048)
|
||||
{
|
||||
Console.Error(L"CSO frame size must be at least one sector.");
|
||||
Console.Error("CSO frame size must be at least one sector.");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -85,11 +86,11 @@ bool CsoFileReader::ValidateHeader(const CsoHeader& hdr)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CsoFileReader::Open2(const wxString& fileName)
|
||||
bool CsoFileReader::Open2(std::string fileName)
|
||||
{
|
||||
Close2();
|
||||
m_filename = fileName;
|
||||
m_src = PX_fopen_rb(m_filename);
|
||||
m_filename = std::move(fileName);
|
||||
m_src = FileSystem::OpenCFile(m_filename.c_str(), "rb");
|
||||
|
||||
bool success = false;
|
||||
if (m_src && ReadFileHeader() && InitializeBuffers())
|
||||
@@ -109,16 +110,15 @@ bool CsoFileReader::ReadFileHeader()
|
||||
{
|
||||
CsoHeader hdr = {};
|
||||
|
||||
PX_fseeko(m_src, m_dataoffset, SEEK_SET);
|
||||
if (fread(&hdr, 1, sizeof(hdr), m_src) != sizeof(hdr))
|
||||
if (FileSystem::FSeek64(m_src, m_dataoffset, SEEK_SET) != 0 || std::fread(&hdr, 1, sizeof(hdr), m_src) != sizeof(hdr))
|
||||
{
|
||||
Console.Error(L"Failed to read CSO file header.");
|
||||
Console.Error("Failed to read CSO file header.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!ValidateHeader(hdr))
|
||||
{
|
||||
Console.Error(L"CSO has invalid header.");
|
||||
Console.Error("CSO has invalid header.");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -156,7 +156,7 @@ bool CsoFileReader::InitializeBuffers()
|
||||
m_index = new u32[indexSize];
|
||||
if (fread(m_index, sizeof(u32), indexSize, m_src) != indexSize)
|
||||
{
|
||||
Console.Error(L"Unable to read index data from CSO.");
|
||||
Console.Error("Unable to read index data from CSO.");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -175,7 +175,7 @@ bool CsoFileReader::InitializeBuffers()
|
||||
|
||||
void CsoFileReader::Close2()
|
||||
{
|
||||
m_filename.Empty();
|
||||
m_filename.clear();
|
||||
|
||||
if (m_src)
|
||||
{
|
||||
@@ -235,7 +235,7 @@ int CsoFileReader::ReadChunk(void *dst, s64 chunkID)
|
||||
if (!compressed)
|
||||
{
|
||||
// Just read directly, easy.
|
||||
if (PX_fseeko(m_src, frameRawPos, SEEK_SET) != 0)
|
||||
if (FileSystem::FSeek64(m_src, frameRawPos, SEEK_SET) != 0)
|
||||
{
|
||||
Console.Error("Unable to seek to uncompressed CSO data.");
|
||||
return 0;
|
||||
@@ -244,7 +244,7 @@ int CsoFileReader::ReadChunk(void *dst, s64 chunkID)
|
||||
}
|
||||
else
|
||||
{
|
||||
if (PX_fseeko(m_src, frameRawPos, SEEK_SET) != 0)
|
||||
if (FileSystem::FSeek64(m_src, frameRawPos, SEEK_SET) != 0)
|
||||
{
|
||||
Console.Error("Unable to seek to compressed CSO data.");
|
||||
return 0;
|
||||
|
||||
@@ -52,8 +52,8 @@ public:
|
||||
|
||||
~CsoFileReader(void) { Close(); };
|
||||
|
||||
static bool CanHandle(const wxString& fileName);
|
||||
bool Open2(const wxString& fileName) override;
|
||||
static bool CanHandle(const std::string& fileName, const std::string& displayName);
|
||||
bool Open2(std::string fileName) override;
|
||||
|
||||
Chunk ChunkForOffset(u64 offset) override;
|
||||
int ReadChunk(void *dst, s64 chunkID) override;
|
||||
|
||||
@@ -14,29 +14,17 @@
|
||||
*/
|
||||
|
||||
#include "PrecompiledHeader.h"
|
||||
#include <fstream>
|
||||
#include <wx/stdpaths.h>
|
||||
#include <fstream>
|
||||
#include "common/FileSystem.h"
|
||||
#include "common/StringUtil.h"
|
||||
#include "Config.h"
|
||||
#include "ChunksCache.h"
|
||||
#include "CompressedFileReaderUtils.h"
|
||||
#include "GzippedFileReader.h"
|
||||
#include "zlib_indexed.h"
|
||||
|
||||
#define CLAMP(val, minval, maxval) (std::min(maxval, std::max(minval, val)))
|
||||
|
||||
static s64 fsize(const wxString& filename)
|
||||
{
|
||||
if (!wxFileName::FileExists(filename))
|
||||
return -1;
|
||||
|
||||
std::ifstream f(PX_wfilename(filename), std::ifstream::binary);
|
||||
f.seekg(0, f.end);
|
||||
s64 size = f.tellg();
|
||||
f.close();
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
#define GZIP_ID "PCSX2.index.gzip.v1|"
|
||||
#define GZIP_ID_LEN (sizeof(GZIP_ID) - 1) /* sizeof includes the \0 terminator */
|
||||
|
||||
@@ -44,71 +32,75 @@ static s64 fsize(const wxString& filename)
|
||||
// - [GZIP_ID_LEN] GZIP_ID (no \0)
|
||||
// - [sizeof(Access)] index (should be allocated, contains various sizes)
|
||||
// - [rest] the indexed data points (should be allocated, index->list should then point to it)
|
||||
static Access* ReadIndexFromFile(const wxString& filename)
|
||||
static Access* ReadIndexFromFile(const char* filename)
|
||||
{
|
||||
s64 size = fsize(filename);
|
||||
if (size <= 0)
|
||||
auto fp = FileSystem::OpenManagedCFile(filename, "rb");
|
||||
s64 size;
|
||||
if (!fp || (size = FileSystem::FSize64(fp.get())) <= 0)
|
||||
{
|
||||
Console.Error(L"Error: Can't open index file: '%s'", WX_STR(filename));
|
||||
Console.Error("Error: Can't open index file: '%s'", filename);
|
||||
return 0;
|
||||
}
|
||||
std::ifstream infile(PX_wfilename(filename), std::ifstream::binary);
|
||||
|
||||
char fileId[GZIP_ID_LEN + 1] = {0};
|
||||
infile.read(fileId, GZIP_ID_LEN);
|
||||
if (wxString::From8BitData(GZIP_ID) != wxString::From8BitData(fileId))
|
||||
if (std::fread(fileId, GZIP_ID_LEN, 1, fp.get()) != 1 || std::memcmp(fileId, GZIP_ID, 4) != 0)
|
||||
{
|
||||
Console.Error(L"Error: Incompatible gzip index, please delete it manually: '%s'", WX_STR(filename));
|
||||
infile.close();
|
||||
Console.Error("Error: Incompatible gzip index, please delete it manually: '%s'", filename);
|
||||
return 0;
|
||||
}
|
||||
|
||||
Access* index = (Access*)malloc(sizeof(Access));
|
||||
infile.read((char*)index, sizeof(Access));
|
||||
|
||||
s64 datasize = size - GZIP_ID_LEN - sizeof(Access);
|
||||
if (datasize != (s64)index->have * sizeof(Point))
|
||||
Access* const index = (Access*)malloc(sizeof(Access));
|
||||
const s64 datasize = size - GZIP_ID_LEN - sizeof(Access);
|
||||
if (std::fread(index, sizeof(Access), 1, fp.get()) != 1 ||
|
||||
datasize != static_cast<s64>(index->have) * static_cast<s64>(sizeof(Point)))
|
||||
{
|
||||
Console.Error(L"Error: unexpected size of gzip index, please delete it manually: '%s'.", WX_STR(filename));
|
||||
infile.close();
|
||||
Console.Error("Error: unexpected size of gzip index, please delete it manually: '%s'.", filename);
|
||||
free(index);
|
||||
return 0;
|
||||
}
|
||||
|
||||
char* buffer = (char*)malloc(datasize);
|
||||
infile.read(buffer, datasize);
|
||||
infile.close();
|
||||
if (std::fread(buffer, datasize, 1, fp.get()) != 1)
|
||||
{
|
||||
Console.Error("Error: failed read of gzip index, please delete it manually: '%s'.", filename);
|
||||
free(buffer);
|
||||
free(index);
|
||||
return 0;
|
||||
}
|
||||
|
||||
index->list = (Point*)buffer; // adjust list pointer
|
||||
return index;
|
||||
}
|
||||
|
||||
static void WriteIndexToFile(Access* index, const wxString filename)
|
||||
static void WriteIndexToFile(Access* index, const char* filename)
|
||||
{
|
||||
if (wxFileName::FileExists(filename))
|
||||
if (FileSystem::FileExists(filename))
|
||||
{
|
||||
Console.Warning(L"WARNING: Won't write index - file name exists (please delete it manually): '%s'", WX_STR(filename));
|
||||
Console.Warning("WARNING: Won't write index - file name exists (please delete it manually): '%s'", filename);
|
||||
return;
|
||||
}
|
||||
|
||||
std::ofstream outfile(PX_wfilename(filename), std::ofstream::binary);
|
||||
outfile.write(GZIP_ID, GZIP_ID_LEN);
|
||||
auto fp = FileSystem::OpenManagedCFile(filename, "wb");
|
||||
if (!fp)
|
||||
return;
|
||||
|
||||
bool success = (std::fwrite(GZIP_ID, GZIP_ID_LEN, 1, fp.get()) == 1);
|
||||
|
||||
Point* tmp = index->list;
|
||||
index->list = 0; // current pointer is useless on disk, normalize it as 0.
|
||||
outfile.write((char*)index, sizeof(Access));
|
||||
std::fwrite((char*)index, sizeof(Access), 1, fp.get());
|
||||
index->list = tmp;
|
||||
|
||||
outfile.write((char*)index->list, sizeof(Point) * index->have);
|
||||
outfile.close();
|
||||
success = success && (std::fwrite((char*)index->list, sizeof(Point) * index->have, 1, fp.get()) == 1);
|
||||
|
||||
// Verify
|
||||
if (fsize(filename) != (s64)GZIP_ID_LEN + sizeof(Access) + sizeof(Point) * index->have)
|
||||
if (!success)
|
||||
{
|
||||
Console.Warning(L"Warning: Can't write index file to disk: '%s'", WX_STR(filename));
|
||||
Console.Warning("Warning: Can't write index file to disk: '%s'", filename);
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLn(Color_Green, L"OK: Gzip quick access index file saved to disk: '%s'", WX_STR(filename));
|
||||
Console.WriteLn(Color_Green, "OK: Gzip quick access index file saved to disk: '%s'", filename);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -123,10 +115,10 @@ static wxString INDEX_TEMPLATE_KEY(L"$(f)");
|
||||
// No checks are performed if the result file name can be created.
|
||||
// If this proves useful, we can move it into Path:: . Right now there's no need.
|
||||
static wxString ApplyTemplate(const wxString& name, const wxDirName& base,
|
||||
const wxString& fileTemplate, const wxString& filename,
|
||||
const std::string& fileTemplate, const std::string& filename,
|
||||
bool canEndWithKey)
|
||||
{
|
||||
wxString tem(fileTemplate);
|
||||
wxString tem(StringUtil::UTF8StringToWxString(fileTemplate));
|
||||
wxString key = INDEX_TEMPLATE_KEY;
|
||||
tem = tem.Trim(true).Trim(false); // both sides
|
||||
|
||||
@@ -141,7 +133,7 @@ static wxString ApplyTemplate(const wxString& name, const wxDirName& base,
|
||||
return L"";
|
||||
}
|
||||
|
||||
wxString fname(filename);
|
||||
wxString fname(StringUtil::UTF8StringToWxString(filename));
|
||||
if (first > 0)
|
||||
fname = Path::GetFilename(fname); // without path
|
||||
|
||||
@@ -179,13 +171,13 @@ static void TestTemplate(const wxDirName &base, const wxString &fname, bool canE
|
||||
}
|
||||
*/
|
||||
|
||||
static wxString iso2indexname(const wxString& isoname)
|
||||
static std::string iso2indexname(const std::string& isoname)
|
||||
{
|
||||
//testTemplate(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, fromUTF8(EmuConfig.GzipIsoIndexTemplate), isoname, false);
|
||||
return StringUtil::wxStringToUTF8String(ApplyTemplate(L"gzip index", appRoot, EmuConfig.GzipIsoIndexTemplate, isoname, false));
|
||||
}
|
||||
|
||||
GzippedFileReader::GzippedFileReader(void)
|
||||
@@ -218,7 +210,7 @@ void GzippedFileReader::InitZstates()
|
||||
void GzippedFileReader::AsyncPrefetchReset(){};
|
||||
void GzippedFileReader::AsyncPrefetchOpen(){};
|
||||
void GzippedFileReader::AsyncPrefetchClose(){};
|
||||
void GzippedFileReader::AsyncPrefetchChunk(PX_off_t dummy){};
|
||||
void GzippedFileReader::AsyncPrefetchChunk(s64 dummy){};
|
||||
void GzippedFileReader::AsyncPrefetchCancel(){};
|
||||
#else
|
||||
// AsyncPrefetch works as follows:
|
||||
@@ -239,7 +231,7 @@ void GzippedFileReader::AsyncPrefetchReset()
|
||||
void GzippedFileReader::AsyncPrefetchOpen()
|
||||
{
|
||||
hOverlappedFile = CreateFile(
|
||||
m_filename,
|
||||
StringUtil::UTF8StringToWideString(m_filename).c_str(),
|
||||
GENERIC_READ,
|
||||
FILE_SHARE_READ,
|
||||
NULL,
|
||||
@@ -258,7 +250,7 @@ void GzippedFileReader::AsyncPrefetchClose()
|
||||
AsyncPrefetchReset();
|
||||
};
|
||||
|
||||
void GzippedFileReader::AsyncPrefetchChunk(PX_off_t start)
|
||||
void GzippedFileReader::AsyncPrefetchChunk(s64 start)
|
||||
{
|
||||
if (hOverlappedFile == INVALID_HANDLE_VALUE || asyncInProgress)
|
||||
{
|
||||
@@ -296,9 +288,9 @@ void GzippedFileReader::AsyncPrefetchCancel()
|
||||
#endif /* _WIN32 */
|
||||
|
||||
// TODO: do better than just checking existance and extension
|
||||
bool GzippedFileReader::CanHandle(const wxString& fileName)
|
||||
bool GzippedFileReader::CanHandle(const std::string& fileName, const std::string& displayName)
|
||||
{
|
||||
return wxFileName::FileExists(fileName) && fileName.Lower().EndsWith(L".gz");
|
||||
return StringUtil::EndsWith(fileName, ".gz");
|
||||
}
|
||||
|
||||
bool GzippedFileReader::OkIndex()
|
||||
@@ -307,29 +299,29 @@ bool GzippedFileReader::OkIndex()
|
||||
return true;
|
||||
|
||||
// Try to read index from disk
|
||||
wxString indexfile = iso2indexname(m_filename);
|
||||
if (indexfile.length() == 0)
|
||||
const std::string indexfile(iso2indexname(m_filename));
|
||||
if (indexfile.empty())
|
||||
return false; // iso2indexname(...) will print errors if it can't apply the template
|
||||
|
||||
if (wxFileName::FileExists(indexfile) && (m_pIndex = ReadIndexFromFile(indexfile)))
|
||||
if (FileSystem::FileExists(indexfile.c_str()) && (m_pIndex = ReadIndexFromFile(indexfile.c_str())))
|
||||
{
|
||||
Console.WriteLn(Color_Green, L"OK: Gzip quick access index read from disk: '%s'", WX_STR(indexfile));
|
||||
Console.WriteLn(Color_Green, "OK: Gzip quick access index read from disk: '%s'", indexfile.c_str());
|
||||
if (m_pIndex->span != GZFILE_SPAN_DEFAULT)
|
||||
{
|
||||
Console.Warning(L"Note: This index has %1.1f MB intervals, while the current default for new indexes is %1.1f MB.",
|
||||
Console.Warning("Note: This index has %1.1f MB intervals, while the current default for new indexes is %1.1f MB.",
|
||||
(float)m_pIndex->span / 1024 / 1024, (float)GZFILE_SPAN_DEFAULT / 1024 / 1024);
|
||||
Console.Warning(L"It will work fine, but if you want to generate a new index with default intervals, delete this index file.");
|
||||
Console.Warning(L"(smaller intervals mean bigger index file and quicker but more frequent decompressions)");
|
||||
Console.Warning("It will work fine, but if you want to generate a new index with default intervals, delete this index file.");
|
||||
Console.Warning("(smaller intervals mean bigger index file and quicker but more frequent decompressions)");
|
||||
}
|
||||
InitZstates();
|
||||
return true;
|
||||
}
|
||||
|
||||
// No valid index file. Generate an index
|
||||
Console.Warning(L"This may take a while (but only once). Scanning compressed file to generate a quick access index...");
|
||||
Console.Warning("This may take a while (but only once). Scanning compressed file to generate a quick access index...");
|
||||
|
||||
Access* index;
|
||||
FILE* infile = PX_fopen_rb(m_filename);
|
||||
FILE* infile = FileSystem::OpenCFile(m_filename.c_str(), "rb");
|
||||
int len = build_index(infile, GZFILE_SPAN_DEFAULT, &index);
|
||||
printf("\n"); // build_index prints progress without \n's
|
||||
fclose(infile);
|
||||
@@ -337,11 +329,11 @@ bool GzippedFileReader::OkIndex()
|
||||
if (len >= 0)
|
||||
{
|
||||
m_pIndex = index;
|
||||
WriteIndexToFile((Access*)m_pIndex, indexfile);
|
||||
WriteIndexToFile((Access*)m_pIndex, indexfile.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.Error(L"ERROR (%d): index could not be generated for file '%s'", len, WX_STR(m_filename));
|
||||
Console.Error("ERROR (%d): index could not be generated for file '%s'", len, m_filename.c_str());
|
||||
free_index(index);
|
||||
InitZstates();
|
||||
return false;
|
||||
@@ -351,11 +343,11 @@ bool GzippedFileReader::OkIndex()
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GzippedFileReader::Open(const wxString& fileName)
|
||||
bool GzippedFileReader::Open(std::string fileName)
|
||||
{
|
||||
Close();
|
||||
m_filename = fileName;
|
||||
if (!(m_src = PX_fopen_rb(m_filename)) || !CanHandle(fileName) || !OkIndex())
|
||||
m_filename = std::move(fileName);
|
||||
if (!(m_src = FileSystem::OpenCFile(m_filename.c_str(), "rb")) || !OkIndex())
|
||||
{
|
||||
Close();
|
||||
return false;
|
||||
@@ -384,7 +376,7 @@ int GzippedFileReader::FinishRead(void)
|
||||
|
||||
int GzippedFileReader::ReadSync(void* pBuffer, uint sector, uint count)
|
||||
{
|
||||
PX_off_t offset = (s64)sector * m_blocksize + m_dataoffset;
|
||||
s64 offset = (s64)sector * m_blocksize + m_dataoffset;
|
||||
int bytesToRead = count * m_blocksize;
|
||||
int res = _ReadSync(pBuffer, offset, bytesToRead);
|
||||
if (res < 0)
|
||||
@@ -393,11 +385,11 @@ int GzippedFileReader::ReadSync(void* pBuffer, uint sector, uint count)
|
||||
}
|
||||
|
||||
// If we have a valid and adequate zstate for this span, use it, else, use the index
|
||||
PX_off_t GzippedFileReader::GetOptimalExtractionStart(PX_off_t offset)
|
||||
s64 GzippedFileReader::GetOptimalExtractionStart(s64 offset)
|
||||
{
|
||||
int span = m_pIndex->span;
|
||||
Czstate& cstate = m_zstates[offset / span];
|
||||
PX_off_t stateOffset = cstate.state.isValid ? cstate.state.out_offset : 0;
|
||||
s64 stateOffset = cstate.state.isValid ? cstate.state.out_offset : 0;
|
||||
if (stateOffset && stateOffset <= offset)
|
||||
return stateOffset; // state is faster than indexed
|
||||
|
||||
@@ -409,7 +401,7 @@ PX_off_t GzippedFileReader::GetOptimalExtractionStart(PX_off_t offset)
|
||||
return span * (offset / span); // index direct access boundaries
|
||||
}
|
||||
|
||||
int GzippedFileReader::_ReadSync(void* pBuffer, PX_off_t offset, uint bytesToRead)
|
||||
int GzippedFileReader::_ReadSync(void* pBuffer, s64 offset, uint bytesToRead)
|
||||
{
|
||||
if (!OkIndex())
|
||||
return -1;
|
||||
@@ -441,7 +433,7 @@ int GzippedFileReader::_ReadSync(void* pBuffer, PX_off_t offset, uint bytesToRea
|
||||
// Not available from cache. Decompress from optimal starting
|
||||
// point in GZFILE_READ_CHUNK_SIZE chunks and cache each chunk.
|
||||
PTT s = NOW();
|
||||
PX_off_t extractOffset = GetOptimalExtractionStart(offset); // guaranteed in GZFILE_READ_CHUNK_SIZE boundaries
|
||||
s64 extractOffset = GetOptimalExtractionStart(offset); // guaranteed in GZFILE_READ_CHUNK_SIZE boundaries
|
||||
int size = offset + maxInChunk - extractOffset;
|
||||
unsigned char* extracted = (unsigned char*)malloc(size);
|
||||
|
||||
@@ -501,7 +493,7 @@ int GzippedFileReader::_ReadSync(void* pBuffer, PX_off_t offset, uint bytesToRea
|
||||
|
||||
void GzippedFileReader::Close()
|
||||
{
|
||||
m_filename.Empty();
|
||||
m_filename.clear();
|
||||
if (m_pIndex)
|
||||
{
|
||||
free_index((Access*)m_pIndex);
|
||||
|
||||
@@ -34,8 +34,8 @@ public:
|
||||
|
||||
virtual ~GzippedFileReader(void) { Close(); };
|
||||
|
||||
static bool CanHandle(const wxString& fileName);
|
||||
virtual bool Open(const wxString& fileName);
|
||||
static bool CanHandle(const std::string& fileName, const std::string& displayName);
|
||||
virtual bool Open(std::string fileName);
|
||||
|
||||
virtual int ReadSync(void* pBuffer, uint sector, uint count);
|
||||
|
||||
@@ -71,8 +71,8 @@ private:
|
||||
};
|
||||
|
||||
bool OkIndex(); // Verifies that we have an index, or try to create one
|
||||
PX_off_t GetOptimalExtractionStart(PX_off_t offset);
|
||||
int _ReadSync(void* pBuffer, PX_off_t offset, uint bytesToRead);
|
||||
s64 GetOptimalExtractionStart(s64 offset);
|
||||
int _ReadSync(void* pBuffer, s64 offset, uint bytesToRead);
|
||||
void InitZstates();
|
||||
|
||||
int mBytesRead; // Temp sync read result when simulating async read
|
||||
@@ -93,6 +93,6 @@ private:
|
||||
void AsyncPrefetchReset();
|
||||
void AsyncPrefetchOpen();
|
||||
void AsyncPrefetchClose();
|
||||
void AsyncPrefetchChunk(PX_off_t dummy);
|
||||
void AsyncPrefetchChunk(s64 dummy);
|
||||
void AsyncPrefetchCancel();
|
||||
};
|
||||
|
||||
@@ -194,19 +194,16 @@ void InputIsoFile::_init()
|
||||
//
|
||||
// Note that this is a member method, and that it will clobber any existing ISO state.
|
||||
// (assertions are generated in debug mode if the object state is not already closed).
|
||||
bool InputIsoFile::Test(const wxString& srcfile)
|
||||
bool InputIsoFile::Test(std::string srcfile)
|
||||
{
|
||||
Close();
|
||||
m_filename = srcfile;
|
||||
|
||||
return Open(srcfile, true);
|
||||
return Open(std::move(srcfile), true);
|
||||
}
|
||||
|
||||
bool InputIsoFile::Open(const wxString& srcfile, bool testOnly)
|
||||
bool InputIsoFile::Open(std::string srcfile, bool testOnly)
|
||||
{
|
||||
Close();
|
||||
m_filename = srcfile;
|
||||
m_reader = NULL;
|
||||
m_filename = std::move(srcfile);
|
||||
|
||||
bool isBlockdump = false;
|
||||
bool isCompressed = false;
|
||||
@@ -224,7 +221,8 @@ bool InputIsoFile::Open(const wxString& srcfile, bool testOnly)
|
||||
m_reader = new FlatFileReader(EmuConfig.CdvdShareWrite);
|
||||
}
|
||||
|
||||
m_reader->Open(m_filename);
|
||||
if (!m_reader->Open(m_filename))
|
||||
return false;
|
||||
|
||||
// It might actually be a blockdump file.
|
||||
// Check that before continuing with the FlatFileReader.
|
||||
@@ -270,7 +268,7 @@ bool InputIsoFile::Open(const wxString& srcfile, bool testOnly)
|
||||
|
||||
m_blocks = m_reader->GetBlockCount();
|
||||
|
||||
Console.WriteLn(Color_StrongBlue, L"isoFile open ok: %s", WX_STR(m_filename));
|
||||
Console.WriteLn(Color_StrongBlue, "isoFile open ok: %s", m_filename.c_str());
|
||||
|
||||
ConsoleIndentScope indent;
|
||||
|
||||
|
||||
@@ -16,10 +16,10 @@
|
||||
#pragma once
|
||||
|
||||
#include "CDVD.h"
|
||||
#include "wx/wfstream.h"
|
||||
#include "AsyncFileReader.h"
|
||||
#include "CompressedFileReader.h"
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
enum isoType
|
||||
{
|
||||
@@ -45,7 +45,7 @@ protected:
|
||||
uint ReadUnit;
|
||||
|
||||
protected:
|
||||
wxString m_filename;
|
||||
std::string m_filename;
|
||||
AsyncFileReader* m_reader;
|
||||
|
||||
u32 m_current_lsn;
|
||||
@@ -75,13 +75,13 @@ public:
|
||||
uint GetBlockCount() const { return m_blocks; }
|
||||
int GetBlockOffset() const { return m_blockofs; }
|
||||
|
||||
const wxString& GetFilename() const
|
||||
const std::string& GetFilename() const
|
||||
{
|
||||
return m_filename;
|
||||
}
|
||||
|
||||
bool Test(const wxString& srcfile);
|
||||
bool Open(const wxString& srcfile, bool testOnly = false);
|
||||
bool Test(std::string srcfile);
|
||||
bool Open(std::string srcfile, bool testOnly = false);
|
||||
void Close();
|
||||
bool Detect(bool readType = true);
|
||||
|
||||
@@ -102,7 +102,7 @@ class OutputIsoFile
|
||||
DeclareNoncopyableObject(OutputIsoFile);
|
||||
|
||||
protected:
|
||||
wxString m_filename;
|
||||
std::string m_filename;
|
||||
|
||||
u32 m_version;
|
||||
|
||||
@@ -116,7 +116,7 @@ protected:
|
||||
// dtable is used when reading blockdumps
|
||||
std::vector<u32> m_dtable;
|
||||
|
||||
std::unique_ptr<wxFileOutputStream> m_outstream;
|
||||
std::FILE* m_outstream = nullptr;
|
||||
|
||||
public:
|
||||
OutputIsoFile();
|
||||
@@ -125,12 +125,12 @@ public:
|
||||
bool IsOpened() const;
|
||||
u32 GetBlockSize() const;
|
||||
|
||||
const wxString& GetFilename() const
|
||||
const std::string& GetFilename() const
|
||||
{
|
||||
return m_filename;
|
||||
}
|
||||
|
||||
void Create(const wxString& filename, int mode);
|
||||
void Create(std::string filename, int mode);
|
||||
void Close();
|
||||
|
||||
void WriteHeader(int blockofs, uint blocksize, uint blocks);
|
||||
|
||||
@@ -17,15 +17,17 @@
|
||||
#include "PrecompiledHeader.h"
|
||||
#include "IopCommon.h"
|
||||
#include "IsoFileFormats.h"
|
||||
#include "common/FileSystem.h"
|
||||
#include "common/StringUtil.h"
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
void pxStream_OpenCheck(const wxStreamBase& stream, const wxString& fname, const wxString& mode)
|
||||
void pxStream_OpenCheck(std::FILE* stream, const std::string& fname, const wxString& mode)
|
||||
{
|
||||
if (stream.IsOk())
|
||||
if (stream)
|
||||
return;
|
||||
|
||||
ScopedExcept ex(Exception::FromErrno(fname, errno));
|
||||
ScopedExcept ex(Exception::FromErrno(StringUtil::UTF8StringToWxString(fname), errno));
|
||||
ex->SetDiagMsg(pxsFmt(L"Unable to open the file for %s: %s", WX_STR(mode), WX_STR(ex->DiagMsg())));
|
||||
ex->Rethrow();
|
||||
}
|
||||
@@ -50,20 +52,20 @@ void OutputIsoFile::_init()
|
||||
m_blocks = 0;
|
||||
}
|
||||
|
||||
void OutputIsoFile::Create(const wxString& filename, int version)
|
||||
void OutputIsoFile::Create(std::string filename, int version)
|
||||
{
|
||||
Close();
|
||||
m_filename = filename;
|
||||
m_filename = std::move(filename);
|
||||
|
||||
m_version = version;
|
||||
m_offset = 0;
|
||||
m_blockofs = 24;
|
||||
m_blocksize = 2048;
|
||||
|
||||
m_outstream = std::make_unique<wxFileOutputStream>(m_filename);
|
||||
pxStream_OpenCheck(*m_outstream, m_filename, L"writing");
|
||||
m_outstream = FileSystem::OpenCFile(m_filename.c_str(), "wb");
|
||||
pxStream_OpenCheck(m_outstream, m_filename, L"writing");
|
||||
|
||||
Console.WriteLn("isoFile create ok: %s ", WX_STR(m_filename));
|
||||
Console.WriteLn("isoFile create ok: %s ", m_filename.c_str());
|
||||
}
|
||||
|
||||
// Generates format header information for blockdumps.
|
||||
@@ -100,9 +102,8 @@ void OutputIsoFile::WriteSector(const u8* src, uint lsn)
|
||||
}
|
||||
else
|
||||
{
|
||||
wxFileOffset ofs = (wxFileOffset)lsn * m_blocksize + m_offset;
|
||||
|
||||
m_outstream->SeekO(ofs);
|
||||
const s64 ofs = (s64)lsn * m_blocksize + m_offset;
|
||||
FileSystem::FSeek64(m_outstream, ofs, SEEK_SET);
|
||||
}
|
||||
|
||||
WriteBuffer(src + m_blockofs, m_blocksize);
|
||||
@@ -112,19 +113,27 @@ void OutputIsoFile::Close()
|
||||
{
|
||||
m_dtable.clear();
|
||||
|
||||
if (m_outstream)
|
||||
{
|
||||
std::fclose(m_outstream);
|
||||
m_outstream = nullptr;
|
||||
}
|
||||
|
||||
_init();
|
||||
}
|
||||
|
||||
void OutputIsoFile::WriteBuffer(const void* src, size_t size)
|
||||
{
|
||||
m_outstream->Write(src, size);
|
||||
if (m_outstream->GetLastError() == wxSTREAM_WRITE_ERROR)
|
||||
if (std::fwrite(src, size, 1, m_outstream) != 1)
|
||||
{
|
||||
int err = errno;
|
||||
if (!err)
|
||||
throw Exception::BadStream(m_filename).SetDiagMsg(pxsFmt(L"An error occurred while writing %u bytes to file", size));
|
||||
{
|
||||
throw Exception::BadStream(StringUtil::UTF8StringToWxString(m_filename))
|
||||
.SetDiagMsg(pxsFmt(L"An error occurred while writing %u bytes to file", size));
|
||||
}
|
||||
|
||||
ScopedExcept ex(Exception::FromErrno(m_filename, err));
|
||||
ScopedExcept ex(Exception::FromErrno(StringUtil::UTF8StringToWxString(m_filename), err));
|
||||
ex->SetDiagMsg(pxsFmt(L"An error occurred while writing %u bytes to file: %s", size, WX_STR(ex->DiagMsg())));
|
||||
ex->Rethrow();
|
||||
}
|
||||
@@ -132,7 +141,7 @@ void OutputIsoFile::WriteBuffer(const void* src, size_t size)
|
||||
|
||||
bool OutputIsoFile::IsOpened() const
|
||||
{
|
||||
return m_outstream && m_outstream->IsOk();
|
||||
return m_outstream != nullptr;
|
||||
}
|
||||
|
||||
u32 OutputIsoFile::GetBlockSize() const
|
||||
|
||||
@@ -239,10 +239,10 @@ bool ThreadedFileReader::TryCachedRead(void*& buffer, u64& offset, u32& size, co
|
||||
return allDone;
|
||||
}
|
||||
|
||||
bool ThreadedFileReader::Open(const wxString& fileName)
|
||||
bool ThreadedFileReader::Open(std::string fileName)
|
||||
{
|
||||
CancelAndWaitUntilStopped();
|
||||
return Open2(fileName);
|
||||
return Open2(std::move(fileName));
|
||||
}
|
||||
|
||||
int ThreadedFileReader::ReadSync(void* pBuffer, uint sector, uint count)
|
||||
|
||||
@@ -47,7 +47,7 @@ protected:
|
||||
/// Synchronously read the given block into `dst`
|
||||
virtual int ReadChunk(void* dst, s64 chunkID) = 0;
|
||||
/// AsyncFileReader open but ThreadedFileReader needs prep work first
|
||||
virtual bool Open2(const wxString& fileName) = 0;
|
||||
virtual bool Open2(std::string fileName) = 0;
|
||||
/// AsyncFileReader close but ThreadedFileReader needs prep work first
|
||||
virtual void Close2(void) = 0;
|
||||
|
||||
@@ -109,7 +109,7 @@ private:
|
||||
bool TryCachedRead(void*& buffer, u64& offset, u32& size, const std::lock_guard<std::mutex>&);
|
||||
|
||||
public:
|
||||
bool Open(const wxString& fileName) final override;
|
||||
bool Open(std::string fileName) final override;
|
||||
int ReadSync(void* pBuffer, uint sector, uint count) final override;
|
||||
void BeginRead(void* pBuffer, uint sector, uint count) final override;
|
||||
int FinishRead(void) final override;
|
||||
|
||||
+15
-15
@@ -107,7 +107,7 @@ Comments) 1950 to 1952 in the files http://tools.ietf.org/html/rfc1950
|
||||
#include <zlib/zlib.h>
|
||||
#endif
|
||||
|
||||
#include "CompressedFileReaderUtils.h"
|
||||
#include "common/FileSystem.h"
|
||||
|
||||
#define local static
|
||||
|
||||
@@ -122,8 +122,8 @@ Comments) 1950 to 1952 in the files http://tools.ietf.org/html/rfc1950
|
||||
/* access point entry */
|
||||
struct point
|
||||
{
|
||||
PX_off_t out; /* corresponding offset in uncompressed data */
|
||||
PX_off_t in; /* offset in input file of first full byte */
|
||||
s64 out; /* corresponding offset in uncompressed data */
|
||||
s64 in; /* offset in input file of first full byte */
|
||||
int bits; /* number of bits (1-7) from byte at in - 1, or 0 */
|
||||
unsigned char window[WINSIZE]; /* preceding 32K of uncompressed data */
|
||||
}
|
||||
@@ -142,7 +142,7 @@ struct access
|
||||
struct point* list; /* allocated list */
|
||||
|
||||
s32 span; /* once the index is built, holds the span size used to build it */
|
||||
PX_off_t uncompressed_size; /* filled by build_index */
|
||||
s64 uncompressed_size; /* filled by build_index */
|
||||
}
|
||||
#ifndef _WIN32
|
||||
__attribute__((packed))
|
||||
@@ -168,7 +168,7 @@ local void free_index(struct access* index)
|
||||
/* Add an entry to the access point list. If out of memory, deallocate the
|
||||
existing list and return NULL. */
|
||||
local struct access* addpoint(struct access* index, int bits,
|
||||
PX_off_t in, PX_off_t out, unsigned left, unsigned char* window)
|
||||
s64 in, s64 out, unsigned left, unsigned char* window)
|
||||
{
|
||||
struct point* next;
|
||||
|
||||
@@ -224,11 +224,11 @@ local struct access* addpoint(struct access* index, int bits,
|
||||
returns the number of access points on success (>= 1), Z_MEM_ERROR for out
|
||||
of memory, Z_DATA_ERROR for an error in the input file, or Z_ERRNO for a
|
||||
file read error. On success, *built points to the resulting index. */
|
||||
local int build_index(FILE* in, PX_off_t span, struct access** built)
|
||||
local int build_index(FILE* in, s64 span, struct access** built)
|
||||
{
|
||||
int ret;
|
||||
PX_off_t totin, totout, totPrinted; /* our own total counters to avoid 4GB limit */
|
||||
PX_off_t last; /* totout value of last access point */
|
||||
s64 totin, totout, totPrinted; /* our own total counters to avoid 4GB limit */
|
||||
s64 last; /* totout value of last access point */
|
||||
struct access* index; /* access points being generated */
|
||||
z_stream strm;
|
||||
unsigned char input[CHUNK];
|
||||
@@ -344,13 +344,13 @@ build_index_error:
|
||||
|
||||
typedef struct zstate
|
||||
{
|
||||
PX_off_t out_offset;
|
||||
PX_off_t in_offset;
|
||||
s64 out_offset;
|
||||
s64 in_offset;
|
||||
z_stream strm;
|
||||
int isValid;
|
||||
} Zstate;
|
||||
|
||||
static inline PX_off_t getInOffset(zstate* state)
|
||||
static inline s64 getInOffset(zstate* state)
|
||||
{
|
||||
return state->in_offset;
|
||||
}
|
||||
@@ -362,7 +362,7 @@ static inline PX_off_t getInOffset(zstate* state)
|
||||
should not return a data error unless the file was modified since the index
|
||||
was generated. extract() may also return Z_ERRNO if there is an error on
|
||||
reading or seeking the input file. */
|
||||
local int extract(FILE* in, struct access* index, PX_off_t offset,
|
||||
local int extract(FILE* in, struct access* index, s64 offset,
|
||||
unsigned char* buf, int len, zstate* state)
|
||||
{
|
||||
int ret, skip;
|
||||
@@ -386,7 +386,7 @@ local int extract(FILE* in, struct access* index, PX_off_t offset,
|
||||
if (state->isValid)
|
||||
{
|
||||
state->isValid = 0; // we took control over strm. revalidate when/if we give it back
|
||||
PX_fseeko(in, state->in_offset, SEEK_SET);
|
||||
FileSystem::FSeek64(in, state->in_offset, SEEK_SET);
|
||||
state->strm.avail_in = 0;
|
||||
offset = 0;
|
||||
skip = 1;
|
||||
@@ -408,7 +408,7 @@ local int extract(FILE* in, struct access* index, PX_off_t offset,
|
||||
ret = inflateInit2(&state->strm, -15); /* raw inflate */
|
||||
if (ret != Z_OK)
|
||||
return ret;
|
||||
ret = PX_fseeko(in, here->in - (here->bits ? 1 : 0), SEEK_SET);
|
||||
ret = FileSystem::FSeek64(in, here->in - (here->bits ? 1 : 0), SEEK_SET);
|
||||
if (ret == -1)
|
||||
goto extract_ret;
|
||||
if (here->bits)
|
||||
@@ -456,7 +456,7 @@ local int extract(FILE* in, struct access* index, PX_off_t offset,
|
||||
{
|
||||
if (state->strm.avail_in == 0)
|
||||
{
|
||||
state->in_offset = PX_ftello(in);
|
||||
state->in_offset = FileSystem::FTell64(in);
|
||||
state->strm.avail_in = fread(input, 1, CHUNK, in);
|
||||
if (ferror(in))
|
||||
{
|
||||
|
||||
+34
-74
@@ -70,10 +70,6 @@ if(TARGET SDL::SDL)
|
||||
target_link_libraries(PCSX2_FLAGS INTERFACE SDL::SDL)
|
||||
endif()
|
||||
|
||||
if(WAYLAND_CLIENT_FOUND)
|
||||
target_compile_definitions(PCSX2 PRIVATE WAYLAND_BUILD)
|
||||
endif()
|
||||
|
||||
if(WIN32)
|
||||
# Resources
|
||||
target_sources(PCSX2 PRIVATE
|
||||
@@ -130,7 +126,7 @@ set(pcsx2Sources
|
||||
IopIrq.cpp
|
||||
IopMem.cpp
|
||||
IopSio2.cpp
|
||||
IPC.cpp
|
||||
PINE.cpp
|
||||
Mdec.cpp
|
||||
Memory.cpp
|
||||
MemoryCardFile.cpp
|
||||
@@ -139,10 +135,10 @@ set(pcsx2Sources
|
||||
MTGS.cpp
|
||||
MTVU.cpp
|
||||
MultipartFileReader.cpp
|
||||
OutputIsoFile.cpp
|
||||
Patch.cpp
|
||||
Patch_Memory.cpp
|
||||
Pcsx2Config.cpp
|
||||
PerformanceMetrics.cpp
|
||||
PrecompiledHeader.cpp
|
||||
R3000A.cpp
|
||||
R3000AInterpreter.cpp
|
||||
@@ -195,6 +191,7 @@ set(pcsx2Headers
|
||||
Gif_Unit.h
|
||||
GS.h
|
||||
Hardware.h
|
||||
Host.h
|
||||
Hw.h
|
||||
IopBios.h
|
||||
IopCommon.h
|
||||
@@ -204,7 +201,7 @@ set(pcsx2Headers
|
||||
IopHw.h
|
||||
IopMem.h
|
||||
IopSio2.h
|
||||
IPC.h
|
||||
PINE.h
|
||||
Mdec.h
|
||||
MTVU.h
|
||||
Memory.h
|
||||
@@ -214,6 +211,7 @@ set(pcsx2Headers
|
||||
Patch.h
|
||||
PathDefs.h
|
||||
PCSX2Base.h
|
||||
PerformanceMetrics.h
|
||||
PrecompiledHeader.h
|
||||
R3000A.h
|
||||
R5900Exceptions.h
|
||||
@@ -268,7 +266,6 @@ set(pcsx2CDVDHeaders
|
||||
CDVD/CDVDisoReader.h
|
||||
CDVD/ChunksCache.h
|
||||
CDVD/CompressedFileReader.h
|
||||
CDVD/CompressedFileReaderUtils.h
|
||||
CDVD/ChdFileReader.h
|
||||
CDVD/CsoFileReader.h
|
||||
CDVD/GzippedFileReader.h
|
||||
@@ -531,18 +528,6 @@ else(WIN32)
|
||||
COMMAND ${BIN2CPP} "${PADImg}/${result_file}.png" "${PADImgHeader}/${result_file}" )
|
||||
endforeach()
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT ${CMAKE_BINARY_DIR}/pcsx2/PAD/Linux/resources_pad.h
|
||||
COMMAND glib-compile-resources --sourcedir "${CMAKE_SOURCE_DIR}/pcsx2/PAD/Linux/res" --generate-header
|
||||
--c-name PAD_res "${CMAKE_SOURCE_DIR}/pcsx2/PAD/Linux/res/PAD-res.xml" --target=${CMAKE_BINARY_DIR}/pcsx2/PAD/Linux/resources_pad.h
|
||||
DEPENDS ${CMAKE_SOURCE_DIR}/pcsx2/PAD/Linux/res/PAD-res.xml ${CMAKE_SOURCE_DIR}/pcsx2/PAD/Linux/res/game_controller_db.txt)
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT ${CMAKE_BINARY_DIR}/pcsx2/PAD/Linux/resources_pad.cpp
|
||||
COMMAND glib-compile-resources --sourcedir "${CMAKE_SOURCE_DIR}/pcsx2/PAD/Linux/res" --generate-source
|
||||
--c-name PAD_res "${CMAKE_SOURCE_DIR}/pcsx2/PAD/Linux/res/PAD-res.xml" --target=${CMAKE_BINARY_DIR}/pcsx2/PAD/Linux/resources_pad.cpp
|
||||
DEPENDS ${CMAKE_SOURCE_DIR}/pcsx2/PAD/Linux/res/PAD-res.xml ${CMAKE_SOURCE_DIR}/pcsx2/PAD/Linux/res/game_controller_db.txt)
|
||||
|
||||
# PAD/Linux sources
|
||||
set(pcsx2PADSources
|
||||
PAD/Linux/Device.cpp
|
||||
@@ -557,7 +542,6 @@ else(WIN32)
|
||||
PAD/Linux/wx_dialog/GamepadConfiguration.cpp
|
||||
PAD/Linux/wx_dialog/JoystickConfiguration.cpp
|
||||
PAD/Linux/Config.cpp
|
||||
${CMAKE_BINARY_DIR}/pcsx2/PAD/Linux/resources_pad.cpp
|
||||
)
|
||||
|
||||
# PAD/Linux headers
|
||||
@@ -575,7 +559,6 @@ else(WIN32)
|
||||
PAD/Linux/wx_dialog/opPanel.h
|
||||
PAD/Linux/wx_dialog/GamepadConfiguration.h
|
||||
PAD/Linux/wx_dialog/JoystickConfiguration.h
|
||||
${CMAKE_BINARY_DIR}/pcsx2/PAD/Linux/resources_pad.h
|
||||
# images
|
||||
${PADImgHeader}/analog.h
|
||||
${PADImgHeader}/circle.h
|
||||
@@ -651,7 +634,6 @@ set(pcsx2GSSources
|
||||
GS/Renderers/OpenGL/GSDeviceOGL.cpp
|
||||
GS/Renderers/OpenGL/GSRendererOGL.cpp
|
||||
GS/Renderers/OpenGL/GSShaderOGL.cpp
|
||||
GS/Renderers/OpenGL/GSTextureCacheOGL.cpp
|
||||
GS/Renderers/OpenGL/GSTextureOGL.cpp
|
||||
GS/Window/GSSetting.cpp
|
||||
GS/Window/GSwxDialog.cpp
|
||||
@@ -722,7 +704,6 @@ set(pcsx2GSHeaders
|
||||
GS/Renderers/OpenGL/GSDeviceOGL.h
|
||||
GS/Renderers/OpenGL/GSRendererOGL.h
|
||||
GS/Renderers/OpenGL/GSShaderOGL.h
|
||||
GS/Renderers/OpenGL/GSTextureCacheOGL.h
|
||||
GS/Renderers/OpenGL/GSTextureOGL.h
|
||||
GS/Renderers/OpenGL/GSUniformBufferOGL.h
|
||||
GS/Window/GSCaptureDlg.h
|
||||
@@ -797,7 +778,6 @@ if(WIN32)
|
||||
GS/Renderers/DX11/GSDevice11.cpp
|
||||
GS/Renderers/DX11/GSRendererDX11.cpp
|
||||
GS/Renderers/DX11/GSTexture11.cpp
|
||||
GS/Renderers/DX11/GSTextureCache11.cpp
|
||||
GS/Renderers/DX11/GSTextureFX11.cpp
|
||||
GS/Window/GSCaptureDlg.cpp
|
||||
GS/Window/GSDialog.cpp
|
||||
@@ -807,7 +787,6 @@ if(WIN32)
|
||||
GS/Renderers/DX11/GSDevice11.h
|
||||
GS/Renderers/DX11/GSRendererDX11.h
|
||||
GS/Renderers/DX11/GSTexture11.h
|
||||
GS/Renderers/DX11/GSTextureCache11.h
|
||||
)
|
||||
else(WIN32)
|
||||
list(APPEND pcsx2SPU2Sources
|
||||
@@ -862,42 +841,6 @@ else(WIN32)
|
||||
USB/usb-pad/evdev/evdev.h
|
||||
USB/usb-pad/evdev/shared.h
|
||||
)
|
||||
|
||||
|
||||
# GS resources
|
||||
set(pcsx2GSResources
|
||||
GS/res/fxaa.fx
|
||||
GS/res/glsl/common_header.glsl
|
||||
GS/res/glsl/convert.glsl
|
||||
GS/res/glsl/interlace.glsl
|
||||
GS/res/glsl/merge.glsl
|
||||
GS/res/glsl/shadeboost.glsl
|
||||
GS/res/glsl/tfx_fs.glsl
|
||||
GS/res/glsl/tfx_vgs.glsl)
|
||||
|
||||
set(GSBin "${CMAKE_BINARY_DIR}/pcsx2/GS")
|
||||
target_include_directories(PCSX2_FLAGS INTERFACE "${GSBin}")
|
||||
file(MAKE_DIRECTORY "${GSBin}")
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT ${CMAKE_BINARY_DIR}/pcsx2/GS/GS_res.h
|
||||
COMMAND glib-compile-resources --sourcedir "${CMAKE_SOURCE_DIR}/pcsx2/GS/res" --generate-header
|
||||
--c-name GS_res "${CMAKE_SOURCE_DIR}/pcsx2/GS/res/GS-res.xml" --target=${CMAKE_BINARY_DIR}/pcsx2/GS/GS_res.h
|
||||
DEPENDS ${pcsx2GSResources})
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT ${CMAKE_BINARY_DIR}/pcsx2/GS/GS_res.cpp
|
||||
COMMAND glib-compile-resources --sourcedir "${CMAKE_SOURCE_DIR}/pcsx2/GS/res" --generate-source
|
||||
--c-name GS_res "${CMAKE_SOURCE_DIR}/pcsx2/GS/res/GS-res.xml" --target=${CMAKE_BINARY_DIR}/pcsx2/GS/GS_res.cpp
|
||||
DEPENDS ${pcsx2GSResources})
|
||||
|
||||
list(APPEND pcsx2GSSources
|
||||
GS/GS_res.cpp
|
||||
)
|
||||
|
||||
list(APPEND pcsx2GSHeaders
|
||||
GS/GS_res.h
|
||||
)
|
||||
endif(WIN32)
|
||||
|
||||
|
||||
@@ -941,14 +884,13 @@ set(pcsx2GuiSources
|
||||
gui/AppConfig.cpp
|
||||
gui/AppCoreThread.cpp
|
||||
gui/AppEventSources.cpp
|
||||
gui/AppGameDatabase.cpp
|
||||
gui/AppHost.cpp
|
||||
gui/AppUserMode.cpp
|
||||
gui/AppInit.cpp
|
||||
gui/AppMain.cpp
|
||||
gui/AppRes.cpp
|
||||
gui/CheckedStaticBox.cpp
|
||||
gui/ConsoleLogger.cpp
|
||||
gui/CpuUsageProvider.cpp
|
||||
gui/Dialogs/AboutBoxDialog.cpp
|
||||
gui/Dialogs/GSDumpDialog.cpp
|
||||
gui/Dialogs/AssertionDialog.cpp
|
||||
@@ -962,7 +904,7 @@ set(pcsx2GuiSources
|
||||
gui/Dialogs/McdConfigDialog.cpp
|
||||
gui/Dialogs/PickUserModeDialog.cpp
|
||||
gui/Dialogs/SysConfigDialog.cpp
|
||||
gui/Dialogs/IPCDialog.cpp
|
||||
gui/Dialogs/PINEDialog.cpp
|
||||
gui/Debugger/BreakpointWindow.cpp
|
||||
gui/Debugger/CtrlDisassemblyView.cpp
|
||||
gui/Debugger/CtrlRegisterList.cpp
|
||||
@@ -1017,13 +959,11 @@ set(pcsx2GuiHeaders
|
||||
gui/AppCoreThread.h
|
||||
gui/AppEventListeners.h
|
||||
gui/AppForwardDefs.h
|
||||
gui/AppGameDatabase.h
|
||||
gui/App.h
|
||||
gui/ApplyState.h
|
||||
gui/AppSaveStates.h
|
||||
gui/CheckedStaticBox.h
|
||||
gui/ConsoleLogger.h
|
||||
gui/CpuUsageProvider.h
|
||||
gui/Debugger/BreakpointWindow.h
|
||||
gui/Debugger/CtrlDisassemblyView.h
|
||||
gui/Debugger/CtrlMemView.h
|
||||
@@ -1400,7 +1340,7 @@ if(UNIX AND NOT APPLE)
|
||||
endif()
|
||||
if(WAYLAND_API)
|
||||
target_link_libraries(PCSX2_FLAGS INTERFACE
|
||||
${WAYLAND_CLIENT_LIBRARIES}
|
||||
Wayland::Client
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
@@ -1470,7 +1410,6 @@ if(WIN32)
|
||||
)
|
||||
elseif(APPLE)
|
||||
target_link_libraries(PCSX2_FLAGS INTERFACE
|
||||
PkgConfig::GIO
|
||||
PCAP::PCAP
|
||||
LibXml2::LibXml2
|
||||
)
|
||||
@@ -1525,6 +1464,31 @@ if(COMMAND target_precompile_headers)
|
||||
target_precompile_headers(PCSX2_FLAGS INTERFACE PrecompiledHeader.h)
|
||||
endif()
|
||||
|
||||
# Copy resource files if needed
|
||||
function(pcsx2_resource path basedir)
|
||||
get_filename_component(dir ${path} DIRECTORY)
|
||||
file(RELATIVE_PATH subdir ${basedir} ${dir})
|
||||
if(APPLE)
|
||||
target_sources(PCSX2 PRIVATE ${path})
|
||||
set_source_files_properties(${path} PROPERTIES MACOSX_PACKAGE_LOCATION Resources/${subdir})
|
||||
elseif(PACKAGE_MODE)
|
||||
install(FILES ${path} DESTINATION ${CMAKE_INSTALL_DATADIR}/PCSX2/resources/${subdir})
|
||||
endif()
|
||||
source_group(Resources/${subdir} FILES ${path})
|
||||
endfunction()
|
||||
|
||||
file(GLOB_RECURSE RESOURCE_FILES ${CMAKE_SOURCE_DIR}/bin/resources/*)
|
||||
foreach(path IN LISTS RESOURCE_FILES)
|
||||
get_filename_component(file ${path} NAME)
|
||||
if("${file}" MATCHES "^\\.") # Don't copy macOS garbage (mainly Finder's .DS_Store files) into application
|
||||
continue()
|
||||
endif()
|
||||
if (NOT WIN32 AND "${path}" MATCHES "/dx11/") # Don't include unneccessary stuff
|
||||
continue()
|
||||
endif()
|
||||
pcsx2_resource(${path} ${CMAKE_SOURCE_DIR}/bin/resources/)
|
||||
endforeach()
|
||||
|
||||
if (APPLE)
|
||||
# MacOS defaults to having a maximum protection of the __DATA segment of rw (non-executable)
|
||||
# We have a bunch of page-sized arrays in bss that we use for jit
|
||||
@@ -1537,10 +1501,7 @@ if (APPLE)
|
||||
OUTPUT_NAME PCSX2
|
||||
)
|
||||
|
||||
target_sources(PCSX2 PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/gui/Resources/PCSX2.icns")
|
||||
target_sources(PCSX2 PRIVATE "${CMAKE_SOURCE_DIR}/bin/GameIndex.yaml")
|
||||
set_source_files_properties("${CMAKE_CURRENT_SOURCE_DIR}/gui/Resources/PCSX2.icns" PROPERTIES MACOSX_PACKAGE_LOCATION Resources)
|
||||
set_source_files_properties("${CMAKE_SOURCE_DIR}/bin/GameIndex.yaml" PROPERTIES MACOSX_PACKAGE_LOCATION Resources)
|
||||
pcsx2_resource(${CMAKE_CURRENT_SOURCE_DIR}/gui/Resources/PCSX2.icns ${CMAKE_CURRENT_SOURCE_DIR}/gui/Resources)
|
||||
|
||||
# If they say to skip postprocess bundle, leave the target in but make it so they have
|
||||
# to manually run it
|
||||
@@ -1585,5 +1546,4 @@ source_group(System/Ps2/USB REGULAR_EXPRESSION USB/*)
|
||||
source_group(Resources/GUI FILES ${pcsx2GuiResources})
|
||||
source_group(Resources/PAD FILES ${pcsx2PADResources})
|
||||
source_group(Resources/Recording FILES ${pcsx2RecordingVirtualPadResources})
|
||||
source_group(Resources FILES ../bin/GameIndex.yaml gui/Resources/PCSX2.icns)
|
||||
source_group(Resources REGULAR_EXPRESSION ${CMAKE_CURRENT_BINARY_DIR}/*)
|
||||
|
||||
+4
-2
@@ -545,7 +545,7 @@ struct Pcsx2Config
|
||||
CdvdShareWrite : 1, // allows the iso to be modified while it's loaded
|
||||
EnablePatches : 1, // enables patch detection and application
|
||||
EnableCheats : 1, // enables cheat detection and application
|
||||
EnableIPC : 1, // enables inter-process communication
|
||||
EnablePINE : 1, // enables inter-process communication
|
||||
EnableWideScreenPatches : 1,
|
||||
#ifndef DISABLE_RECORDING
|
||||
EnableRecordingTools : 1,
|
||||
@@ -598,7 +598,7 @@ struct Pcsx2Config
|
||||
void LoadSaveMemcards(SettingsWrapper& wrap);
|
||||
|
||||
// TODO: Make these std::string when we remove wxFile...
|
||||
wxString FullpathToBios() const;
|
||||
std::string FullpathToBios() const;
|
||||
wxString FullpathToMcd(uint slot) const;
|
||||
|
||||
bool MultitapEnabled(uint port) const;
|
||||
@@ -627,6 +627,8 @@ namespace EmuFolders
|
||||
extern wxDirName Logs;
|
||||
extern wxDirName Cheats;
|
||||
extern wxDirName CheatsWS;
|
||||
extern wxDirName Resources;
|
||||
extern wxDirName Cache;
|
||||
} // namespace EmuFolders
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
|
||||
#include "GS.h"
|
||||
#include "VUmicro.h"
|
||||
#include "PerformanceMetrics.h"
|
||||
|
||||
#include "ps2/HwInternal.h"
|
||||
#include "Sio.h"
|
||||
@@ -400,6 +401,8 @@ u32 UpdateVSyncRate()
|
||||
cpuRcntSet();
|
||||
}
|
||||
|
||||
PerformanceMetrics::SetVerticalFrequency(vertical_frequency);
|
||||
|
||||
if (m_iTicks != ticks)
|
||||
m_iTicks = ticks;
|
||||
|
||||
|
||||
+21
-7
@@ -45,6 +45,7 @@ char errbuf[PCAP_ERRBUF_SIZE];
|
||||
|
||||
int pcap_io_running = 0;
|
||||
bool pcap_io_switched;
|
||||
bool pcap_io_blocking;
|
||||
|
||||
extern u8 eeprom[];
|
||||
|
||||
@@ -83,7 +84,7 @@ bool PCAPGetWin32Adapter(const char* name, PIP_ADAPTER_ADDRESSES adapter, std::u
|
||||
dwBufLen = sizeof(IP_ADAPTER_ADDRESSES) * neededSize;
|
||||
DevCon.WriteLn("DEV9: New size %i", neededSize);
|
||||
|
||||
DWORD dwStatus = GetAdaptersAddresses(
|
||||
dwStatus = GetAdaptersAddresses(
|
||||
AF_UNSPEC,
|
||||
GAA_FLAG_INCLUDE_PREFIX | GAA_FLAG_INCLUDE_GATEWAYS,
|
||||
NULL,
|
||||
@@ -219,6 +220,14 @@ int pcap_io_init(char* adapter, bool switched, mac_address virtual_mac)
|
||||
}
|
||||
}
|
||||
|
||||
if (pcap_setnonblock(adhandle, 1, errbuf) == -1)
|
||||
{
|
||||
Console.Error("DEV9: Error setting non-blocking: %s", pcap_geterr(adhandle));
|
||||
Console.Error("DEV9: Continuing in blocking mode");
|
||||
pcap_io_blocking = true;
|
||||
}
|
||||
else
|
||||
pcap_io_blocking = false;
|
||||
|
||||
dlt = pcap_datalink(adhandle);
|
||||
dlt_name = (char*)pcap_datalink_val_to_name(dlt);
|
||||
@@ -370,6 +379,12 @@ PCAPAdapter::PCAPAdapter()
|
||||
host_mac = hostMAC;
|
||||
ps2_mac = newMAC; //Needed outside of this class
|
||||
|
||||
if (pcap_io_init(config.Eth, config.EthApi == NetApi::PCAP_Switched, newMAC) == -1)
|
||||
{
|
||||
Console.Error("DEV9: Can't open Device '%s'", config.Eth);
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
IP_ADAPTER_ADDRESSES adapter;
|
||||
std::unique_ptr<IP_ADAPTER_ADDRESSES[]> buffer;
|
||||
@@ -394,15 +409,11 @@ PCAPAdapter::PCAPAdapter()
|
||||
InitInternalServer(nullptr);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (pcap_io_init(config.Eth, config.EthApi == NetApi::PCAP_Switched, newMAC) == -1)
|
||||
{
|
||||
Console.Error("Can't open Device '%s'\n", config.Eth);
|
||||
}
|
||||
}
|
||||
bool PCAPAdapter::blocks()
|
||||
{
|
||||
return true;
|
||||
pxAssert(pcap_io_running);
|
||||
return pcap_io_blocking;
|
||||
}
|
||||
bool PCAPAdapter::isInitialised()
|
||||
{
|
||||
@@ -411,6 +422,9 @@ bool PCAPAdapter::isInitialised()
|
||||
//gets a packet.rv :true success
|
||||
bool PCAPAdapter::recv(NetPacket* pkt)
|
||||
{
|
||||
if (!pcap_io_blocking && NetAdapter::recv(pkt))
|
||||
return true;
|
||||
|
||||
int size = pcap_io_recv(pkt->buffer, sizeof(pkt->buffer));
|
||||
if (size > 0 && VerifyPkt(pkt, size))
|
||||
{
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
|
||||
#include "PrecompiledHeader.h"
|
||||
#include "AsyncFileReader.h"
|
||||
#include "common/FileSystem.h"
|
||||
|
||||
// The aio module has been reported to cause issues with FreeBSD 10.3, so let's
|
||||
// disable it for 10.3 and earlier and hope FreeBSD 11 and onwards is fine.
|
||||
@@ -36,11 +37,11 @@ FlatFileReader::~FlatFileReader(void)
|
||||
Close();
|
||||
}
|
||||
|
||||
bool FlatFileReader::Open(const wxString& fileName)
|
||||
bool FlatFileReader::Open(std::string fileName)
|
||||
{
|
||||
m_filename = fileName;
|
||||
m_filename = std::move(fileName);
|
||||
|
||||
m_fd = wxOpen(fileName, O_RDONLY, 0);
|
||||
m_fd = FileSystem::OpenFDFile(m_filename.c_str(), O_RDONLY, 0);
|
||||
|
||||
return (m_fd != -1);
|
||||
}
|
||||
|
||||
+2
-1
@@ -15,6 +15,7 @@
|
||||
|
||||
#include "PrecompiledHeader.h"
|
||||
#include "Common.h"
|
||||
#include "common/FileSystem.h"
|
||||
|
||||
#include "GS.h" // for sending game crc to mtgs
|
||||
#include "Elfheader.h"
|
||||
@@ -152,7 +153,7 @@ void ElfObject::readIso(IsoFile& file)
|
||||
void ElfObject::readFile()
|
||||
{
|
||||
int rsize = 0;
|
||||
FILE *f = wxFopen( filename, "rb" );
|
||||
FILE *f = FileSystem::OpenCFile( filename.ToUTF8(), "rb" );
|
||||
if (f == NULL) throw Exception::FileNotFound( filename );
|
||||
|
||||
fseek(f, 0, SEEK_SET);
|
||||
|
||||
@@ -912,91 +912,6 @@ void fifo_free(void* ptr, size_t size, size_t repeat)
|
||||
|
||||
#endif
|
||||
|
||||
static void* s_hModule;
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
bool GSApp::LoadResource(int id, std::vector<char>& buff, const wchar_t* type)
|
||||
{
|
||||
buff.clear();
|
||||
HRSRC hRsrc = FindResource((HMODULE)s_hModule, MAKEINTRESOURCE(id), type != NULL ? type : (LPWSTR)RT_RCDATA);
|
||||
if (!hRsrc)
|
||||
return false;
|
||||
HGLOBAL hGlobal = ::LoadResource((HMODULE)s_hModule, hRsrc);
|
||||
if (!hGlobal)
|
||||
return false;
|
||||
DWORD size = SizeofResource((HMODULE)s_hModule, hRsrc);
|
||||
if (!size)
|
||||
return false;
|
||||
// On Linux resources are always NULL terminated
|
||||
// Add + 1 on size to do the same for compatibility sake (required by GSDeviceOGL)
|
||||
buff.resize(size + 1);
|
||||
memcpy(buff.data(), LockResource(hGlobal), size);
|
||||
return true;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#include "GS_res.h"
|
||||
|
||||
bool GSApp::LoadResource(int id, std::vector<char>& buff, const char* type)
|
||||
{
|
||||
std::string path;
|
||||
switch (id)
|
||||
{
|
||||
case IDR_COMMON_GLSL:
|
||||
path = "/GS/res/glsl/common_header.glsl";
|
||||
break;
|
||||
case IDR_CONVERT_GLSL:
|
||||
path = "/GS/res/glsl/convert.glsl";
|
||||
break;
|
||||
case IDR_FXAA_FX:
|
||||
path = "/GS/res/fxaa.fx";
|
||||
break;
|
||||
case IDR_INTERLACE_GLSL:
|
||||
path = "/GS/res/glsl/interlace.glsl";
|
||||
break;
|
||||
case IDR_MERGE_GLSL:
|
||||
path = "/GS/res/glsl/merge.glsl";
|
||||
break;
|
||||
case IDR_SHADEBOOST_GLSL:
|
||||
path = "/GS/res/glsl/shadeboost.glsl";
|
||||
break;
|
||||
case IDR_TFX_VGS_GLSL:
|
||||
path = "/GS/res/glsl/tfx_vgs.glsl";
|
||||
break;
|
||||
case IDR_TFX_FS_GLSL:
|
||||
path = "/GS/res/glsl/tfx_fs.glsl";
|
||||
break;
|
||||
case IDR_FONT_ROBOTO:
|
||||
path = "/GS/res/fonts-roboto/Roboto-Regular.ttf";
|
||||
break;
|
||||
default:
|
||||
printf("LoadResource not implemented for id %d\n", id);
|
||||
return false;
|
||||
}
|
||||
|
||||
GBytes* bytes = g_resource_lookup_data(GS_res_get_resource(), path.c_str(), G_RESOURCE_LOOKUP_FLAGS_NONE, nullptr);
|
||||
|
||||
size_t size = 0;
|
||||
const void* data = g_bytes_get_data(bytes, &size);
|
||||
|
||||
if (data == nullptr || size == 0)
|
||||
{
|
||||
printf("Failed to get data for resource: %d\n", id);
|
||||
return false;
|
||||
}
|
||||
|
||||
buff.clear();
|
||||
buff.resize(size + 1);
|
||||
memcpy(buff.data(), data, size + 1);
|
||||
|
||||
g_bytes_unref(bytes);
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
size_t GSApp::GetIniString(const char* lpAppName, const char* lpKeyName, const char* lpDefault, char* lpReturnedString, size_t nSize, const char* lpFileName)
|
||||
{
|
||||
BuildConfigurationMap(lpFileName);
|
||||
@@ -1219,7 +1134,6 @@ void GSApp::Init()
|
||||
m_default_configuration["extrathreads"] = "2";
|
||||
m_default_configuration["extrathreads_height"] = "4";
|
||||
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";
|
||||
m_default_configuration["conservative_framebuffer"] = "1";
|
||||
@@ -1361,11 +1275,6 @@ void GSApp::BuildConfigurationMap(const char* lpFileName)
|
||||
}
|
||||
}
|
||||
|
||||
void* GSApp::GetModuleHandlePtr()
|
||||
{
|
||||
return s_hModule;
|
||||
}
|
||||
|
||||
void GSApp::SetConfigDir()
|
||||
{
|
||||
// we need to initialize the ini folder later at runtime than at theApp init, as
|
||||
|
||||
@@ -149,14 +149,6 @@ public:
|
||||
GSApp();
|
||||
|
||||
void Init();
|
||||
void* GetModuleHandlePtr();
|
||||
|
||||
#ifdef _WIN32
|
||||
HMODULE GetModuleHandle()
|
||||
{
|
||||
return (HMODULE)GetModuleHandlePtr();
|
||||
}
|
||||
#endif
|
||||
|
||||
void BuildConfigurationMap(const char* lpFileName);
|
||||
void ReloadConfig();
|
||||
@@ -165,12 +157,6 @@ public:
|
||||
bool WriteIniString(const char* lpAppName, const char* lpKeyName, const char* pString, const char* lpFileName);
|
||||
int GetIniInt(const char* lpAppName, const char* lpKeyName, int nDefault, const char* lpFileName);
|
||||
|
||||
#ifdef _WIN32
|
||||
bool LoadResource(int id, std::vector<char>& buff, const wchar_t* type = nullptr);
|
||||
#else
|
||||
bool LoadResource(int id, std::vector<char>& buff, const char* type = nullptr);
|
||||
#endif
|
||||
|
||||
void SetConfig(const char* entry, const char* value);
|
||||
void SetConfig(const char* entry, int value);
|
||||
// Avoid issue with overloading
|
||||
|
||||
@@ -44,54 +44,9 @@ BEGIN
|
||||
"\0"
|
||||
END
|
||||
|
||||
3 TEXTINCLUDE
|
||||
BEGIN
|
||||
"#include ""res/tfx.fx""\r\n"
|
||||
"#include ""res/convert.fx""\r\n"
|
||||
"#include ""res/interlace.fx""\r\n"
|
||||
"#include ""res/merge.fx""\r\n"
|
||||
"#include ""res/fxaa.fx""\r\n"
|
||||
"#include ""res/shadeboost.fx""\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// RCDATA
|
||||
//
|
||||
|
||||
IDR_TFX_FX RCDATA "res\\tfx.fx"
|
||||
|
||||
IDR_CONVERT_FX RCDATA "res\\convert.fx"
|
||||
|
||||
IDR_INTERLACE_FX RCDATA "res\\interlace.fx"
|
||||
|
||||
IDR_MERGE_FX RCDATA "res\\merge.fx"
|
||||
|
||||
IDR_FXAA_FX RCDATA "res\\fxaa.fx"
|
||||
|
||||
IDR_SHADEBOOST_FX RCDATA "res\\shadeboost.fx"
|
||||
|
||||
IDR_CONVERT_GLSL RCDATA "res\\glsl\\convert.glsl";
|
||||
|
||||
IDR_INTERLACE_GLSL RCDATA "res\\glsl\\interlace.glsl";
|
||||
|
||||
IDR_MERGE_GLSL RCDATA "res\\glsl\\merge.glsl";
|
||||
|
||||
IDR_SHADEBOOST_GLSL RCDATA "res\\glsl\\shadeboost.glsl";
|
||||
|
||||
IDR_COMMON_GLSL RCDATA "res\\glsl\\common_header.glsl";
|
||||
|
||||
IDR_TFX_VGS_GLSL RCDATA "res\\glsl\\tfx_vgs.glsl";
|
||||
|
||||
IDR_TFX_FS_GLSL RCDATA "res\\glsl\\tfx_fs.glsl";
|
||||
|
||||
IDR_FONT_ROBOTO RCDATA "res\\fonts-roboto\\Roboto-Regular.ttf";
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Dialog
|
||||
@@ -139,18 +94,4 @@ END
|
||||
|
||||
|
||||
|
||||
#ifndef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 3 resource.
|
||||
//
|
||||
#include "res/tfx.fx"
|
||||
#include "res/convert.fx"
|
||||
#include "res/interlace.fx"
|
||||
#include "res/merge.fx"
|
||||
#include "res/fxaa.fx"
|
||||
#include "res/shadeboost.fx"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#endif // not APSTUDIO_INVOKED
|
||||
// clang-format on
|
||||
|
||||
@@ -38,6 +38,12 @@ public:
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void operator delete(void* ptr, void* placement_ptr)
|
||||
{
|
||||
// Just here to satisfy compilers
|
||||
// Person who calls in-place placement new must handle error case
|
||||
}
|
||||
|
||||
void* operator new[](size_t size)
|
||||
{
|
||||
return _aligned_malloc(size, i);
|
||||
|
||||
+4
-3
@@ -148,16 +148,17 @@ bool GSClut::WriteTest(const GIFRegTEX0& TEX0, const GIFRegTEXCLUT& TEXCLUT)
|
||||
__assume(0);
|
||||
}
|
||||
|
||||
return m_write.IsDirty(TEX0, TEXCLUT);
|
||||
// CLUT only reloads if PSM is a valid index type, avoid unnecessary flushes
|
||||
return ((TEX0.PSM & 0x7) >= 3) && m_write.IsDirty(TEX0, TEXCLUT);
|
||||
}
|
||||
|
||||
void GSClut::Write(const GIFRegTEX0& TEX0, const GIFRegTEXCLUT& TEXCLUT)
|
||||
{
|
||||
m_write.TEX0 = TEX0;
|
||||
m_write.TEXCLUT = TEXCLUT;
|
||||
m_write.dirty = false;
|
||||
m_read.dirty = true;
|
||||
|
||||
m_write.dirty = false;
|
||||
|
||||
(this->*m_wc[TEX0.CSM][TEX0.CPSM][TEX0.PSM])(TEX0, TEXCLUT);
|
||||
}
|
||||
|
||||
|
||||
@@ -1733,7 +1733,7 @@ void GSLocalMemory::SaveBMP(const std::string& fn, u32 bp, u32 bw, u32 psm, int
|
||||
}
|
||||
}
|
||||
|
||||
GSTextureSW t(GSTexture::Offscreen, w, h);
|
||||
GSTextureSW t(GSTexture::Type::Offscreen, w, h);
|
||||
|
||||
if (t.Update(GSVector4i(0, 0, w, h), bits, pitch))
|
||||
{
|
||||
|
||||
+10
-8
@@ -64,18 +64,18 @@ public:
|
||||
template <typename T, typename... Args>
|
||||
T* make(Args&&... args)
|
||||
{
|
||||
void* ptr = alloc(sizeof(T), alignof(T));
|
||||
new (ptr) T(std::forward<Args>(args)...);
|
||||
return static_cast<T*>(ptr);
|
||||
std::unique_ptr<void, void(*)(void*)> ptr(alloc(sizeof(T), alignof(T)), GSRingHeap::free);
|
||||
new (ptr.get()) T(std::forward<Args>(args)...);
|
||||
return static_cast<T*>(ptr.release());
|
||||
}
|
||||
|
||||
/// Allocate and default-initialize `count` `T`s
|
||||
template <typename T>
|
||||
T* make_array(size_t count)
|
||||
{
|
||||
void* ptr = alloc(sizeof(T) * count, alignof(T));
|
||||
new (ptr) T[count]();
|
||||
return static_cast<T*>(ptr);
|
||||
std::unique_ptr<void, void(*)(void*)> ptr(alloc(sizeof(T) * count, alignof(T)), GSRingHeap::free);
|
||||
new (ptr.get()) T[count]();
|
||||
return static_cast<T*>(ptr.release());
|
||||
}
|
||||
|
||||
/// Free a pointer allocated with `alloc`
|
||||
@@ -207,17 +207,19 @@ public:
|
||||
SharedPtr<T> make_shared(Args&&... args)
|
||||
{
|
||||
using Header = typename SharedPtr<T>::AllocationHeader;
|
||||
size_t alloc_size = sizeof(T) + sizeof(Header);
|
||||
static constexpr size_t alloc_size = sizeof(T) + sizeof(Header);
|
||||
static_assert(alignof(Header) <= MIN_ALIGN, "Header alignment too high");
|
||||
static_assert(alloc_size <= UINT32_MAX, "Allocation overflow");
|
||||
|
||||
void* ptr = alloc_internal(sizeof(T), getAlignMask(alignof(T)), sizeof(Header));
|
||||
std::unique_ptr<void, void(*)(void*)> guard(ptr, [](void* p){ free_internal(p, alloc_size); });
|
||||
Header* header = static_cast<Header*>(ptr);
|
||||
assert(alloc_size <= UINT32_MAX && "Allocation overflow");
|
||||
header->size = static_cast<uint32_t>(alloc_size);
|
||||
header->refcnt.store(1, std::memory_order_relaxed);
|
||||
|
||||
T* tptr = reinterpret_cast<T*>(header + 1);
|
||||
new (tptr) T(std::forward<Args>(args)...);
|
||||
guard.release();
|
||||
return SharedPtr<T>(tptr);
|
||||
}
|
||||
|
||||
|
||||
@@ -2546,8 +2546,13 @@ __forceinline void GSState::VertexKick(u32 skip)
|
||||
__assume(0);
|
||||
}
|
||||
|
||||
if (auto_flush && PRIM->TME && (m_context->FRAME.Block() == m_context->TEX0.TBP0))
|
||||
FlushPrim();
|
||||
if (m_context->FRAME.FBMSK != 0xFFFFFFFF)
|
||||
{
|
||||
m_mem.m_clut.Invalidate(m_context->FRAME.Block());
|
||||
|
||||
if (auto_flush && PRIM->TME && (m_context->FRAME.Block() == m_context->TEX0.TBP0))
|
||||
FlushPrim();
|
||||
}
|
||||
}
|
||||
|
||||
void GSState::GetTextureMinMax(GSVector4i& r, const GIFRegTEX0& TEX0, const GIFRegCLAMP& CLAMP, bool linear)
|
||||
|
||||
@@ -18,6 +18,36 @@
|
||||
#include "GS/GSGL.h"
|
||||
#include "GS/GS.h"
|
||||
|
||||
const char* shaderName(ShaderConvert value)
|
||||
{
|
||||
switch (value)
|
||||
{
|
||||
case ShaderConvert::COPY: return "ps_copy";
|
||||
case ShaderConvert::RGBA8_TO_16_BITS: return "ps_convert_rgba8_16bits";
|
||||
case ShaderConvert::DATM_1: return "ps_datm1";
|
||||
case ShaderConvert::DATM_0: return "ps_datm0";
|
||||
case ShaderConvert::MOD_256: return "ps_mod256";
|
||||
case ShaderConvert::SCANLINE: return "ps_filter_scanlines";
|
||||
case ShaderConvert::DIAGONAL_FILTER: return "ps_filter_diagonal";
|
||||
case ShaderConvert::TRANSPARENCY_FILTER: return "ps_filter_transparency";
|
||||
case ShaderConvert::TRIANGULAR_FILTER: return "ps_filter_triangular";
|
||||
case ShaderConvert::COMPLEX_FILTER: return "ps_filter_complex";
|
||||
case ShaderConvert::FLOAT32_TO_32_BITS: return "ps_convert_float32_32bits";
|
||||
case ShaderConvert::FLOAT32_TO_RGBA8: return "ps_convert_float32_rgba8";
|
||||
case ShaderConvert::FLOAT16_TO_RGB5A1: return "ps_convert_float16_rgb5a1";
|
||||
case ShaderConvert::RGBA8_TO_FLOAT32: return "ps_convert_rgba8_float32";
|
||||
case ShaderConvert::RGBA8_TO_FLOAT24: return "ps_convert_rgba8_float24";
|
||||
case ShaderConvert::RGBA8_TO_FLOAT16: return "ps_convert_rgba8_float16";
|
||||
case ShaderConvert::RGB5A1_TO_FLOAT16: return "ps_convert_rgb5a1_float16";
|
||||
case ShaderConvert::RGBA_TO_8I: return "ps_convert_rgba_8i";
|
||||
case ShaderConvert::YUV: return "ps_yuv";
|
||||
case ShaderConvert::OSD: return "ps_osd";
|
||||
default:
|
||||
ASSERT(0);
|
||||
return "ShaderConvertUnknownShader";
|
||||
}
|
||||
}
|
||||
|
||||
GSDevice::GSDevice()
|
||||
: m_vsync(false)
|
||||
, m_rbswapped(false)
|
||||
@@ -36,9 +66,7 @@ GSDevice::GSDevice()
|
||||
|
||||
GSDevice::~GSDevice()
|
||||
{
|
||||
for (auto t : m_pool)
|
||||
delete t;
|
||||
|
||||
PurgePool();
|
||||
delete m_backbuffer;
|
||||
delete m_merge;
|
||||
delete m_weavebob;
|
||||
@@ -53,10 +81,7 @@ bool GSDevice::Create(const WindowInfo& wi)
|
||||
|
||||
bool GSDevice::Reset(int w, int h)
|
||||
{
|
||||
for (auto t : m_pool)
|
||||
delete t;
|
||||
|
||||
m_pool.clear();
|
||||
PurgePool();
|
||||
|
||||
delete m_backbuffer;
|
||||
delete m_merge;
|
||||
@@ -64,13 +89,13 @@ bool GSDevice::Reset(int w, int h)
|
||||
delete m_blend;
|
||||
delete m_target_tmp;
|
||||
|
||||
m_backbuffer = NULL;
|
||||
m_merge = NULL;
|
||||
m_weavebob = NULL;
|
||||
m_blend = NULL;
|
||||
m_target_tmp = NULL;
|
||||
m_backbuffer = nullptr;
|
||||
m_merge = nullptr;
|
||||
m_weavebob = nullptr;
|
||||
m_blend = nullptr;
|
||||
m_target_tmp = nullptr;
|
||||
|
||||
m_current = NULL; // current is special, points to other textures, no need to delete
|
||||
m_current = nullptr; // current is special, points to other textures, no need to delete
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -89,9 +114,9 @@ void GSDevice::Present(const GSVector4i& r, int shader)
|
||||
|
||||
if (m_current)
|
||||
{
|
||||
static int s_shader[5] = {ShaderConvert_COPY, ShaderConvert_SCANLINE,
|
||||
ShaderConvert_DIAGONAL_FILTER, ShaderConvert_TRIANGULAR_FILTER,
|
||||
ShaderConvert_COMPLEX_FILTER}; // FIXME
|
||||
static constexpr ShaderConvert s_shader[5] = {ShaderConvert::COPY, ShaderConvert::SCANLINE,
|
||||
ShaderConvert::DIAGONAL_FILTER, ShaderConvert::TRIANGULAR_FILTER,
|
||||
ShaderConvert::COMPLEX_FILTER}; // FIXME
|
||||
|
||||
Present(m_current, m_backbuffer, GSVector4(r), s_shader[shader]);
|
||||
RenderOsd(m_backbuffer);
|
||||
@@ -100,28 +125,53 @@ void GSDevice::Present(const GSVector4i& r, int shader)
|
||||
Flip();
|
||||
}
|
||||
|
||||
void GSDevice::Present(GSTexture* sTex, GSTexture* dTex, const GSVector4& dRect, int shader)
|
||||
void GSDevice::Present(GSTexture* sTex, GSTexture* dTex, const GSVector4& dRect, ShaderConvert shader)
|
||||
{
|
||||
StretchRect(sTex, dTex, dRect, shader, m_linear_present);
|
||||
}
|
||||
|
||||
GSTexture* GSDevice::FetchSurface(int type, int w, int h, int format)
|
||||
GSTexture* GSDevice::FetchSurface(GSTexture::Type type, int w, int h, GSTexture::Format format)
|
||||
{
|
||||
const GSVector2i size(w, h);
|
||||
|
||||
GSTexture* t = nullptr;
|
||||
|
||||
for (auto i = m_pool.begin(); i != m_pool.end(); ++i)
|
||||
{
|
||||
GSTexture* t = *i;
|
||||
t = *i;
|
||||
|
||||
assert(t);
|
||||
|
||||
if (t->GetType() == type && t->GetFormat() == format && t->GetSize() == size)
|
||||
{
|
||||
m_pool.erase(i);
|
||||
|
||||
return t;
|
||||
break;
|
||||
}
|
||||
|
||||
t = nullptr;
|
||||
}
|
||||
|
||||
return CreateSurface(type, w, h, format);
|
||||
if (!t)
|
||||
t = CreateSurface(type, w, h, format);
|
||||
|
||||
if (!t)
|
||||
throw std::bad_alloc();
|
||||
|
||||
t->Commit(); // Clear won't be done if the texture isn't committed.
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case GSTexture::Type::RenderTarget:
|
||||
ClearRenderTarget(t, 0);
|
||||
break;
|
||||
case GSTexture::Type::DepthStencil:
|
||||
ClearDepth(t);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
void GSDevice::PrintMemoryUsage()
|
||||
@@ -184,46 +234,67 @@ void GSDevice::AgePool()
|
||||
|
||||
void GSDevice::PurgePool()
|
||||
{
|
||||
// OOM emergency. Let's free this useless pool
|
||||
while (!m_pool.empty())
|
||||
{
|
||||
delete m_pool.back();
|
||||
|
||||
m_pool.pop_back();
|
||||
}
|
||||
for (auto t : m_pool)
|
||||
delete t;
|
||||
m_pool.clear();
|
||||
}
|
||||
|
||||
GSTexture* GSDevice::CreateSparseRenderTarget(int w, int h, int format)
|
||||
GSTexture* GSDevice::CreateSparseRenderTarget(int w, int h, GSTexture::Format format)
|
||||
{
|
||||
return FetchSurface(HasColorSparse() ? GSTexture::SparseRenderTarget : GSTexture::RenderTarget, w, h, format);
|
||||
return FetchSurface(HasColorSparse() ? GSTexture::Type::SparseRenderTarget : GSTexture::Type::RenderTarget, w, h, format);
|
||||
}
|
||||
|
||||
GSTexture* GSDevice::CreateSparseDepthStencil(int w, int h, int format)
|
||||
GSTexture* GSDevice::CreateSparseDepthStencil(int w, int h, GSTexture::Format format)
|
||||
{
|
||||
return FetchSurface(HasDepthSparse() ? GSTexture::SparseDepthStencil : GSTexture::DepthStencil, w, h, format);
|
||||
return FetchSurface(HasDepthSparse() ? GSTexture::Type::SparseDepthStencil : GSTexture::Type::DepthStencil, w, h, format);
|
||||
}
|
||||
|
||||
GSTexture* GSDevice::CreateRenderTarget(int w, int h, int format)
|
||||
GSTexture* GSDevice::CreateRenderTarget(int w, int h, GSTexture::Format format)
|
||||
{
|
||||
return FetchSurface(GSTexture::RenderTarget, w, h, format);
|
||||
return FetchSurface(GSTexture::Type::RenderTarget, w, h, format);
|
||||
}
|
||||
|
||||
GSTexture* GSDevice::CreateDepthStencil(int w, int h, int format)
|
||||
GSTexture* GSDevice::CreateDepthStencil(int w, int h, GSTexture::Format format)
|
||||
{
|
||||
return FetchSurface(GSTexture::DepthStencil, w, h, format);
|
||||
return FetchSurface(GSTexture::Type::DepthStencil, w, h, format);
|
||||
}
|
||||
|
||||
GSTexture* GSDevice::CreateTexture(int w, int h, int format)
|
||||
GSTexture* GSDevice::CreateTexture(int w, int h, GSTexture::Format format)
|
||||
{
|
||||
return FetchSurface(GSTexture::Texture, w, h, format);
|
||||
return FetchSurface(GSTexture::Type::Texture, w, h, format);
|
||||
}
|
||||
|
||||
GSTexture* GSDevice::CreateOffscreen(int w, int h, int format)
|
||||
GSTexture* GSDevice::CreateOffscreen(int w, int h, GSTexture::Format format)
|
||||
{
|
||||
return FetchSurface(GSTexture::Offscreen, w, h, format);
|
||||
return FetchSurface(GSTexture::Type::Offscreen, w, h, format);
|
||||
}
|
||||
|
||||
void GSDevice::StretchRect(GSTexture* sTex, GSTexture* dTex, const GSVector4& dRect, int shader, bool linear)
|
||||
GSTexture::Format GSDevice::GetDefaultTextureFormat(GSTexture::Type type)
|
||||
{
|
||||
if (type == GSTexture::Type::DepthStencil || type == GSTexture::Type::SparseDepthStencil)
|
||||
return GSTexture::Format::DepthStencil;
|
||||
else
|
||||
return GSTexture::Format::Color;
|
||||
}
|
||||
|
||||
bool GSDevice::DownloadTextureConvert(GSTexture* src, const GSVector4& sRect, const GSVector2i& dSize, GSTexture::Format format, ShaderConvert ps_shader, GSTexture::GSMap& out_map, const bool linear)
|
||||
{
|
||||
ASSERT(src);
|
||||
ASSERT(format == GSTexture::Format::Color || format == GSTexture::Format::UInt16 || format == GSTexture::Format::UInt32);
|
||||
|
||||
GSTexture* dst = CreateRenderTarget(dSize.x, dSize.y, format);
|
||||
if (!dst)
|
||||
return false;
|
||||
|
||||
GSVector4i dRect(0, 0, dSize.x, dSize.y);
|
||||
StretchRect(src, sRect, dst, GSVector4(dRect), ps_shader, linear);
|
||||
|
||||
bool ret = DownloadTexture(dst, dRect, out_map);
|
||||
Recycle(dst);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void GSDevice::StretchRect(GSTexture* sTex, GSTexture* dTex, const GSVector4& dRect, ShaderConvert shader, bool linear)
|
||||
{
|
||||
StretchRect(sTex, GSVector4(0, 0, 1, 1), dTex, dRect, shader, linear);
|
||||
}
|
||||
@@ -315,7 +386,7 @@ void GSDevice::ExternalFX()
|
||||
const GSVector4 sRect(0, 0, 1, 1);
|
||||
const GSVector4 dRect(0, 0, s.x, s.y);
|
||||
|
||||
StretchRect(m_current, sRect, m_target_tmp, dRect, ShaderConvert_TRANSPARENCY_FILTER, false);
|
||||
StretchRect(m_current, sRect, m_target_tmp, dRect, ShaderConvert::TRANSPARENCY_FILTER, false);
|
||||
DoExternalFX(m_target_tmp, m_current);
|
||||
}
|
||||
}
|
||||
@@ -329,7 +400,7 @@ void GSDevice::FXAA()
|
||||
const GSVector4 sRect(0, 0, 1, 1);
|
||||
const GSVector4 dRect(0, 0, s.x, s.y);
|
||||
|
||||
StretchRect(m_current, sRect, m_target_tmp, dRect, ShaderConvert_TRANSPARENCY_FILTER, false);
|
||||
StretchRect(m_current, sRect, m_target_tmp, dRect, ShaderConvert::TRANSPARENCY_FILTER, false);
|
||||
DoFXAA(m_target_tmp, m_current);
|
||||
}
|
||||
}
|
||||
@@ -343,12 +414,12 @@ void GSDevice::ShadeBoost()
|
||||
const GSVector4 sRect(0, 0, 1, 1);
|
||||
const GSVector4 dRect(0, 0, s.x, s.y);
|
||||
|
||||
StretchRect(m_current, sRect, m_target_tmp, dRect, ShaderConvert_COPY, false);
|
||||
StretchRect(m_current, sRect, m_target_tmp, dRect, ShaderConvert::COPY, false);
|
||||
DoShadeBoost(m_target_tmp, m_current);
|
||||
}
|
||||
}
|
||||
|
||||
bool GSDevice::ResizeTexture(GSTexture** t, int type, int w, int h)
|
||||
bool GSDevice::ResizeTexture(GSTexture** t, GSTexture::Type type, int w, int h)
|
||||
{
|
||||
if (t == NULL)
|
||||
{
|
||||
@@ -360,9 +431,10 @@ bool GSDevice::ResizeTexture(GSTexture** t, int type, int w, int h)
|
||||
|
||||
if (t2 == NULL || t2->GetWidth() != w || t2->GetHeight() != h)
|
||||
{
|
||||
GSTexture::Format fmt = t2 ? t2->GetFormat() : GetDefaultTextureFormat(type);
|
||||
delete t2;
|
||||
|
||||
t2 = FetchSurface(type, w, h, 0);
|
||||
t2 = FetchSurface(type, w, h, fmt);
|
||||
|
||||
*t = t2;
|
||||
}
|
||||
@@ -372,18 +444,18 @@ bool GSDevice::ResizeTexture(GSTexture** t, int type, int w, int h)
|
||||
|
||||
bool GSDevice::ResizeTexture(GSTexture** t, int w, int h)
|
||||
{
|
||||
return ResizeTexture(t, GSTexture::Texture, w, h);
|
||||
return ResizeTexture(t, GSTexture::Type::Texture, w, h);
|
||||
}
|
||||
|
||||
bool GSDevice::ResizeTarget(GSTexture** t, int w, int h)
|
||||
{
|
||||
return ResizeTexture(t, GSTexture::RenderTarget, w, h);
|
||||
return ResizeTexture(t, GSTexture::Type::RenderTarget, w, h);
|
||||
}
|
||||
|
||||
bool GSDevice::ResizeTarget(GSTexture** t)
|
||||
{
|
||||
GSVector2i s = m_current->GetSize();
|
||||
return ResizeTexture(t, GSTexture::RenderTarget, s.x, s.y);
|
||||
return ResizeTexture(t, GSTexture::Type::RenderTarget, s.x, s.y);
|
||||
}
|
||||
|
||||
GSAdapter::operator std::string() const
|
||||
@@ -438,15 +510,15 @@ std::array<HWBlend, 3*3*3*3 + 1> GSDevice::m_blendMap =
|
||||
{ BLEND_NO_REC , OP_ADD , CONST_ONE , CONST_ZERO} , // 0020: (Cs - Cs)*F + Cs ==> Cs
|
||||
{ 0 , OP_ADD , CONST_ZERO , CONST_ONE} , // 0021: (Cs - Cs)*F + Cd ==> Cd
|
||||
{ BLEND_NO_REC , OP_ADD , CONST_ZERO , CONST_ZERO} , // 0022: (Cs - Cs)*F + 0 ==> 0
|
||||
{ BLEND_A_MAX , OP_SUBTRACT , CONST_ONE , SRC1_ALPHA} , //*0100: (Cs - Cd)*As + Cs ==> Cs*(As + 1) - Cd*As
|
||||
{ 0 , OP_ADD , SRC1_ALPHA , INV_SRC1_ALPHA} , // 0101: (Cs - Cd)*As + Cd ==> Cs*As + Cd*(1 - As)
|
||||
{ 0 , OP_SUBTRACT , SRC1_ALPHA , SRC1_ALPHA} , // 0102: (Cs - Cd)*As + 0 ==> Cs*As - Cd*As
|
||||
{ BLEND_A_MAX | BLEND_MIX2 , OP_SUBTRACT , CONST_ONE , SRC1_ALPHA} , //*0100: (Cs - Cd)*As + Cs ==> Cs*(As + 1) - Cd*As
|
||||
{ BLEND_MIX1 , OP_ADD , SRC1_ALPHA , INV_SRC1_ALPHA} , // 0101: (Cs - Cd)*As + Cd ==> Cs*As + Cd*(1 - As)
|
||||
{ BLEND_MIX1 , OP_SUBTRACT , SRC1_ALPHA , SRC1_ALPHA} , // 0102: (Cs - Cd)*As + 0 ==> Cs*As - Cd*As
|
||||
{ BLEND_A_MAX , OP_SUBTRACT , CONST_ONE , DST_ALPHA} , //*0110: (Cs - Cd)*Ad + Cs ==> Cs*(Ad + 1) - Cd*Ad
|
||||
{ 0 , OP_ADD , DST_ALPHA , INV_DST_ALPHA} , // 0111: (Cs - Cd)*Ad + Cd ==> Cs*Ad + Cd*(1 - Ad)
|
||||
{ 0 , OP_SUBTRACT , DST_ALPHA , DST_ALPHA} , // 0112: (Cs - Cd)*Ad + 0 ==> Cs*Ad - Cd*Ad
|
||||
{ BLEND_A_MAX , OP_SUBTRACT , CONST_ONE , CONST_COLOR} , //*0120: (Cs - Cd)*F + Cs ==> Cs*(F + 1) - Cd*F
|
||||
{ 0 , OP_ADD , CONST_COLOR , INV_CONST_COLOR} , // 0121: (Cs - Cd)*F + Cd ==> Cs*F + Cd*(1 - F)
|
||||
{ 0 , OP_SUBTRACT , CONST_COLOR , CONST_COLOR} , // 0122: (Cs - Cd)*F + 0 ==> Cs*F - Cd*F
|
||||
{ BLEND_A_MAX | BLEND_MIX2 , OP_SUBTRACT , CONST_ONE , CONST_COLOR} , //*0120: (Cs - Cd)*F + Cs ==> Cs*(F + 1) - Cd*F
|
||||
{ BLEND_MIX1 , OP_ADD , CONST_COLOR , INV_CONST_COLOR} , // 0121: (Cs - Cd)*F + Cd ==> Cs*F + Cd*(1 - F)
|
||||
{ BLEND_MIX1 , OP_SUBTRACT , CONST_COLOR , CONST_COLOR} , // 0122: (Cs - Cd)*F + 0 ==> Cs*F - Cd*F
|
||||
{ BLEND_NO_REC | BLEND_A_MAX , OP_ADD , CONST_ONE , CONST_ZERO} , //*0200: (Cs - 0)*As + Cs ==> Cs*(As + 1)
|
||||
{ BLEND_ACCU , OP_ADD , SRC1_ALPHA , CONST_ONE} , //?0201: (Cs - 0)*As + Cd ==> Cs*As + Cd
|
||||
{ BLEND_NO_REC , OP_ADD , SRC1_ALPHA , CONST_ZERO} , // 0202: (Cs - 0)*As + 0 ==> Cs*As
|
||||
@@ -456,15 +528,15 @@ std::array<HWBlend, 3*3*3*3 + 1> GSDevice::m_blendMap =
|
||||
{ BLEND_NO_REC | BLEND_A_MAX , OP_ADD , CONST_ONE , CONST_ZERO} , //*0220: (Cs - 0)*F + Cs ==> Cs*(F + 1)
|
||||
{ BLEND_ACCU , OP_ADD , CONST_COLOR , CONST_ONE} , //?0221: (Cs - 0)*F + Cd ==> Cs*F + Cd
|
||||
{ BLEND_NO_REC , OP_ADD , CONST_COLOR , CONST_ZERO} , // 0222: (Cs - 0)*F + 0 ==> Cs*F
|
||||
{ 0 , OP_ADD , INV_SRC1_ALPHA , SRC1_ALPHA} , // 1000: (Cd - Cs)*As + Cs ==> Cd*As + Cs*(1 - As)
|
||||
{ BLEND_A_MAX , OP_REV_SUBTRACT , SRC1_ALPHA , CONST_ONE} , //*1001: (Cd - Cs)*As + Cd ==> Cd*(As + 1) - Cs*As
|
||||
{ 0 , OP_REV_SUBTRACT , SRC1_ALPHA , SRC1_ALPHA} , // 1002: (Cd - Cs)*As + 0 ==> Cd*As - Cs*As
|
||||
{ BLEND_MIX3 , OP_ADD , INV_SRC1_ALPHA , SRC1_ALPHA} , // 1000: (Cd - Cs)*As + Cs ==> Cd*As + Cs*(1 - As)
|
||||
{ BLEND_A_MAX | BLEND_MIX1 , OP_REV_SUBTRACT , SRC1_ALPHA , CONST_ONE} , //*1001: (Cd - Cs)*As + Cd ==> Cd*(As + 1) - Cs*As
|
||||
{ BLEND_MIX1 , OP_REV_SUBTRACT , SRC1_ALPHA , SRC1_ALPHA} , // 1002: (Cd - Cs)*As + 0 ==> Cd*As - Cs*As
|
||||
{ 0 , OP_ADD , INV_DST_ALPHA , DST_ALPHA} , // 1010: (Cd - Cs)*Ad + Cs ==> Cd*Ad + Cs*(1 - Ad)
|
||||
{ BLEND_A_MAX , OP_REV_SUBTRACT , DST_ALPHA , CONST_ONE} , //*1011: (Cd - Cs)*Ad + Cd ==> Cd*(Ad + 1) - Cs*Ad
|
||||
{ 0 , OP_REV_SUBTRACT , DST_ALPHA , DST_ALPHA} , // 1012: (Cd - Cs)*Ad + 0 ==> Cd*Ad - Cs*Ad
|
||||
{ 0 , OP_ADD , INV_CONST_COLOR , CONST_COLOR} , // 1020: (Cd - Cs)*F + Cs ==> Cd*F + Cs*(1 - F)
|
||||
{ BLEND_A_MAX , OP_REV_SUBTRACT , CONST_COLOR , CONST_ONE} , //*1021: (Cd - Cs)*F + Cd ==> Cd*(F + 1) - Cs*F
|
||||
{ 0 , OP_REV_SUBTRACT , CONST_COLOR , CONST_COLOR} , // 1022: (Cd - Cs)*F + 0 ==> Cd*F - Cs*F
|
||||
{ BLEND_MIX3 , OP_ADD , INV_CONST_COLOR , CONST_COLOR} , // 1020: (Cd - Cs)*F + Cs ==> Cd*F + Cs*(1 - F)
|
||||
{ BLEND_A_MAX | BLEND_MIX1 , OP_REV_SUBTRACT , CONST_COLOR , CONST_ONE} , //*1021: (Cd - Cs)*F + Cd ==> Cd*(F + 1) - Cs*F
|
||||
{ BLEND_MIX1 , OP_REV_SUBTRACT , CONST_COLOR , CONST_COLOR} , // 1022: (Cd - Cs)*F + 0 ==> Cd*F - Cs*F
|
||||
{ BLEND_NO_REC , OP_ADD , CONST_ONE , CONST_ZERO} , // 1100: (Cd - Cd)*As + Cs ==> Cs
|
||||
{ 0 , OP_ADD , CONST_ZERO , CONST_ONE} , // 1101: (Cd - Cd)*As + Cd ==> Cd
|
||||
{ BLEND_NO_REC , OP_ADD , CONST_ZERO , CONST_ZERO} , // 1102: (Cd - Cd)*As + 0 ==> 0
|
||||
|
||||
@@ -26,31 +26,35 @@
|
||||
#include <dxgi.h>
|
||||
#endif
|
||||
|
||||
enum ShaderConvert
|
||||
enum class ShaderConvert
|
||||
{
|
||||
ShaderConvert_COPY = 0,
|
||||
ShaderConvert_RGBA8_TO_16_BITS,
|
||||
ShaderConvert_DATM_1,
|
||||
ShaderConvert_DATM_0,
|
||||
ShaderConvert_MOD_256,
|
||||
ShaderConvert_SCANLINE = 5,
|
||||
ShaderConvert_DIAGONAL_FILTER,
|
||||
ShaderConvert_TRANSPARENCY_FILTER,
|
||||
ShaderConvert_TRIANGULAR_FILTER,
|
||||
ShaderConvert_COMPLEX_FILTER,
|
||||
ShaderConvert_FLOAT32_TO_32_BITS = 10,
|
||||
ShaderConvert_FLOAT32_TO_RGBA8,
|
||||
ShaderConvert_FLOAT16_TO_RGB5A1,
|
||||
ShaderConvert_RGBA8_TO_FLOAT32 = 13,
|
||||
ShaderConvert_RGBA8_TO_FLOAT24,
|
||||
ShaderConvert_RGBA8_TO_FLOAT16,
|
||||
ShaderConvert_RGB5A1_TO_FLOAT16,
|
||||
ShaderConvert_RGBA_TO_8I = 17,
|
||||
ShaderConvert_YUV,
|
||||
ShaderConvert_OSD,
|
||||
ShaderConvert_Count
|
||||
COPY = 0,
|
||||
RGBA8_TO_16_BITS,
|
||||
DATM_1,
|
||||
DATM_0,
|
||||
MOD_256,
|
||||
SCANLINE = 5,
|
||||
DIAGONAL_FILTER,
|
||||
TRANSPARENCY_FILTER,
|
||||
TRIANGULAR_FILTER,
|
||||
COMPLEX_FILTER,
|
||||
FLOAT32_TO_32_BITS = 10,
|
||||
FLOAT32_TO_RGBA8,
|
||||
FLOAT16_TO_RGB5A1,
|
||||
RGBA8_TO_FLOAT32 = 13,
|
||||
RGBA8_TO_FLOAT24,
|
||||
RGBA8_TO_FLOAT16,
|
||||
RGB5A1_TO_FLOAT16,
|
||||
RGBA_TO_8I = 17,
|
||||
YUV,
|
||||
OSD,
|
||||
Count
|
||||
};
|
||||
|
||||
/// Get the name of a shader
|
||||
/// (Can't put methods on an enum class)
|
||||
const char* shaderName(ShaderConvert value);
|
||||
|
||||
enum ChannelFetch
|
||||
{
|
||||
ChannelFetch_NONE = 0,
|
||||
@@ -115,6 +119,9 @@ public:
|
||||
enum HWBlendFlags
|
||||
{
|
||||
// A couple of flag to determine the blending behavior
|
||||
BLEND_MIX1 = 0x20, // Mix of hw and sw, do Cs*F or Cs*As in shader
|
||||
BLEND_MIX2 = 0x40, // Mix of hw and sw, do Cs*(As + 1) or Cs*(F + 1) in shader
|
||||
BLEND_MIX3 = 0x80, // Mix of hw and sw, do Cs*(1 - As) or Cs*(1 - F) in shader
|
||||
BLEND_A_MAX = 0x100, // Impossible blending uses coeff bigger than 1
|
||||
BLEND_C_CLR = 0x200, // Clear color blending (use directly the destination color as blending factor)
|
||||
BLEND_NO_REC = 0x400, // Doesn't require sampling of the RT as a texture
|
||||
@@ -168,8 +175,8 @@ protected:
|
||||
unsigned int m_frame; // for ageing the pool
|
||||
bool m_linear_present;
|
||||
|
||||
virtual GSTexture* CreateSurface(int type, int w, int h, int format) = 0;
|
||||
virtual GSTexture* FetchSurface(int type, int w, int h, int format);
|
||||
virtual GSTexture* CreateSurface(GSTexture::Type type, int w, int h, GSTexture::Format format) = 0;
|
||||
virtual GSTexture* FetchSurface(GSTexture::Type type, int w, int h, GSTexture::Format format);
|
||||
|
||||
virtual void DoMerge(GSTexture* sTex[3], GSVector4* sRect, GSTexture* dTex, GSVector4* dRect, const GSRegPMODE& PMODE, const GSRegEXTBUF& EXTBUF, const GSVector4& c) = 0;
|
||||
virtual void DoInterlace(GSTexture* sTex, GSTexture* dTex, int shader, bool linear, float yoffset) = 0;
|
||||
@@ -197,15 +204,12 @@ public:
|
||||
virtual bool Reset(int w, int h);
|
||||
virtual bool IsLost(bool update = false) { return false; }
|
||||
virtual void Present(const GSVector4i& r, int shader);
|
||||
virtual void Present(GSTexture* sTex, GSTexture* dTex, const GSVector4& dRect, int shader = 0);
|
||||
virtual void Present(GSTexture* sTex, GSTexture* dTex, const GSVector4& dRect, ShaderConvert shader = ShaderConvert::COPY);
|
||||
virtual void Flip() {}
|
||||
|
||||
virtual void SetVSync(int vsync) { m_vsync = vsync; }
|
||||
|
||||
virtual void BeginScene() {}
|
||||
virtual void DrawPrimitive() {};
|
||||
virtual void DrawIndexedPrimitive() {}
|
||||
virtual void DrawIndexedPrimitive(int offset, int count) {}
|
||||
virtual void EndScene();
|
||||
|
||||
virtual bool HasDepthSparse() { return false; }
|
||||
@@ -216,24 +220,30 @@ public:
|
||||
virtual void ClearDepth(GSTexture* t) {}
|
||||
virtual void ClearStencil(GSTexture* t, u8 c) {}
|
||||
|
||||
GSTexture* CreateSparseRenderTarget(int w, int h, int format = 0);
|
||||
GSTexture* CreateSparseDepthStencil(int w, int h, int format = 0);
|
||||
GSTexture* CreateRenderTarget(int w, int h, int format = 0);
|
||||
GSTexture* CreateDepthStencil(int w, int h, int format = 0);
|
||||
GSTexture* CreateTexture(int w, int h, int format = 0);
|
||||
GSTexture* CreateOffscreen(int w, int h, int format = 0);
|
||||
GSTexture* CreateSparseRenderTarget(int w, int h, GSTexture::Format format);
|
||||
GSTexture* CreateSparseDepthStencil(int w, int h, GSTexture::Format format);
|
||||
GSTexture* CreateRenderTarget(int w, int h, GSTexture::Format format);
|
||||
GSTexture* CreateDepthStencil(int w, int h, GSTexture::Format format);
|
||||
GSTexture* CreateTexture(int w, int h, GSTexture::Format format);
|
||||
GSTexture* CreateOffscreen(int w, int h, GSTexture::Format format);
|
||||
GSTexture::Format GetDefaultTextureFormat(GSTexture::Type type);
|
||||
|
||||
virtual GSTexture* CopyOffscreen(GSTexture* src, const GSVector4& sRect, int w, int h, int format = 0, int ps_shader = 0) { return NULL; }
|
||||
/// Download the region `rect` of `src` into `out_map`
|
||||
/// `out_map` will be valid a call to `DownloadTextureComplete`
|
||||
virtual bool DownloadTexture(GSTexture* src, const GSVector4i& rect, GSTexture::GSMap& out_map) { return false; }
|
||||
|
||||
/// Scale the region `sRect` of `src` to the size `dSize` using `ps_shader` and store the result in `out_map`
|
||||
/// `out_map` will be valid a call to `DownloadTextureComplete`
|
||||
virtual bool DownloadTextureConvert(GSTexture* src, const GSVector4& sRect, const GSVector2i& dSize, GSTexture::Format format, ShaderConvert ps_shader, GSTexture::GSMap& out_map, bool linear);
|
||||
|
||||
/// Must be called to free resources after calling `DownloadTexture` or `DownloadTextureConvert`
|
||||
virtual void DownloadTextureComplete() {}
|
||||
|
||||
virtual void CopyRect(GSTexture* sTex, GSTexture* dTex, const GSVector4i& r) {}
|
||||
virtual void StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, int shader = 0, bool linear = true) {}
|
||||
virtual void StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, ShaderConvert shader = ShaderConvert::COPY, bool linear = true) {}
|
||||
virtual void StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, bool red, bool green, bool blue, bool alpha) {}
|
||||
|
||||
void StretchRect(GSTexture* sTex, GSTexture* dTex, const GSVector4& dRect, int shader = 0, bool linear = true);
|
||||
|
||||
virtual void PSSetShaderResources(GSTexture* sr0, GSTexture* sr1) {}
|
||||
virtual void PSSetShaderResource(int i, GSTexture* sRect) {}
|
||||
virtual void OMSetRenderTargets(GSTexture* rt, GSTexture* ds, const GSVector4i* scissor = NULL) {}
|
||||
void StretchRect(GSTexture* sTex, GSTexture* dTex, const GSVector4& dRect, ShaderConvert shader = ShaderConvert::COPY, bool linear = true);
|
||||
|
||||
GSTexture* GetCurrent();
|
||||
|
||||
@@ -244,7 +254,7 @@ public:
|
||||
void ExternalFX();
|
||||
virtual void RenderOsd(GSTexture* dt) {};
|
||||
|
||||
bool ResizeTexture(GSTexture** t, int type, int w, int h);
|
||||
bool ResizeTexture(GSTexture** t, GSTexture::Type type, int w, int h);
|
||||
bool ResizeTexture(GSTexture** t, int w, int h);
|
||||
bool ResizeTarget(GSTexture** t, int w, int h);
|
||||
bool ResizeTarget(GSTexture** t);
|
||||
|
||||
@@ -16,9 +16,7 @@
|
||||
#include "PrecompiledHeader.h"
|
||||
#include "GSOsdManager.h"
|
||||
#include "GS/GS.h"
|
||||
#ifdef _WIN32
|
||||
#include "GS/resource.h"
|
||||
#endif
|
||||
#include "Host.h"
|
||||
|
||||
#if __GNUC__ > 5 || (__GNUC__ == 5 && __GNUC_MINOR__ >= 4)
|
||||
#include <codecvt>
|
||||
@@ -31,8 +29,12 @@ void GSOsdManager::LoadFont()
|
||||
if (error)
|
||||
{
|
||||
FT_Error error_load_res = 1;
|
||||
if (theApp.LoadResource(IDR_FONT_ROBOTO, resource_data_buffer))
|
||||
error_load_res = FT_New_Memory_Face(m_library, (const FT_Byte*)resource_data_buffer.data(), resource_data_buffer.size(), 0, &m_face);
|
||||
auto buffer = Host::ReadResourceFile("fonts/Roboto-Regular.ttf");
|
||||
if (buffer.has_value())
|
||||
{
|
||||
resource_data_buffer = std::move(*buffer);
|
||||
error_load_res = FT_New_Memory_Face(m_library, resource_data_buffer.data(), resource_data_buffer.size(), 0, &m_face);
|
||||
}
|
||||
|
||||
if (error_load_res)
|
||||
{
|
||||
|
||||
@@ -94,5 +94,5 @@ public:
|
||||
size_t GeneratePrimitives(GSVertexPT1* dst, size_t count);
|
||||
|
||||
private:
|
||||
std::vector<char> resource_data_buffer;
|
||||
std::vector<u8> resource_data_buffer;
|
||||
};
|
||||
|
||||
@@ -512,18 +512,17 @@ void GSRenderer::VSync(int field)
|
||||
{
|
||||
GSVector2i size = m_capture.GetSize();
|
||||
|
||||
if (GSTexture* offscreen = m_dev->CopyOffscreen(current, GSVector4(0, 0, 1, 1), size.x, size.y))
|
||||
bool res;
|
||||
GSTexture::GSMap m;
|
||||
if (size == current->GetSize())
|
||||
res = m_dev->DownloadTexture(current, GSVector4i(0, 0, size.x, size.y), m);
|
||||
else
|
||||
res = m_dev->DownloadTextureConvert(current, GSVector4(0, 0, 1, 1), size, GSTexture::Format::Color, ShaderConvert::COPY, m, true);
|
||||
|
||||
if (res)
|
||||
{
|
||||
GSTexture::GSMap m;
|
||||
|
||||
if (offscreen->Map(m))
|
||||
{
|
||||
m_capture.DeliverFrame(m.bits, m.pitch, !m_dev->IsRBSwapped());
|
||||
|
||||
offscreen->Unmap();
|
||||
}
|
||||
|
||||
m_dev->Recycle(offscreen);
|
||||
m_capture.DeliverFrame(m.bits, m.pitch, !m_dev->IsRBSwapped());
|
||||
m_dev->DownloadTextureComplete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,6 +60,7 @@ public:
|
||||
virtual bool CanUpscale() { return false; }
|
||||
virtual int GetUpscaleMultiplier() { return 1; }
|
||||
virtual GSVector2i GetCustomResolution() { return GSVector2i(0, 0); }
|
||||
virtual GSVector2 GetTextureScaleFactor() { return { 1.0f, 1.0f }; }
|
||||
GSVector2i GetInternalResolution();
|
||||
void SetVSync(int vsync);
|
||||
|
||||
|
||||
@@ -22,8 +22,8 @@ GSTexture::GSTexture()
|
||||
, m_size(0, 0)
|
||||
, m_committed_size(0, 0)
|
||||
, m_gpu_page_size(0, 0)
|
||||
, m_type(0)
|
||||
, m_format(0)
|
||||
, m_type(Type::Invalid)
|
||||
, m_format(Format::Invalid)
|
||||
, m_sparse(false)
|
||||
, last_frame_used(0)
|
||||
, LikelyOffset(false)
|
||||
|
||||
@@ -19,15 +19,6 @@
|
||||
|
||||
class GSTexture
|
||||
{
|
||||
protected:
|
||||
GSVector2 m_scale;
|
||||
GSVector2i m_size;
|
||||
GSVector2i m_committed_size;
|
||||
GSVector2i m_gpu_page_size;
|
||||
int m_type;
|
||||
int m_format;
|
||||
bool m_sparse;
|
||||
|
||||
public:
|
||||
struct GSMap
|
||||
{
|
||||
@@ -35,17 +26,40 @@ public:
|
||||
int pitch;
|
||||
};
|
||||
|
||||
enum
|
||||
enum class Type
|
||||
{
|
||||
Invalid = 0,
|
||||
RenderTarget = 1,
|
||||
DepthStencil,
|
||||
Texture,
|
||||
Offscreen,
|
||||
Backbuffer,
|
||||
SparseRenderTarget,
|
||||
SparseDepthStencil
|
||||
SparseDepthStencil,
|
||||
};
|
||||
|
||||
enum class Format
|
||||
{
|
||||
Invalid = 0, ///< Used for initialization
|
||||
Backbuffer, ///< For displaying to the screen
|
||||
Color, ///< Standard (RGBA8) color texture
|
||||
FloatColor, ///< Float-based color texture for colclip emulation (RGBA32F)
|
||||
DepthStencil, ///< Depth stencil texture
|
||||
UNorm8, ///< A8UNorm texture for paletted textures and the OSD font
|
||||
UInt16, ///< UInt16 texture for reading back 16-bit depth
|
||||
UInt32, ///< UInt32 texture for reading back 24 and 32-bit depth
|
||||
Int32, ///< Int32 texture for date emulation
|
||||
};
|
||||
|
||||
protected:
|
||||
GSVector2 m_scale;
|
||||
GSVector2i m_size;
|
||||
GSVector2i m_committed_size;
|
||||
GSVector2i m_gpu_page_size;
|
||||
Type m_type;
|
||||
Format m_format;
|
||||
bool m_sparse;
|
||||
|
||||
public:
|
||||
GSTexture();
|
||||
virtual ~GSTexture() {}
|
||||
@@ -70,8 +84,8 @@ public:
|
||||
int GetHeight() const { return m_size.y; }
|
||||
GSVector2i GetSize() const { return m_size; }
|
||||
|
||||
int GetType() const { return m_type; }
|
||||
int GetFormat() const { return m_format; }
|
||||
Type GetType() const { return m_type; }
|
||||
Format GetFormat() const { return m_format; }
|
||||
|
||||
virtual void CommitPages(const GSVector2i& region, bool commit) {}
|
||||
void CommitRegion(const GSVector2i& region);
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
#include "GS/Renderers/DX11/D3D.h"
|
||||
#include "GS/GSExtra.h"
|
||||
#include "GS/GSUtil.h"
|
||||
#include "GS/resource.h"
|
||||
#include "Host.h"
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <VersionHelpers.h>
|
||||
@@ -218,6 +218,11 @@ bool GSDevice11::Create(const WindowInfo& wi)
|
||||
m_hack_topleft_offset = (m_upscale_multiplier != 1 && D3D::IsNvidia(adapter.get()) && !disable_safe_features) ? -0.01f : 0.0f;
|
||||
}
|
||||
|
||||
std::optional<std::string> shader = Host::ReadResourceFileToString("shaders/dx11/tfx.fx");
|
||||
if (!shader.has_value())
|
||||
return false;
|
||||
m_tfx_source = std::move(*shader);
|
||||
|
||||
// convert
|
||||
|
||||
D3D11_INPUT_ELEMENT_DESC il_convert[] =
|
||||
@@ -229,9 +234,10 @@ bool GSDevice11::Create(const WindowInfo& wi)
|
||||
|
||||
ShaderMacro sm_model(m_shader.model);
|
||||
|
||||
std::vector<char> shader;
|
||||
theApp.LoadResource(IDR_CONVERT_FX, shader);
|
||||
CreateShader(shader, "convert.fx", nullptr, "vs_main", sm_model.GetPtr(), &m_convert.vs, il_convert, std::size(il_convert), m_convert.il.put());
|
||||
shader = Host::ReadResourceFileToString("shaders/dx11/convert.fx");
|
||||
if (!shader.has_value())
|
||||
return false;
|
||||
CreateShader(*shader, "convert.fx", nullptr, "vs_main", sm_model.GetPtr(), &m_convert.vs, il_convert, std::size(il_convert), m_convert.il.put());
|
||||
|
||||
ShaderMacro sm_convert(m_shader.model);
|
||||
sm_convert.AddMacro("PS_SCALE_FACTOR", std::max(1, m_upscale_multiplier));
|
||||
@@ -240,7 +246,7 @@ bool GSDevice11::Create(const WindowInfo& wi)
|
||||
|
||||
for (size_t i = 0; i < std::size(m_convert.ps); i++)
|
||||
{
|
||||
CreateShader(shader, "convert.fx", nullptr, format("ps_main%d", i).c_str(), sm_convert_ptr, m_convert.ps[i].put());
|
||||
CreateShader(*shader, "convert.fx", nullptr, shaderName(static_cast<ShaderConvert>(i)), sm_convert_ptr, m_convert.ps[i].put());
|
||||
}
|
||||
|
||||
memset(&dsd, 0, sizeof(dsd));
|
||||
@@ -269,10 +275,13 @@ bool GSDevice11::Create(const WindowInfo& wi)
|
||||
|
||||
m_dev->CreateBuffer(&bd, nullptr, m_merge.cb.put());
|
||||
|
||||
theApp.LoadResource(IDR_MERGE_FX, shader);
|
||||
shader = Host::ReadResourceFileToString("shaders/dx11/merge.fx");
|
||||
if (!shader.has_value())
|
||||
return false;
|
||||
|
||||
for (size_t i = 0; i < std::size(m_merge.ps); i++)
|
||||
{
|
||||
CreateShader(shader, "merge.fx", nullptr, format("ps_main%d", i).c_str(), sm_model.GetPtr(), m_merge.ps[i].put());
|
||||
CreateShader(*shader, "merge.fx", nullptr, format("ps_main%d", i).c_str(), sm_model.GetPtr(), m_merge.ps[i].put());
|
||||
}
|
||||
|
||||
memset(&bsd, 0, sizeof(bsd));
|
||||
@@ -298,10 +307,12 @@ bool GSDevice11::Create(const WindowInfo& wi)
|
||||
|
||||
m_dev->CreateBuffer(&bd, nullptr, m_interlace.cb.put());
|
||||
|
||||
theApp.LoadResource(IDR_INTERLACE_FX, shader);
|
||||
shader = Host::ReadResourceFileToString("shaders/dx11/interlace.fx");
|
||||
if (!shader.has_value())
|
||||
return false;
|
||||
for (size_t i = 0; i < std::size(m_interlace.ps); i++)
|
||||
{
|
||||
CreateShader(shader, "interlace.fx", nullptr, format("ps_main%d", i).c_str(), sm_model.GetPtr(), m_interlace.ps[i].put());
|
||||
CreateShader(*shader, "interlace.fx", nullptr, format("ps_main%d", i).c_str(), sm_model.GetPtr(), m_interlace.ps[i].put());
|
||||
}
|
||||
|
||||
// Shade Boost
|
||||
@@ -320,8 +331,10 @@ bool GSDevice11::Create(const WindowInfo& wi)
|
||||
|
||||
m_dev->CreateBuffer(&bd, nullptr, m_shadeboost.cb.put());
|
||||
|
||||
theApp.LoadResource(IDR_SHADEBOOST_FX, shader);
|
||||
CreateShader(shader, "shadeboost.fx", nullptr, "ps_main", sm_sboost.GetPtr(), m_shadeboost.ps.put());
|
||||
shader = Host::ReadResourceFileToString("shaders/dx11/shadeboost.fx");
|
||||
if (!shader.has_value())
|
||||
return false;
|
||||
CreateShader(*shader, "shadeboost.fx", nullptr, "ps_main", sm_sboost.GetPtr(), m_shadeboost.ps.put());
|
||||
|
||||
// External fx shader
|
||||
|
||||
@@ -418,7 +431,7 @@ bool GSDevice11::Create(const WindowInfo& wi)
|
||||
const GSVector2i tex_font = m_osd.get_texture_font_size();
|
||||
|
||||
m_font = std::unique_ptr<GSTexture>(
|
||||
CreateSurface(GSTexture::Texture, tex_font.x, tex_font.y, DXGI_FORMAT_R8_UNORM));
|
||||
CreateSurface(GSTexture::Type::Texture, tex_font.x, tex_font.y, GSTexture::Format::UNorm8));
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -443,7 +456,7 @@ bool GSDevice11::Reset(int w, int h)
|
||||
return false;
|
||||
}
|
||||
|
||||
m_backbuffer = new GSTexture11(std::move(backbuffer));
|
||||
m_backbuffer = new GSTexture11(std::move(backbuffer), GSTexture::Format::Backbuffer);
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -562,16 +575,32 @@ void GSDevice11::ClearStencil(GSTexture* t, u8 c)
|
||||
m_ctx->ClearDepthStencilView(*(GSTexture11*)t, D3D11_CLEAR_STENCIL, 0, c);
|
||||
}
|
||||
|
||||
GSTexture* GSDevice11::CreateSurface(int type, int w, int h, int format)
|
||||
GSTexture* GSDevice11::CreateSurface(GSTexture::Type type, int w, int h, GSTexture::Format format)
|
||||
{
|
||||
D3D11_TEXTURE2D_DESC desc;
|
||||
|
||||
memset(&desc, 0, sizeof(desc));
|
||||
|
||||
DXGI_FORMAT dxformat;
|
||||
switch (format)
|
||||
{
|
||||
case GSTexture::Format::Color: dxformat = DXGI_FORMAT_R8G8B8A8_UNORM; break;
|
||||
case GSTexture::Format::FloatColor: dxformat = DXGI_FORMAT_R32G32B32A32_FLOAT; break;
|
||||
case GSTexture::Format::DepthStencil: dxformat = DXGI_FORMAT_R32G8X24_TYPELESS; break;
|
||||
case GSTexture::Format::UNorm8: dxformat = DXGI_FORMAT_A8_UNORM; break;
|
||||
case GSTexture::Format::UInt16: dxformat = DXGI_FORMAT_R16_UINT; break;
|
||||
case GSTexture::Format::UInt32: dxformat = DXGI_FORMAT_R32_UINT; break;
|
||||
case GSTexture::Format::Int32: dxformat = DXGI_FORMAT_R32_SINT; break;
|
||||
case GSTexture::Format::Invalid:
|
||||
case GSTexture::Format::Backbuffer:
|
||||
ASSERT(0);
|
||||
dxformat = DXGI_FORMAT_UNKNOWN;
|
||||
}
|
||||
|
||||
// Texture limit for D3D10/11 min 1, max 8192 D3D10, max 16384 D3D11.
|
||||
desc.Width = std::max(1, std::min(w, m_d3d_texsize));
|
||||
desc.Height = std::max(1, std::min(h, m_d3d_texsize));
|
||||
desc.Format = (DXGI_FORMAT)format;
|
||||
desc.Format = dxformat;
|
||||
desc.MipLevels = 1;
|
||||
desc.ArraySize = 1;
|
||||
desc.SampleDesc.Count = 1;
|
||||
@@ -580,44 +609,35 @@ GSTexture* GSDevice11::CreateSurface(int type, int w, int h, int format)
|
||||
|
||||
// mipmap = m_mipmap > 1 || m_filter != TriFiltering::None;
|
||||
const bool mipmap = m_mipmap > 1;
|
||||
const int layers = mipmap && format == DXGI_FORMAT_R8G8B8A8_UNORM ? (int)log2(std::max(w, h)) : 1;
|
||||
const int layers = mipmap && format == GSTexture::Format::Color ? (int)log2(std::max(w, h)) : 1;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case GSTexture::RenderTarget:
|
||||
case GSTexture::Type::RenderTarget:
|
||||
desc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
|
||||
break;
|
||||
case GSTexture::DepthStencil:
|
||||
case GSTexture::Type::DepthStencil:
|
||||
desc.BindFlags = D3D11_BIND_DEPTH_STENCIL | D3D11_BIND_SHADER_RESOURCE;
|
||||
break;
|
||||
case GSTexture::Texture:
|
||||
case GSTexture::Type::Texture:
|
||||
desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
|
||||
desc.MipLevels = layers;
|
||||
break;
|
||||
case GSTexture::Offscreen:
|
||||
case GSTexture::Type::Offscreen:
|
||||
desc.Usage = D3D11_USAGE_STAGING;
|
||||
desc.CPUAccessFlags |= D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE;
|
||||
break;
|
||||
}
|
||||
|
||||
GSTexture11* t = NULL;
|
||||
GSTexture11* t = nullptr;
|
||||
|
||||
wil::com_ptr_nothrow<ID3D11Texture2D> texture;
|
||||
HRESULT hr = m_dev->CreateTexture2D(&desc, nullptr, texture.put());
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
t = new GSTexture11(std::move(texture));
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case GSTexture::RenderTarget:
|
||||
ClearRenderTarget(t, 0);
|
||||
break;
|
||||
case GSTexture::DepthStencil:
|
||||
ClearDepth(t);
|
||||
break;
|
||||
}
|
||||
t = new GSTexture11(std::move(texture), format);
|
||||
assert(type == t->GetType());
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -627,42 +647,24 @@ GSTexture* GSDevice11::CreateSurface(int type, int w, int h, int format)
|
||||
return t;
|
||||
}
|
||||
|
||||
GSTexture* GSDevice11::FetchSurface(int type, int w, int h, int format)
|
||||
bool GSDevice11::DownloadTexture(GSTexture* src, const GSVector4i& rect, GSTexture::GSMap& out_map)
|
||||
{
|
||||
if (format == 0)
|
||||
format = (type == GSTexture::DepthStencil || type == GSTexture::SparseDepthStencil) ? DXGI_FORMAT_R32G8X24_TYPELESS : DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
|
||||
return __super::FetchSurface(type, w, h, format);
|
||||
ASSERT(src);
|
||||
ASSERT(!m_download_tex);
|
||||
m_download_tex.reset(static_cast<GSTexture11*>(CreateOffscreen(rect.width(), rect.height(), src->GetFormat())));
|
||||
if (!m_download_tex)
|
||||
return false;
|
||||
CopyRect(src, m_download_tex.get(), rect);
|
||||
return m_download_tex->Map(out_map);
|
||||
}
|
||||
|
||||
GSTexture* GSDevice11::CopyOffscreen(GSTexture* src, const GSVector4& sRect, int w, int h, int format, int ps_shader)
|
||||
void GSDevice11::DownloadTextureComplete()
|
||||
{
|
||||
GSTexture* dst = NULL;
|
||||
|
||||
if (format == 0)
|
||||
if (m_download_tex)
|
||||
{
|
||||
format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
m_download_tex->Unmap();
|
||||
Recycle(m_download_tex.release());
|
||||
}
|
||||
|
||||
ASSERT(format == DXGI_FORMAT_R8G8B8A8_UNORM || format == DXGI_FORMAT_R16_UINT || format == DXGI_FORMAT_R32_UINT);
|
||||
|
||||
if (GSTexture* rt = CreateRenderTarget(w, h, format))
|
||||
{
|
||||
GSVector4 dRect(0, 0, w, h);
|
||||
|
||||
StretchRect(src, sRect, rt, dRect, m_convert.ps[ps_shader].get(), NULL);
|
||||
|
||||
dst = CreateOffscreen(w, h, format);
|
||||
|
||||
if (dst)
|
||||
{
|
||||
m_ctx->CopyResource(*(GSTexture11*)dst, *(GSTexture11*)rt);
|
||||
}
|
||||
|
||||
Recycle(rt);
|
||||
}
|
||||
|
||||
return dst;
|
||||
}
|
||||
|
||||
void GSDevice11::CopyRect(GSTexture* sTex, GSTexture* dTex, const GSVector4i& r)
|
||||
@@ -678,7 +680,7 @@ void GSDevice11::CopyRect(GSTexture* sTex, GSTexture* dTex, const GSVector4i& r)
|
||||
// DX api isn't happy if we pass a box for depth copy
|
||||
// It complains that depth/multisample must be a full copy
|
||||
// and asks us to use a NULL for the box
|
||||
const bool depth = (sTex->GetType() == GSTexture::DepthStencil);
|
||||
const bool depth = (sTex->GetType() == GSTexture::Type::DepthStencil);
|
||||
auto pBox = depth ? nullptr : &box;
|
||||
|
||||
m_ctx->CopySubresourceRegion(*(GSTexture11*)dTex, 0, 0, 0, 0, *(GSTexture11*)sTex, 0, pBox);
|
||||
@@ -686,7 +688,7 @@ void GSDevice11::CopyRect(GSTexture* sTex, GSTexture* dTex, const GSVector4i& r)
|
||||
|
||||
void GSDevice11::CloneTexture(GSTexture* src, GSTexture** dest)
|
||||
{
|
||||
if (!src || !(src->GetType() == GSTexture::DepthStencil || src->GetType() == GSTexture::RenderTarget))
|
||||
if (!src || !(src->GetType() == GSTexture::Type::DepthStencil || src->GetType() == GSTexture::Type::RenderTarget))
|
||||
{
|
||||
ASSERT(0);
|
||||
return;
|
||||
@@ -695,7 +697,7 @@ void GSDevice11::CloneTexture(GSTexture* src, GSTexture** dest)
|
||||
const int w = src->GetWidth();
|
||||
const int h = src->GetHeight();
|
||||
|
||||
if (src->GetType() == GSTexture::DepthStencil)
|
||||
if (src->GetType() == GSTexture::Type::DepthStencil)
|
||||
*dest = CreateDepthStencil(w, h, src->GetFormat());
|
||||
else
|
||||
*dest = CreateRenderTarget(w, h, src->GetFormat());
|
||||
@@ -703,9 +705,9 @@ void GSDevice11::CloneTexture(GSTexture* src, GSTexture** dest)
|
||||
CopyRect(src, *dest, GSVector4i(0, 0, w, h));
|
||||
}
|
||||
|
||||
void GSDevice11::StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, int shader, bool linear)
|
||||
void GSDevice11::StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, ShaderConvert shader, bool linear)
|
||||
{
|
||||
StretchRect(sTex, sRect, dTex, dRect, m_convert.ps[shader].get(), nullptr, linear);
|
||||
StretchRect(sTex, sRect, dTex, dRect, m_convert.ps[static_cast<int>(shader)].get(), nullptr, linear);
|
||||
}
|
||||
|
||||
void GSDevice11::StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, ID3D11PixelShader* ps, ID3D11Buffer* ps_cb, bool linear)
|
||||
@@ -729,7 +731,7 @@ void GSDevice11::StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture*
|
||||
wil::com_ptr_nothrow<ID3D11BlendState> bs;
|
||||
m_dev->CreateBlendState(&bd, bs.put());
|
||||
|
||||
StretchRect(sTex, sRect, dTex, dRect, m_convert.ps[ShaderConvert_COPY].get(), nullptr, bs.get(), false);
|
||||
StretchRect(sTex, sRect, dTex, dRect, m_convert.ps[static_cast<int>(ShaderConvert::COPY)].get(), nullptr, bs.get(), false);
|
||||
}
|
||||
|
||||
void GSDevice11::StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, ID3D11PixelShader* ps, ID3D11Buffer* ps_cb, ID3D11BlendState* bs, bool linear)
|
||||
@@ -740,8 +742,10 @@ void GSDevice11::StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture*
|
||||
return;
|
||||
}
|
||||
|
||||
const bool draw_in_depth = (ps == m_convert.ps[ShaderConvert_RGBA8_TO_FLOAT32] || ps == m_convert.ps[ShaderConvert_RGBA8_TO_FLOAT24]
|
||||
|| ps == m_convert.ps[ShaderConvert_RGBA8_TO_FLOAT16] || ps == m_convert.ps[ShaderConvert_RGB5A1_TO_FLOAT16]);
|
||||
const bool draw_in_depth = ps == m_convert.ps[static_cast<int>(ShaderConvert::RGBA8_TO_FLOAT32)]
|
||||
|| ps == m_convert.ps[static_cast<int>(ShaderConvert::RGBA8_TO_FLOAT24)]
|
||||
|| ps == m_convert.ps[static_cast<int>(ShaderConvert::RGBA8_TO_FLOAT16)]
|
||||
|| ps == m_convert.ps[static_cast<int>(ShaderConvert::RGB5A1_TO_FLOAT16)];
|
||||
|
||||
BeginScene();
|
||||
|
||||
@@ -827,7 +831,7 @@ void GSDevice11::RenderOsd(GSTexture* dt)
|
||||
// ps
|
||||
PSSetShaderResource(0, m_font.get());
|
||||
PSSetSamplerState(m_convert.pt.get(), nullptr);
|
||||
PSSetShader(m_convert.ps[ShaderConvert_OSD].get(), nullptr);
|
||||
PSSetShader(m_convert.ps[static_cast<int>(ShaderConvert::OSD)].get(), nullptr);
|
||||
|
||||
// ia
|
||||
IASetInputLayout(m_convert.il.get());
|
||||
@@ -920,9 +924,8 @@ void GSDevice11::DoExternalFX(GSTexture* sTex, GSTexture* dTex)
|
||||
|
||||
shader << fshader.rdbuf();
|
||||
const std::string& s = shader.str();
|
||||
std::vector<char> buff(s.begin(), s.end());
|
||||
ShaderMacro sm(m_shader.model);
|
||||
CreateShader(buff, shader_name.c_str(), D3D_COMPILE_STANDARD_FILE_INCLUDE, "ps_main", sm.GetPtr(), m_shaderfx.ps.put());
|
||||
CreateShader(s, shader_name.c_str(), D3D_COMPILE_STANDARD_FILE_INCLUDE, "ps_main", sm.GetPtr(), m_shaderfx.ps.put());
|
||||
}
|
||||
catch (GSRecoverableError)
|
||||
{
|
||||
@@ -952,10 +955,12 @@ void GSDevice11::DoFXAA(GSTexture* sTex, GSTexture* dTex)
|
||||
{
|
||||
try
|
||||
{
|
||||
std::vector<char> shader;
|
||||
theApp.LoadResource(IDR_FXAA_FX, shader);
|
||||
ShaderMacro sm(m_shader.model);
|
||||
CreateShader(shader, "fxaa.fx", nullptr, "ps_main", sm.GetPtr(), m_fxaa.ps.put());
|
||||
std::optional<std::string> shader = Host::ReadResourceFileToString("shaders/common/fxaa.fx");
|
||||
if (shader.has_value())
|
||||
{
|
||||
ShaderMacro sm(m_shader.model);
|
||||
CreateShader(*shader, "fxaa.fx", nullptr, "ps_main", sm.GetPtr(), m_fxaa.ps.put());
|
||||
}
|
||||
}
|
||||
catch (GSRecoverableError)
|
||||
{
|
||||
@@ -1022,7 +1027,7 @@ void GSDevice11::SetupDATE(GSTexture* rt, GSTexture* ds, const GSVertexPT1* vert
|
||||
// ps
|
||||
PSSetShaderResources(rt, nullptr);
|
||||
PSSetSamplerState(m_convert.pt.get(), nullptr);
|
||||
PSSetShader(m_convert.ps[datm ? ShaderConvert_DATM_1 : ShaderConvert_DATM_0].get(), nullptr);
|
||||
PSSetShader(m_convert.ps[static_cast<int>(datm ? ShaderConvert::DATM_1 : ShaderConvert::DATM_0)].get(), nullptr);
|
||||
|
||||
//
|
||||
|
||||
@@ -1394,7 +1399,7 @@ D3D_SHADER_MACRO* GSDevice11::ShaderMacro::GetPtr(void)
|
||||
return (D3D_SHADER_MACRO*)mout.data();
|
||||
}
|
||||
|
||||
void GSDevice11::CreateShader(const std::vector<char>& source, const char* fn, ID3DInclude* include, const char* entry, D3D_SHADER_MACRO* macro, ID3D11VertexShader** vs, D3D11_INPUT_ELEMENT_DESC* layout, int count, ID3D11InputLayout** il)
|
||||
void GSDevice11::CreateShader(const std::string& source, const char* fn, ID3DInclude* include, const char* entry, D3D_SHADER_MACRO* macro, ID3D11VertexShader** vs, D3D11_INPUT_ELEMENT_DESC* layout, int count, ID3D11InputLayout** il)
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
@@ -1417,7 +1422,7 @@ void GSDevice11::CreateShader(const std::vector<char>& source, const char* fn, I
|
||||
}
|
||||
}
|
||||
|
||||
void GSDevice11::CreateShader(const std::vector<char>& source, const char* fn, ID3DInclude* include, const char* entry, D3D_SHADER_MACRO* macro, ID3D11GeometryShader** gs)
|
||||
void GSDevice11::CreateShader(const std::string& source, const char* fn, ID3DInclude* include, const char* entry, D3D_SHADER_MACRO* macro, ID3D11GeometryShader** gs)
|
||||
{
|
||||
wil::com_ptr_nothrow<ID3DBlob> shader;
|
||||
|
||||
@@ -1431,7 +1436,7 @@ void GSDevice11::CreateShader(const std::vector<char>& source, const char* fn, I
|
||||
}
|
||||
}
|
||||
|
||||
void GSDevice11::CreateShader(const std::vector<char>& source, const char* fn, ID3DInclude* include, const char* entry, D3D_SHADER_MACRO* macro, ID3D11PixelShader** ps)
|
||||
void GSDevice11::CreateShader(const std::string& source, const char* fn, ID3DInclude* include, const char* entry, D3D_SHADER_MACRO* macro, ID3D11PixelShader** ps)
|
||||
{
|
||||
wil::com_ptr_nothrow<ID3DBlob> shader;
|
||||
|
||||
@@ -1445,7 +1450,7 @@ void GSDevice11::CreateShader(const std::vector<char>& source, const char* fn, I
|
||||
}
|
||||
}
|
||||
|
||||
void GSDevice11::CompileShader(const std::vector<char>& source, const char* fn, ID3DInclude* include, const char* entry, D3D_SHADER_MACRO* macro, ID3DBlob** shader, const std::string& shader_model)
|
||||
void GSDevice11::CompileShader(const std::string& source, const char* fn, ID3DInclude* include, const char* entry, D3D_SHADER_MACRO* macro, ID3DBlob** shader, const std::string& shader_model)
|
||||
{
|
||||
wil::com_ptr_nothrow<ID3DBlob> error;
|
||||
|
||||
@@ -1456,7 +1461,7 @@ void GSDevice11::CompileShader(const std::vector<char>& source, const char* fn,
|
||||
#endif
|
||||
|
||||
const HRESULT hr = D3DCompile(
|
||||
source.data(), source.size(), fn, macro,
|
||||
source.c_str(), source.size(), fn, macro,
|
||||
include, entry, shader_model.c_str(),
|
||||
flags, 0, shader, error.put());
|
||||
|
||||
|
||||
@@ -336,6 +336,7 @@ public:
|
||||
u32 blend_index : 7;
|
||||
u32 abe : 1;
|
||||
u32 accu_blend : 1;
|
||||
u32 blend_mix : 1;
|
||||
};
|
||||
|
||||
struct
|
||||
@@ -347,7 +348,7 @@ public:
|
||||
u32 key;
|
||||
};
|
||||
|
||||
operator u32() { return key & 0x1fff; }
|
||||
operator u32() { return key & 0x3fff; }
|
||||
|
||||
OMBlendSelector()
|
||||
: key(0)
|
||||
@@ -395,8 +396,7 @@ private:
|
||||
int m_mipmap;
|
||||
int m_d3d_texsize;
|
||||
|
||||
GSTexture* CreateSurface(int type, int w, int h, int format);
|
||||
GSTexture* FetchSurface(int type, int w, int h, int format);
|
||||
GSTexture* CreateSurface(GSTexture::Type type, int w, int h, GSTexture::Format format) final;
|
||||
|
||||
void DoMerge(GSTexture* sTex[3], GSVector4* sRect, GSTexture* dTex, GSVector4* dRect, const GSRegPMODE& PMODE, const GSRegEXTBUF& EXTBUF, const GSVector4& c) final;
|
||||
void DoInterlace(GSTexture* sTex, GSTexture* dTex, int shader, bool linear, float yoffset = 0) final;
|
||||
@@ -449,7 +449,7 @@ private:
|
||||
{
|
||||
wil::com_ptr_nothrow<ID3D11InputLayout> il;
|
||||
wil::com_ptr_nothrow<ID3D11VertexShader> vs;
|
||||
wil::com_ptr_nothrow<ID3D11PixelShader> ps[ShaderConvert_Count];
|
||||
wil::com_ptr_nothrow<ID3D11PixelShader> ps[static_cast<int>(ShaderConvert::Count)];
|
||||
wil::com_ptr_nothrow<ID3D11SamplerState> ln;
|
||||
wil::com_ptr_nothrow<ID3D11SamplerState> pt;
|
||||
wil::com_ptr_nothrow<ID3D11DepthStencilState> dss;
|
||||
@@ -512,6 +512,9 @@ private:
|
||||
PSConstantBuffer m_ps_cb_cache;
|
||||
|
||||
std::unique_ptr<GSTexture> m_font;
|
||||
std::unique_ptr<GSTexture11> m_download_tex;
|
||||
|
||||
std::string m_tfx_source;
|
||||
|
||||
protected:
|
||||
struct
|
||||
@@ -532,22 +535,23 @@ public:
|
||||
void Flip();
|
||||
void SetVSync(int vsync) final;
|
||||
|
||||
void DrawPrimitive() final;
|
||||
void DrawPrimitive();
|
||||
void DrawIndexedPrimitive();
|
||||
void DrawIndexedPrimitive(int offset, int count) final;
|
||||
void DrawIndexedPrimitive(int offset, int count);
|
||||
|
||||
void ClearRenderTarget(GSTexture* t, const GSVector4& c) final;
|
||||
void ClearRenderTarget(GSTexture* t, u32 c) final;
|
||||
void ClearDepth(GSTexture* t) final;
|
||||
void ClearStencil(GSTexture* t, u8 c) final;
|
||||
|
||||
GSTexture* CopyOffscreen(GSTexture* src, const GSVector4& sRect, int w, int h, int format = 0, int ps_shader = 0) final;
|
||||
bool DownloadTexture(GSTexture* src, const GSVector4i& rect, GSTexture::GSMap& out_map) final;
|
||||
void DownloadTextureComplete() final;
|
||||
|
||||
void CloneTexture(GSTexture* src, GSTexture** dest);
|
||||
|
||||
void CopyRect(GSTexture* sTex, GSTexture* dTex, const GSVector4i& r);
|
||||
|
||||
void StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, int shader = 0, bool linear = true) final;
|
||||
void StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, ShaderConvert shader = ShaderConvert::COPY, bool linear = true) final;
|
||||
void StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, ID3D11PixelShader* ps, ID3D11Buffer* ps_cb, bool linear = true);
|
||||
void StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, bool red, bool green, bool blue, bool alpha);
|
||||
void StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, ID3D11PixelShader* ps, ID3D11Buffer* ps_cb, ID3D11BlendState* bs, bool linear = true);
|
||||
@@ -566,8 +570,8 @@ public:
|
||||
void VSSetShader(ID3D11VertexShader* vs, ID3D11Buffer* vs_cb);
|
||||
void GSSetShader(ID3D11GeometryShader* gs, ID3D11Buffer* gs_cb = NULL);
|
||||
|
||||
void PSSetShaderResources(GSTexture* sr0, GSTexture* sr1) final;
|
||||
void PSSetShaderResource(int i, GSTexture* sr) final;
|
||||
void PSSetShaderResources(GSTexture* sr0, GSTexture* sr1);
|
||||
void PSSetShaderResource(int i, GSTexture* sr);
|
||||
void PSSetShaderResourceView(int i, ID3D11ShaderResourceView* srv, GSTexture* sr);
|
||||
void PSSetShader(ID3D11PixelShader* ps, ID3D11Buffer* ps_cb);
|
||||
void PSUpdateShaderState();
|
||||
@@ -575,7 +579,7 @@ public:
|
||||
|
||||
void OMSetDepthStencilState(ID3D11DepthStencilState* dss, u8 sref);
|
||||
void OMSetBlendState(ID3D11BlendState* bs, float bf);
|
||||
void OMSetRenderTargets(GSTexture* rt, GSTexture* ds, const GSVector4i* scissor = NULL) final;
|
||||
void OMSetRenderTargets(GSTexture* rt, GSTexture* ds, const GSVector4i* scissor = NULL);
|
||||
|
||||
bool CreateTextureFX();
|
||||
void SetupVS(VSSelector sel, const VSConstantBuffer* cb);
|
||||
@@ -587,9 +591,9 @@ public:
|
||||
operator ID3D11Device*() { return m_dev.get(); }
|
||||
operator ID3D11DeviceContext*() { return m_ctx.get(); }
|
||||
|
||||
void CreateShader(const std::vector<char>& source, const char* fn, ID3DInclude* include, const char* entry, D3D_SHADER_MACRO* macro, ID3D11VertexShader** vs, D3D11_INPUT_ELEMENT_DESC* layout, int count, ID3D11InputLayout** il);
|
||||
void CreateShader(const std::vector<char>& source, const char* fn, ID3DInclude* include, const char* entry, D3D_SHADER_MACRO* macro, ID3D11GeometryShader** gs);
|
||||
void CreateShader(const std::vector<char>& source, const char* fn, ID3DInclude* include, const char* entry, D3D_SHADER_MACRO* macro, ID3D11PixelShader** ps);
|
||||
void CreateShader(const std::string& source, const char* fn, ID3DInclude* include, const char* entry, D3D_SHADER_MACRO* macro, ID3D11VertexShader** vs, D3D11_INPUT_ELEMENT_DESC* layout, int count, ID3D11InputLayout** il);
|
||||
void CreateShader(const std::string& source, const char* fn, ID3DInclude* include, const char* entry, D3D_SHADER_MACRO* macro, ID3D11GeometryShader** gs);
|
||||
void CreateShader(const std::string& source, const char* fn, ID3DInclude* include, const char* entry, D3D_SHADER_MACRO* macro, ID3D11PixelShader** ps);
|
||||
|
||||
void CompileShader(const std::vector<char>& source, const char* fn, ID3DInclude* include, const char* entry, D3D_SHADER_MACRO* macro, ID3DBlob** shader, const std::string& shader_model);
|
||||
void CompileShader(const std::string& source, const char* fn, ID3DInclude* include, const char* entry, D3D_SHADER_MACRO* macro, ID3DBlob** shader, const std::string& shader_model);
|
||||
};
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
#include "GSRendererDX11.h"
|
||||
|
||||
GSRendererDX11::GSRendererDX11()
|
||||
: GSRendererHW(new GSTextureCache11(this))
|
||||
{
|
||||
m_sw_blending = theApp.GetConfigI("accurate_blending_unit_d3d11");
|
||||
|
||||
@@ -317,7 +316,7 @@ void GSRendererDX11::EmulateChannelShuffle(GSTexture** rt, const GSTextureCache:
|
||||
m_channel_shuffle = false;
|
||||
}
|
||||
}
|
||||
else if ((tex->m_texture->GetType() == GSTexture::DepthStencil) && !(tex->m_32_bits_fmt))
|
||||
else if ((tex->m_texture->GetType() == GSTexture::Type::DepthStencil) && !(tex->m_32_bits_fmt))
|
||||
{
|
||||
// So far 2 games hit this code path. Urban Chaos and Tales of Abyss
|
||||
// UC: will copy depth to green channel
|
||||
@@ -361,11 +360,10 @@ void GSRendererDX11::EmulateChannelShuffle(GSTexture** rt, const GSTextureCache:
|
||||
{
|
||||
// Typically used in Terminator 3
|
||||
const int blue_mask = m_context->FRAME.FBMSK >> 24;
|
||||
const int green_mask = ~blue_mask & 0xFF;
|
||||
int blue_shift = -1;
|
||||
|
||||
// Note: potentially we could also check the value of the clut
|
||||
switch (m_context->FRAME.FBMSK >> 24)
|
||||
switch (blue_mask)
|
||||
{
|
||||
case 0xFF: ASSERT(0); break;
|
||||
case 0xFE: blue_shift = 1; break;
|
||||
@@ -375,21 +373,22 @@ void GSRendererDX11::EmulateChannelShuffle(GSTexture** rt, const GSTextureCache:
|
||||
case 0xE0: blue_shift = 5; break;
|
||||
case 0xC0: blue_shift = 6; break;
|
||||
case 0x80: blue_shift = 7; break;
|
||||
default: ASSERT(0); break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
const int green_shift = 8 - blue_shift;
|
||||
ps_cb.ChannelShuffle = GSVector4i(blue_mask, blue_shift, green_mask, green_shift);
|
||||
|
||||
if (blue_shift >= 0)
|
||||
{
|
||||
const int green_mask = ~blue_mask & 0xFF;
|
||||
const int green_shift = 8 - blue_shift;
|
||||
|
||||
// fprintf(stderr, "%d: Green/Blue channel (%d, %d)\n", s_n, blue_shift, green_shift);
|
||||
ps_cb.ChannelShuffle = GSVector4i(blue_mask, blue_shift, green_mask, green_shift);
|
||||
m_ps_sel.channel = ChannelFetch_GXBY;
|
||||
m_context->FRAME.FBMSK = 0x00FFFFFF;
|
||||
}
|
||||
else
|
||||
{
|
||||
// fprintf(stderr, "%d: Green channel (wrong mask) (fbmask %x)\n", s_n, m_context->FRAME.FBMSK >> 24);
|
||||
// fprintf(stderr, "%d: Green channel (wrong mask) (fbmask %x)\n", s_n, blue_mask);
|
||||
m_ps_sel.channel = ChannelFetch_GREEN;
|
||||
}
|
||||
}
|
||||
@@ -461,6 +460,16 @@ void GSRendererDX11::EmulateBlending(u8& afix)
|
||||
// Blending doesn't require sampling of the rt
|
||||
const bool blend_non_recursive = !!(blend_flag & BLEND_NO_REC);
|
||||
|
||||
// BLEND MIX selection, use a mix of hw/sw blending
|
||||
if (!m_vt.m_alpha.valid && (ALPHA.C == 0))
|
||||
GetAlphaMinMax();
|
||||
const bool blend_mix1 = !!(blend_flag & BLEND_MIX1);
|
||||
const bool blend_mix2 = !!(blend_flag & BLEND_MIX2);
|
||||
const bool blend_mix3 = !!(blend_flag & BLEND_MIX3);
|
||||
bool blend_mix = (blend_mix1 || blend_mix2 || blend_mix3)
|
||||
// Do not enable if As > 128 or F > 128, hw blend clamps to 1
|
||||
&& !((ALPHA.C == 0 && m_vt.m_alpha.max > 128) || (ALPHA.C == 2 && ALPHA.FIX > 128u));
|
||||
|
||||
bool sw_blending = false;
|
||||
switch (m_sw_blending)
|
||||
{
|
||||
@@ -473,6 +482,13 @@ void GSRendererDX11::EmulateBlending(u8& afix)
|
||||
break;
|
||||
}
|
||||
|
||||
// Do not run BLEND MIX if sw blending is already present, it's less accurate
|
||||
if (m_sw_blending)
|
||||
{
|
||||
blend_mix &= !sw_blending;
|
||||
sw_blending |= blend_mix;
|
||||
}
|
||||
|
||||
// Color clip
|
||||
if (m_env.COLCLAMP.CLAMP == 0)
|
||||
{
|
||||
@@ -484,7 +500,7 @@ void GSRendererDX11::EmulateBlending(u8& afix)
|
||||
m_ps_sel.colclip = 1;
|
||||
sw_blending = true;
|
||||
}
|
||||
else if (accumulation_blend)
|
||||
else if (accumulation_blend || blend_mix)
|
||||
{
|
||||
// fprintf(stderr, "%d: COLCLIP Fast HDR mode ENABLED\n", s_n);
|
||||
sw_blending = true;
|
||||
@@ -514,6 +530,7 @@ void GSRendererDX11::EmulateBlending(u8& afix)
|
||||
{
|
||||
// fprintf(stderr, "%d: PABE mode ENABLED\n", s_n);
|
||||
m_ps_sel.pabe = 1;
|
||||
sw_blending = blend_non_recursive;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -543,6 +560,30 @@ void GSRendererDX11::EmulateBlending(u8& afix)
|
||||
// Remove the addition/substraction from the SW blending
|
||||
m_ps_sel.blend_d = 2;
|
||||
}
|
||||
else if (blend_mix)
|
||||
{
|
||||
afix = (ALPHA.C == 2) ? ALPHA.FIX : 0;
|
||||
m_om_bsel.blend_mix = 1;
|
||||
|
||||
if (blend_mix1)
|
||||
{
|
||||
m_ps_sel.blend_a = 0;
|
||||
m_ps_sel.blend_b = 2;
|
||||
m_ps_sel.blend_d = 2;
|
||||
}
|
||||
else if (blend_mix2)
|
||||
{
|
||||
m_ps_sel.blend_a = 0;
|
||||
m_ps_sel.blend_b = 2;
|
||||
m_ps_sel.blend_d = 0;
|
||||
}
|
||||
else if (blend_mix3)
|
||||
{
|
||||
m_ps_sel.blend_a = 2;
|
||||
m_ps_sel.blend_b = 0;
|
||||
m_ps_sel.blend_d = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Disable HW blending
|
||||
@@ -611,7 +652,7 @@ void GSRendererDX11::EmulateTextureSampler(const GSTextureCache::Source* tex)
|
||||
// Require a float conversion if the texure is a depth otherwise uses Integral scaling
|
||||
if (psm.depth)
|
||||
{
|
||||
m_ps_sel.depth_fmt = (tex->m_texture->GetType() != GSTexture::DepthStencil) ? 3 : 1;
|
||||
m_ps_sel.depth_fmt = (tex->m_texture->GetType() != GSTexture::Type::DepthStencil) ? 3 : 1;
|
||||
}
|
||||
|
||||
// Shuffle is a 16 bits format, so aem is always required
|
||||
@@ -658,7 +699,7 @@ void GSRendererDX11::EmulateTextureSampler(const GSTextureCache::Source* tex)
|
||||
}
|
||||
|
||||
// Depth format
|
||||
if (tex->m_texture->GetType() == GSTexture::DepthStencil)
|
||||
if (tex->m_texture->GetType() == GSTexture::Type::DepthStencil)
|
||||
{
|
||||
// Require a float conversion if the texure is a depth format
|
||||
m_ps_sel.depth_fmt = (psm.bpp == 16) ? 2 : 1;
|
||||
@@ -848,10 +889,10 @@ void GSRendererDX11::DrawPrims(GSTexture* rt, GSTexture* ds, GSTextureCache::Sou
|
||||
{
|
||||
const GSVector4 dRect(ComputeBoundingBox(rtscale, rtsize));
|
||||
const GSVector4 sRect = dRect / GSVector4(rtsize.x, rtsize.y).xyxy();
|
||||
hdr_rt = dev->CreateRenderTarget(rtsize.x, rtsize.y, DXGI_FORMAT_R32G32B32A32_FLOAT);
|
||||
hdr_rt = dev->CreateRenderTarget(rtsize.x, rtsize.y, GSTexture::Format::FloatColor);
|
||||
// Warning: StretchRect must be called before BeginScene otherwise
|
||||
// vertices will be overwritten. Trust me you don't want to do that.
|
||||
dev->StretchRect(rt, sRect, hdr_rt, dRect, ShaderConvert_COPY, false);
|
||||
dev->StretchRect(rt, sRect, hdr_rt, dRect, ShaderConvert::COPY, false);
|
||||
}
|
||||
|
||||
if (m_ps_sel.dfmt == 1)
|
||||
@@ -1138,7 +1179,7 @@ void GSRendererDX11::DrawPrims(GSTexture* rt, GSTexture* ds, GSTextureCache::Sou
|
||||
{
|
||||
const GSVector4 dRect(ComputeBoundingBox(rtscale, rtsize));
|
||||
const GSVector4 sRect = dRect / GSVector4(rtsize.x, rtsize.y).xyxy();
|
||||
dev->StretchRect(hdr_rt, sRect, rt, dRect, ShaderConvert_MOD_256, false);
|
||||
dev->StretchRect(hdr_rt, sRect, rt, dRect, ShaderConvert::MOD_256, false);
|
||||
|
||||
dev->Recycle(hdr_rt);
|
||||
}
|
||||
|
||||
@@ -15,8 +15,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "GSDevice11.h"
|
||||
#include "GS/Renderers/HW/GSRendererHW.h"
|
||||
#include "GSTextureCache11.h"
|
||||
#include "GS/Renderers/HW/GSVertexHW.h"
|
||||
|
||||
class GSRendererDX11 final : public GSRendererHW
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
#include "GSTexture11.h"
|
||||
#include "GS/GSPng.h"
|
||||
|
||||
GSTexture11::GSTexture11(wil::com_ptr_nothrow<ID3D11Texture2D> texture)
|
||||
GSTexture11::GSTexture11(wil::com_ptr_nothrow<ID3D11Texture2D> texture, GSTexture::Format format)
|
||||
: m_texture(std::move(texture)), m_layer(0)
|
||||
{
|
||||
ASSERT(m_texture);
|
||||
@@ -31,15 +31,15 @@ GSTexture11::GSTexture11(wil::com_ptr_nothrow<ID3D11Texture2D> texture)
|
||||
m_size.y = (int)m_desc.Height;
|
||||
|
||||
if (m_desc.BindFlags & D3D11_BIND_RENDER_TARGET)
|
||||
m_type = RenderTarget;
|
||||
m_type = Type::RenderTarget;
|
||||
else if (m_desc.BindFlags & D3D11_BIND_DEPTH_STENCIL)
|
||||
m_type = DepthStencil;
|
||||
m_type = Type::DepthStencil;
|
||||
else if (m_desc.BindFlags & D3D11_BIND_SHADER_RESOURCE)
|
||||
m_type = Texture;
|
||||
m_type = Type::Texture;
|
||||
else if (m_desc.Usage == D3D11_USAGE_STAGING)
|
||||
m_type = Offscreen;
|
||||
m_type = Type::Offscreen;
|
||||
|
||||
m_format = (int)m_desc.Format;
|
||||
m_format = format;
|
||||
|
||||
m_max_layer = m_desc.MipLevels;
|
||||
}
|
||||
@@ -168,7 +168,7 @@ bool GSTexture11::Save(const std::string& fn)
|
||||
|
||||
res->GetDesc(&desc);
|
||||
|
||||
#ifdef ENABLE_OGL_DEBUG
|
||||
#ifdef PCSX2_DEVBUILD
|
||||
GSPng::Format format = GSPng::RGB_A_PNG;
|
||||
#else
|
||||
GSPng::Format format = GSPng::RGB_PNG;
|
||||
|
||||
@@ -34,7 +34,7 @@ class GSTexture11 : public GSTexture
|
||||
int m_max_layer;
|
||||
|
||||
public:
|
||||
explicit GSTexture11(wil::com_ptr_nothrow<ID3D11Texture2D> texture);
|
||||
explicit GSTexture11(wil::com_ptr_nothrow<ID3D11Texture2D> texture, GSTexture::Format format);
|
||||
|
||||
bool Update(const GSVector4i& r, const void* data, int pitch, int layer = 0);
|
||||
bool Map(GSMap& m, const GSVector4i* r = NULL, int layer = 0);
|
||||
|
||||
@@ -1,137 +0,0 @@
|
||||
/* 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/>.
|
||||
*/
|
||||
|
||||
#include "PrecompiledHeader.h"
|
||||
#include "GSTextureCache11.h"
|
||||
|
||||
// GSTextureCache11
|
||||
|
||||
GSTextureCache11::GSTextureCache11(GSRenderer* r)
|
||||
: GSTextureCache(r)
|
||||
{
|
||||
}
|
||||
|
||||
void GSTextureCache11::Read(Target* t, const GSVector4i& r)
|
||||
{
|
||||
if (!t->m_dirty.empty() || r.width() == 0 || r.height() == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const GIFRegTEX0& TEX0 = t->m_TEX0;
|
||||
|
||||
DXGI_FORMAT format;
|
||||
int ps_shader;
|
||||
switch (TEX0.PSM)
|
||||
{
|
||||
case PSM_PSMCT32:
|
||||
case PSM_PSMCT24:
|
||||
format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
ps_shader = ShaderConvert_COPY;
|
||||
break;
|
||||
|
||||
case PSM_PSMCT16:
|
||||
case PSM_PSMCT16S:
|
||||
format = DXGI_FORMAT_R16_UINT;
|
||||
ps_shader = ShaderConvert_RGBA8_TO_16_BITS;
|
||||
break;
|
||||
|
||||
case PSM_PSMZ32:
|
||||
case PSM_PSMZ24:
|
||||
format = DXGI_FORMAT_R32_UINT;
|
||||
ps_shader = ShaderConvert_FLOAT32_TO_32_BITS;
|
||||
break;
|
||||
|
||||
case PSM_PSMZ16:
|
||||
case PSM_PSMZ16S:
|
||||
format = DXGI_FORMAT_R16_UINT;
|
||||
ps_shader = ShaderConvert_FLOAT32_TO_32_BITS;
|
||||
break;
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
// printf("GSRenderTarget::Read %d,%d - %d,%d (%08x)\n", r.left, r.top, r.right, r.bottom, TEX0.TBP0);
|
||||
|
||||
int w = r.width();
|
||||
int h = r.height();
|
||||
|
||||
GSVector4 src = GSVector4(r) * GSVector4(t->m_texture->GetScale()).xyxy() / GSVector4(t->m_texture->GetSize()).xyxy();
|
||||
|
||||
if (GSTexture* offscreen = m_renderer->m_dev->CopyOffscreen(t->m_texture, src, w, h, format, ps_shader))
|
||||
{
|
||||
GSTexture::GSMap m;
|
||||
|
||||
if (offscreen->Map(m))
|
||||
{
|
||||
// TODO: block level write
|
||||
|
||||
GSOffset off = m_renderer->m_mem.GetOffset(TEX0.TBP0, TEX0.TBW, TEX0.PSM);
|
||||
|
||||
switch (TEX0.PSM)
|
||||
{
|
||||
case PSM_PSMCT32:
|
||||
case PSM_PSMZ32:
|
||||
m_renderer->m_mem.WritePixel32(m.bits, m.pitch, off, r);
|
||||
break;
|
||||
case PSM_PSMCT24:
|
||||
case PSM_PSMZ24:
|
||||
m_renderer->m_mem.WritePixel24(m.bits, m.pitch, off, r);
|
||||
break;
|
||||
case PSM_PSMCT16:
|
||||
case PSM_PSMCT16S:
|
||||
case PSM_PSMZ16:
|
||||
case PSM_PSMZ16S:
|
||||
m_renderer->m_mem.WritePixel16(m.bits, m.pitch, off, r);
|
||||
break;
|
||||
|
||||
default:
|
||||
ASSERT(0);
|
||||
}
|
||||
|
||||
offscreen->Unmap();
|
||||
}
|
||||
|
||||
m_renderer->m_dev->Recycle(offscreen);
|
||||
}
|
||||
}
|
||||
|
||||
void GSTextureCache11::Read(Source* t, const GSVector4i& r)
|
||||
{
|
||||
// FIXME: copy was copyied from openGL. It is unlikely to work.
|
||||
|
||||
const GIFRegTEX0& TEX0 = t->m_TEX0;
|
||||
|
||||
if (GSTexture* offscreen = m_renderer->m_dev->CreateOffscreen(r.width(), r.height()))
|
||||
{
|
||||
m_renderer->m_dev->CopyRect(t->m_texture, offscreen, r);
|
||||
|
||||
GSTexture::GSMap m;
|
||||
GSVector4i r_offscreen(0, 0, r.width(), r.height());
|
||||
|
||||
if (offscreen->Map(m, &r_offscreen))
|
||||
{
|
||||
GSOffset off = m_renderer->m_mem.GetOffset(TEX0.TBP0, TEX0.TBW, TEX0.PSM);
|
||||
|
||||
m_renderer->m_mem.WritePixel32(m.bits, m.pitch, off, r);
|
||||
|
||||
offscreen->Unmap();
|
||||
}
|
||||
|
||||
// FIXME invalidate data
|
||||
m_renderer->m_dev->Recycle(offscreen);
|
||||
}
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
/* 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 "GS/Renderers/HW/GSTextureCache.h"
|
||||
#include "GSDevice11.h"
|
||||
|
||||
class GSTextureCache11 : public GSTextureCache
|
||||
{
|
||||
protected:
|
||||
int Get8bitFormat() { return DXGI_FORMAT_A8_UNORM; }
|
||||
|
||||
void Read(Target* t, const GSVector4i& r);
|
||||
void Read(Source* t, const GSVector4i& r);
|
||||
|
||||
public:
|
||||
GSTextureCache11(GSRenderer* r);
|
||||
};
|
||||
@@ -114,10 +114,7 @@ void GSDevice11::SetupVS(VSSelector sel, const VSConstantBuffer* cb)
|
||||
};
|
||||
|
||||
GSVertexShader11 vs;
|
||||
|
||||
std::vector<char> shader;
|
||||
theApp.LoadResource(IDR_TFX_FX, shader);
|
||||
CreateShader(shader, "tfx.fx", nullptr, "vs_main", sm.GetPtr(), &vs.vs, layout, std::size(layout), vs.il.put());
|
||||
CreateShader(m_tfx_source, "tfx.fx", nullptr, "vs_main", sm.GetPtr(), &vs.vs, layout, std::size(layout), vs.il.put());
|
||||
|
||||
m_vs[sel] = vs;
|
||||
|
||||
@@ -157,9 +154,7 @@ void GSDevice11::SetupGS(GSSelector sel, const GSConstantBuffer* cb)
|
||||
sm.AddMacro("GS_POINT", sel.point);
|
||||
sm.AddMacro("GS_LINE", sel.line);
|
||||
|
||||
std::vector<char> shader;
|
||||
theApp.LoadResource(IDR_TFX_FX, shader);
|
||||
CreateShader(shader, "tfx.fx", nullptr, "gs_main", sm.GetPtr(), gs.put());
|
||||
CreateShader(m_tfx_source, "tfx.fx", nullptr, "gs_main", sm.GetPtr(), gs.put());
|
||||
|
||||
m_gs[sel] = gs;
|
||||
}
|
||||
@@ -218,10 +213,7 @@ void GSDevice11::SetupPS(PSSelector sel, const PSConstantBuffer* cb, PSSamplerSe
|
||||
sm.AddMacro("PS_ZCLAMP", sel.zclamp);
|
||||
|
||||
wil::com_ptr_nothrow<ID3D11PixelShader> ps;
|
||||
|
||||
std::vector<char> shader;
|
||||
theApp.LoadResource(IDR_TFX_FX, shader);
|
||||
CreateShader(shader, "tfx.fx", nullptr, "ps_main", sm.GetPtr(), ps.put());
|
||||
CreateShader(m_tfx_source, "tfx.fx", nullptr, "ps_main", sm.GetPtr(), ps.put());
|
||||
|
||||
i = m_ps.try_emplace(sel, std::move(ps)).first;
|
||||
}
|
||||
@@ -351,6 +343,8 @@ void GSDevice11::SetupOM(OMDepthStencilSelector dssel, OMBlendSelector bsel, u8
|
||||
bd.RenderTarget[0].SrcBlend = D3D11_BLEND_ONE;
|
||||
bd.RenderTarget[0].DestBlend = D3D11_BLEND_ONE;
|
||||
}
|
||||
else if (bsel.blend_mix)
|
||||
bd.RenderTarget[0].SrcBlend = D3D11_BLEND_ONE;
|
||||
}
|
||||
|
||||
if (bsel.wr) bd.RenderTarget[0].RenderTargetWriteMask |= D3D11_COLOR_WRITE_ENABLE_RED;
|
||||
|
||||
@@ -885,20 +885,6 @@ bool GSC_GodOfWar(const GSFrameInfo& fi, int& skip)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GSC_SoTC(const GSFrameInfo& fi, int& skip)
|
||||
{
|
||||
// Not needed anymore? What did it fix anyway? (rama)
|
||||
if (skip == 0)
|
||||
{
|
||||
if (fi.TME /*&& fi.FBP == 0x03d80*/ && fi.FPSM == 0 && fi.TBP0 == 0x03fc0 && fi.TPSM == 1)
|
||||
{
|
||||
skip = 48; // Removes sky bloom
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GSC_FFXGames(const GSFrameInfo& fi, int& skip)
|
||||
{
|
||||
if (skip == 0)
|
||||
@@ -1103,7 +1089,6 @@ void GSState::SetupCrcHack()
|
||||
lut[CRC::FFXII] = GSC_FFXGames;
|
||||
lut[CRC::RedDeadRevolver] = GSC_RedDeadRevolver;
|
||||
lut[CRC::ShinOnimusha] = GSC_ShinOnimusha;
|
||||
lut[CRC::SoTC] = GSC_SoTC;
|
||||
lut[CRC::XenosagaE3] = GSC_XenosagaE3;
|
||||
|
||||
// Upscaling issues
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user