TRS-80 Tips and Tricks - Easter Eggs and Bugs

Easter Eggs - ROM/BIOS

COCO

In Color Basic ROM v1.1, clearing the screen to an invalid color (9-255) will give you a Microsoft copyright message

COCO III

Press CTRL-ALT-RESET and a 256x192 hi res picture comes up the screen. This is actually the power-on cold start sequence for the CoCo 3. The picture is of 3 Microware guys that did work for Tandy on enhancing the Extended Color Basic ROM into CoCo 3 capabilities. Tandy knew of this pix just before release into the market and decided to ship the units as is instead of reworking the ROM code. (Rogelio)

The picture consumed about 6K of the 8K of additional ROM that Microware was given in those systems to make some enhancements for BASIC. Generally known as "The Three Stooges" image, you frequently found it up on the store computers .... The three people were employees at Microware. The Tandy buyer knew or became aware of the picture before the machines shipped, but no one in R&D knew. If it was known, the VP of the hardware groups would have replaced the 8K with a 2K part to save a nickel. (Frank Durda IV).

Model III

Model III and early Model 4 ROMs had "RON" for Ron Light hidden down in the "A" ROM. As far as Frank knows there wasn't anything that caused it to be displayed, but that is what that is. (Frank Durda IV).

Model 4 Boot ROM

Frank Durda IV's footprints are in a few places in the the Model 4P boot ROM. When you turn on a Model 4P, after the initial "di" instruction at location 0, the next four instructions executed are actually the ASCII characters "FDIV"! The instructions don't do anything useful in this context. In addition, lowercase "fdiv" appears a bit further down, and the words "Frank" and "Durda" can be found mixed in with the French and German error messages. (Tim Mann).

Model III/A

"fdiv" also occurs in various places in all versions of the MODELA/III file. (MODELA/III is the ROM image that was loaded into RAM for Model III compatibility mode on the Model 4P.) In some it's in the actual ROM image; in others it's in extra bytes at the end of the file that are not loaded into RAM. (Tim Mann).

Tandy VIS Systems

On the Tandy VIS systems, Microsoft tried to sneak a new product line logo for Modular Windows in at the last minute (it looked like a rip-off of the "Wool" logo you see on garments), but as it was displayed on each boot, replaced the VIS logo, which Tandy didn't like, and MS was over their ROM budget in the first place even before adding this bloat, Tandy complained loudly.

The Next release MS sent Tandy doesn't display the logo and we are told it has been removed, BUT the modules are even bigger. We get suspicious. A disassembly shows the image is still there and MS added new code to make the image appear only in certain situations. Only after John Roach called Bill Gates on this, did the logo really get removed. Of course, we didn't know that in retaliation, MS decided to torpedo the VIS project anyway by changing Modular Windows in a very minor but incompatible way with the version in VIS, and told us just two days after the VIS ROMs were sent to be fabbed. Modular Windows was disowned by Microsoft after a few more months (they denied it was even a product in public statements), but it was eventually remarketed with bigger system CPU and memory requirements, more bloat and a brand new name: Windows CE.

Of course, if you examine the VIS ROMS, you will find hundreds of messages telling you that the network printer is out of paper and other messages that don't make sense for a machine with no network or printer capabilities. That's Windows CE (I mean Modular Windows) dragging around great steaming chunks of regular Windows that could not be cut-out, or at least that's what Microsoft claimed. After the stunt with the logo, relations were real bad. (Frank Durda IV).

Easter Eggs - DOS / OPERATING SYSTEMS

TRSDOS v2.x

The TRSDOS v2.x BOOT/SYS file is to check for SYS0/SYS and if its directory entry is found on Drive :0, Track 11, Directory Entry 4, it uses the information from this entry to load SYS1/SYS into memory at 4D00H and then jump to it. If SYS0/SYS is not present, it displays a NO SYSTEM message and halts.

But when Randy Cook created the operating system, he hid a secret message in the boot code area.

To bring up the easter egg, once TRSDOS boots you type in BOOT/SYS.WHO and then hold down the R+V keys (or any keys which will produce a 44H result, such as 2+6). If you do this correctly you will get the screen. As can be seen from the routine below, if you hold down the wrong keys, you just get garbage.

The screens were:

Tandy caught on and the message was changed in TRSDOS v2.3

According to Frank Durda IV, that message is one of the key items that made Randy Cook and Tandy part ways so violently, and probably why Tandys various revisionist histories of that period frequently fail to mention him or Steve Ls role in putting Tandy in the computer business. As Frank recalls, the original message also had a non-Tandy telephone number Randy set up to do his own support from, which ticked-off Tandy even more. Either George Robertson or Ron Light (both now deceased) created the patch that changed the message after Randy went away. (Frank Durda IV).

Click for more detail

The BOOT/SYS sector begins with "00 FE", which is a cleverly disguised load module code (equivalent to a comment record). That /CMD comment skips over the boot sector leaving a program that loads to $4E00 (the encrypted data) and $4fea (the display code).

