mirror of
https://github.com/libretro/RetroArch.git
synced 2025-02-01 14:31:54 +00:00
(wiiu) small style nits; declare variables at top; C comments
This commit is contained in:
parent
af9911df8a
commit
cf8e7cd362
@ -139,7 +139,7 @@ static void hidpad_wiiugca_set_rumble(void *data,
|
||||
(void)strength;
|
||||
}
|
||||
|
||||
const char * hidpad_wiiugca_get_name(void *data)
|
||||
const char *hidpad_wiiugca_get_name(void *data)
|
||||
{
|
||||
(void)data;
|
||||
/* For now we return a single static name */
|
||||
|
@ -31,14 +31,17 @@
|
||||
|
||||
int MountFS(void *pClient, void *pCmd, char **mount_path)
|
||||
{
|
||||
int result = -1;
|
||||
char *mountPath = NULL;
|
||||
int result = -1;
|
||||
void *mountSrc = malloc(FS_MOUNT_SOURCE_SIZE);
|
||||
|
||||
void *mountSrc = malloc(FS_MOUNT_SOURCE_SIZE);
|
||||
if(!mountSrc)
|
||||
return -3;
|
||||
if (!mountSrc)
|
||||
return -3;
|
||||
|
||||
char* mountPath = (char*) malloc(FS_MAX_MOUNTPATH_SIZE);
|
||||
if(!mountPath) {
|
||||
mountPath = (char*) malloc(FS_MAX_MOUNTPATH_SIZE);
|
||||
|
||||
if (!mountPath)
|
||||
{
|
||||
free(mountSrc);
|
||||
return -4;
|
||||
}
|
||||
@ -46,14 +49,16 @@ int MountFS(void *pClient, void *pCmd, char **mount_path)
|
||||
memset(mountSrc, 0, FS_MOUNT_SOURCE_SIZE);
|
||||
memset(mountPath, 0, FS_MAX_MOUNTPATH_SIZE);
|
||||
|
||||
// Mount sdcard
|
||||
/* Mount sdcard */
|
||||
if (FSGetMountSource(pClient, pCmd, FS_SOURCETYPE_EXTERNAL, mountSrc, -1) == 0)
|
||||
{
|
||||
result = FSMount(pClient, pCmd, mountSrc, mountPath, FS_MAX_MOUNTPATH_SIZE, -1);
|
||||
if((result == 0) && mount_path) {
|
||||
|
||||
if ((result == 0) && mount_path)
|
||||
{
|
||||
*mount_path = (char*)malloc(strlen(mountPath) + 1);
|
||||
if(*mount_path)
|
||||
strcpy(*mount_path, mountPath);
|
||||
if (*mount_path)
|
||||
strcpy(*mount_path, mountPath);
|
||||
}
|
||||
}
|
||||
|
||||
@ -64,45 +69,45 @@ int MountFS(void *pClient, void *pCmd, char **mount_path)
|
||||
|
||||
int UmountFS(void *pClient, void *pCmd, const char *mountPath)
|
||||
{
|
||||
int result = -1;
|
||||
result = FSUnmount(pClient, pCmd, mountPath, -1);
|
||||
|
||||
return result;
|
||||
return FSUnmount(pClient, pCmd, mountPath, -1);
|
||||
}
|
||||
|
||||
int LoadFileToMem(const char *filepath, u8 **inbuffer, u32 *size)
|
||||
{
|
||||
//! always initialze input
|
||||
*inbuffer = NULL;
|
||||
if(size)
|
||||
*size = 0;
|
||||
u8 *buffer;
|
||||
u32 filesize;
|
||||
int iFd;
|
||||
u32 blocksize = 0x4000;
|
||||
u32 done = 0;
|
||||
int readBytes = 0;
|
||||
|
||||
int iFd = open(filepath, O_RDONLY);
|
||||
/* always initialze input */
|
||||
*inbuffer = NULL;
|
||||
|
||||
if (size)
|
||||
*size = 0;
|
||||
|
||||
iFd = open(filepath, O_RDONLY);
|
||||
if (iFd < 0)
|
||||
return -1;
|
||||
return -1;
|
||||
|
||||
u32 filesize = lseek(iFd, 0, SEEK_END);
|
||||
filesize = lseek(iFd, 0, SEEK_END);
|
||||
lseek(iFd, 0, SEEK_SET);
|
||||
|
||||
u8 *buffer = (u8 *) malloc(filesize);
|
||||
buffer = (u8 *) malloc(filesize);
|
||||
if (buffer == NULL)
|
||||
{
|
||||
close(iFd);
|
||||
return -2;
|
||||
}
|
||||
|
||||
u32 blocksize = 0x4000;
|
||||
u32 done = 0;
|
||||
int readBytes = 0;
|
||||
|
||||
while(done < filesize)
|
||||
{
|
||||
if(done + blocksize > filesize) {
|
||||
if (done + blocksize > filesize)
|
||||
blocksize = filesize - done;
|
||||
}
|
||||
readBytes = read(iFd, buffer + done, blocksize);
|
||||
if(readBytes <= 0)
|
||||
break;
|
||||
if (readBytes <= 0)
|
||||
break;
|
||||
done += readBytes;
|
||||
}
|
||||
|
||||
@ -116,72 +121,71 @@ int LoadFileToMem(const char *filepath, u8 **inbuffer, u32 *size)
|
||||
|
||||
*inbuffer = buffer;
|
||||
|
||||
//! sign is optional input
|
||||
if(size)
|
||||
*size = filesize;
|
||||
/* sign is optional input */
|
||||
if (size)
|
||||
*size = filesize;
|
||||
|
||||
return filesize;
|
||||
}
|
||||
|
||||
int CheckFile(const char * filepath)
|
||||
{
|
||||
if(!filepath)
|
||||
return 0;
|
||||
|
||||
struct stat filestat;
|
||||
char *notRoot = NULL;
|
||||
|
||||
if (!filepath)
|
||||
return 0;
|
||||
|
||||
char dirnoslash[strlen(filepath)+2];
|
||||
|
||||
snprintf(dirnoslash, sizeof(dirnoslash), "%s", filepath);
|
||||
|
||||
while(dirnoslash[strlen(dirnoslash)-1] == '/')
|
||||
dirnoslash[strlen(dirnoslash)-1] = '\0';
|
||||
dirnoslash[strlen(dirnoslash)-1] = '\0';
|
||||
|
||||
char * notRoot = strrchr(dirnoslash, '/');
|
||||
if(!notRoot)
|
||||
{
|
||||
notRoot = strrchr(dirnoslash, '/');
|
||||
if (!notRoot)
|
||||
strcat(dirnoslash, "/");
|
||||
}
|
||||
|
||||
if (stat(dirnoslash, &filestat) == 0)
|
||||
return 1;
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CreateSubfolder(const char * fullpath)
|
||||
{
|
||||
if(!fullpath)
|
||||
return 0;
|
||||
|
||||
int pos;
|
||||
int result = 0;
|
||||
|
||||
if (!fullpath)
|
||||
return 0;
|
||||
|
||||
char dirnoslash[strlen(fullpath)+1];
|
||||
strcpy(dirnoslash, fullpath);
|
||||
|
||||
int pos = strlen(dirnoslash)-1;
|
||||
pos = strlen(dirnoslash)-1;
|
||||
while(dirnoslash[pos] == '/')
|
||||
{
|
||||
dirnoslash[pos] = '\0';
|
||||
pos--;
|
||||
}
|
||||
|
||||
if(CheckFile(dirnoslash))
|
||||
{
|
||||
if (CheckFile(dirnoslash))
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
|
||||
{
|
||||
char parentpath[strlen(dirnoslash)+2];
|
||||
strcpy(parentpath, dirnoslash);
|
||||
char * ptr = strrchr(parentpath, '/');
|
||||
|
||||
if(!ptr)
|
||||
if (!ptr)
|
||||
{
|
||||
//!Device root directory (must be with '/')
|
||||
/* Device root directory (must be with '/') */
|
||||
strcat(parentpath, "/");
|
||||
struct stat filestat;
|
||||
if (stat(parentpath, &filestat) == 0)
|
||||
return 1;
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -192,13 +196,11 @@ int CreateSubfolder(const char * fullpath)
|
||||
result = CreateSubfolder(parentpath);
|
||||
}
|
||||
|
||||
if(!result)
|
||||
return 0;
|
||||
if (!result)
|
||||
return 0;
|
||||
|
||||
if (mkdir(dirnoslash, 0777) == -1)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
@ -12,7 +12,7 @@ int UmountFS(void *pClient, void *pCmd, const char *mountPath);
|
||||
|
||||
int LoadFileToMem(const char *filepath, u8 **inbuffer, u32 *size);
|
||||
|
||||
//! todo: C++ class
|
||||
/* TODO/FIXME: C++ class */
|
||||
int CreateSubfolder(const char * fullpath);
|
||||
int CheckFile(const char * filepath);
|
||||
|
||||
@ -20,4 +20,4 @@ int CheckFile(const char * filepath);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // __FS_UTILS_H_
|
||||
#endif /* __FS_UTILS_H_ */
|
||||
|
@ -30,112 +30,130 @@ static bool ready = false;
|
||||
static wiiu_hid_t *hid_data;
|
||||
static hid_driver_t *hid_driver;
|
||||
|
||||
static unsigned to_slot(unsigned pad) {
|
||||
return pad - (WIIU_WIIMOTE_CHANNELS+1);
|
||||
static unsigned to_slot(unsigned pad)
|
||||
{
|
||||
return pad - (WIIU_WIIMOTE_CHANNELS+1);
|
||||
}
|
||||
|
||||
const void *get_hid_data(void) {
|
||||
return hid_data;
|
||||
const void *get_hid_data(void)
|
||||
{
|
||||
return hid_data;
|
||||
}
|
||||
|
||||
static hid_driver_t *init_hid_driver(void)
|
||||
{
|
||||
unsigned connections_size = MAX_USERS - (WIIU_WIIMOTE_CHANNELS+1);
|
||||
hid_data = (wiiu_hid_t *)wiiu_hid.init();
|
||||
joypad_connection_t *connections = pad_connection_init(connections_size);
|
||||
joypad_connection_t *connections = NULL;
|
||||
unsigned connections_size = MAX_USERS - (WIIU_WIIMOTE_CHANNELS+1);
|
||||
|
||||
if(!hid_data || !connections)
|
||||
goto error;
|
||||
hid_data = (wiiu_hid_t *)wiiu_hid.init();
|
||||
connections = pad_connection_init(connections_size);
|
||||
|
||||
hid_data->connections = connections;
|
||||
hid_data->connections_size = connections_size;
|
||||
return &wiiu_hid;
|
||||
if (!hid_data || !connections)
|
||||
goto error;
|
||||
|
||||
error:
|
||||
if(connections)
|
||||
hid_data->connections = connections;
|
||||
hid_data->connections_size = connections_size;
|
||||
return &wiiu_hid;
|
||||
|
||||
error:
|
||||
if (connections)
|
||||
free(connections);
|
||||
if(hid_data)
|
||||
{
|
||||
if (hid_data)
|
||||
{
|
||||
wiiu_hid.free(hid_data);
|
||||
free(hid_data);
|
||||
hid_data = NULL;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static bool hidpad_init(void *data)
|
||||
{
|
||||
(void *)data;
|
||||
hid_driver = init_hid_driver();
|
||||
if(!hid_driver)
|
||||
{
|
||||
RARCH_ERR("Failed to initialize HID driver.\n");
|
||||
return false;
|
||||
}
|
||||
(void *)data;
|
||||
|
||||
hidpad_poll();
|
||||
ready = true;
|
||||
hid_driver = init_hid_driver();
|
||||
if (!hid_driver)
|
||||
{
|
||||
RARCH_ERR("Failed to initialize HID driver.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
hidpad_poll();
|
||||
ready = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool hidpad_query_pad(unsigned pad)
|
||||
{
|
||||
return ready && (pad > WIIU_WIIMOTE_CHANNELS && pad < MAX_USERS);
|
||||
return ready && (pad > WIIU_WIIMOTE_CHANNELS && pad < MAX_USERS);
|
||||
}
|
||||
|
||||
static void hidpad_destroy(void)
|
||||
{
|
||||
ready = false;
|
||||
ready = false;
|
||||
|
||||
if(hid_driver)
|
||||
{
|
||||
hid_driver->free(get_hid_data());
|
||||
free(hid_data);
|
||||
hid_data = NULL;
|
||||
}
|
||||
if (!hid_driver)
|
||||
return;
|
||||
|
||||
hid_driver->free(get_hid_data());
|
||||
free(hid_data);
|
||||
hid_data = NULL;
|
||||
}
|
||||
|
||||
static bool hidpad_button(unsigned pad, uint16_t button)
|
||||
{
|
||||
if(!hidpad_query_pad(pad))
|
||||
return false;
|
||||
if (!hidpad_query_pad(pad))
|
||||
return false;
|
||||
|
||||
// return hid_driver->button(hid_data, to_slot(pad), button);
|
||||
return false;
|
||||
#if 0
|
||||
return hid_driver->button(hid_data, to_slot(pad), button);
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void hidpad_get_buttons(unsigned pad, retro_bits_t *state)
|
||||
{
|
||||
if(!hidpad_query_pad(pad))
|
||||
if (!hidpad_query_pad(pad))
|
||||
BIT256_CLEAR_ALL_PTR(state);
|
||||
|
||||
// hid_driver->get_buttons(hid_data, to_slot(pad), state);
|
||||
#if 0
|
||||
hid_driver->get_buttons(hid_data, to_slot(pad), state);
|
||||
#endif
|
||||
BIT256_CLEAR_ALL_PTR(state);
|
||||
}
|
||||
|
||||
static int16_t hidpad_axis(unsigned pad, uint32_t axis)
|
||||
{
|
||||
if(!hidpad_query_pad(pad));
|
||||
return 0;
|
||||
if (!hidpad_query_pad(pad));
|
||||
return 0;
|
||||
|
||||
// return hid_driver->axis(hid_data, to_slot(pad), axis);
|
||||
return 0;
|
||||
#if 0
|
||||
return hid_driver->axis(hid_data, to_slot(pad), axis);
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void hidpad_poll(void)
|
||||
{
|
||||
// if(ready)
|
||||
// hid_driver->poll(hid_data);
|
||||
#if 0
|
||||
if (ready)
|
||||
hid_driver->poll(hid_data);
|
||||
#endif
|
||||
}
|
||||
|
||||
static const char *hidpad_name(unsigned pad)
|
||||
{
|
||||
if(!hidpad_query_pad(pad))
|
||||
return "N/A";
|
||||
if (!hidpad_query_pad(pad))
|
||||
return "N/A";
|
||||
|
||||
return PAD_NAME_HID;
|
||||
//return hid_driver->name(hid_data, to_slot(pad));
|
||||
#if 1
|
||||
return PAD_NAME_HID;
|
||||
#else
|
||||
return hid_driver->name(hid_data, to_slot(pad));
|
||||
#endif
|
||||
}
|
||||
|
||||
input_device_driver_t hidpad_driver =
|
||||
|
@ -33,77 +33,84 @@ static const char *kpad_name(unsigned pad);
|
||||
|
||||
typedef struct _wiimote_state wiimote_state;
|
||||
|
||||
struct _wiimote_state {
|
||||
uint64_t button_state;
|
||||
int16_t analog_state[3][2];
|
||||
uint8_t type;
|
||||
struct _wiimote_state
|
||||
{
|
||||
uint64_t button_state;
|
||||
int16_t analog_state[3][2];
|
||||
uint8_t type;
|
||||
};
|
||||
|
||||
static bool ready = false;
|
||||
|
||||
wiimote_state wiimotes[WIIU_WIIMOTE_CHANNELS];
|
||||
|
||||
static unsigned to_wiimote_channel(unsigned pad) {
|
||||
if(pad == PAD_GAMEPAD || pad > WIIU_WIIMOTE_CHANNELS)
|
||||
return 0xffffffff;
|
||||
static unsigned to_wiimote_channel(unsigned pad)
|
||||
{
|
||||
if (pad == PAD_GAMEPAD || pad > WIIU_WIIMOTE_CHANNELS)
|
||||
return 0xffffffff;
|
||||
|
||||
return pad-1;
|
||||
return pad-1;
|
||||
}
|
||||
|
||||
static unsigned to_retro_pad(unsigned channel) {
|
||||
return channel+1;
|
||||
static unsigned to_retro_pad(unsigned channel)
|
||||
{
|
||||
return channel+1;
|
||||
}
|
||||
|
||||
static bool kpad_init(void *data)
|
||||
{
|
||||
(void *)data;
|
||||
(void *)data;
|
||||
|
||||
kpad_poll();
|
||||
ready = true;
|
||||
kpad_poll();
|
||||
ready = true;
|
||||
}
|
||||
|
||||
static bool kpad_query_pad(unsigned pad)
|
||||
{
|
||||
return ready && pad <= WIIU_WIIMOTE_CHANNELS && pad > PAD_GAMEPAD;
|
||||
return ready && pad <= WIIU_WIIMOTE_CHANNELS && pad > PAD_GAMEPAD;
|
||||
}
|
||||
|
||||
static void kpad_destroy(void)
|
||||
{
|
||||
ready = false;
|
||||
ready = false;
|
||||
}
|
||||
|
||||
static bool kpad_button(unsigned pad, uint16_t button_bit)
|
||||
{
|
||||
if(!kpad_query_pad(pad))
|
||||
return false;
|
||||
if (!kpad_query_pad(pad))
|
||||
return false;
|
||||
|
||||
return wiimotes[to_wiimote_channel(pad)].button_state & (UINT64_C(1) << button_bit);
|
||||
return wiimotes[to_wiimote_channel(pad)].button_state
|
||||
& (UINT64_C(1) << button_bit);
|
||||
}
|
||||
|
||||
static void kpad_get_buttons(unsigned pad, retro_bits_t *state)
|
||||
{
|
||||
if(!kpad_query_pad(pad))
|
||||
BIT256_CLEAR_ALL_PTR(state);
|
||||
else
|
||||
BITS_COPY16_PTR(state, wiimotes[to_wiimote_channel(pad)].button_state);
|
||||
if (!kpad_query_pad(pad))
|
||||
BIT256_CLEAR_ALL_PTR(state);
|
||||
else
|
||||
BITS_COPY16_PTR(state, wiimotes[to_wiimote_channel(pad)].button_state);
|
||||
}
|
||||
|
||||
static int16_t kpad_axis(unsigned pad, uint32_t axis)
|
||||
{
|
||||
axis_data data;
|
||||
if(!kpad_query_pad(pad) || axis == AXIS_NONE)
|
||||
return 0;
|
||||
axis_data data;
|
||||
if (!kpad_query_pad(pad) || axis == AXIS_NONE)
|
||||
return 0;
|
||||
|
||||
pad_functions.read_axis_data(axis, &data);
|
||||
return pad_functions.get_axis_value(data.axis, wiimotes[to_wiimote_channel(pad)].analog_state, data.is_negative);
|
||||
pad_functions.read_axis_data(axis, &data);
|
||||
return pad_functions.get_axis_value(data.axis,
|
||||
wiimotes[to_wiimote_channel(pad)].analog_state,
|
||||
data.is_negative);
|
||||
}
|
||||
|
||||
static void kpad_register(unsigned channel, uint8_t device_type)
|
||||
{
|
||||
if(wiimotes[channel].type != device_type) {
|
||||
wiimotes[channel].type = device_type;
|
||||
pad_functions.connect(to_retro_pad(channel), &kpad_driver);
|
||||
}
|
||||
if (wiimotes[channel].type != device_type)
|
||||
{
|
||||
wiimotes[channel].type = device_type;
|
||||
pad_functions.connect(to_retro_pad(channel), &kpad_driver);
|
||||
}
|
||||
}
|
||||
|
||||
#define WIIU_PRO_BUTTON_MASK 0x3FC0000;
|
||||
@ -111,85 +118,88 @@ static void kpad_register(unsigned channel, uint8_t device_type)
|
||||
|
||||
static void kpad_poll_one_channel(unsigned channel, KPADData *kpad)
|
||||
{
|
||||
kpad_register(channel, kpad->device_type);
|
||||
switch(kpad->device_type)
|
||||
{
|
||||
case WIIMOTE_TYPE_PRO:
|
||||
wiimotes[channel].button_state = kpad->classic.btns_h & ~WIIU_PRO_BUTTON_MASK;
|
||||
pad_functions.set_axis_value(wiimotes[channel].analog_state,
|
||||
WIIU_READ_STICK(kpad->classic.lstick_x),
|
||||
WIIU_READ_STICK(kpad->classic.lstick_y),
|
||||
WIIU_READ_STICK(kpad->classic.rstick_x),
|
||||
WIIU_READ_STICK(kpad->classic.rstick_y), 0, 0);
|
||||
break;
|
||||
case WIIMOTE_TYPE_CLASSIC:
|
||||
wiimotes[channel].button_state = kpad->classic.btns_h & ~CLASSIC_BUTTON_MASK;
|
||||
pad_functions.set_axis_value(wiimotes[channel].analog_state,
|
||||
WIIU_READ_STICK(kpad->classic.lstick_x),
|
||||
WIIU_READ_STICK(kpad->classic.lstick_y),
|
||||
WIIU_READ_STICK(kpad->classic.rstick_x),
|
||||
WIIU_READ_STICK(kpad->classic.rstick_y), 0, 0);
|
||||
break;
|
||||
case WIIMOTE_TYPE_NUNCHUK:
|
||||
wiimotes[channel].button_state = kpad->btns_h;
|
||||
pad_functions.set_axis_value(wiimotes[channel].analog_state,
|
||||
WIIU_READ_STICK(kpad->nunchuck.stick_x),
|
||||
WIIU_READ_STICK(kpad->nunchuck.stick_y), 0, 0, 0, 0);
|
||||
break;
|
||||
case WIIMOTE_TYPE_WIIPLUS:
|
||||
wiimotes[channel].button_state = kpad->btns_h;
|
||||
pad_functions.set_axis_value(wiimotes[channel].analog_state, 0, 0, 0, 0, 0, 0);
|
||||
break;
|
||||
}
|
||||
kpad_register(channel, kpad->device_type);
|
||||
switch(kpad->device_type)
|
||||
{
|
||||
case WIIMOTE_TYPE_PRO:
|
||||
wiimotes[channel].button_state = kpad->classic.btns_h
|
||||
& ~WIIU_PRO_BUTTON_MASK;
|
||||
pad_functions.set_axis_value(wiimotes[channel].analog_state,
|
||||
WIIU_READ_STICK(kpad->classic.lstick_x),
|
||||
WIIU_READ_STICK(kpad->classic.lstick_y),
|
||||
WIIU_READ_STICK(kpad->classic.rstick_x),
|
||||
WIIU_READ_STICK(kpad->classic.rstick_y), 0, 0);
|
||||
break;
|
||||
case WIIMOTE_TYPE_CLASSIC:
|
||||
wiimotes[channel].button_state = kpad->classic.btns_h
|
||||
& ~CLASSIC_BUTTON_MASK;
|
||||
pad_functions.set_axis_value(wiimotes[channel].analog_state,
|
||||
WIIU_READ_STICK(kpad->classic.lstick_x),
|
||||
WIIU_READ_STICK(kpad->classic.lstick_y),
|
||||
WIIU_READ_STICK(kpad->classic.rstick_x),
|
||||
WIIU_READ_STICK(kpad->classic.rstick_y), 0, 0);
|
||||
break;
|
||||
case WIIMOTE_TYPE_NUNCHUK:
|
||||
wiimotes[channel].button_state = kpad->btns_h;
|
||||
pad_functions.set_axis_value(wiimotes[channel].analog_state,
|
||||
WIIU_READ_STICK(kpad->nunchuck.stick_x),
|
||||
WIIU_READ_STICK(kpad->nunchuck.stick_y), 0, 0, 0, 0);
|
||||
break;
|
||||
case WIIMOTE_TYPE_WIIPLUS:
|
||||
wiimotes[channel].button_state = kpad->btns_h;
|
||||
pad_functions.set_axis_value(wiimotes[channel].analog_state,
|
||||
0, 0, 0, 0, 0, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void kpad_poll(void)
|
||||
{
|
||||
unsigned channel;
|
||||
unsigned channel;
|
||||
|
||||
for(channel = 0; channel < WIIU_WIIMOTE_CHANNELS; channel++)
|
||||
{
|
||||
KPADData kpad;
|
||||
for (channel = 0; channel < WIIU_WIIMOTE_CHANNELS; channel++)
|
||||
{
|
||||
KPADData kpad;
|
||||
|
||||
if(!KPADRead(channel, &kpad, 1))
|
||||
continue;
|
||||
if (!KPADRead(channel, &kpad, 1))
|
||||
continue;
|
||||
|
||||
kpad_poll_one_channel(channel, &kpad);
|
||||
}
|
||||
kpad_poll_one_channel(channel, &kpad);
|
||||
}
|
||||
}
|
||||
|
||||
static const char *kpad_name(unsigned pad)
|
||||
{
|
||||
pad = to_wiimote_channel(pad);
|
||||
if(pad >= WIIU_WIIMOTE_CHANNELS)
|
||||
return "unknown";
|
||||
pad = to_wiimote_channel(pad);
|
||||
if (pad >= WIIU_WIIMOTE_CHANNELS)
|
||||
return "unknown";
|
||||
|
||||
switch(wiimotes[pad].type)
|
||||
{
|
||||
case WIIMOTE_TYPE_PRO:
|
||||
return PAD_NAME_WIIU_PRO;
|
||||
case WIIMOTE_TYPE_CLASSIC:
|
||||
return PAD_NAME_CLASSIC;
|
||||
case WIIMOTE_TYPE_NUNCHUK:
|
||||
return PAD_NAME_NUNCHUK;
|
||||
case WIIMOTE_TYPE_WIIPLUS:
|
||||
return PAD_NAME_WIIMOTE;
|
||||
case WIIMOTE_TYPE_NONE:
|
||||
default:
|
||||
return "N/A";
|
||||
}
|
||||
switch(wiimotes[pad].type)
|
||||
{
|
||||
case WIIMOTE_TYPE_PRO:
|
||||
return PAD_NAME_WIIU_PRO;
|
||||
case WIIMOTE_TYPE_CLASSIC:
|
||||
return PAD_NAME_CLASSIC;
|
||||
case WIIMOTE_TYPE_NUNCHUK:
|
||||
return PAD_NAME_NUNCHUK;
|
||||
case WIIMOTE_TYPE_WIIPLUS:
|
||||
return PAD_NAME_WIIMOTE;
|
||||
case WIIMOTE_TYPE_NONE:
|
||||
default:
|
||||
return "N/A";
|
||||
}
|
||||
}
|
||||
|
||||
input_device_driver_t kpad_driver =
|
||||
{
|
||||
kpad_init,
|
||||
kpad_query_pad,
|
||||
kpad_destroy,
|
||||
kpad_button,
|
||||
kpad_get_buttons,
|
||||
kpad_axis,
|
||||
kpad_poll,
|
||||
NULL,
|
||||
kpad_name,
|
||||
"wiimote",
|
||||
kpad_init,
|
||||
kpad_query_pad,
|
||||
kpad_destroy,
|
||||
kpad_button,
|
||||
kpad_get_buttons,
|
||||
kpad_axis,
|
||||
kpad_poll,
|
||||
NULL,
|
||||
kpad_name,
|
||||
"wiimote",
|
||||
};
|
||||
|
@ -26,38 +26,42 @@ enum wiiu_pad_axes {
|
||||
AXIS_INVALID
|
||||
};
|
||||
|
||||
static int16_t clamp_axis(int16_t value, bool is_negative) {
|
||||
if(is_negative && value > 0)
|
||||
return 0;
|
||||
if(!is_negative && value < 0)
|
||||
return 0;
|
||||
static int16_t clamp_axis(int16_t value, bool is_negative)
|
||||
{
|
||||
if(is_negative && value > 0)
|
||||
return 0;
|
||||
if(!is_negative && value < 0)
|
||||
return 0;
|
||||
|
||||
return value;
|
||||
return value;
|
||||
}
|
||||
|
||||
static int16_t wiiu_pad_get_axis_value(int32_t axis, int16_t state[3][2], bool is_negative) {
|
||||
int16_t value = 0;
|
||||
static int16_t wiiu_pad_get_axis_value(int32_t axis,
|
||||
int16_t state[3][2], bool is_negative)
|
||||
{
|
||||
int16_t value = 0;
|
||||
|
||||
switch(axis) {
|
||||
case AXIS_LEFT_ANALOG_X:
|
||||
value = state[RETRO_DEVICE_INDEX_ANALOG_LEFT][RETRO_DEVICE_ID_ANALOG_X];
|
||||
break;
|
||||
case AXIS_LEFT_ANALOG_Y:
|
||||
value = state[RETRO_DEVICE_INDEX_ANALOG_LEFT][RETRO_DEVICE_ID_ANALOG_Y];
|
||||
break;
|
||||
case AXIS_RIGHT_ANALOG_X:
|
||||
value = state[RETRO_DEVICE_INDEX_ANALOG_RIGHT][RETRO_DEVICE_ID_ANALOG_X];
|
||||
break;
|
||||
case AXIS_RIGHT_ANALOG_Y:
|
||||
value = state[RETRO_DEVICE_INDEX_ANALOG_RIGHT][RETRO_DEVICE_ID_ANALOG_Y];
|
||||
break;
|
||||
case AXIS_TOUCH_X:
|
||||
return state[WIIU_DEVICE_INDEX_TOUCHPAD][RETRO_DEVICE_ID_ANALOG_X];
|
||||
case AXIS_TOUCH_Y:
|
||||
return state[WIIU_DEVICE_INDEX_TOUCHPAD][RETRO_DEVICE_ID_ANALOG_Y];
|
||||
}
|
||||
switch(axis)
|
||||
{
|
||||
case AXIS_LEFT_ANALOG_X:
|
||||
value = state[RETRO_DEVICE_INDEX_ANALOG_LEFT][RETRO_DEVICE_ID_ANALOG_X];
|
||||
break;
|
||||
case AXIS_LEFT_ANALOG_Y:
|
||||
value = state[RETRO_DEVICE_INDEX_ANALOG_LEFT][RETRO_DEVICE_ID_ANALOG_Y];
|
||||
break;
|
||||
case AXIS_RIGHT_ANALOG_X:
|
||||
value = state[RETRO_DEVICE_INDEX_ANALOG_RIGHT][RETRO_DEVICE_ID_ANALOG_X];
|
||||
break;
|
||||
case AXIS_RIGHT_ANALOG_Y:
|
||||
value = state[RETRO_DEVICE_INDEX_ANALOG_RIGHT][RETRO_DEVICE_ID_ANALOG_Y];
|
||||
break;
|
||||
case AXIS_TOUCH_X:
|
||||
return state[WIIU_DEVICE_INDEX_TOUCHPAD][RETRO_DEVICE_ID_ANALOG_X];
|
||||
case AXIS_TOUCH_Y:
|
||||
return state[WIIU_DEVICE_INDEX_TOUCHPAD][RETRO_DEVICE_ID_ANALOG_Y];
|
||||
}
|
||||
|
||||
return clamp_axis(value, is_negative);
|
||||
return clamp_axis(value, is_negative);
|
||||
}
|
||||
|
||||
void wiiu_pad_set_axis_value(int16_t state[3][2], int16_t left_x, int16_t left_y,
|
||||
@ -72,22 +76,23 @@ void wiiu_pad_set_axis_value(int16_t state[3][2], int16_t left_x, int16_t left_y
|
||||
}
|
||||
|
||||
|
||||
void wiiu_pad_read_axis_data(uint32_t axis, axis_data *data) {
|
||||
data->axis = AXIS_POS_GET(axis);
|
||||
data->is_negative = false;
|
||||
void wiiu_pad_read_axis_data(uint32_t axis, axis_data *data)
|
||||
{
|
||||
data->axis = AXIS_POS_GET(axis);
|
||||
data->is_negative = false;
|
||||
|
||||
if(data->axis >= AXIS_INVALID) {
|
||||
data->axis = AXIS_NEG_GET(axis);
|
||||
data->is_negative = true;
|
||||
}
|
||||
if(data->axis >= AXIS_INVALID)
|
||||
{
|
||||
data->axis = AXIS_NEG_GET(axis);
|
||||
data->is_negative = true;
|
||||
}
|
||||
}
|
||||
|
||||
void wiiu_pad_connect(unsigned pad, input_device_driver_t *driver) {
|
||||
if(!input_autoconfigure_connect(driver->name(pad), NULL, driver->ident,
|
||||
pad, VID_NONE, PID_NONE))
|
||||
{
|
||||
input_config_set_device_name(pad, driver->name(pad));
|
||||
}
|
||||
void wiiu_pad_connect(unsigned pad, input_device_driver_t *driver)
|
||||
{
|
||||
if(!input_autoconfigure_connect(driver->name(pad), NULL, driver->ident,
|
||||
pad, VID_NONE, PID_NONE))
|
||||
input_config_set_device_name(pad, driver->name(pad));
|
||||
}
|
||||
|
||||
wiiu_pad_functions_t pad_functions = {
|
||||
|
@ -21,21 +21,21 @@ static wiiu_adapter_list adapters;
|
||||
|
||||
static bool wiiu_hid_joypad_query(void *data, unsigned slot)
|
||||
{
|
||||
wiiu_hid_t *hid = (wiiu_hid_t *)data;
|
||||
if(!hid)
|
||||
return false;
|
||||
wiiu_hid_t *hid = (wiiu_hid_t *)data;
|
||||
if (!hid)
|
||||
return false;
|
||||
|
||||
return slot < hid->connections_size;
|
||||
return slot < hid->connections_size;
|
||||
}
|
||||
|
||||
static const char *wiiu_hid_joypad_name(void *data, unsigned slot)
|
||||
{
|
||||
if(!wiiu_hid_joypad_query(data, slot))
|
||||
return NULL;
|
||||
if (!wiiu_hid_joypad_query(data, slot))
|
||||
return NULL;
|
||||
|
||||
wiiu_hid_t *hid = (wiiu_hid_t *)data;
|
||||
wiiu_hid_t *hid = (wiiu_hid_t *)data;
|
||||
|
||||
return hid->connections[slot].iface->get_name(data);
|
||||
return hid->connections[slot].iface->get_name(data);
|
||||
}
|
||||
|
||||
static void wiiu_hid_joypad_get_buttons(void *data, unsigned port, retro_bits_t *state)
|
||||
@ -81,14 +81,13 @@ static void *wiiu_hid_init(void)
|
||||
wiiu_hid_t *hid = new_hid();
|
||||
HIDClient *client = new_hidclient();
|
||||
|
||||
if(!hid || !client) {
|
||||
goto error;
|
||||
}
|
||||
if (!hid || !client)
|
||||
goto error;
|
||||
|
||||
wiiu_hid_init_lists();
|
||||
start_polling_thread(hid);
|
||||
if(!hid->polling_thread)
|
||||
goto error;
|
||||
if (!hid->polling_thread)
|
||||
goto error;
|
||||
|
||||
RARCH_LOG("[hid]: Registering HIDClient\n");
|
||||
HIDAddClient(client, wiiu_attach_callback);
|
||||
@ -97,30 +96,34 @@ static void *wiiu_hid_init(void)
|
||||
RARCH_LOG("[hid]: init success\n");
|
||||
return hid;
|
||||
|
||||
error:
|
||||
RARCH_LOG("[hid]: initialization failed. cleaning up.\n");
|
||||
stop_polling_thread(hid);
|
||||
delete_hid(hid);
|
||||
delete_hidclient(client);
|
||||
return NULL;
|
||||
error:
|
||||
RARCH_LOG("[hid]: initialization failed. cleaning up.\n");
|
||||
stop_polling_thread(hid);
|
||||
delete_hid(hid);
|
||||
delete_hidclient(client);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void wiiu_hid_free(const void *data)
|
||||
{
|
||||
wiiu_hid_t *hid = (wiiu_hid_t*)data;
|
||||
|
||||
if (hid) {
|
||||
stop_polling_thread(hid);
|
||||
delete_hidclient(hid->client);
|
||||
delete_hid(hid);
|
||||
if(events.list) {
|
||||
wiiu_attach_event *event;
|
||||
while( (event = events.list) != NULL) {
|
||||
events.list = event->next;
|
||||
delete_attach_event(event);
|
||||
}
|
||||
memset(&events, 0, sizeof(events));
|
||||
if (!hid)
|
||||
return;
|
||||
|
||||
stop_polling_thread(hid);
|
||||
delete_hidclient(hid->client);
|
||||
delete_hid(hid);
|
||||
|
||||
if (events.list)
|
||||
{
|
||||
wiiu_attach_event *event = NULL;
|
||||
while( (event = events.list) != NULL)
|
||||
{
|
||||
events.list = event->next;
|
||||
delete_attach_event(event);
|
||||
}
|
||||
memset(&events, 0, sizeof(events));
|
||||
}
|
||||
}
|
||||
|
||||
@ -131,220 +134,238 @@ static void wiiu_hid_poll(void *data)
|
||||
|
||||
static void wiiu_hid_send_control(void *data, uint8_t *buf, size_t size)
|
||||
{
|
||||
wiiu_adapter_t *adapter = (wiiu_adapter_t *)data;
|
||||
if(!adapter)
|
||||
return;
|
||||
wiiu_adapter_t *adapter = (wiiu_adapter_t *)data;
|
||||
if (!adapter)
|
||||
return;
|
||||
|
||||
HIDWrite(adapter->handle, buf, size, NULL, NULL);
|
||||
HIDWrite(adapter->handle, buf, size, NULL, NULL);
|
||||
}
|
||||
|
||||
static int32_t wiiu_hid_set_report(void *data, uint8_t report_type,
|
||||
uint8_t report_id, void *report_data, uint32_t report_length)
|
||||
{
|
||||
wiiu_adapter_t *adapter = (wiiu_adapter_t *)data;
|
||||
if(!adapter)
|
||||
return -1;
|
||||
wiiu_adapter_t *adapter = (wiiu_adapter_t *)data;
|
||||
if (!adapter)
|
||||
return -1;
|
||||
|
||||
return HIDSetReport(adapter->handle,
|
||||
report_type,
|
||||
report_id,
|
||||
report_data,
|
||||
report_length,
|
||||
NULL, NULL);
|
||||
return HIDSetReport(adapter->handle,
|
||||
report_type,
|
||||
report_id,
|
||||
report_data,
|
||||
report_length,
|
||||
NULL, NULL);
|
||||
}
|
||||
|
||||
static int32_t wiiu_hid_set_idle(void *data, uint8_t duration)
|
||||
{
|
||||
wiiu_adapter_t *adapter = (wiiu_adapter_t *)data;
|
||||
if(!adapter)
|
||||
return -1;
|
||||
wiiu_adapter_t *adapter = (wiiu_adapter_t *)data;
|
||||
if (!adapter)
|
||||
return -1;
|
||||
|
||||
return HIDSetIdle(adapter->handle,
|
||||
adapter->interface_index,
|
||||
duration,
|
||||
NULL, NULL);
|
||||
return HIDSetIdle(adapter->handle,
|
||||
adapter->interface_index,
|
||||
duration,
|
||||
NULL, NULL);
|
||||
}
|
||||
|
||||
static int32_t wiiu_hid_set_protocol(void *data, uint8_t protocol)
|
||||
{
|
||||
wiiu_adapter_t *adapter = (wiiu_adapter_t *)data;
|
||||
if(!adapter)
|
||||
return -1;
|
||||
wiiu_adapter_t *adapter = (wiiu_adapter_t *)data;
|
||||
if (!adapter)
|
||||
return -1;
|
||||
|
||||
return HIDSetProtocol(adapter->handle,
|
||||
adapter->interface_index,
|
||||
protocol,
|
||||
NULL, NULL);
|
||||
return HIDSetProtocol(adapter->handle,
|
||||
adapter->interface_index,
|
||||
protocol,
|
||||
NULL, NULL);
|
||||
}
|
||||
|
||||
static void start_polling_thread(wiiu_hid_t *hid) {
|
||||
RARCH_LOG("[hid]: starting polling thread.\n");
|
||||
OSThreadAttributes attributes = OS_THREAD_ATTRIB_AFFINITY_CPU2;
|
||||
BOOL result;
|
||||
static void start_polling_thread(wiiu_hid_t *hid)
|
||||
{
|
||||
OSThreadAttributes attributes = OS_THREAD_ATTRIB_AFFINITY_CPU2;
|
||||
BOOL result = false;
|
||||
int32_t stack_size = 0x8000;
|
||||
int32_t priority = 10;
|
||||
OSThread *thread = new_thread();
|
||||
void *stack = alloc_zeroed(16, stack_size);
|
||||
|
||||
int32_t stack_size = 0x8000;
|
||||
int32_t priority = 10;
|
||||
OSThread *thread = new_thread();
|
||||
void *stack = alloc_zeroed(16, stack_size);
|
||||
RARCH_LOG("[hid]: starting polling thread.\n");
|
||||
|
||||
if(!thread || !stack) {
|
||||
RARCH_LOG("[hid]: allocation failed, aborting thread start.\n");
|
||||
goto error;
|
||||
}
|
||||
if (!thread || !stack)
|
||||
{
|
||||
RARCH_LOG("[hid]: allocation failed, aborting thread start.\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
RARCH_LOG("[hid]: thread: 0x%x; stack: 0x%x\n", thread, stack);
|
||||
RARCH_LOG("[hid]: thread: 0x%x; stack: 0x%x\n", thread, stack);
|
||||
|
||||
if(!OSCreateThread(thread,
|
||||
wiiu_hid_polling_thread,
|
||||
1, (char *)hid,
|
||||
stack+stack_size, stack_size,
|
||||
priority,
|
||||
attributes)) {
|
||||
RARCH_LOG("[hid]: OSCreateThread failed.\n");
|
||||
goto error;
|
||||
}
|
||||
if (!OSCreateThread(thread,
|
||||
wiiu_hid_polling_thread,
|
||||
1, (char *)hid,
|
||||
stack+stack_size, stack_size,
|
||||
priority,
|
||||
attributes))
|
||||
{
|
||||
RARCH_LOG("[hid]: OSCreateThread failed.\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
OSSetThreadCleanupCallback(thread, wiiu_hid_polling_thread_cleanup);
|
||||
OSSetThreadCleanupCallback(thread, wiiu_hid_polling_thread_cleanup);
|
||||
|
||||
hid->polling_thread = thread;
|
||||
hid->polling_thread_stack = stack;
|
||||
OSResumeThread(thread);
|
||||
return;
|
||||
hid->polling_thread = thread;
|
||||
hid->polling_thread_stack = stack;
|
||||
OSResumeThread(thread);
|
||||
return;
|
||||
|
||||
error:
|
||||
if(thread)
|
||||
error:
|
||||
if (thread)
|
||||
free(thread);
|
||||
if(stack)
|
||||
if (stack)
|
||||
free(stack);
|
||||
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
static void stop_polling_thread(wiiu_hid_t *hid) {
|
||||
int thread_result = 0;
|
||||
RARCH_LOG("[hid]: stopping polling thread.\n");
|
||||
static void stop_polling_thread(wiiu_hid_t *hid)
|
||||
{
|
||||
int thread_result = 0;
|
||||
RARCH_LOG("[hid]: stopping polling thread.\n");
|
||||
|
||||
if(!hid || !hid->polling_thread)
|
||||
return;
|
||||
if (!hid || !hid->polling_thread)
|
||||
return;
|
||||
|
||||
hid->polling_thread_quit = true;
|
||||
OSJoinThread(hid->polling_thread, &thread_result);
|
||||
free(hid->polling_thread);
|
||||
free(hid->polling_thread_stack);
|
||||
hid->polling_thread = NULL;
|
||||
hid->polling_thread_stack = NULL;
|
||||
hid->polling_thread_quit = true;
|
||||
OSJoinThread(hid->polling_thread, &thread_result);
|
||||
free(hid->polling_thread);
|
||||
free(hid->polling_thread_stack);
|
||||
hid->polling_thread = NULL;
|
||||
hid->polling_thread_stack = NULL;
|
||||
}
|
||||
|
||||
static void log_device(HIDDevice *device) {
|
||||
if(!device) {
|
||||
RARCH_LOG("NULL device.\n");
|
||||
}
|
||||
static void log_device(HIDDevice *device)
|
||||
{
|
||||
if (!device)
|
||||
{
|
||||
RARCH_LOG("NULL device.\n");
|
||||
}
|
||||
|
||||
RARCH_LOG(" handle: %d\n", device->handle);
|
||||
RARCH_LOG(" physical_device_inst: %d\n", device->physical_device_inst);
|
||||
RARCH_LOG(" vid: 0x%x\n", device->vid);
|
||||
RARCH_LOG(" pid: 0x%x\n", device->pid);
|
||||
RARCH_LOG(" interface_index: %d\n", device->interface_index);
|
||||
RARCH_LOG(" sub_class: %d\n", device->sub_class);
|
||||
RARCH_LOG(" protocol: %d\n", device->protocol);
|
||||
RARCH_LOG(" max_packet_size_rx: %d\n", device->max_packet_size_rx);
|
||||
RARCH_LOG(" max_packet_size_tx: %d\n", device->max_packet_size_tx);
|
||||
RARCH_LOG(" handle: %d\n", device->handle);
|
||||
RARCH_LOG(" physical_device_inst: %d\n", device->physical_device_inst);
|
||||
RARCH_LOG(" vid: 0x%x\n", device->vid);
|
||||
RARCH_LOG(" pid: 0x%x\n", device->pid);
|
||||
RARCH_LOG(" interface_index: %d\n", device->interface_index);
|
||||
RARCH_LOG(" sub_class: %d\n", device->sub_class);
|
||||
RARCH_LOG(" protocol: %d\n", device->protocol);
|
||||
RARCH_LOG(" max_packet_size_rx: %d\n", device->max_packet_size_rx);
|
||||
RARCH_LOG(" max_packet_size_tx: %d\n", device->max_packet_size_tx);
|
||||
}
|
||||
|
||||
|
||||
static void synchronized_add_event(wiiu_attach_event *event) {
|
||||
OSFastMutex_Lock(&(events.lock));
|
||||
event->next = events.list;
|
||||
events.list = event;
|
||||
OSFastMutex_Unlock(&(events.lock));
|
||||
static void synchronized_add_event(wiiu_attach_event *event)
|
||||
{
|
||||
OSFastMutex_Lock(&(events.lock));
|
||||
event->next = events.list;
|
||||
events.list = event;
|
||||
OSFastMutex_Unlock(&(events.lock));
|
||||
}
|
||||
|
||||
static wiiu_attach_event *synchronized_get_events_list(void) {
|
||||
wiiu_attach_event *list;
|
||||
OSFastMutex_Lock(&(events.lock));
|
||||
list = events.list;
|
||||
events.list = NULL;
|
||||
OSFastMutex_Unlock(&(events.lock));
|
||||
static wiiu_attach_event *synchronized_get_events_list(void)
|
||||
{
|
||||
wiiu_attach_event *list;
|
||||
OSFastMutex_Lock(&(events.lock));
|
||||
list = events.list;
|
||||
events.list = NULL;
|
||||
OSFastMutex_Unlock(&(events.lock));
|
||||
|
||||
return list;
|
||||
return list;
|
||||
}
|
||||
|
||||
static void synchronized_add_to_adapters_list(wiiu_adapter_t *adapter) {
|
||||
OSFastMutex_Lock(&(adapters.lock));
|
||||
adapter->next = adapters.list;
|
||||
adapters.list = adapter;
|
||||
OSFastMutex_Unlock(&(adapters.lock));
|
||||
static void synchronized_add_to_adapters_list(wiiu_adapter_t *adapter)
|
||||
{
|
||||
OSFastMutex_Lock(&(adapters.lock));
|
||||
adapter->next = adapters.list;
|
||||
adapters.list = adapter;
|
||||
OSFastMutex_Unlock(&(adapters.lock));
|
||||
}
|
||||
|
||||
static int32_t wiiu_attach_callback(HIDClient *client, HIDDevice *device, uint32_t attach) {
|
||||
wiiu_attach_event *event;
|
||||
log_device(device);
|
||||
switch(attach) {
|
||||
case HID_DEVICE_ATTACH:
|
||||
case HID_DEVICE_DETACH:
|
||||
event = new_attach_event(device);
|
||||
if(!event)
|
||||
goto error;
|
||||
static int32_t wiiu_attach_callback(HIDClient *client,
|
||||
HIDDevice *device, uint32_t attach)
|
||||
{
|
||||
wiiu_attach_event *event = NULL;
|
||||
|
||||
event->type = attach;
|
||||
synchronized_add_event(event);
|
||||
return DEVICE_USED;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
log_device(device);
|
||||
|
||||
error:
|
||||
delete_attach_event(event);
|
||||
return DEVICE_UNUSED;
|
||||
switch(attach)
|
||||
{
|
||||
case HID_DEVICE_ATTACH:
|
||||
case HID_DEVICE_DETACH:
|
||||
if (device)
|
||||
event = new_attach_event(device);
|
||||
|
||||
if(!event)
|
||||
goto error;
|
||||
|
||||
event->type = attach;
|
||||
synchronized_add_event(event);
|
||||
return DEVICE_USED;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
error:
|
||||
delete_attach_event(event);
|
||||
return DEVICE_UNUSED;
|
||||
}
|
||||
|
||||
static void wiiu_hid_detach(wiiu_hid_t *hid, wiiu_attach_event *event)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
static void wiiu_hid_attach(wiiu_hid_t *hid, wiiu_attach_event *event)
|
||||
{
|
||||
wiiu_adapter_t *adapter = new_adapter(event);
|
||||
|
||||
static void wiiu_hid_detach(wiiu_hid_t *hid, wiiu_attach_event *event) {
|
||||
}
|
||||
if(!adapter)
|
||||
{
|
||||
RARCH_ERR("[hid]: Failed to allocate adapter.\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
adapter->hid = hid;
|
||||
adapter->slot = pad_connection_pad_init(hid->connections,
|
||||
"hid", event->vendor_id, event->product_id, adapter,
|
||||
&wiiu_hid);
|
||||
|
||||
static void wiiu_hid_attach(wiiu_hid_t *hid, wiiu_attach_event *event) {
|
||||
wiiu_adapter_t *adapter = new_adapter(event);
|
||||
if(adapter->slot < 0)
|
||||
{
|
||||
RARCH_ERR("[hid]: No available slots.\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
if(!adapter) {
|
||||
RARCH_ERR("[hid]: Failed to allocate adapter.\n");
|
||||
goto error;
|
||||
}
|
||||
RARCH_LOG("[hid]: got slot %d\n", adapter->slot);
|
||||
|
||||
adapter->hid = hid;
|
||||
if(!pad_connection_has_interface(hid->connections, adapter->slot))
|
||||
{
|
||||
RARCH_ERR("[hid]: Interface not found for HID device with vid=0x%04x pid=0x%04x\n",
|
||||
event->vendor_id, event->product_id);
|
||||
goto error;
|
||||
}
|
||||
|
||||
RARCH_LOG("[hid]: pad_connection_pad_init\n");
|
||||
adapter->slot = pad_connection_pad_init(hid->connections,
|
||||
"hid", event->vendor_id, event->product_id, adapter,
|
||||
&wiiu_hid);
|
||||
RARCH_LOG("[hid]: adding to adapter list\n");
|
||||
synchronized_add_to_adapters_list(adapter);
|
||||
|
||||
if(adapter->slot < 0) {
|
||||
RARCH_ERR("[hid]: No available slots.\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
RARCH_LOG("[hid]: got slot %d\n", adapter->slot);
|
||||
|
||||
if(!pad_connection_has_interface(hid->connections, adapter->slot)) {
|
||||
RARCH_ERR("[hid]: Interface not found for HID device with vid=0x%04x pid=0x%04x\n",
|
||||
event->vendor_id, event->product_id);
|
||||
goto error;
|
||||
}
|
||||
|
||||
RARCH_LOG("[hid]: adding to adapter list\n");
|
||||
synchronized_add_to_adapters_list(adapter);
|
||||
#if 0
|
||||
// this is breaking again. Not sure why. But disabling it now so the
|
||||
// startup/shutdown times aren't affected by the blocking call.
|
||||
RARCH_LOG("[hid]: starting read loop\n");
|
||||
wiiu_start_read_loop(adapter);
|
||||
/* this is breaking again. Not sure why. But disabling it now so the
|
||||
* startup/shutdown times aren't affected by the blocking call. */
|
||||
RARCH_LOG("[hid]: starting read loop\n");
|
||||
wiiu_start_read_loop(adapter);
|
||||
#endif
|
||||
return;
|
||||
return;
|
||||
|
||||
error:
|
||||
delete_adapter(adapter);
|
||||
error:
|
||||
delete_adapter(adapter);
|
||||
}
|
||||
|
||||
void wiiu_start_read_loop(wiiu_adapter_t *adapter)
|
||||
@ -368,42 +389,50 @@ void wiiu_start_read_loop(wiiu_adapter_t *adapter)
|
||||
* 0102030405ffffff ffffffffffffffff
|
||||
* ==================================
|
||||
*/
|
||||
static void log_buffer(uint8_t *data, uint32_t len) {
|
||||
(uint8_t *)data;
|
||||
(uint32_t)len;
|
||||
static void log_buffer(uint8_t *data, uint32_t len)
|
||||
{
|
||||
int i, o;
|
||||
int padding = len % 16;
|
||||
uint8_t buf[16];
|
||||
|
||||
int i, o;
|
||||
int padding = len % 16;
|
||||
uint8_t buf[16];
|
||||
(uint8_t *)data;
|
||||
(uint32_t)len;
|
||||
|
||||
RARCH_LOG("%d bytes read from HIDRead:\n", len);
|
||||
|
||||
for(i = 0, o = 0; i < len; i++)
|
||||
{
|
||||
buf[o] = data[i];
|
||||
o++;
|
||||
if(o == 16)
|
||||
{
|
||||
o = 0;
|
||||
RARCH_LOG("%02x%02x%02x%02x%02x%02x%02x%02x %02x%02x%02x%02x%02x%02x%02x%02x\n",
|
||||
buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7],
|
||||
buf[8], buf[9], buf[10], buf[11], buf[12], buf[13], buf[14], buf[15]);
|
||||
}
|
||||
}
|
||||
|
||||
if(padding)
|
||||
{
|
||||
for(i = padding; i < 16; i++)
|
||||
buf[i] = 0xff;
|
||||
|
||||
RARCH_LOG("%d bytes read from HIDRead:\n", len);
|
||||
for(i = 0, o = 0; i < len; i++) {
|
||||
buf[o] = data[i];
|
||||
o++;
|
||||
if(o == 16) {
|
||||
o = 0;
|
||||
RARCH_LOG("%02x%02x%02x%02x%02x%02x%02x%02x %02x%02x%02x%02x%02x%02x%02x%02x\n",
|
||||
buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7],
|
||||
buf[8], buf[9], buf[10], buf[11], buf[12], buf[13], buf[14], buf[15]);
|
||||
}
|
||||
}
|
||||
if(padding) {
|
||||
for(i = padding; i < 16; i++)
|
||||
buf[i] = 0xff;
|
||||
|
||||
RARCH_LOG("%02x%02x%02x%02x%02x%02x%02x%02x %02x%02x%02x%02x%02x%02x%02x%02x\n",
|
||||
buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7],
|
||||
buf[8], buf[9], buf[10], buf[11], buf[12], buf[13], buf[14], buf[15]);
|
||||
}
|
||||
RARCH_LOG("==================================\n");
|
||||
buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7],
|
||||
buf[8], buf[9], buf[10], buf[11], buf[12], buf[13], buf[14], buf[15]);
|
||||
}
|
||||
RARCH_LOG("==================================\n");
|
||||
|
||||
}
|
||||
|
||||
static void wiiu_hid_do_read(wiiu_adapter_t *adapter, uint8_t *data, uint32_t length)
|
||||
static void wiiu_hid_do_read(wiiu_adapter_t *adapter,
|
||||
uint8_t *data, uint32_t length)
|
||||
{
|
||||
// log_buffer(data, length);
|
||||
// do_sampling()
|
||||
// do other stuff?
|
||||
/* log_buffer(data, length);
|
||||
* do_sampling()
|
||||
* do other stuff?
|
||||
*/
|
||||
}
|
||||
|
||||
static void wiiu_hid_read_loop_callback(uint32_t handle, int32_t error,
|
||||
@ -416,7 +445,8 @@ static void wiiu_hid_read_loop_callback(uint32_t handle, int32_t error,
|
||||
return;
|
||||
}
|
||||
|
||||
if(adapter->hid->polling_thread_quit) {
|
||||
if(adapter->hid->polling_thread_quit)
|
||||
{
|
||||
RARCH_LOG("Shutting down read loop for slot %d\n", adapter->slot);
|
||||
adapter->state = ADAPTER_STATE_DONE;
|
||||
return;
|
||||
@ -432,168 +462,197 @@ static void wiiu_hid_read_loop_callback(uint32_t handle, int32_t error,
|
||||
/**
|
||||
* Block until all the HIDRead() calls have returned.
|
||||
*/
|
||||
static void wiiu_hid_polling_thread_cleanup(OSThread *thread, void *stack) {
|
||||
int incomplete = 0;
|
||||
int retries = 0;
|
||||
wiiu_adapter_t *adapter;
|
||||
RARCH_LOG("Waiting for in-flight reads to finish.\n");
|
||||
do {
|
||||
OSFastMutex_Lock(&(adapters.lock));
|
||||
incomplete = 0;
|
||||
for(adapter = adapters.list; adapter != NULL; adapter = adapter->next) {
|
||||
if(adapter->state == ADAPTER_STATE_READING) {
|
||||
incomplete++;
|
||||
}
|
||||
}
|
||||
// We are clear for shutdown. Clean up the list while we are holding
|
||||
// the lock.
|
||||
if(incomplete == 0) {
|
||||
while(adapters.list != NULL) {
|
||||
adapter = adapters.list;
|
||||
adapters.list = adapter->next;
|
||||
delete_adapter(adapter);
|
||||
}
|
||||
}
|
||||
OSFastMutex_Unlock(&(adapters.lock));
|
||||
if(incomplete) {
|
||||
usleep(5000);
|
||||
}
|
||||
if(++retries >= 1000) {
|
||||
RARCH_WARN("[hid]: timed out waiting for in-flight read to finish.\n");
|
||||
static void wiiu_hid_polling_thread_cleanup(OSThread *thread, void *stack)
|
||||
{
|
||||
int incomplete = 0;
|
||||
int retries = 0;
|
||||
wiiu_adapter_t *adapter = NULL;
|
||||
|
||||
RARCH_LOG("Waiting for in-flight reads to finish.\n");
|
||||
|
||||
do
|
||||
{
|
||||
OSFastMutex_Lock(&(adapters.lock));
|
||||
incomplete = 0;
|
||||
}
|
||||
} while(incomplete);
|
||||
RARCH_LOG("All in-flight reads complete.\n");
|
||||
for(adapter = adapters.list; adapter != NULL; adapter = adapter->next)
|
||||
{
|
||||
if(adapter->state == ADAPTER_STATE_READING)
|
||||
incomplete++;
|
||||
}
|
||||
/* We are clear for shutdown. Clean up the list
|
||||
* while we are holding the lock. */
|
||||
if(incomplete == 0)
|
||||
{
|
||||
while(adapters.list != NULL)
|
||||
{
|
||||
adapter = adapters.list;
|
||||
adapters.list = adapter->next;
|
||||
delete_adapter(adapter);
|
||||
}
|
||||
}
|
||||
OSFastMutex_Unlock(&(adapters.lock));
|
||||
|
||||
if(incomplete)
|
||||
usleep(5000);
|
||||
|
||||
if(++retries >= 1000)
|
||||
{
|
||||
RARCH_WARN("[hid]: timed out waiting for in-flight read to finish.\n");
|
||||
incomplete = 0;
|
||||
}
|
||||
}while(incomplete);
|
||||
|
||||
RARCH_LOG("All in-flight reads complete.\n");
|
||||
}
|
||||
|
||||
static void wiiu_handle_attach_events(wiiu_hid_t *hid, wiiu_attach_event *list) {
|
||||
wiiu_attach_event *event, *event_next = NULL;
|
||||
static void wiiu_handle_attach_events(wiiu_hid_t *hid, wiiu_attach_event *list)
|
||||
{
|
||||
wiiu_attach_event *event, *event_next = NULL;
|
||||
|
||||
if(!hid || !list)
|
||||
return;
|
||||
if(!hid || !list)
|
||||
return;
|
||||
|
||||
for(event = list; event != NULL; event = event_next ) {
|
||||
event_next = event->next;
|
||||
if(event->type == HID_DEVICE_ATTACH) {
|
||||
wiiu_hid_attach(hid, event);
|
||||
} else {
|
||||
wiiu_hid_detach(hid, event);
|
||||
}
|
||||
delete_attach_event(event);
|
||||
}
|
||||
for(event = list; event != NULL; event = event_next)
|
||||
{
|
||||
event_next = event->next;
|
||||
if(event->type == HID_DEVICE_ATTACH)
|
||||
wiiu_hid_attach(hid, event);
|
||||
else
|
||||
wiiu_hid_detach(hid, event);
|
||||
delete_attach_event(event);
|
||||
}
|
||||
}
|
||||
|
||||
static int wiiu_hid_polling_thread(int argc, const char **argv) {
|
||||
wiiu_hid_t *hid = (wiiu_hid_t *)argv;
|
||||
int i = 0;
|
||||
RARCH_LOG("[hid]: polling thread is starting\n");
|
||||
while(!hid->polling_thread_quit) {
|
||||
wiiu_handle_attach_events(hid, synchronized_get_events_list());
|
||||
usleep(10000);
|
||||
i += 10000;
|
||||
if(i >= (1000 * 1000 * 3)) {
|
||||
RARCH_LOG("[hid]: thread: TICK!\n");
|
||||
i = 0;
|
||||
}
|
||||
}
|
||||
static int wiiu_hid_polling_thread(int argc, const char **argv)
|
||||
{
|
||||
wiiu_hid_t *hid = (wiiu_hid_t *)argv;
|
||||
int i = 0;
|
||||
|
||||
RARCH_LOG("[hid]: polling thread is stopping\n");
|
||||
return 0;
|
||||
RARCH_LOG("[hid]: polling thread is starting\n");
|
||||
|
||||
while(!hid->polling_thread_quit)
|
||||
{
|
||||
wiiu_handle_attach_events(hid, synchronized_get_events_list());
|
||||
usleep(10000);
|
||||
i += 10000;
|
||||
if(i >= (1000 * 1000 * 3))
|
||||
i = 0;
|
||||
}
|
||||
|
||||
RARCH_LOG("[hid]: polling thread is stopping\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static OSThread *new_thread(void) {
|
||||
OSThread *t = alloc_zeroed(8, sizeof(OSThread));
|
||||
t->tag = OS_THREAD_TAG;
|
||||
static OSThread *new_thread(void)
|
||||
{
|
||||
OSThread *t = alloc_zeroed(8, sizeof(OSThread));
|
||||
|
||||
return t;
|
||||
if (!t)
|
||||
return NULL;
|
||||
|
||||
t->tag = OS_THREAD_TAG;
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
static void wiiu_hid_init_lists(void) {
|
||||
RARCH_LOG("[hid]: Initializing events list\n");
|
||||
memset(&events, 0, sizeof(events));
|
||||
OSFastMutex_Init(&(events.lock), "attach_events");
|
||||
RARCH_LOG("[hid]: Initializing adapters list\n");
|
||||
memset(&adapters, 0, sizeof(adapters));
|
||||
OSFastMutex_Init(&(adapters.lock), "adapters");
|
||||
static void wiiu_hid_init_lists(void)
|
||||
{
|
||||
RARCH_LOG("[hid]: Initializing events list\n");
|
||||
memset(&events, 0, sizeof(events));
|
||||
OSFastMutex_Init(&(events.lock), "attach_events");
|
||||
RARCH_LOG("[hid]: Initializing adapters list\n");
|
||||
memset(&adapters, 0, sizeof(adapters));
|
||||
OSFastMutex_Init(&(adapters.lock), "adapters");
|
||||
}
|
||||
|
||||
static wiiu_hid_t *new_hid(void) {
|
||||
RARCH_LOG("[hid]: new_hid()\n");
|
||||
return alloc_zeroed(4, sizeof(wiiu_hid_t));
|
||||
static wiiu_hid_t *new_hid(void)
|
||||
{
|
||||
RARCH_LOG("[hid]: new_hid()\n");
|
||||
return alloc_zeroed(4, sizeof(wiiu_hid_t));
|
||||
}
|
||||
|
||||
static void delete_hid(wiiu_hid_t *hid) {
|
||||
RARCH_LOG("[hid]: delete_hid()\n");
|
||||
if(hid)
|
||||
free(hid);
|
||||
static void delete_hid(wiiu_hid_t *hid)
|
||||
{
|
||||
RARCH_LOG("[hid]: delete_hid()\n");
|
||||
if(hid)
|
||||
free(hid);
|
||||
}
|
||||
|
||||
static HIDClient *new_hidclient(void) {
|
||||
RARCH_LOG("[hid]: new_hidclient()\n");
|
||||
return alloc_zeroed(32, sizeof(HIDClient));
|
||||
static HIDClient *new_hidclient(void)
|
||||
{
|
||||
RARCH_LOG("[hid]: new_hidclient()\n");
|
||||
return alloc_zeroed(32, sizeof(HIDClient));
|
||||
}
|
||||
|
||||
static void delete_hidclient(HIDClient *client) {
|
||||
RARCH_LOG("[hid]: delete_hidclient()\n");
|
||||
if(client)
|
||||
free(client);
|
||||
static void delete_hidclient(HIDClient *client)
|
||||
{
|
||||
RARCH_LOG("[hid]: delete_hidclient()\n");
|
||||
if(client)
|
||||
free(client);
|
||||
}
|
||||
|
||||
static wiiu_adapter_t *new_adapter(wiiu_attach_event *event) {
|
||||
RARCH_LOG("[hid]: new_adapter()\n");
|
||||
static wiiu_adapter_t *new_adapter(wiiu_attach_event *event)
|
||||
{
|
||||
wiiu_adapter_t *adapter = alloc_zeroed(64, sizeof(wiiu_adapter_t));
|
||||
|
||||
wiiu_adapter_t *adapter = alloc_zeroed(64, sizeof(wiiu_adapter_t));
|
||||
adapter->handle = event->handle;
|
||||
adapter->interface_index = event->interface_index;
|
||||
adapter->rx_size = event->max_packet_size_rx;
|
||||
adapter->rx_buffer = alloc_zeroed(64, adapter->rx_size);
|
||||
if (!adapter)
|
||||
return NULL;
|
||||
|
||||
return adapter;
|
||||
adapter->handle = event->handle;
|
||||
adapter->interface_index = event->interface_index;
|
||||
adapter->rx_size = event->max_packet_size_rx;
|
||||
adapter->rx_buffer = alloc_zeroed(64, adapter->rx_size);
|
||||
|
||||
return adapter;
|
||||
}
|
||||
|
||||
static void delete_adapter(wiiu_adapter_t *adapter) {
|
||||
RARCH_LOG("[hid]: delete_adapter()\n");
|
||||
if(adapter) {
|
||||
if(adapter->rx_buffer) {
|
||||
static void delete_adapter(wiiu_adapter_t *adapter)
|
||||
{
|
||||
if (!adapter)
|
||||
return;
|
||||
|
||||
if(adapter->rx_buffer)
|
||||
{
|
||||
free(adapter->rx_buffer);
|
||||
adapter->rx_buffer = NULL;
|
||||
}
|
||||
free(adapter);
|
||||
}
|
||||
}
|
||||
free(adapter);
|
||||
}
|
||||
|
||||
static wiiu_attach_event *new_attach_event(HIDDevice *device) {
|
||||
if(!device)
|
||||
return NULL;
|
||||
static wiiu_attach_event *new_attach_event(HIDDevice *device)
|
||||
{
|
||||
wiiu_attach_event *event = alloc_zeroed(4, sizeof(wiiu_attach_event));
|
||||
if(!event)
|
||||
return NULL;
|
||||
|
||||
wiiu_attach_event *event = alloc_zeroed(4, sizeof(wiiu_attach_event));
|
||||
if(!event)
|
||||
return NULL;
|
||||
event->handle = device->handle;
|
||||
event->vendor_id = device->vid;
|
||||
event->product_id = device->pid;
|
||||
event->interface_index = device->interface_index;
|
||||
event->is_keyboard = (device->sub_class == 1 && device->protocol == 1);
|
||||
event->is_mouse = (device->sub_class == 1 && device->protocol == 2);
|
||||
event->max_packet_size_rx = device->max_packet_size_rx;
|
||||
event->max_packet_size_tx = device->max_packet_size_tx;
|
||||
event->handle = device->handle;
|
||||
event->vendor_id = device->vid;
|
||||
event->product_id = device->pid;
|
||||
event->interface_index = device->interface_index;
|
||||
event->is_keyboard = (device->sub_class == 1
|
||||
&& device->protocol == 1);
|
||||
event->is_mouse = (device->sub_class == 1
|
||||
&& device->protocol == 2);
|
||||
event->max_packet_size_rx = device->max_packet_size_rx;
|
||||
event->max_packet_size_tx = device->max_packet_size_tx;
|
||||
|
||||
return event;
|
||||
return event;
|
||||
}
|
||||
|
||||
static void delete_attach_event(wiiu_attach_event *event) {
|
||||
if(event)
|
||||
free(event);
|
||||
static void delete_attach_event(wiiu_attach_event *event)
|
||||
{
|
||||
if(event)
|
||||
free(event);
|
||||
}
|
||||
|
||||
|
||||
void *alloc_zeroed(size_t alignment, size_t size) {
|
||||
void *result = memalign(alignment, size);
|
||||
if(result) {
|
||||
memset(result, 0, size);
|
||||
}
|
||||
void *alloc_zeroed(size_t alignment, size_t size)
|
||||
{
|
||||
void *result = memalign(alignment, size);
|
||||
if(result)
|
||||
memset(result, 0, size);
|
||||
|
||||
return result;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
@ -29,24 +29,24 @@ static int16_t analog_state[3][2];
|
||||
|
||||
static void update_button_state(uint64_t *state, uint32_t held_buttons)
|
||||
{
|
||||
*state = held_buttons & VPAD_MASK_BUTTONS;
|
||||
*state = held_buttons & VPAD_MASK_BUTTONS;
|
||||
}
|
||||
|
||||
static void update_analog_state(int16_t state[3][2], VPADStatus *vpad)
|
||||
{
|
||||
state[RETRO_DEVICE_INDEX_ANALOG_LEFT] [RETRO_DEVICE_ID_ANALOG_X] = WIIU_READ_STICK(vpad->leftStick.x);
|
||||
state[RETRO_DEVICE_INDEX_ANALOG_LEFT] [RETRO_DEVICE_ID_ANALOG_Y] = WIIU_READ_STICK(vpad->leftStick.y);
|
||||
state[RETRO_DEVICE_INDEX_ANALOG_RIGHT][RETRO_DEVICE_ID_ANALOG_X] = WIIU_READ_STICK(vpad->rightStick.x);
|
||||
state[RETRO_DEVICE_INDEX_ANALOG_RIGHT][RETRO_DEVICE_ID_ANALOG_Y] = WIIU_READ_STICK(vpad->rightStick.y);
|
||||
state[RETRO_DEVICE_INDEX_ANALOG_LEFT] [RETRO_DEVICE_ID_ANALOG_X] = WIIU_READ_STICK(vpad->leftStick.x);
|
||||
state[RETRO_DEVICE_INDEX_ANALOG_LEFT] [RETRO_DEVICE_ID_ANALOG_Y] = WIIU_READ_STICK(vpad->leftStick.y);
|
||||
state[RETRO_DEVICE_INDEX_ANALOG_RIGHT][RETRO_DEVICE_ID_ANALOG_X] = WIIU_READ_STICK(vpad->rightStick.x);
|
||||
state[RETRO_DEVICE_INDEX_ANALOG_RIGHT][RETRO_DEVICE_ID_ANALOG_Y] = WIIU_READ_STICK(vpad->rightStick.y);
|
||||
}
|
||||
|
||||
static int16_t scale_touchpad(int16_t from_min, int16_t from_max,
|
||||
int16_t to_min, int16_t to_max, int16_t value )
|
||||
int16_t to_min, int16_t to_max, int16_t value )
|
||||
{
|
||||
int32_t from_range = from_max - from_min;
|
||||
int32_t to_range = to_max - to_min;
|
||||
int32_t from_range = from_max - from_min;
|
||||
int32_t to_range = to_max - to_min;
|
||||
|
||||
return (((value - from_min) * to_range) / from_range) + to_min;
|
||||
return (((value - from_min) * to_range) / from_range) + to_min;
|
||||
}
|
||||
|
||||
|
||||
@ -61,35 +61,36 @@ static void get_calibrated_point(VPADTouchData *point, struct video_viewport *vi
|
||||
|
||||
static void apply_clamping(VPADTouchData *point, struct video_viewport *viewport, bool *clamped)
|
||||
{
|
||||
/* clamp the x domain to the viewport */
|
||||
if(point->x < viewport->x)
|
||||
{
|
||||
point->x = viewport->x;
|
||||
*clamped = true;
|
||||
}
|
||||
else if(point->x > (viewport->x + viewport->width))
|
||||
{
|
||||
point->x = viewport->x + viewport->width;
|
||||
*clamped = true;
|
||||
}
|
||||
|
||||
/* clamp the y domain to the viewport */
|
||||
if(point->y < viewport->y)
|
||||
{
|
||||
point->y = viewport->y;
|
||||
*clamped = true;
|
||||
}
|
||||
else if(point->y > (viewport->y + viewport->height))
|
||||
{
|
||||
point->y = viewport->y + viewport->height;
|
||||
*clamped = true;
|
||||
}
|
||||
/* clamp the x domain to the viewport */
|
||||
if (point->x < viewport->x)
|
||||
{
|
||||
point->x = viewport->x;
|
||||
*clamped = true;
|
||||
}
|
||||
else if (point->x > (viewport->x + viewport->width))
|
||||
{
|
||||
point->x = viewport->x + viewport->width;
|
||||
*clamped = true;
|
||||
}
|
||||
|
||||
/* clamp the y domain to the viewport */
|
||||
if (point->y < viewport->y)
|
||||
{
|
||||
point->y = viewport->y;
|
||||
*clamped = true;
|
||||
}
|
||||
else if (point->y > (viewport->y + viewport->height))
|
||||
{
|
||||
point->y = viewport->y + viewport->height;
|
||||
*clamped = true;
|
||||
}
|
||||
}
|
||||
|
||||
static void get_touch_coordinates(VPADTouchData *point, VPADStatus *vpad, struct video_viewport *viewport, bool *clamped)
|
||||
static void get_touch_coordinates(VPADTouchData *point, VPADStatus *vpad,
|
||||
struct video_viewport *viewport, bool *clamped)
|
||||
{
|
||||
get_calibrated_point(point, viewport, vpad);
|
||||
apply_clamping(point, viewport, clamped);
|
||||
get_calibrated_point(point, viewport, vpad);
|
||||
apply_clamping(point, viewport, clamped);
|
||||
}
|
||||
|
||||
#if 0
|
||||
@ -98,12 +99,12 @@ static void get_touch_coordinates(VPADTouchData *point, VPADStatus *vpad, struct
|
||||
*/
|
||||
static int16_t bitwise_abs(int16_t value)
|
||||
{
|
||||
bool is_negative = value & 0x8000;
|
||||
if(!is_negative)
|
||||
return value;
|
||||
bool is_negative = value & 0x8000;
|
||||
if (!is_negative)
|
||||
return value;
|
||||
|
||||
value = value &~ 0x8000;
|
||||
return (~value & 0x7fff)+1;
|
||||
value = value &~ 0x8000;
|
||||
return (~value & 0x7fff)+1;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -111,17 +112,17 @@ static int16_t bitwise_abs(int16_t value)
|
||||
*/
|
||||
static void log_coords(int16_t x, int16_t y)
|
||||
{
|
||||
bool x_negative = x & 0x8000;
|
||||
bool y_negative = y & 0x8000;
|
||||
|
||||
int16_t x_digit = bitwise_abs(x);
|
||||
int16_t y_digit = bitwise_abs(y);
|
||||
bool x_negative = x & 0x8000;
|
||||
bool y_negative = y & 0x8000;
|
||||
|
||||
RARCH_LOG("[wpad]: calibrated point: %s%04x, %s%04x\n",
|
||||
x_negative ? "-" : "",
|
||||
x_digit,
|
||||
y_negative ? "-" : "",
|
||||
y_digit);
|
||||
int16_t x_digit = bitwise_abs(x);
|
||||
int16_t y_digit = bitwise_abs(y);
|
||||
|
||||
RARCH_LOG("[wpad]: calibrated point: %s%04x, %s%04x\n",
|
||||
x_negative ? "-" : "",
|
||||
x_digit,
|
||||
y_negative ? "-" : "",
|
||||
y_digit);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -132,7 +133,7 @@ static void update_touch_state(int16_t state[3][2], uint64_t *buttons, VPADStatu
|
||||
|
||||
bool touch_clamped = false;
|
||||
|
||||
if(!vpad->tpNormal.touched || vpad->tpNormal.validity != VPAD_VALID)
|
||||
if (!vpad->tpNormal.touched || vpad->tpNormal.validity != VPAD_VALID)
|
||||
{
|
||||
*buttons &= ~VPAD_BUTTON_TOUCH;
|
||||
return;
|
||||
@ -141,16 +142,18 @@ static void update_touch_state(int16_t state[3][2], uint64_t *buttons, VPADStatu
|
||||
video_driver_get_viewport_info(&viewport);
|
||||
get_touch_coordinates(&point, vpad, &viewport, &touch_clamped);
|
||||
|
||||
state[WIIU_DEVICE_INDEX_TOUCHPAD][RETRO_DEVICE_ID_ANALOG_X] = scale_touchpad(viewport.x, viewport.x + viewport.width, -0x7fff, 0x7fff, point.x);
|
||||
state[WIIU_DEVICE_INDEX_TOUCHPAD][RETRO_DEVICE_ID_ANALOG_Y] = scale_touchpad(viewport.y, viewport.y + viewport.height, -0x7fff, 0x7fff, point.y);
|
||||
state[WIIU_DEVICE_INDEX_TOUCHPAD][RETRO_DEVICE_ID_ANALOG_X] = scale_touchpad(
|
||||
viewport.x, viewport.x + viewport.width, -0x7fff, 0x7fff, point.x);
|
||||
state[WIIU_DEVICE_INDEX_TOUCHPAD][RETRO_DEVICE_ID_ANALOG_Y] = scale_touchpad(
|
||||
viewport.y, viewport.y + viewport.height, -0x7fff, 0x7fff, point.y);
|
||||
|
||||
#if 0
|
||||
log_coords(state[WIIU_DEVICE_INDEX_TOUCHPAD][RETRO_DEVICE_ID_ANALOG_X],
|
||||
state[WIIU_DEVICE_INDEX_TOUCHPAD][RETRO_DEVICE_ID_ANALOG_Y]);
|
||||
state[WIIU_DEVICE_INDEX_TOUCHPAD][RETRO_DEVICE_ID_ANALOG_Y]);
|
||||
#endif
|
||||
|
||||
|
||||
if(!touch_clamped)
|
||||
if (!touch_clamped)
|
||||
*buttons |= VPAD_BUTTON_TOUCH;
|
||||
else
|
||||
*buttons &= ~VPAD_BUTTON_TOUCH;
|
||||
@ -158,7 +161,7 @@ static void update_touch_state(int16_t state[3][2], uint64_t *buttons, VPADStatu
|
||||
|
||||
static void check_panic_button(uint32_t held_buttons)
|
||||
{
|
||||
if( (held_buttons & PANIC_BUTTON_MASK) == PANIC_BUTTON_MASK)
|
||||
if ((held_buttons & PANIC_BUTTON_MASK) == PANIC_BUTTON_MASK)
|
||||
command_event(CMD_EVENT_QUIT, NULL);
|
||||
}
|
||||
|
||||
@ -170,22 +173,22 @@ static void wpad_poll(void)
|
||||
|
||||
VPADRead(PAD_GAMEPAD, &vpad, 1, &error);
|
||||
|
||||
if(!error)
|
||||
{
|
||||
update_button_state(&button_state, vpad.hold);
|
||||
update_analog_state(analog_state, &vpad);
|
||||
update_touch_state(analog_state, &button_state, &vpad);
|
||||
check_panic_button(vpad.hold);
|
||||
}
|
||||
if (error)
|
||||
return;
|
||||
|
||||
update_button_state(&button_state, vpad.hold);
|
||||
update_analog_state(analog_state, &vpad);
|
||||
update_touch_state(analog_state, &button_state, &vpad);
|
||||
check_panic_button(vpad.hold);
|
||||
}
|
||||
|
||||
static bool wpad_init(void *data)
|
||||
{
|
||||
pad_functions.connect(PAD_GAMEPAD, &wpad_driver);
|
||||
wpad_poll();
|
||||
ready = true;
|
||||
pad_functions.connect(PAD_GAMEPAD, &wpad_driver);
|
||||
wpad_poll();
|
||||
ready = true;
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool wpad_query_pad(unsigned pad)
|
||||
@ -208,7 +211,7 @@ static bool wpad_button(unsigned pad, uint16_t button_bit)
|
||||
|
||||
static void wpad_get_buttons(unsigned pad, retro_bits_t *state)
|
||||
{
|
||||
if(!wpad_query_pad(pad))
|
||||
if (!wpad_query_pad(pad))
|
||||
BIT256_CLEAR_ALL_PTR(state);
|
||||
else
|
||||
BITS_COPY32_PTR(state, button_state);
|
||||
@ -218,7 +221,7 @@ static int16_t wpad_axis(unsigned pad, uint32_t axis)
|
||||
{
|
||||
axis_data data;
|
||||
|
||||
if(!wpad_query_pad(pad) || axis == AXIS_NONE)
|
||||
if (!wpad_query_pad(pad) || axis == AXIS_NONE)
|
||||
return 0;
|
||||
|
||||
pad_functions.read_axis_data(axis, &data);
|
||||
|
@ -53,223 +53,257 @@ typedef struct _framerec
|
||||
/* Some bitmasks for determining DSI causes.
|
||||
Taken from the PowerPC Programming Environments Manual (32-bit).
|
||||
*/
|
||||
//Set if the EA is unmapped.
|
||||
|
||||
/* Set if the EA is unmapped. */
|
||||
#define DSISR_TRANSLATION_MISS 0x40000000
|
||||
//Set if the memory accessed is protected.
|
||||
/* Set if the memory accessed is protected. */
|
||||
#define DSISR_TRANSLATION_PROT 0x8000000
|
||||
//Set if certain instructions are used on uncached memory (see manual)
|
||||
/* Set if certain instructions are used on uncached memory (see manual) */
|
||||
#define DSISR_BAD_CACHING 0x4000000
|
||||
//Set if the offending operation is a write, clear for a read.
|
||||
/* Set if the offending operation is a write, clear for a read. */
|
||||
#define DSISR_WRITE_ATTEMPTED 0x2000000
|
||||
//Set if the memory accessed is a DABR match
|
||||
/* Set if the memory accessed is a DABR match */
|
||||
#define DSISR_DABR_MATCH 0x400000
|
||||
/* ISI cause bitmasks, same source */
|
||||
#define SRR1_ISI_TRANSLATION_MISS 0x40000000
|
||||
#define SRR1_ISI_TRANSLATION_PROT 0x8000000
|
||||
/* PROG cause bitmasks, guess where from */
|
||||
//Set on floating-point exceptions
|
||||
/* Set on floating-point exceptions */
|
||||
#define SRR1_PROG_IEEE_FLOAT 0x100000
|
||||
//Set on an malformed instruction (can't decode)
|
||||
/* Set on an malformed instruction (can't decode) */
|
||||
#define SRR1_PROG_BAD_INSTR 0x80000
|
||||
//Set on a privileged instruction executing in userspace
|
||||
/* Set on a privileged instruction executing in userspace */
|
||||
#define SRR1_PROG_PRIV_INSTR 0x40000
|
||||
//Set on a trap instruction
|
||||
/* Set on a trap instruction */
|
||||
#define SRR1_PROG_TRAP 0x20000
|
||||
//Clear if srr0 points to the address that caused the exception (yes, really)
|
||||
/* Clear if srr0 points to the address that caused the exception (yes, really) */
|
||||
#define SRR1_PROG_SRR0_INACCURATE 0x10000
|
||||
|
||||
#define buf_add(...) pos += sprintf(exception_msgbuf + pos, __VA_ARGS__)
|
||||
size_t pos = 0;
|
||||
char* exception_msgbuf;
|
||||
|
||||
void __attribute__((__noreturn__)) exception_cb(OSContext* ctx, OSExceptionType type) {
|
||||
if (!exception_msgbuf || !OSEffectiveToPhysical(exception_msgbuf)) {
|
||||
/* No message buffer available, fall back onto MEM1 */
|
||||
exception_msgbuf = (char*)0xF4000000;
|
||||
}
|
||||
void __attribute__((__noreturn__)) exception_cb(OSContext* ctx, OSExceptionType type)
|
||||
{
|
||||
/* No message buffer available, fall back onto MEM1 */
|
||||
if (!exception_msgbuf || !OSEffectiveToPhysical(exception_msgbuf))
|
||||
exception_msgbuf = (char*)0xF4000000;
|
||||
|
||||
/* First up, the pretty header that tells you wtf just happened */
|
||||
if (type == OS_EXCEPTION_TYPE_DSI) {
|
||||
/* Exception type and offending instruction location */
|
||||
buf_add("DSI: Instr at %08" PRIX32, ctx->srr0);
|
||||
/* Was this a read or a write? */
|
||||
if (ctx->dsisr & DSISR_WRITE_ATTEMPTED) {
|
||||
buf_add(" bad write to");
|
||||
} else {
|
||||
buf_add(" bad read from");
|
||||
}
|
||||
/* So why was it bad?
|
||||
Other causes (DABR) don't have a message to go with them. */
|
||||
if (ctx->dsisr & DSISR_TRANSLATION_MISS) {
|
||||
buf_add(" unmapped memory at");
|
||||
} else if (ctx->dsisr & DSISR_TRANSLATION_PROT) {
|
||||
buf_add(" protected memory at");
|
||||
} else if (ctx->dsisr & DSISR_BAD_CACHING) {
|
||||
buf_add(" uncached memory at");
|
||||
}
|
||||
buf_add(" %08" PRIX32 "\n", ctx->dar);
|
||||
} else if (type == OS_EXCEPTION_TYPE_ISI) {
|
||||
buf_add("ISI: Bad execute of");
|
||||
if (ctx->srr1 & SRR1_ISI_TRANSLATION_PROT) {
|
||||
buf_add(" protected memory at");
|
||||
} else if (ctx->srr1 & SRR1_ISI_TRANSLATION_MISS) {
|
||||
buf_add(" unmapped memory at");
|
||||
}
|
||||
buf_add(" %08" PRIX32 "\n", ctx->srr0);
|
||||
} else if (type == OS_EXCEPTION_TYPE_PROGRAM) {
|
||||
buf_add("PROG:");
|
||||
if (ctx->srr1 & SRR1_PROG_BAD_INSTR) {
|
||||
buf_add(" Malformed instruction at");
|
||||
} else if (ctx->srr1 & SRR1_PROG_PRIV_INSTR) {
|
||||
buf_add(" Privileged instruction in userspace at");
|
||||
} else if (ctx->srr1 & SRR1_PROG_IEEE_FLOAT) {
|
||||
buf_add(" Floating-point exception at");
|
||||
} else if (ctx->srr1 & SRR1_PROG_TRAP) {
|
||||
buf_add(" Trap conditions met at");
|
||||
} else {
|
||||
buf_add(" Out-of-spec error (!) at");
|
||||
}
|
||||
if (ctx->srr1 & SRR1_PROG_SRR0_INACCURATE) {
|
||||
buf_add("%08" PRIX32 "-ish\n", ctx->srr0);
|
||||
} else {
|
||||
buf_add("%08" PRIX32 "\n", ctx->srr0);
|
||||
}
|
||||
}
|
||||
/* First up, the pretty header that tells you wtf just happened */
|
||||
if (type == OS_EXCEPTION_TYPE_DSI)
|
||||
{
|
||||
/* Exception type and offending instruction location */
|
||||
buf_add("DSI: Instr at %08" PRIX32, ctx->srr0);
|
||||
/* Was this a read or a write? */
|
||||
if (ctx->dsisr & DSISR_WRITE_ATTEMPTED)
|
||||
buf_add(" bad write to");
|
||||
else
|
||||
buf_add(" bad read from");
|
||||
|
||||
/* Add register dump
|
||||
There's space for two more regs at the end of the last line...
|
||||
Any ideas for what to put there? */
|
||||
buf_add( \
|
||||
"r0 %08" PRIX32 " r1 %08" PRIX32 " r2 %08" PRIX32 " r3 %08" PRIX32 " r4 %08" PRIX32 "\n" \
|
||||
"r5 %08" PRIX32 " r6 %08" PRIX32 " r7 %08" PRIX32 " r8 %08" PRIX32 " r9 %08" PRIX32 "\n" \
|
||||
"r10 %08" PRIX32 " r11 %08" PRIX32 " r12 %08" PRIX32 " r13 %08" PRIX32 " r14 %08" PRIX32 "\n" \
|
||||
"r15 %08" PRIX32 " r16 %08" PRIX32 " r17 %08" PRIX32 " r18 %08" PRIX32 " r19 %08" PRIX32 "\n" \
|
||||
"r20 %08" PRIX32 " r21 %08" PRIX32 " r22 %08" PRIX32 " r23 %08" PRIX32 " r24 %08" PRIX32 "\n" \
|
||||
"r25 %08" PRIX32 " r26 %08" PRIX32 " r27 %08" PRIX32 " r28 %08" PRIX32 " r29 %08" PRIX32 "\n" \
|
||||
"r30 %08" PRIX32 " r31 %08" PRIX32 " lr %08" PRIX32 " sr1 %08" PRIX32 " dsi %08" PRIX32 "\n" \
|
||||
"ctr %08" PRIX32 " cr %08" PRIX32 " xer %08" PRIX32 "\n",\
|
||||
ctx->gpr[0], ctx->gpr[1], ctx->gpr[2], ctx->gpr[3], ctx->gpr[4], \
|
||||
ctx->gpr[5], ctx->gpr[6], ctx->gpr[7], ctx->gpr[8], ctx->gpr[9], \
|
||||
ctx->gpr[10], ctx->gpr[11], ctx->gpr[12], ctx->gpr[13], ctx->gpr[14], \
|
||||
ctx->gpr[15], ctx->gpr[16], ctx->gpr[17], ctx->gpr[18], ctx->gpr[19], \
|
||||
ctx->gpr[20], ctx->gpr[21], ctx->gpr[22], ctx->gpr[23], ctx->gpr[24], \
|
||||
ctx->gpr[25], ctx->gpr[26], ctx->gpr[27], ctx->gpr[28], ctx->gpr[29], \
|
||||
ctx->gpr[30], ctx->gpr[31], ctx->lr, ctx->srr1, ctx->dsisr, \
|
||||
ctx->ctr, ctx->cr, ctx->xer \
|
||||
);
|
||||
/* So why was it bad?
|
||||
Other causes (DABR) don't have a message to go with them. */
|
||||
if (ctx->dsisr & DSISR_TRANSLATION_MISS)
|
||||
buf_add(" unmapped memory at");
|
||||
else if (ctx->dsisr & DSISR_TRANSLATION_PROT)
|
||||
buf_add(" protected memory at");
|
||||
else if (ctx->dsisr & DSISR_BAD_CACHING)
|
||||
buf_add(" uncached memory at");
|
||||
|
||||
/* Stack trace!
|
||||
First, let's print the PC... */
|
||||
exception_print_symbol(ctx->srr0);
|
||||
buf_add(" %08" PRIX32 "\n", ctx->dar);
|
||||
}
|
||||
else if (type == OS_EXCEPTION_TYPE_ISI)
|
||||
{
|
||||
buf_add("ISI: Bad execute of");
|
||||
if (ctx->srr1 & SRR1_ISI_TRANSLATION_PROT)
|
||||
buf_add(" protected memory at");
|
||||
else if (ctx->srr1 & SRR1_ISI_TRANSLATION_MISS)
|
||||
buf_add(" unmapped memory at");
|
||||
|
||||
if (ctx->gpr[1]) {
|
||||
/* Then the addresses off the stack.
|
||||
Code borrowed from Dimok's exception handler. */
|
||||
frame_rec_t p = (frame_rec_t)ctx->gpr[1];
|
||||
if ((unsigned int)p->lr != ctx->lr) {
|
||||
exception_print_symbol(ctx->lr);
|
||||
}
|
||||
for (int i = 0; i < NUM_STACK_TRACE_LINES && p->up; p = p->up, i++) {
|
||||
exception_print_symbol((unsigned int)p->lr);
|
||||
}
|
||||
} else {
|
||||
buf_add("Stack pointer invalid. Could not trace further.\n");
|
||||
}
|
||||
buf_add(" %08" PRIX32 "\n", ctx->srr0);
|
||||
}
|
||||
else if (type == OS_EXCEPTION_TYPE_PROGRAM)
|
||||
{
|
||||
buf_add("PROG:");
|
||||
if (ctx->srr1 & SRR1_PROG_BAD_INSTR)
|
||||
buf_add(" Malformed instruction at");
|
||||
else if (ctx->srr1 & SRR1_PROG_PRIV_INSTR)
|
||||
buf_add(" Privileged instruction in userspace at");
|
||||
else if (ctx->srr1 & SRR1_PROG_IEEE_FLOAT)
|
||||
buf_add(" Floating-point exception at");
|
||||
else if (ctx->srr1 & SRR1_PROG_TRAP)
|
||||
buf_add(" Trap conditions met at");
|
||||
else
|
||||
buf_add(" Out-of-spec error (!) at");
|
||||
|
||||
OSFatal(exception_msgbuf);
|
||||
for (;;) {}
|
||||
if (ctx->srr1 & SRR1_PROG_SRR0_INACCURATE)
|
||||
buf_add("%08" PRIX32 "-ish\n", ctx->srr0);
|
||||
else
|
||||
buf_add("%08" PRIX32 "\n", ctx->srr0);
|
||||
}
|
||||
|
||||
/* Add register dump
|
||||
There's space for two more regs at the end of the last line...
|
||||
Any ideas for what to put there? */
|
||||
buf_add( \
|
||||
"r0 %08" PRIX32 " r1 %08" PRIX32 " r2 %08" PRIX32 " r3 %08" PRIX32 " r4 %08" PRIX32 "\n" \
|
||||
"r5 %08" PRIX32 " r6 %08" PRIX32 " r7 %08" PRIX32 " r8 %08" PRIX32 " r9 %08" PRIX32 "\n" \
|
||||
"r10 %08" PRIX32 " r11 %08" PRIX32 " r12 %08" PRIX32 " r13 %08" PRIX32 " r14 %08" PRIX32 "\n" \
|
||||
"r15 %08" PRIX32 " r16 %08" PRIX32 " r17 %08" PRIX32 " r18 %08" PRIX32 " r19 %08" PRIX32 "\n" \
|
||||
"r20 %08" PRIX32 " r21 %08" PRIX32 " r22 %08" PRIX32 " r23 %08" PRIX32 " r24 %08" PRIX32 "\n" \
|
||||
"r25 %08" PRIX32 " r26 %08" PRIX32 " r27 %08" PRIX32 " r28 %08" PRIX32 " r29 %08" PRIX32 "\n" \
|
||||
"r30 %08" PRIX32 " r31 %08" PRIX32 " lr %08" PRIX32 " sr1 %08" PRIX32 " dsi %08" PRIX32 "\n" \
|
||||
"ctr %08" PRIX32 " cr %08" PRIX32 " xer %08" PRIX32 "\n",\
|
||||
ctx->gpr[0], ctx->gpr[1], ctx->gpr[2], ctx->gpr[3], ctx->gpr[4], \
|
||||
ctx->gpr[5], ctx->gpr[6], ctx->gpr[7], ctx->gpr[8], ctx->gpr[9], \
|
||||
ctx->gpr[10], ctx->gpr[11], ctx->gpr[12], ctx->gpr[13], ctx->gpr[14], \
|
||||
ctx->gpr[15], ctx->gpr[16], ctx->gpr[17], ctx->gpr[18], ctx->gpr[19], \
|
||||
ctx->gpr[20], ctx->gpr[21], ctx->gpr[22], ctx->gpr[23], ctx->gpr[24], \
|
||||
ctx->gpr[25], ctx->gpr[26], ctx->gpr[27], ctx->gpr[28], ctx->gpr[29], \
|
||||
ctx->gpr[30], ctx->gpr[31], ctx->lr, ctx->srr1, ctx->dsisr, \
|
||||
ctx->ctr, ctx->cr, ctx->xer \
|
||||
);
|
||||
|
||||
/* Stack trace!
|
||||
First, let's print the PC... */
|
||||
exception_print_symbol(ctx->srr0);
|
||||
|
||||
if (ctx->gpr[1])
|
||||
{
|
||||
int i;
|
||||
/* Then the addresses off the stack.
|
||||
Code borrowed from Dimok's exception handler. */
|
||||
frame_rec_t p = (frame_rec_t)ctx->gpr[1];
|
||||
if ((unsigned int)p->lr != ctx->lr)
|
||||
exception_print_symbol(ctx->lr);
|
||||
|
||||
for (i = 0; i < NUM_STACK_TRACE_LINES && p->up; p = p->up, i++)
|
||||
exception_print_symbol((unsigned int)p->lr);
|
||||
}
|
||||
else
|
||||
buf_add("Stack pointer invalid. Could not trace further.\n");
|
||||
|
||||
OSFatal(exception_msgbuf);
|
||||
for (;;) {}
|
||||
}
|
||||
|
||||
BOOL __attribute__((__noreturn__)) exception_dsi_cb(OSContext* ctx) {
|
||||
BOOL __attribute__((__noreturn__)) exception_dsi_cb(OSContext* ctx)
|
||||
{
|
||||
exception_cb(ctx, OS_EXCEPTION_TYPE_DSI);
|
||||
}
|
||||
BOOL __attribute__((__noreturn__)) exception_isi_cb(OSContext* ctx) {
|
||||
exception_cb(ctx, OS_EXCEPTION_TYPE_ISI);
|
||||
|
||||
BOOL __attribute__((__noreturn__)) exception_isi_cb(OSContext* ctx)
|
||||
{
|
||||
exception_cb(ctx, OS_EXCEPTION_TYPE_ISI);
|
||||
}
|
||||
BOOL __attribute__((__noreturn__)) exception_prog_cb(OSContext* ctx) {
|
||||
|
||||
BOOL __attribute__((__noreturn__)) exception_prog_cb(OSContext* ctx)
|
||||
{
|
||||
exception_cb(ctx, OS_EXCEPTION_TYPE_PROGRAM);
|
||||
}
|
||||
|
||||
void exception_print_symbol(uint32_t addr) {
|
||||
/* Check if addr is within this RPX's .text */
|
||||
if (addr >= TEXT_START && addr < TEXT_END) {
|
||||
char symbolName[64];
|
||||
OSGetSymbolName(addr, symbolName, 63);
|
||||
void exception_print_symbol(uint32_t addr)
|
||||
{
|
||||
/* Check if addr is within this RPX's .text */
|
||||
if (addr >= TEXT_START && addr < TEXT_END)
|
||||
{
|
||||
char symbolName[64];
|
||||
OSGetSymbolName(addr, symbolName, 63);
|
||||
|
||||
buf_add("%08" PRIX32 "(%08" PRIX32 "):%s\n", addr, addr - TEXT_START, symbolName);
|
||||
}
|
||||
/* Check if addr is within the system library area... */
|
||||
else if ((addr >= 0x01000000 && addr < 0x01800000) ||
|
||||
/* Or the rest of the app executable area.
|
||||
I would have used whatever method JGeckoU uses to determine
|
||||
the real lowest address, but *someone* didn't make it open-source :/ */
|
||||
(addr >= 0x01800000 && addr < 0x1000000)) {
|
||||
char symbolName[64];
|
||||
OSGetSymbolName(addr, symbolName, 63);
|
||||
/* Extract RPL name and try and find its base address */
|
||||
char* seperator = strchr(symbolName, '|');
|
||||
if (seperator) {
|
||||
/* Isolate library name; should end with .rpl
|
||||
(our main RPX was caught by another test case above) */
|
||||
*seperator = '\0';
|
||||
/* Try for a base address */
|
||||
void* libAddr;
|
||||
OSDynLoad_Acquire(symbolName, &libAddr);
|
||||
/* Special case for coreinit; which has broken handles */
|
||||
if (!strcmp(symbolName, "coreinit.rpl")) {
|
||||
void* PPCExit_addr;
|
||||
OSDynLoad_FindExport(libAddr, 0, "__PPCExit", &PPCExit_addr);
|
||||
libAddr = PPCExit_addr - 0x180;
|
||||
}
|
||||
*seperator = '|';
|
||||
/* We got one! */
|
||||
if (libAddr) {
|
||||
buf_add("%08" PRIX32 "(%08" PRIX32 "):%s\n", addr, addr - (unsigned int)libAddr, symbolName);
|
||||
OSDynLoad_Release(libAddr);
|
||||
return;
|
||||
}
|
||||
}
|
||||
/* Ah well. We can still print the basics. */
|
||||
buf_add("%08" PRIX32 "( ):%s\n", addr, symbolName);
|
||||
}
|
||||
/* Check if addr is in the HBL range
|
||||
TODO there's no real reason we couldn't find the symbol here,
|
||||
it's just laziness and arguably uneccesary bloat */
|
||||
else if (addr >= 0x00800000 && addr < 0x01000000) {
|
||||
buf_add("%08" PRIX32 "(%08" PRIX32 "):<unknown:HBL>\n", addr, addr - 0x00800000);
|
||||
}
|
||||
/* If all else fails, just say "unknown" */
|
||||
else {
|
||||
buf_add("%08" PRIX32 "( ):<unknown>\n", addr);
|
||||
}
|
||||
buf_add("%08" PRIX32 "(%08" PRIX32 "):%s\n",
|
||||
addr, addr - TEXT_START, symbolName);
|
||||
}
|
||||
/* Check if addr is within the system library area... */
|
||||
else if ((addr >= 0x01000000 && addr < 0x01800000) ||
|
||||
/* Or the rest of the app executable area.
|
||||
I would have used whatever method JGeckoU uses to determine
|
||||
the real lowest address, but *someone* didn't make it open-source :/ */
|
||||
(addr >= 0x01800000 && addr < 0x1000000))
|
||||
{
|
||||
char *seperator = NULL;
|
||||
char symbolName[64];
|
||||
|
||||
OSGetSymbolName(addr, symbolName, 63);
|
||||
|
||||
/* Extract RPL name and try and find its base address */
|
||||
seperator = strchr(symbolName, '|');
|
||||
|
||||
if (seperator)
|
||||
{
|
||||
void* libAddr = NULL;
|
||||
/* Isolate library name; should end with .rpl
|
||||
(our main RPX was caught by another test case above) */
|
||||
*seperator = '\0';
|
||||
/* Try for a base address */
|
||||
OSDynLoad_Acquire(symbolName, &libAddr);
|
||||
|
||||
/* Special case for coreinit; which has broken handles */
|
||||
if (!strcmp(symbolName, "coreinit.rpl"))
|
||||
{
|
||||
void* PPCExit_addr;
|
||||
OSDynLoad_FindExport(libAddr, 0, "__PPCExit", &PPCExit_addr);
|
||||
libAddr = PPCExit_addr - 0x180;
|
||||
}
|
||||
|
||||
*seperator = '|';
|
||||
|
||||
/* We got one! */
|
||||
if (libAddr)
|
||||
{
|
||||
buf_add("%08" PRIX32 "(%08" PRIX32 "):%s\n", addr, addr - (unsigned int)libAddr, symbolName);
|
||||
OSDynLoad_Release(libAddr);
|
||||
return;
|
||||
}
|
||||
}
|
||||
/* Ah well. We can still print the basics. */
|
||||
buf_add("%08" PRIX32 "( ):%s\n", addr, symbolName);
|
||||
}
|
||||
|
||||
/* Check if addr is in the HBL range
|
||||
TODO there's no real reason we couldn't find the symbol here,
|
||||
it's just laziness and arguably uneccesary bloat */
|
||||
else if (addr >= 0x00800000 && addr < 0x01000000)
|
||||
buf_add("%08" PRIX32 "(%08" PRIX32 "):<unknown:HBL>\n", addr, addr - 0x00800000);
|
||||
/* If all else fails, just say "unknown" */
|
||||
else
|
||||
buf_add("%08" PRIX32 "( ):<unknown>\n", addr);
|
||||
}
|
||||
|
||||
/* void setup_os_exceptions(void)
|
||||
Install and initialize the exception handler.
|
||||
*/
|
||||
void setup_os_exceptions(void) {
|
||||
exception_msgbuf = malloc(4096);
|
||||
OSSetExceptionCallback(OS_EXCEPTION_TYPE_DSI, exception_dsi_cb);
|
||||
OSSetExceptionCallback(OS_EXCEPTION_TYPE_ISI, exception_isi_cb);
|
||||
OSSetExceptionCallback(OS_EXCEPTION_TYPE_PROGRAM, exception_prog_cb);
|
||||
test_os_exceptions();
|
||||
void setup_os_exceptions(void)
|
||||
{
|
||||
exception_msgbuf = malloc(4096);
|
||||
OSSetExceptionCallback(OS_EXCEPTION_TYPE_DSI, exception_dsi_cb);
|
||||
OSSetExceptionCallback(OS_EXCEPTION_TYPE_ISI, exception_isi_cb);
|
||||
OSSetExceptionCallback(OS_EXCEPTION_TYPE_PROGRAM, exception_prog_cb);
|
||||
test_os_exceptions();
|
||||
}
|
||||
|
||||
/* void test_os_exceptions(void)
|
||||
Used for debugging. Insert code here to induce a crash.
|
||||
*/
|
||||
void test_os_exceptions(void) {
|
||||
//Write to 0x00000000; causes DSI
|
||||
/*__asm__ volatile (
|
||||
"li %r3, 0 \n" \
|
||||
"stw %r3, 0(%r3) \n"
|
||||
);
|
||||
DCFlushRange((void*)0, 4);*/
|
||||
//Malformed instruction, causes PROG. Doesn't seem to work.
|
||||
/*__asm__ volatile (
|
||||
".int 0xDEADC0DE"
|
||||
);*/
|
||||
//Jump to 0; causes ISI
|
||||
/*void (*testFunc)() = (void(*)())0;
|
||||
testFunc();*/
|
||||
void test_os_exceptions(void)
|
||||
{
|
||||
/*Write to 0x00000000; causes DSI */
|
||||
#if 0
|
||||
__asm__ volatile (
|
||||
"li %r3, 0 \n" \
|
||||
"stw %r3, 0(%r3) \n"
|
||||
);
|
||||
DCFlushRange((void*)0, 4);
|
||||
#endif
|
||||
|
||||
/*Malformed instruction, causes PROG. Doesn't seem to work. */
|
||||
#if 0
|
||||
__asm__ volatile (
|
||||
".int 0xDEADC0DE"
|
||||
);
|
||||
#endif
|
||||
|
||||
/* Jump to 0; causes ISI */
|
||||
#if 0
|
||||
void (*testFunc)() = (void(*)())0;
|
||||
testFunc();
|
||||
#endif
|
||||
}
|
||||
|
@ -18,12 +18,12 @@
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif //__cplusplus
|
||||
#endif /* __cplusplus */
|
||||
|
||||
void setup_os_exceptions(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif //__cplusplus
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif //__EXCEPTION_HANDLER_H_
|
||||
#endif /*__EXCEPTION_HANDLER_H_ */
|
||||
|
@ -24,17 +24,24 @@ static MEMExpandedHeap* bucket_heap;
|
||||
|
||||
void memoryInitialize(void)
|
||||
{
|
||||
MEMHeapHandle mem1_heap_handle = MEMGetBaseHeapHandle(MEM_BASE_HEAP_MEM1);
|
||||
unsigned int mem1_allocatable_size = MEMGetAllocatableSizeForFrmHeapEx(mem1_heap_handle, 4);
|
||||
void *mem1_memory = MEMAllocFromFrmHeapEx(mem1_heap_handle, mem1_allocatable_size, 4);
|
||||
if(mem1_memory)
|
||||
mem1_heap = MEMCreateExpHeapEx(mem1_memory, mem1_allocatable_size, 0);
|
||||
unsigned int bucket_allocatable_size;
|
||||
MEMHeapHandle bucket_heap_handle;
|
||||
void *bucket_memory = NULL;
|
||||
MEMHeapHandle mem1_heap_handle = MEMGetBaseHeapHandle(MEM_BASE_HEAP_MEM1);
|
||||
unsigned int mem1_allocatable_size = MEMGetAllocatableSizeForFrmHeapEx(mem1_heap_handle, 4);
|
||||
void *mem1_memory = MEMAllocFromFrmHeapEx(mem1_heap_handle, mem1_allocatable_size, 4);
|
||||
|
||||
MEMHeapHandle bucket_heap_handle = MEMGetBaseHeapHandle(MEM_BASE_HEAP_FG);
|
||||
unsigned int bucket_allocatable_size = MEMGetAllocatableSizeForFrmHeapEx(bucket_heap_handle, 4);
|
||||
void *bucket_memory = MEMAllocFromFrmHeapEx(bucket_heap_handle, bucket_allocatable_size, 4);
|
||||
if(bucket_memory)
|
||||
bucket_heap = MEMCreateExpHeapEx(bucket_memory, bucket_allocatable_size, 0);
|
||||
if(mem1_memory)
|
||||
mem1_heap = MEMCreateExpHeapEx(mem1_memory,
|
||||
mem1_allocatable_size, 0);
|
||||
|
||||
bucket_heap_handle = MEMGetBaseHeapHandle(MEM_BASE_HEAP_FG);
|
||||
bucket_allocatable_size = MEMGetAllocatableSizeForFrmHeapEx(bucket_heap_handle, 4);
|
||||
bucket_memory = MEMAllocFromFrmHeapEx(bucket_heap_handle, bucket_allocatable_size, 4);
|
||||
|
||||
if(bucket_memory)
|
||||
bucket_heap = MEMCreateExpHeapEx(bucket_memory,
|
||||
bucket_allocatable_size, 0);
|
||||
}
|
||||
|
||||
void memoryRelease(void)
|
||||
@ -60,9 +67,8 @@ void* _malloc_r(struct _reent *r, size_t size)
|
||||
|
||||
void _free_r(struct _reent *r, void *ptr)
|
||||
{
|
||||
if (ptr) {
|
||||
if (ptr)
|
||||
MEMFreeToExpHeap(MEMGetBaseHeapHandle(MEM_BASE_HEAP_MEM2), ptr);
|
||||
}
|
||||
}
|
||||
|
||||
size_t _malloc_usable_size_r(struct _reent *r, void *ptr)
|
||||
@ -72,13 +78,14 @@ size_t _malloc_usable_size_r(struct _reent *r, void *ptr)
|
||||
|
||||
void * _realloc_r(struct _reent *r, void *ptr, size_t size)
|
||||
{
|
||||
void *realloc_ptr = NULL;
|
||||
if (!ptr)
|
||||
return _malloc_r(r, size);
|
||||
|
||||
if (_malloc_usable_size_r(r, ptr) >= size)
|
||||
return ptr;
|
||||
|
||||
void *realloc_ptr = _malloc_r(r, size);
|
||||
realloc_ptr = _malloc_r(r, size);
|
||||
|
||||
if(!realloc_ptr)
|
||||
return NULL;
|
||||
@ -93,9 +100,8 @@ void* _calloc_r(struct _reent *r, size_t num, size_t size)
|
||||
{
|
||||
void *ptr = _malloc_r(r, num*size);
|
||||
|
||||
if(ptr) {
|
||||
if(ptr)
|
||||
memset(ptr, 0, num*size);
|
||||
}
|
||||
|
||||
return ptr;
|
||||
}
|
||||
@ -106,12 +112,11 @@ void * _valloc_r(struct _reent *r, size_t size)
|
||||
}
|
||||
|
||||
|
||||
//!-------------------------------------------------------------------------------------------
|
||||
//! some wrappers
|
||||
//!-------------------------------------------------------------------------------------------
|
||||
/* some wrappers */
|
||||
|
||||
void * MEM2_alloc(unsigned int size, unsigned int align)
|
||||
{
|
||||
return MEMAllocFromExpHeapEx(MEMGetBaseHeapHandle(MEM_BASE_HEAP_MEM2), size, align);
|
||||
return MEMAllocFromExpHeapEx(MEMGetBaseHeapHandle(MEM_BASE_HEAP_MEM2), size, align);
|
||||
}
|
||||
|
||||
void MEM2_free(void *ptr)
|
||||
@ -122,24 +127,24 @@ void MEM2_free(void *ptr)
|
||||
|
||||
void * MEM1_alloc(unsigned int size, unsigned int align)
|
||||
{
|
||||
if (align < 4)
|
||||
align = 4;
|
||||
return MEMAllocFromExpHeapEx(mem1_heap, size, align);
|
||||
if (align < 4)
|
||||
align = 4;
|
||||
return MEMAllocFromExpHeapEx(mem1_heap, size, align);
|
||||
}
|
||||
|
||||
void MEM1_free(void *ptr)
|
||||
{
|
||||
MEMFreeToExpHeap(mem1_heap, ptr);
|
||||
MEMFreeToExpHeap(mem1_heap, ptr);
|
||||
}
|
||||
|
||||
void * MEMBucket_alloc(unsigned int size, unsigned int align)
|
||||
{
|
||||
if (align < 4)
|
||||
align = 4;
|
||||
return MEMAllocFromExpHeapEx(bucket_heap, size, align);
|
||||
if (align < 4)
|
||||
align = 4;
|
||||
return MEMAllocFromExpHeapEx(bucket_heap, size, align);
|
||||
}
|
||||
|
||||
void MEMBucket_free(void *ptr)
|
||||
{
|
||||
MEMFreeToExpHeap(bucket_heap, ptr);
|
||||
MEMFreeToExpHeap(bucket_heap, ptr);
|
||||
}
|
||||
|
@ -39,4 +39,4 @@ void MEMBucket_free(void *ptr);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // __MEMORY_H_
|
||||
#endif /* __MEMORY_H_ */
|
||||
|
Loading…
x
Reference in New Issue
Block a user