Merge branch 'master' into d3d12

This commit is contained in:
gibbed 2019-05-01 21:00:21 -05:00
commit fac37e7c50
18 changed files with 290 additions and 108 deletions

View File

@ -41,7 +41,7 @@ legally purchased devices and games and information made public on the internet
## Quickstart ## Quickstart
Windows 8.1+ with Python 3.4 and [Visual Studio 2017](https://www.visualstudio.com/downloads/) and the Windows SDKs installed: With Windows 8+, Python 3.4+, and [Visual Studio 2017 or 2019](https://www.visualstudio.com/downloads/) and the Windows SDKs installed:
> git clone https://github.com/xenia-project/xenia.git > git clone https://github.com/xenia-project/xenia.git
> cd xenia > cd xenia
@ -82,7 +82,7 @@ is wide open greenfield fun.
Fixes and optimizations are always welcome (please!), but in addition to Fixes and optimizations are always welcome (please!), but in addition to
that there are some major work areas still untouched: that there are some major work areas still untouched:
* Help work through missing functionality/bugs in game [compat](https://github.com/xenia-project/xenia/issues?labels=compat) * Help work through [missing functionality/bugs in games](https://github.com/xenia-project/xenia/labels/compat)
* Add input drivers for [PS4 controllers](https://github.com/xenia-project/xenia/issues/60) (or anything else) * Add input drivers for [PS4 controllers](https://github.com/xenia-project/xenia/issues/60) (or anything else)
* Skilled with Linux? A strong contributor is needed to [help with porting](https://github.com/xenia-project/xenia/labels/cross%20platform) * Skilled with Linux? A strong contributor is needed to [help with porting](https://github.com/xenia-project/xenia/labels/cross%20platform)

View File

@ -9,10 +9,9 @@ video drivers for your card.
### Windows ### Windows
* Windows 8 or later * Windows 8 or later
* Visual Studio 2017 * [Visual Studio 2017 or Visual Studio 2019](https://www.visualstudio.com/downloads/)
* Windows Universal CRT SDK
* [Python 3.4+](https://www.python.org/downloads/) * [Python 3.4+](https://www.python.org/downloads/)
* You will also need the [Windows 8.1 SDK](https://msdn.microsoft.com/en-us/windows/desktop/bg162891) * You may also need the [Windows 8.1 SDK](https://msdn.microsoft.com/en-us/windows/desktop/bg162891)
* (for VS2017 just click the Windows 8.1 SDK option in the Individual Components section in the Visual Studio Installer) * (for VS2017 just click the Windows 8.1 SDK option in the Individual Components section in the Visual Studio Installer)
Ensure Python is in your PATH. Ensure Python is in your PATH.

View File

@ -176,11 +176,16 @@ bool EmulatorWindow::Initialize() {
auto file_menu = MenuItem::Create(MenuItem::Type::kPopup, L"&File"); auto file_menu = MenuItem::Create(MenuItem::Type::kPopup, L"&File");
{ {
file_menu->AddChild( file_menu->AddChild(
MenuItem::Create(MenuItem::Type::kString, L"&Open", L"Ctrl+O", MenuItem::Create(MenuItem::Type::kString, L"&Open...", L"Ctrl+O",
std::bind(&EmulatorWindow::FileOpen, this))); std::bind(&EmulatorWindow::FileOpen, this)));
file_menu->AddChild( file_menu->AddChild(
MenuItem::Create(MenuItem::Type::kString, L"Close", MenuItem::Create(MenuItem::Type::kString, L"Close",
std::bind(&EmulatorWindow::FileClose, this))); std::bind(&EmulatorWindow::FileClose, this)));
file_menu->AddChild(MenuItem::Create(MenuItem::Type::kSeparator));
file_menu->AddChild(MenuItem::Create(
MenuItem::Type::kString, L"Show content directory...",
std::bind(&EmulatorWindow::ShowContentDirectory, this)));
file_menu->AddChild(MenuItem::Create(MenuItem::Type::kSeparator));
file_menu->AddChild(MenuItem::Create(MenuItem::Type::kString, L"E&xit", file_menu->AddChild(MenuItem::Create(MenuItem::Type::kString, L"E&xit",
L"Alt+F4", L"Alt+F4",
[this]() { window_->Close(); })); [this]() { window_->Close(); }));
@ -251,16 +256,17 @@ bool EmulatorWindow::Initialize() {
{ {
help_menu->AddChild(MenuItem::Create( help_menu->AddChild(MenuItem::Create(
MenuItem::Type::kString, L"Build commit on GitHub...", [this]() { MenuItem::Type::kString, L"Build commit on GitHub...", [this]() {
std::string url = std::wstring url =
std::string("https://github.com/benvanik/xenia/tree/") + std::wstring(L"https://github.com/xenia-project/xenia/tree/") +
XE_BUILD_COMMIT + "/"; xe::to_wstring(XE_BUILD_COMMIT) + L"/";
LaunchBrowser(url.c_str()); LaunchBrowser(url.c_str());
})); }));
help_menu->AddChild(MenuItem::Create( help_menu->AddChild(MenuItem::Create(
MenuItem::Type::kString, L"Recent changes on GitHub...", [this]() { MenuItem::Type::kString, L"Recent changes on GitHub...", [this]() {
std::string url = std::wstring url =
std::string("https://github.com/benvanik/xenia/compare/") + std::wstring(L"https://github.com/xenia-project/xenia/compare/") +
XE_BUILD_COMMIT + "..." + XE_BUILD_BRANCH; xe::to_wstring(XE_BUILD_COMMIT) + L"..." +
xe::to_wstring(XE_BUILD_BRANCH);
LaunchBrowser(url.c_str()); LaunchBrowser(url.c_str());
})); }));
help_menu->AddChild(MenuItem::Create(MenuItem::Type::kSeparator)); help_menu->AddChild(MenuItem::Create(MenuItem::Type::kSeparator));
@ -269,7 +275,7 @@ bool EmulatorWindow::Initialize() {
std::bind(&EmulatorWindow::ShowHelpWebsite, this))); std::bind(&EmulatorWindow::ShowHelpWebsite, this)));
help_menu->AddChild(MenuItem::Create( help_menu->AddChild(MenuItem::Create(
MenuItem::Type::kString, L"&About...", MenuItem::Type::kString, L"&About...",
[this]() { LaunchBrowser("https://xenia.jp/about/"); })); [this]() { LaunchBrowser(L"https://xenia.jp/about/"); }));
} }
main_menu->AddChild(std::move(help_menu)); main_menu->AddChild(std::move(help_menu));
@ -331,6 +337,27 @@ void EmulatorWindow::FileClose() {
} }
} }
void EmulatorWindow::ShowContentDirectory() {
std::wstring target_path;
auto content_root = emulator_->content_root();
if (!emulator_->is_title_open() || !emulator_->kernel_state()) {
target_path = content_root;
} else {
// TODO(gibbed): expose this via ContentManager?
wchar_t title_id[9] = L"00000000";
std::swprintf(title_id, 9, L"%.8X", emulator_->kernel_state()->title_id());
auto package_root = xe::join_paths(content_root, title_id);
target_path = package_root;
}
if (!xe::filesystem::PathExists(target_path)) {
xe::filesystem::CreateFolder(target_path);
}
LaunchBrowser(target_path.c_str());
}
void EmulatorWindow::CheckHideCursor() { void EmulatorWindow::CheckHideCursor() {
if (!window_->is_fullscreen()) { if (!window_->is_fullscreen()) {
// Only hide when fullscreen. // Only hide when fullscreen.
@ -395,7 +422,7 @@ void EmulatorWindow::ToggleFullscreen() {
} }
} }
void EmulatorWindow::ShowHelpWebsite() { LaunchBrowser("https://xenia.jp"); } void EmulatorWindow::ShowHelpWebsite() { LaunchBrowser(L"https://xenia.jp"); }
void EmulatorWindow::UpdateTitle() { void EmulatorWindow::UpdateTitle() {
std::wstring title(base_title_); std::wstring title(base_title_);

View File

@ -46,6 +46,7 @@ class EmulatorWindow {
void FileDrop(wchar_t* filename); void FileDrop(wchar_t* filename);
void FileOpen(); void FileOpen();
void FileClose(); void FileClose();
void ShowContentDirectory();
void CheckHideCursor(); void CheckHideCursor();
void CpuTimeScalarReset(); void CpuTimeScalarReset();
void CpuTimeScalarSetHalf(); void CpuTimeScalarSetHalf();

View File

@ -69,23 +69,23 @@ void av_log_callback(void* avcl, int level, const char* fmt, va_list va) {
switch (level) { switch (level) {
case AV_LOG_ERROR: case AV_LOG_ERROR:
level_char = '!'; level_char = '!';
log_level = xe::LogLevel::LOG_LEVEL_ERROR; log_level = xe::LogLevel::Error;
break; break;
case AV_LOG_WARNING: case AV_LOG_WARNING:
level_char = 'w'; level_char = 'w';
log_level = xe::LogLevel::LOG_LEVEL_WARNING; log_level = xe::LogLevel::Warning;
break; break;
case AV_LOG_INFO: case AV_LOG_INFO:
level_char = 'i'; level_char = 'i';
log_level = xe::LogLevel::LOG_LEVEL_INFO; log_level = xe::LogLevel::Info;
break; break;
case AV_LOG_VERBOSE: case AV_LOG_VERBOSE:
level_char = 'v'; level_char = 'v';
log_level = xe::LogLevel::LOG_LEVEL_DEBUG; log_level = xe::LogLevel::Debug;
break; break;
case AV_LOG_DEBUG: case AV_LOG_DEBUG:
level_char = 'd'; level_char = 'd';
log_level = xe::LogLevel::LOG_LEVEL_DEBUG; log_level = xe::LogLevel::Debug;
break; break;
} }
@ -109,18 +109,18 @@ X_STATUS XmaDecoder::Setup(kernel::KernelState* kernel_state) {
sizeof(XMA_CONTEXT_DATA) * kContextCount, 256, kSystemHeapPhysical); sizeof(XMA_CONTEXT_DATA) * kContextCount, 256, kSystemHeapPhysical);
context_data_last_ptr_ = context_data_last_ptr_ =
context_data_first_ptr_ + (sizeof(XMA_CONTEXT_DATA) * kContextCount - 1); context_data_first_ptr_ + (sizeof(XMA_CONTEXT_DATA) * kContextCount - 1);
registers_.context_array_ptr = context_data_first_ptr_; register_file_[XE_XMA_REG_CONTEXT_ARRAY_ADDRESS].u32 =
context_data_first_ptr_;
// Setup XMA contexts. // Setup XMA contexts.
for (int i = 0; i < kContextCount; ++i) { for (int i = 0; i < kContextCount; ++i) {
uint32_t guest_ptr = uint32_t guest_ptr = context_data_first_ptr_ + i * sizeof(XMA_CONTEXT_DATA);
registers_.context_array_ptr + i * sizeof(XMA_CONTEXT_DATA);
XmaContext& context = contexts_[i]; XmaContext& context = contexts_[i];
if (context.Setup(i, memory(), guest_ptr)) { if (context.Setup(i, memory(), guest_ptr)) {
assert_always(); assert_always();
} }
} }
registers_.next_context = 1; register_file_[XE_XMA_REG_NEXT_CONTEXT_INDEX].u32 = 1;
context_bitmap_.Resize(kContextCount); context_bitmap_.Resize(kContextCount);
worker_running_ = true; worker_running_ = true;
@ -185,11 +185,16 @@ void XmaDecoder::Shutdown() {
xe::threading::Wait(worker_thread_->thread(), false); xe::threading::Wait(worker_thread_->thread(), false);
worker_thread_.reset(); worker_thread_.reset();
memory()->SystemHeapFree(registers_.context_array_ptr); if (context_data_first_ptr_) {
memory()->SystemHeapFree(context_data_first_ptr_);
}
context_data_first_ptr_ = 0;
context_data_last_ptr_ = 0;
} }
int XmaDecoder::GetContextId(uint32_t guest_ptr) { int XmaDecoder::GetContextId(uint32_t guest_ptr) {
static_assert(sizeof(XMA_CONTEXT_DATA) == 64, "FIXME"); static_assert_size(XMA_CONTEXT_DATA, 64);
if (guest_ptr < context_data_first_ptr_ || if (guest_ptr < context_data_first_ptr_ ||
guest_ptr > context_data_last_ptr_) { guest_ptr > context_data_last_ptr_) {
return -1; return -1;
@ -229,51 +234,70 @@ bool XmaDecoder::BlockOnContext(uint32_t guest_ptr, bool poll) {
return context.Block(poll); return context.Block(poll);
} }
// free60 may be useful here, however it looks like it's using a different
// piece of hardware:
// https://github.com/Free60Project/libxenon/blob/master/libxenon/drivers/xenon_sound/sound.c
uint32_t XmaDecoder::ReadRegister(uint32_t addr) { uint32_t XmaDecoder::ReadRegister(uint32_t addr) {
uint32_t r = addr & 0xFFFF; uint32_t r = (addr & 0xFFFF) / 4;
// 1800h is read on startup and stored -- context? buffers?
// 1818h is read during a lock?
assert_true(r % 4 == 0); switch (r) {
uint32_t value = register_file_[r / 4]; default: {
if (!register_file_.GetRegisterInfo(r)) {
// 1818 is rotating context processing # set to hardware ID of context being XELOGE("XMA: Read from unknown register (%.4X)", r);
// processed. }
// If bit 200h is set, the locking code will possibly collide on hardware IDs }
// and error out, so we should never set it (I think?). #pragma warning(suppress : 4065)
if (r == 0x1818) {
// To prevent games from seeing a stuck XMA context, return a rotating
// number
registers_.current_context = registers_.next_context;
registers_.next_context = (registers_.next_context + 1) % kContextCount;
} }
value = xe::byte_swap(value); assert_true(r < XmaRegisterFile::kRegisterCount);
return value;
// 0606h (1818h) is rotating context processing # set to hardware ID of
// context being processed.
// If bit 200h is set, the locking code will possibly collide on hardware IDs
// and error out, so we should never set it (I think?).
if (r == XE_XMA_REG_CURRENT_CONTEXT_INDEX) {
// To prevent games from seeing a stuck XMA context, return a rotating
// number
uint32_t next_context_index =
register_file_[XE_XMA_REG_NEXT_CONTEXT_INDEX].u32;
register_file_[XE_XMA_REG_CURRENT_CONTEXT_INDEX].u32 = next_context_index;
register_file_[XE_XMA_REG_NEXT_CONTEXT_INDEX].u32 =
(next_context_index + 1) % kContextCount;
}
return xe::byte_swap(register_file_.values[r].u32);
} }
void XmaDecoder::WriteRegister(uint32_t addr, uint32_t value) { void XmaDecoder::WriteRegister(uint32_t addr, uint32_t value) {
SCOPE_profile_cpu_f("apu"); SCOPE_profile_cpu_f("apu");
uint32_t r = addr & 0xFFFF; uint32_t r = (addr & 0xFFFF) / 4;
value = xe::byte_swap(value); value = xe::byte_swap(value);
// 1804h is written to with 0x02000000 and 0x03000000 around a lock operation
assert_true(r % 4 == 0); if ((r >= XE_XMA_REG_CONTEXT_KICK_0 && r <= XE_XMA_REG_CONTEXT_KICK_9) ||
register_file_[r / 4] = uint32_t(value); (r >= XE_XMA_REG_CONTEXT_LOCK_0 && r <= XE_XMA_REG_CONTEXT_LOCK_9) ||
(r >= XE_XMA_REG_CONTEXT_CLEAR_0 && r <= XE_XMA_REG_CONTEXT_CLEAR_9)) {
} else {
switch (r) {
default: {
XELOGE("XMA: Write to unhandled register (%.4X): %.8X", r, value);
break;
}
#pragma warning(suppress : 4065)
}
}
if (r >= 0x1940 && r <= 0x1940 + 9 * 4) { // 0601h (1804h) is written to with 0x02000000 and 0x03000000 around a lock
// operation
assert_true(r < XmaRegisterFile::kRegisterCount);
register_file_.values[r].u32 = value;
if (r >= XE_XMA_REG_CONTEXT_KICK_0 && r <= XE_XMA_REG_CONTEXT_KICK_9) {
// Context kick command. // Context kick command.
// This will kick off the given hardware contexts. // This will kick off the given hardware contexts.
// Basically, this kicks the SPU and says "hey, decode that audio!" // Basically, this kicks the SPU and says "hey, decode that audio!"
// XMAEnableContext // XMAEnableContext
// The context ID is a bit in the range of the entire context array. // The context ID is a bit in the range of the entire context array.
uint32_t base_context_id = (r - 0x1940) / 4 * 32; uint32_t base_context_id = (r - XE_XMA_REG_CONTEXT_KICK_0) * 32;
for (int i = 0; value && i < 32; ++i, value >>= 1) { for (int i = 0; value && i < 32; ++i, value >>= 1) {
if (value & 1) { if (value & 1) {
uint32_t context_id = base_context_id + i; uint32_t context_id = base_context_id + i;
@ -284,11 +308,11 @@ void XmaDecoder::WriteRegister(uint32_t addr, uint32_t value) {
// Signal the decoder thread to start processing. // Signal the decoder thread to start processing.
work_event_->Set(); work_event_->Set();
} else if (r >= 0x1A40 && r <= 0x1A40 + 9 * 4) { } else if (r >= XE_XMA_REG_CONTEXT_LOCK_0 && r <= XE_XMA_REG_CONTEXT_LOCK_9) {
// Context lock command. // Context lock command.
// This requests a lock by flagging the context. // This requests a lock by flagging the context.
// XMADisableContext // XMADisableContext
uint32_t base_context_id = (r - 0x1A40) / 4 * 32; uint32_t base_context_id = (r - XE_XMA_REG_CONTEXT_LOCK_0) * 32;
for (int i = 0; value && i < 32; ++i, value >>= 1) { for (int i = 0; value && i < 32; ++i, value >>= 1) {
if (value & 1) { if (value & 1) {
uint32_t context_id = base_context_id + i; uint32_t context_id = base_context_id + i;
@ -299,10 +323,11 @@ void XmaDecoder::WriteRegister(uint32_t addr, uint32_t value) {
// Signal the decoder thread to start processing. // Signal the decoder thread to start processing.
work_event_->Set(); work_event_->Set();
} else if (r >= 0x1A80 && r <= 0x1A80 + 9 * 4) { } else if (r >= XE_XMA_REG_CONTEXT_CLEAR_0 &&
r <= XE_XMA_REG_CONTEXT_CLEAR_9) {
// Context clear command. // Context clear command.
// This will reset the given hardware contexts. // This will reset the given hardware contexts.
uint32_t base_context_id = (r - 0x1A80) / 4 * 32; uint32_t base_context_id = (r - XE_XMA_REG_CONTEXT_CLEAR_0) * 32;
for (int i = 0; value && i < 32; ++i, value >>= 1) { for (int i = 0; value && i < 32; ++i, value >>= 1) {
if (value & 1) { if (value & 1) {
uint32_t context_id = base_context_id + i; uint32_t context_id = base_context_id + i;

View File

@ -15,6 +15,7 @@
#include <queue> #include <queue>
#include "xenia/apu/xma_context.h" #include "xenia/apu/xma_context.h"
#include "xenia/apu/xma_register_file.h"
#include "xenia/base/bit_map.h" #include "xenia/base/bit_map.h"
#include "xenia/kernel/xthread.h" #include "xenia/kernel/xthread.h"
#include "xenia/xbox.h" #include "xenia/xbox.h"
@ -35,7 +36,9 @@ class XmaDecoder {
X_STATUS Setup(kernel::KernelState* kernel_state); X_STATUS Setup(kernel::KernelState* kernel_state);
void Shutdown(); void Shutdown();
uint32_t context_array_ptr() const { return registers_.context_array_ptr; } uint32_t context_array_ptr() const {
return register_file_.values[XE_XMA_REG_CONTEXT_ARRAY_ADDRESS].u32;
}
uint32_t AllocateContext(); uint32_t AllocateContext();
void ReleaseContext(uint32_t guest_ptr); void ReleaseContext(uint32_t guest_ptr);
@ -75,26 +78,7 @@ class XmaDecoder {
xe::threading::Fence pause_fence_; // Signaled when worker paused. xe::threading::Fence pause_fence_; // Signaled when worker paused.
xe::threading::Fence resume_fence_; // Signaled when resume requested. xe::threading::Fence resume_fence_; // Signaled when resume requested.
// Stored little endian, accessed through 0x7FEA.... XmaRegisterFile register_file_;
union {
struct {
union {
struct {
uint8_t ignored0[0x1800];
// 1800h; points to guest-space physical block of 320 contexts.
uint32_t context_array_ptr;
};
struct {
uint8_t ignored1[0x1818];
// 1818h; current context ID.
uint32_t current_context;
// 181Ch; next context ID to process.
uint32_t next_context;
};
};
} registers_;
uint32_t register_file_[0xFFFF / 4];
};
static const uint32_t kContextCount = 320; static const uint32_t kContextCount = 320;
XmaContext contexts_[kContextCount]; XmaContext contexts_[kContextCount];

View File

@ -0,0 +1,39 @@
/**
******************************************************************************
* 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 "xenia/apu/xma_register_file.h"
#include <cstring>
#include "xenia/base/math.h"
namespace xe {
namespace apu {
XmaRegisterFile::XmaRegisterFile() { std::memset(values, 0, sizeof(values)); }
const XmaRegisterInfo* XmaRegisterFile::GetRegisterInfo(uint32_t index) {
switch (index) {
#define XE_XMA_REGISTER(index, type, name) \
case index: { \
static const XmaRegisterInfo reg_info = { \
XmaRegisterInfo::Type::type, \
#name, \
}; \
return &reg_info; \
}
#include "xenia/apu/xma_register_table.inc"
#undef XE_XMA_REGISTER
default:
return nullptr;
}
}
} // namespace apu
} // namespace xe

View File

@ -0,0 +1,54 @@
/**
******************************************************************************
* 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 XENIA_APU_XMA_REGISTER_FILE_H_
#define XENIA_APU_XMA_REGISTER_FILE_H_
#include <cstdint>
#include <cstdlib>
namespace xe {
namespace apu {
enum XmaRegister {
#define XE_XMA_REGISTER(index, type, name) XE_XMA_REG_##name = index,
#include "xenia/apu/xma_register_table.inc"
#undef XE_XMA_REGISTER
};
struct XmaRegisterInfo {
enum class Type {
kDword,
kFloat,
};
Type type;
const char* name;
};
class XmaRegisterFile {
public:
XmaRegisterFile();
static const XmaRegisterInfo* GetRegisterInfo(uint32_t index);
static const size_t kRegisterCount = (0xFFFF + 1) / 4;
union RegisterValue {
uint32_t u32;
float f32;
};
RegisterValue values[kRegisterCount];
RegisterValue& operator[](int reg) { return values[reg]; }
RegisterValue& operator[](XmaRegister reg) { return values[reg]; }
};
} // namespace apu
} // namespace xe
#endif // XENIA_APU_XMA_REGISTER_FILE_H_

View File

@ -0,0 +1,51 @@
/**
******************************************************************************
* 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. *
******************************************************************************
*/
// This is a partial file designed to be included by other files when
// constructing various tables.
//#define XE_XMA_REGISTER(index, type, name)
XE_XMA_REGISTER(0x0600, kDword, CONTEXT_ARRAY_ADDRESS)
XE_XMA_REGISTER(0x0606, kDword, CURRENT_CONTEXT_INDEX)
XE_XMA_REGISTER(0x0607, kDword, NEXT_CONTEXT_INDEX)
XE_XMA_REGISTER(0x0650, kDword, CONTEXT_KICK_0)
XE_XMA_REGISTER(0x0651, kDword, CONTEXT_KICK_1)
XE_XMA_REGISTER(0x0652, kDword, CONTEXT_KICK_2)
XE_XMA_REGISTER(0x0653, kDword, CONTEXT_KICK_3)
XE_XMA_REGISTER(0x0654, kDword, CONTEXT_KICK_4)
XE_XMA_REGISTER(0x0655, kDword, CONTEXT_KICK_5)
XE_XMA_REGISTER(0x0656, kDword, CONTEXT_KICK_6)
XE_XMA_REGISTER(0x0657, kDword, CONTEXT_KICK_7)
XE_XMA_REGISTER(0x0658, kDword, CONTEXT_KICK_8)
XE_XMA_REGISTER(0x0659, kDword, CONTEXT_KICK_9)
XE_XMA_REGISTER(0x0690, kDword, CONTEXT_LOCK_0)
XE_XMA_REGISTER(0x0691, kDword, CONTEXT_LOCK_1)
XE_XMA_REGISTER(0x0692, kDword, CONTEXT_LOCK_2)
XE_XMA_REGISTER(0x0693, kDword, CONTEXT_LOCK_3)
XE_XMA_REGISTER(0x0694, kDword, CONTEXT_LOCK_4)
XE_XMA_REGISTER(0x0695, kDword, CONTEXT_LOCK_5)
XE_XMA_REGISTER(0x0696, kDword, CONTEXT_LOCK_6)
XE_XMA_REGISTER(0x0697, kDword, CONTEXT_LOCK_7)
XE_XMA_REGISTER(0x0698, kDword, CONTEXT_LOCK_8)
XE_XMA_REGISTER(0x0699, kDword, CONTEXT_LOCK_9)
XE_XMA_REGISTER(0x06A0, kDword, CONTEXT_CLEAR_0)
XE_XMA_REGISTER(0x06A1, kDword, CONTEXT_CLEAR_1)
XE_XMA_REGISTER(0x06A2, kDword, CONTEXT_CLEAR_2)
XE_XMA_REGISTER(0x06A3, kDword, CONTEXT_CLEAR_3)
XE_XMA_REGISTER(0x06A4, kDword, CONTEXT_CLEAR_4)
XE_XMA_REGISTER(0x06A5, kDword, CONTEXT_CLEAR_5)
XE_XMA_REGISTER(0x06A6, kDword, CONTEXT_CLEAR_6)
XE_XMA_REGISTER(0x06A7, kDword, CONTEXT_CLEAR_7)
XE_XMA_REGISTER(0x06A8, kDword, CONTEXT_CLEAR_8)
XE_XMA_REGISTER(0x06A9, kDword, CONTEXT_CLEAR_9)

View File

@ -315,7 +315,7 @@ void LogLine(LogLevel log_level, const char prefix_char,
void FatalError(const char* fmt, ...) { void FatalError(const char* fmt, ...) {
va_list args; va_list args;
va_start(args, fmt); va_start(args, fmt);
LogLineVarargs(LogLevel::LOG_LEVEL_ERROR, 'X', fmt, args); LogLineVarargs(LogLevel::Error, 'X', fmt, args);
va_end(args); va_end(args);
#if XE_PLATFORM_WIN32 #if XE_PLATFORM_WIN32

View File

@ -19,11 +19,17 @@ namespace xe {
#define XE_OPTION_ENABLE_LOGGING 1 #define XE_OPTION_ENABLE_LOGGING 1
// Log level is a general indication of the importance of a given log line.
//
// While log levels are named, they are a rough correlation of what the log line
// may be related to. These names should not be taken as fact as what a given
// log line from any log level actually is.
enum class LogLevel { enum class LogLevel {
LOG_LEVEL_ERROR, Error = 0,
LOG_LEVEL_WARNING, Warning,
LOG_LEVEL_INFO, Info,
LOG_LEVEL_DEBUG, Debug,
Trace,
}; };
// Initializes the logging system and any outputs requested. // Initializes the logging system and any outputs requested.
@ -56,25 +62,21 @@ void FatalError(const std::string& str);
} while (false) } while (false)
#endif // ENABLE_LOGGING #endif // ENABLE_LOGGING
#define XELOGE(fmt, ...) \ #define XELOGE(fmt, ...) XELOGCORE(xe::LogLevel::Error, '!', fmt, ##__VA_ARGS__)
XELOGCORE(xe::LogLevel::LOG_LEVEL_ERROR, '!', fmt, ##__VA_ARGS__)
#define XELOGW(fmt, ...) \ #define XELOGW(fmt, ...) \
XELOGCORE(xe::LogLevel::LOG_LEVEL_WARNING, 'w', fmt, ##__VA_ARGS__) XELOGCORE(xe::LogLevel::Warning, 'w', fmt, ##__VA_ARGS__)
#define XELOGI(fmt, ...) \ #define XELOGI(fmt, ...) XELOGCORE(xe::LogLevel::Info, 'i', fmt, ##__VA_ARGS__)
XELOGCORE(xe::LogLevel::LOG_LEVEL_INFO, 'i', fmt, ##__VA_ARGS__) #define XELOGD(fmt, ...) XELOGCORE(xe::LogLevel::Debug, 'd', fmt, ##__VA_ARGS__)
#define XELOGD(fmt, ...) \
XELOGCORE(xe::LogLevel::LOG_LEVEL_DEBUG, 'd', fmt, ##__VA_ARGS__)
#define XELOGCPU(fmt, ...) \ #define XELOGCPU(fmt, ...) \
XELOGCORE(xe::LogLevel::LOG_LEVEL_INFO, 'C', fmt, ##__VA_ARGS__) XELOGCORE(xe::LogLevel::Info, 'C', fmt, ##__VA_ARGS__)
#define XELOGAPU(fmt, ...) \ #define XELOGAPU(fmt, ...) \
XELOGCORE(xe::LogLevel::LOG_LEVEL_INFO, 'A', fmt, ##__VA_ARGS__) XELOGCORE(xe::LogLevel::Info, 'A', fmt, ##__VA_ARGS__)
#define XELOGGPU(fmt, ...) \ #define XELOGGPU(fmt, ...) \
XELOGCORE(xe::LogLevel::LOG_LEVEL_INFO, 'G', fmt, ##__VA_ARGS__) XELOGCORE(xe::LogLevel::Info, 'G', fmt, ##__VA_ARGS__)
#define XELOGKERNEL(fmt, ...) \ #define XELOGKERNEL(fmt, ...) \
XELOGCORE(xe::LogLevel::LOG_LEVEL_INFO, 'K', fmt, ##__VA_ARGS__) XELOGCORE(xe::LogLevel::Info, 'K', fmt, ##__VA_ARGS__)
#define XELOGFS(fmt, ...) \ #define XELOGFS(fmt, ...) XELOGCORE(xe::LogLevel::Info, 'F', fmt, ##__VA_ARGS__)
XELOGCORE(xe::LogLevel::LOG_LEVEL_INFO, 'F', fmt, ##__VA_ARGS__)
} // namespace xe } // namespace xe

View File

@ -103,7 +103,7 @@ const size_t kMaxPath = 1024; // PATH_MAX
#endif // XE_PLATFORM_WIN32 #endif // XE_PLATFORM_WIN32
// Launches a web browser to the given URL. // Launches a web browser to the given URL.
void LaunchBrowser(const char* url); void LaunchBrowser(const wchar_t* url);
} // namespace xe } // namespace xe

View File

@ -10,11 +10,12 @@
#include "xenia/base/platform_linux.h" #include "xenia/base/platform_linux.h"
#include <stdlib.h> #include <stdlib.h>
#include <string> #include <string>
#include "xenia/base/string.h"
namespace xe { namespace xe {
void LaunchBrowser(const char* url) { void LaunchBrowser(const wchar_t* url) {
auto cmd = std::string("xdg-open " + std::string(url)); auto cmd = std::string("xdg-open " + xe::to_string(url));
system(cmd.c_str()); system(cmd.c_str());
} }

View File

@ -11,8 +11,8 @@
namespace xe { namespace xe {
void LaunchBrowser(const char* url) { void LaunchBrowser(const wchar_t* url) {
ShellExecuteA(NULL, "open", url, NULL, NULL, SW_SHOWNORMAL); ShellExecuteW(NULL, L"open", url, NULL, NULL, SW_SHOWNORMAL);
} }
} // namespace xe } // namespace xe

View File

@ -32,13 +32,12 @@ bool trace_enabled = true;
#define THREAD_MATCH \ #define THREAD_MATCH \
(!TARGET_THREAD || thread_state->thread_id() == TARGET_THREAD) (!TARGET_THREAD || thread_state->thread_id() == TARGET_THREAD)
#define IFLUSH() #define IFLUSH()
#define IPRINT(s) \ #define IPRINT(s) \
if (trace_enabled && THREAD_MATCH) \ if (trace_enabled && THREAD_MATCH) xe::LogLine(xe::LogLevel::Debug, 't', s)
xe::LogLine(xe::LogLevel::LOG_LEVEL_DEBUG, 't', s)
#define DFLUSH() #define DFLUSH()
#define DPRINT(...) \ #define DPRINT(...) \
if (trace_enabled && THREAD_MATCH) \ if (trace_enabled && THREAD_MATCH) \
xe::LogLineFormat(xe::LogLevel::LOG_LEVEL_DEBUG, 't', __VA_ARGS__) xe::LogLineFormat(xe::LogLevel::Debug, 't', __VA_ARGS__)
uint32_t GetTracingMode() { uint32_t GetTracingMode() {
uint32_t mode = 0; uint32_t mode = 0;

View File

@ -804,7 +804,7 @@ void UserModule::Dump() {
sb.AppendFormat("\n"); sb.AppendFormat("\n");
} }
xe::LogLine(xe::LogLevel::LOG_LEVEL_INFO, 'i', sb.GetString()); xe::LogLine(xe::LogLevel::Info, 'i', sb.GetString());
} }
} // namespace kernel } // namespace kernel

View File

@ -451,10 +451,10 @@ void PrintKernelCall(cpu::Export* export_entry, const Tuple& params) {
AppendKernelCallParams(string_buffer, export_entry, params); AppendKernelCallParams(string_buffer, export_entry, params);
string_buffer.Append(')'); string_buffer.Append(')');
if (export_entry->tags & xe::cpu::ExportTag::kImportant) { if (export_entry->tags & xe::cpu::ExportTag::kImportant) {
xe::LogLine(xe::LogLevel::LOG_LEVEL_INFO, 'i', string_buffer.GetString(), xe::LogLine(xe::LogLevel::Info, 'i', string_buffer.GetString(),
string_buffer.length()); string_buffer.length());
} else { } else {
xe::LogLine(xe::LogLevel::LOG_LEVEL_DEBUG, 'd', string_buffer.GetString(), xe::LogLine(xe::LogLevel::Debug, 'd', string_buffer.GetString(),
string_buffer.length()); string_buffer.length());
} }
} }

View File

@ -63,7 +63,7 @@ bool Win32Window::OnCreate() {
auto spda = (decltype(&SetProcessDpiAwareness))SetProcessDpiAwareness_; auto spda = (decltype(&SetProcessDpiAwareness))SetProcessDpiAwareness_;
auto res = spda(PROCESS_PER_MONITOR_DPI_AWARE); auto res = spda(PROCESS_PER_MONITOR_DPI_AWARE);
if (res != S_OK) { if (res != S_OK) {
XELOGE("Failed to set process DPI awareness. (code = 0x%.8X)", res); XELOGW("Failed to set process DPI awareness. (code = 0x%.8X)", res);
} }
} }