Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Joypad subsystem #430

Merged
merged 49 commits into from
Sep 15, 2023
Merged
Show file tree
Hide file tree
Changes from 34 commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
cb11e21
Update old examples to use n64.mk
meeq Sep 1, 2023
df0b5fe
Fix dfsdemo Makefile CFLAGS and LDFLAGS
meeq Sep 2, 2023
fb8e077
Refactor examples Makefile to use template macro
meeq Sep 1, 2023
34cc885
Cleanup customfont example
meeq Sep 2, 2023
c35b396
Cleanup examples Makefile to include all subdirectories
meeq Sep 2, 2023
bc455ba
Rename joybusinternal.h to joybus_internal.h
meeq Sep 1, 2023
1452c01
Cleanup joybus.c includes
meeq Sep 1, 2023
253cfd5
Fix unknown type name 'uint32_t' in interrupt.h
meeq Sep 1, 2023
172debc
Use refcount for timer_init/close
meeq Sep 1, 2023
f6d15c0
Copy joypad subsystem from meeq/joypadtest repository
meeq Aug 23, 2023
de2b931
Integrate, refactor, and document Joypad subsystem
meeq Sep 1, 2023
c210a87
Include joypadtest example
meeq Sep 1, 2023
c19ae2b
Refactor inspector to use Joypad subsystem
meeq Sep 1, 2023
80db15a
Deprecate Controller subsystem; reimplement it using Joypad subsystem
meeq Sep 1, 2023
95d408a
Merge branch 'unstable' into joypad-subsystem
meeq Sep 5, 2023
6357b4a
Feedback: Remove unnecessary usage of "N64" in Joypad subsystem
meeq Sep 5, 2023
b45c166
Feedback: move ASSERT_JOYPAD_PORT_VALID to internal header
meeq Sep 5, 2023
c2d0d6d
Feedback: move joypad_read_n64_inputs_sync to internal header
meeq Sep 5, 2023
ed85655
Feedback: remove defensive joypad_read_count check
meeq Sep 5, 2023
dc2f2ca
Feedback: make buttons substruct of joypad_inputs_t private
meeq Sep 5, 2023
01e762c
Fix: remove unnecessary display_init from joypadtest example
meeq Sep 5, 2023
dc65d58
Feedback: deprecate execute_raw_command, introduce Game ID send/clear…
meeq Sep 5, 2023
d25e502
Fix: close out Joybus operation block in joybus_accessory_write_sync
meeq Sep 5, 2023
b627f33
Fix: Remove `static inline` from joybus_clear_game_id
meeq Sep 5, 2023
db31e69
Follow-up: Refactor execute_raw_command into joybus_send_command
meeq Sep 5, 2023
30cf1d3
Cleanup controller subsystem deprecation
meeq Sep 5, 2023
5c8b70e
Rename joybus_send_command to joybus_exec_command
meeq Sep 5, 2023
e287660
Remove duplicate shim for execute_raw_command
meeq Sep 5, 2023
e696f01
Refactor joybus_command structs
meeq Sep 6, 2023
6753d90
Resolve deprecation warnings in mempak and tpak subsystems
meeq Sep 6, 2023
e6045b4
Move joypad function docs into headers
meeq Sep 6, 2023
66e9d81
Move joypad module docs to header
meeq Sep 6, 2023
0c34d29
Remove backreference to controller subsystem in joypad subystem docs
meeq Sep 6, 2023
4b5917a
Feedback: Joypad identify interval should use TICKS_READ
meeq Sep 6, 2023
cecc953
Refactor Joybus exec command public API
meeq Sep 11, 2023
78b3c2d
Cleanup joybus_accessory public API
meeq Sep 11, 2023
a9a85eb
Adopt Rasky's optimized CRC8 algorithm implementation
meeq Sep 11, 2023
b97ad21
Rename joypad_scan to joypad_poll
meeq Sep 11, 2023
2194859
Cleanup joypad synchronous function naming
meeq Sep 12, 2023
6b932aa
Fix missing refactor of joypad_reset
meeq Sep 12, 2023
de2b018
Lift Joybus + Joypad documentation into headers
meeq Sep 12, 2023
dd7a9e8
Merge branch 'unstable' into joypad-subsystem
meeq Sep 12, 2023
03e9642
Refactor PixelFX Joybus commands into their own module
meeq Sep 12, 2023
cc38716
Revert unused Doxygen GENERATE_DEPRECATEDLIST = YES
meeq Sep 13, 2023
5cd5c24
Incorporate Rasky's feedback on joypad_get_direction
meeq Sep 13, 2023
ab3499d
Restore joypad_get_stick_direction doc block
meeq Sep 13, 2023
a8a5964
Feedback: Improve joypad documentation for GameCube controllers
meeq Sep 13, 2023
54c832f
Merge branch 'unstable' into joypad-subsystem
meeq Sep 13, 2023
3cde0c6
Merge branch 'unstable' into joypad-subsystem
meeq Sep 15, 2023
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
6 changes: 5 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,10 @@ libdragon.a: $(BUILD_DIR)/n64sys.o $(BUILD_DIR)/interrupt.o $(BUILD_DIR)/backtra
$(BUILD_DIR)/debug.o $(BUILD_DIR)/debugcpp.o $(BUILD_DIR)/usb.o $(BUILD_DIR)/libcart/cart.o $(BUILD_DIR)/fatfs/ff.o \
$(BUILD_DIR)/fatfs/ffunicode.o $(BUILD_DIR)/rompak.o $(BUILD_DIR)/dragonfs.o \
$(BUILD_DIR)/audio.o $(BUILD_DIR)/display.o $(BUILD_DIR)/surface.o \
$(BUILD_DIR)/console.o $(BUILD_DIR)/joybus.o $(BUILD_DIR)/asset.o \
$(BUILD_DIR)/console.o $(BUILD_DIR)/asset.o \
$(BUILD_DIR)/compress/lzh5.o $(BUILD_DIR)/compress/lz4_dec.o $(BUILD_DIR)/compress/ringbuf.o \
$(BUILD_DIR)/joybus.o $(BUILD_DIR)/joybus_accessory.o \
$(BUILD_DIR)/joypad.o $(BUILD_DIR)/joypad_accessory.o \
$(BUILD_DIR)/controller.o $(BUILD_DIR)/rtc.o \
$(BUILD_DIR)/eeprom.o $(BUILD_DIR)/eepromfs.o $(BUILD_DIR)/mempak.o \
$(BUILD_DIR)/tpak.o $(BUILD_DIR)/graphics.o $(BUILD_DIR)/rdp.o \
Expand Down Expand Up @@ -124,6 +126,8 @@ install: install-mk libdragon
install -Cv -m 0644 include/usb.h $(INSTALLDIR)/mips64-elf/include/usb.h
install -Cv -m 0644 include/console.h $(INSTALLDIR)/mips64-elf/include/console.h
install -Cv -m 0644 include/joybus.h $(INSTALLDIR)/mips64-elf/include/joybus.h
install -Cv -m 0644 include/joybus_accessory.h $(INSTALLDIR)/mips64-elf/include/joybus_accessory.h
install -Cv -m 0644 include/joypad.h $(INSTALLDIR)/mips64-elf/include/joypad.h
install -Cv -m 0644 include/mempak.h $(INSTALLDIR)/mips64-elf/include/mempak.h
install -Cv -m 0644 include/controller.h $(INSTALLDIR)/mips64-elf/include/controller.h
install -Cv -m 0644 include/rtc.h $(INSTALLDIR)/mips64-elf/include/rtc.h
Expand Down
2 changes: 1 addition & 1 deletion doxygen-public.conf
Original file line number Diff line number Diff line change
Expand Up @@ -700,7 +700,7 @@ GENERATE_BUGLIST = NO
# the documentation.
# The default value is: YES.

