Subversion Repositories Kolibri OS

Rev

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