From cc62827d3c0bafd09c928a4a18af214e50fab89a Mon Sep 17 00:00:00 2001 From: Tom Date: Fri, 7 Oct 2022 17:02:30 +0100 Subject: [PATCH 01/40] git ignore --- .gitignore | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index a66d5e28..2ce477f0 100644 --- a/.gitignore +++ b/.gitignore @@ -32,4 +32,6 @@ # Executables *.exe *.out -*.app \ No newline at end of file +*.app +/.vs +/out/build/x64-debug From 165a71a69e28a1fb55ffaaacc67520dc2036d30f Mon Sep 17 00:00:00 2001 From: Tom Date: Fri, 7 Oct 2022 19:11:26 +0100 Subject: [PATCH 02/40] Add sln and vcxproj --- .gitignore | 441 +++++++++++++++++++ GGPO.sln | 34 ++ src/GGPO.vcxproj | 197 +++++++++ src/GGPO.vcxproj.filters | 54 +++ src/apps/vectorwar/VectorWar.vcxproj | 175 ++++++++ src/apps/vectorwar/VectorWar.vcxproj.filters | 28 ++ src/include/ggponet.h | 24 +- 7 files changed, 941 insertions(+), 12 deletions(-) create mode 100644 GGPO.sln create mode 100644 src/GGPO.vcxproj create mode 100644 src/GGPO.vcxproj.filters create mode 100644 src/apps/vectorwar/VectorWar.vcxproj create mode 100644 src/apps/vectorwar/VectorWar.vcxproj.filters diff --git a/.gitignore b/.gitignore index 2ce477f0..018f0464 100644 --- a/.gitignore +++ b/.gitignore @@ -35,3 +35,444 @@ *.app /.vs /out/build/x64-debug + +Skip to content +Search or jump to… +Pull requests +Issues +Marketplace +Explore + +@thomashenry79 +github +/ +gitignore +Public +Code +Pull requests +326 +Actions +Security +Insights +gitignore/VisualStudio.gitignore +@n0099 +n0099 [VisualStudio.gitignore] remove a trailing space +Latest commit 491040e on 26 Jan + History + 165 contributors +@shiftkey@arcresu@aroben@bbodenmiller@HassanHashemi@haacked@niik@AArnott@sayedihashimi@saschanaz@bdougie@OsirisTerje +398 lines (319 sloc) 6.7 KB + +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore + +# User-specific files +*.rsuser +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Mono auto generated files +mono_crash.* + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +[Ww][Ii][Nn]32/ +[Aa][Rr][Mm]/ +[Aa][Rr][Mm]64/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ +[Ll]ogs/ + +# Visual Studio 2015/2017 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# Visual Studio 2017 auto generated files +Generated\ Files/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUnit +*.VisualState.xml +TestResult.xml +nunit-*.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET Core +project.lock.json +project.fragment.lock.json +artifacts/ + +# ASP.NET Scaffolding +ScaffoldingReadMe.txt + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio +*_i.c +*_p.c +*_h.h +*.ilk +*.meta +*.obj +*.iobj +*.pch +*.pdb +*.ipdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*_wpftmp.csproj +*.log +*.tlog +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# Visual Studio Trace Files +*.e2e + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Coverlet is a free, cross platform Code Coverage Tool +coverage*.json +coverage*.xml +coverage*.info + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# Note: Comment the next line if you want to checkin your web deploy settings, +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# NuGet Symbol Packages +*.snupkg +# The packages folder can be ignored because of Package Restore +**/[Pp]ackages/* +# except build/, which is used as an MSBuild target. +!**/[Pp]ackages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/[Pp]ackages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx +*.appxbundle +*.appxupload + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!?*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Including strong name files can present a security risk +# (https://github.com/github/gitignore/pull/2483#issue-259490424) +#*.snk + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm +ServiceFabricBackup/ +*.rptproj.bak + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings +*.rptproj.rsuser +*- [Bb]ackup.rdl +*- [Bb]ackup ([0-9]).rdl +*- [Bb]ackup ([0-9][0-9]).rdl + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio 6 auto-generated project file (contains which files were open etc.) +*.vbp + +# Visual Studio 6 workspace and project file (working project files containing files to include in project) +*.dsw +*.dsp + +# Visual Studio 6 technical files +*.ncb +*.aps + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# CodeRush personal settings +.cr/personal + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# OpenCover UI analysis results +OpenCover/ + +# Azure Stream Analytics local run output +ASALocalRun/ + +# MSBuild Binary and Structured Log +*.binlog + +# NVidia Nsight GPU debugger configuration file +*.nvuser + +# MFractors (Xamarin productivity tool) working folder +.mfractor/ + +# Local History for Visual Studio +.localhistory/ + +# Visual Studio History (VSHistory) files +.vshistory/ + +# BeatPulse healthcheck temp database +healthchecksdb + +# Backup folder for Package Reference Convert tool in Visual Studio 2017 +MigrationBackup/ + +# Ionide (cross platform F# VS Code tools) working folder +.ionide/ + +# Fody - auto-generated XML schema +FodyWeavers.xsd + +# VS Code files for those working on multiple tools +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +*.code-workspace + +# Local History for Visual Studio Code +.history/ + +# Windows Installer files from build outputs +*.cab +*.msi +*.msix +*.msm +*.msp + +# JetBrains Rider +*.sln.iml +Footer +© 2022 GitHub, Inc. +Footer navigation +Terms +Privacy +Security +Status +Docs +Contact GitHub +Pricing +API +Training +Blog +About +/CMakeCache.txt diff --git a/GGPO.sln b/GGPO.sln new file mode 100644 index 00000000..91b1f9a3 --- /dev/null +++ b/GGPO.sln @@ -0,0 +1,34 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.3.32922.545 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GGPO", "src\GGPO.vcxproj", "{1B89CCF2-963B-30F8-A86A-FB85A0BB8077}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "VectorWar", "src\apps\vectorwar\VectorWar.vcxproj", "{58789CDC-C8E2-30F9-9FD6-8043C74C79E8}" + ProjectSection(ProjectDependencies) = postProject + {1B89CCF2-963B-30F8-A86A-FB85A0BB8077} = {1B89CCF2-963B-30F8-A86A-FB85A0BB8077} + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {1B89CCF2-963B-30F8-A86A-FB85A0BB8077}.Debug|x64.ActiveCfg = Debug|x64 + {1B89CCF2-963B-30F8-A86A-FB85A0BB8077}.Debug|x64.Build.0 = Debug|x64 + {1B89CCF2-963B-30F8-A86A-FB85A0BB8077}.Release|x64.ActiveCfg = Release|x64 + {1B89CCF2-963B-30F8-A86A-FB85A0BB8077}.Release|x64.Build.0 = Release|x64 + {58789CDC-C8E2-30F9-9FD6-8043C74C79E8}.Debug|x64.ActiveCfg = Debug|x64 + {58789CDC-C8E2-30F9-9FD6-8043C74C79E8}.Debug|x64.Build.0 = Debug|x64 + {58789CDC-C8E2-30F9-9FD6-8043C74C79E8}.Release|x64.ActiveCfg = Release|x64 + {58789CDC-C8E2-30F9-9FD6-8043C74C79E8}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {AB7CAFF3-6E5A-3140-B682-FA4800872C24} + EndGlobalSection +EndGlobal diff --git a/src/GGPO.vcxproj b/src/GGPO.vcxproj new file mode 100644 index 00000000..0a558739 --- /dev/null +++ b/src/GGPO.vcxproj @@ -0,0 +1,197 @@ + + + + x64 + + + + Debug + x64 + + + Release + x64 + + + + {1B89CCF2-963B-30F8-A86A-FB85A0BB8077} + 10.0.19041.0 + Win32Proj + x64 + GGPO + NoUpgrade + + + + StaticLibrary + MultiByte + v142 + + + StaticLibrary + MultiByte + v142 + + + + + + + + + + <_ProjectFileVersion>10.0.20506.1 + $(ProjectDir)..\lib\$(Platform)\$(Configuration) + GGPO.dir\$(Configuration)\ + GGPO + .lib + true + true + $(ProjectDir)..\lib\$(Platform)\$(Configuration) + GGPO.dir\$(Configuration)\ + GGPO + .lib + false + true + + + + $(ProjectDir)include;$(ProjectDir)lib\ggpo;%(AdditionalIncludeDirectories) + %(AdditionalOptions) /bigobj + $(IntDir) + EnableFastChecks + false + EditAndContinue + 4577;4530 + Sync + Disabled + true + Disabled + NotUsing + MultiThreadedDebugDLL + true + true + true + false + Level4 + WIN32;_WINDOWS;GGPO_SHARED_LIB;GGPO_SDK_EXPORT;CMAKE_INTDIR="Debug";GGPO_EXPORTS;%(PreprocessorDefinitions) + $(IntDir) + + + WIN32;_DEBUG;_WINDOWS;GGPO_SHARED_LIB;GGPO_SDK_EXPORT;CMAKE_INTDIR=\"Debug\";GGPO_EXPORTS;%(PreprocessorDefinitions) + $(ProjectDir)include;$(ProjectDir)lib\ggpo;%(AdditionalIncludeDirectories) + + + $(ProjectDir)include;$(ProjectDir)lib\ggpo;%(AdditionalIncludeDirectories) + $(ProjectDir)/$(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + winmm.lib;ws2_32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;comdlg32.lib;advapi32.lib + %(AdditionalLibraryDirectories) + %(AdditionalOptions) /machine:x64 + true + %(IgnoreSpecificDefaultLibraries) + $(ProjectDir)$(Platform)\$(Configuration)\GGPO.lib + $(ProjectDir)$(Platform)\$(Configuration)\GGPO.pdb + Console + + + false + + + + + $(ProjectDir)include;$(ProjectDir)lib\ggpo;%(AdditionalIncludeDirectories) + %(AdditionalOptions) /bigobj + $(IntDir) + false + ProgramDatabase + 4577;4530 + Sync + true + AnySuitable + true + true + MaxSpeed + NotUsing + MultiThreadedDLL + true + true + true + false + Level4 + true + WIN32;_WINDOWS;NDEBUG;GGPO_SHARED_LIB;GGPO_SDK_EXPORT;CMAKE_INTDIR="Release";GGPO_EXPORTS;%(PreprocessorDefinitions) + $(IntDir) + + + WIN32;_WINDOWS;NDEBUG;GGPO_SHARED_LIB;GGPO_SDK_EXPORT;CMAKE_INTDIR=\"Release\";GGPO_EXPORTS;%(PreprocessorDefinitions) + $(ProjectDir)include;$(ProjectDir)lib\ggpo;%(AdditionalIncludeDirectories) + + + $(ProjectDir)include;$(ProjectDir)lib\ggpo;%(AdditionalIncludeDirectories) + $(ProjectDir)/$(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + winmm.lib;ws2_32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;comdlg32.lib;advapi32.lib + %(AdditionalLibraryDirectories) + %(AdditionalOptions) /machine:x64 + true + %(IgnoreSpecificDefaultLibraries) + $(ProjectDir)$(Platform)\$(Configuration)\GGPO.lib + UseLinkTimeCodeGeneration + true + $(ProjectDir)$(Platform)\$(Configuration)\GGPO.pdb + Console + + + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/GGPO.vcxproj.filters b/src/GGPO.vcxproj.filters new file mode 100644 index 00000000..d619690f --- /dev/null +++ b/src/GGPO.vcxproj.filters @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {A4022066-BFC1-3E5C-BF0B-F262BFDC77F6} + + + {F3906B9A-515B-3BA2-914A-1F0384BF97B2} + + + {F623A9F0-68E4-3BF5-AFA7-22DD63404C53} + + + {1246EDFE-CC75-39EC-918E-B8611BBC8437} + + + \ No newline at end of file diff --git a/src/apps/vectorwar/VectorWar.vcxproj b/src/apps/vectorwar/VectorWar.vcxproj new file mode 100644 index 00000000..9fb49049 --- /dev/null +++ b/src/apps/vectorwar/VectorWar.vcxproj @@ -0,0 +1,175 @@ + + + + x64 + + + + Debug + x64 + + + Release + x64 + + + + {58789CDC-C8E2-30F9-9FD6-8043C74C79E8} + 10.0.19041.0 + Win32Proj + x64 + VectorWar + NoUpgrade + + + + Application + Unicode + v142 + + + Application + Unicode + v142 + + + + + + + + + + <_ProjectFileVersion>10.0.20506.1 + $(ProjectDir)..\..\..\bin\$(Platform)\$(Configuration) + VectorWar.dir\Debug\ + VectorWar + .exe + true + true + $(ProjectDir)..\..\..\bin\$(Platform)\$(Configuration) + VectorWar.dir\Release\ + VectorWar + .exe + false + true + + + + ..\..\include;..\..\lib\ggpo;%(AdditionalIncludeDirectories) + %(AdditionalOptions) /bigobj + $(IntDir) + EnableFastChecks + false + EditAndContinue + 4577;4530 + Sync + Disabled + true + Disabled + NotUsing + MultiThreadedDebugDLL + true + true + true + false + Level4 + WIN32;_WINDOWS;GGPO_SHARED_LIB;_UNICODE;UNICODE;CMAKE_INTDIR="Debug";%(PreprocessorDefinitions) + $(IntDir) + + + WIN32;_DEBUG;_WINDOWS;GGPO_SHARED_LIB;_UNICODE;UNICODE;CMAKE_INTDIR=\"Debug\";%(PreprocessorDefinitions) + ..\..\include;..\..\lib\ggpo;%(AdditionalIncludeDirectories) + + + ..\..\include;..\..\lib\ggpo;%(AdditionalIncludeDirectories) + $(ProjectDir)/$(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + GGPO.lib;winmm.lib;ws2_32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;comdlg32.lib;advapi32.lib + $(ProjectDir)..\..\..\lib\$(Platform)\$(Configuration);%(AdditionalLibraryDirectories) + %(AdditionalOptions) /machine:x64 + true + %(IgnoreSpecificDefaultLibraries) + Windows + + + false + + + + + ..\..\include;..\..\lib\ggpo;%(AdditionalIncludeDirectories) + %(AdditionalOptions) /bigobj + $(IntDir) + false + ProgramDatabase + 4577;4530 + Sync + true + AnySuitable + true + true + MaxSpeed + NotUsing + MultiThreadedDLL + true + true + true + false + Level4 + true + WIN32;_WINDOWS;NDEBUG;GGPO_SHARED_LIB;_UNICODE;UNICODE;CMAKE_INTDIR="Release";%(PreprocessorDefinitions) + $(IntDir) + + + WIN32;_WINDOWS;NDEBUG;GGPO_SHARED_LIB;_UNICODE;UNICODE;CMAKE_INTDIR=\"Release\";%(PreprocessorDefinitions) + ..\..\include;..\..lib\ggpo;%(AdditionalIncludeDirectories) + + + ..\..\include;..\..\lib\ggpo;%(AdditionalIncludeDirectories) + $(ProjectDir)/$(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + GGPO.lib;winmm.lib;ws2_32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;comdlg32.lib;advapi32.lib + $(ProjectDir)..\..\..\lib\$(Platform)\$(Configuration);%(AdditionalLibraryDirectories) + %(AdditionalOptions) /machine:x64 + true + %(IgnoreSpecificDefaultLibraries) + ..\..\lib/x64/Release/VectorWar.lib + UseLinkTimeCodeGeneration + true + Windows + + + false + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/apps/vectorwar/VectorWar.vcxproj.filters b/src/apps/vectorwar/VectorWar.vcxproj.filters new file mode 100644 index 00000000..5cfd096a --- /dev/null +++ b/src/apps/vectorwar/VectorWar.vcxproj.filters @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + {A4022066-BFC1-3E5C-BF0B-F262BFDC77F6} + + + \ No newline at end of file diff --git a/src/include/ggponet.h b/src/include/ggponet.h index f8146074..ba99a678 100644 --- a/src/include/ggponet.h +++ b/src/include/ggponet.h @@ -16,19 +16,19 @@ extern "C" { // On windows, export at build time and import at runtime. // ELF systems don't need an explicit export/import. -#ifdef _WIN32 -# if defined(GGPO_SHARED_LIB) -# ifdef GGPO_SDK_EXPORT -# define GGPO_API __declspec(dllexport) -# else -# define GGPO_API __declspec(dllimport) -# endif -# else -# define GGPO_API -# endif -#else +//#ifdef _WIN32 +//# if defined(GGPO_SHARED_LIB) +//# ifdef GGPO_SDK_EXPORT +//# define GGPO_API __declspec(dllexport) +//# else +//# define GGPO_API __declspec(dllimport) +//# endif +//# else +//# define GGPO_API +//# endif +//#else # define GGPO_API -#endif +//#endif #define GGPO_MAX_PLAYERS 4 #define GGPO_MAX_PREDICTION_FRAMES 8 From 4ed161eeb9e124fcb24acd180db4442592f2151f Mon Sep 17 00:00:00 2001 From: Tom Date: Sun, 9 Oct 2022 15:21:52 +0100 Subject: [PATCH 03/40] add win32 target --- GGPO.sln | 10 ++ src/GGPO.vcxproj | 140 ++++++++++++++++++++++++++- src/apps/vectorwar/VectorWar.vcxproj | 132 ++++++++++++++++++++++++- 3 files changed, 278 insertions(+), 4 deletions(-) diff --git a/GGPO.sln b/GGPO.sln index 91b1f9a3..03376f9d 100644 --- a/GGPO.sln +++ b/GGPO.sln @@ -13,17 +13,27 @@ EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 Release|x64 = Release|x64 + Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {1B89CCF2-963B-30F8-A86A-FB85A0BB8077}.Debug|x64.ActiveCfg = Debug|x64 {1B89CCF2-963B-30F8-A86A-FB85A0BB8077}.Debug|x64.Build.0 = Debug|x64 + {1B89CCF2-963B-30F8-A86A-FB85A0BB8077}.Debug|x86.ActiveCfg = Debug|Win32 + {1B89CCF2-963B-30F8-A86A-FB85A0BB8077}.Debug|x86.Build.0 = Debug|Win32 {1B89CCF2-963B-30F8-A86A-FB85A0BB8077}.Release|x64.ActiveCfg = Release|x64 {1B89CCF2-963B-30F8-A86A-FB85A0BB8077}.Release|x64.Build.0 = Release|x64 + {1B89CCF2-963B-30F8-A86A-FB85A0BB8077}.Release|x86.ActiveCfg = Release|Win32 + {1B89CCF2-963B-30F8-A86A-FB85A0BB8077}.Release|x86.Build.0 = Release|Win32 {58789CDC-C8E2-30F9-9FD6-8043C74C79E8}.Debug|x64.ActiveCfg = Debug|x64 {58789CDC-C8E2-30F9-9FD6-8043C74C79E8}.Debug|x64.Build.0 = Debug|x64 + {58789CDC-C8E2-30F9-9FD6-8043C74C79E8}.Debug|x86.ActiveCfg = Debug|Win32 + {58789CDC-C8E2-30F9-9FD6-8043C74C79E8}.Debug|x86.Build.0 = Debug|Win32 {58789CDC-C8E2-30F9-9FD6-8043C74C79E8}.Release|x64.ActiveCfg = Release|x64 {58789CDC-C8E2-30F9-9FD6-8043C74C79E8}.Release|x64.Build.0 = Release|x64 + {58789CDC-C8E2-30F9-9FD6-8043C74C79E8}.Release|x86.ActiveCfg = Release|Win32 + {58789CDC-C8E2-30F9-9FD6-8043C74C79E8}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/src/GGPO.vcxproj b/src/GGPO.vcxproj index 0a558739..8d2862c9 100644 --- a/src/GGPO.vcxproj +++ b/src/GGPO.vcxproj @@ -4,10 +4,18 @@ x64 + + Debug + Win32 + Debug x64 + + Release + Win32 + Release x64 @@ -25,12 +33,22 @@ StaticLibrary MultiByte - v142 + v140_xp + + + StaticLibrary + MultiByte + v140_xp StaticLibrary MultiByte - v142 + v140_xp + + + StaticLibrary + MultiByte + v140_xp @@ -42,17 +60,27 @@ <_ProjectFileVersion>10.0.20506.1 $(ProjectDir)..\lib\$(Platform)\$(Configuration) + $(ProjectDir)..\lib\$(Platform)\$(Configuration) GGPO.dir\$(Configuration)\ GGPO + GGPO .lib + .lib true + true true + true $(ProjectDir)..\lib\$(Platform)\$(Configuration) + $(ProjectDir)..\lib\$(Platform)\$(Configuration) GGPO.dir\$(Configuration)\ GGPO + GGPO .lib + .lib false + false true + true @@ -103,6 +131,58 @@ false + + + $(ProjectDir)include;$(ProjectDir)lib\ggpo;%(AdditionalIncludeDirectories) + %(AdditionalOptions) /bigobj + $(IntDir) + EnableFastChecks + false + EditAndContinue + 4577;4530 + Sync + Disabled + true + Disabled + NotUsing + MultiThreadedDebugDLL + true + true + true + false + Level4 + WIN32;_WINDOWS;GGPO_SHARED_LIB;GGPO_SDK_EXPORT;CMAKE_INTDIR="Debug";GGPO_EXPORTS;%(PreprocessorDefinitions) + $(IntDir) + + + WIN32;_DEBUG;_WINDOWS;GGPO_SHARED_LIB;GGPO_SDK_EXPORT;CMAKE_INTDIR=\"Debug\";GGPO_EXPORTS;%(PreprocessorDefinitions) + $(ProjectDir)include;$(ProjectDir)lib\ggpo;%(AdditionalIncludeDirectories) + + + $(ProjectDir)include;$(ProjectDir)lib\ggpo;%(AdditionalIncludeDirectories) + $(ProjectDir)/$(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + winmm.lib;ws2_32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;comdlg32.lib;advapi32.lib + %(AdditionalLibraryDirectories) + %(AdditionalOptions) /machine:x64 + true + %(IgnoreSpecificDefaultLibraries) + $(ProjectDir)$(Platform)\$(Configuration)\GGPO.lib + $(ProjectDir)$(Platform)\$(Configuration)\GGPO.pdb + Console + + + false + + + MachineX86 + + $(ProjectDir)include;$(ProjectDir)lib\ggpo;%(AdditionalIncludeDirectories) @@ -156,6 +236,62 @@ false + + + $(ProjectDir)include;$(ProjectDir)lib\ggpo;%(AdditionalIncludeDirectories) + %(AdditionalOptions) /bigobj + $(IntDir) + false + ProgramDatabase + 4577;4530 + Sync + true + AnySuitable + true + true + MaxSpeed + NotUsing + MultiThreadedDLL + true + true + true + false + Level4 + true + WIN32;_WINDOWS;NDEBUG;GGPO_SHARED_LIB;GGPO_SDK_EXPORT;CMAKE_INTDIR="Release";GGPO_EXPORTS;%(PreprocessorDefinitions) + $(IntDir) + + + WIN32;_WINDOWS;NDEBUG;GGPO_SHARED_LIB;GGPO_SDK_EXPORT;CMAKE_INTDIR=\"Release\";GGPO_EXPORTS;%(PreprocessorDefinitions) + $(ProjectDir)include;$(ProjectDir)lib\ggpo;%(AdditionalIncludeDirectories) + + + $(ProjectDir)include;$(ProjectDir)lib\ggpo;%(AdditionalIncludeDirectories) + $(ProjectDir)/$(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + winmm.lib;ws2_32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;comdlg32.lib;advapi32.lib + %(AdditionalLibraryDirectories) + %(AdditionalOptions) /machine:x64 + true + %(IgnoreSpecificDefaultLibraries) + $(ProjectDir)$(Platform)\$(Configuration)\GGPO.lib + UseLinkTimeCodeGeneration + true + $(ProjectDir)$(Platform)\$(Configuration)\GGPO.pdb + Console + + + false + + + MachineX86 + + diff --git a/src/apps/vectorwar/VectorWar.vcxproj b/src/apps/vectorwar/VectorWar.vcxproj index 9fb49049..453d3314 100644 --- a/src/apps/vectorwar/VectorWar.vcxproj +++ b/src/apps/vectorwar/VectorWar.vcxproj @@ -4,10 +4,18 @@ x64 + + Debug + Win32 + Debug x64 + + Release + Win32 + Release x64 @@ -25,12 +33,22 @@ Application Unicode - v142 + v140_xp + + + Application + Unicode + v140_xp Application Unicode - v142 + v140_xp + + + Application + Unicode + v140_xp @@ -42,17 +60,27 @@ <_ProjectFileVersion>10.0.20506.1 $(ProjectDir)..\..\..\bin\$(Platform)\$(Configuration) + $(ProjectDir)..\..\..\bin\$(Platform)\$(Configuration) VectorWar.dir\Debug\ VectorWar + VectorWar .exe + .exe true + true true + true $(ProjectDir)..\..\..\bin\$(Platform)\$(Configuration) + $(ProjectDir)..\..\..\bin\$(Platform)\$(Configuration) VectorWar.dir\Release\ VectorWar + VectorWar .exe + .exe false + false true + true @@ -101,6 +129,54 @@ false + + + ..\..\include;..\..\lib\ggpo;%(AdditionalIncludeDirectories) + %(AdditionalOptions) /bigobj + $(IntDir) + EnableFastChecks + false + EditAndContinue + 4577;4530 + Sync + Disabled + true + Disabled + NotUsing + MultiThreadedDebugDLL + true + true + true + false + Level4 + WIN32;_WINDOWS;GGPO_SHARED_LIB;_UNICODE;UNICODE;CMAKE_INTDIR="Debug";%(PreprocessorDefinitions) + $(IntDir) + + + WIN32;_DEBUG;_WINDOWS;GGPO_SHARED_LIB;_UNICODE;UNICODE;CMAKE_INTDIR=\"Debug\";%(PreprocessorDefinitions) + ..\..\include;..\..\lib\ggpo;%(AdditionalIncludeDirectories) + + + ..\..\include;..\..\lib\ggpo;%(AdditionalIncludeDirectories) + $(ProjectDir)/$(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + GGPO.lib;winmm.lib;ws2_32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;comdlg32.lib;advapi32.lib + $(ProjectDir)..\..\..\lib\$(Platform)\$(Configuration);%(AdditionalLibraryDirectories) + %(AdditionalOptions) /machine:x86 + true + %(IgnoreSpecificDefaultLibraries) + Windows + MachineX86 + + + false + + ..\..\include;..\..\lib\ggpo;%(AdditionalIncludeDirectories) @@ -153,6 +229,58 @@ false + + + ..\..\include;..\..\lib\ggpo;%(AdditionalIncludeDirectories) + %(AdditionalOptions) /bigobj + $(IntDir) + false + ProgramDatabase + 4577;4530 + Sync + true + AnySuitable + true + true + MaxSpeed + NotUsing + MultiThreadedDLL + true + true + true + false + Level4 + true + WIN32;_WINDOWS;NDEBUG;GGPO_SHARED_LIB;_UNICODE;UNICODE;CMAKE_INTDIR="Release";%(PreprocessorDefinitions) + $(IntDir) + + + WIN32;_WINDOWS;NDEBUG;GGPO_SHARED_LIB;_UNICODE;UNICODE;CMAKE_INTDIR=\"Release\";%(PreprocessorDefinitions) + ..\..\include;..\..lib\ggpo;%(AdditionalIncludeDirectories) + + + ..\..\include;..\..\lib\ggpo;%(AdditionalIncludeDirectories) + $(ProjectDir)/$(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + GGPO.lib;winmm.lib;ws2_32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;comdlg32.lib;advapi32.lib + $(ProjectDir)..\..\..\lib\$(Platform)\$(Configuration);%(AdditionalLibraryDirectories) + %(AdditionalOptions) /machine:x86 + true + %(IgnoreSpecificDefaultLibraries) + ..\..\lib/x64/Release/VectorWar.lib + UseLinkTimeCodeGeneration + true + Windows + + + false + + From 2974ba642dc49e63355096413979085cbef03556 Mon Sep 17 00:00:00 2001 From: Tom Date: Sun, 9 Oct 2022 20:07:37 +0100 Subject: [PATCH 04/40] rename to ggpo-x --- GGPO.sln => GGPO-x.sln | 20 ++++---- src/{GGPO.vcxproj => GGPO-x.vcxproj} | 46 +++++++++--------- ...vcxproj.filters => GGPO-x.vcxproj.filters} | 0 src/apps/vectorwar/VectorWar.vcxproj | 48 +++++++++---------- 4 files changed, 57 insertions(+), 57 deletions(-) rename GGPO.sln => GGPO-x.sln (94%) rename src/{GGPO.vcxproj => GGPO-x.vcxproj} (94%) rename src/{GGPO.vcxproj.filters => GGPO-x.vcxproj.filters} (100%) diff --git a/GGPO.sln b/GGPO-x.sln similarity index 94% rename from GGPO.sln rename to GGPO-x.sln index 03376f9d..cfc6dde7 100644 --- a/GGPO.sln +++ b/GGPO-x.sln @@ -3,13 +3,13 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 VisualStudioVersion = 17.3.32922.545 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GGPO", "src\GGPO.vcxproj", "{1B89CCF2-963B-30F8-A86A-FB85A0BB8077}" -EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "VectorWar", "src\apps\vectorwar\VectorWar.vcxproj", "{58789CDC-C8E2-30F9-9FD6-8043C74C79E8}" ProjectSection(ProjectDependencies) = postProject {1B89CCF2-963B-30F8-A86A-FB85A0BB8077} = {1B89CCF2-963B-30F8-A86A-FB85A0BB8077} EndProjectSection EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GGPO-x", "src\GGPO-x.vcxproj", "{1B89CCF2-963B-30F8-A86A-FB85A0BB8077}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|x64 = Debug|x64 @@ -18,14 +18,6 @@ Global Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {1B89CCF2-963B-30F8-A86A-FB85A0BB8077}.Debug|x64.ActiveCfg = Debug|x64 - {1B89CCF2-963B-30F8-A86A-FB85A0BB8077}.Debug|x64.Build.0 = Debug|x64 - {1B89CCF2-963B-30F8-A86A-FB85A0BB8077}.Debug|x86.ActiveCfg = Debug|Win32 - {1B89CCF2-963B-30F8-A86A-FB85A0BB8077}.Debug|x86.Build.0 = Debug|Win32 - {1B89CCF2-963B-30F8-A86A-FB85A0BB8077}.Release|x64.ActiveCfg = Release|x64 - {1B89CCF2-963B-30F8-A86A-FB85A0BB8077}.Release|x64.Build.0 = Release|x64 - {1B89CCF2-963B-30F8-A86A-FB85A0BB8077}.Release|x86.ActiveCfg = Release|Win32 - {1B89CCF2-963B-30F8-A86A-FB85A0BB8077}.Release|x86.Build.0 = Release|Win32 {58789CDC-C8E2-30F9-9FD6-8043C74C79E8}.Debug|x64.ActiveCfg = Debug|x64 {58789CDC-C8E2-30F9-9FD6-8043C74C79E8}.Debug|x64.Build.0 = Debug|x64 {58789CDC-C8E2-30F9-9FD6-8043C74C79E8}.Debug|x86.ActiveCfg = Debug|Win32 @@ -34,6 +26,14 @@ Global {58789CDC-C8E2-30F9-9FD6-8043C74C79E8}.Release|x64.Build.0 = Release|x64 {58789CDC-C8E2-30F9-9FD6-8043C74C79E8}.Release|x86.ActiveCfg = Release|Win32 {58789CDC-C8E2-30F9-9FD6-8043C74C79E8}.Release|x86.Build.0 = Release|Win32 + {1B89CCF2-963B-30F8-A86A-FB85A0BB8077}.Debug|x64.ActiveCfg = Debug|x64 + {1B89CCF2-963B-30F8-A86A-FB85A0BB8077}.Debug|x64.Build.0 = Debug|x64 + {1B89CCF2-963B-30F8-A86A-FB85A0BB8077}.Debug|x86.ActiveCfg = Debug|Win32 + {1B89CCF2-963B-30F8-A86A-FB85A0BB8077}.Debug|x86.Build.0 = Debug|Win32 + {1B89CCF2-963B-30F8-A86A-FB85A0BB8077}.Release|x64.ActiveCfg = Release|x64 + {1B89CCF2-963B-30F8-A86A-FB85A0BB8077}.Release|x64.Build.0 = Release|x64 + {1B89CCF2-963B-30F8-A86A-FB85A0BB8077}.Release|x86.ActiveCfg = Release|Win32 + {1B89CCF2-963B-30F8-A86A-FB85A0BB8077}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/src/GGPO.vcxproj b/src/GGPO-x.vcxproj similarity index 94% rename from src/GGPO.vcxproj rename to src/GGPO-x.vcxproj index 8d2862c9..e02e0694 100644 --- a/src/GGPO.vcxproj +++ b/src/GGPO-x.vcxproj @@ -26,7 +26,7 @@ 10.0.19041.0 Win32Proj x64 - GGPO + GGPO-x NoUpgrade @@ -61,9 +61,9 @@ <_ProjectFileVersion>10.0.20506.1 $(ProjectDir)..\lib\$(Platform)\$(Configuration) $(ProjectDir)..\lib\$(Platform)\$(Configuration) - GGPO.dir\$(Configuration)\ - GGPO - GGPO + GGPO-x.dir\$(Configuration)\ + GGPO-x + GGPO-x .lib .lib true @@ -72,9 +72,9 @@ true $(ProjectDir)..\lib\$(Platform)\$(Configuration) $(ProjectDir)..\lib\$(Platform)\$(Configuration) - GGPO.dir\$(Configuration)\ - GGPO - GGPO + GGPO-x.dir\$(Configuration)\ + GGPO-x + GGPO-x .lib .lib false @@ -107,10 +107,10 @@ WIN32;_DEBUG;_WINDOWS;GGPO_SHARED_LIB;GGPO_SDK_EXPORT;CMAKE_INTDIR=\"Debug\";GGPO_EXPORTS;%(PreprocessorDefinitions) - $(ProjectDir)include;$(ProjectDir)lib\ggpo;%(AdditionalIncludeDirectories) + $(ProjectDir)include;$(ProjectDir)lib\ggpo-x;%(AdditionalIncludeDirectories) - $(ProjectDir)include;$(ProjectDir)lib\ggpo;%(AdditionalIncludeDirectories) + $(ProjectDir)include;$(ProjectDir)lib\ggpo-x;%(AdditionalIncludeDirectories) $(ProjectDir)/$(IntDir) %(Filename).h %(Filename).tlb @@ -123,8 +123,8 @@ %(AdditionalOptions) /machine:x64 true %(IgnoreSpecificDefaultLibraries) - $(ProjectDir)$(Platform)\$(Configuration)\GGPO.lib - $(ProjectDir)$(Platform)\$(Configuration)\GGPO.pdb + $(ProjectDir)$(Platform)\$(Configuration)\GGPO-x.lib + $(ProjectDir)$(Platform)\$(Configuration)\GGPO-x.pdb Console @@ -156,10 +156,10 @@ WIN32;_DEBUG;_WINDOWS;GGPO_SHARED_LIB;GGPO_SDK_EXPORT;CMAKE_INTDIR=\"Debug\";GGPO_EXPORTS;%(PreprocessorDefinitions) - $(ProjectDir)include;$(ProjectDir)lib\ggpo;%(AdditionalIncludeDirectories) + $(ProjectDir)include;$(ProjectDir)lib\ggpo-x;%(AdditionalIncludeDirectories) - $(ProjectDir)include;$(ProjectDir)lib\ggpo;%(AdditionalIncludeDirectories) + $(ProjectDir)include;$(ProjectDir)lib\ggpo-x;%(AdditionalIncludeDirectories) $(ProjectDir)/$(IntDir) %(Filename).h %(Filename).tlb @@ -172,8 +172,8 @@ %(AdditionalOptions) /machine:x64 true %(IgnoreSpecificDefaultLibraries) - $(ProjectDir)$(Platform)\$(Configuration)\GGPO.lib - $(ProjectDir)$(Platform)\$(Configuration)\GGPO.pdb + $(ProjectDir)$(Platform)\$(Configuration)\GGPO-x.lib + $(ProjectDir)$(Platform)\$(Configuration)\GGPO-x.pdb Console @@ -210,10 +210,10 @@ WIN32;_WINDOWS;NDEBUG;GGPO_SHARED_LIB;GGPO_SDK_EXPORT;CMAKE_INTDIR=\"Release\";GGPO_EXPORTS;%(PreprocessorDefinitions) - $(ProjectDir)include;$(ProjectDir)lib\ggpo;%(AdditionalIncludeDirectories) + $(ProjectDir)include;$(ProjectDir)lib\ggpo-x;%(AdditionalIncludeDirectories) - $(ProjectDir)include;$(ProjectDir)lib\ggpo;%(AdditionalIncludeDirectories) + $(ProjectDir)include;$(ProjectDir)lib\ggpo-x;%(AdditionalIncludeDirectories) $(ProjectDir)/$(IntDir) %(Filename).h %(Filename).tlb @@ -226,10 +226,10 @@ %(AdditionalOptions) /machine:x64 true %(IgnoreSpecificDefaultLibraries) - $(ProjectDir)$(Platform)\$(Configuration)\GGPO.lib + $(ProjectDir)$(Platform)\$(Configuration)\GGPO-x.lib UseLinkTimeCodeGeneration true - $(ProjectDir)$(Platform)\$(Configuration)\GGPO.pdb + $(ProjectDir)$(Platform)\$(Configuration)\GGPO-x.pdb Console @@ -263,10 +263,10 @@ WIN32;_WINDOWS;NDEBUG;GGPO_SHARED_LIB;GGPO_SDK_EXPORT;CMAKE_INTDIR=\"Release\";GGPO_EXPORTS;%(PreprocessorDefinitions) - $(ProjectDir)include;$(ProjectDir)lib\ggpo;%(AdditionalIncludeDirectories) + $(ProjectDir)include;$(ProjectDir)lib\ggpo-x;%(AdditionalIncludeDirectories) - $(ProjectDir)include;$(ProjectDir)lib\ggpo;%(AdditionalIncludeDirectories) + $(ProjectDir)include;$(ProjectDir)lib\ggpo-x;%(AdditionalIncludeDirectories) $(ProjectDir)/$(IntDir) %(Filename).h %(Filename).tlb @@ -279,10 +279,10 @@ %(AdditionalOptions) /machine:x64 true %(IgnoreSpecificDefaultLibraries) - $(ProjectDir)$(Platform)\$(Configuration)\GGPO.lib + $(ProjectDir)$(Platform)\$(Configuration)\GGPO-x.lib UseLinkTimeCodeGeneration true - $(ProjectDir)$(Platform)\$(Configuration)\GGPO.pdb + $(ProjectDir)$(Platform)\$(Configuration)\GGPO-x.pdb Console diff --git a/src/GGPO.vcxproj.filters b/src/GGPO-x.vcxproj.filters similarity index 100% rename from src/GGPO.vcxproj.filters rename to src/GGPO-x.vcxproj.filters diff --git a/src/apps/vectorwar/VectorWar.vcxproj b/src/apps/vectorwar/VectorWar.vcxproj index 453d3314..ce49b1e6 100644 --- a/src/apps/vectorwar/VectorWar.vcxproj +++ b/src/apps/vectorwar/VectorWar.vcxproj @@ -84,7 +84,7 @@ - ..\..\include;..\..\lib\ggpo;%(AdditionalIncludeDirectories) + ..\..\include;..\..\lib\ggpo-x;%(AdditionalIncludeDirectories) %(AdditionalOptions) /bigobj $(IntDir) EnableFastChecks @@ -102,15 +102,15 @@ true false Level4 - WIN32;_WINDOWS;GGPO_SHARED_LIB;_UNICODE;UNICODE;CMAKE_INTDIR="Debug";%(PreprocessorDefinitions) + WIN32;_WINDOWS;ggpo-x_SHARED_LIB;_UNICODE;UNICODE;CMAKE_INTDIR="Debug";%(PreprocessorDefinitions) $(IntDir) - WIN32;_DEBUG;_WINDOWS;GGPO_SHARED_LIB;_UNICODE;UNICODE;CMAKE_INTDIR=\"Debug\";%(PreprocessorDefinitions) - ..\..\include;..\..\lib\ggpo;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_WINDOWS;ggpo-x_SHARED_LIB;_UNICODE;UNICODE;CMAKE_INTDIR=\"Debug\";%(PreprocessorDefinitions) + ..\..\include;..\..\lib\ggpo-x;%(AdditionalIncludeDirectories) - ..\..\include;..\..\lib\ggpo;%(AdditionalIncludeDirectories) + ..\..\include;..\..\lib\ggpo-x;%(AdditionalIncludeDirectories) $(ProjectDir)/$(IntDir) %(Filename).h %(Filename).tlb @@ -118,7 +118,7 @@ %(Filename)_p.c - GGPO.lib;winmm.lib;ws2_32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;comdlg32.lib;advapi32.lib + ggpo-x.lib;winmm.lib;ws2_32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;comdlg32.lib;advapi32.lib $(ProjectDir)..\..\..\lib\$(Platform)\$(Configuration);%(AdditionalLibraryDirectories) %(AdditionalOptions) /machine:x64 true @@ -131,7 +131,7 @@ - ..\..\include;..\..\lib\ggpo;%(AdditionalIncludeDirectories) + ..\..\include;..\..\lib\ggpo-x;%(AdditionalIncludeDirectories) %(AdditionalOptions) /bigobj $(IntDir) EnableFastChecks @@ -149,15 +149,15 @@ true false Level4 - WIN32;_WINDOWS;GGPO_SHARED_LIB;_UNICODE;UNICODE;CMAKE_INTDIR="Debug";%(PreprocessorDefinitions) + WIN32;_WINDOWS;ggpo-x_SHARED_LIB;_UNICODE;UNICODE;CMAKE_INTDIR="Debug";%(PreprocessorDefinitions) $(IntDir) - WIN32;_DEBUG;_WINDOWS;GGPO_SHARED_LIB;_UNICODE;UNICODE;CMAKE_INTDIR=\"Debug\";%(PreprocessorDefinitions) - ..\..\include;..\..\lib\ggpo;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_WINDOWS;ggpo-x_SHARED_LIB;_UNICODE;UNICODE;CMAKE_INTDIR=\"Debug\";%(PreprocessorDefinitions) + ..\..\include;..\..\lib\ggpo-x;%(AdditionalIncludeDirectories) - ..\..\include;..\..\lib\ggpo;%(AdditionalIncludeDirectories) + ..\..\include;..\..\lib\ggpo-x;%(AdditionalIncludeDirectories) $(ProjectDir)/$(IntDir) %(Filename).h %(Filename).tlb @@ -165,7 +165,7 @@ %(Filename)_p.c - GGPO.lib;winmm.lib;ws2_32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;comdlg32.lib;advapi32.lib + ggpo-x.lib;winmm.lib;ws2_32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;comdlg32.lib;advapi32.lib $(ProjectDir)..\..\..\lib\$(Platform)\$(Configuration);%(AdditionalLibraryDirectories) %(AdditionalOptions) /machine:x86 true @@ -179,7 +179,7 @@ - ..\..\include;..\..\lib\ggpo;%(AdditionalIncludeDirectories) + ..\..\include;..\..\lib\ggpo-x;%(AdditionalIncludeDirectories) %(AdditionalOptions) /bigobj $(IntDir) false @@ -199,15 +199,15 @@ false Level4 true - WIN32;_WINDOWS;NDEBUG;GGPO_SHARED_LIB;_UNICODE;UNICODE;CMAKE_INTDIR="Release";%(PreprocessorDefinitions) + WIN32;_WINDOWS;NDEBUG;ggpo-x_SHARED_LIB;_UNICODE;UNICODE;CMAKE_INTDIR="Release";%(PreprocessorDefinitions) $(IntDir) - WIN32;_WINDOWS;NDEBUG;GGPO_SHARED_LIB;_UNICODE;UNICODE;CMAKE_INTDIR=\"Release\";%(PreprocessorDefinitions) - ..\..\include;..\..lib\ggpo;%(AdditionalIncludeDirectories) + WIN32;_WINDOWS;NDEBUG;ggpo-x_SHARED_LIB;_UNICODE;UNICODE;CMAKE_INTDIR=\"Release\";%(PreprocessorDefinitions) + ..\..\include;..\..lib\ggpo-x;%(AdditionalIncludeDirectories) - ..\..\include;..\..\lib\ggpo;%(AdditionalIncludeDirectories) + ..\..\include;..\..\lib\ggpo-x;%(AdditionalIncludeDirectories) $(ProjectDir)/$(IntDir) %(Filename).h %(Filename).tlb @@ -215,7 +215,7 @@ %(Filename)_p.c - GGPO.lib;winmm.lib;ws2_32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;comdlg32.lib;advapi32.lib + ggpo-x.lib;winmm.lib;ws2_32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;comdlg32.lib;advapi32.lib $(ProjectDir)..\..\..\lib\$(Platform)\$(Configuration);%(AdditionalLibraryDirectories) %(AdditionalOptions) /machine:x64 true @@ -231,7 +231,7 @@ - ..\..\include;..\..\lib\ggpo;%(AdditionalIncludeDirectories) + ..\..\include;..\..\lib\ggpo-x;%(AdditionalIncludeDirectories) %(AdditionalOptions) /bigobj $(IntDir) false @@ -251,15 +251,15 @@ false Level4 true - WIN32;_WINDOWS;NDEBUG;GGPO_SHARED_LIB;_UNICODE;UNICODE;CMAKE_INTDIR="Release";%(PreprocessorDefinitions) + WIN32;_WINDOWS;NDEBUG;ggpo-x_SHARED_LIB;_UNICODE;UNICODE;CMAKE_INTDIR="Release";%(PreprocessorDefinitions) $(IntDir) - WIN32;_WINDOWS;NDEBUG;GGPO_SHARED_LIB;_UNICODE;UNICODE;CMAKE_INTDIR=\"Release\";%(PreprocessorDefinitions) - ..\..\include;..\..lib\ggpo;%(AdditionalIncludeDirectories) + WIN32;_WINDOWS;NDEBUG;ggpo-x_SHARED_LIB;_UNICODE;UNICODE;CMAKE_INTDIR=\"Release\";%(PreprocessorDefinitions) + ..\..\include;..\..lib\ggpo-x;%(AdditionalIncludeDirectories) - ..\..\include;..\..\lib\ggpo;%(AdditionalIncludeDirectories) + ..\..\include;..\..\lib\ggpo-x;%(AdditionalIncludeDirectories) $(ProjectDir)/$(IntDir) %(Filename).h %(Filename).tlb @@ -267,7 +267,7 @@ %(Filename)_p.c - GGPO.lib;winmm.lib;ws2_32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;comdlg32.lib;advapi32.lib + ggpo-x.lib;winmm.lib;ws2_32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;comdlg32.lib;advapi32.lib $(ProjectDir)..\..\..\lib\$(Platform)\$(Configuration);%(AdditionalLibraryDirectories) %(AdditionalOptions) /machine:x86 true From 902fea60625eee8e17904d1cfc4bece047d5f39c Mon Sep 17 00:00:00 2001 From: Tom Date: Sun, 9 Oct 2022 21:00:27 +0100 Subject: [PATCH 05/40] Add ggpo-x submodule --- .gitmodules | 3 +++ ggpo-x | 1 + 2 files changed, 4 insertions(+) create mode 100644 .gitmodules create mode 160000 ggpo-x diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 00000000..ccf7ab3b --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "ggpo-x"] + path = ggpo-x + url = https://github.com/thomashenry79/ggpo-x diff --git a/ggpo-x b/ggpo-x new file mode 160000 index 00000000..2974ba64 --- /dev/null +++ b/ggpo-x @@ -0,0 +1 @@ +Subproject commit 2974ba642dc49e63355096413979085cbef03556 From 7d2837fe7450eecfa0977ba25d42947baea9d548 Mon Sep 17 00:00:00 2001 From: Tom Date: Sun, 9 Oct 2022 21:09:28 +0100 Subject: [PATCH 06/40] remove mistake --- .gitmodules | 3 --- ggpo-x | 1 - 2 files changed, 4 deletions(-) delete mode 160000 ggpo-x diff --git a/.gitmodules b/.gitmodules index ccf7ab3b..e69de29b 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +0,0 @@ -[submodule "ggpo-x"] - path = ggpo-x - url = https://github.com/thomashenry79/ggpo-x diff --git a/ggpo-x b/ggpo-x deleted file mode 160000 index 2974ba64..00000000 --- a/ggpo-x +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 2974ba642dc49e63355096413979085cbef03556 From 2e23cae8abfca1eac59989f66bbd2b4e1bd22595 Mon Sep 17 00:00:00 2001 From: Tom Date: Sun, 9 Oct 2022 21:30:21 +0100 Subject: [PATCH 07/40] remove dead code --- src/lib/ggpo/poll.cpp | 21 ++------------------- src/lib/ggpo/poll.h | 5 ----- 2 files changed, 2 insertions(+), 24 deletions(-) diff --git a/src/lib/ggpo/poll.cpp b/src/lib/ggpo/poll.cpp index 7468d6a4..46397abe 100644 --- a/src/lib/ggpo/poll.cpp +++ b/src/lib/ggpo/poll.cpp @@ -9,24 +9,11 @@ #include "poll.h" Poll::Poll(void) : - _handle_count(0), _start_time(0) { - /* - * Create a dummy handle to simplify things. - */ - _handles[_handle_count++] = CreateEvent(NULL, true, false, NULL); } -void -Poll::RegisterHandle(IPollSink *sink, HANDLE h, void *cookie) -{ - ASSERT(_handle_count < MAX_POLLABLE_HANDLES - 1); - _handles[_handle_count] = h; - _handle_sinks[_handle_count] = PollSinkCb(sink, cookie); - _handle_count++; -} void Poll::RegisterMsgLoop(IPollSink *sink, void *cookie) @@ -56,7 +43,7 @@ Poll::Run() bool Poll::Pump(int timeout) { - int i, res; + int i; bool finished = false; if (_start_time == 0) { @@ -68,11 +55,7 @@ Poll::Pump(int timeout) timeout = MIN(timeout, maxwait); } - res = WaitForMultipleObjects(_handle_count, _handles, false, timeout); - if (res >= WAIT_OBJECT_0 && res < WAIT_OBJECT_0 + _handle_count) { - i = res - WAIT_OBJECT_0; - finished = !_handle_sinks[i].sink->OnHandlePoll(_handle_sinks[i].cookie) || finished; - } + for (i = 0; i < _msg_sinks.size(); i++) { PollSinkCb &cb = _msg_sinks[i]; finished = !cb.sink->OnMsgPoll(cb.cookie) || finished; diff --git a/src/lib/ggpo/poll.h b/src/lib/ggpo/poll.h index 3ef21083..20608d60 100644 --- a/src/lib/ggpo/poll.h +++ b/src/lib/ggpo/poll.h @@ -16,7 +16,6 @@ class IPollSink { public: virtual ~IPollSink() { } - virtual bool OnHandlePoll(void *) { return true; } virtual bool OnMsgPoll(void *) { return true; } virtual bool OnPeriodicPoll(void *, int ) { return true; } virtual bool OnLoopPoll(void *) { return true; } @@ -25,7 +24,6 @@ class IPollSink { class Poll { public: Poll(void); - void RegisterHandle(IPollSink *sink, HANDLE h, void *cookie = NULL); void RegisterMsgLoop(IPollSink *sink, void *cookie = NULL); void RegisterPeriodic(IPollSink *sink, int interval, void *cookie = NULL); void RegisterLoop(IPollSink *sink, void *cookie = NULL); @@ -52,9 +50,6 @@ class Poll { }; int _start_time; - int _handle_count; - HANDLE _handles[MAX_POLLABLE_HANDLES]; - PollSinkCb _handle_sinks[MAX_POLLABLE_HANDLES]; StaticBuffer _msg_sinks; StaticBuffer _loop_sinks; From 1038af3b80d1cb32f031649ae04238751a586340 Mon Sep 17 00:00:00 2001 From: Tom Date: Mon, 10 Oct 2022 00:09:07 +0100 Subject: [PATCH 08/40] Big changes --- src/apps/vectorwar/gdi_renderer.cpp | 36 ++++++++++- src/apps/vectorwar/ggpo_perfmon.cpp | 14 ++--- src/apps/vectorwar/main.cpp | 15 +++-- src/apps/vectorwar/nongamestate.h | 86 ++++++++++++++++++++++--- src/apps/vectorwar/vectorwar.cpp | 76 +++++++++++++++++----- src/apps/vectorwar/vectorwar.h | 4 +- src/include/ggponet.h | 45 +++++++------ src/lib/ggpo/backends/backend.h | 2 +- src/lib/ggpo/backends/p2p.cpp | 34 +++++----- src/lib/ggpo/backends/p2p.h | 4 +- src/lib/ggpo/backends/synctest.cpp | 4 +- src/lib/ggpo/bitvector.cpp | 1 + src/lib/ggpo/main.cpp | 10 +-- src/lib/ggpo/network/udp_proto.cpp | 30 +++++---- src/lib/ggpo/network/udp_proto.h | 14 +++-- src/lib/ggpo/poll.cpp | 21 ++++++- src/lib/ggpo/poll.h | 5 ++ src/lib/ggpo/sync.cpp | 28 ++++----- src/lib/ggpo/sync.h | 15 +++-- src/lib/ggpo/timesync.cpp | 98 +++++++++++++++++++---------- src/lib/ggpo/timesync.h | 22 +++++-- 21 files changed, 400 insertions(+), 164 deletions(-) diff --git a/src/apps/vectorwar/gdi_renderer.cpp b/src/apps/vectorwar/gdi_renderer.cpp index 77db4987..0b27b49c 100644 --- a/src/apps/vectorwar/gdi_renderer.cpp +++ b/src/apps/vectorwar/gdi_renderer.cpp @@ -57,12 +57,46 @@ GDIRenderer::Draw(GameState &gs, NonGameState &ngs) SetTextAlign(hdc, TA_BOTTOM | TA_CENTER); TextOutA(hdc, (_rc.left + _rc.right) / 2, _rc.bottom - 32, _status, (int)strlen(_status)); - + SetTextColor(hdc, RGB(192, 192, 192)); RenderChecksum(hdc, 40, ngs.periodic); SetTextColor(hdc, RGB(128, 128, 128)); RenderChecksum(hdc, 56, ngs.now); + char statsinfo[128]; + sprintf_s(statsinfo, + ARRAYSIZE(statsinfo), + "Input Delay: %d, Local adv: %.1f,remote adv: %.1f", + ngs.inputDelay, + ngs.stats.timesync.local_frames_behind, + ngs.stats.timesync.remote_frames_behind); + TextOutA(hdc, (_rc.left + _rc.right) / 2, _rc.top + 72, statsinfo, (int)strlen(statsinfo)); + + sprintf_s(statsinfo, ARRAYSIZE(statsinfo), "Rbcks: %i, tsyncs: %i, ntsyncs: %i, inputreject: %d, RTT: %d, total fr dly :%.1f", ngs.nRollbacks, ngs.nTimeSyncs,ngs.nonTimeSyncs,ngs.inputDelays, ngs.stats.network.ping, ngs.totalFrameDelays); + + TextOutA(hdc, (_rc.left + _rc.right) / 2, _rc.top + 88, statsinfo, (int)strlen(statsinfo)); + sprintf_s(statsinfo, + ARRAYSIZE(statsinfo), + "Average advantage difference: %.2f", + ngs.stats.timesync.avg_local_frames_behind- ngs.stats.timesync.avg_remote_frames_behind); + TextOutA(hdc, (_rc.left + _rc.right) / 2, _rc.top + 102, statsinfo, (int)strlen(statsinfo)); + auto ms = ngs.loopTimer.slowdown(); + ms; + { + sprintf_s(statsinfo, ARRAYSIZE(statsinfo), "Slowing frame by %.2fpc", ngs.loopTimer.slowDownPC()); + if(ms == 0) + SetTextColor(hdc, RGB(255, 255, 0)); + else + SetTextColor(hdc, RGB(0, 255, 0)); + TextOutA(hdc, _rc.left+50 , _rc.top+ 56 , statsinfo, (int)strlen(statsinfo)); + } + sprintf_s(statsinfo, ARRAYSIZE(statsinfo), "Rollback count by size:"); + TextOutA(hdc, _rc.left+50 , _rc.top+ 72 , statsinfo, (int)strlen(statsinfo)); + for (auto i = 1u; i < ngs.rollbacksBySize.size(); i++) + { + sprintf_s(statsinfo, ARRAYSIZE(statsinfo), "%d: %d",i, ngs.rollbacksBySize[i]); + TextOutA(hdc, _rc.left + 50, _rc.top + 72+(16*i), statsinfo, (int)strlen(statsinfo)); + } //SwapBuffers(hdc); ReleaseDC(_hwnd, hdc); } diff --git a/src/apps/vectorwar/ggpo_perfmon.cpp b/src/apps/vectorwar/ggpo_perfmon.cpp index a66d612b..b06284fd 100644 --- a/src/apps/vectorwar/ggpo_perfmon.cpp +++ b/src/apps/vectorwar/ggpo_perfmon.cpp @@ -3,7 +3,7 @@ #include "resource.h" #include "ggponet.h" #include "ggpo_perfmon.h" - +#include #define MAX_GRAPH_SIZE 4096 #define MAX_FAIRNESS 20 #define MAX_PLAYERS 4 @@ -190,13 +190,13 @@ ggpoutil_perfmon_update(GGPOSession *ggpo, GGPOPlayerHandle players[], int num_p /* * Frame Advantage */ - _local_fairness_graph[j][i] = stats.timesync.local_frames_behind; - _remote_fairness_graph[j][i] = stats.timesync.remote_frames_behind; + _local_fairness_graph[j][i] = std::lround (stats.timesync.local_frames_behind); + _remote_fairness_graph[j][i] = std::lround(stats.timesync.remote_frames_behind); if (stats.timesync.local_frames_behind < 0 && stats.timesync.remote_frames_behind < 0) { /* * Both think it's unfair (which, ironically, is fair). Scale both and subtrace. */ - _fairness_graph[i] = abs(abs(stats.timesync.local_frames_behind) - abs(stats.timesync.remote_frames_behind)); + _fairness_graph[i] = std::lround(fabs(std::fabs(stats.timesync.local_frames_behind) - std::fabs(stats.timesync.remote_frames_behind))); } else if (stats.timesync.local_frames_behind > 0 && stats.timesync.remote_frames_behind > 0) { /* * Impossible! Unless the network has negative transmit time. Odd.... @@ -206,7 +206,7 @@ ggpoutil_perfmon_update(GGPOSession *ggpo, GGPOPlayerHandle players[], int num_p /* * They disagree. Add. */ - _fairness_graph[i] = abs(stats.timesync.local_frames_behind) + abs(stats.timesync.remote_frames_behind); + _fairness_graph[i] = std::lround(std::abs(stats.timesync.local_frames_behind) + std::abs(stats.timesync.remote_frames_behind)); } } @@ -222,8 +222,8 @@ ggpoutil_perfmon_update(GGPOSession *ggpo, GGPOPlayerHandle players[], int num_p sprintf_s(msLag, ARRAYSIZE(msLag), "%d ms", stats.network.ping); sprintf_s(frameLag, ARRAYSIZE(frameLag), "%.1f frames", stats.network.ping ? stats.network.ping * 60.0 / 1000 : 0); sprintf_s(fBandwidth, ARRAYSIZE(fBandwidth), "%.2f kilobytes/sec", stats.network.kbps_sent / 8.0); - sprintf_s(fLocal, ARRAYSIZE(fLocal), "%d frames", stats.timesync.local_frames_behind); - sprintf_s(fRemote, ARRAYSIZE(fRemote), "%d frames", stats.timesync.remote_frames_behind); + sprintf_s(fLocal, ARRAYSIZE(fLocal), "%.1f frames", stats.timesync.local_frames_behind); + sprintf_s(fRemote, ARRAYSIZE(fRemote), "%.1f frames", stats.timesync.remote_frames_behind); SetWindowTextA(GetDlgItem(_dialog, IDC_NETWORK_LAG), msLag); SetWindowTextA(GetDlgItem(_dialog, IDC_FRAME_LAG), frameLag); SetWindowTextA(GetDlgItem(_dialog, IDC_BANDWIDTH), fBandwidth); diff --git a/src/apps/vectorwar/main.cpp b/src/apps/vectorwar/main.cpp index 59d378be..e3147227 100644 --- a/src/apps/vectorwar/main.cpp +++ b/src/apps/vectorwar/main.cpp @@ -5,7 +5,7 @@ #endif #include "vectorwar.h" #include "ggpo_perfmon.h" - +#include LRESULT CALLBACK MainWindowProc(HWND hwnd, UINT uMsg, @@ -61,14 +61,13 @@ CreateMainWindow(HINSTANCE hInstance) SetWindowPos(hwnd, NULL, 0, 0, width + (width - (rc.right - rc.left)), height + (height - (rc.bottom - rc.top)), SWP_NOMOVE); return hwnd; } - void RunMainLoop(HWND hwnd) { MSG msg = { 0 }; - int start, next, now; + std::chrono::steady_clock::time_point start, next, now; - start = next = now = timeGetTime(); + start = next = now = std::chrono::high_resolution_clock::now(); while(1) { while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { TranslateMessage(&msg); @@ -77,11 +76,11 @@ RunMainLoop(HWND hwnd) return; } } - now = timeGetTime(); - VectorWar_Idle(max(0, next - now - 1)); + now = std::chrono::high_resolution_clock::now(); if (now >= next) { - VectorWar_RunFrame(hwnd); - next = now + (1000 / 60); + int usToWait; + VectorWar_RunFrame(hwnd, usToWait); + next = now + std::chrono::microseconds(usToWait); } } } diff --git a/src/apps/vectorwar/nongamestate.h b/src/apps/vectorwar/nongamestate.h index 17ab48b1..d5e11a36 100644 --- a/src/apps/vectorwar/nongamestate.h +++ b/src/apps/vectorwar/nongamestate.h @@ -2,9 +2,8 @@ #define _NON_GAMESTATE_H_ #include "ggponet.h" - #define MAX_PLAYERS 64 - +#include /* * nongamestate.h -- * @@ -13,6 +12,72 @@ * included in the GameState class because they specifically * should not be rolled back. */ +struct LoopTimer +{ +public: + + void Init(unsigned int fps, unsigned int framesToSpreadWait) + { + m_usPerGameLoop = 1000000 / fps; + m_usAhead = 0; + m_usExtraToWait = 0; + m_framesToSpreadWait = framesToSpreadWait; + lastAdvantage = 0.0f; + + } + void OnGGPOTimeSyncEvent(float framesAhead) + { + lastAdvantage = /*(int)*/(1000.0f * framesAhead / 60.0f); + + m_usExtraToWait = (int)(lastAdvantage*1000); + if (m_usExtraToWait) + { + m_usExtraToWait /= m_framesToSpreadWait; + m_WaitCount = m_framesToSpreadWait; + } + /*if (framesAhead < 0.5f) + m_usExtraToWait = 0; + else + m_usExtraToWait = (int)(framesAhead*800); + + m_usExtraToWait = min(3000, m_usExtraToWait);*/ + ////const int framesToSpreadover = 150; + //m_usAhead = (int)((framesAhead)*(float)m_usPerGameLoop); + //m_usExtraToWait = max(1, m_usAhead / m_framesToSpreadWait); + //m_WaitCount = m_framesToSpreadWait; + //char str[256]; + //sprintf_s<256>(str, "We are %.2f frames (%dus) ahead and will wait an extra %dus per frame for %d frames\n", framesAhead, m_usAhead, m_usExtraToWait, m_framesToSpreadWait); + //OutputDebugStringA(str); + } + float slowDownPC() const + { + return m_usExtraToWait * 100.0f / m_usPerGameLoop; + } + unsigned int slowdown() const + { + return m_WaitCount ? m_usExtraToWait : 0; + } + + // Call every loop, to get the amount of time the current iteration of gameloop should take + unsigned int usToWaitThisLoop() + { + auto timetoWait = m_usPerGameLoop; + if (m_WaitCount) { + timetoWait += m_usExtraToWait; + m_WaitCount--; + if (!m_WaitCount) + m_usExtraToWait = 0; + } + return timetoWait; + } + + float lastAdvantage = 0.0f; + unsigned int m_usPerGameLoop; + int m_usAhead; + unsigned int m_usExtraToWait; + unsigned int m_framesToSpreadWait; + unsigned int m_WaitCount = 0; +}; enum PlayerConnectState { Connecting = 0, @@ -33,10 +98,11 @@ struct PlayerConnectionInfo { struct NonGameState { struct ChecksumInfo { - int framenumber; - int checksum; + int framenumber=0; + int checksum=0; }; - + LoopTimer loopTimer; + GGPONetworkStats stats; void SetConnectState(GGPOPlayerHandle handle, PlayerConnectState state) { for (int i = 0; i < num_players; i++) { if (players[i].handle == handle) { @@ -72,11 +138,17 @@ struct NonGameState { } } } - + std::array rollbacksBySize = {0,0,0,0,0,0,0,0,0,0}; GGPOPlayerHandle local_player_handle; + GGPOPlayerHandle remote_player_handle; PlayerConnectionInfo players[MAX_PLAYERS]; + int inputDelay; + int inputDelays = 0; int num_players; - + int nRollbacks = 0; + int nTimeSyncs = 0; + int nonTimeSyncs = 0; + float totalFrameDelays = 0; ChecksumInfo now; ChecksumInfo periodic; }; diff --git a/src/apps/vectorwar/vectorwar.cpp b/src/apps/vectorwar/vectorwar.cpp index e52831bc..c23e5785 100644 --- a/src/apps/vectorwar/vectorwar.cpp +++ b/src/apps/vectorwar/vectorwar.cpp @@ -11,7 +11,7 @@ #define MAX_PLAYERS 64 GameState gs = { 0 }; -NonGameState ngs = { 0 }; +NonGameState ngs;// { 0 }; Renderer *renderer = NULL; GGPOSession *ggpo = NULL; @@ -92,7 +92,16 @@ vw_on_event_callback(GGPOEvent *info) ngs.SetConnectState(info->u.disconnected.player, Disconnected); break; case GGPO_EVENTCODE_TIMESYNC: - Sleep(1000 * info->u.timesync.frames_ahead / 60); + ngs.loopTimer.OnGGPOTimeSyncEvent(info->u.timesync.frames_ahead); + if (info->u.timesync.frames_ahead > 0) { + // Sleep(max(1, (int)(1000.0f * info->u.timesync.frames_ahead / 60.f))); + ngs.nTimeSyncs++; + ngs.totalFrameDelays += info->u.timesync.frames_ahead; + } + else + { + ngs.nonTimeSyncs++; + } break; } return true; @@ -110,7 +119,7 @@ vw_advance_frame_callback(int) { int inputs[MAX_SHIPS] = { 0 }; int disconnect_flags; - + // OutputDebugStringA("Advance one rollback frame\n"); // Make sure we fetch new inputs from GGPO and use those to update // the game state instead of reading from the keyboard. ggpo_synchronize_input(ggpo, (void *)inputs, sizeof(int) * MAX_SHIPS, &disconnect_flags); @@ -124,8 +133,12 @@ vw_advance_frame_callback(int) * Makes our current state match the state passed in by GGPO. */ bool __cdecl -vw_load_game_state_callback(unsigned char *buffer, int len) +vw_load_game_state_callback(unsigned char *buffer, int len, int nFrames) { + if (nFrames < 10) + ngs.rollbacksBySize[nFrames]++; + ngs.nRollbacks++; + // OutputDebugStringA("Restore state\n"); memcpy(&gs, buffer, len); return true; } @@ -205,6 +218,7 @@ vw_free_buffer(void *buffer) * Initialize the vector war game. This initializes the game state and * the video renderer and creates a new network session. */ +bool p1IsLocal; void VectorWar_Init(HWND hwnd, unsigned short localport, int num_players, GGPOPlayer *players, int num_spectators) { @@ -214,7 +228,7 @@ VectorWar_Init(HWND hwnd, unsigned short localport, int num_players, GGPOPlayer // Initialize the game state gs.Init(hwnd, num_players); ngs.num_players = num_players; - + ngs.loopTimer.Init(60,1);// 60FPS; // Fill in a ggpo callbacks structure to pass to start_session. GGPOSessionCallbacks cb = { 0 }; cb.begin_game = vw_begin_game_callback; @@ -224,19 +238,24 @@ VectorWar_Init(HWND hwnd, unsigned short localport, int num_players, GGPOPlayer cb.free_buffer = vw_free_buffer; cb.on_event = vw_on_event_callback; cb.log_game_state = vw_log_game_state; + p1IsLocal = players[0].type == GGPO_PLAYERTYPE_LOCAL; + + ngs.inputDelay = p1IsLocal ? 1 :2; #if defined(SYNC_TEST) result = ggpo_start_synctest(&ggpo, &cb, "vectorwar", num_players, sizeof(int), 1); #else - result = ggpo_start_session(&ggpo, &cb, "vectorwar", num_players, sizeof(int), localport); + result = ggpo_start_session(&ggpo, &cb, "vectorwar", num_players, sizeof(int), localport, 8/*min(8,ngs.inputDelay+4)*/); #endif - + + // automatically disconnect clients after 3000 ms and start our count-down timer // for disconnects after 1000 ms. To completely disable disconnects, simply use // a value of 0 for ggpo_set_disconnect_timeout. ggpo_set_disconnect_timeout(ggpo, 3000); ggpo_set_disconnect_notify_start(ggpo, 1000); + int i; for (i = 0; i < num_players + num_spectators; i++) { GGPOPlayerHandle handle; @@ -247,12 +266,13 @@ VectorWar_Init(HWND hwnd, unsigned short localport, int num_players, GGPOPlayer ngs.players[i].connect_progress = 100; ngs.local_player_handle = handle; ngs.SetConnectState(handle, Connecting); - ggpo_set_frame_delay(ggpo, handle, FRAME_DELAY); + } else { ngs.players[i].connect_progress = 0; + ngs.remote_player_handle = handle; } } - + ggpo_set_frame_delay(ggpo, ngs.local_player_handle, ngs.inputDelay); ggpoutil_perfmon_init(hwnd); renderer->SetStatusText("Connecting to peers."); } @@ -398,20 +418,35 @@ ReadInputs(HWND hwnd) * Run a single frame of the game. */ void -VectorWar_RunFrame(HWND hwnd) +VectorWar_RunFrame(HWND hwnd, int&usToWait) { + // Rest these counts after 3 seconds as they take a hit right at the start while the connection stabilises. + if (ngs.now.framenumber == 240) + { + ngs.nRollbacks = 0; + ngs.inputDelays = 0; + ngs.nTimeSyncs = 0; + ngs.nonTimeSyncs = 0; + ngs.rollbacksBySize = { 0 }; + ngs.totalFrameDelays = 0; + } + hwnd; GGPOErrorCode result = GGPO_OK; int disconnect_flags; int inputs[MAX_SHIPS] = { 0 }; - + bool needIdle = true; if (ngs.local_player_handle != GGPO_INVALID_HANDLE) { - int input = ReadInputs(hwnd); + static int nc = 0; + int input = nc++ % 2 == 0 ? INPUT_ROTATE_LEFT : INPUT_ROTATE_RIGHT; + // input= ReadInputs(hwnd); #if defined(SYNC_TEST) input = rand(); // test: use random inputs to demonstrate sync testing #endif result = ggpo_add_local_input(ggpo, ngs.local_player_handle, &input, sizeof(input)); } - + + + // synchronize these inputs with ggpo. If we have enough input to proceed // ggpo will modify the input list with the correct inputs to use and // return 1. @@ -421,9 +456,20 @@ VectorWar_RunFrame(HWND hwnd) // inputs[0] and inputs[1] contain the inputs for p1 and p2. Advance // the game by 1 frame using those inputs. VectorWar_AdvanceFrame(inputs, disconnect_flags); + needIdle = false; } } + else + { + ngs.inputDelays++; + } + VectorWar_DrawCurrentFrame(); + usToWait = ngs.loopTimer.usToWaitThisLoop(); + // usToWait+=2000; + if(needIdle) + VectorWar_Idle(); + ggpo_get_network_stats(ggpo, ngs.remote_player_handle, &ngs.stats); } /* @@ -433,9 +479,9 @@ VectorWar_RunFrame(HWND hwnd) * for its internal bookkeeping. */ void -VectorWar_Idle(int time) +VectorWar_Idle() { - ggpo_idle(ggpo, time); + ggpo_idle(ggpo); } void diff --git a/src/apps/vectorwar/vectorwar.h b/src/apps/vectorwar/vectorwar.h index 39de962f..b6d76164 100644 --- a/src/apps/vectorwar/vectorwar.h +++ b/src/apps/vectorwar/vectorwar.h @@ -23,8 +23,8 @@ void VectorWar_Init(HWND hwnd, unsigned short localport, int num_players, GGPOPl void VectorWar_InitSpectator(HWND hwnd, unsigned short localport, int num_players, char *host_ip, unsigned short host_port); void VectorWar_DrawCurrentFrame(); void VectorWar_AdvanceFrame(int inputs[], int disconnect_flags); -void VectorWar_RunFrame(HWND hwnd); -void VectorWar_Idle(int time); +void VectorWar_RunFrame(HWND hwnd, int& usToWait); +void VectorWar_Idle(); void VectorWar_DisconnectPlayer(int player); void VectorWar_Exit(); diff --git a/src/include/ggponet.h b/src/include/ggponet.h index ba99a678..657c82ad 100644 --- a/src/include/ggponet.h +++ b/src/include/ggponet.h @@ -16,22 +16,22 @@ extern "C" { // On windows, export at build time and import at runtime. // ELF systems don't need an explicit export/import. -//#ifdef _WIN32 -//# if defined(GGPO_SHARED_LIB) -//# ifdef GGPO_SDK_EXPORT -//# define GGPO_API __declspec(dllexport) -//# else -//# define GGPO_API __declspec(dllimport) -//# endif -//# else -//# define GGPO_API -//# endif -//#else +#ifdef _WIN32 +# if defined(GGPO_SHARED_LIB) +# ifdef GGPO_SDK_EXPORT +# define GGPO_API __declspec(dllexport) +# else +# define GGPO_API __declspec(dllimport) +# endif +# else +# define GGPO_API +# endif +#else # define GGPO_API -//#endif +#endif #define GGPO_MAX_PLAYERS 4 -#define GGPO_MAX_PREDICTION_FRAMES 8 +//#define GGPO_MAX_PREDICTION_FRAMES 8 #define GGPO_MAX_SPECTATORS 32 #define GGPO_SPECTATOR_INPUT_INTERVAL 4 @@ -177,7 +177,7 @@ typedef struct { GGPOPlayerHandle player; } disconnected; struct { - int frames_ahead; + float frames_ahead; } timesync; struct { GGPOPlayerHandle player; @@ -216,7 +216,7 @@ typedef struct { * should make the current game state match the state contained in the * buffer. */ - bool (__cdecl *load_game_state)(unsigned char *buffer, int len); + bool (__cdecl *load_game_state)(unsigned char *buffer, int len, int framesToRollback); /* * log_game_state - Used in diagnostic testing. The client should use @@ -291,8 +291,10 @@ typedef struct GGPONetworkStats { int kbps_sent; } network; struct { - int local_frames_behind; - int remote_frames_behind; + float local_frames_behind; + float remote_frames_behind; + float avg_local_frames_behind; + float avg_remote_frames_behind; } timesync; } GGPONetworkStats; @@ -324,7 +326,8 @@ GGPO_API GGPOErrorCode __cdecl ggpo_start_session(GGPOSession **session, const char *game, int num_players, int input_size, - unsigned short localport); + unsigned short localport, + int maxPrediction); /* @@ -431,12 +434,8 @@ GGPO_API GGPOErrorCode __cdecl ggpo_set_frame_delay(GGPOSession *, * Should be called periodically by your application to give GGPO.net * a chance to do some work. Most packet transmissions and rollbacks occur * in ggpo_idle. - * - * timeout - The amount of time GGPO.net is allowed to spend in this function, - * in milliseconds. */ -GGPO_API GGPOErrorCode __cdecl ggpo_idle(GGPOSession *, - int timeout); +GGPO_API GGPOErrorCode __cdecl ggpo_idle(GGPOSession *); /* * ggpo_add_local_input -- diff --git a/src/lib/ggpo/backends/backend.h b/src/lib/ggpo/backends/backend.h index fedbe5e6..a1f6305a 100644 --- a/src/lib/ggpo/backends/backend.h +++ b/src/lib/ggpo/backends/backend.h @@ -13,7 +13,7 @@ struct GGPOSession { virtual ~GGPOSession() { } - virtual GGPOErrorCode DoPoll(int timeout) { return GGPO_OK; } + virtual GGPOErrorCode DoPoll() { return GGPO_OK; } virtual GGPOErrorCode AddPlayer(GGPOPlayer *player, GGPOPlayerHandle *handle) = 0; virtual GGPOErrorCode AddLocalInput(GGPOPlayerHandle player, void *values, int size) = 0; virtual GGPOErrorCode SyncInput(void *values, int size, int *disconnect_flags) = 0; diff --git a/src/lib/ggpo/backends/p2p.cpp b/src/lib/ggpo/backends/p2p.cpp index 6aa0f37c..edab8e08 100644 --- a/src/lib/ggpo/backends/p2p.cpp +++ b/src/lib/ggpo/backends/p2p.cpp @@ -7,7 +7,7 @@ #include "p2p.h" -static const int RECOMMENDATION_INTERVAL = 240; +static const int RECOMMENDATION_INTERVAL = 120; static const int DEFAULT_DISCONNECT_TIMEOUT = 5000; static const int DEFAULT_DISCONNECT_NOTIFY_START = 750; @@ -15,10 +15,10 @@ Peer2PeerBackend::Peer2PeerBackend(GGPOSessionCallbacks *cb, const char *gamename, uint16 localport, int num_players, - int input_size) : + int input_size, int nframes) : _num_players(num_players), _input_size(input_size), - _sync(_local_connect_status), + _sync(_local_connect_status, nframes), _disconnect_timeout(DEFAULT_DISCONNECT_TIMEOUT), _disconnect_notify_start(DEFAULT_DISCONNECT_NOTIFY_START), _num_spectators(0), @@ -35,7 +35,7 @@ Peer2PeerBackend::Peer2PeerBackend(GGPOSessionCallbacks *cb, config.num_players = num_players; config.input_size = input_size; config.callbacks = _callbacks; - config.num_prediction_frames = MAX_PREDICTION_FRAMES; + config.num_prediction_frames = nframes; _sync.Init(config); /* @@ -99,7 +99,7 @@ GGPOErrorCode Peer2PeerBackend::AddSpectator(char *ip, } GGPOErrorCode -Peer2PeerBackend::DoPoll(int timeout) +Peer2PeerBackend::DoPoll() { if (!_sync.InRollback()) { _poll.Pump(0); @@ -107,7 +107,7 @@ Peer2PeerBackend::DoPoll(int timeout) PollUdpProtocolEvents(); if (!_synchronizing) { - _sync.CheckSimulation(timeout); + _sync.CheckSimulation(); // notify all of our endpoints of their local frame number for their // next connection quality report @@ -146,23 +146,20 @@ Peer2PeerBackend::DoPoll(int timeout) // send timesync notifications if now is the proper time if (current_frame > _next_recommended_sleep) { - int interval = 0; + float interval = 0; for (int i = 0; i < _num_players; i++) { interval = MAX(interval, _endpoints[i].RecommendFrameDelay()); } - if (interval > 0) { + //if (interval > 0) + { GGPOEvent info; info.code = GGPO_EVENTCODE_TIMESYNC; info.u.timesync.frames_ahead = interval; _callbacks.on_event(&info); - _next_recommended_sleep = current_frame + RECOMMENDATION_INTERVAL; + _next_recommended_sleep = current_frame + RECOMMENDATION_INTERVAL;// RECOMMENDATION_INTERVAL;// RECOMMENDATION_INTERVAL; } } - // XXX: this is obviously a farce... - if (timeout) { - Sleep(1); - } } } return GGPO_OK; @@ -331,7 +328,7 @@ Peer2PeerBackend::IncrementFrame(void) { Log("End of frame (%d)...\n", _sync.GetFrameCount()); _sync.IncrementFrame(); - DoPoll(0); + DoPoll(); PollSyncEvents(); return GGPO_OK; @@ -541,8 +538,15 @@ Peer2PeerBackend::SetFrameDelay(GGPOPlayerHandle player, int delay) result = PlayerHandleToQueue(player, &queue); if (!GGPO_SUCCEEDED(result)) { return result; + } _sync.SetFrameDelay(queue, delay); + + for (int i = 0; i < _num_players; i++) { + if (_endpoints[i].IsInitialized()) { + _endpoints[i].SetFrameDelay(delay); + + } } - _sync.SetFrameDelay(queue, delay); + ; return GGPO_OK; } diff --git a/src/lib/ggpo/backends/p2p.h b/src/lib/ggpo/backends/p2p.h index f400f830..7e1443fd 100644 --- a/src/lib/ggpo/backends/p2p.h +++ b/src/lib/ggpo/backends/p2p.h @@ -17,12 +17,12 @@ class Peer2PeerBackend : public IQuarkBackend, IPollSink, Udp::Callbacks { public: - Peer2PeerBackend(GGPOSessionCallbacks *cb, const char *gamename, uint16 localport, int num_players, int input_size); + Peer2PeerBackend(GGPOSessionCallbacks *cb, const char *gamename, uint16 localport, int num_players, int input_size, int nframes); virtual ~Peer2PeerBackend(); public: - virtual GGPOErrorCode DoPoll(int timeout); + virtual GGPOErrorCode DoPoll(); virtual GGPOErrorCode AddPlayer(GGPOPlayer *player, GGPOPlayerHandle *handle); virtual GGPOErrorCode AddLocalInput(GGPOPlayerHandle player, void *values, int size); virtual GGPOErrorCode SyncInput(void *values, int size, int *disconnect_flags); diff --git a/src/lib/ggpo/backends/synctest.cpp b/src/lib/ggpo/backends/synctest.cpp index 4af0426d..7cd3e21e 100644 --- a/src/lib/ggpo/backends/synctest.cpp +++ b/src/lib/ggpo/backends/synctest.cpp @@ -11,7 +11,7 @@ SyncTestBackend::SyncTestBackend(GGPOSessionCallbacks *cb, char *gamename, int frames, int num_players) : - _sync(NULL) + _sync(NULL, MAX_PREDICTION_FRAMES) { _callbacks = *cb; _num_players = num_players; @@ -128,7 +128,7 @@ SyncTestBackend::IncrementFrame(void) if (frame - _last_verified == _check_distance) { // We've gone far enough ahead and should now start replaying frames. // Load the last verified frame and set the rollback flag to true. - _sync.LoadFrame(_last_verified); + _sync.LoadFrame(_last_verified,(int)_saved_frames.size()); _rollingback = true; while(!_saved_frames.empty()) { diff --git a/src/lib/ggpo/bitvector.cpp b/src/lib/ggpo/bitvector.cpp index 670177d1..ff87cd5e 100644 --- a/src/lib/ggpo/bitvector.cpp +++ b/src/lib/ggpo/bitvector.cpp @@ -13,6 +13,7 @@ BitVector_SetBit(uint8 *vector, int *offset) { vector[(*offset) / 8] |= (1 << ((*offset) % 8)); *offset += 1; + } void diff --git a/src/lib/ggpo/main.cpp b/src/lib/ggpo/main.cpp index 01b6e6aa..d55e6f9f 100644 --- a/src/lib/ggpo/main.cpp +++ b/src/lib/ggpo/main.cpp @@ -41,13 +41,15 @@ ggpo_start_session(GGPOSession **session, const char *game, int num_players, int input_size, - unsigned short localport) + unsigned short localport, + int maxPrediction) { *session= (GGPOSession *)new Peer2PeerBackend(cb, game, localport, num_players, - input_size); + input_size, + maxPrediction); return GGPO_OK; } @@ -88,12 +90,12 @@ ggpo_set_frame_delay(GGPOSession *ggpo, } GGPOErrorCode -ggpo_idle(GGPOSession *ggpo, int timeout) +ggpo_idle(GGPOSession *ggpo) { if (!ggpo) { return GGPO_ERRORCODE_INVALID_SESSION; } - return ggpo->DoPoll(timeout); + return ggpo->DoPoll(); } GGPOErrorCode diff --git a/src/lib/ggpo/network/udp_proto.cpp b/src/lib/ggpo/network/udp_proto.cpp index 358b3707..2c3868dc 100644 --- a/src/lib/ggpo/network/udp_proto.cpp +++ b/src/lib/ggpo/network/udp_proto.cpp @@ -8,15 +8,16 @@ #include "types.h" #include "udp_proto.h" #include "bitvector.h" - +#include +#include static const int UDP_HEADER_SIZE = 28; /* Size of IP + UDP headers */ static const int NUM_SYNC_PACKETS = 5; static const int SYNC_RETRY_INTERVAL = 2000; static const int SYNC_FIRST_RETRY_INTERVAL = 500; static const int RUNNING_RETRY_INTERVAL = 200; static const int KEEP_ALIVE_INTERVAL = 200; -static const int QUALITY_REPORT_INTERVAL = 1000; -static const int NETWORK_STATS_INTERVAL = 1000; +static const int QUALITY_REPORT_INTERVAL = 333; +static const int NETWORK_STATS_INTERVAL = 500; static const int UDP_SHUTDOWN_TIMER = 5000; static const int MAX_SEQ_DISTANCE = (1 << 15); @@ -60,7 +61,10 @@ UdpProtocol::~UdpProtocol() { ClearSendQueue(); } - +void UdpProtocol::SetFrameDelay(int delay) +{ + _timesync.SetFrameDelay(delay); +} void UdpProtocol::Init(Udp *udp, Poll &poll, @@ -209,7 +213,9 @@ UdpProtocol::OnLoopPoll(void *cookie) if (!_state.running.last_quality_report_time || _state.running.last_quality_report_time + QUALITY_REPORT_INTERVAL < now) { UdpMsg *msg = new UdpMsg(UdpMsg::QualityReport); msg->u.quality_report.ping = Platform::GetCurrentTimeMS(); - msg->u.quality_report.frame_advantage = (uint8)_local_frame_advantage; + // encode frame advantage into a byte by multiplying the float by 10, and croppeing to 255 - any frame advantage + // of 25 or more means catastrophe has already befallen us. + msg->u.quality_report.frame_advantage = (uint8)min(255.0f,(_timesync.LocalAdvantage()*10.f)); SendMsg(msg); _state.running.last_quality_report_time = now; } @@ -645,7 +651,7 @@ UdpProtocol::OnQualityReport(UdpMsg *msg, int len) reply->u.quality_reply.pong = msg->u.quality_report.ping; SendMsg(reply); - _remote_frame_advantage = msg->u.quality_report.frame_advantage; + _remote_frame_advantage = (float)(msg->u.quality_report.frame_advantage/10.f); return true; } @@ -668,8 +674,10 @@ UdpProtocol::GetNetworkStats(struct GGPONetworkStats *s) s->network.ping = _round_trip_time; s->network.send_queue_len = _pending_output.size(); s->network.kbps_sent = _kbps_sent; - s->timesync.remote_frames_behind = _remote_frame_advantage; - s->timesync.local_frames_behind = _local_frame_advantage; + s->timesync.remote_frames_behind = _timesync.RemoteAdvantage(); + s->timesync.local_frames_behind = _timesync.LocalAdvantage(); + s->timesync.avg_local_frames_behind = _timesync.AvgLocalAdvantageSinceStart(); + s->timesync.avg_remote_frames_behind = _timesync.AvgRemoteAdvantageSinceStart(); } void @@ -680,7 +688,7 @@ UdpProtocol::SetLocalFrameNumber(int localFrame) * last frame they gave us plus some delta for the one-way packet * trip time. */ - int remoteFrame = _last_received_input.frame + (_round_trip_time * 60 / 1000); + float remoteFrame = _last_received_input.frame + (_round_trip_time * 60.f /2000); /* * Our frame advantage is how many frames *behind* the other guy @@ -688,10 +696,10 @@ UdpProtocol::SetLocalFrameNumber(int localFrame) * it means they'll have to predict more often and our moves will * pop more frequenetly. */ - _local_frame_advantage = remoteFrame - localFrame; + _local_frame_advantage = (float)(remoteFrame - localFrame)- _timesync._frameDelay2; } -int +float UdpProtocol::RecommendFrameDelay() { // XXX: require idle input should be a configuration parameter diff --git a/src/lib/ggpo/network/udp_proto.h b/src/lib/ggpo/network/udp_proto.h index 57699aa1..5bde8ace 100644 --- a/src/lib/ggpo/network/udp_proto.h +++ b/src/lib/ggpo/network/udp_proto.h @@ -21,8 +21,10 @@ class UdpProtocol : public IPollSink public: struct Stats { int ping; - int remote_frame_advantage; - int local_frame_advantage; + float remote_frame_advantage; + float local_frame_advantage; + float av_remote_frame_advantage; + float av_local_frame_advantage; int send_queue_len; Udp::Stats udp; }; @@ -80,11 +82,11 @@ class UdpProtocol : public IPollSink bool GetEvent(UdpProtocol::Event &e); void GGPONetworkStats(Stats *stats); void SetLocalFrameNumber(int num); - int RecommendFrameDelay(); + float RecommendFrameDelay(); void SetDisconnectTimeout(int timeout); void SetDisconnectNotifyStart(int timeout); - + void SetFrameDelay(int delay); protected: enum State { Syncing, @@ -172,8 +174,8 @@ class UdpProtocol : public IPollSink /* * Fairness. */ - int _local_frame_advantage; - int _remote_frame_advantage; + float _local_frame_advantage; + float _remote_frame_advantage; /* * Packet loss... diff --git a/src/lib/ggpo/poll.cpp b/src/lib/ggpo/poll.cpp index 46397abe..7468d6a4 100644 --- a/src/lib/ggpo/poll.cpp +++ b/src/lib/ggpo/poll.cpp @@ -9,11 +9,24 @@ #include "poll.h" Poll::Poll(void) : + _handle_count(0), _start_time(0) { + /* + * Create a dummy handle to simplify things. + */ + _handles[_handle_count++] = CreateEvent(NULL, true, false, NULL); } +void +Poll::RegisterHandle(IPollSink *sink, HANDLE h, void *cookie) +{ + ASSERT(_handle_count < MAX_POLLABLE_HANDLES - 1); + _handles[_handle_count] = h; + _handle_sinks[_handle_count] = PollSinkCb(sink, cookie); + _handle_count++; +} void Poll::RegisterMsgLoop(IPollSink *sink, void *cookie) @@ -43,7 +56,7 @@ Poll::Run() bool Poll::Pump(int timeout) { - int i; + int i, res; bool finished = false; if (_start_time == 0) { @@ -55,7 +68,11 @@ Poll::Pump(int timeout) timeout = MIN(timeout, maxwait); } - + res = WaitForMultipleObjects(_handle_count, _handles, false, timeout); + if (res >= WAIT_OBJECT_0 && res < WAIT_OBJECT_0 + _handle_count) { + i = res - WAIT_OBJECT_0; + finished = !_handle_sinks[i].sink->OnHandlePoll(_handle_sinks[i].cookie) || finished; + } for (i = 0; i < _msg_sinks.size(); i++) { PollSinkCb &cb = _msg_sinks[i]; finished = !cb.sink->OnMsgPoll(cb.cookie) || finished; diff --git a/src/lib/ggpo/poll.h b/src/lib/ggpo/poll.h index 20608d60..3ef21083 100644 --- a/src/lib/ggpo/poll.h +++ b/src/lib/ggpo/poll.h @@ -16,6 +16,7 @@ class IPollSink { public: virtual ~IPollSink() { } + virtual bool OnHandlePoll(void *) { return true; } virtual bool OnMsgPoll(void *) { return true; } virtual bool OnPeriodicPoll(void *, int ) { return true; } virtual bool OnLoopPoll(void *) { return true; } @@ -24,6 +25,7 @@ class IPollSink { class Poll { public: Poll(void); + void RegisterHandle(IPollSink *sink, HANDLE h, void *cookie = NULL); void RegisterMsgLoop(IPollSink *sink, void *cookie = NULL); void RegisterPeriodic(IPollSink *sink, int interval, void *cookie = NULL); void RegisterLoop(IPollSink *sink, void *cookie = NULL); @@ -50,6 +52,9 @@ class Poll { }; int _start_time; + int _handle_count; + HANDLE _handles[MAX_POLLABLE_HANDLES]; + PollSinkCb _handle_sinks[MAX_POLLABLE_HANDLES]; StaticBuffer _msg_sinks; StaticBuffer _loop_sinks; diff --git a/src/lib/ggpo/sync.cpp b/src/lib/ggpo/sync.cpp index fd134fe5..c94117ac 100644 --- a/src/lib/ggpo/sync.cpp +++ b/src/lib/ggpo/sync.cpp @@ -7,14 +7,14 @@ #include "sync.h" -Sync::Sync(UdpMsg::connect_status *connect_status) : +Sync::Sync(UdpMsg::connect_status *connect_status, int maxPrediction) : _local_connect_status(connect_status), - _input_queues(NULL) + _input_queues(NULL), + _savedstate(maxPrediction) { _framecount = 0; _last_confirmed_frame = -1; _max_prediction_frames = 0; - memset(&_savedstate, 0, sizeof(_savedstate)); } Sync::~Sync() @@ -23,7 +23,7 @@ Sync::~Sync() * Delete frames manually here rather than in a destructor of the SavedFrame * structure so we can efficently copy frames via weak references. */ - for (int i = 0; i < ARRAY_SIZE(_savedstate.frames); i++) { + for (int i = 0; i < _savedstate.frames.size(); i++) { _callbacks.free_buffer(_savedstate.frames[i].buf); } delete [] _input_queues; @@ -125,7 +125,7 @@ Sync::SynchronizeInputs(void *values, int size) } void -Sync::CheckSimulation(int timeout) +Sync::CheckSimulation() { int seek_to; if (!CheckSimulationConsistency(&seek_to)) { @@ -152,7 +152,7 @@ Sync::AdjustSimulation(int seek_to) /* * Flush our input queue and load the last frame. */ - LoadFrame(seek_to); + LoadFrame(seek_to, count); ASSERT(_framecount == seek_to); /* @@ -171,7 +171,7 @@ Sync::AdjustSimulation(int seek_to) } void -Sync::LoadFrame(int frame) +Sync::LoadFrame(int frame, int framesToRollback) { // find the frame in question if (frame == _framecount) { @@ -181,18 +181,18 @@ Sync::LoadFrame(int frame) // Move the head pointer back and load it up _savedstate.head = FindSavedFrameIndex(frame); - SavedFrame *state = _savedstate.frames + _savedstate.head; + SavedFrame *state = &_savedstate.frames[_savedstate.head]; Log("=== Loading frame info %d (size: %d checksum: %08x).\n", state->frame, state->cbuf, state->checksum); ASSERT(state->buf && state->cbuf); - _callbacks.load_game_state(state->buf, state->cbuf); + _callbacks.load_game_state(state->buf, state->cbuf, framesToRollback); // Reset framecount and the head of the state ring-buffer to point in // advance of the current frame (as if we had just finished executing it). _framecount = state->frame; - _savedstate.head = (_savedstate.head + 1) % ARRAY_SIZE(_savedstate.frames); + _savedstate.head = (_savedstate.head + 1) % _savedstate.frames.size(); } void @@ -202,7 +202,7 @@ Sync::SaveCurrentFrame() * See StateCompress for the real save feature implemented by FinalBurn. * Write everything into the head, then advance the head pointer. */ - SavedFrame *state = _savedstate.frames + _savedstate.head; + SavedFrame *state = &_savedstate.frames[_savedstate.head]; if (state->buf) { _callbacks.free_buffer(state->buf); state->buf = NULL; @@ -211,7 +211,7 @@ Sync::SaveCurrentFrame() _callbacks.save_game_state(&state->buf, &state->cbuf, &state->checksum, state->frame); Log("=== Saved frame info %d (size: %d checksum: %08x).\n", state->frame, state->cbuf, state->checksum); - _savedstate.head = (_savedstate.head + 1) % ARRAY_SIZE(_savedstate.frames); + _savedstate.head = (_savedstate.head + 1) % (int)_savedstate.frames.size(); } Sync::SavedFrame& @@ -219,7 +219,7 @@ Sync::GetLastSavedFrame() { int i = _savedstate.head - 1; if (i < 0) { - i = ARRAY_SIZE(_savedstate.frames) - 1; + i = (int)_savedstate.frames.size() - 1; } return _savedstate.frames[i]; } @@ -228,7 +228,7 @@ Sync::GetLastSavedFrame() int Sync::FindSavedFrameIndex(int frame) { - int i, count = ARRAY_SIZE(_savedstate.frames); + int i, count = (int)_savedstate.frames.size(); for (i = 0; i < count; i++) { if (_savedstate.frames[i].frame == frame) { break; diff --git a/src/lib/ggpo/sync.h b/src/lib/ggpo/sync.h index 46d8c96f..98b13504 100644 --- a/src/lib/ggpo/sync.h +++ b/src/lib/ggpo/sync.h @@ -14,7 +14,7 @@ #include "input_queue.h" #include "ring_buffer.h" #include "network/udp_msg.h" - +#include #define MAX_PREDICTION_FRAMES 8 class SyncTestBackend; @@ -39,7 +39,7 @@ class Sync { }; public: - Sync(UdpMsg::connect_status *connect_status); + Sync(UdpMsg::connect_status *connect_status, int maxPrediction); virtual ~Sync(); void Init(Config &config); @@ -51,7 +51,7 @@ class Sync { int GetConfirmedInputs(void *values, int size, int frame); int SynchronizeInputs(void *values, int size); - void CheckSimulation(int timeout); + void CheckSimulation(); void AdjustSimulation(int seek_to); void IncrementFrame(void); @@ -71,11 +71,16 @@ class Sync { SavedFrame() : buf(NULL), cbuf(0), frame(-1), checksum(0) { } }; struct SavedState { - SavedFrame frames[MAX_PREDICTION_FRAMES + 2]; + SavedState(int max_prediction) { + frames.resize(max_prediction + 2); + head = 0; + + } + std::vector frames;// [MAX_PREDICTION_FRAMES + 2] ; int head; }; - void LoadFrame(int frame); + void LoadFrame(int frame, int framesToRollback); void SaveCurrentFrame(); int FindSavedFrameIndex(int frame); SavedFrame &GetLastSavedFrame(); diff --git a/src/lib/ggpo/timesync.cpp b/src/lib/ggpo/timesync.cpp index f298928f..06b67f9b 100644 --- a/src/lib/ggpo/timesync.cpp +++ b/src/lib/ggpo/timesync.cpp @@ -6,7 +6,7 @@ */ #include "timesync.h" - +#include TimeSync::TimeSync() { memset(_local, 0, sizeof(_local)); @@ -17,53 +17,85 @@ TimeSync::TimeSync() TimeSync::~TimeSync() { } - +void TimeSync::SetFrameDelay(int frame) +{ + _frameDelay2 = frame; +} void -TimeSync::advance_frame(GameInput &input, int advantage, int radvantage) +TimeSync::advance_frame(GameInput &input, float advantage, float radvantage) { // Remember the last frame and frame advantage _last_inputs[input.frame % ARRAY_SIZE(_last_inputs)] = input; _local[input.frame % ARRAY_SIZE(_local)] = advantage; _remote[input.frame % ARRAY_SIZE(_remote)] = radvantage; + + + _avgLocal = ((nFrame * _avgLocal) + advantage) / (nFrame + 1); + _avgRemote = ((nFrame * _avgRemote) + radvantage) / (nFrame + 1); + + nFrame++; + //Clear after first 3 seconds, as this is a bit crazy + if (!clearedInitial && nFrame == 240) + { + clearedInitial = true; + nFrame = 0; + } +} +float TimeSync::LocalAdvantage() const +{ + int i ; + float advantage=0; + for (i = 0; i < ARRAY_SIZE(_local); i++) { + advantage += _local[i]; + } + advantage /=(float)ARRAY_SIZE(_local); + return (advantage); } -int +float TimeSync::RemoteAdvantage() const +{ + int i; + float advantage = 0;; + for (i = 0; i < ARRAY_SIZE(_local); i++) { + advantage += _remote[i]; + } + advantage /= (float)ARRAY_SIZE(_local); + return (advantage); +} +float TimeSync::recommend_frame_wait_duration(bool require_idle_input) { - // Average our local and remote frame advantages - int i, sum = 0; - float advantage, radvantage; - for (i = 0; i < ARRAY_SIZE(_local); i++) { - sum += _local[i]; - } - advantage = sum / (float)ARRAY_SIZE(_local); + + auto advantage = LocalAdvantage(); - sum = 0; - for (i = 0; i < ARRAY_SIZE(_remote); i++) { - sum += _remote[i]; - } - radvantage = sum / (float)ARRAY_SIZE(_remote); + auto radvantage = RemoteAdvantage(); - static int count = 0; - count++; // See if someone should take action. The person furthest ahead // needs to slow down so the other user can catch up. // Only do this if both clients agree on who's ahead!! - if (advantage >= radvantage) { + + + if (advantage >= radvantage) { + return 0; } + float sleep_frames = (((radvantage - advantage) / 2.0f)); // Both clients agree that we're the one ahead. Split // the difference between the two to figure out how long to // sleep for. - int sleep_frames = (int)(((radvantage - advantage) / 2) + 0.5); - - Log("iteration %d: sleep frames is %d\n", count, sleep_frames); + /* char logMessage[256]; + sprintf_s<256>(logMessage, "Local Adv: %.2f, remoate adv %.2f", advantage, radvantage); + OutputDebugString(logMessage); + + sprintf_s<256>(logMessage, ": Sleep for %.2f frames\n", sleep_frames); + OutputDebugString(logMessage); + Log("iteration %d: sleep frames is %d\n", count, sleep_frames);*/ // Some things just aren't worth correcting for. Make sure // the difference is relevant before proceeding. - if (sleep_frames < MIN_FRAME_ADVANTAGE) { + if (sleep_frames < 0.2f){//{ MIN_FRAME_ADVANTAGE) { return 0; } @@ -71,15 +103,15 @@ TimeSync::recommend_frame_wait_duration(bool require_idle_input) // a sleep. This tries to make the emulator sleep while the // user's input isn't sweeping in arcs (e.g. fireball motions in // Street Fighter), which could cause the player to miss moves. - if (require_idle_input) { - for (i = 1; i < ARRAY_SIZE(_last_inputs); i++) { - if (!_last_inputs[i].equal(_last_inputs[0], true)) { - Log("iteration %d: rejecting due to input stuff at position %d...!!!\n", count, i); - return 0; - } - } - } - + //if (require_idle_input) { + // for (i = 1; i < ARRAY_SIZE(_last_inputs); i++) { + // if (!_last_inputs[i].equal(_last_inputs[0], true)) { + // Log("iteration %d: rejecting due to input stuff at position %d...!!!\n", count, i); + // return 0; + // } + // } + //} + //require_idle_input; // Success!!! Recommend the number of frames to sleep and adjust - return MIN(sleep_frames, MAX_FRAME_ADVANTAGE); + return (float)MIN(sleep_frames, MAX_FRAME_ADVANTAGE); } diff --git a/src/lib/ggpo/timesync.h b/src/lib/ggpo/timesync.h index ecbed844..a99f123c 100644 --- a/src/lib/ggpo/timesync.h +++ b/src/lib/ggpo/timesync.h @@ -11,7 +11,7 @@ #include "types.h" #include "game_input.h" -#define FRAME_WINDOW_SIZE 40 +#define FRAME_WINDOW_SIZE 120 #define MIN_UNIQUE_FRAMES 10 #define MIN_FRAME_ADVANTAGE 3 #define MAX_FRAME_ADVANTAGE 9 @@ -21,14 +21,24 @@ class TimeSync { TimeSync(); virtual ~TimeSync (); - void advance_frame(GameInput &input, int advantage, int radvantage); - int recommend_frame_wait_duration(bool require_idle_input); + void advance_frame(GameInput &input, float advantage, float radvantage); + float recommend_frame_wait_duration(bool require_idle_input); + float LocalAdvantage() const; + float RemoteAdvantage() const; + float AvgLocalAdvantageSinceStart() const { return _avgLocal; } + float AvgRemoteAdvantageSinceStart() const { return _avgRemote; } + void SetFrameDelay(int frame); + int _frameDelay2 ; protected: - int _local[FRAME_WINDOW_SIZE]; - int _remote[FRAME_WINDOW_SIZE]; + float _local[FRAME_WINDOW_SIZE]; + float _remote[FRAME_WINDOW_SIZE]; GameInput _last_inputs[MIN_UNIQUE_FRAMES]; int _next_prediction; -}; + int nFrame=0; + float _avgLocal = 0; + float _avgRemote = 0; + bool clearedInitial = false; + }; #endif From f185cc9affd43b36c617f330901d62528de696b9 Mon Sep 17 00:00:00 2001 From: Tom Date: Mon, 10 Oct 2022 01:08:58 +0100 Subject: [PATCH 09/40] remove dead code --- src/include/ggponet.h | 2 +- src/lib/ggpo/backends/backend.h | 4 +- src/lib/ggpo/backends/p2p.h | 2 +- src/lib/ggpo/backends/spectator.h | 2 +- src/lib/ggpo/backends/synctest.h | 2 +- src/lib/ggpo/network/udp.h | 4 +- src/lib/ggpo/poll.cpp | 100 +++++++++--------------------- src/lib/ggpo/poll.h | 20 ++---- 8 files changed, 45 insertions(+), 91 deletions(-) diff --git a/src/include/ggponet.h b/src/include/ggponet.h index 657c82ad..b2a9dbb0 100644 --- a/src/include/ggponet.h +++ b/src/include/ggponet.h @@ -36,7 +36,7 @@ extern "C" { #define GGPO_SPECTATOR_INPUT_INTERVAL 4 -typedef struct GGPOSession GGPOSession; +typedef class GGPOSession GGPOSession; typedef int GGPOPlayerHandle; diff --git a/src/lib/ggpo/backends/backend.h b/src/lib/ggpo/backends/backend.h index a1f6305a..1b39a3b6 100644 --- a/src/lib/ggpo/backends/backend.h +++ b/src/lib/ggpo/backends/backend.h @@ -11,7 +11,8 @@ #include "ggponet.h" #include "types.h" -struct GGPOSession { +class GGPOSession { +public: virtual ~GGPOSession() { } virtual GGPOErrorCode DoPoll() { return GGPO_OK; } virtual GGPOErrorCode AddPlayer(GGPOPlayer *player, GGPOPlayerHandle *handle) = 0; @@ -28,7 +29,6 @@ struct GGPOSession { virtual GGPOErrorCode SetDisconnectNotifyStart(int timeout) { return GGPO_ERRORCODE_UNSUPPORTED; } }; -typedef struct GGPOSession Quark, IQuarkBackend; /* XXX: nuke this */ #endif diff --git a/src/lib/ggpo/backends/p2p.h b/src/lib/ggpo/backends/p2p.h index 7e1443fd..9d71e12e 100644 --- a/src/lib/ggpo/backends/p2p.h +++ b/src/lib/ggpo/backends/p2p.h @@ -15,7 +15,7 @@ #include "timesync.h" #include "network/udp_proto.h" -class Peer2PeerBackend : public IQuarkBackend, IPollSink, Udp::Callbacks { +class Peer2PeerBackend : public GGPOSession, /*IPollSink,*/ Udp::Callbacks { public: Peer2PeerBackend(GGPOSessionCallbacks *cb, const char *gamename, uint16 localport, int num_players, int input_size, int nframes); virtual ~Peer2PeerBackend(); diff --git a/src/lib/ggpo/backends/spectator.h b/src/lib/ggpo/backends/spectator.h index 77b929c6..2a6fae6a 100644 --- a/src/lib/ggpo/backends/spectator.h +++ b/src/lib/ggpo/backends/spectator.h @@ -17,7 +17,7 @@ #define SPECTATOR_FRAME_BUFFER_SIZE 64 -class SpectatorBackend : public IQuarkBackend, IPollSink, Udp::Callbacks { +class SpectatorBackend : public GGPOSession, /*IPollSink,*/ Udp::Callbacks { public: SpectatorBackend(GGPOSessionCallbacks *cb, const char *gamename, uint16 localport, int num_players, int input_size, char *hostip, u_short hostport); virtual ~SpectatorBackend(); diff --git a/src/lib/ggpo/backends/synctest.h b/src/lib/ggpo/backends/synctest.h index a2260b47..d1d002ae 100644 --- a/src/lib/ggpo/backends/synctest.h +++ b/src/lib/ggpo/backends/synctest.h @@ -13,7 +13,7 @@ #include "sync.h" #include "ring_buffer.h" -class SyncTestBackend : public IQuarkBackend { +class SyncTestBackend : public GGPOSession { public: SyncTestBackend(GGPOSessionCallbacks *cb, char *gamename, int frames, int num_players); virtual ~SyncTestBackend(); diff --git a/src/lib/ggpo/network/udp.h b/src/lib/ggpo/network/udp.h index be9d975c..c725150c 100644 --- a/src/lib/ggpo/network/udp.h +++ b/src/lib/ggpo/network/udp.h @@ -42,7 +42,7 @@ class Udp : public IPollSink void SendTo(char *buffer, int len, int flags, struct sockaddr *dst, int destlen); - virtual bool OnLoopPoll(void *cookie); + bool OnLoopPoll(void *cookie) override; public: ~Udp(void); @@ -54,6 +54,8 @@ class Udp : public IPollSink // state management Callbacks *_callbacks; Poll *_poll; + + }; #endif diff --git a/src/lib/ggpo/poll.cpp b/src/lib/ggpo/poll.cpp index 7468d6a4..b5c0b500 100644 --- a/src/lib/ggpo/poll.cpp +++ b/src/lib/ggpo/poll.cpp @@ -9,41 +9,28 @@ #include "poll.h" Poll::Poll(void) : - _handle_count(0), _start_time(0) { - /* - * Create a dummy handle to simplify things. - */ - _handles[_handle_count++] = CreateEvent(NULL, true, false, NULL); } -void -Poll::RegisterHandle(IPollSink *sink, HANDLE h, void *cookie) -{ - ASSERT(_handle_count < MAX_POLLABLE_HANDLES - 1); - - _handles[_handle_count] = h; - _handle_sinks[_handle_count] = PollSinkCb(sink, cookie); - _handle_count++; -} -void -Poll::RegisterMsgLoop(IPollSink *sink, void *cookie) -{ - _msg_sinks.push_back(PollSinkCb(sink, cookie)); -} +// +//void +//Poll::RegisterMsgLoop(IPollSink *sink, void *cookie) +//{ +// _msg_sinks.push_back(PollSinkCb(sink, cookie)); +//} void Poll::RegisterLoop(IPollSink *sink, void *cookie) { _loop_sinks.push_back(PollSinkCb(sink, cookie)); } -void -Poll::RegisterPeriodic(IPollSink *sink, int interval, void *cookie) -{ - _periodic_sinks.push_back(PollPeriodicSinkCb(sink, cookie, interval)); -} +//void +//Poll::RegisterPeriodic(IPollSink *sink, int interval, void *cookie) +//{ +// _periodic_sinks.push_back(PollPeriodicSinkCb(sink, cookie, interval)); +//} void Poll::Run() @@ -56,57 +43,30 @@ Poll::Run() bool Poll::Pump(int timeout) { - int i, res; + int i; bool finished = false; - if (_start_time == 0) { - _start_time = Platform::GetCurrentTimeMS(); - } - int elapsed = Platform::GetCurrentTimeMS() - _start_time; - int maxwait = ComputeWaitTime(elapsed); - if (maxwait != INFINITE) { - timeout = MIN(timeout, maxwait); - } - - res = WaitForMultipleObjects(_handle_count, _handles, false, timeout); - if (res >= WAIT_OBJECT_0 && res < WAIT_OBJECT_0 + _handle_count) { - i = res - WAIT_OBJECT_0; - finished = !_handle_sinks[i].sink->OnHandlePoll(_handle_sinks[i].cookie) || finished; - } - for (i = 0; i < _msg_sinks.size(); i++) { - PollSinkCb &cb = _msg_sinks[i]; - finished = !cb.sink->OnMsgPoll(cb.cookie) || finished; - } - - for (i = 0; i < _periodic_sinks.size(); i++) { - PollPeriodicSinkCb &cb = _periodic_sinks[i]; - if (cb.interval + cb.last_fired <= elapsed) { - cb.last_fired = (elapsed / cb.interval) * cb.interval; - finished = !cb.sink->OnPeriodicPoll(cb.cookie, cb.last_fired) || finished; - } - } - for (i = 0; i < _loop_sinks.size(); i++) { PollSinkCb &cb = _loop_sinks[i]; finished = !cb.sink->OnLoopPoll(cb.cookie) || finished; } return finished; } - -int -Poll::ComputeWaitTime(int elapsed) -{ - int waitTime = INFINITE; - size_t count = _periodic_sinks.size(); - - if (count > 0) { - for (int i = 0; i < count; i++) { - PollPeriodicSinkCb &cb = _periodic_sinks[i]; - int timeout = (cb.interval + cb.last_fired) - elapsed; - if (waitTime == INFINITE || (timeout < waitTime)) { - waitTime = MAX(timeout, 0); - } - } - } - return waitTime; -} +// +//int +//Poll::ComputeWaitTime(int elapsed) +//{ +// int waitTime = INFINITE; +// size_t count = _periodic_sinks.size(); +// +// if (count > 0) { +// for (int i = 0; i < count; i++) { +// PollPeriodicSinkCb &cb = _periodic_sinks[i]; +// int timeout = (cb.interval + cb.last_fired) - elapsed; +// if (waitTime == INFINITE || (timeout < waitTime)) { +// waitTime = MAX(timeout, 0); +// } +// } +// } +// return waitTime; +//} diff --git a/src/lib/ggpo/poll.h b/src/lib/ggpo/poll.h index 3ef21083..597cf58b 100644 --- a/src/lib/ggpo/poll.h +++ b/src/lib/ggpo/poll.h @@ -16,25 +16,21 @@ class IPollSink { public: virtual ~IPollSink() { } - virtual bool OnHandlePoll(void *) { return true; } - virtual bool OnMsgPoll(void *) { return true; } - virtual bool OnPeriodicPoll(void *, int ) { return true; } - virtual bool OnLoopPoll(void *) { return true; } + //virtual bool OnMsgPoll(void*) = 0;//{ return true; } + // virtual bool OnPeriodicPoll(void*, int) = 0;// { return true; } + virtual bool OnLoopPoll(void*) = 0;// { return true; } }; class Poll { public: Poll(void); - void RegisterHandle(IPollSink *sink, HANDLE h, void *cookie = NULL); - void RegisterMsgLoop(IPollSink *sink, void *cookie = NULL); - void RegisterPeriodic(IPollSink *sink, int interval, void *cookie = NULL); void RegisterLoop(IPollSink *sink, void *cookie = NULL); void Run(); bool Pump(int timeout); protected: - int ComputeWaitTime(int elapsed); + //int ComputeWaitTime(int elapsed); struct PollSinkCb { IPollSink *sink; @@ -52,13 +48,9 @@ class Poll { }; int _start_time; - int _handle_count; - HANDLE _handles[MAX_POLLABLE_HANDLES]; - PollSinkCb _handle_sinks[MAX_POLLABLE_HANDLES]; - - StaticBuffer _msg_sinks; + // StaticBuffer _msg_sinks; StaticBuffer _loop_sinks; - StaticBuffer _periodic_sinks; + // StaticBuffer _periodic_sinks; }; #endif From ea06663dea69ceaa7dd5a3d0bd3e0bbf57d87ceb Mon Sep 17 00:00:00 2001 From: Tom Date: Mon, 10 Oct 2022 01:09:10 +0100 Subject: [PATCH 10/40] remove more dead code --- src/lib/ggpo/backends/backend.h | 2 +- src/lib/ggpo/backends/spectator.cpp | 4 ++-- src/lib/ggpo/backends/spectator.h | 2 +- src/lib/ggpo/backends/synctest.cpp | 2 +- src/lib/ggpo/backends/synctest.h | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/lib/ggpo/backends/backend.h b/src/lib/ggpo/backends/backend.h index 1b39a3b6..c34c68cd 100644 --- a/src/lib/ggpo/backends/backend.h +++ b/src/lib/ggpo/backends/backend.h @@ -14,7 +14,7 @@ class GGPOSession { public: virtual ~GGPOSession() { } - virtual GGPOErrorCode DoPoll() { return GGPO_OK; } + virtual GGPOErrorCode DoPoll() = 0; virtual GGPOErrorCode AddPlayer(GGPOPlayer *player, GGPOPlayerHandle *handle) = 0; virtual GGPOErrorCode AddLocalInput(GGPOPlayerHandle player, void *values, int size) = 0; virtual GGPOErrorCode SyncInput(void *values, int size, int *disconnect_flags) = 0; diff --git a/src/lib/ggpo/backends/spectator.cpp b/src/lib/ggpo/backends/spectator.cpp index 81f924d7..e56d7e48 100644 --- a/src/lib/ggpo/backends/spectator.cpp +++ b/src/lib/ggpo/backends/spectator.cpp @@ -47,7 +47,7 @@ SpectatorBackend::~SpectatorBackend() } GGPOErrorCode -SpectatorBackend::DoPoll(int timeout) +SpectatorBackend::DoPoll() { _poll.Pump(0); @@ -90,7 +90,7 @@ GGPOErrorCode SpectatorBackend::IncrementFrame(void) { Log("End of frame (%d)...\n", _next_input_to_send - 1); - DoPoll(0); + DoPoll(); PollUdpProtocolEvents(); return GGPO_OK; diff --git a/src/lib/ggpo/backends/spectator.h b/src/lib/ggpo/backends/spectator.h index 2a6fae6a..0b647b25 100644 --- a/src/lib/ggpo/backends/spectator.h +++ b/src/lib/ggpo/backends/spectator.h @@ -24,7 +24,7 @@ class SpectatorBackend : public GGPOSession, /*IPollSink,*/ Udp::Callbacks { public: - virtual GGPOErrorCode DoPoll(int timeout); + virtual GGPOErrorCode DoPoll(); virtual GGPOErrorCode AddPlayer(GGPOPlayer *player, GGPOPlayerHandle *handle) { return GGPO_ERRORCODE_UNSUPPORTED; } virtual GGPOErrorCode AddLocalInput(GGPOPlayerHandle player, void *values, int size) { return GGPO_OK; } virtual GGPOErrorCode SyncInput(void *values, int size, int *disconnect_flags); diff --git a/src/lib/ggpo/backends/synctest.cpp b/src/lib/ggpo/backends/synctest.cpp index 7cd3e21e..dcc6e23b 100644 --- a/src/lib/ggpo/backends/synctest.cpp +++ b/src/lib/ggpo/backends/synctest.cpp @@ -42,7 +42,7 @@ SyncTestBackend::~SyncTestBackend() } GGPOErrorCode -SyncTestBackend::DoPoll(int timeout) +SyncTestBackend::DoPoll() { if (!_running) { GGPOEvent info; diff --git a/src/lib/ggpo/backends/synctest.h b/src/lib/ggpo/backends/synctest.h index d1d002ae..3e36d06e 100644 --- a/src/lib/ggpo/backends/synctest.h +++ b/src/lib/ggpo/backends/synctest.h @@ -18,7 +18,7 @@ class SyncTestBackend : public GGPOSession { SyncTestBackend(GGPOSessionCallbacks *cb, char *gamename, int frames, int num_players); virtual ~SyncTestBackend(); - virtual GGPOErrorCode DoPoll(int timeout); + virtual GGPOErrorCode DoPoll(); virtual GGPOErrorCode AddPlayer(GGPOPlayer *player, GGPOPlayerHandle *handle); virtual GGPOErrorCode AddLocalInput(GGPOPlayerHandle player, void *values, int size); virtual GGPOErrorCode SyncInput(void *values, int size, int *disconnect_flags); From 67a95637af433c62d86b39b77e9e36a533499e3f Mon Sep 17 00:00:00 2001 From: Tom Date: Mon, 10 Oct 2022 11:44:04 +0100 Subject: [PATCH 11/40] tidy things up --- src/apps/vectorwar/vectorwar.cpp | 4 ++-- src/include/ggponet.h | 3 ++- src/lib/ggpo/backends/backend.h | 6 +++--- src/lib/ggpo/backends/p2p.cpp | 9 +++++++++ src/lib/ggpo/backends/p2p.h | 22 +++++++++++----------- src/lib/ggpo/backends/spectator.h | 1 + src/lib/ggpo/backends/synctest.h | 3 ++- src/lib/ggpo/main.cpp | 6 +++--- 8 files changed, 33 insertions(+), 21 deletions(-) diff --git a/src/apps/vectorwar/vectorwar.cpp b/src/apps/vectorwar/vectorwar.cpp index c23e5785..8c1ec6d5 100644 --- a/src/apps/vectorwar/vectorwar.cpp +++ b/src/apps/vectorwar/vectorwar.cpp @@ -92,9 +92,9 @@ vw_on_event_callback(GGPOEvent *info) ngs.SetConnectState(info->u.disconnected.player, Disconnected); break; case GGPO_EVENTCODE_TIMESYNC: - ngs.loopTimer.OnGGPOTimeSyncEvent(info->u.timesync.frames_ahead); + // ngs.loopTimer.OnGGPOTimeSyncEvent(info->u.timesync.frames_ahead); if (info->u.timesync.frames_ahead > 0) { - // Sleep(max(1, (int)(1000.0f * info->u.timesync.frames_ahead / 60.f))); + Sleep(max(1, (int)(1000.0f * info->u.timesync.frames_ahead / 60.f))); ngs.nTimeSyncs++; ngs.totalFrameDelays += info->u.timesync.frames_ahead; } diff --git a/src/include/ggponet.h b/src/include/ggponet.h index b2a9dbb0..05986810 100644 --- a/src/include/ggponet.h +++ b/src/include/ggponet.h @@ -103,7 +103,8 @@ typedef struct GGPOLocalEndpoint { GGPO_ERRORLIST_ENTRY(GGPO_ERRORCODE_INPUT_DROPPED, 8) \ GGPO_ERRORLIST_ENTRY(GGPO_ERRORCODE_PLAYER_DISCONNECTED, 9) \ GGPO_ERRORLIST_ENTRY(GGPO_ERRORCODE_TOO_MANY_SPECTATORS, 10) \ - GGPO_ERRORLIST_ENTRY(GGPO_ERRORCODE_INVALID_REQUEST, 11) + GGPO_ERRORLIST_ENTRY(GGPO_ERRORCODE_INVALID_REQUEST, 11) \ + GGPO_ERRORLIST_ENTRY(GGPO_CHAT_MESSAGE_TOO_LONG, 12) #define GGPO_ERRORLIST_ENTRY(name, value) name = value, typedef enum { diff --git a/src/lib/ggpo/backends/backend.h b/src/lib/ggpo/backends/backend.h index c34c68cd..3fcdccb0 100644 --- a/src/lib/ggpo/backends/backend.h +++ b/src/lib/ggpo/backends/backend.h @@ -18,9 +18,9 @@ class GGPOSession { virtual GGPOErrorCode AddPlayer(GGPOPlayer *player, GGPOPlayerHandle *handle) = 0; virtual GGPOErrorCode AddLocalInput(GGPOPlayerHandle player, void *values, int size) = 0; virtual GGPOErrorCode SyncInput(void *values, int size, int *disconnect_flags) = 0; - virtual GGPOErrorCode IncrementFrame(void) { return GGPO_OK; } - virtual GGPOErrorCode Chat(char *text) { return GGPO_OK; } - virtual GGPOErrorCode DisconnectPlayer(GGPOPlayerHandle handle) { return GGPO_OK; } + virtual GGPOErrorCode IncrementFrame(void) = 0; + virtual GGPOErrorCode Chat(const char* text) = 0;// { return GGPO_OK; } + virtual GGPOErrorCode DisconnectPlayer(GGPOPlayerHandle handle) = 0;// { return GGPO_OK; } virtual GGPOErrorCode GetNetworkStats(GGPONetworkStats *stats, GGPOPlayerHandle handle) { return GGPO_OK; } virtual GGPOErrorCode Logv(const char *fmt, va_list list) { ::Logv(fmt, list); return GGPO_OK; } diff --git a/src/lib/ggpo/backends/p2p.cpp b/src/lib/ggpo/backends/p2p.cpp index edab8e08..fd1b3917 100644 --- a/src/lib/ggpo/backends/p2p.cpp +++ b/src/lib/ggpo/backends/p2p.cpp @@ -574,6 +574,15 @@ Peer2PeerBackend::SetDisconnectNotifyStart(int timeout) return GGPO_OK; } +GGPOErrorCode +Peer2PeerBackend::Chat(const char* text) +{ + if (strlen(text) > 64) + return GGPO_CHAT_MESSAGE_TOO_LONG; + + return GGPO_OK; +} + GGPOErrorCode Peer2PeerBackend::PlayerHandleToQueue(GGPOPlayerHandle player, int *queue) { diff --git a/src/lib/ggpo/backends/p2p.h b/src/lib/ggpo/backends/p2p.h index 9d71e12e..462569f0 100644 --- a/src/lib/ggpo/backends/p2p.h +++ b/src/lib/ggpo/backends/p2p.h @@ -22,17 +22,17 @@ class Peer2PeerBackend : public GGPOSession, /*IPollSink,*/ Udp::Callbacks { public: - virtual GGPOErrorCode DoPoll(); - virtual GGPOErrorCode AddPlayer(GGPOPlayer *player, GGPOPlayerHandle *handle); - virtual GGPOErrorCode AddLocalInput(GGPOPlayerHandle player, void *values, int size); - virtual GGPOErrorCode SyncInput(void *values, int size, int *disconnect_flags); - virtual GGPOErrorCode IncrementFrame(void); - virtual GGPOErrorCode DisconnectPlayer(GGPOPlayerHandle handle); - virtual GGPOErrorCode GetNetworkStats(GGPONetworkStats *stats, GGPOPlayerHandle handle); - virtual GGPOErrorCode SetFrameDelay(GGPOPlayerHandle player, int delay); - virtual GGPOErrorCode SetDisconnectTimeout(int timeout); - virtual GGPOErrorCode SetDisconnectNotifyStart(int timeout); - + virtual GGPOErrorCode DoPoll() override; + virtual GGPOErrorCode AddPlayer(GGPOPlayer *player, GGPOPlayerHandle *handle) override; + virtual GGPOErrorCode AddLocalInput(GGPOPlayerHandle player, void *values, int size) override; + virtual GGPOErrorCode SyncInput(void *values, int size, int *disconnect_flags) override; + virtual GGPOErrorCode IncrementFrame(void) override; + virtual GGPOErrorCode DisconnectPlayer(GGPOPlayerHandle handle) override; + virtual GGPOErrorCode GetNetworkStats(GGPONetworkStats *stats, GGPOPlayerHandle handle) override; + virtual GGPOErrorCode SetFrameDelay(GGPOPlayerHandle player, int delay) override; + virtual GGPOErrorCode SetDisconnectTimeout(int timeout) override; + virtual GGPOErrorCode SetDisconnectNotifyStart(int timeout) override; + virtual GGPOErrorCode Chat(const char* text) override; public: virtual void OnMsg(sockaddr_in &from, UdpMsg *msg, int len); diff --git a/src/lib/ggpo/backends/spectator.h b/src/lib/ggpo/backends/spectator.h index 0b647b25..6fbcb41b 100644 --- a/src/lib/ggpo/backends/spectator.h +++ b/src/lib/ggpo/backends/spectator.h @@ -34,6 +34,7 @@ class SpectatorBackend : public GGPOSession, /*IPollSink,*/ Udp::Callbacks { virtual GGPOErrorCode SetFrameDelay(GGPOPlayerHandle player, int delay) { return GGPO_ERRORCODE_UNSUPPORTED; } virtual GGPOErrorCode SetDisconnectTimeout(int timeout) { return GGPO_ERRORCODE_UNSUPPORTED; } virtual GGPOErrorCode SetDisconnectNotifyStart(int timeout) { return GGPO_ERRORCODE_UNSUPPORTED; } + virtual GGPOErrorCode Chat(const char* text) override { return GGPO_ERRORCODE_UNSUPPORTED; } public: virtual void OnMsg(sockaddr_in &from, UdpMsg *msg, int len); diff --git a/src/lib/ggpo/backends/synctest.h b/src/lib/ggpo/backends/synctest.h index 3e36d06e..aef23fec 100644 --- a/src/lib/ggpo/backends/synctest.h +++ b/src/lib/ggpo/backends/synctest.h @@ -24,7 +24,8 @@ class SyncTestBackend : public GGPOSession { virtual GGPOErrorCode SyncInput(void *values, int size, int *disconnect_flags); virtual GGPOErrorCode IncrementFrame(void); virtual GGPOErrorCode Logv(char *fmt, va_list list); - + virtual GGPOErrorCode DisconnectPlayer(GGPOPlayerHandle handle) { return GGPO_OK; } + virtual GGPOErrorCode Chat(const char* text) override { return GGPO_ERRORCODE_UNSUPPORTED; } protected: struct SavedInfo { int frame; diff --git a/src/lib/ggpo/main.cpp b/src/lib/ggpo/main.cpp index d55e6f9f..dd8094e0 100644 --- a/src/lib/ggpo/main.cpp +++ b/src/lib/ggpo/main.cpp @@ -44,7 +44,7 @@ ggpo_start_session(GGPOSession **session, unsigned short localport, int maxPrediction) { - *session= (GGPOSession *)new Peer2PeerBackend(cb, + *session= new Peer2PeerBackend(cb, game, localport, num_players, @@ -74,7 +74,7 @@ ggpo_start_synctest(GGPOSession **ggpo, int input_size, int frames) { - *ggpo = (GGPOSession *)new SyncTestBackend(cb, game, frames, num_players); + *ggpo = new SyncTestBackend(cb, game, frames, num_players); return GGPO_OK; } @@ -198,7 +198,7 @@ GGPOErrorCode ggpo_start_spectating(GGPOSession **session, char *host_ip, unsigned short host_port) { - *session= (GGPOSession *)new SpectatorBackend(cb, + *session= new SpectatorBackend(cb, game, local_port, num_players, From c08a8dd98a396c5f6ac31bf771938ff53dcfb08d Mon Sep 17 00:00:00 2001 From: thomashenry79 Date: Sat, 15 Oct 2022 18:14:20 +0100 Subject: [PATCH 12/40] ggpo-x chat --- .gitignore | 1 + src/apps/vectorwar/nongamestate.h | 1 + src/apps/vectorwar/vectorwar.cpp | 15 +++++++++++---- src/include/ggponet.h | 23 +++++++++++++++++++++++ src/lib/ggpo/backends/p2p.cpp | 19 ++++++++++++++++++- src/lib/ggpo/main.cpp | 2 +- src/lib/ggpo/network/udp_msg.h | 9 +++++++-- src/lib/ggpo/network/udp_proto.cpp | 21 +++++++++++++++++++++ src/lib/ggpo/network/udp_proto.h | 9 +++++++-- 9 files changed, 90 insertions(+), 10 deletions(-) diff --git a/.gitignore b/.gitignore index 018f0464..79255562 100644 --- a/.gitignore +++ b/.gitignore @@ -476,3 +476,4 @@ Training Blog About /CMakeCache.txt +/CMakeFiles/cmake.check_cache diff --git a/src/apps/vectorwar/nongamestate.h b/src/apps/vectorwar/nongamestate.h index d5e11a36..571f1e2b 100644 --- a/src/apps/vectorwar/nongamestate.h +++ b/src/apps/vectorwar/nongamestate.h @@ -141,6 +141,7 @@ struct NonGameState { std::array rollbacksBySize = {0,0,0,0,0,0,0,0,0,0}; GGPOPlayerHandle local_player_handle; GGPOPlayerHandle remote_player_handle; + int LocalPLayerNumber; PlayerConnectionInfo players[MAX_PLAYERS]; int inputDelay; int inputDelays = 0; diff --git a/src/apps/vectorwar/vectorwar.cpp b/src/apps/vectorwar/vectorwar.cpp index 8c1ec6d5..853d4bd6 100644 --- a/src/apps/vectorwar/vectorwar.cpp +++ b/src/apps/vectorwar/vectorwar.cpp @@ -66,6 +66,11 @@ vw_on_event_callback(GGPOEvent *info) { int progress; switch (info->code) { + case GGPO_EVENTCODE_CHAT: + char buffer[128]; + sprintf_s<128>(buffer, "P:%d recived message: %s from P%d", ngs.LocalPLayerNumber, info->u.chat.msg, info->u.chat.senderID+1); + OutputDebugStringA(buffer); + break; case GGPO_EVENTCODE_CONNECTED_TO_PEER: ngs.SetConnectState(info->u.connected.player, Synchronizing); break; @@ -92,7 +97,7 @@ vw_on_event_callback(GGPOEvent *info) ngs.SetConnectState(info->u.disconnected.player, Disconnected); break; case GGPO_EVENTCODE_TIMESYNC: - // ngs.loopTimer.OnGGPOTimeSyncEvent(info->u.timesync.frames_ahead); + ngs.loopTimer.OnGGPOTimeSyncEvent(info->u.timesync.frames_ahead); if (info->u.timesync.frames_ahead > 0) { Sleep(max(1, (int)(1000.0f * info->u.timesync.frames_ahead / 60.f))); ngs.nTimeSyncs++; @@ -239,8 +244,8 @@ VectorWar_Init(HWND hwnd, unsigned short localport, int num_players, GGPOPlayer cb.on_event = vw_on_event_callback; cb.log_game_state = vw_log_game_state; p1IsLocal = players[0].type == GGPO_PLAYERTYPE_LOCAL; - - ngs.inputDelay = p1IsLocal ? 1 :2; + ngs.LocalPLayerNumber = p1IsLocal ? 1 : 2; + ngs.inputDelay = p1IsLocal ? 2 :7; #if defined(SYNC_TEST) result = ggpo_start_synctest(&ggpo, &cb, "vectorwar", num_players, sizeof(int), 1); @@ -438,7 +443,9 @@ VectorWar_RunFrame(HWND hwnd, int&usToWait) if (ngs.local_player_handle != GGPO_INVALID_HANDLE) { static int nc = 0; int input = nc++ % 2 == 0 ? INPUT_ROTATE_LEFT : INPUT_ROTATE_RIGHT; - // input= ReadInputs(hwnd); + auto i = ReadInputs(hwnd); + if (i == INPUT_FIRE) + ggpo_client_chat(ggpo, "You wanker!"); #if defined(SYNC_TEST) input = rand(); // test: use random inputs to demonstrate sync testing #endif diff --git a/src/include/ggponet.h b/src/include/ggponet.h index 05986810..75214fc4 100644 --- a/src/include/ggponet.h +++ b/src/include/ggponet.h @@ -153,6 +153,7 @@ typedef enum { GGPO_EVENTCODE_TIMESYNC = 1005, GGPO_EVENTCODE_CONNECTION_INTERRUPTED = 1006, GGPO_EVENTCODE_CONNECTION_RESUMED = 1007, + GGPO_EVENTCODE_CHAT = 1008, } GGPOEventCode; /* @@ -187,6 +188,10 @@ typedef struct { struct { GGPOPlayerHandle player; } connection_resumed; + struct { + int senderID; + const char* msg; + } chat; } u; } GGPOEvent; @@ -457,6 +462,24 @@ GGPO_API GGPOErrorCode __cdecl ggpo_add_local_input(GGPOSession *, GGPOPlayerHandle player, void *values, int size); +/* + * ggpo_add_local_input -- + * + * Used to notify GGPO.net of inputs that should be trasmitted to remote + * players. ggpo_add_local_input must be called once every frame for + * all player of type GGPO_PLAYERTYPE_LOCAL. + * + * player - The player handle returned for this player when you called + * ggpo_add_local_player. + * + * values - The controller inputs for this player. + * + * size - The size of the controller inputs. This must be exactly equal to the + * size passed into ggpo_start_session. + */ + +GGPO_API GGPOErrorCode __cdecl ggpo_client_chat(GGPOSession *, + const char* message); /* * ggpo_synchronize_input -- diff --git a/src/lib/ggpo/backends/p2p.cpp b/src/lib/ggpo/backends/p2p.cpp index fd1b3917..bde00147 100644 --- a/src/lib/ggpo/backends/p2p.cpp +++ b/src/lib/ggpo/backends/p2p.cpp @@ -101,6 +101,17 @@ GGPOErrorCode Peer2PeerBackend::AddSpectator(char *ip, GGPOErrorCode Peer2PeerBackend::DoPoll() { + // Pass on chat + for (int i = 0; i < _num_players; i++) { + _endpoints[i].ConsumeChat([&](const char* msg) { + GGPOEvent info; + info.u.chat.senderID = i; + info.code = GGPO_EVENTCODE_CHAT; + info.u.chat.msg = msg; + _callbacks.on_event(&info); + }); + } + if (!_sync.InRollback()) { _poll.Pump(0); @@ -577,9 +588,15 @@ Peer2PeerBackend::SetDisconnectNotifyStart(int timeout) GGPOErrorCode Peer2PeerBackend::Chat(const char* text) { - if (strlen(text) > 64) + if (strlen(text) >= MAX_CHAT_LENGTH) return GGPO_CHAT_MESSAGE_TOO_LONG; + // Send the input to all the remote players. + for (int i = 0; i < _num_players; i++) { + if (_endpoints[i].IsInitialized()) { + _endpoints[i].SendChat(text); + } + } return GGPO_OK; } diff --git a/src/lib/ggpo/main.cpp b/src/lib/ggpo/main.cpp index dd8094e0..5d06cae7 100644 --- a/src/lib/ggpo/main.cpp +++ b/src/lib/ggpo/main.cpp @@ -141,7 +141,7 @@ ggpo_advance_frame(GGPOSession *ggpo) } GGPOErrorCode -ggpo_client_chat(GGPOSession *ggpo, char *text) +ggpo_client_chat(GGPOSession *ggpo, const char *text) { if (!ggpo) { return GGPO_ERRORCODE_INVALID_SESSION; diff --git a/src/lib/ggpo/network/udp_msg.h b/src/lib/ggpo/network/udp_msg.h index 495a002e..41f75091 100644 --- a/src/lib/ggpo/network/udp_msg.h +++ b/src/lib/ggpo/network/udp_msg.h @@ -10,7 +10,7 @@ #define MAX_COMPRESSED_BITS 4096 #define UDP_MSG_MAX_PLAYERS 4 - +#define MAX_CHAT_LENGTH 120 #pragma pack(push, 1) struct UdpMsg @@ -24,6 +24,7 @@ struct UdpMsg QualityReply = 5, KeepAlive = 6, InputAck = 7, + Chat = 8, }; struct connect_status { @@ -72,7 +73,9 @@ struct UdpMsg struct { int ack_frame:31; } input_ack; - + struct { + char msg[MAX_CHAT_LENGTH]; + } chat; } u; public: @@ -89,12 +92,14 @@ struct UdpMsg case QualityReport: return sizeof(u.quality_report); case QualityReply: return sizeof(u.quality_reply); case InputAck: return sizeof(u.input_ack); + case Chat: return MAX_CHAT_LENGTH; case KeepAlive: return 0; case Input: size = (int)((char *)&u.input.bits - (char *)&u.input); size += (u.input.num_bits + 7) / 8; return size; } + ASSERT(false); return 0; } diff --git a/src/lib/ggpo/network/udp_proto.cpp b/src/lib/ggpo/network/udp_proto.cpp index 2c3868dc..131b4ee2 100644 --- a/src/lib/ggpo/network/udp_proto.cpp +++ b/src/lib/ggpo/network/udp_proto.cpp @@ -181,6 +181,12 @@ UdpProtocol::GetEvent(UdpProtocol::Event &e) return true; } +void UdpProtocol::SendChat(const char* message) +{ + UdpMsg* msg = new UdpMsg(UdpMsg::Chat); + strcpy_s(msg->u.chat.msg, message); + SendMsg(msg); +} bool UdpProtocol::OnLoopPoll(void *cookie) @@ -318,6 +324,7 @@ UdpProtocol::OnMsg(UdpMsg *msg, int len) &UdpProtocol::OnQualityReply, /* QualityReply */ &UdpProtocol::OnKeepAlive, /* KeepAlive */ &UdpProtocol::OnInputAck, /* InputAck */ + &UdpProtocol::OnChat, /* InputAck */ }; // filter out messages that don't match what we expect @@ -447,6 +454,9 @@ UdpProtocol::LogMsg(const char *prefix, UdpMsg *msg) case UdpMsg::InputAck: Log("%s input ack.\n", prefix); break; + case UdpMsg::Chat: + Log("%s chat.\n", prefix); + break; default: ASSERT(FALSE && "Unknown UdpMsg type."); } @@ -667,6 +677,17 @@ UdpProtocol::OnKeepAlive(UdpMsg *msg, int len) { return true; } +void UdpProtocol::ConsumeChat(std::function onChat) +{ + for (const auto& msg : _chatMessages) + onChat(msg.c_str()); + _chatMessages.clear(); +} +bool UdpProtocol::OnChat(UdpMsg* msg, int len) +{ + _chatMessages.push_back(msg->u.chat.msg); + return true; +} void UdpProtocol::GetNetworkStats(struct GGPONetworkStats *s) diff --git a/src/lib/ggpo/network/udp_proto.h b/src/lib/ggpo/network/udp_proto.h index 5bde8ace..3b06f37a 100644 --- a/src/lib/ggpo/network/udp_proto.h +++ b/src/lib/ggpo/network/udp_proto.h @@ -15,7 +15,9 @@ #include "timesync.h" #include "ggponet.h" #include "ring_buffer.h" - +#include +#include +#include class UdpProtocol : public IPollSink { public: @@ -73,6 +75,7 @@ class UdpProtocol : public IPollSink bool IsSynchronized() { return _current_state == Running; } bool IsRunning() { return _current_state == Running; } void SendInput(GameInput &input); + void SendChat(const char* message); void SendInputAck(); bool HandlesMsg(sockaddr_in &from, UdpMsg *msg); void OnMsg(UdpMsg *msg, int len); @@ -87,6 +90,7 @@ class UdpProtocol : public IPollSink void SetDisconnectTimeout(int timeout); void SetDisconnectNotifyStart(int timeout); void SetFrameDelay(int delay); + void ConsumeChat(std::function onChat); protected: enum State { Syncing, @@ -113,7 +117,6 @@ class UdpProtocol : public IPollSink void SendSyncRequest(); void SendMsg(UdpMsg *msg); void PumpSendQueue(); - void DispatchMsg(uint8 *buffer, int len); void SendPendingOutput(); bool OnInvalid(UdpMsg *msg, int len); bool OnSyncRequest(UdpMsg *msg, int len); @@ -123,6 +126,7 @@ class UdpProtocol : public IPollSink bool OnQualityReport(UdpMsg *msg, int len); bool OnQualityReply(UdpMsg *msg, int len); bool OnKeepAlive(UdpMsg *msg, int len); + bool OnChat(UdpMsg *msg, int len); protected: /* @@ -204,6 +208,7 @@ class UdpProtocol : public IPollSink * Event queue */ RingBuffer _event_queue; + std::vector _chatMessages; }; #endif From ac903eae967f16921dee6fa773e1ac4ab309f4c5 Mon Sep 17 00:00:00 2001 From: thomashenry79 Date: Wed, 19 Oct 2022 17:25:30 +0100 Subject: [PATCH 13/40] Desync detection --- src/apps/vectorwar/gamestate.cpp | 7 +- src/apps/vectorwar/gdi_renderer.cpp | 6 + src/apps/vectorwar/nongamestate.h | 3 +- src/apps/vectorwar/vectorwar.cpp | 30 ++++- src/apps/vectorwar/vectorwar.h | 1 + src/include/ggponet.h | 10 +- src/lib/ggpo/backends/backend.h | 2 +- src/lib/ggpo/backends/p2p.cpp | 176 ++++++++++++++++++++++++++-- src/lib/ggpo/backends/p2p.h | 20 +++- src/lib/ggpo/backends/spectator.cpp | 5 +- src/lib/ggpo/backends/spectator.h | 4 +- src/lib/ggpo/backends/synctest.cpp | 5 +- src/lib/ggpo/backends/synctest.h | 2 +- src/lib/ggpo/game_input.h | 6 +- src/lib/ggpo/main.cpp | 4 +- src/lib/ggpo/network/udp_msg.h | 2 + src/lib/ggpo/network/udp_proto.cpp | 20 +++- src/lib/ggpo/network/udp_proto.h | 9 +- src/lib/ggpo/ring_buffer.h | 6 +- src/lib/ggpo/sync.h | 120 +++++++++---------- src/lib/ggpo/timesync.h | 2 +- src/lib/ggpo/types.h | 2 +- 22 files changed, 332 insertions(+), 110 deletions(-) diff --git a/src/apps/vectorwar/gamestate.cpp b/src/apps/vectorwar/gamestate.cpp index 41cae455..e1774969 100644 --- a/src/apps/vectorwar/gamestate.cpp +++ b/src/apps/vectorwar/gamestate.cpp @@ -25,10 +25,11 @@ distance(Position *lhs, Position *rhs) * * Initialize our game state. */ - +#include void GameState::Init(HWND hwnd, int num_players) { + srand((unsigned)time(0)); int i, w, h, r; GetClientRect(hwnd, &_bounds); @@ -79,6 +80,10 @@ void GameState::ParseShipInputs(int inputs, int i, double *heading, double *thru *heading = ship->heading; } + if (inputs & INPUT_RAND) + { + *heading = (ship->heading +rand()%720 -360) % 360; + } if (inputs & INPUT_THRUST) { *thrust = SHIP_THRUST; } else if (inputs & INPUT_BREAK) { diff --git a/src/apps/vectorwar/gdi_renderer.cpp b/src/apps/vectorwar/gdi_renderer.cpp index 0b27b49c..bc220623 100644 --- a/src/apps/vectorwar/gdi_renderer.cpp +++ b/src/apps/vectorwar/gdi_renderer.cpp @@ -97,6 +97,12 @@ GDIRenderer::Draw(GameState &gs, NonGameState &ngs) sprintf_s(statsinfo, ARRAYSIZE(statsinfo), "%d: %d",i, ngs.rollbacksBySize[i]); TextOutA(hdc, _rc.left + 50, _rc.top + 72+(16*i), statsinfo, (int)strlen(statsinfo)); } + if (ngs.desyncFrame >= 0) + { + sprintf_s(statsinfo, ARRAYSIZE(statsinfo), "!!!!!!!!! DESYNC AT FRAME %d", ngs.desyncFrame); + SetTextColor(hdc, RGB(255, 0, 0)); + TextOutA(hdc, (_rc.left + _rc.right) / 2, (_rc.top +_rc.bottom)/2, statsinfo, (int)strlen(statsinfo)); + } //SwapBuffers(hdc); ReleaseDC(_hwnd, hdc); } diff --git a/src/apps/vectorwar/nongamestate.h b/src/apps/vectorwar/nongamestate.h index 571f1e2b..cb15d453 100644 --- a/src/apps/vectorwar/nongamestate.h +++ b/src/apps/vectorwar/nongamestate.h @@ -99,7 +99,7 @@ struct PlayerConnectionInfo { struct NonGameState { struct ChecksumInfo { int framenumber=0; - int checksum=0; + uint16_t checksum=0; }; LoopTimer loopTimer; GGPONetworkStats stats; @@ -152,6 +152,7 @@ struct NonGameState { float totalFrameDelays = 0; ChecksumInfo now; ChecksumInfo periodic; + int desyncFrame = -1; }; #endif diff --git a/src/apps/vectorwar/vectorwar.cpp b/src/apps/vectorwar/vectorwar.cpp index 853d4bd6..8ede0326 100644 --- a/src/apps/vectorwar/vectorwar.cpp +++ b/src/apps/vectorwar/vectorwar.cpp @@ -42,7 +42,20 @@ fletcher32_checksum(short *data, size_t len) sum2 = (sum2 & 0xffff) + (sum2 >> 16); return sum2 << 16 | sum1; } +uint16_t Fletcher16(uint8_t* data, int count) +{ + uint16_t sum1 = 0; + uint16_t sum2 = 0; + int index; + + for (index = 0; index < count; ++index) + { + sum1 = (sum1 + data[index]) % 255; + sum2 = (sum2 + sum1) % 255; + } + return (sum2 << 8) | sum1; +} /* * vw_begin_game_callback -- * @@ -96,6 +109,12 @@ vw_on_event_callback(GGPOEvent *info) case GGPO_EVENTCODE_DISCONNECTED_FROM_PEER: ngs.SetConnectState(info->u.disconnected.player, Disconnected); break; + case GGPO_EVENTCODE_DESYNC: + { + if(ngs.desyncFrame <0) + ngs.desyncFrame = info->u.desync.nFrameOfDesync; + break; + } case GGPO_EVENTCODE_TIMESYNC: ngs.loopTimer.OnGGPOTimeSyncEvent(info->u.timesync.frames_ahead); if (info->u.timesync.frames_ahead > 0) { @@ -245,7 +264,7 @@ VectorWar_Init(HWND hwnd, unsigned short localport, int num_players, GGPOPlayer cb.log_game_state = vw_log_game_state; p1IsLocal = players[0].type == GGPO_PLAYERTYPE_LOCAL; ngs.LocalPLayerNumber = p1IsLocal ? 1 : 2; - ngs.inputDelay = p1IsLocal ? 2 :7; + ngs.inputDelay = p1IsLocal ? 2 : 0; #if defined(SYNC_TEST) result = ggpo_start_synctest(&ggpo, &cb, "vectorwar", num_players, sizeof(int), 1); @@ -363,13 +382,13 @@ void VectorWar_AdvanceFrame(int inputs[], int disconnect_flags) // update the checksums to display in the top of the window. this // helps to detect desyncs. ngs.now.framenumber = gs._framenumber; - ngs.now.checksum = fletcher32_checksum((short *)&gs, sizeof(gs) / 2); + ngs.now.checksum = Fletcher16((uint8_t *)&gs, sizeof(gs)); if ((gs._framenumber % 90) == 0) { ngs.periodic = ngs.now; } // Notify ggpo that we've moved forward exactly 1 frame. - ggpo_advance_frame(ggpo); + ggpo_advance_frame(ggpo, ngs.now.checksum); // Update the performance monitor display. GGPOPlayerHandle handles[MAX_PLAYERS]; @@ -403,6 +422,7 @@ ReadInputs(HWND hwnd) { VK_RIGHT, INPUT_ROTATE_RIGHT }, { 'D', INPUT_FIRE }, { 'S', INPUT_BOMB }, + { 'R', INPUT_RAND }, }; int i, inputs = 0; @@ -443,8 +463,8 @@ VectorWar_RunFrame(HWND hwnd, int&usToWait) if (ngs.local_player_handle != GGPO_INVALID_HANDLE) { static int nc = 0; int input = nc++ % 2 == 0 ? INPUT_ROTATE_LEFT : INPUT_ROTATE_RIGHT; - auto i = ReadInputs(hwnd); - if (i == INPUT_FIRE) + input = ReadInputs(hwnd); + if (input == INPUT_FIRE) ggpo_client_chat(ggpo, "You wanker!"); #if defined(SYNC_TEST) input = rand(); // test: use random inputs to demonstrate sync testing diff --git a/src/apps/vectorwar/vectorwar.h b/src/apps/vectorwar/vectorwar.h index b6d76164..3057760f 100644 --- a/src/apps/vectorwar/vectorwar.h +++ b/src/apps/vectorwar/vectorwar.h @@ -17,6 +17,7 @@ enum VectorWarInputs { INPUT_ROTATE_RIGHT = (1 << 3), INPUT_FIRE = (1 << 4), INPUT_BOMB = (1 << 5), + INPUT_RAND = (1 << 6), }; void VectorWar_Init(HWND hwnd, unsigned short localport, int num_players, GGPOPlayer *players, int num_spectators); diff --git a/src/include/ggponet.h b/src/include/ggponet.h index 75214fc4..bf6ee5e6 100644 --- a/src/include/ggponet.h +++ b/src/include/ggponet.h @@ -13,7 +13,7 @@ extern "C" { #endif #include - +#include // On windows, export at build time and import at runtime. // ELF systems don't need an explicit export/import. #ifdef _WIN32 @@ -154,6 +154,7 @@ typedef enum { GGPO_EVENTCODE_CONNECTION_INTERRUPTED = 1006, GGPO_EVENTCODE_CONNECTION_RESUMED = 1007, GGPO_EVENTCODE_CHAT = 1008, + GGPO_EVENTCODE_DESYNC = 1009 } GGPOEventCode; /* @@ -192,6 +193,11 @@ typedef struct { int senderID; const char* msg; } chat; + struct { + int nFrameOfDesync; + uint16_t ourCheckSum; + uint16_t remoteChecksum; + } desync; } u; } GGPOEvent; @@ -520,7 +526,7 @@ GGPO_API GGPOErrorCode __cdecl ggpo_disconnect_player(GGPOSession *, * you advance the gamestate by a frame, even during rollbacks. GGPO.net * may call your save_state callback before this function returns. */ -GGPO_API GGPOErrorCode __cdecl ggpo_advance_frame(GGPOSession *); +GGPO_API GGPOErrorCode __cdecl ggpo_advance_frame(GGPOSession *, uint16_t checksum); /* * ggpo_get_network_stats -- diff --git a/src/lib/ggpo/backends/backend.h b/src/lib/ggpo/backends/backend.h index 3fcdccb0..64c3c671 100644 --- a/src/lib/ggpo/backends/backend.h +++ b/src/lib/ggpo/backends/backend.h @@ -18,7 +18,7 @@ class GGPOSession { virtual GGPOErrorCode AddPlayer(GGPOPlayer *player, GGPOPlayerHandle *handle) = 0; virtual GGPOErrorCode AddLocalInput(GGPOPlayerHandle player, void *values, int size) = 0; virtual GGPOErrorCode SyncInput(void *values, int size, int *disconnect_flags) = 0; - virtual GGPOErrorCode IncrementFrame(void) = 0; + virtual GGPOErrorCode IncrementFrame(uint16_t checksum) = 0; virtual GGPOErrorCode Chat(const char* text) = 0;// { return GGPO_OK; } virtual GGPOErrorCode DisconnectPlayer(GGPOPlayerHandle handle) = 0;// { return GGPO_OK; } virtual GGPOErrorCode GetNetworkStats(GGPONetworkStats *stats, GGPOPlayerHandle handle) { return GGPO_OK; } diff --git a/src/lib/ggpo/backends/p2p.cpp b/src/lib/ggpo/backends/p2p.cpp index bde00147..4f5363e7 100644 --- a/src/lib/ggpo/backends/p2p.cpp +++ b/src/lib/ggpo/backends/p2p.cpp @@ -43,7 +43,7 @@ Peer2PeerBackend::Peer2PeerBackend(GGPOSessionCallbacks *cb, */ _udp.Init(localport, &_poll, this); - _endpoints = new UdpProtocol[_num_players]; + _endpoints.resize(_num_players); memset(_local_connect_status, 0, sizeof(_local_connect_status)); for (int i = 0; i < ARRAY_SIZE(_local_connect_status); i++) { _local_connect_status[i].last_frame = -1; @@ -57,7 +57,6 @@ Peer2PeerBackend::Peer2PeerBackend(GGPOSessionCallbacks *cb, Peer2PeerBackend::~Peer2PeerBackend() { - delete [] _endpoints; } void @@ -97,7 +96,59 @@ GGPOErrorCode Peer2PeerBackend::AddSpectator(char *ip, return GGPO_OK; } - +void Peer2PeerBackend::CheckDesync() +{ + std::vector keysToRemove; + for (auto& ep : _endpoints) + { + for (const auto& pair : ep._remoteCheckSums) + { + auto checkSumFrame = pair.first; + auto remoteChecksum = pair.second; + + if (_confirmedCheckSums.count(checkSumFrame)) + { + keysToRemove.push_back(checkSumFrame); + auto localChecksum = _confirmedCheckSums.at(checkSumFrame); + + if (remoteChecksum != localChecksum) + { + GGPOEvent info; + info.code = GGPO_EVENTCODE_DESYNC; + info.u.desync.nFrameOfDesync = checkSumFrame; + info.u.desync.ourCheckSum = localChecksum; + info.u.desync.remoteChecksum = remoteChecksum; + _callbacks.on_event(&info); + + char buf[256]; + sprintf_s<256>(buf, "DESYNC Checksum frame %d, local: %d, remote %d, size of checksum maps: %d,%d", checkSumFrame, localChecksum, remoteChecksum, (int)_confirmedCheckSums.size(), (int)ep._remoteCheckSums.size()); + // OutputDebugStringA(buf); + } + + if (checkSumFrame % 100 == 0) + { + char buf[256]; + sprintf_s<256>(buf, "Checksum frame %d, local: %d, remote %d, size of checksum maps: %d,%d\n", checkSumFrame, localChecksum, remoteChecksum, (int)_confirmedCheckSums.size(), (int)ep._remoteCheckSums.size()); + //OutputDebugStringA(buf); + } + } + } + for (auto k : keysToRemove) + { + ep._remoteCheckSums.erase(k); + } + } + for (auto k : keysToRemove) + { + char buf[256]; + sprintf_s<256>(buf, "Erase checksums for frame %d\n",k); + // OutputDebugStringA(buf); + + _confirmedCheckSums.erase(k); + // ep._remoteCheckSums.erase(k); + } + +} GGPOErrorCode Peer2PeerBackend::DoPoll() { @@ -116,7 +167,7 @@ Peer2PeerBackend::DoPoll() _poll.Pump(0); PollUdpProtocolEvents(); - + CheckDesync(); if (!_synchronizing) { _sync.CheckSimulation(); @@ -301,6 +352,22 @@ Peer2PeerBackend::AddLocalInput(GGPOPlayerHandle player, // confirmed local frame for this player. this must come first so it // gets incorporated into the next packet we send. + // Send checksum for frames old enough to be confirmed (ie older then current - MaxPredictionFrames()) + + + + _confirmedCheckSumFrame = input.frame - HowFarBackForChecksums(); + + + input.checksum = 0; + if (_confirmedCheckSumFrame >= 0) { + char buf[128]; + input.checksum = _pendingCheckSums.at(_confirmedCheckSumFrame); + _confirmedCheckSums[_confirmedCheckSumFrame] = input.checksum; + _pendingCheckSums.erase(_confirmedCheckSumFrame); + sprintf_s<128>(buf, "Frame %d: Send checksum for frame %d, val %d\n", input.frame, _confirmedCheckSumFrame, input.checksum); + //OutputDebugStringA(buf); + } Log("setting local connect status for local queue %d to %d", queue, input.frame); _local_connect_status[queue].last_frame = input.frame; @@ -335,14 +402,55 @@ Peer2PeerBackend::SyncInput(void *values, } GGPOErrorCode -Peer2PeerBackend::IncrementFrame(void) +Peer2PeerBackend::IncrementFrame(uint16_t checksum1) { - Log("End of frame (%d)...\n", _sync.GetFrameCount()); - _sync.IncrementFrame(); - DoPoll(); - PollSyncEvents(); + auto currentFrame = _sync.GetFrameCount(); + char buf[256]; + uint16_t cSum = checksum1; + Log("End of frame (%d)...\n", _sync.GetFrameCount()); + // OutputDebugStringA("cock\n"); + static int maxDif = 0; + if (_pendingCheckSums.count(_sync.GetFrameCount())) + { + // OutputDebugStringA("cunt\n"); + auto max = _pendingCheckSums.rbegin()->first; + auto diff = max - currentFrame; + maxDif = max(maxDif, diff); + int oldChecksum = _pendingCheckSums[_sync.GetFrameCount()]; + _pendingCheckSums[_sync.GetFrameCount()] = cSum; + sprintf_s<256>(buf, "Replace local checksum for frame %d: %d with %d, newest frame is %d, max diff %d\n", _sync.GetFrameCount(), oldChecksum, _pendingCheckSums[_sync.GetFrameCount()], max, maxDif); + // OutputDebugStringA(buf); + + if (currentFrame <= _confirmedCheckSumFrame) + { + sprintf_s<256>(buf, "Changing frame %d in a rollback, but we've already sent frame %d\n", currentFrame, _confirmedCheckSumFrame); + + OutputDebugStringA(buf); + throw std::exception(buf); + } + if (diff >= (_sync.MaxPredictionFrames())) { - return GGPO_OK; + sprintf_s<256>(buf, "diff is bigger than max prediction\n"); + + OutputDebugStringA(buf); + throw std::exception(buf); + } + } + else + { + sprintf_s<256>(buf, "Added local checksum for frame %d: %d\n", _sync.GetFrameCount(), cSum); + // OutputDebugStringA(buf); + } + + _pendingCheckSums[_sync.GetFrameCount()]= cSum ; + + + + _sync.IncrementFrame(); + DoPoll(); + PollSyncEvents(); + + return GGPO_OK; } @@ -372,6 +480,36 @@ Peer2PeerBackend::PollUdpProtocolEvents(void) } } +void Peer2PeerBackend::CheckRemoteChecksum(int framenumber, uint16 cs) +{ + if (framenumber <= _sync.MaxPredictionFrames()) + return; + framenumber; cs; + //auto frameOfChecksumToSend = framenumber - (_sync.MaxPredictionFrames() + 1); + +} + +int Peer2PeerBackend::HowFarBackForChecksums()const +{ + return _sync.MaxPredictionFrames()+1; +}/* +uint16 Peer2PeerBackend::GetChecksumForConfirmedFrame(int frameNumber) const +{ + + + auto frameOfChecksumToSend = frameNumber - HowFarBackForChecksums(); + if (frameOfChecksumToSend < 0) + return 0; + + if (_checkSums.count(frameOfChecksumToSend) == 0) + { + char s[128]; + sprintf_s<128>(s, "No local checksum found, remote frame is %d, adjusted is %d, most recent we have is %d\n", frameNumber, frameOfChecksumToSend, _checkSums.rbegin()->first); + OutputDebugStringA(s); + throw std::exception("s"); + } + return _checkSums.at(frameOfChecksumToSend); +}*/ void Peer2PeerBackend::OnUdpProtocolPeerEvent(UdpProtocol::Event &evt, int queue) { @@ -387,6 +525,20 @@ Peer2PeerBackend::OnUdpProtocolPeerEvent(UdpProtocol::Event &evt, int queue) // Notify the other endpoints which frame we received from a peer Log("setting remote connect status for queue %d to %d\n", queue, evt.u.input.input.frame); _local_connect_status[queue].last_frame = evt.u.input.input.frame; + + auto remoteChecksum = evt.u.input.input.checksum; + int checkSumFrame = new_remote_frame - HowFarBackForChecksums(); + if (checkSumFrame >= _endpoints[queue].RemoteFrameDelay()-1) + _endpoints[queue]._remoteCheckSums[checkSumFrame] = remoteChecksum; + // auto localChecksum = GetChecksumForConfirmedFrame(new_remote_frame); + // + + if (checkSumFrame %120==0) + { + char buf[256]; + sprintf_s<256>(buf, "Received checksum for frame %d, remote cs is %d\n", checkSumFrame, remoteChecksum); + //OutputDebugStringA(buf); + } } break; @@ -509,11 +661,11 @@ Peer2PeerBackend::DisconnectPlayerQueue(int queue, int syncto) _local_connect_status[queue].disconnected = 1; _local_connect_status[queue].last_frame = syncto; - if (syncto < framecount) { + /*if (syncto < framecount) { Log("adjusting simulation to account for the fact that %d disconnected @ %d.\n", queue, syncto); _sync.AdjustSimulation(syncto); Log("finished adjusting simulation.\n"); - } + }*/ info.code = GGPO_EVENTCODE_DISCONNECTED_FROM_PEER; info.u.disconnected.player = QueueToPlayerHandle(queue); diff --git a/src/lib/ggpo/backends/p2p.h b/src/lib/ggpo/backends/p2p.h index 462569f0..ad28452c 100644 --- a/src/lib/ggpo/backends/p2p.h +++ b/src/lib/ggpo/backends/p2p.h @@ -14,8 +14,8 @@ #include "backend.h" #include "timesync.h" #include "network/udp_proto.h" - -class Peer2PeerBackend : public GGPOSession, /*IPollSink,*/ Udp::Callbacks { +#include +class Peer2PeerBackend : public GGPOSession, Udp::Callbacks { public: Peer2PeerBackend(GGPOSessionCallbacks *cb, const char *gamename, uint16 localport, int num_players, int input_size, int nframes); virtual ~Peer2PeerBackend(); @@ -26,7 +26,7 @@ class Peer2PeerBackend : public GGPOSession, /*IPollSink,*/ Udp::Callbacks { virtual GGPOErrorCode AddPlayer(GGPOPlayer *player, GGPOPlayerHandle *handle) override; virtual GGPOErrorCode AddLocalInput(GGPOPlayerHandle player, void *values, int size) override; virtual GGPOErrorCode SyncInput(void *values, int size, int *disconnect_flags) override; - virtual GGPOErrorCode IncrementFrame(void) override; + virtual GGPOErrorCode IncrementFrame(uint16_t checksum) override; virtual GGPOErrorCode DisconnectPlayer(GGPOPlayerHandle handle) override; virtual GGPOErrorCode GetNetworkStats(GGPONetworkStats *stats, GGPOPlayerHandle handle) override; virtual GGPOErrorCode SetFrameDelay(GGPOPlayerHandle player, int delay) override; @@ -58,7 +58,7 @@ class Peer2PeerBackend : public GGPOSession, /*IPollSink,*/ Udp::Callbacks { Poll _poll; Sync _sync; Udp _udp; - UdpProtocol *_endpoints; + std::vector _endpoints; UdpProtocol _spectators[GGPO_MAX_SPECTATORS]; int _num_spectators; int _input_size; @@ -72,6 +72,18 @@ class Peer2PeerBackend : public GGPOSession, /*IPollSink,*/ Udp::Callbacks { int _disconnect_notify_start; UdpMsg::connect_status _local_connect_status[UDP_MSG_MAX_PLAYERS]; + struct ChecksumEntry { + int nFrame; + int checkSum;; + }; + std::map _pendingCheckSums; + std::map _confirmedCheckSums; + + // uint16 GetChecksumForConfirmedFrame(int frameNumber) const; + void CheckRemoteChecksum(int framenumber, uint16 cs); + int HowFarBackForChecksums()const; + int _confirmedCheckSumFrame = -500; + void CheckDesync(); }; #endif diff --git a/src/lib/ggpo/backends/spectator.cpp b/src/lib/ggpo/backends/spectator.cpp index e56d7e48..04644cd5 100644 --- a/src/lib/ggpo/backends/spectator.cpp +++ b/src/lib/ggpo/backends/spectator.cpp @@ -87,8 +87,9 @@ SpectatorBackend::SyncInput(void *values, } GGPOErrorCode -SpectatorBackend::IncrementFrame(void) -{ +SpectatorBackend::IncrementFrame(uint16_t checksum) +{ + checksum; Log("End of frame (%d)...\n", _next_input_to_send - 1); DoPoll(); PollUdpProtocolEvents(); diff --git a/src/lib/ggpo/backends/spectator.h b/src/lib/ggpo/backends/spectator.h index 6fbcb41b..5b4dace4 100644 --- a/src/lib/ggpo/backends/spectator.h +++ b/src/lib/ggpo/backends/spectator.h @@ -17,7 +17,7 @@ #define SPECTATOR_FRAME_BUFFER_SIZE 64 -class SpectatorBackend : public GGPOSession, /*IPollSink,*/ Udp::Callbacks { +class SpectatorBackend : public GGPOSession, Udp::Callbacks { public: SpectatorBackend(GGPOSessionCallbacks *cb, const char *gamename, uint16 localport, int num_players, int input_size, char *hostip, u_short hostport); virtual ~SpectatorBackend(); @@ -28,7 +28,7 @@ class SpectatorBackend : public GGPOSession, /*IPollSink,*/ Udp::Callbacks { virtual GGPOErrorCode AddPlayer(GGPOPlayer *player, GGPOPlayerHandle *handle) { return GGPO_ERRORCODE_UNSUPPORTED; } virtual GGPOErrorCode AddLocalInput(GGPOPlayerHandle player, void *values, int size) { return GGPO_OK; } virtual GGPOErrorCode SyncInput(void *values, int size, int *disconnect_flags); - virtual GGPOErrorCode IncrementFrame(void); + virtual GGPOErrorCode IncrementFrame(uint16_t); virtual GGPOErrorCode DisconnectPlayer(GGPOPlayerHandle handle) { return GGPO_ERRORCODE_UNSUPPORTED; } virtual GGPOErrorCode GetNetworkStats(GGPONetworkStats *stats, GGPOPlayerHandle handle) { return GGPO_ERRORCODE_UNSUPPORTED; } virtual GGPOErrorCode SetFrameDelay(GGPOPlayerHandle player, int delay) { return GGPO_ERRORCODE_UNSUPPORTED; } diff --git a/src/lib/ggpo/backends/synctest.cpp b/src/lib/ggpo/backends/synctest.cpp index dcc6e23b..bc7931ef 100644 --- a/src/lib/ggpo/backends/synctest.cpp +++ b/src/lib/ggpo/backends/synctest.cpp @@ -100,8 +100,9 @@ SyncTestBackend::SyncInput(void *values, } GGPOErrorCode -SyncTestBackend::IncrementFrame(void) -{ +SyncTestBackend::IncrementFrame(uint16_t cs) +{ + cs; _sync.IncrementFrame(); _current_input.erase(); diff --git a/src/lib/ggpo/backends/synctest.h b/src/lib/ggpo/backends/synctest.h index aef23fec..44a6abca 100644 --- a/src/lib/ggpo/backends/synctest.h +++ b/src/lib/ggpo/backends/synctest.h @@ -22,7 +22,7 @@ class SyncTestBackend : public GGPOSession { virtual GGPOErrorCode AddPlayer(GGPOPlayer *player, GGPOPlayerHandle *handle); virtual GGPOErrorCode AddLocalInput(GGPOPlayerHandle player, void *values, int size); virtual GGPOErrorCode SyncInput(void *values, int size, int *disconnect_flags); - virtual GGPOErrorCode IncrementFrame(void); + virtual GGPOErrorCode IncrementFrame(uint16_t checksum); virtual GGPOErrorCode Logv(char *fmt, va_list list); virtual GGPOErrorCode DisconnectPlayer(GGPOPlayerHandle handle) { return GGPO_OK; } virtual GGPOErrorCode Chat(const char* text) override { return GGPO_ERRORCODE_UNSUPPORTED; } diff --git a/src/lib/ggpo/game_input.h b/src/lib/ggpo/game_input.h index bd3910ce..a19b834b 100644 --- a/src/lib/ggpo/game_input.h +++ b/src/lib/ggpo/game_input.h @@ -14,8 +14,8 @@ // GAMEINPUT_MAX_BYTES * GAMEINPUT_MAX_PLAYERS * 8 must be less than // 2^BITVECTOR_NIBBLE_SIZE (see bitvector.h) -#define GAMEINPUT_MAX_BYTES 9 -#define GAMEINPUT_MAX_PLAYERS 2 +#define GAMEINPUT_MAX_BYTES 4 +#define GAMEINPUT_MAX_PLAYERS 6 struct GameInput { enum Constants { @@ -24,7 +24,7 @@ struct GameInput { int frame; int size; /* size in bytes of the entire input for all players */ char bits[GAMEINPUT_MAX_BYTES * GAMEINPUT_MAX_PLAYERS]; - + uint16 checksum; bool is_null() { return frame == NullFrame; } void init(int frame, char *bits, int size, int offset); void init(int frame, char *bits, int size); diff --git a/src/lib/ggpo/main.cpp b/src/lib/ggpo/main.cpp index 5d06cae7..7b750105 100644 --- a/src/lib/ggpo/main.cpp +++ b/src/lib/ggpo/main.cpp @@ -132,12 +132,12 @@ GGPOErrorCode ggpo_disconnect_player(GGPOSession *ggpo, } GGPOErrorCode -ggpo_advance_frame(GGPOSession *ggpo) +ggpo_advance_frame(GGPOSession *ggpo, uint16_t checksum) { if (!ggpo) { return GGPO_ERRORCODE_INVALID_SESSION; } - return ggpo->IncrementFrame(); + return ggpo->IncrementFrame(checksum); } GGPOErrorCode diff --git a/src/lib/ggpo/network/udp_msg.h b/src/lib/ggpo/network/udp_msg.h index 41f75091..e21d24f2 100644 --- a/src/lib/ggpo/network/udp_msg.h +++ b/src/lib/ggpo/network/udp_msg.h @@ -42,6 +42,7 @@ struct UdpMsg uint32 random_request; /* please reply back with this random data */ uint16 remote_magic; uint8 remote_endpoint; + uint8 remote_inputDelay; } sync_request; struct { @@ -66,6 +67,7 @@ struct UdpMsg int ack_frame:31; uint16 num_bits; + uint16 checksum16; uint8 input_size; // XXX: shouldn't be in every single packet! uint8 bits[MAX_COMPRESSED_BITS]; /* must be last */ } input; diff --git a/src/lib/ggpo/network/udp_proto.cpp b/src/lib/ggpo/network/udp_proto.cpp index 131b4ee2..10a971c6 100644 --- a/src/lib/ggpo/network/udp_proto.cpp +++ b/src/lib/ggpo/network/udp_proto.cpp @@ -65,6 +65,11 @@ void UdpProtocol::SetFrameDelay(int delay) { _timesync.SetFrameDelay(delay); } + +int UdpProtocol::RemoteFrameDelay()const +{ + return _timesync._remoteFrameDelay; +} void UdpProtocol::Init(Udp *udp, Poll &poll, @@ -125,10 +130,11 @@ UdpProtocol::SendPendingOutput() msg->u.input.start_frame = _pending_output.front().frame; msg->u.input.input_size = (uint8)_pending_output.front().size; - + ASSERT(last.frame == -1 || last.frame + 1 == msg->u.input.start_frame); - for (j = 0; j < _pending_output.size(); j++) { + for (j = 0; j < _pending_output.size(); j++) { GameInput ¤t = _pending_output.item(j); + msg->u.input.checksum16 = current.checksum; if (memcmp(current.bits, last.bits, current.size) != 0) { ASSERT((GAMEINPUT_MAX_BYTES * GAMEINPUT_MAX_PLAYERS * 8) < (1 << BITVECTOR_NIBBLE_SIZE)); for (i = 0; i < current.size * 8; i++) { @@ -280,6 +286,7 @@ UdpProtocol::SendSyncRequest() _state.sync.random = rand() & 0xFFFF; UdpMsg *msg = new UdpMsg(UdpMsg::SyncRequest); msg->u.sync_request.random_request = _state.sync.random; + msg->u.sync_request.remote_inputDelay = (uint8_t)_timesync._frameDelay2; SendMsg(msg); } @@ -489,6 +496,8 @@ UdpProtocol::OnSyncRequest(UdpMsg *msg, int len) } UdpMsg *reply = new UdpMsg(UdpMsg::SyncReply); reply->u.sync_reply.random_reply = msg->u.sync_request.random_request; + _timesync._remoteFrameDelay = msg->u.sync_request.remote_inputDelay; + SendMsg(reply); return true; } @@ -564,7 +573,6 @@ UdpProtocol::OnInput(UdpMsg *msg, int len) uint8 *bits = (uint8 *)msg->u.input.bits; int numBits = msg->u.input.num_bits; int currentFrame = msg->u.input.start_frame; - _last_received_input.size = msg->u.input.input_size; if (_last_received_input.frame < 0) { _last_received_input.frame = msg->u.input.start_frame - 1; @@ -601,7 +609,7 @@ UdpProtocol::OnInput(UdpMsg *msg, int len) char desc[1024]; ASSERT(currentFrame == _last_received_input.frame + 1); _last_received_input.frame = currentFrame; - + _last_received_input.checksum = msg->u.input.checksum16; /* * Send the event to the emualtor */ @@ -669,6 +677,8 @@ bool UdpProtocol::OnQualityReply(UdpMsg *msg, int len) { _round_trip_time = Platform::GetCurrentTimeMS() - msg->u.quality_reply.pong; + + return true; } @@ -709,7 +719,7 @@ UdpProtocol::SetLocalFrameNumber(int localFrame) * last frame they gave us plus some delta for the one-way packet * trip time. */ - float remoteFrame = _last_received_input.frame + (_round_trip_time * 60.f /2000); + float remoteFrame = _last_received_input.frame + (_round_trip_time * 60.f / 2000); /* * Our frame advantage is how many frames *behind* the other guy diff --git a/src/lib/ggpo/network/udp_proto.h b/src/lib/ggpo/network/udp_proto.h index 3b06f37a..f8e479bc 100644 --- a/src/lib/ggpo/network/udp_proto.h +++ b/src/lib/ggpo/network/udp_proto.h @@ -18,6 +18,7 @@ #include #include #include +#include class UdpProtocol : public IPollSink { public: @@ -86,11 +87,12 @@ class UdpProtocol : public IPollSink void GGPONetworkStats(Stats *stats); void SetLocalFrameNumber(int num); float RecommendFrameDelay(); - + int RemoteFrameDelay()const; void SetDisconnectTimeout(int timeout); void SetDisconnectNotifyStart(int timeout); void SetFrameDelay(int delay); void ConsumeChat(std::function onChat); + std::map _remoteCheckSums; protected: enum State { Syncing, @@ -107,7 +109,6 @@ class UdpProtocol : public IPollSink QueueEntry(int time, sockaddr_in &dst, UdpMsg *m) : queue_time(time), dest_addr(dst), msg(m) { } }; - bool CreateSocket(int retries); void UpdateNetworkStats(void); void QueueEvent(const UdpProtocol::Event &evt); void ClearSendQueue(void); @@ -127,7 +128,7 @@ class UdpProtocol : public IPollSink bool OnQualityReply(UdpMsg *msg, int len); bool OnKeepAlive(UdpMsg *msg, int len); bool OnChat(UdpMsg *msg, int len); - + protected: /* * Network transmission information @@ -150,7 +151,7 @@ class UdpProtocol : public IPollSink /* * Stats */ - int _round_trip_time; + int _round_trip_time = 0; int _packets_sent; int _bytes_sent; int _kbps_sent; diff --git a/src/lib/ggpo/ring_buffer.h b/src/lib/ggpo/ring_buffer.h index 9a5d9d6a..81c93960 100644 --- a/src/lib/ggpo/ring_buffer.h +++ b/src/lib/ggpo/ring_buffer.h @@ -28,6 +28,10 @@ template class RingBuffer ASSERT(i < _size); return _elements[(_tail + i) % N]; } + const T& item(int i) const { + ASSERT(i < _size); + return _elements[(_tail + i) % N]; + } void pop() { ASSERT(_size != N); @@ -42,7 +46,7 @@ template class RingBuffer _size++; } - int size() { + int size() const { return _size; } diff --git a/src/lib/ggpo/sync.h b/src/lib/ggpo/sync.h index 98b13504..f5ac6803 100644 --- a/src/lib/ggpo/sync.h +++ b/src/lib/ggpo/sync.h @@ -21,74 +21,74 @@ class SyncTestBackend; class Sync { public: - struct Config { - GGPOSessionCallbacks callbacks; - int num_prediction_frames; - int num_players; - int input_size; - }; - struct Event { - enum { - ConfirmedInput, - } type; - union { - struct { - GameInput input; - } confirmedInput; - } u; - }; + struct Config { + GGPOSessionCallbacks callbacks; + int num_prediction_frames; + int num_players; + int input_size; + }; + struct Event { + enum { + ConfirmedInput, + } type; + union { + struct { + GameInput input; + } confirmedInput; + } u; + }; public: - Sync(UdpMsg::connect_status *connect_status, int maxPrediction); - virtual ~Sync(); + Sync(UdpMsg::connect_status* connect_status, int maxPrediction); + virtual ~Sync(); - void Init(Config &config); + void Init(Config& config); - void SetLastConfirmedFrame(int frame); - void SetFrameDelay(int queue, int delay); - bool AddLocalInput(int queue, GameInput &input); - void AddRemoteInput(int queue, GameInput &input); - int GetConfirmedInputs(void *values, int size, int frame); - int SynchronizeInputs(void *values, int size); + void SetLastConfirmedFrame(int frame); + void SetFrameDelay(int queue, int delay); + bool AddLocalInput(int queue, GameInput& input); + void AddRemoteInput(int queue, GameInput& input); + int GetConfirmedInputs(void* values, int size, int frame); + int SynchronizeInputs(void* values, int size); - void CheckSimulation(); - void AdjustSimulation(int seek_to); - void IncrementFrame(void); + void CheckSimulation(); + void AdjustSimulation(int seek_to); + void IncrementFrame(void); - int GetFrameCount() { return _framecount; } - bool InRollback() { return _rollingback; } - - bool GetEvent(Event &e); + int GetFrameCount() { return _framecount; } + bool InRollback() { return _rollingback; } + bool GetEvent(Event& e); + int MaxPredictionFrames() const { return _max_prediction_frames; } protected: - friend SyncTestBackend; - - struct SavedFrame { - byte *buf; - int cbuf; - int frame; - int checksum; - SavedFrame() : buf(NULL), cbuf(0), frame(-1), checksum(0) { } - }; - struct SavedState { - SavedState(int max_prediction) { - frames.resize(max_prediction + 2); - head = 0; - - } - std::vector frames;// [MAX_PREDICTION_FRAMES + 2] ; - int head; - }; - - void LoadFrame(int frame, int framesToRollback); - void SaveCurrentFrame(); - int FindSavedFrameIndex(int frame); - SavedFrame &GetLastSavedFrame(); - - bool CreateQueues(Config &config); - bool CheckSimulationConsistency(int *seekTo); - void ResetPrediction(int frameNumber); - + friend SyncTestBackend; + + struct SavedFrame { + byte* buf; + int cbuf; + int frame; + int checksum; + SavedFrame() : buf(NULL), cbuf(0), frame(-1), checksum(0) { } + }; + struct SavedState { + SavedState(int max_prediction) { + frames.resize(max_prediction + 2); + head = 0; + + } + std::vector frames;// [MAX_PREDICTION_FRAMES + 2] ; + int head; + }; + + void LoadFrame(int frame, int framesToRollback); + void SaveCurrentFrame(); + int FindSavedFrameIndex(int frame); + SavedFrame& GetLastSavedFrame(); + + bool CreateQueues(Config& config); + bool CheckSimulationConsistency(int* seekTo); + void ResetPrediction(int frameNumber); + protected: GGPOSessionCallbacks _callbacks; SavedState _savedstate; diff --git a/src/lib/ggpo/timesync.h b/src/lib/ggpo/timesync.h index a99f123c..2452d16a 100644 --- a/src/lib/ggpo/timesync.h +++ b/src/lib/ggpo/timesync.h @@ -29,7 +29,7 @@ class TimeSync { float AvgRemoteAdvantageSinceStart() const { return _avgRemote; } void SetFrameDelay(int frame); int _frameDelay2 ; - + int _remoteFrameDelay = 0;; protected: float _local[FRAME_WINDOW_SIZE]; float _remote[FRAME_WINDOW_SIZE]; diff --git a/src/lib/ggpo/types.h b/src/lib/ggpo/types.h index a799f6f8..05dbce29 100644 --- a/src/lib/ggpo/types.h +++ b/src/lib/ggpo/types.h @@ -32,7 +32,7 @@ typedef unsigned char byte; typedef char int8; typedef short int16; typedef int int32; - +#include /* * Additional headers */ From 92be39c9e4971480c8bc0160d2996f5764c1746d Mon Sep 17 00:00:00 2001 From: thomashenry79 Date: Thu, 20 Oct 2022 13:55:06 +0100 Subject: [PATCH 14/40] improvements --- src/apps/vectorwar/vectorwar.cpp | 4 ++-- src/lib/ggpo/backends/p2p.cpp | 16 ++++++++++++---- src/lib/ggpo/network/udp_proto.cpp | 21 ++++++++++++++++++++- src/lib/ggpo/network/udp_proto.h | 5 ++++- 4 files changed, 38 insertions(+), 8 deletions(-) diff --git a/src/apps/vectorwar/vectorwar.cpp b/src/apps/vectorwar/vectorwar.cpp index 8ede0326..4e7a39c0 100644 --- a/src/apps/vectorwar/vectorwar.cpp +++ b/src/apps/vectorwar/vectorwar.cpp @@ -118,7 +118,7 @@ vw_on_event_callback(GGPOEvent *info) case GGPO_EVENTCODE_TIMESYNC: ngs.loopTimer.OnGGPOTimeSyncEvent(info->u.timesync.frames_ahead); if (info->u.timesync.frames_ahead > 0) { - Sleep(max(1, (int)(1000.0f * info->u.timesync.frames_ahead / 60.f))); + //Sleep(max(1, (int)(1000.0f * info->u.timesync.frames_ahead / 60.f))); ngs.nTimeSyncs++; ngs.totalFrameDelays += info->u.timesync.frames_ahead; } @@ -264,7 +264,7 @@ VectorWar_Init(HWND hwnd, unsigned short localport, int num_players, GGPOPlayer cb.log_game_state = vw_log_game_state; p1IsLocal = players[0].type == GGPO_PLAYERTYPE_LOCAL; ngs.LocalPLayerNumber = p1IsLocal ? 1 : 2; - ngs.inputDelay = p1IsLocal ? 2 : 0; + ngs.inputDelay = p1IsLocal ? 6 : 2; #if defined(SYNC_TEST) result = ggpo_start_synctest(&ggpo, &cb, "vectorwar", num_players, sizeof(int), 1); diff --git a/src/lib/ggpo/backends/p2p.cpp b/src/lib/ggpo/backends/p2p.cpp index 4f5363e7..93eb75de 100644 --- a/src/lib/ggpo/backends/p2p.cpp +++ b/src/lib/ggpo/backends/p2p.cpp @@ -143,7 +143,7 @@ void Peer2PeerBackend::CheckDesync() char buf[256]; sprintf_s<256>(buf, "Erase checksums for frame %d\n",k); // OutputDebugStringA(buf); - +// _confirmedCheckSums.erase(k); // ep._remoteCheckSums.erase(k); } @@ -439,7 +439,7 @@ Peer2PeerBackend::IncrementFrame(uint16_t checksum1) else { sprintf_s<256>(buf, "Added local checksum for frame %d: %d\n", _sync.GetFrameCount(), cSum); - // OutputDebugStringA(buf); + // OutputDebugStringA(buf); } _pendingCheckSums[_sync.GetFrameCount()]= cSum ; @@ -469,15 +469,23 @@ Peer2PeerBackend::PollUdpProtocolEvents(void) { UdpProtocol::Event evt; for (int i = 0; i < _num_players; i++) { + _endpoints[i].StartPollLoop(); while (_endpoints[i].GetEvent(evt)) { OnUdpProtocolPeerEvent(evt, i); } + _endpoints[i].EndPollLoop(); } for (int i = 0; i < _num_spectators; i++) { while (_spectators[i].GetEvent(evt)) { OnUdpProtocolSpectatorEvent(evt, i); } } + + //for (int i = 0; i < _num_players; i++) { +// _endpoints[i].ApplyToEvents([&](UdpProtocol::Event& e) { +// OnUdpProtocolPeerEvent(evt, i); +// }); +//} } void Peer2PeerBackend::CheckRemoteChecksum(int framenumber, uint16 cs) @@ -491,7 +499,7 @@ void Peer2PeerBackend::CheckRemoteChecksum(int framenumber, uint16 cs) int Peer2PeerBackend::HowFarBackForChecksums()const { - return _sync.MaxPredictionFrames()+1; + return _sync.MaxPredictionFrames()+8; }/* uint16 Peer2PeerBackend::GetChecksumForConfirmedFrame(int frameNumber) const { @@ -529,7 +537,7 @@ Peer2PeerBackend::OnUdpProtocolPeerEvent(UdpProtocol::Event &evt, int queue) auto remoteChecksum = evt.u.input.input.checksum; int checkSumFrame = new_remote_frame - HowFarBackForChecksums(); if (checkSumFrame >= _endpoints[queue].RemoteFrameDelay()-1) - _endpoints[queue]._remoteCheckSums[checkSumFrame] = remoteChecksum; + _endpoints[queue]._remoteCheckSumsThisFrame[checkSumFrame] = remoteChecksum; // auto localChecksum = GetChecksumForConfirmedFrame(new_remote_frame); // diff --git a/src/lib/ggpo/network/udp_proto.cpp b/src/lib/ggpo/network/udp_proto.cpp index 10a971c6..f558336c 100644 --- a/src/lib/ggpo/network/udp_proto.cpp +++ b/src/lib/ggpo/network/udp_proto.cpp @@ -186,7 +186,25 @@ UdpProtocol::GetEvent(UdpProtocol::Event &e) _event_queue.pop(); return true; } +void UdpProtocol::ApplyToEvents(std::function cb) +{ + StartPollLoop(); + UdpProtocol::Event evt; + while (GetEvent(evt)) { + cb(evt); + } + EndPollLoop(); +} +void UdpProtocol::StartPollLoop() +{ + _remoteCheckSumsThisFrame.clear(); +} +void UdpProtocol::EndPollLoop() +{ + if (_remoteCheckSumsThisFrame.size()) + _remoteCheckSums.emplace(*_remoteCheckSumsThisFrame.rbegin()); +} void UdpProtocol::SendChat(const char* message) { UdpMsg* msg = new UdpMsg(UdpMsg::Chat); @@ -620,7 +638,8 @@ UdpProtocol::OnInput(UdpMsg *msg, int len) _state.running.last_input_packet_recv_time = Platform::GetCurrentTimeMS(); - Log("Sending frame %d to emu queue %d (%s).\n", _last_received_input.frame, _queue, desc); + Log("Sending frame %d to emu queue %d, (%s).\n", _last_received_input.frame, _queue,desc); + QueueEvent(evt); } else { diff --git a/src/lib/ggpo/network/udp_proto.h b/src/lib/ggpo/network/udp_proto.h index f8e479bc..14947e27 100644 --- a/src/lib/ggpo/network/udp_proto.h +++ b/src/lib/ggpo/network/udp_proto.h @@ -84,7 +84,6 @@ class UdpProtocol : public IPollSink void GetNetworkStats(struct GGPONetworkStats *stats); bool GetEvent(UdpProtocol::Event &e); - void GGPONetworkStats(Stats *stats); void SetLocalFrameNumber(int num); float RecommendFrameDelay(); int RemoteFrameDelay()const; @@ -92,7 +91,11 @@ class UdpProtocol : public IPollSink void SetDisconnectNotifyStart(int timeout); void SetFrameDelay(int delay); void ConsumeChat(std::function onChat); + void ApplyToEvents(std::function cb); + void StartPollLoop(); + void EndPollLoop(); std::map _remoteCheckSums; + std::map _remoteCheckSumsThisFrame; protected: enum State { Syncing, From 256463fe4b4384d0952413a837bcd50725320cb7 Mon Sep 17 00:00:00 2001 From: thomashenry79 Date: Thu, 20 Oct 2022 14:13:53 +0100 Subject: [PATCH 15/40] remove things --- src/lib/ggpo/backends/p2p.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/lib/ggpo/backends/p2p.cpp b/src/lib/ggpo/backends/p2p.cpp index 93eb75de..e6664a4f 100644 --- a/src/lib/ggpo/backends/p2p.cpp +++ b/src/lib/ggpo/backends/p2p.cpp @@ -143,8 +143,9 @@ void Peer2PeerBackend::CheckDesync() char buf[256]; sprintf_s<256>(buf, "Erase checksums for frame %d\n",k); // OutputDebugStringA(buf); -// - _confirmedCheckSums.erase(k); + for (auto itr = _confirmedCheckSums.cbegin(); itr != _confirmedCheckSums.cend(); ) + itr = (itr->first <=k) ? _confirmedCheckSums.erase(itr) : std::next(itr); + // ep._remoteCheckSums.erase(k); } @@ -439,7 +440,7 @@ Peer2PeerBackend::IncrementFrame(uint16_t checksum1) else { sprintf_s<256>(buf, "Added local checksum for frame %d: %d\n", _sync.GetFrameCount(), cSum); - // OutputDebugStringA(buf); + //OutputDebugStringA(buf); } _pendingCheckSums[_sync.GetFrameCount()]= cSum ; From d2f44a2f470d2ff2f3aba188ef07f853c59c68b2 Mon Sep 17 00:00:00 2001 From: thomashenry79 Date: Thu, 20 Oct 2022 21:09:22 +0100 Subject: [PATCH 16/40] small tidyup --- src/lib/ggpo/sync.cpp | 4 ++-- src/lib/ggpo/sync.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/lib/ggpo/sync.cpp b/src/lib/ggpo/sync.cpp index c94117ac..8960d5d8 100644 --- a/src/lib/ggpo/sync.cpp +++ b/src/lib/ggpo/sync.cpp @@ -40,7 +40,7 @@ Sync::Init(Sync::Config &config) _max_prediction_frames = config.num_prediction_frames; - CreateQueues(config); + CreateQueues(); } void @@ -242,7 +242,7 @@ Sync::FindSavedFrameIndex(int frame) bool -Sync::CreateQueues(Config &config) +Sync::CreateQueues() { delete [] _input_queues; _input_queues = new InputQueue[_config.num_players]; diff --git a/src/lib/ggpo/sync.h b/src/lib/ggpo/sync.h index f5ac6803..76308ae2 100644 --- a/src/lib/ggpo/sync.h +++ b/src/lib/ggpo/sync.h @@ -85,7 +85,7 @@ class Sync { int FindSavedFrameIndex(int frame); SavedFrame& GetLastSavedFrame(); - bool CreateQueues(Config& config); + bool CreateQueues(); bool CheckSimulationConsistency(int* seekTo); void ResetPrediction(int frameNumber); From de0acabdc1ebf0c8156b57d31ce374fe6893e1e5 Mon Sep 17 00:00:00 2001 From: thomashenry79 <61023880+thomashenry79@users.noreply.github.com> Date: Fri, 21 Oct 2022 11:56:59 +0100 Subject: [PATCH 17/40] remove swear words --- src/GGPO-x.vcxproj | 4 ++-- src/apps/vectorwar/VectorWar.vcxproj | 4 ++-- src/lib/ggpo/backends/p2p.cpp | 4 +--- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/src/GGPO-x.vcxproj b/src/GGPO-x.vcxproj index e02e0694..ff899841 100644 --- a/src/GGPO-x.vcxproj +++ b/src/GGPO-x.vcxproj @@ -33,7 +33,7 @@ StaticLibrary MultiByte - v140_xp + v142 StaticLibrary @@ -43,7 +43,7 @@ StaticLibrary MultiByte - v140_xp + v142 StaticLibrary diff --git a/src/apps/vectorwar/VectorWar.vcxproj b/src/apps/vectorwar/VectorWar.vcxproj index ce49b1e6..b77bdc5d 100644 --- a/src/apps/vectorwar/VectorWar.vcxproj +++ b/src/apps/vectorwar/VectorWar.vcxproj @@ -33,7 +33,7 @@ Application Unicode - v140_xp + v142 Application @@ -43,7 +43,7 @@ Application Unicode - v140_xp + v142 Application diff --git a/src/lib/ggpo/backends/p2p.cpp b/src/lib/ggpo/backends/p2p.cpp index e6664a4f..0979f213 100644 --- a/src/lib/ggpo/backends/p2p.cpp +++ b/src/lib/ggpo/backends/p2p.cpp @@ -409,18 +409,16 @@ Peer2PeerBackend::IncrementFrame(uint16_t checksum1) char buf[256]; uint16_t cSum = checksum1; Log("End of frame (%d)...\n", _sync.GetFrameCount()); - // OutputDebugStringA("cock\n"); static int maxDif = 0; if (_pendingCheckSums.count(_sync.GetFrameCount())) { - // OutputDebugStringA("cunt\n"); auto max = _pendingCheckSums.rbegin()->first; auto diff = max - currentFrame; maxDif = max(maxDif, diff); int oldChecksum = _pendingCheckSums[_sync.GetFrameCount()]; _pendingCheckSums[_sync.GetFrameCount()] = cSum; sprintf_s<256>(buf, "Replace local checksum for frame %d: %d with %d, newest frame is %d, max diff %d\n", _sync.GetFrameCount(), oldChecksum, _pendingCheckSums[_sync.GetFrameCount()], max, maxDif); - // OutputDebugStringA(buf); + if (currentFrame <= _confirmedCheckSumFrame) { From a9033d09dd4ff5fa413140b0259da0a9531c3540 Mon Sep 17 00:00:00 2001 From: thd79 Date: Sun, 23 Oct 2022 22:54:32 +0100 Subject: [PATCH 18/40] add new function --- src/lib/ggpo/backends/backend.h | 1 + src/lib/ggpo/backends/p2p.cpp | 6 +++++- src/lib/ggpo/backends/p2p.h | 1 + src/lib/ggpo/backends/spectator.cpp | 5 +++++ src/lib/ggpo/backends/spectator.h | 2 ++ src/lib/ggpo/backends/synctest.cpp | 6 ++++++ src/lib/ggpo/backends/synctest.h | 1 + 7 files changed, 21 insertions(+), 1 deletion(-) diff --git a/src/lib/ggpo/backends/backend.h b/src/lib/ggpo/backends/backend.h index 64c3c671..9b2466a8 100644 --- a/src/lib/ggpo/backends/backend.h +++ b/src/lib/ggpo/backends/backend.h @@ -19,6 +19,7 @@ class GGPOSession { virtual GGPOErrorCode AddLocalInput(GGPOPlayerHandle player, void *values, int size) = 0; virtual GGPOErrorCode SyncInput(void *values, int size, int *disconnect_flags) = 0; virtual GGPOErrorCode IncrementFrame(uint16_t checksum) = 0; + virtual GGPOErrorCode CurrentFrame(int& current) =0; virtual GGPOErrorCode Chat(const char* text) = 0;// { return GGPO_OK; } virtual GGPOErrorCode DisconnectPlayer(GGPOPlayerHandle handle) = 0;// { return GGPO_OK; } virtual GGPOErrorCode GetNetworkStats(GGPONetworkStats *stats, GGPOPlayerHandle handle) { return GGPO_OK; } diff --git a/src/lib/ggpo/backends/p2p.cpp b/src/lib/ggpo/backends/p2p.cpp index 0979f213..3180cfd3 100644 --- a/src/lib/ggpo/backends/p2p.cpp +++ b/src/lib/ggpo/backends/p2p.cpp @@ -401,7 +401,11 @@ Peer2PeerBackend::SyncInput(void *values, } return GGPO_OK; } - +GGPOErrorCode Peer2PeerBackend::CurrentFrame(int& current) +{ + current = _sync.GetFrameCount(); + return GGPO_OK; +} GGPOErrorCode Peer2PeerBackend::IncrementFrame(uint16_t checksum1) { diff --git a/src/lib/ggpo/backends/p2p.h b/src/lib/ggpo/backends/p2p.h index ad28452c..62cfea0f 100644 --- a/src/lib/ggpo/backends/p2p.h +++ b/src/lib/ggpo/backends/p2p.h @@ -33,6 +33,7 @@ class Peer2PeerBackend : public GGPOSession, Udp::Callbacks { virtual GGPOErrorCode SetDisconnectTimeout(int timeout) override; virtual GGPOErrorCode SetDisconnectNotifyStart(int timeout) override; virtual GGPOErrorCode Chat(const char* text) override; + virtual GGPOErrorCode CurrentFrame(int& current) override; public: virtual void OnMsg(sockaddr_in &from, UdpMsg *msg, int len); diff --git a/src/lib/ggpo/backends/spectator.cpp b/src/lib/ggpo/backends/spectator.cpp index 04644cd5..d2a3edd7 100644 --- a/src/lib/ggpo/backends/spectator.cpp +++ b/src/lib/ggpo/backends/spectator.cpp @@ -86,6 +86,11 @@ SpectatorBackend::SyncInput(void *values, return GGPO_OK; } +GGPOErrorCode SpectatorBackend::CurrentFrame(int& current) +{ + current= _next_input_to_send; + return GGPO_OK; +} GGPOErrorCode SpectatorBackend::IncrementFrame(uint16_t checksum) { diff --git a/src/lib/ggpo/backends/spectator.h b/src/lib/ggpo/backends/spectator.h index 5b4dace4..4d464514 100644 --- a/src/lib/ggpo/backends/spectator.h +++ b/src/lib/ggpo/backends/spectator.h @@ -35,6 +35,8 @@ class SpectatorBackend : public GGPOSession, Udp::Callbacks { virtual GGPOErrorCode SetDisconnectTimeout(int timeout) { return GGPO_ERRORCODE_UNSUPPORTED; } virtual GGPOErrorCode SetDisconnectNotifyStart(int timeout) { return GGPO_ERRORCODE_UNSUPPORTED; } virtual GGPOErrorCode Chat(const char* text) override { return GGPO_ERRORCODE_UNSUPPORTED; } + virtual GGPOErrorCode CurrentFrame(int& current) override; + public: virtual void OnMsg(sockaddr_in &from, UdpMsg *msg, int len); diff --git a/src/lib/ggpo/backends/synctest.cpp b/src/lib/ggpo/backends/synctest.cpp index bc7931ef..73a02e6f 100644 --- a/src/lib/ggpo/backends/synctest.cpp +++ b/src/lib/ggpo/backends/synctest.cpp @@ -99,6 +99,12 @@ SyncTestBackend::SyncInput(void *values, return GGPO_OK; } +GGPOErrorCode SyncTestBackend::CurrentFrame(int& current) +{ + current = _sync.GetFrameCount(); + return GGPO_OK; +} + GGPOErrorCode SyncTestBackend::IncrementFrame(uint16_t cs) { diff --git a/src/lib/ggpo/backends/synctest.h b/src/lib/ggpo/backends/synctest.h index 44a6abca..f0955a35 100644 --- a/src/lib/ggpo/backends/synctest.h +++ b/src/lib/ggpo/backends/synctest.h @@ -26,6 +26,7 @@ class SyncTestBackend : public GGPOSession { virtual GGPOErrorCode Logv(char *fmt, va_list list); virtual GGPOErrorCode DisconnectPlayer(GGPOPlayerHandle handle) { return GGPO_OK; } virtual GGPOErrorCode Chat(const char* text) override { return GGPO_ERRORCODE_UNSUPPORTED; } + virtual GGPOErrorCode CurrentFrame(int& current) override; protected: struct SavedInfo { int frame; From 3a26ffc38a87dda04b2ca469eaa95bc277fb9132 Mon Sep 17 00:00:00 2001 From: thd79 Date: Sun, 23 Oct 2022 23:52:14 +0100 Subject: [PATCH 19/40] cur frame --- src/include/ggponet.h | 5 +++++ src/lib/ggpo/main.cpp | 9 +++++++++ 2 files changed, 14 insertions(+) diff --git a/src/include/ggponet.h b/src/include/ggponet.h index bf6ee5e6..7400208c 100644 --- a/src/include/ggponet.h +++ b/src/include/ggponet.h @@ -528,6 +528,11 @@ GGPO_API GGPOErrorCode __cdecl ggpo_disconnect_player(GGPOSession *, */ GGPO_API GGPOErrorCode __cdecl ggpo_advance_frame(GGPOSession *, uint16_t checksum); +/* + * ggpo_get_current_frame -- current frame GGPO is dealing with + * + */ +GGPO_API GGPOErrorCode __cdecl ggpo_get_current_frame(GGPOSession* ggpo, int& nFrame); /* * ggpo_get_network_stats -- * diff --git a/src/lib/ggpo/main.cpp b/src/lib/ggpo/main.cpp index 7b750105..e858394f 100644 --- a/src/lib/ggpo/main.cpp +++ b/src/lib/ggpo/main.cpp @@ -140,6 +140,15 @@ ggpo_advance_frame(GGPOSession *ggpo, uint16_t checksum) return ggpo->IncrementFrame(checksum); } +GGPOErrorCode +ggpo_get_current_frame(GGPOSession *ggpo, int& nFrame) +{ + if (!ggpo) { + return GGPO_ERRORCODE_INVALID_SESSION; + } + return ggpo->CurrentFrame(nFrame); +} + GGPOErrorCode ggpo_client_chat(GGPOSession *ggpo, const char *text) { From bedccff51ca2d9743fbf1ae627db607f8dc523af Mon Sep 17 00:00:00 2001 From: thd79 Date: Tue, 1 Nov 2022 17:15:38 +0100 Subject: [PATCH 20/40] add context to callbacks --- src/apps/vectorwar/vectorwar.cpp | 14 +++++++------- src/include/ggponet.h | 19 ++++++++++++------- src/lib/ggpo/backends/p2p.cpp | 24 ++++++++++++------------ src/lib/ggpo/backends/spectator.cpp | 16 ++++++++-------- src/lib/ggpo/backends/synctest.cpp | 10 +++++----- src/lib/ggpo/sync.cpp | 10 +++++----- 6 files changed, 49 insertions(+), 44 deletions(-) diff --git a/src/apps/vectorwar/vectorwar.cpp b/src/apps/vectorwar/vectorwar.cpp index 4e7a39c0..8372d999 100644 --- a/src/apps/vectorwar/vectorwar.cpp +++ b/src/apps/vectorwar/vectorwar.cpp @@ -63,7 +63,7 @@ uint16_t Fletcher16(uint8_t* data, int count) * so just return true. */ bool __cdecl -vw_begin_game_callback(const char *) +vw_begin_game_callback(void*, const char *) { return true; } @@ -75,7 +75,7 @@ vw_begin_game_callback(const char *) * text at the bottom of the screen to notify the user. */ bool __cdecl -vw_on_event_callback(GGPOEvent *info) +vw_on_event_callback(void*, GGPOEvent *info) { int progress; switch (info->code) { @@ -139,7 +139,7 @@ vw_on_event_callback(GGPOEvent *info) * during a rollback. */ bool __cdecl -vw_advance_frame_callback(int) +vw_advance_frame_callback(void*, int) { int inputs[MAX_SHIPS] = { 0 }; int disconnect_flags; @@ -157,7 +157,7 @@ vw_advance_frame_callback(int) * Makes our current state match the state passed in by GGPO. */ bool __cdecl -vw_load_game_state_callback(unsigned char *buffer, int len, int nFrames) +vw_load_game_state_callback(void*, unsigned char *buffer, int len, int nFrames) { if (nFrames < 10) ngs.rollbacksBySize[nFrames]++; @@ -174,7 +174,7 @@ vw_load_game_state_callback(unsigned char *buffer, int len, int nFrames) * buffer and len parameters. */ bool __cdecl -vw_save_game_state_callback(unsigned char **buffer, int *len, int *checksum, int) +vw_save_game_state_callback(void*, unsigned char **buffer, int *len, int *checksum, int) { *len = sizeof(gs); *buffer = (unsigned char *)malloc(*len); @@ -192,7 +192,7 @@ vw_save_game_state_callback(unsigned char **buffer, int *len, int *checksum, int * Log the gamestate. Used by the synctest debugging tool. */ bool __cdecl -vw_log_game_state(char *filename, unsigned char *buffer, int) +vw_log_game_state(void*, char *filename, unsigned char *buffer, int) { FILE* fp = nullptr; fopen_s(&fp, filename, "w"); @@ -230,7 +230,7 @@ vw_log_game_state(char *filename, unsigned char *buffer, int) * Free a save state buffer previously returned in vw_save_game_state_callback. */ void __cdecl -vw_free_buffer(void *buffer) +vw_free_buffer(void*, void *buffer) { free(buffer); } diff --git a/src/include/ggponet.h b/src/include/ggponet.h index 7400208c..fa39dcdb 100644 --- a/src/include/ggponet.h +++ b/src/include/ggponet.h @@ -211,7 +211,7 @@ typedef struct { * begin_game callback - This callback has been deprecated. You must * implement it, but should ignore the 'game' parameter. */ - bool (__cdecl *begin_game)(const char *game); + bool (__cdecl *begin_game)(void* context, const char *game); /* * save_game_state - The client should allocate a buffer, copy the @@ -219,7 +219,7 @@ typedef struct { * length into the *len parameter. Optionally, the client can compute * a checksum of the data and store it in the *checksum argument. */ - bool (__cdecl *save_game_state)(unsigned char **buffer, int *len, int *checksum, int frame); + bool (__cdecl *save_game_state)(void* context, unsigned char **buffer, int *len, int *checksum, int frame); /* * load_game_state - GGPO.net will call this function at the beginning @@ -228,20 +228,20 @@ typedef struct { * should make the current game state match the state contained in the * buffer. */ - bool (__cdecl *load_game_state)(unsigned char *buffer, int len, int framesToRollback); + bool (__cdecl *load_game_state)(void* context, unsigned char *buffer, int len, int framesToRollback); /* * log_game_state - Used in diagnostic testing. The client should use * the ggpo_log function to write the contents of the specified save * state in a human readible form. */ - bool (__cdecl *log_game_state)(char *filename, unsigned char *buffer, int len); + bool (__cdecl *log_game_state)(void* context, char *filename, unsigned char *buffer, int len); /* * free_buffer - Frees a game state allocated in save_game_state. You * should deallocate the memory contained in the buffer. */ - void (__cdecl *free_buffer)(void *buffer); + void (__cdecl *free_buffer)(void* context, void *buffer); /* * advance_frame - Called during a rollback. You should advance your game @@ -252,13 +252,18 @@ typedef struct { * * The flags parameter is reserved. It can safely be ignored at this time. */ - bool (__cdecl *advance_frame)(int flags); + bool (__cdecl *advance_frame)(void* context, int flags); /* * on_event - Notification that something has happened. See the GGPOEventCode * structure above for more information. */ - bool (__cdecl *on_event)(GGPOEvent *info); + bool (__cdecl *on_event)(void* context, GGPOEvent *info); + + /* + * Calling context + */ + void* context; } GGPOSessionCallbacks; /* diff --git a/src/lib/ggpo/backends/p2p.cpp b/src/lib/ggpo/backends/p2p.cpp index 3180cfd3..f1f53823 100644 --- a/src/lib/ggpo/backends/p2p.cpp +++ b/src/lib/ggpo/backends/p2p.cpp @@ -52,7 +52,7 @@ Peer2PeerBackend::Peer2PeerBackend(GGPOSessionCallbacks *cb, /* * Preload the ROM */ - _callbacks.begin_game(gamename); + _callbacks.begin_game(_callbacks.context, gamename); } Peer2PeerBackend::~Peer2PeerBackend() @@ -118,7 +118,7 @@ void Peer2PeerBackend::CheckDesync() info.u.desync.nFrameOfDesync = checkSumFrame; info.u.desync.ourCheckSum = localChecksum; info.u.desync.remoteChecksum = remoteChecksum; - _callbacks.on_event(&info); + _callbacks.on_event(_callbacks.context, &info); char buf[256]; sprintf_s<256>(buf, "DESYNC Checksum frame %d, local: %d, remote %d, size of checksum maps: %d,%d", checkSumFrame, localChecksum, remoteChecksum, (int)_confirmedCheckSums.size(), (int)ep._remoteCheckSums.size()); @@ -160,7 +160,7 @@ Peer2PeerBackend::DoPoll() info.u.chat.senderID = i; info.code = GGPO_EVENTCODE_CHAT; info.u.chat.msg = msg; - _callbacks.on_event(&info); + _callbacks.on_event(_callbacks.context, &info); }); } @@ -219,7 +219,7 @@ Peer2PeerBackend::DoPoll() GGPOEvent info; info.code = GGPO_EVENTCODE_TIMESYNC; info.u.timesync.frames_ahead = interval; - _callbacks.on_event(&info); + _callbacks.on_event(_callbacks.context, &info); _next_recommended_sleep = current_frame + RECOMMENDATION_INTERVAL;// RECOMMENDATION_INTERVAL;// RECOMMENDATION_INTERVAL; } } @@ -574,7 +574,7 @@ Peer2PeerBackend::OnUdpProtocolSpectatorEvent(UdpProtocol::Event &evt, int queue info.code = GGPO_EVENTCODE_DISCONNECTED_FROM_PEER; info.u.disconnected.player = handle; - _callbacks.on_event(&info); + _callbacks.on_event(_callbacks.context, &info); break; } @@ -589,19 +589,19 @@ Peer2PeerBackend::OnUdpProtocolEvent(UdpProtocol::Event &evt, GGPOPlayerHandle h case UdpProtocol::Event::Connected: info.code = GGPO_EVENTCODE_CONNECTED_TO_PEER; info.u.connected.player = handle; - _callbacks.on_event(&info); + _callbacks.on_event(_callbacks.context, &info); break; case UdpProtocol::Event::Synchronizing: info.code = GGPO_EVENTCODE_SYNCHRONIZING_WITH_PEER; info.u.synchronizing.player = handle; info.u.synchronizing.count = evt.u.synchronizing.count; info.u.synchronizing.total = evt.u.synchronizing.total; - _callbacks.on_event(&info); + _callbacks.on_event(_callbacks.context, &info); break; case UdpProtocol::Event::Synchronzied: info.code = GGPO_EVENTCODE_SYNCHRONIZED_WITH_PEER; info.u.synchronized.player = handle; - _callbacks.on_event(&info); + _callbacks.on_event(_callbacks.context, &info); CheckInitialSync(); break; @@ -610,13 +610,13 @@ Peer2PeerBackend::OnUdpProtocolEvent(UdpProtocol::Event &evt, GGPOPlayerHandle h info.code = GGPO_EVENTCODE_CONNECTION_INTERRUPTED; info.u.connection_interrupted.player = handle; info.u.connection_interrupted.disconnect_timeout = evt.u.network_interrupted.disconnect_timeout; - _callbacks.on_event(&info); + _callbacks.on_event(_callbacks.context, &info); break; case UdpProtocol::Event::NetworkResumed: info.code = GGPO_EVENTCODE_CONNECTION_RESUMED; info.u.connection_resumed.player = handle; - _callbacks.on_event(&info); + _callbacks.on_event(_callbacks.context, &info); break; } } @@ -680,7 +680,7 @@ Peer2PeerBackend::DisconnectPlayerQueue(int queue, int syncto) info.code = GGPO_EVENTCODE_DISCONNECTED_FROM_PEER; info.u.disconnected.player = QueueToPlayerHandle(queue); - _callbacks.on_event(&info); + _callbacks.on_event(_callbacks.context, &info); CheckInitialSync(); } @@ -814,7 +814,7 @@ Peer2PeerBackend::CheckInitialSync() GGPOEvent info; info.code = GGPO_EVENTCODE_RUNNING; - _callbacks.on_event(&info); + _callbacks.on_event(_callbacks.context, &info); _synchronizing = false; } } diff --git a/src/lib/ggpo/backends/spectator.cpp b/src/lib/ggpo/backends/spectator.cpp index d2a3edd7..5d101181 100644 --- a/src/lib/ggpo/backends/spectator.cpp +++ b/src/lib/ggpo/backends/spectator.cpp @@ -39,7 +39,7 @@ SpectatorBackend::SpectatorBackend(GGPOSessionCallbacks *cb, /* * Preload the ROM */ - _callbacks.begin_game(gamename); + _callbacks.begin_game(_callbacks.context, gamename); } SpectatorBackend::~SpectatorBackend() @@ -120,23 +120,23 @@ SpectatorBackend::OnUdpProtocolEvent(UdpProtocol::Event &evt) case UdpProtocol::Event::Connected: info.code = GGPO_EVENTCODE_CONNECTED_TO_PEER; info.u.connected.player = 0; - _callbacks.on_event(&info); + _callbacks.on_event(_callbacks.context, &info); break; case UdpProtocol::Event::Synchronizing: info.code = GGPO_EVENTCODE_SYNCHRONIZING_WITH_PEER; info.u.synchronizing.player = 0; info.u.synchronizing.count = evt.u.synchronizing.count; info.u.synchronizing.total = evt.u.synchronizing.total; - _callbacks.on_event(&info); + _callbacks.on_event(_callbacks.context, &info); break; case UdpProtocol::Event::Synchronzied: if (_synchronizing) { info.code = GGPO_EVENTCODE_SYNCHRONIZED_WITH_PEER; info.u.synchronized.player = 0; - _callbacks.on_event(&info); + _callbacks.on_event(_callbacks.context, &info); info.code = GGPO_EVENTCODE_RUNNING; - _callbacks.on_event(&info); + _callbacks.on_event(_callbacks.context, &info); _synchronizing = false; } break; @@ -145,19 +145,19 @@ SpectatorBackend::OnUdpProtocolEvent(UdpProtocol::Event &evt) info.code = GGPO_EVENTCODE_CONNECTION_INTERRUPTED; info.u.connection_interrupted.player = 0; info.u.connection_interrupted.disconnect_timeout = evt.u.network_interrupted.disconnect_timeout; - _callbacks.on_event(&info); + _callbacks.on_event(_callbacks.context, &info); break; case UdpProtocol::Event::NetworkResumed: info.code = GGPO_EVENTCODE_CONNECTION_RESUMED; info.u.connection_resumed.player = 0; - _callbacks.on_event(&info); + _callbacks.on_event(_callbacks.context, &info); break; case UdpProtocol::Event::Disconnected: info.code = GGPO_EVENTCODE_DISCONNECTED_FROM_PEER; info.u.disconnected.player = 0; - _callbacks.on_event(&info); + _callbacks.on_event(_callbacks.context, &info); break; case UdpProtocol::Event::Input: diff --git a/src/lib/ggpo/backends/synctest.cpp b/src/lib/ggpo/backends/synctest.cpp index 73a02e6f..692bab4d 100644 --- a/src/lib/ggpo/backends/synctest.cpp +++ b/src/lib/ggpo/backends/synctest.cpp @@ -34,7 +34,7 @@ SyncTestBackend::SyncTestBackend(GGPOSessionCallbacks *cb, /* * Preload the ROM */ - _callbacks.begin_game(gamename); + _callbacks.begin_game(_callbacks.context, gamename); } SyncTestBackend::~SyncTestBackend() @@ -48,7 +48,7 @@ SyncTestBackend::DoPoll() GGPOEvent info; info.code = GGPO_EVENTCODE_RUNNING; - _callbacks.on_event(&info); + _callbacks.on_event(_callbacks.context, &info); _running = true; } return GGPO_OK; @@ -139,7 +139,7 @@ SyncTestBackend::IncrementFrame(uint16_t cs) _rollingback = true; while(!_saved_frames.empty()) { - _callbacks.advance_frame(0); + _callbacks.advance_frame(_callbacks.context, 0); // Verify that the checksumn of this frame is the same as the one in our // list. @@ -217,8 +217,8 @@ SyncTestBackend::LogSaveStates(SavedInfo &info) { char filename[MAX_PATH]; sprintf_s(filename, ARRAY_SIZE(filename), "synclogs\\state-%04d-original.log", _sync.GetFrameCount()); - _callbacks.log_game_state(filename, (unsigned char *)info.buf, info.cbuf); + _callbacks.log_game_state(_callbacks.context, filename, (unsigned char *)info.buf, info.cbuf); sprintf_s(filename, ARRAY_SIZE(filename), "synclogs\\state-%04d-replay.log", _sync.GetFrameCount()); - _callbacks.log_game_state(filename, _sync.GetLastSavedFrame().buf, _sync.GetLastSavedFrame().cbuf); + _callbacks.log_game_state(_callbacks.context, filename, _sync.GetLastSavedFrame().buf, _sync.GetLastSavedFrame().cbuf); } diff --git a/src/lib/ggpo/sync.cpp b/src/lib/ggpo/sync.cpp index 8960d5d8..2440e417 100644 --- a/src/lib/ggpo/sync.cpp +++ b/src/lib/ggpo/sync.cpp @@ -24,7 +24,7 @@ Sync::~Sync() * structure so we can efficently copy frames via weak references. */ for (int i = 0; i < _savedstate.frames.size(); i++) { - _callbacks.free_buffer(_savedstate.frames[i].buf); + _callbacks.free_buffer(_callbacks.context, _savedstate.frames[i].buf); } delete [] _input_queues; _input_queues = NULL; @@ -161,7 +161,7 @@ Sync::AdjustSimulation(int seek_to) */ ResetPrediction(_framecount); for (int i = 0; i < count; i++) { - _callbacks.advance_frame(0); + _callbacks.advance_frame(_callbacks.context, 0); } ASSERT(_framecount == framecount); @@ -187,7 +187,7 @@ Sync::LoadFrame(int frame, int framesToRollback) state->frame, state->cbuf, state->checksum); ASSERT(state->buf && state->cbuf); - _callbacks.load_game_state(state->buf, state->cbuf, framesToRollback); + _callbacks.load_game_state(_callbacks.context, state->buf, state->cbuf, framesToRollback); // Reset framecount and the head of the state ring-buffer to point in // advance of the current frame (as if we had just finished executing it). @@ -204,11 +204,11 @@ Sync::SaveCurrentFrame() */ SavedFrame *state = &_savedstate.frames[_savedstate.head]; if (state->buf) { - _callbacks.free_buffer(state->buf); + _callbacks.free_buffer(_callbacks.context, state->buf); state->buf = NULL; } state->frame = _framecount; - _callbacks.save_game_state(&state->buf, &state->cbuf, &state->checksum, state->frame); + _callbacks.save_game_state(_callbacks.context, &state->buf, &state->cbuf, &state->checksum, state->frame); Log("=== Saved frame info %d (size: %d checksum: %08x).\n", state->frame, state->cbuf, state->checksum); _savedstate.head = (_savedstate.head + 1) % (int)_savedstate.frames.size(); From 86196ec44d04d039e2b2e3fe838b33767cc48f50 Mon Sep 17 00:00:00 2001 From: thd79 Date: Mon, 14 Nov 2022 00:41:57 +0000 Subject: [PATCH 21/40] dont crash on unexpected message --- src/lib/ggpo/network/udp_proto.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/ggpo/network/udp_proto.cpp b/src/lib/ggpo/network/udp_proto.cpp index f558336c..cdbfd624 100644 --- a/src/lib/ggpo/network/udp_proto.cpp +++ b/src/lib/ggpo/network/udp_proto.cpp @@ -483,7 +483,7 @@ UdpProtocol::LogMsg(const char *prefix, UdpMsg *msg) Log("%s chat.\n", prefix); break; default: - ASSERT(FALSE && "Unknown UdpMsg type."); + Log("Unknown UdpMsg type."); } } @@ -500,7 +500,7 @@ UdpProtocol::LogEvent(const char *prefix, const UdpProtocol::Event &evt) bool UdpProtocol::OnInvalid(UdpMsg *msg, int len) { - ASSERT(FALSE && "Invalid msg in UdpProtocol"); + // ASSERT(FALSE && "Invalid msg in UdpProtocol"); return false; } From 5f75e8dc65bfed426ef10570939a3b263e000df2 Mon Sep 17 00:00:00 2001 From: thd79 Date: Wed, 23 Nov 2022 22:52:04 +0000 Subject: [PATCH 22/40] change to rift sync code --- src/apps/vectorwar/gdi_renderer.cpp | 2 +- src/apps/vectorwar/nongamestate.h | 19 ++++++++++++------- src/apps/vectorwar/vectorwar.cpp | 9 +++++---- src/lib/ggpo/backends/p2p.cpp | 2 +- src/lib/ggpo/timesync.cpp | 14 +++++++------- src/lib/ggpo/types.h | 3 +++ 6 files changed, 29 insertions(+), 20 deletions(-) diff --git a/src/apps/vectorwar/gdi_renderer.cpp b/src/apps/vectorwar/gdi_renderer.cpp index bc220623..45b9055d 100644 --- a/src/apps/vectorwar/gdi_renderer.cpp +++ b/src/apps/vectorwar/gdi_renderer.cpp @@ -72,7 +72,7 @@ GDIRenderer::Draw(GameState &gs, NonGameState &ngs) ngs.stats.timesync.remote_frames_behind); TextOutA(hdc, (_rc.left + _rc.right) / 2, _rc.top + 72, statsinfo, (int)strlen(statsinfo)); - sprintf_s(statsinfo, ARRAYSIZE(statsinfo), "Rbcks: %i, tsyncs: %i, ntsyncs: %i, inputreject: %d, RTT: %d, total fr dly :%.1f", ngs.nRollbacks, ngs.nTimeSyncs,ngs.nonTimeSyncs,ngs.inputDelays, ngs.stats.network.ping, ngs.totalFrameDelays); + sprintf_s(statsinfo, ARRAYSIZE(statsinfo), "Rbcks: %i, tsyncs: %i, negtsyncs: %i, inputreject: %d, RTT: %d, total fr dly :%.1f", ngs.nRollbacks, ngs.nTimeSyncs,ngs.nonTimeSyncs,ngs.inputDelays, ngs.stats.network.ping, ngs.totalFrameDelays); TextOutA(hdc, (_rc.left + _rc.right) / 2, _rc.top + 88, statsinfo, (int)strlen(statsinfo)); sprintf_s(statsinfo, diff --git a/src/apps/vectorwar/nongamestate.h b/src/apps/vectorwar/nongamestate.h index cb15d453..0b607998 100644 --- a/src/apps/vectorwar/nongamestate.h +++ b/src/apps/vectorwar/nongamestate.h @@ -28,7 +28,12 @@ struct LoopTimer void OnGGPOTimeSyncEvent(float framesAhead) { lastAdvantage = /*(int)*/(1000.0f * framesAhead / 60.0f); - + lastAdvantage /= 2; + if (lastAdvantage < 0) + { + int t = 0; + t++; + } m_usExtraToWait = (int)(lastAdvantage*1000); if (m_usExtraToWait) { @@ -53,13 +58,13 @@ struct LoopTimer { return m_usExtraToWait * 100.0f / m_usPerGameLoop; } - unsigned int slowdown() const + int slowdown() const { return m_WaitCount ? m_usExtraToWait : 0; } // Call every loop, to get the amount of time the current iteration of gameloop should take - unsigned int usToWaitThisLoop() + int usToWaitThisLoop() { auto timetoWait = m_usPerGameLoop; if (m_WaitCount) { @@ -72,11 +77,11 @@ struct LoopTimer } float lastAdvantage = 0.0f; - unsigned int m_usPerGameLoop; + int m_usPerGameLoop; int m_usAhead; - unsigned int m_usExtraToWait; - unsigned int m_framesToSpreadWait; - unsigned int m_WaitCount = 0; + int m_usExtraToWait; + int m_framesToSpreadWait; + int m_WaitCount = 0; }; enum PlayerConnectState { diff --git a/src/apps/vectorwar/vectorwar.cpp b/src/apps/vectorwar/vectorwar.cpp index 8372d999..14806e53 100644 --- a/src/apps/vectorwar/vectorwar.cpp +++ b/src/apps/vectorwar/vectorwar.cpp @@ -116,13 +116,14 @@ vw_on_event_callback(void*, GGPOEvent *info) break; } case GGPO_EVENTCODE_TIMESYNC: + + ngs.totalFrameDelays += info->u.timesync.frames_ahead; ngs.loopTimer.OnGGPOTimeSyncEvent(info->u.timesync.frames_ahead); + if (info->u.timesync.frames_ahead > 0) { - //Sleep(max(1, (int)(1000.0f * info->u.timesync.frames_ahead / 60.f))); ngs.nTimeSyncs++; - ngs.totalFrameDelays += info->u.timesync.frames_ahead; } - else + else if(info->u.timesync.frames_ahead < 0) { ngs.nonTimeSyncs++; } @@ -252,7 +253,7 @@ VectorWar_Init(HWND hwnd, unsigned short localport, int num_players, GGPOPlayer // Initialize the game state gs.Init(hwnd, num_players); ngs.num_players = num_players; - ngs.loopTimer.Init(60,1);// 60FPS; + ngs.loopTimer.Init(60,110);// 60FPS; // Fill in a ggpo callbacks structure to pass to start_session. GGPOSessionCallbacks cb = { 0 }; cb.begin_game = vw_begin_game_callback; diff --git a/src/lib/ggpo/backends/p2p.cpp b/src/lib/ggpo/backends/p2p.cpp index f1f53823..d43dfb2f 100644 --- a/src/lib/ggpo/backends/p2p.cpp +++ b/src/lib/ggpo/backends/p2p.cpp @@ -211,7 +211,7 @@ Peer2PeerBackend::DoPoll() if (current_frame > _next_recommended_sleep) { float interval = 0; for (int i = 0; i < _num_players; i++) { - interval = MAX(interval, _endpoints[i].RecommendFrameDelay()); + interval = BIGGEST(interval, _endpoints[i].RecommendFrameDelay()); } //if (interval > 0) diff --git a/src/lib/ggpo/timesync.cpp b/src/lib/ggpo/timesync.cpp index 06b67f9b..4fb8d6be 100644 --- a/src/lib/ggpo/timesync.cpp +++ b/src/lib/ggpo/timesync.cpp @@ -76,10 +76,10 @@ TimeSync::recommend_frame_wait_duration(bool require_idle_input) // Only do this if both clients agree on who's ahead!! - if (advantage >= radvantage) { + // if (advantage >= radvantage) { - return 0; - } + // return 0; + // } float sleep_frames = (((radvantage - advantage) / 2.0f)); // Both clients agree that we're the one ahead. Split @@ -95,9 +95,9 @@ TimeSync::recommend_frame_wait_duration(bool require_idle_input) // Some things just aren't worth correcting for. Make sure // the difference is relevant before proceeding. - if (sleep_frames < 0.2f){//{ MIN_FRAME_ADVANTAGE) { - return 0; - } + // if (sleep_frames < 0.2f){//{ MIN_FRAME_ADVANTAGE) { + // return 0; + // } // Make sure our input had been "idle enough" before recommending // a sleep. This tries to make the emulator sleep while the @@ -113,5 +113,5 @@ TimeSync::recommend_frame_wait_duration(bool require_idle_input) //} //require_idle_input; // Success!!! Recommend the number of frames to sleep and adjust - return (float)MIN(sleep_frames, MAX_FRAME_ADVANTAGE); + return sleep_frames > 0 ? (float)MIN(sleep_frames, MAX_FRAME_ADVANTAGE) : (float)MAX(sleep_frames, -MAX_FRAME_ADVANTAGE); } diff --git a/src/lib/ggpo/types.h b/src/lib/ggpo/types.h index 05dbce29..d4d5080c 100644 --- a/src/lib/ggpo/types.h +++ b/src/lib/ggpo/types.h @@ -81,4 +81,7 @@ typedef int int32; # define MIN(x, y) (((x) < (y)) ? (x) : (y)) #endif +#ifndef BIGGEST +# define BIGGEST(x, y) (((abs(x)) > (abs(y))) ? (x) : (y)) +#endif #endif // _TYPES_H From 1d413ba4cdf5a26cf24952f0eaf13b78b8001407 Mon Sep 17 00:00:00 2001 From: thd79 Date: Wed, 23 Nov 2022 23:04:22 +0000 Subject: [PATCH 23/40] add recommendation interval --- src/include/ggponet.h | 1 + src/lib/ggpo/backends/p2p.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/src/include/ggponet.h b/src/include/ggponet.h index fa39dcdb..0b7dbf35 100644 --- a/src/include/ggponet.h +++ b/src/include/ggponet.h @@ -181,6 +181,7 @@ typedef struct { } disconnected; struct { float frames_ahead; + int timeSyncPeriodInFrames; } timesync; struct { GGPOPlayerHandle player; diff --git a/src/lib/ggpo/backends/p2p.cpp b/src/lib/ggpo/backends/p2p.cpp index d43dfb2f..babab339 100644 --- a/src/lib/ggpo/backends/p2p.cpp +++ b/src/lib/ggpo/backends/p2p.cpp @@ -219,6 +219,7 @@ Peer2PeerBackend::DoPoll() GGPOEvent info; info.code = GGPO_EVENTCODE_TIMESYNC; info.u.timesync.frames_ahead = interval; + info.u.timesync.timeSyncPeriodInFrames = RECOMMENDATION_INTERVAL; _callbacks.on_event(_callbacks.context, &info); _next_recommended_sleep = current_frame + RECOMMENDATION_INTERVAL;// RECOMMENDATION_INTERVAL;// RECOMMENDATION_INTERVAL; } From 1020f8049194106be4a4932da35b557531f40479 Mon Sep 17 00:00:00 2001 From: thomashenry79 <61023880+thomashenry79@users.noreply.github.com> Date: Mon, 12 Dec 2022 09:20:17 +0000 Subject: [PATCH 24/40] Update README.md --- README.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/README.md b/README.md index bdb66996..00a0d9ef 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,10 @@ +Fork of GGPO with some changes: + +1. Bug fixes eg GGPO was not working properly when players chose different input delays +2. Much improved rift handling +3. in game chat +4. desync detection + ![](doc/images/ggpo_header.png)   _[![Appveyor build status](https://img.shields.io/appveyor/ci/pond3r/ggpo/master.svg?logo=appveyor)](https://ci.appveyor.com/project/pond3r/ggpo/branch/master)_ From b457b2a9ffaf97ebb53d148f3849172f0bc3de26 Mon Sep 17 00:00:00 2001 From: thd79 Date: Wed, 14 Dec 2022 11:16:40 +0000 Subject: [PATCH 25/40] small change --- src/lib/ggpo/backends/p2p.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/ggpo/backends/p2p.cpp b/src/lib/ggpo/backends/p2p.cpp index babab339..ab090f9c 100644 --- a/src/lib/ggpo/backends/p2p.cpp +++ b/src/lib/ggpo/backends/p2p.cpp @@ -503,7 +503,7 @@ void Peer2PeerBackend::CheckRemoteChecksum(int framenumber, uint16 cs) int Peer2PeerBackend::HowFarBackForChecksums()const { - return _sync.MaxPredictionFrames()+8; + return 16; }/* uint16 Peer2PeerBackend::GetChecksumForConfirmedFrame(int frameNumber) const { From 9cc4ab14c8de9f212cde0d311113221d1edfbc11 Mon Sep 17 00:00:00 2001 From: thd79 Date: Mon, 10 Jul 2023 16:52:04 +0200 Subject: [PATCH 26/40] add UWP variant --- GGPO-x.sln | 34 +++- src/GGPO-x-UWP.vcxproj | 290 +++++++++++++++++++++++++++ src/GGPO-x-UWP.vcxproj.filters | 77 +++++++ src/apps/vectorwar/VectorWar.vcxproj | 6 + src/apps/vectorwar/gdi_renderer.cpp | 11 +- src/apps/vectorwar/main.cpp | 43 +++- src/apps/vectorwar/nongamestate.h | 68 ++++--- src/apps/vectorwar/vectorwar.cpp | 23 ++- src/apps/vectorwar/vectorwar.h | 2 +- src/lib/ggpo/network/udp.h | 1 - src/lib/ggpo/network/udp_proto.cpp | 2 +- src/lib/ggpo/platform_windows.cpp | 16 +- src/lib/ggpo/platform_windows.h | 13 +- src/lib/ggpo/timesync.cpp | 32 --- src/lib/ggpo/timesync.h | 2 - 15 files changed, 514 insertions(+), 106 deletions(-) create mode 100644 src/GGPO-x-UWP.vcxproj create mode 100644 src/GGPO-x-UWP.vcxproj.filters diff --git a/GGPO-x.sln b/GGPO-x.sln index cfc6dde7..0786518b 100644 --- a/GGPO-x.sln +++ b/GGPO-x.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 17 -VisualStudioVersion = 17.3.32922.545 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.33328.57 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "VectorWar", "src\apps\vectorwar\VectorWar.vcxproj", "{58789CDC-C8E2-30F9-9FD6-8043C74C79E8}" ProjectSection(ProjectDependencies) = postProject @@ -10,30 +10,60 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "VectorWar", "src\apps\vecto EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GGPO-x", "src\GGPO-x.vcxproj", "{1B89CCF2-963B-30F8-A86A-FB85A0BB8077}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GGPO-x-UWP", "src\GGPO-x-UWP.vcxproj", "{327D7407-D1D2-4788-B399-15B8921CD539}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|ARM = Debug|ARM + Debug|ARM64 = Debug|ARM64 Debug|x64 = Debug|x64 Debug|x86 = Debug|x86 + Release|ARM = Release|ARM + Release|ARM64 = Release|ARM64 Release|x64 = Release|x64 Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution + {58789CDC-C8E2-30F9-9FD6-8043C74C79E8}.Debug|ARM.ActiveCfg = Debug|Win32 + {58789CDC-C8E2-30F9-9FD6-8043C74C79E8}.Debug|ARM64.ActiveCfg = Debug|Win32 {58789CDC-C8E2-30F9-9FD6-8043C74C79E8}.Debug|x64.ActiveCfg = Debug|x64 {58789CDC-C8E2-30F9-9FD6-8043C74C79E8}.Debug|x64.Build.0 = Debug|x64 {58789CDC-C8E2-30F9-9FD6-8043C74C79E8}.Debug|x86.ActiveCfg = Debug|Win32 {58789CDC-C8E2-30F9-9FD6-8043C74C79E8}.Debug|x86.Build.0 = Debug|Win32 + {58789CDC-C8E2-30F9-9FD6-8043C74C79E8}.Release|ARM.ActiveCfg = Release|Win32 + {58789CDC-C8E2-30F9-9FD6-8043C74C79E8}.Release|ARM64.ActiveCfg = Release|Win32 {58789CDC-C8E2-30F9-9FD6-8043C74C79E8}.Release|x64.ActiveCfg = Release|x64 {58789CDC-C8E2-30F9-9FD6-8043C74C79E8}.Release|x64.Build.0 = Release|x64 {58789CDC-C8E2-30F9-9FD6-8043C74C79E8}.Release|x86.ActiveCfg = Release|Win32 {58789CDC-C8E2-30F9-9FD6-8043C74C79E8}.Release|x86.Build.0 = Release|Win32 + {1B89CCF2-963B-30F8-A86A-FB85A0BB8077}.Debug|ARM.ActiveCfg = Debug|Win32 + {1B89CCF2-963B-30F8-A86A-FB85A0BB8077}.Debug|ARM64.ActiveCfg = Debug|Win32 {1B89CCF2-963B-30F8-A86A-FB85A0BB8077}.Debug|x64.ActiveCfg = Debug|x64 {1B89CCF2-963B-30F8-A86A-FB85A0BB8077}.Debug|x64.Build.0 = Debug|x64 {1B89CCF2-963B-30F8-A86A-FB85A0BB8077}.Debug|x86.ActiveCfg = Debug|Win32 {1B89CCF2-963B-30F8-A86A-FB85A0BB8077}.Debug|x86.Build.0 = Debug|Win32 + {1B89CCF2-963B-30F8-A86A-FB85A0BB8077}.Release|ARM.ActiveCfg = Release|Win32 + {1B89CCF2-963B-30F8-A86A-FB85A0BB8077}.Release|ARM64.ActiveCfg = Release|Win32 {1B89CCF2-963B-30F8-A86A-FB85A0BB8077}.Release|x64.ActiveCfg = Release|x64 {1B89CCF2-963B-30F8-A86A-FB85A0BB8077}.Release|x64.Build.0 = Release|x64 {1B89CCF2-963B-30F8-A86A-FB85A0BB8077}.Release|x86.ActiveCfg = Release|Win32 {1B89CCF2-963B-30F8-A86A-FB85A0BB8077}.Release|x86.Build.0 = Release|Win32 + {327D7407-D1D2-4788-B399-15B8921CD539}.Debug|ARM.ActiveCfg = Debug|ARM + {327D7407-D1D2-4788-B399-15B8921CD539}.Debug|ARM.Build.0 = Debug|ARM + {327D7407-D1D2-4788-B399-15B8921CD539}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {327D7407-D1D2-4788-B399-15B8921CD539}.Debug|ARM64.Build.0 = Debug|ARM64 + {327D7407-D1D2-4788-B399-15B8921CD539}.Debug|x64.ActiveCfg = Debug|x64 + {327D7407-D1D2-4788-B399-15B8921CD539}.Debug|x64.Build.0 = Debug|x64 + {327D7407-D1D2-4788-B399-15B8921CD539}.Debug|x86.ActiveCfg = Debug|Win32 + {327D7407-D1D2-4788-B399-15B8921CD539}.Debug|x86.Build.0 = Debug|Win32 + {327D7407-D1D2-4788-B399-15B8921CD539}.Release|ARM.ActiveCfg = Release|ARM + {327D7407-D1D2-4788-B399-15B8921CD539}.Release|ARM.Build.0 = Release|ARM + {327D7407-D1D2-4788-B399-15B8921CD539}.Release|ARM64.ActiveCfg = Release|ARM64 + {327D7407-D1D2-4788-B399-15B8921CD539}.Release|ARM64.Build.0 = Release|ARM64 + {327D7407-D1D2-4788-B399-15B8921CD539}.Release|x64.ActiveCfg = Release|x64 + {327D7407-D1D2-4788-B399-15B8921CD539}.Release|x64.Build.0 = Release|x64 + {327D7407-D1D2-4788-B399-15B8921CD539}.Release|x86.ActiveCfg = Release|Win32 + {327D7407-D1D2-4788-B399-15B8921CD539}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/src/GGPO-x-UWP.vcxproj b/src/GGPO-x-UWP.vcxproj new file mode 100644 index 00000000..9048445d --- /dev/null +++ b/src/GGPO-x-UWP.vcxproj @@ -0,0 +1,290 @@ + + + + + Debug + ARM + + + Debug + ARM64 + + + Debug + Win32 + + + Debug + x64 + + + Release + ARM + + + Release + ARM64 + + + Release + Win32 + + + Release + x64 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {327d7407-d1d2-4788-b399-15b8921cd539} + DynamicLibrary + GGPO_x_UWP + en-US + 14.0 + true + Windows Store + 10.0.19041.0 + 10.0.10240.0 + 10.0 + + + + DynamicLibrary + true + v142 + + + DynamicLibrary + true + v142 + + + DynamicLibrary + true + v142 + + + DynamicLibrary + true + v142 + + + DynamicLibrary + false + true + v142 + + + DynamicLibrary + false + true + v142 + + + DynamicLibrary + false + true + v142 + + + DynamicLibrary + false + true + v142 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + false + false + + + false + false + + + false + false + + + false + false + + + false + false + + + false + false + + + false + false + + + false + false + + + + Use + false + + + Console + false + false + + + + + Use + false + + + Console + false + false + + + + + Use + false + + + Console + false + false + + + + + Use + false + + + Console + false + false + + + + + Use + false + + + Console + false + false + + + + + Use + false + + + Console + false + false + + + + + NotUsing + false + _WINDLL;%(PreprocessorDefinitions);_WINDOWS; + $(ProjectDir)lib\ggpo;$(ProjectDir)include;%(AdditionalIncludeDirectories) + + + Console + false + false + + + + + NotUsing + false + _WINDLL;%(PreprocessorDefinitions);_WINDOWS; + $(ProjectDir)lib\ggpo;$(ProjectDir)include;%(AdditionalIncludeDirectories) + + + Console + false + false + + + + + + \ No newline at end of file diff --git a/src/GGPO-x-UWP.vcxproj.filters b/src/GGPO-x-UWP.vcxproj.filters new file mode 100644 index 00000000..bcd9cfcf --- /dev/null +++ b/src/GGPO-x-UWP.vcxproj.filters @@ -0,0 +1,77 @@ + + + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tga;tiff;tif;png;wav;mfcribbon-ms + + + {bad1d827-4d52-4e34-b542-967e88a39a56} + + + {183c5201-c677-4c6b-95d7-5e4c4517a552} + + + + + + + + + + + + + + network + + + network + + + backends + + + backends + + + backends + + + + + + + + + + + + + + + + + + network + + + network + + + network + + + backends + + + backends + + + backends + + + backends + + + \ No newline at end of file diff --git a/src/apps/vectorwar/VectorWar.vcxproj b/src/apps/vectorwar/VectorWar.vcxproj index b77bdc5d..1e2840f3 100644 --- a/src/apps/vectorwar/VectorWar.vcxproj +++ b/src/apps/vectorwar/VectorWar.vcxproj @@ -82,6 +82,12 @@ true true + + C:\Users\thoma\source\repos\vcpkg + + + C:\Users\thoma\source\repos\vcpkg + ..\..\include;..\..\lib\ggpo-x;%(AdditionalIncludeDirectories) diff --git a/src/apps/vectorwar/gdi_renderer.cpp b/src/apps/vectorwar/gdi_renderer.cpp index 45b9055d..010b53b7 100644 --- a/src/apps/vectorwar/gdi_renderer.cpp +++ b/src/apps/vectorwar/gdi_renderer.cpp @@ -72,7 +72,9 @@ GDIRenderer::Draw(GameState &gs, NonGameState &ngs) ngs.stats.timesync.remote_frames_behind); TextOutA(hdc, (_rc.left + _rc.right) / 2, _rc.top + 72, statsinfo, (int)strlen(statsinfo)); - sprintf_s(statsinfo, ARRAYSIZE(statsinfo), "Rbcks: %i, tsyncs: %i, negtsyncs: %i, inputreject: %d, RTT: %d, total fr dly :%.1f", ngs.nRollbacks, ngs.nTimeSyncs,ngs.nonTimeSyncs,ngs.inputDelays, ngs.stats.network.ping, ngs.totalFrameDelays); + sprintf_s(statsinfo, ARRAYSIZE(statsinfo), + "Rbcks: %i, tsyncs: %i, negtsyncs: %i, inputreject: %d, RTT: %d, total fr dly :%.1f, extraUS: %d", + ngs.nRollbacks, ngs.nTimeSyncs,ngs.nonTimeSyncs,ngs.inputDelays, ngs.stats.network.ping, ngs.totalFrameDelays,ngs.loopTimer.m_usExtraToWait); TextOutA(hdc, (_rc.left + _rc.right) / 2, _rc.top + 88, statsinfo, (int)strlen(statsinfo)); sprintf_s(statsinfo, @@ -80,16 +82,15 @@ GDIRenderer::Draw(GameState &gs, NonGameState &ngs) "Average advantage difference: %.2f", ngs.stats.timesync.avg_local_frames_behind- ngs.stats.timesync.avg_remote_frames_behind); TextOutA(hdc, (_rc.left + _rc.right) / 2, _rc.top + 102, statsinfo, (int)strlen(statsinfo)); - auto ms = ngs.loopTimer.slowdown(); - ms; - { + + /*{ sprintf_s(statsinfo, ARRAYSIZE(statsinfo), "Slowing frame by %.2fpc", ngs.loopTimer.slowDownPC()); if(ms == 0) SetTextColor(hdc, RGB(255, 255, 0)); else SetTextColor(hdc, RGB(0, 255, 0)); TextOutA(hdc, _rc.left+50 , _rc.top+ 56 , statsinfo, (int)strlen(statsinfo)); - } + }*/ sprintf_s(statsinfo, ARRAYSIZE(statsinfo), "Rollback count by size:"); TextOutA(hdc, _rc.left+50 , _rc.top+ 72 , statsinfo, (int)strlen(statsinfo)); for (auto i = 1u; i < ngs.rollbacksBySize.size(); i++) diff --git a/src/apps/vectorwar/main.cpp b/src/apps/vectorwar/main.cpp index e3147227..9f12f065 100644 --- a/src/apps/vectorwar/main.cpp +++ b/src/apps/vectorwar/main.cpp @@ -61,13 +61,26 @@ CreateMainWindow(HINSTANCE hInstance) SetWindowPos(hwnd, NULL, 0, 0, width + (width - (rc.right - rc.left)), height + (height - (rc.bottom - rc.top)), SWP_NOMOVE); return hwnd; } + +void BusyWait(int uS) +{ + auto start = std::chrono::high_resolution_clock::now(); + while (true) + { + auto newtime = std::chrono::high_resolution_clock::now(); + auto frameTime = (int)std::chrono::duration_cast(newtime - start).count(); + if (frameTime >= uS) + break; + } +} void RunMainLoop(HWND hwnd) { MSG msg = { 0 }; - std::chrono::steady_clock::time_point start, next, now; - - start = next = now = std::chrono::high_resolution_clock::now(); + std::chrono::steady_clock::time_point start, next, now,newtime, current; + int dt = 1000000 / 60; + int accumulator = 0; + start = next = current =newtime = std::chrono::high_resolution_clock::now(); while(1) { while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { TranslateMessage(&msg); @@ -76,12 +89,26 @@ RunMainLoop(HWND hwnd) return; } } - now = std::chrono::high_resolution_clock::now(); - if (now >= next) { - int usToWait; - VectorWar_RunFrame(hwnd, usToWait); - next = now + std::chrono::microseconds(usToWait); + newtime = std::chrono::high_resolution_clock::now(); + auto frameTime = (int)std::chrono::duration_cast(newtime - current).count(); + current = newtime; + accumulator += frameTime; + + // + int playerNum=1; + int extraUS = 0; + // while(accumulator>= dt) + { + VectorWar_RunFrame(hwnd, playerNum,extraUS); + accumulator -= dt; + // dt = usToWait; } + auto baseuS = (playerNum == 1) ? dt +rand()%1000: dt + 200 + rand() % 500; + baseuS; + BusyWait(baseuS+ extraUS); + VectorWar_DrawCurrentFrame(); + // Sleep(1); + } } diff --git a/src/apps/vectorwar/nongamestate.h b/src/apps/vectorwar/nongamestate.h index 0b607998..00b8f7bd 100644 --- a/src/apps/vectorwar/nongamestate.h +++ b/src/apps/vectorwar/nongamestate.h @@ -4,6 +4,7 @@ #include "ggponet.h" #define MAX_PLAYERS 64 #include +#include /* * nongamestate.h -- * @@ -15,7 +16,18 @@ struct LoopTimer { public: - + void BusyWait(int uS) + { + auto start = std::chrono::high_resolution_clock::now(); + while (true) + { + auto newtime = std::chrono::high_resolution_clock::now(); + auto frameTime = (int)std::chrono::duration_cast(newtime - start).count(); + if (frameTime >= uS) + break; + } + } + int nCalls; void Init(unsigned int fps, unsigned int framesToSpreadWait) { m_usPerGameLoop = 1000000 / fps; @@ -23,65 +35,55 @@ struct LoopTimer m_usExtraToWait = 0; m_framesToSpreadWait = framesToSpreadWait; lastAdvantage = 0.0f; + nCalls = 0; } void OnGGPOTimeSyncEvent(float framesAhead) { - lastAdvantage = /*(int)*/(1000.0f * framesAhead / 60.0f); - lastAdvantage /= 2; + auto thisAdvantage = /*(int)*/(1000.0f * framesAhead / 60.0f);// *0.5f; + nCalls++; + if (nCalls <= 1) + { + if (thisAdvantage > 0) + Sleep((int)thisAdvantage); + return; + } + + lastAdvantage = (lastAdvantage * 8) / 10; + + lastAdvantage += (thisAdvantage*10)/10; if (lastAdvantage < 0) { - int t = 0; - t++; + m_usExtraToWait = 0; + return; } m_usExtraToWait = (int)(lastAdvantage*1000); if (m_usExtraToWait) { + //BusyWait(m_usExtraToWait); m_usExtraToWait /= m_framesToSpreadWait; m_WaitCount = m_framesToSpreadWait; } - /*if (framesAhead < 0.5f) - m_usExtraToWait = 0; - else - m_usExtraToWait = (int)(framesAhead*800); - - m_usExtraToWait = min(3000, m_usExtraToWait);*/ - ////const int framesToSpreadover = 150; - //m_usAhead = (int)((framesAhead)*(float)m_usPerGameLoop); - //m_usExtraToWait = max(1, m_usAhead / m_framesToSpreadWait); - //m_WaitCount = m_framesToSpreadWait; - //char str[256]; - //sprintf_s<256>(str, "We are %.2f frames (%dus) ahead and will wait an extra %dus per frame for %d frames\n", framesAhead, m_usAhead, m_usExtraToWait, m_framesToSpreadWait); - //OutputDebugStringA(str); } float slowDownPC() const { return m_usExtraToWait * 100.0f / m_usPerGameLoop; } - int slowdown() const + int slowdown() { - return m_WaitCount ? m_usExtraToWait : 0; + return m_WaitCount-- ? m_usExtraToWait : 0; } - // Call every loop, to get the amount of time the current iteration of gameloop should take - int usToWaitThisLoop() - { - auto timetoWait = m_usPerGameLoop; - if (m_WaitCount) { - timetoWait += m_usExtraToWait; - m_WaitCount--; - if (!m_WaitCount) - m_usExtraToWait = 0; - } - return timetoWait; - } + float lastAdvantage = 0.0f; int m_usPerGameLoop; int m_usAhead; - int m_usExtraToWait; + int m_framesToSpreadWait; int m_WaitCount = 0; + int m_usExtraToWait; +private: }; enum PlayerConnectState { diff --git a/src/apps/vectorwar/vectorwar.cpp b/src/apps/vectorwar/vectorwar.cpp index 14806e53..6f51e970 100644 --- a/src/apps/vectorwar/vectorwar.cpp +++ b/src/apps/vectorwar/vectorwar.cpp @@ -253,7 +253,7 @@ VectorWar_Init(HWND hwnd, unsigned short localport, int num_players, GGPOPlayer // Initialize the game state gs.Init(hwnd, num_players); ngs.num_players = num_players; - ngs.loopTimer.Init(60,110);// 60FPS; + ngs.loopTimer.Init(60,30);// 60FPS; // Fill in a ggpo callbacks structure to pass to start_session. GGPOSessionCallbacks cb = { 0 }; cb.begin_game = vw_begin_game_callback; @@ -265,12 +265,12 @@ VectorWar_Init(HWND hwnd, unsigned short localport, int num_players, GGPOPlayer cb.log_game_state = vw_log_game_state; p1IsLocal = players[0].type == GGPO_PLAYERTYPE_LOCAL; ngs.LocalPLayerNumber = p1IsLocal ? 1 : 2; - ngs.inputDelay = p1IsLocal ? 6 : 2; - + ngs.inputDelay = p1IsLocal ? 2 : 2; + ngs.loopTimer.m_usPerGameLoop = p1IsLocal ? 1000000 / 59 : 1000000 / 60; #if defined(SYNC_TEST) result = ggpo_start_synctest(&ggpo, &cb, "vectorwar", num_players, sizeof(int), 1); #else - result = ggpo_start_session(&ggpo, &cb, "vectorwar", num_players, sizeof(int), localport, 8/*min(8,ngs.inputDelay+4)*/); + result = ggpo_start_session(&ggpo, &cb, "vectorwar", num_players, sizeof(int), localport, 5/*min(8,ngs.inputDelay+4)*/); #endif @@ -444,7 +444,7 @@ ReadInputs(HWND hwnd) * Run a single frame of the game. */ void -VectorWar_RunFrame(HWND hwnd, int&usToWait) +VectorWar_RunFrame(HWND hwnd, int&playerNum, int & extraUS) { // Rest these counts after 3 seconds as they take a hit right at the start while the connection stabilises. if (ngs.now.framenumber == 240) @@ -464,7 +464,7 @@ VectorWar_RunFrame(HWND hwnd, int&usToWait) if (ngs.local_player_handle != GGPO_INVALID_HANDLE) { static int nc = 0; int input = nc++ % 2 == 0 ? INPUT_ROTATE_LEFT : INPUT_ROTATE_RIGHT; - input = ReadInputs(hwnd); + // input = ReadInputs(hwnd); if (input == INPUT_FIRE) ggpo_client_chat(ggpo, "You wanker!"); #if defined(SYNC_TEST) @@ -492,11 +492,12 @@ VectorWar_RunFrame(HWND hwnd, int&usToWait) ngs.inputDelays++; } - VectorWar_DrawCurrentFrame(); - usToWait = ngs.loopTimer.usToWaitThisLoop(); - // usToWait+=2000; - if(needIdle) - VectorWar_Idle(); + //VectorWar_DrawCurrentFrame(); + playerNum = ngs.LocalPLayerNumber; + + extraUS = ngs.loopTimer.slowdown(); + + VectorWar_Idle(); ggpo_get_network_stats(ggpo, ngs.remote_player_handle, &ngs.stats); } diff --git a/src/apps/vectorwar/vectorwar.h b/src/apps/vectorwar/vectorwar.h index 3057760f..d157b2b6 100644 --- a/src/apps/vectorwar/vectorwar.h +++ b/src/apps/vectorwar/vectorwar.h @@ -24,7 +24,7 @@ void VectorWar_Init(HWND hwnd, unsigned short localport, int num_players, GGPOPl void VectorWar_InitSpectator(HWND hwnd, unsigned short localport, int num_players, char *host_ip, unsigned short host_port); void VectorWar_DrawCurrentFrame(); void VectorWar_AdvanceFrame(int inputs[], int disconnect_flags); -void VectorWar_RunFrame(HWND hwnd, int& usToWait); +void VectorWar_RunFrame(HWND hwnd, int& usToWait, int& extraUS); void VectorWar_Idle(); void VectorWar_DisconnectPlayer(int player); void VectorWar_Exit(); diff --git a/src/lib/ggpo/network/udp.h b/src/lib/ggpo/network/udp.h index c725150c..fb14a29d 100644 --- a/src/lib/ggpo/network/udp.h +++ b/src/lib/ggpo/network/udp.h @@ -12,7 +12,6 @@ #include "udp_msg.h" #include "ggponet.h" #include "ring_buffer.h" - #define MAX_UDP_ENDPOINTS 16 static const int MAX_UDP_PACKET_SIZE = 4096; diff --git a/src/lib/ggpo/network/udp_proto.cpp b/src/lib/ggpo/network/udp_proto.cpp index cdbfd624..4bf52ec0 100644 --- a/src/lib/ggpo/network/udp_proto.cpp +++ b/src/lib/ggpo/network/udp_proto.cpp @@ -16,7 +16,7 @@ static const int SYNC_RETRY_INTERVAL = 2000; static const int SYNC_FIRST_RETRY_INTERVAL = 500; static const int RUNNING_RETRY_INTERVAL = 200; static const int KEEP_ALIVE_INTERVAL = 200; -static const int QUALITY_REPORT_INTERVAL = 333; +static const int QUALITY_REPORT_INTERVAL = 120; static const int NETWORK_STATS_INTERVAL = 500; static const int UDP_SHUTDOWN_TIMER = 5000; static const int MAX_SEQ_DISTANCE = (1 << 15); diff --git a/src/lib/ggpo/platform_windows.cpp b/src/lib/ggpo/platform_windows.cpp index 31a25d32..3c8b9208 100644 --- a/src/lib/ggpo/platform_windows.cpp +++ b/src/lib/ggpo/platform_windows.cpp @@ -10,18 +10,20 @@ int Platform::GetConfigInt(const char* name) { - char buf[1024]; + return 0; + /* char buf[1024]; if (GetEnvironmentVariable(name, buf, ARRAY_SIZE(buf)) == 0) { return 0; } - return atoi(buf); + return atoi(buf);*/ } bool Platform::GetConfigBool(const char* name) { - char buf[1024]; - if (GetEnvironmentVariable(name, buf, ARRAY_SIZE(buf)) == 0) { - return false; - } - return atoi(buf) != 0 || _stricmp(buf, "true") == 0; + return false; + //char buf[1024]; + //if (GetEnvironmentVariable(name, buf, ARRAY_SIZE(buf)) == 0) { + // return false; + //} + //return atoi(buf) != 0 || _stricmp(buf, "true") == 0; } diff --git a/src/lib/ggpo/platform_windows.h b/src/lib/ggpo/platform_windows.h index 1d308ceb..67715243 100644 --- a/src/lib/ggpo/platform_windows.h +++ b/src/lib/ggpo/platform_windows.h @@ -13,15 +13,22 @@ #include #include #include "types.h" - +#include +#include +using namespace std::chrono; class Platform { public: // types typedef DWORD ProcessID; public: // functions static ProcessID GetProcessID() { return GetCurrentProcessId(); } - static void AssertFailed(char *msg) { MessageBoxA(NULL, msg, "GGPO Assertion Failed", MB_OK | MB_ICONEXCLAMATION); } - static uint32 GetCurrentTimeMS() { return timeGetTime(); } + static void AssertFailed(char* msg) { throw std::exception(msg); } + static uint32 GetCurrentTimeMS() { + + static auto startTime = high_resolution_clock::now(); + return static_cast(duration_cast(high_resolution_clock::now() - startTime).count()); + + } static int GetConfigInt(const char* name); static bool GetConfigBool(const char* name); }; diff --git a/src/lib/ggpo/timesync.cpp b/src/lib/ggpo/timesync.cpp index 4fb8d6be..b3da7c40 100644 --- a/src/lib/ggpo/timesync.cpp +++ b/src/lib/ggpo/timesync.cpp @@ -11,7 +11,6 @@ TimeSync::TimeSync() { memset(_local, 0, sizeof(_local)); memset(_remote, 0, sizeof(_remote)); - _next_prediction = FRAME_WINDOW_SIZE * 3; } TimeSync::~TimeSync() @@ -25,7 +24,6 @@ void TimeSync::advance_frame(GameInput &input, float advantage, float radvantage) { // Remember the last frame and frame advantage - _last_inputs[input.frame % ARRAY_SIZE(_last_inputs)] = input; _local[input.frame % ARRAY_SIZE(_local)] = advantage; _remote[input.frame % ARRAY_SIZE(_remote)] = radvantage; @@ -82,36 +80,6 @@ TimeSync::recommend_frame_wait_duration(bool require_idle_input) // } float sleep_frames = (((radvantage - advantage) / 2.0f)); - // Both clients agree that we're the one ahead. Split - // the difference between the two to figure out how long to - // sleep for. - /* char logMessage[256]; - sprintf_s<256>(logMessage, "Local Adv: %.2f, remoate adv %.2f", advantage, radvantage); - OutputDebugString(logMessage); - - sprintf_s<256>(logMessage, ": Sleep for %.2f frames\n", sleep_frames); - OutputDebugString(logMessage); - Log("iteration %d: sleep frames is %d\n", count, sleep_frames);*/ - - // Some things just aren't worth correcting for. Make sure - // the difference is relevant before proceeding. - // if (sleep_frames < 0.2f){//{ MIN_FRAME_ADVANTAGE) { - // return 0; - // } - // Make sure our input had been "idle enough" before recommending - // a sleep. This tries to make the emulator sleep while the - // user's input isn't sweeping in arcs (e.g. fireball motions in - // Street Fighter), which could cause the player to miss moves. - //if (require_idle_input) { - // for (i = 1; i < ARRAY_SIZE(_last_inputs); i++) { - // if (!_last_inputs[i].equal(_last_inputs[0], true)) { - // Log("iteration %d: rejecting due to input stuff at position %d...!!!\n", count, i); - // return 0; - // } - // } - //} - //require_idle_input; - // Success!!! Recommend the number of frames to sleep and adjust return sleep_frames > 0 ? (float)MIN(sleep_frames, MAX_FRAME_ADVANTAGE) : (float)MAX(sleep_frames, -MAX_FRAME_ADVANTAGE); } diff --git a/src/lib/ggpo/timesync.h b/src/lib/ggpo/timesync.h index 2452d16a..6f0a270d 100644 --- a/src/lib/ggpo/timesync.h +++ b/src/lib/ggpo/timesync.h @@ -33,8 +33,6 @@ class TimeSync { protected: float _local[FRAME_WINDOW_SIZE]; float _remote[FRAME_WINDOW_SIZE]; - GameInput _last_inputs[MIN_UNIQUE_FRAMES]; - int _next_prediction; int nFrame=0; float _avgLocal = 0; float _avgRemote = 0; From 89d87e18573f7847eb1482adf6d2b01806f848e7 Mon Sep 17 00:00:00 2001 From: thd79 Date: Mon, 10 Jul 2023 17:29:00 +0200 Subject: [PATCH 27/40] change to lib --- src/GGPO-x-UWP.vcxproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/GGPO-x-UWP.vcxproj b/src/GGPO-x-UWP.vcxproj index 9048445d..9a734c30 100644 --- a/src/GGPO-x-UWP.vcxproj +++ b/src/GGPO-x-UWP.vcxproj @@ -101,7 +101,7 @@ v142 - DynamicLibrary + StaticLibrary true v142 @@ -124,7 +124,7 @@ v142 - DynamicLibrary + StaticLibrary false true v142 From ebd2404e0e09cb76f7a190ca698ac05d76b0c593 Mon Sep 17 00:00:00 2001 From: thd79 Date: Tue, 11 Jul 2023 19:24:03 +0200 Subject: [PATCH 28/40] revert a few things --- src/lib/ggpo/network/udp_proto.cpp | 2 +- src/lib/ggpo/platform_windows.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/ggpo/network/udp_proto.cpp b/src/lib/ggpo/network/udp_proto.cpp index 4bf52ec0..cdbfd624 100644 --- a/src/lib/ggpo/network/udp_proto.cpp +++ b/src/lib/ggpo/network/udp_proto.cpp @@ -16,7 +16,7 @@ static const int SYNC_RETRY_INTERVAL = 2000; static const int SYNC_FIRST_RETRY_INTERVAL = 500; static const int RUNNING_RETRY_INTERVAL = 200; static const int KEEP_ALIVE_INTERVAL = 200; -static const int QUALITY_REPORT_INTERVAL = 120; +static const int QUALITY_REPORT_INTERVAL = 333; static const int NETWORK_STATS_INTERVAL = 500; static const int UDP_SHUTDOWN_TIMER = 5000; static const int MAX_SEQ_DISTANCE = (1 << 15); diff --git a/src/lib/ggpo/platform_windows.h b/src/lib/ggpo/platform_windows.h index 67715243..cca9d9b5 100644 --- a/src/lib/ggpo/platform_windows.h +++ b/src/lib/ggpo/platform_windows.h @@ -22,7 +22,7 @@ class Platform { public: // functions static ProcessID GetProcessID() { return GetCurrentProcessId(); } - static void AssertFailed(char* msg) { throw std::exception(msg); } + static void AssertFailed(char* msg) { MessageBoxA(NULL, msg, "GGPO Assertion Failed", MB_OK | MB_ICONEXCLAMATION); } static uint32 GetCurrentTimeMS() { static auto startTime = high_resolution_clock::now(); From b74a9f6c2254bdc32a90289c0abc94946d4c1c84 Mon Sep 17 00:00:00 2001 From: thd79 Date: Tue, 11 Jul 2023 20:04:35 +0200 Subject: [PATCH 29/40] change to static runtime --- src/GGPO-x.vcxproj | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/GGPO-x.vcxproj b/src/GGPO-x.vcxproj index ff899841..ebd9bfb6 100644 --- a/src/GGPO-x.vcxproj +++ b/src/GGPO-x.vcxproj @@ -96,7 +96,7 @@ true Disabled NotUsing - MultiThreadedDebugDLL + MultiThreadedDebug true true true @@ -145,7 +145,7 @@ true Disabled NotUsing - MultiThreadedDebugDLL + MultiThreadedDebug true true true @@ -198,7 +198,7 @@ true MaxSpeed NotUsing - MultiThreadedDLL + MultiThreadedDebug true true true @@ -251,7 +251,7 @@ true MaxSpeed NotUsing - MultiThreadedDLL + MultiThreadedDebug true true true From 5c6f0e264a8af22af5f01b59dd364ff04733296d Mon Sep 17 00:00:00 2001 From: thd79 Date: Tue, 11 Jul 2023 20:11:12 +0200 Subject: [PATCH 30/40] grrr --- src/GGPO-x.vcxproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/GGPO-x.vcxproj b/src/GGPO-x.vcxproj index ebd9bfb6..ad067e95 100644 --- a/src/GGPO-x.vcxproj +++ b/src/GGPO-x.vcxproj @@ -198,7 +198,7 @@ true MaxSpeed NotUsing - MultiThreadedDebug + MultiThreaded true true true @@ -251,7 +251,7 @@ true MaxSpeed NotUsing - MultiThreadedDebug + MultiThreaded true true true From f178d7592cda3ca3e0e035a7aacde05a92717390 Mon Sep 17 00:00:00 2001 From: thd79 Date: Fri, 14 Jul 2023 21:30:26 +0100 Subject: [PATCH 31/40] LLVM --- GGPO-x.sln | 24 +++ src/GGPO-x-UWP.vcxproj | 114 ++++++++++++++ src/GGPO-x.dir/Release-LLVM/GGPO-x.lib.recipe | 7 + src/GGPO-x.vcxproj | 139 ++++++++++++++++++ src/apps/vectorwar/VectorWar.vcxproj | 136 +++++++++++++++++ src/include/ggponet.h | 4 +- src/lib/ggpo/backends/backend.h | 8 +- src/lib/ggpo/backends/p2p.cpp | 60 +++++--- src/lib/ggpo/backends/p2p.h | 4 +- src/lib/ggpo/backends/spectator.cpp | 36 ++--- src/lib/ggpo/backends/spectator.h | 26 ++-- src/lib/ggpo/backends/synctest.cpp | 7 +- src/lib/ggpo/backends/synctest.h | 18 +-- src/lib/ggpo/game_input.h | 4 +- src/lib/ggpo/input_queue.cpp | 2 +- src/lib/ggpo/main.cpp | 4 +- src/lib/ggpo/network/udp.cpp | 2 +- src/lib/ggpo/network/udp_proto.cpp | 78 +++++----- src/lib/ggpo/network/udp_proto.h | 46 +++--- src/lib/ggpo/platform_windows.cpp | 4 +- src/lib/ggpo/poll.cpp | 2 +- src/lib/ggpo/sync.cpp | 9 +- src/lib/ggpo/sync.h | 6 +- src/lib/ggpo/timesync.cpp | 6 +- src/lib/ggpo/types.h | 2 +- 25 files changed, 584 insertions(+), 164 deletions(-) create mode 100644 src/GGPO-x.dir/Release-LLVM/GGPO-x.lib.recipe diff --git a/GGPO-x.sln b/GGPO-x.sln index 0786518b..0dcbfd16 100644 --- a/GGPO-x.sln +++ b/GGPO-x.sln @@ -22,6 +22,10 @@ Global Release|ARM64 = Release|ARM64 Release|x64 = Release|x64 Release|x86 = Release|x86 + Release-LLVM|ARM = Release-LLVM|ARM + Release-LLVM|ARM64 = Release-LLVM|ARM64 + Release-LLVM|x64 = Release-LLVM|x64 + Release-LLVM|x86 = Release-LLVM|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {58789CDC-C8E2-30F9-9FD6-8043C74C79E8}.Debug|ARM.ActiveCfg = Debug|Win32 @@ -36,6 +40,12 @@ Global {58789CDC-C8E2-30F9-9FD6-8043C74C79E8}.Release|x64.Build.0 = Release|x64 {58789CDC-C8E2-30F9-9FD6-8043C74C79E8}.Release|x86.ActiveCfg = Release|Win32 {58789CDC-C8E2-30F9-9FD6-8043C74C79E8}.Release|x86.Build.0 = Release|Win32 + {58789CDC-C8E2-30F9-9FD6-8043C74C79E8}.Release-LLVM|ARM.ActiveCfg = Release-LLVM|Win32 + {58789CDC-C8E2-30F9-9FD6-8043C74C79E8}.Release-LLVM|ARM64.ActiveCfg = Release-LLVM|Win32 + {58789CDC-C8E2-30F9-9FD6-8043C74C79E8}.Release-LLVM|x64.ActiveCfg = Release-LLVM|x64 + {58789CDC-C8E2-30F9-9FD6-8043C74C79E8}.Release-LLVM|x64.Build.0 = Release-LLVM|x64 + {58789CDC-C8E2-30F9-9FD6-8043C74C79E8}.Release-LLVM|x86.ActiveCfg = Release-LLVM|Win32 + {58789CDC-C8E2-30F9-9FD6-8043C74C79E8}.Release-LLVM|x86.Build.0 = Release-LLVM|Win32 {1B89CCF2-963B-30F8-A86A-FB85A0BB8077}.Debug|ARM.ActiveCfg = Debug|Win32 {1B89CCF2-963B-30F8-A86A-FB85A0BB8077}.Debug|ARM64.ActiveCfg = Debug|Win32 {1B89CCF2-963B-30F8-A86A-FB85A0BB8077}.Debug|x64.ActiveCfg = Debug|x64 @@ -48,6 +58,12 @@ Global {1B89CCF2-963B-30F8-A86A-FB85A0BB8077}.Release|x64.Build.0 = Release|x64 {1B89CCF2-963B-30F8-A86A-FB85A0BB8077}.Release|x86.ActiveCfg = Release|Win32 {1B89CCF2-963B-30F8-A86A-FB85A0BB8077}.Release|x86.Build.0 = Release|Win32 + {1B89CCF2-963B-30F8-A86A-FB85A0BB8077}.Release-LLVM|ARM.ActiveCfg = Release-LLVM|Win32 + {1B89CCF2-963B-30F8-A86A-FB85A0BB8077}.Release-LLVM|ARM64.ActiveCfg = Release-LLVM|Win32 + {1B89CCF2-963B-30F8-A86A-FB85A0BB8077}.Release-LLVM|x64.ActiveCfg = Release-LLVM|x64 + {1B89CCF2-963B-30F8-A86A-FB85A0BB8077}.Release-LLVM|x64.Build.0 = Release-LLVM|x64 + {1B89CCF2-963B-30F8-A86A-FB85A0BB8077}.Release-LLVM|x86.ActiveCfg = Release-LLVM|Win32 + {1B89CCF2-963B-30F8-A86A-FB85A0BB8077}.Release-LLVM|x86.Build.0 = Release-LLVM|Win32 {327D7407-D1D2-4788-B399-15B8921CD539}.Debug|ARM.ActiveCfg = Debug|ARM {327D7407-D1D2-4788-B399-15B8921CD539}.Debug|ARM.Build.0 = Debug|ARM {327D7407-D1D2-4788-B399-15B8921CD539}.Debug|ARM64.ActiveCfg = Debug|ARM64 @@ -64,6 +80,14 @@ Global {327D7407-D1D2-4788-B399-15B8921CD539}.Release|x64.Build.0 = Release|x64 {327D7407-D1D2-4788-B399-15B8921CD539}.Release|x86.ActiveCfg = Release|Win32 {327D7407-D1D2-4788-B399-15B8921CD539}.Release|x86.Build.0 = Release|Win32 + {327D7407-D1D2-4788-B399-15B8921CD539}.Release-LLVM|ARM.ActiveCfg = Release-LLVM|ARM + {327D7407-D1D2-4788-B399-15B8921CD539}.Release-LLVM|ARM.Build.0 = Release-LLVM|ARM + {327D7407-D1D2-4788-B399-15B8921CD539}.Release-LLVM|ARM64.ActiveCfg = Release-LLVM|ARM64 + {327D7407-D1D2-4788-B399-15B8921CD539}.Release-LLVM|ARM64.Build.0 = Release-LLVM|ARM64 + {327D7407-D1D2-4788-B399-15B8921CD539}.Release-LLVM|x64.ActiveCfg = Release-LLVM|x64 + {327D7407-D1D2-4788-B399-15B8921CD539}.Release-LLVM|x64.Build.0 = Release-LLVM|x64 + {327D7407-D1D2-4788-B399-15B8921CD539}.Release-LLVM|x86.ActiveCfg = Release-LLVM|Win32 + {327D7407-D1D2-4788-B399-15B8921CD539}.Release-LLVM|x86.Build.0 = Release-LLVM|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/src/GGPO-x-UWP.vcxproj b/src/GGPO-x-UWP.vcxproj index 9a734c30..458771a5 100644 --- a/src/GGPO-x-UWP.vcxproj +++ b/src/GGPO-x-UWP.vcxproj @@ -17,6 +17,22 @@ Debug x64 + + Release-LLVM + ARM + + + Release-LLVM + ARM64 + + + Release-LLVM + Win32 + + + Release-LLVM + x64 + Release ARM @@ -111,24 +127,48 @@ true v142 + + DynamicLibrary + false + true + v142 + DynamicLibrary false true v142 + + DynamicLibrary + false + true + v142 + DynamicLibrary false true v142 + + DynamicLibrary + false + true + v142 + StaticLibrary false true v142 + + StaticLibrary + false + true + v142 + @@ -140,24 +180,36 @@ + + + + + + + + + + + + @@ -168,6 +220,10 @@ false false + + false + false + false false @@ -176,6 +232,10 @@ false false + + false + false + false false @@ -184,6 +244,10 @@ false false + + false + false + false false @@ -192,6 +256,10 @@ false false + + false + false + Use @@ -214,6 +282,17 @@ false + + + Use + false + + + Console + false + false + + Use @@ -236,6 +315,17 @@ false + + + Use + false + + + Console + false + false + + Use @@ -258,6 +348,17 @@ false + + + Use + false + + + Console + false + false + + NotUsing @@ -284,6 +385,19 @@ false + + + NotUsing + false + _WINDLL;%(PreprocessorDefinitions);_WINDOWS; + $(ProjectDir)lib\ggpo;$(ProjectDir)include;%(AdditionalIncludeDirectories) + + + Console + false + false + + diff --git a/src/GGPO-x.dir/Release-LLVM/GGPO-x.lib.recipe b/src/GGPO-x.dir/Release-LLVM/GGPO-x.lib.recipe new file mode 100644 index 00000000..a53f9611 --- /dev/null +++ b/src/GGPO-x.dir/Release-LLVM/GGPO-x.lib.recipe @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/src/GGPO-x.vcxproj b/src/GGPO-x.vcxproj index ad067e95..0c0bf609 100644 --- a/src/GGPO-x.vcxproj +++ b/src/GGPO-x.vcxproj @@ -12,6 +12,14 @@ Debug x64 + + Release-LLVM + Win32 + + + Release-LLVM + x64 + Release Win32 @@ -45,11 +53,21 @@ MultiByte v142 + + StaticLibrary + MultiByte + ClangCL + StaticLibrary MultiByte v140_xp + + StaticLibrary + MultiByte + ClangCL + @@ -71,16 +89,27 @@ true true $(ProjectDir)..\lib\$(Platform)\$(Configuration) + $(ProjectDir)..\lib\$(Platform)\$(Configuration) $(ProjectDir)..\lib\$(Platform)\$(Configuration) + $(ProjectDir)..\lib\$(Platform)\$(Configuration) GGPO-x.dir\$(Configuration)\ + GGPO-x.dir\$(Configuration)\ GGPO-x + GGPO-x GGPO-x + GGPO-x .lib + .lib .lib + .lib false + false false + false true + true true + true @@ -236,6 +265,60 @@ false + + + $(ProjectDir)include;$(ProjectDir)lib\ggpo;%(AdditionalIncludeDirectories) + %(AdditionalOptions) /bigobj + $(IntDir) + false + ProgramDatabase + 4577;4530 + Sync + true + AnySuitable + true + true + MaxSpeed + NotUsing + MultiThreaded + true + true + true + false + Level4 + true + WIN32;_WINDOWS;NDEBUG;GGPO_SHARED_LIB;GGPO_SDK_EXPORT;CMAKE_INTDIR="Release";GGPO_EXPORTS;%(PreprocessorDefinitions) + $(IntDir) + stdcpp17 + + + WIN32;_WINDOWS;NDEBUG;GGPO_SHARED_LIB;GGPO_SDK_EXPORT;CMAKE_INTDIR=\"Release\";GGPO_EXPORTS;%(PreprocessorDefinitions) + $(ProjectDir)include;$(ProjectDir)lib\ggpo-x;%(AdditionalIncludeDirectories) + + + $(ProjectDir)include;$(ProjectDir)lib\ggpo-x;%(AdditionalIncludeDirectories) + $(ProjectDir)/$(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + winmm.lib;ws2_32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;comdlg32.lib;advapi32.lib + %(AdditionalLibraryDirectories) + %(AdditionalOptions) /machine:x64 + true + %(IgnoreSpecificDefaultLibraries) + $(ProjectDir)$(Platform)\$(Configuration)\GGPO-x.lib + UseLinkTimeCodeGeneration + true + $(ProjectDir)$(Platform)\$(Configuration)\GGPO-x.pdb + Console + + + false + + $(ProjectDir)include;$(ProjectDir)lib\ggpo;%(AdditionalIncludeDirectories) @@ -292,6 +375,62 @@ MachineX86 + + + $(ProjectDir)include;$(ProjectDir)lib\ggpo;%(AdditionalIncludeDirectories) + %(AdditionalOptions) /bigobj + $(IntDir) + false + ProgramDatabase + 4577;4530 + Sync + true + AnySuitable + true + true + MaxSpeed + NotUsing + MultiThreaded + true + true + true + false + Level4 + true + WIN32;_WINDOWS;NDEBUG;GGPO_SHARED_LIB;GGPO_SDK_EXPORT;CMAKE_INTDIR="Release";GGPO_EXPORTS;%(PreprocessorDefinitions) + $(IntDir) + + + WIN32;_WINDOWS;NDEBUG;GGPO_SHARED_LIB;GGPO_SDK_EXPORT;CMAKE_INTDIR=\"Release\";GGPO_EXPORTS;%(PreprocessorDefinitions) + $(ProjectDir)include;$(ProjectDir)lib\ggpo-x;%(AdditionalIncludeDirectories) + + + $(ProjectDir)include;$(ProjectDir)lib\ggpo-x;%(AdditionalIncludeDirectories) + $(ProjectDir)/$(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + winmm.lib;ws2_32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;comdlg32.lib;advapi32.lib + %(AdditionalLibraryDirectories) + %(AdditionalOptions) /machine:x64 + true + %(IgnoreSpecificDefaultLibraries) + $(ProjectDir)$(Platform)\$(Configuration)\GGPO-x.lib + UseLinkTimeCodeGeneration + true + $(ProjectDir)$(Platform)\$(Configuration)\GGPO-x.pdb + Console + + + false + + + MachineX86 + + diff --git a/src/apps/vectorwar/VectorWar.vcxproj b/src/apps/vectorwar/VectorWar.vcxproj index 1e2840f3..375ec3bb 100644 --- a/src/apps/vectorwar/VectorWar.vcxproj +++ b/src/apps/vectorwar/VectorWar.vcxproj @@ -12,6 +12,14 @@ Debug x64 + + Release-LLVM + Win32 + + + Release-LLVM + x64 + Release Win32 @@ -45,11 +53,21 @@ Unicode v142 + + Application + Unicode + v142 + Application Unicode v140_xp + + Application + Unicode + v140_xp + @@ -71,20 +89,34 @@ true true $(ProjectDir)..\..\..\bin\$(Platform)\$(Configuration) + $(ProjectDir)..\..\..\bin\$(Platform)\$(Configuration) $(ProjectDir)..\..\..\bin\$(Platform)\$(Configuration) + $(ProjectDir)..\..\..\bin\$(Platform)\$(Configuration) VectorWar.dir\Release\ + VectorWar.dir\Release\ VectorWar + VectorWar VectorWar + VectorWar .exe + .exe .exe + .exe false + false false + false true + true true + true C:\Users\thoma\source\repos\vcpkg + + C:\Users\thoma\source\repos\vcpkg + C:\Users\thoma\source\repos\vcpkg @@ -235,6 +267,58 @@ false + + + ..\..\include;..\..\lib\ggpo-x;%(AdditionalIncludeDirectories) + %(AdditionalOptions) /bigobj + $(IntDir) + false + ProgramDatabase + 4577;4530 + Sync + true + AnySuitable + true + true + MaxSpeed + NotUsing + MultiThreadedDLL + true + true + true + false + Level4 + true + WIN32;_WINDOWS;NDEBUG;ggpo-x_SHARED_LIB;_UNICODE;UNICODE;CMAKE_INTDIR="Release";%(PreprocessorDefinitions) + $(IntDir) + + + WIN32;_WINDOWS;NDEBUG;ggpo-x_SHARED_LIB;_UNICODE;UNICODE;CMAKE_INTDIR=\"Release\";%(PreprocessorDefinitions) + ..\..\include;..\..lib\ggpo-x;%(AdditionalIncludeDirectories) + + + ..\..\include;..\..\lib\ggpo-x;%(AdditionalIncludeDirectories) + $(ProjectDir)/$(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + ggpo-x.lib;winmm.lib;ws2_32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;comdlg32.lib;advapi32.lib + $(ProjectDir)..\..\..\lib\$(Platform)\$(Configuration);%(AdditionalLibraryDirectories) + %(AdditionalOptions) /machine:x64 + true + %(IgnoreSpecificDefaultLibraries) + ..\..\lib/x64/Release/VectorWar.lib + UseLinkTimeCodeGeneration + true + Windows + + + false + + ..\..\include;..\..\lib\ggpo-x;%(AdditionalIncludeDirectories) @@ -287,6 +371,58 @@ false + + + ..\..\include;..\..\lib\ggpo-x;%(AdditionalIncludeDirectories) + %(AdditionalOptions) /bigobj + $(IntDir) + false + ProgramDatabase + 4577;4530 + Sync + true + AnySuitable + true + true + MaxSpeed + NotUsing + MultiThreadedDLL + true + true + true + false + Level4 + true + WIN32;_WINDOWS;NDEBUG;ggpo-x_SHARED_LIB;_UNICODE;UNICODE;CMAKE_INTDIR="Release";%(PreprocessorDefinitions) + $(IntDir) + + + WIN32;_WINDOWS;NDEBUG;ggpo-x_SHARED_LIB;_UNICODE;UNICODE;CMAKE_INTDIR=\"Release\";%(PreprocessorDefinitions) + ..\..\include;..\..lib\ggpo-x;%(AdditionalIncludeDirectories) + + + ..\..\include;..\..\lib\ggpo-x;%(AdditionalIncludeDirectories) + $(ProjectDir)/$(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + ggpo-x.lib;winmm.lib;ws2_32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;comdlg32.lib;advapi32.lib + $(ProjectDir)..\..\..\lib\$(Platform)\$(Configuration);%(AdditionalLibraryDirectories) + %(AdditionalOptions) /machine:x86 + true + %(IgnoreSpecificDefaultLibraries) + ..\..\lib/x64/Release/VectorWar.lib + UseLinkTimeCodeGeneration + true + Windows + + + false + + diff --git a/src/include/ggponet.h b/src/include/ggponet.h index 0b7dbf35..3d7deccc 100644 --- a/src/include/ggponet.h +++ b/src/include/ggponet.h @@ -75,8 +75,8 @@ typedef struct GGPOPlayer { GGPOPlayerType type; int player_num; union { - struct { - } local; + /*struct { + } local;*/ struct { char ip_address[32]; unsigned short port; diff --git a/src/lib/ggpo/backends/backend.h b/src/lib/ggpo/backends/backend.h index 9b2466a8..5708ffde 100644 --- a/src/lib/ggpo/backends/backend.h +++ b/src/lib/ggpo/backends/backend.h @@ -22,12 +22,12 @@ class GGPOSession { virtual GGPOErrorCode CurrentFrame(int& current) =0; virtual GGPOErrorCode Chat(const char* text) = 0;// { return GGPO_OK; } virtual GGPOErrorCode DisconnectPlayer(GGPOPlayerHandle handle) = 0;// { return GGPO_OK; } - virtual GGPOErrorCode GetNetworkStats(GGPONetworkStats *stats, GGPOPlayerHandle handle) { return GGPO_OK; } + virtual GGPOErrorCode GetNetworkStats(GGPONetworkStats *, GGPOPlayerHandle ) { return GGPO_OK; } virtual GGPOErrorCode Logv(const char *fmt, va_list list) { ::Logv(fmt, list); return GGPO_OK; } - virtual GGPOErrorCode SetFrameDelay(GGPOPlayerHandle player, int delay) { return GGPO_ERRORCODE_UNSUPPORTED; } - virtual GGPOErrorCode SetDisconnectTimeout(int timeout) { return GGPO_ERRORCODE_UNSUPPORTED; } - virtual GGPOErrorCode SetDisconnectNotifyStart(int timeout) { return GGPO_ERRORCODE_UNSUPPORTED; } + virtual GGPOErrorCode SetFrameDelay(GGPOPlayerHandle , int ) { return GGPO_ERRORCODE_UNSUPPORTED; } + virtual GGPOErrorCode SetDisconnectTimeout(int ) { return GGPO_ERRORCODE_UNSUPPORTED; } + virtual GGPOErrorCode SetDisconnectNotifyStart(int ) { return GGPO_ERRORCODE_UNSUPPORTED; } }; diff --git a/src/lib/ggpo/backends/p2p.cpp b/src/lib/ggpo/backends/p2p.cpp index ab090f9c..a1e9023a 100644 --- a/src/lib/ggpo/backends/p2p.cpp +++ b/src/lib/ggpo/backends/p2p.cpp @@ -16,13 +16,18 @@ Peer2PeerBackend::Peer2PeerBackend(GGPOSessionCallbacks *cb, uint16 localport, int num_players, int input_size, int nframes) : - _num_players(num_players), - _input_size(input_size), _sync(_local_connect_status, nframes), - _disconnect_timeout(DEFAULT_DISCONNECT_TIMEOUT), - _disconnect_notify_start(DEFAULT_DISCONNECT_NOTIFY_START), _num_spectators(0), - _next_spectator_frame(0) + _input_size(input_size), + + + _num_players(num_players), + + _next_spectator_frame(0), + _disconnect_timeout(DEFAULT_DISCONNECT_TIMEOUT), + _disconnect_notify_start(DEFAULT_DISCONNECT_NOTIFY_START) + + { _callbacks = *cb; _synchronizing = true; @@ -31,7 +36,7 @@ Peer2PeerBackend::Peer2PeerBackend(GGPOSessionCallbacks *cb, /* * Initialize the synchronziation layer */ - Sync::Config config = { 0 }; + Sync::Config config = { {nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr},0 }; config.num_players = num_players; config.input_size = input_size; config.callbacks = _callbacks; @@ -45,7 +50,7 @@ Peer2PeerBackend::Peer2PeerBackend(GGPOSessionCallbacks *cb, _endpoints.resize(_num_players); memset(_local_connect_status, 0, sizeof(_local_connect_status)); - for (int i = 0; i < ARRAY_SIZE(_local_connect_status); i++) { + for (size_t i = 0; i < ARRAY_SIZE(_local_connect_status); i++) { _local_connect_status[i].last_frame = -1; } @@ -229,7 +234,7 @@ Peer2PeerBackend::DoPoll() return GGPO_OK; } -int Peer2PeerBackend::Poll2Players(int current_frame) +int Peer2PeerBackend::Poll2Players(int ) { int i; @@ -254,7 +259,7 @@ int Peer2PeerBackend::Poll2Players(int current_frame) return total_min_confirmed; } -int Peer2PeerBackend::PollNPlayers(int current_frame) +int Peer2PeerBackend::PollNPlayers(int ) { int i, queue, last_received; @@ -492,11 +497,10 @@ Peer2PeerBackend::PollUdpProtocolEvents(void) //} } -void Peer2PeerBackend::CheckRemoteChecksum(int framenumber, uint16 cs) +void Peer2PeerBackend::CheckRemoteChecksum(int framenumber, uint16) { if (framenumber <= _sync.MaxPredictionFrames()) return; - framenumber; cs; //auto frameOfChecksumToSend = framenumber - (_sync.MaxPredictionFrames() + 1); } @@ -527,7 +531,7 @@ Peer2PeerBackend::OnUdpProtocolPeerEvent(UdpProtocol::Event &evt, int queue) { OnUdpProtocolEvent(evt, QueueToPlayerHandle(queue)); switch (evt.type) { - case UdpProtocol::Event::Input: + case UdpProtocol::Event::Type::Input: if (!_local_connect_status[queue].disconnected) { int current_remote_frame = _local_connect_status[queue].last_frame; int new_remote_frame = evt.u.input.input.frame; @@ -554,9 +558,11 @@ Peer2PeerBackend::OnUdpProtocolPeerEvent(UdpProtocol::Event &evt, int queue) } break; - case UdpProtocol::Event::Disconnected: + case UdpProtocol::Event::Type::Disconnected: DisconnectPlayer(QueueToPlayerHandle(queue)); break; + default: + break; } } @@ -570,14 +576,18 @@ Peer2PeerBackend::OnUdpProtocolSpectatorEvent(UdpProtocol::Event &evt, int queue GGPOEvent info; switch (evt.type) { - case UdpProtocol::Event::Disconnected: - _spectators[queue].Disconnect(); + case UdpProtocol::Event::Type::Disconnected: + { _spectators[queue].Disconnect(); - info.code = GGPO_EVENTCODE_DISCONNECTED_FROM_PEER; - info.u.disconnected.player = handle; - _callbacks.on_event(_callbacks.context, &info); + info.code = GGPO_EVENTCODE_DISCONNECTED_FROM_PEER; + info.u.disconnected.player = handle; + _callbacks.on_event(_callbacks.context, &info); - break; + break; + } + + default: + break; } } @@ -587,19 +597,19 @@ Peer2PeerBackend::OnUdpProtocolEvent(UdpProtocol::Event &evt, GGPOPlayerHandle h GGPOEvent info; switch (evt.type) { - case UdpProtocol::Event::Connected: + case UdpProtocol::Event::Type::Connected: info.code = GGPO_EVENTCODE_CONNECTED_TO_PEER; info.u.connected.player = handle; _callbacks.on_event(_callbacks.context, &info); break; - case UdpProtocol::Event::Synchronizing: + case UdpProtocol::Event::Type::Synchronizing: info.code = GGPO_EVENTCODE_SYNCHRONIZING_WITH_PEER; info.u.synchronizing.player = handle; info.u.synchronizing.count = evt.u.synchronizing.count; info.u.synchronizing.total = evt.u.synchronizing.total; _callbacks.on_event(_callbacks.context, &info); break; - case UdpProtocol::Event::Synchronzied: + case UdpProtocol::Event::Type::Synchronzied: info.code = GGPO_EVENTCODE_SYNCHRONIZED_WITH_PEER; info.u.synchronized.player = handle; _callbacks.on_event(_callbacks.context, &info); @@ -607,18 +617,20 @@ Peer2PeerBackend::OnUdpProtocolEvent(UdpProtocol::Event &evt, GGPOPlayerHandle h CheckInitialSync(); break; - case UdpProtocol::Event::NetworkInterrupted: + case UdpProtocol::Event::Type::NetworkInterrupted: info.code = GGPO_EVENTCODE_CONNECTION_INTERRUPTED; info.u.connection_interrupted.player = handle; info.u.connection_interrupted.disconnect_timeout = evt.u.network_interrupted.disconnect_timeout; _callbacks.on_event(_callbacks.context, &info); break; - case UdpProtocol::Event::NetworkResumed: + case UdpProtocol::Event::Type::NetworkResumed: info.code = GGPO_EVENTCODE_CONNECTION_RESUMED; info.u.connection_resumed.player = handle; _callbacks.on_event(_callbacks.context, &info); break; + default: + break; } } diff --git a/src/lib/ggpo/backends/p2p.h b/src/lib/ggpo/backends/p2p.h index 62cfea0f..dc1fa815 100644 --- a/src/lib/ggpo/backends/p2p.h +++ b/src/lib/ggpo/backends/p2p.h @@ -35,7 +35,7 @@ class Peer2PeerBackend : public GGPOSession, Udp::Callbacks { virtual GGPOErrorCode Chat(const char* text) override; virtual GGPOErrorCode CurrentFrame(int& current) override; public: - virtual void OnMsg(sockaddr_in &from, UdpMsg *msg, int len); + virtual void OnMsg(sockaddr_in &from, UdpMsg *msg, int len) override; protected: GGPOErrorCode PlayerHandleToQueue(GGPOPlayerHandle player, int *queue); @@ -49,7 +49,7 @@ class Peer2PeerBackend : public GGPOSession, Udp::Callbacks { int PollNPlayers(int current_frame); void AddRemotePlayer(char *remoteip, uint16 reportport, int queue); GGPOErrorCode AddSpectator(char *remoteip, uint16 reportport); - virtual void OnSyncEvent(Sync::Event &e) { } + virtual void OnSyncEvent(Sync::Event &) { } virtual void OnUdpProtocolEvent(UdpProtocol::Event &e, GGPOPlayerHandle handle); virtual void OnUdpProtocolPeerEvent(UdpProtocol::Event &e, int queue); virtual void OnUdpProtocolSpectatorEvent(UdpProtocol::Event &e, int queue); diff --git a/src/lib/ggpo/backends/spectator.cpp b/src/lib/ggpo/backends/spectator.cpp index 5d101181..7026d64a 100644 --- a/src/lib/ggpo/backends/spectator.cpp +++ b/src/lib/ggpo/backends/spectator.cpp @@ -14,14 +14,14 @@ SpectatorBackend::SpectatorBackend(GGPOSessionCallbacks *cb, int input_size, char *hostip, u_short hostport) : - _num_players(num_players), - _input_size(input_size), + _input_size(input_size), + _num_players(num_players), _next_input_to_send(0) { _callbacks = *cb; _synchronizing = true; - for (int i = 0; i < ARRAY_SIZE(_inputs); i++) { + for (size_t i = 0; i < ARRAY_SIZE(_inputs); i++) { _inputs[i].frame = -1; } @@ -92,9 +92,8 @@ GGPOErrorCode SpectatorBackend::CurrentFrame(int& current) return GGPO_OK; } GGPOErrorCode -SpectatorBackend::IncrementFrame(uint16_t checksum) +SpectatorBackend::IncrementFrame(uint16_t ) { - checksum; Log("End of frame (%d)...\n", _next_input_to_send - 1); DoPoll(); PollUdpProtocolEvents(); @@ -117,19 +116,19 @@ SpectatorBackend::OnUdpProtocolEvent(UdpProtocol::Event &evt) GGPOEvent info; switch (evt.type) { - case UdpProtocol::Event::Connected: + case UdpProtocol::Event::Type::Connected: info.code = GGPO_EVENTCODE_CONNECTED_TO_PEER; info.u.connected.player = 0; _callbacks.on_event(_callbacks.context, &info); break; - case UdpProtocol::Event::Synchronizing: + case UdpProtocol::Event::Type::Synchronizing: info.code = GGPO_EVENTCODE_SYNCHRONIZING_WITH_PEER; info.u.synchronizing.player = 0; info.u.synchronizing.count = evt.u.synchronizing.count; info.u.synchronizing.total = evt.u.synchronizing.total; _callbacks.on_event(_callbacks.context, &info); break; - case UdpProtocol::Event::Synchronzied: + case UdpProtocol::Event::Type::Synchronzied: if (_synchronizing) { info.code = GGPO_EVENTCODE_SYNCHRONIZED_WITH_PEER; info.u.synchronized.player = 0; @@ -141,32 +140,35 @@ SpectatorBackend::OnUdpProtocolEvent(UdpProtocol::Event &evt) } break; - case UdpProtocol::Event::NetworkInterrupted: + case UdpProtocol::Event::Type::NetworkInterrupted: info.code = GGPO_EVENTCODE_CONNECTION_INTERRUPTED; info.u.connection_interrupted.player = 0; info.u.connection_interrupted.disconnect_timeout = evt.u.network_interrupted.disconnect_timeout; _callbacks.on_event(_callbacks.context, &info); break; - case UdpProtocol::Event::NetworkResumed: + case UdpProtocol::Event::Type::NetworkResumed: info.code = GGPO_EVENTCODE_CONNECTION_RESUMED; info.u.connection_resumed.player = 0; _callbacks.on_event(_callbacks.context, &info); break; - case UdpProtocol::Event::Disconnected: + case UdpProtocol::Event::Type::Disconnected: info.code = GGPO_EVENTCODE_DISCONNECTED_FROM_PEER; info.u.disconnected.player = 0; _callbacks.on_event(_callbacks.context, &info); break; - case UdpProtocol::Event::Input: - GameInput& input = evt.u.input.input; + case UdpProtocol::Event::Type::Input: + { GameInput& input = evt.u.input.input; - _host.SetLocalFrameNumber(input.frame); - _host.SendInputAck(); - _inputs[input.frame % SPECTATOR_FRAME_BUFFER_SIZE] = input; - break; + _host.SetLocalFrameNumber(input.frame); + _host.SendInputAck(); + _inputs[input.frame % SPECTATOR_FRAME_BUFFER_SIZE] = input; + break; + } + case UdpProtocol::Event::Type::Unknown: + break; } } diff --git a/src/lib/ggpo/backends/spectator.h b/src/lib/ggpo/backends/spectator.h index 4d464514..07515418 100644 --- a/src/lib/ggpo/backends/spectator.h +++ b/src/lib/ggpo/backends/spectator.h @@ -24,22 +24,22 @@ class SpectatorBackend : public GGPOSession, Udp::Callbacks { public: - virtual GGPOErrorCode DoPoll(); - virtual GGPOErrorCode AddPlayer(GGPOPlayer *player, GGPOPlayerHandle *handle) { return GGPO_ERRORCODE_UNSUPPORTED; } - virtual GGPOErrorCode AddLocalInput(GGPOPlayerHandle player, void *values, int size) { return GGPO_OK; } - virtual GGPOErrorCode SyncInput(void *values, int size, int *disconnect_flags); - virtual GGPOErrorCode IncrementFrame(uint16_t); - virtual GGPOErrorCode DisconnectPlayer(GGPOPlayerHandle handle) { return GGPO_ERRORCODE_UNSUPPORTED; } - virtual GGPOErrorCode GetNetworkStats(GGPONetworkStats *stats, GGPOPlayerHandle handle) { return GGPO_ERRORCODE_UNSUPPORTED; } - virtual GGPOErrorCode SetFrameDelay(GGPOPlayerHandle player, int delay) { return GGPO_ERRORCODE_UNSUPPORTED; } - virtual GGPOErrorCode SetDisconnectTimeout(int timeout) { return GGPO_ERRORCODE_UNSUPPORTED; } - virtual GGPOErrorCode SetDisconnectNotifyStart(int timeout) { return GGPO_ERRORCODE_UNSUPPORTED; } - virtual GGPOErrorCode Chat(const char* text) override { return GGPO_ERRORCODE_UNSUPPORTED; } - virtual GGPOErrorCode CurrentFrame(int& current) override; + GGPOErrorCode DoPoll() override; + GGPOErrorCode AddPlayer(GGPOPlayer *, GGPOPlayerHandle *) override { return GGPO_ERRORCODE_UNSUPPORTED; } + GGPOErrorCode AddLocalInput(GGPOPlayerHandle , void *, int ) override { return GGPO_OK; } + GGPOErrorCode SyncInput(void *, int , int *)override; + GGPOErrorCode IncrementFrame(uint16_t)override; + GGPOErrorCode DisconnectPlayer(GGPOPlayerHandle )override { return GGPO_ERRORCODE_UNSUPPORTED; } + GGPOErrorCode GetNetworkStats(GGPONetworkStats *, GGPOPlayerHandle ) override { return GGPO_ERRORCODE_UNSUPPORTED; } + GGPOErrorCode SetFrameDelay(GGPOPlayerHandle , int ) override { return GGPO_ERRORCODE_UNSUPPORTED; } + GGPOErrorCode SetDisconnectTimeout(int ) override { return GGPO_ERRORCODE_UNSUPPORTED; } + GGPOErrorCode SetDisconnectNotifyStart(int ) override { return GGPO_ERRORCODE_UNSUPPORTED; } + GGPOErrorCode Chat(const char* ) override { return GGPO_ERRORCODE_UNSUPPORTED; } + GGPOErrorCode CurrentFrame(int& ) override; public: - virtual void OnMsg(sockaddr_in &from, UdpMsg *msg, int len); + void OnMsg(sockaddr_in &from, UdpMsg *msg, int len) override; protected: void PollUdpProtocolEvents(void); diff --git a/src/lib/ggpo/backends/synctest.cpp b/src/lib/ggpo/backends/synctest.cpp index 692bab4d..98c4cb55 100644 --- a/src/lib/ggpo/backends/synctest.cpp +++ b/src/lib/ggpo/backends/synctest.cpp @@ -26,7 +26,7 @@ SyncTestBackend::SyncTestBackend(GGPOSessionCallbacks *cb, /* * Initialize the synchronziation layer */ - Sync::Config config = { 0 }; + Sync::Config config = { {nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr},0 }; config.callbacks = _callbacks; config.num_prediction_frames = MAX_PREDICTION_FRAMES; _sync.Init(config); @@ -106,9 +106,8 @@ GGPOErrorCode SyncTestBackend::CurrentFrame(int& current) } GGPOErrorCode -SyncTestBackend::IncrementFrame(uint16_t cs) +SyncTestBackend::IncrementFrame(uint16_t ) { - cs; _sync.IncrementFrame(); _current_input.erase(); @@ -180,7 +179,7 @@ SyncTestBackend::RaiseSyncError(const char *fmt, ...) } GGPOErrorCode -SyncTestBackend::Logv(char *fmt, va_list list) +SyncTestBackend::Logv(const char *fmt, va_list list) { if (_logfp) { vfprintf(_logfp, fmt, list); diff --git a/src/lib/ggpo/backends/synctest.h b/src/lib/ggpo/backends/synctest.h index f0955a35..06044b23 100644 --- a/src/lib/ggpo/backends/synctest.h +++ b/src/lib/ggpo/backends/synctest.h @@ -18,15 +18,15 @@ class SyncTestBackend : public GGPOSession { SyncTestBackend(GGPOSessionCallbacks *cb, char *gamename, int frames, int num_players); virtual ~SyncTestBackend(); - virtual GGPOErrorCode DoPoll(); - virtual GGPOErrorCode AddPlayer(GGPOPlayer *player, GGPOPlayerHandle *handle); - virtual GGPOErrorCode AddLocalInput(GGPOPlayerHandle player, void *values, int size); - virtual GGPOErrorCode SyncInput(void *values, int size, int *disconnect_flags); - virtual GGPOErrorCode IncrementFrame(uint16_t checksum); - virtual GGPOErrorCode Logv(char *fmt, va_list list); - virtual GGPOErrorCode DisconnectPlayer(GGPOPlayerHandle handle) { return GGPO_OK; } - virtual GGPOErrorCode Chat(const char* text) override { return GGPO_ERRORCODE_UNSUPPORTED; } - virtual GGPOErrorCode CurrentFrame(int& current) override; + GGPOErrorCode DoPoll() override; + GGPOErrorCode AddPlayer(GGPOPlayer *player, GGPOPlayerHandle *handle)override; + GGPOErrorCode AddLocalInput(GGPOPlayerHandle player, void *values, int size)override; + GGPOErrorCode SyncInput(void *values, int size, int *disconnect_flags)override; + GGPOErrorCode IncrementFrame(uint16_t checksum)override; + GGPOErrorCode Logv(const char *fmt, va_list list)override; + GGPOErrorCode DisconnectPlayer(GGPOPlayerHandle ) override { return GGPO_OK; } + GGPOErrorCode Chat(const char* ) override { return GGPO_ERRORCODE_UNSUPPORTED; } + GGPOErrorCode CurrentFrame(int& current) override; protected: struct SavedInfo { int frame; diff --git a/src/lib/ggpo/game_input.h b/src/lib/ggpo/game_input.h index a19b834b..307db101 100644 --- a/src/lib/ggpo/game_input.h +++ b/src/lib/ggpo/game_input.h @@ -18,9 +18,7 @@ #define GAMEINPUT_MAX_PLAYERS 6 struct GameInput { - enum Constants { - NullFrame = -1 - }; + static const int NullFrame = -1; int frame; int size; /* size in bytes of the entire input for all players */ char bits[GAMEINPUT_MAX_BYTES * GAMEINPUT_MAX_PLAYERS]; diff --git a/src/lib/ggpo/input_queue.cpp b/src/lib/ggpo/input_queue.cpp index ee143dc7..7edaf3a6 100644 --- a/src/lib/ggpo/input_queue.cpp +++ b/src/lib/ggpo/input_queue.cpp @@ -40,7 +40,7 @@ InputQueue::Init(int id, int input_size) * no virtual methods, no contained classes, etc.). */ memset(_inputs, 0, sizeof _inputs); - for (int i = 0; i < ARRAY_SIZE(_inputs); i++) { + for (size_t i = 0; i < ARRAY_SIZE(_inputs); i++) { _inputs[i].size = input_size; } } diff --git a/src/lib/ggpo/main.cpp b/src/lib/ggpo/main.cpp index e858394f..f83d90ba 100644 --- a/src/lib/ggpo/main.cpp +++ b/src/lib/ggpo/main.cpp @@ -12,7 +12,7 @@ #include "ggponet.h" BOOL WINAPI -DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) +DllMain(HINSTANCE , DWORD , LPVOID ) { srand(Platform::GetCurrentTimeMS() + Platform::GetProcessID()); return TRUE; @@ -71,7 +71,7 @@ ggpo_start_synctest(GGPOSession **ggpo, GGPOSessionCallbacks *cb, char *game, int num_players, - int input_size, + int , int frames) { *ggpo = new SyncTestBackend(cb, game, frames, num_players); diff --git a/src/lib/ggpo/network/udp.cpp b/src/lib/ggpo/network/udp.cpp index 5c225047..1e02da70 100644 --- a/src/lib/ggpo/network/udp.cpp +++ b/src/lib/ggpo/network/udp.cpp @@ -79,7 +79,7 @@ Udp::SendTo(char *buffer, int len, int flags, struct sockaddr *dst, int destlen) } bool -Udp::OnLoopPoll(void *cookie) +Udp::OnLoopPoll(void *) { uint8 recv_buf[MAX_UDP_PACKET_SIZE]; sockaddr_in recv_addr; diff --git a/src/lib/ggpo/network/udp_proto.cpp b/src/lib/ggpo/network/udp_proto.cpp index cdbfd624..e89069c7 100644 --- a/src/lib/ggpo/network/udp_proto.cpp +++ b/src/lib/ggpo/network/udp_proto.cpp @@ -21,25 +21,9 @@ static const int NETWORK_STATS_INTERVAL = 500; static const int UDP_SHUTDOWN_TIMER = 5000; static const int MAX_SEQ_DISTANCE = (1 << 15); -UdpProtocol::UdpProtocol() : - _local_frame_advantage(0), - _remote_frame_advantage(0), - _queue(-1), - _magic_number(0), - _remote_magic_number(0), - _packets_sent(0), - _bytes_sent(0), - _stats_start_time(0), - _last_send_time(0), - _shutdown_timeout(0), - _disconnect_timeout(0), - _disconnect_notify_start(0), - _disconnect_notify_sent(false), - _disconnect_event_sent(false), - _connected(false), - _next_send_seq(0), - _next_recv_seq(0), - _udp(NULL) + + +UdpProtocol::UdpProtocol() { _last_sent_input.init(-1, NULL, 1); _last_received_input.init(-1, NULL, 1); @@ -47,7 +31,7 @@ UdpProtocol::UdpProtocol() : memset(&_state, 0, sizeof _state); memset(_peer_connect_status, 0, sizeof(_peer_connect_status)); - for (int i = 0; i < ARRAY_SIZE(_peer_connect_status); i++) { + for (size_t i = 0; i < ARRAY_SIZE(_peer_connect_status); i++) { _peer_connect_status[i].last_frame = -1; } memset(&_peer_addr, 0, sizeof _peer_addr); @@ -131,7 +115,7 @@ UdpProtocol::SendPendingOutput() msg->u.input.start_frame = _pending_output.front().frame; msg->u.input.input_size = (uint8)_pending_output.front().size; - ASSERT(last.frame == -1 || last.frame + 1 == msg->u.input.start_frame); + ASSERT(last.frame == -1 || last.frame + 1 == (int)msg->u.input.start_frame); for (j = 0; j < _pending_output.size(); j++) { GameInput ¤t = _pending_output.item(j); msg->u.input.checksum16 = current.checksum; @@ -213,7 +197,7 @@ void UdpProtocol::SendChat(const char* message) } bool -UdpProtocol::OnLoopPoll(void *cookie) +UdpProtocol::OnLoopPoll(void *) { if (!_udp) { return true; @@ -263,7 +247,7 @@ UdpProtocol::OnLoopPoll(void *cookie) if (_disconnect_timeout && _disconnect_notify_start && !_disconnect_notify_sent && (_last_recv_time + _disconnect_notify_start < now)) { Log("Endpoint has stopped receiving packets for %d ms. Sending notification.\n", _disconnect_notify_start); - Event e(Event::NetworkInterrupted); + Event e(Event::Type::NetworkInterrupted); e.u.network_interrupted.disconnect_timeout = _disconnect_timeout - _disconnect_notify_start; QueueEvent(e); _disconnect_notify_sent = true; @@ -272,7 +256,7 @@ UdpProtocol::OnLoopPoll(void *cookie) if (_disconnect_timeout && (_last_recv_time + _disconnect_timeout < now)) { if (!_disconnect_event_sent) { Log("Endpoint has stopped receiving packets for %d ms. Disconnecting.\n", _disconnect_timeout); - QueueEvent(Event(Event::Disconnected)); + QueueEvent(Event(Event::Type::Disconnected)); _disconnect_event_sent = true; } } @@ -284,7 +268,9 @@ UdpProtocol::OnLoopPoll(void *cookie) _udp = NULL; _shutdown_timeout = 0; } - + break; + case Synchronzied: + break; } @@ -326,7 +312,7 @@ UdpProtocol::SendMsg(UdpMsg *msg) bool UdpProtocol::HandlesMsg(sockaddr_in &from, - UdpMsg *msg) + UdpMsg *) { if (!_udp) { return false; @@ -380,7 +366,7 @@ UdpProtocol::OnMsg(UdpMsg *msg, int len) if (handled) { _last_recv_time = Platform::GetCurrentTimeMS(); if (_disconnect_notify_sent && _current_state == Running) { - QueueEvent(Event(Event::NetworkResumed)); + QueueEvent(Event(Event::Type::NetworkResumed)); _disconnect_notify_sent = false; } } @@ -491,21 +477,23 @@ void UdpProtocol::LogEvent(const char *prefix, const UdpProtocol::Event &evt) { switch (evt.type) { - case UdpProtocol::Event::Synchronzied: + case UdpProtocol::Event::Type::Synchronzied: Log("%s (event: Synchronzied).\n", prefix); break; + default: + break; } } bool -UdpProtocol::OnInvalid(UdpMsg *msg, int len) +UdpProtocol::OnInvalid(UdpMsg *, int ) { // ASSERT(FALSE && "Invalid msg in UdpProtocol"); return false; } bool -UdpProtocol::OnSyncRequest(UdpMsg *msg, int len) +UdpProtocol::OnSyncRequest(UdpMsg *msg, int ) { if (_remote_magic_number != 0 && msg->hdr.magic != _remote_magic_number) { Log("Ignoring sync request from unknown endpoint (%d != %d).\n", @@ -521,7 +509,7 @@ UdpProtocol::OnSyncRequest(UdpMsg *msg, int len) } bool -UdpProtocol::OnSyncReply(UdpMsg *msg, int len) +UdpProtocol::OnSyncReply(UdpMsg *msg, int ) { if (_current_state != Syncing) { Log("Ignoring SyncReply while not synching.\n"); @@ -535,19 +523,19 @@ UdpProtocol::OnSyncReply(UdpMsg *msg, int len) } if (!_connected) { - QueueEvent(Event(Event::Connected)); + QueueEvent(Event(Event::Type::Connected)); _connected = true; } Log("Checking sync state (%d round trips remaining).\n", _state.sync.roundtrips_remaining); if (--_state.sync.roundtrips_remaining == 0) { Log("Synchronized!\n"); - QueueEvent(UdpProtocol::Event(UdpProtocol::Event::Synchronzied)); + QueueEvent(UdpProtocol::Event(UdpProtocol::Event::Type::Synchronzied)); _current_state = Running; _last_received_input.frame = -1; _remote_magic_number = msg->hdr.magic; } else { - UdpProtocol::Event evt(UdpProtocol::Event::Synchronizing); + UdpProtocol::Event evt(UdpProtocol::Event::Type::Synchronizing); evt.u.synchronizing.total = NUM_SYNC_PACKETS; evt.u.synchronizing.count = NUM_SYNC_PACKETS - _state.sync.roundtrips_remaining; QueueEvent(evt); @@ -557,7 +545,7 @@ UdpProtocol::OnSyncReply(UdpMsg *msg, int len) } bool -UdpProtocol::OnInput(UdpMsg *msg, int len) +UdpProtocol::OnInput(UdpMsg *msg, int ) { /* * If a disconnect is requested, go ahead and disconnect now. @@ -566,7 +554,7 @@ UdpProtocol::OnInput(UdpMsg *msg, int len) if (disconnect_requested) { if (_current_state != Disconnected && !_disconnect_event_sent) { Log("Disconnecting endpoint on remote request.\n"); - QueueEvent(Event(Event::Disconnected)); + QueueEvent(Event(Event::Type::Disconnected)); _disconnect_event_sent = true; } } else { @@ -575,7 +563,7 @@ UdpProtocol::OnInput(UdpMsg *msg, int len) * of the network. */ UdpMsg::connect_status* remote_status = msg->u.input.peer_connect_status; - for (int i = 0; i < ARRAY_SIZE(_peer_connect_status); i++) { + for (size_t i = 0; i < ARRAY_SIZE(_peer_connect_status); i++) { ASSERT(remote_status[i].last_frame >= _peer_connect_status[i].last_frame); _peer_connect_status[i].disconnected = _peer_connect_status[i].disconnected || remote_status[i].disconnected; _peer_connect_status[i].last_frame = MAX(_peer_connect_status[i].last_frame, remote_status[i].last_frame); @@ -631,7 +619,7 @@ UdpProtocol::OnInput(UdpMsg *msg, int len) /* * Send the event to the emualtor */ - UdpProtocol::Event evt(UdpProtocol::Event::Input); + UdpProtocol::Event evt(UdpProtocol::Event::Type::Input); evt.u.input.input = _last_received_input; _last_received_input.desc(desc, ARRAY_SIZE(desc)); @@ -667,7 +655,7 @@ UdpProtocol::OnInput(UdpMsg *msg, int len) bool -UdpProtocol::OnInputAck(UdpMsg *msg, int len) +UdpProtocol::OnInputAck(UdpMsg *msg, int ) { /* * Get rid of our buffered input @@ -681,7 +669,7 @@ UdpProtocol::OnInputAck(UdpMsg *msg, int len) } bool -UdpProtocol::OnQualityReport(UdpMsg *msg, int len) +UdpProtocol::OnQualityReport(UdpMsg *msg, int ) { // send a reply so the other side can compute the round trip transmit time. UdpMsg *reply = new UdpMsg(UdpMsg::QualityReply); @@ -693,7 +681,7 @@ UdpProtocol::OnQualityReport(UdpMsg *msg, int len) } bool -UdpProtocol::OnQualityReply(UdpMsg *msg, int len) +UdpProtocol::OnQualityReply(UdpMsg *msg, int ) { _round_trip_time = Platform::GetCurrentTimeMS() - msg->u.quality_reply.pong; @@ -702,7 +690,7 @@ UdpProtocol::OnQualityReply(UdpMsg *msg, int len) } bool -UdpProtocol::OnKeepAlive(UdpMsg *msg, int len) +UdpProtocol::OnKeepAlive(UdpMsg *, int ) { return true; } @@ -712,7 +700,7 @@ void UdpProtocol::ConsumeChat(std::function onChat) onChat(msg.c_str()); _chatMessages.clear(); } -bool UdpProtocol::OnChat(UdpMsg* msg, int len) +bool UdpProtocol::OnChat(UdpMsg* msg, int ) { _chatMessages.push_back(msg->u.chat.msg); return true; @@ -779,7 +767,7 @@ UdpProtocol::PumpSendQueue() // should really come up with a gaussian distributation based on the configured // value, but this will do for now. int jitter = (_send_latency * 2 / 3) + ((rand() % _send_latency) / 3); - if (Platform::GetCurrentTimeMS() < _send_queue.front().queue_time + jitter) { + if ((int)Platform::GetCurrentTimeMS() < _send_queue.front().queue_time + jitter) { break; } } @@ -799,7 +787,7 @@ UdpProtocol::PumpSendQueue() } _send_queue.pop(); } - if (_oo_packet.msg && _oo_packet.send_time < Platform::GetCurrentTimeMS()) { + if (_oo_packet.msg && _oo_packet.send_time < (int)Platform::GetCurrentTimeMS()) { Log("sending rogue oop!"); _udp->SendTo((char *)_oo_packet.msg, _oo_packet.msg->PacketSize(), 0, (struct sockaddr *)&_oo_packet.dest_addr, sizeof _oo_packet.dest_addr); diff --git a/src/lib/ggpo/network/udp_proto.h b/src/lib/ggpo/network/udp_proto.h index 14947e27..9828906b 100644 --- a/src/lib/ggpo/network/udp_proto.h +++ b/src/lib/ggpo/network/udp_proto.h @@ -33,7 +33,7 @@ class UdpProtocol : public IPollSink }; struct Event { - enum Type { + enum class Type { Unknown = -1, Connected, Synchronizing, @@ -58,7 +58,7 @@ class UdpProtocol : public IPollSink } network_interrupted; } u; - UdpProtocol::Event(Type t = Unknown) : type(t) { } + Event(Event::Type t = Event::Type::Unknown) : type(t) { }; }; public: @@ -136,12 +136,12 @@ class UdpProtocol : public IPollSink /* * Network transmission information */ - Udp *_udp; + Udp *_udp= nullptr; sockaddr_in _peer_addr; - uint16 _magic_number; - int _queue; - uint16 _remote_magic_number; - bool _connected; + uint16 _magic_number=0; + int _queue=-1; + uint16 _remote_magic_number=0; + bool _connected=false; int _send_latency; int _oop_percent; struct { @@ -155,10 +155,10 @@ class UdpProtocol : public IPollSink * Stats */ int _round_trip_time = 0; - int _packets_sent; - int _bytes_sent; - int _kbps_sent; - int _stats_start_time; + int _packets_sent=0; + int _bytes_sent=0; + int _kbps_sent=0; + int _stats_start_time=0; /* * The state machine @@ -182,8 +182,8 @@ class UdpProtocol : public IPollSink /* * Fairness. */ - float _local_frame_advantage; - float _remote_frame_advantage; + float _local_frame_advantage=0; + float _remote_frame_advantage=0; /* * Packet loss... @@ -192,16 +192,16 @@ class UdpProtocol : public IPollSink GameInput _last_received_input; GameInput _last_sent_input; GameInput _last_acked_input; - unsigned int _last_send_time; - unsigned int _last_recv_time; - unsigned int _shutdown_timeout; - unsigned int _disconnect_event_sent; - unsigned int _disconnect_timeout; - unsigned int _disconnect_notify_start; - bool _disconnect_notify_sent; - - uint16 _next_send_seq; - uint16 _next_recv_seq; + unsigned int _last_send_time=0; + unsigned int _last_recv_time=0; + unsigned int _shutdown_timeout=0; + unsigned int _disconnect_event_sent=0; + unsigned int _disconnect_timeout=0; + unsigned int _disconnect_notify_start=0; + bool _disconnect_notify_sent=false; + + uint16 _next_send_seq=0; + uint16 _next_recv_seq=0; /* * Rift synchronization. diff --git a/src/lib/ggpo/platform_windows.cpp b/src/lib/ggpo/platform_windows.cpp index 3c8b9208..356e0a26 100644 --- a/src/lib/ggpo/platform_windows.cpp +++ b/src/lib/ggpo/platform_windows.cpp @@ -8,7 +8,7 @@ #include "platform_windows.h" int -Platform::GetConfigInt(const char* name) +Platform::GetConfigInt(const char* ) { return 0; /* char buf[1024]; @@ -18,7 +18,7 @@ Platform::GetConfigInt(const char* name) return atoi(buf);*/ } -bool Platform::GetConfigBool(const char* name) +bool Platform::GetConfigBool(const char* ) { return false; //char buf[1024]; diff --git a/src/lib/ggpo/poll.cpp b/src/lib/ggpo/poll.cpp index b5c0b500..3c8499ac 100644 --- a/src/lib/ggpo/poll.cpp +++ b/src/lib/ggpo/poll.cpp @@ -41,7 +41,7 @@ Poll::Run() } bool -Poll::Pump(int timeout) +Poll::Pump(int ) { int i; bool finished = false; diff --git a/src/lib/ggpo/sync.cpp b/src/lib/ggpo/sync.cpp index 2440e417..9df874bc 100644 --- a/src/lib/ggpo/sync.cpp +++ b/src/lib/ggpo/sync.cpp @@ -8,9 +8,10 @@ #include "sync.h" Sync::Sync(UdpMsg::connect_status *connect_status, int maxPrediction) : - _local_connect_status(connect_status), - _input_queues(NULL), - _savedstate(maxPrediction) + _savedstate(maxPrediction), + _input_queues(NULL), + _local_connect_status(connect_status) + { _framecount = 0; _last_confirmed_frame = -1; @@ -23,7 +24,7 @@ Sync::~Sync() * Delete frames manually here rather than in a destructor of the SavedFrame * structure so we can efficently copy frames via weak references. */ - for (int i = 0; i < _savedstate.frames.size(); i++) { + for (size_t i = 0; i < _savedstate.frames.size(); i++) { _callbacks.free_buffer(_callbacks.context, _savedstate.frames[i].buf); } delete [] _input_queues; diff --git a/src/lib/ggpo/sync.h b/src/lib/ggpo/sync.h index 76308ae2..efd769b1 100644 --- a/src/lib/ggpo/sync.h +++ b/src/lib/ggpo/sync.h @@ -23,9 +23,9 @@ class Sync { public: struct Config { GGPOSessionCallbacks callbacks; - int num_prediction_frames; - int num_players; - int input_size; + int num_prediction_frames=0; + int num_players=0; + int input_size=0; }; struct Event { enum { diff --git a/src/lib/ggpo/timesync.cpp b/src/lib/ggpo/timesync.cpp index b3da7c40..a94c74e0 100644 --- a/src/lib/ggpo/timesync.cpp +++ b/src/lib/ggpo/timesync.cpp @@ -41,7 +41,7 @@ TimeSync::advance_frame(GameInput &input, float advantage, float radvantage) } float TimeSync::LocalAdvantage() const { - int i ; + size_t i ; float advantage=0; for (i = 0; i < ARRAY_SIZE(_local); i++) { advantage += _local[i]; @@ -52,7 +52,7 @@ float TimeSync::LocalAdvantage() const float TimeSync::RemoteAdvantage() const { - int i; + size_t i; float advantage = 0;; for (i = 0; i < ARRAY_SIZE(_local); i++) { advantage += _remote[i]; @@ -61,7 +61,7 @@ float TimeSync::RemoteAdvantage() const return (advantage); } float -TimeSync::recommend_frame_wait_duration(bool require_idle_input) +TimeSync::recommend_frame_wait_duration(bool ) { auto advantage = LocalAdvantage(); diff --git a/src/lib/ggpo/types.h b/src/lib/ggpo/types.h index d4d5080c..2017e1a8 100644 --- a/src/lib/ggpo/types.h +++ b/src/lib/ggpo/types.h @@ -55,7 +55,7 @@ typedef int int32; do { \ if (!(x)) { \ char assert_buf[1024]; \ - snprintf(assert_buf, sizeof(assert_buf) - 1, "Assertion: %s @ %s:%d (pid:%d)", #x, __FILE__, __LINE__, Platform::GetProcessID()); \ + snprintf(assert_buf, sizeof(assert_buf) - 1, "Assertion: %s @ %s:%d (pid:%d)", #x, __FILE__, __LINE__, (int)Platform::GetProcessID()); \ Log("%s\n", assert_buf); \ Log("\n"); \ Log("\n"); \ From 3dc96983355081a8ed84b754b6bdd95294e5e05a Mon Sep 17 00:00:00 2001 From: thd79 Date: Fri, 14 Jul 2023 21:46:15 +0100 Subject: [PATCH 32/40] uwp --- src/GGPO-x-UWP.vcxproj | 6 +++--- src/lib/ggpo/platform_windows.h | 9 ++++++++- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/GGPO-x-UWP.vcxproj b/src/GGPO-x-UWP.vcxproj index 458771a5..ab3908ca 100644 --- a/src/GGPO-x-UWP.vcxproj +++ b/src/GGPO-x-UWP.vcxproj @@ -363,7 +363,7 @@ NotUsing false - _WINDLL;%(PreprocessorDefinitions);_WINDOWS; + _WINDLL;%(PreprocessorDefinitions);_WINDOWS;_UWP_; $(ProjectDir)lib\ggpo;$(ProjectDir)include;%(AdditionalIncludeDirectories) @@ -376,7 +376,7 @@ NotUsing false - _WINDLL;%(PreprocessorDefinitions);_WINDOWS; + _WINDLL;%(PreprocessorDefinitions);_WINDOWS;_UWP_; $(ProjectDir)lib\ggpo;$(ProjectDir)include;%(AdditionalIncludeDirectories) @@ -389,7 +389,7 @@ NotUsing false - _WINDLL;%(PreprocessorDefinitions);_WINDOWS; + _WINDLL;%(PreprocessorDefinitions);_WINDOWS;_UWP_; $(ProjectDir)lib\ggpo;$(ProjectDir)include;%(AdditionalIncludeDirectories) diff --git a/src/lib/ggpo/platform_windows.h b/src/lib/ggpo/platform_windows.h index cca9d9b5..67d09b6d 100644 --- a/src/lib/ggpo/platform_windows.h +++ b/src/lib/ggpo/platform_windows.h @@ -22,7 +22,14 @@ class Platform { public: // functions static ProcessID GetProcessID() { return GetCurrentProcessId(); } - static void AssertFailed(char* msg) { MessageBoxA(NULL, msg, "GGPO Assertion Failed", MB_OK | MB_ICONEXCLAMATION); } + static void AssertFailed(char* msg) { +#ifdef _UWP_ + throw std::exception(msg);// , "GGPO Assertion Failed", MB_OK | MB_ICONEXCLAMATION); +#else + + MessageBoxA(NULL, msg, "GGPO Assertion Failed", MB_OK | MB_ICONEXCLAMATION); +#endif + } static uint32 GetCurrentTimeMS() { static auto startTime = high_resolution_clock::now(); From 2e7a888a49f0ef3bcbb4e800b5a5a20b64431061 Mon Sep 17 00:00:00 2001 From: thd79 Date: Wed, 15 Nov 2023 23:21:10 +0000 Subject: [PATCH 33/40] remove dead files --- src/GGPO-x.vcxproj | 2 - src/GGPO-x.vcxproj.filters | 2 - src/lib/ggpo/zconf.h | 283 ------------ src/lib/ggpo/zlib.h | 893 ------------------------------------- 4 files changed, 1180 deletions(-) delete mode 100644 src/lib/ggpo/zconf.h delete mode 100644 src/lib/ggpo/zlib.h diff --git a/src/GGPO-x.vcxproj b/src/GGPO-x.vcxproj index ff899841..162079f0 100644 --- a/src/GGPO-x.vcxproj +++ b/src/GGPO-x.vcxproj @@ -302,8 +302,6 @@ - - diff --git a/src/GGPO-x.vcxproj.filters b/src/GGPO-x.vcxproj.filters index d619690f..939a070f 100644 --- a/src/GGPO-x.vcxproj.filters +++ b/src/GGPO-x.vcxproj.filters @@ -26,8 +26,6 @@ - - diff --git a/src/lib/ggpo/zconf.h b/src/lib/ggpo/zconf.h deleted file mode 100644 index 7374ff73..00000000 --- a/src/lib/ggpo/zconf.h +++ /dev/null @@ -1,283 +0,0 @@ -/* zconf.h -- configuration of the zlib compression library - * Copyright (C) 1995-2002 Jean-loup Gailly. - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -// Dave: -#define ZEXPORT __fastcall -#define ZEXPORTVA __cdecl - -/* @(#) $Id$ */ - -#ifndef _ZCONF_H -#define _ZCONF_H - -/* - * If you *really* need a unique prefix for all types and library functions, - * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. - */ -#ifdef Z_PREFIX -# define deflateInit_ z_deflateInit_ -# define deflate z_deflate -# define deflateEnd z_deflateEnd -# define inflateInit_ z_inflateInit_ -# define inflate z_inflate -# define inflateEnd z_inflateEnd -# define deflateInit2_ z_deflateInit2_ -# define deflateSetDictionary z_deflateSetDictionary -# define deflateCopy z_deflateCopy -# define deflateReset z_deflateReset -# define deflateParams z_deflateParams -# define inflateInit2_ z_inflateInit2_ -# define inflateSetDictionary z_inflateSetDictionary -# define inflateSync z_inflateSync -# define inflateSyncPoint z_inflateSyncPoint -# define inflateReset z_inflateReset -# define compress z_compress -# define compress2 z_compress2 -# define uncompress z_uncompress -# define adler32 z_adler32 -# define crc32 z_crc32 -# define get_crc_table z_get_crc_table - -# define Byte z_Byte -# define uInt z_uInt -# define uLong z_uLong -# define Bytef z_Bytef -# define charf z_charf -# define intf z_intf -# define uIntf z_uIntf -# define uLongf z_uLongf -# define voidpf z_voidpf -# define voidp z_voidp -#endif - -#if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32) -# define WIN32 -#endif -#if defined(__GNUC__) || defined(WIN32) || defined(__386__) || defined(i386) -# ifndef __32BIT__ -# define __32BIT__ -# endif -#endif -#if defined(__MSDOS__) && !defined(MSDOS) -# define MSDOS -#endif - -/* - * Compile with -DMAXSEG_64K if the alloc function cannot allocate more - * than 64k bytes at a time (needed on systems with 16-bit int). - */ -#if defined(MSDOS) && !defined(__32BIT__) -# define MAXSEG_64K -#endif -#ifdef MSDOS -# define UNALIGNED_OK -#endif - -#if (defined(MSDOS) || defined(_WINDOWS) || defined(WIN32)) && !defined(STDC) -# define STDC -#endif -#if defined(__STDC__) || defined(__cplusplus) || defined(__OS2__) -# ifndef STDC -# define STDC -# endif -#endif - -#ifndef STDC -# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ -# define const -# endif -#endif - -/* Some Mac compilers merge all .h files incorrectly: */ -#if defined(__MWERKS__) || defined(applec) ||defined(THINK_C) ||defined(__SC__) -# define NO_DUMMY_DECL -#endif - -/* Old Borland C incorrectly complains about missing returns: */ -#if defined(__BORLANDC__) && (__BORLANDC__ < 0x500) -# define NEED_DUMMY_RETURN -#endif - - -/* Maximum value for memLevel in deflateInit2 */ -#ifndef MAX_MEM_LEVEL -# ifdef MAXSEG_64K -# define MAX_MEM_LEVEL 8 -# else -# define MAX_MEM_LEVEL 9 -# endif -#endif - -/* Maximum value for windowBits in deflateInit2 and inflateInit2. - * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files - * created by gzip. (Files created by minigzip can still be extracted by - * gzip.) - */ -#ifndef MAX_WBITS -# define MAX_WBITS 15 /* 32K LZ77 window */ -#endif - -/* The memory requirements for deflate are (in bytes): - (1 << (windowBits+2)) + (1 << (memLevel+9)) - that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) - plus a few kilobytes for small objects. For example, if you want to reduce - the default memory requirements from 256K to 128K, compile with - make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" - Of course this will generally degrade compression (there's no free lunch). - - The memory requirements for inflate are (in bytes) 1 << windowBits - that is, 32K for windowBits=15 (default value) plus a few kilobytes - for small objects. -*/ - - /* Type declarations */ - -#ifndef OF /* function prototypes */ -# ifdef STDC -# define OF(args) args -# else -# define OF(args) () -# endif -#endif - -/* The following definitions for FAR are needed only for MSDOS mixed - * model programming (small or medium model with some far allocations). - * This was tsted only with MSC; for other MSDOS compilers you may have - * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, - * just define FAR to be empty. - */ -#if (defined(M_I86SM) || defined(M_I86MM)) && !defined(__32BIT__) - /* MSC small or medium model */ -# define SMALL_MEDIUM -# ifdef _MSC_VER -# define FAR _far -# else -# define FAR far -# endif -#endif -#if defined(__BORLANDC__) && (defined(__SMALL__) || defined(__MEDIUM__)) -# ifndef __32BIT__ -# define SMALL_MEDIUM -# define FAR _far -# endif -#endif - -/* Compile with -DZLIB_DLL for Windows DLL support */ -#if defined(ZLIB_DLL) -# if defined(_WINDOWS) || defined(WINDOWS) -# ifdef FAR -# undef FAR -# endif -# include -# define ZEXPORT WINAPI -# ifdef WIN32 -# define ZEXPORTVA WINAPIV -# else -# define ZEXPORTVA FAR _cdecl _export -# endif -# endif -# if defined (__BORLANDC__) -# if (__BORLANDC__ >= 0x0500) && defined (WIN32) -# include -# define ZEXPORT __declspec(dllexport) WINAPI -# define ZEXPORTRVA __declspec(dllexport) WINAPIV -# else -# if defined (_Windows) && defined (__DLL__) -# define ZEXPORT _export -# define ZEXPORTVA _export -# endif -# endif -# endif -#endif - -#if defined (__BEOS__) -# if defined (ZLIB_DLL) -# define ZEXTERN extern __declspec(dllexport) -# else -# define ZEXTERN extern __declspec(dllimport) -# endif -#endif - -#ifndef ZEXPORT -# define ZEXPORT -#endif -#ifndef ZEXPORTVA -# define ZEXPORTVA -#endif -#ifndef ZEXTERN -# define ZEXTERN extern -#endif - -#ifndef FAR -# define FAR -#endif - -#if !defined(MACOS) && !defined(TARGET_OS_MAC) -typedef unsigned char Byte; /* 8 bits */ -#endif -typedef unsigned int uInt; /* 16 bits or more */ -typedef unsigned long uLong; /* 32 bits or more */ - -#ifdef SMALL_MEDIUM - /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ -# define Bytef Byte FAR -#else - typedef Byte FAR Bytef; -#endif -typedef char FAR charf; -typedef int FAR intf; -typedef uInt FAR uIntf; -typedef uLong FAR uLongf; - -#ifdef STDC - typedef void FAR *voidpf; - typedef void *voidp; -#else - typedef Byte FAR *voidpf; - typedef Byte *voidp; -#endif - -#ifdef HAVE_UNISTD_H -# include /* for off_t */ -# include /* for SEEK_* and off_t */ -# define z_off_t off_t -#endif -#ifndef SEEK_SET -# define SEEK_SET 0 /* Seek from beginning of file. */ -# define SEEK_CUR 1 /* Seek from current position. */ -# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ -#endif -#ifndef z_off_t -# define z_off_t long -#endif - -/* MVS linker does not support external names larger than 8 bytes */ -#if defined(__MVS__) -# pragma map(deflateInit_,"DEIN") -# pragma map(deflateInit2_,"DEIN2") -# pragma map(deflateEnd,"DEEND") -# pragma map(inflateInit_,"ININ") -# pragma map(inflateInit2_,"ININ2") -# pragma map(inflateEnd,"INEND") -# pragma map(inflateSync,"INSY") -# pragma map(inflateSetDictionary,"INSEDI") -# pragma map(inflate_blocks,"INBL") -# pragma map(inflate_blocks_new,"INBLNE") -# pragma map(inflate_blocks_free,"INBLFR") -# pragma map(inflate_blocks_reset,"INBLRE") -# pragma map(inflate_codes_free,"INCOFR") -# pragma map(inflate_codes,"INCO") -# pragma map(inflate_fast,"INFA") -# pragma map(inflate_flush,"INFLU") -# pragma map(inflate_mask,"INMA") -# pragma map(inflate_set_dictionary,"INSEDI2") -# pragma map(inflate_copyright,"INCOPY") -# pragma map(inflate_trees_bits,"INTRBI") -# pragma map(inflate_trees_dynamic,"INTRDY") -# pragma map(inflate_trees_fixed,"INTRFI") -# pragma map(inflate_trees_free,"INTRFR") -#endif - -#endif /* _ZCONF_H */ diff --git a/src/lib/ggpo/zlib.h b/src/lib/ggpo/zlib.h deleted file mode 100644 index affd260b..00000000 --- a/src/lib/ggpo/zlib.h +++ /dev/null @@ -1,893 +0,0 @@ - /* zlib.h -- interface of the 'zlib' general purpose compression library - version 1.1.4, March 11th, 2002 - - Copyright (C) 1995-2002 Jean-loup Gailly and Mark Adler - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. - - Jean-loup Gailly Mark Adler - jloup@gzip.org madler@alumni.caltech.edu - - - The data format used by the zlib library is described by RFCs (Request for - Comments) 1950 to 1952 in the files ftp://ds.internic.net/rfc/rfc1950.txt - (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format). -*/ - -#ifndef _ZLIB_H -#define _ZLIB_H - -#include "zconf.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#define ZLIB_VERSION "1.1.4" - -/* - The 'zlib' compression library provides in-memory compression and - decompression functions, including integrity checks of the uncompressed - data. This version of the library supports only one compression method - (deflation) but other algorithms will be added later and will have the same - stream interface. - - Compression can be done in a single step if the buffers are large - enough (for example if an input file is mmap'ed), or can be done by - repeated calls of the compression function. In the latter case, the - application must provide more input and/or consume the output - (providing more output space) before each call. - - The library also supports reading and writing files in gzip (.gz) format - with an interface similar to that of stdio. - - The library does not install any signal handler. The decoder checks - the consistency of the compressed data, so the library should never - crash even in case of corrupted input. -*/ - -typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size)); -typedef void (*free_func) OF((voidpf opaque, voidpf address)); - -struct internal_state; - -typedef struct z_stream_s { - Bytef *next_in; /* next input byte */ - uInt avail_in; /* number of bytes available at next_in */ - uLong total_in; /* total nb of input bytes read so far */ - - Bytef *next_out; /* next output byte should be put there */ - uInt avail_out; /* remaining free space at next_out */ - uLong total_out; /* total nb of bytes output so far */ - - char *msg; /* last error message, NULL if no error */ - struct internal_state FAR *state; /* not visible by applications */ - - alloc_func zalloc; /* used to allocate the internal state */ - free_func zfree; /* used to free the internal state */ - voidpf opaque; /* private data object passed to zalloc and zfree */ - - int data_type; /* best guess about the data type: ascii or binary */ - uLong adler; /* adler32 value of the uncompressed data */ - uLong reserved; /* reserved for future use */ -} z_stream; - -typedef z_stream FAR *z_streamp; - -/* - The application must update next_in and avail_in when avail_in has - dropped to zero. It must update next_out and avail_out when avail_out - has dropped to zero. The application must initialize zalloc, zfree and - opaque before calling the init function. All other fields are set by the - compression library and must not be updated by the application. - - The opaque value provided by the application will be passed as the first - parameter for calls of zalloc and zfree. This can be useful for custom - memory management. The compression library attaches no meaning to the - opaque value. - - zalloc must return Z_NULL if there is not enough memory for the object. - If zlib is used in a multi-threaded application, zalloc and zfree must be - thread safe. - - On 16-bit systems, the functions zalloc and zfree must be able to allocate - exactly 65536 bytes, but will not be required to allocate more than this - if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, - pointers returned by zalloc for objects of exactly 65536 bytes *must* - have their offset normalized to zero. The default allocation function - provided by this library ensures this (see zutil.c). To reduce memory - requirements and avoid any allocation of 64K objects, at the expense of - compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h). - - The fields total_in and total_out can be used for statistics or - progress reports. After compression, total_in holds the total size of - the uncompressed data and may be saved for use in the decompressor - (particularly if the decompressor wants to decompress everything in - a single step). -*/ - - /* constants */ - -#define Z_NO_FLUSH 0 -#define Z_PARTIAL_FLUSH 1 /* will be removed, use Z_SYNC_FLUSH instead */ -#define Z_SYNC_FLUSH 2 -#define Z_FULL_FLUSH 3 -#define Z_FINISH 4 -/* Allowed flush values; see deflate() below for details */ - -#define Z_OK 0 -#define Z_STREAM_END 1 -#define Z_NEED_DICT 2 -#define Z_ERRNO (-1) -#define Z_STREAM_ERROR (-2) -#define Z_DATA_ERROR (-3) -#define Z_MEM_ERROR (-4) -#define Z_BUF_ERROR (-5) -#define Z_VERSION_ERROR (-6) -/* Return codes for the compression/decompression functions. Negative - * values are errors, positive values are used for special but normal events. - */ - -#define Z_NO_COMPRESSION 0 -#define Z_BEST_SPEED 1 -#define Z_BEST_COMPRESSION 9 -#define Z_DEFAULT_COMPRESSION (-1) -/* compression levels */ - -#define Z_FILTERED 1 -#define Z_HUFFMAN_ONLY 2 -#define Z_DEFAULT_STRATEGY 0 -/* compression strategy; see deflateInit2() below for details */ - -#define Z_BINARY 0 -#define Z_ASCII 1 -#define Z_UNKNOWN 2 -/* Possible values of the data_type field */ - -#define Z_DEFLATED 8 -/* The deflate compression method (the only one supported in this version) */ - -#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */ - -#define zlib_version zlibVersion() -/* for compatibility with versions < 1.0.2 */ - - /* basic functions */ - -ZEXTERN const char * ZEXPORT zlibVersion OF((void)); -/* The application can compare zlibVersion and ZLIB_VERSION for consistency. - If the first character differs, the library code actually used is - not compatible with the zlib.h header file used by the application. - This check is automatically made by deflateInit and inflateInit. - */ - -/* -ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level)); - - Initializes the internal stream state for compression. The fields - zalloc, zfree and opaque must be initialized before by the caller. - If zalloc and zfree are set to Z_NULL, deflateInit updates them to - use default allocation functions. - - The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9: - 1 gives best speed, 9 gives best compression, 0 gives no compression at - all (the input data is simply copied a block at a time). - Z_DEFAULT_COMPRESSION requests a default compromise between speed and - compression (currently equivalent to level 6). - - deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not - enough memory, Z_STREAM_ERROR if level is not a valid compression level, - Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible - with the version assumed by the caller (ZLIB_VERSION). - msg is set to null if there is no error message. deflateInit does not - perform any compression: this will be done by deflate(). -*/ - - -ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); -/* - deflate compresses as much data as possible, and stops when the input - buffer becomes empty or the output buffer becomes full. It may introduce some - output latency (reading input without producing any output) except when - forced to flush. - - The detailed semantics are as follows. deflate performs one or both of the - following actions: - - - Compress more input starting at next_in and update next_in and avail_in - accordingly. If not all input can be processed (because there is not - enough room in the output buffer), next_in and avail_in are updated and - processing will resume at this point for the next call of deflate(). - - - Provide more output starting at next_out and update next_out and avail_out - accordingly. This action is forced if the parameter flush is non zero. - Forcing flush frequently degrades the compression ratio, so this parameter - should be set only when necessary (in interactive applications). - Some output may be provided even if flush is not set. - - Before the call of deflate(), the application should ensure that at least - one of the actions is possible, by providing more input and/or consuming - more output, and updating avail_in or avail_out accordingly; avail_out - should never be zero before the call. The application can consume the - compressed output when it wants, for example when the output buffer is full - (avail_out == 0), or after each call of deflate(). If deflate returns Z_OK - and with zero avail_out, it must be called again after making room in the - output buffer because there might be more output pending. - - If the parameter flush is set to Z_SYNC_FLUSH, all pending output is - flushed to the output buffer and the output is aligned on a byte boundary, so - that the decompressor can get all input data available so far. (In particular - avail_in is zero after the call if enough output space has been provided - before the call.) Flushing may degrade compression for some compression - algorithms and so it should be used only when necessary. - - If flush is set to Z_FULL_FLUSH, all output is flushed as with - Z_SYNC_FLUSH, and the compression state is reset so that decompression can - restart from this point if previous compressed data has been damaged or if - random access is desired. Using Z_FULL_FLUSH too often can seriously degrade - the compression. - - If deflate returns with avail_out == 0, this function must be called again - with the same value of the flush parameter and more output space (updated - avail_out), until the flush is complete (deflate returns with non-zero - avail_out). - - If the parameter flush is set to Z_FINISH, pending input is processed, - pending output is flushed and deflate returns with Z_STREAM_END if there - was enough output space; if deflate returns with Z_OK, this function must be - called again with Z_FINISH and more output space (updated avail_out) but no - more input data, until it returns with Z_STREAM_END or an error. After - deflate has returned Z_STREAM_END, the only possible operations on the - stream are deflateReset or deflateEnd. - - Z_FINISH can be used immediately after deflateInit if all the compression - is to be done in a single step. In this case, avail_out must be at least - 0.1% larger than avail_in plus 12 bytes. If deflate does not return - Z_STREAM_END, then it must be called again as described above. - - deflate() sets strm->adler to the adler32 checksum of all input read - so far (that is, total_in bytes). - - deflate() may update data_type if it can make a good guess about - the input data type (Z_ASCII or Z_BINARY). In doubt, the data is considered - binary. This field is only for information purposes and does not affect - the compression algorithm in any manner. - - deflate() returns Z_OK if some progress has been made (more input - processed or more output produced), Z_STREAM_END if all input has been - consumed and all output has been produced (only when flush is set to - Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example - if next_in or next_out was NULL), Z_BUF_ERROR if no progress is possible - (for example avail_in or avail_out was zero). -*/ - - -ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm)); -/* - All dynamically allocated data structures for this stream are freed. - This function discards any unprocessed input and does not flush any - pending output. - - deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the - stream state was inconsistent, Z_DATA_ERROR if the stream was freed - prematurely (some input or output was discarded). In the error case, - msg may be set but then points to a static string (which must not be - deallocated). -*/ - - -/* -ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm)); - - Initializes the internal stream state for decompression. The fields - next_in, avail_in, zalloc, zfree and opaque must be initialized before by - the caller. If next_in is not Z_NULL and avail_in is large enough (the exact - value depends on the compression method), inflateInit determines the - compression method from the zlib header and allocates all data structures - accordingly; otherwise the allocation will be deferred to the first call of - inflate. If zalloc and zfree are set to Z_NULL, inflateInit updates them to - use default allocation functions. - - inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough - memory, Z_VERSION_ERROR if the zlib library version is incompatible with the - version assumed by the caller. msg is set to null if there is no error - message. inflateInit does not perform any decompression apart from reading - the zlib header if present: this will be done by inflate(). (So next_in and - avail_in may be modified, but next_out and avail_out are unchanged.) -*/ - - -ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); -/* - inflate decompresses as much data as possible, and stops when the input - buffer becomes empty or the output buffer becomes full. It may some - introduce some output latency (reading input without producing any output) - except when forced to flush. - - The detailed semantics are as follows. inflate performs one or both of the - following actions: - - - Decompress more input starting at next_in and update next_in and avail_in - accordingly. If not all input can be processed (because there is not - enough room in the output buffer), next_in is updated and processing - will resume at this point for the next call of inflate(). - - - Provide more output starting at next_out and update next_out and avail_out - accordingly. inflate() provides as much output as possible, until there - is no more input data or no more space in the output buffer (see below - about the flush parameter). - - Before the call of inflate(), the application should ensure that at least - one of the actions is possible, by providing more input and/or consuming - more output, and updating the next_* and avail_* values accordingly. - The application can consume the uncompressed output when it wants, for - example when the output buffer is full (avail_out == 0), or after each - call of inflate(). If inflate returns Z_OK and with zero avail_out, it - must be called again after making room in the output buffer because there - might be more output pending. - - If the parameter flush is set to Z_SYNC_FLUSH, inflate flushes as much - output as possible to the output buffer. The flushing behavior of inflate is - not specified for values of the flush parameter other than Z_SYNC_FLUSH - and Z_FINISH, but the current implementation actually flushes as much output - as possible anyway. - - inflate() should normally be called until it returns Z_STREAM_END or an - error. However if all decompression is to be performed in a single step - (a single call of inflate), the parameter flush should be set to - Z_FINISH. In this case all pending input is processed and all pending - output is flushed; avail_out must be large enough to hold all the - uncompressed data. (The size of the uncompressed data may have been saved - by the compressor for this purpose.) The next operation on this stream must - be inflateEnd to deallocate the decompression state. The use of Z_FINISH - is never required, but can be used to inform inflate that a faster routine - may be used for the single inflate() call. - - If a preset dictionary is needed at this point (see inflateSetDictionary - below), inflate sets strm-adler to the adler32 checksum of the - dictionary chosen by the compressor and returns Z_NEED_DICT; otherwise - it sets strm->adler to the adler32 checksum of all output produced - so far (that is, total_out bytes) and returns Z_OK, Z_STREAM_END or - an error code as described below. At the end of the stream, inflate() - checks that its computed adler32 checksum is equal to that saved by the - compressor and returns Z_STREAM_END only if the checksum is correct. - - inflate() returns Z_OK if some progress has been made (more input processed - or more output produced), Z_STREAM_END if the end of the compressed data has - been reached and all uncompressed output has been produced, Z_NEED_DICT if a - preset dictionary is needed at this point, Z_DATA_ERROR if the input data was - corrupted (input stream not conforming to the zlib format or incorrect - adler32 checksum), Z_STREAM_ERROR if the stream structure was inconsistent - (for example if next_in or next_out was NULL), Z_MEM_ERROR if there was not - enough memory, Z_BUF_ERROR if no progress is possible or if there was not - enough room in the output buffer when Z_FINISH is used. In the Z_DATA_ERROR - case, the application may then call inflateSync to look for a good - compression block. -*/ - - -ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm)); -/* - All dynamically allocated data structures for this stream are freed. - This function discards any unprocessed input and does not flush any - pending output. - - inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state - was inconsistent. In the error case, msg may be set but then points to a - static string (which must not be deallocated). -*/ - - /* Advanced functions */ - -/* - The following functions are needed only in some special applications. -*/ - -/* -ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm, - int level, - int method, - int windowBits, - int memLevel, - int strategy)); - - This is another version of deflateInit with more compression options. The - fields next_in, zalloc, zfree and opaque must be initialized before by - the caller. - - The method parameter is the compression method. It must be Z_DEFLATED in - this version of the library. - - The windowBits parameter is the base two logarithm of the window size - (the size of the history buffer). It should be in the range 8..15 for this - version of the library. Larger values of this parameter result in better - compression at the expense of memory usage. The default value is 15 if - deflateInit is used instead. - - The memLevel parameter specifies how much memory should be allocated - for the internal compression state. memLevel=1 uses minimum memory but - is slow and reduces compression ratio; memLevel=9 uses maximum memory - for optimal speed. The default value is 8. See zconf.h for total memory - usage as a function of windowBits and memLevel. - - The strategy parameter is used to tune the compression algorithm. Use the - value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a - filter (or predictor), or Z_HUFFMAN_ONLY to force Huffman encoding only (no - string match). Filtered data consists mostly of small values with a - somewhat random distribution. In this case, the compression algorithm is - tuned to compress them better. The effect of Z_FILTERED is to force more - Huffman coding and less string matching; it is somewhat intermediate - between Z_DEFAULT and Z_HUFFMAN_ONLY. The strategy parameter only affects - the compression ratio but not the correctness of the compressed output even - if it is not set appropriately. - - deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough - memory, Z_STREAM_ERROR if a parameter is invalid (such as an invalid - method). msg is set to null if there is no error message. deflateInit2 does - not perform any compression: this will be done by deflate(). -*/ - -ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, - const Bytef *dictionary, - uInt dictLength)); -/* - Initializes the compression dictionary from the given byte sequence - without producing any compressed output. This function must be called - immediately after deflateInit, deflateInit2 or deflateReset, before any - call of deflate. The compressor and decompressor must use exactly the same - dictionary (see inflateSetDictionary). - - The dictionary should consist of strings (byte sequences) that are likely - to be encountered later in the data to be compressed, with the most commonly - used strings preferably put towards the end of the dictionary. Using a - dictionary is most useful when the data to be compressed is short and can be - predicted with good accuracy; the data can then be compressed better than - with the default empty dictionary. - - Depending on the size of the compression data structures selected by - deflateInit or deflateInit2, a part of the dictionary may in effect be - discarded, for example if the dictionary is larger than the window size in - deflate or deflate2. Thus the strings most likely to be useful should be - put at the end of the dictionary, not at the front. - - Upon return of this function, strm->adler is set to the Adler32 value - of the dictionary; the decompressor may later use this value to determine - which dictionary has been used by the compressor. (The Adler32 value - applies to the whole dictionary even if only a subset of the dictionary is - actually used by the compressor.) - - deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a - parameter is invalid (such as NULL dictionary) or the stream state is - inconsistent (for example if deflate has already been called for this stream - or if the compression method is bsort). deflateSetDictionary does not - perform any compression: this will be done by deflate(). -*/ - -ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest, - z_streamp source)); -/* - Sets the destination stream as a complete copy of the source stream. - - This function can be useful when several compression strategies will be - tried, for example when there are several ways of pre-processing the input - data with a filter. The streams that will be discarded should then be freed - by calling deflateEnd. Note that deflateCopy duplicates the internal - compression state which can be quite large, so this strategy is slow and - can consume lots of memory. - - deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not - enough memory, Z_STREAM_ERROR if the source stream state was inconsistent - (such as zalloc being NULL). msg is left unchanged in both source and - destination. -*/ - -ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm)); -/* - This function is equivalent to deflateEnd followed by deflateInit, - but does not free and reallocate all the internal compression state. - The stream will keep the same compression level and any other attributes - that may have been set by deflateInit2. - - deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent (such as zalloc or state being NULL). -*/ - -ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm, - int level, - int strategy)); -/* - Dynamically update the compression level and compression strategy. The - interpretation of level and strategy is as in deflateInit2. This can be - used to switch between compression and straight copy of the input data, or - to switch to a different kind of input data requiring a different - strategy. If the compression level is changed, the input available so far - is compressed with the old level (and may be flushed); the new level will - take effect only at the next call of deflate(). - - Before the call of deflateParams, the stream state must be set as for - a call of deflate(), since the currently available input may have to - be compressed and flushed. In particular, strm->avail_out must be non-zero. - - deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source - stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR - if strm->avail_out was zero. -*/ - -/* -ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm, - int windowBits)); - - This is another version of inflateInit with an extra parameter. The - fields next_in, avail_in, zalloc, zfree and opaque must be initialized - before by the caller. - - The windowBits parameter is the base two logarithm of the maximum window - size (the size of the history buffer). It should be in the range 8..15 for - this version of the library. The default value is 15 if inflateInit is used - instead. If a compressed stream with a larger window size is given as - input, inflate() will return with the error code Z_DATA_ERROR instead of - trying to allocate a larger window. - - inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough - memory, Z_STREAM_ERROR if a parameter is invalid (such as a negative - memLevel). msg is set to null if there is no error message. inflateInit2 - does not perform any decompression apart from reading the zlib header if - present: this will be done by inflate(). (So next_in and avail_in may be - modified, but next_out and avail_out are unchanged.) -*/ - -ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, - const Bytef *dictionary, - uInt dictLength)); -/* - Initializes the decompression dictionary from the given uncompressed byte - sequence. This function must be called immediately after a call of inflate - if this call returned Z_NEED_DICT. The dictionary chosen by the compressor - can be determined from the Adler32 value returned by this call of - inflate. The compressor and decompressor must use exactly the same - dictionary (see deflateSetDictionary). - - inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a - parameter is invalid (such as NULL dictionary) or the stream state is - inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the - expected one (incorrect Adler32 value). inflateSetDictionary does not - perform any decompression: this will be done by subsequent calls of - inflate(). -*/ - -ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm)); -/* - Skips invalid compressed data until a full flush point (see above the - description of deflate with Z_FULL_FLUSH) can be found, or until all - available input is skipped. No output is provided. - - inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR - if no more input was provided, Z_DATA_ERROR if no flush point has been found, - or Z_STREAM_ERROR if the stream structure was inconsistent. In the success - case, the application may save the current current value of total_in which - indicates where valid compressed data was found. In the error case, the - application may repeatedly call inflateSync, providing more input each time, - until success or end of the input data. -*/ - -ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm)); -/* - This function is equivalent to inflateEnd followed by inflateInit, - but does not free and reallocate all the internal decompression state. - The stream will keep attributes that may have been set by inflateInit2. - - inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent (such as zalloc or state being NULL). -*/ - - - /* utility functions */ - -/* - The following utility functions are implemented on top of the - basic stream-oriented functions. To simplify the interface, some - default options are assumed (compression level and memory usage, - standard memory allocation functions). The source code of these - utility functions can easily be modified if you need special options. -*/ - -ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen, - const Bytef *source, uLong sourceLen)); -/* - Compresses the source buffer into the destination buffer. sourceLen is - the byte length of the source buffer. Upon entry, destLen is the total - size of the destination buffer, which must be at least 0.1% larger than - sourceLen plus 12 bytes. Upon exit, destLen is the actual size of the - compressed buffer. - This function can be used to compress a whole file at once if the - input file is mmap'ed. - compress returns Z_OK if success, Z_MEM_ERROR if there was not - enough memory, Z_BUF_ERROR if there was not enough room in the output - buffer. -*/ - -ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen, - const Bytef *source, uLong sourceLen, - int level)); -/* - Compresses the source buffer into the destination buffer. The level - parameter has the same meaning as in deflateInit. sourceLen is the byte - length of the source buffer. Upon entry, destLen is the total size of the - destination buffer, which must be at least 0.1% larger than sourceLen plus - 12 bytes. Upon exit, destLen is the actual size of the compressed buffer. - - compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough - memory, Z_BUF_ERROR if there was not enough room in the output buffer, - Z_STREAM_ERROR if the level parameter is invalid. -*/ - -ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, - const Bytef *source, uLong sourceLen)); -/* - Decompresses the source buffer into the destination buffer. sourceLen is - the byte length of the source buffer. Upon entry, destLen is the total - size of the destination buffer, which must be large enough to hold the - entire uncompressed data. (The size of the uncompressed data must have - been saved previously by the compressor and transmitted to the decompressor - by some mechanism outside the scope of this compression library.) - Upon exit, destLen is the actual size of the compressed buffer. - This function can be used to decompress a whole file at once if the - input file is mmap'ed. - - uncompress returns Z_OK if success, Z_MEM_ERROR if there was not - enough memory, Z_BUF_ERROR if there was not enough room in the output - buffer, or Z_DATA_ERROR if the input data was corrupted. -*/ - - -typedef voidp gzFile; - -ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode)); -/* - Opens a gzip (.gz) file for reading or writing. The mode parameter - is as in fopen ("rb" or "wb") but can also include a compression level - ("wb9") or a strategy: 'f' for filtered data as in "wb6f", 'h' for - Huffman only compression as in "wb1h". (See the description - of deflateInit2 for more information about the strategy parameter.) - - gzopen can be used to read a file which is not in gzip format; in this - case gzread will directly read from the file without decompression. - - gzopen returns NULL if the file could not be opened or if there was - insufficient memory to allocate the (de)compression state; errno - can be checked to distinguish the two cases (if errno is zero, the - zlib error is Z_MEM_ERROR). */ - -ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode)); -/* - gzdopen() associates a gzFile with the file descriptor fd. File - descriptors are obtained from calls like open, dup, creat, pipe or - fileno (in the file has been previously opened with fopen). - The mode parameter is as in gzopen. - The next call of gzclose on the returned gzFile will also close the - file descriptor fd, just like fclose(fdopen(fd), mode) closes the file - descriptor fd. If you want to keep fd open, use gzdopen(dup(fd), mode). - gzdopen returns NULL if there was insufficient memory to allocate - the (de)compression state. -*/ - -ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy)); -/* - Dynamically update the compression level or strategy. See the description - of deflateInit2 for the meaning of these parameters. - gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not - opened for writing. -*/ - -ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len)); -/* - Reads the given number of uncompressed bytes from the compressed file. - If the input file was not in gzip format, gzread copies the given number - of bytes into the buffer. - gzread returns the number of uncompressed bytes actually read (0 for - end of file, -1 for error). */ - -ZEXTERN int ZEXPORT gzwrite OF((gzFile file, - const voidp buf, unsigned len)); -/* - Writes the given number of uncompressed bytes into the compressed file. - gzwrite returns the number of uncompressed bytes actually written - (0 in case of error). -*/ - -ZEXTERN int ZEXPORTVA gzprintf OF((gzFile file, const char *format, ...)); -/* - Converts, formats, and writes the args to the compressed file under - control of the format string, as in fprintf. gzprintf returns the number of - uncompressed bytes actually written (0 in case of error). -*/ - -ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s)); -/* - Writes the given null-terminated string to the compressed file, excluding - the terminating null character. - gzputs returns the number of characters written, or -1 in case of error. -*/ - -ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len)); -/* - Reads bytes from the compressed file until len-1 characters are read, or - a newline character is read and transferred to buf, or an end-of-file - condition is encountered. The string is then terminated with a null - character. - gzgets returns buf, or Z_NULL in case of error. -*/ - -ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c)); -/* - Writes c, converted to an unsigned char, into the compressed file. - gzputc returns the value that was written, or -1 in case of error. -*/ - -ZEXTERN int ZEXPORT gzgetc OF((gzFile file)); -/* - Reads one byte from the compressed file. gzgetc returns this byte - or -1 in case of end of file or error. -*/ - -ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush)); -/* - Flushes all pending output into the compressed file. The parameter - flush is as in the deflate() function. The return value is the zlib - error number (see function gzerror below). gzflush returns Z_OK if - the flush parameter is Z_FINISH and all output could be flushed. - gzflush should be called only when strictly necessary because it can - degrade compression. -*/ - -ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file, - z_off_t offset, int whence)); -/* - Sets the starting position for the next gzread or gzwrite on the - given compressed file. The offset represents a number of bytes in the - uncompressed data stream. The whence parameter is defined as in lseek(2); - the value SEEK_END is not supported. - If the file is opened for reading, this function is emulated but can be - extremely slow. If the file is opened for writing, only forward seeks are - supported; gzseek then compresses a sequence of zeroes up to the new - starting position. - - gzseek returns the resulting offset location as measured in bytes from - the beginning of the uncompressed stream, or -1 in case of error, in - particular if the file is opened for writing and the new starting position - would be before the current position. -*/ - -ZEXTERN int ZEXPORT gzrewind OF((gzFile file)); -/* - Rewinds the given file. This function is supported only for reading. - - gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET) -*/ - -ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file)); -/* - Returns the starting position for the next gzread or gzwrite on the - given compressed file. This position represents a number of bytes in the - uncompressed data stream. - - gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR) -*/ - -ZEXTERN int ZEXPORT gzeof OF((gzFile file)); -/* - Returns 1 when EOF has previously been detected reading the given - input stream, otherwise zero. -*/ - -ZEXTERN int ZEXPORT gzclose OF((gzFile file)); -/* - Flushes all pending output if necessary, closes the compressed file - and deallocates all the (de)compression state. The return value is the zlib - error number (see function gzerror below). -*/ - -ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum)); -/* - Returns the error message for the last error which occurred on the - given compressed file. errnum is set to zlib error number. If an - error occurred in the file system and not in the compression library, - errnum is set to Z_ERRNO and the application may consult errno - to get the exact error code. -*/ - - /* checksum functions */ - -/* - These functions are not related to compression but are exported - anyway because they might be useful in applications using the - compression library. -*/ - -ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len)); - -/* - Update a running Adler-32 checksum with the bytes buf[0..len-1] and - return the updated checksum. If buf is NULL, this function returns - the required initial value for the checksum. - An Adler-32 checksum is almost as reliable as a CRC32 but can be computed - much faster. Usage example: - - uLong adler = adler32(0L, Z_NULL, 0); - - while (read_buffer(buffer, length) != EOF) { - adler = adler32(adler, buffer, length); - } - if (adler != original_adler) error(); -*/ - -ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len)); -/* - Update a running crc with the bytes buf[0..len-1] and return the updated - crc. If buf is NULL, this function returns the required initial value - for the crc. Pre- and post-conditioning (one's complement) is performed - within this function so it shouldn't be done by the application. - Usage example: - - uLong crc = crc32(0L, Z_NULL, 0); - - while (read_buffer(buffer, length) != EOF) { - crc = crc32(crc, buffer, length); - } - if (crc != original_crc) error(); -*/ - - - /* various hacks, don't look :) */ - -/* deflateInit and inflateInit are macros to allow checking the zlib version - * and the compiler's view of z_stream: - */ -ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level, - const char *version, int stream_size)); -ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm, - const char *version, int stream_size)); -ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int level, int method, - int windowBits, int memLevel, - int strategy, const char *version, - int stream_size)); -ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits, - const char *version, int stream_size)); -#define deflateInit(strm, level) \ - deflateInit_((strm), (level), ZLIB_VERSION, sizeof(z_stream)) -#define inflateInit(strm) \ - inflateInit_((strm), ZLIB_VERSION, sizeof(z_stream)) -#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ - deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ - (strategy), ZLIB_VERSION, sizeof(z_stream)) -#define inflateInit2(strm, windowBits) \ - inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream)) - - -#if !defined(_Z_UTIL_H) && !defined(NO_DUMMY_DECL) - struct internal_state {int dummy;}; /* hack for buggy compilers */ -#endif - -ZEXTERN const char * ZEXPORT zError OF((int err)); -ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp z)); -ZEXTERN const uLongf * ZEXPORT get_crc_table OF((void)); - -#ifdef __cplusplus -} -#endif - -#endif /* _ZLIB_H */ From 09dc194fae3c40f57015b70efed088dce8b8c0ce Mon Sep 17 00:00:00 2001 From: thd79 Date: Thu, 9 May 2024 16:31:32 +0100 Subject: [PATCH 34/40] what is iths --- src/GGPO-x.dir/Debug-LLVM/GGPO-x.lib.recipe | 7 + src/GGPO-x.vcxproj | 139 ++++++++++++++++++++ src/lib/ggpo/backends/p2p.cpp | 2 +- src/lib/ggpo/backends/spectator.cpp | 2 +- src/lib/ggpo/network/udp.cpp | 5 +- src/lib/ggpo/network/udp.h | 5 +- src/lib/ggpo/network/udp_proto.cpp | 37 +----- src/lib/ggpo/network/udp_proto.h | 2 +- src/lib/ggpo/poll.cpp | 57 +------- src/lib/ggpo/poll.h | 31 +---- 10 files changed, 169 insertions(+), 118 deletions(-) create mode 100644 src/GGPO-x.dir/Debug-LLVM/GGPO-x.lib.recipe diff --git a/src/GGPO-x.dir/Debug-LLVM/GGPO-x.lib.recipe b/src/GGPO-x.dir/Debug-LLVM/GGPO-x.lib.recipe new file mode 100644 index 00000000..a53f9611 --- /dev/null +++ b/src/GGPO-x.dir/Debug-LLVM/GGPO-x.lib.recipe @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/src/GGPO-x.vcxproj b/src/GGPO-x.vcxproj index a874544f..911a48e9 100644 --- a/src/GGPO-x.vcxproj +++ b/src/GGPO-x.vcxproj @@ -4,6 +4,14 @@ x64 + + Debug-LLVM + Win32 + + + Debug-LLVM + x64 + Debug Win32 @@ -58,6 +66,11 @@ MultiByte ClangCL + + StaticLibrary + MultiByte + ClangCL + StaticLibrary MultiByte @@ -68,6 +81,11 @@ MultiByte ClangCL + + StaticLibrary + MultiByte + ClangCL + @@ -90,26 +108,37 @@ true $(ProjectDir)..\lib\$(Platform)\$(Configuration) $(ProjectDir)..\lib\$(Platform)\$(Configuration) + $(ProjectDir)..\lib\$(Platform)\$(Configuration) $(ProjectDir)..\lib\$(Platform)\$(Configuration) $(ProjectDir)..\lib\$(Platform)\$(Configuration) + $(ProjectDir)..\lib\$(Platform)\$(Configuration) GGPO-x.dir\$(Configuration)\ GGPO-x.dir\$(Configuration)\ + GGPO-x.dir\$(Configuration)\ GGPO-x GGPO-x + GGPO-x GGPO-x GGPO-x + GGPO-x .lib .lib + .lib .lib .lib + .lib false false + false false false + false true true + true true true + true @@ -319,6 +348,60 @@ false + + + $(ProjectDir)include;$(ProjectDir)lib\ggpo;%(AdditionalIncludeDirectories) + %(AdditionalOptions) /bigobj + $(IntDir) + false + ProgramDatabase + 4577;4530 + Sync + true + AnySuitable + true + true + MaxSpeed + NotUsing + MultiThreaded + true + true + true + false + Level4 + true + WIN32;_WINDOWS;NDEBUG;GGPO_SHARED_LIB;GGPO_SDK_EXPORT;CMAKE_INTDIR="Release";GGPO_EXPORTS;%(PreprocessorDefinitions) + $(IntDir) + stdcpp17 + + + WIN32;_WINDOWS;NDEBUG;GGPO_SHARED_LIB;GGPO_SDK_EXPORT;CMAKE_INTDIR=\"Release\";GGPO_EXPORTS;%(PreprocessorDefinitions) + $(ProjectDir)include;$(ProjectDir)lib\ggpo-x;%(AdditionalIncludeDirectories) + + + $(ProjectDir)include;$(ProjectDir)lib\ggpo-x;%(AdditionalIncludeDirectories) + $(ProjectDir)/$(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + winmm.lib;ws2_32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;comdlg32.lib;advapi32.lib + %(AdditionalLibraryDirectories) + %(AdditionalOptions) /machine:x64 + true + %(IgnoreSpecificDefaultLibraries) + $(ProjectDir)$(Platform)\$(Configuration)\GGPO-x.lib + UseLinkTimeCodeGeneration + true + $(ProjectDir)$(Platform)\$(Configuration)\GGPO-x.pdb + Console + + + false + + $(ProjectDir)include;$(ProjectDir)lib\ggpo;%(AdditionalIncludeDirectories) @@ -431,6 +514,62 @@ MachineX86 + + + $(ProjectDir)include;$(ProjectDir)lib\ggpo;%(AdditionalIncludeDirectories) + %(AdditionalOptions) /bigobj + $(IntDir) + false + ProgramDatabase + 4577;4530 + Sync + true + AnySuitable + true + true + MaxSpeed + NotUsing + MultiThreaded + true + true + true + false + Level4 + true + WIN32;_WINDOWS;NDEBUG;GGPO_SHARED_LIB;GGPO_SDK_EXPORT;CMAKE_INTDIR="Release";GGPO_EXPORTS;%(PreprocessorDefinitions) + $(IntDir) + + + WIN32;_WINDOWS;NDEBUG;GGPO_SHARED_LIB;GGPO_SDK_EXPORT;CMAKE_INTDIR=\"Release\";GGPO_EXPORTS;%(PreprocessorDefinitions) + $(ProjectDir)include;$(ProjectDir)lib\ggpo-x;%(AdditionalIncludeDirectories) + + + $(ProjectDir)include;$(ProjectDir)lib\ggpo-x;%(AdditionalIncludeDirectories) + $(ProjectDir)/$(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + winmm.lib;ws2_32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;comdlg32.lib;advapi32.lib + %(AdditionalLibraryDirectories) + %(AdditionalOptions) /machine:x64 + true + %(IgnoreSpecificDefaultLibraries) + $(ProjectDir)$(Platform)\$(Configuration)\GGPO-x.lib + UseLinkTimeCodeGeneration + true + $(ProjectDir)$(Platform)\$(Configuration)\GGPO-x.pdb + Console + + + false + + + MachineX86 + + diff --git a/src/lib/ggpo/backends/p2p.cpp b/src/lib/ggpo/backends/p2p.cpp index a1e9023a..9cfd5971 100644 --- a/src/lib/ggpo/backends/p2p.cpp +++ b/src/lib/ggpo/backends/p2p.cpp @@ -170,7 +170,7 @@ Peer2PeerBackend::DoPoll() } if (!_sync.InRollback()) { - _poll.Pump(0); + _poll.Pump(); PollUdpProtocolEvents(); CheckDesync(); diff --git a/src/lib/ggpo/backends/spectator.cpp b/src/lib/ggpo/backends/spectator.cpp index 7026d64a..e376271d 100644 --- a/src/lib/ggpo/backends/spectator.cpp +++ b/src/lib/ggpo/backends/spectator.cpp @@ -49,7 +49,7 @@ SpectatorBackend::~SpectatorBackend() GGPOErrorCode SpectatorBackend::DoPoll() { - _poll.Pump(0); + _poll.Pump(); PollUdpProtocolEvents(); return GGPO_OK; diff --git a/src/lib/ggpo/network/udp.cpp b/src/lib/ggpo/network/udp.cpp index 1e02da70..698e21d5 100644 --- a/src/lib/ggpo/network/udp.cpp +++ b/src/lib/ggpo/network/udp.cpp @@ -56,8 +56,7 @@ Udp::Init(uint16 port, Poll *poll, Callbacks *callbacks) { _callbacks = callbacks; - _poll = poll; - _poll->RegisterLoop(this); + poll->RegisterLoop(this); Log("binding udp socket to port %d.\n", port); _socket = CreateSocket(port, 0); @@ -79,7 +78,7 @@ Udp::SendTo(char *buffer, int len, int flags, struct sockaddr *dst, int destlen) } bool -Udp::OnLoopPoll(void *) +Udp::OnLoopPoll() { uint8 recv_buf[MAX_UDP_PACKET_SIZE]; sockaddr_in recv_addr; diff --git a/src/lib/ggpo/network/udp.h b/src/lib/ggpo/network/udp.h index fb14a29d..0a859f49 100644 --- a/src/lib/ggpo/network/udp.h +++ b/src/lib/ggpo/network/udp.h @@ -41,7 +41,7 @@ class Udp : public IPollSink void SendTo(char *buffer, int len, int flags, struct sockaddr *dst, int destlen); - bool OnLoopPoll(void *cookie) override; + bool OnLoopPoll() override; public: ~Udp(void); @@ -52,9 +52,6 @@ class Udp : public IPollSink // state management Callbacks *_callbacks; - Poll *_poll; - - }; #endif diff --git a/src/lib/ggpo/network/udp_proto.cpp b/src/lib/ggpo/network/udp_proto.cpp index e89069c7..983b137d 100644 --- a/src/lib/ggpo/network/udp_proto.cpp +++ b/src/lib/ggpo/network/udp_proto.cpp @@ -197,7 +197,7 @@ void UdpProtocol::SendChat(const char* message) } bool -UdpProtocol::OnLoopPoll(void *) +UdpProtocol::OnLoopPoll() { if (!_udp) { return true; @@ -763,38 +763,15 @@ UdpProtocol::PumpSendQueue() while (!_send_queue.empty()) { QueueEntry &entry = _send_queue.front(); - if (_send_latency) { - // should really come up with a gaussian distributation based on the configured - // value, but this will do for now. - int jitter = (_send_latency * 2 / 3) + ((rand() % _send_latency) / 3); - if ((int)Platform::GetCurrentTimeMS() < _send_queue.front().queue_time + jitter) { - break; - } - } - if (_oop_percent && !_oo_packet.msg && ((rand() % 100) < _oop_percent)) { - int delay = rand() % (_send_latency * 10 + 1000); - Log("creating rogue oop (seq: %d delay: %d)\n", entry.msg->hdr.sequence_number, delay); - _oo_packet.send_time = Platform::GetCurrentTimeMS() + delay; - _oo_packet.msg = entry.msg; - _oo_packet.dest_addr = entry.dest_addr; - } else { - ASSERT(entry.dest_addr.sin_addr.s_addr); - - _udp->SendTo((char *)entry.msg, entry.msg->PacketSize(), 0, - (struct sockaddr *)&entry.dest_addr, sizeof entry.dest_addr); + + ASSERT(entry.dest_addr.sin_addr.s_addr); - delete entry.msg; - } + _udp->SendTo((char *)entry.msg, entry.msg->PacketSize(), 0, + (struct sockaddr *)&entry.dest_addr, sizeof entry.dest_addr); + delete entry.msg; + _send_queue.pop(); } - if (_oo_packet.msg && _oo_packet.send_time < (int)Platform::GetCurrentTimeMS()) { - Log("sending rogue oop!"); - _udp->SendTo((char *)_oo_packet.msg, _oo_packet.msg->PacketSize(), 0, - (struct sockaddr *)&_oo_packet.dest_addr, sizeof _oo_packet.dest_addr); - - delete _oo_packet.msg; - _oo_packet.msg = NULL; - } } void diff --git a/src/lib/ggpo/network/udp_proto.h b/src/lib/ggpo/network/udp_proto.h index 9828906b..e2c60ffd 100644 --- a/src/lib/ggpo/network/udp_proto.h +++ b/src/lib/ggpo/network/udp_proto.h @@ -62,7 +62,7 @@ class UdpProtocol : public IPollSink }; public: - virtual bool OnLoopPoll(void *cookie); + virtual bool OnLoopPoll() override; public: UdpProtocol(); diff --git a/src/lib/ggpo/poll.cpp b/src/lib/ggpo/poll.cpp index 3c8499ac..ae575c42 100644 --- a/src/lib/ggpo/poll.cpp +++ b/src/lib/ggpo/poll.cpp @@ -8,65 +8,20 @@ #include "types.h" #include "poll.h" -Poll::Poll(void) : - _start_time(0) -{ -} - -// -//void -//Poll::RegisterMsgLoop(IPollSink *sink, void *cookie) -//{ -// _msg_sinks.push_back(PollSinkCb(sink, cookie)); -//} - -void -Poll::RegisterLoop(IPollSink *sink, void *cookie) +void Poll::RegisterLoop(IPollSink *sink) { - _loop_sinks.push_back(PollSinkCb(sink, cookie)); + _loop_sinks.push_back(sink); } -//void -//Poll::RegisterPeriodic(IPollSink *sink, int interval, void *cookie) -//{ -// _periodic_sinks.push_back(PollPeriodicSinkCb(sink, cookie, interval)); -//} -void -Poll::Run() -{ - while (Pump(100)) { - continue; - } -} - -bool -Poll::Pump(int ) +bool Poll::Pump() { int i; bool finished = false; for (i = 0; i < _loop_sinks.size(); i++) { - PollSinkCb &cb = _loop_sinks[i]; - finished = !cb.sink->OnLoopPoll(cb.cookie) || finished; + auto *sink = _loop_sinks[i]; + finished = !sink->OnLoopPoll() || finished; } return finished; -} -// -//int -//Poll::ComputeWaitTime(int elapsed) -//{ -// int waitTime = INFINITE; -// size_t count = _periodic_sinks.size(); -// -// if (count > 0) { -// for (int i = 0; i < count; i++) { -// PollPeriodicSinkCb &cb = _periodic_sinks[i]; -// int timeout = (cb.interval + cb.last_fired) - elapsed; -// if (waitTime == INFINITE || (timeout < waitTime)) { -// waitTime = MAX(timeout, 0); -// } -// } -// } -// return waitTime; -//} +} \ No newline at end of file diff --git a/src/lib/ggpo/poll.h b/src/lib/ggpo/poll.h index 597cf58b..83dadf6f 100644 --- a/src/lib/ggpo/poll.h +++ b/src/lib/ggpo/poll.h @@ -18,39 +18,16 @@ class IPollSink { virtual ~IPollSink() { } //virtual bool OnMsgPoll(void*) = 0;//{ return true; } // virtual bool OnPeriodicPoll(void*, int) = 0;// { return true; } - virtual bool OnLoopPoll(void*) = 0;// { return true; } + virtual bool OnLoopPoll() = 0;// { return true; } }; class Poll { public: - Poll(void); - void RegisterLoop(IPollSink *sink, void *cookie = NULL); - - void Run(); - bool Pump(int timeout); + void RegisterLoop(IPollSink *sink); + bool Pump(); protected: - //int ComputeWaitTime(int elapsed); - - struct PollSinkCb { - IPollSink *sink; - void *cookie; - PollSinkCb() : sink(NULL), cookie(NULL) { } - PollSinkCb(IPollSink *s, void *c) : sink(s), cookie(c) { } - }; - - struct PollPeriodicSinkCb : public PollSinkCb { - int interval; - int last_fired; - PollPeriodicSinkCb() : PollSinkCb(NULL, NULL), interval(0), last_fired(0) { } - PollPeriodicSinkCb(IPollSink *s, void *c, int i) : - PollSinkCb(s, c), interval(i), last_fired(0) { } - }; - - int _start_time; - // StaticBuffer _msg_sinks; - StaticBuffer _loop_sinks; - // StaticBuffer _periodic_sinks; + StaticBuffer _loop_sinks; }; #endif From 78f212fbc2d81fb00dd785092d5f3f770400d40b Mon Sep 17 00:00:00 2001 From: thd79 Date: Tue, 11 Jun 2024 12:52:38 +0100 Subject: [PATCH 35/40] add detail to assert display --- src/apps/vectorwar/VectorWar.vcxproj | 2 +- src/lib/ggpo/network/udp.cpp | 5 +++-- src/lib/ggpo/poll.h | 5 +---- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/src/apps/vectorwar/VectorWar.vcxproj b/src/apps/vectorwar/VectorWar.vcxproj index 375ec3bb..9e289c78 100644 --- a/src/apps/vectorwar/VectorWar.vcxproj +++ b/src/apps/vectorwar/VectorWar.vcxproj @@ -134,7 +134,7 @@ true Disabled NotUsing - MultiThreadedDebugDLL + MultiThreadedDebug true true true diff --git a/src/lib/ggpo/network/udp.cpp b/src/lib/ggpo/network/udp.cpp index 698e21d5..8582705f 100644 --- a/src/lib/ggpo/network/udp.cpp +++ b/src/lib/ggpo/network/udp.cpp @@ -7,7 +7,7 @@ #include "types.h" #include "udp.h" - +#include SOCKET CreateSocket(uint16 bind_port, int retries) { @@ -70,8 +70,9 @@ Udp::SendTo(char *buffer, int len, int flags, struct sockaddr *dst, int destlen) int res = sendto(_socket, buffer, len, flags, dst, destlen); if (res == SOCKET_ERROR) { DWORD err = WSAGetLastError(); + std::string errorMessage = "unknown error in sendto (erro :" + std::to_string(res) +" wsaerr: " + std::to_string(err) + ").\n"; Log("unknown error in sendto (erro: %d wsaerr: %d).\n", res, err); - ASSERT(FALSE && "Unknown error in sendto"); + ASSERT(FALSE && errorMessage.c_str()); } char dst_ip[1024]; Log("sent packet length %d to %s:%d (ret:%d).\n", len, inet_ntop(AF_INET, (void *)&to->sin_addr, dst_ip, ARRAY_SIZE(dst_ip)), ntohs(to->sin_port), res); diff --git a/src/lib/ggpo/poll.h b/src/lib/ggpo/poll.h index 83dadf6f..03cb91e3 100644 --- a/src/lib/ggpo/poll.h +++ b/src/lib/ggpo/poll.h @@ -10,15 +10,12 @@ #include "static_buffer.h" -#define MAX_POLLABLE_HANDLES 64 class IPollSink { public: virtual ~IPollSink() { } - //virtual bool OnMsgPoll(void*) = 0;//{ return true; } - // virtual bool OnPeriodicPoll(void*, int) = 0;// { return true; } - virtual bool OnLoopPoll() = 0;// { return true; } + virtual bool OnLoopPoll() = 0; }; class Poll { From d951bcfd9cfadab3e1cfd0035ea2a2014e30e454 Mon Sep 17 00:00:00 2001 From: thd79 Date: Fri, 21 Jun 2024 13:19:14 +0100 Subject: [PATCH 36/40] change to allow compilation for XP --- src/include/ggponet.h | 16 ++++++++-------- src/lib/ggpo/backends/p2p.cpp | 2 +- src/lib/ggpo/backends/synctest.cpp | 2 +- src/lib/ggpo/network/udp.cpp | 2 +- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/include/ggponet.h b/src/include/ggponet.h index 3d7deccc..26af1914 100644 --- a/src/include/ggponet.h +++ b/src/include/ggponet.h @@ -212,7 +212,7 @@ typedef struct { * begin_game callback - This callback has been deprecated. You must * implement it, but should ignore the 'game' parameter. */ - bool (__cdecl *begin_game)(void* context, const char *game); + bool (__cdecl *begin_game)(void* context, const char *game) = nullptr; /* * save_game_state - The client should allocate a buffer, copy the @@ -220,7 +220,7 @@ typedef struct { * length into the *len parameter. Optionally, the client can compute * a checksum of the data and store it in the *checksum argument. */ - bool (__cdecl *save_game_state)(void* context, unsigned char **buffer, int *len, int *checksum, int frame); + bool (__cdecl *save_game_state)(void* context, unsigned char **buffer, int *len, int *checksum, int frame) = nullptr; /* * load_game_state - GGPO.net will call this function at the beginning @@ -229,20 +229,20 @@ typedef struct { * should make the current game state match the state contained in the * buffer. */ - bool (__cdecl *load_game_state)(void* context, unsigned char *buffer, int len, int framesToRollback); + bool (__cdecl *load_game_state)(void* context, unsigned char *buffer, int len, int framesToRollback) = nullptr; /* * log_game_state - Used in diagnostic testing. The client should use * the ggpo_log function to write the contents of the specified save * state in a human readible form. */ - bool (__cdecl *log_game_state)(void* context, char *filename, unsigned char *buffer, int len); + bool (__cdecl *log_game_state)(void* context, char *filename, unsigned char *buffer, int len) = nullptr; /* * free_buffer - Frees a game state allocated in save_game_state. You * should deallocate the memory contained in the buffer. */ - void (__cdecl *free_buffer)(void* context, void *buffer); + void (__cdecl *free_buffer)(void* context, void *buffer) = nullptr; /* * advance_frame - Called during a rollback. You should advance your game @@ -253,18 +253,18 @@ typedef struct { * * The flags parameter is reserved. It can safely be ignored at this time. */ - bool (__cdecl *advance_frame)(void* context, int flags); + bool (__cdecl *advance_frame)(void* context, int flags) = nullptr; /* * on_event - Notification that something has happened. See the GGPOEventCode * structure above for more information. */ - bool (__cdecl *on_event)(void* context, GGPOEvent *info); + bool (__cdecl *on_event)(void* context, GGPOEvent *info) = nullptr; /* * Calling context */ - void* context; + void* context=nullptr; } GGPOSessionCallbacks; /* diff --git a/src/lib/ggpo/backends/p2p.cpp b/src/lib/ggpo/backends/p2p.cpp index 9cfd5971..a6e69dc8 100644 --- a/src/lib/ggpo/backends/p2p.cpp +++ b/src/lib/ggpo/backends/p2p.cpp @@ -36,7 +36,7 @@ Peer2PeerBackend::Peer2PeerBackend(GGPOSessionCallbacks *cb, /* * Initialize the synchronziation layer */ - Sync::Config config = { {nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr},0 }; + Sync::Config config; config.num_players = num_players; config.input_size = input_size; config.callbacks = _callbacks; diff --git a/src/lib/ggpo/backends/synctest.cpp b/src/lib/ggpo/backends/synctest.cpp index 98c4cb55..41606488 100644 --- a/src/lib/ggpo/backends/synctest.cpp +++ b/src/lib/ggpo/backends/synctest.cpp @@ -26,7 +26,7 @@ SyncTestBackend::SyncTestBackend(GGPOSessionCallbacks *cb, /* * Initialize the synchronziation layer */ - Sync::Config config = { {nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr},0 }; + Sync::Config config; config.callbacks = _callbacks; config.num_prediction_frames = MAX_PREDICTION_FRAMES; _sync.Init(config); diff --git a/src/lib/ggpo/network/udp.cpp b/src/lib/ggpo/network/udp.cpp index 8582705f..a88db9c3 100644 --- a/src/lib/ggpo/network/udp.cpp +++ b/src/lib/ggpo/network/udp.cpp @@ -70,7 +70,7 @@ Udp::SendTo(char *buffer, int len, int flags, struct sockaddr *dst, int destlen) int res = sendto(_socket, buffer, len, flags, dst, destlen); if (res == SOCKET_ERROR) { DWORD err = WSAGetLastError(); - std::string errorMessage = "unknown error in sendto (erro :" + std::to_string(res) +" wsaerr: " + std::to_string(err) + ").\n"; + std::string errorMessage = "Error in sendto (erro :" + std::to_string(res) +" wsaerr: " + std::to_string(err) + ").\n"; Log("unknown error in sendto (erro: %d wsaerr: %d).\n", res, err); ASSERT(FALSE && errorMessage.c_str()); } From f11a62f3edfac0eff2e7867617c1e054e41e05bc Mon Sep 17 00:00:00 2001 From: thd79 Date: Sun, 23 Jun 2024 21:45:59 +0100 Subject: [PATCH 37/40] correct the error message in the sendto assert --- src/include/ggponet.h | 4 ++-- src/lib/ggpo/network/udp.cpp | 12 ++++++++---- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/include/ggponet.h b/src/include/ggponet.h index 26af1914..230d4ddc 100644 --- a/src/include/ggponet.h +++ b/src/include/ggponet.h @@ -207,7 +207,7 @@ typedef struct { * your application must implement. GGPO.net will periodically call these * functions during the game. All callback functions must be implemented. */ -typedef struct { +struct GGPOSessionCallbacks { /* * begin_game callback - This callback has been deprecated. You must * implement it, but should ignore the 'game' parameter. @@ -265,7 +265,7 @@ typedef struct { * Calling context */ void* context=nullptr; -} GGPOSessionCallbacks; +} ; /* * The GGPONetworkStats function contains some statistics about the current diff --git a/src/lib/ggpo/network/udp.cpp b/src/lib/ggpo/network/udp.cpp index a88db9c3..b7233327 100644 --- a/src/lib/ggpo/network/udp.cpp +++ b/src/lib/ggpo/network/udp.cpp @@ -69,10 +69,14 @@ Udp::SendTo(char *buffer, int len, int flags, struct sockaddr *dst, int destlen) int res = sendto(_socket, buffer, len, flags, dst, destlen); if (res == SOCKET_ERROR) { - DWORD err = WSAGetLastError(); - std::string errorMessage = "Error in sendto (erro :" + std::to_string(res) +" wsaerr: " + std::to_string(err) + ").\n"; - Log("unknown error in sendto (erro: %d wsaerr: %d).\n", res, err); - ASSERT(FALSE && errorMessage.c_str()); + DWORD err = WSAGetLastError(); + std::string errorMessage = "Error in sendto (erro :" + std::to_string(res) +" wsaerr: " + std::to_string(err) + ").\n"; + Log("unknown error in sendto (erro: %d wsaerr: %d).\n", res, err); + + char assert_buf[1024]; + snprintf(assert_buf, sizeof(assert_buf) - 1, "Assertion: %s @ %s:%d (pid:%d)", errorMessage.c_str(), __FILE__, __LINE__, (int)Platform::GetProcessID()); \ + Platform::AssertFailed(assert_buf); + exit(0); } char dst_ip[1024]; Log("sent packet length %d to %s:%d (ret:%d).\n", len, inet_ntop(AF_INET, (void *)&to->sin_addr, dst_ip, ARRAY_SIZE(dst_ip)), ntohs(to->sin_port), res); From ca20434a1d36a4a31d6b8b6a57f59b374bc7a1fc Mon Sep 17 00:00:00 2001 From: thd79 Date: Tue, 25 Jun 2024 12:09:34 +0100 Subject: [PATCH 38/40] add network error event --- src/apps/vectorwar/VectorWar.vcxproj | 4 +- src/apps/vectorwar/gdi_renderer.cpp | 4 ++ src/apps/vectorwar/main.cpp | 4 +- src/apps/vectorwar/nongamestate.h | 5 ++- src/apps/vectorwar/vectorwar.cpp | 12 ++++-- src/include/ggponet.h | 7 +++- src/lib/ggpo/backends/p2p.cpp | 19 ++++----- src/lib/ggpo/backends/p2p.h | 4 +- src/lib/ggpo/network/udp.cpp | 36 ++++++++++------- src/lib/ggpo/network/udp.h | 2 +- src/lib/ggpo/network/udp_proto.cpp | 58 ++++++++++++++++------------ src/lib/ggpo/network/udp_proto.h | 13 +++++-- src/lib/ggpo/ring_buffer.h | 7 ++++ src/lib/ggpo/sync.cpp | 7 ++-- src/lib/ggpo/sync.h | 2 +- 15 files changed, 113 insertions(+), 71 deletions(-) diff --git a/src/apps/vectorwar/VectorWar.vcxproj b/src/apps/vectorwar/VectorWar.vcxproj index 9e289c78..d1e53d54 100644 --- a/src/apps/vectorwar/VectorWar.vcxproj +++ b/src/apps/vectorwar/VectorWar.vcxproj @@ -230,7 +230,7 @@ true MaxSpeed NotUsing - MultiThreadedDLL + MultiThreaded true true true @@ -334,7 +334,7 @@ true MaxSpeed NotUsing - MultiThreadedDLL + MultiThreaded true true true diff --git a/src/apps/vectorwar/gdi_renderer.cpp b/src/apps/vectorwar/gdi_renderer.cpp index 010b53b7..216e251b 100644 --- a/src/apps/vectorwar/gdi_renderer.cpp +++ b/src/apps/vectorwar/gdi_renderer.cpp @@ -98,6 +98,10 @@ GDIRenderer::Draw(GameState &gs, NonGameState &ngs) sprintf_s(statsinfo, ARRAYSIZE(statsinfo), "%d: %d",i, ngs.rollbacksBySize[i]); TextOutA(hdc, _rc.left + 50, _rc.top + 72+(16*i), statsinfo, (int)strlen(statsinfo)); } + + sprintf_s(statsinfo, ARRAYSIZE(statsinfo), "Network errors: %d", ngs._networkErrorCount); + TextOutA(hdc, _rc.left + 50, _rc.top + 350, statsinfo, (int)strlen(statsinfo)); + if (ngs.desyncFrame >= 0) { sprintf_s(statsinfo, ARRAYSIZE(statsinfo), "!!!!!!!!! DESYNC AT FRAME %d", ngs.desyncFrame); diff --git a/src/apps/vectorwar/main.cpp b/src/apps/vectorwar/main.cpp index 9f12f065..211fd278 100644 --- a/src/apps/vectorwar/main.cpp +++ b/src/apps/vectorwar/main.cpp @@ -103,9 +103,9 @@ RunMainLoop(HWND hwnd) accumulator -= dt; // dt = usToWait; } - auto baseuS = (playerNum == 1) ? dt +rand()%1000: dt + 200 + rand() % 500; + auto baseuS = dt;// (playerNum == 1) ? dt + rand() % 1000 : dt + 200 + rand() % 500; baseuS; - BusyWait(baseuS+ extraUS); + BusyWait(baseuS); VectorWar_DrawCurrentFrame(); // Sleep(1); diff --git a/src/apps/vectorwar/nongamestate.h b/src/apps/vectorwar/nongamestate.h index 00b8f7bd..4b2b2c83 100644 --- a/src/apps/vectorwar/nongamestate.h +++ b/src/apps/vectorwar/nongamestate.h @@ -49,9 +49,9 @@ struct LoopTimer return; } - lastAdvantage = (lastAdvantage * 8) / 10; + lastAdvantage = (lastAdvantage * 5) / 10; - lastAdvantage += (thisAdvantage*10)/10; + lastAdvantage += (thisAdvantage*8)/10; if (lastAdvantage < 0) { m_usExtraToWait = 0; @@ -160,6 +160,7 @@ struct NonGameState { ChecksumInfo now; ChecksumInfo periodic; int desyncFrame = -1; + int _networkErrorCount = 0; }; #endif diff --git a/src/apps/vectorwar/vectorwar.cpp b/src/apps/vectorwar/vectorwar.cpp index 6f51e970..54d9bb9d 100644 --- a/src/apps/vectorwar/vectorwar.cpp +++ b/src/apps/vectorwar/vectorwar.cpp @@ -115,6 +115,12 @@ vw_on_event_callback(void*, GGPOEvent *info) ngs.desyncFrame = info->u.desync.nFrameOfDesync; break; } + + case GGPO_EVENTCODE_NETWORK_ERROR: + { + ngs._networkErrorCount++; + break; + } case GGPO_EVENTCODE_TIMESYNC: ngs.totalFrameDelays += info->u.timesync.frames_ahead; @@ -255,7 +261,7 @@ VectorWar_Init(HWND hwnd, unsigned short localport, int num_players, GGPOPlayer ngs.num_players = num_players; ngs.loopTimer.Init(60,30);// 60FPS; // Fill in a ggpo callbacks structure to pass to start_session. - GGPOSessionCallbacks cb = { 0 }; + GGPOSessionCallbacks cb; cb.begin_game = vw_begin_game_callback; cb.advance_frame = vw_advance_frame_callback; cb.load_game_state = vw_load_game_state_callback; @@ -318,7 +324,7 @@ VectorWar_InitSpectator(HWND hwnd, unsigned short localport, int num_players, ch ngs.num_players = num_players; // Fill in a ggpo callbacks structure to pass to start_session. - GGPOSessionCallbacks cb = { 0 }; + GGPOSessionCallbacks cb; cb.begin_game = vw_begin_game_callback; cb.advance_frame = vw_advance_frame_callback; cb.load_game_state = vw_load_game_state_callback; @@ -464,7 +470,7 @@ VectorWar_RunFrame(HWND hwnd, int&playerNum, int & extraUS) if (ngs.local_player_handle != GGPO_INVALID_HANDLE) { static int nc = 0; int input = nc++ % 2 == 0 ? INPUT_ROTATE_LEFT : INPUT_ROTATE_RIGHT; - // input = ReadInputs(hwnd); + // int input = ReadInputs(hwnd); if (input == INPUT_FIRE) ggpo_client_chat(ggpo, "You wanker!"); #if defined(SYNC_TEST) diff --git a/src/include/ggponet.h b/src/include/ggponet.h index 230d4ddc..e7e1a2d2 100644 --- a/src/include/ggponet.h +++ b/src/include/ggponet.h @@ -154,7 +154,9 @@ typedef enum { GGPO_EVENTCODE_CONNECTION_INTERRUPTED = 1006, GGPO_EVENTCODE_CONNECTION_RESUMED = 1007, GGPO_EVENTCODE_CHAT = 1008, - GGPO_EVENTCODE_DESYNC = 1009 + GGPO_EVENTCODE_DESYNC = 1009, + GGPO_EVENTCODE_NETWORK_ERROR = 1010 + } GGPOEventCode; /* @@ -199,6 +201,9 @@ typedef struct { uint16_t ourCheckSum; uint16_t remoteChecksum; } desync; + struct { + int errorCode; + } network_error; } u; } GGPOEvent; diff --git a/src/lib/ggpo/backends/p2p.cpp b/src/lib/ggpo/backends/p2p.cpp index a6e69dc8..f05f7e82 100644 --- a/src/lib/ggpo/backends/p2p.cpp +++ b/src/lib/ggpo/backends/p2p.cpp @@ -48,7 +48,9 @@ Peer2PeerBackend::Peer2PeerBackend(GGPOSessionCallbacks *cb, */ _udp.Init(localport, &_poll, this); - _endpoints.resize(_num_players); + for (int i = 0; i < _num_players; i++) + _endpoints.emplace_back(); + // _endpoints.resize(_num_players); memset(_local_connect_status, 0, sizeof(_local_connect_status)); for (size_t i = 0; i < ARRAY_SIZE(_local_connect_status); i++) { _local_connect_status[i].last_frame = -1; @@ -497,13 +499,6 @@ Peer2PeerBackend::PollUdpProtocolEvents(void) //} } -void Peer2PeerBackend::CheckRemoteChecksum(int framenumber, uint16) -{ - if (framenumber <= _sync.MaxPredictionFrames()) - return; - //auto frameOfChecksumToSend = framenumber - (_sync.MaxPredictionFrames() + 1); - -} int Peer2PeerBackend::HowFarBackForChecksums()const { @@ -560,7 +555,7 @@ Peer2PeerBackend::OnUdpProtocolPeerEvent(UdpProtocol::Event &evt, int queue) case UdpProtocol::Event::Type::Disconnected: DisconnectPlayer(QueueToPlayerHandle(queue)); - break; + break; default: break; } @@ -624,6 +619,12 @@ Peer2PeerBackend::OnUdpProtocolEvent(UdpProtocol::Event &evt, GGPOPlayerHandle h _callbacks.on_event(_callbacks.context, &info); break; + case UdpProtocol::Event::Type::NetworkError: + info.code = GGPO_EVENTCODE_NETWORK_ERROR; + info.u.network_error.errorCode = evt.u.network_error.errorCode; + _callbacks.on_event(_callbacks.context, &info); + break; + case UdpProtocol::Event::Type::NetworkResumed: info.code = GGPO_EVENTCODE_CONNECTION_RESUMED; info.u.connection_resumed.player = handle; diff --git a/src/lib/ggpo/backends/p2p.h b/src/lib/ggpo/backends/p2p.h index dc1fa815..e0dbe17a 100644 --- a/src/lib/ggpo/backends/p2p.h +++ b/src/lib/ggpo/backends/p2p.h @@ -79,9 +79,7 @@ class Peer2PeerBackend : public GGPOSession, Udp::Callbacks { }; std::map _pendingCheckSums; std::map _confirmedCheckSums; - - // uint16 GetChecksumForConfirmedFrame(int frameNumber) const; - void CheckRemoteChecksum(int framenumber, uint16 cs); + int HowFarBackForChecksums()const; int _confirmedCheckSumFrame = -500; void CheckDesync(); diff --git a/src/lib/ggpo/network/udp.cpp b/src/lib/ggpo/network/udp.cpp index b7233327..7b447bbd 100644 --- a/src/lib/ggpo/network/udp.cpp +++ b/src/lib/ggpo/network/udp.cpp @@ -62,24 +62,30 @@ Udp::Init(uint16 port, Poll *poll, Callbacks *callbacks) _socket = CreateSocket(port, 0); } -void -Udp::SendTo(char *buffer, int len, int flags, struct sockaddr *dst, int destlen) +bool Udp::SendTo(char *buffer, int len, int flags, struct sockaddr *dst, int destlen, int& errorcode) { - struct sockaddr_in *to = (struct sockaddr_in *)dst; - + // Just for artificially triggering a network error + /* struct sockaddr_in* to = (struct sockaddr_in*)dst; + if (GetKeyState('A') & 0x8000 && ntohs(to->sin_port)==9567) + { + errorcode = 999; + return false; + }*/ int res = sendto(_socket, buffer, len, flags, dst, destlen); - if (res == SOCKET_ERROR) { - DWORD err = WSAGetLastError(); - std::string errorMessage = "Error in sendto (erro :" + std::to_string(res) +" wsaerr: " + std::to_string(err) + ").\n"; - Log("unknown error in sendto (erro: %d wsaerr: %d).\n", res, err); - - char assert_buf[1024]; - snprintf(assert_buf, sizeof(assert_buf) - 1, "Assertion: %s @ %s:%d (pid:%d)", errorMessage.c_str(), __FILE__, __LINE__, (int)Platform::GetProcessID()); \ - Platform::AssertFailed(assert_buf); - exit(0); + if (res == SOCKET_ERROR) + { + errorcode = WSAGetLastError(); + return false; } - char dst_ip[1024]; - Log("sent packet length %d to %s:%d (ret:%d).\n", len, inet_ntop(AF_INET, (void *)&to->sin_addr, dst_ip, ARRAY_SIZE(dst_ip)), ntohs(to->sin_port), res); + if (res < len) + { + errorcode = res-len; + return false; + } + return true; + + // char dst_ip[1024]; + // Log("sent packet length %d to %s:%d (ret:%d).\n", len, inet_ntop(AF_INET, (void *)&to->sin_addr, dst_ip, ARRAY_SIZE(dst_ip)), ntohs(to->sin_port), res); } bool diff --git a/src/lib/ggpo/network/udp.h b/src/lib/ggpo/network/udp.h index 0a859f49..3ee6ec3b 100644 --- a/src/lib/ggpo/network/udp.h +++ b/src/lib/ggpo/network/udp.h @@ -39,7 +39,7 @@ class Udp : public IPollSink void Init(uint16 port, Poll *p, Callbacks *callbacks); - void SendTo(char *buffer, int len, int flags, struct sockaddr *dst, int destlen); + bool SendTo(char *buffer, int len, int flags, struct sockaddr *dst, int destlen, int& errorCode); bool OnLoopPoll() override; diff --git a/src/lib/ggpo/network/udp_proto.cpp b/src/lib/ggpo/network/udp_proto.cpp index 983b137d..835397b7 100644 --- a/src/lib/ggpo/network/udp_proto.cpp +++ b/src/lib/ggpo/network/udp_proto.cpp @@ -103,7 +103,7 @@ UdpProtocol::SendInput(GameInput &input) void UdpProtocol::SendPendingOutput() { - UdpMsg *msg = new UdpMsg(UdpMsg::Input); + auto msg = std::make_unique(UdpMsg::Input); int i, j, offset = 0; uint8 *bits; GameInput last; @@ -149,15 +149,15 @@ UdpProtocol::SendPendingOutput() ASSERT(offset < MAX_COMPRESSED_BITS); - SendMsg(msg); + SendMsg(std::move(msg)); } void UdpProtocol::SendInputAck() { - UdpMsg *msg = new UdpMsg(UdpMsg::InputAck); + auto msg = std::make_unique(UdpMsg::InputAck); msg->u.input_ack.ack_frame = _last_received_input.frame; - SendMsg(msg); + SendMsg(std::move(msg)); } bool @@ -191,9 +191,9 @@ void UdpProtocol::EndPollLoop() } void UdpProtocol::SendChat(const char* message) { - UdpMsg* msg = new UdpMsg(UdpMsg::Chat); + auto msg = std::make_unique(UdpMsg::Chat); strcpy_s(msg->u.chat.msg, message); - SendMsg(msg); + SendMsg(std::move(msg)); } bool @@ -225,12 +225,13 @@ UdpProtocol::OnLoopPoll() } if (!_state.running.last_quality_report_time || _state.running.last_quality_report_time + QUALITY_REPORT_INTERVAL < now) { - UdpMsg *msg = new UdpMsg(UdpMsg::QualityReport); + auto msg = std::make_unique(UdpMsg::QualityReport); + msg->u.quality_report.ping = Platform::GetCurrentTimeMS(); // encode frame advantage into a byte by multiplying the float by 10, and croppeing to 255 - any frame advantage // of 25 or more means catastrophe has already befallen us. msg->u.quality_report.frame_advantage = (uint8)min(255.0f,(_timesync.LocalAdvantage()*10.f)); - SendMsg(msg); + SendMsg(std::move(msg)); _state.running.last_quality_report_time = now; } @@ -241,7 +242,7 @@ UdpProtocol::OnLoopPoll() if (_last_send_time && _last_send_time + KEEP_ALIVE_INTERVAL < now) { Log("Sending keep alive packet\n"); - SendMsg(new UdpMsg(UdpMsg::KeepAlive)); + SendMsg(std::make_unique(UdpMsg::KeepAlive)); } if (_disconnect_timeout && _disconnect_notify_start && @@ -288,16 +289,16 @@ void UdpProtocol::SendSyncRequest() { _state.sync.random = rand() & 0xFFFF; - UdpMsg *msg = new UdpMsg(UdpMsg::SyncRequest); + auto msg = std::make_unique(UdpMsg::SyncRequest); msg->u.sync_request.random_request = _state.sync.random; msg->u.sync_request.remote_inputDelay = (uint8_t)_timesync._frameDelay2; - SendMsg(msg); + SendMsg(std::move(msg)); } void -UdpProtocol::SendMsg(UdpMsg *msg) +UdpProtocol::SendMsg(std::unique_ptr&& msg) { - LogMsg("send", msg); + LogMsg("send", msg.get()); _packets_sent++; _last_send_time = Platform::GetCurrentTimeMS(); @@ -306,7 +307,7 @@ UdpProtocol::SendMsg(UdpMsg *msg) msg->hdr.magic = _magic_number; msg->hdr.sequence_number = _next_send_seq++; - _send_queue.push(QueueEntry(Platform::GetCurrentTimeMS(), _peer_addr, msg)); + _send_queue.push(QueueEntry(Platform::GetCurrentTimeMS(), _peer_addr, std::move(msg))); PumpSendQueue(); } @@ -500,11 +501,11 @@ UdpProtocol::OnSyncRequest(UdpMsg *msg, int ) msg->hdr.magic, _remote_magic_number); return false; } - UdpMsg *reply = new UdpMsg(UdpMsg::SyncReply); + auto reply = std::make_unique(UdpMsg::SyncReply); reply->u.sync_reply.random_reply = msg->u.sync_request.random_request; _timesync._remoteFrameDelay = msg->u.sync_request.remote_inputDelay; - SendMsg(reply); + SendMsg(std::move(reply)); return true; } @@ -671,10 +672,10 @@ UdpProtocol::OnInputAck(UdpMsg *msg, int ) bool UdpProtocol::OnQualityReport(UdpMsg *msg, int ) { - // send a reply so the other side can compute the round trip transmit time. - UdpMsg *reply = new UdpMsg(UdpMsg::QualityReply); + // send a reply so the other side can compute the round trip transmit time. + auto reply = std::make_unique(UdpMsg::QualityReply); reply->u.quality_reply.pong = msg->u.quality_report.ping; - SendMsg(reply); + SendMsg(std::move(reply)); _remote_frame_advantage = (float)(msg->u.quality_report.frame_advantage/10.f); return true; @@ -765,11 +766,19 @@ UdpProtocol::PumpSendQueue() ASSERT(entry.dest_addr.sin_addr.s_addr); + int errorCode{ 0 }; + + // If send fails, don't pop the message, try to send it next time, and report an error + // repeated failure to send will result in disconnected + if (!_udp->SendTo((char*)entry.msg.get(), entry.msg->PacketSize(), 0, + (struct sockaddr*)&entry.dest_addr, sizeof entry.dest_addr, errorCode)) + { + Event e(Event::Type::NetworkError); + e.u.network_error.errorCode = errorCode; + QueueEvent(e); + break; + } - _udp->SendTo((char *)entry.msg, entry.msg->PacketSize(), 0, - (struct sockaddr *)&entry.dest_addr, sizeof entry.dest_addr); - delete entry.msg; - _send_queue.pop(); } } @@ -777,8 +786,7 @@ UdpProtocol::PumpSendQueue() void UdpProtocol::ClearSendQueue() { - while (!_send_queue.empty()) { - delete _send_queue.front().msg; + while (!_send_queue.empty()) { _send_queue.pop(); } } diff --git a/src/lib/ggpo/network/udp_proto.h b/src/lib/ggpo/network/udp_proto.h index e2c60ffd..5ad2499f 100644 --- a/src/lib/ggpo/network/udp_proto.h +++ b/src/lib/ggpo/network/udp_proto.h @@ -19,6 +19,7 @@ #include #include #include +#include class UdpProtocol : public IPollSink { public: @@ -42,6 +43,7 @@ class UdpProtocol : public IPollSink Disconnected, NetworkInterrupted, NetworkResumed, + NetworkError, }; Type type; @@ -56,6 +58,9 @@ class UdpProtocol : public IPollSink struct { int disconnect_timeout; } network_interrupted; + struct { + int errorCode; + } network_error; } u; Event(Event::Type t = Event::Type::Unknown) : type(t) { }; @@ -96,6 +101,7 @@ class UdpProtocol : public IPollSink void EndPollLoop(); std::map _remoteCheckSums; std::map _remoteCheckSumsThisFrame; + UdpProtocol(UdpProtocol&&) = default; protected: enum State { Syncing, @@ -106,10 +112,10 @@ class UdpProtocol : public IPollSink struct QueueEntry { int queue_time; sockaddr_in dest_addr; - UdpMsg *msg; + std::unique_ptr msg; QueueEntry() {} - QueueEntry(int time, sockaddr_in &dst, UdpMsg *m) : queue_time(time), dest_addr(dst), msg(m) { } + QueueEntry(int time, sockaddr_in &dst, std::unique_ptr&& m) : queue_time(time), dest_addr(dst), msg(std::move(m)) { } }; void UpdateNetworkStats(void); @@ -119,7 +125,7 @@ class UdpProtocol : public IPollSink void LogMsg(const char *prefix, UdpMsg *msg); void LogEvent(const char *prefix, const UdpProtocol::Event &evt); void SendSyncRequest(); - void SendMsg(UdpMsg *msg); + void SendMsg(std::unique_ptr&& msg); void PumpSendQueue(); void SendPendingOutput(); bool OnInvalid(UdpMsg *msg, int len); @@ -213,6 +219,7 @@ class UdpProtocol : public IPollSink */ RingBuffer _event_queue; std::vector _chatMessages; + UdpProtocol(const UdpProtocol&) = delete; }; #endif diff --git a/src/lib/ggpo/ring_buffer.h b/src/lib/ggpo/ring_buffer.h index 81c93960..2dbdc369 100644 --- a/src/lib/ggpo/ring_buffer.h +++ b/src/lib/ggpo/ring_buffer.h @@ -46,6 +46,13 @@ template class RingBuffer _size++; } + void push(T&& t) { + ASSERT(_size != (N - 1)); + _elements[_head] = std::move(t); + _head = (_head + 1) % N; + _size++; + } + int size() const { return _size; } diff --git a/src/lib/ggpo/sync.cpp b/src/lib/ggpo/sync.cpp index 9df874bc..b4813c9c 100644 --- a/src/lib/ggpo/sync.cpp +++ b/src/lib/ggpo/sync.cpp @@ -27,8 +27,7 @@ Sync::~Sync() for (size_t i = 0; i < _savedstate.frames.size(); i++) { _callbacks.free_buffer(_callbacks.context, _savedstate.frames[i].buf); } - delete [] _input_queues; - _input_queues = NULL; + } void @@ -245,8 +244,8 @@ Sync::FindSavedFrameIndex(int frame) bool Sync::CreateQueues() { - delete [] _input_queues; - _input_queues = new InputQueue[_config.num_players]; + + _input_queues.resize(_config.num_players); for (int i = 0; i < _config.num_players; i++) { _input_queues[i].Init(i, _config.input_size); diff --git a/src/lib/ggpo/sync.h b/src/lib/ggpo/sync.h index efd769b1..7fef59d9 100644 --- a/src/lib/ggpo/sync.h +++ b/src/lib/ggpo/sync.h @@ -99,7 +99,7 @@ class Sync { int _framecount; int _max_prediction_frames; - InputQueue *_input_queues; + std::vector _input_queues; RingBuffer _event_queue; UdpMsg::connect_status *_local_connect_status; From a24d115d4dc0616333d9031bc7e83f759365b430 Mon Sep 17 00:00:00 2001 From: thd79 Date: Tue, 25 Jun 2024 12:56:46 +0100 Subject: [PATCH 39/40] change mtd options for 32-bit verison --- src/GGPO-x.vcxproj | 4 ++-- src/apps/vectorwar/VectorWar.vcxproj | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/GGPO-x.vcxproj b/src/GGPO-x.vcxproj index 911a48e9..d53c83d8 100644 --- a/src/GGPO-x.vcxproj +++ b/src/GGPO-x.vcxproj @@ -203,7 +203,7 @@ true Disabled NotUsing - MultiThreadedDebug + MultiThreadedDebugDLL true true true @@ -417,7 +417,7 @@ true MaxSpeed NotUsing - MultiThreaded + MultiThreadedDLL true true true diff --git a/src/apps/vectorwar/VectorWar.vcxproj b/src/apps/vectorwar/VectorWar.vcxproj index d1e53d54..5efb0647 100644 --- a/src/apps/vectorwar/VectorWar.vcxproj +++ b/src/apps/vectorwar/VectorWar.vcxproj @@ -334,7 +334,7 @@ true MaxSpeed NotUsing - MultiThreaded + MultiThreadedDLL true true true From fe727b90c19b6e933abccf81851569c2ed121a9e Mon Sep 17 00:00:00 2001 From: thd79 Date: Wed, 26 Jun 2024 14:59:40 +0100 Subject: [PATCH 40/40] changes to vectorwar --- src/apps/vectorwar/gdi_renderer.cpp | 2 +- src/apps/vectorwar/main.cpp | 55 +++++++++++++++++----- src/apps/vectorwar/nongamestate.h | 73 +++++++++++++++++------------ src/apps/vectorwar/vectorwar.cpp | 7 ++- src/apps/vectorwar/vectorwar.h | 2 +- 5 files changed, 93 insertions(+), 46 deletions(-) diff --git a/src/apps/vectorwar/gdi_renderer.cpp b/src/apps/vectorwar/gdi_renderer.cpp index 216e251b..1843c685 100644 --- a/src/apps/vectorwar/gdi_renderer.cpp +++ b/src/apps/vectorwar/gdi_renderer.cpp @@ -73,7 +73,7 @@ GDIRenderer::Draw(GameState &gs, NonGameState &ngs) TextOutA(hdc, (_rc.left + _rc.right) / 2, _rc.top + 72, statsinfo, (int)strlen(statsinfo)); sprintf_s(statsinfo, ARRAYSIZE(statsinfo), - "Rbcks: %i, tsyncs: %i, negtsyncs: %i, inputreject: %d, RTT: %d, total fr dly :%.1f, extraUS: %d", + "Rbcks: %i, tsyncs: %i, negtsyncs: %i, inputreject: %d, RTT: %d, total fr dly :%.1f, extraUS: %i", ngs.nRollbacks, ngs.nTimeSyncs,ngs.nonTimeSyncs,ngs.inputDelays, ngs.stats.network.ping, ngs.totalFrameDelays,ngs.loopTimer.m_usExtraToWait); TextOutA(hdc, (_rc.left + _rc.right) / 2, _rc.top + 88, statsinfo, (int)strlen(statsinfo)); diff --git a/src/apps/vectorwar/main.cpp b/src/apps/vectorwar/main.cpp index 211fd278..f9cf48f3 100644 --- a/src/apps/vectorwar/main.cpp +++ b/src/apps/vectorwar/main.cpp @@ -5,6 +5,7 @@ #endif #include "vectorwar.h" #include "ggpo_perfmon.h" +#include "nongamestate.h" #include LRESULT CALLBACK MainWindowProc(HWND hwnd, @@ -73,14 +74,36 @@ void BusyWait(int uS) break; } } + +using namespace std::chrono; + +void AccurateSleep(int timeToSleep) +{ + if (timeToSleep <= 0) + return; + + auto start = high_resolution_clock::now(); + + // Sleep, but only to within 2ms of the target wait time (as sleep is not that accurate) + auto maxusToSleep = timeToSleep - 2000; + if (maxusToSleep > 1000) { + Sleep(maxusToSleep / 1000); + } + + //Spin wait the rest + auto now = high_resolution_clock::now(); + while (duration_cast(now - start).count() < timeToSleep) { + now = high_resolution_clock::now(); + } +} void RunMainLoop(HWND hwnd) { MSG msg = { 0 }; - std::chrono::steady_clock::time_point start, next, now,newtime, current; + auto current = std::chrono::high_resolution_clock::now(); + auto lastFrameEndTime = std::chrono::high_resolution_clock::now(); int dt = 1000000 / 60; int accumulator = 0; - start = next = current =newtime = std::chrono::high_resolution_clock::now(); while(1) { while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { TranslateMessage(&msg); @@ -89,25 +112,31 @@ RunMainLoop(HWND hwnd) return; } } - newtime = std::chrono::high_resolution_clock::now(); - auto frameTime = (int)std::chrono::duration_cast(newtime - current).count(); - current = newtime; + auto newTime = lastFrameEndTime; + auto frameTime = (int)std::chrono::duration_cast(newTime - current).count(); + current = newTime; accumulator += frameTime; - + if (accumulator >= dt * 5) + accumulator = dt * 5; // - int playerNum=1; + int playerNum = localPlayerNumber(); int extraUS = 0; - // while(accumulator>= dt) + auto frameBudget = dt + extraUS; + while(accumulator>= frameBudget) { VectorWar_RunFrame(hwnd, playerNum,extraUS); - accumulator -= dt; + accumulator -= frameBudget; // dt = usToWait; } - auto baseuS = dt;// (playerNum == 1) ? dt + rand() % 1000 : dt + 200 + rand() % 500; - baseuS; - BusyWait(baseuS); + + + // auto frameTimeLeft = frameBudget - duration_cast(high_resolution_clock::now() - lastFrameEndTime).count(); + // BusyWait((int)frameTimeLeft); + + Sleep(rand()%20); VectorWar_DrawCurrentFrame(); - // Sleep(1); + + lastFrameEndTime = high_resolution_clock::now(); } } diff --git a/src/apps/vectorwar/nongamestate.h b/src/apps/vectorwar/nongamestate.h index 4b2b2c83..eed79b14 100644 --- a/src/apps/vectorwar/nongamestate.h +++ b/src/apps/vectorwar/nongamestate.h @@ -38,40 +38,53 @@ struct LoopTimer nCalls = 0; } - void OnGGPOTimeSyncEvent(float framesAhead) + void OnGGPOTimeSyncEvent(float framesAhead, int nTimeSyncInterval) { - auto thisAdvantage = /*(int)*/(1000.0f * framesAhead / 60.0f);// *0.5f; - nCalls++; - if (nCalls <= 1) - { - if (thisAdvantage > 0) - Sleep((int)thisAdvantage); - return; - } - - lastAdvantage = (lastAdvantage * 5) / 10; - - lastAdvantage += (thisAdvantage*8)/10; - if (lastAdvantage < 0) - { - m_usExtraToWait = 0; - return; - } - m_usExtraToWait = (int)(lastAdvantage*1000); - if (m_usExtraToWait) - { - //BusyWait(m_usExtraToWait); - m_usExtraToWait /= m_framesToSpreadWait; - m_WaitCount = m_framesToSpreadWait; - } - } - float slowDownPC() const - { - return m_usExtraToWait * 100.0f / m_usPerGameLoop; + + + + + // This message tells us we are running ahead or behind the opponent, so we should speed up or slow down our loop a bit. + // This message comes every nTimeSyncInterval frames. We aim to speed up/slow down 33% of reported difference by the time of the + // next sync message. 33% is chosen in order to avoid overcompensation - the other player will be doing 33% in the opposite direction, + // giving 66% overall. So the gap should reduce geometrically, but not overshoot. + // We spread the 33% wait/speedup over the next nTimeSyncInterval frames, + auto ticksPerFrame = 1000000 / (float)60; + float ticksAhead = ticksPerFrame * framesAhead; // could be negative if behind + m_usExtraToWait = (int)(ticksAhead / nTimeSyncInterval); + + // Divive by 3 for reasons described above + m_usExtraToWait /= 2; + //m_usExtraToWait = 0; + //auto thisAdvantage = /*(int)*/(1000.0f * framesAhead / 60.0f);// *0.5f; + //nCalls++; + //if (nCalls <= 1) + //{ + // if (thisAdvantage > 0) + // Sleep((int)thisAdvantage); + // return; + //} + // + //lastAdvantage = (lastAdvantage * 5) / 10; + // + // lastAdvantage += (thisAdvantage*8)/10; + //if (lastAdvantage < 0) + //{ + // m_usExtraToWait = 0; + // return; + //} + //m_usExtraToWait = (int)(lastAdvantage*1000); + //if (m_usExtraToWait) + //{ + // //BusyWait(m_usExtraToWait); + // m_usExtraToWait /= m_framesToSpreadWait; + // m_WaitCount = m_framesToSpreadWait; + //} } + int slowdown() { - return m_WaitCount-- ? m_usExtraToWait : 0; + return m_usExtraToWait; } diff --git a/src/apps/vectorwar/vectorwar.cpp b/src/apps/vectorwar/vectorwar.cpp index 54d9bb9d..ed87f5d6 100644 --- a/src/apps/vectorwar/vectorwar.cpp +++ b/src/apps/vectorwar/vectorwar.cpp @@ -124,7 +124,7 @@ vw_on_event_callback(void*, GGPOEvent *info) case GGPO_EVENTCODE_TIMESYNC: ngs.totalFrameDelays += info->u.timesync.frames_ahead; - ngs.loopTimer.OnGGPOTimeSyncEvent(info->u.timesync.frames_ahead); + ngs.loopTimer.OnGGPOTimeSyncEvent(info->u.timesync.frames_ahead,info->u.timesync.timeSyncPeriodInFrames); if (info->u.timesync.frames_ahead > 0) { ngs.nTimeSyncs++; @@ -449,6 +449,11 @@ ReadInputs(HWND hwnd) * * Run a single frame of the game. */ + +int localPlayerNumber() +{ + return ngs.local_player_handle; +} void VectorWar_RunFrame(HWND hwnd, int&playerNum, int & extraUS) { diff --git a/src/apps/vectorwar/vectorwar.h b/src/apps/vectorwar/vectorwar.h index d157b2b6..1039bb26 100644 --- a/src/apps/vectorwar/vectorwar.h +++ b/src/apps/vectorwar/vectorwar.h @@ -28,7 +28,7 @@ void VectorWar_RunFrame(HWND hwnd, int& usToWait, int& extraUS); void VectorWar_Idle(); void VectorWar_DisconnectPlayer(int player); void VectorWar_Exit(); - +int localPlayerNumber(); #define ARRAY_SIZE(n) (sizeof(n) / sizeof(n[0])) #define FRAME_DELAY 2