HOWTO
1) Write a controller
2) Find the current score in a game that is not listed in score.dat.


Write a controller
------------------------

The best way to know the interface is to look at dummy.c and to
randomplayer.py for the C and Python bindings.

In both cases the interface is almost identical.  Only one function
whose name is predefined is necessary to be supplied by the agent
library, called acGetFunctions. This function is supposed to return an
ACFunctions structure (look at src/ac/ac-common.h for all structures)
pointing to a function which will be called once on start up, a function
which will be called once on exit, and two functions which will be
called repeatedly, one to update the state, and the second to obtain
the agent's actions.

So the flow is a bit like the following:

Mame started, acGetFunctions called.

start function called with the parameters passed on
command line through ac_options, and a structure specifying the name
of the game, and the bitmap size to be expected.

While in game:
	  update function is called with current score and current frame
	  buffer.  The update function is meant to return the number of
	  frames to skip till the next update (0 to receive the next
	  update available). This is just to speed up processing in the
	  case that not all updates are desired.  Even if the update is
	  not sent, the actions will still be polled.

	  actions function is called with no parameters asking for the
	  state of the buttons (non-zero for pressed, zero for not
	  pressed). Look in ac-common.h for the order of the buttons.  

on exit, the exit function is called with no parameters.


The format of the bitmap passed to the agent is BGRA (although this
will probably be run-time selectable in the future).  That is, one
unsigned byte for the blue, green, red and alpha values of each pixel
in turn.  The alpha channel can be ignored since it will always be
255. In the python bindings, this is passed as a string.  Look at
randomplayer.py about how to convert it into a more usual image format
through PIL.

----

Finding the current score
-------------------------

MAME comes with a very useful in-game debugger, and people have been
very interested in keeping their high scores table, so a short
tutorial available at Mame high score tutorial
http://www.mameworld.net/highscore/tutorial.htm on how to find these
high scores can be easily adapted to finding the current score. The
size of the score in bytes can also be guessed from the large
collection of high score address ranges described in the hiscore.dat
file available from Mame high score download page
http://www.mameworld.net/highscore/download.htm which MAME uses to
save these high scores table.

The process involves playing the game, pausing at some point, and
searching for some encoding of your current score in RAM with the
debugger. Since the encoding is unknown prior to finding the score, a
lot of different encodings probably have to be tried. The CPU family
used for the game should be consulted since this will likely limit the
types of encodings that are likely to be used, especially regarding
little versus big-endian choices. A non-complete list of encodings
follows:

 1. 8, 16 or 32 bit numbers encoded in big-endian format. Big-endian
 format is easy to spot since it looks natural on the screen of a
 debugger. In big-endian format, the most significant byte is stored
 at the lowest address, the second most significant byte at the second
 lowest address, and so on, so for example, the hexadecimal number
 0x12 34 56 78 will appear on a debugger as 12 34 56 78.

2. 8, 16 or 32 bit numbers encoded in little-endian
 format. Little-endian format stores the numbers in reverse, i.e. the
 least significant byte is stored in the lowest address and the most
 significant byte in the highest address. This gets slightly more
 complicated due to the data width of the CPU, since if the number
 does not fit in the data width, the number is likely to be stored
 with the least significant word in the lowest address and the most
 significant word in the highest. Going back to the example, 0x12 34
 56 78 would be encoded as 78 56 34 12 in a 32-bit width word CPU, but
 as 34 12 78 56 in a 16-bit word CPU.

3. Decimal encoding stores numbers as if each nibble could only store
 10 states instead of 16. This makes the number very easy to spot on a
 debugger since it becomes the decimal score as normally written. For
 example if the score is 1857 then the memory in hexadecimal will be
 0x18 57. Big and little-endian formats of this encoding are likely to
 be encountered. Although this kind of encoding seems to have been
 popular in early arcade machines (late 70s, early 80s), it is not
 common in later games.

4. Modifications of current score. For example, if the score is always
 a multiple of 10, then it is likely that the last zero is not stored
 in RAM, only getting added at display time, so if the score is 18530
 then encodings of 1853 should be looked for as well.

Once the location and encoding of the score is known, the memory can
be read by the MAME utility function cpunum_read_byte defined in
src/cpuintrf.h, and decoded.

If you find the location of the current score in a game not currently
listed in score.dat, please email me at alito@organicrobot.com with
the details.


