October 23rd, 2010

Echoes of KFest podcast

The KansasFest committee, having recently published an extensive video record of KansasFest 2010’s sessions, is now making the audio of some of those recordings available separately. The Echoes of KFest podcast debuted with Mark Simonsen’s keynote speech. Catch future episodes by subscribing to the podcast in iTunes.

October 21st, 2010

Leadlight brings horror adventure to the Apple II

Australian Apple II enthusiast Wade Clarke has released Leadlight, a “survival horror” interactive fiction game (i.e. text adventure) for the Apple II.

The premise of the game is that you are Belinda Nettle, a teenage student attending Linville Girls High School. While studying in the library one afternoon, Belinda falls asleep — but when she wakes up, everything is changed. Something horrific stalks the school’s grounds, and Belinda’s classmates aren’t who they once were. You must help her survive the night and escape, or Belinda will surely die.

Leadlight was developed with the Eamon gaming system. It’s available for download and can be played on a real Apple II. Or, you can play it online with your web browser using one of the available emulator plug-ins. See the site for details.

Wade Clarke is also known as Aeriae, a Sydney-based producer and composer of electronic music. Check out his amazing YouTube videoclip for the track “AMay” from his album Hold R1. The animation for the video was created using Fantavison for the Apple II. I’ve watched it a few times and I’m rather at a loss for words to describe how awesome I think it is.

October 6th, 2010

Some Assembly Required: Let’s Do It Again

Last time, we looked at how to increment and decrement the values in registers. The code sample wasn’t very interesting, but learning how to use INC and DEC is a key step in learning how to build code that repeats tasks.

A loop is a code sequence that executes over and over again until some condition is met. A very common use case is to repeat some specific number of times. If you’re familiar with BASIC, this is equivalent to the notion of the FOR...NEXT loop.

Our Code This Time

In this installment, we’re going to create our first subroutine, which will use a loop to output a string of characters to the screen. This is actually very similar code to the string printing code in the example in the first Some Assembly Required article a few weeks ago. We’ll likely be using this exact routine a lot in the future — a simple “print a string” routine. Let’s have a look at the code.

Apple II game info site added to Links page (0 downloads)
*
* print
*
* Prints the null-terminated string
* pointed to by the X and Y registers.
*
print    start
string   equ   $00                      ;String pointer address

         sty   string                   ;Save the string
         stx   string+1

         ldy   #$00                     ;Start at the beginning
loop     lda   (string),y               ;Get a character
         beq   done                     ;->If it's zero, done
         jsr   COUT                     ;Print it
         iny                            ;Next character
         jmp   loop                     ;And keep going
done     rts                            ;Return to caller
         end

Our print routine starts by using the EQU (EQUate) directive to give a name to the memory location at the address $00 in memory. This location is in the zero page, the very first page of memory. This page has special properties that make it particularly useful, since locations in the zero page can be referenced using a single byte (since the first 256 addresses in memory range from $00 to $FF). There are even special addressing modes just for working with the zero page, and instructions using these addressing modes are faster than when addressing other parts of memory. We’ll talk about that in more detail next time, though.

The first thing this routine does is take the value in the Y register and store it in the memory location pointed to by string, and then the X register into the next location in memory (string+1 equals $00+1 equals $01).

What we’ve done, then, is take the two-byte memory address pointed to by the bytes in the X and Y registers, and store them as a two-byte value in the memory locations at $00 and $01.

Numbers on the 6502

Let’s step back for a moment and look at how numbers are represented on the Apple II. A single byte can have the value $00 to $FF (that is, 0 to 255). To represent higher numbers, you need to use more bytes. By adding a second byte, you can represent values from $00 to $FFFF (0 to 65,535). For the foreseeable future, that will suffice for our needs.

It’s extremely important to keep in mind that the 6502 (like Intel’s processors, by the way) is a little-endian architecture. This means it uses low-byte first byte ordering. That means that if you need to represent a 16-bit (two byte) value, you put the lowest-order byte first, then the highest-order byte.

So, for example, the number $1234 would be represented in memory by $34 then $12.

This takes a little getting used to, but has key advantages on an 8-bit platform, since typically we need to manipulate the bytes in order from lowest to highest anyway when performing calculations. We’ll be looking at how to do math in the near(ish) future.

Back to Our Code

That said, now we can see that we’ve taken the address of the string we want to print and stored its low byte at the address $00 and its high byte at byte $01 in memory. This is the correct order for storing a 16-bit value (such as an address) on the 6502.

The next thing we do is initialize the Y register to have the numeric value 0, using the LDY (LoaD Y register) instruction. We’ll be using the Y register as a counter to keep track of how far into the string we’ve progressed while printing it out.

The next line is the first line of our printing loop. As I mentioned earlier, a loop is a set of instructions that runs over and over again until a condition is met. Let’s see how it works.

The first line of the loop starts with the text “loop”. Text that starts at the left-hand edge of the source code is called a label. Labels represent a location in memory. The actual value of the label is computed by the assembler when you assemble your program. This lets you refer to memory locations without having to know where they are.

The first thing the loop does is use a new addressing mode we haven’t looked at before. This is the indirect indexed addressing mode. When you see an address in parentheses in 6502 assembly language, we’re performing an indirect access to memory. That is, we take the address specified by the operand (in this case, the address referenced by string, which is $00), and then look at the address that’s stored in that memory. In this case, that’s the address that was specified by the X and Y registers when the print routine was run — which we previously stored in the two bytes at $00 and $01.

The indexed part of this addressing mode means we then take the retrieved address and add the value of the Y register to it to get the actual address to use for our operation.

For Example

Let’s say that when this routine was called, the value in string was $1234, meaning that the string we’re going to print is in memory starting at the address $1234.

That means we would store the number $34 in address $00 and $12 at $01.

Then, Y is set to zero.

The next thing we do is get the first character of the string to print. We look at the two bytes located at string and string+1 to determine the address of the string, so LDA knows to start looking at $1234. Then it adds the value of the Y register to that, getting $1234 for the address of the first character. It then loads the byte from that location into A.

Finishing the Loop

Once the character is in the accumulator, we need to see if we need to actually print it, or if the string is done being printed. We’re using null terminated strings; these are strings that end with a null character (that is, a character with the ASCII value 0). So we need to look to see if the character we just loaded is zero.

This is easy to do using the BEQ (Branch if EQual) instruction.

Whenever the value of a register changes, special status flags in the processor are changed. We’ll be looking at each of them over time as we proceed through this series of articles, but for now, let’s consider the zero flag. This flag’s value is 1 if the result of the last operation was zero, or if the result of a comparison operation indicated that two values were equal.

So BEQ branches (that is, starts executing code at a different location in memory) if the zero flag is 1. Which it is, if the LDA instruction loaded a zero into the accumulator.

So simply using BEQ to exit our loop if the end of the string was reached works nicely for us here; we simply branch if equal to the line of code with the label done. If the accumulator isn’t zero, the code continues to run on the next line.

The next line calls the ROM routine COUT, located at $FDED, which prints the character whose ASCII value is in the accumulator.

Now comes the fun part. We increment the value in the Y register so that the next time we run through our loop, we get the next character. This is done using the INY instruction; this implied mode instruction takes no operands at all. It simply adds one to the value of the Y register. We looked at this last time.

Finally, we use the JMP instruction to jump back to the start of the loop to continue printing the string.

Next Time

Next time, we’re going to learn more about the magic of the zero page, and the layout of the Apple II’s memory in general, which we only briefly touched on this time.

|