Getting Started as an Achievement Developer
Welcome to the world of Achievement Creation!
Technically an achievement is a group of conditions that must be met in a particular frame of the video game.
When you launch a game on an emulator with the RetroAchievements feature, the emulator is always checking if those conditions are met in the current frame. When all conditions for a particular achievement are met, it is awarded and the emulator stops checking the conditions for that achievement.
The process of creating an achievement basically involves 3 steps:
Finding a place in the game's RAM where the information you want is stored (examples: level, life bar, time, coins, holding a weapon, get an item, etc.).
Create conditions that must be met in order to award an Achievement.
Test if your achievement is working as expected.
Most likely you'll go back to step 2 and 3 many times to refine the logic of your Achievement.
In this doc we'll see how to accomplish the steps above.
After you're sure your achievement is triggering at the conditions you want, you can submit it to the server. We'll see more about it later.
In this guide we'll be using RAGens to demonstrate, and the game Sonic the Hedgehog. We are using RAGens but the same applies for the other emulators.
To begin, run the RAGens executable, and login when prompted. Next, use File -> Open and select whatever ROM you would like to find achievements for.
You should now have your main window running Sonic. There are 3 other dialogs we'll be using, which can be found under RetroAchievements in the menu. We'll be dealing with the Memory Inspector first:
The Memory Inspector can be used to find addresses in RAM for us to use. Essentially you are on a treasure hunt for memory locations - this dialog will help you examine and filter the game's RAM while the game is running. If you want a step-by-step video explanation on finding memory addresses, this video can be very useful.
To start or restart a test, click New 8-bit Test near the top middle.
To keep things simple, we'll start by looking for the memory address which holds the number of rings we have collected. Our steps will be the following:
Load the ROM and start a new game.
Reset the memory dialog: click New 8-bit Test.
Return to the game and change the number of rings in memory. For example, collect a ring.
In the memory dialog, we now want to filter for values that are 'greater than previous values' (symbol
>). We select this, then hit Filter.
Each time you perform 3 then 4, the number of possibilities or 'candidates' will get smaller. We will continue doing this until the number of candidates reaches a very small number (as few as possible), it might take 4-5 attempts. Next we can click in the results window, and monitor the memory address in the memory viewer at the bottom. Continue using the game and you should see the values in memory change as you collect rings. If you don't, or if something doesn't look right, try another value. With the first Sonic the Hedgehog, the memory address for the number of rings should be
Note: Using save states (F5 to save state, F8 to load state, F6-F7 to toggle which state to use), you can switch back and forth between different states allowing you to alter what is in RAM, and use this to filter out bad candidates. You can search for values that remain the same (I.e. If you know the value didn't change, use
=), or values that are different (use 'not equal', symbol
Note: There's unfortunately no guarantee from game to game on how the developers have stored their data (4-bit, 8-bit, 16-bit, binary-coded decimals, negative/inverted, i.e. using 0xff/0xffff to represent 'set', or plain randomly), but eventually you should come across some good address. Note if you are struggling to find good values, post RetroAchievements.org Development Help forum, or RetroAchievements Discord server. There are plenty of people who will be very happy to help!!
Tip: if you'd like to experiment with memory, try entering new values directly into the RAM viewer. This can have devastating effects on the game, or it might do exactly what you expect, (or nothing at all!) It can be useful though, to see if you can enter a value and get the result you expect. Use with caution!
When you've found an address you're happy with, you can write a short note for what it is and hit Save Note, this will store it on database, and will be automatically restored next time you load up the memory viewer for this game, wherever you are! Note that after clicking 'Save Note', the note will be automatically stored on the database, and shared so all developers will share access to these memory notes. They will all be downloaded afresh when you load a ROM. If you try to overwrite a note, it will check with you first before submitting.
You can find more useful Memory Digging Tips here.
OK so the memory location for the number of rings is stored at
0xfe20 - note to a non-programmer, we're dealing in hexadecimal numeral system which can be daunting, but don't worry, essentially its just numbers and letters instead of only numbers, and not forgetting
0x at the start to show that it's a memory location in hex. We've found an address we're interested in and stored it using Save Note. We now want to create a new achievement.
Go to the RetroAchievements in the menu, choose Achievement Sets and you'll see this dialog:
Here we group all the achievements we know about into three sets: 1. Core Achievements (the main, public Achievement set), 2. Unofficial/User Achievements (public, but will not award you points: for peer review), 3. Local Achievements (personal to your PC).
In the Achievements dialog, click Local Achievements (top left), then Add New Achievement (bottom left). This will add a blank entry to the list in the center. Double click on it: if it's not already open, this should select it and open the Achievement Editor dialog.
This is how it looks:
This is the final dialog where we bring all the data together. Most of the top fields are self explanatory, I.e. Title, Description, Points. The main one is the 'Requirements' part.
Let's say we want to add an achievement for collecting a certain number of rings. Let's say 15 rings for simplicity. After filling out the fields at the top and selecting a suitable icon (in this example we used the gold trophy badge (00136), but you can upload a new one), we need to fill out Requirements. We have one requirement, that the number of rings is at least 15. Next click is Add New Requirement.
Clicking this button will add several default values to the Requirements list. These defaults just ensure that something relatively sensible is added to the list. For now, ignoring the field 'Special?'. When we clicked create, the default memory value will be whatever value you last left in the memory dialog.
Next we will change these values to the following:
>=- this is the comparison to make. We could have any comparison here, but it's sensible to have "greater than or equal to". This is important because if we get 10 rings then a super ring box to have 20, we would miss out having exactly 15 rings.
Value- we're comparing this memory value to a fixed value: 15
Empty- this is only relevant when comparing memory to memory
15- the number of rings required: the value we are comparing the memory to
- Hit Count:
0- ignore this for now, its useful for when something needs to happen a certain number of times
With that set, we don't have any more conditions to add, so we return to the Achievements Dialog. To be safe, we should save our progress by hitting Save Local! This saves everything to file locally to ensure that we won't lose any progress.
- Note: usually achievements have more than one requirement to avoid it triggering in a wrong time (i.e. playing demo mode). In this example we are using only one requirement just to simplify the explanation. See more Achievement Creation Tips here.
Testing the Achievement
We can now 'activate' this achievement locally by hitting Activate on the right-hand side. This will start monitoring these memory locations and will award the achievement once all the conditions are true. Now we can go ahead and test to see if this achievement works!
If we press
Esc n-game, you will see the achievement show up as a demonstration of what it would look like in the in-game overlay!
The cheevo we created in this tutorial is very simple, it has only one condition: "collected rings >= 15". But the address to record the number of collected rings is also used when the game runs in "demo mode" (AI playing the game after your wait a while on the title screen). So, if Sonic collect 15 rings on demo mode this achievement will trigger, which is unwanted.
So here are some tips you always have to keep in mind when creating your achievements:
~~Never use~~ Avoid using only one condition as much as you can. Otherwise the achievement will most likely pop at the wrong time. This is the most common error by a developer
PauseIfDemo Mode: If the game has a demo mode, make sure to find the address for it and add
mode != demoor something similar in your achievements. More info about
PauseIfon the Achievement Logic Features page.
PauseIfcheat codes: If the game has a cheat code to increase lives, select stages, etc. Make sure to find the addresses for it and add some kind of protection in your achievements. OK, maybe it's not a very basic topic, but you have to keep it in mind when creating a real achievement set.
OK, the Achievement works. Now What?
Once we have tested that the achievement works locally, there is a two-step commit process:
First in the Achievements Dialog, we select our achievement and press Commit Selected, and agree to the dialog. This will push our achievement to the server and store it under Unofficial User-submitted Achievements.
For the achievement to be enjoyed by many, it must be pushed into the Core Achievement set. For your few first achievements, it must be reviewed by a staff member before it can be pushed to Core. Once you have uploaded a set of achievements to Unofficial, you need to contact an admin who will, using their judgement and personal standards of quality to approve the set and give you a Developer status on the site. In which case you can push any achievement to Core yourself.
Naturally, it's best only to submit achievements that are unique and interesting into the Core Achievements group. If there are duplicates in the Core group, the most recently added duplicates will be manually moderated and deleted. If you don't want your achievement in the Core group, or you think it might not be appropriate for the Core group (i.e. if it's incomplete, or if sometimes it appears to trigger when it's not supposed to, like when the game is showing a demo), leave it in the Unofficial/User Submitted section.
Now that you know how to use the Memory Inspector, and the Achievement Editor. It's time to learn new techniques and practice:
In order to refine your achievement logic, you can see what features you have in the Achievement Logic Features page.
You can learn by looking at existing Achievements that other devs made with an extra explanation in the Real Examples page.
You can also see some generic examples in the Achievement Templates page.