MODE 8
xres=@vdu%!208
yres=@vdu%!212
minx=-2.0
maxx=2.0
xrange=maxx-minx
xstep=xrange/xres
miny=-1.25
maxy=1.25
yrange=maxy-miny
ystep=yrange/yres
REM Reserve space for the assembly routine itself, making sure it's in its own 2K block to avoid cache thrashing.
size% = 2048
DIM code% NOTEND AND 2047, code% size%-1
REM These are just dummy variables, while setting up the assembler
nr=3.5
ni=1.5
cr=0.29
ci=0.01
mag%=0
temp=0.0
col%=TRUE
fixed%=FALSE
PROCAssJulia
REM Set up a DIBsection for screen output, so we can write data to it directly
DIM BITMAPINFOHEADER{Size%, Width%, Height%, Planes{l&,h&}, BitCount{l&,h&}, \
\ Compression%, SizeImage%, XPelsPerMeter%, YPelsPerMeter%, \
\ ClrUsed%, ClrImportant%}
DIM bmi{Header{} = BITMAPINFOHEADER{}, Palette%(255)}
bmi.Header.Size% = DIM(BITMAPINFOHEADER{})
bmi.Header.Width% = @vdu%!208
bmi.Header.Height% = @vdu%!212
bmi.Header.Planes.l& = 1
bmi.Header.BitCount.l& = 8
REM We've made an 8 bit per pixel bitmap definition: define a palette to go with it
SYS "CreateDIBSection", @memhdc%, bmi{}, 0, ^bits%, 0, 0 TO hbitmap%
IF hbitmap% = 0 ERROR 100, "Couldn't create DIBSection"
SYS "SelectObject", @memhdc%, hbitmap% TO oldhbm%
SYS "DeleteObject", oldhbm%
PROCSetColour(col%)
CLS
bytesperpixel% = bmi.Header.BitCount.l& DIV 8
bytesperline% = ((bmi.Header.Width% * bytesperpixel%) + 3) AND -4
REPEAT
MOUSE x%,y%,z%
IF NOT fixed% THEN
cr=minx+x%*xstep/2
ci=miny+y%*ystep/2
PRINT TAB(0,0);cr,ci
ELSE
IF z%>0 THEN
tx%=x%
ty%=y%
REPEAT MOUSE x%,y%,z% UNTIL z%=0
minx+=(tx%-x%)*xstep/2
maxx+=(tx%-x%)*xstep/2
miny+=(ty%-y%)*ystep/2
maxy+=(ty%-y%)*ystep/2
ENDIF
ENDIF
CALL code%
SYS "InvalidateRect", @hwnd%, 0, 0
q$=INKEY$(0)
CASE q$ OF
WHEN "c","C":col%=NOT col%:PROCSetColour(col%)
WHEN "f","F": fixed%=NOT fixed%
WHEN CHR$(140):
fixed%=TRUE
minx+=xrange/4
maxx-=xrange/4
xrange=maxx-minx
xstep=xrange/xres
miny+=yrange/4
maxy-=yrange/4
yrange=maxy-miny
ystep=yrange/yres
WHEN CHR$(141):
fixed%=TRUE
minx-=xrange/4
maxx+=xrange/4
xrange=maxx-minx
xstep=xrange/xres
miny-=yrange/4
maxy+=yrange/4
yrange=maxy-miny
ystep=yrange/yres
ENDCASE
UNTIL q$="q" OR q$="Q"
QUIT
:
DEFPROCSetColour(col%)
LOCAL i%,r%,g%,b%
IF col% THEN
FOR i% = 0 TO 255
r% = (i% MOD 16)*16
g% = (i% MOD 64)*4
b% = 255-i%/2
bmi.Palette%(i%) = b% + (g% << 8) + (r% << 16)
NEXT
ELSE
FOR i% = 0 TO 255
bmi.Palette%(i%) = i% + (i% << 8) + (i% << 16)
NEXT
ENDIF
SYS "SetDIBColorTable", @memhdc%, 0, 256, ^bmi.Palette%(0)
ENDPROC
:
DEFPROCAssJulia
LOCAL opt%
FOR opt%=0 TO 2 STEP 2
P%=code%
[
OPT opt%
mov esi,[^yres]
mov edx,[^bits%]
fld tbyte [^miny]
fstp tbyte [^ni]
.yloop
mov ecx,[^xres]
fld tbyte [^minx]
fstp tbyte [^nr]
.xloop
mov eax,0
fld tbyte [^ci]
fld tbyte [^cr]
fld tbyte [^nr]
fst st3
fmul st0,st0
fstp st4 ;After this we have cr,ci,nr and nr2 in ST0-3, and 2 pushes
fld tbyte [^ni]
fst st5
fmul st0,st0
fstp st6 ;After this we have cr,ci,nr, nr2,ni and ni2 in ST0-5, and 2 pushes
.lpt
;OK now we should be able to calculate the new values of nr, ni
fld st2
fadd st0,st0
fmul st0,st5
fadd st0,st2
fstp st5 ;we should be in the same place, but with the new value of ni
fld st3
fsub st0,st6
fadd st0,st1
fstp st3 ;After this we now have cr,ci, the new nr, the old nr2, the new ni, and the old ni2 in ST0-5, and 2 pushes
fld st2
fmul st0,st0
fstp st4 ;now with new nr2, still 2 pushes
fld st4
fmul st0,st0
fst st6 ;now with new ni2, now 3 pushes
fadd st0,st4 ;gives magnitude squared
fistp dword [^mag%] ;store it as an integer, so it can be read into a standard register and compared, Back to 2 pushes
inc eax
mov ebx,[^mag%]
cmp ebx,4
ja esc
cmp eax,255
jb lpt
.esc
;Now we have the problem of popping the stack twice
fstp tbyte [^temp] ;should pop cr into temp
fstp tbyte [^temp] ;should pop ci into temp
mov byte [edx],al
add edx,[^bytesperpixel%]
fld tbyte [^nr]
fld tbyte [^xstep]
faddp st1,st0
fstp tbyte [^nr]
dec ecx
jnz near xloop
fld tbyte [^ni]
fld tbyte [^ystep]
faddp st1,st0
fstp tbyte [^ni]
dec esi
jnz near yloop
ret
]
NEXT opt%
ENDPROC
MODE 8
xres=@vdu%!208
yres=@vdu%!212
julia%=1:PROCSetfieldJ
REM Reserve space for the assembly routine itself, making sure it's in its own 2K block to avoid cache thrashing.
size% = 2048
DIM code% NOTEND AND 2047, code% size%-1
REM These are just dummy variables, while setting up the assembler
nr=3.5
ni=1.5
cr=0.29
ci=0.01
mag%=0
temp=0.0
col%=TRUE
fixed%=FALSE
PROCAssJulia
REM Set up a DIBsection for screen output, so we can write data to it directly
DIM BITMAPINFOHEADER{Size%, Width%, Height%, Planes{l&,h&}, BitCount{l&,h&}, \
\ Compression%, SizeImage%, XPelsPerMeter%, YPelsPerMeter%, \
\ ClrUsed%, ClrImportant%}
DIM bmi{Header{} = BITMAPINFOHEADER{}, Palette%(255)}
bmi.Header.Size% = DIM(BITMAPINFOHEADER{})
bmi.Header.Width% = @vdu%!208
bmi.Header.Height% = @vdu%!212
bmi.Header.Planes.l& = 1
bmi.Header.BitCount.l& = 8
REM We've made an 8 bit per pixel bitmap definition: define a palette to go with it
SYS "CreateDIBSection", @memhdc%, bmi{}, 0, ^bits%, 0, 0 TO hbitmap%
IF hbitmap% = 0 ERROR 100, "Couldn't create DIBSection"
SYS "SelectObject", @memhdc%, hbitmap% TO oldhbm%
SYS "DeleteObject", oldhbm%
PROCSetColour(col%)
CLS
OFF
bytesperpixel% = bmi.Header.BitCount.l& DIV 8
bytesperline% = ((bmi.Header.Width% * bytesperpixel%) + 3) AND -4
tcr=-5
tci=-5
REPEAT
WAIT 0
MOUSE x%,y%,z%
IF (NOT fixed%) AND julia% THEN
cr=minx+x%*xstep/2
ci=miny+y%*ystep/2
IF cr<>tcr OR ci<>tci THEN changed%=TRUE
PRINT TAB(0,0);cr,ci
ELSE
IF z%>0 THEN
tx%=x%
ty%=y%
REPEAT MOUSE x%,y%,z% UNTIL z%=0
minx+=(tx%-x%)*xstep/2
maxx+=(tx%-x%)*xstep/2
miny+=(ty%-y%)*ystep/2
maxy+=(ty%-y%)*ystep/2
changed%=TRUE
ENDIF
ENDIF
IF changed% THEN
CALL code%
changed%=FALSE
tcr=cr
tci=ci
SYS "InvalidateRect", @hwnd%, 0, 0
ENDIF
q$=INKEY$(0)
CASE q$ OF
WHEN "c","C":col%=NOT col%:PROCSetColour(col%):changed%=TRUE
WHEN "f","F": fixed%=NOT fixed%
WHEN "j","J": julia%=1:PROCSetfieldJ
WHEN "m","M": julia%=0:PROCSetfieldM
WHEN CHR$(140):
fixed%=TRUE
minx+=xrange/4
maxx-=xrange/4
xrange=maxx-minx
xstep=xrange/xres
miny+=yrange/4
maxy-=yrange/4
yrange=maxy-miny
ystep=yrange/yres
changed%=TRUE
WHEN CHR$(141):
fixed%=TRUE
minx-=xrange/4
maxx+=xrange/4
xrange=maxx-minx
xstep=xrange/xres
miny-=yrange/4
maxy+=yrange/4
yrange=maxy-miny
ystep=yrange/yres
changed%=TRUE
ENDCASE
UNTIL q$="q" OR q$="Q"
QUIT
:
DEFPROCSetColour(col%)
LOCAL i%,r%,g%,b%
IF col% THEN
FOR i% = 0 TO 255
r% = (i% MOD 16)*16
g% = (i% MOD 64)*4
b% = 255-i%/2
bmi.Palette%(i%) = b% + (g% << 8) + (r% << 16)
NEXT
ELSE
FOR i% = 0 TO 255
bmi.Palette%(i%) = i% + (i% << 8) + (i% << 16)
NEXT
ENDIF
SYS "SetDIBColorTable", @memhdc%, 0, 256, ^bmi.Palette%(0)
ENDPROC
:
DEFPROCSetfieldJ
minx=-2.0
maxx=2.0
xrange=maxx-minx
xstep=xrange/xres
miny=-1.25
maxy=1.25
yrange=maxy-miny
ystep=yrange/yres
changed%=TRUE
fixed%=FALSE
ENDPROC
:
DEFPROCSetfieldM
minx=-2.0
maxx=0.5
xrange=maxx-minx
xstep=xrange/xres
miny=-1.25
maxy=1.25
yrange=maxy-miny
ystep=yrange/yres
changed%=TRUE
fixed%=FALSE
ENDPROC
:
DEFPROCAssJulia
LOCAL opt%
FOR opt%=0 TO 2 STEP 2
P%=code%
[
OPT opt%
mov esi,[^yres]
mov edx,[^bits%]
fld tbyte [^miny]
fstp tbyte [^ni]
.yloop
mov ecx,[^xres]
fld tbyte [^minx]
fstp tbyte [^nr]
.xloop
mov eax,[^julia%]
cmp eax,0
jz mand
fld tbyte [^ci]
fld tbyte [^cr]
jmp inloop
.mand
fld tbyte [^ni]
fld tbyte [^nr]
.inloop
mov eax,0
fld tbyte [^nr]
fst st3
fmul st0,st0
fstp st4 ;After this we have cr,ci,nr and nr2 in ST0-3, and 2 pushes
fld tbyte [^ni]
fst st5
fmul st0,st0
fstp st6 ;After this we have cr,ci,nr, nr2,ni and ni2 in ST0-5, and 2 pushes
.lpt
;OK now we should be able to calculate the new values of nr, ni
fld st2
fadd st0,st0
fmul st0,st5
fadd st0,st2
fstp st5 ;we should be in the same place, but with the new value of ni
fld st3
fsub st0,st6
fadd st0,st1
fstp st3 ;After this we now have cr,ci, the new nr, the old nr2, the new ni, and the old ni2 in ST0-5, and 2 pushes
fld st2
fmul st0,st0
fstp st4 ;now with new nr2, still 2 pushes
fld st4
fmul st0,st0
fst st6 ;now with new ni2, now 3 pushes
fadd st0,st4 ;gives magnitude squared
fistp dword [^mag%] ;store it as an integer, so it can be read into a standard register and compared, Back to 2 pushes
inc eax
mov ebx,[^mag%]
cmp ebx,4
ja esc
cmp eax,255
jb lpt
.esc
;Now we have the problem of popping the stack twice
fstp tbyte [^temp] ;should pop cr into temp
fstp tbyte [^temp] ;should pop ci into temp
mov byte [edx],al
add edx,[^bytesperpixel%]
fld tbyte [^nr]
fld tbyte [^xstep]
faddp st1,st0
fstp tbyte [^nr]
dec ecx
jnz near xloop
fld tbyte [^ni]
fld tbyte [^ystep]
faddp st1,st0
fstp tbyte [^ni]
dec esi
jnz near yloop
ret
]
NEXT opt%
ENDPROC