Model 100 and TP-10

Improved Banner Program for the TRS-80 Model 100

After successfully finding and connecting a vintage TP-10 thermal printer to the Model 100, I tried out a slightly modified version of my banner program for the PC-8. One of the items I wanted to improve for the Model 100 version was the character bitmap data.

When working with the PC-8, my original idea was to read the font bitmap data directly from the PC-8’s ROM using the undocumented PEEK command. However, the PEEK command on the PC-8 works only with the 2KB RAM memory space and not the ROM. I had to recreate the font bitmap myself and store it within a series of DATA statements in my program.

Even though the method I used for the banner program on the PC-8 was optimized for memory usage, it would have been far more optimized if I didn’t need to store the font bitmap as part of the program.

When working with the Model 100 version, my initial approach was to simply tweak only what was necessary to get the program to work with the TP-10 printer. However, further improvements could be made. The first and easiest improvement would be to use the Model 100’s built in font bitmap data instead of recreating it within the program using a series of DATA statements. This would not only save a bit of RAM, but it would also expand the character set supported by the program. This is because I would be able to use all of the characters the Model 100 has a bitmap for, as opposed to the limited characters I recreated by hand and included within the program itself.

Finding the Characters

I had a few options for finding where in ROM the font bitmap data was hiding. First, I could search for a known pattern, such as the character “A”. Both the Model 100 and the PC-8 (along with most other pocket computers of the era) used the same or very similar 5 x 7 font. Therefore, if I knew how the letter “A” was stored in ROM, I could search for the pattern.

I suspected the storage of the font bitmap data in the Model 100 ROM would be the same approach I took with my PC-8 program. It would store the data as a series of 5 bytes per character, with each byte being a “row” of bits if the character were horizontally rotated.

Model 100 – Sample of a 5 x 7 character

To illustrate further, the letter “A” if rotated 90 degrees, is 7 pixels wide by 5 rows tall. This means I need 5 bytes of data to represent the character in a bitmap. In each of these bytes, each pixel in the row represents a bit in the same position within the byte. The 8th bit would usually be zero.

BYTE 1: 01111100
BYTE 2: 00010010
BYTE 3: 00010001
BYTE 4: 00010010
BYTE 5: 01111100

For example, the first row, or byte 1 in the character “A” can be represented by a decimal value of 124 (111100 binary). The 8th bit would always be zero, since the font is only 7 pixels wide. In hexadecimal notation, this would be 0x7C. The next byte would be 0x12, and so on.

The letter A therefore can be represented by the following byte values: 0x7C, 0x12, 0x11, 0x12, 0x7C.

I could search the Model 100 ROM for these 5 bytes occurring in sequence. This would indicate where the letter “A” is stored, and then I can work from there to address the other characters. This could easily be done in BASIC if needed.

However, I figured it would be worth a try to search the world wide web for a ROM dump, ideally with some notes on where things are and what they do. Luckily, I ran across a ROM dump of the Model 100 on the club100.org site (from a member’s post). It had the following section:

