WIDJUP Mandelbrot Plotter

Developer(s): William J. Pedersen
Date: 198x
Type: Program
Platform(s): TS 2068
Tags: Graphics

The WIDJUP Mandelbrot Plotter turns an Epson-class dot-matrix printer into a plotter for the Mandelbrot set. You choose 64 × 44-cell frames (GO TO 3000) or 144 × 144-cell frames (GO TO 5000), then enter the left edge, the bottom and top limits of the region and the number of frames per strip, while the program marks the area on a small map of the set. It then computes each frame cell by cell, shows it on screen in shades built from user-defined characters, and prints it through its own printer module, so the strips can be pasted together into a large poster.

It comes from a Larken disk of William J. Pedersen’s WIDJUP Company software. The August MHTSUG meeting report describes Pedersen’s WIDJUP package, which “will turn your printer into a high resolution plotter”, with sample Mandelbrot printouts. This is a different program from Pedersen’s 1985 character-cell Mandelbrot Set.

Program Analysis

Setup and loading

SETUP.Bw runs first. It lists the current channel assignments, then builds new ones: a LLIST #5 / LPRINT #5 channel for formatted printing, assembled from DATA lines with mnemonic variables (JR, CALL, RET and so on, set to opcode values), and a 512-byte buffer that moves the start of BASIC to 27253. That leaves a 256-byte area at 26995 for the printer module. Mandel.Bw then loads the 137-byte Mandelbrot routine at 64512 and the 242-byte printer module from the string array PmodE.A$.

Tables and the module

At line 6007 the program builds a table of 17 grey-level patterns as UDG-style bytes at 60672, and a 120-entry string K$ mapping iteration counts to those characters through the thresholds in G(). Line 7770 copies the module from U$ to 26995, initialises the printer interface and patches the printer channel to point at it.

Plotting

For each cell the program sets the starting point in A and B, pokes the low byte of the UDG pointer (23675) to select the pattern set for that half-cell and calls USR 64512, which returns the iteration count. Two cells share each character position, so the screen frame is built in half-character steps; when a frame is complete, GO SUB 451 to 453 pass the dump parameters in DATA lines to the module.

Notable Techniques

  • Machine code for the print channel is written as DATA with named opcodes, read through BASIC variables, so the listing stays readable.
  • Moving PROG by creating a channel with a 512-byte buffer makes room for a resident module below BASIC.
  • The inner Mandelbrot loop is a 137-byte routine; BASIC only steps through the cells and draws.

Potential Issues

  • Everything is printed: without a printer on the chosen interface the program waits at the first LPRINT.
  • The printer module on the tape is the one saved on the original disk; for another interface, build a new one with the Printer Interface Setup tape.

This copy came from a Larken disk and was converted to load from tape. The LKDOS disk prefixes and the loads of the disk’s menu shell were removed, the program loads its code and printer module from tape, and the printer-module array, which had a stray disk header at the start, was repaired. The download also holds a second tape, the Printer Interface Setup (INTFC.BE), which builds a printer module for Tasman A or B, AERCO/Oliger, A&J or a general Z80 PIO interface. Both were tested in ZEsarUX as far as the channel screen, the menu and the parameter screen.

Related Articles

Last month’s meeting started at 2 PM as scheduled. The monthly newsletters received were read and reviewed.

Related Content

Image Gallery

Source Code

    1 CLS : PRINT ''''"   MANDELBROT SET"''" 3000  64*44 gixel frames"'" 5000  144*144 gixel frames"''" Use GO TO your choice." 
    2 STOP 
  449 FOR n=1 TO 11: READ i$: POKE (Ld0+CODE o$(n)),VAL i$: NEXT n
  450 RANDOMIZE USR (Ld0+CODE o$(12)): RETURN 
  451 RESTORE 501: GO TO 449: REM Dump
  452 RESTORE 502: GO TO 449: REM Zoom Dump
  453 RESTORE 503: GO SUB 449: GO SUB 449: GO TO 449: REM Wide Strip @ 0,0
  500 STOP 
  501 DATA "0","0","8","22","80","32","2","24","5","80","1"
  502 DATA "0","0","68","44","40","32","2","24","5","40","2"
  503 DATA "0","0","8","1","0","72","2","1","5","64","2"
  504 DATA "0","0","8","1","0","72","2","1","5","64","2"
  505 DATA "0","0","8","1","0","72","2","22","5","64","2"
  551 RESTORE 501: GO TO 448
  552 RESTORE 502: GO TO 448
  553 RESTORE 503: GO TO 448
 3000 CLS : PRINT '" 1.25";AT 8,0;" 0.00";AT 15,0;"-1.25  MANDELBROT SET";AT 17,4;"-2    -1     0  0.5"
 3001 PLOT 47,45: DRAW 127,0: DRAW 0,127: DRAW -127,0: DRAW 0,-127
 3002 OVER 0: PRINT '" This program prints frames of  the Mandelbrot set which can be assembled into a larger montage."
 3003 PAUSE 240: PRINT AT 19,0;" Each frame of the array is 64  cells wide by 44 cells high.",,,
 3004 PAUSE 240: PRINT AT 19,0;" As each column is completed, a new column will start until the entire [K x K] is completed.",
 3005 PAUSE 240: PRINT AT 19,0;" Five frames per strip will give1100 cell vertical resolution.     SELECT YOUR PARAMETERS.",
 3006 INPUT "LEFT GRID: ";XL: INPUT "BOTTOM GRID: ";YB: PLOT OVER 1; FLASH 1;XL*50+148,YB*50+108
 3007 INPUT "TOP LIMIT: ";YT: LET WW=YT-YB: LET HT=WW*50: DRAW OVER 1; FLASH 1;0,HT: IF WW<.05 THEN CIRCLE XL*50+148,YB*50+108,15
 3008 INPUT "FRAMES PER STRIP:";K: LET W=64/44*HT/K: DRAW OVER 1; FLASH 1;W,0: DRAW OVER 1; FLASH 1;0,-HT: DRAW OVER 1; FLASH 1;-W,0
 3009 PAUSE 240: LET GRID=WW/K/44: LPRINT "   Top limit=";YT;CHR$ 10'"   Left margin=";XL;"  Right limit=";XL+32/22*(YT-YB);CHR$ 10'"   Bottom margin=";YB;CHR$ 10'"   Frames per banner=";K;"  Resolution=";GRID;CHR$ 10'CHR$ 10
 3010 FOR S=1 TO K: FOR J=0 TO K-1: CLS : LET YY=YB+(K-1-J)*WW/K: OVER 1
 3011 FOR V=1 TO 44: LET vv=4 AND (V-2*INT (V/2)): LET B=YT-GRID*(V+44*J)
 3012 LET A=XL: FOR H=1 TO 64: LET hh=136-(136 AND (H-2*INT (H/2))): POKE 23675,vv+hh
 3013 LET N=USR 64512: LET A=XL+GRID*H
 3015 LET Wa=INT (V/2-.5): LET Wb=INT (H/2-.5)
 3016 PRINT AT Wa,Wb;K$(N+1)
 3017 NEXT H: NEXT V: OVER 0: LPRINT ("l-" AND neg);
 3018 GO SUB 451: NEXT J: LPRINT ": .:: .:";
 3019 LET XL=XL+64*GRID: NEXT S: STOP 
 5000 CLS : PRINT '" 1.25";AT 8,0;" 0.00";AT 15,0;"-1.25  MANDELBROT SET";AT 17,4;"-2    -1     0  0.5"
 5001 PLOT 47,45: DRAW 127,0: DRAW 0,127: DRAW -127,0: DRAW 0,-127
 5002 OVER 0: PRINT '" This program prints frames of  the Mandelbrot set which can be assembled into a larger montage."
 5003 PAUSE 240: PRINT AT 19,0;" Each frame of the array is 144 cells wide by 144 cells  high.",,,
 5004 PAUSE 240: PRINT AT 19,0;" As each column is completed, a new column will start until a   square array is completed.",
 5005 PAUSE 240: PRINT AT 19,0,,"   SELECT YOUR PARAMETERS.",,,
 5007 INPUT "LEFT GRID: ";XL
 5008 INPUT "BOTTOM GRID: ";YB: PLOT OVER 1; FLASH 1;XL*50+148,YB*50+108
 5009 INPUT "TOP LIMIT: ";YT: LET WW=YT-YB: LET HT=WW*50: DRAW OVER 1; FLASH 1;0,HT: IF WW<.05 THEN CIRCLE XL*50+148,YB*50+108,15
 5010 INPUT "FRAMES PER STRIP:";K: LET W=HT/K: DRAW OVER 1; FLASH 1;W,0: DRAW OVER 1; FLASH 1;0,-HT: DRAW OVER 1; FLASH 1;-W,0
 5011 PAUSE 240: LET GRID=WW/K/200: LPRINT "   Top limit=";YT;CHR$ 10'"   Left margin=";XL;"  Right limit=";XL+YT-YB;CHR$ 10'"   Bottom margin=";YB;CHR$ 10'"   Frames per banner=";K;"  Resolution=";GRID;CHR$ 10'CHR$ 10
 5012 FOR S=1 TO K: FOR J=0 TO K-1: CLS 
 5013 LET YY=YB+(K-1-J)*WW/K: OVER 1
 5014 FOR V=1 TO 144: LET vv=4 AND (V-2*INT (V/2)): LET B=YT-GRID*(V+200*J)
 5015 LET A=XL: FOR H=1 TO 144: LET hh=136-(136 AND (H-2*INT (H/2))): POKE 23675,vv+hh
 5016 LET N=USR 64512: LET A=XL+GRID*H
 5017 LET Wa=INT ((H-1)/64): LET Wb=INT (H/2-.5)-32*Wa
 5018 PRINT AT Wa,Wb;K$(N+1)
 5019 NEXT H
 5020 IF NOT V-2*INT (V/2) THEN GO SUB 453: CLS 
 5021 NEXT V: OVER 0: NEXT J
 5022 LPRINT ''
 5023 LET XL=XL+144*GRID: NEXT S: STOP 
 6000 REM "TAPE SAVE INSTRUCTIONS"
 6001 SAVE "Mandel#" LINE 6004: SAVE "Mandy/L"CODE 64512,137
 6002 SAVE "U$" DATA U$()
 6003 STOP : GO TO 6000
 6004 CLEAR 61439: LOAD ""CODE 
 6005 LET A=0: LET B=A: LET X=A: LET Y=A: LET AA=A: LET Z=A: LET N=A: LET V=A: LET H=A
 6006 LOAD "" DATA U$()
 6007 RESTORE 6050
 6008 LET b=60672
 6009 FOR n=b TO b+3: POKE n,0: NEXT n: LET b=b+4
 6010 FOR u=1 TO 17
 6011 FOR n=b TO b+3: READ a: LET a=16*a: POKE n,a: NEXT n
 6012 FOR n=b+4 TO b+7: POKE n,0: NEXT n
 6013 LET b=b+8: NEXT u: RESTORE 6050
 6014 FOR u=1 TO 17
 6015 FOR n=b TO b+3: READ a: POKE n,a: NEXT n
 6016 FOR n=b+4 TO b+7: POKE n,0: NEXT n
 6017 LET b=b+8: NEXT u
 6018 POKE 64010,0: POKE 64011,0: POKE 64012,4: POKE 64013,0: POKE 64014,0: POKE 23676,237
 6019 RESTORE 6060: DIM G(17): FOR n=1 TO 17: READ a: LET G(n)=a: NEXT n
 6020 CLS : FOR n=1 TO 17: PRINT "G(";n;") ";G(n): NEXT n: PAUSE 180
 6021 LET J=17: LET K=160: DIM K$(120): FOR n=1 TO 120: LET K$(n)=CHR$ K: IF G(J)<n THEN LET J=J-1: LET K=K-1
 6022 NEXT n: CLS : FOR n=1 TO 120: PRINT K$(n);" ";: NEXT n: PAUSE 180
 6023 LET Save=6000: LET Margin=0: LET Neg=0: GO SUB 7770
 6040 GO TO 1
 6050 DATA 15,15,13,15,7,15,13,15,7,15,5,15,5,15,5,15,5,14,5,15,5,14,5,11,5,14,5,10,5,10,5,10
 6051 DATA 10,5,8,5,2,5,8,5,0,5,8,5,0,5,0,5,0,4,0,5,0,4,0,1,0,4,0,0,0,0,0,0,15,15,15,15
 6060 DATA 119,118,117,116,115,110,105,100,95,90,80,70,60,50,30,15,0
 6061 REM DATA 119,95,85,80,75,70,65,60,55,50,45,40,34,27,19,10,0
 7770 LET Ld0=26995: GO SUB 7772: FOR j=1 TO 242: POKE Ld0+j-1,CODE U$(j): NEXT j: RANDOMIZE USR (Ld0+49): LET Wa=PEEK 23631+256*PEEK 23632: LET Wc=INT (Ld0/256): POKE Wa+15,Ld0-256*Wc: POKE Wa+16,Wc: RETURN 
 7772 RESTORE 7773: DIM o$(13): FOR n=1 TO 13: READ i$: LET x=VAL i$: LET o$(n)=CHR$ x: NEXT n: RETURN 
 7773 DATA "161","162","164","165","175","188","235","229","232","233","234","45","49"
 9990 CLEAR 61439: LOAD "MandyL.Cw"CODE : LOAD "PmodE.A$" DATA u$()
 9991 LET A=0: LET B=A: LET X=A: LET Y=A: LET AA=A: LET Z=A: LET N=A: LET V=A: LET H=A: CLS : PRINT AT 11,12;" WORKING "
 9992 DIM x$(242): FOR n=1 TO 242: LET x$(n)=u$(n): NEXT n
 9993 ON ERR GO TO 9994: DIM u$(0)
 9994 ON ERR RESET : DIM u$(242): FOR n=1 TO 242: LET u$(n)=x$(n): NEXT n
 9995 ON ERR GO TO 9996: DIM x$(0)
 9996 ON ERR RESET : GO TO 6007
 9998 LPRINT "lN";CHR$ 6;: LPRINT #5'"Mandel.Bw Listing": LLIST #5: STOP 
 9999 SAVE "Mandel.Bw" LINE 9990: SAVE "MandyL.Cw" CODE 64512,137: SAVE "U$.A$" DATA u$()

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