Go Down

Topic: Arduino 6502 emulator + BASIC interpreter (Read 144730 times) previous topic - next topic


Some Changes to EhBasic

I modified EhBasic a little bit.
Now Basic-Keywords are accepted in lower case. Some of the code examples makes use of it.
The Integer parameter check is less restrictive.
Poke now works if the second parameter is out of range. In this case the low byte will be taken. The Basic program does not abort.
Input does not abort the Basic program, if you just press enter without typing anything. It simply repeats the "?" prompt and gives you a second chance.
These modifications may have side effects to other functions. As far as I tested, it seems to be OK.

6502 Emulator bugfix decimal mode

I had to patch the adc() procedure in cpu.c for decimal mode to make the HEX$() function of EhBASIC work correctly. It did print wrong characters for 'A'-F'.
A discussion at 6502.org pointed out problems with HEX$() function and decimal mode on emulated 6502 CPUs.
I'm not sure if decimal mode is correct now, but it's good enough for the Hex$() function.

The sbc() function should also be fixed for decimal mode, if anybody needs it.

Memory Map for Arduino Uno / Nano

This is the actual Memory Map:

// 6502 memory map
// 0000-00FF: 6502 Zeropage (AVR internal)
// 0100-01FF: 6502 Stack (AVR internal)
// 0200-BFFF: external EDO RAM
// F000-FEFF: IO_AREA, Simulated I/O
//  F001      simulated ACIA write port
//  F004      simulated ACIA read port
//  F0A0/A1   timer tick counter (r) prescaler & reset (w)
//  F0B0/B1   edoPage1 hi memory address register
//  F0B2/B3   edoPage2 hi memory address register
//  F100/1FF  AVR IO Address space is mapped here
//  F400/7FF  1K hi memory block #1
//  F800/bFF  1K hi memory block #2

// FF00-FF7F: BOOT-ROM (reserved)
// FF80-FFFF: BOOT-ROM (mini_mon)
// FFFA/FFFB: NMI vector
// FFFC/FFFD: RESET vector
// FFFE/FFFF: IRQ vector

Startup message
The startup message has been reformatted to fit on a small 128x64 OLED display.

6502 EhBASIC
48383 Bytes free
Derived from

Benchmark FOR-loop
Test program: Empty FOR-loop executed 10000 times.

doke $f0a0,10:for i=1 to 10000:next:print deek($f0a0)


The FOR-loop runs 44.03 seconds.

Minute / Second Counter
A small program that uses the timer/counter to display minutes and seconds on the OLED display.

10 print chr$(12);chr$(3);"    Min:Sec"
20 doke $f0a0,1000:do:d=deek($f0a0):m=int(d/60):s=d-m*60
30 s$=str$(s):s$="0"+right$(s$,1-(s>9)):s$=right$(s$,2)
40 print chr$(6);"    ";m;":";s$;chr$(9)
50 do: loop until d<>deek($f0a0):loop

There are some simple control characters supported by the OLED driver:

chr$(1)   Set cursor Home, line 0
chr$(2-8)   Set cursor at start of line 1-7
chr$(9)   Clear end of line from current cursor position
chr$(10)   CR+LF
chr$(12)   Clear screen

Decode EhBASIC Program
This program decodes a BASIC program which is stored in RAM. It is useful to understand, how EhBASIC encodes the program lines.

Startaddress of BASIC program: $79/$7A.
Endaddress of BASIC program: $7B/$7C.

First element in a BASIC line is a link field to the next line.
Second element is the binary encoded line number.
Token are encoded with bit7 = 1 (128..255).
A BASIC line ends with a zero.

100 a=DEEK($79):e=DEEK($7b)
110 PRINT "Start:";HEX$(a,4),"End:";HEX$(e,4)
120 DO:PRINT HEX$(a,4), HEX$(DEEK(a),4), "Link":a=a+2
130 PRINT HEX$(a,4),HEX$(DEEK(a),4),"L=";DEEK(a):a=a+2
140 DO:c=PEEK(a):PRINT HEX$(a,4), HEX$(c,2),
150 IF c>=$80 THEN PRINT "Token";
160 IF c>31 AND c<$80 THEN PRINT CHR$(c);
180 PRINT:a=a+1

output for the first line:

Start:0301    End:040E
0301          0316          Link
0303          0064          L= 100
0305          61            a
0306          C1            Token
0307          D2            Token
0308          24            $
0309          37            7
030A          39            9
030B          29            )
030C          3A            :
030D          65            e
030E          C1            Token
030F          D2            Token
0310          24            $
0311          37            7
0312          62            b
0313          29            )
0314          20             
0315          00           


I have a (near) full Apple II+ emulator running on DUE, based on Mike's 6502 emulator. See here: https://youtu.be/nySPcWenwTQ for more details.


Apr 30, 2019, 04:57 am Last Edit: Apr 30, 2019, 04:58 am by airturk
This is an awesome project.  Thanks for sharing it.  I came across it while looking for KIM-1 information.

