Skip to content

Latest commit

 

History

History
214 lines (143 loc) · 9.18 KB

README.md

File metadata and controls

214 lines (143 loc) · 9.18 KB

emudore, a Commodore 64 emulator

basic

What's this?

emudore is a Commodore 64 emulator, fully written from the scratch and built on the top of the following technologies:

emudore builds and runs on Linux, Windows (Visual Studio), OSX and even runs in your browser thanks to Emscriptem, it should theoretically work on any platform supported by SDL2 provided a C++11 compiler is available.

JavaScript and WebAssembly builds

If you wish to play a bit around without having to go through the hassle of compiling it you can try the web build:

A WebAssembly build of emudore is also available, please note that a browser with WebAssembly support is required to run these demos:

Why am I writing another C64 emulator?

Long story short: to learn a bit more about computer architecture, graphics, C++, etc.. while having some fun!

The Commodore 64 is regarded as one of the most epic 8-bit computers, it was actually the first computer I ever laid hands on - thanks to my dad :) - and it seemed like a sound choice to write an emulator for.

Does this even work?

Well, yeah, mostly...

The BASIC ROM runs just fine, and most simple programs run without issues, however, many of the more advanced games written in ML do not yet play well due to unimplemented hardware features, writing an emulator is a tough task and after all my goal wasn't to write a full perfect emulator but to learn in the process of making a simple one, here follow some facts you might be interested in knowing about emudore's implementation:

emulation is instruction-exact

That's right, on every emulation cycle a single instruction is fetched and interpreted, the number of CPU cycles the instruction has taken to execute is used to synchronize the rest of the chips in a C64 board.

Unfortunately, this is not the best approach, other emulators are able to execute a single instruction over multiple iterations of their emulation loop and mimic more accurately the behaviour of the real hardware, however, this is an easier approach to implement and does not impede the emulation from being relatively accurate.

illegal opcodes not supported yet

As many other architectures the MOS 6510 features a number of undocumented opcodes, most of these are thought to be unintended and usually perform a mix of other opcodes operations:

NMOS 6510 Unintended Opcodes - PDF

Nevertheless, some of these unintended opcodes have proven to be useful and are often used in games and demos, emudore will need to support these in the future if we ever intend to emulate serious games and demos.

single-threaded

emudore has been written as a single-threaded program, everything (including graphics) is handled within the same thread, again, this approach has possibly some drawbacks, especially in terms of performance, but it greatly simplifies the architecture: things like synchronization of the mainboard chips become easier to implement.

hardware acceleration and vertical refresh sync

The screen is refreshed once at the end of every frame, when the video raster reaches the last visible scanline, this way we're not constantly writing to the host video memory.

Also, to speed things up a bit I implemented hardware acceleration, we use an accelerated renderer and streaming textures, unfortunately, we need to keep the rendered video frame within emudore's memory and upload the texture to the GPU on every frame, direct pixel-access is not doable straight on the GPU memory.

I also implemented vertical refresh synchronization, at the end of every frame we check whether we are ahead of time compared to a real C64 computer, if that's the case we sleep for a bit and wake up at the point a real C64 would have finished rendering the frame, this effectively locks the screen refresh down to ~50Hz (PAL).

There are two main benefits of implementing vsync: it helps with performance since GPU operations are costly and after all we don't want to run at the limit of fps our GPU can handle; also, and more importantly, by doing this we emulate the speed of the real C64 computer synce the CPU and other chips are synchronized and run within the same thread, if we are on a fast computer visual effects won't look accelerated and games become playable :)

VIC-II chip

The vic-ii is a relatively complex chip, my implementation is not yet complete whatsoever, and certain features are more than likely still buggy, for now four out of the five official graphic modes are supported:

  • standard character mode
  • multicolor character mode
  • standard bitmap mode
  • multicolor bitmap mode

Smooth scrolling, sprites and raster interrupts have also been implemented and badlines are also emulated.

Some things that are left to implement include: sprite double height/width mode, sprite collision interrupts, etc.

A simple approach was taken to emulate the raster beam drawing, pixels drawn to the screen surface are computed at the end of each scan line, this might result in certain graphic effects being badly emulated, bear in mind that timing is of the essence in the c64, well-versed programmers master and exploit it to put together amazing effects that otherwise wouldn't be feasible.

beware

Due to some of the aforementioned facts, expect things to fail, don't even dream the emulation is going to be pixel-exact, certain effects are likely to get badly emulated, specially if you're running things like a demo.

Are you bleedin' serious radare2 is supported?

Indeed, for now it's only suppported on Linux and OSX (debug) builds, you can grab a fresh copy of radare from github

Then fire the emulator up and connect with radare:

r2 -w -a 6502 rap://localhost:9999//

For now radare can just read and modify memory, further support might be coming down the line once this feature gets implemented in radare.

Some pictures of radare in action:

r2mem r2dis

I hope this feature will come in useful to retrodev reverse engineers :)

So now .. what?

There are many features of the currently emulated chips that I haven't implemented yet, time permitting my plan is to keep working and learning about other aspects of the C64 technology, also, at some stage I'd love to get the time to work on:

Alright, enough of your jibba-jabba, how do I run this?

If you are running a Linux Debian-based distro:

sudo apt-get install g++ cmake libsdl2-dev

Then simply compile and run:

make release
cd build
./emudore

What C64 programs can I load into this?

For the time being emudore can load PRGs, you can test:

./emudore assets/prg/monopole.prg

emudore can also type BASIC listings for you (special keys not supported yet):

./emudore assets/bas/10print.bas 
(then type RUN at the emulator window)

Got some more screenshots?

Sure..

parallax mario pacman hitmen montezuma ghostbusters

References

If you are interested in computer archeology, and particularly in the C64, among others, the following resources came in handy to develop (and get inspiration) while developing emudore:

Forks

Some people have forked emudore and experimented with it, some notable forks include:

License

I don't think anybody will ever dare to use this for an actual useful purpose, but just in case, the project is licensed under the Apache 2.0 license