Fun with Lisp: Programming the NES (2012)
ahefner.livejournal.com
ahefner.livejournal.com
Brit Butler has written a 6502 emulator[0] and is now writting a NES emulator in lisp[1]
Henry baker wrote a compiler for a simple lisp named 'comfy' for the 6502 chip which intended to replace it's assembly in emacs lisp[2] which has been ported to common lisp[3]
[0]: https://github.com/redline6561/famiclom
[1]: https://github.com/redline6561/cl-6502
[2]: http://home.pipeline.com/~hbaker1/sigplannotices/sigcol03.pd...
A typical assembler reads the program in assembly language syntax and translates the lines into binary instructions. And you could write a Lisp compiler that reads in Lisp and produces maybe C which is then compiled into assembly language which is finally fed to the assembler. But he started by writing the assembler in Lisp and instead of parsing and translating assembly language he wrote his assembly program by calling Lisp functions such as (inc) (txa) (lsr) which just emitted the appropriate instruction codes.
However, at this point there was no barrier left between his host-side Lisp and target-side machine code. He could write constructs in Lisp that, by running the Lisp program, expand to the corresponding machine code. And given some well-chosen Lisp constructs he could elevate the code into a much higher level but still output 6502 machine code. He could write Lisp macros to produce Lisp code that produces 6502 code.
And because everything was still tightly integrated in a single running Lisp program, he could keep doing the low-level stuff as well because he was still in control of what machine code instructions would be written out.
This IMHO is a much better way to write assembly language than the usual syntax that assemblers parse. But it's not possible unless code is data is code.
Here is a sample of code generation in Prolog for register machines, https://github.com/segmond/PrologThingz/blob/master/clause_a...
An example for accumulator based machines which the 6502 https://github.com/segmond/PrologThingz/blob/master/clause_a...
The examples I posted is from an awesome Prolog book I read called "Clause and Effect"
You can start writing a debugger on top, disassembler, and an emulator. You're not restricted in Lisp from doing low-level bit-twiddling of this sort.
Here's one dev's experiences making a GTA-like game for the NES, using his own high level assembler: https://www.youtube.com/watch?v=Hvx4xXhZMrU
Here's one for CHIP8: http://johnearnest.github.io/Octo/
Impressive.
I so want to start learning to program in NES now. Not really in Lisp as I would like to learning curve to be gentler, but this article definitely sparked my interest into learning one of the devices I used most during my childhood.
Great work!
I've already been productively using it for myself doing a bit of ROM hacking. It feels like a much nicer environment to me than the usual romhacking setup. Still has some rough edges, though.
One of the best parts of it for me is seeing the assembly assemble as I type it, telling where it goes in the file, what the PC should be at that point, and if the line has an error, it shows it. http://i.imgur.com/JfEwJ9U.png
Knowing Lisp would help you easily understand and extend the assembler, so you could do things like create yourself some badly needed program organization abstractions and then use them. Otherwise you could just ask the author, or people in a mailing list. "Hey I would like a feature whereby if I write (foo bar) in the code, such and such an effect takes place in the generation of the 6502 image."
In any case, learning 6502 asm seems like a must like you say. I'm gonna have to try to learn a bit.
I've actually been walking around for a few days just now pondering if one could do the corresponding thing for contemporary graphics processors. Seems like communicating with them in Lisp could be a great thing. (That idea was inspired by another HN post https://news.ycombinator.com/item?id=7408807) Do you know of any attempts at that?
I find it to be very readable:
https://github.com/gutomaia/pyNES/blob/0.1.x/pynes/examples/... example file, I like it