mirror of
https://github.com/ARMSX2/ARMSX3.git
synced 2026-08-24 16:58:52 -07:00
Drop fast-forward from the in-game menu and the second screen
It stays a feature -- the hotkey, the touch button and the OSD indicator are untouched -- it just no longer occupies a tile in either panel. Removing it also repairs the Session grid's controller dispatch, which was broken. EmulationMenuViewModel indexes three things by the same number: the grid in SessionPane, actionCount(), and activateSelection(). Fast-forward sat at index 1 in the grid and had no entry in activateSelection, so every index from 1 up dispatched to its neighbour -- a pad press on Fast Forward restarted the game, Restart swapped the disc, Swap Disc closed the game, and Close could not be activated at all. actionCount had been corrected to 5 to let the pad reach the last tile, which made the misalignment reachable rather than fixing it. With the tile gone the grid is resume/restart/swap/close, exactly what activateSelection already dispatched, and actionCount goes to 4. Touch users are unaffected: the grid is tapped by index through onSelect, so it was always correct there. This only ever misfired for a controller.
This commit is contained in:
@@ -47,6 +47,7 @@ struct RPCSXApi {
|
||||
void (*surfaceSizeChanged)(int width, int height);
|
||||
void (*setPadSensor)(int port, int x, int y, int z, int g);
|
||||
int (*getPadRumble)(int port);
|
||||
void (*setThermals)(float cpu, float gpu, float battery, bool show);
|
||||
bool (*usbDeviceEvent)(int fd, int vendorId, int productId, int event);
|
||||
bool (*installFw)(JNIEnv *env, int fd, long progressId);
|
||||
bool (*isInstallableFile)(jint fd);
|
||||
@@ -161,6 +162,7 @@ struct RPCSXLibrary : RPCSXApi {
|
||||
result.surfaceSizeChanged = reinterpret_cast<decltype(surfaceSizeChanged)>(dlsym(handle, "_rpcsx_surfaceSizeChanged"));
|
||||
result.setPadSensor = reinterpret_cast<decltype(setPadSensor)>(dlsym(handle, "_rpcsx_setPadSensor"));
|
||||
result.getPadRumble = reinterpret_cast<decltype(getPadRumble)>(dlsym(handle, "_rpcsx_getPadRumble"));
|
||||
result.setThermals = reinterpret_cast<decltype(setThermals)>(dlsym(handle, "_rpcsx_setThermals"));
|
||||
result.usbDeviceEvent = reinterpret_cast<decltype(usbDeviceEvent)>(dlsym(handle, "_rpcsx_usbDeviceEvent"));
|
||||
result.installFw = reinterpret_cast<decltype(installFw)>(dlsym(handle, "_rpcsx_installFw"));
|
||||
result.isInstallableFile = reinterpret_cast<decltype(isInstallableFile)>(dlsym(handle, "_rpcsx_isInstallableFile"));
|
||||
@@ -506,6 +508,18 @@ extern "C" JNIEXPORT jint JNICALL Java_net_rpcsx_RPCSX_getPadRumble(
|
||||
return rpcsxLib.getPadRumble(port);
|
||||
}
|
||||
|
||||
// Device temperatures for the perf overlay. Discovery is the app's job -- Android exposes no
|
||||
// supported API for SoC temperatures, so it reads the thermal sysfs, whose zone naming and units
|
||||
// are vendor-specific -- and this only carries the result across.
|
||||
extern "C" JNIEXPORT void JNICALL Java_net_rpcsx_RPCSX_setThermals(
|
||||
JNIEnv *, jobject, jfloat cpu, jfloat gpu, jfloat battery, jboolean show) {
|
||||
if (rpcsxLib.setThermals == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
rpcsxLib.setThermals(cpu, gpu, battery, show == JNI_TRUE);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL Java_net_rpcsx_RPCSX_surfaceSizeChanged(
|
||||
JNIEnv *, jobject, jint width, jint height) {
|
||||
if (rpcsxLib.surfaceSizeChanged == nullptr) {
|
||||
|
||||
@@ -216,9 +216,6 @@ object SecondScreen {
|
||||
row1.addView(action(I18n.get("touch.stateAction.load")) {
|
||||
MainActivityRuntime.instance?.loadState()
|
||||
}, rowLp())
|
||||
row1.addView(action(I18n.get("secondScreen.fastForward")) {
|
||||
MainActivityRuntime.instance?.toggleFastForward()
|
||||
}, rowLp())
|
||||
row2.addView(action(I18n.get("secondScreen.pause")) {
|
||||
// Same toggle the on-screen pause button uses.
|
||||
if (MainActivityRuntime.eState.value == EmuState.PAUSED) MainActivityRuntime.resume()
|
||||
|
||||
@@ -636,12 +636,6 @@ private fun SessionPane(state: EmulationMenuUiState, viewModel: EmulationMenuVie
|
||||
ActionGrid(
|
||||
actions = listOf(
|
||||
MenuAction(str("action.resume"), str("action.play"), "▶", Success, viewModel::resume),
|
||||
MenuAction(
|
||||
str("action.fastForward"),
|
||||
if (MainActivityRuntime.fastForwardToggleActive) str("action.fastForward.on") else str("action.fastForward.detail"),
|
||||
"⏩",
|
||||
if (MainActivityRuntime.fastForwardToggleActive) Success else null,
|
||||
) { MainActivityRuntime.instance?.toggleFastForward(); viewModel.resume() },
|
||||
MenuAction(str("memcard.restart"), str("action.reset"), "↻", null, MainActivityRuntime::restart),
|
||||
MenuAction(str("action.swapDisc"), str("action.swapDisc.detail"), "⏏", null, MainActivityRuntime::promptSwapDisc),
|
||||
MenuAction(str("action.close"), MainActivityRuntime.currentGame.value?.title.orEmpty(), "■", Danger) {
|
||||
|
||||
+6
-3
@@ -381,9 +381,12 @@ class EmulationMenuViewModel(application: Application) : AndroidViewModel(applic
|
||||
}
|
||||
|
||||
private fun actionCount(tab: EmulationMenuTab): Int = when (tab) {
|
||||
// MUST match SessionPane's action list length. This was 4 against a list of 5, so the pad
|
||||
// could never reach Close at all.
|
||||
EmulationMenuTab.Session -> 5
|
||||
// MUST match SessionPane's action list length, AND activateSelection's Session branch
|
||||
// below -- all three are indexed by the same number and nothing checks they agree.
|
||||
// Fast-forward used to sit at index 1 in the grid but had no entry in activateSelection,
|
||||
// so every index from 1 up dispatched to its neighbour: a pad press on Fast Forward
|
||||
// restarted the game, and Close could not be activated at all.
|
||||
EmulationMenuTab.Session -> 4
|
||||
EmulationMenuTab.Graphics -> 2
|
||||
EmulationMenuTab.Fixes -> 0
|
||||
EmulationMenuTab.Performance -> 3
|
||||
|
||||
@@ -111,6 +111,13 @@ class RPCSX {
|
||||
|
||||
/** What the game is asking the rumble motors to do: (large shl 8) or small, each 0..255. */
|
||||
external fun getPadRumble(port: Int): Int
|
||||
|
||||
/**
|
||||
* Device temperatures for the perf overlay, in degrees Celsius, or Thermals.NONE for a
|
||||
* reading that could not be taken. Discovery is the app's job -- Android has no supported
|
||||
* API for SoC temperatures -- so the core is only ever told the answer.
|
||||
*/
|
||||
external fun setThermals(cpu: Float, gpu: Float, battery: Float, show: Boolean)
|
||||
external fun usbDeviceEvent(fd: Int, vendorId: Int, productId: Int, event: Int): Boolean
|
||||
external fun processCompilationQueue(): Boolean
|
||||
external fun startMainThreadProcessor(): Boolean
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "Emu/Io/pad_config_types.h"
|
||||
#include "Emu/RSX/Null/NullGSRender.h"
|
||||
#include "Emu/RSX/Overlays/overlay_manager.h"
|
||||
#include "Emu/RSX/Overlays/overlay_perf_metrics.h"
|
||||
#include "Emu/RSX/Overlays/overlay_save_dialog.h"
|
||||
#include "Emu/RSX/Overlays/overlay_trophy_notification.h"
|
||||
#include "Emu/RSX/Overlays/overlay_utils.h"
|
||||
@@ -4307,6 +4308,15 @@ extern "C" void _rpcsx_setPadSensor(int port, int x, int y, int z, int g) {
|
||||
// whenever it likes, and there is no notification to hook. The caller reads it on a
|
||||
// timer and drives the phone's vibrator. Returns 0 when nothing is running, so a
|
||||
// caller that keeps polling after the game stops simply sees silence.
|
||||
// Device temperatures, pushed from the app layer -- see the note in overlay_perf_metrics.h for
|
||||
// why discovery lives there and not here. Values are degrees Celsius, or the 'none' sentinel.
|
||||
extern "C" void _rpcsx_setThermals(float cpu, float gpu, float battery, bool show) {
|
||||
rsx::overlays::thermals::g_cpu = cpu;
|
||||
rsx::overlays::thermals::g_gpu = gpu;
|
||||
rsx::overlays::thermals::g_battery = battery;
|
||||
rsx::overlays::thermals::g_show = show;
|
||||
}
|
||||
|
||||
extern "C" int _rpcsx_getPadRumble(int port) {
|
||||
std::lock_guard lock(g_virtual_pad_mutex);
|
||||
|
||||
|
||||
@@ -640,6 +640,15 @@ namespace rsx
|
||||
fmt::append(perf_text, "%s%s", perf_text.empty() ? "" : "\n", lsfg);
|
||||
}
|
||||
|
||||
// Device temperatures, for the same reason and in the same place: appended after
|
||||
// the switch so every detail level gets them without four format strings and
|
||||
// their positional arguments having to agree. Empty when the option is off or no
|
||||
// zone was readable, so the overlay is unchanged for anyone it cannot serve.
|
||||
if (const std::string temps = thermals::status_text(); !temps.empty())
|
||||
{
|
||||
fmt::append(perf_text, "%s%s", perf_text.empty() ? "" : "\n", temps);
|
||||
}
|
||||
|
||||
m_body.set_text(perf_text);
|
||||
|
||||
if (perf_text.empty())
|
||||
@@ -940,6 +949,42 @@ namespace rsx
|
||||
return compiled_resources;
|
||||
}
|
||||
|
||||
namespace thermals
|
||||
{
|
||||
atomic_t<f32> g_cpu{none};
|
||||
atomic_t<f32> g_gpu{none};
|
||||
atomic_t<f32> g_battery{none};
|
||||
atomic_t<bool> g_show{false};
|
||||
|
||||
std::string status_text()
|
||||
{
|
||||
if (!g_show)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
std::string out;
|
||||
|
||||
// Whole degrees. A tenth is noise on a sysfs zone that updates every couple of
|
||||
// seconds, and this is read at a glance.
|
||||
const auto add = [&out](const char* label, f32 c)
|
||||
{
|
||||
if (c <= none)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
fmt::append(out, "%s%s %d\u00b0C", out.empty() ? "" : " ", label, static_cast<int>(c));
|
||||
};
|
||||
|
||||
add("CPU", g_cpu);
|
||||
add("GPU", g_gpu);
|
||||
add("BAT", g_battery);
|
||||
|
||||
return out;
|
||||
}
|
||||
}
|
||||
|
||||
extern void reset_performance_overlay()
|
||||
{
|
||||
if (!g_cfg.misc.use_native_interface)
|
||||
|
||||
@@ -113,5 +113,33 @@ namespace rsx
|
||||
};
|
||||
|
||||
void reset_performance_overlay();
|
||||
|
||||
// Device temperatures, pushed in from the Android app layer.
|
||||
//
|
||||
// The core cannot read these and should not learn how: Android has no supported API for
|
||||
// SoC temperatures (HardwarePropertiesManager is gated behind the signature-level
|
||||
// DEVICE_POWER), so the only route is the thermal sysfs, whose zone naming, ordering and
|
||||
// even units are vendor-specific. That discovery belongs in the app, which already deals
|
||||
// in Android specifics; this side just holds what it was told and prints it.
|
||||
//
|
||||
// Atomic because the writer is a UI-thread poll and the reader is the render thread.
|
||||
// Relaxed is fine: three independent display values with no ordering relationship to each
|
||||
// other or to anything else, and the worst a torn read can do is show one stale number
|
||||
// for one frame.
|
||||
namespace thermals
|
||||
{
|
||||
// Below any real temperature, so one comparison separates "could not read" from
|
||||
// "cold" without carrying a second flag per value. A device with no readable zone is
|
||||
// a normal outcome, not an error.
|
||||
constexpr f32 none = -1000.0f;
|
||||
|
||||
extern atomic_t<f32> g_cpu;
|
||||
extern atomic_t<f32> g_gpu;
|
||||
extern atomic_t<f32> g_battery;
|
||||
extern atomic_t<bool> g_show;
|
||||
|
||||
// "45°C GPU 43°C BAT 31°C", or empty when off or nothing is readable.
|
||||
std::string status_text();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user