GithubHelp home page GithubHelp logo

c64rust's Introduction

c64rust

This is a simple (and incomplete) CMOS6502 and C64 emulator/debugger implemented in Rust. The main purpose of this project is to practice my Rust skills and turn into reality my old dream of building an emulator.

When built, the project provides three binaries (in target/debug)

  • machine: a generic 6502 emulator (CPU and memory only) for CLI,
  • c64: CLI-based C64 emulator built on top of the above - good for testing: it can execute a binary and exit (on BRK or specific address) with processor status (or full disassembly)
  • gui: ncurses-based client that allows for interaction with the emulator

How to run

  1. Download ROM file
  2. Execute: cargo run --bin gui -- --rom path-to-rom

If you don't have any ROM file, don't worry - I've created a test ROM from scratch! It doesn't do much, but at least it displays a welcome message and a cursor. You are welcome to contribute and help to make it an alternative C64 OS :-) (the source is here) But for now, just hit: cargo run --bin gui -- --rom rom/hello.rom

Running options:

Options:
  -r, --rom <ROM>
      --ram <RAM>
      --ram-file-addr <RAM_FILE_ADDR>
      --ram-size <RAM_SIZE>            [default: 65536]
  -a, --start-addr <START_ADDR>
  -s, --show-screen
      --show-status
  -d, --disassemble
      --max-cycles <MAX_CYCLES>
      --max-time <MAX_TIME>
      --stop-on-addr <STOP_ON_ADDR>
      --stop-on-brk
  -v, --verbose
      --char-rom <CHARACTER_ROM>
      --profile <PROFILE>
  -h, --help                           Print help
  -V, --version                        Print version

Current state

  • MOS6502 (6510) instruction set fully implemented (no illegal opcodes)
  • C64 memory addressing implemented (RAM/ROM switching, with partial CIA)
  • The emulator boots with provided C64 ROM (some cartridges work too)
  • Text client with keyboard emulation - possible to run BASIC commands
  • The client has integrated simple debugging features: memory view, disassembler, and processor state
  • Step-by-step debugging: including breakpoints, variables and dissassembler (see the screenshots below)

This is the result of running current version of the emulator:

Features and goals

