diff --git a/.github/workflows/Windows_Build.yml b/.github/workflows/Windows_Build.yml new file mode 100644 index 00000000..0a4abe41 --- /dev/null +++ b/.github/workflows/Windows_Build.yml @@ -0,0 +1,39 @@ +name: Windows Build + +on: + push: + branches: + - master + pull_request: + +env: + # Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.) + BUILD_TYPE: Release + +jobs: + build: + # The CMake configure and build commands are platform agnostic and should work equally + # well on Windows or Mac. You can convert this to a matrix build if you need + # cross-platform coverage. + # See: https://docs.github.com/en/free-pro-team@latest/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix + runs-on: windows-latest + + steps: + - uses: actions/checkout@v2 + - name: Fetch submodules + run: git submodule update --init --recursive + + - name: Configure CMake + # Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make. + # See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type + run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} + + - name: Build + # Build your program with the given configuration + run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} + + - name: Upload executable + uses: actions/upload-artifact@v2 + with: + name: Windows executable + path: './build/Release/Alber.exe' diff --git a/docs/img/OoT_Title.png b/docs/img/OoT_Title.png index b137ce17..da450079 100644 Binary files a/docs/img/OoT_Title.png and b/docs/img/OoT_Title.png differ diff --git a/include/services/hid.hpp b/include/services/hid.hpp index 70a25673..3a7bd570 100644 --- a/include/services/hid.hpp +++ b/include/services/hid.hpp @@ -49,10 +49,12 @@ class HIDService { u32 oldButtons; // The previous pad state s16 circlePadX, circlePadY; // Circlepad state + s16 touchScreenX, touchScreenY; // Touchscreen state bool accelerometerEnabled; bool eventsInitialized; bool gyroEnabled; + bool touchScreenPressed; std::array, 5> events; @@ -116,4 +118,14 @@ public: std::memset(ptr, 0, 0x2b0); } } + + void setTouchScreenPress(u16 x, u16 y) { + touchScreenX = x; + touchScreenY = y; + touchScreenPressed = true; + } + + void releaseTouchScreen() { + touchScreenPressed = false; + } }; \ No newline at end of file diff --git a/include/services/service_manager.hpp b/include/services/service_manager.hpp index 8084c1ea..300e8f2e 100644 --- a/include/services/service_manager.hpp +++ b/include/services/service_manager.hpp @@ -85,9 +85,12 @@ public: void signalDSPEvents() { dsp.signalEvents(); } + // Input function wrappers void pressKey(u32 key) { hid.pressKey(key); } void releaseKey(u32 key) { hid.releaseKey(key); } void setCirclepadX(u16 x) { hid.setCirclepadX(x); } void setCirclepadY(u16 y) { hid.setCirclepadY(y); } void updateInputs(u64 currentTimestamp) { hid.updateInputs(currentTimestamp); } + void setTouchScreenPress(u16 x, u16 y) { hid.setTouchScreenPress(x, y); } + void releaseTouchScreen() { hid.releaseTouchScreen(); } }; \ No newline at end of file diff --git a/readme.md b/readme.md index 8631d18f..46b57e0d 100644 --- a/readme.md +++ b/readme.md @@ -1,4 +1,5 @@ # Panda3DS +[![Windows Build](https://github.com/wheremyfoodat/Panda3DS/actions/workflows/Windows_Build.yml/badge.svg?branch=master)](https://github.com/wheremyfoodat/Panda3DS/actions/workflows/Windows_Build.yml) [![MacOS Build](https://github.com/wheremyfoodat/Panda3DS/actions/workflows/MacOS_Build.yml/badge.svg?branch=master)](https://github.com/wheremyfoodat/Panda3DS/actions/workflows/MacOS_Build.yml) [![Linux Build](https://github.com/wheremyfoodat/Panda3DS/actions/workflows/Linux_Build.yml/badge.svg?branch=master)](https://github.com/wheremyfoodat/Panda3DS/actions/workflows/Linux_Build.yml) Panda3DS is an HLE, red-panda-themed Nintendo 3DS emulator written in C++ which started out as a fun project out of curiosity, but evolved into something that can sort of play games! diff --git a/src/core/kernel/file_operations.cpp b/src/core/kernel/file_operations.cpp index c6307e06..d3d01bb7 100644 --- a/src/core/kernel/file_operations.cpp +++ b/src/core/kernel/file_operations.cpp @@ -25,6 +25,7 @@ void Kernel::handleFileOperation(u32 messagePointer, Handle file) { const u32 cmd = mem.read32(messagePointer); switch (cmd) { case FileOps::Close: closeFile(messagePointer, file); break; + case FileOps::Flush: flushFile(messagePointer, file); break; case FileOps::GetSize: getFileSize(messagePointer, file); break; case FileOps::OpenLinkFile: openLinkFile(messagePointer, file); break; case FileOps::Read: readFile(messagePointer, file); break; @@ -264,4 +265,4 @@ void Kernel::setFilePriority(u32 messagePointer, Handle fileHandle) { mem.write32(messagePointer, IPC::responseHeader(0x080A, 1, 0)); mem.write32(messagePointer + 4, Result::Success); -} \ No newline at end of file +} diff --git a/src/core/renderer_gl/renderer_gl.cpp b/src/core/renderer_gl/renderer_gl.cpp index 64525144..6da0dd70 100644 --- a/src/core/renderer_gl/renderer_gl.cpp +++ b/src/core/renderer_gl/renderer_gl.cpp @@ -361,6 +361,7 @@ constexpr u32 bottomScreenBuffer = 0x1f05dc00; // Quick hack to display top screen for now void Renderer::display() { + OpenGL::disableBlend(); OpenGL::disableDepth(); OpenGL::disableScissor(); diff --git a/src/core/services/hid.cpp b/src/core/services/hid.cpp index cc4d5575..fa4536d0 100644 --- a/src/core/services/hid.cpp +++ b/src/core/services/hid.cpp @@ -25,6 +25,7 @@ void HIDService::reset() { accelerometerEnabled = false; eventsInitialized = false; gyroEnabled = false; + touchScreenPressed = false; // Deinitialize HID events for (auto& e : events) { @@ -36,6 +37,7 @@ void HIDService::reset() { // Reset button states newButtons = oldButtons = 0; circlePadX = circlePadY = 0; + touchScreenX = touchScreenY = 0; } void HIDService::handleSyncRequest(u32 messagePointer) { @@ -147,7 +149,12 @@ void HIDService::updateInputs(u64 currentTick) { writeSharedMem(0xA8, currentTick); // Write new tick count } writeSharedMem(0xB8, nextTouchscreenIndex); // Index last updated by the HID module + const size_t touchEntryOffset = 0xC8 + (nextTouchscreenIndex * 8); // Offset in the array of 8 touchscreen entries nextTouchscreenIndex = (nextTouchscreenIndex + 1) % 8; // Move to next entry + + writeSharedMem(touchEntryOffset, touchScreenX); + writeSharedMem(touchEntryOffset + 2, touchScreenY); + writeSharedMem(touchEntryOffset + 4, touchScreenPressed ? 1 : 0); // Next, update accelerometer state if (nextAccelerometerIndex == 0) { diff --git a/src/emulator.cpp b/src/emulator.cpp index 9d274ebf..8141a94a 100644 --- a/src/emulator.cpp +++ b/src/emulator.cpp @@ -38,60 +38,86 @@ void Emulator::run() { namespace Keys = HID::Keys; switch (event.type) { - case SDL_QUIT: - printf("Bye :(\n"); - running = false; - return; - case SDL_KEYDOWN: - switch (event.key.keysym.sym) { - case SDLK_l: srv.pressKey(Keys::A); break; - case SDLK_k: srv.pressKey(Keys::B); break; - case SDLK_o: srv.pressKey(Keys::X); break; - case SDLK_i: srv.pressKey(Keys::Y); break; + case SDL_QUIT: + printf("Bye :(\n"); + running = false; + return; + case SDL_KEYDOWN: + switch (event.key.keysym.sym) { + case SDLK_l: srv.pressKey(Keys::A); break; + case SDLK_k: srv.pressKey(Keys::B); break; + case SDLK_o: srv.pressKey(Keys::X); break; + case SDLK_i: srv.pressKey(Keys::Y); break; - case SDLK_q: srv.pressKey(Keys::L); break; - case SDLK_p: srv.pressKey(Keys::R); break; + case SDLK_q: srv.pressKey(Keys::L); break; + case SDLK_p: srv.pressKey(Keys::R); break; - case SDLK_RIGHT: srv.pressKey(Keys::Right); break; - case SDLK_LEFT: srv.pressKey(Keys::Left); break; - case SDLK_UP: srv.pressKey(Keys::Up); break; - case SDLK_DOWN: srv.pressKey(Keys::Down); break; + case SDLK_RIGHT: srv.pressKey(Keys::Right); break; + case SDLK_LEFT: srv.pressKey(Keys::Left); break; + case SDLK_UP: srv.pressKey(Keys::Up); break; + case SDLK_DOWN: srv.pressKey(Keys::Down); break; - case SDLK_w: srv.setCirclepadY(0x9C); break; - case SDLK_a: srv.setCirclepadX(-0x9C); break; - case SDLK_s: srv.setCirclepadY(-0x9C); break; - case SDLK_d: srv.setCirclepadX(0x9C); break; + case SDLK_w: srv.setCirclepadY(0x9C); break; + case SDLK_a: srv.setCirclepadX(-0x9C); break; + case SDLK_s: srv.setCirclepadY(-0x9C); break; + case SDLK_d: srv.setCirclepadX(0x9C); break; - case SDLK_RETURN: srv.pressKey(Keys::Start); break; - case SDLK_BACKSPACE: srv.pressKey(Keys::Select); break; + case SDLK_RETURN: srv.pressKey(Keys::Start); break; + case SDLK_BACKSPACE: srv.pressKey(Keys::Select); break; + } + break; + case SDL_KEYUP: + switch (event.key.keysym.sym) { + case SDLK_l: srv.releaseKey(Keys::A); break; + case SDLK_k: srv.releaseKey(Keys::B); break; + case SDLK_o: srv.releaseKey(Keys::X); break; + case SDLK_i: srv.releaseKey(Keys::Y); break; + + case SDLK_q: srv.releaseKey(Keys::L); break; + case SDLK_p: srv.releaseKey(Keys::R); break; + + case SDLK_RIGHT: srv.releaseKey(Keys::Right); break; + case SDLK_LEFT: srv.releaseKey(Keys::Left); break; + case SDLK_UP: srv.releaseKey(Keys::Up); break; + case SDLK_DOWN: srv.releaseKey(Keys::Down); break; + + // Err this is probably not ideal + case SDLK_w: srv.setCirclepadY(0); break; + case SDLK_a: srv.setCirclepadX(0); break; + case SDLK_s: srv.setCirclepadY(0); break; + case SDLK_d: srv.setCirclepadX(0); break; + + case SDLK_RETURN: srv.releaseKey(Keys::Start); break; + case SDLK_BACKSPACE: srv.releaseKey(Keys::Select); break; + } + break; + + case SDL_MOUSEBUTTONDOWN: { + if (event.button.button == SDL_BUTTON_LEFT) { + const s32 x = event.button.x; + const s32 y = event.button.y; + + // Check if touch falls in the touch screen area + if (y >= 240 && y <= 480 && x >= 40 && x < 40 + 320) { + // Convert to 3DS coordinates + u16 x_converted = static_cast(x) - 40; + u16 y_converted = static_cast(y) - 240; + + srv.setTouchScreenPress(x_converted, y_converted); + } + else { + srv.releaseTouchScreen(); + } + } + break; } - break; - case SDL_KEYUP: - switch (event.key.keysym.sym) { - case SDLK_l: srv.releaseKey(Keys::A); break; - case SDLK_k: srv.releaseKey(Keys::B); break; - case SDLK_o: srv.releaseKey(Keys::X); break; - case SDLK_i: srv.releaseKey(Keys::Y); break; - case SDLK_q: srv.releaseKey(Keys::L); break; - case SDLK_p: srv.releaseKey(Keys::R); break; - - case SDLK_RIGHT: srv.releaseKey(Keys::Right); break; - case SDLK_LEFT: srv.releaseKey(Keys::Left); break; - case SDLK_UP: srv.releaseKey(Keys::Up); break; - case SDLK_DOWN: srv.releaseKey(Keys::Down); break; - - // Err this is probably not ideal - case SDLK_w: srv.setCirclepadY(0); break; - case SDLK_a: srv.setCirclepadX(0); break; - case SDLK_s: srv.setCirclepadY(0); break; - case SDLK_d: srv.setCirclepadX(0); break; - - case SDLK_RETURN: srv.releaseKey(Keys::Start); break; - case SDLK_BACKSPACE: srv.releaseKey(Keys::Select); break; + case SDL_MOUSEBUTTONUP: + if (event.button.button == SDL_BUTTON_LEFT) { + srv.releaseTouchScreen(); + } + break; } - break; - } } // Update inputs in the HID module