{"id":17681816,"url":"https://github.com/geolessel/ex6502","last_synced_at":"2025-05-07T21:45:01.884Z","repository":{"id":57498449,"uuid":"332374862","full_name":"geolessel/ex6502","owner":"geolessel","description":"An emulator of the 6502 processor written in Elixir with a focus on modern variants (65c02).","archived":false,"fork":false,"pushed_at":"2024-04-10T06:38:24.000Z","size":226,"stargazers_count":21,"open_issues_count":1,"forks_count":1,"subscribers_count":4,"default_branch":"main","last_synced_at":"2025-04-22T07:54:55.153Z","etag":null,"topics":["6502","6502-assembly","6502-disassembly","6502-processor","65c02","apple-ii","apple-iie","atari2600","commodore","commodore-64","commodore64","elixir","emulator","nes","nintendo-ent","nintendo-entertainment-system"],"latest_commit_sha":null,"homepage":"","language":"Elixir","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/geolessel.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-01-24T05:32:12.000Z","updated_at":"2025-03-10T08:04:47.000Z","dependencies_parsed_at":"2024-10-24T13:33:42.629Z","dependency_job_id":null,"html_url":"https://github.com/geolessel/ex6502","commit_stats":{"total_commits":97,"total_committers":1,"mean_commits":97.0,"dds":0.0,"last_synced_commit":"a52975ecaa94a725cfadfa7d868085cfc4c0494c"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/geolessel%2Fex6502","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/geolessel%2Fex6502/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/geolessel%2Fex6502/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/geolessel%2Fex6502/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/geolessel","download_url":"https://codeload.github.com/geolessel/ex6502/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252961835,"owners_count":21832190,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["6502","6502-assembly","6502-disassembly","6502-processor","65c02","apple-ii","apple-iie","atari2600","commodore","commodore-64","commodore64","elixir","emulator","nes","nintendo-ent","nintendo-entertainment-system"],"created_at":"2024-10-24T09:12:15.069Z","updated_at":"2025-05-07T21:45:01.858Z","avatar_url":"https://github.com/geolessel.png","language":"Elixir","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Ex6502 - 6502 Processor Emulator in Elixir\n\nEx6502 is an emulation of the famous 6502 processor that was used in classic\ncomputers of the 80s such as the Apple II series, Commodore 64, Atari 2600,\nNintendo Entertainment System (NES), and countless others. It is still being\nmanufactured by the millions anually and this emulation is targeting the modern\nversions of the CPU (65c02, W65C02S, etc.).\n\n[![justforfunnoreally.dev badge](https://img.shields.io/badge/justforfunnoreally-dev-9ff)](https://justforfunnoreally.dev)\n\n## Installation, documentation, and usage\n\nAdd `ex6502` to your list of dependencies in `mix.exs`:\n\n```elixir\ndef deps do\n  [\n    {:ex6502, \"~\u003e 0.1.0\"}\n  ]\nend\n```\n\n**Note that since this version is still pre-1.0, major API changes could occur\nbetween any version number (major, minor, or patch level).** To see if breaking\nchanges occur between releases, check out the [CHANGELOG](CHANGELOG.md).\n\n### Documentation\n\nDocumentation can be be found at\n[https://hexdocs.pm/ex6502](https://hexdocs.pm/ex6502) or in the source code of\nthe modules themselves.\n\nEven though you will likely never call a specific operation directly, each\noperation has its own module and module documentation. For a good example, take\na look at the [source for\n`CMP`](https://github.com/geolessel/ex6502/blob/main/lib/ex6502/cpu/executor/cmp.ex).\n\n### Usage\n\nSince this is in the earliest stages of usability, it's not exactly the most\nuser-friendly to get started with. If you'd like to dive in, I recommend the\nfollowing:\n\n1. Assemble a generic, non-platform-specific hex file that contains your\n   operations. A good example right now would be a routine to add two 32-bit\n   numbers.\n\n2. In some code or in an IEx session, set up your computer.\n\n   ```elixir\n   c =\n     Ex6502.Computer.init()                               # initializes a Computer\n     |\u003e Ex6502.Computer.load_file(\"your-assembled-file\")  # loads your program code into memory\n     |\u003e Ex6502.Computer.reset()                           # uses the 6502's reset vector to load the program counter\n   ```\n\n   As per the documentation for the 6502, when the CPU is reset, it fetches the\n   16-bit address from memory locations 0xFFFC and 0xFFFD and sets the program\n   counter to that address. Since the 6502 operates in little endian format, the\n   low byle is stored first, then the high byte. That means that if your program\n   code starts at 0xC000, you need values `0x00` and `0xC0` in bytes `0xFFFC`\n   and `0xFFFD` respectively.\n\n3. Single-step your computer with `Ex6502.Computer.step/1`:\n\n   ```elixir\n   c = Ex6502.Computer.set(c)\n   ```\n\n4. Run the program in its entirety with `Ex6502.Computer.run/1`:\n\n   ```elixir\n   c = Ex6502.Computer.run(c)\n   ```\n\n5. Inspect your memory locations with `Ex6502.Memory.inspect/3` or dump it all\n   with `Ex6502.Memory.dump/2`:\n\n   ```elixir\n   # inspect 512 bytes of memory starting at location 0xC000\n   Ex6502.Memory.inspect(c, 0xC000, 512)\n   |\u003e IO.puts()\n   ```\n\n#### Usage notes\n\nI'm trying to emulate the hardware 6502 processor as closely as possible and\nthere are some potentially counter-intuitive pitfalls that you may fall into.\nHere's a small list of things to remember.\n\n* Zero-page memory addressing as the fastest way for the real processor to set\n  and fetch data. While cycle speed emulation is not implemented (yet), it _is_\n  nice to see some data in the zero page when inspecting memory since it is at\n  the start of memory.\n\n* As in the real CPU, the stack pointer is initialized to `0xFF`. However, since\n  the stack lives in the address range of `0x0100` to `0x01FF`, the stack\n  actually starts at address `0x01FF` and grows downwards towards `0x0100`. I\n  would recommend against using any of those locations for program code or data\n  unless you know what you are doing.\n\n* Currently, when the emulator encounters a `BRK` command (`0x00`) it does what\n  the hardware does. Specifically, it pushes onto the stack the high byte of the\n  current address, then the low byte of the current address, then the current\n  status register with the `B` flag set. After this, it sets the program counter\n  to the \"interrupt vector\" address (`0xFFFE`). The emulator also stops the CPU\n  and currently cannot continue automatically (though you can manually point the\n  program counter anywhere you'd like at this point).\n\n## Background\n\n### Why do this?\n\nEven though the most famous examples of usage of the 6502 were those systems, it\nis actually a still-heavily used and produced CPU. While the machines of the\nearly 80s typically used the 6502 produced by MOS, the current producer of the\n6502 processors is Western Design Center. [According to their\nwebsite](https://www.westerndesigncenter.com/), they still ship hundreds of\nmillions of units a year. While the majority of the operations handled by the\nCPU are the same as when they were manufactured by MOS, the modern version adds\na few operations and removes all of the undocumented operations that the\noriginal MOS 6502 had.\n\nWhile it is not hard to find an emulation of a specific computer system (such as\nthe Apple II or Commodore 64), I had a hard time finding an emulator of the\nprocessor itself. I had always had a curiosity about learning assembly\nprogramming and from various sources I heard that the 6502 was a decent place to\nstart. Because of the popularity of the various computers that ran on the 6502,\nthere are LOADS of resources all over the internet and in (used) bookstores that\nteach how to program for the 6502. I decided that's where I wanted to start.\n\nBut I could not find a good place to step through a piece of code and see what\nthe processor was actually doing with the operation. So I built this.\n\nWith this baseline 6502 emulation, I have focused on the modern version of the\n6502, as produced by Western Design Center. While every documented opcode is\nimplemented already (and a simple disassembler is as well), there are likely\nsome flaws in my emulation. I did not study other people's emulations of the\nCPU, nor did I do much research on emulation itself. I basically dove right in.\nBecause of this, I'm 100% positive there are better ways to do some things I've\ndone. But the main thing is: it seems to work.\n\n### Pitch in\n\nIf this project interests you, please pitch in and help make this codebase\nbetter. You can see in my earliest commits I wasn't quite sure where I was\nheaded. But by the end of the opcode implementations, I had found a good pattern\nand settled into that.\n\nMost of the code is likely much more verbose that it needs to be and I'm OK with\nthat. I don't mind a bit of duplication so that I (or others learning the 6502)\ncan better understand what is going on inside the processor.\n\n### Put this emulation into a larger system emulator\n\nSince this is just an emulation of the CPU itself, I believe it can be used to\nprogram multiple various sytems that included the 6502 (such as the Apple II or\nCommodore 64). While I may tackle some of those larger system emulations myself\nat some point, feel free to take this CPU emulation and build a more robust\nemulator around it.\n\nIf you do create such an emulation, PLEASE let me know about it. I'd love to use\nwhat you've created.\n\n## Wishlist\n\n* [x] every opcode implemented\n* [x] basic disassembler\n* [ ] documentation for public APIs\n* [ ] typespecs for public APIs\n* [ ] correct operation tables for each opcode\n* [ ] refactor earliest operation implementations\n* [ ] correctly count cycles used during processing\n* [ ] time-correct emulation of the CPU (running at original speeds such as\n      1MHz, but also configurable)\n* [ ] handle continuation from `BRK` interrupts\n* [ ] emulate hardware interrupts\n* [ ] basic assembler?\n* [ ] better tests using named [named\n      setups](https://mreigen.medium.com/elixir-a-cleaner-way-to-organize-tests-using-exunits-named-setup-8abb43971ca4)?\n\n## Me\n\nContact me any time! I'm [@geolessel](https://twitter.com/geolessel) on twitter,\n\"geo\" in the Elixir Slack community, and\n[geo](https://elixirforum.com/u/geo/summary) on elixirforum.com. I've given a\nnumber of talks at conferences (about Elixir mostly) and you can check those out\non my [Talks I've Given Playlist on YouTube](https://www.youtube.com/playlist?list=PLydu3IE1lef2Po9GJWjL9zl1X4xAPphTM).\n\nIf you like my work and want to support me, feel free to buy my book, [Phoenix\nin Action](http://phoenixinaction.com) from Manning Publishing. If you already\nhave the book, please leave a review on any major online retailer or community\n-- it really does help. If you've already done that or don't like reading (how\ndid you get this far into the README?), contact me directly and I'm sure we can\nfigure some way.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgeolessel%2Fex6502","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgeolessel%2Fex6502","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgeolessel%2Fex6502/lists"}