Bmc64
A bare metal Commodore 64 emulator for the Raspberry Pi 1/2/3 with true 50hz/60hz smooth scrolling, low input latency and better audio/video sync.
Install / Use
/learn @randyrossi/Bmc64README
BMC64
BMC64 is a bare metal C64 emulator for the Raspberry Pi with true 50hz/60hz smooth scrolling and low latency between input & video/audio. Four other Commodore machines are available as well; C128, Vic20, Plus/4 and PET.
BMC64 Features
- Quick boot time (C64 in 4.1 seconds over composite!)
- Frames are timed to vsync for true 50/60 hz smooth scrolling (no horizontal tearing!)
- Low latency between input & audio/video
- No shutdown sequence required, just power off
- High C64 compatibility thanks to VICE
- High Plus/4 compatibility thanks to Plus4Emu (Rpi3 Only)
- Easily wire real Commodore/Atari Joysticks and nav buttons via GPIO using jumpers (GPIO Config 1)
- Can use a real Commodore Keyboard and Joysticks via PCB (GPIO Config 2)
- Can use a Waveshare Game HAT (Pi2 or 3 Only) (GPIO Config 3)
- Also works with the Keyrah and TheC64 'Maxi' case
Limitations
- USB gamepad support is limited. Not all gamepads will work (especially wireless).
- There is no network support.
This project uses VICE for emulation without any O/S (Linux) distribution installed on the Pi. VICE (Versatile Commodore Emulator) platform dependencies are satisfied using circle-stdlib.
For Plus/4 emulation on the Rasbperry Pi 3, a more accurate emulator using Plus4Emu is also available.
Known Issues
-
There is no hot plug in/out support for USB devices. All devices must be plugged in before the device is booted and never removed. Attempting to remove them will halt the emulator or make it slow down considerably.
-
Some USB gamepads will require manual tweaking of settings from the defaults.
Precompiled Images
NOTE: Since V3.0, all machines are now bundled into one release for all Pi models. You can switch from the 'Machine' menu.
- https://accentual.com/bmc64
Github Link
- https://github.com/randyrossi/bmc64
Machine Selection
The default machine is a C64. You can switch to VIC20, C128, Plus/4 or PET from the 'Machines->Switch' menu option. These configurations are defined in machines.txt. There you will find configurations for each machine type for NTSC/PAL over HDMI/Composite combinations. Most video modes are 720p but you can change this (see below).
machines.txt (Video & Timing)
The emulated machine is timed by the video mode you select. The default config provided uses 720p PAL 50hz on HDMI. This is a 'safe' mode that should work on all monitors. A 50.125hz custom mode is provided for the C64/Vic20/C128 machines that will match the timing of the real machine. However, this mode may not work on all monitors.
Inside machines.txt, you can change or add new machine configurations. These will show up in the Machines->Switch menu.
Here is an example of a machine entry:
[C64/PAL/HDMI/VICE 720p@50Hz]
disable_overscan=1
sdtv_mode=18
hdmi_group=1
hdmi_mode=19
machine_timing=pal-hdmi
scaling_params=384,240,1152,720
NOTE: Even though a config is intended to be used for HDMI or Composite (never both), you should always define both composite and hdmi parameters.
Valid machine names are C64, C128, VIC20, PET, PLUS4 and PLUS4EMU (Rpi3 only) Valid video standards are NTSC, PAL Valid video output types are HDMI, Composite, DPI
For HDMI, you should choose either a 50hz or 60hz mode. See below for notes on using DPI.
If you want to use composite out, you MUST set machine_timing parameter to ntsc-composite or pal-composite and set the corresponding sdtv_mode. Otherwise, you will have audio synchronization issues.
Raspberry Pi Video Mode | machine_timing | cycles_per_second ----------------------------|----------------|------------------- hdmi_group=1,hdmi_mode=19 | pal-hdmi | not required hdmi_group=1,hdmi_mode=4 | ntsc-hdmi | not required sdtv_mode=18 | pal-composite | not required sdtv_mode=16 | ntsc-composite | not required hdmi_group=2,hdmi_mode=87 | pal-custom or ntsc-custom | see below
How to add your own custom HDMI mode (VICE emulators only)
You are free to experiment with different modes. It may be advantageous to set the video mode to match the native resolution of your monitor. That way, it may have less processing to do and may save on latency (not confirmed). That can be accomplished with either a different hdmi_mode or a custom mode.
If you plan to use a custom HDMI mode, you will have to alter the machine's 'cycles_per_second' value to match the actual fps that mode outputs. Custom HDMI modes may not be exactly 50 hz or 60 hz and that can cause audio sync issues if you use the default value. A tool to calculate this number is provided under the 'Video' menu. The test will take 10 minutes and will let you know what values you should add to cmdline.txt for machine_timing and cycles_per_second. You only need to run the test once for that mode.
Example: Making a custom 1360x768 50Hz HDMI Mode
First change config.txt to the custom mode you want
disable_overscan=1
sdtv_mode=18
hdmi_group=2
hdmi_mode=87
hdmi_cvt=1360 768 50 3 0 0 0
In config.txt you would temporarily have:
fast=true machine_timing=pal-hdmi (remove any cycles_per_second settings)
Boot, then run the test tool. The tool will tell you the actual frame rate for this mode is 49.89 and show you the machine_timing and cycles_per_second parameters to use:
machine_timing=pal-custom cycles_per_second=980670
You would then define your machines.txt entry like this:
[C64/PAL/HDMI/1360x768@49.89Hz]
disable_overscan=1
hdmi_cvt=1360 768 50 3 0 0 0
sdtv_mode=18
hdmi_group=2
hdmi_mode=87
machine_timing=pal-custom
cycles_per_second=980670
(see below for chosing scaling_params)
And this option will show up in the Machine->Switch menu.
Custom HDMI modes are not supported for plus4emu yet.
DPI (Parallel Display Interface)
BMC64 v3.3 and higher supports video output via DPI. DPI is a (up to) 24-bit parallel RGB interface. A DPI capable display device or RGB adapter board is required. You will have to match the output format to your device. See https://www.raspberrypi.org/documentation/hardware/raspberrypi/dpi/README.md for more details.
DPI disables HDMI and Composite video and is different for every device. For this reason, these configurations are not provided by default and must be added manually to machines.txt. I suggest once you have a working configuration, you add the machines.txt entries for all the machines you want to use DPI with.
Here are a couple examples you can add to machines.txt that will work with the VGA666 adapter board:
[C64/NTSC/DPI/VGA666:720p@60hz]
enable_dpi=true
machine_timing=ntsc-custom
cycles_per_second=1025643
enable_dpi_lcd=1
display_default_lcd=1
dpi_group=1
dpi_mode=4
scaling_params=384,240,1152,720
[C64/PAL/DPI/VGA666:720p@50hz]
enable_dpi=true
machine_timing=pal-custom
cycles_per_second=982734
enable_dpi_lcd=1
display_default_lcd=1
dpi_group=1
dpi_mode=19
scaling_params=384,240,1152,720
- It appears these modes are not exactly 50hz/60hz like HDMI. It's likely the case that all DPI modes will require custom timing. See steps mentioned above for how to find the correct cycles_per_second value for your DPI mode.
** DPI uses almost all the GPIO pins. GPIO configs for things like joysticks/keyboards/buttons are disabled when enable_dpi is present in cmdline.txt
*** Special thanks goes out to github user K-rnivoro (https://github.com/K-rnivoro) for suggesting this feature.
Recovering from a Blank Screen
If you are experimenting with a video mode and are not getting a picture, you can press Cntrl followed by F7 and hold both for 5 seconds after a boot, then release the F7 key. This will reset the emulator and switch back to C64 with a 'safe' HDMI 720p video mode. (This will also work over composite but you should follow up with a switch to one of the composite modes for correct audio sync.)
Video + Timing (VIC20, C128, Plus/4, PET)
All of the above re: timing applies to the other machines as well. However, in my opinion, the VIC20 machine is better configured to be an NTSC machine. Most cartridges were made for NTSC and you will notice they position their screens poorly when inserted into a PAL machine. Most games gave the option of moving it using cursor keys or joystick but this is annoying.
Dimensions and Scaling
The virtual display dimensions can be adjusted dynamically from the menu. Under 'Video', you will find Horizontal Border (px), Vertical Border (px), and H/V Stretch controls for each virtual display available. Displays are scaled as follows:
1. The main graphics area is trimmed or padded by border level adjustments.
2. The resulting image is scaled according to stretch factors (1.0 is full vertical height, horizontal is a scalar of the display height)
3. The scaled image is then centered within the display resolution.
Using the settings, you should be able to customize the display to your liking. However, if you plan on using scaling_kernel=8 (nearest neighbor) there are benefits to chosing dimensions that result in integer multipliers of the frame buffer (see below).
Integer Scaling
If you want to get better picture quality on your CRT monitor or if you prefer the 'pixel perfect' look on HDMI, integer scaling is what you want. Integer scaling along with scaling_kernel=8 will eliminate scaling artifacts (i.e. variation in thickness of scaled up pixels). However, you may have to sacrifice some border area and/or not get the exact aspect ratio you want.
When you change the border values, you will see three dimensions displayed; the display dimensions, the frame buffer dimensions (FB) and the scaled frame buffer (SFB) dimensions. When the scaled frame buffer dimensions are an integer multiple of the frame buffer dimensions, they will turn green.
To make this easier, there are video opti
