Showing posts with label CC65. Show all posts
Showing posts with label CC65. Show all posts

Thursday, July 9, 2020

Robot Game: 65C02 C, assembly, and Forth Comparison

The last six months or so, I have been working on a project to compare the performance of C, assembly, and Forth on the 65C02. This week I finally finished everything and published the results on my website. A few days later, the project was featured on Hackaday!

To compare the performance between the languages, I made a simple game called Robot Game in Python in order to have something to port. The C version is compiled with CC65 and the Forth version with Tali Forth 2. There are two assembly versions. One is plain 65C02 assembly using the X register as a data stack and the other uses the Assembly Optimizer I have been working on to get slightly better performance by putting locals in zero page at fixed addresses. All four version of the game work in my JavaScript-based emulator and can be played on my website. The source code for all the versions of the game, the emulator, and optimizer are now on my GitHub page.

Porting the four games was a challenge and also a lot of fun! I learned a lot about how C and especially Forth work internally. After I had the games ported, I looked at 28 different tasks the game does internally and compared performance across languages. Here are the results where traditional assembly is normalized at 100%:


The optimizer adds up to 10% performance and 25% in one very short routine. C was about 2-3 times slower than regular assembly in the tests and Forth was usually around 10-20 times slower. One of the really interesting things was figuring out why Forth is so much slower despite Forth fans claiming it's much better than C. 

Monday, June 23, 2014

6502 Virtual Trainer: Update

Lately I have been working on several different projects and I have made a lot of progress on the 6502 Virtual Trainer. The first step was connecting the PC interface to an MSP430 over UART. This was easy because I have done it in other projects. Microchip let me sample some MCP23S17 IO expanders and I was really excited to be able to try them out to read and write the pins of the 6502. Unfortunately, they were a little finicky to get going because the datasheet incorrectly lists the reset pin as an output instead of an input.  They do save a lot of space, though, because five shift registers would be needed to replace them. After that was solved, I was able to single-step the processor as I intended but only at about 90 cycles per second. For comparison's sake, with the processor doing nothing else, that is a little too slow to type comfortably. At the beginning I knew this would be slow but that is much slower than I expected. The bottleneck seems to be the USB<->serial layer since the program sends lots of small packets of data instead of small numbers of large packets. To speed this up, I send 10 bytes of op codes every packet. Then the MSP430 can use the data sent if it needs to read a byte that is near. It will have to request more data if a jump takes place or data is read from another location in memory but in general this improvement led to a speed up of about 150 cycles per second. This was still not as fast as I had hoped for so I decided to keep a copy of all of the memory on an SPI SRAM chip. For this I used a 23LC1024, also from Microchip, which holds 128k. Using an SPI SRAM might seem to make less sense than just hooking up a typical parallel SRAM but by letting the microcontroller control the memory I can hold extra information about the data such as which bytes have not been initialized and which should be ROM. This will let me break when reads and writes that would be illegal are performed. Even during testing this turned out to be useful as it is easy for a beginner to assembly to write something like LDX $FF instead of LDX #$FF. As a compromise the MSP430 runs the 6502 as fast as possible then pauses and updates the PC every 200ms or when 64 bytes of memory have been modified, whichever comes first. Another way to speed things up was to increase the COM port speed from the 230,400 bps max of the MSComm control I'm using with Visual Basic 6 to 1,000,000 bps. At 1,200,000 bps the MSP430 could not keep up running the 6502 and reading data. With these changes I can run the 6502 at about 12,000 cycles per second. This is still pretty slow but fast enough to play with for learning purposes. To test things I made a few programs including one that draws a faded red pattern like below: