We start the process of porting righto.com/sinclair to an Arduino sketch by looking under the hood.
Right click on an empty place on the page and select View page source. This is a very friendly page that is meant to be read and understood by others. We have to start finding out what happens in each of the following modules.
The file cpu.js is important to us, so are masks_sinclair.js, model.js, sourceCode_Sinclair.js
Here is the beginning of the CPU step function, found in CPU.js
We have to start looking for important functions and their dependencies. The function step() seems important, it fetches an instruction, decodes and executes it. it depends on variable called model and it uses extensively a function called add.
Below is the ported code. Since the instructions are numbers greater than 255, but less than 65535, and they are always positive, the type unsigned int (we could also use uint16_t). The variables classBits and opcode are bit shifts of the variable instruction. Looking at the amount of shifts or the mask applied with a bitwise AND (&) operator, one can see that these hold 8 bit values and can be expressed as byte or uint8_t.
Looking at the add function we see that it depends on getMask and maskVec, time to find those functions and port them.
As a quick example of the effort involved, here is the C version of this function. The amount of information that has to be added is visible. Since src1 is an array of 8 bit values that can go negative, signed char src1 is used. The for loop logic counts down from 10 to 0, exiting when it goes negative, a signed char has to be used here as well.
The mask function is also found in cpu.js. We need to identify its dependencies and the data types of the variables used.
Here are the masks, expressed as an array of strings. Since this do not change, when porting these, the keyword PROGMEM will be used to keep them in ROM space in the Arduino and not load them into the very limited 2K RAM space. The pgm_read_byte_near() function is needed to get their values from ROM.
Here is an important data structure. It holds all the CPU registers, flags, program counter,
Finally, the actual original Sinclair program can be found in the objectCode variable. Above it is a commented disassembly of the program.
The following file is the beginning of the porting efforts. It contains the ALU (Arithmetic Logic Unic) functions such as ADD, SUB, COMPARE and their mask related dependencies. The setup function tests those functions and displays the results.
Here is the final Arduino Sketch (SinclairScientific1.ino). It has all the data structures needed by the CPU emulator. Everything is put together here, the keyboard is read, the display updated and the CPU stepped.
The following file is called by the step() function with a sequential instruction ID number assigned to each original cpu instruction. It was useful at the beginning to see that the instructions being executed matched the disassembly on the web page.
Time for a couple of Tweets: