Julia Sets is a hi-res fractal program that computes and displays Julia set images derived from user-specified points in the Mandelbrot set, using the same floating-point processor (FFP) machine code core as its companion program “Mandelbrot FFP.” The main computation loop at lines 100–200 iterates over all 192×256 pixel positions, calling a machine code routine via USR 16514 to perform the iteration count, then uses RAND USR to plot individual pixels at address 16681. A zoom utility (line 4000) allows the user to move a flashing pixel cursor around the current image to identify corners and side lengths for a follow-up run at higher magnification. The program stores the display in a 6144-byte string array P$ so the current state can be saved to tape and resumed later. Machine code entry points for functions such as hi-res clear (HR), normal mode (NML), reverse (RVS), upload/download (ULD/DLD), and copy (CPY) are assigned to named variables at lines 9190–9310, making the BASIC readable while keeping the actual addresses in ROM/RAM.
Program Analysis
Program Structure
The program is organized into several distinct functional blocks:
- Lines 0–1: REM header (contains embedded machine code in line 0) and a
GOTO 9E3bootstrap that jumps to the initialization/help section. - Lines 100–200: The main fractal rendering loop, iterating over rows (
M) and columns (N) of the 192×256 hi-res display. - Lines 4000–4450: Zoom utility — moves a cursor pixel around the screen, reads coordinates, and reports corner/side values.
- Lines 4990–4995: Completion message, redirects to menu.
- Lines 5000–5140: Main menu, offering start, save, resume, display, progress, parameters, zoom, and stop options.
- Lines 6000–6090: Display/copy sub-menu (reverse, copy, return).
- Lines 8000–8060: Save-to-tape routine with user-supplied filename.
- Lines 9000–9330: Parameter input and variable initialization.
- Lines 9480–9720: Save/splash screen, extensive help text, and re-read option.
- Lines 9860–9950: GOSUB wait-for-keypress subroutine used between help pages.
Machine Code Integration
The program makes heavy use of machine code routines accessed via RAND USR and USR. All machine code entry points are assigned to named BASIC variables at lines 9190–9310, keeping the code readable:
| Variable | Address | Function |
|---|---|---|
CLS | 16648 | Hi-res clear screen |
HR | 16634 | Switch to hi-res mode |
NML | 16639 | Switch to normal mode |
RVS | 16669 | Reverse the display |
PLT | 16681 | Plot a pixel |
YP | 16439 | Y-coordinate POKE address |
XP | 16438 | X-coordinate POKE address |
ULD | 16758 | Upload display (P$ → screen) |
DLD | 16765 | Download display (screen → P$) |
CPY | 16790 | Copy (print) screen |
UPL | 16687 | Update pixel location |
The core Julia set iteration is performed by a machine code routine at address 16514, called inline via USR 16514 within the expression at line 150. This provides nearly 3× the speed of equivalent BASIC floating-point math, as noted in the help text referencing the original algorithm. The pixel coordinates are passed by POKEing values into addresses XP (16438) and YP (16439) before calling the plot routine.
Line 9000 also calls RAND USR 16582, which appears to be a memory initialization or relocation routine called before dimensioning P$. This same call appears at line 8055 after a save, and at line 9480 before the splash screen.
Main Rendering Loop
Lines 100–200 form the fractal computation loop. M iterates from its current value to 191 (rows), and N from its current value to 255 (columns). This design allows the run to be interrupted and resumed, since M and N retain their values between menu visits. The guard at line 110 skips directly to MNU-10 (line 4990, the “ALL DONE” message) if M has already reached 192.
Line 150 is the key computation expression:
LET C=INT((L+(CB+(CA+(M*G+B+(N*G+A+USR 16514)))))/W)
The nested additions pass the current pixel’s complex-plane coordinates (real part N*G+A, imaginary part M*G+B) along with the generator constants CA and CB to the machine code routine via the floating-point stack. The result is the iteration count, which is then banded by dividing by W and tested for odd/even at line 160 to determine whether to plot the pixel.
After each row, N is reset to 0 (line 180) so subsequent rows start from the left edge. The loop at line 200 wraps back to line 100 rather than falling through NEXT M, allowing the interrupt check at line 140 to cause a clean exit to the menu.
Interrupt and Resume Mechanism
Line 140 checks INKEY$ on every pixel. If any key is held, execution jumps to MNU (5000). Because M and N are not reset, menu option 3 (line 5080, GOTO 100) resumes exactly where the run was interrupted. Similarly, after a save/reload cycle, the saved values of M and N allow a seamless continue.
Picture Storage and Save/Restore
Line 9005 dimensions P$(6144), exactly matching the 6144-byte hi-res display memory. The machine code routines ULD and DLD transfer data between this string and the screen, allowing the current image to be preserved across menu operations and saved to tape (line 8040, SAVE N$) along with all program variables.
Zoom Utility
The zoom utility (lines 4000–4450) uses machine code to display and move a flashing cursor pixel. The user navigates to the lower-left corner of the desired area and presses 1 to record A1 and B1 (real and imaginary coordinates), then moves to the upper-right and presses 2 to compute and display the side length. The flag variable B2 is used as state: -1 means no corner selected yet, 0 means corner recorded. This gives the user the new parameters needed to start a zoomed-in run without modifying the current run’s variables.
The zoom loop at line 4120 uses GOTO USR 16963 — a computed GOTO to a machine code routine that reads the cursor keys and updates the pixel position, returning a line number to branch to for each action (move, corner, side, escape).
Key BASIC Idioms
VAL "number"inGOTOandGOSUBstatements (e.g., lines 9515, 9550) — a memory optimization that stores the target as a short string rather than a floating-point number.- Named numeric variables (
MNU,PLT,HR, etc.) used as symbolic constants for machine code addresses and line numbers, improving readability. ANDused as a conditional string mask at line 5030:("3: RESUME CURRENT RUN " AND M<192)prints the option only if a run is in progress.POKE VAL "16418",NOT PIat line 9490 —NOT PIevaluates to 0, switching the display to FAST mode by poking 0 into the system variable at 16418.- Line 9695 uses
POKE VAL "16418",VAL "2"to re-enable SLOW mode.
Parameter Input and Validation
Lines 9000–9180 collect six parameters: A (real corner), B (imaginary corner), S (vertical side length), CA and CB (the generator point from the Mandelbrot set), L (iteration limit), and W (band width). After input, the user is prompted with “OK?” and if the answer is not “Y”, the program restarts with RUN (line 9180), clearing all variables and starting fresh. The grid step G=S/192 is computed at line 9090.
The two dummy FOR loops at lines 9100–9110 (FOR M=0 TO 0, FOR N=0 TO 0) initialize M and N to 0 without a visible loop body, ensuring the rendering loop starts from the top-left pixel.
Help System
Lines 9480–9720 implement a multi-page help and splash screen system. Each page ends with a call to the subroutine at line 9860, which displays a “press a key twice to continue” prompt and waits for a keypress, clears the screen, then waits for the key to be released and a second press before returning. This two-keypress debounce prevents accidental page advances. The user can opt to re-read all help screens or proceed directly to the main menu.
Content
Image Gallery
Source Code
0 REM LOAD [4]VAL ▝""▝AT ▝TAB ▝#▝CODE ▝ STOP LLIST STEP H▖ LPRINT H▖▀?▘ STEP LPRINT ▖H??AT ▘""H▖▘H▖?KN ▀N " FAST[5]?VAL SLOW: ▀JCHR$ [4][4][4][4] FASTO▘ TAN 5 LIST INKEY$ ) LIST AT ▘9 GOSUB [K]TAN E£RNDE£RNDE£RND ) RUN ▙;Y2 GOSUB #Y PRINT ▘▛▝LN [P]▝LN [>]▝LN 4▝<>5+PI#[8]▝<>5+PITAN Y2 GOSUB #<>5[?]▝TAN 5 4U6PI333#: Q "##< GOSUB [K]TAN 5 PAUSE INKEY$ ▘4 #LEN █#/ GOSUB CLEARACS VCHR$ /▖ CLEARACS V[-] GOSUB #QRNDU6PIX[(] AND [H]:##ACS UACS .ACS UACS .ACS UACS .5 4;## NEW▛W▘ ▒ACS ▝ACS )X4£ CLEARACS V#C▖ACS AT /▝ACS ▟( FOR #TAN LN ▙INKEY$ FOR GOSUB [K]TAN LN ▙INKEY$ /:E(RND)▞ ;) 4▘ /TAN GOSUB [K]#AT RND LN 7?U6PI#5 4[J]PEEK CLSLN #?ABS ▐▒<= CLS*K CLS-4▞▒# FASTSTR$ Y4[>]#- 5 PAUSE INKEY$ ;ACS #SGN LPRINT #C▘J#<= CLS3K CLS# NEW█PEEK CLSACS )( PAUSE 7+4CHR$ <= CLS3K CLS14[Y]Y▖PEEK CLS0#F? GOSUB # #GPI NEXT Y▛# ( CLEARLEN INPUT W4 CLEAR▞"")4 5 4#NPI ▌ASN PEEK RND;# GOSUB ### LIST AT LN [V]▝G4▖▘6(TAN H##LN [X]▛K POKE # GOSUB #QRND RETURN64=#X RETURN COPY4▝Y[Z] RETURN""4▘[J]MRRND▘#(TAN RETURN74▖#W/ GOTO RETURN54▛#XMQRND/ DIM RETURN84▖#W/ NEXT RETURN14▖▘ATN (TAN RETURN24▖▘K)TAN RETURN#4[C]▘#(TAN
1 GOTO 9E3 AND CODE "[H][R][-][J][U][L][I][A]█[S][E][T][S] FASTF.P. V1.4 [G][O][T][O]█[M][N][U]█[T][O]█[S][T][A][R][T][/][S][A][V][E] "
100 FAST
110 IF M>=192 THEN GOTO MNU-10
120 FOR M=M TO 191
125 POKE YP,M
130 FOR N=N TO 255
135 POKE XP,N
140 IF INKEY$ <>"" THEN GOTO MNU
150 LET C=INT ((L+(CB+(CA+(M*G+B+(N*G+A+USR 16514)))))/W)
160 IF C/2<>INT (C/2) THEN RAND USR PLT
170 NEXT N
180 LET N=0
190 NEXT M
200 GOTO 100
4000 POKE 16418,0
4020 RAND USR HR
4030 RAND USR ULD
4040 LET M1=0
4050 LET N1=0
4070 CLS
4072 PRINT AT 23,0;"[5][-][8]:MOVE [1]:CORNER [2]:SIDE [N][/][L]:ESC"
4075 LET B2=-1
4090 POKE XP,N1
4095 POKE YP,M1
4110 RAND USR PLT
4120 GOTO USR 16963
4130 RAND USR UPL
4170 GOTO 4110
4180 RAND USR DLD
4190 POKE 16418,2
4195 GOTO MNU
4200 LET M1=PEEK YP
4210 LET N1=PEEK XP
4220 RAND USR UPL
4250 GOTO 4110
4300 CLS
4310 LET A1=A+N1*G
4315 LET B1=B+M1*G
4330 PRINT AT 23,0;"A=";A1,"B=";B1
4340 LET B2=0
4350 GOTO 4110
4400 IF B2<>0 THEN GOTO 4070
4410 CLS
4420 LET B2=B+M1*G
4430 PRINT AT 23,0;"SIDE=";B2-B1
4440 IF INKEY$ ="" THEN GOTO 4440
4450 GOTO 4070
4990 CLS
4992 PRINT AT 10,0;"ALL DONE.",,,,
4995 GOTO MNU+10
5000 CLS
5010 RAND USR NML
5020 SLOW
5030 PRINT AT 0,0;" [M][A][I][N]█[M][E][N][U][:]",,,,"1: START A NEW RUN ","2: SAVE CURRENT PROGRAM STATE";TAB 0;("3: RESUME CURRENT RUN " AND M<192);TAB 0;"4: DISPLAY/COPY PICTURE","5: PROGRESS REPORT","6: PRINT PARAMETERS","7: ZOOM LOCATION","8: STOP"
5040 LET Z$=INKEY$
5050 IF Z$="" THEN GOTO 5040
5060 IF Z$="1" THEN RUN
5070 IF Z$="2" THEN GOTO 8000
5080 IF Z$="3" THEN GOTO 100
5090 IF Z$="4" THEN GOTO 6000
5100 IF Z$="5" THEN PRINT ,,"ROW: ";M,"COL: ";N,49151-256*M-N;" TO GO"
5110 IF Z$="6" THEN PRINT ,,"R-CORNER=";A;TAB 0;"I-CORNER=";B;TAB 0;"R-SIDE =";S*4/3;TAB 0;"I-SIDE =";S;TAB 0;"IT.LIMIT=";L;TAB 0;"BANDWIDTH=";W
5120 IF Z$="7" THEN GOTO 4000
5130 IF Z$="8" THEN STOP
5140 GOTO 5040
6000 CLS
6010 POKE 16418,0
6020 PRINT AT 23,0;"[R]= REVERSE, [Z]= COPY, [Y]= RETURN"
6030 POKE 16418,2
6040 RAND USR HR
6050 LET Z$=INKEY$
6060 IF Z$="R" THEN RAND USR RVS
6070 IF Z$="Z" THEN RAND USR CPY
6080 IF Z$="Y" THEN GOTO MNU
6090 GOTO 6050
8000 RAND USR ULD
8010 CLS
8020 PRINT " INPUT SAVE NAME:"
8030 INPUT N$
8040 SAVE N$
8050 RAND USR DLD
8055 RAND USR 16582
8060 GOTO MNU
9000 RAND USR 16582
9005 DIM P$(6144)
9010 CLS
9020 SLOW
9030 PRINT " INPUT CO-ORDS OF SW CORNER OF THE PROPOSED JULIA-SET PLANE:",,,"A-CORNER (REAL PART)=";
9040 INPUT A
9050 PRINT A;AT 5,0;"B-CORNER (IMAG PART)=";
9060 INPUT B
9070 PRINT B;AT 7,0;"LENGTH OF VERT SIDE =";
9080 INPUT S
9090 LET G=S/192
9092 PRINT S;AT 9,0;"CO-ORDINATES OF MANDELBROT SET ""GENERATOR"" (REAL)=";
9093 INPUT CA
9094 PRINT CA,TAB 7;"(IMAGINARY)=";
9095 INPUT CB
9100 FOR M=0 TO 0
9110 FOR N=0 TO 0
9120 PRINT CB;AT 13,0;"ITERATION LIMIT=";
9130 INPUT L
9140 PRINT L;AT 15,0;"BAND WIDTH=";
9150 INPUT W
9160 PRINT W,,,,"OK?"
9170 INPUT Y$
9180 IF Y$<>"Y" THEN RUN
9190 LET CLS=16648
9200 LET HR=16634
9210 LET NML=16639
9220 LET RVS=16669
9230 LET PLT=16681
9240 LET YP=16439
9250 LET XP=16438
9260 LET ULD=16758
9270 LET DLD=16765
9280 LET CPY=16790
9290 LET MNU= 5000
9300 LET UPL=16687
9310 RAND USR CLS
9320 CLS
9330 GOTO 100
9480 SAVE "JUL-FF[P]"
9482 RAND USR 16582
9485 CLS
9487 SLOW
9490 POKE VAL "16418",NOT PI
9492 PRINT "[J][U][L][I][A]█[S][E][T][S]█[W][I][T][H][I][N]█[M][A][N][D][E][L][B][R][O][T]█[S][E][T]",,"A HI-RES FRACTAL PROGRAM FOR THEZX81/TS1000 AND 1500 WITH STATICRAM IN THE 8-16K REGION.",,,"BY FRED NACHBAUR, HI-RES CORE BYWILF RIGTER. CONCEPT BY BENOIT BMANDELBROT, I.B.M. RESEARCH.",,,"▛▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▜▌[F][E][E][L]█[F][R][E][E]█[T][O]█[D][I][S][T][R][I][B][U][T][E][:]█[T][H][I][S]█▐▌[P][R][O][G][R][A][M]█[I][S]█[I][N]██[P][U][B][L][I][C]█[D][O][M][A][I][N][,]█▐▌[B][U][T]█[I][S]█[N][O][T]█[T][O]█[B][E]█[S][O][L][D]█[F][O][R]█[G][A][I][N]▐▙▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▟",,"PRESS BREAK, THEN GOTO 9480 TO MAKE COPIES OF ORIGINAL PG."
9495 PRINT ,,"WRITE: [S][I][L][I][C][O][N]█[M][O][U][N][T][A][I][N]█[C][O][M][P][U][T][E][R] [C][-][1][2][,]█[M][T][N][.]█[S][T][N][.]█[G][R][O][U][P]█[B][O][X] [N][E][L][S][O][N][,]█[B][C]█[V][1][L]█[5][P][1]█[C][A][N][A][D][A]FOR INFO ON MORE HI-RES PROGRAMS"
9502 RAND USR DLD
9505 SLOW
9510 POKE VAL "16418",NOT PI
9515 GOSUB VAL "9860"
9520 PRINT ">>>>>>>>>>>[J][U][L][I][A]█[S][E][T][S]<<<<<<<<<<<",,"ARE FRACTALS RELATED TO THE WELLKNOWN MANDELBROT SET. EACH POINTIN THE MANDELBROT SET GIVES RISETO A UNIQUE NEW FRACTAL BASED ONTHE SAME ESSENTIAL ALGORITHM."
9530 PRINT ,," THIS PROGRAM LETS YOU EXAMINE ENTIRE OR PARTIAL JULIA SETS; ITS A ""SEQUEL"" TO MANDEL-FFP."
9540 PRINT ,," THE COVER SCREEN DISPLAYS ONE ENTIRE SET, GENERATED BY THE POINT -.74543 + .11301(I)","""A""-CORNER=-5/3, ""B""-CORNER=-5/4LENGTH OF SIDE=2.5",,,"YOU CAN ZOOM IN ON ANY AREA NEARTHE SET (EG THE STIPPLED REGION)TO REVEAL EVER MORE DETAILS ASYOU ZOOM IN FURTHER AND FURTHER."
9550 GOSUB VAL "9860"
9560 PRINT ,,"VAR [T][H][E]█[P][A][R][A][M][E][T][E][R][S]",,,"""A"" (REAL)=COORD. OF X-AXIS","""B"" (IMAG)=COORD. OF Y-AXIS"," (LOWER LEFT CORNER)",,,"""S""=LENGTH OF VERTICAL SIDE",,,"""CA""=REAL COMP. OF GENERATOR","""CB""=IMAGINARY COMPONENT",,,"""L""=ITERATION LIMIT BEFORE PGM. ASSUMES THAT POINT IS WITHIN SET"
9570 PRINT ,,"""W""= BAND WIDTH; NO. OF COUNTS FOR EACH BAND. NORMALLY 1, BUT IF PICTURE TOO ""BUSY"", TRY 2-3"
9575 PRINT ,,"P$ - USED FOR STORAGE OF YOUR PICTURE SO IT WILL SAVE TO TAPE"
9580 GOSUB VAL "9860"
9590 PRINT TAB VAL "10";"[M][E][N][U]█[O][P][T][I][O][N][S]",,,"1: START ANEW. CLEARS PICTURE.",,,"2: SAVE PRESENT STATUS TO TAPE. USEFUL IF YOU NEED TO USE YOUR MACHINE FOR OTHER THINGS, AS THESE RUNS CAN TAKE AWHILE",,,"3: CONTINUE RUN AFTER SAVE , RE- LOAD , OR OTHER MENU OPTION",,,"4: DISPLAY/REVERSE/COPY PICTURE",,,"5: REPORT ON PROGRESS SO FAR",,,"6: PRINT PARAMETERS"
9600 PRINT ,,"7: ZOOM UTILITY; SEE NEXT PAGE",,,"8: STOPPGM. GOTO MNU TO CONT "
9610 GOSUB VAL "9860"
9620 PRINT TAB VAL "12";"[Z][O][O][M][I][N][G]","AFTER PRESSING 7 FROM MENU, MOVEFLASHING PIXEL TO DESIRED AREA (LOWER LEFT CORNER OF AREA TO BEZOOMED), USING CURSOR KEYS. NOW HIT 1 TO PRINT A/B-CORNER; NOTE THESE DOWN. MOVE PIXEL VERTICAL-LY TO UPPER RIGHT CORNER THEN PRESS 2 TO PRINT LENGTH OF SIDE.ANY KEY TO CONT OR ENTER TO GO BACK TO MENU.",,,,"NOTE: USING THIS OPTION DOES NOTMESS UP YOUR CURRENT RUN. TRY ITWITH THE SAMPLE SCREEN SUPPLIED."
9630 PRINT ,,"YOU CAN THENSTART A NEW RUN ANDSPECIFY THE NEW PARAMETERS TO BLOW-UP ANY REGION. YOU CAN KEEPENLARGING (WITHIN LIMITS OF ZX CALCULATOR) AND ALWAYS FIND MOREDETAIL."
9640 GOSUB VAL "9860"
9650 PRINT "ONCE YOU HAVE THE HANG OF IT YOUCAN DELETE THESE HELP SCREENS (LINES 9480-9950) TO REDUCE TIMETO LOAD / SAVE YOUR RUNS."
9670 PRINT ,,"NOTE: THE EVALUATION LOOP USES THE ROM▘S FLOATING-POINT CALCU- LATOR DIRECTLY, FOR AN ALMOST 3XSPEED INCREASE OVER BASIC. SEE SYNCWARE NEWS VOL. 3 NO. 5 FOR THE ORIGINAL ALGORITHM"
9680 PRINT ,,"TS2040 USE IS SUPPORTED, OTHER PRINTOUTS POSSIBLE USING PETER MCMULLIN▘S ""BIG-PRINTER"" SINC- ARTIST UPGRADE. JUST MOVE DATA FROM 8192-14335 INTO A$.",,,"DURING A RUN, HOLD ANY KEY TOGET TO MENU (CHECK PROGRESS,ETC)"
9690 PRINT ,," DO YOU WANT TO RE-READ THESE HELP SCREENS? (Y/N)"
9692 SLOW
9695 POKE VAL "16418",VAL "2"
9700 IF INKEY$ ="Y" THEN GOTO VAL "9485"
9710 IF INKEY$ ="N" THEN GOTO MNU
9720 GOTO 9700
9860 REM [W][A][I][T]
9870 PRINT AT VAL "23",VAL "0";"*[P][R][E][S][S]█[A]█[K][E][Y]█[T][W][I][C][E]█[T][O]█[C][O][N][T][I][N][U][E]**"
9880 SLOW
9890 IF INKEY$ ="" THEN GOTO 9890
9900 RAND USR HR
9910 CLS
9920 IF INKEY$ <>"" THEN GOTO 9920
9930 IF INKEY$ ="" THEN GOTO 9930
9940 FAST
9950 RETURN
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.