The microcontroller chosen for this project, the ATMega, can only execute programs out of ROM. I knew that limitation from the beginning; I have a bytecode interpreter embedded in OS that I have been extending during this retrochallenge. As I write short programs for it, I realize there are some operations that are inconvenient, so I have been adjusting the instruction set as I go along.
The interpreter is a direct threaded-code interpreter. One unusual feature of this interpreter is that the opcode of the instruction is actually part of the address of the instruction handler. The upper byte address of the handlers are fixed: The entry points of the interpreter must be in a table 256 instructions and aligned along a page boundaty. Some short, common instructions like add, are embedded directly in the interpreter table, whereas instructions that already take longer, like multiplication, are JMPed to the actual handler.
Here is what the assembly language for the emulated 16-bit CPU. I will add comments and explain how this works soon. This program is the main loop animating several rows of sprites moving left and right on the screen. I intend to fill this out into a Space Invaders clone.
FINDDEV=1 WRITE1=2 READ1=3 DRAWSPRITE=5 UMOD=9 CLEARSCREEN=6 ldi a 0 syscall @CLEARSCREEN draw: ldi a @sprite offset a mov c a #c has sprite ldi b 20 nextrow: ldi d @apos offset d lda d next: push a push b push c #save pos and sprite swp d ldi a @eraser offset a mov c a swp d add $ffff swp b add $ffff swp b syscall @DRAWSPRITE #draw sprite c at a,b pop c pop b pop a syscall @DRAWSPRITE #draw sprite c at a,b ldi d 16 add d #add increment #compare to 200 + apos push a ldi d @apos offset d lda d add 200 mov d a pop a cmp d jb @next ##next row swp b # a has y coord ldi d 16 add d #add to it ldi d 120 cmp d #compare jae @donerows swp b jmpr @nextrow donerows: ldi a @adir offset a ldb a #b=adir ldi d @apos offset d lda d #a=apos add b #a+=b sta d #apos=a #check if need to flip direction to - ldi b 30 cmp b jb @AA ldi a $ffff ldi d @adir offset d sta d AA: #check of need to flip to plus ldi b 8 cmp b jnz @noflip ldi a $0001 ldi d @adir offset d sta d noflip: jmpr @draw #halt: #jmpr @halt apos: word 16 adir: word 1 bpos: word 16 playerpos: word 120 sprite: byte $5 byte $5 data $ff03ff03ff data $0303ff0303 data $ffff03ffff data $0c03ff030c data $03ff0cff03 psprite: byte $7 byte $6 data $ffffff0cffffff data $ffff0cff0cffff data $ffff0cff0cffff data $ff0cffffff0cff data $ff0cffffff0cff data $0cffffffffff0c eraser: byte $7 byte $7 data 00000000000000 data 00000000000000 data 00000000000000 data 00000000000000 data 00000000000000 data 00000000000000 data 00000000000000