--- a/content/blog/2017/01/chip8-disassembly.markdown Mon Jan 02 15:11:10 2017 +0000
+++ b/content/blog/2017/01/chip8-disassembly.markdown Mon Jan 02 15:28:31 2017 +0000
@@ -10,11 +10,11 @@
Lisp. After adding a screen, input, and sound the core of the emulator is
essentially complete.
-I've been guiding you through the code step by step and it might look pretty
-simple, but that's only because I went down all the dead ends myself first. In
+I've been guiding you through the code step by step and it might look simple,
+but that's only because I went down all the dead ends myself first. In
practice, when you're writing an emulator for a system you'll need a way to
-debug the execution of code, and the first step is to be able to *read* the
-code, so let's look at how to add a disassembler to our simple CHIP-8 emulator.
+debug the execution of code. The first step is to be able to *read* the code,
+so let's look at how to add a disassembler to our simple CHIP-8 emulator.
The full series of posts so far:
@@ -91,7 +91,7 @@
There are a lot of other ways we could have done this, like making a proper
parser or adding functionality to `define-opcode`, but since there's not that
-many instructions I think this is pretty reasonable. Now we can pass in a raw,
+many instructions I think this is reasonable. Now we can pass in a raw,
two-byte instruction and get out something readable:
```
@@ -139,15 +139,16 @@
instruction to the screen. Running it for a single instruction would print
something like:
-```
-Address Disassembly
- | |
- v v
-200: 8055 (SUB V0 V5)
- ^
- |
- Raw instruction
-```
+<pre class="lineart">
+ 200: 8055 (SUB V0 V5)
+ ^ ^ ^
+ | | |
+ | | Disassembly
+ | |
+ | Raw instruction
+ |
+ Address
+</pre>
The helper function `instruction-information` is simple, but we'll be using it
in the future for something else, so it's nice to have:
@@ -174,10 +175,9 @@
(aref array (1+ index))))
```
-These functions *could* be combined into a single, bigger function, but I'm
-a strong believer in having each function do exactly one thing only. And as
-we'll see, each of these "simple" tasks is going to get more complicated in the
-real world.
+These functions *could* be combined into a single bigger function, but I'm
+a strong believer in having each function do exactly one thing. And as we'll
+see, each of these "simple" tasks is going to get more complicated later.
Now we can dump the disassembly for a ROM to see how it works:
@@ -224,18 +224,18 @@
valid opcodes it will return `nil`.
The CHIP-8 (like [most computers][neumann]) uses the same memory to hold both
-program code (instructions) and data. This includes things like player health,
-score, location, and most importantly: the sprites that will be drawn on the
-screen.
+program code (instructions) and data. Data includes things like player
+health, score, location, and most importantly: the sprites that will be drawn on
+the screen.
[neumann]: https://en.wikipedia.org/wiki/Von_Neumann_architecture
Unfortunately there's no way to know for sure whether a given memory location
contains an instruction (and thus needs to be disassembled) or is intended to be
a piece of data. Indeed, someone like [Mel][] could conceivably figure out
-a way to use a particular sequence of instructions as a sprite! So our
-disassembler will just always show the disassembly for anything that *might* be
-an instruction.
+a way to make a particular sequence of instructions perform double duty as
+a sprite! So our disassembler will just always show the disassembly for
+anything that *might* be an instruction.
[Mel]: http://www.catb.org/jargon/html/story-of-mel.html
@@ -247,7 +247,6 @@
We could add a separate function to draw out the sprite data, but the CHIP-8's
sprites are so simple that we can just tack it on to the disassembly output.
-
[Remember][cowgod-disp] that each byte of memory defines one eight-pixel-wide
row of a sprite, and that `DRW X, Y, Size` will draw `Size` rows of a sprite
using contiguous bytes in memory. So if memory contains something like this (at
@@ -280,22 +279,19 @@
*one* byte long. Our sprites would get pretty mangled if we printed two of
their rows per line of disassembly — for example, `4` would look like this:
-```
- byte 1 byte 2
- 1111111122222222
-064: 9090 (SNE V0 V9) █ █ █ █
-066: F010 ████ █
-068: 10F0 (JP F0) █
-```
+<pre class="lineart"> byte 1 byte 2
+ 1111111122222222
+ 064: 9090 (SNE V0 V9) █ █ █ █
+ 066: F010 ████ █
+ 068: 10F0 (JP F0) █ ████
+</pre>
Not ideal. One option would be to make every instruction of disassembly two
lines long, but that's painful to read when trying to look at the code portions
-of the ROM.
-
-We can get around this with a delightful little hack: using characters from
-[Unicode Block Elements][block] to cram two rows of sprite data into a single
-line of output. Let's start by defining a `bit-diagram` function that will take
-a two-byte-wide integer and return an ASCII diagram of its bits:
+of the ROM. We can get around this with a delightful little hack: using
+characters from [Unicode Block Elements][block] to cram two rows of sprite data
+into a single line of output. Let's start by defining a `bit-diagram` function
+that will take a two-byte-wide integer and return an ASCII diagram of its bits:
[block]: https://en.wikipedia.org/wiki/Block_Elements
@@ -305,11 +301,10 @@
(for low-bit :from 7 :downto 0)
(for hi = (logbitp high-bit integer))
(for lo = (logbitp low-bit integer))
- (collect (cond
- ((and hi lo) #\full_block)
- (hi #\upper_half_block)
- (lo #\lower_half_block)
- (t #\space))
+ (collect (cond ((and hi lo) #\full_block)
+ (hi #\upper_half_block)
+ (lo #\lower_half_block)
+ (t #\space))
:result-type 'string)))
```