Difference between revisions of "MAME Internals"
(Category) |
|||
(6 intermediate revisions by one other user not shown) | |||
Line 3: | Line 3: | ||
* by the ROM_LOAD declaration | * by the ROM_LOAD declaration | ||
* by a software list | * by a software list | ||
== ROM storage == | |||
In order to run an emulation in MAME, or to run cartridge-based programs within emulation, the contents of the memory chips inside the console or cartridge are needed. The contents are saved as files on the host file system and are called '''(memory) dumps'''. | |||
There are usually more dump files than a single one, so it makes sense to keep those files together. In MAME there are two ways: | |||
* as an archive file (zip or 7z) | |||
* as a directory | |||
containing all the dumps of the system or of a cartridge, respectively. We shall call both kinds a ''ROM package''. | |||
In MAME, ROM packages are not selected by their file system name. Instead, ROM packages for all supported systems are collected in directories and selected by a name which is defined in the system driver. The directories to store the ROM packages must be listed in the property '''rompath''' in ''mame.ini'' or ''mess.ini''. | |||
# | |||
# CORE SEARCH PATH OPTIONS | |||
# | |||
rompath /home/michael/mame/systemroms;/home/michael/mame/cartroms | |||
or in a Windows environment | |||
# | |||
# CORE SEARCH PATH OPTIONS | |||
# | |||
rompath C:\prg\mame\roms;C:\Users\Michael\Documents\cartroms | |||
The paths may be specified as relative paths (like ''systemroms;cartroms'') when the folder, where MAME has been started, contains these directories. The directories are separated by semicolon; they are searched from left to right. | |||
Taking the BurgerTime cartridge as an example, we have a file ''burgertm.zip'' | |||
$ unzip -t /home/michael/mame/cartroms/burgertm.zip | |||
Archive: /home/michael/mame/cartroms/burgertm.zip | |||
testing: phm3233c.bin OK | |||
testing: phm3233g3.bin OK | |||
testing: phm3233g4.bin OK | |||
This file has obviously already been put into a directory in the rompath. Alternatively, we can create a directory ''burgertm'' and unpack the archive there. | |||
$ ls /home/michael/mame/cartroms/burgertm | |||
phm3233c.bin phm3233g3.bin phm3233g4.bin | |||
If you like you can drop all zips into a single directory, but since you can define different directories that you can use to retain some overview, why not make use of this? | |||
== ROM_LOAD == | == ROM_LOAD == | ||
Line 16: | Line 58: | ||
A program, as found on systems like the TI-99/4A, was typically available as a cartridge, or as one or more files on a diskette or cassette. Within a cartridge there are one or more permanent memory chips containing the program code. | A program, as found on systems like the TI-99/4A, was typically available as a cartridge, or as one or more files on a diskette or cassette. Within a cartridge there are one or more permanent memory chips containing the program code. | ||
=== Example definition === | === Example definition === | ||
Line 39: | Line 80: | ||
</software> | </software> | ||
This <software> element contains, among further information, one child element '''<part>'''. Parts can be understood as different editions of a game or program, like "Part 1: First | This <software> element contains, among further information, one child element '''<part>'''. Parts can be understood as different editions of a game or program, like "Part 1: First Encounter", "Part 2: The Hunt Continues", "Part 3: The Endgame". Each part would then declare its specific collection of dumps. We do not have such use cases in the TI emulation, so there is a single <part> element. | ||
The '''<feature>''' element is a simple name/value information element, but it is nonetheless very important: it determines the type of the cartridge. | The ''name'' of the part is "cart", which is not really important; it could be given any name, since we do not distinguish parts here. The match to the value of the ''interface'' attribute "ti99_cart" is the value of ''ti99_cartridge_device::image_interface''. This means we could set up another way to process cartridges by providing another ''device_image_interface''. <ref name="otherif">Indeed, we could also specify that a game be loaded from a disk drive, in which case the associated interface would be, for instance, "ti99_disk".</ref> | ||
The '''<feature>''' element is a simple name/value information element, but it is nonetheless very important: In our case it determines the type of the cartridge. | |||
The two '''<dataarea>''' elements are particularly interesting here. Each <dataarea> element contains a '''name''' attribute which associates the contained dumps to a '''region''', and it specifies the size of this region. We have two regions: '''grom''' and '''rom''', which are used to hold the contents of the GROMs and of the EPROM in the cartridge. | The two '''<dataarea>''' elements are particularly interesting here. Each <dataarea> element contains a '''name''' attribute which associates the contained dumps to a '''region''', and it specifies the size of this region. We have two regions: '''grom''' and '''rom''', which are used to hold the contents of the GROMs and of the EPROM in the cartridge. | ||
In the element for the grom region we have two '''<rom>''' elements, one for GROM 3 (at offset 0000), and one for GROM 4 (at offset 2000). Note that the grom region in a cartridge is associated to the GROMs with IDs 3 to 7. The GROMs 0 to 2 are contained in the console and have their own memory region. | In the element for the grom region we have two '''<rom>''' elements, one for GROM 3 (at offset 0000), and one for GROM 4 (at offset 2000).<ref>Note that the grom region in a cartridge is associated to the GROMs with IDs 3 to 7. The GROMs 0 to 2 are contained in the console and have their own memory region.</ref> | ||
The element for the rom region contains a single <rom> element for the dump of the EPROM. This region is accessed at address 6000, which is not obvious here, but which is determined by the cartridge type. | The element for the rom region contains a single <rom> element for the dump of the EPROM. This region is accessed at address 6000, which is not obvious here, but which is determined by the cartridge type. | ||
Line 57: | Line 100: | ||
./mame64 ti99_4a -cart burgertm | ./mame64 ti99_4a -cart burgertm | ||
The action starts inside ''image.cpp'' where the loop over all instances of image devices causes a call to ''device_image_interface::load''. The image type of ''ti99_cartridge_device'' is ''IO_CARTSLOT'', the name registered for it is "cartridge", matching the short name "cart" in the command line. Accordingly, the instance is ''ti99_cartridge_device'', and ''burgertm'' will be passed as argument (all in ''image.cpp''). | The action starts inside ''image.cpp'' where the loop over all instances of image devices causes a call to ''device_image_interface::load''. The image type of ''ti99_cartridge_device'' is ''IO_CARTSLOT'', the name registered for it is "cartridge", matching the short name "cart" in the command line. <ref>When the core finds out that there are multiple devices that support the same image type, the names are suffixed with a number ("cart1", "cart2", "flop1", "flop2").</ref> Accordingly, the instance is ''ti99_cartridge_device'', and ''burgertm'' will be passed as argument (all in ''image.cpp''). | ||
First, the parent class does some internal handling. | First, the parent class does some internal handling. | ||
Line 64: | Line 107: | ||
If the argument behind ''cart'' contains a period, the name is considered a file name. | If the argument behind ''cart'' contains a period, the name is considered a file name. | ||
'''To be continued''' | |||
==== Program name argument ==== | ==== Program name argument ==== | ||
If the argument behind ''cart'' does not contain a period, the name is considered a software name from a software list. | If the argument behind ''cart'' does not contain a period, the name is considered a software name from a software list. Next, within ''load_software_part'', | ||
The following methods are called subsequently: | |||
* device_image_interface::load_internal: | |||
* device_image_interface::load_software_part: | |||
* device_image_interface::find_software_item: Searches the matching <software> element within the specified software list, and returns the part from it that was either specified explicitly, or that appears first in the <software> element. | |||
* virtual device_image_interface::call_softlist_load: Implemented in ''gromport.cpp''. Calls rom_load_manager::load_software_part_region, passing a pointer to the [[#rom_entry | rom_entry]] list, starting with a region declaration | |||
* rom_load_manager::load_software_part_region: Determine the ''locationtag'' (list%name(%parent)). Allocate memory, then process all rom entries starting from the given position. | |||
* rom_load_manager::process_rom_entries: The <rom> entries in the software list are processed as ROM_LOAD entries (ISFILE). | |||
* rom_load_manager::open_rom_file: Rom loader | |||
* virtual call_load | |||
'''To be continued''' | '''To be continued''' | ||
== Technical details == | |||
=== rom_entry === | |||
This is a structure that is used for multiple purposes: | |||
* Represents a ROM entry: Every ROM declaration between ROM_START and ROM_END (inclusive) is a ROM entry. | |||
* Represents a ROM region: Within the ROM declarations there may be several region declarations (e.g. for ROM and GROM, see ti99_4x.cpp). | |||
* Represents a ROM element: Within code, this is a ROM_LOAD(_*) declaration. Within a softlist, it is a <rom> element. crc and sha1 are stored in the same _hashdata member: '''R'''crc'''S'''sha1. | |||
All rom_entry instances are collected in a list. ''rom_next_region'' proceeds to the next rom_entry in the list that declares a region. | |||
=== ROM loader === | |||
The ROM loader is implemented in rom_load_manager::open_rom_file and rom_load_manager::read_rom_data. | |||
rom_fread -> emu_file::read | |||
open -> open_next -> attempt_zipped | |||
== Notes == | |||
<references /> | |||
[[Category:MESS|Internals]] |
Latest revision as of 13:44, 3 June 2016
The ROM loader is an internal component of the MAME core. It is not directly called by the driver but in one of these occasions:
- by the ROM_LOAD declaration
- by a software list
ROM storage
In order to run an emulation in MAME, or to run cartridge-based programs within emulation, the contents of the memory chips inside the console or cartridge are needed. The contents are saved as files on the host file system and are called (memory) dumps.
There are usually more dump files than a single one, so it makes sense to keep those files together. In MAME there are two ways:
- as an archive file (zip or 7z)
- as a directory
containing all the dumps of the system or of a cartridge, respectively. We shall call both kinds a ROM package.
In MAME, ROM packages are not selected by their file system name. Instead, ROM packages for all supported systems are collected in directories and selected by a name which is defined in the system driver. The directories to store the ROM packages must be listed in the property rompath in mame.ini or mess.ini.
# # CORE SEARCH PATH OPTIONS # rompath /home/michael/mame/systemroms;/home/michael/mame/cartroms
or in a Windows environment
# # CORE SEARCH PATH OPTIONS # rompath C:\prg\mame\roms;C:\Users\Michael\Documents\cartroms
The paths may be specified as relative paths (like systemroms;cartroms) when the folder, where MAME has been started, contains these directories. The directories are separated by semicolon; they are searched from left to right.
Taking the BurgerTime cartridge as an example, we have a file burgertm.zip
$ unzip -t /home/michael/mame/cartroms/burgertm.zip Archive: /home/michael/mame/cartroms/burgertm.zip testing: phm3233c.bin OK testing: phm3233g3.bin OK testing: phm3233g4.bin OK
This file has obviously already been put into a directory in the rompath. Alternatively, we can create a directory burgertm and unpack the archive there.
$ ls /home/michael/mame/cartroms/burgertm phm3233c.bin phm3233g3.bin phm3233g4.bin
If you like you can drop all zips into a single directory, but since you can define different directories that you can use to retain some overview, why not make use of this?
ROM_LOAD
ROM dumps can be specified by ROM_LOAD declaration.
To be continued
Software list
Software lists are used for declaring the software dumps associated to some program or game. A software list is a XML document which contains one or more child nodes named <software>. Every <software> nodes describes a single program (or game).
A program, as found on systems like the TI-99/4A, was typically available as a cartridge, or as one or more files on a diskette or cassette. Within a cartridge there are one or more permanent memory chips containing the program code.
Example definition
For illustration purposes we have a look at the following entry from the TI-99 softlist in MAME.
<software name="burgertm"> <description>Burgertime</description> <year>1983</year> <publisher>Data East USA</publisher> <info name="serial" value="PHM 3233"/> <part name="cart" interface="ti99_cart"> <feature name="pcb" value="standard"/> <dataarea name="grom" size="0x4000"> <rom name="phm3233g3.bin" size="0x1800" crc="4d55a729" sha1="523f57cd388b2a1d117737d40422b1ad7dd3dabc" offset="0x0000" /> <rom name="phm3233g4.bin" size="0x1800" crc="d3637b23" sha1="d6bef21943169a154264633bacf62408ef0b479d" offset="0x2000" /> </dataarea> <dataarea name="rom" size="0x2000"> <rom name="phm3233c.bin" size="0x2000" crc="ed7ef022" sha1="8959a44c9ca8aaf15da5ba49d4d26656e8175554" offset="0x0000" /> </dataarea> </part> </software>
This <software> element contains, among further information, one child element <part>. Parts can be understood as different editions of a game or program, like "Part 1: First Encounter", "Part 2: The Hunt Continues", "Part 3: The Endgame". Each part would then declare its specific collection of dumps. We do not have such use cases in the TI emulation, so there is a single <part> element.
The name of the part is "cart", which is not really important; it could be given any name, since we do not distinguish parts here. The match to the value of the interface attribute "ti99_cart" is the value of ti99_cartridge_device::image_interface. This means we could set up another way to process cartridges by providing another device_image_interface. [1]
The <feature> element is a simple name/value information element, but it is nonetheless very important: In our case it determines the type of the cartridge.
The two <dataarea> elements are particularly interesting here. Each <dataarea> element contains a name attribute which associates the contained dumps to a region, and it specifies the size of this region. We have two regions: grom and rom, which are used to hold the contents of the GROMs and of the EPROM in the cartridge.
In the element for the grom region we have two <rom> elements, one for GROM 3 (at offset 0000), and one for GROM 4 (at offset 2000).[2]
The element for the rom region contains a single <rom> element for the dump of the EPROM. This region is accessed at address 6000, which is not obvious here, but which is determined by the cartridge type.
So we can see three files: phm3233g3.bin, phm3233g4.bin, phm3233c.bin, each containing a dump that must be loaded. For the MAME core it does not matter whether the contents are dumped from a GROM or from a ROM - the only job for the core is to load these files and to put them in the given locations in the respective regions. This is where the ROM loader is invoked.
Loading
Suppose we launch the emulation with the cartridge plugged in (see later discussion for cartridge swap):
./mame64 ti99_4a -cart burgertm
The action starts inside image.cpp where the loop over all instances of image devices causes a call to device_image_interface::load. The image type of ti99_cartridge_device is IO_CARTSLOT, the name registered for it is "cartridge", matching the short name "cart" in the command line. [3] Accordingly, the instance is ti99_cartridge_device, and burgertm will be passed as argument (all in image.cpp).
First, the parent class does some internal handling.
File argument
If the argument behind cart contains a period, the name is considered a file name.
To be continued
Program name argument
If the argument behind cart does not contain a period, the name is considered a software name from a software list. Next, within load_software_part,
The following methods are called subsequently:
- device_image_interface::load_internal:
- device_image_interface::load_software_part:
- device_image_interface::find_software_item: Searches the matching <software> element within the specified software list, and returns the part from it that was either specified explicitly, or that appears first in the <software> element.
- virtual device_image_interface::call_softlist_load: Implemented in gromport.cpp. Calls rom_load_manager::load_software_part_region, passing a pointer to the rom_entry list, starting with a region declaration
- rom_load_manager::load_software_part_region: Determine the locationtag (list%name(%parent)). Allocate memory, then process all rom entries starting from the given position.
- rom_load_manager::process_rom_entries: The <rom> entries in the software list are processed as ROM_LOAD entries (ISFILE).
- rom_load_manager::open_rom_file: Rom loader
- virtual call_load
To be continued
Technical details
rom_entry
This is a structure that is used for multiple purposes:
- Represents a ROM entry: Every ROM declaration between ROM_START and ROM_END (inclusive) is a ROM entry.
- Represents a ROM region: Within the ROM declarations there may be several region declarations (e.g. for ROM and GROM, see ti99_4x.cpp).
- Represents a ROM element: Within code, this is a ROM_LOAD(_*) declaration. Within a softlist, it is a <rom> element. crc and sha1 are stored in the same _hashdata member: RcrcSsha1.
All rom_entry instances are collected in a list. rom_next_region proceeds to the next rom_entry in the list that declares a region.
ROM loader
The ROM loader is implemented in rom_load_manager::open_rom_file and rom_load_manager::read_rom_data.
rom_fread -> emu_file::read
open -> open_next -> attempt_zipped
Notes
- ↑ Indeed, we could also specify that a game be loaded from a disk drive, in which case the associated interface would be, for instance, "ti99_disk".
- ↑ Note that the grom region in a cartridge is associated to the GROMs with IDs 3 to 7. The GROMs 0 to 2 are contained in the console and have their own memory region.
- ↑ When the core finds out that there are multiple devices that support the same image type, the names are suffixed with a number ("cart1", "cart2", "flop1", "flop2").