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) cmake_minimum_required(VERSION 3.0)
project(hecl) 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(HECL_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/include)
set(ATHENA_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/extern/Athena/include) set(ATHENA_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/extern/Athena/include)
set(LOG_VISOR_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/extern/LogVisor/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_definitions(-DAS_USE_NAMESPACE=1)
add_subdirectory(extern) add_subdirectory(extern)
include_directories(include ${LOG_VISOR_INCLUDE_DIR} ${ATHENA_INCLUDE_DIR} ${ANGELSCRIPT_INCLUDE_DIR}) 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(lib)
add_subdirectory(blender) add_subdirectory(blender)
add_subdirectory(driver) 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 <system_error>
#include <string> #include <string>
#include <HECL/HECL.hpp>
#include <LogVisor/LogVisor.hpp>
#include "BlenderConnection.hpp" #include "BlenderConnection.hpp"
static LogVisor::LogModule Log("BlenderConnection");
#ifdef __APPLE__ #ifdef __APPLE__
#define DEFAULT_BLENDER_BIN "/Applications/Blender.app/Contents/MacOS/blender" #define DEFAULT_BLENDER_BIN "/Applications/Blender.app/Contents/MacOS/blender"
#elif _WIN32 #elif _WIN32
#define DEFAULT_BLENDER_BIN "%ProgramFiles%\\Blender Foundation\\Blender\\blender.exe" #define DEFAULT_BLENDER_BIN _S("%ProgramFiles%\\Blender Foundation\\Blender\\blender.exe")
#else #else
#define DEFAULT_BLENDER_BIN "blender" #define DEFAULT_BLENDER_BIN "blender"
#endif #endif
#define TEMP_SHELLSCRIPT "/home/jacko/hecl/blender/blendershell.py" #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; size_t readBytes = 0;
while (true) while (true)
@ -28,9 +32,15 @@ size_t CBlenderConnection::_readLine(char* buf, size_t bufSz)
*(buf-1) = '\0'; *(buf-1) = '\0';
return bufSz - 1; 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); ssize_t ret = read(m_readpipe[0], buf, 1);
if (ret < 0) if (ret < 0)
goto err; goto err;
#endif
else if (ret == 1) else if (ret == 1)
{ {
if (*buf == '\n') if (*buf == '\n')
@ -52,8 +62,15 @@ err:
return 0; 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; ssize_t ret, nlerr;
ret = write(m_writepipe[1], buf, strlen(buf)); ret = write(m_writepipe[1], buf, strlen(buf));
if (ret < 0) if (ret < 0)
@ -61,43 +78,125 @@ size_t CBlenderConnection::_writeLine(const char* buf)
nlerr = write(m_writepipe[1], "\n", 1); nlerr = write(m_writepipe[1], "\n", 1);
if (nlerr < 0) if (nlerr < 0)
goto err; goto err;
#endif
return (size_t)ret; return (size_t)ret;
err: err:
throw std::error_code(errno, std::system_category()); 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); ssize_t ret = read(m_readpipe[0], buf, len);
if (ret < 0) if (ret < 0)
throw std::error_code(errno, std::system_category()); goto err;
#endif
return ret; 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); ssize_t ret = write(m_writepipe[1], buf, len);
if (ret < 0) if (ret < 0)
throw std::error_code(errno, std::system_category()); goto err;
#endif
return ret; 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_readpipe[0]);
close(m_writepipe[1]); close(m_writepipe[1]);
#endif
} }
CBlenderConnection::CBlenderConnection(bool silenceBlender) BlenderConnection::BlenderConnection(bool silenceBlender)
{ {
/* Construct communication pipes */ /* 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_readpipe);
pipe(m_writepipe); pipe(m_writepipe);
#endif
/* User-specified blender path */ /* 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"); char* blenderBin = getenv("BLENDER_BIN");
#endif
/* Child process of blender */ /* 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(); pid_t pid = fork();
if (!pid) if (!pid)
{ {
@ -149,6 +248,7 @@ CBlenderConnection::CBlenderConnection(bool silenceBlender)
close(m_writepipe[0]); close(m_writepipe[0]);
close(m_readpipe[1]); close(m_readpipe[1]);
m_blenderProc = pid; m_blenderProc = pid;
#endif
/* Handle first response */ /* Handle first response */
char lineBuf[256]; char lineBuf[256];
@ -156,40 +256,38 @@ CBlenderConnection::CBlenderConnection(bool silenceBlender)
if (!strcmp(lineBuf, "NOLAUNCH")) if (!strcmp(lineBuf, "NOLAUNCH"))
{ {
_closePipe(); _closePipe();
throw std::runtime_error("Unable to launch blender"); Log.report(LogVisor::FatalError, "Unable to launch blender");
} }
else if (!strcmp(lineBuf, "NOBLENDER")) else if (!strcmp(lineBuf, "NOBLENDER"))
{ {
_closePipe(); _closePipe();
if (blenderBin) if (blenderBin)
throw std::runtime_error("Unable to find blender at '" + Log.report(LogVisor::FatalError, _S("Unable to find blender at '%s' or '%s'"),
std::string(blenderBin) + "' or '" + blenderBin, DEFAULT_BLENDER_BIN);
std::string(DEFAULT_BLENDER_BIN) + "'");
else else
throw std::runtime_error("Unable to find blender at '" + Log.report(LogVisor::FatalError, _S("Unable to find blender at '%s'"),
std::string(DEFAULT_BLENDER_BIN) + "'"); DEFAULT_BLENDER_BIN);
} }
else if (!strcmp(lineBuf, "NOADDON")) else if (!strcmp(lineBuf, "NOADDON"))
{ {
_closePipe(); _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")) else if (strcmp(lineBuf, "READY"))
{ {
_closePipe(); _closePipe();
throw std::runtime_error("read '" + std::string(lineBuf) + Log.report(LogVisor::FatalError, "read '%s' from blender; expected 'READY'", lineBuf);
"' from blender; expected 'READY'");
} }
_writeLine("ACK"); _writeLine("ACK");
} }
CBlenderConnection::~CBlenderConnection() BlenderConnection::~BlenderConnection()
{ {
_closePipe(); _closePipe();
} }
bool CBlenderConnection::openBlend(const std::string& path) bool BlenderConnection::openBlend(const std::string& path)
{ {
_writeLine(("OPEN" + path).c_str()); _writeLine(("OPEN" + path).c_str());
char lineBuf[256]; char lineBuf[256];
@ -202,7 +300,7 @@ bool CBlenderConnection::openBlend(const std::string& path)
return false; 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& expectedType,
const std::string& platform, const std::string& platform,
bool bigEndian) bool bigEndian)
@ -238,7 +336,7 @@ bool CBlenderConnection::cookBlend(std::function<char*(uint32_t)> bufGetter,
return false; return false;
} }
void CBlenderConnection::quitBlender() void BlenderConnection::quitBlender()
{ {
_writeLine("QUIT"); _writeLine("QUIT");
char lineBuf[256]; char lineBuf[256];

View File

@ -1,5 +1,5 @@
#ifndef CBLENDERCONNECTION_HPP #ifndef BLENDERCONNECTION_HPP
#define CBLENDERCONNECTION_HPP #define BLENDERCONNECTION_HPP
#if _WIN32 #if _WIN32
#define _WIN32_LEAN_AND_MEAN 1 #define _WIN32_LEAN_AND_MEAN 1
@ -8,15 +8,16 @@
#include <unistd.h> #include <unistd.h>
#endif #endif
#include <stdint.h>
#include <string> #include <string>
#include <functional> #include <functional>
class CBlenderConnection class BlenderConnection
{ {
#if _WIN32 #if _WIN32
HANDLE m_blenderProc; HANDLE m_blenderProc;
HANDLE m_readpipe; HANDLE m_readpipe[2];
HANDLE m_writepipe; HANDLE m_writepipe[2];
#else #else
pid_t m_blenderProc; pid_t m_blenderProc;
int m_readpipe[2]; int m_readpipe[2];
@ -29,8 +30,8 @@ class CBlenderConnection
size_t _writeBuf(const char* buf, size_t len); size_t _writeBuf(const char* buf, size_t len);
void _closePipe(); void _closePipe();
public: public:
CBlenderConnection(bool silenceBlender=false); BlenderConnection(bool silenceBlender=false);
~CBlenderConnection(); ~BlenderConnection();
bool openBlend(const std::string& path); bool openBlend(const std::string& path);
enum CookPlatform enum CookPlatform
@ -45,4 +46,4 @@ public:
void quitBlender(); 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 add_executable(hecl main.cpp
ToolBase.hpp ToolBase.hpp
ToolPackage.hpp ToolPackage.hpp
@ -19,7 +23,12 @@ list(APPEND DATA_SPEC_LIBS
DNAMP2 DNAMP2
DNAMP3) DNAMP3)
if(NOT WIN32)
set(WHOLE_START "-Wl,-whole-archive")
set(WHOLE_END "-Wl,-no-whole-archive")
endif()
target_link_libraries(hecl target_link_libraries(hecl
"-Wl,-whole-archive" HECLDatabaseInit ${DATA_SPEC_LIBS} "-Wl,-no-whole-archive" ${WHOLE_START} HECLDatabaseInit ${DATA_SPEC_LIBS} ${WHOLE_END}
HECLDatabase HECL AthenaCore AngelScript NOD LogVisor png squish blowfish z lzo2 HECLDatabase HECLCommon AthenaCore AngelScript NOD LogVisor png squish blowfish z lzo2
) )

View File

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

View File

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

View File

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

View File

@ -30,10 +30,10 @@ public:
help.secHead(_S("DESCRIPTION")); help.secHead(_S("DESCRIPTION"));
help.beginWrap(); help.beginWrap();
help.wrap(_S("This command initiates a cooking pass on the project database. Cooking " 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 " _S("is analogous to compiling in software development. The resulting object buffers ")
"are cached within the project database. HECL performs the following " _S("are cached within the project database. HECL performs the following ")
"tasks for each object during the cook process:\n\n")); _S("tasks for each object during the cook process:\n\n"));
help.wrapBold(_S("- Object Gather: ")); help.wrapBold(_S("- Object Gather: "));
help.wrap(_S("Files added with ")); help.wrap(_S("Files added with "));
help.wrapBold(_S("hecl add")); help.wrapBold(_S("hecl add"));
@ -43,13 +43,13 @@ public:
help.wrapBold(_S(".png")); help.wrapBold(_S(".png"));
help.wrap(_S(" images). If the dependent files are unable to be found, the cook process aborts.\n\n")); 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.wrapBold(_S("- Modtime Comparison: "));
help.wrap(_S("Files that have previously finished a cook pass are inspected for their time of " 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 " _S("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 " _S("process is skipped. If the file has been moved or deleted, the object is automatically ")
"removed from the project database.\n\n")); _S("removed from the project database.\n\n"));
help.wrapBold(_S("- Cook: ")); help.wrapBold(_S("- Cook: "));
help.wrap(_S("A type-specific procedure compiles the file's contents into an efficient format " 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")); _S("for use by the runtime. A data-buffer is provided to HECL.\n\n"));
help.wrapBold(_S("- Hash and Compress: ")); 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.wrap(_S("The data-buffer is hashed and compressed before being cached in the object database.\n\n"));
help.endWrap(); help.endWrap();
@ -57,11 +57,11 @@ public:
help.secHead(_S("OPTIONS")); help.secHead(_S("OPTIONS"));
help.optionHead(_S("<pathspec>..."), _S("input file(s)")); help.optionHead(_S("<pathspec>..."), _S("input file(s)"));
help.beginWrap(); help.beginWrap();
help.wrap(_S("Specifies working file(s) containing production data to be cooked by HECL. " help.wrap(_S("Specifies working file(s) containing production data to be cooked by HECL. ")
"Glob-strings may be specified (e.g. ")); _S("Glob-strings may be specified (e.g. "));
help.wrapBold(_S("*.blend")); help.wrapBold(_S("*.blend"));
help.wrap(_S(") to automatically cook all matching current-directory files in the project database. " 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")); _S("If no path specified, all files in the project database are cooked.\n"));
help.endWrap(); help.endWrap();
help.optionHead(_S("-r"), _S("recursion")); 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; std::unique_ptr<HECL::Database::IDataSpec> m_instance;
SpecExtractPass(const HECL::Database::DataSpecEntry* entry, HECL::Database::IDataSpec* instance) SpecExtractPass(const HECL::Database::DataSpecEntry* entry, HECL::Database::IDataSpec* instance)
: m_entry(entry), m_instance(instance) {} : m_entry(entry), m_instance(instance) {}
SpecExtractPass(const SpecExtractPass& other) = delete;
SpecExtractPass(SpecExtractPass&& other) = default;
}; };
std::vector<SpecExtractPass> m_specPasses; std::vector<SpecExtractPass> m_specPasses;
std::vector<HECL::Database::IDataSpec::ExtractReport> m_reps; std::vector<HECL::Database::IDataSpec::ExtractReport> m_reps;
@ -60,16 +62,16 @@ public:
help.secHead(_S("DESCRIPTION")); help.secHead(_S("DESCRIPTION"));
help.beginWrap(); help.beginWrap();
help.wrap(_S("This command recursively extracts all or part of a dataspec-supported " 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")); _S("package format. Each object is decoded to a working format and added to the project.\n\n"));
help.endWrap(); help.endWrap();
help.secHead(_S("OPTIONS")); help.secHead(_S("OPTIONS"));
help.optionHead(_S("<packagefile>[/<subnode>...]"), _S("input file")); help.optionHead(_S("<packagefile>[/<subnode>...]"), _S("input file"));
help.beginWrap(); help.beginWrap();
help.wrap(_S("Specifies the package file or disc image to source data from. " help.wrap(_S("Specifies the package file or disc image to source data from. ")
"An optional subnode specifies a named hierarchical-node specific " _S("An optional subnode specifies a named hierarchical-node specific ")
"to the game architecture (levels/areas).")); _S("to the game architecture (levels/areas)."));
help.endWrap(); help.endWrap();
} }
@ -79,10 +81,14 @@ public:
{ {
for (int l=0 ; l<level ; ++l) for (int l=0 ; l<level ; ++l)
HECL::Printf(_S(" ")); HECL::Printf(_S(" "));
#if _WIN32
HECL::Printf(_S("%s"), rep.name.c_str());
#else
if (XTERM_COLOR) if (XTERM_COLOR)
HECL::Printf(_S("" BOLD "%s" NORMAL ""), rep.name.c_str()); HECL::Printf(_S("" BOLD "%s" NORMAL ""), rep.name.c_str());
else else
HECL::Printf(_S("%s"), rep.name.c_str()); HECL::Printf(_S("%s"), rep.name.c_str());
#endif
if (rep.desc.size()) if (rep.desc.size())
HECL::Printf(_S(" [%s]"), rep.desc.c_str()); HECL::Printf(_S(" [%s]"), rep.desc.c_str());
HECL::Printf(_S("\n")); HECL::Printf(_S("\n"));
@ -94,17 +100,25 @@ public:
{ {
if (m_specPasses.empty()) if (m_specPasses.empty())
{ {
#if _WIN32
HECL::Printf(_S("NOTHING TO EXTRACT\n"));
#else
if (XTERM_COLOR) if (XTERM_COLOR)
HECL::Printf(_S("" RED BOLD "NOTHING TO EXTRACT" NORMAL "\n")); HECL::Printf(_S("" RED BOLD "NOTHING TO EXTRACT" NORMAL "\n"));
else else
HECL::Printf(_S("NOTHING TO EXTRACT\n")); HECL::Printf(_S("NOTHING TO EXTRACT\n"));
#endif
return -1; return -1;
} }
#if _WIN32
HECL::Printf(_S("ABOUT TO EXTRACT:\n"));
#else
if (XTERM_COLOR) if (XTERM_COLOR)
HECL::Printf(_S("" GREEN BOLD "ABOUT TO EXTRACT:" NORMAL "\n")); HECL::Printf(_S("" GREEN BOLD "ABOUT TO EXTRACT:" NORMAL "\n"));
else else
HECL::Printf(_S("ABOUT TO EXTRACT:\n")); HECL::Printf(_S("ABOUT TO EXTRACT:\n"));
#endif
for (HECL::Database::IDataSpec::ExtractReport& rep : m_reps) for (HECL::Database::IDataSpec::ExtractReport& rep : m_reps)
{ {
@ -112,10 +126,14 @@ public:
HECL::Printf(_S("\n")); HECL::Printf(_S("\n"));
} }
#if _WIN32
HECL::Printf(_S("\nContinue? (Y/N) "));
#else
if (XTERM_COLOR) if (XTERM_COLOR)
HECL::Printf(_S("\n" BLUE BOLD "Continue?" NORMAL " (Y/N) ")); HECL::Printf(_S("\n" BLUE BOLD "Continue?" NORMAL " (Y/N) "));
else else
HECL::Printf(_S("\nContinue? (Y/N) ")); HECL::Printf(_S("\nContinue? (Y/N) "));
#endif
int ch; int ch;
while ((ch = getchar())) while ((ch = getchar()))
@ -128,17 +146,23 @@ public:
for (SpecExtractPass& ds : m_specPasses) for (SpecExtractPass& ds : m_specPasses)
{ {
#if _WIN32
HECL::Printf(_S("Using DataSpec %s:\n"), ds.m_entry->m_name);
#else
if (XTERM_COLOR) 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 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; int lineIdx = 0;
ds.m_instance->doExtract(*m_info.project, m_einfo, ds.m_instance->doExtract(*m_info.project, m_einfo,
[&lineIdx](const HECL::SystemChar* message, int lidx, float factor) [&lineIdx](const HECL::SystemChar* message, int lidx, float factor)
{ {
#ifndef _WIN32
if (XTERM_COLOR) if (XTERM_COLOR)
HECL::Printf(_S("" HIDE_CURSOR "")); HECL::Printf(_S("" HIDE_CURSOR ""));
#endif
if (lidx > lineIdx) if (lidx > lineIdx)
{ {
@ -161,6 +185,7 @@ public:
HECL::Printf(_S(" ")); HECL::Printf(_S(" "));
} }
#ifndef _WIN32
if (XTERM_COLOR) if (XTERM_COLOR)
{ {
size_t blocks = half - 7; size_t blocks = half - 7;
@ -175,6 +200,7 @@ public:
} }
else else
{ {
#endif
size_t blocks = half - 7; size_t blocks = half - 7;
size_t filled = blocks * factor; size_t filled = blocks * factor;
size_t rem = blocks - filled; size_t rem = blocks - filled;
@ -184,11 +210,15 @@ public:
for (int b=0 ; b<rem ; ++b) for (int b=0 ; b<rem ; ++b)
HECL::Printf(_S("-"), message); HECL::Printf(_S("-"), message);
HECL::Printf(_S("]")); HECL::Printf(_S("]"));
#ifndef _WIN32
} }
#endif
HECL::Printf(_S("\r")); HECL::Printf(_S("\r"));
#ifndef _WIN32
if (XTERM_COLOR) if (XTERM_COLOR)
HECL::Printf(_S("" SHOW_CURSOR "")); HECL::Printf(_S("" SHOW_CURSOR ""));
#endif
}); });
HECL::Printf(_S("\n\n")); HECL::Printf(_S("\n\n"));
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,7 +1,10 @@
#if _WIN32
#define WIN_PAUSE 1
#endif
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include <sys/param.h>
#include <regex> #include <regex>
#include <stdexcept> #include <stdexcept>
#include <list> #include <list>
@ -22,6 +25,8 @@ LogVisor::LogModule LogModule("HECLDriver");
#include "ToolPackage.hpp" #include "ToolPackage.hpp"
#include "ToolHelp.hpp" #include "ToolHelp.hpp"
#include "../DataSpecRegistry.hpp"
bool XTERM_COLOR = false; bool XTERM_COLOR = false;
@ -35,10 +40,14 @@ bool XTERM_COLOR = false;
/* Main usage message */ /* Main usage message */
static void printHelp(const HECL::SystemChar* pname) static void printHelp(const HECL::SystemChar* pname)
{ {
#if _WIN32
HECL::Printf(_S("HECL"));
#else
if (XTERM_COLOR) if (XTERM_COLOR)
HECL::Printf(_S("" BOLD "HECL" NORMAL "")); HECL::Printf(_S("" BOLD "HECL" NORMAL ""));
else else
HECL::Printf(_S("HECL")); HECL::Printf(_S("HECL"));
#endif
#if HECL_GIT #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); 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 #elif HECL_VER
@ -61,6 +70,7 @@ int wmain(int argc, const wchar_t** argv)
int main(int argc, const char** argv) int main(int argc, const char** argv)
#endif #endif
{ {
//dummy();
/* Xterm check */ /* Xterm check */
const char* term = getenv("TERM"); const char* term = getenv("TERM");
if (term && !strncmp(term, "xterm", 5)) if (term && !strncmp(term, "xterm", 5))
@ -75,19 +85,25 @@ int main(int argc, const char** argv)
if (argc == 1) if (argc == 1)
{ {
printHelp(argv[0]); printHelp(argv[0]);
#if WIN_PAUSE
system("PAUSE");
#endif
return 0; return 0;
} }
else if (argc == 0) else if (argc == 0)
{ {
printHelp(_S("hecl")); printHelp(_S("hecl"));
#if WIN_PAUSE
system("PAUSE");
#endif
return 0; return 0;
} }
/* Assemble common tool pass info */ /* Assemble common tool pass info */
ToolPassInfo info; ToolPassInfo info;
info.pname = argv[0]; info.pname = argv[0];
HECL::SystemChar cwdbuf[MAXPATHLEN]; HECL::SystemChar cwdbuf[1024];
if (HECL::Getcwd(cwdbuf, MAXPATHLEN)) if (HECL::Getcwd(cwdbuf, 1024))
info.cwd = cwdbuf; info.cwd = cwdbuf;
/* Concatenate args */ /* Concatenate args */
@ -173,6 +189,9 @@ int main(int argc, const char** argv)
LogModule.report(LogVisor::Error, LogModule.report(LogVisor::Error,
_S("Unable to open discovered project at '%s'"), _S("Unable to open discovered project at '%s'"),
rootPath->getAbsolutePath().c_str()); rootPath->getAbsolutePath().c_str());
#if WIN_PAUSE
system("PAUSE");
#endif
return -1; return -1;
} }
} }
@ -214,6 +233,9 @@ int main(int argc, const char** argv)
#else #else
LogModule.report(LogVisor::Error, _S("Unable to construct HECL tool '%s': %s"), LogModule.report(LogVisor::Error, _S("Unable to construct HECL tool '%s': %s"),
toolName.c_str(), ex.what()); toolName.c_str(), ex.what());
#endif
#if WIN_PAUSE
system("PAUSE");
#endif #endif
return -1; return -1;
} }
@ -236,10 +258,16 @@ int main(int argc, const char** argv)
#else #else
LogModule.report(LogVisor::Error, _S("Error running HECL tool '%s': %s"), LogModule.report(LogVisor::Error, _S("Error running HECL tool '%s': %s"),
toolName.c_str(), ex.what()); toolName.c_str(), ex.what());
#endif
#if WIN_PAUSE
system("PAUSE");
#endif #endif
return -1; return -1;
} }
#if WIN_PAUSE
system("PAUSE");
#endif
return retval; 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(blowfish)
add_subdirectory(LogVisor) add_subdirectory(LogVisor)
add_subdirectory(AngelScript) add_subdirectory(AngelScript)
add_subdirectory(Athena) add_subdirectory(Athena EXCLUDE_FROM_ALL)
add_subdirectory(RetroCommon) 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; *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; unsigned i,j;
union union
{ {
uint32_t h32[2]; uint32_t h32[2];
int64_t h64; int64_t h64;
} hash = {}; } hash = {0,0};
for (i=0 ; i<len/4 ; ++i) 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_encipher(uint32_t *xl, uint32_t *xr);
void Blowfish_decipher(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 #ifdef __cplusplus
} }

View File

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

View File

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

View File

@ -10,6 +10,12 @@
#include <dirent.h> #include <dirent.h>
#include <fcntl.h> #include <fcntl.h>
#include <unistd.h> #include <unistd.h>
#else
#define _WIN32_LEAN_AND_MEAN 1
#include <Windows.h>
#include <wchar.h>
#include "winsupport.h"
#define snprintf _snprintf
#endif #endif
#include <time.h> #include <time.h>
@ -24,6 +30,10 @@
#include <Athena/DNA.hpp> #include <Athena/DNA.hpp>
#include "../extern/blowfish/blowfish.h" #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 namespace HECL
{ {
@ -73,6 +83,7 @@ inline std::wstring operator+(const wchar_t* lhs, const SystemStringView& rhs) {
#ifndef _S #ifndef _S
#define _S(val) L ## val #define _S(val) L ## val
#endif #endif
typedef struct _stat Sstat;
#else #else
typedef char SystemChar; typedef char SystemChar;
static inline size_t StrLen(const SystemChar* str) {return strlen(str);} 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 #ifndef _S
#define _S(val) val #define _S(val) val
#endif #endif
typedef struct stat Sstat;
#endif #endif
static inline void MakeDir(const SystemString& dir) 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) static inline SystemChar* Getcwd(SystemChar* buf, int maxlen)
{ {
#if HECL_UCS2 #if HECL_UCS2
return wgetcwd(buf, maxlen); return _wgetcwd(buf, maxlen);
#else #else
return getcwd(buf, maxlen); return getcwd(buf, maxlen);
#endif #endif
@ -144,7 +156,7 @@ enum FileLockType
static inline FILE* Fopen(const SystemChar* path, const SystemChar* mode, FileLockType lock=LNONE) static inline FILE* Fopen(const SystemChar* path, const SystemChar* mode, FileLockType lock=LNONE)
{ {
#if HECL_UCS2 #if HECL_UCS2
FILE* fp = wfopen(path, mode); FILE* fp = _wfopen(path, mode);
#else #else
FILE* fp = fopen(path, mode); FILE* fp = fopen(path, mode);
#endif #endif
@ -154,9 +166,8 @@ static inline FILE* Fopen(const SystemChar* path, const SystemChar* mode, FileLo
if (lock) if (lock)
{ {
#if _WIN32 #if _WIN32
HANDLE fhandle = (HANDLE)fileno(fp);
OVERLAPPED ov = {}; 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 #else
if (flock(fileno(fp), ((lock == LWRITE) ? LOCK_EX : LOCK_SH) | LOCK_NB)) if (flock(fileno(fp), ((lock == LWRITE) ? LOCK_EX : LOCK_SH) | LOCK_NB))
throw std::error_code(errno, std::system_category()); 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; return fp;
} }
static inline int Stat(const SystemChar* path, struct stat* statOut) static inline int Stat(const SystemChar* path, Sstat* statOut)
{ {
#if HECL_UCS2 #if HECL_UCS2
return wstat(path, statOut); return _wstat(path, statOut);
#else #else
return stat(path, statOut); return stat(path, statOut);
#endif #endif
@ -204,7 +215,7 @@ static inline void SNPrintf(SystemChar* str, size_t maxlen, const SystemChar* fo
va_list va; va_list va;
va_start(va, format); va_start(va, format);
#if HECL_UCS2 #if HECL_UCS2
vsnwprintf(str, maxlen, format, va); _vsnwprintf(str, maxlen, format, va);
#else #else
vsnprintf(str, maxlen, format, va); vsnprintf(str, maxlen, format, va);
#endif #endif
@ -243,7 +254,7 @@ static inline int ConsoleWidth()
#if _WIN32 #if _WIN32
CONSOLE_SCREEN_BUFFER_INFO info; CONSOLE_SCREEN_BUFFER_INFO info;
GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &info); GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &info);
m_lineWidth = info.dwSize.X; retval = info.dwSize.X;
#else #else
struct winsize w; struct winsize w;
if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &w) != -1) if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &w) != -1)
@ -304,9 +315,11 @@ class Hash final
int64_t hash; int64_t hash;
public: public:
Hash(const void* buf, size_t len) 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(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(int64_t hashin)
: hash(hashin) {} : hash(hashin) {}
Hash(const Hash& other) {hash = other.hash;} Hash(const Hash& other) {hash = other.hash;}
@ -362,14 +375,14 @@ protected:
Hash m_hash = 0; Hash m_hash = 0;
#if HECL_UCS2 #if HECL_UCS2
std::string m_utf8AbsPath; std::string m_utf8AbsPath;
const char* m_utf8RelPath; std::string m_utf8RelPath;
#endif #endif
ProjectPath(const SystemString& projRoot) 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 #if HECL_UCS2
m_utf8AbsPath = WideToUTF8(m_absPath); m_utf8AbsPath = WideToUTF8(m_absPath);
m_utf8RelPath = m_utf8AbsPath.c_str() + ((ProjectPath&)rootPath).m_utf8AbsPath.size(); m_utf8RelPath = ".";
#endif #endif
} }
public: public:
@ -380,6 +393,10 @@ public:
*/ */
ProjectPath(const ProjectPath& parentPath, const SystemString& path); 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 * @brief Determine if ProjectPath represents project root directory
* @return true if 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 namespace std
{ {
template <> struct hash<HECL::FourCC> 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();} {return val.toUint32();}
}; };
template <> struct hash<HECL::ProjectPath> 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();} {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(Frontend)
add_subdirectory(Runtime) add_subdirectory(Runtime)
add_library(HECL if(WIN32)
list(APPEND PLAT_SRCS winsupport.c ../include/HECL/winsupport.h)
endif()
add_library(HECLCommon
HECL.cpp HECL.cpp
ProjectPath.cpp ProjectPath.cpp
WideStringConvert.cpp WideStringConvert.cpp
@ -11,5 +15,6 @@ add_library(HECL
../include/HECL/Backend.hpp ../include/HECL/Backend.hpp
../include/HECL/Frontend.hpp ../include/HECL/Frontend.hpp
../include/HECL/Database.hpp ../include/HECL/Database.hpp
../include/HECL/Runtime.hpp) ../include/HECL/Runtime.hpp
${PLAT_SRCS})

View File

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

View File

@ -174,12 +174,20 @@ bool Project::ConfigFile::unlockAndCommit()
m_lockedFile = NULL; m_lockedFile = NULL;
if (fail) if (fail)
{ {
#if HECL_UCS2
_wunlink(newPath.c_str());
#else
unlink(newPath.c_str()); unlink(newPath.c_str());
#endif
return false; return false;
} }
else else
{ {
#if HECL_UCS2
_wrename(newPath.c_str(), m_filepath.c_str());
#else
rename(newPath.c_str(), m_filepath.c_str()); rename(newPath.c_str(), m_filepath.c_str());
#endif
return true; return true;
} }
} }
@ -197,7 +205,7 @@ Project::Project(const ProjectRootPath& rootPath)
m_groups(*this, _S("groups")) m_groups(*this, _S("groups"))
{ {
/* Stat for existing project directory (must already exist) */ /* Stat for existing project directory (must already exist) */
struct stat myStat; Sstat myStat;
if (HECL::Stat(m_rootPath.getAbsolutePath().c_str(), &myStat)) if (HECL::Stat(m_rootPath.getAbsolutePath().c_str(), &myStat))
throw std::error_code(errno, std::system_category()); throw std::error_code(errno, std::system_category());
@ -293,7 +301,7 @@ void Project::rescanDataSpecs()
for (const DataSpecEntry* spec : DATA_SPEC_REGISTRY) for (const DataSpecEntry* spec : DATA_SPEC_REGISTRY)
{ {
SystemUTF8View specUTF8(spec->m_name); 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.checkForLine(specUTF8) ? true : false});
} }
m_specs.unlockAndDiscard(); m_specs.unlockAndDiscard();
@ -303,7 +311,10 @@ bool Project::enableDataSpecs(const std::vector<SystemString>& specs)
{ {
m_specs.lockAndRead(); m_specs.lockAndRead();
for (const SystemString& spec : specs) for (const SystemString& spec : specs)
m_specs.addLine(spec); {
SystemUTF8View specView(spec);
m_specs.addLine(specView);
}
bool result = m_specs.unlockAndCommit(); bool result = m_specs.unlockAndCommit();
rescanDataSpecs(); rescanDataSpecs();
return result; return result;
@ -313,16 +324,20 @@ bool Project::disableDataSpecs(const std::vector<SystemString>& specs)
{ {
m_specs.lockAndRead(); m_specs.lockAndRead();
for (const SystemString& spec : specs) for (const SystemString& spec : specs)
m_specs.removeLine(spec); {
SystemUTF8View specView(spec);
m_specs.removeLine(specView);
}
bool result = m_specs.unlockAndCommit(); bool result = m_specs.unlockAndCommit();
rescanDataSpecs(); rescanDataSpecs();
return result; return result;
} }
bool Project::cookPath(const ProjectPath& path, bool Project::cookPath(const ProjectPath& path,
std::function<void(std::string&, Cost, unsigned)> feedbackCb, std::function<void(SystemString&, Cost, unsigned)> feedbackCb,
bool recursive) bool recursive)
{ {
return false;
} }
void Project::interruptCook() void Project::interruptCook()
@ -331,10 +346,12 @@ void Project::interruptCook()
bool Project::cleanPath(const ProjectPath& path, bool recursive) bool Project::cleanPath(const ProjectPath& path, bool recursive)
{ {
return false;
} }
PackageDepsgraph Project::buildPackageDepsgraph(const ProjectPath& path) 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 retval;
} }
return "."; return _S(".");
} }
ProjectPath::ProjectPath(const ProjectPath& parentPath, const SystemString& path) ProjectPath::ProjectPath(const ProjectPath& parentPath, const SystemString& path)
: m_projRoot(parentPath.m_projRoot) : m_projRoot(parentPath.m_projRoot)
{ {
m_relPath = canonRelPath(parentPath.m_relPath + '/' + path); m_relPath = canonRelPath(parentPath.m_relPath + _S('/') + path);
m_absPath = parentPath.m_projRoot + '/' + m_relPath; m_absPath = parentPath.m_projRoot + _S('/') + m_relPath;
m_hash = Hash(m_relPath); m_hash = Hash(m_relPath);
#if HECL_UCS2 #if HECL_UCS2
m_utf8AbsPath = WideToUTF8(m_absPath); m_utf8AbsPath = WideToUTF8(m_absPath);
m_utf8RelPath = m_utf8AbsPath.c_str() + ((ProjectPath&)rootPath).m_utf8AbsPath.size(); m_utf8RelPath = WideToUTF8(m_relPath);
#endif #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 ProjectPath::PathType ProjectPath::getPathType() const
{ {
if (std::regex_search(m_absPath, regGLOB)) if (std::regex_search(m_absPath, regGLOB))
return PT_GLOB; return PT_GLOB;
#if _WIN32 Sstat theStat;
#else if (HECL::Stat(m_absPath.c_str(), &theStat))
struct stat theStat;
if (stat(m_absPath.c_str(), &theStat))
return PT_NONE; return PT_NONE;
if (S_ISDIR(theStat.st_mode)) if (S_ISDIR(theStat.st_mode))
return PT_DIRECTORY; return PT_DIRECTORY;
if (S_ISREG(theStat.st_mode)) if (S_ISREG(theStat.st_mode))
return PT_FILE; return PT_FILE;
return PT_NONE; return PT_NONE;
#endif
} }
Time ProjectPath::getModtime() const Time ProjectPath::getModtime() const
{ {
struct stat theStat; Sstat theStat;
time_t latestTime = 0; time_t latestTime = 0;
if (std::regex_search(m_absPath, regGLOB)) 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 void ProjectPath::getGlobResults(std::vector<SystemString>& outPaths) const
{ {
#if _WIN32 #if _WIN32
TSystemPath itStr; SystemString itStr;
SystemRegexMatch letterMatch; SystemRegexMatch letterMatch;
if (m_absPath.compare(0, 2, _S("//"))) if (m_absPath.compare(0, 2, _S("//")))
itStr = _S("\\\\"); itStr = _S("\\\\");
@ -214,7 +224,7 @@ std::unique_ptr<ProjectRootPath> SearchForProject(const SystemString& path)
{ {
SystemString testPath(begin, end); SystemString testPath(begin, end);
SystemString testIndexPath = testPath + _S("/.hecl/beacon"); SystemString testIndexPath = testPath + _S("/.hecl/beacon");
struct stat theStat; Sstat theStat;
if (!HECL::Stat(testIndexPath.c_str(), &theStat)) if (!HECL::Stat(testIndexPath.c_str(), &theStat))
{ {
if (S_ISREG(theStat.st_mode)) if (S_ISREG(theStat.st_mode))
@ -236,6 +246,7 @@ std::unique_ptr<ProjectRootPath> SearchForProject(const SystemString& path)
while (begin != end && *(end-1) != _S('/') && *(end-1) != _S('\\')) while (begin != end && *(end-1) != _S('/') && *(end-1) != _S('\\'))
--end; --end;
if (begin != end)
--end; --end;
} }
return std::unique_ptr<ProjectRootPath>(); return std::unique_ptr<ProjectRootPath>();

View File

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