4E00H
58 5A 51 6D 60 6B 62 69 6C 67 6E 65 68 63 6A 61
4E10H
74 7F 76 7D 70 7B 72 79 7C 77 7E 75 78 73 7A 71
4E20H
44 4F 46 4D 40 41 42 43 4C 23 4E 4F 27 49 4A 3F
4E30H
54 55 3F 57 50 32 52 53 39 5D 5E 5E 58 59 5A 5B
4E40H
24 2F 26 2D DD 2B 22 29 2C 2D 5A 47 41 5A 2A 44
4E50H
51 44 56 44 58 5C 54 3C 4E 47 4C 4C 5C 57 3B 73
4E60H
64 75 07 00 0B 02 09 0C 69 6B 7C 61 6E 64 6E 70
4E70H
15 74 6E 10 70 7C 77 1C 74 6D 1F 6C 71 7F 1B 97
4E80H
8A 8A 82 E0 EB E2 E9 EC ED EE 9F 9A 86 9A 8E 86
4E90H
81 8F F7 9F 97 F2 81 9D 93 9A 86 F8 9A 95 94 AF
4EA0H
CB C6 C7 C0 CB C2 C9 31 C7 CE C5 C8 C9 AB A7 B8
4EB0H
D5 BF B9 B6 BE A0 BE BD A9 B7 B0 B6 D9 B9 B4 CA
4EC0H
D1 C7 CE CE C4 C6 A3 AC A7 AE A5 A8 A9 C2 CE C6
4ED0H
D0 DF D9 B0 D8 C1 B3 CC CF D1 CF CA D0 DF CF E5
4EE0H
F7 FF 87 E1 EF E6 83 8C 87 8E 85 88 89 E7 FE E7
4EF0H
E1 96 F9 FF E5 92 F1 F9 9D EC FA E8 EB F5 FF 11
4F00H
06 03 03 60 0E 10 63 6C 67 6E 65 68 69 0E 02 07
4F10H
01 04 1E 12 04 06 16 18 7D 17 11 78 0E 12 14 28
4F20H
20 46 28 32 41 2B 2D 4C 47 4E 45 48 49 3A 2A 26
4F30H
21 56 20 39 25 3A 3C 29 29 5E 2F 2A 30 35 29 24
4F40H
52 54 4E 54 55 47 4D 2C 27 2E 25 28 29 49 44 5A
4F50H
46 53 59 44 31 54 41 53 50 3E 4D 59 57 5E 42 04
4F60H
66 69 68 6B 0F 02 03 0C 07 0E 05 08 09 0A 0B 05
4F70H
06 06 06 10 62 66 7C 72 78 69 70 77 7D 1A 7F 96
4F80H
EB E6 E7 E0 E1 E2 E3 EC E7 EE E5 E8 E9 EA EB 97
4F90H
94 84 85 9F 9D 9E 87 93 93 F2 FF 8C 81 F4 FB C4
4FA0H
D2 D3 D7 D0 D7 C2 C3 CC C7 CE C5 C8 C3 CA C1 D4
4FB0H
DF D6 DD D0 DB D2 D9 DC D7 DE D5 D8 D3 DA D1 A4
4FC0H
AF A6 AD A0 AB A2 A9 AC A7 8D xx xx xx xx xx xx

4FEA
LD A,(038FFH)
Poll the keyboard and put the result code in Register A
4FED
LD B,A
Copy the keypress result code from B to A
4FEE
LD HL,4E00H
Put the RAM Address 4E00H into Register Pair HL, to point to the encoded text

Top of a loop.

4FF1
LD A,(HL)
Copy the current byte held in the encoded text into Register A
4FF2
XOR B
Exclusive OR that byte against the keypress result (which needs to be 44H to actually decode properly)
4FF3
XOR L
Exclusive OR that result against the LSB of the RAM address holding the encoded text
4FF4
CP 003H
Check to see if that result is an 03H delimter
4FF6
JR Z,4FFEH
If it is an 03H delimeter, then JUMP to 4FEEH
4FF8
CALL 0033H
If it is NOT an 03H delimter, call the ROM routine to display the character held in Register A to the next screen position
4FFB
INC HL
Bump HL to point to the next encoded character
4FFC
JR 4FF1H
LOOP back to 4FF1H to fetch the byte, XOR it twice, check against 03H, and display
4FFE
JR 4FFEH
JUMP to 4FFEH in an infinite loop

Here's an example of the first two lines

RAM
Addr
Encoded
Char
(Hex)
Key
Code
(Hex)
Address
LSB
(Hex)
CalculationDecoded
4E00H584400
    0101 1000 (58H)
xor 0100 0100 (44H)
  = 0001 1100

    0001 1100 (1CH)
xor 0000 0000 (00H)
  = 0001 1100 (1C)
(FS)
4E01H5A4401
    0101 1010 (5AH)
xor 0100 0100 (44H)
  = 0001 1110

    0001 1110 (1EH)
xor 0000 0001 (01H)
  = 0001 1111 (1F)
(US)
4E02H514402
    0101 0001 (51H)
xor 0100 0100 (44H)
  = 0001 0101

    0001 0101 (15H)
xor 0000 0010 (02H)
  = 0001 0111 (17)
(ETB)
4E03H6D4403
    0110 1101 (6DH)
xor 0100 0100 (44H)
  = 0010 1001

    0010 1001 (29H)
xor 0000 0011 (03H)
  = 0010 1010 (2A)
*
4E04H604404
    0110 0000 (60H)
xor 0100 0100 (44H)
  = 0010 0100

    0010 0100 (24H)
xor 0000 0100 (04H)
  = 0010 0000 (20)
