Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Nes emulator written in go (github.com/fogleman)
108 points by netbun on March 23, 2015 | hide | past | favorite | 55 comments


Take a look at the code if you haven't: https://github.com/fogleman/nes/tree/master/nes

I don't know if it's a statement about fogleman or Go, but it seems so much more clean than other emulators I've looked at.


See also sprocketnes, an NES emulator written in Rust: https://github.com/pcwalton/sprocketnes

It was written by pcwalton, one of the main driving forces behind Rust. (Unfortunately, it hasn't been updated for a couple months, so it won't build with latest rust).


NES emulators are a common and fun challenge for testing out languages. Here's one in Clojure that intends to be fully immutable, such that you can rewind and fast-forward through history at will: https://github.com/samfoo/clones

In the case of Sprocketnes, one of its goals is to serve as a demonstration of Rust's ability to run entirely without a runtime (see the long-outdated quote in the readme: "The Rust garbage collector is not used in this project"... we really need to get this updated for 1.0).


Woah, that is a really cool idea. The idea of walkable state is neat... even if 1 FPS.


> It was written by pcwalton, one of the main driving forces behind Rust. (Unfortunately, it hasn't been updated for a couple months, so it won't build with latest rust).

Possibly the most telling sentence I have ever read about Rust. I am (well more honestly, was) excited by the language but until there is some sort of stability guarantee, it is a fun toy, a distraction.

The Rust community appears desperate to have continuous improvement at the core language level, and despite some hand-waving, it feels like they simply won't be pinned down. I will watch it with interested post the May 15th 1.0 deadline -- but since they shipped entirely new Path and IO in Feb -- added new language constructs and removed others (Alpha2)... I am worried...


> Possibly the most telling sentence I have ever read about Rust. I am (well more honestly, was) excited by the language but until there is some sort of stability guarantee, it is a fun toy, a distraction.

> The Rust community appears desperate to have continuous improvement at the core language level, and despite some hand-waving, it feels like they simply won't be pinned down.

What is the impending 1.0 release if not that? We've been very clear all along that 1.0 means language stability. I see no "hand-waving".

> I will watch it with interested post the May 15th 1.0 deadline -- but since they shipped entirely new Path and IO in Feb -- added new language constructs and removed others (Alpha2)... I am worried...

Why would you be worried that we're following precisely the schedule that we said we would?


I was vague and unclear, entirely my fault. I really want Rust to be successful, I just think some of the decisions being made are shortsighted, so I will watch after release to see if I am correct, hope I am not.

> What is the impending 1.0 release if not that? We've been very clear all along that 1.0 means language stability. I see no "hand-waving".

I guess I don't consider "stability" and "backwards compatibility" the same thing -- in the "stability as a deliverable" post, it was specifically referenced that rust will "continue to evolve at a rapid pace and even accelerate!" (quoted from memory, sure it is somewhat off).

I think a constantly growing language (no longer changing cause old code has to work, but growing... which seems worse) and the fact that libraries will opt into new features and bundle use of those features with bug fixes will mean that the entire userbase is on a 6 week upgrade cycle -- 8 or 9 upgrades a year. I consider that a mistake. Furthermore, I consider the idea that the channels will not fracture the community to be very naive. I expect a lot of libraries will just live on unstable and tell users to "come with them".

> Why would you be worried that we're following precisely the schedule that we said we would?

You are correct and that was unfair. I can't fault the team for doing what they said -- even if to an outsider it seems like an insanely late time to be doing these types of refactoring.


  > no longer changing cause old code has to work, but 
  > growing... which seems worse
It should be mentioned that the "features" that Rust has yet to implement are largely not of the nature of "wholly new concepts that will drastically change the language", but tweaks to existing features to make them more performant and more ergonomic. Such features include lessening the restrictions on the borrow checker, making it possible to return unboxed closures constructed in a lower stack frame, and improvements to user-defined smart pointer types to make them equal to first-class constructs (such as the ability to do `Rc<Trait>`). "Growing" here means refining the language as it exists, not succumbing to featuritis.

  > the entire userbase is on a 6 week upgrade cycle -- 8 or 
  > 9 upgrades a year.
