Added callback when new module is launched

This avoids having to guess the display window title format
Also manually fixed the linting errors picked out by travis which do not
get picked up using xb format locally
This commit is contained in:
x1nixmzeng 2016-01-09 17:36:46 +00:00
parent 5fa9499a12
commit 6530b9dc49
11 changed files with 56 additions and 53 deletions

View File

@ -35,11 +35,12 @@ class EmulatorWindow {
ui::Loop* loop() const { return loop_.get(); } ui::Loop* loop() const { return loop_.get(); }
ui::Window* window() const { return window_.get(); } ui::Window* window() const { return window_.get(); }
void UpdateTitle();
private: private:
explicit EmulatorWindow(Emulator* emulator); explicit EmulatorWindow(Emulator* emulator);
bool Initialize(); bool Initialize();
void UpdateTitle();
void CpuTimeScalarReset(); void CpuTimeScalarReset();
void CpuTimeScalarSetHalf(); void CpuTimeScalarSetHalf();

View File

@ -195,7 +195,8 @@ int xenia_main(const std::vector<std::wstring>& args) {
// Normalize the path and make absolute. // Normalize the path and make absolute.
std::wstring abs_path = xe::to_absolute_path(path); std::wstring abs_path = xe::to_absolute_path(path);
result = emulator->LaunchPath(abs_path); result = emulator->LaunchPath(abs_path,
[&]() { emulator_window->UpdateTitle(); });
if (XFAILED(result)) { if (XFAILED(result)) {
XELOGE("Failed to launch target: %.8X", result); XELOGE("Failed to launch target: %.8X", result);
emulator.reset(); emulator.reset();

View File

@ -465,8 +465,8 @@ bool XexModule::SetupLibraryImports(const char* name,
GuestFunction::ExternHandler handler = nullptr; GuestFunction::ExternHandler handler = nullptr;
if (kernel_export) { if (kernel_export) {
if (kernel_export->function_data.trampoline) { if (kernel_export->function_data.trampoline) {
handler = (GuestFunction::ExternHandler)kernel_export handler = (GuestFunction::ExternHandler)
->function_data.trampoline; kernel_export->function_data.trampoline;
} else { } else {
handler = handler =
(GuestFunction::ExternHandler)kernel_export->function_data.shim; (GuestFunction::ExternHandler)kernel_export->function_data.shim;

View File

@ -192,7 +192,8 @@ X_STATUS Emulator::Setup(
return result; return result;
} }
X_STATUS Emulator::LaunchPath(std::wstring path) { X_STATUS Emulator::LaunchPath(std::wstring path,
std::function<void()> on_launch) {
// Launch based on file type. // Launch based on file type.
// This is a silly guess based on file extension. // This is a silly guess based on file extension.
auto last_slash = path.find_last_of(xe::kPathSeparator); auto last_slash = path.find_last_of(xe::kPathSeparator);
@ -202,18 +203,19 @@ X_STATUS Emulator::LaunchPath(std::wstring path) {
} }
if (last_dot == std::wstring::npos) { if (last_dot == std::wstring::npos) {
// Likely an STFS container. // Likely an STFS container.
return LaunchStfsContainer(path); return LaunchStfsContainer(path, on_launch);
} else if (path.substr(last_dot) == L".xex" || } else if (path.substr(last_dot) == L".xex" ||
path.substr(last_dot) == L".elf") { path.substr(last_dot) == L".elf") {
// Treat as a naked xex file. // Treat as a naked xex file.
return LaunchXexFile(path); return LaunchXexFile(path, on_launch);
} else { } else {
// Assume a disc image. // Assume a disc image.
return LaunchDiscImage(path); return LaunchDiscImage(path, on_launch);
} }
} }
X_STATUS Emulator::LaunchXexFile(std::wstring path) { X_STATUS Emulator::LaunchXexFile(std::wstring path,
std::function<void()> on_launch) {
// We create a virtual filesystem pointing to its directory and symlink // We create a virtual filesystem pointing to its directory and symlink
// that to the game filesystem. // that to the game filesystem.
// e.g., /my/files/foo.xex will get a local fs at: // e.g., /my/files/foo.xex will get a local fs at:
@ -245,10 +247,11 @@ X_STATUS Emulator::LaunchXexFile(std::wstring path) {
// Launch the game. // Launch the game.
std::string fs_path = "game:\\" + xe::to_string(file_name); std::string fs_path = "game:\\" + xe::to_string(file_name);
return CompleteLaunch(path, fs_path); return CompleteLaunch(path, fs_path, on_launch);
} }
X_STATUS Emulator::LaunchDiscImage(std::wstring path) { X_STATUS Emulator::LaunchDiscImage(std::wstring path,
std::function<void()> on_launch) {
auto mount_path = "\\Device\\Cdrom0"; auto mount_path = "\\Device\\Cdrom0";
// Register the disc image in the virtual filesystem. // Register the disc image in the virtual filesystem.
@ -267,10 +270,11 @@ X_STATUS Emulator::LaunchDiscImage(std::wstring path) {
file_system_->RegisterSymbolicLink("d:", mount_path); file_system_->RegisterSymbolicLink("d:", mount_path);
// Launch the game. // Launch the game.
return CompleteLaunch(path, "game:\\default.xex"); return CompleteLaunch(path, "game:\\default.xex", on_launch);
} }
X_STATUS Emulator::LaunchStfsContainer(std::wstring path) { X_STATUS Emulator::LaunchStfsContainer(std::wstring path,
std::function<void()> on_launch) {
auto mount_path = "\\Device\\Cdrom0"; auto mount_path = "\\Device\\Cdrom0";
// Register the container in the virtual filesystem. // Register the container in the virtual filesystem.
@ -289,7 +293,7 @@ X_STATUS Emulator::LaunchStfsContainer(std::wstring path) {
file_system_->RegisterSymbolicLink("d:", mount_path); file_system_->RegisterSymbolicLink("d:", mount_path);
// Launch the game. // Launch the game.
return CompleteLaunch(path, "game:\\default.xex"); return CompleteLaunch(path, "game:\\default.xex", on_launch);
} }
void Emulator::Pause() { void Emulator::Pause() {
@ -494,8 +498,9 @@ void Emulator::WaitUntilExit() {
} }
} }
X_STATUS Emulator::CompleteLaunch(const std::wstring& path, X_STATUS Emulator::CompleteLaunch(const std::wstring &path,
const std::string& module_path) { const std::string &module_path,
std::function<void()> on_launch) {
// Allow xam to request module loads. // Allow xam to request module loads.
auto xam = kernel_state()->GetKernelModule<kernel::xam::XamModule>("xam.xex"); auto xam = kernel_state()->GetKernelModule<kernel::xam::XamModule>("xam.xex");
@ -510,10 +515,6 @@ X_STATUS Emulator::CompleteLaunch(const std::wstring& path,
} }
kernel_state_->SetExecutableModule(module); kernel_state_->SetExecutableModule(module);
auto main_xthread = module->Launch();
if (!main_xthread) {
return X_STATUS_UNSUCCESSFUL;
}
// Try and load the resource database (xex only) // Try and load the resource database (xex only)
char title[9] = {0}; char title[9] = {0};
@ -526,15 +527,7 @@ X_STATUS Emulator::CompleteLaunch(const std::wstring& path,
if (xdb_ptr != nullptr) { if (xdb_ptr != nullptr) {
xe::xdbf::XdbfWrapper db; xe::xdbf::XdbfWrapper db;
if (db.initialize(xdb_ptr, static_cast<size_t>(resource_size))) { if (db.initialize(xdb_ptr, static_cast<size_t>(resource_size))) {
game_title_ = xe::to_wstring(xe::xdbf::get_title(db));
std::string game_title(xe::xdbf::get_title(db));
if (!game_title.empty()) {
game_title_ = xe::to_wstring(game_title);
// TODO(x1nixmzeng): Need to somehow callback to
// EmulatorWindow::UpdateTitle
display_window_->set_title(game_title_ + L" - " +
display_window_->title());
}
xe::xdbf::XdbfBlock icon_block = xe::xdbf::get_icon(db); xe::xdbf::XdbfBlock icon_block = xe::xdbf::get_icon(db);
if (icon_block.buffer != nullptr) { if (icon_block.buffer != nullptr) {
display_window_->SetIconFromBuffer(icon_block.buffer, display_window_->SetIconFromBuffer(icon_block.buffer,
@ -544,6 +537,12 @@ X_STATUS Emulator::CompleteLaunch(const std::wstring& path,
} }
} }
auto main_xthread = module->Launch();
if (!main_xthread) {
return X_STATUS_UNSUCCESSFUL;
}
on_launch();
main_thread_ = main_xthread->thread(); main_thread_ = main_xthread->thread();
WaitUntilExit(); WaitUntilExit();

View File

@ -54,7 +54,7 @@ class Emulator {
const std::wstring& command_line() const { return command_line_; } const std::wstring& command_line() const { return command_line_; }
// Title of the game in the default language. // Title of the game in the default language.
const std::wstring &game_title() const { return game_title_; } const std::wstring& game_title() const { return game_title_; }
// Window used for displaying graphical output. // Window used for displaying graphical output.
ui::Window* display_window() const { return display_window_; } ui::Window* display_window() const { return display_window_; }
@ -109,17 +109,18 @@ class Emulator {
// Launches a game from the given file path. // Launches a game from the given file path.
// This will attempt to infer the type of the given file (such as an iso, etc) // This will attempt to infer the type of the given file (such as an iso, etc)
// using heuristics. // using heuristics.
X_STATUS LaunchPath(std::wstring path); X_STATUS LaunchPath(std::wstring path, std::function<void()> on_launch);
// Launches a game from a .xex file by mounting the containing folder as if it // Launches a game from a .xex file by mounting the containing folder as if it
// was an extracted STFS container. // was an extracted STFS container.
X_STATUS LaunchXexFile(std::wstring path); X_STATUS LaunchXexFile(std::wstring path, std::function<void()> on_launch);
// Launches a game from a disc image file (.iso, etc). // Launches a game from a disc image file (.iso, etc).
X_STATUS LaunchDiscImage(std::wstring path); X_STATUS LaunchDiscImage(std::wstring path, std::function<void()> on_launch);
// Launches a game from an STFS container file. // Launches a game from an STFS container file.
X_STATUS LaunchStfsContainer(std::wstring path); X_STATUS LaunchStfsContainer(std::wstring path,
std::function<void()> on_launch);
void Pause(); void Pause();
void Resume(); void Resume();
@ -134,8 +135,9 @@ class Emulator {
static bool ExceptionCallbackThunk(Exception* ex, void* data); static bool ExceptionCallbackThunk(Exception* ex, void* data);
bool ExceptionCallback(Exception* ex); bool ExceptionCallback(Exception* ex);
X_STATUS CompleteLaunch(const std::wstring& path, X_STATUS CompleteLaunch(const std::wstring &path,
const std::string& module_path); const std::string &module_path,
std::function<void()> on_launch);
std::wstring command_line_; std::wstring command_line_;
std::wstring game_title_; std::wstring game_title_;

View File

@ -105,8 +105,8 @@ uint32_t KernelModule::GetProcAddressByOrdinal(uint16_t ordinal) {
cpu::GuestFunction::ExternHandler handler = nullptr; cpu::GuestFunction::ExternHandler handler = nullptr;
if (export_entry->function_data.trampoline) { if (export_entry->function_data.trampoline) {
handler = (cpu::GuestFunction::ExternHandler)export_entry handler = (cpu::GuestFunction::ExternHandler)
->function_data.trampoline; export_entry->function_data.trampoline;
} else { } else {
handler = handler =
(cpu::GuestFunction::ExternHandler)export_entry->function_data.shim; (cpu::GuestFunction::ExternHandler)export_entry->function_data.shim;

View File

@ -53,7 +53,7 @@ class Window {
return true; return true;
} }
virtual bool SetIconFromBuffer(void *buffer, size_t size) = 0; virtual bool SetIconFromBuffer(void* buffer, size_t size) = 0;
virtual bool is_fullscreen() const { return false; } virtual bool is_fullscreen() const { return false; }
virtual void ToggleFullscreen(bool fullscreen) {} virtual void ToggleFullscreen(bool fullscreen) {}

View File

@ -167,7 +167,7 @@ bool Win32Window::set_title(const std::wstring& title) {
return true; return true;
} }
bool Win32Window::SetIconFromBuffer(void *buffer, size_t size) { bool Win32Window::SetIconFromBuffer(void* buffer, size_t size) {
if (icon_ != nullptr) { if (icon_ != nullptr) {
DestroyIcon(icon_); DestroyIcon(icon_);
} }

View File

@ -31,7 +31,7 @@ class Win32Window : public Window {
HWND hwnd() const { return hwnd_; } HWND hwnd() const { return hwnd_; }
bool set_title(const std::wstring& title) override; bool set_title(const std::wstring& title) override;
bool SetIconFromBuffer(void *buffer, size_t size) override; bool SetIconFromBuffer(void* buffer, size_t size) override;
bool is_fullscreen() const override; bool is_fullscreen() const override;
void ToggleFullscreen(bool fullscreen) override; void ToggleFullscreen(bool fullscreen) override;

View File

@ -84,14 +84,14 @@ XdbfBlock XdbfWrapper::get_entry(XdbfSection section, uint64_t id) const {
return block; return block;
} }
XdbfBlock get_icon(const XdbfWrapper &ref) { XdbfBlock get_icon(const XdbfWrapper& ref) {
return ref.get_entry(kSectionImage, kIdTitle); return ref.get_entry(kSectionImage, kIdTitle);
} }
XdbfLocale get_default_language(const XdbfWrapper &ref) { XdbfLocale get_default_language(const XdbfWrapper& ref) {
XdbfBlock block = ref.get_entry(kSectionMetadata, kIdXSTC); XdbfBlock block = ref.get_entry(kSectionMetadata, kIdXSTC);
if (block.buffer != nullptr) { if (block.buffer != nullptr) {
XDBF_XSTC *xstc = reinterpret_cast<XDBF_XSTC *>(block.buffer); XDBF_XSTC* xstc = reinterpret_cast<XDBF_XSTC*>(block.buffer);
assert_true(xstc->magic == kMagicXSTC); assert_true(xstc->magic == kMagicXSTC);
uint32_t default_language = xstc->default_language; uint32_t default_language = xstc->default_language;
@ -101,7 +101,7 @@ XdbfLocale get_default_language(const XdbfWrapper &ref) {
return kLocaleEnglish; return kLocaleEnglish;
} }
std::string get_title(const XdbfWrapper &ref) { std::string get_title(const XdbfWrapper& ref) {
std::string title_str; std::string title_str;
uint64_t language_id = static_cast<uint64_t>(get_default_language(ref)); uint64_t language_id = static_cast<uint64_t>(get_default_language(ref));
@ -109,19 +109,19 @@ std::string get_title(const XdbfWrapper &ref) {
XdbfBlock lang_block = ref.get_entry(kSectionStringTable, language_id); XdbfBlock lang_block = ref.get_entry(kSectionStringTable, language_id);
if (lang_block.buffer != nullptr) { if (lang_block.buffer != nullptr) {
XDBF_XSTR_HEADER *xstr_head = XDBF_XSTR_HEADER* xstr_head =
reinterpret_cast<XDBF_XSTR_HEADER *>(lang_block.buffer); reinterpret_cast<XDBF_XSTR_HEADER*>(lang_block.buffer);
assert_true(xstr_head->magic == kMagicXSTR); assert_true(xstr_head->magic == kMagicXSTR);
assert_true(xstr_head->version == 1); assert_true(xstr_head->version == 1);
uint16_t str_count = xstr_head->string_count; uint16_t str_count = xstr_head->string_count;
uint8_t *currentAddress = lang_block.buffer + sizeof(XDBF_XSTR_HEADER); uint8_t* currentAddress = lang_block.buffer + sizeof(XDBF_XSTR_HEADER);
uint16_t s = 0; uint16_t s = 0;
while (s < str_count && title_str.empty()) { while (s < str_count && title_str.empty()) {
XDBF_STRINGTABLE_ENTRY *entry = XDBF_STRINGTABLE_ENTRY* entry =
reinterpret_cast<XDBF_STRINGTABLE_ENTRY *>(currentAddress); reinterpret_cast<XDBF_STRINGTABLE_ENTRY*>(currentAddress);
currentAddress += sizeof(XDBF_STRINGTABLE_ENTRY); currentAddress += sizeof(XDBF_STRINGTABLE_ENTRY);
uint16_t len = entry->string_length; uint16_t len = entry->string_length;

View File

@ -119,9 +119,9 @@ class XdbfWrapper {
XdbfState state_; XdbfState state_;
}; };
XdbfBlock get_icon(const XdbfWrapper &ref); XdbfBlock get_icon(const XdbfWrapper& ref);
XdbfLocale get_default_language(const XdbfWrapper &ref); XdbfLocale get_default_language(const XdbfWrapper& ref);
std::string get_title(const XdbfWrapper &ref); std::string get_title(const XdbfWrapper& ref);
} // namespace xdbf } // namespace xdbf
} // namespace xe } // namespace xe