Live data from Hacker News

Implementing a NES Emulator in Rust

michaelburge.us

51–60 of 93 posts

Re: Implementing a NES Emulator in Rust

#51
post #2

Question, what made it easier to build this in Rust than other languages? I know the advantages of Rust, but what exactly was the experience in this context?

From the article:

"C is probably still a better choice for those cases: It’s more difficult to find someone who can implement a Rust compiler than a C compiler.

But Rust seems usable in any project where C++ is a viable language."

Re: Implementing a NES Emulator in Rust

#52
post #47

Earlier quoted context omitted.

"How do you get to Carnegie Hall?" Seriously, the best thing to do for virtually all professional or hobby work is to get more experience with it. Choose a project with small enough scope to give you encouraging results to keep that feedback loop going.

That is a great analogy thanks.

From personal experience, invest in good (for you) resources to learn the language. I had two attempts, and it wasn't until I took "learning" seriously and purchased a book did Rust stick. My first attempt that has worked for all other languages, mostly by just reading docs and programming, was a massive headache.

That was years ago though, perhaps it's better now. All I know is after reading Programming Rust, I picked Rust up and it's been amazing. I love the language.

Re: Implementing a NES Emulator in Rust

#53

Earlier quoted context omitted.

It seems that unsafe references were used, so the advantages of Rust appear to have been somewhat relinquished in this case.

I am not sure you can not use `unsafe` in an embedded type of project. `unsafe` isn't necessarily bad, but when used at least makes it very clear where extra attention should be paid.

Writing an emulator is not really embedded programming (the target often qualifies as an embedded environment but the host can be any random desktop computer).

It's definitely possible to write an emulator without unsafe code. Here's a toy gameboy emulator I wrote a while ago in Rust without any unsafe code: https://github.com/simias/gb-rs

Here's a very incomplete PSX emulator with only a single unsafe (which might not even be necessary anymore, I haven't updated the code in a while): https://github.com/simias/rustation

Re: Implementing a NES Emulator in Rust

#55
Why not use serde instead of rolling your own "Savable"?

Also you should use Rc/Arc and Weak (along with RefCell/Mutex if needed) instead of the unsafe pointers. Even better, if possible, move the functions that access multiple components to the object that holds them all, and don't use any "smart pointers". Another possible design is to pass borrowed references explicitly to the methods, and add them to the trait signatures where needed.

Regarding memory access, it's probably fastest to have an hardcoded fast path for RAM and ROM, and then process the rest like now. Lookup tables might help as well (as long as all the data including them fits in cache, of course).

Re: Implementing a NES Emulator in Rust

#56

Earlier quoted context omitted.

Nitpicking a bit, but there's not a lot of useful things that could be multithreaded in an 8-bit emulator, so it would be more like 1x3Ghz ;) In those old 8- and 16-bit machines all components usually ran completely synchronous for each clock tick, for instance if the video emulation runs out of sync with the CPU emulation for a tick or two, a write from the CPU to a video hardware register might not make it in time…

The original hardware was multithreaded... in the sense that there were several separate processing units.

Yes, but as far as I can glance from the NES spec, those still run from the same clock (with different dividers, but they're still locked to each other).

I haven't written an emulator for the NES yet, but on machines like the Amstrad CPC or C64, the CPU can reprogram video hardware registers (like color palette entries) at any time, for instance in the middle of a scanline. When this is off by a tick, you get the color palette change a couple of pixels late or early.

If CPU and video chip emulation would run on different threads, they would need to sync with each other a few million times per second, that doesn't sound like a good idea. If synchronization is only needed once per scanline, or even per frame that's an option of course. Often this is good enough to run some games which didn't go too close to the metal (again this is only from my experience with home computer emulators, haven't done NES stuff yet).

Parallelizing through SIMD might be an option though (one can pack a lot of 4- or 8-bit counters into a 512-bit register).

Re: Implementing a NES Emulator in Rust

#57

Earlier quoted context omitted.

unsafe exists in Rust for when you need it. When it is used, it means nothing more than you’re writing code for which you must ensure the safety instead of the compiler. The times when unsafe is poorly used are when it’s being abused to ignore safety related compilation issues, like lifetimes and/or mutability. Though, even in those cases it might be ok if you’re using lower level concurrency primitives to enforce th…

It doesn’t remove restrictions, it adds unchecked constructs. Very different!

Hm, I’m not sure I see the difference between those concepts, but I do like your framing better.

Re: Implementing a NES Emulator in Rust

#59
post #2

Question, what made it easier to build this in Rust than other languages? I know the advantages of Rust, but what exactly was the experience in this context?

Implementing an NES emulator is a great way to learn more about a language and the internals of the NES (which is well documented). It's sorta like a rite of passage and has been done in most of the "newer" languages like Nim ( https://github.com/def-/nimes ) , Go ( https://github.com/fogleman/nes )

[deleted]
Post reply on HN