(nw) add doxygen comments for a bunch of core stuff, and convert a bunch of comments to doxygen format

This commit is contained in:
Vas Crabb 2019-10-16 18:31:48 +11:00
parent 151f5fca25
commit 063e81d756
14 changed files with 562 additions and 318 deletions

View File

@ -140,12 +140,12 @@ public:
// construction/destruction
virtual ~device_a2bus_card_interface();
virtual uint8_t read_c0nx(uint8_t offset) { m_device.logerror("a2bus: unhandled read at C0n%x\n", offset); return 0; } // C0nX - /DEVSEL
virtual void write_c0nx(uint8_t offset, uint8_t data) { m_device.logerror("a2bus: unhandled write %02x to C0n%x\n", data, offset); }
virtual uint8_t read_c0nx(uint8_t offset) { device().logerror("a2bus: unhandled read at C0n%x\n", offset); return 0; } // C0nX - /DEVSEL
virtual void write_c0nx(uint8_t offset, uint8_t data) { device().logerror("a2bus: unhandled write %02x to C0n%x\n", data, offset); }
virtual uint8_t read_cnxx(uint8_t offset) { return 0; } // CnXX - /IOSEL
virtual void write_cnxx(uint8_t offset, uint8_t data) { m_device.logerror("a2bus: unhandled write %02x to Cn%02x\n", data, offset); }
virtual void write_cnxx(uint8_t offset, uint8_t data) { device().logerror("a2bus: unhandled write %02x to Cn%02x\n", data, offset); }
virtual uint8_t read_c800(uint16_t offset) { return 0; } // C800 - /IOSTB
virtual void write_c800(uint16_t offset, uint8_t data) {m_device.logerror("a2bus: unhandled write %02x to %04x\n", data, offset + 0xc800); }
virtual void write_c800(uint16_t offset, uint8_t data) {device().logerror("a2bus: unhandled write %02x to %04x\n", data, offset + 0xc800); }
virtual bool take_c800() { return true; } // override and return false if your card doesn't take over the c800 space
virtual uint8_t read_inh_rom(uint16_t offset) { return 0; }
virtual void write_inh_rom(uint16_t offset, uint8_t data) { }

View File

@ -117,7 +117,7 @@ public:
// reading and writing
virtual uint8_t read(offs_t offset) { return 0xff; }
virtual void write(offs_t offset, uint8_t data) { m_device.logerror("unhandled ROM write to %04X = %02X\n", offset | 0x8000, data); }
virtual void write(offs_t offset, uint8_t data) { device().logerror("unhandled ROM write to %04X = %02X\n", offset | 0x8000, data); }
void rom_alloc(uint32_t size, const char *tag);
void ram_alloc(uint32_t size);

View File

@ -106,8 +106,8 @@ public:
virtual int read_test() { return 0; } // used by Virtua Racing test
/* this probably should do more, like make Genesis V2 'die' if the SEGA string is not written promptly */
virtual DECLARE_WRITE16_MEMBER(write_tmss_bank) { m_device.logerror("Write to TMSS bank: offset %x data %x\n", 0xa14000 + (offset << 1), data); };
// this probably should do more, like make Genesis V2 'die' if the SEGA string is not written promptly
virtual DECLARE_WRITE16_MEMBER(write_tmss_bank) { device().logerror("Write to TMSS bank: offset %x data %x\n", 0xa14000 + (offset << 1), data); };
virtual void rom_alloc(size_t size, const char *tag);
virtual void nvram_alloc(size_t size);

View File

@ -369,4 +369,4 @@ inline attotime attotime::from_double(double _time)
}
#endif // MAME_EMU_ATTOTIME_H
#endif // MAME_EMU_ATTOTIME_H

View File

@ -1,13 +1,9 @@
// license:BSD-3-Clause
// copyright-holders:Aaron Giles, Vas Crabb
/**
* \file devfind.h
* Object auto-discovery helpers
* \defgroup devfind
* \{
* Object auto-discovery helpers
*/
/// \file
/// \brief Object auto-discovery helpers
/// \defgroup devfind Object auto-discovery helpers
/// \{
#ifndef __EMU_H__
#error Dont include this file directly; include emu.h instead.
#endif
@ -1212,4 +1208,4 @@ extern template class shared_ptr_finder<s64, false>;
extern template class shared_ptr_finder<s64, true>;
#endif // MAME_EMU_DEVFIND_H
/** \} */
/// \}

View File

@ -489,7 +489,34 @@ public:
// device flags
using feature = emu::detail::device_feature;
using feature_type = emu::detail::device_feature::type;
/// \brief Report unemulated features
///
/// Implement this member in a derived class to declare features
/// that are not emulated. This will propagate to all other devices
/// and systems that use the device. Unemulated features are shown
/// in the system selection UI, and cause a red warning to be
/// displayed on starting a system.
/// \return Bitwise or of the feature constants for unemulated
/// features of the device.
/// \sa imperfect_features
static constexpr feature_type unemulated_features() { return feature::NONE; }
/// \brief Report imperfectly emulated features
///
/// Implement this member in a derived class to declare features
/// that are imperfectly emulated. This will propagate to all other
/// devices and systems that use the device. Imperfectly emulated
/// features are shown in the system selection UI, and cause a
/// yellow warning to be displayed on starting a system (provided
/// there are no unemulated features, which take precedence and
/// cause the warning to be red).
///
/// An exception is imperfectly emulated protection, which results
/// in a red warning being displayed when starting a system.
/// \return Bitwise or of the feature constants for imperfectly
/// emulated features of the device.
/// \sa unemulated_features
static constexpr feature_type imperfect_features() { return feature::NONE; }
virtual ~device_t();
@ -616,15 +643,132 @@ protected:
virtual const tiny_rom_entry *device_rom_region() const;
virtual void device_add_mconfig(machine_config &config);
virtual ioport_constructor device_input_ports() const;
/// \brief Finalise device configuration
///
/// Perform any final configuration tasks after all devices in the
/// system have added machine configuration. This is called after
/// any #device_interface mix-in interface_config_complete members
/// have completed.
///
/// Note that automatic object finders will not have been resolved
/// at the time this member is called.
virtual void device_config_complete();
/// \brief Additional device validity checks
///
/// Implement this member to provide additional validity checks.
/// Report errors using #osd_printf_error and report warnings using
/// #osd_printf_warning. The system being validated, device type
/// and device tag are collected automatically. Do not throw
/// exceptions to report errors.
///
/// This provides an opportunity to check that the device has been
/// configured correctly. Systems are validated on start, and also
/// when the user manually runs a validity check. Validity checks
/// are only run for devices configured in runnable systems, not
/// when checking that a device can be instantiated in isolation.
/// \param [in] valid Reference to the validity checker object
/// performing validation (provides some helper member functions).
/// \sa device_interface::interface_validity_check
virtual void device_validity_check(validity_checker &valid) const ATTR_COLD;
/// \brief Resolve objects that may be needed while starting
///
/// Implement this member to complete object resolution before any
/// devices are started. For example it may be necessary to resolve
/// callbacks before any devices start so initial input conditions
/// can be set. This is called after all registerd automatic object
/// finders are resolved.
virtual void device_resolve_objects() ATTR_COLD;
/// \brief Device start handler
///
/// Implement this member to set up the initial state of the device
/// on start. This will be called after all #device_interface
// /mix-in interface_pre_start members have completed successfully.
/// If the device can't start until another device has completed
/// starting, throw a #device_missing_dependencies exception.
/// Starting will be postponed until additional devices have been
/// started.
///
/// If a device's base class is not device_t, it's good practice to
/// check start order dependencies (and throw
/// #device_missing_dependencies if necessary) before calling the
/// base implementation. This will ensure that the base
/// implementation won't be called twice if starting needs to be
/// postponed.
///
/// This is the correct place to register for save states.
/// \sa device_reset device_stop
/// device_interface::interface_pre_start
/// device_interface::interface_post_start
virtual void device_start() ATTR_COLD = 0;
/// \brief Device stop handler
///
/// Implement this member to perform additional tasks on ending an
/// emulation session. You may deallocate memory here. This is
/// called after interface_pre_stop is called for all
/// #device_interface mix-ins, and before interface_post_stop is
/// called for any #device_interface mix-ins.
/// \sa device_interface::interface_pre_stop
/// device_interface::interface_post_stop
virtual void device_stop() ATTR_COLD;
/// \brief Device reset handler
///
/// Implement this member to provide reset behaviour. This is
/// called after all #device_interface mix-in interface_pre_reset
/// members have completed, and before any child devices are reset.
/// All devices are reset at the beginning of an emulation session
/// (after all devices have been started), and also when the user
/// requests a soft reset (by pressing F3 by default, and also
/// available from the debugger).
///
/// Note that child devices are reset automatically when a device is
/// reset. You should not reset child devices manually from this
/// member. If you need to provide additional behaviour after child
/// devices are reset, implement #device_reset_after_children.
///
/// Only implement warm reset behaviour in this member. Initial
/// cold reset conditions should be set up in #device_start.
/// \sa device_reset_after_children device_start
/// device_interface::interface_pre_reset
/// device_interface::interface_post_reset
virtual void device_reset() ATTR_COLD;
/// \brief Additional reset behaviour after child device reset
///
/// Implement this member to provide additional reset behaviour
/// after child devices are reset. This is called when resetting a
/// device after #device_reset has been called and all child devices
/// have been reset, and before any #device_interface mix-in
/// interface_post_reset members are called.
/// \sa device_reset device_interface::interface_pre_reset
/// device_interface::interface_post_reset
virtual void device_reset_after_children() ATTR_COLD;
/// \brief Prepare for a save state to be written
///
/// Implement this member to perform any tasks necessary before any
/// registered save state items are recorded. For example it may be
/// necessary to flush caches, serialise self-referencing members or
/// pointers into data structures. This is called after all
/// #device_interface mix-in interface_pre_save members are called.
/// \sa device_post_load device_interface::interface_pre_save
virtual void device_pre_save() ATTR_COLD;
/// \brief Complete save state loading
///
/// Implement this member to perform any tasks necessary after
/// registered save state items are loaded. For example it may be
/// necessary to update or invalidate caches, or de-serialise
/// pointers into data structures. This is called after all
/// #device_interface mix-in interface_post_load members are called.
/// \sa device_pre_save device_interface::interface_post_load
virtual void device_post_load() ATTR_COLD;
virtual void device_clock_changed();
virtual void device_debug_setup();
virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
@ -677,9 +821,12 @@ private:
};
// ======================> device_interface
// device_interface represents runtime information for a particular device interface
/// \brief Device mix-in base
///
/// Provides a base for #device_t mix-ins that integrate with the device
/// lifecycle. Derived classes are used to implement a number of
/// standard concepts and interfaces, and integrate with the scheduler,
/// debugger and user interface.
class device_interface
{
DISABLE_COPYING(device_interface);
@ -701,24 +848,138 @@ public:
device_interface *interface_next() const { return m_interface_next; }
// optional operation overrides
//
// WARNING: interface_pre_start must be callable multiple times in
// case another interface throws a missing dependency. In
// particular, state saving registrations should be done in post.
/// \brief Finalise mix-in configuration
///
/// Perform any final configuration tasks after all devices in the
/// system have added machine configuration. This is called before
/// device_config_complete is called for the device.
///
/// Note that automatic object finders will not have been resolved
/// at this time.
/// \sa device_t::device_config_complete
virtual void interface_config_complete();
virtual void interface_validity_check(validity_checker &valid) const;
virtual void interface_pre_start();
virtual void interface_post_start();
virtual void interface_pre_reset();
virtual void interface_post_reset();
virtual void interface_pre_stop();
virtual void interface_post_stop();
virtual void interface_pre_save();
virtual void interface_post_load();
/// \brief Additional mix-in validity checks
///
/// Implement this member to provide additional validity checks.
/// Report errors using #osd_printf_error and report warnings using
/// #osd_printf_warning. The system being validated, device type
/// and device tag are collected automatically. Do not throw
/// exceptions to report errors.
///
/// This provides an opportunity to check that the mix-in has been
/// configured correctly. Systems are validated on start, and also
/// when the user manually runs a validity check. Validity checks
/// are only run for devices configured in runnable systems, not
/// when checking that a device can be instantiated in isolation.
/// \param [in] valid Reference to the validity checker object
/// performing validation (provides some helper member functions).
/// \sa device_t::device_validity_check
virtual void interface_validity_check(validity_checker &valid) const ATTR_COLD;
/// \brief Mix-in start handler
///
/// Implement this member to set up the initial state of the mix-in
/// on start. This is called before the device_start member is
/// called for the device. If the mix-in can't be started until
/// another device has started, throw a #device_missing_dependencies
/// exception. Starting will be postponed until additional devices
/// have been started.
///
/// Note that this member may be called multiple times if another
/// device_interface mix-in throws a #device_missing_dependencies
/// exception from its interface_pre_start member, or if the device
/// throws a #device_missing_dependencies exception from its
/// device_start member. You must check to ensure that operations
/// like resource allocation are not performed multiple times, or
/// postpone them until #interface_post_start is called.
///
/// It's simpler to register for save states when
/// #interface_post_start is called.
/// \sa interface_post_start device_t::device_start
virtual void interface_pre_start() ATTR_COLD;
/// \brief Mix-in start completion handler
///
/// Implement this member to complete mix-in start-up. This is
/// called after #interface_pre_start is called for all
/// device_interface mix-ins, and after device_start is called for
/// the device. This member will only be called once, it will not
/// be called multiple times if device starting is postponed.
///
/// This member must not throw #device_missing_dependencies (start
/// order dependencies should be checked in #interface_pre_start).
/// This is the appropriate place to allocate resources like
/// timers and register for save states.
/// \sa interface_pre_start device_t::device_start
virtual void interface_post_start() ATTR_COLD;
/// \brief Mix-in reset handler
///
/// Implement this member to provide reset behaviour. This is
/// called before device_reset is called for the device, and before
/// any child devices are reset. Only implement warm reset
/// behaviour in this member. Initial cold reset conditions should
/// be set up in #interface_pre_start and/or #interface_post_start.
/// If you need to provide additional behaviour after child devices
/// are reset, implement #interface_post_reset.
/// \sa interface_post_reset device_t::device_reset
virtual void interface_pre_reset() ATTR_COLD;
/// \brief Mix-in reset completion handler
///
/// Implement this member to provide additional reset behaviour
/// after child devices are reset. This is called after
/// device_reset_after_children has been called for the device.
/// \sa interface_pre_reset device_t::device_reset
/// device_t::device_reset_after_children
virtual void interface_post_reset() ATTR_COLD;
/// \brief Mix-in stop handler
///
/// Implement this member to perform additional tasks on ending an
/// emulation session. Do not deallocate anything that may need to
/// be referenced from another device_interface mix-in's
/// interface_pre_stop member or from the device's device_stop
/// member. This is called before device_stop is called for the
/// device.
/// \sa interface_post_stop device_t::device_stop
virtual void interface_pre_stop() ATTR_COLD;
/// \brief Mix-in stop completion handler
///
/// Implement this member to perform additional tasks on ending an
/// emulation session after the device is stopped. You can
/// deallocate memory here. This is called after device_stop is
/// called for the device.
/// \sa interface_pre_stop device_t::device_stop
virtual void interface_post_stop() ATTR_COLD;
/// \brief Prepare for a save state to be written
///
/// Implement this member to perform any tasks necessary before any
/// registered save state items are recorded. For example it may be
/// necessary to flush caches, serialise self-referencing members or
/// pointers into data structures. This is called before
/// device_pre_save is called for the device.
/// \sa interface_post_load device_t::device_pre_save
virtual void interface_pre_save() ATTR_COLD;
/// \brief Complete save state loading
///
/// Implement this member to perform any tasks necessary after
/// registered save state items are loaded. For example it may be
/// necessary to update or invalidate caches, or de-serialise
/// pointers into data structures. This is called before
/// device_post_load is called for the device.
/// \sa interface_pre_save device_t::device_post_load
virtual void interface_post_load() ATTR_COLD;
virtual void interface_clock_changed();
virtual void interface_debug_setup();
protected:
private:
// internal state
device_interface * m_interface_next;
device_t & m_device;

View File

@ -85,8 +85,8 @@ int device_sound_interface::inputs() const
{
// scan the list counting streams we own and summing their inputs
int inputs = 0;
for (auto &stream : m_device.machine().sound().streams())
if (&stream->device() == &m_device)
for (auto &stream : device().machine().sound().streams())
if (&stream->device() == &device())
inputs += stream->input_count();
return inputs;
}
@ -101,8 +101,8 @@ int device_sound_interface::outputs() const
{
// scan the list counting streams we own and summing their outputs
int outputs = 0;
for (auto &stream : m_device.machine().sound().streams())
if (&stream->device() == &m_device)
for (auto &stream : device().machine().sound().streams())
if (&stream->device() == &device())
outputs += stream->output_count();
return outputs;
}
@ -119,8 +119,8 @@ sound_stream *device_sound_interface::input_to_stream_input(int inputnum, int &s
assert(inputnum >= 0);
// scan the list looking for streams owned by this device
for (auto &stream : m_device.machine().sound().streams())
if (&stream->device() == &m_device)
for (auto &stream : device().machine().sound().streams())
if (&stream->device() == &device())
{
if (inputnum < stream->input_count())
{
@ -146,7 +146,7 @@ sound_stream *device_sound_interface::output_to_stream_output(int outputnum, int
assert(outputnum >= 0);
// scan the list looking for streams owned by this device
for (auto &stream : m_device.machine().sound().streams())
for (auto &stream : device().machine().sound().streams())
if (&stream->device() == &device())
{
if (outputnum < stream->output_count())
@ -212,7 +212,7 @@ void device_sound_interface::set_output_gain(int outputnum, float gain)
// handle ALL_OUTPUTS as a special case
if (outputnum == ALL_OUTPUTS)
{
for (auto &stream : m_device.machine().sound().streams())
for (auto &stream : device().machine().sound().streams())
if (&stream->device() == &device())
for (int num = 0; num < stream->output_count(); num++)
stream->set_output_gain(num, gain);
@ -237,7 +237,7 @@ void device_sound_interface::set_output_gain(int outputnum, float gain)
int device_sound_interface::inputnum_from_device(device_t &source_device, int outputnum) const
{
int overall = 0;
for (auto &stream : m_device.machine().sound().streams())
for (auto &stream : device().machine().sound().streams())
if (&stream->device() == &device())
for (int inputnum = 0; inputnum < stream->input_count(); inputnum++, overall++)
if (stream->input_source_device(inputnum) == &source_device && stream->input_source_outputnum(inputnum) == outputnum)
@ -278,7 +278,7 @@ void device_sound_interface::interface_validity_check(validity_checker &valid) c
void device_sound_interface::interface_pre_start()
{
// scan all the sound devices
sound_interface_iterator iter(m_device.machine().root_device());
sound_interface_iterator iter(device().machine().root_device());
for (device_sound_interface const &sound : iter)
{
// scan each route on the device
@ -286,7 +286,7 @@ void device_sound_interface::interface_pre_start()
{
// see if we are the target of this route; if we are, make sure the source device is started
device_t *const target_device = route.m_base.get().subdevice(route.m_target.c_str());
if ((target_device == &m_device) && !sound.device().started())
if ((target_device == &device()) && !sound.device().started())
throw device_missing_dependencies();
}
}
@ -300,7 +300,7 @@ void device_sound_interface::interface_pre_start()
{
// see if we are the target of this route
device_t *const target_device = route.m_base.get().subdevice(route.m_target.c_str());
if ((target_device == &m_device) && (route.m_input == AUTO_ALLOC_INPUT))
if ((target_device == &device()) && (route.m_input == AUTO_ALLOC_INPUT))
{
route.m_input = m_auto_allocated_inputs;
m_auto_allocated_inputs += (route.m_output == ALL_OUTPUTS) ? sound.outputs() : 1;
@ -318,14 +318,14 @@ void device_sound_interface::interface_pre_start()
void device_sound_interface::interface_post_start()
{
// iterate over all the sound devices
for (device_sound_interface &sound : sound_interface_iterator(m_device.machine().root_device()))
for (device_sound_interface &sound : sound_interface_iterator(device().machine().root_device()))
{
// scan each route on the device
for (sound_route const &route : sound.routes())
{
// if we are the target of this route, hook it up
device_t *const target_device = route.m_base.get().subdevice(route.m_target.c_str());
if (target_device == &m_device)
if (target_device == &device())
{
// iterate over all outputs, matching any that apply
int inputnum = route.m_input;
@ -343,7 +343,7 @@ void device_sound_interface::interface_post_start()
int streaminputnum;
sound_stream *const inputstream = input_to_stream_input(inputnum++, streaminputnum);
if (!inputstream)
fatalerror("Sound device '%s' targeted output #%d to nonexistent device '%s' input %d\n", sound.device().tag(), outputnum, m_device.tag(), inputnum - 1);
fatalerror("Sound device '%s' targeted output #%d to nonexistent device '%s' input %d\n", sound.device().tag(), outputnum, device().tag(), inputnum - 1);
// set the input
inputstream->set_input(streaminputnum, outputstream, streamoutputnum, route.m_gain);
@ -362,7 +362,7 @@ void device_sound_interface::interface_post_start()
void device_sound_interface::interface_pre_reset()
{
// update all streams on this device prior to reset
for (auto &stream : m_device.machine().sound().streams())
for (auto &stream : device().machine().sound().streams())
if (&stream->device() == &device())
stream->update();
}
@ -415,7 +415,7 @@ void device_mixer_interface::interface_pre_start()
m_outputmap.resize(m_auto_allocated_inputs);
// iterate through all routes that point to us and note their mixer output
for (device_sound_interface const &sound : sound_interface_iterator(m_device.machine().root_device()))
for (device_sound_interface const &sound : sound_interface_iterator(device().machine().root_device()))
{
for (sound_route const &route : sound.routes())
{

View File

@ -624,7 +624,7 @@ void device_state_interface::interface_post_start()
{
// make sure we got something during startup
if (m_state_list.size() == 0)
throw emu_fatalerror("No state registered for device '%s' that supports it!", m_device.tag());
throw emu_fatalerror("No state registered for device '%s' that supports it!", device().tag());
}

View File

@ -373,4 +373,4 @@ inline u64 d2u(double d)
return u.vv;
}
#endif /* MAME_EMU_EMUCORE_H */
#endif // MAME_EMU_EMUCORE_H

View File

@ -940,7 +940,7 @@ static DISCRETE_SOUND_START(boothill_discrete)
/************************************************
* Shot sounds
************************************************/
/* Noise clock was breadboarded and measured at 7700Hz */
// Noise clock was breadboarded and measured at 7700Hz
DISCRETE_LFSR_NOISE(BOOTHILL_NOISE, 1, 1, 7700, 12.0, 0, 12.0/2, &midway_lfsr)
DISCRETE_OP_AMP_TRIG_VCA(NODE_30, BOOTHILL_LEFT_SHOT_EN, 0, 0, BOOTHILL_NOISE, 0, &boothill_shot_tvca_info)
@ -977,8 +977,8 @@ static DISCRETE_SOUND_START(boothill_discrete)
DISCRETE_MIXER2(NODE_91, BOOTHILL_GAME_ON_EN, BOOTHILL_L_SHOT_SND, BOOTHILL_L_HIT_SND, &boothill_l_mixer)
/* Music is only added to the right channel per schematics */
/* This should be verified on the real game */
// Music is only added to the right channel per schematics
// This should be verified on the real game
DISCRETE_MIXER3(NODE_92, BOOTHILL_GAME_ON_EN, BOOTHILL_R_SHOT_SND, BOOTHILL_R_HIT_SND, MIDWAY_TONE_SND, &boothill_r_mixer)
DISCRETE_OUTPUT(NODE_91, 1)

View File

@ -1407,8 +1407,7 @@ void a7800_state::a7800_ntsc(machine_config &config)
A78_CART_SLOT(config, "cartslot", a7800_cart, nullptr);
/* software lists */
SOFTWARE_LIST(config, "cart_list").set_original("a7800");
subdevice<software_list_device>("cart_list")->set_filter("NTSC");
SOFTWARE_LIST(config, "cart_list").set_original("a7800").set_filter("NTSC");
}
void a7800_pal_state::a7800_pal(machine_config &config)

View File

@ -109,6 +109,9 @@ bool posix_check_ptty_path(std::string const &path)
osd_file::error posix_open_ptty(std::uint32_t openflags, osd_file::ptr &file, std::uint64_t &filesize, std::string &name)
{
#if defined(__ANDROID__)
return osd_file::error::FAILURE;
#else // defined(__ANDROID__)
#if (defined(sun) || defined(__sun)) && (defined(__SVR4) || defined(__svr4__))
int access = O_NOCTTY;
if (openflags & OPEN_FLAG_WRITE)
@ -145,9 +148,6 @@ osd_file::error posix_open_ptty(std::uint32_t openflags, osd_file::ptr &file, st
::close(masterfd);
return errno_to_file_error(err);
}
#elif defined(__ANDROID__)
int masterfd = -1, slavefd = -1;
char slavepath[PATH_MAX];
#else
struct termios tios;
std::memset(&tios, 0, sizeof(tios));
@ -188,4 +188,5 @@ osd_file::error posix_open_ptty(std::uint32_t openflags, osd_file::ptr &file, st
::close(masterfd);
return osd_file::error::OUT_OF_MEMORY;
}
#endif // defined(__ANDROID__)
}

View File

@ -90,13 +90,13 @@ void osd_free_executable(void *ptr, size_t size)
void osd_break_into_debugger(const char *message)
{
#ifdef MAME_DEBUG
#ifdef MAME_DEBUG
printf("MAME exception: %s\n", message);
printf("Attempting to fall into debugger\n");
kill(getpid(), SIGTRAP);
#else
#else
printf("Ignoring MAME exception: %s\n", message);
#endif
#endif
}
#ifdef SDLMAME_ANDROID

View File

@ -1,18 +1,11 @@
// license:BSD-3-Clause
// copyright-holders:Aaron Giles
/***************************************************************************
osdcore.h
Core OS-dependent code interface.
****************************************************************************
The prototypes in this file describe the interfaces that the MAME core
and various tools rely upon to interact with the outside world. They are
broken out into several categories.
***************************************************************************/
/// \file
/// \brief Core OS-dependent code interface
///
/// The prototypes in this file describe the interfaces that the MAME
/// core and various tools rely on to interact with the outside world.
/// They are broken out into several categories.
#ifndef MAME_OSD_OSDCORE_H
#define MAME_OSD_OSDCORE_H
@ -46,216 +39,188 @@
#endif
#endif
/* flags controlling file access */
#define OPEN_FLAG_READ 0x0001 /* open for read */
#define OPEN_FLAG_WRITE 0x0002 /* open for write */
#define OPEN_FLAG_CREATE 0x0004 /* create & truncate file */
#define OPEN_FLAG_CREATE_PATHS 0x0008 /* create paths as necessary */
#define OPEN_FLAG_NO_PRELOAD 0x0010 /* do not decompress on open */
/// \defgroup openflags File open flags
/// \{
// osd_file is an interface which represents an open file/PTY/socket
/// Open file for reading.
#define OPEN_FLAG_READ 0x0001
/// Open file for writing.
#define OPEN_FLAG_WRITE 0x0002
/// Create the file, or truncate it if it exists.
#define OPEN_FLAG_CREATE 0x0004
/// Create non-existent directories in the path.
#define OPEN_FLAG_CREATE_PATHS 0x0008
/// Do not decompress into memory on open.
#define OPEN_FLAG_NO_PRELOAD 0x0010
/// \}
/// \brief Interface to file-like resources
///
/// This interface is used to access file-like and stream-like
/// resources. Examples include plain files, TCP socket, named pipes,
/// pseudo-terminals, and compressed archive members.
class osd_file
{
public:
// error codes returned by routines below
/// \brief Result of a file operation
///
/// Returned by most members of osd_file, and also used by other
/// classes that access files or other file-like resources.
enum class error
{
/// Operation completed successfully.
NONE,
/// Operation failed, but there is no more specific code to
/// describe the failure.
FAILURE,
/// Operation failed due to an error allocating memory.
OUT_OF_MEMORY,
/// The requested file, path or resource was not found.
NOT_FOUND,
/// Current permissions do not allow the requested access.
ACCESS_DENIED,
/// Requested access is not permitted because the file or
/// resource is currently open for exclusive access.
ALREADY_OPEN,
/// Request cannot be completed due to resource exhaustion
/// (maximum number of open files or other objects has been
/// reached).
TOO_MANY_FILES,
/// The request cannot be completed because invalid data was
/// encountered (for example an inconsistent filesystem, or a
/// corrupt archive file).
INVALID_DATA,
/// The requested access mode is invalid, or not appropriate for
/// the file or resource.
INVALID_ACCESS
};
/// \brief Smart pointer to a file handle
typedef std::unique_ptr<osd_file> ptr;
/*-----------------------------------------------------------------------------
osd_file::open: open a new file.
Parameters:
path - path to the file to open
openflags - some combination of:
OPEN_FLAG_READ - open the file for read access
OPEN_FLAG_WRITE - open the file for write access
OPEN_FLAG_CREATE - create/truncate the file when opening
OPEN_FLAG_CREATE_PATHS - specifies that non-existant paths
should be created if necessary
file - reference to an osd_file::ptr to receive the newly-opened file
handle; this is only valid if the function returns FILERR_NONE
filesize - reference to a uint64_t to receive the size of the opened
file; this is only valid if the function returns FILERR_NONE
Return value:
a file_error describing any error that occurred while opening
the file, or FILERR_NONE if no error occurred
Notes:
This function is called by core_fopen and several other places in
the core to access files. These functions will construct paths by
concatenating various search paths held in the options.c options
database with partial paths specified by the core. The core assumes
that the path separator is the first character of the string
PATH_SEPARATOR, but does not interpret any path separators in the
search paths, so if you use a different path separator in a search
path, you may get a mixture of PATH_SEPARATORs (from the core) and
alternate path separators (specified by users and placed into the
options database).
-----------------------------------------------------------------------------*/
/// \brief Open a new file handle
///
/// This function is called by core_fopen and several other places
/// in the core to access files. These functions will construct
/// paths by concatenating various search paths held in the
/// options.c options database with partial paths specified by the
/// core. The core assumes that the path separator is the first
/// character of the string PATH_SEPARATOR, but does not interpret
/// any path separators in the search paths, so if you use a
/// different path separator in a search path, you may get a mixture
/// of PATH_SEPARATORs (from the core) and alternate path separators
/// (specified by users and placed into the options database).
/// \param [in] path Path to the file to open.
/// \param [in] openflags Combination of #OPEN_FLAG_READ,
/// #OPEN_FLAG_WRITE, #OPEN_FLAG_CREATE and
/// #OPEN_FLAG_CREATE_PATHS specifying the requested access mode
/// and open behaviour.
/// \param [out] file Receives the file handle if the operation
/// succeeds. Not valid if the operation fails.
/// \param [out] filesize Receives the size of the opened file if
/// the operation succeeded. Not valid if the operation failed.
/// Will be zero for stream-like objects (e.g. TCP sockets or
/// named pipes).
/// \return Result of the operation.
static error open(std::string const &path, std::uint32_t openflags, ptr &file, std::uint64_t &filesize);
/*-----------------------------------------------------------------------------
osd_file::openpty: create a new PTY pair
Parameters:
file - reference to an osd_file::ptr to receive the handle of the master
side of the newly-created PTY; this is only valid if the function
returns FILERR_NONE
name - reference to string where slave filename will be stored
Return value:
a file_error describing any error that occurred while creating the
PTY, or FILERR_NONE if no error occurred
-----------------------------------------------------------------------------*/
/// \brief Create a new pseudo-terminal (PTY) pair
///
/// \param [out] file Receives the handle of the master side of the
/// pseudo-terminal if the operation succeeds. Not valid if the
/// operation fails.
/// \param [out] name Receives the name of the slave side of the
/// pseudo-terminal if the operation succeeds. Not valid if the
/// operation fails.
/// \return Result of the operation.
static error openpty(ptr &file, std::string &name);
/*-----------------------------------------------------------------------------
osd_file::~osd_file: close an open file
-----------------------------------------------------------------------------*/
/// \brief Close an open file
virtual ~osd_file() { }
/*-----------------------------------------------------------------------------
osd_file::read: read from an open file
Parameters:
buffer - pointer to memory that will receive the data read
offset - offset within the file to read from
length - number of bytes to read from the file
actual - reference to a uint32_t to receive the number of bytes actually
read during the operation; valid only if the function returns
FILERR_NONE
Return value:
a file_error describing any error that occurred while reading
from the file, or FILERR_NONE if no error occurred
-----------------------------------------------------------------------------*/
/// \brief Read from an open file
///
/// Read data from an open file at specified offset. Note that the
/// seek and read are not guaranteed to be atomic, which may cause
/// issues in multi-threaded applications.
/// \param [out] buffer Pointer to memory that will receive the data
/// read.
/// \param [in] offset Byte offset within the file to read at,
/// relative to the start of the file. Ignored for stream-like
/// objects (e.g. TCP sockets or named pipes).
/// \param [in] length Number of bytes to read. Fewer bytes may be
/// read if the end of file is reached, or if no data is
/// available.
/// \param [out] actual Receives the number of bytes read if the
/// operation succeeds. Not valid if the operation fails.
/// \return Result of the operation.
virtual error read(void *buffer, std::uint64_t offset, std::uint32_t length, std::uint32_t &actual) = 0;
/*-----------------------------------------------------------------------------
osd_file::write: write to an open file
Parameters:
buffer - pointer to memory that contains the data to write
offset - offset within the file to write to
length - number of bytes to write to the file
actual - reference to a uint32_t to receive the number of bytes actually
written during the operation; valid only if the function returns
FILERR_NONE
Return value:
a file_error describing any error that occurred while writing to
the file, or FILERR_NONE if no error occurred
-----------------------------------------------------------------------------*/
/// \brief Write to an open file
///
/// Write data to an open file at specified offset. Note that the
/// seek and write are not guaranteed to be atomic, which may cause
/// issues in multi-threaded applications.
/// \param [in] buffer Pointer to memory containing data to write.
/// \param [in] offset Byte offset within the file to write at,
/// relative to the start of the file. Ignored for stream-like
/// objects (e.g. TCP sockets or named pipes).
/// \param [in] length Number of bytes to write.
/// \param [out] actual Receives the number of bytes written if the
/// operation succeeds. Not valid if the operation fails.
/// \return Result of the operation.
virtual error write(void const *buffer, std::uint64_t offset, std::uint32_t length, std::uint32_t &actual) = 0;
/*-----------------------------------------------------------------------------
osd_file::truncate: change the size of an open file
Parameters:
. offset - future size of the file
Return value:
a file_error describing any error that occurred while writing to
the file, or FILERR_NONE if no error occurred
-----------------------------------------------------------------------------*/
/// \brief Change the size of an open file
///
/// \param [in] offset Desired size of the file.
/// \return Result of the operation.
virtual error truncate(std::uint64_t offset) = 0;
/*-----------------------------------------------------------------------------
osd_file::flush: flush file buffers
Parameters:
file - handle to a file previously opened via osd_open
Return value:
a file_error describing any error that occurred while flushing file
buffers, or FILERR_NONE if no error occurred
-----------------------------------------------------------------------------*/
/// \brief Flush file buffers
///
/// This flushes any data cached by the application, but does not
/// guarantee that all prior writes have reached persistent storage.
/// \return Result of the operation.
virtual error flush() = 0;
/*-----------------------------------------------------------------------------
osd_file::remove: deletes a file
Parameters:
filename - path to file to delete
Return value:
a file_error describing any error that occurred while deleting
the file, or FILERR_NONE if no error occurred
-----------------------------------------------------------------------------*/
/// \brief Delete a file
///
/// \param [in] filename Path to the file to delete.
/// \return Result of the operation.
static error remove(std::string const &filename);
};
/*-----------------------------------------------------------------------------
osd_getenv: return pointer to environment variable
Parameters:
name - name of environment variable
Return value:
pointer to value
-----------------------------------------------------------------------------*/
/// \brief Get environment variable value
///
/// \param [in] name Name of the environment variable as a
/// NUL-terminated string.
/// \return Pointer to environment variable value as a NUL-terminated
/// string if found, or nullptr if not found.
const char *osd_getenv(const char *name);
/*-----------------------------------------------------------------------------
osd_getpid: gets process id
Return value:
process id
-----------------------------------------------------------------------------*/
/// \brief Get current process ID
///
/// \return The process ID of the current process.
int osd_getpid();
/*-----------------------------------------------------------------------------
osd_get_physical_drive_geometry: if the given path points to a physical
drive, return the geometry of that drive
@ -442,7 +407,7 @@ typedef uint64_t osd_ticks_t;
accurate. It is ok if this call is not ultra-fast, since it is
primarily used for once/frame synchronization.
-----------------------------------------------------------------------------*/
osd_ticks_t osd_ticks(void);
osd_ticks_t osd_ticks();
/*-----------------------------------------------------------------------------
@ -457,7 +422,7 @@ osd_ticks_t osd_ticks(void);
an osd_ticks_t value which represents the number of ticks per
second
-----------------------------------------------------------------------------*/
osd_ticks_t osd_ticks_per_second(void);
osd_ticks_t osd_ticks_per_second();
/*-----------------------------------------------------------------------------
@ -697,67 +662,42 @@ void osd_work_item_release(osd_work_item *item);
MISCELLANEOUS INTERFACES
***************************************************************************/
/*-----------------------------------------------------------------------------
osd_alloc_executable: allocate memory that can contain executable code
Parameters:
size - the number of bytes to allocate
Return value:
a pointer to the allocated memory
Notes:
On many systems, this call may acceptably map to malloc(). On systems
where pages are tagged with "no execute" privileges, it may be
necessary to perform some kind of special allocation to ensure that
code placed into this buffer can be executed.
-----------------------------------------------------------------------------*/
/// \brief Allocate memory that can contain executable code
///
/// Allocated memory must be both writable and executable. Allocated
/// memory must be freed by calling #osd_free_executable passing the
/// same size.
/// \param [in] size Number of bytes to allocate.
/// \return Pointer to allocated memory, or nullptr if allocation
/// failed.
/// \sa osd_free_executable
void *osd_alloc_executable(size_t size);
/*-----------------------------------------------------------------------------
osd_free_executable: free memory allocated by osd_alloc_executable
Parameters:
ptr - the pointer returned from osd_alloc_executable
size - the number of bytes originally requested
Return value:
None
-----------------------------------------------------------------------------*/
/// \brief Free memory allocated by osd_alloc_executable
///
/// \param [in] ptr Pointer returned by #osd_alloc_executable.
/// \param [in] size Number of bytes originally requested. Must match
/// the value passed to #osd_alloc_executable.
/// \sa osd_alloc_executable
void osd_free_executable(void *ptr, size_t size);
/*-----------------------------------------------------------------------------
osd_break_into_debugger: break into the hosting system's debugger if one
is attached
Parameters:
message - pointer to string to output to the debugger
Return value:
None.
Notes:
This function is called when an assertion or other important error
occurs. If a debugger is attached to the current process, it should
break into the debugger and display the given message.
-----------------------------------------------------------------------------*/
/// \brief Break into host debugger if attached
///
/// This function is called when a fatal error occurs. If a debugger is
/// attached, it should break and display the specified message.
/// \param [in] message Message to output to the debugger as a
/// NUL-terminated string.
void osd_break_into_debugger(const char *message);
/*-----------------------------------------------------------------------------
osd_get_clipboard_text: retrieves text from the clipboard
-----------------------------------------------------------------------------*/
std::string osd_get_clipboard_text(void);
/// \brief Get clipboard text
///
/// Gets current clipboard content as UTF-8 text. Returns an empty
/// string if the clipboard contents cannot be converted to plain text.
/// \return Clipboard contents or an empty string.
std::string osd_get_clipboard_text();
/***************************************************************************
@ -818,7 +758,8 @@ public:
};
//FIXME: really needed here?
void osd_list_network_adapters(void);
void osd_list_network_adapters();
/***************************************************************************
UNCATEGORIZED INTERFACES
@ -847,21 +788,7 @@ const char *osd_get_volume_name(int idx);
src - source string
-----------------------------------------------------------------------------*/
void osd_subst_env(std::string &dst,std::string const &src);
/* ----- output management ----- */
// output channels
enum osd_output_channel
{
OSD_OUTPUT_CHANNEL_ERROR,
OSD_OUTPUT_CHANNEL_WARNING,
OSD_OUTPUT_CHANNEL_INFO,
OSD_OUTPUT_CHANNEL_DEBUG,
OSD_OUTPUT_CHANNEL_VERBOSE,
OSD_OUTPUT_CHANNEL_LOG,
OSD_OUTPUT_CHANNEL_COUNT
};
void osd_subst_env(std::string &dst, std::string const &src);
class osd_gpu
{
@ -1014,6 +941,22 @@ public:
virtual void unbind_buffer(vertex_buffer_interface *vb) = 0;
};
/// \defgroup osd_printf Diagnostic output functions
/// \{
// output channels
enum osd_output_channel
{
OSD_OUTPUT_CHANNEL_ERROR,
OSD_OUTPUT_CHANNEL_WARNING,
OSD_OUTPUT_CHANNEL_INFO,
OSD_OUTPUT_CHANNEL_DEBUG,
OSD_OUTPUT_CHANNEL_VERBOSE,
OSD_OUTPUT_CHANNEL_LOG,
OSD_OUTPUT_CHANNEL_COUNT
};
class osd_output
{
public:
@ -1037,35 +980,79 @@ private:
osd_output *m_chain = nullptr;
};
// diagnostic output
void osd_vprintf_error(util::format_argument_pack<std::ostream> const &args);
void osd_vprintf_warning(util::format_argument_pack<std::ostream> const &args);
void osd_vprintf_info(util::format_argument_pack<std::ostream> const &args);
void osd_vprintf_verbose(util::format_argument_pack<std::ostream> const &args);
void osd_vprintf_debug(util::format_argument_pack<std::ostream> const &args);
/// \brief Print error message
///
/// By default, error messages are sent to standard error. The relaxed
/// format rules used by util::string_format apply.
/// \param [in] fmt Message format string.
/// \param [in] args Optional message format arguments.
/// \sa util::string_format
template <typename Format, typename... Params> void osd_printf_error(Format &&fmt, Params &&...args)
{
return osd_vprintf_error(util::make_format_argument_pack(std::forward<Format>(fmt), std::forward<Params>(args)...));
}
/// \brief Print warning message
///
/// By default, warning messages are sent to standard error. The
/// relaxed format rules used by util::string_format apply.
/// \param [in] fmt Message format string.
/// \param [in] args Optional message format arguments.
/// \sa util::string_format
template <typename Format, typename... Params> void osd_printf_warning(Format &&fmt, Params &&...args)
{
return osd_vprintf_warning(util::make_format_argument_pack(std::forward<Format>(fmt), std::forward<Params>(args)...));
}
/// \brief Print informational message
///
/// By default, informational messages are sent to standard output.
/// The relaxed format rules used by util::string_format apply.
/// \param [in] fmt Message format string.
/// \param [in] args Optional message format arguments.
/// \sa util::string_format
template <typename Format, typename... Params> void osd_printf_info(Format &&fmt, Params &&...args)
{
return osd_vprintf_info(util::make_format_argument_pack(std::forward<Format>(fmt), std::forward<Params>(args)...));
}
/// \brief Print verbose diagnostic message
///
/// Verbose diagnostic messages are disabled by default. If enabled,
/// they are sent to standard output by default. The relaxed format
/// rules used by util::string_format apply. Note that the format
/// string and arguments will always be evaluated, even if verbose
/// diagnostic messages are disabled.
/// \param [in] fmt Message format string.
/// \param [in] args Optional message format arguments.
/// \sa util::string_format
template <typename Format, typename... Params> void osd_printf_verbose(Format &&fmt, Params &&...args)
{
return osd_vprintf_verbose(util::make_format_argument_pack(std::forward<Format>(fmt), std::forward<Params>(args)...));
}
/// \brief Print debug message
///
/// By default, debug messages are sent to standard output for debug
/// builds only. The relaxed format rules used by util::string_format
/// apply. Note that the format string and arguments will always be
/// evaluated, even if debug messages are disabled.
/// \param [in] fmt Message format string.
/// \param [in] args Optional message format arguments.
/// \sa util::string_format
template <typename Format, typename... Params> void osd_printf_debug(Format &&fmt, Params &&...args)
{
return osd_vprintf_debug(util::make_format_argument_pack(std::forward<Format>(fmt), std::forward<Params>(args)...));
}
/// \}
// returns command line arguments as an std::vector<std::string> in UTF-8
std::vector<std::string> osd_get_command_line(int argc, char *argv[]);