C64 emulator for the development board Lilygo T-HMI equipped with an ESP32-S3 chip, a 2.8 inch touch display LCD screen (ST7789V driver) and an SD card slot. The emulator was later expanded to also support the board T-Display S3 AMOLED.
The keyboard for the emulator is simulated by an Android app, communication between the app and the emulator is realized using BLE (Bluetooth Low Energy).
Contact: retroelec42@gmail.com
From Xinyuan-LilyGO/T-HMI:
The ESP32-S3 is dual core containing a Protocol CPU (known as CPU 0, core 0 or PRO_CPU) and an Application CPU (known as CPU 1, core 1 or APP_CPU). The two cores are identical in practice and share the same memory. The tasks responsible for handling wireless networking (Wi-Fi or Bluetooth) are pinned to core 0 by default (see Espressif - Task Priorities).
For this project core 0 is used to copy the graphic bitmap to LCD. Emulation of the CPU and the custom chips (VIC and CIAs) are done on core 1.
The 2.8 inch ST7789V TFT LCD has a resolution of 240x320 pixel and an 8 bit parallel interface.
The display can be rotated to support the resolution of a C64 (320x200).
I connected an “Arduino joystick shield” to the T-HMI development board. The joystick is optional (as there exists also a virtual joystick on the Android device) but recommended. It has an analog 2-axis thumb joystick and several buttons. As there are several games which use the space bar as a second fire button (e.g. Commando), another button of the Arduino joystick can be used to simulate the pressing of the space bar.
Connections:
Switch voltage to 3.3V on the Arduino joystick module.
If you do not use an Arduino joystick or choose to use other pins on the development board, you may have to adapt the following constants in src/Config.h:
You can also operate your board with a battery. The T-HMI development board allows you to switch on the board by pressing the On/Off switch (next to the SD card slot). However, it does not appear to be possible to turn the board off with this switch. Therefore, the Android app allows the board to be switched off by pressing the Off switch in the top right-hand corner.
I use arduino-cli to upload the provided binary files to the development board:
If you want to install the development environment, you can use the provided Makefile (which itself uses arduino-cli) or you can use the Arduino IDE.
You may have installed already a specfic Arduino core for other projects (e.g. Arduino core 2.0.x) and you don’t want to change this setup. For this situation you can use a prepared docker image to compile the code:
From Xinyuan-LilyGO/T-HMI: In Arduino Preferences, on the Settings tab, enter the Espressif Arduino ESP32 Package URL in the Additional boards manager URLs input box. Click OK and the software will install. Search for ESP32 in Tools → Board Manager and install ESP32-Arduino SDK (V3.0.5).
Use the following settings in the Tools menu of the Arduino IDE 2.3.2:
Setting | Value |
---|---|
Board | ESP32 S3 Dev Module |
Port | /dev/ttyACM0 |
USB CDC On Boot | Enabled |
CPU Frequency | 240MHz (WiFi) |
Core Debug Level | None |
USB DFU On Boot | Enabled |
Events Run On | Core 1 |
Flash Mode | QIO 80 MHz |
Flash Size | 16MB (128Mb) |
JTAG Adapter | Integrated USB JTAG |
Arduino Runs On | Core 0 |
USB Firmware MSC On Boot | Disabled |
Partition Scheme | Huge APP (3MB No OTA/1MB SPIFFS) |
Upload mode | UART0 / Hardware CDC |
PSRAM | OPI PSRAM |
USB Mode | Hardware CDC and JTAG |
Core Debug Level | Info |
The following Arduino libraries are used (all are part of ESP32 Arduino core, version 3.0):
To upload the emulator from the Arduino IDE just open the file T-HMI-C64.ino and choose menu Sketch - Upload or press ctrl-u.
Provided files (source code and binary files) are ready for the board T-HMI. If you want to install the emulator on the T-Display S3 AMOLED board, you have to adapt src/Config.h:
comment line “#define BOARD_T_HMI”
uncomment line “//#define BOARD_T_DISPLAY_S3”
Afterwards you have to compile and upload the code to the T-Display S3 AMOLED board (see chapter “Install C64 Emulator on Lilygo T-HMI”).
Note: Files rm67162.cpp, rm67162.h and pins_config.h were copied from https://github.com/Xinyuan-LilyGO/T-Display-S3-AMOLED/tree/main/examples/factory.
As the board has no SD card you can send a programm from your Android device to the emulator (see below).
I wrote an Android app which provides a C64 keyboard for the emulator.
However, this app is not available in the Google Play Store - you have to download the APK file and install it “manually”. You may follow these steps to install the app on your Android device (there may be slight variations depending on your smartphone).
The emulator starts a BLE (Bluetooth Low Energy) server to receive keystrokes from the Android client.
Once the app is installed and launched, you must accept the requested permissions once (access to the precise location (not coarse location), permission to search for BLE devices). If you start the emulator (i.e. power on the T-HMI) before starting the app, the app will automatically connect to the BLE server. Otherwise you can move the “BLE connection” switch to the right to connect to the BLE server. You also have to do this manually after “hardware reseting” the development board.
As it is not possible to press two keys together on the Android keyboard, the keys Shift, Ctrl and Commodore are special keys which usually are pressed first, followed by another key to simulate the corresponding key combination.
If it is necessary to send the raw key code of these special keys, you have to set the corresponding switch in the Android app (“Send raw keycodes”, DIV screen).
By default, only the pressing of a key is sent to the emulator, which results in, for example, only one space being output even if the space key is held down. With the ‘Detect release key’ option (DIV Screen), the C64 keyboard is emulated more authentically (with the drawback that typing speed is reduced).
The key combination Run/Stop + Restore has been replaced by first pressing the Commodore key and then pressing the Restore key.
Besides the normal C64 keys this virtual keyboard also provides some extra buttons:
Extra functionality and some settings are available in the DIV screen.
The virtual joystick has some drawbacks in terms of responsiveness. To play games, a hardware joystick is recommended.
Because it is difficult to keep an eye on the screen and press the right keys on the virtual keyboard at the same time for pinball games, the flippers of “David’s Midnight Magic” have been outsourced to a separate screen. When you open this screen, the options “Send raw keycodes” and “Detect key release” are automatically enabled. When you close this screen again, both options are reset to the previous values.
You first have to copy C64 games in prg format (only supported format!) to an SD card (game names must be in lower case letters, max. 16 characters, no spaces in file names allowed, extension must be “.prg”, e.g. dkong.prg). You have to insert the SD card before you power on the T-HMI development board.
As there is no C64 tape/disk drive emulation available, the file must be loaded into memory using an “external command”. To do this, you first type in the name of the game (without extension “.prg”!) so it shows up on the C64 text screen (e.g. dkong). You then press the LOAD button on your Android phone (cursor must be on the same line and behind the game title). If the file is found the text “LOADED” appears on screen, otherwise the text “FILE NOT FOUND” appears. Afterwards, as usual, you can start the game by typing “RUN” followed by pressing the button RETURN.
Hint: You can use D64 Editor to extract prg files from d64 files (also works unter linux using wine).
You can also send a programm from your Android device to the emulator (DIV screen, SENDPRG Button).
Keyboard inputs are sent to the ESP32 via BLE. Three bytes must be sent for each key press:
First of all: This is a hobby project :)
All hardware ports not explicitly mentioned including their corresponding registers are not emulated (e.g. user port and serial port).
“Software stuff” not emulated resp. known bugs (list probably not conclusive):
As there is no disk drive emulation, only “onefiled games” can be played. Up to now I tested the following games.
Games that are playable:
Games not working: