MSVC build fixes

This commit is contained in:
Jack Andersen 2015-07-22 09:14:50 -10:00
parent 4d4636f2e7
commit 9e27a9d07b
34 changed files with 541 additions and 221 deletions

View File

@ -1,5 +1,10 @@
cmake_minimum_required(VERSION 3.0)
project(hecl)
if(WIN32)
add_definitions(-DUNICODE=1 -D_UNICODE=1 -D_CRT_SECURE_NO_WARNINGS=1 /wd4267 /wd4244)
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wno-multichar")
endif()
set(HECL_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/include)
set(ATHENA_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/extern/Athena/include)
set(LOG_VISOR_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/extern/LogVisor/include)
@ -9,7 +14,6 @@ set(SQUISH_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/extern/libSquish)
add_definitions(-DAS_USE_NAMESPACE=1)
add_subdirectory(extern)
include_directories(include ${LOG_VISOR_INCLUDE_DIR} ${ATHENA_INCLUDE_DIR} ${ANGELSCRIPT_INCLUDE_DIR})
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
add_subdirectory(lib)
add_subdirectory(blender)
add_subdirectory(driver)

25
hecl/DataSpecRegistry.hpp Normal file
View File

@ -0,0 +1,25 @@
#include "HECL/Database.hpp"
namespace HECL
{
namespace Database
{
/* Centralized registry for DataSpec lookup */
std::vector<const struct DataSpecEntry*> DATA_SPEC_REGISTRY;
}
}
/* RetroCommon specs */
namespace Retro
{
extern HECL::Database::DataSpecEntry SpecEntMP1;
extern HECL::Database::DataSpecEntry SpecEntMP2;
extern HECL::Database::DataSpecEntry SpecEntMP3;
}
extern "C" void HECLDataSpecs()
{
HECL::Printf(Retro::SpecEntMP1.m_name);
HECL::Printf(Retro::SpecEntMP2.m_name);
HECL::Printf(Retro::SpecEntMP3.m_name);
}

View File

