-
Notifications
You must be signed in to change notification settings - Fork 40
How to add a new game
RLE currently supports the following game consoles: Atari, Super Nintendo Entertainment System (SNES), Sega Genesis/Mega Drive, Master System, Game Gear and SG-1000. In order to add a game, you must complete the following steps:
- A ROM file of the game.
- An emulator that supports RAM access (i.e., for Sega Genesis and SNES, we recommend BizHawk).
- RLE installed.
Keep in mind that you may run the shared_library_interface_example to test the new game.
-
Under Retro-Learning-Environment/src/games/supported/ create two files <rom_name>.hpp, <rom_name>.cpp.
-
The new class should subclass its matching console (
AtariSettings
orSnesSettings
orGenesisSettings
). Note that the classes exist within the rle namespace. The new class must implement theRomSettings
class interface, which consists of the following functions:
void reset();
RomSettings* clone() const;
void step(const RleSystem& system);
void saveState( Serializer & ser );
void loadState( Deserializer & des );
ActionVect getStartingActions(const RleSystem& system);
void startingOperations(RleSystem& system); // optional
The implementations of ``reset``, ``savestate``, ``loadState`` and clone are trivial and can easily be implemented by observing another class' implementation.
The implementation details of the remaining functions is described in the following bullets.
- Implementing the constructor
The constructor should perform two actions:
call the
reset()
function and define theminimalActionsSet
as all possible unique actions that can be performed in the game, including combinations. For example, for Super Mario the minimal actions are:
minimalActions = {
JOYPAD_NOOP,
JOYPAD_DOWN,
JOYPAD_LEFT,
JOYPAD_RIGHT,
JOYPAD_A,
JOYPAD_X,
JOYPAD_A | JOYPAD_RIGHT,
JOYPAD_A | JOYPAD_LEFT,
JOYPAD_X | JOYPAD_RIGHT,
JOYPAD_X | JOYPAD_LEFT,
JOYPAD_X | JOYPAD_A
};
-
getStartingActions() - by defining the sequence of joypad keys that are needed to be pressed in order the start the game with a delay (set by inserting no-operation sequences between them). Try to reduce the delay to a minimum, as restarting the game occurs very often during training and reducing the delay will save valuable time. Configure the starting action according to the level, character and other game parameters you wish to configure. Useful macros for doing so exist in
RomSettings.hpp
. Additionally, if you compiled with SDL, you may uncomment the last line inRetroEnvironment::reset()
in order to view the screen while the starting actions are performed. -
Step() - This functions has two responsibilities: Computes the reward by subtracting the current score from the previous one, saved in the class internal variable, m_reward, and check if the game reached a terminal state. To extract the information from the game, read the RAM address the game holds the relevant data in. To find the address open the emulator (1.b) and create various save states of the game, in which the value of interest hold a different value (for example, two different score values). Many emulators, including BizHawk, include a "HexEditor" or "RamSearch" allowing you to search for address with specific values, number of changes, etc. Alternate between the save states and monitor the changes in RAM to find the addresses. A few tips:
- Some games tend to save the score in an hex format (score = 10 in the game will results with the value 16 being saved in the RAM or vice-versa) or allocate an entire byte for each digit of the score.
- Interesting RAM addresses tend to be located adjacently (score, time, lives, etc.).
- RAM maps for popular games are often available online.
Once the game’s source file have been created, open Retro-Learning-Environment/src/games/Roms.cpp
and include the game’s hpp and create the game’s class under RomSettings.
Re-run cmake:
$ cd build
$ cmake -DUSE_SDL=ON -DBUILD_EXAMPLES=ON ..
$ make –j 4