Compare commits

...
101 Commits
Author SHA1 Message Date
Connor McLaughlin fac171fa95 CDVD: Check file actually opened before proceeding
If you loaded an invalid file, particularly with compression, the file
open may fail, leading to a division by zero (on block size), or trying
to read from nothing.
2021-12-18 13:41:56 +00:00
refractionpcsx2 fa1b6493da CDVD GZip: Correct type causing index creation to fail 2021-12-17 11:46:31 +00:00
refractionpcsx2 e58766745c Log: Restore BIOS Found message 2021-12-16 11:45:12 +00:00
Mrlinkwii d8a9c5b479 Gamedb add gamefixes to 'Titeuf Mega-compet' and patch 'Yamiyo ni Sasayaku - Tantei Sagara Kyouichirou' series 2021-12-15 17:17:18 +00:00
Mrlinkwii 9a4d8ba934 Gamedb: add more 2k games patches 2021-12-15 10:52:22 +00:00
refractionpcsx2 ab816543c8 CDVD: Fixed typo opening gzip files
Fixes #5162
2021-12-15 09:38:04 +00:00
refractionpcsx2 37ccd81985 GS: Avoid some unnecessary flushes
CLUT only updates if valid index type used in PSM
2021-12-14 18:28:21 +00:00
refractionpcsx2 42dad4ade8 GS: Check CLUT dirty write on vertex kick 2021-12-14 18:28:21 +00:00
refractionpcsx2 b2ac035862 VS: Fix location of shaders in project 2021-12-14 17:47:53 +00:00
refractionpcsx2 f42d7eec74 CDVD: Don't set as Reading when buffering. 2021-12-14 10:35:12 +00:00
refractionpcsx2 e4ef41f86a CDVD: Fix some read timing logic 2021-12-14 10:35:12 +00:00
Mrlinkwii 103dd3954a missing UI and game elements. 2021-12-14 09:22:31 +00:00
Tokman5 2f9577a28e Add "Jikkyou Powerful Pro Yakyuu 2009" to GameIndex.yaml 2021-12-14 08:06:34 +00:00
Gauvain 'GovanifY' Roussel-Tarbouriech 33ec4d9430 msvc: fix issues with size() not being correctly evaluated as const 2021-12-13 09:34:24 +00:00
Gauvain 'GovanifY' Roussel-Tarbouriech 209f09ca7a pine: send serial without gui beautification 2021-12-13 09:34:24 +00:00
Gauvain 'GovanifY' Roussel-Tarbouriech 2e6af75f1d pine: add vle replies 2021-12-13 09:34:24 +00:00
Gauvain 'GovanifY' Roussel-Tarbouriech f68122a380 ipc: rename to pine 2021-12-13 09:34:24 +00:00
TellowKrinkle d51bdccf7f CMake: Remove gio dependency on macOS 2021-12-13 03:29:16 -06:00
iMineLink 7d8377b133 GS-hw: define some consts only in debug mode. 2021-12-13 08:06:52 +01:00
iMineLink 80d3a8a757 GS-hw, TC: don't linearly interpolate downloads.
Greatly improves Burnout games clouds rendering
with even (x2, x4, ...) upscaling factors.
2021-12-13 08:06:52 +01:00
iMineLink 2e6c5cde29 GS-hw: rework surface fetching.
Factorized code.
Always clear render targets and depth stencils
when being fetched.
"force_texture_clear" OGL only config removed.
2021-12-13 08:06:52 +01:00
iMineLink 0f2768dca4 GS-hw, TC: improve LookupTarget.
allow propagation of increased target size and
correct the rescaling.
2021-12-13 08:06:52 +01:00
iMineLink d5be095482 GS-hw: fix burnout black sky and no clouds.
Achieved with a combination of OI+OO hacks that operate
during level loading to consolidate the rendering results
in the GS local memory.

