mirror of
https://github.com/wheremyfoodat/Panda3DS.git
synced 2025-04-07 14:45:41 +12:00
Merge branch 'master' into shader-decomp
This commit is contained in:
commit
1366e7a76e
19 changed files with 305 additions and 18 deletions
2
.github/workflows/MacOS_Build.yml
vendored
2
.github/workflows/MacOS_Build.yml
vendored
|
@ -40,7 +40,7 @@ jobs:
|
|||
run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}}
|
||||
|
||||
- name: Install bundle dependencies
|
||||
run: brew install dylibbundler imagemagick
|
||||
run: brew install --overwrite python@3.12 && brew install dylibbundler imagemagick
|
||||
|
||||
- name: Run bundle script
|
||||
run: ./.github/mac-bundle.sh
|
||||
|
|
2
.github/workflows/Qt_Build.yml
vendored
2
.github/workflows/Qt_Build.yml
vendored
|
@ -67,7 +67,7 @@ jobs:
|
|||
|
||||
- name: Install bundle dependencies
|
||||
run: |
|
||||
brew install dylibbundler imagemagick
|
||||
brew install --overwrite python@3.12 && brew install dylibbundler imagemagick
|
||||
|
||||
- name: Install qt
|
||||
run: brew install qt && which macdeployqt
|
||||
|
|
130
.gitlab-ci.yml
Normal file
130
.gitlab-ci.yml
Normal file
|
@ -0,0 +1,130 @@
|
|||
# DESCRIPTION: GitLab CI/CD for libRetro (NOT FOR GitLab-proper)
|
||||
|
||||
##############################################################################
|
||||
################################# BOILERPLATE ################################
|
||||
##############################################################################
|
||||
|
||||
# Core definitions
|
||||
.core-defs:
|
||||
variables:
|
||||
GIT_SUBMODULE_STRATEGY: recursive
|
||||
CORENAME: panda3ds
|
||||
CORE_ARGS: -DBUILD_LIBRETRO_CORE=ON -DENABLE_USER_BUILD=ON -DENABLE_VULKAN=OFF -DENABLE_LUAJIT=OFF -DENABLE_DISCORD_RPC=OFF
|
||||
|
||||
# Inclusion templates, required for the build to work
|
||||
|
||||
include:
|
||||
################################## DESKTOPS ################################
|
||||
# Linux
|
||||
- project: 'libretro-infrastructure/ci-templates'
|
||||
file: '/linux-cmake.yml'
|
||||
|
||||
# Windows
|
||||
- project: 'libretro-infrastructure/ci-templates'
|
||||
file: '/windows-cmake-mingw.yml'
|
||||
|
||||
# MacOS
|
||||
- project: 'libretro-infrastructure/ci-templates'
|
||||
file: 'osx-cmake-x86.yml'
|
||||
|
||||
# MacOS
|
||||
- project: 'libretro-infrastructure/ci-templates'
|
||||
file: 'osx-cmake-arm64.yml'
|
||||
|
||||
################################## CELLULAR ################################
|
||||
# Android
|
||||
- project: 'libretro-infrastructure/ci-templates'
|
||||
file: '/android-cmake.yml'
|
||||
|
||||
# iOS
|
||||
- project: 'libretro-infrastructure/ci-templates'
|
||||
file: '/ios-cmake.yml'
|
||||
|
||||
# Stages for building
|
||||
stages:
|
||||
- build-prepare
|
||||
- build-static
|
||||
- build-shared
|
||||
|
||||
##############################################################################
|
||||
#################################### STAGES ##################################
|
||||
##############################################################################
|
||||
#
|
||||
################################### DESKTOPS #################################
|
||||
# Linux 64-bit
|
||||
libretro-build-linux-x64:
|
||||
image: $CI_SERVER_HOST:5050/libretro-infrastructure/libretro-build-amd64-ubuntu:latest
|
||||
before_script:
|
||||
- export NUMPROC=$(($(nproc)/5))
|
||||
- sudo apt-get update -qy
|
||||
- sudo apt-get install -qy software-properties-common
|
||||
- sudo add-apt-repository -y ppa:savoury1/build-tools
|
||||
- sudo add-apt-repository -y ppa:savoury1/gcc-defaults-12
|
||||
- sudo apt-get update -qy
|
||||
- sudo apt-get install -qy cmake gcc-12 g++-12
|
||||
variables:
|
||||
CC: /usr/bin/gcc-12
|
||||
CXX: /usr/bin/g++-12
|
||||
extends:
|
||||
- .libretro-linux-cmake-x86_64
|
||||
- .core-defs
|
||||
|
||||
# Windows 64-bit
|
||||
libretro-build-windows-x64:
|
||||
extends:
|
||||
- .libretro-windows-cmake-x86_64
|
||||
- .core-defs
|
||||
|
||||
# MacOS 64-bit
|
||||
libretro-build-osx-x64:
|
||||
tags:
|
||||
- mac-apple-silicon
|
||||
variables:
|
||||
CORE_ARGS: -DBUILD_LIBRETRO_CORE=ON -DENABLE_USER_BUILD=ON -DENABLE_VULKAN=OFF -DENABLE_LUAJIT=OFF -DENABLE_DISCORD_RPC=OFF -DCMAKE_OSX_ARCHITECTURES=x86_64 -DCRYPTOPP_AMD64=1
|
||||
extends:
|
||||
- .libretro-osx-cmake-x86
|
||||
- .core-defs
|
||||
|
||||
# MacOS arm 64-bit
|
||||
libretro-build-osx-arm64:
|
||||
tags:
|
||||
- mac-apple-silicon
|
||||
extends:
|
||||
- .libretro-osx-cmake-arm64
|
||||
- .core-defs
|
||||
|
||||
################################### CELLULAR #################################
|
||||
# Android ARMv7a
|
||||
#android-armeabi-v7a:
|
||||
# extends:
|
||||
# - .libretro-android-cmake-armeabi-v7a
|
||||
# - .core-defs
|
||||
|
||||
# Android ARMv8a
|
||||
# android-arm64-v8a:
|
||||
# extends:
|
||||
# - .libretro-android-cmake-arm64-v8a
|
||||
# - .core-defs
|
||||
|
||||
# Android 64-bit x86
|
||||
# android-x86_64:
|
||||
# extends:
|
||||
# - .libretro-android-cmake-x86_64
|
||||
# - .core-defs
|
||||
|
||||
# Android 32-bit x86
|
||||
# android-x86:
|
||||
# extends:
|
||||
# - .libretro-android-cmake-x86
|
||||
# - .core-defs
|
||||
|
||||
# iOS
|
||||
# libretro-build-ios-arm64:
|
||||
# extends:
|
||||
# - .libretro-ios-cmake-arm64
|
||||
# - .core-defs
|
||||
# variables:
|
||||
# CORE_ARGS: -DBUILD_LIBRETRO_CORE=ON -DBUILD_PLAY=OFF -DENABLE_AMAZON_S3=off -DBUILD_TESTS=OFF -DCMAKE_TOOLCHAIN_FILE=deps/Dependencies/cmake-ios/ios.cmake -DTARGET_IOS=ON
|
||||
# LIBNAME: ${CORENAME}_libretro_ios.dylib
|
||||
|
||||
################################### CONSOLES #################################
|
|
@ -261,7 +261,7 @@ set(HEADER_FILES include/emulator.hpp include/helpers.hpp include/termcolor.hpp
|
|||
include/audio/miniaudio_device.hpp include/ring_buffer.hpp include/bitfield.hpp include/audio/dsp_shared_mem.hpp
|
||||
include/audio/hle_core.hpp include/capstone.hpp include/audio/aac.hpp include/PICA/pica_frag_config.hpp
|
||||
include/PICA/pica_frag_uniforms.hpp include/PICA/shader_gen_types.hpp include/PICA/shader_decompiler.hpp
|
||||
include/PICA/pica_vert_config.hpp
|
||||
include/PICA/pica_vert_config.hpp include/sdl_sensors.hpp
|
||||
)
|
||||
|
||||
cmrc_add_resource_library(
|
||||
|
@ -521,17 +521,17 @@ elseif(BUILD_HYDRA_CORE)
|
|||
target_link_libraries(Alber PUBLIC AlberCore)
|
||||
elseif(BUILD_LIBRETRO_CORE)
|
||||
include_directories(third_party/libretro/include)
|
||||
add_library(Alber SHARED src/libretro_core.cpp)
|
||||
target_link_libraries(Alber PUBLIC AlberCore)
|
||||
|
||||
set_target_properties(Alber PROPERTIES
|
||||
OUTPUT_NAME "panda3ds_libretro"
|
||||
PREFIX ""
|
||||
)
|
||||
add_library(panda3ds_libretro SHARED src/libretro_core.cpp)
|
||||
target_link_libraries(panda3ds_libretro PUBLIC AlberCore)
|
||||
set_target_properties(panda3ds_libretro PROPERTIES PREFIX "")
|
||||
endif()
|
||||
|
||||
if(ENABLE_LTO OR ENABLE_USER_BUILD)
|
||||
set_target_properties(Alber PROPERTIES INTERPROCEDURAL_OPTIMIZATION TRUE)
|
||||
if (NOT BUILD_LIBRETRO_CORE)
|
||||
set_target_properties(Alber PROPERTIES INTERPROCEDURAL_OPTIMIZATION TRUE)
|
||||
else()
|
||||
set_target_properties(panda3ds_libretro PROPERTIES INTERPROCEDURAL_OPTIMIZATION TRUE)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(ENABLE_TESTS)
|
||||
|
|
BIN
docs/3ds/accelerometer_readings/readings_flat_1.png
Normal file
BIN
docs/3ds/accelerometer_readings/readings_flat_1.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 148 KiB |
BIN
docs/3ds/accelerometer_readings/readings_flat_2.png
Normal file
BIN
docs/3ds/accelerometer_readings/readings_flat_2.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 54 KiB |
BIN
docs/3ds/accelerometer_readings/readings_shaking_1.png
Normal file
BIN
docs/3ds/accelerometer_readings/readings_shaking_1.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 212 KiB |
BIN
docs/3ds/accelerometer_readings/readings_shaking_2.png
Normal file
BIN
docs/3ds/accelerometer_readings/readings_shaking_2.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 65 KiB |
|
@ -122,6 +122,7 @@ class MainWindow : public QMainWindow {
|
|||
void showAboutMenu();
|
||||
void initControllers();
|
||||
void pollControllers();
|
||||
void setupControllerSensors(SDL_GameController* controller);
|
||||
void sendMessage(const EmulatorMessage& message);
|
||||
void dispatchMessage(const EmulatorMessage& message);
|
||||
|
||||
|
|
|
@ -37,4 +37,6 @@ class FrontendSDL {
|
|||
// And so the user can still use the keyboard to control the analog
|
||||
bool keyboardAnalogX = false;
|
||||
bool keyboardAnalogY = false;
|
||||
|
||||
void setupControllerSensors(SDL_GameController* controller);
|
||||
};
|
32
include/sdl_sensors.hpp
Normal file
32
include/sdl_sensors.hpp
Normal file
|
@ -0,0 +1,32 @@
|
|||
#pragma once
|
||||
|
||||
#include <cmath>
|
||||
#include <glm/glm.hpp>
|
||||
#include <numbers>
|
||||
|
||||
#include "helpers.hpp"
|
||||
#include "services/hid.hpp"
|
||||
|
||||
namespace Sensors::SDL {
|
||||
// Convert the rotation data we get from SDL sensor events to rotation data we can feed right to HID
|
||||
// Returns [pitch, roll, yaw]
|
||||
static glm::vec3 convertRotation(glm::vec3 rotation) {
|
||||
// Convert the rotation from rad/s to deg/s and scale by the gyroscope coefficient in HID
|
||||
constexpr float scale = 180.f / std::numbers::pi * HIDService::gyroscopeCoeff;
|
||||
// The axes are also inverted, so invert scale before the multiplication.
|
||||
return rotation * -scale;
|
||||
}
|
||||
|
||||
static glm::vec3 convertAcceleration(float* data) {
|
||||
// Set our cap to ~9 m/s^2. The 3DS sensors cap at -930 and +930, so values above this value will get clamped to 930
|
||||
// At rest (3DS laid flat on table), hardware reads around ~0 for x and z axis, and around ~480 for y axis due to gravity.
|
||||
// This code tries to mimic this approximately, with offsets based on measurements from my DualShock 4.
|
||||
static constexpr float accelMax = 9.f;
|
||||
|
||||
s16 x = std::clamp<s16>(s16(data[0] / accelMax * 930.f), -930, +930);
|
||||
s16 y = std::clamp<s16>(s16(data[1] / (SDL_STANDARD_GRAVITY * accelMax) * 930.f - 350.f), -930, +930);
|
||||
s16 z = std::clamp<s16>(s16((data[2] - 2.1f) / accelMax * 930.f), -930, +930);
|
||||
|
||||
return glm::vec3(x, y, z);
|
||||
}
|
||||
} // namespace Sensors::SDL
|
|
@ -56,6 +56,7 @@ class HIDService {
|
|||
s16 circlePadX, circlePadY; // Circlepad state
|
||||
s16 touchScreenX, touchScreenY; // Touchscreen state
|
||||
s16 roll, pitch, yaw; // Gyroscope state
|
||||
s16 accelX, accelY, accelZ; // Accelerometer state
|
||||
|
||||
bool accelerometerEnabled;
|
||||
bool eventsInitialized;
|
||||
|
@ -87,7 +88,14 @@ class HIDService {
|
|||
*(T*)&sharedMem[offset] = value;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T* getSharedMemPointer(size_t offset) {
|
||||
return (T*)&sharedMem[offset];
|
||||
}
|
||||
|
||||
public:
|
||||
static constexpr float gyroscopeCoeff = 14.375f; // Same as retail 3DS
|
||||
|
||||
HIDService(Memory& mem, Kernel& kernel) : mem(mem), kernel(kernel) {}
|
||||
void reset();
|
||||
void handleSyncRequest(u32 messagePointer);
|
||||
|
@ -128,6 +136,12 @@ class HIDService {
|
|||
void setPitch(s16 value) { pitch = value; }
|
||||
void setYaw(s16 value) { yaw = value; }
|
||||
|
||||
void setAccel(s16 x, s16 y, s16 z) {
|
||||
accelX = x;
|
||||
accelY = y;
|
||||
accelZ = z;
|
||||
}
|
||||
|
||||
void updateInputs(u64 currentTimestamp);
|
||||
|
||||
void setSharedMem(u8* ptr) {
|
||||
|
|
|
@ -627,5 +627,6 @@ namespace Audio {
|
|||
rateMultiplier = 1.f;
|
||||
|
||||
buffers = {};
|
||||
currentSamples.clear();
|
||||
}
|
||||
} // namespace Audio
|
||||
|
|
|
@ -35,6 +35,7 @@ void HIDService::reset() {
|
|||
circlePadX = circlePadY = 0;
|
||||
touchScreenX = touchScreenY = 0;
|
||||
roll = pitch = yaw = 0;
|
||||
accelX = accelY = accelZ = 0;
|
||||
}
|
||||
|
||||
void HIDService::handleSyncRequest(u32 messagePointer) {
|
||||
|
@ -103,7 +104,6 @@ void HIDService::getGyroscopeLowCalibrateParam(u32 messagePointer) {
|
|||
void HIDService::getGyroscopeCoefficient(u32 messagePointer) {
|
||||
log("HID::GetGyroscopeLowRawToDpsCoefficient\n");
|
||||
|
||||
constexpr float gyroscopeCoeff = 14.375f; // Same as retail 3DS
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x15, 2, 0));
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
mem.write32(messagePointer + 8, Helpers::bit_cast<u32, float>(gyroscopeCoeff));
|
||||
|
@ -190,6 +190,20 @@ void HIDService::updateInputs(u64 currentTick) {
|
|||
writeSharedMem<u64>(0x108, currentTick); // Write new tick count
|
||||
}
|
||||
writeSharedMem<u32>(0x118, nextAccelerometerIndex); // Index last updated by the HID module
|
||||
const size_t accelEntryOffset = 0x128 + (nextAccelerometerIndex * 6); // Offset in the array of 8 accelerometer entries
|
||||
|
||||
// Raw data of current accelerometer entry
|
||||
// TODO: How is the "raw" data actually calculated?
|
||||
s16* accelerometerDataRaw = getSharedMemPointer<s16>(0x120);
|
||||
accelerometerDataRaw[0] = accelX;
|
||||
accelerometerDataRaw[1] = accelY;
|
||||
accelerometerDataRaw[2] = accelZ;
|
||||
|
||||
// Accelerometer entry in entry table
|
||||
s16* accelerometerData = getSharedMemPointer<s16>(accelEntryOffset);
|
||||
accelerometerData[0] = accelX;
|
||||
accelerometerData[1] = accelY;
|
||||
accelerometerData[2] = accelZ;
|
||||
nextAccelerometerIndex = (nextAccelerometerIndex + 1) % 8; // Move to next entry
|
||||
|
||||
// Next, update gyro state
|
||||
|
@ -198,9 +212,10 @@ void HIDService::updateInputs(u64 currentTick) {
|
|||
writeSharedMem<u64>(0x158, currentTick); // Write new tick count
|
||||
}
|
||||
const size_t gyroEntryOffset = 0x178 + (nextGyroIndex * 6); // Offset in the array of 8 touchscreen entries
|
||||
writeSharedMem<u16>(gyroEntryOffset, pitch);
|
||||
writeSharedMem<u16>(gyroEntryOffset + 2, yaw);
|
||||
writeSharedMem<u16>(gyroEntryOffset + 4, roll);
|
||||
s16* gyroData = getSharedMemPointer<s16>(gyroEntryOffset);
|
||||
gyroData[0] = pitch;
|
||||
gyroData[1] = yaw;
|
||||
gyroData[2] = roll;
|
||||
|
||||
// Since gyroscope euler angles are relative, we zero them out here and the frontend will update them again when we receive a new rotation
|
||||
roll = pitch = yaw = 0;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#include "emulator.hpp"
|
||||
|
||||
#ifndef __ANDROID__
|
||||
#if !defined(__ANDROID__) && !defined(__LIBRETRO__)
|
||||
#include <SDL_filesystem.h>
|
||||
#endif
|
||||
|
||||
|
|
|
@ -372,7 +372,7 @@ uint retro_api_version() { return RETRO_API_VERSION; }
|
|||
|
||||
usize retro_get_memory_size(uint id) {
|
||||
if (id == RETRO_MEMORY_SYSTEM_RAM) {
|
||||
return 0;
|
||||
return Memory::FCRAM_SIZE;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -380,7 +380,7 @@ usize retro_get_memory_size(uint id) {
|
|||
|
||||
void* retro_get_memory_data(uint id) {
|
||||
if (id == RETRO_MEMORY_SYSTEM_RAM) {
|
||||
return 0;
|
||||
return emulator->getMemory().getFCRAM();
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
#include "cheats.hpp"
|
||||
#include "input_mappings.hpp"
|
||||
#include "sdl_sensors.hpp"
|
||||
#include "services/dsp.hpp"
|
||||
|
||||
MainWindow::MainWindow(QApplication* app, QWidget* parent) : QMainWindow(parent), keyboardMappings(InputMappings::defaultKeyboardMappings()) {
|
||||
|
@ -521,6 +522,8 @@ void MainWindow::initControllers() {
|
|||
SDL_Joystick* stick = SDL_GameControllerGetJoystick(gameController);
|
||||
gameControllerID = SDL_JoystickInstanceID(stick);
|
||||
}
|
||||
|
||||
setupControllerSensors(gameController);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -558,6 +561,8 @@ void MainWindow::pollControllers() {
|
|||
if (gameController == nullptr) {
|
||||
gameController = SDL_GameControllerOpen(event.cdevice.which);
|
||||
gameControllerID = event.cdevice.which;
|
||||
|
||||
setupControllerSensors(gameController);
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -598,6 +603,37 @@ void MainWindow::pollControllers() {
|
|||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case SDL_CONTROLLERSENSORUPDATE: {
|
||||
if (event.csensor.sensor == SDL_SENSOR_GYRO) {
|
||||
auto rotation = Sensors::SDL::convertRotation({
|
||||
event.csensor.data[0],
|
||||
event.csensor.data[1],
|
||||
event.csensor.data[2],
|
||||
});
|
||||
|
||||
hid.setPitch(s16(rotation.x));
|
||||
hid.setRoll(s16(rotation.y));
|
||||
hid.setYaw(s16(rotation.z));
|
||||
} else if (event.csensor.sensor == SDL_SENSOR_ACCEL) {
|
||||
auto accel = Sensors::SDL::convertAcceleration(event.csensor.data);
|
||||
hid.setAccel(accel.x, accel.y, accel.z);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::setupControllerSensors(SDL_GameController* controller) {
|
||||
bool haveGyro = SDL_GameControllerHasSensor(controller, SDL_SENSOR_GYRO) == SDL_TRUE;
|
||||
bool haveAccelerometer = SDL_GameControllerHasSensor(controller, SDL_SENSOR_ACCEL) == SDL_TRUE;
|
||||
|
||||
if (haveGyro) {
|
||||
SDL_GameControllerSetSensorEnabled(controller, SDL_SENSOR_GYRO, SDL_TRUE);
|
||||
}
|
||||
|
||||
if (haveAccelerometer) {
|
||||
SDL_GameControllerSetSensorEnabled(controller, SDL_SENSOR_ACCEL, SDL_TRUE);
|
||||
}
|
||||
}
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
#include <glad/gl.h>
|
||||
|
||||
#include "sdl_sensors.hpp"
|
||||
|
||||
FrontendSDL::FrontendSDL() : keyboardMappings(InputMappings::defaultKeyboardMappings()) {
|
||||
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS) < 0) {
|
||||
Helpers::panic("Failed to initialize SDL2");
|
||||
|
@ -20,6 +22,8 @@ FrontendSDL::FrontendSDL() : keyboardMappings(InputMappings::defaultKeyboardMapp
|
|||
SDL_Joystick* stick = SDL_GameControllerGetJoystick(gameController);
|
||||
gameControllerID = SDL_JoystickInstanceID(stick);
|
||||
}
|
||||
|
||||
setupControllerSensors(gameController);
|
||||
}
|
||||
|
||||
const EmulatorConfig& config = emu.getConfig();
|
||||
|
@ -200,6 +204,8 @@ void FrontendSDL::run() {
|
|||
if (gameController == nullptr) {
|
||||
gameController = SDL_GameControllerOpen(event.cdevice.which);
|
||||
gameControllerID = event.cdevice.which;
|
||||
|
||||
setupControllerSensors(gameController);
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -280,6 +286,24 @@ void FrontendSDL::run() {
|
|||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case SDL_CONTROLLERSENSORUPDATE: {
|
||||
if (event.csensor.sensor == SDL_SENSOR_GYRO) {
|
||||
auto rotation = Sensors::SDL::convertRotation({
|
||||
event.csensor.data[0],
|
||||
event.csensor.data[1],
|
||||
event.csensor.data[2],
|
||||
});
|
||||
|
||||
hid.setPitch(s16(rotation.x));
|
||||
hid.setRoll(s16(rotation.y));
|
||||
hid.setYaw(s16(rotation.z));
|
||||
} else if (event.csensor.sensor == SDL_SENSOR_ACCEL) {
|
||||
auto accel = Sensors::SDL::convertAcceleration(event.csensor.data);
|
||||
hid.setAccel(accel.x, accel.y, accel.z);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case SDL_DROPFILE: {
|
||||
char* droppedDir = event.drop.file;
|
||||
|
@ -342,3 +366,16 @@ void FrontendSDL::run() {
|
|||
SDL_GL_SwapWindow(window);
|
||||
}
|
||||
}
|
||||
|
||||
void FrontendSDL::setupControllerSensors(SDL_GameController* controller) {
|
||||
bool haveGyro = SDL_GameControllerHasSensor(controller, SDL_SENSOR_GYRO) == SDL_TRUE;
|
||||
bool haveAccelerometer = SDL_GameControllerHasSensor(controller, SDL_SENSOR_ACCEL) == SDL_TRUE;
|
||||
|
||||
if (haveGyro) {
|
||||
SDL_GameControllerSetSensorEnabled(controller, SDL_SENSOR_GYRO, SDL_TRUE);
|
||||
}
|
||||
|
||||
if (haveAccelerometer) {
|
||||
SDL_GameControllerSetSensorEnabled(controller, SDL_SENSOR_ACCEL, SDL_TRUE);
|
||||
}
|
||||
}
|
19
third_party/opengl/opengl.hpp
vendored
19
third_party/opengl/opengl.hpp
vendored
|
@ -432,6 +432,25 @@ namespace OpenGL {
|
|||
return m_handle != 0;
|
||||
}
|
||||
|
||||
bool createFromBinary(const uint8_t* binary, size_t size, GLenum format) {
|
||||
m_handle = glCreateProgram();
|
||||
glProgramBinary(m_handle, format, binary, size);
|
||||
|
||||
GLint success;
|
||||
glGetProgramiv(m_handle, GL_LINK_STATUS, &success);
|
||||
|
||||
if (!success) {
|
||||
char buf[4096];
|
||||
glGetProgramInfoLog(m_handle, 4096, nullptr, buf);
|
||||
fprintf(stderr, "Failed to link program\nError: %s\n", buf);
|
||||
glDeleteProgram(m_handle);
|
||||
|
||||
m_handle = 0;
|
||||
}
|
||||
|
||||
return m_handle != 0;
|
||||
}
|
||||
|
||||
GLuint handle() const { return m_handle; }
|
||||
bool exists() const { return m_handle != 0; }
|
||||
void use() const { glUseProgram(m_handle); }
|
||||
|
|
Loading…
Add table
Reference in a new issue