mirror of https://github.com/987123879113/mame
docs: Added preliminary guide for would-be contributors. (#10717) [Ryan Holtz, Vas Crabb, O. Galibert]
parent
0619912fb0
commit
e85a2899c5
10 changed files with 862 additions and 76 deletions
@ -0,0 +1,4 @@ |
||||
Contributing to MAME |
||||
==================== |
||||
|
||||
Please see the guidelines for [Contributing to MAME](https://docs.mamedev.org/contributing/) on our documentation web site. |
@ -1 +0,0 @@ |
||||
|
@ -0,0 +1,510 @@ |
||||
.. _contributing-cxx: |
||||
|
||||
C++ Coding Guidelines |
||||
===================== |
||||
|
||||
.. contents:: :local: |
||||
|
||||
|
||||
.. _contributing-cxx-intro: |
||||
|
||||
Introduction |
||||
------------ |
||||
|
||||
**In terms of coding conventions, the style present within an existing |
||||
source file should be favoured over the standards found below.** |
||||
|
||||
When a new source file is being created, the following coding |
||||
conventions should be observed if creating a new file within the MAME |
||||
core (``src/emu`` and ``src/lib``). If the source file is outside the |
||||
core, deference can be given to a contributor’s preferred style, |
||||
although it is strongly encouraged to code with the understanding that |
||||
the file may need to be comprehensible by more than one person as time |
||||
marches forward. |
||||
|
||||
|
||||
.. _contributing-cxx-definitions: |
||||
|
||||
Definitions |
||||
----------- |
||||
|
||||
Snake case |
||||
All lowercase letters with words separated by underscores: |
||||
``this_is_snake_case`` |
||||
Screaming snake case |
||||
All uppercase letters with words separated by underscores: |
||||
``SCREAMING_SNAKE_CASE`` |
||||
Camel case: |
||||
Lowercase initial letter, first letter of each subsequent word |
||||
capitalised, with no separators between words: ``exampleCamelCase`` |
||||
Llama case: |
||||
Uppercase initial letter, first letter of each subsequent word |
||||
capitalised, with no separators between words: ``LlamaCaseSample`` |
||||
|
||||
|
||||
.. _contributing-cxx-naming: |
||||
|
||||
Naming conventions |
||||
------------------ |
||||
|
||||
Preprocessor macros |
||||
Macro names should use screaming snake case. Macros are always |
||||
global and name conflicts can cause confusing errors – think |
||||
carefully about what macros really need to be in headers and name |
||||
them carefully. |
||||
Include guards |
||||
Include guard macros should begin with ``MAME_``, and end with a |
||||
capitalised version of the file name, with separators replaced by |
||||
underscores. |
||||
Constants |
||||
Constants should use screaming snake case, whether they are constant |
||||
globals, constant data members, enumerators or preprocessor |
||||
constants. |
||||
Functions |
||||
Free functions names should use snake case. (There are some utility |
||||
function that were previously implemented as preprocessor macros |
||||
that still use screaming snake case.) |
||||
Classes |
||||
Class names should use snake case. Abstract class names should end |
||||
in ``_base``. Public member functions (including static member |
||||
functions) should use snake case. |
||||
Device classes |
||||
Concrete driver ``driver_device`` implementation names |
||||
conventionally end in ``_state``, while other concrete device class |
||||
names end in ``_device``. Concrete ``device_interface`` names |
||||
conventionally begin with ``device_`` and end with ``_interface``. |
||||
Device types |
||||
Device types should use screaming snake case. Remember that device |
||||
types are names in the global namespace, so choose explicit, |
||||
unambiguous names. |
||||
Enumerations |
||||
The enumeration name should use snake case. The enumerators should |
||||
use screaming snake case. |
||||
Template parameters |
||||
Template parameters should use llama case (both type and value |
||||
parameters). |
||||
|
||||
|
||||
.. _contributing-cxx-literals: |
||||
|
||||
Variables and literals |
||||
---------------------- |
||||
|
||||
Octal literals are discouraged from use outside of specific cases. They |
||||
lack the obvious letter-based prefixes found in hexadecimal and binary |
||||
literals, and therefore can be difficult to distinguish at a glance from |
||||
a decimal literal to coders who are unfamiliar with octal notation. |
||||
|
||||
Lower-case hexadecimal literals are preferred, e.g. ``0xbadc0de`` rather |
||||
than ``0xBADC0DE``. For clarity, try not to exceed the bit width of the |
||||
variable which will be used to store it. |
||||
|
||||
Binary literals have rarely been used in the MAME source code due to the |
||||
``0b`` prefix not being standardised until C++14, but there is no policy |
||||
to avoid their use. |
||||
|
||||
Integer suffix notation should be used when specifying 64-bit literals, |
||||
but is not strictly required in other cases. It can, however, clarify |
||||
the intended use of a given literal at a glance. Uppercase long integer |
||||
literal suffixes should be used to avoid confusion with the digit 1, |
||||
e.g. ``7LL`` rather than ``7ll``. |
||||
|
||||
Types that do not have a specifically defined size should be avoided if |
||||
they are to be registered with MAME’s save-state system, as it harms |
||||
portability. In general, this means avoiding the use of ``int`` for |
||||
these members. |
||||
|
||||
It's encouraged, but not required, for class data members to be prefixed |
||||
with ``m_`` for non-static instance members and ``s_`` for static |
||||
members. This does not apply to nested classes or structs. |
||||
|
||||
|
||||
.. _contributing-cxx-braceindent: |
||||
|
||||
Bracing and indentation |
||||
----------------------- |
||||
|
||||
Tabs are used for initial indentation of lines, with one tab used per |
||||
nested scope level. Statements split across multiple lines should be |
||||
indented by two tabs. Spaces are used for alignment at other places |
||||
within a line. |
||||
|
||||
Either K&R or Allman-style bracing is preferred. There is no specific |
||||
preference for bracing on single-line statements, although bracing |
||||
should be consistent for a given ``if/else`` block, as shown: |
||||
|
||||
.. code-block:: C++ |
||||
|
||||
if (x == 0) |
||||
{ |
||||
return; |
||||
} |
||||
else |
||||
{ |
||||
call_some_function(); |
||||
x--; |
||||
} |
||||
|
||||
When using a series of ``if``/``else`` or ``if``/``else if``/``else`` |
||||
blocks with comments at the top indentation level, avoid extraneous |
||||
newlines. The use of additional newlines may lead to ``else if`` or |
||||
``else`` blocks being missed due to the newlines pushing the blocks |
||||
outside the visible editor height: |
||||
|
||||
.. code-block:: C++ |
||||
|
||||
// Early-out if our hypothetical counter has run out. |
||||
if (x == 0) |
||||
{ |
||||
return; |
||||
} |
||||
// We should do something if the counter is running. |
||||
else |
||||
{ |
||||
call_some_function(); |
||||
x--; |
||||
} |
||||
|
||||
Indentation for ``case`` statements inside a ``switch`` body can either |
||||
be on the same level as the ``switch`` statement or inward by one level. |
||||
There is no specific style which is used across all core files, although |
||||
indenting by one level appears to be used most often. |
||||
|
||||
|
||||
.. _contributing-cxx-spacing: |
||||
|
||||
Spacing |
||||
------- |
||||
|
||||
Consistent single-spacing between binary operators, variables, and |
||||
literals is strongly preferred. The following examples exhibit |
||||
reasonably consistent spacing: |
||||
|
||||
.. code-block:: C++ |
||||
|
||||
uint8_t foo = (((bar + baz) + 3) & 7) << 1; |
||||
uint8_t foo = ((bar << 1) + baz) & 0x0e; |
||||
uint8_t foo = bar ? baz : 5; |
||||
|
||||
The following examples exhibit extremes in either direction, although |
||||
having extra spaces is less difficult to read than having too few: |
||||
|
||||
.. code-block:: C++ |
||||
|
||||
uint8_t foo = ( ( ( bar + baz ) + 3 ) & 7 ) << 1; |
||||
uint8_t foo = ((bar<<1)+baz)&0x0e; |
||||
uint8_t foo = (bar?baz:5); |
||||
|
||||
A space should be used between a fundamental C++ statement and its |
||||
opening parenthesis, e.g.: |
||||
|
||||
.. code-block:: C++ |
||||
|
||||
switch (value) ... |
||||
if (a != b) ... |
||||
for (int i = 0; i < foo; i++) ... |
||||
|
||||
|
||||
.. _contributing-cxx-scoping: |
||||
|
||||
Scoping |
||||
------- |
||||
|
||||
Variables should be scoped as narrowly as is reasonably possible. There |
||||
are many instances of C89-style local variable declaration in the MAME |
||||
codebase, but this is largely a hold-over from MAME’s early days, which |
||||
pre-date the C99 specification. |
||||
|
||||
The following two snippets exhibit the legacy style of local variable |
||||
declaration, followed by the more modern and preferred style: |
||||
|
||||
.. code-block:: C++ |
||||
|
||||
void example_device::some_function() |
||||
{ |
||||
int i; |
||||
uint8_t data; |
||||
|
||||
for (i = 0; i < std::size(m_buffer); i++) |
||||
{ |
||||
data = m_buffer[i]; |
||||
if (data) |
||||
{ |
||||
some_other_function(data); |
||||
} |
||||
} |
||||
} |
||||
|
||||
.. code-block:: C++ |
||||
|
||||
void example_device::some_function() |
||||
{ |
||||
for (int i = 0; i < std::size(m_buffer); i++) |
||||
{ |
||||
const uint8_t data = m_buffer[i]; |
||||
if (data) |
||||
{ |
||||
some_other_function(data); |
||||
} |
||||
} |
||||
} |
||||
|
||||
Enumerated values, structs, and classes used only by one specific device |
||||
should be declared within the device's class itself. This avoids |
||||
pollution of the global namespace and makes the device-specific use of |
||||
them more obvious at a glance. |
||||
|
||||
|
||||
.. _contributing-cxx-const: |
||||
|
||||
Const Correctness |
||||
----------------- |
||||
|
||||
Const-correctness has not historically been a strict requirement of code |
||||
that goes into MAME, but there’s increasing value in it as the amount of |
||||
code refactoring increases and technical debt decreases. |
||||
|
||||
When writing new code, it’s worth taking the time to determine if a |
||||
local variable can be declared ``const``. Similarly, it's encouraged to |
||||
consider which member functions of a new class can be ``const`` |
||||
qualified. |
||||
|
||||
In a similar vein, arrays of constants should be declared ``constexpr`` |
||||
and should use screaming snake case, as outlined towards the top of this |
||||
document. Lastly, arrays of C-style strings should be declared as both |
||||
a const array of const strings, as so: |
||||
|
||||
.. code-block:: C++ |
||||
|
||||
static const char *const EXAMPLE_NAMES[4] = |
||||
{ |
||||
"1-bit", |
||||
"2-bit", |
||||
"4-bit", |
||||
"Invalid" |
||||
}; |
||||
|
||||
|
||||
.. _contributing-cxx-comments: |
||||
|
||||
Comments |
||||
-------- |
||||
|
||||
While ``/* ANSI C comments */`` are often found in the codebase, there |
||||
has been a gradual shift towards ``// C++-style comments`` for |
||||
single-line comments. This is very much a guideline, and coders are |
||||
encouraged to use whichever style is most comfortable. |
||||
|
||||
Unless specifically quoting content from a machine or ancillary |
||||
materials, comments should be in English so as to match the predominant |
||||
language that the MAME team shares worldwide. |
||||
|
||||
Commented-out code should typically be removed prior to authoring a pull |
||||
request, as it has a tendency to rot due to the fast-moving nature of |
||||
MAME’s core API. If there is a desire known beforehand for the code to |
||||
eventually be included, it should be bookended in ``if (0)`` or |
||||
``if (false)``, as code removed through a preprocessor macro will rot at |
||||
the same rate. |
||||
|
||||
|
||||
.. _contributing-cxx-helpers: |
||||
|
||||
MAME-Specific Helpers |
||||
--------------------- |
||||
|
||||
When at all possible, use helper functions and macros for bit |
||||
manipulation operations. |
||||
|
||||
The ``BIT(value, bit)`` helper can be used to extract the state of a bit |
||||
at a given position from an integer value. The resulting value will be |
||||
aligned to the least significant bit position, i.e. will be either 0 or |
||||
1. |
||||
|
||||
An overload of the same function, ``BIT(value, bit, width)`` can be used |
||||
to extract a bit field of a specified width from an integer value, |
||||
starting at the specified bit position. The result will also be |
||||
right-justified and will be of the same type as the incoming value. |
||||
|
||||
There are, additionally, a number of helpers for functionality such as |
||||
counting leading zeroes/ones, population count, and signed/unsigned |
||||
integer multiplication and division for both 32-bit and 64-bit results. |
||||
Not all of these helpers have wide use in the MAME codebase, but using |
||||
them in new code is strongly preferred when that code is performance- |
||||
critical, as they utilise inline assembly or compiler intrinsics per- |
||||
platform when available. |
||||
|
||||
``count_leading_zeros_32/64(T value)`` |
||||
Accepts an unsigned 32/64-bit value and returns an unsigned 8-bit |
||||
value containing the number of consecutive zeros starting from the |
||||
most significant bit. |
||||
``count_leading_ones_32/64(T value)`` |
||||
Same functionality as above, but examining consecutive one-bits. |
||||
``population_count_32/64(T value)`` |
||||
Accepts an unsigned 32/64-bit value and returns the number of |
||||
one-bits found, i.e. the Hamming weight of the value. |
||||
``rotl_32/64(T value, int shift)`` |
||||
Performs a circular/barrel left shift of an unsigned 32/64-bit value |
||||
with the specified shift value. The shift value will be masked to |
||||
the valid bit range for a 32-bit or 64-bit value. |
||||
``rotr_32/64(T value, int shift)`` |
||||
Same functionality as above, but with a right shift. |
||||
|
||||
For documentation on helpers related to multiplication and division, |
||||
refer to ``src/osd/eminline.h``. |
||||
|
||||
|
||||
.. _contributing-cxx-logging: |
||||
|
||||
Logging |
||||
------- |
||||
|
||||
MAME has multiple logging function for different purposes. Two of the |
||||
most frequently used logging functions are ``logerror`` and |
||||
``osd_printf_verbose``: |
||||
|
||||
* Devices inherit a ``logerror`` member function. This automatically |
||||
includes the fully-qualified tag of the invoking device in log |
||||
messages. Output is sent to MAME’s debugger’s rotating log buffer if |
||||
the debugger is enabled. If the |
||||
:ref:`-log option <mame-commandline-log>` is enabled, it’s also |
||||
written to the file ``error.log`` in the working directory. If the |
||||
:ref:`-oslog option <mame-commandline-oslog>` is enabled, it’s |
||||
additionally sent to the OS diagnostic output (the host debugger |
||||
diagnostic log on Windows if a host debugger is attached, or standard |
||||
error otherwise). |
||||
* The output of the ``osd_printf_verbose`` function is sent to standard |
||||
error if the :ref:`-verbose option <mame-commandline-verbose>` is |
||||
enabled. |
||||
|
||||
The ``osd_printf_verbose`` function should be used for logging that is |
||||
useful for diagnosing user issues, while ``logerror`` should be used for |
||||
messages more relevant to developers (either developing MAME itself, or |
||||
developing software for emulated systems using MAME’s debugger). |
||||
|
||||
For debug logging, a channel-based logging system exists via the header |
||||
``logmacro.h``. It can be used as a generic logging system as follows, |
||||
without needing to make use of its ability to mask out specific |
||||
channels: |
||||
|
||||
.. code-block:: C++ |
||||
|
||||
// All other headers in the .cpp file should be above this line. |
||||
#define VERBOSE (1) |
||||
#include "logmacro.h" |
||||
... |
||||
void some_device::some_reg_write(u8 data) |
||||
{ |
||||
LOG("%s: some_reg_write: %02x\n", machine().describe_context(), data); |
||||
} |
||||
|
||||
The above example also makes use of a helper function which is available |
||||
in all derivatives of ``device_t``: ``machine().describe_context()``. |
||||
This function will return a string that describe the emulation context |
||||
in which the function is being run. This includes the full-qualified |
||||
tag of the currently executing device (if any). If the relevant device |
||||
implements ``device_state_interface``, it will also include the current |
||||
program-counter value reported by the device. |
||||
|
||||
For more fine-grained control, specific bit masks can be defined and |
||||
used via the ``LOGMASKED`` macro: |
||||
|
||||
.. code-block:: C++ |
||||
|
||||
// All other headers in the .cpp file should be above this line. |
||||
#define LOG_FOO (1 << 1U) |
||||
#define LOG_BAR (1 << 2U) |
||||
|
||||
#define VERBOSE (LOG_FOO | LOG_BAR) |
||||
#include "logmacro.h" |
||||
... |
||||
void some_device::some_reg_write(u8 data) |
||||
{ |
||||
LOGMASKED(LOG_FOO, "some_reg_write: %02x\n", data); |
||||
} |
||||
|
||||
void some_device::another_reg_write(u8 data) |
||||
{ |
||||
LOGMASKED(LOG_BAR, "another_reg_write: %02x\n", data); |
||||
} |
||||
|
||||
Note that the least significant bit position for user-supplied masks is |
||||
1, as bit position 0 is reserved for ``LOG_GENERAL``. |
||||
|
||||
By default, ``LOG`` and ``LOGMASKED`` will use the device-supplied |
||||
``logerror`` function. However, this can be redirected as desired. The |
||||
most common use case would be to direct output to the standard output |
||||
instead, which can be accomplished by explicitly defining |
||||
``LOG_OUTPUT_FUNC`` as so: |
||||
|
||||
.. code-block:: C++ |
||||
|
||||
#define LOG_OUTPUT_FUNC osd_printf_info |
||||
|
||||
A developer should always ensure that ``VERBOSE`` is set to 0 and that |
||||
any definition of ``LOG_OUTPUT_FUNC`` is commented out prior to opening |
||||
a pull request. |
||||
|
||||
|
||||
.. _contributing-cxx-structure: |
||||
|
||||
Structural organization |
||||
----------------------- |
||||
|
||||
Header includes should generally be grouped from most-dependent to |
||||
least-dependent, and sorted alphabetically within said groups: |
||||
|
||||
* The project prefix header, ``emu.h``, must be the first thing in a |
||||
translation unit |
||||
* Local project headers (i.e. headers found in the same source |
||||
directory) |
||||
* Headers in ``src/devices`` |
||||
* Headers in ``src/emu`` |
||||
* Headers in ``src/lib/formats`` |
||||
* Headers in ``src/lib/util`` |
||||
* Headers from the OSD layer |
||||
* C++ standard library headers |
||||
* C standard library headers |
||||
* OS-specific headers |
||||
* Layout headers |
||||
|
||||
Finally, task-specific headers such as ``logmacro.h`` - described in the |
||||
previous section - should be included last. A practical example |
||||
follows: |
||||
|
||||
.. code-block:: C++ |
||||
|
||||
#include "emu.h" |
||||
|
||||
#include "cpu/m68000/m68000.h" |
||||
#include "machine/mc68328.h" |
||||
#include "machine/ram.h" |
||||
#include "sound/dac.h" |
||||
#include "video/mc68328lcd.h" |
||||
#include "video/sed1375.h" |
||||
|
||||
#include "emupal.h" |
||||
#include "screen.h" |
||||
#include "speaker.h" |
||||
|
||||
#include "pilot1k.lh" |
||||
|
||||
#define VERBOSE (0) |
||||
#include "logmacro.h" |
||||
|
||||
The class declaration for a machine driver should be within the |
||||
corresponding source file. In such cases, the class declaration and all |
||||
contents of the source file, excluding the ``GAME``, ``COMP``, or |
||||
``CONS`` macro, should be enclosed in an anonymous namespace. |
||||
|
||||
Constants which are used by a device or machine driver should be in the |
||||
form of explicitly-sized enumerated values within the class declaration, |
||||
or be relegated to ``#define`` macros within the source file. This |
||||
helps avoid polluting the preprocessor. |
||||
|
||||
Type names and other identifiers with a leading underscore should be |
||||
avoided within the global namespace, as they are explicitly reserved |
||||
according to the C++ standard. Additionally, identifiers suffixed with |
||||
``_t`` should be avoided within the global namespace, as they are also |
||||
reserved according to POSIX standards. While MAME violates this policy |
||||
occasionally – most notably with ``device_t`` – it’s considered to be an |
||||
unfortunate legacy decision that should be avoided in any new code. |
@ -0,0 +1,144 @@ |
||||
.. _contributing: |
||||
|
||||
Contributing to MAME |
||||
==================== |
||||
|
||||
So you want to contribute to MAME but aren’t sure where to start? Well |
||||
the great news is that there’s always plenty to do for people with a |
||||
variety of skill sets. |
||||
|
||||
|
||||
.. _contributing-testing: |
||||
|
||||
Testing and reporting bugs |
||||
-------------------------- |
||||
|
||||
One thing MAME can always do with is more testing and bug reports. If |
||||
you’re familiar with a system that MAME emulates and notice something |
||||
wrong, or if you find a bug in MAME’s user interface, you can head over |
||||
to `MAME Testers <https://mametesters.org/>`_ and, assuming it isn’t |
||||
already reported, register an account and open an issue. Be sure to |
||||
read the `FAQ <https://mametesters.org/faq.html>`_ and |
||||
`rules <https://mametesters.org/rules.html>`_ first to ensure you start |
||||
out on the right foot. Please note that MAME Testers only accepts |
||||
user-facing bugs in tagged release versions. |
||||
|
||||
For other kinds of issues, we have |
||||
`GitHub Issues <https://github.com/mamedev/mame/issues/>`_. There’s a |
||||
bit more leeway here. For example we accept developer-facing issues |
||||
(e.g. bugs in internal APIs, or build system inadequacies), feature |
||||
requests, and major regressions before they make it into a released |
||||
version. Please respect the fact that the issue tracker is *not* a |
||||
discussion or support forum, it’s only for reporting reproducible |
||||
issues. Don’t open issues to ask questions or request support. Also, |
||||
keep in mind that the ``master`` branch is unstable. If the current |
||||
revision doesn’t compile at all or is completely broken, we’re probably |
||||
already aware of it and don’t need issues opened for that. Wait a while |
||||
and see if there’s an update. You might want to comment on the commit |
||||
in question with the compiler error message, particularly if you’re |
||||
compiling in an unorthodox but supported configuration. |
||||
|
||||
When opening an issue, remember to provide as much information as |
||||
possible to help others understand, reproduce, and diagnose the issue. |
||||
Things that are helpful to include: |
||||
|
||||
* The incorrect behaviour, and expected or correct behaviour. Be |
||||
specific: just saying it “doesn’t work” usually isn’t enough detail. |
||||
* Environment details, including your operating system, CPU |
||||
architecture, system locale, and display language, if applicable. For |
||||
video output bugs, note your video hardware (GPU), driver version, and |
||||
the MAME video output module you’re using. For input handling bugs, |
||||
include the input peripherals and MAME input modules you’re using. |
||||
* The exact version of MAME you’re using, including a git commit digest |
||||
if it isn’t a tagged release version, and any non-standard build |
||||
options. |
||||
* The exact system and software being emulated (may not be applicable |
||||
for issues with parts of MAME’s UI, like the system selection menu). |
||||
Include things like the selected BIOS version, and emulated peripheral |
||||
(slot device) configuration. |
||||
* Steps to reproduce the issue. Assume the person reading is familiar |
||||
with MAME itself, but not necessarily familiar with the emulated |
||||
system and software in question. For emulation issues, input |
||||
recordings and/or saved state files for reproducing the issue can be |
||||
invaluable. |
||||
* An original reference for the correct behaviour. If you have access |
||||
to the original hardware for the emulated system, it helps to make a |
||||
recording of the correct behaviour for comparison. |
||||
|
||||
|
||||
.. _contributing-code: |
||||
|
||||
Contributing to MAME’s source code |
||||
---------------------------------- |
||||
|
||||
MAME itself is written in C++, but that isn’t the sum total of the |
||||
source code. The source code also includes: |
||||
|
||||
* The documentation hosted on this site (and also included in releases |
||||
as a PDF), written in |
||||
`reStructuredText <https://www.sphinx-doc.org/en/master/usage/restructuredtext/basics.html>`_ |
||||
markup. |
||||
* The supplied :ref:`plugins <plugins>`, written in |
||||
`Lua 5.3 <https://www.lua.org/manual/5.3/>`_. |
||||
* Internal layouts for emulated machines that need to display more than |
||||
a simple video screen. These are an XML application |
||||
:ref:`described here <layfile>`. |
||||
* The software lists, describing known software media for systems that |
||||
MAME emulates. MAME software lists are an XML application. |
||||
* The user interface translations, in GNU gettext PO format. They can |
||||
be edited with a good text editor, or a dedicated tool like |
||||
`Poedit <https://poedit.net/>`_. |
||||
|
||||
Our primary source code repository is |
||||
`hosted on GitHub <https://github.com/mamedev/mame/>`_. We prefer to |
||||
receive source code contributions in the form of |
||||
`pull requests <https://github.com/mamedev/mame/pulls>`_. You’ll need |
||||
to learn the basics of git distributed version control and familiarise |
||||
yourself with the git tools. The basic process for creating a pull |
||||
request is as follows: |
||||
|
||||
* Sign up for an account on GitHub. |
||||
* Create a fork of the mamedev/mame repository. |
||||
* Create a new branch off the ``master`` branch in your forked |
||||
repository. |
||||
* Clone your forked repository, and check out your new branch. |
||||
* Make your changes, and build and test them locally. |
||||
* Commit your changes, and push your branch to GitHub. |
||||
* Optionally enable GitHub Actions for your forked repository, allowing |
||||
your changes to be built on Windows, macOS and Linux. |
||||
* Open a pull request to merge your changes into the ``master`` branch |
||||
in the mamedev/mame repository. |
||||
|
||||
Please keep the following in mind (note that not all points are relevant |
||||
to all kinds of changes): |
||||
|
||||
* Make your commit messages descriptive. Please include what the change |
||||
affects, and what it’s supposed to achieve. A person reading the |
||||
commit log shouldn’t need to resort to examining the diff to get a |
||||
basic idea of what a commit is supposed to do. The default commit |
||||
messages provided by GitHub are completely useless, as they don’t give |
||||
any indication of what a change is supposed to do. |
||||
* Test your changes. Ensure that a full build of MAME completes, and |
||||
that the code you changed works. It’s a good idea to build with |
||||
``DEBUG=1`` to check that assertions compile and don’t trigger. |
||||
* Use an enlightening pull request title and description. The title |
||||
should give a one-line summary of what the overall change affects and |
||||
what it’s supposed to do. The description should contain more detail. |
||||
Don’t leave the description empty and describe the change in comments, |
||||
as this makes searching and filtering more difficult. |
||||
* Be aware that GitHub Actions has opaque resource limits. It isn’t |
||||
clear when you’re close to the limits, and we’ve had contributors |
||||
banned from GitHub Actions for violating the limits. Even if you |
||||
appeal the ban, they still won’t tell you what the actual limits are, |
||||
justifying this by saying that if you know the limits, you can take |
||||
steps to evade them. If you enable GitHub Actions, consider not |
||||
pushing individual commits if you don’t need them to be automatically |
||||
built, or cancelling workflow runs when you don’t need the results. |
||||
|
||||
We have guidelines for specific parts of the source: |
||||
|
||||
.. toctree:: |
||||
:titlesonly: |
||||
|
||||
cxx |
||||
softlist |
@ -0,0 +1,175 @@ |
||||
.. _contributing-softlist: |
||||
|
||||
Guidelines for Software Lists |
||||
============================= |
||||
|
||||
.. contents:: :local: |
||||
|
||||
|
||||
.. _contributing-softlist-intro: |
||||
|
||||
Introduction |
||||
------------ |
||||
|
||||
MAME’s software lists describe known software media for emulated |
||||
systems in a form that can be used to identify media image files for |
||||
known software, verify media image file integrity, and load media |
||||
image files for emulation. Software lists are implemented as XML |
||||
files in the ``hash`` folder. The XML structure is described in the |
||||
file ``hash/softwarelist.dtd``. |
||||
|
||||
Philosophically, software list items should represent the original |
||||
media, rather than a specific dump of the media. Ideally, it should be |
||||
possible for anyone with the media to dump it and produce the same image |
||||
file. Of course, this isn’t always possible in practice – in particular |
||||
it’s problematic for inherently analog media, like home computer |
||||
software stored on audio tape cassettes. |
||||
|
||||
MAME strives to document the best available media images. It is not our |
||||
intention to propagate corrupted, truncated, defaced, watermarked, or |
||||
otherwise bad media images. Where possible, file structures matching |
||||
the original media structure are preferred. For example we prefer |
||||
individual files for separate ROM chips in cartridge media, and we use |
||||
disk images rather than archives of files extracted from the original |
||||
disks. |
||||
|
||||
|
||||
.. _contributing-softlist-itempart: |
||||
|
||||
Items and parts |
||||
--------------- |
||||
|
||||
A software list is a collection of *items* and each item may have |
||||
multiple *parts*. An item represents a piece of software, as |
||||
distributed as a complete package. A part represents a single piece of |
||||
media within the package. Parts can be mounted individually in |
||||
emulated media devices. For example a piece of software distributed on |
||||
three floppy disks will be a single item, while each floppy disk will be |
||||
one part within that item. |
||||
|
||||
Sometimes, logically separate parts of a single physical piece of media |
||||
are represented as separate parts within a software item. For example |
||||
each side of an audio tape cassette is represented as a separate part. |
||||
However individual ROM chips within a cartridge may be separate files, |
||||
but they are *not* separate parts, as the cartridge is mounted as a |
||||
whole. |
||||
|
||||
Each item is a ``software`` element. The ``software`` element may have |
||||
the following attributes: |
||||
|
||||
name (required) |
||||
The short name identifying the item. This is used for file names, |
||||
command line arguments, database keys, URL fragments, and many other |
||||
purposes. It should be terse but still recognisable. It must be |
||||
unique within the software list. Valid characters are lowercase |
||||
English letters, decimal digits and underscores. The maximum |
||||
allowed length is sixteen characters. |
||||
cloneof (optional) |
||||
The short name of the parent item if the item is a clone. The |
||||
parent must be within the same software list – parent/clone |
||||
relationships spanning multiple software lists are not supported. |
||||
supported (optional) |
||||
One of the values ``yes`` (fully usable in emulation), ``no`` (not |
||||
usable in emulation), or ``partial`` (usable in emulation with |
||||
limitations). If the attribute is not present, it is equivalent to |
||||
``yes``. Examples of partially supported software include games |
||||
that are playable with graphical glitches, and office software where |
||||
some but not all functionality works. |
||||
|
||||
Each part is a ``part`` element within the ``software`` element. The |
||||
``part`` element must have the following attributes: |
||||
|
||||
name (required) |
||||
The short name identifying the part. This is used for command line |
||||
arguments, database keys, URL fragments, and many other purposes. |
||||
It must be unique within the item. It is also used as the display |
||||
name if a separate display name is not provided. Valid characters |
||||
are lowercase English letters, decimal digits and underscores. The |
||||
maximum allowed length is sixteen characters. |
||||
interface (required) |
||||
This attribute is used to identify suitable emulated media devices |
||||
for mounting the software part. Applicable values depend on the |
||||
emulated system. |
||||
|
||||
|
||||
.. _contributing-softlist-metadata: |
||||
|
||||
Metadata |
||||
-------- |
||||
|
||||
Software lists support various kinds of metadata. All software list |
||||
items require the following metadata elements to be present: |
||||
|
||||
description |
||||
This is the primary display name for the software item. It should |
||||
be the original name of the software, transliterated into English |
||||
Latin script if necessary. It must be unique within the software |
||||
list. If extra text besides the title itself is required for |
||||
disambiguation, use lowercase outside of proper nouns, initialisms |
||||
and verbatim quotes. |
||||
year |
||||
The year of release or copyright year for the software. If unknown, |
||||
use an estimate with a question mark. Items can be filtered by year |
||||
in the software selection menu. |
||||
publisher |
||||
The publisher of the software. This may be the same as the |
||||
developer if the software was self-published. Items can be filtered |
||||
by published in the software selection menu. |
||||
|
||||
Most user-visible software item metadata is provided using ``info`` |
||||
elements. Each ``info`` element must have a ``name`` attribute and a |
||||
``value`` attribute. The ``name`` attribute identifies the type of |
||||
metadata, and the ``value`` attribute is the metadata value itself. |
||||
Note that ``name`` attributes do not need to be unique within an item. |
||||
Multiple ``info`` elements with the same ``name`` may be present if |
||||
appropriate. This is frequently seen for software sold using different |
||||
titles in different regions. |
||||
|
||||
MAME displays metadata from ``info`` elements in the software selection |
||||
menu. The following ``name`` attributes are recognised specifically, |
||||
and can show localised names: |
||||
|
||||
alt_title |
||||
Used for alternate titles. Examples are different tiles used in |
||||
different languages, scripts or regions, or different titles used |
||||
on the title screen and packaging. MAME searches alternate titles |
||||
as well as the description. |
||||
author |
||||
Author of the software. Items can be filtered by author in the |
||||
software selection menu. |
||||
barcode |
||||
Barcode number identifying the software package (typically an EAN). |
||||
developer |
||||
Developer responsible for implementing the software. Items can be |
||||
filtered by developer in the software selection menu. |
||||
distributor |
||||
Party responsible for distributing the software to retailers (or |
||||
customers in the case of direct sales). Items can be filtered by |
||||
distributor in the software selection menu. |
||||
install |
||||
Installation instructions. |
||||
isbn |
||||
ISBN for software included with a commercial book. |
||||
oem |
||||
Original equipment manufacturer, typically used with customised |
||||
versions of software distributed by a hardware vendor. |
||||
original_publisher |
||||
The original publisher, for items representing software re-released |
||||
by a different publisher. |
||||
partno |
||||
Distributor’s part number for the software. |
||||
pcb |
||||
Printed circuit board identifier, typically for cartridge media. |
||||
programmer |
||||
Programmer who wrote the code for the software. |
||||
release |
||||
Fine-grained release date for the software, if known. Use |
||||
YYYYMMDD format with no punctuation. If only the month is know, |
||||
use “xx” for the day digits. For example ``199103xx`` or |
||||
``19940729``. |
||||
serial |
||||
Number identifying the software within a series of releases. |
||||
usage |
||||
Usage instructions. |
||||
version |
||||
Version number of the software. |
Loading…
Reference in new issue