Skip to content

Tips and Tricks

Achievement Creation Tipslink

  • Never use / Avoid using only one condition as much as you can. When using only one condition the achievement will most likely pop at the wrong time. This is the most common error by a developer resulting in "Popped at the Wrong Time" reasoning attached to Bug Tickets received at Write your achievements soundly.

  • PauseIf Demo Mode: If the game has a demo mode (AI plays the game after you wait a while on the title screen), make sure to find the address for it and add mode != demo or something similar in your achievements. You'll probably need to know how to use PauseIf and ResetIf.

  • Protect your cheevos: If you wanna create an achieve for getting a specific and unique item in the game, add some conditions to make sure the player got the item where it is supposed to be obtained, like in this template here. Otherwise the achievement will be earnable by loading a state.

  • Resetting Happens: Some emulators send some addresses in RAM a specific value when reset/reloaded. It's only for the first frame, but it can cause achievements to pop up, so you need to prepare for it. It's usually all one value like FF. You can see the value if you use Frame Advance / Next Frame while resetting the game.

  • Limitations: There's a 100 achievement cap, 400 point cap, and a character cap for single achievements (try not to put 50+ conditions in one achievement).

  • Alt groups (left side of editor) are used for "or" conditions. The core group is always there and must always be true with at least one alt group being completely true to get the achievement. The entire group is your "or" condition. More info on the Achievement Logic Features page.

  • Avoid Achievement spam. If a game has 100 levels, do not make an achievement for each level. Do every 25 or so. It is generally looked down upon by RA's development team to code these "Filler" type Achievements. If you intend to create a few progressive unlocks in this manner - the words: ("Easy", "Medium", "Hard") will help to put you in context. Consider the time segment a casual player would unlock these progressive Achievements in. If generally you could unlock all in a progressive set of Achievements of this nature in under half an hour as a casual player, that's filler design, and not recommended.

  • Be Creative and Fun: Get as creative as possible with achievements. "Beat X without using/doing Y", "Beat X in 5 seconds", "3 heart run". Be sure casual players can still get these with their best effort. It isn't fun if its way too difficult for a casual player! (See: Bonus Set Tips below for the real challenges!). There is a whole page about Achievement Design that can give good advices on how to think about good achievements.

  • Glitchless, please!: Do not make achievements requiring glitches. Glitches, in most cases, corrupt and destabilize game memory and RAM. They break the rest of the set to include. It is however, wise to code block walls stopping players from using them to get easy mastery. This is a topic of much debate on RA, since performing a game-breaking glitch sometimes requires a lot of player skill. Some glitches are possible on console-only, some on emulator-only. For their inconsistency and instability in regards to memory, it is recommended that you blockwall them to protect the integrity of your set and its/your reputation. (This is an exceptional issue in some GameBoy games, where playground talk in glitching your way to victory was prominent!)

  • We love Art: Pretty badges are rewarding badges! It should visually represent the achievement itself, or hint at the location in the game for secrets. Matching to the game's art style works well. Google Image searches for "Sprite Sheets" is an useful tip to include some game art. If you're a good graphics artist, updating badges is your time to shine! More info can be found at the Badge and Icon Creation page.

  • Uncheck "Show Decimal Values" in the Achievement Editor so you can enter the hex values you see in the Memory Viewer. Its better than using a programmers calculator!

  • 16-bit Secrets: 16-bit requirements do not have to be used on an even number of RAM, they can be used in-between properly, even if 16-bit view doesn't show it right. Ex: 0 1 2 3 4 5, in 16-bit it's usually viewed as 10 32 54, but if you start the address at the 1 here in your requirement, "21" will be read by the achievement, even if 16-bit view in the memory viewer isn't showing it. It also works if it's the last address in the line(starting at F, going to 0). Be aware that if you're coding for LE cores as well, you'll have to update this, too! Always leave descriptive code notes for yourself or someone else.

  • Bit field Secrets: Use single bits(0-7) for things that only change a single bit. In the Memory Viewer, when an address is selected, there will be "bits 0 1 2 3 4 5 6 7" above the addresses, and below those numbers will be either "0" or "1" like "0 0 0 0 0 0 0 0" if bit3 has a 1 under it, bit3=1 for that address. Single bit usage is very common for game events/unlocks/etc.. You'll want to use these in games where you can do things in different orders, dialogues, events, unlocks.. If you check for "8-bit x = 7" and someone did something different like skip something or get something extra, their 8-bit value will very likely be different because the single bits within are different and the achievement won't unlock, so in this case you check for specific bits inside the 8-bit address. Now if for example, item unlocks use all 8 bits of the 8-bit address, and you want to do "unlock all items," you can just do "8-bit x = 0xff" This may be confusing, but it's very important to understand. Some games with limited memory space use bit fields a lot! Its an important technique to learn.

