Skip to content

Commit

Permalink
Analog button and keyboard tester.
Browse files Browse the repository at this point in the history
Added analog button indication for those buttons that may have use for it
- primarily L2/R2, but support was added for all buttons where at least
one controller is known to support it.

Added a keyboard tester screen which includes a standard 102-key PC
keyboard + extra blocks for all RETROK_ values present in the code.
Screen adapted from DOSBox-Pure onscreen keyboard with permission.
Keyboard button A+B switches between the two screens. Keyboard
inputs are not set up for remote transmission, only for local test.
  • Loading branch information
zoltanvb committed Mar 29, 2024
1 parent 83d6cc5 commit 30e01cf
Show file tree
Hide file tree
Showing 2 changed files with 505 additions and 72 deletions.
238 changes: 189 additions & 49 deletions cores/libretro-net-retropad/net_retropad_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
* - Allow changing IP address and port in runtime
* - Input recording / Combos
* - Enable test input loading from menu
* - Visualization of keyboard and aux inputs (gyro, accelero, light)
* - Visualization of aux inputs (gyro, accelero, light)
*/

#include <stdio.h>
Expand Down Expand Up @@ -50,14 +50,17 @@

#define DESC_OFFSET(desc, port, index, id) ( \
port * ((desc)->index_max - (desc)->index_min + 1) * ((desc)->id_max - (desc)->id_min + 1) + \
index * ((desc)->id_max - (desc)->id_min + 1) + \
(index - (desc)->index_min) * ((desc)->id_max - (desc)->id_min + 1) + \
id \
)

#define MAX_TEST_STEPS 200
#define INITIAL_FRAMES 60*5
#define ONE_TEST_STEP_FRAMES 60*5

#define NETRETROPAD_SCREEN_PAD 0
#define NETRETROPAD_SCREEN_KEYBOARD 1

struct descriptor {
int device;
int port_min;
Expand All @@ -77,6 +80,9 @@ struct remote_joypad_message {
uint16_t state;
};

static bool keyboard_state[RETROK_LAST];
static bool keyboard_state_validated[RETROK_LAST];

static int s;
static int port;
static char server[64];
Expand Down Expand Up @@ -114,9 +120,20 @@ static struct descriptor analog = {
.id_max = RETRO_DEVICE_ID_ANALOG_Y
};

static struct descriptor analog_button = {
.device = RETRO_DEVICE_ANALOG,
.port_min = 0,
.port_max = 0,
.index_min = RETRO_DEVICE_INDEX_ANALOG_BUTTON,
.index_max = RETRO_DEVICE_INDEX_ANALOG_BUTTON,
.id_min = RETRO_DEVICE_ID_JOYPAD_B,
.id_max = RETRO_DEVICE_ID_JOYPAD_R3
};

static struct descriptor *descriptors[] = {
&joypad,
&analog
&analog,
&analog_button
};

static uint16_t combo_def[] =
Expand All @@ -137,6 +154,8 @@ static uint16_t combo_def[] =
1 << RETRO_DEVICE_ID_JOYPAD_L2 | 1 << RETRO_DEVICE_ID_JOYPAD_R2
};

static unsigned current_screen = NETRETROPAD_SCREEN_PAD;

