Grafix

Products: Grafix, GRAPHIX
Date: 1982
Type: Program
Platform(s): TS 1000
Tags: Art, Graphics

This program is a full-screen text and block-graphic editor that stores a 704-character (22×32) canvas in the string variable Z$(704). It supports cursor movement, character placement, SAVE/LOAD of the canvas to a named file, RAMTOP-based POKE/PEEK transfer to address 32000, horizontal and vertical scrolling, a mirror/flip function, find-and-replace for graphic characters, and a configurable print routine using direct POKEs to system variables around address 16529. Navigation and command dispatch are handled by a computed GOSUB (line 210: GOSUB X*30+1000), routing keypress codes to the appropriate handler subroutine. The keypress loop at lines 8900–8902 uses PAUSE 40000 followed by CODE INKEY$ as an efficient non-blocking wait.


Program Analysis

Program Structure

The program is organised as a collection of subroutines scattered across a wide line-number range, with a main loop at lines 200–590 and a dispatch table implemented via a computed GOSUB. Lines 1–11 hold short utility subroutines that are called frequently. The initialisation block (lines 100–130) sets up the 704-character canvas string Z$, the cursor position A, the working string X$, and the mode flag Z.

Canvas Layout

The editing canvas is a 704-character string (DIM Z$(704), line 100), representing a 22-row × 32-column display. Position A is a linear index into this string. Row and column are recovered with integer arithmetic:

  • Row: B = INT((A-1)/32) (line 520)
  • Column: A - B*32 - 1 (line 540)

The status line at row 21 is used for prompts and is not part of the canvas data.

Computed GOSUB Dispatch

The central command-dispatch mechanism at line 210 is:

GOSUB X*30+1000

where X is the raw CODE of the last keypress. Each key maps to a handler whose line number equals X*30+1000. For example, key code 119 (the clear/home key) maps to line 119*30+1000 = 4570; the target lines 4538–4540 handle reset. This avoids a long IF/THEN chain and is a well-known BASIC optimisation technique.

Key Handler Subroutines

Key CodeTarget LineFunction
112 (cursor left)4360Move cursor left one character
113 (cursor right)4390Move cursor right one character
114 (cursor down)4420Move cursor down one row
115 (cursor up)4450Move cursor up one row
116 (EXTEND)8800INPUT a string into X$
119 (clear)4538Reset X and X$
216 (SHIFT+Q)Toggle insert/overwrite mode via Z
226 (SHIFT+S)730SAVE canvas to named file
227 (SHIFT+A)STOP (exit program)

Keypress Wait Idiom

Lines 8900–8902 implement the standard efficient keypress wait:

PAUSE 40000 / POKE 16437,255 / LET X=CODE INKEY$

The POKE 16437,255 resets the FRAMES system variable so the PAUSE does not expire prematurely on repeated calls. This yields a responsive input loop without busy-waiting.

Mode Flag Z

Z tracks the editor’s insert/cursor mode. Key 216 (SHIFT+Q) toggles it: first press sets Z=1 (line 240), second press sets Z=2 (line 230), and line 550 resets it to Z=1 after each frame. When Z=1, the current X$ is displayed at the cursor position (line 540) without being committed to Z$; when Z<>1 and X$>"", X$ is written into Z$ (line 490).

Direct Memory Access

Several routines use direct POKEs to system variable addresses:

  • POKE 16529,X — sets the current output stream or print channel character
  • POKE 16563,X and POKE 16583,X — configure character codes for the MIX PRINT and PRINT routines respectively
  • POKE 16597,B — stores the file name character for the file-name routine
  • POKE 16614,CODE X$(J) — clears references by character code in the REFS routine

The RAMTOP check at line 7580 verifies PEEK 16388 + 256*PEEK 16389 = 32000 before reading or writing the canvas to/from raw memory at address 32000. If the check fails, the program halts with a message (line 7590–7595).

Scroll and Mirror Functions

