Category Archives: apple

Wrapping Up Our Apple II Adventure

Having covered sound in the previous post, let’s talk about graphics now.

bumber_ii

This is using the Apple II’s low-resolution graphics mode, both because I’m not much of an artist, and this means I can hide that a little better, and because the low-res mode has a number of wonderful callbacks to our earlier explorations of CGA graphics on the IBM PC.

The first is hardware. Look at the colors in use in the screenshot above, and then compare them to the ones we created with chrominance artifacts on the CGA high resolution display:

cga_artifacts

The colors are very similar. Identical, in fact, though not quite in exactly the same order—the Apple II’s color palette is being generated, at the hardware level, by exactly the technique we deployed in software on the PC.

Meanwhile, on the software side, the technique used for programming is almost exactly the technique we used for the 160x100x16 mode on the PC. Here, however, instead of an 80×100 text display being split into left and right halves, here it is 20 lines of the 40×24 display being split into top and bottom halves. Producing a display is simply a matter of copying a big chunk of data to screen memory. That lets us put the text at the bottom in with the same mechanism, so that’s nice too.

But, sadly, it’s not quite as simple as all that. The Apple II’s screen memory is kind of bonkers.

It starts out much like the Commodore 64’s—memory location 1024 ($0400) is the top left character, and as we advance to the right we find our self at location 1063, 39 spaces over and in the upper right.

The surprise hits at 1064. Instead of being the first character of the second line, it is the first character of the ninth line. Forty more characters down, at 1104, we find ourself at line seventeen. But what of 1144? There are only 24 lines, so one might think that this takes us back to the top for line 2.

It doesn’t. The first character of line 2 is at location 1152 ($0480), 128 bytes after the character above it. That’s a nice round number, but it leaves us a screen hole—a run of 8 bytes that aren’t part of the screen display. Poking around old documentation I get the impression that the screen holes are somehow used by I/O devices or extension cards. At any rate, one isn’t supposed to mess with them.

So that’s a little inconvenient, but it’s not too bad. I used a very simple run-length encoding scheme for the image here, and repurposed the “end of input” marker to also mean “skip 8 bytes, and, oh, by the way, you have to run out of input eight times before you’re done.” After that it was like encoding eight 120-byte lines. Not too bad, and a few runs even get to go multi-line as a result. Not many, but some.

Goodies

I composed the image here by fiddling around in BASIC for a bit until I got the picture the way I wanted it, and then I decided to not worry about the screen holes and just BSAVEd the screen memory out to a file and encoded it offline. I then encoded a little tune to go with one of the playroutines from last time to make a simple program with graphics and sound. Thanks to Nick Montfort, this has actually been tested on proper hardware and it seems to work as advertised.

Source code for the complete program is up on Github, and actually has been for quite awhile now. I’ve just been incredibly slow in actually writing this project up.

But now it has been, so that’s one more little project down. I’ve got something a bit more ambitious in mind for my next project. We’ll see how that goes.

Advertisements

Making Music on the Apple II

Hey everyone. It’s been quite a while since I’ve managed to actually write anything up for this blog. Sorry about that.

Let’s dive into a new system and a new technology: graphics and sound on the Apple IIe. It ought to be fine. I mean, we’ve already done stuff with graphics on the Atari 2600—where sprites are placed by cycle-counting out from HBLANK—so really, can this be worse than that?

Spoiler alert: it turns out it can.

Sound on the Apple II

Sound on the Apple II computers is controlled via a single register located at $C030. Whenever that memory location is read or written, the Apple’s 1-bit speaker is toggled from in to out or vice versa, producing a little “pop”. By accessing this location in a regular rhythm, the system can be made to produce square waves.

This is, in fact, a harder problem than Atari 2600 sprite placement. The cycle counting on this is so precise that the CPU really can’t reasonably be doing anything else. That’s why, as you may recall, Apple games tended to pause the action when playing little tunes.

But we are undaunted. How can we get a system that can actually produce recognizable notes and songs

The Plan

We’re used to thinking of notes in terms of their frequency. In particular, the A above middle C is standardized at 440 Hz, and then each note extends out in a geometric series, with octaves being factors of two. To produce a note at 440Hz we would need to produce 440 oscillations per second, which means we’d need to write the speaker 880 times per second, which (for a proper square wave) means a transition every 1/880th of a second.

This tells us, straight away, that the most convenient way to describe notes will be, not its frequency, but its half-wavelength. Our basic loop will look something like this:

  1. Wait a half-wavelength’s worth of time.
  2. Toggle the speaker.
  3. Subtract the time spent from the note duration.
  4. If the note is over, we’re done. Otherwise, loop back.

