Show HN: NES Contra (1987) port (ASM –> C and then C –> WebAssembly) (epoyraz.github.io)

1 points by tevlon ↗ HN
Based on vermiceli's annotated disassembly of Contra: https://github.com/vermiceli/nes-contra-us. Thanks for the great work.

I ported it in two steps. First to C: the game logic is translated routine by routine from the 6502 assembly, and checked frame by frame against the original in the Mesen emulator. Then the C code to WebAssembly so it runs in the browser.

The cherry on top: online multiplayer, so two players can play co-op over the internet.

Source: https://github.com/epoyraz/nes-contra-us

66 comments

[ 0.23 ms ] story [ 35.8 ms ] thread
Cool, how did you build the multiplayer mode? And how much AI was used?
(comment deleted)
100% AI I'm sure. I played around with this kind of thing a month or so ago and Codex had no problems mashing games up from just the ROMs. In about 30 minutes I had the contra guys running through SMB 1 shooting enemies.
Can you elaborate on the process? Do you just provide it with the ROMs and it is able to pull apart the relevant sprites and code pieces, and recombine into a new ROM?
Yep. Fire up a new project, give it the two ROMs and the emulator to use and tell it what you what. I had to guide it a little bit about the sprite size and collison logic, but it was extremely painless.
I think you know the answer to that; they poked and prodded their surrogate mommy to do their homework for them.
I'm so glad that things being hard has never been connected to my self worth. Maybe someday you'll be able to enjoy just playing with technology rather than using it to prove how verysmart you are. Work smarter not harder.
It's a cute rationalization, albeit not particularly novel unsurprisingly.
One of the things that I'm curious about: How easy / hard is it to use the same NES game with higher resolution / color graphics, and sample-based sound?

Are there any emulators out there that let you swap in higher resolution assets so a game can be freshened without a complete port?

Idk about swapping assets but zsnes used to have a range of video filters that could improve the experience on a modern screen quite a bit.

Edit: For SNES, not NES, my bad.

Yeah, its upscaler is nicer than the Switch and the mini SNES.
I would not think so, at least not in a meaningful way. That would require to edit the cartridge data thus the ROM, as all sprite data was contained within the cartridge. Sample based sound is impossible natively, as NES and older game consoles don't work with digital data but synthesizers. You could perhaps synthesize the music to WAV files and then enchance it. But then again, NES and thus its emulators have no way of playing digitized audio!
> Sample based sound is impossible natively, as NES and older game consoles don't work with digital data

The NES supports PCM audio. It was notably implemented wrong in the title screen of Double Dribble and fixed with a patch that produces clearer audio after bit reversal into the correct encoding for the hardware:

https://www.youtube.com/watch?v=Jli0RGpuZDg

It does work with channels that produce pulse waves yes, but what I meant is that you can't supply samples of a wave and expect it to play it. The sound is still analog.
No. It has a Delta Modulation Channel that plays back differential pulse-code modulation samples. It is not the same as a waveform generator. Moreover, every sampled audio system with an analog output generates analog signals so that isn't a differentiator.

The DMC is typically used for instruments that are hard to reproduce well with the other generators. Double Dribble is using the DMC for the speech, not some clever setup of the waveform generators.

How would that work for hit detection algorithms in the code?
Most of the keys aren't working for me in Firefox though :-(
i only testing in chrome. Will look into it!
But the Japanese Contra was so much better! https://www.youtube.com/shorts/CiXzONyCDW0
Yeah I noticed this when I was mucking about with emulators. Thought I was imagining things until I looked it up. As far as I remember it has better sound too, or maybe I'm remembering castlevania three.
The Famicom Disk System included special sound hardware the NES lacked, so their Contra, Zelda, and Metroid sounded much better than ours.
In Germany they considered shooting humans problematic, so we got "Probotector" with robots instead, lol. They did that for the whole franchise.
All that work and then somehow transposing the A and B keys at the very end.
Is the audio not supposed to work? I was hoping to hear the legendary tracks!
I added audio support, but now you need to upload your own ROM. I didn't expect this to get so much attention. Since Konami is company behind Contra and they are known for DMCAing, i want to be better safe than sorry.
thanks for bringing back my childhood memories!
Contra is my favorite game of all time so this is a real treat, and the co-op idea is fantastic. Not to be greedy, but how hard would it be to add music? :)
fixed. But, now you have to upload your own ROM. (Afraid of getting DMCAed by Konami)
No controller support?
Whenever I see a game that uses the arrow keys and doesn't offer WASD as well, I can't help but see a game written by a non-gamer. I consider these fundamentals, and a shibboleth of whether I should care.
Literally 95% of 2D games on a PC were controlled via arrow keys. Not many allowed rebinding. Even in emulators, until later on.

