Character

Date: 198x
Type: Program
Platform(s): TS 2068
Tags: Utility

This program is a character set browser that displays each of the 96 printable ASCII characters (codes 32–127) along with a visual representation of the 8×8 pixel bitmap that defines each glyph. It reads the ROM character set address from system variables at addresses 23606–23607, then peeks the 8 bytes that define each character’s dot matrix. Each row byte is decomposed bit-by-bit using repeated integer division by 2, and each bit is rendered using a UDG (User Defined Graphic) character — either a filled or empty block depending on whether the bit is 1 or 0. A single UDG is defined at startup via the DATA statement at line 100, which encodes a fully bordered 8×8 square (255, 129, 129, 129, 129, 129, 129, 255). The program pauses between characters waiting for a keypress, then stops after displaying all 96 characters.


Program Analysis

Program Structure

The program is organized into three logical phases:

  1. Initialization (lines 5–10): Defines a single UDG and locates the ROM character set base address.
  2. Display loop (lines 15–65): Iterates over all 96 printable characters (ASCII 32–127), displaying each glyph’s bitmap row by row with a keypress pause between entries.
  3. Data (line 100): Provides the 8 bytes for the UDG used to render “off” pixels (a hollow bordered square).

Character Set Address Lookup

Line 10 reads the system variable pair at addresses 23606 and 23607, which together hold a pointer to the start of the character set data (normally pointing into ROM). The formula PEEK 23606 + 256 * PEEK 23607 + 256 computes the 16-bit address and adds 256. This offset of 256 is necessary because the system variable actually points 256 bytes before the character data for CHR$ 32 (space), so adding 256 aligns o to the actual start of the space character’s bitmap. Each subsequent character occupies 8 consecutive bytes, accessed as o + p + j*8 where j is the character index (0–95) and p is the row (0–7).

Bit Extraction Technique

Lines 35–50 implement a right-to-left bit unpacking loop without using bitwise operators. For each of the 8 bits in a byte, the code computes:

  • x = INT(byte / 2) — integer quotient (shifts right by one bit)
  • bit = byte - 2*x — the least significant bit (0 or 1)
  • byte = x — advance to next bit

Because bits are extracted LSB-first but printed left-to-right with a decrementing column index (AT p, 9-l), the display ends up correctly oriented — bit 7 (MSB) appears at the leftmost column.

UDG Usage

Only one UDG is defined (character 144, \a), using the 8 bytes 255,129,129,129,129,129,129,255 — an 8×8 square outline. This represents an “off” pixel. An “on” pixel is rendered as CHR$(144 - 1) = CHR$ 143, which is the built-in block graphic character \::=█ (a fully filled 8×8 block). The expression CHR$(144 - bit) thus elegantly selects between the filled block (when bit=1) and the UDG square outline (when bit=0).

Display Layout

For each character, the screen shows:

  • The character code and the character itself printed at row 4, column 20 (AT 4,20)
  • The decimal byte value for each of the 8 rows, printed at column 15
  • The 8×1 pixel row rendered graphically starting at column 2 (columns 2–9), using AT p, 9-l

Notable Idioms and Anomalies

The PAUSE 0 at line 60 waits indefinitely until any key is pressed — a standard keypress-wait idiom. The condition IF j<>95 skips the pause after the final character (index 95, CHR$ 127), so the program simply halts with STOP at line 65 after the last entry.

Line 9997 contains a redundant STOP that is unreachable under normal execution. Line 9998 is a SAVE statement that saves the program.

Variable Summary

VariablePurpose
oBase address of character bitmap data in ROM
jCharacter index (0–95, corresponding to CHR$ 32–127)
pRow index within the 8×8 character bitmap (0–7)
byteCurrent bitmap row byte, consumed during bit extraction
lBit position counter within a row (1–8)
xTemporary integer quotient during bit extraction
bitExtracted bit value (0 or 1)
aTemporary variable for reading UDG DATA bytes

Content

Appears On

The biggest LIST tape yet — play poker accompanied by chip-tune renditions of classic songs, diagnose illnesses with a Bayesian expert system, master Z80 opcodes with a quiz, or unscramble anagrams before the cauldron boils over. Four custom fonts included.

Related Products

Related Articles

Related Content

Image Gallery

Source Code

    5 RESTORE : FOR j=0 TO 7: READ a: POKE USR CHR$ 144+j,a: NEXT j
   10 LET o=PEEK 23606+256*PEEK 23607+256
   15 FOR j=0 TO 95: CLS : PRINT AT 4,20;"CHR$ ";j+32;" ";CHR$ (j+32)
   20 FOR p=0 TO 7
   25 LET byte=PEEK (o+p+j*8)
   30 PRINT AT p,15;byte
   35 FOR l=1 TO 8
   40 LET x=INT (byte/2): LET bit=byte-2*x: LET byte=x
   45 PRINT AT p,9-l;CHR$ (144-bit)
   50 NEXT l
   55 NEXT p
   60 IF j<>95 THEN PRINT AT 15,0;"press any key for next character": PAUSE 0
   65 NEXT j: STOP 
  100 DATA 255,129,129,129,129,129,129,255
 9997 STOP 
 9998 SAVE "CHARACTER" LINE 0

Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.

People

No people associated with this content.

Scroll to Top