This is a MOS Technology MCS 6502 micro-processor simulator currently working on POSIX systems such as Linux and the Microchip PIC32 micro-controller.
A legacy version for the Commodore Amiga also exists. This version needs bug fixing and has had no maintenance since it was written in 1989.
Fetch the source and build. For PIC32, install the MPIDE compiler first.
hg clone http://hg.kewl.org/pub/Ape65 cd Ape65 make
make install
The POSIX simulator has 48KB of usable RAM. The rest of the 64KB addressable is for ROM and console I/O.
For the MX150/MX250 this simple schematic can be used to realise the simulator.
Pickle is used to program the chip on the RPi. PIC32Prog can be used with an Arduino.
For the MX150
p32 program mx150.hex
or, the MX250
p32 program mx250.hex
The MX150/MX250 has 16KB of usable RAM set aside for the simulator. There is also 10KB ROM, a console and an I/O port.
The MX170/MX270 is an enhanced version of the MX150/MX250. The MX150/MX250 schematic above can be used for this chip.
Pickle is used in this example to program the chip on the RPi.
For the MX170
p32 program mx170.hex
or, the MX270
p32 program mx270.hex
The MX170/MX270 has more RAM than the MX150/MX250 and 48KB is free for the simulator along with the ROM, console and an I/O port.
The MX250 is the chip that comes pre-installed on the chipKIT Pi. We upload the hex file to the standard loader.
Pickle pload can be used to upload the object, alternatively PIC32Prog may be utilised.
pctrl restore && pload program /dev/ttyAMA0 mx250_ckpi.hex 24
The MX250, as the MX150 has 16KB of usable RAM for simulation along with the ROM and I/O.
This is an enhanced PIC32 which has been used to upgrade the chipKIT Pi using the chipkit32 boot loader.
pctrl restore && pload program /dev/ttyAMA0 mx270_ckpi.hex 24
The MX270 is identical to the MX250 but has 48KB of usable RAM for the simulator.
The Majenko SDXL is a powerful PIC32MX795F512H based board with a USB boot loader.
pload program /dev/ttyACM0 sdxl.hex 24
48KB of RAM is free for use with the simulator along with BASIC, a UART console and an I/O port.
Ape65 emulates TEDMON (the machine code monitor) found in the Commodore plus/4 and C16 home computers with slight variation and some enhancements.
Entering a query (?) in Ape65 will instruct it to show a short overview of the commands available.
On the POSIX version we run Ape65 to begin a simulation and get the overview.
/usr/local/bin/ape65
On the PIC32 version, rather than run, we attach to the serial port of the micro. For example, we can use screen,
screen /dev/ttyAMA0 115200 X
or picocom.
picocom -b 115200 /dev/ttyUSB0 X
To exit from screen, perform CTRL + A k, to exit picocom it's CTRL + a q.
With both versions we will see something similar to what is below.
Welcome to the APE65 MCS6502 simulator -------------------------------------- Written by Darron M. Broad. August 1989, February & March 2015. Includes EhBASIC by Lee Davison. Enter ? for HELP. PC SR AC XR YR SP NV.BDIZC ; 0000 30 00 00 00 FF ..11.... ? A assemble D disassemble C compare T transfer F fill H hunt G go R register dump M memory dump > modify memory ; modify reg X exit L load file S save file V verify file ! shell command + trace on - trace off $ hex convert # dec convert % bin convert @ oct convert B start BASIC ^S stop BASIC
All the commands documented in the plus/4 user manual on page 182 onward are implemented on the POSIX version of Ape65. There is some variation, however, with the file operations. Ape65 omits the device parameter found in the original TEDMON since it serves no purpose here.
See this TEDMON help file for a better overview of the commands.
EhBASIC is also included. EhBASIC is a BASIC interpreter written in 6502 assembly code. It can be started with the B command and stopped with CONTROL-S.
The EhBASIC language and syntax is documented here.
At this time, the PIC32 version has no file operations and the POSIX version doesn't support any port I/O.
To simulate the 6502, the assemble command must be issued to Ape65 and a number of 6502 instructions are then entered into memory. Once this is done, the code may be executed on the virtual processor.
Memory is organised as follows, as good a place as any to enter machine code is $1000.
Address | Function |
---|---|
$0000 | RAM |
$C000 | BASIC ROM |
$F000 | CONSOLE |
$FD10 | GPIO |
$FF80 | BOOT ROM |
Below we enter some code into Ape65. Although it cannot be seen here, the last line is simply the enter key entered alone to exit assemble mode.
A 1000 LDA #1 CLC ADC #127 BRK
As per the original TEDMON, the display is updated with the opcode and operand data as each line is completed. This is what is shown in the terminal as the above is entered.
A 1000 A9 01 LDA #$01 A 1002 18 CLC A 1003 69 7F ADC #$7F A 1005 00 BRK A 1006
We now enable trace mode and execute the code, with trace mode enabled we get a running status of the instructions.
+ TRACE ON G 1000 PC SR AC XR YR SP NV.BDIZC ; 1000 30 00 00 00 FF ..11.... A9 01 LDA #$01 ; 1002 30 01 00 00 FF ..11.... 18 CLC ; 1003 30 01 00 00 FF ..11.... 69 7F ADC #$7F ; 1005 F0 80 00 00 FF 1111.... 00 BRK PC SR AC XR YR SP NV.BDIZC ; 1007 F4 80 00 00 FC 1111.1..
Above we can see the number 1 ($01) loaded into the accumulator AC and then 127 ($7F) is added to it to get a total of 80 hexadecimal which is 128.
A UART is simulated for both read and write of a single character. Read is non-blocking and will return 0 when no character is ready. Write will always return after sending a character.
Address | Function |
---|---|
0xF001 | WRITE |
0xF004 | READ |
For these MX devices a virtual MOS 6529B I/O port is implemented at $FD10. This I/O port works as the original chip in an open-drain mode of operation. The virtual I/O port utilises pins B0 through to B7 on PORT B.
Writing a 0 results in the pin going LOW, writing a one leaves the pin to be pulled high or low externally. When writing a one, the port can be read as an input.
On the chipKIT Pi the four LEDs are assigned to the lower nibble of a virtual I/O port at $FD10. Writing a one to any of these bits will turn the LED on. The next three bits are set up as open-drain pins as per the MX150 above, and the most significant pin is used for the BOOTLOAD-EN switch input.
Bit | Function |
---|---|
0 | LED1 |
1 | LED2 |
2 | LEDRX |
3 | LEDTX |
4 | D2 |
5 | D3 |
6 | D8 |
7 | BOOTLOAD-EN |
A simple program can be used to demonstrate turning the LEDs on and off slowly.
A 1000 A9 00 LDA #$00 A 1002 8D 10 FD STA $FD10 A 1005 A2 00 LDX #$00 A 1007 A0 00 LDY #$00 A 1009 88 DEY A 100A D0 FD BNE $1009 A 100C CA DEX A 100D D0 FA BNE $1009 A 100F EE 10 FD INC $FD10 A 1012 4C 09 10 JMP $1009 A 1015 G 1000
CTRL-C will break the emulation.
Port E is assigned as a virtual I/O port at $FD10 on the SDXL. The MSB is the LED output and the other 7 bits emulate a MOS6529B as explained above for the MX150 and MX170.
From TEDMON entering B will start EhBASIC. There are two start up methods. Enter C for cold initially and enter W for warm after BASIC has been stopped with CTRL-S.
For the memory size option, just press enter and EhBASIC will work out the RAM size available.
B 6502 EhBASIC [C]old/[W]arm ? Memory size ? 48383 Bytes free Enhanced BASIC 2.22 Ready
Now we can enter a program. EhBASIC statements must be in upper case and Ape65 will automatically convert lower to upper and upper to lower for us without having to resort to caps-lock.
10 PRINT "HELLO WORLD "; 20 GOTO 10 LIST 10 PRINT "HELLO WORLD "; 20 GOTO 10 Ready
When running a program which doesn't end, pressing CTRL-C will terminate it.
RUN HELLO WORLD HELLO WORLD HELLO WORLD HELLO WORLD HELLO WORLD Break in line 10 Ready
If we press CTRL-S we will exit EhBASIC completely.
PC SR AC XR YR SP NV.BDIZC ; FFB6 30 13 00 09 FB ..11....
Warm starting EhBASIC is needed after a CTRL-S if we wish to continue.
B 6502 EhBASIC [C]old/[W]arm ? Ready LIST 10 PRINT "HELLO WORLD "; 20 GOTO 10 Ready
On the PIC32 we can also do I/O from within EhBASIC with the PEEK, POKE, BITSET and BITCLR commands.
POKE $FD10,0 POKE $FD10,15
If we want to reset the simulator on the PIC32, we can use the pickle command pctrl.
pctrl restore
For the POSIX version, just exit and restart the program.