I'm going to use couple of ideas from this project on my RetroShield for Arduino Mega project. (6502 connected to an Arduino Mega, and Mega currently emulating the Apple-I or KIM-1 hardware). I bought the 128KB SPI RAM and will implement the cache. I think it would be great. C64 BASIC will be next :)


I've just started looking at this - like it.
Quick question - I have the c64 ROMS but how do I convert them so I can load them? 
Currently they are Hex arrays in code (0x??)




I know it's a few years since this thread started - but we now have 400/480MHz  STM32H743 Nucleo boards that are all part of the growing Arduino family.
There's enough grunt there to run a very fast 6502 emulation - and drive a VGA monitor directly from the STM32 LCD driver signals.

For about $25 investment you could have a super-retro 6502 machine - with 1MB of SRAM and 128K of Flash ROM.

Just a Thought



You can also use a BluePill, 64Kb flash (but it seems that is 128!) and 20Kb RAM about 2$


Jul 13, 2019, 01:32 pm Last Edit: Jul 14, 2019, 12:39 pm by guinnessimo
Hi All,

I've tried Mike's code (as posted in the first post of this very long thread) on a 400MHz Nucleo STM32H743ZI

Arduino IDE now supports this board if you install the STM32 boards using Board Manager.

Mike's code runs ehBASIC on this board without modification, but you may wish to increase the RAMSIZE to 48K  (49152) and increase the serial speed to 921600 .

Using this program it will print the numbers 0 to 10000 in about 8 seconds

10 FOR I = 0 TO 10000

The Trigonometric function test runs in about 2 seconds

I also tried a 0 to 1,000,000 empty FOR-NEXT loop. This ran in 111 seconds.

I'm sure if I used some of the modifications and tweaks as discussed in this thread it could be a lot quicker - but if you want a quick and dirty 6502 emulation in a hurry, on a stock Nucleo board, this will only take about 30 minutes to get running




Hi, I used the code found in this posting to load ROMs of various Commodore machines (PET2001 BASIC1, BASIC2 and CBM8032) with an ESP8266. I was even able to do it for a VIC20.
The screen output is not send via Serial but to a SSD1306 OLED Display.
Now I am struggeling with the C16/PLUS4 ROMs.
At first it came up with the "MONITOR" because it assumed the RUN/STOP key is pressed.
Now everything looks fine, I get the startup screen. The only issue is witn any numbers printed on the screen.
E.g. the bytes free info shows strange letters only.
Same is I enter a "PRINT 2" (or any other number or variable.
This comes back with:   |L   (Pipe/Capital L)

Any idea on that?

I am using this to access ROM/RAM:

uint8_t read6502(uint16_t address)
  if (address < RAM_SIZE) return (RAM[address]);                                // free RAM for user
  if (address >= BASIC_START_ADDR)  return pgm_read_byte_near(BIOS + (address - BASIC_START_ADDR));
  return (0x00);

void write6502(uint16_t address, uint8_t value)
  if (address < RAM_SIZE) RAM[address] = value;


Hello, i have a problem with compilation of "arduino_6502.ino & cpu.c".

Arduino:1.8.10 (Windows 10), Tarjeta:"Arduino/Genuino Uno"

cpu.c:70:1: error: unknown type name 'prog_uchar'

 prog_uchar BIOS[10496] PROGMEM = {


cpu.c:70:12: error: variable 'BIOS' must be const in order to be put into read-only section by means of '__attribute__((progmem))'

 prog_uchar BIOS[10496] PROGMEM = {


cpu.c:1028:1: error: unknown type name 'prog_uchar'

 prog_uchar BIOStop[256] PROGMEM = {


cpu.c:1028:12: error: variable 'BIOStop' must be const in order to be put into read-only section by means of '__attribute__((progmem))'

 prog_uchar BIOStop[256] PROGMEM = {


exit status 1
unknown type name 'prog_uchar'

I need help. Thanks


any idea why the execution of miker00lz 6502 emulator code fail on arduino uno/nano?
I get stucked on the memory size part
Any hints are welcome to go further ;)


It is a test with a TTGO display and its graphic library, with a small tribute to Commodore 64. I use a serial wifi connection with the putty configured in rlogin. It is a first version that can be improved. Thank the community for the development of libraries. I upload photos and the program.



Whats the license this code is under? MIT, LGPL, public domain?
I'm considering converting this thing to lua.



Sorry, I don't know the license.
I am trying to save and read the basic in sd card, in case someone has worked on it.
It would be interesting to enable the save command and the load command of the basic commodore.


unknown type name 'prog_uchar'

I had the same problem.

To fix it:

1. Make sure the file pgmspace.h is present so that

#include <pgmspace.h>

will reference it. You could simple copy it to the same place as stdint.h
I found it in an older version of the Arduino IDE in arduino-0021.zip
I have attached this file.

2. Change

prog_uchar BIOS[10496] PROGMEM = {


const char BIOS[10496] PROGMEM = {

3. Change

prog_uchar BIOStop[256] PROGMEM = {


const char BIOStop[256] PROGMEM = {

That's all, and it compiled and loaded, then used a Terminal to run it.

Go Up