This commit is contained in:
Iain King-Speir
2024-08-06 09:47:00 +00:00
committed by GitHub
18 changed files with 752 additions and 110 deletions

View File

@@ -5,6 +5,28 @@ SET(EXECNAME "AerofoilX" CACHE STRING "Defines the exec name")
message(${CMAKE_BINARY_DIR})
# Use Release build type by default
if("${CMAKE_BUILD_TYPE}" STREQUAL "")
set(CMAKE_BUILD_TYPE Release)
message("Build type unspecified, using Release")
endif()
# Enable LTO by default if supported
if("${CMAKE_INTERPROCEDURAL_OPTIMIZATION}" STREQUAL "")
include(CheckIPOSupported)
check_ipo_supported(RESULT IPO_SUPPORTED)
if(IPO_SUPPORTED)
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION On)
message("Compiler supports LTO, enabling automatically")
endif()
endif()
# FIXME: Clang treats this as an error by default; fixing the source rather
# than downgrading the error to a warning would be a better solution.
add_compile_options(
$<$<COMPILE_LANG_AND_ID:CXX,AppleClang,Clang>:-Wno-error=c++11-narrowing>
)
find_package(SDL2 REQUIRED)
if(PLATFORM STREQUAL "MAC")
@@ -127,18 +149,18 @@ add_library(PortabilityLayer STATIC
)
target_include_directories(PortabilityLayer PRIVATE
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/Common>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/GpCommon>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/PortabilityLayer>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/zlib>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/rapidjson/include>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/MacRomanConversion>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/stb>
Common
GpCommon
PortabilityLayer
zlib
rapidjson/include
MacRomanConversion
stb
)
target_compile_options(PortabilityLayer PRIVATE -Wno-multichar)
target_link_libraries(PortabilityLayer zlib MacRomanConversion stb)
target_link_libraries(PortabilityLayer PRIVATE zlib MacRomanConversion stb)
add_library(GpShell STATIC
@@ -153,9 +175,9 @@ add_library(GpShell STATIC
)
target_include_directories(GpShell PRIVATE
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/Common>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/GpCommon>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/PortabilityLayer>
Common
GpCommon
PortabilityLayer
)
add_library(GpApp STATIC
@@ -233,16 +255,15 @@ add_library(GpApp STATIC
target_compile_options(GpApp PRIVATE -Wno-multichar)
target_include_directories(GpApp PRIVATE
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/Common>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/GpCommon>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/PortabilityLayer>
Common
GpCommon
PortabilityLayer
)
target_link_libraries(GpApp PortabilityLayer)
target_link_libraries(GpApp PRIVATE PortabilityLayer)
if(CMAKE_HOST_UNIX)
set(EXEC_SOURCES )
list(APPEND EXEC_SOURCES
set(EXEC_SOURCES
AerofoilPortable/GpSystemServices_POSIX.cpp
AerofoilPortable/GpThreadEvent_Cpp11.cpp
AerofoilPortable/GpAllocator_C.cpp
@@ -260,21 +281,20 @@ if(CMAKE_HOST_UNIX)
AerofoilX/GpFileSystem_X.cpp
)
set(EXEC_LIBS )
list(APPEND EXEC_LIBS
set(EXEC_LIBS
${SDL2_LIBRARIES}
GpApp
GpShell
PortabilityLayer
)
set(EXEC_INC_DIRS )
list(APPEND EXEC_INC_DIRS
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/Common>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/GpCommon>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/GpShell>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/AerofoilSDL>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/AerofoilPortable>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/PortabilityLayer>
set(EXEC_INC_DIRS
Common
GpCommon
GpShell
AerofoilSDL
AerofoilPortable
PortabilityLayer
${SDL2_INCLUDE_DIRS}
)
if(PLATFORM STREQUAL "MAC")
@@ -283,7 +303,7 @@ if(CMAKE_HOST_UNIX)
AerofoilMac/AerofoilMac/MacInit.mm
)
list(APPEND EXEC_INC_DIRS
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/AerofoilMac/AerofoilMac>
AerofoilMac/AerofoilMac
)
list(APPEND EXEC_LIBS
"-framework Cocoa"
@@ -296,4 +316,418 @@ if(CMAKE_HOST_UNIX)
endif()
install (TARGETS ${EXECNAME})
add_executable(flattenmov EXCLUDE_FROM_ALL flattenmov/flattenmov.cpp AerofoilPortable/GpAllocator_C.cpp)
target_include_directories(flattenmov PRIVATE
Common
GpCommon
PortabilityLayer
AerofoilPortable
)
target_link_libraries(flattenmov PortabilityLayer)
add_executable(bin2gp EXCLUDE_FROM_ALL bin2gp/bin2gp.cpp AerofoilPortable/GpAllocator_C.cpp)
target_include_directories(bin2gp PRIVATE
Common
GpCommon
PortabilityLayer
AerofoilPortable
)
target_link_libraries(bin2gp PortabilityLayer)
add_executable(hqx2bin EXCLUDE_FROM_ALL hqx2bin/hqx2bin.cpp AerofoilPortable/GpAllocator_C.cpp)
target_include_directories(hqx2bin PRIVATE
Common
GpCommon
PortabilityLayer
AerofoilPortable
)
target_link_libraries(hqx2bin PortabilityLayer)
add_executable(hqx2gp EXCLUDE_FROM_ALL
hqx2gp/hqx2gp.cpp
AerofoilPortable/GpAllocator_C.cpp
WindowsUnicodeToolShim/UnixUnicodeToolShim.cpp
)
target_include_directories(hqx2gp PRIVATE
Common
GpCommon
PortabilityLayer
AerofoilPortable
WindowsUnicodeToolShim
)
target_link_libraries(hqx2gp PortabilityLayer)
add_executable(gpr2gpa EXCLUDE_FROM_ALL
gpr2gpa/gpr2gpa.cpp
gpr2gpa/macedec.cpp
AerofoilPortable/GpAllocator_C.cpp
WindowsUnicodeToolShim/UnixUnicodeToolShim.cpp
)
target_include_directories(gpr2gpa PRIVATE
Common
GpCommon
PortabilityLayer
AerofoilPortable
MacRomanConversion
WindowsUnicodeToolShim
rapidjson/include
zlib
)
target_link_libraries(gpr2gpa PortabilityLayer MacRomanConversion zlib)
add_executable(MakeTimestamp EXCLUDE_FROM_ALL MakeTimestamp/MakeTimestamp.cpp)
target_include_directories(MakeTimestamp PRIVATE PortabilityLayer)
target_link_libraries(MakeTimestamp PortabilityLayer)
add_executable(FTagData EXCLUDE_FROM_ALL
FTagData/FTagData.cpp
WindowsUnicodeToolShim/UnixUnicodeToolShim.cpp
)
target_include_directories(FTagData PRIVATE
Common
GpCommon
PortabilityLayer
AerofoilPortable
WindowsUnicodeToolShim
)
target_link_libraries(FTagData PortabilityLayer)
add_executable(MergeGPF EXCLUDE_FROM_ALL
MergeGPF/MergeGPF.cpp
AerofoilPortable/GpAllocator_C.cpp
WindowsUnicodeToolShim/UnixUnicodeToolShim.cpp
)
target_include_directories(MergeGPF PRIVATE
Common
GpCommon
PortabilityLayer
AerofoilPortable
WindowsUnicodeToolShim
)
target_link_libraries(MergeGPF PortabilityLayer)
add_executable(MiniRez EXCLUDE_FROM_ALL MiniRez/MiniRez.cpp WindowsUnicodeToolShim/UnixUnicodeToolShim.cpp)
target_include_directories(MiniRez PRIVATE
Common
GpCommon
PortabilityLayer
WindowsUnicodeToolShim
)
target_link_libraries(MiniRez PortabilityLayer)
add_executable(HouseTool EXCLUDE_FROM_ALL
HouseTool/HouseTool.cpp
WindowsUnicodeToolShim/UnixUnicodeToolShim.cpp
)
target_include_directories(HouseTool PRIVATE
Common
GpCommon
PortabilityLayer
MacRomanConversion
WindowsUnicodeToolShim
)
target_link_libraries(HouseTool PortabilityLayer MacRomanConversion)
add_executable(unpacktool EXCLUDE_FROM_ALL
unpacktool/ArchiveDescription.cpp
unpacktool/BWT.cpp
unpacktool/CompactProLZHDecompressor.cpp
unpacktool/CompactProLZHRLEDecompressor.cpp
unpacktool/CompactProParser.cpp
unpacktool/CompactProRLEDecompressor.cpp
unpacktool/CRC.cpp
unpacktool/CSInputBuffer.cpp
unpacktool/DecompressorProxyReader.cpp
unpacktool/LZSSDecompressor.cpp
unpacktool/LZW.cpp
unpacktool/LZWDecompressor.cpp
unpacktool/NullDecompressor.cpp
unpacktool/PrefixCode.cpp
unpacktool/RLE90Decompressor.cpp
unpacktool/StringCommon.cpp
unpacktool/StuffIt13Decompressor.cpp
unpacktool/StuffIt5Parser.cpp
unpacktool/StuffItArsenicDecompressor.cpp
unpacktool/StuffItCommon.cpp
unpacktool/StuffItHuffmanDecompressor.cpp
unpacktool/StuffItParser.cpp
unpacktool/unpacktool.cpp
WindowsUnicodeToolShim/UnixUnicodeToolShim.cpp
)
target_include_directories(unpacktool PRIVATE
Common
GpCommon
PortabilityLayer
MacRomanConversion
WindowsUnicodeToolShim
)
target_link_libraries(unpacktool PortabilityLayer MacRomanConversion)
find_package(Freetype)
if(FREETYPE_FOUND)
add_library(GpFontHandler_FreeType2 STATIC
GpFontHandler_FreeType2/GpFontHandler_FreeType2.cpp
)
target_include_directories(GpFontHandler_FreeType2 PRIVATE
Common
GpCommon
"${FREETYPE_INCLUDE_DIR_ft2build}"
)
target_link_libraries(GpFontHandler_FreeType2 PRIVATE Freetype::Freetype)
add_executable(GenerateFonts EXCLUDE_FROM_ALL
GenerateFonts/GenerateFonts.cpp
AerofoilPortable/GpAllocator_C.cpp
WindowsUnicodeToolShim/UnixUnicodeToolShim.cpp
)
target_include_directories(GenerateFonts PRIVATE
Common
GpCommon
PortabilityLayer
AerofoilPortable
WindowsUnicodeToolShim
)
target_link_libraries(GenerateFonts PortabilityLayer GpFontHandler_FreeType2)
endif()
add_executable(ConvertColorCursors EXCLUDE_FROM_ALL
ConvertColorCursors/ConvertColorCursors.cpp
AerofoilPortable/GpAllocator_C.cpp
stb/stb_image_write.c
WindowsUnicodeToolShim/UnixUnicodeToolShim.cpp
)
target_include_directories(ConvertColorCursors PRIVATE
Common
GpCommon
PortabilityLayer
AerofoilPortable
stb
WindowsUnicodeToolShim
)
target_link_libraries(ConvertColorCursors PortabilityLayer)
add_custom_target(BuildDirs
BYPRODUCTS Packaged tmp
COMMAND "${CMAKE_COMMAND}" -E make_directory Packaged/Houses tmp
VERBATIM
)
set(DATA_FILES)
function(add_data_file NAME)
list(APPEND DATA_FILES "Packaged/${NAME}")
set(DATA_FILES "${DATA_FILES}" PARENT_SCOPE)
cmake_parse_arguments(PARSE_ARGV 1 ARG "" "" "")
set(TMPDIR "${CMAKE_CURRENT_BINARY_DIR}/tmp/${NAME}")
list(TRANSFORM ARG_UNPARSED_ARGUMENTS
REPLACE {TMPDIR} "${TMPDIR}"
)
add_custom_command(
OUTPUT "Packaged/${NAME}"
DEPENDS BuildDirs
COMMAND "${CMAKE_COMMAND}" -E make_directory "${TMPDIR}"
${ARG_UNPARSED_ARGUMENTS}
COMMAND "${CMAKE_COMMAND}" -E rename
"${TMPDIR}/${NAME}"
"${CMAKE_CURRENT_BINARY_DIR}/Packaged/${NAME}"
COMMAND "${CMAKE_COMMAND}" -E rm -r -- "${TMPDIR}"
VERBATIM
)
endfunction()
add_data_file(ApplicationResources.gpf
DEPENDS
MiniRez gpr2gpa FTagData MergeGPF "GliderProData/Glider PRO.r"
ApplicationResourcePatches/manifest.json DefaultTimestamp.timestamp
COMMAND MiniRez
"GliderProData/Glider PRO.r"
"{TMPDIR}/ApplicationResources.gpr"
COMMAND gpr2gpa
"{TMPDIR}/ApplicationResources.gpr"
DefaultTimestamp.timestamp
"{TMPDIR}/ApplicationResources.gpa"
-patch ApplicationResourcePatches/manifest.json
COMMAND FTagData
DefaultTimestamp.timestamp
"{TMPDIR}/ApplicationResources.gpf"
data ozm5 0 0 locked
COMMAND MergeGPF
"{TMPDIR}/ApplicationResources.gpf"
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
)
file(GLOB_RECURSE FONT_DEPS RELATIVE "${CMAKE_SOURCE_DIR}" CONFIGURE_DEPENDS Resources/Fonts/*)
add_data_file(Fonts.gpf
DEPENDS GenerateFonts MiniRez gpr2gpa FTagData MergeGPF ${FONT_DEPS}
COMMAND GenerateFonts "${CMAKE_SOURCE_DIR}/Resources" {TMPDIR}
COMMAND MiniRez "${CMAKE_SOURCE_DIR}/Empty.r" {TMPDIR}/Fonts.gpr
COMMAND gpr2gpa
{TMPDIR}/Fonts.gpr
"${CMAKE_SOURCE_DIR}/DefaultTimestamp.timestamp"
{TMPDIR}/Fonts.gpa
-patch {TMPDIR}/FontCacheManifest.json
COMMAND FTagData
DefaultTimestamp.timestamp
{TMPDIR}/Fonts.gpf
data ozm5 0 0 locked
COMMAND MergeGPF {TMPDIR}/Fonts.gpf
)
# These files are committed to the repo and aren't currently useful on non-Windows systems anyway.
#file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/Aerofoil/ConvertedResources)
#
#set(CONVERTED_ICONS
# Aerofoil/ConvertedResources/Large128.ico
# Aerofoil/ConvertedResources/Large129.ico
# Aerofoil/ConvertedResources/Large130.ico
# Aerofoil/ConvertedResources/Large131.ico
# Aerofoil/ConvertedResources/Large132.ico
# Aerofoil/ConvertedResources/Large133.ico
# Aerofoil/ConvertedResources/Small128.ico
# Aerofoil/ConvertedResources/Small129.ico
# Aerofoil/ConvertedResources/Small130.ico
# Aerofoil/ConvertedResources/Small133.ico
# )
#
#add_custom_command(
# OUTPUT ${CONVERTED_ICONS}
# DEPENDS ConvertColorCursors Packaged/ApplicationResources.gpr
# COMMAND ConvertColorCursors
# )
#add_custom_target(Icons DEPENDS ${CONVERTED_ICONS})
set(HOUSE_FILES)
function(add_house NAME)
cmake_parse_arguments(PARSE_ARGV 0 ARG
""
PATCH
""
)
if(ARG_PATCH)
set(PATCH_ARGS -patch "${CMAKE_SOURCE_DIR}/HousePatches/${ARG_PATCH}")
endif()
set(BASE_PATH "Packaged/Houses/${NAME}")
list(APPEND HOUSE_FILES "${BASE_PATH}.gpf")
set(BYPRODUCTS "${BASE_PATH}.gpr" "${BASE_PATH}.gpa" "${BASE_PATH}.gpd")
set(BINHEX_SRC "${CMAKE_SOURCE_DIR}/GliderProData/Houses/${NAME}.binhex")
set(TS "${CMAKE_SOURCE_DIR}/DefaultTimestamp.timestamp")
add_custom_command(
OUTPUT
"${BASE_PATH}.gpf"
BYPRODUCTS
${BYPRODUCTS}
DEPENDS hqx2gp gpr2gpa MergeGPF BuildDirs "${BINHEX_SRC}" "${TS}"
COMMAND hqx2gp
"${BINHEX_SRC}"
"${TS}"
"${BASE_PATH}"
COMMAND gpr2gpa
"${BASE_PATH}.gpr"
"${TS}"
"${BASE_PATH}.gpa"
${PATCH_ARGS}
${HOUSE_EXTRA_COMMANDS}
COMMAND MergeGPF
"${BASE_PATH}.gpf"
COMMAND "${CMAKE_COMMAND}" -E rm
${BYPRODUCTS}
VERBATIM
)
set(MOV_GPA_SRC "${CMAKE_SOURCE_DIR}/GliderProData/ConvertedMovies/${NAME}.mov.gpa")
if(EXISTS "${MOV_GPA_SRC}")
list(APPEND HOUSE_FILES "${BASE_PATH}.mov.gpf")
add_custom_command(
OUTPUT
"${BASE_PATH}.mov.gpf"
BYPRODUCTS
"${BASE_PATH}.mov.gpa"
DEPENDS FTagData MergeGPF BuildDirs "${MOV_GPA_SRC}" "${TS}"
COMMAND FTagData
"${TS}"
"${BASE_PATH}.mov.gpf"
MooV ozm5 0 0 locked
COMMAND "${CMAKE_COMMAND}" -E copy
-t "Packaged/Houses"
"${MOV_GPA_SRC}"
COMMAND MergeGPF
"${BASE_PATH}.mov.gpf"
COMMAND "${CMAKE_COMMAND}" -E rm
"${BASE_PATH}.mov.gpa"
VERBATIM
)
endif()
set(HOUSE_FILES "${HOUSE_FILES}" PARENT_SCOPE)
endfunction()
add_house("Art Museum")
add_house("California or Bust!")
set(HOUSE_EXTRA_COMMANDS
DEPENDS HouseTool
COMMAND HouseTool
patch "Packaged/Houses/Castle o' the Air.gpd" .firstRoom 77
)
add_house("Castle o' the Air")
unset(HOUSE_EXTRA_COMMANDS)
add_house("CD Demo House")
add_house("Davis Station")
add_house("Demo House")
add_house("Fun House")
add_house("Grand Prix" PATCH "GrandPrix.json")
add_house("ImagineHouse PRO II" PATCH "ImagineHousePROII.json")
add_house("In The Mirror" PATCH "InTheMirror.json")
add_house("Land of Illusion")
add_house("Leviathan" PATCH "Leviathan.json")
add_house("Metropolis")
add_house("Nemo's Market")
add_house("Rainbow's End" PATCH "RainbowsEnd.json")
add_house("Slumberland")
add_house("SpacePods")
add_house("Teddy World")
add_house("The Asylum Pro")
add_house("Titanic")
add_custom_target(Executable DEPENDS "${EXECNAME}")
add_custom_target(Resources ALL
DEPENDS
${DATA_FILES}
${HOUSE_FILES}
)
set(TOOL_EXES
flattenmov
bin2gp
hqx2bin
hqx2gp
MakeTimestamp
FTagData
gpr2gpa
unpacktool
MergeGPF
)
add_custom_target(Tools ALL DEPENDS ${TOOL_EXES})
list(TRANSFORM DATA_FILES PREPEND "${CMAKE_CURRENT_BINARY_DIR}/")
list(TRANSFORM HOUSE_FILES PREPEND "${CMAKE_CURRENT_BINARY_DIR}/")
install(TARGETS "${EXECNAME}" COMPONENT Executable)
install(FILES ${DATA_FILES} DESTINATION lib/aerofoil/Packaged COMPONENT Resources)
install(FILES ${HOUSE_FILES} DESTINATION lib/aerofoil/Packaged/Houses COMPONENT Resources)
install(TARGETS ${TOOL_EXES} DESTINATION lib/aerofoil/tools COMPONENT Tools)

View File

@@ -8,8 +8,11 @@
#include "QDStandardPalette.h"
#include "PLBigEndian.h"
#include "PLDrivers.h"
#include <assert.h>
#include "WindowsUnicodeToolShim.h"
#include <cassert>
#include <cstdio>
#include <sstream>
#include <string>
#include <vector>
@@ -92,12 +95,12 @@ void ConvertIconFamily(PortabilityLayer::ResourceFile *resFile, int32_t iconBitm
item.a = 0;
}
char outPath[256];
sprintf_s(outPath, "Aerofoil\\ConvertedResources\\%s%i.ico", prefix, resID);
std::string outPath = (
std::ostringstream() << "Aerofoil/ConvertedResources/" << prefix << resID << ".ico"
).str();
FILE *outF = nullptr;
errno_t outErr = fopen_s(&outF, outPath, "wb");
if (!outErr)
FILE *outF = fopen_utf8(outPath.c_str(), "wb");
if (outF)
{
IconDir iconDir;
iconDir.m_reserved = 0;
@@ -127,6 +130,8 @@ void ConvertIconFamily(PortabilityLayer::ResourceFile *resFile, int32_t iconBitm
fwrite(&iconDirEntry, 1, sizeof(IconDirEntry), outF);
fclose(outF);
}
else
perror(outPath.c_str());
delete[] pixelData;
bwBlock.Dispose();
@@ -134,12 +139,14 @@ void ConvertIconFamily(PortabilityLayer::ResourceFile *resFile, int32_t iconBitm
}
}
int main(int argc, const char **argv)
int toolMain(int argc, const char **argv)
{
FILE *f = nullptr;
errno_t err = fopen_s(&f, "Packaged\\ApplicationResources.gpr", "rb");
if (err)
return err;
FILE *f = fopen_utf8("Packaged/ApplicationResources.gpr", "rb");
if (!f)
{
perror("Cannot open Packaged/ApplicationResources.gpr");
return -1;
}
PortabilityLayer::CFileStream stream(f);

View File

@@ -8,7 +8,7 @@ x64\Release\gpr2gpa.exe "Packaged\ApplicationResources.gpr" "DefaultTimestamp.ti
x64\Release\FTagData.exe "DefaultTimestamp.timestamp" "Packaged\ApplicationResources.gpf" data ozm5 0 0 locked
x64\Release\MergeGPF.exe "Packaged\ApplicationResources.gpf"
x64\Release\GenerateFonts.exe
x64\Release\GenerateFonts.exe Resources Packaged
x64\Release\MiniRez.exe "Empty.r" Packaged\Fonts.gpr
x64\Release\gpr2gpa.exe "Packaged\Fonts.gpr" "DefaultTimestamp.timestamp" "Packaged\Fonts.gpa" -patch "Packaged\FontCacheManifest.json"

View File

@@ -1,6 +1,6 @@
#include <stdio.h>
#include <string>
#include <Windows.h>
#include "MacFileInfo.h"
#include "CFileStream.h"
#include "CombinedTimestamp.h"

View File

@@ -1,3 +1,7 @@
#include <algorithm>
#include <string>
#include <vector>
#include "FontFamily.h"
#include "FontManager.h"
#include "FontRenderer.h"
@@ -7,8 +11,6 @@
#include "GpAppInterface.h"
#include "GpDriverIndex.h"
#include "GpFontHandlerProperties.h"
#include "GpFileSystem_Win32.h"
#include "GpSystemServices_Win32.h"
#include "CFileStream.h"
#include "PLDrivers.h"
@@ -17,7 +19,11 @@
#include "WindowsUnicodeToolShim.h"
extern "C" __declspec(dllimport) IGpFontHandler *GpDriver_CreateFontHandler_FreeType2(const GpFontHandlerProperties &properties);
extern "C"
#ifdef _MSC_VER
__declspec(dllimport)
#endif
IGpFontHandler *GpDriver_CreateFontHandler_FreeType2(const GpFontHandlerProperties &properties);
class MemBufferStream final : public GpIOStream
{
@@ -168,6 +174,16 @@ bool KnownFontSpec::operator!=(const KnownFontSpec &other) const
int toolMain(int argc, const char **argv)
{
if (argc < 3)
{
fputs("Usage: GenerateFonts <resources dir> <output dir>\n", stderr);
return -1;
}
std::string resourcesDir(argv[1]);
resourcesDir += '/';
std::string outputDir(argv[2]);
outputDir += '/';
IGpAllocator *alloc = GpAllocator_C::GetInstance();
GpFontHandlerProperties fhProperties;
@@ -187,12 +203,13 @@ int toolMain(int argc, const char **argv)
std::vector<PortabilityLayer::RenderedFontCatalogRFontEntry> catalog;
std::vector<KnownFontSpec> fontSpecs;
FILE *manifestF = fopen_utf8("Packaged/FontCacheManifest.json", "wb");
std::string tmpPath(outputDir + "FontCacheManifest.json");
FILE *manifestF = fopen_utf8(tmpPath.c_str(), "wb");
fprintf(manifestF, "{\n");
fprintf(manifestF, "\t\"add\" :\n");
fprintf(manifestF, "\t{\n");
fprintf(manifestF, "\t\t\"RFCT/1000.bin\" : \"Packaged/FontCacheCatalog.bin\"");
fprintf(manifestF, "\t\t\"RFCT/1000.bin\" : \"%sFontCacheCatalog.bin\"", outputDir.c_str());
int numFontsEmitted = 0;
for (int presetIndex = 0; presetIndex < PortabilityLayer::FontPresets::kCount; presetIndex++)
@@ -220,8 +237,9 @@ int toolMain(int argc, const char **argv)
fontSpecs.push_back(spec);
std::string resPath = std::string("Resources/") + path;
FILE *fontFile = fopen_utf8(resPath.c_str(), "rb");
tmpPath = resourcesDir;
tmpPath += path;
FILE *fontFile = fopen_utf8(tmpPath.c_str(), "rb");
if (fontFile)
{
@@ -236,7 +254,7 @@ int toolMain(int argc, const char **argv)
{
char fontPath[1024];
sprintf(fontPath, "Packaged/CachedFont%i.bin", numFontsEmitted);
sprintf(fontPath, "%sCachedFont%i.bin", outputDir.c_str(), numFontsEmitted);
FILE *cachedFontF = fopen_utf8(fontPath, "wb");
PortabilityLayer::CFileStream cacheStream(cachedFontF);
@@ -290,7 +308,9 @@ int toolMain(int argc, const char **argv)
PortabilityLayer::RenderedFontCatalogHeader catHeader;
FILE *catF = fopen_utf8("Packaged/FontCacheCatalog.bin", "wb");
tmpPath = outputDir;
tmpPath += "FontCacheCatalog.bin";
FILE *catF = fopen_utf8(tmpPath.c_str(), "wb");
catHeader.m_version = PortabilityLayer::RenderedFontCatalogHeader::kVersion;
catHeader.m_pathsOffset = static_cast<uint32_t>(sizeof(PortabilityLayer::RenderedFontCatalogHeader) + paths.size() * sizeof(PortabilityLayer::RenderedFontCatalogPathEntry) + numFontsEmitted * sizeof(PortabilityLayer::RenderedFontCatalogRFontEntry));

View File

@@ -1,5 +1,6 @@
#pragma once
#include <stddef.h>
#include <stdint.h>
struct GpRenderedGlyphMetrics

View File

@@ -1,18 +1,49 @@
Linux support is IN ALPHA and may or may not work. Only Cygwin has been
tested so far.
Linux support is IN ALPHA and may or may not work.
You can attempt the following:
- Install CMake (https://cmake.org/download/)
- Install SDL 2.0.12 or higher, or build it from the included source
- Run "cmake ." in the Aerofoil source directory
- Run "make install" to build the AerofoilX program
- Unzip the the Windows build
- Copy the "Packaged" and "Resources" directories from the Windows build into
the "lib" folder above the "bin" folder that the AerofoilX program installed
to. For example, if it installed to /usr/local/bin/, then the data files
should go in /usr/local/lib/aerofoil/
- Run AerofoilX
Use these basic steps to build and install Aerofoil:
- Ensure dependencies are installed - all of these are likely available from
your distribution's package manager:
- CMake 3.10 or later (https://cmake.org/download/)
- SDL 2.0.12 or later (https://libsdl.org)
- FreeType 2.10.1 or later (https://freetype.org/download.html)
- Change directory to the Aerofoil source root (the directory containing this file)
- Run "cmake -B build" to create a CMake build tree under "build"
- Run "cmake --build build" to build the AerofoilX program and its resources
- Run "cmake --install build" to install everything under /usr/local
- You can now run Aerofoil with the command "AerofoilX"
You can also build just the AerofoilX executable and use the prebuilt resources
from the Windows release:
- Follow the steps above, ignoring the FreeType dependency and stopping after
running "cmake -B build"
- Run "cmake --build build --target Executable" to build only the executable
- Run "cmake --install build --component Executable" to install AerofoilX in
/usr/local/bin
- Download the Windows build from
https://github.com/elasota/Aerofoil/releases/latest and unzip it
- Create the directory /usr/local/lib/aerofoil and copy the "Packaged"
directory from the Windows build into it
To install under a prefix other than /usr/local add
"-DCMAKE_INSTALL_PREFIX=<prefix>" to "cmake -B build"
Tools for converting Glider PRO houses are installed under
/usr/local/lib/aerofoil/tools, see Documentation/userhouses.txt for
instructions on how to use them.
The main AerofoilX executable, its required resources and the conversion tools
can be built and installed individually via these build targets and install
components:
- Executable
- Resources
- Tools
For instance, you can use
cmake --build build --target Executable Resources
to build only Aerofoil and its resources, and
cmake --install build --component Executable
cmake --install build --component Resources
to install them.
Please report any issues that you experience with this to the issue tracker on
GitHub.

View File

@@ -1,6 +1,13 @@
#ifdef _WIN32
#include <Windows.h>
#include <stdio.h>
#include <stdint.h>
#include <cstdint>
#else
#include <cstring>
#include <ctime>
#endif
#include <cstdio>
#include "CombinedTimestamp.h"
@@ -13,6 +20,7 @@ int main(int argc, const char **argv)
return -1;
}
#ifdef _WIN32
SYSTEMTIME epochStart;
epochStart.wYear = 1904;
epochStart.wMonth = 1;
@@ -34,13 +42,6 @@ int main(int argc, const char **argv)
int64_t currentTime64 = (static_cast<int64_t>(timestampFT.dwLowDateTime) & 0xffffffff) | (static_cast<int64_t>(timestampFT.dwHighDateTime) << 32);
int64_t timeDelta = (currentTime64 - epochStart64) / 10000000;
FILE *f = nullptr;
if (fopen_s(&f, argv[1], "wb"))
{
fprintf(stderr, "Error opening output file");
return -1;
}
TIME_ZONE_INFORMATION tz;
GetTimeZoneInformation(&tz);
@@ -60,9 +61,36 @@ int main(int argc, const char **argv)
ts.m_localHour = localST.wHour;
ts.m_localMinute = localST.wMinute;
ts.m_localSecond = localST.wSecond;
#else
time_t currentTimeUnix = time(nullptr);
tm *currentTimeStruct = localtime(&currentTimeUnix);
if (currentTimeStruct == nullptr) {
fprintf(stderr, "Error converting system time to calendar format");
return -1;
}
PortabilityLayer::CombinedTimestamp ts;
ts.SetMacEpochTime(currentTimeUnix + ts.kMacEpochToUTC);
ts.SetLocalYear(currentTimeStruct->tm_year + 1900);
ts.m_localMonth = currentTimeStruct->tm_mon + 1;
ts.m_localDay = currentTimeStruct->tm_mday;
ts.m_localHour = currentTimeStruct->tm_hour;
ts.m_localMinute = currentTimeStruct->tm_min;
ts.m_localSecond = currentTimeStruct->tm_sec;
#endif
memset(ts.m_padding, 0, sizeof(ts.m_padding));
FILE *f = fopen(argv[1], "wb");
if (!f)
{
perror("Error opening output file");
return -1;
}
fwrite(&ts, sizeof(ts), 1, f);
fclose(f);

View File

@@ -1,3 +1,4 @@
#include <algorithm>
#include <stdio.h>
#include <string>
#include <vector>

View File

@@ -0,0 +1,99 @@
#include "WindowsUnicodeToolShim.h"
#include <cstdio>
#include <cstring>
#include <string>
#include <utility>
#include <vector>
#include <dirent.h>
#include <sys/stat.h>
// Linux and macOS (and probably other non-Windows systems in general) do not
// have separate file system or command line APIs for different text encodings.
// On these systems UTF-8 is commonly the system encoding and, if so, argv will
// typically be UTF-8 encoded, though it is the calling process's responsibility
// to ensure this, as argv is passed verbatim as a sequence of byte strings.
//
// Filesystems on Unix-like systems are typically encoding-unaware, in which
// case the actual encoding used should match the system encoding, or else
// manual intervention is required.
//
// On macOS, HFS+ and APFS filenames are encoded as UTF-16 and UTF-8
// respectively, and the C filesystem API accepts UTF-8 strings. There are some
// gotchas relating to Unicode normalization, where HFS+ enforces a specific
// form of normalization at the filesystem layer but APFS does not, and using
// the C API to access the filesystem may avoid automatic normalization that
// higher-level macOS API functions may perform.
//
// In summary, text encoding is still a hairy problem on every computer system,
// though on the major non-Windows systems, assuming UTF-8 encoding is
// reasonable. For now, this header simply maps the WindowsUnicodeToolShim
// functions to their regular C API counterparts.
int toolMain(int argc, const char **argv);
int main(int argc, const char **argv) { return toolMain(argc, argv); }
FILE *fopen_utf8(const char *path, const char *options) { return fopen(path, options); }
int fputs_utf8(const char *str, FILE *f) { return fputs(str, f); }
int mkdir_utf8(const char *path) { return mkdir(path, 0777); }
void TerminateDirectoryPath(std::string &path)
{
const size_t len = path.length();
if (len == 0 || path[len - 1] != '/')
path.push_back('/');
}
void ScanDirectoryForExtension
(
std::vector<std::string> &outPaths,
const char *path,
const char *ending,
bool recursive
) {
DIR *dir = opendir(path);
if (!dir)
{
return;
}
size_t endingLen = strlen(ending);
dirent *ent;
while ((ent = readdir(dir)))
{
if (strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0)
continue;
else if (recursive && ent->d_type == DT_DIR)
{
std::string tmpPath(path);
tmpPath.append("/");
tmpPath.append(ent->d_name);
ScanDirectoryForExtension(
outPaths,
tmpPath.c_str(),
ending,
recursive
);
}
else
{
size_t nameLen = strlen(ent->d_name);
if (endingLen <= nameLen && memcmp
(
ent->d_name + nameLen - endingLen,
ending,
endingLen
) == 0
) {
std::string tmpPath(path);
tmpPath.append("/");
tmpPath.append(ent->d_name);
outPaths.push_back(std::move(tmpPath));
}
}
}
closedir(dir);
}

View File

@@ -8,6 +8,7 @@ int mkdir_utf8(const char *path);
void TerminateDirectoryPath(std::string &path);
void ScanDirectoryForExtension(std::vector<std::string>& outPaths, const char *path, const char *ending, bool recursive);
#ifdef _WIN32
struct DirectoryScanContext;
struct DirectoryScanEntry
{
@@ -17,3 +18,11 @@ struct DirectoryScanEntry
DirectoryScanContext *opendir_utf8(const char *name);
DirectoryScanEntry *readdir_utf8(DirectoryScanContext *dir);
void closedir_utf8(DirectoryScanContext *context);
#else
inline int _fseeki64(FILE *stream, long offset, int whence) {
return fseek(stream, offset, whence);
}
inline long _ftelli64(FILE *stream) { return ftell(stream); };
#endif

View File

@@ -31,9 +31,9 @@
#include <stdio.h>
#include <string>
#include <sstream>
#include <utility>
#include <vector>
#include <algorithm>
#include "GpWindows.h"
enum AudioCompressionCodecID
{
@@ -98,6 +98,11 @@ void AppendFmt(std::vector<uint8_t> &array, const char *fmt, ...)
if (resultSize <= 0)
return;
// vsnprintf invalidates the va_list, so we need to
// reinit args so the next call doesn't print garbage.
va_end(args);
va_start(args, fmt);
size_t appendSize = static_cast<size_t>(resultSize);
if (SIZE_MAX == appendSize)
@@ -1466,7 +1471,7 @@ bool DecompressSound(int compressionID, int channelCount, const void *sndData, s
}
}
}
else if (compressionID = AudioCompressionCodecID_SixToOne)
else if (compressionID == AudioCompressionCodecID_SixToOne)
{
if (channelCount != 1)
{
@@ -2427,14 +2432,11 @@ int ConvertSingleFile(const char *resPath, const PortabilityLayer::CombinedTimes
const size_t numRefs = typeList.m_numRefs;
{
char subName[256];
sprintf_s(subName, "%s", resTag.m_id);
PlannedEntry entry;
entry.m_name = subName;
entry.m_name = resTag.m_id;
entry.m_isDirectory = true;
contents.push_back(entry);
contents.push_back(std::move(entry));
}
for (size_t rlIndex = 0; rlIndex < numRefs; rlIndex++)
@@ -2453,14 +2455,15 @@ int ConvertSingleFile(const char *resPath, const PortabilityLayer::CombinedTimes
if (typeList.m_resType == pictTypeID || typeList.m_resType == dateTypeID)
{
char resName[256];
sprintf_s(resName, "%s/%i.bmp", resTag.m_id, static_cast<int>(res.m_resID));
std::string resName = (
std::ostringstream() << resTag.m_id << '/' << res.m_resID << ".bmp"
).str();
if (ContainsName(reservedNames, resName))
if (ContainsName(reservedNames, resName.c_str()))
continue;
PlannedEntry entry;
entry.m_name = resName;
entry.m_name = std::move(resName);
entry.m_comment = resComment;
if (ImportPICT(entry.m_uncompressedContents, resData, resSize, dumpqtDir, res.m_resID))
@@ -2470,14 +2473,15 @@ int ConvertSingleFile(const char *resPath, const PortabilityLayer::CombinedTimes
}
else if (typeList.m_resType == sndTypeID)
{
char resName[256];
sprintf_s(resName, "%s/%i.wav", resTag.m_id, static_cast<int>(res.m_resID));
std::string resName = (
std::ostringstream() << resTag.m_id << '/' << res.m_resID << ".wav"
).str();
if (ContainsName(reservedNames, resName))
if (ContainsName(reservedNames, resName.c_str()))
continue;
PlannedEntry entry;
entry.m_name = resName;
entry.m_name = std::move(resName);
entry.m_comment = resComment;
if (ImportSound(entry.m_uncompressedContents, resData, resSize, res.m_resID))
@@ -2487,14 +2491,15 @@ int ConvertSingleFile(const char *resPath, const PortabilityLayer::CombinedTimes
}
else if (typeList.m_resType == indexStringTypeID)
{
char resName[256];
sprintf_s(resName, "%s/%i.txt", resTag.m_id, static_cast<int>(res.m_resID));
std::string resName = (
std::ostringstream() << resTag.m_id << '/' << res.m_resID << ".txt"
).str();
if (ContainsName(reservedNames, resName))
if (ContainsName(reservedNames, resName.c_str()))
continue;
PlannedEntry entry;
entry.m_name = resName;
entry.m_name = std::move(resName);
entry.m_comment = resComment;
if (ImportIndexedString(entry.m_uncompressedContents, resData, resSize))
@@ -2502,14 +2507,15 @@ int ConvertSingleFile(const char *resPath, const PortabilityLayer::CombinedTimes
}
else if (typeList.m_resType == ditlTypeID)
{
char resName[256];
sprintf_s(resName, "%s/%i.json", resTag.m_id, static_cast<int>(res.m_resID));
std::string resName = (
std::ostringstream() << resTag.m_id << '/' << res.m_resID << ".json"
).str();
if (ContainsName(reservedNames, resName))
if (ContainsName(reservedNames, resName.c_str()))
continue;
PlannedEntry entry;
entry.m_name = resName;
entry.m_name = std::move(resName);
entry.m_comment = resComment;
if (ImportDialogItemTemplate(entry.m_uncompressedContents, resData, resSize))
@@ -2524,15 +2530,16 @@ int ConvertSingleFile(const char *resPath, const PortabilityLayer::CombinedTimes
const IconTypeSpec &iconSpec = iconTypeSpecs[i];
if (typeList.m_resType == iconSpec.m_resTypeID)
{
char resName[256];
sprintf_s(resName, "%s/%i.bmp", resTag.m_id, static_cast<int>(res.m_resID));
std::string resName = (
std::ostringstream() << resTag.m_id << '/' << res.m_resID << ".bmp"
).str();
if (!ContainsName(reservedNames, resName))
if (!ContainsName(reservedNames, resName.c_str()))
{
isIcon = true;
PlannedEntry entry;
entry.m_name = resName;
entry.m_name = std::move(resName);
entry.m_comment = resComment;
if (ImportIcon(entry.m_uncompressedContents, resData, resSize, iconSpec.m_width, iconSpec.m_height, iconSpec.m_bpp))
@@ -2545,15 +2552,16 @@ int ConvertSingleFile(const char *resPath, const PortabilityLayer::CombinedTimes
if (!isIcon)
{
char resName[256];
sprintf_s(resName, "%s/%i.bin", resTag.m_id, static_cast<int>(res.m_resID));
std::string resName = (
std::ostringstream() << resTag.m_id << '/' << res.m_resID << ".bin"
).str();
if (ContainsName(reservedNames, resName))
if (ContainsName(reservedNames, resName.c_str()))
continue;
PlannedEntry entry;
entry.m_name = resName;
entry.m_name = std::move(resName);
entry.m_comment = resComment;
entry.m_uncompressedContents.resize(res.GetSize());

View File

@@ -1,5 +1,7 @@
#pragma once
#include <cstdint>
#include "IDecompressor.h"
class CompactProRLEDecompressor : public IDecompressor

View File

@@ -1,6 +1,6 @@
#pragma once
#include <stdint.h>
#include <cstddef>
struct CSInputBuffer;

View File

@@ -1,6 +1,7 @@
#pragma once
#include <stdint.h>
#include <cstddef>
#include <cstdint>
struct IFileReader
{

View File

@@ -1,3 +1,5 @@
#include <climits>
#include "PrefixCode.h"
struct XADCodeTreeNode

View File

@@ -1,5 +1,7 @@
#pragma once
#include <cstdint>
#include "IDecompressor.h"
class RLE90Decompressor : public IDecompressor

View File

@@ -28,9 +28,6 @@
#include <string.h>
#include <Windows.h>
#include <shellapi.h>
#include <string>
#include <vector>
@@ -387,7 +384,7 @@ int ExtractItem(int depth, const ArchiveItem &item, const std::string &dirPath,
{
mkdir_utf8(path.c_str());
path.append("\\");
path.append("/");
int returnCode = RecursiveExtractFiles(depth + 1, item.m_children, path, pathParanoid, reader, ts);
if (returnCode)