; ======================================================
; LCD char generator shape table (20H-7FH
; ======================================================
7711H DB 00H,00H,00H,00H,00H,00H,00H,4FH
7719H DB 00H,00H,00H,07H,00H,07H,00H,14H
7721H DB 7FH,14H,7FH,14H,24H,2AH,7FH,2AH
7729H DB 12H,23H,13H,08H,64H,62H,3AH,45H
7731H DB 4AH,30H,28H,00H,04H,02H,01H,00H
7739H DB 00H,1CH,22H,41H,00H,00H,41H,22H
7741H DB 1CH,00H,22H,14H,7FH,14H,22H,08H
7749H DB 08H,3EH,08H,08H,00H,80H,60H,00H
7751H DB 00H,08H,08H,08H,08H,08H,00H,60H
7759H DB 60H,00H,00H,40H,20H,10H,08H,04H
7761H DB 3EH,51H,49H,45H,3EH,44H,42H,7FH
7769H DB 40H,40H,62H,51H,51H,49H,46H,22H
7771H DB 41H,49H,49H,36H,18H,14H,12H,7FH
7779H DB 10H,47H,45H,45H,29H,11H,3CH,4AH
7781H DB 49H,49H,30H,03H,01H,79H,05H,03H
7789H DB 36H,49H,49H,49H,36H,06H,49H,49H
7791H DB 29H,1EH,00H,00H,24H,00H,00H,00H
7799H DB 80H,64H,00H,00H,08H,1CH,36H,63H
77A1H DB 41H,14H,14H,14H,14H,14H,41H,63H
77A9H DB 36H,1CH,08H,02H,01H,51H,09H,06H
77B1H DB 32H,49H,79H,41H,3EH,7CH,12H,11H
77B9H DB 12H,7CH,41H,7FH,49H,49H,36H,1CH
77C1H DB 22H,41H,41H,22H,41H,7FH,41H,22H
77C9H DB 1CH,7FH,49H,49H,49H,41H,7FH,09H
77D1H DB 09H,09H,01H,3EH,41H,49H,49H,3AH
77D9H DB 7FH,08H,08H,08H,7FH,00H,41H,7FH
77E1H DB 41H,00H,30H,40H,41H,3FH,01H,7FH
77E9H DB 08H,14H,22H,41H,7FH,40H,40H,40H
77F1H DB 40H,7FH,02H,0CH,02H,7FH,7FH,06H
77F9H DB 08H,30H,7FH,3EH,41H,41H,41H,3EH
7801H DB 7FH,09H,09H,09H,06H,3EH,41H,51H
7809H DB 21H,5EH,7FH,09H,19H,29H,46H,26H
7811H DB 49H,49H,49H,32H,01H,01H,7FH,01H
7819H DB 01H,3FH,40H,40H,40H,3FH,0FH,30H
7821H DB 40H,30H,0FH,7FH,20H,18H,20H,7FH
7829H DB 63H,14H,08H,14H,63H,07H,08H,78H
7831H DB 08H,07H,61H,51H,49H,45H,43H,00H
7839H DB 7FH,41H,41H,00H,04H,08H,10H,20H
7841H DB 40H,00H,41H,41H,7FH,00H,04H,02H

We can see the letter A bitmap represented in the bitmap data above, highlighted.

What a convenient find! The banner program already works with the bitmap data in this format. Next, I needed to ensure that the characters are in a convenient or usable sequence. Ideally, in sequence that’s linear at least in part with the ASCII character set. This allows me to easily index this bitmap array.

As it turns out, all of the characters I tested for were in fact stored in a linear fashion with respect to the ASCII character codes.

Upon further testing and inspection, I found that some characters, such as the lower-case “g” and “j” used the 8th bit in the font bitmap data. Therefore, I modified the program to inspect and use the 8th bit.

Caveat

It is possible that other versions of the ROM for the Model 100 have the bitmap data in a different location than the version I have. Or, for other similar models, it might be in a different location, such as the Model 102 for example.

Improvements Made

Now that I know where the font bitmap data resides in the Model 100, I can modify the banner program further. I can remove the DATA bytes at the beginning of my program and reference the bitmap data in the ROM.

Further, every character on the keyboard is available to be used on the banners since this bitmap contains all of the characters, even lower case characters.

Final Thoughts

Improving the banner program to use even less memory was possible on the Model 100. It’s a bit ironic that the computer with far more memory could be optimized more and consume less memory than the computer with less memory (the PC-8).

In addition to using less memory, this version supports far more characters than the previous version on the PC-8.

Program Listing

Below is the listing for the updated banner program. Note that the REM statements should be ignored and not included in the program.

REM LCD 5x8 FONT IN ROM STARTS AT 0x7711

REM INIT AND LOOP THROUGH EACH CHAR IN STRING TO PRINT FOR BANNER

100 CLEAR : OPEN "COM:48N2D" FOR OUTPUT AS 1
110 X$ = CHR$(143) + CHR$(159) : X$ = X$ + X$
120 Y$ = CHR$(128) + CHR$(144) : Y$ = Y$ + Y$
130 INPUT “Banner Text”;T$
140 PRINT #1,CHR$(26);
150 L = LEN(T$)
160 FOR C = 1 TO L

REM READ TO LOCATION IN DATA ARRAY FOR CURRENT CHAR BITMAP
 
170 E$ = MID$(T$,C,1)
180 K = ASC(E$) : A = 30646
190 A = A + ((K - 65) * 5)
200 B = PEEK(A)
REM READ EACH ROW IN BITMAP FOR THIS CHAR
300 FOR D = 1 TO 5
305 Z$ = "" : G = 128
310 FOR F = 1 TO 8
320 H = B AND G : IF H = 0 THEN GOTO 340
330 Z$ = Z$ + X$ : GOTO 350
340 Z$ = Z$ + Y$
350 G = G / 2 : NEXT F

REM PRINT THIS LINE TO PRINTER

400 GOSUB 500 : GOSUB 500 : GOSUB 500
410 A = A + 1 : B = PEEK(A) : NEXT D
420 Z$ = CHR$(13) + CHR$(13) : GOSUB 500
425 NEXT C
430 END

REM STRING TO PRINT IS Z$, ONE CHAR AT A TIME, THEN CR/LF CONTROL TO PRINTER

500 M = LEN(Z$)
510 FOR N = 1 TO M
520 PRINT #1,MID$(Z$,N,1);
527 GOSUB 600
530 NEXT N
540 PRINT #1,CHR$(13);
560 GOSUB 600
570 RETURN

REM READ CTS BIT AND RETURN WHEN LOW (INVERTED)

600 O = 0 : O = INP(187) AND 16
610 IF O = 0 THEN RETURN
620 GOTO 600

Leave a Reply