Added Unicode support for the Windows build.

- tcharx.h: Copied over from RVT-H Tool.
- SetWindowsEntrypoint.cmake: Likewise.
- CMakeLists.txt: Compile with -DUNICODE and -D_UNICODE, plus several
  other useful things like MSVCRT secure overloads.

TODO:
- Enable wildcard expansion for mst06?
- Move Windows compiler settings to a separate .cmake file.
This commit is contained in:
David Korth 2019-05-11 11:57:59 -04:00
parent 459fa78c93
commit 30bad7d0d6
5 changed files with 161 additions and 5 deletions

View File

@ -1,6 +1,10 @@
PROJECT(mst06_base) PROJECT(mst06_base)
CMAKE_MINIMUM_REQUIRED(VERSION 3.1) CMAKE_MINIMUM_REQUIRED(VERSION 3.1)
LIST(APPEND CMAKE_MODULE_PATH
"${CMAKE_SOURCE_DIR}/cmake/modules"
)
# If no build type is set, default to "Debug". # If no build type is set, default to "Debug".
# TODO: Default to "Release"? # TODO: Default to "Release"?
STRING(TOLOWER "${CMAKE_BUILD_TYPE}" TMP_BUILD_TYPE) STRING(TOLOWER "${CMAKE_BUILD_TYPE}" TMP_BUILD_TYPE)
@ -37,6 +41,31 @@ CONFIGURE_FILE(
ADD_CUSTOM_TARGET(uninstall ADD_CUSTOM_TARGET(uninstall
"${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_BINARY_DIR}/cmake/cmake_uninstall.cmake") "${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_BINARY_DIR}/cmake/cmake_uninstall.cmake")
# Windows-specific compile flags.
IF(WIN32)
SET(WIN32_C_FLAGS_COMMON "-DSTRICT -DWIN32_LEAN_AND_MEAN -DNOMINMAX")
# NOTE: This program only supports Unicode on Windows.
# No support for ANSI Windows, i.e. Win9x.
SET(WIN32_C_FLAGS_COMMON "${WIN32_C_FLAGS_COMMON} -DUNICODE -D_UNICODE")
# Minimum Windows version for the SDK is Windows 2000.
SET(WIN32_C_FLAGS_COMMON "${WIN32_C_FLAGS_COMMON} -DWINVER=0x0500 -D_WIN32_WINNT=0x0500 -D_WIN32_IE=0x0500")
# Enable secure template overloads for C++.
# References:
# - MinGW's _mingw_secapi.h
# - http://msdn.microsoft.com/en-us/library/ms175759%28v=VS.100%29.aspx
SET(WIN32_CXX_FLAGS_COMMON "-D_CRT_SECURE_CPP_OVERLOAD_SECURE_NAMES=1")
SET(WIN32_CXX_FLAGS_COMMON "${WIN32_CXX_FLAGS_COMMON} -D_CRT_SECURE_CPP_OVERLOAD_SECURE_NAMES_MEMORY=1")
SET(WIN32_CXX_FLAGS_COMMON "${WIN32_CXX_FLAGS_COMMON} -D_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES=1")
SET(WIN32_CXX_FLAGS_COMMON "${WIN32_CXX_FLAGS_COMMON} -D_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_COUNT=1")
SET(WIN32_CXX_FLAGS_COMMON "${WIN32_CXX_FLAGS_COMMON} -D_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_MEMORY=1")
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${WIN32_C_FLAGS_COMMON}")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${WIN32_C_FLAGS_COMMON} ${WIN32_CXX_FLAGS_COMMON}")
ENDIF(WIN32)
# Disable unnecessary warnings. # Disable unnecessary warnings.
INCLUDE(CheckCCompilerFlag) INCLUDE(CheckCCompilerFlag)
IF(MSVC) IF(MSVC)

View File

@ -0,0 +1,51 @@
# Set Windows entrypoint.
# _target: Target.
# _entrypoint: Entry point. (main, wmain, WinMain, wWinMain)
# _setargv: If true, link to setargv.obj/wsetargv.obj in MSVC builds.
FUNCTION(SET_WINDOWS_ENTRYPOINT _target _entrypoint _setargv)
IF(WIN32)
IF(MSVC)
# MSVC automatically prepends an underscore if necessary.
SET(ENTRY_POINT_FLAG "/ENTRY:${_entrypoint}CRTStartup")
IF(_setargv)
IF(_entrypoint MATCHES ^wmain OR _entrypoint MATCHES ^wWinMain)
SET(SETARGV_FLAG "wsetargv.obj")
ELSE()
SET(SETARGV_FLAG "setargv.obj")
ENDIF()
ENDIF(_setargv)
UNSET(UNICODE_FLAG)
ELSE(MSVC)
# MinGW does not automatically prepend an underscore.
# TODO: Does ARM Windows have a leading underscore?
# TODO: _setargv for MinGW.
# NOTE: MinGW uses separate crt*.o files for Unicode
# instead of a separate entry point.
IF(_entrypoint MATCHES "^w")
SET(UNICODE_FLAG "-municode")
STRING(SUBSTRING "${_entrypoint}" 1 -1 _entrypoint)
ENDIF()
IF(CPU_i386 OR CPU_amd64)
IF(CMAKE_SIZEOF_VOID_P EQUAL 4)
SET(ENTRY_POINT "_${_entrypoint}CRTStartup")
ELSE()
SET(ENTRY_POINT "${_entrypoint}CRTStartup")
ENDIF()
ELSE()
SET(ENTRY_POINT "${_entrypoint}CRTStartup")
ENDIF(CPU_i386 OR CPU_amd64)
SET(ENTRY_POINT_FLAG "-Wl,-e,${ENTRY_POINT}")
UNSET(SETARGV_FLAG)
ENDIF(MSVC)
GET_TARGET_PROPERTY(TARGET_LINK_FLAGS ${_target} LINK_FLAGS)
IF(TARGET_LINK_FLAGS)
SET(TARGET_LINK_FLAGS "${TARGET_LINK_FLAGS} ${UNICODE_FLAG} ${ENTRY_POINT_FLAG} ${SETARGV_FLAG}")
ELSE()
SET(TARGET_LINK_FLAGS "${UNICODE_FLAG} ${ENTRY_POINT_FLAG} ${SETARGV_FLAG}")
ENDIF()
SET_TARGET_PROPERTIES(${_target} PROPERTIES LINK_FLAGS "${TARGET_LINK_FLAGS}")
ENDIF(WIN32)
ENDFUNCTION()

