B800
Text Format
Most shareware (and registered!) games of the era displayed a full-screen text page immediately before returning to the DOS prompt, and Cosmo was no exception:
These screens showed colorful line-drawn boxes, customarily in front of a background that resembled the closed curtains on a theater stage. Most contained teasers and ordering information in the case of shareware episodes, or messages thanking the player for purchasing the registered episodes.
Much less commonly, this type of text display was used to provide a more substantial-looking error message in cases where the game was unable to run on a particular system:
Red Marking Pen
These were some of the, shall we say, “less proofread” parts of the game.
There were several B800
text entries in the game’s group files:
Entry Name | Description |
---|---|
COSMO1.MNI | End screen for episode 1. Contains teasers for the registered game and ordering information. |
COSMO2.MNI | End screen for episode 2. Contains advertisements for other Apogee games. |
COSMO3.MNI | End screen for episode 3. Identical to COSMO2.MNI except for the episode number in the top line of text. |
NOMEMORY.MNI | Error message explaining that the system does not have enough memory. |
The B800
Mechanism
PC-compatible graphics adapters that supported color usually booted into mode number 03h by default. This was a text mode providing 80x25 characters with 16 colors. The foreground and background color of each character on the screen could be set independently.
B800
files are named after the segment address where the mode 03h screen buffer is located: B800:0000
. The 4,000 bytes at this memory-mapped address contain the full screen buffer, and writing data within this address range immediately changes the text/colors displayed on the screen. That’s all the file format is – 4,000 bytes that are loaded directly into the video memory in order to put characters on the screen.
The printable text content uses 2,000 bytes (80 × 25) of memory, the foreground colors use 1,000 bytes (80 × 25 × log2 16 = 8,000 bits), and the background colors use another 1,000 bytes. The colors are encoded using the standard RGBI palette with one key difference: on the background only, the intensity bit flashes the foreground text instead of brightening the background color. B800
text files utilized this liberally.
Encoding and Decoding
Within a B800
text file, and the memory area it mirrors, every even-addressed byte controls the character displayed on the screen, and every odd-addressed byte controls the attributes (foreground color, background color, flashing) on the character that immediately preceded it.
Characters and attributes are stored in row-major order, starting at the top-left corner of the screen.
Characters
Unicode 1.0 was less than a year old when the game was released, and DOS PCs were rooted firmly in the world of code pages. The basic idea was this: Since there were only eight bits available for each character on the screen, there could only be 256 (28) different characters (or code points) to choose from. This isn’t too much of a problem if all you’re doing is writing using the Latin alphabet, but toss in Cyrillic, Greek, Arabic, Hebrew, Urdu… You run out of encoding space real fast. Using code pages, the system can “switch” to a different display font, where the underlying text data doesn’t change but the fonts on the display do:
Byte | CP437 | CP850 | CP860 | CP737 | CP775 | CP856 | CP861 | CP863 | CP864 | CP866 |
---|---|---|---|---|---|---|---|---|---|---|
... | ... | |||||||||
80h | Ç | Ç | Ç | Α | Ć | א | Ç | Ç | ° | А |
81h | ü | ü | ü | Β | ü | ב | ü | ü | · | Б |
82h | é | é | é | Γ | é | ג | é | é | ∙ | В |
83h | â | â | â | Δ | ā | ד | â | â | √ | Г |
84h | ä | ä | ã | Ε | ä | ה | ä | Â | ▒ | Д |
85h | à | à | à | Ζ | ģ | ו | à | à | ─ | Е |
86h | å | å | Á | Η | å | ז | å | ¶ | │ | Ж |
87h | ç | ç | ç | Θ | ć | ח | ç | ç | ┼ | З |
88h | ê | ê | ê | Ι | ł | ט | ê | ê | ┤ | И |
89h | ë | ë | Ê | Κ | ē | י | ë | ë | ┬ | Й |
8Ah | è | è | è | Λ | Ŗ | ך | è | è | ├ | К |
8Bh | ï | ï | Í | Μ | ŗ | כ | Ð | ï | ┴ | Л |
8Ch | î | î | Ô | Ν | ī | ל | ð | î | ┐ | М |
8Dh | ì | ì | ì | Ξ | Ź | ם | Þ | ‗ | ┌ | Н |
8Eh | Ä | Ä | Ã | Ο | Ä | מ | Ä | À | └ | О |
8Fh | Å | Å | Â | Π | Å | ן | Å | § | ┘ | П |
90h | É | É | É | Ρ | É | נ | É | É | β | Р |
91h | æ | æ | À | Σ | æ | ס | æ | È | ∞ | С |
92h | Æ | Æ | È | Τ | Æ | ע | Æ | Ê | φ | Т |
93h | ô | ô | ô | Υ | ō | ף | ô | ô | ± | У |
94h | ö | ö | õ | Φ | ö | פ | ö | Ë | ½ | Ф |
95h | ò | ò | ò | Χ | Ģ | ץ | þ | Ï | ¼ | Х |
96h | û | û | Ú | Ψ | ¢ | צ | û | û | ≈ | Ц |
97h | ù | ù | ù | Ω | Ś | ק | Ý | ù | « | Ч |
98h | ÿ | ÿ | Ì | α | ś | ר | ý | ¤ | » | Ш |
99h | Ö | Ö | Õ | β | Ö | ש | Ö | Ô | ﻷ | Щ |
9Ah | Ü | Ü | Ü | γ | Ü | ת | Ü | Ü | ﻸ | Ъ |
9Bh | ¢ | ø | ¢ | δ | ø | (none) | ø | ¢ | (none) | Ы |
9Ch | £ | £ | £ | ε | £ | £ | £ | £ | (none) | Ь |
9Dh | ¥ | Ø | Ù | ζ | Ø | (none) | Ø | Ù | ﻻ | Э |
9Eh | ₧ | × | ₧ | η | × | × | ₧ | Û | ﻼ | Ю |
9Fh | ƒ | ƒ | Ó | θ | ¤ | (none) | ƒ | ƒ | (none) | Я |
... | ... |
Note that in the preceding table, the raw bytes never change. All that changes from one code page to another is what the visual representation of a code point is.
The lower half of most code pages was the same, mirroring the 7-bit character assignments originally defined by the American Standard Code for Information Interchange (ASCII) in the 1960s. This allowed for compatible rendering of the letters A-Z, digits, and common printable punctuation characters across all configurations. The upper half above 80h, however, was a free-for-all.
The prevailing theory of the day was that files would tend to only be opened on computers that were geographically near one another, and all of those computers would be configured to use the same code page for display. If a file was written with the expectation that it would be displayed in one code page, and was instead opened on a computer with a different code page loaded, it may display as abject gibberish. The IBM PC (and most compatibles sold in the Western world) booted into code page 437 (CP437) by default.
CP437 defined a few international characters – mostly currency symbols, accented vowels to properly write out certain names and loanwords from other languages, and enough Greek letters and mathematical symbols to write physics equations. Most of the rest of the characters were for block and box drawing, allowing solid filled areas and continuous single- or double-lines to be drawn in all four directions with corners and intersections. These box drawing characters were integral to some of the first text-based UIs in DOS software. They were also used extensively in B800
text screens.
The full CP437 character set is as follows:
00h | (blank) | 20h | (space) | 40h | @ | 60h | ` | 80h | Ç | A0h | á | C0h | └ | E0h | α |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
01h | ☺ | 21h | ! | 41h | A | 61h | a | 81h | ü | A1h | í | C1h | ┴ | E1h | ß |
02h | ☻ | 22h | " | 42h | B | 62h | b | 82h | é | A2h | ó | C2h | ┬ | E2h | Γ |
03h | ♥ | 23h | # | 43h | C | 63h | c | 83h | â | A3h | ú | C3h | ├ | E3h | π |
04h | ♦ | 24h | $ | 44h | D | 64h | d | 84h | ä | A4h | ñ | C4h | ─ | E4h | Σ |
05h | ♣ | 25h | % | 45h | E | 65h | e | 85h | à | A5h | Ñ | C5h | ┼ | E5h | σ |
06h | ♠ | 26h | & | 46h | F | 66h | f | 86h | å | A6h | ª | C6h | ╞ | E6h | µ |
07h | • | 27h | ' | 47h | G | 67h | g | 87h | ç | A7h | º | C7h | ╟ | E7h | τ |
08h | ◘ | 28h | ( | 48h | H | 68h | h | 88h | ê | A8h | ¿ | C8h | ╚ | E8h | Φ |
09h | ○ | 29h | ) | 49h | I | 69h | i | 89h | ë | A9h | ⌐ | C9h | ╔ | E9h | Θ |
0Ah | ◙ | 2Ah | * | 4Ah | J | 6Ah | j | 8Ah | è | AAh | ¬ | CAh | ╩ | EAh | Ω |
0Bh | ♂ | 2Bh | + | 4Bh | K | 6Bh | k | 8Bh | ï | ABh | ½ | CBh | ╦ | EBh | δ |
0Ch | ♀ | 2Ch | , | 4Ch | L | 6Ch | l | 8Ch | î | ACh | ¼ | CCh | ╠ | ECh | ∞ |
0Dh | ♪ | 2Dh | - | 4Dh | M | 6Dh | m | 8Dh | ì | ADh | ¡ | CDh | ═ | EDh | φ |
0Eh | ♫ | 2Eh | . | 4Eh | N | 6Eh | n | 8Eh | Ä | AEh | « | CEh | ╬ | EEh | ε |
0Fh | ☼ | 2Fh | / | 4Fh | O | 6Fh | o | 8Fh | Å | AFh | » | CFh | ╧ | EFh | ∩ |
10h | ► | 30h | 0 | 50h | P | 70h | p | 90h | É | B0h | ░ | D0h | ╨ | F0h | ≡ |
11h | ◄ | 31h | 1 | 51h | Q | 71h | q | 91h | æ | B1h | ▒ | D1h | ╤ | F1h | ± |
12h | ↕ | 32h | 2 | 52h | R | 72h | r | 92h | Æ | B2h | ▓ | D2h | ╥ | F2h | ≥ |
13h | ‼ | 33h | 3 | 53h | S | 73h | s | 93h | ô | B3h | │ | D3h | ╙ | F3h | ≤ |
14h | ¶ | 34h | 4 | 54h | T | 74h | t | 94h | ö | B4h | ┤ | D4h | ╘ | F4h | ⌠ |
15h | § | 35h | 5 | 55h | U | 75h | u | 95h | ò | B5h | ╡ | D5h | ╒ | F5h | ⌡ |
16h | ▬ | 36h | 6 | 56h | V | 76h | v | 96h | û | B6h | ╢ | D6h | ╓ | F6h | ÷ |
17h | ↨ | 37h | 7 | 57h | W | 77h | w | 97h | ù | B7h | ╖ | D7h | ╫ | F7h | ≈ |
18h | ↑ | 38h | 8 | 58h | X | 78h | x | 98h | ÿ | B8h | ╕ | D8h | ╪ | F8h | ° |
19h | ↓ | 39h | 9 | 59h | Y | 79h | y | 99h | Ö | B9h | ╣ | D9h | ┘ | F9h | ∙ |
1Ah | → | 3Ah | : | 5Ah | Z | 7Ah | z | 9Ah | Ü | BAh | ║ | DAh | ┌ | FAh | · |
1Bh | ← | 3Bh | ; | 5Bh | [ | 7Bh | { | 9Bh | ¢ | BBh | ╗ | DBh | █ | FBh | √ |
1Ch | ∟ | 3Ch | < | 5Ch | \ | 7Ch | | | 9Ch | £ | BCh | ╝ | DCh | ▄ | FCh | ⁿ |
1Dh | ↔ | 3Dh | = | 5Dh | ] | 7Dh | } | 9Dh | ¥ | BDh | ╜ | DDh | ▌ | FDh | ² |
1Eh | ▲ | 3Eh | > | 5Eh | ^ | 7Eh | ~ | 9Eh | ₧ | BEh | ╛ | DEh | ▐ | FEh | ■ |
1Fh | ▼ | 3Fh | ? | 5Fh | _ | 7Fh | ⌂ | 9Fh | ƒ | BFh | ┐ | DFh | ▀ | FFh | (blank | )
Everything old is new again.
There are some precursors to emoji in the CP437 table – especially the faces, arrows, and playing card suits. Some computers may even display some of the above characters as emoji.
In files and console output, the control characters (00h-1Fh) represent newlines, tabs, audible beeps, and other commands to move the cursor around. In the video memory, however, these characters have absolutely no special behavior and display a single character just like any other.
Attributes
Each attribute byte has four bits that control foreground color, three bits that control background color, and one bit that controls flashing of the foreground text:
Bit Position | Description |
---|---|
0 (least significant bit) | Foreground blue palette bit. |
1 | Foreground green palette bit. |
2 | Foreground red palette bit. |
3 | Foreground intensity palette bit. |
4 | Background blue palette bit. |
5 | Background green palette bit. |
6 | Background red palette bit. |
7 (most significant bit) | 0 = foreground text displays normally, 1 = foreground text flashes. |
The default system color was 07h, or low-intensity white on a black background.
The attribute byte affects the character byte that immediately precedes it:
Offset (Bytes) | Description |
---|---|
0 | Character at (0, 0). |
1 | Attributes for character at (0, 0). |
2 | Character at (1, 0). |
3 | Attributes for character at (1, 0). |
… | … |
3,996 | Character at (78, 24). |
3,997 | Attributes for character at (78, 24). |
3,998 | Character at (79, 24). |
3,999 | Attributes for character at (79, 24). |
Programming Considerations
DOS is unaware of characters drawn directly to video memory, and the cursor position is not updated in any way to reflect the updated contents of the screen. When the program exits, DOS thinks the screen is blank and the most appropriate place for the prompt should be at the current cursor position, which is near the top of the screen. With B800
text already occupying space on the screen, this naive assumption results in the DOS prompt appearing on top of the text, with new and old characters and attributes jumbling together in an unreadable mess.
Typically, any program that displayed B800
text would also emit – usually via printf()
– a series of newline characters to move the cursor down far enough to clear the bottom of the displayed text.