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: