Italics

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

This program installs a custom italic character set for use in BASIC programs by POKEing 42 bytes of Z80 machine code into address 30000, then executing it with RANDOMIZE USR. The machine code (lines 30–40) copies and transforms the ROM character set from address 15616 (0x3D00) to address 30208 (0x7600), applying two right-rotation operations (RLC→RRC, i.e. CB 63 twice) to each byte to produce an italic slant effect. The resulting 768-byte block (three pages covering 96 characters) is then saved to tape as a named CODE file. After saving, the user redirects the system font pointer via POKEs to addresses 23606 and 23607 (CHARS system variable) in their own program to activate the italic set at any load address.


Program Analysis

Program Structure

The program is a one-shot utility that builds, executes, and saves a machine-code font transformer. Its flow is strictly linear:

  1. Lines 1–5: REM documentation block explaining usage and the CHARS system variable POKEs.
  2. Line 20: LIST — displays the program listing so the user can read the instructions before anything runs.
  3. Line 30: Loads 42 bytes of Z80 machine code into RAM at address 30000.
  4. Line 40: The DATA statement containing those 42 bytes.
  5. Line 50: RANDOMIZE USR 30000 — calls the machine code routine.
  6. Lines 60–80: Asks for a filename, then saves the generated font block.
  7. Lines 90–100: Rewind prompt and VERIFY.
  8. Lines 110–120: Completion beep and NEW to clean up.

Machine Code Routine (address 30000)

The 42 data bytes disassemble to a Z80 routine that copies the ROM character set and applies a bit-rotation to each byte to produce an italic effect:

OffsetBytes (hex)MnemonicNotes
021 00 3DLD HL,3D00hSource: ROM charset (char 32 = space)
311 00 76LD DE,7600hDestination: 30208 decimal
601 00 03LD BC,0300h768 bytes = 96 characters × 8 rows
9ED B0LDIRBlock copy ROM font to RAM
1121 00 76LD HL,7600hPoint to start of copied font
140E 60LD C,60hOuter loop: 96 characters
1606 02LD B,02hInner loop A: 2 rows per pass (top portion)
187ELD A,(HL)Load byte
19CB 3FSRL AShift right logical (italic slant)
21CB 3FSRL ASecond right shift
2377LD (HL),AWrite back
2423INC HLNext row
2510 F7DJNZ 18Loop B times
2706 04LD B,04hInner loop B: 4 rows (middle)
297ELD A,(HL)Load byte
30CB 3FSRL ASingle right shift
3277LD (HL),AWrite back
3323INC HLNext row
3410 F9DJNZ 29Loop B times
3623INC HLSkip remaining 2 rows (bottom = unshifted)
3723INC HL
380DDEC CDecrement character counter
39C8RET ZReturn when all 96 chars processed
4018 E6JR 14Loop back to outer character loop

The italic effect is achieved by dividing each 8-row character bitmap into three zones: the top 2 rows are shifted right by 2 bits (SRL twice), the middle 4 rows by 1 bit, and the bottom 2 rows are left unchanged. This creates a stepped rightward lean that mimics italic slant when rendered on screen.

Font Relocation and the CHARS System Variable

The generated font is saved as a raw CODE block of 768 bytes starting at 30208 (0x7600). To use it, the host program must update the CHARS system variable at addresses 23606–23607, which normally points 256 bytes before the ROM font. The REM in line 5 gives the correct formula:

  • POKE 23606, addr - 256*INT(addr/256) — low byte of (addr − 256)
  • POKE 23607, INT(addr/256) — high byte

Because CHARS is indexed from character 0 (not character 32), the system subtracts 256 bytes (32 chars × 8 rows) from the supplied address, so the caller must account for this offset.

Key BASIC Idioms and Notable Techniques

  • LINE N$ in the INPUT statement (line 60) accepts the full input as a string without string-quote processing, allowing filenames with spaces or special characters.
  • RANDOMIZE USR 30000 is the standard idiom for calling machine code; the return value from the routine (0 from RET Z) is discarded harmlessly.
  • NEW at line 120 clears both the BASIC program and variables after saving, leaving a clean slate — appropriate for a utility intended to run exactly once.
  • The LIST at line 20 serves as an in-program documentation display, ensuring the user reads the REM instructions before any code executes.

Anomalies and Observations

  • The outer loop counter in C is loaded as 0x60 (96), covering the printable ASCII range (characters 32–127), which matches the 768-byte save length exactly.
  • The bottom 2 rows of each character are skipped entirely (two INC HL instructions), so descenders and baseline pixels are not shifted — this preserves legibility at the cost of a slight discontinuity at the character baseline.
  • The routine does not preserve registers, but since it is called via USR and returns with RET Z after the loop naturally exhausts, this is benign.

Content

Appears On

Related Products

Related Articles

Related Content

Image Gallery

Italics

Source Code

    1 REM "CHAR SET2"
    2 REM 'ITALICS'
    3 REM By Ben Stagnell
    4 REM ZX Computing Monthly
    5 REM To use in any memory           addr CLEAR addr-1,             LOAD "code name" CODE           addr, play tape then            type or include as pgm          lines POKE 23606,addr           -256*INT (addr/256): POKE       23607,INT (addr/256)            Where "addr" is any             address you wish to put         the code at.  
   20 LIST 
   30 FOR N=30000 TO 30041: READ A: POKE N,A: NEXT N
   40 DATA 33,0,61,17,0,118,1,0,3,237,176,33,0,118,14,96,6,2,126,203,63,203,63,119,35,16,247,6,4,126,203,63,119,35,16,249,35,35,13,200,24,230
   50 RANDOMIZE USR 30000
   60 INPUT "NAME TO SAVE >) "; LINE N$
   70 CLS : PRINT "SAVING :";N$
   80 SAVE N$CODE 30208,768
   90 PRINT ''"REWIND TAPE TO VERIFY"
  100 VERIFY N$CODE 
  110 BEEP .1,10: PRINT "SAVE COMPLETE"
  120 NEW 

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

People

No people associated with this content.

Scroll to Top