Merge branch 'master' into d3d12

This commit is contained in:
Triang3l
2018-11-22 20:59:55 +03:00
130 changed files with 481 additions and 248 deletions

View File

@@ -260,7 +260,7 @@ bool EmulatorWindow::Initialize() {
std::bind(&EmulatorWindow::ShowHelpWebsite, this)));
help_menu->AddChild(MenuItem::Create(
MenuItem::Type::kString, L"&About...",
[this]() { LaunchBrowser("http://xenia.jp/about/"); }));
[this]() { LaunchBrowser("https://xenia.jp/about/"); }));
}
main_menu->AddChild(std::move(help_menu));
@@ -384,7 +384,7 @@ void EmulatorWindow::ToggleFullscreen() {
}
}
void EmulatorWindow::ShowHelpWebsite() { LaunchBrowser("http://xenia.jp"); }
void EmulatorWindow::ShowHelpWebsite() { LaunchBrowser("https://xenia.jp"); }
void EmulatorWindow::UpdateTitle() {
std::wstring title(base_title_);

View File

@@ -47,6 +47,8 @@ DEFINE_string(hid, "any", "Input system. Use: [any, nop, winkey, xinput]");
DEFINE_string(target, "", "Specifies the target .xex or .iso to execute.");
DEFINE_bool(fullscreen, false, "Toggles fullscreen");
DEFINE_string(content_root, "", "Root path for content (save/etc) storage.");
DEFINE_bool(mount_scratch, false, "Enable scratch mount");
DEFINE_bool(mount_cache, false, "Enable cache mount");
@@ -132,11 +134,18 @@ std::vector<std::unique_ptr<hid::InputDriver>> CreateInputDrivers(
drivers.emplace_back(std::move(winkey_driver));
}
#endif // XE_PLATFORM_WIN32
if (drivers.empty()) {
// Fallback to nop if none created.
drivers.emplace_back(xe::hid::nop::Create(window));
}
for (auto it = drivers.begin(); it != drivers.end();) {
if (XFAILED((*it)->Setup())) {
it = drivers.erase(it);
} else {
++it;
}
}
if (drivers.empty()) {
// Fallback to nop if none created.
drivers.emplace_back(xe::hid::nop::Create(window));
}
return drivers;
}
@@ -144,8 +153,35 @@ int xenia_main(const std::vector<std::wstring>& args) {
Profiler::Initialize();
Profiler::ThreadEnter("main");
// Figure out where content should go.
std::wstring content_root;
if (!FLAGS_content_root.empty()) {
content_root = xe::to_wstring(FLAGS_content_root);
} else {
auto base_path = xe::filesystem::GetExecutableFolder();
base_path = xe::to_absolute_path(base_path);
auto portable_path = xe::join_paths(base_path, L"portable.txt");
if (xe::filesystem::PathExists(portable_path)) {
content_root = xe::join_paths(base_path, L"content");
} else {
content_root = xe::filesystem::GetUserFolder();
#if defined(XE_PLATFORM_WIN32)
content_root = xe::join_paths(content_root, L"Xenia");
#elif defined(XE_PLATFORM_LINUX)
content_root = xe::join_paths(content_root, L".xenia");
#else
#warning Unhandled platform for content root.
content_root = xe::join_paths(content_root, L"Xenia");
#endif
content_root = xe::join_paths(content_root, L"content");
}
content_root = xe::to_absolute_path(content_root);
}
// Create the emulator but don't initialize so we can setup the window.
auto emulator = std::make_unique<Emulator>(L"");
auto emulator = std::make_unique<Emulator>(L"", content_root);
// Main emulator display window.
auto emulator_window = EmulatorWindow::Create(emulator.get());

View File

@@ -25,7 +25,7 @@
// Helpful resources:
// https://github.com/koolkdev/libertyv/blob/master/libav_wrapper/xma2dec.c
// http://hcs64.com/mboard/forum.php?showthread=14818
// https://hcs64.com/mboard/forum.php?showthread=14818
// https://github.com/hrydgard/minidx9/blob/master/Include/xma2defs.h
// Forward declarations
@@ -41,7 +41,7 @@ namespace apu {
// We load and swap the whole thing to splat here so that we can
// use bitfields.
// This could be important:
// http://www.fmod.org/questions/question/forum-15859
// https://www.fmod.org/questions/question/forum-15859
// Appears to be dumped in order (for the most part)
struct XMA_CONTEXT_DATA {

View File

@@ -17,7 +17,9 @@
namespace xe {
// These functions are modeled off of the Apple OSAtomic routines
// http://developer.apple.com/library/mac/#documentation/DriversKernelHardware/Reference/libkern_ref/OSAtomic_h/
// https://developer.apple.com/documentation/kernel/osatomic_h (?)
// Original link (dead):
// https://developer.apple.com/library/mac/#documentation/DriversKernelHardware/Reference/libkern_ref/OSAtomic_h/
#if XE_PLATFORM_MAC

View File

@@ -44,8 +44,8 @@ LONG CALLBACK ExceptionHandlerCallback(PEXCEPTION_POINTERS ex_info) {
std::memcpy(thread_context.xmm_registers, &ex_info->ContextRecord->Xmm0,
sizeof(thread_context.xmm_registers));
// http://msdn.microsoft.com/en-us/library/ms679331(v=vs.85).aspx
// http://msdn.microsoft.com/en-us/library/aa363082(v=vs.85).aspx
// https://msdn.microsoft.com/en-us/library/ms679331(v=vs.85).aspx
// https://msdn.microsoft.com/en-us/library/aa363082(v=vs.85).aspx
Exception ex;
switch (ex_info->ExceptionRecord->ExceptionCode) {
case STATUS_ILLEGAL_INSTRUCTION:

View File

@@ -20,6 +20,15 @@
namespace xe {
namespace filesystem {
// Get executable path.
std::wstring GetExecutablePath();
// Get executable folder.
std::wstring GetExecutableFolder();
// Get user folder.
std::wstring GetUserFolder();
// Canonicalizes a path, removing ..'s.
std::string CanonicalizePath(const std::string& original_path);

View File

@@ -7,6 +7,7 @@
******************************************************************************
*/
#include "xenia/base/assert.h"
#include "xenia/base/filesystem.h"
#include "xenia/base/logging.h"
#include "xenia/base/string.h"
@@ -21,6 +22,21 @@
namespace xe {
namespace filesystem {
std::wstring GetExecutablePath() {
assert_always(); // IMPLEMENT ME.
return std::wstring();
}
std::wstring GetExecutableFolder() {
assert_always(); // IMPLEMENT ME.
return std::wstring();
}
std::wstring GetUserFolder() {
assert_always(); // IMPLEMENT ME.
return std::wstring();
}
bool PathExists(const std::wstring& path) {
struct stat st;
return stat(xe::to_string(path).c_str(), &st) == 0;

View File

@@ -12,11 +12,33 @@
#include <string>
#include <shlobj.h>
#include "xenia/base/platform_win.h"
namespace xe {
namespace filesystem {
std::wstring GetExecutablePath() {
wchar_t* path;
auto error = _get_wpgmptr(&path);
return !error ? std::wstring(path) : std::wstring();
}
std::wstring GetExecutableFolder() {
auto path = GetExecutablePath();
return xe::find_base_path(path);
}
std::wstring GetUserFolder() {
wchar_t path[MAX_PATH];
if (!SUCCEEDED(SHGetFolderPathW(nullptr, CSIDL_MYDOCUMENTS, nullptr,
SHGFP_TYPE_CURRENT, path))) {
return std::wstring();
}
return std::wstring(path);
}
bool PathExists(const std::wstring& path) {
DWORD attrib = GetFileAttributes(path.c_str());
return attrib != INVALID_FILE_ATTRIBUTES;

View File

@@ -15,9 +15,13 @@
namespace xe {
// TODO(benvanik): fancy AVX versions.
// http://gnuradio.org/redmine/projects/gnuradio/repository/revisions/cb32b70b79f430456208a2cd521d028e0ece5d5b/entry/volk/kernels/volk/volk_16u_byteswap.h
// http://gnuradio.org/redmine/projects/gnuradio/repository/revisions/f2bc76cc65ffba51a141950f98e75364e49df874/entry/volk/kernels/volk/volk_32u_byteswap.h
// http://gnuradio.org/redmine/projects/gnuradio/repository/revisions/2c4c371885c31222362f70a1cd714415d1398021/entry/volk/kernels/volk/volk_64u_byteswap.h
// https://github.com/gnuradio/volk/blob/master/kernels/volk/volk_16u_byteswap.h
// https://github.com/gnuradio/volk/blob/master/kernels/volk/volk_32u_byteswap.h
// https://github.com/gnuradio/volk/blob/master/kernels/volk/volk_64u_byteswap.h
// Original links:
// https://gnuradio.org/redmine/projects/gnuradio/repository/revisions/cb32b70b79f430456208a2cd521d028e0ece5d5b/entry/volk/kernels/volk/volk_16u_byteswap.h
// https://gnuradio.org/redmine/projects/gnuradio/repository/revisions/f2bc76cc65ffba51a141950f98e75364e49df874/entry/volk/kernels/volk/volk_32u_byteswap.h
// https://gnuradio.org/redmine/projects/gnuradio/repository/revisions/2c4c371885c31222362f70a1cd714415d1398021/entry/volk/kernels/volk/volk_64u_byteswap.h
void copy_128_aligned(void* dest, const void* src, size_t count) {
std::memcpy(dest, src, count * 16);

View File

@@ -19,7 +19,9 @@
// NOTE: ordering matters here as sometimes multiple flags are defined on
// certain platforms.
//
// Great resource on predefined macros: http://predef.sourceforge.net/preos.html
// Great resource on predefined macros:
// https://sourceforge.net/p/predef/wiki/OperatingSystems/
// Original link: https://predef.sourceforge.net/preos.html
#if defined(__APPLE__)
#include <TargetConditionals.h>

View File

@@ -114,7 +114,7 @@ void Profiler::ThreadEnter(const char* name) {
void Profiler::ThreadExit() { MicroProfileOnThreadExit(); }
bool Profiler::OnKeyDown(int key_code) {
// http://msdn.microsoft.com/en-us/library/windows/desktop/dd375731(v=vs.85).aspx
// https://msdn.microsoft.com/en-us/library/windows/desktop/dd375731(v=vs.85).aspx
switch (key_code) {
case VK_OEM_3: // `
MicroProfileTogglePause();

View File

@@ -29,7 +29,7 @@ uint32_t current_thread_system_id() {
return static_cast<uint32_t>(GetCurrentThreadId());
}
// http://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx
// https://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx
#pragma pack(push, 8)
struct THREADNAME_INFO {
DWORD dwType; // Must be 0x1000.

View File

@@ -187,7 +187,7 @@ uint64_t ReadCapstoneReg(X64Context* context, x86_reg reg) {
#define X86_EFLAGS_SF 0x00000080 // Sign Flag
#define X86_EFLAGS_OF 0x00000800 // Overflow Flag
bool TestCapstoneEflags(uint32_t eflags, uint32_t insn) {
// http://www.felixcloutier.com/x86/Jcc.html
// https://www.felixcloutier.com/x86/Jcc.html
switch (insn) {
case X86_INS_JAE:
// CF=0 && ZF=0

View File

@@ -37,7 +37,7 @@ namespace cpu {
namespace backend {
namespace x64 {
// http://msdn.microsoft.com/en-us/library/ssa62fwe.aspx
// https://msdn.microsoft.com/en-us/library/ssa62fwe.aspx
typedef enum _UNWIND_OP_CODES {
UWOP_PUSH_NONVOL = 0, /* info == register number */
UWOP_ALLOC_LARGE, /* no info, alloc size in next 2 slots */
@@ -242,7 +242,7 @@ void Win32X64CodeCache::InitializeUnwindEntry(uint8_t* unwind_entry_address,
UNWIND_CODE* unwind_code = nullptr;
if (!stack_size) {
// http://msdn.microsoft.com/en-us/library/ddssxxy8.aspx
// https://msdn.microsoft.com/en-us/library/ddssxxy8.aspx
unwind_info->Version = 1;
unwind_info->Flags = 0;
unwind_info->SizeOfProlog = 0;
@@ -252,7 +252,7 @@ void Win32X64CodeCache::InitializeUnwindEntry(uint8_t* unwind_entry_address,
} else if (stack_size <= 128) {
uint8_t prolog_size = 4;
// http://msdn.microsoft.com/en-us/library/ddssxxy8.aspx
// https://msdn.microsoft.com/en-us/library/ddssxxy8.aspx
unwind_info->Version = 1;
unwind_info->Flags = 0;
unwind_info->SizeOfProlog = prolog_size;
@@ -260,7 +260,7 @@ void Win32X64CodeCache::InitializeUnwindEntry(uint8_t* unwind_entry_address,
unwind_info->FrameRegister = 0;
unwind_info->FrameOffset = 0;
// http://msdn.microsoft.com/en-us/library/ck9asaa9.aspx
// https://msdn.microsoft.com/en-us/library/ck9asaa9.aspx
unwind_code = &unwind_info->UnwindCode[unwind_info->CountOfCodes++];
unwind_code->CodeOffset =
14; // end of instruction + 1 == offset of next instruction
@@ -270,7 +270,7 @@ void Win32X64CodeCache::InitializeUnwindEntry(uint8_t* unwind_entry_address,
// TODO(benvanik): take as parameters?
uint8_t prolog_size = 7;
// http://msdn.microsoft.com/en-us/library/ddssxxy8.aspx
// https://msdn.microsoft.com/en-us/library/ddssxxy8.aspx
unwind_info->Version = 1;
unwind_info->Flags = 0;
unwind_info->SizeOfProlog = prolog_size;
@@ -278,7 +278,7 @@ void Win32X64CodeCache::InitializeUnwindEntry(uint8_t* unwind_entry_address,
unwind_info->FrameRegister = 0;
unwind_info->FrameOffset = 0;
// http://msdn.microsoft.com/en-us/library/ck9asaa9.aspx
// https://msdn.microsoft.com/en-us/library/ck9asaa9.aspx
unwind_code = &unwind_info->UnwindCode[unwind_info->CountOfCodes++];
unwind_code->CodeOffset =
7; // end of instruction + 1 == offset of next instruction

View File

@@ -82,7 +82,7 @@ X64Emitter::X64Emitter(X64Backend* backend, XbyakAllocator* allocator)
if (!cpu_.has(Xbyak::util::Cpu::tAVX)) {
xe::FatalError(
"Your CPU is too old to support Xenia. See the FAQ for system "
"requirements at http://xenia.jp");
"requirements at https://xenia.jp");
return;
}
}
@@ -160,7 +160,7 @@ bool X64Emitter::Emit(HIRBuilder* builder, size_t* out_stack_size) {
// Function prolog.
// Must be 16b aligned.
// Windows is very strict about the form of this and the epilog:
// http://msdn.microsoft.com/en-us/library/tawsa7cb.aspx
// https://msdn.microsoft.com/en-us/library/tawsa7cb.aspx
// IMPORTANT: any changes to the prolog must be kept in sync with
// X64CodeCache, which dynamically generates exception information.
// Adding or changing anything here must be matched!
@@ -738,7 +738,7 @@ Xbyak::Address X64Emitter::GetXmmConstPtr(XmmConst id) {
}
void X64Emitter::LoadConstantXmm(Xbyak::Xmm dest, const vec128_t& v) {
// http://www.agner.org/optimize/optimizing_assembly.pdf
// https://www.agner.org/optimize/optimizing_assembly.pdf
// 13.4 Generating constants
if (!v.low && !v.high) {
// 0000...

View File

@@ -3367,7 +3367,8 @@ EMITTER_ASSOCIATIVE_COMPARE_XX(ULE, setbe, setae);
EMITTER_ASSOCIATIVE_COMPARE_XX(UGT, seta, setb);
EMITTER_ASSOCIATIVE_COMPARE_XX(UGE, setae, setbe);
// http://x86.renejeschke.de/html/file_module_x86_id_288.html
// https://web.archive.org/web/20171129015931/https://x86.renejeschke.de/html/file_module_x86_id_288.html
// Original link: https://x86.renejeschke.de/html/file_module_x86_id_288.html
#define EMITTER_ASSOCIATIVE_COMPARE_FLT_XX(op, instr) \
struct COMPARE_##op##_F32 \
: Sequence<COMPARE_##op##_F32, \
@@ -3793,7 +3794,7 @@ struct VECTOR_ADD
// If result is smaller than either of the inputs, we've
// overflowed (only need to check one input)
// if (src1 > res) then overflowed
// http://locklessinc.com/articles/sat_arithmetic/
// https://locklessinc.com/articles/sat_arithmetic/
e.vpxor(e.xmm2, src1, e.GetXmmConstPtr(XMMSignMaskI32));
e.vpxor(e.xmm0, e.xmm1, e.GetXmmConstPtr(XMMSignMaskI32));
e.vpcmpgtd(e.xmm0, e.xmm2, e.xmm0);
@@ -3804,7 +3805,7 @@ struct VECTOR_ADD
// Overflow results if two inputs are the same sign and the
// result isn't the same sign. if ((s32b)(~(src1 ^ src2) &
// (src1 ^ res)) < 0) then overflowed
// http://locklessinc.com/articles/sat_arithmetic/
// https://locklessinc.com/articles/sat_arithmetic/
e.vpxor(e.xmm2, src1, src2);
e.vpxor(e.xmm3, src1, e.xmm1);
e.vpandn(e.xmm2, e.xmm2, e.xmm3);
@@ -3950,7 +3951,7 @@ struct VECTOR_SUB
// If result is greater than either of the inputs, we've
// underflowed (only need to check one input)
// if (res > src1) then underflowed
// http://locklessinc.com/articles/sat_arithmetic/
// https://locklessinc.com/articles/sat_arithmetic/
e.vpxor(e.xmm2, src1, e.GetXmmConstPtr(XMMSignMaskI32));
e.vpxor(e.xmm0, e.xmm1, e.GetXmmConstPtr(XMMSignMaskI32));
e.vpcmpgtd(e.xmm0, e.xmm0, e.xmm2);
@@ -3962,7 +3963,7 @@ struct VECTOR_SUB
// opposite. If signs are opposite and result sign isn't the
// same as src1's sign, we've overflowed. if ((s32b)((src1 ^
// src2) & (src1 ^ res)) < 0) then overflowed
// http://locklessinc.com/articles/sat_arithmetic/
// https://locklessinc.com/articles/sat_arithmetic/
e.vpxor(e.xmm2, src1, src2);
e.vpxor(e.xmm3, src1, e.xmm1);
e.vpand(e.xmm2, e.xmm2, e.xmm3);
@@ -5062,7 +5063,7 @@ EMITTER_OPCODE_TABLE(OPCODE_RECIP, RECIP_F32, RECIP_F64, RECIP_V128);
// OPCODE_POW2
// ============================================================================
// TODO(benvanik): use approx here:
// http://jrfonseca.blogspot.com/2008/09/fast-sse2-pow-tables-or-polynomials.html
// https://jrfonseca.blogspot.com/2008/09/fast-sse2-pow-tables-or-polynomials.html
struct POW2_F32 : Sequence<POW2_F32, I<OPCODE_POW2, F32Op, F32Op>> {
static __m128 EmulatePow2(void*, __m128 src) {
float src_value;
@@ -5112,7 +5113,7 @@ EMITTER_OPCODE_TABLE(OPCODE_POW2, POW2_F32, POW2_F64, POW2_V128);
// OPCODE_LOG2
// ============================================================================
// TODO(benvanik): use approx here:
// http://jrfonseca.blogspot.com/2008/09/fast-sse2-pow-tables-or-polynomials.html
// https://jrfonseca.blogspot.com/2008/09/fast-sse2-pow-tables-or-polynomials.html
// TODO(benvanik): this emulated fn destroys all xmm registers! don't do it!
struct LOG2_F32 : Sequence<LOG2_F32, I<OPCODE_LOG2, F32Op, F32Op>> {
static __m128 EmulateLog2(void*, __m128 src) {
@@ -5166,7 +5167,7 @@ struct DOT_PRODUCT_3_V128
: Sequence<DOT_PRODUCT_3_V128,
I<OPCODE_DOT_PRODUCT_3, F32Op, V128Op, V128Op>> {
static void Emit(X64Emitter& e, const EmitArgType& i) {
// http://msdn.microsoft.com/en-us/library/bb514054(v=vs.90).aspx
// https://msdn.microsoft.com/en-us/library/bb514054(v=vs.90).aspx
EmitCommutativeBinaryXmmOp(e, i,
[](X64Emitter& e, Xmm dest, Xmm src1, Xmm src2) {
// TODO(benvanik): apparently this is very slow
@@ -5184,7 +5185,7 @@ struct DOT_PRODUCT_4_V128
: Sequence<DOT_PRODUCT_4_V128,
I<OPCODE_DOT_PRODUCT_4, F32Op, V128Op, V128Op>> {
static void Emit(X64Emitter& e, const EmitArgType& i) {
// http://msdn.microsoft.com/en-us/library/bb514054(v=vs.90).aspx
// https://msdn.microsoft.com/en-us/library/bb514054(v=vs.90).aspx
EmitCommutativeBinaryXmmOp(e, i,
[](X64Emitter& e, Xmm dest, Xmm src1, Xmm src2) {
// TODO(benvanik): apparently this is very slow
@@ -7003,7 +7004,7 @@ struct PACK : Sequence<PACK, I<OPCODE_PACK, V128Op, V128Op, V128Op>> {
}
static void EmitFLOAT16_2(X64Emitter& e, const EmitArgType& i) {
assert_true(i.src2.value->IsConstantZero());
// http://blogs.msdn.com/b/chuckw/archive/2012/09/11/directxmath-f16c-and-fma.aspx
// https://blogs.msdn.com/b/chuckw/archive/2012/09/11/directxmath-f16c-and-fma.aspx
// dest = [(src1.x | src1.y), 0, 0, 0]
Xmm src;
@@ -7398,10 +7399,10 @@ struct UNPACK : Sequence<UNPACK, I<OPCODE_UNPACK, V128Op, V128Op>> {
// 1 bit sign, 5 bit exponent, 10 bit mantissa
// D3D10 half float format
// TODO(benvanik):
// http://blogs.msdn.com/b/chuckw/archive/2012/09/11/directxmath-f16c-and-fma.aspx
// https://blogs.msdn.com/b/chuckw/archive/2012/09/11/directxmath-f16c-and-fma.aspx
// Use _mm_cvtph_ps -- requires very modern processors (SSE5+)
// Unpacking half floats:
// http://fgiesen.wordpress.com/2012/03/28/half-to-float-done-quic/
// https://fgiesen.wordpress.com/2012/03/28/half-to-float-done-quic/
// Packing half floats: https://gist.github.com/rygorous/2156668
// Load source, move from tight pack of X16Y16.... to X16...Y16...
// Also zero out the high end.

View File

@@ -489,7 +489,7 @@ int CompareValueUse(const Value::Use* a, const Value::Use* b) {
} // namespace
void RegisterAllocationPass::SortUsageList(Value* value) {
// Modified in-place linked list sort from:
// http://www.chiark.greenend.org.uk/~sgtatham/algorithms/listsort.c
// https://www.chiark.greenend.org.uk/~sgtatham/algorithms/listsort.c
if (!value->use_head) {
return;
}

View File

@@ -505,7 +505,7 @@ bool TryDecodeMov(const uint8_t* p, DecodedMov* mov) {
}
if (p[i] == 0x0F && p[i + 1] == 0x38 && p[i + 2] == 0xF1) {
// MOVBE m32, r32 (store)
// http://www.tptp.cc/mirrors/siyobik.info/instruction/MOVBE.html
// https://web.archive.org/web/20170629091435/https://www.tptp.cc/mirrors/siyobik.info/instruction/MOVBE.html
// 44 0f 38 f1 a4 02 00 movbe DWORD PTR [rdx+rax*1+0x0],r12d
// 42 0f 38 f1 8c 22 00 movbe DWORD PTR [rdx+r12*1+0x0],ecx
// 0f 38 f1 8c 02 00 00 movbe DWORD PTR [rdx + rax * 1 + 0x0], ecx
@@ -514,7 +514,7 @@ bool TryDecodeMov(const uint8_t* p, DecodedMov* mov) {
i += 3;
} else if (p[i] == 0x0F && p[i + 1] == 0x38 && p[i + 2] == 0xF0) {
// MOVBE r32, m32 (load)
// http://www.tptp.cc/mirrors/siyobik.info/instruction/MOVBE.html
// https://web.archive.org/web/20170629091435/https://www.tptp.cc/mirrors/siyobik.info/instruction/MOVBE.html
// 44 0f 38 f0 a4 02 00 movbe r12d,DWORD PTR [rdx+rax*1+0x0]
// 42 0f 38 f0 8c 22 00 movbe ecx,DWORD PTR [rdx+r12*1+0x0]
// 46 0f 38 f0 a4 22 00 movbe r12d,DWORD PTR [rdx+r12*1+0x0]
@@ -525,7 +525,7 @@ bool TryDecodeMov(const uint8_t* p, DecodedMov* mov) {
i += 3;
} else if (p[i] == 0x89) {
// MOV m32, r32 (store)
// http://www.tptp.cc/mirrors/siyobik.info/instruction/MOV.html
// https://web.archive.org/web/20170629072136/https://www.tptp.cc/mirrors/siyobik.info/instruction/MOV.html
// 44 89 24 02 mov DWORD PTR[rdx + rax * 1], r12d
// 42 89 0c 22 mov DWORD PTR[rdx + r12 * 1], ecx
// 89 0c 02 mov DWORD PTR[rdx + rax * 1], ecx
@@ -534,7 +534,7 @@ bool TryDecodeMov(const uint8_t* p, DecodedMov* mov) {
++i;
} else if (p[i] == 0x8B) {
// MOV r32, m32 (load)
// http://www.tptp.cc/mirrors/siyobik.info/instruction/MOV.html
// https://web.archive.org/web/20170629072136/https://www.tptp.cc/mirrors/siyobik.info/instruction/MOV.html
// 44 8b 24 02 mov r12d, DWORD PTR[rdx + rax * 1]
// 42 8b 0c 22 mov ecx, DWORD PTR[rdx + r12 * 1]
// 46 8b 24 22 mov r12d, DWORD PTR[rdx + r12 * 1]
@@ -544,7 +544,7 @@ bool TryDecodeMov(const uint8_t* p, DecodedMov* mov) {
++i;
} else if (p[i] == 0xC7) {
// MOV m32, simm32
// http://www.asmpedia.org/index.php?title=MOV
// https://web.archive.org/web/20161017042413/https://www.asmpedia.org/index.php?title=MOV
// C7 04 02 02 00 00 00 mov dword ptr [rdx+rax],2
mov->is_load = false;
mov->byte_swap = false;

View File

@@ -31,7 +31,7 @@ Value* CalculateEA_0(PPCHIRBuilder& f, uint32_t ra, uint32_t rb);
// Most of this file comes from:
// http://biallas.net/doc/vmx128/vmx128.txt
// https://github.com/kakaroto/ps3ida/blob/master/plugins/PPCAltivec/src/main.cpp
// http://sannybuilder.com/forums/viewtopic.php?id=190
// https://sannybuilder.com/forums/viewtopic.php?id=190
#define OP(x) ((((uint32_t)(x)) & 0x3f) << 26)
#define VX128(op, xop) (OP(op) | (((uint32_t)(xop)) & 0x3d0))
@@ -2068,7 +2068,7 @@ int InstrEmit_vpkd3d128(PPCHIRBuilder& f, const InstrData& i) {
assert_unhandled_case(type);
return 1;
}
// http://hlssmod.net/he_code/public/pixelwriter.h
// https://hlssmod.net/he_code/public/pixelwriter.h
// control = prev:0123 | new:4567
uint32_t control = kIdentityPermuteMask; // original
switch (pack) {
@@ -2141,7 +2141,8 @@ int InstrEmit_vpkd3d128(PPCHIRBuilder& f, const InstrData& i) {
int InstrEmit_vupkd3d128(PPCHIRBuilder& f, const InstrData& i) {
// Can't find many docs on this. Best reference is
// http://worldcraft.googlecode.com/svn/trunk/src/qylib/math/xmmatrix.inl,
// https://code.google.com/archive/p/worldcraft/source/default/source?page=4
// (qylib/math/xmmatrix.inl)
// which shows how it's used in some cases. Since it's all intrinsics,
// finding it in code is pretty easy.
const uint32_t vd = i.VX128_3.VD128l | (i.VX128_3.VD128h << 5);

View File

@@ -26,7 +26,7 @@ using xe::cpu::hir::RoundMode;
using xe::cpu::hir::Value;
// Good source of information:
// http://mamedev.org/source/src/emu/cpu/powerpc/ppc_ops.c
// https://github.com/mamedev/historic-mame/blob/master/src/emu/cpu/powerpc/ppc_ops.c
// The correctness of that code is not reflected here yet -_-
// Enable rounding numbers to single precision as required.

View File

@@ -48,8 +48,9 @@ DEFINE_double(time_scalar, 1.0,
namespace xe {
Emulator::Emulator(const std::wstring& command_line)
: command_line_(command_line) {}
Emulator::Emulator(const std::wstring& command_line,
const std::wstring& content_root)
: command_line_(command_line), content_root_(content_root) {}
Emulator::~Emulator() {
// Note that we delete things in the reverse order they were initialized.

View File

@@ -47,12 +47,16 @@ namespace xe {
// This is responsible for initializing and managing all the various subsystems.
class Emulator {
public:
explicit Emulator(const std::wstring& command_line);
explicit Emulator(const std::wstring& command_line,
const std::wstring& content_root);
~Emulator();
// Full command line used when launching the process.
const std::wstring& command_line() const { return command_line_; }
// Folder content is stored in.
const std::wstring& content_root() const { return content_root_; }
// Title of the game in the default language.
const std::wstring& game_title() const { return game_title_; }
@@ -154,6 +158,8 @@ class Emulator {
const std::string& module_path);
std::wstring command_line_;
std::wstring content_root_;
std::wstring game_title_;
ui::Window* display_window_;

View File

@@ -347,8 +347,8 @@ void CommandProcessor::MakeCoherent() {
// some way to check for dest coherency (what all the COHER_DEST_BASE_*
// registers are for).
// Best docs I've found on this are here:
// http://amd-dev.wpengine.netdna-cdn.com/wordpress/media/2013/10/R6xx_R7xx_3D.pdf
// http://cgit.freedesktop.org/xorg/driver/xf86-video-radeonhd/tree/src/r6xx_accel.c?id=3f8b6eccd9dba116cc4801e7f80ce21a879c67d2#n454
// https://web.archive.org/web/20160711162346/https://amd-dev.wpengine.netdna-cdn.com/wordpress/media/2013/10/R6xx_R7xx_3D.pdf
// https://cgit.freedesktop.org/xorg/driver/xf86-video-radeonhd/tree/src/r6xx_accel.c?id=3f8b6eccd9dba116cc4801e7f80ce21a879c67d2#n454
RegisterFile* regs = register_file_;
auto status_host = regs->values[XE_GPU_REG_COHER_STATUS_HOST].u32;
@@ -1392,7 +1392,7 @@ bool CommandProcessor::ExecutePacketType3_VIZ_QUERY(RingBuffer* reader,
uint32_t packet,
uint32_t count) {
// begin/end initiator for viz query extent processing
// http://www.google.com/patents/US20050195186
// https://www.google.com/patents/US20050195186
assert_true(count == 1);
uint32_t dword0 = reader->ReadAndSwap<uint32_t>();

View File

@@ -131,8 +131,8 @@ struct VertexData {
};
)");
// http://www.nvidia.com/object/cube_map_ogl_tutorial.html
// http://developer.amd.com/wordpress/media/2012/10/R600_Instruction_Set_Architecture.pdf
// https://www.nvidia.com/object/cube_map_ogl_tutorial.html
// https://developer.amd.com/wordpress/media/2012/10/R600_Instruction_Set_Architecture.pdf
// src0 = Rn.zzxy, src1 = Rn.yxzz
// dst.W = FaceId;
// dst.Z = 2.0f * MajorAxis;

View File

@@ -26,8 +26,8 @@ namespace gpu {
// Nvidia Optimus/AMD PowerXpress support.
// These exports force the process to trigger the discrete GPU in multi-GPU
// systems.
// http://developer.download.nvidia.com/devzone/devcenter/gamegraphics/files/OptimusRenderingPolicies.pdf
// http://stackoverflow.com/questions/17458803/amd-equivalent-to-nvoptimusenablement
// https://developer.download.nvidia.com/devzone/devcenter/gamegraphics/files/OptimusRenderingPolicies.pdf
// https://stackoverflow.com/questions/17458803/amd-equivalent-to-nvoptimusenablement
#if XE_PLATFORM_WIN32
extern "C" {
__declspec(dllexport) uint32_t NvOptimusEnablement = 0x00000001;
@@ -74,7 +74,7 @@ X_STATUS GraphicsSystem::Setup(cpu::Processor* processor,
"Ensure you have the latest drivers for your GPU and "
"that it supports Vulkan.\n"
"\n"
"See http://xenia.jp/faq/ for more information and a list of "
"See https://xenia.jp/faq/ for more information and a list of "
"supported GPUs.");
return X_STATUS_UNSUCCESSFUL;
}

View File

@@ -40,7 +40,7 @@ using namespace ucode;
// https://github.com/freedreno/freedreno/blob/master/util/disasm-a2xx.c
//
// Lots of naming comes from the disassembly spit out by the XNA GS compiler
// and dumps of d3dcompiler and games: http://pastebin.com/i4kAv7bB
// and dumps of d3dcompiler and games: https://pastebin.com/i4kAv7bB
ShaderTranslator::ShaderTranslator() = default;

View File

@@ -48,7 +48,7 @@ void CopySwapBlock(Endian endian, void* output, const void* input,
void ConvertTexelCTX1ToR8G8(Endian endian, void* output, const void* input,
size_t length) {
// http://fileadmin.cs.lth.se/cs/Personal/Michael_Doggett/talks/unc-xenos-doggett.pdf
// https://fileadmin.cs.lth.se/cs/Personal/Michael_Doggett/talks/unc-xenos-doggett.pdf
union {
uint8_t data[8];
struct {

View File

@@ -26,7 +26,7 @@ using namespace xe::gpu::xenos;
bool TextureInfo::Prepare(const xe_gpu_texture_fetch_t& fetch,
TextureInfo* out_info) {
// http://msdn.microsoft.com/en-us/library/windows/desktop/cc308051(v=vs.85).aspx
// https://msdn.microsoft.com/en-us/library/windows/desktop/cc308051(v=vs.85).aspx
// a2xx_sq_surfaceformat
std::memset(out_info, 0, sizeof(TextureInfo));

View File

@@ -103,7 +103,7 @@ int TraceDump::Main(const std::vector<std::wstring>& args) {
bool TraceDump::Setup() {
// Create the emulator but don't initialize so we can setup the window.
emulator_ = std::make_unique<Emulator>(L"");
emulator_ = std::make_unique<Emulator>(L"", L"");
X_STATUS result = emulator_->Setup(
nullptr, nullptr, [this]() { return CreateGraphicsSystem(); }, nullptr);
if (XFAILED(result)) {

View File

@@ -122,7 +122,7 @@ bool TraceViewer::Setup() {
window_->Resize(1920, 1200);
// Create the emulator but don't initialize so we can setup the window.
emulator_ = std::make_unique<Emulator>(L"");
emulator_ = std::make_unique<Emulator>(L"", L"");
X_STATUS result =
emulator_->Setup(window_.get(), nullptr,
[this]() { return CreateGraphicsSystem(); }, nullptr);

View File

@@ -17,7 +17,7 @@
#include "xenia/gpu/xenos.h"
// Closest AMD doc:
// http://developer.amd.com/wordpress/media/2012/10/R600_Instruction_Set_Architecture.pdf
// https://developer.amd.com/wordpress/media/2012/10/R600_Instruction_Set_Architecture.pdf
// Microcode format differs, but most fields/enums are the same.
// This code comes from the freedreno project:
@@ -701,7 +701,7 @@ static_assert_size(TextureFetchInstruction, 12);
// R600 docs that have a near 1:1 with the instructions available in the xenos
// GPU. Some of the behavior has been experimentally verified. Some has been
// guessed.
// Docs: http://www.x.org/docs/AMD/old/r600isa.pdf
// Docs: https://www.x.org/docs/AMD/old/r600isa.pdf
//
// Conventions:
// - All temporary registers are vec4s.

View File

@@ -660,7 +660,7 @@ bool PipelineCache::SetDynamicState(VkCommandBuffer command_buffer,
}
// Whether each of the viewport settings are enabled.
// http://www.x.org/docs/AMD/old/evergreen_3D_registers_v2.pdf
// https://www.x.org/docs/AMD/old/evergreen_3D_registers_v2.pdf
bool vport_xscale_enable = (regs.pa_cl_vte_cntl & (1 << 0)) > 0;
bool vport_xoffset_enable = (regs.pa_cl_vte_cntl & (1 << 1)) > 0;
bool vport_yscale_enable = (regs.pa_cl_vte_cntl & (1 << 2)) > 0;
@@ -865,7 +865,7 @@ bool PipelineCache::SetDynamicState(VkCommandBuffer command_buffer,
push_constants.window_scale[3] = (-1280.f / window_height_scalar) + 0.5f;
}
// http://www.x.org/docs/AMD/old/evergreen_3D_registers_v2.pdf
// https://www.x.org/docs/AMD/old/evergreen_3D_registers_v2.pdf
// VTX_XY_FMT = true: the incoming XY have already been multiplied by 1/W0.
// = false: multiply the X, Y coordinates by 1/W0.
// VTX_Z_FMT = true: the incoming Z has already been multiplied by 1/W0.

View File

@@ -786,7 +786,7 @@ bool RenderCache::ParseConfiguration(RenderConfiguration* config) {
config->mode_control = regs.rb_modecontrol.edram_mode;
// RB_SURFACE_INFO
// http://fossies.org/dox/MesaLib-10.3.5/fd2__gmem_8c_source.html
// https://fossies.org/dox/MesaLib-10.3.5/fd2__gmem_8c_source.html
config->surface_pitch_px = regs.rb_surface_info.surface_pitch;
config->surface_msaa = regs.rb_surface_info.msaa_samples;

View File

@@ -99,7 +99,7 @@ const TextureConfig texture_configs[64] = {
/* k_16_MPEG_INTERLACED */ ___(UNDEFINED),
/* k_16_16_MPEG_INTERLACED */ ___(UNDEFINED),
// http://fileadmin.cs.lth.se/cs/Personal/Michael_Doggett/talks/unc-xenos-doggett.pdf
// https://fileadmin.cs.lth.se/cs/Personal/Michael_Doggett/talks/unc-xenos-doggett.pdf
/* k_DXN */ ___(BC5_UNORM_BLOCK), // ?
/* k_8_8_8_8_AS_16_16_16_16 */ ___(R8G8B8A8_UNORM),
@@ -116,7 +116,7 @@ const TextureConfig texture_configs[64] = {
/* k_DXT3A */ _c_(BC2_UNORM_BLOCK, ___R),
/* k_DXT5A */ _c_(BC4_UNORM_BLOCK, RRRR), // ATI1N
// http://fileadmin.cs.lth.se/cs/Personal/Michael_Doggett/talks/unc-xenos-doggett.pdf
// https://fileadmin.cs.lth.se/cs/Personal/Michael_Doggett/talks/unc-xenos-doggett.pdf
/* k_CTX1 */ ___(R8G8_UINT),
/* k_DXT3A_AS_1_1_1_1 */ ___(UNDEFINED),

View File

@@ -916,7 +916,7 @@ bool VulkanCommandProcessor::IssueCopy() {
assert_true(copy_regs->copy_mask == 0);
// RB_SURFACE_INFO
// http://fossies.org/dox/MesaLib-10.3.5/fd2__gmem_8c_source.html
// https://fossies.org/dox/MesaLib-10.3.5/fd2__gmem_8c_source.html
uint32_t surface_info = regs[XE_GPU_REG_RB_SURFACE_INFO].u32;
uint32_t surface_pitch = surface_info & 0x3FFF;
auto surface_msaa = static_cast<MsaaSamples>((surface_info >> 16) & 0x3);

View File

@@ -68,7 +68,7 @@ enum class TextureSign : uint32_t {
kUnsigned = 0,
// Two's complement texture data.
kSigned = 1,
// 2*color-1 - http://xboxforums.create.msdn.com/forums/t/107374.aspx
// 2*color-1 - https://xboxforums.create.msdn.com/forums/t/107374.aspx
kUnsignedBiased = 2,
// Linearized when sampled.
kGamma = 3,

View File

@@ -70,7 +70,7 @@ struct X_INPUT_CAPABILITIES {
static_assert_size(X_INPUT_CAPABILITIES,
sizeof(X_INPUT_GAMEPAD) + sizeof(X_INPUT_VIBRATION) + 4);
// http://msdn.microsoft.com/en-us/library/windows/desktop/microsoft.directx_sdk.reference.xinput_keystroke(v=vs.85).aspx
// https://msdn.microsoft.com/en-us/library/windows/desktop/microsoft.directx_sdk.reference.xinput_keystroke(v=vs.85).aspx
struct X_INPUT_KEYSTROKE {
be<uint16_t> virtual_key;
be<uint16_t> unicode;

View File

@@ -20,33 +20,65 @@ namespace xe {
namespace hid {
namespace xinput {
// TODO(Triang3l): Find why XInputEnable is deprecated on Windows 10.
#pragma warning(push)
#pragma warning(disable : 4995)
XInputInputDriver::XInputInputDriver(xe::ui::Window* window)
: InputDriver(window) {
#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8 && _WIN32_WINNT < _WIN32_WINNT_WIN10)
// TODO(gibbed): Is this necessary?
XInputEnable(TRUE);
#endif
}
: InputDriver(window),
module_(nullptr),
XInputGetCapabilities_(nullptr),
XInputGetState_(nullptr),
XInputGetKeystroke_(nullptr),
XInputSetState_(nullptr),
XInputEnable_(nullptr) {}
XInputInputDriver::~XInputInputDriver() {
#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8 && _WIN32_WINNT < _WIN32_WINNT_WIN10)
// TODO(gibbed): Is this necessary?
XInputEnable(FALSE);
#endif
if (module_) {
FreeLibrary((HMODULE)module_);
module_ = nullptr;
XInputGetCapabilities_ = nullptr;
XInputGetState_ = nullptr;
XInputGetKeystroke_ = nullptr;
XInputSetState_ = nullptr;
XInputEnable_ = nullptr;
}
}
#pragma warning(pop)
X_STATUS XInputInputDriver::Setup() {
HMODULE module = LoadLibraryW(L"xinput1_4.dll");
if (!module) {
module = LoadLibraryW(L"xinput1_3.dll");
}
if (!module) {
return X_STATUS_DLL_NOT_FOUND;
}
X_STATUS XInputInputDriver::Setup() { return X_STATUS_SUCCESS; }
// Required.
auto xigc = GetProcAddress(module, "XInputGetCapabilities");
auto xigs = GetProcAddress(module, "XInputGetState");
auto xigk = GetProcAddress(module, "XInputGetKeystroke");
auto xiss = GetProcAddress(module, "XInputSetState");
// Not required.
auto xie = GetProcAddress(module, "XInputEnable");
// Only fail when we don't have the bare essentials;
if (!xigc || !xigs || !xigk || !xiss) {
FreeLibrary(module);
return X_STATUS_PROCEDURE_NOT_FOUND;
}
module_ = module;
XInputGetCapabilities_ = xigc;
XInputGetState_ = xigs;
XInputGetKeystroke_ = xigk;
XInputSetState_ = xiss;
XInputEnable_ = xie;
return X_STATUS_SUCCESS;
}
X_RESULT XInputInputDriver::GetCapabilities(uint32_t user_index, uint32_t flags,
X_INPUT_CAPABILITIES* out_caps) {
XINPUT_CAPABILITIES native_caps;
DWORD result = XInputGetCapabilities(user_index, flags, &native_caps);
auto xigc = (decltype(&XInputGetCapabilities))XInputGetCapabilities_;
DWORD result = xigc(user_index, flags, &native_caps);
if (result) {
return result;
}
@@ -71,7 +103,8 @@ X_RESULT XInputInputDriver::GetCapabilities(uint32_t user_index, uint32_t flags,
X_RESULT XInputInputDriver::GetState(uint32_t user_index,
X_INPUT_STATE* out_state) {
XINPUT_STATE native_state;
DWORD result = XInputGetState(user_index, &native_state);
auto xigs = (decltype(&XInputGetState))XInputGetState_;
DWORD result = xigs(user_index, &native_state);
if (result) {
return result;
}
@@ -93,7 +126,8 @@ X_RESULT XInputInputDriver::SetState(uint32_t user_index,
XINPUT_VIBRATION native_vibration;
native_vibration.wLeftMotorSpeed = vibration->left_motor_speed;
native_vibration.wRightMotorSpeed = vibration->right_motor_speed;
DWORD result = XInputSetState(user_index, &native_vibration);
auto xiss = (decltype(&XInputSetState))XInputSetState_;
DWORD result = xiss(user_index, &native_vibration);
return result;
}
@@ -105,18 +139,20 @@ X_RESULT XInputInputDriver::GetKeystroke(uint32_t user_index, uint32_t flags,
// XInputGetKeystroke on Windows has a bug where it will return
// ERROR_SUCCESS (0) even if the device is not connected:
// http://stackoverflow.com/questions/23669238/xinputgetkeystroke-returning-error-success-while-controller-is-unplugged
// https://stackoverflow.com/questions/23669238/xinputgetkeystroke-returning-error-success-while-controller-is-unplugged
//
// So we first check if the device is connected via XInputGetCapabilities, so
// we are not passing back an uninitialized X_INPUT_KEYSTROKE structure:
XINPUT_CAPABILITIES caps;
result = XInputGetCapabilities(user_index, 0, &caps);
auto xigc = (decltype(&XInputGetCapabilities))XInputGetCapabilities_;
result = xigc(user_index, 0, &caps);
if (result) {
return result;
}
XINPUT_KEYSTROKE native_keystroke;
result = XInputGetKeystroke(user_index, 0, &native_keystroke);
auto xigk = (decltype(&XInputGetKeystroke))XInputGetKeystroke_;
result = xigk(user_index, 0, &native_keystroke);
if (result) {
return result;
}

View File

@@ -31,6 +31,12 @@ class XInputInputDriver : public InputDriver {
X_INPUT_KEYSTROKE* out_keystroke) override;
protected:
void* module_;
void* XInputGetCapabilities_;
void* XInputGetState_;
void* XInputGetKeystroke_;
void* XInputSetState_;
void* XInputEnable_;
};
} // namespace xinput

View File

@@ -31,8 +31,6 @@
DEFINE_bool(headless, false,
"Don't display any UI, using defaults for prompts as needed.");
DEFINE_string(content_root, "content",
"Root path for content (save/etc) storage.");
namespace xe {
namespace kernel {
@@ -57,7 +55,7 @@ KernelState::KernelState(Emulator* emulator)
app_manager_ = std::make_unique<xam::AppManager>();
user_profile_ = std::make_unique<xam::UserProfile>();
auto content_root = xe::to_wstring(FLAGS_content_root);
auto content_root = emulator_->content_root();
content_root = xe::to_absolute_path(content_root);
content_manager_ = std::make_unique<xam::ContentManager>(this, content_root);
@@ -581,7 +579,7 @@ void KernelState::RegisterNotifyListener(NotifyListener* listener) {
// Games seem to expect a few notifications on startup, only for the first
// listener.
// http://cs.rin.ru/forum/viewtopic.php?f=38&t=60668&hilit=resident+evil+5&start=375
// https://cs.rin.ru/forum/viewtopic.php?f=38&t=60668&hilit=resident+evil+5&start=375
if (!has_notified_startup_ && listener->mask() & 0x00000001) {
has_notified_startup_ = true;
// XN_SYS_UI (on, off)

View File

@@ -19,8 +19,8 @@ namespace xe {
namespace kernel {
namespace util {
// http://freestyledash.googlecode.com/svn/trunk/Freestyle/Tools/XEX/SPA.h
// http://freestyledash.googlecode.com/svn/trunk/Freestyle/Tools/XEX/SPA.cpp
// https://github.com/oukiar/freestyledash/blob/master/Freestyle/Tools/XEX/SPA.h
// https://github.com/oukiar/freestyledash/blob/master/Freestyle/Tools/XEX/SPA.cpp
enum class XdbfSection : uint16_t {
kMetadata = 0x0001,
@@ -49,7 +49,7 @@ struct XdbfBlock {
};
// Wraps an XBDF (XboxDataBaseFormat) in-memory database.
// http://www.free60.org/wiki/XDBF
// https://free60project.github.io/wiki/XDBF.html
class XdbfWrapper {
public:
XdbfWrapper(const uint8_t* data, size_t data_size);

View File

@@ -25,7 +25,7 @@ namespace xam {
namespace apps {
// Only source of docs for a lot of these functions:
// http://freestyledash.googlecode.com/svn-history/r1/trunk/Freestyle/Scenes/Media/Music/ScnMusic.cpp
// https://github.com/oukiar/freestyledash/blob/master/Freestyle/Scenes/Media/Music/ScnMusic.cpp
class XmpApp : public App {
public:

View File

@@ -23,6 +23,8 @@ namespace xam {
static const wchar_t* kThumbnailFileName = L"__thumbnail.png";
static const wchar_t* kGameUserContentDirName = L"profile";
static int content_device_id_ = 0;
ContentPackage::ContentPackage(KernelState* kernel_state, std::string root_name,
@@ -252,6 +254,20 @@ X_RESULT ContentManager::DeleteContent(const XCONTENT_DATA& data) {
}
}
std::wstring ContentManager::ResolveGameUserContentPath() {
wchar_t title_id[9] = L"00000000";
std::swprintf(title_id, 9, L"%.8X", kernel_state_->title_id());
auto user_name = xe::to_wstring(kernel_state_->user_profile()->name());
// Per-game per-profile data location:
// content_root/title_id/profile/user_name
auto package_root = xe::join_paths(
root_path_,
xe::join_paths(title_id,
xe::join_paths(kGameUserContentDirName, user_name)));
return package_root + xe::kWPathSeparator;
}
} // namespace xam
} // namespace kernel
} // namespace xe

View File

@@ -84,6 +84,7 @@ class ContentManager {
X_RESULT SetContentThumbnail(const XCONTENT_DATA& data,
std::vector<uint8_t> buffer);
X_RESULT DeleteContent(const XCONTENT_DATA& data);
std::wstring ResolveGameUserContentPath();
private:
std::wstring ResolvePackageRoot(uint32_t content_type);

View File

@@ -7,6 +7,10 @@
******************************************************************************
*/
#include <sstream>
#include "xenia/kernel/kernel_state.h"
#include "xenia/kernel/util/shim_utils.h"
#include "xenia/kernel/xam/user_profile.h"
namespace xe {
@@ -17,7 +21,7 @@ UserProfile::UserProfile() {
xuid_ = 0xBABEBABEBABEBABE;
name_ = "User";
// http://cs.rin.ru/forum/viewtopic.php?f=38&t=60668&hilit=gfwl+live&start=195
// https://cs.rin.ru/forum/viewtopic.php?f=38&t=60668&hilit=gfwl+live&start=195
// https://github.com/arkem/py360/blob/master/py360/constants.py
// XPROFILE_GAMER_YAXIS_INVERSION
AddSetting(std::make_unique<Int32Setting>(0x10040002, 0));
@@ -87,6 +91,10 @@ void UserProfile::AddSetting(std::unique_ptr<Setting> setting) {
Setting* previous_setting = setting.get();
std::swap(settings_[setting->setting_id], previous_setting);
if (setting->is_set && setting->is_title_specific()) {
SaveSetting(setting.get());
}
if (previous_setting) {
// replace: swap out the old setting from the owning list
for (auto vec_it = setting_list_.begin(); vec_it != setting_list_.end();
@@ -107,7 +115,58 @@ UserProfile::Setting* UserProfile::GetSetting(uint32_t setting_id) {
if (it == settings_.end()) {
return nullptr;
}
return it->second;
UserProfile::Setting* setting = it->second;
if (setting->is_title_specific()) {
// If what we have loaded in memory isn't for the title that is running
// right now, then load it from disk.
if (kernel_state()->title_id() != setting->loaded_title_id) {
LoadSetting(setting);
}
}
return setting;
}
void UserProfile::LoadSetting(UserProfile::Setting* setting) {
if (setting->is_title_specific()) {
auto content_dir =
kernel_state()->content_manager()->ResolveGameUserContentPath();
auto setting_id = xe::format_string(L"%.8X", setting->setting_id);
auto file_path = xe::join_paths(content_dir, setting_id);
auto file = xe::filesystem::OpenFile(file_path, "rb");
if (file) {
fseek(file, 0, SEEK_END);
uint32_t input_file_size = static_cast<uint32_t>(ftell(file));
fseek(file, 0, SEEK_SET);
std::vector<uint8_t> serialized_data(input_file_size);
fread(serialized_data.data(), 1, serialized_data.size(), file);
fclose(file);
setting->Deserialize(serialized_data);
setting->loaded_title_id = kernel_state()->title_id();
}
} else {
// Unsupported for now. Other settings aren't per-game and need to be
// stored some other way.
XELOGW("Attempting to load unsupported profile setting from disk");
}
}
void UserProfile::SaveSetting(UserProfile::Setting* setting) {
if (setting->is_title_specific()) {
auto serialized_setting = setting->Serialize();
auto content_dir =
kernel_state()->content_manager()->ResolveGameUserContentPath();
xe::filesystem::CreateFolder(content_dir);
auto setting_id = xe::format_string(L"%.8X", setting->setting_id);
auto file_path = xe::join_paths(content_dir, setting_id);
auto file = xe::filesystem::OpenFile(file_path, "wb");
fwrite(serialized_setting.data(), 1, serialized_setting.size(), file);
fclose(file);
} else {
// Unsupported for now. Other settings aren't per-game and need to be
// stored some other way.
XELOGW("Attempting to save unsupported profile setting to disk");
}
}
} // namespace xam

View File

@@ -25,7 +25,7 @@ class UserProfile {
public:
struct Setting {
enum class Type {
UNKNOWN = 0,
CONTENT = 0,
INT32 = 1,
INT64 = 2,
DOUBLE = 3,
@@ -48,8 +48,13 @@ class UserProfile {
Type type;
size_t size;
bool is_set;
uint32_t loaded_title_id;
Setting(uint32_t setting_id, Type type, size_t size, bool is_set)
: setting_id(setting_id), type(type), size(size), is_set(is_set) {}
: setting_id(setting_id),
type(type),
size(size),
is_set(is_set),
loaded_title_id(0) {}
virtual size_t extra_size() const { return 0; }
virtual size_t Append(uint8_t* user_data, uint8_t* buffer,
uint32_t buffer_ptr, size_t buffer_offset) {
@@ -57,6 +62,10 @@ class UserProfile {
static_cast<uint8_t>(type));
return buffer_offset;
}
virtual std::vector<uint8_t> Serialize() const {
return std::vector<uint8_t>();
}
virtual void Deserialize(std::vector<uint8_t>) {}
bool is_title_specific() const { return (setting_id & 0x3F00) == 0x3F00; }
protected:
@@ -167,6 +176,13 @@ class UserProfile {
}
return buffer_offset + length;
}
std::vector<uint8_t> Serialize() const override {
return std::vector<uint8_t>(value.data(), value.data() + value.size());
}
void Deserialize(std::vector<uint8_t> data) override {
value = data;
is_set = true;
}
};
struct DateTimeSetting : public Setting {
DateTimeSetting(uint32_t setting_id, int64_t value)
@@ -195,6 +211,9 @@ class UserProfile {
std::string name_;
std::vector<std::unique_ptr<Setting>> setting_list_;
std::unordered_map<uint32_t, Setting*> settings_;
void LoadSetting(UserProfile::Setting*);
void SaveSetting(UserProfile::Setting*);
};
} // namespace xam

View File

@@ -128,7 +128,7 @@ dword_result_t XamContentResolve(dword_t user_index, lpvoid_t content_data_ptr,
}
DECLARE_XAM_EXPORT1(XamContentResolve, kContent, kStub);
// http://gameservice.googlecode.com/svn-history/r14/trunk/ContentManager.cpp
// https://github.com/MrColdbird/gameservice/blob/master/ContentManager.cpp
// https://github.com/LestaD/SourceEngine2007/blob/master/se2007/engine/xboxsystem.cpp#L499
dword_result_t XamContentCreateEnumerator(dword_t user_index, dword_t device_id,
dword_t content_type,

View File

@@ -88,32 +88,28 @@ DECLARE_XAM_EXPORT1(XamGetExecutionId, kNone, kImplemented);
dword_result_t XamLoaderSetLaunchData(lpvoid_t data, dword_t size) {
auto xam = kernel_state()->GetKernelModule<XamModule>("xam.xex");
auto& loader_data = xam->loader_data();
loader_data.launch_data_present = size ? true : false;
loader_data.launch_data.resize(size);
std::memcpy(loader_data.launch_data.data(), data, size);
// FIXME: Unknown return value.
return 0;
}
DECLARE_XAM_EXPORT1(XamLoaderSetLaunchData, kNone, kSketchy);
dword_result_t XamLoaderGetLaunchDataSize(lpdword_t size_ptr) {
auto xam = kernel_state()->GetKernelModule<XamModule>("xam.xex");
auto& loader_data = xam->loader_data();
if (!size_ptr) {
return X_ERROR_INVALID_PARAMETER;
}
if (loader_data.launch_data_present) {
*size_ptr = uint32_t(xam->loader_data().launch_data.size());
return X_ERROR_SUCCESS;
auto xam = kernel_state()->GetKernelModule<XamModule>("xam.xex");
auto& loader_data = xam->loader_data();
if (!loader_data.launch_data_present) {
*size_ptr = 0;
return X_ERROR_NOT_FOUND;
}
*size_ptr = 0;
return X_ERROR_NOT_FOUND;
*size_ptr = uint32_t(xam->loader_data().launch_data.size());
return X_ERROR_SUCCESS;
}
DECLARE_XAM_EXPORT1(XamLoaderGetLaunchDataSize, kNone, kSketchy);
@@ -202,18 +198,26 @@ dword_result_t XamEnumerate(dword_t handle, dword_t flags, lpvoid_t buffer,
}
}
buffer.Zero(buffer_length);
size_t actual_buffer_length = e->item_size() * e->items_per_enumerate();
if (actual_buffer_length != buffer_length) {
// Known culprits:
// Final Fight: Double Impact
XELOGW("Broken usage of XamEnumerate! %.X vs %.X", buffer_length,
actual_buffer_length);
}
buffer.Zero(actual_buffer_length);
X_RESULT result;
uint32_t item_count = 0;
if (buffer_length < e->item_size()) {
if (actual_buffer_length < e->item_size()) {
result = X_ERROR_INSUFFICIENT_BUFFER;
} else if (e->current_item() >= e->item_count()) {
result = X_ERROR_NO_MORE_FILES;
} else {
auto item_buffer = buffer.as<uint8_t*>();
auto max_items = buffer_length / e->item_size();
auto max_items = actual_buffer_length / e->item_size();
while (max_items--) {
if (!e->WriteItem(item_buffer)) {
break;

View File

@@ -38,7 +38,7 @@ dword_result_t XamEnableInactivityProcessing(dword_t unk, dword_t enable) {
}
DECLARE_XAM_EXPORT1(XamEnableInactivityProcessing, kInput, kStub);
// http://msdn.microsoft.com/en-us/library/windows/desktop/microsoft.directx_sdk.reference.xinputgetcapabilities(v=vs.85).aspx
// https://msdn.microsoft.com/en-us/library/windows/desktop/microsoft.directx_sdk.reference.xinputgetcapabilities(v=vs.85).aspx
dword_result_t XamInputGetCapabilities(dword_t user_index, dword_t flags,
pointer_t<X_INPUT_CAPABILITIES> caps) {
if (!caps) {
@@ -84,7 +84,7 @@ dword_result_t XamInputGetCapabilitiesEx(dword_t unk, dword_t user_index,
}
DECLARE_XAM_EXPORT1(XamInputGetCapabilitiesEx, kInput, kSketchy);
// http://msdn.microsoft.com/en-us/library/windows/desktop/microsoft.directx_sdk.reference.xinputgetstate(v=vs.85).aspx
// https://msdn.microsoft.com/en-us/library/windows/desktop/microsoft.directx_sdk.reference.xinputgetstate(v=vs.85).aspx
dword_result_t XamInputGetState(dword_t user_index, dword_t flags,
pointer_t<X_INPUT_STATE> input_state) {
// Games call this with a NULL state ptr, probably as a query.
@@ -105,7 +105,7 @@ dword_result_t XamInputGetState(dword_t user_index, dword_t flags,
}
DECLARE_XAM_EXPORT1(XamInputGetState, kInput, kImplemented);
// http://msdn.microsoft.com/en-us/library/windows/desktop/microsoft.directx_sdk.reference.xinputsetstate(v=vs.85).aspx
// https://msdn.microsoft.com/en-us/library/windows/desktop/microsoft.directx_sdk.reference.xinputsetstate(v=vs.85).aspx
dword_result_t XamInputSetState(dword_t user_index, dword_t unk,
pointer_t<X_INPUT_VIBRATION> vibration) {
if (!vibration) {
@@ -123,10 +123,10 @@ dword_result_t XamInputSetState(dword_t user_index, dword_t unk,
}
DECLARE_XAM_EXPORT1(XamInputSetState, kInput, kImplemented);
// http://msdn.microsoft.com/en-us/library/windows/desktop/microsoft.directx_sdk.reference.xinputgetkeystroke(v=vs.85).aspx
// https://msdn.microsoft.com/en-us/library/windows/desktop/microsoft.directx_sdk.reference.xinputgetkeystroke(v=vs.85).aspx
dword_result_t XamInputGetKeystroke(dword_t user_index, dword_t flags,
pointer_t<X_INPUT_KEYSTROKE> keystroke) {
// http://ffplay360.googlecode.com/svn/Test/Common/AtgXime.cpp
// https://github.com/CodeAsm/ffplay360/blob/master/Common/AtgXime.cpp
// user index = index or XUSER_INDEX_ANY
// flags = XINPUT_FLAG_GAMEPAD (| _ANYUSER | _ANYDEVICE)

View File

@@ -483,7 +483,7 @@ dword_result_t NetDll_XNetInAddrToXnAddr(dword_t caller, lpvoid_t in_addr,
}
DECLARE_XAM_EXPORT1(NetDll_XNetInAddrToXnAddr, kNetworking, kStub);
// http://www.google.com/patents/WO2008112448A1?cl=en
// https://www.google.com/patents/WO2008112448A1?cl=en
// Reserves a port for use by system link
dword_result_t NetDll_XNetSetSystemLinkPort(dword_t caller, dword_t port) {
return 1;

View File

@@ -32,7 +32,7 @@ dword_result_t XamNotifyCreateListener(qword_t mask, dword_t one) {
}
DECLARE_XAM_EXPORT1(XamNotifyCreateListener, kNone, kImplemented);
// http://ffplay360.googlecode.com/svn/Test/Common/AtgSignIn.cpp
// https://github.com/CodeAsm/ffplay360/blob/master/Common/AtgSignIn.cpp
dword_result_t XNotifyGetNext(dword_t handle, dword_t match_id,
lpdword_t id_ptr, lpdword_t param_ptr) {
if (!handle) {

View File

@@ -83,7 +83,7 @@ class MessageBoxDialog : public xe::ui::ImGuiDialog {
uint32_t* out_chosen_button_ = nullptr;
};
// http://www.se7ensins.com/forums/threads/working-xshowmessageboxui.844116/?jdfwkey=sb0vm
// https://www.se7ensins.com/forums/threads/working-xshowmessageboxui.844116/
dword_result_t XamShowMessageBoxUI(dword_t user_index, lpwstring_t title_ptr,
lpwstring_t text_ptr, dword_t button_count,
lpdword_t button_ptrs, dword_t active_button,
@@ -221,7 +221,7 @@ class KeyboardInputDialog : public xe::ui::ImGuiDialog {
size_t max_length_ = 0;
};
// http://www.se7ensins.com/forums/threads/release-how-to-use-xshowkeyboardui-release.906568/
// https://www.se7ensins.com/forums/threads/release-how-to-use-xshowkeyboardui-release.906568/
dword_result_t XamShowKeyboardUI(dword_t user_index, dword_t flags,
lpwstring_t default_text, lpwstring_t title,
lpwstring_t description, lpwstring_t buffer,

View File

@@ -108,7 +108,7 @@ typedef struct {
} X_USER_READ_PROFILE_SETTING;
static_assert_size(X_USER_READ_PROFILE_SETTING, 40);
// http://freestyledash.googlecode.com/svn/trunk/Freestyle/Tools/Generic/xboxtools.cpp
// https://github.com/oukiar/freestyledash/blob/master/Freestyle/Tools/Generic/xboxtools.cpp
dword_result_t XamUserReadProfileSettings(
dword_t title_id, dword_t user_index, dword_t unk_0, dword_t unk_1,
dword_t setting_count, lpdword_t setting_ids, lpdword_t buffer_size_ptr,
@@ -285,6 +285,7 @@ dword_result_t XamUserWriteProfileSettings(
static_cast<xam::UserProfile::Setting::Type>(settings_data.type);
switch (settingType) {
case UserProfile::Setting::Type::CONTENT:
case UserProfile::Setting::Type::BINARY: {
uint8_t* settings_data_ptr = kernel_state()->memory()->TranslateVirtual(
settings_data.binary.ptr);

View File

@@ -71,7 +71,7 @@ void RtlRaiseException(pointer_t<X_EXCEPTION_RECORD> record) {
if (record->exception_code == 0xE06D7363) {
// C++ exception.
// http://blogs.msdn.com/b/oldnewthing/archive/2010/07/30/10044061.aspx
// https://blogs.msdn.com/b/oldnewthing/archive/2010/07/30/10044061.aspx
xe::debugging::Break();
return;
}

View File

@@ -24,7 +24,7 @@ namespace xe {
namespace kernel {
namespace xboxkrnl {
// http://msdn.microsoft.com/en-us/library/windows/hardware/ff540287.aspx
// https://msdn.microsoft.com/en-us/library/windows/hardware/ff540287.aspx
struct X_FILE_FS_VOLUME_INFORMATION {
// FILE_FS_VOLUME_INFORMATION
xe::be<uint64_t> creation_time;
@@ -45,7 +45,7 @@ struct X_FILE_FS_SIZE_INFORMATION {
};
static_assert_size(X_FILE_FS_SIZE_INFORMATION, 24);
// http://msdn.microsoft.com/en-us/library/windows/hardware/ff540251(v=vs.85).aspx
// https://msdn.microsoft.com/en-us/library/windows/hardware/ff540251(v=vs.85).aspx
struct X_FILE_FS_ATTRIBUTE_INFORMATION {
// FILE_FS_ATTRIBUTE_INFORMATION
xe::be<uint32_t> attributes;
@@ -56,7 +56,7 @@ struct X_FILE_FS_ATTRIBUTE_INFORMATION {
static_assert_size(X_FILE_FS_ATTRIBUTE_INFORMATION, 16);
struct CreateOptions {
// http://processhacker.sourceforge.net/doc/ntioapi_8h.html
// https://processhacker.sourceforge.io/doc/ntioapi_8h.html
static const uint32_t FILE_DIRECTORY_FILE = 0x00000001;
// Optimization - files access will be sequential, not random.
static const uint32_t FILE_SEQUENTIAL_ONLY = 0x00000004;

View File

@@ -371,7 +371,8 @@ dword_result_t MmQueryAddressProtect(dword_t base_address) {
return access;
}
DECLARE_XBOXKRNL_EXPORT1(MmQueryAddressProtect, kMemory, kImplemented);
DECLARE_XBOXKRNL_EXPORT2(MmQueryAddressProtect, kMemory, kImplemented,
kHighFrequency);
void MmSetAddressProtect(lpvoid_t base_address, dword_t region_size,
dword_t protect_bits) {
@@ -495,7 +496,7 @@ dword_result_t MmQueryStatistics(
}
DECLARE_XBOXKRNL_EXPORT1(MmQueryStatistics, kMemory, kImplemented);
// http://msdn.microsoft.com/en-us/library/windows/hardware/ff554547(v=vs.85).aspx
// https://msdn.microsoft.com/en-us/library/windows/hardware/ff554547(v=vs.85).aspx
dword_result_t MmGetPhysicalAddress(dword_t base_address) {
// PHYSICAL_ADDRESS MmGetPhysicalAddress(
// _In_ PVOID BaseAddress

View File

@@ -26,8 +26,8 @@ X_STATUS xeExGetXConfigSetting(uint16_t category, uint16_t setting,
uint32_t value = 0;
// TODO(benvanik): have real structs here that just get copied from.
// http://free60.org/XConfig
// http://freestyledash.googlecode.com/svn/trunk/Freestyle/Tools/Generic/ExConfig.h
// https://free60project.github.io/wiki/XConfig.html
// https://github.com/oukiar/freestyledash/blob/master/Freestyle/Tools/Generic/ExConfig.h
switch (category) {
case 0x0002:
// XCONFIG_SECURED_CATEGORY

View File

@@ -33,7 +33,7 @@ namespace xe {
namespace kernel {
namespace xboxkrnl {
// http://msdn.microsoft.com/en-us/library/ff561778
// https://msdn.microsoft.com/en-us/library/ff561778
dword_result_t RtlCompareMemory(lpvoid_t source1, lpvoid_t source2,
dword_t length) {
uint8_t* p1 = source1;
@@ -54,7 +54,7 @@ dword_result_t RtlCompareMemory(lpvoid_t source1, lpvoid_t source2,
}
DECLARE_XBOXKRNL_EXPORT1(RtlCompareMemory, kMemory, kImplemented);
// http://msdn.microsoft.com/en-us/library/ff552123
// https://msdn.microsoft.com/en-us/library/ff552123
dword_result_t RtlCompareMemoryUlong(lpvoid_t source, dword_t length,
dword_t pattern) {
// Return 0 if source/length not aligned
@@ -75,7 +75,7 @@ dword_result_t RtlCompareMemoryUlong(lpvoid_t source, dword_t length,
}
DECLARE_XBOXKRNL_EXPORT1(RtlCompareMemoryUlong, kMemory, kImplemented);
// http://msdn.microsoft.com/en-us/library/ff552263
// https://msdn.microsoft.com/en-us/library/ff552263
void RtlFillMemoryUlong(lpvoid_t destination, dword_t length, dword_t pattern) {
// NOTE: length must be % 4, so we can work on uint32s.
uint32_t count = length >> 2;
@@ -138,7 +138,7 @@ dword_result_t RtlCompareStringN(lpstring_t string_1, dword_t string_1_len,
}
DECLARE_XBOXKRNL_EXPORT1(RtlCompareStringN, kNone, kImplemented);
// http://msdn.microsoft.com/en-us/library/ff561918
// https://msdn.microsoft.com/en-us/library/ff561918
void RtlInitAnsiString(pointer_t<X_ANSI_STRING> destination,
lpstring_t source) {
if (source) {
@@ -153,7 +153,7 @@ void RtlInitAnsiString(pointer_t<X_ANSI_STRING> destination,
}
DECLARE_XBOXKRNL_EXPORT1(RtlInitAnsiString, kNone, kImplemented);
// http://msdn.microsoft.com/en-us/library/ff561899
// https://msdn.microsoft.com/en-us/library/ff561899
void RtlFreeAnsiString(pointer_t<X_ANSI_STRING> string) {
if (string->pointer) {
kernel_memory()->SystemHeapFree(string->pointer);
@@ -163,7 +163,7 @@ void RtlFreeAnsiString(pointer_t<X_ANSI_STRING> string) {
}
DECLARE_XBOXKRNL_EXPORT1(RtlFreeAnsiString, kNone, kImplemented);
// http://msdn.microsoft.com/en-us/library/ff561934
// https://msdn.microsoft.com/en-us/library/ff561934
void RtlInitUnicodeString(pointer_t<X_UNICODE_STRING> destination,
lpwstring_t source) {
if (source) {
@@ -176,7 +176,7 @@ void RtlInitUnicodeString(pointer_t<X_UNICODE_STRING> destination,
}
DECLARE_XBOXKRNL_EXPORT1(RtlInitUnicodeString, kNone, kImplemented);
// http://msdn.microsoft.com/en-us/library/ff561903
// https://msdn.microsoft.com/en-us/library/ff561903
void RtlFreeUnicodeString(pointer_t<X_UNICODE_STRING> string) {
if (string->pointer) {
kernel_memory()->SystemHeapFree(string->pointer);
@@ -220,7 +220,7 @@ void RtlCopyUnicodeString(pointer_t<X_UNICODE_STRING> destination,
}
DECLARE_XBOXKRNL_EXPORT1(RtlCopyUnicodeString, kNone, kImplemented);
// http://msdn.microsoft.com/en-us/library/ff562969
// https://msdn.microsoft.com/en-us/library/ff562969
dword_result_t RtlUnicodeStringToAnsiString(
pointer_t<X_ANSI_STRING> destination_ptr,
pointer_t<X_UNICODE_STRING> source_ptr, dword_t alloc_dest) {
@@ -332,9 +332,10 @@ DECLARE_XBOXKRNL_EXPORT1(RtlImageXexHeaderField, kNone, kImplemented);
// into guest memory, as it should be opaque and so long as our size is right
// the user code will never know.
//
// Ref: http://msdn.microsoft.com/en-us/magazine/cc164040.aspx
// Ref:
// http://svn.reactos.org/svn/reactos/trunk/reactos/lib/rtl/critical.c?view=markup
// https://web.archive.org/web/20161214022602/https://msdn.microsoft.com/en-us/magazine/cc164040.aspx
// Ref:
// https://github.com/reactos/reactos/blob/master/sdk/lib/rtl/critical.c
// This structure tries to match the one on the 360 as best I can figure out.
// Unfortunately some games have the critical sections pre-initialized in

View File

@@ -313,7 +313,7 @@ void KeQuerySystemTime(lpqword_t time_ptr) {
}
DECLARE_XBOXKRNL_EXPORT1(KeQuerySystemTime, kThreading, kImplemented);
// http://msdn.microsoft.com/en-us/library/ms686801
// https://msdn.microsoft.com/en-us/library/ms686801
dword_result_t KeTlsAlloc() {
uint32_t slot = kernel_state()->AllocateTLS();
XThread::GetCurrentThread()->SetTLSValue(slot, 0);
@@ -322,7 +322,7 @@ dword_result_t KeTlsAlloc() {
}
DECLARE_XBOXKRNL_EXPORT1(KeTlsAlloc, kThreading, kImplemented);
// http://msdn.microsoft.com/en-us/library/ms686804
// https://msdn.microsoft.com/en-us/library/ms686804
dword_result_t KeTlsFree(dword_t tls_index) {
if (tls_index == X_TLS_OUT_OF_INDEXES) {
return 0;
@@ -333,7 +333,7 @@ dword_result_t KeTlsFree(dword_t tls_index) {
}
DECLARE_XBOXKRNL_EXPORT1(KeTlsFree, kThreading, kImplemented);
// http://msdn.microsoft.com/en-us/library/ms686812
// https://msdn.microsoft.com/en-us/library/ms686812
dword_result_t KeTlsGetValue(dword_t tls_index) {
// xboxkrnl doesn't actually have an error branch - it always succeeds, even
// if it overflows the TLS.
@@ -347,7 +347,7 @@ dword_result_t KeTlsGetValue(dword_t tls_index) {
DECLARE_XBOXKRNL_EXPORT2(KeTlsGetValue, kThreading, kImplemented,
kHighFrequency);
// http://msdn.microsoft.com/en-us/library/ms686818
// https://msdn.microsoft.com/en-us/library/ms686818
dword_result_t KeTlsSetValue(dword_t tls_index, dword_t tls_value) {
// xboxkrnl doesn't actually have an error branch - it always succeeds, even
// if it overflows the TLS.
@@ -625,8 +625,6 @@ dword_result_t NtReleaseMutant(dword_t mutant_handle, dword_t unknown) {
bool abandon = false;
bool wait = false;
XELOGD("NtReleaseMutant(%.8X, %.8X)", mutant_handle, unknown);
X_STATUS result = X_STATUS_SUCCESS;
auto mutant =

View File

@@ -24,17 +24,17 @@ namespace xe {
namespace kernel {
namespace xboxkrnl {
// http://www.tweakoz.com/orkid/
// https://web.archive.org/web/20150805074003/https://www.tweakoz.com/orkid/
// http://www.tweakoz.com/orkid/dox/d3/d52/xb360init_8cpp_source.html
// https://github.com/Free60Project/xenosfb/
// https://github.com/Free60Project/xenosfb/blob/master/src/xe.h
// https://github.com/gligli/libxemit
// http://web.archive.org/web/20090428095215/http://msdn.microsoft.com/en-us/library/bb313877.aspx
// http://web.archive.org/web/20100423054747/http://msdn.microsoft.com/en-us/library/bb313961.aspx
// http://web.archive.org/web/20100423054747/http://msdn.microsoft.com/en-us/library/bb313878.aspx
// http://web.archive.org/web/20090510235238/http://msdn.microsoft.com/en-us/library/bb313942.aspx
// http://svn.dd-wrt.com/browser/src/linux/universal/linux-3.8/drivers/gpu/drm/radeon/radeon_ring.c
// http://www.microsoft.com/en-za/download/details.aspx?id=5313 -- "Stripped
// https://web.archive.org/web/20090428095215/https://msdn.microsoft.com/en-us/library/bb313877.aspx
// https://web.archive.org/web/20100423054747/https://msdn.microsoft.com/en-us/library/bb313961.aspx
// https://web.archive.org/web/20100423054747/https://msdn.microsoft.com/en-us/library/bb313878.aspx
// https://web.archive.org/web/20090510235238/https://msdn.microsoft.com/en-us/library/bb313942.aspx
// https://svn.dd-wrt.com/browser/src/linux/universal/linux-3.8/drivers/gpu/drm/radeon/radeon_ring.c?rev=21595
// https://www.microsoft.com/en-za/download/details.aspx?id=5313 -- "Stripped
// Down Direct3D: Xbox 360 Command Buffer and Resource Management"
void VdGetCurrentDisplayGamma(lpdword_t type_ptr, lpfloat_t unknown_ptr) {

View File

@@ -17,7 +17,7 @@
namespace xe {
namespace kernel {
// http://www.nirsoft.net/kernel_struct/vista/KEVENT.html
// https://www.nirsoft.net/kernel_struct/vista/KEVENT.html
struct X_KEVENT {
X_DISPATCH_HEADER header;
};

View File

@@ -19,7 +19,7 @@
namespace xe {
namespace kernel {
// http://www.nirsoft.net/kernel_struct/vista/LDR_DATA_TABLE_ENTRY.html
// https://www.nirsoft.net/kernel_struct/vista/LDR_DATA_TABLE_ENTRY.html
// HMODULE points to this struct!
struct X_LDR_DATA_TABLE_ENTRY {
X_LIST_ENTRY in_load_order_links; // 0x0

View File

@@ -385,7 +385,7 @@ object_ref<XObject> XObject::GetNativeObject(KernelState* kernel_state,
return object;
} else {
// First use, create new.
// http://www.nirsoft.net/kernel_struct/vista/KOBJECTS.html
// https://www.nirsoft.net/kernel_struct/vista/KOBJECTS.html
XObject* object = nullptr;
switch (as_type) {
case 0: // EventNotificationObject

View File

@@ -32,7 +32,7 @@ class KernelState;
template <typename T>
class object_ref;
// http://www.nirsoft.net/kernel_struct/vista/DISPATCHER_HEADER.html
// https://www.nirsoft.net/kernel_struct/vista/DISPATCHER_HEADER.html
typedef struct {
struct {
uint8_t type;
@@ -60,7 +60,7 @@ typedef struct {
} X_DISPATCH_HEADER;
static_assert_size(X_DISPATCH_HEADER, 0x10);
// http://www.nirsoft.net/kernel_struct/vista/OBJECT_HEADER.html
// https://www.nirsoft.net/kernel_struct/vista/OBJECT_HEADER.html
struct X_OBJECT_HEADER {
xe::be<uint32_t> pointer_count;
union {
@@ -82,7 +82,7 @@ struct X_OBJECT_HEADER {
// (There's actually a body field here which is the object itself)
};
// http://www.nirsoft.net/kernel_struct/vista/OBJECT_CREATE_INFORMATION.html
// https://www.nirsoft.net/kernel_struct/vista/OBJECT_CREATE_INFORMATION.html
struct X_OBJECT_CREATE_INFORMATION {
xe::be<uint32_t> attributes; // 0x0
xe::be<uint32_t> root_directory_ptr; // 0x4

View File

@@ -82,7 +82,7 @@ class XSocket : public XObject {
IPPROTO_UDP = 17,
// LIVE Voice and Data Protocol
// http://blog.csdn.net/baozi3026/article/details/4277227
// https://blog.csdn.net/baozi3026/article/details/4277227
// Format: [cbGameData][GameData(encrypted)][VoiceData(unencrypted)]
IPPROTO_VDP = 254,
};

View File

@@ -313,7 +313,7 @@ X_STATUS XThread::Create() {
}
// Allocate thread state block from heap.
// http://www.microsoft.com/msj/archive/s2ce.aspx
// https://web.archive.org/web/20170704035330/https://www.microsoft.com/msj/archive/S2CE.aspx
// This is set as r13 for user code and some special inlined Win32 calls
// (like GetLastError/etc) will poke it directly.
// We try to use it as our primary store of data just to keep things all
@@ -568,8 +568,8 @@ void XThread::EnqueueApc(uint32_t normal_routine, uint32_t normal_context,
}
void XThread::DeliverAPCs() {
// http://www.drdobbs.com/inside-nts-asynchronous-procedure-call/184416590?pgno=1
// http://www.drdobbs.com/inside-nts-asynchronous-procedure-call/184416590?pgno=7
// https://www.drdobbs.com/inside-nts-asynchronous-procedure-call/184416590?pgno=1
// https://www.drdobbs.com/inside-nts-asynchronous-procedure-call/184416590?pgno=7
auto processor = kernel_state()->processor();
LockApc();
while (apc_list_.HasPending()) {

View File

@@ -34,8 +34,8 @@ std::unique_ptr<VulkanProvider> VulkanProvider::Create(Window* main_window) {
"Ensure you have the latest drivers for your GPU and that it "
"supports Vulkan.\n"
"\n"
"See http://xenia.jp/faq/ for more information and a list of supported "
"GPUs.");
"See https://xenia.jp/faq/ for more information and a list of "
"supported GPUs.");
return nullptr;
}
return provider;

View File

@@ -403,7 +403,7 @@ void FatalVulkanError(std::string error) {
"Ensure you have the latest drivers for your GPU and that it supports "
"Vulkan.\n"
"\n"
"See http://xenia.jp/faq/ for more information and a list of supported "
"See https://xenia.jp/faq/ for more information and a list of supported "
"GPUs.");
}

View File

@@ -47,12 +47,20 @@ bool Win32Window::Initialize() { return OnCreate(); }
bool Win32Window::OnCreate() {
HINSTANCE hInstance = GetModuleHandle(nullptr);
if (!SetProcessDpiAwareness_ || !GetDpiForMonitor_) {
auto shcore = GetModuleHandle(L"shcore.dll");
if (shcore) {
SetProcessDpiAwareness_ =
GetProcAddress(shcore, "SetProcessDpiAwareness");
GetDpiForMonitor_ = GetProcAddress(shcore, "GetDpiForMonitor");
}
}
static bool has_registered_class = false;
if (!has_registered_class) {
// Tell Windows that we're DPI aware.
auto spda = (decltype(&SetProcessDpiAwareness))GetProcAddress(
GetModuleHandle(L"shcore.dll"), "SetProcessDpiAwareness");
if (spda) {
if (SetProcessDpiAwareness_) {
auto spda = (decltype(&SetProcessDpiAwareness))SetProcessDpiAwareness_;
auto res = spda(PROCESS_PER_MONITOR_DPI_AWARE);
if (res != S_OK) {
XELOGE("Failed to set process DPI awareness. (code = 0x%.8X)", res);
@@ -245,7 +253,7 @@ void Win32Window::ToggleFullscreen(bool fullscreen) {
DWORD style = GetWindowLong(hwnd_, GWL_STYLE);
if (fullscreen) {
// http://blogs.msdn.com/b/oldnewthing/archive/2010/04/12/9994016.aspx
// https://blogs.msdn.com/b/oldnewthing/archive/2010/04/12/9994016.aspx
MONITORINFO mi = {sizeof(mi)};
if (GetWindowPlacement(hwnd_, &windowed_pos_) &&
GetMonitorInfo(MonitorFromWindow(hwnd_, MONITOR_DEFAULTTOPRIMARY),
@@ -303,11 +311,16 @@ void Win32Window::set_bordered(bool enabled) {
}
int Win32Window::get_dpi() const {
if (!GetDpiForMonitor_) {
return 96;
}
HMONITOR monitor = MonitorFromWindow(hwnd_, MONITOR_DEFAULTTOPRIMARY);
// According to msdn, x and y are identical...
UINT dpi_x, dpi_y;
GetDpiForMonitor(monitor, MDT_DEFAULT, &dpi_x, &dpi_y);
auto gdfm = (decltype(&GetDpiForMonitor))GetDpiForMonitor_;
gdfm(monitor, MDT_DEFAULT, &dpi_x, &dpi_y);
return dpi_x;
}

View File

@@ -85,6 +85,9 @@ class Win32Window : public Window {
WINDOWPLACEMENT windowed_pos_ = {0};
POINT last_mouse_pos_ = {0};
void* SetProcessDpiAwareness_ = nullptr;
void* GetDpiForMonitor_ = nullptr;
};
class Win32MenuItem : public MenuItem {

View File

@@ -19,7 +19,7 @@
namespace xe {
namespace vfs {
// http://www.free60.org/wiki/STFS
// https://free60project.github.io/wiki/STFS.html
class StfsContainerEntry;

View File

@@ -34,7 +34,7 @@ namespace vfs {
class Device;
class File;
// Matches http://source.winehq.org/source/include/winternl.h#1591.
// Matches https://source.winehq.org/source/include/winternl.h#1591.
enum class FileAction {
kSuperseded = 0,
kOpened = 1,

View File

@@ -27,7 +27,7 @@ typedef uint32_t X_HANDLE;
// TODO(benvanik): type all of this so we get some safety.
// NT_STATUS (STATUS_*)
// http://msdn.microsoft.com/en-us/library/cc704588.aspx
// https://msdn.microsoft.com/en-us/library/cc704588.aspx
// Adding as needed.
typedef uint32_t X_STATUS;
#define XSUCCEEDED(s) ((s & 0xC0000000) == 0)
@@ -60,6 +60,7 @@ typedef uint32_t X_STATUS;
#define X_STATUS_OBJECT_NAME_COLLISION ((X_STATUS)0xC0000035L)
#define X_STATUS_INVALID_PAGE_PROTECTION ((X_STATUS)0xC0000045L)
#define X_STATUS_MUTANT_NOT_OWNED ((X_STATUS)0xC0000046L)
#define X_STATUS_PROCEDURE_NOT_FOUND ((X_STATUS)0xC000007AL)
#define X_STATUS_INSUFFICIENT_RESOURCES ((X_STATUS)0xC000009AL)
#define X_STATUS_MEMORY_NOT_ALLOCATED ((X_STATUS)0xC00000A0L)
#define X_STATUS_NOT_SUPPORTED ((X_STATUS)0xC00000BBL)
@@ -67,6 +68,7 @@ typedef uint32_t X_STATUS;
#define X_STATUS_INVALID_PARAMETER_2 ((X_STATUS)0xC00000F0L)
#define X_STATUS_INVALID_PARAMETER_3 ((X_STATUS)0xC00000F1L)
#define X_STATUS_DLL_NOT_FOUND ((X_STATUS)0xC0000135L)
#define X_STATUS_ENTRYPOINT_NOT_FOUND ((X_STATUS)0xC0000139L)
#define X_STATUS_MAPPED_ALIGNMENT ((X_STATUS)0xC0000220L)
#define X_STATUS_NOT_FOUND ((X_STATUS)0xC0000225L)
#define X_STATUS_DRIVER_ORDINAL_NOT_FOUND ((X_STATUS)0xC0000262L)
@@ -160,7 +162,7 @@ enum X_FILE_ATTRIBUTES : uint32_t {
X_FILE_ATTRIBUTE_ENCRYPTED = 0x4000,
};
// http://code.google.com/p/vdash/source/browse/trunk/vdash/include/kernel.h
// https://github.com/oukiar/vdash/blob/master/vdash/include/kernel.h
enum X_FILE_INFORMATION_CLASS {
XFileDirectoryInformation = 1,
XFileFullDirectoryInformation,
@@ -324,10 +326,10 @@ struct X_UNICODE_STRING {
};
static_assert_size(X_UNICODE_STRING, 8);
// http://pastebin.com/SMypYikG
// https://pastebin.com/SMypYikG
typedef uint32_t XNotificationID;
// http://ffplay360.googlecode.com/svn/trunk/Common/XTLOnPC.h
// https://github.com/CodeAsm/ffplay360/blob/master/Common/XTLOnPC.h
struct X_VIDEO_MODE {
be<uint32_t> display_width;
be<uint32_t> display_height;
@@ -361,7 +363,7 @@ struct X_SINGLE_LIST_ENTRY {
};
static_assert_size(X_SINGLE_LIST_ENTRY, 4);
// http://www.nirsoft.net/kernel_struct/vista/SLIST_HEADER.html
// https://www.nirsoft.net/kernel_struct/vista/SLIST_HEADER.html
struct X_SLIST_HEADER {
X_SINGLE_LIST_ENTRY next; // 0x0
be<uint16_t> depth; // 0x4