Compare commits

...

157 Commits

Author SHA1 Message Date
elasota
b9b7d91989 Reject zip archives with non-zero file count but empty central directory 2022-03-17 13:14:17 -04:00
Eric Lasota
3e13877788 Merge pull request #11 from ryandesign/stdlib
Include stdlib.h where its functions are used
2022-03-17 13:10:33 -04:00
Ryan Schmidt
53ff18d337 Include stdlib.h where its functions are used
Fixes build failure on OS X 10.10 and 10.11:

error: use of undeclared identifier 'free'
error: use of undeclared identifier 'malloc'
error: use of undeclared identifier 'qsort'
2022-03-17 02:54:37 -05:00
elasota
e33c01cc40 Change line endings to UNIX 2022-03-17 02:00:06 -04:00
Eric Lasota
0c891d3117 Merge pull request #10 from ryandesign/mac
Improve CMake macOS build
2022-03-17 01:58:13 -04:00
elasota
e4d2d9f9a4 Fix bad null compares 2022-03-17 01:50:19 -04:00
elasota
41c0312921 Add more nullptr_t operators 2022-03-17 01:48:16 -04:00
Ryan Schmidt
e78b01a5f3 Improve CMake macOS build
Now actually builds on macOS.

Closes #9
2022-03-17 00:39:55 -05:00
elasota
d470bb5eeb Add nullptr_t constructor to THandle 2022-03-16 21:24:47 -04:00
elasota
1fe94e4f06 Split AerofoilTools package 2021-11-10 18:05:19 -05:00
elasota
5f2f73e176 Bump to API 30 2021-11-10 17:51:59 -05:00
elasota
7c5864d59b Update installer to VS2019 C++ runtime. 2021-11-10 17:22:01 -05:00
elasota
d698ff23db Bump version to 1.1.2 2021-11-10 17:21:45 -05:00
elasota
92cb961208 Update credits 2021-11-10 17:21:29 -05:00
elasota
545798600e Fix gamepads not working, enable on Android 2021-10-22 22:01:33 -04:00
elasota
9ba15c6d78 Update C++ projects to VS2019, fix warnings/errors 2021-10-22 22:01:14 -04:00
elasota
0706640bc9 Merge branch 'master' of https://github.com/elasota/GlidePort 2021-10-22 13:07:56 -04:00
Eric Lasota
bdb7ddbdbb Create README.md 2021-10-10 11:28:36 -04:00
Eric Lasota
c5dee3ce9e Update README.md 2021-10-10 11:25:21 -04:00
elasota
7e3569500a Handle RGB15BE blit 2021-09-02 04:13:43 -04:00
elasota
376fdf16c4 Add name-to-comment support to GPAs 2021-09-01 22:06:43 -04:00
Eric Lasota
40b38046b9 Merge pull request #6 from pmarell/mac
Mac-specific improvements
2021-08-25 10:06:53 -04:00
Phil Marell
5b5fb15780 Send events through queue instead of calling game methods directly 2021-08-08 16:59:27 +10:00
Phil Marell
744b06796d Remove no longer true comment 2021-08-08 16:57:25 +10:00
Phil Marell
7ba11df286 Add quit event to queue without using private SDL method 2021-08-08 16:57:24 +10:00
Phil Marell
9f5699a61e Return correct value for macOS 2021-08-08 16:56:19 +10:00
Phil Marell
5ab966ea98 Fix build errors 2021-08-08 16:56:19 +10:00
Phil Marell
42ec9e3646 Use #pragma once 2021-08-05 18:46:36 +10:00
Phil Marell
83978d0397 Merge branch 'master' into mac
# Conflicts:
#	AerofoilSDL/GpDisplayDriver_SDL_GL2.cpp
#	PortabilityLayer/MenuManager.cpp
2021-08-05 18:46:18 +10:00
elasota
82fe38dfc7 Fix about dialog misalignments 2021-08-04 02:34:54 -04:00
elasota
2c90110668 Fix key names not lining up correctly, bump prefs version since new key specials don't match old prefs 2021-08-02 01:19:20 -04:00
elasota
eac270670d Add command/meta key support 2021-08-02 01:04:22 -04:00
elasota
c04aeeb962 Add Inter font, map Chicago system symbol reservations using it, use Command symbol on macOS 2021-08-01 22:24:41 -04:00
elasota
f9109850a6 Remove tools from install package so they can be split off into a separate download. 2021-08-01 22:23:56 -04:00
elasota
71955ac729 Fixed GenerateFonts bugs 2021-07-31 17:40:57 -04:00
Phil Marell
f36a8da95f Allow native menu to unhighlight 2021-07-28 20:14:34 +10:00
Phil Marell
0e3534d902 Wire objects/actions in nib 2021-07-28 19:44:07 +10:00
Phil Marell
90943d945b Expose certain methods to be used for Mac menu items 2021-07-28 19:44:07 +10:00
Phil Marell
00488c6fea Override Cocoa app lifecycle defined by SDL 2021-07-28 19:44:07 +10:00
Phil Marell
f16ffa0c4c Replace Main.storyboard with custom MainMenu.xib
The new xib file contains the default main menu created by Xcode, but removes the command-H shortcut from the Hide menu item, so that the in-game High Scores item takes effect instead.

Also SDL only supports custom nib files, not storyboards.
2021-07-28 19:44:03 +10:00
Phil Marell
e098370249 Use Command key instead of Control as modifier on macOS
This provides an experience closer to the original classic Mac version.

This is supported by the earlier changes to gracefully quit the game.
2021-07-24 16:27:55 +10:00
Phil Marell
c3eb23af4b Handle external quits while in editor
This mitigates against potential data loss after having finished editing a house.
2021-07-24 16:27:55 +10:00
Phil Marell
a32b33ef1b Ask to save game if user “externally” quits while in-game
An “external quit” being defined as one where the portability handler receives a request to quit the app, such as closing the window, or on macOS using the Quit menu item.

This can prevent the user losing their progress after having finished with a game.
2021-07-24 16:27:55 +10:00
Phil Marell
b83fd1b28f Move “end game” logic into common function 2021-07-24 16:27:55 +10:00
Phil Marell
ab6c447a2f Compile on Xcode 13 2021-07-24 16:27:55 +10:00
Phil Marell
e02919f1fc Use tabs in Xcode project 2021-07-24 16:27:55 +10:00
Phil Marell
ccceec8b3c Xcode 13 automatic change 2021-07-24 16:18:10 +10:00
Phil Marell
40c1a39c40 Add .DS_Store to .gitignore 2021-07-24 16:18:10 +10:00
elasota
c27d78d329 Bulk import script early version + StuffIt 5 fixes. 2021-06-30 00:45:53 -04:00
elasota
66cce6bcd4 Bump version to 1.1.1 2021-06-06 01:12:31 -04:00
elasota
b616c6bf6e Icon refactor 2021-06-06 01:12:21 -04:00
elasota
2e9954677d Merge branch 'master' of https://github.com/elasota/GlidePort 2021-05-16 12:08:38 -04:00
elasota
3d5265258e Disable asserts 2021-05-16 12:08:23 -04:00
Eric Lasota
6103007ed2 Update README.md 2021-05-16 00:28:58 -04:00
elasota
240ba88f53 Fix Android crash 2021-05-14 19:30:31 -04:00
elasota
71115b2366 Fix AerofoilX compile failure 2021-05-14 19:19:03 -04:00
elasota
2bde3bc60b Update version to 1.1.0 2021-05-14 19:09:35 -04:00
elasota
0524c312d0 Update credits 2021-05-14 18:55:28 -04:00
Eric Lasota
8a69d7b921 Merge pull request #5 from madthijs/mac
Mac version 1.1.0
2021-05-14 18:07:05 -04:00
Madthijs
20a3918535 Merge branch 'master' into mac
# Conflicts:
#	GpApp/House.cpp
2021-05-14 21:44:39 +02:00
Madthijs
bd61b23bde code review changes 2021-05-14 21:40:56 +02:00
elasota
b1bebc2afd Disable asserts in web release build 2021-05-13 12:14:18 -04:00
elasota
5b16ed826f Fix compile failure in debug 2021-05-13 12:13:45 -04:00
elasota
567b82eb23 Tag 1.1.0 rc2 2021-05-11 21:36:12 -04:00
elasota
e8565a122d EOL fix 2021-05-11 21:32:00 -04:00
elasota
32ff2f6fe8 Finish clearing out std::vector from PortabilityLayer 2021-05-11 21:27:40 -04:00
elasota
95260f8d8a Zero out structures when creating houses and rooms 2021-05-11 19:47:05 -04:00
elasota
e7b02f37a5 Fix memory corruption when creating a new house 2021-05-11 19:42:05 -04:00
elasota
781c6ce610 Fix missing return value 2021-05-11 19:18:24 -04:00
elasota
98c7a1eea6 Fix MergeGPF missing from simple release 2021-05-11 19:18:15 -04:00
Madthijs
0a9b5ded9b unneeded changes 2021-05-11 17:15:21 +02:00
Madthijs
09485b7cf4 compile + hardened security 2021-05-11 15:43:09 +02:00
Madthijs
6fd1edd2c8 Merge branch 'master' into mac
# Conflicts:
#	GpApp/Main.cpp
2021-05-11 14:28:46 +02:00
elasota
6858230dde Update copyright 2021-05-11 01:52:56 -04:00
elasota
a6486c137b Change version tag to 1.1.0 rc1 2021-05-11 01:42:06 -04:00
elasota
318a5868d7 Disable loading room editor if the current house is damaged beyond repair, and re-enable loading a different house. 2021-05-11 01:39:17 -04:00
elasota
295db5f064 Fix memory leak 2021-05-11 01:29:40 -04:00
elasota
0def879db1 Fix build 2021-05-11 00:58:26 -04:00
elasota
ac56badffa Add download house option 2021-05-11 00:41:35 -04:00
elasota
75923ad7b0 Fix deleted houses still being in the house list 2021-05-10 23:21:40 -04:00
elasota
32d96798cc Fix file deletion not working in web version 2021-05-10 19:43:52 -04:00
elasota
c354d49e9f Replace beep sound with a simple 80% 440hz + 20% 60hz + fadeout generated tone 2021-05-10 00:10:14 -04:00
elasota
24169507bd Add beep sound to platforms with no beep 2021-05-09 23:45:27 -04:00
elasota
d54ad576bc Add delete option to File browser 2021-05-09 22:48:23 -04:00
elasota
222927d56f Fix double-free when handle is shrunk to zero size 2021-05-09 22:47:57 -04:00
elasota
d74c4b70f3 Remove unused function 2021-05-08 10:55:22 -04:00
elasota
fb7b9b02d9 Web save mechanism 2021-05-07 23:09:35 -04:00
elasota
1ac8032411 Log to stdout 2021-05-07 23:08:29 -04:00
elasota
a012c6d3e7 Fix web build and add export path 2021-05-07 20:12:41 -04:00
elasota
08c6fd5108 EOL fix 2021-05-07 20:12:27 -04:00
elasota
a7cf9d48e3 Fix double GP_RESTRICT definition 2021-05-07 13:29:45 -04:00
elasota
d6ce07685e Clean up vector use 2021-05-07 10:59:31 -04:00
elasota
5e060279af Clean up warnings 2021-05-07 10:59:19 -04:00
elasota
a2ca1725fa Improve export house errors 2021-05-07 03:02:30 -04:00
elasota
f32866510e EOL fix 2021-05-07 02:59:30 -04:00
elasota
ac15c26bef Update installer manufacturer ID 2021-05-07 02:52:28 -04:00
elasota
9510aaee32 Re-enable initial launch disclaimer 2021-05-07 02:30:20 -04:00
elasota
c6aa82db35 Adjust credits 2021-05-07 02:26:10 -04:00
elasota
6d12b6ff1a Add house export to room editor 2021-05-07 02:16:25 -04:00
elasota
c3b2a7e8af EOL fix 2021-05-07 02:14:50 -04:00
elasota
b0d5673d95 Add export dir to Windows 2021-05-07 02:12:58 -04:00
Madthijs
14ef73a8ab add readme for resources 2021-05-05 10:47:42 +02:00
Madthijs
456a134041 ignore resources 2021-05-05 10:47:28 +02:00
Madthijs
27ae449353 remove resources from git 2021-05-05 10:46:12 +02:00
elasota
0de26b5e71 Remove header guards 2021-05-04 18:26:33 -04:00
elasota
65d4784618 Fix desaturation filter not isolating wand star. 2021-05-04 18:26:23 -04:00
elasota
5187ef5dc6 Use upscale filter at 1.5x and 2.5x 2021-05-04 18:25:49 -04:00
Madthijs
b96acad0ca logging fix 2021-05-04 18:11:03 +02:00
Madthijs
2277d1340c Merge branch 'master' into mac 2021-05-04 16:18:01 +02:00
Madthijs
57798c05c6 Undo runtime fonts 2021-05-04 16:05:15 +02:00
elasota
f24b0a0e77 Preprocess audio into S16 for faster mixing. 2021-04-29 20:16:24 -04:00
elasota
7442b92dd3 Make FS use new allocator API 2021-04-28 23:18:24 -04:00
Madthijs
0725828a5f allocator + font stuff 2021-04-28 20:06:51 +02:00
Madthijs
c5a1303b71 Merge branch 'master' into mac
# Conflicts:
#	AerofoilX/GpMain_SDL_X.cpp
2021-04-28 19:17:55 +02:00
elasota
a2d374f650 Allocator refactor 2021-04-28 01:46:07 -04:00
elasota
472462c535 AerofoilX logging fixes 2021-04-27 10:38:09 -04:00
elasota
80683464af Buildfix AerofoilX 2021-04-27 10:00:23 -04:00
elasota
2cd4e4f178 UTF refactor to eliminate duplicated code outside of PL 2021-04-27 09:54:01 -04:00
elasota
07df94fb00 Use combined files on Android for faster build 2021-04-27 09:52:59 -04:00
elasota
d6b206195d Buildfix Android 2021-04-27 09:51:05 -04:00
elasota
65e68f790a Don't allow empty images. 2021-04-27 03:37:24 -04:00
elasota
56d999f400 Don't allow empty sounds 2021-04-27 03:37:14 -04:00
elasota
2991a7490e Preserve active room on editor resolution change. 2021-04-27 01:33:23 -04:00
elasota
0c43370353 Patch Castle o' the Air start room. Fixes issue #4. 2021-04-27 00:14:59 -04:00
elasota
9ba5b14db6 Add HouseTool 2021-04-27 00:14:16 -04:00
elasota
5e1f5655a0 Fix unpacktool not working 2021-04-27 00:13:51 -04:00
Madthijs
67b594fe68 renames 2021-04-26 20:24:38 +02:00
elasota
0385c28002 User house validation 2021-04-25 22:08:15 -04:00
elasota
19b1a307e7 EOL fix 2021-04-25 22:07:04 -04:00
elasota
9341c4c378 EOL fix 2021-04-25 01:59:48 -04:00
elasota
5d9dde6589 Refactor audio buffering API, this should mainly prevent SDL audio driver from allocating memory in the mixer callback. 2021-04-25 00:34:02 -04:00
elasota
f9d3b91f72 Fixed redundant set 2021-04-20 21:02:11 -04:00
elasota
1dc86a703e Fix somewhat incorrect upscale texture handling. Replace InstancedResources reset with something that's less likely to be undefined behavior. 2021-04-20 20:42:30 -04:00
Madthijs
82aaefe342 removed logging + fixed crash issue 2021-04-20 20:24:25 +02:00
Madthijs
d77cf6f5db AppIcon added 2021-04-20 16:44:49 +02:00
Madthijs
a9b6d1dc4f Xcode project clean up target build SDL 2021-04-19 16:01:14 +02:00
Madthijs
08349fc6db Xcode project 2021-04-19 12:10:34 +02:00
elasota
77e02927c6 Fix web crash when dragging or closing popup windows 2021-04-19 02:44:19 -04:00
elasota
c473271e4e Super-minimal shell 2021-04-19 02:28:34 -04:00
elasota
84a4d16aed Web file system implementation + fixes 2021-04-19 01:02:10 -04:00
elasota
f15a87041a Improve synthetic bold quality and use synthetic bold for most Open Sans uses 2021-04-18 18:11:38 -04:00
elasota
d826a908e9 Remove font cache from web 2021-04-18 18:06:45 -04:00
elasota
3d3f839801 Add synthetic bold hack to better support Geneva CY 2021-04-16 00:26:42 -04:00
elasota
141f840888 Specialize font paths for preinstalled font selection instead 2021-04-15 20:56:31 -04:00
elasota
22ae442f87 Handle preinstalled fonts case 2021-04-15 20:08:16 -04:00
elasota
5dd8bf28f5 Add IsUsingPreinstalledFonts API 2021-04-15 20:03:06 -04:00
elasota
bd422d0eb3 EOL fix 2021-04-15 19:52:50 -04:00
elasota
4e8e76f8fc Re-enable runtime font rendering if a font handler is assigned, clean up some font handler things. 2021-04-15 19:49:43 -04:00
Madthijs
bf1dad34c3 It's alive!!! 🦄 2021-04-13 17:18:54 +02:00
elasota
c49bab04d5 Fix modulation being applied twice 2021-04-11 10:57:33 -04:00
Madthijs
e6df94dac0 First compile, Logger works 2021-04-11 14:07:16 +02:00
elasota
71f27f0a05 Fix some suboptimal audio constants. 2021-04-11 01:22:48 -04:00
elasota
b9fe553ff8 Improve mixer performance 2021-04-10 23:56:25 -04:00
elasota
7ae31bc7fc Use fixed latency offset in SDL mixer. This should fix score tick sounds having uneven spacing.
Reduce buffer to 512 samples again.
2021-04-10 21:54:41 -04:00
elasota
2234190f24 Remove FreeType from basic release 2021-04-08 02:01:43 -04:00
elasota
d62de80ff1 Flag GenerateFonts as a dependency for the release package installer 2021-04-08 01:43:00 -04:00
elasota
03f07d7c4f Remove resources dir from basic release 2021-04-08 01:40:48 -04:00
376 changed files with 18478 additions and 4209 deletions

16
.gitignore vendored
View File

@@ -21,6 +21,8 @@
*.aps
*.res
*.a
*.recipe
*.FileListAbsolute.txt
.vs/*
Packaged/*
DebugData/*
@@ -49,3 +51,17 @@ SDL2-2.0.12/Makefile.rules
SDL2-2.0.12/sdl2.pc
SDL2-2.0.12/sdl2-config
install_manifest.txt
## macOS
.DS_Store
## Xcode projects
AerofoilMac/xcuserdata/
AerofoilMac/*.xcodeproj/xcuserdata/
AerofoilMac/build/
AerofoilMac/DerivedData/
*.xcuserstate
SDL2-2.0.12/Xcode/SDL/SDL.xcodeproj/xcuserdata/*
AerofoilMac/Resources/*.gpf
AerofoilMac/Resources/Houses/*.gpf
AerofoilMac/*.xcodeproj/project.xcworkspace/xcuserdata

4
.gitmodules vendored Normal file
View File

@@ -0,0 +1,4 @@
[submodule "AerofoilWeb/FileSaverDotJS"]
path = AerofoilWeb/FileSaverDotJS
url = https://github.com/eligrey/FileSaver.js.git
branch = master

66
.vscode/settings.json vendored Normal file
View File

@@ -0,0 +1,66 @@
{
"files.associations": {
"iostream": "cpp",
"array": "cpp",
"atomic": "cpp",
"bit": "cpp",
"*.tcc": "cpp",
"bitset": "cpp",
"cctype": "cpp",
"chrono": "cpp",
"clocale": "cpp",
"cmath": "cpp",
"codecvt": "cpp",
"compare": "cpp",
"complex": "cpp",
"concepts": "cpp",
"condition_variable": "cpp",
"cstdarg": "cpp",
"cstddef": "cpp",
"cstdint": "cpp",
"cstdio": "cpp",
"cstdlib": "cpp",
"cstring": "cpp",
"ctime": "cpp",
"cwchar": "cpp",
"cwctype": "cpp",
"deque": "cpp",
"map": "cpp",
"unordered_map": "cpp",
"vector": "cpp",
"exception": "cpp",
"algorithm": "cpp",
"functional": "cpp",
"iterator": "cpp",
"memory": "cpp",
"memory_resource": "cpp",
"numeric": "cpp",
"optional": "cpp",
"random": "cpp",
"ratio": "cpp",
"regex": "cpp",
"string": "cpp",
"string_view": "cpp",
"system_error": "cpp",
"tuple": "cpp",
"type_traits": "cpp",
"utility": "cpp",
"fstream": "cpp",
"initializer_list": "cpp",
"iosfwd": "cpp",
"istream": "cpp",
"limits": "cpp",
"mutex": "cpp",
"new": "cpp",
"ostream": "cpp",
"ranges": "cpp",
"shared_mutex": "cpp",
"sstream": "cpp",
"stdexcept": "cpp",
"stop_token": "cpp",
"streambuf": "cpp",
"thread": "cpp",
"cinttypes": "cpp",
"typeinfo": "cpp"
}
}

322
ASADTool/ASADTool.cpp Normal file
View File

@@ -0,0 +1,322 @@
#include "WindowsUnicodeToolShim.h"
#include "PLBigEndian.h"
#include "MacFileInfo.h"
#include "CombinedTimestamp.h"
#include "CFileStream.h"
#include "PLCore.h"
#include <algorithm>
// https://tools.ietf.org/rfc/rfc1740
int ProcessFork(FILE *f, uint32_t length, const char *basePath, const char *suffix)
{
const size_t kBufferSize = 4096;
uint8_t buffer[kBufferSize];
std::string combinedPath = std::string(basePath) + suffix;
FILE *outF = fopen_utf8(combinedPath.c_str(), "wb");
if (!outF)
{
fprintf(stderr, "Failed to open output file '%s'", combinedPath.c_str());
return -1;
}
while (length > 0)
{
const size_t amountToCopy = std::min<size_t>(length, kBufferSize);
if (fread(buffer, 1, amountToCopy, f) != amountToCopy)
{
fprintf(stderr, "Failed to copy data");
fclose(outF);
return -1;
}
if (fwrite(buffer, 1, amountToCopy, outF) != amountToCopy)
{
fprintf(stderr, "Failed to copy data");
fclose(outF);
return -1;
}
length -= static_cast<uint32_t>(amountToCopy);
}
fclose(outF);
return 0;
}
int ProcessFileDatesInfo(FILE *f, uint32_t length, PortabilityLayer::MacFileProperties &mfp, PortabilityLayer::CombinedTimestamp &ts)
{
struct ASFileDates
{
BEInt32_t m_created;
BEInt32_t m_modified;
BEInt32_t m_backup;
BEInt32_t m_access;
};
ASFileDates fileDates;
if (length < sizeof(fileDates))
{
fprintf(stderr, "File dates block was truncated");
return -1;
}
if (fread(&fileDates, 1, sizeof(fileDates), f) != sizeof(fileDates))
{
fprintf(stderr, "Failed to read file dates");
return -1;
}
const int64_t asEpochToMacEpoch = -3029547600LL;
// Mac epoch in Unix time: -2082844800
// ASAD epoch in Unix time: 946702800
mfp.m_createdTimeMacEpoch = static_cast<int64_t>(fileDates.m_created) + asEpochToMacEpoch;
mfp.m_modifiedTimeMacEpoch = static_cast<int64_t>(fileDates.m_modified) + asEpochToMacEpoch;
ts.SetMacEpochTime(mfp.m_modifiedTimeMacEpoch);
return 0;
}
int ProcessFinderInfo(FILE *f, uint32_t length, PortabilityLayer::MacFileProperties &mfp)
{
struct ASFinderInfo
{
uint8_t m_type[4];
uint8_t m_creator[4];
BEUInt16_t m_finderFlags;
BEPoint m_location;
BEUInt16_t m_folder; // ???
};
struct ASExtendedFinderInfo
{
BEUInt16_t m_iconID;
uint8_t m_unused[6];
uint8_t m_scriptCode;
uint8_t m_xFlags;
BEUInt16_t m_commentID;
BEUInt32_t m_putAwayDirectoryID;
};
ASFinderInfo finderInfo;
if (length < sizeof(finderInfo))
{
fprintf(stderr, "Finder Info block was truncated");
return -1;
}
if (fread(&finderInfo, 1, sizeof(finderInfo), f) != sizeof(finderInfo))
{
fprintf(stderr, "Failed to read Finder info");
return -1;
}
memcpy(mfp.m_fileCreator, finderInfo.m_creator, 4);
memcpy(mfp.m_fileType, finderInfo.m_type, 4);
mfp.m_finderFlags = finderInfo.m_finderFlags;
mfp.m_xPos = finderInfo.m_location.h;
mfp.m_yPos = finderInfo.m_location.v;
return 0;
}
int ProcessMacintoshFileInfo(FILE *f, uint32_t length, PortabilityLayer::MacFileProperties &mfp)
{
struct ASMacInfo
{
uint8_t m_filler[3];
uint8_t m_protected;
};
ASMacInfo macInfo;
if (length < sizeof(macInfo))
{
fprintf(stderr, "File dates block was truncated");
return -1;
}
if (fread(&macInfo, 1, sizeof(macInfo), f) != sizeof(macInfo))
{
fprintf(stderr, "Failed to read file dates");
return -1;
}
mfp.m_protected = macInfo.m_protected;
return 0;
}
int ProcessFile(FILE *f, const char *outPath, PortabilityLayer::CombinedTimestamp ts, bool isDouble)
{
struct ASHeader
{
BEUInt32_t m_version;
uint8_t m_filler[16];
BEUInt16_t m_numEntries;
};
struct ASEntry
{
BEUInt32_t m_entryID;
BEUInt32_t m_offset;
BEUInt32_t m_length;
};
ASHeader header;
if (fread(&header, 1, sizeof(header), f) != sizeof(header))
{
fprintf(stderr, "Failed to read header");
return -1;
}
const uint32_t numEntries = header.m_numEntries;
if (numEntries > 0xffff)
{
fprintf(stderr, "Too many entries");
return -1;
}
if (numEntries == 0)
return 0;
std::vector<ASEntry> entries;
entries.resize(static_cast<uint32_t>(numEntries));
PortabilityLayer::MacFileProperties mfp;
if (fread(&entries[0], 1, sizeof(ASEntry) * numEntries, f) != sizeof(ASEntry) * numEntries)
{
fprintf(stderr, "Failed to read entries");
return -1;
}
for (const ASEntry &asEntry : entries)
{
int fseekResult = fseek(f, asEntry.m_offset, SEEK_SET);
if (fseekResult != 0)
return fseekResult;
int rc = 0;
switch (static_cast<uint32_t>(asEntry.m_entryID))
{
case 1:
if (asEntry.m_length > 0)
rc = ProcessFork(f, asEntry.m_length, outPath, ".gpd");
break;
case 2:
if (asEntry.m_length > 0)
rc = ProcessFork(f, asEntry.m_length, outPath, ".gpr");
break;
case 4:
if (asEntry.m_length > 0)
rc = ProcessFork(f, asEntry.m_length, outPath, ".gpc");
break;
case 8:
rc = ProcessFileDatesInfo(f, asEntry.m_length, mfp, ts);
break;
case 9:
rc = ProcessFinderInfo(f, asEntry.m_length, mfp);
break;
case 10:
rc = ProcessMacintoshFileInfo(f, asEntry.m_length, mfp);
break;
case 3: // Real name
case 5: // B&W icon
case 6: // Color icon
case 11: // ProDOS file info
case 12: // MS-DOS file info
case 13: // AFP short name
case 14: // AFP file info
case 15: // AFP directory ID
break;
default:
fprintf(stderr, "Unknown entry type %i", static_cast<int>(static_cast<uint32_t>(asEntry.m_entryID)));
return -1;
}
if (rc != 0)
return rc;
}
PortabilityLayer::MacFilePropertiesSerialized mfps;
mfps.Serialize(mfp);
std::string gpfPath = std::string(outPath) + ".gpf";
FILE *gpfFile = fopen_utf8(gpfPath.c_str(), "wb");
if (!gpfFile)
{
fprintf(stderr, "Failed to open output gpf");
return -1;
}
PortabilityLayer::CFileStream gpfStream(gpfFile);
mfps.WriteAsPackage(gpfStream, ts);
gpfStream.Close();
return 0;
}
int toolMain(int argc, const char **argv)
{
BEUInt32_t magic;
if (argc != 4)
{
fprintf(stderr, "Usage: ASADTool <input> <timestamp.ts> <output>");
return -1;
}
PortabilityLayer::CombinedTimestamp ts;
FILE *tsFile = fopen_utf8(argv[2], "rb");
if (!tsFile)
{
fprintf(stderr, "Could not open timestamp file");
return -1;
}
if (fread(&ts, 1, sizeof(ts), tsFile) != sizeof(ts))
{
fprintf(stderr, "Could not read timestamp file");
return -1;
}
fclose(tsFile);
FILE *asadFile = fopen_utf8(argv[1], "rb");
if (!asadFile)
{
fprintf(stderr, "Could not open input file");
return -1;
}
if (fread(&magic, 1, 4, asadFile) != 4)
{
fprintf(stderr, "Could not read file magic");
return -1;
}
int returnCode = 0;
if (magic == 0x00051607)
returnCode = ProcessFile(asadFile, argv[3], ts, true);
else if (magic == 0x00051600)
returnCode = ProcessFile(asadFile, argv[3], ts, false);
else
{
fprintf(stderr, "Unknown file type %x", static_cast<int>(magic));
return -1;
}
fclose(asadFile);
return returnCode;
}

96
ASADTool/ASADTool.vcxproj Normal file
View File

@@ -0,0 +1,96 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>15.0</VCProjectVersion>
<ProjectGuid>{DF692F94-3A11-40E1-8846-9815B4DBBDB0}</ProjectGuid>
<RootNamespace>ASADTool</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\Debug.props" />
<Import Project="..\WindowsUnicodeToolShim.props" />
<Import Project="..\PortabilityLayer.props" />
<Import Project="..\GpCommon.props" />
<Import Project="..\Common.props" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\Release.props" />
<Import Project="..\WindowsUnicodeToolShim.props" />
<Import Project="..\PortabilityLayer.props" />
<Import Project="..\GpCommon.props" />
<Import Project="..\Common.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup />
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ProjectReference Include="..\PortabilityLayer\PortabilityLayer.vcxproj">
<Project>{6ec62b0f-9353-40a4-a510-3788f1368b33}</Project>
</ProjectReference>
<ProjectReference Include="..\WindowsUnicodeToolShim\WindowsUnicodeToolShim.vcxproj">
<Project>{15009625-1120-405e-8bba-69a16cd6713d}</Project>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<ClCompile Include="ASADTool.cpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;hm;inl;inc;ipp;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="ASADTool.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>

View File

@@ -48,6 +48,8 @@ Project("{930C7802-8A8C-48F9-8165-68863BCCD9DD}") = "ReleasePackageInstaller", "
{7EFF1E21-C375-45EA-A069-4E2232C8A72B} = {7EFF1E21-C375-45EA-A069-4E2232C8A72B}
{B852D549-4020-4477-8BFB-E199FF78B047} = {B852D549-4020-4477-8BFB-E199FF78B047}
{2FF15659-5C72-48B8-B55B-3C658E4125B5} = {2FF15659-5C72-48B8-B55B-3C658E4125B5}
{3B7FD18D-7A50-4DF5-AC25-543E539BFACE} = {3B7FD18D-7A50-4DF5-AC25-543E539BFACE}
{B31BFF9D-2D14-4B1A-A625-8348CC3D8D67} = {B31BFF9D-2D14-4B1A-A625-8348CC3D8D67}
{36DAF5FA-6ADB-4F20-9810-1610DE0AE653} = {36DAF5FA-6ADB-4F20-9810-1610DE0AE653}
EndProjectSection
EndProject
@@ -67,6 +69,10 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GenerateFonts", "GenerateFo
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bin2h", "bin2h\bin2h.vcxproj", "{D045F28D-F245-44DD-B576-CC91BF3BE6E9}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "HouseTool", "HouseTool\HouseTool.vcxproj", "{B31BFF9D-2D14-4B1A-A625-8348CC3D8D67}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ASADTool", "ASADTool\ASADTool.vcxproj", "{DF692F94-3A11-40E1-8846-9815B4DBBDB0}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
@@ -187,6 +193,14 @@ Global
{D045F28D-F245-44DD-B576-CC91BF3BE6E9}.Debug|x64.Build.0 = Debug|x64
{D045F28D-F245-44DD-B576-CC91BF3BE6E9}.Release|x64.ActiveCfg = Release|x64
{D045F28D-F245-44DD-B576-CC91BF3BE6E9}.Release|x64.Build.0 = Release|x64
{B31BFF9D-2D14-4B1A-A625-8348CC3D8D67}.Debug|x64.ActiveCfg = Debug|x64
{B31BFF9D-2D14-4B1A-A625-8348CC3D8D67}.Debug|x64.Build.0 = Debug|x64
{B31BFF9D-2D14-4B1A-A625-8348CC3D8D67}.Release|x64.ActiveCfg = Release|x64
{B31BFF9D-2D14-4B1A-A625-8348CC3D8D67}.Release|x64.Build.0 = Release|x64
{DF692F94-3A11-40E1-8846-9815B4DBBDB0}.Debug|x64.ActiveCfg = Debug|x64
{DF692F94-3A11-40E1-8846-9815B4DBBDB0}.Debug|x64.Build.0 = Debug|x64
{DF692F94-3A11-40E1-8846-9815B4DBBDB0}.Release|x64.ActiveCfg = Release|x64
{DF692F94-3A11-40E1-8846-9815B4DBBDB0}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

@@ -14,19 +14,19 @@
<VCProjectVersion>15.0</VCProjectVersion>
<ProjectGuid>{0E383EF0-CEF7-4733-87C6-5AC9844AA1EF}</ProjectGuid>
<RootNamespace>Aerofoil</RootNamespace>
<WindowsTargetPlatformVersion>10.0.17763.0</WindowsTargetPlatformVersion>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
@@ -43,6 +43,7 @@
<Import Project="..\GpMainApp.props" />
<Import Project="..\GpShell.props" />
<Import Project="..\Debug.props" />
<Import Project="..\AerofoilPortable.props" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
@@ -52,6 +53,7 @@
<Import Project="..\GpMainApp.props" />
<Import Project="..\Release.props" />
<Import Project="..\GpShell.props" />
<Import Project="..\AerofoilPortable.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup />
@@ -82,6 +84,7 @@
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\AerofoilPortable\GpAllocator_C.cpp" />
<ClCompile Include="GpBWCursor_Win32.cpp" />
<ClCompile Include="GpColorCursor_Win32.cpp" />
<ClCompile Include="GpFileStream_Win32.cpp" />
@@ -100,6 +103,8 @@
<ClInclude Include="..\GpCommon\GpDisplayDriverTickStatus.h" />
<ClInclude Include="..\GpCommon\GpFileCreationDisposition.h" />
<ClInclude Include="..\GpCommon\GpInputDriverProperties.h" />
<ClInclude Include="..\GpCommon\GpString.h" />
<ClInclude Include="..\GpCommon\GpVector.h" />
<ClInclude Include="..\GpCommon\IGpCursor.h" />
<ClInclude Include="..\GpCommon\IGpAudioChannelCallbacks.h" />
<ClInclude Include="..\GpCommon\IGpDisplayDriverSurface.h" />

View File

@@ -28,6 +28,9 @@
<ClCompile Include="GpBWCursor_Win32.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\AerofoilPortable\GpAllocator_C.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\GpCommon\EGpInputDriverType.h">
@@ -90,6 +93,12 @@
<ClInclude Include="GpBWCursor_Win32.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\GpCommon\GpVector.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\GpCommon\GpString.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<Image Include="ConvertedResources\Large128.ico">

View File

@@ -21,6 +21,7 @@
#include "GpBWCursor_Win32.h"
#include "GpWindows.h"
#include "IGpAllocator.h"
#include <stdint.h>
#include <stdlib.h>
@@ -34,19 +35,19 @@ void GpBWCursor_Win32::Destroy()
this->DecRef();
}
IGpCursor_Win32 *GpBWCursor_Win32::Create(size_t width, size_t height, const void *pixelData, const void *maskData, size_t hotSpotX, size_t hotSpotY)
IGpCursor_Win32 *GpBWCursor_Win32::Create(IGpAllocator *alloc, size_t width, size_t height, const void *pixelData, const void *maskData, size_t hotSpotX, size_t hotSpotY)
{
size_t numBits = width * height;
size_t numBytes = (width * height + 7) / 8;
uint8_t *convertedAndData = static_cast<uint8_t*>(malloc(numBytes));
uint8_t *convertedXorData = static_cast<uint8_t*>(malloc(numBytes));
size_t numBytes = (numBits + 7) / 8;
uint8_t *convertedAndData = static_cast<uint8_t*>(alloc->Alloc(numBytes));
uint8_t *convertedXorData = static_cast<uint8_t*>(alloc->Alloc(numBytes));
if (!convertedAndData || !convertedXorData)
{
if (convertedAndData)
free(convertedAndData);
alloc->Release(convertedAndData);
if (convertedXorData)
free(convertedXorData);
alloc->Release(convertedXorData);
return nullptr;
}
@@ -62,25 +63,26 @@ IGpCursor_Win32 *GpBWCursor_Win32::Create(size_t width, size_t height, const voi
HCURSOR hcursor = CreateCursor(g_gpWindowsGlobals.m_hInstance, static_cast<int>(hotSpotX), static_cast<int>(hotSpotY), static_cast<int>(width), static_cast<int>(height), convertedAndData, convertedXorData);
free(convertedAndData);
free(convertedXorData);
alloc->Release(convertedAndData);
alloc->Release(convertedXorData);
if (!hcursor)
return nullptr;
void *storage = malloc(sizeof(GpBWCursor_Win32));
void *storage = alloc->Alloc(sizeof(GpBWCursor_Win32));
if (!storage)
{
DestroyCursor(hcursor);
return nullptr;
}
return new (storage) GpBWCursor_Win32(hcursor);
return new (storage) GpBWCursor_Win32(hcursor, alloc);
}
GpBWCursor_Win32::GpBWCursor_Win32(HCURSOR cursor)
GpBWCursor_Win32::GpBWCursor_Win32(HCURSOR cursor, IGpAllocator *alloc)
: m_cursor(cursor)
, m_refCount(1)
, m_alloc(alloc)
{
}
@@ -104,7 +106,8 @@ void GpBWCursor_Win32::DecRef()
m_refCount--;
if (m_refCount == 0)
{
IGpAllocator *alloc = m_alloc;
this->~GpBWCursor_Win32();
free(this);
alloc->Release(this);
}
}

View File

@@ -3,6 +3,8 @@
#include "IGpCursor_Win32.h"
#include "GpWindows.h"
struct IGpAllocator;
class GpBWCursor_Win32 final : public IGpCursor_Win32
{
public:
@@ -13,12 +15,13 @@ public:
void IncRef() override;
void DecRef() override;
static IGpCursor_Win32 *Create(size_t width, size_t height, const void *pixelData, const void *maskData, size_t hotSpotX, size_t hotSpotY);
static IGpCursor_Win32 *Create(IGpAllocator *alloc, size_t width, size_t height, const void *pixelData, const void *maskData, size_t hotSpotX, size_t hotSpotY);
private:
GpBWCursor_Win32(HCURSOR cursor);
GpBWCursor_Win32(HCURSOR cursor, IGpAllocator *alloc);
~GpBWCursor_Win32();
HCURSOR m_cursor;
int m_refCount;
IGpAllocator *m_alloc;
};

View File

@@ -20,6 +20,7 @@
*/
#include "GpColorCursor_Win32.h"
#include "IGpAllocator.h"
#include <stdint.h>
#include <stdlib.h>
@@ -31,7 +32,7 @@ void GpColorCursor_Win32::Destroy()
this->DecRef();
}
IGpCursor_Win32 *GpColorCursor_Win32::Create(size_t width, size_t height, const void *pixelDataRGBA, size_t hotSpotX, size_t hotSpotY)
IGpCursor_Win32 *GpColorCursor_Win32::Create(IGpAllocator *alloc, size_t width, size_t height, const void *pixelDataRGBA, size_t hotSpotX, size_t hotSpotY)
{
const size_t paddingBits = (sizeof(void*) * 8);
@@ -52,7 +53,7 @@ IGpCursor_Win32 *GpColorCursor_Win32::Create(size_t width, size_t height, const
size_t maskPitch = width + paddingBits - 1;
maskPitch -= maskPitch % paddingBits;
LPVOID maskBits = malloc(maskPitch * height);
LPVOID maskBits = alloc->Alloc(maskPitch * height);
if (!maskBits)
return nullptr;
@@ -71,6 +72,8 @@ IGpCursor_Win32 *GpColorCursor_Win32::Create(size_t width, size_t height, const
ii.hbmMask = CreateBitmap(width, height, 1, 1, maskBits);
ReleaseDC(NULL, hdc);
alloc->Release(maskBits);
size_t cursorPitch = width * 4;
size_t numPixels = width * height;
@@ -90,19 +93,20 @@ IGpCursor_Win32 *GpColorCursor_Win32::Create(size_t width, size_t height, const
if (!hicon)
return nullptr;
void *storage = malloc(sizeof(GpColorCursor_Win32));
void *storage = alloc->Alloc(sizeof(GpColorCursor_Win32));
if (!storage)
{
DestroyIcon(hicon);
return nullptr;
}
return new (storage) GpColorCursor_Win32(reinterpret_cast<HCURSOR>(hicon));
return new (storage) GpColorCursor_Win32(alloc, reinterpret_cast<HCURSOR>(hicon));
}
GpColorCursor_Win32::GpColorCursor_Win32(HCURSOR cursor)
GpColorCursor_Win32::GpColorCursor_Win32(IGpAllocator *alloc, HCURSOR cursor)
: m_cursor(cursor)
, m_refCount(1)
, m_alloc(alloc)
{
}
@@ -126,7 +130,8 @@ void GpColorCursor_Win32::DecRef()
m_refCount--;
if (m_refCount == 0)
{
IGpAllocator *alloc = m_alloc;
this->~GpColorCursor_Win32();
free(this);
alloc->Release(this);
}
}

View File

@@ -3,6 +3,7 @@
#include "IGpCursor_Win32.h"
#include "GpWindows.h"
struct IGpAllocator;
class GpColorCursor_Win32 final : public IGpCursor_Win32
{
@@ -14,12 +15,13 @@ public:
void IncRef() override;
void DecRef() override;
static IGpCursor_Win32 *Create(size_t width, size_t height, const void *pixelDataRGBA, size_t hotSpotX, size_t hotSpotY);
static IGpCursor_Win32 *Create(IGpAllocator *alloc, size_t width, size_t height, const void *pixelDataRGBA, size_t hotSpotX, size_t hotSpotY);
private:
GpColorCursor_Win32(HCURSOR cursor);
GpColorCursor_Win32(IGpAllocator *alloc, HCURSOR cursor);
~GpColorCursor_Win32();
HCURSOR m_cursor;
int m_refCount;
IGpAllocator *m_alloc;
};

View File

@@ -1,13 +1,32 @@
#include "GpFileStream_Win32.h"
#include "IGpAllocator.h"
GpFileStream_Win32::GpFileStream_Win32(HANDLE handle, bool readable, bool writeable, bool seekable)
: m_handle(handle)
#include <new>
GpFileStream_Win32::GpFileStream_Win32(IGpAllocator *alloc, HANDLE handle, bool readable, bool writeable, bool seekable)
: m_alloc(alloc)
, m_handle(handle)
, m_readable(readable)
, m_writeable(writeable)
, m_seekable(seekable)
{
}
GpFileStream_Win32 *GpFileStream_Win32::Create(IGpAllocator *alloc, HANDLE handle, bool readable, bool writeable, bool seekable)
{
void *storage = alloc->Alloc(sizeof(GpFileStream_Win32));
if (!storage)
return nullptr;
return new (storage) GpFileStream_Win32(alloc, handle, readable, writeable, seekable);
}
GpFileStream_Win32::~GpFileStream_Win32()
{
CloseHandle(m_handle);
}
size_t GpFileStream_Win32::Read(void *bytesOut, size_t size)
{
if (!m_readable)
@@ -122,7 +141,10 @@ GpUFilePos_t GpFileStream_Win32::Tell() const
void GpFileStream_Win32::Close()
{
CloseHandle(m_handle);
IGpAllocator *alloc = m_alloc;
this->~GpFileStream_Win32();
alloc->Release(this);
}
void GpFileStream_Win32::Flush()

View File

@@ -7,7 +7,7 @@
class GpFileStream_Win32 final : public GpIOStream
{
public:
explicit GpFileStream_Win32(HANDLE handle, bool readable, bool writeable, bool seekable);
~GpFileStream_Win32();
size_t Read(void *bytesOut, size_t size) override;
size_t Write(const void *bytes, size_t size) override;
@@ -19,10 +19,19 @@ public:
bool SeekEnd(GpUFilePos_t loc) override;
GpUFilePos_t Size() const override;
GpUFilePos_t Tell() const override;
void Close() override;
void GP_ASYNCIFY_PARANOID_NAMED(Close)() override;
void Flush() override;
#if GP_ASYNCIFY_PARANOID
void Close();
#endif
static GpFileStream_Win32 *Create(IGpAllocator *alloc, HANDLE handle, bool readable, bool writeable, bool seekable);
private:
GpFileStream_Win32(IGpAllocator *alloc, HANDLE handle, bool readable, bool writeable, bool seekable);
IGpAllocator *m_alloc;
HANDLE m_handle;
bool m_readable;
bool m_writeable;

View File

@@ -1,44 +1,49 @@
#include "GpFileSystem_Win32.h"
#include "GpAllocator_C.h"
#include "GpApplicationName.h"
#include "GpFileStream_Win32.h"
#include "GpWindows.h"
#include "IGpAllocator.h"
#include "IGpDirectoryCursor.h"
#include <string>
#include <Shlwapi.h>
#include <ShlObj.h>
#include <commdlg.h>
#include <assert.h>
struct IGpAllocator;
extern GpWindowsGlobals g_gpWindowsGlobals;
class GpDirectoryCursor_Win32 final : public IGpDirectoryCursor
{
public:
static GpDirectoryCursor_Win32 *Create(const HANDLE &handle, const WIN32_FIND_DATAW &findData);
static GpDirectoryCursor_Win32 *Create(IGpAllocator *alloc, const HANDLE &handle, const WIN32_FIND_DATAW &findData);
bool GetNext(const char *&outFileName) override;
void Destroy() override;
private:
GpDirectoryCursor_Win32(const HANDLE &handle, const WIN32_FIND_DATAW &findData);
GpDirectoryCursor_Win32(IGpAllocator *alloc, const HANDLE &handle, const WIN32_FIND_DATAW &findData);
~GpDirectoryCursor_Win32();
IGpAllocator *m_alloc;
HANDLE m_handle;
WIN32_FIND_DATAW m_findData;
char m_chars[MAX_PATH + 1];
bool m_haveNext;
};
GpDirectoryCursor_Win32 *GpDirectoryCursor_Win32::Create(const HANDLE &handle, const WIN32_FIND_DATAW &findData)
GpDirectoryCursor_Win32 *GpDirectoryCursor_Win32::Create(IGpAllocator *alloc, const HANDLE &handle, const WIN32_FIND_DATAW &findData)
{
void *storage = malloc(sizeof(GpDirectoryCursor_Win32));
void *storage = alloc->Alloc(sizeof(GpDirectoryCursor_Win32));
if (!storage)
return nullptr;
return new (storage) GpDirectoryCursor_Win32(handle, findData);
return new (storage) GpDirectoryCursor_Win32(alloc, handle, findData);
}
bool GpDirectoryCursor_Win32::GetNext(const char *&outFileName)
@@ -82,14 +87,16 @@ bool GpDirectoryCursor_Win32::GetNext(const char *&outFileName)
void GpDirectoryCursor_Win32::Destroy()
{
IGpAllocator *alloc = m_alloc;
this->~GpDirectoryCursor_Win32();
free(this);
alloc->Release(this);
}
GpDirectoryCursor_Win32::GpDirectoryCursor_Win32(const HANDLE &handle, const WIN32_FIND_DATAW &findData)
GpDirectoryCursor_Win32::GpDirectoryCursor_Win32(IGpAllocator *alloc, const HANDLE &handle, const WIN32_FIND_DATAW &findData)
: m_handle(handle)
, m_findData(findData)
, m_haveNext(true)
, m_alloc(alloc)
{
}
@@ -98,47 +105,76 @@ GpDirectoryCursor_Win32::~GpDirectoryCursor_Win32()
FindClose(m_handle);
}
GpFileSystem_Win32::GpFileSystem_Win32()
GpFileSystem_Win32::GpFileSystem_Win32(IGpAllocator *alloc)
: m_alloc(alloc)
, m_prefsDir(alloc)
, m_scoresDir(alloc)
, m_packagedDir(alloc)
, m_housesDir(alloc)
, m_logsDir(alloc)
, m_userHousesDir(alloc)
, m_userSavesDir(alloc)
, m_resourcesDir(alloc)
, m_exportDir(alloc)
{
// GP TODO: This shouldn't be static init since it allocates memory
m_executablePath[0] = 0;
}
void GpFileSystem_Win32::Destroy()
{
IGpAllocator *alloc = m_alloc;
this->~GpFileSystem_Win32();
alloc->Release(this);
}
bool GpFileSystem_Win32::Init()
{
PWSTR docsPath;
if (!FAILED(SHGetKnownFolderPath(FOLDERID_Documents, KF_FLAG_DEFAULT, nullptr, &docsPath)))
if (FAILED(SHGetKnownFolderPath(FOLDERID_Documents, KF_FLAG_DEFAULT, nullptr, &docsPath)))
return false;
if (!m_prefsDir.Set(docsPath))
{
try
{
m_prefsDir = docsPath;
}
catch(...)
{
CoTaskMemFree(docsPath);
throw;
}
m_prefsDir.append(L"\\" GP_APPLICATION_NAME_W);
m_userHousesDir = m_prefsDir + L"\\Houses";
m_userSavesDir = m_prefsDir + L"\\SavedGames";
m_scoresDir = m_prefsDir + L"\\Scores";
m_logsDir = m_prefsDir + L"\\Logs";
m_fontCacheDir = m_prefsDir + L"\\FontCache";
CreateDirectoryW(m_prefsDir.c_str(), nullptr);
CreateDirectoryW(m_scoresDir.c_str(), nullptr);
CreateDirectoryW(m_userHousesDir.c_str(), nullptr);
CreateDirectoryW(m_userSavesDir.c_str(), nullptr);
CreateDirectoryW(m_logsDir.c_str(), nullptr);
CreateDirectoryW(m_fontCacheDir.c_str(), nullptr);
m_prefsDir.append(L"\\");
m_scoresDir.append(L"\\");
m_userHousesDir.append(L"\\");
m_userSavesDir.append(L"\\");
m_logsDir.append(L"\\");
m_fontCacheDir.append(L"\\");
CoTaskMemFree(docsPath);
return false;
}
CoTaskMemFree(docsPath);
if (!m_prefsDir.Append(L"\\" GP_APPLICATION_NAME_W))
return false;
if (!m_userHousesDir.Set(m_prefsDir) || !m_userHousesDir.Append(L"\\Houses"))
return false;
if (!m_userSavesDir.Set(m_prefsDir) || !m_userSavesDir.Append(L"\\SavedGames"))
return false;
if (!m_scoresDir.Set(m_prefsDir) || !m_scoresDir.Append(L"\\Scores"))
return false;
if (!m_logsDir.Set(m_prefsDir) || !m_logsDir.Append(L"\\Logs"))
return false;
if (!m_exportDir.Set(m_prefsDir) || !m_exportDir.Append(L"\\Export"))
return false;
CreateDirectoryW(m_prefsDir.Buffer(), nullptr);
CreateDirectoryW(m_scoresDir.Buffer(), nullptr);
CreateDirectoryW(m_userHousesDir.Buffer(), nullptr);
CreateDirectoryW(m_userSavesDir.Buffer(), nullptr);
CreateDirectoryW(m_logsDir.Buffer(), nullptr);
CreateDirectoryW(m_exportDir.Buffer(), nullptr);
if (!m_prefsDir.Append(L"\\") ||
!m_scoresDir.Append(L"\\") ||
!m_userHousesDir.Append(L"\\") ||
!m_userSavesDir.Append(L"\\") ||
!m_logsDir.Append(L"\\") ||
!m_resourcesDir.Append(L"\\") ||
!m_exportDir.Append(L"\\"))
return false;
DWORD modulePathSize = GetModuleFileNameW(nullptr, m_executablePath, MAX_PATH);
if (modulePathSize == MAX_PATH || modulePathSize == 0)
m_executablePath[0] = 0;
@@ -173,11 +209,19 @@ GpFileSystem_Win32::GpFileSystem_Win32()
currentPathLength--;
}
if (currentPathLength > 0)
{
m_packagedDir = std::wstring(m_executablePath) + L"Packaged\\";
m_housesDir = std::wstring(m_executablePath) + L"Packaged\\Houses\\";
}
if (currentPathLength == 0)
return false;
if (!m_packagedDir.Set(m_executablePath) || !m_packagedDir.Append(L"Packaged\\"))
return false;
if (!m_housesDir.Set(m_executablePath) || !m_housesDir.Append(L"Packaged\\Houses\\"))
return false;
if (!m_resourcesDir.Set(m_executablePath) || !m_resourcesDir.Append(L"Resources\\"))
return false;
return true;
}
bool GpFileSystem_Win32::FileExists(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *path)
@@ -216,7 +260,7 @@ GpIOStream *GpFileSystem_Win32::OpenFileNested(PortabilityLayer::VirtualDirector
wchar_t winPath[MAX_PATH + 1];
if (!ResolvePath(virtualDirectory, paths, numPaths, winPath))
return false;
return nullptr;
const DWORD desiredAccess = writeAccess ? (GENERIC_WRITE | GENERIC_READ) : GENERIC_READ;
DWORD winCreationDisposition = 0;
@@ -239,14 +283,14 @@ GpIOStream *GpFileSystem_Win32::OpenFileNested(PortabilityLayer::VirtualDirector
winCreationDisposition = TRUNCATE_EXISTING;
break;
default:
return false;
return nullptr;
}
HANDLE h = CreateFileW(winPath, desiredAccess, FILE_SHARE_READ, nullptr, winCreationDisposition, FILE_ATTRIBUTE_NORMAL, nullptr);
if (h == INVALID_HANDLE_VALUE)
return false;
return nullptr;
return new GpFileStream_Win32(h, true, writeAccess, true);
return GpFileStream_Win32::Create(m_alloc, h, true, writeAccess, true);
}
bool GpFileSystem_Win32::DeleteFile(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *path, bool &existed)
@@ -275,7 +319,7 @@ IGpDirectoryCursor *GpFileSystem_Win32::ScanDirectoryNested(PortabilityLayer::Vi
{
wchar_t winPath[MAX_PATH + 2];
const char **expandedPaths = static_cast<const char**>(malloc(sizeof(const char*) * (numPaths + 1)));
const char **expandedPaths = static_cast<const char**>(m_alloc->Alloc(sizeof(const char*) * (numPaths + 1)));
if (!expandedPaths)
return nullptr;
@@ -284,7 +328,7 @@ IGpDirectoryCursor *GpFileSystem_Win32::ScanDirectoryNested(PortabilityLayer::Vi
expandedPaths[numPaths] = "*";
const bool isPathResolved = ResolvePath(virtualDirectory, expandedPaths, numPaths + 1, winPath);
free(expandedPaths);
m_alloc->Release(expandedPaths);
if (!isPathResolved)
return nullptr;
@@ -295,7 +339,7 @@ IGpDirectoryCursor *GpFileSystem_Win32::ScanDirectoryNested(PortabilityLayer::Vi
if (ff == INVALID_HANDLE_VALUE)
return nullptr;
return GpDirectoryCursor_Win32::Create(ff, findData);
return GpDirectoryCursor_Win32::Create(m_alloc, ff, findData);
}
bool GpFileSystem_Win32::ValidateFilePathUnicodeChar(uint32_t c) const
@@ -418,9 +462,27 @@ const wchar_t *GpFileSystem_Win32::GetBasePath() const
return m_executablePath;
}
GpFileSystem_Win32 *GpFileSystem_Win32::CreateInstance(IGpAllocator *alloc)
{
void *storage = alloc->Alloc(sizeof(GpFileSystem_Win32));
if (!storage)
return nullptr;
GpFileSystem_Win32 *fs = new (storage) GpFileSystem_Win32(alloc);
if (!fs->Init())
{
fs->Destroy();
return nullptr;
}
ms_instance = fs;
return fs;
}
GpFileSystem_Win32 *GpFileSystem_Win32::GetInstance()
{
return &ms_instance;
return ms_instance;
}
bool GpFileSystem_Win32::ResolvePath(PortabilityLayer::VirtualDirectory_t virtualDirectory, char const* const* paths, size_t numPaths, wchar_t *outPath)
@@ -430,31 +492,31 @@ bool GpFileSystem_Win32::ResolvePath(PortabilityLayer::VirtualDirectory_t virtua
switch (virtualDirectory)
{
case PortabilityLayer::VirtualDirectories::kApplicationData:
baseDir = m_packagedDir.c_str();
baseDir = m_packagedDir.Buffer();
break;
case PortabilityLayer::VirtualDirectories::kGameData:
baseDir = m_housesDir.c_str();
baseDir = m_housesDir.Buffer();
break;
case PortabilityLayer::VirtualDirectories::kUserData:
baseDir = m_userHousesDir.c_str();
baseDir = m_userHousesDir.Buffer();
break;
case PortabilityLayer::VirtualDirectories::kUserSaves:
baseDir = m_userSavesDir.c_str();
baseDir = m_userSavesDir.Buffer();
break;
case PortabilityLayer::VirtualDirectories::kPrefs:
baseDir = m_prefsDir.c_str();
baseDir = m_prefsDir.Buffer();
break;
case PortabilityLayer::VirtualDirectories::kFonts:
baseDir = m_resourcesDir.c_str();
baseDir = m_resourcesDir.Buffer();
break;
case PortabilityLayer::VirtualDirectories::kHighScores:
baseDir = m_scoresDir.c_str();
baseDir = m_scoresDir.Buffer();
break;
case PortabilityLayer::VirtualDirectories::kLogs:
baseDir = m_logsDir.c_str();
baseDir = m_logsDir.Buffer();
break;
case PortabilityLayer::VirtualDirectories::kFontCache:
baseDir = m_fontCacheDir.c_str();
case PortabilityLayer::VirtualDirectories::kSourceExport:
baseDir = m_exportDir.Buffer();
break;
default:
return false;
@@ -500,4 +562,4 @@ bool GpFileSystem_Win32::ResolvePath(PortabilityLayer::VirtualDirectory_t virtua
return true;
}
GpFileSystem_Win32 GpFileSystem_Win32::ms_instance;
GpFileSystem_Win32 *GpFileSystem_Win32::ms_instance;

View File

@@ -4,13 +4,14 @@
#include "GpCoreDefs.h"
#include "GpWindows.h"
#include <string>
#include "GpString.h"
class GpFileSystem_Win32 final : public IGpFileSystem
{
public:
GpFileSystem_Win32();
explicit GpFileSystem_Win32(IGpAllocator *alloc);
void Destroy();
bool FileExists(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *path) override;
bool FileLocked(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *path, bool &exists) override;
@@ -25,21 +26,26 @@ public:
const wchar_t *GetBasePath() const;
static GpFileSystem_Win32 *CreateInstance(IGpAllocator *alloc);
static GpFileSystem_Win32 *GetInstance();
private:
bool Init();
bool ResolvePath(PortabilityLayer::VirtualDirectory_t virtualDirectory, char const* const* paths, size_t numPaths, wchar_t *outPath);
std::wstring m_prefsDir;
std::wstring m_scoresDir;
std::wstring m_packagedDir;
std::wstring m_housesDir;
std::wstring m_logsDir;
std::wstring m_userHousesDir;
std::wstring m_userSavesDir;
std::wstring m_resourcesDir;
std::wstring m_fontCacheDir;
GpWString m_prefsDir;
GpWString m_scoresDir;
GpWString m_packagedDir;
GpWString m_housesDir;
GpWString m_logsDir;
GpWString m_userHousesDir;
GpWString m_userSavesDir;
GpWString m_resourcesDir;
GpWString m_exportDir;
wchar_t m_executablePath[MAX_PATH];
static GpFileSystem_Win32 ms_instance;
IGpAllocator *m_alloc;
static GpFileSystem_Win32 *ms_instance;
};

View File

@@ -1,3 +1,4 @@
#include "GpAllocator_C.h"
#include "GpLogDriver_Win32.h"
#include "GpFileSystem_Win32.h"
@@ -7,6 +8,7 @@
GpLogDriver_Win32::GpLogDriver_Win32()
: m_stream(nullptr)
, m_isInitialized(false)
, m_alloc(GpAllocator_C::GetInstance())
{
}
@@ -58,14 +60,14 @@ void GpLogDriver_Win32::VPrintf(Category category, const char *fmt, va_list args
if (formattedSize <= 0)
return;
char *charBuff = static_cast<char*>(malloc(formattedSize + 1));
char *charBuff = static_cast<char*>(m_alloc->Alloc(formattedSize + 1));
if (!charBuff)
return;
vsnprintf(charBuff, formattedSize + 1, fmt, args);
m_stream->Write(charBuff, formattedSize);
free(charBuff);
m_alloc->Release(charBuff);
}
m_stream->Write("\n", 1);

View File

@@ -3,6 +3,7 @@
#include "IGpLogDriver.h"
class GpIOStream;
struct IGpAllocator;
class GpLogDriver_Win32 : public IGpLogDriver
{
@@ -20,6 +21,7 @@ private:
void InitInternal();
GpIOStream *m_stream;
IGpAllocator *m_alloc;
bool m_isInitialized;
static GpLogDriver_Win32 ms_instance;

View File

@@ -1,4 +1,5 @@
#include "GpMain.h"
#include "GpAllocator_C.h"
#include "GpAudioDriverFactory.h"
#include "GpBWCursor_Win32.h"
#include "GpColorCursor_Win32.h"
@@ -403,6 +404,13 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
int nArgs;
LPWSTR *cmdLineArgs = CommandLineToArgvW(cmdLine, &nArgs);
IGpAllocator *alloc = GpAllocator_C::GetInstance();
// Init file system first since logging may depend on it
GpFileSystem_Win32 *fs = GpFileSystem_Win32::CreateInstance(alloc);
if (!fs)
return -1;
for (int i = 1; i < nArgs; i++)
{
if (!wcscmp(cmdLineArgs[i], L"-diagnostics"))
@@ -410,12 +418,14 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
}
IGpLogDriver *logger = GpLogDriver_Win32::GetInstance();
IGpSystemServices *sysServices = GpSystemServices_Win32::GetInstance();
GpDriverCollection *drivers = GpAppInterface_Get()->PL_GetDriverCollection();
drivers->SetDriver<GpDriverIDs::kFileSystem>(GpFileSystem_Win32::GetInstance());
drivers->SetDriver<GpDriverIDs::kSystemServices>(GpSystemServices_Win32::GetInstance());
drivers->SetDriver<GpDriverIDs::kLog>(GpLogDriver_Win32::GetInstance());
drivers->SetDriver<GpDriverIDs::kSystemServices>(sysServices);
drivers->SetDriver<GpDriverIDs::kLog>(logger);
drivers->SetDriver<GpDriverIDs::kAlloc>(alloc);
g_gpWindowsGlobals.m_hInstance = hInstance;
g_gpWindowsGlobals.m_hPrevInstance = hPrevInstance;
@@ -448,7 +458,8 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
g_gpGlobalConfig.m_osGlobals = &g_gpWindowsGlobals;
g_gpGlobalConfig.m_logger = logger;
g_gpGlobalConfig.m_systemServices = GpSystemServices_Win32::GetInstance();
g_gpGlobalConfig.m_systemServices = sysServices;
g_gpGlobalConfig.m_allocator = alloc;
GpDisplayDriverFactory::RegisterDisplayDriverFactory(EGpDisplayDriverType_D3D11, GpDriver_CreateDisplayDriver_D3D11);
GpAudioDriverFactory::RegisterAudioDriverFactory(EGpAudioDriverType_XAudio2, GpDriver_CreateAudioDriver_XAudio2);
@@ -464,5 +475,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
LocalFree(cmdLineArgs);
fs->Destroy();
return returnCode;
}

View File

@@ -1,5 +1,6 @@
#include "GpMutex_Win32.h"
#include "IGpAllocator.h"
#include "GpWindows.h"
#include <stdlib.h>
@@ -7,8 +8,9 @@
void GpMutex_Win32::Destroy()
{
IGpAllocator *alloc = m_alloc;
this->~GpMutex_Win32();
free(this);
alloc->Release(this);
}
void GpMutex_Win32::Lock()
@@ -22,16 +24,17 @@ void GpMutex_Win32::Unlock()
}
GpMutex_Win32 *GpMutex_Win32::Create()
GpMutex_Win32 *GpMutex_Win32::Create(IGpAllocator *alloc)
{
void *storage = malloc(sizeof(GpMutex_Win32));
void *storage = alloc->Alloc(sizeof(GpMutex_Win32));
if (!storage)
return nullptr;
return new (storage) GpMutex_Win32();
return new (storage) GpMutex_Win32(alloc);
}
GpMutex_Win32::GpMutex_Win32()
GpMutex_Win32::GpMutex_Win32(IGpAllocator *alloc)
: m_alloc(alloc)
{
InitializeCriticalSection(&m_critSection);
}

View File

@@ -4,6 +4,8 @@
#include "GpWindows.h"
struct IGpAllocator;
class GpMutex_Win32 final : public IGpMutex
{
public:
@@ -11,11 +13,12 @@ public:
void Lock() override;
void Unlock() override;
static GpMutex_Win32 *Create();
static GpMutex_Win32 *Create(IGpAllocator *alloc);
private:
const GpMutex_Win32();
explicit GpMutex_Win32(IGpAllocator *alloc);
~GpMutex_Win32();
CRITICAL_SECTION m_critSection;
IGpAllocator *m_alloc;
};

View File

@@ -2,11 +2,11 @@
#include "GpMutex_Win32.h"
#include "GpThreadEvent_Win32.h"
#include "GpWindows.h"
#include "GpAllocator_C.h"
#include "IGpClipboardContents.h"
#include "UTF16.h"
#include "UTF8.h"
#include "GpUnicode.h"
#include <assert.h>
#include <vector>
@@ -134,6 +134,7 @@ static DWORD WINAPI StaticStartThread(LPVOID lpThreadParameter)
GpSystemServices_Win32::GpSystemServices_Win32()
: m_isTouchscreenSimulation(false)
, m_alloc(GpAllocator_C::GetInstance())
{
}
@@ -181,17 +182,17 @@ void GpSystemServices_Win32::GetLocalDateTime(unsigned int &year, unsigned int &
IGpMutex *GpSystemServices_Win32::CreateMutex()
{
return GpMutex_Win32::Create();
return GpMutex_Win32::Create(m_alloc);
}
IGpMutex *GpSystemServices_Win32::CreateRecursiveMutex()
{
return GpMutex_Win32::Create();
return GpMutex_Win32::Create(m_alloc);
}
IGpThreadEvent *GpSystemServices_Win32::CreateThreadEvent(bool autoReset, bool startSignaled)
{
return GpThreadEvent_Win32::Create(autoReset, startSignaled);
return GpThreadEvent_Win32::Create(m_alloc, autoReset, startSignaled);
}
void *GpSystemServices_Win32::CreateThread(ThreadFunc_t threadFunc, void *context)
@@ -231,9 +232,10 @@ uint64_t GpSystemServices_Win32::GetFreeMemoryCosmetic() const
return memStatus.ullAvailPhys;
}
void GpSystemServices_Win32::Beep() const
bool GpSystemServices_Win32::Beep() const
{
MessageBeep(MB_OK);
return true;
}
bool GpSystemServices_Win32::IsTouchscreen() const
@@ -261,6 +263,21 @@ bool GpSystemServices_Win32::IsFullscreenOnStartup() const
return false;
}
bool GpSystemServices_Win32::HasNativeFileManager() const
{
return true;
}
GpOperatingSystem_t GpSystemServices_Win32::GetOperatingSystem() const
{
return GpOperatingSystems::kWindows;
}
GpOperatingSystemFlavor_t GpSystemServices_Win32::GetOperatingSystemFlavor() const
{
return GpOperatingSystemFlavors::kGeneric;
}
unsigned int GpSystemServices_Win32::GetCPUCount() const
{
SYSTEM_INFO sysInfo;

View File

@@ -28,12 +28,15 @@ public:
void *CreateThread(ThreadFunc_t threadFunc, void *context) override;
IGpThreadEvent *CreateThreadEvent(bool autoReset, bool startSignaled) override;
uint64_t GetFreeMemoryCosmetic() const override;
void Beep() const override;
bool Beep() const override;
bool IsTouchscreen() const override;
bool IsUsingMouseAsTouch() const override;
bool IsTextInputObstructive() const override;
bool IsFullscreenPreferred() const override;
bool IsFullscreenOnStartup() const override;
bool HasNativeFileManager() const override;
GpOperatingSystem_t GetOperatingSystem() const override;
GpOperatingSystemFlavor_t GetOperatingSystemFlavor() const override;
unsigned int GetCPUCount() const override;
void SetTextInputEnabled(bool isEnabled) override;
bool IsTextInputEnabled() const override;
@@ -48,6 +51,8 @@ public:
private:
bool m_isTouchscreenSimulation;
IGpAllocator *m_alloc;
static GpSystemServices_Win32 ms_instance;
};

View File

@@ -1,4 +1,5 @@
#include "GpThreadEvent_Win32.h"
#include "IGpAllocator.h"
#include <stdlib.h>
#include <new>
@@ -20,28 +21,30 @@ void GpThreadEvent_Win32::Signal()
void GpThreadEvent_Win32::Destroy()
{
IGpAllocator *alloc = m_alloc;
this->~GpThreadEvent_Win32();
free(this);
alloc->Release(this);
}
GpThreadEvent_Win32 *GpThreadEvent_Win32::Create(bool autoReset, bool startSignaled)
GpThreadEvent_Win32 *GpThreadEvent_Win32::Create(IGpAllocator *alloc, bool autoReset, bool startSignaled)
{
HANDLE handle = CreateEventA(nullptr, autoReset ? FALSE : TRUE, startSignaled ? TRUE : FALSE, nullptr);
if (handle == nullptr)
return nullptr;
void *storage = malloc(sizeof(GpThreadEvent_Win32));
void *storage = alloc->Alloc(sizeof(GpThreadEvent_Win32));
if (!storage)
{
CloseHandle(handle);
return nullptr;
}
return new (storage) GpThreadEvent_Win32(handle);
return new (storage) GpThreadEvent_Win32(alloc, handle);
}
GpThreadEvent_Win32::GpThreadEvent_Win32(const HANDLE &handle)
GpThreadEvent_Win32::GpThreadEvent_Win32(IGpAllocator *alloc, const HANDLE &handle)
: m_event(handle)
, m_alloc(alloc)
{
}

View File

@@ -12,11 +12,12 @@ public:
void Signal() override;
void Destroy() override;
static GpThreadEvent_Win32 *Create(bool autoReset, bool startSignaled);
static GpThreadEvent_Win32 *Create(IGpAllocator *alloc, bool autoReset, bool startSignaled);
private:
explicit GpThreadEvent_Win32(const HANDLE &handle);
explicit GpThreadEvent_Win32(IGpAllocator *alloc, const HANDLE &handle);
~GpThreadEvent_Win32();
HANDLE m_event;
IGpAllocator *m_alloc;
};

View File

@@ -8,15 +8,15 @@ else {
}
android {
compileSdkVersion 29
compileSdkVersion 30
defaultConfig {
if (buildAsApplication) {
applicationId "org.thecodedeposit.aerofoil"
}
minSdkVersion 16
targetSdkVersion 29
versionCode 14
versionName "1.1.0"
targetSdkVersion 30
versionCode 16
versionName "1.1.2"
externalNativeBuild {
ndkBuild {
arguments "APP_PLATFORM=android-16"

View File

@@ -424,9 +424,6 @@ bool GpFileSystem_Android::ResolvePath(PortabilityLayer::VirtualDirectory_t virt
case PortabilityLayer::VirtualDirectories::kPrefs:
prefsAppend = "Prefs";
break;
case PortabilityLayer::VirtualDirectories::kFontCache:
prefsAppend = "FontCache";
break;
default:
return false;
};

View File

@@ -1,6 +1,7 @@
#include "SDL.h"
#include "GpMain.h"
#include "GpAllocator_C.h"
#include "GpAudioDriverFactory.h"
#include "GpDisplayDriverFactory.h"
#include "GpGlobalConfig.h"
@@ -25,6 +26,7 @@ GpAndroidGlobals g_gpAndroidGlobals;
IGpDisplayDriver *GpDriver_CreateDisplayDriver_SDL_GL2(const GpDisplayDriverProperties &properties);
IGpAudioDriver *GpDriver_CreateAudioDriver_SDL(const GpAudioDriverProperties &properties);
IGpInputDriver *GpDriver_CreateInputDriver_SDL2_Gamepad(const GpInputDriverProperties &properties);
class GpLogDriver_Android final : public IGpLogDriver
{
@@ -70,9 +72,11 @@ GpLogDriver_Android GpLogDriver_Android::ms_instance;
int main(int argc, char* argv[])
{
IGpAllocator *alloc = GpAllocator_C::GetInstance();
SDL_LogSetAllPriority(SDL_LOG_PRIORITY_INFO);
if (SDL_Init(SDL_INIT_VIDEO) < 0)
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMECONTROLLER) < 0)
return -1;
SDL_SetHint(SDL_HINT_ORIENTATIONS, "LandscapeLeft LandscapeRight");
@@ -83,6 +87,7 @@ int main(int argc, char* argv[])
drivers->SetDriver<GpDriverIDs::kFileSystem>(GpFileSystem_Android::GetInstance());
drivers->SetDriver<GpDriverIDs::kSystemServices>(GpSystemServices_Android::GetInstance());
drivers->SetDriver<GpDriverIDs::kLog>(GpLogDriver_Android::GetInstance());
drivers->SetDriver<GpDriverIDs::kAlloc>(alloc);
g_gpGlobalConfig.m_displayDriverType = EGpDisplayDriverType_SDL_GL2;
@@ -90,15 +95,22 @@ int main(int argc, char* argv[])
g_gpGlobalConfig.m_fontHandlerType = EGpFontHandlerType_None;
g_gpGlobalConfig.m_inputDriverTypes = nullptr;
g_gpGlobalConfig.m_numInputDrivers = 0;
EGpInputDriverType inputDrivers[] =
{
EGpInputDriverType_SDL2_Gamepad
};
g_gpGlobalConfig.m_inputDriverTypes = inputDrivers;
g_gpGlobalConfig.m_numInputDrivers = sizeof(inputDrivers) / sizeof(inputDrivers[0]);
g_gpGlobalConfig.m_osGlobals = &g_gpAndroidGlobals;
g_gpGlobalConfig.m_logger = GpLogDriver_Android::GetInstance();
g_gpGlobalConfig.m_systemServices = GpSystemServices_Android::GetInstance();
g_gpGlobalConfig.m_allocator = alloc;
GpDisplayDriverFactory::RegisterDisplayDriverFactory(EGpDisplayDriverType_SDL_GL2, GpDriver_CreateDisplayDriver_SDL_GL2);
GpAudioDriverFactory::RegisterAudioDriverFactory(EGpAudioDriverType_SDL2, GpDriver_CreateAudioDriver_SDL);
GpInputDriverFactory::RegisterInputDriverFactory(EGpInputDriverType_SDL2_Gamepad, GpDriver_CreateInputDriver_SDL2_Gamepad);
int returnCode = GpMain::Run();
@@ -113,8 +125,3 @@ int main(int argc, char* argv[])
return returnCode;
}
IGpInputDriverSDLGamepad *IGpInputDriverSDLGamepad::GetInstance()
{
return nullptr;
}

View File

@@ -55,8 +55,9 @@ void *GpSystemServices_Android::CreateThread(ThreadFunc_t threadFunc, void *cont
return thread;
}
void GpSystemServices_Android::Beep() const
bool GpSystemServices_Android::Beep() const
{
return false;
}
bool GpSystemServices_Android::IsTouchscreen() const
@@ -84,6 +85,21 @@ bool GpSystemServices_Android::IsFullscreenOnStartup() const
return true;
}
bool GpSystemServices_Android::HasNativeFileManager() const
{
return false;
}
GpOperatingSystem_t GpSystemServices_Android::GetOperatingSystem() const
{
return GpOperatingSystems::kAndroid;
}
GpOperatingSystemFlavor_t GpSystemServices_Android::GetOperatingSystemFlavor() const
{
return GpOperatingSystemFlavors::kGeneric;
}
unsigned int GpSystemServices_Android::GetCPUCount() const
{
return SDL_GetCPUCount();

View File

@@ -9,12 +9,15 @@ public:
GpSystemServices_Android();
void *CreateThread(ThreadFunc_t threadFunc, void *context) override;
void Beep() const override;
bool Beep() const override;
bool IsTouchscreen() const override;
bool IsUsingMouseAsTouch() const override;
bool IsTextInputObstructive() const override;
bool IsFullscreenPreferred() const override;
bool IsFullscreenOnStartup() const override;
bool HasNativeFileManager() const override;
GpOperatingSystem_t GetOperatingSystem() const override;
GpOperatingSystemFlavor_t GetOperatingSystemFlavor() const override;
unsigned int GetCPUCount() const override;
void SetTextInputEnabled(bool isEnabled) override;
bool IsTextInputEnabled() const override;

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:">
</FileRef>
</Workspace>

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>

View File

@@ -0,0 +1,84 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1240"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "5C54D0952629B42100AB55E0"
BuildableName = "Aerofoil.app"
BlueprintName = "Aerofoil"
ReferencedContainer = "container:AerofoilMac.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "5C54D0952629B42100AB55E0"
BuildableName = "Aerofoil.app"
BlueprintName = "Aerofoil"
ReferencedContainer = "container:AerofoilMac.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
<CommandLineArguments>
<CommandLineArgument
argument = "-diagnostics"
isEnabled = "YES">
</CommandLineArgument>
</CommandLineArguments>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "5C54D0952629B42100AB55E0"
BuildableName = "Aerofoil.app"
BlueprintName = "Aerofoil"
ReferencedContainer = "container:AerofoilMac.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

View File

@@ -0,0 +1,9 @@
#import <Cocoa/Cocoa.h>
NS_ASSUME_NONNULL_BEGIN
@interface AerofoilAppDelegate : NSObject <NSApplicationDelegate>
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,43 @@
#import "AerofoilAppDelegate.h"
#import "AerofoilApplication.h"
#include "WindowManager.h"
#include "GliderDefines.h" // kPlayMode
extern short theMode;
@interface AerofoilAppDelegate ()
@property (weak) IBOutlet NSMenuItem *aboutAerofoilMenuItem;
@property (weak) IBOutlet NSMenuItem *aboutGliderPROMenuItem;
@property (weak) IBOutlet NSMenuItem *preferencesMenuItem;
@end
@implementation AerofoilAppDelegate
- (IBAction)showAboutAerofoil:(id)sender {
[NSApp sendMenuItemEvent:GpMenuItemSelectionEvents::kAboutAerofoil];
}
- (IBAction)showAboutGliderPRO:(id)sender {
[NSApp sendMenuItemEvent:GpMenuItemSelectionEvents::kAboutGliderPRO];
}
- (IBAction)showPreferences:(id)sender {
[NSApp sendMenuItemEvent:GpMenuItemSelectionEvents::kPreferences];
}
- (BOOL)validateMenuItem:(NSMenuItem *)menuItem {
if (menuItem == _aboutAerofoilMenuItem || menuItem == _aboutGliderPROMenuItem) {
return ![self menuItemsDisabled];
} else if (menuItem == _preferencesMenuItem) {
return ![self menuItemsDisabled];
} else {
return NO;
}
}
- (BOOL)menuItemsDisabled {
PortabilityLayer::WindowManager* wm = PortabilityLayer::WindowManager::GetInstance();
return theMode == kPlayMode || wm->IsExclusiveWindowVisible();
}
@end

View File

@@ -0,0 +1,12 @@
#import <Cocoa/Cocoa.h>
#include "GpVOSEvent.h"
NS_ASSUME_NONNULL_BEGIN
@interface AerofoilApplication : NSApplication
- (void)sendMenuItemEvent:(GpMenuItemSelectionEvent_t)itemEvent;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,28 @@
#import "AerofoilApplication.h"
#include "IGpVOSEventQueue.h"
#include "GpAppInterface.h"
#include "SDL.h"
@implementation AerofoilApplication
- (void)terminate:(id)sender {
SDL_Event event;
event.quit.type = SDL_QUIT;
event.quit.timestamp = SDL_GetTicks();
SDL_PushEvent(&event);
}
- (void)sendMenuItemEvent:(GpMenuItemSelectionEvent_t)itemEvent {
GpVOSEvent event;
event.m_eventType = GpVOSEventTypes::kMenuItemSelected;
event.m_event.m_menuItemSelectionEvent = itemEvent;
[self sendVOSEvent:event];
}
- (void)sendVOSEvent:(GpVOSEvent)event {
IGpVOSEventQueue* queue = GpAppInterface_Get()->PL_GetDriverCollection()->GetDriver<GpDriverIDs::kEventQueue>();
if (GpVOSEvent *evt = queue->QueueEvent())
*evt = event;
}
@end

View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.app-sandbox</key>
<true/>
<key>com.apple.security.cs.disable-library-validation</key>
<true/>
<key>com.apple.security.files.user-selected.read-only</key>
<true/>
</dict>
</plist>

View File

@@ -0,0 +1,11 @@
{
"colors" : [
{
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 98 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 343 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.3 KiB

View File

@@ -0,0 +1 @@
{"images":[{"size":"128x128","expected-size":"128","filename":"128.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"1x"},{"size":"256x256","expected-size":"256","filename":"256.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"1x"},{"size":"128x128","expected-size":"256","filename":"256.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"2x"},{"size":"256x256","expected-size":"512","filename":"512.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"2x"},{"size":"32x32","expected-size":"32","filename":"32.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"1x"},{"size":"512x512","expected-size":"512","filename":"512.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"1x"},{"size":"16x16","expected-size":"16","filename":"16.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"1x"},{"size":"16x16","expected-size":"32","filename":"32.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"2x"},{"size":"32x32","expected-size":"64","filename":"64.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"2x"},{"size":"512x512","expected-size":"1024","filename":"1024.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"2x"}]}

View File

@@ -0,0 +1,6 @@
{
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@@ -0,0 +1,126 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="19115.3" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
<dependencies>
<deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="19115.3"/>
</dependencies>
<objects>
<customObject id="-2" userLabel="File's Owner" customClass="NSApplication">
<connections>
<outlet property="delegate" destination="Rej-MO-9Vm" id="Gxm-Yh-n2y"/>
</connections>
</customObject>
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
<customObject id="-3" userLabel="Application" customClass="SDLApplication"/>
<menu title="Main Menu" systemMenu="main" id="AYu-sK-qS6">
<items>
<menuItem title="Aerofoil" id="1Xt-HY-uBw">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Aerofoil" systemMenu="apple" id="uQy-DD-JDr">
<items>
<menuItem title="About Aerofoil" id="5kV-Vb-QxS">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="showAboutAerofoil:" target="Rej-MO-9Vm" id="bhL-jn-Mnf"/>
</connections>
</menuItem>
<menuItem title="About Glider PRO" id="s5u-0T-8m0">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="showAboutGliderPRO:" target="Rej-MO-9Vm" id="GmM-Kv-7Zh"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="VOq-y0-SEH"/>
<menuItem title="Preferences…" keyEquivalent="," id="BOF-NM-1cW">
<connections>
<action selector="showPreferences:" target="Rej-MO-9Vm" id="eLk-ZW-NLG"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="wFC-TO-SCJ"/>
<menuItem title="Services" id="NMo-om-nkz">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Services" systemMenu="services" id="hz9-B4-Xy5"/>
</menuItem>
<menuItem isSeparatorItem="YES" id="4je-JR-u6R"/>
<menuItem title="Hide Aerofoil" id="Olw-nP-bQN">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="hide:" target="-1" id="PnN-Uc-m68"/>
</connections>
</menuItem>
<menuItem title="Hide Others" keyEquivalent="h" id="Vdr-fp-XzO">
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
<connections>
<action selector="hideOtherApplications:" target="-1" id="VT4-aY-XCT"/>
</connections>
</menuItem>
<menuItem title="Show All" id="Kd2-mp-pUS">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="unhideAllApplications:" target="-1" id="Dhg-Le-xox"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="kCx-OE-vgT"/>
<menuItem title="Quit Aerofoil" keyEquivalent="q" id="4sb-4s-VLi">
<connections>
<action selector="terminate:" target="-1" id="Te7-pn-YzF"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Window" id="aUF-d1-5bR">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Window" systemMenu="window" id="Td7-aD-5lo">
<items>
<menuItem title="Minimize" keyEquivalent="m" id="OY7-WF-poV">
<connections>
<action selector="performMiniaturize:" target="-1" id="VwT-WD-YPe"/>
</connections>
</menuItem>
<menuItem title="Zoom" id="R4o-n2-Eq4">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="performZoom:" target="-1" id="DIl-cC-cCs"/>
</connections>
</menuItem>
<menuItem title="Enter Full Screen" keyEquivalent="f" id="Kyh-0n-SY2">
<modifierMask key="keyEquivalentModifierMask" control="YES" command="YES"/>
<connections>
<action selector="toggleFullScreen:" target="-1" id="wEJ-jN-ABr"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="eu3-7i-yIM"/>
<menuItem title="Bring All to Front" id="LE2-aR-0XJ">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="arrangeInFront:" target="-1" id="DRN-fu-gQh"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Help" id="wpr-3q-Mcd">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Help" systemMenu="help" id="F2S-fz-NVQ">
<items>
<menuItem title="Aerofoil Help" keyEquivalent="?" id="FKE-Sm-Kum">
<connections>
<action selector="showHelp:" target="-1" id="y7X-2Q-9no"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
</items>
<point key="canvasLocation" x="139" y="154"/>
</menu>
<customObject id="Rej-MO-9Vm" customClass="AerofoilAppDelegate">
<connections>
<outlet property="aboutAerofoilMenuItem" destination="5kV-Vb-QxS" id="Cd2-zP-auq"/>
<outlet property="aboutGliderPROMenuItem" destination="s5u-0T-8m0" id="gQV-eb-cs2"/>
<outlet property="preferencesMenuItem" destination="BOF-NM-1cW" id="oG4-1W-R0t"/>
</connections>
</customObject>
</objects>
</document>

View File

@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIconFile</key>
<string></string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
<key>CFBundleShortVersionString</key>
<string>$(MARKETING_VERSION)</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>LSApplicationCategoryType</key>
<string>public.app-category.arcade-games</string>
<key>LSMinimumSystemVersion</key>
<string>$(MACOSX_DEPLOYMENT_TARGET)</string>
<key>NSMainNibFile</key>
<string>MainMenu</string>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
</dict>
</plist>

View File

@@ -0,0 +1,3 @@
#pragma once
int MacInit(void);

View File

@@ -0,0 +1,22 @@
#import <Cocoa/Cocoa.h>
#import "AerofoilApplication.h"
#import "AerofoilAppDelegate.h"
#import "MacInit.h"
#include "SDL.h"
int MacInit(void) {
// Instantiate NSApp and its delegate first, so SDL chooses those over its own implementation.
[AerofoilApplication sharedApplication];
[[NSBundle mainBundle] loadNibNamed:@"MainMenu" owner:NSApp topLevelObjects:nil];
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMECONTROLLER) < 0)
return -1;
// Gracefully activate app.
//
// (SDL forcefully does this via [NSApp activateIgnoringOtherApps:YES],
// which isn't consistent with normal Mac apps).
[NSApp finishLaunching];
return 0;
}

View File

@@ -0,0 +1,6 @@
Extract resources from the Windows build and place here to create the Mac build.
Files are included in the Xcode project, but not in the Git repo.
- ApplicationResources.gpf
- Fonts.gpf
- Houses/*.gpf

View File

@@ -1,8 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ImportGroup Label="PropertySheets" />
<PropertyGroup Label="UserMacros" />
<PropertyGroup />
<PropertyGroup>
<IncludePath>$(SolutionDir)AerofoilPortable;$(IncludePath)</IncludePath>
</PropertyGroup>
<ItemDefinitionGroup />
<ItemGroup />
</Project>
</Project>

View File

@@ -14,6 +14,7 @@ LOCAL_CFLAGS := -DGP_DEBUG_CONFIG=0
# Add your application source files here...
LOCAL_SRC_FILES := \
GpAllocator_C.cpp \
GpThreadEvent_Cpp11.cpp \
GpSystemServices_POSIX.cpp

View File

@@ -0,0 +1,115 @@
#include "GpAllocator_C.h"
#include "CoreDefs.h"
#include <string.h>
#include <stdlib.h>
#include <assert.h>
struct GpAllocator_C_MMBlock
{
uint8_t m_offsetFromAllocLocation;
static size_t AlignedSize();
};
size_t GpAllocator_C_MMBlock::AlignedSize()
{
const size_t paddedSize = sizeof(GpAllocator_C_MMBlock) + GP_SYSTEM_MEMORY_ALIGNMENT - 1;
const size_t paddedSizeTruncated = paddedSize - (paddedSize % GP_SYSTEM_MEMORY_ALIGNMENT);
return paddedSizeTruncated;
}
void *GpAllocator_C::Realloc(void *buf, size_t newSize)
{
if (buf == nullptr)
{
if (newSize == 0)
return nullptr;
return this->Alloc(newSize);
}
if (newSize == 0)
{
this->Free(buf);
return nullptr;
}
assert(buf != nullptr);
const size_t mmBlockSize = GpAllocator_C_MMBlock::AlignedSize();
uint8_t *oldBufBytes = static_cast<uint8_t*>(buf);
const GpAllocator_C_MMBlock *oldBufMMBlock = reinterpret_cast<const GpAllocator_C_MMBlock*>(oldBufBytes - GpAllocator_C_MMBlock::AlignedSize());
const size_t oldBufOffsetFromAlignLoc = oldBufMMBlock->m_offsetFromAllocLocation;
uint8_t *oldBufBase = oldBufBytes - GpAllocator_C_MMBlock::AlignedSize() - oldBufOffsetFromAlignLoc;
const size_t mmBlockSizeWithMaxPadding = GpAllocator_C_MMBlock::AlignedSize() + GP_SYSTEM_MEMORY_ALIGNMENT - 1;
if (SIZE_MAX - newSize < mmBlockSizeWithMaxPadding)
return nullptr;
const size_t newBufferSize = newSize + mmBlockSizeWithMaxPadding;
uint8_t *newBuffer = static_cast<uint8_t*>(realloc(oldBufBase, newSize + mmBlockSizeWithMaxPadding));
if (!newBuffer)
return nullptr;
const intptr_t offsetFromAlignPoint = reinterpret_cast<intptr_t>(newBuffer) & static_cast<intptr_t>(GP_SYSTEM_MEMORY_ALIGNMENT - 1);
intptr_t alignPadding = 0;
if (offsetFromAlignPoint != 0)
alignPadding = static_cast<intptr_t>(GP_SYSTEM_MEMORY_ALIGNMENT) - offsetFromAlignPoint;
// Check if the alignment changed, if so relocate
if (static_cast<size_t>(alignPadding) != oldBufOffsetFromAlignLoc)
memmove(newBuffer + alignPadding, newBuffer + oldBufOffsetFromAlignLoc, GpAllocator_C_MMBlock::AlignedSize() + newSize);
GpAllocator_C_MMBlock *newMMBlock = reinterpret_cast<GpAllocator_C_MMBlock*>(newBuffer + alignPadding);
newMMBlock->m_offsetFromAllocLocation = static_cast<uint8_t>(alignPadding);
return newBuffer + alignPadding + GpAllocator_C_MMBlock::AlignedSize();
}
void *GpAllocator_C::Alloc(size_t size)
{
if (size == 0)
return nullptr;
const size_t mmBlockSizeWithMaxPadding = GpAllocator_C_MMBlock::AlignedSize() + GP_SYSTEM_MEMORY_ALIGNMENT - 1;
if (SIZE_MAX - size < mmBlockSizeWithMaxPadding)
return nullptr;
uint8_t *buffer = static_cast<uint8_t*>(realloc(nullptr, size + mmBlockSizeWithMaxPadding));
if (!buffer)
return nullptr;
const intptr_t offsetFromAlignPoint = reinterpret_cast<intptr_t>(buffer) & static_cast<intptr_t>(GP_SYSTEM_MEMORY_ALIGNMENT - 1);
intptr_t alignPadding = 0;
if (offsetFromAlignPoint != 0)
alignPadding = static_cast<intptr_t>(GP_SYSTEM_MEMORY_ALIGNMENT) - offsetFromAlignPoint;
GpAllocator_C_MMBlock *mmBlock = reinterpret_cast<GpAllocator_C_MMBlock*>(buffer + alignPadding);
mmBlock->m_offsetFromAllocLocation = static_cast<uint8_t>(alignPadding);
return buffer + alignPadding + GpAllocator_C_MMBlock::AlignedSize();
}
void GpAllocator_C::Free(void *buf)
{
if (!buf)
return;
const size_t mmBlockSize = GpAllocator_C_MMBlock::AlignedSize();
uint8_t *bytes = static_cast<uint8_t*>(buf);
const GpAllocator_C_MMBlock *mmBlock = reinterpret_cast<const GpAllocator_C_MMBlock*>(bytes - GpAllocator_C_MMBlock::AlignedSize());
void *freeLoc = bytes - GpAllocator_C_MMBlock::AlignedSize() - mmBlock->m_offsetFromAllocLocation;
(void)realloc(freeLoc, 0);
}
GpAllocator_C *GpAllocator_C::GetInstance()
{
return &ms_instance;
}
GpAllocator_C GpAllocator_C::ms_instance;

View File

@@ -0,0 +1,17 @@
#pragma once
#include "IGpAllocator.h"
class GpAllocator_C final : public IGpAllocator
{
public:
void *Realloc(void *buf, size_t newSize) override;
static GpAllocator_C *GetInstance();
private:
void *Alloc(size_t size);
void Free(void *ptr);
static GpAllocator_C ms_instance;
};

View File

@@ -6,6 +6,10 @@
#include <time.h>
#include <unistd.h>
#ifdef __MACOS__
#include <sys/sysctl.h>
#endif
GpSystemServices_POSIX::GpSystemServices_POSIX()
{
}
@@ -44,7 +48,21 @@ IGpThreadEvent *GpSystemServices_POSIX::CreateThreadEvent(bool autoReset, bool s
uint64_t GpSystemServices_POSIX::GetFreeMemoryCosmetic() const
{
#ifdef __MACOS__
{ /* This works on *bsd and darwin. */
unsigned int usermem;
size_t len = sizeof usermem;
static int mib[2] = { CTL_HW, HW_USERMEM };
if (sysctl (mib, 2, &usermem, &len, NULL, 0) == 0
&& len == sizeof (usermem))
return (long) usermem;
}
return 0;
#else
long pages = sysconf(_SC_AVPHYS_PAGES);
long pageSize = sysconf(_SC_PAGE_SIZE);
return pages * pageSize;
#endif
}

View File

@@ -1,5 +1,7 @@
#include "GpThreadEvent_Cpp11.h"
#include <stdlib.h>
GpThreadEvent_Cpp11::GpThreadEvent_Cpp11(bool autoReset, bool startSignaled)
: m_flag(startSignaled)
, m_autoReset(autoReset)

View File

@@ -14,19 +14,19 @@
<VCProjectVersion>15.0</VCProjectVersion>
<ProjectGuid>{33542FF0-0473-4802-BC79-3B8261790F65}</ProjectGuid>
<RootNamespace>AerofoilSDL</RootNamespace>
<WindowsTargetPlatformVersion>10.0.17763.0</WindowsTargetPlatformVersion>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
@@ -84,6 +84,7 @@
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\AerofoilPortable\GpAllocator_C.cpp" />
<ClCompile Include="..\Aerofoil\GpColorCursor_Win32.cpp" />
<ClCompile Include="..\Aerofoil\GpFileStream_Win32.cpp" />
<ClCompile Include="..\Aerofoil\GpFileSystem_Win32.cpp" />

View File

@@ -66,6 +66,9 @@
<ClCompile Include="GpInputDriver_SDL_Gamepad.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\AerofoilPortable\GpAllocator_C.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="ShaderCode\Functions.h">

View File

@@ -20,6 +20,7 @@ LOCAL_CFLAGS := -DGP_DEBUG_CONFIG=0
LOCAL_SRC_FILES := \
GpAudioDriver_SDL2.cpp \
GpDisplayDriver_SDL_GL2.cpp \
GpInputDriver_SDL_Gamepad.cpp \
ShaderCode/CopyQuadP.cpp \
ShaderCode/DrawQuadPaletteP.cpp \
ShaderCode/DrawQuad32P.cpp \

View File

@@ -1,4 +1,5 @@
#include "CoreDefs.h"
#include "IGpAudioBuffer.h"
#include "IGpAudioDriver.h"
#include "IGpAudioChannel.h"
#include "IGpAudioChannelCallbacks.h"
@@ -13,13 +14,21 @@
#include "SDL_atomic.h"
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <new>
#include <stdio.h>
#include <chrono>
class GpAudioDriver_SDL2;
typedef std::chrono::high_resolution_clock::duration GpAudioDriver_SDL2_Duration_t;
typedef std::chrono::high_resolution_clock::time_point GpAudioDriver_SDL2_TimePoint_t;
typedef std::chrono::high_resolution_clock::period GpAudioDriver_SDL2_Period_t;
typedef std::chrono::high_resolution_clock::rep GpAudioDriver_SDL2_Rep_t;
static void *AlignedAlloc(size_t size, size_t alignment)
{
void *storage = malloc(size + alignment);
@@ -46,72 +55,150 @@ static void AlignedFree(void *ptr)
free(storageLoc);
}
struct GpAudioChannelBufferChain_SDL2 final
{
GpAudioChannelBufferChain_SDL2();
static GpAudioChannelBufferChain_SDL2 *Alloc();
void Release();
static const size_t kMaxCapacity = 65536;
size_t m_consumed;
size_t m_used;
uint8_t m_data[kMaxCapacity];
GpAudioChannelBufferChain_SDL2 *m_next;
bool m_hasTrigger;
};
class GP_ALIGNED(GP_SYSTEM_MEMORY_ALIGNMENT) GpAudioChannel_SDL2 final : public IGpAudioChannel
class GpAudioBuffer_SDL2 final : public IGpAudioBuffer
{
public:
enum ChannelState
{
ChannelState_Idle,
ChannelState_Playing,
ChannelState_Stopped,
};
typedef int16_t AudioSample_t;
static GpAudioBuffer_SDL2 *Create(const void *data, size_t size);
void AddRef() override;
void Release() override;
const AudioSample_t *GetData() const;
size_t GetSize() const;
private:
GpAudioBuffer_SDL2(const AudioSample_t *data, size_t size);
~GpAudioBuffer_SDL2();
void Destroy();
const AudioSample_t *m_data;
size_t m_size;
SDL_atomic_t m_count;
};
GpAudioBuffer_SDL2 *GpAudioBuffer_SDL2::Create(const void *data, size_t size)
{
size_t baseSize = sizeof(GpAudioBuffer_SDL2) + GP_SYSTEM_MEMORY_ALIGNMENT + 1;
baseSize -= baseSize % GP_SYSTEM_MEMORY_ALIGNMENT;
void *storage = malloc(size * sizeof(AudioSample_t) + baseSize);
if (!storage)
return nullptr;
AudioSample_t *dataPos = reinterpret_cast<AudioSample_t*>(static_cast<uint8_t*>(storage) + baseSize);
// Convert from u8 to s16
const uint8_t *srcData = static_cast<const uint8_t*>(data);
for (size_t i = 0; i < size; i++)
dataPos[i] = srcData[i] - 0x80;
return new (storage) GpAudioBuffer_SDL2(dataPos, size);
}
void GpAudioBuffer_SDL2::AddRef()
{
SDL_AtomicAdd(&m_count, 1);
}
void GpAudioBuffer_SDL2::Release()
{
int prevCount = SDL_AtomicAdd(&m_count, -1);
if (prevCount == 1)
this->Destroy();
}
const int16_t *GpAudioBuffer_SDL2::GetData() const
{
return m_data;
}
size_t GpAudioBuffer_SDL2::GetSize() const
{
return m_size;
}
GpAudioBuffer_SDL2::GpAudioBuffer_SDL2(const int16_t *data, size_t size)
: m_data(data)
, m_size(size)
{
SDL_AtomicSet(&m_count, 1);
}
GpAudioBuffer_SDL2::~GpAudioBuffer_SDL2()
{
}
void GpAudioBuffer_SDL2::Destroy()
{
this->~GpAudioBuffer_SDL2();
free(this);
}
class GpAudioChannel_SDL2 final : public IGpAudioChannel
{
public:
friend class GpAudioDriver_SDL2;
typedef GpAudioBuffer_SDL2::AudioSample_t AudioSample_t;
GpAudioChannel_SDL2();
GpAudioChannel_SDL2(GpAudioDriver_SDL2_Duration_t latency, GpAudioDriver_SDL2_Duration_t bufferTime, size_t bufferSamplesMax, uint16_t sampleRate);
~GpAudioChannel_SDL2();
void AddRef();
void Release();
void SetAudioChannelContext(IGpAudioChannelCallbacks *callbacks) override;
void PostBuffer(const void *buffer, size_t bufferSize) override;
bool PostBuffer(IGpAudioBuffer *buffer) override;
void Stop() override;
void Destroy() override;
void Consume(uint8_t *output, size_t sz);
void Consume(int16_t *output, size_t sz, GpAudioDriver_SDL2_TimePoint_t mixStartTime, GpAudioDriver_SDL2_TimePoint_t mixEndTime);
static GpAudioChannel_SDL2 *Alloc(GpAudioDriver_SDL2 *driver);
static GpAudioChannel_SDL2 *Alloc(GpAudioDriver_SDL2 *driver, GpAudioDriver_SDL2_Duration_t latency, GpAudioDriver_SDL2_Duration_t bufferTime, size_t bufferSamplesMax, uint16_t sampleRate);
private:
bool Init(GpAudioDriver_SDL2 *driver);
static const size_t kMaxBuffers = 16;
IGpAudioChannelCallbacks *m_callbacks;
IGpMutex *m_mutex;
GpAudioDriver_SDL2 *m_owner;
SDL_atomic_t m_refCount;
GpAudioChannelBufferChain_SDL2 *m_firstPendingBuffer;
GpAudioChannelBufferChain_SDL2 *m_lastPendingBuffer;
GpAudioBuffer_SDL2 *m_pendingBuffers[kMaxBuffers];
size_t m_nextPendingBufferConsumePos;
size_t m_nextPendingBufferInsertionPos;
size_t m_numQueuedBuffers;
size_t m_firstBufferSamplesConsumed;
ChannelState m_channelState;
GpAudioDriver_SDL2_TimePoint_t m_timestamp; // Time that audio will be consumed if posted to the channel, if m_hasTimestamp is true.
GpAudioDriver_SDL2_Duration_t m_latency;
GpAudioDriver_SDL2_Duration_t m_bufferTime;
size_t m_bufferSamplesMax;
size_t m_leadingSilence;
uint16_t m_sampleRate;
bool m_isMixing;
bool m_hasTimestamp;
};
class GP_ALIGNED(GP_SYSTEM_MEMORY_ALIGNMENT) GpAudioDriver_SDL2 final : public IGpAudioDriver, public IGpPrefsHandler
class GpAudioDriver_SDL2 final : public IGpAudioDriver, public IGpPrefsHandler
{
public:
friend class GpAudioChannel_SDL2;
typedef GpAudioChannel_SDL2::AudioSample_t AudioSample_t;
explicit GpAudioDriver_SDL2(const GpAudioDriverProperties &properties);
~GpAudioDriver_SDL2();
IGpAudioBuffer *CreateBuffer(const void *data, size_t size) override;
IGpAudioChannel *CreateChannel() override;
void SetMasterVolume(uint32_t vol, uint32_t maxVolume) override;
void Shutdown() override;
@@ -122,63 +209,59 @@ public:
bool Init();
static GpAudioDriver_SDL2_TimePoint_t GetCurrentTime();
private:
void DetachAudioChannel(GpAudioChannel_SDL2 *channel);
static void SDLCALL StaticMixAudio(void *userdata, Uint8 *stream, int len);
void MixAudio(void *stream, size_t len);
void RefillMixChunk(GpAudioChannel_SDL2 *const*channels, size_t numChannels);
void RefillMixChunk(GpAudioChannel_SDL2 *const*channels, size_t numChannels, size_t maxSamplesToFill, GpAudioDriver_SDL2_TimePoint_t mixStartTime, GpAudioDriver_SDL2_TimePoint_t mixEndTime);
static void AddSamples(AudioSample_t *GP_RESTRICT dest, const AudioSample_t *GP_RESTRICT src, size_t nSamples);
GpAudioDriverProperties m_properties;
IGpMutex *m_mutex;
IGpMutex *m_mixState;
static const size_t kMaxChannels = 16;
static const size_t kMixChunkSize = 256;
static const int16_t kMaxAudioVolumeScale = 25;
static const size_t kMixChunkSamples = 512;
static const int16_t kMaxAudioVolumeScale = 64;
GpAudioChannel_SDL2 *m_channels[kMaxChannels];
size_t m_numChannels;
unsigned int m_sampleRate;
GpAudioDriver_SDL2_Duration_t m_latency;
GpAudioDriver_SDL2_Duration_t m_bufferTime;
size_t m_bufferSamples;
bool m_sdlAudioRunning;
GP_ALIGNED(GP_SYSTEM_MEMORY_ALIGNMENT) int16_t m_mixChunk[kMixChunkSize];
GP_ALIGNED(GP_SYSTEM_MEMORY_ALIGNMENT) int16_t m_mixChunk[kMixChunkSamples];
size_t m_mixChunkReadOffset;
int16_t m_audioVolumeScale;
};
GpAudioChannelBufferChain_SDL2::GpAudioChannelBufferChain_SDL2()
: m_used(0)
, m_consumed(0)
, m_next(nullptr)
, m_hasTrigger(false)
{
}
GpAudioChannelBufferChain_SDL2 *GpAudioChannelBufferChain_SDL2::Alloc()
{
void *storage = AlignedAlloc(sizeof(GpAudioChannelBufferChain_SDL2), GP_SYSTEM_MEMORY_ALIGNMENT);
return new (storage) GpAudioChannelBufferChain_SDL2();
}
void GpAudioChannelBufferChain_SDL2::Release()
{
this->~GpAudioChannelBufferChain_SDL2();
AlignedFree(this);
}
/////////////////////////////////////////////////////////////////////////////////////////
// GpAudioChannel
GpAudioChannel_SDL2::GpAudioChannel_SDL2()
GpAudioChannel_SDL2::GpAudioChannel_SDL2(GpAudioDriver_SDL2_Duration_t latency, GpAudioDriver_SDL2_Duration_t bufferTime, size_t bufferSamplesMax, uint16_t sampleRate)
: m_callbacks(nullptr)
, m_mutex(nullptr)
, m_owner(nullptr)
, m_firstPendingBuffer(nullptr)
, m_lastPendingBuffer(nullptr)
, m_latency(latency)
, m_bufferTime(bufferTime)
, m_bufferSamplesMax(bufferSamplesMax)
, m_leadingSilence(0)
, m_sampleRate(sampleRate)
, m_isMixing(false)
, m_hasTimestamp(false)
, m_nextPendingBufferConsumePos(0)
, m_nextPendingBufferInsertionPos(0)
, m_numQueuedBuffers(0)
, m_firstBufferSamplesConsumed(0)
{
SDL_AtomicSet(&m_refCount, 1);
}
@@ -190,12 +273,7 @@ GpAudioChannel_SDL2::~GpAudioChannel_SDL2()
if (m_mutex)
m_mutex->Destroy();
while (m_firstPendingBuffer)
{
GpAudioChannelBufferChain_SDL2 *buffer = m_firstPendingBuffer;
m_firstPendingBuffer = buffer->m_next;
buffer->Release();
}
assert(m_numQueuedBuffers == 0);
}
void GpAudioChannel_SDL2::AddRef()
@@ -218,54 +296,70 @@ void GpAudioChannel_SDL2::SetAudioChannelContext(IGpAudioChannelCallbacks *callb
m_callbacks = callbacks;
}
void GpAudioChannel_SDL2::PostBuffer(const void *buffer, size_t bufferSize)
bool GpAudioChannel_SDL2::PostBuffer(IGpAudioBuffer *buffer)
{
buffer->AddRef();
m_mutex->Lock();
while (bufferSize > 0)
if (m_numQueuedBuffers == kMaxBuffers)
{
GpAudioChannelBufferChain_SDL2 *newBuffer = GpAudioChannelBufferChain_SDL2::Alloc();
if (newBuffer == nullptr)
break;
if (m_lastPendingBuffer == nullptr)
m_firstPendingBuffer = newBuffer;
else
m_lastPendingBuffer->m_next = newBuffer;
m_lastPendingBuffer = newBuffer;
size_t bufferable = newBuffer->kMaxCapacity;
if (bufferSize < bufferable)
bufferable = bufferSize;
memcpy(newBuffer->m_data, buffer, bufferable);
buffer = static_cast<const uint8_t*>(buffer) + bufferable;
bufferSize -= bufferable;
m_lastPendingBuffer->m_used = bufferable;
m_lastPendingBuffer->m_hasTrigger = (bufferSize == 0);
m_mutex->Unlock();
buffer->Release();
return false;
}
size_t leadingSilence = 0;
if (m_numQueuedBuffers == 0 && m_hasTimestamp && !m_isMixing)
{
GpAudioDriver_SDL2_TimePoint_t queueTime = GpAudioDriver_SDL2::GetCurrentTime() + m_latency;
if (queueTime > m_timestamp)
{
const GpAudioDriver_SDL2_Duration_t leadTime = queueTime - m_timestamp;
if (leadTime > m_bufferTime)
leadingSilence = m_bufferSamplesMax;
else
{
const GpAudioDriver_SDL2_Rep_t leadTimeRep = leadTime.count();
leadingSilence = leadTimeRep * static_cast<GpAudioDriver_SDL2_Rep_t>(m_sampleRate) * GpAudioDriver_SDL2_Period_t::num / GpAudioDriver_SDL2_Period_t::den;
}
}
}
m_leadingSilence = leadingSilence;
m_pendingBuffers[m_nextPendingBufferInsertionPos++] = static_cast<GpAudioBuffer_SDL2*>(buffer);
m_numQueuedBuffers++;
m_nextPendingBufferInsertionPos = m_nextPendingBufferInsertionPos % kMaxBuffers;
m_mutex->Unlock();
return true;
}
void GpAudioChannel_SDL2::Stop()
{
m_mutex->Lock();
GpAudioChannelBufferChain_SDL2 *buffer = m_firstPendingBuffer;
m_firstPendingBuffer = nullptr;
m_lastPendingBuffer = nullptr;
m_leadingSilence = 0;
while (buffer)
size_t numBuffersToDischarge = m_numQueuedBuffers;
for (size_t i = 0; i < numBuffersToDischarge; i++)
{
if (buffer->m_hasTrigger && m_callbacks)
GpAudioBuffer_SDL2 *buffer = m_pendingBuffers[m_nextPendingBufferConsumePos];
m_nextPendingBufferConsumePos = (m_nextPendingBufferConsumePos + 1) % kMaxBuffers;
m_numQueuedBuffers--;
m_firstBufferSamplesConsumed = 0;
if (m_callbacks)
m_callbacks->NotifyBufferFinished();
GpAudioChannelBufferChain_SDL2 *nextBuffer = buffer->m_next;
buffer->Release();
buffer = nextBuffer;
}
m_mutex->Unlock();
@@ -289,25 +383,57 @@ bool GpAudioChannel_SDL2::Init(GpAudioDriver_SDL2 *driver)
return true;
}
void GpAudioChannel_SDL2::Consume(uint8_t *output, size_t sz)
void GpAudioChannel_SDL2::Consume(int16_t *output, size_t sz, GpAudioDriver_SDL2_TimePoint_t mixStartTime, GpAudioDriver_SDL2_TimePoint_t mixEndTime)
{
m_mutex->Lock();
while (m_firstPendingBuffer != nullptr)
m_isMixing = true;
m_hasTimestamp = true;
m_timestamp = mixEndTime;
if (sz <= m_leadingSilence)
{
GpAudioChannelBufferChain_SDL2 *buffer = m_firstPendingBuffer;
const size_t available = (buffer->m_used - buffer->m_consumed);
memset(output, 0, sz * sizeof(AudioSample_t));
m_leadingSilence -= sz;
m_isMixing = false;
m_mutex->Unlock();
return;
}
else
{
size_t leadingSilence = m_leadingSilence;
if (leadingSilence > 0)
{
memset(output, 0, leadingSilence * sizeof(AudioSample_t));
output += leadingSilence;
sz -= leadingSilence;
m_leadingSilence = 0;
}
}
while (m_numQueuedBuffers > 0)
{
GpAudioBuffer_SDL2 *buffer = m_pendingBuffers[m_nextPendingBufferConsumePos];
const int16_t *bufferData = buffer->GetData();
const size_t bufferSize = buffer->GetSize();
assert(m_firstBufferSamplesConsumed < bufferSize);
const size_t available = (bufferSize - m_firstBufferSamplesConsumed);
if (available <= sz)
{
memcpy(output, buffer->m_data + buffer->m_consumed, available);
memcpy(output, bufferData + m_firstBufferSamplesConsumed, available * sizeof(AudioSample_t));
sz -= available;
output += available;
m_firstPendingBuffer = buffer->m_next;
if (m_firstPendingBuffer == nullptr)
m_lastPendingBuffer = nullptr;
m_nextPendingBufferConsumePos = (m_nextPendingBufferConsumePos + 1) % kMaxBuffers;
m_numQueuedBuffers--;
if (buffer->m_hasTrigger && m_callbacks)
m_firstBufferSamplesConsumed = 0;
if (m_callbacks)
m_callbacks->NotifyBufferFinished();
buffer->Release();
@@ -317,26 +443,28 @@ void GpAudioChannel_SDL2::Consume(uint8_t *output, size_t sz)
}
else
{
memcpy(output, buffer->m_data + buffer->m_consumed, sz);
buffer->m_consumed += sz;
buffer += sz;
memcpy(output, bufferData + m_firstBufferSamplesConsumed, sz * sizeof(AudioSample_t));
m_firstBufferSamplesConsumed += sz;
output += sz;
sz = 0;
break;
}
}
m_isMixing = false;
m_mutex->Unlock();
memset(output, 0x80, sz);
memset(output, 0, sz * sizeof(AudioSample_t));
}
GpAudioChannel_SDL2 *GpAudioChannel_SDL2::Alloc(GpAudioDriver_SDL2 *driver)
GpAudioChannel_SDL2 *GpAudioChannel_SDL2::Alloc(GpAudioDriver_SDL2 *driver, GpAudioDriver_SDL2_Duration_t latency, GpAudioDriver_SDL2_Duration_t bufferTime, size_t bufferSamplesMax, uint16_t sampleRate)
{
void *storage = AlignedAlloc(sizeof(GpAudioChannel_SDL2), GP_SYSTEM_MEMORY_ALIGNMENT);
if (!storage)
return nullptr;
GpAudioChannel_SDL2 *channel = new (storage) GpAudioChannel_SDL2();
GpAudioChannel_SDL2 *channel = new (storage) GpAudioChannel_SDL2(latency, bufferTime, bufferSamplesMax, sampleRate);
if (!channel->Init(driver))
{
channel->Destroy();
@@ -354,15 +482,18 @@ GpAudioDriver_SDL2::GpAudioDriver_SDL2(const GpAudioDriverProperties &properties
: m_properties(properties)
, m_mutex(nullptr)
, m_numChannels(0)
, m_sampleRate(0)
, m_latency(GpAudioDriver_SDL2_Duration_t::zero())
, m_bufferTime(GpAudioDriver_SDL2_Duration_t::zero())
, m_sdlAudioRunning(false)
, m_mixChunkReadOffset(kMixChunkSize)
, m_mixChunkReadOffset(kMixChunkSamples)
, m_audioVolumeScale(kMaxAudioVolumeScale)
{
for (size_t i = 0; i < kMaxChannels; i++)
m_channels[i] = nullptr;
for (size_t i = 0; i < kMixChunkSize; i++)
for (size_t i = 0; i < kMixChunkSamples; i++)
m_mixChunk[i] = 0;
}
@@ -375,9 +506,14 @@ GpAudioDriver_SDL2::~GpAudioDriver_SDL2()
m_mutex->Destroy();
}
IGpAudioBuffer *GpAudioDriver_SDL2::CreateBuffer(const void *data, size_t size)
{
return GpAudioBuffer_SDL2::Create(data, size);
}
IGpAudioChannel *GpAudioDriver_SDL2::CreateChannel()
{
GpAudioChannel_SDL2 *newChannel = GpAudioChannel_SDL2::Alloc(this);
GpAudioChannel_SDL2 *newChannel = GpAudioChannel_SDL2::Alloc(this, m_latency, m_bufferTime, m_bufferSamples, m_sampleRate);
if (!newChannel)
return nullptr;
@@ -437,7 +573,7 @@ bool GpAudioDriver_SDL2::Init()
requestedSpec.channels = 1;
requestedSpec.format = AUDIO_S16;
requestedSpec.freq = m_properties.m_sampleRate;
requestedSpec.samples = 1024;
requestedSpec.samples = kMixChunkSamples;
requestedSpec.userdata = this;
if (SDL_OpenAudio(&requestedSpec, nullptr))
@@ -450,6 +586,10 @@ bool GpAudioDriver_SDL2::Init()
SDL_PauseAudio(0);
m_sdlAudioRunning = true;
m_sampleRate = requestedSpec.freq;
m_latency = GpAudioDriver_SDL2_Duration_t(static_cast<GpAudioDriver_SDL2_Rep_t>(GpAudioDriver_SDL2_Period_t::den * requestedSpec.samples / GpAudioDriver_SDL2_Period_t::num / m_sampleRate));
m_bufferTime = GpAudioDriver_SDL2_Duration_t(static_cast<GpAudioDriver_SDL2_Rep_t>(GpAudioDriver_SDL2_Period_t::den * requestedSpec.samples / GpAudioDriver_SDL2_Period_t::num / m_sampleRate));
m_bufferSamples = requestedSpec.samples;
return true;
}
@@ -492,11 +632,16 @@ void GpAudioDriver_SDL2::MixAudio(void *stream, size_t len)
}
m_mutex->Unlock();
size_t samplesRemaining = len / sizeof(int16_t);
const size_t totalSamples = len / sizeof(int16_t);
size_t samplesRemaining = totalSamples;
GpAudioDriver_SDL2_TimePoint_t audioMixStartTime = GpAudioDriver_SDL2::GetCurrentTime();
GpAudioDriver_SDL2_TimePoint_t audioMixBlockStartTime = audioMixStartTime;
size_t samplesSinceStart = 0;
for (;;)
{
size_t availableInMixChunk = kMixChunkSize - m_mixChunkReadOffset;
size_t availableInMixChunk = kMixChunkSamples - m_mixChunkReadOffset;
if (availableInMixChunk > samplesRemaining)
{
@@ -510,10 +655,17 @@ void GpAudioDriver_SDL2::MixAudio(void *stream, size_t len)
memcpy(stream, m_mixChunk + m_mixChunkReadOffset, availableInMixChunk * sizeof(int16_t));
stream = static_cast<int16_t*>(stream) + availableInMixChunk;
samplesRemaining -= availableInMixChunk;
samplesSinceStart += availableInMixChunk;
GpAudioDriver_SDL2_Duration_t audioMixDurationSinceStart = GpAudioDriver_SDL2_Duration_t(static_cast<GpAudioDriver_SDL2_Rep_t>(GpAudioDriver_SDL2_Period_t::den * samplesSinceStart / GpAudioDriver_SDL2_Period_t::num / m_sampleRate));
GpAudioDriver_SDL2_TimePoint_t audioMixBlockEndTime = audioMixStartTime + audioMixDurationSinceStart;
m_mixChunkReadOffset = 0;
RefillMixChunk(mixingChannels, numChannels);
RefillMixChunk(mixingChannels, numChannels, samplesRemaining, audioMixBlockStartTime, audioMixBlockEndTime);
audioMixBlockStartTime = audioMixBlockEndTime;
samplesRemaining -= availableInMixChunk;
}
}
@@ -521,42 +673,66 @@ void GpAudioDriver_SDL2::MixAudio(void *stream, size_t len)
mixingChannels[i]->Release();
}
void GpAudioDriver_SDL2::RefillMixChunk(GpAudioChannel_SDL2 *const*channels, size_t numChannels)
void GpAudioDriver_SDL2::RefillMixChunk(GpAudioChannel_SDL2 *const*channels, size_t numChannels, size_t maxSamplesToFill, GpAudioDriver_SDL2_TimePoint_t mixStartTime, GpAudioDriver_SDL2_TimePoint_t mixEndTime)
{
uint8_t audioMixBufferUnaligned[kMixChunkSize + GP_SYSTEM_MEMORY_ALIGNMENT];
uint8_t *audioMixBuffer = audioMixBufferUnaligned;
uint8_t audioMixBufferUnaligned[kMixChunkSamples * sizeof(AudioSample_t) + GP_SYSTEM_MEMORY_ALIGNMENT];
uint8_t *audioMixBufferBytes = audioMixBufferUnaligned;
{
uintptr_t bufferPtr = reinterpret_cast<uintptr_t>(audioMixBuffer);
uintptr_t bufferPtr = reinterpret_cast<uintptr_t>(audioMixBufferBytes);
size_t alignPadding = GP_SYSTEM_MEMORY_ALIGNMENT - (bufferPtr % GP_SYSTEM_MEMORY_ALIGNMENT);
audioMixBuffer += alignPadding;
audioMixBufferBytes += alignPadding;
}
AudioSample_t *audioMixBuffer = reinterpret_cast<AudioSample_t*>(audioMixBufferBytes);
bool noAudio = true;
const int16_t audioVolumeScale = m_audioVolumeScale;
size_t samplesToFill = kMixChunkSamples;
if (samplesToFill > maxSamplesToFill)
{
m_mixChunkReadOffset += samplesToFill - maxSamplesToFill;
samplesToFill = maxSamplesToFill;
}
else
m_mixChunkReadOffset = 0;
AudioSample_t *mixChunkStart = m_mixChunk + m_mixChunkReadOffset;
for (size_t i = 0; i < numChannels; i++)
{
channels[i]->Consume(audioMixBuffer, kMixChunkSize);
channels[i]->Consume(audioMixBuffer, samplesToFill, mixStartTime, mixEndTime);
if (i == 0)
{
noAudio = false;
for (size_t j = 0; j < kMixChunkSize; j++)
m_mixChunk[j] = (static_cast<int16_t>(audioMixBuffer[j]) - 0x80) * audioVolumeScale;
memcpy(mixChunkStart, audioMixBuffer, samplesToFill * sizeof(AudioSample_t));
}
else
{
for (size_t j = 0; j < kMixChunkSize; j++)
m_mixChunk[j] += (static_cast<int16_t>(audioMixBuffer[j]) - 0x80) * audioVolumeScale;
}
AddSamples(mixChunkStart, audioMixBuffer, samplesToFill);
}
if (noAudio)
memset(m_mixChunk, 0, kMixChunkSize * sizeof(m_mixChunk[0]));
memset(mixChunkStart, 0, samplesToFill * sizeof(AudioSample_t));
else
{
for (size_t i = 0; i < samplesToFill; i++)
mixChunkStart[i] *= audioVolumeScale;
}
}
void GpAudioDriver_SDL2::AddSamples(AudioSample_t *GP_RESTRICT dest, const AudioSample_t *GP_RESTRICT src, size_t nSamples)
{
for (size_t i = 0; i < nSamples; i++)
dest[i] += src[i];
}
GpAudioDriver_SDL2_TimePoint_t GpAudioDriver_SDL2::GetCurrentTime()
{
return std::chrono::high_resolution_clock::now();
}
IGpAudioDriver *GpDriver_CreateAudioDriver_SDL(const GpAudioDriverProperties &properties)
{

View File

@@ -8,6 +8,7 @@
#include "GpRingBuffer.h"
#include "GpInputDriver_SDL_Gamepad.h"
#include "GpSDL.h"
#include "GpUnicode.h"
#include "IGpCursor.h"
#include "IGpDisplayDriverSurface.h"
#include "IGpLogDriver.h"
@@ -52,68 +53,6 @@ struct GpDisplayDriver_SDL_GL2_Prefs
bool m_isFullScreen;
};
namespace DeleteMe
{
bool DecodeCodePoint(const uint8_t *characters, size_t availableCharacters, size_t &outCharactersDigested, uint32_t &outCodePoint)
{
if (availableCharacters <= 0)
return false;
if ((characters[0] & 0x80) == 0x00)
{
outCharactersDigested = 1;
outCodePoint = characters[0];
return true;
}
size_t sz = 0;
uint32_t codePoint = 0;
uint32_t minCodePoint = 0;
if ((characters[0] & 0xe0) == 0xc0)
{
sz = 2;
minCodePoint = 0x80;
codePoint = (characters[0] & 0x1f);
}
else if ((characters[0] & 0xf0) == 0xe0)
{
sz = 3;
minCodePoint = 0x800;
codePoint = (characters[0] & 0x0f);
}
else if ((characters[0] & 0xf8) == 0xf0)
{
sz = 4;
minCodePoint = 0x10000;
codePoint = (characters[0] & 0x07);
}
else
return false;
if (availableCharacters < sz)
return false;
for (size_t auxByte = 1; auxByte < sz; auxByte++)
{
if ((characters[auxByte] & 0xc0) != 0x80)
return false;
codePoint = (codePoint << 6) | (characters[auxByte] & 0x3f);
}
if (codePoint < minCodePoint || codePoint > 0x10ffff)
return false;
if (codePoint >= 0xd800 && codePoint <= 0xdfff)
return false;
outCodePoint = codePoint;
outCharactersDigested = sz;
return true;
}
}
namespace GpBinarizedShaders
{
extern const char *g_drawQuadV_GL2;
@@ -846,9 +785,6 @@ private:
GpComPtr<GpGLRenderTargetView> m_upscaleTextureRTV;
GpComPtr<GpGLTexture> m_upscaleTexture;
uint32_t m_upscaleTextureWidth;
uint32_t m_upscaleTextureHeight;
GpComPtr<GpGLVertexArray> m_quadVertexArray;
GpComPtr<GpGLBuffer> m_quadVertexBufferKeepalive;
GpComPtr<GpGLBuffer> m_quadIndexBuffer;
@@ -905,7 +841,10 @@ private:
uint32_t m_initialHeightVirtual;
float m_pixelScaleX;
float m_pixelScaleY;
bool m_useUpscaleFilter;
uint32_t m_upscaleTextureWidth;
uint32_t m_upscaleTextureHeight;
GpCursor_SDL2 *m_activeCursor;
GpCursor_SDL2 *m_pendingCursor;
@@ -1197,6 +1136,8 @@ GpDisplayDriver_SDL_GL2::GpDisplayDriver_SDL_GL2(const GpDisplayDriverProperties
, m_pixelScaleX(1.0f)
, m_pixelScaleY(1.0f)
, m_useUpscaleFilter(false)
, m_upscaleTextureWidth(0)
, m_upscaleTextureHeight(0)
, m_pendingCursor(nullptr)
, m_activeCursor(nullptr)
, m_currentStandardCursor(EGpStandardCursors::kArrow)
@@ -1531,8 +1472,7 @@ void GpDisplayDriver_SDL_GL2::ServeTicks(int ticks)
logger->Printf(IGpLogDriver::Category_Information, "Resetting OpenGL context. Physical: %i x %i Virtual %i x %i", static_cast<int>(m_windowWidthPhysical), static_cast<int>(m_windowHeightPhysical), static_cast<int>(m_windowWidthVirtual), static_cast<int>(m_windowHeightVirtual));
// Drop everything and reset
m_res.~InstancedResources();
new (&m_res) InstancedResources();
m_res = InstancedResources();
if (m_firstSurface)
m_firstSurface->DestroyAll();
@@ -1697,6 +1637,14 @@ static bool IdentifyVKey(const SDL_KeyboardEvent *keyEvt, GpKeyIDSubset_t &outSu
return false;
}
break;
case SDLK_LGUI:
outSubset = GpKeyIDSubsets::kSpecial;
outKey.m_specialKey = GpKeySpecials::kLeftCommand;
break;
case SDLK_RGUI:
outSubset = GpKeyIDSubsets::kSpecial;
outKey.m_specialKey = GpKeySpecials::kRightCommand;
break;
case SDLK_LCTRL:
outSubset = GpKeyIDSubsets::kSpecial;
outKey.m_specialKey = GpKeySpecials::kLeftCtrl;
@@ -2040,7 +1988,7 @@ void GpDisplayDriver_SDL_GL2::TranslateSDLMessage(const SDL_Event *msg, IGpVOSEv
{
uint32_t codePoint;
size_t numDigested;
DeleteMe::DecodeCodePoint(reinterpret_cast<const uint8_t*>(teEvt->text) + parseOffset, lenUTF8 - parseOffset, numDigested, codePoint);
GpUnicode::UTF8::Decode(reinterpret_cast<const uint8_t*>(teEvt->text) + parseOffset, lenUTF8 - parseOffset, numDigested, codePoint);
parseOffset += numDigested;
@@ -2458,11 +2406,6 @@ bool GpDisplayDriver_SDL_GL2::InitResources(uint32_t physicalWidth, uint32_t phy
if (logger)
logger->Printf(IGpLogDriver::Category_Information, "GpDisplayDriver_SDL_GL2::InitResources");
if ((m_pixelScaleX < 2.0f && m_pixelScaleX > 1.0f) || (m_pixelScaleY < 2.0f && m_pixelScaleY > 1.0f))
m_useUpscaleFilter = true;
else
m_useUpscaleFilter = false;
CheckGLError(m_gl, logger);
if (!InitBackBuffer(virtualWidth, virtualHeight))
@@ -2539,22 +2482,20 @@ bool GpDisplayDriver_SDL_GL2::InitResources(uint32_t physicalWidth, uint32_t phy
}
GpComPtr<GpGLShader<GL_VERTEX_SHADER>> drawQuadVertexShader = CreateShader<GL_VERTEX_SHADER>(GpBinarizedShaders::g_drawQuadV_GL2);
GpComPtr<GpGLShader<GL_FRAGMENT_SHADER>> drawQuadPaletteFlickerPixelShader = CreateShader<GL_FRAGMENT_SHADER>(GpBinarizedShaders::g_drawQuadPalettePF_GL2);
GpComPtr<GpGLShader<GL_FRAGMENT_SHADER>> drawQuadPaletteNoFlickerPixelShader = CreateShader<GL_FRAGMENT_SHADER>(GpBinarizedShaders::g_drawQuadPalettePNF_GL2);
GpComPtr<GpGLShader<GL_FRAGMENT_SHADER>> drawQuad32FlickerPixelShader = CreateShader<GL_FRAGMENT_SHADER>(GpBinarizedShaders::g_drawQuad32PF_GL2);
GpComPtr<GpGLShader<GL_FRAGMENT_SHADER>> drawQuad32NoFlickerPixelShader = CreateShader<GL_FRAGMENT_SHADER>(GpBinarizedShaders::g_drawQuad32PNF_GL2);
GpComPtr<GpGLShader<GL_FRAGMENT_SHADER>> drawQuadPaletteICCFPixelShader = CreateShader<GL_FRAGMENT_SHADER>(GpBinarizedShaders::g_drawQuadPaletteICCPF_GL2);
GpComPtr<GpGLShader<GL_FRAGMENT_SHADER>> drawQuadPaletteICCNFPixelShader = CreateShader<GL_FRAGMENT_SHADER>(GpBinarizedShaders::g_drawQuadPaletteICCPNF_GL2);
GpComPtr<GpGLShader<GL_FRAGMENT_SHADER>> drawQuad32ICCFPixelShader = CreateShader<GL_FRAGMENT_SHADER>(GpBinarizedShaders::g_drawQuad32ICCPF_GL2);
GpComPtr<GpGLShader<GL_FRAGMENT_SHADER>> drawQuad32ICCNFPixelShader = CreateShader<GL_FRAGMENT_SHADER>(GpBinarizedShaders::g_drawQuad32ICCPNF_GL2);
GpComPtr<GpGLShader<GL_FRAGMENT_SHADER>> scaleQuadPixelShader = CreateShader<GL_FRAGMENT_SHADER>(GpBinarizedShaders::g_scaleQuadP_GL2);
GpComPtr<GpGLShader<GL_FRAGMENT_SHADER>> copyQuadPixelShader = CreateShader<GL_FRAGMENT_SHADER>(GpBinarizedShaders::g_copyQuadP_GL2);
if (!m_res.m_drawQuadPaletteFlickerProgram.Link(this, drawQuadVertexShader, drawQuadPaletteFlickerPixelShader)
|| !m_res.m_drawQuadPaletteNoFlickerProgram.Link(this, drawQuadVertexShader, drawQuadPaletteNoFlickerPixelShader)
if (!m_res.m_drawQuadPaletteFlickerProgram.Link(this, drawQuadVertexShader, drawQuadPaletteFlickerPixelShader) ||
!m_res.m_drawQuadPaletteNoFlickerProgram.Link(this, drawQuadVertexShader, drawQuadPaletteNoFlickerPixelShader)
|| !m_res.m_drawQuad32FlickerProgram.Link(this, drawQuadVertexShader, drawQuad32FlickerPixelShader)
|| !m_res.m_drawQuad32NoFlickerProgram.Link(this, drawQuadVertexShader, drawQuad32NoFlickerPixelShader)
|| !m_res.m_drawQuadPaletteICCFlickerProgram.Link(this, drawQuadVertexShader, drawQuadPaletteICCFPixelShader)
@@ -2562,8 +2503,8 @@ bool GpDisplayDriver_SDL_GL2::InitResources(uint32_t physicalWidth, uint32_t phy
|| !m_res.m_drawQuad32ICCFlickerProgram.Link(this, drawQuadVertexShader, drawQuad32ICCFPixelShader)
|| !m_res.m_drawQuad32ICCNoFlickerProgram.Link(this, drawQuadVertexShader, drawQuad32ICCNFPixelShader)
//|| !m_drawQuadRGBICCProgram.Link(this, drawQuadVertexShader, drawQuadRGBICCPixelShader)
//|| !m_drawQuad15BitICCProgram.Link(this, drawQuadVertexShader, drawQuad15BitICCPixelShader)
// || !m_drawQuadRGBICCProgram.Link(this, drawQuadVertexShader, drawQuadRGBICCPixelShader)
// || !m_drawQuad15BitICCProgram.Link(this, drawQuadVertexShader, drawQuad15BitICCPixelShader)
|| !m_res.m_scaleQuadProgram.Link(this, drawQuadVertexShader, scaleQuadPixelShader)
|| !m_res.m_copyQuadProgram.Link(this, drawQuadVertexShader, copyQuadPixelShader))
return false;
@@ -2778,8 +2719,9 @@ bool GpDisplayDriver_SDL_GL2::InitBackBuffer(uint32_t width, uint32_t height)
m_gl.BindFramebuffer(GL_FRAMEBUFFER, 0);
}
m_useUpscaleFilter = (m_pixelScaleX == 1.5f || m_pixelScaleX == 2.5f || m_pixelScaleY == 1.5f || m_pixelScaleY == 2.5f);
if (m_pixelScaleX != floor(m_pixelScaleX) || m_pixelScaleY != floor(m_pixelScaleY))
if (m_useUpscaleFilter)
{
uint32_t upscaleX = ceil(m_pixelScaleX);
uint32_t upscaleY = ceil(m_pixelScaleY);
@@ -2794,8 +2736,8 @@ bool GpDisplayDriver_SDL_GL2::InitBackBuffer(uint32_t width, uint32_t height)
return false;
}
m_res.m_upscaleTextureWidth = width * upscaleX;
m_res.m_upscaleTextureHeight = height * upscaleY;
m_upscaleTextureWidth = width * upscaleX;
m_upscaleTextureHeight = height * upscaleY;
GLenum internalFormat = SupportsSizedFormats() ? GL_RGBA8 : GL_RGBA;
@@ -2805,7 +2747,7 @@ bool GpDisplayDriver_SDL_GL2::InitBackBuffer(uint32_t width, uint32_t height)
m_gl.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
m_gl.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
m_gl.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
m_gl.TexImage2D(GL_TEXTURE_2D, 0, internalFormat, m_res.m_upscaleTextureWidth, m_res.m_upscaleTextureHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
m_gl.TexImage2D(GL_TEXTURE_2D, 0, internalFormat, m_upscaleTextureWidth, m_upscaleTextureHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
m_gl.BindTexture(GL_TEXTURE_2D, 0);
CheckGLError(m_gl, logger);
@@ -2850,7 +2792,7 @@ void GpDisplayDriver_SDL_GL2::ScaleVirtualScreen()
{
m_gl.BindFramebuffer(GL_FRAMEBUFFER, m_res.m_upscaleTextureRTV->GetID());
m_gl.Viewport(0, 0, m_res.m_upscaleTextureWidth, m_res.m_upscaleTextureHeight);
m_gl.Viewport(0, 0, m_upscaleTextureWidth, m_upscaleTextureHeight);
const BlitQuadProgram &program = m_res.m_scaleQuadProgram;

View File

@@ -177,8 +177,6 @@ void GpInputDriverSDLGamepad::HandleDeviceRemoved(SDL_JoystickID joystickID)
{
m_playerButtonDown[playerNum][button] = false;
GpVOSEvent evt;
evt.m_eventType = GpVOSEventTypes::kKeyboardInput;
evt.m_event.m_keyboardInputEvent.m_eventType = GpKeyboardInputEventTypes::kUp;
@@ -197,7 +195,7 @@ void GpInputDriverSDLGamepad::ProcessSDLEvent(const SDL_Event &msg)
IGpVOSEventQueue *evtQueue = m_properties.m_eventQueue;
switch (msg.type)
{
{
case SDL_CONTROLLERAXISMOTION:
{
const SDL_ControllerAxisEvent &axisMsg = msg.caxis;
@@ -231,8 +229,8 @@ void GpInputDriverSDLGamepad::ProcessSDLEvent(const SDL_Event &msg)
m_pendingEvents.push_back(evt);
}
break;
case SDL_CONTROLLERBUTTONDOWN:
break;
case SDL_CONTROLLERBUTTONDOWN:
case SDL_CONTROLLERBUTTONUP:
{
const bool isDown = (msg.type == SDL_CONTROLLERBUTTONDOWN);
@@ -287,22 +285,22 @@ void GpInputDriverSDLGamepad::ProcessSDLEvent(const SDL_Event &msg)
m_pendingEvents.push_back(evt);
}
break;
break;
case SDL_CONTROLLERDEVICEADDED:
HandleDeviceAdded(msg.cdevice.which);
break;
break;
case SDL_CONTROLLERDEVICEREMOVED:
HandleDeviceRemoved(msg.cdevice.which);
break;
break;
case SDL_CONTROLLERDEVICEREMAPPED:
// Not really sure what to do here, just re-add it
HandleDeviceRemoved(msg.cdevice.which);
HandleDeviceAdded(msg.cdevice.which);
break;
}
break;
}
}
IGpInputDriver *GpDriver_CreateInputDriver_SDL2_Gamepad(const GpInputDriverProperties &properties)
{
return GpInputDriverSDLGamepad::Create(properties);
return GpInputDriverSDLGamepad::Create(properties);
}

View File

@@ -1,6 +1,7 @@
#include "SDL.h"
#include "GpMain.h"
#include "GpAllocator_C.h"
#include "GpAudioDriverFactory.h"
#include "GpDisplayDriverFactory.h"
#include "GpGlobalConfig.h"
@@ -36,6 +37,12 @@ IGpInputDriver *GpDriver_CreateInputDriver_SDL2_Gamepad(const GpInputDriverPrope
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
IGpAllocator *alloc = GpAllocator_C::GetInstance();
GpFileSystem_Win32 *fs = GpFileSystem_Win32::CreateInstance(alloc);
if (!fs)
return -1;
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMECONTROLLER) < 0)
return -1;
@@ -56,9 +63,10 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
IGpLogDriver *logger = GpLogDriver_Win32::GetInstance();
GpDriverCollection *drivers = GpAppInterface_Get()->PL_GetDriverCollection();
drivers->SetDriver<GpDriverIDs::kFileSystem>(GpFileSystem_Win32::GetInstance());
drivers->SetDriver<GpDriverIDs::kFileSystem>(fs);
drivers->SetDriver<GpDriverIDs::kSystemServices>(GpSystemServices_Win32::GetInstance());
drivers->SetDriver<GpDriverIDs::kLog>(GpLogDriver_Win32::GetInstance());
drivers->SetDriver<GpDriverIDs::kAlloc>(GpAllocator_C::GetInstance());
g_gpWindowsGlobals.m_hInstance = hInstance;
g_gpWindowsGlobals.m_hPrevInstance = hPrevInstance;
@@ -86,6 +94,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
g_gpGlobalConfig.m_osGlobals = &g_gpWindowsGlobals;
g_gpGlobalConfig.m_logger = logger;
g_gpGlobalConfig.m_systemServices = GpSystemServices_Win32::GetInstance();
g_gpGlobalConfig.m_allocator = alloc;
GpDisplayDriverFactory::RegisterDisplayDriverFactory(EGpDisplayDriverType_SDL_GL2, GpDriver_CreateDisplayDriver_SDL_GL2);
GpAudioDriverFactory::RegisterAudioDriverFactory(EGpAudioDriverType_SDL2, GpDriver_CreateAudioDriver_SDL);
@@ -102,5 +111,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
LocalFree(cmdLineArgs);
fs->Destroy();
return returnCode;
}

View File

@@ -11,6 +11,6 @@
"}\n"
namespace GpBinarizedShaders
{
{
const char *g_copyQuadP_GL2 = GP_GL_SHADER_CODE_MEDIUM_PRECISION_PREFIX GP_GL_SHADER_CODE_FUNCTIONS_H GP_GL_SHADER_CODE_COPYQUADP_GLSL;
}

View File

@@ -17,7 +17,7 @@
" vec4 resultColor = vec4(SamplePixel(texCoord.xy), 1.0);\n"\
" resultColor *= constants_Modulation;\n"\
"#ifdef ENABLE_FLICKER\n"\
" resultColor = ApplyFlicker(constants_FlickerAxis, texCoord.zw, constants_FlickerStartThreshold, constants_FlickerEndThreshold, resultColor * constants_Modulation);\n"\
" resultColor = ApplyFlicker(constants_FlickerAxis, texCoord.zw, constants_FlickerStartThreshold, constants_FlickerEndThreshold, resultColor);\n"\
" if (resultColor.a < 1.0)\n"\
" discard;\n"\
"#endif\n"\

View File

@@ -18,7 +18,7 @@
" vec4 resultColor = vec4(SamplePixel(texCoord.xy), 1.0);\n"\
" resultColor *= constants_Modulation;\n"\
"#ifdef ENABLE_FLICKER\n"\
" resultColor = ApplyFlicker(constants_FlickerAxis, texCoord.zw, constants_FlickerStartThreshold, constants_FlickerEndThreshold, resultColor * constants_Modulation);\n"\
" resultColor = ApplyFlicker(constants_FlickerAxis, texCoord.zw, constants_FlickerStartThreshold, constants_FlickerEndThreshold, resultColor);\n"\
" if (resultColor.a < 1.0)\n"\
" discard;\n"\
"#endif\n"\

View File

@@ -1,7 +1,10 @@
#define GP_GL_SHADER_CODE_MEDIUM_PRECISION_PREFIX "precision mediump float;\n"\
#define GP_GL_SHADER_CODE_HIGH_PRECISION_PREFIX "precision highp float;\n"\
#ifdef __MACOS__
#define GP_GL_SHADER_CODE_MEDIUM_PRECISION_PREFIX ""
#define GP_GL_SHADER_CODE_HIGH_PRECISION_PREFIX ""
#else
#define GP_GL_SHADER_CODE_MEDIUM_PRECISION_PREFIX "precision mediump float;\n"
#define GP_GL_SHADER_CODE_HIGH_PRECISION_PREFIX "precision highp float;\n"
#endif
#define GP_GL_SHADER_CODE_FUNCTIONS_H "vec3 pow3(vec3 v, float ex)\n"\
"{\n"\
@@ -58,7 +61,7 @@
"vec4 ApplyDesaturation(float desaturation, vec4 color)\n"\
"{\n"\
" // This is intentionally done in gamma space\n"\
" if (desaturation == 0.0)\n"\
" if (desaturation == 0.0 || (color.r == 1.0 && color.g == 1.0 && color.b == 0.0))\n"\
" return color;\n"\
"\n"\
" float grayLevel = dot(color.rgb, vec3(3.0, 6.0, 1.0) / 10.0);\n"\

View File

@@ -0,0 +1,11 @@
set INPUT_DIR=../AerofoilPortable
set OUTPUT_DIR=obj
rem set DEBUG_LEVEL_FLAGS=-g4 -O0
set DEBUG_LEVEL_FLAGS=-O3 -DNDEBUG=1
set FLAGS=-s USE_SDL=2 -flto -I../GpCommon/ -I../Common/ -s ASYNCIFY %DEBUG_LEVEL_FLAGS% -DGP_DEBUG_CONFIG=0
emcc -c %INPUT_DIR%/GpAllocator_C.cpp -o %OUTPUT_DIR%/AerofoilPortable_Combined.o %FLAGS%
pause

View File

@@ -1,6 +1,10 @@
set INPUT_DIR=../AerofoilSDL
set OUTPUT_DIR=obj
set FLAGS=-s USE_SDL=2 -flto -I../GpCommon/ -I../PortabilityLayer/ -I../Common/ -s ASYNCIFY -O3 -DGP_DEBUG_CONFIG=0
rem set DEBUG_LEVEL_FLAGS=-g4 -O0
set DEBUG_LEVEL_FLAGS=-O3 -DNDEBUG=1
set FLAGS=-s USE_SDL=2 -flto -I../GpCommon/ -I../PortabilityLayer/ -I../Common/ -s ASYNCIFY %DEBUG_LEVEL_FLAGS% -DGP_DEBUG_CONFIG=0
emcc -c %INPUT_DIR%/AerofoilSDL_Combined.cpp -o %OUTPUT_DIR%/AerofoilSDL_Combined.o %FLAGS%

View File

@@ -1,6 +1,10 @@
set INPUT_DIR=.
set OUTPUT_DIR=obj
set FLAGS=-s USE_SDL=2 -flto -I../GpCommon/ -I../PortabilityLayer/ -I../Common/ -I../GpShell/ -s ASYNCIFY -O3 -DGP_DEBUG_CONFIG=0
rem set DEBUG_LEVEL_FLAGS=-g4 -O0
set DEBUG_LEVEL_FLAGS=-O3 -DNDEBUG=1
set FLAGS=-s USE_SDL=2 -flto -I../GpCommon/ -I../PortabilityLayer/ -I../Common/ -I../AerofoilPortable/ -I../GpShell/ -s ASYNCIFY %DEBUG_LEVEL_FLAGS% -DGP_DEBUG_CONFIG=0
emcc -c %INPUT_DIR%/AerofoilWeb_Combined.cpp -o %OUTPUT_DIR%/AerofoilWeb_Combined.o %FLAGS%

View File

@@ -1,6 +1,10 @@
set INPUT_DIR=../GpApp
set OUTPUT_DIR=obj
set FLAGS=-s USE_SDL=2 -flto -I../GpCommon/ -I../PortabilityLayer/ -I../Common/ -s ASYNCIFY -O3 -DGP_DEBUG_CONFIG=0
rem set DEBUG_LEVEL_FLAGS=-g4 -O0
set DEBUG_LEVEL_FLAGS=-O3 -DNDEBUG=1
set FLAGS=-s USE_SDL=2 -flto -I../GpCommon/ -I../PortabilityLayer/ -I../Common/ -s ASYNCIFY %DEBUG_LEVEL_FLAGS% -DGP_DEBUG_CONFIG=0
emcc -c %INPUT_DIR%/GpApp_Combined.cpp -o %OUTPUT_DIR%/GpApp_Combined.o %FLAGS%

View File

@@ -1,6 +1,10 @@
set INPUT_DIR=../GpShell
set OUTPUT_DIR=obj
set FLAGS=-s USE_SDL=2 -flto -I../GpCommon/ -I../PortabilityLayer/ -I../Common/ -s ASYNCIFY -O3 -DGP_DEBUG_CONFIG=0
rem set DEBUG_LEVEL_FLAGS=-g4 -O0
set DEBUG_LEVEL_FLAGS=-O3 -DNDEBUG=1
set FLAGS=-s USE_SDL=2 -flto -I../GpCommon/ -I../PortabilityLayer/ -I../Common/ -s ASYNCIFY %DEBUG_LEVEL_FLAGS% -DGP_DEBUG_CONFIG=0
emcc -c %INPUT_DIR%/GpShell_Combined.cpp -o %OUTPUT_DIR%/GpShell_Combined.o %FLAGS%

View File

@@ -1,6 +1,10 @@
set INPUT_DIR=../MacRomanConversion
set OUTPUT_DIR=obj
set FLAGS=-flto -I../MacRomanConversion/ -s ASYNCIFY -O3
rem set DEBUG_LEVEL_FLAGS=-g4 -O0
set DEBUG_LEVEL_FLAGS=-O3 -DNDEBUG=1
set FLAGS=-flto -I../MacRomanConversion/ -s ASYNCIFY %DEBUG_LEVEL_FLAGS%
emcc -c %INPUT_DIR%/MacRomanConversion.cpp -o %OUTPUT_DIR%/MacRomanConversion.o %FLAGS%

View File

@@ -1,6 +1,10 @@
set INPUT_DIR=../PortabilityLayer
set OUTPUT_DIR=obj
set FLAGS=-s USE_ZLIB=1 -flto -I../GpCommon/ -I../Common/ -I../PortabilityLayer/ -I../rapidjson/include/ -I../MacRomanConversion/ -I../stb/ -s ASYNCIFY -O3 -DGP_DEBUG_CONFIG=0 -Wno-tautological-constant-out-of-range-compare
rem set DEBUG_LEVEL_FLAGS=-g4 -O0
set DEBUG_LEVEL_FLAGS=-O3 -DNDEBUG=1
set FLAGS=-s USE_ZLIB=1 -flto -I../GpCommon/ -I../Common/ -I../PortabilityLayer/ -I../rapidjson/include/ -I../MacRomanConversion/ -I../stb/ -s ASYNCIFY %DEBUG_LEVEL_FLAGS% -DGP_DEBUG_CONFIG=0 -Wno-tautological-constant-out-of-range-compare
emcc -c %INPUT_DIR%/PortabilityLayer_Combined.cpp -o %OUTPUT_DIR%/PortabilityLayer_Combined.o %FLAGS%

File diff suppressed because it is too large Load Diff

View File

@@ -21,7 +21,7 @@ public:
bool FileExists(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *path) override;
bool FileLocked(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *path, bool &exists) override;
GpIOStream *OpenFileNested(PortabilityLayer::VirtualDirectory_t virtualDirectory, char const* const* subPaths, size_t numSubPaths, bool writeAccess, GpFileCreationDisposition_t createDisposition) override;
bool DeleteFile(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *path, bool &existed) override;
bool DeleteFile(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *path, bool &existed) GP_ASYNCIFY_PARANOID_OVERRIDE;
IGpDirectoryCursor *ScanDirectoryNested(PortabilityLayer::VirtualDirectory_t virtualDirectory, char const* const* paths, size_t numPaths) override;
bool ValidateFilePath(const char *path, size_t pathLen) const override;
@@ -29,6 +29,10 @@ public:
void SetDelayCallback(DelayCallback_t delayCallback) override;
static void MarkFSStateDirty();
static void SyncDownloadFile(const std::string &filePath, const std::string &prettyName);
static void FlushFS();
static GpFileSystem_Web *GetInstance();
private:
@@ -51,12 +55,14 @@ private:
static IGpDirectoryCursor *ScanCatalog(const GpFileSystem_Web_Resources::FileCatalog &catalog);
bool ResolvePath(PortabilityLayer::VirtualDirectory_t virtualDirectory, char const* const* paths, size_t numPaths, std::string &resolution);
bool ResolvePath(PortabilityLayer::VirtualDirectory_t virtualDirectory, char const* const* paths, size_t numPaths, bool trailingSlash, std::string &resolution, bool &outIsIDB);
DelayCallback_t m_delayCallback;
std::string m_prefsPath;
std::string m_basePath;
std::string m_exportPath;
static bool ms_fsStateDirty;
static GpFileSystem_Web ms_instance;
};

View File

@@ -58,8 +58,8 @@ void GpLogDriver_Web::VPrintf(Category category, const char *fmt, va_list args)
vsnprintf(charBuff, formattedSize + 1, fmt, args);
fprintf(stderr, "%s%s%s\n", timestampBuffer, debugTag, charBuff);
fflush(stderr);
fprintf(stdout, "%s%s%s\n", timestampBuffer, debugTag, charBuff);
fflush(stdout);
free(charBuff);
}

View File

@@ -1,91 +1,109 @@
#include <SDL.h>
#include "SDL_main.h"
#include "GpMain.h"
#include "GpAudioDriverFactory.h"
#include "GpDisplayDriverFactory.h"
#include "GpGlobalConfig.h"
#include "GpFileSystem_Web.h"
#include "GpLogDriver_Web.h"
#include "GpFontHandlerFactory.h"
#include "GpInputDriverFactory.h"
#include "GpAppInterface.h"
#include "GpSystemServices_Web.h"
#include "GpVOSEvent.h"
#include "GpX.h"
#include "IGpFileSystem.h"
#include "IGpThreadEvent.h"
#include "IGpVOSEventQueue.h"
#include <string>
GpXGlobals g_gpXGlobals;
extern "C" IGpFontHandler *GpDriver_CreateFontHandler_FreeType2(const GpFontHandlerProperties &properties);
IGpDisplayDriver *GpDriver_CreateDisplayDriver_SDL_GL2(const GpDisplayDriverProperties &properties);
IGpAudioDriver *GpDriver_CreateAudioDriver_SDL(const GpAudioDriverProperties &properties);
IGpInputDriver *GpDriver_CreateInputDriver_SDL2_Gamepad(const GpInputDriverProperties &properties);
int main(int argc, char* argv[])
{
GpLogDriver_Web::Init();
IGpLogDriver *logger = GpLogDriver_Web::GetInstance();
#if GP_ASYNCIFY_PARANOID
SDL_SetHint(SDL_HINT_EMSCRIPTEN_ASYNCIFY, "0");
#endif
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMECONTROLLER) < 0)
return -1;
if (logger)
logger->Printf(IGpLogDriver::Category_Information, "Starting filesystem...");
GpFileSystem_Web::GetInstance()->Init();
GpDriverCollection *drivers = GpAppInterface_Get()->PL_GetDriverCollection();
if (logger)
logger->Printf(IGpLogDriver::Category_Information, "Setting up drivers...");
drivers->SetDriver<GpDriverIDs::kFileSystem>(GpFileSystem_Web::GetInstance());
drivers->SetDriver<GpDriverIDs::kSystemServices>(GpSystemServices_Web::GetInstance());
drivers->SetDriver<GpDriverIDs::kLog>(GpLogDriver_Web::GetInstance());
g_gpGlobalConfig.m_displayDriverType = EGpDisplayDriverType_SDL_GL2;
g_gpGlobalConfig.m_audioDriverType = EGpAudioDriverType_SDL2;
g_gpGlobalConfig.m_fontHandlerType = EGpFontHandlerType_None;
EGpInputDriverType inputDrivers[] =
{
EGpInputDriverType_SDL2_Gamepad
};
g_gpGlobalConfig.m_inputDriverTypes = inputDrivers;
g_gpGlobalConfig.m_numInputDrivers = sizeof(inputDrivers) / sizeof(inputDrivers[0]);
g_gpGlobalConfig.m_osGlobals = &g_gpXGlobals;
g_gpGlobalConfig.m_logger = logger;
g_gpGlobalConfig.m_systemServices = GpSystemServices_Web::GetInstance();
GpDisplayDriverFactory::RegisterDisplayDriverFactory(EGpDisplayDriverType_SDL_GL2, GpDriver_CreateDisplayDriver_SDL_GL2);
GpAudioDriverFactory::RegisterAudioDriverFactory(EGpAudioDriverType_SDL2, GpDriver_CreateAudioDriver_SDL);
GpInputDriverFactory::RegisterInputDriverFactory(EGpInputDriverType_SDL2_Gamepad, GpDriver_CreateInputDriver_SDL2_Gamepad);
if (logger)
logger->Printf(IGpLogDriver::Category_Information, "SDL environment configured, starting up");
int returnCode = GpMain::Run();
if (logger)
logger->Printf(IGpLogDriver::Category_Information, "SDL environment exited with code %i, cleaning up", returnCode);
SDL_Quit();
return returnCode;
}
#include <SDL.h>
#include "SDL_main.h"
#include "GpMain.h"
#include "GpAllocator_C.h"
#include "GpAudioDriverFactory.h"
#include "GpDisplayDriverFactory.h"
#include "GpGlobalConfig.h"
#include "GpFileSystem_Web.h"
#include "GpLogDriver_Web.h"
#include "GpFontHandlerFactory.h"
#include "GpInputDriverFactory.h"
#include "GpAppInterface.h"
#include "GpSystemServices_Web.h"
#include "GpVOSEvent.h"
#include "GpX.h"
#include "IGpFileSystem.h"
#include "IGpThreadEvent.h"
#include "IGpVOSEventQueue.h"
#include <string>
#include <emscripten.h>
GpXGlobals g_gpXGlobals;
IGpDisplayDriver *GpDriver_CreateDisplayDriver_SDL_GL2(const GpDisplayDriverProperties &properties);
IGpAudioDriver *GpDriver_CreateAudioDriver_SDL(const GpAudioDriverProperties &properties);
IGpInputDriver *GpDriver_CreateInputDriver_SDL2_Gamepad(const GpInputDriverProperties &properties);
EM_JS(void, InitFileSystem, (), {
Asyncify.handleSleep(wakeUp => {
FS.mkdir('/aerofoil');
FS.mkdir('/aerofoil_memfs');
FS.mount(IDBFS, {}, '/aerofoil');
FS.mount(MEMFS, {}, '/aerofoil_memfs');
FS.syncfs(true, function (err) {
assert(!err);
wakeUp();
});
});
});
int main(int argc, char* argv[])
{
IGpAllocator *alloc = GpAllocator_C::GetInstance();
InitFileSystem();
GpLogDriver_Web::Init();
IGpLogDriver *logger = GpLogDriver_Web::GetInstance();
#if GP_ASYNCIFY_PARANOID
SDL_SetHint(SDL_HINT_EMSCRIPTEN_ASYNCIFY, "0");
#endif
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMECONTROLLER) < 0)
return -1;
if (logger)
logger->Printf(IGpLogDriver::Category_Information, "Starting filesystem...");
GpFileSystem_Web::GetInstance()->Init();
GpDriverCollection *drivers = GpAppInterface_Get()->PL_GetDriverCollection();
if (logger)
logger->Printf(IGpLogDriver::Category_Information, "Setting up drivers...");
drivers->SetDriver<GpDriverIDs::kFileSystem>(GpFileSystem_Web::GetInstance());
drivers->SetDriver<GpDriverIDs::kSystemServices>(GpSystemServices_Web::GetInstance());
drivers->SetDriver<GpDriverIDs::kLog>(GpLogDriver_Web::GetInstance());
drivers->SetDriver<GpDriverIDs::kAlloc>(alloc);
g_gpGlobalConfig.m_displayDriverType = EGpDisplayDriverType_SDL_GL2;
g_gpGlobalConfig.m_audioDriverType = EGpAudioDriverType_SDL2;
g_gpGlobalConfig.m_fontHandlerType = EGpFontHandlerType_None;
EGpInputDriverType inputDrivers[] =
{
EGpInputDriverType_SDL2_Gamepad
};
g_gpGlobalConfig.m_inputDriverTypes = inputDrivers;
g_gpGlobalConfig.m_numInputDrivers = sizeof(inputDrivers) / sizeof(inputDrivers[0]);
g_gpGlobalConfig.m_osGlobals = &g_gpXGlobals;
g_gpGlobalConfig.m_logger = logger;
g_gpGlobalConfig.m_systemServices = GpSystemServices_Web::GetInstance();
g_gpGlobalConfig.m_allocator = alloc;
GpDisplayDriverFactory::RegisterDisplayDriverFactory(EGpDisplayDriverType_SDL_GL2, GpDriver_CreateDisplayDriver_SDL_GL2);
GpAudioDriverFactory::RegisterAudioDriverFactory(EGpAudioDriverType_SDL2, GpDriver_CreateAudioDriver_SDL);
GpInputDriverFactory::RegisterInputDriverFactory(EGpInputDriverType_SDL2_Gamepad, GpDriver_CreateInputDriver_SDL2_Gamepad);
if (logger)
logger->Printf(IGpLogDriver::Category_Information, "SDL environment configured, starting up");
int returnCode = GpMain::Run();
if (logger)
logger->Printf(IGpLogDriver::Category_Information, "SDL environment exited with code %i, cleaning up", returnCode);
SDL_Quit();
return returnCode;
}

View File

@@ -136,8 +136,9 @@ void *GpSystemServices_Web::CreateThread(ThreadFunc_t threadFunc, void *context)
return nullptr;
}
void GpSystemServices_Web::Beep() const
bool GpSystemServices_Web::Beep() const
{
return false;
}
bool GpSystemServices_Web::IsTouchscreen() const
@@ -165,6 +166,21 @@ bool GpSystemServices_Web::IsFullscreenOnStartup() const
return false;
}
bool GpSystemServices_Web::HasNativeFileManager() const
{
return false;
}
GpOperatingSystem_t GpSystemServices_Web::GetOperatingSystem() const
{
return GpOperatingSystems::kWeb;
}
GpOperatingSystemFlavor_t GpSystemServices_Web::GetOperatingSystemFlavor() const
{
return GpOperatingSystemFlavors::kGeneric;
}
unsigned int GpSystemServices_Web::GetCPUCount() const
{
return SDL_GetCPUCount();

View File

@@ -12,12 +12,15 @@ public:
~GpSystemServices_Web();
void *CreateThread(ThreadFunc_t threadFunc, void *context) override;
void Beep() const override;
bool Beep() const override;
bool IsTouchscreen() const override;
bool IsUsingMouseAsTouch() const override;
bool IsTextInputObstructive() const override;
bool IsFullscreenPreferred() const override;
bool IsFullscreenOnStartup() const override;
bool HasNativeFileManager() const override;
GpOperatingSystem_t GetOperatingSystem() const override;
GpOperatingSystemFlavor_t GetOperatingSystemFlavor() const override;
unsigned int GetCPUCount() const override;
void SetTextInputEnabled(bool isEnabled) override;
bool IsTextInputEnabled() const override;

View File

@@ -1,5 +1,10 @@
set INPUT_DIR=.
set OUTPUT_DIR=bin
set FLAGS=-flto -O3 -s USE_SDL=2 -s USE_ZLIB=1 -s ASYNCIFY -s ASYNCIFY_IGNORE_INDIRECT -s INITIAL_MEMORY=33554432 -s ASYNCIFY_ADVISE
emcc obj/AerofoilWeb_Combined.o obj/AerofoilWeb_Resources.o obj/GpShell_Combined.o obj/AerofoilSDL_Combined.o obj/GpApp_Combined.o obj/PortabilityLayer_Combined.o obj/MacRomanConversion.o -o %OUTPUT_DIR%/aerofoil.html %FLAGS%
rem set DEBUG_LEVEL_FLAGS=-g4 -O0
set DEBUG_LEVEL_FLAGS=-O3
copy /Y FileSaverDotJS\dist\FileSaver.js bin\FileSaver.js
set FLAGS=-flto %DEBUG_LEVEL_FLAGS% -s USE_SDL=2 -s USE_ZLIB=1 -s ASYNCIFY -s ASYNCIFY_IGNORE_INDIRECT -s INITIAL_MEMORY=33554432 -s ASYNCIFY_ADVISE -lidbfs.js -s ASYNCIFY_IMPORTS=['InitFileSystem','FlushFileSystem'] --shell-file shell_minimal.html
emcc obj/AerofoilWeb_Combined.o obj/AerofoilWeb_Resources.o obj/GpShell_Combined.o obj/AerofoilSDL_Combined.o obj/AerofoilPortable_Combined.o obj/GpApp_Combined.o obj/PortabilityLayer_Combined.o obj/MacRomanConversion.o -o %OUTPUT_DIR%/aerofoil.html %FLAGS%

View File

@@ -0,0 +1,141 @@
<!doctype html>
<html lang="en-us">
<head>
<meta charset="utf-8">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Aerofoil</title>
<style>
.emscripten { padding-right: 0; padding-top: 0; margin-left: auto; margin-right: auto; margin-top: 0; display: block; }
textarea.emscripten { font-family: monospace; width: 80%; }
div.emscripten { text-align: center; }
div.emscripten_border { border: 1px solid black; }
/* the canvas *must not* have any border or padding, or mouse coords will be wrong */
canvas.emscripten { border: 0px none; background-color: black; }
.spinner {
height: 50px;
width: 50px;
margin: 0px auto;
-webkit-animation: rotation .8s linear infinite;
-moz-animation: rotation .8s linear infinite;
-o-animation: rotation .8s linear infinite;
animation: rotation 0.8s linear infinite;
border-left: 10px solid rgb(0,150,240);
border-right: 10px solid rgb(0,150,240);
border-bottom: 10px solid rgb(0,150,240);
border-top: 10px solid rgb(100,0,200);
border-radius: 100%;
background-color: rgb(200,100,250);
}
@-webkit-keyframes rotation {
from {-webkit-transform: rotate(0deg);}
to {-webkit-transform: rotate(360deg);}
}
@-moz-keyframes rotation {
from {-moz-transform: rotate(0deg);}
to {-moz-transform: rotate(360deg);}
}
@-o-keyframes rotation {
from {-o-transform: rotate(0deg);}
to {-o-transform: rotate(360deg);}
}
@keyframes rotation {
from {transform: rotate(0deg);}
to {transform: rotate(360deg);}
}
</style>
</head>
<body class="emscripten">
<div class="emscripten" id="preload">
<figure style="overflow:visible;" id="spinner"><div class="spinner"></div><center style="margin-top:0.5em"><strong>emscripten</strong></center></figure>
<div class="emscripten" id="status">Downloading...</div>
<div class="emscripten">
<progress value="0" max="100" id="progress" hidden=1></progress>
</div>
<div class="emscripten_border">
<canvas class="emscripten" id="canvas" oncontextmenu="event.preventDefault()" tabindex=-1></canvas>
</div>
</div>
<script type='text/javascript'>
var statusElement = document.getElementById('status');
var progressElement = document.getElementById('progress');
var spinnerElement = document.getElementById('spinner');
var preloadElement = document.getElementById('preload');
var Module = {
preRun: [],
postRun: [],
print: (function() {
var element = document.getElementById('output');
if (element) element.value = ''; // clear browser cache
return function(text) {
if (arguments.length > 1) text = Array.prototype.slice.call(arguments).join(' ');
// These replacements are necessary if you render to raw HTML
//text = text.replace(/&/g, "&amp;");
//text = text.replace(/</g, "&lt;");
//text = text.replace(/>/g, "&gt;");
//text = text.replace('\n', '<br>', 'g');
console.log(text);
if (element) {
element.value += text + "\n";
element.scrollTop = element.scrollHeight; // focus on bottom
}
};
})(),
printErr: function(text) {
if (arguments.length > 1) text = Array.prototype.slice.call(arguments).join(' ');
console.error(text);
},
canvas: (function() {
var canvas = document.getElementById('canvas');
// As a default initial behavior, pop up an alert when webgl context is lost. To make your
// application robust, you may want to override this behavior before shipping!
// See http://www.khronos.org/registry/webgl/specs/latest/1.0/#5.15.2
canvas.addEventListener("webglcontextlost", function(e) { alert('WebGL context lost. You will need to reload the page.'); e.preventDefault(); }, false);
return canvas;
})(),
setStatus: function(text) {
if (!Module.setStatus.last) Module.setStatus.last = { time: Date.now(), text: '' };
if (text === Module.setStatus.last.text) return;
var m = text.match(/([^(]+)\((\d+(\.\d+)?)\/(\d+)\)/);
var now = Date.now();
if (m && now - Module.setStatus.last.time < 30) return; // if this is a progress update, skip it if too soon
Module.setStatus.last.time = now;
Module.setStatus.last.text = text;
if (m) {
text = m[1];
progressElement.value = parseInt(m[2])*100;
progressElement.max = parseInt(m[4])*100;
progressElement.hidden = false;
spinnerElement.hidden = false;
} else {
progressElement.value = null;
progressElement.max = null;
progressElement.hidden = true;
if (!text) spinnerElement.hidden = true;
preloadElement.hidden = true;
}
statusElement.innerHTML = text;
},
totalDependencies: 0,
monitorRunDependencies: function(left) {
this.totalDependencies = Math.max(this.totalDependencies, left);
Module.setStatus(left ? 'Preparing... (' + (this.totalDependencies-left) + '/' + this.totalDependencies + ')' : 'All downloads complete.');
}
};
Module.setStatus('Downloading...');
window.onerror = function() {
Module.setStatus('Exception thrown, see JavaScript console');
spinnerElement.style.display = 'none';
Module.setStatus = function(text) {
if (text) Module.printErr('[post-exception status] ' + text);
};
};
</script>
<script type="text/javascript" src="FileSaver.js"></script>
{{{ SCRIPT }}}
</body>
</html>

View File

@@ -9,8 +9,13 @@
#include "PLDrivers.h"
#ifdef __MACOS__
#include <SDL.h>
#include <SDL_rwops.h>
#else
#include "SDL2/SDL.h"
#include "SDL2/SDL_rwops.h"
#endif
#include <string>
#include <vector>
@@ -22,7 +27,7 @@
#include "UTF8.h"
#ifdef __CYGWIN__
#if defined(__CYGWIN__) || defined(__MACOS__)
typedef off_t off64_t;
#define fstat64 fstat
#define fseek64 fseek
@@ -180,8 +185,8 @@ bool GpFileSystem_X::ResolvePath(PortabilityLayer::VirtualDirectory_t virtualDir
case PortabilityLayer::VirtualDirectories::kPrefs:
prefsAppend = "Prefs";
break;
case PortabilityLayer::VirtualDirectories::kFontCache:
prefsAppend = "FontCache";
case PortabilityLayer::VirtualDirectories::kLogs:
prefsAppend = "Logs";
break;
default:
return false;
@@ -197,7 +202,7 @@ bool GpFileSystem_X::ResolvePath(PortabilityLayer::VirtualDirectory_t virtualDir
resolution += "/";
resolution += paths[i];
}
return true;
}
@@ -223,7 +228,7 @@ void GpFileSystem_X::Init()
if (m_basePath.size() >= 4 && m_basePath.substr(m_basePath.size() - 4, 3) == "bin")
m_basePath = m_basePath.substr(0, m_basePath.size() - 4) + "lib" + baseDirSeparator + "aerofoil" + baseDirSeparator;
const char *extensions[] = { "HighScores", "Houses", "SavedGames", "Prefs", "FontCache" };
const char *extensions[] = { "HighScores", "Houses", "SavedGames", "Prefs", "Logs" };
for (size_t i = 0; i < sizeof(extensions) / sizeof(extensions[0]); i++)
{
std::string prefsPath = std::string(prefsDir) + extensions[i];
@@ -289,6 +294,7 @@ GpIOStream *GpFileSystem_X::OpenFileNested(PortabilityLayer::VirtualDirectory_t
return nullptr;
std::string resolvedPath;
if (!ResolvePath(virtualDirectory, subPaths, numSubPaths, resolvedPath))
return nullptr;

View File

@@ -4,6 +4,7 @@
#include "GpApplicationName.h"
#include "GpIOStream.h"
#include <stdlib.h>
#include <time.h>
#include <cstring>
@@ -64,6 +65,10 @@ void GpLogDriver_X::VPrintf(Category category, const char *fmt, va_list args)
}
else
{
//a copy is needed if using va_list multiple times (otherwise unexpected output)
va_list args_copy;
va_copy(args_copy, args);
int formattedSize = vsnprintf(nullptr, 0, fmt, args);
if (formattedSize <= 0)
return;
@@ -72,7 +77,8 @@ void GpLogDriver_X::VPrintf(Category category, const char *fmt, va_list args)
if (!charBuff)
return;
vsnprintf(charBuff, formattedSize + 1, fmt, args);
vsnprintf(charBuff, formattedSize + 1, fmt, args_copy);
va_end(args_copy);
if (m_stream)
m_stream->Write(charBuff, formattedSize);

View File

@@ -12,7 +12,7 @@ public:
GpLogDriver_X();
static void Init();
void VPrintf(Category category, const char *fmt, va_list args) override;
void Shutdown() override;

View File

@@ -2,6 +2,7 @@
#include "SDL_main.h"
#include "GpMain.h"
#include "GpAllocator_C.h"
#include "GpAudioDriverFactory.h"
#include "GpDisplayDriverFactory.h"
#include "GpGlobalConfig.h"
@@ -19,6 +20,9 @@
#include "IGpVOSEventQueue.h"
#include <string>
#ifdef __MACOS__
#include "MacInit.h"
#endif
GpXGlobals g_gpXGlobals;
@@ -26,27 +30,45 @@ IGpDisplayDriver *GpDriver_CreateDisplayDriver_SDL_GL2(const GpDisplayDriverProp
IGpAudioDriver *GpDriver_CreateAudioDriver_SDL(const GpAudioDriverProperties &properties);
IGpInputDriver *GpDriver_CreateInputDriver_SDL2_Gamepad(const GpInputDriverProperties &properties);
#ifdef __MACOS__
int main(int argc, char *argv[])
#else
SDLMAIN_DECLSPEC int SDL_main(int argc, char *argv[])
#endif
{
GpLogDriver_X::Init();
bool enableLogging = false;
for (int i = 1; i < argc; i++)
{
if (!strcmp(argv[i], "-diagnostics"))
enableLogging = true;
}
#ifndef __MACOS__
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMECONTROLLER) < 0)
#else
if (MacInit())
#endif
return -1;
GpFileSystem_X::GetInstance()->Init();
IGpLogDriver *logger = GpLogDriver_X::GetInstance();
IGpLogDriver *logger = nullptr;
if (enableLogging)
{
GpLogDriver_X::Init();
logger = GpLogDriver_X::GetInstance();
}
GpDriverCollection *drivers = GpAppInterface_Get()->PL_GetDriverCollection();
drivers->SetDriver<GpDriverIDs::kFileSystem>(GpFileSystem_X::GetInstance());
drivers->SetDriver<GpDriverIDs::kSystemServices>(GpSystemServices_X::GetInstance());
drivers->SetDriver<GpDriverIDs::kLog>(GpLogDriver_X::GetInstance());
drivers->SetDriver<GpDriverIDs::kAlloc>(GpAllocator_C::GetInstance());
g_gpGlobalConfig.m_displayDriverType = EGpDisplayDriverType_SDL_GL2;
g_gpGlobalConfig.m_audioDriverType = EGpAudioDriverType_SDL2;
g_gpGlobalConfig.m_fontHandlerType = EGpFontHandlerType_None;
EGpInputDriverType inputDrivers[] =
@@ -60,6 +82,7 @@ SDLMAIN_DECLSPEC int SDL_main(int argc, char *argv[])
g_gpGlobalConfig.m_osGlobals = &g_gpXGlobals;
g_gpGlobalConfig.m_logger = logger;
g_gpGlobalConfig.m_systemServices = GpSystemServices_X::GetInstance();
g_gpGlobalConfig.m_allocator = GpAllocator_C::GetInstance();
GpDisplayDriverFactory::RegisterDisplayDriverFactory(EGpDisplayDriverType_SDL_GL2, GpDriver_CreateDisplayDriver_SDL_GL2);
GpAudioDriverFactory::RegisterAudioDriverFactory(EGpAudioDriverType_SDL2, GpDriver_CreateAudioDriver_SDL);

View File

@@ -2,7 +2,13 @@
#include "IGpClipboardContents.h"
#include "IGpThreadEvent.h"
#ifdef __MACOS__
#include <SDL.h>
#include <pthread.h>
#else
#include "SDL2/SDL.h"
#endif
#include <time.h>
#include <unistd.h>
@@ -64,8 +70,9 @@ void *GpSystemServices_X::CreateThread(ThreadFunc_t threadFunc, void *context)
return thread;
}
void GpSystemServices_X::Beep() const
bool GpSystemServices_X::Beep() const
{
return false;
}
bool GpSystemServices_X::IsTouchscreen() const
@@ -84,7 +91,7 @@ bool GpSystemServices_X::IsTextInputObstructive() const
}
bool GpSystemServices_X::IsFullscreenPreferred() const
{
{
return true;
}
@@ -93,6 +100,25 @@ bool GpSystemServices_X::IsFullscreenOnStartup() const
return false;
}
bool GpSystemServices_X::HasNativeFileManager() const
{
return true;
}
GpOperatingSystem_t GpSystemServices_X::GetOperatingSystem() const
{
#ifdef __MACOS__
return GpOperatingSystems::kMacOS;
#else
return GpOperatingSystems::kLinux;
#endif
}
GpOperatingSystemFlavor_t GpSystemServices_X::GetOperatingSystemFlavor() const
{
return GpOperatingSystemFlavors::kGeneric;
}
unsigned int GpSystemServices_X::GetCPUCount() const
{
return SDL_GetCPUCount();

View File

@@ -12,12 +12,15 @@ public:
~GpSystemServices_X();
void *CreateThread(ThreadFunc_t threadFunc, void *context) override;
void Beep() const override;
bool Beep() const override;
bool IsTouchscreen() const override;
bool IsUsingMouseAsTouch() const override;
bool IsTextInputObstructive() const override;
bool IsFullscreenPreferred() const override;
bool IsFullscreenOnStartup() const override;
bool HasNativeFileManager() const override;
GpOperatingSystem_t GetOperatingSystem() const override;
GpOperatingSystemFlavor_t GetOperatingSystemFlavor() const override;
unsigned int GetCPUCount() const override;
void SetTextInputEnabled(bool isEnabled) override;
bool IsTextInputEnabled() const override;

View File

@@ -4,7 +4,7 @@
{
"name" : "Okay",
"itemType" : "Button",
"pos" : [ 376, 240 ],
"pos" : [ 376, 300 ],
"size" : [ 58, 20 ],
"id" : 1,
"enabled" : true
@@ -12,7 +12,7 @@
{
"name" : "Third Party/Licensing Info...",
"itemType" : "Button",
"pos" : [ 176, 240 ],
"pos" : [ 176, 300 ],
"size" : [ 190, 20 ],
"id" : 1,
"enabled" : true

View File

@@ -4,7 +4,7 @@
{
"name" : "Okay",
"itemType" : "Button",
"pos" : [ 438, 292 ],
"pos" : [ 438, 316 ],
"size" : [ 58, 20 ],
"id" : 1,
"enabled" : true
@@ -12,13 +12,13 @@
{
"name" : "Export Source Code to ZIP Archive...",
"itemType" : "Button",
"pos" : [ 205, 292 ],
"pos" : [ 205, 316 ],
"size" : [ 226, 20 ],
"id" : 1,
"enabled" : false
},
{
"name" : "Aerofoil ©2019-2021 Eric Lasota",
"name" : "Aerofoil ©2019-2021 Gale Force Games LLC",
"itemType" : "Label",
"pos" : [ 16, 21 ],
"size" : [ 406, 20 ],
@@ -98,7 +98,7 @@
"enabled" : true
},
{
"name" : "LIBICONV ©1999-2001, 2016 Free Software Foundation, Inc.",
"name" : "Inter font ©2016-2019 Rasmus Andersson + Inter Project Authors",
"itemType" : "Label",
"pos" : [ 16, 149 ],
"size" : [ 406, 20 ],
@@ -114,25 +114,9 @@
"enabled" : true
},
{
"name" : "RapidJSON ©2015 THL A29 Limited, a Tencent company, and Milo Yip",
"name" : "LIBICONV ©1999-2001, 2016 Free Software Foundation, Inc.",
"itemType" : "Label",
"pos" : [ 16, 172 ],
"size" : [ 406, 28 ],
"id" : 1,
"enabled" : true
},
{
"name" : "License...",
"itemType" : "Button",
"pos" : [ 430, 172 ],
"size" : [ 66, 20 ],
"id" : 1,
"enabled" : true
},
{
"name" : "zlib ©1995-2017 Jean-loup Gailly and Mark Adler",
"itemType" : "Label",
"pos" : [ 16, 205 ],
"pos" : [ 16, 173 ],
"size" : [ 406, 20 ],
"id" : 1,
"enabled" : true
@@ -140,13 +124,29 @@
{
"name" : "License...",
"itemType" : "Button",
"pos" : [ 430, 200 ],
"pos" : [ 430, 168 ],
"size" : [ 66, 20 ],
"id" : 1,
"enabled" : true
},
{
"name" : "FreeType ©2020 The FreeType Project",
"name" : "RapidJSON ©2015 THL A29 Limited, a Tencent company, and Milo Yip",
"itemType" : "Label",
"pos" : [ 16, 194 ],
"size" : [ 406, 28 ],
"id" : 1,
"enabled" : true
},
{
"name" : "License...",
"itemType" : "Button",
"pos" : [ 430, 196 ],
"size" : [ 66, 20 ],
"id" : 1,
"enabled" : true
},
{
"name" : "zlib ©1995-2017 Jean-loup Gailly and Mark Adler",
"itemType" : "Label",
"pos" : [ 16, 229 ],
"size" : [ 406, 20 ],
@@ -162,7 +162,7 @@
"enabled" : true
},
{
"name" : "Simple DirectMedia Layer ©1997-2020 Sam Lantinga",
"name" : "FreeType ©2020 The FreeType Project",
"itemType" : "Label",
"pos" : [ 16, 253 ],
"size" : [ 406, 20 ],
@@ -176,6 +176,22 @@
"size" : [ 66, 20 ],
"id" : 1,
"enabled" : true
},
{
"name" : "Simple DirectMedia Layer ©1997-2020 Sam Lantinga",
"itemType" : "Label",
"pos" : [ 16, 277 ],
"size" : [ 406, 20 ],
"id" : 1,
"enabled" : true
},
{
"name" : "License...",
"itemType" : "Button",
"pos" : [ 430, 272 ],
"size" : [ 66, 20 ],
"id" : 1,
"enabled" : true
}
]
}

View File

@@ -0,0 +1,61 @@
{
"items" :
[
{
"name" : "Okay",
"itemType" : "Button",
"pos" : [ 376, 240 ],
"size" : [ 58, 20 ],
"id" : 1,
"enabled" : true
},
{
"name" : "Cancel",
"itemType" : "Button",
"pos" : [ 302, 240 ],
"size" : [ 58, 20 ],
"id" : 2,
"enabled" : true
},
{
"name" : "",
"itemType" : "CustomControl",
"pos" : [ 17, 33 ],
"size" : [ 401, 186 ],
"id" : 2,
"enabled" : true
},
{
"name" : "",
"itemType" : "CustomControl",
"pos" : [ 418, 32 ],
"size" : [ 16, 188 ],
"id" : 3,
"enabled" : true
},
{
"name" : "",
"itemType" : "EditBox",
"pos" : [ 16, 240 ],
"size" : [ 196, 16 ],
"id" : 4,
"enabled" : true
},
{
"name" : "^0",
"itemType" : "Label",
"pos" : [ 16, 16 ],
"size" : [ 418, 16 ],
"id" : 10,
"enabled" : true
},
{
"name" : "Delete",
"itemType" : "Button",
"pos" : [ 228, 240 ],
"size" : [ 58, 20 ],
"id" : 2,
"enabled" : false
}
]
}

Binary file not shown.

View File

@@ -0,0 +1,26 @@
A never-before-seen error has arisen. Proceed with caution! (Save and Quit immediately.)
I failed to open the house's resource fork. Any unique room backgrounds are not accessible.
I failed to add a resource to the house's resource fork. See error number.
I failed to create a new resource fork for the house. See error number for problem.
There are no houses on this drive! About your only option is to create your own new house with the Editor.
This house is incompatible with us! You'll need to upgrade Glider PRO to use this house. Do not attempt to play/edit this house!
The background specified by this room was not found! Try re-selecting a new background (the Room Info menu).
The room number is out of bounds. I suspect the house file is corrupt. Try deleting this "illegal" room though.
The data is missing that specifies where the openings in this room are. The house may be damaged. Try selecting a new background though.
There was a problem with the clipboard (Cut, Copy and Paste commands). I couldn't guess why.
I think we just ran out of memory. Quit now and give Glider PRO<52> more memory.
We failed to write the house to disk. (That shouldn't have happened.)
Well, the music didn't load. Glider PRO<52> will still run, you'll just be musically challenged.
Wow, there was a problem bringing sounds up. You might try giving Glider PRO<52> more memory - otherwise ... silence.
Some kind of strange Apple Event error. I think I would just ignore it. Or call Casady & Greene with the error number.
Did you save the house on the same volume Glider PRO is on? I saved the house but had to re-open the old house because I couldn't find the new one.
Wow, I couldn't find the old or new house. Go to the Select House menu item and see if it's there. If not, make sure they're on the same volume as Glider PRO.
Couldn't create a saved game structure. Memory is probably too low.
The saved game doesn't match the house. Either this game was saved for a different house or the house was modified recently.
This saved game is an old version. We cannot use this game with this house.
The number of rooms saved doesn't match the number of house rooms. We cannot use this game with this house.
The QuickTime<6D> movie that goes with this house will not be used. Glider PRO<52> must have enough memory to easily load the entire movie into RAM.
This house has no rooms! Do not attempt to play this house! Select a new house to play.
There was an error generating or parsing a links list. Memory may be tight.
This house contains invalid data that couldn't be repaired. Select a new house to play.
This house contained invalid data, which was repaired. Some things may be missing or not work correctly.

View File

@@ -12,6 +12,7 @@
"DITL/2006.json" : "ApplicationResourcePatches/DITL/2006.json",
"DITL/2007.json" : "ApplicationResourcePatches/DITL/2007.json",
"DITL/2008.json" : "ApplicationResourcePatches/DITL/2008.json",
"DITL/2009.json" : "ApplicationResourcePatches/DITL/2009.json",
"PICT/1300.bmp" : "ApplicationResourcePatches/PICT/1300.bmp",
"PICT/1301.bmp" : "ApplicationResourcePatches/PICT/1301.bmp",
"PICT/1971.bmp" : "ApplicationResourcePatches/PICT/1971.bmp",
@@ -37,7 +38,9 @@
"LICS/1003.txt" : "ApplicationResourcePatches/LICS/1003.txt",
"LICS/1004.txt" : "ApplicationResourcePatches/LICS/1004.txt",
"LICS/1005.txt" : "ApplicationResourcePatches/LICS/1005.txt",
"LICS/1006.txt" : "ApplicationResourcePatches/LICS/1006.txt"
"LICS/1006.txt" : "ApplicationResourcePatches/LICS/1006.txt",
"STR$23/1006.txt" : "ApplicationResourcePatches/STR/1006.txt",
"snd$20/1063.wav" : "ApplicationResourcePatches/SND/1063.wav"
},
"delete" :
[

Some files were not shown because too many files have changed in this diff Show More