summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-x[-rw-r--r--].travis-build.sh6
-rwxr-xr-x[-rw-r--r--].travis-deps.sh4
-rw-r--r--.travis-upload.sh29
-rw-r--r--.travis.yml7
-rw-r--r--appveyor.yml40
-rw-r--r--src/common/common_paths.h11
-rw-r--r--src/common/emu_window.h2
-rw-r--r--src/common/platform.h6
-rw-r--r--src/core/arm/arm_interface.h6
-rw-r--r--src/core/arm/dyncom/arm_dyncom.cpp5
-rw-r--r--src/core/arm/dyncom/arm_dyncom.h1
-rw-r--r--src/core/arm/dyncom/arm_dyncom_interpreter.cpp150
-rw-r--r--src/core/arm/interpreter/armsupp.cpp6
-rw-r--r--src/core/arm/skyeye_common/armdefs.h3
-rw-r--r--src/core/arm/skyeye_common/armmmu.h105
-rw-r--r--src/core/arm/skyeye_common/vfp/vfpinstr.cpp102
-rw-r--r--src/core/hle/service/hid/hid.cpp38
-rw-r--r--src/core/hle/service/hid/hid.h30
-rw-r--r--src/core/hle/service/hid/hid_spvr.cpp6
-rw-r--r--src/core/hle/service/hid/hid_user.cpp16
-rw-r--r--src/core/hle/svc.cpp5
-rw-r--r--src/core/hw/gpu.cpp31
-rw-r--r--src/core/hw/gpu.h11
-rw-r--r--src/core/loader/ncch.h25
-rw-r--r--src/core/mem_map.h1
-rw-r--r--src/core/mem_map_funcs.cpp6
-rw-r--r--src/video_core/color.h2
-rw-r--r--src/video_core/debug_utils/debug_utils.cpp6
-rw-r--r--src/video_core/vertex_shader.cpp44
-rw-r--r--upload_to_mega.js28
30 files changed, 484 insertions, 248 deletions
diff --git a/.travis-build.sh b/.travis-build.sh
index b869b8b8f..21582c689 100644..100755
--- a/.travis-build.sh
+++ b/.travis-build.sh
@@ -4,13 +4,13 @@ set -e
4set -x 4set -x
5 5
6#if OS is linux or is not set 6#if OS is linux or is not set
7if [ "$TRAVIS_OS_NAME" = linux -o -z "$TRAVIS_OS_NAME" ]; then 7if [ "$TRAVIS_OS_NAME" = "linux" -o -z "$TRAVIS_OS_NAME" ]; then
8 mkdir build && cd build 8 mkdir build && cd build
9 cmake -DUSE_QT5=OFF .. 9 cmake -DUSE_QT5=OFF ..
10 make -j4 10 make -j4
11elif [ "$TRAVIS_OS_NAME" = osx ]; then 11elif [ "$TRAVIS_OS_NAME" = "osx" ]; then
12 export Qt5_DIR=$(brew --prefix)/opt/qt5 12 export Qt5_DIR=$(brew --prefix)/opt/qt5
13 mkdir build && cd build 13 mkdir build && cd build
14 cmake .. -GXcode 14 cmake .. -GXcode
15 xcodebuild 15 xcodebuild -configuration Release
16fi 16fi
diff --git a/.travis-deps.sh b/.travis-deps.sh
index bd09da0d0..f8074fb91 100644..100755
--- a/.travis-deps.sh
+++ b/.travis-deps.sh
@@ -4,7 +4,7 @@ set -e
4set -x 4set -x
5 5
6#if OS is linux or is not set 6#if OS is linux or is not set
7if [ "$TRAVIS_OS_NAME" = linux -o -z "$TRAVIS_OS_NAME" ]; then 7if [ "$TRAVIS_OS_NAME" = "linux" -o -z "$TRAVIS_OS_NAME" ]; then
8 sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y 8 sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y
9 sudo apt-get -qq update 9 sudo apt-get -qq update
10 sudo apt-get -qq install g++-4.9 xorg-dev libglu1-mesa-dev libxcursor-dev 10 sudo apt-get -qq install g++-4.9 xorg-dev libglu1-mesa-dev libxcursor-dev
@@ -23,7 +23,7 @@ if [ "$TRAVIS_OS_NAME" = linux -o -z "$TRAVIS_OS_NAME" ]; then
23 sudo mkdir -p /usr/local 23 sudo mkdir -p /usr/local
24 curl http://www.cmake.org/files/v2.8/cmake-2.8.11-Linux-i386.tar.gz \ 24 curl http://www.cmake.org/files/v2.8/cmake-2.8.11-Linux-i386.tar.gz \
25 | sudo tar -xz -C /usr/local --strip-components=1 25 | sudo tar -xz -C /usr/local --strip-components=1
26elif [ "$TRAVIS_OS_NAME" = osx ]; then 26elif [ "$TRAVIS_OS_NAME" = "osx" ]; then
27 brew tap homebrew/versions 27 brew tap homebrew/versions
28 brew install qt5 glfw3 pkgconfig 28 brew install qt5 glfw3 pkgconfig
29fi 29fi
diff --git a/.travis-upload.sh b/.travis-upload.sh
new file mode 100644
index 000000000..4b9446a96
--- /dev/null
+++ b/.travis-upload.sh
@@ -0,0 +1,29 @@
1if [ "$TRAVIS_BRANCH" = "master" ]; then
2 GITDATE="`git show -s --date=short --format='%ad' | sed 's/-//g'`"
3 GITREV="`git show -s --format='%h'`"
4
5 if [ "$TRAVIS_OS_NAME" = "linux" -o -z "$TRAVIS_OS_NAME" ]; then
6 REV_NAME="citra-${GITDATE}-${GITREV}-linux-amd64"
7 UPLOAD_DIR="/citra/nightly/linux-amd64"
8 mkdir "$REV_NAME"
9
10 sudo apt-get -qq install lftp
11 cp build/src/citra/citra "$REV_NAME"
12 cp build/src/citra_qt/citra-qt "$REV_NAME"
13 elif [ "$TRAVIS_OS_NAME" = "osx" ]; then
14 REV_NAME="citra-${GITDATE}-${GITREV}-osx-amd64"
15 UPLOAD_DIR="/citra/nightly/osx-amd64"
16 mkdir "$REV_NAME"
17
18 brew install lftp
19 cp build/src/citra/Release/citra "$REV_NAME"
20 cp -r build/src/citra_qt/Release/citra-qt.app "$REV_NAME"
21
22 # move qt libs into app bundle for deployment
23 $(brew --prefix)/opt/qt5/bin/macdeployqt "${REV_NAME}/citra-qt.app"
24 fi
25
26 ARCHIVE_NAME="${REV_NAME}.tar.xz"
27 tar -cJvf "$ARCHIVE_NAME" "$REV_NAME"
28 lftp -c "open -u citra-builds,$BUILD_PASSWORD sftp://builds.citra-emu.org; put -O '$UPLOAD_DIR' '$ARCHIVE_NAME'"
29fi
diff --git a/.travis.yml b/.travis.yml
index 1cb369d5b..b878cc160 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -4,8 +4,15 @@ os:
4 4
5language: cpp 5language: cpp
6 6
7env:
8 global:
9 - secure: "AXHFIafTmbGDsHD3mUVj5a4I397DQjti/WoqAJGUp2PglxTcc04BwxZ9Z+xLuf5N2Hs5r9ojAJLT8OGxJCLBDXzneQTNSqXbFuYSLbqrEAiIRlA9eRIotWCg+wYcO+5e8MKX+cHVKwiIWasUB21AtCdq6msh6Y3pUshZp212VPg="
10
7before_install: 11before_install:
8 - sh .travis-deps.sh 12 - sh .travis-deps.sh
9 13
10script: 14script:
11 - sh .travis-build.sh 15 - sh .travis-build.sh
16
17after_success:
18 - sh .travis-upload.sh
diff --git a/appveyor.yml b/appveyor.yml
index c9edb9e19..7886b905b 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -6,10 +6,8 @@ clone_depth: 5
6 6
7environment: 7environment:
8 QTDIR: C:\Qt\5.4\msvc2013_64_opengl 8 QTDIR: C:\Qt\5.4\msvc2013_64_opengl
9 MEGA_EMAIL: 9 BUILD_PASSWORD:
10 secure: rEo9CGAYX87GKTqZCZ9vLCNCNqxO5JLgbERaHF3YJWg= 10 secure: EXGNlWKJsCtbeImEJ5EP9qrxZ+EqUFfNy+CP61nDOMA=
11 MEGA_PASSWORD:
12 secure: zE1zmgjS/6GfN/19ROl/O0fVR58svORQ5gdtsxI7J8k=
13 11
14platform: 12platform:
15 - x64 13 - x64
@@ -27,11 +25,6 @@ before_build:
27 - cd .. 25 - cd ..
28 26
29after_build: 27after_build:
30 # upload the build to Mega
31 - cinst wget -x86
32 - wget -q http://megatools.megous.com/builds/megatools-1.9.94-win64.zip
33 # extract megatools silently. See http://stackoverflow.com/a/11629736/1748450
34 - 7z x megatools-1.9.94-win64.zip | FIND /V "ing "
35 # copy the qt dlls 28 # copy the qt dlls
36 - copy C:\Qt\5.4\msvc2013_64_opengl\bin\icudt53.dll build\bin\release 29 - copy C:\Qt\5.4\msvc2013_64_opengl\bin\icudt53.dll build\bin\release
37 - copy C:\Qt\5.4\msvc2013_64_opengl\bin\icuin53.dll build\bin\release 30 - copy C:\Qt\5.4\msvc2013_64_opengl\bin\icuin53.dll build\bin\release
@@ -42,9 +35,26 @@ after_build:
42 - copy C:\Qt\5.4\msvc2013_64_opengl\bin\Qt5Widgets.dll build\bin\release 35 - copy C:\Qt\5.4\msvc2013_64_opengl\bin\Qt5Widgets.dll build\bin\release
43 - mkdir build\bin\release\platforms\ 36 - mkdir build\bin\release\platforms\
44 - copy C:\Qt\5.4\msvc2013_64_opengl\plugins\platforms\qwindows.dll build\bin\release\platforms 37 - copy C:\Qt\5.4\msvc2013_64_opengl\plugins\platforms\qwindows.dll build\bin\release\platforms
45 # zip up the build folder -> build.7z 38
46 - 7z a build .\build\bin\release\* 39 - ps: >
47 # rename, upload to Mega 40 if (!"$env:APPVEYOR_PULL_REQUEST_TITLE" -and ("$env:APPVEYOR_REPO_BRANCH" -eq "master"))
48 - npm install sanitize-filename 41 {
49 - cd megatools-1.9.94-win64 42 $GITDATE = $(git show -s --date=short --format='%ad') -replace "-",""
50 - node ..\upload_to_mega.js 43 $GITREV = $(git show -s --format='%h')
44 # Where are these spaces coming from? Regardless, let's remove them
45 $BUILD_NAME = "citra-${GITDATE}-${GITREV}-windows-amd64.7z" -replace " ",""
46 # Zip up the build folder
47 7z a $BUILD_NAME .\build\bin\release\*
48
49 # Download winscp
50 Invoke-WebRequest "http://hivelocity.dl.sourceforge.net/project/winscp/WinSCP/5.7/winscp570.zip" -OutFile "winscp570.zip"
51 7z e -y winscp570.zip
52
53 # Upload to server
54 .\WinSCP.com /command `
55 "option batch abort" `
56 "option confirm off" `
57 "open sftp://citra-builds:${env:BUILD_PASSWORD}@builds.citra-emu.org -hostkey=*" `
58 "put $BUILD_NAME /citra/nightly/windows-amd64/" `
59 "exit"
60 }
diff --git a/src/common/common_paths.h b/src/common/common_paths.h
index eb43d589f..440b06060 100644
--- a/src/common/common_paths.h
+++ b/src/common/common_paths.h
@@ -17,13 +17,12 @@
17 17
18// The user data dir 18// The user data dir
19#define ROOT_DIR "." 19#define ROOT_DIR "."
20#ifdef _WIN32 20#define USERDATA_DIR "user"
21 #define USERDATA_DIR "user" 21#ifdef USER_DIR
22 #define EMU_DATA_DIR "Citra Emulator" 22 #define EMU_DATA_DIR USER_DIR
23#else 23#else
24 #define USERDATA_DIR "user" 24 #ifdef _WIN32
25 #ifdef USER_DIR 25 #define EMU_DATA_DIR "Citra Emulator"
26 #define EMU_DATA_DIR USER_DIR
27 #else 26 #else
28 #define EMU_DATA_DIR "citra-emu" 27 #define EMU_DATA_DIR "citra-emu"
29 #endif 28 #endif
diff --git a/src/common/emu_window.h b/src/common/emu_window.h
index 2be7517bc..c8e2de04a 100644
--- a/src/common/emu_window.h
+++ b/src/common/emu_window.h
@@ -110,7 +110,7 @@ public:
110 * @return std::tuple of (x, y, pressed) where `x` and `y` are the touch coordinates and 110 * @return std::tuple of (x, y, pressed) where `x` and `y` are the touch coordinates and
111 * `pressed` is true if the touch screen is currently being pressed 111 * `pressed` is true if the touch screen is currently being pressed
112 */ 112 */
113 const std::tuple<u16, u16, bool>& GetTouchState() const { 113 const std::tuple<u16, u16, bool> GetTouchState() const {
114 return std::make_tuple(touch_x, touch_y, touch_pressed); 114 return std::make_tuple(touch_x, touch_y, touch_pressed);
115 } 115 }
116 116
diff --git a/src/common/platform.h b/src/common/platform.h
index ba1109c9f..e27d6e31f 100644
--- a/src/common/platform.h
+++ b/src/common/platform.h
@@ -83,7 +83,7 @@ inline struct tm* localtime_r(const time_t *clock, struct tm *result) {
83} 83}
84#endif 84#endif
85 85
86#else 86#else // EMU_PLATFORM != PLATFORM_WINDOWS
87 87
88#define EMU_FASTCALL __attribute__((fastcall)) 88#define EMU_FASTCALL __attribute__((fastcall))
89#define __stdcall 89#define __stdcall
@@ -92,10 +92,6 @@ inline struct tm* localtime_r(const time_t *clock, struct tm *result) {
92#define BOOL bool 92#define BOOL bool
93#define DWORD u32 93#define DWORD u32
94 94
95#endif
96
97#if EMU_PLATFORM != PLATFORM_WINDOWS
98
99// TODO: Hacks.. 95// TODO: Hacks..
100#include <limits.h> 96#include <limits.h>
101 97
diff --git a/src/core/arm/arm_interface.h b/src/core/arm/arm_interface.h
index ef37ee055..fe1e584ad 100644
--- a/src/core/arm/arm_interface.h
+++ b/src/core/arm/arm_interface.h
@@ -74,12 +74,6 @@ public:
74 virtual void SetCPSR(u32 cpsr) = 0; 74 virtual void SetCPSR(u32 cpsr) = 0;
75 75
76 /** 76 /**
77 * Returns the number of clock ticks since the last rese
78 * @return Returns number of clock ticks
79 */
80 virtual u64 GetTicks() const = 0;
81
82 /**
83 * Advance the CPU core by the specified number of ticks (e.g. to simulate CPU execution time) 77 * Advance the CPU core by the specified number of ticks (e.g. to simulate CPU execution time)
84 * @param ticks Number of ticks to advance the CPU core 78 * @param ticks Number of ticks to advance the CPU core
85 */ 79 */
diff --git a/src/core/arm/dyncom/arm_dyncom.cpp b/src/core/arm/dyncom/arm_dyncom.cpp
index bbcbbdd2b..cb1a410a0 100644
--- a/src/core/arm/dyncom/arm_dyncom.cpp
+++ b/src/core/arm/dyncom/arm_dyncom.cpp
@@ -68,11 +68,6 @@ void ARM_DynCom::SetCPSR(u32 cpsr) {
68 state->Cpsr = cpsr; 68 state->Cpsr = cpsr;
69} 69}
70 70
71u64 ARM_DynCom::GetTicks() const {
72 // TODO(Subv): Remove ARM_DynCom::GetTicks() and use CoreTiming::GetTicks() directly once ARMemu is gone
73 return CoreTiming::GetTicks();
74}
75
76void ARM_DynCom::AddTicks(u64 ticks) { 71void ARM_DynCom::AddTicks(u64 ticks) {
77 down_count -= ticks; 72 down_count -= ticks;
78 if (down_count < 0) 73 if (down_count < 0)
diff --git a/src/core/arm/dyncom/arm_dyncom.h b/src/core/arm/dyncom/arm_dyncom.h
index 213cac1ad..a7f95d307 100644
--- a/src/core/arm/dyncom/arm_dyncom.h
+++ b/src/core/arm/dyncom/arm_dyncom.h
@@ -23,7 +23,6 @@ public:
23 u32 GetCPSR() const override; 23 u32 GetCPSR() const override;
24 void SetCPSR(u32 cpsr) override; 24 void SetCPSR(u32 cpsr) override;
25 25
26 u64 GetTicks() const override;
27 void AddTicks(u64 ticks) override; 26 void AddTicks(u64 ticks) override;
28 27
29 void ResetContext(Core::ThreadContext& context, u32 stack_top, u32 entry_point, u32 arg); 28 void ResetContext(Core::ThreadContext& context, u32 stack_top, u32 entry_point, u32 arg);
diff --git a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp
index d953adba9..cfa6de8fc 100644
--- a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp
+++ b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp
@@ -1075,6 +1075,10 @@ typedef struct _swp_inst {
1075 unsigned int Rm; 1075 unsigned int Rm;
1076} swp_inst; 1076} swp_inst;
1077 1077
1078typedef struct setend_inst {
1079 unsigned int set_bigend;
1080} setend_inst;
1081
1078typedef struct _b_2_thumb { 1082typedef struct _b_2_thumb {
1079 unsigned int imm; 1083 unsigned int imm;
1080}b_2_thumb; 1084}b_2_thumb;
@@ -2283,7 +2287,20 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(sel)(unsigned int inst, int index)
2283 return inst_base; 2287 return inst_base;
2284} 2288}
2285 2289
2286static ARM_INST_PTR INTERPRETER_TRANSLATE(setend)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("SETEND"); } 2290static ARM_INST_PTR INTERPRETER_TRANSLATE(setend)(unsigned int inst, int index)
2291{
2292 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(setend_inst));
2293 setend_inst* const inst_cream = (setend_inst*)inst_base->component;
2294
2295 inst_base->cond = AL;
2296 inst_base->idx = index;
2297 inst_base->br = NON_BRANCH;
2298 inst_base->load_r15 = 0;
2299
2300 inst_cream->set_bigend = BIT(inst, 9);
2301
2302 return inst_base;
2303}
2287 2304
2288static ARM_INST_PTR INTERPRETER_TRANSLATE(shadd8)(unsigned int inst, int index) 2305static ARM_INST_PTR INTERPRETER_TRANSLATE(shadd8)(unsigned int inst, int index)
2289{ 2306{
@@ -4345,30 +4362,30 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
4345 if (BIT(inst, 22) && !BIT(inst, 15)) { 4362 if (BIT(inst, 22) && !BIT(inst, 15)) {
4346 for (int i = 0; i < 13; i++) { 4363 for (int i = 0; i < 13; i++) {
4347 if(BIT(inst, i)) { 4364 if(BIT(inst, i)) {
4348 cpu->Reg[i] = Memory::Read32(addr); 4365 cpu->Reg[i] = ReadMemory32(cpu, addr);
4349 addr += 4; 4366 addr += 4;
4350 } 4367 }
4351 } 4368 }
4352 if (BIT(inst, 13)) { 4369 if (BIT(inst, 13)) {
4353 if (cpu->Mode == USER32MODE) 4370 if (cpu->Mode == USER32MODE)
4354 cpu->Reg[13] = Memory::Read32(addr); 4371 cpu->Reg[13] = ReadMemory32(cpu, addr);
4355 else 4372 else
4356 cpu->Reg_usr[0] = Memory::Read32(addr); 4373 cpu->Reg_usr[0] = ReadMemory32(cpu, addr);
4357 4374
4358 addr += 4; 4375 addr += 4;
4359 } 4376 }
4360 if (BIT(inst, 14)) { 4377 if (BIT(inst, 14)) {
4361 if (cpu->Mode == USER32MODE) 4378 if (cpu->Mode == USER32MODE)
4362 cpu->Reg[14] = Memory::Read32(addr); 4379 cpu->Reg[14] = ReadMemory32(cpu, addr);
4363 else 4380 else
4364 cpu->Reg_usr[1] = Memory::Read32(addr); 4381 cpu->Reg_usr[1] = ReadMemory32(cpu, addr);
4365 4382
4366 addr += 4; 4383 addr += 4;
4367 } 4384 }
4368 } else if (!BIT(inst, 22)) { 4385 } else if (!BIT(inst, 22)) {
4369 for(int i = 0; i < 16; i++ ){ 4386 for(int i = 0; i < 16; i++ ){
4370 if(BIT(inst, i)){ 4387 if(BIT(inst, i)){
4371 unsigned int ret = Memory::Read32(addr); 4388 unsigned int ret = ReadMemory32(cpu, addr);
4372 4389
4373 // For armv5t, should enter thumb when bits[0] is non-zero. 4390 // For armv5t, should enter thumb when bits[0] is non-zero.
4374 if(i == 15){ 4391 if(i == 15){
@@ -4383,7 +4400,7 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
4383 } else if (BIT(inst, 22) && BIT(inst, 15)) { 4400 } else if (BIT(inst, 22) && BIT(inst, 15)) {
4384 for(int i = 0; i < 15; i++ ){ 4401 for(int i = 0; i < 15; i++ ){
4385 if(BIT(inst, i)){ 4402 if(BIT(inst, i)){
4386 cpu->Reg[i] = Memory::Read32(addr); 4403 cpu->Reg[i] = ReadMemory32(cpu, addr);
4387 addr += 4; 4404 addr += 4;
4388 } 4405 }
4389 } 4406 }
@@ -4394,7 +4411,7 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
4394 LOAD_NZCVT; 4411 LOAD_NZCVT;
4395 } 4412 }
4396 4413
4397 cpu->Reg[15] = Memory::Read32(addr); 4414 cpu->Reg[15] = ReadMemory32(cpu, addr);
4398 } 4415 }
4399 4416
4400 if (BIT(inst, 15)) { 4417 if (BIT(inst, 15)) {
@@ -4428,20 +4445,18 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
4428 LDR_INST: 4445 LDR_INST:
4429 { 4446 {
4430 ldst_inst *inst_cream = (ldst_inst *)inst_base->component; 4447 ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
4431 //if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 4448 inst_cream->get_addr(cpu, inst_cream->inst, addr, 1);
4432 inst_cream->get_addr(cpu, inst_cream->inst, addr, 1);
4433 4449
4434 unsigned int value = Memory::Read32(addr); 4450 unsigned int value = ReadMemory32(cpu, addr);
4435 cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value; 4451 cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value;
4436 4452
4437 if (BITS(inst_cream->inst, 12, 15) == 15) { 4453 if (BITS(inst_cream->inst, 12, 15) == 15) {
4438 // For armv5t, should enter thumb when bits[0] is non-zero. 4454 // For armv5t, should enter thumb when bits[0] is non-zero.
4439 cpu->TFlag = value & 0x1; 4455 cpu->TFlag = value & 0x1;
4440 cpu->Reg[15] &= 0xFFFFFFFE; 4456 cpu->Reg[15] &= 0xFFFFFFFE;
4441 INC_PC(sizeof(ldst_inst)); 4457 INC_PC(sizeof(ldst_inst));
4442 goto DISPATCH; 4458 goto DISPATCH;
4443 } 4459 }
4444 //}
4445 4460
4446 cpu->Reg[15] += GET_INST_SIZE(cpu); 4461 cpu->Reg[15] += GET_INST_SIZE(cpu);
4447 INC_PC(sizeof(ldst_inst)); 4462 INC_PC(sizeof(ldst_inst));
@@ -4454,7 +4469,7 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
4454 ldst_inst *inst_cream = (ldst_inst *)inst_base->component; 4469 ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
4455 inst_cream->get_addr(cpu, inst_cream->inst, addr, 1); 4470 inst_cream->get_addr(cpu, inst_cream->inst, addr, 1);
4456 4471
4457 unsigned int value = Memory::Read32(addr); 4472 unsigned int value = ReadMemory32(cpu, addr);
4458 cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value; 4473 cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value;
4459 4474
4460 if (BITS(inst_cream->inst, 12, 15) == 15) { 4475 if (BITS(inst_cream->inst, 12, 15) == 15) {
@@ -4537,8 +4552,10 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
4537 // Should check if RD is even-numbered, Rd != 14, addr[0:1] == 0, (CP15_reg1_U == 1 || addr[2] == 0) 4552 // Should check if RD is even-numbered, Rd != 14, addr[0:1] == 0, (CP15_reg1_U == 1 || addr[2] == 0)
4538 inst_cream->get_addr(cpu, inst_cream->inst, addr, 1); 4553 inst_cream->get_addr(cpu, inst_cream->inst, addr, 1);
4539 4554
4540 cpu->Reg[BITS(inst_cream->inst, 12, 15)] = Memory::Read32(addr); 4555 // The 3DS doesn't have LPAE (Large Physical Access Extension), so it
4541 cpu->Reg[BITS(inst_cream->inst, 12, 15) + 1] = Memory::Read32(addr + 4); 4556 // wouldn't do this as a single read.
4557 cpu->Reg[BITS(inst_cream->inst, 12, 15) + 0] = ReadMemory32(cpu, addr);
4558 cpu->Reg[BITS(inst_cream->inst, 12, 15) + 1] = ReadMemory32(cpu, addr + 4);
4542 4559
4543 // No dispatch since this operation should not modify R15 4560 // No dispatch since this operation should not modify R15
4544 } 4561 }
@@ -4557,7 +4574,7 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
4557 add_exclusive_addr(cpu, read_addr); 4574 add_exclusive_addr(cpu, read_addr);
4558 cpu->exclusive_state = 1; 4575 cpu->exclusive_state = 1;
4559 4576
4560 RD = Memory::Read32(read_addr); 4577 RD = ReadMemory32(cpu, read_addr);
4561 if (inst_cream->Rd == 15) { 4578 if (inst_cream->Rd == 15) {
4562 INC_PC(sizeof(generic_arm_inst)); 4579 INC_PC(sizeof(generic_arm_inst));
4563 goto DISPATCH; 4580 goto DISPATCH;
@@ -4597,7 +4614,7 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
4597 add_exclusive_addr(cpu, read_addr); 4614 add_exclusive_addr(cpu, read_addr);
4598 cpu->exclusive_state = 1; 4615 cpu->exclusive_state = 1;
4599 4616
4600 RD = Memory::Read16(read_addr); 4617 RD = ReadMemory16(cpu, read_addr);
4601 if (inst_cream->Rd == 15) { 4618 if (inst_cream->Rd == 15) {
4602 INC_PC(sizeof(generic_arm_inst)); 4619 INC_PC(sizeof(generic_arm_inst));
4603 goto DISPATCH; 4620 goto DISPATCH;
@@ -4617,8 +4634,8 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
4617 add_exclusive_addr(cpu, read_addr); 4634 add_exclusive_addr(cpu, read_addr);
4618 cpu->exclusive_state = 1; 4635 cpu->exclusive_state = 1;
4619 4636
4620 RD = Memory::Read32(read_addr); 4637 RD = ReadMemory32(cpu, read_addr);
4621 RD2 = Memory::Read32(read_addr + 4); 4638 RD2 = ReadMemory32(cpu, read_addr + 4);
4622 4639
4623 if (inst_cream->Rd == 15) { 4640 if (inst_cream->Rd == 15) {
4624 INC_PC(sizeof(generic_arm_inst)); 4641 INC_PC(sizeof(generic_arm_inst));
@@ -4635,7 +4652,8 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
4635 if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) { 4652 if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) {
4636 ldst_inst* inst_cream = (ldst_inst*)inst_base->component; 4653 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
4637 inst_cream->get_addr(cpu, inst_cream->inst, addr, 1); 4654 inst_cream->get_addr(cpu, inst_cream->inst, addr, 1);
4638 cpu->Reg[BITS(inst_cream->inst, 12, 15)] = Memory::Read16(addr); 4655
4656 cpu->Reg[BITS(inst_cream->inst, 12, 15)] = ReadMemory16(cpu, addr);
4639 if (BITS(inst_cream->inst, 12, 15) == 15) { 4657 if (BITS(inst_cream->inst, 12, 15) == 15) {
4640 INC_PC(sizeof(ldst_inst)); 4658 INC_PC(sizeof(ldst_inst));
4641 goto DISPATCH; 4659 goto DISPATCH;
@@ -4671,7 +4689,8 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
4671 if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) { 4689 if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) {
4672 ldst_inst* inst_cream = (ldst_inst*)inst_base->component; 4690 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
4673 inst_cream->get_addr(cpu, inst_cream->inst, addr, 1); 4691 inst_cream->get_addr(cpu, inst_cream->inst, addr, 1);
4674 unsigned int value = Memory::Read16(addr); 4692
4693 unsigned int value = ReadMemory16(cpu, addr);
4675 if (BIT(value, 15)) { 4694 if (BIT(value, 15)) {
4676 value |= 0xffff0000; 4695 value |= 0xffff0000;
4677 } 4696 }
@@ -4692,7 +4711,7 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
4692 ldst_inst* inst_cream = (ldst_inst*)inst_base->component; 4711 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
4693 inst_cream->get_addr(cpu, inst_cream->inst, addr, 1); 4712 inst_cream->get_addr(cpu, inst_cream->inst, addr, 1);
4694 4713
4695 unsigned int value = Memory::Read32(addr); 4714 unsigned int value = ReadMemory32(cpu, addr);
4696 cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value; 4715 cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value;
4697 4716
4698 if (BITS(inst_cream->inst, 12, 15) == 15) { 4717 if (BITS(inst_cream->inst, 12, 15) == 15) {
@@ -5521,6 +5540,23 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
5521 } 5540 }
5522 5541
5523 SETEND_INST: 5542 SETEND_INST:
5543 {
5544 // SETEND is unconditional
5545 setend_inst* const inst_cream = (setend_inst*)inst_base->component;
5546 const bool big_endian = (inst_cream->set_bigend == 1);
5547
5548 if (big_endian)
5549 cpu->Cpsr |= (1 << 9);
5550 else
5551 cpu->Cpsr &= ~(1 << 9);
5552
5553 LOG_WARNING(Core_ARM11, "SETEND %s executed", big_endian ? "BE" : "LE");
5554
5555 cpu->Reg[15] += GET_INST_SIZE(cpu);
5556 INC_PC(sizeof(setend_inst));
5557 FETCH_INST;
5558 GOTO_NEXT_INST;
5559 }
5524 5560
5525 SHADD8_INST: 5561 SHADD8_INST:
5526 SHADD16_INST: 5562 SHADD16_INST:
@@ -5976,36 +6012,36 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
5976 if (BIT(inst_cream->inst, 22) == 1) { 6012 if (BIT(inst_cream->inst, 22) == 1) {
5977 for (int i = 0; i < 13; i++) { 6013 for (int i = 0; i < 13; i++) {
5978 if (BIT(inst_cream->inst, i)) { 6014 if (BIT(inst_cream->inst, i)) {
5979 Memory::Write32(addr, cpu->Reg[i]); 6015 WriteMemory32(cpu, addr, cpu->Reg[i]);
5980 addr += 4; 6016 addr += 4;
5981 } 6017 }
5982 } 6018 }
5983 if (BIT(inst_cream->inst, 13)) { 6019 if (BIT(inst_cream->inst, 13)) {
5984 if (cpu->Mode == USER32MODE) 6020 if (cpu->Mode == USER32MODE)
5985 Memory::Write32(addr, cpu->Reg[13]); 6021 WriteMemory32(cpu, addr, cpu->Reg[13]);
5986 else 6022 else
5987 Memory::Write32(addr, cpu->Reg_usr[0]); 6023 WriteMemory32(cpu, addr, cpu->Reg_usr[0]);
5988 6024
5989 addr += 4; 6025 addr += 4;
5990 } 6026 }
5991 if (BIT(inst_cream->inst, 14)) { 6027 if (BIT(inst_cream->inst, 14)) {
5992 if (cpu->Mode == USER32MODE) 6028 if (cpu->Mode == USER32MODE)
5993 Memory::Write32(addr, cpu->Reg[14]); 6029 WriteMemory32(cpu, addr, cpu->Reg[14]);
5994 else 6030 else
5995 Memory::Write32(addr, cpu->Reg_usr[1]); 6031 WriteMemory32(cpu, addr, cpu->Reg_usr[1]);
5996 6032
5997 addr += 4; 6033 addr += 4;
5998 } 6034 }
5999 if (BIT(inst_cream->inst, 15)) { 6035 if (BIT(inst_cream->inst, 15)) {
6000 Memory::Write32(addr, cpu->Reg_usr[1] + 8); 6036 WriteMemory32(cpu, addr, cpu->Reg_usr[1] + 8);
6001 } 6037 }
6002 } else { 6038 } else {
6003 for (int i = 0; i < 15; i++) { 6039 for (int i = 0; i < 15; i++) {
6004 if (BIT(inst_cream->inst, i)) { 6040 if (BIT(inst_cream->inst, i)) {
6005 if (i == Rn) 6041 if (i == Rn)
6006 Memory::Write32(addr, old_RN); 6042 WriteMemory32(cpu, addr, old_RN);
6007 else 6043 else
6008 Memory::Write32(addr, cpu->Reg[i]); 6044 WriteMemory32(cpu, addr, cpu->Reg[i]);
6009 6045
6010 addr += 4; 6046 addr += 4;
6011 } 6047 }
@@ -6013,7 +6049,7 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
6013 6049
6014 // Check PC reg 6050 // Check PC reg
6015 if (BIT(inst_cream->inst, 15)) 6051 if (BIT(inst_cream->inst, 15))
6016 Memory::Write32(addr, cpu->Reg_usr[1] + 8); 6052 WriteMemory32(cpu, addr, cpu->Reg_usr[1] + 8);
6017 } 6053 }
6018 } 6054 }
6019 cpu->Reg[15] += GET_INST_SIZE(cpu); 6055 cpu->Reg[15] += GET_INST_SIZE(cpu);
@@ -6046,7 +6082,7 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
6046 inst_cream->get_addr(cpu, inst_cream->inst, addr, 0); 6082 inst_cream->get_addr(cpu, inst_cream->inst, addr, 0);
6047 6083
6048 unsigned int value = cpu->Reg[BITS(inst_cream->inst, 12, 15)]; 6084 unsigned int value = cpu->Reg[BITS(inst_cream->inst, 12, 15)];
6049 Memory::Write32(addr, value); 6085 WriteMemory32(cpu, addr, value);
6050 } 6086 }
6051 cpu->Reg[15] += GET_INST_SIZE(cpu); 6087 cpu->Reg[15] += GET_INST_SIZE(cpu);
6052 INC_PC(sizeof(ldst_inst)); 6088 INC_PC(sizeof(ldst_inst));
@@ -6109,10 +6145,10 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
6109 ldst_inst* inst_cream = (ldst_inst*)inst_base->component; 6145 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
6110 inst_cream->get_addr(cpu, inst_cream->inst, addr, 0); 6146 inst_cream->get_addr(cpu, inst_cream->inst, addr, 0);
6111 6147
6112 unsigned int value = cpu->Reg[BITS(inst_cream->inst, 12, 15)]; 6148 // The 3DS doesn't have the Large Physical Access Extension (LPAE)
6113 Memory::Write32(addr, value); 6149 // so STRD wouldn't store these as a single write.
6114 value = cpu->Reg[BITS(inst_cream->inst, 12, 15) + 1]; 6150 WriteMemory32(cpu, addr + 0, cpu->Reg[BITS(inst_cream->inst, 12, 15)]);
6115 Memory::Write32(addr + 4, value); 6151 WriteMemory32(cpu, addr + 4, cpu->Reg[BITS(inst_cream->inst, 12, 15) + 1]);
6116 } 6152 }
6117 cpu->Reg[15] += GET_INST_SIZE(cpu); 6153 cpu->Reg[15] += GET_INST_SIZE(cpu);
6118 INC_PC(sizeof(ldst_inst)); 6154 INC_PC(sizeof(ldst_inst));
@@ -6129,7 +6165,7 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
6129 remove_exclusive(cpu, write_addr); 6165 remove_exclusive(cpu, write_addr);
6130 cpu->exclusive_state = 0; 6166 cpu->exclusive_state = 0;
6131 6167
6132 Memory::Write32(write_addr, cpu->Reg[inst_cream->Rm]); 6168 WriteMemory32(cpu, write_addr, RM);
6133 RD = 0; 6169 RD = 0;
6134 } else { 6170 } else {
6135 // Failed to write due to mutex access 6171 // Failed to write due to mutex access
@@ -6173,8 +6209,16 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
6173 remove_exclusive(cpu, write_addr); 6209 remove_exclusive(cpu, write_addr);
6174 cpu->exclusive_state = 0; 6210 cpu->exclusive_state = 0;
6175 6211
6176 Memory::Write32(write_addr, cpu->Reg[inst_cream->Rm]); 6212 const u32 rt = cpu->Reg[inst_cream->Rm + 0];
6177 Memory::Write32(write_addr + 4, cpu->Reg[inst_cream->Rm + 1]); 6213 const u32 rt2 = cpu->Reg[inst_cream->Rm + 1];
6214 u64 value;
6215
6216 if (InBigEndianMode(cpu))
6217 value = (((u64)rt << 32) | rt2);
6218 else
6219 value = (((u64)rt2 << 32) | rt);
6220
6221 WriteMemory64(cpu, write_addr, value);
6178 RD = 0; 6222 RD = 0;
6179 } 6223 }
6180 else { 6224 else {
@@ -6197,7 +6241,7 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
6197 remove_exclusive(cpu, write_addr); 6241 remove_exclusive(cpu, write_addr);
6198 cpu->exclusive_state = 0; 6242 cpu->exclusive_state = 0;
6199 6243
6200 Memory::Write16(write_addr, cpu->Reg[inst_cream->Rm]); 6244 WriteMemory16(cpu, write_addr, RM);
6201 RD = 0; 6245 RD = 0;
6202 } else { 6246 } else {
6203 // Failed to write due to mutex access 6247 // Failed to write due to mutex access
@@ -6216,7 +6260,7 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
6216 inst_cream->get_addr(cpu, inst_cream->inst, addr, 0); 6260 inst_cream->get_addr(cpu, inst_cream->inst, addr, 0);
6217 6261
6218 unsigned int value = cpu->Reg[BITS(inst_cream->inst, 12, 15)] & 0xffff; 6262 unsigned int value = cpu->Reg[BITS(inst_cream->inst, 12, 15)] & 0xffff;
6219 Memory::Write16(addr, value); 6263 WriteMemory16(cpu, addr, value);
6220 } 6264 }
6221 cpu->Reg[15] += GET_INST_SIZE(cpu); 6265 cpu->Reg[15] += GET_INST_SIZE(cpu);
6222 INC_PC(sizeof(ldst_inst)); 6266 INC_PC(sizeof(ldst_inst));
@@ -6230,7 +6274,7 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
6230 inst_cream->get_addr(cpu, inst_cream->inst, addr, 0); 6274 inst_cream->get_addr(cpu, inst_cream->inst, addr, 0);
6231 6275
6232 unsigned int value = cpu->Reg[BITS(inst_cream->inst, 12, 15)]; 6276 unsigned int value = cpu->Reg[BITS(inst_cream->inst, 12, 15)];
6233 Memory::Write32(addr, value); 6277 WriteMemory32(cpu, addr, value);
6234 } 6278 }
6235 cpu->Reg[15] += GET_INST_SIZE(cpu); 6279 cpu->Reg[15] += GET_INST_SIZE(cpu);
6236 INC_PC(sizeof(ldst_inst)); 6280 INC_PC(sizeof(ldst_inst));
@@ -6289,8 +6333,8 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
6289 swp_inst* inst_cream = (swp_inst*)inst_base->component; 6333 swp_inst* inst_cream = (swp_inst*)inst_base->component;
6290 6334
6291 addr = RN; 6335 addr = RN;
6292 unsigned int value = Memory::Read32(addr); 6336 unsigned int value = ReadMemory32(cpu, addr);
6293 Memory::Write32(addr, RM); 6337 WriteMemory32(cpu, addr, RM);
6294 6338
6295 RD = value; 6339 RD = value;
6296 } 6340 }
diff --git a/src/core/arm/interpreter/armsupp.cpp b/src/core/arm/interpreter/armsupp.cpp
index ed4f6c2a2..aca2bfbbd 100644
--- a/src/core/arm/interpreter/armsupp.cpp
+++ b/src/core/arm/interpreter/armsupp.cpp
@@ -201,3 +201,9 @@ u32 ARMul_UnsignedSatQ(s32 value, u8 shift, bool* saturation_occurred)
201 *saturation_occurred = false; 201 *saturation_occurred = false;
202 return (u32)value; 202 return (u32)value;
203} 203}
204
205// Whether or not the given CPU is in big endian mode (E bit is set)
206bool InBigEndianMode(ARMul_State* cpu)
207{
208 return (cpu->Cpsr & (1 << 9)) != 0;
209}
diff --git a/src/core/arm/skyeye_common/armdefs.h b/src/core/arm/skyeye_common/armdefs.h
index 16f3ac86c..c1a19fecc 100644
--- a/src/core/arm/skyeye_common/armdefs.h
+++ b/src/core/arm/skyeye_common/armdefs.h
@@ -18,7 +18,6 @@
18#pragma once 18#pragma once
19 19
20#include "common/common_types.h" 20#include "common/common_types.h"
21#include "core/arm/skyeye_common/armmmu.h"
22#include "core/arm/skyeye_common/arm_regformat.h" 21#include "core/arm/skyeye_common/arm_regformat.h"
23#include "core/arm/skyeye_common/skyeye_defs.h" 22#include "core/arm/skyeye_common/skyeye_defs.h"
24 23
@@ -356,3 +355,5 @@ extern u16 ARMul_UnsignedSaturatedSub16(u16, u16);
356extern u8 ARMul_UnsignedAbsoluteDifference(u8, u8); 355extern u8 ARMul_UnsignedAbsoluteDifference(u8, u8);
357extern u32 ARMul_SignedSatQ(s32, u8, bool*); 356extern u32 ARMul_SignedSatQ(s32, u8, bool*);
358extern u32 ARMul_UnsignedSatQ(s32, u8, bool*); 357extern u32 ARMul_UnsignedSatQ(s32, u8, bool*);
358
359extern bool InBigEndianMode(ARMul_State*);
diff --git a/src/core/arm/skyeye_common/armmmu.h b/src/core/arm/skyeye_common/armmmu.h
index 6e54142ee..22e564c3d 100644
--- a/src/core/arm/skyeye_common/armmmu.h
+++ b/src/core/arm/skyeye_common/armmmu.h
@@ -20,37 +20,82 @@
20 20
21#pragma once 21#pragma once
22 22
23#include "core/mem_map.h"
24#include "core/arm/skyeye_common/armdefs.h"
25
23// Register numbers in the MMU 26// Register numbers in the MMU
24enum 27enum
25{ 28{
26 MMU_ID = 0, 29 MMU_ID = 0,
27 MMU_CONTROL = 1, 30 MMU_CONTROL = 1,
28 MMU_TRANSLATION_TABLE_BASE = 2, 31 MMU_TRANSLATION_TABLE_BASE = 2,
29 MMU_DOMAIN_ACCESS_CONTROL = 3, 32 MMU_DOMAIN_ACCESS_CONTROL = 3,
30 MMU_FAULT_STATUS = 5, 33 MMU_FAULT_STATUS = 5,
31 MMU_FAULT_ADDRESS = 6, 34 MMU_FAULT_ADDRESS = 6,
32 MMU_CACHE_OPS = 7, 35 MMU_CACHE_OPS = 7,
33 MMU_TLB_OPS = 8, 36 MMU_TLB_OPS = 8,
34 MMU_CACHE_LOCKDOWN = 9, 37 MMU_CACHE_LOCKDOWN = 9,
35 MMU_TLB_LOCKDOWN = 10, 38 MMU_TLB_LOCKDOWN = 10,
36 MMU_PID = 13, 39 MMU_PID = 13,
37 40
38 // MMU_V4 41 // MMU_V4
39 MMU_V4_CACHE_OPS = 7, 42 MMU_V4_CACHE_OPS = 7,
40 MMU_V4_TLB_OPS = 8, 43 MMU_V4_TLB_OPS = 8,
41 44
42 // MMU_V3 45 // MMU_V3
43 MMU_V3_FLUSH_TLB = 5, 46 MMU_V3_FLUSH_TLB = 5,
44 MMU_V3_FLUSH_TLB_ENTRY = 6, 47 MMU_V3_FLUSH_TLB_ENTRY = 6,
45 MMU_V3_FLUSH_CACHE = 7, 48 MMU_V3_FLUSH_CACHE = 7,
46
47 // MMU Intel SA-1100
48 MMU_SA_RB_OPS = 9,
49 MMU_SA_DEBUG = 14,
50 MMU_SA_CP15_R15 = 15,
51
52 // Intel xscale CP15
53 XSCALE_CP15_CACHE_TYPE = 0,
54 XSCALE_CP15_AUX_CONTROL = 1,
55 XSCALE_CP15_COPRO_ACCESS = 15,
56}; 49};
50
51// Reads data in big/little endian format based on the
52// state of the E (endian) bit in the emulated CPU's APSR.
53inline u16 ReadMemory16(ARMul_State* cpu, u32 address) {
54 u16 data = Memory::Read16(address);
55
56 if (InBigEndianMode(cpu))
57 data = Common::swap16(data);
58
59 return data;
60}
61
62inline u32 ReadMemory32(ARMul_State* cpu, u32 address) {
63 u32 data = Memory::Read32(address);
64
65 if (InBigEndianMode(cpu))
66 data = Common::swap32(data);
67
68 return data;
69}
70
71inline u64 ReadMemory64(ARMul_State* cpu, u32 address) {
72 u64 data = Memory::Read64(address);
73
74 if (InBigEndianMode(cpu))
75 data = Common::swap64(data);
76
77 return data;
78}
79
80// Writes data in big/little endian format based on the
81// state of the E (endian) bit in the emulated CPU's APSR.
82inline void WriteMemory16(ARMul_State* cpu, u32 address, u16 data) {
83 if (InBigEndianMode(cpu))
84 data = Common::swap16(data);
85
86 Memory::Write16(address, data);
87}
88
89inline void WriteMemory32(ARMul_State* cpu, u32 address, u32 data) {
90 if (InBigEndianMode(cpu))
91 data = Common::swap32(data);
92
93 Memory::Write32(address, data);
94}
95
96inline void WriteMemory64(ARMul_State* cpu, u32 address, u64 data) {
97 if (InBigEndianMode(cpu))
98 data = Common::swap64(data);
99
100 Memory::Write64(address, data);
101}
diff --git a/src/core/arm/skyeye_common/vfp/vfpinstr.cpp b/src/core/arm/skyeye_common/vfp/vfpinstr.cpp
index b9b96c388..368b5a25d 100644
--- a/src/core/arm/skyeye_common/vfp/vfpinstr.cpp
+++ b/src/core/arm/skyeye_common/vfp/vfpinstr.cpp
@@ -1388,12 +1388,20 @@ VSTR_INST:
1388 1388
1389 if (inst_cream->single) 1389 if (inst_cream->single)
1390 { 1390 {
1391 Memory::Write32(addr, cpu->ExtReg[inst_cream->d]); 1391 WriteMemory32(cpu, addr, cpu->ExtReg[inst_cream->d]);
1392 } 1392 }
1393 else 1393 else
1394 { 1394 {
1395 Memory::Write32(addr, cpu->ExtReg[inst_cream->d*2]); 1395 const u32 word1 = cpu->ExtReg[inst_cream->d*2+0];
1396 Memory::Write32(addr + 4, cpu->ExtReg[inst_cream->d*2+1]); 1396 const u32 word2 = cpu->ExtReg[inst_cream->d*2+1];
1397
1398 if (InBigEndianMode(cpu)) {
1399 WriteMemory32(cpu, addr + 0, word2);
1400 WriteMemory32(cpu, addr + 4, word1);
1401 } else {
1402 WriteMemory32(cpu, addr + 0, word1);
1403 WriteMemory32(cpu, addr + 4, word2);
1404 }
1397 } 1405 }
1398 } 1406 }
1399 cpu->Reg[15] += GET_INST_SIZE(cpu); 1407 cpu->Reg[15] += GET_INST_SIZE(cpu);
@@ -1447,17 +1455,27 @@ VPUSH_INST:
1447 { 1455 {
1448 if (inst_cream->single) 1456 if (inst_cream->single)
1449 { 1457 {
1450 Memory::Write32(addr, cpu->ExtReg[inst_cream->d+i]); 1458 WriteMemory32(cpu, addr, cpu->ExtReg[inst_cream->d+i]);
1451 addr += 4; 1459 addr += 4;
1452 } 1460 }
1453 else 1461 else
1454 { 1462 {
1455 Memory::Write32(addr, cpu->ExtReg[(inst_cream->d+i)*2]); 1463 const u32 word1 = cpu->ExtReg[(inst_cream->d+i)*2+0];
1456 Memory::Write32(addr + 4, cpu->ExtReg[(inst_cream->d+i)*2 + 1]); 1464 const u32 word2 = cpu->ExtReg[(inst_cream->d+i)*2+1];
1465
1466 if (InBigEndianMode(cpu)) {
1467 WriteMemory32(cpu, addr + 0, word2);
1468 WriteMemory32(cpu, addr + 4, word1);
1469 } else {
1470 WriteMemory32(cpu, addr + 0, word1);
1471 WriteMemory32(cpu, addr + 4, word2);
1472 }
1473
1457 addr += 8; 1474 addr += 8;
1458 } 1475 }
1459 } 1476 }
1460 cpu->Reg[R13] = cpu->Reg[R13] - inst_cream->imm32; 1477
1478 cpu->Reg[R13] -= inst_cream->imm32;
1461 } 1479 }
1462 cpu->Reg[15] += GET_INST_SIZE(cpu); 1480 cpu->Reg[15] += GET_INST_SIZE(cpu);
1463 INC_PC(sizeof(vpush_inst)); 1481 INC_PC(sizeof(vpush_inst));
@@ -1516,13 +1534,22 @@ VSTM_INST: /* encoding 1 */
1516 { 1534 {
1517 if (inst_cream->single) 1535 if (inst_cream->single)
1518 { 1536 {
1519 Memory::Write32(addr, cpu->ExtReg[inst_cream->d+i]); 1537 WriteMemory32(cpu, addr, cpu->ExtReg[inst_cream->d+i]);
1520 addr += 4; 1538 addr += 4;
1521 } 1539 }
1522 else 1540 else
1523 { 1541 {
1524 Memory::Write32(addr, cpu->ExtReg[(inst_cream->d+i)*2]); 1542 const u32 word1 = cpu->ExtReg[(inst_cream->d+i)*2+0];
1525 Memory::Write32(addr + 4, cpu->ExtReg[(inst_cream->d+i)*2 + 1]); 1543 const u32 word2 = cpu->ExtReg[(inst_cream->d+i)*2+1];
1544
1545 if (InBigEndianMode(cpu)) {
1546 WriteMemory32(cpu, addr + 0, word2);
1547 WriteMemory32(cpu, addr + 4, word1);
1548 } else {
1549 WriteMemory32(cpu, addr + 0, word1);
1550 WriteMemory32(cpu, addr + 4, word2);
1551 }
1552
1526 addr += 8; 1553 addr += 8;
1527 } 1554 }
1528 } 1555 }
@@ -1575,8 +1602,6 @@ VPOP_INST:
1575 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 1602 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
1576 CHECK_VFP_ENABLED; 1603 CHECK_VFP_ENABLED;
1577 1604
1578 unsigned int value1, value2;
1579
1580 vpop_inst *inst_cream = (vpop_inst *)inst_base->component; 1605 vpop_inst *inst_cream = (vpop_inst *)inst_base->component;
1581 1606
1582 addr = cpu->Reg[R13]; 1607 addr = cpu->Reg[R13];
@@ -1585,20 +1610,26 @@ VPOP_INST:
1585 { 1610 {
1586 if (inst_cream->single) 1611 if (inst_cream->single)
1587 { 1612 {
1588 value1 = Memory::Read32(addr); 1613 cpu->ExtReg[inst_cream->d+i] = ReadMemory32(cpu, addr);
1589 cpu->ExtReg[inst_cream->d+i] = value1;
1590 addr += 4; 1614 addr += 4;
1591 } 1615 }
1592 else 1616 else
1593 { 1617 {
1594 value1 = Memory::Read32(addr); 1618 const u32 word1 = ReadMemory32(cpu, addr + 0);
1595 value2 = Memory::Read32(addr + 4); 1619 const u32 word2 = ReadMemory32(cpu, addr + 4);
1596 cpu->ExtReg[(inst_cream->d+i)*2] = value1; 1620
1597 cpu->ExtReg[(inst_cream->d+i)*2 + 1] = value2; 1621 if (InBigEndianMode(cpu)) {
1622 cpu->ExtReg[(inst_cream->d+i)*2+0] = word2;
1623 cpu->ExtReg[(inst_cream->d+i)*2+1] = word1;
1624 } else {
1625 cpu->ExtReg[(inst_cream->d+i)*2+0] = word1;
1626 cpu->ExtReg[(inst_cream->d+i)*2+1] = word2;
1627 }
1628
1598 addr += 8; 1629 addr += 8;
1599 } 1630 }
1600 } 1631 }
1601 cpu->Reg[R13] = cpu->Reg[R13] + inst_cream->imm32; 1632 cpu->Reg[R13] += inst_cream->imm32;
1602 } 1633 }
1603 cpu->Reg[15] += GET_INST_SIZE(cpu); 1634 cpu->Reg[15] += GET_INST_SIZE(cpu);
1604 INC_PC(sizeof(vpop_inst)); 1635 INC_PC(sizeof(vpop_inst));
@@ -1653,16 +1684,20 @@ VLDR_INST:
1653 1684
1654 if (inst_cream->single) 1685 if (inst_cream->single)
1655 { 1686 {
1656 cpu->ExtReg[inst_cream->d] = Memory::Read32(addr); 1687 cpu->ExtReg[inst_cream->d] = ReadMemory32(cpu, addr);
1657 } 1688 }
1658 else 1689 else
1659 { 1690 {
1660 unsigned int word1, word2; 1691 const u32 word1 = ReadMemory32(cpu, addr + 0);
1661 word1 = Memory::Read32(addr); 1692 const u32 word2 = ReadMemory32(cpu, addr + 4);
1662 word2 = Memory::Read32(addr + 4); 1693
1663 1694 if (InBigEndianMode(cpu)) {
1664 cpu->ExtReg[inst_cream->d*2] = word1; 1695 cpu->ExtReg[inst_cream->d*2+0] = word2;
1665 cpu->ExtReg[inst_cream->d*2+1] = word2; 1696 cpu->ExtReg[inst_cream->d*2+1] = word1;
1697 } else {
1698 cpu->ExtReg[inst_cream->d*2+0] = word1;
1699 cpu->ExtReg[inst_cream->d*2+1] = word2;
1700 }
1666 } 1701 }
1667 } 1702 }
1668 cpu->Reg[15] += GET_INST_SIZE(cpu); 1703 cpu->Reg[15] += GET_INST_SIZE(cpu);
@@ -1722,13 +1757,22 @@ VLDM_INST:
1722 { 1757 {
1723 if (inst_cream->single) 1758 if (inst_cream->single)
1724 { 1759 {
1725 cpu->ExtReg[inst_cream->d+i] = Memory::Read32(addr); 1760 cpu->ExtReg[inst_cream->d+i] = ReadMemory32(cpu, addr);
1726 addr += 4; 1761 addr += 4;
1727 } 1762 }
1728 else 1763 else
1729 { 1764 {
1730 cpu->ExtReg[(inst_cream->d+i)*2] = Memory::Read32(addr); 1765 const u32 word1 = ReadMemory32(cpu, addr + 0);
1731 cpu->ExtReg[(inst_cream->d+i)*2 + 1] = Memory::Read32(addr + 4); 1766 const u32 word2 = ReadMemory32(cpu, addr + 4);
1767
1768 if (InBigEndianMode(cpu)) {
1769 cpu->ExtReg[(inst_cream->d+i)*2+0] = word2;
1770 cpu->ExtReg[(inst_cream->d+i)*2+1] = word1;
1771 } else {
1772 cpu->ExtReg[(inst_cream->d+i)*2+0] = word1;
1773 cpu->ExtReg[(inst_cream->d+i)*2+1] = word2;
1774 }
1775
1732 addr += 8; 1776 addr += 8;
1733 } 1777 }
1734 } 1778 }
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp
index e7f9bec7e..138603d9b 100644
--- a/src/core/hle/service/hid/hid.cpp
+++ b/src/core/hle/service/hid/hid.cpp
@@ -7,7 +7,7 @@
7#include "core/hle/service/hid/hid_spvr.h" 7#include "core/hle/service/hid/hid_spvr.h"
8#include "core/hle/service/hid/hid_user.h" 8#include "core/hle/service/hid/hid_user.h"
9 9
10#include "core/arm/arm_interface.h" 10#include "core/core_timing.h"
11#include "core/hle/kernel/event.h" 11#include "core/hle/kernel/event.h"
12#include "core/hle/kernel/shared_memory.h" 12#include "core/hle/kernel/shared_memory.h"
13#include "core/hle/hle.h" 13#include "core/hle/hle.h"
@@ -82,7 +82,7 @@ void HIDUpdate() {
82 // If we just updated index 0, provide a new timestamp 82 // If we just updated index 0, provide a new timestamp
83 if (mem->pad.index == 0) { 83 if (mem->pad.index == 0) {
84 mem->pad.index_reset_ticks_previous = mem->pad.index_reset_ticks; 84 mem->pad.index_reset_ticks_previous = mem->pad.index_reset_ticks;
85 mem->pad.index_reset_ticks = (s64)Core::g_app_core->GetTicks(); 85 mem->pad.index_reset_ticks = (s64)CoreTiming::GetTicks();
86 } 86 }
87 87
88 mem->touch.index = next_touch_index; 88 mem->touch.index = next_touch_index;
@@ -102,7 +102,7 @@ void HIDUpdate() {
102 // If we just updated index 0, provide a new timestamp 102 // If we just updated index 0, provide a new timestamp
103 if (mem->touch.index == 0) { 103 if (mem->touch.index == 0) {
104 mem->touch.index_reset_ticks_previous = mem->touch.index_reset_ticks; 104 mem->touch.index_reset_ticks_previous = mem->touch.index_reset_ticks;
105 mem->touch.index_reset_ticks = (s64)Core::g_app_core->GetTicks(); 105 mem->touch.index_reset_ticks = (s64)CoreTiming::GetTicks();
106 } 106 }
107 107
108 // Signal both handles when there's an update to Pad or touch 108 // Signal both handles when there's an update to Pad or touch
@@ -114,6 +114,7 @@ void GetIPCHandles(Service::Interface* self) {
114 u32* cmd_buff = Kernel::GetCommandBuffer(); 114 u32* cmd_buff = Kernel::GetCommandBuffer();
115 115
116 cmd_buff[1] = 0; // No error 116 cmd_buff[1] = 0; // No error
117 cmd_buff[2] = 0x14000000; // IPC Command Structure translate-header
117 // TODO(yuriks): Return error from SendSyncRequest is this fails (part of IPC marshalling) 118 // TODO(yuriks): Return error from SendSyncRequest is this fails (part of IPC marshalling)
118 cmd_buff[3] = Kernel::g_handle_table.Create(Service::HID::shared_mem).MoveFrom(); 119 cmd_buff[3] = Kernel::g_handle_table.Create(Service::HID::shared_mem).MoveFrom();
119 cmd_buff[4] = Kernel::g_handle_table.Create(Service::HID::event_pad_or_touch_1).MoveFrom(); 120 cmd_buff[4] = Kernel::g_handle_table.Create(Service::HID::event_pad_or_touch_1).MoveFrom();
@@ -123,6 +124,37 @@ void GetIPCHandles(Service::Interface* self) {
123 cmd_buff[8] = Kernel::g_handle_table.Create(Service::HID::event_debug_pad).MoveFrom(); 124 cmd_buff[8] = Kernel::g_handle_table.Create(Service::HID::event_debug_pad).MoveFrom();
124} 125}
125 126
127void EnableAccelerometer(Service::Interface* self) {
128 u32* cmd_buff = Kernel::GetCommandBuffer();
129
130 event_accelerometer->Signal();
131
132 cmd_buff[1] = RESULT_SUCCESS.raw;
133
134 LOG_WARNING(Service_HID, "(STUBBED) called");
135}
136
137void EnableGyroscopeLow(Service::Interface* self) {
138 u32* cmd_buff = Kernel::GetCommandBuffer();
139
140 event_gyroscope->Signal();
141
142 cmd_buff[1] = RESULT_SUCCESS.raw;
143
144 LOG_WARNING(Service_HID, "(STUBBED) called");
145}
146
147void GetSoundVolume(Service::Interface* self) {
148 u32* cmd_buff = Kernel::GetCommandBuffer();
149
150 const u8 volume = 0x3F; // TODO(purpasmart): Find out if this is the max value for the volume
151
152 cmd_buff[1] = RESULT_SUCCESS.raw;
153 cmd_buff[2] = volume;
154
155 LOG_WARNING(Service_HID, "(STUBBED) called");
156}
157
126void HIDInit() { 158void HIDInit() {
127 using namespace Kernel; 159 using namespace Kernel;
128 160
diff --git a/src/core/hle/service/hid/hid.h b/src/core/hle/service/hid/hid.h
index 0946cf660..97462c7f8 100644
--- a/src/core/hle/service/hid/hid.h
+++ b/src/core/hle/service/hid/hid.h
@@ -161,7 +161,7 @@ const PadState PAD_CIRCLE_DOWN = {{1u << 31}};
161 * None 161 * None
162 * Outputs: 162 * Outputs:
163 * 1 : Result of function, 0 on success, otherwise error code 163 * 1 : Result of function, 0 on success, otherwise error code
164 * 2 : Unused 164 * 2 : IPC Command Structure translate-header
165 * 3 : Handle to HID_User shared memory 165 * 3 : Handle to HID_User shared memory
166 * 4 : Event signaled by HID_User 166 * 4 : Event signaled by HID_User
167 * 5 : Event signaled by HID_User 167 * 5 : Event signaled by HID_User
@@ -171,6 +171,34 @@ const PadState PAD_CIRCLE_DOWN = {{1u << 31}};
171 */ 171 */
172void GetIPCHandles(Interface* self); 172void GetIPCHandles(Interface* self);
173 173
174/**
175 * HID::EnableAccelerometer service function
176 * Inputs:
177 * None
178 * Outputs:
179 * 1 : Result of function, 0 on success, otherwise error code
180 */
181void EnableAccelerometer(Interface* self);
182
183/**
184 * HID::EnableGyroscopeLow service function
185 * Inputs:
186 * None
187 * Outputs:
188 * 1 : Result of function, 0 on success, otherwise error code
189 */
190void EnableGyroscopeLow(Interface* self);
191
192/**
193 * HID::GetSoundVolume service function
194 * Inputs:
195 * None
196 * Outputs:
197 * 1 : Result of function, 0 on success, otherwise error code
198 * 2 : u8 output value
199 */
200void GetSoundVolume(Interface* self);
201
174/// Checks for user input updates 202/// Checks for user input updates
175void HIDUpdate(); 203void HIDUpdate();
176 204
diff --git a/src/core/hle/service/hid/hid_spvr.cpp b/src/core/hle/service/hid/hid_spvr.cpp
index 790dcabbf..f296b076f 100644
--- a/src/core/hle/service/hid/hid_spvr.cpp
+++ b/src/core/hle/service/hid/hid_spvr.cpp
@@ -13,13 +13,13 @@ const Interface::FunctionInfo FunctionTable[] = {
13 {0x000A0000, GetIPCHandles, "GetIPCHandles"}, 13 {0x000A0000, GetIPCHandles, "GetIPCHandles"},
14 {0x000B0000, nullptr, "StartAnalogStickCalibration"}, 14 {0x000B0000, nullptr, "StartAnalogStickCalibration"},
15 {0x000E0000, nullptr, "GetAnalogStickCalibrateParam"}, 15 {0x000E0000, nullptr, "GetAnalogStickCalibrateParam"},
16 {0x00110000, nullptr, "EnableAccelerometer"}, 16 {0x00110000, EnableAccelerometer, "EnableAccelerometer"},
17 {0x00120000, nullptr, "DisableAccelerometer"}, 17 {0x00120000, nullptr, "DisableAccelerometer"},
18 {0x00130000, nullptr, "EnableGyroscopeLow"}, 18 {0x00130000, EnableGyroscopeLow, "EnableGyroscopeLow"},
19 {0x00140000, nullptr, "DisableGyroscopeLow"}, 19 {0x00140000, nullptr, "DisableGyroscopeLow"},
20 {0x00150000, nullptr, "GetGyroscopeLowRawToDpsCoefficient"}, 20 {0x00150000, nullptr, "GetGyroscopeLowRawToDpsCoefficient"},
21 {0x00160000, nullptr, "GetGyroscopeLowCalibrateParam"}, 21 {0x00160000, nullptr, "GetGyroscopeLowCalibrateParam"},
22 {0x00170000, nullptr, "GetSoundVolume"}, 22 {0x00170000, GetSoundVolume, "GetSoundVolume"},
23}; 23};
24 24
25HID_SPVR_Interface::HID_SPVR_Interface() { 25HID_SPVR_Interface::HID_SPVR_Interface() {
diff --git a/src/core/hle/service/hid/hid_user.cpp b/src/core/hle/service/hid/hid_user.cpp
index c2d5758fb..3682c9416 100644
--- a/src/core/hle/service/hid/hid_user.cpp
+++ b/src/core/hle/service/hid/hid_user.cpp
@@ -10,14 +10,14 @@ namespace Service {
10namespace HID { 10namespace HID {
11 11
12const Interface::FunctionInfo FunctionTable[] = { 12const Interface::FunctionInfo FunctionTable[] = {
13 {0x000A0000, GetIPCHandles, "GetIPCHandles"}, 13 {0x000A0000, GetIPCHandles, "GetIPCHandles"},
14 {0x00110000, nullptr, "EnableAccelerometer"}, 14 {0x00110000, EnableAccelerometer, "EnableAccelerometer"},
15 {0x00120000, nullptr, "DisableAccelerometer"}, 15 {0x00120000, nullptr, "DisableAccelerometer"},
16 {0x00130000, nullptr, "EnableGyroscopeLow"}, 16 {0x00130000, EnableGyroscopeLow, "EnableGyroscopeLow"},
17 {0x00140000, nullptr, "DisableGyroscopeLow"}, 17 {0x00140000, nullptr, "DisableGyroscopeLow"},
18 {0x00150000, nullptr, "GetGyroscopeLowRawToDpsCoefficient"}, 18 {0x00150000, nullptr, "GetGyroscopeLowRawToDpsCoefficient"},
19 {0x00160000, nullptr, "GetGyroscopeLowCalibrateParam"}, 19 {0x00160000, nullptr, "GetGyroscopeLowCalibrateParam"},
20 {0x00170000, nullptr, "GetSoundVolume"}, 20 {0x00170000, GetSoundVolume, "GetSoundVolume"},
21}; 21};
22 22
23HID_U_Interface::HID_U_Interface() { 23HID_U_Interface::HID_U_Interface() {
diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp
index 17385f9b2..bbb4eb9cd 100644
--- a/src/core/hle/svc.cpp
+++ b/src/core/hle/svc.cpp
@@ -7,8 +7,9 @@
7#include "common/string_util.h" 7#include "common/string_util.h"
8#include "common/symbols.h" 8#include "common/symbols.h"
9 9
10#include "core/arm/arm_interface.h" 10#include "core/core_timing.h"
11#include "core/mem_map.h" 11#include "core/mem_map.h"
12#include "core/arm/arm_interface.h"
12 13
13#include "core/hle/kernel/address_arbiter.h" 14#include "core/hle/kernel/address_arbiter.h"
14#include "core/hle/kernel/event.h" 15#include "core/hle/kernel/event.h"
@@ -551,7 +552,7 @@ static void SleepThread(s64 nanoseconds) {
551 552
552/// This returns the total CPU ticks elapsed since the CPU was powered-on 553/// This returns the total CPU ticks elapsed since the CPU was powered-on
553static s64 GetSystemTick() { 554static s64 GetSystemTick() {
554 return (s64)Core::g_app_core->GetTicks(); 555 return (s64)CoreTiming::GetTicks();
555} 556}
556 557
557/// Creates a memory block at the specified address with the specified permissions and size 558/// Creates a memory block at the specified address with the specified permissions and size
diff --git a/src/core/hw/gpu.cpp b/src/core/hw/gpu.cpp
index f933a5e8d..e6983a225 100644
--- a/src/core/hw/gpu.cpp
+++ b/src/core/hw/gpu.cpp
@@ -118,8 +118,14 @@ inline void Write(u32 addr, const T data) {
118 u8* src_pointer = Memory::GetPointer(Memory::PhysicalToVirtualAddress(config.GetPhysicalInputAddress())); 118 u8* src_pointer = Memory::GetPointer(Memory::PhysicalToVirtualAddress(config.GetPhysicalInputAddress()));
119 u8* dst_pointer = Memory::GetPointer(Memory::PhysicalToVirtualAddress(config.GetPhysicalOutputAddress())); 119 u8* dst_pointer = Memory::GetPointer(Memory::PhysicalToVirtualAddress(config.GetPhysicalOutputAddress()));
120 120
121 unsigned horizontal_scale = (config.scale_horizontally != 0) ? 2 : 1; 121 if (config.scaling > config.ScaleXY) {
122 unsigned vertical_scale = (config.scale_vertically != 0) ? 2 : 1; 122 LOG_CRITICAL(HW_GPU, "Unimplemented display transfer scaling mode %u", config.scaling.Value());
123 UNIMPLEMENTED();
124 break;
125 }
126
127 unsigned horizontal_scale = (config.scaling != config.NoScale) ? 2 : 1;
128 unsigned vertical_scale = (config.scaling == config.ScaleXY) ? 2 : 1;
123 129
124 u32 output_width = config.output_width / horizontal_scale; 130 u32 output_width = config.output_width / horizontal_scale;
125 u32 output_height = config.output_height / vertical_scale; 131 u32 output_height = config.output_height / vertical_scale;
@@ -140,14 +146,23 @@ inline void Write(u32 addr, const T data) {
140 break; 146 break;
141 } 147 }
142 148
143 // TODO(Subv): Blend the pixels when horizontal / vertical scaling is enabled, 149 // TODO(Subv): Implement the box filter when scaling is enabled
144 // right now we're just skipping the extra pixels. 150 // right now we're just skipping the extra pixels.
145 for (u32 y = 0; y < output_height; ++y) { 151 for (u32 y = 0; y < output_height; ++y) {
146 for (u32 x = 0; x < output_width; ++x) { 152 for (u32 x = 0; x < output_width; ++x) {
147 Math::Vec4<u8> src_color = { 0, 0, 0, 0 }; 153 Math::Vec4<u8> src_color = { 0, 0, 0, 0 };
148 154
149 u32 scaled_x = x * horizontal_scale; 155 // Calculate the [x,y] position of the input image
150 u32 scaled_y = y * vertical_scale; 156 // based on the current output position and the scale
157 u32 input_x = x * horizontal_scale;
158 u32 input_y = y * vertical_scale;
159
160 if (config.flip_vertically) {
161 // Flip the y value of the output data,
162 // we do this after calculating the [x,y] position of the input image
163 // to account for the scaling options.
164 y = output_height - y - 1;
165 }
151 166
152 u32 dst_bytes_per_pixel = GPU::Regs::BytesPerPixel(config.output_format); 167 u32 dst_bytes_per_pixel = GPU::Regs::BytesPerPixel(config.output_format);
153 u32 src_bytes_per_pixel = GPU::Regs::BytesPerPixel(config.input_format); 168 u32 src_bytes_per_pixel = GPU::Regs::BytesPerPixel(config.input_format);
@@ -159,14 +174,14 @@ inline void Write(u32 addr, const T data) {
159 u32 coarse_y = y & ~7; 174 u32 coarse_y = y & ~7;
160 u32 stride = output_width * dst_bytes_per_pixel; 175 u32 stride = output_width * dst_bytes_per_pixel;
161 176
162 src_offset = (scaled_x + scaled_y * config.input_width) * src_bytes_per_pixel; 177 src_offset = (input_x + input_y * config.input_width) * src_bytes_per_pixel;
163 dst_offset = VideoCore::GetMortonOffset(x, y, dst_bytes_per_pixel) + coarse_y * stride; 178 dst_offset = VideoCore::GetMortonOffset(x, y, dst_bytes_per_pixel) + coarse_y * stride;
164 } else { 179 } else {
165 // Interpret the input as tiled and the output as linear 180 // Interpret the input as tiled and the output as linear
166 u32 coarse_y = scaled_y & ~7; 181 u32 coarse_y = input_y & ~7;
167 u32 stride = config.input_width * src_bytes_per_pixel; 182 u32 stride = config.input_width * src_bytes_per_pixel;
168 183
169 src_offset = VideoCore::GetMortonOffset(scaled_x, scaled_y, src_bytes_per_pixel) + coarse_y * stride; 184 src_offset = VideoCore::GetMortonOffset(input_x, input_y, src_bytes_per_pixel) + coarse_y * stride;
170 dst_offset = (x + y * output_width) * dst_bytes_per_pixel; 185 dst_offset = (x + y * output_width) * dst_bytes_per_pixel;
171 } 186 }
172 187
diff --git a/src/core/hw/gpu.h b/src/core/hw/gpu.h
index 5b7f0a4e9..c8f884494 100644
--- a/src/core/hw/gpu.h
+++ b/src/core/hw/gpu.h
@@ -188,17 +188,22 @@ struct Regs {
188 BitField<16, 16, u32> input_height; 188 BitField<16, 16, u32> input_height;
189 }; 189 };
190 190
191 enum ScalingMode : u32 {
192 NoScale = 0, // Doesn't scale the image
193 ScaleX = 1, // Downscales the image in half in the X axis and applies a box filter
194 ScaleXY = 2, // Downscales the image in half in both the X and Y axes and applies a box filter
195 };
196
191 union { 197 union {
192 u32 flags; 198 u32 flags;
193 199
194 BitField< 0, 1, u32> flip_data; // flips input data horizontally (TODO) if true 200 BitField< 0, 1, u32> flip_vertically; // flips input data vertically
195 BitField< 1, 1, u32> output_tiled; // Converts from linear to tiled format 201 BitField< 1, 1, u32> output_tiled; // Converts from linear to tiled format
196 BitField< 3, 1, u32> raw_copy; // Copies the data without performing any processing 202 BitField< 3, 1, u32> raw_copy; // Copies the data without performing any processing
197 BitField< 8, 3, PixelFormat> input_format; 203 BitField< 8, 3, PixelFormat> input_format;
198 BitField<12, 3, PixelFormat> output_format; 204 BitField<12, 3, PixelFormat> output_format;
199 205
200 BitField<24, 1, u32> scale_horizontally; 206 BitField<24, 2, ScalingMode> scaling; // Determines the scaling mode of the transfer
201 BitField<25, 1, u32> scale_vertically;
202 }; 207 };
203 208
204 INSERT_PADDING_WORDS(0x1); 209 INSERT_PADDING_WORDS(0x1);
diff --git a/src/core/loader/ncch.h b/src/core/loader/ncch.h
index 9ae2de99f..f6f670060 100644
--- a/src/core/loader/ncch.h
+++ b/src/core/loader/ncch.h
@@ -20,8 +20,8 @@ struct NCCH_Header {
20 u16 version; 20 u16 version;
21 u8 reserved_0[4]; 21 u8 reserved_0[4];
22 u8 program_id[8]; 22 u8 program_id[8];
23 u8 temp_flag; 23 u8 reserved_1[0x10];
24 u8 reserved_1[0x2f]; 24 u8 logo_region_hash[0x20];
25 u8 product_code[0x10]; 25 u8 product_code[0x10];
26 u8 extended_header_hash[0x20]; 26 u8 extended_header_hash[0x20];
27 u32 extended_header_size; 27 u32 extended_header_size;
@@ -29,15 +29,16 @@ struct NCCH_Header {
29 u8 flags[8]; 29 u8 flags[8];
30 u32 plain_region_offset; 30 u32 plain_region_offset;
31 u32 plain_region_size; 31 u32 plain_region_size;
32 u8 reserved_3[8]; 32 u32 logo_region_offset;
33 u32 logo_region_size;
33 u32 exefs_offset; 34 u32 exefs_offset;
34 u32 exefs_size; 35 u32 exefs_size;
35 u32 exefs_hash_region_size; 36 u32 exefs_hash_region_size;
36 u8 reserved_4[4]; 37 u8 reserved_3[4];
37 u32 romfs_offset; 38 u32 romfs_offset;
38 u32 romfs_size; 39 u32 romfs_size;
39 u32 romfs_hash_region_size; 40 u32 romfs_hash_region_size;
40 u8 reserved_5[4]; 41 u8 reserved_4[4];
41 u8 exefs_super_block_hash[0x20]; 42 u8 exefs_super_block_hash[0x20];
42 u8 romfs_super_block_hash[0x20]; 43 u8 romfs_super_block_hash[0x20];
43}; 44};
@@ -88,8 +89,7 @@ struct ExHeader_DependencyList{
88}; 89};
89 90
90struct ExHeader_SystemInfo{ 91struct ExHeader_SystemInfo{
91 u32 save_data_size; 92 u64 save_data_size;
92 u8 reserved[4];
93 u8 jump_id[8]; 93 u8 jump_id[8];
94 u8 reserved_2[0x30]; 94 u8 reserved_2[0x30];
95}; 95};
@@ -104,11 +104,14 @@ struct ExHeader_StorageInfo{
104 104
105struct ExHeader_ARM11_SystemLocalCaps{ 105struct ExHeader_ARM11_SystemLocalCaps{
106 u8 program_id[8]; 106 u8 program_id[8];
107 u8 flags[8]; 107 u32 core_version;
108 u8 resource_limit_descriptor[0x10][2]; 108 u8 flags[3];
109 u8 priority;
110 u8 resource_limit_descriptor[0x16][2];
109 ExHeader_StorageInfo storage_info; 111 ExHeader_StorageInfo storage_info;
110 u8 service_access_control[0x20][8]; 112 u8 service_access_control[0x32][8];
111 u8 reserved[0x1f]; 113 u8 ex_service_access_control[0x2][8];
114 u8 reserved[0xf];
112 u8 resource_limit_category; 115 u8 resource_limit_category;
113}; 116};
114 117
diff --git a/src/core/mem_map.h b/src/core/mem_map.h
index 8f4f21fec..bce99dffa 100644
--- a/src/core/mem_map.h
+++ b/src/core/mem_map.h
@@ -147,6 +147,7 @@ inline void Write(VAddr addr, T data);
147u8 Read8(VAddr addr); 147u8 Read8(VAddr addr);
148u16 Read16(VAddr addr); 148u16 Read16(VAddr addr);
149u32 Read32(VAddr addr); 149u32 Read32(VAddr addr);
150u64 Read64(VAddr addr);
150 151
151u32 Read8_ZX(VAddr addr); 152u32 Read8_ZX(VAddr addr);
152u32 Read16_ZX(VAddr addr); 153u32 Read16_ZX(VAddr addr);
diff --git a/src/core/mem_map_funcs.cpp b/src/core/mem_map_funcs.cpp
index 48f61db4e..a161a8204 100644
--- a/src/core/mem_map_funcs.cpp
+++ b/src/core/mem_map_funcs.cpp
@@ -245,6 +245,12 @@ u32 Read32(const VAddr addr) {
245 return (u32)data; 245 return (u32)data;
246} 246}
247 247
248u64 Read64(const VAddr addr) {
249 u64_le data = 0;
250 Read<u64_le>(data, addr);
251 return (u64)data;
252}
253
248u32 Read8_ZX(const VAddr addr) { 254u32 Read8_ZX(const VAddr addr) {
249 return (u32)Read8(addr); 255 return (u32)Read8(addr);
250} 256}
diff --git a/src/video_core/color.h b/src/video_core/color.h
index 14ade74f2..43d635e2c 100644
--- a/src/video_core/color.h
+++ b/src/video_core/color.h
@@ -124,7 +124,7 @@ inline u32 DecodeD24(const u8* bytes) {
124 * @return Resulting values stored as a Math::Vec2 124 * @return Resulting values stored as a Math::Vec2
125 */ 125 */
126inline const Math::Vec2<u32> DecodeD24S8(const u8* bytes) { 126inline const Math::Vec2<u32> DecodeD24S8(const u8* bytes) {
127 return { (bytes[2] << 16) | (bytes[1] << 8) | bytes[0], bytes[3] }; 127 return { static_cast<u32>((bytes[2] << 16) | (bytes[1] << 8) | bytes[0]), bytes[3] };
128} 128}
129 129
130/** 130/**
diff --git a/src/video_core/debug_utils/debug_utils.cpp b/src/video_core/debug_utils/debug_utils.cpp
index 745c4f4ed..83982b4f2 100644
--- a/src/video_core/debug_utils/debug_utils.cpp
+++ b/src/video_core/debug_utils/debug_utils.cpp
@@ -322,7 +322,7 @@ const Math::Vec4<u8> LookupTexture(const u8* source, int x, int y, const Texture
322 case Regs::TextureFormat::RGBA8: 322 case Regs::TextureFormat::RGBA8:
323 { 323 {
324 auto res = Color::DecodeRGBA8(source + VideoCore::GetMortonOffset(x, y, 4)); 324 auto res = Color::DecodeRGBA8(source + VideoCore::GetMortonOffset(x, y, 4));
325 return { res.r(), res.g(), res.b(), disable_alpha ? 255 : res.a() }; 325 return { res.r(), res.g(), res.b(), static_cast<u8>(disable_alpha ? 255 : res.a()) };
326 } 326 }
327 327
328 case Regs::TextureFormat::RGB8: 328 case Regs::TextureFormat::RGB8:
@@ -334,7 +334,7 @@ const Math::Vec4<u8> LookupTexture(const u8* source, int x, int y, const Texture
334 case Regs::TextureFormat::RGB5A1: 334 case Regs::TextureFormat::RGB5A1:
335 { 335 {
336 auto res = Color::DecodeRGB5A1(source + VideoCore::GetMortonOffset(x, y, 2)); 336 auto res = Color::DecodeRGB5A1(source + VideoCore::GetMortonOffset(x, y, 2));
337 return { res.r(), res.g(), res.b(), disable_alpha ? 255 : res.a() }; 337 return { res.r(), res.g(), res.b(), static_cast<u8>(disable_alpha ? 255 : res.a()) };
338 } 338 }
339 339
340 case Regs::TextureFormat::RGB565: 340 case Regs::TextureFormat::RGB565:
@@ -346,7 +346,7 @@ const Math::Vec4<u8> LookupTexture(const u8* source, int x, int y, const Texture
346 case Regs::TextureFormat::RGBA4: 346 case Regs::TextureFormat::RGBA4:
347 { 347 {
348 auto res = Color::DecodeRGBA4(source + VideoCore::GetMortonOffset(x, y, 2)); 348 auto res = Color::DecodeRGBA4(source + VideoCore::GetMortonOffset(x, y, 2));
349 return { res.r(), res.g(), res.b(), disable_alpha ? 255 : res.a() }; 349 return { res.r(), res.g(), res.b(), static_cast<u8>(disable_alpha ? 255 : res.a()) };
350 } 350 }
351 351
352 case Regs::TextureFormat::IA8: 352 case Regs::TextureFormat::IA8:
diff --git a/src/video_core/vertex_shader.cpp b/src/video_core/vertex_shader.cpp
index 4eb3e743e..e8d865172 100644
--- a/src/video_core/vertex_shader.cpp
+++ b/src/video_core/vertex_shader.cpp
@@ -72,7 +72,7 @@ struct VertexShaderState {
72 u32* program_counter; 72 u32* program_counter;
73 73
74 const float24* input_register_table[16]; 74 const float24* input_register_table[16];
75 float24* output_register_table[7*4]; 75 Math::Vec4<float24> output_registers[16];
76 76
77 Math::Vec4<float24> temporary_registers[16]; 77 Math::Vec4<float24> temporary_registers[16];
78 bool conditional_code[2]; 78 bool conditional_code[2];
@@ -198,8 +198,7 @@ static void ProcessShaderCode(VertexShaderState& state) {
198 src2[3] = src2[3] * float24::FromFloat32(-1); 198 src2[3] = src2[3] * float24::FromFloat32(-1);
199 } 199 }
200 200
201 float24* dest = (instr.common.dest.Value() < 0x08) ? state.output_register_table[4*instr.common.dest.Value().GetIndex()] 201 float24* dest = (instr.common.dest.Value() < 0x10) ? &state.output_registers[instr.common.dest.Value().GetIndex()][0]
202 : (instr.common.dest.Value() < 0x10) ? dummy_vec4_float24
203 : (instr.common.dest.Value() < 0x20) ? &state.temporary_registers[instr.common.dest.Value().GetIndex()][0] 202 : (instr.common.dest.Value() < 0x20) ? &state.temporary_registers[instr.common.dest.Value().GetIndex()][0]
204 : dummy_vec4_float24; 203 : dummy_vec4_float24;
205 204
@@ -409,8 +408,7 @@ static void ProcessShaderCode(VertexShaderState& state) {
409 src3[3] = src3[3] * float24::FromFloat32(-1); 408 src3[3] = src3[3] * float24::FromFloat32(-1);
410 } 409 }
411 410
412 float24* dest = (instr.mad.dest.Value() < 0x08) ? state.output_register_table[4*instr.mad.dest.Value().GetIndex()] 411 float24* dest = (instr.mad.dest.Value() < 0x10) ? &state.output_registers[instr.mad.dest.Value().GetIndex()][0]
413 : (instr.mad.dest.Value() < 0x10) ? dummy_vec4_float24
414 : (instr.mad.dest.Value() < 0x20) ? &state.temporary_registers[instr.mad.dest.Value().GetIndex()][0] 412 : (instr.mad.dest.Value() < 0x20) ? &state.temporary_registers[instr.mad.dest.Value().GetIndex()][0]
415 : dummy_vec4_float24; 413 : dummy_vec4_float24;
416 414
@@ -587,12 +585,18 @@ OutputVertex RunShader(const InputVertex& input, int num_attributes) {
587 if(num_attributes > 14) state.input_register_table[attribute_register_map.attribute14_register] = &input.attr[14].x; 585 if(num_attributes > 14) state.input_register_table[attribute_register_map.attribute14_register] = &input.attr[14].x;
588 if(num_attributes > 15) state.input_register_table[attribute_register_map.attribute15_register] = &input.attr[15].x; 586 if(num_attributes > 15) state.input_register_table[attribute_register_map.attribute15_register] = &input.attr[15].x;
589 587
590 // Setup output register table 588 state.conditional_code[0] = false;
591 OutputVertex ret; 589 state.conditional_code[1] = false;
592 // Zero output so that attributes which aren't output won't have denormals in them, which will 590
593 // slow us down later. 591 ProcessShaderCode(state);
594 memset(&ret, 0, sizeof(ret)); 592 DebugUtils::DumpShader(shader_memory.data(), state.debug.max_offset, swizzle_data.data(),
593 state.debug.max_opdesc_id, registers.vs_main_offset,
594 registers.vs_output_attributes);
595 595
596 // Setup output data
597 OutputVertex ret;
598 // TODO(neobrain): Under some circumstances, up to 16 attributes may be output. We need to
599 // figure out what those circumstances are and enable the remaining outputs then.
596 for (int i = 0; i < 7; ++i) { 600 for (int i = 0; i < 7; ++i) {
597 const auto& output_register_map = registers.vs_output_attributes[i]; 601 const auto& output_register_map = registers.vs_output_attributes[i];
598 602
@@ -601,18 +605,18 @@ OutputVertex RunShader(const InputVertex& input, int num_attributes) {
601 output_register_map.map_z, output_register_map.map_w 605 output_register_map.map_z, output_register_map.map_w
602 }; 606 };
603 607
604 for (int comp = 0; comp < 4; ++comp) 608 for (int comp = 0; comp < 4; ++comp) {
605 state.output_register_table[4*i+comp] = ((float24*)&ret) + semantics[comp]; 609 float24* out = ((float24*)&ret) + semantics[comp];
610 if (semantics[comp] != Regs::VSOutputAttributes::INVALID) {
611 *out = state.output_registers[i][comp];
612 } else {
613 // Zero output so that attributes which aren't output won't have denormals in them,
614 // which would slow us down later.
615 memset(out, 0, sizeof(*out));
616 }
617 }
606 } 618 }
607 619
608 state.conditional_code[0] = false;
609 state.conditional_code[1] = false;
610
611 ProcessShaderCode(state);
612 DebugUtils::DumpShader(shader_memory.data(), state.debug.max_offset, swizzle_data.data(),
613 state.debug.max_opdesc_id, registers.vs_main_offset,
614 registers.vs_output_attributes);
615
616 LOG_TRACE(Render_Software, "Output vertex: pos (%.2f, %.2f, %.2f, %.2f), col(%.2f, %.2f, %.2f, %.2f), tc0(%.2f, %.2f)", 620 LOG_TRACE(Render_Software, "Output vertex: pos (%.2f, %.2f, %.2f, %.2f), col(%.2f, %.2f, %.2f, %.2f), tc0(%.2f, %.2f)",
617 ret.pos.x.ToFloat32(), ret.pos.y.ToFloat32(), ret.pos.z.ToFloat32(), ret.pos.w.ToFloat32(), 621 ret.pos.x.ToFloat32(), ret.pos.y.ToFloat32(), ret.pos.z.ToFloat32(), ret.pos.w.ToFloat32(),
618 ret.color.x.ToFloat32(), ret.color.y.ToFloat32(), ret.color.z.ToFloat32(), ret.color.w.ToFloat32(), 622 ret.color.x.ToFloat32(), ret.color.y.ToFloat32(), ret.color.z.ToFloat32(), ret.color.w.ToFloat32(),
diff --git a/upload_to_mega.js b/upload_to_mega.js
deleted file mode 100644
index c0abd5ed5..000000000
--- a/upload_to_mega.js
+++ /dev/null
@@ -1,28 +0,0 @@
1var util = require('util');
2var exec = require('child_process').exec;
3var sanitize = require("sanitize-filename");
4
5var email = process.env.MEGA_EMAIL;
6var password = process.env.MEGA_PASSWORD;
7var sourceFileName = 'build.7z';
8var dstFileName = process.env.APPVEYOR_REPO_COMMIT.substring(0, 8) + " - " +
9 process.env.APPVEYOR_REPO_COMMIT_MESSAGE.substring(0, 100) + ".7z";
10dstFileName = sanitize(dstFileName);
11
12var cmd = util.format('megaput ../%s --path \"/Root/Citra/Windows/%s\" --username=%s --password=%s --no-progress',
13 sourceFileName,
14 dstFileName,
15 email,
16 password);
17
18// only upload build on master branch, and not on other branches or PRs
19if (process.env.APPVEYOR_REPO_BRANCH == "master") {
20 console.log("Uploading file " + dstFileName + " to Mega...");
21 exec(cmd, function(error, stdout, stderr) {
22 console.log('stdout: ' + stdout);
23 console.log('stderr: ' + stderr);
24 if (error !== null) {
25 console.log('exec error: ' + error);
26 }
27 });
28}