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

Posted by tevlon 1 day ago

Counter89Comment80OpenOriginal

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

Comments

Comment by throwaway2037 1 day ago

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!

Comment by zahlman 1 day ago

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.

Comment by tevlon 1 day ago

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.

Comment by throwaway2037 1 day ago

100% agree. That makes this commented code so incredibly impressive to me!

Comment by raldi 1 day ago

But the Japanese Contra was so much better! https://www.youtube.com/shorts/CiXzONyCDW0

Comment by pipes 1 day ago

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.

Comment by raldi 22 hours ago

The Famicom Disk System included special sound hardware the NES lacked, so their Contra, Zelda, and Metroid sounded much better than ours.

Comment by hobo123 22 hours ago

In Germany they considered shooting humans problematic, so we got "Probotector" with robots instead, lol. They did that for the whole franchise.

Comment by tevlon 1 day ago

i had no idea. TIL

Comment by shinryudbz 1 day ago

Is the audio not supposed to work? I was hoping to hear the legendary tracks!

Comment by tevlon 1 day ago

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.

Comment by incr_me 1 day ago

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.

Comment by davesque 1 day ago

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.

Comment by Panzerschrek 1 day ago

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.

Comment by userbinator 1 day ago

Local models will never be restricted, and I suspect the Chinese ones wouldn't try to do so either.

Comment by tancop 17 hours ago

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.

Comment by em3rgent0rdr 1 day ago

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.

Comment by userbinator 14 hours ago

It was worth it to the one who wanted it, and clearly many others too.

Comment by EmX_3000 1 day ago

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.

Comment by davesque 1 day ago

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?

Comment by tadfisher 1 day ago

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.

Comment by pjmlp 1 day ago

Yes, that is exactly the fun, not contracting someone else to do it.

Comment by Buttons840 1 day ago

You are free to do so. Have fun!

Comment by pjmlp 1 day ago

I certainly am, only pointing out the comments vibe.

When someone commissions a painting, or a sculpture, they might cut the ribbon that holds the curtain on the opening day, that is all.

Comment by davesque 1 day ago

What if you've already played that game many other times during your 15 year long career? I mean the "game" of learning the ins and outs of a technical subtopic. And you know you could spend months ramping up on another thing just to see an idea take shape, but you only have limited resources in your life, a full time job, and so forth. And you'd still like to see an idea become a reality regardless of all that. So I guess that's not real work and it's cheating and it doesn't have value?

I mean, if you insist on doing everything by hand, go right ahead.

Afterthoughts: I really just don't get why people are so weird about this AI coding thing. What difference does it make to you if someone thinks they have more to learn from high-level planning work than from low-level coding work? A lot of the time, I get the vibe from people who talk this way that they are still early on in their career and think they have to prove their coding chops. I think that's why people like Linus Torvalds couldn't give a shit if people use AI or not, as long as it's not slop and suits its purpose. If you've already spent over a decade writing code and savoring the process, maybe you're just getting a little tired of it. And maybe agonizing over code perfection even drives you slightly insane sometimes. Who the f*** knows? In any case, it's none of your business. I don't know why I'm even writing all this. Because I know you'll just come back with the same old tired gatekeeping non-arguments.

Comment by pjmlp 1 day ago

There is some quite tasty microwave food, it doesn't make the person into a proper cook, not even an aspiring chef.

Comment by EmX_3000 19 hours ago

I've been dabbling in 6502 assembly since the 1980s. Sometimes your BASIC code just isn't fast enough you know.

Comment by jkahrs595 1 day ago

“It’s not really that cool” they said on hacker news.

Comment by gnabgib 1 day ago

Long standing account freaks out about latest GenAI/green account making vapid statement? Where are you going here?

Comment by EmX_3000 19 hours ago

It's not vapid. Half this web site at this poing is people saying "I-i made this" when AI made it for them. HALF. Nobody cares, it's old news. These stories are not relevant to tech, they're not thought-provoking nor is there anything to learn from them. It's about as cool as reading about some MIS directing a code sweatshop to make his or her latest web site.

Comment by jkahrs595 1 day ago

I’m going to sleep actually. Goodnight