Lines 7690–7719 implement four-directional scrolling by slicing and concatenating Z$:

  • Scroll up (A=68): Z$(33 TO)+Z$(1 TO 32)
  • Scroll down (A=132): Z$(673 TO)+Z$(1 TO 672)
  • Scroll left (A=99): Z$(2 TO)+Z$(1)
  • Scroll right (A=101): Z$(704)+Z$(1 TO 703)

Lines 7720–7739 implement a horizontal mirror of the canvas. The routine reverses character order within each row (stepping J from 32 to 1) and uses a lookup string X$ to translate asymmetric block graphics to their mirrored equivalents, ensuring that graphical characters remain visually correct after reflection.

Inverse-Video Toggle

Lines 7510–7539 invert every character in Z$ by toggling bit 7 of its character code: characters below 128 gain 128, characters above 127 lose 128 (with a special case for code 192, mapped to 267−128=139 to avoid an out-of-range CHR$). After the pass, the routine resets X to 119.

Find and Replace

Lines 7630–7649 implement a simple single-character find-and-replace across the entire canvas: the user inputs the graphic to be replaced (X$) and the replacement (Y$), then a FOR loop substitutes every matching cell in Z$.

Notable Anomalies

  • Line 7529 uses GOTO 7536 to skip the second branch of the inversion loop, but line 7525 contains NEXT J and line 7535 also contains NEXT J: the loop at 7514 has two NEXT J statements on different branches, which means the FOR loop at 7512 is only iterated correctly on the first pass through the non-inverse branch; control then falls through or jumps to line 7536. This is a structural oddity that may cause premature loop termination in the inverse branch.
  • The subroutine at line 4480 is a bare GOTO 8700, delegating entirely to the graphics-input handler without any wrapping logic.
  • Line 7526 returns immediately if Y$="" after the co-ordinate input, but the co-ordinate encoding at line 4528 assumes exactly two characters in Y$ without bounds checking.

Content

Appears On

Related Products

Draw complex images and save them on tape or put them in your own program.
Image processor. No more tedious number punching to “draw” on the screen. Features: transferable images, image mixer, image reverser, up...

Related Articles

Related Content

Image Gallery

