v0.9.0 (v1.0 beta) (#338)

* move aurora to the aurora-wiicompiled submodule (#315)

* Update settings_overlay.cpp (#257)

* Simplify controller settings menu (#317)

* simplify controller settings menu

* platform pairing hint

* build for x86-64-v2 on older linux cpus (#319)

* Real Wii Remote support over Bluetooth (#323)

* pass real wii remotes through emulated bluetooth

* build bluetooth tests on macos ci

* address review comments

* cancel replaced bluetooth reads

* Run GX on its own thread (#325)

* NTSC-U and NTSC-J support (#326)

* add ntsc-u and ntsc-j support

Co-authored-by: DarthMDev <mgracer48@yahoo.com>
Co-authored-by: rooklz <rookieb@muzo-works.com>

* hash inc files and require project for shards

* port remaining stale rr us hooks

* drop map report generation

* drop one-off region porters

---------

Co-authored-by: DarthMDev <mgracer48@yahoo.com>
Co-authored-by: rooklz <rookieb@muzo-works.com>

* Keyboard input for friend code entry (#327)

* keyboard input for friend code entry

* add new guest imports to synthetic test

* replace per-address region table with range map (#328)

* paste friend codes from clipboard (#329)

* Verify dependency archive hashes (#330)

* verify dependency archive hashes

* verify cached cppwinrt tool

* check dependency path types

* Check CPU support before building (#331)

* check cpu support before building

* build for x86-64-v2 on windows and intel macs

* bump aurora for fog fsel fix

* add vsync option (#333)

* Add exe icons (#334)

* add exe icons

* rebuild icon resource on ico change

* drop icon rebuild tracking

* Fix bugs found in forks (#336)

* port fixes found in forks

* fill whole disk id

* dump kamek overlay on crash (#335)

* bump aurora and version to 0.9.0

---------

Co-authored-by: DarthMDev <mgracer48@yahoo.com>
Co-authored-by: rooklz <rookieb@muzo-works.com>
This commit is contained in:
patchzyy
2026-10-23 18:00:55 +02:00
committed by GitHub
parent 4c166a7eb1
commit ac99413d45
467 changed files with 72272 additions and 65657 deletions
+168
View File
@@ -0,0 +1,168 @@
#include "friend_code_keyboard.h"
#include "abi_bridge.h"
#include "guest_abi/guest_region.h"
#include "guest_function_imports.h"
#include "input_bindings.h"
#include "memory.h"
#include "runtime_product.h"
#include <SDL3/SDL_clipboard.h>
#include <SDL3/SDL_events.h>
#include <atomic>
#include <cstdint>
#include <mutex>
#include <optional>
#include <vector>
namespace {
// UI::RegisterFriendPage
constexpr uint32_t kDigitButtonsOffset = 0x44;
constexpr uint32_t kPushButtonSize = 0x254;
constexpr uint32_t kDigitButtonCount = 10;
constexpr uint32_t kButtonDigitOffset = 0x240;
constexpr uint32_t kPageStateOffset = 0x8;
constexpr uint32_t kPageStateActive = 4;
constexpr uint32_t kVtableGetTypeInfoOffset = 0x60;
constexpr int kBackspace = -1;
constexpr size_t kMaxPendingKeys = 32;
constexpr size_t kFriendCodeDigits = 12;
std::mutex g_pendingMutex;
std::vector<int> g_pending;
std::atomic_bool g_pageFocused{false};
bool IsPaste(const SDL_KeyboardEvent& key) {
return !key.repeat && key.key == SDLK_V && (key.mod & (SDL_KMOD_CTRL | SDL_KMOD_GUI)) != 0 &&
(key.mod & SDL_KMOD_ALT) == 0;
}
void AppendClipboardDigits(std::vector<int>& keys) {
char* text = SDL_GetClipboardText();
if (!text) {
return;
}
size_t digits = 0;
for (const char* c = text; *c && digits < kFriendCodeDigits; ++c) {
if (*c >= '0' && *c <= '9') {
keys.push_back(*c - '0');
++digits;
}
}
SDL_free(text);
}
std::optional<int> KeyValue(const SDL_KeyboardEvent& key) {
if ((key.mod & (SDL_KMOD_CTRL | SDL_KMOD_ALT | SDL_KMOD_GUI)) != 0) {
return std::nullopt;
}
if (key.scancode == SDL_SCANCODE_BACKSPACE) {
return kBackspace;
}
if (key.repeat) {
return std::nullopt;
}
if (key.scancode == SDL_SCANCODE_0 || key.scancode == SDL_SCANCODE_KP_0) {
return 0;
}
if (key.scancode >= SDL_SCANCODE_1 && key.scancode <= SDL_SCANCODE_9) {
return 1 + (key.scancode - SDL_SCANCODE_1);
}
if (key.scancode >= SDL_SCANCODE_KP_1 && key.scancode <= SDL_SCANCODE_KP_9) {
return 1 + (key.scancode - SDL_SCANCODE_KP_1);
}
return std::nullopt;
}
bool IsFocusedRegisterFriendPage(uint32_t page) {
try {
const uint32_t vtable = Memory::Read32(page);
return Memory::Read32(vtable + kVtableGetTypeInfoOffset) == MKW_GADDR(8061E804) &&
Memory::Read32(page + kPageStateOffset) == kPageStateActive;
} catch (const Memory::AccessViolation&) {
return false;
}
}
std::optional<uint32_t> DigitButton(uint32_t page, int digit) {
for (uint32_t i = 0; i < kDigitButtonCount; ++i) {
const uint32_t button = page + kDigitButtonsOffset + i * kPushButtonSize;
if (static_cast<int>(Memory::Read32(button + kButtonDigitOffset)) == digit) {
return button;
}
}
return std::nullopt;
}
void Type(CpuContext* ctx, uint32_t page, int key) {
if (key == kBackspace) {
ctx->gpr[3] = page;
MKW_GUEST_FUNC(8061E3B4)(ctx);
return;
}
const std::optional<uint32_t> button = DigitButton(page, key);
if (!button) {
return;
}
ctx->gpr[3] = page;
ctx->gpr[4] = *button;
ctx->gpr[5] = 0;
MKW_GUEST_FUNC(8061E348)(ctx);
}
} // namespace
namespace FriendCodeKeyboard {
void HandleEvents(const AuroraEvent* events) noexcept {
if (!events || !g_pageFocused.load(std::memory_order_acquire) || InputBindings::InputBlocked()) {
return;
}
std::vector<int> keys;
for (const AuroraEvent* ev = events; ev->type != AURORA_NONE; ++ev) {
if (ev->type != AURORA_SDL_EVENT || ev->sdl.type != SDL_EVENT_KEY_DOWN) {
continue;
}
if (IsPaste(ev->sdl.key)) {
AppendClipboardDigits(keys);
} else if (const std::optional<int> key = KeyValue(ev->sdl.key)) {
keys.push_back(*key);
}
}
if (keys.empty()) {
return;
}
std::lock_guard lock(g_pendingMutex);
for (const int key : keys) {
if (g_pending.size() >= kMaxPendingKeys) {
break;
}
g_pending.push_back(key);
}
}
} // namespace FriendCodeKeyboard
// Page::CheckActions, only ever called for the topmost page.
extern "C" void Page_CheckActions_80601c64(CpuContext* ctx) {
const uint32_t page = ctx->gpr[3];
MKW_GUEST_FUNC(80601C64)(ctx);
const bool focused = RuntimeProduct::IsRetroRewind() && IsFocusedRegisterFriendPage(page);
g_pageFocused.store(focused, std::memory_order_release);
std::vector<int> keys;
{
std::lock_guard lock(g_pendingMutex);
keys.swap(g_pending);
}
if (!focused || InputBindings::InputBlocked()) {
return;
}
for (const int key : keys) {
Type(ctx, page, key);
}
}
REGISTER_NATIVE_FUNCTION_AS(0x80601C64, Page_CheckActions_80601c64, "Page_CheckActions_80601c64");