Building a Motorola 68000 Emulator in the Browser ๐Ÿ–ฅ๏ธ

GR
Gianluca Rea

Building a Motorola 68000 Emulator in the Browser ๐Ÿ–ฅ๏ธ

If you've ever taken a computer architecture course, chances are you've been forced to use Easy68Kโ€”a Windows-only, decades-old tool for writing and running Motorola 68000 assembly. It works, but it hasn't aged well ๐Ÿ‘ด.

I decided to build something better: an m68k assembly interpreter that runs entirely in the browser. No installation, no Windows dependency, no excuses. This is the story of how a small side project turned into a week-long sprint to implement every instruction I could get my hands on.

This project started as the foundation of my bachelor thesis in 2021, and with the help of Claude and GitHub Copilot, I've been able to modernize, rewrite, and complete it into something genuinely useful.


๐Ÿ”ง Day One: Modernizing the Foundation (March 12)

The project already existed in a basic form, but the codebase was showing its age. The first thing I did was rip out the old setup and modernize everything:

  • โ†’Migrated the entire project to TypeScript ๐Ÿ“˜
  • โ†’Switched the build system to Vite 5 โšก for lightning-fast dev builds
  • โ†’Set up a proper CI/CD pipeline with GitHub Actions
  • โ†’Integrated Vercel Analytics to understand how people use the tool
  • โ†’Updated the homepage and deployed it live

It felt like renovating a house before moving in. You don't see the plumbing, but everything runs smoother because of it.


๐Ÿ›ก๏ธ Day Two: Fixing the Cracks (March 13)

With the new foundation in place, it was time to address all the little things that had piled up. This was the "boring but necessary" day ๐Ÿ˜…:

  • โ†’Fixed a ReDoS vulnerability in minimatch flagged by Dependabot
  • โ†’Replaced the vendored ace-builds editor with the proper npm package
  • โ†’Set up CodeQL analysis with correct workflow permissions
  • โ†’Added block scoping in switch statements to squash subtle bugs
  • โ†’Introduced a configurable execution delay so users can watch their code run step-by-step in real time โฑ๏ธ
  • โ†’Threw in a โญ GitHub star button in the navbar (every project needs one, right?)

Not glamorous work, but the kind of stuff that separates a toy project from something people can actually rely on.


๐Ÿ” Day Three: CI/CD Wrangling (March 16)

Ah, CI/CDโ€”the thing you set up once and then fix forever ๐Ÿ”„.

package-lock.json kept falling out of sync, tests were flaky, and Codecov wasn't reporting correctly. I spent this day:

  • โ†’Simplifying the CI workflow into something maintainable
  • โ†’Fixing package-lock sync issues (the bane of every Node.js project)
  • โ†’Getting Codecov integration working properly

Two PRs merged, pipeline green โœ…. Moving on.


๐Ÿงฎ Day Four: The Instruction Sprint Begins (March 17)

This is where things got fun. I started actually implementing the M68K instructions I'd been putting off:

  • โ†’MULU and DIVU โ€” unsigned multiply and divide ๐Ÿ”ข
  • โ†’Branch instructions (BRA, BEQ, BNE, BCC, BPL, BGE, BGT, BLE, BLT, BVC)
  • โ†’STOP โ€” halt execution

I also focused on developer experience:

  • โ†’Wrote an ultimate_test.asm file to stress-test every feature
  • โ†’Made error messages way more descriptive โ€” instead of "Unknown operation," you now get context about what went wrong and where
  • โ†’Cleaned out old JavaScript files that were left over from the pre-TypeScript era ๐Ÿงน

๐Ÿš€ Day Five: Going All-In (March 18)

March 18th was the big one. I sat down and said "I'm implementing everything" ๐Ÿ’ช.

Data movement:

  • โ†’MOVEQ, MOVEM, MOVEP, PEA

Extended arithmetic:

  • โ†’ADDX, SUBX, NEGX, CMPM

Shift & rotate:

  • โ†’ROXL, ROXR

Bit manipulation:

  • โ†’BTST, BCLR, BCHG

CCR operations:

  • โ†’ANDI to CCR, ORI to CCR, EORI to CCR, MOVE to CCR, MOVE from CCR

More branching:

  • โ†’BSR, BSET, BLS, BHI, BCS, BMI, BVS

System control:

  • โ†’NOP, RESET, RTE, TRAP, TRAPV, CHK, LINK, UNLK, TAS

That's 30+ instructions in a single day. Each one with proper flag handling, size variants (.B, .W, .L), and edge cases. My coffee consumption was... significant โ˜•โ˜•โ˜•.


๐Ÿ› Day Six: Bug Hunting and Polish (March 19)

With all those instructions in place, it was time to make sure nothing was broken. Turns out, a few things were ๐Ÿ˜ฌ:

  • โ†’Labels starting with A or D were being incorrectly parsed as register names โ€” AGAIN: was treated as address register A. Fixed the parser to properly distinguish labels from registers.
  • โ†’End-of-arguments errors weren't being caught cleanly โ€” tightened up the argument parsing logic.
  • โ†’Ran the full test suite, fixed everything that turned red ๐Ÿ”ดโ†’๐ŸŸข

Finally, I updated the README and the Help page with the complete list of supported instructions. Two final PRs merged, and the project was in a state I could be proud of.


๐Ÿ“Š By the Numbers

Looking at the week in total:

  • โ†’60+ commits in 8 days
  • โ†’50+ M68K instructions fully implemented
  • โ†’9 pull requests merged
  • โ†’0 installations required to use it

The emulator went from a basic proof-of-concept to a genuinely useful tool that covers nearly the entire M68K instruction set that students encounter in courses.


๐ŸŒฑ What's Next

There's always more to do. The roadmap includes:

  • โ†’Data Definition instructions โ€” DC (Define Constant), DS (Define Storage), DCB (Define Constant Block)
  • โ†’I/O Operations โ€” file and console input/output support
  • โ†’Examples folder โ€” comprehensive assembly examples with step-by-step annotations

But for now? It works. It runs in your browser. And it's free and open source.

โ†’ Try it live
โ˜… Star It


โœจ Final thought: What started as "Easy68K is annoying" turned into one of the most rewarding coding sprints I've ever had. Sometimes the best motivation is scratching your own itch. โœจ