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.
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.
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.
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.
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.
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