* OI_BurnoutGames to perform small draws directly in local memory:
** improved OI_PointListPalette to draw clouds CLUT,
** improved SwSpriteRender to draw sky texture;
* OO_BurnoutGames used to download clouds texture from GPU.
2021-12-13 08:06:52 +01:00
iMineLink b315625a94 GS-hw: resize rt and ds before draw if necessary. 2021-12-13 08:06:52 +01:00
iMineLink 6b51462fa0 GS-hw: use CanUpscale to check for upscaling. 2021-12-13 08:06:52 +01:00
iMineLink 373e698545 GS-hw, TC: fix tex scaling for native res draws.
The GSTextureCache::ScaleTexture method did not work
correctly when an old texture with a scale factor
different from 1 was recycled for a draw which was forced at
native resolution (the old scale factor was kept).
2021-12-13 08:06:52 +01:00
iMineLink 3b309c6d4e GS: dump alpha channel too. 2021-12-13 08:06:52 +01:00
kenshen112 8e93e9f516 CMake: Switch Wayland find script and usage to use imported targets
Also clears warning about mismatched names getting sent to FIND_PACKAGE_HANDLE_STANDARD_ARGS
2021-12-13 00:23:52 -06:00
kenshen112 ac8582eca7 CMake: Set minimum version first
Makes policy enabling based on minimum version work properly
Also increases minimum version to 3.11 because we actually do use 3.11 features
2021-12-13 00:23:52 -06:00
kenshen112 e6f72fdde7 GHActions: Enable Wayland in CI builds 2021-12-13 00:23:52 -06:00
Connor McLaughlin 9166218d07 EERec: Remove zero-distance jmp in full fpu mode 2021-12-13 00:56:50 +00:00
Mrlinkwii c0b1bde94b Gamedb: add EEclamping to 'Dark cloud 2' 2021-12-12 22:31:30 +00:00
Mrlinkwii 756a679262 Gamdb:add EE clamping to 'Chou Saisoku! Zokusha King B.U.' 2021-12-12 21:35:54 +00:00
Mrlinkwii 13b19b35c0 GameDB: add patches to the 'Netsu Chu!' series and 'Samurai 7' series 2021-12-12 18:16:46 +00:00
Mrlinkwii cadb70d1e4 Gamedb: add EEtiminghack to 'MGS2' and change VU and EE rounding for 'Primal' and add missing entries 2021-12-12 12:30:47 +00:00
TellowKrinkle 4cb4844e8d AppImage: Fix resource location 2021-12-12 06:10:47 -06:00
TellowKrinkle 556c7ca080 CMake: Don't include non-windows files on non-windows 2021-12-12 06:10:47 -06:00
TellowKrinkle 962db4bfc4 Resources: Move fxaa.fx to out of dx11 directory
It was used by both DX and OGL
2021-12-12 06:10:47 -06:00
TellowKrinkle da651cabe4 Resources: Move shaders to shared shader/ directory 2021-12-12 06:10:47 -06:00
TellowKrinkle e03076c6ff CMake: Fix macOS resource packaging
Previously was just putting in empty folders
2021-12-12 06:10:47 -06:00
refractionpcsx2 122968e63a CDVD: No rotational delay for seeks less than buffered sectors
Fixes Shadow Hearts Covenant hangs
2021-12-12 06:33:01 +00:00
Connor McLaughlin 6beac26727 GS/OpenGL: Fix an unused variable warning 2021-12-12 03:27:43 +00:00
Connor McLaughlin 3073281d13 CMake: Fix package mode 2021-12-12 03:27:43 +00:00
TellowKrinkle 0e0e23eefb PAD: Use files on disk instead of embedded resources 2021-12-12 03:27:43 +00:00
Connor McLaughlin bcec38bd97 Patch: Make variables static 2021-12-12 03:27:43 +00:00
Connor McLaughlin bd706f99b2 GlobalCommands: Remove FreezeGS
This was ifdefed out anyway...
2021-12-12 03:27:43 +00:00
Connor McLaughlin 501af632f7 IopBios: Use FileSystem for host access 2021-12-12 03:27:43 +00:00
Connor McLaughlin a143122804 CI: Copy resources into AppImage 2021-12-12 03:27:43 +00:00
Connor McLaughlin 92aa426bba Move cheats_ws.zip to resources directory 2021-12-12 03:27:43 +00:00
Connor McLaughlin 96a1ce2fb2 CI: Fix path to GameIndex.yaml 2021-12-12 03:27:43 +00:00
Connor McLaughlin c203a09435 Wx: Add check for resources directory before starting 2021-12-12 03:27:43 +00:00
Connor McLaughlin c4084b4162 Add PerformanceMetrics to replace multiple sources of truth 2021-12-12 03:27:43 +00:00
Connor McLaughlin 2a7c948a57 GameDatabase: Store enums instead of strings 2021-12-12 03:27:43 +00:00
Connor McLaughlin 46912595ea GameDatabase: Move out of gui 2021-12-12 03:27:43 +00:00
Connor McLaughlin 120ee6c673 Get rid of wxChar in EnumToString 2021-12-12 03:27:43 +00:00
Connor McLaughlin 112238fbd7 Config: Add cache folder 2021-12-12 03:27:43 +00:00
Connor McLaughlin 38e288ef6a Common: Add utility classes 2021-12-12 03:27:43 +00:00
Connor McLaughlin 35322cf49b BiosTools: Add autoloader 2021-12-12 03:27:43 +00:00
Connor McLaughlin 8d44e1af0e CDVD: Remove wx from file access 2021-12-12 03:27:43 +00:00
Connor McLaughlin 16af078b3b BiosTools: Remove wx 2021-12-12 03:27:43 +00:00
Connor McLaughlin 3e968b4390 GS: Use files on disk instead of embedded resources 2021-12-12 03:27:43 +00:00
Connor McLaughlin 0029dac32d Host: Add the ability to read files from the resources directory 2021-12-12 03:27:43 +00:00
Connor McLaughlin a083343c6e Common: Add FileSystem 2021-12-12 03:27:43 +00:00
refractionpcsx2 c277ee1d34 GS: D3D11 Download texture use rect 2021-12-10 11:06:36 +00:00
refractionpcsx2 ebe8592a8d GS: Fix typo on GS download
Fixes #5131
2021-12-10 09:49:50 +00:00
lightningterror 6c3e357d9e GS-ogl: Optimize fragment shader uniform buffer.
Couple MaxDepthPS with TA and Af vector.

