mirror of
https://github.com/wheremyfoodat/Panda3DS.git
synced 2025-04-07 06:35:40 +12:00
Merge branch 'master' into dynapica
This commit is contained in:
commit
3606c005c5
9 changed files with 138 additions and 48 deletions
39
.github/workflows/Windows_Build.yml
vendored
Normal file
39
.github/workflows/Windows_Build.yml
vendored
Normal file
|
@ -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'
|
Binary file not shown.
Before Width: | Height: | Size: 159 KiB After Width: | Height: | Size: 216 KiB |
|
@ -49,10 +49,12 @@ class HIDService {
|
||||||
u32 oldButtons; // The previous pad state
|
u32 oldButtons; // The previous pad state
|
||||||
|
|
||||||
s16 circlePadX, circlePadY; // Circlepad state
|
s16 circlePadX, circlePadY; // Circlepad state
|
||||||
|
s16 touchScreenX, touchScreenY; // Touchscreen state
|
||||||
|
|
||||||
bool accelerometerEnabled;
|
bool accelerometerEnabled;
|
||||||
bool eventsInitialized;
|
bool eventsInitialized;
|
||||||
bool gyroEnabled;
|
bool gyroEnabled;
|
||||||
|
bool touchScreenPressed;
|
||||||
|
|
||||||
std::array<std::optional<Handle>, 5> events;
|
std::array<std::optional<Handle>, 5> events;
|
||||||
|
|
||||||
|
@ -116,4 +118,14 @@ public:
|
||||||
std::memset(ptr, 0, 0x2b0);
|
std::memset(ptr, 0, 0x2b0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setTouchScreenPress(u16 x, u16 y) {
|
||||||
|
touchScreenX = x;
|
||||||
|
touchScreenY = y;
|
||||||
|
touchScreenPressed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void releaseTouchScreen() {
|
||||||
|
touchScreenPressed = false;
|
||||||
|
}
|
||||||
};
|
};
|
|
@ -85,9 +85,12 @@ public:
|
||||||
|
|
||||||
void signalDSPEvents() { dsp.signalEvents(); }
|
void signalDSPEvents() { dsp.signalEvents(); }
|
||||||
|
|
||||||
|
// Input function wrappers
|
||||||
void pressKey(u32 key) { hid.pressKey(key); }
|
void pressKey(u32 key) { hid.pressKey(key); }
|
||||||
void releaseKey(u32 key) { hid.releaseKey(key); }
|
void releaseKey(u32 key) { hid.releaseKey(key); }
|
||||||
void setCirclepadX(u16 x) { hid.setCirclepadX(x); }
|
void setCirclepadX(u16 x) { hid.setCirclepadX(x); }
|
||||||
void setCirclepadY(u16 y) { hid.setCirclepadY(y); }
|
void setCirclepadY(u16 y) { hid.setCirclepadY(y); }
|
||||||
void updateInputs(u64 currentTimestamp) { hid.updateInputs(currentTimestamp); }
|
void updateInputs(u64 currentTimestamp) { hid.updateInputs(currentTimestamp); }
|
||||||
|
void setTouchScreenPress(u16 x, u16 y) { hid.setTouchScreenPress(x, y); }
|
||||||
|
void releaseTouchScreen() { hid.releaseTouchScreen(); }
|
||||||
};
|
};
|
|
@ -1,4 +1,5 @@
|
||||||
# Panda3DS
|
# Panda3DS
|
||||||
|
[](https://github.com/wheremyfoodat/Panda3DS/actions/workflows/Windows_Build.yml) [](https://github.com/wheremyfoodat/Panda3DS/actions/workflows/MacOS_Build.yml) [](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!
|
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!
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,7 @@ void Kernel::handleFileOperation(u32 messagePointer, Handle file) {
|
||||||
const u32 cmd = mem.read32(messagePointer);
|
const u32 cmd = mem.read32(messagePointer);
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
case FileOps::Close: closeFile(messagePointer, file); break;
|
case FileOps::Close: closeFile(messagePointer, file); break;
|
||||||
|
case FileOps::Flush: flushFile(messagePointer, file); break;
|
||||||
case FileOps::GetSize: getFileSize(messagePointer, file); break;
|
case FileOps::GetSize: getFileSize(messagePointer, file); break;
|
||||||
case FileOps::OpenLinkFile: openLinkFile(messagePointer, file); break;
|
case FileOps::OpenLinkFile: openLinkFile(messagePointer, file); break;
|
||||||
case FileOps::Read: readFile(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, IPC::responseHeader(0x080A, 1, 0));
|
||||||
mem.write32(messagePointer + 4, Result::Success);
|
mem.write32(messagePointer + 4, Result::Success);
|
||||||
}
|
}
|
||||||
|
|
|
@ -361,6 +361,7 @@ constexpr u32 bottomScreenBuffer = 0x1f05dc00;
|
||||||
|
|
||||||
// Quick hack to display top screen for now
|
// Quick hack to display top screen for now
|
||||||
void Renderer::display() {
|
void Renderer::display() {
|
||||||
|
OpenGL::disableBlend();
|
||||||
OpenGL::disableDepth();
|
OpenGL::disableDepth();
|
||||||
OpenGL::disableScissor();
|
OpenGL::disableScissor();
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,7 @@ void HIDService::reset() {
|
||||||
accelerometerEnabled = false;
|
accelerometerEnabled = false;
|
||||||
eventsInitialized = false;
|
eventsInitialized = false;
|
||||||
gyroEnabled = false;
|
gyroEnabled = false;
|
||||||
|
touchScreenPressed = false;
|
||||||
|
|
||||||
// Deinitialize HID events
|
// Deinitialize HID events
|
||||||
for (auto& e : events) {
|
for (auto& e : events) {
|
||||||
|
@ -36,6 +37,7 @@ void HIDService::reset() {
|
||||||
// Reset button states
|
// Reset button states
|
||||||
newButtons = oldButtons = 0;
|
newButtons = oldButtons = 0;
|
||||||
circlePadX = circlePadY = 0;
|
circlePadX = circlePadY = 0;
|
||||||
|
touchScreenX = touchScreenY = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void HIDService::handleSyncRequest(u32 messagePointer) {
|
void HIDService::handleSyncRequest(u32 messagePointer) {
|
||||||
|
@ -147,7 +149,12 @@ void HIDService::updateInputs(u64 currentTick) {
|
||||||
writeSharedMem<u64>(0xA8, currentTick); // Write new tick count
|
writeSharedMem<u64>(0xA8, currentTick); // Write new tick count
|
||||||
}
|
}
|
||||||
writeSharedMem<u32>(0xB8, nextTouchscreenIndex); // Index last updated by the HID module
|
writeSharedMem<u32>(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
|
nextTouchscreenIndex = (nextTouchscreenIndex + 1) % 8; // Move to next entry
|
||||||
|
|
||||||
|
writeSharedMem<u16>(touchEntryOffset, touchScreenX);
|
||||||
|
writeSharedMem<u16>(touchEntryOffset + 2, touchScreenY);
|
||||||
|
writeSharedMem<u8>(touchEntryOffset + 4, touchScreenPressed ? 1 : 0);
|
||||||
|
|
||||||
// Next, update accelerometer state
|
// Next, update accelerometer state
|
||||||
if (nextAccelerometerIndex == 0) {
|
if (nextAccelerometerIndex == 0) {
|
||||||
|
|
120
src/emulator.cpp
120
src/emulator.cpp
|
@ -38,60 +38,86 @@ void Emulator::run() {
|
||||||
namespace Keys = HID::Keys;
|
namespace Keys = HID::Keys;
|
||||||
|
|
||||||
switch (event.type) {
|
switch (event.type) {
|
||||||
case SDL_QUIT:
|
case SDL_QUIT:
|
||||||
printf("Bye :(\n");
|
printf("Bye :(\n");
|
||||||
running = false;
|
running = false;
|
||||||
return;
|
return;
|
||||||
case SDL_KEYDOWN:
|
case SDL_KEYDOWN:
|
||||||
switch (event.key.keysym.sym) {
|
switch (event.key.keysym.sym) {
|
||||||
case SDLK_l: srv.pressKey(Keys::A); break;
|
case SDLK_l: srv.pressKey(Keys::A); break;
|
||||||
case SDLK_k: srv.pressKey(Keys::B); break;
|
case SDLK_k: srv.pressKey(Keys::B); break;
|
||||||
case SDLK_o: srv.pressKey(Keys::X); break;
|
case SDLK_o: srv.pressKey(Keys::X); break;
|
||||||
case SDLK_i: srv.pressKey(Keys::Y); break;
|
case SDLK_i: srv.pressKey(Keys::Y); break;
|
||||||
|
|
||||||
case SDLK_q: srv.pressKey(Keys::L); break;
|
case SDLK_q: srv.pressKey(Keys::L); break;
|
||||||
case SDLK_p: srv.pressKey(Keys::R); break;
|
case SDLK_p: srv.pressKey(Keys::R); break;
|
||||||
|
|
||||||
case SDLK_RIGHT: srv.pressKey(Keys::Right); break;
|
case SDLK_RIGHT: srv.pressKey(Keys::Right); break;
|
||||||
case SDLK_LEFT: srv.pressKey(Keys::Left); break;
|
case SDLK_LEFT: srv.pressKey(Keys::Left); break;
|
||||||
case SDLK_UP: srv.pressKey(Keys::Up); break;
|
case SDLK_UP: srv.pressKey(Keys::Up); break;
|
||||||
case SDLK_DOWN: srv.pressKey(Keys::Down); break;
|
case SDLK_DOWN: srv.pressKey(Keys::Down); break;
|
||||||
|
|
||||||
case SDLK_w: srv.setCirclepadY(0x9C); break;
|
case SDLK_w: srv.setCirclepadY(0x9C); break;
|
||||||
case SDLK_a: srv.setCirclepadX(-0x9C); break;
|
case SDLK_a: srv.setCirclepadX(-0x9C); break;
|
||||||
case SDLK_s: srv.setCirclepadY(-0x9C); break;
|
case SDLK_s: srv.setCirclepadY(-0x9C); break;
|
||||||
case SDLK_d: srv.setCirclepadX(0x9C); break;
|
case SDLK_d: srv.setCirclepadX(0x9C); break;
|
||||||
|
|
||||||
case SDLK_RETURN: srv.pressKey(Keys::Start); break;
|
case SDLK_RETURN: srv.pressKey(Keys::Start); break;
|
||||||
case SDLK_BACKSPACE: srv.pressKey(Keys::Select); 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<u16>(x) - 40;
|
||||||
|
u16 y_converted = static_cast<u16>(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 SDL_MOUSEBUTTONUP:
|
||||||
case SDLK_p: srv.releaseKey(Keys::R); break;
|
if (event.button.button == SDL_BUTTON_LEFT) {
|
||||||
|
srv.releaseTouchScreen();
|
||||||
case SDLK_RIGHT: srv.releaseKey(Keys::Right); break;
|
}
|
||||||
case SDLK_LEFT: srv.releaseKey(Keys::Left); break;
|
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update inputs in the HID module
|
// Update inputs in the HID module
|
||||||
|
|
Loading…
Add table
Reference in a new issue