Skip to content

C64 emulation using the neo6502 development board

License

Notifications You must be signed in to change notification settings

B3rndK/C64Neo6502

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

94 Commits
 
 
 
 
 
 

Repository files navigation

C64Neo6502

C64 emulation using the Neo6502 development board

What it is used for

I coded this because the Neo6502 seems to be a very good piece of hardware to refresh old memories and to deal with microprocessor bus interfacing on hardware level by using a common high level programming language instead of e.g. VHDL or VERILOG. I see this as being in the middle of purely software based emulation and pure hardware simulation by using FPGAs. By looking at the code and debugging you can see how to initiate the RESET sequence of the 65C02, how to interface with RAM / ROM and how to do mapped IO and create hardware interrupts. It also enables to debug the internals of the C-64 to check, e.g. how the Kernal detects PAL or NTSC machines etc. The real fun is to learn C-64 programming or even to extend this emulation. May the source code inspire other developers to reuse it and make it better. To cut a long story short: It should be fun!

What it is not

It is an emulation which you can use to play around with, investigate, get more and more games runnig and even play a lot of commercial games. However, you have to dump game game roms and integrate them yourself. I cannot provide any roms to you, but you can easily copy from what is already there and what I have already done. For game ROMS and how to integrate, the same is valid like for the ROMs section below.

Making gaming possible (for non-developers)

It is possible to integrate a whole bunch of working ROMs and have them all stored in the RP2040 flash simultaneously. Using a small C64 (yes, 6502) program ... you could offer a game selection menu on startup. When a game is selected, the program could, for example, poke a magic value identifying the game into an unused IO area. The emulator would then see that a value is stored in this "IO register" and could then load and run the game from flash.

Prerequisits

I am following the wireing standard from Vaselin Sladkov, so in order to have the RP2040 create real interrupts please connect pin 10 of UEXT connector (GPIO 25) to pin 24 of 6502 bus connector (IRQ) using an external wire. Furthermore we will need to create a real RESET signal, so please connect pin 9 of the UEXT connector to pin 40 (RESET) as well as pin 8 of the UEXT connector to pin 26 (NMI) of the 6502 bus.

PICO-SDK (RP2040)

You need to install the PICO-SDK Pico-SDK and set the environment variable PICO_SDK_PATH. Furthermore I am using the Open On Chip Debugger (OpenOCD) using a RP Debug Probe.

tinyusb

https://github.com/hathach/tinyusb

PicoDVI

https://github.com/Wren6991/PicoDVI/tree/master/software

Visual Studio Code

I am using Visual Studio Code and the following plugins:

  • C/C++ (incl. Extension Pack and Themes)
  • CMake
  • CMake Tools
  • Cortex Debug

Build

Building this emulator is straightforward. Create (mkdir) and then cd to a build subfolder, then run cmake .. Please see the CMakeLists.txt file in case you do not want Simon's Basic or monitor support. You can simply remove _SIMONS_BASIC from the compile definition list.

ROMs

Due to copyright reasons, I cannot include the C-64 bios files "basic", "kernal" and "chargen". So please use e.g. the tool "bin2hdr" from Veselin Sladkov Reload-Emulator) to convert your C-64 rom files to

  • basic.hxx
  • kernal.hxx
  • chargen.hxx

replacing the included but invalid files.

Note: In case you want to upload the compiled `UF2` of this emulator to a website, please ensure you are legally entitled to do this because of these still copyrighted ROMs.

Simon's Basic

This was a very popular expanded basic for the C-64. I also included support for this. You need to dump $8000-BFFF of the software. I cannot provide it to you due to copyright laws:

  • simons_basic.hxx

In case you have licensed Simon's Basic, you can enable this module within the `CMakeLists.txt`. It is switched off by default. IPXL_20240411_123345109.TS (1)n order to boot Simon's Basic, you have to enter `POKE 32776,48` and then restart the C-64 by typing `SYS 64738`. You will be presented the welcome screen. Here you can type `OLD` to recover the basic program. Then enter `LIST` to edit it or `RUN` to start it.

Monitor

I included a small machine code monitor at $c000 (SYS 49152). You can enable this module within the CMakeLists.txt. It is switched off by default.

Sound

Source Code of TinySid is now included but it is WIP. NightShade sounds quite well while others, hmmm... ok...

Output

DVI output is now implemented for all official C-64 VIC modes, textmode, multicolor textmode, hires, hires multicolor and extended color mode (ECM) . The design also supports fli support. No support for sprites or bitscrolling yet. The resolution used is a "quirk mode" of 340x240 and may not run on every display. You can enforce using a 640x480 mode by changing a single line of code in case you prefer a more safe timing.

Input

Keyboard input is currently handled by directly attaching a usb keyboard. There is currently no explicit USB-hub, so you have to connect your USB keyboard either directly or use a working USB hub. I am using the keyboard of the RaspberryPi foundation. Joystick supported in Port A (SNES_OEM type).

WIP

This is work in progress and is set up for fun.

How can I add my own games and start them?

I created my own small, rising collection of games by doing the following:

  • After start of the C64Neo6502 (counting the cycles) I import a little basic program showing selection of roms by copying it to $0801. Then the user has to type "run" to start it. I saved this basic program upfront and imported it like a rom file.
  • In case the user entered desired ROM letter to start, in Basic I "poke" this selection into an unused IO memory cell which I catch in the C64Neo6502. I took a non-usable VICII address.
  • In the EMU code, I see that this address is accessed for write and I then copy the appropriate ROM to it's start address via memcpy, e.g. $0801. I also copy a little handwritten piece of machine code to the cassette buffer. It will put the start address of the rom to start onto the stack and will do a return from interrupt. I then raise an NMI (non-maskable interrupt). This is why you definitely need the extra cabling mentioned above. ** Example: This is the loader code which will start a ROM at $0812:
    static uint8_t timem_nmi_loader[]={0x68,0x68,0x68,0xa9,0x08,0x48,0xa9,0x12,0x48,0x08,0x40}; // $0812
  • The machine code in the cassette buffer is executed by the NMI: In case the C64Neo6502 find out that the 6502's $FFFA, $FFFB address is requested for READ on the address bus, I return the vector to the little machine code routine which will then RTI directly to the start of the ROM.

How does it look?


* This is how it currently looks like using my collection:
c64Neo6502menu.mp4
  • You can of course easily start roms individually by just copying them to C64 RAM:
C64Neo6502.mp4
  • How to activate the expanded basic (and run a little 3D-Mandelbrot-Set):
expanded_basic.mp4
  • And the final result after some hours of computation...

result

Some of the games tested:

fairlight.mp4
drevenge.mp4
nightshade.mp4
lofmidnight.mp4

About

C64 emulation using the neo6502 development board

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published