(Space)
4E05H6B4405
    0110 1011 (6BH)
xor 0100 0100 (44H)
  = 0010 1111

    0010 1111 (2FH)
xor 0000 0101 (05H)
  = 0010 1010 (2A)
*
4E06H624406
    0110 0010 (62H)
xor 0100 0100 (44H)
  = 0010 0110

    0010 0110 (26H)
xor 0000 0110 (06H)
  = 0010 0000 (20)
(Space)
4E07H694407
    0110 1001 (69H)
xor 0100 0100 (44H)
  = 0010 1101

    0010 1101 (2DH)
xor 0000 0111 (07H)
  = 0010 1010 (2A)
*
4E08H6C4408
    0110 1100 (6CH)
xor 0100 0100 (44H)
  = 0010 1000

    0010 1000 (28H)
xor 0000 1000 (08H)
  = 0010 0000 (20)
(Space)
4E09H674409
    0110 0111 (67H)
xor 0100 0100 (44H)
  = 0010 0011

    0010 0011 (23H)
xor 0000 1001 (09H)
  = 0010 1010 (2A)
*
4E0AH6E440A
    0110 1110 (6EH)
xor 0100 0100 (44H)
  = 0010 1010

    0010 1010 (2AH)
xor 0000 1010 (0AH)
  = 0010 0000 (20)
(Space)
4E0BH65440B
    0110 0101 (65H)
xor 0100 0100 (44H)
  = 0010 0001

    0010 0001 (21H)
xor 0000 1011 (0BH)
  = 0010 1010 (2A)
*
4E0CH68440C
    0110 1000 (68H)
xor 0100 0100 (44H)
  = 0010 1100

    0010 1100 (2CH)
xor 0000 1100 (0CH)
  = 0010 0000 (20)
(Space)
4E0DH63440D
    0110 0011 (63H)
xor 0100 0100 (44H)
  = 0010 0111

    0010 0111 (27H)
xor 0000 1101 (0DH)
  = 0010 1010 (2A)
*
4E0EH6A440E
    0110 1010 (6AH)
xor 0100 0100 (44H)
  = 0010 1110

    0010 1110 (2EH)
xor 0000 1110 (0EH)
  = 0010 0000 (20)
(Space)
4E0FH61440F
    0110 0001 (61H)
xor 0100 0100 (44H)
  = 0010 0101

    0010 0101 (25H)
xor 0000 1111 (0FH)
  = 0010 1010 (2A)
*
4E10H744410
    0111 0100 (74H)
xor 0100 0100 (44H)
  = 0011 0000

    0011 0000 (30H)
xor 0001 0000 (10H)
  = 0010 0000 (20)
(Space)
4E11H7F4411
    0111 1111 (7FH)
xor 0100 0100 (44H)
  = 0011 1011

    0011 1011 (3BH)
xor 0001 0001 (11H)
  = 0010 1010 (2A)
*
4E12H764412
    0111 0110 (76H)
xor 0100 0100 (44H)
  = 0011 0010

    0011 0010 (32H)
xor 0001 0010 (12H)
  = 0010 0000 (20)
(Space)
4E13H7D4413
    0111 1101 (7DH)
xor 0100 0100 (44H)
  = 0011 1001

    0011 1001 (39H)
xor 0001 0011 (13H)
  = 0010 1010 (2A)
*
4E14H704414
    0111 0000 (70H)
xor 0100 0100 (44H)
  = 0011 0100

    0011 0100 (34H)
xor 0001 0100 (14H)
  = 0010 0000 (20)
(Space)
4E15H7B4415
    0111 1011 (7BH)
xor 0100 0100 (44H)
  = 0011 1111

    0011 1111 (3FH)
xor 0001 0101 (15H)
  = 0010 1010 (2A)
*
4E16H724416
    0111 0010 (72H)
xor 0100 0100 (44H)
  = 0011 0110

    0011 0110 (36H)
xor 0001 0110 (16H)
  = 0010 0000 (20)
(Space)
4E17H794417
    0111 1001 (79H)
xor 0100 0100 (44H)
  = 0011 1101

    0011 1101 (3DH)
xor 0001 0111 (17H)
  = 0010 1010 (2A)
*
4E18H7C4418
    0111 1100 (7CH)
xor 0100 0100 (44H)
  = 0011 1000

    0011 1000 (38H)
xor 0001 1000 (18H)
  = 0010 0000 (20)
(Space)
4E19H774419
    0111 0111 (77H)
xor 0100 0100 (44H)
  = 0011 0011

    0011 0011 (33H)
xor 0001 1001 (19H)
  = 0010 1010 (2A)
*
4E1AH7E441A
    0111 1110 (7EH)
xor 0100 0100 (44H)
  = 0011 1010

    0011 1010 (3AH)
xor 0001 1010 (1AH)
  = 0010 0000 (20)
(Space)
4E1BH75441B
    0111 0101 (75H)
xor 0100 0100 (44H)
  = 0011 0001

    0011 0001 (31H)
xor 0001 1011 (1BH)
  = 0010 1010 (2A)
*
4E1CH78441C
    0111 1000 (78H)
xor 0100 0100 (44H)
  = 0011 1100

    0011 1100 (3CH)
xor 0001 1100 (1CH)
  = 0010 0000 (20)
(Space)
4E1DH73441D
    0111 0011 (73H)
xor 0100 0100 (44H)
  = 0011 0111

    0011 0111 (37H)
xor 0001 1101 (1DH)
  = 0010 1010 (2A)
*
4E1EH7A441E
    0111 1010 (7AH)
xor 0100 0100 (44H)
  = 0011 1110

    0011 1110 (3EH)
xor 0001 1110 (1EH)
  = 0010 0000 (20)
(Space)
4E1FH71441F
    0111 0001 (71H)
xor 0100 0100 (44H)
  = 0011 0101

    0011 0101 (35H)
xor 0001 1111 (1FH)
  = 0010 1010 (2A)
*
4E20H444420
    0100 0100 (44H)
xor 0100 0100 (44H)
  = 0000 0000

    0000 0000 (00H)
xor 0010 0000 (20H)
  = 0010 0000 (20)
(Space)
4E21H4F4421
    0100 1111 (4FH)
xor 0100 0100 (44H)
  = 0000 1011

    0000 1011 (0BH)
xor 0010 0001 (21H)
  = 0010 1010 (2A)
*
4E22H464422
    0100 0110 (46H)
xor 0100 0100 (44H)
  = 0000 0010

    0000 0010 (02H)
xor 0010 0010 (22H)
  = 0010 0000 (20)
(Space)
4E23H4D4423
    0100 1101 (4DH)
xor 0100 0100 (44H)
  = 0000 1001

    0000 1001 (09H)
xor 0010 0011 (23H)
  = 0010 1010 (2A)
*
4E24H404424
    0100 0000 (40H)
xor 0100 0100 (44H)
  = 0000 0100

    0000 0100 (04H)
xor 0010 0100 (24H)
  = 0010 0000 (20)
(Space)
4E25H414425
    0100 0001 (41H)
xor 0100 0100 (44H)
  = 0000 0101

    0000 0101 (05H)
xor 0010 0101 (25H)
  = 0010 0000 (20)
(Space)
4E26H424426
    0100 0010 (42H)
xor 0100 0100 (44H)
  = 0000 0010

    0000 0010 (02H)
xor 0010 0110 (26H)
  = 0010 0100 (24)
$
4E27H434427
    0100 0011 (43H)
xor 0100 0100 (44H)
  = 0000 0011

    0000 0011 (03H)
xor 0010 0111 (27H)
  = 0010 0100 (24)
$
4E28H4C4428
    0100 1100 (4CH)
xor 0100 0100 (44H)
  = 0000 1000

    0000 1000 (08H)
xor 0010 1000 (28H)
  = 0010 0000 (20)
(Space)
4E29H234429
    0010 0011 (23H)
xor 0100 0100 (44H)
  = 0110 0111

    0110 0111 (67H)
xor 0010 1001 (29H)
  = 0100 1110 (4E)
N
4E2AH4E442A
    0100 1110 (4EH)
xor 0100 0100 (44H)
  = 0000 1010

    0000 1010 (0AH)
xor 0010 1010 (2AH)
  = 0010 0000 (20)
(Space)
4E2BH4F442B
    0100 1111 (4FH)
xor 0100 0100 (44H)
  = 0000 1011

    0000 1011 (0BH)
xor 0010 1011 (2BH)
  = 0010 0000 (20)
(Space)
4E2CH27442C
    0010 0111 (27H)
xor 0100 0100 (44H)
  = 0110 0011

    0110 0011 (63H)
xor 0010 1100 (2CH)
  = 0100 1111 (4F)
O
4E2DH49442D
    0100 1001 (49H)
xor 0100 0100 (44H)
  = 0000 1101

    0000 1101 (0DH)
xor 0010 1101 (2DH)
  = 0010 0000 (20)
(Space)
4E2EH4A442E
    0100 1010 (4AH)
xor 0100 0100 (44H)
  = 0000 1110

    0000 1110 (0EH)
xor 0010 1110 (2EH)
  = 0010 0000 (20)
(Space)
4E2FH3F442F
    0011 1111 (3FH)
xor 0100 0100 (44H)
  = 0111 1011

    0111 1011 (7BH)
xor 0010 1111 (2FH)
  = 0101 0100 (54)
T
4E30H544430
    0101 0100 (54H)
xor 0100 0100 (44H)
  = 0001 0000

    0001 0000 (10H)
xor 0011 0000 (30H)
  = 0010 0000 (20)
(Space)
4E31H554431
    0101 0101 (55H)
xor 0100 0100 (44H)
  = 0001 0001

    0001 0001 (11H)
xor 0011 0001 (31H)
  = 0010 0000 (20)
(Space)
4E32H3F4432
    0011 1111 (3FH)
xor 0100 0100 (44H)
  = 0111 1011

    0111 1011 (7BH)
xor 0011 0010 (32H)
  = 0100 1001 (49)
I
4E33H574433
    0101 0111 (57H)
xor 0100 0100 (44H)
  = 0001 0011

    0001 0011 (13H)
xor 0011 0011 (33H)
  = 0010 0000 (20)
(Space)
4E34H504434
    0101 0000 (50H)
xor 0100 0100 (44H)
  = 0001 0100

    0001 0100 (14H)
xor 0011 0100 (34H)
  = 0010 0000 (20)
(Space)
4E35H324435
    0011 0010 (32H)
