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

83 points by tevlon 14 hours ago

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

throwaway2037 2 hours 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!

tevlon 9 minutes 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.

zahlman an hour 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.

raldi 12 hours ago

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

tevlon 8 minutes ago

i had no idea. TIL

davesque 7 hours 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.

Panzerschrek 4 hours 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.

Buttons840 2 hours ago

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

EmX_3000 5 hours 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.

davesque 4 hours 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?

tadfisher 2 hours ago

pjmlp 2 hours ago

jkahrs595 5 hours ago

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

gnabgib 5 hours ago

em3rgent0rdr 4 hours 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.

userbinator 5 hours ago

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

pansa2 6 hours ago

> Anthropic is moving to restrict this kind of usage

I hadn’t heard about that - any details?

gnabgib 6 hours 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

shinryudbz 11 hours ago

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

tevlon 7 minutes 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.

msephton 9 hours 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.

gwbas1c 13 hours 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?

vunderba 12 hours 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

tevlon 12 hours ago

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

throwaway2037 2 hours ago

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

unleaded 13 hours 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...

BSPtree 13 hours 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!

cowlevel 13 hours 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.

kevin_thibedeau 10 hours 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

pantelisk 13 hours 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 :)

kekebo 13 hours 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.

gwbas1c 8 hours ago

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

sfblah 7 hours ago

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

tevlon 5 minutes ago

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

egonschiele 11 hours 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? :)

tevlon 5 minutes ago

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

BSPtree 14 hours ago

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

esikich 11 hours 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.

waltbosz 9 hours 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?

esikich 6 hours ago

tevlon 12 hours 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.

pmarreck 8 hours ago

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

Dwedit 12 hours ago

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

tevlon 4 minutes ago

fixed!

erictheguy 8 hours ago

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

pxx 10 hours ago

No controller support?

gosen 11 hours ago

thanks for bringing back my childhood memories!

einpoklum 13 hours ago

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

tevlon 13 hours ago

i only testing in chrome. Will look into it!

jasonlotito 9 hours 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.

lightedman 6 hours 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.

pjmlp an hour ago

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

anonymous908213 9 hours ago

While I'm not defending a slop port, I have to question your gamer credentials. Maybe by gamer you mean a Call of Duty player? WASD is traditional for FPS/TPS games that expect you to have one hand on the mouse. Most 2D games, and every emulator I've ever used, have never offered WASD.

literallyanythi 9 hours 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)

justsomehnguy 9 hours ago