I don't see how this would be the case. If you write a lib for Rust 1.0, the intent is that it will continue to work for all users on Rust 1.1, and 1.2, and 1.3, and so on. No need for the lib author to explicitly upgrade, and hence no need for lib consumers to upgrade.

  > I consider the idea that the channels will not fracture 
  > the community to be very naive.
Nobody is expecting the entire Rust ecosystem to transition to stable overnight. Rust 1.0 presents a very conservative foundation upon which you might want to base your code. If you do, you are rewarded with future stability for all 1.x (and also means that even unstable users will be able to use your code without breakage). This means that the stable Rust ecosystem will gradually accumulate over time. This gradual transition process is fully expected and encouraged.

Rust 1.0 does not mean "the language is done and perfect". It means "we know you're tired of breaking changes, so we've set aside all these enhancements that we were planning on adding so that we can achieve stability sooner, with the expectation of landing those features backward-compatibly at some later date." Rust could easily spend years and years and years in an unstable state, seeking perfection, and there are some in the community who still wish that were the plan. But as someone who's been using Rust since 2011, I'm in agreement with the core team: stability now, evolution over time.


> "Growing" here means refining the language as it exists, not succumbing to featuritis.

In no world does "we expect that pace of change to accelerate" mean "we expect subtle refinement of the language". Refinement or polishing generally isn't something that "accelerates change".


The Go authors have a really nice slide they like to show that shows the interest in Go as a trend. And right after they announced Go 1.0 with the backwards-stability promise, the interest sky-rocketed.

You can't have a perfect language. Ever. But if you want people to use the damn thing to build actual software, you have to stabilize eventually. C/C++ aren't perfect either - even the most hard-core C++ fan will admit to that - but they get shit done.

Go gets shit done. Sometimes in an ugly way. Rust could get things done in a beautiful way, if they just....stabilized it. Just stop changing it.


  > Rust could get things done in a beautiful way, if they 
  > just....stabilized it.
Hence the Rust 1.0 stable release on May 15th. :) http://blog.rust-lang.org/2015/02/13/Final-1.0-timeline.html


"Stable" but adding new features every 6 weeks... which will get used by library authors... which will put all users on a 6 week upgrade cycle.. yey?

Or your favorite library author just likes nightlies, which effectively forces you to run nightlies to keep up with bug fixes if he isn't maintaining a separate branch (and who has time for that noise).


  > "Stable" but adding new features every 6 weeks... which 
  > will get used by library authors... which will put all 
  > users on a 6 week upgrade cycle
Why would it force anyone to upgrade? If a library exists for Rust 1.0, and then a library author releases a new version of the library with Rust 1.1 features, the Rust 1.0 library does not cease to exist. And Cargo supports semantic versioning to make it easy for library authors to inform their users when a new release is backwards-incompatible, and automatically upgrade users to new minor releases of the lib when the user has opted into receiving them. Even if a library author breaks their own backcompat and does all new feature development on a new version of Rust, thereby requiring you to upgrade your own version of Rust in order to get new features, the worst case scenario is that you download a new Rust compiler and all your other code continues working (hence, backwards compatibility).

  > Or your favorite library author just likes nightlies,
  > which effectively forces you to run nightlies
If a sufficiently-popular lib exists only on nightlies, then there will exist demand from stable users for a lib of equivalent functionality that targets a stable release. Stability is a competitive advantage! And because Rust can release a new minor version every six weeks, the core developers can look at what popular libraries are using the nightly branch, determine which features that library can't live without, and then prioritize stabilizing those specific features for the next minor release. Six weeks later, that lib is suddenly using a stable release.


> If a library exists for Rust 1.0, and then a library author releases a new version of the library with Rust 1.1 features, the Rust 1.0 library does not cease to exist. And Cargo supports semantic versioning...