xor 0100 0100 (44H)
  = 0111 0110

    0111 0110 (76H)
xor 0011 0101 (35H)
  = 0100 0011 (43)
C
4E36H524436
    0101 0010 (52H)
xor 0100 0100 (44H)
  = 0001 0110

    0001 0110 (16H)
xor 0011 0110 (36H)
  = 0010 0000 (20)
(Space)
4E37H534437
    0101 0011 (53H)
xor 0100 0100 (44H)
  = 0001 0111

    0001 0111 (17H)
xor 0011 0111 (37H)
  = 0010 0000 (20)
(Space)
4E38H394438
    0011 1001 (39H)
xor 0100 0100 (44H)
  = 0111 1101

    0111 1101 (7DH)
xor 0011 1000 (38H)
  = 0100 0101 (45)
E
4E39H5D4439
    0101 1101 (5DH)
xor 0100 0100 (44H)
  = 0001 1001

    0001 1001 (19H)
xor 0011 1001 (39H)
  = 0010 0000 (20)
(Space)
4E3AH5E443A
    0101 1110 (5EH)
xor 0100 0100 (44H)
  = 0001 1010

    0001 1010 (1AH)
xor 0011 1010 (3AH)
  = 0010 0000 (20)
(Space)
4E3BH5E443B
    0101 1110 (5EH)
xor 0100 0100 (44H)
  = 0001 1010

    0001 1010 (1AH)
xor 0011 1011 (3BH)
  = 0010 0001 (21)
!
4E3CH58443C
    0101 1000 (58H)
xor 0100 0100 (44H)
  = 0001 1100

    0001 1100 (1CH)
xor 0011 1100 (3CH)
  = 0010 0000 (20)
(Space)
4E3DH59443D
    0101 1001 (59H)
xor 0100 0100 (44H)
  = 0001 1101

    0001 1101 (1DH)
xor 0011 1101 (3DH)
  = 0010 0000 (20)
(Space)
4E3EH5A443E
    0101 1010 (5AH)
xor 0100 0100 (44H)
  = 0001 1110

    0001 1110 (1EH)
xor 0011 1110 (3EH)
  = 0010 0000 (20)
(Space)
4E3FH5B443F
    0101 1011 (5BH)
xor 0100 0100 (44H)
  = 0001 1111

    0001 1111 (1FH)
xor 0011 1111 (3FH)
  = 0010 0000 (20)
(Space)
4E40H244440
    0010 0100 (24H)
xor 0100 0100 (44H)
  = 0110 0000

    0110 0000 (60H)
xor 0100 0000 (40H)
  = 0010 0000 (20)
(Space)
4E41H2F4441
    0010 1111 (2FH)
xor 0100 0100 (44H)
  = 0110 1011

    0110 1011 (6BH)
xor 0100 0001 (41H)
  = 0010 1010 (2A)
*
4E42H264442
    0010 0110 (26H)
xor 0100 0100 (44H)
  = 0110 0010

    0110 0010 (62H)
xor 0100 0010 (42H)
  = 0010 0000 (20)
(Space)
4E43H2D4443
    0010 1101 (2DH)
xor 0100 0100 (44H)
  = 0110 1001

    0110 1001 (69H)
xor 0100 0011 (43H)
  = 0010 1010 (2A)
*
4E44HDD4444
    1101 1101 (DDH)
xor 0100 0100 (44H)
  = 1001 1001

    1001 1001 (99H)
xor 0100 0100 (44H)
  = 1101 1101 (DD)
(DDH Non-ASCII)
4E45H2B4445
    0010 1011 (2BH)
xor 0100 0100 (44H)
  = 0110 1111

    0110 1111 (6FH)
xor 0100 0101 (45H)
  = 0010 1010 (2A)
*
4E46H224446
    0010 0010 (22H)
xor 0100 0100 (44H)
  = 0110 0110

    0110 0110 (66H)
xor 0100 0110 (46H)
  = 0010 0000 (20)
(Space)
4E47H294447
    0010 1001 (29H)
xor 0100 0100 (44H)
  = 0110 1101

    0110 1101 (6DH)
xor 0100 0111 (47H)
  = 0010 1010 (2A)
*
4E48H2C4448
    0010 1100 (2CH)
xor 0100 0100 (44H)
  = 0110 1000

    0110 1000 (68H)
xor 0100 1000 (48H)
  = 0010 0000 (20)
(Space)
4E49H2D4449
    0010 1101 (2DH)
xor 0100 0100 (44H)
  = 0110 1001

    0110 1001 (69H)
xor 0100 1001 (49H)
  = 0010 0000 (20)
(Space)
4E4AH5A444A
    0101 1010 (5AH)
xor 0100 0100 (44H)
  = 0001 1110

    0001 1110 (1EH)
xor 0100 1010 (4AH)
  = 0101 0100 (54)
T
4E4BH47444B
    0100 0111 (47H)
xor 0100 0100 (44H)
  = 0000 0011

    0000 0011 (03H)
xor 0100 1011 (4BH)
  = 0100 1000 (48)
H
4E4CH41444C
    0100 0001 (41H)
xor 0100 0100 (44H)
  = 0000 0101

    0000 0101 (05H)
xor 0100 1100 (4CH)
  = 0100 1001 (49)
I
4E4DH5A444D
    0101 1010 (5AH)
