This is the Apple I computer designed by Steve Wozniak and released in 1976.
And apparently this particular one can be yours for just $1.5 million,
which given the condition it's in and how rare these things are,
is maybe not such a terrible deal.
But if you did happen to buy one, here's a copy of the manual that came with it.
You can see that it uses a 6502 microprocessor running at about 1 MHz.
Now unfortunately I don't happen to have an Apple I,
but I did build this 1 MHz 6502-based computer that will run roughly the same software.
And it talks about that software here.
It says it contains resident system monitor software enabling the user via keyboard and
display to write, examine, debug, and run programs efficiently,
thus being an educational tool for the learning of microprocessor programming and an aid
to development of software.
Now they talk about getting the keyboard, display,
and power and everything hooked up here.
And then how to use the system monitor software, we'll come back to this in a second.
But they also provide a listing of the code for the 6502-hex monitor.
And this is some very interesting code.
They call it the 6502-hex monitor, but most people call this
program Wosmon because this code was written by Steve Wozniak.
And it's remarkable because it packs a lot of functionality,
as you'll see, into a very small amount of code.
This entire thing fits in ROM from address FF00 through address FFFF, so just 256 bytes.
And that actually includes the interrupt and reset vectors,
as well as two bytes that are unused.
So really, the entire program here is just 248 bytes of code.
And so I've got it running on my breadboard 6502 computer here.
And of course, if you'd like to build your own 6502 breadboard computer,
I sell kits with all the parts you need over on my website, eater.net.shop.
So check that out for more.
And I also have a link to the PDF of this operation manual over
there if you want to look at that in a little more detail.
But to get the Wosmon program working on this, I had to make a few changes.
You know, the major difference between this and the Apple I computer is that
here I'm using a serial interface for I-O rather than a keyboard and display.
So I modified the original Wosmon code here.
So instead of setting up a keyboard and display, I'm setting up the serial interface.
So that's what this code is doing here versus this code over here.
And then the key codes that we get from the serial interface
are different from the key codes from the Apple I keyboard.
So I've had to change which values we're using for,
you know, backspace key, escape, backslash, and so on.
And then the code to input a character is slightly different because, again,
you know, we're reading from the serial port versus reading from a keyboard.
And I had to tweak a little bit of logic here for keeping track of
what mode we're in because of some of the differences in key codes.
But for the most part, the changes I'm making are just to those key codes.
But by and large, the rest of the logic is the same until we
get down here to the bottom where I modified the code to output
a character to the serial interface rather than to a display.
So with those few changes, the code ended up being a little bit longer,
but fortunately only two bytes longer.
And there were those two unused bytes that were part of the original.
So it still fits into the last 256-byte block of ROM at address FF00.
So what can we do with Wosmon? Well, it says here that it's
a PROM program in location FF00 through FFFF, and of course
it still is, which uses keyboard and display to perform the
front panel functions of examining memory and running programs.
Monitor programs entered by hitting reset, which displays a backslash return.
So let's try that.
So I'll hit reset, and there's the backslash.
And so there's a bunch of stuff we can do.
We can look at what's at a particular memory location.
So if I type FF00, that shows that there's an A9 in ROM at address FF00.
I can look at FF01, and we see a 1F.
But if we want to look at multiple addresses, there's actually an easier way.
We can type FF00.FF0F, let's say, to see that entire range.
In fact, we can look at FF00 through FFFF, and that's
the entire Wosmon program that we're running right now.
But we don't have to just look at what's in ROM, we can inspect what's in RAM as well.
So for example, address 0200 is a RAM address.
You can see it contains 30.
And this particular address is interesting because Wosmon uses it as a variable.
If we look here, we can see that address 200, or 0200 if you will,
through 027F is the in variable, and Wosmon uses that as the input buffer.
So if we look at 0200 through 027F, we see 30, which is the ASCII code for a character 0,
and then 32 is the ASCII character for a character 2, and then 3030.
So we see 0200, which is in fact what we had just typed, 2E is the ASCII code for a dot,
which we typed, and then 30 is a 027, and then 46 is the ASCII code for a capital F,
and 0D is the ASCII code for a carriage return.
So as we were typing this command, each character we typed was being put into memory here.
And then when we pressed enter, it showed us what was in memory at that moment.
So that's pretty cool.
And we can look at some other locations, say 0300 through 030F,
and this area of memory isn't used for anything, and it just has some random stuff in it.
But another thing that Wosmon lets us do is it lets us write to memory.
So we can do 0300 colon, and then some value, let's say BE.
If we press enter, it tells us that 0300 used to be 00, right? You can see that it was 00.
But by executing this command, it now put a BE into that location.
So if we look again at 0300 through 030F, you
can see now that location 0300 has the value BE.
And so that's stored in RAM in that location.
You can even write multiple values this way.
So if I do something like this, at address 0300, I want to write BE01,
BE02, BE03, it'll write all those values starting at address 0300.
So if we look again at 0300 through 030F, you
can see it stored those values just like that.
And then the rest of this is just whatever random
garbage was in memory when we powered the computer on.
Now, of course, we don't have to confine our addresses to ROM or RAM.
We can also do I-O.
You know, we've got this interface adapter chip here,
which has a bunch of I-O lines on it.
And these unused I-O lines here, for example, are mapped to address 6001.
So if we look at address 6001, we see that it's got a value of 0 in it.
But let's connect one of these lines here to a 5-volt signal.
Now if we look at 6001, the value is 1.
Connect it back to ground, and it switches back to 0.
If we connect a different pin to 5 volts, then you can see a different bit gets set.
And of course, these pins can do input and output.
So if we write to address 6003, we can change the direction.
So FF will set all of those pins to output.
So now if we hook up an LED up to that first pin,
we should be able to control it by writing to that address.
So I'll connect the LED to the first pin here, and then to ground through a resistor.
Now if we write to address 6001, and we set it to 01, the LED comes on.
And if we write a 0, then it turns off.
So this can be very handy for experimenting with various hardware without
having to reprogram the EEPROM every time you want to try something.
For example, this LCD screen is hooked up at address 6000,
and you can send it various commands by writing different values to that address.
Here are some examples.
So, you know, for example, if we want to clear the display,
you could set address 600 to these six different values, kind of in this order.
And that would send the command to the LCD to clear the display.
And so I've got a whole sequence of commands here,
and I kind of put them all together here.
And I can just literally copy and paste them into the Wasmon terminal.
It's going through and setting address 600 to each of those values,
which should be doing something to the LCD.
So it's initialized, and there it goes printing some letters to it.
So it's kind of a cool way of experimenting with and manipulating hardware.
But the other thing that Wasmon will let you do is run other programs by jumping
to some other address in memory and executing whatever happens to be there.
So right now, the only program we have is Wasmon itself at address FF00.
But if we type FF00 to set that as our current address,
and then just type R and press enter, it's going to jump to Wasmon.
And so we get that backslash again, because Wasmon just restarted
from scratch when we told it to run whatever was at address FF00.
But of course, we have the tools here to input and run our own program.
And in fact, the Apple I documentation walks you through entering a test program.
Here it says you can try a simple program to test if your system is functioning properly.
So let's try this.
So it says first, hit the reset button to enter the system monitor,
and a backslash should be displayed, and the cursor should drop to the next line.
So there we go.
And maybe I need to debounce that reset button.
And then second, we have to type this in, and it says that a B means a blank or a space.
So I'll go ahead and type this in, 0 A9 space 0 AA20 EF FF E8 8A 4C 2 0.
So I've got all that typed in, and then press return.
And then third, it says type 0 dot A, and it says this
should print out on the display the program we just entered.
And so there it is.
Basically everything we typed here was putting a program in
the form of machine code into memory starting at address 0.
And here we've just printed that out to verify that everything we typed in is correct.
And then because we just printed from memory starting at address 0,
address 0 is the current address.
So it says if we just type R and return, it'll run the program starting at address 0.
And there it goes.
And it says the program should then print out on
the display a continuous stream of ASCII characters.
To stop the program and return to the system monitor, hit the reset button.
I'll hit the reset button.
There we go.
We got our backslash.
We're back at the system monitor.
To run again, we can type R to run it again.
Now maybe you think it's a bit inconvenient to
enter programs in hex machine code like this.
You know, normally we want to write a program in assembly like this program here,
which initializes the LCD and then prints out a message.
But we can do that.
So at the top of this program, I specify org 1 0 0 0,
which tells the assembler that this program expects to run in memory at address 1 0 0 0.
That's where, you know, this first command will start in memory.
And so it'll run this program, it'll print out the message, and then halt,
although actually I changed halt so that instead of just, you know,
jumping back to halt and sitting in an infinite loop, when the program's done,
it jumps back to FF 0 0, which is going to return to Wasmon.
Now if we assemble this program, it's going to create ADOT out.
It has a segment at 1 0 0 0, that's 249 bytes.
So ironically, my program to print hello world is bigger than Wasmon itself,
which I think speaks to Steve Wozniak's ability to cram a lot of functionality into just
248 bytes.
But anyway, we can hex dump ADOT out to see the contents.
And so here's the machine code for that program.
If I'm clever with the parameters to hex dump and such,
I can massage that into a slightly different format.
So now it has the address here, starting at 1 0 0 0, followed by a colon,
followed by the machine code in uppercase, because that's what Wasmon requires.
And so each line here is a Wasmon command that writes 16 bytes into memory,
starting at this location.
So I can just copy all of this and paste it into Wasmon.
And now that assembly program we were just looking at
is now assembled and in memory now at address 1 0 0 0.
So if we go to address 1 0 0 0 and do R, when I hit enter, it's going to run that program.
So it should reinitialize the LCD and print out the hello world message.
And there it goes, except it looks like we have a bug, or at least a typo.
But since our program is in RAM, we can actually try to fix that in place.
We just need to change one byte in our program.
So if we look here, it's this byte right here, this U, and we want that to be an R.
And so that's going to be at address 3 0 3 1 3 2 3 3 3 4 3 5 3 6,
you know, 7 5 is the ASCII for lowercase u.
So if we look at 1 0 0 3 6, that address, whoops, 1 0 3 6 rather, 1 0 3 6 is a 7 5.
And to fix that, we just need to change 1 0 3 6 to be 7 2,
which is the ASCII for lowercase R. And then it replies with what it used to be.
We can just verify 1 0 3 6 is in fact now a 7 2.
And then we just need to rerun the program.
1 0 0 0 is where we want to start running the program.
We'll do R. If we hit enter, it'll reinitialize the LCD and print the new message.
And there we go.
It fixed the typo.
So hopefully this gives you an idea of how you can tweak and debug programs in
place rather than having to reassemble and re-upload to change any little thing.
Also, it's a lot easier than having to reprogram an entire EEPROM to change any one thing.
And I find it remarkable how Steve Wozniak was able to
squeeze all that functionality into just 248 bytes of code.
So hopefully you found that interesting.
And as always, thanks to my patrons for helping make these videos possible.
And if you're interested in trying any of this yourself,
check out my website, eeder.net slash 6502, for links to my modified Wasmon code,
as well as kits and schematics and everything else.