trunk/src/emu/ui/inputmap.c
| r0 | r242909 | |
| 1 | /********************************************************************* |
| 2 | |
| 3 | ui/inputmap.c |
| 4 | |
| 5 | Internal menus for input mappings. |
| 6 | |
| 7 | Copyright Nicola Salmoria and the MAME Team. |
| 8 | Visit http://mamedev.org for licensing and usage restrictions. |
| 9 | |
| 10 | *********************************************************************/ |
| 11 | |
| 12 | #include "emu.h" |
| 13 | |
| 14 | #include "uiinput.h" |
| 15 | #include "ui/ui.h" |
| 16 | #include "ui/inputmap.h" |
| 17 | |
| 18 | |
| 19 | /*************************************************************************** |
| 20 | CONSTANTS |
| 21 | ***************************************************************************/ |
| 22 | |
| 23 | #define MAX_PHYSICAL_DIPS 10 |
| 24 | #define MAX_INPUT_PORTS 32 |
| 25 | #define MAX_BITS_PER_PORT 32 |
| 26 | |
| 27 | /* DIP switch rendering parameters */ |
| 28 | #define DIP_SWITCH_HEIGHT 0.05f |
| 29 | #define DIP_SWITCH_SPACING 0.01 |
| 30 | #define SINGLE_TOGGLE_SWITCH_FIELD_WIDTH 0.025f |
| 31 | #define SINGLE_TOGGLE_SWITCH_WIDTH 0.020f |
| 32 | /* make the switch 80% of the width space and 1/2 of the switch height */ |
| 33 | #define PERCENTAGE_OF_HALF_FIELD_USED 0.80f |
| 34 | #define SINGLE_TOGGLE_SWITCH_HEIGHT ((DIP_SWITCH_HEIGHT / 2) * PERCENTAGE_OF_HALF_FIELD_USED) |
| 35 | |
| 36 | |
| 37 | |
| 38 | /*------------------------------------------------- |
| 39 | menu_input_groups_populate - populate the |
| 40 | input groups menu |
| 41 | -------------------------------------------------*/ |
| 42 | |
| 43 | ui_menu_input_groups::ui_menu_input_groups(running_machine &machine, render_container *container) : ui_menu(machine, container) |
| 44 | { |
| 45 | } |
| 46 | |
| 47 | void ui_menu_input_groups::populate() |
| 48 | { |
| 49 | int player; |
| 50 | |
| 51 | /* build up the menu */ |
| 52 | item_append("User Interface", NULL, 0, (void *)(IPG_UI + 1)); |
| 53 | for (player = 0; player < MAX_PLAYERS; player++) |
| 54 | { |
| 55 | char buffer[40]; |
| 56 | sprintf(buffer, "Player %d Controls", player + 1); |
| 57 | item_append(buffer, NULL, 0, (void *)(FPTR)(IPG_PLAYER1 + player + 1)); |
| 58 | } |
| 59 | item_append("Other Controls", NULL, 0, (void *)(FPTR)(IPG_OTHER + 1)); |
| 60 | } |
| 61 | |
| 62 | ui_menu_input_groups::~ui_menu_input_groups() |
| 63 | { |
| 64 | } |
| 65 | |
| 66 | /*------------------------------------------------- |
| 67 | menu_input_groups - handle the input groups |
| 68 | menu |
| 69 | -------------------------------------------------*/ |
| 70 | |
| 71 | void ui_menu_input_groups::handle() |
| 72 | { |
| 73 | /* process the menu */ |
| 74 | const ui_menu_event *menu_event = process(0); |
| 75 | if (menu_event != NULL && menu_event->iptkey == IPT_UI_SELECT) |
| 76 | ui_menu::stack_push(auto_alloc_clear(machine(), ui_menu_input_general(machine(), container, int((long long)(menu_event->itemref)-1)))); |
| 77 | } |
| 78 | |
| 79 | |
| 80 | |
| 81 | /*------------------------------------------------- |
| 82 | menu_input_general - handle the general |
| 83 | input menu |
| 84 | -------------------------------------------------*/ |
| 85 | |
| 86 | ui_menu_input_general::ui_menu_input_general(running_machine &machine, render_container *container, int _group) : ui_menu_input(machine, container) |
| 87 | { |
| 88 | group = _group; |
| 89 | } |
| 90 | |
| 91 | void ui_menu_input_general::populate() |
| 92 | { |
| 93 | input_item_data *itemlist = NULL; |
| 94 | int suborder[SEQ_TYPE_TOTAL]; |
| 95 | astring tempstring; |
| 96 | int sortorder = 1; |
| 97 | |
| 98 | /* create a mini lookup table for sort order based on sequence type */ |
| 99 | suborder[SEQ_TYPE_STANDARD] = 0; |
| 100 | suborder[SEQ_TYPE_DECREMENT] = 1; |
| 101 | suborder[SEQ_TYPE_INCREMENT] = 2; |
| 102 | |
| 103 | /* iterate over the input ports and add menu items */ |
| 104 | for (input_type_entry *entry = machine().ioport().first_type(); entry != NULL; entry = entry->next()) |
| 105 | |
| 106 | /* add if we match the group and we have a valid name */ |
| 107 | if (entry->group() == group && entry->name() != NULL && entry->name()[0] != 0) |
| 108 | { |
| 109 | input_seq_type seqtype; |
| 110 | |
| 111 | /* loop over all sequence types */ |
| 112 | sortorder++; |
| 113 | for (seqtype = SEQ_TYPE_STANDARD; seqtype < SEQ_TYPE_TOTAL; seqtype++) |
| 114 | { |
| 115 | /* build an entry for the standard sequence */ |
| 116 | input_item_data *item = (input_item_data *)m_pool_alloc(sizeof(*item)); |
| 117 | memset(item, 0, sizeof(*item)); |
| 118 | item->ref = entry; |
| 119 | if(pollingitem && pollingref == entry && pollingseq == seqtype) |
| 120 | pollingitem = item; |
| 121 | item->seqtype = seqtype; |
| 122 | item->seq = machine().ioport().type_seq(entry->type(), entry->player(), seqtype); |
| 123 | item->defseq = &entry->defseq(seqtype); |
| 124 | item->sortorder = sortorder * 4 + suborder[seqtype]; |
| 125 | item->type = ioport_manager::type_is_analog(entry->type()) ? (INPUT_TYPE_ANALOG + seqtype) : INPUT_TYPE_DIGITAL; |
| 126 | item->name = entry->name(); |
| 127 | item->owner_name = NULL; |
| 128 | item->next = itemlist; |
| 129 | itemlist = item; |
| 130 | |
| 131 | /* stop after one, unless we're analog */ |
| 132 | if (item->type == INPUT_TYPE_DIGITAL) |
| 133 | break; |
| 134 | } |
| 135 | } |
| 136 | |
| 137 | /* sort and populate the menu in a standard fashion */ |
| 138 | populate_and_sort(itemlist); |
| 139 | } |
| 140 | |
| 141 | ui_menu_input_general::~ui_menu_input_general() |
| 142 | { |
| 143 | } |
| 144 | |
| 145 | /*------------------------------------------------- |
| 146 | menu_input_specific - handle the game-specific |
| 147 | input menu |
| 148 | -------------------------------------------------*/ |
| 149 | |
| 150 | ui_menu_input_specific::ui_menu_input_specific(running_machine &machine, render_container *container) : ui_menu_input(machine, container) |
| 151 | { |
| 152 | } |
| 153 | |
| 154 | void ui_menu_input_specific::populate() |
| 155 | { |
| 156 | input_item_data *itemlist = NULL; |
| 157 | ioport_field *field; |
| 158 | ioport_port *port; |
| 159 | int suborder[SEQ_TYPE_TOTAL]; |
| 160 | astring tempstring; |
| 161 | |
| 162 | /* create a mini lookup table for sort order based on sequence type */ |
| 163 | suborder[SEQ_TYPE_STANDARD] = 0; |
| 164 | suborder[SEQ_TYPE_DECREMENT] = 1; |
| 165 | suborder[SEQ_TYPE_INCREMENT] = 2; |
| 166 | |
| 167 | /* iterate over the input ports and add menu items */ |
| 168 | for (port = machine().ioport().first_port(); port != NULL; port = port->next()) |
| 169 | for (field = port->first_field(); field != NULL; field = field->next()) |
| 170 | { |
| 171 | const char *name = field->name(); |
| 172 | |
| 173 | /* add if we match the group and we have a valid name */ |
| 174 | if (name != NULL && field->enabled() && |
| 175 | ((field->type() == IPT_OTHER && field->name() != NULL) || machine().ioport().type_group(field->type(), field->player()) != IPG_INVALID)) |
| 176 | { |
| 177 | input_seq_type seqtype; |
| 178 | UINT32 sortorder; |
| 179 | |
| 180 | /* determine the sorting order */ |
| 181 | if (field->type() >= IPT_START1 && field->type() < IPT_ANALOG_LAST) |
| 182 | { |
| 183 | sortorder = (field->type() << 2) | (field->player() << 12); |
| 184 | if (strcmp(field->device().tag(), ":")) |
| 185 | sortorder |= 0x10000; |
| 186 | } |
| 187 | else |
| 188 | sortorder = field->type() | 0xf000; |
| 189 | |
| 190 | /* loop over all sequence types */ |
| 191 | for (seqtype = SEQ_TYPE_STANDARD; seqtype < SEQ_TYPE_TOTAL; seqtype++) |
| 192 | { |
| 193 | /* build an entry for the standard sequence */ |
| 194 | input_item_data *item = (input_item_data *)m_pool_alloc(sizeof(*item)); |
| 195 | memset(item, 0, sizeof(*item)); |
| 196 | item->ref = field; |
| 197 | item->seqtype = seqtype; |
| 198 | if(pollingitem && pollingref == field && pollingseq == seqtype) |
| 199 | pollingitem = item; |
| 200 | item->seq = field->seq(seqtype); |
| 201 | item->defseq = &field->defseq(seqtype); |
| 202 | item->sortorder = sortorder + suborder[seqtype]; |
| 203 | item->type = field->is_analog() ? (INPUT_TYPE_ANALOG + seqtype) : INPUT_TYPE_DIGITAL; |
| 204 | item->name = name; |
| 205 | item->owner_name = field->device().tag(); |
| 206 | item->next = itemlist; |
| 207 | itemlist = item; |
| 208 | |
| 209 | /* stop after one, unless we're analog */ |
| 210 | if (item->type == INPUT_TYPE_DIGITAL) |
| 211 | break; |
| 212 | } |
| 213 | } |
| 214 | } |
| 215 | |
| 216 | /* sort and populate the menu in a standard fashion */ |
| 217 | populate_and_sort(itemlist); |
| 218 | } |
| 219 | |
| 220 | ui_menu_input_specific::~ui_menu_input_specific() |
| 221 | { |
| 222 | } |
| 223 | |
| 224 | /*------------------------------------------------- |
| 225 | menu_input - display a menu for inputs |
| 226 | -------------------------------------------------*/ |
| 227 | ui_menu_input::ui_menu_input(running_machine &machine, render_container *container) : ui_menu(machine, container) |
| 228 | { |
| 229 | pollingitem = 0; |
| 230 | pollingref = 0; |
| 231 | pollingseq = SEQ_TYPE_STANDARD; |
| 232 | } |
| 233 | |
| 234 | ui_menu_input::~ui_menu_input() |
| 235 | { |
| 236 | } |
| 237 | |
| 238 | /*------------------------------------------------- |
| 239 | toggle_none_default - toggle between "NONE" |
| 240 | and the default item |
| 241 | -------------------------------------------------*/ |
| 242 | |
| 243 | void ui_menu_input::toggle_none_default(input_seq &selected_seq, input_seq &original_seq, const input_seq &selected_defseq) |
| 244 | { |
| 245 | /* if we used to be "none", toggle to the default value */ |
| 246 | if (original_seq.length() == 0) |
| 247 | selected_seq = selected_defseq; |
| 248 | |
| 249 | /* otherwise, toggle to "none" */ |
| 250 | else |
| 251 | selected_seq.reset(); |
| 252 | } |
| 253 | |
| 254 | void ui_menu_input::handle() |
| 255 | { |
| 256 | input_item_data *seqchangeditem = NULL; |
| 257 | const ui_menu_event *menu_event; |
| 258 | int invalidate = false; |
| 259 | |
| 260 | /* process the menu */ |
| 261 | menu_event = process((pollingitem != NULL) ? UI_MENU_PROCESS_NOKEYS : 0); |
| 262 | |
| 263 | /* if we are polling, handle as a special case */ |
| 264 | if (pollingitem != NULL) |
| 265 | { |
| 266 | input_item_data *item = pollingitem; |
| 267 | input_seq newseq; |
| 268 | |
| 269 | /* if UI_CANCEL is pressed, abort */ |
| 270 | if (ui_input_pressed(machine(), IPT_UI_CANCEL)) |
| 271 | { |
| 272 | pollingitem = NULL; |
| 273 | record_next = false; |
| 274 | toggle_none_default(item->seq, starting_seq, *item->defseq); |
| 275 | seqchangeditem = item; |
| 276 | } |
| 277 | |
| 278 | /* poll again; if finished, update the sequence */ |
| 279 | if (machine().input().seq_poll()) |
| 280 | { |
| 281 | pollingitem = NULL; |
| 282 | record_next = true; |
| 283 | item->seq = machine().input().seq_poll_final(); |
| 284 | seqchangeditem = item; |
| 285 | } |
| 286 | } |
| 287 | |
| 288 | /* otherwise, handle the events */ |
| 289 | else if (menu_event != NULL && menu_event->itemref != NULL) |
| 290 | { |
| 291 | input_item_data *item = (input_item_data *)menu_event->itemref; |
| 292 | switch (menu_event->iptkey) |
| 293 | { |
| 294 | /* an item was selected: begin polling */ |
| 295 | case IPT_UI_SELECT: |
| 296 | pollingitem = item; |
| 297 | last_sortorder = item->sortorder; |
| 298 | starting_seq = item->seq; |
| 299 | machine().input().seq_poll_start((item->type == INPUT_TYPE_ANALOG) ? ITEM_CLASS_ABSOLUTE : ITEM_CLASS_SWITCH, record_next ? &item->seq : NULL); |
| 300 | invalidate = true; |
| 301 | break; |
| 302 | |
| 303 | /* if the clear key was pressed, reset the selected item */ |
| 304 | case IPT_UI_CLEAR: |
| 305 | toggle_none_default(item->seq, item->seq, *item->defseq); |
| 306 | record_next = false; |
| 307 | seqchangeditem = item; |
| 308 | break; |
| 309 | } |
| 310 | |
| 311 | /* if the selection changed, reset the "record next" flag */ |
| 312 | if (item->sortorder != last_sortorder) |
| 313 | record_next = false; |
| 314 | last_sortorder = item->sortorder; |
| 315 | } |
| 316 | |
| 317 | /* if the sequence changed, update it */ |
| 318 | if (seqchangeditem != NULL) |
| 319 | { |
| 320 | update_input(seqchangeditem); |
| 321 | |
| 322 | /* invalidate the menu to force an update */ |
| 323 | invalidate = true; |
| 324 | } |
| 325 | |
| 326 | /* if the menu is invalidated, clear it now */ |
| 327 | if (invalidate) |
| 328 | { |
| 329 | pollingref = NULL; |
| 330 | if (pollingitem != NULL) |
| 331 | { |
| 332 | pollingref = pollingitem->ref; |
| 333 | pollingseq = pollingitem->seqtype; |
| 334 | } |
| 335 | reset(UI_MENU_RESET_REMEMBER_POSITION); |
| 336 | } |
| 337 | } |
| 338 | |
| 339 | void ui_menu_input_general::update_input(struct input_item_data *seqchangeditem) |
| 340 | { |
| 341 | const input_type_entry *entry = (const input_type_entry *)seqchangeditem->ref; |
| 342 | machine().ioport().set_type_seq(entry->type(), entry->player(), seqchangeditem->seqtype, seqchangeditem->seq); |
| 343 | } |
| 344 | |
| 345 | void ui_menu_input_specific::update_input(struct input_item_data *seqchangeditem) |
| 346 | { |
| 347 | ioport_field::user_settings settings; |
| 348 | |
| 349 | ((ioport_field *)seqchangeditem->ref)->get_user_settings(settings); |
| 350 | settings.seq[seqchangeditem->seqtype] = seqchangeditem->seq; |
| 351 | ((ioport_field *)seqchangeditem->ref)->set_user_settings(settings); |
| 352 | } |
| 353 | |
| 354 | |
| 355 | /*------------------------------------------------- |
| 356 | menu_input_compare_items - compare two |
| 357 | items for quicksort |
| 358 | -------------------------------------------------*/ |
| 359 | |
| 360 | int ui_menu_input::compare_items(const void *i1, const void *i2) |
| 361 | { |
| 362 | const input_item_data * const *data1 = (const input_item_data * const *)i1; |
| 363 | const input_item_data * const *data2 = (const input_item_data * const *)i2; |
| 364 | if ((*data1)->sortorder < (*data2)->sortorder) |
| 365 | return -1; |
| 366 | if ((*data1)->sortorder > (*data2)->sortorder) |
| 367 | return 1; |
| 368 | return 0; |
| 369 | } |
| 370 | |
| 371 | |
| 372 | /*------------------------------------------------- |
| 373 | menu_input_populate_and_sort - take a list |
| 374 | of input_item_data objects and build up the |
| 375 | menu from them |
| 376 | -------------------------------------------------*/ |
| 377 | |
| 378 | void ui_menu_input::populate_and_sort(input_item_data *itemlist) |
| 379 | { |
| 380 | const char *nameformat[INPUT_TYPE_TOTAL] = { 0 }; |
| 381 | input_item_data **itemarray, *item; |
| 382 | int numitems = 0, curitem; |
| 383 | astring text; |
| 384 | astring subtext; |
| 385 | astring prev_owner; |
| 386 | bool first_entry = true; |
| 387 | |
| 388 | /* create a mini lookup table for name format based on type */ |
| 389 | nameformat[INPUT_TYPE_DIGITAL] = "%s"; |
| 390 | nameformat[INPUT_TYPE_ANALOG] = "%s Analog"; |
| 391 | nameformat[INPUT_TYPE_ANALOG_INC] = "%s Analog Inc"; |
| 392 | nameformat[INPUT_TYPE_ANALOG_DEC] = "%s Analog Dec"; |
| 393 | |
| 394 | /* first count the number of items */ |
| 395 | for (item = itemlist; item != NULL; item = item->next) |
| 396 | numitems++; |
| 397 | |
| 398 | /* now allocate an array of items and fill it up */ |
| 399 | itemarray = (input_item_data **)m_pool_alloc(sizeof(*itemarray) * numitems); |
| 400 | for (item = itemlist, curitem = 0; item != NULL; item = item->next) |
| 401 | itemarray[curitem++] = item; |
| 402 | |
| 403 | /* sort it */ |
| 404 | qsort(itemarray, numitems, sizeof(*itemarray), compare_items); |
| 405 | |
| 406 | /* build the menu */ |
| 407 | for (curitem = 0; curitem < numitems; curitem++) |
| 408 | { |
| 409 | UINT32 flags = 0; |
| 410 | |
| 411 | /* generate the name of the item itself, based off the base name and the type */ |
| 412 | item = itemarray[curitem]; |
| 413 | assert(nameformat[item->type] != NULL); |
| 414 | |
| 415 | if (strcmp(item->owner_name, prev_owner.cstr()) != 0) |
| 416 | { |
| 417 | if (first_entry) |
| 418 | first_entry = false; |
| 419 | else |
| 420 | item_append(MENU_SEPARATOR_ITEM, NULL, 0, NULL); |
| 421 | text.printf("[root%s]", item->owner_name); |
| 422 | item_append(text, NULL, 0, NULL); |
| 423 | prev_owner.cpy(item->owner_name); |
| 424 | } |
| 425 | |
| 426 | text.printf(nameformat[item->type], item->name); |
| 427 | |
| 428 | /* if we're polling this item, use some spaces with left/right arrows */ |
| 429 | if (pollingref == item->ref) |
| 430 | { |
| 431 | subtext.cpy(" "); |
| 432 | flags |= MENU_FLAG_LEFT_ARROW | MENU_FLAG_RIGHT_ARROW; |
| 433 | } |
| 434 | |
| 435 | /* otherwise, generate the sequence name and invert it if different from the default */ |
| 436 | else |
| 437 | { |
| 438 | machine().input().seq_name(subtext, item->seq); |
| 439 | flags |= (item->seq != *item->defseq) ? MENU_FLAG_INVERT : 0; |
| 440 | } |
| 441 | |
| 442 | /* add the item */ |
| 443 | item_append(text, subtext, flags, item); |
| 444 | } |
| 445 | } |
| 446 | |
| 447 | |
| 448 | /*------------------------------------------------- |
| 449 | menu_settings_dip_switches - handle the DIP |
| 450 | switches menu |
| 451 | -------------------------------------------------*/ |
| 452 | |
| 453 | ui_menu_settings_dip_switches::ui_menu_settings_dip_switches(running_machine &machine, render_container *container) : ui_menu_settings(machine, container, IPT_DIPSWITCH) |
| 454 | { |
| 455 | } |
| 456 | |
| 457 | ui_menu_settings_dip_switches::~ui_menu_settings_dip_switches() |
| 458 | { |
| 459 | } |
| 460 | |
| 461 | /*------------------------------------------------- |
| 462 | menu_settings_driver_config - handle the |
| 463 | driver config menu |
| 464 | -------------------------------------------------*/ |
| 465 | |
| 466 | ui_menu_settings_driver_config::ui_menu_settings_driver_config(running_machine &machine, render_container *container) : ui_menu_settings(machine, container, IPT_CONFIG) |
| 467 | { |
| 468 | } |
| 469 | |
| 470 | ui_menu_settings_driver_config::~ui_menu_settings_driver_config() |
| 471 | { |
| 472 | } |
| 473 | |
| 474 | /*------------------------------------------------- |
| 475 | menu_settings_common - handle one of the |
| 476 | switches menus |
| 477 | -------------------------------------------------*/ |
| 478 | |
| 479 | void ui_menu_settings::handle() |
| 480 | { |
| 481 | // process the menu |
| 482 | const ui_menu_event *menu_event = process(0); |
| 483 | |
| 484 | // handle events |
| 485 | if (menu_event != NULL && menu_event->itemref != NULL) |
| 486 | { |
| 487 | // reset |
| 488 | if ((FPTR)menu_event->itemref == 1) |
| 489 | { |
| 490 | if (menu_event->iptkey == IPT_UI_SELECT) |
| 491 | machine().schedule_hard_reset(); |
| 492 | } |
| 493 | // actual settings |
| 494 | else |
| 495 | { |
| 496 | ioport_field *field = (ioport_field *)menu_event->itemref; |
| 497 | ioport_field::user_settings settings; |
| 498 | int changed = false; |
| 499 | |
| 500 | switch (menu_event->iptkey) |
| 501 | { |
| 502 | /* if selected, reset to default value */ |
| 503 | case IPT_UI_SELECT: |
| 504 | field->get_user_settings(settings); |
| 505 | settings.value = field->defvalue(); |
| 506 | field->set_user_settings(settings); |
| 507 | changed = true; |
| 508 | break; |
| 509 | |
| 510 | /* left goes to previous setting */ |
| 511 | case IPT_UI_LEFT: |
| 512 | field->select_previous_setting(); |
| 513 | changed = true; |
| 514 | break; |
| 515 | |
| 516 | /* right goes to next setting */ |
| 517 | case IPT_UI_RIGHT: |
| 518 | field->select_next_setting(); |
| 519 | changed = true; |
| 520 | break; |
| 521 | } |
| 522 | |
| 523 | /* if anything changed, rebuild the menu, trying to stay on the same field */ |
| 524 | if (changed) |
| 525 | reset(UI_MENU_RESET_REMEMBER_REF); |
| 526 | } |
| 527 | } |
| 528 | } |
| 529 | |
| 530 | |
| 531 | /*------------------------------------------------- |
| 532 | menu_settings_populate - populate one of the |
| 533 | switches menus |
| 534 | -------------------------------------------------*/ |
| 535 | |
| 536 | ui_menu_settings::ui_menu_settings(running_machine &machine, render_container *container, UINT32 _type) : ui_menu(machine, container) |
| 537 | { |
| 538 | type = _type; |
| 539 | } |
| 540 | |
| 541 | void ui_menu_settings::populate() |
| 542 | { |
| 543 | ioport_field *field; |
| 544 | ioport_port *port; |
| 545 | dip_descriptor **diplist_tailptr; |
| 546 | astring prev_owner; |
| 547 | bool first_entry = true; |
| 548 | |
| 549 | /* reset the dip switch tracking */ |
| 550 | dipcount = 0; |
| 551 | diplist = NULL; |
| 552 | diplist_tailptr = &diplist; |
| 553 | |
| 554 | /* loop over input ports and set up the current values */ |
| 555 | for (port = machine().ioport().first_port(); port != NULL; port = port->next()) |
| 556 | for (field = port->first_field(); field != NULL; field = field->next()) |
| 557 | if (field->type() == type && field->enabled()) |
| 558 | { |
| 559 | UINT32 flags = 0; |
| 560 | astring name; |
| 561 | |
| 562 | /* set the left/right flags appropriately */ |
| 563 | if (field->has_previous_setting()) |
| 564 | flags |= MENU_FLAG_LEFT_ARROW; |
| 565 | if (field->has_next_setting()) |
| 566 | flags |= MENU_FLAG_RIGHT_ARROW; |
| 567 | |
| 568 | /* add the menu item */ |
| 569 | if (strcmp(field->device().tag(), prev_owner.cstr()) != 0) |
| 570 | { |
| 571 | if (first_entry) |
| 572 | first_entry = false; |
| 573 | else |
| 574 | item_append(MENU_SEPARATOR_ITEM, NULL, 0, NULL); |
| 575 | name.printf("[root%s]", field->device().tag()); |
| 576 | item_append(name, NULL, 0, NULL); |
| 577 | prev_owner.cpy(field->device().tag()); |
| 578 | } |
| 579 | |
| 580 | name.cpy(field->name()); |
| 581 | |
| 582 | item_append(name, field->setting_name(), flags, (void *)field); |
| 583 | |
| 584 | /* for DIP switches, build up the model */ |
| 585 | if (type == IPT_DIPSWITCH && field->first_diplocation() != NULL) |
| 586 | { |
| 587 | const ioport_diplocation *diploc; |
| 588 | ioport_field::user_settings settings; |
| 589 | UINT32 accummask = field->mask(); |
| 590 | |
| 591 | /* get current settings */ |
| 592 | field->get_user_settings(settings); |
| 593 | |
| 594 | /* iterate over each bit in the field */ |
| 595 | for (diploc = field->first_diplocation(); diploc != NULL; diploc = diploc->next()) |
| 596 | { |
| 597 | UINT32 mask = accummask & ~(accummask - 1); |
| 598 | dip_descriptor *dip; |
| 599 | |
| 600 | /* find the matching switch name */ |
| 601 | for (dip = diplist; dip != NULL; dip = dip->next) |
| 602 | if (strcmp(dip->name, diploc->name()) == 0) |
| 603 | break; |
| 604 | |
| 605 | /* allocate new if none */ |
| 606 | if (dip == NULL) |
| 607 | { |
| 608 | dip = (dip_descriptor *)m_pool_alloc(sizeof(*dip)); |
| 609 | dip->next = NULL; |
| 610 | dip->name = diploc->name(); |
| 611 | dip->mask = dip->state = 0; |
| 612 | *diplist_tailptr = dip; |
| 613 | diplist_tailptr = &dip->next; |
| 614 | dipcount++; |
| 615 | } |
| 616 | |
| 617 | /* apply the bits */ |
| 618 | dip->mask |= 1 << (diploc->number() - 1); |
| 619 | if (((settings.value & mask) != 0 && !diploc->inverted()) || ((settings.value & mask) == 0 && diploc->inverted())) |
| 620 | dip->state |= 1 << (diploc->number() - 1); |
| 621 | |
| 622 | /* clear the relevant bit in the accumulated mask */ |
| 623 | accummask &= ~mask; |
| 624 | } |
| 625 | } |
| 626 | } |
| 627 | if (type == IPT_DIPSWITCH) |
| 628 | custombottom = dipcount ? dipcount * (DIP_SWITCH_HEIGHT + DIP_SWITCH_SPACING) + DIP_SWITCH_SPACING : 0; |
| 629 | |
| 630 | item_append(MENU_SEPARATOR_ITEM, NULL, 0, NULL); |
| 631 | item_append("Reset", NULL, 0, (void *)1); |
| 632 | } |
| 633 | |
| 634 | ui_menu_settings::~ui_menu_settings() |
| 635 | { |
| 636 | } |
| 637 | |
| 638 | /*------------------------------------------------- |
| 639 | menu_settings_custom_render - perform our special |
| 640 | rendering |
| 641 | -------------------------------------------------*/ |
| 642 | |
| 643 | void ui_menu_settings_dip_switches::custom_render(void *selectedref, float top, float bottom, float x1, float y1, float x2, float y2) |
| 644 | { |
| 645 | // catch if no diploc has to be drawn |
| 646 | if (bottom == 0) |
| 647 | return; |
| 648 | |
| 649 | // add borders |
| 650 | y1 = y2 + UI_BOX_TB_BORDER; |
| 651 | y2 = y1 + bottom; |
| 652 | |
| 653 | // draw extra menu area |
| 654 | machine().ui().draw_outlined_box(container, x1, y1, x2, y2, UI_BACKGROUND_COLOR); |
| 655 | y1 += (float)DIP_SWITCH_SPACING; |
| 656 | |
| 657 | // iterate over DIP switches |
| 658 | for (dip_descriptor *dip = diplist; dip != NULL; dip = dip->next) |
| 659 | { |
| 660 | const ioport_diplocation *diploc; |
| 661 | UINT32 selectedmask = 0; |
| 662 | |
| 663 | // determine the mask of selected bits |
| 664 | if ((FPTR)selectedref != 1) |
| 665 | { |
| 666 | ioport_field *field = (ioport_field *)selectedref; |
| 667 | |
| 668 | if (field != NULL && field->first_diplocation() != NULL) |
| 669 | for (diploc = field->first_diplocation(); diploc != NULL; diploc = diploc->next()) |
| 670 | if (strcmp(dip->name, diploc->name()) == 0) |
| 671 | selectedmask |= 1 << (diploc->number() - 1); |
| 672 | } |
| 673 | |
| 674 | // draw one switch |
| 675 | custom_render_one(x1, y1, x2, y1 + DIP_SWITCH_HEIGHT, dip, selectedmask); |
| 676 | y1 += (float)(DIP_SWITCH_SPACING + DIP_SWITCH_HEIGHT); |
| 677 | } |
| 678 | } |
| 679 | |
| 680 | |
| 681 | /*------------------------------------------------- |
| 682 | menu_settings_custom_render_one - draw a single |
| 683 | DIP switch |
| 684 | -------------------------------------------------*/ |
| 685 | |
| 686 | void ui_menu_settings_dip_switches::custom_render_one(float x1, float y1, float x2, float y2, const dip_descriptor *dip, UINT32 selectedmask) |
| 687 | { |
| 688 | float switch_field_width = SINGLE_TOGGLE_SWITCH_FIELD_WIDTH * container->manager().ui_aspect(); |
| 689 | float switch_width = SINGLE_TOGGLE_SWITCH_WIDTH * container->manager().ui_aspect(); |
| 690 | int numtoggles, toggle; |
| 691 | float switch_toggle_gap; |
| 692 | float y1_off, y1_on; |
| 693 | |
| 694 | /* determine the number of toggles in the DIP */ |
| 695 | numtoggles = 32 - count_leading_zeros(dip->mask); |
| 696 | |
| 697 | /* center based on the number of switches */ |
| 698 | x1 += (x2 - x1 - numtoggles * switch_field_width) / 2; |
| 699 | |
| 700 | /* draw the dip switch name */ |
| 701 | machine().ui().draw_text_full( container, |
| 702 | dip->name, |
| 703 | 0, |
| 704 | y1 + (DIP_SWITCH_HEIGHT - UI_TARGET_FONT_HEIGHT) / 2, |
| 705 | x1 - machine().ui().get_string_width(" "), |
| 706 | JUSTIFY_RIGHT, |
| 707 | WRAP_NEVER, |
| 708 | DRAW_NORMAL, |
| 709 | UI_TEXT_COLOR, |
| 710 | PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA), |
| 711 | NULL , |
| 712 | NULL); |
| 713 | |
| 714 | /* compute top and bottom for on and off positions */ |
| 715 | switch_toggle_gap = ((DIP_SWITCH_HEIGHT/2) - SINGLE_TOGGLE_SWITCH_HEIGHT)/2; |
| 716 | y1_off = y1 + UI_LINE_WIDTH + switch_toggle_gap; |
| 717 | y1_on = y1 + DIP_SWITCH_HEIGHT/2 + switch_toggle_gap; |
| 718 | |
| 719 | /* iterate over toggles */ |
| 720 | for (toggle = 0; toggle < numtoggles; toggle++) |
| 721 | { |
| 722 | float innerx1; |
| 723 | |
| 724 | /* first outline the switch */ |
| 725 | machine().ui().draw_outlined_box(container, x1, y1, x1 + switch_field_width, y2, UI_BACKGROUND_COLOR); |
| 726 | |
| 727 | /* compute x1/x2 for the inner filled in switch */ |
| 728 | innerx1 = x1 + (switch_field_width - switch_width) / 2; |
| 729 | |
| 730 | /* see if the switch is actually used */ |
| 731 | if (dip->mask & (1 << toggle)) |
| 732 | { |
| 733 | float innery1 = (dip->state & (1 << toggle)) ? y1_on : y1_off; |
| 734 | container->add_rect(innerx1, innery1, innerx1 + switch_width, innery1 + SINGLE_TOGGLE_SWITCH_HEIGHT, |
| 735 | (selectedmask & (1 << toggle)) ? UI_DIPSW_COLOR : UI_TEXT_COLOR, |
| 736 | PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA)); |
| 737 | } |
| 738 | else |
| 739 | { |
| 740 | container->add_rect(innerx1, y1_off, innerx1 + switch_width, y1_on + SINGLE_TOGGLE_SWITCH_HEIGHT, |
| 741 | UI_UNAVAILABLE_COLOR, |
| 742 | PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA)); |
| 743 | } |
| 744 | |
| 745 | /* advance to the next switch */ |
| 746 | x1 += switch_field_width; |
| 747 | } |
| 748 | } |
| 749 | |
| 750 | |
| 751 | /*------------------------------------------------- |
| 752 | menu_analog - handle the analog settings menu |
| 753 | -------------------------------------------------*/ |
| 754 | |
| 755 | void ui_menu_analog::handle() |
| 756 | { |
| 757 | /* process the menu */ |
| 758 | const ui_menu_event *menu_event = process(UI_MENU_PROCESS_LR_REPEAT); |
| 759 | |
| 760 | /* handle events */ |
| 761 | if (menu_event != NULL && menu_event->itemref != NULL) |
| 762 | { |
| 763 | analog_item_data *data = (analog_item_data *)menu_event->itemref; |
| 764 | int newval = data->cur; |
| 765 | |
| 766 | switch (menu_event->iptkey) |
| 767 | { |
| 768 | /* if selected, reset to default value */ |
| 769 | case IPT_UI_SELECT: |
| 770 | newval = data->defvalue; |
| 771 | break; |
| 772 | |
| 773 | /* left decrements */ |
| 774 | case IPT_UI_LEFT: |
| 775 | newval -= machine().input().code_pressed(KEYCODE_LSHIFT) ? 10 : 1; |
| 776 | break; |
| 777 | |
| 778 | /* right increments */ |
| 779 | case IPT_UI_RIGHT: |
| 780 | newval += machine().input().code_pressed(KEYCODE_LSHIFT) ? 10 : 1; |
| 781 | break; |
| 782 | } |
| 783 | |
| 784 | /* clamp to range */ |
| 785 | if (newval < data->min) |
| 786 | newval = data->min; |
| 787 | if (newval > data->max) |
| 788 | newval = data->max; |
| 789 | |
| 790 | /* if things changed, update */ |
| 791 | if (newval != data->cur) |
| 792 | { |
| 793 | ioport_field::user_settings settings; |
| 794 | |
| 795 | /* get the settings and set the new value */ |
| 796 | data->field->get_user_settings(settings); |
| 797 | switch (data->type) |
| 798 | { |
| 799 | case ANALOG_ITEM_KEYSPEED: settings.delta = newval; break; |
| 800 | case ANALOG_ITEM_CENTERSPEED: settings.centerdelta = newval; break; |
| 801 | case ANALOG_ITEM_REVERSE: settings.reverse = newval; break; |
| 802 | case ANALOG_ITEM_SENSITIVITY: settings.sensitivity = newval; break; |
| 803 | } |
| 804 | data->field->set_user_settings(settings); |
| 805 | |
| 806 | /* rebuild the menu */ |
| 807 | reset(UI_MENU_RESET_REMEMBER_POSITION); |
| 808 | } |
| 809 | } |
| 810 | } |
| 811 | |
| 812 | |
| 813 | /*------------------------------------------------- |
| 814 | menu_analog_populate - populate the analog |
| 815 | settings menu |
| 816 | -------------------------------------------------*/ |
| 817 | |
| 818 | ui_menu_analog::ui_menu_analog(running_machine &machine, render_container *container) : ui_menu(machine, container) |
| 819 | { |
| 820 | } |
| 821 | |
| 822 | void ui_menu_analog::populate() |
| 823 | { |
| 824 | ioport_field *field; |
| 825 | ioport_port *port; |
| 826 | astring text; |
| 827 | astring subtext; |
| 828 | astring prev_owner; |
| 829 | bool first_entry = true; |
| 830 | |
| 831 | /* loop over input ports and add the items */ |
| 832 | for (port = machine().ioport().first_port(); port != NULL; port = port->next()) |
| 833 | for (field = port->first_field(); field != NULL; field = field->next()) |
| 834 | if (field->is_analog() && field->enabled()) |
| 835 | { |
| 836 | ioport_field::user_settings settings; |
| 837 | int use_autocenter = false; |
| 838 | int type; |
| 839 | |
| 840 | /* based on the type, determine if we enable autocenter */ |
| 841 | switch (field->type()) |
| 842 | { |
| 843 | case IPT_POSITIONAL: |
| 844 | case IPT_POSITIONAL_V: |
| 845 | if (field->analog_wraps()) |
| 846 | break; |
| 847 | |
| 848 | case IPT_AD_STICK_X: |
| 849 | case IPT_AD_STICK_Y: |
| 850 | case IPT_AD_STICK_Z: |
| 851 | case IPT_PADDLE: |
| 852 | case IPT_PADDLE_V: |
| 853 | case IPT_PEDAL: |
| 854 | case IPT_PEDAL2: |
| 855 | case IPT_PEDAL3: |
| 856 | use_autocenter = true; |
| 857 | break; |
| 858 | |
| 859 | default: |
| 860 | break; |
| 861 | } |
| 862 | |
| 863 | /* get the user settings */ |
| 864 | field->get_user_settings(settings); |
| 865 | |
| 866 | /* iterate over types */ |
| 867 | for (type = 0; type < ANALOG_ITEM_COUNT; type++) |
| 868 | if (type != ANALOG_ITEM_CENTERSPEED || use_autocenter) |
| 869 | { |
| 870 | analog_item_data *data; |
| 871 | UINT32 flags = 0; |
| 872 | astring name; |
| 873 | if (strcmp(field->device().tag(), prev_owner.cstr()) != 0) |
| 874 | { |
| 875 | if (first_entry) |
| 876 | first_entry = false; |
| 877 | else |
| 878 | item_append(MENU_SEPARATOR_ITEM, NULL, 0, NULL); |
| 879 | name.printf("[root%s]", field->device().tag()); |
| 880 | item_append(name, NULL, 0, NULL); |
| 881 | prev_owner.cpy(field->device().tag()); |
| 882 | } |
| 883 | |
| 884 | name.cpy(field->name()); |
| 885 | |
| 886 | /* allocate a data item for tracking what this menu item refers to */ |
| 887 | data = (analog_item_data *)m_pool_alloc(sizeof(*data)); |
| 888 | data->field = field; |
| 889 | data->type = type; |
| 890 | |
| 891 | /* determine the properties of this item */ |
| 892 | switch (type) |
| 893 | { |
| 894 | default: |
| 895 | case ANALOG_ITEM_KEYSPEED: |
| 896 | text.printf("%s Digital Speed", name.cstr()); |
| 897 | subtext.printf("%d", settings.delta); |
| 898 | data->min = 0; |
| 899 | data->max = 255; |
| 900 | data->cur = settings.delta; |
| 901 | data->defvalue = field->delta(); |
| 902 | break; |
| 903 | |
| 904 | case ANALOG_ITEM_CENTERSPEED: |
| 905 | text.printf("%s Autocenter Speed", name.cstr()); |
| 906 | subtext.printf("%d", settings.centerdelta); |
| 907 | data->min = 0; |
| 908 | data->max = 255; |
| 909 | data->cur = settings.centerdelta; |
| 910 | data->defvalue = field->centerdelta(); |
| 911 | break; |
| 912 | |
| 913 | case ANALOG_ITEM_REVERSE: |
| 914 | text.printf("%s Reverse", name.cstr()); |
| 915 | subtext.cpy(settings.reverse ? "On" : "Off"); |
| 916 | data->min = 0; |
| 917 | data->max = 1; |
| 918 | data->cur = settings.reverse; |
| 919 | data->defvalue = field->analog_reverse(); |
| 920 | break; |
| 921 | |
| 922 | case ANALOG_ITEM_SENSITIVITY: |
| 923 | text.printf("%s Sensitivity", name.cstr()); |
| 924 | subtext.printf("%d", settings.sensitivity); |
| 925 | data->min = 1; |
| 926 | data->max = 255; |
| 927 | data->cur = settings.sensitivity; |
| 928 | data->defvalue = field->sensitivity(); |
| 929 | break; |
| 930 | } |
| 931 | |
| 932 | /* put on arrows */ |
| 933 | if (data->cur > data->min) |
| 934 | flags |= MENU_FLAG_LEFT_ARROW; |
| 935 | if (data->cur < data->max) |
| 936 | flags |= MENU_FLAG_RIGHT_ARROW; |
| 937 | |
| 938 | /* append a menu item */ |
| 939 | item_append(text, subtext, flags, data); |
| 940 | } |
| 941 | } |
| 942 | } |
| 943 | |
| 944 | ui_menu_analog::~ui_menu_analog() |
| 945 | { |
| 946 | } |
trunk/src/emu/ui/miscmenu.c
| r242908 | r242909 | |
| 24 | 24 | #include "ui/filemngr.h" |
| 25 | 25 | |
| 26 | 26 | |
| 27 | | /*************************************************************************** |
| 28 | | CONSTANTS |
| 29 | | ***************************************************************************/ |
| 30 | | |
| 31 | | #define MAX_PHYSICAL_DIPS 10 |
| 32 | | #define MAX_INPUT_PORTS 32 |
| 33 | | #define MAX_BITS_PER_PORT 32 |
| 34 | | |
| 35 | | /* DIP switch rendering parameters */ |
| 36 | | #define DIP_SWITCH_HEIGHT 0.05f |
| 37 | | #define DIP_SWITCH_SPACING 0.01 |
| 38 | | #define SINGLE_TOGGLE_SWITCH_FIELD_WIDTH 0.025f |
| 39 | | #define SINGLE_TOGGLE_SWITCH_WIDTH 0.020f |
| 40 | | /* make the switch 80% of the width space and 1/2 of the switch height */ |
| 41 | | #define PERCENTAGE_OF_HALF_FIELD_USED 0.80f |
| 42 | | #define SINGLE_TOGGLE_SWITCH_HEIGHT ((DIP_SWITCH_HEIGHT / 2) * PERCENTAGE_OF_HALF_FIELD_USED) |
| 43 | | |
| 44 | 27 | /*------------------------------------------------- |
| 45 | 28 | ui_slider_ui_handler - pushes the slider |
| 46 | 29 | menu on the stack and hands off to the |
| r242908 | r242909 | |
| 108 | 91 | |
| 109 | 92 | |
| 110 | 93 | /*------------------------------------------------- |
| 111 | | ui_slot_get_current_option - returns |
| 112 | | -------------------------------------------------*/ |
| 113 | | device_slot_option *ui_menu_slot_devices::slot_get_current_option(device_slot_interface *slot) |
| 114 | | { |
| 115 | | const char *current; |
| 116 | | if (slot->fixed()) |
| 117 | | { |
| 118 | | current = slot->default_option(); |
| 119 | | } |
| 120 | | else |
| 121 | | { |
| 122 | | astring temp; |
| 123 | | current = machine().options().main_value(temp, slot->device().tag() + 1); |
| 124 | | } |
| 125 | | |
| 126 | | return slot->option(current); |
| 127 | | } |
| 128 | | |
| 129 | | /*------------------------------------------------- |
| 130 | | ui_slot_get_current_index - returns |
| 131 | | -------------------------------------------------*/ |
| 132 | | int ui_menu_slot_devices::slot_get_current_index(device_slot_interface *slot) |
| 133 | | { |
| 134 | | const device_slot_option *current = slot_get_current_option(slot); |
| 135 | | |
| 136 | | if (current != NULL) |
| 137 | | { |
| 138 | | int val = 0; |
| 139 | | for (const device_slot_option *option = slot->first_option(); option != NULL; option = option->next()) |
| 140 | | { |
| 141 | | if (option == current) |
| 142 | | return val; |
| 143 | | |
| 144 | | if (option->selectable()) |
| 145 | | val++; |
| 146 | | } |
| 147 | | } |
| 148 | | |
| 149 | | return -1; |
| 150 | | } |
| 151 | | |
| 152 | | /*------------------------------------------------- |
| 153 | | ui_slot_get_length - returns |
| 154 | | -------------------------------------------------*/ |
| 155 | | int ui_menu_slot_devices::slot_get_length(device_slot_interface *slot) |
| 156 | | { |
| 157 | | int val = 0; |
| 158 | | for (const device_slot_option *option = slot->first_option(); option != NULL; option = option->next()) |
| 159 | | if (option->selectable()) |
| 160 | | val++; |
| 161 | | |
| 162 | | return val; |
| 163 | | } |
| 164 | | |
| 165 | | /*------------------------------------------------- |
| 166 | | ui_slot_get_next - returns |
| 167 | | -------------------------------------------------*/ |
| 168 | | const char *ui_menu_slot_devices::slot_get_next(device_slot_interface *slot) |
| 169 | | { |
| 170 | | int idx = slot_get_current_index(slot); |
| 171 | | if (idx < 0) |
| 172 | | idx = 0; |
| 173 | | else |
| 174 | | idx++; |
| 175 | | |
| 176 | | if (idx >= slot_get_length(slot)) |
| 177 | | return ""; |
| 178 | | |
| 179 | | return slot_get_option(slot, idx); |
| 180 | | } |
| 181 | | |
| 182 | | /*------------------------------------------------- |
| 183 | | ui_slot_get_prev - returns |
| 184 | | -------------------------------------------------*/ |
| 185 | | const char *ui_menu_slot_devices::slot_get_prev(device_slot_interface *slot) |
| 186 | | { |
| 187 | | int idx = slot_get_current_index(slot); |
| 188 | | if (idx < 0) |
| 189 | | idx = slot_get_length(slot) - 1; |
| 190 | | else |
| 191 | | idx--; |
| 192 | | |
| 193 | | if (idx < 0) |
| 194 | | return ""; |
| 195 | | |
| 196 | | return slot_get_option(slot, idx); |
| 197 | | } |
| 198 | | |
| 199 | | /*------------------------------------------------- |
| 200 | | ui_slot_get_option - returns |
| 201 | | -------------------------------------------------*/ |
| 202 | | const char *ui_menu_slot_devices::slot_get_option(device_slot_interface *slot, int index) |
| 203 | | { |
| 204 | | if (index >= 0) |
| 205 | | { |
| 206 | | int val = 0; |
| 207 | | for (const device_slot_option *option = slot->first_option(); option != NULL; option = option->next()) |
| 208 | | { |
| 209 | | if (val == index) |
| 210 | | return option->name(); |
| 211 | | |
| 212 | | if (option->selectable()) |
| 213 | | val++; |
| 214 | | } |
| 215 | | } |
| 216 | | |
| 217 | | return ""; |
| 218 | | } |
| 219 | | |
| 220 | | |
| 221 | | /*------------------------------------------------- |
| 222 | | ui_set_use_natural_keyboard - specifies |
| 223 | | whether the natural keyboard is active |
| 224 | | -------------------------------------------------*/ |
| 225 | | |
| 226 | | void ui_menu_slot_devices::set_slot_device(device_slot_interface *slot, const char *val) |
| 227 | | { |
| 228 | | astring error; |
| 229 | | machine().options().set_value(slot->device().tag()+1, val, OPTION_PRIORITY_CMDLINE, error); |
| 230 | | assert(!error); |
| 231 | | } |
| 232 | | |
| 233 | | /*------------------------------------------------- |
| 234 | | menu_slot_devices_populate - populates the main |
| 235 | | slot device menu |
| 236 | | -------------------------------------------------*/ |
| 237 | | |
| 238 | | ui_menu_slot_devices::ui_menu_slot_devices(running_machine &machine, render_container *container) : ui_menu(machine, container) |
| 239 | | { |
| 240 | | } |
| 241 | | |
| 242 | | void ui_menu_slot_devices::populate() |
| 243 | | { |
| 244 | | /* cycle through all devices for this system */ |
| 245 | | slot_interface_iterator iter(machine().root_device()); |
| 246 | | for (device_slot_interface *slot = iter.first(); slot != NULL; slot = iter.next()) |
| 247 | | { |
| 248 | | /* record the menu item */ |
| 249 | | const device_slot_option *option = slot_get_current_option(slot); |
| 250 | | astring opt_name; |
| 251 | | if (option == NULL) |
| 252 | | opt_name.cpy("------"); |
| 253 | | else |
| 254 | | { |
| 255 | | opt_name.cpy(option->name()); |
| 256 | | if (slot->fixed() || slot_get_length(slot) == 0) |
| 257 | | opt_name.cat(" [internal]"); |
| 258 | | } |
| 259 | | |
| 260 | | item_append(slot->device().tag() + 1, opt_name, (slot->fixed() || slot_get_length(slot) == 0) ? 0 : (MENU_FLAG_LEFT_ARROW | MENU_FLAG_RIGHT_ARROW), (void *)slot); |
| 261 | | } |
| 262 | | item_append(MENU_SEPARATOR_ITEM, NULL, 0, NULL); |
| 263 | | item_append("Reset", NULL, 0, (void *)1); |
| 264 | | } |
| 265 | | |
| 266 | | ui_menu_slot_devices::~ui_menu_slot_devices() |
| 267 | | { |
| 268 | | } |
| 269 | | |
| 270 | | /*------------------------------------------------- |
| 271 | | ui_menu_slot_devices - menu that |
| 272 | | -------------------------------------------------*/ |
| 273 | | |
| 274 | | void ui_menu_slot_devices::handle() |
| 275 | | { |
| 276 | | /* process the menu */ |
| 277 | | const ui_menu_event *menu_event = process(0); |
| 278 | | |
| 279 | | if (menu_event != NULL && menu_event->itemref != NULL) |
| 280 | | { |
| 281 | | if ((FPTR)menu_event->itemref == 1 && menu_event->iptkey == IPT_UI_SELECT) |
| 282 | | machine().schedule_hard_reset(); |
| 283 | | else if (menu_event->iptkey == IPT_UI_LEFT || menu_event->iptkey == IPT_UI_RIGHT) |
| 284 | | { |
| 285 | | device_slot_interface *slot = (device_slot_interface *)menu_event->itemref; |
| 286 | | const char *val = (menu_event->iptkey == IPT_UI_LEFT) ? slot_get_prev(slot) : slot_get_next(slot); |
| 287 | | set_slot_device(slot, val); |
| 288 | | reset(UI_MENU_RESET_REMEMBER_REF); |
| 289 | | } |
| 290 | | } |
| 291 | | } |
| 292 | | |
| 293 | | /*------------------------------------------------- |
| 294 | 94 | ui_menu_bios_selection - populates the main |
| 295 | 95 | bios selection menu |
| 296 | 96 | -------------------------------------------------*/ |
| r242908 | r242909 | |
| 426 | 226 | } |
| 427 | 227 | } |
| 428 | 228 | |
| 429 | | /*------------------------------------------------- |
| 430 | | menu_input_groups_populate - populate the |
| 431 | | input groups menu |
| 432 | | -------------------------------------------------*/ |
| 433 | 229 | |
| 434 | | ui_menu_input_groups::ui_menu_input_groups(running_machine &machine, render_container *container) : ui_menu(machine, container) |
| 435 | | { |
| 436 | | } |
| 437 | | |
| 438 | | void ui_menu_input_groups::populate() |
| 439 | | { |
| 440 | | int player; |
| 441 | | |
| 442 | | /* build up the menu */ |
| 443 | | item_append("User Interface", NULL, 0, (void *)(IPG_UI + 1)); |
| 444 | | for (player = 0; player < MAX_PLAYERS; player++) |
| 445 | | { |
| 446 | | char buffer[40]; |
| 447 | | sprintf(buffer, "Player %d Controls", player + 1); |
| 448 | | item_append(buffer, NULL, 0, (void *)(FPTR)(IPG_PLAYER1 + player + 1)); |
| 449 | | } |
| 450 | | item_append("Other Controls", NULL, 0, (void *)(FPTR)(IPG_OTHER + 1)); |
| 451 | | } |
| 452 | | |
| 453 | | ui_menu_input_groups::~ui_menu_input_groups() |
| 454 | | { |
| 455 | | } |
| 456 | | |
| 457 | 230 | /*------------------------------------------------- |
| 458 | | menu_input_groups - handle the input groups |
| 459 | | menu |
| 460 | | -------------------------------------------------*/ |
| 461 | | |
| 462 | | void ui_menu_input_groups::handle() |
| 463 | | { |
| 464 | | /* process the menu */ |
| 465 | | const ui_menu_event *menu_event = process(0); |
| 466 | | if (menu_event != NULL && menu_event->iptkey == IPT_UI_SELECT) |
| 467 | | ui_menu::stack_push(auto_alloc_clear(machine(), ui_menu_input_general(machine(), container, int((long long)(menu_event->itemref)-1)))); |
| 468 | | } |
| 469 | | |
| 470 | | |
| 471 | | |
| 472 | | /*------------------------------------------------- |
| 473 | | menu_input_general - handle the general |
| 474 | | input menu |
| 475 | | -------------------------------------------------*/ |
| 476 | | |
| 477 | | ui_menu_input_general::ui_menu_input_general(running_machine &machine, render_container *container, int _group) : ui_menu_input(machine, container) |
| 478 | | { |
| 479 | | group = _group; |
| 480 | | } |
| 481 | | |
| 482 | | void ui_menu_input_general::populate() |
| 483 | | { |
| 484 | | input_item_data *itemlist = NULL; |
| 485 | | int suborder[SEQ_TYPE_TOTAL]; |
| 486 | | astring tempstring; |
| 487 | | int sortorder = 1; |
| 488 | | |
| 489 | | /* create a mini lookup table for sort order based on sequence type */ |
| 490 | | suborder[SEQ_TYPE_STANDARD] = 0; |
| 491 | | suborder[SEQ_TYPE_DECREMENT] = 1; |
| 492 | | suborder[SEQ_TYPE_INCREMENT] = 2; |
| 493 | | |
| 494 | | /* iterate over the input ports and add menu items */ |
| 495 | | for (input_type_entry *entry = machine().ioport().first_type(); entry != NULL; entry = entry->next()) |
| 496 | | |
| 497 | | /* add if we match the group and we have a valid name */ |
| 498 | | if (entry->group() == group && entry->name() != NULL && entry->name()[0] != 0) |
| 499 | | { |
| 500 | | input_seq_type seqtype; |
| 501 | | |
| 502 | | /* loop over all sequence types */ |
| 503 | | sortorder++; |
| 504 | | for (seqtype = SEQ_TYPE_STANDARD; seqtype < SEQ_TYPE_TOTAL; seqtype++) |
| 505 | | { |
| 506 | | /* build an entry for the standard sequence */ |
| 507 | | input_item_data *item = (input_item_data *)m_pool_alloc(sizeof(*item)); |
| 508 | | memset(item, 0, sizeof(*item)); |
| 509 | | item->ref = entry; |
| 510 | | if(pollingitem && pollingref == entry && pollingseq == seqtype) |
| 511 | | pollingitem = item; |
| 512 | | item->seqtype = seqtype; |
| 513 | | item->seq = machine().ioport().type_seq(entry->type(), entry->player(), seqtype); |
| 514 | | item->defseq = &entry->defseq(seqtype); |
| 515 | | item->sortorder = sortorder * 4 + suborder[seqtype]; |
| 516 | | item->type = ioport_manager::type_is_analog(entry->type()) ? (INPUT_TYPE_ANALOG + seqtype) : INPUT_TYPE_DIGITAL; |
| 517 | | item->name = entry->name(); |
| 518 | | item->owner_name = NULL; |
| 519 | | item->next = itemlist; |
| 520 | | itemlist = item; |
| 521 | | |
| 522 | | /* stop after one, unless we're analog */ |
| 523 | | if (item->type == INPUT_TYPE_DIGITAL) |
| 524 | | break; |
| 525 | | } |
| 526 | | } |
| 527 | | |
| 528 | | /* sort and populate the menu in a standard fashion */ |
| 529 | | populate_and_sort(itemlist); |
| 530 | | } |
| 531 | | |
| 532 | | ui_menu_input_general::~ui_menu_input_general() |
| 533 | | { |
| 534 | | } |
| 535 | | |
| 536 | | /*------------------------------------------------- |
| 537 | | menu_input_specific - handle the game-specific |
| 538 | | input menu |
| 539 | | -------------------------------------------------*/ |
| 540 | | |
| 541 | | ui_menu_input_specific::ui_menu_input_specific(running_machine &machine, render_container *container) : ui_menu_input(machine, container) |
| 542 | | { |
| 543 | | } |
| 544 | | |
| 545 | | void ui_menu_input_specific::populate() |
| 546 | | { |
| 547 | | input_item_data *itemlist = NULL; |
| 548 | | ioport_field *field; |
| 549 | | ioport_port *port; |
| 550 | | int suborder[SEQ_TYPE_TOTAL]; |
| 551 | | astring tempstring; |
| 552 | | |
| 553 | | /* create a mini lookup table for sort order based on sequence type */ |
| 554 | | suborder[SEQ_TYPE_STANDARD] = 0; |
| 555 | | suborder[SEQ_TYPE_DECREMENT] = 1; |
| 556 | | suborder[SEQ_TYPE_INCREMENT] = 2; |
| 557 | | |
| 558 | | /* iterate over the input ports and add menu items */ |
| 559 | | for (port = machine().ioport().first_port(); port != NULL; port = port->next()) |
| 560 | | for (field = port->first_field(); field != NULL; field = field->next()) |
| 561 | | { |
| 562 | | const char *name = field->name(); |
| 563 | | |
| 564 | | /* add if we match the group and we have a valid name */ |
| 565 | | if (name != NULL && field->enabled() && |
| 566 | | ((field->type() == IPT_OTHER && field->name() != NULL) || machine().ioport().type_group(field->type(), field->player()) != IPG_INVALID)) |
| 567 | | { |
| 568 | | input_seq_type seqtype; |
| 569 | | UINT32 sortorder; |
| 570 | | |
| 571 | | /* determine the sorting order */ |
| 572 | | if (field->type() >= IPT_START1 && field->type() < IPT_ANALOG_LAST) |
| 573 | | { |
| 574 | | sortorder = (field->type() << 2) | (field->player() << 12); |
| 575 | | if (strcmp(field->device().tag(), ":")) |
| 576 | | sortorder |= 0x10000; |
| 577 | | } |
| 578 | | else |
| 579 | | sortorder = field->type() | 0xf000; |
| 580 | | |
| 581 | | /* loop over all sequence types */ |
| 582 | | for (seqtype = SEQ_TYPE_STANDARD; seqtype < SEQ_TYPE_TOTAL; seqtype++) |
| 583 | | { |
| 584 | | /* build an entry for the standard sequence */ |
| 585 | | input_item_data *item = (input_item_data *)m_pool_alloc(sizeof(*item)); |
| 586 | | memset(item, 0, sizeof(*item)); |
| 587 | | item->ref = field; |
| 588 | | item->seqtype = seqtype; |
| 589 | | if(pollingitem && pollingref == field && pollingseq == seqtype) |
| 590 | | pollingitem = item; |
| 591 | | item->seq = field->seq(seqtype); |
| 592 | | item->defseq = &field->defseq(seqtype); |
| 593 | | item->sortorder = sortorder + suborder[seqtype]; |
| 594 | | item->type = field->is_analog() ? (INPUT_TYPE_ANALOG + seqtype) : INPUT_TYPE_DIGITAL; |
| 595 | | item->name = name; |
| 596 | | item->owner_name = field->device().tag(); |
| 597 | | item->next = itemlist; |
| 598 | | itemlist = item; |
| 599 | | |
| 600 | | /* stop after one, unless we're analog */ |
| 601 | | if (item->type == INPUT_TYPE_DIGITAL) |
| 602 | | break; |
| 603 | | } |
| 604 | | } |
| 605 | | } |
| 606 | | |
| 607 | | /* sort and populate the menu in a standard fashion */ |
| 608 | | populate_and_sort(itemlist); |
| 609 | | } |
| 610 | | |
| 611 | | ui_menu_input_specific::~ui_menu_input_specific() |
| 612 | | { |
| 613 | | } |
| 614 | | |
| 615 | | /*------------------------------------------------- |
| 616 | | menu_input - display a menu for inputs |
| 617 | | -------------------------------------------------*/ |
| 618 | | ui_menu_input::ui_menu_input(running_machine &machine, render_container *container) : ui_menu(machine, container) |
| 619 | | { |
| 620 | | pollingitem = 0; |
| 621 | | pollingref = 0; |
| 622 | | pollingseq = SEQ_TYPE_STANDARD; |
| 623 | | } |
| 624 | | |
| 625 | | ui_menu_input::~ui_menu_input() |
| 626 | | { |
| 627 | | } |
| 628 | | |
| 629 | | /*------------------------------------------------- |
| 630 | | toggle_none_default - toggle between "NONE" |
| 631 | | and the default item |
| 632 | | -------------------------------------------------*/ |
| 633 | | |
| 634 | | void ui_menu_input::toggle_none_default(input_seq &selected_seq, input_seq &original_seq, const input_seq &selected_defseq) |
| 635 | | { |
| 636 | | /* if we used to be "none", toggle to the default value */ |
| 637 | | if (original_seq.length() == 0) |
| 638 | | selected_seq = selected_defseq; |
| 639 | | |
| 640 | | /* otherwise, toggle to "none" */ |
| 641 | | else |
| 642 | | selected_seq.reset(); |
| 643 | | } |
| 644 | | |
| 645 | | void ui_menu_input::handle() |
| 646 | | { |
| 647 | | input_item_data *seqchangeditem = NULL; |
| 648 | | const ui_menu_event *menu_event; |
| 649 | | int invalidate = false; |
| 650 | | |
| 651 | | /* process the menu */ |
| 652 | | menu_event = process((pollingitem != NULL) ? UI_MENU_PROCESS_NOKEYS : 0); |
| 653 | | |
| 654 | | /* if we are polling, handle as a special case */ |
| 655 | | if (pollingitem != NULL) |
| 656 | | { |
| 657 | | input_item_data *item = pollingitem; |
| 658 | | input_seq newseq; |
| 659 | | |
| 660 | | /* if UI_CANCEL is pressed, abort */ |
| 661 | | if (ui_input_pressed(machine(), IPT_UI_CANCEL)) |
| 662 | | { |
| 663 | | pollingitem = NULL; |
| 664 | | record_next = false; |
| 665 | | toggle_none_default(item->seq, starting_seq, *item->defseq); |
| 666 | | seqchangeditem = item; |
| 667 | | } |
| 668 | | |
| 669 | | /* poll again; if finished, update the sequence */ |
| 670 | | if (machine().input().seq_poll()) |
| 671 | | { |
| 672 | | pollingitem = NULL; |
| 673 | | record_next = true; |
| 674 | | item->seq = machine().input().seq_poll_final(); |
| 675 | | seqchangeditem = item; |
| 676 | | } |
| 677 | | } |
| 678 | | |
| 679 | | /* otherwise, handle the events */ |
| 680 | | else if (menu_event != NULL && menu_event->itemref != NULL) |
| 681 | | { |
| 682 | | input_item_data *item = (input_item_data *)menu_event->itemref; |
| 683 | | switch (menu_event->iptkey) |
| 684 | | { |
| 685 | | /* an item was selected: begin polling */ |
| 686 | | case IPT_UI_SELECT: |
| 687 | | pollingitem = item; |
| 688 | | last_sortorder = item->sortorder; |
| 689 | | starting_seq = item->seq; |
| 690 | | machine().input().seq_poll_start((item->type == INPUT_TYPE_ANALOG) ? ITEM_CLASS_ABSOLUTE : ITEM_CLASS_SWITCH, record_next ? &item->seq : NULL); |
| 691 | | invalidate = true; |
| 692 | | break; |
| 693 | | |
| 694 | | /* if the clear key was pressed, reset the selected item */ |
| 695 | | case IPT_UI_CLEAR: |
| 696 | | toggle_none_default(item->seq, item->seq, *item->defseq); |
| 697 | | record_next = false; |
| 698 | | seqchangeditem = item; |
| 699 | | break; |
| 700 | | } |
| 701 | | |
| 702 | | /* if the selection changed, reset the "record next" flag */ |
| 703 | | if (item->sortorder != last_sortorder) |
| 704 | | record_next = false; |
| 705 | | last_sortorder = item->sortorder; |
| 706 | | } |
| 707 | | |
| 708 | | /* if the sequence changed, update it */ |
| 709 | | if (seqchangeditem != NULL) |
| 710 | | { |
| 711 | | update_input(seqchangeditem); |
| 712 | | |
| 713 | | /* invalidate the menu to force an update */ |
| 714 | | invalidate = true; |
| 715 | | } |
| 716 | | |
| 717 | | /* if the menu is invalidated, clear it now */ |
| 718 | | if (invalidate) |
| 719 | | { |
| 720 | | pollingref = NULL; |
| 721 | | if (pollingitem != NULL) |
| 722 | | { |
| 723 | | pollingref = pollingitem->ref; |
| 724 | | pollingseq = pollingitem->seqtype; |
| 725 | | } |
| 726 | | reset(UI_MENU_RESET_REMEMBER_POSITION); |
| 727 | | } |
| 728 | | } |
| 729 | | |
| 730 | | void ui_menu_input_general::update_input(struct input_item_data *seqchangeditem) |
| 731 | | { |
| 732 | | const input_type_entry *entry = (const input_type_entry *)seqchangeditem->ref; |
| 733 | | machine().ioport().set_type_seq(entry->type(), entry->player(), seqchangeditem->seqtype, seqchangeditem->seq); |
| 734 | | } |
| 735 | | |
| 736 | | void ui_menu_input_specific::update_input(struct input_item_data *seqchangeditem) |
| 737 | | { |
| 738 | | ioport_field::user_settings settings; |
| 739 | | |
| 740 | | ((ioport_field *)seqchangeditem->ref)->get_user_settings(settings); |
| 741 | | settings.seq[seqchangeditem->seqtype] = seqchangeditem->seq; |
| 742 | | ((ioport_field *)seqchangeditem->ref)->set_user_settings(settings); |
| 743 | | } |
| 744 | | |
| 745 | | |
| 746 | | /*------------------------------------------------- |
| 747 | | menu_input_compare_items - compare two |
| 748 | | items for quicksort |
| 749 | | -------------------------------------------------*/ |
| 750 | | |
| 751 | | int ui_menu_input::compare_items(const void *i1, const void *i2) |
| 752 | | { |
| 753 | | const input_item_data * const *data1 = (const input_item_data * const *)i1; |
| 754 | | const input_item_data * const *data2 = (const input_item_data * const *)i2; |
| 755 | | if ((*data1)->sortorder < (*data2)->sortorder) |
| 756 | | return -1; |
| 757 | | if ((*data1)->sortorder > (*data2)->sortorder) |
| 758 | | return 1; |
| 759 | | return 0; |
| 760 | | } |
| 761 | | |
| 762 | | |
| 763 | | /*------------------------------------------------- |
| 764 | | menu_input_populate_and_sort - take a list |
| 765 | | of input_item_data objects and build up the |
| 766 | | menu from them |
| 767 | | -------------------------------------------------*/ |
| 768 | | |
| 769 | | void ui_menu_input::populate_and_sort(input_item_data *itemlist) |
| 770 | | { |
| 771 | | const char *nameformat[INPUT_TYPE_TOTAL] = { 0 }; |
| 772 | | input_item_data **itemarray, *item; |
| 773 | | int numitems = 0, curitem; |
| 774 | | astring text; |
| 775 | | astring subtext; |
| 776 | | astring prev_owner; |
| 777 | | bool first_entry = true; |
| 778 | | |
| 779 | | /* create a mini lookup table for name format based on type */ |
| 780 | | nameformat[INPUT_TYPE_DIGITAL] = "%s"; |
| 781 | | nameformat[INPUT_TYPE_ANALOG] = "%s Analog"; |
| 782 | | nameformat[INPUT_TYPE_ANALOG_INC] = "%s Analog Inc"; |
| 783 | | nameformat[INPUT_TYPE_ANALOG_DEC] = "%s Analog Dec"; |
| 784 | | |
| 785 | | /* first count the number of items */ |
| 786 | | for (item = itemlist; item != NULL; item = item->next) |
| 787 | | numitems++; |
| 788 | | |
| 789 | | /* now allocate an array of items and fill it up */ |
| 790 | | itemarray = (input_item_data **)m_pool_alloc(sizeof(*itemarray) * numitems); |
| 791 | | for (item = itemlist, curitem = 0; item != NULL; item = item->next) |
| 792 | | itemarray[curitem++] = item; |
| 793 | | |
| 794 | | /* sort it */ |
| 795 | | qsort(itemarray, numitems, sizeof(*itemarray), compare_items); |
| 796 | | |
| 797 | | /* build the menu */ |
| 798 | | for (curitem = 0; curitem < numitems; curitem++) |
| 799 | | { |
| 800 | | UINT32 flags = 0; |
| 801 | | |
| 802 | | /* generate the name of the item itself, based off the base name and the type */ |
| 803 | | item = itemarray[curitem]; |
| 804 | | assert(nameformat[item->type] != NULL); |
| 805 | | |
| 806 | | if (strcmp(item->owner_name, prev_owner.cstr()) != 0) |
| 807 | | { |
| 808 | | if (first_entry) |
| 809 | | first_entry = false; |
| 810 | | else |
| 811 | | item_append(MENU_SEPARATOR_ITEM, NULL, 0, NULL); |
| 812 | | text.printf("[root%s]", item->owner_name); |
| 813 | | item_append(text, NULL, 0, NULL); |
| 814 | | prev_owner.cpy(item->owner_name); |
| 815 | | } |
| 816 | | |
| 817 | | text.printf(nameformat[item->type], item->name); |
| 818 | | |
| 819 | | /* if we're polling this item, use some spaces with left/right arrows */ |
| 820 | | if (pollingref == item->ref) |
| 821 | | { |
| 822 | | subtext.cpy(" "); |
| 823 | | flags |= MENU_FLAG_LEFT_ARROW | MENU_FLAG_RIGHT_ARROW; |
| 824 | | } |
| 825 | | |
| 826 | | /* otherwise, generate the sequence name and invert it if different from the default */ |
| 827 | | else |
| 828 | | { |
| 829 | | machine().input().seq_name(subtext, item->seq); |
| 830 | | flags |= (item->seq != *item->defseq) ? MENU_FLAG_INVERT : 0; |
| 831 | | } |
| 832 | | |
| 833 | | /* add the item */ |
| 834 | | item_append(text, subtext, flags, item); |
| 835 | | } |
| 836 | | } |
| 837 | | |
| 838 | | |
| 839 | | /*------------------------------------------------- |
| 840 | | menu_settings_dip_switches - handle the DIP |
| 841 | | switches menu |
| 842 | | -------------------------------------------------*/ |
| 843 | | |
| 844 | | ui_menu_settings_dip_switches::ui_menu_settings_dip_switches(running_machine &machine, render_container *container) : ui_menu_settings(machine, container, IPT_DIPSWITCH) |
| 845 | | { |
| 846 | | } |
| 847 | | |
| 848 | | ui_menu_settings_dip_switches::~ui_menu_settings_dip_switches() |
| 849 | | { |
| 850 | | } |
| 851 | | |
| 852 | | /*------------------------------------------------- |
| 853 | | menu_settings_driver_config - handle the |
| 854 | | driver config menu |
| 855 | | -------------------------------------------------*/ |
| 856 | | |
| 857 | | ui_menu_settings_driver_config::ui_menu_settings_driver_config(running_machine &machine, render_container *container) : ui_menu_settings(machine, container, IPT_CONFIG) |
| 858 | | { |
| 859 | | } |
| 860 | | |
| 861 | | ui_menu_settings_driver_config::~ui_menu_settings_driver_config() |
| 862 | | { |
| 863 | | } |
| 864 | | |
| 865 | | /*------------------------------------------------- |
| 866 | | menu_settings_common - handle one of the |
| 867 | | switches menus |
| 868 | | -------------------------------------------------*/ |
| 869 | | |
| 870 | | void ui_menu_settings::handle() |
| 871 | | { |
| 872 | | // process the menu |
| 873 | | const ui_menu_event *menu_event = process(0); |
| 874 | | |
| 875 | | // handle events |
| 876 | | if (menu_event != NULL && menu_event->itemref != NULL) |
| 877 | | { |
| 878 | | // reset |
| 879 | | if ((FPTR)menu_event->itemref == 1) |
| 880 | | { |
| 881 | | if (menu_event->iptkey == IPT_UI_SELECT) |
| 882 | | machine().schedule_hard_reset(); |
| 883 | | } |
| 884 | | // actual settings |
| 885 | | else |
| 886 | | { |
| 887 | | ioport_field *field = (ioport_field *)menu_event->itemref; |
| 888 | | ioport_field::user_settings settings; |
| 889 | | int changed = false; |
| 890 | | |
| 891 | | switch (menu_event->iptkey) |
| 892 | | { |
| 893 | | /* if selected, reset to default value */ |
| 894 | | case IPT_UI_SELECT: |
| 895 | | field->get_user_settings(settings); |
| 896 | | settings.value = field->defvalue(); |
| 897 | | field->set_user_settings(settings); |
| 898 | | changed = true; |
| 899 | | break; |
| 900 | | |
| 901 | | /* left goes to previous setting */ |
| 902 | | case IPT_UI_LEFT: |
| 903 | | field->select_previous_setting(); |
| 904 | | changed = true; |
| 905 | | break; |
| 906 | | |
| 907 | | /* right goes to next setting */ |
| 908 | | case IPT_UI_RIGHT: |
| 909 | | field->select_next_setting(); |
| 910 | | changed = true; |
| 911 | | break; |
| 912 | | } |
| 913 | | |
| 914 | | /* if anything changed, rebuild the menu, trying to stay on the same field */ |
| 915 | | if (changed) |
| 916 | | reset(UI_MENU_RESET_REMEMBER_REF); |
| 917 | | } |
| 918 | | } |
| 919 | | } |
| 920 | | |
| 921 | | |
| 922 | | /*------------------------------------------------- |
| 923 | | menu_settings_populate - populate one of the |
| 924 | | switches menus |
| 925 | | -------------------------------------------------*/ |
| 926 | | |
| 927 | | ui_menu_settings::ui_menu_settings(running_machine &machine, render_container *container, UINT32 _type) : ui_menu(machine, container) |
| 928 | | { |
| 929 | | type = _type; |
| 930 | | } |
| 931 | | |
| 932 | | void ui_menu_settings::populate() |
| 933 | | { |
| 934 | | ioport_field *field; |
| 935 | | ioport_port *port; |
| 936 | | dip_descriptor **diplist_tailptr; |
| 937 | | astring prev_owner; |
| 938 | | bool first_entry = true; |
| 939 | | |
| 940 | | /* reset the dip switch tracking */ |
| 941 | | dipcount = 0; |
| 942 | | diplist = NULL; |
| 943 | | diplist_tailptr = &diplist; |
| 944 | | |
| 945 | | /* loop over input ports and set up the current values */ |
| 946 | | for (port = machine().ioport().first_port(); port != NULL; port = port->next()) |
| 947 | | for (field = port->first_field(); field != NULL; field = field->next()) |
| 948 | | if (field->type() == type && field->enabled()) |
| 949 | | { |
| 950 | | UINT32 flags = 0; |
| 951 | | astring name; |
| 952 | | |
| 953 | | /* set the left/right flags appropriately */ |
| 954 | | if (field->has_previous_setting()) |
| 955 | | flags |= MENU_FLAG_LEFT_ARROW; |
| 956 | | if (field->has_next_setting()) |
| 957 | | flags |= MENU_FLAG_RIGHT_ARROW; |
| 958 | | |
| 959 | | /* add the menu item */ |
| 960 | | if (strcmp(field->device().tag(), prev_owner.cstr()) != 0) |
| 961 | | { |
| 962 | | if (first_entry) |
| 963 | | first_entry = false; |
| 964 | | else |
| 965 | | item_append(MENU_SEPARATOR_ITEM, NULL, 0, NULL); |
| 966 | | name.printf("[root%s]", field->device().tag()); |
| 967 | | item_append(name, NULL, 0, NULL); |
| 968 | | prev_owner.cpy(field->device().tag()); |
| 969 | | } |
| 970 | | |
| 971 | | name.cpy(field->name()); |
| 972 | | |
| 973 | | item_append(name, field->setting_name(), flags, (void *)field); |
| 974 | | |
| 975 | | /* for DIP switches, build up the model */ |
| 976 | | if (type == IPT_DIPSWITCH && field->first_diplocation() != NULL) |
| 977 | | { |
| 978 | | const ioport_diplocation *diploc; |
| 979 | | ioport_field::user_settings settings; |
| 980 | | UINT32 accummask = field->mask(); |
| 981 | | |
| 982 | | /* get current settings */ |
| 983 | | field->get_user_settings(settings); |
| 984 | | |
| 985 | | /* iterate over each bit in the field */ |
| 986 | | for (diploc = field->first_diplocation(); diploc != NULL; diploc = diploc->next()) |
| 987 | | { |
| 988 | | UINT32 mask = accummask & ~(accummask - 1); |
| 989 | | dip_descriptor *dip; |
| 990 | | |
| 991 | | /* find the matching switch name */ |
| 992 | | for (dip = diplist; dip != NULL; dip = dip->next) |
| 993 | | if (strcmp(dip->name, diploc->name()) == 0) |
| 994 | | break; |
| 995 | | |
| 996 | | /* allocate new if none */ |
| 997 | | if (dip == NULL) |
| 998 | | { |
| 999 | | dip = (dip_descriptor *)m_pool_alloc(sizeof(*dip)); |
| 1000 | | dip->next = NULL; |
| 1001 | | dip->name = diploc->name(); |
| 1002 | | dip->mask = dip->state = 0; |
| 1003 | | *diplist_tailptr = dip; |
| 1004 | | diplist_tailptr = &dip->next; |
| 1005 | | dipcount++; |
| 1006 | | } |
| 1007 | | |
| 1008 | | /* apply the bits */ |
| 1009 | | dip->mask |= 1 << (diploc->number() - 1); |
| 1010 | | if (((settings.value & mask) != 0 && !diploc->inverted()) || ((settings.value & mask) == 0 && diploc->inverted())) |
| 1011 | | dip->state |= 1 << (diploc->number() - 1); |
| 1012 | | |
| 1013 | | /* clear the relevant bit in the accumulated mask */ |
| 1014 | | accummask &= ~mask; |
| 1015 | | } |
| 1016 | | } |
| 1017 | | } |
| 1018 | | if (type == IPT_DIPSWITCH) |
| 1019 | | custombottom = dipcount ? dipcount * (DIP_SWITCH_HEIGHT + DIP_SWITCH_SPACING) + DIP_SWITCH_SPACING : 0; |
| 1020 | | |
| 1021 | | item_append(MENU_SEPARATOR_ITEM, NULL, 0, NULL); |
| 1022 | | item_append("Reset", NULL, 0, (void *)1); |
| 1023 | | } |
| 1024 | | |
| 1025 | | ui_menu_settings::~ui_menu_settings() |
| 1026 | | { |
| 1027 | | } |
| 1028 | | |
| 1029 | | /*------------------------------------------------- |
| 1030 | | menu_settings_custom_render - perform our special |
| 1031 | | rendering |
| 1032 | | -------------------------------------------------*/ |
| 1033 | | |
| 1034 | | void ui_menu_settings_dip_switches::custom_render(void *selectedref, float top, float bottom, float x1, float y1, float x2, float y2) |
| 1035 | | { |
| 1036 | | // catch if no diploc has to be drawn |
| 1037 | | if (bottom == 0) |
| 1038 | | return; |
| 1039 | | |
| 1040 | | // add borders |
| 1041 | | y1 = y2 + UI_BOX_TB_BORDER; |
| 1042 | | y2 = y1 + bottom; |
| 1043 | | |
| 1044 | | // draw extra menu area |
| 1045 | | machine().ui().draw_outlined_box(container, x1, y1, x2, y2, UI_BACKGROUND_COLOR); |
| 1046 | | y1 += (float)DIP_SWITCH_SPACING; |
| 1047 | | |
| 1048 | | // iterate over DIP switches |
| 1049 | | for (dip_descriptor *dip = diplist; dip != NULL; dip = dip->next) |
| 1050 | | { |
| 1051 | | const ioport_diplocation *diploc; |
| 1052 | | UINT32 selectedmask = 0; |
| 1053 | | |
| 1054 | | // determine the mask of selected bits |
| 1055 | | if ((FPTR)selectedref != 1) |
| 1056 | | { |
| 1057 | | ioport_field *field = (ioport_field *)selectedref; |
| 1058 | | |
| 1059 | | if (field != NULL && field->first_diplocation() != NULL) |
| 1060 | | for (diploc = field->first_diplocation(); diploc != NULL; diploc = diploc->next()) |
| 1061 | | if (strcmp(dip->name, diploc->name()) == 0) |
| 1062 | | selectedmask |= 1 << (diploc->number() - 1); |
| 1063 | | } |
| 1064 | | |
| 1065 | | // draw one switch |
| 1066 | | custom_render_one(x1, y1, x2, y1 + DIP_SWITCH_HEIGHT, dip, selectedmask); |
| 1067 | | y1 += (float)(DIP_SWITCH_SPACING + DIP_SWITCH_HEIGHT); |
| 1068 | | } |
| 1069 | | } |
| 1070 | | |
| 1071 | | |
| 1072 | | /*------------------------------------------------- |
| 1073 | | menu_settings_custom_render_one - draw a single |
| 1074 | | DIP switch |
| 1075 | | -------------------------------------------------*/ |
| 1076 | | |
| 1077 | | void ui_menu_settings_dip_switches::custom_render_one(float x1, float y1, float x2, float y2, const dip_descriptor *dip, UINT32 selectedmask) |
| 1078 | | { |
| 1079 | | float switch_field_width = SINGLE_TOGGLE_SWITCH_FIELD_WIDTH * container->manager().ui_aspect(); |
| 1080 | | float switch_width = SINGLE_TOGGLE_SWITCH_WIDTH * container->manager().ui_aspect(); |
| 1081 | | int numtoggles, toggle; |
| 1082 | | float switch_toggle_gap; |
| 1083 | | float y1_off, y1_on; |
| 1084 | | |
| 1085 | | /* determine the number of toggles in the DIP */ |
| 1086 | | numtoggles = 32 - count_leading_zeros(dip->mask); |
| 1087 | | |
| 1088 | | /* center based on the number of switches */ |
| 1089 | | x1 += (x2 - x1 - numtoggles * switch_field_width) / 2; |
| 1090 | | |
| 1091 | | /* draw the dip switch name */ |
| 1092 | | machine().ui().draw_text_full( container, |
| 1093 | | dip->name, |
| 1094 | | 0, |
| 1095 | | y1 + (DIP_SWITCH_HEIGHT - UI_TARGET_FONT_HEIGHT) / 2, |
| 1096 | | x1 - machine().ui().get_string_width(" "), |
| 1097 | | JUSTIFY_RIGHT, |
| 1098 | | WRAP_NEVER, |
| 1099 | | DRAW_NORMAL, |
| 1100 | | UI_TEXT_COLOR, |
| 1101 | | PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA), |
| 1102 | | NULL , |
| 1103 | | NULL); |
| 1104 | | |
| 1105 | | /* compute top and bottom for on and off positions */ |
| 1106 | | switch_toggle_gap = ((DIP_SWITCH_HEIGHT/2) - SINGLE_TOGGLE_SWITCH_HEIGHT)/2; |
| 1107 | | y1_off = y1 + UI_LINE_WIDTH + switch_toggle_gap; |
| 1108 | | y1_on = y1 + DIP_SWITCH_HEIGHT/2 + switch_toggle_gap; |
| 1109 | | |
| 1110 | | /* iterate over toggles */ |
| 1111 | | for (toggle = 0; toggle < numtoggles; toggle++) |
| 1112 | | { |
| 1113 | | float innerx1; |
| 1114 | | |
| 1115 | | /* first outline the switch */ |
| 1116 | | machine().ui().draw_outlined_box(container, x1, y1, x1 + switch_field_width, y2, UI_BACKGROUND_COLOR); |
| 1117 | | |
| 1118 | | /* compute x1/x2 for the inner filled in switch */ |
| 1119 | | innerx1 = x1 + (switch_field_width - switch_width) / 2; |
| 1120 | | |
| 1121 | | /* see if the switch is actually used */ |
| 1122 | | if (dip->mask & (1 << toggle)) |
| 1123 | | { |
| 1124 | | float innery1 = (dip->state & (1 << toggle)) ? y1_on : y1_off; |
| 1125 | | container->add_rect(innerx1, innery1, innerx1 + switch_width, innery1 + SINGLE_TOGGLE_SWITCH_HEIGHT, |
| 1126 | | (selectedmask & (1 << toggle)) ? UI_DIPSW_COLOR : UI_TEXT_COLOR, |
| 1127 | | PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA)); |
| 1128 | | } |
| 1129 | | else |
| 1130 | | { |
| 1131 | | container->add_rect(innerx1, y1_off, innerx1 + switch_width, y1_on + SINGLE_TOGGLE_SWITCH_HEIGHT, |
| 1132 | | UI_UNAVAILABLE_COLOR, |
| 1133 | | PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA)); |
| 1134 | | } |
| 1135 | | |
| 1136 | | /* advance to the next switch */ |
| 1137 | | x1 += switch_field_width; |
| 1138 | | } |
| 1139 | | } |
| 1140 | | |
| 1141 | | |
| 1142 | | /*------------------------------------------------- |
| 1143 | | menu_analog - handle the analog settings menu |
| 1144 | | -------------------------------------------------*/ |
| 1145 | | |
| 1146 | | void ui_menu_analog::handle() |
| 1147 | | { |
| 1148 | | /* process the menu */ |
| 1149 | | const ui_menu_event *menu_event = process(UI_MENU_PROCESS_LR_REPEAT); |
| 1150 | | |
| 1151 | | /* handle events */ |
| 1152 | | if (menu_event != NULL && menu_event->itemref != NULL) |
| 1153 | | { |
| 1154 | | analog_item_data *data = (analog_item_data *)menu_event->itemref; |
| 1155 | | int newval = data->cur; |
| 1156 | | |
| 1157 | | switch (menu_event->iptkey) |
| 1158 | | { |
| 1159 | | /* if selected, reset to default value */ |
| 1160 | | case IPT_UI_SELECT: |
| 1161 | | newval = data->defvalue; |
| 1162 | | break; |
| 1163 | | |
| 1164 | | /* left decrements */ |
| 1165 | | case IPT_UI_LEFT: |
| 1166 | | newval -= machine().input().code_pressed(KEYCODE_LSHIFT) ? 10 : 1; |
| 1167 | | break; |
| 1168 | | |
| 1169 | | /* right increments */ |
| 1170 | | case IPT_UI_RIGHT: |
| 1171 | | newval += machine().input().code_pressed(KEYCODE_LSHIFT) ? 10 : 1; |
| 1172 | | break; |
| 1173 | | } |
| 1174 | | |
| 1175 | | /* clamp to range */ |
| 1176 | | if (newval < data->min) |
| 1177 | | newval = data->min; |
| 1178 | | if (newval > data->max) |
| 1179 | | newval = data->max; |
| 1180 | | |
| 1181 | | /* if things changed, update */ |
| 1182 | | if (newval != data->cur) |
| 1183 | | { |
| 1184 | | ioport_field::user_settings settings; |
| 1185 | | |
| 1186 | | /* get the settings and set the new value */ |
| 1187 | | data->field->get_user_settings(settings); |
| 1188 | | switch (data->type) |
| 1189 | | { |
| 1190 | | case ANALOG_ITEM_KEYSPEED: settings.delta = newval; break; |
| 1191 | | case ANALOG_ITEM_CENTERSPEED: settings.centerdelta = newval; break; |
| 1192 | | case ANALOG_ITEM_REVERSE: settings.reverse = newval; break; |
| 1193 | | case ANALOG_ITEM_SENSITIVITY: settings.sensitivity = newval; break; |
| 1194 | | } |
| 1195 | | data->field->set_user_settings(settings); |
| 1196 | | |
| 1197 | | /* rebuild the menu */ |
| 1198 | | reset(UI_MENU_RESET_REMEMBER_POSITION); |
| 1199 | | } |
| 1200 | | } |
| 1201 | | } |
| 1202 | | |
| 1203 | | |
| 1204 | | /*------------------------------------------------- |
| 1205 | | menu_analog_populate - populate the analog |
| 1206 | | settings menu |
| 1207 | | -------------------------------------------------*/ |
| 1208 | | |
| 1209 | | ui_menu_analog::ui_menu_analog(running_machine &machine, render_container *container) : ui_menu(machine, container) |
| 1210 | | { |
| 1211 | | } |
| 1212 | | |
| 1213 | | void ui_menu_analog::populate() |
| 1214 | | { |
| 1215 | | ioport_field *field; |
| 1216 | | ioport_port *port; |
| 1217 | | astring text; |
| 1218 | | astring subtext; |
| 1219 | | astring prev_owner; |
| 1220 | | bool first_entry = true; |
| 1221 | | |
| 1222 | | /* loop over input ports and add the items */ |
| 1223 | | for (port = machine().ioport().first_port(); port != NULL; port = port->next()) |
| 1224 | | for (field = port->first_field(); field != NULL; field = field->next()) |
| 1225 | | if (field->is_analog() && field->enabled()) |
| 1226 | | { |
| 1227 | | ioport_field::user_settings settings; |
| 1228 | | int use_autocenter = false; |
| 1229 | | int type; |
| 1230 | | |
| 1231 | | /* based on the type, determine if we enable autocenter */ |
| 1232 | | switch (field->type()) |
| 1233 | | { |
| 1234 | | case IPT_POSITIONAL: |
| 1235 | | case IPT_POSITIONAL_V: |
| 1236 | | if (field->analog_wraps()) |
| 1237 | | break; |
| 1238 | | |
| 1239 | | case IPT_AD_STICK_X: |
| 1240 | | case IPT_AD_STICK_Y: |
| 1241 | | case IPT_AD_STICK_Z: |
| 1242 | | case IPT_PADDLE: |
| 1243 | | case IPT_PADDLE_V: |
| 1244 | | case IPT_PEDAL: |
| 1245 | | case IPT_PEDAL2: |
| 1246 | | case IPT_PEDAL3: |
| 1247 | | use_autocenter = true; |
| 1248 | | break; |
| 1249 | | |
| 1250 | | default: |
| 1251 | | break; |
| 1252 | | } |
| 1253 | | |
| 1254 | | /* get the user settings */ |
| 1255 | | field->get_user_settings(settings); |
| 1256 | | |
| 1257 | | /* iterate over types */ |
| 1258 | | for (type = 0; type < ANALOG_ITEM_COUNT; type++) |
| 1259 | | if (type != ANALOG_ITEM_CENTERSPEED || use_autocenter) |
| 1260 | | { |
| 1261 | | analog_item_data *data; |
| 1262 | | UINT32 flags = 0; |
| 1263 | | astring name; |
| 1264 | | if (strcmp(field->device().tag(), prev_owner.cstr()) != 0) |
| 1265 | | { |
| 1266 | | if (first_entry) |
| 1267 | | first_entry = false; |
| 1268 | | else |
| 1269 | | item_append(MENU_SEPARATOR_ITEM, NULL, 0, NULL); |
| 1270 | | name.printf("[root%s]", field->device().tag()); |
| 1271 | | item_append(name, NULL, 0, NULL); |
| 1272 | | prev_owner.cpy(field->device().tag()); |
| 1273 | | } |
| 1274 | | |
| 1275 | | name.cpy(field->name()); |
| 1276 | | |
| 1277 | | /* allocate a data item for tracking what this menu item refers to */ |
| 1278 | | data = (analog_item_data *)m_pool_alloc(sizeof(*data)); |
| 1279 | | data->field = field; |
| 1280 | | data->type = type; |
| 1281 | | |
| 1282 | | /* determine the properties of this item */ |
| 1283 | | switch (type) |
| 1284 | | { |
| 1285 | | default: |
| 1286 | | case ANALOG_ITEM_KEYSPEED: |
| 1287 | | text.printf("%s Digital Speed", name.cstr()); |
| 1288 | | subtext.printf("%d", settings.delta); |
| 1289 | | data->min = 0; |
| 1290 | | data->max = 255; |
| 1291 | | data->cur = settings.delta; |
| 1292 | | data->defvalue = field->delta(); |
| 1293 | | break; |
| 1294 | | |
| 1295 | | case ANALOG_ITEM_CENTERSPEED: |
| 1296 | | text.printf("%s Autocenter Speed", name.cstr()); |
| 1297 | | subtext.printf("%d", settings.centerdelta); |
| 1298 | | data->min = 0; |
| 1299 | | data->max = 255; |
| 1300 | | data->cur = settings.centerdelta; |
| 1301 | | data->defvalue = field->centerdelta(); |
| 1302 | | break; |
| 1303 | | |
| 1304 | | case ANALOG_ITEM_REVERSE: |
| 1305 | | text.printf("%s Reverse", name.cstr()); |
| 1306 | | subtext.cpy(settings.reverse ? "On" : "Off"); |
| 1307 | | data->min = 0; |
| 1308 | | data->max = 1; |
| 1309 | | data->cur = settings.reverse; |
| 1310 | | data->defvalue = field->analog_reverse(); |
| 1311 | | break; |
| 1312 | | |
| 1313 | | case ANALOG_ITEM_SENSITIVITY: |
| 1314 | | text.printf("%s Sensitivity", name.cstr()); |
| 1315 | | subtext.printf("%d", settings.sensitivity); |
| 1316 | | data->min = 1; |
| 1317 | | data->max = 255; |
| 1318 | | data->cur = settings.sensitivity; |
| 1319 | | data->defvalue = field->sensitivity(); |
| 1320 | | break; |
| 1321 | | } |
| 1322 | | |
| 1323 | | /* put on arrows */ |
| 1324 | | if (data->cur > data->min) |
| 1325 | | flags |= MENU_FLAG_LEFT_ARROW; |
| 1326 | | if (data->cur < data->max) |
| 1327 | | flags |= MENU_FLAG_RIGHT_ARROW; |
| 1328 | | |
| 1329 | | /* append a menu item */ |
| 1330 | | item_append(text, subtext, flags, data); |
| 1331 | | } |
| 1332 | | } |
| 1333 | | } |
| 1334 | | |
| 1335 | | ui_menu_analog::~ui_menu_analog() |
| 1336 | | { |
| 1337 | | } |
| 1338 | | |
| 1339 | | /*------------------------------------------------- |
| 1340 | 231 | menu_bookkeeping - handle the bookkeeping |
| 1341 | 232 | information menu |
| 1342 | 233 | -------------------------------------------------*/ |
trunk/src/mame/drivers/eolith.c
| r242908 | r242909 | |
| 103 | 103 | |
| 104 | 104 | #include "machine/eepromser.h" |
| 105 | 105 | #include "includes/eolith.h" |
| 106 | | #include "includes/eolithsp.h" |
| 107 | 106 | |
| 108 | 107 | |
| 109 | | |
| 110 | | |
| 111 | | |
| 112 | 108 | /************************************* |
| 113 | 109 | * |
| 114 | 110 | * Control |
| r242908 | r242909 | |
| 125 | 121 | bit 8 = ??? |
| 126 | 122 | bit 9 = ??? |
| 127 | 123 | */ |
| 128 | | eolith_speedup_read(space); |
| 124 | speedup_read(); |
| 129 | 125 | |
| 130 | 126 | return (m_in0->read() & ~0x300) | (machine().rand() & 0x300); |
| 131 | 127 | } |
| r242908 | r242909 | |
| 165 | 161 | m_sound_data = data; |
| 166 | 162 | m_soundcpu->set_input_line(MCS51_INT0_LINE, ASSERT_LINE); |
| 167 | 163 | |
| 168 | | space.machine().scheduler().boost_interleave(attotime::zero, attotime::from_usec(250)); |
| 164 | machine().scheduler().boost_interleave(attotime::zero, attotime::from_usec(250)); |
| 169 | 165 | } |
| 170 | 166 | |
| 171 | 167 | |
| r242908 | r242909 | |
| 1491 | 1487 | |
| 1492 | 1488 | DRIVER_INIT_MEMBER(eolith_state,eolith) |
| 1493 | 1489 | { |
| 1494 | | init_eolith_speedup(machine()); |
| 1490 | init_speedup(); |
| 1495 | 1491 | |
| 1496 | 1492 | // Sound CPU -> QS1000 CPU serial link |
| 1497 | 1493 | m_soundcpu->i8051_set_serial_tx_callback(write8_delegate(FUNC(eolith_state::soundcpu_to_qs1000),this)); |
| 1498 | 1494 | |
| 1499 | 1495 | // Configure the sound ROM banking |
| 1500 | 1496 | membank("sound_bank")->configure_entries(0, 16, memregion("sounddata")->base(), 0x8000); |
| 1497 | |
| 1498 | save_item(NAME(m_sound_data)); |
| 1501 | 1499 | } |
| 1502 | 1500 | |
| 1503 | 1501 | DRIVER_INIT_MEMBER(eolith_state,landbrk) |
| r242908 | r242909 | |
| 1569 | 1567 | * |
| 1570 | 1568 | *************************************/ |
| 1571 | 1569 | |
| 1572 | | GAME( 1998, linkypip, 0, eolith45, linkypip, eolith_state, eolith, ROT0, "Eolith", "Linky Pipe", GAME_IMPERFECT_SOUND ) |
| 1573 | | GAME( 1998, ironfort, 0, ironfort, ironfort, eolith_state, eolith, ROT0, "Eolith", "Iron Fortress", GAME_IMPERFECT_SOUND ) |
| 1574 | | GAME( 1998, ironfortj, ironfort, ironfort, ironfortj, eolith_state, eolith, ROT0, "Eolith", "Iron Fortress (Japan)", GAME_IMPERFECT_SOUND ) |
| 1575 | | GAME( 1998, hidnctch, 0, eolith45, hidnctch, eolith_state, eolith, ROT0, "Eolith", "Hidden Catch (World) / Tul Lin Gu Lim Chat Ki '98 (Korea) (pcb ver 3.03)", GAME_IMPERFECT_SOUND ) // or Teurrin Geurim Chajgi '98 |
| 1576 | | GAME( 1998, raccoon, 0, eolith45, raccoon, eolith_state, eolith, ROT0, "Eolith", "Raccoon World", GAME_IMPERFECT_SOUND ) |
| 1577 | | GAME( 1998, puzzlekg, 0, eolith45, puzzlekg, eolith_state, eolith, ROT0, "Eolith", "Puzzle King (Dance & Puzzle)", GAME_IMPERFECT_SOUND ) |
| 1578 | | GAME( 1999, candy, 0, eolith50, candy, eolith_state, eolith, ROT0, "Eolith", "Candy Candy", GAME_IMPERFECT_GRAPHICS | GAME_IMPERFECT_SOUND ) |
| 1579 | | GAME( 1999, hidctch2, 0, eolith50, hidctch2, eolith_state, hidctch2, ROT0, "Eolith", "Hidden Catch 2 (pcb ver 3.03) (Kor/Eng) (AT89c52 protected)", GAME_IMPERFECT_SOUND ) |
| 1580 | | GAME( 1999, hidctch2a, hidctch2, eolith50, hidctch2, eolith_state, eolith, ROT0, "Eolith", "Hidden Catch 2 (pcb ver 1.00) (Kor/Eng/Jpn/Chi)", GAME_IMPERFECT_SOUND ) |
| 1581 | | GAME( 1999, hidnc2k, 0, eolith50, hidctch2, eolith_state, hidnc2k, ROT0, "Eolith", "Hidden Catch 2000 (AT89c52 protected)", GAME_IMPERFECT_SOUND ) |
| 1582 | | GAME( 1999, landbrk, 0, eolith45, landbrk, eolith_state, landbrk, ROT0, "Eolith", "Land Breaker (World) / Miss Tang Ja Ru Gi (Korea) (pcb ver 3.02)", GAME_IMPERFECT_SOUND ) // or Miss Ttang Jjareugi |
| 1583 | | GAME( 1999, landbrka, landbrk, eolith45, landbrk, eolith_state, landbrka, ROT0, "Eolith", "Land Breaker (World) / Miss Tang Ja Ru Gi (Korea) (pcb ver 3.03) (AT89c52 protected)", GAME_IMPERFECT_SOUND ) // or Miss Ttang Jjareugi |
| 1584 | | GAME( 1999, nhidctch, 0, eolith45, hidctch2, eolith_state, eolith, ROT0, "Eolith", "New Hidden Catch (World) / New Tul Lin Gu Lim Chat Ki '98 (Korea) (pcb ver 3.02)", GAME_IMPERFECT_SOUND ) // or New Teurrin Geurim Chajgi '98 |
| 1585 | | GAME( 1999, penfan, 0, eolith45, penfan, eolith_state, eolith, ROT0, "Eolith", "Penfan Girls - Step1. Mild Mind (set 1)", GAME_IMPERFECT_SOUND ) // alt title of Ribbon |
| 1586 | | GAME( 1999, penfana, penfan, eolith45, penfan, eolith_state, eolith, ROT0, "Eolith", "Penfan Girls - Step1. Mild Mind (set 2)", GAME_IMPERFECT_SOUND ) |
| 1587 | | GAME( 2000, stealsee, 0, eolith45, stealsee, eolith_state, eolith, ROT0, "Moov Generation / Eolith", "Steal See", GAME_IMPERFECT_SOUND ) |
| 1588 | | GAME( 2000, hidctch3, 0, eolith50, hidctch3, eolith_state, hidctch3, ROT0, "Eolith", "Hidden Catch 3 (ver 1.00 / pcb ver 3.05)", GAME_IMPERFECT_SOUND ) |
| 1589 | | GAME( 2001, fort2b, 0, eolith50, common, eolith_state, eolith, ROT0, "Eolith", "Fortress 2 Blue Arcade (ver 1.01 / pcb ver 3.05)", GAME_IMPERFECT_SOUND ) |
| 1590 | | GAME( 2001, fort2ba, fort2b, eolith50, common, eolith_state, eolith, ROT0, "Eolith", "Fortress 2 Blue Arcade (ver 1.00 / pcb ver 3.05)", GAME_IMPERFECT_SOUND ) |
| 1570 | GAME( 1998, linkypip, 0, eolith45, linkypip, eolith_state, eolith, ROT0, "Eolith", "Linky Pipe", GAME_IMPERFECT_SOUND | GAME_SUPPORTS_SAVE ) |
| 1571 | GAME( 1998, ironfort, 0, ironfort, ironfort, eolith_state, eolith, ROT0, "Eolith", "Iron Fortress", GAME_IMPERFECT_SOUND | GAME_SUPPORTS_SAVE ) |
| 1572 | GAME( 1998, ironfortj, ironfort, ironfort, ironfortj, eolith_state, eolith, ROT0, "Eolith", "Iron Fortress (Japan)", GAME_IMPERFECT_SOUND | GAME_SUPPORTS_SAVE ) |
| 1573 | GAME( 1998, hidnctch, 0, eolith45, hidnctch, eolith_state, eolith, ROT0, "Eolith", "Hidden Catch (World) / Tul Lin Gu Lim Chat Ki '98 (Korea) (pcb ver 3.03)", GAME_IMPERFECT_SOUND | GAME_SUPPORTS_SAVE ) // or Teurrin Geurim Chajgi '98 |
| 1574 | GAME( 1998, raccoon, 0, eolith45, raccoon, eolith_state, eolith, ROT0, "Eolith", "Raccoon World", GAME_IMPERFECT_SOUND | GAME_SUPPORTS_SAVE ) |
| 1575 | GAME( 1998, puzzlekg, 0, eolith45, puzzlekg, eolith_state, eolith, ROT0, "Eolith", "Puzzle King (Dance & Puzzle)", GAME_IMPERFECT_SOUND | GAME_SUPPORTS_SAVE ) |
| 1576 | GAME( 1999, candy, 0, eolith50, candy, eolith_state, eolith, ROT0, "Eolith", "Candy Candy", GAME_IMPERFECT_GRAPHICS | GAME_IMPERFECT_SOUND | GAME_SUPPORTS_SAVE ) |
| 1577 | GAME( 1999, hidctch2, 0, eolith50, hidctch2, eolith_state, hidctch2, ROT0, "Eolith", "Hidden Catch 2 (pcb ver 3.03) (Kor/Eng) (AT89c52 protected)", GAME_IMPERFECT_SOUND | GAME_SUPPORTS_SAVE ) |
| 1578 | GAME( 1999, hidctch2a, hidctch2, eolith50, hidctch2, eolith_state, eolith, ROT0, "Eolith", "Hidden Catch 2 (pcb ver 1.00) (Kor/Eng/Jpn/Chi)", GAME_IMPERFECT_SOUND | GAME_SUPPORTS_SAVE ) |
| 1579 | GAME( 1999, hidnc2k, 0, eolith50, hidctch2, eolith_state, hidnc2k, ROT0, "Eolith", "Hidden Catch 2000 (AT89c52 protected)", GAME_IMPERFECT_SOUND | GAME_SUPPORTS_SAVE ) |
| 1580 | GAME( 1999, landbrk, 0, eolith45, landbrk, eolith_state, landbrk, ROT0, "Eolith", "Land Breaker (World) / Miss Tang Ja Ru Gi (Korea) (pcb ver 3.02)", GAME_IMPERFECT_SOUND | GAME_SUPPORTS_SAVE ) // or Miss Ttang Jjareugi |
| 1581 | GAME( 1999, landbrka, landbrk, eolith45, landbrk, eolith_state, landbrka, ROT0, "Eolith", "Land Breaker (World) / Miss Tang Ja Ru Gi (Korea) (pcb ver 3.03) (AT89c52 protected)", GAME_IMPERFECT_SOUND | GAME_SUPPORTS_SAVE ) // or Miss Ttang Jjareugi |
| 1582 | GAME( 1999, nhidctch, 0, eolith45, hidctch2, eolith_state, eolith, ROT0, "Eolith", "New Hidden Catch (World) / New Tul Lin Gu Lim Chat Ki '98 (Korea) (pcb ver 3.02)", GAME_IMPERFECT_SOUND | GAME_SUPPORTS_SAVE ) // or New Teurrin Geurim Chajgi '98 |
| 1583 | GAME( 1999, penfan, 0, eolith45, penfan, eolith_state, eolith, ROT0, "Eolith", "Penfan Girls - Step1. Mild Mind (set 1)", GAME_IMPERFECT_SOUND | GAME_SUPPORTS_SAVE ) // alt title of Ribbon |
| 1584 | GAME( 1999, penfana, penfan, eolith45, penfan, eolith_state, eolith, ROT0, "Eolith", "Penfan Girls - Step1. Mild Mind (set 2)", GAME_IMPERFECT_SOUND | GAME_SUPPORTS_SAVE ) |
| 1585 | GAME( 2000, stealsee, 0, eolith45, stealsee, eolith_state, eolith, ROT0, "Moov Generation / Eolith", "Steal See", GAME_IMPERFECT_SOUND | GAME_SUPPORTS_SAVE ) |
| 1586 | GAME( 2000, hidctch3, 0, eolith50, hidctch3, eolith_state, hidctch3, ROT0, "Eolith", "Hidden Catch 3 (ver 1.00 / pcb ver 3.05)", GAME_IMPERFECT_SOUND | GAME_SUPPORTS_SAVE ) |
| 1587 | GAME( 2001, fort2b, 0, eolith50, common, eolith_state, eolith, ROT0, "Eolith", "Fortress 2 Blue Arcade (ver 1.01 / pcb ver 3.05)", GAME_IMPERFECT_SOUND | GAME_SUPPORTS_SAVE ) |
| 1588 | GAME( 2001, fort2ba, fort2b, eolith50, common, eolith_state, eolith, ROT0, "Eolith", "Fortress 2 Blue Arcade (ver 1.00 / pcb ver 3.05)", GAME_IMPERFECT_SOUND | GAME_SUPPORTS_SAVE ) |