@ -5,19 +5,23 @@
#include <system_error>
#include <string>
#include <HECL/HECL.hpp>
#include <LogVisor/LogVisor.hpp>
#include "BlenderConnection.hpp"
static LogVisor::LogModule Log("BlenderConnection");
#ifdef __APPLE__
#define DEFAULT_BLENDER_BIN "/Applications/Blender.app/Contents/MacOS/blender"
#elif _WIN32
#define DEFAULT_BLENDER_BIN "%ProgramFiles%\\Blender Foundation\\Blender\\blender.exe"
#define DEFAULT_BLENDER_BIN _S("%ProgramFiles%\\Blender Foundation\\Blender\\blender.exe")
#else
#define DEFAULT_BLENDER_BIN "blender"
#endif
#define TEMP_SHELLSCRIPT "/home/jacko/hecl/blender/blendershell.py"
size_t CBlenderConnection::_readLine(char* buf, size_t bufSz)
size_t BlenderConnection::_readLine(char* buf, size_t bufSz)
{
size_t readBytes = 0;
while (true)
@ -28,9 +32,15 @@ size_t CBlenderConnection::_readLine(char* buf, size_t bufSz)
*(buf-1) = '\0';
return bufSz - 1;
}
#if _WIN32
DWORD ret = 0;
if (!ReadFile(m_readpipe[0], buf, 1, &ret, NULL))
goto err;
#else
ssize_t ret = read(m_readpipe[0], buf, 1);
if (ret < 0)
goto err;
#endif
else if (ret == 1)
{
if (*buf == '\n')
@ -52,8 +62,15 @@ err:
return 0;
}
size_t CBlenderConnection::_writeLine(const char* buf)
size_t BlenderConnection::_writeLine(const char* buf)
{
#if _WIN32
DWORD ret = 0;
if (!WriteFile(m_writepipe[1], buf, strlen(buf), &ret, NULL))
goto err;
if (!WriteFile(m_writepipe[1], "\n", 1, NULL, NULL))
goto err;
#else
ssize_t ret, nlerr;
ret = write(m_writepipe[1], buf, strlen(buf));
if (ret < 0)
@ -61,43 +78,125 @@ size_t CBlenderConnection::_writeLine(const char* buf)
nlerr = write(m_writepipe[1], "\n", 1);
if (nlerr < 0)
goto err;
#endif
return (size_t)ret;
err:
throw std::error_code(errno, std::system_category());
}
size_t CBlenderConnection::_readBuf(char* buf, size_t len)
size_t BlenderConnection::_readBuf(char* buf, size_t len)
{
#if _WIN32
DWORD ret = 0;
if (!ReadFile(m_readpipe[0], buf, len, &ret, NULL))
goto err;
#else
ssize_t ret = read(m_readpipe[0], buf, len);
if (ret < 0)
throw std::error_code(errno, std::system_category());
goto err;
#endif
return ret;
err:
throw std::error_code(errno, std::system_category());
return 0;
}
size_t CBlenderConnection::_writeBuf(const char* buf, size_t len)
size_t BlenderConnection::_writeBuf(const char* buf, size_t len)
{
#if _WIN32
DWORD ret = 0;
if (!WriteFile(m_writepipe[1], buf, len, &ret, NULL))
goto err;
#else
ssize_t ret = write(m_writepipe[1], buf, len);
if (ret < 0)
throw std::error_code(errno, std::system_category());
goto err;
#endif
return ret;
err:
throw std::error_code(errno, std::system_category());
return 0;
}
void CBlenderConnection::_closePipe()
void BlenderConnection::_closePipe()
{
#if _WIN32
CloseHandle(m_readpipe[0]);
CloseHandle(m_writepipe[1]);
#else
close(m_readpipe[0]);
close(m_writepipe[1]);
#endif
}
CBlenderConnection::CBlenderConnection(bool silenceBlender)
BlenderConnection::BlenderConnection(bool silenceBlender)
{
/* Construct communication pipes */
#if _WIN32
SECURITY_ATTRIBUTES sattrs = {sizeof(SECURITY_ATTRIBUTES), NULL, TRUE};
CreatePipe(&m_readpipe[0], &m_readpipe[1], &sattrs, 0);
CreatePipe(&m_writepipe[0], &m_writepipe[1], &sattrs, 0);
#else
pipe(m_readpipe);
pipe(m_writepipe);
#endif
/* User-specified blender path */
#if _WIN32
wchar_t BLENDER_BIN_BUF[2048];
wchar_t* blenderBin = _wgetenv(L"BLENDER_BIN");
#else
char* blenderBin = getenv("BLENDER_BIN");
#endif
/* Child process of blender */
#if _WIN32
if (!blenderBin)
{
/* Environment not set; use registry */
HKEY blenderKey;
if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\BlenderFoundation", 0, KEY_READ, &blenderKey) == ERROR_SUCCESS)
{
DWORD bufSz = sizeof(BLENDER_BIN_BUF);
if (RegGetValueW(blenderKey, NULL, L"Install_Dir", REG_SZ, NULL, BLENDER_BIN_BUF, &bufSz) == ERROR_SUCCESS)
{
wcscat_s(BLENDER_BIN_BUF, 2048, L"\\blender.exe");
blenderBin = BLENDER_BIN_BUF;
}
RegCloseKey(blenderKey);
}
}
if (!blenderBin)
{
Log.report(LogVisor::FatalError, "unable to find blender");
return;
}
wchar_t cmdLine[2048];
_snwprintf(cmdLine, 2048, L" --background -P shellscript.py -- %08X %08X",
(uint32_t)m_writepipe[0], (uint32_t)m_readpipe[1]);
STARTUPINFO sinfo = {sizeof(STARTUPINFO)};
HANDLE nulHandle = NULL;
if (silenceBlender)
{
nulHandle = CreateFileW(L"nul", GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, &sattrs, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
sinfo.hStdError = nulHandle;
sinfo.hStdOutput = nulHandle;
sinfo.dwFlags = STARTF_USESTDHANDLES;
}
PROCESS_INFORMATION pinfo;
if (!CreateProcessW(blenderBin, cmdLine, NULL, NULL, TRUE, NORMAL_PRIORITY_CLASS, NULL, NULL, &sinfo, &pinfo))
Log.report(LogVisor::FatalError, "unable to launch blender");
CloseHandle(m_writepipe[1]);
CloseHandle(m_readpipe[0]);
if (nulHandle)
CloseHandle(nulHandle);
#else
pid_t pid = fork();
if (!pid)
{
@ -149,6 +248,7 @@ CBlenderConnection::CBlenderConnection(bool silenceBlender)
close(m_writepipe[0]);
close(m_readpipe[1]);
m_blenderProc = pid;
#endif
/* Handle first response */
char lineBuf[256];
@ -156,40 +256,38 @@ CBlenderConnection::CBlenderConnection(bool silenceBlender)
if (!strcmp(lineBuf, "NOLAUNCH"))
{
_closePipe();
throw std::runtime_error("Unable to launch blender");
Log.report(LogVisor::FatalError, "Unable to launch blender");
}
else if (!strcmp(lineBuf, "NOBLENDER"))
{
_closePipe();
if (blenderBin)
throw std::runtime_error("Unable to find blender at '" +
std::string(blenderBin) + "' or '" +
std::string(DEFAULT_BLENDER_BIN) + "'");
Log.report(LogVisor::FatalError, _S("Unable to find blender at '%s' or '%s'"),
blenderBin, DEFAULT_BLENDER_BIN);
else
throw std::runtime_error("Unable to find blender at '" +
std::string(DEFAULT_BLENDER_BIN) + "'");
Log.report(LogVisor::FatalError, _S("Unable to find blender at '%s'"),
DEFAULT_BLENDER_BIN);
}
else if (!strcmp(lineBuf, "NOADDON"))
{
_closePipe();
throw std::runtime_error("HECL addon not installed within blender");
Log.report(LogVisor::FatalError, "HECL addon not installed within blender");
}
else if (strcmp(lineBuf, "READY"))
{
_closePipe();
throw std::runtime_error("read '" + std::string(lineBuf) +
"' from blender; expected 'READY'");
Log.report(LogVisor::FatalError, "read '%s' from blender; expected 'READY'", lineBuf);
}
_writeLine("ACK");
}
CBlenderConnection::~CBlenderConnection()
BlenderConnection::~BlenderConnection()
{
_closePipe();
}
bool CBlenderConnection::openBlend(const std::string& path)
bool BlenderConnection::openBlend(const std::string& path)
{
_writeLine(("OPEN" + path).c_str());
char lineBuf[256];
@ -202,7 +300,7 @@ bool CBlenderConnection::openBlend(const std::string& path)
return false;
}
bool CBlenderConnection::cookBlend(std::function<char*(uint32_t)> bufGetter,
bool BlenderConnection::cookBlend(std::function<char*(uint32_t)> bufGetter,
const std::string& expectedType,
const std::string& platform,
bool bigEndian)
@ -238,7 +336,7 @@ bool CBlenderConnection::cookBlend(std::function<char*(uint32_t)> bufGetter,
return false;
}
void CBlenderConnection::quitBlender()
void BlenderConnection::quitBlender()
{
_writeLine("QUIT");
char lineBuf[256];

View File

@ -1,5 +1,5 @@
#ifndef CBLENDERCONNECTION_HPP
#define CBLENDERCONNECTION_HPP
#ifndef BLENDERCONNECTION_HPP
#define BLENDERCONNECTION_HPP
#if _WIN32
#define _WIN32_LEAN_AND_MEAN 1
@ -8,15 +8,16 @@
#include <unistd.h>
#endif
#include <stdint.h>
#include <string>
#include <functional>
class CBlenderConnection
class BlenderConnection
{
#if _WIN32
HANDLE m_blenderProc;
HANDLE m_readpipe;
HANDLE m_writepipe;
HANDLE m_readpipe[2];
HANDLE m_writepipe[2];
#else
pid_t m_blenderProc;
int m_readpipe[2];
@ -29,8 +30,8 @@ class CBlenderConnection
size_t _writeBuf(const char* buf, size_t len);
void _closePipe();
public:
CBlenderConnection(bool silenceBlender=false);
~CBlenderConnection();
BlenderConnection(bool silenceBlender=false);
~BlenderConnection();
bool openBlend(const std::string& path);
enum CookPlatform
@ -45,4 +46,4 @@ public:
void quitBlender();
};
#endif // CBLENDERCONNECTION_HPP
#endif // BLENDERCONNECTION_HPP

View File

@ -1,3 +1,7 @@
if(WIN32)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /INCLUDE:HECLDataSpecs")
endif()
add_executable(hecl main.cpp
ToolBase.hpp
ToolPackage.hpp
@ -19,7 +23,12 @@ list(APPEND DATA_SPEC_LIBS
DNAMP2
DNAMP3)
if(NOT WIN32)
set(WHOLE_START "-Wl,-whole-archive")
set(WHOLE_END "-Wl,-no-whole-archive")
endif()
target_link_libraries(hecl
"-Wl,-whole-archive" HECLDatabaseInit ${DATA_SPEC_LIBS} "-Wl,-no-whole-archive"
HECLDatabase HECL AthenaCore AngelScript NOD LogVisor png squish blowfish z lzo2
${WHOLE_START} HECLDatabaseInit ${DATA_SPEC_LIBS} ${WHOLE_END}
HECLDatabase HECLCommon AthenaCore AngelScript NOD LogVisor png squish blowfish z lzo2
)

View File

@ -26,15 +26,15 @@ public:
help.secHead(_S("DESCRIPTION"));
help.beginWrap();
help.wrap(_S("This command stages a file or glob-pattern of files within the project database "
"for inclusion in the "));
help.wrap(_S("This command stages a file or glob-pattern of files within the project database ")
_S("for inclusion in the "));
help.wrapBold(_S("hecl cook"));
help.wrap(_S(" process.\n\n"
"Files added in this manner automatically become 'explicit' database "
"objects. 'Explicit objects' will not be removed in housekeeping tasks automatically "
"performed by HECL's library functions, unless the user (re)moves the file "
"using the filesystem.\n\n"
"For details on explicit vs. implicit objects, view the "));
help.wrap(_S(" process.\n\n")
_S("Files added in this manner automatically become 'explicit' database ")
_S("objects. 'Explicit objects' will not be removed in housekeeping tasks automatically ")
_S("performed by HECL's library functions, unless the user (re)moves the file ")
_S("using the filesystem.\n\n")
_S("For details on explicit vs. implicit objects, view the "));
help.wrapBold(_S("hecl cook"));
help.wrap(_S(" documentation.\n"));
help.endWrap();
@ -42,8 +42,8 @@ public:
help.secHead(_S("OPTIONS"));
help.optionHead(_S("<pathspec>..."), _S("input file(s)"));
help.beginWrap();
help.wrap(_S("Working file(s) containing production data to be cooked by HECL. "
"Glob-strings may be specified (e.g. "));
help.wrap(_S("Working file(s) containing production data to be cooked by HECL. ")
_S("Glob-strings may be specified (e.g. "));
help.wrapBold(_S("*.blend"));
help.wrap(_S(") to automatically add all matching files to the database.\n"));
help.endWrap();

View File

@ -4,9 +4,12 @@
#include <string>
#include <vector>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#ifndef _WIN32
#include <unistd.h>
#endif
#include "HECL/Database.hpp"
#include "LogVisor/LogVisor.hpp"
@ -151,26 +154,38 @@ public:
void printBold(const HECL::SystemChar* str)
{
#if _WIN32
HECL::FPrintf(m_sout, _S("%s"), str);
#else
if (XTERM_COLOR)
HECL::FPrintf(m_sout, _S("" BOLD "%s" NORMAL ""), str);
else
HECL::FPrintf(m_sout, _S("%s"), str);
#endif
}
void secHead(const HECL::SystemChar* headName)
{
#if _WIN32
HECL::FPrintf(m_sout, _S("%s\n"), headName);
#else
if (XTERM_COLOR)
HECL::FPrintf(m_sout, _S("" BOLD "%s" NORMAL "\n"), headName);
else
HECL::FPrintf(m_sout, _S("%s\n"), headName);
#endif
}
void optionHead(const HECL::SystemChar* flag, const HECL::SystemChar* synopsis)
{
#if _WIN32
HECL::FPrintf(m_sout, _S("%s (%s)\n"), flag, synopsis);
#else
if (XTERM_COLOR)
HECL::FPrintf(m_sout, _S("" BOLD "%s" NORMAL " (%s)\n"), flag, synopsis);
else
HECL::FPrintf(m_sout, _S("%s (%s)\n"), flag, synopsis);
#endif
}
void beginWrap()
@ -185,11 +200,15 @@ public:
void wrapBold(const HECL::SystemChar* str)
{
#if _WIN32
m_wrapBuffer += str;
#else
if (XTERM_COLOR)
m_wrapBuffer += _S("" BOLD "");
m_wrapBuffer += str;
if (XTERM_COLOR)
m_wrapBuffer += _S("" NORMAL "");
#endif
}
void endWrap()

View File

@ -30,19 +30,19 @@ public:
help.secHead(_S("DESCRIPTION"));
help.beginWrap();
help.wrap(_S("This command performs an immediate deletion of cooked objects cached "
"within the project database. It may operate on a subset of objects or the "
"entire project.\n"));
help.wrap(_S("This command performs an immediate deletion of cooked objects cached ")
_S("within the project database. It may operate on a subset of objects or the ")
_S("entire project.\n"));
help.endWrap();
help.secHead(_S("OPTIONS"));
help.optionHead(_S("<pathspec>..."), _S("clean path(s)"));
help.beginWrap();
help.wrap(_S("When one or more paths are specified in the command, the clean process will "
"restrict object deletion to only the working file(s) specified. If "));
help.wrap(_S("When one or more paths are specified in the command, the clean process will ")
_S("restrict object deletion to only the working file(s) specified. If "));
help.wrapBold(_S("-r"));
help.wrap(_S(" is also specifed, directories may be provided as well. If no path(s) specified, "
"the entire project is cleaned.\n"));
help.wrap(_S(" is also specifed, directories may be provided as well. If no path(s) specified, ")
_S("the entire project is cleaned.\n"));
help.endWrap();
help.optionHead(_S("-r"), _S("recursion"));
@ -52,10 +52,10 @@ public:
help.optionHead(_S("-i"), _S("follow implicit links"));
help.beginWrap();
help.wrap(_S("Enables implicit object traversal and cleaning. This is only useful if one or more paths "
"are specified. For objects supporting implicit-gathering, this will query those "
"objects for their current implicit links and ensure the linked-objects are cleaned "
"as well.\n"));
help.wrap(_S("Enables implicit object traversal and cleaning. This is only useful if one or more paths ")
_S("are specified. For objects supporting implicit-gathering, this will query those ")
_S("objects for their current implicit links and ensure the linked-objects are cleaned ")
_S("as well.\n"));
help.endWrap();
}

View File

@ -30,10 +30,10 @@ public:
help.secHead(_S("DESCRIPTION"));
help.beginWrap();
help.wrap(_S("This command initiates a cooking pass on the project database. Cooking "
"is analogous to compiling in software development. The resulting object buffers "
"are cached within the project database. HECL performs the following "
"tasks for each object during the cook process:\n\n"));
help.wrap(_S("This command initiates a cooking pass on the project database. Cooking ")
_S("is analogous to compiling in software development. The resulting object buffers ")
_S("are cached within the project database. HECL performs the following ")
_S("tasks for each object during the cook process:\n\n"));
help.wrapBold(_S("- Object Gather: "));
help.wrap(_S("Files added with "));
help.wrapBold(_S("hecl add"));
@ -43,13 +43,13 @@ public:
help.wrapBold(_S(".png"));
help.wrap(_S(" images). If the dependent files are unable to be found, the cook process aborts.\n\n"));
help.wrapBold(_S("- Modtime Comparison: "));
help.wrap(_S("Files that have previously finished a cook pass are inspected for their time of "
"last modification. If the file hasn't changed since its previous cook-pass, the "
"process is skipped. If the file has been moved or deleted, the object is automatically "
"removed from the project database.\n\n"));
help.wrap(_S("Files that have previously finished a cook pass are inspected for their time of ")
_S("last modification. If the file hasn't changed since its previous cook-pass, the ")
_S("process is skipped. If the file has been moved or deleted, the object is automatically ")
_S("removed from the project database.\n\n"));
help.wrapBold(_S("- Cook: "));
help.wrap(_S("A type-specific procedure compiles the file's contents into an efficient format "
"for use by the runtime. A data-buffer is provided to HECL.\n\n"));
help.wrap(_S("A type-specific procedure compiles the file's contents into an efficient format ")
_S("for use by the runtime. A data-buffer is provided to HECL.\n\n"));
help.wrapBold(_S("- Hash and Compress: "));
help.wrap(_S("The data-buffer is hashed and compressed before being cached in the object database.\n\n"));
help.endWrap();
@ -57,11 +57,11 @@ public:
help.secHead(_S("OPTIONS"));
help.optionHead(_S("<pathspec>..."), _S("input file(s)"));
help.beginWrap();
help.wrap(_S("Specifies working file(s) containing production data to be cooked by HECL. "
"Glob-strings may be specified (e.g. "));
help.wrap(_S("Specifies working file(s) containing production data to be cooked by HECL. ")
_S("Glob-strings may be specified (e.g. "));
help.wrapBold(_S("*.blend"));
help.wrap(_S(") to automatically cook all matching current-directory files in the project database. "
"If no path specified, all files in the project database are cooked.\n"));
help.wrap(_S(") to automatically cook all matching current-directory files in the project database. ")
_S("If no path specified, all files in the project database are cooked.\n"));
help.endWrap();
help.optionHead(_S("-r"), _S("recursion"));

View File

@ -13,6 +13,8 @@ class ToolExtract final : public ToolBase
std::unique_ptr<HECL::Database::IDataSpec> m_instance;
SpecExtractPass(const HECL::Database::DataSpecEntry* entry, HECL::Database::IDataSpec* instance)
: m_entry(entry), m_instance(instance) {}
SpecExtractPass(const SpecExtractPass& other) = delete;
SpecExtractPass(SpecExtractPass&& other) = default;
};
std::vector<SpecExtractPass> m_specPasses;
std::vector<HECL::Database::IDataSpec::ExtractReport> m_reps;
@ -60,16 +62,16 @@ public:
help.secHead(_S("DESCRIPTION"));
help.beginWrap();
help.wrap(_S("This command recursively extracts all or part of a dataspec-supported "
"package format. Each object is decoded to a working format and added to the project.\n\n"));
help.wrap(_S("This command recursively extracts all or part of a dataspec-supported ")
_S("package format. Each object is decoded to a working format and added to the project.\n\n"));
help.endWrap();
help.secHead(_S("OPTIONS"));
help.optionHead(_S("<packagefile>[/<subnode>...]"), _S("input file"));
help.beginWrap();
help.wrap(_S("Specifies the package file or disc image to source data from. "
"An optional subnode specifies a named hierarchical-node specific "
"to the game architecture (levels/areas)."));
help.wrap(_S("Specifies the package file or disc image to source data from. ")
_S("An optional subnode specifies a named hierarchical-node specific ")
_S("to the game architecture (levels/areas)."));
help.endWrap();
}
@ -79,10 +81,14 @@ public:
{
for (int l=0 ; l<level ; ++l)
HECL::Printf(_S(" "));
#if _WIN32
HECL::Printf(_S("%s"), rep.name.c_str());
#else
if (XTERM_COLOR)
HECL::Printf(_S("" BOLD "%s" NORMAL ""), rep.name.c_str());
else
HECL::Printf(_S("%s"), rep.name.c_str());
#endif
if (rep.desc.size())
HECL::Printf(_S(" [%s]"), rep.desc.c_str());
HECL::Printf(_S("\n"));
@ -94,17 +100,25 @@ public:
{
if (m_specPasses.empty())
{
#if _WIN32
HECL::Printf(_S("NOTHING TO EXTRACT\n"));
#else
if (XTERM_COLOR)
HECL::Printf(_S("" RED BOLD "NOTHING TO EXTRACT" NORMAL "\n"));
else
HECL::Printf(_S("NOTHING TO EXTRACT\n"));
#endif
return -1;
}
#if _WIN32
HECL::Printf(_S("ABOUT TO EXTRACT:\n"));
#else
if (XTERM_COLOR)
HECL::Printf(_S("" GREEN BOLD "ABOUT TO EXTRACT:" NORMAL "\n"));
else
HECL::Printf(_S("ABOUT TO EXTRACT:\n"));
#endif
for (HECL::Database::IDataSpec::ExtractReport& rep : m_reps)
{
@ -112,10 +126,14 @@ public:
HECL::Printf(_S("\n"));
}
#if _WIN32
HECL::Printf(_S("\nContinue? (Y/N) "));
#else
if (XTERM_COLOR)
HECL::Printf(_S("\n" BLUE BOLD "Continue?" NORMAL " (Y/N) "));
else
HECL::Printf(_S("\nContinue? (Y/N) "));
#endif
int ch;
while ((ch = getchar()))
@ -128,17 +146,23 @@ public:
for (SpecExtractPass& ds : m_specPasses)
{
#if _WIN32
HECL::Printf(_S("Using DataSpec %s:\n"), ds.m_entry->m_name);
#else
if (XTERM_COLOR)
HECL::Printf(_S("" MAGENTA BOLD "Using DataSpec %s:" NORMAL "\n"), ds.m_entry->m_name.c_str());
HECL::Printf(_S("" MAGENTA BOLD "Using DataSpec %s:" NORMAL "\n"), ds.m_entry->m_name);
else
HECL::Printf(_S("Using DataSpec %s:\n"), ds.m_entry->m_name.c_str());
HECL::Printf(_S("Using DataSpec %s:\n"), ds.m_entry->m_name);
#endif
int lineIdx = 0;
ds.m_instance->doExtract(*m_info.project, m_einfo,
[&lineIdx](const HECL::SystemChar* message, int lidx, float factor)
{
#ifndef _WIN32
if (XTERM_COLOR)
HECL::Printf(_S("" HIDE_CURSOR ""));
#endif
if (lidx > lineIdx)
{
@ -161,6 +185,7 @@ public:
HECL::Printf(_S(" "));
}
#ifndef _WIN32
if (XTERM_COLOR)
{
size_t blocks = half - 7;
@ -175,6 +200,7 @@ public:
}
else
{
#endif
size_t blocks = half - 7;
size_t filled = blocks * factor;
size_t rem = blocks - filled;
@ -184,11 +210,15 @@ public:
for (int b=0 ; b<rem ; ++b)
HECL::Printf(_S("-"), message);
HECL::Printf(_S("]"));
#ifndef _WIN32
}
#endif
HECL::Printf(_S("\r"));
#ifndef _WIN32
if (XTERM_COLOR)
HECL::Printf(_S("" SHOW_CURSOR ""));
#endif
});
HECL::Printf(_S("\n\n"));
}

View File

@ -32,17 +32,17 @@ public:
help.secHead(_S("DESCRIPTION"));
help.beginWrap();
help.wrap(_S("This command turns a nested subdirectory of the project into a HECL group. "
"Groups play an important role in the resulting structure of the packaged "
"database. All objects in HECL belong to a group of some sort since the runtime "
"only provides loading functions for groups. Ungrouped "
"objects in the project root are individually added to 'loose groups'.\n\n With "));
help.wrap(_S("This command turns a nested subdirectory of the project into a HECL group. ")
_S("Groups play an important role in the resulting structure of the packaged ")
_S("database. All objects in HECL belong to a group of some sort since the runtime ")
_S("only provides loading functions for groups. Ungrouped ")
_S("objects in the project root are individually added to 'loose groups'.\n\n With "));
help.wrapBold(_S("hecl group"));
help.wrap(_S(", explicit groups may be defined (e.g. a stage, level, area, loadable segment). "));
help.wrap(_S("Groups are defined by filesystem directories relative to the project root "
"and may be loaded within the runtime using the relative path as a lookup-string. "
"Sub-directories that aren't explicitly made into a group inherit the group-status "
"of the parent directory.\n"));
help.wrap(_S("Groups are defined by filesystem directories relative to the project root ")
_S("and may be loaded within the runtime using the relative path as a lookup-string. ")
_S("Sub-directories that aren't explicitly made into a group inherit the group-status ")
_S("of the parent directory.\n"));
help.endWrap();
help.secHead(_S("OPTIONS"));
@ -53,8 +53,8 @@ public:
help.optionHead(_S("-D"), _S("delete group"));
help.beginWrap();
help.wrap(_S("Remove's directory's status as an explicit group; restoring its inheritance "
"from the parent directory.\n"));
help.wrap(_S("Remove's directory's status as an explicit group; restoring its inheritance ")
_S("from the parent directory.\n"));
help.endWrap();
}

View File

@ -26,30 +26,31 @@ public:
static void Help(HelpOutput& help)
{
help.printBold(_S("................................___________ \n"
"...........................,.-'\"...........``~., \n"
"........................,.-\".......................\"-., \n"
"....................,/..................................\":, \n"
"..................,?........................................, \n"
"................/...........................................,}\n"
"............../........................................,:`^`..}\n"
"............./.......................................,:\"...../\n"
"............?.....__..................................:`...../\n"
".........../__.(...\"~-,_...........................,:`....../\n"
"........../(_....\"~,_....\"~,_.....................,:`...._/ \n"
"..........{.._$;_....\"=,_.....\"-,_......,.-~-,},.~\";/....} \n"
"...........((...*~_......\"=-._...\";,,./`........../\"..../ \n"
"...,,,___.`~,......\"~.,....................`......}....../ \n"
"............(....`=-,,...`.........................(...;_,,-\" \n"
"............/.`~,......`-.................................../ \n"
".............`~.*-,.....................................|,./...,__ \n"
",,_..........}.>-._...................................|.......`=~-, \n"
".....`=~-,__......`,................................. \n"
"...................`=~-,,.,........................... \n"
".........................`:,,..........................`\n"
"...........................`=-,...............,%%`>--==`` \n"
".................................._.........._,-%%...` \n"
"...................................,\n"));
help.printBold(
_S("................................___________ \n")
_S("...........................,.-'\"...........``~., \n")
_S("........................,.-\".......................\"-., \n")
_S("....................,/..................................\":, \n")
_S("..................,?........................................, \n")
_S("................/...........................................,}\n")
_S("............../........................................,:`^`..}\n")
_S("............./.......................................,:\"...../\n")
_S("............?.....__..................................:`...../\n")
_S(".........../__.(...\"~-,_...........................,:`....../\n")
_S("........../(_....\"~,_....\"~,_.....................,:`...._/ \n")
_S("..........{.._$;_....\"=,_.....\"-,_......,.-~-,},.~\";/....} \n")
_S("...........((...*~_......\"=-._...\";,,./`........../\"..../ \n")
_S("...,,,___.`~,......\"~.,....................`......}....../ \n")
_S("............(....`=-,,...`.........................(...;_,,-\" \n")
_S("............/.`~,......`-.................................../ \n")
_S(".............`~.*-,.....................................|,./...,__ \n")
_S(",,_..........}.>-._...................................|.......`=~-, \n")
_S(".....`=~-,__......`,................................. \n")
_S("...................`=~-,,.,........................... \n")
_S(".........................`:,,..........................`\n")
_S("...........................`=-,...............,%%`>--==`` \n")
_S(".................................._.........._,-%%...` \n")
_S("...................................,\n"));
}
static void ShowHelp(const HECL::SystemString& toolName)

View File

@ -11,7 +11,7 @@ public:
ToolInit(const ToolPassInfo& info)
: ToolBase(info)
{
struct stat theStat;
HECL::Sstat theStat;
const HECL::SystemString* dir;
if (info.args.size())
dir = &info.args[0];
@ -50,7 +50,7 @@ public:
}
catch (std::exception& e)
{
LogModule.report(LogVisor::Error, "unable to init project");
LogModule.report(LogVisor::Error, "unable to init project: %s", e.what());
return -1;
}
LogModule.report(LogVisor::Info, _S("initialized project at '%s/.hecl'"), m_dir->c_str());
@ -73,8 +73,8 @@ public:
help.beginWrap();
help.wrap(_S("Creates a "));
help.wrapBold(_S(".hecl"));
help.wrap(_S(" directory within the selected directory with an initialized database index. "
"This constitutes an empty HECL project, ready for making stuff!!\n"));
help.wrap(_S(" directory within the selected directory with an initialized database index. ")
_S("This constitutes an empty HECL project, ready for making stuff!!\n"));
help.endWrap();
help.secHead(_S("OPTIONS"));

View File

@ -24,8 +24,8 @@ public:
{
help.secHead(_S("NAME"));
help.beginWrap();
help.wrap(_S("hecl-pack\n"
"hecl-package - Package objects within the project database\n"));
help.wrap(_S("hecl-pack\n")
_S("hecl-package - Package objects within the project database\n"));
help.endWrap();
help.secHead(_S("SYNOPSIS"));
@ -35,29 +35,29 @@ public:
help.secHead(_S("DESCRIPTION"));
help.beginWrap();
help.wrap(_S("This command initiates a packaging pass on the project database. Packaging "
"is analogous to linking in software development. All objects necessary to "
"generate a complete package are gathered, grouped, and indexed within an .hlpk file.\n"));
help.wrap(_S("This command initiates a packaging pass on the project database. Packaging ")
_S("is analogous to linking in software development. All objects necessary to ")
_S("generate a complete package are gathered, grouped, and indexed within an .hlpk file.\n"));
help.endWrap();
help.secHead(_S("OPTIONS"));
help.optionHead(_S("<dir>"), _S("input directory"));
help.beginWrap();
help.wrap(_S("Specifies a project subdirectory to root the resulting package from. "
"If any dependent-files fall outside this subdirectory, they will implicitly "
"be gathered and packaged.\n"));
help.wrap(_S("Specifies a project subdirectory to root the resulting package from. ")
_S("If any dependent-files fall outside this subdirectory, they will implicitly ")
_S("be gathered and packaged.\n"));
help.endWrap();
help.optionHead(_S("-o <package-out>"), _S("output package file"));
help.beginWrap();
help.wrap(_S("Specifies a target path to write the package. If not specified, the package "
"is written into <project-root>/out/<relative-input-dirs>/<input-dir>.hlpk\n"));
help.wrap(_S("Specifies a target path to write the package. If not specified, the package ")
_S("is written into <project-root>/out/<relative-input-dirs>/<input-dir>.hlpk\n"));
help.endWrap();
help.optionHead(_S("-a"), _S("auto cook"));
help.beginWrap();
help.wrap(_S("Any referenced objects that haven't already been cooked are automatically cooked as "
"part of the packaging process. If this flag is omitted, the packaging process will abort.\n"));
help.wrap(_S("Any referenced objects that haven't already been cooked are automatically cooked as ")
_S("part of the packaging process. If this flag is omitted, the packaging process will abort.\n"));
help.endWrap();
}

View File

@ -31,16 +31,16 @@ public:
help.secHead(_S("DESCRIPTION"));
help.beginWrap();
help.wrap(_S("This command removes a file, directory, or glob-pattern of files from the project database. "
"Once a file is removed, any cooked cache objects are deleted automatically. "));
help.wrap(_S("This command removes a file, directory, or glob-pattern of files from the project database. ")
_S("Once a file is removed, any cooked cache objects are deleted automatically. "));
help.wrapBold(_S("The working file itself is not deleted from the filesystem.\n"));
help.endWrap();
help.secHead(_S("OPTIONS"));
help.optionHead(_S("<pathspec>..."), _S("input file(s)"));
help.beginWrap();
help.wrap(_S("Working file(s) to be removed from the project database. "
"Glob-strings may be specified (e.g. "));
help.wrap(_S("Working file(s) to be removed from the project database. ")
_S("Glob-strings may be specified (e.g. "));
help.wrapBold(_S("*.blend"));
help.wrap(_S(") to automatically remove all matching files from the database.\n"));
help.endWrap();

View File

@ -48,7 +48,7 @@ public:
bool found = false;
for (auto& spec : specs)
{
if (!spec.spec.m_name.compare(*it))
if (!it->compare(spec.spec.m_name))
{
found = true;
break;
@ -75,9 +75,9 @@ public:
help.secHead(_S("DESCRIPTION"));
help.beginWrap();
help.wrap(_S("This command configures the HECL project with the user's preferred target DataSpecs.\n\n"
"Providing enable/disable argument will bulk-set the enable status of the provided spec(s)"
"list. If enable/disable is not provided, a list of supported DataSpecs is printed.\n\n"));
help.wrap(_S("This command configures the HECL project with the user's preferred target DataSpecs.\n\n")
_S("Providing enable/disable argument will bulk-set the enable status of the provided spec(s)")
_S("list. If enable/disable is not provided, a list of supported DataSpecs is printed.\n\n"));
help.endWrap();
help.secHead(_S("OPTIONS"));
@ -95,11 +95,15 @@ public:
{
for (const HECL::Database::DataSpecEntry* spec : HECL::Database::DATA_SPEC_REGISTRY)
{
#if _WIN32
HECL::Printf(_S("%s\n %s\n"), spec->m_name, spec->m_desc);
#else
if (XTERM_COLOR)
HECL::Printf(_S("" BOLD CYAN "%s" NORMAL "\n"), spec->m_name.c_str());
HECL::Printf(_S("" BOLD CYAN "%s" NORMAL "\n"), spec->m_name);
else
HECL::Printf(_S("%s\n"), spec->m_name.c_str());
HECL::Printf(_S(" %s\n"), spec->m_desc.c_str());
HECL::Printf(_S("%s\n"), spec->m_name);
HECL::Printf(_S(" %s\n"), spec->m_desc);
#endif
}
return 0;
}
@ -109,10 +113,16 @@ public:
{
for (auto& spec : specs)
{
#if _WIN32
HECL::Printf(_S("%s"), spec.spec.m_name);
if (spec.active)
HECL::Printf(_S(" [ENABLED]"));
HECL::Printf(_S("\n %s\n"), spec.spec.m_desc);
#else
if (XTERM_COLOR)
HECL::Printf(_S("" BOLD CYAN "%s" NORMAL ""), spec.spec.m_name.c_str());
HECL::Printf(_S("" BOLD CYAN "%s" NORMAL ""), spec.spec.m_name);
else
HECL::Printf(_S("%s"), spec.spec.m_name.c_str());
HECL::Printf(_S("%s"), spec.spec.m_name);
if (spec.active)
{
if (XTERM_COLOR)
@ -120,7 +130,8 @@ public:
else
HECL::Printf(_S(" [ENABLED]"));
}
HECL::Printf(_S("\n %s\n"), spec.spec.m_desc.c_str());
HECL::Printf(_S("\n %s\n"), spec.spec.m_desc);
#endif
}
return 0;
}
@ -134,7 +145,7 @@ public:
HECL::ToLower(itName);
for (auto& spec : specs)
{
if (!spec.spec.m_name.compare(itName))
if (!itName.compare(spec.spec.m_name))
{
opSpecs.push_back(spec.spec.m_name);
break;

View File

@ -1,7 +1,10 @@
#if _WIN32
#define WIN_PAUSE 1
#endif
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/param.h>
#include <regex>
#include <stdexcept>
#include <list>
@ -22,6 +25,8 @@ LogVisor::LogModule LogModule("HECLDriver");
#include "ToolPackage.hpp"
#include "ToolHelp.hpp"
#include "../DataSpecRegistry.hpp"
bool XTERM_COLOR = false;
@ -35,10 +40,14 @@ bool XTERM_COLOR = false;
/* Main usage message */
static void printHelp(const HECL::SystemChar* pname)
{
#if _WIN32
HECL::Printf(_S("HECL"));
#else
if (XTERM_COLOR)
HECL::Printf(_S("" BOLD "HECL" NORMAL ""));
else
HECL::Printf(_S("HECL"));
#endif
#if HECL_GIT
HECL::Printf(_S(" Commit " HECL_GIT_S " " HECL_BRANCH_S "\nUsage: %s init|add|remove|group|cook|clean|package|help\n"), pname);
#elif HECL_VER
@ -61,6 +70,7 @@ int wmain(int argc, const wchar_t** argv)
int main(int argc, const char** argv)
#endif
{
//dummy();
/* Xterm check */
const char* term = getenv("TERM");
if (term && !strncmp(term, "xterm", 5))
@ -75,19 +85,25 @@ int main(int argc, const char** argv)
if (argc == 1)
{
printHelp(argv[0]);
#if WIN_PAUSE
system("PAUSE");
#endif
return 0;
}
else if (argc == 0)
{
printHelp(_S("hecl"));
#if WIN_PAUSE
system("PAUSE");
#endif
return 0;
}
/* Assemble common tool pass info */
ToolPassInfo info;
info.pname = argv[0];
HECL::SystemChar cwdbuf[MAXPATHLEN];
if (HECL::Getcwd(cwdbuf, MAXPATHLEN))
HECL::SystemChar cwdbuf[1024];
if (HECL::Getcwd(cwdbuf, 1024))
info.cwd = cwdbuf;
/* Concatenate args */
@ -173,6 +189,9 @@ int main(int argc, const char** argv)
LogModule.report(LogVisor::Error,
_S("Unable to open discovered project at '%s'"),
rootPath->getAbsolutePath().c_str());
#if WIN_PAUSE
system("PAUSE");
#endif
return -1;
}
}
@ -214,6 +233,9 @@ int main(int argc, const char** argv)
#else
LogModule.report(LogVisor::Error, _S("Unable to construct HECL tool '%s': %s"),
toolName.c_str(), ex.what());
#endif
#if WIN_PAUSE
system("PAUSE");
#endif
return -1;
}
@ -236,10 +258,16 @@ int main(int argc, const char** argv)
#else
LogModule.report(LogVisor::Error, _S("Error running HECL tool '%s': %s"),
toolName.c_str(), ex.what());
#endif
#if WIN_PAUSE
system("PAUSE");
#endif
return -1;
}
#if WIN_PAUSE
system("PAUSE");
#endif
return retval;
}

2
hecl/extern/Athena vendored

@ -1 +1 @@
Subproject commit 6405bffdd20d9b4c5e61a9600c69ca7bde5bc582
Subproject commit 5d3dcb57ad44fc270f87a7c554490ca2d5a263ef

View File

@ -3,5 +3,5 @@ add_subdirectory(libSquish)
add_subdirectory(blowfish)
add_subdirectory(LogVisor)
add_subdirectory(AngelScript)
add_subdirectory(Athena)
add_subdirectory(RetroCommon)
add_subdirectory(Athena EXCLUDE_FROM_ALL)
add_subdirectory(RetroCommon EXCLUDE_FROM_ALL)

@ -1 +1 @@
Subproject commit c2bfffa6cf1d07986fecaf7dde42acb29fe1f6e6
Subproject commit 085920205b71a0a5a9bf710de5794cc136051b2d

@ -1 +1 @@
Subproject commit a4d6e32e4848b2b33c9e95104b7259d24067b0b9
Subproject commit 5deacef567cd295e78cbbabfde944a8e0b3a2272

View File

@ -94,14 +94,14 @@ void Blowfish_decipher(uint32_t *xl, uint32_t *xr)
*xr = Xr;
}
int64_t Blowfish_hash(const void* buf, size_t len)
int64_t Blowfish_hash(const uint8_t* buf, size_t len)
{
unsigned i,j;
union
{
uint32_t h32[2];
int64_t h64;
} hash = {};
} hash = {0,0};
for (i=0 ; i<len/4 ; ++i)
{

View File

@ -7,7 +7,7 @@ extern "C" {
void Blowfish_encipher(uint32_t *xl, uint32_t *xr);
void Blowfish_decipher(uint32_t *xl, uint32_t *xr);
int64_t Blowfish_hash(const void* buf, size_t len);
int64_t Blowfish_hash(const uint8_t* buf, size_t len);
#ifdef __cplusplus
}

View File

@ -1,3 +1,4 @@
include_directories(${ZLIB_INCLUDE_DIR})
add_library(png
png.h
pngconf.h

View File

@ -128,9 +128,9 @@ class ASUniqueModule
public:
~ASUniqueModule() {if (m_mod) m_mod->Discard();}
ASUniqueModule(ASUniqueModule&& other) = default;
ASUniqueModule(ASUniqueModule& other) = delete;
ASUniqueModule(const ASUniqueModule& other) = delete;
ASUniqueModule& operator=(ASUniqueModule&& other) = default;
ASUniqueModule& operator=(ASUniqueModule& other) = delete;
ASUniqueModule& operator=(const ASUniqueModule& other) = delete;
inline operator AngelScript::asIScriptModule&() {return *m_mod;}
inline operator bool() {return m_mod != nullptr;}
static ASUniqueModule CreateFromCode(const char* module, const char* code)
@ -218,10 +218,10 @@ public:
typedef std::function<void(const HECL::SystemChar*, int, float)> FExtractProgress;
virtual bool canExtract(Project& project, const ExtractPassInfo& info, std::vector<ExtractReport>& reps)
{(void)project;(void)info;LogModule.report(LogVisor::Error, "not implemented");return false;}
virtual void doExtract(Project& project, const ExtractPassInfo& info, FExtractProgress progress)
{(void)project;(void)info;(void)progress;}
virtual bool canExtract(Project&, const ExtractPassInfo& info, std::vector<ExtractReport>& reps)
{(void)info;LogModule.report(LogVisor::Error, "not implemented");return false;}
virtual void doExtract(Project&, const ExtractPassInfo& info, FExtractProgress progress)
{(void)info;(void)progress;}
/**
* @brief Cook Task Info
@ -234,11 +234,11 @@ public:
ProjectPath path;
ProjectPath cookedPath;
};
virtual bool canCook(const Project& project, const CookTaskInfo& info,
virtual bool canCook(const Project&, const CookTaskInfo& info,
SystemString& reasonNo)
{(void)project;(void)info;reasonNo=_S("not implemented");return false;}
virtual void doCook(const Project& project, const CookTaskInfo& info)
{(void)project;(void)info;}
{(void)info;reasonNo=_S("not implemented");return false;}
virtual void doCook(const Project&, const CookTaskInfo& info)
{(void)info;}
/**
* @brief Package Pass Info
@ -253,14 +253,14 @@ public:
ProjectPath subpath;
ProjectPath outpath;
};
virtual bool canPackage(const Project& project, const PackagePassInfo& info,
virtual bool canPackage(const Project&, const PackagePassInfo& info,
SystemString& reasonNo)
{(void)project;(void)info;reasonNo=_S("not implemented");return false;}
virtual void gatherDependencies(const Project& project, const PackagePassInfo& info,
{(void)info;reasonNo=_S("not implemented");return false;}
virtual void gatherDependencies(const Project&, const PackagePassInfo& info,
std::unordered_set<ProjectPath>& implicitsOut)
{(void)project;(void)info;(void)implicitsOut;}
virtual void doPackage(const Project& project, const PackagePassInfo& info)
{(void)project;(void)info;}
{(void)info;(void)implicitsOut;}
virtual void doPackage(const Project&, const PackagePassInfo& info)
{(void)info;}
};
/**
@ -282,11 +282,11 @@ extern std::vector<const struct DataSpecEntry*> DATA_SPEC_REGISTRY;
*/
struct DataSpecEntry
{
SystemString m_name;
SystemString m_desc;
const SystemChar* m_name;
const SystemChar* m_desc;
std::function<IDataSpec*(DataSpecTool)> m_factory;
DataSpecEntry(SystemString&& name, SystemString&& desc,
DataSpecEntry(const SystemChar* name, const SystemChar* desc,
std::function<IDataSpec*(DataSpecTool)>&& factory)
: m_name(std::move(name)), m_desc(std::move(desc)), m_factory(std::move(factory))
{
@ -469,7 +469,7 @@ public:
for (const ProjectDataSpec& sp : m_compiledSpecs)
if (&sp.spec == &spec)
return sp.cookedPath;
LogModule.report(LogVisor::FatalError, "Unable to find spec '%s'", spec.m_name.c_str());
LogModule.report(LogVisor::FatalError, "Unable to find spec '%s'", spec.m_name);
return m_cookedRoot;
}

View File

@ -10,6 +10,12 @@
#include <dirent.h>
#include <fcntl.h>
#include <unistd.h>
#else
#define _WIN32_LEAN_AND_MEAN 1
#include <Windows.h>
#include <wchar.h>
#include "winsupport.h"
#define snprintf _snprintf
#endif
#include <time.h>
@ -24,6 +30,10 @@
#include <Athena/DNA.hpp>
#include "../extern/blowfish/blowfish.h"
/* Handy MIN/MAX macros */
#define MAX(x, y) (((x) > (y)) ? (x) : (y))
#define MIN(x, y) (((x) < (y)) ? (x) : (y))
namespace HECL
{
@ -73,6 +83,7 @@ inline std::wstring operator+(const wchar_t* lhs, const SystemStringView& rhs) {
#ifndef _S
#define _S(val) L ## val
#endif
typedef struct _stat Sstat;
#else
typedef char SystemChar;
static inline size_t StrLen(const SystemChar* str) {return strlen(str);}
@ -110,6 +121,7 @@ inline std::string operator+(const char* lhs, const SystemStringView& rhs) {retu
#ifndef _S
#define _S(val) val
#endif
typedef struct stat Sstat;
#endif
static inline void MakeDir(const SystemString& dir)
@ -129,7 +141,7 @@ static inline void MakeDir(const SystemString& dir)
static inline SystemChar* Getcwd(SystemChar* buf, int maxlen)
{
#if HECL_UCS2
return wgetcwd(buf, maxlen);
return _wgetcwd(buf, maxlen);
#else
return getcwd(buf, maxlen);
#endif
@ -144,7 +156,7 @@ enum FileLockType
static inline FILE* Fopen(const SystemChar* path, const SystemChar* mode, FileLockType lock=LNONE)
{
#if HECL_UCS2
FILE* fp = wfopen(path, mode);
FILE* fp = _wfopen(path, mode);
#else
FILE* fp = fopen(path, mode);
#endif
@ -154,9 +166,8 @@ static inline FILE* Fopen(const SystemChar* path, const SystemChar* mode, FileLo
if (lock)
{
#if _WIN32
HANDLE fhandle = (HANDLE)fileno(fp);
OVERLAPPED ov = {};
LockFileEx(fhandle, (lock == LWRITE) ? LOCKFILE_EXCLUSIVE_LOCK : 0, 0, 0, 1, &ov);
LockFileEx((HANDLE)(uintptr_t)_fileno(fp), (lock == LWRITE) ? LOCKFILE_EXCLUSIVE_LOCK : 0, 0, 0, 1, &ov);
#else
if (flock(fileno(fp), ((lock == LWRITE) ? LOCK_EX : LOCK_SH) | LOCK_NB))
throw std::error_code(errno, std::system_category());
@ -166,10 +177,10 @@ static inline FILE* Fopen(const SystemChar* path, const SystemChar* mode, FileLo
return fp;
}
static inline int Stat(const SystemChar* path, struct stat* statOut)
static inline int Stat(const SystemChar* path, Sstat* statOut)
{
#if HECL_UCS2
return wstat(path, statOut);
return _wstat(path, statOut);
#else
return stat(path, statOut);
#endif
@ -204,7 +215,7 @@ static inline void SNPrintf(SystemChar* str, size_t maxlen, const SystemChar* fo
va_list va;
va_start(va, format);
#if HECL_UCS2
vsnwprintf(str, maxlen, format, va);
_vsnwprintf(str, maxlen, format, va);
#else
vsnprintf(str, maxlen, format, va);
#endif
@ -243,7 +254,7 @@ static inline int ConsoleWidth()
#if _WIN32
CONSOLE_SCREEN_BUFFER_INFO info;
GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &info);
m_lineWidth = info.dwSize.X;
retval = info.dwSize.X;
#else
struct winsize w;
if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &w) != -1)
@ -304,9 +315,11 @@ class Hash final
int64_t hash;
public:
Hash(const void* buf, size_t len)
: hash(Blowfish_hash(buf, len)) {}
: hash(Blowfish_hash((uint8_t*)buf, len)) {}
Hash(const std::string& str)
: hash(Blowfish_hash(str.data(), str.size())) {}
: hash(Blowfish_hash((uint8_t*)str.data(), str.size())) {}
Hash(const std::wstring& str)
: hash(Blowfish_hash((uint8_t*)str.data(), str.size()*2)) {}
Hash(int64_t hashin)
: hash(hashin) {}
Hash(const Hash& other) {hash = other.hash;}
@ -362,14 +375,14 @@ protected:
Hash m_hash = 0;
#if HECL_UCS2
std::string m_utf8AbsPath;
const char* m_utf8RelPath;
std::string m_utf8RelPath;
#endif
ProjectPath(const SystemString& projRoot)
: m_projRoot(projRoot), m_absPath(projRoot), m_relPath("."), m_hash(m_relPath)
: m_projRoot(projRoot), m_absPath(projRoot), m_relPath(_S(".")), m_hash(m_relPath)
{
#if HECL_UCS2
m_utf8AbsPath = WideToUTF8(m_absPath);
m_utf8RelPath = m_utf8AbsPath.c_str() + ((ProjectPath&)rootPath).m_utf8AbsPath.size();
m_utf8RelPath = ".";
#endif
}
public:
@ -380,6 +393,10 @@ public:
*/
ProjectPath(const ProjectPath& parentPath, const SystemString& path);
#if HECL_UCS2
ProjectPath(const ProjectPath& parentPath, const std::string& path);
#endif
/**
* @brief Determine if ProjectPath represents project root directory
* @return true if project root directory
@ -577,16 +594,22 @@ static inline uint64_t SBig(uint64_t val) {return val;}
}
#if _MSC_VER
#define NOEXCEPT
#else
#define NOEXCEPT noexcept
#endif
namespace std
{
template <> struct hash<HECL::FourCC>
{
inline size_t operator()(const HECL::FourCC& val) const noexcept
inline size_t operator()(const HECL::FourCC& val) const NOEXCEPT
{return val.toUint32();}
};
template <> struct hash<HECL::ProjectPath>
{
inline size_t operator()(const HECL::ProjectPath& val) const noexcept
inline size_t operator()(const HECL::ProjectPath& val) const NOEXCEPT
{return val.hash();}
};
}

View File

@ -0,0 +1,14 @@
#ifndef _HECL_WINSUPPORT_H_
#define _HECL_WINSUPPORT_H_
#if __cplusplus
extern "C" {
#endif
void* memmem(const void *haystack, size_t hlen, const void *needle, size_t nlen);
#if __cplusplus
}
#endif
#endif // _HECL_WINSUPPORT_H_

View File

@ -3,7 +3,11 @@ add_subdirectory(Database)
add_subdirectory(Frontend)
add_subdirectory(Runtime)
add_library(HECL
if(WIN32)
list(APPEND PLAT_SRCS winsupport.c ../include/HECL/winsupport.h)
endif()
add_library(HECLCommon
HECL.cpp
ProjectPath.cpp
WideStringConvert.cpp
@ -11,5 +15,6 @@ add_library(HECL
../include/HECL/Backend.hpp
../include/HECL/Frontend.hpp
../include/HECL/Database.hpp
../include/HECL/Runtime.hpp)
../include/HECL/Runtime.hpp
${PLAT_SRCS})

View File

@ -1,5 +1,4 @@
add_library(HECLDatabaseInit
Registry.cpp
ASInit.cpp)
add_library(HECLDatabase
ASEngine.cpp

View File

@ -174,12 +174,20 @@ bool Project::ConfigFile::unlockAndCommit()
m_lockedFile = NULL;
if (fail)
{
#if HECL_UCS2
_wunlink(newPath.c_str());
#else
unlink(newPath.c_str());
#endif
return false;
}
else
{
#if HECL_UCS2
_wrename(newPath.c_str(), m_filepath.c_str());
#else
rename(newPath.c_str(), m_filepath.c_str());
#endif
return true;
}
}
@ -197,7 +205,7 @@ Project::Project(const ProjectRootPath& rootPath)
m_groups(*this, _S("groups"))
{
/* Stat for existing project directory (must already exist) */
struct stat myStat;
Sstat myStat;
if (HECL::Stat(m_rootPath.getAbsolutePath().c_str(), &myStat))
throw std::error_code(errno, std::system_category());
@ -293,7 +301,7 @@ void Project::rescanDataSpecs()
for (const DataSpecEntry* spec : DATA_SPEC_REGISTRY)
{
SystemUTF8View specUTF8(spec->m_name);
m_compiledSpecs.push_back({*spec, ProjectPath(m_cookedRoot, spec->m_name + ".spec"),
m_compiledSpecs.push_back({*spec, ProjectPath(m_cookedRoot, HECL::SystemString(spec->m_name) + _S(".spec")),
m_specs.checkForLine(specUTF8) ? true : false});
}
m_specs.unlockAndDiscard();
@ -303,7 +311,10 @@ bool Project::enableDataSpecs(const std::vector<SystemString>& specs)
{
m_specs.lockAndRead();
for (const SystemString& spec : specs)
m_specs.addLine(spec);
{
SystemUTF8View specView(spec);
m_specs.addLine(specView);
}
bool result = m_specs.unlockAndCommit();
rescanDataSpecs();
return result;
@ -313,16 +324,20 @@ bool Project::disableDataSpecs(const std::vector<SystemString>& specs)
{
m_specs.lockAndRead();
for (const SystemString& spec : specs)
m_specs.removeLine(spec);
{
SystemUTF8View specView(spec);
m_specs.removeLine(specView);
}
bool result = m_specs.unlockAndCommit();
rescanDataSpecs();
return result;
}
bool Project::cookPath(const ProjectPath& path,
std::function<void(std::string&, Cost, unsigned)> feedbackCb,
std::function<void(SystemString&, Cost, unsigned)> feedbackCb,
bool recursive)
{
return false;
}
void Project::interruptCook()
@ -331,10 +346,12 @@ void Project::interruptCook()
bool Project::cleanPath(const ProjectPath& path, bool recursive)
{
return false;
}
PackageDepsgraph Project::buildPackageDepsgraph(const ProjectPath& path)
{
return PackageDepsgraph();
}
}

View File

@ -1,12 +0,0 @@
#include "HECL/Database.hpp"
namespace HECL
{
namespace Database
{
/* Centralized registry for DataSpec lookup */
std::vector<const struct DataSpecEntry*> DATA_SPEC_REGISTRY;
}
}

View File

@ -54,41 +54,51 @@ static SystemString canonRelPath(const SystemString& path)
}
return retval;
}
return ".";
return _S(".");
}
ProjectPath::ProjectPath(const ProjectPath& parentPath, const SystemString& path)
: m_projRoot(parentPath.m_projRoot)
{
m_relPath = canonRelPath(parentPath.m_relPath + '/' + path);
m_absPath = parentPath.m_projRoot + '/' + m_relPath;
m_relPath = canonRelPath(parentPath.m_relPath + _S('/') + path);
m_absPath = parentPath.m_projRoot + _S('/') + m_relPath;
m_hash = Hash(m_relPath);
#if HECL_UCS2
m_utf8AbsPath = WideToUTF8(m_absPath);
m_utf8RelPath = m_utf8AbsPath.c_str() + ((ProjectPath&)rootPath).m_utf8AbsPath.size();
m_utf8RelPath = WideToUTF8(m_relPath);
#endif
}
#if HECL_UCS2
ProjectPath::ProjectPath(const ProjectPath& parentPath, const std::string& path)
: m_projRoot(parentPath.m_projRoot)
{
std::wstring wpath = UTF8ToWide(path);
m_relPath = canonRelPath(parentPath.m_relPath + _S('/') + wpath);
m_absPath = parentPath.m_projRoot + _S('/') + m_relPath;
m_hash = Hash(m_relPath);
m_utf8AbsPath = WideToUTF8(m_absPath);
m_utf8RelPath = WideToUTF8(m_relPath);
}
#endif
ProjectPath::PathType ProjectPath::getPathType() const
{
if (std::regex_search(m_absPath, regGLOB))
return PT_GLOB;
#if _WIN32
#else
struct stat theStat;
if (stat(m_absPath.c_str(), &theStat))
Sstat theStat;
if (HECL::Stat(m_absPath.c_str(), &theStat))
return PT_NONE;
if (S_ISDIR(theStat.st_mode))
return PT_DIRECTORY;
if (S_ISREG(theStat.st_mode))
return PT_FILE;
return PT_NONE;
#endif
}
Time ProjectPath::getModtime() const
{
struct stat theStat;
Sstat theStat;
time_t latestTime = 0;
if (std::regex_search(m_absPath, regGLOB))
{
@ -189,7 +199,7 @@ static void _recursiveGlob(std::vector<SystemString>& outPaths,
void ProjectPath::getGlobResults(std::vector<SystemString>& outPaths) const
{
#if _WIN32
TSystemPath itStr;
SystemString itStr;
SystemRegexMatch letterMatch;
if (m_absPath.compare(0, 2, _S("//")))
itStr = _S("\\\\");
@ -214,7 +224,7 @@ std::unique_ptr<ProjectRootPath> SearchForProject(const SystemString& path)
{
SystemString testPath(begin, end);
SystemString testIndexPath = testPath + _S("/.hecl/beacon");
struct stat theStat;
Sstat theStat;
if (!HECL::Stat(testIndexPath.c_str(), &theStat))
{
if (S_ISREG(theStat.st_mode))
@ -236,7 +246,8 @@ std::unique_ptr<ProjectRootPath> SearchForProject(const SystemString& path)
while (begin != end && *(end-1) != _S('/') && *(end-1) != _S('\\'))
--end;
--end;
if (begin != end)
--end;
}
return std::unique_ptr<ProjectRootPath>();
}

View File

@ -15,11 +15,13 @@ Runtime::~Runtime()
std::shared_ptr<Entity> Runtime::loadSync(const Hash& pathHash)
{
return std::shared_ptr<Entity>();
}
std::shared_ptr<Entity> Runtime::loadAsync(const Hash& pathHash,
SGroupLoadStatus* statusOut)
{
return std::shared_ptr<Entity>();
}
}

34
hecl/lib/winsupport.c Normal file
View File

@ -0,0 +1,34 @@
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
/*
* The memmem() function finds the start of the first occurrence of the
* substring 'needle' of length 'nlen' in the memory area 'haystack' of
* length 'hlen'.
*
* The return value is a pointer to the beginning of the sub-string, or
* NULL if the substring is not found.
*/
void *memmem(const uint8_t *haystack, size_t hlen, const void *needle, size_t nlen)
{
int needle_first;
const uint8_t *p = haystack;
size_t plen = hlen;
if (!nlen)
return NULL;
needle_first = *(unsigned char *)needle;
while (plen >= nlen && (p = memchr(p, needle_first, plen - nlen + 1)))
{
if (!memcmp(p, needle, nlen))
return (void *)p;
p++;
plen = hlen - (p - haystack);
}
return NULL;
}