Rev 485 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
31 | halyavin | 1 | ; tinyfrac.asm |
2 | ; |
||
3 | ; teeny program displays the Mandelbrot set. |
||
4 | ; |
||
5 | ; written on Sun 03-26-1995 by Ed Beroset (Fidonet 1:3641/1.250) |
||
6 | ; |
||
7 | ; This program was based on a program by Frank Hommers, later optimized |
||
8 | ; for size by Mikko Hyvarinen and posted in Fidonet's 80XXX echo. |
||
9 | ; |
||
10 | ; This new version has many new features and was based on my own |
||
11 | ; optimization of Hyvarinen's version. Some features: |
||
12 | ; |
||
13 | ; pan using the arrow keys, one can navigate the fractal. |
||
14 | ; |
||
15 | ; Home Up PgUp |
||
16 | ; Left Right correspond to 8 obvious directions |
||
17 | ; End Dn PgDn |
||
18 | ; |
||
19 | ; zoom there are now ten levels of magnification available. If the |
||
20 | ; program is assembled with FEATURES defined, the number |
||
21 | ; corresponding to the zoom level (0-9, zero is most zoomed in) |
||
22 | ; is displayed in the upper left hand corner of the screen just |
||
23 | ; before each new fractal is drawn. The gray '+' key zooms out, |
||
24 | ; the gray '-' key zooms in. |
||
25 | ; |
||
26 | ; beep the program will beep at the completion of each fractal |
||
27 | ; drawing or if the user attempts to zoom past either limit. |
||
28 | ; |
||
29 | ; mode if the program is assembled with MODECHANGE defined, the |
||
30 | ; will change to the next video mode if the 'v' key is pressed. |
||
31 | ; This is handy because drawing fractals at high resolution can |
||
32 | ; be very timeconsuming. The user can find an interesting spot |
||
33 | ; in a low res mode and then change to a high res mode to see it |
||
34 | ; more fully rendered. |
||
35 | ; |
||
36 | ; size this whole project was started off as a size optimization |
||
37 | ; exercise, so there have been some rather ugly tradeoffs to |
||
38 | ; sacrifice speed for size. |
||
39 | ; |
||
40 | ; 8086 yes, it runs on an 8086 although only if you leave out either |
||
41 | ; the FEATURES option or the MODECHANGE option and it would be |
||
42 | ; slower and more painful than oral surgery. |
||
43 | ; |
||
44 | ; cost there IS such a thing as a free lunch! This code is hereby |
||
45 | ; released to the public domain by the author. |
||
46 | ; |
||
47 | ; |
||
48 | ; to assemble & link: |
||
49 | ; TASM /m2 tinyfrac (assemble using two pass mode if required) |
||
50 | ; TLINK /Tdc tinyfrac (link Target platform is DOS, COM file) |
||
51 | ; |
||
52 | ; |
||
53 | |||
54 | PIXWIDTH equ 511 |
||
55 | PIXHEIGHT equ 255 |
||
56 | |||
57 | ZOOMLIMIT equ 13 ; can change to up to 13 for extended zoom in |
||
58 | |||
59 | ; feel free to experiment with the following constants: |
||
60 | |||
61 | DELTA equ 200 ; the unit of pan movement in pixels |
||
485 | heavyiron | 62 | THRESHOLD equ 7 ; must be in the range of (0,255) |
31 | halyavin | 63 | STARTSCALE equ 5 ; a number from 0 to ZOOMLIMIT, inclusive |
64 | CHAR_COLOR equ 0fh ; white on black background (for PRINTZOOM feature) |
||
65 | |||
66 | |||
67 | |||
68 | ; ************************************************************ |
||
69 | ; |
||
70 | ; Menuet header |
||
71 | |||
72 | |||
73 | use32 |
||
74 | |||
75 | org 0x0 |
||
76 | |||
77 | db 'MENUET01' |
||
78 | dd 0x01 |
||
79 | dd START |
||
80 | dd I_END |
||
81 | dd 0x62000 |
||
82 | dd 0x1000 |
||
83 | dd 0,0 |
||
84 | |||
85 | include 'lang.inc' |
||
485 | heavyiron | 86 | include '..\..\..\macros.inc' |
31 | halyavin | 87 | |
88 | STARTX dd 200 |
||
89 | STARTY dd 120 |
||
90 | |||
91 | scaleaddy dd 120 |
||
92 | scaleaddx dd 200 |
||
93 | |||
94 | START: |
||
95 | |||
485 | heavyiron | 96 | red: |
31 | halyavin | 97 | call draw_window |
98 | call draw_fractal |
||
99 | |||
100 | still: |
||
101 | |||
102 | mov eax,10 |
||
485 | heavyiron | 103 | mcall |
31 | halyavin | 104 | |
485 | heavyiron | 105 | dec eax |
106 | jz red |
||
107 | dec eax |
||
108 | jz key |
||
31 | halyavin | 109 | |
485 | heavyiron | 110 | button: |
111 | mov al,17 |
||
112 | mcall |
||
113 | |||
114 | cmp ah,1 |
||
115 | jne no_close |
||
116 | or eax,-1 |
||
117 | mcall |
||
118 | no_close: |
||
119 | |||
120 | cmp ah,2 |
||
121 | jne no_bgr |
||
122 | |||
123 | |||
124 | mov eax,15 ; bgr 512 x 256 |
||
125 | mov ebx,1 |
||
126 | mov ecx,512 |
||
127 | mov edx,256 |
||
128 | mcall |
||
129 | |||
130 | mov eax,15 |
||
131 | mov ebx,5 |
||
132 | mov ecx,0x1000 |
||
133 | mov edx,0 |
||
134 | mov esi,512*3*256 |
||
135 | mcall |
||
136 | |||
137 | mov eax,15 |
||
138 | mov ebx,3 |
||
139 | mcall |
||
140 | |||
31 | halyavin | 141 | jmp still |
142 | |||
485 | heavyiron | 143 | no_bgr: |
144 | |||
145 | cmp ah,3 |
||
146 | jb no_color |
||
147 | cmp ah,5 |
||
148 | jg no_color |
||
149 | shr eax,8 |
||
150 | sub eax,3 |
||
151 | imul eax,8 |
||
152 | add eax,8 |
||
153 | not eax |
||
154 | and eax,11000b |
||
155 | mov [shlc],al |
||
156 | call draw_fractal |
||
31 | halyavin | 157 | jmp still |
158 | |||
485 | heavyiron | 159 | no_color: |
160 | |||
161 | jmp still |
||
162 | |||
163 | |||
31 | halyavin | 164 | key: |
485 | heavyiron | 165 | mov al,2 |
166 | mcall |
||
31 | halyavin | 167 | |
168 | cmp ah,'e' |
||
169 | je cycle |
||
170 | cmp ah,'r' |
||
171 | je cycle |
||
172 | jmp no_cycle |
||
173 | cycle: |
||
174 | call color_cycle |
||
175 | jmp still |
||
176 | no_cycle: |
||
177 | |||
178 | cmp ah,'q' |
||
179 | jne no_in |
||
180 | inc byte [scale] |
||
181 | mov ebx,[STARTX] |
||
182 | imul ebx,2 |
||
183 | sub ebx,[scaleaddx] |
||
184 | mov [STARTX],ebx |
||
185 | mov ebx,[STARTY] |
||
186 | imul ebx,2 |
||
187 | sub ebx,[scaleaddy] |
||
188 | mov [STARTY],ebx |
||
189 | no_in: |
||
190 | |||
191 | cmp ah,'w' |
||
192 | jne no_out |
||
193 | dec byte [scale] |
||
194 | mov ebx,[STARTX] |
||
195 | add ebx,[scaleaddx] |
||
196 | shr ebx,1 |
||
197 | mov [STARTX],ebx |
||
198 | mov ebx,[STARTY] |
||
199 | add ebx,[scaleaddy] |
||
200 | shr ebx,1 |
||
201 | mov [STARTY],ebx |
||
202 | no_out: |
||
203 | |||
204 | cmp ah,130+48 |
||
205 | jne no_up |
||
206 | sub [STARTY],100 |
||
207 | no_up: |
||
208 | |||
209 | cmp ah,129+48 |
||
210 | jne no_down |
||
211 | add [STARTY],100 |
||
212 | no_down: |
||
213 | |||
214 | cmp ah,128+48 |
||
215 | jne no_left |
||
216 | sub [STARTX],100 |
||
217 | no_left: |
||
218 | |||
219 | cmp ah,131+48 |
||
220 | jne no_right |
||
221 | add [STARTX],100 |
||
222 | no_right: |
||
223 | |||
224 | call draw_fractal |
||
225 | jmp still |
||
226 | |||
227 | color_cycle: |
||
228 | |||
229 | pusha |
||
230 | mov ecx,0x08080808 |
||
231 | mov esi,(256/8)*5 |
||
232 | cmp ah,'e' |
||
233 | je f_out |
||
234 | mov ecx,-0x08080808 |
||
235 | mov esi,(256/8)*5-1 |
||
236 | f_out: |
||
237 | |||
238 | newcycle: |
||
239 | mov edi,0x1000 |
||
240 | newpix: |
||
241 | mov eax,[edi] |
||
242 | add eax,ecx |
||
243 | mov [edi],eax |
||
244 | add edi,4 |
||
245 | cmp edi,0x1000+512*256*3 |
||
246 | jb newpix |
||
247 | call put_image |
||
248 | mov eax,5 |
||
249 | mov ebx,1 |
||
485 | heavyiron | 250 | mcall |
31 | halyavin | 251 | dec esi |
252 | jnz newcycle |
||
253 | |||
254 | mov eax,0 |
||
255 | mov edi,0x1000 |
||
256 | mov ecx,512*256*3 / 4 +50 |
||
257 | cld |
||
258 | rep stosd |
||
259 | |||
260 | popa |
||
261 | |||
262 | call draw_fractal |
||
263 | |||
264 | ret |
||
265 | |||
266 | |||
267 | |||
268 | |||
269 | |||
270 | ; ********************************************************************** |
||
271 | ; |
||
272 | ; Tinyfrac |
||
273 | ; |
||
274 | |||
275 | |||
276 | draw_fractal: |
||
277 | |||
278 | pusha |
||
279 | mov eax,4 |
||
485 | heavyiron | 280 | mov ebx,10*65536+30 |
281 | mov ecx,0x80ffffff |
||
31 | halyavin | 282 | mov edx,calc |
485 | heavyiron | 283 | mcall |
31 | halyavin | 284 | popa |
285 | pusha |
||
286 | |||
287 | movzx ebp,word [STARTX] |
||
288 | movzx edi,word [STARTY] |
||
289 | |||
290 | |||
291 | ; This routine is the fractal drawing engine. It has been |
||
292 | ; optimized for size, sacrificing speed. |
||
293 | |||
294 | mov cx, PIXHEIGHT ; height of screen in pixels |
||
295 | |||
296 | sub di,cx ; adjust our Y offset |
||
297 | @@CalcRow: |
||
298 | |||
299 | push cx |
||
300 | |||
301 | mov cx, PIXWIDTH -1 ; width of screen in pixels |
||
302 | |||
303 | sub bp,cx ; |
||
304 | @@CalcPixel: |
||
305 | push cx ; save the column counter on stack |
||
306 | xor cx, cx ; clear out color loop counter |
||
307 | xor bx, bx ; zero i coefficient |
||
308 | xor dx, dx ; zero j coefficient |
||
309 | @@CycleColors: |
||
310 | push dx ; save j value for later |
||
311 | mov ax, bx ; ax = i |
||
312 | sub ax, dx ; ax = i - j |
||
313 | add dx, bx ; dx = i + j |
||
314 | stc ; one additional shift, please |
||
315 | call Shifty ; ax = ((i+j)*(i-j)) shifted right |
||
316 | pop dx ; retrieve our saved value for j |
||
317 | add ax,bp ; account for base offset... |
||
318 | cmp ah,THRESHOLD ; Q: is i > THRESHOLD * 256? |
||
319 | xchg bx,ax ; now swap new i with old i |
||
320 | jg @@draw ; Y: draw this pixel |
||
321 | clc ; no additional shifts here, please |
||
322 | call Shifty ; now dx:ax = old i * j |
||
323 | xchg dx,ax ; |
||
324 | add dx,di ; account for base offset... |
||
325 | inc cl ; increment color |
||
326 | jnz @@CycleColors ; keep going until we're done |
||
327 | @@draw: |
||
328 | xchg ax, cx ; mov color into al |
||
329 | pop cx ; retrieve our column counter |
||
330 | pop dx ; fetch row (column already in cx) |
||
331 | push dx ; must leave a copy on the stack |
||
332 | xor bx,bx ; write to video page zero |
||
333 | |||
334 | call put_pixel |
||
335 | |||
336 | inc bp |
||
337 | loop @@CalcPixel |
||
338 | inc di |
||
339 | pop cx |
||
340 | loop @@CalcRow |
||
341 | |||
342 | call put_image |
||
343 | |||
344 | popa |
||
345 | |||
346 | ret |
||
347 | |||
348 | |||
349 | put_image: |
||
350 | |||
351 | pusha |
||
352 | |||
353 | mov eax,7 |
||
354 | mov ebx,0x1000 |
||
485 | heavyiron | 355 | mov ecx,512*65536+256 |
356 | mov edx,4*65536+21 |
||
357 | mcall |
||
31 | halyavin | 358 | |
359 | popa |
||
360 | |||
361 | ret |
||
362 | |||
363 | |||
364 | shlc db 0 |
||
365 | |||
366 | put_pixel: |
||
367 | |||
368 | pusha |
||
369 | sub edi,[STARTY] |
||
370 | sub ebp,[STARTX] |
||
371 | and edi,0xff |
||
372 | and ebp,0x1ff |
||
373 | shl edi,9 |
||
374 | mov ebx,edi ; * 3 - Y |
||
375 | add edi,ebx |
||
376 | add edi,ebx |
||
377 | mov ebx,ebp |
||
378 | add ebp,ebx |
||
379 | add ebp,ebx |
||
380 | add edi,ebp |
||
381 | mov cl,[shlc] |
||
382 | mov ebx,0xff |
||
383 | shl ebx,cl |
||
384 | add cl,3 |
||
385 | shl eax,cl |
||
386 | and eax,ebx |
||
387 | mov [0x1000+edi],eax |
||
388 | popa |
||
389 | |||
390 | ret |
||
391 | |||
392 | |||
393 | ;**************************************************************************** |
||
394 | ; |
||
395 | ; This routine multiplies AX by DX and shifts the result (in |
||
396 | ; DX:AX) to the right by scale bits (or scale+1 bits if CY is |
||
397 | ; set). The resulting value is left in AX. DX is destroyed. |
||
398 | ; |
||
399 | ;**************************************************************************** |
||
400 | |||
401 | Shifty: |
||
402 | push cx ; save middle bits (i*i - j*j) |
||
403 | db 0b1h ; code for mov cl,immed8 |
||
404 | scale db STARTSCALE |
||
405 | adc cl,0 ; adjust per CY flag |
||
406 | imul dx ; do the multiply |
||
407 | |||
408 | xchg ax,dx ; |
||
409 | shl eax,16 ; put hi part in hi 16 bits |
||
410 | xchg ax,dx |
||
411 | shr eax,cl ; |
||
412 | |||
413 | pop cx ; |
||
414 | ret ; |
||
415 | |||
416 | |||
417 | |||
418 | ; ********************************************************************** |
||
419 | ; |
||
420 | ; WINDOW DEFINITIONS AND DRAW |
||
421 | ; |
||
422 | ; ********************************************************************** |
||
423 | |||
424 | |||
425 | |||
426 | draw_window: |
||
427 | |||
428 | pusha |
||
429 | |||
430 | mov eax,12 |
||
431 | mov ebx,1 |
||
485 | heavyiron | 432 | mcall |
31 | halyavin | 433 | |
485 | heavyiron | 434 | xor eax,eax |
435 | mov ebx,50*65536+PIXWIDTH+8 |
||
436 | mov ecx,100*65536+PIXHEIGHT+25 |
||
551 | spraid | 437 | mov edx,0x14334455 |
485 | heavyiron | 438 | mov edi,title |
439 | mcall |
||
31 | halyavin | 440 | |
441 | mov eax,8 |
||
485 | heavyiron | 442 | mov ebx,290*65536+112 |
31 | halyavin | 443 | mov ecx,5*65536+12 |
444 | mov edx,2 |
||
445 | mov esi,0x808080 |
||
485 | heavyiron | 446 | mcall |
31 | halyavin | 447 | |
485 | heavyiron | 448 | mov ebx,420*65536+12 |
31 | halyavin | 449 | mov ecx,5*65536+12 |
450 | mov edx,3 |
||
451 | mov esi,0xa00000 |
||
452 | mov edi,3 |
||
485 | heavyiron | 453 | ;mov eax,8 |
31 | halyavin | 454 | newcolor: |
485 | heavyiron | 455 | mcall |
31 | halyavin | 456 | add ebx,13*65536 |
457 | shr esi,8 |
||
458 | inc edx |
||
459 | dec edi |
||
460 | jnz newcolor |
||
461 | |||
462 | mov eax,4 |
||
485 | heavyiron | 463 | mov ebx,300*65536+8 |
464 | mov ecx,0x80ffffff |
||
465 | mov edx,button_txt |
||
466 | mcall |
||
31 | halyavin | 467 | |
468 | mov eax,12 |
||
469 | mov ebx,2 |
||
485 | heavyiron | 470 | mcall |
31 | halyavin | 471 | |
472 | popa |
||
473 | ret |
||
474 | |||
475 | |||
476 | ; *************************************************************** |
||
477 | ; |
||
478 | ; DATA AREA |
||
479 | ; |
||
480 | |||
481 | |||
485 | heavyiron | 482 | title db 'Tinyfrac - MOVE: ARROWS, ZOOM Q/W, CYCLE: E/R',0 |
483 | button_txt db 'Set as wallpaper',0 |
||
31 | halyavin | 484 | |
485 | heavyiron | 485 | calc db 'CALCULATING',0 |
31 | halyavin | 486 | |
485 | heavyiron | 487 | I_END: |