// interface-level overrides //------------------------------------------------- // interface_validity_check - validation for a // device after the configuration has been // constructed //------------------------------------------------- protected override void interface_validity_check(validity_checker valid) { // validate the interrupts if (m_vblank_interrupt != null) { screen_device_iterator iter = new screen_device_iterator(device().mconfig().root_device()); if (iter.first() == null) { osd_printf_error("VBLANK interrupt specified, but the driver is screenless\n"); } else if (m_vblank_interrupt_screen != null && device().siblingdevice(m_vblank_interrupt_screen) == null) { osd_printf_error("VBLANK interrupt references a nonexistant screen tag '{0}'\n", m_vblank_interrupt_screen); } } if (m_timed_interrupt != null && m_timed_interrupt_period == attotime.zero) { osd_printf_error("Timed interrupt handler specified with 0 period\n"); } else if (m_timed_interrupt == null && m_timed_interrupt_period != attotime.zero) { osd_printf_error("No timer interrupt handler specified, but has a non-0 period given\n"); } }
//template <typename T, typename F, typename U> void configure_scanline(T &&target, F &&callback, const char *name, U &&screen, int first_vpos, int increment) //{ // m_type = TIMER_TYPE_SCANLINE; // m_callback.set(std::forward<T>(target), std::forward<F>(callback), name); // m_screen.set_tag(std::forward<U>(screen)); // m_first_vpos = first_vpos; // m_increment = increment; //} //template <typename Object> void set_callback(Object &&cb) { m_callback = std::forward<Object>(cb); } //template <class FunctionClass> void set_callback(void (FunctionClass::*callback)(timer_device &, void *, s32), const char *name) //{ // set_callback(expired_delegate(callback, name, nullptr, static_cast<FunctionClass *>(nullptr))); //} //void set_start_delay(const attotime &delay) { m_start_delay = delay; } //void config_param(int param) { m_param = param; } // property getters //int param() const { return m_timer->param(); } //void *ptr() const { return m_ptr; } //bool enabled() const { return m_timer->enabled(); } // property setters //void set_param(int param) { assert(m_type == TIMER_TYPE_GENERIC); m_timer->set_param(param); } //void set_ptr(void *ptr) { m_ptr = ptr; } //void enable(bool enable = true) { m_timer->enable(enable); } // adjustments //void reset() { adjust(attotime::never, 0, attotime::never); } //void adjust(const attotime &duration, INT32 param = 0, const attotime &period = attotime::never) { assert(m_type == TIMER_TYPE_GENERIC); m_timer->adjust(duration, param, period); } // timing information //attotime time_elapsed() const { return m_timer->elapsed(); } //attotime time_left() const { return m_timer->remaining(); } //attotime start_time() const { return m_timer->start(); } //attotime fire_time() const { return m_timer->expire(); } // device-level overrides //------------------------------------------------- // device_validity_check - validate the device // configuration //------------------------------------------------- protected override void device_validity_check(validity_checker valid) { // type based configuration switch (m_type) { case timer_type.TIMER_TYPE_GENERIC: if (m_screen.finder_tag() != finder_base.DUMMY_TAG || m_first_vpos != 0 || m_start_delay != attotime.zero) { osd_printf_warning("Generic timer specified parameters for a scanline timer\n"); } if (m_period != attotime.zero || m_start_delay != attotime.zero) { osd_printf_warning("Generic timer specified parameters for a periodic timer\n"); } break; case timer_type.TIMER_TYPE_PERIODIC: if (m_screen.finder_tag() != finder_base.DUMMY_TAG || m_first_vpos != 0) { osd_printf_warning("Periodic timer specified parameters for a scanline timer\n"); } if (m_period <= attotime.zero) { osd_printf_error("Periodic timer specified invalid period\n"); } break; case timer_type.TIMER_TYPE_SCANLINE: if (m_period != attotime.zero || m_start_delay != attotime.zero) { osd_printf_warning("Scanline timer specified parameters for a periodic timer\n"); } if (m_param != 0) { osd_printf_warning("Scanline timer specified parameter which is ignored\n"); } // if (m_first_vpos < 0) // osd_printf_error("Scanline timer specified invalid initial position\n"); // if (m_increment < 0) // osd_printf_error("Scanline timer specified invalid increment\n"); break; default: osd_printf_error("Invalid type specified\n"); break; } }
//int inputnum_from_device(device_t &device, int outputnum = 0) const; // configuration access //std::vector<sound_route> &routes() { return m_route_list; } // optional operation overrides //------------------------------------------------- // interface_validity_check - validation for a // device after the configuration has been // constructed //------------------------------------------------- protected override void interface_validity_check(validity_checker valid) { // loop over all the routes foreach (sound_route route in routes()) { // find a device with the requested tag device_t target = route.m_base.subdevice(route.m_target); if (target == null) { osd_printf_error("Attempting to route sound to non-existent device '{0}'\n", route.m_base.subtag(route.m_target)); } // if it's not a speaker or a sound device, error device_sound_interface sound; if (target != null && (target.type() != speaker_device.SPEAKER) && !target.interface_(out sound)) { osd_printf_error("Attempting to route sound to a non-sound device '{0}' ({1})\n", target.tag(), target.name()); } } }
/* execute as configured by the OPTION_SYSTEMNAME option on the specified options */ //------------------------------------------------- // execute - run the core emulation //------------------------------------------------- public int execute() { bool started_empty = false; bool firstgame = true; // loop across multiple hard resets bool exit_pending = false; int error = EMU_ERR_NONE; while (error == EMU_ERR_NONE && !exit_pending) { m_new_driver_pending = null; // if no driver, use the internal empty driver game_driver system = mame_options.system(m_options); if (system == null) { system = ___empty.driver____empty; if (firstgame) { started_empty = true; } } firstgame = false; // parse any INI files as the first thing if (m_options.read_config()) { // but first, revert out any potential game-specific INI settings from previous runs via the internal UI m_options.revert(OPTION_PRIORITY_INI); string errors; mame_options.parse_standard_inis(m_options, out errors); } // otherwise, perform validity checks before anything else bool is_empty = system == ___empty.driver____empty; if (!is_empty) { validity_checker valid = new validity_checker(m_options, true); valid.set_verbose(false); valid.check_shared_source(system); valid.Dispose(); } // create the machine configuration machine_config config = new machine_config(system, m_options); // create the machine structure and driver running_machine machine = new running_machine(config, this); set_machine(machine); // run the machine error = machine.run(is_empty); m_firstrun = false; // check the state of the machine if (m_new_driver_pending != null) { // set up new system name and adjust device options accordingly m_options.set_system_name(m_new_driver_pending.name); m_firstrun = true; } else { if (machine.exit_pending()) { m_options.set_system_name(""); } } if (machine.exit_pending() && (!started_empty || is_empty)) { exit_pending = true; } // machine will go away when we exit scope machine.Dispose(); set_machine(null); } // return an error return(error); }
//void set_gfx(int index, gfx_element *element) { assert(index < MAX_GFX_ELEMENTS); m_gfx[index].reset(element); } // interface-level overrides //------------------------------------------------- // interface_validity_check - validate graphics // decoding configuration //------------------------------------------------- protected override void interface_validity_check(validity_checker valid) { if (!m_palette_is_disabled && m_paletteDevice == null) { KeyValuePair <device_t, string> target = m_paletteDevice.finder_target(); if (target.second() == finder_base.DUMMY_TAG) { osd_printf_error("No palette specified for device '{0}'\n", device().tag()); } else { osd_printf_error( "Device '{0}' specifies nonexistent device '{1}' relative to '{2}' as palette\n", device().tag(), target.second(), target.first().tag()); } } if (m_gfxdecodeinfo == null) { return; } // validate graphics decoding entries for (int gfxnum = 0; gfxnum < digfx_global.MAX_GFX_ELEMENTS && m_gfxdecodeinfo[gfxnum].gfxlayout != null; gfxnum++) { gfx_decode_entry gfx = m_gfxdecodeinfo[gfxnum]; gfx_layout layout = gfx.gfxlayout; // currently we are unable to validate RAM-based entries string region = gfx.memory_region; if (region != null && GFXENTRY_ISROM(gfx.flags)) { // resolve the region string gfxregion; if (GFXENTRY_ISDEVICE(gfx.flags)) { gfxregion = device().subtag(region); } else { gfxregion = device().owner().subtag(region); } UInt32 region_length = (UInt32)valid.region_length(gfxregion); if (region_length == 0) { osd_printf_error("gfx[{0}] references nonexistent region '{1}'\n", gfxnum, gfxregion); } // if we have a valid region, and we're not using auto-sizing, check the decode against the region length else if (!IS_FRAC(layout.total)) { // determine which plane is at the largest offset int start = 0; for (int plane = 0; plane < layout.planes; plane++) { if (layout.planeoffset[plane] > start) { start = (int)layout.planeoffset[plane]; } } start &= ~(int)(layout.charincrement - 1); // determine the total length based on this info int len = (int)(layout.total * layout.charincrement); // do we have enough space in the region to cover the whole decode? int avail = (int)(region_length - (gfx.start & ~(layout.charincrement / 8 - 1))); // if not, this is an error if ((start + len) / 8 > avail) { osd_printf_error("gfx[{0}] extends past allocated memory of region '{1}'\n", gfxnum, region); } } } int xscale = (int)GFXENTRY_GETXSCALE(gfx.flags); int yscale = (int)GFXENTRY_GETYSCALE(gfx.flags); // verify raw decode, which can only be full-region and have no scaling if (layout.planeoffset[0] == digfx_global.GFX_RAW) { if (layout.total != RGN_FRAC(1, 1)) { osd_printf_error("gfx[{0}] RAW layouts can only be RGN_FRAC(1,1)\n", gfxnum); } if (xscale != 1 || yscale != 1) { osd_printf_error("gfx[{0}] RAW layouts do not support xscale/yscale\n", gfxnum); } } // verify traditional decode doesn't have too many planes, // and has extended offset arrays if its width and/or height demand them else { throw new emu_unimplemented(); } } }
protected override void interface_validity_check(validity_checker valid) { throw new emu_unimplemented(); }