Short-term / realistic goals

  • Clock emulation (right now the emu ticks at host speed; it's not an issue as there is no emulation of other devices like GPU/VIC II, so sync is not required).
  • Basic CIA features (other than the keyboard)

Ambitions

  • VIC II graphics (without sprites and smooth scrolling)
  • Improved debugger (variables, breakpoints)

Long-term goals

  • Sprites and smooth scrolling
  • Sound
  • Joystick emulation
  • Cartridge binaries support

No-goals

  • Making competitive product to Vice and other well-established emulators.
  • CRT emulation

Screenshots

Debugger in its current full capabilities - memory view, disassembler, variables watch and breakpoints. Variables and breakpoints must be at this stage configured in a profile file, but I debug my HelloOS that way, and it's usable, so - the first step towards MVP!

The Dead Test cartridge image executed quite fine, but the two timers at the bottom-right of the scrren show zeros, which - according to the documentation - means "Possible 6526 CIA Failure". Well, it's quite right as CIA is not implemented at this stage at all (apart keyboard support).

Another diagnostic tool - this one - besides proving that I've found the right Unicode characters for C64 graphics characters, seems to be failing miserably. At least it's doing nothing (perhaps depends heavily on clock).

This is how it looks like when run the raw 6502 "machine" emulator in CLI. It's configured as 1kB machine that starts loaded program at 0x200. The provided ROM is 6-byte jump vector setting the reset vector to 0x200. Some "static" debugging is possible that way.

Credits

  • srounce - made the environment work with Nix Flakes. So cool!

References

I've compiled much longer list of topic-specific links in a separate references document, but here I'd like to mention a few sites I was returning to constantly in order to gain my knowledge about 6502 and C64 internals.

  • 6502.org An absolute must-visit page for all 6502 enthusiasts: documents, active forum and plenty of links to existing projects, tools, assemblers, etc.
  • C64 Wiki Another very detailed knowledge base site, but focused on C64. Lot of information about C64-specific chips, Kernal functions, graphics and C64 software.
  • Codebase 64 This is a deep-dive into C64 world. Lot of ASM examples, advanced topics and many how-to guides.
  • C64OS C64OS is a name of a modern operating system for C64, but the site provides much more than that. The author invested a lot of time in understanding and explaining the details of how C64/6510 functions and has a great talent in presenting that knowledge in digestible form.
  • pagetable.com Great blog and reference docs about 6502, C64 and many other topics. It provides super detailed C64 Memory Map and ROM Disassembly

c64rust's People

Contributors

ddrcode avatar srounce avatar

Stargazers

 avatar

Watchers

 avatar  avatar  avatar

c64rust's Issues

Address mapping - do it right

Some form of addreess mapping is currently implemented as a bunch of if conditions.
Let's abstract it properly.

Tasks

  • Any adress-bus attached device can't be accessed directly. The only way to interact with should be via machine's get_byte, set_byte methods (perhaps worth renaming to read_byte / write_byte)
  • read_word / write_word are just a convenience functions on machine level, not on memory-device
  • unit tests!
  • get rid of the current concept of Memory struct that has rom/rom fields. Separate them!
  • the minimalistic implementation (MOS6502_Machine) - that cen be considered as implementation of Default trait, should consist of 64kB of RAM and 6-bytes ROM for reset/irq/nmi vectors. Don't hardcoded vector addresses anymore on machine's start function.
  • for C64 implement at least a primitive version of PLA-82S100 - the memory "bus" logic
  • on C64 level connect CIA, RAM, ROM and VIC_II via memory address bus and don't refer to them directly from C64 logic.
  • Make the proper use of Byte 0, that may prevent writing access at some occasions
  • (optional) would be great to have debugger being aware of the source of data

References:

CRT files support

CRT files are binary images of C64 cartridges. They contain additional header data providing additional details, i.e. which address. space the cartridge occupies. most of downloadable cartridge files in the internet are in this format.

There is very good description of the file format at Codebase64

Opcode tests

We need asm tests for all opcodes in integration tests

  • Arithmetic operations
  • Arithmetic operations in BCD
  • Bitwise instructions
  • Branch instructions
  • Compare instructions
  • Flag instructions
  • Memory instructions (including testing all addressing modes)
  • Register instructions
  • Stack instructions
  • Jump instructions
  • IRQ / NMI / BRQ

Pin-based emulation (research)

Experiment with "pin-based emulation". In such emulation the connectivity between components mimics physicial connections of electronic components and interaction happens via pins/ports. With such type of emulation it should be possible to design custom machines easily, and avoid programming model where one component "owns" another. See whether such approach is feasible and performant enough.

  • Figure out convenient way of implementing pins, ports and connectivity between them,
  • Find out how to make signal on pin activate certain functionality of a component (ideally without callback pattern),
  • As an POC, implement a simple 6502 machine with pin-based approach (Ben Eater computer seem to be a good example)
  • Compare performance of pin-based emulation with the current approach

Support for PAL / NTSC version of C64

C64 stores PAL/NTSC flag under $02A6
According to Pagetable:

This test is accomplished by setting a raster interrupt for scan line 311, and testing if the interrupt occurs. Since NTSC monitors have only 262 raster scan lines per screen, the interrupt will occur only if a PAL monitor is used. The results of that test are stored here, with a 0 indicating an NTSC system in use, and one signifying a PAL system.

This information is used by the routines which set the prescaler values for the system IRQ timer, so that the IRQ occurs every 1/60 second. Since the PAL system 02 clock runs a bit slower than the NTSC version, this prescaler value must be adjusted accordingly.

Cursor doesn't blink after Kernal init

Kernal loads, I can type, I can execute BASIC commands, but the cursor is not visible.
Shame... Perhaps it depend's on CIA ticking or something like that. I spent some time tracking the code on Kernal dissassembly page, but still nothing.

POC: Experiment with Kitty's graphical output.

Beyond the MVP for sure, but tempting to experiment. Of course there is no support in Cursive, so the problem is bigger (UI rewrite?), but first - lets try to have some output and see whether it can make any sense.

It's definitely worth checking Kitty's documentation on Unicode placeholders as that sounds like option worth exploring.

Reset when in debug mode doesn't work

At lest with kernal.
It either makes machine to freeze or quits gui completely.
With helloOs it seems to be working.
Anyway - some instability is there.

Simple debugger (with machine profile files)

Add option to start emulator with a profile file (toml), ie:
machine --profile hello-os.toml

It's some form of a "static" debugger, where user can't add/remove variables in runtime, but can predefine them in the profile file.

Features:

  • config section with same options as CLI arguments
  • variables sections with variables
  • debug section with breakpoints
    • checkboxes for breakpoints to enable/disable them

Cycle-accurate CPU emulation

Current implementation of CPU opcodes only cares about total amount of cycles (and progresses cycle count accordingly). This ticket proposes an enhancement where each instruction is divided into a number of independent steps: one per processor cycle. At this stage it is mainly important for the POC of pin-based-emulation (as per #31), but it should improve overall emulator accuracy.

References

  • All About Your 64 - Online Help V0.64
    Very detailed instruction of each cycle per addressing mode. Search for text "6510/65816 Addressing mode: Immediate" to find the beginning. It provides info about 16-bit and 8-bit 6xxx processors in the same text, so it's a little bit tricky sometimes to extract the knowledge. The description in the link below is clearer, but slightly less detailed.
  • 6502 CPU
    Search for phrase "6510 Instruction Timing". It focuses purely and 6502 - easier to start with. When missing some details - check the link above.

Debugger - next steps

This ticket, at this stage, works as a set of ideas for future development of the debugger.
It should contain rather sane enhancements than something unreal. Still to be considered within MVP scope.

  • Disable/enable interrupts
    • In state of disabled interrupts - option to send one (NMI/IRQ) manually
  • Enabling debugger on BRK
  • Option to add/remove variables in GUI
  • Would be good to indicate on debugger level the actual memory device being used for read/write operation (see #23)

Keyboard emulation - works, but...

Issues:

  • Key 1 is not read during keyscan. All toher keys seem to be fine. Row and column scanning codes the right value. Strange...
  • Some keys are being dropped when typing faster - mastly because of no actualy key-up event in current client
  • No ctrl/Commode keys
  • Special keys: F's, stop, restore

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.