GENERATE_DEPRECATEDLIST= NO
GENERATE_DEPRECATEDLIST = YES

# The ENABLED_SECTIONS tag can be used to enable conditional documentation
# sections, marked by \if <section_label> ... \endif and \cond <section_label>
Expand Down
1 change: 1 addition & 0 deletions examples/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ EXAMPLES += customfont
EXAMPLES += eepromfstest
EXAMPLES += fontdemo
EXAMPLES += gldemo
EXAMPLES += joypadtest
EXAMPLES += loadspritefromsd
EXAMPLES += mixertest
EXAMPLES += mptest
Expand Down
17 changes: 17 additions & 0 deletions examples/joypadtest/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
all: joypadtest.z64
.PHONY: all

BUILD_DIR = build
include $(N64_INST)/include/n64.mk

OBJS = $(BUILD_DIR)/joypadtest.o

joypadtest.z64: N64_ROM_TITLE = "Joypad Test"

$(BUILD_DIR)/joypadtest.elf: $(OBJS)

clean:
rm -rf $(BUILD_DIR) *.z64
.PHONY: clean

-include $(wildcard $(BUILD_DIR)/*.d)
133 changes: 133 additions & 0 deletions examples/joypadtest/joypadtest.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
/**
* @file joypadtest.c
* @author Christopher Bonhage ([email protected])
* @brief N64 test ROM for Joypad subsystem
*/

#include <string.h>
#include <libdragon.h>

const char *format_joypad_style(joypad_style_t style)
{
switch (style)
{
case JOYPAD_STYLE_NONE:
return "None ";
case JOYPAD_STYLE_N64:
return "N64 ";
case JOYPAD_STYLE_GCN:
return "GCN ";
case JOYPAD_STYLE_MOUSE:
return "Mouse ";
default:
return "Unknown";
}
}

const char *format_joypad_accessory_type(joypad_accessory_type_t accessory_type)
{
switch (accessory_type)
{
case JOYPAD_ACCESSORY_TYPE_NONE:
return "None ";
case JOYPAD_ACCESSORY_TYPE_CONTROLLER_PAK:
return "Memory ";
case JOYPAD_ACCESSORY_TYPE_RUMBLE_PAK:
return "Rumble Pak ";
case JOYPAD_ACCESSORY_TYPE_TRANSFER_PAK:
return "Transfer Pak";
case JOYPAD_ACCESSORY_TYPE_BIO_SENSOR:
return "Bio Sensor ";
case JOYPAD_ACCESSORY_TYPE_SNAP_STATION:
return "Snap Station";
default:
return "Unknown ";
}
}

const char *format_joypad_rumble(bool supported, bool enabled)
{
if (!supported) return "Unavailable";
if (enabled) return "Active";
return "Idle";
}

void print_joypad_inputs(joypad_inputs_t inputs)
{
printf(
"Stick: %+04d,%+04d C-Stick: %+04d,%+04d L-Trig:%03d R-Trig:%03d\n",
inputs.stick_x, inputs.stick_y,
inputs.cstick_x, inputs.cstick_y,
inputs.analog_l, inputs.analog_r
);
printf(
"D-U:%d D-D:%d D-L:%d D-R:%d C-U:%d C-D:%d C-L:%d C-R:%d\n",
inputs.d_up, inputs.d_down,
inputs.d_left, inputs.d_right,
inputs.c_up, inputs.c_down,
inputs.c_left, inputs.c_right
);
printf(
"A:%d B:%d X:%d Y:%d L:%d R:%d Z:%d Start:%d\n",
inputs.a, inputs.b,
inputs.x, inputs.y,
inputs.l, inputs.r,
inputs.z, inputs.start
);
}

int main(void)
{
joypad_style_t style;
joypad_accessory_type_t accessory_type;
bool rumble_supported;
bool rumble_active;
joypad_inputs_t inputs;

timer_init();
joypad_init();
debug_init_isviewer();
console_init();
console_set_render_mode(RENDER_MANUAL);
console_set_debug(false);

while (1)
{
console_clear();

printf("LibDragon Joypad Subsystem Test\n\n");

joypad_scan();

JOYPAD_PORT_FOREACH (port)
{
style = joypad_get_style(port);
accessory_type = joypad_get_accessory_type(port);
rumble_supported = joypad_get_rumble_supported(port);
rumble_active = joypad_get_rumble_active(port);
inputs = joypad_get_inputs(port);

if (rumble_supported)
{
if (inputs.a && !rumble_active)
{
joypad_set_rumble_active(port, true);
}
else if (!inputs.a && rumble_active)
{
joypad_set_rumble_active(port, false);
}
}

printf("Port %d ", port + 1);
printf("Style: %s ", format_joypad_style(style));
printf("Pak: %s ", format_joypad_accessory_type(accessory_type));
printf("Rumble: %s", format_joypad_rumble(rumble_supported, rumble_active));
printf("\n");
print_joypad_inputs(inputs);
printf("\n");
}

console_render();
}
}
108 changes: 96 additions & 12 deletions include/controller.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,35 @@

#include <stdint.h>

#include "joybus.h"
#include "joybus_accessory.h"
#include "joypad.h"

/**
* @addtogroup controller
* @{
*/

#ifdef __cplusplus
extern "C" {
#endif

/*****************************************************************************
* Deprecated API
*
* The following API is deprecated and will be removed in the future.
* This API is being kept for compatibility with existing code. The
* implementation is now based on the Joypad Subsystem, which fixes
* several deficiencies and implements first-class support for GameCube
* controllers. The Controller Subsystem will emit deprecation warnings
* when used and suggest replacement functions and data structures.
****************************************************************************/

/**
* @name Bitmasks for controller status
* @see #get_controllers_present
* @see #get_accessories_present
*
* @deprecated Use #joypad_is_connected instead.
*
* @{
*/
/** @brief Controller 1 Inserted */
Expand All @@ -31,7 +51,9 @@

/**
* @name Accessory ID Values
* @see #identify_accessory
*
* @deprecated Use #joypad_accessory_type_t instead.
*
* @{
*/
/** @brief No accessory present */
Expand All @@ -48,6 +70,9 @@

/**
* @name SI Error Values
*
* @deprecated These values are no longer used. They will be removed in the future.
*
* @{
*/
/** @brief No error occured */
Expand All @@ -62,6 +87,10 @@
* @brief SI Nintendo 64 controller data
*
* Data structure for Joybus response to `0x01` (Read N64 controller state) command.
*
* @deprecated The @ref joypad "Joypad Subsystem" now automatically normalizes
* Nintendo 64 and GameCube controller inputs. This structure is no
* longer needed. Use #joypad_inputs_t instead.
*/
typedef struct SI_condat
{
Expand Down Expand Up @@ -123,6 +152,10 @@ typedef struct SI_condat
* @brief SI GameCube controller data.
*
* Data structure for Joybus response to `0x40` (Read GC controller state) command.
*
* @deprecated The @ref joypad "Joypad Subsystem" now automatically normalizes
* Nintendo 64 and GameCube controller inputs. This structure is no
* longer needed. Use #joypad_inputs_t instead.
*/
typedef struct SI_condat_gc
{
Expand Down Expand Up @@ -165,6 +198,9 @@ typedef struct SI_condat_gc
* @brief SI GameCube controller origin data.
*
* Data structure for Joybus response to `0x41` (Read GC controller origin) command.
*
* @deprecated The @ref joypad "Joypad Subsystem" now handles GameCube controller
* origins automatically. This structure is no longer needed.
*/
struct SI_origdat_gc {
struct SI_condat_gc data;
Expand All @@ -177,6 +213,10 @@ struct SI_origdat_gc {
*
* When reading N64 controller state, only the `c` member array will be populated.
* When reading GC controller state, only the `gc` member array will be populated.
*
* @deprecated The @ref joypad "Joypad Subsystem" now automatically normalizes
* Nintendo 64 and GameCube controller inputs. This structure is no
* longer needed. Use #joypad_inputs_t instead.
*/
typedef struct controller_data
{
Expand All @@ -186,35 +226,79 @@ typedef struct controller_data
struct SI_condat_gc gc[4];
} SI_controllers_state_t;

/** @brief SI GameCube controller origin data for all controller ports. */
/**
* @brief SI GameCube controller origin data for all controller ports.
*
* @deprecated The @ref joypad "Joypad Subsystem" now handles GameCube controller
* origins automatically. This structure is no longer needed.
*/
typedef struct controller_origin_data
{
/** @brief Array of GameCube controller origin data for each controller port. */
struct SI_origdat_gc gc[4];
} SI_controllers_origin_t;

#ifdef __cplusplus
extern "C" {
#endif
/**************************************
* DEPRECATED FUNCTIONS
**************************************/

void controller_init( void );
/// @cond

__attribute__((deprecated("use joybus_exec_raw_command instead")))
void execute_raw_command( int controller, int command, int bytesout, int bytesin, unsigned char *out, unsigned char *in );

__attribute__((deprecated("use joypad_read_n64_inputs_sync instead")))
void controller_read( struct controller_data * data );

__attribute__((deprecated("use joypad_get_inputs instead")))
void controller_read_gc( struct controller_data * data, const uint8_t rumble[4] );

__attribute__((deprecated("use joypad subsystem instead")))
void controller_read_gc_origin( struct controller_origin_data * data);
int get_controllers_present( void );
int get_accessories_present( struct controller_data * data );

__attribute__((deprecated("use joypad_init instead")))
void controller_init( void );

__attribute__((deprecated("use joypad_scan instead")))
void controller_scan( void );

__attribute__((deprecated("use joypad_get_buttons_pressed instead")))
struct controller_data get_keys_down( void );

__attribute__((deprecated("use joypad_get_buttons_released instead")))
struct controller_data get_keys_up( void );

__attribute__((deprecated("use joypad_get_buttons_held instead")))
struct controller_data get_keys_held( void );

__attribute__((deprecated("use joypad_get_buttons instead")))
struct controller_data get_keys_pressed( void );

__attribute__((deprecated("use joypad_get_identifier instead")))
int get_controllers_present( void );

__attribute__((deprecated("use joypad_get_accessory_type instead")))
int get_accessories_present( struct controller_data * data );

__attribute__((deprecated("use joypad_get_accessory_type instead")))
int identify_accessory( int controller );

__attribute__((deprecated("use joypad_get_dpad_direction instead")))
int get_dpad_direction( int controller );

__attribute__((deprecated("use joybus_accessory_read_sync instead")))
int read_mempak_address( int controller, uint16_t address, uint8_t *data );

__attribute__((deprecated("use joybus_accessory_write_sync instead")))
int write_mempak_address( int controller, uint16_t address, uint8_t *data );
int identify_accessory( int controller );

__attribute__((deprecated("use joypad_set_rumble_active instead")))
void rumble_start( int controller );

__attribute__((deprecated("use joypad_set_rumble_active instead")))
void rumble_stop( int controller );
void execute_raw_command( int controller, int command, int bytesout, int bytesin, unsigned char *out, unsigned char *in );

/// @endcond

#ifdef __cplusplus
}
Expand Down
Loading