Compare commits

..

5 Commits

Author SHA1 Message Date
patchzyy 4e73a51616 drop one-off region porters 2026-10-21 17:37:31 +02:00
patchzyy 7db64ea00a drop map report generation 2026-10-21 17:33:30 +02:00
patchzyy a222d02fbf port remaining stale rr us hooks 2026-10-21 16:49:54 +02:00
patchzyy 9dfbef00f5 hash inc files and require project for shards 2026-10-21 16:17:42 +02:00
patchzyy 5e337e6ecf add ntsc-u and ntsc-j support
Co-authored-by: DarthMDev <mgracer48@yahoo.com>
Co-authored-by: rooklz <rookieb@muzo-works.com>
2026-10-21 16:01:27 +02:00
6 changed files with 6 additions and 159 deletions
+6 -7
View File
@@ -54,14 +54,13 @@ foreach ($relative in $sourceFiles | Sort-Object -Unique) {
}
# One synthetic text section: li r3,40; addi r3,r3,2; nop; blr.
# Native HLE wrappers also call these guest symbols directly. Give each
# Native HLE wrappers also call these eight guest symbols directly. Give each
# its own generated blr function so the real product can link without game code.
# Keep this list explicit: a new unresolved guest dependency must fail the test.
[uint32]$entry = 0x80001000L
[uint32[]]$guestCallbacks = @(
0x8012B830L, 0x801A0620L, 0x801A1ED8L, 0x801A961CL,
0x801AADE0L, 0x801D8D30L, 0x801D9E94L, 0x8055531CL,
0x80601C64L, 0x8061E348L, 0x8061E3B4L
0x801AADE0L, 0x801D8D30L, 0x801D9E94L, 0x8055531CL
)
$textSize = [int]($guestCallbacks[-1] - $entry + 4)
$dataOffset = 0x100 + $textSize
@@ -76,9 +75,9 @@ Write-BigEndian32 0x00 0x100 # text[0] file offset
Write-BigEndian32 0x48 $entry # text[0] guest address
Write-BigEndian32 0x90 $textSize # text[0] length (unreachable gaps are zero)
Write-BigEndian32 0x1C $dataOffset # data[0] file offset
Write-BigEndian32 0x64 0x80700000L # data[0] guest address
Write-BigEndian32 0x64 0x80600000L # data[0] guest address
Write-BigEndian32 0xAC 4 # data[0] length
Write-BigEndian32 0xD8 0x80701000L # BSS address
Write-BigEndian32 0xD8 0x80601000L # BSS address
Write-BigEndian32 0xDC 32 # BSS length
Write-BigEndian32 0xE0 $entry # entry point
Write-BigEndian32 0x100 0x38600028 # li r3,40
@@ -103,8 +102,8 @@ project:
memory:
base: 0x80000000
size: 0x01800000
sda_base: 0x80700000
sda2_base: 0x80700000
sda_base: 0x80600000
sda2_base: 0x80600000
inputs:
dol:
path: synthetic.dol
-2
View File
@@ -1,6 +1,5 @@
#pragma once
#include "friend_code_keyboard.h"
#include "settings_overlay.h"
#include "runtime_config.h"
#include "gx_worker.h"
@@ -119,7 +118,6 @@ inline void ProcessAuroraEvents(const AuroraEvent* events) {
g_mkwDynamicAspectSurfacePending.store(true, std::memory_order_release);
}
settings_overlay::HandleEvents(events);
FriendCodeKeyboard::HandleEvents(events);
}
inline void ApplyPendingMkwDynamicAspectSurface() {
-8
View File
@@ -1,8 +0,0 @@
#pragma once
#include <aurora/event.h>
// Lets the keyboard type into Retro Rewind's friend code entry page.
namespace FriendCodeKeyboard {
void HandleEvents(const AuroraEvent* events) noexcept;
} // namespace FriendCodeKeyboard
-4
View File
@@ -729,10 +729,6 @@ MKW_GUEST_ADDRESS(805529A8, 8054CA50, 80552328) // THP::VideoDecoder
MKW_GUEST_ADDRESS(80552A74, 8054CB1C, 805523F4) // THP::VideoDecoderOnMemory
MKW_GUEST_ADDRESS(8055531C, 8054F2FC, 80554C9C) // RelProlog
MKW_GUEST_ADDRESS(805653D0, 80561050, 80564D50)
MKW_GUEST_ADDRESS(80601C64, 805DD384, 806013D8) // Page::CheckActions
MKW_GUEST_ADDRESS(8061E348, 805EE30C, 8061DABC) // Pages::RegisterFriend::OnDigitClick
MKW_GUEST_ADDRESS(8061E3B4, 805EE378, 8061DB28) // Pages::RegisterFriend::OnBackSpaceClick
MKW_GUEST_ADDRESS(8061E804, 805EE7C8, 8061DF78) // Pages::RegisterFriend::GetRuntimeTypeInfo
MKW_GUEST_ADDRESS(8088F400, 8088AFD0, 8088EA6C)
MKW_GUEST_ADDRESS(8088F704, 8088B2D4, 8088ED70)
MKW_GUEST_ADDRESS(8088FDB8, 8088B960, 8088F418)
-3
View File
@@ -8,6 +8,3 @@ MKW_GUEST_FUNCTION_IMPORT(801AADE0, 801AAD40, 801AAD00) // OS::__TimeToSystemTi
MKW_GUEST_FUNCTION_IMPORT(801D8D30, 801D8C90, 801D8C50) // NHTTPStartup
MKW_GUEST_FUNCTION_IMPORT(801D9E94, 801D9DF4, 801D9DB4) // NHTTPi_GetSystemInfoP
MKW_GUEST_FUNCTION_IMPORT(8055531C, 8054F2FC, 80554C9C) // RelProlog
MKW_GUEST_FUNCTION_IMPORT(80601C64, 805DD384, 806013D8) // Page::CheckActions
MKW_GUEST_FUNCTION_IMPORT(8061E348, 805EE30C, 8061DABC) // Pages::RegisterFriend::OnDigitClick
MKW_GUEST_FUNCTION_IMPORT(8061E3B4, 805EE378, 8061DB28) // Pages::RegisterFriend::OnBackSpaceClick
-135
View File
@@ -1,135 +0,0 @@
#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_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;
std::mutex g_pendingMutex;
std::vector<int> g_pending;
std::atomic_bool g_pageFocused{false};
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::lock_guard lock(g_pendingMutex);
for (const AuroraEvent* ev = events; ev->type != AURORA_NONE; ++ev) {
if (ev->type != AURORA_SDL_EVENT || ev->sdl.type != SDL_EVENT_KEY_DOWN) {
continue;
}
const std::optional<int> key = KeyValue(ev->sdl.key);
if (key && g_pending.size() < kMaxPendingKeys) {
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");