xor 0100 0100 (44H)
  = 0001 1110

    0001 1110 (1EH)
xor 0100 1101 (4DH)
  = 0101 0011 (53)
S
4E4EH2A444E
    0010 1010 (2AH)
xor 0100 0100 (44H)
  = 0110 1110

    0110 1110 (6EH)
xor 0100 1110 (4EH)
  = 0010 0000 (20)
(Space)
4E4FH44444F
    0100 0100 (44H)
xor 0100 0100 (44H)
  = 0000 0000

    0000 0000 (00H)
xor 0100 1111 (4FH)
  = 0100 1111 (4F)
O
4E50H444450
    0100 0100 (44H)
xor 0100 0100 (44H)
  = 0000 0000

    0000 0000 (00H)
xor 0101 0000 (50H)
  = 0101 0000 (50)
P
4E51H504451
    0101 0000 (50H)
xor 0100 0100 (44H)
  = 0001 0100

    0001 0100 (14H)
xor 0101 0001 (51H)
  = 0100 0101 (45)
E
4E52H444452
    0100 0100 (44H)
xor 0100 0100 (44H)
  = 0000 0000

    0000 0000 (00H)
xor 0101 0010 (52H)
  = 0101 0010 (52)
R
4E53H564453
    0101 0110 (56H)
xor 0100 0100 (44H)
  = 0001 0010

    0001 0010 (12H)
xor 0101 0011 (53H)
  = 0100 0001 (41)
A
4E54H444454
    0100 0100 (44H)
xor 0100 0100 (44H)
  = 0000 0000

    0000 0000 (00H)
xor 0101 0100 (54H)
  = 0101 0100 (54)
T
4E55H584455
    0101 1000 (58H)
xor 0100 0100 (44H)
  = 0001 1100

    0001 1100 (1CH)
xor 0101 0101 (55H)
  = 0100 1001 (49)
I
4E56H5C4456
    0101 1100 (5CH)
xor 0100 0100 (44H)
  = 0001 1000

    0001 1000 (18H)
xor 0101 0110 (56H)
  = 0100 1110 (4E)
N
4E57H544457
    0101 0100 (54H)
xor 0100 0100 (44H)
  = 0001 0000

    0001 0000 (10H)
xor 0101 0111 (57H)
  = 0100 0111 (47)
G
4E58H3C4458
    0011 1100 (3CH)
xor 0100 0100 (44H)
  = 0111 1000

    0111 1000 (78H)
xor 0101 1000 (58H)
  = 0010 0000 (20)
(Space)
4E59H4E4459
    0100 1110 (4EH)
xor 0100 0100 (44H)
  = 0000 1010

    0000 1010 (0AH)
xor 0101 1001 (59H)
  = 0101 0011 (53)
S
4E5AH47445A
    0100 0111 (47H)
xor 0100 0100 (44H)
  = 0000 0011

    0000 0011 (03H)
xor 0101 1010 (5AH)
  = 0101 1001 (59)
Y
4E5BH4C445B
    0100 1100 (4CH)
xor 0100 0100 (44H)
  = 0000 1000

    0000 1000 (08H)
xor 0101 1011 (5BH)
  = 0101 0011 (53)
S
4E5CH4C445C
    0100 1100 (4CH)
xor 0100 0100 (44H)
  = 0000 1000

    0000 1000 (08H)
xor 0101 1100 (5CH)
  = 0101 0100 (54)
T
4E5DH5C445D
    0101 1100 (5CH)
xor 0100 0100 (44H)
  = 0001 1000

    0001 1000 (18H)
xor 0101 1101 (5DH)
  = 0100 0101 (45)
E
4E5EH57445E
    0101 0111 (57H)
xor 0100 0100 (44H)
  = 0001 0011

    0001 0011 (13H)
xor 0101 1110 (5EH)
  = 0100 1101 (4D)
M
4E5FH3B445F
    0011 1011 (3BH)
xor 0100 0100 (44H)
  = 0111 1111

    0111 1111 (7FH)
xor 0101 1111 (5FH)
  = 0010 0000 (20)
(Space)
4E60H734460
    0111 0011 (73H)
xor 0100 0100 (44H)
  = 0011 0111

    0011 0111 (37H)
xor 0110 0000 (60H)
  = 0101 0111 (57)
W
4E61H644461
    0110 0100 (64H)
xor 0100 0100 (44H)
  = 0010 0000

    0010 0000 (20H)
xor 0110 0001 (61H)
  = 0100 0001 (41)
A
4E62H754462
    0111 0101 (75H)
xor 0100 0100 (44H)
  = 0011 0001

    0011 0001 (31H)
xor 0110 0010 (62H)
  = 0101 0011 (53)
S
4E63H074463
    0000 0111 (07H)
xor 0100 0100 (44H)
  = 0100 0011

    0100 0011 (43H)
xor 0110 0011 (63H)
  = 0010 0000 (20)
(Space)
4E64H004464
    0000 0000 (00H)
xor 0100 0100 (44H)
  = 0100 0100

    0100 0100 (44H)
xor 0110 0100 (64H)
  = 0010 0000 (20)
(Space)
4E65H0B4465
    0000 1011 (0BH)
xor 0100 0100 (44H)
  = 0100 1111

    0100 1111 (4FH)
xor 0110 0101 (65H)
  = 0010 1010 (2A)
*
4E66H024466
    0000 0010 (02H)
xor 0100 0100 (44H)
  = 0100 0110

    0100 0110 (46H)
xor 0110 0110 (66H)
  = 0010 0000 (20)
(Space)
4E67H094467
    0000 1001 (09H)
xor 0100 0100 (44H)
  = 0100 1101

    0100 1101 (4DH)
xor 0110 0111 (67H)
  = 0010 1010 (2A)
*
......
4FCAH8D44CAH
    1000 1101 (8DH)
xor 0100 0100 (44H)
  = 1100 1001

    1100 1001 (C9H)
xor 1100 1010 (CAH)
  = 0000 0011 (03)
END DELIMETER

Special thanks to George Phillips (really, every page should say this) for his assistance here. I had used Gemini and Gemini came up with a fantastic halluciation about a double table in RAM, one with the encoded bytes, and one with the key to XOR against; which apparently was not accurate.


TRSDOS v1.3

In Model III BASIC under TRSDOS 1.3 type CMD"&"& and you will get:

TRSDOS 1.3 Hidden Message

LDOS v5.1.0

Type the command A! or B! at the LDOS Ready prompt. It will print "Hi there! This command is reserved for the future by your LDOS Support group. Roy, Bill, Tim, Chuck, Dick." (The "Tim" was Tim Mann.)

LDOS 5.1 Hidden Message

Tandy made LSI change the message in the versions Radio Shack shipped to something different, probably due to vivid memories of Randy Cooks activities. (Mike Yetsko).

LDOS 5.3.1 Hidden Message

You'll also find "Roy" or "Tim" here and there in the middle of a few /CMD or /DVR or /SYS files. When the development team needed a 3-byte data area that didn't have to be initialized to anything in particular, they'd sometimes have the assembler put their names there. (Tim Mann).

