practice
Doi: 10.1145/1743546.1743566
Article development led by
queue.acm.org
Emulating a video system shows how even
a simple interface can be more complex—and
capable—than it appears.
BY GeoRGe PhiLLiPs
simplicity
Betrayed
An eMULATor is a program that runs programs built
for different computer architectures from the host
platform that supports the emulator. Approaches
differ, but most emulators simulate the original
hardware in some way. At a minimum the emulator
interprets the original CPU instructions and provides
simulated hardware-level devices for input and output.
For example, keyboard input is taken from the host
platform and translated into the original hardware
format, resulting in the emulated program “seeing”
the same sequence of keystrokes. Conversely, the
emulator will translate the original hardware screen
format into an equivalent form on the host machine.
The emulator is similar to a program that
implements the Java Virtual Machine (JVM). The
difference is merely one of degree. JVM is designed
to enable efficient and tractable implementations,
whereas an emulator’s machine is defined by real
hardware that generally imposes undesirable
constraints on the emulator. Most significantly, the
original hardware may be fully described only in terms
of how existing software uses it. JVM
tends to be forward-looking with the
expectation that new code will be written and run under JVM to increase
its portability. Emulators tend to be
backward-looking, expecting only to
make old code more portable.
In either case the emulator and
JVM give the programs that run under
them a suite of services needed to interact with the host system. JVM presents those services as a series of API
calls; the emulator presents them as
simulated hardware. Nonetheless, the
simulated hardware is an API—just
not in the form most programmers
expect.
tRs- 80 example
As an example hardware API, consider
the TRS- 80 video system, which displays text and graphics on a modified
television set. It has 16 lines of characters with 64 columns each. It supports the normal ASCII character set,
with an additional 64 graphics characters allowing every possible combination of a 2-pixel by 3-pixel sub-block.
Judicious use of the graphics characters provide an effective 128-pixel by
48-pixel resolution, albeit with pixels the size of watermelon seeds. A
TRS- 80 program displays a character
by writing the character value to the
memory location associated with the
desired position. In effect, the API has
only one call:
void ChangeCharacter
(location /* 0 – 1024 */,
character)
Emulating such a simple graphics
format is trivial. It can be rendered
quite adequately on a 512-by-192 image allotting each character an 8-by-
12 rectangle. Each graphics pixel is a
4-by- 4 rectangle, while the characters
themselves occupy the upper two-thirds, or an 8-by- 8 area. While you
could get away with any old font for
the characters, a little more work will
get something that looks dot-for-dot
identical to the original. (To get the