You sure you're a gamer? I've been at it since about 1986.

Very true, WASD only became a thing with FPS games.
Where's the sound? You can likely ask AI to emulate the sound hardware with WASM!
Nostalgic!! Took me a few tries to beat the first level haha
Unfortunately, I'm a bit concerned that cool labor of love hacker projects like this will become much less common now that Anthropic (and possibly soon others) is moving to restrict this kind of usage. Oh well, so much for cool fun stuff.
> Anthropic is moving to restrict this kind of usage

I hadn’t heard about that - any details?

It's not really that cool to get a bot to do this work for you, anybody can ask for that assuming they have the tokens to burn.
“It’s not really that cool” they said on hacker news.
I could write a well crafted reply, with a convincing argument, but why bother? You're just trolling. The whole anti AI coding thing is such a meme. I suppose you'd like to spend all the time it would take to reverse engineer a classic NES game by hand? Go familiarize yourself with 6502 assembly and everything else you'd need to know?
I would rather read a write up of someone doing just that. This exact thing has been done many times now and no one is really learning or demonstrating anything new. It is cool, insofar as AI tools are capable of reverse-engineering, mechanical translation, and automatic verification, but it is no longer _novel_ and borders on spam.
Yes, that is exactly the fun, not contracting someone else to do it.
I've been dabbling in 6502 assembly since the 1980s. Sometimes your BASIC code just isn't fast enough you know.
Local models will never be restricted, and I suspect the Chinese ones wouldn't try to do so either.
The first project like this (of using AI to port old software from assembly) was interesting and novel. But every subsequent post has me wondering what new insight or lessons we have learned and if doing more of these is worth the energy burn.
It was worth it to the one who wanted it, and clearly many others too.
Recently I did something similar (or even more labor-intensive). I recreated an existing game from scratch by manually rewriting its code without even thinking about LLM/"AI" tools usage. (see my submissions).

But I agree, that using an "AI" tool may be a serious temptation and thus way less new porting projects will be done with such care.

A silver lining is that porting games will serve as a catalyst to help the self-hosted LLM ecosystem grow.
Most of the new game {decompiling, porting, modding} efforts use Codex anyway. And if they lose that they can switch to Chinese models that can get the same work done (because the results are easy to verify), just take more time to get it right.
No sound and the a and b buttons should be the other direction (a is to the right of b) on the keyboard.
fixed. But, now you have to upload your own ROM. (Afraid of getting DMCAed by Konami)
Wow, the source 6502 assembly with comments is incredible: https://github.com/vermiceli/nes-contra-us/blob/main/src/ban...

The whole thing (all banks) is more than 10,000 lines of assembly code. When I wrote assembly code for a university computer science course, it was hard to manage even 200 lines. I cannot imagine writing and managing 10,000 lines!

As much as I wouldn't want to write that much assembly, you make it less daunting the same way that you would with any other programming language. There are simple idioms for loops that you can macro-ize; similarly for function setup and teardown; more importantly, the concept of a function still exists at that level.
Bear in mind: the dissambly was done pre-LLMs. The early commits are from 2023. Although, ChatGPT 4 existed then, it was not capable of doing these things.

Impressive work, indeed. vermiceli the GOAT.

100% agree. That makes this commented code so incredibly impressive to me!
Nice! Can you speak to your process? How much structure did you give the agent? Did you have to "discover" the right way to do the port? Perhaps you just asked Claude, and then iterated? How do you feel about the final architecture/layout of the code, and would you approach a similar project in a new way given what you've learned?

You said in another comment:

> Then, i spent some time in building a harness and collect telemetry data in Mesen. Once, i had that: i just played the game in the emulator and asked Claude Opus 5.5 to use this as verification.

Can you comment on how this verification process worked?

You'll have to forgive me for not trying to answer these questions myself by investigating the code/git history, but... I hope you understand.

Actually, I am peeking around the code a bit and it's a bit disappointing, but it's what I should have expected having tried a project like this myself with a Game Boy game. I would like to see what an AI-produced semantic (?) rewrite of a retro game would look like. That is, what a port/rewrite that wasn't so faithful/wedded to the original ROM layout or platform architecture. For example, the agent (and you, presumably) was satisfied with writing a sort of RP2C02 emulator facade instead of doing the hard work of translating the bytes into platform-agnostic graphics rendering code. So now any customization/extensions you write to the game are fundamentally constrained to the abstractions of a specific chip from the 80s.

> I ported it in two steps

You didn't port it at all. You had Claude do it for you.

The only cheat code I still remember.