11 ms·
LaiNES – Cycle-accurate NES emulator in around 1000 lines of code
- tlack 10y agoPeople always say that terse code is hard to read and understand. I'd say I just learned a lot from a quick skim of the concise source here. If it had been structured with tons of white space and split over dozens of files/folders/modules, I'd have no chance of understanding it at a glance.
- qwertyuiop924 10y agoTerse code is easy to read. Gratuitously compact code isn't The rule of thumb is that if it's short but in no way obfuscated, it's terse. If it's short, and impossible to read because of it, it's gratuitously compact.
- posterboy 10y agoIt is in multiple files, but still very terse, eg. using single letter variables. /* CPU state */ u8 ram[0x800]; u8 A, X, Y, S; u16 PC; Flags P; bool nmi, irq; I like it.
- andreaorru 10y agoI'm the author. The reason for the single letters is that those are the actual names of the 6502 registers. Glad you like it overall. :)
- pawadu 10y agoIt's really nice that you keep it so close to the actual hardware (not just the variable names, but also the way the logic works in for example PPU). I also love the way you use C++ templates to simplify things!
- posterboy 10y agoaccumulator xchange ... y, something stacky perhaps? program counter flagPort non maskable interrupt, interrupt request I'm sure you knew that though, it's common micro processor nomenclature.
- Two9A 10y agoSpecifically on 6502-derived processors, you have the following registers: Accumulator, X and Y indexes, Stack Pointer, Program Counter, Flags. Of these, only the Program Counter is double-width. Additionally, the zeroth "page" of memory (the lowest 256 bytes) are accessible with a dedicated addressing mode which saves space and time in the program, and can be used as a form of cache.
- serge2k 10y agothe variables are named for the registers they represent, it's not single letter variables for the sake of compactness.
- posterboy 10y agoOK, that was an unfair pick, other variables have longer strings. I just picked the example, because I thought it was cute how short the CPU status is, and because I couldn't remember what nmi ment, at first. Trying to talk about it brought it back to mind, so that worked for me, but I blamed the project in vain, because the decision was made elsewhere. Those electronic engineers!! Let's argue about better names for x and y. is anyone even reading this? I'm prolly not gonna come back to this either.
- Graziano_M 10y agoAbsolutely agree. I'm writing an NES emulator myself and just glancing at this code has given me a few line-saving ideas.
- qwertyuiop924 10y agoThat is very cool. I'm always kind of in awe of this sort of thing. Maybe I should try to do it. Should take some of the awe away. But I should probably focus on sucking less, first.
- bluedino 10y agoTry making a small virtual machine first - https://github.com/tekknolagi/carp/blob/master/README.md https://github.com/tekknolagi/carp/blob/master/README.md
- tekknolagi 10y agoWhoa, that's my project. Wouldn't recommend looking at that one, but definitely take a look at it's successor (linked on the README).
- deleted 10y ago[deleted]
- Jach 10y agoAnother interesting project to take away some magic: https://github.com/ssloy/tinyrenderer/wiki https://github.com/ssloy/tinyrenderer/wiki
- toast0 10y agoThere's a lot of docs out there, and some test roms to help. A CPU emulator is actually pretty straightforward. Adding the PPU is more complex, of course.
- khedoros1 10y agoDo it. Emulation has always fascinated me, so I wrote a (kind of crappy) NES emulator a few years ago. It demystifies things, there's a ton of documentation out there, and you'll get the joy of increasing numbers of games working as you make progress.
- plandis 10y agoAs someone currently writing an NES emulator, do it! There are a ton of references to help you figure everything out it's been a pretty interesting experience.
- raldi 10y agoWhat 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."
- johndoe90 10y agoI 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 http://emulation-general.wikia.com/wiki/Emulation_Accuracy
- stonogo 10y agoSome 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.
- posterboy 10y agoI take that to mean that the timing of instruction execution is true to the original, hence no unintended glitches.
- pubby 10y agoNES 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.
- deleted 10y ago[deleted]
- ggggtez 10y agoMaybe of you inline entire functions...
- userbinator 10y agoFunctions which are only "called" once, which I think is a perfectly reasonable thing to do.
- glandium 10y agoThis makes me wonder. The 6502 in the NES ran at 1.79MHz. According to https://en.wikipedia.org/wiki/Instructions_per_second https://en.wikipedia.org/wiki/Instructions_per_second , a modern i7 processor handles north of 100,000 MIPS. According to https://en.wikipedia.org/wiki/Transistor_count https://en.wikipedia.org/wiki/Transistor_count, the 6502 had 3510 transistors. At 100,000 MIPS, a modern CPU would have a budget of ~56k instructions to process one cycle of that CPU, or about 16 instructions per transistor. So it would seem it might now be possible to simulate those old processors, at the transistor level, in real time. Is anyone aware of experiments in this domain? If not really useful, that sounds like an interesting fun (side) project.
- SeanDav 10y agoIt turns out that for several reasons, creating an exact emulation of even much older gaming technology can be very computationally intensive. http://arstechnica.com/gaming/2011/08/accuracy-takes-power-one-mans-3ghz-quest-to-build-a-perfect-snes-emulator/ http://arstechnica.com/gaming/2011/08/accuracy-takes-power-o...
- anonbanker 10y agoWhen people link to this, it's a good idea to mention that 65816 emulation runs as one enormous switch statement. Yes, it's accurate, but at a rather large performance penalty. I'm a daily/weekly higan user, nut I make no excuses for how it's written. take a peek into the code.
- mattbee 10y agohttp://www.visual6502.org/ http://www.visual6502.org/ does it in the browser & flashes transistor states at you! And if you liked that you'll probably also enjoy http://www.megaprocessor.com/progress.html http://www.megaprocessor.com/progress.html
- vincnetas 10y agoAlso: Introducing the MOnSter 6502 http://www.evilmadscientist.com/2016/6502/ http://www.evilmadscientist.com/2016/6502/
- rounce 10y agoFirst I'd like to say this project represents fantastically impressive achievement regardless. However, putting this repo through `cloc` reveals the HN title to be rather misleading. EDIT: I had initially read through {cpu,apu,ppu,gui,joypad,mapper}.{cpp,h} and noticed that the mental tally I was taking had run well over 1000LOC. In my haste I quickly cloned the repository and ran cloc against the current dir which massively inflated the result (Doh!). See author's comment below for a more sensible figure.
- mentat 10y agoI'm guessing that that figure is just for the emulation code. The UI and sound interface code eat up quite a few lines of code. Doesn't hurt to actually dig instead of karma farming...
- rounce 10y agoI had read the repo first and just from counting in my head it was deffo over 1000 lines. Turns out the author agrees, that it's almost 1500 LOC. I was a bit hasty (read: dumb) in generating the table is all :) Maybe calm down with the "karma farming" accusations, my problem was with the HN title, not the repository.
- andreaorru 10y agoAlso I'm not the author of the HN submission... ;)
- andreaorru 10y agoSorry, but that's really not fair. You are running that on all the folders inside the src/ directory (and the README?), including blargg's libraries that I'm using. I'm not counting that. Go ahead and include those if you want. It's code I didn't write, and bigger than the rest of the emulator! I don't think that's representative. CPU and PPU implementations tend to be in the order of the thousands of lines -- they are around 200 and 300 lines respectively in LaiNES. In fact, most of the code is in the GUI that I could easily strip away if this was a competition. And this wasn't written to be small - it was written to be simple. It also came out small, but that's incidental. Here's how I counted the lines and how I decided on the description for the repository, which by the way has been catapulted from totally unknown to worldwide attention overnight, and it's now object of unexpected, ruthless scrutiny that I couldn't foresee. [andrea@manhattan src]$ rm -rf boost nes_apu Sound_Queue.* [andrea@manhattan src]$ cloc . 24 text files. 24 unique files. 1 file ignored. github.com/AlDanial/cloc v 1.70 T=0.03 s (780.3 files/s, 63170.2 lines/s) ------------------------------------------------------------------------------- Language files blank comment code ------------------------------------------------------------------------------- C++ 11 210 110 1163 C/C++ Header 12 87 7 285 ------------------------------------------------------------------------------- SUM: 23 297 117 1448 -------------------------------------------------------------------------------
- anonbanker 10y agoAny plans for a libretro port?