Category Archives: apple

An Ambition, Completed

I belong that that somewhat narrow cohort that straddles Generation X and the Millenials—we grew up with the microcomputer omnipresent but we remember a time before The Internet. The cohort has gotten various attempts at nicknames but I’ve always been fond of the name Oregon Trail generation, after the famous educational software.

My parents were also somewhat technically inclined (or at least gadget-oriented), and as a result I had grown up alongside a number of game consoles and home computers. A lot of the work I did on those, both as a hobby and for schoolwork, shaped my talents in the years to come.

One of my goals here on Bumbershoot over the past few years has been to demystify the machines I grew up with. I’m now a genuine software professional, after all—surely I’ve learned enough to see how the tricks were done and to join in myself, if a bit late.

As such, once I realized that this was what I was doing, I formalized the nature of the task and started getting systematic about it. And now, with this latest release, I have finished it.

The Rules

Here are the rules I had set for this task.

  • Childhood ends in 1992. This is a somewhat arbitrary division point, but it turns out I can pick any year from there to my 20th birthday and not change the list of targeted systems, and 1992 means I don’t have to distinguish between when a platform was released in North America and when I got access to it.
  • Systems require a full year of exposure to count as “one I grew up with.” I had brief acquaintance with the Macintosh and the SNES, but both were systems I didn’t really have any experience with until adulthood. I first beat Super Metroid in 2010.
  • Programs must run on the metal. Interpreted languages are permitted only to the extent that they can then transfer control to machine code. This started out as “BASIC and LOGO don’t count” but eventually became a requirement that, for at least one project, I produce a binary where every single byte in the program exists because I put it there.
  • Programs must be for the platform. Writing a highly portable C program and jamming it through a compiler for each system doesn’t count. I should make use of a generous set of system-specific capabilities that let it show off what it’s good at. Any stunt that reaches demoeffect quality automatically achieves this goal.
  • The platform must have been intended to receive third-party programs. That means the graphing calculators we had in high school don’t count, even though they had Z80 chips in them and you could program them with special connectors and PC programs that no longer run on 64-bit operating systems.
  • Period tools are not required. Since half the targets are game consoles, cross-development tools were the norm even at the time.

So, without further ado, the systems I grew up with.

Continue reading

Advertisements

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.

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.