Now the problem looks a lot more tractable! But there’s some trickery hiding in “update timing information”. The easiest way to track timing information is simply to count iterations of this loop. But the loop is full of branches, which means that the length of the loop will vary from iteration to iteration. Branch instructions even take a varying number of cycles to execute based on whether or not the branch succeeds.

We’ll be better off using having a single loop with a constant iteration time, and then having it keep track of both counters at once:

  • If we’ve finished a half-wavelength, toggle the speaker state.
  • If we’ve finished the note, we’re done.
  • Update timing information and loop back.

So this very simple routine can stay very simple as long as we can ensure that every iteration through the loop takes exactly the same amount of time. Then we can hit specific notes by working out the iteration count that is closest to any given note’s half-wavelength. We’ll want our code to be as small as possible, too: the shorter each iteration is, the more precise we can be when specifying pitch

We’ll begin to do the work below the fold.

Continue reading

A New Platform

I’ve done a bunch of work on this blog with 6502-based systems, but there’s been a pretty glaring omission so far: the Apple II series. This has mostly been because it’s very hard to get modern tools to produce artifacts that Apple II emulators are willing to read.

The reason for that has a lot to do with the smarts for I/O living in the CPU and not on the disk drive, which means that we won’t get anything done without a proper disk image, really. And the best tools for Apple interoperability were not merely proprietary but commercial until quite recently.

That’s changed, and this time when I went to try to run some code on a simulated Apple IIe, I actually succeeded. It’s still a bit complicated, though. Here’s how I did it.

Programs used

The emulator I used was AppleWin. Accurate, easy to use, handles a goodly number of disk formats, but is unfortunately Windows-only. I haven’t found any other IIe emulators I actually like, though. Open to suggestions.

To work with disk images, I used CiderPress. This recently got a heavy rewrite and the disk utilities can in principle be compiled to a standalone library that works anywhere, but CiderPress itself is still Windows-only.

Making a disk image

CiderPress makes this trivial. I click “create a new image”, select DOS 3.3, give it a volume number, and specify a filename. AppleWin will boot the resulting image, albeit straight into Applesoft BASIC.

Writing a binary program

Unlike the C64 and its PRG format, information about a program’s load address is part of its file attributes on Apple disks. That means that we can write our Hello World program with no metadata whatsoever:

        .org    $1900
    
        ldy     #$00
lp:     lda     msg, y
        beq     done
        ora     #$80
        jsr     $fded
        iny
        bne     lp
done:   jmp     $03d0

msg:    .byte   13,"HELLO, APPLE WORLD!",13,0

When we assemble this program, we need to give it a name like HELLO.WORLD#061900.BIN. The HELLO.WORLD is the filename on disk, the 06 is the file type (binary), the 1900 is the load address, and the .BIN is also the file type, just to make sure. Open your disk image in CiderPress, add it as a file, and make sure that “use file attribute tags and guess file type from extension” is set. You can now enter the command BRUN HELLO.WORLD and see the program run!

Quirks of that program, aka Welcome To The Apple II

  • We can’t name the program HELLO because that’s the default autoboot program and under normal circumstances it must be a BASIC program.
  • We have to set the high bits on our characters on the way to the character-out routine at $FDED because that’s where normal characters live. The first 128 characters are inverse-video and flashing variants.
  • Instead of returning with RTS we must return with JMP $03D0, which is much like the C64’s JMP ($A002)—a jump to the BASIC warm-start vector. This is necessary because if you try to BRUN a program that calls the character-out routine, the system ends up in a state where it will hang on a return-from-subroutine. Machine language routines invoked via the CALL statement (equivalent to CBM BASIC’s SYS) do not have this problem.

Writing a hybrid program

This is a little unusual—it’s far more typical to BRUN your target program or have the BASIC program BLOAD it into place and then call it itself—but it’s still totally possible to wrote BASIC loader stubs for the Apple II the way we did for the C64. The exact token values are a little different, but the structure is extremely similar; both Applesoft BASIC and Commodore BASIC were developed off of Microsoft’s base. They even use an identical base address:

        .org	$0801
        .word	next, 10
        .byte	$8c, " 2062", 0
next:   .word   0

        ldy     #$00
lp:     lda     msg, y
        beq     done
        ora     #$80
        jsr     $fded
        iny
        bne     lp
done:   rts

msg:    .byte   13,"HELLO, APPLE WORLD!",13,0

When you assemble this program, give it a filename like HELLO.WORLD.BAS. CiderPress will identify it as a BASIC program and set attributes accordingly. You will probably want to rename away the .BAS from the filename on the disk, but the resulting program can be LOADed and RUN like any other BASIC program.

That’s great, but so what?

A fair question, really. Except for having access to more memory and different peripherals, the Apple IIe was really a generation behind the C64, and it’s somewhat obnoxious to work with as a result. Still, I’m sure we’ll find a few fun things to make it do.