diff --git a/librecomp/src/cont.cpp b/librecomp/src/cont.cpp index fe56c66..e036127 100644 --- a/librecomp/src/cont.cpp +++ b/librecomp/src/cont.cpp @@ -28,26 +28,13 @@ void set_input_callbacks(const ultramodern::input_callbacks_t& callbacks) { static int max_controllers = 0; extern "C" void osContInit_recomp(uint8_t* rdram, recomp_context* ctx) { - PTR(void) bitpattern = _arg<1, PTR(void)>(rdram, ctx); - PTR(void) status = _arg<2, PTR(void)>(rdram, ctx); + PTR(OSMesgQueue) mq = _arg<0, PTR(OSMesgQueue)>(rdram, ctx); + PTR(u8) bitpattern = _arg<1, PTR(u8)>(rdram, ctx); + PTR(OSContStatus) data = _arg<2, PTR(OSContStatus)>(rdram, ctx); - // Set bit 0 to indicate that controller 0 is present - MEM_B(0, bitpattern) = 0x01; + s32 ret = osContInit(PASS_RDRAM mq, bitpattern, data); - // Mark controller 0 as present - MEM_H(0, status) = 0x0005; // type: CONT_TYPE_NORMAL (from joybus) - MEM_B(2, status) = 0x00; // status: 0 (from joybus) - MEM_B(3, status) = 0x00; // errno: 0 (from libultra) - - max_controllers = 4; - - // Mark controllers 1-3 as not connected - for (size_t controller = 1; controller < max_controllers; controller++) { - // Libultra doesn't write status or type for absent controllers - MEM_B(4 * controller + 3, status) = 0x80 >> 4; // errno: CONT_NO_RESPONSE_ERROR >> 4 - } - - _return(ctx, 0); + _return(ctx, ret); } extern "C" void osContStartReadData_recomp(uint8_t* rdram, recomp_context* ctx) { @@ -90,18 +77,9 @@ extern "C" void osContStartQuery_recomp(uint8_t * rdram, recomp_context * ctx) { } extern "C" void osContGetQuery_recomp(uint8_t * rdram, recomp_context * ctx) { - PTR(void) status = _arg<0, PTR(void)>(rdram, ctx); + PTR(OSContStatus) data = _arg<0, PTR(OSContStatus)>(rdram, ctx); - // Mark controller 0 as present - MEM_H(0, status) = 0x0005; // type: CONT_TYPE_NORMAL (from joybus) - MEM_B(2, status) = 0x01; // status: 0x01 (from joybus, indicates that a pak is plugged into the controller) - MEM_B(3, status) = 0x00; // errno: 0 (from libultra) - - // Mark controllers 1-3 as not connected - for (size_t controller = 1; controller < max_controllers; controller++) { - // Libultra doesn't write status or type for absent controllers - MEM_B(4 * controller + 3, status) = 0x80 >> 4; // errno: CONT_NO_RESPONSE_ERROR >> 4 - } + osContGetQuery(PASS_RDRAM data); } extern "C" void osContSetCh_recomp(uint8_t* rdram, recomp_context* ctx) { diff --git a/ultramodern/CMakeLists.txt b/ultramodern/CMakeLists.txt index 336fd16..91a3335 100644 --- a/ultramodern/CMakeLists.txt +++ b/ultramodern/CMakeLists.txt @@ -11,6 +11,7 @@ set(CMAKE_CXX_EXTENSIONS OFF) add_library(ultramodern STATIC "${CMAKE_CURRENT_SOURCE_DIR}/src/audio.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/src/cont.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/src/error_handling.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/src/events.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/src/mesgqueue.cpp" diff --git a/ultramodern/include/ultramodern/input.hpp b/ultramodern/include/ultramodern/input.hpp new file mode 100644 index 0000000..1ce2284 --- /dev/null +++ b/ultramodern/include/ultramodern/input.hpp @@ -0,0 +1,24 @@ +#ifndef __ULTRAMODERN_INPUT_HPP__ +#define __ULTRAMODERN_INPUT_HPP__ + +#include + +namespace ultramodern { + namespace input { + struct callbacks_t { + using poll_input_t = void(void); + using get_input_t = void(uint16_t*, float*, float*); + using set_rumble_t = void(bool); + + poll_input_t* poll_input; + get_input_t* get_input; + set_rumble_t* set_rumble; + }; + + void set_callbacks(const callbacks_t& callbacks); + + + } +} + +#endif diff --git a/ultramodern/include/ultramodern/ultra64.h b/ultramodern/include/ultramodern/ultra64.h index 395cadb..a202572 100644 --- a/ultramodern/include/ultramodern/ultra64.h +++ b/ultramodern/include/ultramodern/ultra64.h @@ -214,6 +214,26 @@ typedef struct { OSViFieldRegs fldRegs[2]; } OSViMode; +// Controller + +typedef struct { + // These three members reversed due to endianness + u8 err_no; + u8 status; /* Controller status */ + u16 type; /* Controller Type */ +} OSContStatus; + +typedef struct { + // These three members reversed due to endianness + s8 stick_y; /* -80 <= stick_y <= 80 */ + s8 stick_x; /* -80 <= stick_x <= 80 */ + u16 button; + // Padding due to endianness + u8 padding[3]; + u8 err_no; +} OSContPad; + + /////////////// // Functions // /////////////// @@ -255,6 +275,16 @@ int osSetTimer(RDRAM_ARG PTR(OSTimer) timer, OSTime countdown, OSTime interval, int osStopTimer(RDRAM_ARG PTR(OSTimer) timer); u32 osVirtualToPhysical(PTR(void) addr); +/* Controller interface */ + +s32 osContInit(RDRAM_ARG PTR(OSMesgQueue), PTR(u8), PTR(OSContStatus)); +s32 osContReset(RDRAM_ARG PTR(OSMesgQueue), PTR(OSContStatus)); +s32 osContStartQuery(RDRAM_ARG PTR(OSMesgQueue)); +s32 osContStartReadData(RDRAM_ARG PTR(OSMesgQueue)); +s32 osContSetCh(RDRAM_ARG u8); +void osContGetQuery(RDRAM_ARG PTR(OSContStatus)); +void osContGetReadData(RDRAM_ARG PTR(OSContPad)); + #ifdef __cplusplus } // extern "C" #endif diff --git a/ultramodern/src/cont.cpp b/ultramodern/src/cont.cpp new file mode 100644 index 0000000..636ef62 --- /dev/null +++ b/ultramodern/src/cont.cpp @@ -0,0 +1,66 @@ +#include + +#include "ultramodern/input.hpp" +#include "ultramodern/ultra64.h" + +static ultramodern::input::callbacks_t input_callbacks {}; + +void ultramodern::input::set_callbacks(const callbacks_t& callbacks) { + input_callbacks = callbacks; +} + +static int max_controllers = 0; + +static void __osContGetInitData(u8* pattern, OSContStatus *data) { + // Set bit 0 to indicate that controller 0 is present + *pattern = 0x01; + + // Mark controller 0 as present + data[0].type = 0x0005; // type: CONT_TYPE_NORMAL (from joybus) + data[0].status = 0x00; // status: 0 (from joybus) + data[0].err_no = 0x00; // errno: 0 (from libultra) + + // Mark controllers 1-3 as not connected + for (int controller = 1; controller < max_controllers; controller++) { + // Libultra doesn't write status or type for absent controllers + data[controller].err_no = 0x80 >> 4; // errno: CONT_NO_RESPONSE_ERROR >> 4 + } +} + +extern "C" s32 osContInit(RDRAM_ARG PTR(OSMesgQueue) mq, PTR(u8) bitpattern_, PTR(OSContStatus) data_) { + u8 *bitpattern = TO_PTR(u8, bitpattern_); + OSContStatus *data = TO_PTR(OSContStatus, data_); + + max_controllers = 4; + + __osContGetInitData(bitpattern, data); + + return 0; +} + +extern "C" s32 osContResetRDRAM_ARG (PTR(OSMesgQueue) , PTR(OSContStatus) ) { + assert(false); +} + +extern "C" s32 osContStartQuery(RDRAM_ARG PTR(OSMesgQueue) ) { + assert(false); +} + +extern "C" s32 osContStartReadData(RDRAM_ARG PTR(OSMesgQueue) ) { + assert(false); +} + +extern "C" s32 osContSetCh(RDRAM_ARG u8) { + assert(false); +} + +extern "C" void osContGetQuery(RDRAM_ARG PTR(OSContStatus) data_) { + u8 pattern; + OSContStatus *data = TO_PTR(OSContStatus, data_); + + __osContGetInitData(&pattern, data); +} + +extern "C" void osContGetReadData(RDRAM_ARG PTR(OSContPad) ) { + assert(false); +}