Difference between revisions of "Guided tour through MESS"
(Created page with "MESS is lacking what many software projects, in particular open-source projects, also fail to give: a good introduction to find into the concepts of what you can see there as pro...") |
|||
Line 5: | Line 5: | ||
* ''different level of understanding'': What may be plain to see for the developer is often cryptic to the beginner. | * ''different level of understanding'': What may be plain to see for the developer is often cryptic to the beginner. | ||
* ''hidden knowledge'': Similar to the last point, the developer does not even know that he adds some missing links for understanding. | * ''hidden knowledge'': Similar to the last point, the developer does not even know that he adds some missing links for understanding. | ||
I'll try to fight the last two points with this guided tour through MESS. We will discuss on the example of the TI-99/4A emulation how MESS works and how to implement new parts. | |||
== Terminology == | |||
MESS is a sister project of MAME, the ''Multi Arcade Machine Emulator''. It uses the same software core but adds new structures and support for typical devices used with computers. MAME introduced some terms which are also used inside MESS (which is reasonable, or we would need a dictionary all the time) but which can be confusing or misleading sometimes. Accordingly, I will present some of the more important terms here. | |||
{| class="plain" style="width:90%; margin-top:3em" | |||
! MAME/MESS term | |||
! Meaning | |||
|- | |||
| Game | |||
| Refers to the emulated system (consider the viewpoint of MAME); GAME_NOT_WORKING is a flag to mark a system as non-functional | |||
|- | |||
| Driver | |||
| The complete system; ti99_4a is a driver, as is geneve. | |||
|- | |||
| Device | |||
| An instance of the device_t class. Managed by the core. | |||
|- | |||
| Image | |||
| Representation of memory contents stored in a file, usually referring to media like disks, cartridges | |||
|- | |||
| Dump | |||
| File of ROM contents. Good dump = verified to be correct; overdump = dump that is longer than the original contents | |||
|- | |||
| Cartridges | |||
| Representation of pluggable software components, like the TI-99/4A command modules. | |||
|- | |||
| CHD | |||
| Compressed Hunk of Data, storage format for mass storage devices, allows for uncompressed or compressed and checksummed content. | |||
|- | |||
| Input ports | |||
| Any kind of system component that changes state on external action, like a dip switch or a key on the keyboard. | |||
|- | |||
| ... | |||
| ... | |||
|} | |||
== Starting point == | |||
MESS can be started from the command line or from a frontend like QMC2. The frontend supplies the same parameters to the emulator as would be required on a command line. A simple command line could look like this: | |||
mess ti99_4ae | |||
The executable program file is '''mess''' (in Windows: mess.exe), sometimes also '''mess64''' (for 64 bit systems) or '''messd''' (special version containing symbols for debugging) or '''mess64d'''. If you want to find bugs in the emulator (not in your TI programs running on the emulator!) you should use a debug build. For normal usage the standard build is recommended which is also much smaller. | |||
Within the whole TI emulation part you will not find any '''int main(...)'''. The main function belongs to the core, and this is a area where I would recommended to go not before you finished our tour and completely understood the concepts. For now, just keep in mind that the program starts somewhere in the core and will later reach the TI emulation. | |||
=== The system === | |||
The first thing to do for the system is to process the argument ti99_4ae. This is a name of a driver which it must look up in its tables. These tables were created during build time, so this is not of interest for you. The file where we should look at next is '''ti99_4x.c'''. (It could have been named in any way - the important point are the data which it registers in the core.) | |||
At the end of ti99_4x we can find the following lines: | |||
COMP( 1979, ti99_4, 0, 0, ti99_4_60hz, ti99_4, 0, "Texas Instruments", "TI99/4 Home Computer (US)" , 0) | |||
COMP( 1980, ti99_4e, ti99_4, 0, ti99_4_50hz, ti99_4, 0, "Texas Instruments", "TI99/4 Home Computer (Europe)" , 0) | |||
COMP( 1981, ti99_4a, 0, 0, ti99_4a_60hz, ti99_4a, 0, "Texas Instruments", "TI99/4A Home Computer (US)" , 0) | |||
COMP( 1981, ti99_4ae, ti99_4a, 0, ti99_4a_50hz, ti99_4a, 0, "Texas Instruments", "TI99/4A Home Computer (Europe)" , 0) | |||
COMP( 1994, ti99_4ev, ti99_4a, 0, ti99_4ev_60hz,ti99_4a, 0, "Texas Instruments", "TI99/4A Home Computer with EVPC" , 0) | |||
'''COMP''' is not a command, but it is a macro which is transformed to a structure that is loaded into the core at startup time. In the fourth line you can find the character string that we provided on the command line. | |||
The components of the lines have the following meaning: | |||
* Year of the release of the system; just an information item | |||
* The driver name | |||
* The parent driver name. | |||
* Compatibility information (not used here) | |||
* Machine name - this one points to configuration data | |||
* A pointer to the configuration of input ports | |||
* Initialization information (not used here) | |||
* Company; just information | |||
* System name; used in frontends | |||
There is already one important thing to note. Drivers (see above for the meaning - it is the complete system) may have ''children''. Sometimes you have systems that closely resemble each other, except for some small differences. If they share the same ROM dumps you can avoid to provide the dumps for each system again. In our case, the ti99_4ae driver is a child of ti99_4a; it only differs in the video refresh rate. Therefore we do not need to provide the emulator with the dumps for ti99_4a and ti99_4ae. If the emulator cannot find a ROM dump for a driver, it checks whether there is a parent which can deliver the missing dumps. As all dumps are the same, it suffices to provide the ROMs for ti99_4a only. | |||
=== ROMs === | |||
The next thing the core has to find out is whether it must load any ROM dumps, and how they are named. For a TI-99/4A we need dumps for the console ROMs and GROMs. This is also declared inside ti99_4x.c: | |||
ROM_START(ti99_4a) | |||
ROM_REGION16_BE(0x2000, "maincpu", 0) | |||
ROM_LOAD16_WORD("994arom.bin", 0x0000, 0x2000, CRC(db8f33e5) SHA1(6541705116598ab462ea9403c00656d6353ceb85)) | |||
ROM_REGION(0x10000, region_grom, 0) | |||
ROM_LOAD("994agrom.bin", 0x0000, 0x6000, CRC(af5c2449) SHA1(0c5eaad0093ed89e9562a2c0ee6a370bdc9df439)) | |||
ROM_END | |||
As just explained, we do not have separate ROMs for ti99_4ae, so the core looks up the parent name and finds this structure. Again, ROM_START is a macro, like all the other capitalized terms. It does not execute anything but transforms the data as shown here into a structure that is registered in the core. The CRC and SHA1 declarations are used to verify that the ROMs are unchanged. | |||
What if I want to use a modified ROM? - Well, this is not directly possible. You would need to calculate the new CRC and SHA1 values (MESS prints them on startup when they differ) and recompile the emulator. If it were allowed to modify the ROMs, debugging would become a nightmare. Imagine your TI emulation locks up - we could not be sure whether the bug is in the emulation or whether the dump has been modified. Sorry ... you're on your own here. | |||
Both ROM files must be stored in a ZIP file named after the driver name, in this case ti99_4a.zip. The lines should be read in this way: | |||
* This is ROM content for the memory region "maincpu" (see later). | |||
* It is 16 bit (our ROMs are connected to the 16 bit bus), and the byte order is big-endian (in the TI, the most significant byte has a lower address than the least significant byte; if you store >1234 at >A000, then >12 is at >A000 and >34 is at >A001). PCs use little-endian, in contrast. | |||
* Load the contents of the file "994arom.bin" into the region, >2000 bytes (8192). | |||
* Another region we use is region_grom (somewhere else declared as a string "console_groms"). | |||
* Its size is 64 KiB (yes, each GROMs only has 6 KiB contents, but they nevertheless occupy the whole address space) and it is 8-bit memory. | |||
* We load the contents of "994agrom.bin" into the region, size is >6000 bytes (24576; the first three GROMs). The remainder of the region is filled with zeros. | |||
We could also clip the GROM region, since we put cartridge GROMs in their own regions. (Maybe I'll do that in a later release.) For now it does not hurt to waste 40960 bytes. |
Revision as of 13:20, 4 March 2012
MESS is lacking what many software projects, in particular open-source projects, also fail to give: a good introduction to find into the concepts of what you can see there as program code. This is rarely a malevolence of the implemententors; it is usually caused by one or more of these reasons:
- lack of time: We have to fix bug#18274 and have to more time to write the docs
- outdated: Docs have been written with quite some efforts, but since version x.y most of them do not apply any longer, and no one really has the energy to make them catch up (Sisyphus)
- different level of understanding: What may be plain to see for the developer is often cryptic to the beginner.
- hidden knowledge: Similar to the last point, the developer does not even know that he adds some missing links for understanding.
I'll try to fight the last two points with this guided tour through MESS. We will discuss on the example of the TI-99/4A emulation how MESS works and how to implement new parts.
Terminology
MESS is a sister project of MAME, the Multi Arcade Machine Emulator. It uses the same software core but adds new structures and support for typical devices used with computers. MAME introduced some terms which are also used inside MESS (which is reasonable, or we would need a dictionary all the time) but which can be confusing or misleading sometimes. Accordingly, I will present some of the more important terms here.
MAME/MESS term | Meaning |
---|---|
Game | Refers to the emulated system (consider the viewpoint of MAME); GAME_NOT_WORKING is a flag to mark a system as non-functional |
Driver | The complete system; ti99_4a is a driver, as is geneve. |
Device | An instance of the device_t class. Managed by the core. |
Image | Representation of memory contents stored in a file, usually referring to media like disks, cartridges |
Dump | File of ROM contents. Good dump = verified to be correct; overdump = dump that is longer than the original contents |
Cartridges | Representation of pluggable software components, like the TI-99/4A command modules. |
CHD | Compressed Hunk of Data, storage format for mass storage devices, allows for uncompressed or compressed and checksummed content. |
Input ports | Any kind of system component that changes state on external action, like a dip switch or a key on the keyboard. |
... | ... |
Starting point
MESS can be started from the command line or from a frontend like QMC2. The frontend supplies the same parameters to the emulator as would be required on a command line. A simple command line could look like this:
mess ti99_4ae
The executable program file is mess (in Windows: mess.exe), sometimes also mess64 (for 64 bit systems) or messd (special version containing symbols for debugging) or mess64d. If you want to find bugs in the emulator (not in your TI programs running on the emulator!) you should use a debug build. For normal usage the standard build is recommended which is also much smaller.
Within the whole TI emulation part you will not find any int main(...). The main function belongs to the core, and this is a area where I would recommended to go not before you finished our tour and completely understood the concepts. For now, just keep in mind that the program starts somewhere in the core and will later reach the TI emulation.
The system
The first thing to do for the system is to process the argument ti99_4ae. This is a name of a driver which it must look up in its tables. These tables were created during build time, so this is not of interest for you. The file where we should look at next is ti99_4x.c. (It could have been named in any way - the important point are the data which it registers in the core.)
At the end of ti99_4x we can find the following lines:
COMP( 1979, ti99_4, 0, 0, ti99_4_60hz, ti99_4, 0, "Texas Instruments", "TI99/4 Home Computer (US)" , 0) COMP( 1980, ti99_4e, ti99_4, 0, ti99_4_50hz, ti99_4, 0, "Texas Instruments", "TI99/4 Home Computer (Europe)" , 0) COMP( 1981, ti99_4a, 0, 0, ti99_4a_60hz, ti99_4a, 0, "Texas Instruments", "TI99/4A Home Computer (US)" , 0) COMP( 1981, ti99_4ae, ti99_4a, 0, ti99_4a_50hz, ti99_4a, 0, "Texas Instruments", "TI99/4A Home Computer (Europe)" , 0) COMP( 1994, ti99_4ev, ti99_4a, 0, ti99_4ev_60hz,ti99_4a, 0, "Texas Instruments", "TI99/4A Home Computer with EVPC" , 0)
COMP is not a command, but it is a macro which is transformed to a structure that is loaded into the core at startup time. In the fourth line you can find the character string that we provided on the command line.
The components of the lines have the following meaning:
- Year of the release of the system; just an information item
- The driver name
- The parent driver name.
- Compatibility information (not used here)
- Machine name - this one points to configuration data
- A pointer to the configuration of input ports
- Initialization information (not used here)
- Company; just information
- System name; used in frontends
There is already one important thing to note. Drivers (see above for the meaning - it is the complete system) may have children. Sometimes you have systems that closely resemble each other, except for some small differences. If they share the same ROM dumps you can avoid to provide the dumps for each system again. In our case, the ti99_4ae driver is a child of ti99_4a; it only differs in the video refresh rate. Therefore we do not need to provide the emulator with the dumps for ti99_4a and ti99_4ae. If the emulator cannot find a ROM dump for a driver, it checks whether there is a parent which can deliver the missing dumps. As all dumps are the same, it suffices to provide the ROMs for ti99_4a only.
ROMs
The next thing the core has to find out is whether it must load any ROM dumps, and how they are named. For a TI-99/4A we need dumps for the console ROMs and GROMs. This is also declared inside ti99_4x.c:
ROM_START(ti99_4a) ROM_REGION16_BE(0x2000, "maincpu", 0) ROM_LOAD16_WORD("994arom.bin", 0x0000, 0x2000, CRC(db8f33e5) SHA1(6541705116598ab462ea9403c00656d6353ceb85)) ROM_REGION(0x10000, region_grom, 0) ROM_LOAD("994agrom.bin", 0x0000, 0x6000, CRC(af5c2449) SHA1(0c5eaad0093ed89e9562a2c0ee6a370bdc9df439)) ROM_END
As just explained, we do not have separate ROMs for ti99_4ae, so the core looks up the parent name and finds this structure. Again, ROM_START is a macro, like all the other capitalized terms. It does not execute anything but transforms the data as shown here into a structure that is registered in the core. The CRC and SHA1 declarations are used to verify that the ROMs are unchanged.
What if I want to use a modified ROM? - Well, this is not directly possible. You would need to calculate the new CRC and SHA1 values (MESS prints them on startup when they differ) and recompile the emulator. If it were allowed to modify the ROMs, debugging would become a nightmare. Imagine your TI emulation locks up - we could not be sure whether the bug is in the emulation or whether the dump has been modified. Sorry ... you're on your own here.
Both ROM files must be stored in a ZIP file named after the driver name, in this case ti99_4a.zip. The lines should be read in this way:
- This is ROM content for the memory region "maincpu" (see later).
- It is 16 bit (our ROMs are connected to the 16 bit bus), and the byte order is big-endian (in the TI, the most significant byte has a lower address than the least significant byte; if you store >1234 at >A000, then >12 is at >A000 and >34 is at >A001). PCs use little-endian, in contrast.
- Load the contents of the file "994arom.bin" into the region, >2000 bytes (8192).
- Another region we use is region_grom (somewhere else declared as a string "console_groms").
- Its size is 64 KiB (yes, each GROMs only has 6 KiB contents, but they nevertheless occupy the whole address space) and it is 8-bit memory.
- We load the contents of "994agrom.bin" into the region, size is >6000 bytes (24576; the first three GROMs). The remainder of the region is filled with zeros.
We could also clip the GROM region, since we put cartridge GROMs in their own regions. (Maybe I'll do that in a later release.) For now it does not hurt to waste 40960 bytes.