Tutorial on 9845 Game Design
Why and How
As long as automated data processing exists, implementing games on computer systems had been one of the most deeply settled desires of any computer programmer.
One reason of course is the challenge. Games always had been the killer applications for each computer generation, especially within the personal computer domain. This was true with the very first systems and still is one of the most important driver for the development of faster personal computer systems.
Wereas real mainframes were most of all number crunchers and excelled primarily on pure computation tasks like chess algorithms, workstations and as such the HP 9845 were in the middle between home computers and mainframes. Many home computers were much better suited for game development, however it was not impossible to implement games on a 9845, and some features like the large memory space, the fast 16-bit dual CPU processing or the vector generators could beat home computers by far for certain applications.
Actually, performance always depends on specialization vs. generalization. So, for example, simple, bitmapped low resolution graphics with slow eight-bit processors could outperform a hundred times faster platform, depending on the specific task. On the 9845, graphics memory access was either done through high level graphics commands, or by the use of some kind of data streaming, which - although working at DMA speed - was mainly intended for save & restore of the full graphics contents and not as fast as memory mapped access. Low level bitmap operations, although possible and partially implemented with the "rubber band" functionality, simply were not really part of the concept. Among the small and affordable home computer systems probably the early Ataris (400 and 800) with their GTIA and ANTIC custom chips were the ones which showed best what was possible in the late 70's with comparably cheap hardware.
The strength of the 9845 system was directed much more towards engineering requirements like CAD (where the 9845 outperformed most other systems) than to arcarde style games. Unfortunately. But only this purpose justified the high price of the systems. Unfortunately, because some simple extensions like some extra graphics memory for loading the shape objects and some extra firmware for the advanced vector generators and the 9845 systems would have made fantastic gaming platforms.
This section now concentrates on what can be done with a 9845 system, and how it can be done. Using a prominent example the basic concepts of programming games on a 9845 system are diskussed. I also will try to give some insight into game related hardware and concepts in general, with some relation on what is supported by the 9845.
In case you want to learn more about games written for the HP 9845 platform, also have a look at the new 9845 Games Section.
Background: Basics of Game Design
In principle not much has changed during the years. Success of games still can't be planned, but yet there are a couple of rules good game design should obey:
- Motivation:
Just like a good book, each game needs a story which drives the player to his/her limits. The game has to be demanding and it has to apply to basic human needs, such as collecting, puzzle solving, constructing/building, acting control, thrill, advancement, approval and awarding. Typical instruments or instances for awarding are rankings, medals or skill levels. Typical game genres like action shooters, role play or or strategy games are more or less a matter of specialization towards those needs. - Playability:
It may get hard during a game, but the degree of difficulty has to be build with reasonable relation to the expected reward. Trying again and again without noticeable success will soon lead to annoyance. Also the game should not be too complex to understand, although possibly without limits in terms of game depth. No one likes to take a course or to read books of documentation before starting a game. Everything should be intuitive and all training must happen as far as needed invisible and step by step. - Seamless gameplay:
Nothing bothers more than permanent interruptions, long pauses or frequent repetitions. Choppy animations look ragged and unprofessional and attention drops with every break. The player likes diving into the world of the game, and every disruption pushes him back into the real world again. A game should, if possible, address all senses in order to bring illusion towards perfection. - Appeal:
This has something to do with innovation and trends. Once even plain and simple video games like Pong had incredible success, simply because they offered a completely new and fascinating type of entertainment.
Most other rules apply more or less to what an individual player expects in a certain situation. There are the quick games in between, and the long-term strategy and role games with casually never ending game play.
Technical game design always means to drive the system hardware towards its limits. Before designing a game, you need to know the capabilities of your system quite well in order to plan best possible leverage of what the system supplies. Today, modern game design packages provide everything you need for development and, of course, for distributing and running the games. This makes it possible to keep the development efforts even for complex games within limits. And it provides a high degree of independence from the underlaying hardware (which is highly standardized anyway), so that platforms differ more or less in terms of visibility details and display quality such as anti-aliasing, resolution and - of course - frame rates, but no game developer today has to know anything about the hardware details.
This was different in the early times of computers, where freedom of game design was frequently limited by hardware capabilities, such as CPU performance or support for color or sound. So - with a few exceptions - the really successful games did not come from the computer scene, but from entertainment industry, which was mainly represented by the arcade game machines. Those game machines, although using standard computer parts, were highly tuned towards efficient game play. Most were built with robust cabinets and controller hardware, which provided some reliability even under heavy use.
Most arcade game system hardware was custom design. But, just as with car racing and rock-solid familiy vans, arcade experiences had a strong influence on computer games hardware, and, most of all, popularity of arcade games was extremely important for the marketing success of both video game consoles and computer games. This lasted for roughly twenty years, until average video consoles and PCs got so much capable, that special development for arcade systems did not revenue any more.
The HP 9845 and Games
The 9845 was - of course - not designed with gaming in mind. Solid engineering for grounded engineers. In fact, although fast and compact, workstations in general never had been really good game machines. Too few were sold at a too high price to justify investments into game development. However I am almost certain, that the importance of gaming capabilities had been highly underestimated for those systems. It showed that when doing a purchase decision, there are always non-rational aspects which may finally turn the balance. And the target group of the workstations had been highly susceptible to all kinds of technology aspects, including high-tech gaming.
Anyway, even HP offered a package of popular game ports to the HP 9845 system. Also, enthusiasts did both additional ports and own developments. But due to the non-disklosure policy of HP, not much of the know-how needed for the development of really demanding games had been available. So most programs were limited to what BASIC supports, and this was anything else but fast real-time action. Not even one single assembler programmed game is known, in contrast to e.g. most home computers of the time.
Looking a bit deeper into the HP 9845 hardware and operating system, we can find both limitations and possibilities with respect to what a game developer can use.
Game Logic and Physics
The HP 9845 systems were fast machines. Programs written in machine language for home computers could be imlemented on the HP 9845 in BASIC, with no loss of speed, especially with the model 200 systems which were equipped with a special bit slice language processor. As long as no PRINT statements were used. PRINT statements tend to slow down a program dramatically.
HP's implementation of the BASIC language is one of the most powerful available at the time of the HP 9845. All numbers are calculated at full speed in full precision floating point format, thanks to the BPC maths hardware. Special matrix commands provide fast operations on large numeric arrays. Interrupts could be handled in BASIC, too. And for easy bug handling, sophisticated tracing and debugging features were already part of the language. Even structured programming was supported (unusual at the time for BASIC, yet requiring a special option ROM). So for many applications, there was no need to use assembler, although even this would not have been a complex task with the support of the Assembly Execution and Development option ROM, which provided a complete hybrid BASIC/assembler development environment.
And last but not least, thanks to the dual processor design, tasks can be distributed among both processors (e.g. game logic on the LPU and background tasks on the PPU). As a conclusion, the 9845 systems were in principle well suited for programming game logic, movements, interactions and reactions. Maybe better than any other personal system at the time.
Speed
For most games speed is an issue, in particular for action games. Now fortunately, the HP 9845 is not a slow system. But in fact the BASIC implementation was only optimized on performance for certain types of applications, mainly of the engineering and scientific area. Whereas matrix and floating point operations are (compared to other systems of the time) lightning fast, simple 16-bit integer calculations - although directly supported by the CPUs - are not part of the HP BASIC concept. If you believe it or not, full precision floating point calculations are faster than 16-bit integer operations, simply because HP BASIC on the 9845 takes the integer value, converts it to a floating point number, does the calculation, and then reconverts the result to integer format. The only exceptions are FOR-NEXT counter variables and array indices, which in fact work faster with integers than with floating point numbers.
Also the HP 9845 BASIC implementation suffers from some overhead. Just as an example, processing a single line of BASIC alone without any command execution or expression evaluation takes about 200 microseconds on standard LPUs, which is a remarkably high amount considering a CPU clock speed of nearly 6 MHz. Since commands can't be combined on a single line, this already makes a significant part of the overall processing. Reason probably lies in the way HP BASIC is dealing with asynchroneous events: Interrupts generated by hardware (keystrokes, serial communication input etc.) are immediately served by the interrupt controller which is built into the PPU. The controller immediately stops processing and branches into a registered firmware routine (the ISR).
The PPU now checks whether an LPU action may be required. If yes, a signal is set for the LPU, but the LPU is not interrupted in its current processing. The only way for the LPU to get knowledge of the interrupt is to check once on each processed BASIC code line for the presence of a PPU message (this regular polling is called end-of-line branch). This (and some other things checked at this point) takes some time. It can be switched off with the DISABLE command, but all user input is then lost, too (keycodes can be polled from select code 0, but there is no indicator whether a key is currently pressed or not). In any case, one have to admit that other BASIC dialects do not provide interrupt processing on BASIC level at all.
Most of these performance restrictions are addressed by two different approaches, one is HP's Assembly Programmer's Utility, which translates a subset of the BASIC language including integer arithmetics efficiently into assembly language programs (similar to a compiler frontend), the other is the bit slice processor option, which implements the most important BASIC routines directly in processor firmware.
The Assembly Programmer's Utility is keen because it is a software-only solution, however it needs the Assembly Execution & Development ROM for producing and any assembly option ROM for running the final machine code, and it won't support several important features like string processing or interrupt handling. And, since the translator is written in BASIC, it needs much time and memory for compilation. However, once the programs are translated, they run at the limit.
The bit slice processor option (code name "Steamer") is another perfect enhancement, since it speeds up almost any type of BASIC programs by a factor of 3 up to 10 and more without any changes on the program itself. Just as an example, processing of a single BASIC line takes 30 microseconds on the bit slice LPU compared to 200 microseconds on a standard LPU, which is a performance gain of more than factor 6 for one of the basic speed indicators. Machine language code, on the other side, does not take profit from this type of performance boost, since it is executed in the original way.
Now what is the impact on game design? The Assembly Programmer's Utility is fine, but needs at least extensions for string processing and a library for character graphics for being used as game development tool. And even then, the produced program would run only on systems with one of the assembly option ROMs. So if maximum speed is required, the bit slice processor seems to be the better choice, however it does need special hardware.
Real Time
Some games need real time functionality, for example for tracking time constraints or for constant scheduling of certain tasks. The plain HP 9845 system only supports WAIT commands, which pause all LPU execution for a certain amount of milliseconds. Measure is not too precise, but with high enough numbers it works with less than 10% deviation.
The genuine option for real time functionality is the HP 98035A Real Time Interface, which actually is not an interface but a battery back-up'ed real time hardware clock. It is very precise up to milliseconds, and provides a date/time clock together with several programmable high-resolution timers, which can also trigger interrupts. This is all you can whish for game design, however you need the interface hardware, and this is not common and therefore not too easy to acquire.
Although constant task scheduling is best achieved with regular interrupts, scheduling can also be implemented with some kind of self-adjusting loops. Self-adjusting means, that the number of operations between those events which we like to happen in constant intervals, multiplied with the time needed for each operation, has to be constant. If there are less operations between the regular events, we simply have to include dummy delays.
Sound and Music
Sound is what makes computer games atmosphere, and it provides additional means for interactive feedback. Normally so-called Programmable Sound Generators (PSGs) or sound samples did the job. Early arcade machines also implemented sound synthesis implemented by analog circuits. Since sounds normally happens in parallel to other operations such as moving objects or querying controllers, there also must be some mechanisms to schedule playing scores e.g. in sync with vertical retrace of the CRT (normally done within an interrupt service routine) and to play samples independent of the CPU e.g. with direct memory access (DMA).
Describing the built-in capabilities of the 9845 we are quite quickly through. There is only a single beeper with a fixed frequency, a fixed duration and a fixed volume. Activated within a BASIC program with the BEEP instruction or within assembler by simply writing to a register on select code 0. That's it. There was no option to add more sophisticated sound or music to the HP 9845 but to build something on your own. With one single exception. You could program the sound hardware of digitizer tablets via HP-IB and HPGL (see the Digitizer/Plotter/Sound Project section).
The main drawback with those digitizers is that new sounds are only possible after the last sound pattern has been completed, and the I/O system for this device is blocked until this happens. Normally, game flow would freeze as long as sounds are active, however thanks to the dual processor design of the 9845, while the PPU is doing the I/O, the LPU still can handle everything else and no freeze happens as long as not too many sounds do overlap. Assumed OVERLAP mode is enabled.
Of course there is neither support for PSGs (although some already had been available at the time of the 9845), nor for playing sound samples (although the 9845 in principle supports DMA). So there is no direct way to play digital wave data or create noise like explosions. The only solution would be to communicate with another intelligent device which acts as sound controller. See the Featureboard Project for some ideas related to that subject.
Text vs. Graphics
All 9845 systems provide two different, completely independent display systems: the alpha display for pure text, and the graphics display for high resolution bitmapped graphics. For really fast action games, the text buffer is much better suited than the graphics option since with every access to screen memory, a character matrix is written instead of individual pixels. This also has the advantage, that it works (almost) independent of the 9845 model used. The text buffer is memory mapped and located in the R/W memory address space of the PPU. It starts at octal address 70000 for 98750A standard displays or at octal 60000 for 98780A enhanced monochrome or 98770A color displays.
The alpha controller fetches the text data from this buffer during display refresh via so-called 'cycle stealing', so processor and alpha controller share access to this buffer but without noticeable latencies. The alpha controller does this in a semi-intelligent way by checking for each word in the buffer whether it actually holds character data or one of a small number of control commands. Control commands can be placed anywhere in the display buffer and provide changing text attributes, branching and partial line processing. This dynamic structure is great for easy scrolling, windowing and efficient use of the buffer memory so that as many display lines as possible. But not necessarily for game programming, where a static buffer is easier to handle.
This issue is addressed by a special binary program called SPRINT, which can be used for first setting up the display buffer as static buffer, and then do fast reads and writes from/to this buffer. This includes using text attributes like color, blinking, underline, inverse and blinking underline, as well as utilizing line drawing characters, providing at least the same capabilities as e.g. a PET/CBM machine.
But graphics is what really makes up the strength of the HP 9845 family. Optional for the standard HP 9845A and B, and included for the HP 9845S, T and C, graphics are high resolution, hardware accelerated (with 98770A or 98780A display top) and capable of color (9845C only). The whole development concept provided means for very fast and flexible graphics programming, which in fact was outstanding at the time. The strengths of the 9845 graphics subsystems are at the same time its weaknesses. Since graphics hardware was well-separated from the central processing units, efficient low-level access by simply writing into certain memory locations - as it is done with memory mapped bitmap graphics on most home computers of the time - is not possible. So fast graphics programming is in principle limited to what the graphics hardware can do on its own, of course under CPU control. Which is in general fast line drawing and area fill for the HP 9845C plus erase, rubber band and arc/circle drawing on the 98780A enhanced monochrome graphics. But also fast DMA transfer of continuous memory to and from the graphics buffer.
Originally, the graphics capabilities of the HP 9845 system family were fully oriented towards flexibility and versatility. Similar to the Graphics Kernel System (GKS) from 1977, the 9845 graphics subsystem is a high level programming environment which works almost completely independent of the graphics device used. This makes transformation of real world applications easy, several coordinate systems provide different levels of abstraction, and sophisticated scaling and clipping transformations match almost any requirement. But all those transformations also require processing time, which is expendable at least for game development.
HP addressed this issue with so-called absolute plotter units (APUs). All graphics operations on this kind of measure bypass time-consuming transformations and directly address hardware coordinates (560 by 455 for the CRT display). With the color and enhanced graphics option ROMs, HP also introduced fast list-driven multi-draw operations, the MAT graphics statements, and in particular the MAT A* operations, which directly stream 16-bit integer coordinates to the vector engines. This was and still is fast.
Screen Animation
For gameplay something must happen on the screen. Several well-known classic games leverage certain capabilities of different display types. Just as examples, Asteroids, Battle Zone and Star Wars all were optimized for vector displays, Qix was good for vector generators, and most others did work well with bit blitting or overlay hardware (sprites). The HP 9845 is strong on creating high resolution images, but not on moving objects around the screen. The vector generators of the 98770A or the 98780A display tops are perfect for Qix, but this is probably the exception.
Anyway, although far below the performance of the vector generators, access to the bitmap memory of the graphics subsystems is possible for the 9845 processors, too. And even a special GPRINT binary is provided to support drawing and moving objects on the 9845 display. But, as stated above, with limited performance since all the data has to be negotiated with the graphics display as peripheral and transferred over the I/O bus. See the Dogfight game within the 9845 Games Section as an example.
The 98780A enhanced graphics display also implemented a technique in hardware called 'rubber banding'. Key feature was that random shapes could be drawn with standard vector commands e.g. from a vertex list and without destroying the background graphics. This was achieved with assistance of a rubber band pixel memory of 4,095 pixels, which simply buffered the existing pixel data during draw, so that the original background could be completely reconstructed when erasing the shape with exactly the same vector commands. Originally designed for simple straight lines ('rubber bands') with one end fixed and the other end moved by the input device, this technique could be used to animate much more complex objects. 4,095 pixel doesn't sound much, but in theory more than 80 vectors of an average length of 50 pixels could be used to make up a shape.
This worked completely on the fly and was well suited for moving vector shapes smoothly around the screen, even for multiple objects, as long as the rubber band memory was not exceeded. A similar technique was implemented for the Apple II in software (Applesoft BASIC) with the so-called 'shape tables', however not as sophisticated and performant as on the 98780A display. Unfortunately HP BASIC supports only using 'rubber bands' in the original sense as pointer/cursor alternative - full rubber band functionality for arbitrary shapes is available with assembly programming only. There also is a software-only implementation of rubber banding for 9845C systems with the RUBBND binary program, again limited to pointer/cursor operation. The 9845C has no hardware support for rubber bands as the enhanced monochrome graphics does, however non-destructive animations can easily be achieved by accessing the memory planes separately.
Left is the technique which works with almost any system: using character shapes on a text based screen. Advantage is that the access works very fast but (this is the disadvantage) not with HP 9845 BASIC. Quite contrary HP 9845 BASIC provides extremely slow access to the display data, even slower than most home computers, which probably is caused by the extensive flexibility of built-in formatting options and the overhead needed for re-organizing the data in the text buffer. That text buffer also normally does not allow low-level random positioning, so the text buffer has to be set up properly for full use which, again, is not possible within BASIC but with the SPRINT binary mentioned above.
With SPRINT, that problem has been addressed by some developers, by supplying extremely fast access to the alpha screen buffer. In contrast to GPRINT, SPRINT is quite generic, so it does only support low level access to the sceen memory, but no blocks of characters covering more than one single text line.
Finally, there is no way to define custom characters for the CRT display (as it is possible with the thermal printe)r - all CRT characters are hold in ROM within the display tops. The built-in set of characters does not include too many graphics symbols, so composing shapes from characters is limited to ASCII plus international plus a set of line drawing characters. But including hilighting (inverse, blinking, underline) and color (9845C only).
Bit Blitting, Tile Maps and Sprites
One of the essentials of 2D game design is efficiently creating backgrounds, landscapes or scenes within games by being able to rapidly draw pre-defined patterns on the screen. This usually is achieved by copying data from some designated memory areas holding predefined tile patterns into the frame buffer memory creating "tile maps". The copying process is also called BLock Image Transfer, or BLITting. By sophisticated use of tile maps, even complex scenes can be created quickly with very little pattern storage. Copying character data into graphics memory for text display can also be considered as a simple application of blitting.
Blitting can not only be used to render backgrounds, but also to move and animate objects (sprites) around the screen. Some R-Type like shooters are using 20 or more sprites at one time on the screen, and arcade hardware such as the CPS-III system from Capcom could support up to 1024 independent sprites with hardware scaling. Animation is easily achieved by modifying the content of the sprite source memory or by simply changing some source address pointers. Moving sprites includes restoring the previous background after every move.
Normally tile maps also include a special "color" which stands for transparency (i.e. "don't overwrite frame buffer data at 'transparent' pixels" or for more sophisticated hardware with different levels of transparency). More complex blockwise operations on bitmaps and tile maps can include combining more than one tile pattern for the same target, color mixing, horizontal or vertical flipping, rotation, or logical operations.
In order to free up the CPU from doing blitting or tile map operations on its own, newer systems such as the AMIGA (Agnus) or the Atari ATW (Blossom) had dedicated blitter hardware which used direct memory access (DMA) to perform fast tile map operations without the involvement of the CPU. In fact, specialized hardware could outperform any general purpose CPU for block operations by an order of magnitude.
An HP 9845 in fact has some kind blitting mechanism to rapdily copy data from system memory into graphics frame buffer memory via DMA (and back from frame buffer to system memory) without the involvement of the CPU. The implementation differs a bit between the display models: For the the standard display (98750A) and the color display (98770A), the data transfer is not limited to a certain tile, but always writes the data into consecutive frame buffer memory, thereby spanning the whole scanline. That means, that each tile transfer has to be split up into separate transfers for every scan line.The enhanced display (98780A) also supports vertically organized tiles (16 bit wide with arbitrary height).
Another restriction is that the target address of the hardware BLIT operation is always on word boundries rather than towards a pixel address. Also, the HP 9845 always overwrites existing frame buffer memory, and it is not capable of supporting transparency, flipping, rotation or logical operations.
The GPRINT binary makes use of the BLIT feature to quickly copy image data from an array into the frame buffer. HP BASIC provides the GLOAD and GSTORE instructions for block image transfers. A simple example is the implementation of non-destructive pop-up menues in the mouse graphics drawing demo (see Mouse Project Section).
Hardware Scrolling
Smooth scrolling within games is generally rarely done by moving the full frame buffer content (which requires tremendous computing time), bur rather by copying new data into "invisible" parts of the frame buffer, and then stepwise moving a kind of "visible window" (which defines which part of the fame buffer is shown on a pixel by pixel basis) so that the new data appears into the picture line by line.
Although a HP9845 standard graphics display offers off-screen "invisible" frame buffer memory which can be written to, there is no hardware windowing for the display which might be used to scroll into that area. So the invisible area strictly keeps invisible and finally is of no use at all. The enhanced or color displays offer no such off-screen frame buffer memory.
Vertical scrolling on graphics however is supported in hardware for the enhanced display, where the start of the effective screen memory can be defined.
Also text can be scrolled for any of the 9845 displays by altering the start address of the text buffer memory, but won't support smooth scrolling on scanline level.
Shapes
This feature is known from the Apple II and means drawing pre-defined graphics primitives (normally vectors) instead of memory blocks, again with remembering the existing frame buffer data before the write and restoring that frame buffer data before the next move.
The HP 9845 enhanced graphics system provides a special circuit, which implements exactly this feature with up to 4095 pixels which can be restored. Main application was a "rubber band" connecting some point with the currrent (moving) cursor position without destroying the background, which led to the name of that feature (see screen animation above).
Overlays
In contrast to writing into the frame buffer memory like it is done with tile maps, overlays are added to the video output after the video data has been read from the frame buffer memory without altering the frame buffer memory. A typical application is the rendering of a mouse pointer or graphics cursor. The video data for the overlay in general is kept somewhere apart from the frame buffer. One of the first examples for overlays have been the "Player Missile Graphics" of the Atari 400 and 800 computers.
Mixing can be done in different ways, frame buffer video information can be combined with the overlay in a translucent way, or overwritten/replaced with full opacity. Again posssibly with a special color for tansparancy and logical operations.
The HP 9845 in general offers overlays only for the graphics cursor, not for separate video data. The HP 9845C color display is capable of mixing color text and graphics information independently within one display, which opens up additional possibilities.
Collision Detection
Within games it is often of high importance to easily detect when a moving object (such as star ship) touches other objects (like a other star ships or playground objects) in order to properly handle that situation (e.g. initiate an explosion sequence and reduce the number of lifes). Many gaming platforms offered some indication on collisions which could be polled or which triggered appropriate interrupts.
Unsurprisingly, there is no such feature for the HP 9845, so any movement and collision detection must be done under full control of the CPU.
Real Time Display Tweaking
In order to pass by hardware restrictions such as a limited number of colors, many game systems provide the possibility to create software interrupts on horizontal or vertical retrace/blanking, which enables the CPU to alter video display properties such as color palettes on the fly from one scanline to the next or between frames. Changes then can be synchronized with the display e.g. for implementing smooth scrolling, double buffering or split screens. Regular interrupts on vertical blanks also can be quite useful for checking input controller status or to play music scores in the background.
Unfortunately, there is no such feature for the HP 9845, although at least the vertical retrace signal is theoretically available with the status of the HLT line and can be polled with the SHC instruction in assembler. Again it would just require a small change to the display interface to also generate interrupts on vertical blank.
Game Controllers
The HP 9845 supported a large set of controllers for human interaction like digitizers and even a light pen, however again they were much more specialized towards CAD like applications than for moving pacmans. So the keyboard often is the first choice to use. On the 9845, it is not possible to query the key-down state of certain keys (you can only write keystroke handlers or poll the keycode of the last key pressed). Again this is due to the well-planned design of the HP 9845 where anybody thought about good practice and nobody about gaming. So key press is only reported once via interrupts, and only the arrow keys, which work as three-state-keys, have built-in auto-repeat capabilities. All other controller devices need an interface module for connection.
The original 9845 peripheral concepts did not include support for computer mice, but with a 98036A serial interface and a Assembly ROM you can connect and utilize a mouse with your system (see the 9845 Mouse Project).
Connecting a joystick could be best done with a 98032A GPIO interface. All 16 input lines are fully buffered, so building an interface to up to three joysticks with trigger should not be a problem. The 98032A interface can be programmed to generate interrupts, alternatively the data can be polled from the interface.
Timers
It is nice to use timers for numerous types of game activities. The most important application is the game engine itself, which should be timer controlled rather than running freely to implement a game speed independent of the actual hardware performance.
In the standard 9845 configuration, there are just two built-in time references, the vertical retrace, which resets 60 times in a second, and a WAIT instruction which simply puts the LPU into a wait loop for a specified number of miliseconds. Both types are not suited for game programming, the vertical retrace because it needs assembler programming and must be polled (no interrupt can be generated on retrace) and the WAIT instruction prevents any other action until the command is completed.
However, if you own a 98035A real-time module, this nice device provides everything you need, multiple independently programmable high resolution timers including interrupt capability.
Also, the light pen controller can be programmed to generate interrupts on every vertical retrace on a 60 Hz base. This controller is extremely rare and fits only in the 9845C and 9845B model 200 displays.
Randomizer
Many game functions require random decisions which direct gameflow into intentionally unpredictable directions. The HP 9845 BASIC provides the pseudo-random number generator function RND() with its seeds controlled with the RANDOMIZE command. Like all other strictly software implemented random number generators, the 9845's RND() function is anything else but unpredictable and generates in case of doubt same results after each program start. But it can be used to get a certain level of event distribution along the game play which effectively appears random to the user.
What Would Be If...
Now what changes to hardware design would have been practical for the HP 9845 to do better game developments? Let's try to feel like one of the HP 9845 designers, with the knowledge of that time. Besides developing custom chips like the Atari 400/800 (which would have been without doubt the best but most expensive solution) even minor changes to the design would have made the 9845 a quite capable game machine, such as
- The possibility to generate interrupts from the vertical retrace. This would enable many software solutions implemented as interrupt service routine (ISR), such as real-time counters and scheduling tasks like sound control or I/O polling. Updates of 60 times per second are sufficient for most game processes. Keyboard and vertical retrace interrupts could be separated with the current keyboard interrupt bit in R7 plus examining the HLT line.
- Using the R6 keyboard register for sound control. A simple solution would have been an 8 bit rotating shift register as sound pattern, clocked by an 8 bit programmable counter which again is clocked exactly with the same circuit as the existing beeper, both loaded from the IOD when the (currently unused) R6 out register with select code 0 is being addressed. A similar solution had been used as home-brew feature for the PET hardware.
- A hardware randomizer. A simple circuit based on a plain white noise generator with two transistors, another transistor for amplification, a Schmitt-trigger for generating TTL squarewaves plus a constantly clocked shift register would have been a perfect solution. If coupled with the sound pattern register above would make a perfect noise generator. The randomizer also would help statistics, which had been an important application for the 9845 systems.
Sample Circuit for a Simple Binary Random Number Generator by Aaron Logue
- A simple buffered 16-bit parallel input port for connecting digital controllers like joysticks (enough for three joysticks with trigger), built up with two 8-bit latch registers and two 8 bit buffers and wired to R4 address on select code.
More elaborate extensions, but still feasable would have been:
- The possibility to define custom characters. Harder to achieve, since the 9845 alpha display doesn't have own memory installed (unless the graphics option is present) and programming this additional memory would need some kind of handshake which is currently not implemented. Easiest solution probably would be some static RAM in the CRT, plus a simple circuit which fetches the first word after the display data has been read into a counter register, which again controls feeding the next n words into the SRAM. This would have required minor changes in the alpha control state machine, plus a switch to fetch the character data from the SRAM instead of the ROM, e.g. triggered by one of the reserved bits the character control commands.
- Implementing overlay sprites in the graphics hardware. This would require a complete new circuit with extra sprite memory and x/y-controlled overlays. Controlled by a mask the sprite data simply replaces the graphics serializer's digital input data or gets mixed with the background graphics by the or'ing with the digital input of the graphics memory serializer. No background saving memory as used for the rubberband circuit would be needed, since the content of the graphics memory would not be changed.
- Fast bit blitting: Use a reserved memory buffer area as a source for e.g. pixel accurate tile mapping. This probably would just require some extra RAM for the pattern memory plus small firmware changes for the graphics processors.
- Another nice feature would have been a 15-bit-wide look-up table with eight entries for the 9845C in combination with a proper DAC, not only for more flexible color handling with the same amount of display memory (e.g. with 8 shades of grey), but also for instant changes with effect on the full display. The existing MEMORY command could have been used to set up this look up table.
- Another application for a DAC would have been the output of digital sound samples (wave output) with a fixed rate between, say, 8 and 15 kHz. Since this rate is too high to be handled via interrupts, a DMA solution for wave data access would have been required. Would have made nice applications possible including speech output and MIDI instruments. A multi register design on the keyboard/printer device plus a programmable analog amplifier would supply the system with a master volume, which would also be nice for the built-in beeper (which has no volume control, too) or for simulating explosions with the noise generator mentioned above.
Some of the features diskussed in this section have been addressed within a sample hardware design I did for a special add-on multimedia device which I call the "Feature Board". Please check the appropriate Feature Board Project for more information.
The Space Invaders Example
Now let's see how to write games for the HP 9845. I chose Space Invaders as programming example for 9845 game design for a couple of reasons:
- It had been a real milestone in the history of computer games (technically and commercially) and practically founded the shooter genre
- It had been released as arcade game almost at the same time as the 9845 series came up
- It can be easily implemented with character based animations (an early PET port showed how that could be achieved)
- Complexity is not that high that it can't be implemented within a couple of days
- I loved it 30 years ago and still do
Screenshots of the Original Space Invaders Arcade Game
Space Invaders had been one of the commercially most successful games ever. The estimated revenue for the developing company Taito was around USD 500 million. Space Invaders was one of the very early arcade games (released in 1978), still with black and white displays, but with colored transparencies which provided an illusion of color. One reason for the success probably was the coincidence with the Star Wars movie, when space themes in general were quite popular. Ports to other systems often boosted sales, it is reported that the Atari VCS 2600 port (which is said to be the first ever home adaption of a coin-up game) quadrupled sales, and that a relevant number of PET machines suffered from the frequent use of the A, 4 and 6 keys.
Space Invaders Cabinet
The story is quite simple. Waves of descending aliens attack your home planet and your mission is to prevent landing by eliminating all aliens with your lasers before they succeed with their touchdown. With every defeated alien, the player earns points and the aliens move a bit faster. Of course this is a quite dangerous task, since all aliens are equipped with several deadly weapons, and they definitely build the majority (55:1).
You can hide with your laser base behind a couple of bunker-like fortresses, but those buildings are under permanent fire themselves and gradually dissipate during the attacks. Occasionally a mystery ship appears, which, when hit, scores an unknown number of points. Once the first alien row reaches the your planet's surface, the aliens have won and the game is over. On the other side, if all aliens could be eliminated, the game continues with the next wave. Each wave gets more difficult than the previous one, since the aliens make heavier use of their weapons, the fortresses are faster destroyed and you have less time to escape. For compensation, you get better armed, too, every second level, so you can fire your lasers more rapidly. You got three laser bases at the beginning. You lose one base each time you are hit by the aliens, and win another bonus base every 1500 points. If your last base is gone, your planet has lost its last hope and game is over, too.
I tried to use all of the technical concepts described above for realization. One additional objective was to get it run with the simplest 9845B configuration available. So you don't need anything but the pure system with minimum R/W memory and without any option ROMs, even a graphics option is not required. The main program design is in BASIC with roughly 1,000 lines of code, only one single binary program is used for fast character writes to the screen which works with all 9845 systems (SPRINT binary). However, be warned, although in principle playable on a standard LPU, it is not fast enough for demanding gameplay. For real thrill, a bit slice (fast) LPU option is mandatory. Sorry for this, but see the speed paragraph within the above section for some background.
Sound is optional, using the technique decribed above by transferring sound commands via HP-IB to a 9111A graphics tablet. So, if you own a 9111A tablet together with a 98034A HP-IB interface and an I/O option ROM, you can use the sound option. But no other hardware is necessary to play the game than the plain HP 9845 system.
By the way, according to Wikipedia, the Stratford Record for non-stop Space Invaders play to this day is hold by Eric Furrer - 38 hours and 37 minutes and an accumulation of 1,114,000 points (111 roll overs, averaging three rolls an hour). Furrer also found the only known cheat which gurantees full 300 points for each mystery ship by manipulating the pseudo random number generator algorithm.
Space Invaders Adaption for HP 9845
Game control for the HP 9845 version is via the following keys:
TAB | Insert coin (always possible during game play) |
1 | Select one player (only during selection) |
2 | Select two players (only during selection) |
EXECUTE | Fire (only during level play) |
CONT | Shield (only during level play) |
Arrow keys | Move left and right (you also can use the better positioned X and Z/Y keys, but the only keys with built-in auto-repeat are the arrow keys) |
I also tried to make everything as far as possible like the original. However, I could not contain myself adding some (very few) features:
- The aliens have a terrible weapon with hight impact - the seismic bomb. If this bomb hits your ship, your ship is gone, but even worse, if it comes down near you, the impact of the blast can destroy your ship, too. In the original game, the aliens do not have this bomb.
- As compensation for the terrible seismic bomb, you are equipped with a shield field, which protects you for a limited period of time against all alien weapons. This can save your base especially in case many bombs come down at once near you. However, since all energy is guided to the shields, neither fire nor movements are possible as long as the shield is up. In the original game, no shield is available (guess it was added in a later version of Space Invaders).
Some parts of the port were not easy to solve. In particular the alien shapes were really hard to implement in the text based 9845 version without user defined and only a few line drawing characters. Creating noise had not been possible at all, the 9111A only supports playing tones. I also decided to keep the original screen ratio as far as possible (the original has portrait screen orientation) and not use the whole screen for a wide screen version. Explosions are somewhat better animated than in the original, and I dropped the laser explosion if the laser beam reaches the upper screen border (we are in space, not in a box).
But now for the program structure.
Implementations Details
I tried to do the implementation generic, so you can re-use it for other games if you like. The basic game flow is almost the same for arcade style games and most other genres:
Generic Game Flow
The different functional blocks are mirrored in the program sections. Altogether there are 8 sections:
Main Program | Implements the overall generic game flow and calls all the main routines in the right sequence. At the beginning of this section are some customizable parameters located. |
Initializations | Here are all the setups which are required only once. One routine is called at program start, the other before each level play. |
Main routines | These are the high order game routines, such as different screens and playing a level (next order level game engine). |
Display update subroutines | This section holds all the routines which are used for updating the display, but have nothing to do with the game action itself. These are updates for score display, status display, redrawing the bunkers, bonus life and game over. |
Gameplay update subroutines | Here are all the routines which do the action on the screen, sound etc., like moving aliens, bombs, lasers, mystery ship and so on. All things which happen under control of the enemy (this role is played by the computer) are initiated in a single automation routine, which also implements the bot for the game demo (it then plays both roles at once, but as a lousy defender so that the aliens always win). |
Control action subroutines | These are the routines which are called when you do something, like firing lasers, activating shield, insert coins etc. |
Event handlers | There are only two handlers, which are both called asynchroneously, one for keyboard input, and another for errors occurring during gameplay (which actually should not happen) |
SUBs | For technical reasons, routines which use calling parameters are placed in this section (Space Invaders only uses one of those for simulating a typewriter on the screen, all other routines work on global variables, which is easier and faster, but also less structured and more susceptible to programming errors) |
As you can see, there are two main game loops, one high order loop implementing the highl level game flow (=showing the different screens in sequence, starting the game demo and the level plays) and the lower order game engine which controls the level play. There is only one lower order game engine, which can run both in demo and interactive mode.
All user interactions are implemented via keyboard interrupts, can happen at any time, and are served immediately. All other actions are scheduled and updated whith a frequency depending on the appropriate action. So alien moves, for instance, have to be updated not as frequently as laser shots. By handling all those actions semi parallel, the whole game play looks like many simultaneous actions, which again is important for a good implementation.
Concerning sound, the program looks once at start if there is a 9111A digitizer board connected and powered on, and if yes, sets the system into OVERLAP mode and uses this for sound output during the whole game. If you like you can check the impact of the OVERLAP mode by simply commenting this line. All sound events are hold in strings, which are set up at initialization time and simply sent to the digitizer when needed.
Animations use arrays of strings, holding different strings for different animation steps. Playing those fast one after the other then gives the impression of animation. Each animated object (including explosions) has its own string array, whereby all aliens in one row make up one object all together. Weapons all check at each move for collision with other objects and, if hit, initiate the proper actions.
Creating and moving objects are different routines. Creating an object means to activate it and to set its initial position. Then the creation routines return and leave the rest to the update routines, which do the motion, the collision detection or whatever is required to perfom action. So every object has its life cycle, which is initiated with a create routine, controlled with an update routine and terminated after reaching a certain screen position, hitting other objects or after a certain time (simulated by expiring counters). The main rule is that every update routine must do its work in as short time as possible in order not to delay the next update routine. This principle is also called voluntary multitasking (as it is done e.g. withing Windows 98), in contrast to preemptive multitasking (as it is implemented under UNIX or Windows NT and its successors).
Customization
Some parts in the implementation can be customized at the beginning of the program.
First of all there is a master speed parameter, which is 1 by default and can be increased or decreased at your needs to give good game action (a value of 21 would result in maximum speed). Although game play is somewhat tough on an HP 9845 without bit slice processor, the game is barely playable with a speed value of 21. For systems with bit slice LPU, a speed value of 1 is standard (everything between 0 and 1 is cheating).
Other settings are required for using a 9111A digitizer as sound device (select code of the 98034A HP-IB interface, HP-IB address of the digitizer). Also you can completely disable sound by setting Sound=0.
But in fact, you can change everything you like...
Perspectives
First of all, I'd like to construct a color version of space invaders, utilizing the color features of a HP 9845C. However, I am not quite sure how many working 9845C system there are in the world, but they are probably limited, so it will be essentially for personal fun.
Next, sequels of the original Space Invaders can be implemented, like those which are keeping high score lists.
Another task would be to set up a better development environment maybe based on the Assembly Programmer's Utility, to supply cross-development for lightning-fast action gaming even on systems not equipped with a bit slice processor. But it will become a real challenge to implement all those functionality still missing like interrupt handling, string processing and character graphics, and to realize for target systems without Assembly ROMs. Maybe there is someone else who likes to take up the challenge ;-)
Nice would also be a hardware supplement for connecting game controllers and producing sound output and vertical trace interrupts which fits on the I/O extension connectors, a task which should be easy to achieve with some kind of Atmel- or PIC-like micro controller. Or simply using the HP-IB or the serial interface to the PC for using its game controllers & sound hardware.
Downloads
Click here for downloading Space Invaders (both program including SPRINT binary and program source):
Space Invaders HP 9845 version (program and binary): | 9845-space-invaders-hpi.zip |
Space Invaders HP 9845 version (source code): | 9845-space-invaders-listing.zip |
Use the hpi-image contained in the zip archive to mount it with HPDrive:
hpdrive 9845-space-invaders.hpi
Then (supposed your 98034 HP-IB interface is configured to select code 7) load the Space Invaders game from your HP 9845 with
LOAD "INVAD:H7"
Alternatively, load binary program and program source separately with
LOAD BIN "SPRINT:H7"
GET "INVAD_:H7"
Connect and switch on the 9111A digitizer (if available), run the game, have fun.
More Information
You can find more information about sound programming in the Digitizer/Plotter/Sound Section. Binary programs, including the SPRINT and the GPRINT binaries are diskussed in detail in the Binary Program Section. Connecting a mouse for using it as game controller is described in the 9845 Mouse Project.
If you like to get an impression how the original Space Invader game feels, use M.A.M.E., the Multiple Arcade Machine Emulator (look at mamedev.org for download) with the original Space Invaders ROMs (download here). Unpack the MAME program archive, then place the ROMs zipfile into MAME's roms subdirectory and run mame.exe. Controls are 5 to insert coins, 1 and 2 to select players, and CTRL for fire.