Clock

This file is part of Byte Power December 1986 - January 1987 . Download the collection to get this file.
Developer(s): Eric Boisvert
Date: 1987
Type: Program
Platform(s): TS 2068

This program is a loader and documentation stub for an interrupt-driven real-time clock implemented in machine code. The machine code block, 536 bytes long starting at address 64770, hooks into the system interrupt to maintain a running hours/minutes/seconds clock entirely in the background. Three USR entry points are provided: 64770 to enter the time interactively (accepting H, M, S, and ENTER keystrokes), 65303 to stop the clock, and 65296 to start it. POKEs at addresses 64970–64972 give direct read/write access to the seconds, minutes, and hours counters, while a POKE to 64887 toggles the display on or off and 64858 selects between 50 Hz (ZX Spectrum) and 60 Hz (TS2068) interrupt rates. The BASIC loader checks PEEK 23681 to detect whether the machine code is already resident before deciding whether to load or just list the documentation.


Program Structure

The BASIC listing is almost entirely comments and loader logic, with the real work performed by the 536-byte machine code block loaded separately. The program divides into four logical regions:

  1. Lines 10–170: REM-based API documentation for the machine code module.
  2. Lines 175–180: Residency check and graceful abort if the machine code is not yet present.
  3. Lines 9000–9020: The actual loader, reached either by direct RUN or by LOAD "CLOCK" LINE 9000.
  4. Line 9999: Combined SAVE routine that writes both the BASIC program and the machine code tape block.

Residency Detection

Line 175 uses PEEK 23681 as a sentinel. Address 23681 is the system variable FRAMES (low byte of the frame counter). The check IF PEEK 23681=0 is used loosely here as a proxy: if the machine code has not yet been loaded and started, this byte happens to be zero (or the interrupt hook is inactive), so the program clears the screen, lists the stub at line 9999, and stops. After a successful load and RANDOMIZE USR 65296 starts the clock, the interrupt routine keeps FRAMES non-zero, so re-running the BASIC program falls through to the documentation list instead of re-loading.

Line 9010 performs a complementary check after loading: IF PEEK 23681<>0 THEN RANDOMIZE USR 65296 starts the clock immediately if the environment looks live, then lists the documentation.

Machine Code API

AddressPurpose
64770Entry point: interactive time-set (H / M / S / ENTER keys)
65296Start the interrupt clock
65303Stop the interrupt clock
AddressPOKE value / meaning
64970Seconds counter (read/write)
64971Minutes counter (read/write)
64972Hours counter (read/write)
64887201 = display off; 33 = display on (likely a RET / INC opcode swap)
64894Attribute byte controlling clock colour
6485860 = TS2068 (60 Hz); 50 = ZX Spectrum (50 Hz) interrupt divisor
64888Column/row position of colour display
64902Column/row position of digit display

Notable Techniques

  • Interrupt hook: The machine code installs itself into the IM 1 / IM 2 interrupt chain so the clock ticks without any BASIC involvement, a common but non-trivial technique in the upper RAM area near 64770 (0xFD02).
  • 50/60 Hz configurable divisor: POKE 64858 lets the user correct for the different mains frequencies of PAL (50 Hz) and NTSC (60 Hz) machines, making the clock accurate on both.
  • Display toggle via opcode swap: POKE 64887,201 writes a RET opcode (0xC9), effectively disabling the display routine; POKE 64887,33 restores an LD HL,nn opcode (0x21), re-enabling it — a classic self-modifying code pattern.
  • Combined SAVE on one line: Line 9999 saves both the BASIC program (SAVE "CLOCK" LINE 9000) and the 536-byte machine code block (SAVE "CLOCK Mc" CODE 64770,536), followed by two VERIFY passes for tape reliability.
  • High RAM placement: Locating the code above 64770 (0xFD02) keeps it well above normal BASIC/variable space and out of the way of most programs, while still being below the 65535 boundary.

Content

Appears On

Related Products

Related Articles

This program is quite simply a clock, it might be useful in many ways. Example in a game where you...

Related Content

Image Gallery

Clock

Source Code

10 REM  INTERUPT CLOCK                 By Eric Boisvert                ©1987 BYTE POWER         
   25 REM  USR CALLS 
   30 REM 64770 ENTER TIME,      Keys [H]our,[M]inutes,[S]econds and [ENTER]
   40 REM 65303 STOP CLOCK
   50 REM 65296 START CLOCK
   60 REM  USEFULL POKES 
   70 REM 64970,SECONDS
   80 REM 64971,MINUTES
   90 REM 64972,HOURS
  100 REM 64887,201  NO DISPLAY
  110 REM 64887,33   DISPLAY ON
  120 REM 64894,COLOR OF CLOCK
  130 REM 64858,60 T/S 2068
  140 REM 64858,50 ZX SPECTRUM
  150 REM  SPECIAL POKES 
  160 REM 64888,COLOR POSITION
  170 REM 64902,NUMBERS POSITION
  175 IF PEEK 23681=0 THEN CLS : LIST 9999: STOP 
  180 STOP 
 9000 REM LOAD CODES
 9010 LOAD "CLOCK Mc"CODE : IF PEEK 23681<>0 THEN RANDOMIZE USR 65296: CLS : LIST 
 9020 CLS : LIST 9999: STOP 
 9999 SAVE "CLOCK" LINE 9000: SAVE "CLOCK Mc"CODE 64770,536: VERIFY "": VERIFY ""CODE

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

Scroll to Top