That's true, but it ignores the way modern software unfortunately works. Programmers are lazy, and maintaining multiple development branches takes work, so they will try not to do that if they can get away with it. How many bug fixes will get backported to Rust 1.0.x, or to the 1.0-supporting version of that library? Probably not very many. Most developers will just bump the major version every 6 weeks, because that's easier than worrying about stability.


I think this attitude is far too cynical. Library authors that care about their users don't break backcompat lightly, and they do backport bugfixes. The mantra "programmers are lazy" does not imply that programmers are inherently amateurs.


I think that isn't so much attitude as experience. That said, I will watch post May 15th and hope I am wrong, but I suspect despite the buzz some of the policies will be (broad adoption) language suicide.


  > I think that isn't so much attitude as experience
Experience with library ecosystems which lack proper versioning support, perhaps.

  > some of the policies will be (broad adoption) language 
  > suicide
What policies? How does this discussion at all concern any deficiencies that are unique to Rust?


So instead we end up with libraries on 1.0 for years because you can't break by upgrading.


I cannot express how amused I am at the silliness of this whole conversation, which is predicated on the absurd premise that users won't want to upgrade their versions of the compiler. What part of the phrase "backwards compatible" is lost on this crowd?


The last time I checked this is a link about go? Or no?


If I may be so bolt to plug my tool, but would http://gotools.org/github.com/fogleman/nes/nes be a nicer way to look at the source of the entire Go package?


If you must force a target on links to other packages, can you at least use a static name (rather than _blank) so the same package doesn't keep opening in different tabs? E.g.

    <a href="/errors" target="errors">"errors"</a>


Thanks for the suggestion. I've opened https://github.com/shurcooL/gtdo/issues/33.


Line numbers should be linkable in the same way as a filename is. Perhaps they should be foldable.


Thanks for the suggestion. That's an opened issue [1] and the highest priority for the project.

[1] https://github.com/shurcooL/gtdo/issues/11


Looks pretty good.


Assuming you are the author (nice work!), any chance you'll consider adding support for the 'famicom disk system' ?

It's a bit 'exotic' but there are some interesting NES games which only exists on the disk system, like '3d hot rally' (super mario racing game), 'doki doki panic' (the game from which super mario 2 was remade), here's a list of all the disk games: http://en.wikipedia.org/wiki/List_of_Family_Computer_Disk_Sy...


*bold, sorry about the typo.


Where can I find newbie resources (books, or anything) to write NES (and potentially SEGA and SNES) emulator?

I wouldn't mind if I have to learn from zero (OS, hardware, etc). I think I might have found a side project that I can be passionate about!

UPDATE: Thanks for the replies. I'm having hard time to follow those links since I don't even know where to start. Is there another tutorial that can explain the fundamental of "emulator" first before the NES part kicks in?

PS: I'm planning to use Java for this side-project.