typedef struct
{
unsigned expected_button;
Expand Down Expand Up @@ -338,33 +357,64 @@ static bool input_test_file_read(const char* file_path)
/* Test input file handling end */
/********************************/

void NETRETROPAD_CORE_PREFIX(retro_init)(void)
static void draw_background(void)
{
unsigned i;

dump_state_blocked = false;
frame_buf = (uint16_t*)calloc(320 * 240, sizeof(uint16_t));

if (frame_buf)
{
unsigned rle, runs, count;
/* Body is 255 * 142 within the 320 * 240 frame */
uint16_t *pixel = frame_buf + 49 * 320 + 32;

for (rle = 0; rle < sizeof(body); )
{
uint16_t color = 0;

for (runs = body[rle++]; runs > 0; runs--)
if (current_screen == NETRETROPAD_SCREEN_PAD)
for (rle = 0; rle < sizeof(body); )
{
for (count = body[rle++]; count > 0; count--)
*pixel++ = color;
uint16_t color = 0;

for (runs = body[rle++]; runs > 0; runs--)
{
for (count = body[rle++]; count > 0; count--)
*pixel++ = color;

color = 0x4208 - color;
}

color = 0x4208 - color;
pixel += 65;
}
else if (current_screen == NETRETROPAD_SCREEN_KEYBOARD)
for (rle = 0; rle < sizeof(keyboard_body); )
{
uint16_t color = 0;

pixel += 65;
}
for (runs = keyboard_body[rle++]; runs > 0; runs--)
{
for (count = keyboard_body[rle++]; count > 0; count--)
*pixel++ = color;

color = 0x4208 - color;
}

pixel += 65;
}
}
}

static void flip_screen(void)
{
if (current_screen == NETRETROPAD_SCREEN_PAD)
current_screen = NETRETROPAD_SCREEN_KEYBOARD;
else if (current_screen == NETRETROPAD_SCREEN_KEYBOARD)
current_screen = NETRETROPAD_SCREEN_PAD;
draw_background();
}

void NETRETROPAD_CORE_PREFIX(retro_init)(void)
{
unsigned i;

dump_state_blocked = false;
frame_buf = (uint16_t*)calloc(320 * 240, sizeof(uint16_t));

draw_background();

/* Allocate descriptor values */
for (i = 0; i < ARRAY_SIZE(descriptors); i++)
Expand Down Expand Up @@ -430,6 +480,25 @@ void NETRETROPAD_CORE_PREFIX(retro_get_system_av_info)(
info->geometry.aspect_ratio = 4.0 / 3.0;
}

static void NETRETROPAD_CORE_PREFIX(update_keyboard_cb)(bool down, unsigned keycode,
uint32_t character, uint16_t key_modifiers)
{
struct retro_message message;
char buf[255];

if (keycode < RETROK_LAST)
{
keyboard_state[keycode] = down ? true : false;
if (down && ((keycode == RETROK_a && keyboard_state[RETROK_b]) || (keycode == RETROK_b && keyboard_state[RETROK_a])))
flip_screen();
/* TODO: message only for the bottom blocks, with key name */
snprintf(buf, sizeof(buf), "Key pressed: %d",keycode);
message.msg = buf;
message.frames = 60;
NETRETROPAD_CORE_PREFIX(environ_cb)(RETRO_ENVIRONMENT_SET_MESSAGE, &message);
}
}

static void retropad_update_input(void)
{
unsigned i;
Expand Down Expand Up @@ -504,6 +573,8 @@ void NETRETROPAD_CORE_PREFIX(retro_set_environment)(retro_environment_t cb)
{ NULL, NULL },
};
enum retro_pixel_format fmt = RETRO_PIXEL_FORMAT_RGB565;
struct retro_keyboard_callback kcb = { NETRETROPAD_CORE_PREFIX(update_keyboard_cb) };

cb(RETRO_ENVIRONMENT_SET_VARIABLES, (void*)vars);

NETRETROPAD_CORE_PREFIX(environ_cb) = cb;
Expand All @@ -514,6 +585,9 @@ void NETRETROPAD_CORE_PREFIX(retro_set_environment)(retro_environment_t cb)

if (cb(RETRO_ENVIRONMENT_GET_LOG_INTERFACE, &logger))
NETRETROPAD_CORE_PREFIX(log_cb) = logger.log;

NETRETROPAD_CORE_PREFIX(environ_cb)(RETRO_ENVIRONMENT_SET_KEYBOARD_CALLBACK, &kcb);

}

static void netretropad_check_variables(void)
Expand Down Expand Up @@ -683,54 +757,120 @@ void NETRETROPAD_CORE_PREFIX(retro_run)(void)
}
}
/* Input test section end. */

for (rle = 0; rle < sizeof(retropad_buttons); )
if (current_screen == NETRETROPAD_SCREEN_PAD)
{
unsigned runs;
char paint = 0;

for (runs = retropad_buttons[rle++]; runs > 0; runs--)
for (rle = 0; rle < sizeof(retropad_buttons); )
{
unsigned button = paint ? 1 << retropad_buttons[rle++] : 0;
unsigned runs;
char paint = 0;

if (paint)
for (runs = retropad_buttons[rle++]; runs > 0; runs--)
{
unsigned count;
uint16_t color;
unsigned button = 0;
unsigned button_analog = 0;
int offset;
if (paint)
{
/* 0 - 15: buttons, 16 - 31: analog x/y */
/* 32 - 47: analog input for same buttons */
if (retropad_buttons[rle] < 32)
button = paint ? 1 << retropad_buttons[rle] : 0;
else
{
button_analog = paint ? 1 << (retropad_buttons[rle] - 32) : 0;
offset = DESC_OFFSET(&analog_button, 0, RETRO_DEVICE_INDEX_ANALOG_BUTTON, retropad_buttons[rle] - 32);
}
rle++;
}

/* Red for active inputs */
if (input_state & button)
if (paint)
{
color = 0xA000;
input_state_validated |= button;
unsigned count;
uint16_t color;

/* Red for active inputs */
if (input_state & button)
{
color = 0xA000;
input_state_validated |= button;
}
/* Red gradient for active analog button inputs, from 0 to 0xa000 */
else if (button_analog && (int16_t)analog_button.value[offset] > 3276)
{
color = (uint16_t)((int16_t)analog_button.value[offset]/1638) << 11;
}
else
{
/* Light blue for expected input */
if (expected_input & button || expected_input & button_analog)
color = 0x7fff;
/* Light green for already validated input */
else if (input_state_validated & button || input_state_validated & button_analog)
color = 0xbff7;
/* White as default */
else
color = 0xffff;
}

for (count = retropad_buttons[rle++]; count > 0; count--)
*pixel++ = color;
}
else
pixel += retropad_buttons[rle++];

paint = !paint;
}

pixel += 65;
}
}
else if (current_screen == NETRETROPAD_SCREEN_KEYBOARD)
{
for (rle = 0; rle < (sizeof(keyboard_buttons)/sizeof(keyboard_buttons[0])); )
{
unsigned runs;
char paint = 0;

for (runs = keyboard_buttons[rle++]; runs > 0; runs--)
{
unsigned button = 0;
unsigned button_analog = 0;
int offset;

if (paint)
{
/* Light blue for expected input */
if (expected_input & button)
color = 0x7fff;
/* Light green for already validated input */
else if (input_state_validated & button )
color = 0xbff7;
/* White as default */
unsigned count;
uint16_t color;

/* Red for active inputs */
if (keyboard_state[keyboard_buttons[rle]])
{
color = 0xA000;
keyboard_state_validated[keyboard_buttons[rle]] = true;
}
else
color = 0xffff;
{
if (keyboard_state_validated[keyboard_buttons[rle]])
color = 0xbff7;
else
color = 0xffff;
}
rle++;

for (count = keyboard_buttons[rle++]; count > 0; count--)
*pixel++ = color;
}
else
pixel += keyboard_buttons[rle++];

for (count = retropad_buttons[rle++]; count > 0; count--)
*pixel++ = color;
paint = !paint;
}
else
pixel += retropad_buttons[rle++];

paint = !paint;
pixel += 65;
}

pixel += 65;
}

NETRETROPAD_CORE_PREFIX(video_cb)(frame_buf, 320, 240, 640);

retro_sleep(4);
}

Expand Down
Loading

0 comments on commit 30e01cf

Please sign in to comment.