From 53291432e8b112932829bceb3f9a21a3000a8761 Mon Sep 17 00:00:00 2001 From: SarahW Date: Sat, 29 Feb 2020 14:04:31 +0000 Subject: [PATCH] Add CD-ROM drive model configuration. Patch from EluanCM. --- src/pc.c | 2 + src/pc.xrc | 37 ++++++++- src/scsi_cd.c | 161 ++++++++++++++++++++++++++++++++++++--- src/scsi_cd.h | 16 ++++ src/wx-config.c | 110 +++++++++++++++++++++++++-- src/wx-resources.cpp | 176 ++++++++++++++++++++++++++++++------------- 6 files changed, 435 insertions(+), 67 deletions(-) diff --git a/src/pc.c b/src/pc.c index f867092..93f9f2b 100644 --- a/src/pc.c +++ b/src/pc.c @@ -808,6 +808,7 @@ void loadconfig(char *fn) bpb_disable = config_get_int(CFG_MACHINE, NULL, "bpb_disable", 0); cd_speed = config_get_int(CFG_MACHINE, NULL, "cd_speed", 24); + cd_model = cd_model_from_config((char *)config_get_string(CFG_MACHINE, NULL, "cd_model", cd_get_config_model(0))); joystick_type = config_get_int(CFG_MACHINE, NULL, "joystick_type", 0); mouse_type = config_get_int(CFG_MACHINE, NULL, "mouse_type", 0); @@ -955,6 +956,7 @@ void saveconfig(char *fn) config_set_int(CFG_MACHINE, NULL, "bpb_disable", bpb_disable); config_set_int(CFG_MACHINE, NULL, "cd_speed", cd_speed); + config_set_string(CFG_MACHINE, NULL, "cd_model", cd_model_to_config(cd_model)); config_set_int(CFG_MACHINE, NULL, "joystick_type", joystick_type); config_set_int(CFG_MACHINE, NULL, "mouse_type", mouse_type); diff --git a/src/pc.xrc b/src/pc.xrc index cbc4b59..9db0ca0 100644 --- a/src/pc.xrc +++ b/src/pc.xrc @@ -1181,7 +1181,42 @@ 5 80,-1 - + + -1 + + + + + wxEXPAND + 5 + + wxHORIZONTAL + + + wxALL + 5 + + + 350,-1 + + + + + + + + + wxEXPAND + 5 + 0,0 + + + + wxALL | wxALIGN_CENTER_VERTICAL + 5 + + 80,-1 + -1 diff --git a/src/scsi_cd.c b/src/scsi_cd.c index a4fe299..5a56550 100644 --- a/src/scsi_cd.c +++ b/src/scsi_cd.c @@ -204,6 +204,8 @@ typedef struct scsi_cd_data_t int short_seek, long_seek; int max_speed, cur_speed; + + int cur_model; } scsi_cd_data_t; static scsi_cd_data_t *cd_data = NULL; @@ -266,6 +268,146 @@ void cd_set_speed(int speed) } } +static struct +{ + // suffix numbers are sizes from the specs + char *vendor_8; + char *model_and_firmware_40; + char *serial_20; + char *model_16; + char *firmware_4; + + char *serial2_20; + char *firmware2_8; + char *model2_40; + + // for PCem config only + char *model_string_40; + char *model_config_string_40; + int interfaces; + int speed; // Not an index, but a "speed" value. -1 == allow override +} const cd_models[] = +{ + { + // Generic PCem CD + "PCem", + "PCemCD v1.0", + "53R141", + "PCemCD", + "1.0", + + "", + "v1.0", + "PCemCD", + "PCemCD", + "pcemcd", + CD_MODEL_INTERFACE_ALL, + -1, + }, + { + // A 4x CD-ROM drive from Aztech. Choose if your system image has the SGIDECD.SYS driver + "AZT", + "AZT 46802I v1.15", + "53R141", // TODO: clone serial from my real one + "46802I", + "1.15", + + "", + "v1.15", + "CDA46802I", + "AZT CDA 468-02I 4X", + "azt_cda_468_02i_4x", + CD_MODEL_INTERFACE_IDE, + 4, + }, +}; + +char *cd_model = NULL; + +char *cd_get_model(int i) +{ + return cd_models[i].model_string_40; +} + +char *cd_get_config_model(int i) +{ + return cd_models[i].model_config_string_40; +} + +void cd_set_model(char *model) +{ + if (cd_data) + { + int c = 0; + + while (1) + { + if (!model) + break; + if (c > MAX_CD_MODEL) + break; + if (!strncmp(cd_models[c].model_string_40, model, 40)) + break; + + c++; + } + + cd_data->cur_model = c; + } +} + +int cd_get_model_interfaces(int i) +{ + return cd_models[i].interfaces; +} + +int cd_get_model_speed(int i) +{ + return cd_models[i].speed; +} + +char *cd_model_to_config(char *model) +{ + int c = 0; + + while (1) + { + if (!model) + break; + if (c > MAX_CD_MODEL) + { + c = 0; // default + break; + } + if (!strncmp(cd_models[c].model_string_40, model, 40)) + break; + + c++; + } + return cd_models[c].model_config_string_40; +} + +char *cd_model_from_config(char *config) +{ + int c = 0; + + while (1) + { + if (!config) + break; + if (c > MAX_CD_MODEL) + { + c = 0; // default + break; + } + if (!strncmp(cd_models[c].model_config_string_40, config, 40)) + break; + + c++; + } + return cd_models[c].model_string_40; +} + static void scsi_cd_callback(void *p) { scsi_cd_data_t *data = p; @@ -398,6 +540,7 @@ static void *scsi_cd_init(scsi_bus_t *bus, int id) cd_data = data; cd_set_speed(cd_speed); + cd_set_model(cd_model); return data; } @@ -1299,11 +1442,11 @@ static int scsi_cd_command(uint8_t *cdb, void *p) data->data_in[idx++] = 0x01; data->data_in[idx++] = 0x00; data->data_in[idx++] = 68; - ide_padstr8(data->data_in + idx, 8, "PCem"); /* Vendor */ + ide_padstr8(data->data_in + idx, 8, cd_models[cd_data->cur_model].vendor_8); /* Vendor */ idx += 8; - ide_padstr8(data->data_in + idx, 40, "PCemCD v1.0"); /* Product */ + ide_padstr8(data->data_in + idx, 40, cd_models[cd_data->cur_model].model_and_firmware_40); /* Product */ idx += 40; - ide_padstr8(data->data_in + idx, 20, "53R141"); /* Product */ + ide_padstr8(data->data_in + idx, 20, cd_models[cd_data->cur_model].serial_20); /* Product */ idx += 20; break; @@ -1334,9 +1477,9 @@ static int scsi_cd_command(uint8_t *cdb, void *p) data->data_in[6] = 0; data->data_in[7] = 0; - ide_padstr8(data->data_in + 8, 8, "PCem"); /* Vendor */ - ide_padstr8(data->data_in + 16, 16, "PCemCD"); /* Product */ - ide_padstr8(data->data_in + 32, 4, "1.0"); /* Revision */ + ide_padstr8(data->data_in + 8, 8, cd_models[cd_data->cur_model].vendor_8); /* Vendor */ + ide_padstr8(data->data_in + 16, 16, cd_models[cd_data->cur_model].model_16); /* Product */ + ide_padstr8(data->data_in + 32, 4, cd_models[cd_data->cur_model].firmware_4); /* Revision */ idx = 36; } @@ -1488,9 +1631,9 @@ static void scsi_cd_atapi_identify(uint16_t *buffer, void *p) memset(buffer, 0, 512); buffer[0] = 0x8000 | (5<<8) | 0x80 | (2<<5); /* ATAPI device, CD-ROM drive, removable media, accelerated DRQ */ - ide_padstr((char *)(buffer + 10), "", 20); /* Serial Number */ - ide_padstr((char *)(buffer + 23), "v1.0", 8); /* Firmware */ - ide_padstr((char *)(buffer + 27), "PCemCD", 40); /* Model */ + ide_padstr((char *)(buffer + 10), cd_models[cd_data->cur_model].serial2_20, 20); /* Serial Number */ + ide_padstr((char *)(buffer + 23), cd_models[cd_data->cur_model].firmware2_8, 8); /* Firmware */ + ide_padstr((char *)(buffer + 27), cd_models[cd_data->cur_model].model2_40, 40); /* Model */ buffer[49] = 0x300; /*DMA and LBA supported*/ buffer[51] = 120; buffer[52] = 120; diff --git a/src/scsi_cd.h b/src/scsi_cd.h index dc86826..5b3f701 100644 --- a/src/scsi_cd.h +++ b/src/scsi_cd.h @@ -5,3 +5,19 @@ int cd_get_speed(int i); void cd_set_speed(int speed); extern int cd_speed; + +#define MAX_CD_MODEL 1 + +#define CD_MODEL_INTERFACE_ALL 0 // even when controller is not IDE and not SCSI (to always have the PCemCD model as default, even when not selectable) +#define CD_MODEL_INTERFACE_IDE 1 +#define CD_MODEL_INTERFACE_SCSI 2 + +char *cd_get_model(int i); +char *cd_get_config_model(int i); +void cd_set_model(char *model); +int cd_get_model_interfaces(int i); +int cd_get_model_speed(int i); +char *cd_model_to_config(char *model); +char *cd_model_from_config(char *config); + +extern char *cd_model; diff --git a/src/wx-config.c b/src/wx-config.c index cd24749..aa89a5c 100644 --- a/src/wx-config.c +++ b/src/wx-config.c @@ -50,6 +50,8 @@ extern void deviceconfig_open(void* hwnd, device_t *device); extern int hdconf_init(void* hdlg); extern int hdconf_update(void* hdlg); +static int hdd_controller_selected_is_ide(void* hdlg); +static int hdd_controller_selected_is_scsi(void* hdlg); static int hdd_controller_selected_has_config(void *hdlg); static device_t *hdd_controller_selected_get_device(void *hdlg); @@ -360,12 +362,64 @@ static void recalc_hdd_list(void* hdlg, int model, int use_selected_hdd, int for } } -static void recalc_cd_list(void *hdlg, int cur_speed) +// TODO: split this into model/speed recalcs? +static void recalc_cd_list(void *hdlg, int cur_speed, char *cur_model) { - void *h = wx_getdlgitem(hdlg, WX_ID("IDC_COMBO_CDSPEED")); + int temp_model = -1; + void *h = wx_getdlgitem(hdlg, WX_ID("IDC_COMBO_CDMODEL")); int c = 0; - + int found = 0; + wx_sendmessage(h, WX_CB_RESETCONTENT, 0, 0); + if (hdd_controller_selected_is_ide(hdlg) || hdd_controller_selected_is_scsi(hdlg)) + wx_enablewindow(h, TRUE); + else + wx_enablewindow(h, FALSE); + while (1) + { + char s[40]; + char *model; + + if ((cd_get_model_interfaces(c) == CD_MODEL_INTERFACE_ALL) || + (cd_get_model_interfaces(c) == CD_MODEL_INTERFACE_IDE && hdd_controller_selected_is_ide(hdlg)) || + (cd_get_model_interfaces(c) == CD_MODEL_INTERFACE_SCSI && hdd_controller_selected_is_scsi(hdlg))) + { + + model = cd_get_model(c); + sprintf(s, "%s", model); + wx_sendmessage(h, WX_CB_ADDSTRING, 0, (LONG_PARAM)s); + + if (!strncmp(s, cur_model, 40)) + { + wx_sendmessage(h, WX_CB_SETCURSEL, c, 0); + temp_model = c; + found = 1; + } + } + + c++; + if (c > MAX_CD_MODEL) + break; + } + if (!found) + wx_sendmessage(h, WX_CB_SETCURSEL, 0, 0); // assume that there is always at least one TODO: is this necessary? + + + h = wx_getdlgitem(hdlg, WX_ID("IDC_COMBO_CDSPEED")); + c = 0; + found = 0; + + wx_sendmessage(h, WX_CB_RESETCONTENT, 0, 0); + if (temp_model >= 0 && cd_get_model_speed(temp_model) != -1) + { + // this model has a specific speed + wx_enablewindow(h, FALSE); + cur_speed = cd_get_model_speed(temp_model); + } + else if (hdd_controller_selected_is_ide(hdlg) || hdd_controller_selected_is_scsi(hdlg)) + wx_enablewindow(h, TRUE); + else + wx_enablewindow(h, FALSE); while (1) { char s[8]; @@ -376,12 +430,17 @@ static void recalc_cd_list(void *hdlg, int cur_speed) wx_sendmessage(h, WX_CB_ADDSTRING, 0, (LONG_PARAM)s); if (speed == cur_speed) + { wx_sendmessage(h, WX_CB_SETCURSEL, c, 0); - + found = 1; + } + c++; if (speed >= MAX_CD_SPEED) break; } + if (!found) + wx_sendmessage(h, WX_CB_SETCURSEL, 0, 0); // fall back TODO: is this necessary? } #ifdef USE_NETWORKING @@ -615,6 +674,10 @@ int config_dlgsave(void* hdlg) cd_speed = cd_get_speed(wx_sendmessage(h, WX_CB_GETCURSEL, 0, 0)); cd_set_speed(cd_speed); + h = wx_getdlgitem(hdlg, WX_ID("IDC_COMBO_CDMODEL")); + cd_model = cd_get_model(wx_sendmessage(h, WX_CB_GETCURSEL, 0, 0)); + cd_set_model(cd_model); + if (has_been_inited) saveconfig(NULL); @@ -639,6 +702,7 @@ int config_dlgproc(void* hdlg, int message, INT_PARAM wParam, LONG_PARAM lParam) int temp_dynarec; int cpu_flags; int cpu_type; + int temp_cd_model, temp_cd_speed; int temp_mouse_type; #ifdef USE_NETWORKING int temp_network_card; @@ -893,7 +957,7 @@ int config_dlgproc(void* hdlg, int message, INT_PARAM wParam, LONG_PARAM lParam) wx_sendmessage(h, WX_CB_SETCURSEL, 0, 0); } - recalc_cd_list(hdlg, cd_speed); + recalc_cd_list(hdlg, cd_speed, cd_model); #ifdef USE_NETWORKING recalc_net_list(hdlg, romstomodel[romset]); @@ -1048,6 +1112,12 @@ int config_dlgproc(void* hdlg, int message, INT_PARAM wParam, LONG_PARAM lParam) recalc_hdd_list(hdlg, temp_model, 1, force_ide); + h = wx_getdlgitem(hdlg, WX_ID("IDC_COMBO_CDMODEL")); + temp_cd_model = wx_sendmessage(h, WX_CB_GETCURSEL, 0, 0); + h = wx_getdlgitem(hdlg, WX_ID("IDC_COMBO_CDSPEED")); + temp_cd_speed = wx_sendmessage(h, WX_CB_GETCURSEL, 0, 0); + recalc_cd_list(hdlg, cd_get_speed(temp_cd_speed), cd_get_model(temp_cd_model)); + recalc_snd_list(hdlg, temp_model); #ifdef USE_NETWORKING recalc_net_list(hdlg, temp_model); @@ -1198,11 +1268,25 @@ int config_dlgproc(void* hdlg, int message, INT_PARAM wParam, LONG_PARAM lParam) h = wx_getdlgitem(hdlg, WX_ID("IDC_COMBO1")); temp_model = listtomodel[wx_sendmessage(h, WX_CB_GETCURSEL, 0, 0)]; recalc_hdd_list(hdlg, temp_model, 1, 0); + + h = wx_getdlgitem(hdlg, WX_ID("IDC_COMBO_CDMODEL")); + temp_cd_model = wx_sendmessage(h, WX_CB_GETCURSEL, 0, 0); + h = wx_getdlgitem(hdlg, WX_ID("IDC_COMBO_CDSPEED")); + temp_cd_speed = wx_sendmessage(h, WX_CB_GETCURSEL, 0, 0); + recalc_cd_list(hdlg, cd_get_speed(temp_cd_speed), cd_get_model(temp_cd_model)); } else if (wParam == WX_ID("IDC_CONFIGUREHDD")) { deviceconfig_open(hdlg, (void *)hdd_controller_selected_get_device(hdlg)); } + else if (wParam == WX_ID("IDC_COMBO_CDMODEL")) + { + h = wx_getdlgitem(hdlg, WX_ID("IDC_COMBO_CDMODEL")); + temp_cd_model = wx_sendmessage(h, WX_CB_GETCURSEL, 0, 0); + h = wx_getdlgitem(hdlg, WX_ID("IDC_COMBO_CDSPEED")); + temp_cd_speed = wx_sendmessage(h, WX_CB_GETCURSEL, 0, 0); + recalc_cd_list(hdlg, cd_get_speed(temp_cd_speed), cd_get_model(temp_cd_model)); + } #ifdef USE_NETWORKING else if (wParam == WX_ID("IDC_COMBO_NETCARD")) { @@ -1337,6 +1421,22 @@ static int hdd_controller_selected_is_mfm(void* hdlg) return hdd_controller_is_mfm(hdd_names[c]); return 0; } +static int hdd_controller_selected_is_ide(void* hdlg) +{ + void* h = wx_getdlgitem(hdlg, WX_ID("IDC_COMBOHDD")); + int c = wx_sendmessage(h, WX_CB_GETCURSEL, 0, 0); + if (hdd_names[c]) + return hdd_controller_is_ide(hdd_names[c]); + return 0; +} +static int hdd_controller_selected_is_scsi(void* hdlg) +{ + void* h = wx_getdlgitem(hdlg, WX_ID("IDC_COMBOHDD")); + int c = wx_sendmessage(h, WX_CB_GETCURSEL, 0, 0); + if (hdd_names[c]) + return hdd_controller_is_scsi(hdd_names[c]); + return 0; +} static int hdd_controller_selected_has_config(void* hdlg) { void* h = wx_getdlgitem(hdlg, WX_ID("IDC_COMBOHDD")); diff --git a/src/wx-resources.cpp b/src/wx-resources.cpp index 553b49d..6ed31ee 100644 --- a/src/wx-resources.cpp +++ b/src/wx-resources.cpp @@ -1784,7 +1784,7 @@ static unsigned char xml_res_file_25[] = { 87,93,129,205,251,40,255,176,89,15,134,167,154,149,127,4,24,0,227,17,114, 29,252,169,144,138,0,0,0,0,73,69,78,68,174,66,96,130}; -static size_t xml_res_size_26 = 139477; +static size_t xml_res_size_26 = 141099; static unsigned char xml_res_file_26[] = { 60,63,120,109,108,32,118,101,114,115,105,111,110,61,34,49,46,48,34,32,101, 110,99,111,100,105,110,103,61,34,85,84,70,45,56,34,63,62,10,60,33,45,45, @@ -3915,58 +3915,130 @@ static unsigned char xml_res_file_26[] = { 99,84,101,120,116,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, 32,32,32,32,32,32,32,32,32,32,32,60,115,105,122,101,62,56,48,44,45,49,60, 47,115,105,122,101,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, -32,32,32,32,32,32,32,32,32,32,60,108,97,98,101,108,62,67,68,45,82,79,77, -58,60,47,108,97,98,101,108,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32, -32,32,32,32,32,32,32,32,32,32,32,32,32,60,119,114,97,112,62,45,49,60,47, -119,114,97,112,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, -32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32, -32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99, -116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, -32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,105,122,101, -114,105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32, -32,32,32,32,32,32,32,32,32,32,60,111,112,116,105,111,110,62,49,60,47,111, -112,116,105,111,110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, -32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,69,88,80,65,78, -68,60,47,102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32, -32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,101,114,62,53,60,47,98, -111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, -32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115, -61,34,119,120,66,111,120,83,105,122,101,114,34,62,10,32,32,32,32,32,32, -32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,114, -105,101,110,116,62,119,120,72,79,82,73,90,79,78,84,65,76,60,47,111,114, -105,101,110,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, -32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115, -61,34,115,105,122,101,114,105,116,101,109,34,62,10,32,32,32,32,32,32,32, -32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,112, -116,105,111,110,62,48,60,47,111,112,116,105,111,110,62,10,32,32,32,32,32, -32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60, -102,108,97,103,62,119,120,65,76,76,60,47,102,108,97,103,62,10,32,32,32, -32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, -32,60,98,111,114,100,101,114,62,53,60,47,98,111,114,100,101,114,62,10,32, -32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, -32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,67, -111,109,98,111,66,111,120,34,32,110,97,109,101,61,34,73,68,67,95,67,79, -77,66,79,95,67,68,83,80,69,69,68,34,62,10,32,32,32,32,32,32,32,32,32,32, -32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,115,116, -121,108,101,62,119,120,67,66,95,68,82,79,80,68,79,87,78,124,119,120,67, -66,95,82,69,65,68,79,78,76,89,60,47,115,116,121,108,101,62,10,32,32,32, -32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, -32,32,32,60,115,105,122,101,62,51,53,48,44,45,49,60,47,115,105,122,101, -62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, -32,32,32,32,32,32,32,32,60,118,97,108,117,101,47,62,10,32,32,32,32,32,32, -32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, -60,99,111,110,116,101,110,116,47,62,10,32,32,32,32,32,32,32,32,32,32,32, -32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101, -99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, -32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32, -32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101, -99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, -32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,60,108,97,98,101,108,62,67,68,32,77,111,100, +101,108,58,60,47,108,97,98,101,108,62,10,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,119,114,97,112,62,45, +49,60,47,119,114,97,112,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106, +101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,105, +122,101,114,105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,60,111,112,116,105,111,110,62,49,60, +47,111,112,116,105,111,110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,69,88,80, +65,78,68,60,47,102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,101,114,62,53,60, +47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32, 32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97, -115,115,61,34,115,112,97,99,101,114,34,62,10,32,32,32,32,32,32,32,32,32, -32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,112,116,105,111,110, -62,49,60,47,111,112,116,105,111,110,62,10,32,32,32,32,32,32,32,32,32,32, -32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,119,120, +115,115,61,34,119,120,66,111,120,83,105,122,101,114,34,62,10,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111, +114,105,101,110,116,62,119,120,72,79,82,73,90,79,78,84,65,76,60,47,111, +114,105,101,110,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97, +115,115,61,34,115,105,122,101,114,105,116,101,109,34,62,10,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +60,111,112,116,105,111,110,62,48,60,47,111,112,116,105,111,110,62,10,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,60,102,108,97,103,62,119,120,65,76,76,60,47,102,108,97,103,62, +10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,60,98,111,114,100,101,114,62,53,60,47,98,111,114,100,101, +114,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34, +119,120,67,111,109,98,111,66,111,120,34,32,110,97,109,101,61,34,73,68,67, +95,67,79,77,66,79,95,67,68,77,79,68,69,76,34,62,10,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60, +115,116,121,108,101,62,119,120,67,66,95,68,82,79,80,68,79,87,78,124,119, +120,67,66,95,82,69,65,68,79,78,76,89,60,47,115,116,121,108,101,62,10,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,60,115,105,122,101,62,51,53,48,44,45,49,60,47,115,105,122, +101,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,60,118,97,108,117,101,47,62,10,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +32,60,99,111,110,116,101,110,116,47,62,10,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106, +101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106, +101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108, +97,115,115,61,34,115,112,97,99,101,114,34,62,10,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,112,116,105,111, +110,62,49,60,47,111,112,116,105,111,110,62,10,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,119,120, +69,88,80,65,78,68,60,47,102,108,97,103,62,10,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,101,114, +62,53,60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,115,105,122,101,62,48,44,48, +60,47,115,105,122,101,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116, +32,99,108,97,115,115,61,34,115,105,122,101,114,105,116,101,109,34,62,10, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +60,111,112,116,105,111,110,62,48,60,47,111,112,116,105,111,110,62,10,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60, +102,108,97,103,62,119,120,65,76,76,32,124,32,119,120,65,76,73,71,78,95, +67,69,78,84,69,82,95,86,69,82,84,73,67,65,76,60,47,102,108,97,103,62,10, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +60,98,111,114,100,101,114,62,53,60,47,98,111,114,100,101,114,62,10,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111, +98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,83,116,97,116,105, +99,84,101,120,116,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,60,115,105,122,101,62,56,48,44,45,49,60, +47,115,105,122,101,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,60,108,97,98,101,108,62,67,68,32,83,112,101, +101,100,58,60,47,108,97,98,101,108,62,10,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,119,114,97,112,62,45, +49,60,47,119,114,97,112,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106, +101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,105, +122,101,114,105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,60,111,112,116,105,111,110,62,49,60, +47,111,112,116,105,111,110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,69,88,80, +65,78,68,60,47,102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,101,114,62,53,60, +47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97, +115,115,61,34,119,120,66,111,120,83,105,122,101,114,34,62,10,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111, +114,105,101,110,116,62,119,120,72,79,82,73,90,79,78,84,65,76,60,47,111, +114,105,101,110,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97, +115,115,61,34,115,105,122,101,114,105,116,101,109,34,62,10,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +60,111,112,116,105,111,110,62,48,60,47,111,112,116,105,111,110,62,10,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,60,102,108,97,103,62,119,120,65,76,76,60,47,102,108,97,103,62, +10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,60,98,111,114,100,101,114,62,53,60,47,98,111,114,100,101, +114,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34, +119,120,67,111,109,98,111,66,111,120,34,32,110,97,109,101,61,34,73,68,67, +95,67,79,77,66,79,95,67,68,83,80,69,69,68,34,62,10,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60, +115,116,121,108,101,62,119,120,67,66,95,68,82,79,80,68,79,87,78,124,119, +120,67,66,95,82,69,65,68,79,78,76,89,60,47,115,116,121,108,101,62,10,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,60,115,105,122,101,62,51,53,48,44,45,49,60,47,115,105,122, +101,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,60,118,97,108,117,101,47,62,10,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +32,60,99,111,110,116,101,110,116,47,62,10,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106, +101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106, +101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108, +97,115,115,61,34,115,112,97,99,101,114,34,62,10,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,112,116,105,111, +110,62,49,60,47,111,112,116,105,111,110,62,10,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,119,120, 69,88,80,65,78,68,60,47,102,108,97,103,62,10,32,32,32,32,32,32,32,32,32, 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,101,114, 62,53,60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,32,