static int config_save_xml(running_machine &machine, emu_file &file, int which_type) { xml_data_node *root = xml_file_create(); xml_data_node *confignode, *systemnode; config_type *type; /* if we don't have a root, bail */ if (!root) return 0; /* create a config node */ confignode = xml_add_child(root, "mameconfig", NULL); if (!confignode) goto error; xml_set_attribute_int(confignode, "version", CONFIG_VERSION); /* create a system node */ systemnode = xml_add_child(confignode, "system", NULL); if (!systemnode) goto error; xml_set_attribute(systemnode, "name", (which_type == CONFIG_TYPE_DEFAULT) ? "default" : machine.system().name); /* create the input node and write it out */ /* loop over all registrants and call their save function */ for (type = typelist; type; type = type->next) { xml_data_node *curnode = xml_add_child(systemnode, type->name, NULL); if (!curnode) goto error; type->save(which_type, curnode); /* if nothing was added, just nuke the node */ if (!curnode->value && !curnode->child) xml_delete_node(curnode); } /* flush the file */ xml_file_write(root, file); /* free and get out of here */ xml_file_free(root); return 1; error: xml_file_free(root); return 0; }
ROM_END static void decrypt_gfx(running_machine &machine) { UINT8 *buf = auto_alloc_array(machine, UINT8, 0x40000); UINT8 *rom; int size; int i; rom = machine.root_device().memregion("gfx1")->base(); size = machine.root_device().memregion("gfx1")->bytes(); /* data lines */ for (i = 0;i < size/2;i++) { int w1; w1 = (rom[i + 0*size/2] << 8) + rom[i + 1*size/2]; w1 = BITSWAP16(w1, 9,14,7,2, 6,8,3,15, 10,13,5,12, 0,11,4,1); buf[i + 0*size/2] = w1 >> 8; buf[i + 1*size/2] = w1 & 0xff; } /* address lines */ for (i = 0;i < size;i++) { rom[i] = buf[BITSWAP24(i,23,22,21,20,19,18,17,16,15,14,13,12, 3,2,1, 11,10,9,8, 0, 7,6,5,4)]; } rom = machine.root_device().memregion("gfx2")->base(); size = machine.root_device().memregion("gfx2")->bytes(); /* data lines */ for (i = 0;i < size/2;i++) { int w1; w1 = (rom[i + 0*size/2] << 8) + rom[i + 1*size/2]; w1 = BITSWAP16(w1, 9,14,7,2, 6,8,3,15, 10,13,5,12, 0,11,4,1); buf[i + 0*size/2] = w1 >> 8; buf[i + 1*size/2] = w1 & 0xff; } /* address lines */ for (i = 0;i < size;i++) { rom[i] = buf[BITSWAP24(i,23,22,21,20,19,18,17,16,15,14,13, 5,4,3,2, 12,11,10,9,8, 1,0, 7,6)]; } rom = machine.root_device().memregion("gfx3")->base(); size = machine.root_device().memregion("gfx3")->bytes(); /* data lines */ for (i = 0;i < size/2;i++) { int w1; w1 = (rom[i + 0*size/2] << 8) + rom[i + 1*size/2]; w1 = BITSWAP16(w1, 9,14,7,2, 6,8,3,15, 10,13,5,12, 0,11,4,1); buf[i + 0*size/2] = w1 >> 8; buf[i + 1*size/2] = w1 & 0xff; } /* address lines */ for (i = 0;i < size;i++) { rom[i] = buf[BITSWAP24(i, 23,22,21,20,19,18,17,16,15,14, 12,11,10,9,8, 5,4,3, 13, 7,6, 1,0, 2)]; } auto_free(machine, buf); }
static int config_load_xml(running_machine &machine, emu_file &file, int which_type) { xml_data_node *root, *confignode, *systemnode; config_type *type; const char *srcfile; int version, count; /* read the file */ root = xml_file_read(file, NULL); if (!root) goto error; /* find the config node */ confignode = xml_get_sibling(root->child, "mameconfig"); if (!confignode) goto error; /* validate the config data version */ version = xml_get_attribute_int(confignode, "version", 0); if (version != CONFIG_VERSION) goto error; /* strip off all the path crap from the source filename */ srcfile = strrchr(machine.system().source_file, '/'); if (!srcfile) srcfile = strrchr(machine.system().source_file, '\\'); if (!srcfile) srcfile = strrchr(machine.system().source_file, ':'); if (!srcfile) srcfile = machine.system().source_file; else srcfile++; /* loop over all system nodes in the file */ count = 0; for (systemnode = xml_get_sibling(confignode->child, "system"); systemnode; systemnode = xml_get_sibling(systemnode->next, "system")) { /* look up the name of the system here; skip if none */ const char *name = xml_get_attribute_string(systemnode, "name", ""); /* based on the file type, determine whether we have a match */ switch (which_type) { case CONFIG_TYPE_GAME: /* only match on the specific game name */ if (strcmp(name, machine.system().name) != 0) continue; break; case CONFIG_TYPE_DEFAULT: /* only match on default */ if (strcmp(name, "default") != 0) continue; break; case CONFIG_TYPE_CONTROLLER: { int clone_of; /* match on: default, game name, source file name, parent name, grandparent name */ if (strcmp(name, "default") != 0 && strcmp(name, machine.system().name) != 0 && strcmp(name, srcfile) != 0 && ((clone_of = driver_list::clone(machine.system())) == -1 || strcmp(name, driver_list::driver(clone_of).name) != 0) && (clone_of == -1 || ((clone_of = driver_list::clone(clone_of)) == -1) || strcmp(name, driver_list::driver(clone_of).name) != 0)) continue; break; } } /* log that we are processing this entry */ if (DEBUG_CONFIG) osd_printf_debug("Entry: %s -- processing\n", name); /* loop over all registrants and call their load function */ for (type = typelist; type; type = type->next) type->load(which_type, xml_get_sibling(systemnode->child, type->name)); count++; } /* error if this isn't a valid game match */ if (count == 0) goto error; /* free the parser */ xml_file_free(root); return 1; error: if (root) xml_file_free(root); return 0; }
void k055555_device::K055555_vh_start(running_machine &machine) { machine.save().save_item(NAME(m_regs)); memset(m_regs, 0, 64*sizeof(UINT8)); }
static void create_interrupt_timer( running_machine &machine ) { beaminv_state *state = machine.driver_data<beaminv_state>(); state->m_interrupt_timer = machine.scheduler().timer_alloc(FUNC(interrupt_callback)); }
static void draw_sprites( running_machine &machine, bitmap_t *bitmap, const rectangle *cliprect ) { mcatadv_state *state = machine.driver_data<mcatadv_state>(); UINT16 *source = state->m_spriteram_old; UINT16 *finish = source + (state->m_spriteram_size / 2) / 2; int global_x = state->m_vidregs[0] - 0x184; int global_y = state->m_vidregs[1] - 0x1f1; UINT16 *destline; UINT8 *priline; UINT8 *sprdata = machine.region("gfx1")->base(); int xstart, xend, xinc; int ystart, yend, yinc; if (state->m_vidregs_old[2] == 0x0001) /* Double Buffered */ { source += (state->m_spriteram_size / 2) / 2; finish += (state->m_spriteram_size / 2) / 2; } else if (state->m_vidregs_old[2]) /* I suppose it's possible that there is 4 banks, haven't seen it used though */ { logerror("Spritebank != 0/1\n"); } while (source < finish) { int pen = (source[0] & 0x3f00) >> 8; int tileno = source[1] & 0xffff; int pri = (source[0] & 0xc000) >> 14; int x = source[2] & 0x3ff; int y = source[3] & 0x3ff; int flipy = source[0] & 0x0040; int flipx = source[0] & 0x0080; int height = ((source[3] & 0xf000) >> 12) * 16; int width = ((source[2] & 0xf000) >> 12) * 16; int offset = tileno * 256; int drawxpos, drawypos; int xcnt, ycnt; int pix; if (x & 0x200) x-=0x400; if (y & 0x200) y-=0x400; #if 0 // For Flipscreen/Cocktail if(state->m_vidregs[0] & 0x8000) { flipx = !flipx; } if(state->m_vidregs[1] & 0x8000) { flipy = !flipy; } #endif if (source[3] != source[0]) // 'hack' don't draw sprites while its testing the ram! { if(!flipx) { xstart = 0; xend = width; xinc = 1; } else { xstart = width-1; xend = -1; xinc = -1; } if(!flipy) { ystart = 0; yend = height; yinc = 1; } else { ystart = height-1; yend = -1; yinc = -1; } for (ycnt = ystart; ycnt != yend; ycnt += yinc) { drawypos = y + ycnt - global_y; if ((drawypos >= cliprect->min_y) && (drawypos <= cliprect->max_y)) { destline = BITMAP_ADDR16(bitmap, drawypos, 0); priline = BITMAP_ADDR8(machine.priority_bitmap, drawypos, 0); for (xcnt = xstart; xcnt != xend; xcnt += xinc) { drawxpos = x + xcnt - global_x; if((priline[drawxpos] < pri)) { if (offset >= 0x500000 * 2) offset = 0; pix = sprdata[offset / 2]; if (offset & 1) pix = pix >> 4; pix &= 0x0f; if ((drawxpos >= cliprect->min_x) && (drawxpos <= cliprect->max_x) && pix) destline[drawxpos] = (pix + (pen << 4)); } offset++; } } else { offset += width; } } }
static HRESULT dsound_init(running_machine &machine) { HRESULT result; // create the DirectSound object result = DirectSoundCreate(NULL, &dsound, NULL); if (result != DS_OK) { mame_printf_error(_WINDOWS("Error creating DirectSound: %08x\n"), (UINT32)result); goto error; } // get the capabilities dsound_caps.dwSize = sizeof(dsound_caps); result = IDirectSound_GetCaps(dsound, &dsound_caps); if (result != DS_OK) { mame_printf_error(_WINDOWS("Error getting DirectSound capabilities: %08x\n"), (UINT32)result); goto error; } // set the cooperative level result = IDirectSound_SetCooperativeLevel(dsound, win_window_list->hwnd, DSSCL_PRIORITY); if (result != DS_OK) { mame_printf_error(_WINDOWS("Error setting DirectSound cooperative level: %08x\n"), (UINT32)result); goto error; } // make a format description for what we want stream_format.wBitsPerSample = 16; stream_format.wFormatTag = WAVE_FORMAT_PCM; stream_format.nChannels = 2; stream_format.nSamplesPerSec = machine.sample_rate(); stream_format.nBlockAlign = stream_format.wBitsPerSample * stream_format.nChannels / 8; stream_format.nAvgBytesPerSec = stream_format.nSamplesPerSec * stream_format.nBlockAlign; // compute the buffer size based on the output sample rate stream_buffer_size = stream_format.nSamplesPerSec * stream_format.nBlockAlign * downcast<windows_options &>(machine.options()).audio_latency() / 10; stream_buffer_size = (stream_buffer_size / 1024) * 1024; if (stream_buffer_size < 1024) stream_buffer_size = 1024; LOG(("stream_buffer_size = %d\n", stream_buffer_size)); // create the buffers result = dsound_create_buffers(); if (result != DS_OK) goto error; // start playing result = IDirectSoundBuffer_Play(stream_buffer, 0, 0, DSBPLAY_LOOPING); if (result != DS_OK) { mame_printf_error(_WINDOWS("Error playing: %08x\n"), (UINT32)result); goto error; } return DS_OK; // error handling error: dsound_destroy_buffers(); dsound_kill(); return result; }
video_manager::video_manager(running_machine &machine) : m_machine(machine), m_screenless_frame_timer(nullptr), m_output_changed(false), m_throttle_last_ticks(0), m_throttle_realtime(attotime::zero), m_throttle_emutime(attotime::zero), m_throttle_history(0), m_speed_last_realtime(0), m_speed_last_emutime(attotime::zero), m_speed_percent(1.0), m_overall_real_seconds(0), m_overall_real_ticks(0), m_overall_emutime(attotime::zero), m_overall_valid_counter(0), m_throttled(machine.options().throttle()), m_throttle_rate(1.0f), m_fastforward(false), m_seconds_to_run(machine.options().seconds_to_run()), m_auto_frameskip(machine.options().auto_frameskip()), m_speed(original_speed_setting()), m_empty_skip_count(0), m_frameskip_level(machine.options().frameskip()), m_frameskip_counter(0), m_frameskip_adjust(0), m_skipping_this_frame(false), m_average_oversleep(0), m_snap_target(nullptr), m_snap_native(true), m_snap_width(0), m_snap_height(0), m_mng_frame_period(attotime::zero), m_mng_next_frame_time(attotime::zero), m_mng_frame(0), m_avi_file(nullptr), m_avi_frame_period(attotime::zero), m_avi_next_frame_time(attotime::zero), m_avi_frame(0), m_timecode_enabled(false), m_timecode_write(false), m_timecode_text(""), m_timecode_start(attotime::zero), m_timecode_total(attotime::zero) { // request a callback upon exiting machine.add_notifier(MACHINE_NOTIFY_EXIT, machine_notify_delegate(&video_manager::exit, this)); machine.save().register_postload(save_prepost_delegate(FUNC(video_manager::postload), this)); // extract initial execution state from global configuration settings update_refresh_speed(); // create a render target for snapshots const char *viewname = machine.options().snap_view(); m_snap_native = (machine.first_screen() != nullptr && (viewname[0] == 0 || strcmp(viewname, "native") == 0)); // the native target is hard-coded to our internal layout and has all options disabled if (m_snap_native) { m_snap_target = machine.render().target_alloc(&layout_snap, RENDER_CREATE_SINGLE_FILE | RENDER_CREATE_HIDDEN); m_snap_target->set_backdrops_enabled(false); m_snap_target->set_overlays_enabled(false); m_snap_target->set_bezels_enabled(false); m_snap_target->set_cpanels_enabled(false); m_snap_target->set_marquees_enabled(false); m_snap_target->set_screen_overlay_enabled(false); m_snap_target->set_zoom_to_screen(false); } // other targets select the specified view and turn off effects else { m_snap_target = machine.render().target_alloc(nullptr, RENDER_CREATE_HIDDEN); m_snap_target->set_view(m_snap_target->configured_view(viewname, 0, 1)); m_snap_target->set_screen_overlay_enabled(false); } // extract snap resolution if present if (sscanf(machine.options().snap_size(), "%dx%d", &m_snap_width, &m_snap_height) != 2) m_snap_width = m_snap_height = 0; // start recording movie if specified const char *filename = machine.options().mng_write(); if (filename[0] != 0) begin_recording(filename, MF_MNG); filename = machine.options().avi_write(); if (filename[0] != 0) begin_recording(filename, MF_AVI); // if no screens, create a periodic timer to drive updates if (machine.first_screen() == nullptr) { m_screenless_frame_timer = machine.scheduler().timer_alloc(timer_expired_delegate(FUNC(video_manager::screenless_update_callback), this)); m_screenless_frame_timer->adjust(screen_device::DEFAULT_FRAME_PERIOD, 0, screen_device::DEFAULT_FRAME_PERIOD); machine.output().set_notifier(nullptr, video_notifier_callback, this); } }
void address_map::uplift_submaps(running_machine &machine, device_t &device, device_t &owner, endianness_t endian) { address_map_entry *prev = 0; address_map_entry *entry = m_entrylist.first(); while (entry) { if (entry->m_read.m_type == AMH_DEVICE_SUBMAP) { astring tag; owner.subtag(tag, entry->m_read.m_tag); device_t *mapdevice = machine.device(tag); if (mapdevice == NULL) { throw emu_fatalerror("Attempted to submap a non-existent device '%s' in space %d of device '%s'\n", tag.cstr(), m_spacenum, device.basetag()); } // Grab the submap address_map submap(*mapdevice, entry); // Recursively uplift it if needed submap.uplift_submaps(machine, device, *mapdevice, endian); // Compute the unit repartition characteristics int entry_bits = entry->m_submap_bits; if (!entry_bits) entry_bits = m_databits; if (submap.m_databits != entry_bits) throw emu_fatalerror("AM_DEVICE wants a %d bits large address map and got a %d bits large one instead.\n", entry_bits, submap.m_databits); int entry_bytes = entry_bits / 8; int databytes = m_databits / 8; offs_t mirror_address_mask = (databytes - 1) & ~(entry_bytes - 1); UINT64 entry_mask = (2ULL << (entry_bits-1)) - 1; int slot_offset[8]; int slot_count = 0; int max_slot_count = m_databits / entry_bits; int slot_xor_mask = endian == ENDIANNESS_LITTLE ? 0 : max_slot_count - 1; UINT64 global_mask = entry->m_read.m_mask; // zero means all if (!global_mask) global_mask = ~global_mask; // mask consistency has already been checked in // unitmask_is_appropriate, so one bit is enough for (int slot=0; slot < max_slot_count; slot++) if (global_mask & (1ULL << ((slot ^ slot_xor_mask) * entry_bits))) slot_offset[slot_count++] = (slot ^ slot_xor_mask) * entry_bits; // Merge in all the map contents in order while (submap.m_entrylist.count()) { address_map_entry *subentry = submap.m_entrylist.detach_head(); // Remap start and end int start_offset = subentry->m_addrstart / entry_bytes; int start_slot = start_offset % slot_count; subentry->m_addrstart = entry->m_addrstart + (start_offset / slot_count) * databytes; // Drop the entry if it ends up outside the range if (subentry->m_addrstart > entry->m_addrend) { global_free(subentry); continue; } int end_offset = subentry->m_addrend / entry_bytes; int end_slot = end_offset % slot_count; subentry->m_addrend = entry->m_addrstart + (end_offset / slot_count) * databytes + databytes - 1; // Clip the entry to the end of the range if (subentry->m_addrend > entry->m_addrend || subentry->m_addrend < entry->m_addrstart) subentry->m_addrend = entry->m_addrend; // Detect special unhandled case (range straddling // slots, requiring splitting in multiple entries and // unimplemented offset-add subunit handler) if (subentry->m_addrstart + databytes - 1 != subentry->m_addrend && (start_slot != 0 || end_slot != slot_count - 1)) throw emu_fatalerror("uplift_submaps unhandled case: range straddling slots.\n"); if (entry->m_addrmask || subentry->m_addrmask) throw emu_fatalerror("uplift_submaps unhandled case: address masks.\n"); if (subentry->m_addrmirror & mirror_address_mask) throw emu_fatalerror("uplift_submaps unhandled case: address mirror bit within subentry.\n"); subentry->m_addrmirror |= entry->m_addrmirror; // Twiddle the unitmask on the data accessors that need it for (int data_entry = 0; data_entry < 2; data_entry++) { map_handler_data &mdata = data_entry ? subentry->m_write : subentry->m_read; if (mdata.m_type == AMH_NONE) continue; if (mdata.m_type != AMH_DEVICE_DELEGATE && mdata.m_type != AMH_NOP) throw emu_fatalerror("Only normal read/write methods are accepted in device submaps.\n"); if (mdata.m_bits == 0 && entry_bits != m_databits) mdata.m_bits = entry_bits; UINT64 mask = 0; if (entry_bits != m_databits) { UINT64 unitmask = mdata.m_mask ? mdata.m_mask : entry_mask; for (int slot = start_slot; slot <= end_slot; slot++) mask |= unitmask << slot_offset[slot]; } mdata.m_mask = mask; } // Insert the entry in the map m_entrylist.insert_after(*subentry, prev); prev = subentry; } address_map_entry *to_delete = entry; entry = entry->next(); m_entrylist.remove(*to_delete); } else { prev = entry; entry = entry->next(); } } }
static void orionpro_bank_switch(running_machine &machine) { orion_state *state = machine.driver_data<orion_state>(); address_space *space = machine.device("maincpu")->memory().space(AS_PROGRAM); int page = state->m_orionpro_page & 7; // we have only 8 pages int is128 = (state->m_orionpro_dispatcher & 0x80) ? 1 : 0; UINT8 *ram = ram_get_ptr(machine.device(RAM_TAG)); if (is128==1) { page = state->m_orionpro_128_page & 7; } space->install_write_bank(0x0000, 0x1fff, "bank1"); space->install_write_bank(0x2000, 0x3fff, "bank2"); space->install_write_bank(0x4000, 0x7fff, "bank3"); space->install_write_bank(0x8000, 0xbfff, "bank4"); space->install_write_bank(0xc000, 0xefff, "bank5"); space->install_write_bank(0xf000, 0xf3ff, "bank6"); space->install_write_bank(0xf400, 0xf7ff, "bank7"); space->install_write_bank(0xf800, 0xffff, "bank8"); if ((state->m_orionpro_dispatcher & 0x01)==0x00) { // RAM0 segment disabled memory_set_bankptr(machine, "bank1", ram + 0x10000 * page); memory_set_bankptr(machine, "bank2", ram + 0x10000 * page + 0x2000); } else { memory_set_bankptr(machine, "bank1", ram + (state->m_orionpro_ram0_segment & 31) * 0x4000); memory_set_bankptr(machine, "bank2", ram + (state->m_orionpro_ram0_segment & 31) * 0x4000 + 0x2000); } if ((state->m_orionpro_dispatcher & 0x10)==0x10) { // ROM1 enabled space->unmap_write(0x0000, 0x1fff); memory_set_bankptr(machine, "bank1", machine.region("maincpu")->base() + 0x20000); } if ((state->m_orionpro_dispatcher & 0x08)==0x08) { // ROM2 enabled space->unmap_write(0x2000, 0x3fff); memory_set_bankptr(machine, "bank2", machine.region("maincpu")->base() + 0x22000 + (state->m_orionpro_rom2_segment & 7) * 0x2000); } if ((state->m_orionpro_dispatcher & 0x02)==0x00) { // RAM1 segment disabled memory_set_bankptr(machine, "bank3", ram + 0x10000 * page + 0x4000); } else { memory_set_bankptr(machine, "bank3", ram + (state->m_orionpro_ram1_segment & 31) * 0x4000); } if ((state->m_orionpro_dispatcher & 0x04)==0x00) { // RAM2 segment disabled memory_set_bankptr(machine, "bank4", ram + 0x10000 * page + 0x8000); } else { memory_set_bankptr(machine, "bank4", ram + (state->m_orionpro_ram2_segment & 31) * 0x4000); } memory_set_bankptr(machine, "bank5", ram + 0x10000 * page + 0xc000); if (is128) { memory_set_bankptr(machine, "bank6", ram + 0x10000 * 0 + 0xf000); space->install_legacy_write_handler(0xf400, 0xf4ff, FUNC(orion128_system_w)); space->install_legacy_write_handler(0xf500, 0xf5ff, FUNC(orion128_romdisk_w)); space->unmap_write(0xf600, 0xf6ff); space->install_legacy_write_handler(0xf700, 0xf7ff, FUNC(orion128_floppy_w)); space->install_legacy_read_handler(0xf400, 0xf4ff, FUNC(orion128_system_r)); space->install_legacy_read_handler(0xf500, 0xf5ff, FUNC(orion128_romdisk_r)); space->unmap_read(0xf600, 0xf6ff); space->install_legacy_read_handler(0xf700, 0xf7ff, FUNC(orion128_floppy_r)); space->install_legacy_write_handler(0xf800, 0xf8ff, FUNC(orion128_video_mode_w)); space->install_legacy_write_handler(0xf900, 0xf9ff, FUNC(orionpro_memory_page_w)); space->install_legacy_write_handler(0xfa00, 0xfaff, FUNC(orion128_video_page_w)); space->unmap_write(0xfb00, 0xfeff); space->install_legacy_write_handler(0xff00, 0xffff, FUNC(orionz80_sound_w)); memory_set_bankptr(machine, "bank8", ram + 0x10000 * 0 + 0xf800); } else { if ((state->m_orionpro_dispatcher & 0x40)==0x40) { // FIX F000 enabled memory_set_bankptr(machine, "bank6", ram + 0x10000 * 0 + 0xf000); memory_set_bankptr(machine, "bank7", ram + 0x10000 * 0 + 0xf400); memory_set_bankptr(machine, "bank8", ram + 0x10000 * 0 + 0xf800); } else { memory_set_bankptr(machine, "bank6", ram + 0x10000 * page + 0xf000); memory_set_bankptr(machine, "bank7", ram + 0x10000 * page + 0xf400); memory_set_bankptr(machine, "bank8", ram + 0x10000 * page + 0xf800); } } }
void emulator_info::draw_user_interface(running_machine& machine) { mame_machine_manager::instance()->ui().update_and_render(machine.render().ui_container()); }
static void snes_input_read( running_machine &machine ) { snes_state *state = machine.driver_data<snes_state>(); UINT8 ctrl1 = input_port_read(machine, "CTRLSEL") & 0x0f; UINT8 ctrl2 = (input_port_read(machine, "CTRLSEL") & 0xf0) >> 4; /* Check if lightgun has been chosen as input: if so, enable crosshair */ machine.scheduler().timer_set(attotime::zero, FUNC(lightgun_tick)); switch (ctrl1) { case 1: /* SNES joypad */ snes_input_read_joy(machine, 0); break; case 2: /* SNES Mouse */ snes_input_read_mouse(machine, 0); break; case 3: /* SNES Superscope */ snes_input_read_superscope(machine, 0); break; case 0: /* no controller in port1 */ default: state->m_data1[0] = 0; state->m_data2[0] = 0; break; } switch (ctrl2) { case 1: /* SNES joypad */ snes_input_read_joy(machine, 1); break; case 2: /* SNES Mouse */ snes_input_read_mouse(machine, 1); break; case 3: /* SNES Superscope */ snes_input_read_superscope(machine, 1); break; case 0: /* no controller in port2 */ default: state->m_data1[1] = 0; state->m_data2[1] = 0; break; } // is automatic reading on? if so, copy port data1/data2 to joy1l->joy4h // this actually works like reading the first 16bits from oldjoy1/2 in reverse order if (snes_ram[NMITIMEN] & 1) { state->m_joy1l = (state->m_data1[0] & 0x00ff) >> 0; state->m_joy1h = (state->m_data1[0] & 0xff00) >> 8; state->m_joy2l = (state->m_data1[1] & 0x00ff) >> 0; state->m_joy2h = (state->m_data1[1] & 0xff00) >> 8; state->m_joy3l = (state->m_data2[0] & 0x00ff) >> 0; state->m_joy3h = (state->m_data2[0] & 0xff00) >> 8; state->m_joy4l = (state->m_data2[1] & 0x00ff) >> 0; state->m_joy4h = (state->m_data2[1] & 0xff00) >> 8; // make sure read_idx starts returning all 1s because the auto-read reads it :-) state->m_read_idx[0] = 16; state->m_read_idx[1] = 16; }