summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/common/common_paths.h2
-rw-r--r--src/common/file_util.cpp77
-rw-r--r--src/core/arm/interpreter/arminit.cpp4
-rw-r--r--src/core/arm/skyeye_common/armdefs.h23
-rw-r--r--src/core/hle/service/y2r_u.cpp19
-rw-r--r--src/video_core/debug_utils/debug_utils.cpp6
-rw-r--r--src/video_core/rasterizer.cpp21
7 files changed, 116 insertions, 36 deletions
diff --git a/src/common/common_paths.h b/src/common/common_paths.h
index 0ecf2d9de..eb43d589f 100644
--- a/src/common/common_paths.h
+++ b/src/common/common_paths.h
@@ -25,7 +25,7 @@
#ifdef USER_DIR
#define EMU_DATA_DIR USER_DIR
#else
- #define EMU_DATA_DIR ".citra-emu"
+ #define EMU_DATA_DIR "citra-emu"
#endif
#endif
diff --git a/src/common/file_util.cpp b/src/common/file_util.cpp
index 457376bf4..4ef4918d7 100644
--- a/src/common/file_util.cpp
+++ b/src/common/file_util.cpp
@@ -16,7 +16,10 @@
#include <tchar.h>
#else
#include <sys/param.h>
+#include <sys/types.h>
#include <dirent.h>
+#include <pwd.h>
+#include <unistd.h>
#endif
#if defined(__APPLE__)
@@ -632,6 +635,55 @@ std::string& GetExeDirectory()
}
return exe_path;
}
+#else
+/**
+ * @return The user’s home directory on POSIX systems
+ */
+static const std::string& GetHomeDirectory() {
+ static std::string home_path;
+ if (home_path.empty()) {
+ const char* envvar = getenv("HOME");
+ if (envvar) {
+ home_path = envvar;
+ } else {
+ auto pw = getpwuid(getuid());
+ ASSERT_MSG(pw, "$HOME isn’t defined, and the current user can’t be found in /etc/passwd.");
+ home_path = pw->pw_dir;
+ }
+ }
+ return home_path;
+}
+
+/**
+ * Follows the XDG Base Directory Specification to get a directory path
+ * @param envvar The XDG environment variable to get the value from
+ * @return The directory path
+ * @sa http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html
+ */
+static const std::string GetUserDirectory(const std::string& envvar) {
+ const char* directory = getenv(envvar.c_str());
+
+ std::string user_dir;
+ if (directory) {
+ user_dir = directory;
+ } else {
+ std::string subdirectory;
+ if (envvar == "XDG_DATA_HOME")
+ subdirectory = DIR_SEP ".local" DIR_SEP "share";
+ else if (envvar == "XDG_CONFIG_HOME")
+ subdirectory = DIR_SEP ".config";
+ else if (envvar == "XDG_CACHE_HOME")
+ subdirectory = DIR_SEP ".cache";
+ else
+ ASSERT_MSG(false, "Unknown XDG variable %s.", envvar.c_str());
+ user_dir = GetHomeDirectory() + subdirectory;
+ }
+
+ ASSERT_MSG(!user_dir.empty(), "User directory %s musn’t be empty.", envvar.c_str());
+ ASSERT_MSG(user_dir[0] == '/', "User directory %s must be absolute.", envvar.c_str());
+
+ return user_dir;
+}
#endif
std::string GetSysDirectory()
@@ -661,20 +713,27 @@ const std::string& GetUserPath(const unsigned int DirIDX, const std::string &new
if (paths[D_USER_IDX].empty())
{
#ifdef _WIN32
- paths[D_USER_IDX] = GetExeDirectory() + DIR_SEP USERDATA_DIR DIR_SEP;
+ paths[D_USER_IDX] = GetExeDirectory() + DIR_SEP USERDATA_DIR DIR_SEP;
+ paths[D_CONFIG_IDX] = paths[D_USER_IDX] + CONFIG_DIR DIR_SEP;
+ paths[D_CACHE_IDX] = paths[D_USER_IDX] + CACHE_DIR DIR_SEP;
#else
- if (FileUtil::Exists(ROOT_DIR DIR_SEP USERDATA_DIR))
- paths[D_USER_IDX] = ROOT_DIR DIR_SEP USERDATA_DIR DIR_SEP;
- else
- paths[D_USER_IDX] = std::string(getenv("HOME") ?
- getenv("HOME") : getenv("PWD") ?
- getenv("PWD") : "") + DIR_SEP EMU_DATA_DIR DIR_SEP;
+ if (FileUtil::Exists(ROOT_DIR DIR_SEP USERDATA_DIR)) {
+ paths[D_USER_IDX] = ROOT_DIR DIR_SEP USERDATA_DIR DIR_SEP;
+ paths[D_CONFIG_IDX] = paths[D_USER_IDX] + CONFIG_DIR DIR_SEP;
+ paths[D_CACHE_IDX] = paths[D_USER_IDX] + CACHE_DIR DIR_SEP;
+ } else {
+ std::string data_dir = GetUserDirectory("XDG_DATA_HOME");
+ std::string config_dir = GetUserDirectory("XDG_CONFIG_HOME");
+ std::string cache_dir = GetUserDirectory("XDG_CACHE_HOME");
+
+ paths[D_USER_IDX] = data_dir + DIR_SEP EMU_DATA_DIR DIR_SEP;
+ paths[D_CONFIG_IDX] = config_dir + DIR_SEP EMU_DATA_DIR DIR_SEP;
+ paths[D_CACHE_IDX] = cache_dir + DIR_SEP EMU_DATA_DIR DIR_SEP;
+ }
#endif
- paths[D_CONFIG_IDX] = paths[D_USER_IDX] + CONFIG_DIR DIR_SEP;
paths[D_GAMECONFIG_IDX] = paths[D_USER_IDX] + GAMECONFIG_DIR DIR_SEP;
paths[D_MAPS_IDX] = paths[D_USER_IDX] + MAPS_DIR DIR_SEP;
- paths[D_CACHE_IDX] = paths[D_USER_IDX] + CACHE_DIR DIR_SEP;
paths[D_SDMC_IDX] = paths[D_USER_IDX] + SDMC_DIR DIR_SEP;
paths[D_NAND_IDX] = paths[D_USER_IDX] + NAND_DIR DIR_SEP;
paths[D_SYSDATA_IDX] = paths[D_USER_IDX] + SYSDATA_DIR DIR_SEP;
diff --git a/src/core/arm/interpreter/arminit.cpp b/src/core/arm/interpreter/arminit.cpp
index abafe226e..4ac827e0a 100644
--- a/src/core/arm/interpreter/arminit.cpp
+++ b/src/core/arm/interpreter/arminit.cpp
@@ -58,11 +58,7 @@ void ARMul_SelectProcessor(ARMul_State* state, unsigned properties)
state->is_v4 = (properties & (ARM_v4_Prop | ARM_v5_Prop)) != 0;
state->is_v5 = (properties & ARM_v5_Prop) != 0;
state->is_v5e = (properties & ARM_v5e_Prop) != 0;
- state->is_XScale = (properties & ARM_XScale_Prop) != 0;
- state->is_iWMMXt = (properties & ARM_iWMMXt_Prop) != 0;
state->is_v6 = (properties & ARM_v6_Prop) != 0;
- state->is_ep9312 = (properties & ARM_ep9312_Prop) != 0;
- state->is_pxa27x = (properties & ARM_PXA27X_Prop) != 0;
state->is_v7 = (properties & ARM_v7_Prop) != 0;
// Only initialse the coprocessor support once we
diff --git a/src/core/arm/skyeye_common/armdefs.h b/src/core/arm/skyeye_common/armdefs.h
index 070fcf7dc..16f3ac86c 100644
--- a/src/core/arm/skyeye_common/armdefs.h
+++ b/src/core/arm/skyeye_common/armdefs.h
@@ -185,10 +185,6 @@ So, if lateabtSig=1, then it means Late Abort Model(Base Updated Abort Model)
bool is_v5e; // Are we emulating a v5e architecture?
bool is_v6; // Are we emulating a v6 architecture?
bool is_v7; // Are we emulating a v7 architecture?
- bool is_XScale; // Are we emulating an XScale architecture?
- bool is_iWMMXt; // Are we emulating an iWMMXt co-processor?
- bool is_ep9312; // Are we emulating a Cirrus Maverick co-processor?
- bool is_pxa27x; // Are we emulating a Intel PXA27x co-processor?
// ARM_ARM A2-18
// 0 Base Restored Abort Model, 1 the Early Abort Model, 2 Base Updated Abort Model
@@ -211,20 +207,11 @@ So, if lateabtSig=1, then it means Late Abort Model(Base Updated Abort Model)
\***************************************************************************/
enum {
- ARM_Nexec_Prop = 0x02,
- ARM_Debug_Prop = 0x10,
- ARM_Isync_Prop = ARM_Debug_Prop,
- ARM_Lock_Prop = 0x20,
- ARM_v4_Prop = 0x40,
- ARM_v5_Prop = 0x80,
- ARM_v6_Prop = 0xc0,
-
- ARM_v5e_Prop = 0x100,
- ARM_XScale_Prop = 0x200,
- ARM_ep9312_Prop = 0x400,
- ARM_iWMMXt_Prop = 0x800,
- ARM_PXA27X_Prop = 0x1000,
- ARM_v7_Prop = 0x2000,
+ ARM_v4_Prop = 0x01,
+ ARM_v5_Prop = 0x02,
+ ARM_v5e_Prop = 0x04,
+ ARM_v6_Prop = 0x08,
+ ARM_v7_Prop = 0x10,
};
/***************************************************************************\
diff --git a/src/core/hle/service/y2r_u.cpp b/src/core/hle/service/y2r_u.cpp
index a58e04d6d..6607965e1 100644
--- a/src/core/hle/service/y2r_u.cpp
+++ b/src/core/hle/service/y2r_u.cpp
@@ -11,6 +11,8 @@
namespace Y2R_U {
+static Kernel::SharedPtr<Kernel::Event> completion_event = 0;
+
/**
* Y2R_U::IsBusyConversion service function
* Outputs:
@@ -26,13 +28,26 @@ static void IsBusyConversion(Service::Interface* self) {
LOG_WARNING(Service, "(STUBBED) called");
}
+/**
+ * Y2R_U::GetTransferEndEvent service function
+ * Outputs:
+ * 1 : Result of function, 0 on success, otherwise error code
+ * 3 : The handle of the completion event
+ */
+static void GetTransferEndEvent(Service::Interface* self) {
+ u32* cmd_buff = Kernel::GetCommandBuffer();
+
+ cmd_buff[1] = RESULT_SUCCESS.raw;
+ cmd_buff[3] = Kernel::g_handle_table.Create(completion_event).MoveFrom();
+}
+
const Interface::FunctionInfo FunctionTable[] = {
{0x00010040, nullptr, "SetInputFormat"},
{0x00030040, nullptr, "SetOutputFormat"},
{0x00050040, nullptr, "SetRotation"},
{0x00070040, nullptr, "SetBlockAlignment"},
{0x000D0040, nullptr, "SetTransferEndInterrupt"},
- {0x000F0000, nullptr, "GetTransferEndEvent"},
+ {0x000F0000, GetTransferEndEvent, "GetTransferEndEvent"},
{0x00100102, nullptr, "SetSendingY"},
{0x00110102, nullptr, "SetSendingU"},
{0x00120102, nullptr, "SetSendingV"},
@@ -53,6 +68,8 @@ const Interface::FunctionInfo FunctionTable[] = {
// Interface class
Interface::Interface() {
+ completion_event = Kernel::Event::Create(RESETTYPE_ONESHOT, "Y2R:Completed");
+
Register(FunctionTable);
}
diff --git a/src/video_core/debug_utils/debug_utils.cpp b/src/video_core/debug_utils/debug_utils.cpp
index 0beb72e6b..795449423 100644
--- a/src/video_core/debug_utils/debug_utils.cpp
+++ b/src/video_core/debug_utils/debug_utils.cpp
@@ -333,9 +333,9 @@ const Math::Vec4<u8> LookupTexture(const u8* source, int x, int y, const Texture
// Interleave the lower 3 bits of each coordinate to get the intra-block offsets, which are
// arranged in a Z-order curve. More details on the bit manipulation at:
// https://fgiesen.wordpress.com/2009/12/13/decoding-morton-codes/
- unsigned int i = (x | (y << 8)) & 0x0707; // ---- -210
- i = (i ^ (i << 2)) & 0x1313; // ---2 --10
- i = (i ^ (i << 1)) & 0x1515; // ---2 -1-0
+ unsigned int i = (x & 7) | ((y & 7) << 8); // ---- -210
+ i = (i ^ (i << 2)) & 0x1313; // ---2 --10
+ i = (i ^ (i << 1)) & 0x1515; // ---2 -1-0
i = (i | (i >> 7)) & 0x3F;
if (info.format != Regs::TextureFormat::ETC1 &&
diff --git a/src/video_core/rasterizer.cpp b/src/video_core/rasterizer.cpp
index 17f8f70ca..24dc37856 100644
--- a/src/video_core/rasterizer.cpp
+++ b/src/video_core/rasterizer.cpp
@@ -8,6 +8,7 @@
#include "common/math_util.h"
#include "math.h"
+#include "color.h"
#include "pica.h"
#include "rasterizer.h"
#include "vertex_shader.h"
@@ -37,6 +38,14 @@ static void DrawPixel(int x, int y, const Math::Vec4<u8>& color) {
break;
}
+ case registers.framebuffer.RGBA4:
+ {
+ u8* pixel = color_buffer + (x + y * registers.framebuffer.GetWidth()) * 2;
+ pixel[1] = (color.r() & 0xF0) | (color.g() >> 4);
+ pixel[0] = (color.b() & 0xF0) | (color.a() >> 4);
+ break;
+ }
+
default:
LOG_CRITICAL(Render_Software, "Unknown framebuffer color format %x", registers.framebuffer.color_format);
UNIMPLEMENTED();
@@ -60,6 +69,18 @@ static const Math::Vec4<u8> GetPixel(int x, int y) {
ret.a() = pixel[0];
return ret;
}
+
+ case registers.framebuffer.RGBA4:
+ {
+ Math::Vec4<u8> ret;
+ u8* pixel = color_buffer + (x + y * registers.framebuffer.GetWidth()) * 2;
+ ret.r() = Color::Convert4To8(pixel[1] >> 4);
+ ret.g() = Color::Convert4To8(pixel[1] & 0x0F);
+ ret.b() = Color::Convert4To8(pixel[0] >> 4);
+ ret.a() = Color::Convert4To8(pixel[0] & 0x0F);
+ return ret;
+ }
+
default:
LOG_CRITICAL(Render_Software, "Unknown framebuffer color format %x", registers.framebuffer.color_format);
UNIMPLEMENTED();