Rev 109 | Go to most recent revision | Details | 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 |
||
62 | THRESHOLD equ 7 ; must be in the range of (0,255) |
||
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' |
||
86 | include 'macros.inc' |
||
87 | |||
88 | STARTX dd 200 |
||
89 | STARTY dd 120 |
||
90 | |||
91 | scaleaddy dd 120 |
||
92 | scaleaddx dd 200 |
||
93 | |||
94 | START: |
||
95 | |||
96 | call draw_window |
||
97 | |||
98 | call draw_fractal |
||
99 | |||
100 | still: |
||
101 | |||
102 | mov eax,10 |
||
103 | int 0x40 |
||
104 | |||
105 | cmp eax,1 |
||
106 | je red |
||
107 | cmp eax,2 |
||
108 | je key |
||
109 | cmp eax,3 |
||
110 | je button |
||
111 | |||
112 | jmp still |
||
113 | |||
114 | red: |
||
115 | call draw_window |
||
116 | call put_image |
||
117 | jmp still |
||
118 | |||
119 | key: |
||
120 | mov eax,2 |
||
121 | int 0x40 |
||
122 | |||
123 | cmp ah,'e' |
||
124 | je cycle |
||
125 | cmp ah,'r' |
||
126 | je cycle |
||
127 | jmp no_cycle |
||
128 | cycle: |
||
129 | call color_cycle |
||
130 | jmp still |
||
131 | no_cycle: |
||
132 | |||
133 | cmp ah,'q' |
||
134 | jne no_in |
||
135 | inc byte [scale] |
||
136 | mov ebx,[STARTX] |
||
137 | imul ebx,2 |
||
138 | sub ebx,[scaleaddx] |
||
139 | mov [STARTX],ebx |
||
140 | mov ebx,[STARTY] |
||
141 | imul ebx,2 |
||
142 | sub ebx,[scaleaddy] |
||
143 | mov [STARTY],ebx |
||
144 | no_in: |
||
145 | |||
146 | cmp ah,'w' |
||
147 | jne no_out |
||
148 | dec byte [scale] |
||
149 | mov ebx,[STARTX] |
||
150 | add ebx,[scaleaddx] |
||
151 | shr ebx,1 |
||
152 | mov [STARTX],ebx |
||
153 | mov ebx,[STARTY] |
||
154 | add ebx,[scaleaddy] |
||
155 | shr ebx,1 |
||
156 | mov [STARTY],ebx |
||
157 | no_out: |
||
158 | |||
159 | cmp ah,130+48 |
||
160 | jne no_up |
||
161 | sub [STARTY],100 |
||
162 | no_up: |
||
163 | |||
164 | cmp ah,129+48 |
||
165 | jne no_down |
||
166 | add [STARTY],100 |
||
167 | no_down: |
||
168 | |||
169 | cmp ah,128+48 |
||
170 | jne no_left |
||
171 | sub [STARTX],100 |
||
172 | no_left: |
||
173 | |||
174 | cmp ah,131+48 |
||
175 | jne no_right |
||
176 | add [STARTX],100 |
||
177 | no_right: |
||
178 | |||
179 | call draw_fractal |
||
180 | jmp still |
||
181 | |||
182 | button: |
||
183 | mov eax,17 |
||
184 | int 0x40 |
||
185 | |||
186 | cmp ah,1 |
||
187 | jne no_close |
||
188 | mov eax,-1 |
||
189 | int 0x40 |
||
190 | no_close: |
||
191 | |||
192 | cmp ah,2 |
||
193 | jne no_bgr |
||
194 | |||
195 | mov eax,15 ; bgr 512 x 256 |
||
196 | mov ebx,1 |
||
197 | mov ecx,512 |
||
198 | mov edx,256 |
||
199 | int 0x40 |
||
200 | |||
201 | mov eax,15 |
||
202 | mov ebx,5 |
||
203 | mov ecx,0x1000 |
||
204 | mov edx,0 |
||
205 | mov esi,512*3*256 |
||
206 | int 0x40 |
||
207 | |||
208 | mov eax,15 |
||
209 | mov ebx,3 |
||
210 | int 0x40 |
||
211 | |||
212 | jmp still |
||
213 | |||
214 | no_bgr: |
||
215 | |||
216 | cmp ah,3 |
||
217 | jb no_color |
||
218 | cmp ah,5 |
||
219 | jg no_color |
||
220 | shr eax,8 |
||
221 | sub eax,3 |
||
222 | imul eax,8 |
||
223 | add eax,8 |
||
224 | not eax |
||
225 | and eax,11000b |
||
226 | ; sub eax,8 |
||
227 | mov [shlc],al |
||
228 | call draw_fractal |
||
229 | jmp still |
||
230 | |||
231 | no_color: |
||
232 | |||
233 | |||
234 | jmp still |
||
235 | |||
236 | |||
237 | color_cycle: |
||
238 | |||
239 | pusha |
||
240 | mov ecx,0x08080808 |
||
241 | mov esi,(256/8)*5 |
||
242 | cmp ah,'e' |
||
243 | je f_out |
||
244 | mov ecx,-0x08080808 |
||
245 | mov esi,(256/8)*5-1 |
||
246 | f_out: |
||
247 | |||
248 | newcycle: |
||
249 | mov edi,0x1000 |
||
250 | newpix: |
||
251 | mov eax,[edi] |
||
252 | add eax,ecx |
||
253 | mov [edi],eax |
||
254 | add edi,4 |
||
255 | cmp edi,0x1000+512*256*3 |
||
256 | jb newpix |
||
257 | call put_image |
||
258 | mov eax,5 |
||
259 | mov ebx,1 |
||
260 | int 0x40 |
||
261 | dec esi |
||
262 | jnz newcycle |
||
263 | |||
264 | mov eax,0 |
||
265 | mov edi,0x1000 |
||
266 | mov ecx,512*256*3 / 4 +50 |
||
267 | cld |
||
268 | rep stosd |
||
269 | |||
270 | popa |
||
271 | |||
272 | call draw_fractal |
||
273 | |||
274 | ret |
||
275 | |||
276 | |||
277 | |||
278 | |||
279 | |||
280 | ; ********************************************************************** |
||
281 | ; |
||
282 | ; Tinyfrac |
||
283 | ; |
||
284 | |||
285 | |||
286 | draw_fractal: |
||
287 | |||
288 | pusha |
||
289 | mov eax,4 |
||
290 | mov ebx,15*65536+35 |
||
291 | mov ecx,0xffffff |
||
292 | mov edx,calc |
||
293 | mov esi,calcl-calc |
||
294 | int 0x40 |
||
295 | popa |
||
296 | pusha |
||
297 | |||
298 | movzx ebp,word [STARTX] |
||
299 | movzx edi,word [STARTY] |
||
300 | |||
301 | |||
302 | ; This routine is the fractal drawing engine. It has been |
||
303 | ; optimized for size, sacrificing speed. |
||
304 | |||
305 | mov cx, PIXHEIGHT ; height of screen in pixels |
||
306 | |||
307 | sub di,cx ; adjust our Y offset |
||
308 | @@CalcRow: |
||
309 | |||
310 | push cx |
||
311 | |||
312 | ; and cl,0x7 |
||
313 | ; cmp cl,0 |
||
314 | ; jne noim |
||
315 | ; call put_image |
||
316 | ; noim: |
||
317 | |||
318 | mov cx, PIXWIDTH -1 ; width of screen in pixels |
||
319 | |||
320 | sub bp,cx ; |
||
321 | @@CalcPixel: |
||
322 | push cx ; save the column counter on stack |
||
323 | xor cx, cx ; clear out color loop counter |
||
324 | xor bx, bx ; zero i coefficient |
||
325 | xor dx, dx ; zero j coefficient |
||
326 | @@CycleColors: |
||
327 | push dx ; save j value for later |
||
328 | mov ax, bx ; ax = i |
||
329 | sub ax, dx ; ax = i - j |
||
330 | add dx, bx ; dx = i + j |
||
331 | stc ; one additional shift, please |
||
332 | call Shifty ; ax = ((i+j)*(i-j)) shifted right |
||
333 | pop dx ; retrieve our saved value for j |
||
334 | add ax,bp ; account for base offset... |
||
335 | cmp ah,THRESHOLD ; Q: is i > THRESHOLD * 256? |
||
336 | xchg bx,ax ; now swap new i with old i |
||
337 | jg @@draw ; Y: draw this pixel |
||
338 | clc ; no additional shifts here, please |
||
339 | call Shifty ; now dx:ax = old i * j |
||
340 | xchg dx,ax ; |
||
341 | add dx,di ; account for base offset... |
||
342 | inc cl ; increment color |
||
343 | jnz @@CycleColors ; keep going until we're done |
||
344 | @@draw: |
||
345 | xchg ax, cx ; mov color into al |
||
346 | pop cx ; retrieve our column counter |
||
347 | pop dx ; fetch row (column already in cx) |
||
348 | push dx ; must leave a copy on the stack |
||
349 | xor bx,bx ; write to video page zero |
||
350 | |||
351 | call put_pixel |
||
352 | |||
353 | inc bp |
||
354 | loop @@CalcPixel |
||
355 | inc di |
||
356 | pop cx |
||
357 | loop @@CalcRow |
||
358 | |||
359 | call put_image |
||
360 | |||
361 | popa |
||
362 | |||
363 | ret |
||
364 | |||
365 | |||
366 | put_image: |
||
367 | |||
368 | pusha |
||
369 | |||
370 | mov eax,7 |
||
371 | mov ebx,0x1000 |
||
372 | mov ecx,512*65536+255 |
||
373 | mov edx,10*65536+30 |
||
374 | int 0x40 |
||
375 | |||
376 | popa |
||
377 | |||
378 | ret |
||
379 | |||
380 | |||
381 | shlc db 0 |
||
382 | |||
383 | put_pixel: |
||
384 | |||
385 | pusha |
||
386 | sub edi,[STARTY] |
||
387 | sub ebp,[STARTX] |
||
388 | and edi,0xff |
||
389 | and ebp,0x1ff |
||
390 | shl edi,9 |
||
391 | mov ebx,edi ; * 3 - Y |
||
392 | add edi,ebx |
||
393 | add edi,ebx |
||
394 | mov ebx,ebp |
||
395 | add ebp,ebx |
||
396 | add ebp,ebx |
||
397 | add edi,ebp |
||
398 | mov cl,[shlc] |
||
399 | mov ebx,0xff |
||
400 | shl ebx,cl |
||
401 | add cl,3 |
||
402 | shl eax,cl |
||
403 | and eax,ebx |
||
404 | mov [0x1000+edi],eax |
||
405 | popa |
||
406 | |||
407 | ret |
||
408 | |||
409 | |||
410 | ;**************************************************************************** |
||
411 | ; |
||
412 | ; This routine multiplies AX by DX and shifts the result (in |
||
413 | ; DX:AX) to the right by scale bits (or scale+1 bits if CY is |
||
414 | ; set). The resulting value is left in AX. DX is destroyed. |
||
415 | ; |
||
416 | ;**************************************************************************** |
||
417 | |||
418 | Shifty: |
||
419 | push cx ; save middle bits (i*i - j*j) |
||
420 | db 0b1h ; code for mov cl,immed8 |
||
421 | scale db STARTSCALE |
||
422 | adc cl,0 ; adjust per CY flag |
||
423 | imul dx ; do the multiply |
||
424 | |||
425 | xchg ax,dx ; |
||
426 | shl eax,16 ; put hi part in hi 16 bits |
||
427 | xchg ax,dx |
||
428 | shr eax,cl ; |
||
429 | |||
430 | pop cx ; |
||
431 | ret ; |
||
432 | |||
433 | |||
434 | |||
435 | ; ********************************************************************** |
||
436 | ; |
||
437 | ; WINDOW DEFINITIONS AND DRAW |
||
438 | ; |
||
439 | ; ********************************************************************** |
||
440 | |||
441 | |||
442 | |||
443 | draw_window: |
||
444 | |||
445 | pusha |
||
446 | |||
447 | mov eax,12 |
||
448 | mov ebx,1 |
||
449 | int 0x40 |
||
450 | |||
451 | mov eax,0 |
||
452 | mov ebx,50*65536+531 |
||
453 | mov ecx,100*65536+256+48 |
||
454 | mov edx,0x02334455 |
||
455 | mov esi,0x80778899 |
||
456 | mov edi,0x00778899 |
||
457 | int 0x40 |
||
458 | |||
459 | mov eax,8 |
||
460 | mov ebx,(531-19)*65536+12 |
||
461 | mov ecx,5*65536+12 |
||
462 | mov edx,1 |
||
463 | mov esi,0x808080 |
||
464 | int 0x40 |
||
465 | |||
466 | mov eax,8 |
||
467 | mov ebx,300*65536+112 |
||
468 | mov ecx,5*65536+12 |
||
469 | mov edx,2 |
||
470 | mov esi,0x808080 |
||
471 | int 0x40 |
||
472 | |||
473 | mov ebx,430*65536+12 |
||
474 | mov ecx,5*65536+12 |
||
475 | mov edx,3 |
||
476 | mov esi,0xa00000 |
||
477 | mov edi,3 |
||
478 | newcolor: |
||
479 | mov eax,8 |
||
480 | int 0x40 |
||
481 | add ebx,13*65536 |
||
482 | shr esi,8 |
||
483 | inc edx |
||
484 | dec edi |
||
485 | jnz newcolor |
||
486 | |||
487 | mov eax,4 |
||
488 | mov ebx,8*65536+8 |
||
489 | mov ecx,0xffffff |
||
490 | mov edx,l |
||
491 | mov esi,ll-l |
||
492 | int 0x40 |
||
493 | |||
494 | mov eax,12 |
||
495 | mov ebx,2 |
||
496 | int 0x40 |
||
497 | |||
498 | popa |
||
499 | ret |
||
500 | |||
501 | |||
502 | ; *************************************************************** |
||
503 | ; |
||
504 | ; DATA AREA |
||
505 | ; |
||
506 | |||
507 | |||
508 | l: db 'TINYFRAC - MOVE: ARROWS, ZOOM Q/W, CYCLE: E/R ' |
||
509 | db 'SET AS WALLPAPER' |
||
510 | ll: |
||
511 | |||
512 | calc db 'CALCULATING' |
||
513 | calcl: |
||
514 | |||
515 | I_END: |
||
516 |