Source Code

   1 GOTO 100
   2 IF A$="" THEN LET X=0
   3 RETURN 
   4 LET Z$(J)=D$(J)
   5 RETURN 
   6 LET Z$=B$
   7 RETURN 
   8 LET A$=Z$
   9 RETURN 
  10 LET W$=""
  11 RETURN 
 100 DIM Z$(704)
 110 LET A=1
 120 LET X$=""
 130 LET Z=0
 200 GOSUB 8900
 210 GOSUB X*30+1000
 220 IF X=227 THEN STOP 
 230 IF X=216 AND Z=1 THEN LET Z=2
 240 IF X=216 AND Z=0 THEN LET Z=1
 250 IF X=226 THEN GOTO 730
 490 IF Z<>1 AND X$>"" THEN LET Z$(A TO A+LEN X$-1)=X$
 500 CLS 
 510 PRINT Z$
 520 LET B=INT ((A-1)/32)
 530 IF X<>119 THEN PRINT AT 21,0;CHR$ (B+28);",";CHR$ (A-B*32+27);" "
 540 IF Z=1 THEN PRINT AT B,A-B*32-1;X$
 550 IF Z=2 THEN LET Z=1
 590 GOTO 200
 730 PRINT AT 21,0;"INPUT PROGRAM NAME "
 740 INPUT X$
 750 SAVE X$
 760 GOSUB 4538
 770 GOTO 500
 2890 LET X$=CHR$ X
 2899 RETURN 
 4360 GOSUB 4470
 4370 IF A>32 THEN LET A=A-32
 4379 RETURN 
 4390 GOSUB 4470
 4400 IF A+L<674 THEN LET A=A+32
 4409 RETURN 
 4420 GOSUB 4470
 4430 IF A>L THEN LET A=A-L
 4439 RETURN 
 4450 GOSUB 4470
 4460 IF A<706-2*L THEN LET A=A+L
 4469 RETURN 
 4470 LET L=LEN X$
 4475 IF L=0 OR Z=1 THEN LET L=1
 4479 RETURN 
 4480 GOTO 8700
 4510 LET Y$="0123456789ABCDEFGHIJKLMNOPQRSTUV"
 4512 PRINT AT 0,0;Y$;AT 21,0;Y$
 4514 FOR J=1 TO 21
 4516 LET Y$=CHR$ (J+28)
 4518 PRINT AT J,0;Y$;AT J,31;Y$
 4520 NEXT J
 4522 PRINT AT 21,0;"INPUT CO-ORDS "
 4524 INPUT Y$
 4526 IF Y$="" THEN RETURN 
 4528 LET A=(CODE Y$-28)*32+CODE Y$(2)-27
 4529 RETURN 
 4538 LET X=119
 4540 LET X$=""
 4599 RETURN 
 4630 IF Z=1 THEN LET Z=0
 7480 RETURN 
 7510 LET Y$=""
 7512 FOR J=1 TO 704
 7514 LET X=CODE Z$(J)
 7516 IF X<128 THEN GOTO 7520
 7518 IF X>127 THEN GOTO 7530
 7520 LET Z$(J)=CHR$ (X+128)
 7525 NEXT J
 7529 GOTO 7536
 7530 IF X=192 THEN LET X=267
 7532 LET Z$(J)=CHR$ (X-128)
 7535 NEXT J
 7536 LET X=119
 7539 RETURN 
 7540 PRINT AT 21,0;"MIX PRINT "
 7542 GOSUB 8900
 7544 IF X<38 OR X>60 THEN RETURN 
 7546 POKE 16529,X
 7548 LET B=X
 7550 GOSUB 2
 7552 IF X=0 THEN GOTO 7565
 7554 POKE 16563,X
 7556 FOR J=1 TO 704
 7558 IF Z$(J)=" " THEN GOSUB 4
 7560 NEXT J
 7562 GOTO 4538
 7565 PRINT AT 21,0;CHR$ B;"$ NOT ALLOCATED "
 7567 GOSUB 8900
 7568 LET X=0
 7569 RETURN 
 7570 GOSUB 7580
 7572 FOR J=1 TO 704
 7574 LET Z$(J)=CHR$ PEEK (32000+J)
 7576 NEXT J
 7579 RETURN 
 7580 IF PEEK 16388+256*PEEK 16389<>32000 THEN GOTO 7590
 7589 RETURN 
 7590 PRINT AT 21,0;"RAMTOP <> 32000 "
 7595 STOP 
 7600 GOSUB 7580
 7602 FOR J=1 TO 704
 7604 POKE 32000+J,CODE Z$(J)
 7606 NEXT J
 7609 RETURN 
 7630 PRINT AT 21,0;"INPUT GRAPHIC TO BE REPLACED "
 7632 INPUT X$
 7634 CLS 
 7636 PRINT Z$
 7638 PRINT AT 21,0;"INPUT NEW GRAPHIC "
 7640 INPUT Y$
 7642 FOR J=1 TO 704
 7644 IF Z$(J)=X$ THEN LET Z$(J)=Y$
 7646 NEXT J
 7649 GOTO 4538
 7660 PRINT AT 21,0;"PRINT "
 7662 GOSUB 8900
 7664 IF X<38 OR X>60 THEN RETURN 
 7666 POKE 16529,X
 7668 LET B=X
 7670 GOSUB 2
 7672 IF X=0 THEN GOTO 7565
 7674 POKE 16583,X
 7676 LET X=119
 7679 GOTO 6
 7690 LET B=A
 7691 PRINT AT 21,0;"INPUT DIRECTION "
 7692 LET X$=""
 7694 GOSUB 8900
 7696 IF X<112 OR X>115 THEN GOTO 8910
 7700 LET A=100
 7702 LET L=1
 7704 GOSUB X*30+1000
 7706 IF A=68 THEN LET Z$=Z$(33 TO )+Z$(1 TO 32)
 7708 IF A=132 THEN LET Z$=Z$(673 TO )+Z$(1 TO 672)
 7710 IF A=99 THEN LET Z$=Z$(2 TO )+Z$(1)
 7712 IF A=101 THEN LET Z$=Z$(704)+Z$(1 TO 703)
 7713 CLS 
 7714 PRINT Z$
 7719 GOTO 7691
 7720 LET X$="'  ' .. :  :.::.:'':.''.##@@ '' .  . :: :..:'::''..'@@##"
 7721 LET Y$=""
 7722 FOR B=0 TO 21
 7723 FOR J=32 TO 1 STEP -1
 7724 LET Y$=Y$+Z$(32*B+J)
 7725 LET X=CODE Y$(LEN Y$)
 7726 IF X>0 AND X<9 AND X<>3 OR X>128 AND X<137 AND X<>131 THEN GOSUB 7740
 7727 NEXT J
 7728 NEXT B
 7729 LET Z$=Y$
 7730 LET Y$=""
 7731 LET X$=""
 7732 LET X=119
 7739 RETURN 
 7740 FOR K=15 TO 28
 7741 IF Y$(LEN Y$)=X$(K) THEN GOTO 7745
 7742 NEXT K
 7744 RETURN 
 7745 LET Y$(LEN Y$)=X$(K-14)
 7749 RETURN 
 7750 PRINT AT 21,0;"INPUT FILE NAME "
 7752 GOSUB 8900
 7754 IF X<38 OR X>60 THEN RETURN 
 7756 POKE 16529,X
 7758 LET B=X
 7760 GOSUB 2
 7762 IF X=0 THEN GOTO 7770
 7764 PRINT AT 21,0;"WARNING: ";CHR$ X;"$ IN USE "
 7766 GOSUB 8900
 7768 IF X<>B THEN RETURN 
 7770 POKE 16597,B
 7772 LET X$=""
 7774 LET X=119
 7779 GOTO 8
 7810 RETURN 
 7840 DIM Z$(704)
 7849 GOTO 4540
 7870 PRINT AT 21,0;"REFS TO BE CLEARED (OR ""ALL"")"
 7872 INPUT X$
 7874 IF X$="ALL" THEN LET X$="ABCDEFGHIJKLMNOPQRSTUVW"
 7876 FOR J=1 TO LEN X$
 7878 POKE 16614,CODE X$(J)
 7880 GOSUB 10
 7882 NEXT J
 7889 GOTO 4540
 8700 GOSUB 8900
 8710 IF X=121 THEN RETURN 
 8720 IF X=116 THEN GOTO 8800
 8730 IF X<64 THEN GOTO 8790
 8740 LET X$="'  ' .. : ..'' :% .::.:'':.''.##~~,,!!;;@@"+CHR$ 117+" AND THEN TO "+CHR$ 114+CHR$ 113+CHR$ 112+CHR$ 115+CHR$ 119+""" OR STEP <=<>>= STOP LPRINT SLOW FAST LLIST **"
 8750 FOR J=22 TO 42
 8760 IF X=CODE X$(J) THEN GOTO 8780
 8770 NEXT J
 8779 GOTO 4540
 8780 LET X$=X$(J-21)
 8785 LET X=0
 8789 RETURN 
 8790 LET X$=CHR$ (X+128)
 8799 RETURN 
 8800 INPUT X$
 8809 RETURN 
 8900 PAUSE 40000
 8901 POKE 16437,255
 8902 LET X=CODE INKEY$
 8909 RETURN 
 8910 LET A=B
 8919 RETURN 
 9000 REM COPYRIGHT N.GODWIN 1982

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

People

No people associated with this content.

Scroll to Top