diff --git a/.gitignore b/.gitignore index 4cbcdd63..bd4ddc85 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,4 @@ target/ *.wuhb *.py __pycache__/ +todo.md diff --git a/CMakeLists.txt b/CMakeLists.txt index 9d37dc00..aff940dd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -169,7 +169,7 @@ if (NINTENDO_WIIU) source/modules/image/magpie/PNGHandler.cpp source/modules/font/freetype/Font.cpp source/modules/font/freetype/TrueTypeRasterizer.cpp - source/modules/graphics/Font.cpp + source/modules/graphics/freetype/Font.cpp ) add_library(ddsparse diff --git a/include/common/Exception.hpp b/include/common/Exception.hpp index 7b526535..3657d731 100644 --- a/include/common/Exception.hpp +++ b/include/common/Exception.hpp @@ -27,4 +27,25 @@ namespace love private: std::string message; }; + +#if !(__DEBUG__) + #define LOG() +#else + #include + + // Macro to log to both stdout and a debug.log file + #define LOG(format, ...) \ + do \ + { \ + std::FILE* outFile = std::fopen("debug.log", "a"); \ + static const char* data = "%s %s:%d: " format "\n"; \ + \ + if (outFile) \ + { \ + std::fprintf(outFile, data, __FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__); \ + std::fclose(outFile); \ + } \ + std::printf(data, __FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__); \ + } while (0) +#endif } // namespace love diff --git a/include/common/screen.hpp b/include/common/screen.hpp index b790d314..6e87adf3 100644 --- a/include/common/screen.hpp +++ b/include/common/screen.hpp @@ -22,7 +22,7 @@ namespace love static constexpr inline Screen INVALID_SCREEN = (Screen)-1; static constexpr inline Screen DEFAULT_SCREEN = (Screen)0; - inline Screen currentScreen = INVALID_SCREEN; + inline Screen currentScreen = DEFAULT_SCREEN; std::span getScreenInfo(); @@ -56,17 +56,4 @@ namespace love currentScreen = id; } - - inline void nextScreen() - { - const auto& info = getScreenInfo(); - - if (currentScreen == INVALID_SCREEN) - currentScreen = DEFAULT_SCREEN; - else - currentScreen = (Screen)((int)currentScreen + 1); - - if (currentScreen >= (Screen)info.size()) - currentScreen = DEFAULT_SCREEN; - } } // namespace love diff --git a/include/driver/EventQueue.tcc b/include/driver/EventQueue.tcc index 062c19cc..bf2d5885 100644 --- a/include/driver/EventQueue.tcc +++ b/include/driver/EventQueue.tcc @@ -3,7 +3,7 @@ #include "common/Singleton.tcc" #include "events.hpp" -#include "modules/joystick/Joystick.hpp" +#include "modules/joystick/Joystick.tcc" #include #include diff --git a/include/modules/graphics/Font.hpp b/include/modules/graphics/Font.hpp index 7231b224..93b134e0 100644 --- a/include/modules/graphics/Font.hpp +++ b/include/modules/graphics/Font.hpp @@ -1,3 +1,5 @@ +#pragma once + #include "modules/graphics/Font.tcc" namespace love @@ -10,8 +12,5 @@ namespace love virtual void createTexture() override; bool loadVolatile() override; - - private: - virtual const FontBase::Glyph& addGlyph(TextShaper::GlyphIndex glyphIndex) override; }; } // namespace love diff --git a/include/modules/graphics/Shader.tcc b/include/modules/graphics/Shader.tcc index e1d40723..9d61d13f 100644 --- a/include/modules/graphics/Shader.tcc +++ b/include/modules/graphics/Shader.tcc @@ -31,6 +31,8 @@ namespace love static ShaderBase* current; static ShaderBase* standardShaders[STANDARD_MAX_ENUM]; + ShaderBase(StandardShader type); + virtual ~ShaderBase(); virtual void attach() = 0; @@ -38,5 +40,7 @@ namespace love static void attachDefault(StandardShader type); static bool isDefaultActive(); + + StandardShader shaderType; }; } // namespace love diff --git a/include/modules/graphics/freetype/Font.hpp b/include/modules/graphics/freetype/Font.hpp new file mode 100644 index 00000000..4e4567c3 --- /dev/null +++ b/include/modules/graphics/freetype/Font.hpp @@ -0,0 +1,20 @@ +#pragma once + +#include "modules/font/freetype/TrueTypeRasterizer.hpp" +#include "modules/graphics/Font.tcc" + +namespace love +{ + class Font : public FontBase + { + public: + Font(Rasterizer* rasterizer, const SamplerState& samplerState); + + virtual void createTexture() override; + + bool loadVolatile() override; + + private: + virtual const FontBase::Glyph& addGlyph(TextShaper::GlyphIndex glyphIndex) override; + }; +} // namespace love diff --git a/include/modules/graphics/wrap_Graphics.hpp b/include/modules/graphics/wrap_Graphics.hpp index ad059cb6..ac7a9cbe 100644 --- a/include/modules/graphics/wrap_Graphics.hpp +++ b/include/modules/graphics/wrap_Graphics.hpp @@ -199,6 +199,8 @@ namespace Wrap_Graphics int getScreens(lua_State* L); + int getActiveScreen(lua_State* L); + int setActiveScreen(lua_State* L); int is3D(lua_State* L); @@ -211,5 +213,7 @@ namespace Wrap_Graphics int getDepth(lua_State* L); + int copyCurrentScanBuffer(lua_State* L); + int open(lua_State* L); } // namespace Wrap_Graphics diff --git a/include/modules/joystick/Joystick.tcc b/include/modules/joystick/Joystick.tcc index ae02ecaf..de910950 100644 --- a/include/modules/joystick/Joystick.tcc +++ b/include/modules/joystick/Joystick.tcc @@ -53,6 +53,8 @@ namespace love GAMEPAD_BUTTON_DPAD_DOWN, GAMEPAD_BUTTON_DPAD_LEFT, GAMEPAD_BUTTON_DPAD_RIGHT, + GAMEPAD_BUTTON_MISC1, + GAMEPAD_BUTTON_MISC2, GAMEPAD_BUTTON_MAX_ENUM }; @@ -202,7 +204,9 @@ namespace love { "dpup", GAMEPAD_BUTTON_DPAD_UP }, { "dpdown", GAMEPAD_BUTTON_DPAD_DOWN }, { "dpleft", GAMEPAD_BUTTON_DPAD_LEFT }, - { "dpright", GAMEPAD_BUTTON_DPAD_RIGHT } + { "dpright", GAMEPAD_BUTTON_DPAD_RIGHT }, + { "misc1", GAMEPAD_BUTTON_MISC1 }, + { "misc2", GAMEPAD_BUTTON_MISC2 } ); STRINGMAP_DECLARE(GamepadAxes, GamepadAxis, @@ -260,11 +264,7 @@ namespace love return std::clamp(value / MAX_AXIS_VALUE, -1.0f, 1.0f); } - JoystickBase(int id) : - joystickType(JOYSTICK_TYPE_UNKNOWN), - instanceId(-1), - id(id), - sensors() + JoystickBase(int id) : joystickType(JOYSTICK_TYPE_UNKNOWN), instanceId(-1), id(id), sensors() { this->sensors[Sensor::SENSOR_ACCELEROMETER] = false; this->sensors[Sensor::SENSOR_GYROSCOPE] = false; diff --git a/include/modules/joystick/JoystickModule.hpp b/include/modules/joystick/JoystickModule.hpp index cb04b871..373340e9 100644 --- a/include/modules/joystick/JoystickModule.hpp +++ b/include/modules/joystick/JoystickModule.hpp @@ -1,7 +1,7 @@ #pragma once #include "common/Module.hpp" -#include "modules/joystick/Joystick.hpp" +#include "modules/joystick/Joystick.tcc" #include #include diff --git a/include/modules/joystick/wrap_Joystick.hpp b/include/modules/joystick/wrap_Joystick.hpp index 61ac75a7..827c7e6d 100644 --- a/include/modules/joystick/wrap_Joystick.hpp +++ b/include/modules/joystick/wrap_Joystick.hpp @@ -1,7 +1,7 @@ #pragma once #include "common/luax.hpp" -#include "modules/joystick/Joystick.hpp" +#include "modules/joystick/Joystick.tcc" namespace love { diff --git a/platform/cafe/CMakeLists.txt b/platform/cafe/CMakeLists.txt index 78104379..02e5d280 100644 --- a/platform/cafe/CMakeLists.txt +++ b/platform/cafe/CMakeLists.txt @@ -33,7 +33,8 @@ source/modules/audio/Source.cpp source/modules/graphics/Graphics.cpp source/modules/graphics/Shader.cpp source/modules/graphics/Texture.cpp -source/modules/joystick/Joystick.cpp +source/modules/joystick/vpad/Joystick.cpp +source/modules/joystick/kpad/Joystick.cpp source/modules/joystick/JoystickModule.cpp source/modules/keyboard/Keyboard.cpp source/modules/system/System.cpp diff --git a/platform/cafe/include/driver/EventQueue.hpp b/platform/cafe/include/driver/EventQueue.hpp index 4c5524e6..c183fc3e 100644 --- a/platform/cafe/include/driver/EventQueue.hpp +++ b/platform/cafe/include/driver/EventQueue.hpp @@ -1,7 +1,9 @@ #pragma once #include "driver/EventQueue.tcc" -#include "modules/joystick/Joystick.hpp" + +#include "modules/joystick/kpad/Joystick.hpp" +#include "modules/joystick/vpad/Joystick.hpp" #include @@ -17,7 +19,7 @@ namespace love void pollInternal() override; private: - Joystick* gamepad; + vpad::Joystick* gamepad; VPADTouchData previousTouch; }; } // namespace love diff --git a/platform/cafe/include/driver/display/Framebuffer.hpp b/platform/cafe/include/driver/display/Framebuffer.hpp index cd6ad0f1..0d8eda37 100644 --- a/platform/cafe/include/driver/display/Framebuffer.hpp +++ b/platform/cafe/include/driver/display/Framebuffer.hpp @@ -49,14 +49,14 @@ namespace love void copyScanBuffer(); - void useState() + operator GX2ContextState*() { - GX2SetContextState(this->state); + return this->state; } private: static constexpr auto FORMAT = GX2_SURFACE_FORMAT_UNORM_R8_G8_B8_A8; - static constexpr auto BUFFER_MODE = GX2_BUFFERING_MODE_SINGLE; + static constexpr auto BUFFER_MODE = GX2_BUFFERING_MODE_DOUBLE; static constexpr auto INVALIDATE_COLOR_BUFFER = GX2_INVALIDATE_MODE_CPU | GX2_INVALIDATE_MODE_COLOR_BUFFER; diff --git a/platform/cafe/include/driver/display/GX2.hpp b/platform/cafe/include/driver/display/GX2.hpp index 71e9b602..19479701 100644 --- a/platform/cafe/include/driver/display/GX2.hpp +++ b/platform/cafe/include/driver/display/GX2.hpp @@ -74,6 +74,8 @@ namespace love void setMode(int width, int height); + void copyCurrentScanBuffer(); + // clang-format off ENUMMAP_DECLARE(PixelFormats, PixelFormat, GX2SurfaceFormat, { PIXELFORMAT_R8_UNORM, GX2_SURFACE_FORMAT_UNORM_R8 }, diff --git a/platform/cafe/include/driver/display/Uniform.hpp b/platform/cafe/include/driver/display/Uniform.hpp index 34490afd..d210d665 100644 --- a/platform/cafe/include/driver/display/Uniform.hpp +++ b/platform/cafe/include/driver/display/Uniform.hpp @@ -7,7 +7,8 @@ namespace love { - glm::mat4 updateMatrix(const glm::mat4& matrix); + // void updateMatrix(glm::mat4& modelView, const Matrix4& matrix); + glm::mat4 createTransposedSwappedMatrix(const Matrix4& matrix); struct Uniform { @@ -26,6 +27,18 @@ namespace love for (size_t index = 0; index < count; index++) std::printf("projection[%zu] = %u\n", index, projection[index]); } + + void update(const Matrix4& matrix) + { + const auto count = sizeof(glm::mat4) / sizeof(uint32_t); + uint32_t* destination = (uint32_t*)glm::value_ptr(this->modelView); + + glm::mat4 sourceMatrix = glm::transpose(glm::make_mat4(matrix.getElements())); + uint32_t* source = (uint32_t*)glm::value_ptr(sourceMatrix); + + for (int i = 0; i < count; ++i) + destination[i] = __builtin_bswap32(source[i]); + } }; } // namespace love diff --git a/platform/cafe/include/modules/graphics/Graphics.hpp b/platform/cafe/include/modules/graphics/Graphics.hpp index 76d0f10e..903c4e4e 100644 --- a/platform/cafe/include/modules/graphics/Graphics.hpp +++ b/platform/cafe/include/modules/graphics/Graphics.hpp @@ -62,6 +62,8 @@ namespace love GX2ColorBuffer getInternalBackbuffer() const; + void copyCurrentScanBuffer(); + // clang-format off virtual TextureBase* newTexture(const TextureBase::Settings& settings, const TextureBase::Slices* data = nullptr) override; // clang-format on diff --git a/platform/cafe/include/modules/graphics/Texture.hpp b/platform/cafe/include/modules/graphics/Texture.hpp index e1440e5b..3a4c25e8 100644 --- a/platform/cafe/include/modules/graphics/Texture.hpp +++ b/platform/cafe/include/modules/graphics/Texture.hpp @@ -41,6 +41,6 @@ namespace love GX2Texture* texture = nullptr; GX2ColorBuffer* target = nullptr; - GX2Sampler* sampler = nullptr; + GX2Sampler sampler; }; } // namespace love diff --git a/platform/cafe/include/modules/joystick/Joystick.hpp b/platform/cafe/include/modules/joystick/Joystick.hpp deleted file mode 100644 index 935515d2..00000000 --- a/platform/cafe/include/modules/joystick/Joystick.hpp +++ /dev/null @@ -1,168 +0,0 @@ -#pragma once - -#include "modules/joystick/Joystick.tcc" - -#include -#include - -namespace love -{ - class Joystick : public JoystickBase - { - public: - Joystick(int id); - - Joystick(int id, int index); - - ~Joystick(); - - virtual void update(); - - bool isDRCGamepad() const - { - return this->gamepadType == GAMEPAD_TYPE_NINTENDO_WII_U_GAMEPAD; - } - - VPADStatus& getVPADStatus() - { - return this->vpadStatus; - } - - virtual bool open(int64_t deviceId) override; - - virtual void close() override; - - virtual bool isConnected() const override; - - virtual float getAxis(GamepadAxis axis) const override; - - virtual std::vector getAxes() const override; - - virtual bool isDown(std::span buttons) const override; - - virtual bool isUp(std::span buttons) const override; - - virtual bool isAxisChanged(GamepadAxis axis) const override; - - virtual void setPlayerIndex(int index) override; - - virtual int getPlayerIndex() const override; - - virtual JoystickInput getGamepadMapping(const GamepadInput& input) const override; - - virtual std::string getGamepadMappingString() const override; - - virtual bool isVibrationSupported() const override; - - virtual bool setVibration(float left, float right, float duration = -1.0f) override; - - virtual bool setVibration() override; - - virtual void getVibration(float& left, float& right) const override; - - virtual bool hasSensor(Sensor::SensorType type) const override; - - virtual bool isSensorEnabled(Sensor::SensorType type) const override; - - virtual void setSensorEnabled(Sensor::SensorType type, bool enable) override; - - virtual std::vector getSensorData(Sensor::SensorType type) const override; - - using JoystickBase::getConstant; - - enum VPADAxis - { - VPADAXIS_LEFTX = VPAD_STICK_L_EMULATION_LEFT | VPAD_STICK_L_EMULATION_RIGHT, - VPADAXIS_LEFTY = VPAD_STICK_L_EMULATION_UP | VPAD_STICK_L_EMULATION_DOWN, - VPADAXIS_RIGHTX = VPAD_STICK_R_EMULATION_LEFT | VPAD_STICK_R_EMULATION_RIGHT, - VPADAXIS_RIGHTY = VPAD_STICK_R_EMULATION_UP | VPAD_STICK_R_EMULATION_DOWN, - VPADAXIS_TRIGGERLEFT = VPAD_BUTTON_ZL, - VPADAXIS_TRIGGERRIGHT = VPAD_BUTTON_ZR - }; - - enum WPADProAxis - { - WPADPROAXIS_LEFTX = WPAD_PRO_STICK_L_EMULATION_LEFT | WPAD_PRO_STICK_L_EMULATION_RIGHT, - WPADPROAXIS_LEFTY = WPAD_PRO_STICK_L_EMULATION_UP | WPAD_PRO_STICK_L_EMULATION_DOWN, - WPADPROAXIS_RIGHTX = WPAD_PRO_STICK_R_EMULATION_LEFT | WPAD_PRO_STICK_R_EMULATION_RIGHT, - WPADPROAXIS_RIGHTY = WPAD_PRO_STICK_R_EMULATION_UP | WPAD_PRO_STICK_R_EMULATION_DOWN - }; - - // clang-format off - ENUMMAP_DECLARE(WpadProButtons, GamepadButton, WPADProButton, - { GAMEPAD_BUTTON_A, WPAD_PRO_BUTTON_A }, - { GAMEPAD_BUTTON_B, WPAD_PRO_BUTTON_B }, - { GAMEPAD_BUTTON_X, WPAD_PRO_BUTTON_X }, - { GAMEPAD_BUTTON_Y, WPAD_PRO_BUTTON_Y }, - - { GAMEPAD_BUTTON_DPAD_LEFT, WPAD_PRO_BUTTON_LEFT }, - { GAMEPAD_BUTTON_DPAD_UP, WPAD_PRO_BUTTON_UP }, - { GAMEPAD_BUTTON_DPAD_RIGHT, WPAD_PRO_BUTTON_RIGHT }, - { GAMEPAD_BUTTON_DPAD_DOWN, WPAD_PRO_BUTTON_DOWN }, - - { GAMEPAD_BUTTON_START, WPAD_PRO_BUTTON_PLUS }, - { GAMEPAD_BUTTON_BACK, WPAD_PRO_BUTTON_MINUS }, - { GAMEPAD_BUTTON_LEFTSHOULDER, WPAD_PRO_TRIGGER_L }, - { GAMEPAD_BUTTON_RIGHTSHOULDER, WPAD_PRO_TRIGGER_R }, - - { GAMEPAD_BUTTON_LEFTSTICK, WPAD_PRO_BUTTON_STICK_L }, - { GAMEPAD_BUTTON_RIGHTSTICK, WPAD_PRO_BUTTON_STICK_R } - ); - - ENUMMAP_DECLARE(VpadAxes, GamepadAxis, VPADAxis, - { GAMEPAD_AXIS_LEFTX, VPADAXIS_LEFTX }, - { GAMEPAD_AXIS_LEFTY, VPADAXIS_LEFTY }, - { GAMEPAD_AXIS_RIGHTX, VPADAXIS_RIGHTX }, - { GAMEPAD_AXIS_RIGHTY, VPADAXIS_RIGHTY }, - { GAMEPAD_AXIS_TRIGGERLEFT, VPADAXIS_TRIGGERLEFT }, - { GAMEPAD_AXIS_TRIGGERRIGHT, VPADAXIS_TRIGGERRIGHT } - ); - - ENUMMAP_DECLARE(VpadButtons, GamepadButton, VPADButtons, - { GAMEPAD_BUTTON_A, VPAD_BUTTON_A }, - { GAMEPAD_BUTTON_B, VPAD_BUTTON_B }, - { GAMEPAD_BUTTON_X, VPAD_BUTTON_X }, - { GAMEPAD_BUTTON_Y, VPAD_BUTTON_Y }, - - { GAMEPAD_BUTTON_DPAD_LEFT, VPAD_BUTTON_LEFT }, - { GAMEPAD_BUTTON_DPAD_UP, VPAD_BUTTON_UP }, - { GAMEPAD_BUTTON_DPAD_RIGHT, VPAD_BUTTON_RIGHT }, - { GAMEPAD_BUTTON_DPAD_DOWN, VPAD_BUTTON_DOWN }, - - { GAMEPAD_BUTTON_START, VPAD_BUTTON_PLUS }, - { GAMEPAD_BUTTON_BACK, VPAD_BUTTON_MINUS }, - { GAMEPAD_BUTTON_LEFTSHOULDER, VPAD_BUTTON_L }, - { GAMEPAD_BUTTON_RIGHTSHOULDER, VPAD_BUTTON_R }, - - { GAMEPAD_BUTTON_LEFTSTICK, VPAD_BUTTON_STICK_L }, - { GAMEPAD_BUTTON_RIGHTSTICK, VPAD_BUTTON_STICK_R } - ); - - ENUMMAP_DECLARE(WpadTypes, GamepadType, WPADExtensionType, - { GAMEPAD_TYPE_NINTENDO_WII_U_PRO, WPAD_EXT_PRO_CONTROLLER } - ); - // clang-format on - - private: - VPADStatus vpadStatus; - VPADReadError vpadError; - - KPADStatus kpadStatus; - KPADError kpadError; - - mutable struct State - { - uint32_t pressed; - uint32_t released; - uint32_t held; - } state; - - float getVPADAxis(GamepadAxis axis) const; - - bool isVPADButtonDown(std::span buttons) const; - - float getKPADAxis(GamepadAxis axis) const; - - bool isKPADButtonDown(std::span buttons) const; - }; -} // namespace love diff --git a/platform/cafe/include/modules/joystick/kpad/Joystick.hpp b/platform/cafe/include/modules/joystick/kpad/Joystick.hpp new file mode 100644 index 00000000..c534168e --- /dev/null +++ b/platform/cafe/include/modules/joystick/kpad/Joystick.hpp @@ -0,0 +1,203 @@ +#pragma once + +#include "modules/joystick/Joystick.tcc" + +#include + +namespace love +{ + namespace kpad + { + class Joystick : public JoystickBase + { + public: + Joystick(int id); + + Joystick(int id, int index); + + ~Joystick(); + + virtual void update(); + + virtual bool open(int64_t deviceId) override; + + virtual void close() override; + + virtual bool isConnected() const override; + + virtual float getAxis(GamepadAxis axis) const override; + + virtual std::vector getAxes() const override; + + virtual bool isDown(std::span buttons) const override; + + virtual bool isUp(std::span buttons) const override; + + virtual bool isAxisChanged(GamepadAxis axis) const override; + + virtual void setPlayerIndex(int index) override; + + virtual int getPlayerIndex() const override; + + virtual JoystickInput getGamepadMapping(const GamepadInput& input) const override; + + virtual std::string getGamepadMappingString() const override; + + virtual bool isVibrationSupported() const override; + + virtual bool setVibration(float left, float right, float duration = -1.0f) override; + + virtual bool setVibration() override; + + virtual void getVibration(float& left, float& right) const override; + + virtual bool hasSensor(Sensor::SensorType type) const override; + + virtual bool isSensorEnabled(Sensor::SensorType type) const override; + + virtual void setSensorEnabled(Sensor::SensorType type, bool enable) override; + + virtual std::vector getSensorData(Sensor::SensorType type) const override; + + using JoystickBase::getConstant; + + // #region Wii Remote + // clang-format off + ENUMMAP_DECLARE(CoreButtons, GamepadButton, WPADButton, + { GAMEPAD_BUTTON_A, WPAD_BUTTON_A }, + { GAMEPAD_BUTTON_B, WPAD_BUTTON_B }, + + { GAMEPAD_BUTTON_DPAD_LEFT, WPAD_BUTTON_LEFT }, + { GAMEPAD_BUTTON_DPAD_UP, WPAD_BUTTON_UP }, + { GAMEPAD_BUTTON_DPAD_RIGHT, WPAD_BUTTON_RIGHT }, + { GAMEPAD_BUTTON_DPAD_DOWN, WPAD_BUTTON_DOWN }, + + { GAMEPAD_BUTTON_START, WPAD_BUTTON_PLUS }, + { GAMEPAD_BUTTON_BACK, WPAD_BUTTON_MINUS }, + + { GAMEPAD_BUTTON_MISC1, WPAD_BUTTON_1 }, + { GAMEPAD_BUTTON_MISC2, WPAD_BUTTON_2 } + ) + // clang-format on + // #endregion + + // #region WiimoteNunchuck + enum NunchuckAxis + { + NUNCHUCK_AXIS_X = WPAD_NUNCHUK_STICK_EMULATION_LEFT | WPAD_NUNCHUK_STICK_EMULATION_RIGHT, + NUNCHUCK_AXIS_Y = WPAD_NUNCHUK_STICK_EMULATION_UP | WPAD_NUNCHUK_STICK_EMULATION_DOWN + }; + + // clang-format off + ENUMMAP_DECLARE(NunchuckButtons, GamepadButton, WPADNunchukButton, + { GAMEPAD_BUTTON_LEFTSHOULDER, WPAD_NUNCHUK_BUTTON_C } + ); + + ENUMMAP_DECLARE(NunchuckAxes, GamepadAxis, NunchuckAxis, + { GAMEPAD_AXIS_LEFTX, NUNCHUCK_AXIS_X }, + { GAMEPAD_AXIS_LEFTY, NUNCHUCK_AXIS_Y }, + ); + // clang-format on + // #endregion + + // #region Classic + enum ClassicAxis + { + CLASSIC_AXIS_LEFTX = + WPAD_CLASSIC_STICK_L_EMULATION_LEFT | WPAD_CLASSIC_STICK_R_EMULATION_RIGHT, + CLASSIC_AXIS_LEFTY = WPAD_CLASSIC_STICK_L_EMULATION_UP | WPAD_CLASSIC_STICK_L_EMULATION_DOWN, + CLASSIC_AXIS_RIGHTX = + WPAD_CLASSIC_STICK_R_EMULATION_LEFT | WPAD_CLASSIC_STICK_R_EMULATION_RIGHT, + CLASSIC_AXIS_RIGHTY = WPAD_CLASSIC_STICK_R_EMULATION_UP | WPAD_CLASSIC_STICK_R_EMULATION_DOWN + }; + + // clang-format off + ENUMMAP_DECLARE(ClassicButtons, GamepadButton, WPADClassicButton, + { GAMEPAD_BUTTON_A, WPAD_CLASSIC_BUTTON_A }, + { GAMEPAD_BUTTON_B, WPAD_CLASSIC_BUTTON_B }, + { GAMEPAD_BUTTON_X, WPAD_CLASSIC_BUTTON_X }, + { GAMEPAD_BUTTON_Y, WPAD_CLASSIC_BUTTON_Y }, + + { GAMEPAD_BUTTON_DPAD_LEFT, WPAD_CLASSIC_BUTTON_LEFT }, + { GAMEPAD_BUTTON_DPAD_UP, WPAD_CLASSIC_BUTTON_UP }, + { GAMEPAD_BUTTON_DPAD_RIGHT, WPAD_CLASSIC_BUTTON_RIGHT }, + { GAMEPAD_BUTTON_DPAD_DOWN, WPAD_CLASSIC_BUTTON_DOWN }, + + { GAMEPAD_BUTTON_START, WPAD_CLASSIC_BUTTON_PLUS }, + { GAMEPAD_BUTTON_BACK, WPAD_CLASSIC_BUTTON_MINUS }, + + { GAMEPAD_BUTTON_LEFTSHOULDER, WPAD_CLASSIC_BUTTON_L }, + { GAMEPAD_BUTTON_RIGHTSHOULDER, WPAD_CLASSIC_BUTTON_R } + ); + + ENUMMAP_DECLARE(ClassicAxes, GamepadAxis, ClassicAxis, + { GAMEPAD_AXIS_LEFTX, CLASSIC_AXIS_LEFTX }, + { GAMEPAD_AXIS_LEFTY, CLASSIC_AXIS_LEFTY }, + { GAMEPAD_AXIS_RIGHTX, CLASSIC_AXIS_RIGHTX }, + { GAMEPAD_AXIS_RIGHTY, CLASSIC_AXIS_RIGHTY } + ); + // clang-format on + // #endregion + + // #region Pro + enum ProAxis + { + PRO_AXIS_LEFTX = WPAD_PRO_STICK_L_EMULATION_LEFT | WPAD_PRO_STICK_L_EMULATION_RIGHT, + PRO_AXIS_LEFTY = WPAD_PRO_STICK_L_EMULATION_UP | WPAD_PRO_STICK_L_EMULATION_DOWN, + PRO_AXIS_RIGHTX = WPAD_PRO_STICK_R_EMULATION_LEFT | WPAD_PRO_STICK_R_EMULATION_RIGHT, + PRO_AXIS_RIGHTY = WPAD_PRO_STICK_R_EMULATION_UP | WPAD_PRO_STICK_R_EMULATION_DOWN + }; + + // clang-format off + ENUMMAP_DECLARE(ProButtons, GamepadButton, WPADProButton, + { GAMEPAD_BUTTON_A, WPAD_PRO_BUTTON_A }, + { GAMEPAD_BUTTON_B, WPAD_PRO_BUTTON_B }, + { GAMEPAD_BUTTON_X, WPAD_PRO_BUTTON_X }, + { GAMEPAD_BUTTON_Y, WPAD_PRO_BUTTON_Y }, + + { GAMEPAD_BUTTON_DPAD_LEFT, WPAD_PRO_BUTTON_LEFT }, + { GAMEPAD_BUTTON_DPAD_UP, WPAD_PRO_BUTTON_UP }, + { GAMEPAD_BUTTON_DPAD_RIGHT, WPAD_PRO_BUTTON_RIGHT }, + { GAMEPAD_BUTTON_DPAD_DOWN, WPAD_PRO_BUTTON_DOWN }, + + { GAMEPAD_BUTTON_START, WPAD_PRO_BUTTON_PLUS }, + { GAMEPAD_BUTTON_BACK, WPAD_PRO_BUTTON_MINUS }, + + { GAMEPAD_BUTTON_LEFTSHOULDER, WPAD_PRO_TRIGGER_L }, + { GAMEPAD_BUTTON_RIGHTSHOULDER, WPAD_PRO_TRIGGER_R }, + + { GAMEPAD_BUTTON_LEFTSTICK, WPAD_PRO_BUTTON_STICK_L }, + { GAMEPAD_BUTTON_RIGHTSTICK, WPAD_PRO_BUTTON_STICK_R } + ); + + ENUMMAP_DECLARE(ProAxes, GamepadAxis, ProAxis, + { GAMEPAD_AXIS_LEFTX, PRO_AXIS_LEFTX }, + { GAMEPAD_AXIS_LEFTY, PRO_AXIS_LEFTY }, + { GAMEPAD_AXIS_RIGHTX, PRO_AXIS_RIGHTX }, + { GAMEPAD_AXIS_RIGHTY, PRO_AXIS_RIGHTY } + ); + // clang-format on + // #endregion + + private: + template + bool isButtonDown(std::span buttons) const; + + template + bool isButtonUp(std::span buttons) const; + + template + bool isAxisValueChanged(GamepadAxis axis) const; + + KPADStatus status; + KPADError error; + + mutable struct State + { + uint32_t pressed; + uint32_t released; + uint32_t held; + } state; + }; + } // namespace kpad +} // namespace love diff --git a/platform/cafe/include/modules/joystick/vpad/Joystick.hpp b/platform/cafe/include/modules/joystick/vpad/Joystick.hpp new file mode 100644 index 00000000..6e87e5e0 --- /dev/null +++ b/platform/cafe/include/modules/joystick/vpad/Joystick.hpp @@ -0,0 +1,122 @@ +#pragma once + +#include "modules/joystick/Joystick.tcc" + +#include + +namespace love +{ + namespace vpad + { + class Joystick : public JoystickBase + { + public: + Joystick(int id); + + Joystick(int id, int index); + + ~Joystick(); + + virtual void update(); + + VPADStatus& getVPADStatus() + { + return this->vpadStatus; + } + + virtual bool open(int64_t deviceId) override; + + virtual void close() override; + + virtual bool isConnected() const override; + + virtual float getAxis(GamepadAxis axis) const override; + + virtual std::vector getAxes() const override; + + virtual bool isDown(std::span buttons) const override; + + virtual bool isUp(std::span buttons) const override; + + virtual bool isAxisChanged(GamepadAxis axis) const override; + + virtual void setPlayerIndex(int index) override; + + virtual int getPlayerIndex() const override; + + virtual JoystickInput getGamepadMapping(const GamepadInput& input) const override; + + virtual std::string getGamepadMappingString() const override; + + virtual bool isVibrationSupported() const override; + + virtual bool setVibration(float left, float right, float duration = -1.0f) override; + + virtual bool setVibration() override; + + virtual void getVibration(float& left, float& right) const override; + + virtual bool hasSensor(Sensor::SensorType type) const override; + + virtual bool isSensorEnabled(Sensor::SensorType type) const override; + + virtual void setSensorEnabled(Sensor::SensorType type, bool enable) override; + + virtual std::vector getSensorData(Sensor::SensorType type) const override; + + using JoystickBase::getConstant; + + enum VPADAxis + { + VPADAXIS_LEFTX = VPAD_STICK_L_EMULATION_LEFT | VPAD_STICK_L_EMULATION_RIGHT, + VPADAXIS_LEFTY = VPAD_STICK_L_EMULATION_UP | VPAD_STICK_L_EMULATION_DOWN, + VPADAXIS_RIGHTX = VPAD_STICK_R_EMULATION_LEFT | VPAD_STICK_R_EMULATION_RIGHT, + VPADAXIS_RIGHTY = VPAD_STICK_R_EMULATION_UP | VPAD_STICK_R_EMULATION_DOWN, + VPADAXIS_TRIGGERLEFT = VPAD_BUTTON_ZL, + VPADAXIS_TRIGGERRIGHT = VPAD_BUTTON_ZR + }; + + // clang-format off + ENUMMAP_DECLARE(VpadAxes, GamepadAxis, VPADAxis, + { GAMEPAD_AXIS_LEFTX, VPADAXIS_LEFTX }, + { GAMEPAD_AXIS_LEFTY, VPADAXIS_LEFTY }, + { GAMEPAD_AXIS_RIGHTX, VPADAXIS_RIGHTX }, + { GAMEPAD_AXIS_RIGHTY, VPADAXIS_RIGHTY }, + { GAMEPAD_AXIS_TRIGGERLEFT, VPADAXIS_TRIGGERLEFT }, + { GAMEPAD_AXIS_TRIGGERRIGHT, VPADAXIS_TRIGGERRIGHT } + ); + + ENUMMAP_DECLARE(VpadButtons, GamepadButton, VPADButtons, + { GAMEPAD_BUTTON_A, VPAD_BUTTON_A }, + { GAMEPAD_BUTTON_B, VPAD_BUTTON_B }, + { GAMEPAD_BUTTON_X, VPAD_BUTTON_X }, + { GAMEPAD_BUTTON_Y, VPAD_BUTTON_Y }, + + { GAMEPAD_BUTTON_DPAD_LEFT, VPAD_BUTTON_LEFT }, + { GAMEPAD_BUTTON_DPAD_UP, VPAD_BUTTON_UP }, + { GAMEPAD_BUTTON_DPAD_RIGHT, VPAD_BUTTON_RIGHT }, + { GAMEPAD_BUTTON_DPAD_DOWN, VPAD_BUTTON_DOWN }, + + { GAMEPAD_BUTTON_START, VPAD_BUTTON_PLUS }, + { GAMEPAD_BUTTON_BACK, VPAD_BUTTON_MINUS }, + { GAMEPAD_BUTTON_LEFTSHOULDER, VPAD_BUTTON_L }, + { GAMEPAD_BUTTON_RIGHTSHOULDER, VPAD_BUTTON_R }, + + { GAMEPAD_BUTTON_LEFTSTICK, VPAD_BUTTON_STICK_L }, + { GAMEPAD_BUTTON_RIGHTSTICK, VPAD_BUTTON_STICK_R } + ); + // clang-format on + + private: + VPADStatus vpadStatus; + VPADReadError vpadError; + + mutable struct State + { + uint32_t pressed; + uint32_t released; + uint32_t held; + } state; + }; + } // namespace vpad +} // namespace love diff --git a/platform/cafe/source/boot.cpp b/platform/cafe/source/boot.cpp index 281e88e8..927589b1 100644 --- a/platform/cafe/source/boot.cpp +++ b/platform/cafe/source/boot.cpp @@ -75,6 +75,9 @@ namespace love return -1; } + WPADEnableWiiRemote(true); + WPADEnableURCC(true); + Console::setMainCoreId(OSGetCoreId()); return 0; diff --git a/platform/cafe/source/driver/EventQueue.cpp b/platform/cafe/source/driver/EventQueue.cpp index b274d5a1..bf4dcc01 100644 --- a/platform/cafe/source/driver/EventQueue.cpp +++ b/platform/cafe/source/driver/EventQueue.cpp @@ -60,13 +60,13 @@ namespace love continue; if (joystick->getGamepadType() == GAMEPAD_TYPE_NINTENDO_WII_U_GAMEPAD) - this->gamepad = (Joystick*)joystick; + this->gamepad = (vpad::Joystick*)joystick; joystick->update(); - for (int input = 0; input < Joystick::GAMEPAD_BUTTON_MAX_ENUM; input++) + for (int input = 0; input < JoystickBase::GAMEPAD_BUTTON_MAX_ENUM; input++) { - std::vector inputs = { Joystick::GamepadButton(input) }; + std::vector inputs = { JoystickBase::GamepadButton(input) }; if (joystick->isDown(inputs)) this->sendGamepadButtonEvent(SUBTYPE_GAMEPADDOWN, 0, input); @@ -75,11 +75,11 @@ namespace love this->sendGamepadButtonEvent(SUBTYPE_GAMEPADUP, 0, input); } - for (int input = 0; input < Joystick::GAMEPAD_AXIS_MAX_ENUM; input++) + for (int input = 0; input < JoystickBase::GAMEPAD_AXIS_MAX_ENUM; input++) { - if (joystick->isAxisChanged(Joystick::GamepadAxis(input))) + if (joystick->isAxisChanged(JoystickBase::GamepadAxis(input))) { - float value = joystick->getAxis(Joystick::GamepadAxis(input)); + float value = joystick->getAxis(JoystickBase::GamepadAxis(input)); this->sendGamepadAxisEvent(0, input, value); } } diff --git a/platform/cafe/source/driver/display/Framebuffer.cpp b/platform/cafe/source/driver/display/Framebuffer.cpp index bf7c0349..5e5a0369 100644 --- a/platform/cafe/source/driver/display/Framebuffer.cpp +++ b/platform/cafe/source/driver/display/Framebuffer.cpp @@ -1,3 +1,5 @@ +#include "common/Exception.hpp" + #include "driver/display/Framebuffer.hpp" #include "driver/display/utility.hpp" @@ -76,7 +78,7 @@ namespace love void Framebuffer::copyScanBuffer() { - GX2CopyColorBufferToScanBuffer(&this->target, (GX2ScanTarget)this->id); + GX2CopyColorBufferToScanBuffer(&this->target, this->id); } void Framebuffer::create(const ScreenInfo& info) diff --git a/platform/cafe/source/driver/display/GX2.cpp b/platform/cafe/source/driver/display/GX2.cpp index 7cb0fe71..bd3037a7 100644 --- a/platform/cafe/source/driver/display/GX2.cpp +++ b/platform/cafe/source/driver/display/GX2.cpp @@ -74,6 +74,8 @@ namespace love int GX2::onForegroundReleased() { + GX2DrawDone(); + auto foregroundHeap = MEMGetBaseHeapHandle(MEM_BASE_HEAP_FG); auto memOneHeap = MEMGetBaseHeapHandle(MEM_BASE_HEAP_MEM1); @@ -145,8 +147,6 @@ namespace love this->context.compareMode = GX2_COMPARE_FUNC_ALWAYS; this->uniform = (Uniform*)memalign(GX2_UNIFORM_BLOCK_ALIGNMENT, sizeof(Uniform)); - - love::currentScreen = (Screen)0; this->bindFramebuffer(&this->targets[0].get()); this->initialized = true; @@ -183,11 +183,21 @@ namespace love void GX2::ensureInFrame() { + GX2SetContextState(this->state); + if (!this->inFrame) - { - GX2SetContextState(this->state); this->inFrame = true; - } + } + + void GX2::copyCurrentScanBuffer() + { + Graphics::flushBatchedDrawsGlobal(); + Graphics::advanceStreamBuffersGlobal(); + + this->targets[love::currentScreen].copyScanBuffer(); + + GX2Flush(); + GX2WaitForFlip(); } void GX2::clear(const Color& color) @@ -197,12 +207,6 @@ namespace love GX2ClearColor(this->getFramebuffer(), color.r, color.g, color.b, color.a); GX2SetContextState(this->state); - - if (ShaderBase::current != nullptr) - { - auto* shader = (Shader*)ShaderBase::current; - shader->attach(); - } } void GX2::clearDepthStencil(int depth, uint8_t mask, double stencil) @@ -239,7 +243,8 @@ namespace love void GX2::setSamplerState(TextureBase* texture, const SamplerState& state) { - auto sampler = (GX2Sampler*)texture->getSamplerHandle(); + auto* sampler = (GX2Sampler*)texture->getSamplerHandle(); + GX2InitSampler(sampler, GX2_TEX_CLAMP_MODE_WRAP, GX2_TEX_XY_FILTER_MODE_LINEAR); GX2TexXYFilterMode minFilter; @@ -293,6 +298,9 @@ namespace love auto* sampler = (GX2Sampler*)texture->getSamplerHandle(); + if (sampler == nullptr) + return; + this->bindTextureToUnit(handle, sampler, unit); } @@ -307,25 +315,8 @@ namespace love void GX2::present() { - if (this->inFrame) - { - Graphics::flushBatchedDrawsGlobal(); - - GX2DrawDone(); - - Graphics::advanceStreamBuffersGlobal(); - this->inFrame = false; - } - - // if (Keyboard()->hasTextInput()) - // nn::swkbd::DrawDRC(); - - for (auto& target : this->targets) - target.copyScanBuffer(); - + this->inFrame = false; GX2SwapScanBuffers(); - GX2Flush(); - GX2WaitForFlip(); } void GX2::setViewport(const Rect& rect) diff --git a/platform/cafe/source/driver/display/Uniform.cpp b/platform/cafe/source/driver/display/Uniform.cpp index aef3733e..ed28100a 100644 --- a/platform/cafe/source/driver/display/Uniform.cpp +++ b/platform/cafe/source/driver/display/Uniform.cpp @@ -1,21 +1,22 @@ #include "driver/display/Uniform.hpp" -#include - namespace love { - glm::mat4 updateMatrix(const glm::mat4& matrix) + glm::mat4 createTransposedSwappedMatrix(const Matrix4& matrix) { - glm::mat4 out(1.0f); + const uint32_t count = sizeof(glm::mat4) / sizeof(uint32_t); - uint32_t* destination = (uint32_t*)glm::value_ptr(out); - const uint32_t* source = (const uint32_t*)glm::value_ptr(matrix); + // Transpose the input matrix to convert from row-major to column-major + glm::mat4 sourceMatrix = glm::transpose(glm::make_mat4(matrix.getElements())); - const size_t count = sizeof(glm::mat4) / sizeof(uint32_t); + // Create a new matrix to hold the endian-swapped version + glm::mat4 resultMatrix; + uint32_t* destination = (uint32_t*)glm::value_ptr(resultMatrix); + const uint32_t* source = (const uint32_t*)glm::value_ptr(sourceMatrix); - for (size_t i = 0; i < count; i++) + for (int i = 0; i < count; ++i) destination[i] = __builtin_bswap32(source[i]); - return out; + return resultMatrix; } } // namespace love diff --git a/platform/cafe/source/modules/graphics/Graphics.cpp b/platform/cafe/source/modules/graphics/Graphics.cpp index 91fe7262..ff60cdb0 100644 --- a/platform/cafe/source/modules/graphics/Graphics.cpp +++ b/platform/cafe/source/modules/graphics/Graphics.cpp @@ -8,6 +8,8 @@ #include "modules/graphics/Texture.hpp" #include +#include +#include #include namespace love @@ -167,6 +169,11 @@ namespace love gx2.bindFramebuffer(&gx2.getInternalBackbuffer()); } + void Graphics::copyCurrentScanBuffer() + { + gx2.copyCurrentScanBuffer(); + } + void Graphics::present(void* screenshotCallbackData) { if (!this->isActive()) @@ -179,6 +186,7 @@ namespace love this->drawCalls = 0; this->drawCallsBatched = 0; + Shader::shaderSwitches = 0; } void Graphics::setScissor(const Rect& scissor) @@ -329,7 +337,7 @@ namespace love this->restoreState(this->states.back()); - for (int index = 0; index < 1; index++) + for (int index = 0; index < ShaderBase::STANDARD_MAX_ENUM; index++) { auto type = (Shader::StandardShader)index; @@ -372,6 +380,7 @@ namespace love { gx2.prepareDraw(this); gx2.bindTextureToUnit(command.texture, 0); + // gx2.setCullMode(command.cullMode); const auto mode = GX2::getPrimitiveType(command.primitiveType); auto* buffer = (GX2RBuffer*)command.indexBuffer->getHandle(); diff --git a/platform/cafe/source/modules/graphics/Shader.cpp b/platform/cafe/source/modules/graphics/Shader.cpp index 101daf66..bcd6e2c0 100644 --- a/platform/cafe/source/modules/graphics/Shader.cpp +++ b/platform/cafe/source/modules/graphics/Shader.cpp @@ -1,5 +1,7 @@ #include "modules/graphics/Shader.hpp" +#include "common/screen.hpp" + #include #include #include @@ -14,7 +16,7 @@ namespace love { - Shader::Shader(StandardShader type) : uniform {} + Shader::Shader(StandardShader type) : ShaderBase(type), uniform {} { std::string error; @@ -73,6 +75,9 @@ namespace love uint32_t Shader::getPixelSamplerLocation(int index) { + if (this->shaderType != Shader::STANDARD_TEXTURE) + throw love::Exception("Invalid shader set!"); + size_t count = this->program.pixelShader->samplerVarCount; if (index > count) @@ -106,7 +111,8 @@ namespace love if (current != this) return; - auto transform = graphics->getTransform(); + auto& transform = graphics->getTransform(); + // uniform->update(transform); GX2Invalidate(INVALIDATE_UNIFORM_BLOCK, uniform, sizeof(Uniform)); GX2SetVertexUniformBlock(this->uniform.location, sizeof(Uniform), uniform); @@ -130,6 +136,7 @@ namespace love GX2SetPixelShader(this->program.pixelShader); current = this; + shaderSwitches++; } } diff --git a/platform/cafe/source/modules/graphics/Texture.cpp b/platform/cafe/source/modules/graphics/Texture.cpp index afd1fdda..640f7f78 100644 --- a/platform/cafe/source/modules/graphics/Texture.cpp +++ b/platform/cafe/source/modules/graphics/Texture.cpp @@ -2,6 +2,7 @@ #include "modules/graphics/Texture.hpp" +#include #include #include @@ -15,7 +16,7 @@ namespace love if (!texture) throw love::Exception("Failed to create GX2Texture."); - std::memset(texture, 0, sizeof(GX2Texture)); + std::memset(&texture->surface, 0, sizeof(GX2Surface)); texture->surface.use = GX2_SURFACE_USE_TEXTURE; texture->surface.dim = GX2_SURFACE_DIM_TEXTURE_2D; @@ -33,7 +34,7 @@ namespace love texture->surface.aa = GX2_AA_MODE1X; texture->surface.tileMode = GX2_TILE_MODE_LINEAR_ALIGNED; texture->viewFirstMip = 0; - texture->viewNumMips = 1; + texture->viewNumMips = 0; texture->viewFirstSlice = 0; texture->viewNumSlices = 1; texture->compMap = GX2_COMP_MAP(GX2_SQ_SEL_R, GX2_SQ_SEL_G, GX2_SQ_SEL_B, GX2_SQ_SEL_A); @@ -53,7 +54,7 @@ namespace love Texture::Texture(GraphicsBase* graphics, const Settings& settings, const Slices* data) : TextureBase(graphics, settings, data), slices(settings.type), - sampler(nullptr) + sampler {} { if (data != nullptr) slices = *data; @@ -93,7 +94,7 @@ namespace love const auto faces = (this->textureType == TEXTURE_CUBE) ? 6 : 1; int slices = this->getDepth(mip) * this->layers * faces; - memorySize += getPixelFormatSliceSize(this->format, width, height) * slices; + memorySize += getPixelFormatSliceSize(this->format, width, height, false) * slices; } this->setGraphicsMemorySize(memorySize); @@ -107,7 +108,7 @@ namespace love delete this->texture; if (this->target != nullptr) - delete this->texture; + delete this->target; this->setGraphicsMemorySize(0); } @@ -162,6 +163,11 @@ namespace love { } } + + this->setSamplerState(this->samplerState); + + if (this->slices.getMipmapCount() <= 1 && this->getMipmapsMode() != MIPMAPS_NONE) + this->generateMipmaps(); } void Texture::setSamplerState(const SamplerState& state) @@ -179,16 +185,18 @@ namespace love size_t pixelSize = getPixelFormatBlockSize(this->format); - for (uint32_t y = 0; y < rect.h; y++) + for (uint32_t y = 0; y < (uint32_t)rect.h; y++) { - const auto row = (y * rect.w * pixelSize); - const auto dest = (rect.x + (y + rect.y) * pitch) * pixelSize; + const auto srcRow = (y * rect.w * pixelSize); + const auto destRow = (rect.x + (y + rect.y) * pitch) * pixelSize; - std::memcpy(destination + dest, source + row, rect.w * pixelSize); + std::memcpy(destination + destRow, source + srcRow, rect.w * pixelSize); } const auto imageSize = this->texture->surface.imageSize; - GX2Invalidate(GX2_INVALIDATE_MODE_CPU_TEXTURE, destination, imageSize); + + GX2Invalidate(GX2_INVALIDATE_MODE_CPU_TEXTURE, this->texture->surface.image, imageSize); + GX2Flush(); } void Texture::generateMipmapsInternal() @@ -206,6 +214,6 @@ namespace love ptrdiff_t Texture::getSamplerHandle() const { - return (ptrdiff_t)(&this->sampler); + return (ptrdiff_t)std::addressof(this->sampler); } } // namespace love diff --git a/platform/cafe/source/modules/joystick/Joystick.cpp b/platform/cafe/source/modules/joystick/Joystick.cpp deleted file mode 100644 index 96d52901..00000000 --- a/platform/cafe/source/modules/joystick/Joystick.cpp +++ /dev/null @@ -1,421 +0,0 @@ -#include "modules/joystick/Joystick.hpp" - -namespace love -{ - Joystick::Joystick(int id) : JoystickBase(id) - {} - - Joystick::Joystick(int id, int index) : JoystickBase(id, index) - { - this->open(index); - } - - Joystick::~Joystick() - { - this->close(); - } - - void Joystick::update() - { - if (this->isDRCGamepad()) - { - VPADRead(VPAD_CHAN_0, &this->vpadStatus, 1, &this->vpadError); - - const auto& status = this->vpadStatus; - if (this->vpadError != VPAD_READ_NO_SAMPLES) - this->state = { status.trigger, status.release, status.hold }; - } - else - { - KPADReadEx(KPADChan(this->id - 1), &this->kpadStatus, 1, &this->kpadError); - - const auto& status = this->kpadStatus; - if (this->kpadError != KPAD_ERROR_NO_SAMPLES) - this->state = { status.trigger, status.release, status.hold }; - } - } - - static GamepadType getSystemGamepadType(int id) - { - if (id == 0) - return GAMEPAD_TYPE_NINTENDO_WII_U_GAMEPAD; - - KPADStatus status {}; - KPADError error = KPAD_ERROR_OK; - - KPADReadEx(KPADChan(id - 1), &status, 1, &error); - - GamepadType type = GAMEPAD_TYPE_UNKNOWN; - Joystick::getConstant((WPADExtensionType)status.extensionType, type); - - return type; - } - - bool Joystick::open(int64_t deviceId) - { - int index = (int)deviceId; - this->close(); - - this->instanceId = 0; - - this->gamepadType = getSystemGamepadType(this->id); - this->guid = getGamepadGUID(this->gamepadType); - - if (!Joystick::getConstant(this->gamepadType, this->name)) - this->name = "Unknown"; - - this->joystickType = JOYSTICK_TYPE_GAMEPAD; - this->update(); - - return this->isConnected(); - } - - void Joystick::close() - { - this->instanceId = -1; - } - - bool Joystick::isConnected() const - { - if (this->isDRCGamepad()) - { - switch (this->vpadError) - { - case VPAD_READ_INVALID_CONTROLLER: - case VPAD_READ_UNINITIALIZED: - return false; - default: - return true; - } - } - - switch (this->kpadError) - { - case KPAD_ERROR_INVALID_CONTROLLER: - case KPAD_ERROR_UNINITIALIZED: - return false; - default: - return true; - } - - return false; - } - - float Joystick::getVPADAxis(GamepadAxis axis) const - { - const auto& status = this->vpadStatus; - - switch (axis) - { - case GAMEPAD_AXIS_LEFTX: - return clamp(status.leftStick.x); - case GAMEPAD_AXIS_LEFTY: - return clamp(status.leftStick.y); - case GAMEPAD_AXIS_RIGHTX: - return clamp(status.rightStick.x); - case GAMEPAD_AXIS_RIGHTY: - return clamp(status.rightStick.y); - case GAMEPAD_AXIS_TRIGGERLEFT: - return status.hold & VPAD_BUTTON_ZL ? 1.0f : 0.0f; - case GAMEPAD_AXIS_TRIGGERRIGHT: - return status.hold & VPAD_BUTTON_ZR ? 1.0f : 0.0f; - default: - return 0.0f; - } - } - - float Joystick::getKPADAxis(GamepadAxis axis) const - { - const auto& status = this->kpadStatus; - - switch (this->gamepadType) - { - case GAMEPAD_TYPE_NINTENDO_WII_U_PRO: - { - switch (axis) - { - case GAMEPAD_AXIS_LEFTX: - return clamp(status.pro.leftStick.x); - case GAMEPAD_AXIS_LEFTY: - return clamp(status.pro.leftStick.y); - case GAMEPAD_AXIS_RIGHTX: - return clamp(status.pro.rightStick.x); - case GAMEPAD_AXIS_RIGHTY: - return clamp(status.pro.rightStick.y); - case GAMEPAD_AXIS_TRIGGERLEFT: - return status.hold & WPAD_PRO_TRIGGER_ZL ? 1.0f : 0.0f; - case GAMEPAD_AXIS_TRIGGERRIGHT: - return status.hold & WPAD_PRO_TRIGGER_ZR ? 1.0f : 0.0f; - default: - break; - } - break; - } - default: - return 0.0f; - } - - return 0.0f; - } - - float Joystick::getAxis(GamepadAxis axis) const - { - switch (this->gamepadType) - { - case GAMEPAD_TYPE_NINTENDO_WII_U_GAMEPAD: - return this->getVPADAxis(axis); - case GAMEPAD_TYPE_NINTENDO_WII_U_PRO: - return this->getKPADAxis(axis); - default: - return 0.0f; - } - } - - std::vector Joystick::getAxes() const - { - std::vector axes; - int count = this->getAxisCount(); - - if (!this->isConnected() || count <= 0) - return axes; - - axes.reserve(count); - - for (int i = 0; i < count; i++) - axes.push_back(this->getAxis((GamepadAxis)i)); - - return axes; - } - - bool Joystick::isVPADButtonDown(std::span buttons) const - { - VPADButtons result; - - for (const auto& button : buttons) - { - if (!Joystick::getConstant(button, result)) - continue; - - if (this->state.pressed & result) - { - this->state.pressed ^= result; - return true; - } - } - - return false; - } - - static bool isProControllerDown(const KPADStatus& status, std::span buttons) - { - WPADProButton result; - - for (const auto& button : buttons) - { - if (!Joystick::getConstant(button, result)) - continue; - - if (status.pro.trigger & result) - return true; - } - - return false; - } - - bool Joystick::isKPADButtonDown(std::span buttons) const - { - switch (this->gamepadType) - { - case GAMEPAD_TYPE_NINTENDO_WII_U_PRO: - return isProControllerDown(this->kpadStatus, buttons); - default: - break; - } - - return false; - } - - bool Joystick::isDown(std::span buttons) const - { - if (!this->isConnected()) - return false; - - if (this->isDRCGamepad()) - return this->isVPADButtonDown(buttons); - else - return this->isKPADButtonDown(buttons); - - return false; - } - - bool Joystick::isUp(std::span buttons) const - { - if (!this->isConnected()) - return false; - - VPADButtons result; - - for (GamepadButton button : buttons) - { - if (!Joystick::getConstant(button, result)) - continue; - - if (this->state.released & result) - { - this->state.released ^= result; - return true; - } - } - - return false; - } - - bool Joystick::isAxisChanged(GamepadAxis axis) const - { - if (!this->isConnected()) - return false; - - VPADAxis result; - - if (!Joystick::getConstant(axis, result)) - return false; - - if ((this->state.held & result) || (this->state.released & result)) - { - this->state.held ^= result; - return true; - } - - return false; - } - - void Joystick::setPlayerIndex(int) - {} - - int Joystick::getPlayerIndex() const - { - return this->id; - } - - Joystick::JoystickInput Joystick::getGamepadMapping(const GamepadInput& input) const - { - JoystickInput result {}; - - return result; - } - - std::string Joystick::getGamepadMappingString() const - { - return std::string(); - } - - bool Joystick::isVibrationSupported() const - { - return false; - } - - bool Joystick::setVibration(float, float, float) - { - return false; - } - - bool Joystick::setVibration() - { - return false; - } - - void Joystick::getVibration(float&, float&) const - {} - - bool Joystick::hasSensor(Sensor::SensorType type) const - { - switch (type) - { - case Sensor::SENSOR_ACCELEROMETER: - return getGamepadHasAccelerometer(this->gamepadType); - case Sensor::SENSOR_GYROSCOPE: - return getGamepadHasGyroscope(this->gamepadType); - default: - break; - } - - return false; - } - - bool Joystick::isSensorEnabled(Sensor::SensorType type) const - { - return this->sensors.at(type) == true; - } - - void Joystick::setSensorEnabled(Sensor::SensorType type, bool enable) - { - if (!this->hasSensor(type)) - { - std::string_view name = "Unknown"; - Sensor::getConstant(type, name); - - throw love::Exception("\"{}\" gamepad sensor is not supported", name); - } - - switch (type) - { - case Sensor::SENSOR_ACCELEROMETER: - case Sensor::SENSOR_GYROSCOPE: - this->sensors[type] = enable; - break; - default: - break; - } - } - - std::vector Joystick::getSensorData(Sensor::SensorType type) const - { - std::vector data {}; - - if (!this->hasSensor(type)) - { - std::string_view name = "Unknown"; - Sensor::getConstant(type, name); - - throw love::Exception("\"{}\" gamepad sensor is not enabled.", name); - } - - if (!this->isSensorEnabled(type)) - { - std::string_view name = "Unknown"; - Sensor::getConstant(type, name); - - throw love::Exception("\"{}\" gamepad sensor is not enabled.", name); - } - - data.reserve(3); - - switch (type) - { - case Sensor::SENSOR_ACCELEROMETER: - { - const auto& accelerometer = this->vpadStatus.accelorometer; - - data.push_back(accelerometer.acc.x); - data.push_back(accelerometer.acc.y); - data.push_back(accelerometer.acc.z); - - return data; - } - case Sensor::SENSOR_GYROSCOPE: - { - const auto& gyroscope = this->vpadStatus.gyro; - - data.push_back(gyroscope.x); - data.push_back(gyroscope.y); - data.push_back(gyroscope.z); - - return data; - } - default: - break; - } - - return data; - } -} // namespace love diff --git a/platform/cafe/source/modules/joystick/JoystickModule.cpp b/platform/cafe/source/modules/joystick/JoystickModule.cpp index 3391a1e8..6cc8b846 100644 --- a/platform/cafe/source/modules/joystick/JoystickModule.cpp +++ b/platform/cafe/source/modules/joystick/JoystickModule.cpp @@ -3,6 +3,9 @@ #include #include +#include "modules/joystick/kpad/Joystick.hpp" +#include "modules/joystick/vpad/Joystick.hpp" + namespace love::joystick { int getJoystickCount() @@ -37,6 +40,9 @@ namespace love::joystick */ JoystickBase* openJoystick(int index) { - return nullptr; + if (index == 0) + return new vpad::Joystick(index); + + return new kpad::Joystick(index); } } // namespace love::joystick diff --git a/platform/cafe/source/modules/joystick/kpad/Joystick.cpp b/platform/cafe/source/modules/joystick/kpad/Joystick.cpp new file mode 100644 index 00000000..84d53d20 --- /dev/null +++ b/platform/cafe/source/modules/joystick/kpad/Joystick.cpp @@ -0,0 +1,404 @@ +#include "modules/joystick/kpad/Joystick.hpp" + +namespace love +{ + namespace kpad + { + Joystick::Joystick(int id) : JoystickBase(id) + {} + + Joystick::Joystick(int id, int index) : JoystickBase(id, index) + { + this->open(index); + } + + Joystick::~Joystick() + { + this->close(); + } + + void Joystick::update() + { + KPADReadEx(WPAD_CHAN_0, &this->status, 1, &this->error); + + if (this->error != KPAD_ERROR_NO_SAMPLES) + { + switch (this->getGamepadType()) + { + case GAMEPAD_TYPE_NINTENDO_WII_REMOTE: + { + this->state = { this->status.trigger, this->status.release, this->status.hold }; + break; + } + case GAMEPAD_TYPE_NINTENDO_WII_CLASSIC: + { + this->state = { this->status.classic.trigger, this->status.classic.release, + this->status.classic.hold }; + break; + } + case GAMEPAD_TYPE_NINTENDO_WII_U_PRO: + { + this->state = { this->status.pro.trigger, this->status.pro.release, + this->status.pro.hold }; + break; + } + default: + break; + } + } + } + + bool Joystick::open(int64_t deviceId) + { + if (deviceId > WPAD_CHAN_4) + return false; + + int index = (int)deviceId; + this->close(); + + this->instanceId = 0; + + WPADExtensionType extension; + if (WPADProbe(WPADChan(index - 1), &extension) < 0) + return false; + + switch (extension) + { + default: + case WPAD_EXT_CORE: + { + this->gamepadType = GAMEPAD_TYPE_NINTENDO_WII_REMOTE; + break; + } + case WPAD_EXT_CLASSIC: + { + this->gamepadType = GAMEPAD_TYPE_NINTENDO_WII_CLASSIC; + break; + } + case WPAD_EXT_NUNCHUK: + { + this->gamepadType = GAMEPAD_TYPE_NINTENDO_WII_REMOTE_NUNCHUCK; + break; + } + case WPAD_EXT_PRO_CONTROLLER: + { + this->gamepadType = GAMEPAD_TYPE_NINTENDO_WII_U_PRO; + break; + } + } + + this->guid = love::getGamepadGUID(this->gamepadType); + if (!Joystick::getConstant(this->gamepadType, this->name)) + this->name = "Unknown"; + + this->joystickType = JOYSTICK_TYPE_GAMEPAD; + this->update(); + + return this->isConnected(); + } + + void Joystick::close() + { + this->instanceId = -1; + } + + bool Joystick::isConnected() const + { + switch (this->error) + { + case KPAD_ERROR_INVALID_CONTROLLER: + case KPAD_ERROR_UNINITIALIZED: + return false; + default: + return true; + } + + return false; + } + + float Joystick::getAxis(GamepadAxis axis) const + { + switch (this->gamepadType) + { + case GAMEPAD_TYPE_NINTENDO_WII_REMOTE: + return 0.0f; + case GAMEPAD_TYPE_NINTENDO_WII_CLASSIC: + { + if (axis == GAMEPAD_AXIS_LEFTX) + return clamp(this->status.classic.leftStick.x); + else if (axis == GAMEPAD_AXIS_LEFTY) + return clamp(this->status.classic.leftStick.y); + else if (axis == GAMEPAD_AXIS_RIGHTX) + return clamp(this->status.classic.rightStick.x); + else if (axis == GAMEPAD_AXIS_RIGHTY) + return clamp(this->status.classic.rightStick.y); + else if (axis == GAMEPAD_AXIS_TRIGGERLEFT) + return this->status.classic.hold & WPAD_CLASSIC_BUTTON_ZL ? 1.0f : 0.0f; + + return this->status.classic.hold & WPAD_CLASSIC_BUTTON_ZR ? 1.0f : 0.0f; + } + case GAMEPAD_TYPE_NINTENDO_WII_REMOTE_NUNCHUCK: + { + if (axis == GAMEPAD_AXIS_TRIGGERLEFT) + return this->status.nunchuk.hold & WPAD_NUNCHUK_BUTTON_Z ? 1.0f : 0.0f; + + break; + } + case GAMEPAD_TYPE_NINTENDO_WII_U_PRO: + { + if (axis == GAMEPAD_AXIS_LEFTX) + return clamp(this->status.pro.leftStick.x); + else if (axis == GAMEPAD_AXIS_LEFTY) + return clamp(this->status.pro.leftStick.y); + else if (axis == GAMEPAD_AXIS_RIGHTX) + return clamp(this->status.pro.rightStick.x); + else if (axis == GAMEPAD_AXIS_RIGHTY) + return clamp(this->status.pro.rightStick.y); + else if (axis == GAMEPAD_AXIS_TRIGGERLEFT) + return this->status.pro.hold & WPAD_PRO_TRIGGER_ZL ? 1.0f : 0.0f; + + return this->status.pro.hold & WPAD_PRO_TRIGGER_ZR ? 1.0f : 0.0f; + } + default: + return 0.0f; + } + + return 0.0f; + } + + std::vector Joystick::getAxes() const + { + std::vector axes; + int count = this->getAxisCount(); + + if (!this->isConnected() || count <= 0) + return axes; + + axes.reserve(count); + + for (int i = 0; i < count; i++) + axes.push_back(this->getAxis((GamepadAxis)i)); + + return axes; + } + + template + bool Joystick::isButtonDown(std::span buttons) const + { + T result; + + for (const auto& button : buttons) + { + if (!Joystick::getConstant(button, result)) + continue; + + if (this->state.pressed & result) + { + this->state.pressed ^= result; + return true; + } + } + + return false; + } + + template + bool Joystick::isButtonUp(std::span buttons) const + { + T result; + + for (const auto& button : buttons) + { + if (!Joystick::getConstant(button, result)) + continue; + + if (this->state.released & result) + { + this->state.released ^= result; + return true; + } + } + + return false; + } + + bool Joystick::isDown(std::span buttons) const + { + if (!this->isConnected()) + return false; + + switch (this->gamepadType) + { + case GAMEPAD_TYPE_NINTENDO_WII_REMOTE: + return isButtonDown(buttons); + case GAMEPAD_TYPE_NINTENDO_WII_REMOTE_NUNCHUCK: + break; + case GAMEPAD_TYPE_NINTENDO_WII_CLASSIC: + return isButtonDown(buttons); + case GAMEPAD_TYPE_NINTENDO_WII_U_PRO: + return isButtonDown(buttons); + default: + break; + } + + return false; + } + + bool Joystick::isUp(std::span buttons) const + { + if (!this->isConnected()) + return false; + + switch (this->gamepadType) + { + case GAMEPAD_TYPE_NINTENDO_WII_REMOTE: + return isButtonUp(buttons); + case GAMEPAD_TYPE_NINTENDO_WII_REMOTE_NUNCHUCK: + break; + case GAMEPAD_TYPE_NINTENDO_WII_CLASSIC: + return isButtonUp(buttons); + case GAMEPAD_TYPE_NINTENDO_WII_U_PRO: + return isButtonUp(buttons); + default: + break; + } + + return false; + } + + template + bool Joystick::isAxisValueChanged(GamepadAxis axis) const + { + T result; + + if (!Joystick::getConstant(axis, result)) + return false; + + if ((this->state.held & result) || (this->state.released & result)) + { + this->state.held ^= result; + return true; + } + + return false; + } + + bool Joystick::isAxisChanged(GamepadAxis axis) const + { + if (!this->isConnected()) + return false; + + switch (this->gamepadType) + { + case GAMEPAD_TYPE_NINTENDO_WII_REMOTE: + break; + case GAMEPAD_TYPE_NINTENDO_WII_REMOTE_NUNCHUCK: + return isAxisValueChanged(axis); + case GAMEPAD_TYPE_NINTENDO_WII_CLASSIC: + return isAxisValueChanged(axis); + case GAMEPAD_TYPE_NINTENDO_WII_U_PRO: + return isAxisValueChanged(axis); + default: + break; + } + + return false; + } + + void Joystick::setPlayerIndex(int) + {} + + int Joystick::getPlayerIndex() const + { + return this->id; + } + + Joystick::JoystickInput Joystick::getGamepadMapping(const GamepadInput& input) const + { + JoystickInput result {}; + + return result; + } + + std::string Joystick::getGamepadMappingString() const + { + return std::string(); + } + + bool Joystick::isVibrationSupported() const + { + return false; + } + + bool Joystick::setVibration(float, float, float) + { + return false; + } + + bool Joystick::setVibration() + { + return false; + } + + void Joystick::getVibration(float&, float&) const + {} + + bool Joystick::hasSensor(Sensor::SensorType type) const + { + switch (type) + { + case Sensor::SENSOR_ACCELEROMETER: + return getGamepadHasAccelerometer(this->gamepadType); + case Sensor::SENSOR_GYROSCOPE: + return getGamepadHasGyroscope(this->gamepadType); + default: + break; + } + + return false; + } + + bool Joystick::isSensorEnabled(Sensor::SensorType type) const + { + return this->sensors.at(type) == true; + } + + void Joystick::setSensorEnabled(Sensor::SensorType type, bool enable) + { + if (!this->hasSensor(type)) + { + std::string_view name = "Unknown"; + Sensor::getConstant(type, name); + + throw love::Exception("\"{}\" gamepad sensor is not supported", name); + } + + switch (type) + { + case Sensor::SENSOR_ACCELEROMETER: + case Sensor::SENSOR_GYROSCOPE: + this->sensors[type] = enable; + break; + default: + break; + } + } + + std::vector Joystick::getSensorData(Sensor::SensorType type) const + { + std::vector data {}; + + if (!this->hasSensor(type)) + { + std::string_view name = "Unknown"; + Sensor::getConstant(type, name); + + throw love::Exception("\"{}\" gamepad sensor is not enabled.", name); + } + + data.reserve(3); + + return data; + } + } // namespace kpad +} // namespace love diff --git a/platform/cafe/source/modules/joystick/vpad/Joystick.cpp b/platform/cafe/source/modules/joystick/vpad/Joystick.cpp new file mode 100644 index 00000000..6072a06e --- /dev/null +++ b/platform/cafe/source/modules/joystick/vpad/Joystick.cpp @@ -0,0 +1,290 @@ +#include "modules/joystick/vpad/Joystick.hpp" + +namespace love +{ + namespace vpad + { + Joystick::Joystick(int id) : JoystickBase(id) + {} + + Joystick::Joystick(int id, int index) : JoystickBase(id, index) + { + this->open(index); + } + + Joystick::~Joystick() + { + this->close(); + } + + void Joystick::update() + { + VPADRead(VPAD_CHAN_0, &this->vpadStatus, 1, &this->vpadError); + + const auto& status = this->vpadStatus; + if (this->vpadError != VPAD_READ_NO_SAMPLES) + this->state = { status.trigger, status.release, status.hold }; + } + + bool Joystick::open(int64_t deviceId) + { + int index = (int)deviceId; + this->close(); + + this->instanceId = 0; + + this->gamepadType = GAMEPAD_TYPE_NINTENDO_WII_U_GAMEPAD; + this->guid = love::getGamepadGUID(this->gamepadType); + + if (!Joystick::getConstant(this->gamepadType, this->name)) + this->name = "Unknown"; + + this->joystickType = JOYSTICK_TYPE_GAMEPAD; + this->update(); + + return this->isConnected(); + } + + void Joystick::close() + { + this->instanceId = -1; + } + + bool Joystick::isConnected() const + { + switch (this->vpadError) + { + case VPAD_READ_INVALID_CONTROLLER: + case VPAD_READ_UNINITIALIZED: + return false; + default: + return true; + } + + return false; + } + + float Joystick::getAxis(GamepadAxis axis) const + { + const auto status = this->vpadStatus; + + switch (axis) + { + case GAMEPAD_AXIS_LEFTX: + return clamp(status.leftStick.x); + case GAMEPAD_AXIS_LEFTY: + return clamp(status.leftStick.y); + case GAMEPAD_AXIS_RIGHTX: + return clamp(status.rightStick.x); + case GAMEPAD_AXIS_RIGHTY: + return clamp(status.rightStick.y); + case GAMEPAD_AXIS_TRIGGERLEFT: + return status.hold & VPAD_BUTTON_ZL ? 1.0f : 0.0f; + case GAMEPAD_AXIS_TRIGGERRIGHT: + return status.hold & VPAD_BUTTON_ZR ? 1.0f : 0.0f; + default: + return 0.0f; + } + + return 0.0f; + } + + std::vector Joystick::getAxes() const + { + std::vector axes; + int count = this->getAxisCount(); + + if (!this->isConnected() || count <= 0) + return axes; + + axes.reserve(count); + + for (int i = 0; i < count; i++) + axes.push_back(this->getAxis((GamepadAxis)i)); + + return axes; + } + + bool Joystick::isDown(std::span buttons) const + { + VPADButtons result; + + for (const auto& button : buttons) + { + if (!Joystick::getConstant(button, result)) + continue; + + if (this->state.pressed & result) + { + this->state.pressed ^= result; + return true; + } + } + + return false; + } + + bool Joystick::isUp(std::span buttons) const + { + if (!this->isConnected()) + return false; + + VPADButtons result; + + for (GamepadButton button : buttons) + { + if (!Joystick::getConstant(button, result)) + continue; + + if (this->state.released & result) + { + this->state.released ^= result; + return true; + } + } + + return false; + } + + bool Joystick::isAxisChanged(GamepadAxis axis) const + { + if (!this->isConnected()) + return false; + + VPADAxis result; + + if (!Joystick::getConstant(axis, result)) + return false; + + if ((this->state.held & result) || (this->state.released & result)) + { + this->state.held ^= result; + return true; + } + + return false; + } + + void Joystick::setPlayerIndex(int) + {} + + int Joystick::getPlayerIndex() const + { + return this->id; + } + + Joystick::JoystickInput Joystick::getGamepadMapping(const GamepadInput& input) const + { + JoystickInput result {}; + + return result; + } + + std::string Joystick::getGamepadMappingString() const + { + return std::string(); + } + + bool Joystick::isVibrationSupported() const + { + return false; + } + + bool Joystick::setVibration(float, float, float) + { + return false; + } + + bool Joystick::setVibration() + { + return false; + } + + void Joystick::getVibration(float&, float&) const + {} + + bool Joystick::hasSensor(Sensor::SensorType type) const + { + switch (type) + { + case Sensor::SENSOR_ACCELEROMETER: + return getGamepadHasAccelerometer(this->gamepadType); + case Sensor::SENSOR_GYROSCOPE: + return getGamepadHasGyroscope(this->gamepadType); + default: + break; + } + + return false; + } + + bool Joystick::isSensorEnabled(Sensor::SensorType type) const + { + return this->sensors.at(type) == true; + } + + void Joystick::setSensorEnabled(Sensor::SensorType type, bool enable) + { + if (!this->hasSensor(type)) + { + std::string_view name = "Unknown"; + Sensor::getConstant(type, name); + + throw love::Exception("\"{}\" gamepad sensor is not supported", name); + } + + switch (type) + { + case Sensor::SENSOR_ACCELEROMETER: + case Sensor::SENSOR_GYROSCOPE: + this->sensors[type] = enable; + break; + default: + break; + } + } + + std::vector Joystick::getSensorData(Sensor::SensorType type) const + { + std::vector data {}; + + if (!this->hasSensor(type)) + { + std::string_view name = "Unknown"; + Sensor::getConstant(type, name); + + throw love::Exception("\"{}\" gamepad sensor is not enabled.", name); + } + + data.reserve(3); + + switch (type) + { + case Sensor::SENSOR_ACCELEROMETER: + { + const auto& accelerometer = this->vpadStatus.accelorometer; + + data.push_back(accelerometer.acc.x); + data.push_back(accelerometer.acc.y); + data.push_back(accelerometer.acc.z); + + return data; + } + case Sensor::SENSOR_GYROSCOPE: + { + const auto& gyroscope = this->vpadStatus.gyro; + + data.push_back(gyroscope.x); + data.push_back(gyroscope.y); + data.push_back(gyroscope.z); + + return data; + } + default: + break; + } + + return data; + } + } // namespace vpad +} // namespace love diff --git a/platform/ctr/include/driver/display/citro3d.hpp b/platform/ctr/include/driver/display/citro3d.hpp index 603095f8..461f21bb 100644 --- a/platform/ctr/include/driver/display/citro3d.hpp +++ b/platform/ctr/include/driver/display/citro3d.hpp @@ -93,6 +93,9 @@ namespace love void ensureInFrame(); + void copyCurrentScanBuffer() + {} + static GPU_TEXTURE_MODE_PARAM getTextureType(TextureType type); static GPU_Primitive_t getPrimitiveType(PrimitiveType type); diff --git a/platform/ctr/source/modules/graphics/Shader.cpp b/platform/ctr/source/modules/graphics/Shader.cpp index 5a008909..40d39002 100644 --- a/platform/ctr/source/modules/graphics/Shader.cpp +++ b/platform/ctr/source/modules/graphics/Shader.cpp @@ -7,7 +7,7 @@ namespace love { - Shader::Shader() : uniforms {} + Shader::Shader() : ShaderBase(STANDARD_DEFAULT), uniforms {} { this->loadVolatile(); } diff --git a/source/modules/audio/Source.cpp b/source/modules/audio/Source.cpp index 439da4e7..5445181f 100644 --- a/source/modules/audio/Source.cpp +++ b/source/modules/audio/Source.cpp @@ -98,6 +98,7 @@ namespace love } Source::Source(const Source& other) : + Object(other), sourceType(other.sourceType), pool(other.pool), valid(false), diff --git a/source/modules/event/Event.cpp b/source/modules/event/Event.cpp index c48b19f8..2e5bffad 100644 --- a/source/modules/event/Event.cpp +++ b/source/modules/event/Event.cpp @@ -175,7 +175,7 @@ namespace love } case SUBTYPE_GAMEPADAXIS: { - if (!Joystick::getConstant((Joystick::GamepadAxis)event.gamepadAxis.axis, name)) + if (!JoystickBase::getConstant((JoystickBase::GamepadAxis)event.gamepadAxis.axis, name)) break; joystick = module->getJoystickFromID(event.gamepadAxis.which); @@ -194,7 +194,7 @@ namespace love case SUBTYPE_GAMEPADUP: { // clang-format off - if (!Joystick::getConstant((Joystick::GamepadButton)event.gamepadButton.button, name)) + if (!JoystickBase::getConstant((JoystickBase::GamepadButton)event.gamepadButton.button, name)) break; // clang-format on diff --git a/source/modules/graphics/FontBase.cpp b/source/modules/graphics/FontBase.cpp index e5a79ec9..9447d605 100644 --- a/source/modules/graphics/FontBase.cpp +++ b/source/modules/graphics/FontBase.cpp @@ -160,6 +160,19 @@ namespace love "Cannot upload font glyphs to texture atlas: unexpected format conversion."); const uint8_t* source = (const uint8_t*)gd->getData(); + size_t destSize = getPixelFormatSliceSize(this->pixelFormat, width, height); + std::vector destination(destSize, 0); + uint8_t* destData = destination.data(); + + for (int pixel = 0; pixel < width * height; pixel++) + { + destData[pixel * 4 + 0] = source[pixel * 2 + 0]; + destData[pixel * 4 + 1] = source[pixel * 2 + 0]; + destData[pixel * 4 + 2] = source[pixel * 2 + 0]; + destData[pixel * 4 + 3] = source[pixel * 2 + 1]; + } + + texture->replacePixels(destData, destSize, 0, 0, rect, false); } else texture->replacePixels(gd->getData(), gd->getSize(), 0, 0, rect, false); @@ -184,7 +197,7 @@ namespace love { glyph.vertices[i] = vertices[i]; glyph.vertices[i].x += gd->getBearingX(); - glyph.vertices[i].y += gd->getBearingY(); + glyph.vertices[i].y -= gd->getBearingY(); } this->textureX += width + TEXTURE_PADDING; @@ -440,6 +453,9 @@ namespace love return drawcommands; } + static constexpr auto shaderType = + (Console::is(Console::CTR)) ? ShaderBase::STANDARD_DEFAULT : ShaderBase::STANDARD_TEXTURE; + void FontBase::printv(GraphicsBase* graphics, const Matrix4& matrix, const std::vector& drawcommands, const std::vector& vertices) @@ -457,6 +473,7 @@ namespace love command.vertexCount = cmd.vertexCount; command.texture = cmd.texture; command.isFont = true; + command.shaderType = shaderType; auto data = graphics->requestBatchedDraw(command); GlyphVertex* vertexdata = (GlyphVertex*)data.stream; diff --git a/source/modules/graphics/Graphics.cpp b/source/modules/graphics/Graphics.cpp index 74e2c651..33a015d0 100644 --- a/source/modules/graphics/Graphics.cpp +++ b/source/modules/graphics/Graphics.cpp @@ -346,7 +346,7 @@ namespace love state.pushTransform = command.pushTransform; } - if (state.vertexCount == 0) + if (state.lastVertexCount == 0) { if (ShaderBase::isDefaultActive()) ShaderBase::attachDefault(state.shaderType); @@ -455,7 +455,7 @@ namespace love if ((state.lastIndexCount == 0 && state.lastVertexCount == 0) || state.flushing) return; - if ((state.vertexCount == 0 && state.indexCount == 0) || state.flushing) + if ((state.indexCount == 0 && state.vertexCount == 0) || state.flushing) return; VertexAttributes attributes {}; @@ -478,7 +478,7 @@ namespace love if (attributes.enableBits == 0) return; - // state.flushing = true; + state.flushing = true; // auto originalColor = this->getColor(); // if (attributes.isEnabled(ATTRIB_COLOR)) @@ -498,6 +498,7 @@ namespace love command.indexBufferOffset = state.indexBuffer->unmap(usedSizes[1]); command.texture = state.texture; command.isFont = state.isFont; + this->draw(command); state.indexBufferMap = MapInfo(); @@ -527,6 +528,7 @@ namespace love state.lastVertexCount = 0; state.lastIndexCount = 0; + state.flushing = false; } void GraphicsBase::flushBatchedDrawsGlobal() diff --git a/source/modules/graphics/Shader.cpp b/source/modules/graphics/Shader.cpp index 0638b69b..71a96efb 100644 --- a/source/modules/graphics/Shader.cpp +++ b/source/modules/graphics/Shader.cpp @@ -1,4 +1,4 @@ -#include "common/Console.hpp" +#include "common/Exception.hpp" #include "modules/graphics/Shader.tcc" @@ -9,6 +9,9 @@ namespace love int ShaderBase::shaderSwitches = 0; + ShaderBase::ShaderBase(StandardShader type) : shaderType(type) + {} + ShaderBase::~ShaderBase() { for (int index = 0; index < STANDARD_MAX_ENUM; index++) @@ -31,12 +34,7 @@ namespace love return; } - if constexpr (!Console::is(Console::CAFE)) - { - if (current != defaultShader) - defaultShader->attach(); - } - else + if (current != defaultShader) defaultShader->attach(); } diff --git a/source/modules/graphics/TextBatch.cpp b/source/modules/graphics/TextBatch.cpp index 26631abe..6d3cd623 100644 --- a/source/modules/graphics/TextBatch.cpp +++ b/source/modules/graphics/TextBatch.cpp @@ -1,5 +1,7 @@ -#include "modules/graphics/TextBatch.hpp" +#include "common/Console.hpp" + #include "modules/graphics/Graphics.tcc" +#include "modules/graphics/TextBatch.hpp" #include @@ -192,6 +194,9 @@ namespace love return this->textData[index].textInfo.height; } + static constexpr auto shaderType = + Console::is(Console::CTR) ? ShaderBase::STANDARD_DEFAULT : ShaderBase::STANDARD_TEXTURE; + void TextBatch::draw(GraphicsBase* graphics, const Matrix4& matrix) { if (this->buffer.empty() || this->drawCommands.empty()) @@ -225,6 +230,7 @@ namespace love command.indexMode = TRIANGLEINDEX_QUADS; command.vertexCount = cmd.vertexCount; command.texture = cmd.texture; + command.shaderType = shaderType; command.isFont = true; command.pushTransform = false; diff --git a/source/modules/graphics/Texture.cpp b/source/modules/graphics/Texture.cpp index 79f13c92..3e1427c6 100644 --- a/source/modules/graphics/Texture.cpp +++ b/source/modules/graphics/Texture.cpp @@ -367,6 +367,9 @@ namespace love this->draw(graphics, this->quad, matrix); } + static constexpr ShaderBase::StandardShader shader = + (Console::is(Console::CTR) ? ShaderBase::STANDARD_DEFAULT : ShaderBase::STANDARD_TEXTURE); + void TextureBase::draw(GraphicsBase* graphics, Quad* quad, const Matrix4& matrix) { if (!this->readable) @@ -383,6 +386,7 @@ namespace love command.indexMode = TRIANGLEINDEX_QUADS; command.vertexCount = 4; command.texture = this; + command.shaderType = shader; BatchedVertexData data = graphics->requestBatchedDraw(command); @@ -407,11 +411,13 @@ namespace love } } + static constexpr bool pow2 = (Console::is(Console::CTR) ? true : false); + void TextureBase::uploadImageData(ImageDataBase* data, int level, int slice, int x, int y) { Rect rectangle = { x, y, data->getWidth(), data->getHeight() }; - const auto size = getPixelFormatSliceSize(this->format, data->getWidth(), data->getHeight()); + const auto size = getPixelFormatSliceSize(this->format, data->getWidth(), data->getHeight(), pow2); this->uploadByteData(data->getData(), size, level, slice, rectangle); } diff --git a/source/modules/graphics/Font.cpp b/source/modules/graphics/freetype/Font.cpp similarity index 51% rename from source/modules/graphics/Font.cpp rename to source/modules/graphics/freetype/Font.cpp index bce6d39c..4f9cac66 100644 --- a/source/modules/graphics/Font.cpp +++ b/source/modules/graphics/freetype/Font.cpp @@ -1,5 +1,5 @@ #include "modules/graphics/Font.hpp" -#include "modules/graphics/Graphics.hpp" +#include "modules/graphics/Graphics.tcc" namespace love { @@ -8,18 +8,29 @@ namespace love this->loadVolatile(); } + bool Font::loadVolatile() + { + textureCacheID++; + glyphs.clear(); + textures.clear(); + createTexture(); + return true; + } + void Font::createTexture() { - auto* graphics = Module::getInstance(Module::M_GRAPHICS); - graphics->flushBatchedDraws(); + auto* module = Module::getInstance(Module::M_GRAPHICS); + module->flushBatchedDraws(); TextureBase* texture = nullptr; TextureSize size = { this->textureWidth, this->textureHeight }; TextureSize nextSize = this->getNextTextureSize(); - bool recreateTexture = false; - if ((nextSize.width > size.width || nextSize.height > size.height) && !this->textures.empty()) + const bool biggerWidth = nextSize.width > size.width; + const bool biggerHeight = nextSize.height > size.height; + + if ((biggerWidth || biggerHeight) && !this->textures.empty()) { recreateTexture = true; size = nextSize; @@ -27,45 +38,44 @@ namespace love } TextureBase::Settings settings {}; - settings.format = pixelFormat; + settings.format = this->pixelFormat; settings.width = size.width; settings.height = size.height; - texture = graphics->newTexture(settings, nullptr); - texture->setSamplerState(samplerState); + texture = module->newTexture(settings, nullptr); + texture->setSamplerState(this->samplerState); { - auto dataSize = getPixelFormatSliceSize(pixelFormat, size.width, size.height); - auto pixelCount = size.width * size.height; + size_t dataSize = getPixelFormatSliceSize(this->pixelFormat, size.width, size.height); + size_t pixelCount = size.width * size.height; std::vector empty(dataSize, 0); - - if (this->shaper->getRasterizers()[0]->getDataType() == Rasterizer::DATA_TRUETYPE) + if (shaper->getRasterizers()[0]->getDataType() == Rasterizer::DATA_TRUETYPE) { if (this->pixelFormat == PIXELFORMAT_LA8_UNORM) { - for (size_t i = 0; i < pixelCount; i++) - empty[i * 2 + 0] = 255; + for (size_t index = 0; index < pixelCount; index++) + empty[index * 2 + 0] = 255; } else if (this->pixelFormat == PIXELFORMAT_RGBA8_UNORM) { - for (size_t i = 0; i < pixelCount; i++) + for (size_t index = 0; index < pixelCount; index++) { - empty[i * 4 + 0] = 255; - empty[i * 4 + 1] = 255; - empty[i * 4 + 2] = 255; + empty[index * 4 + 0] = 255; + empty[index * 4 + 1] = 255; + empty[index * 4 + 2] = 255; } } } - Rect rect = { 0, 0, size.width, size.height }; - texture->replacePixels(empty.data(), empty.size(), 0, 0, rect, false); + Rect rectangle = { 0, 0, size.width, size.height }; + texture->replacePixels(empty.data(), empty.size(), 0, 0, rectangle, false); } - textures.emplace_back(texture); + this->textures.emplace_back(texture, Acquire::NO_RETAIN); + this->textureWidth = size.width; this->textureHeight = size.height; - this->rowHeight = this->textureX = this->textureY = TEXTURE_PADDING; if (recreateTexture) @@ -73,28 +83,13 @@ namespace love this->textureCacheID++; std::vector glyphsToAdd; - for (const auto& glyph : this->glyphs) - glyphsToAdd.push_back(unpackGlyphIndex(glyph.first)); + for (const auto& glyphPair : this->glyphs) + glyphsToAdd.push_back(unpackGlyphIndex(glyphPair.first)); this->glyphs.clear(); - for (const auto& glyphIndex : glyphsToAdd) + for (auto glyphIndex : glyphsToAdd) this->addGlyph(glyphIndex); } } - - bool Font::loadVolatile() - { - this->textureCacheID++; - this->glyphs.clear(); - this->textures.clear(); - this->createTexture(); - - return true; - } - - const FontBase::Glyph& Font::addGlyph(TextShaper::GlyphIndex glyphIndex) - { - return FontBase::addGlyph(glyphIndex); - } } // namespace love diff --git a/source/modules/graphics/wrap_Graphics.cpp b/source/modules/graphics/wrap_Graphics.cpp index 33122efb..cd2d16a2 100644 --- a/source/modules/graphics/wrap_Graphics.cpp +++ b/source/modules/graphics/wrap_Graphics.cpp @@ -1667,17 +1667,35 @@ int Wrap_Graphics::getScreens(lua_State* L) return 1; } +int Wrap_Graphics::getActiveScreen(lua_State* L) +{ + auto& info = love::getScreenInfo(love::currentScreen); + luax_pushstring(L, info.name); + + return 1; +} + int Wrap_Graphics::setActiveScreen(lua_State* L) { std::string name = luax_checkstring(L, 1); - Screen screen = love::getScreenId(name); + auto value = love::getScreenId(name); - love::currentScreen = screen; + if (value == INVALID_SCREEN) + return luaL_error(L, "Invalid screen '%s'", name.c_str()); + + love::currentScreen = value; instance()->setActiveScreen(); return 0; } +#if !defined(__WIIU__) +int Wrap_Graphics::copyCurrentScanBuffer(lua_State* L) +{ + return 0; +} +#endif + // clang-format off #if defined(__3DS__) int Wrap_Graphics::is3D(lua_State* L) @@ -1725,7 +1743,16 @@ static constexpr std::array platformFunctions = { "setWide", Wrap_Graphics::setWide }, { "getDepth", Wrap_Graphics::getDepth } }}; -#else +#elif defined(__WIIU__) +int Wrap_Graphics::copyCurrentScanBuffer(lua_State* L) +{ + instance()->copyCurrentScanBuffer(); + + return 0; +} +#endif + +#if !defined(__3DS__) static constexpr std::span platformFunctions = {}; #endif @@ -1808,8 +1835,10 @@ static constexpr luaL_Reg functions[] = { "print", Wrap_Graphics::print }, { "printf", Wrap_Graphics::printf }, - { "setActiveScreen", Wrap_Graphics::setActiveScreen }, - { "getScreens", Wrap_Graphics::getScreens } + { "getScreens", Wrap_Graphics::getScreens }, + { "getActiveScreen", Wrap_Graphics::getActiveScreen }, + { "setActiveScreen", Wrap_Graphics::setActiveScreen }, + { "copyCurrentScanBuffer", Wrap_Graphics::copyCurrentScanBuffer } }; static int open_drawable(lua_State* L) diff --git a/source/modules/image/ImageData.cpp b/source/modules/image/ImageData.cpp index 47f0974e..950a2bbe 100644 --- a/source/modules/image/ImageData.cpp +++ b/source/modules/image/ImageData.cpp @@ -90,9 +90,11 @@ namespace love } } + static constexpr bool needsPowTwo = (Console::is(Console::CTR) ? true : false); + void ImageData::create(int width, int height, PixelFormat format, void* data) { - const auto dataSize = love::getPixelFormatSliceSize(format, width, height); + const auto dataSize = love::getPixelFormatSliceSize(format, width, height, needsPowTwo); try { @@ -105,7 +107,7 @@ namespace love if (data) { - if (Console::is(Console::CTR)) + if constexpr (Console::is(Console::CTR)) { if (format == PIXELFORMAT_RGB565_UNORM) copyBytesTiled(this->data, data, width, height); diff --git a/source/modules/image/magpie/JPGHandler.cpp b/source/modules/image/magpie/JPGHandler.cpp index 72701bbb..57bdb37b 100644 --- a/source/modules/image/magpie/JPGHandler.cpp +++ b/source/modules/image/magpie/JPGHandler.cpp @@ -46,7 +46,7 @@ namespace love image.width = width; image.height = height; image.format = PIXELFORMAT_RGBA8_UNORM; - image.size = (width * height * sizeof(uint32_t)); + image.size = (width * height) * sizeof(uint32_t); image.data = new uint8_t[image.size]; const auto format = TJPF_RGBA; diff --git a/source/modules/image/magpie/PNGHandler.cpp b/source/modules/image/magpie/PNGHandler.cpp index d387bfae..50cb448a 100644 --- a/source/modules/image/magpie/PNGHandler.cpp +++ b/source/modules/image/magpie/PNGHandler.cpp @@ -44,9 +44,11 @@ namespace love result.width = image.width; result.height = image.height; result.format = PIXELFORMAT_RGBA8_UNORM; - result.size = (image.width * image.height * sizeof(uint32_t)); + result.size = (image.width * image.height) * sizeof(uint32_t); result.data = new uint8_t[result.size]; + png_image_finish_read(&image, nullptr, result.data, PNG_IMAGE_ROW_STRIDE(image), nullptr); + if (PNG_IMAGE_FAILED(image)) { png_image_free(&image); diff --git a/source/modules/joystick/JoystickModule.cpp b/source/modules/joystick/JoystickModule.cpp index 0b024b9c..586387d5 100644 --- a/source/modules/joystick/JoystickModule.cpp +++ b/source/modules/joystick/JoystickModule.cpp @@ -75,7 +75,7 @@ namespace love // for when Wii U handles are dealt with (WPADHandle, VPADHandle classes) if (!joystick) { - joystick = new Joystick(this->joysticks.size()); + joystick = love::joystick::openJoystick(this->joysticks.size()); this->joysticks.push_back(joystick); } diff --git a/source/modules/joystick/wrap_Joystick.cpp b/source/modules/joystick/wrap_Joystick.cpp index 3ea30647..925e6e08 100644 --- a/source/modules/joystick/wrap_Joystick.cpp +++ b/source/modules/joystick/wrap_Joystick.cpp @@ -67,7 +67,7 @@ int Wrap_Joystick::getJoystickType(lua_State* L) auto* self = luax_checkjoystick(L, 1); std::string_view type = "Unknown"; - Joystick::getConstant(self->getJoystickType(), type); + JoystickBase::getConstant(self->getJoystickType(), type); luax_pushstring(L, type); @@ -106,7 +106,7 @@ int Wrap_Joystick::getAxis(lua_State* L) auto* self = luax_checkjoystick(L, 1); int axis = luaL_checkinteger(L, 2) - 1; - auto current = (Joystick::GamepadAxis)axis; + auto current = (JoystickBase::GamepadAxis)axis; lua_pushnumber(L, self->getAxis(current)); return 1; @@ -144,7 +144,7 @@ int Wrap_Joystick::isDown(lua_State* L) if (argc == 0) luaL_checkinteger(L, 2); - std::vector buttons {}; + std::vector buttons {}; buttons.reserve(argc); if (isTable) @@ -154,7 +154,7 @@ int Wrap_Joystick::isDown(lua_State* L) lua_rawgeti(L, 2, index + 1); int button = luaL_checkinteger(L, -1) - 1; - buttons.push_back(Joystick::GamepadButton(button)); + buttons.push_back(JoystickBase::GamepadButton(button)); lua_pop(L, 1); } } @@ -163,7 +163,7 @@ int Wrap_Joystick::isDown(lua_State* L) for (int index = 0; index < argc; index++) { int button = luaL_checkinteger(L, index + 2) - 1; - buttons.push_back(Joystick::GamepadButton(button)); + buttons.push_back(JoystickBase::GamepadButton(button)); } } @@ -205,7 +205,7 @@ int Wrap_Joystick::getGamepadType(lua_State* L) auto* self = luax_checkjoystick(L, 1); std::string_view type = "Unknown"; - Joystick::getConstant(self->getGamepadType(), type); + JoystickBase::getConstant(self->getGamepadType(), type); luax_pushstring(L, type); @@ -217,9 +217,9 @@ int Wrap_Joystick::getGamepadAxis(lua_State* L) auto* self = luax_checkjoystick(L, 1); const char* name = luaL_checkstring(L, 2); - Joystick::GamepadAxis axis; - if (!Joystick::getConstant(name, axis)) - return luax_enumerror(L, "gamepad axis", Joystick::GamepadButtons, name); + JoystickBase::GamepadAxis axis; + if (!JoystickBase::getConstant(name, axis)) + return luax_enumerror(L, "gamepad axis", JoystickBase::GamepadButtons, name); lua_pushnumber(L, self->getAxis(axis)); @@ -236,10 +236,10 @@ int Wrap_Joystick::isGamepadDown(lua_State* L) if (argc == 0) luaL_checkstring(L, 2); - std::vector buttons {}; + std::vector buttons {}; buttons.reserve(argc); - Joystick::GamepadButton button; + JoystickBase::GamepadButton button; if (isTable) { @@ -248,8 +248,8 @@ int Wrap_Joystick::isGamepadDown(lua_State* L) lua_rawgeti(L, 2, index + 1); const char* string = luaL_checkstring(L, -1); - if (!Joystick::getConstant(string, button)) - return luax_enumerror(L, "gamepad button", Joystick::GamepadButtons, string); + if (!JoystickBase::getConstant(string, button)) + return luax_enumerror(L, "gamepad button", JoystickBase::GamepadButtons, string); buttons.push_back(button); lua_pop(L, 1); @@ -261,8 +261,8 @@ int Wrap_Joystick::isGamepadDown(lua_State* L) { const char* string = luaL_checkstring(L, index + 2); - if (!Joystick::getConstant(string, button)) - return luax_enumerror(L, "gamepad button", Joystick::GamepadButtons, string); + if (!JoystickBase::getConstant(string, button)) + return luax_enumerror(L, "gamepad button", JoystickBase::GamepadButtons, string); buttons.push_back(button); } diff --git a/source/modules/love/love.cpp b/source/modules/love/love.cpp index 19314cb6..278d462f 100644 --- a/source/modules/love/love.cpp +++ b/source/modules/love/love.cpp @@ -25,13 +25,16 @@ #include "boot.hpp" +// #region DEBUG CONSOLE #include #include +#include #include #if defined(__WIIU__) #include #endif +// #endregion #include #include @@ -313,6 +316,31 @@ int love_openConsole(lua_State* L) return 1; } + fd_set set; + FD_ZERO(&set); + FD_SET(lsockfd, &set); + + struct timeval timeout; + timeout.tv_sec = 10; + timeout.tv_usec = 0; + + const auto result = select(lsockfd + 1, &set, NULL, NULL, &timeout); + + if (result == -1) + { + // select(...) failed + love::luax_pushboolean(L, false); + close(lsockfd); + return 1; + } + else if (result == 0) + { + // timeout occurred + love::luax_pushboolean(L, false); + close(lsockfd); + return 1; + } + int sockfd = accept(lsockfd, NULL, NULL); close(lsockfd); diff --git a/source/modules/love/scripts/callbacks.lua b/source/modules/love/scripts/callbacks.lua index 3f61238d..9de4c070 100644 --- a/source/modules/love/scripts/callbacks.lua +++ b/source/modules/love/scripts/callbacks.lua @@ -206,7 +206,7 @@ end -- we need to fix some bugs/inconsistencies on Wii U -- local is_wii_u = love._os == "Cafe" -local function get3DDepth(screen) +local function get_3d_depth(screen) if love._console ~= "3DS" then return nil end @@ -221,6 +221,8 @@ local function get3DDepth(screen) return depth end +-- local copyCurrentScanBuffer = love.graphics.copyCurrentScanBuffer or function() end + function love.run() if love.load then love.load(love.parsedGameArguments, love.rawGameArguments) @@ -232,11 +234,6 @@ function love.run() local delta = 0 - local screens, current_screen = nil, 1 - if love.graphics and love.graphics.isActive() then - screens = love.graphics.getScreens() - end - return function() if love.window and g_windowShown then return @@ -267,6 +264,8 @@ function love.run() end if love.graphics and love.graphics.isActive() then + local screens = love.graphics.getScreens() + for _, screen in ipairs(screens) do love.graphics.setActiveScreen(screen) @@ -274,8 +273,10 @@ function love.run() love.graphics.clear(love.graphics.getBackgroundColor()) if love.draw then - love.draw(screen, get3DDepth(screen)) + love.draw(screen, get_3d_depth(screen)) end + + love.graphics.copyCurrentScanBuffer() end love.graphics.present()