Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 18 additions & 9 deletions host/gpu/vulkan_renderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -421,6 +421,10 @@ struct PadTuning {
bool trace{false};
};

// The SceCtrlButtons bit the game confirms with: the console's confirm
// button, as sceUtilityGetSystemParamInt reports it (0 circle, 1 cross).
std::uint32_t confirm_button_bit() { return portablekit::game().confirm_button == 1u ? 0x4000u : 0x2000u; }

// Read on every poll, so the in-game menu's changes apply at once.
PadTuning pad_tuning() {
static const bool trace = portablekit::env("TRACE_PAD") != nullptr;
Expand All @@ -435,8 +439,7 @@ PadTuning pad_tuning() {
value.right_stick_mode = player.right_stick;
value.invert_x = player.invert_camera_x;
value.invert_y = player.invert_camera_y;
// A PlayStation pad already carries the PSP's own face buttons, so the
// positional mapping puts confirm on circle where the prompts want it.
// Which face button presses the game's confirm button; see read_gamepad.
value.confirm_south = player.confirm_south;
value.trace = trace;
return value;
Expand All @@ -460,10 +463,15 @@ void read_gamepad(SDL_Gamepad *device, PadState &pad, int &analog_x, int &analog
held(SDL_GAMEPAD_BUTTON_BACK, 0x0001u);
held(SDL_GAMEPAD_BUTTON_NORTH, 0x1000u);
held(SDL_GAMEPAD_BUTTON_WEST, 0x8000u);
// The game prompts "circle Enter / cross Back", and on a PlayStation pad
// those are the same two buttons in the same two places.
held(SDL_GAMEPAD_BUTTON_SOUTH, tuning.confirm_south ? 0x2000u : 0x4000u);
held(SDL_GAMEPAD_BUTTON_EAST, tuning.confirm_south ? 0x4000u : 0x2000u);
// The game confirms with the button the console's setting names (circle
// on a Japanese console, cross elsewhere) and goes back with the other.
// The player's setting says which of south and east confirms, so on a
// PlayStation pad the buttons land where the game's prompts show them
// whenever the setting matches the console.
const std::uint32_t confirm = confirm_button_bit();
const std::uint32_t back = confirm ^ 0x6000u;
held(SDL_GAMEPAD_BUTTON_SOUTH, tuning.confirm_south ? confirm : back);
held(SDL_GAMEPAD_BUTTON_EAST, tuning.confirm_south ? back : confirm);

// The PSP triggers are digital, and games hold L or R for long stretches,
// so the analog triggers press the same bits as the shoulders.
Expand Down Expand Up @@ -1686,8 +1694,9 @@ struct VulkanRenderer::Impl {
gamepad_id = id;
const char *name = SDL_GetGamepadName(device);
const PadTuning tuning = pad_tuning();
std::cout << "[pad] " << (name != nullptr ? name : "gamepad") << " connected; confirm on "
<< (tuning.confirm_south ? "the south button" : "circle") << ", right stick "
std::cout << "[pad] " << (name != nullptr ? name : "gamepad") << " connected; confirm ("
<< (confirm_button_bit() == 0x4000u ? "cross" : "circle") << ") on the "
<< (tuning.confirm_south ? "south" : "east") << " button, right stick "
<< (tuning.right_stick_mode == settings::RightStick::DPad ? "as D-pad"
: tuning.right_stick_mode == settings::RightStick::Camera ? "as camera"
: "off")
Expand Down Expand Up @@ -4762,7 +4771,7 @@ void VulkanRenderer::Impl::sample_pad(bool focused) {
}();
if (auto_confirm != 0u) {
const std::uint64_t phase = impl_->frames % auto_confirm;
if (phase < auto_confirm / 8u) pad.buttons |= 0x2000u; // circle
if (phase < auto_confirm / 8u) pad.buttons |= confirm_button_bit();
}
// Buttons held when the game got its input back stay hidden from it until
// they are released.
Expand Down
16 changes: 15 additions & 1 deletion host/hle/hle_system.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,13 @@ std::uint64_t guest_unix_us() { return boot_unix_us() + kernel().now_us(); }

void success(Runtime &, AllegrexContext &ctx) { kernel().finish(ctx, 0u); }

// The console settings a game asks for and tells the system, under
// TRACE_KERNEL: which language and which confirm button it ends up using.
bool trace_system_params() {
static const bool enabled = portablekit::env("TRACE_KERNEL") != nullptr;
return enabled;
}

void register_utils(HleRegistrar &hle) {
// The host has no data cache to keep coherent. Phantasy Star Portable 2
// Infinity (NPJH50332) uses WritebackInvalidateRange.
Expand Down Expand Up @@ -243,7 +250,12 @@ void register_platform(HleRegistrar &hle) {
log_once("npdrm-edata", "[npdrm] sceNpDrmEdataSetupKey (UNVERIFIED: no game traced yet)");
kernel().finish(ctx, 0u);
});
hle.add("sceImpose", "sceImposeSetLanguageMode", success);
hle.add("sceImpose", "sceImposeSetLanguageMode", [](Runtime &, AllegrexContext &ctx) {
if (trace_system_params())
std::cout << "[sysparam] sceImposeSetLanguageMode language=" << arg(ctx, 0) << " button=" << arg(ctx, 1)
<< "\n";
kernel().finish(ctx, 0u);
});
// (int *language, int *button): the console's, as GetSystemParamInt says.
hle.add("sceImpose", "sceImposeGetLanguageMode", [](Runtime &rt, AllegrexContext &ctx) {
if (arg(ctx, 0) != 0u) rt.memory().store32(arg(ctx, 0), portablekit::game().system_language);
Expand Down Expand Up @@ -283,6 +295,8 @@ void register_platform(HleRegistrar &hle) {
case 9u: value = portablekit::game().confirm_button; break;
default: break;
}
if (trace_system_params())
std::cout << "[sysparam] sceUtilityGetSystemParamInt id=" << arg(ctx, 0) << " -> " << value << "\n";
rt.memory().store32(arg(ctx, 1), value);
kernel().finish(ctx, 0u);
});
Expand Down
4 changes: 2 additions & 2 deletions host/input/bindings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,8 @@ constexpr const char *kSeparator = " / ";

constexpr ActionInfo kInfo[kActions] = {
{"stick_up", "Move forward"}, {"stick_left", "Move left"}, {"stick_down", "Move back"},
{"stick_right", "Move right"}, {"triangle", "△"}, {"circle", "○ (confirm)"},
{"cross", "× (back)"}, {"square", "□"}, {"l", "L"},
{"stick_right", "Move right"}, {"triangle", "△"}, {"circle", "○"},
{"cross", "×"}, {"square", "□"}, {"l", "L"},
{"r", "R"}, {"start", "START"}, {"select", "SELECT"},
{"dpad_up", "D-pad up"}, {"dpad_left", "D-pad left"}, {"dpad_down", "D-pad down"},
{"dpad_right", "D-pad right"}, {"camera_up", "Camera up"}, {"camera_left", "Camera left"},
Expand Down
3 changes: 3 additions & 0 deletions host/settings/settings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -461,6 +461,9 @@ std::string game_default_name() {

Settings defaults_for(Platform platform) {
Settings values{};
// Confirm where a console of the game's region has it: cross, the south
// button, outside Japan; circle, the east button, in Japan.
values.confirm_south = game().confirm_button == 1u;
if (platform == Platform::Android) {
values.aspect = Aspect::Fill;
values.fullscreen = true;
Expand Down
5 changes: 4 additions & 1 deletion host/settings/settings.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,10 @@ struct Settings {
bool mute{};

// Controls
bool confirm_south{}; // confirm (circle) on the south face button
// The game's confirm button on the south face button rather than the
// east one. The default follows the console the profile describes: south
// where cross confirms, east where circle does.
bool confirm_south{};
float dead_zone{0.15f};
float trigger{0.25f};
// What LT/RT (L2/R2) press past the trigger point: 0 is L and R like the
Expand Down
2 changes: 1 addition & 1 deletion host/ui/input_script.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ void sort_steps(State &s) {
}

// Reads the lines appended to the live file since the last call. Their frames
// count from now, so a line `30:pad a` presses ○ half a second after it is read.
// count from now, so a line `30:pad a` presses the south button half a second after it is read.
void read_live(State &s) {
std::ifstream file(s.live_path, std::ios::binary);
if (!file) return;
Expand Down
16 changes: 12 additions & 4 deletions host/ui/menu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -586,9 +586,12 @@ void Menu::controls() {
info_row("Connected", pad == nullptr ? "No gamepad; the keyboard and mouse drive the game"
: (name != nullptr ? name : "Gamepad"));
}
if (choice_row("Confirm button", s.confirm_south ? "Bottom (Western)" : "Right, ○ (Japanese)",
options_for("input.confirm", "Which face button confirms, in the game and in this menu. The "
"game's prompts show ○ to confirm and × to go back."))) {
const bool cross_confirms = portablekit::game().confirm_button == 1u;
if (choice_row("Confirm button", s.confirm_south ? "Bottom (Western)" : "Right (Japanese)",
options_for("input.confirm",
std::string("Which face button confirms, in the game and in this menu. The game's "
"prompts show ") +
(cross_confirms ? "× to confirm and ○ to go back." : "○ to confirm and × to go back.")))) {
s.confirm_south = !s.confirm_south;
settings::save();
}
Expand Down Expand Up @@ -788,7 +791,12 @@ void Menu::controls() {
const RowOptions o{false, {},
"Press a key or a mouse button to add it, or one it has already to remove it; Esc "
"cancels. A key taken from another control leaves that one."};
if (value_row(input::info(action).label, value, o) && !binding_) {
std::string label = input::info(action).label;
// The game's confirm and back buttons, as the console says.
const bool cross_confirms = portablekit::game().confirm_button == 1u;
if (action == input::Action::Circle) label += cross_confirms ? " (back)" : " (confirm)";
if (action == input::Action::Cross) label += cross_confirms ? " (confirm)" : " (back)";
if (value_row(label.c_str(), value, o) && !binding_) {
binding_ = action;
layer.begin_binding_capture();
}
Expand Down
Loading