diff --git a/src/alloy/core.h b/src/alloy/core.h index f5fd3040c..5f90cb31a 100644 --- a/src/alloy/core.h +++ b/src/alloy/core.h @@ -14,7 +14,6 @@ #include #include #include -#include #include #include #include diff --git a/src/poly/main.h b/src/poly/main.h new file mode 100644 index 000000000..82c02576d --- /dev/null +++ b/src/poly/main.h @@ -0,0 +1,37 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2014 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#ifndef POLY_MAIN_H_ +#define POLY_MAIN_H_ + +#include +#include + +#include + +namespace poly { + +// Returns true if there is a user-visible console attached to receive stdout. +bool has_console_attached(); + +// Extern defined by user code. This must be present for the application to +// launch. +struct EntryInfo { + std::wstring name; + std::wstring usage; + int (*entry_point)(std::vector& args); +}; +EntryInfo GetEntryInfo(); + +#define DEFINE_ENTRY_POINT(name, usage, entry_point) \ + poly::EntryInfo poly::GetEntryInfo() { return {name, usage, entry_point}; } + +} // namespace poly + +#endif // POLY_MAIN_H_ diff --git a/src/poly/main_posix.cc b/src/poly/main_posix.cc new file mode 100644 index 000000000..5af8b2437 --- /dev/null +++ b/src/poly/main_posix.cc @@ -0,0 +1,41 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2014 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#include + +#include + +namespace poly { + +bool has_console_attached() { + return true; +} + +} // namespace poly + + +extern "C" int main(int argc, char** argv) { + auto entry_info = poly::GetEntryInfo(); + + google::SetUsageMessage(std::string("usage: ") + + poly::to_string(entry_info.usage)); + google::SetVersionString("1.0"); + google::ParseCommandLineFlags(&argc, &argv, true); + + std::vector args; + for (int n = 0; n < argc; n++) { + args.push_back(poly::to_wstring(argv[n])); + } + + // Call app-provided entry point. + int result = entry_info.entry_point(args); + + google::ShutDownCommandLineFlags(); + return result; +} diff --git a/src/poly/main_win.cc b/src/poly/main_win.cc new file mode 100644 index 000000000..b4bdad74f --- /dev/null +++ b/src/poly/main_win.cc @@ -0,0 +1,105 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2014 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#include + +#include +#include +#include + +#include +#include + +namespace poly { + +bool has_console_attached_ = true; + +bool has_console_attached() { return has_console_attached_; } + +void AttachConsole() { + bool has_console = ::AttachConsole(ATTACH_PARENT_PROCESS) == TRUE; + if (!has_console) { + // We weren't launched from a console, so just return. + // We could alloc our own console, but meh: + // has_console = AllocConsole() == TRUE; + has_console_attached_ = false; + return; + } + has_console_attached_ = true; + + auto std_handle = (intptr_t)GetStdHandle(STD_OUTPUT_HANDLE); + auto con_handle = _open_osfhandle(std_handle, _O_TEXT); + auto fp = _fdopen(con_handle, "w"); + *stdout = *fp; + setvbuf(stdout, NULL, _IONBF, 0); + + std_handle = (intptr_t)GetStdHandle(STD_ERROR_HANDLE); + con_handle = _open_osfhandle(std_handle, _O_TEXT); + fp = _fdopen(con_handle, "w"); + *stderr = *fp; + setvbuf(stderr, NULL, _IONBF, 0); +} + +} // namespace poly + +// Used in console mode apps; automatically picked based on subsystem. +int wmain(int argc, wchar_t* argv[]) { + auto entry_info = poly::GetEntryInfo(); + + google::SetUsageMessage(std::string("usage: ") + + poly::to_string(entry_info.usage)); + google::SetVersionString("1.0"); + + // Convert all args to narrow, as gflags doesn't support wchar. + int argca = argc; + char** argva = (char**)alloca(sizeof(char*) * argca); + for (int n = 0; n < argca; n++) { + size_t len = wcslen(argv[n]); + argva[n] = (char*)alloca(len + 1); + wcstombs_s(NULL, argva[n], len + 1, argv[n], _TRUNCATE); + } + + // Parse flags; this may delete some of them. + google::ParseCommandLineFlags(&argc, &argva, true); + + // Widen all remaining flags and convert to usable strings. + std::vector args; + for (int n = 0; n < argc; n++) { + args.push_back(poly::to_wstring(argva[n])); + } + + // Call app-provided entry point. + int result = entry_info.entry_point(args); + + google::ShutDownCommandLineFlags(); + return result; +} + +// Used in windowed apps; automatically picked based on subsystem. +int WINAPI wWinMain(HINSTANCE, HINSTANCE, LPWSTR command_line, int) { + // Attach a console so we can write output to stdout. If the user hasn't + // redirected output themselves it'll pop up a window. + poly::AttachConsole(); + + auto entry_info = poly::GetEntryInfo(); + + // Convert to an argv-like format so we can share code/use gflags. + std::wstring buffer = entry_info.name + L" " + command_line; + int argc; + wchar_t** argv = CommandLineToArgvW(buffer.c_str(), &argc); + if (!argv) { + return 1; + } + + // Run normal entry point. + int result = wmain(argc, argv); + + LocalFree(argv); + return result; +} diff --git a/src/poly/poly-private.h b/src/poly/poly-private.h deleted file mode 100644 index 500cddd52..000000000 --- a/src/poly/poly-private.h +++ /dev/null @@ -1,15 +0,0 @@ -/** - ****************************************************************************** - * Xenia : Xbox 360 Emulator Research Project * - ****************************************************************************** - * Copyright 2014 Ben Vanik. All rights reserved. * - * Released under the BSD license - see LICENSE in the root for more details. * - ****************************************************************************** - */ - -#ifndef POLY_POLY_PRIVATE_H_ -#define POLY_POLY_PRIVATE_H_ - -#include - -#endif // POLY_POLY_PRIVATE_H_ diff --git a/src/poly/poly.cc b/src/poly/poly.cc deleted file mode 100644 index 2e306025b..000000000 --- a/src/poly/poly.cc +++ /dev/null @@ -1,13 +0,0 @@ -/** - ****************************************************************************** - * Xenia : Xbox 360 Emulator Research Project * - ****************************************************************************** - * Copyright 2014 Ben Vanik. All rights reserved. * - * Released under the BSD license - see LICENSE in the root for more details. * - ****************************************************************************** - */ - -#include -#include - -namespace poly {} // namespace poly diff --git a/src/poly/sources.gypi b/src/poly/sources.gypi index 547d9e838..b5faa8083 100644 --- a/src/poly/sources.gypi +++ b/src/poly/sources.gypi @@ -7,13 +7,12 @@ 'debugging.h', 'config.h', 'cxx_compat.h', + 'main.h', 'math.cc', 'math.h', 'memory.cc', 'memory.h', 'platform.h', - 'poly-private.h', - 'poly.cc', 'poly.h', 'string.cc', 'string.h', @@ -23,6 +22,7 @@ 'conditions': [ ['OS == "mac" or OS == "linux"', { 'sources': [ + 'main_posix.cc', ], }], ['OS == "linux"', { @@ -39,6 +39,7 @@ ['OS == "win"', { 'sources': [ 'debugging_win.cc', + 'main_win.cc', 'threading_win.cc', ], }], diff --git a/src/poly/string.cc b/src/poly/string.cc index 4716c0a32..0525b5541 100644 --- a/src/poly/string.cc +++ b/src/poly/string.cc @@ -39,4 +39,52 @@ std::string::size_type find_first_of_case(const std::string& target, } } +std::wstring to_absolute_path(const std::wstring& path) { +#if XE_LIKE_WIN32 + wchar_t buffer[poly::max_path]; + _wfullpath(buffer, path.c_str(), sizeof(buffer) / sizeof(wchar_t)); + return buffer; +#else + char buffer[poly::max_path]; + realpath(poly::to_string(path).c_str(), buffer); + return poly::to_wstring(buffer); +#endif // XE_LIKE_WIN32 +} + +std::wstring join_paths(const std::wstring& left, const std::wstring& right, + wchar_t sep) { + if (!left.size()) { + return right; + } else if (!right.size()) { + return left; + } + if (left[left.size() - 1] == sep) { + return left + right; + } else { + return left + sep + right; + } +} + +std::wstring fix_path_separators(const std::wstring& source, wchar_t new_sep) { + // Swap all separators to new_sep. + wchar_t old_sep = new_sep == '\\' ? '/' : '\\'; + std::wstring::size_type pos = 0; + std::wstring dest = source; + while ((pos = source.find_first_of(old_sep, pos)) != std::wstring::npos) { + dest[pos] = new_sep; + ++pos; + } + // Replace redundant separators. + pos = 0; + while ((pos = dest.find_first_of(new_sep, pos)) != std::wstring::npos) { + if (pos < dest.size() - 1) { + if (dest[pos + 1] == new_sep) { + dest.erase(pos + 1, 1); + } + } + ++pos; + } + return dest; +} + } // namespace poly diff --git a/src/poly/string.h b/src/poly/string.h index 7d360abd2..688dd4c1b 100644 --- a/src/poly/string.h +++ b/src/poly/string.h @@ -24,9 +24,22 @@ namespace poly { std::string to_string(const std::wstring& source); std::wstring to_wstring(const std::string& source); +// find_first_of string, case insensitive. std::string::size_type find_first_of_case(const std::string& target, const std::string& search); +// Converts the given path to an absolute path based on cwd. +std::wstring to_absolute_path(const std::wstring& path); + +// Joins two path segments with the given separator. +std::wstring join_paths(const std::wstring& left, const std::wstring& right, + wchar_t sep = poly::path_separator); + +// Replaces all path separators with the given value and removes redundant +// separators. +std::wstring fix_path_separators(const std::wstring& source, + wchar_t new_sep = poly::path_separator); + } // namespace poly #endif // POLY_STRING_H_ diff --git a/src/xenia/common.h b/src/xenia/common.h index 048829080..9288f0d24 100644 --- a/src/xenia/common.h +++ b/src/xenia/common.h @@ -18,7 +18,6 @@ #include #include #include -#include #include #include #include diff --git a/src/xenia/core.h b/src/xenia/core.h index 3f606cc7a..12d7dfb93 100644 --- a/src/xenia/core.h +++ b/src/xenia/core.h @@ -20,7 +20,6 @@ namespace xe { #include #include #include -#include #include #include #include diff --git a/src/xenia/core/path.cc b/src/xenia/core/path.cc deleted file mode 100644 index c24d22966..000000000 --- a/src/xenia/core/path.cc +++ /dev/null @@ -1,35 +0,0 @@ -/** - ****************************************************************************** - * Xenia : Xbox 360 Emulator Research Project * - ****************************************************************************** - * Copyright 2013 Ben Vanik. All rights reserved. * - * Released under the BSD license - see LICENSE in the root for more details. * - ****************************************************************************** - */ - -#include - - -void xe_path_join(const xechar_t* left, const xechar_t* right, - xechar_t* out_path, size_t out_path_size) { -#if XE_WCHAR - xesnprintf(out_path, out_path_size, L"%ls%c%ls", - left, poly::path_separator, right); -#else - xesnprintf(out_path, out_path_size, L"%s%c%s", - left, poly::path_separator, right); -#endif // XE_WCHAR -} - -void xe_path_get_absolute(const xechar_t* path, xechar_t* out_abs_path, - size_t abs_path_size) { -#if XE_PLATFORM_WIN32 -#if XE_WCHAR - _wfullpath(out_abs_path, path, abs_path_size); -#else - _fullpath(out_abs_path, path, abs_path_size); -#endif // XE_WCHAR -#else - realpath(path, out_abs_path); -#endif // WIN32 -} diff --git a/src/xenia/core/path.h b/src/xenia/core/path.h deleted file mode 100644 index 7ccfde28b..000000000 --- a/src/xenia/core/path.h +++ /dev/null @@ -1,25 +0,0 @@ -/** - ****************************************************************************** - * Xenia : Xbox 360 Emulator Research Project * - ****************************************************************************** - * Copyright 2013 Ben Vanik. All rights reserved. * - * Released under the BSD license - see LICENSE in the root for more details. * - ****************************************************************************** - */ - -#ifndef XENIA_CORE_PATH_H_ -#define XENIA_CORE_PATH_H_ - -#include -#include -#include - - -void xe_path_join(const xechar_t* left, const xechar_t* right, - xechar_t* out_path, size_t out_path_size); -void xe_path_get_absolute(const xechar_t* path, xechar_t* out_abs_path, - size_t abs_path_size); - -const xechar_t* xe_path_get_tmp(const xechar_t* prefix); - -#endif // XENIA_CORE_PATH_H_ diff --git a/src/xenia/core/path_posix.cc b/src/xenia/core/path_posix.cc deleted file mode 100644 index 0dc9aadec..000000000 --- a/src/xenia/core/path_posix.cc +++ /dev/null @@ -1,16 +0,0 @@ -/** - ****************************************************************************** - * Xenia : Xbox 360 Emulator Research Project * - ****************************************************************************** - * Copyright 2013 Ben Vanik. All rights reserved. * - * Released under the BSD license - see LICENSE in the root for more details. * - ****************************************************************************** - */ - -#include - - -const xechar_t* xe_path_get_tmp(const xechar_t* prefix) { - // - assert_always(); -} diff --git a/src/xenia/core/path_win.cc b/src/xenia/core/path_win.cc deleted file mode 100644 index ded9bf388..000000000 --- a/src/xenia/core/path_win.cc +++ /dev/null @@ -1,17 +0,0 @@ -/** - ****************************************************************************** - * Xenia : Xbox 360 Emulator Research Project * - ****************************************************************************** - * Copyright 2013 Ben Vanik. All rights reserved. * - * Released under the BSD license - see LICENSE in the root for more details. * - ****************************************************************************** - */ - -#include - - -const xechar_t* xe_path_get_tmp(const xechar_t* prefix) { - // - assert_always(); - return NULL; -} diff --git a/src/xenia/core/sources.gypi b/src/xenia/core/sources.gypi index 450a12cbd..206ae0e60 100644 --- a/src/xenia/core/sources.gypi +++ b/src/xenia/core/sources.gypi @@ -5,8 +5,6 @@ 'hash.h', 'mmap.h', 'pal.h', - 'path.cc', - 'path.h', 'ref.cc', 'ref.h', 'run_loop.h', @@ -17,7 +15,6 @@ ['OS == "mac" or OS == "linux"', { 'sources': [ 'mmap_posix.cc', - 'path_posix.cc', 'socket_posix.cc', ], }], @@ -35,7 +32,6 @@ 'sources': [ 'mmap_win.cc', 'pal_win.cc', - 'path_win.cc', 'run_loop_win.cc', 'socket_win.cc', ], diff --git a/src/xenia/kernel/fs/devices/disc_image_device.cc b/src/xenia/kernel/fs/devices/disc_image_device.cc index da8b8912a..584fe6e21 100644 --- a/src/xenia/kernel/fs/devices/disc_image_device.cc +++ b/src/xenia/kernel/fs/devices/disc_image_device.cc @@ -59,7 +59,7 @@ Entry* DiscImageDevice::ResolvePath(const char* path) { char remaining[poly::max_path]; XEIGNORE(xestrcpya(remaining, XECOUNT(remaining), path)); while (remaining[0]) { - char* next_slash = xestrchra(remaining, '\\'); + char* next_slash = strchr(remaining, '\\'); if (next_slash == remaining) { // Leading slash - shift XEIGNORE(xestrcpya(remaining, XECOUNT(remaining), remaining + 1)); diff --git a/src/xenia/kernel/fs/devices/host_path_device.cc b/src/xenia/kernel/fs/devices/host_path_device.cc index 9bd4c4a29..ff6b55601 100644 --- a/src/xenia/kernel/fs/devices/host_path_device.cc +++ b/src/xenia/kernel/fs/devices/host_path_device.cc @@ -9,7 +9,6 @@ #include -#include #include #include @@ -30,27 +29,9 @@ Entry* HostPathDevice::ResolvePath(const char* path) { XELOGFS("HostPathDevice::ResolvePath(%s)", path); -#if XE_WCHAR - xechar_t rel_path[poly::max_path]; - XEIGNORE(xestrwiden(rel_path, XECOUNT(rel_path), path)); -#else - const xechar_t* rel_path = path; -#endif - - xechar_t full_path[poly::max_path]; - xe_path_join(local_path_.c_str(), rel_path, full_path, XECOUNT(full_path)); - - // Swap around path separators. - if (poly::path_separator != '\\') { - for (size_t n = 0; n < XECOUNT(full_path); n++) { - if (full_path[n] == 0) { - break; - } - if (full_path[n] == '\\') { - full_path[n] = poly::path_separator; - } - } - } + auto rel_path = poly::to_wstring(path); + auto full_path = poly::join_paths(local_path_, rel_path); + full_path = poly::fix_path_separators(full_path); // TODO(benvanik): get file info // TODO(benvanik): fail if does not exit diff --git a/src/xenia/kernel/fs/devices/stfs_container_device.cc b/src/xenia/kernel/fs/devices/stfs_container_device.cc index da37bc4bf..dd35202dc 100644 --- a/src/xenia/kernel/fs/devices/stfs_container_device.cc +++ b/src/xenia/kernel/fs/devices/stfs_container_device.cc @@ -59,7 +59,7 @@ Entry* STFSContainerDevice::ResolvePath(const char* path) { char remaining[poly::max_path]; XEIGNORE(xestrcpya(remaining, XECOUNT(remaining), path)); while (remaining[0]) { - char* next_slash = xestrchra(remaining, '\\'); + char* next_slash = strchr(remaining, '\\'); if (next_slash == remaining) { // Leading slash - shift XEIGNORE(xestrcpya(remaining, XECOUNT(remaining), remaining + 1)); diff --git a/src/xenia/kernel/objects/xmodule.cc b/src/xenia/kernel/objects/xmodule.cc index 462d76ac4..406534556 100644 --- a/src/xenia/kernel/objects/xmodule.cc +++ b/src/xenia/kernel/objects/xmodule.cc @@ -17,19 +17,20 @@ using namespace xe::cpu; using namespace xe::kernel; -XModule::XModule(KernelState* kernel_state, const char* path) : - XObject(kernel_state, kTypeModule) { - XEIGNORE(xestrcpya(path_, XECOUNT(path_), path)); - const char* slash = xestrrchra(path, '/'); - if (!slash) { - slash = xestrrchra(path, '\\'); +XModule::XModule(KernelState* kernel_state, const std::string& path) : + XObject(kernel_state, kTypeModule), path_(path) { + auto last_slash = path.find_last_of('/'); + if (last_slash == path.npos) { + last_slash = path.find_last_of('\\'); } - if (slash) { - XEIGNORE(xestrcpya(name_, XECOUNT(name_), slash + 1)); + if (last_slash == path.npos) { + name_ = path_; + } else { + name_ = path_.substr(last_slash + 1); } - char* dot = xestrrchra(name_, '.'); - if (dot) { - *dot = 0; + auto dot = name_.find_last_of('.'); + if (dot != name_.npos) { + name_ = name_.substr(0, dot); } } diff --git a/src/xenia/kernel/objects/xmodule.h b/src/xenia/kernel/objects/xmodule.h index 9537adbcd..1af9e3ea8 100644 --- a/src/xenia/kernel/objects/xmodule.h +++ b/src/xenia/kernel/objects/xmodule.h @@ -10,6 +10,8 @@ #ifndef XENIA_KERNEL_XBOXKRNL_XMODULE_H_ #define XENIA_KERNEL_XBOXKRNL_XMODULE_H_ +#include + #include #include @@ -21,11 +23,11 @@ namespace kernel { class XModule : public XObject { public: - XModule(KernelState* kernel_state, const char* path); + XModule(KernelState* kernel_state, const std::string& path); virtual ~XModule(); - const char* path() const { return path_; } - const char* name() const { return name_; } + const std::string& path() const { return path_; } + const std::string& name() const { return name_; } virtual void* GetProcAddressByOrdinal(uint16_t ordinal) = 0; virtual X_STATUS GetSection( @@ -35,8 +37,8 @@ public: protected: void OnLoad(); - char name_[256]; - char path_[poly::max_path]; + std::string name_; + std::string path_; }; diff --git a/src/xenia/kernel/xboxkrnl_rtl.cc b/src/xenia/kernel/xboxkrnl_rtl.cc index 5ac309ae6..b08b0bcf7 100644 --- a/src/xenia/kernel/xboxkrnl_rtl.cc +++ b/src/xenia/kernel/xboxkrnl_rtl.cc @@ -200,19 +200,19 @@ SHIM_CALL RtlInitUnicodeString_shim( uint32_t destination_ptr = SHIM_GET_ARG_32(0); uint32_t source_ptr = SHIM_GET_ARG_32(1); - const wchar_t* source = - source_ptr ? (const wchar_t*)SHIM_MEM_ADDR(source_ptr) : NULL; - XELOGD("RtlInitUnicodeString(%.8X, %.8X = %ls)", - destination_ptr, source_ptr, source ? source : L""); + auto source = + source_ptr ? poly::load_and_swap(SHIM_MEM_ADDR(source_ptr)) + : L""; + XELOGD("RtlInitUnicodeString(%.8X, %.8X = %ls)", destination_ptr, source_ptr, + source.empty() ? L"" : source.c_str()); // VOID // _Out_ PUNICODE_STRING DestinationString, // _In_opt_ PCWSTR SourceString - if (source) { - uint16_t length = (uint16_t)xestrlenw(source); - SHIM_SET_MEM_16(destination_ptr + 0, length * 2); - SHIM_SET_MEM_16(destination_ptr + 2, (length + 1) * 2); + if (source.size()) { + SHIM_SET_MEM_16(destination_ptr + 0, source.size() * 2); + SHIM_SET_MEM_16(destination_ptr + 2, (source.size() + 1) * 2); SHIM_SET_MEM_32(destination_ptr + 4, source_ptr); } else { SHIM_SET_MEM_16(destination_ptr + 0, 0); diff --git a/src/xenia/logging.cc b/src/xenia/logging.cc index 1f387ad57..6ed64352d 100644 --- a/src/xenia/logging.cc +++ b/src/xenia/logging.cc @@ -11,10 +11,9 @@ #include -#include - #include - +#include +#include DEFINE_bool(fast_stdout, false, "Don't lock around stdout/stderr. May introduce weirdness."); @@ -31,7 +30,7 @@ void xe_format_log_line( const char* function_name, const char level_char, const char* fmt, va_list args) { // Strip out just the filename from the path. - const char* filename = xestrrchra(file_path, poly::path_separator); + const char* filename = strrchr(file_path, poly::path_separator); if (filename) { // Slash - skip over it. filename++; @@ -108,7 +107,7 @@ void xe_handle_fatal( } #if XE_LIKE_WIN32 - if (!xe_has_console()) { + if (!poly::has_console_attached()) { MessageBoxA(NULL, buffer, "Xenia Error", MB_OK | MB_ICONERROR | MB_APPLMODAL | MB_SETFOREGROUND); } diff --git a/src/xenia/logging.h b/src/xenia/logging.h index c030f4465..d8b7c30ae 100644 --- a/src/xenia/logging.h +++ b/src/xenia/logging.h @@ -12,7 +12,6 @@ #include -#include #include #include diff --git a/src/xenia/platform.cc b/src/xenia/platform.cc deleted file mode 100644 index c9d4d063b..000000000 --- a/src/xenia/platform.cc +++ /dev/null @@ -1,126 +0,0 @@ -/** - ****************************************************************************** - * Xenia : Xbox 360 Emulator Research Project * - ****************************************************************************** - * Copyright 2013 Ben Vanik. All rights reserved. * - * Released under the BSD license - see LICENSE in the root for more details. * - ****************************************************************************** - */ - -#include - -#include - -#include - - -namespace { - -typedef int (*user_main_t)(int argc, xechar_t** argv); - -bool _has_console = true; - -} // namespace - - -#if XE_LIKE_WIN32 && defined(UNICODE) && UNICODE - -#include -#include -#include -#include - -int xe_main_thunk( - int argc, wchar_t* argv[], - void* user_main, const char* usage) { - google::SetUsageMessage(std::string("usage: ") + usage); - google::SetVersionString("1.0"); - - int argca = argc; - char** argva = (char**)alloca(sizeof(char*) * argca); - for (int n = 0; n < argca; n++) { - size_t len = xestrlenw(argv[n]); - argva[n] = (char*)alloca(len + 1); - xestrnarrow(argva[n], len + 1, argv[n]); - } - - google::ParseCommandLineFlags(&argc, &argva, true); - - // Parse may have deleted flags - so widen again. - int argcw = argc; - wchar_t** argvw = (wchar_t**)alloca(sizeof(wchar_t*) * argca); - for (int n = 0; n < argc; n++) { - size_t len = xestrlena(argva[n]); - argvw[n] = (wchar_t*)alloca(sizeof(wchar_t) * (len + 1)); - xestrwiden(argvw[n], len + 1, argva[n]); - } - - int result = ((user_main_t)user_main)(argcw, (xechar_t**)argvw); - google::ShutDownCommandLineFlags(); - return result; -} - -bool xe_has_console() { - return _has_console; -} - -void xe_attach_console() { - bool has_console = AttachConsole(ATTACH_PARENT_PROCESS) == TRUE; - if (!has_console) { - // We weren't launched from a console, so just return. - // We could alloc our own console, but meh: - // has_console = AllocConsole() == TRUE; - _has_console = false; - return; - } - _has_console = true; - - auto std_handle = (intptr_t)GetStdHandle(STD_OUTPUT_HANDLE); - auto con_handle = _open_osfhandle(std_handle, _O_TEXT); - auto fp = _fdopen(con_handle, "w"); - *stdout = *fp; - setvbuf(stdout, NULL, _IONBF, 0); - - std_handle = (intptr_t)GetStdHandle(STD_ERROR_HANDLE); - con_handle = _open_osfhandle(std_handle, _O_TEXT); - fp = _fdopen(con_handle, "w"); - *stderr = *fp; - setvbuf(stderr, NULL, _IONBF, 0); -} - -int xe_main_window_thunk( - wchar_t* command_line, - void* user_main, const wchar_t* name, const char* usage) { - xe_attach_console(); - wchar_t buffer[2048]; - xestrcpy(buffer, XECOUNT(buffer), name); - xestrcat(buffer, XECOUNT(buffer), L" "); - xestrcat(buffer, XECOUNT(buffer), command_line); - int argc; - wchar_t** argv = CommandLineToArgvW(buffer, &argc); - if (!argv) { - return 1; - } - int result = xe_main_thunk(argc, argv, user_main, usage); - LocalFree(argv); - return result; -} - -#else - -bool xe_has_console() { - return _has_console; -} - -int xe_main_thunk( - int argc, char** argv, - void* user_main, const char* usage) { - google::SetUsageMessage(std::string("usage: ") + usage); - google::SetVersionString("1.0"); - google::ParseCommandLineFlags(&argc, &argv, true); - int result = ((user_main_t)user_main)(argc, argv); - google::ShutDownCommandLineFlags(); - return result; -} - -#endif // WIN32 diff --git a/src/xenia/platform.h b/src/xenia/platform.h deleted file mode 100644 index 060b992e5..000000000 --- a/src/xenia/platform.h +++ /dev/null @@ -1,44 +0,0 @@ -/** - ****************************************************************************** - * Xenia : Xbox 360 Emulator Research Project * - ****************************************************************************** - * Copyright 2013 Ben Vanik. All rights reserved. * - * Released under the BSD license - see LICENSE in the root for more details. * - ****************************************************************************** - */ - -#ifndef XENIA_PLATFORM_H_ -#define XENIA_PLATFORM_H_ - -#include - -bool xe_has_console(); -#if XE_LIKE_WIN32 && defined(UNICODE) && UNICODE -int xe_main_thunk( - int argc, wchar_t* argv[], - void* user_main, const char* usage); -#define XE_MAIN_THUNK(NAME, USAGE) \ - int wmain(int argc, wchar_t *argv[]) { \ - return xe_main_thunk(argc, argv, NAME, USAGE); \ - } -int xe_main_window_thunk( - wchar_t* command_line, - void* user_main, const wchar_t* name, const char* usage); -#define XE_MAIN_WINDOW_THUNK(NAME, APP_NAME, USAGE) \ - int APIENTRY wWinMain(HINSTANCE, HINSTANCE, LPTSTR command_line, int) { \ - return xe_main_window_thunk(command_line, NAME, APP_NAME, USAGE); \ - } -#else -int xe_main_thunk( - int argc, char** argv, - void* user_main, const char* usage); -#define XE_MAIN_THUNK(NAME, USAGE) \ - int main(int argc, char **argv) { \ - return xe_main_thunk(argc, argv, (void*)NAME, USAGE); \ - } -#define XE_MAIN_WINDOW_THUNK(NAME, APP_NAME, USAGE) \ - XE_MAIN_THUNK(NAME, USAGE) -#endif // WIN32 - - -#endif // XENIA_PLATFORM_H_ diff --git a/src/xenia/profiling.h b/src/xenia/profiling.h index 3747bbd9b..03ebdf720 100644 --- a/src/xenia/profiling.h +++ b/src/xenia/profiling.h @@ -13,7 +13,6 @@ #include #include -#include #include #include diff --git a/src/xenia/sources.gypi b/src/xenia/sources.gypi index 88a621e58..9eaf39280 100644 --- a/src/xenia/sources.gypi +++ b/src/xenia/sources.gypi @@ -14,8 +14,6 @@ 'logging.h', 'malloc.cc', 'malloc.h', - 'platform.cc', - 'platform.h', 'profiling.cc', 'profiling.h', 'string.h', diff --git a/src/xenia/string.h b/src/xenia/string.h index 0f6b9be2c..076fded47 100644 --- a/src/xenia/string.h +++ b/src/xenia/string.h @@ -10,7 +10,6 @@ #ifndef XENIA_STRING_H_ #define XENIA_STRING_H_ -#include #include // NOTE: these differing implementations should behave pretty much the same. @@ -23,39 +22,25 @@ int strncpy_s(char* dest, size_t destLength, const char* source, size_t count); #define _snprintf_s(dest, destLength, x, format, ...) snprintf(dest, destLength, format, ##__VA_ARGS__) #endif // !WIN32 -#define xestrlenw wcslen -#define xestrchrw wcschr #define xestrcpyw(dest, destLength, source) (wcscpy_s(dest, destLength, source) == 0) -#define xestrcatw(dest, destLength, source) (wcscat_s(dest, destLength, source) == 0) #define xesnprintfw(buffer, bufferCount, format, ...) _snwprintf_s(buffer, bufferCount, (bufferCount) ? (bufferCount - 1) : 0, format, ##__VA_ARGS__) #define xestrlena strlen -#define xestrchra strchr -#define xestrrchra strrchr #define xestrcpya(dest, destLength, source) (strcpy_s(dest, destLength, source) == 0) #define xestrncpya(dest, destLength, source, count) (strncpy_s(dest, destLength, source, count) == 0) -#define xestrcata(dest, destLength, source) (strcat_s(dest, destLength, source) == 0) #define xesnprintfa(buffer, bufferCount, format, ...) _snprintf_s(buffer, bufferCount, bufferCount, format, ##__VA_ARGS__) #define xevsnprintfa(buffer, bufferCount, format, args) vsnprintf(buffer, bufferCount, format, args) #if XE_PLATFORM_WIN32 && defined(UNICODE) && UNICODE typedef wchar_t xechar_t; -#define XE_WCHAR 1 -// xestrchr 2 uses in fs -// xestrrchra xmodule/logging // xestrcpy fs + module // xestrncpya one use in xbox.h -// xestrcat 2 uses in platform // xesnprintf many uses - only remove some? -// xevsnprintf logging, disasm #define xestrcpy xestrcpyw -#define xestrcat xestrcatw #define xesnprintf xesnprintfw -#define xestrnarrow(dest, destLength, source) (wcstombs_s(NULL, dest, destLength, source, _TRUNCATE) == 0) -#define xestrwiden(dest, destLength, source) (mbstowcs_s(NULL, dest, destLength, source, _TRUNCATE) == 0) #else @@ -63,10 +48,7 @@ typedef char xechar_t; #define XE_CHAR 1 #define xestrcpy xestrcpya -#define xestrcat xestrcata #define xesnprintf xesnprintfa -#define xestrnarrow(dest, destLength, source) xestrcpy(dest, destLength, source) -#define xestrwiden(dest, destLength, source) xestrcpy(dest, destLength, source) #endif // WIN32 diff --git a/src/xenia/types.h b/src/xenia/types.h index 59a07c8da..972cad6c7 100644 --- a/src/xenia/types.h +++ b/src/xenia/types.h @@ -13,7 +13,7 @@ #include #include -#include +#include #define XE_EMPTY_MACRO do { } while(0) diff --git a/tools/alloy-sandbox/alloy-sandbox.cc b/tools/alloy-sandbox/alloy-sandbox.cc index 162721ddb..508ede3c9 100644 --- a/tools/alloy-sandbox/alloy-sandbox.cc +++ b/tools/alloy-sandbox/alloy-sandbox.cc @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -75,7 +76,7 @@ class ThreadState : public alloy::runtime::ThreadState { // TODO(benvanik): simple memory? move more into core? -int main(int argc, xechar_t** argv) { +int main(std::vector& args) { xe::Profiler::Initialize(); xe::Profiler::ThreadEnter("main"); @@ -122,7 +123,4 @@ int main(int argc, xechar_t** argv) { } // namespace sandbox } // namespace alloy -// TODO(benvanik): move main thunk into poly -// ehhh -#include -XE_MAIN_THUNK(alloy::sandbox::main, "alloy-sandbox"); +DEFINE_ENTRY_POINT(L"alloy-sandbox", L"?", alloy::sandbox::main); diff --git a/tools/alloy-sandbox/alloy-sandbox.gypi b/tools/alloy-sandbox/alloy-sandbox.gypi index 4c824dce8..7988e708f 100644 --- a/tools/alloy-sandbox/alloy-sandbox.gypi +++ b/tools/alloy-sandbox/alloy-sandbox.gypi @@ -5,6 +5,12 @@ 'target_name': 'alloy-sandbox', 'type': 'executable', + 'msvs_settings': { + 'VCLinkerTool': { + 'SubSystem': '1' + }, + }, + 'dependencies': [ 'alloy', 'xenia', diff --git a/tools/xenia-compare/xenia-compare.cc b/tools/xenia-compare/xenia-compare.cc index 7fb6c9488..e5f338d48 100644 --- a/tools/xenia-compare/xenia-compare.cc +++ b/tools/xenia-compare/xenia-compare.cc @@ -10,6 +10,7 @@ #include #include +#include #include #include #include @@ -21,7 +22,7 @@ namespace xc { using xdb::PostmortemDebugTarget; -int main(int argc, xechar_t** argv) { +int main(std::vector& args) { // Create platform abstraction layer. xe_pal_options_t pal_options; xe_zero_struct(&pal_options, sizeof(pal_options)); @@ -46,6 +47,4 @@ int main(int argc, xechar_t** argv) { } // namespace xc -// TODO(benvanik): move main thunk into poly -// ehhh -XE_MAIN_WINDOW_THUNK(xc::main, L"xenia-compare", "xenia-compare"); +DEFINE_ENTRY_POINT(L"xenia-compare", L"xenia-compare", xc::main); diff --git a/tools/xenia-compare/xenia-compare.gypi b/tools/xenia-compare/xenia-compare.gypi index 2b43a2883..1a75f3f34 100644 --- a/tools/xenia-compare/xenia-compare.gypi +++ b/tools/xenia-compare/xenia-compare.gypi @@ -7,8 +7,8 @@ 'msvs_settings': { 'VCLinkerTool': { - 'SubSystem': '2' - } + 'SubSystem': '1' + }, }, 'dependencies': [ diff --git a/tools/xenia-debug/xenia-debug.cc b/tools/xenia-debug/xenia-debug.cc index 05f0bf846..f16e2401f 100644 --- a/tools/xenia-debug/xenia-debug.cc +++ b/tools/xenia-debug/xenia-debug.cc @@ -12,6 +12,7 @@ #include #include +#include #include #include #include @@ -22,7 +23,7 @@ DEFINE_string(content_file, "", namespace xdb { -int main(int argc, xechar_t** argv) { +int main(std::vector& args) { // Create platform abstraction layer. xe_pal_options_t pal_options; xe_zero_struct(&pal_options, sizeof(pal_options)); @@ -67,6 +68,4 @@ int main(int argc, xechar_t** argv) { } // namespace xdb -// TODO(benvanik): move main thunk into poly -// ehhh -XE_MAIN_WINDOW_THUNK(xdb::main, L"xenia-debug", "xenia-debug"); +DEFINE_ENTRY_POINT(L"xenia-debug", L"xenia-debug", xdb::main); diff --git a/tools/xenia-debug/xenia-debug.gypi b/tools/xenia-debug/xenia-debug.gypi index 14ef1c990..412439497 100644 --- a/tools/xenia-debug/xenia-debug.gypi +++ b/tools/xenia-debug/xenia-debug.gypi @@ -8,7 +8,7 @@ 'msvs_settings': { 'VCLinkerTool': { 'SubSystem': '2' - } + }, }, 'dependencies': [ diff --git a/tools/xenia-run/xenia-run.cc b/tools/xenia-run/xenia-run.cc index fed8c3ae7..51a6dcb3f 100644 --- a/tools/xenia-run/xenia-run.cc +++ b/tools/xenia-run/xenia-run.cc @@ -10,16 +10,13 @@ #include #include - +#include using namespace xe; +DEFINE_string(target, "", "Specifies the target .xex or .iso to execute."); -DEFINE_string(target, "", - "Specifies the target .xex or .iso to execute."); - - -int xenia_run(int argc, xechar_t** argv) { +int xenia_run(std::vector& args) { int result_code = 1; Profiler::Initialize(); @@ -28,33 +25,28 @@ int xenia_run(int argc, xechar_t** argv) { Emulator* emulator = NULL; // Grab path from the flag or unnamed argument. - if (!FLAGS_target.size() && argc < 2) { + if (!FLAGS_target.size() && args.size() < 2) { google::ShowUsageWithFlags("xenia-run"); XEFATAL("Pass a file to launch."); return 1; } - const xechar_t* path = NULL; + std::wstring path; if (FLAGS_target.size()) { // Passed as a named argument. // TODO(benvanik): find something better than gflags that supports unicode. - xechar_t buffer[poly::max_path]; - XEIGNORE(xestrwiden(buffer, sizeof(buffer), FLAGS_target.c_str())); - path = buffer; + path = poly::to_wstring(FLAGS_target); } else { // Passed as an unnamed argument. - path = argv[1]; + path = args[1]; } + // Normalize the path and make absolute. + std::wstring abs_path = poly::to_absolute_path(path); // Create platform abstraction layer. xe_pal_options_t pal_options; xe_zero_struct(&pal_options, sizeof(pal_options)); XEEXPECTZERO(xe_pal_init(pal_options)); - // Normalize the path and make absolute. - // TODO(benvanik): move this someplace common. - xechar_t abs_path[poly::max_path]; - xe_path_get_absolute(path, abs_path, XECOUNT(abs_path)); - // Create the emulator. emulator = new Emulator(L""); XEEXPECTNOTNULL(emulator); @@ -93,4 +85,5 @@ XECLEANUP: Profiler::Shutdown(); return result_code; } -XE_MAIN_WINDOW_THUNK(xenia_run, L"xenia-run", "xenia-run some.xex"); + +DEFINE_ENTRY_POINT(L"xenia-run", L"xenia-run some.xex", xenia_run); diff --git a/tools/xenia-run/xenia-run.gypi b/tools/xenia-run/xenia-run.gypi index 150cb062f..2d2702ac7 100644 --- a/tools/xenia-run/xenia-run.gypi +++ b/tools/xenia-run/xenia-run.gypi @@ -8,7 +8,7 @@ 'msvs_settings': { 'VCLinkerTool': { 'SubSystem': '2' - } + }, }, 'dependencies': [ diff --git a/tools/xenia-test/xenia-test.cc b/tools/xenia-test/xenia-test.cc index 302b68384..955cc2eda 100644 --- a/tools/xenia-test/xenia-test.cc +++ b/tools/xenia-test/xenia-test.cc @@ -14,6 +14,8 @@ #endif // !WIN32 #include +#include + using namespace std; using namespace xe; @@ -273,7 +275,7 @@ int xenia_test(int argc, xechar_t **argv) { if (argc >= 2) { test_name = argv[1]; } - + string test_name_str; if (test_name) { #if XE_WCHAR @@ -290,4 +292,5 @@ int xenia_test(int argc, xechar_t **argv) { return result_code; } -XE_MAIN_THUNK(xenia_test, "xenia-test some.xex"); + +DEFINE_ENTRY_POINT(L"xenia-test", L"xenia-test some.xex", xenia_test); diff --git a/tools/xenia-test/xenia-test.gypi b/tools/xenia-test/xenia-test.gypi index c682fbc74..60ae68dff 100644 --- a/tools/xenia-test/xenia-test.gypi +++ b/tools/xenia-test/xenia-test.gypi @@ -5,6 +5,12 @@ 'target_name': 'xenia-test', 'type': 'executable', + 'msvs_settings': { + 'VCLinkerTool': { + 'SubSystem': '1', + }, + }, + 'dependencies': [ 'xenia', ], diff --git a/xenia.gyp b/xenia.gyp index 736900825..e98acf017 100644 --- a/xenia.gyp +++ b/xenia.gyp @@ -98,6 +98,7 @@ 'AdditionalLibraryDirectories': [ '..\\..\\third_party\\wxWidgets\\lib\\vc_x64_lib\\', ], + 'EntryPointSymbol': 'wWinMainCRTStartup', }, },