Comment by Buttons840 1 day ago

A silver lining is that porting games will serve as a catalyst to help the self-hosted LLM ecosystem grow.

Comment by pansa2 1 day ago

> Anthropic is moving to restrict this kind of usage

I hadn’t heard about that - any details?

Comment by gnabgib 1 day ago

A short search away Anthropic takes steps to block Claude from reverse-engineering video games (106 points, 71 comments) https://news.ycombinator.com/item?id=50320255

Comment by msephton 1 day ago

A couple months ago I wrote about this kind of transcompilation hop-skip-jump: https://news.ycombinator.com/item?id=49643284

I used it to get games written in Lua running on SNES and in my own language/engine running on Dreamcast, Wii, Web and more.

Comment by gwbas1c 1 day ago

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?

Comment by vunderba 1 day ago

You might like 3dSen, which came out several years ago. It does some pretty crazy stuff, converting NES games into essentially 3D voxel environments.

https://store.steampowered.com/app/1147940/3dSen_PC

Comment by tevlon 1 day ago

whoa, that's cool. I didn't know about this. Thanks for sharing!

Comment by unleaded 1 day ago

Mesen has texture packs. Don't know about sound, you'd have to reverse each game's sound driver first. https://vgmpf.com/Wiki/index.php?title=Famicom/NES_Sound_Dri...

Comment by BSPtree 1 day ago

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!

Comment by cowlevel 1 day ago

The NES in particular is probably not too difficult to upscale, because the graphics data is stored on its own ROM chip (sometimes RAM) in a well structured layout. SMB1 just uses a ROM chip containing many tile graphics which the CPU code addresses by tile index. It would be really easy for an emulator to use the same tile indices to address any arbitrary set of tiles loaded from a PNG. Some games use RAM, which makes it harder as you'd have to index the PNG by hash or something.

Comment by kevin_thibedeau 1 day ago

> 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

Comment by BSPtree 1 day ago

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.

Comment by kevin_thibedeau 20 hours ago

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.

Comment by pantelisk 1 day ago

Compute motion vectors, faux depth, and add DLLS5 to it maybe? Could be pretty cool, or pretty horrific. Only one way to find out :)

Comment by gwbas1c 14 hours ago

Consoles like the NES are tile based: They work by placing tiles are particular coordinates on the screen, with a particular pallet.

My theory is that the emulator could swap in a higher resolution tile without needing to port the game.

Comment by throwaway2037 1 day ago

How would that work for hit detection algorithms in the code?

Comment by gwbas1c 14 hours ago

The code still sees the original RAM.

Comment by kekebo 1 day ago

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.

Comment by gwbas1c 1 day ago

Yeah, its upscaler is nicer than the Switch and the mini SNES.

Comment by heybax 11 hours ago

The only cheat code I still remember.

Comment by BSPtree 1 day ago

Cool, how did you build the multiplayer mode? And how much AI was used?

Comment by esikich 1 day ago

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.

Comment by waltbosz 1 day ago

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?

Comment by esikich 1 day ago

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.

Comment by 1 day ago

Comment by tevlon 1 day ago

For the Multiplayer part: It's deterministic lockstep. Both browsers run the same C core (compiled to WebAssembly), and the only thing sent over the network is each player's button bitmask per frame. Local input is delayed by 4 frames (~67 ms), which hides normal internet latency; if the other player's input for a frame hasn't arrived yet, the game waits for it. Every 2 seconds both sides compare a hash of the game RAM to catch desyncs. Transport is a WebRTC data channel via PeerJS (its free cloud server handles matchmaking with a room code), with Google's STUN server for NAT traversal and Metered's free-tier TURN relay as a fallback when a direct connection isn't possible.

For AI usage: It was all done by Claude/Codex, but it wasn't that straight forward. First: i started in April and the models weren't good enough and would make errors. You could see those immediately in glitches. 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. The rest was smooth.

Comment by ov3r45 1 day ago

[dead]

Comment by Emjayen 1 day ago

[flagged]

Comment by esikich 1 day ago

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.

Comment by Emjayen 1 day ago

It's a cute rationalization, albeit not particularly novel unsurprisingly.

