You most likely wrote your early experimental programs in the BASIC language, using Timex’s ROM-resident BASIC interpreter and line editor. Cassette-tape storage would have been accessed using the SAVE
and LOAD
commands in the interpreter’s immediate mode.
Commercial software, however, would nearly always get written in machine language — to gain the best performance and the tightest control over the system. On the Timex 2048, this would have been machine code native to the Zilog Z80 microprocessor.
* * *
A few words on the usage of audio cassettes for storage:
In many countries, the audio cassette was the most popular storage media for the non-business-oriented 8-bit home computers. That is, more popular than the floppy disk.
Don’t get me wrong: floppy disk drives were quite popular as well — among advanced hobbyists, committed gamers, and the rich kids. But for their price, they offered just too little obvious benefit to the great unwashed masses. An FDD could cost as much as the computer itself! Hence, in many markets, tape-based systems comprised of the majority of the installed base.
The UK company behind the original design of the Timex computers — Sinclair Research — were a bit of a special case in that they did not even want to offer floppy disk drives to their users: the company deliberately dragged their feet on specifying how FDDs should be interfaced to their systems and wanted to promote a proprietary storage technology called the Microdrive in their place, effectively preventing FDDs from getting common on their systems. For the Sinclair computers, tape was the primary, standard storage format “by design”.
The original Sinclair systems were very cost-reduced. Favoring tape-based storage was maybe part of this cost-reduction strategy. But they were also very popular, and Sinclair was a major player whose products inspired and incubated lots of computer programmers who would go on to write commercial software for the platform — especially in the UK.
This needed to be said as some answers suggest tape-only setups would not have been too relevant as platforms to program on, or at all. That might have been true for the US market, but the US swiftly abandoning tapes and moving to all disk-based systems was rather the exception than the global norm.
* * *
With that out of the way, some points:
Firstly, many programmers cut their teeth on tape-based setups: owning one was nothing out of the ordinary for many markets, and would not have been viewed as any great impediment by most users, but rather just the natural state of affairs; the standard baseline.
Secondly, developing a software title for an 8-bitter was often a single-man affair. There was a man and his machine, and his wacky idea for a game — say, mutant camels. What more could one want or need — besides a publisher? (A team? Hah! Get me the cheerleaders, instead.)
Thirdly, 8-bit home computers were pretty much designed on the premise of being general-purpose computers: fully capable of self-hosting their programming environments. “A man and his machine” was understood to be quite sufficient for writing all the software in the world that the machine is capable of running. There was no underlying assumption or implication of having to purchase a separate external development kit.
Many of the programmers who got commercially published were self-taught, and started out with bog-standard, entry-level hobbyist setups.
* * *
So how would you go about writing something more advanced on that tape-based system than what the BASIC language is capable of?
Many software titles were developed directly on the target system by self-taught programmers, only using very primitive tools, such as machine language monitors and pencil notes jotted in a cross-ruled notebook.
In this kind of a workflow, you carve the machine-language code directly into the RAM of the running target system by editing the content of the memory live, as in these videos:
https://www.youtube.com/watch?v=0gBoQgeg9r0
https://www.youtube.com/watch?v=MEjnMt_3wkU
You would basically view everything in the computer’s RAM as ever-malleable putty that you can work “hands-on” and keep shaping towards the shape of the program you’re envisioning.
You could copy arbitrary memory ranges (blocks of code or data) around, and directly modify the individual bytes representing the machine-language opcodes and operands.
You could also save arbitrary ranges of memory to a disk or tape, or load bytes from a file into a desired absolute memory address — this way integrating data or code created elsewhere, or saving bits and pieces for later (re)use.
If your machine-language program were to freeze, you could hit the reset button and start your machine-langauge monitor tool again and continue modifying the code — it would remain in the memory.
The finished software title would not be the product of a compiler-linker toolchain, but a dump of the relevant RAM memory ranges; basically a curated snapshot of the developer’s system RAM from the time they deemed the project was ready for release.
The saved memory dumps would maybe have to be further prepared for commercial, cassette tape-based distribution by using a simple compression algorithm, along with some chain-loader/unpacking/initialization code, and a publisher would likely want it to be equipped with a loading screen (perhaps with music) to entertain the user while they wait for the main code to load and start.
This is certainly not the most sophisticated way to work on a software project, but you’re not really working on a fancy “software project” — you’re constructing a computer program, which is something more raw and manly. Also, simple tools, such as a machine-language monitor, do not require much in the way of resources or workflow: you do not need to manage source code files, deal with editors, compilers or linkers, etc. on your limited little system. Everything is raw and direct and immediate.
* * *
What about working with other people?
Many 8-bit commercial titles (those which were not the work of a lone coder but more grandious in their design) have maybe three persons credited: the main programmer, the guy who drew the graphics, and the guy who composed the music.
There isn’t much need for constant integration if the responsibilities are this clearly divided. Meeting up occasionally or sending in your work on cassette, by mail, would be enough.
To allow e.g. the music guy to contribute to the project, the main programmer could just set aside a block of memory at an absolute address and tell them to fit their music code and data in there while informing them that the music player subroutine may only take up so much “raster time” (CPU time during single video raster refresh) in order not to interfere with the game-play mechanics, and let them work from there.
When the guy delivers their piece, you integrate it by loading the binary data blob into the designated address, and call the agreed-upon entry point into the music player routine in each raster interrupt.
Many other things could be handled in a similar fashion.
* * *
As for keeping your work safe, you would save often and keep multiple copies. And keep hand-written notes. Or print out a hard copy of your code on continuous-fold paper if you were lucky enough to own a printer. Floppy disks were known to get random bad sectors, too, so purchasing an FDD would not have saved you from such chores.
Tapes and their content can be kept organized by maintaining an index on the inlay card, or rather in a separate notebook, by using a pencil. The index would be based on the mechanical tape counter readings and file names. (Most implementations of cassette tape-based storage stored a header with a filename on the tape so you could theoretically search for a given file from the current position onward, by its name. But this could only be done at the normal playback speed, so in the normal case, you would first want to rewind or fast-forward the tape roughly to the correct position, using the manually operated, mechanical tape transport buttons and the tape counter readings as your guide.)
* * *
The above descriptions concern a scenario where you pretty much only have a standard tape-based system in your possession, with no expansions.
Would a more elaborate programming kit have helped an aspiring programmer? Certainly. But was it a necessity for commercial software development? Definitely not. Determined, clever people could do wonders using the rather simple tools and environments they had at hand. Things were maybe tedious and tricky — but they sort of always were, on these systems. You would have to figure out the best solutions for overcoming any obstacles mostly by yourself (most people would not have had access to any online community), but as they say, where there’s a will, there’s a way.
Granted, getting some expansions for your lowest-specification base system — such as a RAM expansion, or a more advanced method of mass storage — would make things more convenient.
Be that as it might, a cassette tape-based development workflow on a standard, unexpanded system would have been fully possible — even when having a couple of more guys working on some particular aspects of the game.
Ultimately, programming the 8-bit systems in machine language can be reduced to arranging the bit patterns in the RAM (or in a file) into the desired order — and you can practically always do that, even without purchasing anything extra. Almost all systems came with a built-in BASIC interpreter which readily allows such memory and file manipulation, and therefore writing your own tools. Even if you would not want to keep using BASIC itself for anything, you can bootstrap yourself to better, self-written machine-language tools using BASIC.
* * *
Overall, there was a vast range of possible tools, environments, and development styles. The answer written by Wayne Conrad covers the use of an assembler-based workflow — self-hosted on the system. Other answers mention cross-development tools. However, obtaining another, more powerful PC would have been out of the financial reach of many.
Big, established companies with actual programming teams on their payroll would do things in a much more organized manner than a lone coder, using fancier in-house tools — especially in the later years, on the most popular systems. But were most software titles actually developed that methodical way, for these machines? I’d say hell no. A man and his machine — the lone developer and possibly his cat, maybe accompanied by a GFX or SFX guy, the bossy boss, and Laura from the front desk (who also answered the phone, drew the cover art, tested the levels, and handled packing and shipping) — played a big part. Or so I would imagine.
It must be understood the overwhelming majority of the actual users of these systems were kids, teenagers, and young adults with no formal education in computer science or background in programming. These were also the people who ended up writing much of the software for them.
8-bit home computers were, for many, the first dip into the world of general-purpose computers. Previously, computers were these large multi-user systems or batch-processing behemoths owned and operated by an organization — a university or a telecommunications company, a bank, an insurance company, or your friendly tax authorities. But now you could own an itty-bitty computer yourself, as an individual, and were free to experiment with it as you please.
Not only that, but the home computers had color graphics and sound — features making them suitable for video games — or for some new kind of digital underground art, even — and features definitely not offered by the “serious” systems, because they were oh-so-serious and “all business”. (Business, as we all know, is dull and monochrome and gets by with green-screen text mode and square-wave error bleeps only.)
Personal computers — especially the cheap, colorful, TV-connectable, home-oriented ones — were a great paradigm shift in how people could access and use computers. Much of their early use, and the practices related to those uses — including the practices related to developing commercial software for them — could be labeled as being experimentative and hobbyist-amateur-driven. But that was exactly the fun of it.
* * *
Finally, to expand a bit on the tools and hardware additions, floppy disk drives were not the only way to beef up your programmer’s kit, and not even the only way to get access to a better form of mass storage than audio tape. Many systems had fancy aftermarket memory expansion and ROM tool cartridges available — providing much more RAM workspace than is available in the standard out-of-the-box configuration, and possibly including ROM-based tools — such as a machine language monitor. A programmer could use the extra memory as workspace for storing code or data snippets or memory-resident tools while working on the project which targets the unexpanded hardware.
Some of the more advanced expansion cartridges allowed much more memory to be installed on them than the CPU could address (the extra memory being accessible via memory banking) and were battery backed-up and able to retain their content for as long as the capacity of the battery allowed. They could also simulate a disk drive, in RAM disk style. This made them usable as semi-persistent, lightning-fast scratchpad for your project files or tools.
There were also aftermarket HDD controllers for the 8-bit home computer systems. The very cost-reduced Sinclair ZX81 apparently had one designed for it as early as in 1982 — something Sir Clive Sinclair himself has been quoted as characterizing as “quite overgilding the lily”. These, equipped with an actual HDD, would likely have been prohibitively expensive and viewed as very exotic special-purpose kit by the typical users of such systems, but such solutions did exist for those who had the need and could afford one.
As mentioned, commercial cross-development toolkits were available for some platforms. Another, more powerful system — such as an IBM PC or AT-compatible machine — was harnessed for editing and compiling code for the 8-bit target system. There was typically a cross-assembler running on the development system, and a proprietary data link of some sort connected to an expansion port on the target system. The latter would allow quickly uploading the compiled code to the target system’s memory space for testing. If you were very professionally-minded about software development, you could have used one of these — at the cost of obtaining another, much more expensive computer and an expensive cross-development product to run on it.
The answer provided by Wayne Conrad is an excellent read, as are the entries in the ”Linked” section and the free PDF book (It’s Behind You: the making of a computer game) mentioned by lvd.