When I started out writing programs of any size, I started with BASIC on an Apple II. There were programs supplied in a bunch of the original manuals that you could type in and try. This was how I learned. My dad picked up another book called More Basic Computer Games by David H. Ahl, published by Creative Computing. Me and my brother Pat typed in the games from the book and learned a lot of practical lessons about portability, especially since BASIC had no particular standard at the time and every micro that had BASIC had its own particular variation. We also learned debugging since we typed in all kinds of interesting bugs.
I had seen games for the Apple that had a teeny BASIC prologue with an inevitable CALL into machine language. All the arcade style games were like that. My brother Pat was picking up the Apple’s 6502 machine language and I watched over his shoulder. Our machine had the “Integer BASIC firmware card”, which included a small monitor with a mini assembler, so if the switch on the card was in the right position, hitting reset (or typing CALL -151) put you into the monitor and F666G started up the mini assembler.
One day I was home from school, ostensibly sick and I got tired of hanging around in bed, so I sat down at the computer and opened the Apple II Reference Manual and started looking over the routines available in the reference. They were cookbook. The 6502 had 3 easily accessible registers (in reality, it has 6, but the stack pointer, program counter, and status register aren’t really directly accessible). A reference entry would tell you the address, the name of the routine, what it did, what registers had to be what in order to do it, and what registers were ruined/preserved upon return. To call a routine, you used the JSR instruction, which was a mnemonic for “Jump to SubRoutine”.
I started with:
$FDED – COUT Output a character
COUT is the standard character output subroutine. The character to be output should be in the accumulator. COUT calls the current character output subroutine whose address is stored in CSW (locations $36 and $37), usually COUT1 (see below).
So I fired up the mini assembler and wrote the following program:
0300: A9 C8 LDA #$C8 0302: 20 ED FD JSR $FDED 0305: A9 C9 LDA #$C9 0307: 20 ED FD JSR $FDED 030A: 4C 00 03 JMP $0300
Which was equivalent to the BASIC:
10 PRINT "HI"; : GOTO 10
When I ran it, I was aghast. The screen filled up with “HIHIHIHIHIHIHI….” before I could react. It was astounding.
With all of this in hand, I started writing 6502 machine language programs. The manual had routines for text I/O, low-res graphics, beeping the speaker, etc. I was off and running.
Writing code in in 6502 was tedious, but it was a great first exercise in practical Turing Completeness. I could write anything in 6502 that could be written in BASIC, and it ran a hell of a lot faster, but I had to write a lot more code to do it.
If I recall correctly, the 6502 had 56 instructions, many just register juggling, and in typical coding, you usually just use a handful.
I started disassembling other people’s games and learned to find the main loop that ran the game itself. These were easy to spot as they were usually just a long string of JSR instructions with a JMP up to the top. I used other tricks – like finding the code the read the keyboard and looked for code that compared the values read to the key values that started or controlled the game. Finding what called that routine usually lead back to the main loop. I would change one of the JSR’s to a BRK instruction to drop into the monitor. Then I could manually call one of those routines and see what happened on screen. When I found something interesting, I disassembled that routine and took it apart.
By looking at code written by Bob Bishop, Gary Shannon, Bill Budge, Nasir Gebelli and more, I started to learn how write code that did high-res graphics. This code taught me how to do a table look up. The standard routine to calculate the address of a scanline in 6502 was…interesting. And slow. A table lookup was quicker.
After 8th grade, my dad and my brother Pat and I went on a trip across country by car. We went to the Grand Canyon and hiking down a bit on the Bright Angel trail. It’s a lot easier to hike down than up, and on the way back, my brother Pat, who had the water took off on his own. On the way back up, in the heat, I imagined little happy creatures throwing themselves off the top of the canyon and plummeting to their deaths. When we got home, I started turning the concept into a game called, “Suicide!”. From a grown-up stand point, it’s not all that playable, but it’s fairly astounding that it was produced by a 14 year old, especially because it was all in 6502. Historically, it was the first published game with punctuation in its title. It’s a little thing, I know, but I enjoy that.
When I was in high school, I drew all kinds of doodles in my notes in class, but I also wrote hundreds of lines of 6502 to solve problems that had stumped me. Through the local computer shop, Stonehenge Computing, I found a small, thriving community of young men like me who were hacking on the Apple II, all suffering through the foibles of the 6502 and Woz’s spartan hardware design.
In college, I still hacked 6502. One of the last things I wrote for the Apple II was an implementation of Conway’s Rules of Life. A few years ago, I had a small stack of my remaining 5.25″ floppies read out and I found the source, which I put up on codeplex. To my surprise, I had commented the living hell out of it. Good for me.
1000 * THE FOLLOWING IS AN ADAPTATION 1010 * OF JOHN CONWAYS GAME OF 'LIFE' 1020 * THE RULES ARE SIMPLE: 1030 * THE SCREEN IS DIVIDED IN CELLS. 1040 * A CELL IS EITHER DEAD OR ALIVE. 1050 * IF A CELL HAS EITHER 2 OR 3 1060 * NEIGHBORS, IT WILL LIVE IN THE 1070 * NEXT GENERATION. 1080 * A DEAD CELL WILL REINCARNATE IF 1090 * IT HAS EXACTLY 3 NEIGHBORS. 1100 * ANY OTHER NUMBER OF NEIGHBORS 1110 * WILL MEAN THAT CELL IS DEAD IN 1120 * THE NEXT GENERATION. 1130 *--------------------------------- 1140 * MOST IMPLEMENTATIONS USE A TWO 1150 * BUFFER SYSTEM: ONE FOR THE 1160 * CURRENT GENERATION, AND ONE FOR 1170 * THE NEXT GENERATION. THIS 1180 * VERSION USES ONE BUFFER FOR THE 1190 * CURRENT GENERATION AND KEEPS 1200 * A LIST OF CELLS THAT HAVE 1210 * CHANGED. THIS SAVES TIME AND 1220 * MEMORY. SINCE DEATH AND BIRTH 1230 * ARE A BINARY PROCESS THE CELL 1240 * DRAWING/ERASE ROUTINES ARE ONE 1250 * AND THE SAME. THIS IS DONE VIA 1260 * EXCLUSIVE-OR DRAWING. 1270 *--------------------------------- 1280 * IMPLEMENTAION FOR APPLE II 1290 * SERIES COMPUTERS BY 1300 * STEPHEN HAWLEY 9/85
I put this comment on here because this was the point when I independently invented the display list. This was a repeating theme in college. I invented a ton of things I found out later were CS staples, and all of them in 6502.