Hacker News new | past | comments | ask | show | jobs | submit login

What does "cycle-accurate" mean? The README assumes the reader already knows; Wikipedia via Google is totally unhelpful: "A cycle-accurate simulator is a computer program that simulates a microarchitecture on a cycle-by-cycle basis."



The traditional way of coding a console emulator was to figure out the time interval to the next interrupt in units of CPU cycles, emulate enough instructions to cross that threshold, then emulate the interrupt and hook other routines (redrawing the screen, filling sound output buffers, reading input, etc.) off of those events (see e.g. Marat Fayzullin's classic Emulator HOWTO [1]). This approach runs a lot of stuff just fine because it does synchronize to the most important events, but can cause problems. For example, "well-behaved" code generally only writes to graphics registers or sprite tables during blanking periods, as writing during active display is usually undefined behavior. Some code breaks the rules. Sometimes this is done intentionally to do cool effects with the hardware. Other times it's a side effect of a bug that wasn't caught because there are coincidentally no symptoms with the timing of the actual hardware. But then you plug it into an emulator with only roughly accurate timing and it blows up.

In reality, the clocks for the various components don't necessarily run at the same rate, or even at integer multiples of the CPU clock. You can have a situation where, for example, there are 3.5 clock cycles on the graphics hardware for every one CPU clock cycle. For a lot of the classic systems, this happened because a single higher master clock is divided down for each component.

A "cycle-accurate" emulator is one that operates as if the emulated state of all hardware were updated on every tick of the master clock. This wasn't generally done in the past because it was far too slow ~20 years ago when emulation of classic consoles and computers really took off.

More sophisticated hardware doesn't necessarily have any single master clock in this sense, so it doesn't make much sense to talk about a "cycle-accurate" emulator of a modern PC, for example.

[1] http://fms.komkon.org/EMUL8/HOWTO.html


I played around with this in my own NES emulator, which works roughly the way you describe. I found that, at least for major-brand titles (Mario/Zelda/Metroid/Kirby), cycle accuracy actually doesn't matter. Everything's based off PPU/APU/mapper interrupts.

In fact, doubling (or more) the CPU clock enhanced some of the games I tried. Animations in Kirby's Adventure became more smooth (e.g. the Spark ability). Screens full of enemies in Metroid ran with no slowdown. The glitchy first scanline of status overlays in various games cleared up. I haven't yet observed negative effects in major-party titles.

I had designed my emulator as an experiment: treat the NES as an abstract specification, rather than a concrete implementation. Turns out that a lot of games seem to have actually been designed following the same principle. It was a wonderful feeling to see these games as I imagine they were intended to be experienced, as if I opened a letter from the game designers left unopened for thirty years.


Bear in mind that sometimes, people want to do tricks that depend on the slowdowns and glitches that happen on real hardware.


I'm sure. That wasn't the point of my experiment.


And in fact some games won't work without them. http://arstechnica.com/gaming/2011/08/accuracy-takes-power-o...


Yeah, every emulator is pretty much going to be fine with Mario, Zelda, and Kirby, but that isn't really the point.


In my case it was.


I guess what I mean to say is that someone endeavoring to write a cycle-accurate emulator wants every game to work exactly like it did originally regardless of what bizarre hardware-specific hacks it relies on. For someone who just wants to play any of the top 20 most popular games on a system and isn't too concerned with minor deviations pretty much any emulator is going to suit their needs (in fact it's a common model to have hacks in the emulator just to make a particular popular game work right).


> It was a wonderful feeling to see these games as I imagine they were intended to be experienced

Did you mean the way they were not intended to be experienced? Otherwise it doesn't make sense. The way they were intended to be experienced is on a real console connected to a CRT TV.


It really depends on the game and what the designers and programmers considered ideal or non-ideal at that time. There might not even be unanimous opinion among the creators of what the ideal behavior would be; that's often seen in film, where an actor, director, and screenwriter all have somewhat different interpretations of a character. On one hand you have stuff like Cave shooters where they've tried to reproduce the slowdown in ports because it's expected in the genre and affects difficulty. On the other hand you have stuff like Shadow of the Colossus, which was almost certainly not intended to have extreme framerate drops.

We can objectively talk about various metrics of accuracy compared to the original hardware. Authorial intent is, pretty much by definition, a matter of opinion (and authors themselves, over the years, often change their ideas of what their intent was).


Well-said. For my experiment I took "authorial intent" to include:

* no framerate drops

* audio synthesized with band-limited step functions (including the "triangle" channel)

* video composed of band-limited scanlines

* video interrupt running at NTSC rate

* audio interrupt running at 240 Hz

* free-running audio synthesis

Like you said, it is entirely a matter of opinion what authorial intent is. For my purposes this definition provided an interesting experiment, and the result was aesthetically pleasing.


There's also the part of "authorial intent" where particularly at that time many of the games were designed and developed sometimes on much bigger hardware (corporate mainframes, for instance) targeting the consoles and then later QAed on development consoles (that might not even be the same hardware as production consoles). There certainly are questions for some games if the authors intended something much better that they could get their development hardware to perform. It's not that many console hardware generations back where even development consoles still varied in hardware from production consoles (at least as recently as the early history of the PS3/Xbox 360).