Comment by whoanoway 1 day ago

[dead]

Comment by egonschiele 1 day ago

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? :)

Comment by tevlon 1 day ago

fixed. But, now you have to upload your own ROM. (Afraid of getting DMCAed by Konami)

Comment by sfblah 1 day ago

No sound and the a and b buttons should be the other direction (a is to the right of b) on the keyboard.

Comment by tevlon 1 day ago

fixed. But, now you have to upload your own ROM. (Afraid of getting DMCAed by Konami)

Comment by pmarreck 1 day ago

Where's the sound? You can likely ask AI to emulate the sound hardware with WASM!

Comment by Dwedit 1 day ago

All that work and then somehow transposing the A and B keys at the very end.

Comment by tevlon 1 day ago

fixed!

Comment by erictheguy 1 day ago

Nostalgic!! Took me a few tries to beat the first level haha

Comment by bigstrat2003 19 hours ago

> I ported it in two steps

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

Comment by pxx 1 day ago

No controller support?

Comment by gosen 1 day ago

thanks for bringing back my childhood memories!

Comment by einpoklum 1 day ago

Most of the keys aren't working for me in Firefox though :-(

Comment by tevlon 1 day ago

i only testing in chrome. Will look into it!

Comment by smjy_studio 1 day ago

[flagged]

Comment by jasonlotito 1 day ago

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.

Comment by lightedman 1 day ago

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.

Comment by pjmlp 1 day ago

Very true, WASD only became a thing with FPS games.

Comment by anonymous908213 1 day ago

[flagged]

Comment by literallyanythi 1 day ago

correct me if i'm wrong, gamer credential questioner, but WASD was immortalized by the id Software "win Carmack's ferrari" tournament. Before then EDSF was also popular because it gave you more keys on the left side for hotkeys.

I do think you're objectively correct in your post, but I think what the grandparent meant was that "The author isn't actually interested in playing Contra on his website" which is why QoL stuff like that wasn't added and it "smells" like it should be there if you cared about playing on the thing you actually shared to HN. I know the first thing I would do would be to add wasd + mouse support to Contra, since the control scheme is the reason I don't try to play it. But at the same time I have never been interested in games that deliberately limit your controls as a form of difficulty (feels like a Japanese gamedev thing, from Resident Evil to Dark Souls)

Comment by justsomehnguy 1 day ago

NB: WASD won because most (like 99%) of the keyboards did had (and I can bet cheap shit still have) some dead keys aka 'key ghosting' on ESDF.

Comment by em3rgent0rdr 1 day ago

I think because the computer mouse is typically on the right side of the keyboard (because most people are right-handed), WASD has the advantage of allowing your mouse to be controlled by your right hand and you can keep your left hand in the normal position it is used for typing and not have to have your left hand move all the way to the arrow keys to control directions.

Comment by justsomehnguy 21 hours ago

> WASD has the advantage of allowing your mouse to be controlled by your right hand and you can keep your left hand in the normal position

And this is exactly the same with ESDF.

Comment by literallyanythi 1 day ago

You awoke negative-nostalgia to membrane keyboards where I remember I couldn't hold Shift + W + A at the same time in Minecraft as a kid so you're definitely right about bad keyboards, but I remember dead keys on WASD as well. I wasn't there, but the largest consensus seems to be that Quake popularized it, plain and simple. I'm sure other factors like what you mention helped it become the dominant layout as well

edit: figured out why that nostalgia happened. I was revisiting an old flash game I liked [0] and people were complaining to the dev about this exact key ghosting issue to him when it wasn't his fault but a fault of their keyboards, and in the Newgrounds description he links to a forum post [1] elaborating on the issue

[0] https://www.newgrounds.com/portal/view/547881

[1] https://board.flashkit.com/board/showthread.php?789015-wont-...

Comment by justsomehnguy 21 hours ago

> but the largest consensus seems to be that Quake popularized it, plain and simple

Yes, by being the great equalizer. But the question is why WASD and not something else eg WSDX[0] or some shit like ASDF. And the ghosting explains it well enough.

[0] https://shodan.fandom.com/wiki/Controls_(System_Shock)