Roy thought that the "T" in RS232T/DVR (the Model III RS232 driver) was meant to stand for "Tim". (Tim really didn't, Tim just thought RS2323/DVR would look silly, he picked T to stand for "three".) So Roy changed the name of the Model I RS232 driver to RS232R/DVR, claiming that "R" stood for "Radio Shack", not "Roy." (Tim Mann).

XENIX v3.0

On XENIX 3.0, in a really obscure hardware failure condition (the Z80 got back to the main operation dispatch loop with the stack at a different depth than it was on the previous pass), z80ctl would spit out:

Bugchk: Sckmud
"Shut her down Scotty, she's sucking mud again!"

"Shut her down Scotty..." was somebodys' sig line on USENET back around 1984 and the vision of Captain Kirk yelling this down to Scotty always struck Frank as very funny, so when Frank needed a message for this insanely implausable condition Frank had seen a few times in test, Frank felt you needed a special reward if you managed to get here, so Frank picked that message. The technical support documentation describing this message suggested that rebooting soon would be a good career move. (Frank Durda IV)

Scott Adams' Adventures

In the specially formatted copy protection sector on track 0 of an Scott Adams (Adventure International) disk, there is a message from Kim Watt, who designed the copy protection scheme, saying roughly "If you can read this, phone Kim Watt at xxx-yyy-zzzz to find out what reward you get." (Tim Mann).

Bugs

Olympic Decathlon (Richard Merryman 2016-04-12)

In the high jump event, after you press [SPACEBAR] to start running wait for the athlete to appear on the left side of the screen. As soon as the athlete appears press [DOWN] followed immediately with [ENTER]. The athlete will proceed to jump backwards off the left side of the screen which results in a GOOD JUMP!

You can do this over and over as the bar gets higher and higher until the bar gets to 270cm. For some odd reason at this point the pole vault box appears in front of the bar and your running speed increases from 620 CM/SEC to 56276 CM/SEC. Your distance goes haywire and your athlete never appears on the screen and it says YOU DIDN'T JUMP! after a few seconds. It will do this until you exhaust your three attempts to clear the bar and you will end up with a score of 1290 for the event.

TRS-80 ROM

In BASIC, if you enter 3 spaces and then a '(apostrophe), followed by ENTER, and then enter 4 spaces and then a '(apostrophe), followed by ENTER, your TRS-80 will crash.

George Phillips noted that this can also be accomplished by RIGHT ARROW'ENTER'ENTER.

That's it. The computer will not return to READY. Following a pause, the computer will restart.

The right-arrow acts like a tab key and is equivalent to 8 spaces in this case. The bug depends on spaces at the start of your command and needs at least 3. What appears after those spaces doesn't much matter. Typing this will do the trick:

SPACESPACESPACEDIE!ENTER'ENTER

The apostrophe in the second line is critical but other characters can be put in front of it as long as they don't contain any reserved words longer than two characters. This will cause a crash:

SPACESPACESPACENEWENTERI WOULDN'T PRESS ENTER IF I WERE YOU!ENTER

But this will not:

SPACESPACESPACENEWENTERDON'T PRESS ENTER!ENTER

because the reserved word ON appears before the apostrophe. Yes, being part of the larger word DON counts.

The crash occurs in the subroutine where BASIC tokenizes what you typed in. Tokenizing is nothing more than translating BASIC commands and operators into single byte codes. It's a form of compression that makes a BASIC program take less memory and run faster. BASIC lines can be pretty long, about 255 characters, so that much space must be reserved for what you type. Doesn't seem much by today's (2010) standards, but that may have been as much at 6 percent of total available memory if you had 4K. That's like letting a modern machine have an input buffer 64 megabytes long. In the worst case the input line doesn't compress at all and you need a whole 255 characters for the tokenized version.

But the programmers of BASIC were clever. Since tokenization never makes the input bigger you can write the tokenized version over what was typed in. Completely worthwhile.

It turns out there's a small catch. There is one thing that gets bigger when you tokenize it: the apostrophe. In this dialect of BASIC the apostophe means to ignore the rest of the line. That is, treat it as a comment. I can only guess why it gets turned into 3 whole bytes, but the point is that a tokenized line with an apostrophe could end up two bytes bigger than the input.

No worries. Instead of tokenizing the input over itself, we'll put the tokenization two bytes back. Problem solved. Now what about if there are two (or more!) apostrophes in the input? That's OK. The first one will bloat by two bytes but the others will stay as a single byte because no tokenization happens in the comment.

Everything is perfectly fine, but there's another little bug. When you type in a line you have two fundamental options. Either you're saying "do this now" or "add it to the program I'm working on". If you start with a number it means "add to the program at that line number". Without a number it means "run right away". Thus when BASIC gets a line of input it doesn't tokenize it right away. Instead it first looks to see if there's a number at the start. If so, it notes the line number and calls the tokenizer on whatever appears after the line number. If not, then it can call the tokenizer right away.

Well, it can't call it right away. To look for a number it called a common subroutine. That subroutine does something generally useful. It skips over spaces before looking for a number and skips any spaces after the number. No big deal, but unless something is done you won't be able to indent your BASIC lines. For instance, if you typed:

10 FOR I = 1 TO 5
20 PRINT "HELLO"
30 NEXT I

It would come out looking like this:

10 FOR I = 1 TO 5
20 PRINT "HELLO"
30 NEXT I

The indent on line 20 to make it readable has been lost! Horrifying. Again, easy to fix. After getting the line number we'll back up over any spaces. That way they'll be included in the program. And we don't have to worry backing up because there's the line number to bump into.

And that's it right there. That's the bug. What if there isn't a line number to bump into? What if someone typed something to be executed directly without a line number?

In that case we'll end up starting BEFORE the input buffer and skipping backwards over any spaces we see. This is bad news but often it works out OK. Remember that due to the overlapping what's just before the input buffer is the first two bytes of the previously tokenized line. In almost all cases that character before the input line won't be a space. In fact, I believe it will be a space only if the previous line started with three spaces (sound familiar?). You might think two spaces would do the trick, but BASIC has one more little fudge. Before it tokenzies a line it skips the first space. If the previous input started with three spaces, we'll see two spaces as we back up. And then, by some miracle, we stop. I don't know what stops us, but it must be something that isn't a space. We're about to tell the tokenizer to work from the input buffer directly over itself. It's not quite that bad as we skip over one of the spaces. Too little, too late. There's only a one character safety margin. But you know what, that's OK. Just as long as we don't hit an apostrophe things will be just fine. In fact, if we manage to save some space by tokenizing even a two letter word before the apostrophe we'll be fine.

But if not, look out! That apostrophe will get turned into three bytes. The last of those three bytes is $FB and will be written right where we're looking for our next input character. Recall that once we see the apostrophe we're to copy over the rest of the input verbatim. And we do so until we see a nul ($00) character. We pick up the $FB, write it one down, move to the next character which is the $FB we just wrote because we're overwriting the input buffer on ourself. Thus we being filling memory with $FB until infinity. But we don't hang like one might expect. Eventually we'll get to the end of RAM. On a 48K system the next thing after RAM is the ROM starting over at address 0. We can't write $FB into the ROM we'll break out of our loop as soon as we hit the first zero in ROM. But when the tokenizer goes to return it will have a problem. The return address on the stack got overwritten with $FBFB (as did most of memory). Now we end up going to $FBFB instead of back to BASIC. $FBFB and on up is filled with $FB which the Z-80 will race down quite quickly until it gets to the end of RAM and back to 0. Which is great, because that's where it starts when you power on the machine. So there you are at the "MEMORY SIZE?" prompt or similar.

Things might go down slighly differently if you don't have 48K or have disk drives, real time clocks or anything else that may interrupt the Z-80 in the middle of its death spiral. The end result is likely the same. You'll be OK on the Model III even with its real time clock because the one small piece of RAM that didn't get stomped has all the critical interrupt routine variables in it. If you have and kind of DOS running it will be stomped and who knows what happens. If you have less that 48K you'll still end up jumping to $FBFB. With no valid RAM at that address the processor will see $FF which means "call the interrupt routine". If you even survive that first call, there are a whole bunch more to do. Either it crashes right away or makes a whole bunch more calls before finally hitting zero. There's a simple patch to fix the bug - zero out $1A8C through $1A90. That will get rid of the "backing up" code. But it'll mean you can't type in spaces at the start of your BASIC lines any more.

DOS Oddity re Hexadecimal

When using the hex to decimal conversion in a DISK BASIC or LEVEL 3 BASIC program you will not be able to enter any hex number with the &H notation that has a "DEF" embedded (e.g., FDEF, DEF1, etc). Since DEF is a reserved word you will get an incorrect (partial) hex conversion, and then a SYNTAX ERROR!!!