diff --git a/src/joystick_standard.c b/src/joystick_standard.c new file mode 100644 index 0000000..ac0e9ba --- /dev/null +++ b/src/joystick_standard.c @@ -0,0 +1,208 @@ +#include +#include "ibm.h" +#include "device.h" +#include "timer.h" +#include "gameport.h" +#include "joystick_standard.h" +#include "plat-joystick.h" + +static void *joystick_standard_init() +{ +} + +static void joystick_standard_close(void *p) +{ +} + +static uint8_t joystick_standard_read(void *p) +{ + uint8_t ret = 0xf0; + + if (JOYSTICK_PRESENT(0)) + { + if (joystick_state[0].button[0]) + ret &= ~0x10; + if (joystick_state[0].button[1]) + ret &= ~0x20; + } + if (JOYSTICK_PRESENT(1)) + { + if (joystick_state[1].button[0]) + ret &= ~0x40; + if (joystick_state[1].button[1]) + ret &= ~0x80; + } + + return ret; +} + +static uint8_t joystick_standard_read_4button(void *p) +{ + uint8_t ret = 0xf0; + + if (JOYSTICK_PRESENT(0)) + { + if (joystick_state[0].button[0]) + ret &= ~0x10; + if (joystick_state[0].button[1]) + ret &= ~0x20; + if (joystick_state[0].button[2]) + ret &= ~0x40; + if (joystick_state[0].button[3]) + ret &= ~0x80; + } + + return ret; +} + +static void joystick_standard_write(void *p) +{ +} + +static int joystick_standard_read_axis(void *p, int axis) +{ + switch (axis) + { + case 0: + if (!JOYSTICK_PRESENT(0)) + return AXIS_NOT_PRESENT; + return joystick_state[0].axis[0]; + case 1: + if (!JOYSTICK_PRESENT(0)) + return AXIS_NOT_PRESENT; + return joystick_state[0].axis[1]; + case 2: + if (!JOYSTICK_PRESENT(1)) + return AXIS_NOT_PRESENT; + return joystick_state[1].axis[0]; + case 3: + if (!JOYSTICK_PRESENT(1)) + return AXIS_NOT_PRESENT; + return joystick_state[1].axis[1]; + } +} + +static int joystick_standard_read_axis_4button(void *p, int axis) +{ + if (!JOYSTICK_PRESENT(0)) + return AXIS_NOT_PRESENT; + + switch (axis) + { + case 0: + return joystick_state[0].axis[0]; + case 1: + return joystick_state[0].axis[1]; + case 2: + return 0; + case 3: + return 0; + } +} +static int joystick_standard_read_axis_6button(void *p, int axis) +{ + if (!JOYSTICK_PRESENT(0)) + return AXIS_NOT_PRESENT; + + switch (axis) + { + case 0: + return joystick_state[0].axis[0]; + case 1: + return joystick_state[0].axis[1]; + case 2: + return joystick_state[0].button[4] ? -32767 : 32768; + case 3: + return joystick_state[0].button[5] ? -32767 : 32768; + } +} +static int joystick_standard_read_axis_8button(void *p, int axis) +{ + if (!JOYSTICK_PRESENT(0)) + return AXIS_NOT_PRESENT; + + switch (axis) + { + case 0: + return joystick_state[0].axis[0]; + case 1: + return joystick_state[0].axis[1]; + case 2: + if (joystick_state[0].button[4]) + return -32767; + if (joystick_state[0].button[6]) + return 32768; + return 0; + case 3: + if (joystick_state[0].button[5]) + return -32767; + if (joystick_state[0].button[7]) + return 32768; + return 0; + } +} + +static void joystick_standard_a0_over(void *p) +{ +} + +joystick_if_t joystick_standard = +{ + .name = "Standard 2-button joystick(s)", + .init = joystick_standard_init, + .close = joystick_standard_close, + .read = joystick_standard_read, + .write = joystick_standard_write, + .read_axis = joystick_standard_read_axis, + .a0_over = joystick_standard_a0_over, + .max_joysticks = 2, + .axis_count = 2, + .button_count = 2, + .axis_names = {"X axis", "Y axis"}, + .button_names = {"Button 1", "Button 2"} +}; +joystick_if_t joystick_standard_4button = +{ + .name = "Standard 4-button joystick", + .init = joystick_standard_init, + .close = joystick_standard_close, + .read = joystick_standard_read_4button, + .write = joystick_standard_write, + .read_axis = joystick_standard_read_axis_4button, + .a0_over = joystick_standard_a0_over, + .max_joysticks = 1, + .axis_count = 2, + .button_count = 4, + .axis_names = {"X axis", "Y axis"}, + .button_names = {"Button 1", "Button 2", "Button 3", "Button 4"} +}; +joystick_if_t joystick_standard_6button = +{ + .name = "Standard 6-button joystick", + .init = joystick_standard_init, + .close = joystick_standard_close, + .read = joystick_standard_read_4button, + .write = joystick_standard_write, + .read_axis = joystick_standard_read_axis_6button, + .a0_over = joystick_standard_a0_over, + .max_joysticks = 1, + .axis_count = 2, + .button_count = 6, + .axis_names = {"X axis", "Y axis"}, + .button_names = {"Button 1", "Button 2", "Button 3", "Button 4", "Button 5", "Button 6"} +}; +joystick_if_t joystick_standard_8button = +{ + .name = "Standard 8-button joystick", + .init = joystick_standard_init, + .close = joystick_standard_close, + .read = joystick_standard_read_4button, + .write = joystick_standard_write, + .read_axis = joystick_standard_read_axis_8button, + .a0_over = joystick_standard_a0_over, + .max_joysticks = 1, + .axis_count = 2, + .button_count = 8, + .axis_names = {"X axis", "Y axis"}, + .button_names = {"Button 1", "Button 2", "Button 3", "Button 4", "Button 5", "Button 6", "Button 7", "Button 8"} +}; diff --git a/src/joystick_standard.h b/src/joystick_standard.h new file mode 100644 index 0000000..e319168 --- /dev/null +++ b/src/joystick_standard.h @@ -0,0 +1,4 @@ +extern joystick_if_t joystick_standard; +extern joystick_if_t joystick_standard_4button; +extern joystick_if_t joystick_standard_6button; +extern joystick_if_t joystick_standard_8button; diff --git a/src/joystick_sw_pad.c b/src/joystick_sw_pad.c new file mode 100644 index 0000000..c0d0e8b --- /dev/null +++ b/src/joystick_sw_pad.c @@ -0,0 +1,251 @@ +/*Sidewinder game pad notes : + + - Write to 0x201 starts packet transfer (5*N or 15*N bits) + - Currently alternates between Mode A and Mode B (is there any way of + actually controlling which is used?) + - Windows 9x drivers require Mode B when more than 1 pad connected + - Packet preceeded by high data (currently 50us), and followed by low + data (currently 160us) - timings are probably wrong, but good enough + for everything I've tried + - Analogue inputs are only used to time ID packet request. If A0 timing + out is followed after ~64us by another 0x201 write then an ID packet + is triggered + - Sidewinder game pad ID is 'H0003' + - ID is sent in Mode A (1 bit per clock), but data bit 2 must change + during ID packet transfer, or Windows 9x drivers won't use Mode B. I + don't know if it oscillates, mirrors the data transfer, or something + else - the drivers only check that it changes at least 10 times during + the transfer + - Some DOS stuff will write to 0x201 while a packet is being transferred. + This seems to be ignored. +*/ + +#include +#include "ibm.h" +#include "device.h" +#include "timer.h" +#include "gameport.h" +#include "joystick_sw_pad.h" +#include "plat-joystick.h" + +typedef struct +{ + int poll_time; + int poll_left; + int poll_clock; + uint64_t poll_data; + int poll_mode; + + int trigger_time; + int data_mode; +} sw_data; + +static void sw_timer_over(void *p) +{ + sw_data *sw = (sw_data *)p; + + while (sw->poll_time <= 0 && sw->poll_left) + { + sw->poll_clock = !sw->poll_clock; + + if (sw->poll_clock) + { + sw->poll_data >>= (sw->poll_mode ? 3 : 1); + sw->poll_left--; + } + + if (sw->poll_left == 1 && !sw->poll_clock) + sw->poll_time += TIMER_USEC * 160; + else if (sw->poll_left) + sw->poll_time += TIMER_USEC * 5; + else + sw->poll_time = 0; + } + + if (!sw->poll_left) + sw->poll_time = 0; +} + +static void sw_trigger_timer_over(void *p) +{ + sw_data *sw = (sw_data *)p; + + sw->trigger_time = 0; +} + +static int sw_parity(uint16_t data) +{ + int bits_set = 0; + + while (data) + { + bits_set++; + data &= (data - 1); + } + + return bits_set & 1; +} + +static void *sw_init() +{ + sw_data *sw = (sw_data *)malloc(sizeof(sw_data)); + memset(sw, 0, sizeof(sw_data)); + + timer_add(sw_timer_over, &sw->poll_time, &sw->poll_time, sw); + timer_add(sw_trigger_timer_over, &sw->trigger_time, &sw->trigger_time, sw); + + return sw; +} + +static void sw_close(void *p) +{ + sw_data *sw = (sw_data *)p; + + free(sw); +} + +static uint8_t sw_read(void *p) +{ + sw_data *sw = (sw_data *)p; + uint8_t temp = 0; + + if (!JOYSTICK_PRESENT(0)) + return 0xff; + + if (sw->poll_time) + { + if (sw->poll_clock) + temp |= 0x10; + + if (sw->poll_mode) + temp |= (sw->poll_data & 7) << 5; + else + { + temp |= ((sw->poll_data & 1) << 5) | 0xc0; + if (sw->poll_left > 31 && !(sw->poll_left & 1)) + temp &= ~0x80; + } + } + else + temp |= 0xf0; + + return temp; +} + +static void sw_write(void *p) +{ + sw_data *sw = (sw_data *)p; + int time_since_last = sw->trigger_time / TIMER_USEC; + + if (!JOYSTICK_PRESENT(0)) + return; + + timer_process(); + + if (!sw->poll_left) + { + sw->poll_clock = 1; + sw->poll_time = TIMER_USEC * 50; + + if (time_since_last > 9900 && time_since_last < 9940) + { +// pclog("sw sends ID packet\n"); + sw->poll_mode = 0; + sw->poll_left = 49; + sw->poll_data = 0x2400ull | (0x1830ull << 15) | (0x19b0ull << 30); + } + else + { + int c; + +// pclog("sw sends data packet %08x %i\n", cpu_state.pc, data_packets++); + + sw->poll_mode = sw->data_mode; + sw->data_mode = !sw->data_mode; + + if (sw->poll_mode) + { + sw->poll_left = 1; + sw->poll_data = 7; + } + else + { + sw->poll_left = 1; + sw->poll_data = 1; + } + + for (c = 0; c < 4; c++) + { + uint64_t data = 0x3fff; + int b; + + if (!JOYSTICK_PRESENT(c)) + break; + + if (joystick_state[c].axis[1] < -16383) + data &= ~1; + if (joystick_state[c].axis[1] > 16383) + data &= ~2; + if (joystick_state[c].axis[0] > 16383) + data &= ~4; + if (joystick_state[c].axis[0] < -16383) + data &= ~8; + + for (b = 0; b < 10; b++) + { + if (joystick_state[c].button[b]) + data &= ~(1 << (b + 4)); + } + + if (sw_parity(data)) + data |= 0x4000; + + if (sw->poll_mode) + { + sw->poll_left += 5; + sw->poll_data |= (data << (c*15 + 3)); + } + else + { + sw->poll_left += 15; + sw->poll_data |= (data << (c*15 + 1)); + } + } + } + } + + sw->trigger_time = 0; + + timer_update_outstanding(); +} + +static int sw_read_axis(void *p, int axis) +{ + if (!JOYSTICK_PRESENT(0)) + return AXIS_NOT_PRESENT; + + return 0; /*No analogue support on Sidewinder game pad*/ +} + +static void sw_a0_over(void *p) +{ + sw_data *sw = (sw_data *)p; + + sw->trigger_time = TIMER_USEC * 10000; +} + +joystick_if_t joystick_sw_pad = +{ + .name = "Microsoft SideWinder Pad", + .init = sw_init, + .close = sw_close, + .read = sw_read, + .write = sw_write, + .read_axis = sw_read_axis, + .a0_over = sw_a0_over, + .max_joysticks = 4, + .axis_count = 2, + .button_count = 10, + .axis_names = {"X axis", "Y axis"}, + .button_names = {"A", "B", "C", "X", "Y", "Z", "L", "R", "Start", "M"} +}; diff --git a/src/joystick_sw_pad.h b/src/joystick_sw_pad.h new file mode 100644 index 0000000..589efb6 --- /dev/null +++ b/src/joystick_sw_pad.h @@ -0,0 +1 @@ +extern joystick_if_t joystick_sw_pad; diff --git a/src/win-joystickconfig.c b/src/win-joystickconfig.c new file mode 100644 index 0000000..b2aa4c0 --- /dev/null +++ b/src/win-joystickconfig.c @@ -0,0 +1,407 @@ +#define BITMAP WINDOWS_BITMAP +#include +#include +#undef BITMAP + +#include "ibm.h" +#include "config.h" +#include "device.h" +#include "gameport.h" +#include "plat-joystick.h" +#include "resources.h" +#include "win.h" + +static int joystick_nr; +static int joystick_config_type; +#define AXIS_STRINGS_MAX 3 +static char *axis_strings[AXIS_STRINGS_MAX] = {"X Axis", "Y Axis", "Z Axis"}; + +static void rebuild_axis_button_selections(HWND hdlg) +{ + int id = IDC_CONFIG_BASE + 2; + HWND h; + int joystick; + int c, d; + + h = GetDlgItem(hdlg, IDC_CONFIG_BASE); + joystick = SendMessage(h, CB_GETCURSEL, 0, 0); + + for (c = 0; c < joystick_get_axis_count(joystick_config_type); c++) + { + int sel = c; + + h = GetDlgItem(hdlg, id); + SendMessage(h, CB_RESETCONTENT, 0, 0); + + if (joystick) + { + for (d = 0; d < plat_joystick_state[joystick-1].nr_axes; d++) + { + SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)plat_joystick_state[joystick-1].axis[d].name); + if (c < AXIS_STRINGS_MAX) + { + if (!stricmp(axis_strings[c], plat_joystick_state[joystick-1].axis[d].name)) + sel = d; + } + } + for (d = 0; d < plat_joystick_state[joystick-1].nr_povs; d++) + { + char s[80]; + + sprintf(s, "%s (X axis)", plat_joystick_state[joystick-1].pov[d].name); + SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)s); + sprintf(s, "%s (Y axis)", plat_joystick_state[joystick-1].pov[d].name); + SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)s); + } + SendMessage(h, CB_SETCURSEL, sel, 0); + EnableWindow(h, TRUE); + } + else + EnableWindow(h, FALSE); + + id += 2; + } + + for (c = 0; c < joystick_get_button_count(joystick_config_type); c++) + { + h = GetDlgItem(hdlg, id); + SendMessage(h, CB_RESETCONTENT, 0, 0); + + if (joystick) + { + for (d = 0; d < plat_joystick_state[joystick-1].nr_buttons; d++) + SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)plat_joystick_state[joystick-1].button[d].name); + SendMessage(h, CB_SETCURSEL, c, 0); + EnableWindow(h, TRUE); + } + else + EnableWindow(h, FALSE); + + id += 2; + } +} + +static int get_axis(HWND hdlg, int id) +{ + HWND h = GetDlgItem(hdlg, id); + int axis_sel = SendMessage(h, CB_GETCURSEL, 0, 0); + int nr_axes = plat_joystick_state[joystick_state[joystick_nr].plat_joystick_nr-1].nr_axes; + + if (axis_sel < nr_axes) + return axis_sel; + + axis_sel -= nr_axes; + if (axis_sel & 1) + return POV_Y | (axis_sel >> 1); + else + return POV_X | (axis_sel >> 1); +} + +static BOOL CALLBACK joystickconfig_dlgproc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + switch (message) + { + case WM_INITDIALOG: + { + HWND h = GetDlgItem(hdlg, IDC_CONFIG_BASE); + int c, d; + int id = IDC_CONFIG_BASE + 2; + int joystick = joystick_state[joystick_nr].plat_joystick_nr; + + SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)"None"); + + for (c = 0; c < joysticks_present; c++) + SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)plat_joystick_state[c].name); + + SendMessage(h, CB_SETCURSEL, joystick, 0); + + rebuild_axis_button_selections(hdlg); + + if (joystick_state[joystick_nr].plat_joystick_nr) + { + int nr_axes = plat_joystick_state[joystick-1].nr_axes; + for (c = 0; c < joystick_get_axis_count(joystick_config_type); c++) + { + int mapping = joystick_state[joystick_nr].axis_mapping[c]; + + h = GetDlgItem(hdlg, id); + if (mapping & POV_X) + SendMessage(h, CB_SETCURSEL, nr_axes + (mapping & 3)*2, 0); + else if (mapping & POV_Y) + SendMessage(h, CB_SETCURSEL, nr_axes + (mapping & 3)*2 + 1, 0); + else + SendMessage(h, CB_SETCURSEL, mapping, 0); + id += 2; + } + for (c = 0; c < joystick_get_button_count(joystick_config_type); c++) + { + h = GetDlgItem(hdlg, id); + SendMessage(h, CB_SETCURSEL, joystick_state[joystick_nr].button_mapping[c], 0); + id += 2; + } + } + } + return TRUE; + + case WM_COMMAND: + switch (LOWORD(wParam)) + { + case IDC_CONFIG_BASE: + if (HIWORD(wParam) == CBN_SELCHANGE) + rebuild_axis_button_selections(hdlg); + break; + + case IDOK: + { + HWND h; + int joystick; + int c, d; + int id = IDC_CONFIG_BASE + 2; + + h = GetDlgItem(hdlg, IDC_CONFIG_BASE); + joystick_state[joystick_nr].plat_joystick_nr = SendMessage(h, CB_GETCURSEL, 0, 0); + + if (joystick_state[joystick_nr].plat_joystick_nr) + { + for (c = 0; c < joystick_get_axis_count(joystick_config_type); c++) + { + joystick_state[joystick_nr].axis_mapping[c] = get_axis(hdlg, id); + id += 2; + } + for (c = 0; c < joystick_get_button_count(joystick_config_type); c++) + { + h = GetDlgItem(hdlg, id); + joystick_state[joystick_nr].button_mapping[c] = SendMessage(h, CB_GETCURSEL, 0, 0); + id += 2; + } + } + } + case IDCANCEL: + EndDialog(hdlg, 0); + return TRUE; + } + break; + } + return FALSE; +} + +void joystickconfig_open(HWND hwnd, int joy_nr, int type) +{ +// device_config_t *config = device->config; + uint16_t *data_block = malloc(16384); + uint16_t *data; + DLGTEMPLATE *dlg = (DLGTEMPLATE *)data_block; + DLGITEMTEMPLATE *item; + int y = 10; + int id = IDC_CONFIG_BASE; + int c; + + joystick_nr = joy_nr; + joystick_config_type = type; + + memset(data_block, 0, 4096); + + dlg->style = DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU; + dlg->x = 10; + dlg->y = 10; + dlg->cx = 220; + dlg->cy = 70; + + data = (uint16_t *)(dlg + 1); + + *data++ = 0; /*no menu*/ + *data++ = 0; /*predefined dialog box class*/ + data += MultiByteToWideChar(CP_ACP, 0, "Device Configuration", -1, data, 50); + + *data++ = 8; /*Point*/ + data += MultiByteToWideChar(CP_ACP, 0, "MS Sans Serif", -1, data, 50); + + if (((unsigned long)data) & 2) + data++; + + + /*Combo box*/ + item = (DLGITEMTEMPLATE *)data; + item->x = 70; + item->y = y; + item->id = id++; + + item->cx = 140; + item->cy = 150; + + item->style = WS_CHILD | WS_VISIBLE | CBS_DROPDOWN | WS_VSCROLL; + + data = (uint16_t *)(item + 1); + *data++ = 0xFFFF; + *data++ = 0x0085; // combo box class + + data += MultiByteToWideChar(CP_ACP, 0, "Device", -1, data, 256); + *data++ = 0; // no creation data + + if (((unsigned long)data) & 2) + data++; + + /*Static text*/ + item = (DLGITEMTEMPLATE *)data; + item->x = 10; + item->y = y; + item->id = id++; + + item->cx = 60; + item->cy = 15; + + item->style = WS_CHILD | WS_VISIBLE; + + data = (uint16_t *)(item + 1); + *data++ = 0xFFFF; + *data++ = 0x0082; // static class + + data += MultiByteToWideChar(CP_ACP, 0, "Device :", -1, data, 256); + *data++ = 0; // no creation data + + if (((unsigned long)data) & 2) + data++; + + y += 20; + + + for (c = 0; c < joystick_get_axis_count(type); c++) + { + /*Combo box*/ + item = (DLGITEMTEMPLATE *)data; + item->x = 70; + item->y = y; + item->id = id++; + + item->cx = 140; + item->cy = 150; + + item->style = WS_CHILD | WS_VISIBLE | CBS_DROPDOWN | WS_VSCROLL; + + data = (uint16_t *)(item + 1); + *data++ = 0xFFFF; + *data++ = 0x0085; // combo box class + + data += MultiByteToWideChar(CP_ACP, 0, joystick_get_axis_name(type, c), -1, data, 256); + *data++ = 0; // no creation data + + if (((unsigned long)data) & 2) + data++; + + /*Static text*/ + item = (DLGITEMTEMPLATE *)data; + item->x = 10; + item->y = y; + item->id = id++; + + item->cx = 60; + item->cy = 15; + + item->style = WS_CHILD | WS_VISIBLE; + + data = (uint16_t *)(item + 1); + *data++ = 0xFFFF; + *data++ = 0x0082; // static class + + data += MultiByteToWideChar(CP_ACP, 0, joystick_get_axis_name(type, c), -1, data, 256); + *data++ = 0; // no creation data + + if (((unsigned long)data) & 2) + data++; + + y += 20; + } + + for (c = 0; c < joystick_get_button_count(type); c++) + { + /*Combo box*/ + item = (DLGITEMTEMPLATE *)data; + item->x = 70; + item->y = y; + item->id = id++; + + item->cx = 140; + item->cy = 150; + + item->style = WS_CHILD | WS_VISIBLE | CBS_DROPDOWN | WS_VSCROLL; + + data = (uint16_t *)(item + 1); + *data++ = 0xFFFF; + *data++ = 0x0085; // combo box class + + data += MultiByteToWideChar(CP_ACP, 0, joystick_get_button_name(type, c), -1, data, 256); + *data++ = 0; // no creation data + + if (((unsigned long)data) & 2) + data++; + + /*Static text*/ + item = (DLGITEMTEMPLATE *)data; + item->x = 10; + item->y = y; + item->id = id++; + + item->cx = 60; + item->cy = 15; + + item->style = WS_CHILD | WS_VISIBLE; + + data = (uint16_t *)(item + 1); + *data++ = 0xFFFF; + *data++ = 0x0082; // static class + + data += MultiByteToWideChar(CP_ACP, 0, joystick_get_button_name(type, c), -1, data, 256); + *data++ = 0; // no creation data + + if (((unsigned long)data) & 2) + data++; + + y += 20; + } + + dlg->cdit = (id - IDC_CONFIG_BASE) + 2; + +// DEFPUSHBUTTON "OK",IDOK,64,232,50,14, WS_TABSTOP +// PUSHBUTTON "Cancel",IDCANCEL,128,232,50,14, WS_TABSTOP + + item = (DLGITEMTEMPLATE *)data; + item->x = 20; + item->y = y; + item->cx = 50; + item->cy = 14; + item->id = IDOK; // OK button identifier + item->style = WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON; + + data = (uint16_t *)(item + 1); + *data++ = 0xFFFF; + *data++ = 0x0080; // button class + + data += MultiByteToWideChar(CP_ACP, 0, "OK", -1, data, 50); + *data++ = 0; // no creation data + + if (((unsigned long)data) & 2) + data++; + + item = (DLGITEMTEMPLATE *)data; + item->x = 80; + item->y = y; + item->cx = 50; + item->cy = 14; + item->id = IDCANCEL; // OK button identifier + item->style = WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON; + + data = (uint16_t *)(item + 1); + *data++ = 0xFFFF; + *data++ = 0x0080; // button class + + data += MultiByteToWideChar(CP_ACP, 0, "Cancel", -1, data, 50); + *data++ = 0; // no creation data + + dlg->cy = y + 20; + +// config_device = device; + + DialogBoxIndirect(hinstance, dlg, hwnd, joystickconfig_dlgproc); + + free(data_block); +}