More string swapping and cleaning up main().

This commit is contained in:
Ben Vanik 2014-08-16 16:34:04 -07:00
parent 18ee972b47
commit 7c5fa88661
41 changed files with 326 additions and 413 deletions

View File

@ -14,7 +14,6 @@
#include <xenia/config.h>
#include <xenia/logging.h>
#include <xenia/malloc.h>
#include <xenia/platform.h>
#include <xenia/profiling.h>
#include <xenia/string.h>
#include <xenia/types.h>

37
src/poly/main.h Normal file
View File

@ -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 <string>
#include <vector>
#include <poly/platform.h>
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<std::wstring>& 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_

41
src/poly/main_posix.cc Normal file
View File

@ -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 <poly/main.h>
#include <poly/string.h>
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<std::wstring> 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;
}

105
src/poly/main_win.cc Normal file
View File

@ -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 <poly/main.h>
#include <fcntl.h>
#include <io.h>
#include <shellapi.h>
#include <gflags/gflags.h>
#include <poly/string.h>
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<std::wstring> 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;
}

View File

@ -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 <gflags/gflags.h>
#endif // POLY_POLY_PRIVATE_H_

View File

@ -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 <poly/poly.h>
#include <poly/poly-private.h>
namespace poly {} // namespace poly

View File

@ -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',
],
}],

View File

@ -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

View File

@ -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_

View File

@ -18,7 +18,6 @@
#include <xenia/config.h>
#include <xenia/logging.h>
#include <xenia/malloc.h>
#include <xenia/platform.h>
#include <xenia/profiling.h>
#include <xenia/string.h>
#include <xenia/types.h>

View File

@ -20,7 +20,6 @@ namespace xe {
#include <xenia/core/hash.h>
#include <xenia/core/mmap.h>
#include <xenia/core/pal.h>
#include <xenia/core/path.h>
#include <xenia/core/ref.h>
#include <xenia/core/run_loop.h>
#include <xenia/core/socket.h>

View File

@ -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 <xenia/core/path.h>
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
}

View File

@ -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 <xenia/common.h>
#include <xenia/core/pal.h>
#include <xenia/core/ref.h>
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_

View File

@ -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 <xenia/core/path.h>
const xechar_t* xe_path_get_tmp(const xechar_t* prefix) {
//
assert_always();
}

View File

@ -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 <xenia/core/path.h>
const xechar_t* xe_path_get_tmp(const xechar_t* prefix) {
//
assert_always();
return NULL;
}

View File

@ -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',
],

View File

@ -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));

View File

@ -9,7 +9,6 @@
#include <xenia/kernel/fs/devices/host_path_device.h>
#include <xenia/core/path.h>
#include <xenia/kernel/fs/devices/host_path_entry.h>
#include <xenia/kernel/objects/xfile.h>
@ -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

View File

@ -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));

View File

@ -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);
}
}

View File

@ -10,6 +10,8 @@
#ifndef XENIA_KERNEL_XBOXKRNL_XMODULE_H_
#define XENIA_KERNEL_XBOXKRNL_XMODULE_H_
#include <string>
#include <xenia/kernel/xobject.h>
#include <xenia/xbox.h>
@ -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_;
};

View File

@ -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"<null>");
auto source =
source_ptr ? poly::load_and_swap<std::wstring>(SHIM_MEM_ADDR(source_ptr))
: L"";
XELOGD("RtlInitUnicodeString(%.8X, %.8X = %ls)", destination_ptr, source_ptr,
source.empty() ? L"<null>" : 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);

View File

@ -11,10 +11,9 @@
#include <mutex>
#include <xenia/common.h>
#include <gflags/gflags.h>
#include <poly/main.h>
#include <xenia/common.h>
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);
}

View File

@ -12,7 +12,6 @@
#include <cstdint>
#include <xenia/platform.h>
#include <xenia/config.h>
#include <xenia/string.h>

View File

@ -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 <xenia/platform.h>
#include <gflags/gflags.h>
#include <xenia/common.h>
namespace {
typedef int (*user_main_t)(int argc, xechar_t** argv);
bool _has_console = true;
} // namespace
#if XE_LIKE_WIN32 && defined(UNICODE) && UNICODE
#include <windows.h>
#include <fcntl.h>
#include <io.h>
#include <shellapi.h>
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

View File

@ -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 <poly/platform.h>
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_

View File

@ -13,7 +13,6 @@
#include <memory>
#include <xenia/config.h>
#include <xenia/platform.h>
#include <xenia/string.h>
#include <xenia/types.h>

View File

@ -14,8 +14,6 @@
'logging.h',
'malloc.cc',
'malloc.h',
'platform.cc',
'platform.h',
'profiling.cc',
'profiling.h',
'string.h',

View File

@ -10,7 +10,6 @@
#ifndef XENIA_STRING_H_
#define XENIA_STRING_H_
#include <xenia/platform.h>
#include <poly/string.h>
// 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

View File

@ -13,7 +13,7 @@
#include <cstdint>
#include <functional>
#include <xenia/platform.h>
#include <poly/platform.h>
#define XE_EMPTY_MACRO do { } while(0)

View File

@ -13,6 +13,7 @@
#include <alloy/frontend/ppc/ppc_context.h>
#include <alloy/frontend/ppc/ppc_frontend.h>
#include <alloy/runtime/raw_module.h>
#include <poly/main.h>
#include <poly/poly.h>
#include <xenia/cpu/xenon_memory.h>
@ -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<std::wstring>& 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 <xenia/platform.cc>
XE_MAIN_THUNK(alloy::sandbox::main, "alloy-sandbox");
DEFINE_ENTRY_POINT(L"alloy-sandbox", L"?", alloy::sandbox::main);

View File

@ -5,6 +5,12 @@
'target_name': 'alloy-sandbox',
'type': 'executable',
'msvs_settings': {
'VCLinkerTool': {
'SubSystem': '1'
},
},
'dependencies': [
'alloy',
'xenia',

View File

@ -10,6 +10,7 @@
#include <memory>
#include <gflags/gflags.h>
#include <poly/main.h>
#include <poly/poly.h>
#include <xdb/postmortem_debug_target.h>
#include <xdb/xdb.h>
@ -21,7 +22,7 @@ namespace xc {
using xdb::PostmortemDebugTarget;
int main(int argc, xechar_t** argv) {
int main(std::vector<std::wstring>& 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);

View File

@ -7,8 +7,8 @@
'msvs_settings': {
'VCLinkerTool': {
'SubSystem': '2'
}
'SubSystem': '1'
},
},
'dependencies': [

View File

@ -12,6 +12,7 @@
#include <memory>
#include <gflags/gflags.h>
#include <poly/main.h>
#include <poly/poly.h>
#include <third_party/wxWidgets/include/wx/wx.h>
#include <xdb/ui/xdb_app.h>
@ -22,7 +23,7 @@ DEFINE_string(content_file, "",
namespace xdb {
int main(int argc, xechar_t** argv) {
int main(std::vector<std::wstring>& 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);

View File

@ -8,7 +8,7 @@
'msvs_settings': {
'VCLinkerTool': {
'SubSystem': '2'
}
},
},
'dependencies': [

View File

@ -10,16 +10,13 @@
#include <xenia/xenia.h>
#include <gflags/gflags.h>
#include <poly/main.h>
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<std::wstring>& 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);

View File

@ -8,7 +8,7 @@
'msvs_settings': {
'VCLinkerTool': {
'SubSystem': '2'
}
},
},
'dependencies': [

View File

@ -14,6 +14,8 @@
#endif // !WIN32
#include <gflags/gflags.h>
#include <poly/main.h>
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);

View File

@ -5,6 +5,12 @@
'target_name': 'xenia-test',
'type': 'executable',
'msvs_settings': {
'VCLinkerTool': {
'SubSystem': '1',
},
},
'dependencies': [
'xenia',
],

View File

@ -98,6 +98,7 @@
'AdditionalLibraryDirectories': [
'..\\..\\third_party\\wxWidgets\\lib\\vc_x64_lib\\',
],
'EntryPointSymbol': 'wWinMainCRTStartup',
},
},