(wiiu) small style nits; declare variables at top; C comments

This commit is contained in:
twinaphex 2018-01-05 13:09:05 +01:00
parent af9911df8a
commit cf8e7cd362
12 changed files with 995 additions and 859 deletions

View File

@ -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 */

View File

@ -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;
}

View File

@ -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_ */

View File

@ -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 =

View File

@ -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",
};

View File

@ -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 = {

View File

@ -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;
}

View File

@ -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);

View File

@ -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
}

View File

@ -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_ */

View File

@ -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);
}

View File

@ -39,4 +39,4 @@ void MEMBucket_free(void *ptr);
}
#endif
#endif // __MEMORY_H_
#endif /* __MEMORY_H_ */