View File

@ -23,3 +23,7 @@ SET(mst06_H
ADD_EXECUTABLE(mst06 ${mst06_SRCS} ${mst06_H}) ADD_EXECUTABLE(mst06 ${mst06_SRCS} ${mst06_H})
SET_PROPERTY(TARGET mst06 PROPERTY CXX_STANDARD 11) SET_PROPERTY(TARGET mst06 PROPERTY CXX_STANDARD 11)
TARGET_INCLUDE_DIRECTORIES(mst06 PRIVATE "${CMAKE_CURRENT_BINARY_DIR}") TARGET_INCLUDE_DIRECTORIES(mst06 PRIVATE "${CMAKE_CURRENT_BINARY_DIR}")
# TODO: Enable wildcard expansion on Windows?
INCLUDE(SetWindowsEntrypoint)
SET_WINDOWS_ENTRYPOINT(mst06 wmain OFF)

View File

@ -1,6 +1,6 @@
/*************************************************************************** /***************************************************************************
* MST Decoder/Encoder for Sonic '06 * * MST Decoder/Encoder for Sonic '06 *
* main.cpp: Main program. * * mst06.cpp: Main program. *
* * * *
* Copyright (c) 2019 by David Korth. * * Copyright (c) 2019 by David Korth. *
* * * *
@ -32,17 +32,18 @@ using std::pair;
#include "mst_structs.h" #include "mst_structs.h"
#include "byteswap.h" #include "byteswap.h"
#include "tcharx.h"
int main(int argc, char *argv[]) int _tmain(int argc, TCHAR *argv[])
{ {
if (argc != 2) { if (argc != 2) {
fprintf(stderr, "Syntax: %s mst_file.mst\n", argv[0]); _ftprintf(stderr, _T("Syntax: %s mst_file.mst\n"), argv[0]);
return EXIT_FAILURE; return EXIT_FAILURE;
} }
FILE *f_mst = fopen(argv[1], "rb"); FILE *f_mst = _tfopen(argv[1], _T("rb"));
if (!f_mst) { if (!f_mst) {
fprintf(stderr, "*** ERROR opening %s: %s\n", argv[1], strerror(errno)); _ftprintf(stderr, _T("*** ERROR opening %s: %s\n"), argv[1], _tcserror(errno));
return EXIT_FAILURE; return EXIT_FAILURE;
} }

71
src/tcharx.h Normal file
View File

@ -0,0 +1,71 @@
/***************************************************************************
* MST Decoder/Encoder for Sonic '06 *
* tcharx.h: TCHAR support for Windows and Linux. *
* *
* Copyright (c) 2018-2019 by David Korth. *
* *
* This program is free software; you can redistribute it and/or modify it *
* under the terms of the GNU General Public License as published by the *
* Free Software Foundation; either version 3 of the License, or (at your *
* option) any later version. *
* *
* This program is distributed in the hope that it will be useful, but *
* WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
***************************************************************************/
#ifndef __MST06_TCHARX_H__
#define __MST06_TCHARX_H__
#ifdef _WIN32
// Windows: Use the SDK tchar.h.
#include <tchar.h>
// std::tstring
#ifdef _UNICODE
# define tstring wstring
#else /* !_UNICODE */
# define tstring string
#endif /* _UNICODE */
#else /* !_WIN32 */
// Other systems: Define TCHAR and related macros.
typedef char TCHAR;
#define _T(x) x
#define _tmain main
#define tstring string
// ctype.h
#define _istalpha(c) isalpha(c)
// stdio.h
#define _fputts(s, stream) fputs(s, stream)
#define _tfopen(filename, mode) fopen((filename), (mode))
#define _tprintf printf
#define _ftprintf fprintf
#define _sntprintf snprintf
#define _vtprintf vprintf
#define _vftprintf vfprintf
#define _vsprintf vsprintf
// stdlib.h
#define _tcscmp(s1, s2) strcmp((s1), (s2))
#define _tcsicmp(s1, s2) strcasecmp((s1), (s2))
#define _tcsnicmp(s1, s2) strncasecmp((s1), (s2), (n))
#define _tcstoul(nptr, endptr, base) strtoul((nptr), (endptr), (base))
// string.h
#define _tcsdup(s) strdup(s)
#define _tcserror(err) strerror(err)
#endif /* _WIN32 */
#endif /* __MST06_TCHARX_H__ */