Skip to content
Merged
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
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,11 @@ Some features that are a part of the SDL3 build:
fullscreen.
- **Screenshot capture** - F10 writes the framebuffer to disk.
- **Gamepad support** - cross-platform SDL_Gamepad mapped to the IIgs joystick.
A connected gamepad is used automatically (with hotplug); without one, the
numeric keypad emulates the joystick. The stick's circular travel is remapped
to the square range Apple joysticks have, so games can reach the corners.
Override either behavior in the config menu (F4) under Joystick
Configuration.
- **Terminal debugger** - a REPL for the built-in 65816 debugger from the
controlling terminal.
- **Drag-and-drop disk loading** - drop a disk image on the window and GSplus
Expand Down
5 changes: 5 additions & 0 deletions gsplus/src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,11 @@ add_executable(gsplus-sdl
)
target_link_libraries(gsplus-sdl PRIVATE gsplus_core_sdl SDL3::SDL3)

if(UNIX AND NOT APPLE)
# paddles.c uses sqrt(); glibc keeps it in libm
target_link_libraries(gsplus-sdl PRIVATE m)
endif()

if(APPLE)
# macOS-only: retune SDL's default menu bar so ⌘ combos pass through to the
# emulated IIgs and GSplus quits on ⌥⌘Q. The Objective-C source needs Cocoa.
Expand Down
2 changes: 1 addition & 1 deletion gsplus/src/adb.c
Original file line number Diff line number Diff line change
Expand Up @@ -2126,7 +2126,7 @@ adb_physical_key_update(Kimage *kimage_ptr, int raw_a2code, word32 unicode_c,
if(ascii > 0x30 && ascii <= 0x39) {
g_keypad_key_is_down[ascii - 0x30] = !is_up;
}
if(g_joystick_type == 0) {
if(paddle_effective_joystick_type() == 0) {
/* If Joystick type is keypad, then do not let these */
/* keypress pass on further, except for cmd/opt */
if(ascii == 0x30) {
Expand Down
8 changes: 6 additions & 2 deletions gsplus/src/config.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ extern word32 g_mem_size_exp;
extern int g_video_line_update_interval;
extern int g_user_halt_bad;
extern int g_joystick_type;
extern int g_joystick_square_range;
extern int g_joystick_scale_factor_x;
extern int g_joystick_scale_factor_y;
extern int g_joystick_trim_amount_x;
Expand Down Expand Up @@ -250,8 +251,11 @@ Cfg_menu g_cfg_newslot7_menu[] = {

Cfg_menu g_cfg_joystick_menu[] = {
{ "Joystick Configuration", g_cfg_joystick_menu, 0, 0, CFGTYPE_MENU },
{ "Joystick Emulation,0,Keypad Joystick,1,Mouse Joystick,2,Native Joystick 1,"
"3,Native Joystick 2", KNMP(g_joystick_type), CFGTYPE_INT },
{ "Joystick Emulation,4,Auto (Gamepad or Keypad),0,Keypad Joystick,"
"1,Mouse Joystick,2,Native Joystick 1,3,Native Joystick 2",
KNMP(g_joystick_type), CFGTYPE_INT },
{ "Gamepad Range,1,Square (Full Corners),0,Circular (Raw)",
KNMP(g_joystick_square_range), CFGTYPE_INT },
{ "Joystick Scale X,0x100,Standard,0x119,+10%,0x133,+20%,"
"0x150,+30%,0xb0,-30%,0xcd,-20%,0xe7,-10%",
KNMP(g_joystick_scale_factor_x), CFGTYPE_INT },
Expand Down
86 changes: 81 additions & 5 deletions gsplus/src/paddles.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
/**********************************************************************/

#include "defc.h"
#include <math.h>

extern int g_mouse_raw_x; /* from adb.c */
extern int g_mouse_raw_y;
Expand All @@ -21,7 +22,8 @@ int g_joystick_scale_factor_y = 0x100;
int g_joystick_trim_amount_x = 0;
int g_joystick_trim_amount_y = 0;

int g_joystick_type = 0; /* 0 = Keypad Joystick */
int g_joystick_type = 4; /* 4 = Auto (gamepad if present, else keypad) */
int g_joystick_square_range = 1; /* remap circular stick gate to square */
int g_joystick_native_type1 = -1;
int g_joystick_native_type2 = -1;
int g_joystick_native_type = -1;
Expand All @@ -35,17 +37,72 @@ dword64 g_paddle_dfcyc[4] = { 0, 0, 0, 0 };
/* g_paddle_dfcyc are the dfcyc the paddle goes to 0 */


#define STICK_DEADZONE 0.08 /* radial, as a fraction of full deflection */

void
paddle_map_circle_to_square(int *xptr, int *yptr)
{
double x, y, r, m, scale;

/* A modern gamepad stick travels in a circle, so a full diagonal
* only reaches ~71% on each axis and games expecting the square
* range of Apple joysticks never see the corners. Stretch each
* sample along its own direction -- identity on the axes, up to
* sqrt(2) at the diagonals -- so the circular rim lands exactly on
* the square's perimeter. */
x = *xptr / 32767.0;
y = *yptr / 32767.0;
r = sqrt((x * x) + (y * y));
if(r < STICK_DEADZONE) {
/* Radial deadzone: sticks do not rest at exactly 0, and the
* stretch below would amplify the drift */
*xptr = 0;
*yptr = 0;
return;
}
/* Rescale magnitude so travel is continuous at the deadzone edge */
scale = (r - STICK_DEADZONE) / (1.0 - STICK_DEADZONE);
x = (x / r) * scale;
y = (y / r) * scale;
m = (fabs(x) > fabs(y)) ? fabs(x) : fabs(y);
if(m > 0.0) {
x = x * (scale / m);
y = y * (scale / m);
}
/* Clamp: some pads overshoot the unit circle near the diagonals */
x = (x > 1.0) ? 1.0 : ((x < -1.0) ? -1.0 : x);
y = (y > 1.0) ? 1.0 : ((y < -1.0) ? -1.0 : y);
*xptr = (int)(x * 32767.0);
*yptr = (int)(y * 32767.0);
}

int
paddle_effective_joystick_type()
{
/* Auto (type 4) is resolved every time it's sampled, never stored:
* use the native joystick/gamepad if one is connected, else the
* keypad. g_joystick_native_type1 tracks hotplug, so connecting
* or removing a gamepad mid-game switches modes automatically. */
if(g_joystick_type == 4) {
return (g_joystick_native_type1 >= 0) ? 2 : 0;
}
return g_joystick_type;
}

void
paddle_fixup_joystick_type()
{
int type;

/* If g_joystick_type points to an illegal value, change it */
if(g_joystick_type == 2) {
type = paddle_effective_joystick_type();
if(type == 2) {
g_joystick_native_type = g_joystick_native_type1;
if(g_joystick_native_type1 < 0) {
g_joystick_type = 0;
}
}
if(g_joystick_type == 3) {
if(type == 3) {
g_joystick_native_type = g_joystick_native_type2;
if(g_joystick_native_type2 < 0) {
g_joystick_type = 0;
Expand All @@ -62,7 +119,7 @@ paddle_trigger(dword64 dfcyc)
/* Determine what all the paddle values are right now */
paddle_fixup_joystick_type();

switch(g_joystick_type) {
switch(paddle_effective_joystick_type()) {
case 0: /* Keypad Joystick */
paddle_trigger_keypad(dfcyc);
break;
Expand Down Expand Up @@ -121,15 +178,27 @@ void
paddle_update_trigger_dcycs(dword64 dfcyc)
{
dword64 trig_dfcyc;
int xy_val[2];
int val, paddle_num, scale, trim;
int i;

xy_val[0] = g_paddle_val[0];
xy_val[1] = g_paddle_val[1];
if(g_joystick_square_range &&
(paddle_effective_joystick_type() >= 2)) {
/* Work on a copy: some backends keep g_paddle_val[] between
* samples, so remapping in place would compound */
paddle_map_circle_to_square(&xy_val[0], &xy_val[1]);
}
for(i = 0; i < 4; i++) {
paddle_num = i;
if(g_swap_paddles) {
paddle_num = i ^ 1;
}
val = g_paddle_val[paddle_num];
if(paddle_num < 2) {
val = xy_val[paddle_num];
}
if(g_invert_paddles) {
val = -val;
}
Expand Down Expand Up @@ -183,5 +252,12 @@ void
paddle_update_buttons()
{
paddle_fixup_joystick_type();
joystick_update_buttons();
if(paddle_effective_joystick_type() >= 2) {
joystick_update_buttons();
} else {
/* In keypad/mouse modes a connected gamepad must not drive
* the buttons either (half-working input is confusing);
* also clears bits latched before a mode switch */
g_paddle_buttons &= ~3;
}
}
2 changes: 2 additions & 0 deletions gsplus/src/protos_base.h
Original file line number Diff line number Diff line change
Expand Up @@ -483,6 +483,8 @@ int read_vid_counters(int loc, dword64 dfcyc);


/* paddles.c */
void paddle_map_circle_to_square(int *xptr, int *yptr);
int paddle_effective_joystick_type(void);
void paddle_fixup_joystick_type(void);
void paddle_trigger(dword64 dfcyc);
void paddle_trigger_mouse(dword64 dfcyc);
Expand Down
2 changes: 1 addition & 1 deletion gsplus/src/vars_x86linux
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ OBJECTS1 = pulseaudio_driver.o xdriver.o
CCOPTS = -O2 -Wall -fomit-frame-pointer -DPULSE_AUDIO
NAME = gsplus
LD = $(CC)
EXTRA_LIBS = -lXext -lpulse
EXTRA_LIBS = -lXext -lpulse -lm
EXTRA_SPECIALS =

XOPTS = -I/usr/X11R6/include
Expand Down
Loading