The usual place to start to start an emulator is the CHIP-8 (https://en.wikipedia.org/wiki/CHIP-8), because it's a very easy platform that don't have a lot of the "complicated" stuff that's in more complex hardware.

The overall logic is very simple (read a program into ram, read an opcode from the starting location, do whatever that opcode is supposed to do, go to the next opcode... rinse and repeat) and you can find tons of tutorial online (I liked this one: http://www.multigesture.net/articles/how-to-write-an-emulato...)

It should set your mind on the fact that writing a simple emulator is just doing a fetch/decode/execute (https://en.wikipedia.org/wiki/Instruction_cycle) on some code.

For the documentation, I've found that EmuTalk (www.emutalk.net/forums/30-Emulator-Programming) has tons of interesting links.


Thank you very much!!!!


You can read the source to existing projects (bsnes, SNES9X, gambatte etc.) The Gameboy would probably be the simplest hardware to work on.

> PS: I'm planning to use Java for this side-project.

Emulators typically use repetitive code, less than int-sized math, 2d arrays and pointer manipulation. Java is not good at dealing with any of those, so you might want to find a more fun language. Then again, one thing at a time.


Exactly, one thing at a time. Once I get a good grasp and managed to deliver a working emulator, then I can start thinking about improving/optimize or even port it to another language.

Right now I'm just trying to figure out the basic fundamental concept of "emulation" (what is it, what does it take, how can I write a simple one :)).


I just don't want you to get RSI!


While not NES, one of my students at General Assembly made a Chip-8 emulator/interpreter in JavaScript for their final project.

Chip-8 has 30-something instructions and is relatively simple to implement, and test driving it is pretty easy too. I thought it was a really wonderful first emulation exercise.

http://en.wikipedia.org/wiki/CHIP-8


http://nesdev.com/

Is a fantastic resource. They are helpful and have lots of docs.


Zophar's would be a good place to start

http://www.zophar.net/utilities/nesdev.html


>Is there another tutorial that can explain the fundamental of "emulator" first before the NES part kicks in?

>PS: I'm planning to use Java for this side-project.

One place to start might be to try and write an emulator for the DCPU-16. It's a simple made-up computer that Notch (creator of Minecraft) designed for the game 0x10c.

Although the game was never finished, many people wrote emulators based on the DCPU's specifications[1]; search Github for "DCPU Java" to see several examples in that language.

[1] https://raw.githubusercontent.com/gatesphere/demi-16/master/...


Hah! That's my repo!

Also, the only emulator for anything written in Io, as far as I know :p

Not that it was good, mind you. But I do highly recommend DCPU-16 as an emulation launching point. It's a really easy to understand system :)


Thanks a lot for pointing me at this. While NES is the goal, I definitely need to take baby steps first!


This PDF gives a good high level overview of the NES: http://nesdev.com/NESDoc.pdf


Thanks a lot! I really appreciate this!


Here's a very clean and clever NES emulator in C++ by Bisqwit of TAS fame: https://www.youtube.com/watch?v=y71lli8MS8s

He presents the code in the style of a tool assisted run, typing it in in high speed. I never saw templates used like that to create the unrolled CPU dispatcher


The code for the CPU dispatcher begins at 1:26 in the linked video, for those not willing to watch the whole thing.

A comment elsewhere in the thread mentions Sprocketnes, written in Rust, which takes a different tack here: it uses a hygienic macro to implement opcode dispatching, which allows the giant block of dispatching logic to be reused for both the emulator and the disassembler: https://github.com/pcwalton/sprocketnes/blob/master/cpu.rs#L...


I also wrote an NES emulator in Go https://github.com/nwidger/nintengo


Look at how deeply nested the code is. Hint: it isn't. Super clean code.


This one is very easy to read. I wish the emulator I am working on was this clean. Looks like I may need to do some refactoring!


Thanks for posting the SMB3 screenshot. now I know how (in)accurate the emulator is.

for those that don't know, the title screen, above the checkerboard, has a very thick black line. compare to a proper NES (or Nestopia) to see.


Another ${things that exists} in ${current trendy programming language} submission, why does this get upvoted?


Because programming is fun, new languages too and hacking is what this site is about.


Because comparing the same thing done the 'new' way and the 'old' way is one of the best ways to see the differences between the two ways and find out if and when the new way is better.


I take it as a sign of intelligent life in an otherwise web dominated world.


Because this is Hacker News.

Because doing ${things that exists} in ${current trendy programming language} is somehow gauged as a Good Thing™ in your portfolio by the startup mindset.

Because posting this Good Thing™ on Hacker News is basically the SF startup scene's own LinkedIn equivalent.

Because other people who has bee doing this Good Thing™ want their own Good Things™ to be validated as well, so they continue this tradition.


Because Conservatives are always on the wrong side of history. And new things replace the old, and there is a reason C is the biggest language of them all.


I don't have a problem with people scratching an itch. This is how we practice our craft. However, how is writing yet another NES emulator anything but conservative given the vast number of example and documentation to draw from? Sure, it's not as simple as writing yet another TODO list in yet another JavaScript framework, but it's not 'new'.




Consider applying for YC's Fall 2025 batch! Applications are open till Aug 4

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

Search: