module osdepend.c with default empty implementations. Changed
mame_execute() and cli_execute() to accept a reference to an
osd_interface which is provided by the caller.
Updated SDL and Windows OSD to create an osd_interface-derived
class and moved their OSD callbacks to be members.
broadly used.
Added memory interface to the intelfsh device so you can access/view the
data in the debugger and via the standard memory interfaces. Removed the
old memory() method in favor of new functions read_raw()/write_raw() which
do direct reads/writes of the data.
Cleaned up CPS3 No-CD sets to break up the "ROMs" into individual flash
pieces which are automatically loaded by the intelfsh device on initialization.
Also split the MACHINE_CONFIG to only populate the number of SIMMs actually
present for each game, as documented in the top of the file. And replaced
the NVRAM_HANDLER with an NVRAM device.
work just like required_device<> and optional_device<> for retrieving a
pointer by tag from an address space that specifies AM_SHARE("tag").
Also added templates required_shared_size<> and optional_shared_size<>
for retrieving the size of the AM_SHARE region.
Created a new generic NVRAM device. It can be configured to default to
0-fill, 1-fill, random-fill, or custom fill. In all cases, a same-named
memory region overrides the default fill. The address range where the
NVRAM can be found is now identified by an AM_SHARE() region of the
same tag as the NVRAM device. Drivers can also explicitly configure a
separately-allocated NVRAM region via nvram_device::set_base().
Replaced all instances of MDRV_NVRAM_HANDLER(generic_*) with
MDRV_NVRAM_ADD_*("nvram"). Replaced all AM_BASE_GENERIC/AM_SIZE_GENERIC(nvram)
with AM_SHARE("nvram"). For all remaining drivers that referenced the
generic.nvram directly, changed them to hold a required_shared_ptr<UINTx>
to the NVRAM in their driver state, and use that instead. Removed
nvram and nvram_size from the generic_ptrs.
recently-introduced find_devices() method.
There are two new template classes optional_device<> and required_device<>.
Use these to declare the device pointers in the class. The only difference
between the two is that required will fatalerror if the device is not found.
These new classes are "pass-through" so m_oki can be passed anywhere an
okim6295_device would work, and you can use m_oki->x to reference methods
or variables.
Each of these new classes needs to be specified in the initializer,
passing a reference to the driver_device object and the device tag. So,
for example:
class example_state : public driver_device
{
public:
example_state(running_machine &machine, const driver_device_config_base &config)
: driver_device(machine, config),
m_maincpu(*this, "maincpu"),
m_oki(*this, "oki") { }
required_device<okim6295_device> m_oki;
optional_device<cpu_device> m_maincpu;
};
Given that, the driver_device will auto-populate each device with a
pointer to the device prior to calling any of the initialization methods.
device interface. This means all ROMs are now exposed via devices,
and thus the process of enumerating ROMs gets simpler.
Changed all instances of temporarily allocating machine_config objects
to just put them on the stack for simplicity, letting the destructor
handle the cleanup work automatically.
Changed machine_config constructor to take a game_driver, from which
the machine_config constructor is obtained. This also means the
resulting machine_config holds a reference to the game_driver.
Changed running_machine constructor to no longer take a game_driver,
since the game_driver is now obtainable via the machine_config.
class with a new driver_device class, which is the base class for all
driver_data objects now. The new driver devices are added as the
first device in the device list, with a tag of "root"; all other
devices are now owned by the driver device.
Moved core callbacks (machine_start/_reset, sound_start/_reset,
video_start/_reset/_eof/_update, and palette_init) into device
configuration parameters on these new devices. The driver_device
base class overrides device_start(), ensures all other devices have
been started, and then calls, in order, the following overridable
methods:
find_devices() - new, used to locate devices prior to DRIVER_INIT
DRIVER_INIT function from the game driver
palette_init() - by default calls the MDRV_PALETTE_INIT function
driver_start() - new
machine_start() - by default calls the MDRV_MACHINE_START function
sound_start() - by default calls the MDRV_SOUND_START function
video_start() - by default calls the MDRV_VIDEO_START function
Similarly, the driver_device class overrides device_reset() and then
calls these methods in order:
driver_reset() - new
machine_reset() - by default calls the MDRV_MACHINE_RESET function
sound_reset() - by default calls the MDRV_SOUND_RESET function
video_reset() - by default calls the MDRV_VIDEO_RESET function
To accommodate these changes, initialization order is slightly
altered from before. The tilemap, video, sound, and debug systems
are now initialized prior to the devices' start. And the user
callbacks for DRIVER_INIT, PALETTE_INIT, MACHINE_START, SOUND_START,
and VIDEO_START are all called back-to-back. The net effect should
be similar, however.
Added methods (optional_device and required_device) to the new
driver_device class to find devices, intended to be used from the
find_devices() callback. See harddriv.h and beathead.h for examples
of usage.
Changed device_t::subtag to only prepend a prefix if the device is
not the 'root' device, in order to keep compatibility with existing
tag searching.
Changed device startup to actively reorder devices when they report
missing dependencies. This ensures that the reset functions get
called in the same order that the start functions did.
Bulk updated drivers as follows:
First removed the old static alloc function from the driver_data_t:
S: [ \t]*static driver_device \*alloc *\( *running_machine *\&machine *\) *\{ *return auto_alloc_clear *\( *\&machine *, *[a-zA-Z0-9_]+_state *\( *machine *\) *\); *\}[\r\n]*
R:
Then switched from driver_data_t to driver_device:
S: driver_data_t
R: driver_device
Then changed the constructors to pass the correct parameters:
S: ([a-zA-Z0-9_]+)_state *\( *running_machine *\&machine *\)([\r\n\t ]+): *driver_device *\( *machine *\)
R: \1_state\(running_machine \&machine, const driver_device_config_base \&config\)\2: driver_device\(machine, config\)
1. Renamed MACHINE_DRIVER_* to MACHINE_CONFIG_* to match the name
of the object it actually describes. The MDRV_* prefix may
eventually be bulk updated at some point, but not now.
2. MACHINE_CONFIG_START() now takes a driver_data_t-derived
class as a required second parameter. This means that
MDRV_DRIVER_DATA() is no longer required, and every "root"
machine config *must* specify a driver data class (or driver_data_t
itself if the driver has not yet been updated to use driver data).
3. New MACHINE_CONFIG_DERIVED() macro defines a machine_config
that is derived from another machine_config. This takes the place
of the very typical MACHINE_DRIVER_START()/MDRV_IMPORT_FROM()
combination.
4. New MACHINE_CONFIG_FRAGMENT() macro defines a partial
machine_config that can only be included in another "root"
machine_config. This is also used for machine_configs that are
specified as part of a device.
5. Changed MDRV_IMPORT_FROM() to MDRV_FRAGMENT_ADD() to more
accurately describe what is happening.
6. Added asserts to the above three macros to ensure they are
properly used.
Updated all machine drivers to use the new macros. Search & replace
lists below cover 99% of the changes, with just a few manual fixups.
S: MACHINE_DRIVER_START\( *([a-zA-Z0-9_]+) *\)[\r\n\t ]*MDRV_DRIVER_DATA\( *([a-zA-Z0-9_]+) *\)
R: MACHINE_CONFIG_START\( \1, \2 \)
S: MACHINE_DRIVER_START\( *([a-zA-Z0-9_]+) *\)[\r\n\t ]*/\* driver data \*/[\r\n\t ]*MDRV_DRIVER_DATA\( *([a-zA-Z0-9_]+) *\)
R: MACHINE_CONFIG_START\( \1, \2 \)
S: MACHINE_DRIVER_START\( *([a-zA-Z0-9_]+) *\)[\r\n\t ]*MDRV_IMPORT_FROM\( *([a-zA-Z0-9_]+) *\)
R: MACHINE_CONFIG_DERIVED\( \1, \2 \)
S: MACHINE_DRIVER_START\( *([a-zA-Z0-9_]+) *\)[\r\n\t ]*/\* basic machine hardware \*/[\r\n\t ]*MDRV_IMPORT_FROM\( *([a-zA-Z0-9_]+) *\)
R: MACHINE_CONFIG_DERIVED\( \1, \2 \)\r\n\r\n\t/\* basic machine hardware \*/
For all files outside of mame/drivers....
S: MACHINE_DRIVER_START
R: MACHINE_CONFIG_FRAGMENT in all non-drivers
For all files within mame/drivers....
S: MACHINE_DRIVER_START\( *([a-zA-Z0-9_]+) *\)
R: MACHINE_CONFIG_START\( \1, driver_data_t \)
S: MDRV_IMPORT_FROM
R: MDRV_FRAGMENT_ADD
S: MACHINE_DRIVER_END
R: MACHINE_CONFIG_END
S: MACHINE_DRIVER_NAME
R: MACHINE_CONFIG_NAME
S: MACHINE_DRIVER_EXTERN
R: MACHINE_CONFIG_EXTERN
Final step: run mame -valid and fix the incorrect macros at the lines
where the asserts show up.
machine_start
machine_reset
sound_start
sound_reset
palette_init
video_start
video_reset
video_update
video_eof
The default implementations of these call through the machine
configuration's functions as before. However, if a driver_data_t
overrides them, it will be called instead.
Also added virtual functions for pre_save() and post_load(),
which can be overridden to implement machine driver-specific
pre-save/post-load functionality instead of registering with
the save state system.
Updated beathead to use these new virtual functions instead of
specifying callbacks in the MACHINE_DRIVER.
create a stack class that started the profiler in the constructor
and stopped it in the destructor). Sadly, doing that causes gcc to
call out to hook up the unwind chain, and this tanks performance
quite badly, even when the profiler is off.
Since I had already class-ified profiler.c, I decided to keep the old
way of doing things but wrap it in the newer classes. So at least it
wasn't a complete waste of my time.
Search & replace:
profiler_mark_start -> g_profiler.start
profiler_mark_end -> g_profiler.end
supporting cleaner implementations of drivers in the explicitly OO world.
Expect a follow-on of several more changes to clean up from this one, which
deliberately tried to avoid touching much driver code.
Converted address_space to a class, and moved most members behind accessor
methods, apart from space->machine and space->cpu. Removed external references
to 8le/8be/16le/16be/32le/32be/64le/64be. All external access is now done via
virtual functions read_byte()/read_word()/etc. Moved differentiation between
the endianness and the bus width internal to memory.c, and also added a new
axis to support small/large address spaces, which allows for faster lookups
on spaces smaller than 18 bits.
Provided methods for most global memory operations within the new address_space
class. These will be bulk converted in a future update, but for now there are
inline wrappers to hide this change from existing callers.
Created new module delegate.h which implements C++ delegates in a form that
works for MAME. Details are in the opening comment. Delegates allow member
functions of certain classes to be used as callbacks, which will hopefully
be the beginning of the end of fetching the driver_data field in most
callbacks. All classes that host delegates must derive from bindable_object.
Today, all devices and driver_data do implicitly via their base class.
Defined delegates for read/write handlers. The new delegates are always
passed an address_space reference, along with offset, data, and mask. Delegates
can refer to methods either in the driver_data class or in a device class.
To specify a callback in an address map, just use AM_READ_MEMBER(class, member).
In fact, all existing AM_ macros that take read/write handlers can now accept
delegates in their place. Delegates that are specified in an address map are
proto-delegates which have no object; they are bound to their object when
the corresponding address_space is created.
Added machine->m_nonspecific_space which can be passed as the required
address_space parameter to the new read/write methods in legacy situations
where the space is not provided. Eventually this can go away but we will
need it for a while yet.
Added methods to the new address_space class to dynamically install delegates
just like you can dynamically install handlers today. Delegates installed this
way must be pre-bound to their object.
Moved beathead's read/write handlers into members of beathead_state as an
example of using the new delegates. This provides examples of both static (via
an address_map) and dynamic (via install_handler calls) mapping using delegates.
Added read/write member functions to okim6295_device as an example of using
delegates to call devices. Updated audio/williams.c as a single example of
calling the device via its member function callbacks. These will be bulk
updated in a future update, and the old global callbacks removed.
Changed the DIRECT_UPDATE_CALLBACKs into delegates as well. Updated all users
to the new function format. Added methods on direct_read_data for configuring the
parameters in a standard way to make the implementation clearer.
Created a simple_list template container class for managing the common
singly-linked lists we use all over in the project.
Many other internal changes in memory.c, mostly involving restructuring the code
into proper classes.
Defined new class driver_data_t, which all driver_data classes must
derive from. Updated all class definitions to inherit from the new
class, and to call it in the constructor. Also changed the alloc()
signature to return a driver_data_t pointer instead of a void *.
Renamed and hid machine->driver_data as machine->m_driver_data.
Added a new templatized method machine->driver_data<class> which returns
a properly downcast'ed version of the driver data. Updated all code
which looked like this:
mydriver_state *state = (mydriver_state *)machine->driver_data;
to this:
mydriver_state *state = machine->driver_data<mydriver_state>();
The new function does a downcast<> which in debug builds dynamically
verifies that you're actually casting to the right type.
Changed atarigen_state to be a base class from which all the related
Atari drivers derive their state from.
For MESS: this was mostly a bulk search/replace, in 4 steps in
src/mame:
1. Add ": public driver_data_t" to each driver state class definition:
Search: (class [a-z0-9_]+_state)$
Replace: \1 : public driver_data_t
2. Change the static alloc function to return a driver_data_t *:
Search: static void \*alloc\(
Replace: static driver_data_t \*alloc\(
3. Change the constructor to initialize driver_data_t:
Search: ([a-z0-9_]+_state\(running_machine \&machine\)) { }
Replace: \1\r\n\t\t: driver_data_t(machine) { }
4. Replace the state fetchers to use the new templatized function:
Search: \(([a-z0-9_]+_state) \*\)(.*)machine->driver_data
Replace: \2machine->driver_data<\1>()
DECLARE_LEGACY_CPU_DEVICE and DEFINE_LEGACY_CPU_DEVICE. Changed CPUs
to be their own device types, rather than all of type CPU with a
special internal subtype. Note that as part of this process I removed
the CPU_ prefix from the ALL-CAPS device name, so CPU_Z80 is just
plain old Z80 now. This required changing a couple of names like
8080 to I8080 so that there was an alphabetic first character.
Added memory interfaces to the list of fast-access interfaces. To do
this properly I had to add a separate method to devices which is
called immediately after construction, when it is possible to perform
dynamic_casts on fully-constructed objects. (This is just internal,
no changes necessary to the devices themselves.)
Some additional notes:
* SH2 and SH4 had typedefs that conflicted with their CPU_-less names
so I bulk renamed to structures to sh2_state and sh4_state; RB, feel
free to choose alternate names if you don't like 'em
* SCSP was caught doing something to the 3rd indexed CPU. Since several
systems that use SCSP don't even have 3 CPUs, I had no idea what
this was supposed to do, so I changed to it reference "audiocpu"
assuming that stv was the assumed target. This is really gross and
should be a configuration parameter, not a hard-coded assumption.
running_machine definition and implementation.
Moved global machine-level operations and accessors into methods on the
running_machine class. For the most part, this doesn't affect drivers
except for a few occasional bits:
mame_get_phase() == machine->phase()
add_reset_callback() == machine->add_notifier(MACHINE_NOTIFY_RESET, ...)
add_exit_callback() == machine->add_notifier(MACHINE_NOTIFY_EXIT, ...)
mame_get_base_datetime() == machine->base_datetime()
mame_get_current_datetime() == machine->current_datetime()
Cleaned up the region_info class, removing most global region accessors
except for memory_region() and memory_region_length(). Again, this doesn't
generally affect drivers.