300f1b7919
This fixes an issue where you would be able to mount things other than custom assets in per-level custom asset directories and zips. To be fair, the effects of this issue were fairly limited - about the only thing I could do with it was to override a user-made quicksave of a custom level with one of my own. However, since the quicksave check happens before assets are mounted, if the user didn't have an existing quicksave then they wouldn't be able load my quicksave. Furthermore, mounting things like settings.vvv simply doesn't work because assets only get mounted when the level gets loaded, but the game only reads from settings.vvv on startup. Still, this is an issue, and just because it only has one effect doesn't mean we should single-case patch that one effect only. So what can we do? I was thinking that we should (1) mount custom assets in a dedicated directory, and then from there (2) mount each specific asset directly - namely, mount the graphics/ and sounds/ folders, and mount the vvvvvvmusic.vvv and mmmmmm.vvv files. For (1), assets are now mounted at a (non-existent) location named .vvv-mnt/assets/. However, (2) doesn't fully work due to how PhysFS works. What DOES work is being able to mount the graphics/ and sounds/ folders, but only if the custom assets directory is a directory. And, you actually have to use the real directory where those graphics/ and sounds/ folders are located, and not the mounted directory, because PHYSFS_mount() only accepts real directories. (In which case why bother mounting the directory in the first place if we have to use real directories anyway?) So already this seems like having different directory and zip mounting paths, which I don't want... I tried to unify the directory and zip paths and get around the real directory limitation. So for mounting each individual asset (i.e. graphics/, sounds/, but especially vvvvvvmusic.vvv and mmmmmm.vvv), I tried doing PHYSFS_openRead() followed by PHYSFS_mountHandle() with that PHYSFS_File, but this simply doesn't work, because PHYSFS_mountHandle() will always create a PHYSFS_Io object, and pass it to a PhysFS internal helper function named openDirectory() which will only attempt to treat it as a directory if the PHYSFS_Io* passed is NULL. Since PHYSFS_mountHandle() always passes a non-NULL PHYSFS_Io*, openDirectory() will always treat it like a zip file and never as a directory - in contrast, PHYSFS_mount() will always pass a NULL PHYSFS_Io* to openDirectory(), so PHYSFS_mount() is the only function that works for mounting directories. (And even if this did work, having to keep the file open (because of the PHYSFS_openRead()) results in the user being unable to touch the file on Windows until it gets closed, which I also don't want.) As for zip files, PHYSFS_mount() works just fine on them, but then we run into the issue of accessing the individual assets inside it. As covered above, PHYSFS_mount() only accepts real directories, so we can't use it to access the assets inside, but then if we do the PHYSFS_openRead() and PHYSFS_mountHandle() approach, PHYSFS_mountHandle() will treat the assets inside as zip files instead of just mounting them normally! So in short, PhysFS only seems to be able to mount directories and zip files, and not any loose individual files (like vvvvvvmusic.vvv and mmmmmm.vvv). Furthermore, directories inside directories works, but directories inside zip files doesn't (only zip files inside zip files work). It seems like our asset paths don't really work well with PhysFS's design. Currently, graphics/, sounds/, vvvvvvmusic.vvv, and mmmmmm.vvv all live at the root directory of the VVVVVV folder. But what would work better is if all of those items were organized into a subfolder, for example, a folder named assets/. So the previous assets mounting system before this patch would just have mounted assets/ and be done with it, and there would be no risk of mounting extraneous files that could do bad things. However, due to our unorganized asset paths, the previous system has to mount assets at the root of the VVVVVV folder, which invites the possibility of those extraneous bad files being mounted. Well, we can't change the asset paths now, that would be a pretty big API break (maybe it should be a 2.4 thing). So what can we do? What I've done is, after mounting the assets at .vvv-mnt/assets/, when the game loads an asset, it checks if there's an override available inside .vvv-mnt/assets/, and if so, the game will load that asset instead of the regular one. This is basically reimplementing what PhysFS SHOULD be able to do for us, but can't. This fixes the issue of being able to mount a quicksave for a custom level inside its asset directory. I should also note, the unorganized asset paths issue also means that for .zip files (which contain the level file), the level file itself is also technically mounted at .vvv-mnt/assets/. This is harmless (because when we load a level file, we never load it as an asset) but it's still a bit ugly. Changing the asset paths now seems more and more like a good thing to do... |
||
---|---|---|
.. | ||
src | ||
.dockerignore | ||
.gitignore | ||
CMakeLists.txt | ||
CONTRIBUTORS.txt | ||
Dockerfile | ||
README.md | ||
version.cmake |
How to Build
VVVVVV's official desktop versions are built with the following environments:
- Windows: Visual Studio 2010
- macOS: Xcode CLT, currently targeting 10.9 SDK
- GNU/Linux: CentOS 7
The engine depends solely on SDL2 2.0.14+ and SDL2_mixer. All other dependencies are statically linked into the engine. The development libraries for Windows can be downloaded from their respective websites, Linux developers can find the dev libraries from their respective repositories, and macOS developers should compile and install from source (including libogg/libvorbis/libvorbisfile).
Steamworks support is included and the DLL is loaded dynamically, you do not need the SDK headers and there is no special Steam or non-Steam version. The current implementation has been tested with Steamworks SDK v1.46.
To generate the projects on Windows:
# Put your SDL2/SDL2_mixer folders somewhere nice!
mkdir flibitBuild
cd flibitBuild
cmake -G "Visual Studio 10 2010" .. -DSDL2_INCLUDE_DIRS="C:\SDL2-2.0.10\include;C:\SDL2_mixer-2.0.4\include" -DSDL2_LIBRARIES="C:\SDL2-2.0.10\lib\x86\SDL2;C:\SDL2-2.0.10\lib\x86\SDL2main;C:\SDL2_mixer-2.0.4\lib\x86\SDL2_mixer"
Note that on some systems, the SDL2_LIBRARIES
list on Windows may need
SDL2/SDL2main/SDL2_mixer to have .lib
at the end of them. The reason for this
inconsistency is unknown.
To generate everywhere else:
mkdir flibitBuild
cd flibitBuild
cmake ..
macOS may be fussy about the SDK version. How to fix this is up to the whims of however Apple wants to make CMAKE_OSX_SYSROOT annoying to configure and retain each time Xcode updates.
Including data.zip
You'll need the data.zip file from VVVVVV to actually run the game! It's available to download separately for free in the Make and Play edition of the game. Put this file next to your executable and the game should run.
This is intended for personal use only - our license doesn't allow you to actually distribute this data.zip file with your own forks without getting permission from us first. See LICENSE.md for more details. (If you've got a project in mind that requires distributing this file, get in touch!)
A Word About Compiler Quirks
(Note: This section only applies to version 2.2 of the source code, which is the initial commit of this repository. Since then, much hard work has been put in to fix many undefined behaviors. If you're compiling the latest version of the source code, ignore this section.)
This engine is super fussy about optimization levels and runtime checks. In particular, the Windows version absolutely positively must be compiled in Debug mode, with /RTC enabled. If you build in Release mode, or have /RTC disabled, the game behaves dramatically different in ways that were never fully documented (bizarre softlocks, out-of-bounds issues that don't show up in tools like Valgrind, stuff like that). There are lots of things about this old code that could be cleaned up, polished, rewritten, and so on, but this is the one that will probably bite you the hardest when setting up your own build, regardless of platform.
We hope you'll enjoy messing with the source anyway!
Love, flibit