All told, it's all a part of game's version of the "the artwork is never quite finished/realized, it's just eventually published".


You still have the source?


More sophisticated hardware doesn't necessarily have any single master clock in this sense, so it doesn't make much sense to talk about a "cycle-accurate" emulator of a modern PC, for example.

Even in a modern PC, many of the clocks are divided down using PLLs which maintain a fixed frequency and phase ratio, so it is theoretically possible to make such an accurate emulator, but it would be difficult to write and many orders of magnitude slower than the real hardware.

For an example of PC software which doesn't run correctly on anything but real hardware or really accurate cycle-emulation, see this amazing demo:

https://trixter.oldskool.org/2015/04/07/8088-mph-we-break-al...


It seems like the "cycle-accurate" emulator would be a lot easier to write, is this true?


I'm the author.

I disagree with this statement. It takes a considerable amount of effort and research to reach cycle-accuracy, especially on the PPU side. Understanding how the PPU pipeline works will take you more time than everything else.

If you settle for frame-based emulation you can write the functions to emulate the opcodes without worrying about the order and duration of the internal operations. Once the opcode is emulated, you just add cycles to a global counter based on a table that contains the number of cycles per instruction.

After 29781 cycles (you may end up being a little off each time, if you are not cycle-accurate), you call a function to update the state of the PPU. There you can use familiar iterative constructs to perform the rendering.

Compare this with the state machine approach in my code (ppu.cpp) and how much more careful I have to be composing microinstructions to form opcodes (cpu.cpp). I came up with a (I think) clean design but it wasn't trivial.


I've only actually written one in the classic style. I doubt that cycle-accurate is easier in general. It definitely isn't if you count the effort that goes into discovering the timing information by running experiments on the original hardware. If you start with everything documented, I guess it might be the least effort needed to bridge the gap between 99.5% compatibility and 100%.


TLDR: each CPU instruction takes the exact amount of time it does on the real cpu.

You generally only care about cycles in real-time stuff. In simpler CPUs like those used for microwaves and such, each CPU instruction takes constant time. You can count the number of instructions in your assembler loop and know how long the loop will take. Mind you sometimes each instruction takes constant time but some can take more time than others. A cpu cycle is defined as 1/clockspeed . A fast instruction can take 1 cycle, others 3 or more.

Usually there's multiple cpu instructions for GOTO and loading from memory, a fast set for things "close by" and a slow set for far away code or data. Loops and conditional instructions even on simple cpus can take different amounts of time depending on the outcome, so it gets pretty complicated to time things sometimes.

So when doing really low level timing critical code, you can use a super accurate signal generator to drive your CPU clock, then count your instructions to time things. Common uses include generating audio from bit banging and similar.

In more complex CPUs a number of things made it difficult or impossible to figure out exactly how long an instruction will take. None of the software for these CPUs is written to depend on exact cycle timings. Because nothing depends on cycle accuracy you don't have to worry about the timings when emulating these kinds of CPU's.


For extra speed, a lot of emulators take shortcuts. So, you might have a "frame-accurate" emulator that doesn't match the state of a "real" Nintendo on a cycle-by-cycle basis, but does by the end of the frame. There are a limited number of things triggered in the hardware (interrupts, set register flags, etc), and sometimes, like when the CPU is in an idle loop, the emulator can just skip ahead by a bunch of instructions until the next thing that needs to be handled.

Or in the graphics processor, maybe you'll blit out whole sprites/tiles at once, instead of rendering them pixel-by-pixel, the way that the hardware does.

In a cycle-accurate emulator, you're going to run every opcode, process the graphics pixel-by-pixel, etc.


Some understanding of context is expected to grasp implications of software. I'm not sure a github readme is the place to provide a complete education about the domain of the repository.

In this case, a 'cycle' is a processor cycle. Most emulators are imperfect, usually due to speed considerations, or to lack of access/understanding of the specifications of the original hardware. A short codebase that is entirely accurate is an achievement.


NES instructions are broken down into a series of smaller, simpler steps by the CPU. Each of these steps executes in a fixed amount of time - a cycle. For example, the "load value from memory into register A" instruction might take two steps: 1) fetch memory on the bus 2) move the fetched value into the register.

Cycle-accurate means the emulator is emulating all of the little steps that make up an individual instruction. Instruction-accurate emulators ignore the smaller steps and treat instructions as indivisible.

Cycle-accurate NES emulators only really matter for emulating certain graphical and sound effects.


I guess it's about emulation accuracy. Some emulators fail to emulate correctly for the purpose of speed, which causes visual and sound artifacts.

This comes to the host CPU power. The more accurate the emulator, the more power from the host will be needed.

UPD: Found a wiki article: http://emulation-general.wikia.com/wiki/Emulation_Accuracy


I take that to mean that the timing of instruction execution is true to the original, hence no unintended glitches.




Consider applying for YC's Spring batch! Applications are open till Feb 11.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: