Most emulators don’t work exactly like the original console, and some games use obscure features or undocumented behaviors to squeeze out performance or to create some specific effect.
Usually the people who make emulators tries to fix that with hacks and special overrides for games that are broken, but not every game has an emulator developer that cares about it.
Different reasons, but most often it was because games later in the lifespan of a console, when developers had experience with said console, could pull off some tricks to implement new features like early 3D or rotation of sprites. For example, Wulff Den explained here that yoshis island had a special fx chip in the cartridge to do some extra graphics effects the console couldn’t do, and as such, Yoshis Island is notoriously hard to emulate because you have to emulate the extra chip as well.
Coding the “base” of an emulator is one thing, but the bigger thing is trying out games and see if they run (or realistically, when and how they crash), see what needs to be done and either implement that function into the emulator or find ways to go around it. Example for this is ShadPS4, a PS4 emulator, that specifically started debugging with Bloodborne and got it to run, however, the custom faces of NPCs started to explode. The developer of the emulator can start searching for the issue why that happens, and in the meantime, theres been a patch that simply removes face customization so the issue doesn’t happen.
Consoles are like black boxes. You put game in, some magic happens, you get picture on screen that you can control. People have to figure out what that “magic” is because the console manufacturer obviously doesn’t want you to run games somewhere else. Also, that “magic” could be very easy to figure out (e.g. the Atari 2600 because it’s simple graphics and simple controls), or very complex to figure out (e.g. the Playstation 3 because of complex 3D graphics and a new type of processor)
And on top of that, the chips inside a computer and the chips inside a console are different. Emulators let you run console games on computers by “translating” instructions from the console into instructions your computer can understand.
Think of the translation process like literally translating from one language to another. Imagine trying to translate a slow song from English to Korean in real time. Then imagine trying to translate a very fast rap song from English to Korean in real time. One is easy because there’s not much to translate (e.g. the Atari 2600) and the other is nearly impossible because you need to translate multiple words per second (e.g. the Playstation 3)
Young Monk: “Do not try and [emulate the original console hardware exactly] —that’s impossible. Instead, only try to realize the truth.” Neo: “What truth?” Young Monk: “There is no [console].”
Emulation is about playing the games, so you implement the hardware features that make most of the games work. This means some games that use the more exotic hardware features of the original console will not work as expected, and extra work is needed for these games.
Sometimes the emulator isn’t perfect. The console operates in a very specific way based on very specific hardware clocks regulating the system. The emulator writer is generally only concerned with making sure the right amount of work gets done every frame.
A frame happens every 1/60 of a second. But the console’s concept of a “frame” is usually a clock cycle. On an NES, that happens every 1/24,000 of a second, roughly. Everything the system does takes some number of “cycles” of the CPU clock to finish.
A lot of times the emulator’s author goes about handling that in a rough way. They figure out how many cycles “should” happen in 1 frame and do the emulation work for that many cycles before waiting for the next frame. For a lot of games, that’s “good enough”.
But some games do really weird things. Like, for example, maybe the console has a quirk like, “The CPU instruction to write to this memory takes 4 cycles, but on real hardware there is also an 8-cycle delay for the memory to update because that memory is very slow. ” The game’s programmer may have known this and decided to make some random behavior in the game depend on writing something to the memory then reading it BEFORE the write finishes. On real hardware that’ll tend to get some weird value that isn’t predictable. The emulator author may not have understood that and may update the memory as soon as 4 cycles are over. Even if they do wait 8 cycles, the way the emulator transitions directly from the old value to the new value may not be the same as how the hardware worked (sometimes while you write to memory, you see weird “in-between” values if you read too early.) This will change how the game behaves and may break it.
Also you can’t evenly fit most CPU clocks into a single 60 FPS frame. The NES CPU executes 29,829.55 cycles in a 60FPS frame. The emulator can’t execute 0.55 cycles. It has to decide whether to do 1 cycle too many or omit one cycle every frame. If a video game was extremely optimized and did some things with cycle-perfect timing, this means the emulator can “miss” the right time window for the game and that can break it.
This gets even trickier when you consider almost all consoles have MULTIPLE processors doing different things. For example, the NES has a CPU, a PPU, and an APU. Those are three different microprocessors operating at 3 different clock speeds doing 3 different jobs simultaneously! The CPU can “send” data to each of them, but it takes specific amounts of cycles to send data and specific amounts for them to process it. So the emulator’s author has to juggle all three clocks every frame and do their best to get the “right” amount of work done. Tiny inaccuracies add up.
So it’s really hard to emulate things PERFECTLY. Those tiny little flaws can upset programs that were written to rely on very specific hardware behaviors.
Emulators use a lot of tricks and guess work to get games to run in environments where they weren’t designed to run. A short explanation is something like: developers found if they used the formula A+B=D it always worked because the calculation was always 1+2=3.
But then one game stood out for some reason and the formula should’ve been A+B+C=D. In most games the calculation was actually 1+2+0=3 and the other game was 1+2+3=6. When C=0 the old calculation still worked and that’s why those games worked and the other game didn’t.
Computers (including “consoles”) all expect certain machine code to perform operations. Think of machine code like English words – “Draw this”, “Clear the screen”, “Store X”, “Retrieve X”, “What is 5 x 2.538?”, etc.
Emulators do their best to mirror exactly what those consoles would have returned when the same code is put in, but often the result given back is not exactly what you would expect for various reasons, and it’s really difficult to mirror what the physical console did exactly (e.g. For a simple example, the time taken to retrieve the data may impact what the answer is, but your computer has RAM that is 15x faster than that on the original console, so the timing is different). On more modern hardware, even the physical distance of the RAM from the CPU (or other elements of the motherboard’s physical layout) might matter – and no programmer is going to start their day by trying to measure the distance the RAM is from the CPU in inches or millimetres and then try to translate that to a specific memory latency.
Once you’ve successfully implemented the instructions themselves, you might have to include undocumented instructions (e.g. there are plenty of undocumented “OpCodes” for the PlayStation 1), and there are some edge cases that might be handled by hardware rather than software (e.g. what to do when you divide by zero).
For example, this means one game might avoid dividing by zero (because why would you ever do that intentionally?), when another one intentionally divides by zero because the programmers realised that it’s a quick way to set the memory to a specific value (either +1 or -1, depending on whether the sum was negative; making it a quick way to test the sign of the number). Another game might use the divide by zero option as a mistake when it divides through every item in a list, but relies on the specific timing of the operation to mean the mistake goes unnoticed, but your faster CPU means that the divide-by-zero operation now occurs before the memory update occurs – which means that without a specific “patch”, the emulator you’ve written is going to handle divide-by-zero errors differently, depending on how quickly the game reads the memory location after it’s run.
This means you might get three different games:
Game 1 (Avoids divide by zero): Runs fine, no flaws.
Game 2 (Uses divide by zero to set memory): Runs fine (after you implement undocumented, divide-by-zero-logic), no flaws.
Game 3 (Uses divide-by-zero by accident, but this is unnoticable on original hardware): Has major isseur at the same time relative to the instructions that the original hardware did.
This is just one example of how easy a trivial operation might rely on interactions that could completely go unnoticed in some games, work fine or reasonably fine in others, and completely break other games in ways that are difficult to debug.
Emulators are attempts to build the software that runs games from the ground up.
It is essentially code designed to pretend to be a console.
Let’s imagine:
A car, all the things you can press and change, peddles, steering wheel, radio, air vents, etc, this is your console.
The motors, fuel tanks, engines, axles, etc are the game.
Now, let’s remove all the bits you can control and now is just a bunch of exposed wires. You don’t know who h do what.
You learn when you apply power to one, the breaks apply, so you make something that now acts as breaks. And you keep doing this until you can drive your car.
But you still have a bunch of wires you don’t know what to do with.
You drive on a motorway, a game that works well and it is fine.
Now suddenly you are driving down a foggy road. You haven’t wired up the fog lights, because you never encountered anything that needs it. Now you have a game that doesn’t work well.
And then you run out of fuel, because you didn’t realise one wire was for warning a critical issue. Now you cannot even start the car, a game that doesn’t work at all.
Comments
Most emulators don’t work exactly like the original console, and some games use obscure features or undocumented behaviors to squeeze out performance or to create some specific effect.
Usually the people who make emulators tries to fix that with hacks and special overrides for games that are broken, but not every game has an emulator developer that cares about it.
Different reasons, but most often it was because games later in the lifespan of a console, when developers had experience with said console, could pull off some tricks to implement new features like early 3D or rotation of sprites. For example, Wulff Den explained here that yoshis island had a special fx chip in the cartridge to do some extra graphics effects the console couldn’t do, and as such, Yoshis Island is notoriously hard to emulate because you have to emulate the extra chip as well.
Coding the “base” of an emulator is one thing, but the bigger thing is trying out games and see if they run (or realistically, when and how they crash), see what needs to be done and either implement that function into the emulator or find ways to go around it. Example for this is ShadPS4, a PS4 emulator, that specifically started debugging with Bloodborne and got it to run, however, the custom faces of NPCs started to explode. The developer of the emulator can start searching for the issue why that happens, and in the meantime, theres been a patch that simply removes face customization so the issue doesn’t happen.
Consoles are like black boxes. You put game in, some magic happens, you get picture on screen that you can control. People have to figure out what that “magic” is because the console manufacturer obviously doesn’t want you to run games somewhere else. Also, that “magic” could be very easy to figure out (e.g. the Atari 2600 because it’s simple graphics and simple controls), or very complex to figure out (e.g. the Playstation 3 because of complex 3D graphics and a new type of processor)
And on top of that, the chips inside a computer and the chips inside a console are different. Emulators let you run console games on computers by “translating” instructions from the console into instructions your computer can understand.
Think of the translation process like literally translating from one language to another. Imagine trying to translate a slow song from English to Korean in real time. Then imagine trying to translate a very fast rap song from English to Korean in real time. One is easy because there’s not much to translate (e.g. the Atari 2600) and the other is nearly impossible because you need to translate multiple words per second (e.g. the Playstation 3)
Young Monk: “Do not try and [emulate the original console hardware exactly] —that’s impossible. Instead, only try to realize the truth.” Neo: “What truth?” Young Monk: “There is no [console].”
Emulation is about playing the games, so you implement the hardware features that make most of the games work. This means some games that use the more exotic hardware features of the original console will not work as expected, and extra work is needed for these games.
Sometimes the emulator isn’t perfect. The console operates in a very specific way based on very specific hardware clocks regulating the system. The emulator writer is generally only concerned with making sure the right amount of work gets done every frame.
A frame happens every 1/60 of a second. But the console’s concept of a “frame” is usually a clock cycle. On an NES, that happens every 1/24,000 of a second, roughly. Everything the system does takes some number of “cycles” of the CPU clock to finish.
A lot of times the emulator’s author goes about handling that in a rough way. They figure out how many cycles “should” happen in 1 frame and do the emulation work for that many cycles before waiting for the next frame. For a lot of games, that’s “good enough”.
But some games do really weird things. Like, for example, maybe the console has a quirk like, “The CPU instruction to write to this memory takes 4 cycles, but on real hardware there is also an 8-cycle delay for the memory to update because that memory is very slow. ” The game’s programmer may have known this and decided to make some random behavior in the game depend on writing something to the memory then reading it BEFORE the write finishes. On real hardware that’ll tend to get some weird value that isn’t predictable. The emulator author may not have understood that and may update the memory as soon as 4 cycles are over. Even if they do wait 8 cycles, the way the emulator transitions directly from the old value to the new value may not be the same as how the hardware worked (sometimes while you write to memory, you see weird “in-between” values if you read too early.) This will change how the game behaves and may break it.
Also you can’t evenly fit most CPU clocks into a single 60 FPS frame. The NES CPU executes 29,829.55 cycles in a 60FPS frame. The emulator can’t execute 0.55 cycles. It has to decide whether to do 1 cycle too many or omit one cycle every frame. If a video game was extremely optimized and did some things with cycle-perfect timing, this means the emulator can “miss” the right time window for the game and that can break it.
This gets even trickier when you consider almost all consoles have MULTIPLE processors doing different things. For example, the NES has a CPU, a PPU, and an APU. Those are three different microprocessors operating at 3 different clock speeds doing 3 different jobs simultaneously! The CPU can “send” data to each of them, but it takes specific amounts of cycles to send data and specific amounts for them to process it. So the emulator’s author has to juggle all three clocks every frame and do their best to get the “right” amount of work done. Tiny inaccuracies add up.
So it’s really hard to emulate things PERFECTLY. Those tiny little flaws can upset programs that were written to rely on very specific hardware behaviors.
Emulators use a lot of tricks and guess work to get games to run in environments where they weren’t designed to run. A short explanation is something like: developers found if they used the formula
A+B=D
it always worked because the calculation was always1+2=3
.But then one game stood out for some reason and the formula should’ve been
A+B+C=D
. In most games the calculation was actually1+2+0=3
and the other game was1+2+3=6
. WhenC=0
the old calculation still worked and that’s why those games worked and the other game didn’t.Computers (including “consoles”) all expect certain machine code to perform operations. Think of machine code like English words – “Draw this”, “Clear the screen”, “Store X”, “Retrieve X”, “What is 5 x 2.538?”, etc.
Emulators do their best to mirror exactly what those consoles would have returned when the same code is put in, but often the result given back is not exactly what you would expect for various reasons, and it’s really difficult to mirror what the physical console did exactly (e.g. For a simple example, the time taken to retrieve the data may impact what the answer is, but your computer has RAM that is 15x faster than that on the original console, so the timing is different). On more modern hardware, even the physical distance of the RAM from the CPU (or other elements of the motherboard’s physical layout) might matter – and no programmer is going to start their day by trying to measure the distance the RAM is from the CPU in inches or millimetres and then try to translate that to a specific memory latency.
Once you’ve successfully implemented the instructions themselves, you might have to include undocumented instructions (e.g. there are plenty of undocumented “OpCodes” for the PlayStation 1), and there are some edge cases that might be handled by hardware rather than software (e.g. what to do when you divide by zero).
For example, this means one game might avoid dividing by zero (because why would you ever do that intentionally?), when another one intentionally divides by zero because the programmers realised that it’s a quick way to set the memory to a specific value (either +1 or -1, depending on whether the sum was negative; making it a quick way to test the sign of the number). Another game might use the divide by zero option as a mistake when it divides through every item in a list, but relies on the specific timing of the operation to mean the mistake goes unnoticed, but your faster CPU means that the divide-by-zero operation now occurs before the memory update occurs – which means that without a specific “patch”, the emulator you’ve written is going to handle divide-by-zero errors differently, depending on how quickly the game reads the memory location after it’s run.
This means you might get three different games:
Game 1 (Avoids divide by zero): Runs fine, no flaws.
Game 2 (Uses divide by zero to set memory): Runs fine (after you implement undocumented, divide-by-zero-logic), no flaws.
Game 3 (Uses divide-by-zero by accident, but this is unnoticable on original hardware): Has major isseur at the same time relative to the instructions that the original hardware did.
This is just one example of how easy a trivial operation might rely on interactions that could completely go unnoticed in some games, work fine or reasonably fine in others, and completely break other games in ways that are difficult to debug.
Emulators are attempts to build the software that runs games from the ground up.
It is essentially code designed to pretend to be a console.
Let’s imagine:
A car, all the things you can press and change, peddles, steering wheel, radio, air vents, etc, this is your console.
The motors, fuel tanks, engines, axles, etc are the game.
Now, let’s remove all the bits you can control and now is just a bunch of exposed wires. You don’t know who h do what.
You learn when you apply power to one, the breaks apply, so you make something that now acts as breaks. And you keep doing this until you can drive your car.
But you still have a bunch of wires you don’t know what to do with.
You drive on a motorway, a game that works well and it is fine.
Now suddenly you are driving down a foggy road. You haven’t wired up the fog lights, because you never encountered anything that needs it. Now you have a game that doesn’t work well.
And then you run out of fuel, because you didn’t realise one wire was for warning a critical issue. Now you cannot even start the car, a game that doesn’t work at all.
I worked with the developer that “caused” the Disney Trio of Destruction for the Dolphin emulator. Really cool story.
In emulators the game quality looks kinda low.