Vectors are free so let's use them.

Optimization.
2021-12-10 03:44:47 +01:00
TellowKrinkle 64455620e8 GS: Use actual names for GL convert shaders 2021-12-09 05:26:26 -06:00
TellowKrinkle fc799778de GS: Use actual names for DX11 convert shaders 2021-12-09 05:26:26 -06:00
TellowKrinkle e04e0e38d1 GS:GL: Move TextureOffset to vs cb
It's used by the vs, why would you put it in the ps cb?
2021-12-09 05:26:26 -06:00
TellowKrinkle 8d6569be95 GS: Remove separate GSTextureCaches 2021-12-09 05:26:26 -06:00
TellowKrinkle 8b086a3898 Common: Clean up ScopedAlloc 2021-12-09 05:26:26 -06:00
TellowKrinkle a4b8c33cf3 GS: Convert texture format to enum 2021-12-09 05:26:26 -06:00
TellowKrinkle 1d37ba47f4 GS: Make GSTexture::Type an enum class 2021-12-09 05:26:26 -06:00
TellowKrinkle 8d480c28ce GS: Remove unused virtuals from GSDevice 2021-12-09 05:26:26 -06:00
TellowKrinkle 6e38f40f96 GS: Convert ShaderConvert to enum class 2021-12-09 05:26:26 -06:00
arcum42 017c37f212 Only pass C++ flags to C++ files. (#5115) 2021-12-08 21:10:21 -08:00
TellowKrinkle 6eee4cb38a Core: Remove empty file
Had everything commented out and there's already a file with the same name and things not commented out in CDVD
2021-12-08 11:18:42 +00:00
TellowKrinkle 1f6a14261c VS: Add missing filters 2021-12-08 11:18:42 +00:00
refractionpcsx2 14e8d840ff GS SW: Handle flat prims without float conversion 2021-12-08 10:57:00 +00:00
lightningterror 125b9ea1e1 GS-hw: Purge SoTC crc hack.
No longer needed, fixed by #5110
2021-12-08 11:48:29 +01:00
lightningterror e6b1e1948e GS-d3d11: Add a condition to not enable blend_mix if sw blending is already enabled.
Not yet needed but will be useful for sw blending when prims don't overlap.
2021-12-08 11:36:22 +01:00
lightningterror ba1072f470 GS-ogl: Don't enable blend_mix if sw blend is already enabled.
Less accurate.
2021-12-08 11:36:22 +01:00
lightningterror 1fb29de082 GS-ogl: Try to use a mix of hw/sw blending in more situations.
When alpha is less than 128:
Do Cs*F or Cs*As in shader.
Do Cs*(As + 1) or Cs*(F + 1) in shader.
Do Cs*(1 - As) or Cs*(1 - F) in shader.

Optimization, might be faster as we will require less barriers.
2021-12-08 11:36:22 +01:00
lightningterror f79e5ab559 GS-d3d11: Try to use a mix of hw/sw blending in more situations.
When alpha is less than 128:
Do Cs*F or Cs*As in shader.
Do Cs*(As + 1) or Cs*(F + 1) in shader.
Do Cs*(1 - As) or Cs*(1 - F) in shader.
2021-12-08 11:36:22 +01:00
Mrlinkwii c3a9fd469e GameDB: add VU clamping to 'MVP Baseball 2003' 2021-12-08 10:29:05 +00:00
Mrlinkwii c8abc909fa GameDB:add EEclamping full to 'Shinobido Takumi' 2021-12-07 20:00:15 +00:00
Mrlinkwii 401a9f4c62 GameDB: add patches to the 'K-1 World' series games and EE clamping full to 'D1 Professional Drift Grand Prix Series' 2021-12-07 15:51:13 +00:00
lightningterror f1edb0c960 GS-ogl: Disable accumulation blend on PABE.
Requires accurate sw blending.
2021-12-07 10:12:58 +01:00
lightningterror d73335e4d3 GS-d3d11: Don't enable PABE on accumulation blend.
Requires full sw blending.
2021-12-07 10:11:02 +01:00
TellowKrinkle 7a554be7a7 GS: Fix compiler warning and possible memory leak on exception 2021-12-06 05:44:16 +01:00
TellowKrinkle 31b6ff6046 GS: Use static_assert over assert where possible 2021-12-06 05:44:16 +01:00
lightningterror 38ab0630e6 GS-ogl: Update SetupCBMisc buffer only when GXBY channel is used, and cleanup some variables.
Optimization.
2021-12-06 03:15:48 +01:00
lightningterror b5fa9deb30 GS-d3d11: Update ChannelShuffle buffer only when GXBY channel is used, and cleanup some variables.
Optimization.
2021-12-06 03:15:48 +01:00
lightningterror 4e8bae1703 GS-ogl: Sample depth on green channel. 2021-12-06 03:15:48 +01:00
lightningterror 464ce1c3cd GS-d3d11: Sample depth on green channel. 2021-12-06 03:15:48 +01:00
lightningterror bb55c320c1 GS Debugger: Fix Length of dump. 2021-12-05 10:57:24 +01:00
TheLastRar af585bffa9 DEV9: Add DEV9: prefix to "Can't open Device" log message 2021-12-05 03:53:33 +01:00
TheLastRar bde4868b67 DEV9: Enable pcap non-blocking 2021-12-05 03:53:33 +01:00
TheLastRar 3835fc5ad1 DEV9: Don't shadow return value of GetAdaptersAddresses 2021-12-04 06:09:01 +01:00
Tyler Wilding 7b815b5f07 actions: increase linux build times as well until cache is reliable
We can rely on the cache more once the following issue is resolved - https://github.com/actions/cache/issues/342#issuecomment-673371329

Once we can, we should be able to dynamically set the timeout according to the cache-hit/miss
2021-12-04 06:05:38 +01:00
Tyler Wilding 754c6126b1 actions: Only announce pre-release releases in the discord 2021-12-04 05:57:05 +01:00
186 changed files with 5880 additions and 3707 deletions
+1 -1
View File
@@ -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 }}
+1 -1
View File
@@ -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
+1 -2
View File
@@ -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!
+1
View File
@@ -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
View File
@@ -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;")
-2
View File
@@ -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);
@@ -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;
+6 -4
View File
@@ -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
View File
@@ -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
+1 -5
View File
@@ -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)
+1 -1
View File
@@ -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)
{
+39 -132
View File
@@ -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[];
};
+7 -1
View File
@@ -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
+2 -2
View File
@@ -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
+162
View File
@@ -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
+2
View File
@@ -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);
+15
View File
@@ -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)
+248
View File
@@ -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);
}
+105
View File
@@ -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;
};
+2 -2
View File
@@ -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
// --------------------------------------------------------------------------------------
+347
View File
@@ -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
+94
View File
@@ -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
+9 -3
View File
@@ -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>
+33 -6
View File
@@ -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">
+6 -8
View File
@@ -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
View File
@@ -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);
+27 -27
View File
@@ -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
View File
@@ -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
View File
@@ -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();
+1 -1
View File
@@ -52,7 +52,7 @@ s32 CALLBACK ISOopen(const char* pTitle)
try
{
iso.Open(fromUTF8(pTitle));
iso.Open(pTitle);
}
catch (BaseException& ex)
{
+69 -38
View File
@@ -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;
+5 -3
View File
@@ -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;
};
+3 -3
View File
@@ -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++)
{
+8 -8
View File
@@ -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
+12 -4
View File
@@ -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();
}
+2 -1
View File
@@ -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;
-44
View File
@@ -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 //////////
+18 -18
View File
@@ -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;
+2 -2
View File
@@ -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;
+66 -74
View File
@@ -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);
+5 -5
View File
@@ -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();
};
+7 -9
View File
@@ -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;
+9 -9
View File
@@ -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);
+25 -16
View File
@@ -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
+2 -2
View File
@@ -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)
+2 -2
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
/////////////////////////////////////////////////////////////////////////////////////////
+3
View File
@@ -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
View File
@@ -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))
{
+4 -3
View File
@@ -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
View File
@@ -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);
-91
View File
@@ -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
-14
View File
@@ -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
-59
View File
@@ -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
+6
View File
@@ -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
View File
@@ -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);
}
+1 -1
View File
@@ -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
View File
@@ -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);
}
+7 -2
View File
@@ -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)
+134 -62
View File
@@ -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
+52 -42
View File
@@ -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);
+7 -5
View File
@@ -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)
{
+1 -1
View File
@@ -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;
};
+10 -11
View File
@@ -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();
}
}
}
+1
View File
@@ -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);
+2 -2
View File
@@ -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)
+27 -13
View File
@@ -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);
+88 -83
View File
@@ -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());
+19 -15
View File
@@ -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);
};
+56 -15
View File
@@ -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);
}
+1 -1
View File
@@ -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
+7 -7
View File
@@ -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;
+1 -1
View File
@@ -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);
};
+5 -11
View File
@@ -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;
-15
View File
@@ -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