Naming Convention Tipslink

  • No Symbols: Do not use accented/special characters like the "é" in Pokemon, as they currently break a few things (like feed). They are also not visible in search without the special character.

  • No Emojis: Do not use UTF-8 Universal Emoji codes in your achievement names or set names as the display of these codes is entirely platform dependent (i. e.: Mac OSX, Windows, Linux, iOS, Android, and browser).

  • Mind your English: avoid grammar mistakes. As RetroAchievements is an international community, using English for Code Notes is a good practice, as another developer can use your notes in the future. If English is not your first language, running your achievement titles, names, and code notes through a spell checker will help. It is an extra step for those having difficulty with the English language, but the amount of care and attention to it reflects back of your positive qualities as a developer.

ROM Selection Tipslink

  • Region Selection: Choose NTSC USA release ROMs if available, because 60 FPS is a smoother gaming experience. PAL European releases run at 50 FPS, and are to be avoided in most cases. NTSC Japan releases also run at 60 FPS , but is only the best choice if the game was a Japan-exclusive release. Needing to resort to a PAL European release game should be a last resort case (Europe-only exclusive), and is typically a very select few unique games from the entire console's library.

  • No Mods: Do not use a ROM with a modded/custom launch screen like Mode7 and RisingSun have because it messes up RAM.

  • No Trainers: Do not use a ROM that includes an integrated cheat feature. These are most often refereed to as after-market ROM trainers, are not official, and not in any way supported by Retro Achievements.

Memory Digging Tipslink

  • You can input values in the memory viewer to see if it affects the game.

  • If you find an address, also search the same region surrounding it and you could find many more useful addresses.

  • Even if something is visibly decreasing in-game, like health, the value isn't necessarily decreasing. It's possible for it to be increasing, so since it's uncommon for you to know for sure, you should just filter != and ==.

  • If you absolutely cannot reduce the results of a filter, you can try guessing some values or at least how the value is acting (> or <). For example, no health is usually 0, Stage 1 is usually value 0, Stage 2 is usually value 1 depending on the type of game. Another example, maybe each segment of health has 4 pie slices - Should you be searching when "4" goes to "3" when you lose a slice?

Tips by Skill Levellink

Level 1 - Easylink

Start with 8-bit view in the Memory Viewer. Looking at larger chunks of memory will complicate things, but it will make a seasoned developer's job easier. If you're just starting out and unaware of terms like endianess and bit ordering (or when the eyes are tired), its best to make your observations in 8-bit view. Its just easier!

Level 2 - Intermediatelink

Big Data (16 or 32 bit view): Just remember that when adding a 16-bit address that the address to the right comes first.

Example: AB CD WX YZ in 8-bit will becomes CDAB YZWX in 16-bit.

This is called "big endian byte ordering". You can safely ignore the geek-speak by just remembering things are stored backwards in 16 bit view and above.

Remember that if you are seeing memory in bigger chunks, when you highlight a value, that value now represents a 16 or 32-bit "chunk" of memory, and not the 8-bit memory address you may be looking for. You'll need to drop back down to 8-bit view and highlight the interesting piece if you find something 8-bit that looks interesting.

Level 3 - Advancedlink

Adding support for libretro Little Endian Cores: N64-specific, most times, when adding support for a libretro LE core to your set, concepts from intermediate apply, with the byte ordering changed slightly. What is seen human readable in 16-bit changes drastically in an LE core's insides.

Example: AB CD WX YZ first takes A's bits, flips them around like looking at them in a mirror, B's bits, flips them around, C's bits... etc, all the way to Z, and then becomes WXYZ ABCD with the bytes from your last step.

To add your LE support, you'll be writing a dummy core condition (Mem 0x000001 = Mem 0x000001), copying your original non-LE conditions with a PauseIf at the top into one Alt, copy the same conditions to the other. Both PauseIfs will contain a check looking at a memory address that never changes to see if its 16-bit value has had its byte ordering changed (Think of this as "PauseIf I'm not on an LE core" and "PauseIf I am" alt conditions).

One will run if the gamer is running on an LE core, one wont. You'll then perform the math I described above on the values you're checking for in the "PauseIf I'm not on an LE core" Alt, and updating it.

Confusing? Yes. This is why most beginners and intermediate developers should not worry.