Detecting a PS2 Emulator: When 1*X does not equal X
fobes.dev
fobes.dev
edit: described in more detail here, among other emulation-busting measures from 2004 https://mgba.io//2014/12/28/classic-nes/
X86 has that machinery although I'm not sure if they dropped it eventually on the 64-bit variant.
Both Intel and AMD implement SMC detection that is a bit stronger than required by the specification as well.
- Branch delay slots (https://en.wikipedia.org/wiki/Delay_slot), where one or more instruction(s) after a branch would be executed before the branch actually occurred.
- Load delay slots, where values stored into registers weren't guaranteed to appear until some later instruction. I believe the the value in the register was undefined for several cycles?
Writing tightly-optimized assembly code for these chips was pretty horrible, sort of like playing an unusually tasteless Zachtronics clone.
Things like deliberately using the fact that multiplies only write the results into a register ~6 cycles later, means you can use that register for a bunch of other stuff in the meantime, and then on the 6th cycle the results would magically appear.
Basically, for those 6 cycles, you had no registers in-use for either the source operands or destination of the multiplication.
Obviously this is also pipelinable - you can start more multiplies while the first is running, using the same source and destination registers, but meanwhile you've used other instructions to load more data into the inputs and do something else with the outputs.
Use mGBA instead if you want to play Gameboy games in 2024
However, someone much later found another undetected edge-case: a self-overwriting repeated string instruction.
https://silviocesare.wordpress.com/2009/02/02/anti-debugging...
Dolphin had to reckon with that balance when a few commercial Wii games included such anti-emulator code, which abused details of the real Wii CPUs cache behavior. Technically they could have emulated the real CPU cache to make those games work seamlessly, but the performance overhead (likely a 10x slowdown) would make them unplayable, so they hacked around it instead.
https://dolphin-emu.org/blog/2017/02/01/dolphin-progress-rep...
Edit: it was errata #657417, long since scrubbed from arm.com
You're just making your software worthless in the long run for some value probably less than 5 years, or creating a fun problem for an emu hacker.
Most of the significant losses to piracy monetarily isn't emulation, it's the chippers/mods that bypass cloned media copy protection.
Which emulator authors have a lot more control over in bypassing
When it comes to speedrunning: Some speedrunners do, though, to ensure their speedrun tech are reproducible on both emulators and real hardware.
For the SNES and earlier it's feasible to have exceptional accuracy and still usable performance, but for anything modern it's just not happening. Imagine trying to write a cycle-accurate emulator core for a modern CPU with instruction re-ordering, branch prediction, prefetching, asynchronous memory, etc, nevermind making it go fast.
I think the cutline can be moved to the original PlayStation now.
>but for anything modern it's just not happening.
Which arguably explains a cultural rift in arcade emulation circles. MAME's philosophy is about cycle-accuracy, which might work for bespoke arcade hardware up to early 3D systems, whether they're bespoke (such as Namco's System 22) or console-derived (Namco's System 1x series, which all derive from the original PlayStation hardware) hardware. For newer arcade titles, which are just beefed period PCs, such kind of emulation (philosophy) would not be suffice for gameplay.
beebjit [1] is a cycle-accurate JIT-based emulator for the BBC Micro. It can be done.
You basically have to understand electronics and deep programming wizardry
For instance, I ported a 6502 interpreter from UNIX to Classic Macintosh back in the day. This was to play SID music files. So long as it ran fast enough, clock cycle accuracy wasn’t important.
It worked by calling C code from the interpreter.
http://www.6502.org/users/obelisk/6502/registers.html
http://www.6502.org/users/obelisk/6502/instructions.html
Your 6502 CPU emulator would read the next few bytes of the program, interpret the bytes as an instruction, execute the instruction, which involves updating a couple of registers/counters in the CPU, doing some arithmetic or bitwise operations, and possibly loading or storing a byte of data from one location to another. This process is then repeated in an endless loop.
It is a simulation of the fetch-decode-execute cycle.
I learned about the basics here http://www.emulator101.com
Then I read the docs at NESdev Wiki and eventually wrote my own NES emulator.
https://www.nesdev.org/wiki/Nesdev_Wiki
If you have good documentation then you're just following the specs and turning that into code. Next level difficulty is reverse engineering the hardware, figuring out how it works when there isn't any documentation. These guys did that for NES back in the 90s and early 2000s, writing little test ROMs to see what the hardware does, in addition to whatever official or unofficial developer docs they could find.
You really don't have to understand any deep wizardry to get started (or, for the most part, even to finish). For the most part, you just look at a specification, and implement what it says. It requires some code architecting skill to not make a mess, but there are common patterns and it becomes a lot easier once you've built one or two emulators.
And you almost never need to understand electronics. You're only emulating behavior. When someone discovered bugs in the behavior of the original hardware, you usually just need to special-case it in your emulator. It might help to know some electronics to understand how those behaviors came to be, but that's more so of historical interest than actually practical.
There are certain unique challenges, but it's nothing too difficult. When there's an issue, you're usually debugging three things at once: Your understanding of the hardware, your implementation of the emulator, and the game you're emulating. It can be hard to pin down the exact problem. But here, I encourage you to just hack something together. It's not clean, but all emulators are full of special cases that try to somehow get popular games working. If a couple unclean hacks mean you can get a game working, just do so. You don't really need to exactly implement the original hardware's behavior. Just get the game working.
(otherwise @xcv123's sibling comment is very true).
Some day replicating the PS2 on an FPGA will be feasible, and then figuring out how this worked will be a fun project for someone.
A software emulator has to be able to execute a single PS2 instruction in the same amount of wall time as it'd take on the original hardware. With a regular multiplication that's fairly easy: x86 also has multiplication, so you can do a 1:1 translation and be fairly certain it's within your time budget. With a bugged multiplication you need to do a regular x86 multiplication, and wrap that in a few dozen other instructions to add the buggy behaviour to it. There's a pretty decent chance it's simply too expensive!
When you're writing an FPGA emulator you are able to recreate the buggy multiplication directly in hardware. There's no additional wrapping needed, so (beyond figuring out intended behaviour) it's not any more costly than emulating a non-buggy multiplication. It's far easier to do a cycle-accurate emulation because you have direct control over the transistors!
I doubt the 24 year old, 300Mhz RISC, 32MB Ram, PS2 instruction set is too expensive to do a cycle perfect replication.
Full-speed emulation for the Super Famicom base unit requires an Intel Core 2 Duo (or AMD equivalent), full-speed for games with the SuperFX chip requires an Intel Ivy Bridge (or equivalent), full-speed for the wireframe animations in Mega Man X2 requires an even faster computer. Low-power CPUs like ARM chips, or Intel Atom and Celeron CPUS generally aren’t fast enough to emulate the Super Famicom with higan, although other emulated consoles may work.
Work can't be split across cores (according to the FAQ) because that would compromise the accuracy of the timing.
It may be that the PS2 has similar problems while being more powerful than the SNES.
Remember that you can't just perfectly emulate the CPU, you must also perfectly emulate the GPU, since they share the memory bus so one can slow the other.
You can look more into this in this video by Kaze Emanuar, famous N64 romhacker.
Cycle-accurate PS2 emulation means emulating the state of the CPU, GPU, other interacting processors, and their various interconnecting busses at clock cycle granularity and possibly at sub-cycle granularity if the processors are running asynchronously.
Try running that on a cycle accurate emulator without bringing an i7 to its knees.
A similar PC would be a Pentium II-III at 450-500 MHZ with 64MB of RAM running Damn Small Linux or NetBSD with a small Window Maker setup. Bear in mind that you could run a non-accurate SNES emulation in that machine, with sound outputted at 8000 HZ and with no filters, enough for most common games such as Chrono Trigger and Super Mario World with lots of hacks fixing the imprecise timing under ZSNES.
Yes, software floating point would be slower, but the general solution would probably follow the PS4s PS2 emulator. Where each game can have whitelisted sections of code for the software floating point path.
The result was terrible, but I had tremendous fun!
Free time is scarce, so I’ll gladly pay a couple hundred to not have to spend time fiddling with settings only to ultimately capitulate.
As far as I can tell, his reasoning is literally that 2x2=4, so if you divide both sides by 2, you get 1x1=2.