My first computer was a Trash-80 Model I. I worked all summer to save up the money to buy it. I spent something like $500 on it. It was a lot of money then, especially for a kid (I was in my first year of High School, I think). But this was right after they came out and it was still cheaper than buying a new one. It was used but in perfect condition. It had 4k basic-in-ROM, 4k RAM, and a casette tape drive that worked at some astoundingly slow rate. I forget what it was -- 1200 bps?
The first thing I wrote was a loop in the tiny basic that was built into the ROM, ran it, and immediately got a book on Z-80 assembly language. Because it was obvious I wouldn't be able to do anything interesting in 4k of RAM in tiny basic. It was just too slow and ate up RAM too fast.
The TRS-80 came with a tiny debugger that let you type hex in and run it. So I started learning assembly language, because what could you do in 4k of tiny basic? But you could do a lot more in 4k of assembly. You could do all kinds of tricks that would make a modern programmer's nose really turn up... well, you HAD to do all those tricks to get anything done in that tiny bit of RAM, so you didn't have to make apologizes for them.
I wrote my own tiny operating system, which never went anywhere other than to learn how things worked. To do anything useful, I had to interface with the hardware myself. The TRS-80 had very primitive hardware -- for example, the keys were scanned and decoded in software. There was an output port you could put a bit pattern on, and that turned on a column of wires in the keyboard. Whenever a key was pressed that set over a wire, it connected it to a different wire, and there was a port you could read to see what wire had juice on it. So with only a small number of wires (I don't remember how many, it was probably sixteen: 8 for putting juice on, and 8 for detecting juice on) you could figure out which key was pressed. Very economical, but it meant that a fair amount of software was involved in reading the keys. And the cheap metal fingers used in the keys (does anyone remember taking the keys off to clean the fingers?) used to bounce very badly, so the software had to take care of detecting and ignoring the extra fake key presses that happened because the little finger was vibrating after the key was pressed. All that took a fair amount of bit twiddling, so that's where I learned how to deal with hardware. It's also where I learned to read schematics. Radio Shack didn't release the schematics for the thing, and you need the schematics to do some of this hardware hacking, to know how the chips were put together, but I had gotten an illicit copy of the official repair manual, and it had the schematics. I didn't feel that it was wrong to have the manual -- there's nothing wrong with having a manual for a thing you own, I think. Perhaps selling it would be wrong. Giving it away would be risky if you got large scale with it, but not wrong. Information in itself does not harm anyone, and that's how hackers think. If someone was restricting information, screw them. Information should belong to us all. That's just the hacker ethic, and it was much stronger and much less apologetic then.
The tape was too slow so I figured out how the tape routines worked -- this time using an illicit disassembly of the basic-in-ROM -- information is free, remember? Screw Microsoft for saying I can't look at what's in the box I own. Microsoft was into this keep-everything-secret stuff even way back then. But hackers weren't interested in that, we weren't buying into that attitude. It was just wrong as far as we were concerned, so we were quite happy to pass around the listings we got. But anyhow, it turns out that the tape was coded very very conservatively, because the hardware wasn't always that good, so the software that drove the tape ran it much slower than it was actually capable of. With a little bit of coding I was able to put together my own tape routines that were twice as fast, still leaving some margin for safety so I could get my data back if the tape had a bad spot on it. I wrote this little bootstrap loader that the ROM would load, and then that bootstrap loader would ignore the ROM tape routines and use my own tape routines to load the program much faster. So all my tapes had this little burst of regular noise on them, and then this hiss of my program, which sounded much high pitched because I was flipping the bit on the tape much faster than normal.
This was all just simple PCM (Pulse Code Modulation)... for each bit, there was a clock bit, and then a little time after that, there would either be a data bit or no data bit. So it was self clocking, which was good, because these tape drives weren't exactly high tech and would get a little faster or slower than you expected. I think if I had known more about encoding techniques I could have gone even faster... like hard drives did when they discovered MFM and then RLL encoding, that you can jam the bits closer together if you can use some of the data bits as clock bits and not have to have a clock bit for every data bit. But I didn't know about that then, so I just did the simple PCM thing. But it worked ok.
As an aside, for those who have never seen a TRS-80 model 1 in its original form, you have to understand that the cassette tape drive was a real cassette tape drive, just a regular one you could buy off the shelf from Radio Shack. So if you wanted to, you could listen to your data tape and see what it sounded like. It sounded like a modem, really, because there's not much difference between encoding data on the phone and encoding data on the tape. And the faster you go, the higher-pitched it sounds, just like with modems. It was important to be able to hear the sounds, so you could know when your program was loading (or not loading, if something was going on), or hear if there were dropouts on the tape, so I modified the tape drive so that the speaker was always on even when the computer was plugged into the drive's earphone jack.
The tapes were always going bad, so we used to write a program two or three times on a tape to be sure we could get it back. And there was a trick -- I don't know why this worked -- if you couldn't read a tape, you could put it in a plastic bag (to protect it from condensation) and put it in the freezer, and when you took it out it would sometimes read OK if you could get through it all before it warmed up. I have no idea why the freezer trick worked, or if it just never worked and I was just being fooled into thinking it was working better -- maybe it would have worked if I had just let the tape sit at room temperature for a while. Maybe it was the tape drive sitting still while I waited for the tape to cool that made the tape read better, I just don't know. But I wasn't the only one that did the freezer trick. I'm pretty sure I learned it from another hacker.
I remember when I got 16k of ram for free. It was really expensive stuff -- the chips were something like $150 that summer, but a hacker I knew said if I gave him my 4k chips he could get me the 16k chips for free. And that's when I got to see, for the first time in my life, how a wheeler-dealer works.
We got in his car with my 4k chips and a sofware package he had and went to some guy's house. There we talked, enjoyed some great beef jerkey the guy's wife had made, and then traded. I think we traded the chips for another software package. then we drove to another guy's house, and traded the software packges for some 16k chips. It was really magic to me, seeing how he turned 4k chips and old software into brand new 16k chips. I suppose he's running QVC these days, but I don't know. I think his name was Cliff, but it was so long ago I'm not sure.
One thing I wrote was a tank game like the Atari had, where two players could drive tanks around and shoot each other. It was really two player and real time; each player got some keys on the keyboard to control the tank, and it worked pretty well. I remember sweating over the graphics routines, because the graphics on the TRS-80 model 1 were worse than awful. All it was, is that the screen 64 characters wide by 16 lines, and for the "graphics," you could break a character up into six blocks -- 3 vertical and 2 horizontal -- and turn those blocks on and off. But the blocks were really big, and only black and white, so it looked awful. But the worst part for the programmer was that you couldn't turn an individual block on and off easily -- you could only manipulate these blocks in those groups of six, by writing a different byte into a character position of the video RAM. So it really took some doing to display anything. I remember the collision routines being a bit hellish, trying to figure out if a tank hit a wall or something.
One thing I've noticed, is that programmers that hacked the TRS-80 Model I often end up being very strong in languages, logic, databases, and other back-end things. I think that's because we just couldn't really do graphics, so we just naturally did the other things that our platform could do. And that's all the non-graphics stuff, and that's why I ended up writing keyboard routines and languages and tape drivers most of the time. That's a bent I still have -- I can do GUI stuff, but I'm just not a GUI programmer. It's not what I do by choice; I only do GUI stuff when I have a very pressing need that can't be filled by someone else's code. I've been shaped by the TRS-80 into a non-GUI kind of programmer.
The assembler and the program wouldn't fit in memory at the same time, so I had to write the program in modules. I'd load the assembler, load the source for a module, hack on it (the assembler had a little editor built into it), assemble it, and write the assembled module out to tape. When I wanted to try the program, I'd load each module from its tape and only then were they a complete program I could run. There was no linker or link-loader, so I had a big table in low memory that held the address of each module's entry point. So a module would load its functions, and then load into its part of that jump table all of the addresses of its functions, and any other module wanting to call it would have to go through that jump table. It was clumsy and took a lot of bookkeeping but it worked.
Another thing I wrote in assembly was a forth-like language. I had read a book on TILs (Threaded Interprted Languages) and decided I wanted one too. I wrote code on paper, because I was "working" in my dad's store, but I really spent most of my time writing code. But it would have been too blatent to just bring the computer to the store, so I'd write code on paper instead, and then when I got home, key it in and see if it worked. That was my first experience in using paper artifacts to code, and unfortunately it biased me towards paper as a good thing. It took me some time to figure out that paper is not good; it's a necessary evil. It's what you have to use when you can't have the goodness and immediacy of quick feedback. But I didn't understand that back then -- I figured, hey, it worked pretty good for that one thing, so it must always be good, right? But it was still a neat experience learning that you can use paper to replace feedback, and I was pretty proud of it at the time.
A funny thing about my TRS-80, something different from any other one you've ever seen, is that when you first turned it on, you would only see funny characters on the screen. I mean things like a circle with a dot in it, or a greek letter... that kind of stuff. Then the characters would slowly start to flicker, and then you could see that they were trying to be regular characters, and then they were mostly regular characters with just a faint image of the funny character, and then finally, a minute later, the regular characters you expected were on the screen, the funny characters having faded to black. It was really a neat effect, but not one I got on purpose. What happened is that I had hacked an extra memory chip into the video memory to get upper and lowercase. To save money, the designers had put only seven bits of memory into the video memory (seven chips, each one having 1024 bits), and what they gave up was lowercase and special characters. But the character encoder that turned the video memory bits into bits on the monitor could handle lowercase, and I read an article that showed how to piggyback another memory chip onto the video memory to get lowercase, and so I decided to do that. It just so happened that I had one of these chips around, but it's one I had abused -- I used it for experiments. Among other things, it got sucked through a vacuum cleaner once, but I had unbent the pins and kept it. And that's the chip that went into my TRS-80. But it turns out that it just wouldn't work cold because of the abuse I had given it. Once it got warm then it worked just fine, and that's why my computer needed a minute to warm up before you could see regular characters on the screen.
The TRS-80 is where I got my first exposure to Pascal, too. There was a T-Pascal (everything for the TRS-80 was T-something, T meaning "tiny"). One of the cool things about Pascal, is if you leave out a few things, you get a compiler that can fit in almost anything. And T-Pascal would run in the 16k of RAM I had, and it had Pascal's nested functions and structures. About all it left out was floating point and the USING clause. I think it even had Pascal's nifty thing where you can declare a variable's domain. It didn't run that well, but it was good enough for learning the language. So that's where I learned Pascal, and that's what led me to Turbo Pascal later when it became available for the PC. And the first real thing I wrote in Turbo Pascal was WBBS. For which you can thank -- or curse -- the humble TRS-80 model I.