Pink Squirrel Labs: Posts tagged '6502'urn:http-www-pinksquirrellabs-com:-tags-6502-html2018-11-21T19:01:33ZC64 Remote Programmerurn:http-www-pinksquirrellabs-com:-blog-2018-11-21-c64-remote-programmer2018-11-21T19:01:33Z2018-11-21T19:01:33Zpezi
<p>In this post I will describe a small electronics project designed to enable the remote programming of a real Commodore 64 that is switched on and running. To achieve this, several parts are involed, utilising some custom circuitry and communications protocol, a Raspberry Pi, a C program, a 6502 assembler program and a little F# program to finish it off.</p>
<div class="figure"><img src="http://www.pinksquirrellabs.com/img/prog/programmer1.jpg" alt="" />
<p class="caption"></p></div>
<!-- more-->
<h2 id="introduction">Introduction</h2>
<p>Programming the C64 is a lot of fun, and mostly you can get by with using an <a href="http://vice-emu.sourceforge.net/">emulator</a>. However, there comes a time when you wish to run your program on the real machine. To facilitate this, I own a very awesome <a href="http://www.1541ultimate.net/content/index.php">1541 Ultimate 2</a> which mimics the <a href="https://en.wikipedia.org/wiki/Commodore_1541">Commodore 1541</a> floppy drive and allows you to load things from a USB stick. Whilst this is really cool, it is still annoying having to keep moving the program from my main machine to the C64 with the stick to see small changes. The 1541 Ultimate 2 does have an ethernet port which I think you can use to send new code over (not sure how that works, or if it lets you change a running program…), but what I really want is a way whereby I have my program running on the C64, and then when I assemble a new version of the program on my main machine, it magically writes itself over the top of whatever is currently running, and starts executing on the C64 with no hard connection.</p>
<h2 id="high-level-design">High Level Design</h2>
<p>The general idea is to connect the <a href="https://www.c64-wiki.com/wiki/User_Port">C64’s user port</a> to a <a href="https://www.raspberrypi.org/">Raspberry Pi</a>, and design a protocol to transfer data from one to the other. The C64 side will have to include a small assembly program to do this, whilst the Pi will be running a small C program.</p>
<p>The Pi is notified of a new program to send by monitoring a specific directory. The main machine, post-assembly, augments and sends the output file over <a href="https://en.wikipedia.org/wiki/Secure_copy">SCP</a> to the Pi using a small F# program.</p>
<div class="figure"><img src="http://www.pinksquirrellabs.com/img/prog/high-level.png" alt="" />
<p class="caption"></p></div>
<h2 id="protocol-design">Protocol Design</h2>
<p>The C64 has a user port which is designed for us to connect our own circuits to. You must be careful, of course! You can easily damage the machine if you are not careful, and I don’t know if my user port even works. The usable part of the port is essentially 10 pins – 8 data pins that form a register you can read at <code>$dd01</code>, and two pins you can use for handshaking with another device. Of these two pins, one is special - the <code>FLAG</code> pin. This pin is input only, and detects negative edges. Upon seeing a logic transition from HIGH to LOW, it sets a bit in the port’s interrupt control register at <code>$dd0d</code>. This bit is cleared when you read the register. If you wish, you can also have it raise a non-maskable interrupt (NMI) enabling you to program with it asynchronously.</p>
<div class="figure"><img src="http://www.pinksquirrellabs.com/img/prog/userport.gif" alt="" />
<p class="caption"></p></div>
<p>The C64’s KERNAL has some routines that use this port to enable RS–232 communication. RS–232 is horribly slow however, being a serial protocol it transmits only a single bit at a time, with the protocol orchestration overhead on top of that. For my purposes, I want something much faster and less general. It doesn’t need to be bullet-proof since it is only for my own use. I would like to use all 8 lines to transfer a whole byte at a time as a parrallel interface.</p>
<p>Of course, the Raspberry Pi is ridiculously faster than the C64, so the top speed will be largely down to how fast the 6502 can process the incoming data. To that end, the C64 side of the programmer aims to do the least amount of work as possible, with hardly any logic and only copying of data.</p>
<h3 id="low-level">Low Level</h3>
<p>The low-level handshaking and transmission details are as follows</p>
<ul>
<li>The Pi signals to the C64 there is a new byte available by cycling the <code>FLAG</code> line from HIGH to LOW and back again, after writing the bits to the 8 lines.</li>
<li>The C64 loads the data and puts it somewhere, and then inverts the other handshaking line <code>PA2</code></li>
<li>The Pi notices the C64 has finished with the data by polling <code>PA2</code>, and then sends the next byte.</li></ul>
<h3 id="high-level">High Level</h3>
<p>The 6502 is very good at copying whole pages of data (256 bytes) since it can use its indexed addressing modes to whip through 256 bytes and easily check when it has finished. The data being sent, however, could be destined for any memory location and be of any length. Therefore, to simplify the job for the C64, we will send it some control bytes about any non-perfectly aligned data as a header, which will be the job of the C program on the Pi to compute.</p>
<ul>
<li>1 : low byte of the location to start executing once programming has finished</li>
<li>2 : high byte</li>
<li>3 : low byte of the location to being copying data to</li>
<li>4 : high byte</li>
<li>5 : total amount of full pages of data to copy</li>
<li>6 : number of leading bytes that don’t fill a page</li>
<li>7 : number of trailing bytes that don’t fill a page</li></ul>
<p>The idea then is for the assembly program to:</p>
<ul>
<li>disable interrupts</li>
<li>create a pointer to the start location</li>
<li>copy the amount of leading bytes</li>
<li>repeatedly copy the full pages</li>
<li>copy the trailing bytes</li>
<li>enable interrupts, splat the stack</li>
<li>jump to the execution point</li></ul>
<p>We will see how some of this is implemented later.</p>
<h2 id="circuit-design">Circuit Design</h2>
<p>The C64 is of course an old device released back in 1983 (when I was born!) and as such it uses +/– 5v for its logic lines. The Pi is newer and uses the more modern +3.3v for its logic. This means they cannot directly communicate - whilst you can get away with sending 3.3v to a 5v pin, you shouldn’t really, and sending 5v to a 3.3v pin is a definite no!</p>
<p>To solve this problem you’d typically use a <a href="https://www.adafruit.com/product/735">level shifter</a>, however, I couldn’t find one in my stuff so instead I decided to solve the problem in another way, by using a transistor switching circuit.</p>
<p>One of the transistor’s primary features is that is able to switch on a larger current / voltage using a very small one. We can use this feature to solve our problem. However, in its most basic configuration, this circuit is also a NOT gate - it inverts the input.</p>
<div class="figure"><img src="http://www.pinksquirrellabs.com/img/prog/transistor-1.png" alt="" />
<p class="caption"></p></div>
<p>We have 9 of these in total, one for each data pin and one for the <code>FLAG</code> pin. The transistor is switched on using the 3.3v logic, and it ouputs the opposite logic in 5v to the C64.</p>
<div class="figure"><img src="http://www.pinksquirrellabs.com/img/prog/transistor-2.png" alt="" />
<p class="caption"></p></div>
<p>And one of these for the <code>PA2</code> handshaking pin from the C64 to the Pi. It is the same, except it is switched on from the C64’s 5v logic and outputs 3.3v.</p>
<p>I have kept these diagrams high level since this post is not about the electronics really. I did extensive testing on each part of the circuit and the logic outputs from both devices before putting it all together. The picture below is the Pi’s logic pins driving the transistors and LEDs using a small C program, acting as a binary counter.</p>
<div class="figure"><img src="http://www.pinksquirrellabs.com/img/prog/programmer2.jpg" alt="" />
<p class="caption"></p></div>
<p>Of course, since the circuits invert the logic, the received bytes will be incorrect. We can remedy this by either designing a more complex circuit, or changing how the data is sent / received. It makes sense in this instance to modify how the data is sent since I don’t want to make the circuit more complex and I don’t want the 6502 program to do anything it doesn’t have to.</p>
<h2 id="c-program">C Program</h2>
<p>The C program’s job is to monitor a directory, and when it sees a new file, send it over the wire. It expects the first four bytes of the file will be the post-programming execution address and address to start writing the data as per the protocol section above (more on how these end up in the file in the final section)</p>
<p>Some of the C program is quite boring, so we’ll look at a couple of the more interesting parts. The library being used here is <a href="https://www.airspayce.com/mikem/bcm2835/">bcm2835</a> to control the GPIO pins on the Pi.</p>
<div class="brush: C">
<table class="highlighttable">
<tbody>
<tr>
<td class="linenos">
<div class="linenodiv">
<pre> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28</pre></div></td>
<td class="code">
<div class="highlight">
<pre><span></span><span class="kt">void</span> <span class="nf">send_byte</span><span class="p">(</span><span class="kt">char</span> <span class="n">b</span><span class="p">)</span>
<span class="p">{</span>
<span class="c1">// write inverted bits</span>
<span class="n">bcm2835_gpio_write</span><span class="p">(</span><span class="n">PB0</span><span class="p">,</span> <span class="p">(</span><span class="n">b</span> <span class="o">&</span> <span class="mh">0x1</span><span class="p">)</span> <span class="o">^</span> <span class="mh">0x1</span><span class="p">);</span>
<span class="n">bcm2835_gpio_write</span><span class="p">(</span><span class="n">PB1</span><span class="p">,</span> <span class="p">((</span><span class="n">b</span> <span class="o">>></span> <span class="mi">1</span><span class="p">)</span> <span class="o">&</span> <span class="mh">0x1</span><span class="p">)</span> <span class="o">^</span> <span class="mh">0x1</span><span class="p">);</span>
<span class="n">bcm2835_gpio_write</span><span class="p">(</span><span class="n">PB2</span><span class="p">,</span> <span class="p">((</span><span class="n">b</span> <span class="o">>></span> <span class="mi">2</span><span class="p">)</span> <span class="o">&</span> <span class="mh">0x1</span><span class="p">)</span> <span class="o">^</span> <span class="mh">0x1</span><span class="p">);</span>
<span class="n">bcm2835_gpio_write</span><span class="p">(</span><span class="n">PB3</span><span class="p">,</span> <span class="p">((</span><span class="n">b</span> <span class="o">>></span> <span class="mi">3</span><span class="p">)</span> <span class="o">&</span> <span class="mh">0x1</span><span class="p">)</span> <span class="o">^</span> <span class="mh">0x1</span><span class="p">);</span>
<span class="n">bcm2835_gpio_write</span><span class="p">(</span><span class="n">PB4</span><span class="p">,</span> <span class="p">((</span><span class="n">b</span> <span class="o">>></span> <span class="mi">4</span><span class="p">)</span> <span class="o">&</span> <span class="mh">0x1</span><span class="p">)</span> <span class="o">^</span> <span class="mh">0x1</span><span class="p">);</span>
<span class="n">bcm2835_gpio_write</span><span class="p">(</span><span class="n">PB5</span><span class="p">,</span> <span class="p">((</span><span class="n">b</span> <span class="o">>></span> <span class="mi">5</span><span class="p">)</span> <span class="o">&</span> <span class="mh">0x1</span><span class="p">)</span> <span class="o">^</span> <span class="mh">0x1</span><span class="p">);</span>
<span class="n">bcm2835_gpio_write</span><span class="p">(</span><span class="n">PB6</span><span class="p">,</span> <span class="p">((</span><span class="n">b</span> <span class="o">>></span> <span class="mi">6</span><span class="p">)</span> <span class="o">&</span> <span class="mh">0x1</span><span class="p">)</span> <span class="o">^</span> <span class="mh">0x1</span><span class="p">);</span>
<span class="n">bcm2835_gpio_write</span><span class="p">(</span><span class="n">PB7</span><span class="p">,</span> <span class="p">((</span><span class="n">b</span> <span class="o">>></span> <span class="mi">7</span><span class="p">)</span> <span class="o">&</span> <span class="mh">0x1</span><span class="p">)</span> <span class="o">^</span> <span class="mh">0x1</span><span class="p">);</span>
<span class="c1">// c64 detects negative edge and sets an interrupt bit</span>
<span class="c1">// get the current c64 output flag first</span>
<span class="kt">char</span> <span class="n">pa2</span> <span class="o">=</span> <span class="n">bcm2835_gpio_lev</span><span class="p">(</span><span class="n">PA2</span><span class="p">);</span>
<span class="n">bcm2835_gpio_write</span><span class="p">(</span><span class="n">FLAG2</span><span class="p">,</span> <span class="n">HIGH</span><span class="p">);</span> <span class="c1">// cycle the line low to trigger interrup</span>
<span class="n">bcm2835_gpio_write</span><span class="p">(</span><span class="n">FLAG2</span><span class="p">,</span> <span class="n">LOW</span><span class="p">);</span> <span class="c1">// reset again</span>
<span class="c1">// now wait for the c64 to change its output flag</span>
<span class="k">while</span><span class="p">(</span><span class="n">bcm2835_gpio_lev</span><span class="p">(</span><span class="n">PA2</span><span class="p">)</span> <span class="o">==</span> <span class="n">pa2</span><span class="p">)</span>
<span class="p">{</span>
<span class="p">}</span>
<span class="k">return</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>
</td></tr></tbody></table>
</div>
<p>Here we implement the low level details of the protocol, loading each bit of the byte onto the data lines, inverted so the circuit ends up outputting the correct value. Then it switches the <code>FLAG</code> line and waits for the C64 to respond by inverting <code>PA2</code>, indicating that it has taken the data (ack).</p>
<div class="brush: C">
<table class="highlighttable">
<tbody>
<tr>
<td class="linenos">
<div class="linenodiv">
<pre> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46</pre></div></td>
<td class="code">
<div class="highlight">
<pre><span></span> <span class="kt">FILE</span> <span class="o">*</span><span class="n">fp</span><span class="p">;</span>
<span class="n">fp</span> <span class="o">=</span> <span class="n">fopen</span><span class="p">(</span><span class="n">fn</span><span class="p">,</span><span class="s">"r"</span><span class="p">);</span>
<span class="n">fseek</span><span class="p">(</span><span class="n">fp</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="n">SEEK_END</span><span class="p">);</span>
<span class="kt">int</span> <span class="n">file_length</span> <span class="o">=</span> <span class="n">ftell</span><span class="p">(</span><span class="n">fp</span><span class="p">);</span>
<span class="kt">int</span> <span class="n">data_length</span> <span class="o">=</span> <span class="n">file_length</span> <span class="o">-</span> <span class="mi">4</span><span class="p">;</span>
<span class="kt">char</span><span class="o">*</span> <span class="n">data</span> <span class="o">=</span> <span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="p">)</span> <span class="n">malloc</span><span class="p">(</span><span class="n">data_length</span><span class="p">);</span>
<span class="n">rewind</span><span class="p">(</span><span class="n">fp</span><span class="p">);</span>
<span class="kt">unsigned</span> <span class="kt">char</span> <span class="n">start_lo</span> <span class="o">=</span> <span class="n">fgetc</span><span class="p">(</span><span class="n">fp</span><span class="p">);</span>
<span class="kt">unsigned</span> <span class="kt">char</span> <span class="n">start_hi</span> <span class="o">=</span> <span class="n">fgetc</span><span class="p">(</span><span class="n">fp</span><span class="p">);</span>
<span class="kt">unsigned</span> <span class="kt">char</span> <span class="n">asm_lo</span> <span class="o">=</span> <span class="n">fgetc</span><span class="p">(</span><span class="n">fp</span><span class="p">);</span>
<span class="kt">unsigned</span> <span class="kt">char</span> <span class="n">asm_hi</span> <span class="o">=</span> <span class="n">fgetc</span><span class="p">(</span><span class="n">fp</span><span class="p">);</span>
<span class="n">fread</span><span class="p">(</span><span class="n">data</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="n">data_length</span><span class="p">,</span> <span class="n">fp</span><span class="p">);</span>
<span class="n">fclose</span><span class="p">(</span><span class="n">fp</span><span class="p">);</span>
<span class="kt">int</span> <span class="n">address</span> <span class="o">=</span> <span class="p">(</span><span class="n">asm_hi</span> <span class="o"><<</span> <span class="mi">8</span><span class="p">)</span> <span class="o">|</span> <span class="n">asm_lo</span><span class="p">;</span>
<span class="n">printf</span><span class="p">(</span><span class="s">"data load complete. copy address at $%04X.</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">address</span><span class="p">);</span>
<span class="c1">// work out how many bytes are on the first page</span>
<span class="kt">unsigned</span> <span class="kt">char</span> <span class="n">first_page_bytes</span> <span class="o">=</span> <span class="mi">256</span> <span class="o">-</span> <span class="p">(</span><span class="n">address</span> <span class="o">%</span> <span class="mi">256</span><span class="p">);</span>
<span class="kt">int</span> <span class="n">remaining_bytes</span> <span class="o">=</span> <span class="n">data_length</span> <span class="o">-</span> <span class="n">first_page_bytes</span><span class="p">;</span>
<span class="c1">// see how many full pages we can fit in</span>
<span class="kt">int</span> <span class="n">full_pages</span> <span class="o">=</span> <span class="n">remaining_bytes</span> <span class="o">/</span> <span class="mi">256</span><span class="p">;</span>
<span class="c1">// and any final stragglers</span>
<span class="kt">int</span> <span class="n">last_page_bytes</span> <span class="o">=</span> <span class="n">remaining_bytes</span> <span class="o">%</span> <span class="mi">256</span><span class="p">;</span>
<span class="c1">//now we can send to the C64!</span>
<span class="c1">//first send the control data.</span>
<span class="n">printf</span><span class="p">(</span><span class="s">"sending control headers..</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
<span class="n">send_byte</span><span class="p">(</span><span class="n">start_lo</span><span class="p">);</span>
<span class="n">send_byte</span><span class="p">(</span><span class="n">start_hi</span><span class="p">);</span>
<span class="n">send_byte</span><span class="p">(</span><span class="n">asm_lo</span><span class="p">);</span>
<span class="n">send_byte</span><span class="p">(</span><span class="n">asm_hi</span><span class="p">);</span>
<span class="n">send_byte</span><span class="p">(</span><span class="n">full_pages</span><span class="p">);</span>
<span class="n">send_byte</span><span class="p">(</span><span class="n">first_page_bytes</span><span class="p">);</span>
<span class="n">send_byte</span><span class="p">(</span><span class="n">last_page_bytes</span><span class="p">);</span>
<span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o"><</span> <span class="n">data_length</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">send_byte</span><span class="p">(</span><span class="n">data</span><span class="p">[</span><span class="n">i</span><span class="p">]);</span>
<span class="p">}</span>
<span class="n">free</span><span class="p">(</span><span class="n">data</span><span class="p">);</span>
<span class="n">remove</span><span class="p">(</span><span class="n">fn</span><span class="p">);</span>
</pre></div>
</td></tr></tbody></table>
</div>
<p>In this code we extract the first 4 bytes from the file then read the rest into an array. Then we can work out any leading / trailing bytes as per the protocol description, and finally proceed to send the control header followed by the actual data. (this is not the actual code, but close enough - I changed it around to fit in the post)</p>
<h2 id="6502-program">6502 Program</h2>
<p>For the C64 side, we want the program to be as small as possible. Obviously, it needs to fit somewhere inside your program, where you can call it every now and then to see if a new program has arrived. The location it lives should ideally remain static as your program changes, since the programmer will overwrite itself and it had better be in exactly the same place whilst it is doing it!</p>
<p>For now, the perfect spot for this is the area that follows the BASIC program that is executed when the machine first boots. A common machine language trick is to put your own short basic program there, its purpose is to transfer control to your actual program so you don’t have to type in <code>sys 4096</code> or similar in order to execute your code. This will also become important in the next section with the F# program.</p>
<p>BASIC attempts to execute the program it tries to find at <code>$0801</code>. It expects the program to be in a special format which indicates some stuff to do with line numbers, and the PETSCII (Commodore character set - not the same as ASCII!) text of the BASIC source code to be interpreted. Some details will be glossed over here:</p>
<div class="brush: ca65">
<table class="highlighttable">
<tbody>
<tr>
<td class="linenos">
<div class="linenodiv">
<pre>1
2
3
4
5
6
7
8</pre></div></td>
<td class="code">
<div class="highlight">
<pre><span></span><span class="o">*=</span> <span class="mh">$0801</span>
<span class="c1">;autostart</span>
<span class="p">(</span><span class="n">data</span> <span class="mh">$0b</span> <span class="mh">$08</span> <span class="mh">$01</span> <span class="mh">$00</span> <span class="mh">$9E</span> <span class="mh">$34</span> <span class="mh">$30</span> <span class="mh">$39</span> <span class="mh">$36</span> <span class="mh">$00</span> <span class="mh">$00</span> <span class="mh">$00</span><span class="p">)</span>
<span class="o">*=</span> <span class="mh">$1000</span> <span class="c1">; main program</span>
<span class="c1">; code here ...</span>
</pre></div>
</td></tr></tbody></table>
</div>
<p>This is written in my Racket based assembler, <a href="http://docs.racket-lang.org/asi64/index.html">Asi64</a>. It is admittedly very cryptic, being simply a bunch of bytes. The first few are to do with the line numbers. <code>$9E</code> is the code for the <code>sys</code> instruction, followed by four bytes which represent in decimal, as PETSCII characters, the address to jump to. In this case, <code>$34 $30 $39 $36</code> corresponds to <code>4096</code> in decimal (subtract $30 from each character) which in turn is <code>$1000</code> in hex. Finally, the three <code>$00</code> bytes tell BASIC that the line has ended.</p>
<p>Of course, we can write a nice helper in Asi64 to help us do this like you can in <a href="http://theweb.dk/KickAssembler/Main.html#frontpage">KickAssembler</a></p>
<div class="brush: ca65">
<table class="highlighttable">
<tbody>
<tr>
<td class="linenos">
<div class="linenodiv">
<pre>1
2
3
4
5</pre></div></td>
<td class="code">
<div class="highlight">
<pre><span></span><span class="p">(</span><span class="n">basic</span><span class="o">-</span><span class="n">upstart</span> <span class="mh">$1000</span><span class="p">)</span>
<span class="o">*=</span> <span class="mh">$1000</span>
<span class="c1">; code here ...</span>
</pre></div>
</td></tr></tbody></table>
</div>
<p>The area after the basic program is where we will stuff the remote programmer code. It should be as small as possible, but as long as it fits within the rest of the <code>$0800</code> page we should be fine. I have not optimised it for space yet, what I present below is the first thing I got to work properly!</p>
<div class="brush: ca65">
<table class="highlighttable">
<tbody>
<tr>
<td class="linenos">
<div class="linenodiv">
<pre> 1
2
3
4
5
6
7
8
9
10</pre></div></td>
<td class="code">
<div class="highlight">
<pre><span></span><span class="p">:</span><span class="n">programmer</span><span class="o">-</span><span class="n">check</span>
<span class="c1">;interrupt will be set on a negative transition</span>
<span class="c1">;indicating the pi has put the first byte of a program</span>
<span class="c1">;on the wire</span>
<span class="k">lda</span> <span class="mh">$dd0d</span>
<span class="k">and</span> <span class="n">@</span><span class="mb">%0001</span><span class="n">_0000</span>
<span class="c1">;if this bit is set then</span>
<span class="c1">;jump. reading this also clears it.</span>
<span class="k">bne</span> <span class="n">receive</span><span class="o">-</span><span class="n">program</span><span class="o">+</span>
<span class="k">rts</span>
</pre></div>
</td></tr></tbody></table>
</div>
<p>This function checks the interrupt register, and returns if it has not been set. Using <a href="http://docs.racket-lang.org/asi64/index.html#%28part._.Code_.Diagnostics%29">Asi64’s diagnostics</a> reveals this code takes 14 cycles if the branch is not taken, so you can comfortably fit a call into this function somewhere in your program, perhaps once a frame.</p>
<div class="brush: ca65">
<table class="highlighttable">
<tbody>
<tr>
<td class="linenos">
<div class="linenodiv">
<pre> 1
2
3
4
5
6
7
8
9
10
11</pre></div></td>
<td class="code">
<div class="highlight">
<pre><span></span><span class="p">:</span><span class="n">wait</span>
<span class="c1">;toggle pa2 to let the pi know we are done</span>
<span class="k">lda</span> <span class="mh">$dd00</span>
<span class="k">eor</span> <span class="n">@</span><span class="mb">%0000</span><span class="n">_0100</span>
<span class="k">sta</span> <span class="mh">$dd00</span>
<span class="c1">;wait for pi to send a new byte</span>
<span class="p">:</span><span class="n">inner</span> <span class="k">lda</span> <span class="mh">$dd0d</span>
<span class="k">and</span> <span class="n">@</span><span class="mb">%0001</span><span class="n">_0000</span>
<span class="k">beq</span> <span class="n">inner</span><span class="o">-</span>
<span class="k">rts</span>
</pre></div>
</td></tr></tbody></table>
</div>
<p>Next up is this function that waits for a new byte to arrive. First, it toggles the <code>PA2</code> pin indcitating to the Pi that the last byte was been received, and then it sits polling the interrupt register waiting for the new byte to arrive.</p>
<div class="brush: ca65">
<table class="highlighttable">
<tbody>
<tr>
<td class="linenos">
<div class="linenodiv">
<pre> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36</pre></div></td>
<td class="code">
<div class="highlight">
<pre><span></span><span class="p">:</span><span class="n">receive</span><span class="o">-</span><span class="n">program</span>
<span class="c1">;some zero page addresses</span>
<span class="n">start</span><span class="o">-</span><span class="n">lo</span> <span class="o">=</span> <span class="mh">$40</span>
<span class="n">start</span><span class="o">-</span><span class="n">hi</span> <span class="o">=</span> <span class="mh">$41</span>
<span class="n">total</span><span class="o">-</span><span class="n">pages</span> <span class="o">=</span> <span class="mh">$43</span>
<span class="n">first</span><span class="o">-</span><span class="n">page</span><span class="o">-</span><span class="n">bytes</span> <span class="o">=</span> <span class="mh">$44</span>
<span class="n">last</span><span class="o">-</span><span class="n">page</span><span class="o">-</span><span class="n">bytes</span> <span class="o">=</span> <span class="mh">$45</span>
<span class="n">data</span><span class="o">-</span><span class="n">ptr</span><span class="o">-</span><span class="n">lo</span> <span class="o">=</span> <span class="mh">$46</span>
<span class="n">data</span><span class="o">-</span><span class="n">ptr</span><span class="o">-</span><span class="n">hi</span> <span class="o">=</span> <span class="mh">$47</span>
<span class="c1">;disable interrupts whilst loading </span>
<span class="k">cli</span>
<span class="c1">;read in the control bytes,</span>
<span class="c1">;todo: write these as an indexed loop</span>
<span class="c1">;to save space</span>
<span class="k">lda</span> <span class="mh">$dd01</span>
<span class="k">sta</span> <span class="n">start</span><span class="o">-</span><span class="n">lo</span>
<span class="k">jsr</span> <span class="n">wait</span><span class="o">-</span>
<span class="k">lda</span> <span class="mh">$dd01</span>
<span class="k">sta</span> <span class="n">start</span><span class="o">-</span><span class="n">hi</span>
<span class="k">jsr</span> <span class="n">wait</span><span class="o">-</span>
<span class="k">lda</span> <span class="mh">$dd01</span>
<span class="k">sta</span> <span class="n">data</span><span class="o">-</span><span class="n">ptr</span><span class="o">-</span><span class="n">lo</span>
<span class="k">lda</span> <span class="mh">$dd01</span>
<span class="k">sta</span> <span class="n">data</span><span class="o">-</span><span class="n">ptr</span><span class="o">-</span><span class="n">hi</span>
<span class="k">lda</span> <span class="mh">$dd01</span>
<span class="k">sta</span> <span class="n">total</span><span class="o">-</span><span class="n">pages</span>
<span class="k">jsr</span> <span class="n">wait</span><span class="o">-</span>
<span class="k">lda</span> <span class="mh">$dd01</span>
<span class="k">sta</span> <span class="n">first</span><span class="o">-</span><span class="n">page</span><span class="o">-</span><span class="n">bytes</span>
<span class="k">jsr</span> <span class="n">wait</span><span class="o">-</span>
<span class="k">lda</span> <span class="mh">$dd01</span>
<span class="k">sta</span> <span class="n">last</span><span class="o">-</span><span class="n">page</span><span class="o">-</span><span class="n">bytes</span>
</pre></div>
</td></tr></tbody></table>
</div>
<p>This first section reads in the control bytes from the header and stores them in the zero-page. Notably, the <code>data-ptr-lo</code> and <code>data-ptr-high</code> are set to the first address where we should copy data, and it is this pointer that will be manipulated throughout the copy. Notice here the call to <code>cli</code> disables interrupts. This is important, since we are taking over the machine to re-write the program, we don’t want the user’s interrupt code suddenly trying to execute in the middle of the data transfer!</p>
<div class="brush: ca65">
<table class="highlighttable">
<tbody>
<tr>
<td class="linenos">
<div class="linenodiv">
<pre> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21</pre></div></td>
<td class="code">
<div class="highlight">
<pre><span></span> <span class="c1">;read/write first page bytes</span>
<span class="k">ldx</span> <span class="n">@0</span>
<span class="k">ldy</span> <span class="n">@0</span>
<span class="k">lda</span> <span class="n">first</span><span class="o">-</span><span class="n">page</span><span class="o">-</span><span class="n">bytes</span> <span class="c1">;skip if zero</span>
<span class="k">beq</span> <span class="n">main</span><span class="o">+</span> <span class="c1">; </span>
<span class="c1">; read until end of page</span>
<span class="p">:</span><span class="n">next</span>
<span class="c1">;wait for and read the next byte</span>
<span class="k">jsr</span> <span class="n">wait</span><span class="o">-</span>
<span class="k">lda</span> <span class="mh">$dd01</span>
<span class="c1">;store it offset with the Y register</span>
<span class="k">sta</span> <span class="err">�</span> <span class="n">data</span><span class="o">-</span><span class="n">ptr</span><span class="o">-</span><span class="n">lo</span> <span class="n">y</span>
<span class="c1">;increase Y and check if we are done</span>
<span class="k">iny</span>
<span class="k">cpy</span> <span class="n">first</span><span class="o">-</span><span class="n">page</span><span class="o">-</span><span class="n">bytes</span>
<span class="k">bne</span> <span class="n">next</span><span class="o">-</span>
<span class="c1">;move to next page</span>
<span class="k">inc</span> <span class="n">data</span><span class="o">-</span><span class="n">ptr</span><span class="o">-</span><span class="n">hi</span>
<span class="k">lda</span> <span class="n">@0</span>
<span class="k">sta</span> <span class="n">data</span><span class="o">-</span><span class="n">ptr</span><span class="o">-</span><span class="n">lo</span>
</pre></div>
</td></tr></tbody></table>
</div>
<p>This section deals with copying the leading bytes, if there are any. It reads and stores each byte at the <code>data-ptr</code> pointer, offset by the Y register. The loop uses Y to count up until the target amount of bytes have been transferred. The 6502 is better at counting down since you don’t need an explicit compare instruction to check for zero, but it would have complicated the protocol too much for not a lot of gain, since this copies at most 255 bytes of data.</p>
<p>Once it has finished, we know we are at the end of the page, so <code>data-ptr-lo</code> is set to zero whilst <code>data-ptr-hi</code> is increased by one, leaving us at the start of the next page ready for the full pages of data.</p>
<div class="brush: ca65">
<table class="highlighttable">
<tbody>
<tr>
<td class="linenos">
<div class="linenodiv">
<pre> 1
2
3
4
5
6
7
8
9
10
11
12
13
14</pre></div></td>
<td class="code">
<div class="highlight">
<pre><span></span> <span class="p">:</span><span class="n">main</span>
<span class="k">ldy</span> <span class="n">@0</span>
<span class="k">ldx</span> <span class="n">total</span><span class="o">-</span><span class="n">pages</span>
<span class="k">beq</span> <span class="n">last</span><span class="o">+</span> <span class="c1">;skip if zero</span>
<span class="c1">;copy whole pages</span>
<span class="p">:</span><span class="n">loop</span>
<span class="k">jsr</span> <span class="n">wait</span><span class="o">-</span>
<span class="k">lda</span> <span class="mh">$dd01</span>
<span class="k">sta</span> <span class="err">�</span> <span class="n">data</span><span class="o">-</span><span class="n">ptr</span><span class="o">-</span><span class="n">lo</span> <span class="n">y</span>
<span class="k">iny</span>
<span class="k">bne</span> <span class="n">loop</span><span class="o">-</span>
<span class="k">inc</span> <span class="n">data</span><span class="o">-</span><span class="n">ptr</span><span class="o">-</span><span class="n">hi</span>
<span class="k">dex</span>
<span class="k">bne</span> <span class="n">loop</span><span class="o">-</span>
</pre></div>
</td></tr></tbody></table>
</div>
<p>The main loop for copying bytes uses the X register to count down how many pages we have left to copy, whilst the Y register is increased through 256 values until it overflows. When this happens, 1 is added to <code>data-ptr-hi</code> moving us to the next page. This process repeats until X reaches zero and the whole pages have been copied.</p>
<div class="brush: ca65">
<table class="highlighttable">
<tbody>
<tr>
<td class="linenos">
<div class="linenodiv">
<pre> 1
2
3
4
5
6
7
8
9
10</pre></div></td>
<td class="code">
<div class="highlight">
<pre><span></span> <span class="p">:</span><span class="n">last</span>
<span class="k">lda</span> <span class="n">last</span><span class="o">-</span><span class="n">page</span><span class="o">-</span><span class="n">bytes</span>
<span class="k">beq</span> <span class="n">done</span><span class="o">+</span>
<span class="p">:</span><span class="n">loop</span>
<span class="k">jsr</span> <span class="n">wait</span><span class="o">-</span>
<span class="k">lda</span> <span class="mh">$dd01</span>
<span class="k">sta</span> <span class="err">�</span> <span class="n">data</span><span class="o">-</span><span class="n">ptr</span><span class="o">-</span><span class="n">lo</span> <span class="n">y</span>
<span class="k">iny</span>
<span class="k">cpy</span> <span class="n">last</span><span class="o">-</span><span class="n">page</span><span class="o">-</span><span class="n">bytes</span>
<span class="k">bne</span> <span class="n">loop</span><span class="o">-</span>
</pre></div>
</td></tr></tbody></table>
</div>
<p>The final loop copies any trailing bytes and is very similar to the first loop.</p>
<div class="brush: ca65">
<table class="highlighttable">
<tbody>
<tr>
<td class="linenos">
<div class="linenodiv">
<pre> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21</pre></div></td>
<td class="code">
<div class="highlight">
<pre><span></span> <span class="p">:</span><span class="n">done</span>
<span class="c1">;toggle pa2 to let the pi know we are done</span>
<span class="k">lda</span> <span class="mh">$dd00</span>
<span class="k">eor</span> <span class="n">@</span><span class="mb">%0000</span><span class="n">_0100</span>
<span class="k">sta</span> <span class="mh">$dd00</span>
<span class="k">ldx</span> <span class="n">@$ff</span>
<span class="c1">;delay to let the pin settle </span>
<span class="p">:</span><span class="n">delay</span>
<span class="k">dex</span>
<span class="k">bne</span> <span class="n">delay</span><span class="o">-</span>
<span class="k">ldx</span> <span class="n">@$ff</span>
<span class="p">:</span><span class="n">delay</span>
<span class="k">dex</span>
<span class="k">bne</span> <span class="n">delay</span><span class="o">-</span>
<span class="c1">;splat stack</span>
<span class="k">ldx</span> <span class="n">@$ff</span>
<span class="k">txs</span>
<span class="c1">;re-enable interrupts</span>
<span class="k">sei</span>
<span class="c1">;transfer exection to start address</span>
<span class="k">jmp</span> <span class="err">�</span> <span class="n">start</span><span class="o">-</span><span class="n">lo</span>
</pre></div>
</td></tr></tbody></table>
</div>
<p>Now that all the data has been received, the final ceremony Ack’s the last byte that was received, then it delays a bunch of cycles to make sure the Pi sees the Ack before the new program begins. This was guesswork rather than science, the speed doesn’t really matter at this point.</p>
<p>The next part is very important. Since we don’t know where this code was called from and we want to start executing the new program “from scratch” we reset the machine’s stack pointer right back to <code>$ff</code> where it starts from. Then we switch the interrupts back on, and use the indirect jump instruction to transfer program execution to the new program.</p>
<p>The whole thing fits into about 170 bytes, which is not bad. With a little work it could probably be sqaushed into under half a page.</p>
<div class="brush: ca65">
<table class="highlighttable">
<tbody>
<tr>
<td class="linenos">
<div class="linenodiv">
<pre> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15</pre></div></td>
<td class="code">
<div class="highlight">
<pre><span></span> <span class="k">lda</span> <span class="n">@0</span>
<span class="k">sta</span> <span class="mh">$dd03</span> <span class="c1">;pin all inputs</span>
<span class="c1">;pa2 is an output</span>
<span class="k">lda</span> <span class="mh">$dd02</span>
<span class="k">ora</span> <span class="n">@</span><span class="mb">%0000</span><span class="n">_0100</span>
<span class="k">sta</span> <span class="mh">$dd02</span>
<span class="c1">;pa2 starts HIGH (inverted)</span>
<span class="k">lda</span> <span class="mh">$dd00</span>
<span class="k">and</span> <span class="n">@</span><span class="mb">%1111</span><span class="n">_1011</span>
<span class="k">sta</span> <span class="mh">$dd00</span>
<span class="c1">;clear any pending int</span>
<span class="k">lda</span> <span class="mh">$dd0d</span>
</pre></div>
</td></tr></tbody></table>
</div>
<p>One last thing separate from the main program - this small piece of code must go at the start of your program somewhere, it does the boring job of setting up the user port pins properly and clearing any waiting interrupts, leaving the program ready to receive.</p>
<h2 id="f-program">F# Program</h2>
<p>Ideally, I’d have Asi64 automatically send the new program over SCP once it has finished assembling. However, I haven’t found a nice way of doing so with Racket yet, so for this initial prototype I instead decided to write a small F# program that will watch a directory for changes and copy the files as appropriate using <a href="https://github.com/sshnet/SSH.NET">SSH.NET</a></p>
<p>Of course, things are never quite that straight-forward. The assembler outputs the binary program in a format that the emulator and machine expect. In particular, the first two bytes of the file are the address in the computer where the data should begin. This correlates nicely to bytes 3 and 4 of our protocol headers. However, we are missing one part which is the execution address itself.</p>
<p>Since in this initial version, we know the programs will be using the BASIC upstart program, we can have a look through the binary, locate this code and extract from it the execution address, which can then be prepended to the file before it is sent to the other machine. This is not ideal but it is fine for this version of the project.</p>
<div class="brush: fsharp">
<table class="highlighttable">
<tbody>
<tr>
<td class="linenos">
<div class="linenodiv">
<pre> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53</pre></div></td>
<td class="code">
<div class="highlight">
<pre><span></span><span class="o">[<</span><span class="n">EntryPoint</span><span class="o">>]</span>
<span class="k">let</span> <span class="nv">main</span> <span class="n">argv</span> <span class="o">=</span>
<span class="n">printfn</span> <span class="s">"%A"</span> <span class="n">argv</span>
<span class="k">use</span> <span class="n">client</span> <span class="o">=</span> <span class="k">new</span> <span class="n">ScpClient</span><span class="o">(</span><span class="s">"192.168.0.20"</span><span class="o">,</span> <span class="s">"pi"</span><span class="o">,</span> <span class="s">"raspberry"</span><span class="o">)</span>
<span class="k">let</span> <span class="nv">sendFile</span> <span class="o">(</span><span class="n">file</span><span class="o">:</span><span class="n">FileInfo</span><span class="o">)</span> <span class="o">(</span><span class="n">stream</span><span class="o">:</span><span class="nn">System</span><span class="p">.</span><span class="nn">IO</span><span class="p">.</span><span class="n">MemoryStream</span><span class="o">)</span> <span class="o">=</span>
<span class="n">printfn</span> <span class="s">"sending file %s ..."</span> <span class="n">file</span><span class="o">.</span><span class="n">FullName</span>
<span class="n">client</span><span class="o">.</span><span class="n">Connect</span><span class="bp">()</span>
<span class="n">client</span><span class="o">.</span><span class="n">Upload</span><span class="o">(</span><span class="n">stream</span><span class="o">,</span> <span class="s">"/home/pi/projects/c64/waiting/"</span> <span class="o">+</span> <span class="n">file</span><span class="o">.</span><span class="n">Name</span><span class="o">)</span>
<span class="n">client</span><span class="o">.</span><span class="n">Disconnect</span><span class="bp">()</span>
<span class="k">let</span> <span class="nv">trySend</span> <span class="n">file</span> <span class="o">=</span>
<span class="k">let</span> <span class="nv">fi</span> <span class="o">=</span> <span class="n">FileInfo</span> <span class="n">file</span>
<span class="c1">// try and find the basic startup program that </span>
<span class="c1">// tells us where the execution point is</span>
<span class="nn">System</span><span class="p">.</span><span class="nn">Threading</span><span class="p">.</span><span class="nn">Thread</span><span class="p">.</span><span class="n">Sleep</span><span class="o">(</span><span class="mi">1000</span><span class="o">)</span>
<span class="k">let</span> <span class="nv">bytes</span> <span class="o">=</span> <span class="nn">File</span><span class="p">.</span><span class="n">ReadAllBytes</span> <span class="n">fi</span><span class="o">.</span><span class="n">FullName</span>
<span class="k">let</span> <span class="nv">address</span> <span class="o">=</span>
<span class="k">let</span> <span class="nv">rec</span> <span class="n">find</span> <span class="o">=</span> <span class="k">function</span>
<span class="o">|</span> <span class="mi">0</span><span class="n">xbuy</span> <span class="o">::</span> <span class="mi">0</span><span class="n">x8uy</span> <span class="o">::</span> <span class="mi">0</span><span class="n">x1uy</span> <span class="o">::</span> <span class="mi">0</span><span class="n">x0uy</span><span class="o">::</span> <span class="mi">0</span><span class="n">x9euy</span> <span class="o">::</span>
<span class="n">a</span> <span class="o">::</span> <span class="n">b</span> <span class="o">::</span> <span class="n">c</span> <span class="o">::</span> <span class="n">d</span> <span class="o">::</span> <span class="mi">0</span><span class="n">x0uy</span> <span class="o">::</span> <span class="mi">0</span><span class="n">x0uy</span> <span class="o">::</span> <span class="mi">0</span><span class="n">x0uy</span> <span class="o">::</span> <span class="o">_</span> <span class="o">-></span>
<span class="n">Some</span> <span class="o"><|</span>
<span class="nn">Int32</span><span class="p">.</span><span class="n">Parse</span><span class="o">(</span><span class="n">sprintf</span> <span class="s">"%i%i%i%i"</span>
<span class="o">(</span><span class="n">a</span> <span class="o">-</span> <span class="mi">0</span><span class="n">x30uy</span><span class="o">)</span> <span class="o">(</span><span class="n">b</span> <span class="o">-</span> <span class="mi">0</span><span class="n">x30uy</span><span class="o">)</span>
<span class="o">(</span><span class="n">c</span> <span class="o">-</span> <span class="mi">0</span><span class="n">x30uy</span><span class="o">)</span> <span class="o">(</span><span class="n">d</span> <span class="o">-</span> <span class="mi">0</span><span class="n">x30uy</span><span class="o">))</span>
<span class="o">|</span> <span class="mi">0</span><span class="n">xbuy</span> <span class="o">::</span> <span class="mi">0</span><span class="n">x8uy</span> <span class="o">::</span> <span class="mi">0</span><span class="n">x1uy</span> <span class="o">::</span> <span class="mi">0</span><span class="n">x0uy</span> <span class="o">::</span> <span class="mi">0</span><span class="n">x9euy</span> <span class="o">::</span>
<span class="n">a</span> <span class="o">::</span> <span class="n">b</span> <span class="o">::</span> <span class="n">c</span> <span class="o">::</span> <span class="n">d</span> <span class="o">::</span> <span class="n">e</span> <span class="o">::</span> <span class="mi">0</span><span class="n">x0uy</span> <span class="o">::</span> <span class="mi">0</span><span class="n">x0uy</span> <span class="o">::</span> <span class="mi">0</span><span class="n">x0uy</span> <span class="o">::</span> <span class="o">_</span> <span class="o">-></span>
<span class="n">Some</span> <span class="o"><|</span>
<span class="nn">Int32</span><span class="p">.</span><span class="n">Parse</span><span class="o">(</span><span class="n">sprintf</span> <span class="s">"%i%i%i%i%i"</span>
<span class="o">(</span><span class="n">a</span> <span class="o">-</span> <span class="mi">0</span><span class="n">x30uy</span><span class="o">)</span> <span class="o">(</span><span class="n">b</span> <span class="o">-</span> <span class="mi">0</span><span class="n">x30uy</span><span class="o">)</span>
<span class="o">(</span><span class="n">c</span> <span class="o">-</span> <span class="mi">0</span><span class="n">x30uy</span><span class="o">)</span> <span class="o">(</span><span class="n">d</span> <span class="o">-</span> <span class="mi">0</span><span class="n">x30uy</span><span class="o">)</span>
<span class="o">(</span><span class="n">e</span> <span class="o">-</span> <span class="mi">0</span><span class="n">x30uy</span><span class="o">))</span>
<span class="o">|</span> <span class="o">_</span> <span class="o">::</span> <span class="n">tail</span> <span class="o">-></span> <span class="n">find</span> <span class="n">tail</span>
<span class="o">|</span> <span class="o">_</span> <span class="o">-></span> <span class="n">None</span>
<span class="n">find</span> <span class="o">(</span><span class="nn">Array</span><span class="p">.</span><span class="n">toList</span> <span class="n">bytes</span><span class="o">)</span>
<span class="k">match</span> <span class="n">address</span> <span class="k">with</span>
<span class="o">|</span> <span class="n">Some</span> <span class="n">address</span> <span class="o">-></span>
<span class="k">let</span> <span class="nv">newBytes</span> <span class="o">=</span> <span class="nn">Array</span><span class="p">.</span><span class="n">append</span> <span class="c1">// little endian </span>
<span class="o">[|</span> <span class="kt">byte</span><span class="o">(</span><span class="n">address</span> <span class="o">&&&</span> <span class="mi">0</span><span class="n">xFF</span><span class="o">);</span>
<span class="kt">byte</span><span class="o">((</span><span class="n">address</span> <span class="o">>>></span> <span class="mi">0</span><span class="n">x8</span><span class="o">)</span> <span class="o">&&&</span> <span class="mi">0</span><span class="n">xFF</span><span class="o">);</span> <span class="o">|]</span>
<span class="n">bytes</span>
<span class="k">use</span> <span class="n">stream</span> <span class="o">=</span> <span class="k">new</span> <span class="n">MemoryStream</span><span class="o">(</span><span class="n">newBytes</span><span class="o">)</span>
<span class="n">sendFile</span> <span class="n">fi</span> <span class="n">stream</span>
<span class="o">|</span> <span class="n">None</span> <span class="o">-></span>
<span class="n">printfn</span> <span class="s">"could not find execution point for %s"</span> <span class="n">fi</span><span class="o">.</span><span class="n">FullName</span>
<span class="k">let</span> <span class="nv">watch</span> <span class="o">=</span> <span class="k">new</span> <span class="n">FileSystemWatcher</span><span class="o">(</span><span class="n">argv</span><span class="o">.[</span><span class="mi">0</span><span class="o">])</span>
<span class="n">watch</span><span class="o">.</span><span class="n">Created</span>
<span class="o">|></span> <span class="nn">Event</span><span class="p">.</span><span class="n">add</span><span class="o">(</span><span class="k">fun</span> <span class="n">x</span> <span class="o">-></span> <span class="k">if</span> <span class="n">x</span><span class="o">.</span><span class="n">FullPath</span><span class="o">.</span><span class="n">EndsWith</span> <span class="s">".prg"</span> <span class="k">then</span>
<span class="n">trySend</span> <span class="n">x</span><span class="o">.</span><span class="n">FullPath</span><span class="o">)</span>
<span class="n">watch</span><span class="o">.</span><span class="n">EnableRaisingEvents</span> <span class="o"><-</span> <span class="k">true</span>
<span class="k">while</span> <span class="k">true</span> <span class="k">do</span>
<span class="nn">System</span><span class="p">.</span><span class="nn">Threading</span><span class="p">.</span><span class="nn">Thread</span><span class="p">.</span><span class="n">Sleep</span><span class="o">(</span><span class="mi">1000</span><span class="o">)</span>
</pre></div>
</td></tr></tbody></table>
</div>
<p>In this not-very-nice F# code, a <code>FileSystemWatcher</code> is used to raise events indicating files have changed in the directory that is passed as a command line parameter. The code then scans through the binary data attempting to find the BASIC program, where it extracts the execution address, appends it to the original bytes litte-endian style and finally sends the data across to the Pi via SCP.</p>
<h2 id="final-thoughts">Final Thoughts</h2>
<p>Measuring this first version on my scope reveals the <code>PA2</code> pin transitioning at about 50 microseconds, yielding a transfer rate of about 20khz, or almost 20kb of data per second, which is not too bad at all. It is very cool to use the laptop from anywhere, assemble some new code and see it run automatically on the C64 across the room! Whilst this version is designed to overwrite an entire program, the protocol has no such limitations and will copy some bytes to any location you like. It is not hard to imagine that with a little work you could setup a REPL style system for assembler code, allowing you to send and execute small snippets on the real machine.</p>
<p>The next step is to take the hardware and make a more permanent circuit with it instead of it being on a breadboard, so you can simply plug it into a C64 and Pi running the correct software.</p>C64 Macro State Machineurn:http-www-pinksquirrellabs-com:-blog-2018-10-05-c64-macro-state-machine2018-10-05T10:14:05Z2018-10-05T10:14:05Zpezi
<p>In this post we will see how <a href="http://www.pinksquirrellabs.com/blog/2017/05/30/asi64/">asi64’s</a> (<a href="[https://racket-lang.org/">Racket’s</a>) macro system can massively reduce the amount of 6502 assembly code you have to write, beyond what a typical macro assembler can achieve.</p>
<!-- more-->
<h2 id="state-machines">State Machines</h2>
<p>I am currently writing my first little game for the C64. In it, the player’s sprite has fairly complex movement behaviour which is represented by a state machine that has no less than 13 different states. In order to transition between the states, the player uses some combination of joystick controls, or something outside such as collision detection forces a state change.</p>
<p>In this post we will concentrate on state changes from the joystick. Programming these state machines can be tricky due to the amount of different possible transitions from one state to another and the priority in which they are checked. To show this we will look at a reduced and simplified view using 3 of the 13 states and the interactions between them.</p>
<div class="brush: racket">
<table class="highlighttable">
<tbody>
<tr>
<td class="linenos">
<div class="linenodiv">
<pre> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17</pre></div></td>
<td class="code">
<div class="highlight">
<pre><span></span><span class="c1">;some constants</span>
<span class="p">{</span>
<span class="c1">; joy masks</span>
<span class="n">joy-up</span> <span class="nb"><a href="http://docs.racket-lang.org/reference/generic-numbers.html#(def._((quote._~23~25kernel)._~3d))" style="color: inherit">=</a></span> <span class="n">%00000001</span>
<span class="n">joy-down</span> <span class="nb"><a href="http://docs.racket-lang.org/reference/generic-numbers.html#(def._((quote._~23~25kernel)._~3d))" style="color: inherit">=</a></span> <span class="n">%00000010</span>
<span class="n">joy-left</span> <span class="nb"><a href="http://docs.racket-lang.org/reference/generic-numbers.html#(def._((quote._~23~25kernel)._~3d))" style="color: inherit">=</a></span> <span class="n">%00000100</span>
<span class="n">joy-right</span> <span class="nb"><a href="http://docs.racket-lang.org/reference/generic-numbers.html#(def._((quote._~23~25kernel)._~3d))" style="color: inherit">=</a></span> <span class="n">%00001000</span>
<span class="n">joy-fire</span> <span class="nb"><a href="http://docs.racket-lang.org/reference/generic-numbers.html#(def._((quote._~23~25kernel)._~3d))" style="color: inherit">=</a></span> <span class="n">%00010000</span>
<span class="c1">;machine states</span>
<span class="n">state-standing</span> <span class="nb"><a href="http://docs.racket-lang.org/reference/generic-numbers.html#(def._((quote._~23~25kernel)._~3d))" style="color: inherit">=</a></span> <span class="n">$0</span>
<span class="n">state-walking-right</span> <span class="nb"><a href="http://docs.racket-lang.org/reference/generic-numbers.html#(def._((quote._~23~25kernel)._~3d))" style="color: inherit">=</a></span> <span class="n">$1</span>
<span class="n">state-crouching</span> <span class="nb"><a href="http://docs.racket-lang.org/reference/generic-numbers.html#(def._((quote._~23~25kernel)._~3d))" style="color: inherit">=</a></span> <span class="n">$2</span>
<span class="c1">; variables</span>
<span class="n">current-state</span> <span class="nb"><a href="http://docs.racket-lang.org/reference/generic-numbers.html#(def._((quote._~23~25kernel)._~3d))" style="color: inherit">=</a></span> <span class="n">$f0</span>
<span class="p">}</span>
</pre></div>
</td></tr></tbody></table>
</div>
<p>The above code defines some constants for the three different states, a location to store the current state, and some masks used to detect which buttons on the joysticks are pressed when reading the joystick register.</p>
<p>The states that are defined represent the player standing still, walking to the right, and crouching. A graph of these transitions looks like this :</p>
<div class="figure"><img src="http://www.pinksquirrellabs.com/img/asi/state-graph.png" alt="" />
<p class="caption"></p></div>
<p>Even in this simple example, complexity rears its head. Notice that you cannot transition from walking right into a crouch, since I don’t want the player to enter that state accidentally as they are walking along if they happen to pull the joystick down and right at the same time. Additionally, there has to be some inverse logic for button presses to make some transitions, for example, when walking right, NOT holding right puts you back into the standing state. You can imagine with 13 states this can start to get very complex.</p>
<p>Programming this in 6502 asm is not particularly difficult, it’s just long, boring and very repetitive which in turns makes it a chore to change and maintain (more on the ineffeciency of this approach in the closing thoughts…) Here’s an example for the standing state :</p>
<div class="brush: ca65">
<table class="highlighttable">
<tbody>
<tr>
<td class="linenos">
<div class="linenodiv">
<pre> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23</pre></div></td>
<td class="code">
<div class="highlight">
<pre><span></span><span class="p">:</span><span class="n">update</span><span class="o">-</span><span class="n">machine</span>
<span class="k">ldy</span> <span class="n">current</span><span class="o">-</span><span class="n">state</span> <span class="c1">; load current state</span>
<span class="k">cpy</span> <span class="n">@state</span><span class="o">-</span><span class="n">standing</span> <span class="c1">; is it the standing state?</span>
<span class="k">bne</span> <span class="n">next</span><span class="o">-</span><span class="n">state</span><span class="o">+</span> <span class="c1">; if not then go to the next check...</span>
<span class="k">lda</span> <span class="mh">$dc00</span> <span class="c1">; load the joystick state</span>
<span class="k">tax</span> <span class="c1">; preserve it in X so we can look at it again later..</span>
<span class="k">and</span> <span class="n">@joy</span><span class="o">-</span><span class="n">right</span> <span class="c1">; test joystick (1 is not pressed, 0 is pressed)</span>
<span class="k">bne</span> <span class="n">skip</span><span class="o">+</span> <span class="c1">; if not, move to next joystick check</span>
<span class="k">ldx</span> <span class="n">@state</span><span class="o">-</span><span class="n">walking</span><span class="o">-</span><span class="n">right</span>
<span class="k">jsr</span> <span class="n">change</span><span class="o">-</span><span class="n">state</span><span class="o">-</span> <span class="c1">; call the function that changes the state </span>
<span class="k">rts</span> <span class="c1">; early exit from function</span>
<span class="p">:</span><span class="n">skip</span>
<span class="k">txa</span> <span class="c1">; reload the joy data</span>
<span class="c1">; repeat all the above the for next direction</span>
<span class="k">and</span> <span class="n">@joy</span><span class="o">-</span><span class="n">down</span>
<span class="k">bne</span> <span class="n">skip</span><span class="o">+</span>
<span class="k">ldx</span> <span class="n">@tstate</span><span class="o">-</span><span class="n">crouching</span>
<span class="k">jsr</span> <span class="n">change</span><span class="o">-</span><span class="n">state</span><span class="o">-</span>
<span class="p">:</span><span class="n">skip</span>
<span class="k">rts</span> <span class="c1">; return from function</span>
<span class="p">:</span><span class="n">next</span><span class="o">-</span><span class="n">state</span>
<span class="k">cpy</span> <span class="n">@state</span><span class="o">-</span><span class="n">walking</span><span class="o">-</span><span class="n">right</span>
<span class="c1">; .... repeat all the code for each state and each transition</span>
</pre></div>
</td></tr></tbody></table>
</div>
<p>You can see this is going to extremely long winded with 13 different states each with multiple transitions, sometimes with more complex trigger logic (eg, combinations of joystick button being pressed, things not being pressed and so on).</p>
<p>In addition to this, since this is the update function for the machine, this is also where logic will take place that affects the game depending on the state, e.g. the walking right section needs to actually update the player’s X co-ordinate.</p>
<p>The final salt in the wound is that some state transitions need to execute some logic after the transition actually takes effect, for example resetting some variables or switching on / off some additional sprites.</p>
<p>Whilst I enjoy writing assembly code, I don’t so much enjoy maintaining a monster like this. I takes forever to try changes or introduce new states and it is very easy to introduce subtle, silly bugs that you don’t notice until later.</p>
<h2 id="macros-to-the-resuce">Macros to the resuce!</h2>
<p>Racket’s amazing macro system can help us out here. Wherever you see replication of code, macros are ready to lend you a helping hand. In this example we won’t even see any of the really fancy stuff racket can do, just basic macros.</p>
<p>The way I like to write macros is to first write down the syntax I would like to be able to write, then work backwards from that point to make it happen. Let’s keep it simple to start with, and forget about having to execute game logic and pre-transition logic. In fact let’s also forget about the actual machine states and just concentrate of the repetitve bit in the middle which is the checking of joystick states.</p>
<p>As an inital concept, let’s say it would be nice to write this :</p>
<div class="brush: racket">
<table class="highlighttable">
<tbody>
<tr>
<td class="linenos">
<div class="linenodiv">
<pre> 1
2
3
4
5
6
7
8
9
10</pre></div></td>
<td class="code">
<div class="highlight">
<pre><span></span><span class="n">:update-machine</span>
<span class="n">ldy</span> <span class="n">current-state</span>
<span class="n">cpy</span> <span class="n">@state-standing</span>
<span class="n">bne</span> <span class="n">next-state+</span>
<span class="p">(</span><span class="n">generate-joy-transitions</span>
<span class="p">([</span><span class="n">joy-right</span> <span class="no">#t</span> <span class="n">state-walking-right</span><span class="p">]</span>
<span class="p">[</span><span class="n">joy-down</span> <span class="no">#t</span> <span class="n">state-crouching</span><span class="p">]))</span>
<span class="n">rts</span>
<span class="n">:next-state</span>
<span class="c1">; .....</span>
</pre></div>
</td></tr></tbody></table>
</div>
<p>The macro <code>generate-joy-transitions</code> will take a list of lists, each inner list has three elements. The first is the bit pattern to test against the joystick register, the second is a boolean that indicates if the button should be tested against being pressed or NOT being pressed, and finally the last part is the target state.</p>
<p>Let’s have a frst go at writing it :</p>
<div class="brush: racket">
<table class="highlighttable">
<tbody>
<tr>
<td class="linenos">
<div class="linenodiv">
<pre> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15</pre></div></td>
<td class="code">
<div class="highlight">
<pre><span></span><span class="p">(</span><span class="n"><a href="http://docs.racket-lang.org/syntax/Defining_Simple_Macros.html#(form._((lib._syntax/parse/define..rkt)._define-syntax-parser))" style="color: inherit">define-syntax-parser</a></span> <span class="n">generate-joy-transitions</span>
<span class="p">[(</span><span class="k"><a href="http://docs.racket-lang.org/reference/stx-patterns.html#(form._((lib._racket/private/stxcase-scheme..rkt).__))" style="color: inherit">_</a></span> <span class="p">([</span><span class="n">test</span> <span class="n">is-pressed?</span> <span class="n">target</span><span class="p">]</span> <span class="k"><a href="http://docs.racket-lang.org/reference/stx-patterns.html#(form._((lib._racket/private/stxcase-scheme..rkt)._......))" style="color: inherit">...</a></span><span class="p">))</span>
<span class="o">#'</span><span class="p">{</span><span class="n">lda</span> <span class="n">$dc00</span> <span class="c1">; load joystick register</span>
<span class="n">tax</span> <span class="c1">; preserve it in x</span>
<span class="p">{</span>
<span class="k"><a href="http://docs.racket-lang.org/reference/if.html#(form._((lib._racket/private/letstx-scheme..rkt)._and))" style="color: inherit">and</a></span> <span class="n">@test</span> <span class="c1">; test bits</span>
<span class="c1">; ?? how do we perform the branch?</span>
<span class="n">ldx</span> <span class="n">@target</span> <span class="c1">; perform state transition</span>
<span class="n">jsr</span> <span class="n">change-state-</span>
<span class="n">rts</span> <span class="c1">; exit function</span>
<span class="n">:skip</span>
<span class="n">txa</span> <span class="c1">; restore joytsick data</span>
<span class="p">}</span> <span class="k"><a href="http://docs.racket-lang.org/reference/stx-patterns.html#(form._((lib._racket/private/stxcase-scheme..rkt)._......))" style="color: inherit">...</a></span>
<span class="p">}</span> <span class="c1">; repeat ...</span>
<span class="p">])</span>
</pre></div>
</td></tr></tbody></table>
</div>
<p>This is not a terrible first attempt, we simply pattern match on the inner list, extracting the parameters into the names <code>test</code> <code>is-pressed?</code> and <code>target</code>, the ellipsis <code>...</code> that follows tells racket that any amount of these lists may appear here.</p>
<p>The first two asm instructions are generated only once - the inner section which is wrapped in a nested 6502 block using <code>{ }</code> is repeated for each set of arguments thanks to the <code>...</code> that follows the block.</p>
<p>A problem remains though - after the AND test, we must use a different branch instruction depending on if we are checking that the button was pressed or not pressed via the <code>is-pressed?</code> parameter (<code>bne</code> and <code>beq</code> respectively). How can we do this? We can’t simply replace <code>is-pressed?</code> in the pattern match with <code>#t</code> and then replicate the pattern and macro output with another case for <code>#f</code>, because that would mean ALL of the provided arguments would have to be same, which is no good.</p>
<h2 id="macros-in-yer-macros">Macros in yer macros..</h2>
<p>Likely there are many ways to skin this cat - Racket generally likes you to be declarative about these things, so one way is to simply define another macro that takes care of it.</p>
<div class="brush: racket">
<table class="highlighttable">
<tbody>
<tr>
<td class="linenos">
<div class="linenodiv">
<pre> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18</pre></div></td>
<td class="code">
<div class="highlight">
<pre><span></span><span class="p">(</span><span class="n"><a href="http://docs.racket-lang.org/syntax/Defining_Simple_Macros.html#(form._((lib._syntax/parse/define..rkt)._define-syntax-parser))" style="color: inherit">define-syntax-parser</a></span> <span class="n">joy-branch</span>
<span class="p">[(</span><span class="k"><a href="http://docs.racket-lang.org/reference/stx-patterns.html#(form._((lib._racket/private/stxcase-scheme..rkt).__))" style="color: inherit">_</a></span> <span class="no">#t</span><span class="p">)</span> <span class="o">#'</span><span class="p">{</span><span class="n">bne</span> <span class="n">skip+</span><span class="p">}]</span>
<span class="p">[(</span><span class="k"><a href="http://docs.racket-lang.org/reference/stx-patterns.html#(form._((lib._racket/private/stxcase-scheme..rkt).__))" style="color: inherit">_</a></span> <span class="no">#f</span><span class="p">)</span> <span class="o">#'</span><span class="p">{</span><span class="n">beq</span> <span class="n">skip+</span><span class="p">}])</span>
<span class="p">(</span><span class="n"><a href="http://docs.racket-lang.org/syntax/Defining_Simple_Macros.html#(form._((lib._syntax/parse/define..rkt)._define-syntax-parser))" style="color: inherit">define-syntax-parser</a></span> <span class="n">generate-joy-transitions</span>
<span class="p">[(</span><span class="k"><a href="http://docs.racket-lang.org/reference/stx-patterns.html#(form._((lib._racket/private/stxcase-scheme..rkt).__))" style="color: inherit">_</a></span> <span class="p">([</span><span class="n">test</span> <span class="n">is-pressed?</span> <span class="n">target</span><span class="p">]</span> <span class="k"><a href="http://docs.racket-lang.org/reference/stx-patterns.html#(form._((lib._racket/private/stxcase-scheme..rkt)._......))" style="color: inherit">...</a></span><span class="p">))</span>
<span class="o">#'</span><span class="p">{</span><span class="n">lda</span> <span class="n">$dc00</span>
<span class="n">tax</span>
<span class="p">{</span>
<span class="k"><a href="http://docs.racket-lang.org/reference/if.html#(form._((lib._racket/private/letstx-scheme..rkt)._and))" style="color: inherit">and</a></span> <span class="n">@test</span>
<span class="p">(</span><span class="n">joy-branch</span> <span class="n">is-presed?</span><span class="p">)</span> <span class="c1">; call the other macro here</span>
<span class="n">ldx</span> <span class="n">@target</span>
<span class="n">jsr</span> <span class="n">change-state-</span>
<span class="n">rts</span>
<span class="n">:skip</span>
<span class="n">txa</span>
<span class="p">}</span> <span class="k"><a href="http://docs.racket-lang.org/reference/stx-patterns.html#(form._((lib._racket/private/stxcase-scheme..rkt)._......))" style="color: inherit">...</a></span> <span class="p">}</span>
<span class="p">])</span>
</pre></div>
</td></tr></tbody></table>
</div>
<p>Cool, now it works as expected. Infact, since we haven’t told Racket to expect any particular types (eg, expressions, integers) as the parameters, it is totally possible to pass expressions into <code>test</code> and <code>target</code>, which is very handy if you wanted for example to test a combined bitmask for more than one button at once:</p>
<div class="brush: racket">
<table class="highlighttable">
<tbody>
<tr>
<td class="linenos">
<div class="linenodiv">
<pre>1
2</pre></div></td>
<td class="code">
<div class="highlight">
<pre><span></span> <span class="p">(</span><span class="n">generate-joy-transitions</span>
<span class="p">([(</span><span class="nb"><a href="http://docs.racket-lang.org/reference/generic-numbers.html#(def._((quote._~23~25kernel)._bitwise-ior))" style="color: inherit">bitwise-ior</a></span> <span class="n">joy-right</span> <span class="n">joy-down</span><span class="p">)</span> <span class="no">#t</span> <span class="n">some-state</span><span class="p">]))</span>
</pre></div>
</td></tr></tbody></table>
</div>
<p>Very nice! We basically got that for free. For the final piece of this section we wished to be able to execute some arbitary code after the transition has finished. However, we dont always want to do this, and Racket has just the answer by allowing us to put in an optional parameter that will be defaulted to an empty block if not supplied.</p>
<div class="brush: racket">
<table class="highlighttable">
<tbody>
<tr>
<td class="linenos">
<div class="linenodiv">
<pre> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16</pre></div></td>
<td class="code">
<div class="highlight">
<pre><span></span><span class="p">(</span><span class="n"><a href="http://docs.racket-lang.org/syntax/Defining_Simple_Macros.html#(form._((lib._syntax/parse/define..rkt)._define-syntax-parser))" style="color: inherit">define-syntax-parser</a></span> <span class="n">generate-joy-transitions</span>
<span class="p">[(</span><span class="k"><a href="http://docs.racket-lang.org/reference/stx-patterns.html#(form._((lib._racket/private/stxcase-scheme..rkt).__))" style="color: inherit">_</a></span> <span class="p">([</span><span class="n">test</span> <span class="n">is-pressed?</span> <span class="n">target</span>
<span class="p">(</span><span class="n"><a href="http://docs.racket-lang.org/syntax/stxparse-patterns.html#(form._((lib._syntax/parse..rkt)._~7eoptional))" style="color: inherit">~optional</a></span> <span class="n">extra</span> <span class="kd">#:defaults</span> <span class="p">([</span><span class="n">extra</span> <span class="o">#'</span><span class="p">{}</span> <span class="p">]))]</span> <span class="k"><a href="http://docs.racket-lang.org/reference/stx-patterns.html#(form._((lib._racket/private/stxcase-scheme..rkt)._......))" style="color: inherit">...</a></span><span class="p">))</span>
<span class="o">#'</span><span class="p">{</span><span class="n">lda</span> <span class="n">$dc00</span>
<span class="n">tax</span>
<span class="p">{</span>
<span class="k"><a href="http://docs.racket-lang.org/reference/if.html#(form._((lib._racket/private/letstx-scheme..rkt)._and))" style="color: inherit">and</a></span> <span class="n">@test</span>
<span class="p">(</span><span class="n">joy-branch</span> <span class="n">is-pressed?</span><span class="p">)</span>
<span class="n">ldx</span> <span class="n">@target</span>
<span class="n">jsr</span> <span class="n">change-state-</span>
<span class="n">extra</span> <span class="c1">; stick the extra code in here</span>
<span class="n">rts</span>
<span class="n">:skip</span>
<span class="n">txa</span>
<span class="p">}</span> <span class="k"><a href="http://docs.racket-lang.org/reference/stx-patterns.html#(form._((lib._racket/private/stxcase-scheme..rkt)._......))" style="color: inherit">...</a></span> <span class="p">}</span>
<span class="p">])</span>
</pre></div>
</td></tr></tbody></table>
</div>
<p>Now we can write</p>
<div class="brush: racket">
<table class="highlighttable">
<tbody>
<tr>
<td class="linenos">
<div class="linenodiv">
<pre>1
2
3
4
5
6</pre></div></td>
<td class="code">
<div class="highlight">
<pre><span></span> <span class="p">(</span><span class="n">generate-joy-transitions</span>
<span class="p">([</span><span class="n">joy-right</span> <span class="no">#t</span> <span class="n">state-walking-right</span><span class="p">]</span>
<span class="p">[</span><span class="n">joy-down</span> <span class="no">#t</span> <span class="n">state-crouching</span>
<span class="p">{</span>
<span class="c1">; some asm code...</span>
<span class="p">}]))</span>
</pre></div>
</td></tr></tbody></table>
</div>
<p>Of course, a 6502 block is inlined in the above example, but it could equally call a function that generates some code, calls another macro, or whatever.</p>
<h1 id="macros-in-yer-macros-in-yer-macros-">Macros in yer macros in yer macros …</h1>
<p>The final icing on the cake is to get rid of the state machine branching logic completely. To do this we need to :</p>
<ul>
<li>Create essentially the <code>switch</code> statement for each state</li>
<li>Allow some arbitary code be executed</li>
<li>Check all joystick transitions as above</li></ul>
<p>So, what we want to be able to write is :</p>
<div class="brush: racket">
<table class="highlighttable">
<tbody>
<tr>
<td class="linenos">
<div class="linenodiv">
<pre> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19</pre></div></td>
<td class="code">
<div class="highlight">
<pre><span></span><span class="p">(</span><span class="n">generate-state-machine</span>
<span class="p">([</span><span class="n">state-standing</span>
<span class="p">{</span> <span class="p">}</span>
<span class="p">([</span><span class="n">joy-right</span> <span class="no">#t</span> <span class="n">state-walking-right</span><span class="p">]</span>
<span class="p">[</span><span class="n">joy-left</span> <span class="no">#t</span> <span class="n">state-walking-left</span><span class="p">]</span>
<span class="p">[</span><span class="n">joy-down</span> <span class="no">#t</span> <span class="n">state-crouching</span>
<span class="p">{</span> <span class="n">some</span> <span class="n">code</span> <span class="k"><a href="http://docs.racket-lang.org/reference/stx-patterns.html#(form._((lib._racket/private/stxcase-scheme..rkt)._......))" style="color: inherit">...</a></span> <span class="p">}])]</span>
<span class="p">[</span><span class="n">state-walking-right</span>
<span class="p">{</span>
<span class="c1">; move sprite right</span>
<span class="n">inc</span> <span class="n">$d000</span>
<span class="n">inc</span> <span class="n">$d000</span>
<span class="p">}</span>
<span class="p">([</span><span class="n">joy-left</span> <span class="no">#t</span> <span class="n">state-walking-left</span><span class="p">]</span>
<span class="p">[</span><span class="n">joy-right</span> <span class="no">#f</span> <span class="n">state-standing</span><span class="p">])]</span>
<span class="c1">; more cases ...</span>
<span class="p">))</span>
</pre></div>
</td></tr></tbody></table>
</div>
<p>Following the patterns above this pretty much writes itself:</p>
<div class="brush: racket">
<table class="highlighttable">
<tbody>
<tr>
<td class="linenos">
<div class="linenodiv">
<pre> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17</pre></div></td>
<td class="code">
<div class="highlight">
<pre><span></span><span class="p">(</span><span class="n"><a href="http://docs.racket-lang.org/syntax/Defining_Simple_Macros.html#(form._((lib._syntax/parse/define..rkt)._define-syntax-parser))" style="color: inherit">define-syntax-parser</a></span> <span class="n">generate-state-machine</span>
<span class="p">[(</span><span class="k"><a href="http://docs.racket-lang.org/reference/stx-patterns.html#(form._((lib._racket/private/stxcase-scheme..rkt).__))" style="color: inherit">_</a></span> <span class="p">([</span><span class="n">state-number</span>
<span class="n">update-code</span>
<span class="n">joy-cases</span><span class="p">]</span> <span class="k"><a href="http://docs.racket-lang.org/reference/stx-patterns.html#(form._((lib._racket/private/stxcase-scheme..rkt)._......))" style="color: inherit">...</a></span><span class="p">))</span>
<span class="o">#'</span><span class="p">{</span>
<span class="p">{</span>
<span class="n">ldy</span> <span class="n">current-state</span> <span class="c1">;load current state</span>
<span class="n">cpy</span> <span class="n">@state-number</span>
<span class="n">bne</span> <span class="n">next-state+</span>
<span class="n">update-code</span> <span class="c1">; insert update code here</span>
<span class="c1">;call the joystick macro with the cases</span>
<span class="p">(</span><span class="n">generate-joy-transitions</span> <span class="n">joy-cases</span><span class="p">)</span>
<span class="n">:next-state</span>
<span class="p">}</span> <span class="k"><a href="http://docs.racket-lang.org/reference/stx-patterns.html#(form._((lib._racket/private/stxcase-scheme..rkt)._......))" style="color: inherit">...</a></span>
<span class="p">}])</span>
</pre></div>
</td></tr></tbody></table>
</div>
<p>And we are done.</p>
<h2 id="closing-thoughts">Closing Thoughts</h2>
<p>Macros are a super powerful way to help introduce new syntax over the top of the assembler, and this is really just scratching the surface of it.</p>
<p>This example is kept simple, it has some obvious problems such as the “switch” statement uses branching instructions that can only go +/– 127 bytes and it will break if there is too much code between the branch and the label. It also has to check each state until it finds what it is looking for - a nicer way would be to use a lookup table and jump to the correct address, which is totally possible with a little more macrology …</p>
<p>Happy assembling!</p>
<h2 id="additional-edit">Additional Edit!</h2>
<p>Since I posted this earlier today, I have changed the switch-statement type affair into a much more effecient lookup table, and I thought it might be interesting to show how it works, since it uses the assembler’s open architecture by directly calling into some of the functionality it provides rather than using the assembler syntax.</p>
<p>The idea is to do the following</p>
<ul>
<li>Load the current state number</li>
<li>Using the number as an index, lookup the low address byte where the code for that state lives. Store this number somewhere</li>
<li>Repeat to lookup the high address byte, store it next to the low byte</li>
<li>Use the indirect jump op-code to jump to this address.</li></ul>
<p>In order to do this we will have to know the location of each state’s code that we assemble and put their locations into lookup tables split by their low and high bytes. There are a few ways to do this, the easiest is to label each section of state code, then later extract the address details into lookup tabes. Here’s how it looks :</p>
<div class="brush: racket">
<table class="highlighttable">
<tbody>
<tr>
<td class="linenos">
<div class="linenodiv">
<pre> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37</pre></div></td>
<td class="code">
<div class="highlight">
<pre><span></span><span class="p">(</span><span class="n"><a href="http://docs.racket-lang.org/syntax/Defining_Simple_Macros.html#(form._((lib._syntax/parse/define..rkt)._define-syntax-parser))" style="color: inherit">define-syntax-parser</a></span> <span class="n">generate-state-machine</span>
<span class="p">[(</span><span class="k"><a href="http://docs.racket-lang.org/reference/stx-patterns.html#(form._((lib._racket/private/stxcase-scheme..rkt).__))" style="color: inherit">_</a></span> <span class="p">([</span><span class="n">state-number</span>
<span class="n">update-code</span>
<span class="n">joy-cases</span><span class="p">]</span> <span class="k"><a href="http://docs.racket-lang.org/reference/stx-patterns.html#(form._((lib._racket/private/stxcase-scheme..rkt)._......))" style="color: inherit">...</a></span><span class="p">))</span>
<span class="o">#'</span><span class="p">{</span>
<span class="n">ldx</span> <span class="n">tc-state</span> <span class="c1">; load current state</span>
<span class="n">lda</span> <span class="n">state-machine-lo:</span> <span class="n">x</span> <span class="c1">; use lookup table and setup</span>
<span class="n">sta</span> <span class="n">jump-vector-lo+</span> <span class="c1">; 16 bit address pointer</span>
<span class="n">lda</span> <span class="n">state-machine-hi:</span> <span class="n">x</span>
<span class="n">sta</span> <span class="n">jump-vector-hi+</span>
<span class="n">jmpi</span> <span class="n">jump-vector-lo:</span> <span class="c1">; jump to target state</span>
<span class="c1">; write out the states </span>
<span class="p">{</span>
<span class="c1">;set jump location</span>
<span class="p">(</span><span class="n">set-jump-source-current</span> <span class="p">(</span><span class="nb"><a href="http://docs.racket-lang.org/reference/Writing.html#(def._((quote._~23~25kernel)._format))" style="color: inherit">format</a></span> <span class="s2">"state~a"</span> <span class="n">state-number</span><span class="p">))</span>
<span class="n">update-code</span>
<span class="p">(</span><span class="n">generate-joy-transitions</span> <span class="n">joy-cases</span><span class="p">)</span>
<span class="n">rts</span>
<span class="p">}</span> <span class="k"><a href="http://docs.racket-lang.org/reference/stx-patterns.html#(form._((lib._racket/private/stxcase-scheme..rkt)._......))" style="color: inherit">...</a></span>
<span class="p">(</span><span class="k"><a href="http://docs.racket-lang.org/reference/define.html#(form._((lib._racket/private/base..rkt)._define))" style="color: inherit">define</a></span> <span class="n">jump-labels</span>
<span class="p">(</span><span class="n">~>></span>
<span class="p">(</span><span class="nb"><a href="http://docs.racket-lang.org/reference/pairs.html#(def._((quote._~23~25kernel)._list))" style="color: inherit">list</a></span> <span class="n">state-number</span> <span class="k"><a href="http://docs.racket-lang.org/reference/stx-patterns.html#(form._((lib._racket/private/stxcase-scheme..rkt)._......))" style="color: inherit">...</a></span><span class="p">)</span>
<span class="p">(</span><span class="nb"><a href="http://docs.racket-lang.org/reference/pairs.html#(def._((lib._racket/private/map..rkt)._map))" style="color: inherit">map</a></span> <span class="p">(</span><span class="n"><a href="http://docs.racket-lang.org/reference/lambda.html#(form._((lib._racket/private/base..rkt)._~ce~bb))" style="color: inherit">λ</a></span> <span class="p">(</span><span class="n">n</span><span class="p">)</span> <span class="p">(</span><span class="nb"><a href="http://docs.racket-lang.org/reference/Writing.html#(def._((quote._~23~25kernel)._format))" style="color: inherit">format</a></span> <span class="s2">"state~a"</span> <span class="n">n</span><span class="p">)))</span>
<span class="p">(</span><span class="nb"><a href="http://docs.racket-lang.org/reference/pairs.html#(def._((lib._racket/private/map..rkt)._map))" style="color: inherit">map</a></span> <span class="p">(</span><span class="n"><a href="http://docs.racket-lang.org/reference/lambda.html#(form._((lib._racket/private/base..rkt)._~ce~bb))" style="color: inherit">λ</a></span> <span class="p">(</span><span class="n">n</span><span class="p">)</span> <span class="p">(</span><span class="n">find-closest-label</span> <span class="n">n</span> <span class="p">(</span><span class="n">here</span><span class="p">)</span> <span class="o">'</span><span class="ss"><a href="http://docs.racket-lang.org/reference/generic-numbers.html#(def._((quote._~23~25kernel)._-))" style="color: inherit">-</a></span><span class="p">)))))</span>
<span class="n">:state-machine-lo</span>
<span class="p">(</span><span class="n">write-values</span> <span class="p">(</span><span class="nb"><a href="http://docs.racket-lang.org/reference/pairs.html#(def._((lib._racket/private/map..rkt)._map))" style="color: inherit">map</a></span> <span class="n">lo-byte</span> <span class="n">jump-labels</span><span class="p">))</span>
<span class="n">:state-machine-hi</span>
<span class="p">(</span><span class="n">write-values</span> <span class="p">(</span><span class="nb"><a href="http://docs.racket-lang.org/reference/pairs.html#(def._((lib._racket/private/map..rkt)._map))" style="color: inherit">map</a></span> <span class="n">hi-byte</span> <span class="n">jump-labels</span><span class="p">))</span>
<span class="n">:jump-vector-lo</span> <span class="p">(</span><span class="n">data</span> <span class="n">$FF</span><span class="p">)</span>
<span class="n">:jump-vector-hi</span> <span class="p">(</span><span class="n">data</span> <span class="n">$FF</span><span class="p">)</span>
<span class="p">}])</span>
</pre></div>
</td></tr></tbody></table>
</div>
<p>The first lines of code load in the current state, perfom the indexed lookups into the tables and store the address in the jump-vector. Then, the code jumps via this vector and begins executing the code for the current state.</p>
<p>The code that writes out the states directly calls the internal assembler function to add a label <code>set-jump-source-current</code>, and it names the label <code>state-n</code> where <code>n</code> is the number of the state it is processing.</p>
<p>At the bottom of the macro, we take ALL the numbers together <code>(list state-number ... )</code> re-format them into the label names, call another internal assembler function that locates a label from a given location <code>find-closest-label</code> and finally extracts the low or high bytes from it. These are then written out as lookup data.</p>
<p>Finally, the last two lines label a couple of bytes to use as a jump vector that is written to from the jumping logic.</p>
<p>This is really cool! Now the state machine is much more effecient and has no worries about branching limitations. Most importantly, you can add and remove states withouht ever having to worry about moving loads of code and numbers around, and making far less mistakes because of it.</p>C64 Sprite Previewerurn:http-www-pinksquirrellabs-com:-blog-2018-09-17-c64-sprite-previewer2018-09-17T20:05:58Z2018-09-17T20:05:58Zpezi
<p>In this post we will see how <a href="http://pinksquirrellabs.com/blog/2017/05/30/asi64/">asi64</a> is more than your average macro assembler, by combining arbitrary disk io, functional programming techniques and code generation alongside your typical 6502 assembly code. The aim is to create a very simple sprite animation viewer, that writes the resulting C64 program by interleaving file parsing and machine code generation.</p>
<p>Here’s the program displaying some sprites that <a href="https://twitter.com/silverSpoon">@silverspoon</a> has started working on :) (in different, single colours for the fun of it)</p>
<div class="figure"><img src="http://www.pinksquirrellabs.com/img/asi/tc.gif" alt="" />
<p class="caption"></p></div>
<!-- more-->
<p>To read this post it would probably help to know some 6502 (though not essential), you can read the assembler syntax over at <a href="https://github.com/pezipink/Asi64">asi64’s github</a> or from an <a href="http://pinksquirrellabs.com/blog/2017/05/30/asi64/">older post on it</a></p>
<h2 id="sprites">Sprites</h2>
<p>The C64 has 8 hardware sprites it can utilise. This means the video hardware can display up to 8 sprites at once. To animate something, you would use a series of sprites that you change between. To design these sprites there are various tools available (not like the 80s where you had to draw them manually on graph paper!). I have been using <a href="http://www.spritemate.com/">spritemate</a> which is a nice online tool.</p>
<p>Spritemate is able to save the sprites in a variety of formats, including assembly code output for two of the popular C64 assemblers (KickAss and ACME).</p>
<p>What I would like is a way whereby I can design a series of sprite animation frames in the tool, save a number of these files (each file containing n sprite-frames of animation for some entity), then have the assembler read them from disk and automatically display and animate each sprite on the C64 screen. This will provide a fast feedback loop to see what they look like on the machine, rather than having to mess around moving chunks of data and altering frame counts and animation code manually.</p>
<p>To display sprites on the C64 you need to have a number of things in place. This post is not supposed to be a tutorial on how they work, so not everything will be explained.</p>
<ul>
<li>The actual sprite data itself must live somewhere the VIC graphics chip can see it.</li>
<li>The last 8 bytes of screen memory indicate an offset into the sprite data telling the VIC which sprite to display for each of the 8 sprites.</li>
<li>Sprite colours and positions are set with bunch of memory-mapped registers on the VIC.</li></ul>
<p>The details on how to configure the VIC for this are out of the scope of this post. Suffice to say, for my needs, all the sprite data will be stored at $2000, my screen data lives at $0400, the last 8 bytes of it (the sprite pointers) are at $7fe8.</p>
<p>The sprites are used in multi-colour mode, which means they each have 4 colours. 3 of the colours are shared by all sprites (background, colour 1 and colour 2) and the last colour is individual to each sprite, set within 8 more VIC registers. For the sake of simplicty, this post ignores the individual colour, assuming they are all the same.</p>
<h2 id="file-formats">File Formats</h2>
<p>Since Asi64 extends Racket, it has the <a href="https://racket-lang.org/">full arsenal of Racket at its disposal</a>, including its ridiculous macro system, multiple programming paradigms, extensive libraries and packages. We can quite easily mix this code in with 6502 assembler to help generate code in any way you would like.</p>
<p>Let’s look at one of Spritemate’s output formats, for <a href="http://theweb.dk/KickAssembler/Main.html#frontpage">KickAss</a> (which is a fantasic assmembler, and partly the inspiration for writing Asi64!)</p>
<pre><code>// 4 sprites generated with spritemate on 9/14/2018, 9:03:32 PM
// Byte 64 of each sprite contains multicolor (high nibble) & color (low nibble) information
LDA #$04 // sprite multicolor 1
STA $D025
LDA #$06 // sprite multicolor 2
STA $D026
// sprite 1 / multicolor / color: $0e
sprite_1:
.byte $0c,$00,$30,$0f,$00,$30,$0f,$ff
.byte $f0,$03,$7d,$f0,$03,$ff,$c0,$01
.byte $eb,$40,$00,$ff,$00,$01,$3c,$40
.byte $00,$74,$00,$00,$54,$00,$00,$74
.byte $00,$00,$fc,$00,$00,$fc,$00,$03
.byte $ff,$0c,$03,$ff,$0c,$03,$ff,$0c
.byte $0f,$ff,$cc,$0e,$fe,$cc,$3e,$fe
.byte $f0,$3e,$fe,$f0,$3e,$fe,$f0,$8e
// sprite 2 / multicolor / color: $0e
sprite_2:</code></pre>
<p>The interesting bits of this file are</p>
<ul>
<li>How many sprite frames are in the file (each sprite is a frame of animation)</li>
<li>The sprite data itself, which of course is just a bunch of bytes</li>
<li>Additional colour data which we are ignoring for this post.</li></ul>
<p>Since Asi64 is also Racket, we can write a function that will extract the contents of one of these files into a little structure:</p>
<div class="brush: racket">
<table class="highlighttable">
<tbody>
<tr>
<td class="linenos">
<div class="linenodiv">
<pre> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24</pre></div></td>
<td class="code">
<div class="highlight">
<pre><span></span><span class="kn">#lang </span><span class="nn">asi64</span>
<span class="p">(</span><span class="k"><a href="http://docs.racket-lang.org/reference/define-struct.html#(form._((lib._racket/private/base..rkt)._struct))" style="color: inherit">struct</a></span> <span class="n">sprite-data</span> <span class="p">(</span><span class="n">frame-count</span> <span class="n">data</span><span class="p">))</span>
<span class="p">(</span><span class="k"><a href="http://docs.racket-lang.org/reference/define.html#(form._((lib._racket/private/base..rkt)._define))" style="color: inherit">define</a></span> <span class="p">(</span><span class="n">extract-sprite</span> <span class="n">filename</span><span class="p">)</span>
<span class="p">(</span><span class="k"><a href="http://docs.racket-lang.org/reference/let.html#(form._((lib._racket/private/letstx-scheme..rkt)._let*))" style="color: inherit">let*</a></span> <span class="p">(</span><span class="c1">;read file as a sequence of lines</span>
<span class="p">[</span><span class="n">lines</span> <span class="p">(</span><span class="nb"><a href="http://docs.racket-lang.org/reference/Filesystem.html#(def._((lib._racket/file..rkt)._file-~3elines))" style="color: inherit">file->lines</a></span> <span class="n">filename</span><span class="p">)]</span>
<span class="c1">;count the amount of frames by looking at lines that end with :</span>
<span class="p">[</span><span class="n">frames</span> <span class="p">(</span><span class="nb"><a href="http://docs.racket-lang.org/reference/pairs.html#(def._((quote._~23~25kernel)._length))" style="color: inherit">length</a></span> <span class="p">(</span><span class="nb"><a href="http://docs.racket-lang.org/reference/pairs.html#(def._((lib._racket/private/list..rkt)._filter))" style="color: inherit">filter</a></span> <span class="p">(</span><span class="n"><a href="http://docs.racket-lang.org/reference/lambda.html#(form._((lib._racket/private/base..rkt)._~ce~bb))" style="color: inherit">λ</a></span> <span class="p">(</span><span class="n">s</span><span class="p">)</span> <span class="p">(</span><span class="nb"><a href="http://docs.racket-lang.org/reference/strings.html#(def._((lib._racket/string..rkt)._string-suffix~3f))" style="color: inherit">string-suffix?</a></span> <span class="n">s</span> <span class="s2">":"</span><span class="p">))</span> <span class="n">lines</span><span class="p">))]</span>
<span class="c1">; extract the raw data as one big lump</span>
<span class="p">[</span><span class="n">data</span> <span class="p">(</span><span class="n">~>></span>
<span class="n">lines</span>
<span class="c1">; filter to .byte rows </span>
<span class="p">(</span><span class="nb"><a href="http://docs.racket-lang.org/reference/pairs.html#(def._((lib._racket/private/list..rkt)._filter))" style="color: inherit">filter</a></span> <span class="p">(</span><span class="n"><a href="http://docs.racket-lang.org/reference/lambda.html#(form._((lib._racket/private/base..rkt)._~ce~bb))" style="color: inherit">λ</a></span> <span class="p">(</span><span class="n">s</span><span class="p">)</span> <span class="p">(</span><span class="nb"><a href="http://docs.racket-lang.org/reference/strings.html#(def._((lib._racket/string..rkt)._string-prefix~3f))" style="color: inherit">string-prefix?</a></span> <span class="n">s</span> <span class="s2">".byte"</span><span class="p">)))</span>
<span class="c1">; clean up text leaving raw hex values</span>
<span class="p">(</span><span class="nb"><a href="http://docs.racket-lang.org/reference/pairs.html#(def._((lib._racket/private/map..rkt)._map))" style="color: inherit">map</a></span> <span class="p">(</span><span class="n"><a href="http://docs.racket-lang.org/reference/lambda.html#(form._((lib._racket/private/base..rkt)._~ce~bb))" style="color: inherit">λ</a></span> <span class="p">(</span><span class="n">s</span><span class="p">)</span> <span class="p">(</span><span class="nb"><a href="http://docs.racket-lang.org/reference/strings.html#(def._((lib._racket/string..rkt)._string-replace))" style="color: inherit">string-replace</a></span> <span class="n">s</span> <span class="s2">".byte "</span> <span class="s2">""</span><span class="p">)))</span>
<span class="p">(</span><span class="nb"><a href="http://docs.racket-lang.org/reference/pairs.html#(def._((lib._racket/private/map..rkt)._map))" style="color: inherit">map</a></span> <span class="p">(</span><span class="n"><a href="http://docs.racket-lang.org/reference/lambda.html#(form._((lib._racket/private/base..rkt)._~ce~bb))" style="color: inherit">λ</a></span> <span class="p">(</span><span class="n">s</span><span class="p">)</span> <span class="p">(</span><span class="nb"><a href="http://docs.racket-lang.org/reference/strings.html#(def._((lib._racket/string..rkt)._string-replace))" style="color: inherit">string-replace</a></span> <span class="n">s</span> <span class="s2">"$"</span> <span class="s2">""</span><span class="p">)))</span>
<span class="p">(</span><span class="nb"><a href="http://docs.racket-lang.org/reference/pairs.html#(def._((lib._racket/private/map..rkt)._map))" style="color: inherit">map</a></span> <span class="p">(</span><span class="n"><a href="http://docs.racket-lang.org/reference/lambda.html#(form._((lib._racket/private/base..rkt)._~ce~bb))" style="color: inherit">λ</a></span> <span class="p">(</span><span class="n">s</span><span class="p">)</span> <span class="p">(</span><span class="nb"><a href="http://docs.racket-lang.org/reference/strings.html#(def._((lib._racket/string..rkt)._string-split))" style="color: inherit">string-split</a></span> <span class="n">s</span> <span class="s2">","</span><span class="p">)))</span>
<span class="c1">; flatten into one big list of numbers</span>
<span class="p">(</span><span class="nb"><a href="http://docs.racket-lang.org/reference/pairs.html#(def._((lib._racket/list..rkt)._flatten))" style="color: inherit">flatten</a></span><span class="p">)</span>
<span class="c1">; parse hex </span>
<span class="p">(</span><span class="nb"><a href="http://docs.racket-lang.org/reference/pairs.html#(def._((lib._racket/private/map..rkt)._map))" style="color: inherit">map</a></span> <span class="p">(</span><span class="n"><a href="http://docs.racket-lang.org/reference/lambda.html#(form._((lib._racket/private/base..rkt)._~ce~bb))" style="color: inherit">λ</a></span> <span class="p">(</span><span class="n">s</span><span class="p">)</span> <span class="p">(</span><span class="nb"><a href="http://docs.racket-lang.org/reference/generic-numbers.html#(def._((quote._~23~25kernel)._string-~3enumber))" style="color: inherit">string->number</a></span> <span class="n">s</span> <span class="mi">16</span><span class="p">))))])</span>
<span class="p">(</span><span class="n">sprite-data</span> <span class="n">frames</span> <span class="n">data</span><span class="p">)))</span>
</pre></div>
</td></tr></tbody></table>
</div>
<p>And now we can quite easily scan the sprites directory for all files (we’ll assume there’s no more than 8) and pass them through this function to yield a bunch of structures containing the sprite data that can be used to help write the assembly code.</p>
<div class="brush: racket">
<table class="highlighttable">
<tbody>
<tr>
<td class="linenos">
<div class="linenodiv">
<pre>1
2
3
4
5
6</pre></div></td>
<td class="code">
<div class="highlight">
<pre><span></span><span class="p">(</span><span class="k"><a href="http://docs.racket-lang.org/reference/define.html#(form._((lib._racket/private/base..rkt)._define))" style="color: inherit">define</a></span> <span class="n">sprites</span>
<span class="p">(</span><span class="n">~>></span>
<span class="p">(</span><span class="nb"><a href="http://docs.racket-lang.org/reference/Filesystem.html#(def._((lib._racket/private/base..rkt)._directory-list))" style="color: inherit">directory-list</a></span> <span class="s2">"..</span><span class="se">\\</span><span class="s2">sprites"</span> <span class="kd">#:build?</span> <span class="no">#t</span><span class="p">)</span>
<span class="p">(</span><span class="nb"><a href="http://docs.racket-lang.org/reference/pairs.html#(def._((lib._racket/private/map..rkt)._map))" style="color: inherit">map</a></span> <span class="nb"><a href="http://docs.racket-lang.org/reference/Manipulating_Paths.html#(def._((quote._~23~25kernel)._path-~3estring))" style="color: inherit">path->string</a></span><span class="p">)</span>
<span class="p">(</span><span class="nb"><a href="http://docs.racket-lang.org/reference/pairs.html#(def._((lib._racket/private/list..rkt)._filter))" style="color: inherit">filter</a></span> <span class="p">(</span><span class="n"><a href="http://docs.racket-lang.org/reference/lambda.html#(form._((lib._racket/private/base..rkt)._~ce~bb))" style="color: inherit">λ</a></span> <span class="p">(</span><span class="n">s</span><span class="p">)</span> <span class="p">(</span><span class="nb"><a href="http://docs.racket-lang.org/reference/strings.html#(def._((lib._racket/string..rkt)._string-suffix~3f))" style="color: inherit">string-suffix?</a></span> <span class="n">s</span> <span class="s2">".txt"</span><span class="p">)))</span>
<span class="p">(</span><span class="nb"><a href="http://docs.racket-lang.org/reference/pairs.html#(def._((lib._racket/private/map..rkt)._map))" style="color: inherit">map</a></span> <span class="n">extract-sprite</span><span class="p">)))</span>
</pre></div>
</td></tr></tbody></table>
</div>
<h2 id="6502">6502</h2>
<p>Now we can start to write the actual program. Before we do anything else, we want to dump the raw sprite data that was collected from all the files into memory starting at $2000.</p>
<div class="brush: racket">
<table class="highlighttable">
<tbody>
<tr>
<td class="linenos">
<div class="linenodiv">
<pre> 1
2
3
4
5
6
7
8
9
10</pre></div></td>
<td class="code">
<div class="highlight">
<pre><span></span><span class="p">(</span><span class="n">C64</span><span class="p">{</span>
<span class="c1">; raw sprite data starts at $2000</span>
<span class="n">*=</span> <span class="n">$2000</span>
<span class="p">(</span><span class="n">write-values</span>
<span class="p">(</span><span class="n">~>></span>
<span class="n">sprites</span>
<span class="c1">; extract the "data" field from the struct</span>
<span class="p">(</span><span class="nb"><a href="http://docs.racket-lang.org/reference/pairs.html#(def._((lib._racket/private/map..rkt)._map))" style="color: inherit">map</a></span> <span class="n">sprite-data-data</span><span class="p">)</span>
<span class="p">(</span><span class="nb"><a href="http://docs.racket-lang.org/reference/pairs.html#(def._((lib._racket/list..rkt)._flatten))" style="color: inherit">flatten</a></span><span class="p">)))</span>
</pre></div>
</td></tr></tbody></table>
</div>
<p>We simply extract out the “data” field from the structs created earlier, and flatten it all into one big list. The “write-values” here is an asi64 form that simply instructs the assembler to write whatever numbers it is given to the current location.</p>
<p>The next part is a lot more interesting. We need to setup each of the sprite pointers to point at the first frame of animation for each file that was loaded (we assume in this example there were a maximum of 8 sprites - there are multiplexing techniques you can use to display more)</p>
<p>With the way the VIC is currently setup, the 8 sprite pointers start at $07f8, and the correct index to store in the first one so that it will point at the first frame of data we stored at $2000 is $80. Then, for each successive set of sprite data, we must increase the offset by the number of frames from the previous set, thus arriving at the first frame of the next set, and store that into the next pointer.</p>
<p>That is a bit of a mouthful, hopefully the code will help to make it clear. In asi64, everything between curly braces is 6502 assembler which you can nest anywhere:</p>
<div class="brush: racket">
<table class="highlighttable">
<tbody>
<tr>
<td class="linenos">
<div class="linenodiv">
<pre> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35</pre></div></td>
<td class="code">
<div class="highlight">
<pre><span></span> <span class="c1">; start our actual program at $1000</span>
<span class="n">*=</span> <span class="n">$1000</span>
<span class="c1">; enable all sprites</span>
<span class="n">lda</span> <span class="n">@$FF</span>
<span class="n">sta</span> <span class="n">$d015</span>
<span class="c1">; turn on multicolour mode for all sprites</span>
<span class="n">lda</span> <span class="n">@$FF</span>
<span class="n">sta</span> <span class="n">$d01c</span>
<span class="n">lda</span> <span class="n">@$04</span> <span class="c1">; sprite multicolor 1</span>
<span class="n">sta</span> <span class="n">$D025</span>
<span class="n">lda</span> <span class="n">@$06</span> <span class="c1">; sprite multicolor 2</span>
<span class="n">sta</span> <span class="n">$D026</span>
<span class="c1">; set background colour to black</span>
<span class="n">lda</span> <span class="n">@0</span>
<span class="n">sta</span> <span class="n">$d021</span>
<span class="p">(</span><span class="k"><a href="http://docs.racket-lang.org/reference/for.html#(form._((lib._racket/private/base..rkt)._for/fold))" style="color: inherit">for/fold</a></span> <span class="p">(</span><span class="c1">; points at $2000</span>
<span class="p">[</span><span class="n">data-index</span> <span class="n">$80</span><span class="p">]</span>
<span class="c1">; first sprite pointer </span>
<span class="p">[</span><span class="n">sprite-pointer</span> <span class="n">$07f8</span><span class="p">]</span>
<span class="p">[</span><span class="n">code</span> <span class="p">(</span><span class="nb"><a href="http://docs.racket-lang.org/reference/pairs.html#(def._((quote._~23~25kernel)._list))" style="color: inherit">list</a></span><span class="p">)])</span>
<span class="p">([</span><span class="n">s</span> <span class="n">sprites</span><span class="p">])</span>
<span class="p">(</span><span class="k"><a href="http://docs.racket-lang.org/reference/let.html#(form._((lib._racket/private/letstx-scheme..rkt)._let))" style="color: inherit">let</a></span> <span class="p">([</span><span class="n">new-code</span>
<span class="p">{</span>
<span class="c1">; set the sprite pointer to the first frame</span>
<span class="c1">; for this animation</span>
<span class="n">lda</span> <span class="n">@data-index</span>
<span class="n">sta</span> <span class="n">sprite-pointer</span>
<span class="p">}])</span>
<span class="p">(</span><span class="nb"><a href="http://docs.racket-lang.org/reference/values.html#(def._((quote._~23~25kernel)._values))" style="color: inherit">values</a></span> <span class="p">(</span><span class="nb"><a href="http://docs.racket-lang.org/reference/generic-numbers.html#(def._((quote._~23~25kernel)._+))" style="color: inherit">+</a></span> <span class="p">(</span><span class="n">sprite-data-frame-count</span> <span class="n">s</span><span class="p">)</span> <span class="n">data-index</span><span class="p">)</span>
<span class="p">(</span><span class="nb"><a href="http://docs.racket-lang.org/reference/generic-numbers.html#(def._((quote._~23~25kernel)._+))" style="color: inherit">+</a></span> <span class="mi">1</span> <span class="n">sprite-pointer</span><span class="p">)</span>
<span class="p">(</span><span class="nb"><a href="http://docs.racket-lang.org/reference/pairs.html#(def._((quote._~23~25kernel)._cons))" style="color: inherit">cons</a></span> <span class="n">new-code</span> <span class="n">code</span><span class="p">))))</span>
</pre></div>
</td></tr></tbody></table>
</div>
<p>The for/fold function builds up a list containing chunks of 6502 code, bringing along another 2 accumulators to track the sprite pointer and frame offset.</p>
<p>Racket’s for/fold actually returns all three accumulators as Racket “multiple values”. However, because asi64 only cares about 6502 code, it simply ignores the first two results, but it will then see a list of 6502 code which it will happily assemble.</p>
<p>Next up is to position the sprites on the screen. To do this, you have to set some more VIC registers. $d000 is Sprite 1’s X, $d001 is Sprite 1’s Y, and so on for each sprite.</p>
<p>We want to line the sprites up together at a fixed Y co-ordinate, but of course without overlapping on the X co-ordinates. A sprite is 24 pixels wide, so we’ll factor that in.</p>
<div class="brush: racket">
<table class="highlighttable">
<tbody>
<tr>
<td class="linenos">
<div class="linenodiv">
<pre>1
2
3
4
5
6
7
8</pre></div></td>
<td class="code">
<div class="highlight">
<pre><span></span> <span class="c1">;position sprites</span>
<span class="p">(</span><span class="k"><a href="http://docs.racket-lang.org/reference/for.html#(form._((lib._racket/private/base..rkt)._for))" style="color: inherit">for</a></span> <span class="p">([</span><span class="n">x</span> <span class="p">(</span><span class="nb"><a href="http://docs.racket-lang.org/reference/sequences.html#(def._((lib._racket/private/base..rkt)._in-range))" style="color: inherit">in-range</a></span> <span class="mi">8</span><span class="p">)])</span>
<span class="p">{</span>
<span class="n">lda</span> <span class="n">@</span><span class="p">(</span><span class="nb"><a href="http://docs.racket-lang.org/reference/generic-numbers.html#(def._((quote._~23~25kernel)._+))" style="color: inherit">+</a></span> <span class="n">$20</span> <span class="p">(</span><span class="nb"><a href="http://docs.racket-lang.org/reference/generic-numbers.html#(def._((quote._~23~25kernel)._*))" style="color: inherit">*</a></span> <span class="n">x</span> <span class="mi">24</span><span class="p">))</span>
<span class="n">sta</span> <span class="p">(</span><span class="nb"><a href="http://docs.racket-lang.org/reference/generic-numbers.html#(def._((quote._~23~25kernel)._+))" style="color: inherit">+</a></span> <span class="n">$d000</span> <span class="p">(</span><span class="nb"><a href="http://docs.racket-lang.org/reference/generic-numbers.html#(def._((quote._~23~25kernel)._*))" style="color: inherit">*</a></span> <span class="n">x</span> <span class="mi">2</span><span class="p">))</span> <span class="c1">; x</span>
<span class="n">lda</span> <span class="n">@$D0</span>
<span class="n">sta</span> <span class="p">(</span><span class="nb"><a href="http://docs.racket-lang.org/reference/generic-numbers.html#(def._((quote._~23~25kernel)._+))" style="color: inherit">+</a></span> <span class="n">$d000</span> <span class="p">(</span><span class="nb"><a href="http://docs.racket-lang.org/reference/generic-numbers.html#(def._((quote._~23~25kernel)._+))" style="color: inherit">+</a></span> <span class="mi">1</span> <span class="p">(</span><span class="nb"><a href="http://docs.racket-lang.org/reference/generic-numbers.html#(def._((quote._~23~25kernel)._*))" style="color: inherit">*</a></span> <span class="n">x</span> <span class="mi">2</span><span class="p">)))</span> <span class="c1">; y</span>
<span class="p">})</span>
</pre></div>
</td></tr></tbody></table>
</div>
<p>This is very easy since we can use all the bits of racket and the assembler together as one.</p>
<h2 id="animation">Animation</h2>
<p>Each animation has a set number of frames which we have extracted. What we will need to do is the following:</p>
<ul>
<li>Wait for some time so the animations aren’t ridiculously fast</li>
<li>Animate each sprite by changing its sprite pointer to the next frame, or wrapping back to the start</li></ul>
<p>How do we know where each animation currently is? Well, we know which sprite we are dealing with, and we can read its current pointer value. With a bit of maths we can work out where its base pointer is, therefore which frame it is currently in, and what the pointer value will be when it is at the last frame.</p>
<div class="brush: racket">
<table class="highlighttable">
<tbody>
<tr>
<td class="linenos">
<div class="linenodiv">
<pre> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48</pre></div></td>
<td class="code">
<div class="highlight">
<pre><span></span> <span class="p">(</span><span class="k"><a href="http://docs.racket-lang.org/reference/define.html#(form._((lib._racket/private/base..rkt)._define))" style="color: inherit">define</a></span> <span class="k"><a href="http://docs.racket-lang.org/reference/Delayed_Evaluation.html#(form._((lib._racket/promise..rkt)._delay))" style="color: inherit">delay</a></span> <span class="n">$5</span><span class="p">)</span>
<span class="n">lda</span> <span class="n">@</span> <span class="k"><a href="http://docs.racket-lang.org/reference/Delayed_Evaluation.html#(form._((lib._racket/promise..rkt)._delay))" style="color: inherit">delay</a></span>
<span class="n">sta</span> <span class="n">$42</span>
<span class="n">:loop</span>
<span class="c1">; wait for the raster to hit the bottom of the screen</span>
<span class="n">lda</span> <span class="n">$d012</span>
<span class="n">cmp</span> <span class="n">@$ff</span>
<span class="n">bne</span> <span class="n">loop-</span>
<span class="c1">; decrease our delay by one</span>
<span class="n">ldx</span> <span class="n">$42</span>
<span class="n">dex</span>
<span class="c1">; if it is zero, branch out</span>
<span class="n">beq</span> <span class="n">change+</span>
<span class="c1">; otherwise store the new delay value and go back to waiting</span>
<span class="n">stx</span> <span class="n">$42</span>
<span class="n">jmp</span> <span class="n">loop-</span>
<span class="n">:change</span>
<span class="c1">; reset delay</span>
<span class="n">ldx</span> <span class="n">@</span> <span class="k"><a href="http://docs.racket-lang.org/reference/Delayed_Evaluation.html#(form._((lib._racket/promise..rkt)._delay))" style="color: inherit">delay</a></span>
<span class="n">stx</span> <span class="n">$42</span>
<span class="p">(</span><span class="k"><a href="http://docs.racket-lang.org/reference/for.html#(form._((lib._racket/private/base..rkt)._for/fold))" style="color: inherit">for/fold</a></span> <span class="p">([</span><span class="n">base-offset</span> <span class="n">$80</span><span class="p">]</span>
<span class="p">[</span><span class="n">index</span> <span class="mi">0</span><span class="p">]</span>
<span class="p">[</span><span class="n">code</span> <span class="p">(</span><span class="nb"><a href="http://docs.racket-lang.org/reference/pairs.html#(def._((quote._~23~25kernel)._list))" style="color: inherit">list</a></span><span class="p">)])</span>
<span class="p">([</span> <span class="n">s</span> <span class="n">sprites</span><span class="p">])</span>
<span class="p">(</span><span class="k"><a href="http://docs.racket-lang.org/reference/let.html#(form._((lib._racket/private/letstx-scheme..rkt)._let))" style="color: inherit">let</a></span> <span class="p">([</span><span class="n">new-code</span>
<span class="p">{</span>
<span class="c1">;load sprite pointer value</span>
<span class="n">ldx</span> <span class="p">(</span><span class="nb"><a href="http://docs.racket-lang.org/reference/generic-numbers.html#(def._((quote._~23~25kernel)._+))" style="color: inherit">+</a></span> <span class="n">$07f8</span> <span class="n">index</span><span class="p">)</span>
<span class="c1">;is it on the final frame? </span>
<span class="n">cpx</span> <span class="n">@</span><span class="p">(</span><span class="nb"><a href="http://docs.racket-lang.org/reference/generic-numbers.html#(def._((quote._~23~25kernel)._+))" style="color: inherit">+</a></span> <span class="n">base-offset</span> <span class="p">(</span><span class="nb"><a href="http://docs.racket-lang.org/reference/generic-numbers.html#(def._((quote._~23~25kernel)._-))" style="color: inherit">-</a></span> <span class="p">(</span><span class="n">sprite-data-frame-count</span> <span class="n">s</span><span class="p">)</span> <span class="mi">1</span><span class="p">))</span>
<span class="n">bne</span> <span class="n">skip+</span>
<span class="c1">;reset to its first frame</span>
<span class="n">ldx</span> <span class="n">@base-offset</span>
<span class="n">stx</span> <span class="p">(</span><span class="nb"><a href="http://docs.racket-lang.org/reference/generic-numbers.html#(def._((quote._~23~25kernel)._+))" style="color: inherit">+</a></span> <span class="n">$07f8</span> <span class="n">index</span><span class="p">)</span>
<span class="n">jmp</span> <span class="n">done+</span>
<span class="n">:skip</span>
<span class="c1">; move to next frame</span>
<span class="n">inx</span>
<span class="n">stx</span> <span class="p">(</span><span class="nb"><a href="http://docs.racket-lang.org/reference/generic-numbers.html#(def._((quote._~23~25kernel)._+))" style="color: inherit">+</a></span> <span class="n">$07f8</span> <span class="n">index</span><span class="p">)</span>
<span class="n">:done</span>
<span class="p">}])</span>
<span class="p">(</span><span class="nb"><a href="http://docs.racket-lang.org/reference/values.html#(def._((quote._~23~25kernel)._values))" style="color: inherit">values</a></span> <span class="p">(</span><span class="nb"><a href="http://docs.racket-lang.org/reference/generic-numbers.html#(def._((quote._~23~25kernel)._+))" style="color: inherit">+</a></span> <span class="n">base-offset</span> <span class="p">(</span><span class="n">sprite-data-frame-count</span> <span class="n">s</span><span class="p">))</span>
<span class="p">(</span><span class="nb"><a href="http://docs.racket-lang.org/reference/generic-numbers.html#(def._((quote._~23~25kernel)._+))" style="color: inherit">+</a></span> <span class="mi">1</span> <span class="n">index</span><span class="p">)</span>
<span class="p">(</span><span class="nb"><a href="http://docs.racket-lang.org/reference/pairs.html#(def._((quote._~23~25kernel)._cons))" style="color: inherit">cons</a></span> <span class="n">new-code</span> <span class="n">code</span><span class="p">))))</span>
<span class="n">jmp</span> <span class="n">loop-</span>
</pre></div>
</td></tr></tbody></table>
</div>
<p>Again here we are using our old friend for/fold to generate the code for us. Notice in this example, the generated code uses local labels of :skip and :done, it is able to do this since asi64 has a (fairly common) feature of being able to have many labels named the same thing. You tell it to jump to the nearest one it finds either in front or behid the current location by suffixing with + or - respectively.</p>
<h3 id="conclusion">Conclusion</h3>
<p>The full porgram has a few more features, but hopefully has exemplified the idea of mixing racket and 6502 together to help generating code. It is now very easy to dump some new files into the directory, regardless of how many frames they have, compile and run the program to see them animated in the emulator (or on the real machine!)</p>
<p>If you want to know more about how the sprites work on the C64, check out <a href="http:///www.codebase64.org">codebase</a> which is chock full of great information.</p>Asi64urn:http-www-pinksquirrellabs-com:-blog-2017-05-30-asi642017-05-30T13:37:10Z2017-05-30T13:37:10Zpezi
<p>In my last few posts, I detailed some of my experience learning <a href="http://6502.org/">6502</a> assembler for the Commodore 64. I started off using <a href="http://dasm-dillon.sourceforge.net/">DASM</a>, which seems to be quite a nice assembler, severely lacking in documentation. Then I discovered the very awesome <a href="http://www.theweb.dk/KickAssembler/Main.html#frontpage">KickAssembler</a>, which includes a full blown scripting language on top of java, lots of other very nice features, and great documentation. This made me realise what a powerful modern assembler could be like - and perhaps I could go one step further with it.</p>
<p>Asi64 extends <a href="http://racket-lang.org/">Racket</a> to become a 6502 assembler. No need for scripting languages or half baked macro systems here - you have literally all of Racket and its amazing macro system on your side. It also has direct support for <a href="http://vice-emu.sourceforge.net/">Vice</a>, a popular Commodore 64 emulator, passing your labels and breakpoints along enabling a fluid programming and debugging cycle. Hats off to the fantasic KickAssembler, I have stolen many ideas from it :)</p>
<div class="figure"><img src="http://www.pinksquirrellabs.com/img/asi/asi0.png" alt="" />
<p class="caption"></p></div>
<!-- more-->
<p>If you want to have a go, <a href="https://github.com/pezipink/Asi64">you get can asi64 from my github here</a> or the racket package manager - see the github repo for a brief rundown of syntax and getting started. Currently, this is targetted at Windows - the assembler itself should work fine on any OS but it might need a small tweak in how it executes the emulator - PRs would be welcome!</p>
<p>By way of introduction to some bits of the assembler (definetly not even touching on its potential) we will write a relatively simple demo effect, a very basic starfield. (note this is not attempting to teach 6502 or Racket!)</p>
<h2 id="starfields">Starfields!</h2>
<p>To make a simple starfield we will use the C64’s character graphics. In this mode, the VIC-II graphics chip will point at an area in memory where a character set of our design is stored. A character is defined as an 8x8 grid of pixels. In memory, this is stored sequentially as 8 bytes, where the bits of each byte represent a pixel, going from the top row of the character downwards.</p>
<p>The VIC chip goes on its merry way rendering graphics. On every 8th scanline (known as a “bad line”) it will read the next row of video memory in and work out which characters it needs to display. This is fairly simple, the video memory is somewhere of our choosing and represents the 40*25 characters laid out sequentially. Each byte in the memory represents a character index from the character set to render. This means you can have 256 characters in a set, for a 2k total of memory.</p>
<h2 id="setup">Setup</h2>
<p>First, let’s get the boring stuff out of the way, which is telling the VIC chip where to look for the video and character memory. In this example, we will use $0c00 for the video memory, $2000 for the character memory, and stick our program at $1000.</p>
<div class="brush: racket">
<table class="highlighttable">
<tbody>
<tr>
<td class="linenos">
<div class="linenodiv">
<pre>1
2
3
4
5
6
7
8
9</pre></div></td>
<td class="code">
<div class="highlight">
<pre><span></span><span class="kn">#lang </span><span class="nn">asi64</span>
<span class="p">(</span><span class="k"><a href="http://docs.racket-lang.org/reference/define.html#(form._((lib._racket/private/base..rkt)._define))" style="color: inherit">define</a></span> <span class="n">vic-control</span> <span class="n">$d018</span><span class="p">)</span>
<span class="p">(</span><span class="n">C64</span><span class="p">{</span>
<span class="n">*=</span> <span class="n">$1000</span>
<span class="n">lda</span> <span class="n">@%00111000</span>
<span class="c1">; screen at $0c00, characters at $2000</span>
<span class="n">sta</span> <span class="n">vic-control</span>
<span class="n">jmp</span> <span class="p">(</span><span class="n">here</span><span class="p">)</span> <span class="c1">;infinite loop</span>
<span class="p">})</span>
</pre></div>
</td></tr></tbody></table>
</div>
<p>$d018 is the vic register which controls where it looks for things. Here we load the value 00111000 into it which <a href="http://codebase64.org/doku.php?id=base:vicii_memory_organizing">sets things up how we want</a>. The combination of lda, sta is so common that we can get asi64 to provide us a little abstraction over it by using the <code>define-op</code> macro.</p>
<div class="brush: racket">
<table class="highlighttable">
<tbody>
<tr>
<td class="linenos">
<div class="linenodiv">
<pre> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15</pre></div></td>
<td class="code">
<div class="highlight">
<pre><span></span><span class="kn">#lang </span><span class="nn">asi64</span>
<span class="p">(</span><span class="k"><a href="http://docs.racket-lang.org/reference/define.html#(form._((lib._racket/private/base..rkt)._define))" style="color: inherit">define</a></span> <span class="n">vic-control</span> <span class="n">$d018</span><span class="p">)</span>
<span class="p">(</span><span class="k"><a href="http://docs.racket-lang.org/reference/define.html#(form._((lib._racket/private/base..rkt)._define))" style="color: inherit">define</a></span> <span class="n">black</span> <span class="mi">0</span><span class="p">)</span>
<span class="p">(</span><span class="k"><a href="http://docs.racket-lang.org/reference/define.html#(form._((lib._racket/private/base..rkt)._define))" style="color: inherit">define</a></span> <span class="n">background</span> <span class="n">$d021</span><span class="p">)</span>
<span class="p">(</span><span class="n">define-op</span> <span class="p">(</span><span class="n">mov</span> <span class="n">src</span> <span class="n">dst</span><span class="p">){</span>
<span class="n">lda</span> <span class="n">src</span>
<span class="n">sta</span> <span class="n">dst</span>
<span class="p">})</span>
<span class="p">(</span><span class="n">C64</span><span class="p">{</span>
<span class="n">*=</span> <span class="n">$1000</span>
<span class="p">(</span><span class="n">mov</span> <span class="n">@%00111000</span> <span class="n">vic-control</span><span class="p">)</span>
<span class="p">(</span><span class="n">mov</span> <span class="n">@black</span> <span class="n">background</span><span class="p">)</span>
<span class="n">jmp</span> <span class="p">(</span><span class="n">here</span><span class="p">)</span> <span class="c1">;infinite loop</span>
<span class="p">})</span>
</pre></div>
</td></tr></tbody></table>
</div>
<p>From now on I will mostly omit code that’s already been shown since assembly quickly gets large.</p>
<h2 id="character-design">Character Design</h2>
<p>What we will do is have 5 characters in a row and rotate pixels through them on each screen refresh. Therefore, character 0 we will start off with a single pixel in the centre of it. The next 4 characters will simply be blank, waiting to recieve the pixel. Then, the video memory will be tiled with chracters 0 – 5 to give the illusion of a (terrible) star field.</p>
<p>So let’s go ahead and build our characters. We know the memory starts at $2000, therefore that address represents the top row of pixels for the first character.</p>
<div class="brush: racket">
<table class="highlighttable">
<tbody>
<tr>
<td class="linenos">
<div class="linenodiv">
<pre> 1
2
3
4
5
6
7
8
9
10
11
12</pre></div></td>
<td class="code">
<div class="highlight">
<pre><span></span> <span class="n">lda</span> <span class="n">@0</span>
<span class="n">sta</span> <span class="n">$2000</span>
<span class="n">sta</span> <span class="n">$2001</span>
<span class="n">sta</span> <span class="n">$2002</span>
<span class="n">sta</span> <span class="n">$2003</span>
<span class="n">sta</span> <span class="n">$2005</span>
<span class="n">sta</span> <span class="n">$2006</span>
<span class="n">sta</span> <span class="n">$2007</span>
<span class="c1">; a single pixel in the centre!</span>
<span class="n">lda</span> <span class="n">@%00001000</span>
<span class="n">sta</span> <span class="n">$20004</span>
</pre></div>
</td></tr></tbody></table>
</div>
<p>Well, this is boring. And we still need to do the next 4 characters. As ever in assembly you have to choose between writing loops or unrolling them - space vs speed - in this case we will stick to unrolled code. I think racket can help us out here though.</p>
<div class="brush: racket">
<table class="highlighttable">
<tbody>
<tr>
<td class="linenos">
<div class="linenodiv">
<pre>1
2
3
4
5
6</pre></div></td>
<td class="code">
<div class="highlight">
<pre><span></span> <span class="n">lda</span> <span class="n">@0</span>
<span class="c1">;splat the first 5 characters </span>
<span class="p">(</span><span class="k"><a href="http://docs.racket-lang.org/reference/for.html#(form._((lib._racket/private/base..rkt)._for))" style="color: inherit">for</a></span> <span class="p">([</span><span class="n">i</span> <span class="p">(</span><span class="nb"><a href="http://docs.racket-lang.org/reference/sequences.html#(def._((lib._racket/private/base..rkt)._in-range))" style="color: inherit">in-range</a></span> <span class="p">(</span><span class="nb"><a href="http://docs.racket-lang.org/reference/generic-numbers.html#(def._((quote._~23~25kernel)._*))" style="color: inherit">*</a></span> <span class="mi">8</span> <span class="mi">5</span><span class="p">))])</span>
<span class="p">{</span><span class="n">sta</span> <span class="p">(</span><span class="nb"><a href="http://docs.racket-lang.org/reference/generic-numbers.html#(def._((quote._~23~25kernel)._+))" style="color: inherit">+</a></span> <span class="n">$2000</span> <span class="n">i</span><span class="p">)})</span>
<span class="c1">; load our humble pixel</span>
<span class="p">(</span><span class="n">mov</span> <span class="n">@%00001000</span> <span class="n">$2004</span><span class="p">)</span>
</pre></div>
</td></tr></tbody></table>
</div>
<p>Much better. Ok, so we might have written over $2004 in the loop needlessly, but whatever, that could easily be rectified. Next up is to tile the screen with the 0–4 sequence. We could unroll some code to do this, or write a loop, but there is another option. We can simply write to the video memory directly as part of the assembly process.</p>
<div class="brush: racket">
<table class="highlighttable">
<tbody>
<tr>
<td class="linenos">
<div class="linenodiv">
<pre>1
2
3</pre></div></td>
<td class="code">
<div class="highlight">
<pre><span></span> <span class="n">*=</span> <span class="n">$0c00</span> <span class="c1">;asssemble at video memory location</span>
<span class="p">(</span><span class="k"><a href="http://docs.racket-lang.org/reference/for.html#(form._((lib._racket/private/base..rkt)._for))" style="color: inherit">for</a></span> <span class="p">([</span><span class="n">i</span> <span class="p">(</span><span class="nb"><a href="http://docs.racket-lang.org/reference/sequences.html#(def._((lib._racket/private/base..rkt)._in-range))" style="color: inherit">in-range</a></span> <span class="mi">0</span> <span class="mi">200</span><span class="p">)])</span>
<span class="p">(</span><span class="n">data</span> <span class="mi">0</span> <span class="mi">1</span> <span class="mi">2</span> <span class="mi">3</span> <span class="mi">4</span><span class="p">))</span>
</pre></div>
</td></tr></tbody></table>
</div>
<p>Don’t know about you but I am already bored of keep writing this for .. in-range stuff. Let’s knock up a quick macro to do it for us.</p>
<div class="brush: racket">
<table class="highlighttable">
<tbody>
<tr>
<td class="linenos">
<div class="linenodiv">
<pre>1
2
3
4
5
6
7</pre></div></td>
<td class="code">
<div class="highlight">
<pre><span></span><span class="p">(</span><span class="k"><a href="http://docs.racket-lang.org/reference/define.html#(form._((lib._racket/private/base..rkt)._define-syntax))" style="color: inherit">define-syntax</a></span> <span class="p">(</span><span class="n">fori</span> <span class="n">stx</span><span class="p">)</span>
<span class="p">(</span><span class="n"><a href="http://docs.racket-lang.org/syntax/Parsing_Syntax.html#(form._((lib._syntax/parse..rkt)._syntax-parse))" style="color: inherit">syntax-parse</a></span> <span class="n">stx</span>
<span class="p">([</span><span class="k"><a href="http://docs.racket-lang.org/reference/stx-patterns.html#(form._((lib._racket/private/stxcase-scheme..rkt).__))" style="color: inherit">_</a></span> <span class="n">e</span> <span class="n">f</span><span class="p">]</span>
<span class="c1">; breaking hygeine here, very sorry</span>
<span class="p">(</span><span class="k"><a href="http://docs.racket-lang.org/reference/stx-patterns.html#(form._((lib._racket/private/stxcase-scheme..rkt)._with-syntax))" style="color: inherit">with-syntax</a></span> <span class="p">([</span><span class="n">f2</span> <span class="p">(</span><span class="nb"><a href="http://docs.racket-lang.org/reference/stxops.html#(def._((quote._~23~25kernel)._syntax-~3edatum))" style="color: inherit">syntax->datum</a></span> <span class="o">#'</span><span class="n">f</span><span class="p">)])</span>
<span class="o">#'</span><span class="p">(</span><span class="k"><a href="http://docs.racket-lang.org/reference/for.html#(form._((lib._racket/private/base..rkt)._for))" style="color: inherit">for</a></span> <span class="p">([</span><span class="n">i</span> <span class="p">(</span><span class="nb"><a href="http://docs.racket-lang.org/reference/sequences.html#(def._((lib._racket/private/base..rkt)._in-range))" style="color: inherit">in-range</a></span> <span class="mi">0</span> <span class="n">e</span><span class="p">)])</span>
<span class="n">f2</span><span class="p">)))))</span>
</pre></div>
</td></tr></tbody></table>
</div>
<p>Yes, this is a terrible macro! It breaks hygeine and won’t even work in some cases. I am just putting it here to show that you can!</p>
<p>Now we can write</p>
<div class="brush: racket">
<table class="highlighttable">
<tbody>
<tr>
<td class="linenos">
<div class="linenodiv">
<pre>1
2
3
4
5</pre></div></td>
<td class="code">
<div class="highlight">
<pre><span></span> <span class="n">lda</span> <span class="n">@0</span>
<span class="c1">;splat the first 5 characters </span>
<span class="p">(</span><span class="n">fori</span> <span class="p">(</span><span class="nb"><a href="http://docs.racket-lang.org/reference/generic-numbers.html#(def._((quote._~23~25kernel)._*))" style="color: inherit">*</a></span> <span class="mi">8</span> <span class="mi">5</span><span class="p">)</span> <span class="p">{</span><span class="n">sta</span> <span class="p">(</span><span class="nb"><a href="http://docs.racket-lang.org/reference/generic-numbers.html#(def._((quote._~23~25kernel)._+))" style="color: inherit">+</a></span> <span class="n">$2000</span> <span class="n">i</span><span class="p">)})</span>
<span class="c1">; load our humble pixel</span>
<span class="p">(</span><span class="n">mov</span> <span class="n">@%00001000</span> <span class="n">$2004</span><span class="p">)</span>
</pre></div>
</td></tr></tbody></table>
</div>
<p>and</p>
<div class="brush: racket">
<table class="highlighttable">
<tbody>
<tr>
<td class="linenos">
<div class="linenodiv">
<pre>1
2</pre></div></td>
<td class="code">
<div class="highlight">
<pre><span></span> <span class="n">*=</span> <span class="n">$0c00</span> <span class="c1">;asssemble at video memory location</span>
<span class="p">(</span><span class="n">fori</span> <span class="mi">200</span> <span class="p">(</span><span class="n">data</span> <span class="mi">0</span> <span class="mi">1</span> <span class="mi">2</span> <span class="mi">3</span> <span class="mi">4</span><span class="p">))</span>
</pre></div>
</td></tr></tbody></table>
</div>
<p>Rawr!</p>
<div class="figure"><img src="http://www.pinksquirrellabs.com/img/asi/asi1.png" alt="" />
<p class="caption"></p></div>
<h2 id="move-it">Move it!</h2>
<p>I’ll admit this looks like a pretty terrible star field. Even when moving it will look bad, but one problem at a time. Let’s get it moving! The basic operation will be to rotate $2004 to the right. This will move the bit along one place, and if it falls off the end of the byte it will end up in the processor’s carry bit. From there, if we rotate right the same row-byte of the next character ($200c) the bit will move from the carry into the most signficant bit of the next character’s byte. we can repeat this process, with a special case for the last character since it needs to wrap around back to the first one if the carry is set.</p>
<div class="brush: racket">
<table class="highlighttable">
<tbody>
<tr>
<td class="linenos">
<div class="linenodiv">
<pre>1
2
3
4
5
6
7
8</pre></div></td>
<td class="code">
<div class="highlight">
<pre><span></span><span class="n">:update_starfield</span>
<span class="n">clc</span> <span class="c1">; clear carry bit</span>
<span class="c1">; ror our little guy through memory</span>
<span class="p">(</span><span class="n">fori</span> <span class="mi">5</span> <span class="p">{</span><span class="n">ror</span> <span class="p">(</span><span class="nb"><a href="http://docs.racket-lang.org/reference/generic-numbers.html#(def._((quote._~23~25kernel)._+))" style="color: inherit">+</a></span> <span class="n">$2004</span> <span class="p">(</span><span class="nb"><a href="http://docs.racket-lang.org/reference/generic-numbers.html#(def._((quote._~23~25kernel)._*))" style="color: inherit">*</a></span> <span class="n">i</span> <span class="mi">8</span><span class="p">))})</span>
<span class="n">bcc</span> <span class="n">end+</span>
<span class="n">ror</span> <span class="n">$2004</span>
<span class="n">:end</span>
<span class="n">rts</span>
</pre></div>
</td></tr></tbody></table>
</div>
<p>We will call this subroutine once each video frame. To achieve this we will burn cycles until the raster hits the bottom of the screen-ish (since we don’t want to update whilst the VIC is rendering!), call this procedure, and then wait again. Usually you’d do this with raster interrupts since obviously sitting waiting for the screen means you can’t do anything else, but it will suffice for this example.</p>
<div class="brush: racket">
<table class="highlighttable">
<tbody>
<tr>
<td class="linenos">
<div class="linenodiv">
<pre> 1
2
3
4
5
6
7
8
9
10</pre></div></td>
<td class="code">
<div class="highlight">
<pre><span></span> <span class="n">lda</span> <span class="n">@$ff</span>
<span class="n">:loop</span> <span class="n">cmp</span> <span class="n">$d012</span> <span class="c1">; wait for line 256</span>
<span class="n">bne</span> <span class="n">loop-</span>
<span class="n">jsr</span> <span class="n">update_starfield+</span>
<span class="c1">; do nothing for a while so </span>
<span class="c1">; this doesn't trigger more than</span>
<span class="c1">; once on the same frame!</span>
<span class="p">(</span><span class="n">fori</span> <span class="mi">100</span> <span class="p">{</span><span class="n">nop</span><span class="p">})</span>
<span class="n">lda</span> <span class="n">@$ff</span>
<span class="n">jmp</span> <span class="n">loop-</span>
</pre></div>
</td></tr></tbody></table>
</div>
<div class="figure"><img src="http://www.pinksquirrellabs.com/img/asi/asi2.gif" alt="" />
<p class="caption"></p></div>
<h2 id="making-it-not-terrible">Making it not terrible</h2>
<p>As amazing as the single pixel going across the screen in a lockstep obviously repeated pattern is, we can probably do better. The obvious problems are:</p>
<ul>
<li>There is only one lonely pixel</li>
<li>The pixels should travel at different speeds to produce a parallax effect</li>
<li>The tiling should be broken up into different perumations on each row</li></ul>
<p>If we had more pixels, it would mean more RORing of the relevant bytes. To make them move faster, we’d have to repeat the whole ROR cycle more than once. Clearly, this quickly escalates into tons of boring and hard to change code. Instead, we will get racket to help us out by writing a function that can generate a starfield update to our specifications. We will pass it a memory location of the character set, the amount of characters to rotate through, a list of tuples that indicate which rows of the character need rotating and at what speed.</p>
<div class="brush: racket">
<table class="highlighttable">
<tbody>
<tr>
<td class="linenos">
<div class="linenodiv">
<pre> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22</pre></div></td>
<td class="code">
<div class="highlight">
<pre><span></span><span class="p">(</span><span class="k"><a href="http://docs.racket-lang.org/reference/define-struct.html#(form._((lib._racket/private/base..rkt)._struct))" style="color: inherit">struct</a></span> <span class="n">starbank</span> <span class="p">(</span><span class="n"><a href="http://docs.racket-lang.org/xml/index.html#(def._((lib._xml/main..rkt)._location))" style="color: inherit">location</a></span> <span class="n">len</span> <span class="n">rows</span><span class="p">))</span>
<span class="p">(</span><span class="k"><a href="http://docs.racket-lang.org/reference/define.html#(form._((lib._racket/private/base..rkt)._define))" style="color: inherit">define</a></span> <span class="p">(</span><span class="n">generate-starfield-updates-1</span> <span class="n">starbank</span><span class="p">)</span>
<span class="c1">;location - charset location where the first starfield char is</span>
<span class="c1">;len - how many chars to ROL through</span>
<span class="c1">;rows - which rows of the character contain stars (no point ROLing them otherwise)</span>
<span class="p">(</span><span class="k"><a href="http://docs.racket-lang.org/reference/define.html#(form._((lib._racket/private/base..rkt)._define))" style="color: inherit">define</a></span> <span class="p">(</span><span class="n">char-index</span> <span class="n">i</span><span class="p">)</span>
<span class="p">(</span><span class="nb"><a href="http://docs.racket-lang.org/reference/generic-numbers.html#(def._((quote._~23~25kernel)._+))" style="color: inherit">+</a></span> <span class="p">(</span><span class="n">starbank-location</span> <span class="n">starbank</span><span class="p">)</span> <span class="p">(</span><span class="nb"><a href="http://docs.racket-lang.org/reference/generic-numbers.html#(def._((quote._~23~25kernel)._*))" style="color: inherit">*</a></span> <span class="mi">8</span> <span class="n">i</span><span class="p">)))</span>
<span class="p">(</span><span class="k"><a href="http://docs.racket-lang.org/reference/for.html#(form._((lib._racket/private/base..rkt)._for))" style="color: inherit">for</a></span> <span class="p">([</span><span class="n">row</span> <span class="p">(</span><span class="n">starbank-rows</span> <span class="n">starbank</span><span class="p">)])</span>
<span class="c1">;extract the row number and speed</span>
<span class="p">(</span><span class="k"><a href="http://docs.racket-lang.org/reference/let.html#(form._((lib._racket/private/letstx-scheme..rkt)._let))" style="color: inherit">let</a></span> <span class="p">([</span><span class="n">row</span> <span class="p">(</span><span class="nb"><a href="http://docs.racket-lang.org/reference/pairs.html#(def._((quote._~23~25kernel)._car))" style="color: inherit">car</a></span> <span class="n">row</span><span class="p">)]</span>
<span class="p">[</span><span class="n">speed</span> <span class="p">(</span><span class="nb"><a href="http://docs.racket-lang.org/reference/pairs.html#(def._((quote._~23~25kernel)._cadr))" style="color: inherit">cadr</a></span> <span class="n">row</span><span class="p">)])</span>
<span class="p">(</span><span class="k"><a href="http://docs.racket-lang.org/reference/for.html#(form._((lib._racket/private/base..rkt)._for))" style="color: inherit">for</a></span> <span class="p">([</span><span class="n">s</span> <span class="p">(</span><span class="nb"><a href="http://docs.racket-lang.org/reference/sequences.html#(def._((lib._racket/private/base..rkt)._in-range))" style="color: inherit">in-range</a></span> <span class="mi">0</span> <span class="n">speed</span><span class="p">)])</span>
<span class="c1">;repeat the ror cycle for speed times</span>
<span class="p">{</span><span class="n">clc</span> <span class="c1">; clear the carry bit!</span>
<span class="p">(</span><span class="k"><a href="http://docs.racket-lang.org/reference/for.html#(form._((lib._racket/private/base..rkt)._for))" style="color: inherit">for</a></span> <span class="p">([</span><span class="n">char</span> <span class="p">(</span><span class="nb"><a href="http://docs.racket-lang.org/reference/sequences.html#(def._((lib._racket/private/base..rkt)._in-range))" style="color: inherit">in-range</a></span> <span class="mi">0</span> <span class="p">(</span><span class="n">starbank-len</span> <span class="n">starbank</span><span class="p">))])</span>
<span class="c1">;now we just ror each character in turn</span>
<span class="p">{</span><span class="n">ror</span> <span class="p">(</span><span class="nb"><a href="http://docs.racket-lang.org/reference/generic-numbers.html#(def._((quote._~23~25kernel)._+))" style="color: inherit">+</a></span> <span class="p">(</span><span class="n">char-index</span> <span class="n">char</span><span class="p">)</span> <span class="n">row</span><span class="p">)})</span>
<span class="c1">; special wrap-around case</span>
<span class="n">bcc</span> <span class="n">end+</span>
<span class="n">ror</span> <span class="p">(</span><span class="nb"><a href="http://docs.racket-lang.org/reference/generic-numbers.html#(def._((quote._~23~25kernel)._+))" style="color: inherit">+</a></span> <span class="p">(</span><span class="n">char-index</span> <span class="mi">0</span><span class="p">)</span> <span class="n">row</span><span class="p">)</span>
<span class="n">:end</span> <span class="n">rts</span> <span class="p">}))))</span>
</pre></div>
</td></tr></tbody></table>
</div>
<p>This is pretty cool. It basically writes the same code as we did manually last time except now it can do it for multiple rows at different speeds. This makes it really easy to tinker with the values to produce a nice looking starfield.</p>
<p>What if we wanted to scroll the stars left instead of right? The basic principle is the same, we still need to rotate the pixels through memory, except we must rotate left, the wrap around goes from the first to the last character, and the characters must be processed in reverse. Since racket is allowing us to conditionally generate assembly code, we can interleave this as an option into our generator</p>
<div class="brush: racket">
<table class="highlighttable">
<tbody>
<tr>
<td class="linenos">
<div class="linenodiv">
<pre> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24</pre></div></td>
<td class="code">
<div class="highlight">
<pre><span></span><span class="p">(</span><span class="k"><a href="http://docs.racket-lang.org/reference/define-struct.html#(form._((lib._racket/private/base..rkt)._struct))" style="color: inherit">struct</a></span> <span class="n">starbank</span> <span class="p">(</span><span class="n"><a href="http://docs.racket-lang.org/xml/index.html#(def._((lib._xml/main..rkt)._location))" style="color: inherit">location</a></span> <span class="n">len</span> <span class="n">rows</span><span class="p">))</span>
<span class="p">(</span><span class="k"><a href="http://docs.racket-lang.org/reference/define.html#(form._((lib._racket/private/base..rkt)._define))" style="color: inherit">define</a></span> <span class="p">(</span><span class="n">generate-starfield-updates</span> <span class="n">starbank</span> <span class="n">going-right?</span><span class="p">)</span>
<span class="p">(</span><span class="k"><a href="http://docs.racket-lang.org/reference/define.html#(form._((lib._racket/private/base..rkt)._define))" style="color: inherit">define</a></span> <span class="p">(</span><span class="n">char-index</span> <span class="n">i</span><span class="p">)</span>
<span class="p">(</span><span class="nb"><a href="http://docs.racket-lang.org/reference/generic-numbers.html#(def._((quote._~23~25kernel)._+))" style="color: inherit">+</a></span> <span class="p">(</span><span class="n">starbank-location</span> <span class="n">starbank</span><span class="p">)</span> <span class="p">(</span><span class="nb"><a href="http://docs.racket-lang.org/reference/generic-numbers.html#(def._((quote._~23~25kernel)._*))" style="color: inherit">*</a></span> <span class="mi">8</span> <span class="n">i</span><span class="p">)))</span>
<span class="p">(</span><span class="k"><a href="http://docs.racket-lang.org/reference/for.html#(form._((lib._racket/private/base..rkt)._for))" style="color: inherit">for</a></span> <span class="p">([</span><span class="n">row</span> <span class="p">(</span><span class="n">starbank-rows</span> <span class="n">starbank</span><span class="p">)])</span>
<span class="p">(</span><span class="k"><a href="http://docs.racket-lang.org/reference/let.html#(form._((lib._racket/private/letstx-scheme..rkt)._let))" style="color: inherit">let</a></span> <span class="p">([</span><span class="n">row</span> <span class="p">(</span><span class="nb"><a href="http://docs.racket-lang.org/reference/pairs.html#(def._((quote._~23~25kernel)._car))" style="color: inherit">car</a></span> <span class="n">row</span><span class="p">)]</span>
<span class="p">[</span><span class="n">speed</span> <span class="p">(</span><span class="nb"><a href="http://docs.racket-lang.org/reference/pairs.html#(def._((quote._~23~25kernel)._cadr))" style="color: inherit">cadr</a></span> <span class="n">row</span><span class="p">)])</span>
<span class="p">(</span><span class="k"><a href="http://docs.racket-lang.org/reference/for.html#(form._((lib._racket/private/base..rkt)._for))" style="color: inherit">for</a></span> <span class="p">([</span><span class="n">s</span> <span class="p">(</span><span class="nb"><a href="http://docs.racket-lang.org/reference/sequences.html#(def._((lib._racket/private/base..rkt)._in-range))" style="color: inherit">in-range</a></span> <span class="mi">0</span> <span class="n">speed</span><span class="p">)])</span>
<span class="p">{</span><span class="n">clc</span>
<span class="p">(</span><span class="k"><a href="http://docs.racket-lang.org/reference/for.html#(form._((lib._racket/private/base..rkt)._for))" style="color: inherit">for</a></span> <span class="p">([</span><span class="n">char</span> <span class="p">(</span><span class="k"><a href="http://docs.racket-lang.org/reference/if.html#(form._((quote._~23~25kernel)._if))" style="color: inherit">if</a></span> <span class="n">going-right?</span>
<span class="p">(</span><span class="nb"><a href="http://docs.racket-lang.org/reference/sequences.html#(def._((lib._racket/private/base..rkt)._in-range))" style="color: inherit">in-range</a></span> <span class="mi">0</span> <span class="p">(</span><span class="n">starbank-len</span> <span class="n">starbank</span><span class="p">))</span>
<span class="p">(</span><span class="nb"><a href="http://docs.racket-lang.org/reference/sequences.html#(def._((lib._racket/private/base..rkt)._in-range))" style="color: inherit">in-range</a></span> <span class="p">(</span><span class="nb"><a href="http://docs.racket-lang.org/reference/generic-numbers.html#(def._((quote._~23~25kernel)._-))" style="color: inherit">-</a></span> <span class="p">(</span><span class="n">starbank-len</span> <span class="n">starbank</span><span class="p">)</span> <span class="mi">1</span><span class="p">)</span> <span class="mi">-1</span> <span class="mi">-1</span><span class="p">))])</span>
<span class="p">(</span><span class="k"><a href="http://docs.racket-lang.org/reference/if.html#(form._((quote._~23~25kernel)._if))" style="color: inherit">if</a></span> <span class="n">going-right?</span>
<span class="p">{</span><span class="n">ror</span> <span class="p">(</span><span class="nb"><a href="http://docs.racket-lang.org/reference/generic-numbers.html#(def._((quote._~23~25kernel)._+))" style="color: inherit">+</a></span> <span class="p">(</span><span class="n">char-index</span> <span class="n">char</span><span class="p">)</span> <span class="n">row</span><span class="p">)}</span>
<span class="p">{</span><span class="n">rol</span> <span class="p">(</span><span class="nb"><a href="http://docs.racket-lang.org/reference/generic-numbers.html#(def._((quote._~23~25kernel)._+))" style="color: inherit">+</a></span> <span class="p">(</span><span class="n">char-index</span> <span class="n">char</span><span class="p">)</span> <span class="n">row</span><span class="p">)}))</span>
<span class="c1">;finally wrap around if the carry is et</span>
<span class="n">bcc</span> <span class="n">end+</span>
<span class="p">(</span><span class="k"><a href="http://docs.racket-lang.org/reference/if.html#(form._((quote._~23~25kernel)._if))" style="color: inherit">if</a></span> <span class="n">going-right?</span>
<span class="p">{</span><span class="n">ror</span> <span class="p">(</span><span class="nb"><a href="http://docs.racket-lang.org/reference/generic-numbers.html#(def._((quote._~23~25kernel)._+))" style="color: inherit">+</a></span> <span class="p">(</span><span class="n">char-index</span> <span class="mi">0</span><span class="p">)</span> <span class="n">row</span><span class="p">)}</span>
<span class="p">{</span><span class="n">rol</span> <span class="p">(</span><span class="nb"><a href="http://docs.racket-lang.org/reference/generic-numbers.html#(def._((quote._~23~25kernel)._+))" style="color: inherit">+</a></span> <span class="p">(</span><span class="n">char-index</span> <span class="p">(</span><span class="nb"><a href="http://docs.racket-lang.org/reference/generic-numbers.html#(def._((quote._~23~25kernel)._-))" style="color: inherit">-</a></span> <span class="p">(</span><span class="n">starbank-len</span> <span class="n">starbank</span><span class="p">)</span> <span class="mi">1</span><span class="p">))</span> <span class="n">row</span><span class="p">)})</span>
<span class="n">:end</span><span class="p">}))))</span>
</pre></div>
</td></tr></tbody></table>
</div>
<p>It’s pretty much the same code, it just produces rols instead of rors and processes the things backwards.</p>
<p>You could extend this to also create the chracter memory for you, and have it return two functions that you can call and label somewhere in the program, one for generating and the other for updating. You can probably see how this could quickly become a build-your-own-tailored-compiler-kit if you wanted it to.</p>
<p>The last part was to re-arrange to video memory so each row has a different permuatation of the 0 1 2 3 4 sequence. There’s a number of ways we could do this of course. Randomness doens’t work very well, so I messed around a bit until I found a good pattern, and hardcoded it at compile-time.</p>
<div class="brush: racket">
<table class="highlighttable">
<tbody>
<tr>
<td class="linenos">
<div class="linenodiv">
<pre> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17</pre></div></td>
<td class="code">
<div class="highlight">
<pre><span></span> <span class="n">*=</span> <span class="n">$0c00</span> <span class="c1">;asssemble at video memory location</span>
<span class="p">(</span><span class="k"><a href="http://docs.racket-lang.org/reference/let.html#(form._((lib._racket/private/letstx-scheme..rkt)._let))" style="color: inherit">let</a></span> <span class="p">([</span><span class="n">perm1</span> <span class="o">'</span><span class="p">(</span><span class="mi">0</span> <span class="mi">1</span> <span class="mi">2</span> <span class="mi">3</span> <span class="mi">4</span><span class="p">)]</span>
<span class="p">[</span><span class="n">perm2</span> <span class="o">'</span><span class="p">(</span><span class="mi">4</span> <span class="mi">0</span> <span class="mi">1</span> <span class="mi">2</span> <span class="mi">3</span><span class="p">)]</span>
<span class="p">[</span><span class="n">perm3</span> <span class="o">'</span><span class="p">(</span><span class="mi">3</span> <span class="mi">4</span> <span class="mi">0</span> <span class="mi">1</span> <span class="mi">2</span><span class="p">)]</span>
<span class="p">[</span><span class="n">perm4</span> <span class="o">'</span><span class="p">(</span><span class="mi">2</span> <span class="mi">3</span> <span class="mi">4</span> <span class="mi">0</span> <span class="mi">1</span><span class="p">)]</span>
<span class="p">[</span><span class="n">order</span> <span class="o">'</span><span class="p">(</span><span class="mi">1</span> <span class="mi">4</span> <span class="mi">2</span> <span class="mi">1</span> <span class="mi">3</span> <span class="mi">1</span> <span class="mi">2</span> <span class="mi">4</span>
<span class="mi">1</span> <span class="mi">4</span> <span class="mi">2</span> <span class="mi">1</span> <span class="mi">3</span> <span class="mi">1</span> <span class="mi">2</span> <span class="mi">4</span>
<span class="mi">1</span> <span class="mi">4</span> <span class="mi">2</span> <span class="mi">1</span> <span class="mi">3</span> <span class="mi">1</span> <span class="mi">2</span> <span class="mi">4</span>
<span class="mi">1</span><span class="p">)])</span>
<span class="p">(</span><span class="k"><a href="http://docs.racket-lang.org/reference/for.html#(form._((lib._racket/private/base..rkt)._for))" style="color: inherit">for</a></span> <span class="p">([</span><span class="n">next</span> <span class="n">order</span><span class="p">])</span>
<span class="p">(</span><span class="k"><a href="http://docs.racket-lang.org/reference/for.html#(form._((lib._racket/private/base..rkt)._for))" style="color: inherit">for</a></span><span class="p">([</span><span class="nb"><a href="http://docs.racket-lang.org/reference/pairs.html#(def._((lib._racket/list..rkt)._count))" style="color: inherit">count</a></span> <span class="p">(</span><span class="nb"><a href="http://docs.racket-lang.org/reference/sequences.html#(def._((lib._racket/private/base..rkt)._in-range))" style="color: inherit">in-range</a></span> <span class="mi">8</span><span class="p">)])</span>
<span class="p">(</span><span class="k"><a href="http://docs.racket-lang.org/reference/case.html#(form._((lib._racket/private/more-scheme..rkt)._case))" style="color: inherit">case</a></span> <span class="n">next</span>
<span class="p">[(</span><span class="mi">1</span><span class="p">)</span> <span class="p">(</span><span class="n">data</span> <span class="n">perm1</span><span class="p">)]</span>
<span class="p">[(</span><span class="mi">2</span><span class="p">)</span> <span class="p">(</span><span class="n">data</span> <span class="n">perm2</span><span class="p">)]</span>
<span class="p">[(</span><span class="mi">3</span><span class="p">)</span> <span class="p">(</span><span class="n">data</span> <span class="n">perm3</span><span class="p">)]</span>
<span class="p">[(</span><span class="mi">4</span><span class="p">)</span> <span class="p">(</span><span class="n">data</span> <span class="n">perm4</span><span class="p">)]))))</span>
</pre></div>
</td></tr></tbody></table>
</div>
<p>Omitting the code to stick some more pixels in our character set,our new update code becomes</p>
<div class="brush: racket">
<table class="highlighttable">
<tbody>
<tr>
<td class="linenos">
<div class="linenodiv">
<pre> 1
2
3
4
5
6
7
8
9
10
11
12
13
14</pre></div></td>
<td class="code">
<div class="highlight">
<pre><span></span> <span class="p">(</span><span class="k"><a href="http://docs.racket-lang.org/reference/define.html#(form._((lib._racket/private/base..rkt)._define))" style="color: inherit">define</a></span> <span class="n">sb1</span> <span class="p">(</span><span class="n">starbank</span> <span class="n">$2000</span> <span class="mi">5</span> <span class="o">'</span><span class="p">((</span><span class="mi">1</span> <span class="mi">1</span><span class="p">)</span> <span class="p">(</span><span class="mi">3</span> <span class="mi">2</span><span class="p">)</span> <span class="p">(</span><span class="mi">5</span> <span class="mi">4</span><span class="p">))))</span>
<span class="n">lda</span> <span class="n">@$ff</span>
<span class="n">:loop</span> <span class="n">cmp</span> <span class="n">$d012</span> <span class="c1">; wait for line 256</span>
<span class="n">bne</span> <span class="n">loop-</span>
<span class="n">jsr</span> <span class="n">update-starfield</span>
<span class="c1">; do nothing for a while so </span>
<span class="c1">; this doesn't trigger more than</span>
<span class="c1">; once on the same frame!</span>
<span class="p">(</span><span class="n">fori</span> <span class="mi">100</span> <span class="p">{</span><span class="n">nop</span><span class="p">})</span>
<span class="n">lda</span> <span class="n">@$ff</span>
<span class="n">jmp</span> <span class="n">loop-</span>
<span class="n">:update-starfield</span>
<span class="p">(</span><span class="n">generate-starfield-updates</span> <span class="n">sb1</span> <span class="no">#t</span><span class="p">)</span>
<span class="n">rts</span>
</pre></div>
</td></tr></tbody></table>
</div>
<p>The final result, I think you will agree is much better looking, even if it is still a bit rubbish! (actually, the gif is kinda terrible, it looks a lot better on the emulator and much better still on the real thing!)</p>
<div class="figure"><img src="http://www.pinksquirrellabs.com/img/asi/asi3.gif" alt="" />
<p class="caption"></p></div>
<h2 id="conclusion">Conclusion</h2>
<p>Asi64 brings racket and 6502 together in a (hopefully!) glorious fusion. It is by no means finished, and will likely be rewritten again at least one more time. This is basically my first proper Racket project so I still have much to learn, but it is a lot more fun to program the Commodore 64 now ! (You could also use this to program the NES!). Comments are welcome.</p>
<p>Here is a picture of the lovely starfield running on the real hardware :)</p>
<div class="figure"><img src="http://www.pinksquirrellabs.com/img/asi/asi4.png" alt="" />
<p class="caption"></p></div>
<p>The full code for this example can be found at the github repo <a href="https://github.com/pezipink/asi64/blob/master/samples/starfield.rkt">here</a></p>C64 Programming - Invader Fractal #2urn:http-www-pinksquirrellabs-com:-blog-2017-03-31-c64-programming-invader-fractal-22017-03-31T11:23:17Z2017-03-31T11:23:17Zpezi
<p>In the <a href="http://pinksquirrellabs.com/blog/2017/02/28/c64-programming-invader-fractal/">last post</a> we discovered how to decode 15-bit symmetric invaders into a chacrater set. This time around we will make them fractal!</p>
<p>The invaders from the last post occupy exactly one character each. The aim is to now select an invader at random, and then draw it one size bigger, using other random invaders as its “pixels” like this</p>
<div class="figure"><img src="http://www.pinksquirrellabs.com/img/invaders/7.png" alt="" />
<p class="caption"></p></div>
<p>Then, the process can be repeated again, drawing an even bigger invader which is formed by drawing even bigger “pixels” which are composed of the size 2 invaders, like this!</p>
<div class="figure"><img src="http://www.pinksquirrellabs.com/img/invaders/8.png" alt="" />
<p class="caption"></p></div>
<!-- more-->
<h3 id="a-plan-of-action">A plan of action</h3>
<p>Writing in ASM is very different to high level languages. You can’t simply jump in and start writing code with only a very loose idea, at least some stuff has to be planned out up ahead if you want to get anywhere without wasting time. (Well, I guess with more experience this get easier … )</p>
<p>In order to draw the first level of invader, we are going to need the following high-level elements</p>
<ul>
<li>A way of selecting a random invader and calculating where in character set memory it sits</li>
<li>An algorithm that takes each bit of each row of the invader in turn, and draws another invader into video memory if the bit is set</li>
<li>Another alogrithm that does a very similar thing to the previous one, on a bigger scale</li></ul>
<p>I have a small not-very-random number generator routine originally called <code>rng</code>. Its implementation is out of the scope of this post, but you can call it as follows</p>
<div class="brush: ca65">
<table class="highlighttable">
<tbody>
<tr>
<td class="linenos">
<div class="linenodiv">
<pre>1</pre></div></td>
<td class="code">
<div class="highlight">
<pre><span></span><span class="k">jsr</span> <span class="n">rng</span>
</pre></div>
</td></tr></tbody></table>
</div>
<p><code>jsr</code> is an opcode that jumps to the named routine, after first pushing the current location on the stack, then when it encounters an <code>rts</code> it returns execution to the calling code. The <code>rng</code> routine will leave a not particularly random number inside the accumulator ready for use.</p>
<h3 id="choosing-an-invader">Choosing an invader</h3>
<p>The program I wrote populates a character set at memory location $2000 with 254 sort of unique invaders, using the technique described in the previous post and the <code>rng</code> routine. I defined characters 0 and 1 in the set manually, where 0 is blank and 1 has every pixel set. A character in memory is layed out as 8*8 contiguous bytes, each one represeting the pixels that are switched on for each row. Therefore, the location in memory of character <code>n</code> is <code>$2000 + (n * 8)</code>. The 6502 does not have any multiplication instructions - although you can of course write your own by using a combination of adding and bit shifting, which would be fast. However, for this task we will just write a loop that adds 8 n times.</p>
<div class="brush: ca65">
<table class="highlighttable">
<tbody>
<tr>
<td class="linenos">
<div class="linenodiv">
<pre> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20</pre></div></td>
<td class="code">
<div class="highlight">
<pre><span></span><span class="nl">draw_invader:</span> <span class="n">subroutine</span>
<span class="c1">; store the address at $3E and 3F</span>
<span class="c1">; starting at $2000 where the character memory begins</span>
<span class="k">lda</span> <span class="p">#</span><span class="mh">$0</span>
<span class="k">sta</span> <span class="mh">$3E</span>
<span class="k">lda</span> <span class="p">#</span><span class="mh">$20</span>
<span class="k">sta</span> <span class="mh">$3F</span>
<span class="c1">;; pick random invader number</span>
<span class="k">jsr</span> <span class="n">rng</span>
<span class="k">sta</span> <span class="mh">$3D</span>
<span class="c1">;; add 8 for each count</span>
<span class="kp">.calc_address</span>
<span class="k">clc</span>
<span class="k">lda</span> <span class="p">#</span><span class="mi">8</span>
<span class="k">adc</span> <span class="mh">$3E</span>
<span class="k">sta</span> <span class="mh">$3E</span>
<span class="k">bcc</span> <span class="o">*+</span><span class="mi">4</span>
<span class="k">inc</span> <span class="mh">$3F</span>
<span class="k">dec</span> <span class="mh">$3D</span>
<span class="k">bne</span> <span class="kp">.calc_address</span>
</pre></div>
</td></tr></tbody></table>
</div>
<p>This is fairly straight forward - the address is 16 bits, and we store it in location $3E and $3F in the zero-page (an arbitary choice) so that it can be used with the indirect addressing mode later, as discussed in the previous article. A random number from 0–255 is generated and stored in $3D, and then we enter a loop that adds 8 to the address, decreases $3D and loops until $3D is zero. One new thing here is the operand following the <code>bcc</code> instruction, <code>*+4</code>. The * tells the assembler to use the current location, which you can then offset by some number. Effectively this skips the <code>inc $3F</code> instruction, which saves having to use a label to do it. Oviously, this technique is error prone and hard to read, but it makes sense for stuff you have to do all the time, like this addition of an 8 bit number to a 16 bit one. The “subroutine” keyword tells the assembler to uniquely name any labels following it that start with a ".", this is so you don’t have to keep dreaming up globally unique label names for your different routines.</p>
<h3 id="drawing-an-invader">Drawing an Invader</h3>
<p>Now we have the correct address, we can work out how to draw the invader. The C64 screen is 40*25 characters. A character is 8*8 pixels, although the invaders are only actually using 5*5 of them, which will be useful later since it means we can fit one massive invader on the screen, just!</p>
<div class="brush: ca65">
<table class="highlighttable">
<tbody>
<tr>
<td class="linenos">
<div class="linenodiv">
<pre>1
2
3
4</pre></div></td>
<td class="code">
<div class="highlight">
<pre><span></span> <span class="k">lda</span> <span class="p">#</span><span class="mh">$00</span>
<span class="k">sta</span> <span class="mh">$44</span>
<span class="k">lda</span> <span class="p">#</span><span class="mh">$04</span>
<span class="k">sta</span> <span class="mh">$45</span>
</pre></div>
</td></tr></tbody></table>
</div>
<p>The video memory starts at $0400, and clearly we are going to need to keep track of where we are in order to draw the invader, so another 16 bit address ($0400) is placed in the zero-page at locations $44 and $45 (more random locations).</p>
<p>Now the algorithm can begin:</p>
<ul>
<li>Read the current byte of the invader</li>
<li>For each bit of the byte, determine if it is set</li>
<li>If it is, pick a random invader character and store it at the current video memory location</li>
<li>Increase the video location by one</li>
<li>At the end of the byte, move down to the next row in video memory, at column 0</li>
<li>Loop 5 times</li></ul>
<div class="brush: ca65">
<table class="highlighttable">
<tbody>
<tr>
<td class="linenos">
<div class="linenodiv">
<pre> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34</pre></div></td>
<td class="code">
<div class="highlight">
<pre><span></span> <span class="k">ldx</span> <span class="p">#</span><span class="mi">5</span> <span class="c1">; 5 lines</span>
<span class="kp">.draw_line</span>
<span class="k">ldy</span> <span class="p">#</span><span class="mi">0</span> <span class="c1">;clear y, not using it here</span>
<span class="k">lda</span> <span class="p">(</span><span class="mh">$3E</span><span class="p">),</span><span class="n">y</span> <span class="c1">;load current invader byte</span>
<span class="kp">.loop</span>
<span class="k">pha</span> <span class="c1">;preserve it on the stack</span>
<span class="k">and</span> <span class="p">#</span><span class="mi">1</span> <span class="c1">;check current bit for 1 or 0</span>
<span class="k">beq</span> <span class="kp">.skip</span>
<span class="k">jsr</span> <span class="n">rng</span> <span class="c1">;pick random invader</span>
<span class="k">sta</span> <span class="p">(</span><span class="mh">$40</span><span class="p">),</span><span class="n">y</span> <span class="c1">;draw to screen offset by y</span>
<span class="kp">.skip</span>
<span class="k">pla</span> <span class="c1">;restore from stack</span>
<span class="k">iny</span> <span class="c1">;increase y offset</span>
<span class="k">cpy</span> <span class="p">#</span><span class="mi">5</span> <span class="c1">;are we finished yet? </span>
<span class="k">beq</span> <span class="kp">.finish_line</span> <span class="c1">;(invaders are 5x5 so no point looking at remaning bits)</span>
<span class="k">lsr</span> <span class="c1">;if no, then bit shift one right</span>
<span class="k">clc</span> <span class="c1">;to process next bit, and loop</span>
<span class="k">bcc</span> <span class="kp">.loop</span>
<span class="kp">.finish_line</span>
<span class="k">dex</span> <span class="c1">;move to next line if x still > 0</span>
<span class="k">beq</span> <span class="kp">.finish</span>
<span class="k">lda</span> <span class="p">#</span><span class="mi">39</span> <span class="c1">;add 39 to the video address </span>
<span class="k">adc</span> <span class="mh">$40</span> <span class="c1">;which will move to the next row</span>
<span class="k">sta</span> <span class="mh">$40</span>
<span class="k">bcc</span> <span class="o">*+</span><span class="mi">4</span>
<span class="k">inc</span> <span class="mh">$41</span>
<span class="k">inc</span> <span class="mh">$3E</span> <span class="c1">;add 1 to the invader address to</span>
<span class="k">bcc</span> <span class="o">*+</span><span class="mi">4</span> <span class="c1">;move to its next byte</span>
<span class="k">inc</span> <span class="mh">$3F</span>
<span class="k">clc</span>
<span class="k">bcc</span> <span class="kp">.draw_line</span> <span class="c1">;loop</span>
<span class="kp">.finish</span>
</pre></div>
</td></tr></tbody></table>
</div>
<p>The indirect addressing is used nicely here, with the Y register effectively offseting the video location and acting as a counter at the same time, whilst X is used to count the rows. The rest of the stuff should be pretty self explanatory by now - the only new thing here is the slighly odd looking</p>
<div class="brush: ca65">
<table class="highlighttable">
<tbody>
<tr>
<td class="linenos">
<div class="linenodiv">
<pre>1
2</pre></div></td>
<td class="code">
<div class="highlight">
<pre><span></span><span class="k">clc</span>
<span class="k">bcc</span> <span class="kp">.label</span>
</pre></div>
</td></tr></tbody></table>
</div>
<p>All this does is force a branch, so it is similar to <code>jmp</code> although my reading indicates it is better to use this style since it makes the code more re-locatable.</p>
<h3 id="the-final-invader">The Final Invader!</h3>
<p>The final piece is to draw one massive invader composed of smaller invaders from the previous step across the whole screen.</p>
<ul>
<li>Choose an invader at random</li>
<li>Process the bits as per the first algorithm</li>
<li>For a set bit, store the desired video memory location and call the other algorithm</li>
<li>Update the video memory to start at the next location</li>
<li>Loop</li></ul>
<p>Essentially this routine will seed the other one - the code that sets the video memory location of $0400 is removed from the previous routine, and instead the new routine sets this up before calling it. Because the first routine modifies those numbers, I have chosen to store the actual location in another zero-page address so that is easier to reason about in the top level routine. This isn’t really necessary but it simplies the problem.</p>
<p>Since the algorithm is mostly the same, I will just highlight a few of the different parts:</p>
<div class="brush: ca65">
<table class="highlighttable">
<tbody>
<tr>
<td class="linenos">
<div class="linenodiv">
<pre> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17</pre></div></td>
<td class="code">
<div class="highlight">
<pre><span></span><span class="kp">.loop</span>
<span class="k">pha</span> <span class="c1">;preserve on stack</span>
<span class="k">and</span> <span class="p">#</span><span class="mi">1</span> <span class="c1">;check current bit for 1 or 0</span>
<span class="k">beq</span> <span class="kp">.skip</span>
<span class="k">lda</span> <span class="mh">$44</span> <span class="c1">;copy video memory location</span>
<span class="k">sta</span> <span class="mh">$40</span>
<span class="k">lda</span> <span class="mh">$45</span>
<span class="k">sta</span> <span class="mh">$41</span>
<span class="k">txa</span> <span class="c1">; preserve registers</span>
<span class="k">pha</span>
<span class="k">tya</span>
<span class="k">pha</span>
<span class="k">jsr</span> <span class="n">draw_invader</span> <span class="c1">; call other routine</span>
<span class="k">pla</span> <span class="c1">; restore registers</span>
<span class="k">tay</span>
<span class="k">pla</span>
<span class="k">tax</span>
</pre></div>
</td></tr></tbody></table>
</div>
<p>Notice here we copy the data from the addresses $44 and $45 into $40 and $41 where the <code>draw_invader</code> routine reads from. Then, since both routines use the X and Y registers, we have to push the current contents onto the stack so that they can be recovered after the subroutine has executed. Then we simply generate a random invader number, call the other routine and then restore the status of the registers from the stack.</p>
<div class="brush: ca65">
<table class="highlighttable">
<tbody>
<tr>
<td class="linenos">
<div class="linenodiv">
<pre> 1
2
3
4
5
6
7
8
9
10
11
12
13
14</pre></div></td>
<td class="code">
<div class="highlight">
<pre><span></span><span class="kp">.skip</span>
<span class="k">iny</span> <span class="c1">;increase y offset</span>
<span class="k">cpy</span> <span class="p">#</span><span class="mi">5</span> <span class="c1">;are we finished yet? </span>
<span class="k">beq</span> <span class="kp">.finish_line</span> <span class="c1">;(invaders are 5x5 so no point looking at remaning bits)</span>
<span class="k">lda</span> <span class="p">#</span><span class="mi">8</span> <span class="c1">;update video memory location</span>
<span class="k">adc</span> <span class="mh">$44</span>
<span class="k">sta</span> <span class="mh">$44</span>
<span class="k">bcc</span> <span class="o">*+</span><span class="mi">4</span>
<span class="k">inc</span> <span class="mh">$45</span>
<span class="k">pla</span> <span class="c1">;restore from stack</span>
<span class="k">lsr</span> <span class="c1">;if no then shift one right</span>
<span class="k">clc</span> <span class="c1">;to process next bit and loop</span>
<span class="k">bcc</span> <span class="kp">.loop</span>
</pre></div>
</td></tr></tbody></table>
</div>
<p>Once again, this is mostly the same as before, except now we update the video address by 8 bytes to move into the next “mega pixel” or “grid location”.</p>
<div class="brush: ca65">
<table class="highlighttable">
<tbody>
<tr>
<td class="linenos">
<div class="linenodiv">
<pre> 1
2
3
4
5
6
7
8
9
10
11
12
13
14</pre></div></td>
<td class="code">
<div class="highlight">
<pre><span></span><span class="kp">.finish_line</span>
<span class="k">pla</span>
<span class="k">dex</span>
<span class="k">beq</span> <span class="kp">.finish</span>
<span class="k">lda</span> <span class="p">#</span><span class="mi">167</span> <span class="c1">;update video memory location to next row</span>
<span class="k">adc</span> <span class="mh">$44</span>
<span class="k">sta</span> <span class="mh">$44</span>
<span class="k">bcc</span> <span class="o">*+</span><span class="mi">4</span>
<span class="k">inc</span> <span class="mh">$45</span>
<span class="k">inc</span> <span class="mh">$42</span>
<span class="k">bcc</span> <span class="o">*+</span><span class="mi">4</span>
<span class="k">inc</span> <span class="mh">$43</span>
<span class="k">clc</span>
<span class="k">bcc</span> <span class="kp">.draw_line</span>
</pre></div>
</td></tr></tbody></table>
</div>
<p>Again, very similar to before, and now we also move down 5 rows and back to column zero. This is what the magic number 167 is doing.</p>
<p>And as if by magic!</p>
<div class="figure"><img src="http://www.pinksquirrellabs.com/img/invaders/9.jpg" alt="" />
<p class="caption"></p></div>
<h3 id="conclusion">Conclusion</h3>
<p>You might be thinking, Ross! Why are you repeating yourself in the code!! And that would be a good question. Unlike higher level languages, quite often it doesn’t pay to re-use code in asm. It is always slower for a start, since you are introducing more subroutine calls, more stack usage and so forth. Of course I have no doubts that there are a million other ways to write this, in various degrees of cleverness, but all in all I am happy that I got it to work, and the result is quite pleasing! I have learnt quite a lot from this mini-project, and have bunch of ideas on what to do next :)</p>C64 Programming - Invader Fractalurn:http-www-pinksquirrellabs-com:-blog-2017-02-28-c64-programming-invader-fractal2017-02-28T17:31:32Z2017-02-28T17:31:32Zpezi
<p>I have recently been getting into programming the Commodore 64. It’s lots of fun to work in such a restricted environment, where you have to use various hardware tricks to achieve your goals. Every machine cycle and byte of memory counts!</p>
<p>I have not programmed in 6502 assembler or the C64 before. I am using the popular C64 emulator <a href="http://vice-emu.sourceforge.net/">WinVice</a> and an assembler called <a href="http://dasm-dillon.sourceforge.net/">DASM</a>. Having messed around a bit and learnt the basics of the instruction set and the hardware/memory layout, I programmed a couple of effects such as the basic text scroller. I have an idea in mind for my first demo, and part of it revolves around the <a href="http://levitated.net/daily/levInvaderFractal.html"><em>invader fractal</em></a>. I have implemented this in various langauages (F# and D being the most recent) and figured it would be a nice fit for the C64.</p>
<h3 id="invaders">Invaders</h3>
<p>The invader fractal is a very simpe idea, based on the observation that the classic space invaders are symmetrical. Given a 5x5 grid, we can observe that the middle column is static, whilst columns 4 and 5 are columns 1 and 2 flipped around:</p>
<div class="figure"><img src="http://www.pinksquirrellabs.com/img/invaders/1.png" alt="" />
<p class="caption"></p></div>
<p>This means we can store the information for each row in just 3 bits, multiplied for each row gives us 15 bits to encode an entire invader. 15 bits gives a total of 2^15=32,768 unique invaders. “Real” space invaders are a little bit bigger than 5x5, but we will stick with their smaller cousins.</p>
<!-- more-->
<h3 id="c64-limitations">C64 Limitations</h3>
<p>We will be using the most basic video mode of the C64, which is text mode. In this mode, a character is represented by an 8x8 bitmap. The video memory for each 8x8 location of the screen stores a byte value that is an offset into the character set determining which character to draw.</p>
<p>For example, the video memory is mapped to adresses $0400 - $07F7. If the value of $0400 is set to $01, then the screen will render character 1 from the character set (which happens to be the letter A) into the top left of the screen.</p>
<p>$ denotes a hexadecimal number, and % binary. The # prefix indicates a literal value rather than a memory location.</p>
<p>It is not my intention to explain every op-code, most should make sense from context and the comments, but you can view a fulll list <a href="http://6502.org/tutorials/6502opcodes.html">here</a></p>
<div class="brush: ca65">
<table class="highlighttable">
<tbody>
<tr>
<td class="linenos">
<div class="linenodiv">
<pre>1
2</pre></div></td>
<td class="code">
<div class="highlight">
<pre><span></span><span class="k">lda</span> <span class="p">#</span><span class="mh">$01</span> <span class="c1">; load 1 into the accumulator (A) </span>
<span class="k">sta</span> <span class="mh">$0400</span> <span class="c1">; store A into the first byte of video memory</span>
</pre></div>
</td></tr></tbody></table>
</div>
<div class="figure"><img src="http://www.pinksquirrellabs.com/img/invaders/2.png" alt="" />
<p class="caption"></p></div>
<p>A nice thing about these characters sets is that you can define them yourself, and then you can change them in realtime to affect the screen. Therefore, what I would like to do is work out how to take a 15 bit encoded invader and decode it into a position in the character set.</p>
<p>The C64 only has 3 registers (A, X and Y) and they are all 8 bit. This means we cannot store the entire encoded invader in a register for processing, instead some of it will have sit elsewhere.</p>
<h3 id="the-first-bits">The first bits</h3>
<p>Let’s forget the problem of 15 bits for now and concentrate on how to decode a single row of three bits into the 5 bit destination. Since a character row is 8 bits, we will consider the three most significant bits to not be used. We further consider that bit 3 is the centre pixel, while bits 1 and 2 form the right hand side of the invader, to be mirrored onto the left hand side.</p>
<p>Here are some examples (using an amazing new gfx tech):</p>
<div class="figure"><img src="http://www.pinksquirrellabs.com/img/invaders/3.png" alt="" />
<p class="caption"></p></div>
<p>Since we will have to be moving and masking bits around, we will need working areas for the finished product. We could use the registers, an area in memory or the stack for this purpose.</p>
<p>let us assume we have the value %00000101 at memory location $42 for processing.</p>
<div class="brush: ca65">
<table class="highlighttable">
<tbody>
<tr>
<td class="linenos">
<div class="linenodiv">
<pre>1
2
3</pre></div></td>
<td class="code">
<div class="highlight">
<pre><span></span> <span class="k">lda</span> <span class="mh">$42</span> <span class="c1">; load the encoded invader into A</span>
<span class="k">sta</span> <span class="mh">$43</span> <span class="c1">; copy A into $43 - $43 is now %101, the right side of the invader</span>
<span class="k">and</span> <span class="p">#</span><span class="mb">%11</span> <span class="c1">; mask out the third (centre) bit of A, leaving %01</span>
</pre></div>
</td></tr></tbody></table>
</div>
<p>$42 and $43 are a special memory addresses I have selected. Because they are 8-bit adrresses, they are known as <em>zero-page</em> addresses and have some special properties - they can be accessed much faster from the CPU - almost as fast as the registers themselves.</p>
<p>At this stage we have built the right side of the invader, dumped the centre bit and left ourselves with the two bits that will need mirroring and shifting into place on the left hand side of the invader. There are various ways to approach this. Given we only ever need to mirror 2 bits, and there are only 4 possible combinations, for the sake of 4 bytes of memory we can easily encode this into a lookup table.</p>
<div class="brush: ca65">
<table class="highlighttable">
<tbody>
<tr>
<td class="linenos">
<div class="linenodiv">
<pre> 1
2
3
4
5
6
7
8
9
10</pre></div></td>
<td class="code">
<div class="highlight">
<pre><span></span> <span class="k">tax</span> <span class="c1">; copy the value into the X register</span>
<span class="k">lda</span> <span class="n">lookup</span><span class="p">,</span><span class="n">x</span> <span class="c1">; read the value from the table offset by X into A (%10)</span>
<span class="k">asl</span> <span class="c1">; shift the result left 3 bits (%10000)</span>
<span class="k">asl</span>
<span class="k">asl</span>
<span class="k">ora</span> <span class="mh">$43</span> <span class="c1">; OR the resulting bits with our work area (%00010101)</span>
<span class="k">sta</span> <span class="mh">$43</span> <span class="c1">; store the result</span>
<span class="c1">;store the lookup table after the program data</span>
<span class="nl">lookup:</span> <span class="n">DC</span> <span class="mb">%00</span><span class="p">,</span><span class="mb">%10</span><span class="p">,</span><span class="mb">%01</span><span class="p">,</span><span class="mb">%11</span>
</pre></div>
</td></tr></tbody></table>
</div>
<p>The 6502 has several addressing modes, the one shown here is <em>absolute indexed</em>. This means it can take any absolute address (16 bits) and then it will add the contents of the X or Y register to it and return the byte from that location.</p>
<p>In this example I have told the assembler to label a location of memory <em>lookup</em> and then told it to store four consequtive bytes there.</p>
<p>Thus, the <code>lda lookup,x</code> instruction will return the data from the table depending on the value of the X register. Since we know it is only two bits, it has the following effect:</p>
<div class="figure"><img src="http://www.pinksquirrellabs.com/img/invaders/4.png" alt="" />
<p class="caption"></p></div>
<p>We then take the mirrored value and shift it left 3 bits, so that %10 becomes %10000. Finally we take our result, OR it together with the stored right hand side and store the result of %10101.</p>
<p>Success! this is the first row of an invader complete.</p>
<h3 id="the-rest-of-it">The rest of it..</h3>
<p>Now we have an algorithm to decode an invader row to a characer row, it should be easy to repeat process for all 5 rows, right?</p>
<p>First, there are going to be a couple of problems to solve. To start with, the row has been built at $43, but we don’t actually want it there. Where we really want it is the memory location where the character set starts. Let’s say this is $2000. Now, using the zero-page is very fast, but since we only read/write the intermediate invader a couple of times, we might as well just place it where it needs to end up.</p>
<p>A character set can hold 256 characters, formed of 8 bytes each (as explained earlier) for a total of 2kb. If we are going to generate 256 unique invaders, the <em>absoulte indexed</em> addressing mode is not going to work out too well for us. Since the X register can only contain a single byte, we can offset a known 16 bit address by at most 256 bytes, which will only stretch out to 32 invaders. Clearly some other method will be required.</p>
<p>There are a couple of solutions to this problem. The first is more fun but easy to mess up which is <em>self modifiying code</em>.</p>
<p>Let’s take the instruction <code>lda $2000,x</code>. The assembler of course simply turns this into some bytes - one that represents the opcode with the addressing mode, and two bytes that represent the address of $2000. Since we can write to whatever memory we like however we want to, there is nothing stopping us simply modifying the assembled address that follows the opcode. I will leave this for another post.</p>
<p>The 6502 provides another addressing mode to perform a similar function, which is called <em>zero paged indirect indexed</em>. As the name indciates, this can only be used with the zero page. It looks like this:</p>
<div class="brush: ca65">
<table class="highlighttable">
<tbody>
<tr>
<td class="linenos">
<div class="linenodiv">
<pre>1
2
3
4
5
6
7</pre></div></td>
<td class="code">
<div class="highlight">
<pre><span></span> <span class="k">lda</span> <span class="p">#</span><span class="mh">$20</span> <span class="c1">;target address most significant byte</span>
<span class="k">sta</span> <span class="mh">$41</span>
<span class="k">lda</span> <span class="p">#</span><span class="mh">$00</span> <span class="c1">;least signficant byte goes first</span>
<span class="k">sta</span> <span class="mh">$40</span>
<span class="k">ldy</span> <span class="p">#</span><span class="mh">$F</span> <span class="c1">;some index value</span>
<span class="k">lda</span> <span class="p">#</span><span class="mh">$FF</span> <span class="c1">;some value we wish to store</span>
<span class="k">sta</span> <span class="p">(</span><span class="mh">$40</span><span class="p">),</span><span class="n">y</span> <span class="c1">;stores $FF into $200F</span>
</pre></div>
</td></tr></tbody></table>
</div>
<p>First, we place the target address across two bytes at $40 in the zero page. Notice the address is stored backwards - that is - least significant byte first - $0020. This is because the design of 6502 means it is quicker to load addresses this way. If you look at the assembled instruction of <code>lda $2000</code> you will see the address is backwards there too.</p>
<p>Next we just load some values into Y and A, and the final instruction, denoted by the parens, causes the CPU to construct a 16-bit address from $40 and $41, add the contents of Y onto it, and then finally write the value in the accumulator to this new address. Pretty cool! This means we can store a 16-bit address and change it however we like from the zero page, AND have an index offset as well! Note - this addressing mode can ONLY be used with Y as the index register!</p>
<p>The other problem that needs solving is the fact the invader is 15 bits but we only have 8 bits. Clearly, once we have decoded a row and stored it, we will want to move on to the next 3 bits and repeat this process until all 5 rows are complete. The solution to this is to shift three bits out of the remaining byte and into the accumulator. Let’s say we have the first 8 bits in the accumulator, and the remaining 7 bits are stored in a byte at location $39 (was supposed to be $3F but I had already drawn the table wrong :) ).</p>
<div class="figure"><img src="http://www.pinksquirrellabs.com/img/invaders/5.png" alt="" />
<p class="caption"></p></div>
<div class="brush: ca65">
<table class="highlighttable">
<tbody>
<tr>
<td class="linenos">
<div class="linenodiv">
<pre>1
2
3
4
5
6</pre></div></td>
<td class="code">
<div class="highlight">
<pre><span></span> <span class="k">lsr</span> <span class="mh">$39</span> <span class="c1">;shift bits one to the right</span>
<span class="k">ror</span> <span class="c1">;rotate the accumuator right</span>
<span class="k">lsr</span> <span class="mh">$39</span>
<span class="k">ror</span>
<span class="k">lsr</span> <span class="mh">$39</span>
<span class="k">ror</span>
</pre></div>
</td></tr></tbody></table>
</div>
<p><code>lsr</code> (logical shift right) shifts the byte in question one to the right. If the bit that “falls off” the end is set, then the processor’s carry flag will be set. <code>ror</code> (rotate right) shifts the byte in question (in this case the accumulator since no specfic addressing mode is specified) one to the right, and if the carry bit is currently set, then 1 will also appear at the most signficant bit. In this way we are able to rotate bits out of one number and into another, giving us what we need.</p>
<p>With all being said and done, we can write a new routine that will decode an entire invader into a character, and advance the memory pointer to the next character memory location.</p>
<div class="brush: ca65">
<table class="highlighttable">
<tbody>
<tr>
<td class="linenos">
<div class="linenodiv">
<pre> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41</pre></div></td>
<td class="code">
<div class="highlight">
<pre><span></span><span class="n">setup</span> <span class="k">lda</span> <span class="p">#</span><span class="mh">$20</span> <span class="c1">; store the target charset memory location $2000 at $40</span>
<span class="k">sta</span> <span class="mh">$41</span>
<span class="k">lda</span> <span class="p">#</span><span class="mh">$00</span>
<span class="k">sta</span> <span class="mh">$40</span>
<span class="k">lda</span> <span class="p">#</span><span class="mh">$69</span> <span class="c1">; some random 7 bits i made up for the rest of the invader</span>
<span class="k">sta</span> <span class="mh">$39</span>
<span class="k">lda</span> <span class="p">#</span><span class="mh">$D9</span> <span class="c1">; a random 8 bits for the first half the the invader</span>
<span class="k">ldy</span> <span class="p">#</span><span class="mi">0</span> <span class="c1">; make sure Y is clear and ready</span>
<span class="n">loop</span> <span class="k">pha</span> <span class="c1">; preserve the current state of the invader onto the stack</span>
<span class="k">and</span> <span class="p">#</span><span class="mb">%111</span> <span class="c1">; working with the first 3 bits only</span>
<span class="k">sta</span> <span class="p">(</span><span class="mh">$40</span><span class="p">),</span><span class="n">y</span> <span class="c1">; store right side of the row</span>
<span class="k">and</span> <span class="p">#</span><span class="mb">%11</span> <span class="c1">; mask out centre bit</span>
<span class="k">tax</span>
<span class="k">lda</span> <span class="n">lookup</span><span class="p">,</span><span class="n">x</span> <span class="c1">; load mirrored bits from lookuptable</span>
<span class="k">asl</span>
<span class="k">asl</span>
<span class="k">asl</span>
<span class="k">ora</span> <span class="p">(</span><span class="mh">$40</span><span class="p">),</span><span class="n">y</span>
<span class="k">sta</span> <span class="p">(</span><span class="mh">$40</span><span class="p">),</span><span class="n">y</span> <span class="c1">; row is now complete!</span>
<span class="k">iny</span> <span class="c1">; increase Y by one</span>
<span class="k">cpy</span> <span class="p">#</span><span class="mi">5</span> <span class="c1">; test Y against 5</span>
<span class="k">beq</span> <span class="n">done</span> <span class="c1">; branch to done if Y is 5 </span>
<span class="k">pla</span> <span class="c1">; restore the invader from stack</span>
<span class="k">lsr</span> <span class="mh">$39</span> <span class="c1">; rotate the next 3 bits in</span>
<span class="k">ror</span>
<span class="k">lsr</span> <span class="mh">$39</span>
<span class="k">ror</span>
<span class="k">lsr</span> <span class="mh">$39</span>
<span class="k">ror</span>
<span class="k">jmp</span> <span class="n">loop</span> <span class="c1">; loop</span>
<span class="n">done</span> <span class="k">pla</span> <span class="c1">; restore stack</span>
<span class="k">clc</span> <span class="c1">; add 8 to the target memory location</span>
<span class="k">lda</span> <span class="p">#</span><span class="mi">8</span>
<span class="k">adc</span> <span class="mh">$40</span>
<span class="k">sta</span> <span class="mh">$40</span>
<span class="k">bcc</span> <span class="n">skip</span> <span class="c1">; if the carry bit is set, we overflowed from $FF to $00</span>
<span class="k">inc</span> <span class="mh">$41</span> <span class="c1">; which means we increase the most significant bit as well</span>
<span class="n">skip</span> <span class="p">...</span> <span class="c1">; rest of program </span>
<span class="n">lookup</span> <span class="n">DC</span> <span class="mb">%00</span><span class="p">,</span><span class="mb">%10</span><span class="p">,</span><span class="mb">%01</span><span class="p">,</span><span class="mb">%11</span>
</pre></div>
</td></tr></tbody></table>
</div>
<p>Since the Y register is being used as the indirect index, and X is used for indexing the mirror lookup table, we need a new place to store the current invader byte. Rather than have to copy stuff around, we simply push it onto the stack <code>pha</code> and then restrore it <code>pla</code> when ready to advance the next 3 bits.</p>
<p>The other part here worth mentioning is the slightly odd looking sequence of</p>
<div class="brush: ca65">
<table class="highlighttable">
<tbody>
<tr>
<td class="linenos">
<div class="linenodiv">
<pre>1
2
3
4
5
6
7</pre></div></td>
<td class="code">
<div class="highlight">
<pre><span></span> <span class="k">clc</span>
<span class="k">lda</span> <span class="p">#</span><span class="mi">8</span>
<span class="k">adc</span> <span class="mh">$40</span>
<span class="k">sta</span> <span class="mh">$40</span>
<span class="k">bcc</span> <span class="n">skip</span>
<span class="k">inc</span> <span class="mh">$41</span>
<span class="n">skip</span> <span class="p">...</span>
</pre></div>
</td></tr></tbody></table>
</div>
<p>The 6502 can obviously only do 8 bit addition, and it does not have an instruction to add something ignoring the carry bit. The first instruction <code>clc</code> simply clears the carry bit so we don’t get an unexpected result when we do the addition. The next three instructions add 8 to memory address $40. If this caused $40 to go over $FF and wrap around, then the carry bit will be set. The <code>bcc</code> instruction will branch to the given label when the carry bit is clear - so in the cases where the lower address byte of $40 overflowed, we also add one to the higher address byte at $41. This is a shortcut way to add an 8 bit number to a 16 bit number.</p>
<div class="figure"><img src="http://www.pinksquirrellabs.com/img/invaders/6.png" alt="" />
<p class="caption"></p></div>
<p>My totally random numbers produced quite a nice invader! The routine above can definitely be further optimised. For a start - once the extra 7 bits are shifted in, the <code>lsr $49</code> instructions are wasted. We could drop the loop and just unroll the code to prevent this and make it faster withouht the <code>jmp</code> instructions, at the cost of more program space.</p>
<p>We still need a way to randomise the 256 invaders, but I will save that for another time!</p>
<p>(and no, this version has nothing at all to do with fractals!)</p>