mirror of
https://github.com/wheremyfoodat/Panda3DS.git
synced 2025-04-09 07:35:41 +12:00
Merge pull request #1 from wheremyfoodat/master
Not Ignoring this PR I fucked up something on my Github GUI
This commit is contained in:
commit
0f66527cbe
14 changed files with 147 additions and 72 deletions
2
.github/workflows/Linux_Build.yml
vendored
2
.github/workflows/Linux_Build.yml
vendored
|
@ -26,7 +26,7 @@ jobs:
|
||||||
- name: Configure CMake
|
- name: Configure CMake
|
||||||
# Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make.
|
# Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make.
|
||||||
# See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type
|
# See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type
|
||||||
run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++
|
run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DENABLE_USER_BUILD=ON
|
||||||
|
|
||||||
- name: Build
|
- name: Build
|
||||||
# Build your program with the given configuration
|
# Build your program with the given configuration
|
||||||
|
|
5
.github/workflows/MacOS_Build.yml
vendored
5
.github/workflows/MacOS_Build.yml
vendored
|
@ -23,13 +23,10 @@ jobs:
|
||||||
- name: Fetch submodules
|
- name: Fetch submodules
|
||||||
run: git submodule update --init --recursive
|
run: git submodule update --init --recursive
|
||||||
|
|
||||||
- name: Install LLVM # MacOS comes with "AppleClang" instead of regular Clang, and it can't build the project because no proper C++20
|
|
||||||
run: brew install llvm
|
|
||||||
|
|
||||||
- name: Configure CMake
|
- name: Configure CMake
|
||||||
# Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make.
|
# Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make.
|
||||||
# See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type
|
# See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type
|
||||||
run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DCMAKE_C_COMPILER=/usr/local/opt/llvm/bin/clang -DCMAKE_CXX_COMPILER=/usr/local/opt/llvm/bin/clang++
|
run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DENABLE_USER_BUILD=ON
|
||||||
|
|
||||||
- name: Build
|
- name: Build
|
||||||
# Build your program with the given configuration
|
# Build your program with the given configuration
|
||||||
|
|
2
.github/workflows/Windows_Build.yml
vendored
2
.github/workflows/Windows_Build.yml
vendored
|
@ -26,7 +26,7 @@ jobs:
|
||||||
- name: Configure CMake
|
- name: Configure CMake
|
||||||
# Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make.
|
# Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make.
|
||||||
# See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type
|
# See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type
|
||||||
run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}}
|
run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DENABLE_USER_BUILD=ON
|
||||||
|
|
||||||
- name: Build
|
- name: Build
|
||||||
# Build your program with the given configuration
|
# Build your program with the given configuration
|
||||||
|
|
|
@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.10)
|
||||||
set(CMAKE_CXX_STANDARD 20)
|
set(CMAKE_CXX_STANDARD 20)
|
||||||
set(CMAKE_CXX_STANDARD_REQUIRED True)
|
set(CMAKE_CXX_STANDARD_REQUIRED True)
|
||||||
|
|
||||||
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 12)
|
if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 12)
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fbracket-depth=4096")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fbracket-depth=4096")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
@ -13,8 +13,14 @@ endif()
|
||||||
project(Alber)
|
project(Alber)
|
||||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
|
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
|
||||||
|
|
||||||
|
if(NOT CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-format-nonliteral -Wno-format-security")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
option(DISABLE_PANIC_DEV "Make a build with fewer and less intrusive asserts" OFF)
|
||||||
option(GPU_DEBUG_INFO "Enable additional GPU debugging info" OFF)
|
option(GPU_DEBUG_INFO "Enable additional GPU debugging info" OFF)
|
||||||
option(ENABLE_LTO "Enable link-time optimization" OFF)
|
option(ENABLE_LTO "Enable link-time optimization" OFF)
|
||||||
|
option(ENABLE_USER_BUILD "Make a user-facing build. These builds have various assertions disabled, LTO, and more" OFF)
|
||||||
|
|
||||||
include_directories(${PROJECT_SOURCE_DIR}/include/)
|
include_directories(${PROJECT_SOURCE_DIR}/include/)
|
||||||
include_directories(${PROJECT_SOURCE_DIR}/include/kernel)
|
include_directories(${PROJECT_SOURCE_DIR}/include/kernel)
|
||||||
|
@ -159,7 +165,7 @@ source_group("Source Files\\Third Party" FILES ${THIRD_PARTY_SOURCE_FILES})
|
||||||
add_executable(Alber ${SOURCE_FILES} ${FS_SOURCE_FILES} ${CRYPTO_SOURCE_FILES} ${KERNEL_SOURCE_FILES} ${LOADER_SOURCE_FILES} ${SERVICE_SOURCE_FILES}
|
add_executable(Alber ${SOURCE_FILES} ${FS_SOURCE_FILES} ${CRYPTO_SOURCE_FILES} ${KERNEL_SOURCE_FILES} ${LOADER_SOURCE_FILES} ${SERVICE_SOURCE_FILES}
|
||||||
${PICA_SOURCE_FILES} ${RENDERER_GL_SOURCE_FILES} ${THIRD_PARTY_SOURCE_FILES} ${HEADER_FILES})
|
${PICA_SOURCE_FILES} ${RENDERER_GL_SOURCE_FILES} ${THIRD_PARTY_SOURCE_FILES} ${HEADER_FILES})
|
||||||
|
|
||||||
if(ENABLE_LTO)
|
if(ENABLE_LTO OR ENABLE_USER_BUILD)
|
||||||
set_target_properties(Alber PROPERTIES INTERPROCEDURAL_OPTIMIZATION TRUE)
|
set_target_properties(Alber PROPERTIES INTERPROCEDURAL_OPTIMIZATION TRUE)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
@ -167,4 +173,12 @@ target_link_libraries(Alber PRIVATE dynarmic SDL2-static glad cryptopp)
|
||||||
|
|
||||||
if(GPU_DEBUG_INFO)
|
if(GPU_DEBUG_INFO)
|
||||||
target_compile_definitions(Alber PRIVATE GPU_DEBUG_INFO=1)
|
target_compile_definitions(Alber PRIVATE GPU_DEBUG_INFO=1)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(ENABLE_USER_BUILD)
|
||||||
|
target_compile_definitions(Alber PRIVATE PANDA3DS_USER_BUILD=1)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(ENABLE_USER_BUILD OR DISABLE_PANIC_DEV)
|
||||||
|
target_compile_definitions(Alber PRIVATE PANDA3DS_LIMITED_PANICS=1)
|
||||||
|
endif()
|
||||||
|
|
|
@ -30,24 +30,31 @@ using s32 = std::int32_t;
|
||||||
using s64 = std::int64_t;
|
using s64 = std::int64_t;
|
||||||
|
|
||||||
namespace Helpers {
|
namespace Helpers {
|
||||||
[[noreturn]] static void panic(const char* fmt, ...) {
|
// Unconditional panic, unlike panicDev which does not panic on user builds
|
||||||
std::va_list args;
|
template <class... Args>
|
||||||
va_start(args, fmt);
|
[[noreturn]] static void panic(const char* fmt, Args&&... args) {
|
||||||
std::cout << termcolor::on_red << "[FATAL] ";
|
std::cout << termcolor::on_red << "[FATAL] ";
|
||||||
std::vprintf(fmt, args);
|
std::printf(fmt, args...);
|
||||||
std::cout << termcolor::reset << "\n";
|
std::cout << termcolor::reset << "\n";
|
||||||
va_end(args);
|
|
||||||
|
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef PANDA3DS_LIMITED_PANICS
|
||||||
|
template <class... Args>
|
||||||
|
static void panicDev(const char* fmt, Args&&... args) {}
|
||||||
|
#else
|
||||||
|
template <class... Args>
|
||||||
|
[[noreturn]] static void panicDev(const char* fmt, Args&&... args) {
|
||||||
|
panic(fmt, args...);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static void warn(const char* fmt, ...) {
|
template <class... Args>
|
||||||
std::va_list args;
|
static void warn(const char* fmt, Args&&... args) {
|
||||||
va_start(args, fmt);
|
|
||||||
std::cout << termcolor::on_red << "[Warning] ";
|
std::cout << termcolor::on_red << "[Warning] ";
|
||||||
std::vprintf(fmt, args);
|
std::printf(fmt, args...);
|
||||||
std::cout << termcolor::reset << "\n";
|
std::cout << termcolor::reset << "\n";
|
||||||
va_end(args);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static constexpr bool buildingInDebugMode() {
|
static constexpr bool buildingInDebugMode() {
|
||||||
|
@ -57,6 +64,13 @@ namespace Helpers {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static constexpr bool isUserBuild() {
|
||||||
|
#ifdef PANDA3DS_USER_BUILD
|
||||||
|
return true;
|
||||||
|
#endif
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
static void debug_printf(const char* fmt, ...) {
|
static void debug_printf(const char* fmt, ...) {
|
||||||
if constexpr (buildingInDebugMode()) {
|
if constexpr (buildingInDebugMode()) {
|
||||||
std::va_list args;
|
std::va_list args;
|
||||||
|
|
|
@ -63,6 +63,8 @@ class HIDService {
|
||||||
MAKE_LOG_FUNCTION(log, hidLogger)
|
MAKE_LOG_FUNCTION(log, hidLogger)
|
||||||
|
|
||||||
// Service commands
|
// Service commands
|
||||||
|
void disableAccelerometer(u32 messagePointer);
|
||||||
|
void disableGyroscopeLow(u32 messagePointer);
|
||||||
void enableAccelerometer(u32 messagePointer);
|
void enableAccelerometer(u32 messagePointer);
|
||||||
void enableGyroscopeLow(u32 messagePointer);
|
void enableGyroscopeLow(u32 messagePointer);
|
||||||
void getGyroscopeLowCalibrateParam(u32 messagePointer);
|
void getGyroscopeLowCalibrateParam(u32 messagePointer);
|
||||||
|
|
|
@ -33,7 +33,7 @@ void Kernel::readDirectory(u32 messagePointer, Handle directory) {
|
||||||
const u32 entryCount = mem.read32(messagePointer + 4);
|
const u32 entryCount = mem.read32(messagePointer + 4);
|
||||||
const u32 outPointer = mem.read32(messagePointer + 12);
|
const u32 outPointer = mem.read32(messagePointer + 12);
|
||||||
logFileIO("Directory::Read (handle = %X, entry count = %d, out pointer = %08X)\n", directory, entryCount, outPointer);
|
logFileIO("Directory::Read (handle = %X, entry count = %d, out pointer = %08X)\n", directory, entryCount, outPointer);
|
||||||
Helpers::panic("Unimplemented FsDir::Read");
|
Helpers::panicDev("Unimplemented FsDir::Read");
|
||||||
|
|
||||||
mem.write32(messagePointer + 4, Result::Success);
|
mem.write32(messagePointer + 4, Result::Success);
|
||||||
mem.write32(messagePointer + 8, 0);
|
mem.write32(messagePointer + 8, 0);
|
||||||
|
|
|
@ -59,12 +59,12 @@ void Kernel::setupIdleThread() {
|
||||||
t.fpscr = FPSCR::ThreadDefault;
|
t.fpscr = FPSCR::ThreadDefault;
|
||||||
|
|
||||||
// Our idle thread should have as low of a priority as possible, because, well, it's an idle thread.
|
// Our idle thread should have as low of a priority as possible, because, well, it's an idle thread.
|
||||||
// We handle this by giving it a priority of 0xff, which is lower than is actually allowed for user threads
|
// We handle this by giving it a priority of 0x40, which is lower than is actually allowed for user threads
|
||||||
// (High priority value = low priority)
|
// (High priority value = low priority). This is the same priority used in the retail kernel.
|
||||||
t.priority = 0xff;
|
t.priority = 0x40;
|
||||||
t.status = ThreadStatus::Ready;
|
t.status = ThreadStatus::Ready;
|
||||||
|
|
||||||
// Add idle thread to the list of thread indices
|
// Add idle thread to the list of thread indices
|
||||||
threadIndices.push_back(idleThreadIndex);
|
threadIndices.push_back(idleThreadIndex);
|
||||||
sortThreads();
|
sortThreads();
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,24 +44,21 @@ bool NCCH::loadFromHeader(Crypto::AESEngine &aesEngine, IOFile& file, const FSIn
|
||||||
exheaderInfo.offset = info.offset + 0x200;
|
exheaderInfo.offset = info.offset + 0x200;
|
||||||
exheaderInfo.size = exheaderSize;
|
exheaderInfo.size = exheaderSize;
|
||||||
exheaderInfo.hashRegionSize = 0;
|
exheaderInfo.hashRegionSize = 0;
|
||||||
|
exheaderInfo.encryptionInfo = std::nullopt;
|
||||||
|
|
||||||
exeFS.offset = info.offset + u64(*(u32*)&header[0x1A0]) * mediaUnit;
|
exeFS.offset = info.offset + u64(*(u32*)&header[0x1A0]) * mediaUnit;
|
||||||
exeFS.size = u64(*(u32*)&header[0x1A4]) * mediaUnit;
|
exeFS.size = u64(*(u32*)&header[0x1A4]) * mediaUnit;
|
||||||
exeFS.hashRegionSize = u64(*(u32*)&header[0x1A8]) * mediaUnit;
|
exeFS.hashRegionSize = u64(*(u32*)&header[0x1A8]) * mediaUnit;
|
||||||
|
exeFS.encryptionInfo = std::nullopt;
|
||||||
|
|
||||||
romFS.offset = info.offset + u64(*(u32*)&header[0x1B0]) * mediaUnit;
|
romFS.offset = info.offset + u64(*(u32*)&header[0x1B0]) * mediaUnit;
|
||||||
romFS.size = u64(*(u32*)&header[0x1B4]) * mediaUnit;
|
romFS.size = u64(*(u32*)&header[0x1B4]) * mediaUnit;
|
||||||
romFS.hashRegionSize = u64(*(u32*)&header[0x1B8]) * mediaUnit;
|
romFS.hashRegionSize = u64(*(u32*)&header[0x1B8]) * mediaUnit;
|
||||||
|
romFS.encryptionInfo = std::nullopt;
|
||||||
|
|
||||||
|
// Shows whether we got the primary and secondary keys correctly
|
||||||
|
bool gotCryptoKeys = true;
|
||||||
if (encrypted) {
|
if (encrypted) {
|
||||||
if (!aesEngine.haveKeys()) {
|
|
||||||
Helpers::panic(
|
|
||||||
"Loaded an encrypted ROM but AES keys don't seem to have been provided correctly! Navigate to the emulator's\n"
|
|
||||||
"app data folder and make sure you have a sysdata directory with a file called aes_keys.txt which contains your keys!"
|
|
||||||
);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
Crypto::AESKey primaryKeyY;
|
Crypto::AESKey primaryKeyY;
|
||||||
Crypto::AESKey secondaryKeyY;
|
Crypto::AESKey secondaryKeyY;
|
||||||
std::memcpy(primaryKeyY.data(), header, primaryKeyY.size());
|
std::memcpy(primaryKeyY.data(), header, primaryKeyY.size());
|
||||||
|
@ -69,44 +66,36 @@ bool NCCH::loadFromHeader(Crypto::AESEngine &aesEngine, IOFile& file, const FSIn
|
||||||
if (!seedCrypto) {
|
if (!seedCrypto) {
|
||||||
secondaryKeyY = primaryKeyY;
|
secondaryKeyY = primaryKeyY;
|
||||||
} else {
|
} else {
|
||||||
Helpers::panic("Seed crypto is not supported");
|
Helpers::warn("Seed crypto is not supported");
|
||||||
return false;
|
gotCryptoKeys = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto primaryResult = getPrimaryKey(aesEngine, primaryKeyY);
|
auto primaryResult = getPrimaryKey(aesEngine, primaryKeyY);
|
||||||
|
|
||||||
if (!primaryResult.first) {
|
|
||||||
Helpers::panic("getPrimaryKey failed!");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
Crypto::AESKey primaryKey = primaryResult.second;
|
|
||||||
|
|
||||||
auto secondaryResult = getSecondaryKey(aesEngine, secondaryKeyY);
|
auto secondaryResult = getSecondaryKey(aesEngine, secondaryKeyY);
|
||||||
|
|
||||||
if (!secondaryResult.first) {
|
if (!primaryResult.first || !secondaryResult.first) {
|
||||||
Helpers::panic("getSecondaryKey failed!");
|
gotCryptoKeys = false;
|
||||||
return false;
|
} else {
|
||||||
|
Crypto::AESKey primaryKey = primaryResult.second;
|
||||||
|
Crypto::AESKey secondaryKey = secondaryResult.second;
|
||||||
|
|
||||||
|
EncryptionInfo encryptionInfoTmp;
|
||||||
|
encryptionInfoTmp.normalKey = primaryKey;
|
||||||
|
encryptionInfoTmp.initialCounter.fill(0);
|
||||||
|
|
||||||
|
for (std::size_t i = 1; i <= sizeof(std::uint64_t) - 1; i++) {
|
||||||
|
encryptionInfoTmp.initialCounter[i] = header[0x108 + sizeof(std::uint64_t) - 1 - i];
|
||||||
|
}
|
||||||
|
encryptionInfoTmp.initialCounter[8] = 1;
|
||||||
|
exheaderInfo.encryptionInfo = encryptionInfoTmp;
|
||||||
|
|
||||||
|
encryptionInfoTmp.initialCounter[8] = 2;
|
||||||
|
exeFS.encryptionInfo = encryptionInfoTmp;
|
||||||
|
|
||||||
|
encryptionInfoTmp.normalKey = secondaryKey;
|
||||||
|
encryptionInfoTmp.initialCounter[8] = 3;
|
||||||
|
romFS.encryptionInfo = encryptionInfoTmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
Crypto::AESKey secondaryKey = secondaryResult.second;
|
|
||||||
|
|
||||||
EncryptionInfo encryptionInfoTmp;
|
|
||||||
encryptionInfoTmp.normalKey = primaryKey;
|
|
||||||
encryptionInfoTmp.initialCounter.fill(0);
|
|
||||||
|
|
||||||
for (std::size_t i = 1; i <= sizeof(std::uint64_t) - 1; i++) {
|
|
||||||
encryptionInfoTmp.initialCounter[i] = header[0x108 + sizeof(std::uint64_t) - 1 - i];
|
|
||||||
}
|
|
||||||
encryptionInfoTmp.initialCounter[8] = 1;
|
|
||||||
exheaderInfo.encryptionInfo = encryptionInfoTmp;
|
|
||||||
|
|
||||||
encryptionInfoTmp.initialCounter[8] = 2;
|
|
||||||
exeFS.encryptionInfo = encryptionInfoTmp;
|
|
||||||
|
|
||||||
encryptionInfoTmp.normalKey = secondaryKey;
|
|
||||||
encryptionInfoTmp.initialCounter[8] = 3;
|
|
||||||
romFS.encryptionInfo = encryptionInfoTmp;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (exheaderSize != 0) {
|
if (exheaderSize != 0) {
|
||||||
|
@ -125,9 +114,28 @@ bool NCCH::loadFromHeader(Crypto::AESEngine &aesEngine, IOFile& file, const FSIn
|
||||||
if (u32(programID) == u32(jumpID) && encrypted) {
|
if (u32(programID) == u32(jumpID) && encrypted) {
|
||||||
printf("NCSD is supposedly ecrypted but not actually encrypted\n");
|
printf("NCSD is supposedly ecrypted but not actually encrypted\n");
|
||||||
encrypted = false;
|
encrypted = false;
|
||||||
|
|
||||||
|
// Cartridge is not actually encrypted, set all of our encryption info structures to nullopt
|
||||||
|
exheaderInfo.encryptionInfo = std::nullopt;
|
||||||
|
romFS.encryptionInfo = std::nullopt;
|
||||||
|
exeFS.encryptionInfo = std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If it's truly encrypted, we need to read section again.
|
// If it's truly encrypted, we need to read section again.
|
||||||
if (encrypted) {
|
if (encrypted) {
|
||||||
|
if (!aesEngine.haveKeys()) {
|
||||||
|
Helpers::panic(
|
||||||
|
"Loaded an encrypted ROM but AES keys don't seem to have been provided correctly! Navigate to the emulator's\n"
|
||||||
|
"app data folder and make sure you have a sysdata directory with a file called aes_keys.txt which contains your keys!"
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!gotCryptoKeys) {
|
||||||
|
Helpers::panic("ROM is encrypted but it seems we couldn't get either the primary or the secondary key");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
auto [success, bytes] = readFromFile(file, exheaderInfo, &exheader[0], 0, exheaderSize);
|
auto [success, bytes] = readFromFile(file, exheaderInfo, &exheader[0], 0, exheaderSize);
|
||||||
if (!success || bytes != exheaderSize) {
|
if (!success || bytes != exheaderSize) {
|
||||||
printf("Failed to read Extended NCCH header\n");
|
printf("Failed to read Extended NCCH header\n");
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include "resource_limits.hpp"
|
#include "resource_limits.hpp"
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <chrono> // For time since epoch
|
#include <chrono> // For time since epoch
|
||||||
|
#include <ctime>
|
||||||
|
|
||||||
using namespace KernelMemoryTypes;
|
using namespace KernelMemoryTypes;
|
||||||
|
|
||||||
|
@ -424,9 +425,20 @@ void Memory::mirrorMapping(u32 destAddress, u32 sourceAddress, u32 size) {
|
||||||
u64 Memory::timeSince3DSEpoch() {
|
u64 Memory::timeSince3DSEpoch() {
|
||||||
using namespace std::chrono;
|
using namespace std::chrono;
|
||||||
|
|
||||||
// ms since Jan 1 1970
|
std::time_t rawTime = std::time(nullptr); // Get current UTC time
|
||||||
milliseconds ms = duration_cast<milliseconds>(system_clock::now().time_since_epoch());
|
auto localTime = std::localtime(&rawTime); // Convert to local time
|
||||||
// ms between Jan 1 1900 and Jan 1 1970 (2208988800 seconds elapsed between the two)
|
|
||||||
constexpr u64 offset = 2208988800ull * 1000;
|
bool daylightSavings = localTime->tm_isdst > 0; // Get if time includes DST
|
||||||
return ms.count() + offset;
|
localTime = std::gmtime(&rawTime);
|
||||||
|
|
||||||
|
// Use gmtime + mktime to calculate difference between local time and UTC
|
||||||
|
auto timezoneDifference = rawTime - std::mktime(localTime);
|
||||||
|
if (daylightSavings) {
|
||||||
|
timezoneDifference += 60ull * 60ull; // Add 1 hour (60 seconds * 60 minutes)
|
||||||
|
}
|
||||||
|
|
||||||
|
// seconds between Jan 1 1900 and Jan 1 1970
|
||||||
|
constexpr u64 offset = 2208988800ull;
|
||||||
|
milliseconds ms = duration_cast<milliseconds>(seconds(rawTime + timezoneDifference + offset));
|
||||||
|
return ms.count();
|
||||||
}
|
}
|
|
@ -931,7 +931,9 @@ void Renderer::bindDepthBuffer() {
|
||||||
tex = depthBufferCache.add(sampleBuffer).texture.m_handle;
|
tex = depthBufferCache.add(sampleBuffer).texture.m_handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (PICA::DepthFmt::Depth24Stencil8 != depthBufferFormat) Helpers::panic("TODO: Should we remove stencil attachment?");
|
if (PICA::DepthFmt::Depth24Stencil8 != depthBufferFormat) {
|
||||||
|
Helpers::panicDev("TODO: Should we remove stencil attachment?");
|
||||||
|
}
|
||||||
auto attachment = depthBufferFormat == PICA::DepthFmt::Depth24Stencil8 ? GL_DEPTH_STENCIL_ATTACHMENT : GL_DEPTH_ATTACHMENT;
|
auto attachment = depthBufferFormat == PICA::DepthFmt::Depth24Stencil8 ? GL_DEPTH_STENCIL_ATTACHMENT : GL_DEPTH_ATTACHMENT;
|
||||||
glFramebufferTexture2D(GL_FRAMEBUFFER, attachment, GL_TEXTURE_2D, tex, 0);
|
glFramebufferTexture2D(GL_FRAMEBUFFER, attachment, GL_TEXTURE_2D, tex, 0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -81,7 +81,10 @@ void APTService::handleSyncRequest(u32 messagePointer) {
|
||||||
case APTCommands::SetApplicationCpuTimeLimit: setApplicationCpuTimeLimit(messagePointer); break;
|
case APTCommands::SetApplicationCpuTimeLimit: setApplicationCpuTimeLimit(messagePointer); break;
|
||||||
case APTCommands::SetScreencapPostPermission: setScreencapPostPermission(messagePointer); break;
|
case APTCommands::SetScreencapPostPermission: setScreencapPostPermission(messagePointer); break;
|
||||||
case APTCommands::TheSmashBrosFunction: theSmashBrosFunction(messagePointer); break;
|
case APTCommands::TheSmashBrosFunction: theSmashBrosFunction(messagePointer); break;
|
||||||
default: Helpers::panic("APT service requested. Command: %08X\n", command);
|
default:
|
||||||
|
Helpers::panicDev("APT service requested. Command: %08X\n", command);
|
||||||
|
mem.write32(messagePointer + 4, Result::Success);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,10 @@ void CECDService::handleSyncRequest(u32 messagePointer) {
|
||||||
const u32 command = mem.read32(messagePointer);
|
const u32 command = mem.read32(messagePointer);
|
||||||
switch (command) {
|
switch (command) {
|
||||||
case CECDCommands::GetInfoEventHandle: getInfoEventHandle(messagePointer); break;
|
case CECDCommands::GetInfoEventHandle: getInfoEventHandle(messagePointer); break;
|
||||||
default: Helpers::panic("CECD service requested. Command: %08X\n", command);
|
default:
|
||||||
|
Helpers::panicDev("CECD service requested. Command: %08X\n", command);
|
||||||
|
mem.write32(messagePointer + 4, Result::Success);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,9 @@ namespace HIDCommands {
|
||||||
enum : u32 {
|
enum : u32 {
|
||||||
GetIPCHandles = 0x000A0000,
|
GetIPCHandles = 0x000A0000,
|
||||||
EnableAccelerometer = 0x00110000,
|
EnableAccelerometer = 0x00110000,
|
||||||
|
DisableAccelerometer = 0x00120000,
|
||||||
EnableGyroscopeLow = 0x00130000,
|
EnableGyroscopeLow = 0x00130000,
|
||||||
|
DisableGyroscopeLow = 0x00140000,
|
||||||
GetGyroscopeLowRawToDpsCoefficient = 0x00150000,
|
GetGyroscopeLowRawToDpsCoefficient = 0x00150000,
|
||||||
GetGyroscopeLowCalibrateParam = 0x00160000
|
GetGyroscopeLowCalibrateParam = 0x00160000
|
||||||
};
|
};
|
||||||
|
@ -36,6 +38,8 @@ void HIDService::reset() {
|
||||||
void HIDService::handleSyncRequest(u32 messagePointer) {
|
void HIDService::handleSyncRequest(u32 messagePointer) {
|
||||||
const u32 command = mem.read32(messagePointer);
|
const u32 command = mem.read32(messagePointer);
|
||||||
switch (command) {
|
switch (command) {
|
||||||
|
case HIDCommands::DisableAccelerometer: disableAccelerometer(messagePointer); break;
|
||||||
|
case HIDCommands::DisableGyroscopeLow: disableGyroscopeLow(messagePointer); break;
|
||||||
case HIDCommands::EnableAccelerometer: enableAccelerometer(messagePointer); break;
|
case HIDCommands::EnableAccelerometer: enableAccelerometer(messagePointer); break;
|
||||||
case HIDCommands::EnableGyroscopeLow: enableGyroscopeLow(messagePointer); break;
|
case HIDCommands::EnableGyroscopeLow: enableGyroscopeLow(messagePointer); break;
|
||||||
case HIDCommands::GetGyroscopeLowCalibrateParam: getGyroscopeLowCalibrateParam(messagePointer); break;
|
case HIDCommands::GetGyroscopeLowCalibrateParam: getGyroscopeLowCalibrateParam(messagePointer); break;
|
||||||
|
@ -53,6 +57,14 @@ void HIDService::enableAccelerometer(u32 messagePointer) {
|
||||||
mem.write32(messagePointer + 4, Result::Success);
|
mem.write32(messagePointer + 4, Result::Success);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void HIDService::disableAccelerometer(u32 messagePointer) {
|
||||||
|
log("HID::DisableAccelerometer\n");
|
||||||
|
accelerometerEnabled = false;
|
||||||
|
|
||||||
|
mem.write32(messagePointer, IPC::responseHeader(0x12, 1, 0));
|
||||||
|
mem.write32(messagePointer + 4, Result::Success);
|
||||||
|
}
|
||||||
|
|
||||||
void HIDService::enableGyroscopeLow(u32 messagePointer) {
|
void HIDService::enableGyroscopeLow(u32 messagePointer) {
|
||||||
log("HID::EnableGyroscopeLow\n");
|
log("HID::EnableGyroscopeLow\n");
|
||||||
gyroEnabled = true;
|
gyroEnabled = true;
|
||||||
|
@ -61,6 +73,14 @@ void HIDService::enableGyroscopeLow(u32 messagePointer) {
|
||||||
mem.write32(messagePointer + 4, Result::Success);
|
mem.write32(messagePointer + 4, Result::Success);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void HIDService::disableGyroscopeLow(u32 messagePointer) {
|
||||||
|
log("HID::DisableGyroscopeLow\n");
|
||||||
|
gyroEnabled = false;
|
||||||
|
|
||||||
|
mem.write32(messagePointer, IPC::responseHeader(0x14, 1, 0));
|
||||||
|
mem.write32(messagePointer + 4, Result::Success);
|
||||||
|
}
|
||||||
|
|
||||||
void HIDService::getGyroscopeLowCalibrateParam(u32 messagePointer) {
|
void HIDService::getGyroscopeLowCalibrateParam(u32 messagePointer) {
|
||||||
log("HID::GetGyroscopeLowCalibrateParam\n");
|
log("HID::GetGyroscopeLowCalibrateParam\n");
|
||||||
constexpr s16 unit = 6700; // Approximately from Citra which took it from hardware
|
constexpr s16 unit = 6700; // Approximately from Citra which took it from hardware
|
||||||
|
|
Loading…
Add table
Reference in a new issue