diff --git a/input/controller.cpp b/input/controller.cpp index 4f0043e..7c209fa 100644 --- a/input/controller.cpp +++ b/input/controller.cpp @@ -42,6 +42,11 @@ bool Controller::Init(int controllerUserID) { scePadSetLightBar(this->pad, &this->padColors[this->currPadColor]); scePadGetControllerInformation(this->pad, &padInfo); + + if (scePadSetMotionSensorState(this->pad, true) != ORBIS_OK) { + DEBUGLOG << "[DEBUG] [ERROR] Failed to enable motion sensor!"; + } + return true; } @@ -181,8 +186,16 @@ int Controller::ReadFingers(OrbisPadTouch **fingers) { return this->padData.touch.fingers; } -int Controller::GetToucPadResolution(int *w, int *h) { +int Controller::GetTouchPadResolution(int *w, int *h) { if (w) *w = padInfo.touchResolutionX; if (h) *h = padInfo.touchResolutionY; return 0; } + +void Controller::ResetOrientation() { + scePadResetOrientation(this->pad); +} + +void Controller::ReadGyro(vec_float4* quat) { + if (quat) *quat = this->padData.quat; +} diff --git a/input/controller.h b/input/controller.h index 7ba22e9..a0caf5f 100644 --- a/input/controller.h +++ b/input/controller.h @@ -41,8 +41,10 @@ class Controller bool DpadLeftPressed(); bool TouchpadPressed(); int ReadFingers(OrbisPadTouch **fingers); - int GetToucPadResolution(int *w, int *h); + int GetTouchPadResolution(int *w, int *h); void ReadSticks(float *leftx, float *lefty, float *rightx, float *righty); + void ReadGyro(vec_float4* data); + void ResetOrientation(); OrbisPadColor NextColor(); }; diff --git a/input/graphics.cpp b/input/graphics.cpp index 1c1eb4c..561501a 100644 --- a/input/graphics.cpp +++ b/input/graphics.cpp @@ -13,14 +13,14 @@ Scene2D::Scene2D(int w, int h, int pixelDepth) this->width = w; this->height = h; this->depth = pixelDepth; - + this->frameBufferSize = this->width * this->height * this->depth; } bool Scene2D::Init(size_t memSize, int numFrameBuffers) { int rc; - + this->video = sceVideoOutOpen(ORBIS_VIDEO_USER_MAIN, ORBIS_VIDEO_OUT_BUS_MAIN, 0, 0); this->videoMem = NULL; @@ -29,7 +29,7 @@ bool Scene2D::Init(size_t memSize, int numFrameBuffers) DEBUGLOG << "Failed to open a video out handle: " << std::string(strerror(errno)); return false; } - + #ifdef GRAPHICS_USES_FONT // Load freetype rc = sceSysmoduleLoadModule(0x009A); @@ -49,25 +49,25 @@ bool Scene2D::Init(size_t memSize, int numFrameBuffers) return false; } #endif - + if(!initFlipQueue()) { DEBUGLOG << "Failed to initialize flip queue: " << std::string(strerror(errno)); return false; } - + if(!allocateVideoMem(memSize, 0x200000)) { DEBUGLOG << "Failed to allocate video memory: " << std::string(strerror(errno)); return false; } - + if(!allocateFrameBuffers(numFrameBuffers)) { DEBUGLOG << "Failed to allocate frame buffers: " << std::string(strerror(errno)); return false; } - + sceVideoOutSetFlipRate(this->video, 0); return true; } @@ -75,10 +75,10 @@ bool Scene2D::Init(size_t memSize, int numFrameBuffers) bool Scene2D::initFlipQueue() { int rc = sceKernelCreateEqueue(&flipQueue, "homebrew flip queue"); - + if(rc < 0) return false; - + sceVideoOutAddFlipEvent(flipQueue, this->video, 0); return true; } @@ -87,14 +87,14 @@ bool Scene2D::allocateFrameBuffers(int num) { // Allocate frame buffers array this->frameBuffers = new char*[num]; - + // Set the display buffers for(int i = 0; i < num; i++) this->frameBuffers[i] = this->allocateDisplayMem(frameBufferSize); // Set SRGB pixel format sceVideoOutSetBufferAttribute(&this->attr, 0x80000000, 1, 0, this->width, this->height, this->width); - + // Register the buffers to the video handle return (sceVideoOutRegisterBuffers(this->video, 0, (void **)this->frameBuffers, num, &this->attr) == 0); } @@ -111,32 +111,32 @@ char *Scene2D::allocateDisplayMem(size_t size) bool Scene2D::allocateVideoMem(size_t size, int alignment) { int rc; - + // Align the allocation size this->directMemAllocationSize = (size + alignment - 1) / alignment * alignment; - + // Allocate memory for display buffer rc = sceKernelAllocateDirectMemory(0, sceKernelGetDirectMemorySize(), this->directMemAllocationSize, alignment, 3, &this->directMemOff); - + if(rc < 0) { this->directMemAllocationSize = 0; return false; } - + // Map the direct memory rc = sceKernelMapDirectMemory(&this->videoMem, this->directMemAllocationSize, 0x33, 0, this->directMemOff, alignment); - + if(rc < 0) { sceKernelReleaseDirectMemory(this->directMemOff, this->directMemAllocationSize); - + this->directMemOff = 0; this->directMemAllocationSize = 0; - + return false; } - + // Set the stack pointer to the beginning of the buffer this->videoMemSP = (uintptr_t)this->videoMem; return true; @@ -146,13 +146,13 @@ void Scene2D::deallocateVideoMem() { // Free the direct memory sceKernelReleaseDirectMemory(this->directMemOff, this->directMemAllocationSize); - + // Zero out meta data this->videoMem = 0; this->videoMemSP = 0; this->directMemOff = 0; this->directMemAllocationSize = 0; - + // Free the frame buffer array delete this->frameBuffers; this->frameBuffers = 0; @@ -172,21 +172,21 @@ void Scene2D::FrameWait(int frameID) { OrbisKernelEvent evt; int count; - + // If the video handle is not initialized, bail out. This is mostly a failsafe, this should never happen. if(this->video == 0) return; - + for(;;) { OrbisVideoOutFlipStatus flipStatus; - + // Get the flip status and check the arg for the given frame ID sceVideoOutGetFlipStatus(video, &flipStatus); - + if(flipStatus.flipArg == frameID) break; - + // Wait on next flip event if(sceKernelWaitEqueue(this->flipQueue, &evt, 1, &count, 0) != 0) break; @@ -210,17 +210,17 @@ void Scene2D::FrameBufferClear() bool Scene2D::InitFont(FT_Face *face, const char *fontPath, int fontSize) { int rc; - + rc = FT_New_Face(this->ftLib, fontPath, 0, face); - + if(rc < 0) return false; rc = FT_Set_Pixel_Sizes(*face, 0, fontSize); - + if(rc < 0) return false; - + return true; } #endif @@ -234,10 +234,10 @@ void Scene2D::DrawPixel(int x, int y, Color color) { // Get pixel location based on pitch int pixel = (y * this->width) + x; - + // Encode to 24-bit color uint32_t encodedColor = 0x80000000 + (color.r << 16) + (color.g << 8) + color.b; - + // Draw to the frame buffer ((uint32_t *)this->frameBuffers[this->activeFrameBufferIdx])[pixel] = encodedColor; } @@ -245,7 +245,7 @@ void Scene2D::DrawPixel(int x, int y, Color color) void Scene2D::DrawRectangle(int x, int y, int w, int h, Color color) { int xPos, yPos; - + // Draw row-by-row, column-by-column for(yPos = y; yPos < y + h; yPos++) { @@ -262,10 +262,10 @@ void Scene2D::DrawText(char *txt, FT_Face face, int startX, int startY, Color bg int rc; int xOffset = 0; int yOffset = 0; - + // Get the glyph slot for bitmap and font metrics FT_GlyphSlot slot = face->glyph; - + // Iterate each character of the text to write to the screen for(int n = 0; n < strlen(txt); n++) { diff --git a/input/graphics.h b/input/graphics.h index 1624991..b2eb798 100644 --- a/input/graphics.h +++ b/input/graphics.h @@ -23,25 +23,25 @@ class Scene2D #ifdef GRAPHICS_USES_FONT FT_Library ftLib; #endif - + int width; int height; int depth; int video; - + off_t directMemOff; size_t directMemAllocationSize; - + uintptr_t videoMemSP; void *videoMem; - + char **frameBuffers; OrbisKernelEqueue flipQueue; OrbisVideoOutBufferAttribute attr; - + int frameBufferSize; int frameBufferCount; - + int activeFrameBufferIdx; bool initFlipQueue(); @@ -53,20 +53,20 @@ class Scene2D public: Scene2D(int w, int h, int pixelDepth); ~Scene2D(); - + bool Init(size_t memSize, int numFrameBuffers); - + void SetActiveFrameBuffer(int index); void SubmitFlip(int frameID); - + void FrameWait(int frameID); void FrameBufferSwap(); void FrameBufferClear(); void FrameBufferFill(Color color); - + void DrawPixel(int x, int y, Color color); void DrawRectangle(int x, int y, int w, int h, Color color); - + #ifdef GRAPHICS_USES_FONT bool InitFont(FT_Face *face, const char *fontPath, int fontSize); void DrawText(char *txt, FT_Face face, int startX, int startY, Color bgColor, Color fgColor); diff --git a/input/log.h b/input/log.h index 4ea3d85..d24c983 100644 --- a/input/log.h +++ b/input/log.h @@ -14,19 +14,19 @@ class Log { debugLogStream << funcName << ": "; } - + template Log &operator<<(const T &v) { debugLogStream << v; return *this; } - + ~Log() { debugLogStream << std::endl; printf("%s", debugLogStream.str().c_str()); - + // Clear the stream debugLogStream.str(""); } diff --git a/input/main.cpp b/input/main.cpp index 6f34611..5752dff 100644 --- a/input/main.cpp +++ b/input/main.cpp @@ -13,6 +13,11 @@ // Logging std::stringstream debugLogStream; +#ifndef MIN +# define MIN(a,b) (((a)<(b))?(a):(b)) +# define MAX(a,b) (((a)>(b))?(a):(b)) +#endif + int frameID = 0; static void repaintBar(PNG *png, OrbisPadColor newColor) { @@ -37,138 +42,141 @@ static void repaintBar(PNG *png, OrbisPadColor newColor) { } int main(void) { - // No buffering - setvbuf(stdout, NULL, _IONBF, 0); - // Create a 2D scene - DEBUGLOG << "Creating a scene"; - auto scene = new Scene2D(FRAME_WIDTH, FRAME_HEIGHT, FRAME_DEPTH); - if(!scene->Init(0xC000000, 2)) { - DEBUGLOG << "Failed to initialize 2D scene"; - for(;;); - } - // Create a controller - DEBUGLOG << "Initializing controller"; - auto controller = new Controller(); - if(!controller->Init(-1)) { - DEBUGLOG << "Failed to initialize controller"; - for(;;); - } + // No buffering + setvbuf(stdout, NULL, _IONBF, 0); + // Create a 2D scene + DEBUGLOG << "Creating a scene"; + auto scene = new Scene2D(FRAME_WIDTH, FRAME_HEIGHT, FRAME_DEPTH); + if(!scene->Init(0xC000000, 2)) { + DEBUGLOG << "Failed to initialize 2D scene"; + for(;;); + } + // Create a controller + DEBUGLOG << "Initializing controller"; + auto controller = new Controller(); + if(!controller->Init(-1)) { + DEBUGLOG << "Failed to initialize controller"; + for(;;); + } int tpw, tph; - controller->GetToucPadResolution(&tpw, &tph); - - // Create PNG instances for all the sprites - auto controllerBackground = new PNG("/app0/assets/images/controller.png"); - auto thumbstick_pr = new PNG("/app0/assets/images/thumbstick_pr.png"); - auto thumbstick = new PNG("/app0/assets/images/thumbstick.png"); - auto touchpad = new PNG("/app0/assets/images/touchpad.png"); - auto dpadUp = new PNG("/app0/assets/images/dpad-up.png"); - auto dpadRight = new PNG("/app0/assets/images/dpad-right.png"); - auto dpadDown = new PNG("/app0/assets/images/dpad-down.png"); - auto dpadLeft = new PNG("/app0/assets/images/dpad-left.png"); - auto triangleBtn = new PNG("/app0/assets/images/triangle.png"); - auto circleBtn = new PNG("/app0/assets/images/circle.png"); - auto xBtn = new PNG("/app0/assets/images/x.png"); - auto squareBtn = new PNG("/app0/assets/images/square.png"); - auto startBtn = new PNG("/app0/assets/images/start.png"); - auto l1Trigger = new PNG("/app0/assets/images/l1.png"); - auto l2Trigger = new PNG("/app0/assets/images/l2.png"); - auto r1Trigger = new PNG("/app0/assets/images/r1.png"); - auto r2Trigger = new PNG("/app0/assets/images/r2.png"); - - DEBUGLOG << "Entering draw loop..."; - // Draw loop - for (;;) { - controllerBackground->Draw(scene, 0, 0); - static bool released = true; - - if(controller->TrianglePressed()) { - triangleBtn->Draw(scene, 1187, 359); - released = false; - } else if (released == false) { + controller->GetTouchPadResolution(&tpw, &tph); + + // Create PNG instances for all the sprites + auto controllerBackground = new PNG("/app0/assets/images/controller.png"); + auto thumbstick_pr = new PNG("/app0/assets/images/thumbstick_pr.png"); + auto thumbstick = new PNG("/app0/assets/images/thumbstick.png"); + auto touchpad = new PNG("/app0/assets/images/touchpad.png"); + auto dpadUp = new PNG("/app0/assets/images/dpad-up.png"); + auto dpadRight = new PNG("/app0/assets/images/dpad-right.png"); + auto dpadDown = new PNG("/app0/assets/images/dpad-down.png"); + auto dpadLeft = new PNG("/app0/assets/images/dpad-left.png"); + auto triangleBtn = new PNG("/app0/assets/images/triangle.png"); + auto circleBtn = new PNG("/app0/assets/images/circle.png"); + auto xBtn = new PNG("/app0/assets/images/x.png"); + auto squareBtn = new PNG("/app0/assets/images/square.png"); + auto startBtn = new PNG("/app0/assets/images/start.png"); + auto l1Trigger = new PNG("/app0/assets/images/l1.png"); + auto l2Trigger = new PNG("/app0/assets/images/l2.png"); + auto r1Trigger = new PNG("/app0/assets/images/r1.png"); + auto r2Trigger = new PNG("/app0/assets/images/r2.png"); + + DEBUGLOG << "Entering draw loop..."; + // Draw loop + for (;;) { + controllerBackground->Draw(scene, 0, 0); + static bool released = true; + + if(controller->TrianglePressed()) { + triangleBtn->Draw(scene, 1187, 359); + released = false; + } else if (released == false) { repaintBar(controllerBackground, controller->NextColor()); - released = true; - } - - if(controller->CirclePressed()) { - circleBtn->Draw(scene, 1244, 416); - } - - if(controller->XPressed()) { - xBtn->Draw(scene, 1187, 472); - } - - if(controller->SquarePressed()) { - squareBtn->Draw(scene, 1131, 416); - } - - if(controller->L1Pressed()) { - l1Trigger->Draw(scene, 653, 139); - } - - float str = 0.0f; - - if(controller->L2Pressed(&str)) { - scene->DrawRectangle(653, 255, str * 113, 10, Color{0xff, 0x00, 0x00}); - l2Trigger->Draw(scene, 653, 181); - } - - if(controller->R1Pressed()) { - r1Trigger->Draw(scene, 1150, 139); - } - - str = 0.0f; - - if(controller->R2Pressed(&str)) { - scene->DrawRectangle(1150, 255, str * 113, 10, Color{0x00, 0x00, 0xff}); - r2Trigger->Draw(scene, 1150, 181); - } - - if(controller->StartPressed()) { - startBtn->Draw(scene, 1094, 334); - } - - if(controller->DpadUpPressed()) { - dpadUp->Draw(scene, 687, 377); - } - - if(controller->DpadRightPressed()) { - dpadRight->Draw(scene, 722, 422); - } - - if(controller->DpadDownPressed()) { - dpadDown->Draw(scene, 687, 458); - } - - if(controller->DpadLeftPressed()) { - dpadLeft->Draw(scene, 641, 422); - } - - if(controller->TouchpadPressed()) { - touchpad->Draw(scene, 854, 323); - } - - OrbisPadTouch *f = nullptr; - if (int fingers = controller->ReadFingers(&f)) { - for (int x = 0; x < 10; ++x) - for (int y = 0; y < 10; ++y) - for (int i = 0; i < fingers; ++i) { - auto fx = ((float)f[i].x / tpw) * 211, fy = ((float)f[i].y / tph) * 138; - scene->DrawPixel(850 + x + fx, 318 + y + fy, Color {0xFF, 0x00, 0x00}); - } - } - - float lx, ly, rx, ry; - controller->ReadSticks(&lx, &ly, &rx, &ry); - (controller->L3Pressed() ? thumbstick_pr : thumbstick)->Draw(scene, 780 + 20 * lx, 512 + 20 * ly); - (controller->R3Pressed() ? thumbstick_pr : thumbstick)->Draw(scene, 1037 + 20 * rx, 512 + 20 * ry); - - // Submit the frame buffer - scene->SubmitFlip(frameID); - scene->FrameWait(frameID); - - // Swap to the next buffer - scene->FrameBufferSwap(); - frameID++; - } + released = true; + } + + if(controller->CirclePressed()) { + circleBtn->Draw(scene, 1244, 416); + } + + if(controller->XPressed()) { + xBtn->Draw(scene, 1187, 472); + controller->ResetOrientation(); + } + + if(controller->SquarePressed()) { + squareBtn->Draw(scene, 1131, 416); + } + + if(controller->L1Pressed()) { + l1Trigger->Draw(scene, 653, 139); + } + + if(float str; controller->L2Pressed(&str)) { + scene->DrawRectangle(653, 255, str * 113, 10, Color{0xff, 0x00, 0x00}); + l2Trigger->Draw(scene, 653, 181); + } + + if(controller->R1Pressed()) { + r1Trigger->Draw(scene, 1150, 139); + } + + if(float str; controller->R2Pressed(&str)) { + scene->DrawRectangle(1150, 255, str * 113, 10, Color{0x00, 0x00, 0xff}); + r2Trigger->Draw(scene, 1150, 181); + } + + if(controller->StartPressed()) { + startBtn->Draw(scene, 1094, 334); + } + + if(controller->DpadUpPressed()) { + dpadUp->Draw(scene, 687, 377); + } + + if(controller->DpadRightPressed()) { + dpadRight->Draw(scene, 722, 422); + } + + if(controller->DpadDownPressed()) { + dpadDown->Draw(scene, 687, 458); + } + + if(controller->DpadLeftPressed()) { + dpadLeft->Draw(scene, 641, 422); + } + + if(controller->TouchpadPressed()) { + touchpad->Draw(scene, 854, 323); + } + + OrbisPadTouch *f = nullptr; + if (int fingers = controller->ReadFingers(&f)) { + for (int i = 0; i < fingers; ++i) { + auto fx = ((float)f[i].x / tpw) * 211, fy = ((float)f[i].y / tph) * 138; + scene->DrawRectangle(850 + fx, 318 + fy, 10, 10, Color {0xFF, 0x00, 0x00}); + } + } + + vec_float4 q; + controller->ReadGyro(&q); + + scene->DrawRectangle(20, MAX(0, MIN(FRAME_HEIGHT, (FRAME_HEIGHT/2) - q.x * 40)), 15, 10, Color {0xFF, 0x00, 0x00}); + scene->DrawRectangle(40, MAX(0, MIN(FRAME_HEIGHT, (FRAME_HEIGHT/2) - q.y * 40)), 15, 10, Color {0xFF, 0x00, 0x00}); + scene->DrawRectangle(60, MAX(0, MIN(FRAME_HEIGHT, (FRAME_HEIGHT/2) - q.z * 40)), 15, 10, Color {0xFF, 0x00, 0x00}); + scene->DrawRectangle(80, MAX(0, MIN(FRAME_HEIGHT, (FRAME_HEIGHT/2) - q.w * 40)), 15, 10, Color {0xFF, 0x00, 0x00}); + + float lx, ly, rx, ry; + controller->ReadSticks(&lx, &ly, &rx, &ry); + (controller->L3Pressed() ? thumbstick_pr : thumbstick)->Draw(scene, 780 + 20 * lx, 512 + 20 * ly); + (controller->R3Pressed() ? thumbstick_pr : thumbstick)->Draw(scene, 1037 + 20 * rx, 512 + 20 * ry); + + // Submit the frame buffer + scene->SubmitFlip(frameID); + scene->FrameWait(frameID); + + // Swap to the next buffer + scene->FrameBufferSwap(); + frameID++; + } } diff --git a/input/png.cpp b/input/png.cpp index 2712051..87a7ee6 100644 --- a/input/png.cpp +++ b/input/png.cpp @@ -34,7 +34,7 @@ void PNG::Draw(Scene2D *scene, int startX, int startY) // Don't draw non-existant images if(this->img == NULL) return; - + // Iterate the bitmap and draw the pixels for (int yPos = 0; yPos < this->height; yPos++) { diff --git a/padpatch/funcs.h b/padpatch/funcs.h index e60e21e..66f341c 100644 --- a/padpatch/funcs.h +++ b/padpatch/funcs.h @@ -33,6 +33,7 @@ int32_t scePadGetHandle(int32_t userID, uint32_t controller_type, uint32_t contr int32_t scePadResetOrientation(int32_t handle); int32_t scePadSetVibration(int32_t handle, const OrbisPadVibeParam *param); int32_t scePadOutputReport(int32_t handle, int32_t type, uint8_t *report, int32_t length); +int32_t scePadSetMotionSensorState(int32_t handle, bool bEnable); // The below functions are currently not reversed void scePadConnectPort(); @@ -89,7 +90,6 @@ void scePadSetLightBarBaseBrightness(); void scePadSetLightBarBlinking(); void scePadSetLightBarForTracker(); void scePadSetLoginUserNumber(); -void scePadSetMotionSensorState(); void scePadSetProcessFocus(); void scePadSetProcessPrivilege(); void scePadSetProcessPrivilegeOfButtonRemapping();