diff options
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 | |||
| 4 | set -x | 4 | set -x |
| 5 | 5 | ||
| 6 | #if OS is linux or is not set | 6 | #if OS is linux or is not set |
| 7 | if [ "$TRAVIS_OS_NAME" = linux -o -z "$TRAVIS_OS_NAME" ]; then | 7 | if [ "$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 |
| 11 | elif [ "$TRAVIS_OS_NAME" = osx ]; then | 11 | elif [ "$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 |
| 16 | fi | 16 | fi |
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 | |||
| 4 | set -x | 4 | set -x |
| 5 | 5 | ||
| 6 | #if OS is linux or is not set | 6 | #if OS is linux or is not set |
| 7 | if [ "$TRAVIS_OS_NAME" = linux -o -z "$TRAVIS_OS_NAME" ]; then | 7 | if [ "$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 |
| 26 | elif [ "$TRAVIS_OS_NAME" = osx ]; then | 26 | elif [ "$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 |
| 29 | fi | 29 | fi |
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 @@ | |||
| 1 | if [ "$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'" | ||
| 29 | fi | ||
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 | ||
| 5 | language: cpp | 5 | language: cpp |
| 6 | 6 | ||
| 7 | env: | ||
| 8 | global: | ||
| 9 | - secure: "AXHFIafTmbGDsHD3mUVj5a4I397DQjti/WoqAJGUp2PglxTcc04BwxZ9Z+xLuf5N2Hs5r9ojAJLT8OGxJCLBDXzneQTNSqXbFuYSLbqrEAiIRlA9eRIotWCg+wYcO+5e8MKX+cHVKwiIWasUB21AtCdq6msh6Y3pUshZp212VPg=" | ||
| 10 | |||
| 7 | before_install: | 11 | before_install: |
| 8 | - sh .travis-deps.sh | 12 | - sh .travis-deps.sh |
| 9 | 13 | ||
| 10 | script: | 14 | script: |
| 11 | - sh .travis-build.sh | 15 | - sh .travis-build.sh |
| 16 | |||
| 17 | after_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 | ||
| 7 | environment: | 7 | environment: |
| 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 | ||
| 14 | platform: | 12 | platform: |
| 15 | - x64 | 13 | - x64 |
| @@ -27,11 +25,6 @@ before_build: | |||
| 27 | - cd .. | 25 | - cd .. |
| 28 | 26 | ||
| 29 | after_build: | 27 | after_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 | ||
| 71 | u64 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 | |||
| 76 | void ARM_DynCom::AddTicks(u64 ticks) { | 71 | void 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 | ||
| 1078 | typedef struct setend_inst { | ||
| 1079 | unsigned int set_bigend; | ||
| 1080 | } setend_inst; | ||
| 1081 | |||
| 1078 | typedef struct _b_2_thumb { | 1082 | typedef 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 | ||
| 2286 | static ARM_INST_PTR INTERPRETER_TRANSLATE(setend)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("SETEND"); } | 2290 | static 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 | ||
| 2288 | static ARM_INST_PTR INTERPRETER_TRANSLATE(shadd8)(unsigned int inst, int index) | 2305 | static 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) | ||
| 206 | bool 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); | |||
| 356 | extern u8 ARMul_UnsignedAbsoluteDifference(u8, u8); | 355 | extern u8 ARMul_UnsignedAbsoluteDifference(u8, u8); |
| 357 | extern u32 ARMul_SignedSatQ(s32, u8, bool*); | 356 | extern u32 ARMul_SignedSatQ(s32, u8, bool*); |
| 358 | extern u32 ARMul_UnsignedSatQ(s32, u8, bool*); | 357 | extern u32 ARMul_UnsignedSatQ(s32, u8, bool*); |
| 358 | |||
| 359 | extern 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 |
| 24 | enum | 27 | enum |
| 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. | ||
| 53 | inline 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 | |||
| 62 | inline 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 | |||
| 71 | inline 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. | ||
| 82 | inline 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 | |||
| 89 | inline 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 | |||
| 96 | inline 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 | ||
| 127 | void 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 | |||
| 137 | void 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 | |||
| 147 | void 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 | |||
| 126 | void HIDInit() { | 158 | void 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 | */ |
| 172 | void GetIPCHandles(Interface* self); | 172 | void 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 | */ | ||
| 181 | void 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 | */ | ||
| 190 | void 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 | */ | ||
| 200 | void GetSoundVolume(Interface* self); | ||
| 201 | |||
| 174 | /// Checks for user input updates | 202 | /// Checks for user input updates |
| 175 | void HIDUpdate(); | 203 | void 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 | ||
| 25 | HID_SPVR_Interface::HID_SPVR_Interface() { | 25 | HID_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 { | |||
| 10 | namespace HID { | 10 | namespace HID { |
| 11 | 11 | ||
| 12 | const Interface::FunctionInfo FunctionTable[] = { | 12 | const 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 | ||
| 23 | HID_U_Interface::HID_U_Interface() { | 23 | HID_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 |
| 553 | static s64 GetSystemTick() { | 554 | static 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 | ||
| 90 | struct ExHeader_SystemInfo{ | 91 | struct 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 | ||
| 105 | struct ExHeader_ARM11_SystemLocalCaps{ | 105 | struct 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); | |||
| 147 | u8 Read8(VAddr addr); | 147 | u8 Read8(VAddr addr); |
| 148 | u16 Read16(VAddr addr); | 148 | u16 Read16(VAddr addr); |
| 149 | u32 Read32(VAddr addr); | 149 | u32 Read32(VAddr addr); |
| 150 | u64 Read64(VAddr addr); | ||
| 150 | 151 | ||
| 151 | u32 Read8_ZX(VAddr addr); | 152 | u32 Read8_ZX(VAddr addr); |
| 152 | u32 Read16_ZX(VAddr addr); | 153 | u32 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 | ||
| 248 | u64 Read64(const VAddr addr) { | ||
| 249 | u64_le data = 0; | ||
| 250 | Read<u64_le>(data, addr); | ||
| 251 | return (u64)data; | ||
| 252 | } | ||
| 253 | |||
| 248 | u32 Read8_ZX(const VAddr addr) { | 254 | u32 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 | */ |
| 126 | inline const Math::Vec2<u32> DecodeD24S8(const u8* bytes) { | 126 | inline 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 @@ | |||
| 1 | var util = require('util'); | ||
| 2 | var exec = require('child_process').exec; | ||
| 3 | var sanitize = require("sanitize-filename"); | ||
| 4 | |||
| 5 | var email = process.env.MEGA_EMAIL; | ||
| 6 | var password = process.env.MEGA_PASSWORD; | ||
| 7 | var sourceFileName = 'build.7z'; | ||
| 8 | var dstFileName = process.env.APPVEYOR_REPO_COMMIT.substring(0, 8) + " - " + | ||
| 9 | process.env.APPVEYOR_REPO_COMMIT_MESSAGE.substring(0, 100) + ".7z"; | ||
| 10 | dstFileName = sanitize(dstFileName); | ||
| 11 | |||
| 12 | var 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 | ||
| 19 | if (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 | } | ||