diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f553ba7..34c8dce 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -4,7 +4,6 @@ on: push: branches: - 'master' - - 'develop' - 'github-action' jobs: @@ -69,6 +68,8 @@ jobs: - name: Prepare artifact run: | : + + mkdir -p cnc-ddraw-experimental if [[ -f "${{ steps.build-release.outputs.release }}" ]]; then mkdir -p cnc-ddraw-release @@ -80,6 +81,11 @@ jobs: mkdir -p cnc-ddraw-releasexp cp "${{ steps.build-releasexp.outputs.releasexp }}" cnc-ddraw-releasexp + + rundll32.exe ./cnc-ddraw-releasexp/ddraw.dll, DDIsWindowed + + cp "${{ steps.build-releasexp.outputs.releasexp-pdb }}" cnc-ddraw-experimental + 7z a -tzip -mm=Deflate -mfb=258 -mpass=15 "./cnc-ddraw-experimental/cnc-ddraw-experimental-release.zip" "./cnc-ddraw-releasexp/ddraw.*" fi if [[ -f "${{ steps.build-debug.outputs.debug }}" ]]; then @@ -94,6 +100,8 @@ jobs: cp "${{ steps.build-debuglogxp.outputs.debuglogxp }}" cnc-ddraw-debuglogxp cp "${{ steps.build-debuglogxp.outputs.debuglogxp-pdb }}" cnc-ddraw-debuglogxp + + 7z a -tzip -mm=Deflate -mfb=258 -mpass=15 "./cnc-ddraw-experimental/cnc-ddraw-experimental-debuglog.zip" "./cnc-ddraw-debuglogxp/*" fi if [[ -f "${{ steps.build-debuglogminixp.outputs.debuglogminixp }}" ]]; then @@ -110,32 +118,37 @@ jobs: with: name: cnc-ddraw-release path: cnc-ddraw-release - retention-days: 14 - name: Upload artifacts cnc-ddraw-releasexp uses: actions/upload-artifact@v4 with: name: cnc-ddraw-releasexp path: cnc-ddraw-releasexp - retention-days: 14 - name: Upload artifacts cnc-ddraw-debug uses: actions/upload-artifact@v4 with: name: cnc-ddraw-debug path: cnc-ddraw-debug - retention-days: 14 - name: Upload artifacts cnc-ddraw-debuglogxp uses: actions/upload-artifact@v4 with: name: cnc-ddraw-debuglogxp path: cnc-ddraw-debuglogxp - retention-days: 14 - name: Upload artifacts cnc-ddraw-debuglogminixp uses: actions/upload-artifact@v4 with: name: cnc-ddraw-debuglogminixp path: cnc-ddraw-debuglogminixp - retention-days: 14 + + - name: Release experimental + uses: softprops/action-gh-release@v1 + with: + prerelease: true + name: experimental + tag_name: experimental + files: cnc-ddraw-experimental/* + fail_on_unmatched_files: true + draft: true diff --git a/.gitignore b/.gitignore index 158b71e..46accfc 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,6 @@ +inc/git.h + # C++ Builder __astcache/ diff --git a/Makefile b/Makefile index 3371861..c2f547b 100644 --- a/Makefile +++ b/Makefile @@ -1,28 +1,48 @@ -include config.mk -TARGET = ddraw.dll -LDFLAGS = -Wl,--enable-stdcall-fixup -s -static -shared -CFLAGS = -Iinc -O2 -march=i486 -Wall -LIBS = -lgdi32 -lwinmm -ldbghelp -lole32 +TARGET ?= ddraw.dll -CC = i686-w64-mingw32-gcc -WINDRES ?= i686-w64-mingw32-windres +LDFLAGS ?= -Wl,--enable-stdcall-fixup -s -static -shared +CFLAGS ?= -Iinc -O2 -Wall -std=c99 +LIBS = -lgdi32 -lwinmm -lole32 -lmsimg32 -lavifil32 -luuid + +COMMIT := $(shell git describe --match=NeVeRmAtCh --always --dirty || echo UNKNOWN) +BRANCH := $(shell git rev-parse --abbrev-ref HEAD || echo UNKNOWN) + +HASH := \# +ECHOTEST := $(shell echo \"\") +ifeq ($(ECHOTEST),\"\") + # Windows + ECOMMIT := $(shell echo $(HASH)define GIT_COMMIT "$(COMMIT)" > inc/git.h) + EBRANCH := $(shell echo $(HASH)define GIT_BRANCH "$(BRANCH)" >> inc/git.h) +else + # Either *nix or Windows with BusyBox (e.g. w64devkit) + ECOMMIT := $(shell echo "$(HASH)define GIT_COMMIT" \"$(COMMIT)\" > inc/git.h) + EBRANCH := $(shell echo "$(HASH)define GIT_BRANCH" \"$(BRANCH)\" >> inc/git.h) +endif ifdef DEBUG CFLAGS += -D _DEBUG -D _DEBUG_X endif -SRCS := $(wildcard src/*.c) $(wildcard src/*/*.c) -OBJS := $(SRCS:c=o) res.o +ifdef _WIN32_WINNT + CFLAGS += -march=i486 -D _WIN32_WINNT=$(_WIN32_WINNT) +endif + +CC = i686-w64-mingw32-gcc +WINDRES ?= i686-w64-mingw32-windres + +SRCS := $(wildcard src/*.c) $(wildcard src/*/*.c) res.rc +OBJS := $(addsuffix .o, $(basename $(SRCS))) .PHONY: clean all all: $(TARGET) %.o: %.rc - $(WINDRES) -J rc $< $@ + $(WINDRES) -J rc $< $@ || windres -J rc $< $@ $(TARGET): $(OBJS) $(CC) $(LDFLAGS) -o $@ $^ exports.def $(LIBS) clean: - $(RM) $(TARGET) $(OBJS) + $(RM) $(TARGET) $(OBJS) || del $(TARGET) $(subst /,\\,$(OBJS)) diff --git a/README.md b/README.md index 1659ea2..7485601 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,11 @@ # cnc-ddraw -cnc-ddraw can fix compatibility issues in older 2D games, such as black screen, bad performance, crashes or defective Alt+Tab. +cnc-ddraw can fix compatibility issues in older 2D games, such as black screen, bad performance, crashes or defective Alt+Tab. It does also add new features such as borderless mode, windowed mode and upscaling via shaders.   ### Features - - Supports Windows 2000, XP, Vista, 7, 8, 10, 11, Wine (Linux/macOS/Android) and Virtual Machines + - Supports Windows ME, 2000, XP, Vista, 7, 8, 10, 11, Wine (Linux/macOS/Android) and Virtual Machines - GDI / OpenGL / Direct3D 9 renderer (With automatic renderer selection) - Upscaling via glsl shaders - https://imgur.com/a/kxsM1oY | https://imgur.com/a/wjrhpFV - Windowed Mode / Fullscreen Exclusive Mode / Borderless Mode @@ -24,31 +24,16 @@ cnc-ddraw can fix compatibility issues in older 2D games, such as black screen, 1. Download [cnc-ddraw.zip](https://github.com/FunkyFr3sh/cnc-ddraw/releases/latest/download/cnc-ddraw.zip) and extract it into your game folder 2. Start the game -Wine (Linux/macOS/Android) only: override `ddraw` in [winecfg](https://wiki.winehq.org/Winecfg#Libraries) manually or run cnc-ddraw config.exe once. +Wine (Linux/macOS/Android) only: override `ddraw` in [winecfg](https://wiki.winehq.org/Winecfg#Libraries) manually or run `cnc-ddraw config.exe` once.   -If you use cnc-ddraw with a game that got its own windowed mode built in then **make sure you disable the games own windowed mode** first. You can enable windowed mode via cnc-ddraw config.exe instead. +**Important** -  - -**If the game starts but it doesn't work perfectly** then open the config program and check the **Compatibility settings**. - -  - -**cnc-ddraw does not support Direct3D/Glide**, it will only work with games that use a **DirectDraw (Software)** renderer. Usually you can tell by the look of the game if it's a 3D game or not, but you can also let cnc-ddraw generate a debug log and search for "IDirect3D" - Link: https://github.com/FunkyFr3sh/cnc-ddraw/issues/44 - -  - -Some games may require additional steps before they can be used with cnc-ddraw, please check the [wiki](https://github.com/FunkyFr3sh/cnc-ddraw/wiki) for more details. - -  - -**If the game doesn't start at all or it's crashing**, [then please generate a debug log file and upload it.](https://github.com/FunkyFr3sh/cnc-ddraw/issues/44) - -  - -Need help and don't have a github account? Ask your questions on [Discord](https://discord.gg/afWXJNDDF5) (No registration required) +- **The game must be set to fullscreen**. To enable windowed mode, use `cnc-ddraw config.exe` instead +- **cnc-ddraw does not support Direct3D games**, the game must have a **DirectDraw (Software)** renderer +- **If the game doesn't start at all or it's crashing**, [then please generate a debug log file and upload it.](https://github.com/FunkyFr3sh/cnc-ddraw/issues/44) +- Some games require additional steps before they can be used with cnc-ddraw, check the [wiki](https://github.com/FunkyFr3sh/cnc-ddraw/wiki) for details   @@ -61,6 +46,10 @@ Need help and don't have a github account? Ask your questions on [Discord](https   ### Supported Games +- 101: The Airborne Invasion of Normandy +- 7th Legion +- Abomination - The Nemesis Project +- Addiction Pinball - Age of Empires - Age of Empires II - Age of Empires II: The Conquerors @@ -68,14 +57,24 @@ Need help and don't have a github account? Ask your questions on [Discord](https - Age of Wonders - Age of Wonders 2 - Age of Wonders: Shadow Magic +- Agharta the Hollow Earth +- Airline 69: Return to Casablanca - Airline Tycoon Deluxe - Alien Nations - American Conquest (Steam+GOG) - American Girls Dress Designer - Amerzone +- Ancient Conquest +- Ancient Evil - Anno 1602: Creation of a New World +- Another War - Anstoss 3 - Arcanum: Of Steamworks and Magick Obscura +- Arcatera the Dark Brotherhood +- Army Men 2 +- Army Men: Air Tactics +- Army Men: Toys in Space +- Army Men: World War / Army Men: Operation Meltdown - Arthur's Pet Chase - Arthur's Sand Castle Contest - Arthur's Wilderness Rescue @@ -87,23 +86,31 @@ Need help and don't have a github account? Ask your questions on [Discord](https - Baldr Force EXE - Baldur's Gate - Baldur's Gate 2 -- Barbie(tm) Beach Vacation(tm) +- Balls of Steel v1.2 - Barbie(R) Photo Designer +- Barbie(tm) Beach Vacation(tm) - Batman: Justice Unbalanced - Batman: Toxic Chill +- Bejeweled 2 Deluxe +- Birthright: The Gorgons Alliance - Blade & Sword - Blood II - The Chosen - Blue's 123 Time Activities - Blue's Treasure Hunt +- Broken Sword +- Broken Sword 2: The Smoking Mirror - Caesar III (Sierra - 1998) - Call To Power 2 +- Callus 95 - CPS-1 (Capcom Play System 1) emulator - Capitalism II - Capitalism Lab - Captain Claw - Carmageddon - Carmageddon 2 - Casino Empire (AKA Hoyle Casino) +- Championship Manager 99-00 - Chaos Gate +- Clans - Close Combat 2: A Bridge Too Far - Close Combat 3: The Russian Front - Close Combat 4: The Battle of the Bulge @@ -127,24 +134,41 @@ Need help and don't have a github account? Ask your questions on [Discord](https - Commandos - Commandos - Beyond The Call Of Duty - Commandos 2 +- Commando 2004 (only with /ddraw command line parameter) +- Constructor - Corsairs Gold - Cossacks (Steam+GOG) - Cultures - The Discovery of Vinland - Cultures 2 +- Cyber Gladiators (needs CyberGladiators_Patch_Win_EN_WinXP.zip) - Cyberchase Carnival Chaos - Cyberchase Castleblanca Quest +- Cydonia Mars - The First Manned Mission +- Cloud Kingdom 3 (only with /ddraw command line parameter) +- Dark Earth - Dark Reign: The Future of War +- Dark Secret of Africa +- Day Of The Tentacle +- Daytona - Daytona USA (Sega - 1996) - Deadlock 2 +- Deadly Tide +- Delta Force - Desperados: Wanted Dead or Alive - Diablo - Diablo 2 - Diablo 2: Lord of Destruction - Diablo: Hellfire +- Die by the Sword - Disciples - Disciples 2 - Rise of the Elves +- Discoworld Noir - Divine Divinity +- Dominion - Storm Over Gift 3 +- Doom 95 +- Dracula - Dragon Throne: Battle of Red Cliffs +- Dreams to Realty - DuelSavior - DuelSavior: Justice - Dune 2000 @@ -155,13 +179,19 @@ Need help and don't have a github account? Ask your questions on [Discord](https - Emperor: Rise of the Middle Kingdom - Enemy Infestation - Escape Velocity Nova +- Excalibur 2555AD +- F-16 Agressor - F-16 Multirole Fighter - F-22 Raptor +- Fable - Fairy Tale About Father Frost, Ivan and Nastya +- Falcon 4.0 (Microprose version) - Fallout - Fallout 2 +- Fallout Tactics: Brotherhood of Steel - Final fantasy VII - Final fantasy VIII +- Final Liberation: Warhammer Epic 40000 (GOG) - Freddi Fish - Freddi Fish 4 - Freddi Fish's One-Stop Fun Shop @@ -170,24 +200,41 @@ Need help and don't have a github account? Ask your questions on [Discord](https - Freddi Fish: The Case of the Haunted Schoolhouse - Freddi Fish: The Case of the Hogfish Rustlers of Briny Gulch - Freddi Water Worries +- Full Throttle - Future Cop L.A.P.D - G-Police +- Gateway (Remake) +- Geneforge +- Gilbert Goodmate And The Mushroom Of Phungoria +- Gorasul: The Legacy of the Dragon - Grand Theft Auto - Grand Theft Auto: London 1961 - Grand Theft Auto: London 1969 +- Gromada Revenge - Gruntz -- Gorasul: The Legacy of the Dragon - Hamtaro: Wake Up Snoozer! +- Handkerchief - Hard Truck: Road to Victory +- Heart of Darkness - Hearts of Iron 2 +- Heroes Chronicles: Clash of the Dragons +- Heroes Chronicles: Conquest of the Underworld +- Heroes Chronicles: Masters of the Elements +- Heroes Chronicles: Warlords of the Wasteland +- Heroes of Might and Magic - Heroes of Might and Magic II - Heroes of Might and Magic III - Heroes of Might and Magic IV +- Hexen 95 - Hooligans: Storm over Europe - Hugo Gold - Hugo Wild River - Icewind Dale - Icewind Dale 2 +- Ignition +- Imperialism 2: The Age of Exploration +- Indiana Jones and the Fate of Atlantis +- Indiana Jones and the Last Crusade - Infantry Online - Interstate 76 - Invictus: In the Shadow of Olympus @@ -195,6 +242,8 @@ Need help and don't have a github account? Ask your questions on [Discord](https - Jagged Alliance 2: Unfinished Business - Jagged Alliance 2: Wildfire - Jazz Jackrabbit 2 +- Jeff Wayne's The War of the Worlds +- Karma Immortal Wrath - Killing Time - Kings Quest 8: Mask of Eternity - KKND Xtreme @@ -204,6 +253,10 @@ Need help and don't have a github account? Ask your questions on [Discord](https - Kohan: Immortal Sovereigns - Konung - Konung 2 +- Lands of Lore 2 Guardian of Destiny (Software mode only) +- Lapis (lapis.mgame.com) +- Last Bronx +- Links Extreme - Lionheart - Legacy of the Crusader - Little Bear Kindergarten Thinking Adventures - Little Bear Preschool Thinking Adventures @@ -211,17 +264,27 @@ Need help and don't have a github account? Ask your questions on [Discord](https - Little Bear Toddler Discovery Adventures - Locomotion - Lode Runner 2 +- Lost Vikings 2 +- M.A.X. 2 Mechanized Assault & Exploration - Madeline 1st Grade Math - Madeline 2nd Grade Math +- Mageslayer - Majesty Gold - Majesty Gold HD -- ​M.A.X. 2 Mechanized Assault & Exploration +- Mario Sorb 3 +- Meat Puppet - Mech Warrior 3 - Megaman X4 - Metal Gear Solid +- Metal Knight +- Mob Rule (AKA Constructor: Street Wars / Street Wars: Constructor Underworld) - Moorhuhn - Moorhuhn 2 +- Moorhuhn Adventure: Fluch des Goldes +- Moorhuhn Adventure: Schatz des Pharao and Fluch des Goldes) - Moorhuhn Winter Editon +- MiG-29 Fulcrum +- Mission Deliver Kindness - Moto Racer - Moto Racer 2 - Nancy Drew: Danger on Deception Island @@ -231,27 +294,37 @@ Need help and don't have a github account? Ask your questions on [Discord](https - Nancy Drew: Stay Tuned For Danger - Nancy Drew: The Secret of Shadow Ranch - Nancy Drew: Treasure in the Royal Tower +- NBA Action '98 +- NBA Full Court Press - Need For Speed III: Hot Pursuit - Need For Speed: High Stakes +- Neo Sonic Universe - New Robinson - NexusTk +- Nightmare Creatures +- Ninja Jonder Deluxe - Nox (Westwood - 2000) - Oddworld: Abe's Exoddus - Oddworld: Abe's Oddysee +- Original War - Outlaws - Outlive +- Outwars (software mode) - Pacific General - Pajama Sam - Pajama Sam 3 +- Pajama Sam 3: You Are What You Eat From Your Head To Your Feet - Pajama Sam's Games to Play on Any Day - Pajama Sam's One-Stop Fun Shop - Pajama Sam(r): Life is Rough When You Lose Your Stuff(tm) - Pajama Sam: No Need to Hide When It's Dark Outside -- Pajama Sam 3: You Are What You Eat From Your Head To Your Feet +- Pandora's Box Puzzle Game +- Panzer Dragoon - Patrician 3 - Pax Imperia - Pharaoh (Sierra - 1999) - Pizza Syndicate (AKA Fast Food Tycoon) +- Platypus - Populous: The Beginning - Poseidon: Master of Atlantis - Pro Pinball - Big Race USA @@ -264,6 +337,7 @@ Need help and don't have a github account? Ask your questions on [Discord](https - Putt-Putt: Pep's Birthday Surprise - Putt-Putt: Travels Through Time - Quest for Glory 5 +- Rage of Mages - Rage of Mages 2 - Railroad Tycoon II - Reader Rabbit 1st Grade @@ -279,15 +353,21 @@ Need help and don't have a github account? Ask your questions on [Discord](https - Reader Rabbit Thinking Ages 4-6 (US) - Reader Rabbit Toddler - Reader Rabbit's(R) Math Ages 6 - 9 (2002) +- Real War - Red Baron 3D -- Reksio and the Pirate Treasure (Reksio i Skarb Piratów) -- Reksio and the UFO (Reksio i Ufo) -- Reksio and the Wizards (Reksio i Czarodzieje) -- Reksio and the Time Machine (Reksio i Wehikuł Czasu) - Reksio and Captain Nemo (Reksio i Kapitan Nemo) - Reksio and Kretes in Action (Reksio i Kretes w Akcji!) +- Reksio and the Pirate Treasure (Reksio i Skarb Piratów) +- Reksio and the Time Machine (Reksio i Wehikuł Czasu) +- Reksio and the UFO (Reksio i Ufo) +- Reksio and the Wizards (Reksio i Czarodzieje) +- Rent-A-Hero +- Resurrection - The Return of the Black Dragon (software mode) +- Return to Krondor +- Rising Lands (patched) - Road Rash - Robin Hood - The Legend of Sherwood +- Roland Garros 98 (software mode) - RollerCoaster Tycoon - Sanitarium - Scooby-Doo(TM), Case File #2 The Scary Stone Dragon @@ -297,23 +377,39 @@ Need help and don't have a github account? Ask your questions on [Discord](https - Sega Touring Car - Septerra Core - Settlers 3 +- Seven Kingdoms II - Shadow Flare - Shadow Watch - Shogo - Mobile Armor Division +- Silver (needs "SilverUK GeForce2 And Radeon Patch") - Sim City 3000 - Sim Copter +- SimTunes - Sim Theme Park (aka Theme Park World) - SimCoaster / Theme Park Inc +- Simon the Sorcerer 1/2 (windows 95 version) - Sonic 3D Blast +- Soldiers At War - Space Rangers +- Spec Ops - Ranger Assault (software mode) - SpongeBob SquarePants: Typing - SPY Fox : Some Assembly Required - SPY Fox in Dry Cereal - SPY Fox: Hold the Mustard - SPY Fox: Operation Ozone +- Squad Leader +- Star Trek Away Team +- Star Trek Generations +- Star Wars Anakin's Speedway +- Star Wars Early Learning Activity Center +- Star Wars Episode I: The Gungan Frontier - Star Wars Jedi Knight: Dark Forces II +- Star Wars Rebellion +- Star Wars Yoda's Challenge +- Star Wars: Droid Works - Star Wars: Galactic Battlegrounds - Star Wars: Galactic Battlegrounds: Clone Campaigns +- Star Wars: Pit Droids - StarCraft - StarCraft: Broodwars - StarFlyers Alien Space Chase @@ -326,40 +422,68 @@ Need help and don't have a github account? Ask your questions on [Discord](https - Stronghold Crusader HD - Stronghold HD - Sudden Strike 2 +- Superbike 2000 +- Swarog +- The Jungle Book Groove Party +- The Curse Of Monkey Island +- The Dig +- The Last Express - The Missing on Lost Island +- The Neverhood +- The Next Worlds - The Powerpuff Girls - Princess Snorebucks - The Powerpuff Girls(TM) Mojo Jojo's Clone Zone +- The Rocky Interactive Horror Show +- The Sex Files - The X-Files DVD - Theme Hospital - Three Kingdoms: Fate of the Dragon - Throne of Darkness +- Thunder Brigade +- TianLong BaBu +- Tone Rebellion - Total Annihilation - Total Annihilation (Unofficial Beta Patch v3.9.02) - Total Annihilation: Kingdoms +- Toy Story +- Tridonis - Twisted Metal - Twisted Metal 2 - Tzar: The Burden of the Crown +- Unreal - Uprising 2: Lead and Destroy - Uprising: Join or Die - Vermeer +- Virtua Cop +- Virtua Cop 2 +- Virtua Fighter 2 - Virtua Fighter PC +- Virtual Springfield +- Virtual On: Cyber Troopers +- WarGames - War Wind - War Wind II - Human Onslaught - Warcraft 2 +- WarCraft 2000: Nuclear Epidemic - Warlords 3: Darklords Rising - Warlords Battlecry - Warlords Battlecry 2 - Warlords Battlecry 3 +- Weird War +- Wheel Of Fortune +- Wing Commander - The Kilrathi Saga - Wizardry 8 - Wizards and Warriors - Worms 2 - Worms Armageddon +- Z & Z Expansion Kit - Zeus: Master of Olympus - Zoombinis Island Odyssey - Zoombinis Logical Journey - Zoombinis Mountain Rescue +- Zork Nemesis - Zuma Deluxe - - ... +- ... There are a lot more games supported but I don't usually update the list, just give it a try and if it doesn't work then check the [wiki](https://github.com/FunkyFr3sh/cnc-ddraw/wiki) and the instructions above. diff --git a/action.yml b/action.yml index 86b657c..f2a0b38 100644 --- a/action.yml +++ b/action.yml @@ -11,7 +11,7 @@ # uses: phobos2077/sfall@develop # with: # release-xp: true -# +# # - name: Copy sfall to mod directory # run: copy "${{ steps.sfall.outputs.release-xp }}" "my/mod/directory/ddraw.dll" # @@ -46,10 +46,16 @@ outputs: release: description: 'Full path to ddraw.dll built with Release configuration' value: ${{ steps.build-release.outputs.ddraw-dll }} + release-pdb: + description: 'Full path to ddraw.pdb built with Release configuration' + value: ${{ steps.build-release.outputs.ddraw-pdb }} releasexp: description: 'Full path to ddraw.dll built with ReleaseXP configuration' value: ${{ steps.build-releasexp.outputs.ddraw-dll }} + releasexp-pdb: + description: 'Full path to ddraw.pdb built with ReleaseXP configuration' + value: ${{ steps.build-releasexp.outputs.ddraw-pdb }} debug: description: 'Full path to ddraw.dll built with Debug configuration' @@ -119,6 +125,7 @@ runs: "${{ steps.msbuild.outputs.exe }}" "$GITHUB_ACTION_PATH/cnc-ddraw.sln" -p:Configuration=Release -p:Platform=x86 -p:PlatformToolset=v142 # echo "ddraw-dll=$(cygpath --windows "$GITHUB_ACTION_PATH/bin/Release/ddraw.dll")" >> $GITHUB_OUTPUT + echo "ddraw-pdb=$(cygpath --windows "$GITHUB_ACTION_PATH/bin/Release/ddraw.pdb")" >> $GITHUB_OUTPUT echo "::endgroup::" fi @@ -137,6 +144,7 @@ runs: "${{ steps.msbuild.outputs.exe }}" "$GITHUB_ACTION_PATH/cnc-ddraw.sln" -p:Configuration=ReleaseXP -p:Platform=x86 -p:PlatformToolset=v141_xp # echo "ddraw-dll=$(cygpath --windows "$GITHUB_ACTION_PATH/bin/ReleaseXP/ddraw.dll")" >> $GITHUB_OUTPUT + echo "ddraw-pdb=$(cygpath --windows "$GITHUB_ACTION_PATH/bin/ReleaseXP/ddraw.pdb")" >> $GITHUB_OUTPUT echo "::endgroup::" fi diff --git a/build.cmd b/build.cmd index c9d3564..801abe4 100644 --- a/build.cmd +++ b/build.cmd @@ -1,9 +1,15 @@ @echo off -REM -REM patch environment config -REM -set PATH=C:\w64devkit\bin + +set GIT1=C:\Program Files\Microsoft Visual Studio\2022\Community\Common7\IDE\CommonExtensions\Microsoft\TeamFoundation\Team Explorer\Git\mingw64\bin\ +set GIT2=C:\Program Files\Microsoft Visual Studio\2022\Enterprise\Common7\IDE\CommonExtensions\Microsoft\TeamFoundation\Team Explorer\Git\mingw64\bin\ +set GIT3=C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\Common7\IDE\CommonExtensions\Microsoft\TeamFoundation\Team Explorer\Git\mingw32\bin\ +set GIT4=C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\IDE\CommonExtensions\Microsoft\TeamFoundation\Team Explorer\Git\mingw32\bin\ +set GIT5=C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\Common7\IDE\CommonExtensions\Microsoft\TeamFoundation\Team Explorer\Git\mingw32\bin\ +set GIT6=C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\Common7\IDE\CommonExtensions\Microsoft\TeamFoundation\Team Explorer\Git\mingw32\bin\ + +set PATH=C:\w64devkit\bin;%GIT1%;%GIT2%;%GIT3%;%GIT4%;%GIT5%;%GIT6%;%PATH% + make clean -make -REM make DEBUG=1 +make _WIN32_WINNT=0x0400 + pause diff --git a/build_debug.cmd b/build_debug.cmd new file mode 100644 index 0000000..4e43145 --- /dev/null +++ b/build_debug.cmd @@ -0,0 +1,15 @@ +@echo off + +set GIT1=C:\Program Files\Microsoft Visual Studio\2022\Community\Common7\IDE\CommonExtensions\Microsoft\TeamFoundation\Team Explorer\Git\mingw64\bin\ +set GIT2=C:\Program Files\Microsoft Visual Studio\2022\Enterprise\Common7\IDE\CommonExtensions\Microsoft\TeamFoundation\Team Explorer\Git\mingw64\bin\ +set GIT3=C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\Common7\IDE\CommonExtensions\Microsoft\TeamFoundation\Team Explorer\Git\mingw32\bin\ +set GIT4=C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\IDE\CommonExtensions\Microsoft\TeamFoundation\Team Explorer\Git\mingw32\bin\ +set GIT5=C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\Common7\IDE\CommonExtensions\Microsoft\TeamFoundation\Team Explorer\Git\mingw32\bin\ +set GIT6=C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\Common7\IDE\CommonExtensions\Microsoft\TeamFoundation\Team Explorer\Git\mingw32\bin\ + +set PATH=C:\w64devkit\bin;%GIT1%;%GIT2%;%GIT3%;%GIT4%;%GIT5%;%GIT6%;%PATH% + +make clean +make DEBUG=1 _WIN32_WINNT=0x0400 + +pause diff --git a/cnc-ddraw.vcxproj b/cnc-ddraw.vcxproj index fda7e42..3f5d12d 100644 --- a/cnc-ddraw.vcxproj +++ b/cnc-ddraw.vcxproj @@ -27,6 +27,7 @@ + @@ -51,6 +52,7 @@ + @@ -76,8 +78,10 @@ + + @@ -87,6 +91,8 @@ + + @@ -220,7 +226,7 @@ Windows - dbghelp.lib;winmm.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + avifil32.lib;winmm.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) exports.def @@ -230,6 +236,21 @@ if NOT "$(LocalDebuggerWorkingDirectory)" == "$(ProjectDir)" if exist "$(LocalDe ) + + +set DST_FILE="inc/git.h" +set GIT_PATH="$(DevEnvDir)\CommonExtensions\Microsoft\TeamFoundation\Team Explorer\Git\mingw64\bin\git.exe" + +if not exist %GIT_PATH% set GIT_PATH="$(DevEnvDir)\CommonExtensions\Microsoft\TeamFoundation\Team Explorer\Git\mingw32\bin\git.exe" +if not exist %GIT_PATH% set GIT_PATH=git.exe + +for /f "tokens=*" %%I in ('%GIT_PATH% describe --match=NeVeRmAtCh --always --dirty ^|^| echo UNKNOWN') do set GIT_COMMIT=%%I +for /f "tokens=*" %%I in ('%GIT_PATH% rev-parse --abbrev-ref HEAD ^|^| echo UNKNOWN') do set GIT_BRANCH=%%I + +echo #define GIT_COMMIT "%GIT_COMMIT%" > %DST_FILE% +echo #define GIT_BRANCH "%GIT_BRANCH%" >> %DST_FILE% + + @@ -247,7 +268,7 @@ if NOT "$(LocalDebuggerWorkingDirectory)" == "$(ProjectDir)" if exist "$(LocalDe Windows true true - winmm.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + avifil32.lib;winmm.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) exports.def @@ -257,6 +278,21 @@ if NOT "$(LocalDebuggerWorkingDirectory)" == "$(ProjectDir)" if exist "$(LocalDe ) + + +set DST_FILE="inc/git.h" +set GIT_PATH="$(DevEnvDir)\CommonExtensions\Microsoft\TeamFoundation\Team Explorer\Git\mingw64\bin\git.exe" + +if not exist %GIT_PATH% set GIT_PATH="$(DevEnvDir)\CommonExtensions\Microsoft\TeamFoundation\Team Explorer\Git\mingw32\bin\git.exe" +if not exist %GIT_PATH% set GIT_PATH=git.exe + +for /f "tokens=*" %%I in ('%GIT_PATH% describe --match=NeVeRmAtCh --always --dirty ^|^| echo UNKNOWN') do set GIT_COMMIT=%%I +for /f "tokens=*" %%I in ('%GIT_PATH% rev-parse --abbrev-ref HEAD ^|^| echo UNKNOWN') do set GIT_BRANCH=%%I + +echo #define GIT_COMMIT "%GIT_COMMIT%" > %DST_FILE% +echo #define GIT_BRANCH "%GIT_BRANCH%" >> %DST_FILE% + + @@ -274,7 +310,7 @@ if NOT "$(LocalDebuggerWorkingDirectory)" == "$(ProjectDir)" if exist "$(LocalDe Windows true true - winmm.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + avifil32.lib;winmm.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) exports.def @@ -284,6 +320,21 @@ if NOT "$(LocalDebuggerWorkingDirectory)" == "$(ProjectDir)" if exist "$(LocalDe ) + + +set DST_FILE="inc/git.h" +set GIT_PATH="$(DevEnvDir)\CommonExtensions\Microsoft\TeamFoundation\Team Explorer\Git\mingw64\bin\git.exe" + +if not exist %GIT_PATH% set GIT_PATH="$(DevEnvDir)\CommonExtensions\Microsoft\TeamFoundation\Team Explorer\Git\mingw32\bin\git.exe" +if not exist %GIT_PATH% set GIT_PATH=git.exe + +for /f "tokens=*" %%I in ('%GIT_PATH% describe --match=NeVeRmAtCh --always --dirty ^|^| echo UNKNOWN') do set GIT_COMMIT=%%I +for /f "tokens=*" %%I in ('%GIT_PATH% rev-parse --abbrev-ref HEAD ^|^| echo UNKNOWN') do set GIT_BRANCH=%%I + +echo #define GIT_COMMIT "%GIT_COMMIT%" > %DST_FILE% +echo #define GIT_BRANCH "%GIT_BRANCH%" >> %DST_FILE% + + @@ -301,7 +352,7 @@ if NOT "$(LocalDebuggerWorkingDirectory)" == "$(ProjectDir)" if exist "$(LocalDe Windows true true - dbghelp.lib;winmm.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + avifil32.lib;winmm.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) exports.def @@ -311,6 +362,21 @@ if NOT "$(LocalDebuggerWorkingDirectory)" == "$(ProjectDir)" if exist "$(LocalDe ) + + +set DST_FILE="inc/git.h" +set GIT_PATH="$(DevEnvDir)\CommonExtensions\Microsoft\TeamFoundation\Team Explorer\Git\mingw64\bin\git.exe" + +if not exist %GIT_PATH% set GIT_PATH="$(DevEnvDir)\CommonExtensions\Microsoft\TeamFoundation\Team Explorer\Git\mingw32\bin\git.exe" +if not exist %GIT_PATH% set GIT_PATH=git.exe + +for /f "tokens=*" %%I in ('%GIT_PATH% describe --match=NeVeRmAtCh --always --dirty ^|^| echo UNKNOWN') do set GIT_COMMIT=%%I +for /f "tokens=*" %%I in ('%GIT_PATH% rev-parse --abbrev-ref HEAD ^|^| echo UNKNOWN') do set GIT_BRANCH=%%I + +echo #define GIT_COMMIT "%GIT_COMMIT%" > %DST_FILE% +echo #define GIT_BRANCH "%GIT_BRANCH%" >> %DST_FILE% + + @@ -328,7 +394,7 @@ if NOT "$(LocalDebuggerWorkingDirectory)" == "$(ProjectDir)" if exist "$(LocalDe Windows true true - dbghelp.lib;winmm.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + avifil32.lib;winmm.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) exports.def @@ -338,6 +404,21 @@ if NOT "$(LocalDebuggerWorkingDirectory)" == "$(ProjectDir)" if exist "$(LocalDe ) + + +set DST_FILE="inc/git.h" +set GIT_PATH="$(DevEnvDir)\CommonExtensions\Microsoft\TeamFoundation\Team Explorer\Git\mingw64\bin\git.exe" + +if not exist %GIT_PATH% set GIT_PATH="$(DevEnvDir)\CommonExtensions\Microsoft\TeamFoundation\Team Explorer\Git\mingw32\bin\git.exe" +if not exist %GIT_PATH% set GIT_PATH=git.exe + +for /f "tokens=*" %%I in ('%GIT_PATH% describe --match=NeVeRmAtCh --always --dirty ^|^| echo UNKNOWN') do set GIT_COMMIT=%%I +for /f "tokens=*" %%I in ('%GIT_PATH% rev-parse --abbrev-ref HEAD ^|^| echo UNKNOWN') do set GIT_BRANCH=%%I + +echo #define GIT_COMMIT "%GIT_COMMIT%" > %DST_FILE% +echo #define GIT_BRANCH "%GIT_BRANCH%" >> %DST_FILE% + + diff --git a/cnc-ddraw.vcxproj.filters b/cnc-ddraw.vcxproj.filters index 7de9def..b15230e 100644 --- a/cnc-ddraw.vcxproj.filters +++ b/cnc-ddraw.vcxproj.filters @@ -165,6 +165,12 @@ Source Files + + Source Files + + + Source Files + @@ -287,6 +293,18 @@ Header Files + + Header Files + + + Header Files + + + Header Files + + + Header Files + diff --git a/config/ConfigFormUnit.cpp b/config/ConfigFormUnit.cpp index 9da37ad..7d40a88 100644 --- a/config/ConfigFormUnit.cpp +++ b/config/ConfigFormUnit.cpp @@ -131,31 +131,31 @@ void TConfigForm::ApplyTranslation(TIniFile *ini) ConfigForm->Caption = L"cnc-ddraw 配置"; DisplayBtn->Caption = L"显示设置"; AdvancedBtn->Caption = L"高级设置"; - HotkeyBtn->Caption = L"热键设置"; + HotkeyBtn->Caption = L"快捷键设置"; CompatibilityBtn->Caption = L"兼容性设置"; RestoreDefaultsBtn->Caption = L"恢复默认设置"; PresentationLbl->Caption = L"显示方式"; - MaintasLbl->Caption = L"保持纵横比"; - VsyncLbl->Caption = L"打开垂直同步"; + MaintasLbl->Caption = L"保持宽高比"; + VsyncLbl->Caption = L"启用垂直同步"; AdjmouseLbl->Caption = L"调整鼠标灵敏度"; - DevmodeLbl->Caption = L"锁定光标到窗口/屏幕"; + DevmodeLbl->Caption = L"将光标锁定到窗口/屏幕"; RendererLbl->Caption = L"渲染器"; BorderLbl->Caption = L"在窗口模式下显示窗口边框"; SavesettingsLbl->Caption = L"记住窗口位置和大小"; - ShaderLbl->Caption = L"OpenGL着色器"; - MaxfpsLbl->Caption = L"限制帧率"; - BoxingLbl->Caption = L"打开窗盒显示/整数缩放"; + ShaderLbl->Caption = L"OpenGL 着色器"; + MaxfpsLbl->Caption = L"限制帧速率"; + BoxingLbl->Caption = L"启用整数缩放"; ToggleWindowedLbl->Caption = L"切换窗口模式"; MaximizeWindowLbl->Caption = L"最大化窗口"; UnlockCursor1Lbl->Caption = L"解锁光标 1"; UnlockCursor2Lbl->Caption = L"解锁光标 2"; - ScreenshotLbl->Caption = L"截屏"; - MaxgameticksLbl->Caption = L"限制游戏速率"; + ScreenshotLbl->Caption = L"截图"; + MaxgameticksLbl->Caption = L"限制游戏速度"; NoactivateappLbl->Caption = L"修复损坏的Alt+Tab功能"; - ResolutionsLbl->Caption = L"解锁其他屏幕分辨率"; - MinfpsLbl->Caption = L"强制高FPS / 修复使用Freesync/G-Sync的卡顿问题"; - SinglecpuLbl->Caption = L"修复性能不佳和声音问题"; - NonexclusiveLbl->Caption = L"修复不显示的视频/UI元素"; + ResolutionsLbl->Caption = L"解锁额外的屏幕分辨率"; + MinfpsLbl->Caption = L"强制高 FPS / 修复 Freesync/G-Sync 卡顿"; + SinglecpuLbl->Caption = L"修复低性能和声音问题"; + NonexclusiveLbl->Caption = L"修复不显示的视频/UI 元素"; RendererCbx->Items->Clear(); RendererCbx->AddItem(L"自动", NULL); @@ -172,25 +172,26 @@ void TConfigForm::ApplyTranslation(TIniFile *ini) MaxgameticksCbx->Items->Clear(); MaxgameticksCbx->AddItem(L"无限制", NULL); MaxgameticksCbx->AddItem(L"与显示器刷新率同步", NULL); - MaxgameticksCbx->AddItem(L"模拟60hz刷新率显示器", NULL); - MaxgameticksCbx->AddItem(L"1000tick每秒", NULL); - MaxgameticksCbx->AddItem(L"500tick每秒", NULL); - MaxgameticksCbx->AddItem(L"250tick每秒", NULL); - MaxgameticksCbx->AddItem(L"125tick每秒", NULL); - MaxgameticksCbx->AddItem(L"60tick每秒", NULL); - MaxgameticksCbx->AddItem(L"30tick每秒", NULL); - MaxgameticksCbx->AddItem(L"25tick每秒", NULL); - MaxgameticksCbx->AddItem(L"15tick每秒", NULL); + MaxgameticksCbx->AddItem(L"模拟 60hz 刷新率显示器", NULL); + MaxgameticksCbx->AddItem(L"1000 次每秒", NULL); + MaxgameticksCbx->AddItem(L"500 次每秒", NULL); + MaxgameticksCbx->AddItem(L"250 次每秒", NULL); + MaxgameticksCbx->AddItem(L"125 次每秒", NULL); + MaxgameticksCbx->AddItem(L"60 次每秒", NULL); + MaxgameticksCbx->AddItem(L"30 次每秒", NULL); + MaxgameticksCbx->AddItem(L"25 次每秒", NULL); + MaxgameticksCbx->AddItem(L"15 次每秒", NULL); System::UnicodeString shaderHint = - L"某些着色器仅在打开放大功能时生效。\n\n"; + L"一些着色器只有在启用放大时才有效。\n\n"; System::UnicodeString upscaleHint = - L"必须打开放大功能才能使此设置生效。\n\n"; + L"必须启用放大才能使此设置生效。\n\n"; System::UnicodeString enableUpscaleHint = - L"要打开放大功能,请将显示方式设置为‘无边框’或‘拉伸至全屏’。\n" - "对于‘窗口化’显示方式,您必须调整窗口大小或最大化窗口。"; + L"要启用放大,请将显示方式设置为“无边框” \n" + "或“拉伸至全屏”。对于“窗口化”, \n" + "你必须调整窗口大小或将窗口开启最大化。"; ShaderLbl->Hint = shaderHint + enableUpscaleHint; ShaderD3DCbx->Hint = shaderHint + enableUpscaleHint; @@ -305,7 +306,7 @@ void TConfigForm::ApplyTranslation(TIniFile *ini) SavesettingsLbl->Caption = L"Fensterposition und Größe merken"; ShaderLbl->Caption = L"OpenGL Shader"; MaxfpsLbl->Caption = L"Limitiere Aktualisierungsrate"; - BoxingLbl->Caption = L"Fensterboxing / Integer Skalierung aktivieren"; //Not 100% sure if "windowboxing" can be translated better. + BoxingLbl->Caption = L"Windowboxing / Integer Skalierung aktivieren"; //Not 100% sure if "windowboxing" can be translated better. ToggleWindowedLbl->Caption = L"Fenstermodus umschalten"; MaximizeWindowLbl->Caption = L"Fenster maximieren"; UnlockCursor1Lbl->Caption = L"Cursor entsperren 1"; @@ -670,15 +671,177 @@ void TConfigForm::ApplyTranslation(TIniFile *ini) MaxgameticksCbx->AddItem(L"15 tick al secondo", NULL); System::UnicodeString shaderHint = - L"Alcuni shader funzionano solo quando l'upscaling è abilitato. \n\n"; + L"Alcuni shader funzionano solo quando il ridimensionamento dell'immagine è abilitato. \n\n"; System::UnicodeString upscaleHint = - L"Affinché questa impostazione funzioni, è necessario abilitare l'upscaling. \n\n"; + L"Affinché questa impostazione funzioni, è necessario abilitare il ridimensionamento dell'immagine. \n\n"; System::UnicodeString enableUpscaleHint = - L"Per abilitare l'ingrandimento, imposta la presentazione su 'Senza Bordi' \n" - "o 'Schermo Intero Ridimensionato'. Per la presentazione 'In Finestra', \n" - "è necessario ridimensionare o ingrandire la finestra."; + L"Per abilitare il ridimensionamento dell'immagine, imposta la modalità di presentazione \n" + "su 'Senza Bordi o 'Schermo Intero Ridimensionato'. Per la modalità 'In Finestra', \n" + "è necessario ridimensionare o ingrandire la finestra manualmente."; + + ShaderLbl->Hint = shaderHint + enableUpscaleHint; + ShaderD3DCbx->Hint = shaderHint + enableUpscaleHint; + ShaderCbx->Hint = shaderHint + enableUpscaleHint; + + MaintasLbl->Hint = upscaleHint + enableUpscaleHint; + MaintasChk->Hint = upscaleHint + enableUpscaleHint; + AdjmouseLbl->Hint = upscaleHint + enableUpscaleHint; + AdjmouseChk->Hint = upscaleHint + enableUpscaleHint; + BoxingLbl->Hint = upscaleHint + enableUpscaleHint; + BoxingChk->Hint = upscaleHint + enableUpscaleHint; + } + else if (lang == "vietnamese" || (lang == "auto" && priID == LANG_VIETNAMESE)) { + LanguageImg->Visible = true; + + /* -vietnamese - made by TheBuck338 @ github */ + + ConfigForm->Caption = L"Thiết lập cnc-ddraw"; + DisplayBtn->Caption = L"Cài Đặt Hình Ảnh"; + AdvancedBtn->Caption = L"Cài Đặt Nâng Cao"; + HotkeyBtn->Caption = L"Cài Đặt Phím Tắt"; + CompatibilityBtn->Caption = L"Cài Đặt Tương Thích"; + RestoreDefaultsBtn->Caption = L"Khôi phục cài đặt gốc"; + PresentationLbl->Caption = L"Chế Độ Hiển Thị"; + MaintasLbl->Caption = L"Giữ nguyên tỉ lệ khung hình"; + VsyncLbl->Caption = L"Bật VSync"; + AdjmouseLbl->Caption = L"Điều chỉnh độ nhạy của chuột"; + DevmodeLbl->Caption = L"Khóa con trỏ vào cửa sổ / màn hình"; + RendererLbl->Caption = L"Trình kết xuất"; + BorderLbl->Caption = L"Hiển thị thanh tiêu đề trong chế độ cửa sổ"; + SavesettingsLbl->Caption = L"Ghi nhớ vị trí kích thước và cửa sổ"; + ShaderLbl->Caption = L"Shader OpenGL"; + MaxfpsLbl->Caption = L"Giới hạn tốc độ khung hình"; + BoxingLbl->Caption = L"Bật windowboxing / chia tỷ lệ theo số nguyên"; + ToggleWindowedLbl->Caption = L"Bật/tắt chế độ cửa sổ"; + MaximizeWindowLbl->Caption = L"Phóng to cửa sổ"; + UnlockCursor1Lbl->Caption = L"Mở khóa con trỏ 1"; + UnlockCursor2Lbl->Caption = L"Mở khóa con trỏ 2"; + ScreenshotLbl->Caption = L"Chụp màn hình"; + MaxgameticksLbl->Caption = L"Giới hạn tốc độ trò chơi"; + NoactivateappLbl->Caption = L"Sửa lỗi Alt+Tab"; + ResolutionsLbl->Caption = L"Mở khóa thêm độ phân giải màn hình"; + MinfpsLbl->Caption = L"Khắc phục hiện tượng giật hình khi sử dụng Freesync/G-Sync"; + SinglecpuLbl->Caption = L"Khắc phục các vấn đề về hiệu năng và âm thanh kém"; + NonexclusiveLbl->Caption = L"Sửa lỗi các video / phần tử UI không hiển thị"; + + RendererCbx->Items->Clear(); + RendererCbx->AddItem(L"Tự Động", NULL); + RendererCbx->AddItem(L"Direct3D 9", NULL); + RendererCbx->AddItem(L"OpenGL", NULL); + RendererCbx->AddItem(L"GDI", NULL); + + PresentationCbx->Items->Clear(); + PresentationCbx->AddItem(L"Toàn Màn Hình", NULL); + PresentationCbx->AddItem(L"Toàn Màn Hình Nâng Cao Độ Phân Giải", NULL); + PresentationCbx->AddItem(L"Toàn Màn Hình Không Viền", NULL); + PresentationCbx->AddItem(L"Cửa Sổ", NULL); + + MaxgameticksCbx->Items->Clear(); + MaxgameticksCbx->AddItem(L"Không giới hạn", NULL); + MaxgameticksCbx->AddItem(L"Đồng bộ hóa với tần số quét màn hình", NULL); + MaxgameticksCbx->AddItem(L"Mô phỏng màn hình với tần số quét 60Hz", NULL); + MaxgameticksCbx->AddItem(L"1000 ticks mỗi giây", NULL); + MaxgameticksCbx->AddItem(L"500 ticks mỗi giây", NULL); + MaxgameticksCbx->AddItem(L"250 ticks mỗi giây", NULL); + MaxgameticksCbx->AddItem(L"125 ticks mỗi giây", NULL); + MaxgameticksCbx->AddItem(L"60 ticks mỗi giây", NULL); + MaxgameticksCbx->AddItem(L"30 ticks mỗi giây", NULL); + MaxgameticksCbx->AddItem(L"25 ticks mỗi giây", NULL); + MaxgameticksCbx->AddItem(L"15 ticks mỗi giây", NULL); + + System::UnicodeString shaderHint = + L"Một số shader chỉ hoạt động khi bật chế độ nâng cao độ phân giải. \n\n"; + + System::UnicodeString upscaleHint = + L"Phải bật chế độ nâng cao độ phân giải để cài đặt này hoạt động. \n\n"; + + System::UnicodeString enableUpscaleHint = + L"Để bật chế độ nâng cao độ phân giải, hãy đặt chế độ hiển thị của bạn\n" + "thành 'Toàn Màn Hình Không Viền' hoặc 'Toàn Màn Hình Nâng Cao Độ Phân Giải'.\n" + "Đối với chế độ 'Cửa Sổ', bạn phải thay đổi kích thước hoặc phóng to cửa sổ."; + + ShaderLbl->Hint = shaderHint + enableUpscaleHint; + ShaderD3DCbx->Hint = shaderHint + enableUpscaleHint; + ShaderCbx->Hint = shaderHint + enableUpscaleHint; + + MaintasLbl->Hint = upscaleHint + enableUpscaleHint; + MaintasChk->Hint = upscaleHint + enableUpscaleHint; + AdjmouseLbl->Hint = upscaleHint + enableUpscaleHint; + AdjmouseChk->Hint = upscaleHint + enableUpscaleHint; + BoxingLbl->Hint = upscaleHint + enableUpscaleHint; + BoxingChk->Hint = upscaleHint + enableUpscaleHint; + } + else if (lang == "polish" || (lang == "auto" && priID == LANG_POLISH)) { + LanguageImg->Visible = true; + + /* -polish - made by WaRzillA @ github */ + + ConfigForm->Caption = L"Konfiguracja cnc-ddraw"; + DisplayBtn->Caption = L"Ustawienia wyświetlania"; + AdvancedBtn->Caption = L"Ustawienia zaawansowane"; + HotkeyBtn->Caption = L"Skróty klawiaturowe"; + CompatibilityBtn->Caption = L"Ustawienia kompatybilności"; + RestoreDefaultsBtn->Caption = L"Przywróć ustawienia domyślne"; + PresentationLbl->Caption = L"Tryb wyświetlania"; + MaintasLbl->Caption = L"Zachowaj proporcje obrazu"; + VsyncLbl->Caption = L"Włącz VSync"; + AdjmouseLbl->Caption = L"Dostosuj czułość myszy"; + DevmodeLbl->Caption = L"Zablokuj kursor w oknie/na ekranie"; + RendererLbl->Caption = L"Silnik renderowania"; + BorderLbl->Caption = L"Pokaż ramki okna w trybie okienkowym"; + SavesettingsLbl->Caption = L"Zapamiętaj pozycję i rozmiar okna"; + ShaderLbl->Caption = L"Shader OpenGL"; + MaxfpsLbl->Caption = L"Ogranicz liczbę klatek na sekundę"; + BoxingLbl->Caption = L"Włącz windowboxing / integer scaling "; + ToggleWindowedLbl->Caption = L"Przełącz na tryb okienkowy"; + MaximizeWindowLbl->Caption = L"Maksymalizuj okno"; + UnlockCursor1Lbl->Caption = L"Odblokuj kursor 1"; + UnlockCursor2Lbl->Caption = L"Odblokuj kursor 2"; + ScreenshotLbl->Caption = L"Zrzut ekranu"; + MaxgameticksLbl->Caption = L"Ogranicz prędkość gry"; + NoactivateappLbl->Caption = L"Napraw nieprawidłowe działanie Alt+Tab"; + ResolutionsLbl->Caption = L"Odblokuj dodatkowe rozdzielczości ekranu"; + MinfpsLbl->Caption = L"Wymuś wysokie FPS / Napraw zacinanie Freesync/G-Sync"; + SinglecpuLbl->Caption = L"Napraw problemy z wydajnością i dźwiękiem"; + NonexclusiveLbl->Caption = L"Napraw niewidoczne filmy / elementy interfejsu"; + + RendererCbx->Items->Clear(); + RendererCbx->AddItem(L"Automatyczny", NULL); + RendererCbx->AddItem(L"Direct3D 9", NULL); + RendererCbx->AddItem(L"OpenGL", NULL); + RendererCbx->AddItem(L"GDI", NULL); + + PresentationCbx->Items->Clear(); + PresentationCbx->AddItem(L"Pełny ekran", NULL); + PresentationCbx->AddItem(L"Pełny ekran z upscalingiem", NULL); + PresentationCbx->AddItem(L"Tryb bezramkowy", NULL); + PresentationCbx->AddItem(L"Tryb okienkowy", NULL); + + MaxgameticksCbx->Items->Clear(); + MaxgameticksCbx->AddItem(L"Bez limitu", NULL); + MaxgameticksCbx->AddItem(L"Synchronizacja z odświeżaniem monitora", NULL); + MaxgameticksCbx->AddItem(L"Symulacja monitora 60 Hz", NULL); + MaxgameticksCbx->AddItem(L"1000 tików na sekundę", NULL); + MaxgameticksCbx->AddItem(L"500 tików na sekundę", NULL); + MaxgameticksCbx->AddItem(L"250 tików na sekundę", NULL); + MaxgameticksCbx->AddItem(L"125 tików na sekundę", NULL); + MaxgameticksCbx->AddItem(L"60 tików na sekundę", NULL); + MaxgameticksCbx->AddItem(L"30 tików na sekundę", NULL); + MaxgameticksCbx->AddItem(L"25 tików na sekundę", NULL); + MaxgameticksCbx->AddItem(L"15 tików na sekundę", NULL); + + System::UnicodeString shaderHint = + L"Niektóre shadery działają tylko wtedy, gdy włączone jest skalowanie. \n\n"; + + System::UnicodeString upscaleHint = + L"Skalowanie musi być włączone, aby ta opcja działała. \n\n"; + + System::UnicodeString enableUpscaleHint = + L"Aby włączyć skalowanie, ustaw tryb wyświetlania na 'Tryb bezramkowy' \n" + "lub 'Pełny ekran z upscalingiem'. Dla 'Tryb okienkowy' \n" + "musisz zmienić rozmiar lub zmaksymalizować okno."; ShaderLbl->Hint = shaderHint + enableUpscaleHint; ShaderD3DCbx->Hint = shaderHint + enableUpscaleHint; @@ -737,6 +900,18 @@ void TConfigForm::ApplyTranslation(TIniFile *ini) LanguageImg->Picture->Graphic = png; LanguageImg->Visible = true; } + else if (priID == LANG_VIETNAMESE) { + TPngImage *png = new TPngImage(); + png->LoadFromResourceName((int)HInstance, "PngImage_VN"); + LanguageImg->Picture->Graphic = png; + LanguageImg->Visible = true; + } + else if (priID == LANG_POLISH) { + TPngImage *png = new TPngImage(); + png->LoadFromResourceName((int)HInstance, "PngImage_PL"); + LanguageImg->Picture->Graphic = png; + LanguageImg->Visible = true; + } } catch (...) { } @@ -1099,7 +1274,7 @@ void __fastcall TConfigForm::FormCreate(TObject *Sender) MinfpsChk->State = Minfps != 0 ? tssOn : tssOff; SinglecpuChk->State = GetBool(ini, "singlecpu", true) ? tssOff : tssOn; - NonexclusiveChk->State = GetBool(ini, "nonexclusive", false) ? tssOn : tssOff; + NonexclusiveChk->State = GetBool(ini, "nonexclusive", true) ? tssOn : tssOff; CompatibilityBtn->Visible = !GetBool(ini, "hide_compat_tab", false); diff --git a/config/ConfigFormUnit.dfm b/config/ConfigFormUnit.dfm index 6ed9761..4f108df 100644 --- a/config/ConfigFormUnit.dfm +++ b/config/ConfigFormUnit.dfm @@ -2677,7 +2677,7 @@ object ConfigForm: TConfigForm 61C0650530766087F0B9DE67A1EF3B173173597F3B695CC608E0B202F8FC22D7 BBBF4CD8CBB88CCBB88CCBB88CCBB88CCBB88CCBB88CCBB88CCBB88CCBB88CCB B88CB18EFF1FA2974C1C31AF16A40000000049454E44AE426082} - Position = poDesktopCenter + Position = poScreenCenter OnActivate = FormActivate OnCreate = FormCreate DesignSize = ( @@ -2696,8 +2696,6 @@ object ConfigForm: TConfigForm ShowCaption = False TabOrder = 1 StyleElements = [seFont, seBorder] - ExplicitWidth = 495 - ExplicitHeight = 464 DesignSize = ( 499 465) @@ -2885,7 +2883,6 @@ object ConfigForm: TConfigForm TabOrder = 5 StyleElements = [seFont, seBorder] OnClick = ThemePnlClick - ExplicitLeft = 471 end end object CompatibilityPnl: TPanel @@ -2901,8 +2898,6 @@ object ConfigForm: TConfigForm TabOrder = 3 Visible = False StyleElements = [seFont, seBorder] - ExplicitWidth = 495 - ExplicitHeight = 464 object MaxgameticksLbl: TLabel Left = 40 Top = 28 @@ -3083,8 +3078,6 @@ object ConfigForm: TConfigForm TabOrder = 2 Visible = False StyleElements = [seFont, seBorder] - ExplicitWidth = 495 - ExplicitHeight = 464 object RendererLbl: TLabel Left = 40 Top = 28 @@ -3309,8 +3302,6 @@ object ConfigForm: TConfigForm TabOrder = 4 Visible = False StyleElements = [seFont, seBorder] - ExplicitWidth = 495 - ExplicitHeight = 464 object ToggleWindowedLbl: TLabel Left = 40 Top = 27 @@ -3538,7 +3529,6 @@ object ConfigForm: TConfigForm Color = clMenu ParentBackground = False TabOrder = 0 - ExplicitHeight = 467 DesignSize = ( 233 468) diff --git a/config/Resources/VN.png b/config/Resources/VN.png new file mode 100644 index 0000000..ec7cd48 Binary files /dev/null and b/config/Resources/VN.png differ diff --git a/config/Resources/pl.png b/config/Resources/pl.png new file mode 100644 index 0000000..d413d01 Binary files /dev/null and b/config/Resources/pl.png differ diff --git a/config/cnc-ddraw config.cbproj b/config/cnc-ddraw config.cbproj index dbd448c..7792b8b 100644 --- a/config/cnc-ddraw config.cbproj +++ b/config/cnc-ddraw config.cbproj @@ -1,7 +1,7 @@  {E020D5C7-AE07-4DB9-9688-6D289E9FFF1A} - 19.5 + 20.1 VCL Application cnc-ddraw config.cpp @@ -10,6 +10,7 @@ Win32 1 c + cnc-ddraw config true @@ -24,6 +25,11 @@ Base true + + true + Base + true + true Base @@ -41,6 +47,12 @@ true true + + true + Cfg_1 + true + true + true Base @@ -58,6 +70,12 @@ true true + + true + Cfg_2 + true + true + JPHNE true @@ -101,6 +119,14 @@ 1033 $(BDS)\bin\default_app.manifest + + Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;$(DCC_Namespace) + Debug + true + CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments= + 1033 + $(BDS)\bin\default_app.manifest + false true @@ -141,6 +167,9 @@ PerMonitorV2 + + PerMonitorV2 + NDEBUG;$(Defines) None @@ -161,6 +190,9 @@ PerMonitorV2 + + PerMonitorV2 + 0 @@ -195,6 +227,10 @@ RCDATA PngImage_IT + + RCDATA + PngImage_PL + RCDATA PngImage_RU @@ -203,6 +239,10 @@ RCDATA PngImage_US + + RCDATA + PngImage_VN + Base @@ -265,6 +305,16 @@ true + + + true + + + + + true + + true @@ -282,6 +332,16 @@ true + + + true + + + + + true + + @@ -294,16 +354,92 @@ true + + + true + + + + + true + + + + + cnc-ddraw config.exe + true + + + + + .\ + true + + + + + .\ + true + + + + + .\ + true + + + + + .\ + true + + + + + .\ + true + + + + + .\ + true + + + + + .\ + true + + + + + .\ + true + + + + + .\ + true + + + + + .\ + true + + 1 @@ -394,6 +530,16 @@ 1 + + + res\drawable-anydpi-v21 + 1 + + + res\drawable-anydpi-v21 + 1 + + res\values @@ -414,6 +560,66 @@ 1 + + + res\values-v31 + 1 + + + res\values-v31 + 1 + + + + + res\drawable-anydpi-v26 + 1 + + + res\drawable-anydpi-v26 + 1 + + + + + res\drawable + 1 + + + res\drawable + 1 + + + + + res\drawable + 1 + + + res\drawable + 1 + + + + + res\drawable + 1 + + + res\drawable + 1 + + + + + res\drawable-anydpi-v33 + 1 + + + res\drawable-anydpi-v33 + 1 + + res\values @@ -424,6 +630,16 @@ 1 + + + res\values-night-v21 + 1 + + + res\values-night-v21 + 1 + + res\drawable @@ -594,6 +810,56 @@ 1 + + + res\drawable-anydpi-v24 + 1 + + + res\drawable-anydpi-v24 + 1 + + + + + res\drawable + 1 + + + res\drawable + 1 + + + + + res\drawable-night-anydpi-v21 + 1 + + + res\drawable-night-anydpi-v21 + 1 + + + + + res\drawable-anydpi-v31 + 1 + + + res\drawable-anydpi-v31 + 1 + + + + + res\drawable-night-anydpi-v31 + 1 + + + res\drawable-night-anydpi-v31 + 1 + + 1 @@ -834,6 +1100,9 @@ 1 + + 1 + @@ -904,6 +1173,10 @@ Assets 1 + + Assets + 1 + @@ -914,6 +1187,10 @@ Assets 1 + + Assets + 1 + @@ -1127,10 +1404,12 @@ + True False + False 12 diff --git a/config/cnc-ddraw config.cpp b/config/cnc-ddraw config.cpp index 4c3dd33..cef38b4 100644 --- a/config/cnc-ddraw config.cpp +++ b/config/cnc-ddraw config.cpp @@ -11,7 +11,6 @@ #include USEFORM("ConfigFormUnit.cpp", ConfigForm); //--------------------------------------------------------------------------- - #define GAME_PATH (TPath::GetDirectoryName(Application->ExeName) + "\\") int WINAPI _tWinMain(HINSTANCE, HINSTANCE, LPTSTR, int) @@ -68,4 +67,15 @@ int WINAPI _tWinMain(HINSTANCE, HINSTANCE, LPTSTR, int) } return 0; } + +// dummy functions to avoid Wtsapi32.dll imports +EXTERN_C BOOL WINAPI WTSRegisterSessionNotification(HWND hWnd, DWORD dwFlags) +{ + return TRUE; +} + +EXTERN_C BOOL WINAPI WTSUnRegisterSessionNotification(HWND hWnd) +{ + return TRUE; +} //--------------------------------------------------------------------------- diff --git a/config/cnc-ddraw config_resources.rc b/config/cnc-ddraw config_resources.rc index a2ed1e5..b077d3a 100644 --- a/config/cnc-ddraw config_resources.rc +++ b/config/cnc-ddraw config_resources.rc @@ -4,5 +4,7 @@ PngImage_ES RCDATA "Resources\\ES.png" PngImage_FR RCDATA "Resources\\fr.png" PngImage_HU RCDATA "Resources\\hu.png" PngImage_IT RCDATA "Resources\\IT.png" +PngImage_PL RCDATA "Resources\\pl.png" PngImage_RU RCDATA "Resources\\RU.png" PngImage_US RCDATA "Resources\\US.png" +PngImage_VN RCDATA "Resources\\VN.png" diff --git a/inc/IDirect3D.h b/inc/IDirect3D.h index dd03465..aed4b3d 100644 --- a/inc/IDirect3D.h +++ b/inc/IDirect3D.h @@ -3,6 +3,7 @@ #define WIN32_LEAN_AND_MEAN #include +#include "d3dcaps.h" DEFINE_GUID(IID_IDirect3D, 0x3BBA0080, 0x2421, 0x11CF, 0xA3, 0x1A, 0x00, 0xAA, 0x00, 0xB9, 0x33, 0x56); @@ -10,6 +11,9 @@ DEFINE_GUID(IID_IDirect3D2, 0x6aae1ec1, 0x662a, 0x11d0, 0x88, 0x9d, 0x00, 0xaa, DEFINE_GUID(IID_IDirect3D3, 0xbb223240, 0xe72b, 0x11d0, 0xa9, 0xb4, 0x00, 0xaa, 0x00, 0xc0, 0x99, 0x3e); DEFINE_GUID(IID_IDirect3D7, 0xf5049e77, 0x4861, 0x11d2, 0xa4, 0x7, 0x0, 0xa0, 0xc9, 0x6, 0x29, 0xa8); +DEFINE_GUID(IID_IDirect3DNullDevice, 0x8767df22, 0xbacc, 0x11d1, 0x89, 0x69, 0x0, 0xa0, 0xc9, 0x6, 0x29, 0xa8); + + #define DECLARE_D3D_INTERFACE(iface) typedef struct iface { \ struct iface##Vtbl FAR* lpVtbl; \ ULONG ref; \ @@ -17,7 +21,6 @@ DEFINE_GUID(IID_IDirect3D7, 0xf5049e77, 0x4861, 0x11d2, 0xa4, 0x7, 0x0, 0xa0, 0x typedef struct iface##Vtbl iface##Vtbl; \ struct iface##Vtbl - /* IID_IDirect3D */ DECLARE_D3D_INTERFACE(IDirect3DImpl) @@ -27,7 +30,7 @@ DECLARE_D3D_INTERFACE(IDirect3DImpl) ULONG(__stdcall * Release) (IDirect3DImpl*); HRESULT(__stdcall * Initialize)(IDirect3DImpl*, int); - HRESULT(__stdcall * EnumDevices)(IDirect3DImpl*, int, int); + HRESULT(__stdcall * EnumDevices)(IDirect3DImpl*, LPD3DENUMDEVICESCALLBACK, LPVOID); HRESULT(__stdcall * CreateLight)(IDirect3DImpl*, int, int); HRESULT(__stdcall * CreateMaterial)(IDirect3DImpl*, int, int); HRESULT(__stdcall * CreateViewport)(IDirect3DImpl*, int, int); @@ -44,7 +47,7 @@ DECLARE_D3D_INTERFACE(IDirect3D2Impl) ULONG(__stdcall * AddRef) (IDirect3D2Impl*); ULONG(__stdcall * Release) (IDirect3D2Impl*); - HRESULT(__stdcall * EnumDevices)(IDirect3D2Impl*, int, int); + HRESULT(__stdcall * EnumDevices)(IDirect3D2Impl*, LPD3DENUMDEVICESCALLBACK, LPVOID); HRESULT(__stdcall * CreateLight)(IDirect3D2Impl*, int, int); HRESULT(__stdcall * CreateMaterial)(IDirect3D2Impl*, int, int); HRESULT(__stdcall * CreateViewport)(IDirect3D2Impl*, int, int); @@ -62,7 +65,7 @@ DECLARE_D3D_INTERFACE(IDirect3D3Impl) ULONG(__stdcall * AddRef) (IDirect3D3Impl*); ULONG(__stdcall * Release) (IDirect3D3Impl*); - HRESULT(__stdcall * EnumDevices)(IDirect3D3Impl*, int, int); + HRESULT(__stdcall * EnumDevices)(IDirect3D3Impl*, LPD3DENUMDEVICESCALLBACK, LPVOID); HRESULT(__stdcall * CreateLight)(IDirect3D3Impl*, int, int); HRESULT(__stdcall * CreateMaterial)(IDirect3D3Impl*, int, int); HRESULT(__stdcall * CreateViewport)(IDirect3D3Impl*, int, int); @@ -83,7 +86,7 @@ DECLARE_D3D_INTERFACE(IDirect3D7Impl) ULONG(__stdcall * AddRef) (IDirect3D7Impl*); ULONG(__stdcall * Release) (IDirect3D7Impl*); - HRESULT(__stdcall * EnumDevices)(IDirect3D7Impl*, int, int); + HRESULT(__stdcall * EnumDevices)(IDirect3D7Impl*, LPD3DENUMDEVICESCALLBACK7, LPVOID); HRESULT(__stdcall * CreateDevice)(IDirect3D7Impl*, int, int, int); HRESULT(__stdcall * CreateVertexBuffer)(IDirect3D7Impl*, int, int, int); HRESULT(__stdcall * EnumZBufferFormats)(IDirect3D7Impl*, int, int, int); diff --git a/inc/IDirectDrawSurface.h b/inc/IDirectDrawSurface.h index e339450..b96314a 100644 --- a/inc/IDirectDrawSurface.h +++ b/inc/IDirectDrawSurface.h @@ -9,6 +9,11 @@ #include "IDirectDraw.h" +typedef struct DDBITMAPINFO{ + BITMAPINFOHEADER bmiHeader; + RGBQUAD bmiColors[256]; +} DDBITMAPINFO; + struct IDirectDrawSurfaceImpl; struct IDirectDrawSurfaceImplVtbl; @@ -18,9 +23,9 @@ typedef struct IDirectDrawSurfaceImpl ULONG ref; + DWORD bpp; DWORD width; DWORD height; - DWORD bpp; DWORD size; DWORD flags; DWORD caps; @@ -28,6 +33,8 @@ typedef struct IDirectDrawSurfaceImpl CRITICAL_SECTION cs; IDirectDrawPaletteImpl* palette; + PALETTEENTRY selected_pal[256]; + UINT selected_pal_count; void* surface; HANDLE mapping; @@ -38,6 +45,7 @@ typedef struct IDirectDrawSurfaceImpl PBITMAPINFO bmi; HBITMAP bitmap; HDC hdc; + int dc_state; DDCOLORKEY color_key; DWORD last_flip_tick; DWORD last_blt_tick; diff --git a/inc/config.h b/inc/config.h index 3a33eaf..e15bece 100644 --- a/inc/config.h +++ b/inc/config.h @@ -22,12 +22,13 @@ typedef struct CNCDDRAWCONFIG INIFILE ini; BOOL d3d9on12; BOOL opengl_core; - + /* Optional settings */ BOOL fullscreen; BOOL windowed; BOOL maintas; + char aspect_ratio[16]; BOOL boxing; int maxfps; BOOL vsync; @@ -39,6 +40,10 @@ typedef struct CNCDDRAWCONFIG int save_settings; BOOL resizable; int d3d9_filter; + int anti_aliased_fonts_min_size; + int min_font_size; + int center_window; + char inject_resolution[128]; BOOL vhack; char screenshot_dir[MAX_PATH]; BOOL toggle_borderless; @@ -55,39 +60,36 @@ typedef struct CNCDDRAWCONFIG int resolutions; int fixchilds; BOOL hook_peekmessage; - BOOL hook_getmessage; /* Undocumented settings */ - BOOL releasealt; - BOOL fixnotresponding; - int hook; + BOOL fix_alt_key_stuck; + BOOL fix_not_responding; + BOOL no_compat_warning; int guard_lines; int max_resolutions; BOOL lock_surfaces; - BOOL allow_wmactivate; BOOL flipclear; - BOOL fixmousehook; BOOL rgb555; BOOL no_dinput_hook; - int refresh_rate; - int anti_aliased_fonts_min_size; - int custom_width; - int custom_height; - int min_font_size; - BOOL direct3d_passthrough; BOOL center_cursor_fix; char fake_mode[128]; - BOOL wine_allow_resize; BOOL lock_mouse_top_left; - BOOL no_compat_warning; + char win_version[32]; + int hook; + BOOL limit_gdi_handles; + BOOL remove_menu; + int refresh_rate; + int terminate_process; /* Hotkeys */ struct { int toggle_fullscreen; + int toggle_fullscreen2; int toggle_maximize; + int toggle_maximize2; int unlock_cursor1; int unlock_cursor2; int screenshot; @@ -95,16 +97,16 @@ typedef struct CNCDDRAWCONFIG /* Game specific settings */ - BOOL remove_menu; - BOOL armadahack; BOOL tshack; BOOL infantryhack; BOOL stronghold_hack; BOOL mgs_hack; BOOL tlc_hack; - BOOL homm_hack; BOOL carma95_hack; + BOOL sirtech_hack; + BOOL flightsim98_hack; + BOOL darkcolony_hack; } CNCDDRAWCONFIG; diff --git a/inc/crc32.h b/inc/crc32.h index d842810..9b0728d 100644 --- a/inc/crc32.h +++ b/inc/crc32.h @@ -6,5 +6,6 @@ unsigned long Crc32_ComputeBuf(unsigned long inCrc32, const void* buf, size_t bufLen); +unsigned long Crc32_FromFile(unsigned long crc32, char* filename); #endif diff --git a/inc/d3dcaps.h b/inc/d3dcaps.h new file mode 100644 index 0000000..4f86f61 --- /dev/null +++ b/inc/d3dcaps.h @@ -0,0 +1,607 @@ +/*==========================================================================; + * + * Copyright (C) Microsoft Corporation. All Rights Reserved. + * + * File: d3dcaps.h + * Content: Direct3D capabilities include file + * + ***************************************************************************/ + + + +#ifndef _D3DCAPS_H +#define _D3DCAPS_H + +/* + * Pull in DirectDraw include file automatically: + */ +#include "ddraw.h" + +#ifndef DIRECT3D_VERSION +#define DIRECT3D_VERSION 0x0700 +#endif + +#if defined(_X86_) || defined(_IA64_) +#pragma pack(4) +#endif + +/* Description of capabilities of transform */ + +typedef struct _D3DTRANSFORMCAPS { + DWORD dwSize; + DWORD dwCaps; +} D3DTRANSFORMCAPS, *LPD3DTRANSFORMCAPS; + +#define D3DTRANSFORMCAPS_CLIP 0x00000001L /* Will clip whilst transforming */ + +/* Description of capabilities of lighting */ + +typedef struct _D3DLIGHTINGCAPS { + DWORD dwSize; + DWORD dwCaps; /* Lighting caps */ + DWORD dwLightingModel; /* Lighting model - RGB or mono */ + DWORD dwNumLights; /* Number of lights that can be handled */ +} D3DLIGHTINGCAPS, *LPD3DLIGHTINGCAPS; + +#define D3DLIGHTINGMODEL_RGB 0x00000001L +#define D3DLIGHTINGMODEL_MONO 0x00000002L + +#define D3DLIGHTCAPS_POINT 0x00000001L /* Point lights supported */ +#define D3DLIGHTCAPS_SPOT 0x00000002L /* Spot lights supported */ +#define D3DLIGHTCAPS_DIRECTIONAL 0x00000004L /* Directional lights supported */ +#if(DIRECT3D_VERSION < 0x700) +#define D3DLIGHTCAPS_PARALLELPOINT 0x00000008L /* Parallel point lights supported */ +#endif +#if(DIRECT3D_VERSION < 0x500) +#define D3DLIGHTCAPS_GLSPOT 0x00000010L /* GL syle spot lights supported */ +#endif + +/* Description of capabilities for each primitive type */ + +typedef struct _D3DPrimCaps { + DWORD dwSize; + DWORD dwMiscCaps; /* Capability flags */ + DWORD dwRasterCaps; + DWORD dwZCmpCaps; + DWORD dwSrcBlendCaps; + DWORD dwDestBlendCaps; + DWORD dwAlphaCmpCaps; + DWORD dwShadeCaps; + DWORD dwTextureCaps; + DWORD dwTextureFilterCaps; + DWORD dwTextureBlendCaps; + DWORD dwTextureAddressCaps; + DWORD dwStippleWidth; /* maximum width and height of */ + DWORD dwStippleHeight; /* of supported stipple (up to 32x32) */ +} D3DPRIMCAPS, *LPD3DPRIMCAPS; + +/* D3DPRIMCAPS dwMiscCaps */ + +#define D3DPMISCCAPS_MASKPLANES 0x00000001L +#define D3DPMISCCAPS_MASKZ 0x00000002L +#define D3DPMISCCAPS_LINEPATTERNREP 0x00000004L +#define D3DPMISCCAPS_CONFORMANT 0x00000008L +#define D3DPMISCCAPS_CULLNONE 0x00000010L +#define D3DPMISCCAPS_CULLCW 0x00000020L +#define D3DPMISCCAPS_CULLCCW 0x00000040L + +/* D3DPRIMCAPS dwRasterCaps */ + +#define D3DPRASTERCAPS_DITHER 0x00000001L +#define D3DPRASTERCAPS_ROP2 0x00000002L +#define D3DPRASTERCAPS_XOR 0x00000004L +#define D3DPRASTERCAPS_PAT 0x00000008L +#define D3DPRASTERCAPS_ZTEST 0x00000010L +#define D3DPRASTERCAPS_SUBPIXEL 0x00000020L +#define D3DPRASTERCAPS_SUBPIXELX 0x00000040L +#define D3DPRASTERCAPS_FOGVERTEX 0x00000080L +#define D3DPRASTERCAPS_FOGTABLE 0x00000100L +#define D3DPRASTERCAPS_STIPPLE 0x00000200L +#if(DIRECT3D_VERSION >= 0x0500) +#define D3DPRASTERCAPS_ANTIALIASSORTDEPENDENT 0x00000400L +#define D3DPRASTERCAPS_ANTIALIASSORTINDEPENDENT 0x00000800L +#define D3DPRASTERCAPS_ANTIALIASEDGES 0x00001000L +#define D3DPRASTERCAPS_MIPMAPLODBIAS 0x00002000L +#define D3DPRASTERCAPS_ZBIAS 0x00004000L +#define D3DPRASTERCAPS_ZBUFFERLESSHSR 0x00008000L +#define D3DPRASTERCAPS_FOGRANGE 0x00010000L +#define D3DPRASTERCAPS_ANISOTROPY 0x00020000L +#endif /* DIRECT3D_VERSION >= 0x0500 */ +#if(DIRECT3D_VERSION >= 0x0600) +#define D3DPRASTERCAPS_WBUFFER 0x00040000L +#define D3DPRASTERCAPS_TRANSLUCENTSORTINDEPENDENT 0x00080000L +#define D3DPRASTERCAPS_WFOG 0x00100000L +#define D3DPRASTERCAPS_ZFOG 0x00200000L +#endif /* DIRECT3D_VERSION >= 0x0600 */ + +/* D3DPRIMCAPS dwZCmpCaps, dwAlphaCmpCaps */ + +#define D3DPCMPCAPS_NEVER 0x00000001L +#define D3DPCMPCAPS_LESS 0x00000002L +#define D3DPCMPCAPS_EQUAL 0x00000004L +#define D3DPCMPCAPS_LESSEQUAL 0x00000008L +#define D3DPCMPCAPS_GREATER 0x00000010L +#define D3DPCMPCAPS_NOTEQUAL 0x00000020L +#define D3DPCMPCAPS_GREATEREQUAL 0x00000040L +#define D3DPCMPCAPS_ALWAYS 0x00000080L + +/* D3DPRIMCAPS dwSourceBlendCaps, dwDestBlendCaps */ + +#define D3DPBLENDCAPS_ZERO 0x00000001L +#define D3DPBLENDCAPS_ONE 0x00000002L +#define D3DPBLENDCAPS_SRCCOLOR 0x00000004L +#define D3DPBLENDCAPS_INVSRCCOLOR 0x00000008L +#define D3DPBLENDCAPS_SRCALPHA 0x00000010L +#define D3DPBLENDCAPS_INVSRCALPHA 0x00000020L +#define D3DPBLENDCAPS_DESTALPHA 0x00000040L +#define D3DPBLENDCAPS_INVDESTALPHA 0x00000080L +#define D3DPBLENDCAPS_DESTCOLOR 0x00000100L +#define D3DPBLENDCAPS_INVDESTCOLOR 0x00000200L +#define D3DPBLENDCAPS_SRCALPHASAT 0x00000400L +#define D3DPBLENDCAPS_BOTHSRCALPHA 0x00000800L +#define D3DPBLENDCAPS_BOTHINVSRCALPHA 0x00001000L + +/* D3DPRIMCAPS dwShadeCaps */ + +#define D3DPSHADECAPS_COLORFLATMONO 0x00000001L +#define D3DPSHADECAPS_COLORFLATRGB 0x00000002L +#define D3DPSHADECAPS_COLORGOURAUDMONO 0x00000004L +#define D3DPSHADECAPS_COLORGOURAUDRGB 0x00000008L +#define D3DPSHADECAPS_COLORPHONGMONO 0x00000010L +#define D3DPSHADECAPS_COLORPHONGRGB 0x00000020L + +#define D3DPSHADECAPS_SPECULARFLATMONO 0x00000040L +#define D3DPSHADECAPS_SPECULARFLATRGB 0x00000080L +#define D3DPSHADECAPS_SPECULARGOURAUDMONO 0x00000100L +#define D3DPSHADECAPS_SPECULARGOURAUDRGB 0x00000200L +#define D3DPSHADECAPS_SPECULARPHONGMONO 0x00000400L +#define D3DPSHADECAPS_SPECULARPHONGRGB 0x00000800L + +#define D3DPSHADECAPS_ALPHAFLATBLEND 0x00001000L +#define D3DPSHADECAPS_ALPHAFLATSTIPPLED 0x00002000L +#define D3DPSHADECAPS_ALPHAGOURAUDBLEND 0x00004000L +#define D3DPSHADECAPS_ALPHAGOURAUDSTIPPLED 0x00008000L +#define D3DPSHADECAPS_ALPHAPHONGBLEND 0x00010000L +#define D3DPSHADECAPS_ALPHAPHONGSTIPPLED 0x00020000L + +#define D3DPSHADECAPS_FOGFLAT 0x00040000L +#define D3DPSHADECAPS_FOGGOURAUD 0x00080000L +#define D3DPSHADECAPS_FOGPHONG 0x00100000L + +/* D3DPRIMCAPS dwTextureCaps */ + +/* + * Perspective-correct texturing is supported + */ +#define D3DPTEXTURECAPS_PERSPECTIVE 0x00000001L + +/* + * Power-of-2 texture dimensions are required + */ +#define D3DPTEXTURECAPS_POW2 0x00000002L + +/* + * Alpha in texture pixels is supported + */ +#define D3DPTEXTURECAPS_ALPHA 0x00000004L + +/* + * Color-keyed textures are supported + */ +#define D3DPTEXTURECAPS_TRANSPARENCY 0x00000008L + +/* + * obsolete, see D3DPTADDRESSCAPS_BORDER + */ +#define D3DPTEXTURECAPS_BORDER 0x00000010L + +/* + * Only square textures are supported + */ +#define D3DPTEXTURECAPS_SQUAREONLY 0x00000020L + +#if(DIRECT3D_VERSION >= 0x0600) +/* + * Texture indices are not scaled by the texture size prior + * to interpolation. + */ +#define D3DPTEXTURECAPS_TEXREPEATNOTSCALEDBYSIZE 0x00000040L + +/* + * Device can draw alpha from texture palettes + */ +#define D3DPTEXTURECAPS_ALPHAPALETTE 0x00000080L + +/* + * Device can use non-POW2 textures if: + * 1) D3DTEXTURE_ADDRESS is set to CLAMP for this texture's stage + * 2) D3DRS_WRAP(N) is zero for this texture's coordinates + * 3) mip mapping is not enabled (use magnification filter only) + */ +#define D3DPTEXTURECAPS_NONPOW2CONDITIONAL 0x00000100L + +#endif /* DIRECT3D_VERSION >= 0x0600 */ +#if(DIRECT3D_VERSION >= 0x0700) + +// 0x00000200L unused + +/* + * Device can divide transformed texture coordinates by the + * COUNTth texture coordinate (can do D3DTTFF_PROJECTED) + */ +#define D3DPTEXTURECAPS_PROJECTED 0x00000400L + +/* + * Device can do cubemap textures + */ +#define D3DPTEXTURECAPS_CUBEMAP 0x00000800L + +#define D3DPTEXTURECAPS_COLORKEYBLEND 0x00001000L +#endif /* DIRECT3D_VERSION >= 0x0700 */ + +/* D3DPRIMCAPS dwTextureFilterCaps */ + +#define D3DPTFILTERCAPS_NEAREST 0x00000001L +#define D3DPTFILTERCAPS_LINEAR 0x00000002L +#define D3DPTFILTERCAPS_MIPNEAREST 0x00000004L +#define D3DPTFILTERCAPS_MIPLINEAR 0x00000008L +#define D3DPTFILTERCAPS_LINEARMIPNEAREST 0x00000010L +#define D3DPTFILTERCAPS_LINEARMIPLINEAR 0x00000020L + +#if(DIRECT3D_VERSION >= 0x0600) +/* Device3 Min Filter */ +#define D3DPTFILTERCAPS_MINFPOINT 0x00000100L +#define D3DPTFILTERCAPS_MINFLINEAR 0x00000200L +#define D3DPTFILTERCAPS_MINFANISOTROPIC 0x00000400L + +/* Device3 Mip Filter */ +#define D3DPTFILTERCAPS_MIPFPOINT 0x00010000L +#define D3DPTFILTERCAPS_MIPFLINEAR 0x00020000L + +/* Device3 Mag Filter */ +#define D3DPTFILTERCAPS_MAGFPOINT 0x01000000L +#define D3DPTFILTERCAPS_MAGFLINEAR 0x02000000L +#define D3DPTFILTERCAPS_MAGFANISOTROPIC 0x04000000L +#define D3DPTFILTERCAPS_MAGFAFLATCUBIC 0x08000000L +#define D3DPTFILTERCAPS_MAGFGAUSSIANCUBIC 0x10000000L +#endif /* DIRECT3D_VERSION >= 0x0600 */ + +/* D3DPRIMCAPS dwTextureBlendCaps */ + +#define D3DPTBLENDCAPS_DECAL 0x00000001L +#define D3DPTBLENDCAPS_MODULATE 0x00000002L +#define D3DPTBLENDCAPS_DECALALPHA 0x00000004L +#define D3DPTBLENDCAPS_MODULATEALPHA 0x00000008L +#define D3DPTBLENDCAPS_DECALMASK 0x00000010L +#define D3DPTBLENDCAPS_MODULATEMASK 0x00000020L +#define D3DPTBLENDCAPS_COPY 0x00000040L +#if(DIRECT3D_VERSION >= 0x0500) +#define D3DPTBLENDCAPS_ADD 0x00000080L +#endif /* DIRECT3D_VERSION >= 0x0500 */ + +/* D3DPRIMCAPS dwTextureAddressCaps */ +#define D3DPTADDRESSCAPS_WRAP 0x00000001L +#define D3DPTADDRESSCAPS_MIRROR 0x00000002L +#define D3DPTADDRESSCAPS_CLAMP 0x00000004L +#if(DIRECT3D_VERSION >= 0x0500) +#define D3DPTADDRESSCAPS_BORDER 0x00000008L +#define D3DPTADDRESSCAPS_INDEPENDENTUV 0x00000010L +#endif /* DIRECT3D_VERSION >= 0x0500 */ + +#if(DIRECT3D_VERSION >= 0x0600) + +/* D3DDEVICEDESC dwStencilCaps */ + +#define D3DSTENCILCAPS_KEEP 0x00000001L +#define D3DSTENCILCAPS_ZERO 0x00000002L +#define D3DSTENCILCAPS_REPLACE 0x00000004L +#define D3DSTENCILCAPS_INCRSAT 0x00000008L +#define D3DSTENCILCAPS_DECRSAT 0x00000010L +#define D3DSTENCILCAPS_INVERT 0x00000020L +#define D3DSTENCILCAPS_INCR 0x00000040L +#define D3DSTENCILCAPS_DECR 0x00000080L + +/* D3DDEVICEDESC dwTextureOpCaps */ + +#define D3DTEXOPCAPS_DISABLE 0x00000001L +#define D3DTEXOPCAPS_SELECTARG1 0x00000002L +#define D3DTEXOPCAPS_SELECTARG2 0x00000004L +#define D3DTEXOPCAPS_MODULATE 0x00000008L +#define D3DTEXOPCAPS_MODULATE2X 0x00000010L +#define D3DTEXOPCAPS_MODULATE4X 0x00000020L +#define D3DTEXOPCAPS_ADD 0x00000040L +#define D3DTEXOPCAPS_ADDSIGNED 0x00000080L +#define D3DTEXOPCAPS_ADDSIGNED2X 0x00000100L +#define D3DTEXOPCAPS_SUBTRACT 0x00000200L +#define D3DTEXOPCAPS_ADDSMOOTH 0x00000400L +#define D3DTEXOPCAPS_BLENDDIFFUSEALPHA 0x00000800L +#define D3DTEXOPCAPS_BLENDTEXTUREALPHA 0x00001000L +#define D3DTEXOPCAPS_BLENDFACTORALPHA 0x00002000L +#define D3DTEXOPCAPS_BLENDTEXTUREALPHAPM 0x00004000L +#define D3DTEXOPCAPS_BLENDCURRENTALPHA 0x00008000L +#define D3DTEXOPCAPS_PREMODULATE 0x00010000L +#define D3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR 0x00020000L +#define D3DTEXOPCAPS_MODULATECOLOR_ADDALPHA 0x00040000L +#define D3DTEXOPCAPS_MODULATEINVALPHA_ADDCOLOR 0x00080000L +#define D3DTEXOPCAPS_MODULATEINVCOLOR_ADDALPHA 0x00100000L +#define D3DTEXOPCAPS_BUMPENVMAP 0x00200000L +#define D3DTEXOPCAPS_BUMPENVMAPLUMINANCE 0x00400000L +#define D3DTEXOPCAPS_DOTPRODUCT3 0x00800000L + +/* D3DDEVICEDESC dwFVFCaps flags */ + +#define D3DFVFCAPS_TEXCOORDCOUNTMASK 0x0000ffffL /* mask for texture coordinate count field */ +#define D3DFVFCAPS_DONOTSTRIPELEMENTS 0x00080000L /* Device prefers that vertex elements not be stripped */ + +#endif /* DIRECT3D_VERSION >= 0x0600 */ + +typedef float D3DVALUE, *LPD3DVALUE; +typedef DWORD D3DCOLORMODEL; + +/* + * Description for a device. + * This is used to describe a device that is to be created or to query + * the current device. + */ +typedef struct _D3DDeviceDesc { + DWORD dwSize; /* Size of D3DDEVICEDESC structure */ + DWORD dwFlags; /* Indicates which fields have valid data */ + D3DCOLORMODEL dcmColorModel; /* Color model of device */ + DWORD dwDevCaps; /* Capabilities of device */ + D3DTRANSFORMCAPS dtcTransformCaps; /* Capabilities of transform */ + BOOL bClipping; /* Device can do 3D clipping */ + D3DLIGHTINGCAPS dlcLightingCaps; /* Capabilities of lighting */ + D3DPRIMCAPS dpcLineCaps; + D3DPRIMCAPS dpcTriCaps; + DWORD dwDeviceRenderBitDepth; /* One of DDBB_8, 16, etc.. */ + DWORD dwDeviceZBufferBitDepth;/* One of DDBD_16, 32, etc.. */ + DWORD dwMaxBufferSize; /* Maximum execute buffer size */ + DWORD dwMaxVertexCount; /* Maximum vertex count */ +//#if(DIRECT3D_VERSION >= 0x0500) + // *** New fields for DX5 *** // + + // Width and height caps are 0 for legacy HALs. + DWORD dwMinTextureWidth, dwMinTextureHeight; + DWORD dwMaxTextureWidth, dwMaxTextureHeight; + DWORD dwMinStippleWidth, dwMaxStippleWidth; + DWORD dwMinStippleHeight, dwMaxStippleHeight; +//#endif /* DIRECT3D_VERSION >= 0x0500 */ + +//#if(DIRECT3D_VERSION >= 0x0600) + // New fields for DX6 + DWORD dwMaxTextureRepeat; + DWORD dwMaxTextureAspectRatio; + DWORD dwMaxAnisotropy; + + // Guard band that the rasterizer can accommodate + // Screen-space vertices inside this space but outside the viewport + // will get clipped properly. + D3DVALUE dvGuardBandLeft; + D3DVALUE dvGuardBandTop; + D3DVALUE dvGuardBandRight; + D3DVALUE dvGuardBandBottom; + + D3DVALUE dvExtentsAdjust; + DWORD dwStencilCaps; + + DWORD dwFVFCaps; + DWORD dwTextureOpCaps; + WORD wMaxTextureBlendStages; + WORD wMaxSimultaneousTextures; +//#endif /* DIRECT3D_VERSION >= 0x0600 */ +} D3DDEVICEDESC, *LPD3DDEVICEDESC; + +#if(DIRECT3D_VERSION >= 0x0700) +typedef struct _D3DDeviceDesc7 { + DWORD dwDevCaps; /* Capabilities of device */ + D3DPRIMCAPS dpcLineCaps; + D3DPRIMCAPS dpcTriCaps; + DWORD dwDeviceRenderBitDepth; /* One of DDBB_8, 16, etc.. */ + DWORD dwDeviceZBufferBitDepth;/* One of DDBD_16, 32, etc.. */ + + DWORD dwMinTextureWidth, dwMinTextureHeight; + DWORD dwMaxTextureWidth, dwMaxTextureHeight; + + DWORD dwMaxTextureRepeat; + DWORD dwMaxTextureAspectRatio; + DWORD dwMaxAnisotropy; + + D3DVALUE dvGuardBandLeft; + D3DVALUE dvGuardBandTop; + D3DVALUE dvGuardBandRight; + D3DVALUE dvGuardBandBottom; + + D3DVALUE dvExtentsAdjust; + DWORD dwStencilCaps; + + DWORD dwFVFCaps; + DWORD dwTextureOpCaps; + WORD wMaxTextureBlendStages; + WORD wMaxSimultaneousTextures; + + DWORD dwMaxActiveLights; + D3DVALUE dvMaxVertexW; + GUID deviceGUID; + + WORD wMaxUserClipPlanes; + WORD wMaxVertexBlendMatrices; + + DWORD dwVertexProcessingCaps; + + DWORD dwReserved1; + DWORD dwReserved2; + DWORD dwReserved3; + DWORD dwReserved4; +} D3DDEVICEDESC7, *LPD3DDEVICEDESC7; +#endif /* DIRECT3D_VERSION >= 0x0700 */ + +#define D3DDEVICEDESCSIZE (sizeof(D3DDEVICEDESC)) +#define D3DDEVICEDESC7SIZE (sizeof(D3DDEVICEDESC7)) + +typedef HRESULT (CALLBACK * LPD3DENUMDEVICESCALLBACK)(GUID FAR *lpGuid, LPSTR lpDeviceDescription, LPSTR lpDeviceName, LPD3DDEVICEDESC, LPD3DDEVICEDESC, LPVOID); + +//#if(DIRECT3D_VERSION >= 0x0700) +typedef HRESULT (CALLBACK * LPD3DENUMDEVICESCALLBACK7)(LPSTR lpDeviceDescription, LPSTR lpDeviceName, LPD3DDEVICEDESC7, LPVOID); +//#endif /* DIRECT3D_VERSION >= 0x0700 */ + +/* D3DDEVICEDESC dwFlags indicating valid fields */ + +#define D3DDD_COLORMODEL 0x00000001L /* dcmColorModel is valid */ +#define D3DDD_DEVCAPS 0x00000002L /* dwDevCaps is valid */ +#define D3DDD_TRANSFORMCAPS 0x00000004L /* dtcTransformCaps is valid */ +#define D3DDD_LIGHTINGCAPS 0x00000008L /* dlcLightingCaps is valid */ +#define D3DDD_BCLIPPING 0x00000010L /* bClipping is valid */ +#define D3DDD_LINECAPS 0x00000020L /* dpcLineCaps is valid */ +#define D3DDD_TRICAPS 0x00000040L /* dpcTriCaps is valid */ +#define D3DDD_DEVICERENDERBITDEPTH 0x00000080L /* dwDeviceRenderBitDepth is valid */ +#define D3DDD_DEVICEZBUFFERBITDEPTH 0x00000100L /* dwDeviceZBufferBitDepth is valid */ +#define D3DDD_MAXBUFFERSIZE 0x00000200L /* dwMaxBufferSize is valid */ +#define D3DDD_MAXVERTEXCOUNT 0x00000400L /* dwMaxVertexCount is valid */ + +/* D3DDEVICEDESC dwDevCaps flags */ + +#define D3DDEVCAPS_FLOATTLVERTEX 0x00000001L /* Device accepts floating point */ + /* for post-transform vertex data */ +#define D3DDEVCAPS_SORTINCREASINGZ 0x00000002L /* Device needs data sorted for increasing Z */ +#define D3DDEVCAPS_SORTDECREASINGZ 0X00000004L /* Device needs data sorted for decreasing Z */ +#define D3DDEVCAPS_SORTEXACT 0x00000008L /* Device needs data sorted exactly */ + +#define D3DDEVCAPS_EXECUTESYSTEMMEMORY 0x00000010L /* Device can use execute buffers from system memory */ +#define D3DDEVCAPS_EXECUTEVIDEOMEMORY 0x00000020L /* Device can use execute buffers from video memory */ +#define D3DDEVCAPS_TLVERTEXSYSTEMMEMORY 0x00000040L /* Device can use TL buffers from system memory */ +#define D3DDEVCAPS_TLVERTEXVIDEOMEMORY 0x00000080L /* Device can use TL buffers from video memory */ +#define D3DDEVCAPS_TEXTURESYSTEMMEMORY 0x00000100L /* Device can texture from system memory */ +#define D3DDEVCAPS_TEXTUREVIDEOMEMORY 0x00000200L /* Device can texture from device memory */ +#if(DIRECT3D_VERSION >= 0x0500) +#define D3DDEVCAPS_DRAWPRIMTLVERTEX 0x00000400L /* Device can draw TLVERTEX primitives */ +#define D3DDEVCAPS_CANRENDERAFTERFLIP 0x00000800L /* Device can render without waiting for flip to complete */ +#define D3DDEVCAPS_TEXTURENONLOCALVIDMEM 0x00001000L /* Device can texture from nonlocal video memory */ +#endif /* DIRECT3D_VERSION >= 0x0500 */ +#if(DIRECT3D_VERSION >= 0x0600) +#define D3DDEVCAPS_DRAWPRIMITIVES2 0x00002000L /* Device can support DrawPrimitives2 */ +#define D3DDEVCAPS_SEPARATETEXTUREMEMORIES 0x00004000L /* Device is texturing from separate memory pools */ +#define D3DDEVCAPS_DRAWPRIMITIVES2EX 0x00008000L /* Device can support Extended DrawPrimitives2 i.e. DX7 compliant driver*/ +#endif /* DIRECT3D_VERSION >= 0x0600 */ +#if(DIRECT3D_VERSION >= 0x0700) +#define D3DDEVCAPS_HWTRANSFORMANDLIGHT 0x00010000L /* Device can support transformation and lighting in hardware and DRAWPRIMITIVES2EX must be also */ +#define D3DDEVCAPS_CANBLTSYSTONONLOCAL 0x00020000L /* Device supports a Tex Blt from system memory to non-local vidmem */ +#define D3DDEVCAPS_HWRASTERIZATION 0x00080000L /* Device has HW acceleration for rasterization */ + +/* + * These are the flags in the D3DDEVICEDESC7.dwVertexProcessingCaps field + */ + +/* device can do texgen */ +#define D3DVTXPCAPS_TEXGEN 0x00000001L +/* device can do IDirect3DDevice7 colormaterialsource ops */ +#define D3DVTXPCAPS_MATERIALSOURCE7 0x00000002L +/* device can do vertex fog */ +#define D3DVTXPCAPS_VERTEXFOG 0x00000004L +/* device can do directional lights */ +#define D3DVTXPCAPS_DIRECTIONALLIGHTS 0x00000008L +/* device can do positional lights (includes point and spot) */ +#define D3DVTXPCAPS_POSITIONALLIGHTS 0x00000010L +/* device can do local viewer */ +#define D3DVTXPCAPS_LOCALVIEWER 0x00000020L + +#endif /* DIRECT3D_VERSION >= 0x0700 */ + +#define D3DFDS_COLORMODEL 0x00000001L /* Match color model */ +#define D3DFDS_GUID 0x00000002L /* Match guid */ +#define D3DFDS_HARDWARE 0x00000004L /* Match hardware/software */ +#define D3DFDS_TRIANGLES 0x00000008L /* Match in triCaps */ +#define D3DFDS_LINES 0x00000010L /* Match in lineCaps */ +#define D3DFDS_MISCCAPS 0x00000020L /* Match primCaps.dwMiscCaps */ +#define D3DFDS_RASTERCAPS 0x00000040L /* Match primCaps.dwRasterCaps */ +#define D3DFDS_ZCMPCAPS 0x00000080L /* Match primCaps.dwZCmpCaps */ +#define D3DFDS_ALPHACMPCAPS 0x00000100L /* Match primCaps.dwAlphaCmpCaps */ +#define D3DFDS_SRCBLENDCAPS 0x00000200L /* Match primCaps.dwSourceBlendCaps */ +#define D3DFDS_DSTBLENDCAPS 0x00000400L /* Match primCaps.dwDestBlendCaps */ +#define D3DFDS_SHADECAPS 0x00000800L /* Match primCaps.dwShadeCaps */ +#define D3DFDS_TEXTURECAPS 0x00001000L /* Match primCaps.dwTextureCaps */ +#define D3DFDS_TEXTUREFILTERCAPS 0x00002000L /* Match primCaps.dwTextureFilterCaps */ +#define D3DFDS_TEXTUREBLENDCAPS 0x00004000L /* Match primCaps.dwTextureBlendCaps */ +#define D3DFDS_TEXTUREADDRESSCAPS 0x00008000L /* Match primCaps.dwTextureBlendCaps */ + +/* + * FindDevice arguments + */ +typedef struct _D3DFINDDEVICESEARCH { + DWORD dwSize; + DWORD dwFlags; + BOOL bHardware; + D3DCOLORMODEL dcmColorModel; + GUID guid; + DWORD dwCaps; + D3DPRIMCAPS dpcPrimCaps; +} D3DFINDDEVICESEARCH, *LPD3DFINDDEVICESEARCH; + +typedef struct _D3DFINDDEVICERESULT { + DWORD dwSize; + GUID guid; /* guid which matched */ + D3DDEVICEDESC ddHwDesc; /* hardware D3DDEVICEDESC */ + D3DDEVICEDESC ddSwDesc; /* software D3DDEVICEDESC */ +} D3DFINDDEVICERESULT, *LPD3DFINDDEVICERESULT; + +/* + * Description of execute buffer. + */ +typedef struct _D3DExecuteBufferDesc { + DWORD dwSize; /* size of this structure */ + DWORD dwFlags; /* flags indicating which fields are valid */ + DWORD dwCaps; /* capabilities of execute buffer */ + DWORD dwBufferSize; /* size of execute buffer data */ + LPVOID lpData; /* pointer to actual data */ +} D3DEXECUTEBUFFERDESC, *LPD3DEXECUTEBUFFERDESC; + +/* D3DEXECUTEBUFFER dwFlags indicating valid fields */ + +#define D3DDEB_BUFSIZE 0x00000001l /* buffer size valid */ +#define D3DDEB_CAPS 0x00000002l /* caps valid */ +#define D3DDEB_LPDATA 0x00000004l /* lpData valid */ + +/* D3DEXECUTEBUFFER dwCaps */ + +#define D3DDEBCAPS_SYSTEMMEMORY 0x00000001l /* buffer in system memory */ +#define D3DDEBCAPS_VIDEOMEMORY 0x00000002l /* buffer in device memory */ +#define D3DDEBCAPS_MEM (D3DDEBCAPS_SYSTEMMEMORY|D3DDEBCAPS_VIDEOMEMORY) + +#if(DIRECT3D_VERSION < 0x0800) + +#if(DIRECT3D_VERSION >= 0x0700) +typedef struct _D3DDEVINFO_TEXTUREMANAGER { + BOOL bThrashing; /* indicates if thrashing */ + DWORD dwApproxBytesDownloaded; /* Approximate number of bytes downloaded by texture manager */ + DWORD dwNumEvicts; /* number of textures evicted */ + DWORD dwNumVidCreates; /* number of textures created in video memory */ + DWORD dwNumTexturesUsed; /* number of textures used */ + DWORD dwNumUsedTexInVid; /* number of used textures present in video memory */ + DWORD dwWorkingSet; /* number of textures in video memory */ + DWORD dwWorkingSetBytes; /* number of bytes in video memory */ + DWORD dwTotalManaged; /* total number of managed textures */ + DWORD dwTotalBytes; /* total number of bytes of managed textures */ + DWORD dwLastPri; /* priority of last texture evicted */ +} D3DDEVINFO_TEXTUREMANAGER, *LPD3DDEVINFO_TEXTUREMANAGER; + +typedef struct _D3DDEVINFO_TEXTURING { + DWORD dwNumLoads; /* counts Load() API calls */ + DWORD dwApproxBytesLoaded; /* Approximate number bytes loaded via Load() */ + DWORD dwNumPreLoads; /* counts PreLoad() API calls */ + DWORD dwNumSet; /* counts SetTexture() API calls */ + DWORD dwNumCreates; /* counts texture creates */ + DWORD dwNumDestroys; /* counts texture destroys */ + DWORD dwNumSetPriorities; /* counts SetPriority() API calls */ + DWORD dwNumSetLODs; /* counts SetLOD() API calls */ + DWORD dwNumLocks; /* counts number of texture locks */ + DWORD dwNumGetDCs; /* counts number of GetDCs to textures */ +} D3DDEVINFO_TEXTURING, *LPD3DDEVINFO_TEXTURING; +#endif /* DIRECT3D_VERSION >= 0x0700 */ + +#endif //(DIRECT3D_VERSION < 0x0800) + +#pragma pack() + + +#endif /* _D3DCAPS_H_ */ + + diff --git a/inc/dd.h b/inc/dd.h index 31708ff..fe175f7 100644 --- a/inc/dd.h +++ b/inc/dd.h @@ -15,15 +15,15 @@ typedef HRESULT(WINAPI* DIRECTDRAWCREATEPROC)(GUID FAR*, LPDIRECTDRAW FAR*, IUnk ULONG dd_AddRef(); ULONG dd_Release(); HRESULT dd_EnumDisplayModes(DWORD dwFlags, LPDDSURFACEDESC lpDDSurfaceDesc, LPVOID lpContext, LPDDENUMMODESCALLBACK lpEnumModesCallback); -HRESULT dd_WaitForVerticalBlank(DWORD dwFlags, HANDLE hEvent); -HRESULT dd_SetDisplayMode(DWORD dwWidth, DWORD dwHeight, DWORD dwBPP, DWORD dwFlags); -HRESULT dd_SetCooperativeLevel(HWND hwnd, DWORD dwFlags); -HRESULT dd_RestoreDisplayMode(); HRESULT dd_GetCaps(LPDDCAPS_DX1 lpDDDriverCaps, LPDDCAPS_DX1 lpDDEmulCaps); HRESULT dd_GetDisplayMode(LPDDSURFACEDESC lpDDSurfaceDesc); HRESULT dd_GetMonitorFrequency(LPDWORD lpdwFreq); -HRESULT dd_GetAvailableVidMem(LPDDSCAPS lpDDCaps, LPDWORD lpdwTotal, LPDWORD lpdwFree); HRESULT dd_GetVerticalBlankStatus(LPBOOL lpbIsInVB); +HRESULT dd_RestoreDisplayMode(); +HRESULT dd_SetCooperativeLevel(HWND hwnd, DWORD dwFlags); +HRESULT dd_SetDisplayMode(DWORD dwWidth, DWORD dwHeight, DWORD dwBPP, DWORD dwFlags); +HRESULT dd_WaitForVerticalBlank(DWORD dwFlags, HANDLE hEvent); +HRESULT dd_GetAvailableVidMem(LPDDSCAPS lpDDCaps, LPDWORD lpdwTotal, LPDWORD lpdwFree); HRESULT dd_TestCooperativeLevel(); HRESULT dd_GetDeviceIdentifier(LPDDDEVICEIDENTIFIER pDDDI, DWORD dwFlags, REFIID riid); HRESULT dd_CreateEx(GUID* lpGuid, LPVOID* lplpDD, REFIID iid, IUnknown* pUnkOuter); @@ -32,6 +32,7 @@ HRESULT dd_CreateEx(GUID* lpGuid, LPVOID* lplpDD, REFIID iid, IUnknown* pUnkOute #define FIX_CHILDS_DETECT 1 #define FIX_CHILDS_DETECT_PAINT 2 #define FIX_CHILDS_DETECT_HIDE 3 +#define FIX_CHILDS_DETECT_HIDE_NOSCALE 4 #define RESLIST_NORMAL 0 #define RESLIST_MINI 1 @@ -49,6 +50,12 @@ HRESULT dd_CreateEx(GUID* lpGuid, LPVOID* lplpDD, REFIID iid, IUnknown* pUnkOute #define LIMIT_AUTO 0 #define LIMIT_TESTCOOP 1 #define LIMIT_BLTFAST 2 +#define LIMIT_UNLOCK 3 +#define LIMIT_PEEKMESSAGE 4 + +#define CENTER_WINDOW_NEVER 0 +#define CENTER_WINDOW_AUTO 1 +#define CENTER_WINDOW_ALWAYS 2 #ifndef CREATE_WAITABLE_TIMER_HIGH_RESOLUTION #define CREATE_WAITABLE_TIMER_HIGH_RESOLUTION 0x00000002 @@ -58,6 +65,18 @@ HRESULT dd_CreateEx(GUID* lpGuid, LPVOID* lplpDD, REFIID iid, IUnknown* pUnkOute #define CREATE_WAITABLE_TIMER_MANUAL_RESET 0x00000001 #endif +#ifndef GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT +#define GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT 0x00000002 +#endif + +#ifndef GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS +#define GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS 0x00000004 +#endif + +#if (_WIN32_WINNT < _WIN32_WINNT_WIN2K) +#define GdiTransparentBlt TransparentBlt +#endif + typedef struct SPEEDLIMITER { DWORD tick_length; @@ -108,6 +127,7 @@ typedef struct CNCDDRAW LONG palette_updated; LONG surface_updated; LONG clear_screen; + LONG screen_updated; float scale_w; float scale_h; @@ -149,14 +169,15 @@ typedef struct CNCDDRAW void* last_freed_palette; /* Dungeon Keeper hack */ void* last_freed_surface; /* Nox hack */ BOOL child_window_exists; - HWND video_window_hwnd; BOOL got_child_windows; DWORD last_set_window_pos_tick; /* WINE hack */ + DWORD last_msg_pull_tick; SPEEDLIMITER ticks_limiter; SPEEDLIMITER flip_limiter; DWORD minfps_tick_len; DWORD gui_thread_id; BOOL show_driver_warning; + BOOL windowed_hack; struct { @@ -165,10 +186,8 @@ typedef struct CNCDDRAW int y; } textbox; /* Age Of Empires 2 textbox align */ - struct { - LONG frame_skip; BOOL enabled; } zoom; } CNCDDRAW; diff --git a/inc/ddpalette.h b/inc/ddpalette.h index 7d264db..cfd46ff 100644 --- a/inc/ddpalette.h +++ b/inc/ddpalette.h @@ -7,6 +7,8 @@ #include "IDirectDrawPalette.h" #include "dd.h" +#define DDPCAPS_REFRESH_CHANGED_ONLY (1 << 31) + HRESULT ddp_GetEntries(IDirectDrawPaletteImpl* This, DWORD dwFlags, DWORD dwBase, DWORD dwNumEntries, LPPALETTEENTRY lpEntries); HRESULT ddp_SetEntries(IDirectDrawPaletteImpl* This, DWORD dwFlags, DWORD dwStartingEntry, DWORD dwCount, LPPALETTEENTRY lpEntries); HRESULT dd_CreatePalette(DWORD dwFlags, LPPALETTEENTRY lpDDColorArray, IDirectDrawPaletteImpl** lpDDPalette, IUnknown FAR* unkOuter); diff --git a/inc/debug.h b/inc/debug.h index 72efcf1..fa70c85 100644 --- a/inc/debug.h +++ b/inc/debug.h @@ -6,6 +6,7 @@ #include LONG WINAPI dbg_exception_handler(EXCEPTION_POINTERS* exception); +LONG WINAPI dbg_vectored_exception_handler(EXCEPTION_POINTERS* exception); void dbg_counter_start(); double dbg_counter_stop(); void dbg_debug_string(const char* format, ...); @@ -26,11 +27,16 @@ void dbg_dump_dds_caps(DWORD caps); void dbg_dump_dds_flags(DWORD flags); void dbg_dump_dds_blt_fast_flags(DWORD flags); void dbg_dump_dds_lock_flags(DWORD flags); +void dbg_dump_di_scm_flags(DWORD flags); +void dbg_dump_hook_type(int idHook); +char* dbg_d3d9_hr_to_str(HRESULT hr); char* dbg_mes_to_str(int id); +void __cdecl dbg_invoke_watson(wchar_t const*, wchar_t const*, wchar_t const*, unsigned int, uintptr_t); extern double g_dbg_frame_time; extern DWORD g_dbg_frame_count; extern LPTOP_LEVEL_EXCEPTION_FILTER g_dbg_exception_filter; +extern PVOID g_dbg_exception_handle; #if defined(__GNUC__) /* wrap msvc intrinsics onto gcc builtins */ #undef _ReturnAddress diff --git a/inc/delay_imports.h b/inc/delay_imports.h new file mode 100644 index 0000000..ba654ed --- /dev/null +++ b/inc/delay_imports.h @@ -0,0 +1,25 @@ +#ifndef DELAY_IMPORTS_H +#define DELAY_IMPORTS_H + +#define STATUS_SUCCESS ((NTSTATUS)0x00000000L) +#define ThreadQuerySetWin32StartAddress 9 + +typedef NTSTATUS(WINAPI* RTLVERIFYVERSIONINFOPROC)(PRTL_OSVERSIONINFOEXW, ULONG, ULONGLONG); +typedef const char* (CDECL* WINE_GET_VERSIONPROC)(); +typedef void (CDECL* WINE_GET_HOST_VERSIONPROC)(const char** sysname, const char** release); +typedef NTSTATUS(WINAPI* NTQUERYINFORMATIONTHREADPROC)(HANDLE, LONG, PVOID, ULONG, PULONG); + +typedef ULONGLONG(WINAPI* VERSETCONDITIONMASKPROC)(ULONGLONG, DWORD, BYTE); +typedef BOOL(WINAPI* GETMODULEHANDLEEXAPROC)(DWORD, LPCSTR, HMODULE*); + +extern NTQUERYINFORMATIONTHREADPROC delay_NtQueryInformationThread; +extern RTLVERIFYVERSIONINFOPROC delay_RtlVerifyVersionInfo; +extern WINE_GET_VERSIONPROC delay_wine_get_version; +extern WINE_GET_HOST_VERSIONPROC delay_wine_get_host_version; + +extern VERSETCONDITIONMASKPROC delay_VerSetConditionMask; +extern GETMODULEHANDLEEXAPROC delay_GetModuleHandleExA; + +void delay_imports_init(); + +#endif diff --git a/inc/dllmain.h b/inc/dllmain.h index 176d72a..f7e028b 100644 --- a/inc/dllmain.h +++ b/inc/dllmain.h @@ -29,4 +29,8 @@ typedef HRESULT(__stdcall* SETPROCESSDPIAWERENESSPROC)(PROCESS_DPI_AWARENESS); typedef BOOL(__stdcall* SETPROCESSDPIAWAREPROC)(); typedef BOOL(__stdcall* SETPROCESSDPIAWARENESSCONTEXTPROC)(DPI_AWARENESS_CONTEXT); +#if (_WIN32_WINNT < _WIN32_WINNT_WINXP) +#define SetThreadExecutionState(a) +#endif + #endif diff --git a/inc/hook.h b/inc/hook.h index f6d175f..23de636 100644 --- a/inc/hook.h +++ b/inc/hook.h @@ -2,10 +2,12 @@ #define HOOK_H #include +#include #define HOOK_SKIP_2 0x00000001l #define HOOK_LOCAL_ONLY 0x00000002l +#define HOOK_SYSTEM_ONLY 0x00000004l typedef struct HOOKLISTDATA { char function_name[32]; @@ -16,7 +18,7 @@ typedef struct HOOKLISTDATA { HMODULE mod; } HOOKLISTDATA; -typedef struct HOOKLIST { char module_name[32]; HOOKLISTDATA data[34]; } HOOKLIST; +typedef struct HOOKLIST { char module_name[32]; HOOKLISTDATA data[39]; } HOOKLIST; typedef BOOL(WINAPI* GETCURSORPOSPROC)(LPPOINT); typedef BOOL(WINAPI* CLIPCURSORPROC)(const RECT*); @@ -35,6 +37,7 @@ typedef BOOL(WINAPI* SETWINDOWPOSPROC)(HWND, HWND, int, int, int, int, UINT); typedef BOOL(WINAPI* MOVEWINDOWPROC)(HWND, int, int, int, int, BOOL); typedef LRESULT(WINAPI* SENDMESSAGEAPROC)(HWND, UINT, WPARAM, LPARAM); typedef LONG(WINAPI* SETWINDOWLONGAPROC)(HWND, int, LONG); +typedef LONG(WINAPI* SETWINDOWLONGWPROC)(HWND, int, LONG); typedef LONG(WINAPI* GETWINDOWLONGAPROC)(HWND, int); typedef BOOL(WINAPI* ENABLEWINDOWPROC)(HWND, BOOL); typedef HWND(WINAPI* CREATEWINDOWEXAPROC)(DWORD, LPCSTR, LPCSTR, DWORD, int, int, int, int, HWND, HMENU, HINSTANCE, LPVOID); @@ -57,26 +60,35 @@ typedef HHOOK(WINAPI* SETWINDOWSHOOKEXAPROC)(int, HOOKPROC, HINSTANCE, DWORD); typedef BOOL(WINAPI* PEEKMESSAGEAPROC)(LPMSG, HWND, UINT, UINT, UINT); typedef BOOL(WINAPI* GETMESSAGEAPROC)(LPMSG, HWND, UINT, UINT); typedef BOOL(WINAPI* GETWINDOWPLACEMENTPROC)(HWND, WINDOWPLACEMENT*); +typedef BOOL(WINAPI* SETWINDOWPLACEMENTPROC)(HWND, const WINDOWPLACEMENT*); typedef BOOL(WINAPI* ENUMDISPLAYSETTINGSAPROC)(LPCSTR, DWORD, DEVMODEA*); - -typedef BOOL(WINAPI* VALIDATERECTPROC)(HWND, const RECT*); -typedef BOOL(WINAPI* INVALIDATERECTPROC)(HWND, const RECT*, BOOL); +typedef LRESULT(WINAPI* DEFWINDOWPROCAPROC)(HWND, UINT, WPARAM, LPARAM); +typedef HWND(WINAPI* SETPARENTPROC)(HWND, HWND); +typedef HDC (WINAPI* BEGINPAINTPROC)(HWND, LPPAINTSTRUCT); typedef SHORT(WINAPI* GETKEYSTATEPROC)(int); typedef SHORT(WINAPI* GETASYNCKEYSTATEPROC)(int); typedef int (WINAPI* GETDEVICECAPSPROC)(HDC, int); typedef HFONT(WINAPI* CREATEFONTINDIRECTAPROC)(CONST LOGFONT*); typedef HFONT(WINAPI* CREATEFONTAPROC)(int, int, int, int, int, DWORD, DWORD, DWORD, DWORD, DWORD, DWORD, DWORD, DWORD, LPCTSTR); +typedef UINT(WINAPI* GETSYSTEMPALETTEENTRIESPROC)(HDC, UINT, UINT, LPPALETTEENTRY); +typedef HPALETTE(WINAPI* SELECTPALETTEPROC)(HDC, HPALETTE, BOOL); +typedef UINT (WINAPI* REALIZEPALETTEPROC)(HDC); + typedef HMODULE(WINAPI* LOADLIBRARYAPROC)(LPCSTR); typedef HMODULE(WINAPI* LOADLIBRARYWPROC)(LPCWSTR); typedef HMODULE(WINAPI* LOADLIBRARYEXAPROC)(LPCSTR, HANDLE, DWORD); typedef HMODULE(WINAPI* LOADLIBRARYEXWPROC)(LPCWSTR, HANDLE, DWORD); typedef FARPROC(WINAPI* GETPROCADDRESSPROC)(HMODULE, LPCSTR); typedef BOOL(WINAPI* GETDISKFREESPACEAPROC)(LPCSTR, LPDWORD, LPDWORD, LPDWORD, LPDWORD); +typedef DWORD(WINAPI* GETVERSIONPROC)(void); +typedef BOOL(WINAPI* GETVERSIONEXAPROC)(LPOSVERSIONINFOA); typedef HRESULT(WINAPI* COCREATEINSTANCEPROC)(REFCLSID, LPUNKNOWN, DWORD, REFIID, LPVOID*); typedef MCIERROR(WINAPI* MCISENDCOMMANDAPROC)(MCIDEVICEID, UINT, DWORD_PTR, DWORD_PTR); typedef LPTOP_LEVEL_EXCEPTION_FILTER(WINAPI* SETUNHANDLEDEXCEPTIONFILTERPROC)(LPTOP_LEVEL_EXCEPTION_FILTER); +typedef PGETFRAME (WINAPI* AVISTREAMGETFRAMEOPENPROC)(PAVISTREAM, LPBITMAPINFOHEADER); + extern GETCURSORPOSPROC real_GetCursorPos; extern CLIPCURSORPROC real_ClipCursor; extern SHOWCURSORPROC real_ShowCursor; @@ -94,6 +106,7 @@ extern SETWINDOWPOSPROC real_SetWindowPos; extern MOVEWINDOWPROC real_MoveWindow; extern SENDMESSAGEAPROC real_SendMessageA; extern SETWINDOWLONGAPROC real_SetWindowLongA; +extern SETWINDOWLONGWPROC real_SetWindowLongW; extern GETWINDOWLONGAPROC real_GetWindowLongA; extern ENABLEWINDOWPROC real_EnableWindow; extern CREATEWINDOWEXAPROC real_CreateWindowExA; @@ -111,23 +124,31 @@ extern SETWINDOWSHOOKEXAPROC real_SetWindowsHookExA; extern PEEKMESSAGEAPROC real_PeekMessageA; extern GETMESSAGEAPROC real_GetMessageA; extern GETWINDOWPLACEMENTPROC real_GetWindowPlacement; +extern SETWINDOWPLACEMENTPROC real_SetWindowPlacement; extern ENUMDISPLAYSETTINGSAPROC real_EnumDisplaySettingsA; -extern VALIDATERECTPROC real_ValidateRect; -extern INVALIDATERECTPROC real_InvalidateRect; +extern DEFWINDOWPROCAPROC real_DefWindowProcA; +extern SETPARENTPROC real_SetParent; +extern BEGINPAINTPROC real_BeginPaint; extern GETKEYSTATEPROC real_GetKeyState; extern GETASYNCKEYSTATEPROC real_GetAsyncKeyState; extern GETDEVICECAPSPROC real_GetDeviceCaps; extern CREATEFONTINDIRECTAPROC real_CreateFontIndirectA; extern CREATEFONTAPROC real_CreateFontA; +extern GETSYSTEMPALETTEENTRIESPROC real_GetSystemPaletteEntries; +extern SELECTPALETTEPROC real_SelectPalette; +extern REALIZEPALETTEPROC real_RealizePalette; extern LOADLIBRARYAPROC real_LoadLibraryA; extern LOADLIBRARYWPROC real_LoadLibraryW; extern LOADLIBRARYEXAPROC real_LoadLibraryExA; extern LOADLIBRARYEXWPROC real_LoadLibraryExW; extern GETPROCADDRESSPROC real_GetProcAddress; extern GETDISKFREESPACEAPROC real_GetDiskFreeSpaceA; +extern GETVERSIONPROC real_GetVersion; +extern GETVERSIONEXAPROC real_GetVersionExA; extern COCREATEINSTANCEPROC real_CoCreateInstance; extern MCISENDCOMMANDAPROC real_mciSendCommandA; extern SETUNHANDLEDEXCEPTIONFILTERPROC real_SetUnhandledExceptionFilter; +extern AVISTREAMGETFRAMEOPENPROC real_AVIStreamGetFrameOpen; extern BOOL g_hook_active; extern HOOKLIST g_hook_hooklist[]; diff --git a/inc/keyboard.h b/inc/keyboard.h new file mode 100644 index 0000000..8962198 --- /dev/null +++ b/inc/keyboard.h @@ -0,0 +1,11 @@ +#ifndef KEYBOARD_H +#define KEYBOARD_H + + +void keyboard_hook_init(); +void keyboard_hook_exit(); +LRESULT CALLBACK keyboard_hook_proc(int Code, WPARAM wParam, LPARAM lParam); + +extern HHOOK g_keyboard_hook; + +#endif diff --git a/inc/opengl_utils.h b/inc/opengl_utils.h index 63d2a73..d84dd20 100644 --- a/inc/opengl_utils.h +++ b/inc/opengl_utils.h @@ -108,10 +108,13 @@ extern PFNGLDRAWBUFFERSPROC glDrawBuffers; extern PFNGLCHECKFRAMEBUFFERSTATUSPROC glCheckFramebufferStatus; extern PFNGLDELETEFRAMEBUFFERSPROC glDeleteFramebuffers; extern PFNGLTEXBUFFERPROC glTexBuffer; +extern PFNGLGETINTEGERVPROC glGetIntegerv; +extern PFNGLGETSTRINGIPROC glGetStringi; extern HMODULE g_oglu_hmodule; extern BOOL g_oglu_got_version2; extern BOOL g_oglu_got_version3; extern char g_oglu_version[]; +extern char g_oglu_version_long[]; #endif diff --git a/inc/palette.h b/inc/palette.h new file mode 100644 index 0000000..8e38ec4 --- /dev/null +++ b/inc/palette.h @@ -0,0 +1,265 @@ +#ifndef PALETTE_H +#define PALETTE_H + +// Original palette copied from Windows ME +static PALETTEENTRY g_ddp_default_palette[] = +{ + { 0, 0, 0, 0 }, + { 128, 0, 0, 0 }, + { 0, 128, 0, 0 }, + { 128, 128, 0, 0 }, + { 0, 0, 128, 0 }, + { 128, 0, 128, 0 }, + { 0, 128, 128, 0 }, + { 192, 192, 192, 0 }, + { 192, 220, 192, 0 }, + { 166, 202, 240, 0 }, + { 95, 63, 63, 0 }, + { 127, 63, 63, 0 }, + { 159, 63, 63, 0 }, + { 191, 63, 63, 0 }, + { 223, 63, 63, 0 }, + { 255, 63, 63, 0 }, + { 63, 95, 63, 0 }, + { 95, 95, 63, 0 }, + { 127, 95, 63, 0 }, + { 159, 95, 63, 0 }, + { 191, 95, 63, 0 }, + { 223, 95, 63, 0 }, + { 255, 95, 63, 0 }, + { 63, 127, 63, 0 }, + { 95, 127, 63, 0 }, + { 127, 127, 63, 0 }, + { 159, 127, 63, 0 }, + { 191, 127, 63, 0 }, + { 223, 127, 63, 0 }, + { 255, 127, 63, 0 }, + { 63, 159, 63, 0 }, + { 95, 159, 63, 0 }, + { 127, 159, 63, 0 }, + { 159, 159, 63, 0 }, + { 191, 159, 63, 0 }, + { 223, 159, 63, 0 }, + { 255, 159, 63, 0 }, + { 63, 191, 63, 0 }, + { 95, 191, 63, 0 }, + { 127, 191, 63, 0 }, + { 159, 191, 63, 0 }, + { 191, 191, 63, 0 }, + { 223, 191, 63, 0 }, + { 255, 191, 63, 0 }, + { 63, 223, 63, 0 }, + { 95, 223, 63, 0 }, + { 127, 223, 63, 0 }, + { 159, 223, 63, 0 }, + { 191, 223, 63, 0 }, + { 223, 223, 63, 0 }, + { 255, 223, 63, 0 }, + { 63, 255, 63, 0 }, + { 95, 255, 63, 0 }, + { 127, 255, 63, 0 }, + { 159, 255, 63, 0 }, + { 191, 255, 63, 0 }, + { 223, 255, 63, 0 }, + { 255, 255, 63, 0 }, + { 63, 63, 95, 0 }, + { 95, 63, 95, 0 }, + { 127, 63, 95, 0 }, + { 159, 63, 95, 0 }, + { 191, 63, 95, 0 }, + { 223, 63, 95, 0 }, + { 255, 63, 95, 0 }, + { 63, 95, 95, 0 }, + { 95, 95, 95, 0 }, + { 127, 95, 95, 0 }, + { 159, 95, 95, 0 }, + { 191, 95, 95, 0 }, + { 223, 95, 95, 0 }, + { 255, 95, 95, 0 }, + { 63, 127, 95, 0 }, + { 95, 127, 95, 0 }, + { 127, 127, 95, 0 }, + { 159, 127, 95, 0 }, + { 191, 127, 95, 0 }, + { 223, 127, 95, 0 }, + { 255, 127, 95, 0 }, + { 63, 159, 95, 0 }, + { 95, 159, 95, 0 }, + { 127, 159, 95, 0 }, + { 159, 159, 95, 0 }, + { 191, 159, 95, 0 }, + { 223, 159, 95, 0 }, + { 255, 159, 95, 0 }, + { 63, 191, 95, 0 }, + { 95, 191, 95, 0 }, + { 127, 191, 95, 0 }, + { 159, 191, 95, 0 }, + { 191, 191, 95, 0 }, + { 223, 191, 95, 0 }, + { 255, 191, 95, 0 }, + { 63, 223, 95, 0 }, + { 95, 223, 95, 0 }, + { 127, 223, 95, 0 }, + { 159, 223, 95, 0 }, + { 191, 223, 95, 0 }, + { 223, 223, 95, 0 }, + { 255, 223, 95, 0 }, + { 63, 255, 95, 0 }, + { 95, 255, 95, 0 }, + { 127, 255, 95, 0 }, + { 159, 255, 95, 0 }, + { 191, 255, 95, 0 }, + { 223, 255, 95, 0 }, + { 255, 255, 95, 0 }, + { 63, 63, 127, 0 }, + { 95, 63, 127, 0 }, + { 127, 63, 127, 0 }, + { 159, 63, 127, 0 }, + { 191, 63, 127, 0 }, + { 223, 63, 127, 0 }, + { 255, 63, 127, 0 }, + { 63, 95, 127, 0 }, + { 95, 95, 127, 0 }, + { 127, 95, 127, 0 }, + { 159, 95, 127, 0 }, + { 191, 95, 127, 0 }, + { 223, 95, 127, 0 }, + { 255, 95, 127, 0 }, + { 63, 127, 127, 0 }, + { 95, 127, 127, 0 }, + { 127, 127, 127, 0 }, + { 159, 127, 127, 0 }, + { 191, 127, 127, 0 }, + { 223, 127, 127, 0 }, + { 255, 127, 127, 0 }, + { 63, 159, 127, 0 }, + { 95, 159, 127, 0 }, + { 127, 159, 127, 0 }, + { 159, 159, 127, 0 }, + { 191, 159, 127, 0 }, + { 223, 159, 127, 0 }, + { 255, 159, 127, 0 }, + { 63, 191, 127, 0 }, + { 95, 191, 127, 0 }, + { 127, 191, 127, 0 }, + { 159, 191, 127, 0 }, + { 191, 191, 127, 0 }, + { 223, 191, 127, 0 }, + { 255, 191, 127, 0 }, + { 63, 223, 127, 0 }, + { 95, 223, 127, 0 }, + { 127, 223, 127, 0 }, + { 159, 223, 127, 0 }, + { 191, 223, 127, 0 }, + { 223, 223, 127, 0 }, + { 255, 223, 127, 0 }, + { 63, 255, 127, 0 }, + { 95, 255, 127, 0 }, + { 127, 255, 127, 0 }, + { 159, 255, 127, 0 }, + { 191, 255, 127, 0 }, + { 223, 255, 127, 0 }, + { 255, 255, 127, 0 }, + { 63, 63, 159, 0 }, + { 95, 63, 159, 0 }, + { 127, 63, 159, 0 }, + { 159, 63, 159, 0 }, + { 191, 63, 159, 0 }, + { 223, 63, 159, 0 }, + { 255, 63, 159, 0 }, + { 63, 95, 159, 0 }, + { 95, 95, 159, 0 }, + { 127, 95, 159, 0 }, + { 159, 95, 159, 0 }, + { 191, 95, 159, 0 }, + { 223, 95, 159, 0 }, + { 255, 95, 159, 0 }, + { 63, 127, 159, 0 }, + { 95, 127, 159, 0 }, + { 127, 127, 159, 0 }, + { 159, 127, 159, 0 }, + { 191, 127, 159, 0 }, + { 223, 127, 159, 0 }, + { 255, 127, 159, 0 }, + { 63, 159, 159, 0 }, + { 95, 159, 159, 0 }, + { 127, 159, 159, 0 }, + { 159, 159, 159, 0 }, + { 191, 159, 159, 0 }, + { 223, 159, 159, 0 }, + { 255, 159, 159, 0 }, + { 63, 191, 159, 0 }, + { 95, 191, 159, 0 }, + { 127, 191, 159, 0 }, + { 159, 191, 159, 0 }, + { 191, 191, 159, 0 }, + { 223, 191, 159, 0 }, + { 255, 191, 159, 0 }, + { 63, 223, 159, 0 }, + { 95, 223, 159, 0 }, + { 127, 223, 159, 0 }, + { 159, 223, 159, 0 }, + { 191, 223, 159, 0 }, + { 223, 223, 159, 0 }, + { 255, 223, 159, 0 }, + { 63, 255, 159, 0 }, + { 95, 255, 159, 0 }, + { 127, 255, 159, 0 }, + { 159, 255, 159, 0 }, + { 191, 255, 159, 0 }, + { 223, 255, 159, 0 }, + { 255, 255, 159, 0 }, + { 63, 63, 191, 0 }, + { 95, 63, 191, 0 }, + { 127, 63, 191, 0 }, + { 159, 63, 191, 0 }, + { 191, 63, 191, 0 }, + { 223, 63, 191, 0 }, + { 255, 63, 191, 0 }, + { 63, 95, 191, 0 }, + { 95, 95, 191, 0 }, + { 127, 95, 191, 0 }, + { 159, 95, 191, 0 }, + { 191, 95, 191, 0 }, + { 223, 95, 191, 0 }, + { 255, 95, 191, 0 }, + { 63, 127, 191, 0 }, + { 95, 127, 191, 0 }, + { 127, 127, 191, 0 }, + { 159, 127, 191, 0 }, + { 191, 127, 191, 0 }, + { 223, 127, 191, 0 }, + { 255, 127, 191, 0 }, + { 63, 159, 191, 0 }, + { 95, 159, 191, 0 }, + { 127, 159, 191, 0 }, + { 159, 159, 191, 0 }, + { 191, 159, 191, 0 }, + { 223, 159, 191, 0 }, + { 255, 159, 191, 0 }, + { 63, 191, 191, 0 }, + { 95, 191, 191, 0 }, + { 127, 191, 191, 0 }, + { 159, 191, 191, 0 }, + { 191, 191, 191, 0 }, + { 223, 191, 191, 0 }, + { 255, 191, 191, 0 }, + { 63, 223, 191, 0 }, + { 95, 223, 191, 0 }, + { 127, 223, 191, 0 }, + { 159, 223, 191, 0 }, + { 191, 223, 191, 0 }, + { 223, 223, 191, 0 }, + { 255, 251, 240, 0 }, + { 58, 109, 165, 0 }, + { 128, 128, 128, 0 }, + { 255, 0, 0, 0 }, + { 0, 255, 0, 0 }, + { 255, 255, 0, 0 }, + { 0, 0, 255, 0 }, + { 255, 0, 255, 0 }, + { 0, 255, 255, 0 }, + { 255, 255, 255, 0 } +}; + +#endif diff --git a/inc/utils.h b/inc/utils.h index beb1c57..3833ede 100644 --- a/inc/utils.h +++ b/inc/utils.h @@ -6,6 +6,10 @@ HMODULE WINAPI util_enumerate_modules(_In_opt_ HMODULE hModuleLast); +void util_set_process_affinity(); +void util_set_thread_affinity(DWORD tid); +void util_pull_messages(); +DWORD util_get_timestamp(HMODULE mod); FARPROC util_get_iat_proc(HMODULE mod, char* module_name, char* function_name); BOOL util_caller_is_ddraw_wrapper(void* return_address); BOOL util_is_bad_read_ptr(void* p); diff --git a/inc/version.h b/inc/version.h index a9eb822..29e19fa 100644 --- a/inc/version.h +++ b/inc/version.h @@ -4,10 +4,10 @@ #define str(s) #s #define ver_str(a,b,c,d) str(a) "." str(b) "." str(c) "." str(d) -#define VERSION_MAJOR 6 -#define VERSION_MINOR 7 +#define VERSION_MAJOR 7 +#define VERSION_MINOR 1 #define VERSION_BUILD 0 -#define VERSION_REVISION 3 +#define VERSION_REVISION 1 #define VERSION VERSION_MAJOR, VERSION_MINOR, VERSION_BUILD, VERSION_REVISION #define VERSION_STRING ver_str(VERSION_MAJOR, VERSION_MINOR, VERSION_BUILD, VERSION_REVISION) diff --git a/inc/versionhelpers.h b/inc/versionhelpers.h index 3aa5742..36f2dd6 100644 --- a/inc/versionhelpers.h +++ b/inc/versionhelpers.h @@ -28,9 +28,13 @@ #define _WIN32_WINNT_WIN11 0x0A00 #endif +#if (_WIN32_WINNT < _WIN32_WINNT_WIN2K) +#define VerifyVersionInfoW(a,b,c) 0 +#define VerSetConditionMask verhelp_set_mask +#endif -void verhelp_init(); BOOL verhelp_verify_version(PRTL_OSVERSIONINFOEXW versionInfo, ULONG typeMask, ULONGLONG conditionMask); +ULONGLONG verhelp_set_mask(ULONGLONG ConditionMask, DWORD TypeMask, BYTE Condition); const char* verhelp_wine_get_version(); void verhelp_wine_get_host_version(const char** sysname, const char** release); @@ -56,6 +60,17 @@ VERSIONHELPERAPI IsWindowsVersion(DWORD major, DWORD minor, DWORD build, WORD se VER_SERVICEPACKMAJOR, VER_EQUAL)); } +VERSIONHELPERAPI IsWindowsVersionExcactBuild(DWORD major, DWORD minor, DWORD build, WORD servpack) +{ + RTL_OSVERSIONINFOEXW vi = { sizeof(vi),major,minor,build,0,{0},servpack }; + return verhelp_verify_version(&vi, VER_MAJORVERSION | VER_MINORVERSION | VER_BUILDNUMBER | VER_SERVICEPACKMAJOR, + VerSetConditionMask(VerSetConditionMask(VerSetConditionMask(VerSetConditionMask(0, + VER_MAJORVERSION, VER_EQUAL), + VER_MINORVERSION, VER_EQUAL), + VER_BUILDNUMBER, VER_EQUAL), + VER_SERVICEPACKMAJOR, VER_EQUAL)); +} + VERSIONHELPERAPI IsWindowsVersionAnySP(DWORD major, DWORD minor, DWORD build) { RTL_OSVERSIONINFOEXW vi = { sizeof(vi),major,minor,build,0,{0},0 }; @@ -67,6 +82,10 @@ VERSIONHELPERAPI IsWindowsVersionAnySP(DWORD major, DWORD minor, DWORD build) VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL)); } +VERSIONHELPERAPI IsWindows2000OrGreater(void) { + return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WIN2K), LOBYTE(_WIN32_WINNT_WIN2K), 0, 0); +} + VERSIONHELPERAPI IsWindowsXPOrGreater(void) { return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WINXP), LOBYTE(_WIN32_WINNT_WINXP), 0, 0); } @@ -127,11 +146,19 @@ VERSIONHELPERAPI IsWindows11OrGreater(void) { return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WIN11), LOBYTE(_WIN32_WINNT_WIN11), 22000, 0); } +VERSIONHELPERAPI IsWindows11Version24H2OrGreater(void) { + return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WIN11), LOBYTE(_WIN32_WINNT_WIN11), 26100, 0); +} + VERSIONHELPERAPI IsWindowsServer(void) { OSVERSIONINFOEXW vi = {sizeof(vi),0,0,0,0,{0},0,0,0,VER_NT_WORKSTATION}; return !verhelp_verify_version(&vi, VER_PRODUCT_TYPE, VerSetConditionMask(0, VER_PRODUCT_TYPE, VER_EQUAL)); } +VERSIONHELPERAPI IsWindows2000(void) { + return IsWindowsVersionAnySP(HIBYTE(_WIN32_WINNT_WIN2K), LOBYTE(_WIN32_WINNT_WIN2K), 0); +} + VERSIONHELPERAPI IsWindowsXP(void) { return IsWindowsVersionAnySP(HIBYTE(_WIN32_WINNT_WINXP), LOBYTE(_WIN32_WINNT_WINXP), 0); } @@ -200,6 +227,10 @@ VERSIONHELPERAPI IsWindows11(void) { return IsWindowsVersion(HIBYTE(_WIN32_WINNT_WIN11), LOBYTE(_WIN32_WINNT_WIN11), 22000, 0); } +VERSIONHELPERAPI IsWindows11Version24H2(void) { + return IsWindowsVersionExcactBuild(HIBYTE(_WIN32_WINNT_WIN11), LOBYTE(_WIN32_WINNT_WIN11), 26100, 0); +} + VERSIONHELPERAPI IsWine(void) { return verhelp_wine_get_version() != NULL; } @@ -220,4 +251,16 @@ VERSIONHELPERAPI IsLinux(void) { return sysname && _strcmpi(sysname, "Linux") == 0; } +VERSIONHELPERAPI IsAndroid(void) { + const char* sysname = NULL; + const char* release = NULL; + verhelp_wine_get_host_version(&sysname, &release); + + return release && strstr(release, "android") != NULL; +} + +VERSIONHELPERAPI IsSteamDeck(void) { + return IsWine() && GetEnvironmentVariable("STEAMDECK", NULL, 0); +} + #endif diff --git a/inc/winapi_hooks.h b/inc/winapi_hooks.h index 4ec75c9..ad44c7e 100644 --- a/inc/winapi_hooks.h +++ b/inc/winapi_hooks.h @@ -2,6 +2,7 @@ #define WINAPI_HOOKS_H #include +#include BOOL WINAPI fake_GetCursorPos(LPPOINT lpPoint); @@ -21,6 +22,7 @@ BOOL WINAPI fake_SetWindowPos(HWND hWnd, HWND hWndInsertAfter, int X, int Y, int BOOL WINAPI fake_MoveWindow(HWND hWnd, int X, int Y, int nWidth, int nHeight, BOOL bRepaint); LRESULT WINAPI fake_SendMessageA(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam); LONG WINAPI fake_SetWindowLongA(HWND hWnd, int nIndex, LONG dwNewLong); +LONG WINAPI fake_SetWindowLongW(HWND hWnd, int nIndex, LONG dwNewLong); LONG WINAPI fake_GetWindowLongA(HWND hWnd, int nIndex); BOOL WINAPI fake_EnableWindow(HWND hWnd, BOOL bEnable); BOOL WINAPI fake_DestroyWindow(HWND hWnd); @@ -33,12 +35,15 @@ HHOOK WINAPI fake_SetWindowsHookExA(int idHook, HOOKPROC lpfn, HINSTANCE hmod, D BOOL WINAPI fake_PeekMessageA(LPMSG lpMsg, HWND hWnd, UINT wMsgFilterMin, UINT wMsgFilterMax, UINT wRemoveMsg); BOOL WINAPI fake_GetMessageA(LPMSG lpMsg, HWND hWnd, UINT wMsgFilterMin, UINT wMsgFilterMax); BOOL WINAPI fake_GetWindowPlacement(HWND hWnd, WINDOWPLACEMENT* lpwndpl); +BOOL WINAPI fake_SetWindowPlacement(HWND hWnd, const WINDOWPLACEMENT* lpwndpl); BOOL WINAPI fake_EnumDisplaySettingsA(LPCSTR lpszDeviceName, DWORD iModeNum, DEVMODEA* lpDevMode); -BOOL WINAPI fake_ValidateRect(HWND hWnd, const RECT* lpRect); -BOOL WINAPI fake_InvalidateRect(HWND hWnd, const RECT* lpRect, BOOL bErase); +LRESULT WINAPI fake_DefWindowProcA(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam); +HWND WINAPI fake_SetParent(HWND hWndChild, HWND hWndNewParent); +HDC WINAPI fake_BeginPaint(HWND hWnd, LPPAINTSTRUCT lpPaint); SHORT WINAPI fake_GetKeyState(int nVirtKey); SHORT WINAPI fake_GetAsyncKeyState(int vKey); int WINAPI fake_GetDeviceCaps(HDC hdc, int index); +int WINAPI fake_GetDeviceCaps_system(HDC hdc, int index); BOOL WINAPI fake_StretchBlt( HDC hdcDest, int xDest, int yDest, int wDest, int hDest, HDC hdcSrc, int xSrc, int ySrc, int wSrc, int hSrc, DWORD rop); @@ -60,6 +65,9 @@ int WINAPI fake_StretchDIBits( HFONT WINAPI fake_CreateFontIndirectA(CONST LOGFONTA*); HFONT WINAPI fake_CreateFontA(int, int, int, int, int, DWORD, DWORD, DWORD, DWORD, DWORD, DWORD, DWORD, DWORD, LPCTSTR); +UINT WINAPI fake_GetSystemPaletteEntries(HDC, UINT, UINT, LPPALETTEENTRY); +HPALETTE WINAPI fake_SelectPalette(HDC, HPALETTE, BOOL); +UINT WINAPI fake_RealizePalette(HDC); HMODULE WINAPI fake_LoadLibraryA(LPCSTR lpLibFileName); HMODULE WINAPI fake_LoadLibraryW(LPCWSTR lpLibFileName); @@ -74,6 +82,9 @@ BOOL WINAPI fake_GetDiskFreeSpaceA( LPDWORD lpNumberOfFreeClusters, LPDWORD lpTotalNumberOfClusters); +DWORD WINAPI fake_GetVersion(void); +BOOL WINAPI fake_GetVersionExA(LPOSVERSIONINFOA lpVersionInformation); + HWND WINAPI fake_CreateWindowExA( DWORD dwExStyle, LPCSTR lpClassName, LPCSTR lpWindowName, DWORD dwStyle, int X, int Y, int nWidth, int nHeight, HWND hWndParent, HMENU hMenu, HINSTANCE hInstance, LPVOID lpParam); @@ -86,4 +97,6 @@ MCIERROR WINAPI fake_mciSendCommandA(MCIDEVICEID IDDevice, UINT uMsg, DWORD_PTR LPTOP_LEVEL_EXCEPTION_FILTER WINAPI fake_SetUnhandledExceptionFilter( LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter); +PGETFRAME WINAPI fake_AVIStreamGetFrameOpen(PAVISTREAM pavi, LPBITMAPINFOHEADER lpbiWanted); + #endif diff --git a/inc/wndproc.h b/inc/wndproc.h index 43a1e8e..4af4f7e 100644 --- a/inc/wndproc.h +++ b/inc/wndproc.h @@ -12,10 +12,15 @@ #define WM_RESTORE_STYLE WM_APP+119 #define IDT_TIMER_LEAVE_BNET 541287654 +#define IDT_TIMER_LINUX_FIX_WINDOW_SIZE 345267753 #define CNC_DDRAW_SET_FULLSCREEN 1 #define CNC_DDRAW_SET_WINDOWED 2 +#ifndef WM_UNICHAR +#define WM_UNICHAR 0x0109 +#endif + LRESULT CALLBACK fake_WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); #endif diff --git a/res.rc b/res.rc index 69ba76c..46f3908 100644 --- a/res.rc +++ b/res.rc @@ -1,4 +1,6 @@ #include "inc/version.h" +#include "inc/git.h" + 1 VERSIONINFO FILEVERSION VERSION @@ -10,13 +12,13 @@ PRODUCTVERSION VERSION { VALUE "CompanyName", "github.com/FunkyFr3sh" VALUE "FileDescription", "DirectDraw replacement" - VALUE "FileVersion", VERSION_STRING + VALUE "FileVersion", VERSION_STRING " (git~" GIT_COMMIT ", " GIT_BRANCH ")" VALUE "InternalName", "ddraw" VALUE "LegalCopyright", "Copyright (c) 2010-2024" VALUE "LegalTrademarks", "" VALUE "OriginalFileName", "ddraw.dll" VALUE "ProductName", "cnc-ddraw" - VALUE "ProductVersion", VERSION_STRING + VALUE "ProductVersion", VERSION_STRING " (git~" GIT_COMMIT ", " GIT_BRANCH ")" VALUE "Comments", "https://github.com/FunkyFr3sh/cnc-ddraw" } } diff --git a/src/IDirect3D/IDirect3D.c b/src/IDirect3D/IDirect3D.c index 0aaa1e8..e4b0ee5 100644 --- a/src/IDirect3D/IDirect3D.c +++ b/src/IDirect3D/IDirect3D.c @@ -14,6 +14,11 @@ HRESULT __stdcall IDirect3D__QueryInterface(IDirect3DImpl* This, REFIID riid, vo HRESULT ret = E_FAIL; + if (riid) + { + TRACE("NOT_IMPLEMENTED GUID = %08X\n", ((GUID*)riid)->Data1); + } + TRACE("NOT_IMPLEMENTED <- %s\n", __FUNCTION__); return ret; } @@ -51,10 +56,20 @@ HRESULT __stdcall IDirect3D__Initialize(IDirect3DImpl* This, int a) return ret; } -HRESULT __stdcall IDirect3D__EnumDevices(IDirect3DImpl* This, int a, int b) +HRESULT __stdcall IDirect3D__EnumDevices( + IDirect3DImpl* This, + LPD3DENUMDEVICESCALLBACK lpEnumDevicesCallback, + LPVOID lpUserArg) { TRACE("NOT_IMPLEMENTED -> %s(This=%p) [%p]\n", __FUNCTION__, This, _ReturnAddress()); - HRESULT ret = E_FAIL; + HRESULT ret = S_OK; + + if (lpEnumDevicesCallback) + { + D3DDEVICEDESC desc = { 0 }; + lpEnumDevicesCallback((GUID FAR*)&GUID_NULL, "NULL", "NULL", &desc, &desc, lpUserArg); + } + TRACE("NOT_IMPLEMENTED <- %s\n", __FUNCTION__); return ret; } diff --git a/src/IDirect3D/IDirect3D2.c b/src/IDirect3D/IDirect3D2.c index 50ae5ec..c4f93ab 100644 --- a/src/IDirect3D/IDirect3D2.c +++ b/src/IDirect3D/IDirect3D2.c @@ -14,6 +14,11 @@ HRESULT __stdcall IDirect3D2__QueryInterface(IDirect3D2Impl* This, REFIID riid, HRESULT ret = E_FAIL; + if (riid) + { + TRACE("NOT_IMPLEMENTED GUID = %08X\n", ((GUID*)riid)->Data1); + } + TRACE("NOT_IMPLEMENTED <- %s\n", __FUNCTION__); return ret; } @@ -43,10 +48,20 @@ ULONG __stdcall IDirect3D2__Release(IDirect3D2Impl* This) return ret; } -HRESULT __stdcall IDirect3D2__EnumDevices(IDirect3D2Impl* This, int a, int b) +HRESULT __stdcall IDirect3D2__EnumDevices( + IDirect3D2Impl* This, + LPD3DENUMDEVICESCALLBACK lpEnumDevicesCallback, + LPVOID lpUserArg) { TRACE("NOT_IMPLEMENTED -> %s(This=%p) [%p]\n", __FUNCTION__, This, _ReturnAddress()); - HRESULT ret = E_FAIL; + HRESULT ret = S_OK; + + if (lpEnumDevicesCallback) + { + //D3DDEVICEDESC desc = { 0 }; + //lpEnumDevicesCallback((GUID FAR*)&GUID_NULL, "NULL", "NULL", &desc, &desc, lpUserArg); + } + TRACE("NOT_IMPLEMENTED <- %s\n", __FUNCTION__); return ret; } diff --git a/src/IDirect3D/IDirect3D3.c b/src/IDirect3D/IDirect3D3.c index 9cc65bd..8b6ff43 100644 --- a/src/IDirect3D/IDirect3D3.c +++ b/src/IDirect3D/IDirect3D3.c @@ -14,6 +14,11 @@ HRESULT __stdcall IDirect3D3__QueryInterface(IDirect3D3Impl* This, REFIID riid, HRESULT ret = E_FAIL; + if (riid) + { + TRACE("NOT_IMPLEMENTED GUID = %08X\n", ((GUID*)riid)->Data1); + } + TRACE("NOT_IMPLEMENTED <- %s\n", __FUNCTION__); return ret; } @@ -43,10 +48,20 @@ ULONG __stdcall IDirect3D3__Release(IDirect3D3Impl* This) return ret; } -HRESULT __stdcall IDirect3D3__EnumDevices(IDirect3D3Impl* This, int a, int b) +HRESULT __stdcall IDirect3D3__EnumDevices( + IDirect3D3Impl* This, + LPD3DENUMDEVICESCALLBACK lpEnumDevicesCallback, + LPVOID lpUserArg) { TRACE("NOT_IMPLEMENTED -> %s(This=%p) [%p]\n", __FUNCTION__, This, _ReturnAddress()); - HRESULT ret = E_FAIL; + HRESULT ret = S_OK; + + if (lpEnumDevicesCallback) + { + //D3DDEVICEDESC desc = { 0 }; + //lpEnumDevicesCallback((GUID FAR*)&GUID_NULL, "NULL", "NULL", &desc, &desc, lpUserArg); + } + TRACE("NOT_IMPLEMENTED <- %s\n", __FUNCTION__); return ret; } diff --git a/src/IDirect3D/IDirect3D7.c b/src/IDirect3D/IDirect3D7.c index 5d64fc6..0102923 100644 --- a/src/IDirect3D/IDirect3D7.c +++ b/src/IDirect3D/IDirect3D7.c @@ -14,6 +14,11 @@ HRESULT __stdcall IDirect3D7__QueryInterface(IDirect3D7Impl* This, REFIID riid, HRESULT ret = E_FAIL; + if (riid) + { + TRACE("NOT_IMPLEMENTED GUID = %08X\n", ((GUID*)riid)->Data1); + } + TRACE("NOT_IMPLEMENTED <- %s\n", __FUNCTION__); return ret; } @@ -43,10 +48,20 @@ ULONG __stdcall IDirect3D7__Release(IDirect3D7Impl* This) return ret; } -HRESULT __stdcall IDirect3D7__EnumDevices(IDirect3D7Impl* This, int a, int b) +HRESULT __stdcall IDirect3D7__EnumDevices( + IDirect3D7Impl* This, + LPD3DENUMDEVICESCALLBACK7 lpEnumDevicesCallback, + LPVOID lpUserArg) { TRACE("NOT_IMPLEMENTED -> %s(This=%p) [%p]\n", __FUNCTION__, This, _ReturnAddress()); - HRESULT ret = E_FAIL; + HRESULT ret = S_OK; + + if (lpEnumDevicesCallback) + { + //D3DDEVICEDESC7 desc = { 0 }; + //lpEnumDevicesCallback("NULL", "NULL", &desc, lpUserArg); + } + TRACE("NOT_IMPLEMENTED <- %s\n", __FUNCTION__); return ret; } diff --git a/src/IDirectDraw/IDirectDraw.c b/src/IDirectDraw/IDirectDraw.c index ee6c653..9384714 100644 --- a/src/IDirectDraw/IDirectDraw.c +++ b/src/IDirectDraw/IDirectDraw.c @@ -18,7 +18,11 @@ HRESULT __stdcall IDirectDraw__QueryInterface(IDirectDrawImpl* This, REFIID riid HRESULT ret = E_NOINTERFACE; - if (riid) + if (!ppvObj) + { + ret = E_INVALIDARG; + } + else if (riid) { if (IsEqualGUID(&IID_IDirectDraw2, riid) || IsEqualGUID(&IID_IDirectDraw4, riid) || @@ -52,7 +56,7 @@ HRESULT __stdcall IDirectDraw__QueryInterface(IDirectDrawImpl* This, REFIID riid ret = S_OK; } - else if (IsEqualGUID(&IID_IDirect3D, riid) && !g_config.direct3d_passthrough) + else if (IsEqualGUID(&IID_IDirect3D, riid)) { IDirect3DImpl* d3d = (IDirect3DImpl*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DImpl)); @@ -66,7 +70,7 @@ HRESULT __stdcall IDirectDraw__QueryInterface(IDirectDrawImpl* This, REFIID riid ret = S_OK; } - else if (IsEqualGUID(&IID_IDirect3D2, riid) && !g_config.direct3d_passthrough) + else if (IsEqualGUID(&IID_IDirect3D2, riid)) { IDirect3D2Impl* d3d = (IDirect3D2Impl*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3D2Impl)); @@ -80,7 +84,7 @@ HRESULT __stdcall IDirectDraw__QueryInterface(IDirectDrawImpl* This, REFIID riid ret = S_OK; } - else if (IsEqualGUID(&IID_IDirect3D3, riid) && !g_config.direct3d_passthrough) + else if (IsEqualGUID(&IID_IDirect3D3, riid)) { IDirect3D3Impl* d3d = (IDirect3D3Impl*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3D3Impl)); @@ -94,7 +98,7 @@ HRESULT __stdcall IDirectDraw__QueryInterface(IDirectDrawImpl* This, REFIID riid ret = S_OK; } - else if (IsEqualGUID(&IID_IDirect3D7, riid) && !g_config.direct3d_passthrough) + else if (IsEqualGUID(&IID_IDirect3D7, riid)) { IDirect3D7Impl* d3d = (IDirect3D7Impl*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3D7Impl)); @@ -128,6 +132,12 @@ HRESULT __stdcall IDirectDraw__QueryInterface(IDirectDrawImpl* This, REFIID riid ret = S_OK; */ } + else if (((GUID*)riid)->Data1 == 0 && ((GUID*)riid)->Data2 == 0 && ((GUID*)riid)->Data3 == 0) + { + TRACE("NOT_IMPLEMENTED GUID = 0 0 0\n"); + + ret = E_NOINTERFACE; + } else { TRACE("NOT_IMPLEMENTED GUID = %08X\n", ((GUID*)riid)->Data1); @@ -318,8 +328,18 @@ HRESULT __stdcall IDirectDraw__EnumSurfaces( LPVOID lpContext, LPDDENUMSURFACESCALLBACK7 lpEnumSurfacesCallback) { - TRACE("NOT_IMPLEMENTED -> %s(This=%p) [%p]\n", __FUNCTION__, This, _ReturnAddress()); + TRACE( + "NOT_IMPLEMENTED -> %s(This=%p, dwFlags=%08X, lpDDSurfaceDesc=%p, lpContext=%p, lpEnumSurfacesCallback=%p) [%p]\n", + __FUNCTION__, + This, + dwFlags, + lpDDSurfaceDesc, + lpContext, + lpEnumSurfacesCallback, + _ReturnAddress()); + HRESULT ret = DD_OK; + TRACE("NOT_IMPLEMENTED <- %s\n", __FUNCTION__); return ret; } diff --git a/src/IDirectDraw/IDirectDrawClipper.c b/src/IDirectDraw/IDirectDrawClipper.c index 86b8a2f..6270c09 100644 --- a/src/IDirectDraw/IDirectDrawClipper.c +++ b/src/IDirectDraw/IDirectDrawClipper.c @@ -14,6 +14,12 @@ HRESULT __stdcall IDirectDrawClipper__QueryInterface(IDirectDrawClipperImpl* Thi _ReturnAddress()); HRESULT ret = E_NOINTERFACE; + + if (!ppvObj) + { + ret = E_INVALIDARG; + } + TRACE("NOT_IMPLEMENTED <- %s\n", __FUNCTION__); return ret; } diff --git a/src/IDirectDraw/IDirectDrawGammaControl.c b/src/IDirectDraw/IDirectDrawGammaControl.c index 65f61fa..d0bd36a 100644 --- a/src/IDirectDraw/IDirectDrawGammaControl.c +++ b/src/IDirectDraw/IDirectDrawGammaControl.c @@ -13,6 +13,12 @@ HRESULT __stdcall IDirectDrawGammaControl__QueryInterface(IDirectDrawGammaContro _ReturnAddress()); HRESULT ret = E_NOINTERFACE; + + if (!ppvObj) + { + ret = E_INVALIDARG; + } + TRACE("NOT_IMPLEMENTED <- %s\n", __FUNCTION__); return ret; } diff --git a/src/IDirectDraw/IDirectDrawPalette.c b/src/IDirectDraw/IDirectDrawPalette.c index a5429ea..0a6334a 100644 --- a/src/IDirectDraw/IDirectDrawPalette.c +++ b/src/IDirectDraw/IDirectDrawPalette.c @@ -15,6 +15,12 @@ HRESULT __stdcall IDirectDrawPalette__QueryInterface(IDirectDrawPaletteImpl* Thi _ReturnAddress()); HRESULT ret = E_NOINTERFACE; + + if (!ppvObj) + { + ret = E_INVALIDARG; + } + TRACE("NOT_IMPLEMENTED <- %s\n", __FUNCTION__); return ret; } diff --git a/src/IDirectDraw/IDirectDrawSurface.c b/src/IDirectDraw/IDirectDrawSurface.c index 8984571..7916405 100644 --- a/src/IDirectDraw/IDirectDrawSurface.c +++ b/src/IDirectDraw/IDirectDrawSurface.c @@ -11,7 +11,11 @@ HRESULT __stdcall IDirectDrawSurface__QueryInterface(IDirectDrawSurfaceImpl* Thi TRACE("-> %s(This=%p, riid=%08X, ppvObj=%p) [%p]\n", __FUNCTION__, This, (unsigned int)riid, ppvObj, _ReturnAddress()); HRESULT ret = S_OK; - if (riid) + if (!ppvObj) + { + ret = E_INVALIDARG; + } + else if (riid) { if (IsEqualGUID(&IID_IDirectDrawSurface, riid) || IsEqualGUID(&IID_IDirectDrawSurface2, riid) || @@ -336,7 +340,7 @@ HRESULT __stdcall IDirectDrawSurface__GetDC(IDirectDrawSurfaceImpl* This, HDC FA HRESULT __stdcall IDirectDrawSurface__GetFlipStatus(IDirectDrawSurfaceImpl* This, DWORD dwFlags) { - TRACE_EXT("-> %s(This=%p) [%p]\n", __FUNCTION__, This, _ReturnAddress()); + TRACE_EXT("-> %s(This=%p, dwFlags=%08X) [%p]\n", __FUNCTION__, This, dwFlags, _ReturnAddress()); HRESULT ret = DD_OK; TRACE_EXT("<- %s\n", __FUNCTION__); return ret; diff --git a/src/blt.c b/src/blt.c index 0c212aa..166e3dd 100644 --- a/src/blt.c +++ b/src/blt.c @@ -518,7 +518,7 @@ void blt_colorfill( if (bpp == 8 || (bpp == 16 && (color & 0xFF) == ((color >> 8) & 0xFF)) || - (bpp == 32 && + ((bpp == 32 || bpp == 24) && (color & 0xFF) == ((color >> 8) & 0xFF) && (color & 0xFF) == ((color >> 16) & 0xFF) && (color & 0xFF) == ((color >> 24) & 0xFF))) diff --git a/src/config.c b/src/config.c index 0ca96a5..36b756a 100644 --- a/src/config.c +++ b/src/config.c @@ -38,6 +38,7 @@ void cfg_load() GET_BOOL(g_config.fullscreen, "fullscreen", FALSE); GET_BOOL(g_config.windowed, "windowed", FALSE); GET_BOOL(g_config.maintas, "maintas", FALSE); + GET_STRING("aspect_ratio", "", g_config.aspect_ratio, sizeof(g_config.aspect_ratio)); GET_BOOL(g_config.boxing, "boxing", FALSE); GET_INT(g_config.maxfps, "maxfps", -1); GET_BOOL(g_config.vsync, "vsync", FALSE); @@ -51,6 +52,10 @@ void cfg_load() GET_INT(g_config.save_settings, "savesettings", 1); GET_BOOL(g_config.resizable, "resizable", TRUE); GET_INT(g_config.d3d9_filter, "d3d9_filter", FILTER_CUBIC); + GET_INT(g_config.anti_aliased_fonts_min_size, "anti_aliased_fonts_min_size", 13); + GET_INT(g_config.min_font_size, "min_font_size", 0); + GET_INT(g_config.center_window, "center_window", CENTER_WINDOW_AUTO); + GET_STRING("inject_resolution", "", g_config.inject_resolution, sizeof(g_config.inject_resolution)); GET_BOOL(g_config.vhack, "vhack", FALSE); GET_STRING("screenshotdir", ".\\Screenshots\\", g_config.screenshot_dir, sizeof(g_config.screenshot_dir)); GET_BOOL(g_config.toggle_borderless, "toggle_borderless", FALSE); @@ -62,50 +67,45 @@ void cfg_load() GET_INT(g_config.maxgameticks, "maxgameticks", 0); GET_INT(g_config.limiter_type, "limiter_type", LIMIT_AUTO); GET_INT(g_config.minfps, "minfps", 0); - GET_BOOL(g_config.nonexclusive, "nonexclusive", FALSE); + GET_BOOL(g_config.nonexclusive, "nonexclusive", TRUE); GET_BOOL(g_config.singlecpu, "singlecpu", TRUE); GET_INT(g_config.resolutions, "resolutions", RESLIST_NORMAL); GET_INT(g_config.fixchilds, "fixchilds", FIX_CHILDS_DETECT_PAINT); GET_BOOL(g_config.hook_peekmessage, "hook_peekmessage", FALSE); - GET_BOOL(g_config.hook_getmessage, "hook_getmessage", FALSE); /* Undocumented settings */ - GET_BOOL(g_config.releasealt, "releasealt", FALSE); + GET_BOOL(g_config.fix_alt_key_stuck, "fix_alt_key_stuck", FALSE); GET_BOOL(GameHandlesClose, "game_handles_close", FALSE); - GET_BOOL(g_config.fixnotresponding, "fixnotresponding", FALSE); - GET_INT(g_config.hook, "hook", 4); + GET_BOOL(g_config.fix_not_responding, "fix_not_responding", FALSE); + GET_BOOL(g_config.no_compat_warning, "no_compat_warning", FALSE); GET_INT(g_config.guard_lines, "guard_lines", 200); GET_INT(g_config.max_resolutions, "max_resolutions", 0); GET_BOOL(g_config.lock_surfaces, "lock_surfaces", FALSE); - GET_BOOL(g_config.allow_wmactivate, "allow_wmactivate", FALSE); GET_BOOL(g_config.flipclear, "flipclear", FALSE); - GET_BOOL(g_config.fixmousehook, "fixmousehook", FALSE); GET_BOOL(g_config.rgb555, "rgb555", FALSE); GET_BOOL(g_config.no_dinput_hook, "no_dinput_hook", FALSE); - GET_INT(g_config.refresh_rate, "refresh_rate", 0); - GET_INT(g_config.anti_aliased_fonts_min_size, "anti_aliased_fonts_min_size", 13); - GET_INT(g_config.custom_width, "custom_width", 0); - GET_INT(g_config.custom_height, "custom_height", 0); - GET_INT(g_config.min_font_size, "min_font_size", 0); - GET_BOOL(g_config.direct3d_passthrough, "direct3d_passthrough", FALSE); GET_BOOL(g_config.center_cursor_fix, "center_cursor_fix", FALSE); GET_STRING("fake_mode", "", g_config.fake_mode, sizeof(g_config.fake_mode)); - GET_BOOL(g_config.wine_allow_resize, "wine_allow_resize", FALSE); GET_BOOL(g_config.lock_mouse_top_left, "lock_mouse_top_left", FALSE); - GET_BOOL(g_config.no_compat_warning, "no_compat_warning", FALSE); + GET_STRING("win_version", "", g_config.win_version, sizeof(g_config.win_version)); + GET_INT(g_config.hook, "hook", 4); + GET_BOOL(g_config.limit_gdi_handles, "limit_gdi_handles", FALSE); + GET_BOOL(g_config.remove_menu, "remove_menu", FALSE); + GET_INT(g_config.refresh_rate, "refresh_rate", 0); + GET_BOOL(g_config.terminate_process, "terminate_process", FALSE); /* Hotkeys */ GET_INT(g_config.hotkeys.toggle_fullscreen, "keytogglefullscreen", VK_RETURN); + GET_INT(g_config.hotkeys.toggle_fullscreen2, "keytogglefullscreen2", 0); GET_INT(g_config.hotkeys.toggle_maximize, "keytogglemaximize", VK_NEXT); + GET_INT(g_config.hotkeys.toggle_maximize2, "keytogglemaximize2", 0); GET_INT(g_config.hotkeys.unlock_cursor1, "keyunlockcursor1", VK_TAB); GET_INT(g_config.hotkeys.unlock_cursor2, "keyunlockcursor2", VK_RCONTROL); GET_INT(g_config.hotkeys.screenshot, "keyscreenshot", VK_SNAPSHOT); /* Game specific settings */ - - GET_BOOL(g_config.remove_menu, "remove_menu", FALSE); /* Added for HoMM4 */ GET_BOOL(g_config.armadahack, "armadahack", FALSE); GET_BOOL(g_config.tshack, "tshack", FALSE); @@ -113,14 +113,19 @@ void cfg_load() GET_BOOL(g_config.stronghold_hack, "stronghold_hack", FALSE); GET_BOOL(g_config.mgs_hack, "mgs_hack", FALSE); GET_BOOL(g_config.tlc_hack, "tlc_hack", FALSE); - GET_BOOL(g_config.homm_hack, "homm_hack", FALSE); GET_BOOL(g_config.carma95_hack, "carma95_hack", FALSE); - + GET_BOOL(g_config.sirtech_hack, "sirtech_hack", FALSE); + GET_BOOL(g_config.flightsim98_hack, "flightsim98_hack", FALSE); + GET_BOOL(g_config.darkcolony_hack, "darkcolony_hack", FALSE); + GameHandlesClose = GameHandlesClose || g_config.infantryhack; if (g_config.lock_mouse_top_left) g_config.adjmouse = FALSE; + if (g_config.aspect_ratio[0]) + g_config.maintas = TRUE; + ini_free(&g_config.ini); } @@ -129,6 +134,10 @@ void cfg_save() if (!g_config.save_settings) return; + /* Do not save settings while macOS maximize is active */ + if (IsMacOS() && !g_config.window_rect.left && !g_config.window_rect.top) + return; + char buf[16]; char* section = g_config.save_settings == 1 ? "ddraw" : g_config.process_file_name; @@ -194,6 +203,9 @@ static void cfg_create_ini() "; Maintain aspect ratio\n" "maintas=false\n" "\n" + "; Use custom aspect ratio - Example values: 4:3, 16:10, 16:9, 21:9\n" + "aspect_ratio=\n" + "\n" "; Windowboxing / Integer Scaling\n" "boxing=false\n" "\n" @@ -239,6 +251,20 @@ static void cfg_create_ini() "; Possible values: 0 = nearest-neighbor, 1 = bilinear, 2 = bicubic, 3 = lanczos (bicubic/lanczos only support 16/32bit color depth games)\n" "d3d9_filter=2\n" "\n" + "; Disable font smoothing for fonts that are smaller than size X\n" + "anti_aliased_fonts_min_size=13\n" + "\n" + "; Raise the size of small fonts to X\n" + "min_font_size=0\n" + "\n" + "; Center window to screen when game changes the display resolution\n" + "; Possible values: 0 = never center, 1 = automatic, 2 = always center\n" + "center_window=1\n" + "\n" + "; Inject a custom display resolution into the in-game resolution list - Example values: 960x540, 3840x2160\n" + "; Note: This setting can used for downscaling as well, you can insert resolutions higher than your monitor supports\n" + "inject_resolution=\n" + "\n" "; Enable upscale hack for high resolution patches (Supports C&C1, Red Alert 1, Worms 2 and KKND Xtreme)\n" "vhack=false\n" "\n" @@ -265,7 +291,7 @@ static void cfg_create_ini() "; Note: Usually one of the following values will work: 60 / 30 / 25 / 20 / 15 (lower value = slower game speed)\n" "maxgameticks=0\n" "\n" - "; Method that should be used to limit game ticks (maxgameticks=): 0 = Automatic, 1 = TestCooperativeLevel, 2 = BltFast\n" + "; Method that should be used to limit game ticks (maxgameticks=): 0 = Automatic, 1 = TestCooperativeLevel, 2 = BltFast, 3 = Unlock, 4 = PeekMessage\n" "limiter_type=0\n" "\n" "; Force minimum FPS, possible values: 0 = disabled, -1 = use 'maxfps=' value, -2 = same as -1 but force full redraw, 1-1000 = custom FPS\n" @@ -274,50 +300,45 @@ static void cfg_create_ini() "\n" "; Disable fullscreen-exclusive mode for the direct3d9*/opengl* renderers\n" "; Note: Can be used in case some GUI elements like buttons/textboxes/videos/etc.. are invisible\n" - "nonexclusive=false\n" + "nonexclusive=true\n" "\n" "; Force CPU0 affinity, avoids crashes/freezing, *might* have a performance impact\n" "; Note: Disable this if the game is not running smooth or there are sound issues\n" "singlecpu=true\n" "\n" - "; Available resolutions, possible values: 0 = Small list, 1 = Very small list, 2 = Full list\n" + "; Available display resolutions, possible values: 0 = Small list, 1 = Very small list, 2 = Full list\n" "; Note: Set this to 2 if your chosen resolution is not working or does not show up in the list\n" "; Note: Set this to 1 if the game is crashing on startup\n" "resolutions=0\n" "\n" - "; Child window handling, possible values: 0 = Disabled, 1 = Display top left, 2 = Display top left + repaint, 3 = Hide\n" + "; Child window handling, possible values: 0 = Disabled, 1 = Display top left, 2 = Display top left + repaint, 3 = Hide, 4 = Display top left + hide\n" "; Note: Disables upscaling if a child window was detected (to ensure the game is fully playable, may look weird though)\n" "fixchilds=2\n" "\n" - "; Enable one of the following settings if your cursor doesn't work properly when upscaling is enabled\n" + "; Enable the following setting if your cursor doesn't lock to the window or it doesn't work properly when upscaling is enabled\n" "hook_peekmessage=false\n" - "hook_getmessage=false\n" "\n" "\n" - "; Undocumented settings - You may or may not change these (You should rather focus on the settings above)\n" - "releasealt=false\n" + "; Undocumented compatibility settings - These will probably not solve your problem, you should rather focus on the settings above\n" + "fix_alt_key_stuck=false\n" "game_handles_close=false\n" - "fixnotresponding=false\n" - "hook=4\n" + "fix_not_responding=false\n" + "no_compat_warning=false\n" "guard_lines=200\n" "max_resolutions=0\n" "lock_surfaces=false\n" - "allow_wmactivate=false\n" "flipclear=false\n" - "fixmousehook=false\n" "rgb555=false\n" "no_dinput_hook=false\n" - "refresh_rate=0\n" - "anti_aliased_fonts_min_size=13\n" - "custom_width=0\n" - "custom_height=0\n" - "min_font_size=0\n" - "direct3d_passthrough=false\n" "center_cursor_fix=false\n" ";fake_mode=640x480x32\n" - "wine_allow_resize=false\n" "lock_mouse_top_left=false\n" - "no_compat_warning=false\n" + ";win_version=95\n" + "hook=4\n" + "limit_gdi_handles=false\n" + "remove_menu=false\n" + "refresh_rate=0\n" + "terminate_process=false\n" "\n" "\n" "\n" @@ -329,9 +350,15 @@ static void cfg_create_ini() "; Switch between windowed and fullscreen mode = [Alt] + ???\n" "keytogglefullscreen=0x0D\n" "\n" + "; Switch between windowed and fullscreen mode (single key) = ???\n" + "keytogglefullscreen2=0x00\n" + "\n" "; Maximize window = [Alt] + ???\n" "keytogglemaximize=0x22\n" "\n" + "; Maximize window (single key) = ???\n" + "keytogglemaximize2=0x00\n" + "\n" "; Unlock cursor 1 = [Ctrl] + ???\n" "keyunlockcursor1=0x09\n" "\n" @@ -347,7 +374,7 @@ static void cfg_create_ini() "; The following settings are for cnc-ddraw config.exe\n" "\n" "\n" - "; cnc-ddraw config program language, possible values: auto, english, chinese, german, spanish, russian, hungarian, french, italian\n" + "; cnc-ddraw config program language, possible values: auto, english, chinese, german, spanish, russian, hungarian, french, italian, vietnamese, polish\n" "configlang=auto\n" "\n" "; cnc-ddraw config program theme, possible values: Windows10, Cobalt XEMedia\n" @@ -365,10 +392,23 @@ static void cfg_create_ini() "; The following settings override all settings shown above, section name = executable name\n" "\n" "\n" + "; 101: The Airborne Invasion of Normandy\n" + "[101]\n" + "terminate_process=true\n" + "\n" + "; 7th Legion\n" + "[legion]\n" + "maxgameticks=25\n" + "\n" "; Atrox\n" "[Atrox]\n" "nonexclusive=true\n" - "allow_wmactivate=true\n" + "\n" + "; Arcatera the Dark Brotherhood\n" + "[darksun]\n" + "maxgameticks=60\n" + "maxfps=60\n" + "minfps=-1\n" "\n" "; Atomic Bomberman\n" "[BM]\n" @@ -413,16 +453,32 @@ static void cfg_create_ini() "fake_mode=640x480x32\n" "nonexclusive=true\n" "\n" + "; Age of Wonders\n" + "[AoW]\n" + "resolutions=2\n" + "nonexclusive=false\n" + "singlecpu=false\n" + "\n" + "; Age of Wonders\n" + "[AoWCompat]\n" + "resolutions=2\n" + "nonexclusive=false\n" + "singlecpu=false\n" + "\n" + "; Age of Wonders Config Tool\n" + "[AoWSetup]\n" + "resolutions=2\n" + "\n" "; Age of Wonders 2\n" "[AoW2]\n" "resolutions=2\n" - "renderer=opengl\n" + "nonexclusive=false\n" "singlecpu=false\n" "\n" "; Age of Wonders 2\n" "[AoW2Compat]\n" "resolutions=2\n" - "renderer=opengl\n" + "nonexclusive=false\n" "singlecpu=false\n" "\n" "; Age of Wonders 2 Config Tool\n" @@ -432,13 +488,13 @@ static void cfg_create_ini() "; Age of Wonders: Shadow Magic\n" "[AoWSM]\n" "resolutions=2\n" - "renderer=opengl\n" + "nonexclusive=false\n" "singlecpu=false\n" "\n" "; Age of Wonders: Shadow Magic\n" "[AoWSMCompat]\n" "resolutions=2\n" - "renderer=opengl\n" + "nonexclusive=false\n" "singlecpu=false\n" "\n" "; Age of Wonders: Shadow Magic Config Tool\n" @@ -454,6 +510,30 @@ static void cfg_create_ini() "[1602]\n" "adjmouse=true\n" "\n" + "; Army Men: World War / Army Men: Operation Meltdown\n" + "[amww]\n" + "maxfps=60\n" + "maxgameticks=120\n" + "minfps=-1\n" + "\n" + "; Army Men: Air Tactics\n" + "[Amat]\n" + "maxfps=60\n" + "maxgameticks=120\n" + "minfps=-1\n" + "\n" + "; Army Men: Toys in Space\n" + "[ARMYMENTIS]\n" + "maxfps=60\n" + "maxgameticks=120\n" + "minfps=-1\n" + "\n" + "; Army Men 2\n" + "[ArmyMen2]\n" + "maxfps=60\n" + "maxgameticks=120\n" + "minfps=-1\n" + "\n" "; Alien Nations\n" "[AN]\n" "adjmouse=true\n" @@ -461,7 +541,7 @@ static void cfg_create_ini() "; Atlantis\n" "[ATLANTIS]\n" "renderer=opengl\n" - "maxgameticks=60\n" + "maxgameticks=30\n" "center_cursor_fix=true\n" "\n" "; Airline Tycoon Deluxe\n" @@ -473,15 +553,34 @@ static void cfg_create_ini() "[Arthur]\n" "renderer=gdi\n" "\n" - "; Barbie(R) Photo Designer\n" - "[pdcam]\n" - "allow_wmactivate=true\n" + "; Axis & Allies\n" + "[AxisAllies]\n" + "hook_peekmessage=true\n" + "maxgameticks=60\n" + "\n" + "; A Bug's Life Action Game\n" + "[bugs]\n" + "fix_not_responding=true\n" + "\n" + "; Barney - Secret of the Rainbow\n" + "[Barney]\n" + "adjmouse=false\n" + "width=0\n" + "height=0\n" + "resizable=false\n" + "maintas=false\n" + "boxing=false\n" "\n" "; Baldur's Gate II\n" "; Note: 'Use 3D Acceleration' must be disabled and 'Full Screen' must be enabled in BGConfig.exe\n" "[BGMain]\n" "resolutions=2\n" "\n" + "; Balls of Steel v1.2\n" + "[bos]\n" + "checkfile=.\\barbarin.ddp\n" + "win_version=95\n" + "\n" "; BALDR FORCE EXE\n" "[BaldrForce]\n" "noactivateapp=true\n" @@ -517,25 +616,32 @@ static void cfg_create_ini() "[ArtTime]\n" "renderer=gdi\n" "\n" + "; Callus 95 - CPS-1 (Capcom Play System 1) emulator\n" + "[CALLUS95]\n" + "game_handles_close=true\n" + "windowed=true\n" + "toggle_borderless=true\n" + "devmode=true\n" + "\n" + "; Callus 95 - CPS-1 (Capcom Play System 1) emulator\n" + "[CALLUS95p]\n" + "game_handles_close=true\n" + "windowed=true\n" + "toggle_borderless=true\n" + "devmode=true\n" + "\n" "; Carmageddon\n" "[CARMA95]\n" - "noactivateapp=true\n" "flipclear=true\n" "carma95_hack=true\n" "\n" "; Carmageddon\n" "[CARM95]\n" - "noactivateapp=true\n" "flipclear=true\n" "carma95_hack=true\n" "\n" - "; Carmageddon 2\n" - "[Carma2_SW]\n" - "noactivateapp=true\n" - "\n" "; Carmen Sandiego's Great Chase - NOT WORKING YET\n" "[TIME32]\n" - "allow_wmactivate=true\n" "renderer=gdi\n" "adjmouse=false\n" "width=0\n" @@ -589,6 +695,7 @@ static void cfg_create_ini() "\n" "; Command & Conquer: Tiberian Sun / Command & Conquer: Red Alert 2\n" "[game]\n" + "nonexclusive=false\n" "checkfile=.\\blowfish.dll\n" "tshack=true\n" "noactivateapp=true\n" @@ -600,6 +707,7 @@ static void cfg_create_ini() "\n" "; Command & Conquer: Tiberian Sun Demo\n" "[SUN]\n" + "nonexclusive=false\n" "noactivateapp=true\n" "tshack=true\n" "adjmouse=true\n" @@ -610,6 +718,7 @@ static void cfg_create_ini() "\n" "; Command & Conquer: Tiberian Sun - CnCNet\n" "[ts-spawn]\n" + "nonexclusive=false\n" "noactivateapp=true\n" "tshack=true\n" "adjmouse=true\n" @@ -620,6 +729,7 @@ static void cfg_create_ini() "\n" "; Command & Conquer: Red Alert 2 - XWIS\n" "[ra2]\n" + "nonexclusive=false\n" "noactivateapp=true\n" "tshack=true\n" "maxfps=60\n" @@ -629,6 +739,7 @@ static void cfg_create_ini() "\n" "; Command & Conquer: Red Alert 2 - XWIS\n" "[Red Alert 2]\n" + "nonexclusive=false\n" "noactivateapp=true\n" "tshack=true\n" "maxfps=60\n" @@ -638,6 +749,7 @@ static void cfg_create_ini() "\n" "; Command & Conquer: Red Alert 2: Yuri's Revenge\n" "[gamemd]\n" + "nonexclusive=false\n" "noactivateapp=true\n" "tshack=true\n" "maxfps=60\n" @@ -647,6 +759,7 @@ static void cfg_create_ini() "\n" "; Command & Conquer: Red Alert 2: Yuri's Revenge - ?ModExe?\n" "[ra2md]\n" + "nonexclusive=false\n" "noactivateapp=true\n" "tshack=true\n" "maxfps=60\n" @@ -656,6 +769,7 @@ static void cfg_create_ini() "\n" "; Command & Conquer: Red Alert 2: Yuri's Revenge - CnCNet\n" "[gamemd-spawn]\n" + "nonexclusive=false\n" "noactivateapp=true\n" "tshack=true\n" "maxfps=60\n" @@ -665,6 +779,7 @@ static void cfg_create_ini() "\n" "; Command & Conquer: Red Alert 2: Yuri's Revenge - XWIS\n" "[Yuri's Revenge]\n" + "nonexclusive=false\n" "noactivateapp=true\n" "tshack=true\n" "maxfps=60\n" @@ -680,13 +795,26 @@ static void cfg_create_ini() "[comandos_w10]\n" "maxgameticks=-1\n" "\n" + "; Constructor\n" + "[Game_W95]\n" + "noactivateapp=true\n" + "\n" "; Caesar III\n" "[c3]\n" "nonexclusive=true\n" "adjmouse=true\n" "\n" + "; Cloud Kingdom 3 (only with /ddraw command line parameter)\n" + "[Clouds Kingdom 3]\n" + "fake_mode=320x240x32\n" + "\n" + "; Commando 2004 (only with /ddraw command line parameter)\n" + "[commando]\n" + "fake_mode=320x240x32\n" + "\n" "; Chris Sawyer's Locomotion\n" - "[LOCO]\n" + "[LOCO/2]\n" + "checkfile=.\\LOCO.EXE\n" "adjmouse=true\n" "\n" "; Cultures 2\n" @@ -699,21 +827,30 @@ static void cfg_create_ini() "\n" "; Close Combat 2: A Bridge Too Far\n" "[cc2]\n" + "maxgameticks=20\n" + "limiter_type=4\n" + "minfps=15\n" "adjmouse=true\n" "nonexclusive=true\n" "\n" "; Close Combat 3: The Russian Front\n" "[cc3]\n" + "maxgameticks=30\n" + "limiter_type=2\n" "adjmouse=true\n" "nonexclusive=true\n" "\n" "; Close Combat 4: The Battle of the Bulge\n" "[cc4]\n" + "maxgameticks=30\n" + "limiter_type=2\n" "adjmouse=true\n" "nonexclusive=true\n" "\n" "; Close Combat 5: Invasion: Normandy\n" "[cc5]\n" + "maxgameticks=30\n" + "limiter_type=2\n" "adjmouse=true\n" "nonexclusive=true\n" "\n" @@ -744,17 +881,33 @@ static void cfg_create_ini() "[corsairs]\n" "adjmouse=true\n" "\n" + "; Dark Colony\n" + "[dc16]\n" + "maxgameticks=30\n" + "darkcolony_hack=true\n" + "hook_peekmessage=true\n" + "\n" "; Divine Divinity\n" "[div]\n" "resolutions=2\n" "singlecpu=false\n" "\n" + "; Die by the Sword\n" + "[windie]\n" + "maxgameticks=30\n" + "\n" "; Dragon Throne: Battle of Red Cliffs\n" "[AdSanguo]\n" "maxgameticks=60\n" "noactivateapp=true\n" "limiter_type=2\n" "\n" + "; Dark Secret of Africa\n" + "[Game/5]\n" + "checkfile=.\\CONFIG.CFG\n" + "maxfps=60\n" + "minfps=-1\n" + "\n" "; Dark Reign: The Future of War\n" "[DKReign]\n" "maxgameticks=60\n" @@ -764,6 +917,10 @@ static void cfg_create_ini() "maxgameticks=60\n" "noactivateapp=true\n" "\n" + "; Dreams to Realty\n" + "[windream]\n" + "maxgameticks=60\n" + "\n" "; Deadlock 2\n" "[DEADLOCK]\n" "fixchilds=0\n" @@ -779,6 +936,20 @@ static void cfg_create_ini() "[hellfire]\n" "devmode=true\n" "\n" + "; Disney Trivia Challenge\n" + "[DisneyTr]\n" + "fixchilds=3\n" + "lock_mouse_top_left=true\n" + "renderer=gdi\n" + "\n" + "; Discoworld Noir\n" + "[dn]\n" + "fake_mode=640x480x16\n" + "\n" + "; Dominion - Storm Over Gift 3\n" + "[dominion]\n" + "flipclear=true\n" + "\n" "; Escape Velocity Nova\n" "[EV Nova]\n" "nonexclusive=true\n" @@ -790,7 +961,7 @@ static void cfg_create_ini() "; Economic War\n" "[EcoW]\n" "maxgameticks=60\n" - "fixnotresponding=true\n" + "fix_not_responding=true\n" "\n" "; Emperor: Rise of the Middle Kingdom\n" "[Emperor]\n" @@ -799,15 +970,46 @@ static void cfg_create_ini() "\n" "; Enemy Infestation\n" "[EI]\n" - "hook_getmessage=true\n" + "hook_peekmessage=true\n" "\n" + "; F-16 Agressor\n" + "[f-16]\n" + "resolutions=1\n" + "\n" + "; Fallout Tactics: Brotherhood of Steel\n" + "[BOS/2]\n" + "checkfile=.\\binkw32.dll\n" + "hook_peekmessage=true\n" + "\n" + "; Fallout Tactics: Brotherhood of Steel\n" + "[BOS_HR]\n" + "hook_peekmessage=true\n" + "\n" + "; Fallout Tactics: Brotherhood of Steel\n" + "[FT Tools]\n" + "hook_peekmessage=true\n" + "\n" + "; Flight Simulator 98\n" + "[FLTSIM95]\n" + "flightsim98_hack=true\n" + "\n" + "; Flight Simulator 98\n" + "[FLTSIM98]\n" + "flightsim98_hack=true\n" + "\n" "; Fairy Tale About Father Frost, Ivan and Nastya\n" "[mrazik]\n" "guard_lines=0\n" "\n" + "; Fable\n" + "[Fable]\n" + "maxgameticks=59\n" + "limiter_type=4\n" + "\n" "; Final Liberation: Warhammer Epic 40000\n" "[Epic40k]\n" "hook_peekmessage=true\n" + "maxgameticks=125\n" "\n" "; Future Cop - L.A.P.D.\n" "[FCopLAPD]\n" @@ -851,6 +1053,10 @@ static void cfg_create_ini() "[Maze]\n" "renderer=gdi\n" "\n" + "; Glover\n" + "[glover]\n" + "fix_not_responding=true\n" + "\n" "; G-Police\n" "[GPOLICE]\n" "maxgameticks=60\n" @@ -859,6 +1065,8 @@ static void cfg_create_ini() "[gangsters]\n" "adjmouse=true\n" "nonexclusive=true\n" + "fixchilds=0\n" + "fake_mode=640x480x8\n" "\n" "; Grand Theft Auto\n" "[Grand Theft Auto]\n" @@ -878,42 +1086,55 @@ static void cfg_create_ini() "noactivateapp=true\n" "nonexclusive=true\n" "\n" + "; Girl Talk\n" + "[GirlTalk]\n" + "resolutions=2\n" + "game_handles_close=true\n" + "\n" "; Jazz Jackrabbit 2 plus\n" "[Jazz2]\n" - "keytogglefullscreen=0x08\n" - "custom_width=800\n" - "custom_height=450\n" + "inject_resolution=800x450\n" "\n" "; Jazz Jackrabbit 2\n" "[Jazz2_NonPlus]\n" - "keytogglefullscreen=0x08\n" - "custom_width=800\n" - "custom_height=450\n" + "inject_resolution=800x450\n" + "\n" + "; Jungle Storm\n" + "[Jstorm]\n" + "no_compat_warning=true\n" + "win_version=98\n" + "\n" + "; Hades Challenge\n" + "[HADESCH]\n" + "no_compat_warning=true\n" "\n" "; Heroes of Might and Magic II: The Succession Wars\n" "[HEROES2W]\n" "adjmouse=true\n" + "game_handles_close=true\n" + "keytogglefullscreen2=0x73\n" "\n" "; Heroes of Might and Magic III\n" "[Heroes3]\n" "renderer=opengl\n" "game_handles_close=true\n" - "homm_hack=true\n" + "keytogglefullscreen2=0x73\n" "\n" "; Heroes of Might and Magic III HD Mod\n" "[Heroes3 HD]\n" "renderer=opengl\n" "game_handles_close=true\n" - "homm_hack=true\n" + "keytogglefullscreen2=0x73\n" "\n" "; Heroes of Might and Magic III - Master of Puppets mod\n" "[MoP]\n" "game_handles_close=true\n" - "homm_hack=true\n" + "keytogglefullscreen2=0x73\n" "\n" "; Heroes of Might and Magic IV\n" "[heroes4]\n" - "homm_hack=true\n" + "remove_menu=true\n" + "keytogglefullscreen2=0x73\n" "\n" "; Hard Truck: Road to Victory\n" "[htruck]\n" @@ -921,13 +1142,25 @@ static void cfg_create_ini() "renderer=opengl\n" "noactivateapp=true\n" "\n" + "; Hooligans: Storm over Europe\n" + "[hooligans]\n" + "limit_gdi_handles=true\n" + "\n" + "; Imperialism 2: The Age of Exploration\n" + "[Imperialism II]\n" + "adjmouse=false\n" + "width=0\n" + "height=0\n" + "resizable=false\n" + "maintas=false\n" + "boxing=false\n" + "\n" "; Icewind Dale 2\n" "; Note: 'Full Screen' must be enabled in Config.exe\n" "; Note: 1070x602 is the lowest possible 16:9 resolution for the Widescreen patch (600/601 height will crash)\n" "[iwd2]\n" "resolutions=2\n" - "custom_width=1070\n" - "custom_height=602\n" + "inject_resolution=1070x602\n" "\n" "; Invictus\n" "[Invictus]\n" @@ -953,45 +1186,48 @@ static void cfg_create_ini() "; Jagged Alliance 2\n" "[ja2]\n" "singlecpu=false\n" - "fixmousehook=true\n" - "noactivateapp=true\n" - "releasealt=true\n" + "sirtech_hack=true\n" + "fix_alt_key_stuck=true\n" "\n" "; Jagged Alliance 2: Unfinished Business\n" "[JA2UB]\n" "singlecpu=false\n" - "fixmousehook=true\n" - "noactivateapp=true\n" - "releasealt=true\n" + "sirtech_hack=true\n" + "fix_alt_key_stuck=true\n" "\n" "; Jagged Alliance 2: Wildfire\n" "[WF6]\n" "singlecpu=false\n" - "fixmousehook=true\n" - "noactivateapp=true\n" - "releasealt=true\n" + "sirtech_hack=true\n" + "fix_alt_key_stuck=true\n" "\n" "; Jagged Alliance 2 - UC mod\n" "[JA2_UC]\n" "singlecpu=false\n" - "fixmousehook=true\n" - "noactivateapp=true\n" - "releasealt=true\n" + "sirtech_hack=true\n" + "fix_alt_key_stuck=true\n" "\n" "; Jagged Alliance 2 - Vengeance Reloaded mod\n" "[JA2_Vengeance]\n" "singlecpu=false\n" - "fixmousehook=true\n" - "noactivateapp=true\n" - "releasealt=true\n" + "sirtech_hack=true\n" + "fix_alt_key_stuck=true\n" "\n" - "; Jedi Knight Dark Forces 2\n" - "[JK]\n" - "direct3d_passthrough=true\n" + "; Jagged Alliance 2 - Vengeance Reloaded mod German exe\n" + "[JA2_Vengeance_DE]\n" + "singlecpu=false\n" + "sirtech_hack=true\n" + "fix_alt_key_stuck=true\n" "\n" - "; Kings Quest 8\n" - "[Mask]\n" - "renderer=opengl\n" + "; Jeopardy! - NOT WORKING YET\n" + "[jeoppc]\n" + "singlecpu=false\n" + "\n" + "; Karma Immortal Wrath\n" + "[karma]\n" + "fix_not_responding=true\n" + "maxgameticks=60\n" + "limiter_type=4\n" "\n" "; Konung\n" "[konung]\n" @@ -1019,6 +1255,29 @@ static void cfg_create_ini() "limiter_type=2\n" "maxgameticks=60\n" "\n" + "; Lode Runner 2\n" + "[LR2]\n" + "no_dinput_hook=true\n" + "fake_mode=640x480x16\n" + "\n" + "; Last Bronx\n" + "[LB]\n" + "maxgameticks=30\n" + "\n" + "; Lapis (lapis.mgame.com)\n" + "[Lapis]\n" + "fixchilds=3\n" + "lock_mouse_top_left=true\n" + "\n" + "; LEGO LOCO - NOT WORKING YET\n" + "[LOCO]\n" + "checkfile=.\\LEGO.INI\n" + "fake_mode=1024x768x16\n" + "posX=0\n" + "posY=0\n" + "border=false\n" + "fullscreen=false\n" + "\n" "; Little Bear Kindergarten/Preschool Thinking Adventures: Parent's Progress Report\n" "[LBPR]\n" "adjmouse=false\n" @@ -1050,6 +1309,18 @@ static void cfg_create_ini() "[Lionheart]\n" "hook_peekmessage=true\n" "\n" + "; Lost Vikings 2\n" + "[LOSTV95]\n" + "fake_mode=320x240x16\n" + "\n" + "; Nightmare Creatures\n" + "[NC]\n" + "maxgameticks=30\n" + "\n" + "; Moto Racer (software mode)\n" + "[moto]\n" + "maxgameticks=59\n" + "\n" "; Madeline 1st Grade Math\n" "[madmath1]\n" "nonexclusive=true\n" @@ -1060,6 +1331,9 @@ static void cfg_create_ini() "resizable=false\n" "maintas=false\n" "boxing=false\n" + "renderer=gdi\n" + "hook=2\n" + "win_version=nt4\n" "\n" "; Madeline 1st Grade Math: Progress Report\n" "[madpr]\n" @@ -1071,6 +1345,9 @@ static void cfg_create_ini() "resizable=false\n" "maintas=false\n" "boxing=false\n" + "renderer=gdi\n" + "hook=2\n" + "win_version=nt4\n" "\n" "; Madeline 2nd Grade Math\n" "[madmath2]\n" @@ -1082,6 +1359,9 @@ static void cfg_create_ini() "resizable=false\n" "maintas=false\n" "boxing=false\n" + "renderer=gdi\n" + "hook=2\n" + "win_version=nt4\n" "\n" "; Majesty Gold\n" "[Majesty]\n" @@ -1095,25 +1375,50 @@ static void cfg_create_ini() "[MajestyHD - Old]\n" "adjmouse=true\n" "\n" + "; Meat Puppet\n" + "[meat]\n" + "hook_peekmessage=true\n" + "\n" "; Mech Warrior 3\n" "[Mech3]\n" "nonexclusive=true\n" "\n" + "; Men In Black - NOT WORKING YET\n" + "[MIB]\n" + "hook=2\n" + "\n" "; Moorhuhn 2\n" "[Moorhuhn2]\n" - "releasealt=true\n" + "fix_alt_key_stuck=true\n" + "\n" + "; Metal Knight\n" + "[mk]\n" + "maxgameticks=60\n" + "limiter_type=4\n" "\n" "; New Robinson\n" "[ROBY]\n" "adjmouse=true\n" "hook_peekmessage=true\n" "\n" + "; Neo Sonic Universe\n" + "[nsu]\n" + "fake_mode=320x240x32\n" + "\n" + "; Neo Sonic Universe - battle mode\n" + "[nsu_battle]\n" + "fake_mode=320x240x32\n" + "\n" "; Nancy Drew (All games)\n" "[Game/3]\n" "checkfile=.\\Nancy.cid\n" "limiter_type=1\n" "maxgameticks=120\n" "\n" + "; NBA Full Court Press\n" + "[NBA_FCP]\n" + "fake_mode=640x480x8\n" + "\n" "; Nox\n" "[NOX]\n" "checkfile=.\\NOX.ICD\n" @@ -1138,6 +1443,14 @@ static void cfg_create_ini() "adjmouse=true\n" "renderer=gdi\n" "\n" + "; Pandora's Box Puzzle Game\n" + "[Pandora]\n" + "fixchilds=0\n" + "\n" + "; Paddle Bash Hotshot\n" + "[SPAGHSPaddle]\n" + "no_compat_warning=true\n" + "\n" "; Pajama Sam's Games to Play on Any Day\n" "[PJGAMES]\n" "renderer=gdi\n" @@ -1154,10 +1467,6 @@ static void cfg_create_ini() "[Pajama3]\n" "renderer=gdi\n" "\n" - "; Pajama Sam(r): Life is Rough When You Lose Your Stuff(tm)\n" - "[PajamaLRS]\n" - "keytogglefullscreen=0x08\n" - "\n" "; Pajama Sam's One-Stop Fun Shop\n" "[SamsFunShop]\n" "renderer=gdi\n" @@ -1211,10 +1520,6 @@ static void cfg_create_ini() "[puttputtjtc]\n" "renderer=gdi\n" "\n" - "; Putt-Putt: Pep's Birthday Surprise\n" - "[PuttsFunShop]\n" - "keytogglefullscreen=0x08\n" - "\n" "; Pizza Syndicate\n" "[Pizza2]\n" "renderer=opengl\n" @@ -1227,8 +1532,23 @@ static void cfg_create_ini() "[Pax Imperia]\n" "nonexclusive=true\n" "\n" + "; Play with the Teletubbies\n" + "[PlayWTT]\n" + "hook=3\n" + "\n" + "; Populous - The Beginning\n" + "[popTB]\n" + "singlecpu=false\n" + "\n" + "; Rage of Mages\n" + "[rom]\n" + "maxgameticks=60\n" + "limiter_type=4\n" + "singlecpu=true\n" + "\n" "; Railroad Tycoon II\n" "[RT2]\n" + "maxgameticks=60" "adjmouse=true\n" "\n" "; Reader Rabbit Thinking Ages 4-6 (US)\n" @@ -1260,6 +1580,20 @@ static void cfg_create_ini() "maintas=false\n" "boxing=false\n" "\n" + "; Real War\n" + "[RealWar]\n" + "maxgameticks=60\n" + "limiter_type=3\n" + "\n" + "; Return to Krondor\n" + "[RtK]\n" + "fixchilds=3\n" + "lock_mouse_top_left=true\n" + "limiter_type=2\n" + "game_handles_close=true\n" + "maxgameticks=59\n" + "anti_aliased_fonts_min_size=99\n" + "\n" "; ROAD RASH\n" "[RoadRash]\n" "adjmouse=true\n" @@ -1269,14 +1603,22 @@ static void cfg_create_ini() "[Game/4]\n" "checkfile=.\\Robin Hood.exe\n" "singlecpu=false\n" + "fix_not_responding=true\n" "\n" "; Robin Hood - The Legend of Sherwood (Steam)\n" "[_rh]\n" "singlecpu=false\n" + "fix_not_responding=true\n" "\n" "; Robin Hood - The Legend of Sherwood\n" "[Robin Hood]\n" "singlecpu=false\n" + "fix_not_responding=true\n" + "\n" + "; Rising Lands\n" + "[Rising]\n" + "maxgameticks=30\n" + "limiter_type=4\n" "\n" "; Scooby-Doo(TM), Case File #1 The Glowing Bug Man - NOT WORKING YET\n" "[Case File #1]\n" @@ -1284,6 +1626,21 @@ static void cfg_create_ini() "nonexclusive=true\n" "fake_mode=640x480x32\n" "\n" + "; Seven Kingdoms II\n" + "[7k2]\n" + "fake_mode=352x240x32\n" + "fix_not_responding=true\n" + "\n" + "; Seven Games of the Soul\n" + "[faust]\n" + "maxgameticks=25\n" + "\n" + "; Swarog\n" + "[Swarog]\n" + "maxfps=60\n" + "maxgameticks=60\n" + "minfps=-1\n" + "\n" "; Sim Copter\n" "[SimCopter]\n" "nonexclusive=true\n" @@ -1300,6 +1657,15 @@ static void cfg_create_ini() "maintas=false\n" "boxing=false\n" "\n" + "; Star Wars Rebellion\n" + "[REBEXE]\n" + "adjmouse=false\n" + "width=0\n" + "height=0\n" + "resizable=false\n" + "maintas=false\n" + "boxing=false\n" + "\n" "; Star Wars: Galactic Battlegrounds\n" "[battlegrounds]\n" "nonexclusive=true\n" @@ -1367,16 +1733,45 @@ static void cfg_create_ini() "; Sim City 3000\n" "[SC3]\n" "minfps=-2\n" + "maxgameticks=60\n" + "\n" + "; SimTunes\n" + "[SIMTUNES]\n" + "terminate_process=true\n" + "hook=3\n" + "\n" + "; Street Wars: Constructor Underworld\n" + "[Sw]\n" + "checkfile=.\\smackw32.dll\n" + "maxgameticks=30\n" + "limiter_type=4\n" "\n" "; Shadow Watch\n" - "[sw]\n" + "[sw/2]\n" + "checkfile=.\\Dx.dll\n" "adjmouse=true\n" + "maxgameticks=30\n" + "hook_peekmessage=true\n" "\n" "; Shadow Flare\n" "[ShadowFlare]\n" "nonexclusive=true\n" "adjmouse=true\n" "\n" + "; Squad Leader\n" + "[SquadLeader]\n" + "maxgameticks=30\n" + "limiter_type=4\n" + "\n" + "; Soldiers At War\n" + "[SAW_Game]\n" + "maxgameticks=30\n" + "limiter_type=4\n" + "\n" + "; The Tone Rebellion\n" + "[Float]\n" + "hook_peekmessage=true\n" + "\n" "; Total Annihilation (Unofficial Beta Patch v3.9.02)\n" "[TotalA]\n" "max_resolutions=32\n" @@ -1389,6 +1784,10 @@ static void cfg_create_ini() "lock_surfaces=true\n" "singlecpu=false\n" "\n" + "; Virtual Springfield\n" + "[VIRTUAL]\n" + "game_handles_close=true\n" + "\n" "; Total Annihilation: Kingdoms\n" "[Kingdoms]\n" "game_handles_close=true\n" @@ -1415,12 +1814,21 @@ static void cfg_create_ini() "maintas=false\n" "boxing=false\n" "\n" + "; The Jungle Book Groove Party\n" + "[Jungle_vr]\n" + "fix_not_responding=true\n" + "\n" "; Three Kingdoms: Fate of the Dragon\n" "[sanguo]\n" "maxgameticks=60\n" "noactivateapp=true\n" "limiter_type=2\n" "\n" + "; Thomas & Friends - The Great Festival Adventure\n" + "[Thomas]\n" + "no_compat_warning=true\n" + "noactivateapp=true\n" + "\n" "; RollerCoaster Tycoon\n" "[rct]\n" "no_dinput_hook=true\n" @@ -1448,6 +1856,13 @@ static void cfg_create_ini() "[Tzar]\n" "adjmouse=true\n" "\n" + "; Unreal\n" + "[Unreal]\n" + "adjmouse=false\n" + "lock_mouse_top_left=true\n" + "center_cursor_fix=true\n" + "noactivateapp=true\n" + "\n" "; Uprising\n" "[uprising]\n" "adjmouse=true\n" @@ -1462,11 +1877,36 @@ static void cfg_create_ini() "adjmouse=true\n" "fake_mode=640x480x32\n" "\n" + "; Virtua Fighter 2\n" + "[VF2]\n" + "fake_mode=640x480x8\n" + "\n" + "; Virtual On: Cyber Troopers\n" + "[V_ON]\n" + "devmode=true\n" + "windowed=true\n" + "fullscreen=true\n" + "toggle_borderless=true\n" + "\n" + "; Wall Street Trader 2000 - NOT WORKING YET\n" + "[WSTrader]\n" + "nonexclusive=false\n" + "windowed=false\n" + "\n" + "; WarCraft 2000: Nuclear Epidemic\n" + "[war2000]\n" + "resolutions=2\n" + "guard_lines=600\n" + "minfps=-2\n" + "\n" + "; Warhammer 40000: Chaos Gate\n" + "[WH40K]\n" + "maxgameticks=250\n" + "\n" "; Wizardry 8\n" "[Wiz8]\n" - "fixmousehook=true\n" - "noactivateapp=true\n" - "releasealt=true\n" + "sirtech_hack=true\n" + "fix_alt_key_stuck=true\n" "\n" "; Worms 2\n" "[worms2]\n" @@ -1477,19 +1917,30 @@ static void cfg_create_ini() "\n" "; Worms Armageddon\n" "[WA]\n" - "adjmouse=true\n" - "width=0\n" - "height=0\n" - "resizable=false\n" + "lock_mouse_top_left=true\n" + "\n" + "; Wheel Of Fortune\n" + "[WHEEL]\n" + "singlecpu=false\n" "\n" "; War Wind\n" "[WW]\n" "minfps=-1\n" "\n" + "; Jeff Wayne's 'The War Of The Worlds'\n" + "[WoW]\n" + "minfps=-1\n" + "\n" "; Zeus and Poseidon\n" "[Zeus]\n" "adjmouse=true\n" "\n" + "; Zork Nemesis\n" + "[znemesis]\n" + "fix_not_responding=true\n" + "maxgameticks=60\n" + "limiter_type=4\n" + "\n" , fh); fclose(fh); diff --git a/src/crc32.c b/src/crc32.c index 826842f..e7ff75d 100644 --- a/src/crc32.c +++ b/src/crc32.c @@ -77,6 +77,29 @@ unsigned long Crc32_ComputeBuf( unsigned long inCrc32, const void *buf, return( crc32 ^ 0xFFFFFFFF ); } +unsigned long Crc32_FromFile(unsigned long crc32, char* filename) +{ + if (!filename) + return 0; + + FILE* fp = fopen(filename, "rb"); + if (!fp) + return 0; + + char buf[1024]; + for (size_t s = 0; (s = fread(buf, 1, sizeof(buf), fp)) && !ferror(fp);) + { + crc32 = Crc32_ComputeBuf(crc32, buf, s); + } + + if (ferror(fp)) + crc32 = 0; + + fclose(fp); + + return crc32; +} + /*----------------------------------------------------------------------------*\ * END OF MODULE: crc32.c \*----------------------------------------------------------------------------*/ diff --git a/src/dd.c b/src/dd.c index 42921db..b9e5b12 100644 --- a/src/dd.c +++ b/src/dd.c @@ -6,6 +6,7 @@ #include "hook.h" #include "config.h" #include "mouse.h" +#include "keyboard.h" #include "wndproc.h" #include "render_d3d9.h" #include "render_gdi.h" @@ -27,6 +28,7 @@ HRESULT dd_EnumDisplayModes( { dbg_dump_edm_flags(dwFlags); + DDSURFACEDESC2 s = { 0 }; DWORD bpp_filter = 0; if (lpDDSurfaceDesc) @@ -46,12 +48,48 @@ HRESULT dd_EnumDisplayModes( bpp_filter = lpDDSurfaceDesc->ddpfPixelFormat.dwRGBBitCount; break; } + + if ((lpDDSurfaceDesc->dwFlags & DDSD_WIDTH) && (lpDDSurfaceDesc->dwFlags & DDSD_HEIGHT)) + { + TRACE(" dwWidth=%u, dwHeight=%u\n", lpDDSurfaceDesc->dwWidth, lpDDSurfaceDesc->dwHeight); + + s.dwSize = sizeof(DDSURFACEDESC); + s.dwFlags = DDSD_HEIGHT | DDSD_REFRESHRATE | DDSD_WIDTH | DDSD_PITCH | DDSD_PIXELFORMAT; + s.dwRefreshRate = 60; + s.dwHeight = lpDDSurfaceDesc->dwHeight; + s.dwWidth = lpDDSurfaceDesc->dwWidth; + + s.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT); + s.ddpfPixelFormat.dwFlags = DDPF_PALETTEINDEXED8 | DDPF_RGB; + s.ddpfPixelFormat.dwRGBBitCount = 8; + + if (lpDDSurfaceDesc->ddpfPixelFormat.dwRGBBitCount == 16) + { + s.ddpfPixelFormat.dwFlags = DDPF_RGB; + s.ddpfPixelFormat.dwRGBBitCount = 16; + s.ddpfPixelFormat.dwRBitMask = 0xF800; + s.ddpfPixelFormat.dwGBitMask = 0x07E0; + s.ddpfPixelFormat.dwBBitMask = 0x001F; + } + else if (lpDDSurfaceDesc->ddpfPixelFormat.dwRGBBitCount == 32) + { + s.ddpfPixelFormat.dwFlags = DDPF_RGB; + s.ddpfPixelFormat.dwRGBBitCount = 32; + s.ddpfPixelFormat.dwRBitMask = 0xFF0000; + s.ddpfPixelFormat.dwGBitMask = 0x00FF00; + s.ddpfPixelFormat.dwBBitMask = 0x0000FF; + } + + s.lPitch = ((s.dwWidth * s.ddpfPixelFormat.dwRGBBitCount + 63) & ~63) >> 3; + + lpEnumModesCallback((LPDDSURFACEDESC)&s, lpContext); + return DD_OK; + } } } DWORD i = 0; DWORD res_count = 0; - DDSURFACEDESC2 s; /* Some games crash when you feed them with too many resolutions so we have to keep the list short */ @@ -75,6 +113,11 @@ HRESULT dd_EnumDisplayModes( while (--max_w % 8); } + char* ires = &g_config.inject_resolution[0]; + + unsigned long custom_width = strtoul(ires, &ires, 0); + unsigned long custom_height = strtoul(ires + 1, &ires, 0); + BOOL rlf = g_config.resolutions == RESLIST_FULL; BOOL rlm = g_config.resolutions == RESLIST_MINI; @@ -111,7 +154,7 @@ HRESULT dd_EnumDisplayModes( { rlf ? 1720 : 0, rlf ? 720 : 0 }, { rlf ? 2560 : 0, rlf ? 1080 : 0 }, /* Inject custom resolution */ - { g_config.custom_width, g_config.custom_height }, + { custom_width, custom_height }, { max_w, max_h }, }; @@ -124,7 +167,8 @@ HRESULT dd_EnumDisplayModes( } } - if ((g_ddraw.bpp && g_config.resolutions == RESLIST_NORMAL) || g_config.resolutions == RESLIST_FULL) + if (((g_ddraw.bpp && !g_ddraw.windowed_hack) && g_config.resolutions == RESLIST_NORMAL) || + g_config.resolutions == RESLIST_FULL) { TRACE(" g_ddraw.bpp=%u\n", g_ddraw.bpp); @@ -189,10 +233,10 @@ HRESULT dd_EnumDisplayModes( while (--m.dmPelsWidth % 8); } - if (!custom_res_injected && g_config.custom_width && g_config.custom_height) + if (!custom_res_injected && custom_width && custom_height) { - m.dmPelsWidth = g_config.custom_width; - m.dmPelsHeight = g_config.custom_height; + m.dmPelsWidth = custom_width; + m.dmPelsHeight = custom_height; custom_res_injected = TRUE; } @@ -301,14 +345,14 @@ HRESULT dd_EnumDisplayModes( } } - if (!g_ddraw.bpp || g_config.resolutions != RESLIST_NORMAL) + if (!g_ddraw.bpp || g_config.resolutions != RESLIST_NORMAL || g_ddraw.windowed_hack) { for (i = 0; i < sizeof(resolutions) / sizeof(resolutions[0]); i++) { if (!resolutions[i].cx || !resolutions[i].cy) continue; - if (!(resolutions[i].cx == g_config.custom_width && resolutions[i].cy == g_config.custom_height) && + if (!(resolutions[i].cx == custom_width && resolutions[i].cy == custom_height) && ((max_w && resolutions[i].cx > max_w) || (max_h && resolutions[i].cy > max_h))) { DEVMODE m; @@ -448,7 +492,18 @@ HRESULT dd_GetCaps(LPDDCAPS_DX1 lpDDDriverCaps, LPDDCAPS_DX1 lpDDEmulCaps) lpDDDriverCaps->dwVidMemTotal = 16777216; lpDDDriverCaps->dwVidMemFree = 16777216; - lpDDDriverCaps->ddsCaps.dwCaps = DDSCAPS_FLIP; + + lpDDDriverCaps->ddsCaps.dwCaps = + DDSCAPS_BACKBUFFER | + DDSCAPS_COMPLEX | + DDSCAPS_FLIP | + DDSCAPS_FRONTBUFFER | + DDSCAPS_OFFSCREENPLAIN | + DDSCAPS_PRIMARYSURFACE | + DDSCAPS_VIDEOMEMORY | + DDSCAPS_OWNDC | + DDSCAPS_LOCALVIDMEM | + DDSCAPS_NONLOCALVIDMEM; } if (lpDDEmulCaps) @@ -463,6 +518,7 @@ HRESULT dd_GetCaps(LPDDCAPS_DX1 lpDDDriverCaps, LPDDCAPS_DX1 lpDDEmulCaps) memset(lpDDEmulCaps, 0, size); lpDDEmulCaps->dwSize = size; + lpDDEmulCaps->dwCaps = DDCAPS_BLTSTRETCH; } return DD_OK; @@ -504,7 +560,7 @@ HRESULT dd_GetDisplayMode(LPDDSURFACEDESC lpDDSurfaceDesc) lpDDSurfaceDesc->dwWidth = width; lpDDSurfaceDesc->dwHeight = height; - if (bpp == 32) + if (bpp == 32 || bpp == 24) { lpDDSurfaceDesc->ddpfPixelFormat.dwFlags = DDPF_RGB; lpDDSurfaceDesc->ddpfPixelFormat.dwRBitMask = 0xFF0000; @@ -539,6 +595,29 @@ HRESULT dd_GetMonitorFrequency(LPDWORD lpdwFreq) return DD_OK; } +HRESULT dd_GetVerticalBlankStatus(LPBOOL lpbIsInVB) +{ + if (!lpbIsInVB) + return DDERR_INVALIDPARAMS; + + static DWORD last_vb; + DWORD tick = GetTickCount(); + + if (last_vb + 16 > tick) + { + *lpbIsInVB = FALSE; + } + else + { + last_vb = tick; + *lpbIsInVB = TRUE; + } + + TRACE(" lpbIsInVB = %s\n", *lpbIsInVB ? "TRUE" : "FALSE"); + + return DD_OK; +} + HRESULT dd_RestoreDisplayMode() { if (!g_ddraw.render.run) @@ -570,6 +649,8 @@ HRESULT dd_RestoreDisplayMode() } } + //real_ShowWindow(g_ddraw.hwnd, SW_MINIMIZE); + return DD_OK; } @@ -630,9 +711,14 @@ HRESULT dd_SetDisplayMode(DWORD dwWidth, DWORD dwHeight, DWORD dwBPP, DWORD dwFl g_ddraw.render.height = g_config.window_rect.bottom; /* temporary fix: center window for games that keep changing their resolution */ - if ((g_ddraw.width || g_config.infantryhack) && + if (g_config.center_window && + (g_ddraw.width || g_config.infantryhack || g_config.center_window == CENTER_WINDOW_ALWAYS) && (g_ddraw.width != dwWidth || g_ddraw.height != dwHeight) && - (dwWidth > g_config.window_rect.right || dwHeight > g_config.window_rect.bottom)) + ( + dwWidth > g_config.window_rect.right || + dwHeight > g_config.window_rect.bottom || + g_config.center_window == CENTER_WINDOW_ALWAYS) + ) { g_config.window_rect.left = -32000; g_config.window_rect.top = -32000; @@ -642,8 +728,8 @@ HRESULT dd_SetDisplayMode(DWORD dwWidth, DWORD dwHeight, DWORD dwBPP, DWORD dwFl g_ddraw.height = dwHeight; g_ddraw.bpp = dwBPP; - //InterlockedExchange((LONG*)&g_ddraw.cursor.x, dwWidth / 2); - //InterlockedExchange((LONG*)&g_ddraw.cursor.y, dwHeight / 2); + InterlockedExchange((LONG*)&g_ddraw.cursor.x, dwWidth / 2); + InterlockedExchange((LONG*)&g_ddraw.cursor.y, dwHeight / 2); BOOL border = g_config.border; BOOL nonexclusive = FALSE; @@ -804,6 +890,7 @@ HRESULT dd_SetDisplayMode(DWORD dwWidth, DWORD dwHeight, DWORD dwBPP, DWORD dwFl g_config.windowed = TRUE; g_config.fullscreen = TRUE; + g_config.toggle_borderless = TRUE; border = FALSE; /* prevent OpenGL from going automatically into fullscreen exclusive mode */ @@ -841,15 +928,12 @@ HRESULT dd_SetDisplayMode(DWORD dwWidth, DWORD dwHeight, DWORD dwBPP, DWORD dwFl if (g_config.boxing) { - g_ddraw.render.viewport.width = g_ddraw.width; - g_ddraw.render.viewport.height = g_ddraw.height; - for (int i = 20; i-- > 1;) { if (g_ddraw.width * i <= g_ddraw.render.width && g_ddraw.height * i <= g_ddraw.render.height) { - g_ddraw.render.viewport.width *= i; - g_ddraw.render.viewport.height *= i; + g_ddraw.render.viewport.width = i * g_ddraw.width; + g_ddraw.render.viewport.height = i * g_ddraw.height; break; } } @@ -859,8 +943,22 @@ HRESULT dd_SetDisplayMode(DWORD dwWidth, DWORD dwHeight, DWORD dwBPP, DWORD dwFl } else if (g_config.maintas) { - double dst_ar = (double)g_ddraw.height / g_ddraw.width; - double src_ar = (double)g_ddraw.render.height / g_ddraw.render.width; + double dst_ar; + double src_ar = (double)g_ddraw.render.height / g_ddraw.render.width;; + + if (g_config.aspect_ratio[0]) + { + char* e = &g_config.aspect_ratio[0]; + + DWORD cx = strtoul(e, &e, 0); + DWORD cy = strtoul(e + 1, &e, 0); + + dst_ar = (double)cy / cx; + } + else + { + dst_ar = (double)g_ddraw.height / g_ddraw.width; + } g_ddraw.render.viewport.width = g_ddraw.render.width; g_ddraw.render.viewport.height = (int)round(dst_ar * g_ddraw.render.viewport.width); @@ -937,9 +1035,15 @@ HRESULT dd_SetDisplayMode(DWORD dwWidth, DWORD dwHeight, DWORD dwBPP, DWORD dwFl if (g_config.remove_menu && GetMenu(g_ddraw.hwnd)) SetMenu(g_ddraw.hwnd, NULL); - if (!IsWine()) + if (!g_config.fix_not_responding && + g_ddraw.last_msg_pull_tick && + g_ddraw.last_msg_pull_tick + 1000 < timeGetTime() && + GetCurrentThreadId() == g_ddraw.gui_thread_id && + !IsWine()) { - MSG msg; /* workaround for "Not Responding" window problem in cnc games */ + /* workaround for "Not Responding" window problem in cnc games */ + g_ddraw.last_msg_pull_tick = timeGetTime(); + MSG msg; real_PeekMessageA(&msg, g_ddraw.hwnd, 0, 0, PM_NOREMOVE | PM_QS_INPUT); } @@ -958,6 +1062,12 @@ HRESULT dd_SetDisplayMode(DWORD dwWidth, DWORD dwHeight, DWORD dwBPP, DWORD dwFl g_ddraw.hwnd, GWL_STYLE, (real_GetWindowLongA(g_ddraw.hwnd, GWL_STYLE) | WS_OVERLAPPEDWINDOW) & ~(WS_MAXIMIZE)); + + DWORD class_sytle = GetClassLongA(g_ddraw.hwnd, GCL_STYLE); + if (class_sytle & CS_NOCLOSE) + { + SetClassLongA(g_ddraw.hwnd, GCL_STYLE, class_sytle & ~CS_NOCLOSE); + } } LONG exstyle = real_GetWindowLongA(g_ddraw.hwnd, GWL_EXSTYLE); @@ -974,12 +1084,14 @@ HRESULT dd_SetDisplayMode(DWORD dwWidth, DWORD dwHeight, DWORD dwBPP, DWORD dwFl real_SetWindowLongA(g_ddraw.hwnd, GWL_EXSTYLE, exstyle & ~(WS_EX_CLIENTEDGE)); } - if (!g_config.wine_allow_resize && IsWine()) + if (IsWine()) { + LONG remove_flags = !g_config.resizable ? (WS_MAXIMIZEBOX | WS_THICKFRAME) : 0; + real_SetWindowLongA( g_ddraw.hwnd, GWL_STYLE, - (real_GetWindowLongA(g_ddraw.hwnd, GWL_STYLE) | WS_MINIMIZEBOX) & ~(WS_MAXIMIZEBOX | WS_THICKFRAME)); + (real_GetWindowLongA(g_ddraw.hwnd, GWL_STYLE) | WS_MINIMIZEBOX) & ~(remove_flags)); } /* center the window with correct dimensions */ @@ -1055,7 +1167,7 @@ HRESULT dd_SetDisplayMode(DWORD dwWidth, DWORD dwHeight, DWORD dwBPP, DWORD dwFl if (GetMenu(g_ddraw.hwnd)) { - if (g_config.remove_menu || !g_config.nonexclusive) + if (1) // g_config.remove_menu || !g_config.nonexclusive) { SetMenu(g_ddraw.hwnd, NULL); } @@ -1142,6 +1254,7 @@ HRESULT dd_SetDisplayMode(DWORD dwWidth, DWORD dwHeight, DWORD dwBPP, DWORD dwFl g_ddraw.render.run = FALSE; g_config.windowed = TRUE; g_config.fullscreen = TRUE; + g_config.toggle_borderless = TRUE; return dd_SetDisplayMode(dwWidth, dwHeight, dwBPP, dwFlags); } @@ -1149,7 +1262,7 @@ HRESULT dd_SetDisplayMode(DWORD dwWidth, DWORD dwHeight, DWORD dwBPP, DWORD dwFl Fix wayland bug: ChangeDisplaySettings fails silently - enable borderless mode in case display resolution was not changed */ - if (IsWine() && + if (IsWine() && !IsSteamDeck() && (g_ddraw.render.mode.dmPelsWidth != real_GetSystemMetrics(SM_CXSCREEN) || g_ddraw.render.mode.dmPelsHeight != real_GetSystemMetrics(SM_CYSCREEN))) { @@ -1158,6 +1271,7 @@ HRESULT dd_SetDisplayMode(DWORD dwWidth, DWORD dwHeight, DWORD dwBPP, DWORD dwFl g_ddraw.render.run = FALSE; g_config.windowed = TRUE; g_config.fullscreen = TRUE; + g_config.toggle_borderless = TRUE; return dd_SetDisplayMode(dwWidth, dwHeight, dwBPP, dwFlags); } } @@ -1227,7 +1341,8 @@ HRESULT dd_SetDisplayMode(DWORD dwWidth, DWORD dwHeight, DWORD dwBPP, DWORD dwFl InterlockedExchange(&g_ddraw.render.surface_updated, TRUE); ReleaseSemaphore(g_ddraw.render.sem, 1, NULL); - g_ddraw.render.thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)g_ddraw.renderer, NULL, 0, NULL); + DWORD tid; + g_ddraw.render.thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)g_ddraw.renderer, NULL, 0, &tid); SetThreadPriority(g_ddraw.render.thread, THREAD_PRIORITY_ABOVE_NORMAL); } @@ -1237,6 +1352,21 @@ HRESULT dd_SetDisplayMode(DWORD dwWidth, DWORD dwHeight, DWORD dwBPP, DWORD dwFl real_SendMessageA(g_ddraw.hwnd, WM_DISPLAYCHANGE_DDRAW, g_ddraw.bpp, MAKELPARAM(g_ddraw.width, g_ddraw.height)); } + TRACE( + " render res=%ux%u (viewport res=%ux%u, x=%d, y=%d)\n", + g_ddraw.render.width, + g_ddraw.render.height, + g_ddraw.render.viewport.width, + g_ddraw.render.viewport.height, + g_ddraw.render.viewport.x, + g_ddraw.render.viewport.y); + + TRACE( + " windowed=%s, fullscreen=%s, adjmouse=%s\n", + g_config.windowed ? "true" : "false", + g_config.fullscreen ? "true" : "false", + g_config.adjmouse ? "true" : "false"); + return DD_OK; } @@ -1272,6 +1402,8 @@ HRESULT dd_SetCooperativeLevel(HWND hwnd, DWORD dwFlags) g_ddraw.wndproc = (WNDPROC)real_SetWindowLongA(g_ddraw.hwnd, GWL_WNDPROC, (LONG)fake_WndProc); g_ddraw.gui_thread_id = GetWindowThreadProcessId(g_ddraw.hwnd, NULL); + keyboard_hook_init(); + if (!g_ddraw.render.hdc) { g_ddraw.render.hdc = GetDC(g_ddraw.hwnd); @@ -1294,10 +1426,7 @@ HRESULT dd_SetCooperativeLevel(HWND hwnd, DWORD dwFlags) if (!g_config.devmode) { - HCURSOR cursor = real_SetCursor(LoadCursor(NULL, IDC_ARROW)); - - if (cursor != LoadCursor(NULL, IDC_WAIT)) - InterlockedExchange((LONG*)&g_ddraw.old_cursor, (LONG)cursor); + InterlockedExchange((LONG*)&g_ddraw.old_cursor, (LONG)real_SetCursor(LoadCursor(NULL, IDC_ARROW))); } int cursor_count = real_ShowCursor(TRUE) - 1; @@ -1401,7 +1530,7 @@ HRESULT dd_SetCooperativeLevel(HWND hwnd, DWORD dwFlags) } } - if (dwFlags & DDSCL_NORMAL) + if ((dwFlags & DDSCL_NORMAL) && !(dwFlags & DDSCL_FULLSCREEN)) { if (g_config.fake_mode[0]) { @@ -1413,6 +1542,25 @@ HRESULT dd_SetCooperativeLevel(HWND hwnd, DWORD dwFlags) dd_SetDisplayMode(width, height, bpp, 0); } + else if (!g_ddraw.width) + { + RECT rc = { 0 }; + real_GetClientRect(hwnd, &rc); + + BOOL popup = real_GetWindowLongA(hwnd, GWL_STYLE) & WS_POPUP; + + if ((rc.right < real_GetSystemMetrics(SM_CXSCREEN) && rc.bottom < real_GetSystemMetrics(SM_CYSCREEN)) || !popup) + { + TRACE(" client rect=%dx%d\n", rc.right, rc.bottom); + + g_ddraw.windowed_hack = TRUE; + dd_SetDisplayMode(rc.right, rc.bottom, 16, 0); + } + } + } + else + { + g_ddraw.windowed_hack = FALSE; } return DD_OK; @@ -1422,17 +1570,8 @@ HRESULT dd_WaitForVerticalBlank(DWORD dwFlags, HANDLE hEvent) { if (g_config.maxgameticks == -2) { - /* Workaround for DwmFlush() freeze (e.g. slow alt+tab) issue on windows 7 SP1 */ - if (g_ddraw.renderer == ogl_render_main && !IsWine() && !IsWindows8OrGreater()) - { - if (fpsl_wait_for_vblank()) - return DD_OK; - } - else - { - if (fpsl_dwm_flush() || fpsl_wait_for_vblank()) - return DD_OK; - } + if (fpsl_wait_for_vblank()) + return DD_OK; } if (!g_ddraw.flip_limiter.tick_length) @@ -1565,9 +1704,9 @@ ULONG dd_Release() DeleteCriticalSection(&g_ddraw.cs); - /* restore old wndproc, subsequent ddraw creation will otherwise fail */ - if (g_ddraw.hwnd) + if (g_ddraw.hwnd && IsWindow(g_ddraw.hwnd)) { + /* restore old wndproc, subsequent ddraw creation will otherwise fail */ real_SetWindowLongA(g_ddraw.hwnd, GWL_WNDPROC, (LONG)g_ddraw.wndproc); } @@ -1596,14 +1735,6 @@ HRESULT dd_GetAvailableVidMem(LPDDSCAPS lpDDCaps, LPDWORD lpdwTotal, LPDWORD lpd return DD_OK; } -HRESULT dd_GetVerticalBlankStatus(LPBOOL lpbIsInVB) -{ - if (lpbIsInVB) - *lpbIsInVB = TRUE; - - return DD_OK; -} - HRESULT dd_TestCooperativeLevel() { if (g_config.limiter_type == LIMIT_TESTCOOP && g_ddraw.ticks_limiter.tick_length > 0) @@ -1697,7 +1828,17 @@ HRESULT dd_CreateEx(GUID* lpGuid, LPVOID* lplpDD, REFIID iid, IUnknown* pUnkOute if (g_config.singlecpu) { - SetProcessAffinityMask(proc, 1); + if (!IsWine() && IsWindows11Version24H2OrGreater()) + { + if (GetProcessAffinityMask(proc, &proc_affinity, &system_affinity)) + SetProcessAffinityMask(proc, system_affinity); + + util_set_process_affinity(); + } + else + { + SetProcessAffinityMask(proc, 1); + } } else if (GetProcessAffinityMask(proc, &proc_affinity, &system_affinity)) { diff --git a/src/ddclipper.c b/src/ddclipper.c index eeec712..d1d6ceb 100644 --- a/src/ddclipper.c +++ b/src/ddclipper.c @@ -3,6 +3,7 @@ #include "IDirectDrawClipper.h" #include "ddclipper.h" #include "debug.h" +#include "dd.h" HRESULT ddc_GetClipList(IDirectDrawClipperImpl* This, LPRECT lpRect, LPRGNDATA lpClipList, LPDWORD lpdwSiz) @@ -168,6 +169,12 @@ HRESULT ddc_SetHWnd(IDirectDrawClipperImpl* This, DWORD dwFlags, HWND hWnd) */ This->hwnd = hWnd; + if (hWnd && !This->region && g_ddraw.width) + { + RECT rc = { 0, 0, g_ddraw.width, g_ddraw.height }; + ddc_SetClipRect(This, &rc); + } + LeaveCriticalSection(&This->cs); return DD_OK; } diff --git a/src/ddpalette.c b/src/ddpalette.c index ed2b858..e51df8e 100644 --- a/src/ddpalette.c +++ b/src/ddpalette.c @@ -14,11 +14,15 @@ HRESULT ddp_GetEntries( DWORD dwNumEntries, LPPALETTEENTRY lpEntries) { - for (int i = dwBase, x = 0; i < dwBase + dwNumEntries; i++, x++) + if (!lpEntries) + return DDERR_INVALIDPARAMS; + + for (int i = dwBase, x = 0; i < dwBase + dwNumEntries && i < 256; i++, x++) { lpEntries[x].peRed = This->data_rgb[i].rgbRed; lpEntries[x].peGreen = This->data_rgb[i].rgbGreen; lpEntries[x].peBlue = This->data_rgb[i].rgbBlue; + lpEntries[x].peFlags = 0; } return DD_OK; @@ -31,7 +35,17 @@ HRESULT ddp_SetEntries( DWORD dwCount, LPPALETTEENTRY lpEntries) { - for (int i = dwStartingEntry, x = 0; i < dwStartingEntry + dwCount; i++, x++) + if (!lpEntries) + return DDERR_INVALIDPARAMS; + + RGBQUAD data_rgb[256]; + + if ((dwFlags & DDPCAPS_REFRESH_CHANGED_ONLY)) + { + memcpy(data_rgb, This->data_rgb, sizeof(This->data_rgb)); + } + + for (int i = dwStartingEntry, x = 0; i < dwStartingEntry + dwCount && i < 256; i++, x++) { This->data_bgr[i] = (lpEntries[x].peBlue << 16) | (lpEntries[x].peGreen << 8) | lpEntries[x].peRed; @@ -57,6 +71,17 @@ HRESULT ddp_SetEntries( This->data_rgb[255].rgbReserved = 0; } + if ((dwFlags & DDPCAPS_REFRESH_CHANGED_ONLY)) + { + if (memcmp(data_rgb, This->data_rgb, sizeof(This->data_rgb)) == 0) + { + // do not set palette_updated BOOL if nothing changed + return DD_OK; + } + + TRACE_EXT(" Palette changed\n"); + } + if (g_ddraw.ref && g_ddraw.primary && g_ddraw.primary->palette == This && g_ddraw.render.run) { InterlockedExchange(&g_ddraw.render.palette_updated, TRUE); diff --git a/src/ddsurface.c b/src/ddsurface.c index 83e05b6..96d69de 100644 --- a/src/ddsurface.c +++ b/src/ddsurface.c @@ -12,7 +12,10 @@ #include "blt.h" #include "config.h" #include "ddclipper.h" +#include "utils.h" #include "versionhelpers.h" +#include "ddpalette.h" +#include "palette.h" LONG g_dds_gdi_handles; @@ -47,9 +50,20 @@ HRESULT dds_Blt( DWORD dwFlags, LPDDBLTFX lpDDBltFx) { + if (lpDDSrcSurface && + lpDDSrcSurface->bpp != 8 && + lpDDSrcSurface->bpp != 16 && + lpDDSrcSurface->bpp != 24 && + lpDDSrcSurface->bpp != 32) + { + return DDERR_INVALIDPARAMS; + } + dbg_dump_dds_blt_flags(dwFlags); dbg_dump_dds_blt_fx_flags((dwFlags & DDBLT_DDFX) && lpDDBltFx ? lpDDBltFx->dwDDFX : 0); + util_pull_messages(); + if (g_ddraw.ref && g_ddraw.iskkndx && (dwFlags & DDBLT_COLORFILL) && @@ -71,10 +85,16 @@ HRESULT dds_Blt( RECT dst_rect = { 0, 0, This->width, This->height }; if (lpSrcRect && src_surface) - memcpy(&src_rect, lpSrcRect, sizeof(src_rect)); + { + //dbg_print_rect("lpSrcRect", lpSrcRect); + src_rect = *lpSrcRect; + } if (lpDestRect) - memcpy(&dst_rect, lpDestRect, sizeof(dst_rect)); + { + //dbg_print_rect("lpDestRect", lpDestRect); + dst_rect = *lpDestRect; + } int src_w = src_rect.right - src_rect.left; int src_h = src_rect.bottom - src_rect.top; @@ -216,6 +236,11 @@ HRESULT dds_Blt( if (dst_buf && (dwFlags & DDBLT_COLORFILL) && lpDDBltFx && dst_w > 0 && dst_h > 0) { + if (This->bpp == 24) + { + TRACE_EXT(" NOT_IMPLEMENTED This->bpp=%u, dwFillColor=%08X\n", This->bpp, lpDDBltFx->dwFillColor); + } + blt_colorfill( dst_buf, dst_x, @@ -239,7 +264,10 @@ HRESULT dds_Blt( BOOL mirror_left_right = got_fx && (lpDDBltFx->dwDDFX & DDBLTFX_MIRRORLEFTRIGHT); BOOL mirror_up_down = got_fx && (lpDDBltFx->dwDDFX & DDBLTFX_MIRRORUPDOWN); - if (This->bpp != src_surface->bpp) + if (This->bpp != src_surface->bpp || + This->bpp == 24 || + src_surface->bpp == 24 || + (is_stretch_blt && This == src_surface)) { TRACE_EXT(" NOT_IMPLEMENTED This->bpp=%u, src_surface->bpp=%u\n", This->bpp, src_surface->bpp); @@ -249,13 +277,13 @@ HRESULT dds_Blt( HDC src_dc; dds_GetDC(src_surface, &src_dc); - if ((dwFlags & DDBLT_KEYSRC) || (dwFlags & DDBLT_KEYSRCOVERRIDE)) + if (((dwFlags & DDBLT_KEYSRC) && (src_surface->flags & DDSD_CKSRCBLT)) || (dwFlags & DDBLT_KEYSRCOVERRIDE)) { UINT color = (dwFlags & DDBLT_KEYSRCOVERRIDE) ? lpDDBltFx->ddckSrcColorkey.dwColorSpaceLowValue : src_surface->color_key.dwColorSpaceLowValue; - if (src_surface->bpp == 32) + if (src_surface->bpp == 32 || src_surface->bpp == 24) { color = color & 0xFFFFFF; } @@ -307,7 +335,7 @@ HRESULT dds_Blt( */ } else if ( - (dwFlags & DDBLT_KEYSRC) || + ((dwFlags & DDBLT_KEYSRC) && (src_surface->flags & DDSD_CKSRCBLT)) || (dwFlags & DDBLT_KEYSRCOVERRIDE) || mirror_left_right || mirror_up_down) @@ -418,10 +446,8 @@ HRESULT dds_Blt( if ((This->caps & DDSCAPS_PRIMARYSURFACE) && g_ddraw.ref && g_ddraw.render.run) { - if (!(dwFlags & DDBLT_COLORFILL)) - InterlockedExchange(&g_ddraw.zoom.frame_skip, 0); - InterlockedExchange(&g_ddraw.render.surface_updated, TRUE); + InterlockedExchange(&g_ddraw.render.screen_updated, TRUE); if (!(This->flags & DDSD_BACKBUFFERCOUNT) || This->last_flip_tick + FLIP_REDRAW_TIMEOUT < timeGetTime()) { @@ -430,7 +456,7 @@ HRESULT dds_Blt( ReleaseSemaphore(g_ddraw.render.sem, 1, NULL); SwitchToThread(); - if (g_ddraw.ticks_limiter.tick_length > 0) + if (g_ddraw.ticks_limiter.tick_length > 0 && g_config.limiter_type != LIMIT_PEEKMESSAGE) { g_ddraw.ticks_limiter.dds_unlock_limiter_disabled = TRUE; util_limit_game_ticks(); @@ -456,7 +482,10 @@ HRESULT dds_BltFast( RECT src_rect = { 0, 0, src_surface ? src_surface->width : 0, src_surface ? src_surface->height : 0 }; if (lpSrcRect && src_surface) - memcpy(&src_rect, lpSrcRect, sizeof(src_rect)); + { + //dbg_print_rect("lpSrcRect", lpSrcRect); + src_rect = *lpSrcRect; + } int dst_x = dwX; int dst_y = dwY; @@ -540,7 +569,9 @@ HRESULT dds_BltFast( if (src_surface && dst_w > 0 && dst_h > 0) { - if (This->bpp != src_surface->bpp) + if (This->bpp != src_surface->bpp || + This->bpp == 24 || + src_surface->bpp == 24) { TRACE_EXT(" NOT_IMPLEMENTED This->bpp=%u, src_surface->bpp=%u\n", This->bpp, src_surface->bpp); @@ -550,11 +581,11 @@ HRESULT dds_BltFast( HDC src_dc; dds_GetDC(src_surface, &src_dc); - if (dwFlags & DDBLTFAST_SRCCOLORKEY) + if ((dwFlags & DDBLTFAST_SRCCOLORKEY) && (src_surface->flags & DDSD_CKSRCBLT)) { UINT color = src_surface->color_key.dwColorSpaceLowValue; - if (src_surface->bpp == 32) + if (src_surface->bpp == 32 || src_surface->bpp == 24) { color = color & 0xFFFFFF; } @@ -603,7 +634,7 @@ HRESULT dds_BltFast( SRCCOPY); */ } - else if (dwFlags & DDBLTFAST_SRCCOLORKEY) + else if ((dwFlags & DDBLTFAST_SRCCOLORKEY) && (src_surface->flags & DDSD_CKSRCBLT)) { blt_colorkey( dst_buf, @@ -655,6 +686,7 @@ HRESULT dds_BltFast( if ((This->caps & DDSCAPS_PRIMARYSURFACE) && g_ddraw.ref && g_ddraw.render.run) { InterlockedExchange(&g_ddraw.render.surface_updated, TRUE); + InterlockedExchange(&g_ddraw.render.screen_updated, TRUE); DWORD time = timeGetTime(); @@ -701,8 +733,7 @@ HRESULT dds_GetSurfaceDesc(IDirectDrawSurfaceImpl* This, LPDDSURFACEDESC lpDDSur DDSD_WIDTH | DDSD_HEIGHT | DDSD_PITCH | - DDSD_PIXELFORMAT | - DDSD_LPSURFACE; + DDSD_PIXELFORMAT; lpDDSurfaceDesc->dwWidth = This->width; lpDDSurfaceDesc->dwHeight = This->height; @@ -736,7 +767,7 @@ HRESULT dds_GetSurfaceDesc(IDirectDrawSurfaceImpl* This, LPDDSURFACEDESC lpDDSur lpDDSurfaceDesc->ddpfPixelFormat.dwGBitMask = 0x07E0; lpDDSurfaceDesc->ddpfPixelFormat.dwBBitMask = 0x001F; } - else if (This->bpp == 32) + else if (This->bpp == 32 || This->bpp == 24) { lpDDSurfaceDesc->ddpfPixelFormat.dwRBitMask = 0xFF0000; lpDDSurfaceDesc->ddpfPixelFormat.dwGBitMask = 0x00FF00; @@ -813,6 +844,7 @@ HRESULT dds_Flip(IDirectDrawSurfaceImpl* This, IDirectDrawSurfaceImpl* lpDDSurfa This->last_flip_tick = timeGetTime(); InterlockedExchange(&g_ddraw.render.surface_updated, TRUE); + InterlockedExchange(&g_ddraw.render.screen_updated, TRUE); ReleaseSemaphore(g_ddraw.render.sem, 1, NULL); SwitchToThread(); @@ -821,7 +853,7 @@ HRESULT dds_Flip(IDirectDrawSurfaceImpl* This, IDirectDrawSurfaceImpl* lpDDSurfa dd_WaitForVerticalBlank(DDWAITVB_BLOCKEND, NULL); } - if (g_ddraw.ticks_limiter.tick_length > 0) + if (g_ddraw.ticks_limiter.tick_length > 0 && g_config.limiter_type != LIMIT_PEEKMESSAGE) { g_ddraw.ticks_limiter.dds_unlock_limiter_disabled = TRUE; util_limit_game_ticks(); @@ -877,6 +909,11 @@ HRESULT dds_GetClipper(IDirectDrawSurfaceImpl* This, IDirectDrawClipperImpl** lp HRESULT dds_GetColorKey(IDirectDrawSurfaceImpl* This, DWORD dwFlags, LPDDCOLORKEY lpColorKey) { + if (!(This->flags & DDSD_CKSRCBLT)) + { + return DDERR_NOCOLORKEY; + } + if (dwFlags != DDCKEY_SRCBLT || !lpColorKey) { TRACE(" NOT_IMPLEMENTED dwFlags=%08X, lpColorKey=%p\n", dwFlags, lpColorKey); @@ -917,6 +954,9 @@ HRESULT dds_GetDC(IDirectDrawSurfaceImpl* This, HDC FAR* lpHDC) if (lpHDC) *lpHDC = dc; + if (!(This->caps & DDSCAPS_OWNDC)) + InterlockedExchange((LONG*)&This->dc_state, SaveDC(dc)); + return DD_OK; } @@ -958,7 +998,7 @@ HRESULT dds_GetPixelFormat(IDirectDrawSurfaceImpl* This, LPDDPIXELFORMAT ddpfPix ddpfPixelFormat->dwGBitMask = 0x07E0; ddpfPixelFormat->dwBBitMask = 0x001F; } - else if (This->bpp == 32) + else if (This->bpp == 32 || This->bpp == 24) { ddpfPixelFormat->dwRBitMask = 0xFF0000; ddpfPixelFormat->dwGBitMask = 0x00FF00; @@ -983,11 +1023,7 @@ HRESULT dds_Lock( dbg_dump_dds_lock_flags(dwFlags); - if (g_ddraw.ref && g_config.fixnotresponding && !IsWine()) - { - MSG msg; /* workaround for "Not Responding" window problem */ - real_PeekMessageA(&msg, g_ddraw.hwnd, 0, 0, PM_NOREMOVE); - } + util_pull_messages(); HRESULT ret = dds_GetSurfaceDesc(This, lpDDSurfaceDesc); @@ -1017,6 +1053,7 @@ HRESULT dds_ReleaseDC(IDirectDrawSurfaceImpl* This, HDC hDC) if ((This->caps & DDSCAPS_PRIMARYSURFACE) && g_ddraw.ref && g_ddraw.render.run) { InterlockedExchange(&g_ddraw.render.surface_updated, TRUE); + InterlockedExchange(&g_ddraw.render.screen_updated, TRUE); DWORD time = timeGetTime(); @@ -1027,6 +1064,9 @@ HRESULT dds_ReleaseDC(IDirectDrawSurfaceImpl* This, HDC hDC) } } + if (!(This->caps & DDSCAPS_OWNDC)) + RestoreDC(hDC, InterlockedExchangeAdd((LONG*)&This->dc_state, 0)); + return DD_OK; } @@ -1079,11 +1119,13 @@ HRESULT dds_SetColorKey(IDirectDrawSurfaceImpl* This, DWORD dwFlags, LPDDCOLORKE HRESULT dds_SetPalette(IDirectDrawSurfaceImpl* This, IDirectDrawPaletteImpl* lpDDPalette) { + if (This->bpp != 8) + return DDERR_INVALIDPIXELFORMAT; + if (lpDDPalette) IDirectDrawPalette_AddRef(lpDDPalette); - if (This->palette) - IDirectDrawPalette_Release(This->palette); + IDirectDrawPaletteImpl* old_palette = This->palette; if ((This->caps & DDSCAPS_PRIMARYSURFACE) && g_ddraw.ref) { @@ -1102,6 +1144,9 @@ HRESULT dds_SetPalette(IDirectDrawSurfaceImpl* This, IDirectDrawPaletteImpl* lpD This->palette = lpDDPalette; } + if (old_palette) + IDirectDrawPalette_Release(old_palette); + return DD_OK; } @@ -1194,6 +1239,7 @@ HRESULT dds_Unlock(IDirectDrawSurfaceImpl* This, LPRECT lpRect) if ((This->caps & DDSCAPS_PRIMARYSURFACE) && g_ddraw.ref && g_ddraw.render.run) { InterlockedExchange(&g_ddraw.render.surface_updated, TRUE); + InterlockedExchange(&g_ddraw.render.screen_updated, TRUE); DWORD time = timeGetTime(); @@ -1202,8 +1248,12 @@ HRESULT dds_Unlock(IDirectDrawSurfaceImpl* This, LPRECT lpRect) { ReleaseSemaphore(g_ddraw.render.sem, 1, NULL); - if (g_ddraw.ticks_limiter.tick_length > 0 && !g_ddraw.ticks_limiter.dds_unlock_limiter_disabled) + if (g_ddraw.ticks_limiter.tick_length > 0 && + g_config.limiter_type != LIMIT_PEEKMESSAGE && + (!g_ddraw.ticks_limiter.dds_unlock_limiter_disabled || g_config.limiter_type == LIMIT_UNLOCK)) + { util_limit_game_ticks(); + } } } @@ -1279,7 +1329,8 @@ HRESULT dds_SetSurfaceDesc(IDirectDrawSurfaceImpl* This, LPDDSURFACEDESC2 lpDDSD This->bpp = 16; break; case 24: - TRACE(" NOT_IMPLEMENTED bpp=%u\n", lpDDSD->ddpfPixelFormat.dwRGBBitCount); + This->bpp = 24; + break; case 32: This->bpp = 32; break; @@ -1392,7 +1443,8 @@ HRESULT dd_CreateSurface( dst_surface->bpp = 16; break; case 24: - TRACE(" NOT_IMPLEMENTED bpp=%u\n", lpDDSurfaceDesc->ddpfPixelFormat.dwRGBBitCount); + dst_surface->bpp = 24; + break; case 32: dst_surface->bpp = 32; break; @@ -1416,8 +1468,8 @@ HRESULT dd_CreateSurface( dst_surface->caps |= DDSCAPS_VISIBLE; - dst_surface->width = g_ddraw.width; - dst_surface->height = g_ddraw.height; + dst_surface->width = g_ddraw.width == 0 ? 1024 : g_ddraw.width; + dst_surface->height = g_ddraw.height == 0 ? 768 : g_ddraw.height; } else { @@ -1446,23 +1498,24 @@ HRESULT dd_CreateSurface( DWORD aligned_width = dst_surface->pitch / dst_surface->bytes_pp; - DWORD bmi_size = sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * 256; DWORD bmp_size = dst_surface->pitch * (dst_surface->height + g_config.guard_lines); - dst_surface->bmi = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, bmi_size); + dst_surface->bmi = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DDBITMAPINFO)); dst_surface->bmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); dst_surface->bmi->bmiHeader.biWidth = aligned_width; dst_surface->bmi->bmiHeader.biHeight = -((int)dst_surface->height + g_config.guard_lines); dst_surface->bmi->bmiHeader.biPlanes = 1; dst_surface->bmi->bmiHeader.biBitCount = dst_surface->bpp; - dst_surface->bmi->bmiHeader.biCompression = dst_surface->bpp == 8 ? BI_RGB : BI_BITFIELDS; + dst_surface->bmi->bmiHeader.biCompression = dst_surface->bpp == 16 ? BI_BITFIELDS : BI_RGB; WORD clr_bits = (WORD)(dst_surface->bmi->bmiHeader.biPlanes * dst_surface->bmi->bmiHeader.biBitCount); - if (clr_bits < 24) - { - dst_surface->bmi->bmiHeader.biClrUsed = (1 << clr_bits); - } + dst_surface->bmi->bmiHeader.biClrUsed = + dst_surface->bpp == 8 ? 256 : + dst_surface->bpp == 16 ? 3 : + dst_surface->bpp == 24 ? 0 : + dst_surface->bpp == 32 ? 0 : + 0; dst_surface->bmi->bmiHeader.biSizeImage = ((aligned_width * clr_bits + 63) & ~63) / 8 * dst_surface->height; @@ -1489,15 +1542,9 @@ HRESULT dd_CreateSurface( ((DWORD*)dst_surface->bmi->bmiColors)[1] = 0x07E0; ((DWORD*)dst_surface->bmi->bmiColors)[2] = 0x001F; } - else if (dst_surface->bpp == 32) - { - ((DWORD*)dst_surface->bmi->bmiColors)[0] = 0xFF0000; - ((DWORD*)dst_surface->bmi->bmiColors)[1] = 0x00FF00; - ((DWORD*)dst_surface->bmi->bmiColors)[2] = 0x0000FF; - } /* Claw hack: 128x128 surfaces need a DC for custom levels to work properly */ - if (InterlockedExchangeAdd(&g_dds_gdi_handles, 0) < 4000 || + if ((!g_config.limit_gdi_handles && InterlockedExchangeAdd(&g_dds_gdi_handles, 0) < 9000) || (dst_surface->width == g_ddraw.width && dst_surface->height == g_ddraw.height) || (dst_surface->width == 128 && dst_surface->height == 128)) { @@ -1506,17 +1553,18 @@ HRESULT dd_CreateSurface( if (dst_surface->hdc) InterlockedIncrement(&g_dds_gdi_handles); + // CreateDIBSection cannot handle values higher than a WORD - 0xFF00 (guard lines); + DWORD map_offset = min(65280, dst_surface->pitch * g_config.guard_lines); + dst_surface->mapping = CreateFileMappingA( INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE | SEC_COMMIT, 0, - bmp_size + 256, + bmp_size + 256 + map_offset, NULL); - DWORD map_offset = 0; - if (dst_surface->mapping) { LPVOID data = MapViewOfFile(dst_surface->mapping, FILE_MAP_ALL_ACCESS, 0, 0, 0); @@ -1562,6 +1610,16 @@ HRESULT dd_CreateSurface( { g_ddraw.primary = dst_surface; FakePrimarySurface = dst_surface->surface; + + if (dst_surface->bpp == 8) + { + IDirectDrawPaletteImpl* lpDDPalette; + dd_CreatePalette(DDPCAPS_ALLOW256, g_ddp_default_palette, &lpDDPalette, NULL); + dds_SetPalette(dst_surface, lpDDPalette); + + // Make sure temp palette will be released once replaced + IDirectDrawPalette_Release(lpDDPalette); + } } } diff --git a/src/debug.c b/src/debug.c index c9b5d1f..b030114 100644 --- a/src/debug.c +++ b/src/debug.c @@ -1,6 +1,9 @@ #include #include #include +#include +#include +#include "directinput.h" #include "ddraw.h" #include "dd.h" #include "ddsurface.h" @@ -8,16 +11,28 @@ #include "debug.h" #include "hook.h" #include "version.h" +#include "git.h" #include "versionhelpers.h" +#include "utils.h" +#include "crc32.h" +#include "dllmain.h" +#include "config.h" +#include "delay_imports.h" double g_dbg_frame_time = 0; DWORD g_dbg_frame_count = 0; LPTOP_LEVEL_EXCEPTION_FILTER g_dbg_exception_filter; +PVOID g_dbg_exception_handle; static LONGLONG g_dbg_counter_start_time = 0; static double g_dbg_counter_freq = 0.0; static FILE* g_dbg_log_file; +static char g_dbg_log_path1[MAX_PATH] = "cnc-ddraw-1.log"; +static char g_dbg_log_path2[MAX_PATH] = "cnc-ddraw-2.log"; +static char g_dbg_log_path3[MAX_PATH] = "cnc-ddraw-3.log"; +static char g_dbg_dmp_path1[MAX_PATH] = "cnc-ddraw-1.dmp"; +static char g_dbg_dmp_path2[MAX_PATH] = "cnc-ddraw-2.dmp"; static BOOL g_dbg_log_rotate; #ifdef _DEBUG @@ -27,36 +42,47 @@ LONG WINAPI dbg_exception_handler(EXCEPTION_POINTERS* exception) { g_dbg_crash_count++; - char filename[MAX_PATH] = { 0 }; - _snprintf(filename, sizeof(filename) - 1, "cnc-ddraw-%d.dmp", g_dbg_crash_count == 1 ? 1 : 2); + BOOL(WINAPI * MiniDumpWriteDumpProc)( + HANDLE, + DWORD, + HANDLE, + MINIDUMP_TYPE, + PMINIDUMP_EXCEPTION_INFORMATION, + PMINIDUMP_USER_STREAM_INFORMATION, + PMINIDUMP_CALLBACK_INFORMATION + ); - HANDLE dmp = - CreateFile( - filename, - GENERIC_READ | GENERIC_WRITE, - FILE_SHARE_WRITE | FILE_SHARE_READ, - 0, - CREATE_ALWAYS, - 0, - 0); - - if (dmp != INVALID_HANDLE_VALUE) + MiniDumpWriteDumpProc = (void*)real_GetProcAddress(real_LoadLibraryA("Dbghelp.dll"), "MiniDumpWriteDump"); + if (MiniDumpWriteDumpProc) { - MINIDUMP_EXCEPTION_INFORMATION info; - info.ThreadId = GetCurrentThreadId(); - info.ExceptionPointers = exception; - info.ClientPointers = TRUE; + HANDLE dmp = + CreateFile( + g_dbg_crash_count == 1 ? g_dbg_dmp_path1 : g_dbg_dmp_path2, + GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_WRITE | FILE_SHARE_READ, + 0, + CREATE_ALWAYS, + 0, + 0); - MiniDumpWriteDump( - GetCurrentProcess(), - GetCurrentProcessId(), - dmp, - 0, - &info, - NULL, - NULL); + if (dmp != INVALID_HANDLE_VALUE) + { + MINIDUMP_EXCEPTION_INFORMATION info; + info.ThreadId = GetCurrentThreadId(); + info.ExceptionPointers = exception; + info.ClientPointers = TRUE; - CloseHandle(dmp); + MiniDumpWriteDumpProc( + GetCurrentProcess(), + GetCurrentProcessId(), + dmp, + 0, + &info, + NULL, + NULL); + + CloseHandle(dmp); + } } if (exception && exception->ExceptionRecord) @@ -64,7 +90,7 @@ LONG WINAPI dbg_exception_handler(EXCEPTION_POINTERS* exception) HMODULE mod = NULL; char filename[MAX_PATH] = { 0 }; - if (GetModuleHandleExA( + if (delay_GetModuleHandleExA && delay_GetModuleHandleExA( GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, exception->ExceptionRecord->ExceptionAddress, &mod)) @@ -86,8 +112,66 @@ LONG WINAPI dbg_exception_handler(EXCEPTION_POINTERS* exception) return EXCEPTION_EXECUTE_HANDLER; } + +void __cdecl dbg_invoke_watson( + wchar_t const* const expression, + wchar_t const* const function_name, + wchar_t const* const file_name, + unsigned int const line_number, + uintptr_t const reserved +) +{ + TRACE("%s [%p]\n", __FUNCTION__, _ReturnAddress()); + + /* Force access violation to produce a dmp file for debugging */ + *(int*)0 = 0; + + TerminateProcess(GetCurrentProcess(), STATUS_INVALID_CRUNTIME_PARAMETER); +} #endif +LONG WINAPI dbg_vectored_exception_handler(EXCEPTION_POINTERS* exception) +{ + if (exception && + exception->ContextRecord && + exception->ExceptionRecord && + exception->ExceptionRecord->ExceptionAddress && + exception->ExceptionRecord->ExceptionCode == STATUS_PRIVILEGED_INSTRUCTION) + { + size_t size = 0; + BYTE* addr = exception->ExceptionRecord->ExceptionAddress; + switch (*addr) + { + case 0xE4: // IN ib + case 0xE5: // IN id + case 0xE6: // OUT ib + case 0xE7: // OUT ib + size = 2; + break; + case 0xF8: // CLC + case 0xF9: // STC + case 0xFA: // CLI + case 0xFB: // STI + case 0xFC: // CLD + case 0xFD: // STD + case 0xEC: // IN ib + case 0xED: // IN id + case 0xEE: // OUT + case 0xEF: // OUT + size = 1; + break; + } + + if (size) + { + exception->ContextRecord->Eip += size; + return EXCEPTION_CONTINUE_EXECUTION; + } + } + + return EXCEPTION_CONTINUE_SEARCH; +} + void dbg_init() { static BOOL once = 0; @@ -96,41 +180,89 @@ void dbg_init() { once = TRUE; - remove("cnc-ddraw-1.dmp"); - remove("cnc-ddraw-2.dmp"); + char exe_path[MAX_PATH] = { 0 }; + if (GetModuleFileNameA(NULL, exe_path, sizeof(exe_path) - 1) > 0) + { + char filename[MAX_PATH] = { 0 }; + char drive[MAX_PATH] = { 0 }; + char dir[MAX_PATH] = { 0 }; + _splitpath(exe_path, drive, dir, filename, NULL); - remove("cnc-ddraw-1.log"); - remove("cnc-ddraw-2.log"); - remove("cnc-ddraw-3.log"); + char game_path[MAX_PATH] = { 0 }; + _makepath(game_path, drive, dir, NULL, NULL); - g_dbg_log_file = fopen("cnc-ddraw-1.log", "w"); - setvbuf(g_dbg_log_file, NULL, _IOLBF, 1024); + _snprintf(g_dbg_dmp_path1, sizeof(g_dbg_dmp_path1) - 1, "%scnc-ddraw-%s-1.dmp", game_path, filename); + _snprintf(g_dbg_dmp_path2, sizeof(g_dbg_dmp_path2) - 1, "%scnc-ddraw-%s-2.dmp", game_path, filename); - TRACE("cnc-ddraw version = %d.%d.%d.%d\n", VERSION_MAJOR, VERSION_MINOR, VERSION_BUILD, VERSION_REVISION); + _snprintf(g_dbg_log_path1, sizeof(g_dbg_log_path1) - 1, "%scnc-ddraw-%s-1.log", game_path, filename); + _snprintf(g_dbg_log_path2, sizeof(g_dbg_log_path2) - 1, "%scnc-ddraw-%s-2.log", game_path, filename); + _snprintf(g_dbg_log_path3, sizeof(g_dbg_log_path3) - 1, "%scnc-ddraw-%s-3.log", game_path, filename); + } - HKEY hkey; + remove(g_dbg_dmp_path1); + remove(g_dbg_dmp_path2); + + remove(g_dbg_log_path1); + remove(g_dbg_log_path2); + remove(g_dbg_log_path3); + + g_dbg_log_file = fopen(g_dbg_log_path1, "w"); + if (g_dbg_log_file) + { + setvbuf(g_dbg_log_file, NULL, _IOLBF, 1024); + } + + TRACE( + "cnc-ddraw version = %d.%d.%d.%d (git~%s, %s)\n", + VERSION_MAJOR, + VERSION_MINOR, + VERSION_BUILD, + VERSION_REVISION, + GIT_COMMIT, + GIT_BRANCH); + + TRACE("cnc-ddraw = %p\n", g_ddraw_module); + + HKEY hkey = NULL; LONG status = RegOpenKeyExA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", 0L, KEY_READ, &hkey); - if (status == ERROR_SUCCESS) + HKEY hkey9x = NULL; + LONG status9x = + RegOpenKeyExA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion", 0L, KEY_READ, &hkey9x); + + char name[256] = { 0 }; + DWORD name_size = sizeof(name); + if (status || RegQueryValueExA(hkey, "ProductName", NULL, NULL, (PVOID)&name, &name_size) != ERROR_SUCCESS) { - char name[256] = { 0 }; - DWORD name_size = sizeof(name); - RegQueryValueExA(hkey, "ProductName", NULL, NULL, (PVOID)&name, &name_size); - - char dversion[256] = { 0 }; - DWORD dversion_size = sizeof(dversion); - RegQueryValueExA(hkey, "DisplayVersion", NULL, NULL, (PVOID)&dversion, &dversion_size); - - char build[256] = { 0 }; - DWORD build_size = sizeof(build); - RegQueryValueExA(hkey, "BuildLab", NULL, NULL, (PVOID)&build, &build_size); - - TRACE("%s %s (%s)\n", name, dversion, build); - - RegCloseKey(hkey); + if (status9x == ERROR_SUCCESS) + RegQueryValueExA(hkey9x, "ProductName", NULL, NULL, (PVOID)&name, &name_size); } + char vers[256] = { 0 }; + DWORD vers_size = sizeof(vers); + if (status || RegQueryValueExA(hkey, "DisplayVersion", NULL, NULL, (PVOID)&vers, &vers_size) != ERROR_SUCCESS) + { + if (status9x == ERROR_SUCCESS) + RegQueryValueExA(hkey9x, "VersionNumber", NULL, NULL, (PVOID)&vers, &vers_size); + } + + char build[256] = { 0 }; + DWORD build_size = sizeof(build); + if (status || RegQueryValueExA(hkey, "BuildLabEx", NULL, NULL, (PVOID)&build, &build_size) != ERROR_SUCCESS) + { + if (status == ERROR_SUCCESS) + RegQueryValueExA(hkey, "BuildLab", NULL, NULL, (PVOID)&build, &build_size); + } + + TRACE("%s %s (%s)\n", name, vers, build); + + if (status == ERROR_SUCCESS) + RegCloseKey(hkey); + + if (status9x == ERROR_SUCCESS) + RegCloseKey(hkey9x); + if (IsWine()) { TRACE("Wine version = %s\n", verhelp_wine_get_version()); @@ -141,6 +273,14 @@ void dbg_init() TRACE("Wine sysname = %s, release = %s\n", sysname, release); } + + TRACE("crc32 = %08X\n", Crc32_FromFile(0, exe_path)); + + DWORD timestamp = util_get_timestamp(GetModuleHandleA(NULL)); + if (timestamp) + { + TRACE("timestamp = %s", asctime(_gmtime32((const long*)×tamp))); + } } } @@ -184,12 +324,15 @@ void dbg_printf(const char* fmt, ...) if (g_dbg_log_file && ftell(g_dbg_log_file) >= 1024 * 1024 * 100) /* rotate every 100MB */ { - char filename[MAX_PATH] = { 0 }; - _snprintf(filename, sizeof(filename) - 1, "cnc-ddraw-%d.log", g_dbg_log_rotate ? 3 : 2); + g_dbg_log_file = + freopen( + g_dbg_log_rotate ? g_dbg_log_path3 : g_dbg_log_path2, + "w", + g_dbg_log_file); g_dbg_log_rotate = !g_dbg_log_rotate; - if ((g_dbg_log_file = freopen(filename, "w", g_dbg_log_file))) + if (g_dbg_log_file) { setvbuf(g_dbg_log_file, NULL, _IOLBF, 1024); } @@ -948,6 +1091,111 @@ void dbg_dump_dds_lock_flags(DWORD flags) #endif } +void dbg_dump_di_scm_flags(DWORD flags) +{ +#ifdef _DEBUG + if (flags & DISCL_EXCLUSIVE) { + TRACE(" DISCL_EXCLUSIVE\n"); + } + if (flags & DISCL_NONEXCLUSIVE) { + TRACE(" DISCL_NONEXCLUSIVE\n"); + } + if (flags & DISCL_FOREGROUND) { + TRACE(" DISCL_FOREGROUND\n"); + } + if (flags & DISCL_BACKGROUND) { + TRACE(" DISCL_BACKGROUND\n"); + } + if (flags & DISCL_NOWINKEY) { + TRACE(" DISCL_NOWINKEY\n"); + } +#endif +} + +void dbg_dump_hook_type(int idHook) +{ +#ifdef _DEBUG + if (idHook == 0) { + TRACE(" WH_JOURNALRECORD\n"); + } + if (idHook == 1) { + TRACE(" WH_JOURNALPLAYBACK\n"); + } + if (idHook == 2) { + TRACE(" WH_KEYBOARD\n"); + } + if (idHook == 3) { + TRACE(" WH_GETMESSAGE\n"); + } + if (idHook == 4) { + TRACE(" WH_CALLWNDPROC\n"); + } + if (idHook == 5) { + TRACE(" WH_CBT\n"); + } + if (idHook == 6) { + TRACE(" WH_SYSMSGFILTER\n"); + } + if (idHook == 7) { + TRACE(" WH_MOUSE\n"); + } + if (idHook == 9) { + TRACE(" WH_DEBUG\n"); + } + if (idHook == 10) { + TRACE(" WH_SHELL\n"); + } + if (idHook == 11) { + TRACE(" WH_FOREGROUNDIDLE\n"); + } + if (idHook == 12) { + TRACE(" WH_CALLWNDPROCRET\n"); + } + if (idHook == 13) { + TRACE(" WH_KEYBOARD_LL\n"); + } + if (idHook == 14) { + TRACE(" WH_MOUSE_LL\n"); + } + if (idHook == -1) { + TRACE(" WH_MSGFILTER\n"); + } +#endif +} + +char* dbg_d3d9_hr_to_str(HRESULT hr) +{ +#define HR_TO_STR(x) if (x == hr) return #x + + HR_TO_STR(D3D_OK); + + HR_TO_STR(D3DERR_WRONGTEXTUREFORMAT); + HR_TO_STR(D3DERR_UNSUPPORTEDCOLOROPERATION); + HR_TO_STR(D3DERR_UNSUPPORTEDCOLORARG); + HR_TO_STR(D3DERR_UNSUPPORTEDALPHAOPERATION); + HR_TO_STR(D3DERR_UNSUPPORTEDALPHAARG); + HR_TO_STR(D3DERR_TOOMANYOPERATIONS); + HR_TO_STR(D3DERR_CONFLICTINGTEXTUREFILTER); + HR_TO_STR(D3DERR_UNSUPPORTEDFACTORVALUE); + HR_TO_STR(D3DERR_CONFLICTINGRENDERSTATE); + HR_TO_STR(D3DERR_UNSUPPORTEDTEXTUREFILTER); + HR_TO_STR(D3DERR_CONFLICTINGTEXTUREPALETTE); + HR_TO_STR(D3DERR_DRIVERINTERNALERROR); + + HR_TO_STR(D3DERR_NOTFOUND); + HR_TO_STR(D3DERR_MOREDATA); + HR_TO_STR(D3DERR_DEVICELOST); + HR_TO_STR(D3DERR_DEVICENOTRESET); + HR_TO_STR(D3DERR_NOTAVAILABLE); + HR_TO_STR(D3DERR_OUTOFVIDEOMEMORY); + HR_TO_STR(D3DERR_INVALIDDEVICE); + HR_TO_STR(D3DERR_INVALIDCALL); + HR_TO_STR(D3DERR_DRIVERINVALIDCALL); + HR_TO_STR(D3DERR_WASSTILLDRAWING); + + return "UNKNOWN"; +} + char* dbg_mes_to_str(int id) { switch (id) diff --git a/src/delay_imports.c b/src/delay_imports.c new file mode 100644 index 0000000..2b23dda --- /dev/null +++ b/src/delay_imports.c @@ -0,0 +1,30 @@ +#include +#include "versionhelpers.h" +#include "delay_imports.h" + +NTQUERYINFORMATIONTHREADPROC delay_NtQueryInformationThread; +RTLVERIFYVERSIONINFOPROC delay_RtlVerifyVersionInfo; +WINE_GET_VERSIONPROC delay_wine_get_version; +WINE_GET_HOST_VERSIONPROC delay_wine_get_host_version; + +VERSETCONDITIONMASKPROC delay_VerSetConditionMask; +GETMODULEHANDLEEXAPROC delay_GetModuleHandleExA; + +void delay_imports_init() +{ + HMODULE mod = GetModuleHandleA("ntdll.dll"); + if (mod) + { + delay_NtQueryInformationThread = (NTQUERYINFORMATIONTHREADPROC)GetProcAddress(mod, "NtQueryInformationThread"); + delay_RtlVerifyVersionInfo = (RTLVERIFYVERSIONINFOPROC)GetProcAddress(mod, "RtlVerifyVersionInfo"); + delay_wine_get_version = (WINE_GET_VERSIONPROC)GetProcAddress(mod, "wine_get_version"); + delay_wine_get_host_version = (WINE_GET_HOST_VERSIONPROC)GetProcAddress(mod, "wine_get_host_version"); + } + + mod = GetModuleHandleA("Kernel32.dll"); + if (mod) + { + delay_VerSetConditionMask = (VERSETCONDITIONMASKPROC)GetProcAddress(mod, "VerSetConditionMask"); + delay_GetModuleHandleExA = (GETMODULEHANDLEEXAPROC)GetProcAddress(mod, "GetModuleHandleExA"); + } +} diff --git a/src/directinput.c b/src/directinput.c index 4c29144..a0d077d 100644 --- a/src/directinput.c +++ b/src/directinput.c @@ -6,6 +6,7 @@ #include "dd.h" #include "mouse.h" #include "config.h" +#include "utils.h" #ifdef _MSC_VER #include "detours.h" @@ -54,10 +55,12 @@ static PROC hook_func(PROC* org_func, PROC new_func) static HRESULT WINAPI fake_did_SetCooperativeLevel(IDirectInputDeviceA* This, HWND hwnd, DWORD dwFlags) { TRACE("DirectInput SetCooperativeLevel(This=%p, hwnd=%p, dwFlags=0x%08X) [%p]\n", This, hwnd, dwFlags, _ReturnAddress()); + TRACE(" mouse_device = %s\n", This == g_mouse_device ? "TRUE" : "FALSE"); + dbg_dump_di_scm_flags(dwFlags); - if (This == g_mouse_device && g_ddraw.ref && (dwFlags & DISCL_EXCLUSIVE)) + if (This == g_mouse_device && (dwFlags & DISCL_EXCLUSIVE)) { - if (g_mouse_locked || g_config.devmode) + if (g_mouse_locked || g_config.devmode || !g_ddraw.ref) { while (real_ShowCursor(FALSE) >= 0); } @@ -75,13 +78,25 @@ static HRESULT WINAPI fake_did_GetDeviceData( LPDWORD pdwInOut, DWORD dwFlags) { - //TRACE("DirectInput GetDeviceData [%p]\n", _ReturnAddress()); + /* + TRACE( + "DirectInput GetDeviceData(This=%p, cbObjectData=%lu, rgdod=%p, pdwInOut=%p, dwFlags=%lu) [%p]\n", + This, + cbObjectData, + rgdod, + pdwInOut, + dwFlags, + _ReturnAddress()); + */ + + BOOL block_mouse = This == g_mouse_device && !g_mouse_locked && !g_config.devmode; + BOOL in_background = FALSE;//g_ddraw.ref && g_ddraw.hwnd && !util_in_foreground(g_ddraw.hwnd); HRESULT result = real_did_GetDeviceData(This, cbObjectData, rgdod, pdwInOut, dwFlags); - if (SUCCEEDED(result) && This == g_mouse_device && !g_mouse_locked && !g_config.devmode) + if (SUCCEEDED(result)) { - if (pdwInOut) + if ((block_mouse || in_background) && pdwInOut) { if (rgdod && *pdwInOut > 0 && cbObjectData > 0) { @@ -97,13 +112,16 @@ static HRESULT WINAPI fake_did_GetDeviceData( static HRESULT WINAPI fake_did_GetDeviceState(IDirectInputDeviceA* This, DWORD cbData, LPVOID lpvData) { - //TRACE("DirectInput GetDeviceState [%p]\n", _ReturnAddress()); + //TRACE("DirectInput GetDeviceState(This=%p, cbData=%lu, lpvData=%p) [%p]\n", This, cbData, lpvData, _ReturnAddress()); + + BOOL block_mouse = This == g_mouse_device && !g_mouse_locked && !g_config.devmode; + BOOL in_background = g_ddraw.ref && g_ddraw.hwnd && !util_in_foreground(g_ddraw.hwnd); HRESULT result = real_did_GetDeviceState(This, cbData, lpvData); - if (SUCCEEDED(result) && This == g_mouse_device && !g_mouse_locked && !g_config.devmode) + if (SUCCEEDED(result)) { - if (cbData > 0 && lpvData) + if ((block_mouse || in_background) && cbData > 0 && lpvData) { memset(lpvData, 0, cbData); } @@ -124,9 +142,14 @@ static HRESULT WINAPI fake_di_CreateDevice( if (SUCCEEDED(result)) { - if (rguid && IsEqualGUID(&GUID_SysMouse, rguid)) + if (rguid) { - g_mouse_device = *lplpDIDevice; + TRACE(" GUID = %08X\n", ((GUID*)rguid)->Data1); + + if (IsEqualGUID(&GUID_SysMouse, rguid)) + { + g_mouse_device = *lplpDIDevice; + } } if (!real_did_SetCooperativeLevel) @@ -164,9 +187,14 @@ static HRESULT WINAPI fake_di_CreateDeviceEx( if (SUCCEEDED(result)) { - if (rguid && IsEqualGUID(&GUID_SysMouse, rguid)) + if (rguid) { - g_mouse_device = *lplpDIDevice; + TRACE(" GUID = %08X\n", ((GUID*)rguid)->Data1); + + if (IsEqualGUID(&GUID_SysMouse, rguid)) + { + g_mouse_device = *lplpDIDevice; + } } if (!real_did_SetCooperativeLevel) diff --git a/src/dllmain.c b/src/dllmain.c index 3dee497..8832177 100644 --- a/src/dllmain.c +++ b/src/dllmain.c @@ -12,6 +12,8 @@ #include "indeo.h" #include "utils.h" #include "versionhelpers.h" +#include "delay_imports.h" +#include "keyboard.h" /* export for cncnet cnc games */ @@ -22,6 +24,7 @@ PVOID FakePrimarySurface; HMODULE g_ddraw_module; +static BOOL g_screensaver_disabled; BOOL WINAPI DllMain(HANDLE hDll, DWORD dwReason, LPVOID lpReserved) { @@ -31,9 +34,9 @@ BOOL WINAPI DllMain(HANDLE hDll, DWORD dwReason, LPVOID lpReserved) { g_ddraw_module = hDll; - verhelp_init(); + delay_imports_init(); - if (GetEnvironmentVariableW(L"cnc_ddraw_config_init", NULL, 0)) + if (GetEnvironmentVariable("cnc_ddraw_config_init", NULL, 0)) { cfg_load(); return TRUE; @@ -41,12 +44,19 @@ BOOL WINAPI DllMain(HANDLE hDll, DWORD dwReason, LPVOID lpReserved) #ifdef _DEBUG dbg_init(); - TRACE("cnc-ddraw = %p\n", hDll); g_dbg_exception_filter = real_SetUnhandledExceptionFilter((LPTOP_LEVEL_EXCEPTION_FILTER)dbg_exception_handler); #endif cfg_load(); + PVOID(WINAPI * add_handler)(ULONG, PVECTORED_EXCEPTION_HANDLER) = + (void*)real_GetProcAddress(GetModuleHandleA("Kernel32.dll"), "AddVectoredExceptionHandler"); + + if (add_handler) + { + g_dbg_exception_handle = add_handler(1, (PVECTORED_EXCEPTION_HANDLER)dbg_vectored_exception_handler); + } + char buf[1024]; if (GetEnvironmentVariable("__COMPAT_LAYER", buf, sizeof(buf))) @@ -65,13 +75,14 @@ BOOL WINAPI DllMain(HANDLE hDll, DWORD dwReason, LPVOID lpReserved) if (_strcmpi(s, "WIN95") == 0 || _strcmpi(s, "WIN98") == 0 || _strcmpi(s, "NT4SP5") == 0) { - char mes[128] = { 0 }; + char mes[280] = { 0 }; _snprintf( mes, sizeof(mes) - 1, - "Please disable the '%s' compatibility mode for all game executables and " - "then try to start the game again.", + "Warning: Compatibility modes detected. \n\nIf there are issues with the game then try to " + "disable the '%s' compatibility mode for all game executables.\n\n" + "Note: You can disable this warning via ddraw.ini -> 'no_compat_warning=true'", s); if (!g_config.no_compat_warning) @@ -122,6 +133,19 @@ BOOL WINAPI DllMain(HANDLE hDll, DWORD dwReason, LPVOID lpReserved) set_aware(); } + /* Make sure screensaver will stay off and monitors will stay on */ + SetThreadExecutionState(ES_CONTINUOUS | ES_DISPLAY_REQUIRED); + + /* WINE does not support SetThreadExecutionState so we'll have to use SPI_SETSCREENSAVEACTIVE instead */ + BOOL screensaver_enabled = FALSE; + SystemParametersInfoA(SPI_GETSCREENSAVEACTIVE, 0, &screensaver_enabled, 0); + + if (screensaver_enabled) + { + SystemParametersInfoA(SPI_SETSCREENSAVEACTIVE, FALSE, NULL, 0); + g_screensaver_disabled = TRUE; + } + indeo_enable(); timeBeginPeriod(1); hook_init(); @@ -129,7 +153,7 @@ BOOL WINAPI DllMain(HANDLE hDll, DWORD dwReason, LPVOID lpReserved) } case DLL_PROCESS_DETACH: { - if (GetEnvironmentVariableW(L"cnc_ddraw_config_init", NULL, 0)) + if (GetEnvironmentVariable("cnc_ddraw_config_init", NULL, 0)) return TRUE; TRACE("cnc-ddraw DLL_PROCESS_DETACH\n"); @@ -138,10 +162,35 @@ BOOL WINAPI DllMain(HANDLE hDll, DWORD dwReason, LPVOID lpReserved) indeo_disable(); timeEndPeriod(1); + keyboard_hook_exit(); dinput_hook_exit(); hook_exit(); + + SetThreadExecutionState(ES_CONTINUOUS); + + if (g_screensaver_disabled) + { + SystemParametersInfoA(SPI_SETSCREENSAVEACTIVE, TRUE, NULL, 0); + } + + ULONG(WINAPI* remove_handler)(PVOID) = + (void*)real_GetProcAddress(GetModuleHandleA("Kernel32.dll"), "RemoveVectoredExceptionHandler"); + + if (g_dbg_exception_handle && remove_handler) + remove_handler(g_dbg_exception_handle); + + if (g_config.terminate_process == 2) + TerminateProcess(GetCurrentProcess(), 0); + break; } + case DLL_THREAD_ATTACH: + { + if (g_config.singlecpu && !IsWine() && IsWindows11Version24H2OrGreater()) + { + util_set_thread_affinity(GetCurrentThreadId()); + } + } } return TRUE; @@ -152,7 +201,6 @@ void DDEnableZoom() TRACE("%s [%p]\n", __FUNCTION__, _ReturnAddress()); g_ddraw.zoom.enabled = TRUE; - InterlockedExchange(&g_ddraw.zoom.frame_skip, 20); } BOOL DDIsWindowed() @@ -175,7 +223,7 @@ HRESULT WINAPI DirectDrawCreate(GUID FAR* lpGUID, LPDIRECTDRAW FAR* lplpDD, IUnk HRESULT ret; - if (util_caller_is_ddraw_wrapper(_ReturnAddress())) + if (util_caller_is_ddraw_wrapper(_ReturnAddress()) || g_config.flightsim98_hack) { if (lplpDD) *lplpDD = NULL; @@ -220,7 +268,7 @@ HRESULT WINAPI DirectDrawCreateEx(GUID* lpGuid, LPVOID* lplpDD, REFIID iid, IUnk HRESULT ret; - if (util_caller_is_ddraw_wrapper(_ReturnAddress())) + if (util_caller_is_ddraw_wrapper(_ReturnAddress()) || g_config.flightsim98_hack) { if (lplpDD) *lplpDD = NULL; diff --git a/src/fps_limiter.c b/src/fps_limiter.c index 14c4394..0996784 100644 --- a/src/fps_limiter.c +++ b/src/fps_limiter.c @@ -120,16 +120,9 @@ BOOL fpsl_wait_for_vblank() BOOL fpsl_dwm_flush() { - if (g_fpsl.initialized && fpsl_dwm_is_enabled() && g_fpsl.DwmFlush) + if (g_fpsl.initialized && fpsl_dwm_is_enabled() && g_fpsl.DwmFlush && !IsWine()) { - HRESULT x = g_fpsl.DwmFlush(); - - if (!SUCCEEDED(x)) - { - //TRACE(" ERROR %s(result=%08X)\n", __FUNCTION__, x); - } - - return SUCCEEDED(x); + return SUCCEEDED(g_fpsl.DwmFlush()); } return FALSE; diff --git a/src/hook.c b/src/hook.c index bab3648..29846c7 100644 --- a/src/hook.c +++ b/src/hook.c @@ -8,6 +8,7 @@ #include "dllmain.h" #include "config.h" #include "utils.h" +#include "patch.h" #include "versionhelpers.h" #ifdef _MSC_VER @@ -50,23 +51,37 @@ SETWINDOWSHOOKEXAPROC real_SetWindowsHookExA = SetWindowsHookExA; PEEKMESSAGEAPROC real_PeekMessageA = PeekMessageA; GETMESSAGEAPROC real_GetMessageA = GetMessageA; GETWINDOWPLACEMENTPROC real_GetWindowPlacement = GetWindowPlacement; +SETWINDOWPLACEMENTPROC real_SetWindowPlacement = SetWindowPlacement; ENUMDISPLAYSETTINGSAPROC real_EnumDisplaySettingsA = EnumDisplaySettingsA; -VALIDATERECTPROC real_ValidateRect = ValidateRect; -INVALIDATERECTPROC real_InvalidateRect = InvalidateRect; +DEFWINDOWPROCAPROC real_DefWindowProcA = DefWindowProcA; +SETPARENTPROC real_SetParent = SetParent; +BEGINPAINTPROC real_BeginPaint = BeginPaint; GETKEYSTATEPROC real_GetKeyState = GetKeyState; GETASYNCKEYSTATEPROC real_GetAsyncKeyState = GetAsyncKeyState; GETDEVICECAPSPROC real_GetDeviceCaps = GetDeviceCaps; CREATEFONTINDIRECTAPROC real_CreateFontIndirectA = CreateFontIndirectA; CREATEFONTAPROC real_CreateFontA = CreateFontA; +GETSYSTEMPALETTEENTRIESPROC real_GetSystemPaletteEntries = GetSystemPaletteEntries; +SELECTPALETTEPROC real_SelectPalette = SelectPalette; +REALIZEPALETTEPROC real_RealizePalette = RealizePalette; LOADLIBRARYAPROC real_LoadLibraryA = LoadLibraryA; LOADLIBRARYWPROC real_LoadLibraryW = LoadLibraryW; LOADLIBRARYEXAPROC real_LoadLibraryExA = LoadLibraryExA; LOADLIBRARYEXWPROC real_LoadLibraryExW = LoadLibraryExW; GETPROCADDRESSPROC real_GetProcAddress = GetProcAddress; GETDISKFREESPACEAPROC real_GetDiskFreeSpaceA = GetDiskFreeSpaceA; +GETVERSIONPROC real_GetVersion = GetVersion; +GETVERSIONEXAPROC real_GetVersionExA = GetVersionExA; COCREATEINSTANCEPROC real_CoCreateInstance = CoCreateInstance; MCISENDCOMMANDAPROC real_mciSendCommandA = mciSendCommandA; SETUNHANDLEDEXCEPTIONFILTERPROC real_SetUnhandledExceptionFilter = SetUnhandledExceptionFilter; +AVISTREAMGETFRAMEOPENPROC real_AVIStreamGetFrameOpen = AVIStreamGetFrameOpen; + +#if (_WIN32_WINNT >= _WIN32_WINNT_WIN2K) +SETWINDOWLONGWPROC real_SetWindowLongW = SetWindowLongW; +#else +SETWINDOWLONGWPROC real_SetWindowLongW; +#endif HOOKLIST g_hook_hooklist[] = { @@ -98,16 +113,23 @@ HOOKLIST g_hook_hooklist[] = { "ShowWindow", (PROC)fake_ShowWindow, (PROC*)&real_ShowWindow, 0 }, { "GetTopWindow", (PROC)fake_GetTopWindow, (PROC*)&real_GetTopWindow, 0 }, { "GetForegroundWindow", (PROC)fake_GetForegroundWindow, (PROC*)&real_GetForegroundWindow, 0 }, - //{ "PeekMessageA", (PROC)fake_PeekMessageA, (PROC*)&real_PeekMessageA, 0 }, - //{ "GetMessageA", (PROC)fake_GetMessageA, (PROC*)&real_GetMessageA, 0 }, + { "PeekMessageA", (PROC)fake_PeekMessageA, (PROC*)&real_PeekMessageA, 0 }, + { "GetMessageA", (PROC)fake_GetMessageA, (PROC*)&real_GetMessageA, 0 }, { "GetWindowPlacement", (PROC)fake_GetWindowPlacement, (PROC*)&real_GetWindowPlacement, 0 }, + { "SetWindowPlacement", (PROC)fake_SetWindowPlacement, (PROC*)&real_SetWindowPlacement, 0 }, { "EnumDisplaySettingsA", (PROC)fake_EnumDisplaySettingsA, (PROC*)&real_EnumDisplaySettingsA, 0 }, - { "ValidateRect", (PROC)fake_ValidateRect, (PROC*)&real_ValidateRect, 0 }, - { "InvalidateRect", (PROC)fake_InvalidateRect, (PROC*)&real_InvalidateRect, 0 }, + { "DefWindowProcA", (PROC)fake_DefWindowProcA, (PROC*)&real_DefWindowProcA, 0 }, + { "SetParent", (PROC)fake_SetParent, (PROC*)&real_SetParent, 0 }, + { "BeginPaint", (PROC)fake_BeginPaint, (PROC*)&real_BeginPaint, 0 }, { "GetKeyState", (PROC)fake_GetKeyState, (PROC*)&real_GetKeyState, 0 }, { "GetAsyncKeyState", (PROC)fake_GetAsyncKeyState, (PROC*)&real_GetAsyncKeyState, 0 }, { "SetForegroundWindow", (PROC)fake_SetForegroundWindow, (PROC*)&real_SetForegroundWindow, 0 }, { "SetWindowsHookExA", (PROC)fake_SetWindowsHookExA, (PROC*)&real_SetWindowsHookExA, 0 }, + +#if (_WIN32_WINNT >= _WIN32_WINNT_WIN2K) + { "SetWindowLongW", (PROC)fake_SetWindowLongW, (PROC*)&real_SetWindowLongW, 0 }, +#endif + { "", NULL, NULL, 0 } } }, @@ -125,6 +147,13 @@ HOOKLIST g_hook_hooklist[] = { "", NULL, NULL, 0 } } }, + { + "Avifil32.dll", + { + { "AVIStreamGetFrameOpen", (PROC)fake_AVIStreamGetFrameOpen, (PROC*)&real_AVIStreamGetFrameOpen, 0 }, + { "", NULL, NULL, 0 } + } + }, { "dinput.dll", { @@ -149,7 +178,11 @@ HOOKLIST g_hook_hooklist[] = { "SetDIBitsToDevice", (PROC)fake_SetDIBitsToDevice, (PROC*)&real_SetDIBitsToDevice, HOOK_SKIP_2 }, { "StretchDIBits", (PROC)fake_StretchDIBits, (PROC*)&real_StretchDIBits, HOOK_SKIP_2 }, { "GetDeviceCaps", (PROC)fake_GetDeviceCaps, (PROC*)&real_GetDeviceCaps, HOOK_LOCAL_ONLY }, + { "GetDeviceCaps", (PROC)fake_GetDeviceCaps_system, NULL, HOOK_SYSTEM_ONLY }, { "CreateFontA", (PROC)fake_CreateFontA, (PROC*)&real_CreateFontA, 0 }, + { "GetSystemPaletteEntries", (PROC)fake_GetSystemPaletteEntries, (PROC*)&real_GetSystemPaletteEntries, 0 }, + { "SelectPalette", (PROC)fake_SelectPalette, (PROC*)&real_SelectPalette, 0 }, + { "RealizePalette", (PROC)fake_RealizePalette, (PROC*)&real_RealizePalette, 0 }, { "CreateFontIndirectA", (PROC)fake_CreateFontIndirectA, (PROC*)&real_CreateFontIndirectA, 0 }, { "", NULL, NULL, 0 } } @@ -157,20 +190,22 @@ HOOKLIST g_hook_hooklist[] = { "WING32.DLL", { - { "WinGBitBlt", (PROC)fake_WinGBitBlt, NULL, HOOK_SKIP_2 }, - { "WinGStretchBlt", (PROC)fake_WinGStretchBlt, NULL, HOOK_SKIP_2 }, + { "WinGBitBlt", (PROC)fake_WinGBitBlt, NULL, 0 }, + { "WinGStretchBlt", (PROC)fake_WinGStretchBlt, NULL, 0 }, { "", NULL, NULL, 0 } } }, { "kernel32.dll", { - //{ "LoadLibraryA", (PROC)fake_LoadLibraryA, (PROC*)&real_LoadLibraryA, HOOK_SKIP_2 }, + { "LoadLibraryA", (PROC)fake_LoadLibraryA, (PROC*)&real_LoadLibraryA, HOOK_SKIP_2 }, { "LoadLibraryW", (PROC)fake_LoadLibraryW, (PROC*)&real_LoadLibraryW, HOOK_SKIP_2 }, { "LoadLibraryExA", (PROC)fake_LoadLibraryExA, (PROC*)&real_LoadLibraryExA, HOOK_SKIP_2 }, { "LoadLibraryExW", (PROC)fake_LoadLibraryExW, (PROC*)&real_LoadLibraryExW, HOOK_SKIP_2 }, { "GetProcAddress", (PROC)fake_GetProcAddress, (PROC*)&real_GetProcAddress, HOOK_SKIP_2 }, - { "GetDiskFreeSpaceA", (PROC)fake_GetDiskFreeSpaceA, (PROC*)&real_GetDiskFreeSpaceA, HOOK_SKIP_2 }, + { "GetDiskFreeSpaceA", (PROC)fake_GetDiskFreeSpaceA, (PROC*)&real_GetDiskFreeSpaceA, 0 }, + { "GetVersion", (PROC)fake_GetVersion, (PROC*)&real_GetVersion, 0 }, + { "GetVersionExA", (PROC)fake_GetVersionExA, (PROC*)&real_GetVersionExA, 0 }, #if defined(_DEBUG) && defined(__GNUC__) { "SetUnhandledExceptionFilter", (PROC)fake_SetUnhandledExceptionFilter, (PROC*)&real_SetUnhandledExceptionFilter, 0 }, #endif @@ -209,17 +244,15 @@ void hook_patch_obfuscated_iat_list(HMODULE hmod, BOOL unhook, HOOKLIST* hooks, if (dos_header->e_magic != IMAGE_DOS_SIGNATURE) return; - PIMAGE_NT_HEADERS nt_headers = (PIMAGE_NT_HEADERS)((DWORD)dos_header + (DWORD)dos_header->e_lfanew); + PIMAGE_NT_HEADERS nt_headers = (PIMAGE_NT_HEADERS)((DWORD)hmod + (DWORD)dos_header->e_lfanew); if (nt_headers->Signature != IMAGE_NT_SIGNATURE) return; DWORD import_desc_rva = nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress; - DWORD import_desc_size = nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size; - - if (import_desc_rva == 0 || import_desc_size == 0) + if (!import_desc_rva) return; - PIMAGE_IMPORT_DESCRIPTOR import_desc = (PIMAGE_IMPORT_DESCRIPTOR)((DWORD)dos_header + import_desc_rva); + PIMAGE_IMPORT_DESCRIPTOR import_desc = (PIMAGE_IMPORT_DESCRIPTOR)((DWORD)hmod + import_desc_rva); while (import_desc->FirstThunk) { @@ -231,13 +264,13 @@ void hook_patch_obfuscated_iat_list(HMODULE hmod, BOOL unhook, HOOKLIST* hooks, for (int i = 0; hooks[i].module_name[0]; i++) { - char* imp_module_name = (char*)((DWORD)dos_header + import_desc->Name); + char* imp_module_name = (char*)((DWORD)hmod + import_desc->Name); if (_stricmp(imp_module_name, hooks[i].module_name) == 0) { HMODULE cur_mod = GetModuleHandleA(hooks[i].module_name); - PIMAGE_THUNK_DATA first_thunk = (void*)((DWORD)dos_header + import_desc->FirstThunk); + PIMAGE_THUNK_DATA first_thunk = (void*)((DWORD)hmod + import_desc->FirstThunk); while (first_thunk->u1.Function) { @@ -261,6 +294,9 @@ void hook_patch_obfuscated_iat_list(HMODULE hmod, BOOL unhook, HOOKLIST* hooks, if (!is_local && (hooks[i].data[x].flags & HOOK_LOCAL_ONLY)) continue; + if (is_local && (hooks[i].data[x].flags & HOOK_SYSTEM_ONLY)) + continue; + if (unhook) { if (first_thunk->u1.Function == (DWORD)hooks[i].data[x].new_function) @@ -331,17 +367,15 @@ void hook_patch_iat_list(HMODULE hmod, BOOL unhook, HOOKLIST* hooks, BOOL is_loc if (dos_header->e_magic != IMAGE_DOS_SIGNATURE) return; - PIMAGE_NT_HEADERS nt_headers = (PIMAGE_NT_HEADERS)((DWORD)dos_header + (DWORD)dos_header->e_lfanew); + PIMAGE_NT_HEADERS nt_headers = (PIMAGE_NT_HEADERS)((DWORD)hmod + (DWORD)dos_header->e_lfanew); if (nt_headers->Signature != IMAGE_NT_SIGNATURE) return; DWORD import_desc_rva = nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress; - DWORD import_desc_size = nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size; - - if (import_desc_rva == 0 || import_desc_size == 0) + if (!import_desc_rva) return; - PIMAGE_IMPORT_DESCRIPTOR import_desc = (PIMAGE_IMPORT_DESCRIPTOR)((DWORD)dos_header + import_desc_rva); + PIMAGE_IMPORT_DESCRIPTOR import_desc = (PIMAGE_IMPORT_DESCRIPTOR)((DWORD)hmod + import_desc_rva); while (import_desc->FirstThunk) { @@ -353,12 +387,12 @@ void hook_patch_iat_list(HMODULE hmod, BOOL unhook, HOOKLIST* hooks, BOOL is_loc for (int i = 0; hooks[i].module_name[0]; i++) { - char* imp_module_name = (char*)((DWORD)dos_header + import_desc->Name); + char* imp_module_name = (char*)((DWORD)hmod + import_desc->Name); if (_stricmp(imp_module_name, hooks[i].module_name) == 0) { - PIMAGE_THUNK_DATA first_thunk = (void*)((DWORD)dos_header + import_desc->FirstThunk); - PIMAGE_THUNK_DATA o_first_thunk = (void*)((DWORD)dos_header + import_desc->OriginalFirstThunk); + PIMAGE_THUNK_DATA first_thunk = (void*)((DWORD)hmod + import_desc->FirstThunk); + PIMAGE_THUNK_DATA o_first_thunk = (void*)((DWORD)hmod + import_desc->OriginalFirstThunk); while (first_thunk->u1.Function) { @@ -381,6 +415,9 @@ void hook_patch_iat_list(HMODULE hmod, BOOL unhook, HOOKLIST* hooks, BOOL is_loc if (!is_local && (hooks[i].data[x].flags & HOOK_LOCAL_ONLY)) continue; + if (is_local && (hooks[i].data[x].flags & HOOK_SYSTEM_ONLY)) + continue; + #if defined(__GNUC__) if (util_is_bad_read_ptr((void*)import->Name)) continue; @@ -449,27 +486,25 @@ BOOL hook_got_ddraw_import(HMODULE mod, BOOL check_imported_dlls) if (dos_header->e_magic != IMAGE_DOS_SIGNATURE) return FALSE; - PIMAGE_NT_HEADERS nt_headers = (PIMAGE_NT_HEADERS)((DWORD)dos_header + (DWORD)dos_header->e_lfanew); + PIMAGE_NT_HEADERS nt_headers = (PIMAGE_NT_HEADERS)((DWORD)mod + (DWORD)dos_header->e_lfanew); if (nt_headers->Signature != IMAGE_NT_SIGNATURE) return FALSE; DWORD import_desc_rva = nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress; - DWORD import_desc_size = nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size; - - if (import_desc_rva == 0 || import_desc_size == 0) + if (!import_desc_rva) return FALSE; - PIMAGE_IMPORT_DESCRIPTOR import_desc = (PIMAGE_IMPORT_DESCRIPTOR)((DWORD)dos_header + import_desc_rva); + PIMAGE_IMPORT_DESCRIPTOR import_desc = (PIMAGE_IMPORT_DESCRIPTOR)((DWORD)mod + import_desc_rva); while (import_desc->FirstThunk) { if (import_desc->Name) { - char* imp_module_name = (char*)((DWORD)dos_header + import_desc->Name); + char* imp_module_name = (char*)((DWORD)mod + import_desc->Name); if (_stricmp(imp_module_name, "ddraw.dll") == 0) { - PIMAGE_THUNK_DATA first_thunk = (void*)((DWORD)dos_header + import_desc->FirstThunk); + PIMAGE_THUNK_DATA first_thunk = (void*)((DWORD)mod + import_desc->FirstThunk); if (first_thunk->u1.Function) return TRUE; @@ -546,6 +581,7 @@ void hook_create(HOOKLIST* hooks, BOOL initial_hook) _strcmpi(mod_filename, "libglapi") == 0 || _strcmpi(mod_filename, "d3d9") == 0 || _strcmpi(mod_filename, "mdraw") == 0 || + _strcmpi(mod_filename, "SH33W32") == 0 || _strcmpi(mod_filename, "Shw32") == 0) continue; @@ -647,6 +683,8 @@ void hook_init() { /* Switch to 3 if we can be sure that ddraw.dll will not be unloaded from the process */ g_config.hook = 3; + + TRACE("Switched to hook 3\n"); } } @@ -659,6 +697,11 @@ void hook_init() DetourUpdateThread(GetCurrentThread()); DetourAttach((PVOID*)&real_SetUnhandledExceptionFilter, (PVOID)fake_SetUnhandledExceptionFilter); DetourTransactionCommit(); + + if (!IsDebuggerPresent()) + { + patch_ljmp((void*)_invoke_watson, (void*)dbg_invoke_watson); + } } #endif diff --git a/src/keyboard.c b/src/keyboard.c new file mode 100644 index 0000000..f54ba63 --- /dev/null +++ b/src/keyboard.c @@ -0,0 +1,132 @@ +#include +#include "debug.h" +#include "hook.h" +#include "dd.h" +#include "utils.h" +#include "config.h" +#include "keyboard.h" +#include "mouse.h" +#include "screenshot.h" + + +HHOOK g_keyboard_hook; + +void keyboard_hook_init() +{ + if (g_keyboard_hook && UnhookWindowsHookEx(g_keyboard_hook)) + { + g_keyboard_hook = NULL; + } + + if (!g_ddraw.gui_thread_id) + return; + + g_keyboard_hook = + real_SetWindowsHookExA( + WH_KEYBOARD, + keyboard_hook_proc, + NULL, + g_ddraw.gui_thread_id); +} + +void keyboard_hook_exit() +{ + if (g_keyboard_hook) + { + UnhookWindowsHookEx(g_keyboard_hook); + } +} + +LRESULT CALLBACK keyboard_hook_proc(int code, WPARAM wParam, LPARAM lParam) +{ + if (code < 0 || !wParam) + return CallNextHookEx(g_keyboard_hook, code, wParam, lParam); + + BOOL alt_down = !!(lParam & (1 << 29)); + BOOL key_down = !(lParam & (1 << 31)); + BOOL key_released = !!(lParam & (1 << 31)); + BOOL key_triggered = !(lParam & (1 << 30)); + + //TRACE("kbhook code=%u, wParam=%u, triggered=%u, released=%u, alt_down=%u\n", code, wParam, key_triggered, key_released, alt_down); + + if (wParam == VK_MENU && (key_released || key_triggered)) /* Fix for alt key being stuck on alt+tab in some games */ + { + g_ddraw.alt_key_down = alt_down; + } + + if (wParam == g_config.hotkeys.toggle_fullscreen && alt_down && key_down) + { + if (key_triggered) + util_toggle_fullscreen(); + + return 1; + } + + if (wParam == g_config.hotkeys.toggle_fullscreen2) + { + if (key_triggered) + util_toggle_fullscreen(); + + return 1; + } + + if (wParam == g_config.hotkeys.toggle_maximize && alt_down && key_down) + { + if (key_triggered) + util_toggle_maximize(); + + return 1; + } + + if (wParam == g_config.hotkeys.toggle_maximize2) + { + if (key_triggered) + util_toggle_maximize(); + + return 1; + } + + if (wParam == g_config.hotkeys.screenshot) + { + // VK_SNAPSHOT does not have a KEYDOWN event... + if (g_config.hotkeys.screenshot == VK_SNAPSHOT) + { + if (key_released) + { + ss_take_screenshot(g_ddraw.primary); + return 1; + } + } + else if (key_triggered) + { + ss_take_screenshot(g_ddraw.primary); + return 1; + } + } + + if (wParam == g_config.hotkeys.unlock_cursor1 || wParam == VK_CONTROL) + { + if ((real_GetAsyncKeyState(VK_CONTROL) & 0x8000) && + (real_GetAsyncKeyState(g_config.hotkeys.unlock_cursor1) & 0x8000)) + { + mouse_unlock(); + + if (key_down) + return 1; + } + } + + if (wParam == g_config.hotkeys.unlock_cursor2 || wParam == VK_MENU || wParam == VK_CONTROL) + { + if ((real_GetAsyncKeyState(VK_RMENU) & 0x8000) && + (real_GetAsyncKeyState(g_config.hotkeys.unlock_cursor2) & 0x8000)) + { + mouse_unlock(); + + if (key_down) + return 1; + } + } + + return CallNextHookEx(g_keyboard_hook, code, wParam, lParam); +} diff --git a/src/mouse.c b/src/mouse.c index 391e985..46aca13 100644 --- a/src/mouse.c +++ b/src/mouse.c @@ -38,35 +38,12 @@ void mouse_lock() real_MapWindowPoints(g_ddraw.hwnd, HWND_DESKTOP, (LPPOINT)&rc, 2); OffsetRect(&rc, g_ddraw.render.viewport.x, g_ddraw.render.viewport.y); - POINT pt; - real_GetCursorPos(&pt); - - if (!g_config.windowed || real_ScreenToClient(g_ddraw.hwnd, &pt)) - { - if (pt.x > g_ddraw.render.viewport.x + g_ddraw.render.viewport.width || - pt.x < g_ddraw.render.viewport.x || - pt.y > g_ddraw.render.viewport.y + g_ddraw.render.viewport.height || - pt.y < g_ddraw.render.viewport.y) - { - pt.x = g_ddraw.width / 2; - pt.y = g_ddraw.height / 2; - } - else - { - pt.x = (DWORD)((pt.x - g_ddraw.render.viewport.x) * g_ddraw.mouse.unscale_x); - pt.y = (DWORD)((pt.y - g_ddraw.render.viewport.y) * g_ddraw.mouse.unscale_y); - } - - pt.x = min(pt.x, g_ddraw.width - 1); - pt.y = min(pt.y, g_ddraw.height - 1); - - InterlockedExchange((LONG*)&g_ddraw.cursor.x, pt.x); - InterlockedExchange((LONG*)&g_ddraw.cursor.y, pt.y); - } + int cur_x = InterlockedExchangeAdd((LONG*)&g_ddraw.cursor.x, 0); + int cur_y = InterlockedExchangeAdd((LONG*)&g_ddraw.cursor.y, 0); real_SetCursorPos( - g_config.adjmouse ? (int)(rc.left + (pt.x * g_ddraw.mouse.scale_x)) : rc.left + pt.x, - g_config.adjmouse ? (int)(rc.top + (pt.y * g_ddraw.mouse.scale_y)) : rc.top + pt.y); + g_config.adjmouse ? (int)(rc.left + (cur_x * g_ddraw.mouse.scale_x)) : rc.left + cur_x, + g_config.adjmouse ? (int)(rc.top + (cur_y * g_ddraw.mouse.scale_y)) : rc.top + cur_y); CopyRect(&rc, &g_ddraw.mouse.rc); real_MapWindowPoints(g_ddraw.hwnd, HWND_DESKTOP, (LPPOINT)&rc, 2); @@ -86,7 +63,7 @@ void mouse_unlock() g_mouse_locked = FALSE; real_ClipCursor(NULL); - //ReleaseCapture(); + ReleaseCapture(); RECT rc = { 0 }; real_GetClientRect(g_ddraw.hwnd, &rc); diff --git a/src/opengl_utils.c b/src/opengl_utils.c index 9e63d8a..e315b15 100644 --- a/src/opengl_utils.c +++ b/src/opengl_utils.c @@ -88,11 +88,14 @@ PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT; PFNWGLGETEXTENSIONSSTRINGARBPROC wglGetExtensionsStringARB; PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB; PFNGLTEXBUFFERPROC glTexBuffer; +PFNGLGETINTEGERVPROC glGetIntegerv; +PFNGLGETSTRINGIPROC glGetStringi; HMODULE g_oglu_hmodule; BOOL g_oglu_got_version2; BOOL g_oglu_got_version3; char g_oglu_version[128]; +char g_oglu_version_long[128]; BOOL oglu_load_dll() { @@ -192,11 +195,14 @@ void oglu_init() wglGetExtensionsStringARB = (PFNWGLGETEXTENSIONSSTRINGARBPROC)xwglGetProcAddress("wglGetExtensionsStringARB"); glTexBuffer = (PFNGLTEXBUFFERPROC)xwglGetProcAddress("glTexBuffer"); + glGetIntegerv = (PFNGLGETINTEGERVPROC)xwglGetProcAddress("glGetIntegerv"); + glGetStringi = (PFNGLGETSTRINGIPROC)xwglGetProcAddress("glGetStringi"); char* glversion = (char*)glGetString(GL_VERSION); if (glversion) { strncpy(g_oglu_version, glversion, sizeof(g_oglu_version) - 1); + strncpy(g_oglu_version_long, glversion, sizeof(g_oglu_version_long) - 1); g_oglu_version[sizeof(g_oglu_version) - 1] = '\0'; /* strncpy fix */ strtok(g_oglu_version, " "); } @@ -227,11 +233,32 @@ void oglu_init() BOOL oglu_ext_exists(char* ext, HDC hdc) { - char* glext = (char*)glGetString(GL_EXTENSIONS); + BOOL got_num_extensions = FALSE; - if (glext) + if (glGetIntegerv && glGetStringi) { - if (strstr(glext, ext)) + GLint n = 0; + glGetIntegerv(GL_NUM_EXTENSIONS, &n); + + if (glGetError() == GL_NO_ERROR) + { + got_num_extensions = TRUE; + + for (GLint i = 0; i < n; i++) + { + char* glext = (char*)glGetStringi(GL_EXTENSIONS, i); + + if (glext && strcmp(glext, ext) == 0) + return TRUE; + } + } + } + + if (!got_num_extensions) + { + char* glext = (char*)glGetString(GL_EXTENSIONS); + + if (glext && strstr(glext, ext)) return TRUE; } diff --git a/src/render_d3d9.c b/src/render_d3d9.c index 876618d..dde4b2c 100644 --- a/src/render_d3d9.c +++ b/src/render_d3d9.c @@ -15,6 +15,16 @@ #include "config.h" +#ifdef _DEBUG +#define FAILEDX(stmt) d3d9_check_failed(stmt, #stmt) +#define SUCCEEDEDX(stmt) d3d9_check_succeeded(stmt, #stmt) +static BOOL d3d9_check_failed(HRESULT hr, const char* stmt); +static BOOL d3d9_check_succeeded(HRESULT hr, const char* stmt); +#else +#define FAILEDX(stmt) FAILED(stmt) +#define SUCCEEDEDX(stmt) SUCCEEDED(stmt) +#endif + static BOOL d3d9_create_resources(); static BOOL d3d9_set_states(); static BOOL d3d9_update_vertices(BOOL upscale_hack, BOOL stretch); @@ -86,10 +96,10 @@ BOOL d3d9_create() #if _DEBUG D3DADAPTER_IDENTIFIER9 ai = {0}; D3DCAPS9 caps = { 0 }; - HRESULT hr = IDirect3D9_GetAdapterIdentifier(g_d3d9.instance, D3DADAPTER_DEFAULT, 0, &ai); - HRESULT hr2 = IDirect3D9_GetDeviceCaps(g_d3d9.instance, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &caps); + HRESULT adapter_hr = IDirect3D9_GetAdapterIdentifier(g_d3d9.instance, D3DADAPTER_DEFAULT, 0, &ai); + HRESULT devcaps_hr = IDirect3D9_GetDeviceCaps(g_d3d9.instance, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &caps); - if (SUCCEEDED(hr)) + if (SUCCEEDEDX(adapter_hr)) { TRACE("+--Direct3D9-------------------------------------\n"); TRACE("| D3D9On12: %s (%p)\n", d3d9on12 != NULL ? "True" : "False", GetModuleHandleA("d3d9on12.dll")); @@ -106,7 +116,7 @@ BOOL d3d9_create() TRACE("| Driver: %s\n", ai.Driver); TRACE("| Description: %s\n", ai.Description); - if (SUCCEEDED(hr2)) + if (SUCCEEDEDX(devcaps_hr)) { TRACE("| MaxTextureWidth: %d\n", caps.MaxTextureWidth); TRACE("| MaxTextureHeight: %d\n", caps.MaxTextureHeight); @@ -146,7 +156,7 @@ BOOL d3d9_create() for (int i = 0; i < sizeof(behavior_flags) / sizeof(behavior_flags[0]); i++) { - if (SUCCEEDED( + if (SUCCEEDEDX( IDirect3D9_CreateDevice( g_d3d9.instance, D3DADAPTER_DEFAULT, @@ -163,6 +173,31 @@ BOOL d3d9_create() return FALSE; } +#ifdef _DEBUG +static BOOL d3d9_check_failed(HRESULT hr, const char* stmt) +{ + if (FAILED(hr)) + { + TRACE("Direct3D9 error %s [%08x] (%s)\n", dbg_d3d9_hr_to_str(hr), hr, stmt); + return TRUE; + } + + return FALSE; +} + +static BOOL d3d9_check_succeeded(HRESULT hr, const char* stmt) +{ + if (!SUCCEEDED(hr)) + { + TRACE("Direct3D9 error %s [%08x] (%s)\n", dbg_d3d9_hr_to_str(hr), hr, stmt); + + return FALSE; + } + + return TRUE; +} +#endif + BOOL d3d9_on_device_lost() { if (g_d3d9.device && IDirect3DDevice9_TestCooperativeLevel(g_d3d9.device) == D3DERR_DEVICENOTRESET) @@ -181,7 +216,7 @@ BOOL d3d9_reset(BOOL windowed) g_d3d9.params.FullScreen_RefreshRateInHz = g_d3d9.params.Windowed ? 0 : g_config.refresh_rate; g_d3d9.params.BackBufferFormat = g_ddraw.mode.dmBitsPerPel == 16 ? D3DFMT_R5G6B5 : D3DFMT_X8R8G8B8; - if (g_d3d9.device && SUCCEEDED(IDirect3DDevice9_Reset(g_d3d9.device, &g_d3d9.params))) + if (g_d3d9.device && SUCCEEDEDX(IDirect3DDevice9_Reset(g_d3d9.device, &g_d3d9.params))) { BOOL result = d3d9_set_states(); @@ -278,7 +313,7 @@ static BOOL d3d9_create_resources() g_d3d9.scale_w = (float)width / g_d3d9.tex_width;; g_d3d9.scale_h = (float)height / g_d3d9.tex_height; - err = err || FAILED( + err = err || FAILEDX( IDirect3DDevice9_CreateVertexBuffer( g_d3d9.device, sizeof(CUSTOMVERTEX) * 4, 0, @@ -293,7 +328,7 @@ static BOOL d3d9_create_resources() { if (g_ddraw.bpp == 16 && g_config.rgb555) { - BOOL error = FAILED( + BOOL error = FAILEDX( IDirect3DDevice9_CreateTexture( g_d3d9.device, g_d3d9.tex_width, @@ -307,7 +342,7 @@ static BOOL d3d9_create_resources() if (error) { - err = err || FAILED( + err = err || FAILEDX( IDirect3DDevice9_CreateTexture( g_d3d9.device, g_d3d9.tex_width, @@ -322,7 +357,7 @@ static BOOL d3d9_create_resources() } else if (g_ddraw.bpp == 32) { - BOOL error = FAILED( + BOOL error = FAILEDX( IDirect3DDevice9_CreateTexture( g_d3d9.device, g_d3d9.tex_width, @@ -336,7 +371,7 @@ static BOOL d3d9_create_resources() if (error) { - err = err || FAILED( + err = err || FAILEDX( IDirect3DDevice9_CreateTexture( g_d3d9.device, g_d3d9.tex_width, @@ -351,7 +386,7 @@ static BOOL d3d9_create_resources() } else { - err = err || FAILED( + err = err || FAILEDX( IDirect3DDevice9_CreateTexture( g_d3d9.device, g_d3d9.tex_width, @@ -368,7 +403,7 @@ static BOOL d3d9_create_resources() if (g_ddraw.bpp == 8) { - BOOL error = FAILED( + BOOL error = FAILEDX( IDirect3DDevice9_CreateTexture( g_d3d9.device, 256, @@ -382,7 +417,7 @@ static BOOL d3d9_create_resources() if (error) { - err = err || FAILED( + err = err || FAILEDX( IDirect3DDevice9_CreateTexture( g_d3d9.device, 256, @@ -401,7 +436,7 @@ static BOOL d3d9_create_resources() if (g_ddraw.bpp == 8) { - err = err || FAILED( + err = err || FAILEDX( IDirect3DDevice9_CreatePixelShader(g_d3d9.device, (DWORD*)D3D9_PALETTE_SHADER, &g_d3d9.pixel_shader)); IDirect3DDevice9_CreatePixelShader( @@ -413,7 +448,7 @@ static BOOL d3d9_create_resources() { if (g_config.d3d9_filter == FILTER_LANCZOS) { - BOOL error = FAILED( + BOOL error = FAILEDX( IDirect3DDevice9_CreatePixelShader( g_d3d9.device, (DWORD*)D3D9_LANCZOS2_SHADER, @@ -441,20 +476,20 @@ static BOOL d3d9_set_states() { BOOL err = FALSE; - err = err || FAILED(IDirect3DDevice9_SetFVF(g_d3d9.device, D3DFVF_XYZRHW | D3DFVF_TEX1)); - err = err || FAILED(IDirect3DDevice9_SetStreamSource(g_d3d9.device, 0, g_d3d9.vertex_buf, 0, sizeof(CUSTOMVERTEX))); - err = err || FAILED(IDirect3DDevice9_SetTexture(g_d3d9.device, 0, (IDirect3DBaseTexture9*)g_d3d9.surface_tex[0])); + err = err || FAILEDX(IDirect3DDevice9_SetFVF(g_d3d9.device, D3DFVF_XYZRHW | D3DFVF_TEX1)); + err = err || FAILEDX(IDirect3DDevice9_SetStreamSource(g_d3d9.device, 0, g_d3d9.vertex_buf, 0, sizeof(CUSTOMVERTEX))); + err = err || FAILEDX(IDirect3DDevice9_SetTexture(g_d3d9.device, 0, (IDirect3DBaseTexture9*)g_d3d9.surface_tex[0])); if (g_ddraw.bpp == 8) { - err = err || FAILED(IDirect3DDevice9_SetTexture(g_d3d9.device, 1, (IDirect3DBaseTexture9*)g_d3d9.palette_tex[0])); + err = err || FAILEDX(IDirect3DDevice9_SetTexture(g_d3d9.device, 1, (IDirect3DBaseTexture9*)g_d3d9.palette_tex[0])); BOOL bilinear = g_config.d3d9_filter && g_d3d9.pixel_shader_upscale && (g_ddraw.render.viewport.width != g_ddraw.width || g_ddraw.render.viewport.height != g_ddraw.height || g_config.vhack); - err = err || FAILED( + err = err || FAILEDX( IDirect3DDevice9_SetPixelShader( g_d3d9.device, bilinear ? g_d3d9.pixel_shader_upscale : g_d3d9.pixel_shader)); @@ -462,7 +497,7 @@ static BOOL d3d9_set_states() if (bilinear) { float texture_size[4] = { (float)g_d3d9.tex_width, (float)g_d3d9.tex_height, 0, 0 }; - err = err || FAILED(IDirect3DDevice9_SetPixelShaderConstantF(g_d3d9.device, 0, texture_size, 1)); + err = err || FAILEDX(IDirect3DDevice9_SetPixelShaderConstantF(g_d3d9.device, 0, texture_size, 1)); } } else @@ -473,22 +508,22 @@ static BOOL d3d9_set_states() g_d3d9.pixel_shader_upscale && (g_ddraw.render.viewport.width != g_ddraw.width || g_ddraw.render.viewport.height != g_ddraw.height) && - SUCCEEDED(IDirect3DDevice9_SetPixelShader(g_d3d9.device, g_d3d9.pixel_shader_upscale))) + SUCCEEDEDX(IDirect3DDevice9_SetPixelShader(g_d3d9.device, g_d3d9.pixel_shader_upscale))) { float texture_size[4] = { (float)g_d3d9.tex_width, (float)g_d3d9.tex_height, 0, 0 }; - err = err || FAILED(IDirect3DDevice9_SetPixelShaderConstantF(g_d3d9.device, 0, texture_size, 1)); + err = err || FAILEDX(IDirect3DDevice9_SetPixelShaderConstantF(g_d3d9.device, 0, texture_size, 1)); } else if ( - SUCCEEDED(IDirect3DDevice9_SetSamplerState(g_d3d9.device, 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR)) && - SUCCEEDED(IDirect3DDevice9_SetSamplerState(g_d3d9.device, 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR)) && + SUCCEEDEDX(IDirect3DDevice9_SetSamplerState(g_d3d9.device, 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR)) && + SUCCEEDEDX(IDirect3DDevice9_SetSamplerState(g_d3d9.device, 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR)) && g_config.d3d9_filter == FILTER_CUBIC && g_d3d9.pixel_shader_upscale && (g_ddraw.render.viewport.width != g_ddraw.width || g_ddraw.render.viewport.height != g_ddraw.height) && - SUCCEEDED(IDirect3DDevice9_SetPixelShader(g_d3d9.device, g_d3d9.pixel_shader_upscale))) + SUCCEEDEDX(IDirect3DDevice9_SetPixelShader(g_d3d9.device, g_d3d9.pixel_shader_upscale))) { float texture_size[4] = { (float)g_d3d9.tex_width, (float)g_d3d9.tex_height, 0, 0 }; - err = err || FAILED(IDirect3DDevice9_SetPixelShaderConstantF(g_d3d9.device, 0, texture_size, 1)); + err = err || FAILEDX(IDirect3DDevice9_SetPixelShaderConstantF(g_d3d9.device, 0, texture_size, 1)); } } } @@ -502,7 +537,7 @@ static BOOL d3d9_set_states() 0.0f, 1.0f }; - err = err || FAILED(IDirect3DDevice9_SetViewport(g_d3d9.device, &view_data)); + err = err || FAILEDX(IDirect3DDevice9_SetViewport(g_d3d9.device, &view_data)); */ return !err; } @@ -527,7 +562,7 @@ static BOOL d3d9_update_vertices(BOOL upscale_hack, BOOL stretch) }; void* data; - if (g_d3d9.vertex_buf && SUCCEEDED(IDirect3DVertexBuffer9_Lock(g_d3d9.vertex_buf, 0, 0, (void**)&data, 0))) + if (g_d3d9.vertex_buf && SUCCEEDEDX(IDirect3DVertexBuffer9_Lock(g_d3d9.vertex_buf, 0, 0, (void**)&data, 0))) { memcpy(data, vertices, sizeof(vertices)); @@ -540,7 +575,7 @@ static BOOL d3d9_update_vertices(BOOL upscale_hack, BOOL stretch) DWORD WINAPI d3d9_render_main(void) { - //Sleep(250); + Sleep(250); fpsl_init(); @@ -552,9 +587,6 @@ DWORD WINAPI d3d9_render_main(void) (g_config.minfps < 0 || WaitForSingleObject(g_ddraw.render.sem, timeout) != WAIT_FAILED) && g_ddraw.render.run) { - if (InterlockedDecrement(&g_ddraw.zoom.frame_skip) > 0) - continue; - #if _DEBUG dbg_draw_frame_info_start(); #endif @@ -597,8 +629,8 @@ DWORD WINAPI d3d9_render_main(void) RECT rc = { 0, 0, g_ddraw.width, g_ddraw.height }; - if (SUCCEEDED(IDirect3DDevice9_SetTexture(g_d3d9.device, 0, (IDirect3DBaseTexture9*)g_d3d9.surface_tex[tex_index])) && - SUCCEEDED(IDirect3DTexture9_LockRect(g_d3d9.surface_tex[tex_index], 0, &lock_rc, &rc, 0))) + if (SUCCEEDEDX(IDirect3DDevice9_SetTexture(g_d3d9.device, 0, (IDirect3DBaseTexture9*)g_d3d9.surface_tex[tex_index])) && + SUCCEEDEDX(IDirect3DTexture9_LockRect(g_d3d9.surface_tex[tex_index], 0, &lock_rc, &rc, 0))) { blt_clean( lock_rc.pBits, @@ -625,8 +657,8 @@ DWORD WINAPI d3d9_render_main(void) RECT rc = { 0,0,256,1 }; - if (SUCCEEDED(IDirect3DDevice9_SetTexture(g_d3d9.device, 1, (IDirect3DBaseTexture9*)g_d3d9.palette_tex[pal_index])) && - SUCCEEDED(IDirect3DTexture9_LockRect(g_d3d9.palette_tex[pal_index], 0, &lock_rc, &rc, 0))) + if (SUCCEEDEDX(IDirect3DDevice9_SetTexture(g_d3d9.device, 1, (IDirect3DBaseTexture9*)g_d3d9.palette_tex[pal_index])) && + SUCCEEDEDX(IDirect3DTexture9_LockRect(g_d3d9.palette_tex[pal_index], 0, &lock_rc, &rc, 0))) { memcpy(lock_rc.pBits, g_ddraw.primary->palette->data_rgb, 256 * sizeof(int)); @@ -637,7 +669,6 @@ DWORD WINAPI d3d9_render_main(void) if (g_config.fixchilds) { g_ddraw.child_window_exists = FALSE; - InterlockedExchangePointer((void*)&g_ddraw.video_window_hwnd, NULL); EnumChildWindows(g_ddraw.hwnd, util_enum_child_proc, (LPARAM)g_ddraw.primary); if (g_ddraw.render.width != g_ddraw.width || g_ddraw.render.height != g_ddraw.height) @@ -685,6 +716,14 @@ DWORD WINAPI d3d9_render_main(void) ReleaseSemaphore(g_ddraw.render.sem, 1, NULL); Sleep(50); } + else + { + /* Force redraw for GDI games (ClueFinders) */ + if (!g_ddraw.primary) + { + RedrawWindow(g_ddraw.hwnd, NULL, NULL, RDW_INVALIDATE | RDW_ALLCHILDREN); + } + } if (!g_ddraw.render.run) break; diff --git a/src/render_gdi.c b/src/render_gdi.c index 3501bbd..c7292ed 100644 --- a/src/render_gdi.c +++ b/src/render_gdi.c @@ -37,7 +37,6 @@ DWORD WINAPI gdi_render_main(void) Sleep(500); fpsl_init(); - SetStretchBltMode(g_ddraw.render.hdc, COLORONCOLOR); DWORD timeout = g_config.minfps > 0 ? g_ddraw.minfps_tick_len : INFINITE; @@ -86,7 +85,6 @@ DWORD WINAPI gdi_render_main(void) if (g_config.fixchilds) { g_ddraw.child_window_exists = FALSE; - InterlockedExchangePointer((void*)&g_ddraw.video_window_hwnd, NULL); EnumChildWindows(g_ddraw.hwnd, util_enum_child_proc, (LPARAM)g_ddraw.primary); } @@ -101,14 +99,17 @@ DWORD WINAPI gdi_render_main(void) FillRect(g_ddraw.render.hdc, &rc, (HBRUSH)GetStockObject(BLACK_BRUSH)); } + int lines_copied = 0; + if (g_ddraw.bnet_active) { RECT rc = { 0, 0, g_ddraw.render.width, g_ddraw.render.height }; FillRect(g_ddraw.render.hdc, &rc, (HBRUSH)GetStockObject(BLACK_BRUSH)); + lines_copied = 1; } else if (upscale_hack) { - real_StretchDIBits( + lines_copied = real_StretchDIBits( g_ddraw.render.hdc, g_ddraw.render.viewport.x, g_ddraw.render.viewport.y, @@ -126,7 +127,7 @@ DWORD WINAPI gdi_render_main(void) else if (!g_ddraw.child_window_exists && (g_ddraw.render.width != g_ddraw.width || g_ddraw.render.height != g_ddraw.height)) { - real_StretchDIBits( + lines_copied = real_StretchDIBits( g_ddraw.render.hdc, g_ddraw.render.viewport.x, g_ddraw.render.viewport.y, @@ -141,7 +142,8 @@ DWORD WINAPI gdi_render_main(void) DIB_RGB_COLORS, SRCCOPY); } - else + + if (lines_copied == 0 || lines_copied == GDI_ERROR) { real_SetDIBitsToDevice( g_ddraw.render.hdc, @@ -164,6 +166,12 @@ DWORD WINAPI gdi_render_main(void) LeaveCriticalSection(&g_ddraw.cs); + /* Force redraw for GDI games (ClueFinders) */ + if (!g_ddraw.primary) + { + RedrawWindow(g_ddraw.hwnd, NULL, NULL, RDW_INVALIDATE | RDW_ALLCHILDREN); + } + if (!g_ddraw.render.run) break; diff --git a/src/render_ogl.c b/src/render_ogl.c index e5befb2..aae1d34 100644 --- a/src/render_ogl.c +++ b/src/render_ogl.c @@ -63,6 +63,10 @@ BOOL ogl_create() TRACE("| GL_SHADING_LANGUAGE_VERSION: %s\n", glGetString(GL_SHADING_LANGUAGE_VERSION)); TRACE("+------------------------------------------------\n"); +#ifdef _DEBUG + while (glGetError() != GL_NO_ERROR); /* Ignore errors from glGetString */ +#endif + GL_CHECK(g_ogl.context = ogl_create_core_context(g_ogl.hdc)); } else @@ -90,7 +94,7 @@ BOOL ogl_create() DWORD WINAPI ogl_render_main(void) { - //Sleep(250); + Sleep(250); g_ogl.got_error = g_ogl.use_opengl = FALSE; GLenum err = GL_NO_ERROR; BOOL made_current = FALSE; @@ -107,6 +111,8 @@ DWORD WINAPI ogl_render_main(void) { GL_CHECK(oglu_init()); + g_ogl.got_error = g_ogl.got_error || (err = glGetError()) != GL_NO_ERROR; + BOOL got_swap_ctrl; GL_CHECK(got_swap_ctrl = oglu_ext_exists("WGL_EXT_swap_control", g_ogl.hdc)); @@ -120,9 +126,11 @@ DWORD WINAPI ogl_render_main(void) GL_CHECK(ogl_init_shader1_program()); GL_CHECK(ogl_init_shader2_program()); - //GL_CHECK(g_ogl.got_error = g_ogl.got_error || !ogl_texture_upload_test()); - //GL_CHECK(g_ogl.got_error = g_ogl.got_error || !ogl_shader_test()); g_ogl.got_error = g_ogl.got_error || (err = glGetError()) != GL_NO_ERROR; + GL_CHECK(g_ogl.got_error = g_ogl.got_error || !ogl_texture_upload_test()); + GL_CHECK(g_ogl.got_error = g_ogl.got_error || !ogl_shader_test()); + g_ogl.got_error = g_ogl.got_error || (err = glGetError()) != GL_NO_ERROR; + g_ogl.use_opengl = (g_ogl.main_program || g_ddraw.bpp == 16 || g_ddraw.bpp == 32) && !g_ogl.got_error; GL_CHECK(ogl_render()); @@ -240,6 +248,15 @@ static void ogl_build_programs() _snprintf(shader_path, sizeof(shader_path) - 1, "%s%s", g_config.dll_path, g_config.shader); } + /* Hack for Intel HD 4000 driver bug - force default shader */ + + if (_stricmp(g_oglu_version_long, "4.0.0 - Build 10.18.10.4252") == 0 || + _stricmp(g_oglu_version_long, "4.0.0 - Build 10.18.10.5161") == 0) + { + //shader_path[0] = 0; + //g_config.shader[0] = 0; + } + /* detect common upscaling shaders and disable them if no upscaling is required */ BOOL is_upscaler = @@ -257,7 +274,9 @@ static void ogl_build_programs() { g_ogl.shader1_program = oglu_build_program_from_file(shader_path, core_profile); - if (g_ogl.shader1_program && strstr(g_config.shader, "xbrz-freescale-multipass.glsl") != NULL) + if (g_ogl.shader1_program && + (strstr(g_config.shader, "xbrz-freescale-multipass.glsl") != NULL || + strstr(g_config.shader, "-pass1scale") != NULL)) { g_ogl.shader2_upscale = TRUE; } @@ -586,8 +605,10 @@ static void ogl_init_shader1_program() glUseProgram(g_ogl.shader1_program); GLint vertex_coord_attr_loc = glGetAttribLocation(g_ogl.shader1_program, "VertexCoord"); + if (vertex_coord_attr_loc == -1) // dosbox staging + vertex_coord_attr_loc = glGetAttribLocation(g_ogl.shader1_program, "a_position"); + g_ogl.shader1_tex_coord_attr_loc = glGetAttribLocation(g_ogl.shader1_program, "TexCoord"); - g_ogl.shader1_frame_count_uni_loc = glGetUniformLocation(g_ogl.shader1_program, "FrameCount"); glGenBuffers(3, g_ogl.shader1_vbos); @@ -644,10 +665,13 @@ static void ogl_init_shader1_program() glEnableVertexAttribArray(vertex_coord_attr_loc); glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindBuffer(GL_ARRAY_BUFFER, g_ogl.shader1_vbos[1]); - glVertexAttribPointer(g_ogl.shader1_tex_coord_attr_loc, 2, GL_FLOAT, GL_FALSE, 0, NULL); - glEnableVertexAttribArray(g_ogl.shader1_tex_coord_attr_loc); - glBindBuffer(GL_ARRAY_BUFFER, 0); + if (g_ogl.shader1_tex_coord_attr_loc != -1) + { + glBindBuffer(GL_ARRAY_BUFFER, g_ogl.shader1_vbos[1]); + glVertexAttribPointer(g_ogl.shader1_tex_coord_attr_loc, 2, GL_FLOAT, GL_FALSE, 0, NULL); + glEnableVertexAttribArray(g_ogl.shader1_tex_coord_attr_loc); + glBindBuffer(GL_ARRAY_BUFFER, 0); + } glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_ogl.shader1_vbos[2]); static const GLushort indices[] = @@ -669,24 +693,44 @@ static void ogl_init_shader1_program() output_size[1] = (float)g_ddraw.render.viewport.height; GLint loc = glGetUniformLocation(g_ogl.shader1_program, "OutputSize"); + if (loc == -1) + loc = glGetUniformLocation(g_ogl.shader1_program, "rubyOutputSize"); + if (loc != -1) glUniform2fv(loc, 1, output_size); + loc = glGetUniformLocation(g_ogl.shader1_program, "TextureSize"); + if (loc == -1) + loc = glGetUniformLocation(g_ogl.shader1_program, "rubyTextureSize"); + if (loc != -1) glUniform2fv(loc, 1, texture_size); + loc = glGetUniformLocation(g_ogl.shader1_program, "InputSize"); + if (loc == -1) + loc = glGetUniformLocation(g_ogl.shader1_program, "rubyInputSize"); + if (loc != -1) glUniform2fv(loc, 1, input_size); + + loc = glGetUniformLocation(g_ogl.shader1_program, "Texture"); + if (loc == -1) + loc = glGetUniformLocation(g_ogl.shader1_program, "rubyTexture"); + + if (loc != -1) + glUniform1i(loc, 0); + + loc = glGetUniformLocation(g_ogl.shader1_program, "FrameDirection"); if (loc != -1) glUniform1i(loc, 1); - loc = glGetUniformLocation(g_ogl.shader1_program, "Texture"); - if (loc != -1) - glUniform1i(loc, 0); + g_ogl.shader1_frame_count_uni_loc = glGetUniformLocation(g_ogl.shader1_program, "FrameCount"); + if (g_ogl.shader1_frame_count_uni_loc == -1) + g_ogl.shader1_frame_count_uni_loc = glGetUniformLocation(g_ogl.shader1_program, "rubyFrameCount"); const float mvp_matrix[16] = { 1,0,0,0, @@ -694,7 +738,10 @@ static void ogl_init_shader1_program() 0,0,1,0, 0,0,0,1, }; - glUniformMatrix4fv(glGetUniformLocation(g_ogl.shader1_program, "MVPMatrix"), 1, GL_FALSE, mvp_matrix); + + loc = glGetUniformLocation(g_ogl.shader1_program, "MVPMatrix"); + if (loc != -1) + glUniformMatrix4fv(loc, 1, GL_FALSE, mvp_matrix); glGenFramebuffers(FBO_COUNT, g_ogl.frame_buffer_id); glGenTextures(FBO_COUNT, g_ogl.frame_buffer_tex_id); @@ -800,8 +847,10 @@ static void ogl_init_shader2_program() glUseProgram(g_ogl.shader2_program); GLint vertex_coord_attr_loc = glGetAttribLocation(g_ogl.shader2_program, "VertexCoord"); + if (vertex_coord_attr_loc == -1) + vertex_coord_attr_loc = glGetAttribLocation(g_ogl.shader2_program, "a_position"); + g_ogl.shader2_tex_coord_attr_loc = glGetAttribLocation(g_ogl.shader2_program, "TexCoord"); - g_ogl.shader2_frame_count_uni_loc = glGetUniformLocation(g_ogl.shader2_program, "FrameCount"); glGenBuffers(3, g_ogl.shader2_vbos); @@ -836,10 +885,13 @@ static void ogl_init_shader2_program() glEnableVertexAttribArray(vertex_coord_attr_loc); glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindBuffer(GL_ARRAY_BUFFER, g_ogl.shader2_vbos[1]); - glVertexAttribPointer(g_ogl.shader2_tex_coord_attr_loc, 2, GL_FLOAT, GL_FALSE, 0, NULL); - glEnableVertexAttribArray(g_ogl.shader2_tex_coord_attr_loc); - glBindBuffer(GL_ARRAY_BUFFER, 0); + if (g_ogl.shader2_tex_coord_attr_loc != -1) + { + glBindBuffer(GL_ARRAY_BUFFER, g_ogl.shader2_vbos[1]); + glVertexAttribPointer(g_ogl.shader2_tex_coord_attr_loc, 2, GL_FLOAT, GL_FALSE, 0, NULL); + glEnableVertexAttribArray(g_ogl.shader2_tex_coord_attr_loc); + glBindBuffer(GL_ARRAY_BUFFER, 0); + } glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_ogl.shader2_vbos[2]); static const GLushort indices[] = @@ -861,25 +913,37 @@ static void ogl_init_shader2_program() output_size[1] = (float)g_ddraw.render.viewport.height; GLint loc = glGetUniformLocation(g_ogl.shader2_program, "OutputSize"); + if (loc == -1) + loc = glGetUniformLocation(g_ogl.shader2_program, "rubyOutputSize"); + if (loc != -1) glUniform2fv(loc, 1, output_size); + loc = glGetUniformLocation(g_ogl.shader2_program, "TextureSize"); + if (loc == -1) + loc = glGetUniformLocation(g_ogl.shader2_program, "rubyTextureSize"); + if (loc != -1) glUniform2fv(loc, 1, texture_size); + loc = glGetUniformLocation(g_ogl.shader2_program, "InputSize"); + if (loc == -1) + loc = glGetUniformLocation(g_ogl.shader2_program, "rubyInputSize"); + if (loc != -1) glUniform2fv(loc, 1, input_size); - loc = glGetUniformLocation(g_ogl.shader2_program, "FrameDirection"); - if (loc != -1) - glUniform1i(loc, 1); loc = glGetUniformLocation(g_ogl.shader2_program, "Texture"); + if (loc == -1) + loc = glGetUniformLocation(g_ogl.shader2_program, "rubyTexture"); + if (loc != -1) glUniform1i(loc, 0); + loc = glGetUniformLocation(g_ogl.shader2_program, "PassPrev2Texture"); if (loc != -1) glUniform1i(loc, 1); @@ -888,13 +952,24 @@ static void ogl_init_shader2_program() if (loc != -1) glUniform2fv(loc, 1, texture_size); + loc = glGetUniformLocation(g_ogl.shader2_program, "FrameDirection"); + if (loc != -1) + glUniform1i(loc, 1); + + g_ogl.shader2_frame_count_uni_loc = glGetUniformLocation(g_ogl.shader2_program, "FrameCount"); + if (g_ogl.shader2_frame_count_uni_loc == -1) + g_ogl.shader2_frame_count_uni_loc = glGetUniformLocation(g_ogl.shader2_program, "rubyFrameCount"); + const float mvp_matrix[16] = { 1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1, }; - glUniformMatrix4fv(glGetUniformLocation(g_ogl.shader2_program, "MVPMatrix"), 1, GL_FALSE, mvp_matrix); + + loc = glGetUniformLocation(g_ogl.shader2_program, "MVPMatrix"); + if (loc != -1) + glUniformMatrix4fv(loc, 1, GL_FALSE, mvp_matrix); } static void ogl_render() @@ -915,6 +990,11 @@ static void ogl_render() { glEnable(GL_TEXTURE_2D); } + else // 8 bpp only works with a shader (opengl 2.0 or above) + { + g_ogl.use_opengl = FALSE; + return; + } DWORD timeout = g_config.minfps > 0 ? g_ddraw.minfps_tick_len : INFINITE; @@ -922,9 +1002,6 @@ static void ogl_render() (g_config.minfps < 0 || WaitForSingleObject(g_ddraw.render.sem, timeout) != WAIT_FAILED) && g_ddraw.render.run) { - if (InterlockedDecrement(&g_ddraw.zoom.frame_skip) > 0) - continue; - #if _DEBUG dbg_draw_frame_info_start(); #endif @@ -1033,7 +1110,6 @@ static void ogl_render() if (g_config.fixchilds) { g_ddraw.child_window_exists = FALSE; - InterlockedExchangePointer((void*)&g_ddraw.video_window_hwnd, NULL); EnumChildWindows(g_ddraw.hwnd, util_enum_child_proc, (LPARAM)g_ddraw.primary); if (g_ddraw.render.width != g_ddraw.width || g_ddraw.render.height != g_ddraw.height) @@ -1085,8 +1161,11 @@ static void ogl_render() 0.0f, g_ogl.scale_h, }; glBufferData(GL_ARRAY_BUFFER, sizeof(tex_coord), tex_coord, GL_STATIC_DRAW); - glVertexAttribPointer(g_ogl.shader2_tex_coord_attr_loc, 2, GL_FLOAT, GL_FALSE, 0, NULL); - glEnableVertexAttribArray(g_ogl.shader2_tex_coord_attr_loc); + if (g_ogl.shader2_tex_coord_attr_loc != -1) + { + glVertexAttribPointer(g_ogl.shader2_tex_coord_attr_loc, 2, GL_FLOAT, GL_FALSE, 0, NULL); + glEnableVertexAttribArray(g_ogl.shader2_tex_coord_attr_loc); + } glBindBuffer(GL_ARRAY_BUFFER, 0); glBindVertexArray(0); } @@ -1101,8 +1180,11 @@ static void ogl_render() g_ogl.scale_w, 0.0f, }; glBufferData(GL_ARRAY_BUFFER, sizeof(tex_coord), tex_coord, GL_STATIC_DRAW); - glVertexAttribPointer(g_ogl.shader1_tex_coord_attr_loc, 2, GL_FLOAT, GL_FALSE, 0, NULL); - glEnableVertexAttribArray(g_ogl.shader1_tex_coord_attr_loc); + if (g_ogl.shader1_tex_coord_attr_loc != -1) + { + glVertexAttribPointer(g_ogl.shader1_tex_coord_attr_loc, 2, GL_FLOAT, GL_FALSE, 0, NULL); + glEnableVertexAttribArray(g_ogl.shader1_tex_coord_attr_loc); + } glBindBuffer(GL_ARRAY_BUFFER, 0); glBindVertexArray(0); } @@ -1117,8 +1199,11 @@ static void ogl_render() 0.0f, g_ogl.scale_h, }; glBufferData(GL_ARRAY_BUFFER, sizeof(tex_coord), tex_coord, GL_STATIC_DRAW); - glVertexAttribPointer(g_ogl.shader1_tex_coord_attr_loc, 2, GL_FLOAT, GL_FALSE, 0, NULL); - glEnableVertexAttribArray(g_ogl.shader1_tex_coord_attr_loc); + if (g_ogl.shader1_tex_coord_attr_loc != -1) + { + glVertexAttribPointer(g_ogl.shader1_tex_coord_attr_loc, 2, GL_FLOAT, GL_FALSE, 0, NULL); + glEnableVertexAttribArray(g_ogl.shader1_tex_coord_attr_loc); + } glBindBuffer(GL_ARRAY_BUFFER, 0); glBindVertexArray(0); } @@ -1140,7 +1225,9 @@ static void ogl_render() } } - glActiveTexture(GL_TEXTURE0); + if (glActiveTexture) + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, g_ogl.surface_tex_ids[tex_index]); if (g_ddraw.bpp == 8) @@ -1292,6 +1379,12 @@ static void ogl_render() SwapBuffers(g_ogl.hdc); + /* Force redraw for GDI games (ClueFinders) */ + if (!g_ddraw.primary) + { + RedrawWindow(g_ddraw.hwnd, NULL, NULL, RDW_INVALIDATE | RDW_ALLCHILDREN); + } + if (!g_ddraw.render.run) break; @@ -1549,13 +1642,16 @@ static BOOL ogl_shader_test() glBindTexture(GL_TEXTURE_2D, fbo_tex_id); glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, surface_tex); - int i; - for (i = 0; i < g_ogl.surface_tex_height * g_ogl.surface_tex_width; i++) + if (glGetError() == GL_NO_ERROR) { - if (surface_tex[i] != 0x80808080) + int i; + for (i = 0; i < g_ogl.surface_tex_height * g_ogl.surface_tex_width; i++) { - result = FALSE; - break; + if (surface_tex[i] != 0x80808080) + { + result = FALSE; + break; + } } } } @@ -1570,6 +1666,8 @@ static BOOL ogl_shader_test() glBindFramebuffer(GL_FRAMEBUFFER, 0); } + while (glGetError() != GL_NO_ERROR); + HeapFree(GetProcessHeap(), 0, surface_tex); return result; } diff --git a/src/screenshot.c b/src/screenshot.c index d76105e..063955b 100644 --- a/src/screenshot.c +++ b/src/screenshot.c @@ -153,6 +153,9 @@ BOOL ss_take_screenshot(IDirectDrawSurfaceImpl* src) strftime(str_time, sizeof(str_time), "%Y-%m-%d_%H-%M-%S", localtime(&t)); _snprintf(filename, sizeof(filename) - 1, "%s%s_%s.png", g_config.screenshot_dir, title, str_time); + if (FILE_EXISTS(filename)) + return FALSE; + if (src->bpp == 8 && src->palette) { if (!ss_screenshot_8bit(filename, src)) diff --git a/src/utils.c b/src/utils.c index 16bdd37..fafd4ed 100644 --- a/src/utils.c +++ b/src/utils.c @@ -1,6 +1,8 @@ #include #include +#include #include +#include #include "ddraw.h" #include "debug.h" #include "dd.h" @@ -10,6 +12,8 @@ #include "render_d3d9.h" #include "utils.h" #include "config.h" +#include "versionhelpers.h" +#include "delay_imports.h" /* @@ -69,6 +73,123 @@ HMODULE WINAPI util_enumerate_modules(_In_opt_ HMODULE hModuleLast) return NULL; } +void util_set_process_affinity() +{ +#if (_WIN32_WINNT >= _WIN32_WINNT_WINXP) + HANDLE snap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0); + if (snap == INVALID_HANDLE_VALUE) + return; + + THREADENTRY32 entry = { 0 }; + entry.dwSize = sizeof(THREADENTRY32); + + if (!Thread32First(snap, &entry)) + { + CloseHandle(snap); + return; + } + + do + { + if (entry.th32OwnerProcessID == GetCurrentProcessId()) + { + util_set_thread_affinity(entry.th32ThreadID); + } + } while (Thread32Next(snap, &entry)); + + CloseHandle(snap); +#endif +} + +void util_set_thread_affinity(DWORD tid) +{ +#if (_WIN32_WINNT >= _WIN32_WINNT_WINXP) + HANDLE thread = OpenThread(THREAD_QUERY_INFORMATION | THREAD_SET_INFORMATION, FALSE, tid); + if (thread) + { + void* start = NULL; + NTSTATUS status = STATUS_PENDING; + + if (delay_NtQueryInformationThread) + { + status = + delay_NtQueryInformationThread(thread, ThreadQuerySetWin32StartAddress, &start, sizeof(start), NULL); + } + + if (status == STATUS_SUCCESS && start && delay_GetModuleHandleExA) + { + char game_exe_path[MAX_PATH] = { 0 }; + char game_dir[MAX_PATH] = { 0 }; + + if (GetModuleFileNameA(NULL, game_exe_path, sizeof(game_exe_path))) + { + _splitpath(game_exe_path, NULL, game_dir, NULL, NULL); + + char mod_path[MAX_PATH] = { 0 }; + char mod_dir[MAX_PATH] = { 0 }; + char mod_filename[MAX_PATH] = { 0 }; + HMODULE mod = NULL; + + if (delay_GetModuleHandleExA( + GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, start, &mod)) + { + if (GetModuleFileNameA(mod, mod_path, sizeof(mod_path))) + { + _splitpath(mod_path, NULL, mod_dir, mod_filename, NULL); + + if (_strnicmp(game_dir, mod_dir, strlen(game_dir)) == 0) // _strcmpi(mod_filename, "WINMM") == 0 + { + SetThreadAffinityMask(thread, 1); + } + } + } + } + } + else + { + SetThreadAffinityMask(thread, 1); + } + + CloseHandle(thread); + } +#endif +} + +void util_pull_messages() +{ + if (g_config.fix_not_responding && + g_ddraw.hwnd && + g_ddraw.last_msg_pull_tick + 1000 < timeGetTime() && + GetCurrentThreadId() == g_ddraw.gui_thread_id && + !IsWine()) + { + /* workaround for "Not Responding" window problem */ + //g_ddraw.last_msg_pull_tick = timeGetTime(); + MSG msg; + if (real_PeekMessageA(&msg, g_ddraw.hwnd, 0, 0, PM_REMOVE)) + { + TranslateMessage(&msg); + DispatchMessageA(&msg); + } + } +} + +DWORD util_get_timestamp(HMODULE mod) +{ + if (!mod || mod == INVALID_HANDLE_VALUE) + return 0; + + PIMAGE_DOS_HEADER dos_header = (PIMAGE_DOS_HEADER)mod; + if (dos_header->e_magic != IMAGE_DOS_SIGNATURE) + return 0; + + PIMAGE_NT_HEADERS nt_headers = (PIMAGE_NT_HEADERS)((DWORD)dos_header + (DWORD)dos_header->e_lfanew); + if (nt_headers->Signature != IMAGE_NT_SIGNATURE) + return 0; + + return nt_headers->FileHeader.TimeDateStamp; +} + FARPROC util_get_iat_proc(HMODULE mod, char* module_name, char* function_name) { if (!mod || mod == INVALID_HANDLE_VALUE) @@ -80,17 +201,15 @@ FARPROC util_get_iat_proc(HMODULE mod, char* module_name, char* function_name) if (dos_header->e_magic != IMAGE_DOS_SIGNATURE) return NULL; - PIMAGE_NT_HEADERS nt_headers = (PIMAGE_NT_HEADERS)((DWORD)dos_header + (DWORD)dos_header->e_lfanew); + PIMAGE_NT_HEADERS nt_headers = (PIMAGE_NT_HEADERS)((DWORD)mod + (DWORD)dos_header->e_lfanew); if (nt_headers->Signature != IMAGE_NT_SIGNATURE) return NULL; DWORD import_desc_rva = nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress; - DWORD import_desc_size = nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size; - - if (import_desc_rva == 0 || import_desc_size == 0) + if (!import_desc_rva) return NULL; - PIMAGE_IMPORT_DESCRIPTOR import_desc = (PIMAGE_IMPORT_DESCRIPTOR)((DWORD)dos_header + import_desc_rva); + PIMAGE_IMPORT_DESCRIPTOR import_desc = (PIMAGE_IMPORT_DESCRIPTOR)((DWORD)mod + import_desc_rva); while (import_desc->FirstThunk) { @@ -100,12 +219,12 @@ FARPROC util_get_iat_proc(HMODULE mod, char* module_name, char* function_name) continue; } - char* imp_module_name = (char*)((DWORD)dos_header + import_desc->Name); + char* imp_module_name = (char*)((DWORD)mod + import_desc->Name); if (_stricmp(imp_module_name, module_name) == 0) { - PIMAGE_THUNK_DATA first_thunk = (void*)((DWORD)dos_header + import_desc->FirstThunk); - PIMAGE_THUNK_DATA o_first_thunk = (void*)((DWORD)dos_header + import_desc->OriginalFirstThunk); + PIMAGE_THUNK_DATA first_thunk = (void*)((DWORD)mod + import_desc->FirstThunk); + PIMAGE_THUNK_DATA o_first_thunk = (void*)((DWORD)mod + import_desc->OriginalFirstThunk); while (first_thunk->u1.Function) { @@ -116,7 +235,7 @@ FARPROC util_get_iat_proc(HMODULE mod, char* module_name, char* function_name) continue; } - PIMAGE_IMPORT_BY_NAME import = (void*)((DWORD)dos_header + o_first_thunk->u1.AddressOfData); + PIMAGE_IMPORT_BY_NAME import = (void*)((DWORD)mod + o_first_thunk->u1.AddressOfData); if ((o_first_thunk->u1.Ordinal & IMAGE_ORDINAL_FLAG) == 0) { @@ -148,10 +267,7 @@ FARPROC util_get_iat_proc(HMODULE mod, char* module_name, char* function_name) BOOL util_caller_is_ddraw_wrapper(void* return_address) { - BOOL (WINAPI *getModuleHandleExA)(DWORD, LPCSTR, HMODULE*) = - (void*)real_GetProcAddress(real_LoadLibraryA("Kernel32.dll"), "GetModuleHandleExA"); - - if (!getModuleHandleExA) + if (!delay_GetModuleHandleExA) return FALSE; void* directDrawCreate = (void*)util_get_iat_proc(GetModuleHandleA(NULL), "ddraw.dll", "DirectDrawCreate"); @@ -165,9 +281,9 @@ BOOL util_caller_is_ddraw_wrapper(void* return_address) HMODULE D3dHook_dll = GetModuleHandleA("D3dHook.dll"); if (D3dHook_dll) { - if ((getModuleHandleExA(flags, return_address, &mod) && mod == D3dHook_dll) || - (getModuleHandleExA(flags, directDrawCreate, &mod) && mod == D3dHook_dll) || - (getModuleHandleExA(flags, directDrawCreateEx, &mod) && mod == D3dHook_dll)) + if ((delay_GetModuleHandleExA(flags, return_address, &mod) && mod == D3dHook_dll) || + (delay_GetModuleHandleExA(flags, directDrawCreate, &mod) && mod == D3dHook_dll) || + (delay_GetModuleHandleExA(flags, directDrawCreateEx, &mod) && mod == D3dHook_dll)) { MessageBoxA( NULL, @@ -183,9 +299,9 @@ BOOL util_caller_is_ddraw_wrapper(void* return_address) HMODULE wndmode_dll = GetModuleHandleA("wndmode.dll"); if (wndmode_dll) { - if ((getModuleHandleExA(flags, return_address, &mod) && mod == wndmode_dll) || - (getModuleHandleExA(flags, directDrawCreate, &mod) && mod == wndmode_dll) || - (getModuleHandleExA(flags, directDrawCreateEx, &mod) && mod == wndmode_dll)) + if ((delay_GetModuleHandleExA(flags, return_address, &mod) && mod == wndmode_dll) || + (delay_GetModuleHandleExA(flags, directDrawCreate, &mod) && mod == wndmode_dll) || + (delay_GetModuleHandleExA(flags, directDrawCreateEx, &mod) && mod == wndmode_dll)) { MessageBoxA( NULL, @@ -201,9 +317,9 @@ BOOL util_caller_is_ddraw_wrapper(void* return_address) HMODULE windmode_dll = GetModuleHandleA("windmode.dll"); if (windmode_dll) { - if ((getModuleHandleExA(flags, return_address, &mod) && mod == windmode_dll) || - (getModuleHandleExA(flags, directDrawCreate, &mod) && mod == windmode_dll) || - (getModuleHandleExA(flags, directDrawCreateEx, &mod) && mod == windmode_dll)) + if ((delay_GetModuleHandleExA(flags, return_address, &mod) && mod == windmode_dll) || + (delay_GetModuleHandleExA(flags, directDrawCreate, &mod) && mod == windmode_dll) || + (delay_GetModuleHandleExA(flags, directDrawCreateEx, &mod) && mod == windmode_dll)) { MessageBoxA( NULL, @@ -219,9 +335,9 @@ BOOL util_caller_is_ddraw_wrapper(void* return_address) HMODULE dxwnd_dll = GetModuleHandleA("dxwnd.dll"); if (dxwnd_dll) { - if ((getModuleHandleExA(flags, return_address, &mod) && mod == dxwnd_dll) || - (getModuleHandleExA(flags, directDrawCreate, &mod) && mod == dxwnd_dll) || - (getModuleHandleExA(flags, directDrawCreateEx, &mod) && mod == dxwnd_dll)) + if ((delay_GetModuleHandleExA(flags, return_address, &mod) && mod == dxwnd_dll) || + (delay_GetModuleHandleExA(flags, directDrawCreate, &mod) && mod == dxwnd_dll) || + (delay_GetModuleHandleExA(flags, directDrawCreateEx, &mod) && mod == dxwnd_dll)) { MessageBoxA( NULL, @@ -237,9 +353,9 @@ BOOL util_caller_is_ddraw_wrapper(void* return_address) HMODULE age_dll = GetModuleHandleA("age.dll"); if (age_dll) { - if ((getModuleHandleExA(flags, return_address, &mod) && mod == age_dll) || - (getModuleHandleExA(flags, directDrawCreate, &mod) && mod == age_dll) || - (getModuleHandleExA(flags, directDrawCreateEx, &mod) && mod == age_dll)) + if ((delay_GetModuleHandleExA(flags, return_address, &mod) && mod == age_dll) || + (delay_GetModuleHandleExA(flags, directDrawCreate, &mod) && mod == age_dll) || + (delay_GetModuleHandleExA(flags, directDrawCreateEx, &mod) && mod == age_dll)) { HKEY hkey; LONG status = @@ -573,6 +689,13 @@ BOOL util_get_lowest_resolution( void util_toggle_maximize() { + if (!g_config.resizable || !g_config.windowed || g_config.fullscreen || !g_ddraw.width) + return; + + /* Do not allow cnc-ddraw maximize while macOS maximize is active */ + if (IsMacOS() && !g_config.window_rect.left && !g_config.window_rect.top) + return; + RECT client_rc; RECT dst_rc; @@ -622,9 +745,23 @@ void util_toggle_maximize() int w = dst_rc.right - dst_rc.left; int h = dst_rc.bottom - dst_rc.top; - double dst_ar = (double)g_ddraw.height / g_ddraw.width; + double dst_ar; double src_ar = (double)h / w; + if (g_config.aspect_ratio[0]) + { + char* e = &g_config.aspect_ratio[0]; + + DWORD cx = strtoul(e, &e, 0); + DWORD cy = strtoul(e + 1, &e, 0); + + dst_ar = (double)cy / cx; + } + else + { + dst_ar = (double)g_ddraw.height / g_ddraw.width; + } + dst_rc.top = 0; dst_rc.left = 0; dst_rc.right = w; @@ -660,7 +797,11 @@ void util_toggle_maximize() void util_toggle_fullscreen() { /* Disable ALT+ENTER on battle.net and Infantry Online Zone List Window */ - if (g_ddraw.bnet_active || (g_config.infantryhack && GetMenu(g_ddraw.hwnd))) + if (g_ddraw.bnet_active || !g_ddraw.width || (g_config.infantryhack && GetMenu(g_ddraw.hwnd))) + return; + + /* Do not allow ALT+ENTER while macOS maximize is active */ + if (IsMacOS() && !g_config.window_rect.left && !g_config.window_rect.top) return; if (g_config.toggle_borderless && g_config.windowed) @@ -847,6 +988,9 @@ BOOL CALLBACK util_enum_child_proc(HWND hwnd, LPARAM lparam) return TRUE; if (g_config.fixchilds == FIX_CHILDS_DETECT_HIDE || + g_config.fixchilds == FIX_CHILDS_DETECT_HIDE_NOSCALE || + strcmp(class_name, "Cc2EditClassTh") == 0 || + strcmp(class_name, "msctls_statusbar32") == 0 || strcmp(class_name, "VideoRenderer") == 0 || strcmp(class_name, "MCIQTZ_Window") == 0 || strcmp(class_name, "MCIAVI") == 0 || @@ -854,9 +998,9 @@ BOOL CALLBACK util_enum_child_proc(HWND hwnd, LPARAM lparam) strcmp(class_name, "MCIWndClass") == 0 || strcmp(class_name, "AVI Window") == 0) { - if (g_config.fixchilds != FIX_CHILDS_DETECT_HIDE) + if (g_config.fixchilds == FIX_CHILDS_DETECT_HIDE_NOSCALE) { - InterlockedExchangePointer((void*)&g_ddraw.video_window_hwnd, hwnd); + g_ddraw.got_child_windows = g_ddraw.child_window_exists = TRUE; } if (!(exstyle & WS_EX_TRANSPARENT)) diff --git a/src/versionhelpers.c b/src/versionhelpers.c index e422e90..f9f35c2 100644 --- a/src/versionhelpers.c +++ b/src/versionhelpers.c @@ -1,43 +1,30 @@ #include #include "versionhelpers.h" +#include "delay_imports.h" -typedef NTSTATUS(WINAPI* RTLVERIFYVERSIONINFOPROC)(PRTL_OSVERSIONINFOEXW, ULONG, ULONGLONG); -typedef const char* (CDECL* WINE_GET_VERSIONPROC)(); -typedef void (CDECL* WINE_GET_HOST_VERSIONPROC)(const char** sysname, const char** release); - -static RTLVERIFYVERSIONINFOPROC RtlVerifyVersionInfo; -static WINE_GET_VERSIONPROC wine_get_version; -static WINE_GET_HOST_VERSIONPROC wine_get_host_version; - -/* GetProcAddress is rather slow so we use a function to initialize it once on startup */ -void verhelp_init() -{ - HMODULE mod = GetModuleHandleA("ntdll.dll"); - if (mod) - { - RtlVerifyVersionInfo = (RTLVERIFYVERSIONINFOPROC)GetProcAddress(mod, "RtlVerifyVersionInfo"); - wine_get_version = (WINE_GET_VERSIONPROC)GetProcAddress(mod, "wine_get_version"); - wine_get_host_version = (WINE_GET_HOST_VERSIONPROC)GetProcAddress(mod, "wine_get_host_version"); - } -} BOOL verhelp_verify_version(PRTL_OSVERSIONINFOEXW versionInfo, ULONG typeMask, ULONGLONG conditionMask) { - return RtlVerifyVersionInfo ? - RtlVerifyVersionInfo(versionInfo, typeMask, conditionMask) == 0 : + return delay_RtlVerifyVersionInfo ? + delay_RtlVerifyVersionInfo(versionInfo, typeMask, conditionMask) == 0 : VerifyVersionInfoW(versionInfo, typeMask, conditionMask); } +ULONGLONG verhelp_set_mask(ULONGLONG ConditionMask, DWORD TypeMask, BYTE Condition) +{ + return delay_VerSetConditionMask ? delay_VerSetConditionMask(ConditionMask, TypeMask, Condition) : 0; +} + const char* verhelp_wine_get_version() { - return wine_get_version ? wine_get_version() : NULL; + return delay_wine_get_version ? delay_wine_get_version() : NULL; } void verhelp_wine_get_host_version(const char** sysname, const char** release) { - if (wine_get_host_version) + if (delay_wine_get_host_version) { - wine_get_host_version(sysname, release); + delay_wine_get_host_version(sysname, release); return; } diff --git a/src/winapi_hooks.c b/src/winapi_hooks.c index 7e5a688..33655c1 100644 --- a/src/winapi_hooks.c +++ b/src/winapi_hooks.c @@ -1,6 +1,7 @@ #include #include #include +#include #include "debug.h" #include "config.h" #include "dd.h" @@ -9,6 +10,7 @@ #include "config.h" #include "utils.h" #include "mouse.h" +#include "keyboard.h" #include "wndproc.h" #include "render_gdi.h" #include "render_d3d9.h" @@ -19,6 +21,8 @@ #include "dllmain.h" #include "hook.h" #include "directinput.h" +#include "ddpalette.h" +#include "palette.h" BOOL WINAPI fake_GetCursorPos(LPPOINT lpPoint) @@ -307,13 +311,29 @@ BOOL WINAPI fake_GetCursorInfo(PCURSORINFO pci) int WINAPI fake_GetSystemMetrics(int nIndex) { + DWORD width = 0; + DWORD height = 0; + if (g_ddraw.ref && g_ddraw.width) + { + width = g_ddraw.width; + height = g_ddraw.height; + } + else if (g_config.fake_mode[0]) + { + char* e = &g_config.fake_mode[0]; + + width = strtoul(e, &e, 0); + height = strtoul(e + 1, &e, 0); + } + + if (width) { if (nIndex == SM_CXSCREEN) - return g_ddraw.width; + return width; if (nIndex == SM_CYSCREEN) - return g_ddraw.height; + return height; } return real_GetSystemMetrics(nIndex); @@ -430,7 +450,7 @@ LRESULT WINAPI fake_SendMessageA(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lPar LONG WINAPI fake_SetWindowLongA(HWND hWnd, int nIndex, LONG dwNewLong) { - if (g_ddraw.ref && g_ddraw.hwnd == hWnd) + if (g_ddraw.ref && g_ddraw.hwnd && g_ddraw.hwnd == hWnd) { if (nIndex == GWL_STYLE) return 0; @@ -447,6 +467,17 @@ LONG WINAPI fake_SetWindowLongA(HWND hWnd, int nIndex, LONG dwNewLong) return real_SetWindowLongA(hWnd, nIndex, dwNewLong); } +LONG WINAPI fake_SetWindowLongW(HWND hWnd, int nIndex, LONG dwNewLong) +{ + if (g_ddraw.ref && g_ddraw.hwnd && g_ddraw.hwnd == hWnd) + { + if (nIndex == GWL_STYLE) + return 0; + } + + return real_SetWindowLongW(hWnd, nIndex, dwNewLong); +} + LONG WINAPI fake_GetWindowLongA(HWND hWnd, int nIndex) { if (g_ddraw.ref && g_ddraw.hwnd == hWnd) @@ -574,31 +605,63 @@ HHOOK WINAPI fake_SetWindowsHookExA(int idHook, HOOKPROC lpfn, HINSTANCE hmod, D dwThreadId, _ReturnAddress()); + dbg_dump_hook_type(idHook); + if (idHook == WH_KEYBOARD_LL && hmod && GetModuleHandle("AcGenral") == hmod) { return NULL; } - if (idHook == WH_MOUSE && lpfn && !hmod && !g_mouse_hook && g_config.fixmousehook) + if (idHook == WH_MOUSE && lpfn && !hmod && !g_mouse_hook && g_config.sirtech_hack) { g_mouse_proc = lpfn; return g_mouse_hook = real_SetWindowsHookExA(idHook, mouse_hook_proc, hmod, dwThreadId); } - return real_SetWindowsHookExA(idHook, lpfn, hmod, dwThreadId); + HHOOK result = real_SetWindowsHookExA(idHook, lpfn, hmod, dwThreadId); + + if (idHook == WH_KEYBOARD) + { + keyboard_hook_init(); + } + + return result; } -BOOL HandleMessage(LPMSG lpMsg, HWND hWnd, UINT wMsgFilterMin, UINT wMsgFilterMax) +void HandleMessage(LPMSG lpMsg, HWND hWnd, UINT wMsgFilterMin, UINT wMsgFilterMax, UINT wRemoveMsg) { - if (g_ddraw.ref && g_ddraw.width) + if (lpMsg && g_ddraw.ref && g_ddraw.hwnd && g_ddraw.width) { - switch (lpMsg->message) + if (!g_config.windowed || real_ScreenToClient(g_ddraw.hwnd, &lpMsg->pt)) + { + int x = max(lpMsg->pt.x - g_ddraw.mouse.x_adjust, 0); + int y = max(lpMsg->pt.y - g_ddraw.mouse.y_adjust, 0); + + if (g_config.adjmouse) + { + x = (DWORD)(roundf(x * g_ddraw.mouse.unscale_x)); + y = (DWORD)(roundf(y * g_ddraw.mouse.unscale_y)); + } + + lpMsg->pt.x = min(x, g_ddraw.width - 1); + lpMsg->pt.y = min(y, g_ddraw.height - 1); + } + else + { + lpMsg->pt.x = InterlockedExchangeAdd((LONG*)&g_ddraw.cursor.x, 0); + lpMsg->pt.y = InterlockedExchangeAdd((LONG*)&g_ddraw.cursor.y, 0); + } + + if (lpMsg->hwnd != g_ddraw.hwnd || !g_config.hook_peekmessage) + return; + + switch (LOWORD(lpMsg->message)) { case WM_LBUTTONUP: case WM_RBUTTONUP: case WM_MBUTTONUP: { - if (!g_config.devmode && !g_mouse_locked) + if (!g_config.devmode && !g_mouse_locked && (wRemoveMsg & PM_REMOVE)) { int x = GET_X_LPARAM(lpMsg->lParam); int y = GET_Y_LPARAM(lpMsg->lParam); @@ -621,7 +684,14 @@ BOOL HandleMessage(LPMSG lpMsg, HWND hWnd, UINT wMsgFilterMin, UINT wMsgFilterMa InterlockedExchange((LONG*)&g_ddraw.cursor.y, y); mouse_lock(); - //return FALSE; + + if (!wMsgFilterMin && + !wMsgFilterMax && + !(wRemoveMsg & (PM_QS_INPUT | PM_QS_PAINT | PM_QS_POSTMESSAGE | PM_QS_SENDMESSAGE))) + { + lpMsg->message = WM_NULL; + break; + } } /* fall through for lParam */ } @@ -641,11 +711,16 @@ BOOL HandleMessage(LPMSG lpMsg, HWND hWnd, UINT wMsgFilterMin, UINT wMsgFilterMa { if (!g_config.devmode && !g_mouse_locked) { - // Does not work with 'New Robinson' - //return FALSE; + if (!wMsgFilterMin && + !wMsgFilterMax && + !(wRemoveMsg & (PM_QS_INPUT | PM_QS_PAINT | PM_QS_POSTMESSAGE | PM_QS_SENDMESSAGE))) + { + lpMsg->message = WM_NULL; + break; + } } - if (lpMsg->message == WM_MOUSEWHEEL) + if (LOWORD(lpMsg->message) == WM_MOUSEWHEEL) { POINT pt = { GET_X_LPARAM(lpMsg->lParam), GET_Y_LPARAM(lpMsg->lParam) }; real_ScreenToClient(g_ddraw.hwnd, &pt); @@ -685,43 +760,19 @@ BOOL HandleMessage(LPMSG lpMsg, HWND hWnd, UINT wMsgFilterMin, UINT wMsgFilterMa break; } - } } - - return TRUE; } BOOL WINAPI fake_GetMessageA(LPMSG lpMsg, HWND hWnd, UINT wMsgFilterMin, UINT wMsgFilterMax) { + if (g_ddraw.ref && (!hWnd || hWnd == g_ddraw.hwnd)) + g_ddraw.last_msg_pull_tick = timeGetTime(); + BOOL result = real_GetMessageA(lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax); - - if (result && lpMsg && g_ddraw.ref && g_ddraw.hwnd && g_ddraw.width && !g_config.fixmousehook) + if (result) { - if (!g_config.windowed || real_ScreenToClient(g_ddraw.hwnd, &lpMsg->pt)) - { - int x = max(lpMsg->pt.x - g_ddraw.mouse.x_adjust, 0); - int y = max(lpMsg->pt.y - g_ddraw.mouse.y_adjust, 0); - - if (g_config.adjmouse) - { - x = (DWORD)(roundf(x * g_ddraw.mouse.unscale_x)); - y = (DWORD)(roundf(y * g_ddraw.mouse.unscale_y)); - } - - lpMsg->pt.x = min(x, g_ddraw.width - 1); - lpMsg->pt.y = min(y, g_ddraw.height - 1); - } - else - { - lpMsg->pt.x = InterlockedExchangeAdd((LONG*)&g_ddraw.cursor.x, 0); - lpMsg->pt.y = InterlockedExchangeAdd((LONG*)&g_ddraw.cursor.y, 0); - } - - if (g_config.hook_getmessage) - { - HandleMessage(lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax); - } + HandleMessage(lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax, PM_REMOVE); } return result; @@ -729,34 +780,28 @@ BOOL WINAPI fake_GetMessageA(LPMSG lpMsg, HWND hWnd, UINT wMsgFilterMin, UINT wM BOOL WINAPI fake_PeekMessageA(LPMSG lpMsg, HWND hWnd, UINT wMsgFilterMin, UINT wMsgFilterMax, UINT wRemoveMsg) { - BOOL result = real_PeekMessageA(lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg); - - if (result && lpMsg && g_ddraw.ref && g_ddraw.hwnd && g_ddraw.width && !g_config.fixmousehook) + if (g_config.darkcolony_hack && !hWnd) { - if (!g_config.windowed || real_ScreenToClient(g_ddraw.hwnd, &lpMsg->pt)) - { - int x = max(lpMsg->pt.x - g_ddraw.mouse.x_adjust, 0); - int y = max(lpMsg->pt.y - g_ddraw.mouse.y_adjust, 0); + hWnd = g_ddraw.hwnd; - if (g_config.adjmouse) - { - x = (DWORD)(roundf(x * g_ddraw.mouse.unscale_x)); - y = (DWORD)(roundf(y * g_ddraw.mouse.unscale_y)); - } + MSG msg; + real_PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE); + } - lpMsg->pt.x = min(x, g_ddraw.width - 1); - lpMsg->pt.y = min(y, g_ddraw.height - 1); - } - else - { - lpMsg->pt.x = InterlockedExchangeAdd((LONG*)&g_ddraw.cursor.x, 0); - lpMsg->pt.y = InterlockedExchangeAdd((LONG*)&g_ddraw.cursor.y, 0); - } + if (g_config.limiter_type == LIMIT_PEEKMESSAGE && + g_ddraw.ticks_limiter.tick_length > 0 && + InterlockedExchange(&g_ddraw.render.screen_updated, FALSE)) + { + util_limit_game_ticks(); + } - if (g_config.hook_peekmessage) - { - HandleMessage(lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax); - } + if (g_ddraw.ref && (!hWnd || hWnd == g_ddraw.hwnd)) + g_ddraw.last_msg_pull_tick = timeGetTime(); + + BOOL result = real_PeekMessageA(lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg); + if (result) + { + HandleMessage(lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg); } return result; @@ -780,7 +825,7 @@ BOOL WINAPI fake_GetWindowPlacement(HWND hWnd, WINDOWPLACEMENT* lpwndpl) lpwndpl->rcNormalPosition.right = g_ddraw.width; lpwndpl->rcNormalPosition.top = 0; } - else + else if (!IsChild(g_ddraw.hwnd, hWnd) && !(real_GetWindowLongA(hWnd, GWL_STYLE) & WS_CHILD)) { real_MapWindowPoints(HWND_DESKTOP, g_ddraw.hwnd, (LPPOINT)&lpwndpl->rcNormalPosition, 2); } @@ -789,6 +834,17 @@ BOOL WINAPI fake_GetWindowPlacement(HWND hWnd, WINDOWPLACEMENT* lpwndpl) return result; } +BOOL WINAPI fake_SetWindowPlacement(HWND hWnd, const WINDOWPLACEMENT* lpwndpl) +{ + if (lpwndpl && g_ddraw.ref && g_ddraw.hwnd && hWnd == g_ddraw.hwnd) + { + if (lpwndpl->showCmd == SW_SHOWMAXIMIZED || lpwndpl->showCmd == SW_MAXIMIZE) + return TRUE; + } + + return real_SetWindowPlacement(hWnd, lpwndpl); +} + BOOL WINAPI fake_EnumDisplaySettingsA(LPCSTR lpszDeviceName, DWORD iModeNum, DEVMODEA* lpDevMode) { BOOL result = real_EnumDisplaySettingsA(lpszDeviceName, iModeNum, lpDevMode); @@ -819,47 +875,72 @@ BOOL WINAPI fake_EnumDisplaySettingsA(LPCSTR lpszDeviceName, DWORD iModeNum, DEV lpDevMode->dmDisplayFrequency = 60; } + if (result && !lpszDeviceName && lpDevMode && iModeNum != ENUM_CURRENT_SETTINGS) + { + //lpDevMode->dmBitsPerPel = 16; + } + return result; } -BOOL WINAPI fake_ValidateRect(HWND hWnd, const RECT* lpRect) +LRESULT WINAPI fake_DefWindowProcA(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) { - if (!g_ddraw.ref || !g_ddraw.width || !g_ddraw.hwnd || hWnd != g_ddraw.hwnd || !lpRect) - return real_ValidateRect(hWnd, lpRect); + if (g_ddraw.ref && g_ddraw.hwnd && g_ddraw.hwnd == hWnd) + { + if (Msg == WM_NCHITTEST) + return HTCLIENT; + } - RECT dst_rc; - - dst_rc.left = (LONG)(roundf(lpRect->left * g_ddraw.render.scale_w)); - dst_rc.top = (LONG)(roundf(lpRect->top * g_ddraw.render.scale_h)); - dst_rc.bottom = (LONG)(roundf(lpRect->bottom * g_ddraw.render.scale_h)); - dst_rc.right = (LONG)(roundf(lpRect->right * g_ddraw.render.scale_w)); - - OffsetRect( - &dst_rc, - g_ddraw.render.viewport.x, - g_ddraw.render.viewport.y); - - return real_ValidateRect(hWnd, &dst_rc); + return real_DefWindowProcA(hWnd, Msg, wParam, lParam); } -BOOL WINAPI fake_InvalidateRect(HWND hWnd, const RECT* lpRect, BOOL bErase) +HWND WINAPI fake_SetParent(HWND hWndChild, HWND hWndNewParent) { - if (!g_ddraw.ref || !g_ddraw.width || !g_ddraw.hwnd || hWnd != g_ddraw.hwnd || !lpRect) - return real_InvalidateRect(hWnd, lpRect, bErase); + if (g_ddraw.ref && g_ddraw.hwnd && g_ddraw.hwnd == hWndNewParent) + { + char class_name[MAX_PATH] = { 0 }; + GetClassNameA(hWndChild, class_name, sizeof(class_name) - 1); - RECT dst_rc; + if (strcmp(class_name, "VideoRenderer") == 0) + { + RECT rc_org; + fake_GetWindowRect(hWndChild, &rc_org); + + HWND result = real_SetParent(hWndChild, hWndNewParent); - dst_rc.left = (LONG)(roundf(lpRect->left * g_ddraw.render.scale_w)); - dst_rc.top = (LONG)(roundf(lpRect->top * g_ddraw.render.scale_h)); - dst_rc.bottom = (LONG)(roundf(lpRect->bottom * g_ddraw.render.scale_h)); - dst_rc.right = (LONG)(roundf(lpRect->right * g_ddraw.render.scale_w)); + real_MoveWindow( + hWndChild, + rc_org.left, + rc_org.top, + (rc_org.right - rc_org.left), + (rc_org.bottom - rc_org.top), + FALSE); - OffsetRect( - &dst_rc, - g_ddraw.render.viewport.x, - g_ddraw.render.viewport.y); + return result; + } + } - return real_InvalidateRect(hWnd, &dst_rc, bErase); + return real_SetParent(hWndChild, hWndNewParent); +} + +HDC WINAPI fake_BeginPaint(HWND hWnd, LPPAINTSTRUCT lpPaint) +{ + if (g_ddraw.ref && g_ddraw.width && g_ddraw.hwnd && g_ddraw.hwnd == hWnd && lpPaint) + { + HDC result = real_BeginPaint(hWnd, lpPaint); + + if (result) + { + lpPaint->rcPaint.left = 0; + lpPaint->rcPaint.top = 0; + lpPaint->rcPaint.right = g_ddraw.width; + lpPaint->rcPaint.bottom = g_ddraw.height; + } + + return result; + } + + return real_BeginPaint(hWnd, lpPaint); } SHORT WINAPI fake_GetKeyState(int nVirtKey) @@ -884,20 +965,81 @@ SHORT WINAPI fake_GetAsyncKeyState(int vKey) int WINAPI fake_GetDeviceCaps(HDC hdc, int index) { - if (g_ddraw.ref && - g_ddraw.bpp && - index == BITSPIXEL && - (g_config.hook != 2 || g_ddraw.renderer == gdi_render_main)) + DWORD bpp = 0; + DWORD width = 0; + DWORD height = 0; + + if (g_ddraw.ref && g_ddraw.bpp) { - return g_ddraw.bpp; + bpp = g_ddraw.bpp; + width = g_ddraw.width; + height = g_ddraw.height; } - + else if (g_config.fake_mode[0]) + { + char* e = &g_config.fake_mode[0]; + + width = strtoul(e, &e, 0); + height = strtoul(e + 1, &e, 0); + bpp = strtoul(e + 1, &e, 0); + } + + if (bpp && index == BITSPIXEL) + { + return bpp; + } + + if (bpp == 8) + { + if (index == RASTERCAPS) + { + return RC_PALETTE | real_GetDeviceCaps(hdc, index); + } + + if (index == SIZEPALETTE) + { + return 256; + } + + if (index == NUMCOLORS) + { + if (WindowFromDC(hdc) == GetDesktopWindow()) + { + return 20; + } + else + { + return 256; + } + } + } + + if (width && ((g_ddraw.hwnd && WindowFromDC(hdc) == g_ddraw.hwnd) || WindowFromDC(hdc) == GetDesktopWindow())) + { + if (index == HORZRES) + { + return width; + } + + if (index == VERTRES) + { + return height; + } + } + + return real_GetDeviceCaps(hdc, index); +} + +int WINAPI fake_GetDeviceCaps_system(HDC hdc, int index) +{ if (g_ddraw.ref && g_ddraw.bpp == 8 && - index == RASTERCAPS && - (g_config.hook != 2 || g_ddraw.renderer == gdi_render_main)) + ((g_ddraw.hwnd && WindowFromDC(hdc) == g_ddraw.hwnd) || WindowFromDC(hdc) == GetDesktopWindow())) { - return RC_PALETTE | real_GetDeviceCaps(hdc, index); + if (index == RASTERCAPS) + { + return RC_PALETTE | real_GetDeviceCaps(hdc, index); + } } return real_GetDeviceCaps(hdc, index); @@ -918,6 +1060,11 @@ BOOL WINAPI fake_StretchBlt( { HWND hwnd = WindowFromDC(hdcDest); + if (g_ddraw.ref && g_ddraw.hwnd && hwnd == g_ddraw.hwnd && !g_ddraw.primary) + { + InterlockedExchange(&g_ddraw.render.screen_updated, TRUE); + } + char class_name[MAX_PATH] = { 0 }; if (g_ddraw.ref && g_ddraw.hwnd && hwnd && hwnd != g_ddraw.hwnd) @@ -971,12 +1118,39 @@ BOOL WINAPI fake_StretchBlt( return result; } } - else if (g_ddraw.width > 0 && g_ddraw.render.hdc) + else if ( + g_ddraw.width > 0 && + g_ddraw.render.hdc && + (hwnd == g_ddraw.hwnd || + (real_GetWindowLongA(hwnd, GWL_EXSTYLE) & WS_EX_TRANSPARENT) || + strcmp(class_name, "AVIWnd32") == 0)) { + POINT pt = { 0 }; + real_MapWindowPoints(hwnd, g_ddraw.hwnd, &pt, 1); + + if (hwnd != g_ddraw.hwnd && strcmp(class_name, "AVIWnd32") == 0) + { + LONG exstyle = real_GetWindowLongA(hwnd, GWL_EXSTYLE); + if (!(exstyle & WS_EX_TRANSPARENT)) + { + real_SetWindowLongA(hwnd, GWL_EXSTYLE, exstyle | WS_EX_TRANSPARENT); + + real_SetWindowPos( + hwnd, + 0, + 0, + 0, + 0, + 0, + SWP_ASYNCWINDOWPOS | SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOOWNERZORDER + ); + } + } + return real_StretchBlt( hwnd == g_ddraw.hwnd ? hdcDest : g_ddraw.render.hdc, - (int)(roundf(xDest * g_ddraw.render.scale_w)) + g_ddraw.render.viewport.x, - (int)(roundf(yDest * g_ddraw.render.scale_h)) + g_ddraw.render.viewport.y, + (int)(roundf((xDest + pt.x) * g_ddraw.render.scale_w)) + g_ddraw.render.viewport.x, + (int)(roundf((yDest + pt.y) * g_ddraw.render.scale_h)) + g_ddraw.render.viewport.y, (int)(roundf(wDest * g_ddraw.render.scale_w)), (int)(roundf(hDest * g_ddraw.render.scale_h)), hdcSrc, @@ -1023,7 +1197,27 @@ BOOL WINAPI fake_BitBlt( { HWND hwnd = WindowFromDC(hdc); - if (g_ddraw.ref && g_ddraw.hwnd && hwnd == g_ddraw.hwnd) + if (g_ddraw.ref && g_ddraw.hwnd && hwnd == g_ddraw.hwnd && !g_ddraw.primary) + { + InterlockedExchange(&g_ddraw.render.screen_updated, TRUE); + } + + char class_name[MAX_PATH] = { 0 }; + + if (g_ddraw.ref && g_ddraw.hwnd && hwnd && hwnd != g_ddraw.hwnd) + { + GetClassNameA(hwnd, class_name, sizeof(class_name) - 1); + } + + if (g_ddraw.ref && g_ddraw.hwnd && + (hwnd == g_ddraw.hwnd || + (g_config.fixchilds && IsChild(g_ddraw.hwnd, hwnd) && + (g_config.fixchilds == FIX_CHILDS_DETECT_HIDE || + strcmp(class_name, "VideoRenderer") == 0 || + strcmp(class_name, "AVI Window") == 0 || + strcmp(class_name, "MCIAVI") == 0 || + strcmp(class_name, "AVIWnd32") == 0 || + strcmp(class_name, "MCIWndClass") == 0)))) { if (g_ddraw.primary && (g_ddraw.primary->bpp == 16 || g_ddraw.primary->bpp == 32 || g_ddraw.primary->palette)) { @@ -1032,11 +1226,14 @@ BOOL WINAPI fake_BitBlt( if (primary_dc) { + POINT pt = { 0 }; + real_MapWindowPoints(hwnd, g_ddraw.hwnd, &pt, 1); + int result = real_BitBlt( primary_dc, - x, - y, + x + pt.x, + y + pt.y, cx, cy, hdcSrc, @@ -1049,7 +1246,10 @@ BOOL WINAPI fake_BitBlt( return result; } } - else if (g_ddraw.width > 0 && g_ddraw.render.hdc) + else if ( + g_ddraw.width > 0 && + g_ddraw.render.hdc && + (hwnd == g_ddraw.hwnd || (real_GetWindowLongA(hwnd, GWL_EXSTYLE) & WS_EX_TRANSPARENT))) { return real_StretchBlt( hwnd == g_ddraw.hwnd ? hdc : g_ddraw.render.hdc, @@ -1098,7 +1298,27 @@ int WINAPI fake_SetDIBitsToDevice( { HWND hwnd = WindowFromDC(hdc); - if (g_ddraw.ref && g_ddraw.hwnd && hwnd == g_ddraw.hwnd) + if (g_ddraw.ref && g_ddraw.hwnd && hwnd == g_ddraw.hwnd && !g_ddraw.primary) + { + InterlockedExchange(&g_ddraw.render.screen_updated, TRUE); + } + + char class_name[MAX_PATH] = { 0 }; + + if (g_ddraw.ref && g_ddraw.hwnd && hwnd && hwnd != g_ddraw.hwnd) + { + GetClassNameA(hwnd, class_name, sizeof(class_name) - 1); + } + + if (g_ddraw.ref && g_ddraw.hwnd && + (hwnd == g_ddraw.hwnd || + (g_config.fixchilds && IsChild(g_ddraw.hwnd, hwnd) && + (g_config.fixchilds == FIX_CHILDS_DETECT_HIDE || + strcmp(class_name, "VideoRenderer") == 0 || + strcmp(class_name, "AVI Window") == 0 || + strcmp(class_name, "MCIAVI") == 0 || + strcmp(class_name, "AVIWnd32") == 0 || + strcmp(class_name, "MCIWndClass") == 0)))) { if (g_ddraw.primary && (g_ddraw.primary->bpp == 16 || g_ddraw.primary->bpp == 32 || g_ddraw.primary->palette)) { @@ -1107,19 +1327,22 @@ int WINAPI fake_SetDIBitsToDevice( if (primary_dc) { + POINT pt = { 0 }; + real_MapWindowPoints(hwnd, g_ddraw.hwnd, &pt, 1); + int result = real_SetDIBitsToDevice( - primary_dc, - xDest, - yDest, - w, - h, - xSrc, - ySrc, - StartScan, - cLines, - lpvBits, - lpbmi, + primary_dc, + xDest + pt.x, + yDest + pt.y, + w, + h, + xSrc, + ySrc, + StartScan, + cLines, + lpvBits, + lpbmi, ColorUse); dds_ReleaseDC(g_ddraw.primary, primary_dc); @@ -1127,7 +1350,10 @@ int WINAPI fake_SetDIBitsToDevice( return result; } } - else if (g_ddraw.width > 0 && g_ddraw.render.hdc) + else if ( + g_ddraw.width > 0 && + g_ddraw.render.hdc && + (hwnd == g_ddraw.hwnd || (real_GetWindowLongA(hwnd, GWL_EXSTYLE) & WS_EX_TRANSPARENT))) { return real_StretchDIBits( @@ -1167,6 +1393,11 @@ int WINAPI fake_StretchDIBits( { HWND hwnd = WindowFromDC(hdc); + if (g_ddraw.ref && g_ddraw.hwnd && hwnd == g_ddraw.hwnd && !g_ddraw.primary) + { + InterlockedExchange(&g_ddraw.render.screen_updated, TRUE); + } + char class_name[MAX_PATH] = { 0 }; if (g_ddraw.ref && g_ddraw.hwnd && hwnd && hwnd != g_ddraw.hwnd) @@ -1215,7 +1446,10 @@ int WINAPI fake_StretchDIBits( return result; } } - else if (g_ddraw.width > 0 && g_ddraw.render.hdc) + else if ( + g_ddraw.width > 0 && + g_ddraw.render.hdc && + (hwnd == g_ddraw.hwnd || (real_GetWindowLongA(hwnd, GWL_EXSTYLE) & WS_EX_TRANSPARENT))) { return real_StretchDIBits( @@ -1314,6 +1548,97 @@ HFONT WINAPI fake_CreateFontA( lpszFace); } +UINT WINAPI fake_GetSystemPaletteEntries(HDC hdc, UINT iStart, UINT cEntries, LPPALETTEENTRY pPalEntries) +{ + TRACE( + "%s(hdc=%p, iStart=%u, cEntries=%u, pPalEntries=%p) [%p]\n", + __FUNCTION__, + hdc, + iStart, + cEntries, + pPalEntries, + _ReturnAddress()); + + if (g_ddraw.ref && g_ddraw.bpp == 8 && pPalEntries && GetObjectType(hdc) == OBJ_DC) + { + TRACE(" Display DC\n"); + + if (g_ddraw.primary && g_ddraw.primary->palette) + { + ddp_GetEntries(g_ddraw.primary->palette, 0, iStart, cEntries, pPalEntries); + } + else + { + for (int i = iStart, x = 0; i < iStart + cEntries && i < 256; i++, x++) + { + pPalEntries[x] = g_ddp_default_palette[i]; + } + } + + return cEntries; + } + + return real_GetSystemPaletteEntries(hdc, iStart, cEntries, pPalEntries); +} + +HPALETTE WINAPI fake_SelectPalette(HDC hdc, HPALETTE hPal, BOOL bForceBkgd) +{ + TRACE_EXT( + "%s(hdc=%p, hPal=%p, bForceBkgd=%d) [%p]\n", + __FUNCTION__, + hdc, + hPal, + bForceBkgd, + _ReturnAddress()); + + if (g_ddraw.ref && + g_ddraw.bpp == 8 && + ((g_ddraw.hwnd && WindowFromDC(hdc) == g_ddraw.hwnd) || WindowFromDC(hdc) == GetDesktopWindow())) + { + TRACE_EXT(" Display DC\n"); + + if (g_ddraw.primary && g_ddraw.primary->palette) + { + g_ddraw.primary->selected_pal_count = GetPaletteEntries(hPal, 0, 256, g_ddraw.primary->selected_pal); + + return real_SelectPalette(g_ddraw.primary->hdc, hPal, bForceBkgd);; + } + } + + return real_SelectPalette(hdc, hPal, bForceBkgd); +} + +UINT WINAPI fake_RealizePalette(HDC hdc) +{ + TRACE_EXT("%s(hdc=%p) [%p]\n", __FUNCTION__, hdc, _ReturnAddress()); + + if (g_ddraw.ref && + g_ddraw.bpp == 8 && + ((g_ddraw.hwnd && WindowFromDC(hdc) == g_ddraw.hwnd) || WindowFromDC(hdc) == GetDesktopWindow())) + { + TRACE_EXT(" Display DC\n"); + + if (g_ddraw.primary && g_ddraw.primary->palette) + { + if (g_ddraw.primary->selected_pal_count != 256) + { + TRACE_EXT(" selected_pal_count = %u\n", g_ddraw.primary->selected_pal_count); + } + + ddp_SetEntries( + g_ddraw.primary->palette, + DDPCAPS_REFRESH_CHANGED_ONLY, + 0, + g_ddraw.primary->selected_pal_count, + g_ddraw.primary->selected_pal); + + return g_ddraw.primary->selected_pal_count; + } + } + + return real_RealizePalette(hdc); +} + HMODULE WINAPI fake_LoadLibraryA(LPCSTR lpLibFileName) { HMODULE hmod_old = GetModuleHandleA(lpLibFileName); @@ -1508,6 +1833,98 @@ BOOL WINAPI fake_GetDiskFreeSpaceA( return result; } +DWORD WINAPI fake_GetVersion() +{ + if (_strcmpi(g_config.win_version, "95") == 0) + return 0xC3B60004; + + if (_strcmpi(g_config.win_version, "98") == 0) + return 0xC0000A04; + + if (_strcmpi(g_config.win_version, "nt4") == 0) + return 0x05650004; + + if (_strcmpi(g_config.win_version, "2000") == 0) + return 0x08930005; + + if (_strcmpi(g_config.win_version, "xp") == 0) + return 0x0A280105; + + return real_GetVersion(); +} + +BOOL WINAPI fake_GetVersionExA(LPOSVERSIONINFOA info) +{ + if (g_config.win_version[0] && info && info->dwOSVersionInfoSize == sizeof(OSVERSIONINFOA)) + { + if (_strcmpi(g_config.win_version, "95") == 0) + { + *info = (OSVERSIONINFOA){ sizeof(OSVERSIONINFOA), 4, 0, 950, 1, "" }; + return TRUE; + } + + if (_strcmpi(g_config.win_version, "98") == 0) + { + *info = (OSVERSIONINFOA){ sizeof(OSVERSIONINFOA), 4, 10, 67766446, 1, "" }; + return TRUE; + } + + if (_strcmpi(g_config.win_version, "nt4") == 0) + { + *info = (OSVERSIONINFOA){ sizeof(OSVERSIONINFOA), 4, 0, 1381, 2, "Service Pack 5" }; + return TRUE; + } + + if (_strcmpi(g_config.win_version, "2000") == 0) + { + *info = (OSVERSIONINFOA){ sizeof(OSVERSIONINFOA), 5, 0, 2195, 2, "" }; + return TRUE; + } + + if (_strcmpi(g_config.win_version, "xp") == 0) + { + *info = (OSVERSIONINFOA){ sizeof(OSVERSIONINFOA), 5, 1, 2600, 2, "Service Pack 3" }; + return TRUE; + } + } + + if (g_config.win_version[0] && info && info->dwOSVersionInfoSize == sizeof(OSVERSIONINFOEXA)) + { + LPOSVERSIONINFOEXA ex = (LPOSVERSIONINFOEXA)info; + if (_strcmpi(g_config.win_version, "95") == 0) + { + *ex = (OSVERSIONINFOEXA){ sizeof(OSVERSIONINFOEXA), 4, 0, 950, 1, "", 1, 0, 256, 1, 30 }; + return TRUE; + } + + if (_strcmpi(g_config.win_version, "98") == 0) + { + *ex = (OSVERSIONINFOEXA){ sizeof(OSVERSIONINFOEXA), 4, 10, 67766446, 1, "", 1, 0, 256, 1, 30 }; + return TRUE; + } + + if (_strcmpi(g_config.win_version, "nt4") == 0) + { + *ex = (OSVERSIONINFOEXA){ sizeof(OSVERSIONINFOEXA), 4, 0, 1381, 2, "Service Pack 5", 5, 0, 256, 1, 30 }; + return TRUE; + } + + if (_strcmpi(g_config.win_version, "2000") == 0) + { + *ex = (OSVERSIONINFOEXA){ sizeof(OSVERSIONINFOEXA), 5, 0, 2195, 2, "", 0, 0, 256, 1, 30 }; + return TRUE; + } + + if (_strcmpi(g_config.win_version, "xp") == 0) + { + *ex = (OSVERSIONINFOEXA){ sizeof(OSVERSIONINFOEXA), 5, 1, 2600, 2, "Service Pack 3", 3, 0, 256, 1, 30 }; + return TRUE; + } + } + + return real_GetVersionExA(info); +} + BOOL WINAPI fake_DestroyWindow(HWND hWnd) { TRACE("DestroyWindow(hwnd=%p) - g_ddraw.hwnd=%p [%p]\n", hWnd, g_ddraw.hwnd, _ReturnAddress()); @@ -1637,6 +2054,29 @@ HWND WINAPI fake_CreateWindowExA( dwStyle &= ~WS_POPUP; } + /* Dark Colony */ + if (HIWORD(lpClassName) && _strcmpi(lpClassName, "Merc Direct Draw Driver") == 0 && + lpWindowName && _strcmpi(lpWindowName, "Direct Draw Driver") == 0 && + !dwExStyle) + { + dwExStyle |= WS_EX_APPWINDOW; + } + + /* Fallout 1/2 */ + if (HIWORD(lpClassName) && _strcmpi(lpClassName, "GNW95 Class") == 0 && + lpWindowName && strstr(lpWindowName, "FALLOUT")) + { + /* Workaround for window not showing up in taskbar sometimes */ + dwExStyle |= WS_EX_APPWINDOW; + } + + /* Fallout Tactics */ + if (HIWORD(lpClassName) && _strcmpi(lpClassName, "bosWin32Class") == 0 && + lpWindowName && _strcmpi(lpWindowName, "Fallout: Tactics (TM)") == 0) + { + dwStyle |= WS_VISIBLE; + } + /* Center Claw DVD movies */ if (HIWORD(lpClassName) && _strcmpi(lpClassName, "Afx:400000:3") == 0 && g_ddraw.ref && g_ddraw.hwnd && hWndParent == g_ddraw.hwnd && @@ -1658,6 +2098,55 @@ HWND WINAPI fake_CreateWindowExA( Y = pt.y + align_y; } + /* Metal Knight Movies */ + if (HIWORD(lpClassName) && _strcmpi(lpClassName, "Afx:400000:3:0:1900011:0") == 0 && + lpWindowName && _strcmpi(lpWindowName, "AVI player") == 0 && + dwStyle == WS_POPUP && + dwExStyle == WS_EX_TOPMOST && + g_ddraw.ref && g_ddraw.hwnd && + g_ddraw.width) + { + dwExStyle = 0; + + POINT pt = { 0, 0 }; + real_ClientToScreen(g_ddraw.hwnd, &pt); + + int added_height = g_ddraw.render.height - g_ddraw.height; + int added_width = g_ddraw.render.width - g_ddraw.width; + int align_y = added_height > 0 ? added_height / 2 : 0; + int align_x = added_width > 0 ? added_width / 2 : 0; + + X += pt.x + align_x; + Y += pt.y + align_y; + } + + /* Disney Trivia Challenge */ + if (HIWORD(lpClassName) && _strcmpi(lpClassName, "Disney Trivia Challenge") == 0 && + hWndParent && (dwStyle & WS_CHILD)) + { + dwExStyle = WS_EX_TRANSPARENT; + } + + /* Center Lego Loco overlays */ + if (lpWindowName && _strcmpi(lpWindowName, "LEGO LOCO") == 0 && + g_ddraw.ref && g_ddraw.hwnd && hWndParent == g_ddraw.hwnd && + g_ddraw.width && + (dwStyle & WS_POPUP)) + { + /* not working currently, game probably moves it with SetWindowPos or MoveWindow afterwards + POINT pt = { 0, 0 }; + real_ClientToScreen(g_ddraw.hwnd, &pt); + + int added_height = g_ddraw.render.height - g_ddraw.height; + int added_width = g_ddraw.render.width - g_ddraw.width; + int align_y = added_height > 0 ? added_height / 2 : 0; + int align_x = added_width > 0 ? added_width / 2 : 0; + + X = pt.x + align_x; + Y = pt.y + align_y; + */ + } + /* Road Rash movies */ if (HIWORD(lpClassName) && _strcmpi(lpClassName, "AVI Window") == 0 && g_ddraw.ref && g_ddraw.hwnd && g_ddraw.width && @@ -1667,12 +2156,20 @@ HWND WINAPI fake_CreateWindowExA( hWndParent = g_ddraw.hwnd; } + /* A Bug's Life Action Game */ + //HIWORD(lpClassName) && _strcmpi(lpClassName, "Bugs") == 0 && + if (dwExStyle == 0x01000008) + { + dwExStyle = WS_EX_TOPMOST; + } + /* Fix for SMACKW32.DLL creating another window that steals the focus */ if (HIWORD(lpClassName) && _strcmpi(lpClassName, "MouseTypeWind") == 0 && g_ddraw.ref && g_ddraw.hwnd) { dwStyle &= ~WS_VISIBLE; } + /* Battle.net */ if (HIWORD(lpClassName) && _strcmpi(lpClassName, "SDlgDialog") == 0 && g_ddraw.ref && g_ddraw.hwnd) { if (!g_ddraw.bnet_active) @@ -1846,3 +2343,27 @@ LPTOP_LEVEL_EXCEPTION_FILTER WINAPI fake_SetUnhandledExceptionFilter( return old; //return real_SetUnhandledExceptionFilter(lpTopLevelExceptionFilter); } + +PGETFRAME WINAPI fake_AVIStreamGetFrameOpen(PAVISTREAM pavi, LPBITMAPINFOHEADER lpbiWanted) +{ + if (g_ddraw.ref && g_ddraw.primary && (DWORD)lpbiWanted == AVIGETFRAMEF_BESTDISPLAYFMT) + { + DDBITMAPINFO bmi; + memcpy(&bmi, g_ddraw.primary->bmi, sizeof(DDBITMAPINFO)); + + bmi.bmiHeader.biHeight = 0; + bmi.bmiHeader.biWidth = 0; + + if (g_ddraw.bpp == 8 && g_ddraw.primary->palette) + { + memcpy(&bmi.bmiColors[0], g_ddraw.primary->palette->data_rgb, sizeof(bmi.bmiColors)); + } + + PGETFRAME result = real_AVIStreamGetFrameOpen(pavi, (LPBITMAPINFOHEADER)&bmi); + + if (result) + return result; + } + + return real_AVIStreamGetFrameOpen(pavi, lpbiWanted); +} diff --git a/src/wndproc.c b/src/wndproc.c index ebde744..3555058 100644 --- a/src/wndproc.c +++ b/src/wndproc.c @@ -22,7 +22,7 @@ LRESULT CALLBACK fake_WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam if (uMsg != WM_MOUSEMOVE && uMsg != WM_NCMOUSEMOVE && uMsg != WM_NCHITTEST && uMsg != WM_SETCURSOR && uMsg != WM_KEYUP && uMsg != WM_KEYDOWN && uMsg != WM_CHAR && uMsg != WM_DEADCHAR && uMsg != WM_INPUT && uMsg != WM_UNICHAR && uMsg != WM_IME_CHAR && uMsg != WM_IME_KEYDOWN && uMsg != WM_IME_KEYUP && uMsg != WM_TIMER && - uMsg != WM_D3D9DEVICELOST) + uMsg != WM_D3D9DEVICELOST && uMsg != WM_NULL) { TRACE( " uMsg = %s (%d), wParam = %08X (%d), lParam = %08X (%d, LO=%d HI=%d)\n", @@ -42,14 +42,16 @@ LRESULT CALLBACK fake_WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam switch (uMsg) { + case WM_NULL: case WM_MOVING: case WM_NCLBUTTONDOWN: case WM_NCLBUTTONUP: case WM_NCPAINT: case WM_CANCELMODE: case WM_DISPLAYCHANGE: + case WM_NCCALCSIZE: { - return DefWindowProc(hWnd, uMsg, wParam, lParam); + return real_DefWindowProcA(hWnd, uMsg, wParam, lParam); } case WM_GETMINMAXINFO: { @@ -87,20 +89,48 @@ LRESULT CALLBACK fake_WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam return 0; } - return DefWindowProc(hWnd, uMsg, wParam, lParam); + return real_DefWindowProcA(hWnd, uMsg, wParam, lParam); } + case WM_KILLFOCUS: case WM_NCACTIVATE: { if (g_config.noactivateapp) { - return DefWindowProc(hWnd, uMsg, wParam, lParam); + return real_DefWindowProcA(hWnd, uMsg, wParam, lParam); } break; } case WM_NCHITTEST: { - LRESULT result = DefWindowProc(hWnd, uMsg, wParam, lParam); + if (g_mouse_locked || g_config.devmode) + { + POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) }; + + if (!g_config.windowed || real_ScreenToClient(g_ddraw.hwnd, &pt)) + { + int x = max(pt.x - g_ddraw.mouse.x_adjust, 0); + int y = max(pt.y - g_ddraw.mouse.y_adjust, 0); + + if (g_config.adjmouse) + { + x = (DWORD)(roundf(x * g_ddraw.mouse.unscale_x)); + y = (DWORD)(roundf(y * g_ddraw.mouse.unscale_y)); + } + + pt.x = min(x, g_ddraw.width - 1); + pt.y = min(y, g_ddraw.height - 1); + } + else + { + pt.x = InterlockedExchangeAdd((LONG*)&g_ddraw.cursor.x, 0); + pt.y = InterlockedExchangeAdd((LONG*)&g_ddraw.cursor.y, 0); + } + + CallWindowProcA(g_ddraw.wndproc, hWnd, uMsg, wParam, MAKELPARAM(pt.x, pt.y)); + } + + LRESULT result = real_DefWindowProcA(hWnd, uMsg, wParam, lParam); if (!g_config.resizable) { @@ -145,7 +175,7 @@ LRESULT CALLBACK fake_WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam case HTTOP: case HTTOPLEFT: case HTTOPRIGHT: - return DefWindowProc(hWnd, uMsg, wParam, lParam); + return real_DefWindowProcA(hWnd, uMsg, wParam, lParam); case HTCLIENT: if (!g_mouse_locked && !g_config.devmode) { @@ -215,6 +245,12 @@ LRESULT CALLBACK fake_WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam return 0; } + case IDT_TIMER_LINUX_FIX_WINDOW_SIZE: + { + KillTimer(g_ddraw.hwnd, IDT_TIMER_LINUX_FIX_WINDOW_SIZE); + util_set_window_rect(0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); + return 0; + } } break; } @@ -317,8 +353,24 @@ LRESULT CALLBACK fake_WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam real_GetWindowLongA(hWnd, GWL_EXSTYLE)) && SetRect(&clientrc, 0, 0, clientrc.right - clientrc.left, clientrc.bottom - clientrc.top)) { - double scaleH = (double)g_ddraw.height / g_ddraw.width; - double scaleW = (double)g_ddraw.width / g_ddraw.height; + double scale_h; + double scale_w; + + if (g_config.aspect_ratio[0]) + { + char* e = &g_config.aspect_ratio[0]; + + DWORD cx = strtoul(e, &e, 0); + DWORD cy = strtoul(e + 1, &e, 0); + + scale_h = (double)cy / cx; + scale_w = (double)cx / cy; + } + else + { + scale_h = (double)g_ddraw.height / g_ddraw.width; + scale_w = (double)g_ddraw.width / g_ddraw.height; + } switch (wParam) { @@ -327,19 +379,19 @@ LRESULT CALLBACK fake_WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam case WMSZ_LEFT: case WMSZ_RIGHT: { - windowrc->bottom += (LONG)round(scaleH * clientrc.right - clientrc.bottom); + windowrc->bottom += (LONG)round(scale_h * clientrc.right - clientrc.bottom); break; } case WMSZ_TOP: case WMSZ_BOTTOM: { - windowrc->right += (LONG)round(scaleW * clientrc.bottom - clientrc.right); + windowrc->right += (LONG)round(scale_w * clientrc.bottom - clientrc.right); break; } case WMSZ_TOPRIGHT: case WMSZ_TOPLEFT: { - windowrc->top -= (LONG)round(scaleH * clientrc.right - clientrc.bottom); + windowrc->top -= (LONG)round(scale_h * clientrc.right - clientrc.bottom); break; } } @@ -424,20 +476,70 @@ LRESULT CALLBACK fake_WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam { if (g_config.windowed) { + WORD width = LOWORD(lParam); + WORD height = HIWORD(lParam); + if (wParam == SIZE_RESTORED) { + /* macOS maximize hack */ + if (in_size_move && g_ddraw.render.thread && IsMacOS()) + { + EnterCriticalSection(&g_ddraw.cs); + g_ddraw.render.run = FALSE; + ReleaseSemaphore(g_ddraw.render.sem, 1, NULL); + LeaveCriticalSection(&g_ddraw.cs); + + WaitForSingleObject(g_ddraw.render.thread, INFINITE); + g_ddraw.render.thread = NULL; + } + if (in_size_move && !g_ddraw.render.thread) { - g_config.window_rect.right = LOWORD(lParam); - g_config.window_rect.bottom = HIWORD(lParam); + g_config.window_rect.right = width; + g_config.window_rect.bottom = height; } - else if (!in_size_move && g_ddraw.render.thread && !g_config.fullscreen && g_config.wine_allow_resize && IsLinux()) + else if (!in_size_move && g_ddraw.render.thread && !g_config.fullscreen && IsLinux()) { - g_config.window_rect.right = LOWORD(lParam); - g_config.window_rect.bottom = HIWORD(lParam); + if (width != g_ddraw.render.width || height != g_ddraw.render.height) + { + KillTimer(g_ddraw.hwnd, IDT_TIMER_LINUX_FIX_WINDOW_SIZE); + + g_config.window_rect.right = width; + g_config.window_rect.bottom = height; - if (g_config.window_rect.right != g_ddraw.render.width || g_config.window_rect.bottom != g_ddraw.render.height) dd_SetDisplayMode(0, 0, 0, 0); + + if (width < g_ddraw.width || height < g_ddraw.height) + { + /* Can't enforce minimum window size in linux because there is no WM_SIZING and + WM_GETMINMAXINFO is ignored for whatever reasons */ + + SetTimer(g_ddraw.hwnd, IDT_TIMER_LINUX_FIX_WINDOW_SIZE, 1000, (TIMERPROC)NULL); + } + } + } + } + else if (wParam == SIZE_MAXIMIZED) + { + if (!in_size_move && g_ddraw.render.thread && !g_config.fullscreen && IsLinux()) + { + if (width != g_ddraw.render.width || height != g_ddraw.render.height) + { + KillTimer(g_ddraw.hwnd, IDT_TIMER_LINUX_FIX_WINDOW_SIZE); + + g_config.window_rect.right = width; + g_config.window_rect.bottom = height; + + dd_SetDisplayMode(0, 0, 0, 0); + + if (width < g_ddraw.width || height < g_ddraw.height) + { + /* Can't enforce minimum window size in linux because there is no WM_SIZING and + WM_GETMINMAXINFO is ignored for whatever reasons */ + + SetTimer(g_ddraw.hwnd, IDT_TIMER_LINUX_FIX_WINDOW_SIZE, 1000, (TIMERPROC)NULL); + } + } } } } @@ -448,7 +550,7 @@ LRESULT CALLBACK fake_WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam RedrawWindow(hWnd, NULL, NULL, RDW_INVALIDATE | RDW_ALLCHILDREN); } - return DefWindowProc(hWnd, uMsg, wParam, lParam); /* Carmageddon fix */ + return real_DefWindowProcA(hWnd, uMsg, wParam, lParam); /* Carmageddon fix */ } case WM_MOVE: { @@ -462,7 +564,7 @@ LRESULT CALLBACK fake_WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam util_update_bnet_pos(x, y); } - if (in_size_move || (IsWine() && !g_config.fullscreen && g_ddraw.render.thread)) + if (in_size_move || (IsLinux() && !g_config.fullscreen && g_ddraw.render.thread)) { if (x != -32000) g_config.window_rect.left = x; /* -32000 = Exit/Minimize */ @@ -475,7 +577,7 @@ LRESULT CALLBACK fake_WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam if (g_ddraw.got_child_windows) RedrawWindow(hWnd, NULL, NULL, RDW_INVALIDATE | RDW_ALLCHILDREN); - return DefWindowProc(hWnd, uMsg, wParam, lParam); /* Carmageddon fix */ + return real_DefWindowProcA(hWnd, uMsg, wParam, lParam); /* Carmageddon fix */ } case WM_RESTORE_STYLE: { @@ -505,6 +607,9 @@ LRESULT CALLBACK fake_WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam if (wParam == SC_MAXIMIZE) { + if (IsWine()) + return real_DefWindowProcA(hWnd, uMsg, wParam, lParam); + if (g_config.resizable) { util_toggle_maximize(); @@ -515,14 +620,18 @@ LRESULT CALLBACK fake_WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam if (wParam == SC_CLOSE && !GameHandlesClose) { - _exit(0); + if (g_config.terminate_process) + g_config.terminate_process = 2; + + ExitProcess(0); + //_exit(0); } if (wParam == SC_KEYMENU && GetMenu(g_ddraw.hwnd) == NULL) return 0; if (!GameHandlesClose) - return DefWindowProc(hWnd, uMsg, wParam, lParam); + return real_DefWindowProcA(hWnd, uMsg, wParam, lParam); break; } @@ -557,13 +666,13 @@ LRESULT CALLBACK fake_WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam } case WM_ACTIVATE: { - if (wParam == WA_ACTIVE || wParam == WA_CLICKACTIVE) + if (LOWORD(wParam) == WA_ACTIVE || LOWORD(wParam) == WA_CLICKACTIVE) { if (g_ddraw.got_child_windows) RedrawWindow(hWnd, NULL, NULL, RDW_INVALIDATE | RDW_ALLCHILDREN); } - if (wParam == WA_INACTIVE) + if (LOWORD(wParam) == WA_INACTIVE) { if (g_config.windowed && !g_config.fullscreen && lParam && GetParent((HWND)lParam) == hWnd) { @@ -600,10 +709,21 @@ LRESULT CALLBACK fake_WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam } } - //if (g_ddraw.windowed || g_ddraw.noactivateapp) + if (g_config.windowed || g_config.noactivateapp) + { + /* let it pass through once (Atrox) */ + static BOOL one_time; + + if (!one_time) + { + one_time = TRUE; + + if (LOWORD(wParam)) + break; + } - if (!g_config.allow_wmactivate) return 0; + } break; } @@ -647,7 +767,7 @@ LRESULT CALLBACK fake_WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam } } - if (wParam && g_config.releasealt) + if (wParam && g_config.fix_alt_key_stuck) { INPUT ip; memset(&ip, 0, sizeof(ip)); @@ -679,8 +799,11 @@ LRESULT CALLBACK fake_WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam break; } - if (wParam && g_ddraw.alt_key_down && !g_config.releasealt) + if (wParam && g_ddraw.alt_key_down && !g_config.fix_alt_key_stuck) + { PostMessageA(g_ddraw.hwnd, WM_SYSKEYUP, VK_MENU, 0); + g_ddraw.alt_key_down = FALSE; + } return 0; } @@ -731,102 +854,28 @@ LRESULT CALLBACK fake_WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam } case WM_SYSKEYDOWN: { - BOOL context_code = (lParam & (1 << 29)) != 0; - BOOL key_state = (lParam & (1 << 30)) != 0; - - if (g_config.hotkeys.toggle_fullscreen && - wParam == g_config.hotkeys.toggle_fullscreen && - (!g_config.fullscreen || g_config.toggle_upscaled || (g_config.windowed && g_config.toggle_borderless)) && - context_code && - !key_state) + if (wParam == VK_F4) { - util_toggle_fullscreen(); - return 0; - } - - if (g_config.hotkeys.toggle_maximize && - wParam == g_config.hotkeys.toggle_maximize && - g_config.resizable && - g_config.windowed && - !g_config.fullscreen) - { - util_toggle_maximize(); - return 0; - } - - if (wParam == VK_MENU) - { - g_ddraw.alt_key_down = TRUE; + return real_DefWindowProcA(hWnd, uMsg, wParam, lParam); } break; } case WM_SYSKEYUP: { - if (wParam == VK_MENU) + if (wParam == VK_TAB || (wParam && wParam == g_config.hotkeys.toggle_fullscreen)) { - g_ddraw.alt_key_down = FALSE; - } - - if (wParam == VK_TAB || (g_config.hotkeys.toggle_fullscreen && wParam == g_config.hotkeys.toggle_fullscreen)) - { - return DefWindowProc(hWnd, uMsg, wParam, lParam); + return real_DefWindowProcA(hWnd, uMsg, wParam, lParam); } break; } case WM_KEYDOWN: { - if (g_config.homm_hack && wParam == VK_F4) /* Heroes of Might and Magic 3 and 4 */ - { - util_toggle_fullscreen(); - return 0; - } - - if (g_config.hotkeys.unlock_cursor1 && - (wParam == VK_CONTROL || wParam == g_config.hotkeys.unlock_cursor1)) - { - if (real_GetAsyncKeyState(VK_CONTROL) & 0x8000 && real_GetAsyncKeyState(g_config.hotkeys.unlock_cursor1) & 0x8000) - { - mouse_unlock(); - return 0; - } - } - - if (g_config.hotkeys.unlock_cursor2 && - (wParam == g_config.hotkeys.unlock_cursor2 || wParam == VK_MENU || wParam == VK_CONTROL)) - { - if ((real_GetAsyncKeyState(VK_RMENU) & 0x8000) && real_GetAsyncKeyState(g_config.hotkeys.unlock_cursor2) & 0x8000) - { - mouse_unlock(); - return 0; - } - } - - HWND video_hwnd = (HWND)InterlockedExchangeAdd((LONG*)&g_ddraw.video_window_hwnd, 0); - if (video_hwnd) - { - //PostMessageA(video_hwnd, uMsg, wParam, lParam); - //return 0; - } - break; } case WM_KEYUP: { - if (g_config.homm_hack && wParam == VK_F4) /* Heroes of Might and Magic 3 and 4 */ - return 0; - - if (g_config.hotkeys.screenshot && wParam == g_config.hotkeys.screenshot) - ss_take_screenshot(g_ddraw.primary); - - HWND video_hwnd = (HWND)InterlockedExchangeAdd((LONG*)&g_ddraw.video_window_hwnd, 0); - if (video_hwnd) - { - //PostMessageA(video_hwnd, uMsg, wParam, lParam); - //return 0; - } - break; } /* button up messages reactivate cursor lock */ @@ -918,13 +967,6 @@ LRESULT CALLBACK fake_WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam lParam = MAKELPARAM(x, y); - HWND video_hwnd = (HWND)InterlockedExchangeAdd((LONG*)&g_ddraw.video_window_hwnd, 0); - if (video_hwnd) - { - //PostMessageA(video_hwnd, uMsg, wParam, lParam); - //return 0; - } - break; } case WM_PARENTNOTIFY: