Compare commits
261 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
1fe94e4f06 | ||
|
5f2f73e176 | ||
|
7c5864d59b | ||
|
d698ff23db | ||
|
92cb961208 | ||
|
545798600e | ||
|
9ba15c6d78 | ||
|
0706640bc9 | ||
|
bdb7ddbdbb | ||
|
c5dee3ce9e | ||
|
7e3569500a | ||
|
376fdf16c4 | ||
|
40b38046b9 | ||
|
5b5fb15780 | ||
|
744b06796d | ||
|
7ba11df286 | ||
|
9f5699a61e | ||
|
5ab966ea98 | ||
|
42ec9e3646 | ||
|
83978d0397 | ||
|
82fe38dfc7 | ||
|
2c90110668 | ||
|
eac270670d | ||
|
c04aeeb962 | ||
|
f9109850a6 | ||
|
71955ac729 | ||
|
f36a8da95f | ||
|
0e3534d902 | ||
|
90943d945b | ||
|
00488c6fea | ||
|
f16ffa0c4c | ||
|
e098370249 | ||
|
c3eb23af4b | ||
|
a32b33ef1b | ||
|
b83fd1b28f | ||
|
ab6c447a2f | ||
|
e02919f1fc | ||
|
ccceec8b3c | ||
|
40c1a39c40 | ||
|
c27d78d329 | ||
|
66cce6bcd4 | ||
|
b616c6bf6e | ||
|
2e9954677d | ||
|
3d5265258e | ||
|
6103007ed2 | ||
|
240ba88f53 | ||
|
71115b2366 | ||
|
2bde3bc60b | ||
|
0524c312d0 | ||
|
8a69d7b921 | ||
|
20a3918535 | ||
|
bd61b23bde | ||
|
b1bebc2afd | ||
|
5b16ed826f | ||
|
567b82eb23 | ||
|
e8565a122d | ||
|
32ff2f6fe8 | ||
|
95260f8d8a | ||
|
e7b02f37a5 | ||
|
781c6ce610 | ||
|
98c7a1eea6 | ||
|
0a9b5ded9b | ||
|
09485b7cf4 | ||
|
6fd1edd2c8 | ||
|
6858230dde | ||
|
a6486c137b | ||
|
318a5868d7 | ||
|
295db5f064 | ||
|
0def879db1 | ||
|
ac56badffa | ||
|
75923ad7b0 | ||
|
32d96798cc | ||
|
c354d49e9f | ||
|
24169507bd | ||
|
d54ad576bc | ||
|
222927d56f | ||
|
d74c4b70f3 | ||
|
fb7b9b02d9 | ||
|
1ac8032411 | ||
|
a012c6d3e7 | ||
|
08c6fd5108 | ||
|
a7cf9d48e3 | ||
|
d6ce07685e | ||
|
5e060279af | ||
|
a2ca1725fa | ||
|
f32866510e | ||
|
ac15c26bef | ||
|
9510aaee32 | ||
|
c6aa82db35 | ||
|
6d12b6ff1a | ||
|
c3b2a7e8af | ||
|
b0d5673d95 | ||
|
14ef73a8ab | ||
|
456a134041 | ||
|
27ae449353 | ||
|
0de26b5e71 | ||
|
65d4784618 | ||
|
5187ef5dc6 | ||
|
b96acad0ca | ||
|
2277d1340c | ||
|
57798c05c6 | ||
|
f24b0a0e77 | ||
|
7442b92dd3 | ||
|
0725828a5f | ||
|
c5a1303b71 | ||
|
a2d374f650 | ||
|
472462c535 | ||
|
80683464af | ||
|
2cd4e4f178 | ||
|
07df94fb00 | ||
|
d6b206195d | ||
|
65e68f790a | ||
|
56d999f400 | ||
|
2991a7490e | ||
|
0c43370353 | ||
|
9ba5b14db6 | ||
|
5e1f5655a0 | ||
|
67b594fe68 | ||
|
0385c28002 | ||
|
19b1a307e7 | ||
|
9341c4c378 | ||
|
5d9dde6589 | ||
|
f9d3b91f72 | ||
|
1dc86a703e | ||
|
82aaefe342 | ||
|
d77cf6f5db | ||
|
a9b6d1dc4f | ||
|
08349fc6db | ||
|
77e02927c6 | ||
|
c473271e4e | ||
|
84a4d16aed | ||
|
f15a87041a | ||
|
d826a908e9 | ||
|
3d3f839801 | ||
|
141f840888 | ||
|
22ae442f87 | ||
|
5dd8bf28f5 | ||
|
bd422d0eb3 | ||
|
4e8e76f8fc | ||
|
bf1dad34c3 | ||
|
c49bab04d5 | ||
|
e6df94dac0 | ||
|
71f27f0a05 | ||
|
b9fe553ff8 | ||
|
7ae31bc7fc | ||
|
2234190f24 | ||
|
d62de80ff1 | ||
|
03f07d7c4f | ||
|
b90d0c303c | ||
|
7842e721e5 | ||
|
93195207dc | ||
|
59741dd966 | ||
|
1ac69c2c75 | ||
|
69f59f769d | ||
|
bb2af5abb3 | ||
|
3692a966bf | ||
|
7916c72fc4 | ||
|
7951f579e0 | ||
|
b64c904558 | ||
|
a6f6ffcdcc | ||
|
6fb45f480b | ||
|
9ba0e9f13d | ||
|
0df94405f8 | ||
|
ae69696cbd | ||
|
50f420d2b1 | ||
|
c87f238563 | ||
|
48fe83bb33 | ||
|
b2b27ef335 | ||
|
89831f0ff6 | ||
|
99fd71196d | ||
|
7060676b73 | ||
|
184f867f79 | ||
|
cbd759c754 | ||
|
2ada8029d0 | ||
|
8e0d8e261e | ||
|
20b9eef64d | ||
|
c147e1100e | ||
|
0a2e730d26 | ||
|
922cd0fd06 | ||
|
b8bf6be44f | ||
|
2897c4ffab | ||
|
35c174984b | ||
|
da16edea8d | ||
|
2fe1ea2ee7 | ||
|
0931f25f23 | ||
|
7f4d782c0d | ||
|
f2cda23b0f | ||
|
6292705968 | ||
|
6931b3f505 | ||
|
d70a5b3bfc | ||
|
f0913d0d6a | ||
|
80584eb781 | ||
|
fe4a8a55c6 | ||
|
55ec6c516c | ||
|
3917e1a370 | ||
|
6715bcb030 | ||
|
c981a97a20 | ||
|
a5562f96e0 | ||
|
d97bd8ad1c | ||
|
a43f32ab88 | ||
|
e94d1511b1 | ||
|
95e4eb4e34 | ||
|
15bdb97c38 | ||
|
e7246c1444 | ||
|
35b8e922d7 | ||
|
3090f70ee6 | ||
|
484e18a9af | ||
|
83d37a7c94 | ||
|
fc043af3a1 | ||
|
2ebd3f2cf3 | ||
|
ebab2ee188 | ||
|
032e44d981 | ||
|
7961ca3af7 | ||
|
6851025147 | ||
|
f0b1d6fff9 | ||
|
70e0948847 | ||
|
a698286087 | ||
|
b75313fd7b | ||
|
cab862ed8b | ||
|
553e343abe | ||
|
0aa36b27a9 | ||
|
f6185b1c78 | ||
|
ff29d5b92c | ||
|
964c9b8858 | ||
|
8a48726b2e | ||
|
de06669239 | ||
|
c0abd77dc4 | ||
|
754b988f09 | ||
|
1c57a51316 | ||
|
80abb498af | ||
|
29cc376438 | ||
|
ef12c471a7 | ||
|
8f4ecfafe1 | ||
|
3c3f9e3675 | ||
|
5c640b72eb | ||
|
9d0f2c35b3 | ||
|
7df624d9b1 | ||
|
29fbe83e8d | ||
|
ad3a878a16 | ||
|
f0e7379db6 | ||
|
e34fec38a2 | ||
|
76db422456 | ||
|
396d107608 | ||
|
30b39c6991 | ||
|
9dafba1092 | ||
|
801408077a | ||
|
2c073937c3 | ||
|
bbd147e1ab | ||
|
66a111dd23 | ||
|
2febed5d2a | ||
|
b47813330a | ||
|
0f630a74a2 | ||
|
edc43e0bed | ||
|
2aca0b6b28 | ||
|
f9a101486c | ||
|
dbf3303145 | ||
|
a28a4cd73d | ||
|
4c6e646133 | ||
|
a13f90bd71 | ||
|
3d0e457008 | ||
|
1bded36339 |
29
.gitignore
vendored
@@ -20,6 +20,9 @@
|
|||||||
*.idb
|
*.idb
|
||||||
*.aps
|
*.aps
|
||||||
*.res
|
*.res
|
||||||
|
*.a
|
||||||
|
*.recipe
|
||||||
|
*.FileListAbsolute.txt
|
||||||
.vs/*
|
.vs/*
|
||||||
Packaged/*
|
Packaged/*
|
||||||
DebugData/*
|
DebugData/*
|
||||||
@@ -30,9 +33,35 @@ InstallerPackages/*
|
|||||||
*.wixobj
|
*.wixobj
|
||||||
*.CopyComplete
|
*.CopyComplete
|
||||||
*.lnk
|
*.lnk
|
||||||
|
*.cmake
|
||||||
ReleasePackageInstaller/obj/*
|
ReleasePackageInstaller/obj/*
|
||||||
ReleasePackageInstaller/bin/*
|
ReleasePackageInstaller/bin/*
|
||||||
ReleasePackageInstaller/AerofoilPackageDefs.wxi
|
ReleasePackageInstaller/AerofoilPackageDefs.wxi
|
||||||
ReleasePackageInstaller/AerofoilPackageVersion.wxi
|
ReleasePackageInstaller/AerofoilPackageVersion.wxi
|
||||||
packages/*
|
packages/*
|
||||||
!SDL2-2.0.12/lib/x64/*
|
!SDL2-2.0.12/lib/x64/*
|
||||||
|
CMakeCache.txt
|
||||||
|
CMakeFiles/*
|
||||||
|
Makefile
|
||||||
|
SDL2-2.0.12/CMakeFiles/*
|
||||||
|
SDL2-2.0.12/build
|
||||||
|
SDL2-2.0.12/config.status
|
||||||
|
SDL2-2.0.12/libtool
|
||||||
|
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
@@ -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
@@ -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
@@ -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
@@ -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>
|
22
ASADTool/ASADTool.vcxproj.filters
Normal 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>
|
35
Aerofoil.sln
@@ -46,6 +46,11 @@ EndProject
|
|||||||
Project("{930C7802-8A8C-48F9-8165-68863BCCD9DD}") = "ReleasePackageInstaller", "ReleasePackageInstaller\ReleasePackageInstaller.wixproj", "{D26BD501-28A7-4849-8130-FB5EA0A2B82F}"
|
Project("{930C7802-8A8C-48F9-8165-68863BCCD9DD}") = "ReleasePackageInstaller", "ReleasePackageInstaller\ReleasePackageInstaller.wixproj", "{D26BD501-28A7-4849-8130-FB5EA0A2B82F}"
|
||||||
ProjectSection(ProjectDependencies) = postProject
|
ProjectSection(ProjectDependencies) = postProject
|
||||||
{7EFF1E21-C375-45EA-A069-4E2232C8A72B} = {7EFF1E21-C375-45EA-A069-4E2232C8A72B}
|
{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
|
EndProjectSection
|
||||||
EndProject
|
EndProject
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WindowsUnicodeToolShim", "WindowsUnicodeToolShim\WindowsUnicodeToolShim.vcxproj", "{15009625-1120-405E-8BBA-69A16CD6713D}"
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WindowsUnicodeToolShim", "WindowsUnicodeToolShim\WindowsUnicodeToolShim.vcxproj", "{15009625-1120-405E-8BBA-69A16CD6713D}"
|
||||||
@@ -58,6 +63,16 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GpFontHandler_FreeType2", "
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AerofoilSDL", "AerofoilSDL\AerofoilSDL.vcxproj", "{33542FF0-0473-4802-BC79-3B8261790F65}"
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AerofoilSDL", "AerofoilSDL\AerofoilSDL.vcxproj", "{33542FF0-0473-4802-BC79-3B8261790F65}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MergeGPF", "MergeGPF\MergeGPF.vcxproj", "{36DAF5FA-6ADB-4F20-9810-1610DE0AE653}"
|
||||||
|
EndProject
|
||||||
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GenerateFonts", "GenerateFonts\GenerateFonts.vcxproj", "{3B7FD18D-7A50-4DF5-AC25-543E539BFACE}"
|
||||||
|
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
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|x64 = Debug|x64
|
Debug|x64 = Debug|x64
|
||||||
@@ -166,6 +181,26 @@ Global
|
|||||||
{33542FF0-0473-4802-BC79-3B8261790F65}.Debug|x64.Build.0 = Debug|x64
|
{33542FF0-0473-4802-BC79-3B8261790F65}.Debug|x64.Build.0 = Debug|x64
|
||||||
{33542FF0-0473-4802-BC79-3B8261790F65}.Release|x64.ActiveCfg = Release|x64
|
{33542FF0-0473-4802-BC79-3B8261790F65}.Release|x64.ActiveCfg = Release|x64
|
||||||
{33542FF0-0473-4802-BC79-3B8261790F65}.Release|x64.Build.0 = Release|x64
|
{33542FF0-0473-4802-BC79-3B8261790F65}.Release|x64.Build.0 = Release|x64
|
||||||
|
{36DAF5FA-6ADB-4F20-9810-1610DE0AE653}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
|
{36DAF5FA-6ADB-4F20-9810-1610DE0AE653}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{36DAF5FA-6ADB-4F20-9810-1610DE0AE653}.Release|x64.ActiveCfg = Release|x64
|
||||||
|
{36DAF5FA-6ADB-4F20-9810-1610DE0AE653}.Release|x64.Build.0 = Release|x64
|
||||||
|
{3B7FD18D-7A50-4DF5-AC25-543E539BFACE}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
|
{3B7FD18D-7A50-4DF5-AC25-543E539BFACE}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{3B7FD18D-7A50-4DF5-AC25-543E539BFACE}.Release|x64.ActiveCfg = Release|x64
|
||||||
|
{3B7FD18D-7A50-4DF5-AC25-543E539BFACE}.Release|x64.Build.0 = Release|x64
|
||||||
|
{D045F28D-F245-44DD-B576-CC91BF3BE6E9}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
|
{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
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
@@ -14,19 +14,19 @@
|
|||||||
<VCProjectVersion>15.0</VCProjectVersion>
|
<VCProjectVersion>15.0</VCProjectVersion>
|
||||||
<ProjectGuid>{0E383EF0-CEF7-4733-87C6-5AC9844AA1EF}</ProjectGuid>
|
<ProjectGuid>{0E383EF0-CEF7-4733-87C6-5AC9844AA1EF}</ProjectGuid>
|
||||||
<RootNamespace>Aerofoil</RootNamespace>
|
<RootNamespace>Aerofoil</RootNamespace>
|
||||||
<WindowsTargetPlatformVersion>10.0.17763.0</WindowsTargetPlatformVersion>
|
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
<UseDebugLibraries>true</UseDebugLibraries>
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
<PlatformToolset>v141</PlatformToolset>
|
<PlatformToolset>v142</PlatformToolset>
|
||||||
<CharacterSet>MultiByte</CharacterSet>
|
<CharacterSet>MultiByte</CharacterSet>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
<UseDebugLibraries>false</UseDebugLibraries>
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
<PlatformToolset>v141</PlatformToolset>
|
<PlatformToolset>v142</PlatformToolset>
|
||||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
<CharacterSet>MultiByte</CharacterSet>
|
<CharacterSet>MultiByte</CharacterSet>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
@@ -43,6 +43,7 @@
|
|||||||
<Import Project="..\GpMainApp.props" />
|
<Import Project="..\GpMainApp.props" />
|
||||||
<Import Project="..\GpShell.props" />
|
<Import Project="..\GpShell.props" />
|
||||||
<Import Project="..\Debug.props" />
|
<Import Project="..\Debug.props" />
|
||||||
|
<Import Project="..\AerofoilPortable.props" />
|
||||||
</ImportGroup>
|
</ImportGroup>
|
||||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
<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="$(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="..\GpMainApp.props" />
|
||||||
<Import Project="..\Release.props" />
|
<Import Project="..\Release.props" />
|
||||||
<Import Project="..\GpShell.props" />
|
<Import Project="..\GpShell.props" />
|
||||||
|
<Import Project="..\AerofoilPortable.props" />
|
||||||
</ImportGroup>
|
</ImportGroup>
|
||||||
<PropertyGroup Label="UserMacros" />
|
<PropertyGroup Label="UserMacros" />
|
||||||
<PropertyGroup />
|
<PropertyGroup />
|
||||||
@@ -82,16 +84,15 @@
|
|||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<ClCompile Include="..\AerofoilPortable\GpAllocator_C.cpp" />
|
||||||
<ClCompile Include="GpBWCursor_Win32.cpp" />
|
<ClCompile Include="GpBWCursor_Win32.cpp" />
|
||||||
<ClCompile Include="GpColorCursor_Win32.cpp" />
|
<ClCompile Include="GpColorCursor_Win32.cpp" />
|
||||||
<ClCompile Include="GpFiber_Win32.cpp" />
|
|
||||||
<ClCompile Include="GpFileStream_Win32.cpp" />
|
<ClCompile Include="GpFileStream_Win32.cpp" />
|
||||||
<ClCompile Include="GpFileSystem_Win32.cpp" />
|
<ClCompile Include="GpFileSystem_Win32.cpp" />
|
||||||
<ClCompile Include="GpLogDriver_Win32.cpp" />
|
<ClCompile Include="GpLogDriver_Win32.cpp" />
|
||||||
<ClCompile Include="GpMain_Win32.cpp" />
|
<ClCompile Include="GpMain_Win32.cpp" />
|
||||||
<ClCompile Include="GpMutex_Win32.cpp" />
|
<ClCompile Include="GpMutex_Win32.cpp" />
|
||||||
<ClCompile Include="GpSystemServices_Win32.cpp" />
|
<ClCompile Include="GpSystemServices_Win32.cpp" />
|
||||||
<ClCompile Include="GpFiberStarter_Win32.cpp" />
|
|
||||||
<ClCompile Include="GpThreadEvent_Win32.cpp" />
|
<ClCompile Include="GpThreadEvent_Win32.cpp" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
@@ -102,13 +103,14 @@
|
|||||||
<ClInclude Include="..\GpCommon\GpDisplayDriverTickStatus.h" />
|
<ClInclude Include="..\GpCommon\GpDisplayDriverTickStatus.h" />
|
||||||
<ClInclude Include="..\GpCommon\GpFileCreationDisposition.h" />
|
<ClInclude Include="..\GpCommon\GpFileCreationDisposition.h" />
|
||||||
<ClInclude Include="..\GpCommon\GpInputDriverProperties.h" />
|
<ClInclude Include="..\GpCommon\GpInputDriverProperties.h" />
|
||||||
|
<ClInclude Include="..\GpCommon\GpString.h" />
|
||||||
|
<ClInclude Include="..\GpCommon\GpVector.h" />
|
||||||
<ClInclude Include="..\GpCommon\IGpCursor.h" />
|
<ClInclude Include="..\GpCommon\IGpCursor.h" />
|
||||||
<ClInclude Include="..\GpCommon\IGpAudioChannelCallbacks.h" />
|
<ClInclude Include="..\GpCommon\IGpAudioChannelCallbacks.h" />
|
||||||
<ClInclude Include="..\GpCommon\IGpDisplayDriverSurface.h" />
|
<ClInclude Include="..\GpCommon\IGpDisplayDriverSurface.h" />
|
||||||
<ClInclude Include="..\GpCommon\IGpLogDriver.h" />
|
<ClInclude Include="..\GpCommon\IGpLogDriver.h" />
|
||||||
<ClInclude Include="..\GpCommon\IGpPrefsHandler.h" />
|
<ClInclude Include="..\GpCommon\IGpPrefsHandler.h" />
|
||||||
<ClInclude Include="GpBWCursor_Win32.h" />
|
<ClInclude Include="GpBWCursor_Win32.h" />
|
||||||
<ClInclude Include="GpFiber_Win32.h" />
|
|
||||||
<ClInclude Include="GpFileStream_Win32.h" />
|
<ClInclude Include="GpFileStream_Win32.h" />
|
||||||
<ClInclude Include="GpFileSystem_Win32.h" />
|
<ClInclude Include="GpFileSystem_Win32.h" />
|
||||||
<ClInclude Include="GpLogDriver_Win32.h" />
|
<ClInclude Include="GpLogDriver_Win32.h" />
|
||||||
@@ -127,9 +129,6 @@
|
|||||||
<ProjectReference Include="..\GpDisplayDriver_D3D11\GpDisplayDriver_D3D11.vcxproj">
|
<ProjectReference Include="..\GpDisplayDriver_D3D11\GpDisplayDriver_D3D11.vcxproj">
|
||||||
<Project>{ffc961ac-55b4-4a38-a83e-06ae98f59acc}</Project>
|
<Project>{ffc961ac-55b4-4a38-a83e-06ae98f59acc}</Project>
|
||||||
</ProjectReference>
|
</ProjectReference>
|
||||||
<ProjectReference Include="..\GpFontHandler_FreeType2\GpFontHandler_FreeType2.vcxproj">
|
|
||||||
<Project>{4b564030-8985-4975-91e1-e1b2c16ae2a1}</Project>
|
|
||||||
</ProjectReference>
|
|
||||||
<ProjectReference Include="..\GpInputDriver_XInput\GpInputDriver_XInput.vcxproj">
|
<ProjectReference Include="..\GpInputDriver_XInput\GpInputDriver_XInput.vcxproj">
|
||||||
<Project>{17b96f07-ef92-47cd-95a5-8e6ee38ab564}</Project>
|
<Project>{17b96f07-ef92-47cd-95a5-8e6ee38ab564}</Project>
|
||||||
</ProjectReference>
|
</ProjectReference>
|
||||||
|
@@ -4,12 +4,6 @@
|
|||||||
<ClCompile Include="GpColorCursor_Win32.cpp">
|
<ClCompile Include="GpColorCursor_Win32.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="GpFiber_Win32.cpp">
|
|
||||||
<Filter>Source Files</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="GpFiberStarter_Win32.cpp">
|
|
||||||
<Filter>Source Files</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="GpFileStream_Win32.cpp">
|
<ClCompile Include="GpFileStream_Win32.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
@@ -34,6 +28,9 @@
|
|||||||
<ClCompile Include="GpBWCursor_Win32.cpp">
|
<ClCompile Include="GpBWCursor_Win32.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\AerofoilPortable\GpAllocator_C.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="..\GpCommon\EGpInputDriverType.h">
|
<ClInclude Include="..\GpCommon\EGpInputDriverType.h">
|
||||||
@@ -48,9 +45,6 @@
|
|||||||
<ClInclude Include="..\GpCommon\GpDisplayDriverTickStatus.h">
|
<ClInclude Include="..\GpCommon\GpDisplayDriverTickStatus.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="GpFiber_Win32.h">
|
|
||||||
<Filter>Header Files</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="..\GpCommon\GpFileCreationDisposition.h">
|
<ClInclude Include="..\GpCommon\GpFileCreationDisposition.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
@@ -99,6 +93,12 @@
|
|||||||
<ClInclude Include="GpBWCursor_Win32.h">
|
<ClInclude Include="GpBWCursor_Win32.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\GpCommon\GpVector.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\GpCommon\GpString.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Image Include="ConvertedResources\Large128.ico">
|
<Image Include="ConvertedResources\Large128.ico">
|
||||||
|
@@ -21,6 +21,7 @@
|
|||||||
|
|
||||||
#include "GpBWCursor_Win32.h"
|
#include "GpBWCursor_Win32.h"
|
||||||
#include "GpWindows.h"
|
#include "GpWindows.h"
|
||||||
|
#include "IGpAllocator.h"
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@@ -34,19 +35,19 @@ void GpBWCursor_Win32::Destroy()
|
|||||||
this->DecRef();
|
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 numBits = width * height;
|
||||||
size_t numBytes = (width * height + 7) / 8;
|
size_t numBytes = (numBits + 7) / 8;
|
||||||
uint8_t *convertedAndData = static_cast<uint8_t*>(malloc(numBytes));
|
uint8_t *convertedAndData = static_cast<uint8_t*>(alloc->Alloc(numBytes));
|
||||||
uint8_t *convertedXorData = static_cast<uint8_t*>(malloc(numBytes));
|
uint8_t *convertedXorData = static_cast<uint8_t*>(alloc->Alloc(numBytes));
|
||||||
|
|
||||||
if (!convertedAndData || !convertedXorData)
|
if (!convertedAndData || !convertedXorData)
|
||||||
{
|
{
|
||||||
if (convertedAndData)
|
if (convertedAndData)
|
||||||
free(convertedAndData);
|
alloc->Release(convertedAndData);
|
||||||
if (convertedXorData)
|
if (convertedXorData)
|
||||||
free(convertedXorData);
|
alloc->Release(convertedXorData);
|
||||||
|
|
||||||
return nullptr;
|
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);
|
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);
|
alloc->Release(convertedAndData);
|
||||||
free(convertedXorData);
|
alloc->Release(convertedXorData);
|
||||||
|
|
||||||
if (!hcursor)
|
if (!hcursor)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
void *storage = malloc(sizeof(GpBWCursor_Win32));
|
void *storage = alloc->Alloc(sizeof(GpBWCursor_Win32));
|
||||||
if (!storage)
|
if (!storage)
|
||||||
{
|
{
|
||||||
DestroyCursor(hcursor);
|
DestroyCursor(hcursor);
|
||||||
return nullptr;
|
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_cursor(cursor)
|
||||||
, m_refCount(1)
|
, m_refCount(1)
|
||||||
|
, m_alloc(alloc)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -104,7 +106,8 @@ void GpBWCursor_Win32::DecRef()
|
|||||||
m_refCount--;
|
m_refCount--;
|
||||||
if (m_refCount == 0)
|
if (m_refCount == 0)
|
||||||
{
|
{
|
||||||
|
IGpAllocator *alloc = m_alloc;
|
||||||
this->~GpBWCursor_Win32();
|
this->~GpBWCursor_Win32();
|
||||||
free(this);
|
alloc->Release(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -3,6 +3,8 @@
|
|||||||
#include "IGpCursor_Win32.h"
|
#include "IGpCursor_Win32.h"
|
||||||
#include "GpWindows.h"
|
#include "GpWindows.h"
|
||||||
|
|
||||||
|
struct IGpAllocator;
|
||||||
|
|
||||||
class GpBWCursor_Win32 final : public IGpCursor_Win32
|
class GpBWCursor_Win32 final : public IGpCursor_Win32
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -13,12 +15,13 @@ public:
|
|||||||
void IncRef() override;
|
void IncRef() override;
|
||||||
void DecRef() 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:
|
private:
|
||||||
GpBWCursor_Win32(HCURSOR cursor);
|
GpBWCursor_Win32(HCURSOR cursor, IGpAllocator *alloc);
|
||||||
~GpBWCursor_Win32();
|
~GpBWCursor_Win32();
|
||||||
|
|
||||||
HCURSOR m_cursor;
|
HCURSOR m_cursor;
|
||||||
int m_refCount;
|
int m_refCount;
|
||||||
|
IGpAllocator *m_alloc;
|
||||||
};
|
};
|
||||||
|
@@ -20,6 +20,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "GpColorCursor_Win32.h"
|
#include "GpColorCursor_Win32.h"
|
||||||
|
#include "IGpAllocator.h"
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@@ -31,7 +32,7 @@ void GpColorCursor_Win32::Destroy()
|
|||||||
this->DecRef();
|
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);
|
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;
|
size_t maskPitch = width + paddingBits - 1;
|
||||||
maskPitch -= maskPitch % paddingBits;
|
maskPitch -= maskPitch % paddingBits;
|
||||||
|
|
||||||
LPVOID maskBits = malloc(maskPitch * height);
|
LPVOID maskBits = alloc->Alloc(maskPitch * height);
|
||||||
if (!maskBits)
|
if (!maskBits)
|
||||||
return nullptr;
|
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);
|
ii.hbmMask = CreateBitmap(width, height, 1, 1, maskBits);
|
||||||
ReleaseDC(NULL, hdc);
|
ReleaseDC(NULL, hdc);
|
||||||
|
|
||||||
|
alloc->Release(maskBits);
|
||||||
|
|
||||||
size_t cursorPitch = width * 4;
|
size_t cursorPitch = width * 4;
|
||||||
|
|
||||||
size_t numPixels = width * height;
|
size_t numPixels = width * height;
|
||||||
@@ -90,19 +93,20 @@ IGpCursor_Win32 *GpColorCursor_Win32::Create(size_t width, size_t height, const
|
|||||||
if (!hicon)
|
if (!hicon)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
void *storage = malloc(sizeof(GpColorCursor_Win32));
|
void *storage = alloc->Alloc(sizeof(GpColorCursor_Win32));
|
||||||
if (!storage)
|
if (!storage)
|
||||||
{
|
{
|
||||||
DestroyIcon(hicon);
|
DestroyIcon(hicon);
|
||||||
return nullptr;
|
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_cursor(cursor)
|
||||||
, m_refCount(1)
|
, m_refCount(1)
|
||||||
|
, m_alloc(alloc)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -126,7 +130,8 @@ void GpColorCursor_Win32::DecRef()
|
|||||||
m_refCount--;
|
m_refCount--;
|
||||||
if (m_refCount == 0)
|
if (m_refCount == 0)
|
||||||
{
|
{
|
||||||
|
IGpAllocator *alloc = m_alloc;
|
||||||
this->~GpColorCursor_Win32();
|
this->~GpColorCursor_Win32();
|
||||||
free(this);
|
alloc->Release(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -3,6 +3,7 @@
|
|||||||
#include "IGpCursor_Win32.h"
|
#include "IGpCursor_Win32.h"
|
||||||
#include "GpWindows.h"
|
#include "GpWindows.h"
|
||||||
|
|
||||||
|
struct IGpAllocator;
|
||||||
|
|
||||||
class GpColorCursor_Win32 final : public IGpCursor_Win32
|
class GpColorCursor_Win32 final : public IGpCursor_Win32
|
||||||
{
|
{
|
||||||
@@ -14,12 +15,13 @@ public:
|
|||||||
void IncRef() override;
|
void IncRef() override;
|
||||||
void DecRef() 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:
|
private:
|
||||||
GpColorCursor_Win32(HCURSOR cursor);
|
GpColorCursor_Win32(IGpAllocator *alloc, HCURSOR cursor);
|
||||||
~GpColorCursor_Win32();
|
~GpColorCursor_Win32();
|
||||||
|
|
||||||
HCURSOR m_cursor;
|
HCURSOR m_cursor;
|
||||||
int m_refCount;
|
int m_refCount;
|
||||||
|
IGpAllocator *m_alloc;
|
||||||
};
|
};
|
||||||
|
@@ -1,56 +0,0 @@
|
|||||||
#include "GpFiberStarter.h"
|
|
||||||
#include "GpFiber_Win32.h"
|
|
||||||
#include "GpWindows.h"
|
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
namespace GpFiberStarter_Win32
|
|
||||||
{
|
|
||||||
struct FiberStartState
|
|
||||||
{
|
|
||||||
GpFiberStarter::ThreadFunc_t m_threadFunc;
|
|
||||||
IGpFiber *m_creatingFiber;
|
|
||||||
void *m_context;
|
|
||||||
};
|
|
||||||
|
|
||||||
static VOID WINAPI FiberStartRoutine(LPVOID lpThreadParameter)
|
|
||||||
{
|
|
||||||
const FiberStartState *tss = static_cast<const FiberStartState*>(lpThreadParameter);
|
|
||||||
|
|
||||||
GpFiberStarter::ThreadFunc_t threadFunc = tss->m_threadFunc;
|
|
||||||
IGpFiber *creatingFiber = tss->m_creatingFiber;
|
|
||||||
void *context = tss->m_context;
|
|
||||||
SwitchToFiber(static_cast<GpFiber_Win32*>(creatingFiber)->GetFiber());
|
|
||||||
|
|
||||||
threadFunc(context);
|
|
||||||
|
|
||||||
assert(!"Fiber function exited");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
IGpFiber *GpFiberStarter::StartFiber(PortabilityLayer::HostSystemServices *systemServices, ThreadFunc_t threadFunc, void *context, IGpFiber *creatingFiber)
|
|
||||||
{
|
|
||||||
ULONG_PTR lowLimit;
|
|
||||||
ULONG_PTR highLimit;
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
GetCurrentThreadStackLimits(&lowLimit, &highLimit);
|
|
||||||
|
|
||||||
ULONG_PTR stackSize = highLimit - lowLimit;
|
|
||||||
#else
|
|
||||||
ULONG_PTR stackSize = 1024 * 1024;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
GpFiberStarter_Win32::FiberStartState startState;
|
|
||||||
startState.m_context = context;
|
|
||||||
startState.m_creatingFiber = creatingFiber;
|
|
||||||
startState.m_threadFunc = threadFunc;
|
|
||||||
|
|
||||||
void *fiber = CreateFiber(static_cast<SIZE_T>(stackSize), GpFiberStarter_Win32::FiberStartRoutine, &startState);
|
|
||||||
if (!fiber)
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
SwitchToFiber(fiber);
|
|
||||||
|
|
||||||
return GpFiber_Win32::Create(fiber);
|
|
||||||
}
|
|
@@ -1,37 +0,0 @@
|
|||||||
#include "GpFiber_Win32.h"
|
|
||||||
#include <new>
|
|
||||||
|
|
||||||
GpFiber_Win32::GpFiber_Win32(LPVOID fiber)
|
|
||||||
: m_fiber(fiber)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void GpFiber_Win32::YieldTo(IGpFiber *toFiber)
|
|
||||||
{
|
|
||||||
SwitchToFiber(static_cast<GpFiber_Win32*>(toFiber)->m_fiber);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GpFiber_Win32::YieldToTerminal(IGpFiber *toFiber)
|
|
||||||
{
|
|
||||||
YieldTo(toFiber);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GpFiber_Win32::Destroy()
|
|
||||||
{
|
|
||||||
this->~GpFiber_Win32();
|
|
||||||
free(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
GpFiber_Win32::~GpFiber_Win32()
|
|
||||||
{
|
|
||||||
DeleteFiber(m_fiber);
|
|
||||||
}
|
|
||||||
|
|
||||||
IGpFiber *GpFiber_Win32::Create(LPVOID fiber)
|
|
||||||
{
|
|
||||||
void *storage = malloc(sizeof(GpFiber_Win32));
|
|
||||||
if (!storage)
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
return new (storage) GpFiber_Win32(fiber);
|
|
||||||
}
|
|
@@ -1,26 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include "GpWindows.h"
|
|
||||||
#include "IGpFiber.h"
|
|
||||||
|
|
||||||
class GpFiber_Win32 final : public IGpFiber
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
void YieldTo(IGpFiber *toFiber) override;
|
|
||||||
void YieldToTerminal(IGpFiber *toFiber) override;
|
|
||||||
void Destroy() override;
|
|
||||||
|
|
||||||
static IGpFiber *Create(LPVOID fiber);
|
|
||||||
|
|
||||||
LPVOID GetFiber() const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
explicit GpFiber_Win32(LPVOID fiber);
|
|
||||||
~GpFiber_Win32();
|
|
||||||
|
|
||||||
LPVOID m_fiber;
|
|
||||||
};
|
|
||||||
|
|
||||||
inline LPVOID GpFiber_Win32::GetFiber() const
|
|
||||||
{
|
|
||||||
return m_fiber;
|
|
||||||
}
|
|
@@ -1,13 +1,32 @@
|
|||||||
#include "GpFileStream_Win32.h"
|
#include "GpFileStream_Win32.h"
|
||||||
|
#include "IGpAllocator.h"
|
||||||
|
|
||||||
GpFileStream_Win32::GpFileStream_Win32(HANDLE handle, bool readable, bool writeable, bool seekable)
|
#include <new>
|
||||||
: m_handle(handle)
|
|
||||||
|
GpFileStream_Win32::GpFileStream_Win32(IGpAllocator *alloc, HANDLE handle, bool readable, bool writeable, bool seekable)
|
||||||
|
: m_alloc(alloc)
|
||||||
|
, m_handle(handle)
|
||||||
, m_readable(readable)
|
, m_readable(readable)
|
||||||
, m_writeable(writeable)
|
, m_writeable(writeable)
|
||||||
, m_seekable(seekable)
|
, 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)
|
size_t GpFileStream_Win32::Read(void *bytesOut, size_t size)
|
||||||
{
|
{
|
||||||
if (!m_readable)
|
if (!m_readable)
|
||||||
@@ -99,24 +118,6 @@ bool GpFileStream_Win32::SeekEnd(GpUFilePos_t loc)
|
|||||||
return SetFilePointerEx(m_handle, li, nullptr, FILE_END) != 0;
|
return SetFilePointerEx(m_handle, li, nullptr, FILE_END) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GpFileStream_Win32::Truncate(GpUFilePos_t loc)
|
|
||||||
{
|
|
||||||
if (!m_writeable)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
GpUFilePos_t oldPos = Tell();
|
|
||||||
if (!SeekStart(loc))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (!SetEndOfFile(m_handle))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (!SeekStart(oldPos))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
GpUFilePos_t GpFileStream_Win32::Size() const
|
GpUFilePos_t GpFileStream_Win32::Size() const
|
||||||
{
|
{
|
||||||
LARGE_INTEGER fsize;
|
LARGE_INTEGER fsize;
|
||||||
@@ -140,7 +141,10 @@ GpUFilePos_t GpFileStream_Win32::Tell() const
|
|||||||
|
|
||||||
void GpFileStream_Win32::Close()
|
void GpFileStream_Win32::Close()
|
||||||
{
|
{
|
||||||
CloseHandle(m_handle);
|
IGpAllocator *alloc = m_alloc;
|
||||||
|
this->~GpFileStream_Win32();
|
||||||
|
|
||||||
|
alloc->Release(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GpFileStream_Win32::Flush()
|
void GpFileStream_Win32::Flush()
|
||||||
|
@@ -7,7 +7,7 @@
|
|||||||
class GpFileStream_Win32 final : public GpIOStream
|
class GpFileStream_Win32 final : public GpIOStream
|
||||||
{
|
{
|
||||||
public:
|
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 Read(void *bytesOut, size_t size) override;
|
||||||
size_t Write(const void *bytes, size_t size) override;
|
size_t Write(const void *bytes, size_t size) override;
|
||||||
@@ -17,13 +17,21 @@ public:
|
|||||||
bool SeekStart(GpUFilePos_t loc) override;
|
bool SeekStart(GpUFilePos_t loc) override;
|
||||||
bool SeekCurrent(GpFilePos_t loc) override;
|
bool SeekCurrent(GpFilePos_t loc) override;
|
||||||
bool SeekEnd(GpUFilePos_t loc) override;
|
bool SeekEnd(GpUFilePos_t loc) override;
|
||||||
bool Truncate(GpUFilePos_t loc) override;
|
|
||||||
GpUFilePos_t Size() const override;
|
GpUFilePos_t Size() const override;
|
||||||
GpUFilePos_t Tell() const override;
|
GpUFilePos_t Tell() const override;
|
||||||
void Close() override;
|
void GP_ASYNCIFY_PARANOID_NAMED(Close)() override;
|
||||||
void Flush() 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:
|
private:
|
||||||
|
GpFileStream_Win32(IGpAllocator *alloc, HANDLE handle, bool readable, bool writeable, bool seekable);
|
||||||
|
|
||||||
|
IGpAllocator *m_alloc;
|
||||||
HANDLE m_handle;
|
HANDLE m_handle;
|
||||||
bool m_readable;
|
bool m_readable;
|
||||||
bool m_writeable;
|
bool m_writeable;
|
||||||
|
@@ -1,45 +1,49 @@
|
|||||||
#include "GpFileSystem_Win32.h"
|
#include "GpFileSystem_Win32.h"
|
||||||
|
|
||||||
|
#include "GpAllocator_C.h"
|
||||||
#include "GpApplicationName.h"
|
#include "GpApplicationName.h"
|
||||||
#include "GpFileStream_Win32.h"
|
#include "GpFileStream_Win32.h"
|
||||||
#include "GpWindows.h"
|
#include "GpWindows.h"
|
||||||
#include "GpMemoryBuffer.h"
|
#include "IGpAllocator.h"
|
||||||
#include "HostDirectoryCursor.h"
|
#include "IGpDirectoryCursor.h"
|
||||||
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <Shlwapi.h>
|
#include <Shlwapi.h>
|
||||||
#include <ShlObj.h>
|
#include <ShlObj.h>
|
||||||
#include <commdlg.h>
|
#include <commdlg.h>
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
|
struct IGpAllocator;
|
||||||
|
|
||||||
extern GpWindowsGlobals g_gpWindowsGlobals;
|
extern GpWindowsGlobals g_gpWindowsGlobals;
|
||||||
|
|
||||||
class GpDirectoryCursor_Win32 final : public PortabilityLayer::HostDirectoryCursor
|
class GpDirectoryCursor_Win32 final : public IGpDirectoryCursor
|
||||||
{
|
{
|
||||||
public:
|
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;
|
bool GetNext(const char *&outFileName) override;
|
||||||
void Destroy() override;
|
void Destroy() override;
|
||||||
|
|
||||||
private:
|
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();
|
~GpDirectoryCursor_Win32();
|
||||||
|
|
||||||
|
IGpAllocator *m_alloc;
|
||||||
HANDLE m_handle;
|
HANDLE m_handle;
|
||||||
WIN32_FIND_DATAW m_findData;
|
WIN32_FIND_DATAW m_findData;
|
||||||
char m_chars[MAX_PATH + 1];
|
char m_chars[MAX_PATH + 1];
|
||||||
bool m_haveNext;
|
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)
|
if (!storage)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
return new (storage) GpDirectoryCursor_Win32(handle, findData);
|
return new (storage) GpDirectoryCursor_Win32(alloc, handle, findData);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GpDirectoryCursor_Win32::GetNext(const char *&outFileName)
|
bool GpDirectoryCursor_Win32::GetNext(const char *&outFileName)
|
||||||
@@ -83,14 +87,16 @@ bool GpDirectoryCursor_Win32::GetNext(const char *&outFileName)
|
|||||||
|
|
||||||
void GpDirectoryCursor_Win32::Destroy()
|
void GpDirectoryCursor_Win32::Destroy()
|
||||||
{
|
{
|
||||||
|
IGpAllocator *alloc = m_alloc;
|
||||||
this->~GpDirectoryCursor_Win32();
|
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_handle(handle)
|
||||||
, m_findData(findData)
|
, m_findData(findData)
|
||||||
, m_haveNext(true)
|
, m_haveNext(true)
|
||||||
|
, m_alloc(alloc)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -99,47 +105,76 @@ GpDirectoryCursor_Win32::~GpDirectoryCursor_Win32()
|
|||||||
FindClose(m_handle);
|
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;
|
m_executablePath[0] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GpFileSystem_Win32::Destroy()
|
||||||
|
{
|
||||||
|
IGpAllocator *alloc = m_alloc;
|
||||||
|
this->~GpFileSystem_Win32();
|
||||||
|
alloc->Release(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GpFileSystem_Win32::Init()
|
||||||
|
{
|
||||||
PWSTR docsPath;
|
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
|
CoTaskMemFree(docsPath);
|
||||||
{
|
return false;
|
||||||
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);
|
||||||
|
|
||||||
|
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);
|
DWORD modulePathSize = GetModuleFileNameW(nullptr, m_executablePath, MAX_PATH);
|
||||||
if (modulePathSize == MAX_PATH || modulePathSize == 0)
|
if (modulePathSize == MAX_PATH || modulePathSize == 0)
|
||||||
m_executablePath[0] = 0;
|
m_executablePath[0] = 0;
|
||||||
@@ -159,7 +194,7 @@ GpFileSystem_Win32::GpFileSystem_Win32()
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wcscat_s(m_executablePath, L"Resources"))
|
if (wcscat_s(m_executablePath, L"Packaged"))
|
||||||
{
|
{
|
||||||
currentPathLength = 0;
|
currentPathLength = 0;
|
||||||
break;
|
break;
|
||||||
@@ -174,12 +209,19 @@ GpFileSystem_Win32::GpFileSystem_Win32()
|
|||||||
currentPathLength--;
|
currentPathLength--;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (currentPathLength > 0)
|
if (currentPathLength == 0)
|
||||||
{
|
return false;
|
||||||
m_packagedDir = std::wstring(m_executablePath) + L"Packaged\\";
|
|
||||||
m_housesDir = std::wstring(m_executablePath) + L"Packaged\\Houses\\";
|
if (!m_packagedDir.Set(m_executablePath) || !m_packagedDir.Append(L"Packaged\\"))
|
||||||
m_resourcesDir = std::wstring(m_executablePath) + L"Resources\\";
|
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)
|
bool GpFileSystem_Win32::FileExists(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *path)
|
||||||
@@ -192,24 +234,24 @@ bool GpFileSystem_Win32::FileExists(PortabilityLayer::VirtualDirectory_t virtual
|
|||||||
return PathFileExistsW(winPath) != 0;
|
return PathFileExistsW(winPath) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GpFileSystem_Win32::FileLocked(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *path, bool *exists)
|
bool GpFileSystem_Win32::FileLocked(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *path, bool &exists)
|
||||||
{
|
{
|
||||||
wchar_t winPath[MAX_PATH + 1];
|
wchar_t winPath[MAX_PATH + 1];
|
||||||
|
|
||||||
if (!ResolvePath(virtualDirectory, &path, 1, winPath))
|
if (!ResolvePath(virtualDirectory, &path, 1, winPath))
|
||||||
{
|
{
|
||||||
*exists = false;
|
exists = false;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
DWORD attribs = GetFileAttributesW(winPath);
|
DWORD attribs = GetFileAttributesW(winPath);
|
||||||
if (attribs == INVALID_FILE_ATTRIBUTES)
|
if (attribs == INVALID_FILE_ATTRIBUTES)
|
||||||
{
|
{
|
||||||
*exists = false;
|
exists = false;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
*exists = true;
|
exists = true;
|
||||||
return (attribs & FILE_ATTRIBUTE_READONLY) != 0;
|
return (attribs & FILE_ATTRIBUTE_READONLY) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -218,7 +260,7 @@ GpIOStream *GpFileSystem_Win32::OpenFileNested(PortabilityLayer::VirtualDirector
|
|||||||
wchar_t winPath[MAX_PATH + 1];
|
wchar_t winPath[MAX_PATH + 1];
|
||||||
|
|
||||||
if (!ResolvePath(virtualDirectory, paths, numPaths, winPath))
|
if (!ResolvePath(virtualDirectory, paths, numPaths, winPath))
|
||||||
return false;
|
return nullptr;
|
||||||
|
|
||||||
const DWORD desiredAccess = writeAccess ? (GENERIC_WRITE | GENERIC_READ) : GENERIC_READ;
|
const DWORD desiredAccess = writeAccess ? (GENERIC_WRITE | GENERIC_READ) : GENERIC_READ;
|
||||||
DWORD winCreationDisposition = 0;
|
DWORD winCreationDisposition = 0;
|
||||||
@@ -241,14 +283,14 @@ GpIOStream *GpFileSystem_Win32::OpenFileNested(PortabilityLayer::VirtualDirector
|
|||||||
winCreationDisposition = TRUNCATE_EXISTING;
|
winCreationDisposition = TRUNCATE_EXISTING;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return false;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
HANDLE h = CreateFileW(winPath, desiredAccess, FILE_SHARE_READ, nullptr, winCreationDisposition, FILE_ATTRIBUTE_NORMAL, nullptr);
|
HANDLE h = CreateFileW(winPath, desiredAccess, FILE_SHARE_READ, nullptr, winCreationDisposition, FILE_ATTRIBUTE_NORMAL, nullptr);
|
||||||
if (h == INVALID_HANDLE_VALUE)
|
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)
|
bool GpFileSystem_Win32::DeleteFile(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *path, bool &existed)
|
||||||
@@ -273,11 +315,11 @@ bool GpFileSystem_Win32::DeleteFile(PortabilityLayer::VirtualDirectory_t virtual
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
PortabilityLayer::HostDirectoryCursor *GpFileSystem_Win32::ScanDirectoryNested(PortabilityLayer::VirtualDirectory_t virtualDirectory, char const* const* paths, size_t numPaths)
|
IGpDirectoryCursor *GpFileSystem_Win32::ScanDirectoryNested(PortabilityLayer::VirtualDirectory_t virtualDirectory, char const* const* paths, size_t numPaths)
|
||||||
{
|
{
|
||||||
wchar_t winPath[MAX_PATH + 2];
|
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)
|
if (!expandedPaths)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
@@ -286,7 +328,7 @@ PortabilityLayer::HostDirectoryCursor *GpFileSystem_Win32::ScanDirectoryNested(P
|
|||||||
expandedPaths[numPaths] = "*";
|
expandedPaths[numPaths] = "*";
|
||||||
|
|
||||||
const bool isPathResolved = ResolvePath(virtualDirectory, expandedPaths, numPaths + 1, winPath);
|
const bool isPathResolved = ResolvePath(virtualDirectory, expandedPaths, numPaths + 1, winPath);
|
||||||
free(expandedPaths);
|
m_alloc->Release(expandedPaths);
|
||||||
|
|
||||||
if (!isPathResolved)
|
if (!isPathResolved)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@@ -297,7 +339,7 @@ PortabilityLayer::HostDirectoryCursor *GpFileSystem_Win32::ScanDirectoryNested(P
|
|||||||
if (ff == INVALID_HANDLE_VALUE)
|
if (ff == INVALID_HANDLE_VALUE)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
return GpDirectoryCursor_Win32::Create(ff, findData);
|
return GpDirectoryCursor_Win32::Create(m_alloc, ff, findData);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GpFileSystem_Win32::ValidateFilePathUnicodeChar(uint32_t c) const
|
bool GpFileSystem_Win32::ValidateFilePathUnicodeChar(uint32_t c) const
|
||||||
@@ -320,16 +362,6 @@ bool GpFileSystem_Win32::ValidateFilePathUnicodeChar(uint32_t c) const
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GpFileSystem_Win32::IsVirtualDirectoryLooseResources(PortabilityLayer::VirtualDirectory_t virtualDir) const
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void GpFileSystem_Win32::SetMainThreadRelay(IGpThreadRelay *relay)
|
|
||||||
{
|
|
||||||
(void)relay;
|
|
||||||
}
|
|
||||||
|
|
||||||
void GpFileSystem_Win32::SetDelayCallback(GpFileSystem_Win32::DelayCallback_t delayCallback)
|
void GpFileSystem_Win32::SetDelayCallback(GpFileSystem_Win32::DelayCallback_t delayCallback)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -342,7 +374,7 @@ bool GpFileSystem_Win32::ValidateFilePath(const char *str, size_t length) const
|
|||||||
if (c >= '0' && c <= '9')
|
if (c >= '0' && c <= '9')
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (c == '_' || c == '.' || c == '\'')
|
if (c == '_' || c == '.' || c == '\'' || c == '!')
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (c == ' ' && i != 0 && i != length - 1)
|
if (c == ' ' && i != 0 && i != length - 1)
|
||||||
@@ -430,9 +462,27 @@ const wchar_t *GpFileSystem_Win32::GetBasePath() const
|
|||||||
return m_executablePath;
|
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()
|
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)
|
bool GpFileSystem_Win32::ResolvePath(PortabilityLayer::VirtualDirectory_t virtualDirectory, char const* const* paths, size_t numPaths, wchar_t *outPath)
|
||||||
@@ -442,31 +492,31 @@ bool GpFileSystem_Win32::ResolvePath(PortabilityLayer::VirtualDirectory_t virtua
|
|||||||
switch (virtualDirectory)
|
switch (virtualDirectory)
|
||||||
{
|
{
|
||||||
case PortabilityLayer::VirtualDirectories::kApplicationData:
|
case PortabilityLayer::VirtualDirectories::kApplicationData:
|
||||||
baseDir = m_packagedDir.c_str();
|
baseDir = m_packagedDir.Buffer();
|
||||||
break;
|
break;
|
||||||
case PortabilityLayer::VirtualDirectories::kGameData:
|
case PortabilityLayer::VirtualDirectories::kGameData:
|
||||||
baseDir = m_housesDir.c_str();
|
baseDir = m_housesDir.Buffer();
|
||||||
break;
|
break;
|
||||||
case PortabilityLayer::VirtualDirectories::kUserData:
|
case PortabilityLayer::VirtualDirectories::kUserData:
|
||||||
baseDir = m_userHousesDir.c_str();
|
baseDir = m_userHousesDir.Buffer();
|
||||||
break;
|
break;
|
||||||
case PortabilityLayer::VirtualDirectories::kUserSaves:
|
case PortabilityLayer::VirtualDirectories::kUserSaves:
|
||||||
baseDir = m_userSavesDir.c_str();
|
baseDir = m_userSavesDir.Buffer();
|
||||||
break;
|
break;
|
||||||
case PortabilityLayer::VirtualDirectories::kPrefs:
|
case PortabilityLayer::VirtualDirectories::kPrefs:
|
||||||
baseDir = m_prefsDir.c_str();
|
baseDir = m_prefsDir.Buffer();
|
||||||
break;
|
break;
|
||||||
case PortabilityLayer::VirtualDirectories::kFonts:
|
case PortabilityLayer::VirtualDirectories::kFonts:
|
||||||
baseDir = m_resourcesDir.c_str();
|
baseDir = m_resourcesDir.Buffer();
|
||||||
break;
|
break;
|
||||||
case PortabilityLayer::VirtualDirectories::kHighScores:
|
case PortabilityLayer::VirtualDirectories::kHighScores:
|
||||||
baseDir = m_scoresDir.c_str();
|
baseDir = m_scoresDir.Buffer();
|
||||||
break;
|
break;
|
||||||
case PortabilityLayer::VirtualDirectories::kLogs:
|
case PortabilityLayer::VirtualDirectories::kLogs:
|
||||||
baseDir = m_logsDir.c_str();
|
baseDir = m_logsDir.Buffer();
|
||||||
break;
|
break;
|
||||||
case PortabilityLayer::VirtualDirectories::kFontCache:
|
case PortabilityLayer::VirtualDirectories::kSourceExport:
|
||||||
baseDir = m_fontCacheDir.c_str();
|
baseDir = m_exportDir.Buffer();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
@@ -512,4 +562,4 @@ bool GpFileSystem_Win32::ResolvePath(PortabilityLayer::VirtualDirectory_t virtua
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
GpFileSystem_Win32 GpFileSystem_Win32::ms_instance;
|
GpFileSystem_Win32 *GpFileSystem_Win32::ms_instance;
|
||||||
|
@@ -1,48 +1,51 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "HostFileSystem.h"
|
#include "IGpFileSystem.h"
|
||||||
|
|
||||||
#include "GpCoreDefs.h"
|
#include "GpCoreDefs.h"
|
||||||
#include "GpWindows.h"
|
#include "GpWindows.h"
|
||||||
|
#include "GpString.h"
|
||||||
|
|
||||||
#include <string>
|
class GpFileSystem_Win32 final : public IGpFileSystem
|
||||||
|
|
||||||
class GpFileSystem_Win32 final : public PortabilityLayer::HostFileSystem
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
GpFileSystem_Win32();
|
explicit GpFileSystem_Win32(IGpAllocator *alloc);
|
||||||
|
|
||||||
|
void Destroy();
|
||||||
|
|
||||||
bool FileExists(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *path) override;
|
bool FileExists(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *path) override;
|
||||||
bool FileLocked(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *path, bool *exists) override;
|
bool FileLocked(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *path, bool &exists) override;
|
||||||
GpIOStream *OpenFileNested(PortabilityLayer::VirtualDirectory_t virtualDirectory, char const* const* paths, size_t numPaths, bool writeAccess, GpFileCreationDisposition_t createDisposition) override;
|
GpIOStream *OpenFileNested(PortabilityLayer::VirtualDirectory_t virtualDirectory, char const* const* paths, size_t numPaths, 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) override;
|
||||||
PortabilityLayer::HostDirectoryCursor *ScanDirectoryNested(PortabilityLayer::VirtualDirectory_t virtualDirectory, char const* const* paths, size_t numPaths) override;
|
IGpDirectoryCursor *ScanDirectoryNested(PortabilityLayer::VirtualDirectory_t virtualDirectory, char const* const* paths, size_t numPaths) override;
|
||||||
|
|
||||||
bool ValidateFilePath(const char *path, size_t sz) const override;
|
bool ValidateFilePath(const char *path, size_t sz) const override;
|
||||||
bool ValidateFilePathUnicodeChar(uint32_t ch) const override;
|
bool ValidateFilePathUnicodeChar(uint32_t ch) const override;
|
||||||
|
|
||||||
bool IsVirtualDirectoryLooseResources(PortabilityLayer::VirtualDirectory_t virtualDir) const override;
|
|
||||||
|
|
||||||
void SetMainThreadRelay(IGpThreadRelay *relay) override;
|
|
||||||
void SetDelayCallback(DelayCallback_t delayCallback) override;
|
void SetDelayCallback(DelayCallback_t delayCallback) override;
|
||||||
|
|
||||||
const wchar_t *GetBasePath() const;
|
const wchar_t *GetBasePath() const;
|
||||||
|
|
||||||
|
static GpFileSystem_Win32 *CreateInstance(IGpAllocator *alloc);
|
||||||
static GpFileSystem_Win32 *GetInstance();
|
static GpFileSystem_Win32 *GetInstance();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
bool Init();
|
||||||
|
|
||||||
bool ResolvePath(PortabilityLayer::VirtualDirectory_t virtualDirectory, char const* const* paths, size_t numPaths, wchar_t *outPath);
|
bool ResolvePath(PortabilityLayer::VirtualDirectory_t virtualDirectory, char const* const* paths, size_t numPaths, wchar_t *outPath);
|
||||||
|
|
||||||
std::wstring m_prefsDir;
|
GpWString m_prefsDir;
|
||||||
std::wstring m_scoresDir;
|
GpWString m_scoresDir;
|
||||||
std::wstring m_packagedDir;
|
GpWString m_packagedDir;
|
||||||
std::wstring m_housesDir;
|
GpWString m_housesDir;
|
||||||
std::wstring m_logsDir;
|
GpWString m_logsDir;
|
||||||
std::wstring m_userHousesDir;
|
GpWString m_userHousesDir;
|
||||||
std::wstring m_userSavesDir;
|
GpWString m_userSavesDir;
|
||||||
std::wstring m_resourcesDir;
|
GpWString m_resourcesDir;
|
||||||
std::wstring m_fontCacheDir;
|
GpWString m_exportDir;
|
||||||
wchar_t m_executablePath[MAX_PATH];
|
wchar_t m_executablePath[MAX_PATH];
|
||||||
|
|
||||||
static GpFileSystem_Win32 ms_instance;
|
IGpAllocator *m_alloc;
|
||||||
|
|
||||||
|
static GpFileSystem_Win32 *ms_instance;
|
||||||
};
|
};
|
||||||
|
@@ -1,3 +1,4 @@
|
|||||||
|
#include "GpAllocator_C.h"
|
||||||
#include "GpLogDriver_Win32.h"
|
#include "GpLogDriver_Win32.h"
|
||||||
#include "GpFileSystem_Win32.h"
|
#include "GpFileSystem_Win32.h"
|
||||||
|
|
||||||
@@ -7,6 +8,7 @@
|
|||||||
GpLogDriver_Win32::GpLogDriver_Win32()
|
GpLogDriver_Win32::GpLogDriver_Win32()
|
||||||
: m_stream(nullptr)
|
: m_stream(nullptr)
|
||||||
, m_isInitialized(false)
|
, 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)
|
if (formattedSize <= 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
char *charBuff = static_cast<char*>(malloc(formattedSize + 1));
|
char *charBuff = static_cast<char*>(m_alloc->Alloc(formattedSize + 1));
|
||||||
if (!charBuff)
|
if (!charBuff)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
vsnprintf(charBuff, formattedSize + 1, fmt, args);
|
vsnprintf(charBuff, formattedSize + 1, fmt, args);
|
||||||
|
|
||||||
m_stream->Write(charBuff, formattedSize);
|
m_stream->Write(charBuff, formattedSize);
|
||||||
free(charBuff);
|
m_alloc->Release(charBuff);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_stream->Write("\n", 1);
|
m_stream->Write("\n", 1);
|
||||||
|
@@ -3,6 +3,7 @@
|
|||||||
#include "IGpLogDriver.h"
|
#include "IGpLogDriver.h"
|
||||||
|
|
||||||
class GpIOStream;
|
class GpIOStream;
|
||||||
|
struct IGpAllocator;
|
||||||
|
|
||||||
class GpLogDriver_Win32 : public IGpLogDriver
|
class GpLogDriver_Win32 : public IGpLogDriver
|
||||||
{
|
{
|
||||||
@@ -20,6 +21,7 @@ private:
|
|||||||
void InitInternal();
|
void InitInternal();
|
||||||
|
|
||||||
GpIOStream *m_stream;
|
GpIOStream *m_stream;
|
||||||
|
IGpAllocator *m_alloc;
|
||||||
bool m_isInitialized;
|
bool m_isInitialized;
|
||||||
|
|
||||||
static GpLogDriver_Win32 ms_instance;
|
static GpLogDriver_Win32 ms_instance;
|
||||||
|
@@ -1,10 +1,10 @@
|
|||||||
#include "GpMain.h"
|
#include "GpMain.h"
|
||||||
|
#include "GpAllocator_C.h"
|
||||||
#include "GpAudioDriverFactory.h"
|
#include "GpAudioDriverFactory.h"
|
||||||
#include "GpBWCursor_Win32.h"
|
#include "GpBWCursor_Win32.h"
|
||||||
#include "GpColorCursor_Win32.h"
|
#include "GpColorCursor_Win32.h"
|
||||||
#include "GpDisplayDriverFactory.h"
|
#include "GpDisplayDriverFactory.h"
|
||||||
#include "GpGlobalConfig.h"
|
#include "GpGlobalConfig.h"
|
||||||
#include "GpFiber_Win32.h"
|
|
||||||
#include "GpFileSystem_Win32.h"
|
#include "GpFileSystem_Win32.h"
|
||||||
#include "GpLogDriver_Win32.h"
|
#include "GpLogDriver_Win32.h"
|
||||||
#include "GpFontHandlerFactory.h"
|
#include "GpFontHandlerFactory.h"
|
||||||
@@ -12,10 +12,9 @@
|
|||||||
#include "GpAppInterface.h"
|
#include "GpAppInterface.h"
|
||||||
#include "GpSystemServices_Win32.h"
|
#include "GpSystemServices_Win32.h"
|
||||||
#include "GpVOSEvent.h"
|
#include "GpVOSEvent.h"
|
||||||
|
#include "IGpFileSystem.h"
|
||||||
#include "IGpVOSEventQueue.h"
|
#include "IGpVOSEventQueue.h"
|
||||||
|
|
||||||
#include "HostFileSystem.h"
|
|
||||||
|
|
||||||
#include "GpWindows.h"
|
#include "GpWindows.h"
|
||||||
|
|
||||||
#include "resource.h"
|
#include "resource.h"
|
||||||
@@ -29,7 +28,6 @@ GpWindowsGlobals g_gpWindowsGlobals;
|
|||||||
extern "C" __declspec(dllimport) IGpAudioDriver *GpDriver_CreateAudioDriver_XAudio2(const GpAudioDriverProperties &properties);
|
extern "C" __declspec(dllimport) IGpAudioDriver *GpDriver_CreateAudioDriver_XAudio2(const GpAudioDriverProperties &properties);
|
||||||
extern "C" __declspec(dllimport) IGpDisplayDriver *GpDriver_CreateDisplayDriver_D3D11(const GpDisplayDriverProperties &properties);
|
extern "C" __declspec(dllimport) IGpDisplayDriver *GpDriver_CreateDisplayDriver_D3D11(const GpDisplayDriverProperties &properties);
|
||||||
extern "C" __declspec(dllimport) IGpInputDriver *GpDriver_CreateInputDriver_XInput(const GpInputDriverProperties &properties);
|
extern "C" __declspec(dllimport) IGpInputDriver *GpDriver_CreateInputDriver_XInput(const GpInputDriverProperties &properties);
|
||||||
extern "C" __declspec(dllimport) IGpFontHandler *GpDriver_CreateFontHandler_FreeType2(const GpFontHandlerProperties &properties);
|
|
||||||
|
|
||||||
static void PostMouseEvent(IGpVOSEventQueue *eventQueue, GpMouseEventType_t eventType, GpMouseButton_t button, int32_t x, int32_t y, float pixelScaleX, float pixelScaleY)
|
static void PostMouseEvent(IGpVOSEventQueue *eventQueue, GpMouseEventType_t eventType, GpMouseButton_t button, int32_t x, int32_t y, float pixelScaleX, float pixelScaleY)
|
||||||
{
|
{
|
||||||
@@ -406,6 +404,13 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
|
|||||||
int nArgs;
|
int nArgs;
|
||||||
LPWSTR *cmdLineArgs = CommandLineToArgvW(cmdLine, &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++)
|
for (int i = 1; i < nArgs; i++)
|
||||||
{
|
{
|
||||||
if (!wcscmp(cmdLineArgs[i], L"-diagnostics"))
|
if (!wcscmp(cmdLineArgs[i], L"-diagnostics"))
|
||||||
@@ -413,10 +418,14 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
|
|||||||
}
|
}
|
||||||
|
|
||||||
IGpLogDriver *logger = GpLogDriver_Win32::GetInstance();
|
IGpLogDriver *logger = GpLogDriver_Win32::GetInstance();
|
||||||
|
IGpSystemServices *sysServices = GpSystemServices_Win32::GetInstance();
|
||||||
|
|
||||||
GpAppInterface_Get()->PL_HostFileSystem_SetInstance(GpFileSystem_Win32::GetInstance());
|
GpDriverCollection *drivers = GpAppInterface_Get()->PL_GetDriverCollection();
|
||||||
GpAppInterface_Get()->PL_HostSystemServices_SetInstance(GpSystemServices_Win32::GetInstance());
|
|
||||||
GpAppInterface_Get()->PL_HostLogDriver_SetInstance(GpLogDriver_Win32::GetInstance());
|
drivers->SetDriver<GpDriverIDs::kFileSystem>(GpFileSystem_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_hInstance = hInstance;
|
||||||
g_gpWindowsGlobals.m_hPrevInstance = hPrevInstance;
|
g_gpWindowsGlobals.m_hPrevInstance = hPrevInstance;
|
||||||
@@ -429,7 +438,6 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
|
|||||||
g_gpWindowsGlobals.m_hIcon = LoadIconW(hInstance, MAKEINTRESOURCEW(IDI_ICON1));
|
g_gpWindowsGlobals.m_hIcon = LoadIconW(hInstance, MAKEINTRESOURCEW(IDI_ICON1));
|
||||||
g_gpWindowsGlobals.m_hIconSm = LoadIconW(hInstance, MAKEINTRESOURCEW(IDI_ICON2));
|
g_gpWindowsGlobals.m_hIconSm = LoadIconW(hInstance, MAKEINTRESOURCEW(IDI_ICON2));
|
||||||
|
|
||||||
g_gpWindowsGlobals.m_createFiberFunc = GpFiber_Win32::Create;
|
|
||||||
g_gpWindowsGlobals.m_createBWCursorFunc = GpBWCursor_Win32::Create;
|
g_gpWindowsGlobals.m_createBWCursorFunc = GpBWCursor_Win32::Create;
|
||||||
g_gpWindowsGlobals.m_createColorCursorFunc = GpColorCursor_Win32::Create;
|
g_gpWindowsGlobals.m_createColorCursorFunc = GpColorCursor_Win32::Create;
|
||||||
g_gpWindowsGlobals.m_translateWindowsMessageFunc = TranslateWindowsMessage;
|
g_gpWindowsGlobals.m_translateWindowsMessageFunc = TranslateWindowsMessage;
|
||||||
@@ -438,7 +446,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
|
|||||||
|
|
||||||
g_gpGlobalConfig.m_audioDriverType = EGpAudioDriverType_XAudio2;
|
g_gpGlobalConfig.m_audioDriverType = EGpAudioDriverType_XAudio2;
|
||||||
|
|
||||||
g_gpGlobalConfig.m_fontHandlerType = EGpFontHandlerType_FreeType2;
|
g_gpGlobalConfig.m_fontHandlerType = EGpFontHandlerType_None;
|
||||||
|
|
||||||
EGpInputDriverType inputDrivers[] =
|
EGpInputDriverType inputDrivers[] =
|
||||||
{
|
{
|
||||||
@@ -450,12 +458,12 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
|
|||||||
|
|
||||||
g_gpGlobalConfig.m_osGlobals = &g_gpWindowsGlobals;
|
g_gpGlobalConfig.m_osGlobals = &g_gpWindowsGlobals;
|
||||||
g_gpGlobalConfig.m_logger = logger;
|
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);
|
GpDisplayDriverFactory::RegisterDisplayDriverFactory(EGpDisplayDriverType_D3D11, GpDriver_CreateDisplayDriver_D3D11);
|
||||||
GpAudioDriverFactory::RegisterAudioDriverFactory(EGpAudioDriverType_XAudio2, GpDriver_CreateAudioDriver_XAudio2);
|
GpAudioDriverFactory::RegisterAudioDriverFactory(EGpAudioDriverType_XAudio2, GpDriver_CreateAudioDriver_XAudio2);
|
||||||
GpInputDriverFactory::RegisterInputDriverFactory(EGpInputDriverType_XInput, GpDriver_CreateInputDriver_XInput);
|
GpInputDriverFactory::RegisterInputDriverFactory(EGpInputDriverType_XInput, GpDriver_CreateInputDriver_XInput);
|
||||||
GpFontHandlerFactory::RegisterFontHandlerFactory(EGpFontHandlerType_FreeType2, GpDriver_CreateFontHandler_FreeType2);
|
|
||||||
|
|
||||||
if (logger)
|
if (logger)
|
||||||
logger->Printf(IGpLogDriver::Category_Information, "Windows environment configured, starting up");
|
logger->Printf(IGpLogDriver::Category_Information, "Windows environment configured, starting up");
|
||||||
@@ -467,5 +475,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
|
|||||||
|
|
||||||
LocalFree(cmdLineArgs);
|
LocalFree(cmdLineArgs);
|
||||||
|
|
||||||
|
fs->Destroy();
|
||||||
|
|
||||||
return returnCode;
|
return returnCode;
|
||||||
}
|
}
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
#include "GpMutex_Win32.h"
|
#include "GpMutex_Win32.h"
|
||||||
|
|
||||||
|
#include "IGpAllocator.h"
|
||||||
#include "GpWindows.h"
|
#include "GpWindows.h"
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@@ -7,8 +8,9 @@
|
|||||||
|
|
||||||
void GpMutex_Win32::Destroy()
|
void GpMutex_Win32::Destroy()
|
||||||
{
|
{
|
||||||
|
IGpAllocator *alloc = m_alloc;
|
||||||
this->~GpMutex_Win32();
|
this->~GpMutex_Win32();
|
||||||
free(this);
|
alloc->Release(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GpMutex_Win32::Lock()
|
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)
|
if (!storage)
|
||||||
return nullptr;
|
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);
|
InitializeCriticalSection(&m_critSection);
|
||||||
}
|
}
|
||||||
|
@@ -1,21 +1,24 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "HostMutex.h"
|
#include "IGpMutex.h"
|
||||||
|
|
||||||
#include "GpWindows.h"
|
#include "GpWindows.h"
|
||||||
|
|
||||||
class GpMutex_Win32 final : public PortabilityLayer::HostMutex
|
struct IGpAllocator;
|
||||||
|
|
||||||
|
class GpMutex_Win32 final : public IGpMutex
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
void Destroy() override;
|
void Destroy() override;
|
||||||
void Lock() override;
|
void Lock() override;
|
||||||
void Unlock() override;
|
void Unlock() override;
|
||||||
|
|
||||||
static GpMutex_Win32 *Create();
|
static GpMutex_Win32 *Create(IGpAllocator *alloc);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const GpMutex_Win32();
|
explicit GpMutex_Win32(IGpAllocator *alloc);
|
||||||
~GpMutex_Win32();
|
~GpMutex_Win32();
|
||||||
|
|
||||||
CRITICAL_SECTION m_critSection;
|
CRITICAL_SECTION m_critSection;
|
||||||
|
IGpAllocator *m_alloc;
|
||||||
};
|
};
|
||||||
|
@@ -1,19 +1,122 @@
|
|||||||
#include "GpSystemServices_Win32.h"
|
#include "GpSystemServices_Win32.h"
|
||||||
#include "GpMutex_Win32.h"
|
#include "GpMutex_Win32.h"
|
||||||
#include "GpThreadEvent_Win32.h"
|
#include "GpThreadEvent_Win32.h"
|
||||||
|
#include "GpWindows.h"
|
||||||
|
#include "GpAllocator_C.h"
|
||||||
|
|
||||||
|
#include "IGpClipboardContents.h"
|
||||||
|
|
||||||
|
#include "GpUnicode.h"
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#pragma push_macro("CreateMutex")
|
#pragma push_macro("CreateMutex")
|
||||||
#ifdef CreateMutex
|
#ifdef CreateMutex
|
||||||
#undef CreateMutex
|
#undef CreateMutex
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
extern GpWindowsGlobals g_gpWindowsGlobals;
|
||||||
|
|
||||||
|
namespace GpSystemServices_Win32_Private
|
||||||
|
{
|
||||||
|
class RefCountedClipboard
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
RefCountedClipboard();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual ~RefCountedClipboard();
|
||||||
|
|
||||||
|
void AddRef();
|
||||||
|
void DecRef();
|
||||||
|
|
||||||
|
unsigned int m_refCount;
|
||||||
|
};
|
||||||
|
|
||||||
|
class TextClipboard : public RefCountedClipboard, public IGpClipboardContentsText
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
TextClipboard(const uint8_t *utf8Text, size_t utf8Size);
|
||||||
|
~TextClipboard() override;
|
||||||
|
|
||||||
|
GpClipboardContentsType_t GetContentsType() const override;
|
||||||
|
void Destroy() override;
|
||||||
|
IGpClipboardContents *Clone() const override;
|
||||||
|
const uint8_t *GetBytes() const override;
|
||||||
|
size_t GetSize() const override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<uint8_t> m_utf8Text;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
RefCountedClipboard::RefCountedClipboard()
|
||||||
|
: m_refCount(1)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
RefCountedClipboard::~RefCountedClipboard()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void RefCountedClipboard::AddRef()
|
||||||
|
{
|
||||||
|
m_refCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RefCountedClipboard::DecRef()
|
||||||
|
{
|
||||||
|
unsigned int rc = --m_refCount;
|
||||||
|
if (rc == 0)
|
||||||
|
delete this;
|
||||||
|
}
|
||||||
|
|
||||||
|
TextClipboard::TextClipboard(const uint8_t *utf8Text, size_t utf8Size)
|
||||||
|
{
|
||||||
|
m_utf8Text.resize(utf8Size);
|
||||||
|
if (utf8Size > 0)
|
||||||
|
memcpy(&m_utf8Text[0], utf8Text, utf8Size);
|
||||||
|
}
|
||||||
|
|
||||||
|
TextClipboard::~TextClipboard()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
GpClipboardContentsType_t TextClipboard::GetContentsType() const
|
||||||
|
{
|
||||||
|
return GpClipboardContentsTypes::kText;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TextClipboard::Destroy()
|
||||||
|
{
|
||||||
|
this->DecRef();
|
||||||
|
}
|
||||||
|
|
||||||
|
IGpClipboardContents *TextClipboard::Clone() const
|
||||||
|
{
|
||||||
|
const_cast<TextClipboard*>(this)->AddRef();
|
||||||
|
return const_cast<TextClipboard*>(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
const uint8_t *TextClipboard::GetBytes() const
|
||||||
|
{
|
||||||
|
if (m_utf8Text.size() == 0)
|
||||||
|
return nullptr;
|
||||||
|
return &m_utf8Text[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t TextClipboard::GetSize() const
|
||||||
|
{
|
||||||
|
return m_utf8Text.size();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct GpSystemServices_Win32_ThreadStartParams
|
struct GpSystemServices_Win32_ThreadStartParams
|
||||||
{
|
{
|
||||||
GpSystemServices_Win32::ThreadFunc_t m_threadFunc;
|
GpSystemServices_Win32::ThreadFunc_t m_threadFunc;
|
||||||
void *m_threadContext;
|
void *m_threadContext;
|
||||||
PortabilityLayer::HostThreadEvent *m_threadStartEvent;
|
IGpThreadEvent *m_threadStartEvent;
|
||||||
};
|
};
|
||||||
|
|
||||||
static DWORD WINAPI StaticStartThread(LPVOID lpThreadParameter)
|
static DWORD WINAPI StaticStartThread(LPVOID lpThreadParameter)
|
||||||
@@ -22,7 +125,7 @@ static DWORD WINAPI StaticStartThread(LPVOID lpThreadParameter)
|
|||||||
|
|
||||||
GpSystemServices_Win32::ThreadFunc_t threadFunc = threadParams->m_threadFunc;
|
GpSystemServices_Win32::ThreadFunc_t threadFunc = threadParams->m_threadFunc;
|
||||||
void *threadContext = threadParams->m_threadContext;
|
void *threadContext = threadParams->m_threadContext;
|
||||||
PortabilityLayer::HostThreadEvent *threadStartEvent = threadParams->m_threadStartEvent;
|
IGpThreadEvent *threadStartEvent = threadParams->m_threadStartEvent;
|
||||||
|
|
||||||
threadStartEvent->Signal();
|
threadStartEvent->Signal();
|
||||||
|
|
||||||
@@ -31,6 +134,11 @@ static DWORD WINAPI StaticStartThread(LPVOID lpThreadParameter)
|
|||||||
|
|
||||||
GpSystemServices_Win32::GpSystemServices_Win32()
|
GpSystemServices_Win32::GpSystemServices_Win32()
|
||||||
: m_isTouchscreenSimulation(false)
|
: m_isTouchscreenSimulation(false)
|
||||||
|
, m_alloc(GpAllocator_C::GetInstance())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
GpSystemServices_Win32::~GpSystemServices_Win32()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,24 +180,24 @@ void GpSystemServices_Win32::GetLocalDateTime(unsigned int &year, unsigned int &
|
|||||||
second = localTime.wSecond;
|
second = localTime.wSecond;
|
||||||
}
|
}
|
||||||
|
|
||||||
PortabilityLayer::HostMutex *GpSystemServices_Win32::CreateMutex()
|
IGpMutex *GpSystemServices_Win32::CreateMutex()
|
||||||
{
|
{
|
||||||
return GpMutex_Win32::Create();
|
return GpMutex_Win32::Create(m_alloc);
|
||||||
}
|
}
|
||||||
|
|
||||||
PortabilityLayer::HostMutex *GpSystemServices_Win32::CreateRecursiveMutex()
|
IGpMutex *GpSystemServices_Win32::CreateRecursiveMutex()
|
||||||
{
|
{
|
||||||
return GpMutex_Win32::Create();
|
return GpMutex_Win32::Create(m_alloc);
|
||||||
}
|
}
|
||||||
|
|
||||||
PortabilityLayer::HostThreadEvent *GpSystemServices_Win32::CreateThreadEvent(bool autoReset, bool startSignaled)
|
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)
|
void *GpSystemServices_Win32::CreateThread(ThreadFunc_t threadFunc, void *context)
|
||||||
{
|
{
|
||||||
PortabilityLayer::HostThreadEvent *evt = CreateThreadEvent(true, false);
|
IGpThreadEvent *evt = CreateThreadEvent(true, false);
|
||||||
if (!evt)
|
if (!evt)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
@@ -124,9 +232,10 @@ uint64_t GpSystemServices_Win32::GetFreeMemoryCosmetic() const
|
|||||||
return memStatus.ullAvailPhys;
|
return memStatus.ullAvailPhys;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GpSystemServices_Win32::Beep() const
|
bool GpSystemServices_Win32::Beep() const
|
||||||
{
|
{
|
||||||
MessageBeep(MB_OK);
|
MessageBeep(MB_OK);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GpSystemServices_Win32::IsTouchscreen() const
|
bool GpSystemServices_Win32::IsTouchscreen() const
|
||||||
@@ -144,6 +253,31 @@ bool GpSystemServices_Win32::IsTextInputObstructive() const
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool GpSystemServices_Win32::IsFullscreenPreferred() const
|
||||||
|
{
|
||||||
|
return !m_isTouchscreenSimulation;
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
unsigned int GpSystemServices_Win32::GetCPUCount() const
|
||||||
{
|
{
|
||||||
SYSTEM_INFO sysInfo;
|
SYSTEM_INFO sysInfo;
|
||||||
@@ -161,6 +295,95 @@ bool GpSystemServices_Win32::IsTextInputEnabled() const
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool GpSystemServices_Win32::AreFontResourcesSeekable() const
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
IGpClipboardContents *GpSystemServices_Win32::GetClipboardContents() const
|
||||||
|
{
|
||||||
|
IGpClipboardContents *cbObject = nullptr;
|
||||||
|
|
||||||
|
if (IsClipboardFormatAvailable(CF_UNICODETEXT))
|
||||||
|
{
|
||||||
|
if (OpenClipboard(g_gpWindowsGlobals.m_hwnd))
|
||||||
|
{
|
||||||
|
HGLOBAL textHandle = GetClipboardData(CF_UNICODETEXT);
|
||||||
|
if (textHandle)
|
||||||
|
{
|
||||||
|
const wchar_t *str = static_cast<const wchar_t*>(GlobalLock(textHandle));
|
||||||
|
if (str)
|
||||||
|
{
|
||||||
|
if (str[0] == 0)
|
||||||
|
cbObject = new GpSystemServices_Win32_Private::TextClipboard(nullptr, 0);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int bytesRequired = WideCharToMultiByte(CP_UTF8, 0, str, -1, nullptr, 0, nullptr, nullptr);
|
||||||
|
|
||||||
|
if (bytesRequired > 0)
|
||||||
|
{
|
||||||
|
std::vector<char> decodedText;
|
||||||
|
decodedText.resize(bytesRequired);
|
||||||
|
WideCharToMultiByte(CP_UTF8, 0, str, -1, &decodedText[0], bytesRequired, nullptr, nullptr);
|
||||||
|
|
||||||
|
cbObject = new GpSystemServices_Win32_Private::TextClipboard(reinterpret_cast<const uint8_t*>(&decodedText[0]), decodedText.size() - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GlobalUnlock(textHandle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CloseClipboard();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return cbObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GpSystemServices_Win32::SetClipboardContents(IGpClipboardContents *contents)
|
||||||
|
{
|
||||||
|
if (!contents)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (contents->GetContentsType() == GpClipboardContentsTypes::kText)
|
||||||
|
{
|
||||||
|
IGpClipboardContentsText *textContents = static_cast<IGpClipboardContentsText*>(contents);
|
||||||
|
|
||||||
|
if (OpenClipboard(g_gpWindowsGlobals.m_hwnd))
|
||||||
|
{
|
||||||
|
if (EmptyClipboard())
|
||||||
|
{
|
||||||
|
int wcharsRequired = MultiByteToWideChar(CP_UTF8, 0, reinterpret_cast<const char*>(textContents->GetBytes()), textContents->GetSize(), nullptr, 0);
|
||||||
|
|
||||||
|
std::vector<wchar_t> wideChars;
|
||||||
|
|
||||||
|
if (wcharsRequired)
|
||||||
|
{
|
||||||
|
wideChars.resize(wcharsRequired + 1);
|
||||||
|
MultiByteToWideChar(CP_UTF8, 0, reinterpret_cast<const char*>(textContents->GetBytes()), textContents->GetSize(), &wideChars[0], wcharsRequired);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
wideChars.resize(1);
|
||||||
|
|
||||||
|
wideChars[wideChars.size() - 1] = static_cast<wchar_t>(0);
|
||||||
|
|
||||||
|
HGLOBAL textObject = GlobalAlloc(GMEM_MOVEABLE, wideChars.size() * sizeof(wchar_t));
|
||||||
|
if (textObject)
|
||||||
|
{
|
||||||
|
wchar_t *buffer = static_cast<wchar_t*>(GlobalLock(textObject));
|
||||||
|
memcpy(buffer, &wideChars[0], wideChars.size() * sizeof(wchar_t));
|
||||||
|
GlobalUnlock(textObject);
|
||||||
|
|
||||||
|
SetClipboardData(CF_UNICODETEXT, textObject);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CloseClipboard();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void GpSystemServices_Win32::SetTouchscreenSimulation(bool isTouchscreenSimulation)
|
void GpSystemServices_Win32::SetTouchscreenSimulation(bool isTouchscreenSimulation)
|
||||||
{
|
{
|
||||||
m_isTouchscreenSimulation = isTouchscreenSimulation;
|
m_isTouchscreenSimulation = isTouchscreenSimulation;
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "HostSystemServices.h"
|
#include "IGpSystemServices.h"
|
||||||
#include "GpCoreDefs.h"
|
#include "GpCoreDefs.h"
|
||||||
#include "GpWindows.h"
|
#include "GpWindows.h"
|
||||||
|
|
||||||
@@ -15,25 +15,34 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
class GpSystemServices_Win32 final : public PortabilityLayer::HostSystemServices
|
class GpSystemServices_Win32 final : public IGpSystemServices
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
GpSystemServices_Win32();
|
GpSystemServices_Win32();
|
||||||
|
~GpSystemServices_Win32();
|
||||||
|
|
||||||
int64_t GetTime() const override;
|
int64_t GetTime() const override;
|
||||||
void GetLocalDateTime(unsigned int &year, unsigned int &month, unsigned int &day, unsigned int &hour, unsigned int &minute, unsigned int &second) const override;
|
void GetLocalDateTime(unsigned int &year, unsigned int &month, unsigned int &day, unsigned int &hour, unsigned int &minute, unsigned int &second) const override;
|
||||||
PortabilityLayer::HostMutex *CreateMutex() override;
|
IGpMutex *CreateMutex() override;
|
||||||
PortabilityLayer::HostMutex *CreateRecursiveMutex() override;
|
IGpMutex *CreateRecursiveMutex() override;
|
||||||
void *CreateThread(ThreadFunc_t threadFunc, void *context) override;
|
void *CreateThread(ThreadFunc_t threadFunc, void *context) override;
|
||||||
PortabilityLayer::HostThreadEvent *CreateThreadEvent(bool autoReset, bool startSignaled) override;
|
IGpThreadEvent *CreateThreadEvent(bool autoReset, bool startSignaled) override;
|
||||||
uint64_t GetFreeMemoryCosmetic() const override;
|
uint64_t GetFreeMemoryCosmetic() const override;
|
||||||
void Beep() const override;
|
bool Beep() const override;
|
||||||
bool IsTouchscreen() const override;
|
bool IsTouchscreen() const override;
|
||||||
bool IsUsingMouseAsTouch() const override;
|
bool IsUsingMouseAsTouch() const override;
|
||||||
bool IsTextInputObstructive() 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;
|
unsigned int GetCPUCount() const override;
|
||||||
void SetTextInputEnabled(bool isEnabled) override;
|
void SetTextInputEnabled(bool isEnabled) override;
|
||||||
bool IsTextInputEnabled() const override;
|
bool IsTextInputEnabled() const override;
|
||||||
|
bool AreFontResourcesSeekable() const override;
|
||||||
|
IGpClipboardContents *GetClipboardContents() const override;
|
||||||
|
void SetClipboardContents(IGpClipboardContents *contents) override;
|
||||||
|
|
||||||
void SetTouchscreenSimulation(bool isTouchscreenSimulation);
|
void SetTouchscreenSimulation(bool isTouchscreenSimulation);
|
||||||
|
|
||||||
@@ -42,6 +51,8 @@ public:
|
|||||||
private:
|
private:
|
||||||
bool m_isTouchscreenSimulation;
|
bool m_isTouchscreenSimulation;
|
||||||
|
|
||||||
|
IGpAllocator *m_alloc;
|
||||||
|
|
||||||
static GpSystemServices_Win32 ms_instance;
|
static GpSystemServices_Win32 ms_instance;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
#include "GpThreadEvent_Win32.h"
|
#include "GpThreadEvent_Win32.h"
|
||||||
|
#include "IGpAllocator.h"
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <new>
|
#include <new>
|
||||||
@@ -20,28 +21,30 @@ void GpThreadEvent_Win32::Signal()
|
|||||||
|
|
||||||
void GpThreadEvent_Win32::Destroy()
|
void GpThreadEvent_Win32::Destroy()
|
||||||
{
|
{
|
||||||
|
IGpAllocator *alloc = m_alloc;
|
||||||
this->~GpThreadEvent_Win32();
|
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);
|
HANDLE handle = CreateEventA(nullptr, autoReset ? FALSE : TRUE, startSignaled ? TRUE : FALSE, nullptr);
|
||||||
if (handle == nullptr)
|
if (handle == nullptr)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
void *storage = malloc(sizeof(GpThreadEvent_Win32));
|
void *storage = alloc->Alloc(sizeof(GpThreadEvent_Win32));
|
||||||
if (!storage)
|
if (!storage)
|
||||||
{
|
{
|
||||||
CloseHandle(handle);
|
CloseHandle(handle);
|
||||||
return nullptr;
|
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_event(handle)
|
||||||
|
, m_alloc(alloc)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,10 +1,10 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "HostThreadEvent.h"
|
#include "IGpThreadEvent.h"
|
||||||
|
|
||||||
#include "GpWindows.h"
|
#include "GpWindows.h"
|
||||||
|
|
||||||
class GpThreadEvent_Win32 final : public PortabilityLayer::HostThreadEvent
|
class GpThreadEvent_Win32 final : public IGpThreadEvent
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
void Wait() override;
|
void Wait() override;
|
||||||
@@ -12,11 +12,12 @@ public:
|
|||||||
void Signal() override;
|
void Signal() override;
|
||||||
void Destroy() override;
|
void Destroy() override;
|
||||||
|
|
||||||
static GpThreadEvent_Win32 *Create(bool autoReset, bool startSignaled);
|
static GpThreadEvent_Win32 *Create(IGpAllocator *alloc, bool autoReset, bool startSignaled);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
explicit GpThreadEvent_Win32(const HANDLE &handle);
|
explicit GpThreadEvent_Win32(IGpAllocator *alloc, const HANDLE &handle);
|
||||||
~GpThreadEvent_Win32();
|
~GpThreadEvent_Win32();
|
||||||
|
|
||||||
HANDLE m_event;
|
HANDLE m_event;
|
||||||
|
IGpAllocator *m_alloc;
|
||||||
};
|
};
|
||||||
|
@@ -8,15 +8,15 @@ else {
|
|||||||
}
|
}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
compileSdkVersion 29
|
compileSdkVersion 30
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
if (buildAsApplication) {
|
if (buildAsApplication) {
|
||||||
applicationId "org.thecodedeposit.aerofoil"
|
applicationId "org.thecodedeposit.aerofoil"
|
||||||
}
|
}
|
||||||
minSdkVersion 16
|
minSdkVersion 16
|
||||||
targetSdkVersion 29
|
targetSdkVersion 30
|
||||||
versionCode 3
|
versionCode 16
|
||||||
versionName "1.0.9b1"
|
versionName "1.1.2"
|
||||||
externalNativeBuild {
|
externalNativeBuild {
|
||||||
ndkBuild {
|
ndkBuild {
|
||||||
arguments "APP_PLATFORM=android-16"
|
arguments "APP_PLATFORM=android-16"
|
||||||
@@ -66,7 +66,7 @@ android {
|
|||||||
}
|
}
|
||||||
|
|
||||||
aaptOptions {
|
aaptOptions {
|
||||||
noCompress 'gpa'
|
noCompress 'gpf'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
1
AerofoilAndroid/app/jni/.gitignore
vendored
@@ -1,4 +1,5 @@
|
|||||||
AerofoilSDL
|
AerofoilSDL
|
||||||
|
AerofoilPortable
|
||||||
Common
|
Common
|
||||||
FreeType
|
FreeType
|
||||||
GpApp
|
GpApp
|
||||||
|
@@ -9,6 +9,7 @@ SDL_PATH := ../SDL
|
|||||||
LOCAL_C_INCLUDES := $(LOCAL_PATH)/$(SDL_PATH)/include \
|
LOCAL_C_INCLUDES := $(LOCAL_PATH)/$(SDL_PATH)/include \
|
||||||
$(LOCAL_PATH)/../GpShell \
|
$(LOCAL_PATH)/../GpShell \
|
||||||
$(LOCAL_PATH)/../GpCommon \
|
$(LOCAL_PATH)/../GpCommon \
|
||||||
|
$(LOCAL_PATH)/../AerofoilPortable \
|
||||||
$(LOCAL_PATH)/../AerofoilSDL \
|
$(LOCAL_PATH)/../AerofoilSDL \
|
||||||
$(LOCAL_PATH)/../Common \
|
$(LOCAL_PATH)/../Common \
|
||||||
$(LOCAL_PATH)/../PortabilityLayer
|
$(LOCAL_PATH)/../PortabilityLayer
|
||||||
@@ -23,7 +24,7 @@ LOCAL_SRC_FILES := \
|
|||||||
|
|
||||||
LOCAL_SHARED_LIBRARIES := SDL2
|
LOCAL_SHARED_LIBRARIES := SDL2
|
||||||
|
|
||||||
LOCAL_STATIC_LIBRARIES := GpShell GpFontHandler_FreeType2 AerofoilSDL GpApp
|
LOCAL_STATIC_LIBRARIES := GpShell AerofoilPortable AerofoilSDL GpApp
|
||||||
|
|
||||||
LOCAL_LDLIBS := -lGLESv1_CM -lGLESv2 -llog
|
LOCAL_LDLIBS := -lGLESv1_CM -lGLESv2 -llog
|
||||||
|
|
||||||
|
@@ -1,12 +1,14 @@
|
|||||||
#define _LARGEFILE64_SOURCE
|
#define _LARGEFILE64_SOURCE
|
||||||
#include "GpFileSystem_Android.h"
|
#include "GpFileSystem_Android.h"
|
||||||
#include "GpIOStream.h"
|
#include "GpIOStream.h"
|
||||||
#include "HostDirectoryCursor.h"
|
#include "IGpDirectoryCursor.h"
|
||||||
#include "HostSystemServices.h"
|
#include "IGpSystemServices.h"
|
||||||
#include "HostMutex.h"
|
#include "IGpMutex.h"
|
||||||
#include "IGpThreadRelay.h"
|
#include "IGpThreadRelay.h"
|
||||||
#include "VirtualDirectory.h"
|
#include "VirtualDirectory.h"
|
||||||
|
|
||||||
|
#include "PLDrivers.h"
|
||||||
|
|
||||||
#include "SDL.h"
|
#include "SDL.h"
|
||||||
#include "SDL_rwops.h"
|
#include "SDL_rwops.h"
|
||||||
|
|
||||||
@@ -40,7 +42,6 @@ public:
|
|||||||
bool SeekStart(GpUFilePos_t loc) override;
|
bool SeekStart(GpUFilePos_t loc) override;
|
||||||
bool SeekCurrent(GpFilePos_t loc) override;
|
bool SeekCurrent(GpFilePos_t loc) override;
|
||||||
bool SeekEnd(GpUFilePos_t loc) override;
|
bool SeekEnd(GpUFilePos_t loc) override;
|
||||||
bool Truncate(GpUFilePos_t loc) override;
|
|
||||||
GpUFilePos_t Size() const override;
|
GpUFilePos_t Size() const override;
|
||||||
GpUFilePos_t Tell() const override;
|
GpUFilePos_t Tell() const override;
|
||||||
void Close() override;
|
void Close() override;
|
||||||
@@ -68,7 +69,6 @@ public:
|
|||||||
bool SeekStart(GpUFilePos_t loc) override;
|
bool SeekStart(GpUFilePos_t loc) override;
|
||||||
bool SeekCurrent(GpFilePos_t loc) override;
|
bool SeekCurrent(GpFilePos_t loc) override;
|
||||||
bool SeekEnd(GpUFilePos_t loc) override;
|
bool SeekEnd(GpUFilePos_t loc) override;
|
||||||
bool Truncate(GpUFilePos_t loc) override;
|
|
||||||
GpUFilePos_t Size() const override;
|
GpUFilePos_t Size() const override;
|
||||||
GpUFilePos_t Tell() const override;
|
GpUFilePos_t Tell() const override;
|
||||||
void Close() override;
|
void Close() override;
|
||||||
@@ -94,7 +94,6 @@ public:
|
|||||||
bool SeekStart(GpUFilePos_t loc) override;
|
bool SeekStart(GpUFilePos_t loc) override;
|
||||||
bool SeekCurrent(GpFilePos_t loc) override;
|
bool SeekCurrent(GpFilePos_t loc) override;
|
||||||
bool SeekEnd(GpUFilePos_t loc) override;
|
bool SeekEnd(GpUFilePos_t loc) override;
|
||||||
bool Truncate(GpUFilePos_t loc) override;
|
|
||||||
GpUFilePos_t Size() const override;
|
GpUFilePos_t Size() const override;
|
||||||
GpUFilePos_t Tell() const override;
|
GpUFilePos_t Tell() const override;
|
||||||
void Close() override;
|
void Close() override;
|
||||||
@@ -166,11 +165,6 @@ bool GpFileStream_PFD::SeekEnd(GpUFilePos_t loc)
|
|||||||
return lseek64(m_fd, loc, SEEK_END) >= 0;
|
return lseek64(m_fd, loc, SEEK_END) >= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GpFileStream_PFD::Truncate(GpUFilePos_t loc)
|
|
||||||
{
|
|
||||||
return ftruncate64(m_fd, static_cast<off64_t>(loc)) >= 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
GpUFilePos_t GpFileStream_PFD::Size() const
|
GpUFilePos_t GpFileStream_PFD::Size() const
|
||||||
{
|
{
|
||||||
struct stat64 s;
|
struct stat64 s;
|
||||||
@@ -249,11 +243,6 @@ bool GpFileStream_SDLRWops::SeekEnd(GpUFilePos_t loc)
|
|||||||
return m_rw->seek(m_rw, -static_cast<Sint64>(loc), RW_SEEK_END) >= 0;
|
return m_rw->seek(m_rw, -static_cast<Sint64>(loc), RW_SEEK_END) >= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GpFileStream_SDLRWops::Truncate(GpUFilePos_t loc)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
GpUFilePos_t GpFileStream_SDLRWops::Size() const
|
GpUFilePos_t GpFileStream_SDLRWops::Size() const
|
||||||
{
|
{
|
||||||
return m_rw->size(m_rw);
|
return m_rw->size(m_rw);
|
||||||
@@ -344,12 +333,6 @@ bool GpFileStream_Android_File::SeekEnd(GpUFilePos_t loc)
|
|||||||
return lseek64(m_fd, -static_cast<off64_t>(loc), SEEK_END) >= 0;
|
return lseek64(m_fd, -static_cast<off64_t>(loc), SEEK_END) >= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GpFileStream_Android_File::Truncate(GpUFilePos_t loc)
|
|
||||||
{
|
|
||||||
fflush(m_f);
|
|
||||||
return ftruncate64(m_fd, static_cast<off64_t>(loc)) >= 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
GpUFilePos_t GpFileStream_Android_File::Size() const
|
GpUFilePos_t GpFileStream_Android_File::Size() const
|
||||||
{
|
{
|
||||||
fflush(m_f);
|
fflush(m_f);
|
||||||
@@ -380,7 +363,7 @@ void GpFileStream_Android_File::Flush()
|
|||||||
bool GpFileSystem_Android::OpenSourceExportFD(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *const *paths, size_t numPaths, int &fd, jobject &pfd)
|
bool GpFileSystem_Android::OpenSourceExportFD(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *const *paths, size_t numPaths, int &fd, jobject &pfd)
|
||||||
{
|
{
|
||||||
if (!m_sourceExportMutex)
|
if (!m_sourceExportMutex)
|
||||||
m_sourceExportMutex = PortabilityLayer::HostSystemServices::GetInstance()->CreateMutex();
|
m_sourceExportMutex = PLDrivers::GetSystemServices()->CreateMutex();
|
||||||
|
|
||||||
m_sourceExportWaiting = true;
|
m_sourceExportWaiting = true;
|
||||||
m_sourceExportCancelled = false;
|
m_sourceExportCancelled = false;
|
||||||
@@ -441,9 +424,6 @@ bool GpFileSystem_Android::ResolvePath(PortabilityLayer::VirtualDirectory_t virt
|
|||||||
case PortabilityLayer::VirtualDirectories::kPrefs:
|
case PortabilityLayer::VirtualDirectories::kPrefs:
|
||||||
prefsAppend = "Prefs";
|
prefsAppend = "Prefs";
|
||||||
break;
|
break;
|
||||||
case PortabilityLayer::VirtualDirectories::kFontCache:
|
|
||||||
prefsAppend = "FontCache";
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
@@ -467,7 +447,6 @@ bool GpFileSystem_Android::ResolvePath(PortabilityLayer::VirtualDirectory_t virt
|
|||||||
|
|
||||||
GpFileSystem_Android::GpFileSystem_Android()
|
GpFileSystem_Android::GpFileSystem_Android()
|
||||||
: m_activity(nullptr)
|
: m_activity(nullptr)
|
||||||
, m_relay(nullptr)
|
|
||||||
, m_delayCallback(nullptr)
|
, m_delayCallback(nullptr)
|
||||||
, m_sourceExportMutex(nullptr)
|
, m_sourceExportMutex(nullptr)
|
||||||
, m_sourceExportFD(0)
|
, m_sourceExportFD(0)
|
||||||
@@ -550,26 +529,26 @@ bool GpFileSystem_Android::FileExists(PortabilityLayer::VirtualDirectory_t virtu
|
|||||||
return stat(resolvedPath.c_str(), &s) == 0;
|
return stat(resolvedPath.c_str(), &s) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GpFileSystem_Android::FileLocked(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *path, bool *exists)
|
bool GpFileSystem_Android::FileLocked(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *path, bool &exists)
|
||||||
{
|
{
|
||||||
std::string resolvedPath;
|
std::string resolvedPath;
|
||||||
bool isAsset;
|
bool isAsset;
|
||||||
if (!ResolvePath(virtualDirectory, &path, 1, resolvedPath, isAsset))
|
if (!ResolvePath(virtualDirectory, &path, 1, resolvedPath, isAsset))
|
||||||
{
|
{
|
||||||
if (exists)
|
if (exists)
|
||||||
*exists = false;
|
exists = false;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isAsset)
|
if (isAsset)
|
||||||
{
|
{
|
||||||
if (exists)
|
if (exists)
|
||||||
*exists = this->FileExists(virtualDirectory, path);
|
exists = this->FileExists(virtualDirectory, path);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int permissions = access(resolvedPath.c_str(), W_OK | F_OK);
|
int permissions = access(resolvedPath.c_str(), W_OK | F_OK);
|
||||||
*exists = ((permissions & F_OK) != 0);
|
exists = ((permissions & F_OK) != 0);
|
||||||
return ((permissions & W_OK) != 0);
|
return ((permissions & W_OK) != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -696,26 +675,7 @@ bool GpFileSystem_Android::DeleteFile(PortabilityLayer::VirtualDirectory_t virtu
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
PortabilityLayer::HostDirectoryCursor *GpFileSystem_Android::ScanDirectoryNested(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *const *paths, size_t numPaths)
|
IGpDirectoryCursor *GpFileSystem_Android::ScanDirectoryNested(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *const *paths, size_t numPaths)
|
||||||
{
|
|
||||||
ScanDirectoryNestedContext ctx;
|
|
||||||
ctx.m_this = this;
|
|
||||||
ctx.m_returnValue = nullptr;
|
|
||||||
ctx.m_virtualDirectory = virtualDirectory;
|
|
||||||
ctx.m_paths = paths;
|
|
||||||
ctx.m_numPaths = numPaths;
|
|
||||||
m_relay->Invoke(ScanDirectoryNestedThunk, &ctx);
|
|
||||||
|
|
||||||
return ctx.m_returnValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
void GpFileSystem_Android::ScanDirectoryNestedThunk(void *context)
|
|
||||||
{
|
|
||||||
ScanDirectoryNestedContext *ctx = static_cast<ScanDirectoryNestedContext*>(context);
|
|
||||||
ctx->m_returnValue = ctx->m_this->ScanDirectoryNestedInternal(ctx->m_virtualDirectory, ctx->m_paths, ctx->m_numPaths);
|
|
||||||
}
|
|
||||||
|
|
||||||
PortabilityLayer::HostDirectoryCursor *GpFileSystem_Android::ScanDirectoryNestedInternal(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *const *paths, size_t numPaths)
|
|
||||||
{
|
{
|
||||||
if (virtualDirectory == PortabilityLayer::VirtualDirectories::kGameData || virtualDirectory == PortabilityLayer::VirtualDirectories::kApplicationData)
|
if (virtualDirectory == PortabilityLayer::VirtualDirectories::kGameData || virtualDirectory == PortabilityLayer::VirtualDirectories::kApplicationData)
|
||||||
return ScanAssetDirectory(virtualDirectory, paths, numPaths);
|
return ScanAssetDirectory(virtualDirectory, paths, numPaths);
|
||||||
@@ -731,7 +691,7 @@ bool GpFileSystem_Android::ValidateFilePath(const char *path, size_t length) con
|
|||||||
if (c >= '0' && c <= '9')
|
if (c >= '0' && c <= '9')
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (c == '_' || c == '.' || c == '\'')
|
if (c == '_' || c == '.' || c == '\'' || c == '!')
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (c == ' ' && i != 0 && i != length - 1)
|
if (c == ' ' && i != 0 && i != length - 1)
|
||||||
@@ -769,16 +729,6 @@ bool GpFileSystem_Android::ValidateFilePathUnicodeChar(uint32_t c) const
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GpFileSystem_Android::IsVirtualDirectoryLooseResources(PortabilityLayer::VirtualDirectory_t virtualDir) const
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void GpFileSystem_Android::SetMainThreadRelay(IGpThreadRelay *relay)
|
|
||||||
{
|
|
||||||
m_relay = relay;
|
|
||||||
}
|
|
||||||
|
|
||||||
void GpFileSystem_Android::SetDelayCallback(DelayCallback_t delayCallback)
|
void GpFileSystem_Android::SetDelayCallback(DelayCallback_t delayCallback)
|
||||||
{
|
{
|
||||||
m_delayCallback = delayCallback;
|
m_delayCallback = delayCallback;
|
||||||
@@ -809,7 +759,7 @@ GpFileSystem_Android *GpFileSystem_Android::GetInstance()
|
|||||||
return &ms_instance;
|
return &ms_instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
class GpDirectoryCursor_StringList final : public PortabilityLayer::HostDirectoryCursor
|
class GpDirectoryCursor_StringList final : public IGpDirectoryCursor
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit GpDirectoryCursor_StringList(std::vector<std::string> &paths);
|
explicit GpDirectoryCursor_StringList(std::vector<std::string> &paths);
|
||||||
@@ -847,7 +797,7 @@ void GpDirectoryCursor_StringList::Destroy()
|
|||||||
delete this;
|
delete this;
|
||||||
}
|
}
|
||||||
|
|
||||||
class GpDirectoryCursor_POSIX final : public PortabilityLayer::HostDirectoryCursor
|
class GpDirectoryCursor_POSIX final : public IGpDirectoryCursor
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit GpDirectoryCursor_POSIX(DIR *dir);
|
explicit GpDirectoryCursor_POSIX(DIR *dir);
|
||||||
@@ -885,7 +835,7 @@ void GpDirectoryCursor_POSIX::Destroy()
|
|||||||
delete this;
|
delete this;
|
||||||
}
|
}
|
||||||
|
|
||||||
PortabilityLayer::HostDirectoryCursor *GpFileSystem_Android::ScanAssetDirectory(PortabilityLayer::VirtualDirectory_t virtualDirectory, char const* const* paths, size_t numPaths)
|
IGpDirectoryCursor *GpFileSystem_Android::ScanAssetDirectory(PortabilityLayer::VirtualDirectory_t virtualDirectory, char const* const* paths, size_t numPaths)
|
||||||
{
|
{
|
||||||
|
|
||||||
std::string resolvedPath;
|
std::string resolvedPath;
|
||||||
@@ -919,7 +869,7 @@ PortabilityLayer::HostDirectoryCursor *GpFileSystem_Android::ScanAssetDirectory(
|
|||||||
return new GpDirectoryCursor_StringList(subPaths);
|
return new GpDirectoryCursor_StringList(subPaths);
|
||||||
}
|
}
|
||||||
|
|
||||||
PortabilityLayer::HostDirectoryCursor *GpFileSystem_Android::ScanStorageDirectory(PortabilityLayer::VirtualDirectory_t virtualDirectory, char const* const* paths, size_t numPaths)
|
IGpDirectoryCursor *GpFileSystem_Android::ScanStorageDirectory(PortabilityLayer::VirtualDirectory_t virtualDirectory, char const* const* paths, size_t numPaths)
|
||||||
{
|
{
|
||||||
std::string resolvedPath;
|
std::string resolvedPath;
|
||||||
std::vector<std::string> subPaths;
|
std::vector<std::string> subPaths;
|
||||||
|
@@ -1,18 +1,15 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "HostFileSystem.h"
|
#include "IGpFileSystem.h"
|
||||||
|
|
||||||
#include "GpCoreDefs.h"
|
#include "GpCoreDefs.h"
|
||||||
|
|
||||||
#include <jni.h>
|
#include <jni.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
namespace PortabilityLayer
|
struct IGpMutex;
|
||||||
{
|
|
||||||
class HostMutex;
|
|
||||||
}
|
|
||||||
|
|
||||||
class GpFileSystem_Android final : public PortabilityLayer::HostFileSystem
|
class GpFileSystem_Android final : public IGpFileSystem
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
GpFileSystem_Android();
|
GpFileSystem_Android();
|
||||||
@@ -22,17 +19,14 @@ public:
|
|||||||
void ShutdownJNI();
|
void ShutdownJNI();
|
||||||
|
|
||||||
bool FileExists(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *path) override;
|
bool FileExists(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *path) override;
|
||||||
bool FileLocked(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *path, bool *exists) 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;
|
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) override;
|
||||||
PortabilityLayer::HostDirectoryCursor *ScanDirectoryNested(PortabilityLayer::VirtualDirectory_t virtualDirectory, char const* const* paths, size_t numPaths) 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;
|
bool ValidateFilePath(const char *path, size_t pathLen) const override;
|
||||||
bool ValidateFilePathUnicodeChar(uint32_t ch) const override;
|
bool ValidateFilePathUnicodeChar(uint32_t ch) const override;
|
||||||
|
|
||||||
bool IsVirtualDirectoryLooseResources(PortabilityLayer::VirtualDirectory_t virtualDir) const override;
|
|
||||||
|
|
||||||
void SetMainThreadRelay(IGpThreadRelay *relay) override;
|
|
||||||
void SetDelayCallback(DelayCallback_t delayCallback) override;
|
void SetDelayCallback(DelayCallback_t delayCallback) override;
|
||||||
|
|
||||||
void PostSourceExportRequest(bool cancelled, int fd, jobject pfd);
|
void PostSourceExportRequest(bool cancelled, int fd, jobject pfd);
|
||||||
@@ -41,26 +35,12 @@ public:
|
|||||||
static GpFileSystem_Android *GetInstance();
|
static GpFileSystem_Android *GetInstance();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct ScanDirectoryNestedContext
|
IGpDirectoryCursor *ScanAssetDirectory(PortabilityLayer::VirtualDirectory_t virtualDirectory, char const* const* paths, size_t numPaths);
|
||||||
{
|
IGpDirectoryCursor *ScanStorageDirectory(PortabilityLayer::VirtualDirectory_t virtualDirectory, char const* const* paths, size_t numPaths);
|
||||||
GpFileSystem_Android *m_this;
|
|
||||||
|
|
||||||
PortabilityLayer::HostDirectoryCursor *m_returnValue;
|
|
||||||
PortabilityLayer::VirtualDirectory_t m_virtualDirectory;
|
|
||||||
char const *const *m_paths;
|
|
||||||
size_t m_numPaths;
|
|
||||||
};
|
|
||||||
|
|
||||||
static void ScanDirectoryNestedThunk(void *context);
|
|
||||||
PortabilityLayer::HostDirectoryCursor *ScanDirectoryNestedInternal(PortabilityLayer::VirtualDirectory_t virtualDirectory, char const* const* paths, size_t numPaths);
|
|
||||||
|
|
||||||
PortabilityLayer::HostDirectoryCursor *ScanAssetDirectory(PortabilityLayer::VirtualDirectory_t virtualDirectory, char const* const* paths, size_t numPaths);
|
|
||||||
PortabilityLayer::HostDirectoryCursor *ScanStorageDirectory(PortabilityLayer::VirtualDirectory_t virtualDirectory, char const* const* paths, size_t numPaths);
|
|
||||||
|
|
||||||
bool OpenSourceExportFD(PortabilityLayer::VirtualDirectory_t virtualDirectory, char const* const* paths, size_t numPaths, int &fd, jobject &pfd);
|
bool OpenSourceExportFD(PortabilityLayer::VirtualDirectory_t virtualDirectory, char const* const* paths, size_t numPaths, int &fd, jobject &pfd);
|
||||||
bool ResolvePath(PortabilityLayer::VirtualDirectory_t virtualDirectory, char const* const* paths, size_t numPaths, std::string &resolution, bool &isAsset);
|
bool ResolvePath(PortabilityLayer::VirtualDirectory_t virtualDirectory, char const* const* paths, size_t numPaths, std::string &resolution, bool &isAsset);
|
||||||
|
|
||||||
IGpThreadRelay *m_relay;
|
|
||||||
DelayCallback_t m_delayCallback;
|
DelayCallback_t m_delayCallback;
|
||||||
|
|
||||||
jobject m_activity;
|
jobject m_activity;
|
||||||
@@ -68,7 +48,7 @@ private:
|
|||||||
jmethodID m_selectSourceExportPathMID;
|
jmethodID m_selectSourceExportPathMID;
|
||||||
jmethodID m_closeSourceExportPFDMID;
|
jmethodID m_closeSourceExportPFDMID;
|
||||||
|
|
||||||
PortabilityLayer::HostMutex *m_sourceExportMutex;
|
IGpMutex *m_sourceExportMutex;
|
||||||
int m_sourceExportFD;
|
int m_sourceExportFD;
|
||||||
bool m_sourceExportWaiting;
|
bool m_sourceExportWaiting;
|
||||||
bool m_sourceExportCancelled;
|
bool m_sourceExportCancelled;
|
||||||
|
@@ -1,21 +1,22 @@
|
|||||||
#include "SDL.h"
|
#include "SDL.h"
|
||||||
|
|
||||||
#include "GpMain.h"
|
#include "GpMain.h"
|
||||||
|
#include "GpAllocator_C.h"
|
||||||
#include "GpAudioDriverFactory.h"
|
#include "GpAudioDriverFactory.h"
|
||||||
#include "GpDisplayDriverFactory.h"
|
#include "GpDisplayDriverFactory.h"
|
||||||
#include "GpGlobalConfig.h"
|
#include "GpGlobalConfig.h"
|
||||||
#include "GpFiber_SDL.h"
|
|
||||||
#include "GpFileSystem_Android.h"
|
#include "GpFileSystem_Android.h"
|
||||||
#include "GpFontHandlerFactory.h"
|
#include "GpFontHandlerFactory.h"
|
||||||
#include "GpInputDriverFactory.h"
|
#include "GpInputDriverFactory.h"
|
||||||
|
#include "GpInputDriver_SDL_Gamepad.h"
|
||||||
#include "GpAppInterface.h"
|
#include "GpAppInterface.h"
|
||||||
#include "GpSystemServices_Android.h"
|
#include "GpSystemServices_Android.h"
|
||||||
#include "GpVOSEvent.h"
|
#include "GpVOSEvent.h"
|
||||||
#include "IGpVOSEventQueue.h"
|
#include "IGpVOSEventQueue.h"
|
||||||
#include "IGpLogDriver.h"
|
#include "IGpLogDriver.h"
|
||||||
|
|
||||||
#include "HostFileSystem.h"
|
#include "IGpFileSystem.h"
|
||||||
#include "HostThreadEvent.h"
|
#include "IGpThreadEvent.h"
|
||||||
|
|
||||||
#include "GpAndroid.h"
|
#include "GpAndroid.h"
|
||||||
|
|
||||||
@@ -23,10 +24,9 @@
|
|||||||
|
|
||||||
GpAndroidGlobals g_gpAndroidGlobals;
|
GpAndroidGlobals g_gpAndroidGlobals;
|
||||||
|
|
||||||
extern "C" IGpFontHandler *GpDriver_CreateFontHandler_FreeType2(const GpFontHandlerProperties &properties);
|
|
||||||
|
|
||||||
IGpDisplayDriver *GpDriver_CreateDisplayDriver_SDL_GL2(const GpDisplayDriverProperties &properties);
|
IGpDisplayDriver *GpDriver_CreateDisplayDriver_SDL_GL2(const GpDisplayDriverProperties &properties);
|
||||||
IGpAudioDriver *GpDriver_CreateAudioDriver_SDL(const GpAudioDriverProperties &properties);
|
IGpAudioDriver *GpDriver_CreateAudioDriver_SDL(const GpAudioDriverProperties &properties);
|
||||||
|
IGpInputDriver *GpDriver_CreateInputDriver_SDL2_Gamepad(const GpInputDriverProperties &properties);
|
||||||
|
|
||||||
class GpLogDriver_Android final : public IGpLogDriver
|
class GpLogDriver_Android final : public IGpLogDriver
|
||||||
{
|
{
|
||||||
@@ -72,35 +72,45 @@ GpLogDriver_Android GpLogDriver_Android::ms_instance;
|
|||||||
|
|
||||||
int main(int argc, char* argv[])
|
int main(int argc, char* argv[])
|
||||||
{
|
{
|
||||||
|
IGpAllocator *alloc = GpAllocator_C::GetInstance();
|
||||||
|
|
||||||
SDL_LogSetAllPriority(SDL_LOG_PRIORITY_INFO);
|
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;
|
return -1;
|
||||||
|
|
||||||
SDL_SetHint(SDL_HINT_ORIENTATIONS, "LandscapeLeft LandscapeRight");
|
SDL_SetHint(SDL_HINT_ORIENTATIONS, "LandscapeLeft LandscapeRight");
|
||||||
|
|
||||||
GpFileSystem_Android::GetInstance()->InitJNI();
|
GpFileSystem_Android::GetInstance()->InitJNI();
|
||||||
|
|
||||||
GpAppInterface_Get()->PL_HostFileSystem_SetInstance(GpFileSystem_Android::GetInstance());
|
GpDriverCollection *drivers = GpAppInterface_Get()->PL_GetDriverCollection();
|
||||||
GpAppInterface_Get()->PL_HostSystemServices_SetInstance(GpSystemServices_Android::GetInstance());
|
drivers->SetDriver<GpDriverIDs::kFileSystem>(GpFileSystem_Android::GetInstance());
|
||||||
GpAppInterface_Get()->PL_HostLogDriver_SetInstance(GpLogDriver_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;
|
g_gpGlobalConfig.m_displayDriverType = EGpDisplayDriverType_SDL_GL2;
|
||||||
|
|
||||||
g_gpGlobalConfig.m_audioDriverType = EGpAudioDriverType_SDL2;
|
g_gpGlobalConfig.m_audioDriverType = EGpAudioDriverType_SDL2;
|
||||||
|
|
||||||
g_gpGlobalConfig.m_fontHandlerType = EGpFontHandlerType_FreeType2;
|
g_gpGlobalConfig.m_fontHandlerType = EGpFontHandlerType_None;
|
||||||
|
|
||||||
g_gpGlobalConfig.m_inputDriverTypes = nullptr;
|
EGpInputDriverType inputDrivers[] =
|
||||||
g_gpGlobalConfig.m_numInputDrivers = 0;
|
{
|
||||||
|
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_osGlobals = &g_gpAndroidGlobals;
|
||||||
g_gpGlobalConfig.m_logger = GpLogDriver_Android::GetInstance();
|
g_gpGlobalConfig.m_logger = GpLogDriver_Android::GetInstance();
|
||||||
g_gpGlobalConfig.m_systemServices = GpSystemServices_Android::GetInstance();
|
g_gpGlobalConfig.m_systemServices = GpSystemServices_Android::GetInstance();
|
||||||
|
g_gpGlobalConfig.m_allocator = alloc;
|
||||||
|
|
||||||
GpDisplayDriverFactory::RegisterDisplayDriverFactory(EGpDisplayDriverType_SDL_GL2, GpDriver_CreateDisplayDriver_SDL_GL2);
|
GpDisplayDriverFactory::RegisterDisplayDriverFactory(EGpDisplayDriverType_SDL_GL2, GpDriver_CreateDisplayDriver_SDL_GL2);
|
||||||
GpAudioDriverFactory::RegisterAudioDriverFactory(EGpAudioDriverType_SDL2, GpDriver_CreateAudioDriver_SDL);
|
GpAudioDriverFactory::RegisterAudioDriverFactory(EGpAudioDriverType_SDL2, GpDriver_CreateAudioDriver_SDL);
|
||||||
GpFontHandlerFactory::RegisterFontHandlerFactory(EGpFontHandlerType_FreeType2, GpDriver_CreateFontHandler_FreeType2);
|
GpInputDriverFactory::RegisterInputDriverFactory(EGpInputDriverType_SDL2_Gamepad, GpDriver_CreateInputDriver_SDL2_Gamepad);
|
||||||
|
|
||||||
int returnCode = GpMain::Run();
|
int returnCode = GpMain::Run();
|
||||||
|
|
||||||
|
@@ -1,18 +1,16 @@
|
|||||||
#include "GpSystemServices_Android.h"
|
#include "GpSystemServices_Android.h"
|
||||||
#include "HostMutex.h"
|
|
||||||
#include "HostThreadEvent.h"
|
#include "IGpThreadEvent.h"
|
||||||
#include "SDL.h"
|
#include "SDL.h"
|
||||||
|
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <mutex>
|
|
||||||
#include <condition_variable>
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
struct GpSystemServices_Android_ThreadStartParams
|
struct GpSystemServices_Android_ThreadStartParams
|
||||||
{
|
{
|
||||||
GpSystemServices_Android::ThreadFunc_t m_threadFunc;
|
GpSystemServices_Android::ThreadFunc_t m_threadFunc;
|
||||||
void *m_threadContext;
|
void *m_threadContext;
|
||||||
PortabilityLayer::HostThreadEvent *m_threadStartEvent;
|
IGpThreadEvent *m_threadStartEvent;
|
||||||
};
|
};
|
||||||
|
|
||||||
static int SDLCALL StaticStartThread(void *lpThreadParameter)
|
static int SDLCALL StaticStartThread(void *lpThreadParameter)
|
||||||
@@ -21,185 +19,21 @@ static int SDLCALL StaticStartThread(void *lpThreadParameter)
|
|||||||
|
|
||||||
GpSystemServices_Android::ThreadFunc_t threadFunc = threadParams->m_threadFunc;
|
GpSystemServices_Android::ThreadFunc_t threadFunc = threadParams->m_threadFunc;
|
||||||
void *threadContext = threadParams->m_threadContext;
|
void *threadContext = threadParams->m_threadContext;
|
||||||
PortabilityLayer::HostThreadEvent *threadStartEvent = threadParams->m_threadStartEvent;
|
IGpThreadEvent *threadStartEvent = threadParams->m_threadStartEvent;
|
||||||
|
|
||||||
threadStartEvent->Signal();
|
threadStartEvent->Signal();
|
||||||
|
|
||||||
return threadFunc(threadContext);
|
return threadFunc(threadContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class TMutex>
|
|
||||||
class GpMutex_Cpp11 final : public PortabilityLayer::HostMutex
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
GpMutex_Cpp11();
|
|
||||||
~GpMutex_Cpp11();
|
|
||||||
|
|
||||||
void Destroy() override;
|
|
||||||
|
|
||||||
void Lock() override;
|
|
||||||
void Unlock() override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
TMutex m_mutex;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<class TMutex>
|
|
||||||
GpMutex_Cpp11<TMutex>::GpMutex_Cpp11()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class TMutex>
|
|
||||||
GpMutex_Cpp11<TMutex>::~GpMutex_Cpp11()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class TMutex>
|
|
||||||
void GpMutex_Cpp11<TMutex>::Destroy()
|
|
||||||
{
|
|
||||||
this->~GpMutex_Cpp11();
|
|
||||||
free(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class TMutex>
|
|
||||||
void GpMutex_Cpp11<TMutex>::Lock()
|
|
||||||
{
|
|
||||||
m_mutex.lock();
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class TMutex>
|
|
||||||
void GpMutex_Cpp11<TMutex>::Unlock()
|
|
||||||
{
|
|
||||||
m_mutex.unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef GpMutex_Cpp11<std::mutex> GpMutex_Cpp11_Vanilla;
|
|
||||||
typedef GpMutex_Cpp11<std::recursive_mutex> GpMutex_Cpp11_Recursive;
|
|
||||||
|
|
||||||
|
|
||||||
class GpThreadEvent_Cpp11 final : public PortabilityLayer::HostThreadEvent
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
GpThreadEvent_Cpp11(bool autoReset, bool startSignaled);
|
|
||||||
~GpThreadEvent_Cpp11();
|
|
||||||
|
|
||||||
void Wait() override;
|
|
||||||
bool WaitTimed(uint32_t msec) override;
|
|
||||||
void Signal() override;
|
|
||||||
void Destroy() override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::mutex m_mutex;
|
|
||||||
std::condition_variable m_cvar;
|
|
||||||
bool m_flag;
|
|
||||||
bool m_autoReset;
|
|
||||||
};
|
|
||||||
|
|
||||||
GpThreadEvent_Cpp11::GpThreadEvent_Cpp11(bool autoReset, bool startSignaled)
|
|
||||||
: m_flag(startSignaled)
|
|
||||||
, m_autoReset(autoReset)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
GpThreadEvent_Cpp11::~GpThreadEvent_Cpp11()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void GpThreadEvent_Cpp11::Wait()
|
|
||||||
{
|
|
||||||
std::unique_lock<std::mutex> lock(m_mutex);
|
|
||||||
if (m_autoReset)
|
|
||||||
{
|
|
||||||
m_cvar.wait(lock,[&]()->bool{
|
|
||||||
if (m_flag)
|
|
||||||
{
|
|
||||||
m_flag = false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else
|
|
||||||
m_cvar.wait(lock,[&]()->bool{ return m_flag; });
|
|
||||||
}
|
|
||||||
|
|
||||||
bool GpThreadEvent_Cpp11::WaitTimed(uint32_t msec)
|
|
||||||
{
|
|
||||||
std::unique_lock<std::mutex> lock(m_mutex);
|
|
||||||
if (m_autoReset)
|
|
||||||
{
|
|
||||||
if (!m_cvar.wait_for(lock, std::chrono::milliseconds(msec), [&]()->bool{
|
|
||||||
if (m_flag)
|
|
||||||
{
|
|
||||||
m_flag = false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
}))
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (!m_cvar.wait_for(lock, std::chrono::milliseconds(msec), [&]()->bool{ return m_flag; }))
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void GpThreadEvent_Cpp11::Signal()
|
|
||||||
{
|
|
||||||
m_mutex.lock();
|
|
||||||
m_flag = true;
|
|
||||||
m_mutex.unlock();
|
|
||||||
if (m_autoReset)
|
|
||||||
m_cvar.notify_one();
|
|
||||||
else
|
|
||||||
m_cvar.notify_all();
|
|
||||||
}
|
|
||||||
|
|
||||||
void GpThreadEvent_Cpp11::Destroy()
|
|
||||||
{
|
|
||||||
this->~GpThreadEvent_Cpp11();
|
|
||||||
free(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
GpSystemServices_Android::GpSystemServices_Android()
|
GpSystemServices_Android::GpSystemServices_Android()
|
||||||
: m_textInputEnabled(false)
|
: m_textInputEnabled(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t GpSystemServices_Android::GetTime() const
|
|
||||||
{
|
|
||||||
time_t t = time(nullptr);
|
|
||||||
return static_cast<int64_t>(t) - 2082844800;
|
|
||||||
}
|
|
||||||
|
|
||||||
void GpSystemServices_Android::GetLocalDateTime(unsigned int &year, unsigned int &month, unsigned int &day, unsigned int &hour, unsigned int &minute, unsigned int &second) const
|
|
||||||
{
|
|
||||||
time_t t = time(nullptr);
|
|
||||||
tm *tmObject = localtime(&t);
|
|
||||||
year = static_cast<unsigned int>(tmObject->tm_year);
|
|
||||||
month = static_cast<unsigned int>(tmObject->tm_mon + 1);
|
|
||||||
hour = static_cast<unsigned int>(tmObject->tm_hour);
|
|
||||||
minute = static_cast<unsigned int>(tmObject->tm_min);
|
|
||||||
second = static_cast<unsigned int>(tmObject->tm_sec);
|
|
||||||
}
|
|
||||||
|
|
||||||
PortabilityLayer::HostMutex *GpSystemServices_Android::CreateMutex()
|
|
||||||
{
|
|
||||||
GpMutex_Cpp11_Vanilla *mutex = static_cast<GpMutex_Cpp11_Vanilla*>(malloc(sizeof(GpMutex_Cpp11_Vanilla)));
|
|
||||||
if (!mutex)
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
return new (mutex) GpMutex_Cpp11_Vanilla();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void *GpSystemServices_Android::CreateThread(ThreadFunc_t threadFunc, void *context)
|
void *GpSystemServices_Android::CreateThread(ThreadFunc_t threadFunc, void *context)
|
||||||
{
|
{
|
||||||
PortabilityLayer::HostThreadEvent *evt = CreateThreadEvent(true, false);
|
IGpThreadEvent *evt = CreateThreadEvent(true, false);
|
||||||
if (!evt)
|
if (!evt)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
@@ -221,33 +55,9 @@ void *GpSystemServices_Android::CreateThread(ThreadFunc_t threadFunc, void *cont
|
|||||||
return thread;
|
return thread;
|
||||||
}
|
}
|
||||||
|
|
||||||
PortabilityLayer::HostMutex *GpSystemServices_Android::CreateRecursiveMutex()
|
bool GpSystemServices_Android::Beep() const
|
||||||
{
|
|
||||||
GpMutex_Cpp11_Recursive *mutex = static_cast<GpMutex_Cpp11_Recursive*>(malloc(sizeof(GpMutex_Cpp11_Recursive)));
|
|
||||||
if (!mutex)
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
return new (mutex) GpMutex_Cpp11_Recursive();
|
|
||||||
}
|
|
||||||
|
|
||||||
PortabilityLayer::HostThreadEvent *GpSystemServices_Android::CreateThreadEvent(bool autoReset, bool startSignaled)
|
|
||||||
{
|
|
||||||
GpThreadEvent_Cpp11 *evt = static_cast<GpThreadEvent_Cpp11*>(malloc(sizeof(GpThreadEvent_Cpp11)));
|
|
||||||
if (!evt)
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
return new (evt) GpThreadEvent_Cpp11(autoReset, startSignaled);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t GpSystemServices_Android::GetFreeMemoryCosmetic() const
|
|
||||||
{
|
|
||||||
long pages = sysconf(_SC_AVPHYS_PAGES);
|
|
||||||
long pageSize = sysconf(_SC_PAGE_SIZE);
|
|
||||||
return pages * pageSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
void GpSystemServices_Android::Beep() const
|
|
||||||
{
|
{
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GpSystemServices_Android::IsTouchscreen() const
|
bool GpSystemServices_Android::IsTouchscreen() const
|
||||||
@@ -265,6 +75,31 @@ bool GpSystemServices_Android::IsTextInputObstructive() const
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool GpSystemServices_Android::IsFullscreenPreferred() const
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
unsigned int GpSystemServices_Android::GetCPUCount() const
|
||||||
{
|
{
|
||||||
return SDL_GetCPUCount();
|
return SDL_GetCPUCount();
|
||||||
@@ -280,6 +115,20 @@ bool GpSystemServices_Android::IsTextInputEnabled() const
|
|||||||
return m_textInputEnabled;
|
return m_textInputEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool GpSystemServices_Android::AreFontResourcesSeekable() const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
IGpClipboardContents *GpSystemServices_Android::GetClipboardContents() const
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GpSystemServices_Android::SetClipboardContents(IGpClipboardContents *contents)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
GpSystemServices_Android *GpSystemServices_Android::GetInstance()
|
GpSystemServices_Android *GpSystemServices_Android::GetInstance()
|
||||||
{
|
{
|
||||||
return &ms_instance;
|
return &ms_instance;
|
||||||
|
@@ -1,27 +1,29 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "HostSystemServices.h"
|
#include "GpSystemServices_POSIX.h"
|
||||||
#include "GpCoreDefs.h"
|
#include "GpCoreDefs.h"
|
||||||
|
|
||||||
class GpSystemServices_Android final : public PortabilityLayer::HostSystemServices
|
class GpSystemServices_Android final : public GpSystemServices_POSIX
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
GpSystemServices_Android();
|
GpSystemServices_Android();
|
||||||
|
|
||||||
int64_t GetTime() const override;
|
|
||||||
void GetLocalDateTime(unsigned int &year, unsigned int &month, unsigned int &day, unsigned int &hour, unsigned int &minute, unsigned int &second) const override;
|
|
||||||
PortabilityLayer::HostMutex *CreateMutex() override;
|
|
||||||
PortabilityLayer::HostMutex *CreateRecursiveMutex() override;
|
|
||||||
void *CreateThread(ThreadFunc_t threadFunc, void *context) override;
|
void *CreateThread(ThreadFunc_t threadFunc, void *context) override;
|
||||||
PortabilityLayer::HostThreadEvent *CreateThreadEvent(bool autoReset, bool startSignaled) override;
|
bool Beep() const override;
|
||||||
uint64_t GetFreeMemoryCosmetic() const override;
|
|
||||||
void Beep() const override;
|
|
||||||
bool IsTouchscreen() const override;
|
bool IsTouchscreen() const override;
|
||||||
bool IsUsingMouseAsTouch() const override;
|
bool IsUsingMouseAsTouch() const override;
|
||||||
bool IsTextInputObstructive() 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;
|
unsigned int GetCPUCount() const override;
|
||||||
void SetTextInputEnabled(bool isEnabled) override;
|
void SetTextInputEnabled(bool isEnabled) override;
|
||||||
bool IsTextInputEnabled() const override;
|
bool IsTextInputEnabled() const override;
|
||||||
|
bool AreFontResourcesSeekable() const override;
|
||||||
|
IGpClipboardContents *GetClipboardContents() const override;
|
||||||
|
void SetClipboardContents(IGpClipboardContents *contents) override;
|
||||||
|
|
||||||
void FlushTextInputEnabled();
|
void FlushTextInputEnabled();
|
||||||
|
|
||||||
|
@@ -41,9 +41,13 @@
|
|||||||
<!-- Allow writing to external storage -->
|
<!-- Allow writing to external storage -->
|
||||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||||
<!-- Allow access to Bluetooth devices -->
|
<!-- Allow access to Bluetooth devices -->
|
||||||
|
<!--
|
||||||
<uses-permission android:name="android.permission.BLUETOOTH" />
|
<uses-permission android:name="android.permission.BLUETOOTH" />
|
||||||
|
-->
|
||||||
<!-- Allow access to the vibrator -->
|
<!-- Allow access to the vibrator -->
|
||||||
|
<!--
|
||||||
<uses-permission android:name="android.permission.VIBRATE" />
|
<uses-permission android:name="android.permission.VIBRATE" />
|
||||||
|
-->
|
||||||
|
|
||||||
<!-- if you want to capture audio, uncomment this. -->
|
<!-- if you want to capture audio, uncomment this. -->
|
||||||
<!-- <uses-permission android:name="android.permission.RECORD_AUDIO" /> -->
|
<!-- <uses-permission android:name="android.permission.RECORD_AUDIO" /> -->
|
||||||
|
@@ -6,7 +6,7 @@ buildscript {
|
|||||||
google()
|
google()
|
||||||
}
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath 'com.android.tools.build:gradle:4.1.0'
|
classpath 'com.android.tools.build:gradle:4.1.1'
|
||||||
|
|
||||||
// NOTE: Do not place your application dependencies here; they belong
|
// NOTE: Do not place your application dependencies here; they belong
|
||||||
// in the individual module build.gradle files
|
// in the individual module build.gradle files
|
||||||
|
@@ -7,6 +7,6 @@ mkdir Packaged
|
|||||||
cd Packaged
|
cd Packaged
|
||||||
rmdir /S /Q Houses
|
rmdir /S /Q Houses
|
||||||
mkdir Houses
|
mkdir Houses
|
||||||
copy ..\..\..\..\..\..\Packaged\*.gpa .\
|
copy ..\..\..\..\..\..\Packaged\*.gpf .\
|
||||||
copy ..\..\..\..\..\..\Packaged\Houses\* Houses\
|
copy ..\..\..\..\..\..\Packaged\Houses\* Houses\
|
||||||
cd ..
|
cd ..
|
||||||
|
@@ -6,3 +6,4 @@ git archive -0 --format zip -o AerofoilAndroid\app\src\main\assets\Packaged\Sour
|
|||||||
tools\7z.exe d AerofoilAndroid\app\src\main\assets\Packaged\SourceCode.zip GliderProData\
|
tools\7z.exe d AerofoilAndroid\app\src\main\assets\Packaged\SourceCode.zip GliderProData\
|
||||||
cd AerofoilAndroid\app\src\main\assets\Packaged
|
cd AerofoilAndroid\app\src\main\assets\Packaged
|
||||||
rename SourceCode.zip SourceCode.pkg
|
rename SourceCode.zip SourceCode.pkg
|
||||||
|
pause
|
||||||
|
@@ -5,17 +5,15 @@ call remove_symlinks.bat
|
|||||||
|
|
||||||
|
|
||||||
mklink /D app\jni\AerofoilSDL ..\..\..\AerofoilSDL
|
mklink /D app\jni\AerofoilSDL ..\..\..\AerofoilSDL
|
||||||
|
mklink /D app\jni\AerofoilPortable ..\..\..\AerofoilPortable
|
||||||
mklink /D app\jni\Common ..\..\..\Common
|
mklink /D app\jni\Common ..\..\..\Common
|
||||||
mklink /D app\jni\SDL2 ..\..\..\SDL2-2.0.12
|
mklink /D app\jni\SDL2 ..\..\..\SDL2-2.0.12
|
||||||
mklink /D app\jni\GpApp ..\..\..\GpApp
|
mklink /D app\jni\GpApp ..\..\..\GpApp
|
||||||
mklink /D app\jni\GpShell ..\..\..\GpShell
|
mklink /D app\jni\GpShell ..\..\..\GpShell
|
||||||
mklink /D app\jni\GpCommon ..\..\..\GpCommon
|
mklink /D app\jni\GpCommon ..\..\..\GpCommon
|
||||||
mklink /D app\jni\GpFontHandler_FreeType2 ..\..\..\GpFontHandler_FreeType2
|
|
||||||
mklink /D app\jni\PortabilityLayer ..\..\..\PortabilityLayer
|
mklink /D app\jni\PortabilityLayer ..\..\..\PortabilityLayer
|
||||||
mklink /D app\jni\FreeType ..\..\..\FreeType
|
|
||||||
mklink /D app\jni\rapidjson ..\..\..\rapidjson
|
mklink /D app\jni\rapidjson ..\..\..\rapidjson
|
||||||
mklink /D app\jni\MacRomanConversion ..\..\..\MacRomanConversion
|
mklink /D app\jni\MacRomanConversion ..\..\..\MacRomanConversion
|
||||||
mklink /D app\jni\stb ..\..\..\stb
|
mklink /D app\jni\stb ..\..\..\stb
|
||||||
mklink /D app\src\main\assets\Resources ..\..\..\..\..\Resources
|
|
||||||
|
|
||||||
pause
|
pause
|
||||||
|
@@ -2,16 +2,13 @@
|
|||||||
@cd /d "%~dp0"
|
@cd /d "%~dp0"
|
||||||
|
|
||||||
rmdir app\jni\AerofoilSDL
|
rmdir app\jni\AerofoilSDL
|
||||||
|
rmdir app\jni\AerofoilPortable
|
||||||
rmdir app\jni\Common
|
rmdir app\jni\Common
|
||||||
rmdir app\jni\SDL2
|
rmdir app\jni\SDL2
|
||||||
rmdir app\jni\GpShell
|
rmdir app\jni\GpShell
|
||||||
rmdir app\jni\GpCommon
|
rmdir app\jni\GpCommon
|
||||||
rmdir app\jni\GpApp
|
rmdir app\jni\GpApp
|
||||||
rmdir app\jni\GpFontHandler_FreeType2
|
|
||||||
rmdir app\jni\PortabilityLayer
|
rmdir app\jni\PortabilityLayer
|
||||||
rmdir app\jni\FreeType
|
|
||||||
rmdir app\jni\zlib
|
|
||||||
rmdir app\jni\rapidjson
|
rmdir app\jni\rapidjson
|
||||||
rmdir app\jni\MacRomanConversion
|
rmdir app\jni\MacRomanConversion
|
||||||
rmdir app\jni\stb
|
rmdir app\jni\stb
|
||||||
rmdir app\src\main\assets\Resources
|
|
||||||
|
2497
AerofoilMac/AerofoilMac.xcodeproj/project.pbxproj
Normal file
7
AerofoilMac/AerofoilMac.xcodeproj/project.xcworkspace/contents.xcworkspacedata
generated
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Workspace
|
||||||
|
version = "1.0">
|
||||||
|
<FileRef
|
||||||
|
location = "self:">
|
||||||
|
</FileRef>
|
||||||
|
</Workspace>
|
@@ -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>
|
@@ -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>
|
9
AerofoilMac/AerofoilMac/AerofoilAppDelegate.h
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
#import <Cocoa/Cocoa.h>
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
@interface AerofoilAppDelegate : NSObject <NSApplicationDelegate>
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
43
AerofoilMac/AerofoilMac/AerofoilAppDelegate.mm
Normal 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
|
12
AerofoilMac/AerofoilMac/AerofoilApplication.h
Normal 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
|
28
AerofoilMac/AerofoilMac/AerofoilApplication.mm
Normal 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
|
12
AerofoilMac/AerofoilMac/AerofoilMac.entitlements
Normal 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>
|
@@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"colors" : [
|
||||||
|
{
|
||||||
|
"idiom" : "universal"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
After Width: | Height: | Size: 1.2 MiB |
After Width: | Height: | Size: 29 KiB |
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 98 KiB |
After Width: | Height: | Size: 3.5 KiB |
After Width: | Height: | Size: 343 KiB |
After Width: | Height: | Size: 9.3 KiB |
@@ -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"}]}
|
6
AerofoilMac/AerofoilMac/Assets.xcassets/Contents.json
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
126
AerofoilMac/AerofoilMac/Base.lproj/MainMenu.xib
Normal 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>
|
32
AerofoilMac/AerofoilMac/Info.plist
Normal 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>
|
3
AerofoilMac/AerofoilMac/MacInit.h
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
int MacInit(void);
|
22
AerofoilMac/AerofoilMac/MacInit.mm
Normal 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;
|
||||||
|
}
|
6
AerofoilMac/Resources/README.TXT
Normal 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
|
10
AerofoilPortable.props
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
<?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>
|
||||||
|
<IncludePath>$(SolutionDir)AerofoilPortable;$(IncludePath)</IncludePath>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemDefinitionGroup />
|
||||||
|
<ItemGroup />
|
||||||
|
</Project>
|
@@ -2,19 +2,21 @@ LOCAL_PATH := $(call my-dir)
|
|||||||
|
|
||||||
include $(CLEAR_VARS)
|
include $(CLEAR_VARS)
|
||||||
|
|
||||||
LOCAL_MODULE := GpFontHandler_FreeType2
|
LOCAL_MODULE := AerofoilPortable
|
||||||
|
|
||||||
LOCAL_C_INCLUDES := \
|
LOCAL_C_INCLUDES := \
|
||||||
$(LOCAL_PATH)/../Common \
|
|
||||||
$(LOCAL_PATH)/../GpCommon \
|
$(LOCAL_PATH)/../GpCommon \
|
||||||
$(LOCAL_PATH)/../FreeType/freetype/include
|
$(LOCAL_PATH)/../GpShell \
|
||||||
|
$(LOCAL_PATH)/../Common \
|
||||||
|
$(LOCAL_PATH)/../PortabilityLayer
|
||||||
|
|
||||||
LOCAL_CFLAGS := -DGP_DEBUG_CONFIG=0
|
LOCAL_CFLAGS := -DGP_DEBUG_CONFIG=0
|
||||||
|
|
||||||
# Add your application source files here...
|
# Add your application source files here...
|
||||||
LOCAL_SRC_FILES := \
|
LOCAL_SRC_FILES := \
|
||||||
GpFontHandler_FreeType2.cpp
|
GpAllocator_C.cpp \
|
||||||
|
GpThreadEvent_Cpp11.cpp \
|
||||||
|
GpSystemServices_POSIX.cpp
|
||||||
|
|
||||||
LOCAL_SHARED_LIBRARIES := FreeType
|
|
||||||
|
|
||||||
include $(BUILD_STATIC_LIBRARY)
|
include $(BUILD_STATIC_LIBRARY)
|
115
AerofoilPortable/GpAllocator_C.cpp
Normal 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;
|
17
AerofoilPortable/GpAllocator_C.h
Normal 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;
|
||||||
|
};
|
66
AerofoilPortable/GpMutex_Cpp11.h
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "IGpMutex.h"
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
|
template<class TMutex>
|
||||||
|
class GpMutex_Cpp11 final : public IGpMutex
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
~GpMutex_Cpp11();
|
||||||
|
|
||||||
|
void Destroy() override;
|
||||||
|
static GpMutex_Cpp11<TMutex> *Create();
|
||||||
|
|
||||||
|
void Lock() override;
|
||||||
|
void Unlock() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
GpMutex_Cpp11();
|
||||||
|
|
||||||
|
TMutex m_mutex;
|
||||||
|
};
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
template<class TMutex>
|
||||||
|
GpMutex_Cpp11<TMutex>::GpMutex_Cpp11()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class TMutex>
|
||||||
|
GpMutex_Cpp11<TMutex>::~GpMutex_Cpp11()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class TMutex>
|
||||||
|
void GpMutex_Cpp11<TMutex>::Destroy()
|
||||||
|
{
|
||||||
|
this->~GpMutex_Cpp11();
|
||||||
|
free(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class TMutex>
|
||||||
|
GpMutex_Cpp11<TMutex> *GpMutex_Cpp11<TMutex>::Create()
|
||||||
|
{
|
||||||
|
GpMutex_Cpp11<TMutex> *mutex = static_cast<GpMutex_Cpp11<TMutex>*>(malloc(sizeof(GpMutex_Cpp11<TMutex>)));
|
||||||
|
if (!mutex)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
return new (mutex) GpMutex_Cpp11<TMutex>();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class TMutex>
|
||||||
|
void GpMutex_Cpp11<TMutex>::Lock()
|
||||||
|
{
|
||||||
|
m_mutex.lock();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class TMutex>
|
||||||
|
void GpMutex_Cpp11<TMutex>::Unlock()
|
||||||
|
{
|
||||||
|
m_mutex.unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef GpMutex_Cpp11<std::mutex> GpMutex_Cpp11_NonRecursive;
|
||||||
|
typedef GpMutex_Cpp11<std::recursive_mutex> GpMutex_Cpp11_Recursive;
|
68
AerofoilPortable/GpSystemServices_POSIX.cpp
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
#include "GpSystemServices_POSIX.h"
|
||||||
|
|
||||||
|
#include "GpMutex_Cpp11.h"
|
||||||
|
#include "GpThreadEvent_Cpp11.h"
|
||||||
|
|
||||||
|
#include <time.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#ifdef __MACOS__
|
||||||
|
#include <sys/sysctl.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
GpSystemServices_POSIX::GpSystemServices_POSIX()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t GpSystemServices_POSIX::GetTime() const
|
||||||
|
{
|
||||||
|
time_t t = time(nullptr);
|
||||||
|
return static_cast<int64_t>(t) - 2082844800;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GpSystemServices_POSIX::GetLocalDateTime(unsigned int &year, unsigned int &month, unsigned int &day, unsigned int &hour, unsigned int &minute, unsigned int &second) const
|
||||||
|
{
|
||||||
|
time_t t = time(nullptr);
|
||||||
|
tm *tmObject = localtime(&t);
|
||||||
|
year = static_cast<unsigned int>(tmObject->tm_year);
|
||||||
|
month = static_cast<unsigned int>(tmObject->tm_mon + 1);
|
||||||
|
hour = static_cast<unsigned int>(tmObject->tm_hour);
|
||||||
|
minute = static_cast<unsigned int>(tmObject->tm_min);
|
||||||
|
second = static_cast<unsigned int>(tmObject->tm_sec);
|
||||||
|
}
|
||||||
|
|
||||||
|
IGpMutex *GpSystemServices_POSIX::CreateMutex()
|
||||||
|
{
|
||||||
|
return GpMutex_Cpp11_NonRecursive::Create();
|
||||||
|
}
|
||||||
|
|
||||||
|
IGpMutex *GpSystemServices_POSIX::CreateRecursiveMutex()
|
||||||
|
{
|
||||||
|
return GpMutex_Cpp11_Recursive::Create();
|
||||||
|
}
|
||||||
|
|
||||||
|
IGpThreadEvent *GpSystemServices_POSIX::CreateThreadEvent(bool autoReset, bool startSignaled)
|
||||||
|
{
|
||||||
|
return GpThreadEvent_Cpp11::Create(autoReset, startSignaled);
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
17
AerofoilPortable/GpSystemServices_POSIX.h
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "IGpSystemServices.h"
|
||||||
|
#include "GpCoreDefs.h"
|
||||||
|
|
||||||
|
class GpSystemServices_POSIX : public IGpSystemServices
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
GpSystemServices_POSIX();
|
||||||
|
|
||||||
|
int64_t GetTime() const override;
|
||||||
|
void GetLocalDateTime(unsigned int &year, unsigned int &month, unsigned int &day, unsigned int &hour, unsigned int &minute, unsigned int &second) const override;
|
||||||
|
IGpMutex *CreateMutex() override;
|
||||||
|
IGpMutex *CreateRecursiveMutex() override;
|
||||||
|
IGpThreadEvent *CreateThreadEvent(bool autoReset, bool startSignaled) override;
|
||||||
|
uint64_t GetFreeMemoryCosmetic() const override;
|
||||||
|
};
|
82
AerofoilPortable/GpThreadEvent_Cpp11.cpp
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
#include "GpThreadEvent_Cpp11.h"
|
||||||
|
|
||||||
|
GpThreadEvent_Cpp11::GpThreadEvent_Cpp11(bool autoReset, bool startSignaled)
|
||||||
|
: m_flag(startSignaled)
|
||||||
|
, m_autoReset(autoReset)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
GpThreadEvent_Cpp11::~GpThreadEvent_Cpp11()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void GpThreadEvent_Cpp11::Wait()
|
||||||
|
{
|
||||||
|
std::unique_lock<std::mutex> lock(m_mutex);
|
||||||
|
if (m_autoReset)
|
||||||
|
{
|
||||||
|
m_cvar.wait(lock,[&]()->bool{
|
||||||
|
if (m_flag)
|
||||||
|
{
|
||||||
|
m_flag = false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
m_cvar.wait(lock,[&]()->bool{ return m_flag; });
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GpThreadEvent_Cpp11::WaitTimed(uint32_t msec)
|
||||||
|
{
|
||||||
|
std::unique_lock<std::mutex> lock(m_mutex);
|
||||||
|
if (m_autoReset)
|
||||||
|
{
|
||||||
|
if (!m_cvar.wait_for(lock, std::chrono::milliseconds(msec), [&]()->bool{
|
||||||
|
if (m_flag)
|
||||||
|
{
|
||||||
|
m_flag = false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!m_cvar.wait_for(lock, std::chrono::milliseconds(msec), [&]()->bool{ return m_flag; }))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GpThreadEvent_Cpp11::Signal()
|
||||||
|
{
|
||||||
|
m_mutex.lock();
|
||||||
|
m_flag = true;
|
||||||
|
m_mutex.unlock();
|
||||||
|
if (m_autoReset)
|
||||||
|
m_cvar.notify_one();
|
||||||
|
else
|
||||||
|
m_cvar.notify_all();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GpThreadEvent_Cpp11::Destroy()
|
||||||
|
{
|
||||||
|
this->~GpThreadEvent_Cpp11();
|
||||||
|
free(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
GpThreadEvent_Cpp11 *GpThreadEvent_Cpp11::Create(bool autoReset, bool startSignaled)
|
||||||
|
{
|
||||||
|
GpThreadEvent_Cpp11 *evt = static_cast<GpThreadEvent_Cpp11*>(malloc(sizeof(GpThreadEvent_Cpp11)));
|
||||||
|
if (!evt)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
return new (evt) GpThreadEvent_Cpp11(autoReset, startSignaled);
|
||||||
|
}
|
||||||
|
|
28
AerofoilPortable/GpThreadEvent_Cpp11.h
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "IGpThreadEvent.h"
|
||||||
|
|
||||||
|
#include <mutex>
|
||||||
|
#include <condition_variable>
|
||||||
|
|
||||||
|
class GpThreadEvent_Cpp11 final : public IGpThreadEvent
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
~GpThreadEvent_Cpp11();
|
||||||
|
|
||||||
|
void Wait() override;
|
||||||
|
bool WaitTimed(uint32_t msec) override;
|
||||||
|
void Signal() override;
|
||||||
|
void Destroy() override;
|
||||||
|
|
||||||
|
static GpThreadEvent_Cpp11 *Create(bool autoReset, bool startSignaled);
|
||||||
|
|
||||||
|
private:
|
||||||
|
GpThreadEvent_Cpp11(bool autoReset, bool startSignaled);
|
||||||
|
GpThreadEvent_Cpp11() = delete;
|
||||||
|
|
||||||
|
std::mutex m_mutex;
|
||||||
|
std::condition_variable m_cvar;
|
||||||
|
bool m_flag;
|
||||||
|
bool m_autoReset;
|
||||||
|
};
|
@@ -3,7 +3,7 @@
|
|||||||
<ImportGroup Label="PropertySheets" />
|
<ImportGroup Label="PropertySheets" />
|
||||||
<PropertyGroup Label="UserMacros" />
|
<PropertyGroup Label="UserMacros" />
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<IncludePath>$(SolutionDir)SDL2-2.0.12\include;$(IncludePath)</IncludePath>
|
<IncludePath>$(SolutionDir)SDL2-2.0.12\include;$(SolutionDir)AerofoilPortable;$(IncludePath)</IncludePath>
|
||||||
<LibraryPath>$(SolutionDir)SDL2-2.0.12\lib\x64;$(LibraryPath)</LibraryPath>
|
<LibraryPath>$(SolutionDir)SDL2-2.0.12\lib\x64;$(LibraryPath)</LibraryPath>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemDefinitionGroup>
|
<ItemDefinitionGroup>
|
||||||
|
@@ -14,19 +14,19 @@
|
|||||||
<VCProjectVersion>15.0</VCProjectVersion>
|
<VCProjectVersion>15.0</VCProjectVersion>
|
||||||
<ProjectGuid>{33542FF0-0473-4802-BC79-3B8261790F65}</ProjectGuid>
|
<ProjectGuid>{33542FF0-0473-4802-BC79-3B8261790F65}</ProjectGuid>
|
||||||
<RootNamespace>AerofoilSDL</RootNamespace>
|
<RootNamespace>AerofoilSDL</RootNamespace>
|
||||||
<WindowsTargetPlatformVersion>10.0.17763.0</WindowsTargetPlatformVersion>
|
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
<UseDebugLibraries>true</UseDebugLibraries>
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
<PlatformToolset>v141</PlatformToolset>
|
<PlatformToolset>v142</PlatformToolset>
|
||||||
<CharacterSet>MultiByte</CharacterSet>
|
<CharacterSet>MultiByte</CharacterSet>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
<UseDebugLibraries>false</UseDebugLibraries>
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
<PlatformToolset>v141</PlatformToolset>
|
<PlatformToolset>v142</PlatformToolset>
|
||||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
<CharacterSet>MultiByte</CharacterSet>
|
<CharacterSet>MultiByte</CharacterSet>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
@@ -84,6 +84,7 @@
|
|||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<ClCompile Include="..\AerofoilPortable\GpAllocator_C.cpp" />
|
||||||
<ClCompile Include="..\Aerofoil\GpColorCursor_Win32.cpp" />
|
<ClCompile Include="..\Aerofoil\GpColorCursor_Win32.cpp" />
|
||||||
<ClCompile Include="..\Aerofoil\GpFileStream_Win32.cpp" />
|
<ClCompile Include="..\Aerofoil\GpFileStream_Win32.cpp" />
|
||||||
<ClCompile Include="..\Aerofoil\GpFileSystem_Win32.cpp" />
|
<ClCompile Include="..\Aerofoil\GpFileSystem_Win32.cpp" />
|
||||||
@@ -93,10 +94,10 @@
|
|||||||
<ClCompile Include="..\Aerofoil\GpThreadEvent_Win32.cpp" />
|
<ClCompile Include="..\Aerofoil\GpThreadEvent_Win32.cpp" />
|
||||||
<ClCompile Include="GpAudioDriver_SDL2.cpp" />
|
<ClCompile Include="GpAudioDriver_SDL2.cpp" />
|
||||||
<ClCompile Include="GpDisplayDriver_SDL_GL2.cpp" />
|
<ClCompile Include="GpDisplayDriver_SDL_GL2.cpp" />
|
||||||
<ClCompile Include="GpFiberStarter_SDL.cpp" />
|
<ClCompile Include="GpInputDriver_SDL_Gamepad.cpp" />
|
||||||
<ClCompile Include="GpFiber_SDL.cpp" />
|
|
||||||
<ClCompile Include="GpMain_SDL_Win32.cpp" />
|
<ClCompile Include="GpMain_SDL_Win32.cpp" />
|
||||||
<ClCompile Include="ShaderCode\CopyQuadP.cpp" />
|
<ClCompile Include="ShaderCode\CopyQuadP.cpp" />
|
||||||
|
<ClCompile Include="ShaderCode\DrawQuad32P.cpp" />
|
||||||
<ClCompile Include="ShaderCode\DrawQuadPaletteP.cpp" />
|
<ClCompile Include="ShaderCode\DrawQuadPaletteP.cpp" />
|
||||||
<ClCompile Include="ShaderCode\DrawQuadV.cpp" />
|
<ClCompile Include="ShaderCode\DrawQuadV.cpp" />
|
||||||
<ClCompile Include="ShaderCode\ScaleQuadP.cpp" />
|
<ClCompile Include="ShaderCode\ScaleQuadP.cpp" />
|
||||||
@@ -111,15 +112,13 @@
|
|||||||
<ProjectReference Include="..\GpFontHandler_FreeType2\GpFontHandler_FreeType2.vcxproj">
|
<ProjectReference Include="..\GpFontHandler_FreeType2\GpFontHandler_FreeType2.vcxproj">
|
||||||
<Project>{4b564030-8985-4975-91e1-e1b2c16ae2a1}</Project>
|
<Project>{4b564030-8985-4975-91e1-e1b2c16ae2a1}</Project>
|
||||||
</ProjectReference>
|
</ProjectReference>
|
||||||
<ProjectReference Include="..\GpInputDriver_XInput\GpInputDriver_XInput.vcxproj">
|
|
||||||
<Project>{17b96f07-ef92-47cd-95a5-8e6ee38ab564}</Project>
|
|
||||||
</ProjectReference>
|
|
||||||
<ProjectReference Include="..\GpShell\GpShell.vcxproj">
|
<ProjectReference Include="..\GpShell\GpShell.vcxproj">
|
||||||
<Project>{10cf9b5f-61d0-4b5b-89f4-810b58fc053d}</Project>
|
<Project>{10cf9b5f-61d0-4b5b-89f4-810b58fc053d}</Project>
|
||||||
</ProjectReference>
|
</ProjectReference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="GpFiber_SDL.h" />
|
<ClInclude Include="GpFiber_SDL.h" />
|
||||||
|
<ClInclude Include="GpInputDriver_SDL_Gamepad.h" />
|
||||||
<ClInclude Include="ShaderCode\DrawQuadPixelConstants.h" />
|
<ClInclude Include="ShaderCode\DrawQuadPixelConstants.h" />
|
||||||
<ClInclude Include="ShaderCode\Functions.h" />
|
<ClInclude Include="ShaderCode\Functions.h" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
@@ -48,12 +48,6 @@
|
|||||||
<ClCompile Include="ShaderCode\ScaleQuadP.cpp">
|
<ClCompile Include="ShaderCode\ScaleQuadP.cpp">
|
||||||
<Filter>Source Files\ShaderCode</Filter>
|
<Filter>Source Files\ShaderCode</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="GpFiber_SDL.cpp">
|
|
||||||
<Filter>Source Files</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="GpFiberStarter_SDL.cpp">
|
|
||||||
<Filter>Source Files</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="GpDisplayDriver_SDL_GL2.cpp">
|
<ClCompile Include="GpDisplayDriver_SDL_GL2.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
@@ -66,6 +60,15 @@
|
|||||||
<ClCompile Include="ShaderCode\CopyQuadP.cpp">
|
<ClCompile Include="ShaderCode\CopyQuadP.cpp">
|
||||||
<Filter>Source Files\ShaderCode</Filter>
|
<Filter>Source Files\ShaderCode</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="ShaderCode\DrawQuad32P.cpp">
|
||||||
|
<Filter>Source Files\ShaderCode</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="GpInputDriver_SDL_Gamepad.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\AerofoilPortable\GpAllocator_C.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="ShaderCode\Functions.h">
|
<ClInclude Include="ShaderCode\Functions.h">
|
||||||
@@ -77,5 +80,8 @@
|
|||||||
<ClInclude Include="GpFiber_SDL.h">
|
<ClInclude Include="GpFiber_SDL.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="GpInputDriver_SDL_Gamepad.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
8
AerofoilSDL/AerofoilSDL_Combined.cpp
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
#include "GpAudioDriver_SDL2.cpp"
|
||||||
|
#include "GpDisplayDriver_SDL_GL2.cpp"
|
||||||
|
#include "GpInputDriver_SDL_Gamepad.cpp"
|
||||||
|
#include "ShaderCode/CopyQuadP.cpp"
|
||||||
|
#include "ShaderCode/DrawQuadPaletteP.cpp"
|
||||||
|
#include "ShaderCode/DrawQuad32P.cpp"
|
||||||
|
#include "ShaderCode/DrawQuadV.cpp"
|
||||||
|
#include "ShaderCode/ScaleQuadP.cpp"
|
@@ -11,6 +11,7 @@ LOCAL_C_INCLUDES := \
|
|||||||
$(LOCAL_PATH)/../GpShell \
|
$(LOCAL_PATH)/../GpShell \
|
||||||
$(LOCAL_PATH)/../Common \
|
$(LOCAL_PATH)/../Common \
|
||||||
$(LOCAL_PATH)/../PortabilityLayer \
|
$(LOCAL_PATH)/../PortabilityLayer \
|
||||||
|
$(LOCAL_PATH)/../AerofoilPortable \
|
||||||
$(LOCAL_PATH)/$(SDL_PATH)/include
|
$(LOCAL_PATH)/$(SDL_PATH)/include
|
||||||
|
|
||||||
LOCAL_CFLAGS := -DGP_DEBUG_CONFIG=0
|
LOCAL_CFLAGS := -DGP_DEBUG_CONFIG=0
|
||||||
@@ -19,10 +20,10 @@ LOCAL_CFLAGS := -DGP_DEBUG_CONFIG=0
|
|||||||
LOCAL_SRC_FILES := \
|
LOCAL_SRC_FILES := \
|
||||||
GpAudioDriver_SDL2.cpp \
|
GpAudioDriver_SDL2.cpp \
|
||||||
GpDisplayDriver_SDL_GL2.cpp \
|
GpDisplayDriver_SDL_GL2.cpp \
|
||||||
GpFiber_SDL.cpp \
|
GpInputDriver_SDL_Gamepad.cpp \
|
||||||
GpFiberStarter_SDL.cpp \
|
|
||||||
ShaderCode/CopyQuadP.cpp \
|
ShaderCode/CopyQuadP.cpp \
|
||||||
ShaderCode/DrawQuadPaletteP.cpp \
|
ShaderCode/DrawQuadPaletteP.cpp \
|
||||||
|
ShaderCode/DrawQuad32P.cpp \
|
||||||
ShaderCode/DrawQuadV.cpp \
|
ShaderCode/DrawQuadV.cpp \
|
||||||
ShaderCode/ScaleQuadP.cpp
|
ShaderCode/ScaleQuadP.cpp
|
||||||
|
|
||||||
|
@@ -1,25 +1,34 @@
|
|||||||
|
#include "CoreDefs.h"
|
||||||
|
#include "IGpAudioBuffer.h"
|
||||||
#include "IGpAudioDriver.h"
|
#include "IGpAudioDriver.h"
|
||||||
#include "IGpAudioChannel.h"
|
#include "IGpAudioChannel.h"
|
||||||
#include "IGpAudioChannelCallbacks.h"
|
#include "IGpAudioChannelCallbacks.h"
|
||||||
|
#include "IGpMutex.h"
|
||||||
#include "IGpPrefsHandler.h"
|
#include "IGpPrefsHandler.h"
|
||||||
|
#include "IGpSystemServices.h"
|
||||||
#include "GpAudioDriverProperties.h"
|
#include "GpAudioDriverProperties.h"
|
||||||
#include "CoreDefs.h"
|
#include "GpSDL.h"
|
||||||
|
|
||||||
#include "HostMutex.h"
|
|
||||||
#include "HostSystemServices.h"
|
|
||||||
|
|
||||||
#include "SDL_audio.h"
|
#include "SDL_audio.h"
|
||||||
#include "GpRingBuffer.h"
|
#include "GpRingBuffer.h"
|
||||||
|
|
||||||
#include "SDL_atomic.h"
|
#include "SDL_atomic.h"
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <new>
|
#include <new>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <chrono>
|
||||||
|
|
||||||
class GpAudioDriver_SDL2;
|
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)
|
static void *AlignedAlloc(size_t size, size_t alignment)
|
||||||
{
|
{
|
||||||
void *storage = malloc(size + alignment);
|
void *storage = malloc(size + alignment);
|
||||||
@@ -46,72 +55,150 @@ static void AlignedFree(void *ptr)
|
|||||||
free(storageLoc);
|
free(storageLoc);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct GpAudioChannelBufferChain_SDL2 final
|
class GpAudioBuffer_SDL2 final : public IGpAudioBuffer
|
||||||
{
|
|
||||||
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
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
enum ChannelState
|
typedef int16_t AudioSample_t;
|
||||||
{
|
|
||||||
ChannelState_Idle,
|
|
||||||
ChannelState_Playing,
|
|
||||||
ChannelState_Stopped,
|
|
||||||
};
|
|
||||||
|
|
||||||
|
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;
|
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();
|
~GpAudioChannel_SDL2();
|
||||||
|
|
||||||
void AddRef();
|
void AddRef();
|
||||||
void Release();
|
void Release();
|
||||||
|
|
||||||
void SetAudioChannelContext(IGpAudioChannelCallbacks *callbacks) override;
|
void SetAudioChannelContext(IGpAudioChannelCallbacks *callbacks) override;
|
||||||
void PostBuffer(const void *buffer, size_t bufferSize) override;
|
bool PostBuffer(IGpAudioBuffer *buffer) override;
|
||||||
void Stop() override;
|
void Stop() override;
|
||||||
void Destroy() 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:
|
private:
|
||||||
bool Init(GpAudioDriver_SDL2 *driver);
|
bool Init(GpAudioDriver_SDL2 *driver);
|
||||||
|
|
||||||
|
static const size_t kMaxBuffers = 16;
|
||||||
|
|
||||||
IGpAudioChannelCallbacks *m_callbacks;
|
IGpAudioChannelCallbacks *m_callbacks;
|
||||||
PortabilityLayer::HostMutex *m_mutex;
|
IGpMutex *m_mutex;
|
||||||
GpAudioDriver_SDL2 *m_owner;
|
GpAudioDriver_SDL2 *m_owner;
|
||||||
|
|
||||||
SDL_atomic_t m_refCount;
|
SDL_atomic_t m_refCount;
|
||||||
|
|
||||||
GpAudioChannelBufferChain_SDL2 *m_firstPendingBuffer;
|
GpAudioBuffer_SDL2 *m_pendingBuffers[kMaxBuffers];
|
||||||
GpAudioChannelBufferChain_SDL2 *m_lastPendingBuffer;
|
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:
|
public:
|
||||||
friend class GpAudioChannel_SDL2;
|
friend class GpAudioChannel_SDL2;
|
||||||
|
|
||||||
|
typedef GpAudioChannel_SDL2::AudioSample_t AudioSample_t;
|
||||||
|
|
||||||
|
|
||||||
explicit GpAudioDriver_SDL2(const GpAudioDriverProperties &properties);
|
explicit GpAudioDriver_SDL2(const GpAudioDriverProperties &properties);
|
||||||
~GpAudioDriver_SDL2();
|
~GpAudioDriver_SDL2();
|
||||||
|
|
||||||
|
IGpAudioBuffer *CreateBuffer(const void *data, size_t size) override;
|
||||||
IGpAudioChannel *CreateChannel() override;
|
IGpAudioChannel *CreateChannel() override;
|
||||||
void SetMasterVolume(uint32_t vol, uint32_t maxVolume) override;
|
void SetMasterVolume(uint32_t vol, uint32_t maxVolume) override;
|
||||||
void Shutdown() override;
|
void Shutdown() override;
|
||||||
@@ -122,60 +209,59 @@ public:
|
|||||||
|
|
||||||
bool Init();
|
bool Init();
|
||||||
|
|
||||||
|
static GpAudioDriver_SDL2_TimePoint_t GetCurrentTime();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void DetachAudioChannel(GpAudioChannel_SDL2 *channel);
|
void DetachAudioChannel(GpAudioChannel_SDL2 *channel);
|
||||||
|
|
||||||
static void SDLCALL StaticMixAudio(void *userdata, Uint8 *stream, int len);
|
static void SDLCALL StaticMixAudio(void *userdata, Uint8 *stream, int len);
|
||||||
|
|
||||||
void MixAudio(void *stream, size_t 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;
|
GpAudioDriverProperties m_properties;
|
||||||
PortabilityLayer::HostMutex *m_mutex;
|
IGpMutex *m_mutex;
|
||||||
PortabilityLayer::HostMutex *m_mixState;
|
IGpMutex *m_mixState;
|
||||||
|
|
||||||
static const size_t kMaxChannels = 16;
|
static const size_t kMaxChannels = 16;
|
||||||
static const size_t kMixChunkSize = 256;
|
static const size_t kMixChunkSamples = 512;
|
||||||
|
static const int16_t kMaxAudioVolumeScale = 64;
|
||||||
|
|
||||||
GpAudioChannel_SDL2 *m_channels[kMaxChannels];
|
GpAudioChannel_SDL2 *m_channels[kMaxChannels];
|
||||||
size_t m_numChannels;
|
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;
|
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;
|
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
|
||||||
|
|
||||||
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_callbacks(nullptr)
|
||||||
, m_mutex(nullptr)
|
, m_mutex(nullptr)
|
||||||
, m_owner(nullptr)
|
, m_owner(nullptr)
|
||||||
, m_firstPendingBuffer(nullptr)
|
, m_latency(latency)
|
||||||
, m_lastPendingBuffer(nullptr)
|
, 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);
|
SDL_AtomicSet(&m_refCount, 1);
|
||||||
}
|
}
|
||||||
@@ -187,12 +273,7 @@ GpAudioChannel_SDL2::~GpAudioChannel_SDL2()
|
|||||||
if (m_mutex)
|
if (m_mutex)
|
||||||
m_mutex->Destroy();
|
m_mutex->Destroy();
|
||||||
|
|
||||||
while (m_firstPendingBuffer)
|
assert(m_numQueuedBuffers == 0);
|
||||||
{
|
|
||||||
GpAudioChannelBufferChain_SDL2 *buffer = m_firstPendingBuffer;
|
|
||||||
m_firstPendingBuffer = buffer->m_next;
|
|
||||||
buffer->Release();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GpAudioChannel_SDL2::AddRef()
|
void GpAudioChannel_SDL2::AddRef()
|
||||||
@@ -215,54 +296,70 @@ void GpAudioChannel_SDL2::SetAudioChannelContext(IGpAudioChannelCallbacks *callb
|
|||||||
m_callbacks = callbacks;
|
m_callbacks = callbacks;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GpAudioChannel_SDL2::PostBuffer(const void *buffer, size_t bufferSize)
|
bool GpAudioChannel_SDL2::PostBuffer(IGpAudioBuffer *buffer)
|
||||||
{
|
{
|
||||||
|
buffer->AddRef();
|
||||||
|
|
||||||
m_mutex->Lock();
|
m_mutex->Lock();
|
||||||
|
|
||||||
while (bufferSize > 0)
|
if (m_numQueuedBuffers == kMaxBuffers)
|
||||||
{
|
{
|
||||||
GpAudioChannelBufferChain_SDL2 *newBuffer = GpAudioChannelBufferChain_SDL2::Alloc();
|
m_mutex->Unlock();
|
||||||
if (newBuffer == nullptr)
|
buffer->Release();
|
||||||
break;
|
return false;
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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();
|
m_mutex->Unlock();
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GpAudioChannel_SDL2::Stop()
|
void GpAudioChannel_SDL2::Stop()
|
||||||
{
|
{
|
||||||
m_mutex->Lock();
|
m_mutex->Lock();
|
||||||
|
|
||||||
GpAudioChannelBufferChain_SDL2 *buffer = m_firstPendingBuffer;
|
m_leadingSilence = 0;
|
||||||
m_firstPendingBuffer = nullptr;
|
|
||||||
m_lastPendingBuffer = nullptr;
|
|
||||||
|
|
||||||
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();
|
m_callbacks->NotifyBufferFinished();
|
||||||
|
|
||||||
GpAudioChannelBufferChain_SDL2 *nextBuffer = buffer->m_next;
|
|
||||||
buffer->Release();
|
buffer->Release();
|
||||||
|
|
||||||
buffer = nextBuffer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
m_mutex->Unlock();
|
m_mutex->Unlock();
|
||||||
@@ -286,25 +383,57 @@ bool GpAudioChannel_SDL2::Init(GpAudioDriver_SDL2 *driver)
|
|||||||
return true;
|
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();
|
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;
|
memset(output, 0, sz * sizeof(AudioSample_t));
|
||||||
const size_t available = (buffer->m_used - buffer->m_consumed);
|
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)
|
if (available <= sz)
|
||||||
{
|
{
|
||||||
memcpy(output, buffer->m_data + buffer->m_consumed, available);
|
memcpy(output, bufferData + m_firstBufferSamplesConsumed, available * sizeof(AudioSample_t));
|
||||||
sz -= available;
|
sz -= available;
|
||||||
output += available;
|
output += available;
|
||||||
|
|
||||||
m_firstPendingBuffer = buffer->m_next;
|
m_nextPendingBufferConsumePos = (m_nextPendingBufferConsumePos + 1) % kMaxBuffers;
|
||||||
if (m_firstPendingBuffer == nullptr)
|
m_numQueuedBuffers--;
|
||||||
m_lastPendingBuffer = nullptr;
|
|
||||||
|
|
||||||
if (buffer->m_hasTrigger && m_callbacks)
|
m_firstBufferSamplesConsumed = 0;
|
||||||
|
|
||||||
|
if (m_callbacks)
|
||||||
m_callbacks->NotifyBufferFinished();
|
m_callbacks->NotifyBufferFinished();
|
||||||
|
|
||||||
buffer->Release();
|
buffer->Release();
|
||||||
@@ -314,26 +443,28 @@ void GpAudioChannel_SDL2::Consume(uint8_t *output, size_t sz)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
memcpy(output, buffer->m_data + buffer->m_consumed, sz);
|
memcpy(output, bufferData + m_firstBufferSamplesConsumed, sz * sizeof(AudioSample_t));
|
||||||
buffer->m_consumed += sz;
|
m_firstBufferSamplesConsumed += sz;
|
||||||
buffer += sz;
|
output += sz;
|
||||||
sz = 0;
|
sz = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_isMixing = false;
|
||||||
|
|
||||||
m_mutex->Unlock();
|
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);
|
void *storage = AlignedAlloc(sizeof(GpAudioChannel_SDL2), GP_SYSTEM_MEMORY_ALIGNMENT);
|
||||||
if (!storage)
|
if (!storage)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
GpAudioChannel_SDL2 *channel = new (storage) GpAudioChannel_SDL2();
|
GpAudioChannel_SDL2 *channel = new (storage) GpAudioChannel_SDL2(latency, bufferTime, bufferSamplesMax, sampleRate);
|
||||||
if (!channel->Init(driver))
|
if (!channel->Init(driver))
|
||||||
{
|
{
|
||||||
channel->Destroy();
|
channel->Destroy();
|
||||||
@@ -351,14 +482,18 @@ GpAudioDriver_SDL2::GpAudioDriver_SDL2(const GpAudioDriverProperties &properties
|
|||||||
: m_properties(properties)
|
: m_properties(properties)
|
||||||
, m_mutex(nullptr)
|
, m_mutex(nullptr)
|
||||||
, m_numChannels(0)
|
, m_numChannels(0)
|
||||||
|
, m_sampleRate(0)
|
||||||
|
, m_latency(GpAudioDriver_SDL2_Duration_t::zero())
|
||||||
|
, m_bufferTime(GpAudioDriver_SDL2_Duration_t::zero())
|
||||||
, m_sdlAudioRunning(false)
|
, m_sdlAudioRunning(false)
|
||||||
, m_mixChunkReadOffset(kMixChunkSize)
|
, m_mixChunkReadOffset(kMixChunkSamples)
|
||||||
|
, m_audioVolumeScale(kMaxAudioVolumeScale)
|
||||||
|
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < kMaxChannels; i++)
|
for (size_t i = 0; i < kMaxChannels; i++)
|
||||||
m_channels[i] = nullptr;
|
m_channels[i] = nullptr;
|
||||||
|
|
||||||
for (size_t i = 0; i < kMixChunkSize; i++)
|
for (size_t i = 0; i < kMixChunkSamples; i++)
|
||||||
m_mixChunk[i] = 0;
|
m_mixChunk[i] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -371,9 +506,14 @@ GpAudioDriver_SDL2::~GpAudioDriver_SDL2()
|
|||||||
m_mutex->Destroy();
|
m_mutex->Destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IGpAudioBuffer *GpAudioDriver_SDL2::CreateBuffer(const void *data, size_t size)
|
||||||
|
{
|
||||||
|
return GpAudioBuffer_SDL2::Create(data, size);
|
||||||
|
}
|
||||||
|
|
||||||
IGpAudioChannel *GpAudioDriver_SDL2::CreateChannel()
|
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)
|
if (!newChannel)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
@@ -395,6 +535,9 @@ IGpAudioChannel *GpAudioDriver_SDL2::CreateChannel()
|
|||||||
|
|
||||||
void GpAudioDriver_SDL2::SetMasterVolume(uint32_t vol, uint32_t maxVolume)
|
void GpAudioDriver_SDL2::SetMasterVolume(uint32_t vol, uint32_t maxVolume)
|
||||||
{
|
{
|
||||||
|
double scale = vol * static_cast<uint64_t>(kMaxAudioVolumeScale) / maxVolume;
|
||||||
|
|
||||||
|
m_audioVolumeScale = static_cast<int16_t>(scale);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GpAudioDriver_SDL2::Shutdown()
|
void GpAudioDriver_SDL2::Shutdown()
|
||||||
@@ -430,7 +573,7 @@ bool GpAudioDriver_SDL2::Init()
|
|||||||
requestedSpec.channels = 1;
|
requestedSpec.channels = 1;
|
||||||
requestedSpec.format = AUDIO_S16;
|
requestedSpec.format = AUDIO_S16;
|
||||||
requestedSpec.freq = m_properties.m_sampleRate;
|
requestedSpec.freq = m_properties.m_sampleRate;
|
||||||
requestedSpec.samples = 512;
|
requestedSpec.samples = kMixChunkSamples;
|
||||||
requestedSpec.userdata = this;
|
requestedSpec.userdata = this;
|
||||||
|
|
||||||
if (SDL_OpenAudio(&requestedSpec, nullptr))
|
if (SDL_OpenAudio(&requestedSpec, nullptr))
|
||||||
@@ -443,6 +586,10 @@ bool GpAudioDriver_SDL2::Init()
|
|||||||
SDL_PauseAudio(0);
|
SDL_PauseAudio(0);
|
||||||
|
|
||||||
m_sdlAudioRunning = true;
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -485,11 +632,16 @@ void GpAudioDriver_SDL2::MixAudio(void *stream, size_t len)
|
|||||||
}
|
}
|
||||||
m_mutex->Unlock();
|
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 (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
size_t availableInMixChunk = kMixChunkSize - m_mixChunkReadOffset;
|
size_t availableInMixChunk = kMixChunkSamples - m_mixChunkReadOffset;
|
||||||
|
|
||||||
if (availableInMixChunk > samplesRemaining)
|
if (availableInMixChunk > samplesRemaining)
|
||||||
{
|
{
|
||||||
@@ -503,10 +655,17 @@ void GpAudioDriver_SDL2::MixAudio(void *stream, size_t len)
|
|||||||
memcpy(stream, m_mixChunk + m_mixChunkReadOffset, availableInMixChunk * sizeof(int16_t));
|
memcpy(stream, m_mixChunk + m_mixChunkReadOffset, availableInMixChunk * sizeof(int16_t));
|
||||||
|
|
||||||
stream = static_cast<int16_t*>(stream) + availableInMixChunk;
|
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;
|
m_mixChunkReadOffset = 0;
|
||||||
RefillMixChunk(mixingChannels, numChannels);
|
RefillMixChunk(mixingChannels, numChannels, samplesRemaining, audioMixBlockStartTime, audioMixBlockEndTime);
|
||||||
|
audioMixBlockStartTime = audioMixBlockEndTime;
|
||||||
|
|
||||||
|
samplesRemaining -= availableInMixChunk;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -514,40 +673,66 @@ void GpAudioDriver_SDL2::MixAudio(void *stream, size_t len)
|
|||||||
mixingChannels[i]->Release();
|
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 audioMixBufferUnaligned[kMixChunkSamples * sizeof(AudioSample_t) + GP_SYSTEM_MEMORY_ALIGNMENT];
|
||||||
uint8_t *audioMixBuffer = audioMixBufferUnaligned;
|
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);
|
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;
|
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++)
|
for (size_t i = 0; i < numChannels; i++)
|
||||||
{
|
{
|
||||||
channels[i]->Consume(audioMixBuffer, kMixChunkSize);
|
channels[i]->Consume(audioMixBuffer, samplesToFill, mixStartTime, mixEndTime);
|
||||||
|
|
||||||
if (i == 0)
|
if (i == 0)
|
||||||
{
|
{
|
||||||
noAudio = false;
|
noAudio = false;
|
||||||
for (size_t j = 0; j < kMixChunkSize; j++)
|
memcpy(mixChunkStart, audioMixBuffer, samplesToFill * sizeof(AudioSample_t));
|
||||||
m_mixChunk[j] = (audioMixBuffer[j] - 0x80) * 25;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
AddSamples(mixChunkStart, audioMixBuffer, samplesToFill);
|
||||||
for (size_t j = 0; j < kMixChunkSize; j++)
|
|
||||||
m_mixChunk[j] += (audioMixBuffer[j] - 0x80) * 25;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (noAudio)
|
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)
|
IGpAudioDriver *GpDriver_CreateAudioDriver_SDL(const GpAudioDriverProperties &properties)
|
||||||
{
|
{
|
||||||
|
@@ -1,16 +1,19 @@
|
|||||||
#include "IGpDisplayDriver.h"
|
#include "IGpDisplayDriver.h"
|
||||||
|
|
||||||
|
#include "CoreDefs.h"
|
||||||
#include "GpApplicationName.h"
|
#include "GpApplicationName.h"
|
||||||
#include "GpComPtr.h"
|
#include "GpComPtr.h"
|
||||||
#include "GpFiber_SDL.h"
|
|
||||||
#include "GpDisplayDriverProperties.h"
|
#include "GpDisplayDriverProperties.h"
|
||||||
#include "GpVOSEvent.h"
|
#include "GpVOSEvent.h"
|
||||||
#include "GpRingBuffer.h"
|
#include "GpRingBuffer.h"
|
||||||
#include "HostSystemServices.h"
|
#include "GpInputDriver_SDL_Gamepad.h"
|
||||||
|
#include "GpSDL.h"
|
||||||
|
#include "GpUnicode.h"
|
||||||
#include "IGpCursor.h"
|
#include "IGpCursor.h"
|
||||||
#include "IGpDisplayDriverSurface.h"
|
#include "IGpDisplayDriverSurface.h"
|
||||||
#include "IGpLogDriver.h"
|
#include "IGpLogDriver.h"
|
||||||
#include "IGpPrefsHandler.h"
|
#include "IGpPrefsHandler.h"
|
||||||
|
#include "IGpSystemServices.h"
|
||||||
#include "IGpVOSEventQueue.h"
|
#include "IGpVOSEventQueue.h"
|
||||||
|
|
||||||
#include "SDL_events.h"
|
#include "SDL_events.h"
|
||||||
@@ -27,6 +30,9 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
|
#ifdef __EMSCRIPTEN__
|
||||||
|
#include <emscripten.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#pragma push_macro("LoadCursor")
|
#pragma push_macro("LoadCursor")
|
||||||
#ifdef LoadCursor
|
#ifdef LoadCursor
|
||||||
@@ -39,68 +45,13 @@ class GpDisplayDriver_SDL_GL2;
|
|||||||
|
|
||||||
static GpDisplayDriverSurfaceEffects gs_defaultEffects;
|
static GpDisplayDriverSurfaceEffects gs_defaultEffects;
|
||||||
|
|
||||||
|
static const char *kPrefsIdentifier = "GpDisplayDriverSDL_GL2";
|
||||||
|
static uint32_t kPrefsVersion = 1;
|
||||||
|
|
||||||
namespace DeleteMe
|
struct GpDisplayDriver_SDL_GL2_Prefs
|
||||||
{
|
{
|
||||||
bool DecodeCodePoint(const uint8_t *characters, size_t availableCharacters, size_t &outCharactersDigested, uint32_t &outCodePoint)
|
bool m_isFullScreen;
|
||||||
{
|
};
|
||||||
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
|
namespace GpBinarizedShaders
|
||||||
{
|
{
|
||||||
@@ -108,17 +59,13 @@ namespace GpBinarizedShaders
|
|||||||
|
|
||||||
extern const char *g_drawQuadPalettePF_GL2;
|
extern const char *g_drawQuadPalettePF_GL2;
|
||||||
extern const char *g_drawQuadPalettePNF_GL2;
|
extern const char *g_drawQuadPalettePNF_GL2;
|
||||||
extern const char *g_drawQuadRGBPF_GL2;
|
extern const char *g_drawQuad32PF_GL2;
|
||||||
extern const char *g_drawQuadRGBPNF_GL2;
|
extern const char *g_drawQuad32PNF_GL2;
|
||||||
extern const char *g_drawQuad15BitPF_GL2;
|
|
||||||
extern const char *g_drawQuad15BitPNF_GL2;
|
|
||||||
|
|
||||||
extern const char *g_drawQuadPaletteICCPF_GL2;
|
extern const char *g_drawQuadPaletteICCPF_GL2;
|
||||||
extern const char *g_drawQuadPaletteICCPNF_GL2;
|
extern const char *g_drawQuadPaletteICCPNF_GL2;
|
||||||
extern const char *g_drawQuadRGBICCPF_GL2;
|
extern const char *g_drawQuad32ICCPF_GL2;
|
||||||
extern const char *g_drawQuadRGBICCPNF_GL2;
|
extern const char *g_drawQuad32ICCPNF_GL2;
|
||||||
extern const char *g_drawQuad15BitICCPF_GL2;
|
|
||||||
extern const char *g_drawQuad15BitICCPNF_GL2;
|
|
||||||
|
|
||||||
extern const char *g_copyQuadP_GL2;
|
extern const char *g_copyQuadP_GL2;
|
||||||
extern const char *g_scaleQuadP_GL2;
|
extern const char *g_scaleQuadP_GL2;
|
||||||
@@ -210,6 +157,7 @@ struct GpGLFunctions
|
|||||||
|
|
||||||
static void CheckGLError(const GpGLFunctions &gl, IGpLogDriver *logger)
|
static void CheckGLError(const GpGLFunctions &gl, IGpLogDriver *logger)
|
||||||
{
|
{
|
||||||
|
#if GP_DEBUG_CONFIG
|
||||||
GLenum errorCode = gl.GetError();
|
GLenum errorCode = gl.GetError();
|
||||||
if (errorCode != 0)
|
if (errorCode != 0)
|
||||||
{
|
{
|
||||||
@@ -218,6 +166,7 @@ static void CheckGLError(const GpGLFunctions &gl, IGpLogDriver *logger)
|
|||||||
}
|
}
|
||||||
|
|
||||||
assert(errorCode == 0);
|
assert(errorCode == 0);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
class GpGLObject
|
class GpGLObject
|
||||||
@@ -725,17 +674,18 @@ public:
|
|||||||
explicit GpDisplayDriver_SDL_GL2(const GpDisplayDriverProperties &properties);
|
explicit GpDisplayDriver_SDL_GL2(const GpDisplayDriverProperties &properties);
|
||||||
~GpDisplayDriver_SDL_GL2();
|
~GpDisplayDriver_SDL_GL2();
|
||||||
|
|
||||||
bool Init();
|
bool Init() GP_ASYNCIFY_PARANOID_OVERRIDE;
|
||||||
|
void ServeTicks(int tickCount) GP_ASYNCIFY_PARANOID_OVERRIDE;
|
||||||
|
void ForceSync() override;
|
||||||
|
void Shutdown() GP_ASYNCIFY_PARANOID_OVERRIDE;
|
||||||
|
|
||||||
void TranslateSDLMessage(const SDL_Event *msg, IGpVOSEventQueue *eventQueue, float pixelScaleX, float pixelScaleY, bool obstructiveTextInput);
|
void TranslateSDLMessage(const SDL_Event *msg, IGpVOSEventQueue *eventQueue, float pixelScaleX, float pixelScaleY, bool obstructiveTextInput);
|
||||||
|
|
||||||
void Run() override;
|
void GetInitialDisplayResolution(unsigned int *width, unsigned int *height) override;
|
||||||
void Shutdown() override;
|
|
||||||
void GetDisplayResolution(unsigned int *width, unsigned int *height) override;
|
|
||||||
IGpDisplayDriverSurface *CreateSurface(size_t width, size_t height, size_t pitch, GpPixelFormat_t pixelFormat, SurfaceInvalidateCallback_t invalidateCallback, void *invalidateContext) override;
|
IGpDisplayDriverSurface *CreateSurface(size_t width, size_t height, size_t pitch, GpPixelFormat_t pixelFormat, SurfaceInvalidateCallback_t invalidateCallback, void *invalidateContext) override;
|
||||||
void DrawSurface(IGpDisplayDriverSurface *surface, int32_t x, int32_t y, size_t width, size_t height, const GpDisplayDriverSurfaceEffects *effects) override;
|
void DrawSurface(IGpDisplayDriverSurface *surface, int32_t x, int32_t y, size_t width, size_t height, const GpDisplayDriverSurfaceEffects *effects) override;
|
||||||
IGpCursor *CreateBWCursor(size_t width, size_t height, const void *pixelData, const void *maskData, size_t hotSpotX, size_t hotSpotY) override;
|
IGpCursor *CreateBWCursor(size_t width, size_t height, const void *pixelData, const void *maskData, size_t hotSpotX, size_t hotSpotY) GP_ASYNCIFY_PARANOID_OVERRIDE;
|
||||||
IGpCursor *CreateColorCursor(size_t width, size_t height, const void *pixelDataRGBA, size_t hotSpotX, size_t hotSpotY) override;
|
IGpCursor *CreateColorCursor(size_t width, size_t height, const void *pixelDataRGBA, size_t hotSpotX, size_t hotSpotY) GP_ASYNCIFY_PARANOID_OVERRIDE;
|
||||||
void SetCursor(IGpCursor *cursor) override;
|
void SetCursor(IGpCursor *cursor) override;
|
||||||
void SetStandardCursor(EGpStandardCursor_t standardCursor) override;
|
void SetStandardCursor(EGpStandardCursor_t standardCursor) override;
|
||||||
void UpdatePalette(const void *paletteData) override;
|
void UpdatePalette(const void *paletteData) override;
|
||||||
@@ -793,7 +743,7 @@ private:
|
|||||||
|
|
||||||
void ScaleVirtualScreen();
|
void ScaleVirtualScreen();
|
||||||
|
|
||||||
GpDisplayDriverTickStatus_t PresentFrameAndSync();
|
bool SyncRender();
|
||||||
|
|
||||||
GpGLFunctions m_gl;
|
GpGLFunctions m_gl;
|
||||||
GpDisplayDriverProperties m_properties;
|
GpDisplayDriverProperties m_properties;
|
||||||
@@ -835,9 +785,6 @@ private:
|
|||||||
GpComPtr<GpGLRenderTargetView> m_upscaleTextureRTV;
|
GpComPtr<GpGLRenderTargetView> m_upscaleTextureRTV;
|
||||||
GpComPtr<GpGLTexture> m_upscaleTexture;
|
GpComPtr<GpGLTexture> m_upscaleTexture;
|
||||||
|
|
||||||
uint32_t m_upscaleTextureWidth;
|
|
||||||
uint32_t m_upscaleTextureHeight;
|
|
||||||
|
|
||||||
GpComPtr<GpGLVertexArray> m_quadVertexArray;
|
GpComPtr<GpGLVertexArray> m_quadVertexArray;
|
||||||
GpComPtr<GpGLBuffer> m_quadVertexBufferKeepalive;
|
GpComPtr<GpGLBuffer> m_quadVertexBufferKeepalive;
|
||||||
GpComPtr<GpGLBuffer> m_quadIndexBuffer;
|
GpComPtr<GpGLBuffer> m_quadIndexBuffer;
|
||||||
@@ -849,12 +796,16 @@ private:
|
|||||||
|
|
||||||
DrawQuadProgram m_drawQuadPaletteNoFlickerProgram;
|
DrawQuadProgram m_drawQuadPaletteNoFlickerProgram;
|
||||||
DrawQuadProgram m_drawQuadPaletteFlickerProgram;
|
DrawQuadProgram m_drawQuadPaletteFlickerProgram;
|
||||||
DrawQuadProgram m_drawQuadRGBProgram;
|
DrawQuadProgram m_drawQuad15NoFlickerProgram;
|
||||||
DrawQuadProgram m_drawQuad15BitProgram;
|
DrawQuadProgram m_drawQuad15FlickerProgram;
|
||||||
|
DrawQuadProgram m_drawQuad32NoFlickerProgram;
|
||||||
|
DrawQuadProgram m_drawQuad32FlickerProgram;
|
||||||
DrawQuadProgram m_drawQuadPaletteICCNoFlickerProgram;
|
DrawQuadProgram m_drawQuadPaletteICCNoFlickerProgram;
|
||||||
DrawQuadProgram m_drawQuadPaletteICCFlickerProgram;
|
DrawQuadProgram m_drawQuadPaletteICCFlickerProgram;
|
||||||
DrawQuadProgram m_drawQuadRGBICCProgram;
|
DrawQuadProgram m_drawQuad15ICCNoFlickerProgram;
|
||||||
DrawQuadProgram m_drawQuad15BitICCProgram;
|
DrawQuadProgram m_drawQuad15ICCFlickerProgram;
|
||||||
|
DrawQuadProgram m_drawQuad32ICCNoFlickerProgram;
|
||||||
|
DrawQuadProgram m_drawQuad32ICCFlickerProgram;
|
||||||
};
|
};
|
||||||
|
|
||||||
InstancedResources m_res;
|
InstancedResources m_res;
|
||||||
@@ -886,9 +837,14 @@ private:
|
|||||||
uint32_t m_windowHeightPhysical;
|
uint32_t m_windowHeightPhysical;
|
||||||
uint32_t m_windowWidthVirtual; // Virtual resolution is the resolution reported to the game
|
uint32_t m_windowWidthVirtual; // Virtual resolution is the resolution reported to the game
|
||||||
uint32_t m_windowHeightVirtual;
|
uint32_t m_windowHeightVirtual;
|
||||||
|
uint32_t m_initialWidthVirtual; // Virtual resolution is the resolution reported to the game
|
||||||
|
uint32_t m_initialHeightVirtual;
|
||||||
float m_pixelScaleX;
|
float m_pixelScaleX;
|
||||||
float m_pixelScaleY;
|
float m_pixelScaleY;
|
||||||
|
|
||||||
bool m_useUpscaleFilter;
|
bool m_useUpscaleFilter;
|
||||||
|
uint32_t m_upscaleTextureWidth;
|
||||||
|
uint32_t m_upscaleTextureHeight;
|
||||||
|
|
||||||
GpCursor_SDL2 *m_activeCursor;
|
GpCursor_SDL2 *m_activeCursor;
|
||||||
GpCursor_SDL2 *m_pendingCursor;
|
GpCursor_SDL2 *m_pendingCursor;
|
||||||
@@ -896,9 +852,6 @@ private:
|
|||||||
EGpStandardCursor_t m_pendingStandardCursor;
|
EGpStandardCursor_t m_pendingStandardCursor;
|
||||||
bool m_mouseIsInClientArea;
|
bool m_mouseIsInClientArea;
|
||||||
|
|
||||||
IGpFiber *m_vosFiber;
|
|
||||||
PortabilityLayer::HostThreadEvent *m_vosEvent;
|
|
||||||
|
|
||||||
float m_bgColor[4];
|
float m_bgColor[4];
|
||||||
bool m_bgIsDark;
|
bool m_bgIsDark;
|
||||||
|
|
||||||
@@ -1178,11 +1131,13 @@ GpDisplayDriver_SDL_GL2::GpDisplayDriver_SDL_GL2(const GpDisplayDriverProperties
|
|||||||
, m_windowHeightPhysical(480)
|
, m_windowHeightPhysical(480)
|
||||||
, m_windowWidthVirtual(640)
|
, m_windowWidthVirtual(640)
|
||||||
, m_windowHeightVirtual(480)
|
, m_windowHeightVirtual(480)
|
||||||
|
, m_initialWidthVirtual(640)
|
||||||
|
, m_initialHeightVirtual(480)
|
||||||
, m_pixelScaleX(1.0f)
|
, m_pixelScaleX(1.0f)
|
||||||
, m_pixelScaleY(1.0f)
|
, m_pixelScaleY(1.0f)
|
||||||
, m_useUpscaleFilter(false)
|
, m_useUpscaleFilter(false)
|
||||||
, m_vosFiber(nullptr)
|
, m_upscaleTextureWidth(0)
|
||||||
, m_vosEvent(nullptr)
|
, m_upscaleTextureHeight(0)
|
||||||
, m_pendingCursor(nullptr)
|
, m_pendingCursor(nullptr)
|
||||||
, m_activeCursor(nullptr)
|
, m_activeCursor(nullptr)
|
||||||
, m_currentStandardCursor(EGpStandardCursors::kArrow)
|
, m_currentStandardCursor(EGpStandardCursors::kArrow)
|
||||||
@@ -1215,7 +1170,7 @@ GpDisplayDriver_SDL_GL2::GpDisplayDriver_SDL_GL2(const GpDisplayDriverProperties
|
|||||||
m_bgColor[3] = 1.f;
|
m_bgColor[3] = 1.f;
|
||||||
|
|
||||||
// Stupid hack to detect mobile...
|
// Stupid hack to detect mobile...
|
||||||
m_isFullScreenDesired = m_properties.m_systemServices->IsTouchscreen() && !m_properties.m_systemServices->IsUsingMouseAsTouch();
|
m_isFullScreenDesired = m_properties.m_systemServices->IsFullscreenOnStartup();
|
||||||
|
|
||||||
const intmax_t periodNum = std::chrono::high_resolution_clock::period::num;
|
const intmax_t periodNum = std::chrono::high_resolution_clock::period::num;
|
||||||
const intmax_t periodDen = std::chrono::high_resolution_clock::period::den;
|
const intmax_t periodDen = std::chrono::high_resolution_clock::period::den;
|
||||||
@@ -1327,9 +1282,246 @@ GpDisplayDriver_SDL_GL2::~GpDisplayDriver_SDL_GL2()
|
|||||||
|
|
||||||
bool GpDisplayDriver_SDL_GL2::Init()
|
bool GpDisplayDriver_SDL_GL2::Init()
|
||||||
{
|
{
|
||||||
|
#if GP_GL_IS_OPENGL_4_CONTEXT
|
||||||
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4);
|
||||||
|
#else
|
||||||
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
|
||||||
|
#endif
|
||||||
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
|
||||||
|
|
||||||
|
IGpLogDriver *logger = m_properties.m_logger;
|
||||||
|
|
||||||
|
uint32_t windowFlags = SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN;
|
||||||
|
if (m_properties.m_systemServices->IsFullscreenOnStartup())
|
||||||
|
{
|
||||||
|
windowFlags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
|
||||||
|
m_isFullScreen = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
windowFlags |= SDL_WINDOW_RESIZABLE;
|
||||||
|
|
||||||
|
m_window = SDL_CreateWindow(GP_APPLICATION_NAME, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, m_windowWidthPhysical, m_windowHeightPhysical, windowFlags);
|
||||||
|
|
||||||
|
if (m_isFullScreen)
|
||||||
|
{
|
||||||
|
m_windowModeRevertWidth = m_windowWidthPhysical;
|
||||||
|
m_windowModeRevertHeight = m_windowHeightPhysical;
|
||||||
|
|
||||||
|
int windowWidth = 0;
|
||||||
|
int windowHeight = 0;
|
||||||
|
SDL_GetWindowSize(m_window, &windowWidth, &windowHeight);
|
||||||
|
|
||||||
|
if (logger)
|
||||||
|
logger->Printf(IGpLogDriver::Category_Information, "Initialized fullscreen SDL window %i x %i", windowWidth, windowHeight);
|
||||||
|
|
||||||
|
m_windowWidthPhysical = windowWidth;
|
||||||
|
m_windowHeightPhysical = windowHeight;
|
||||||
|
|
||||||
|
uint32_t desiredWidth = windowWidth;
|
||||||
|
uint32_t desiredHeight = windowHeight;
|
||||||
|
uint32_t virtualWidth = m_windowWidthVirtual;
|
||||||
|
uint32_t virtualHeight = m_windowHeightVirtual;
|
||||||
|
float pixelScaleX = m_pixelScaleX;
|
||||||
|
float pixelScaleY = m_pixelScaleY;
|
||||||
|
|
||||||
|
if (m_properties.m_adjustRequestedResolutionFunc(m_properties.m_adjustRequestedResolutionFuncContext, desiredWidth, desiredHeight, virtualWidth, virtualHeight, pixelScaleX, pixelScaleY))
|
||||||
|
{
|
||||||
|
m_windowWidthVirtual = virtualWidth;
|
||||||
|
m_windowHeightVirtual = virtualHeight;
|
||||||
|
m_pixelScaleX = pixelScaleX;
|
||||||
|
m_pixelScaleY = pixelScaleY;
|
||||||
|
|
||||||
|
if (logger)
|
||||||
|
logger->Printf(IGpLogDriver::Category_Information, "AdjustedRequestedResolution succeeded. Virtual dimensions %i x %i Pixel scale %f x %f", static_cast<int>(virtualWidth), static_cast<int>(virtualHeight), static_cast<float>(pixelScaleX), static_cast<float>(pixelScaleY));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (logger)
|
||||||
|
logger->Printf(IGpLogDriver::Category_Error, "AdjustedRequestedResolution failed!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const bool obstructiveTextInput = m_properties.m_systemServices->IsTextInputObstructive();
|
||||||
|
|
||||||
|
if (!obstructiveTextInput)
|
||||||
|
SDL_StartTextInput();
|
||||||
|
|
||||||
|
StartOpenGLForWindow(logger);
|
||||||
|
|
||||||
|
if (!m_gl.LookUpFunctions())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
m_initialWidthVirtual = m_windowWidthVirtual;
|
||||||
|
m_initialHeightVirtual = m_windowHeightVirtual;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GpDisplayDriver_SDL_GL2::ServeTicks(int ticks)
|
||||||
|
{
|
||||||
|
IGpLogDriver *logger = m_properties.m_logger;
|
||||||
|
const bool obstructiveTextInput = m_properties.m_systemServices->IsTextInputObstructive();
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
SDL_Event msg;
|
||||||
|
if (SDL_PollEvent(&msg) != 0)
|
||||||
|
{
|
||||||
|
switch (msg.type)
|
||||||
|
{
|
||||||
|
case SDL_MOUSEMOTION:
|
||||||
|
{
|
||||||
|
if (!m_mouseIsInClientArea)
|
||||||
|
m_mouseIsInClientArea = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
//case SDL_MOUSELEAVE: // Does SDL support this??
|
||||||
|
// m_mouseIsInClientArea = false;
|
||||||
|
// break;
|
||||||
|
case SDL_RENDER_DEVICE_RESET:
|
||||||
|
case SDL_RENDER_TARGETS_RESET:
|
||||||
|
{
|
||||||
|
if (logger)
|
||||||
|
logger->Printf(IGpLogDriver::Category_Information, "Triggering GL context reset due to device loss (Type: %i)", static_cast<int>(msg.type));
|
||||||
|
|
||||||
|
m_contextLost = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SDL_CONTROLLERAXISMOTION:
|
||||||
|
case SDL_CONTROLLERBUTTONDOWN:
|
||||||
|
case SDL_CONTROLLERBUTTONUP:
|
||||||
|
case SDL_CONTROLLERDEVICEADDED:
|
||||||
|
case SDL_CONTROLLERDEVICEREMOVED:
|
||||||
|
case SDL_CONTROLLERDEVICEREMAPPED:
|
||||||
|
if (IGpInputDriverSDLGamepad *gamepadDriver = IGpInputDriverSDLGamepad::GetInstance())
|
||||||
|
gamepadDriver->ProcessSDLEvent(msg);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
TranslateSDLMessage(&msg, m_properties.m_eventQueue, m_pixelScaleX, m_pixelScaleY, obstructiveTextInput);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (m_isFullScreen != m_isFullScreenDesired)
|
||||||
|
{
|
||||||
|
if (m_isFullScreenDesired)
|
||||||
|
BecomeFullScreen();
|
||||||
|
else
|
||||||
|
BecomeWindowed();
|
||||||
|
|
||||||
|
if (logger)
|
||||||
|
logger->Printf(IGpLogDriver::Category_Information, "Triggering GL context reset due to fullscreen state change");
|
||||||
|
|
||||||
|
m_contextLost = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
int clientWidth = 0;
|
||||||
|
int clientHeight = 0;
|
||||||
|
SDL_GetWindowSize(m_window, &clientWidth, &clientHeight);
|
||||||
|
|
||||||
|
unsigned int desiredWidth = clientWidth;
|
||||||
|
unsigned int desiredHeight = clientHeight;
|
||||||
|
if (desiredWidth != m_windowWidthPhysical || desiredHeight != m_windowHeightPhysical || m_isResolutionResetDesired)
|
||||||
|
{
|
||||||
|
if (logger)
|
||||||
|
logger->Printf(IGpLogDriver::Category_Information, "Detected window size change");
|
||||||
|
|
||||||
|
uint32_t prevWidthPhysical = m_windowWidthPhysical;
|
||||||
|
uint32_t prevHeightPhysical = m_windowHeightPhysical;
|
||||||
|
uint32_t prevWidthVirtual = m_windowWidthVirtual;
|
||||||
|
uint32_t prevHeightVirtual = m_windowHeightVirtual;
|
||||||
|
uint32_t virtualWidth = m_windowWidthVirtual;
|
||||||
|
uint32_t virtualHeight = m_windowHeightVirtual;
|
||||||
|
float pixelScaleX = 1.0f;
|
||||||
|
float pixelScaleY = 1.0f;
|
||||||
|
|
||||||
|
if (m_properties.m_adjustRequestedResolutionFunc(m_properties.m_adjustRequestedResolutionFuncContext, desiredWidth, desiredHeight, virtualWidth, virtualHeight, pixelScaleX, pixelScaleY))
|
||||||
|
{
|
||||||
|
bool resizedOK = ResizeOpenGLWindow(m_windowWidthPhysical, m_windowHeightPhysical, desiredWidth, desiredHeight, logger);
|
||||||
|
|
||||||
|
if (!resizedOK)
|
||||||
|
break; // Critical video driver error, exit
|
||||||
|
|
||||||
|
m_windowWidthVirtual = virtualWidth;
|
||||||
|
m_windowHeightVirtual = virtualHeight;
|
||||||
|
m_pixelScaleX = pixelScaleX;
|
||||||
|
m_pixelScaleY = pixelScaleY;
|
||||||
|
m_isResolutionResetDesired = false;
|
||||||
|
|
||||||
|
if (GpVOSEvent *resizeEvent = m_properties.m_eventQueue->QueueEvent())
|
||||||
|
{
|
||||||
|
resizeEvent->m_eventType = GpVOSEventTypes::kVideoResolutionChanged;
|
||||||
|
resizeEvent->m_event.m_resolutionChangedEvent.m_prevWidth = prevWidthVirtual;
|
||||||
|
resizeEvent->m_event.m_resolutionChangedEvent.m_prevHeight = prevHeightVirtual;
|
||||||
|
resizeEvent->m_event.m_resolutionChangedEvent.m_newWidth = m_windowWidthVirtual;
|
||||||
|
resizeEvent->m_event.m_resolutionChangedEvent.m_newHeight = m_windowHeightVirtual;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (logger)
|
||||||
|
logger->Printf(IGpLogDriver::Category_Information, "Triggering GL context reset due to window size change");
|
||||||
|
|
||||||
|
m_contextLost = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_contextLost)
|
||||||
|
{
|
||||||
|
if (logger)
|
||||||
|
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();
|
||||||
|
|
||||||
|
if (m_firstSurface)
|
||||||
|
m_firstSurface->DestroyAll();
|
||||||
|
|
||||||
|
if (!InitResources(m_windowWidthPhysical, m_windowHeightPhysical, m_windowWidthVirtual, m_windowHeightVirtual))
|
||||||
|
{
|
||||||
|
if (logger)
|
||||||
|
logger->Printf(IGpLogDriver::Category_Information, "Terminating display driver due to InitResources failing");
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_firstSurface)
|
||||||
|
m_firstSurface->RecreateAll();
|
||||||
|
|
||||||
|
m_contextLost = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool wantTextInput = m_properties.m_systemServices->IsTextInputEnabled();
|
||||||
|
if (wantTextInput != m_textInputEnabled)
|
||||||
|
{
|
||||||
|
m_textInputEnabled = wantTextInput;
|
||||||
|
if (m_textInputEnabled)
|
||||||
|
SDL_StartTextInput();
|
||||||
|
else
|
||||||
|
SDL_StopTextInput();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle dismissal of on-screen keyboard
|
||||||
|
const bool isTextInputActuallyActive = SDL_IsTextInputActive();
|
||||||
|
m_textInputEnabled = isTextInputActuallyActive;
|
||||||
|
m_properties.m_systemServices->SetTextInputEnabled(isTextInputActuallyActive);
|
||||||
|
|
||||||
|
if (SyncRender())
|
||||||
|
{
|
||||||
|
ticks--;
|
||||||
|
if (ticks <= 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GpDisplayDriver_SDL_GL2::ForceSync()
|
||||||
|
{
|
||||||
|
m_frameTimeAccumulated = std::chrono::nanoseconds::zero();
|
||||||
|
}
|
||||||
|
|
||||||
static void PostMouseEvent(IGpVOSEventQueue *eventQueue, GpMouseEventType_t eventType, GpMouseButton_t button, int32_t x, int32_t y, float pixelScaleX, float pixelScaleY)
|
static void PostMouseEvent(IGpVOSEventQueue *eventQueue, GpMouseEventType_t eventType, GpMouseButton_t button, int32_t x, int32_t y, float pixelScaleX, float pixelScaleY)
|
||||||
{
|
{
|
||||||
if (GpVOSEvent *evt = eventQueue->QueueEvent())
|
if (GpVOSEvent *evt = eventQueue->QueueEvent())
|
||||||
@@ -1367,7 +1559,7 @@ static void PostTouchEvent(IGpVOSEventQueue *eventQueue, GpTouchEventType_t even
|
|||||||
|
|
||||||
static bool IdentifyVKey(const SDL_KeyboardEvent *keyEvt, GpKeyIDSubset_t &outSubset, GpKeyboardInputEvent::KeyUnion &outKey)
|
static bool IdentifyVKey(const SDL_KeyboardEvent *keyEvt, GpKeyIDSubset_t &outSubset, GpKeyboardInputEvent::KeyUnion &outKey)
|
||||||
{
|
{
|
||||||
SDL_KeyCode keyCode = static_cast<SDL_KeyCode>(keyEvt->keysym.sym);
|
SDL_Keycode keyCode = static_cast<SDL_Keycode>(keyEvt->keysym.sym);
|
||||||
|
|
||||||
switch (keyCode)
|
switch (keyCode)
|
||||||
{
|
{
|
||||||
@@ -1445,6 +1637,14 @@ static bool IdentifyVKey(const SDL_KeyboardEvent *keyEvt, GpKeyIDSubset_t &outSu
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
break;
|
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:
|
case SDLK_LCTRL:
|
||||||
outSubset = GpKeyIDSubsets::kSpecial;
|
outSubset = GpKeyIDSubsets::kSpecial;
|
||||||
outKey.m_specialKey = GpKeySpecials::kLeftCtrl;
|
outKey.m_specialKey = GpKeySpecials::kLeftCtrl;
|
||||||
@@ -1788,7 +1988,7 @@ void GpDisplayDriver_SDL_GL2::TranslateSDLMessage(const SDL_Event *msg, IGpVOSEv
|
|||||||
{
|
{
|
||||||
uint32_t codePoint;
|
uint32_t codePoint;
|
||||||
size_t numDigested;
|
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;
|
parseOffset += numDigested;
|
||||||
|
|
||||||
@@ -1823,242 +2023,19 @@ void GpDisplayDriver_SDL_GL2::TranslateSDLMessage(const SDL_Event *msg, IGpVOSEv
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GpDisplayDriver_SDL_GL2::Run()
|
|
||||||
{
|
|
||||||
#if GP_GL_IS_OPENGL_4_CONTEXT
|
|
||||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4);
|
|
||||||
#else
|
|
||||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
|
|
||||||
#endif
|
|
||||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
|
|
||||||
|
|
||||||
IGpLogDriver *logger = m_properties.m_logger;
|
|
||||||
|
|
||||||
m_vosEvent = m_properties.m_systemServices->CreateThreadEvent(true, false);
|
|
||||||
m_vosFiber = new GpFiber_SDL(nullptr, m_vosEvent);
|
|
||||||
|
|
||||||
uint32_t windowFlags = SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN;
|
|
||||||
if (m_isFullScreenDesired)
|
|
||||||
{
|
|
||||||
windowFlags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
|
|
||||||
m_isFullScreen = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
windowFlags |= SDL_WINDOW_RESIZABLE;
|
|
||||||
|
|
||||||
m_window = SDL_CreateWindow(GP_APPLICATION_NAME, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, m_windowWidthPhysical, m_windowHeightPhysical, windowFlags);
|
|
||||||
|
|
||||||
if (m_isFullScreen)
|
|
||||||
{
|
|
||||||
m_windowModeRevertWidth = m_windowWidthPhysical;
|
|
||||||
m_windowModeRevertHeight = m_windowHeightPhysical;
|
|
||||||
|
|
||||||
int windowWidth = 0;
|
|
||||||
int windowHeight = 0;
|
|
||||||
SDL_GetWindowSize(m_window, &windowWidth, &windowHeight);
|
|
||||||
|
|
||||||
if (logger)
|
|
||||||
logger->Printf(IGpLogDriver::Category_Information, "Initialized fullscreen SDL window %i x %i", windowWidth, windowHeight);
|
|
||||||
|
|
||||||
m_windowWidthPhysical = windowWidth;
|
|
||||||
m_windowHeightPhysical = windowHeight;
|
|
||||||
|
|
||||||
uint32_t desiredWidth = windowWidth;
|
|
||||||
uint32_t desiredHeight = windowHeight;
|
|
||||||
uint32_t virtualWidth = m_windowWidthVirtual;
|
|
||||||
uint32_t virtualHeight = m_windowHeightVirtual;
|
|
||||||
float pixelScaleX = m_pixelScaleX;
|
|
||||||
float pixelScaleY = m_pixelScaleY;
|
|
||||||
|
|
||||||
if (m_properties.m_adjustRequestedResolutionFunc(m_properties.m_adjustRequestedResolutionFuncContext, desiredWidth, desiredHeight, virtualWidth, virtualHeight, pixelScaleX, pixelScaleY))
|
|
||||||
{
|
|
||||||
m_windowWidthVirtual = virtualWidth;
|
|
||||||
m_windowHeightVirtual = virtualHeight;
|
|
||||||
m_pixelScaleX = pixelScaleX;
|
|
||||||
m_pixelScaleY = pixelScaleY;
|
|
||||||
|
|
||||||
if (logger)
|
|
||||||
logger->Printf(IGpLogDriver::Category_Information, "AdjustedRequestedResolution succeeded. Virtual dimensions %i x %i Pixel scale %f x %f", static_cast<int>(virtualWidth), static_cast<int>(virtualHeight), static_cast<float>(pixelScaleX), static_cast<float>(pixelScaleY));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (logger)
|
|
||||||
logger->Printf(IGpLogDriver::Category_Error, "AdjustedRequestedResolution failed!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const bool obstructiveTextInput = m_properties.m_systemServices->IsTextInputObstructive();
|
|
||||||
|
|
||||||
if (!obstructiveTextInput)
|
|
||||||
SDL_StartTextInput();
|
|
||||||
|
|
||||||
StartOpenGLForWindow(logger);
|
|
||||||
|
|
||||||
if (!m_gl.LookUpFunctions())
|
|
||||||
return;
|
|
||||||
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
SDL_Event msg;
|
|
||||||
if (SDL_PollEvent(&msg) != 0)
|
|
||||||
{
|
|
||||||
if (msg.type == SDL_MOUSEMOTION)
|
|
||||||
{
|
|
||||||
if (!m_mouseIsInClientArea)
|
|
||||||
m_mouseIsInClientArea = true;
|
|
||||||
}
|
|
||||||
//else if (msg.type == SDL_MOUSELEAVE) // Does SDL support this??
|
|
||||||
// m_mouseIsInClientArea = false;
|
|
||||||
else if (msg.type == SDL_RENDER_DEVICE_RESET || msg.type == SDL_RENDER_TARGETS_RESET)
|
|
||||||
{
|
|
||||||
if (logger)
|
|
||||||
logger->Printf(IGpLogDriver::Category_Information, "Triggering GL context reset due to device loss (Type: %i)", static_cast<int>(msg.type));
|
|
||||||
|
|
||||||
m_contextLost = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
TranslateSDLMessage(&msg, m_properties.m_eventQueue, m_pixelScaleX, m_pixelScaleY, obstructiveTextInput);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (m_isFullScreen != m_isFullScreenDesired)
|
|
||||||
{
|
|
||||||
if (m_isFullScreenDesired)
|
|
||||||
BecomeFullScreen();
|
|
||||||
else
|
|
||||||
BecomeWindowed();
|
|
||||||
|
|
||||||
if (logger)
|
|
||||||
logger->Printf(IGpLogDriver::Category_Information, "Triggering GL context reset due to fullscreen state change");
|
|
||||||
|
|
||||||
m_contextLost = true;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
int clientWidth = 0;
|
|
||||||
int clientHeight = 0;
|
|
||||||
SDL_GetWindowSize(m_window, &clientWidth, &clientHeight);
|
|
||||||
|
|
||||||
unsigned int desiredWidth = clientWidth;
|
|
||||||
unsigned int desiredHeight = clientHeight;
|
|
||||||
if (desiredWidth != m_windowWidthPhysical || desiredHeight != m_windowHeightPhysical || m_isResolutionResetDesired)
|
|
||||||
{
|
|
||||||
if (logger)
|
|
||||||
logger->Printf(IGpLogDriver::Category_Information, "Detected window size change");
|
|
||||||
|
|
||||||
uint32_t prevWidthPhysical = m_windowWidthPhysical;
|
|
||||||
uint32_t prevHeightPhysical = m_windowHeightPhysical;
|
|
||||||
uint32_t prevWidthVirtual = m_windowWidthVirtual;
|
|
||||||
uint32_t prevHeightVirtual = m_windowHeightVirtual;
|
|
||||||
uint32_t virtualWidth = m_windowWidthVirtual;
|
|
||||||
uint32_t virtualHeight = m_windowHeightVirtual;
|
|
||||||
float pixelScaleX = 1.0f;
|
|
||||||
float pixelScaleY = 1.0f;
|
|
||||||
|
|
||||||
if (m_properties.m_adjustRequestedResolutionFunc(m_properties.m_adjustRequestedResolutionFuncContext, desiredWidth, desiredHeight, virtualWidth, virtualHeight, pixelScaleX, pixelScaleY))
|
|
||||||
{
|
|
||||||
bool resizedOK = ResizeOpenGLWindow(m_windowWidthPhysical, m_windowHeightPhysical, desiredWidth, desiredHeight, logger);
|
|
||||||
|
|
||||||
if (!resizedOK)
|
|
||||||
break; // Critical video driver error, exit
|
|
||||||
|
|
||||||
m_windowWidthVirtual = virtualWidth;
|
|
||||||
m_windowHeightVirtual = virtualHeight;
|
|
||||||
m_pixelScaleX = pixelScaleX;
|
|
||||||
m_pixelScaleY = pixelScaleY;
|
|
||||||
m_isResolutionResetDesired = false;
|
|
||||||
|
|
||||||
if (GpVOSEvent *resizeEvent = m_properties.m_eventQueue->QueueEvent())
|
|
||||||
{
|
|
||||||
resizeEvent->m_eventType = GpVOSEventTypes::kVideoResolutionChanged;
|
|
||||||
resizeEvent->m_event.m_resolutionChangedEvent.m_prevWidth = prevWidthVirtual;
|
|
||||||
resizeEvent->m_event.m_resolutionChangedEvent.m_prevHeight = prevHeightVirtual;
|
|
||||||
resizeEvent->m_event.m_resolutionChangedEvent.m_newWidth = m_windowWidthVirtual;
|
|
||||||
resizeEvent->m_event.m_resolutionChangedEvent.m_newHeight = m_windowHeightVirtual;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (logger)
|
|
||||||
logger->Printf(IGpLogDriver::Category_Information, "Triggering GL context reset due to window size change");
|
|
||||||
|
|
||||||
m_contextLost = true;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_contextLost)
|
|
||||||
{
|
|
||||||
if (logger)
|
|
||||||
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();
|
|
||||||
|
|
||||||
if (m_firstSurface)
|
|
||||||
m_firstSurface->DestroyAll();
|
|
||||||
|
|
||||||
if (!InitResources(m_windowWidthPhysical, m_windowHeightPhysical, m_windowWidthVirtual, m_windowHeightVirtual))
|
|
||||||
{
|
|
||||||
if (logger)
|
|
||||||
logger->Printf(IGpLogDriver::Category_Information, "Terminating display driver due to InitResources failing");
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_firstSurface)
|
|
||||||
m_firstSurface->RecreateAll();
|
|
||||||
|
|
||||||
m_contextLost = false;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool wantTextInput = m_properties.m_systemServices->IsTextInputEnabled();
|
|
||||||
if (wantTextInput != m_textInputEnabled)
|
|
||||||
{
|
|
||||||
m_textInputEnabled = wantTextInput;
|
|
||||||
if (m_textInputEnabled)
|
|
||||||
SDL_StartTextInput();
|
|
||||||
else
|
|
||||||
SDL_StopTextInput();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle dismissal of on-screen keyboard
|
|
||||||
const bool isTextInputActuallyActive = SDL_IsTextInputActive();
|
|
||||||
m_textInputEnabled = isTextInputActuallyActive;
|
|
||||||
m_properties.m_systemServices->SetTextInputEnabled(isTextInputActuallyActive);
|
|
||||||
|
|
||||||
GpDisplayDriverTickStatus_t tickStatus = PresentFrameAndSync();
|
|
||||||
if (tickStatus == GpDisplayDriverTickStatuses::kFatalFault || tickStatus == GpDisplayDriverTickStatuses::kApplicationTerminated)
|
|
||||||
{
|
|
||||||
if (logger)
|
|
||||||
{
|
|
||||||
if (tickStatus == GpDisplayDriverTickStatuses::kFatalFault)
|
|
||||||
logger->Printf(IGpLogDriver::Category_Information, "Terminating display driver due to fatal fault");
|
|
||||||
if (tickStatus == GpDisplayDriverTickStatuses::kApplicationTerminated)
|
|
||||||
logger->Printf(IGpLogDriver::Category_Information, "Terminating display driver due to application termination");
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Exit
|
|
||||||
}
|
|
||||||
|
|
||||||
void GpDisplayDriver_SDL_GL2::Shutdown()
|
void GpDisplayDriver_SDL_GL2::Shutdown()
|
||||||
{
|
{
|
||||||
this->~GpDisplayDriver_SDL_GL2();
|
this->~GpDisplayDriver_SDL_GL2();
|
||||||
free(this);
|
free(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GpDisplayDriver_SDL_GL2::GetDisplayResolution(unsigned int *width, unsigned int *height)
|
void GpDisplayDriver_SDL_GL2::GetInitialDisplayResolution(unsigned int *width, unsigned int *height)
|
||||||
{
|
{
|
||||||
if (width)
|
if (width)
|
||||||
*width = m_windowWidthVirtual;
|
*width = m_initialWidthVirtual;
|
||||||
|
|
||||||
if (height)
|
if (height)
|
||||||
*height = m_windowHeightVirtual;
|
*height = m_initialHeightVirtual;
|
||||||
}
|
}
|
||||||
|
|
||||||
IGpDisplayDriverSurface *GpDisplayDriver_SDL_GL2::CreateSurface(size_t width, size_t height, size_t pitch, GpPixelFormat_t pixelFormat, SurfaceInvalidateCallback_t invalidateCallback, void *invalidateContext)
|
IGpDisplayDriverSurface *GpDisplayDriver_SDL_GL2::CreateSurface(size_t width, size_t height, size_t pitch, GpPixelFormat_t pixelFormat, SurfaceInvalidateCallback_t invalidateCallback, void *invalidateContext)
|
||||||
@@ -2110,7 +2087,20 @@ void GpDisplayDriver_SDL_GL2::DrawSurface(IGpDisplayDriverSurface *surface, int3
|
|||||||
}
|
}
|
||||||
else if (pixelFormat == GpPixelFormats::kRGB32)
|
else if (pixelFormat == GpPixelFormats::kRGB32)
|
||||||
{
|
{
|
||||||
return;
|
if (m_useICCProfile)
|
||||||
|
{
|
||||||
|
if (effects->m_flicker)
|
||||||
|
program = &m_res.m_drawQuad32ICCFlickerProgram;
|
||||||
|
else
|
||||||
|
program = &m_res.m_drawQuad32ICCNoFlickerProgram;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (effects->m_flicker)
|
||||||
|
program = &m_res.m_drawQuad32FlickerProgram;
|
||||||
|
else
|
||||||
|
program = &m_res.m_drawQuad32NoFlickerProgram;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -2338,11 +2328,19 @@ bool GpDisplayDriver_SDL_GL2::SupportsSizedFormats() const
|
|||||||
|
|
||||||
void GpDisplayDriver_SDL_GL2::ApplyPrefs(const void *identifier, size_t identifierSize, const void *contents, size_t contentsSize, uint32_t version)
|
void GpDisplayDriver_SDL_GL2::ApplyPrefs(const void *identifier, size_t identifierSize, const void *contents, size_t contentsSize, uint32_t version)
|
||||||
{
|
{
|
||||||
|
if (version == kPrefsVersion && identifierSize == strlen(kPrefsIdentifier) && !memcmp(identifier, kPrefsIdentifier, identifierSize))
|
||||||
|
{
|
||||||
|
const GpDisplayDriver_SDL_GL2_Prefs *prefs = static_cast<const GpDisplayDriver_SDL_GL2_Prefs *>(contents);
|
||||||
|
m_isFullScreenDesired = prefs->m_isFullScreen;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GpDisplayDriver_SDL_GL2::SavePrefs(void *context, WritePrefsFunc_t writeFunc)
|
bool GpDisplayDriver_SDL_GL2::SavePrefs(void *context, IGpPrefsHandler::WritePrefsFunc_t writeFunc)
|
||||||
{
|
{
|
||||||
return true;
|
GpDisplayDriver_SDL_GL2_Prefs prefs;
|
||||||
|
prefs.m_isFullScreen = m_isFullScreenDesired;
|
||||||
|
|
||||||
|
return writeFunc(context, kPrefsIdentifier, strlen(kPrefsIdentifier), &prefs, sizeof(prefs), kPrefsVersion);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GpDisplayDriver_SDL_GL2::UnlinkSurface(GpDisplayDriverSurface_GL2 *surface, GpDisplayDriverSurface_GL2 *prev, GpDisplayDriverSurface_GL2 *next)
|
void GpDisplayDriver_SDL_GL2::UnlinkSurface(GpDisplayDriverSurface_GL2 *surface, GpDisplayDriverSurface_GL2 *prev, GpDisplayDriverSurface_GL2 *next)
|
||||||
@@ -2408,9 +2406,6 @@ bool GpDisplayDriver_SDL_GL2::InitResources(uint32_t physicalWidth, uint32_t phy
|
|||||||
if (logger)
|
if (logger)
|
||||||
logger->Printf(IGpLogDriver::Category_Information, "GpDisplayDriver_SDL_GL2::InitResources");
|
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;
|
|
||||||
|
|
||||||
CheckGLError(m_gl, logger);
|
CheckGLError(m_gl, logger);
|
||||||
|
|
||||||
if (!InitBackBuffer(virtualWidth, virtualHeight))
|
if (!InitBackBuffer(virtualWidth, virtualHeight))
|
||||||
@@ -2489,23 +2484,27 @@ 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_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>> 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>> drawQuadPaletteNoFlickerPixelShader = CreateShader<GL_FRAGMENT_SHADER>(GpBinarizedShaders::g_drawQuadPalettePNF_GL2);
|
||||||
//m_drawQuadRGBPixelShader = CreateShader<GL_FRAGMENT_SHADER>(GpBinarizedShaders::g_drawQuadRGBP_GL2);
|
GpComPtr<GpGLShader<GL_FRAGMENT_SHADER>> drawQuad32FlickerPixelShader = CreateShader<GL_FRAGMENT_SHADER>(GpBinarizedShaders::g_drawQuad32PF_GL2);
|
||||||
//m_drawQuad15BitPixelShader = CreateShader<GL_FRAGMENT_SHADER>(GpBinarizedShaders::g_drawQuad15BitP_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>> 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>> drawQuadPaletteICCNFPixelShader = CreateShader<GL_FRAGMENT_SHADER>(GpBinarizedShaders::g_drawQuadPaletteICCPNF_GL2);
|
||||||
//m_drawQuadRGBICCPixelShader = CreateShader<GL_FRAGMENT_SHADER>(GpBinarizedShaders::g_drawQuadRGBICCP_GL2);
|
GpComPtr<GpGLShader<GL_FRAGMENT_SHADER>> drawQuad32ICCFPixelShader = CreateShader<GL_FRAGMENT_SHADER>(GpBinarizedShaders::g_drawQuad32ICCPF_GL2);
|
||||||
//m_drawQuad15BitICCPixelShader = CreateShader<GL_FRAGMENT_SHADER>(GpBinarizedShaders::g_drawQuad15BitICCP_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>> scaleQuadPixelShader = CreateShader<GL_FRAGMENT_SHADER>(GpBinarizedShaders::g_scaleQuadP_GL2);
|
||||||
GpComPtr<GpGLShader<GL_FRAGMENT_SHADER>> copyQuadPixelShader = CreateShader<GL_FRAGMENT_SHADER>(GpBinarizedShaders::g_copyQuadP_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, drawQuadPaletteFlickerPixelShader)
|
if (!m_res.m_drawQuadPaletteFlickerProgram.Link(this, drawQuadVertexShader, drawQuadPaletteFlickerPixelShader) ||
|
||||||
//|| !m_drawQuadRGBProgram.Link(this, drawQuadVertexShader, drawQuadRGBPixelShader)
|
!m_res.m_drawQuadPaletteNoFlickerProgram.Link(this, drawQuadVertexShader, drawQuadPaletteNoFlickerPixelShader)
|
||||||
//|| !m_drawQuad15BitProgram.Link(this, drawQuadVertexShader, drawQuad15BitPixelShader)
|
|| !m_res.m_drawQuad32FlickerProgram.Link(this, drawQuadVertexShader, drawQuad32FlickerPixelShader)
|
||||||
|
|| !m_res.m_drawQuad32NoFlickerProgram.Link(this, drawQuadVertexShader, drawQuad32NoFlickerPixelShader)
|
||||||
|| !m_res.m_drawQuadPaletteICCFlickerProgram.Link(this, drawQuadVertexShader, drawQuadPaletteICCFPixelShader)
|
|| !m_res.m_drawQuadPaletteICCFlickerProgram.Link(this, drawQuadVertexShader, drawQuadPaletteICCFPixelShader)
|
||||||
|| !m_res.m_drawQuadPaletteICCNoFlickerProgram.Link(this, drawQuadVertexShader, drawQuadPaletteICCNFPixelShader)
|
|| !m_res.m_drawQuadPaletteICCNoFlickerProgram.Link(this, drawQuadVertexShader, drawQuadPaletteICCNFPixelShader)
|
||||||
//|| !m_drawQuadRGBICCProgram.Link(this, drawQuadVertexShader, drawQuadRGBICCPixelShader)
|
|| !m_res.m_drawQuad32ICCFlickerProgram.Link(this, drawQuadVertexShader, drawQuad32ICCFPixelShader)
|
||||||
//|| !m_drawQuad15BitICCProgram.Link(this, drawQuadVertexShader, drawQuad15BitICCPixelShader)
|
|| !m_res.m_drawQuad32ICCNoFlickerProgram.Link(this, drawQuadVertexShader, drawQuad32ICCNFPixelShader)
|
||||||
|
|
||||||
|
// || !m_drawQuadRGBICCProgram.Link(this, drawQuadVertexShader, drawQuadRGBICCPixelShader)
|
||||||
|
// || !m_drawQuad15BitICCProgram.Link(this, drawQuadVertexShader, drawQuad15BitICCPixelShader)
|
||||||
|| !m_res.m_scaleQuadProgram.Link(this, drawQuadVertexShader, scaleQuadPixelShader)
|
|| !m_res.m_scaleQuadProgram.Link(this, drawQuadVertexShader, scaleQuadPixelShader)
|
||||||
|| !m_res.m_copyQuadProgram.Link(this, drawQuadVertexShader, copyQuadPixelShader))
|
|| !m_res.m_copyQuadProgram.Link(this, drawQuadVertexShader, copyQuadPixelShader))
|
||||||
return false;
|
return false;
|
||||||
@@ -2720,8 +2719,9 @@ bool GpDisplayDriver_SDL_GL2::InitBackBuffer(uint32_t width, uint32_t height)
|
|||||||
m_gl.BindFramebuffer(GL_FRAMEBUFFER, 0);
|
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 upscaleX = ceil(m_pixelScaleX);
|
||||||
uint32_t upscaleY = ceil(m_pixelScaleY);
|
uint32_t upscaleY = ceil(m_pixelScaleY);
|
||||||
@@ -2736,8 +2736,8 @@ bool GpDisplayDriver_SDL_GL2::InitBackBuffer(uint32_t width, uint32_t height)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_res.m_upscaleTextureWidth = width * upscaleX;
|
m_upscaleTextureWidth = width * upscaleX;
|
||||||
m_res.m_upscaleTextureHeight = height * upscaleY;
|
m_upscaleTextureHeight = height * upscaleY;
|
||||||
|
|
||||||
GLenum internalFormat = SupportsSizedFormats() ? GL_RGBA8 : GL_RGBA;
|
GLenum internalFormat = SupportsSizedFormats() ? GL_RGBA8 : GL_RGBA;
|
||||||
|
|
||||||
@@ -2747,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_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_S, GL_CLAMP_TO_EDGE);
|
||||||
m_gl.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, 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);
|
m_gl.BindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
|
||||||
CheckGLError(m_gl, logger);
|
CheckGLError(m_gl, logger);
|
||||||
@@ -2792,7 +2792,7 @@ void GpDisplayDriver_SDL_GL2::ScaleVirtualScreen()
|
|||||||
{
|
{
|
||||||
m_gl.BindFramebuffer(GL_FRAMEBUFFER, m_res.m_upscaleTextureRTV->GetID());
|
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;
|
const BlitQuadProgram &program = m_res.m_scaleQuadProgram;
|
||||||
|
|
||||||
@@ -2998,8 +2998,15 @@ bool GpDisplayDriver_SDL_GL2::BlitQuadProgram::Link(GpDisplayDriver_SDL_GL2 *dri
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
GpDisplayDriverTickStatus_t GpDisplayDriver_SDL_GL2::PresentFrameAndSync()
|
bool GpDisplayDriver_SDL_GL2::SyncRender()
|
||||||
{
|
{
|
||||||
|
if (m_frameTimeAccumulated >= m_frameTimeSliceSize)
|
||||||
|
{
|
||||||
|
m_frameTimeAccumulated -= m_frameTimeSliceSize;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
SynchronizeCursors();
|
SynchronizeCursors();
|
||||||
|
|
||||||
float bgColor[4];
|
float bgColor[4];
|
||||||
@@ -3031,6 +3038,10 @@ GpDisplayDriverTickStatus_t GpDisplayDriver_SDL_GL2::PresentFrameAndSync()
|
|||||||
|
|
||||||
SDL_GL_SwapWindow(m_window);
|
SDL_GL_SwapWindow(m_window);
|
||||||
|
|
||||||
|
#ifdef __EMSCRIPTEN__
|
||||||
|
emscripten_sleep(1);
|
||||||
|
#endif
|
||||||
|
|
||||||
std::chrono::time_point<std::chrono::high_resolution_clock>::duration syncTime = std::chrono::high_resolution_clock::now().time_since_epoch();
|
std::chrono::time_point<std::chrono::high_resolution_clock>::duration syncTime = std::chrono::high_resolution_clock::now().time_since_epoch();
|
||||||
const intmax_t periodNum = std::chrono::high_resolution_clock::period::num;
|
const intmax_t periodNum = std::chrono::high_resolution_clock::period::num;
|
||||||
const intmax_t periodDen = std::chrono::high_resolution_clock::period::den;
|
const intmax_t periodDen = std::chrono::high_resolution_clock::period::den;
|
||||||
@@ -3121,22 +3132,9 @@ GpDisplayDriverTickStatus_t GpDisplayDriver_SDL_GL2::PresentFrameAndSync()
|
|||||||
}
|
}
|
||||||
|
|
||||||
m_frameTimeAccumulated += frameTimeStep;
|
m_frameTimeAccumulated += frameTimeStep;
|
||||||
while (m_frameTimeAccumulated >= m_frameTimeSliceSize)
|
|
||||||
{
|
|
||||||
GpDisplayDriverTickStatus_t tickStatus = m_properties.m_tickFunc(m_properties.m_tickFuncContext, m_vosFiber);
|
|
||||||
m_frameTimeAccumulated -= m_frameTimeSliceSize;
|
|
||||||
|
|
||||||
if (tickStatus == GpDisplayDriverTickStatuses::kSynchronizing)
|
|
||||||
{
|
|
||||||
m_frameTimeAccumulated = std::chrono::high_resolution_clock::duration::zero();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else if (tickStatus != GpDisplayDriverTickStatuses::kOK)
|
|
||||||
return tickStatus;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return GpDisplayDriverTickStatuses::kOK;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
IGpDisplayDriver *GpDriver_CreateDisplayDriver_SDL_GL2(const GpDisplayDriverProperties &properties)
|
IGpDisplayDriver *GpDriver_CreateDisplayDriver_SDL_GL2(const GpDisplayDriverProperties &properties)
|
||||||
@@ -3145,18 +3143,9 @@ IGpDisplayDriver *GpDriver_CreateDisplayDriver_SDL_GL2(const GpDisplayDriverProp
|
|||||||
if (!driver)
|
if (!driver)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
new (driver) GpDisplayDriver_SDL_GL2(properties);
|
return new (driver) GpDisplayDriver_SDL_GL2(properties);
|
||||||
|
|
||||||
if (!driver->Init())
|
|
||||||
{
|
|
||||||
driver->Shutdown();
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
return driver;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
T *GpGLObjectImpl<T>::Create(GpDisplayDriver_SDL_GL2 *driver)
|
T *GpGLObjectImpl<T>::Create(GpDisplayDriver_SDL_GL2 *driver)
|
||||||
{
|
{
|
||||||
@@ -3177,4 +3166,33 @@ T *GpGLObjectImpl<T>::Create(GpDisplayDriver_SDL_GL2 *driver)
|
|||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if GP_ASYNCIFY_PARANOID
|
||||||
|
bool IGpDisplayDriver::Init()
|
||||||
|
{
|
||||||
|
return static_cast<GpDisplayDriver_SDL_GL2*>(this)->Init();
|
||||||
|
}
|
||||||
|
|
||||||
|
void IGpDisplayDriver::ServeTicks(int tickCount)
|
||||||
|
{
|
||||||
|
static_cast<GpDisplayDriver_SDL_GL2*>(this)->ServeTicks(tickCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IGpDisplayDriver::Shutdown()
|
||||||
|
{
|
||||||
|
static_cast<GpDisplayDriver_SDL_GL2*>(this)->Shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
IGpCursor *IGpDisplayDriver::CreateBWCursor(size_t width, size_t height, const void *pixelData, const void *maskData, size_t hotSpotX, size_t hotSpotY)
|
||||||
|
{
|
||||||
|
return static_cast<GpDisplayDriver_SDL_GL2*>(this)->CreateBWCursor(width, height, pixelData, maskData, hotSpotX, hotSpotY);
|
||||||
|
}
|
||||||
|
|
||||||
|
IGpCursor *IGpDisplayDriver::CreateColorCursor(size_t width, size_t height, const void *pixelDataRGBA, size_t hotSpotX, size_t hotSpotY)
|
||||||
|
{
|
||||||
|
return static_cast<GpDisplayDriver_SDL_GL2*>(this)->CreateColorCursor(width, height, pixelDataRGBA, hotSpotX, hotSpotY);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#pragma pop_macro("LoadCursor")
|
#pragma pop_macro("LoadCursor")
|
||||||
|
@@ -1,70 +0,0 @@
|
|||||||
#include "GpFiberStarter.h"
|
|
||||||
#include "GpFiber_SDL.h"
|
|
||||||
|
|
||||||
#include "HostSystemServices.h"
|
|
||||||
#include "HostThreadEvent.h"
|
|
||||||
|
|
||||||
#include "SDL_thread.h"
|
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
namespace GpFiberStarter_SDL
|
|
||||||
{
|
|
||||||
struct FiberStartState
|
|
||||||
{
|
|
||||||
GpFiberStarter::ThreadFunc_t m_threadFunc;
|
|
||||||
PortabilityLayer::HostThreadEvent *m_creatingReturnEvent;
|
|
||||||
PortabilityLayer::HostThreadEvent *m_creatingWakeEvent;
|
|
||||||
void *m_context;
|
|
||||||
};
|
|
||||||
|
|
||||||
static int SDLCALL FiberStartRoutine(void *lpThreadParameter)
|
|
||||||
{
|
|
||||||
const FiberStartState *tss = static_cast<const FiberStartState*>(lpThreadParameter);
|
|
||||||
|
|
||||||
GpFiberStarter::ThreadFunc_t threadFunc = tss->m_threadFunc;
|
|
||||||
PortabilityLayer::HostThreadEvent *creatingReturnEvent = tss->m_creatingReturnEvent;
|
|
||||||
PortabilityLayer::HostThreadEvent *wakeEvent = tss->m_creatingWakeEvent;
|
|
||||||
void *context = tss->m_context;
|
|
||||||
creatingReturnEvent->Signal();
|
|
||||||
|
|
||||||
wakeEvent->Wait();
|
|
||||||
|
|
||||||
threadFunc(context);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
IGpFiber *GpFiberStarter::StartFiber(PortabilityLayer::HostSystemServices *systemServices, ThreadFunc_t threadFunc, void *context, IGpFiber *creatingFiber)
|
|
||||||
{
|
|
||||||
PortabilityLayer::HostThreadEvent *returnEvent = systemServices->CreateThreadEvent(true, false);
|
|
||||||
if (!returnEvent)
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
PortabilityLayer::HostThreadEvent *wakeEvent = systemServices->CreateThreadEvent(true, false);
|
|
||||||
if (!wakeEvent)
|
|
||||||
{
|
|
||||||
returnEvent->Destroy();
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
GpFiberStarter_SDL::FiberStartState startState;
|
|
||||||
startState.m_context = context;
|
|
||||||
startState.m_creatingReturnEvent = returnEvent;
|
|
||||||
startState.m_creatingWakeEvent = wakeEvent;
|
|
||||||
startState.m_threadFunc = threadFunc;
|
|
||||||
|
|
||||||
SDL_Thread *thread = SDL_CreateThread(GpFiberStarter_SDL::FiberStartRoutine, "Fiber", &startState);
|
|
||||||
if (!thread)
|
|
||||||
{
|
|
||||||
returnEvent->Destroy();
|
|
||||||
wakeEvent->Destroy();
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
returnEvent->Wait();
|
|
||||||
returnEvent->Destroy();
|
|
||||||
|
|
||||||
return new GpFiber_SDL(thread, wakeEvent);
|
|
||||||
}
|
|
@@ -1,30 +0,0 @@
|
|||||||
#include "GpFiber_SDL.h"
|
|
||||||
#include "HostSystemServices.h"
|
|
||||||
#include "HostThreadEvent.h"
|
|
||||||
|
|
||||||
GpFiber_SDL::GpFiber_SDL(SDL_Thread *thread, PortabilityLayer::HostThreadEvent *threadEvent)
|
|
||||||
: m_event(threadEvent)
|
|
||||||
, m_thread(thread)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
GpFiber_SDL::~GpFiber_SDL()
|
|
||||||
{
|
|
||||||
m_event->Destroy();
|
|
||||||
}
|
|
||||||
|
|
||||||
void GpFiber_SDL::YieldTo(IGpFiber *toFiber)
|
|
||||||
{
|
|
||||||
static_cast<GpFiber_SDL*>(toFiber)->m_event->Signal();
|
|
||||||
m_event->Wait();
|
|
||||||
}
|
|
||||||
|
|
||||||
void GpFiber_SDL::YieldToTerminal(IGpFiber *toFiber)
|
|
||||||
{
|
|
||||||
static_cast<GpFiber_SDL*>(toFiber)->m_event->Signal();
|
|
||||||
}
|
|
||||||
|
|
||||||
void GpFiber_SDL::Destroy()
|
|
||||||
{
|
|
||||||
delete this;
|
|
||||||
}
|
|
@@ -1,28 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "IGpFiber.h"
|
|
||||||
#include "SDL_thread.h"
|
|
||||||
|
|
||||||
namespace PortabilityLayer
|
|
||||||
{
|
|
||||||
class HostSystemServices;
|
|
||||||
class HostThreadEvent;
|
|
||||||
}
|
|
||||||
|
|
||||||
class GpFiber_SDL final : public IGpFiber
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
explicit GpFiber_SDL(SDL_Thread *thread, PortabilityLayer::HostThreadEvent *threadEvent);
|
|
||||||
~GpFiber_SDL();
|
|
||||||
|
|
||||||
void YieldTo(IGpFiber *fromFiber) override;
|
|
||||||
void YieldToTerminal(IGpFiber *fromFiber) override;
|
|
||||||
void Destroy() override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
static int SDLCALL InternalThreadFunction(void *data);
|
|
||||||
|
|
||||||
bool m_isDestroying;
|
|
||||||
PortabilityLayer::HostThreadEvent *m_event;
|
|
||||||
SDL_Thread *m_thread;
|
|
||||||
};
|
|
306
AerofoilSDL/GpInputDriver_SDL_Gamepad.cpp
Normal file
@@ -0,0 +1,306 @@
|
|||||||
|
#include "GpInputDriver_SDL_Gamepad.h"
|
||||||
|
#include "GpVOSEvent.h"
|
||||||
|
#include "IGpVOSEventQueue.h"
|
||||||
|
|
||||||
|
#include "SDL_events.h"
|
||||||
|
#include "SDL_joystick.h"
|
||||||
|
#include "SDL_gamecontroller.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <new>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
class GpInputDriverSDLGamepad final : public IGpInputDriverSDLGamepad
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void ProcessInput() override;
|
||||||
|
void Shutdown() override;
|
||||||
|
|
||||||
|
IGpPrefsHandler *GetPrefsHandler() const override;
|
||||||
|
|
||||||
|
static GpInputDriverSDLGamepad *Create(const GpInputDriverProperties &props);
|
||||||
|
|
||||||
|
void ProcessSDLEvent(const SDL_Event &evt) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
static const int kMaxPlayers = 2;
|
||||||
|
|
||||||
|
GpInputDriverSDLGamepad(const GpInputDriverProperties &props);
|
||||||
|
~GpInputDriverSDLGamepad();
|
||||||
|
|
||||||
|
bool FindJoystickPlayer(uint8_t &playerNum, SDL_JoystickID joystickID);
|
||||||
|
|
||||||
|
void HandleDeviceAdded(SDL_JoystickID joystickID);
|
||||||
|
void HandleDeviceRemoved(SDL_JoystickID joystickID);
|
||||||
|
|
||||||
|
std::vector<GpVOSEvent> m_pendingEvents;
|
||||||
|
|
||||||
|
GpInputDriverProperties m_properties;
|
||||||
|
|
||||||
|
SDL_JoystickID m_playerJoystickIDs[kMaxPlayers];
|
||||||
|
SDL_GameController *m_playerControllers[kMaxPlayers];
|
||||||
|
bool m_playerButtonDown[kMaxPlayers][GpGamepadButtons::kCount];
|
||||||
|
};
|
||||||
|
|
||||||
|
static GpInputDriverSDLGamepad *gs_instance = nullptr;
|
||||||
|
|
||||||
|
IGpInputDriverSDLGamepad *IGpInputDriverSDLGamepad::GetInstance()
|
||||||
|
{
|
||||||
|
return gs_instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GpInputDriverSDLGamepad::ProcessInput()
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < m_pendingEvents.size(); i++)
|
||||||
|
{
|
||||||
|
if (GpVOSEvent *evt = m_properties.m_eventQueue->QueueEvent())
|
||||||
|
*evt = m_pendingEvents[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
m_pendingEvents.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GpInputDriverSDLGamepad::Shutdown()
|
||||||
|
{
|
||||||
|
this->~GpInputDriverSDLGamepad();
|
||||||
|
free(this);
|
||||||
|
|
||||||
|
gs_instance = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
IGpPrefsHandler *GpInputDriverSDLGamepad::GetPrefsHandler() const
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
GpInputDriverSDLGamepad *GpInputDriverSDLGamepad::Create(const GpInputDriverProperties &props)
|
||||||
|
{
|
||||||
|
void *storage = malloc(sizeof(GpInputDriverSDLGamepad));
|
||||||
|
if (!storage)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
GpInputDriverSDLGamepad *driver = new (storage) GpInputDriverSDLGamepad(props);
|
||||||
|
gs_instance = driver;
|
||||||
|
return driver;
|
||||||
|
}
|
||||||
|
|
||||||
|
GpInputDriverSDLGamepad::GpInputDriverSDLGamepad(const GpInputDriverProperties &props)
|
||||||
|
: m_properties(props)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < kMaxPlayers; i++)
|
||||||
|
{
|
||||||
|
m_playerJoystickIDs[i] = -1;
|
||||||
|
m_playerControllers[i] = nullptr;
|
||||||
|
|
||||||
|
for (int j = 0; j < GpGamepadButtons::kCount; j++)
|
||||||
|
m_playerButtonDown[i][j] = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GpInputDriverSDLGamepad::~GpInputDriverSDLGamepad()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < kMaxPlayers; i++)
|
||||||
|
{
|
||||||
|
if (m_playerControllers[i])
|
||||||
|
SDL_GameControllerClose(m_playerControllers[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GpInputDriverSDLGamepad::FindJoystickPlayer(uint8_t &playerNum, SDL_JoystickID joystickID)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < kMaxPlayers; i++)
|
||||||
|
{
|
||||||
|
if (m_playerJoystickIDs[i] == joystickID)
|
||||||
|
{
|
||||||
|
playerNum = static_cast<uint8_t>(i);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GpInputDriverSDLGamepad::HandleDeviceAdded(SDL_JoystickID joystickID)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < kMaxPlayers; i++)
|
||||||
|
{
|
||||||
|
if (m_playerJoystickIDs[i] == -1)
|
||||||
|
{
|
||||||
|
SDL_GameController *controller = SDL_GameControllerOpen(joystickID);
|
||||||
|
if (controller)
|
||||||
|
{
|
||||||
|
m_playerJoystickIDs[i] = joystickID;
|
||||||
|
m_playerControllers[i] = controller;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GpInputDriverSDLGamepad::HandleDeviceRemoved(SDL_JoystickID joystickID)
|
||||||
|
{
|
||||||
|
int playerNum = 0;
|
||||||
|
bool foundPlayer = false;
|
||||||
|
for (int i = 0; i < kMaxPlayers; i++)
|
||||||
|
{
|
||||||
|
if (m_playerJoystickIDs[i] == joystickID)
|
||||||
|
{
|
||||||
|
SDL_GameControllerClose(m_playerControllers[i]);
|
||||||
|
|
||||||
|
m_playerJoystickIDs[i] = -1;
|
||||||
|
m_playerControllers[i] = nullptr;
|
||||||
|
|
||||||
|
playerNum = i;
|
||||||
|
foundPlayer = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!foundPlayer)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (int axis = 0; axis < GpGamepadAxes::kCount; axis++)
|
||||||
|
{
|
||||||
|
GpVOSEvent evt;
|
||||||
|
evt.m_eventType = GpVOSEventTypes::kGamepadInput;
|
||||||
|
evt.m_event.m_gamepadInputEvent.m_eventType = GpGamepadInputEventTypes::kAnalogAxisChanged;
|
||||||
|
evt.m_event.m_gamepadInputEvent.m_event.m_analogAxisEvent.m_axis = static_cast<GpGamepadAxis_t>(axis);
|
||||||
|
evt.m_event.m_gamepadInputEvent.m_event.m_analogAxisEvent.m_player = playerNum;
|
||||||
|
evt.m_event.m_gamepadInputEvent.m_event.m_analogAxisEvent.m_state = 0;
|
||||||
|
|
||||||
|
m_pendingEvents.push_back(evt);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int button = 0; button < GpGamepadButtons::kCount; button++)
|
||||||
|
{
|
||||||
|
if (m_playerButtonDown[playerNum][button])
|
||||||
|
{
|
||||||
|
m_playerButtonDown[playerNum][button] = false;
|
||||||
|
|
||||||
|
GpVOSEvent evt;
|
||||||
|
evt.m_eventType = GpVOSEventTypes::kKeyboardInput;
|
||||||
|
evt.m_event.m_keyboardInputEvent.m_eventType = GpKeyboardInputEventTypes::kUp;
|
||||||
|
evt.m_event.m_keyboardInputEvent.m_keyIDSubset = GpKeyIDSubsets::kGamepadButton;
|
||||||
|
evt.m_event.m_keyboardInputEvent.m_key.m_gamepadKey.m_player = playerNum;
|
||||||
|
evt.m_event.m_keyboardInputEvent.m_key.m_gamepadKey.m_button = static_cast<GpGamepadButton_t>(button);
|
||||||
|
evt.m_event.m_keyboardInputEvent.m_repeatCount = 0;
|
||||||
|
|
||||||
|
m_pendingEvents.push_back(evt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
GpGamepadAxis_t axis = GpGamepadAxes::kCount;
|
||||||
|
|
||||||
|
uint8_t playerNumber = 0;
|
||||||
|
if (!FindJoystickPlayer(playerNumber, axisMsg.which))
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (axisMsg.axis == SDL_CONTROLLER_AXIS_TRIGGERLEFT)
|
||||||
|
axis = GpGamepadAxes::kLeftTrigger;
|
||||||
|
else if (axisMsg.axis == SDL_CONTROLLER_AXIS_TRIGGERRIGHT)
|
||||||
|
axis = GpGamepadAxes::kRightTrigger;
|
||||||
|
else if (axisMsg.axis == SDL_CONTROLLER_AXIS_LEFTX)
|
||||||
|
axis = GpGamepadAxes::kLeftStickX;
|
||||||
|
else if (axisMsg.axis == SDL_CONTROLLER_AXIS_LEFTY)
|
||||||
|
axis = GpGamepadAxes::kLeftStickY;
|
||||||
|
else if (axisMsg.axis == SDL_CONTROLLER_AXIS_RIGHTX)
|
||||||
|
axis = GpGamepadAxes::kRightStickX;
|
||||||
|
else if (axisMsg.axis == SDL_CONTROLLER_AXIS_RIGHTY)
|
||||||
|
axis = GpGamepadAxes::kRightStickY;
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
|
||||||
|
GpVOSEvent evt;
|
||||||
|
evt.m_eventType = GpVOSEventTypes::kGamepadInput;
|
||||||
|
evt.m_event.m_gamepadInputEvent.m_eventType = GpGamepadInputEventTypes::kAnalogAxisChanged;
|
||||||
|
evt.m_event.m_gamepadInputEvent.m_event.m_analogAxisEvent.m_axis = axis;
|
||||||
|
evt.m_event.m_gamepadInputEvent.m_event.m_analogAxisEvent.m_player = playerNumber;
|
||||||
|
evt.m_event.m_gamepadInputEvent.m_event.m_analogAxisEvent.m_state = std::max<int16_t>(-32767, axisMsg.value);
|
||||||
|
|
||||||
|
m_pendingEvents.push_back(evt);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SDL_CONTROLLERBUTTONDOWN:
|
||||||
|
case SDL_CONTROLLERBUTTONUP:
|
||||||
|
{
|
||||||
|
const bool isDown = (msg.type == SDL_CONTROLLERBUTTONDOWN);
|
||||||
|
const SDL_ControllerButtonEvent &buttonMsg = msg.cbutton;
|
||||||
|
|
||||||
|
GpGamepadButton_t gpButton = GpGamepadButtons::kCount;
|
||||||
|
|
||||||
|
uint8_t playerNumber = 0;
|
||||||
|
if (!FindJoystickPlayer(playerNumber, buttonMsg.which))
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (buttonMsg.button == SDL_CONTROLLER_BUTTON_A)
|
||||||
|
gpButton = GpGamepadButtons::kFaceRight;
|
||||||
|
else if (buttonMsg.button == SDL_CONTROLLER_BUTTON_B)
|
||||||
|
gpButton = GpGamepadButtons::kFaceDown;
|
||||||
|
else if (buttonMsg.button == SDL_CONTROLLER_BUTTON_X)
|
||||||
|
gpButton = GpGamepadButtons::kFaceUp;
|
||||||
|
else if (buttonMsg.button == SDL_CONTROLLER_BUTTON_Y)
|
||||||
|
gpButton = GpGamepadButtons::kFaceLeft;
|
||||||
|
else if (buttonMsg.button == SDL_CONTROLLER_BUTTON_START)
|
||||||
|
gpButton = GpGamepadButtons::kMisc1;
|
||||||
|
else if (buttonMsg.button == SDL_CONTROLLER_BUTTON_BACK)
|
||||||
|
gpButton = GpGamepadButtons::kMisc2;
|
||||||
|
else if (buttonMsg.button == SDL_CONTROLLER_BUTTON_LEFTSTICK)
|
||||||
|
gpButton = GpGamepadButtons::kLeftStick;
|
||||||
|
else if (buttonMsg.button == SDL_CONTROLLER_BUTTON_RIGHTSTICK)
|
||||||
|
gpButton = GpGamepadButtons::kRightStick;
|
||||||
|
else if (buttonMsg.button == SDL_CONTROLLER_BUTTON_LEFTSHOULDER)
|
||||||
|
gpButton = GpGamepadButtons::kLeftBumper;
|
||||||
|
else if (buttonMsg.button == SDL_CONTROLLER_BUTTON_RIGHTSHOULDER)
|
||||||
|
gpButton = GpGamepadButtons::kRightBumper;
|
||||||
|
else if (buttonMsg.button == SDL_CONTROLLER_BUTTON_DPAD_UP)
|
||||||
|
gpButton = GpGamepadButtons::kDPadUp;
|
||||||
|
else if (buttonMsg.button == SDL_CONTROLLER_BUTTON_DPAD_DOWN)
|
||||||
|
gpButton = GpGamepadButtons::kDPadDown;
|
||||||
|
else if (buttonMsg.button == SDL_CONTROLLER_BUTTON_DPAD_LEFT)
|
||||||
|
gpButton = GpGamepadButtons::kDPadLeft;
|
||||||
|
else if (buttonMsg.button == SDL_CONTROLLER_BUTTON_DPAD_RIGHT)
|
||||||
|
gpButton = GpGamepadButtons::kDPadRight;
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
|
||||||
|
m_playerButtonDown[playerNumber][gpButton] = isDown;
|
||||||
|
|
||||||
|
GpVOSEvent evt;
|
||||||
|
evt.m_eventType = GpVOSEventTypes::kKeyboardInput;
|
||||||
|
evt.m_event.m_keyboardInputEvent.m_eventType = (isDown ? GpKeyboardInputEventTypes::kDown : GpKeyboardInputEventTypes::kUp);
|
||||||
|
evt.m_event.m_keyboardInputEvent.m_keyIDSubset = GpKeyIDSubsets::kGamepadButton;
|
||||||
|
evt.m_event.m_keyboardInputEvent.m_key.m_gamepadKey.m_player = playerNumber;
|
||||||
|
evt.m_event.m_keyboardInputEvent.m_key.m_gamepadKey.m_button = gpButton;
|
||||||
|
evt.m_event.m_keyboardInputEvent.m_repeatCount = 0;
|
||||||
|
|
||||||
|
m_pendingEvents.push_back(evt);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SDL_CONTROLLERDEVICEADDED:
|
||||||
|
HandleDeviceAdded(msg.cdevice.which);
|
||||||
|
break;
|
||||||
|
case SDL_CONTROLLERDEVICEREMOVED:
|
||||||
|
HandleDeviceRemoved(msg.cdevice.which);
|
||||||
|
break;
|
||||||
|
case SDL_CONTROLLERDEVICEREMAPPED:
|
||||||
|
// Not really sure what to do here, just re-add it
|
||||||
|
HandleDeviceRemoved(msg.cdevice.which);
|
||||||
|
HandleDeviceAdded(msg.cdevice.which);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
IGpInputDriver *GpDriver_CreateInputDriver_SDL2_Gamepad(const GpInputDriverProperties &properties)
|
||||||
|
{
|
||||||
|
return GpInputDriverSDLGamepad::Create(properties);
|
||||||
|
}
|
14
AerofoilSDL/GpInputDriver_SDL_Gamepad.h
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "IGpInputDriver.h"
|
||||||
|
#include "GpInputDriverProperties.h"
|
||||||
|
#include "GpVOSEvent.h"
|
||||||
|
|
||||||
|
union SDL_Event;
|
||||||
|
|
||||||
|
struct IGpInputDriverSDLGamepad : public IGpInputDriver
|
||||||
|
{
|
||||||
|
virtual void ProcessSDLEvent(const SDL_Event &evt) = 0;
|
||||||
|
|
||||||
|
static IGpInputDriverSDLGamepad *GetInstance();
|
||||||
|
};
|
@@ -1,11 +1,10 @@
|
|||||||
#include "SDL.h"
|
#include "SDL.h"
|
||||||
|
|
||||||
#include "GpMain.h"
|
#include "GpMain.h"
|
||||||
|
#include "GpAllocator_C.h"
|
||||||
#include "GpAudioDriverFactory.h"
|
#include "GpAudioDriverFactory.h"
|
||||||
#include "GpDisplayDriverFactory.h"
|
#include "GpDisplayDriverFactory.h"
|
||||||
#include "GpGlobalConfig.h"
|
#include "GpGlobalConfig.h"
|
||||||
#include "GpFiber_Win32.h"
|
|
||||||
#include "GpFiber_SDL.h"
|
|
||||||
#include "GpFileSystem_Win32.h"
|
#include "GpFileSystem_Win32.h"
|
||||||
#include "GpLogDriver_Win32.h"
|
#include "GpLogDriver_Win32.h"
|
||||||
#include "GpFontHandlerFactory.h"
|
#include "GpFontHandlerFactory.h"
|
||||||
@@ -13,10 +12,10 @@
|
|||||||
#include "GpAppInterface.h"
|
#include "GpAppInterface.h"
|
||||||
#include "GpSystemServices_Win32.h"
|
#include "GpSystemServices_Win32.h"
|
||||||
#include "GpVOSEvent.h"
|
#include "GpVOSEvent.h"
|
||||||
#include "IGpVOSEventQueue.h"
|
|
||||||
|
|
||||||
#include "HostFileSystem.h"
|
#include "IGpFileSystem.h"
|
||||||
#include "HostThreadEvent.h"
|
#include "IGpThreadEvent.h"
|
||||||
|
#include "IGpVOSEventQueue.h"
|
||||||
|
|
||||||
#include "GpWindows.h"
|
#include "GpWindows.h"
|
||||||
|
|
||||||
@@ -29,16 +28,22 @@
|
|||||||
|
|
||||||
GpWindowsGlobals g_gpWindowsGlobals;
|
GpWindowsGlobals g_gpWindowsGlobals;
|
||||||
|
|
||||||
extern "C" __declspec(dllimport) IGpInputDriver *GpDriver_CreateInputDriver_XInput(const GpInputDriverProperties &properties);
|
|
||||||
extern "C" __declspec(dllimport) IGpFontHandler *GpDriver_CreateFontHandler_FreeType2(const GpFontHandlerProperties &properties);
|
extern "C" __declspec(dllimport) IGpFontHandler *GpDriver_CreateFontHandler_FreeType2(const GpFontHandlerProperties &properties);
|
||||||
|
|
||||||
IGpDisplayDriver *GpDriver_CreateDisplayDriver_SDL_GL2(const GpDisplayDriverProperties &properties);
|
IGpDisplayDriver *GpDriver_CreateDisplayDriver_SDL_GL2(const GpDisplayDriverProperties &properties);
|
||||||
IGpAudioDriver *GpDriver_CreateAudioDriver_SDL(const GpAudioDriverProperties &properties);
|
IGpAudioDriver *GpDriver_CreateAudioDriver_SDL(const GpAudioDriverProperties &properties);
|
||||||
|
IGpInputDriver *GpDriver_CreateInputDriver_SDL2_Gamepad(const GpInputDriverProperties &properties);
|
||||||
|
|
||||||
|
|
||||||
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
|
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
|
||||||
{
|
{
|
||||||
if (SDL_Init(SDL_INIT_VIDEO) < 0)
|
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;
|
return -1;
|
||||||
|
|
||||||
LPWSTR cmdLine = GetCommandLineW();
|
LPWSTR cmdLine = GetCommandLineW();
|
||||||
@@ -56,10 +61,12 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
|
|||||||
}
|
}
|
||||||
|
|
||||||
IGpLogDriver *logger = GpLogDriver_Win32::GetInstance();
|
IGpLogDriver *logger = GpLogDriver_Win32::GetInstance();
|
||||||
|
GpDriverCollection *drivers = GpAppInterface_Get()->PL_GetDriverCollection();
|
||||||
|
|
||||||
GpAppInterface_Get()->PL_HostFileSystem_SetInstance(GpFileSystem_Win32::GetInstance());
|
drivers->SetDriver<GpDriverIDs::kFileSystem>(fs);
|
||||||
GpAppInterface_Get()->PL_HostSystemServices_SetInstance(GpSystemServices_Win32::GetInstance());
|
drivers->SetDriver<GpDriverIDs::kSystemServices>(GpSystemServices_Win32::GetInstance());
|
||||||
GpAppInterface_Get()->PL_HostLogDriver_SetInstance(GpLogDriver_Win32::GetInstance());
|
drivers->SetDriver<GpDriverIDs::kLog>(GpLogDriver_Win32::GetInstance());
|
||||||
|
drivers->SetDriver<GpDriverIDs::kAlloc>(GpAllocator_C::GetInstance());
|
||||||
|
|
||||||
g_gpWindowsGlobals.m_hInstance = hInstance;
|
g_gpWindowsGlobals.m_hInstance = hInstance;
|
||||||
g_gpWindowsGlobals.m_hPrevInstance = hPrevInstance;
|
g_gpWindowsGlobals.m_hPrevInstance = hPrevInstance;
|
||||||
@@ -78,7 +85,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
|
|||||||
|
|
||||||
EGpInputDriverType inputDrivers[] =
|
EGpInputDriverType inputDrivers[] =
|
||||||
{
|
{
|
||||||
EGpInputDriverType_XInput
|
EGpInputDriverType_SDL2_Gamepad
|
||||||
};
|
};
|
||||||
|
|
||||||
g_gpGlobalConfig.m_inputDriverTypes = inputDrivers;
|
g_gpGlobalConfig.m_inputDriverTypes = inputDrivers;
|
||||||
@@ -87,10 +94,11 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
|
|||||||
g_gpGlobalConfig.m_osGlobals = &g_gpWindowsGlobals;
|
g_gpGlobalConfig.m_osGlobals = &g_gpWindowsGlobals;
|
||||||
g_gpGlobalConfig.m_logger = logger;
|
g_gpGlobalConfig.m_logger = logger;
|
||||||
g_gpGlobalConfig.m_systemServices = GpSystemServices_Win32::GetInstance();
|
g_gpGlobalConfig.m_systemServices = GpSystemServices_Win32::GetInstance();
|
||||||
|
g_gpGlobalConfig.m_allocator = alloc;
|
||||||
|
|
||||||
GpDisplayDriverFactory::RegisterDisplayDriverFactory(EGpDisplayDriverType_SDL_GL2, GpDriver_CreateDisplayDriver_SDL_GL2);
|
GpDisplayDriverFactory::RegisterDisplayDriverFactory(EGpDisplayDriverType_SDL_GL2, GpDriver_CreateDisplayDriver_SDL_GL2);
|
||||||
GpAudioDriverFactory::RegisterAudioDriverFactory(EGpAudioDriverType_SDL2, GpDriver_CreateAudioDriver_SDL);
|
GpAudioDriverFactory::RegisterAudioDriverFactory(EGpAudioDriverType_SDL2, GpDriver_CreateAudioDriver_SDL);
|
||||||
GpInputDriverFactory::RegisterInputDriverFactory(EGpInputDriverType_XInput, GpDriver_CreateInputDriver_XInput);
|
GpInputDriverFactory::RegisterInputDriverFactory(EGpInputDriverType_SDL2_Gamepad, GpDriver_CreateInputDriver_SDL2_Gamepad);
|
||||||
GpFontHandlerFactory::RegisterFontHandlerFactory(EGpFontHandlerType_FreeType2, GpDriver_CreateFontHandler_FreeType2);
|
GpFontHandlerFactory::RegisterFontHandlerFactory(EGpFontHandlerType_FreeType2, GpDriver_CreateFontHandler_FreeType2);
|
||||||
|
|
||||||
if (logger)
|
if (logger)
|
||||||
@@ -103,5 +111,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
|
|||||||
|
|
||||||
LocalFree(cmdLineArgs);
|
LocalFree(cmdLineArgs);
|
||||||
|
|
||||||
|
fs->Destroy();
|
||||||
|
|
||||||
return returnCode;
|
return returnCode;
|
||||||
}
|
}
|
||||||
|
5
AerofoilSDL/GpSDL.h
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
#ifdef __CYGWIN__
|
||||||
|
#define GP_SDL_DIRECTORY_PREFIX "SDL2/"
|
||||||
|
#else
|
||||||
|
#define GP_SDL_DIRECTORY_PREFIX
|
||||||
|
#endif
|
@@ -11,6 +11,6 @@
|
|||||||
"}\n"
|
"}\n"
|
||||||
|
|
||||||
namespace GpBinarizedShaders
|
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;
|
const char *g_copyQuadP_GL2 = GP_GL_SHADER_CODE_MEDIUM_PRECISION_PREFIX GP_GL_SHADER_CODE_FUNCTIONS_H GP_GL_SHADER_CODE_COPYQUADP_GLSL;
|
||||||
}
|
}
|
||||||
|
35
AerofoilSDL/ShaderCode/DrawQuad32P.cpp
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
#include "Functions.h"
|
||||||
|
#include "DrawQuadPixelConstants.h"
|
||||||
|
|
||||||
|
#define GP_GL_SHADER_CODE_DRAWQUAD32P_GLSL \
|
||||||
|
"\n"\
|
||||||
|
"varying vec4 texCoord;\n"\
|
||||||
|
"uniform sampler2D surfaceTexture;\n"\
|
||||||
|
"uniform sampler2D paletteTexture;\n"\
|
||||||
|
"\n"\
|
||||||
|
"vec3 SamplePixel(vec2 tc)\n"\
|
||||||
|
"{\n"\
|
||||||
|
" return texture2D(surfaceTexture, tc).rgb;\n"\
|
||||||
|
"}\n"\
|
||||||
|
"\n"\
|
||||||
|
"void main()\n"\
|
||||||
|
"{\n"\
|
||||||
|
" 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);\n"\
|
||||||
|
" if (resultColor.a < 1.0)\n"\
|
||||||
|
" discard;\n"\
|
||||||
|
"#endif\n"\
|
||||||
|
" resultColor = ApplyDesaturation(constants_Desaturation, resultColor);\n"\
|
||||||
|
"\n"\
|
||||||
|
" gl_FragColor = vec4(ApplyColorSpaceTransform(resultColor.rgb), resultColor.a);\n"\
|
||||||
|
"}\n"
|
||||||
|
|
||||||
|
namespace GpBinarizedShaders
|
||||||
|
{
|
||||||
|
const char *g_drawQuad32PF_GL2 = "#define ENABLE_FLICKER\n" GP_GL_SHADER_CODE_MEDIUM_PRECISION_PREFIX GP_GL_SHADER_CODE_DRAWQUADPIXELCONSTANTS_H GP_GL_SHADER_CODE_FUNCTIONS_H GP_GL_SHADER_CODE_DRAWQUAD32P_GLSL;
|
||||||
|
const char *g_drawQuad32PNF_GL2 = GP_GL_SHADER_CODE_MEDIUM_PRECISION_PREFIX GP_GL_SHADER_CODE_DRAWQUADPIXELCONSTANTS_H GP_GL_SHADER_CODE_FUNCTIONS_H GP_GL_SHADER_CODE_DRAWQUAD32P_GLSL;
|
||||||
|
const char *g_drawQuad32ICCPF_GL2 = "#define USE_ICC_PROFILE\n" "#define ENABLE_FLICKER\n" GP_GL_SHADER_CODE_MEDIUM_PRECISION_PREFIX GP_GL_SHADER_CODE_DRAWQUADPIXELCONSTANTS_H GP_GL_SHADER_CODE_FUNCTIONS_H GP_GL_SHADER_CODE_DRAWQUAD32P_GLSL;
|
||||||
|
const char *g_drawQuad32ICCPNF_GL2 = "#define USE_ICC_PROFILE\n" GP_GL_SHADER_CODE_MEDIUM_PRECISION_PREFIX GP_GL_SHADER_CODE_DRAWQUADPIXELCONSTANTS_H GP_GL_SHADER_CODE_FUNCTIONS_H GP_GL_SHADER_CODE_DRAWQUAD32P_GLSL;
|
||||||
|
}
|
@@ -18,7 +18,7 @@
|
|||||||
" vec4 resultColor = vec4(SamplePixel(texCoord.xy), 1.0);\n"\
|
" vec4 resultColor = vec4(SamplePixel(texCoord.xy), 1.0);\n"\
|
||||||
" resultColor *= constants_Modulation;\n"\
|
" resultColor *= constants_Modulation;\n"\
|
||||||
"#ifdef ENABLE_FLICKER\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"\
|
" if (resultColor.a < 1.0)\n"\
|
||||||
" discard;\n"\
|
" discard;\n"\
|
||||||
"#endif\n"\
|
"#endif\n"\
|
||||||
|
@@ -1,7 +1,10 @@
|
|||||||
#define GP_GL_SHADER_CODE_MEDIUM_PRECISION_PREFIX "precision mediump float;\n"\
|
#ifdef __MACOS__
|
||||||
|
#define GP_GL_SHADER_CODE_MEDIUM_PRECISION_PREFIX ""
|
||||||
#define GP_GL_SHADER_CODE_HIGH_PRECISION_PREFIX "precision highp float;\n"\
|
#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"\
|
#define GP_GL_SHADER_CODE_FUNCTIONS_H "vec3 pow3(vec3 v, float ex)\n"\
|
||||||
"{\n"\
|
"{\n"\
|
||||||
@@ -58,7 +61,7 @@
|
|||||||
"vec4 ApplyDesaturation(float desaturation, vec4 color)\n"\
|
"vec4 ApplyDesaturation(float desaturation, vec4 color)\n"\
|
||||||
"{\n"\
|
"{\n"\
|
||||||
" // This is intentionally done in gamma space\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"\
|
" return color;\n"\
|
||||||
"\n"\
|
"\n"\
|
||||||
" float grayLevel = dot(color.rgb, vec3(3.0, 6.0, 1.0) / 10.0);\n"\
|
" float grayLevel = dot(color.rgb, vec3(3.0, 6.0, 1.0) / 10.0);\n"\
|
||||||
|
3
AerofoilWeb/.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
obj
|
||||||
|
res
|
||||||
|
bin
|
4
AerofoilWeb/AerofoilWeb_Combined.cpp
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
#include "GpFileSystem_Web.cpp"
|
||||||
|
#include "GpLogDriver_Web.cpp"
|
||||||
|
#include "GpMain_SDL_Web.cpp"
|
||||||
|
#include "GpSystemServices_Web.cpp"
|
15
AerofoilWeb/AerofoilWeb_Resources.cpp
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "GpFileSystem_Web_Resources.h"
|
||||||
|
|
||||||
|
namespace GpFileSystem_Web_Resources
|
||||||
|
{
|
||||||
|
namespace ApplicationData
|
||||||
|
{
|
||||||
|
#include "res/ApplicationData.h"
|
||||||
|
}
|
||||||
|
namespace GameData
|
||||||
|
{
|
||||||
|
#include "res/GameData.h"
|
||||||
|
}
|
||||||
|
}
|
11
AerofoilWeb/BuildAerofoilPortable.bat
Normal 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
|
11
AerofoilWeb/BuildAerofoilSDL.bat
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
set INPUT_DIR=../AerofoilSDL
|
||||||
|
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../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%
|
||||||
|
|
||||||
|
pause
|
11
AerofoilWeb/BuildAerofoilWeb.bat
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
set INPUT_DIR=.
|
||||||
|
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../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%
|
||||||
|
|
||||||
|
pause
|