; Super MANDELZOOM ; ; Unfortunately, there is no accurate revision history for the first ; few years of this program's development. ; ; 1985 Aug? Begin first Mandelbrot program. ; 1985 ? Release first Mandelbrot program ; 1986 ? Begin work on new, much-improved version ; ? Devise "pre-emptive multitasking" scheme. ; ? Release first version of Super MANDELZOOM. ; ? ? Add filament routine. ; 1987 ? Add menu items for file I/O ; ; 1988 Mar 13 Begin adding a TIFF file routine. ; 20 Start working on "copy to clipboard" command. ; 23 Get Copy to Clipboard working. Fix a bug in the 16-bit in-set ; routine. Change the filaments algorithm to use 8 neighbors ; instead of 4. ; 24 Fix a bug in Copy-to-clipboard. ; 31 Test and approve version 1.06. ; Apr 2 Finish writing a string-to-fixed-point routine. ; 4 Add "Set Center and Size" command. ; 6 Add max iterations command. ; 12 Fix a couple of bugs. ; 19 Start work on a Super MZ file format. ; 25 Split math routines into four files. ; 26 Try to improve _QUERY algorithm, but find a logical flaw and ; discard changes. ; ; Jun 6 Increase max n_max to 9999 (use shading table entry 126 for all ; of the new counts.) Make _QUERY iterate twice as much (i.e. up ; to 4000 instead of previous 2000) to increase accuracy. ; ; 1989 Jan 29 Start work on adding '020 support. ; 30 _in_set_020 works. (Mac II with standard benchmark image: ; 1'33" vs. 2'13" for _in_set_30) ; ; Mar 1 Make the About... menu command bring up a dialog box; add PICT ; for ARTMATRIX version of the program. ; 7 Fix a bug in _update_screen. Remove most file menu items. ; ; xdef start array_size equ $10000 pic_h equ 8 pic_v equ 44 pic_v_h equ (pic_v<<16)+pic_h edit_h equ pic_h+444 ; Dialog and item list IDs ; DLOG_COORDS equ 1000 DLOG_NMAX equ 1001 DLOG_SAVEOPT equ 1002 DLOG_ABOUT equ 1003 ; Constants and variables for _exec_. ; waiting equ 1 ; waiting to start paused equ 2 ; "pre-empted" in the documentation aborted equ 3 ; aborted finished equ 3 ; finished - same as aborted as far as ; _exec_ is concerned. ; Bit masks for processes ; m_julia equ 1 m_draw_pic equ 2 m_query equ 4 m_d_track equ 8 m_mouse_pt equ 16 m_refill equ 32 m_detail equ 64 m_idle_mode equ 128 m_q_search equ 256 m_filaments equ 512 m_tiff equ 1024 ; Variables to keep track of the states of the processes. ; p_julia dc.w 0 p_draw_pic dc.w 0 p_query dc.w 0 p_d_track dc.w 0 p_mouse_pt dc.w 0 p_refill dc.w 0 p_detail dc.w 0 p_idle_mode dc.w 0 p_q_search dc.w 0 p_filaments dc.w 0 p_tiff dc.w 0 ; Useful constants true equ $ffff false equ 0 quit_flag dc.w 0 ; Set true if user picked "Quit" command. time_share dc.w 0 ; Set true if the currently executing process should ; exit immediately. pending_procs dc.w 0 ; Which processes are waiting or paused this time ; around? print_names dc.w 0 ; Indicates when "currently running processes" ; display needs to be updated. ; regbuf allocates correct amout of space to save D0-D7/A0-A4/A6 ; macro regbuf = dc.l 0,0,0,0, 0,0,0,0, 0,0,0,0,0,0 | ; penbuf allocates correct amount of space to save a PenState. macro penbuf = dc.w 0,0, 0,0, 0, 0,0,0,0 | exec_pen penbuf ; So _exec_ can save its own pen state. ; Data and variables, etc. ; my_window dc.l 0 ; WindowPtr for my window scroll_rgn dc.l 0 ; Handle to region returned by ScrollRect screenrect dc.w 0,0,342,512 arrow_cursor dc.l 0 ; handle to arrow crsr arrow_ptr dc.l 0 ; pointer to arrow crsr plus_cursor dc.l 0 ; handle to plus crsr watch_cursor dc.l 0 ; handle to watch crsr selzoom_cursor dc.l 0 pic_rect dc.w pic_v,pic_h,pic_v+256,pic_h+256 pic_frame dc.w pic_v-1,pic_h-1,pic_v+257,pic_h+257 pic_top dc.w pic_v,pic_h,pic_v+32,pic_h+256 pic_left dc.w pic_v,pic_h,pic_v+256,pic_h+32 pic_bottom dc.w pic_v+224,pic_h,pic_v+256,pic_h+256 pic_right dc.w pic_v,pic_h+224,pic_v+256,pic_h+256 mousepoint dc.w 0,0 cur_pensize dc.w 0 command dc.w 0 query_cmd equ 1 selzoom_cmd equ 2 detail_cmd equ 3 julia_cmd equ 4 macro button_1 top,left = dc.w {top},{left},{top}+24,{left}+24 | left_rect button_1 71,268+pic_h right_rect button_1 71,324+pic_h up_rect button_1 43,296+pic_h down_rect button_1 99,296+pic_h _100_rect button_1 -221,268+pic_h ; These buttons are defunct, and are placed _250_rect button_1 -221,301+pic_h ; off-screen so user can't see them. _500_rect button_1 -221,335+pic_h _1000_rect button_1 -221,368+pic_h _16_bit_rect button_1 249,268+pic_h _18_bit_rect button_1 249,301+pic_h _30_bit_rect button_1 249,335+pic_h _32_bit_rect button_1 249,368+pic_h which_bits dc.w 0,0,0,0 macro button_3 top,left = dc.w {top},{left},{top}+36,{left}+36 | macro button_4 top,left = dc.w {top},{left},{top}+32,{left}+32 | home_rect button_3 43,356+pic_h home_icon_rect button_4 45,358+pic_h zoom_out4_rect button_3 87,356+pic_h zo4_icon_rect button_4 89,358+pic_h zoom_in_rect button_3 132,268+pic_h zi_icon_rect button_4 134,270+pic_h zoom_out_rect button_3 132,356+pic_h zo_icon_rect button_4 134,358+pic_h selzoom_rect button_3 132,312+pic_h selz_icon_rect button_4 134,314+pic_h query_rect button_3 176,268+pic_h query_icon_rect button_4 178,270+pic_h julia_rect button_3 176,312+pic_h julia_icon_rect button_4 178,314+pic_h detail_rect button_3 176,356+pic_h det_icon_rect button_4 178,358+pic_h which_cmd dc.w 0,0,0,0 ; palette rect currently inverted ct_1_rect button_3 43,400+pic_h ct_2_rect button_3 87,400+pic_h ct_3_rect button_3 132,400+pic_h ct_4_rect button_3 176,400+pic_h ct_5_rect button_3 221,400+pic_h ct_6_rect button_3 265,400+pic_h which_table dc.w 0,0,0,0 mesg_rect dc.w 301,pic_h-4,342,pic_h+305 status_rect dc.w 281,268+pic_h,301,400+pic_h qry_data_frame dc.w 316,307+pic_h,340,504 qry_data_rect dc.w 317,308+pic_h,339,503 mouse_pt_rect dc.w 302,pic_h+310,312,pic_h+320 mouseloc_rect dc.w 301,pic_h+358,313,512 ; stripes are used to denote areas not-yet evaluated stripes dc.b $03,$06,$0c,$18,$30,$60,$c0,$81 ; Pattern table. This contains "Dithered" gray patterns on 17 levels from ; white to black. pat_table dc.b $00,$00,$00,$00,$00,$00,$00,$00 ; 0 (white) gray1 dc.b $88,$00,$00,$00,$88,$00,$00,$00 ; 1 dc.b $88,$00,$22,$00,$88,$00,$22,$00 dc.b $88,$00,$aa,$00,$88,$00,$aa,$00 dc.b $aa,$00,$aa,$00,$aa,$00,$aa,$00 dc.b $aa,$44,$aa,$00,$aa,$44,$aa,$00 dc.b $aa,$44,$aa,$11,$aa,$44,$aa,$11 dc.b $aa,$44,$aa,$55,$aa,$44,$aa,$55 gray8 dc.b $aa,$55,$aa,$55,$aa,$55,$aa,$55 ; 8 (gray) dc.b $aa,$dd,$aa,$55,$aa,$dd,$aa,$55 dc.b $aa,$dd,$aa,$77,$aa,$dd,$aa,$77 dc.b $aa,$dd,$aa,$ff,$aa,$dd,$aa,$ff dc.b $aa,$ff,$aa,$ff,$aa,$ff,$aa,$ff dc.b $ee,$ff,$aa,$ff,$ee,$ff,$aa,$ff dc.b $ee,$ff,$bb,$ff,$ee,$ff,$bb,$ff gray15 dc.b $ee,$ff,$ff,$ff,$ee,$ff,$ff,$ff black16 dc.b $ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff ; 16 (black) white17 dc.b $00,$00,$00,$00,$00,$00,$00,$00 ; 17 min_real dc.w 0 ; Pixel coordinates control the bounds of _draw.pic. max_real dc.w 0 min_imag dc.w 0 max_imag dc.w 0 zoom_factor dc.w 0 ; log base 2 of magnification pic_center dc.l 1,1 ; 32-bit real & imaginary coordinates of ; center. (We use 1,1 instead of 0,0 in ; order to avoid having the long straight ; filament on the real axis be visible.) num_digits dc.w 0 ; How many digits should coordinates be printed on ; screen with? max_zoom dc.w 0 ; What is the highest value of zoom_factor that ; should be used, given the current choice of number ; of bits? is_proc dc.l 0 ; Pointer to which subroutine to use to evaluate ; points. cpu_020 dc.w 0 ; Set to a non-zero value if we're running on an ; '020 or '030. n_max dc.w 0 ; How many iterations of Z'=Z^2+C before we assume ; that count = infinity color_table dc.l 0 ; Pointer to one of six 128-byte shading tables array_ptr dc.l 0 ; ptr to array data. temp_block dc.l 0 ; ptr to large temp block allocated to make sure ; there's plenty of memory after allocating array. small_mac dc.w 0 ; Set true if we don't have enough memory for array. include Sys-Intf my_events equ EveryEventMask-MouseUpMask macro compare r1,r2 = cmp {r2},{r1} | macro compare_l r1,r2 = cmp.l {r2},{r1} | ; Macro to look up a 7-bit count value in the shading table to find out ; what shade of gray it should be. ; macro cnt_2_shade cntreg,shadereg,areg = move.l color_table,{areg} ; Get address of shading table and #$007f,{cntreg} ; Mask out flag bit adda.w {cntreg},{areg} ; Offset into table move.b ({areg}),{shadereg} ; Get value | macro save_all = movem.l d0-d7/a0-a4,-(sp) | macro restore_all = movem.l (sp)+,d0-d7/a0-a4 | macro move_rect rect1,rect2 = lea {rect1},a0 lea {rect2},a1 move.l (a0),(a1) move.l 4(a0),4(a1) | macro set_var var,value = lea {var},a0 move {value},(a0) | macro cmp_var var,value = move {var},d0 cmp {value},d0 | macro set_state process,state = set_var p{process},#{state} | macro test_state process,state = cmp_var p{process},#{state} | include 020-Macros include MZ-Math16 include MZ-Math18 include MZ-Math30 include MZ-Math32 include MZ-procs start: lea -4(a5),a0 ; Global ThePort must be set to -4(a5) (Mac system move.l a0,(a5) ; won't do it for us) move.l GrafGlobals(a5),a6 ; InitGraf(@ThePort) InitGraf (a6) _InitFonts _InitWindows _InitMenus _TEInit clr.l -(sp) _InitDialogs InitCursor OpenResFile 'MZ.res' ; If file "MZ.res" is present, the menus, tst (sp)+ ; icons, etc. will be read from it rather ; than from our own resource file. This ; is useful during program development. clr.l -(sp) ; Return value clr.l -(sp) ; wStorage pea screenrect ; boundsrect pea 'MZ' ; title move #true,-(sp) ; visible move #2,-(sp) ; procID clr.l -(sp) ; behind clr -(sp) ; goAwayFlag clr.l -(sp) ; refCon _NewWindow lea my_window,a0 move.l (sp)+,(a0) SetPort my_window EraseRect screenrect clr.l -(sp) _NewRgn lea scroll_rgn,a0 move.l (sp)+,(a0) set_var small_mac,#false ; Assume for now enough memory. TextMode #SrcOr ; Get ready for all the messages we might TextSize #18 ; print TextFont #20 ; Move ApplLimit down so we'll have more stack space (this was ; added when I thought one of the ROM calls I was making was taking ; up lots of stack space) ; ; tst.b $7014(a0) ; lea ApplLimit,a0 ; move.l (a0),a1 ; lea $-4000(a1),a1 ; Want to set ApplLimit to this ; move.l HeapEnd,a2 ; compare_l a1,a2 ; bgt @1 ; lea 4(a2),a1 ; Must be at least this @1 ; move.l a1,(a0) move.l #20000,d0 ; Allocate temp 20K of memory _NewPtr lea temp_block,a1 move.l a0,(a1) tst d0 bne _no_memory move.l #array_size,d0 ; Allocate array. _NewPtr lea array_ptr,a1 move.l a0,(a1) tst d0 bne _arr_failed ; If out of memory, handle problem move.l temp_block,a0 ; Free the temp block _DisposPtr bra _start_2 _no_memory: MoveTo #20,#50 DrawString 'There is so little memory I can''t even allocate a 128' MoveTo #20,#70 DrawString 'by 128 array. This program will now exit to Finder.' MoveTo #20,#100 DrawString 'If you have a 128K Mac, make sure you have no clocks,' MoveTo #20,#120 DrawString 'debuggers or other things installed which might take' MoveTo #20,#140 DrawString 'up memory space.' MoveTo #20,#170 DrawString 'Press button to continue.' jsr _wait_button rts ; Return to Finder _wait_button: ; Routine to wait for mouse down. clr.w -(sp) Button tst.w (sp)+ beq _wait_button rts _arr_failed: move.l #16384,d0 ; Allocate array. _NewPtr lea array_ptr,a1 move.l a0,(a1) tst d0 bne _no_memory move.l temp_block,a0 ; Free the temp block _DisposPtr set_var small_mac,#true MoveTo #20,#50 DrawString 'Sorry, but there is only enough memory for a 128 x 128' MoveTo #20,#70 DrawString 'array. Drawing in 256 x 256 resolution will be' MoveTo #20,#90 DrawString 'significantly slower.' MoveTo #20,#120 DrawString 'Press button to continue.' jsr _wait_button EraseRect screenrect TextMode #SrcOr TextSize #18 TextFont #20 MoveTo #100,#100 DrawString 'Release button to continue.' _st_9: clr.w -(sp) Button tst.w (sp)+ bne _st_9 EraseRect screenrect _start_2: move #$93,d0 ; Get addresses of frequently-used trap routines _GetTrapAddress lea tl_moveto,a1 move.l a0,(a1) move #$9d,d0 _GetTrapAddress lea tl_penpat,a1 move.l a0,(a1) move #$91,d0 _GetTrapAddress lea tl_lineto,a1 move.l a0,(a1) jsr _setup_menus TextMode #SrcOr TextSize #18 TextFont #20 lea arrow_cursor,a0 ; Get arrow crsr lea arrow_ptr,a1 move.l a1,(a0) lea -112(a5),a2 move.l a2,(a1) clr.l -(sp) ; Get plus crsr move #2,-(sp) _GetCursor lea plus_cursor,a0 move.l (sp)+,(a0) clr.l -(sp) ; Get wristwatch crsr move #4,-(sp) _GetCursor lea watch_cursor,a0 move.l (sp)+,(a0) clr.l -(sp) ; Get selzoom crsr move #1005,-(sp) _GetCursor lea selzoom_cursor,a0 move.l (sp)+,(a0) jsr _init_strings move.l plus_cursor,a0 ; Initial cursor move.l (a0),-(sp) _SetCursor move.l #$0000ffff,d0 ; Now that controls are visible, start _FlushEvents ; getting events. lea is_proc,a0 ; Default in_set proc is 16-bit version. lea _in_set,a1 move.l a1,(a0) lea cpu_020,a0 ; Figure out which type of 68000 we have. clr (a0) ; Assume 68010 or less. move.b $12f,d0 compare d0,#2 blt _s_no_020 move #-1,(a0) ; 68020 or later _s_no_020: move_rect _16_bit_rect,which_bits set_var max_zoom,#8 ; Default max zoom is 8 lea color_table,a0 ; Default shading table is table_1. lea table_1,a1 move.l a1,(a0) move_rect ct_1_rect,which_table set_var zoom_factor,#0 ; Default zoom is zero. set_var num_digits,#2 ; Default number of digits is 2 set_var n_max,#100 ; Default n.max is 100. lea pic_center,a0 ; Default view is 0.000+0.000i (plus a tiny move.l #-1,d0 ; offset which is added so the filament move.l d0,(a0) ; structure of M.2 doesn't show up) move.l d0,4(a0) jsr _dft_bounds ; Set full bounds for _draw_pic_ set_var command,#selzoom_cmd ; Default command is selzoom_cmd move_rect selzoom_rect,which_cmd set_var dt_rect_on,#false fillrect pic_rect,stripes jsr _clear_array set_var _ee_count,#3 ; Initially get 3 events. _exec: ; Initial states of the processes. set_state _tiff,finished set_state _julia,finished set_state _filaments,finished set_state _draw_pic,waiting set_state _query,finished set_state _d_track,finished set_state _mouse_pt,finished set_state _refill,finished set_state _detail,finished set_state _idle_mode,waiting set_state _q_search,waiting GetPenState exec_pen _e_event: lea _ee_count,a0 ; Decrement count subq #1,(a0) bgt @1 ; Don't allow less than zero. clr (a0) @1: _SystemTask SetPenState exec_pen ; Get an event (and go to _dispatch_ if there was none - it might ; be that we got here because the program just started up or a ; process finished by itself.) ; GetNextEvent #EveryEventMask,my_event ; Get the event tst (sp)+ beq _dispatch ; No event - resume running a process. move evt_what,d0 compare d0,#mouseUp beq _e_event cmp #mouseDown,d0 beq _md_evt cmp #keyDown,d0 beq _kd_evt cmp #updateEvt,d0 bne _dispatch move.l evt_message,a0 ; Get windowPtr compare_l a0,my_window ; if it's not mine, ignore it. bne _dispatch move.l a0,-(sp) _BeginUpdate jsr _update_screen move.l evt_message,-(sp) _EndUpdate bra _dispatch _kd_evt: move evt_modifiers,d0 ; If command key wasn't down, ignore it. and #256,d0 beq _dispatch move.l evt_message,d0 ; Command key was down: menu command. and #$00ff,d0 clr.l -(sp) move d0,-(sp) _MenuKey move.l (sp)+,d0 jsr _do_menu_command move quit_flag,d0 ; Check to see if they quit. bne _e_quit bra _dispatch _md_evt: FindWindow evt_where,which_window move (sp)+,d0 cmp #inMenuBar,d0 bne @1 clr.l -(sp) ; Do menu command. move.l evt_where,-(sp) _MenuSelect move.l (sp)+,d0 jsr _do_menu_command move quit_flag,d0 bne _e_quit bra _dispatch @1: cmp #inSysWindow,d0 ; In case I ever add desk accessories (HAH!) ; Historic sarcasm ----^ bne @2 SystemClick my_event,which_window bra _dispatch @2: lea mousepoint,a0 move.l evt_where,(a0) scroll_control: move.l #$10000000,d3 ; Set up for one of the scrolling commands. move zoom_factor,d4 asr.l d4,d3 lea pic_center,a3 jsr _dft_bounds ; Set full bounds for _draw_pic. PtInRect mousepoint,left_rect tst.w (sp)+ beq bt_2 tst.b $7010(a0) sub.l d3,(a3) ; User wants to go left in the Complex plane pea pic_rect ; dstRect which means that we have move #32,-(sp) ; dh to scroll the graphics clr -(sp) ; dv towards the right. move.l scroll_rgn,-(sp) ; updateRgn _ScrollRect set_var max_real,#31 FillRect pic_left,stripes jsr _scroll_right bra scroll_command bt_2: PtInRect mousepoint,right_rect tst.w (sp)+ beq bt_3 tst.b $7011(a0) add.l d3,(a3) pea pic_rect move #-32,-(sp) clr -(sp) move.l scroll_rgn,-(sp) _ScrollRect set_var min_real,#224 FillRect pic_right,stripes jsr _scroll_left bra scroll_command bt_3: PtInRect mousepoint,down_rect tst.w (sp)+ beq bt_4 tst.b $7012(a0) sub.l d3,4(a3) pea pic_rect clr -(sp) move #-32,-(sp) move.l scroll_rgn,-(sp) _ScrollRect set_var min_imag,#224 FillRect pic_bottom,stripes jsr _scroll_up bra scroll_command bt_4: PtInRect mousepoint,up_rect tst.w (sp)+ beq zoom_control tst.b $7013(a0) add.l d3,4(a3) pea pic_rect clr -(sp) move #32,-(sp) move.l scroll_rgn,-(sp) _ScrollRect set_var max_imag,#31 jsr _scroll_down FillRect pic_top,stripes scroll_command: test_state _refill,finished ; If _refill_ is not finished, it bne @2 ; will have to start over. jsr _da_active ; If front window is not ours, beq @1 ; there could be a desk accessory in front ; of the image and we'll have to redraw ; the part that scrolled out from under the ; desk accessory. @2: set_state _refill,waiting @1: jsr _show_coords set_state _tiff,aborted set_state _filaments,aborted set_state _julia,aborted set_state _draw_pic,waiting ; First, draw the 8 32-bit pixels ; we scrolled in. set_state _detail,aborted set_state _idle_mode,waiting ; Compute the new part of the ; image down to resolution ; matching the other 7/8. (then ; continue with the whole image) set_state _q_search,waiting DisableItem my_options_menu,#1 bra _dispatch zoom_control: PtInRect mousepoint,zoom_in_rect tst.w (sp)+ beq bt_5 move zoom_factor,d1 addq #1,d1 ; Zoom in by a factor of 2. set_var zoom_factor,d1 bra zoom_command bt_5: PtInRect mousepoint,zoom_out_rect tst.w (sp)+ beq bt_5a move zoom_factor,d1 subq #1,d1 ; Zoom out by a factor of 2. set_var zoom_factor,d1 bra zoom_command bt_5a: PtInRect mousepoint,home_rect tst.w (sp)+ beq bt_5b set_var zoom_factor,#0 ; Zoom out all the way lea pic_center,a0 ; Set center to 0,0 (plus tiny offset) moveq.l #-1,d0 move.l d0,(a0) move.l d0,4(a0) bra zoom_command bt_5b: PtInRect mousepoint,zoom_out4_rect tst.w (sp)+ beq _pic_click move zoom_factor,d1 subq #4,d1 ; Zoom out by a factor of 16. set_var zoom_factor,d1 bra zoom_command zoom_command: jsr _zoom_cmd bra _dispatch _pic_click: PtInRect mousepoint,pic_rect tst.w (sp)+ beq bits_control move command,d0 compare d0,#query_cmd bne _pc_1 set_state _query,waiting ; Query bra _dispatch _pc_1: compare d0,#selzoom_cmd bne _pc_2 jsr _track_rect ; Selective zoom bra zoom_command _pc_2: compare d0,#julia_cmd ; Julia... bne _pc_3 set_state _julia,waiting bra _dispatch _pc_3: set_state _d_track,waiting ; Run _d_track; it will run _detail ; when user releases button. bra _dispatch bits_control: lea is_proc,a3 PtInRect mousepoint,_16_bit_rect tst.w (sp)+ beq bt_16b lea _in_set,a0 move.l a0,(a3) set_var max_zoom,#8 InvertRect which_bits move_rect _16_bit_rect,which_bits bra bits_command bt_16b: PtInRect mousepoint,_18_bit_rect tst.w (sp)+ beq bt_16 lea cpu_020,a0 tst (a0) bne.s @1 lea _in_set_18,a0 bra.s @2 @1: lea _in_set_020,a0 @2: move.l a0,(a3) set_var max_zoom,#9 InvertRect which_bits move_rect _18_bit_rect,which_bits bra bits_command bt_16: PtInRect mousepoint,_30_bit_rect tst.w (sp)+ beq.s bt_17 lea cpu_020,a0 tst (a0) bne.s @1 lea _in_set_30,a0 bra.s @2 @1: lea _in_set_020,a0 @2: move.l a0,(a3) set_var max_zoom,#22 InvertRect which_bits move_rect _30_bit_rect,which_bits bra bits_command bt_17: PtInRect mousepoint,_32_bit_rect tst.w (sp)+ beq tableedit_command lea cpu_020,a0 tst (a0) bne.s @1 lea _in_set_32,a0 bra.s @2 @1: lea _in_set_020,a0 @2: move.l a0,(a3) set_var max_zoom,#23 InvertRect which_bits move_rect _32_bit_rect,which_bits bra.s bits_command bits_command: InvertRect which_bits jsr _show_coords jsr _clear_array jsr _dft_bounds set_state _tiff,aborted set_state _filaments,aborted set_state _julia,aborted set_state _draw_pic,waiting set_state _refill,aborted set_state _detail,aborted set_state _idle_mode,waiting set_state _q_search,waiting DisableItem my_options_menu,#1 bra _dispatch tableedit_command: PtInRect mousepoint,edit_rect tst.w (sp)+ beq ct_2 jsr _edit_table set_state _julia,aborted set_state _refill,waiting bra _dispatch ct_2: lea color_table,a3 PtInRect mousepoint,ct_1_rect tst.w (sp)+ beq bt_9 lea table_1,a0 move.l a0,(a3) InvertRect which_table move_rect ct_1_rect,which_table bra choose_table bt_9: PtInRect mousepoint,ct_2_rect tst.w (sp)+ beq bt_10 lea table_2,a0 move.l a0,(a3) InvertRect which_table move_rect ct_2_rect,which_table bra choose_table bt_10: PtInRect mousepoint,ct_3_rect tst.w (sp)+ beq bt_11 lea table_3,a0 move.l a0,(a3) InvertRect which_table move_rect ct_3_rect,which_table bra choose_table bt_11: PtInRect mousepoint,ct_4_rect tst.w (sp)+ beq bt_12 lea table_4,a0 move.l a0,(a3) InvertRect which_table move_rect ct_4_rect,which_table bra choose_table bt_12: PtInRect mousepoint,ct_5_rect tst.w (sp)+ beq @1 lea table_5,a0 move.l a0,(a3) InvertRect which_table move_rect ct_5_rect,which_table bra choose_table @1: PtInRect mousepoint,ct_6_rect tst.w (sp)+ beq palette_control lea table_6,a0 move.l a0,(a3) InvertRect which_table move_rect ct_6_rect,which_table choose_table: InvertRect which_table jsr _show_table set_state _julia,aborted set_state _refill,waiting bra _dispatch palette_control: PtInRect mousepoint,query_rect tst.w (sp)+ beq bt_6 set_var command,#query_cmd InvertRect which_cmd move_rect query_rect,which_cmd jsr _do_cursor bra palette_command bt_6: PtInRect mousepoint,selzoom_rect tst.w (sp)+ beq bt_7 set_var command,#selzoom_cmd InvertRect which_cmd move_rect selzoom_rect,which_cmd jsr _do_cursor bra palette_command bt_7: PtInRect mousepoint,julia_rect tst.w (sp)+ beq bt_8 set_var command,#julia_cmd InvertRect which_cmd move_rect julia_rect,which_cmd jsr _do_cursor bra palette_command bt_8: PtInRect mousepoint,detail_rect tst.w (sp)+ beq bt_20 set_var command,#detail_cmd InvertRect which_cmd move_rect detail_rect,which_cmd jsr _do_cursor bra palette_command palette_command: InvertRect which_cmd set_state _julia,aborted ; Palette aborts _julia bra _dispatch bt_20: PtInRect mousepoint,mouse_pt_rect tst (sp)+ beq bt_21 InvertRect mouse_pt_rect test_state _mouse_pt,aborted beq @1 set_state _mouse_pt,aborted bra _dispatch @1: set_state _mouse_pt,waiting bt_21: ; There are no more rects to test for now. Fall into _dispatch. ; _dispatch_ goes through all the processes, from highest to lowest ; priority, and runs the first one it finds which is waiting or paused. ; _dispatch: lea _ee_count,a0 ; Look at event-allow count tst (a0) bgt _e_event set_var print_names,#false ; For now assume don't print names clr d1 ; Find out what processes are pending. test_state _julia,finished beq @1 add #m_julia,d1 @1: test_state _draw_pic,finished beq @2 add #m_draw_pic,d1 @2: test_state _query,finished beq @3 add #m_query,d1 @3: test_state _d_track,finished beq @4 add #m_d_track,d1 @4: test_state _mouse_pt,finished beq @5 add #m_mouse_pt,d1 @5: test_state _refill,finished beq @6 add #m_refill,d1 @6: test_state _detail,finished beq @7 add #m_detail,d1 @7: test_state _idle_mode,finished beq @8 add #m_idle_mode,d1 @8: test_state _q_search,finished beq @9 add #m_q_search,d1 @9: test_state _filaments,finished beq @0 add #m_filaments,d1 @0: test_state _tiff,finished beq _dz1 add #m_tiff,d1 _dz1: lea pending_procs,a0 compare d1,(a0) ; Same set of procs pending as last time? beq _d_timeshare ; Yes, don't print names move d1,(a0) ; Remember set to compare to next time set_var print_names,#true EraseRect status_rect ; Get ready to print names MoveTo #268+pic_h,#290 TextFont #4 TextSize #9 DrawString 'Processes currently running:' MoveTo #268+pic_h,#298 _d_timeshare: moveq #3,d2 ; Set d2 to number of timeshared processes ; running/waiting; assume 3 for now. test_state _refill,finished bne @1 test_state _detail,finished bne @1 test_state _idle_mode,finished bne @1 test_state _q_search,finished bne @1 subq #1,d2 ; All of these four are finished, so subtract 1 @1: test_state _d_track, finished ; Check _d_track bne @2 subq #1,d2 ; Subtract 1 if it's finished @2: test_state _mouse_pt,aborted ; Check _mouse_pt bne @3 subq #1,d2 ; Subtract 1 if it's finished @3: set_var time_share,#true ; Set time-sharing true compare d2,#2 bge _e_retro ; unless d2<2. set_var time_share,#false _e_retro: ; Retrocheck for a D.A. window and make timeshare jsr _da_active ; true if there is one. beq _e_tiff set_var time_share,#true _e_tiff: test_state _tiff,finished beq _e_fil cmp_var print_names,#true bne @1 DrawString '_TIFF' @1: GetPenState exec_pen jsr s_tiff bra _e_event _e_fil: test_state _filaments,finished beq _e_julia cmp_var print_names,#true bne @1 DrawString '_FILAMENTS' @1: GetPenState exec_pen jsr s_filaments bra _e_event _e_julia: test_state _julia,finished beq _e_draw_pic cmp_var print_names,#true bne @1 DrawString '_JULIA' @1: GetPenState exec_pen jsr s_julia bra _e_event _e_draw_pic: test_state _draw_pic,finished beq _e_query cmp_var print_names,#true bne @2 DrawString '_DRAW_PIC' @2: GetPenState exec_pen test_state _draw_pic,waiting bne @1 jsr s_draw_pic bra _e_event @1: set_var refill_zot,#0 ; If _draw_pic was interrupted, it is no ; longer OK to skip _refill on update events. jsr c_draw_pic bra _e_event _e_query: test_state _query,finished beq _e_mouse_pt cmp_var print_names,#true bne @1 DrawString '_QUERY' @1: GetPenState exec_pen jsr s_query bra _e_event _e_mouse_pt: test_state _mouse_pt,aborted beq _e_d_track cmp_var print_names,#true bne @2 DrawString '_MOUSE_PT ' @2: GetPenState exec_pen test_state _mouse_pt,waiting bne @1 jsr s_mouse_pt SetPenState exec_pen bra _e_d_track ; Fall through to _e_d_track so we can ; time-share with the next 5 processes. @1: jsr c_mouse_pt SetPenState exec_pen bra _e_d_track _e_d_track: test_state _d_track,finished beq _e_refill cmp_var print_names,#true bne @2 TextFont #4 TextSize #9 DrawString '_D_TRACK ' @2: GetPenState exec_pen test_state _d_track,waiting bne @1 jsr s_d_track SetPenState exec_pen bra _e_refill ; Fall through to _e_refill so we can ; time-share with the next 4 processes. @1: jsr c_d_track SetPenState exec_pen bra _e_refill _e_refill: test_state _refill,finished beq _e_detail cmp_var print_names,#true bne @2 TextFont #4 TextSize #9 DrawString '_REFILL' @2: GetPenState exec_pen test_state _refill,waiting bne @1 jsr s_refill bra _e_event @1: jsr c_refill bra _e_event _e_detail: test_state _detail,finished beq _e_idle_mode cmp_var print_names,#true bne @2 TextFont #4 TextSize #9 DrawString '_DETAIL' @2: GetPenState exec_pen test_state _detail,waiting bne @1 jsr s_detail bra _e_event @1: jsr c_detail bra _e_event _e_idle_mode: test_state _idle_mode,finished beq _e_q_search cmp_var print_names,#true bne @2 TextFont #4 TextSize #9 DrawString '_IDLE_MODE' @2: GetPenState exec_pen test_state _idle_mode,waiting bne @1 jsr s_idle_mode bra _e_event @1: jsr c_idle_mode bra _e_event _e_q_search: test_state _q_search,finished beq _e_end cmp_var print_names,#true bne @2 TextFont #4 TextSize #9 DrawString '_Q_SEARCH' @2: GetPenState exec_pen test_state _q_search,waiting bne @1 jsr s_q_search bra _e_event @1: jsr c_q_search bra _e_event _e_end: bra _e_event ; No processes are pending! Go back and see if ; there's an event. _e_quit: rts ; Return to Finder ; Do all the things necessary after a zoom command has been issued. ; _zc_digits: dc.b 2,2,2, 3,3,3, 4,4,4, 5,5,5 dc.b 6,6,6,6, 7,7,7, 8,8,8 dc.b 9,9,9,9, 10,10,10,10,10 .align 2 ; _zoom_cmd: move zoom_factor,d1 compare d1,#0 ; Zoom factor must be from 0 to 30. bge @1 moveq #0,d1 @1: compare d1,#30 ble @2 moveq #30,d1 @2: set_var zoom_factor,d1 lea _zc_digits,a0 ; Set number of digits for coordinate displays. adda d1,a0 moveq #0,d0 move.b (a0),d0 set_var num_digits,d0 jsr _show_coords fillrect pic_rect,stripes jsr _clear_array jsr _dft_bounds set_state _tiff,aborted set_state _filaments,aborted set_state _julia,aborted set_state _draw_pic,waiting set_state _refill,aborted set_state _detail,aborted set_state _idle_mode,waiting set_state _q_search,waiting DisableItem my_options_menu,#1 rts ; Do all the things necessary after a "change nmax" command has been issued. ; _n_max_cmd: jsr _show_coords jsr _clear_array jsr _dft_bounds set_state _tiff,aborted set_state _filaments,aborted set_state _julia,aborted set_state _draw_pic,waiting set_state _refill,aborted set_state _detail,aborted set_state _idle_mode,waiting set_state _q_search,waiting DisableItem my_options_menu,#1 rts ; Set correct cursor (after a palette command is chosen or after a D.A. is ; closed.) ; _do_cursor: move.l plus_cursor,a0 cmp_var command,#selzoom_cmd bne @1 move.l selzoom_cursor,a0 @1: move.l (a0),-(sp) _SetCursor rts ; Process a menu command. ; ; Reg. Input Output ; ---- ------------------------- -------------------------- ; D0 The return value from Trashed. ; MenuSelect or MenuKey. ; m_apple equ 128 mi_apple_about equ 1 m_file equ 129 mi_file_open equ 99 ; unimplemented mi_file_save equ 99 ; unimplemented mi_file_saveas equ 99 ; unimplemented mi_file_savetf equ 99 ; unimplemented ; --- mi_file_quit equ 1 ; will be 6 when file items are added m_edit equ 130 mi_edit_undo equ 1 ; --- mi_edit_cut equ 3 mi_edit_copy equ 4 mi_edit_paste equ 5 mi_edit_clear equ 6 m_opt equ 131 m_opt_fil equ 1 ; --- m_opt_set_cs equ 3 m_opt_nmax equ 4 _do_menu_command: move.l d0,d1 swap d1 ; Get menu ID cmp #m_apple,d1 ; Check for apple menu bne _dmc_2 compare d0,#mi_apple_about bne @1 jsr _do_help bra _dmc_exit @1: GetItem my_apple_menu,d0,the_da_name OpenDeskAcc the_da_name move (sp)+,d0 SetPort my_window jsr _do_edit_enable bra _dmc_exit _dmc_2: cmp #m_file,d1 bne _dmc_3 compare d0,#mi_file_open bne @2 bra _dmc_exit ; "Open" @2: compare d0,#mi_file_save bne @3 bra _dmc_exit ; "Save" @3: compare d0,#mi_file_saveas bne @4 bra _dmc_exit @4: compare d0,#mi_file_savetf ; "Save As TIFF..." bne @6 set_state _tiff,waiting bra _dmc_exit @6: compare d0,#mi_file_quit bne _dmc_exit set_var quit_flag,#true ; "Quit" bra _dmc_exit _dmc_3: cmp #m_edit,d1 bne _dmc_4 move d0,d3 ; Save menu item # for later subq #1,d0 SystemEdit d0 tst (sp)+ bne _dmc_exit ; SystemEdit returned true -- ignore edit command ; Otherwise, check for copy command compare d3,#mi_edit_copy bne _dmc_exit jsr _do_copy ; Call copy-to-clipboard routine bra _dmc_exit _dmc_4: compare d1,#m_opt ; Options Menu bne _dmc_exit compare d0,#m_opt_fil ; "Show Filament Structure" bne @1 set_state _filaments,waiting bra _dmc_exit @1: compare d0,#m_opt_set_cs ; Set center and size bne @2 jsr _set_coords bra _dmc_exit @2: compare d0,#m_opt_nmax ; Set iteration limit bne _dmc_exit jsr _set_nmax bra _dmc_exit _dmc_exit: HiliteMenu #0 rts ; Subroutine to copy the current picture into the Clipboard. ; ; Reg. Input Output ; ---- ------------------------- -------------------------- ; _do_copy: clr.l -(sp) ; Space for return value _ZeroScrap tst.l (sp)+ ; If result non-zero, error. bne _dc_exit clr.l -(sp) ; Open picture pea pic_rect _OpenPicture move.l (sp)+,a0 ; Save handle for use later lea my_picture,a1 move.l a0,(a1) ClipRect pic_rect ; Need a ClipRect for CopyBits to work ; inside a picture. move.l my_window,a0 ; Do the CopyBits CopyBits PortBits(a0), PortBits(a0), pic_rect, pic_rect, #SrcCopy, #0 _ClosePicture ; Lock the picture's handle move.l my_picture,a0 _HLock tst.l d0 ; Check for error blt _dc_killpic move.l my_picture,a0 _GetHandleSize tst.l d0 ; Check for error blt _dc_killpic clr.l -(sp) ; Space for return value move.l d0,-(sp) ; push length move.l #'PICT',-(sp) ; push type move.l my_picture,a0 ; push POINTER to picture move.l (a0),-(sp) _PutScrap tst.l (sp)+ ; Ignore error -- we want to unlock the picture anyway. ; Unlock the picture's handle move.l my_picture,a0 _HUnlock ; Ignore error -- we would just jump to _dc_killpic anyway. _dc_killpic: move.l my_picture,-(sp) ; Dispose picture _KillPicture move.l my_window,a0 ClipRect portRect(a0) _dc_exit: rts my_picture dc.l 0 the_da_name dc.l 0,0,0,0,0,0,0,0,0,0 dc.l 0,0,0,0,0,0,0,0,0,0 ; Set up the menus. ; my_apple_menu dc.l 0 my_file_menu dc.l 0 my_edit_menu dc.l 0 my_options_menu dc.l 0 _setup_menus: GetMenu #128,my_apple_menu AddResMenu my_apple_menu,#'DRVR' InsertMenu my_apple_menu,#0 DisableItem my_apple_menu,#2 GetMenu #129,my_file_menu InsertMenu my_file_menu,#0 ; DisableItem my_file_menu,#mi_file_open ; DisableItem my_file_menu,#mi_file_save ; DisableItem my_file_menu,#mi_file_saveas ; DisableItem my_file_menu,#mi_file_savetf ; DisableItem my_file_menu,#5 ; "---" line GetMenu #130,my_edit_menu InsertMenu my_edit_menu,#0 DisableItem my_edit_menu,#2 ; "---" line GetMenu #131,my_options_menu InsertMenu my_options_menu,#0 DisableItem my_options_menu,#1 jsr _do_edit_enable rts ; Subroutine to enable/disable menus as appropriate, depending on their ; current state. _do_edit_enable: save_all jsr _da_active ; If a DA is active, enable all items beq @1 EnableItem my_edit_menu,#mi_edit_undo EnableItem my_edit_menu,#mi_edit_cut ; Copy is always enabled. EnableItem my_edit_menu,#mi_edit_paste EnableItem my_edit_menu,#mi_edit_clear bra @2 @1: DisableItem my_edit_menu,#mi_edit_undo DisableItem my_edit_menu,#mi_edit_cut ; Copy is always enabled. DisableItem my_edit_menu,#mi_edit_paste DisableItem my_edit_menu,#mi_edit_clear @2: DrawMenuBar restore_all rts my_event evt_what dc.w 0 evt_message dc.l 0 evt_when dc.l 0 evt_where dc.w 0,0 evt_modifiers dc.w 0 _ee_count dc.w 0 ; Number of events that we'll get in a row before ; falling through to _dispatch. which_window dc.l 0 ; Subroutine to print help info _do_help: clr.l -(sp) move #DLOG_ABOUT,-(sp) ; ID clr.l -(sp) ; make it allocate its own storage moveq.l #-1,d0 ; put it in front move.l d0,-(sp) _GetNewDialog move.l (sp)+,a3 _dh_1: clr.l -(sp) ; filter pea _sc_item_hit ; itemHit _ModalDialog move _sc_item_hit,d0 compare d0,#1 bne _dh_1 move.l a3,-(sp) _DisposDialog rts ; This is the old about... code. ; ; EraseRect pic_rect ; TextFont #20 ; TextSize #18 ; MoveTo #pic_h+10,#pic_v+20 ; DrawString 'Super MANDELZOOM, v. 1.08' ; ; TextSize #10 ; MoveTo #pic_h+10,#pic_v+42 ; DrawString ' Inspired by Dewdney "Mathematical Recreations"' ; MoveTo #pic_h+10,#pic_v+54 ; DrawString 'column, Scientific American, August 1985. Written in' ; MoveTo #pic_h+10,#pic_v+66 ; DrawString 'assembly language with the Apple MDS system. If you' ; MoveTo #pic_h+10,#pic_v+78 ; DrawString 'need a copy of the documentation or the source code, send a' ; MoveTo #pic_h+10,#pic_v+90 ; DrawString 'disk with an SASE (It needs to have two stamps on it) to' ; MoveTo #pic_h+10,#pic_v+102 ; DrawString 'me and I will send it to you as soon as I can.' ; MoveTo #pic_h+10,#pic_v+114 ; DrawString ' This program is public domain, but if you *REALLY*' ; MoveTo #pic_h+10,#pic_v+126 ; DrawString 'like it, a small share-ware donation would be appreciated.' ; MoveTo #pic_h+10,#pic_v+138 ; DrawString '(It took a lot longer to finish than I thought it would!)' ; TextSize #18 ; MoveTo #pic_h+10,#pic_v+164 ; DrawString 'Robert Munafo' ; MoveTo #pic_h+10,#pic_v+183 ; DrawString '(street address)' ; MoveTo #pic_h+10,#pic_v+202 ; DrawString '(city, state, post code)' ; MoveTo #pic_h+10,#pic_v+221 ; DrawString '(telephone number)' ; TextSize #10 ; MoveTo #pic_h+10,#pic_v+245 ; DrawString 'Click mouse to continue.' ; ; jsr _wait_button ; ; move.l #$0000ffff,d0 ; Make sure this mouse click is ignored. ; _FlushEvents ; ; set_state _refill,waiting ; set_state _julia,finished ; rts ; Subroutine to draw or update everything on the screen. ; _update_screen: jsr _do_edit_enable @7: EraseRect screenrect TextFont #20 TextSize #18 move.l title_hndl,a3 ; clr -(sp) ; Find length of title. ; move.l (a3),-(sp) ; _StringWidth ; move #256,d0 ; move (sp)+,d1 ; lsr #1,d1 ; sub d1,d0 ; MoveTo d0,#37 MoveTo #79,#37 move.l (a3),-(sp) _DrawString PenMode #PatCopy ; Draw pic frame PenPat black16 PenSize #1,#1 FrameRect pic_frame lea left_rect,a2 ; Draw all the buttons with labels. move #218,d6 ; Button labels are sequential characters ; starting with this one. moveq #11,d7 ; Loop counter - 12 buttons in all. _rect_loop: FrameRect (a2) MoveTo 2(a2),(a2) QdMove #2,#17 DrawChar d6 lea 8(a2),a2 ; Bump pointer to next rect addq #1,d6 ; Add one to char code dbf d7,_rect_loop FrameRect home_rect clr.l -(sp) move #1008,-(sp) _GetIcon move.l (sp)+,a0 pea home_icon_rect move.l a0,-(sp) _PlotIcon FrameRect zoom_out4_rect clr.l -(sp) move #1007,-(sp) _GetIcon move.l (sp)+,a0 pea zo4_icon_rect move.l a0,-(sp) _PlotIcon FrameRect zoom_in_rect clr.l -(sp) move #1000,-(sp) _GetIcon move.l (sp)+,a0 pea zi_icon_rect move.l a0,-(sp) _PlotIcon FrameRect zoom_out_rect clr.l -(sp) move #1001,-(sp) _GetIcon move.l (sp)+,a0 pea zo_icon_rect move.l a0,-(sp) _PlotIcon FrameRect selzoom_rect clr.l -(sp) move #1003,-(sp) _GetIcon move.l (sp)+,a0 pea selz_icon_rect move.l a0,-(sp) _PlotIcon FrameRect query_rect clr.l -(sp) move #1002,-(sp) _GetIcon move.l (sp)+,a0 pea query_icon_rect move.l a0,-(sp) _PlotIcon FrameRect julia_rect clr.l -(sp) move #1005,-(sp) _GetIcon move.l (sp)+,a0 pea julia_icon_rect move.l a0,-(sp) _PlotIcon FrameRect detail_rect clr.l -(sp) move #1004,-(sp) _GetIcon move.l (sp)+,a0 pea det_icon_rect move.l a0,-(sp) _PlotIcon FrameRect edit_frame TextSize #36 FrameRect ct_1_rect MoveTo #pic_h+409,#73 DrawChar #'1' FrameRect ct_2_rect MoveTo #pic_h+409,#117 DrawChar #'2' FrameRect ct_3_rect MoveTo #pic_h+409,#162 DrawChar #'3' FrameRect ct_4_rect MoveTo #pic_h+409,#206 DrawChar #'4' FrameRect ct_5_rect MoveTo #pic_h+409,#251 DrawChar #'5' FrameRect ct_6_rect MoveTo #pic_h+409,#295 DrawChar #'6' FrameRect mouse_pt_rect test_state _mouse_pt,paused bne @1 InvertRect mouse_pt_rect @1: MoveTo #pic_h+326,#310 TextSize #10 DrawString 'Mouse:' FrameRect qry_data_frame InvertRect which_bits InvertRect which_table InvertRect which_cmd jsr _show_table jsr _show_coords set_state _refill,waiting set_var pending_procs,#0 ; Force _dispatch_ to redraw ; currently-running processes display jsr _da_active ; if no D.A. active, set cursor. bne @2 jsr _do_cursor @2: rts ; Set "ne" condition if there is a D.A. window in front of ours. ; _da_active: clr.l -(sp) ; If our window is in front, set cursor. _FrontWindow move.l (sp)+,a0 compare_l a0,my_window ; Condition code is returned. rts ; Load in all the strings from resource file. _init_strings: clr.l -(sp) ; "Center: " move #1000,-(sp) _GetString lea center_hndl,a0 move.l (sp)+,(a0) clr.l -(sp) ; "Size: " move #1001,-(sp) _GetString lea size_hndl,a0 move.l (sp)+,(a0) clr.l -(sp) ; "Super MANDELZOOM x.xx by Robert P. Munafo" move #1002,-(sp) _GetString lea title_hndl,a0 move.l (sp)+,(a0) rts my_string dc.l 0,0,0,0,0,0,0,0,0,0 center_hndl dc.l 0 size_hndl dc.l 0 title_hndl dc.l 0 ; Draw current center coordinates on screen. _show_coords: TextSize #18 TextFont #20 EraseRect mesg_rect MoveTo #pic_h-3,#317 ; Display current center-of-interest move.l center_hndl,a0 move.l (a0),-(sp) _DrawString move.l pic_center,d0 move.l pic_center+4,d1 jsr _draw_point MoveTo #pic_h-3,#336 ; Display size of current view. move.l size_hndl,a0 move.l (a0),-(sp) _DrawString move.l #$40000000,d0 move zoom_factor,d1 asr.l d1,d0 move num_digits,d4 addq #3,d4 lea my_string,a0 jsr _fixed_to_str lea my_string,a2 move.b #' ',1(a2) DrawString my_string move zoom_factor,d0 ; Put an asterisk after size if we're ; currently zoomed in "too far." compare d0,max_zoom ble @1 DrawChar #'*' @1 DrawString ' ( 2' ; Show how much magnification this is QdMove #0,#-6 TextSize #10 move zoom_factor,d0 jsr _draw_number QdMove #0,#6 TextSize #18 DrawString ' x ) nmax: ' move n_max,d0 jsr _draw_number rts _set_pensize: movem.l d0-d2/a0-a1,-(sp) PenSize d1,d1 movem.l (sp)+,d0-d2/a0-a1 rts ; Set default drawing boundaries. ; _dft_bounds: set_var min_real,#0 set_var max_real,#255 set_var min_imag,#0 set_var max_imag,#255 rts ; Subroutine to convert a point to its 32-bit real and imaginary ; coordinates. ; ; Reg. Input Output ; ---- ------------------------- ------ ; D0.w Horizontal pixel Real coordinate (longint) ; D1.w Vertical pixel Imaginary coordinate (longint) ; _get_coords: move.l d3,-(sp) move zoom_factor,d3 sub #128,d0 ; Range is +-$0000007f lsl #7,d0 ; lsl.w #7 + swap + clr.w = lsl.l #21 (but faster) swap d0 clr d0 ; Range is +-$3f800000 asr.l d3,d0 ; Zoom in means compress the possible range of ; coordinates. D3 is zoom factor, so now range is ; +-$3f800000/(2^zoom) add.l pic_center,d0 sub #128,d1 ; Repeat the same steps (almost) on imag. axis. neg d1 ; Un-reverse direction of vertical axis lsl #7,d1 swap d1 clr d1 asr.l d3,d1 add.l pic_center+4,d1 bne @1 ; If result equal to zero, subtract one. This subq.l #1,d1 ; hopefully makes the filament on the real axis @1: ; invisible. move.l (sp)+,d3 rts ; Subroutine to evaluate a point by setting up all the parameters and ; calling _in_set (or _in_set_32), then looking in the color table to ; find the correct value. This routine takes pixel coordinates, while ; _in_set takes fixed-point coordinates. ; ; Reg. Input Output ; ---- ------------------------- ------ ; D0.w Horizontal coordinate Unchanged. ; D1.w Vertical coordinate Unchanged. ; D2.l (ignored) High word: value of the pixel ; Low byte: modified count (1 to 127) ; _eval_point: tst.b $7003(a0) movem.l d0/d1/d3-d7/a2-a4,-(sp) lea _count_conv,a3 move.l is_proc,a4 jsr _get_coords ; Get point's coordinates jsr (a4) ; Call routine to compute value for this point. move d7,d2 ; Put count in high half of d2. swap d2 compare d7,#1024 ; Map counts greater than 1024 onto 1025 ble @1 move #1025,d7 @1: ; Convert answer to a 7-bit value adda d7,a3 ; (Look up value in _count.conv table.) move.b (a3),d2 ; This is the answer! movem.l (sp)+,d0/d1/d3-d7/a2-a4 rts ; Subroutine to clear the flag bit for each element in the array. ; _ceb_array: movem.l d0-d2,-(sp) move.l #$7f7f7f7f,d1 move.l array_ptr,a0 move.l #array_size,d0 move small_mac,d2 ; Divide size by 4 if small mac. beq @2 lsr.l #2,d0 @2: lsr.l #2,d0 ; Convert byte count to longint count subq #1,d0 @1: and.l d1,(a0)+ dbf d0,@1 movem.l (sp)+,d0-d2 rts ; Subroutine to clear the array. ; _clear_array: tst.b $7004(a0) movem.l d0/a0,-(sp) move.l array_ptr,a0 move.l #array_size,d0 move small_mac,d2 ; Divide size by 4 if small mac. beq @2 lsr.l #2,d0 @2: lsr.l #2,d0 subq #1,d0 @1: clr.l (a0)+ dbf d0,@1 set_var refill_zot,#1 ; If the array is empty, then it's OK to skip ; _idle_mode on update events. movem.l (sp)+,d0/a0 rts ; Subroutine to plot a point on the screen. ; ; Reg. Input Output ; ---- ------------------------- ------ ; D0.w Horizontal coordinate Unchanged. ; D1.w Vertical coordinate Unchanged. ; D2.b Value Unchanged. ; pp_pen penbuf tl_moveto dc.l 0 tl_penpat dc.l 0 tl_lineto dc.l 0 _plot_point: movem.l d0-d6/a0/a1,-(sp) move d0,d4 move d1,d5 move d2,d6 move dt_rect_on,d0 ; If _d_track's rect is running, beq @1 ; we need to undraw it before GetPenState pp_pen ; plotting. PenMode #PatXor PenPat black16 PenSize #1,#1 FrameRect dt_rect SetPenState pp_pen @1: move d4,-(sp) move d5,-(sp) add.l #pic_v_h,(sp) move.l (sp),-(sp) ; Set up point for _LineTo move.l tl_moveto,a0 ; call _MoveTo jsr (a0) cnt_2_shade d6,d6,a0 ; Look up color in table lea pat_table,a0 ; Compute address of pattern to use. asl #3,d6 adda d6,a0 move.l a0,-(sp) move.l tl_penpat,a0 ; call _PenPat jsr (a0) move.l tl_lineto,a0 ; call _LineTo jsr (a0) move dt_rect_on,d0 ; If _d_track's rect is running, beq _pp_end ; we need to redraw it. GetPenState pp_pen PenMode #PatXor PenPat black16 PenSize #1,#1 FrameRect dt_rect SetPenState pp_pen _pp_end: movem.l (sp)+,d0-d6/a0/a1 rts ; Subroutine to store a point's value in the array. ; ; Reg. Input Output ; ---- ------------------------- ------ ; D0.w Horizontal coordinate Unchanged. ; D1.w Vertical coordinate Unchanged. ; D2.b Value to store Unchanged. ; _store_point: tst.b $7005(a0) movem.l d0/d1/d3,-(sp) move small_mac,d3 beq @1 lsr #1,d0 ; divide coords by 2 bcs @3 ; if either was odd, do nothing lsr #1,d1 bcs @3 ext.l d1 ; Row size is different. asl.l #7,d1 bra @2 @1: ext.l d1 asl.l #8,d1 @2: add d0,d1 ; d1 now holds offset into array move.l array_ptr,a0 adda.l d1,a0 move.b d2,(a0) ; Store value. @3: movem.l (sp)+,d0/d1/d3 rts ; Subroutine to get the value of a point from the array. ; ; Reg. Input Output ; ---- ------------------------- ------ ; D0.w Horizontal coordinate Unchanged. ; D1.w Vertical coordinate Unchanged. ; D2.b (ignored) Value ; _get_point: tst.b $7006(a0) movem.l d0/d1/d3,-(sp) move small_mac,d3 ; Divide size by 4 if small mac. beq @1 clr d2 ; Assume we'll return zero. lsr #1,d0 ; divide coords by 2 bcs @3 ; if either was odd, do nothing lsr #1,d1 bcs @3 ext.l d1 ; Row size is different. asl.l #7,d1 bra @2 @1: ext.l d1 asl.l #8,d1 @2: add d0,d1 ; d1 now holds offset into array move.l array_ptr,a0 adda.l d1,a0 move.b (a0),d2 ; Get value. @3: movem.l (sp)+,d0/d1/d3 rts ; Subroutine to draw coordinates of a point on the screen. ; ; Reg. Input Output ; ---- ------------------------- ------ ; D0.w Real coordinate Unchanged. ; D1.w Imaginary coordinate Unchanged. _draw_point: save_all move.l d0,d6 move.l d1,d7 move.l d6,d0 move num_digits,d4 addq #3,d4 lea my_string,a0 asr.l #1,d0 ; _fixed_to_str_ still uses old format. jsr _fixed_to_str DrawString my_string move.l d7,d0 move num_digits,d4 addq #3,d4 lea my_string,a0 asr.l #1,d0 ; _fixed_to_str_ still uses old format. jsr _fixed_to_str DrawString my_string DrawChar #255 restore_all rts ; Subroutine to scroll the array towards the right. Every row of 256 ; bytes must be moved towards top of memory by 32 bytes - this operation ; involves moving 224 bytes or 56 longints per row. ; ; Reg. Use ; ---- ---------------------------------------------------------------- ; D0.l Current piece of data being moved / used to test small_mac ; D1.w Initial offset for A1 (7/8 edge length of array) ; D2.w Initial offset for A2 (edge length of array, 128 or 256) ; D3.w 1/4 of 7/8 edge length (minus 1) ; D4.w 1/4 of 1/8 edge length (minus 1) ; D6.w Inner loop counter ( 55 downto 0 ) ; D7.w Outer loop counter (current_row = 255 downto 0) ; A0 Pointer to beginning of current row ; A1 Pointer to source data ( 220(a0) downto 0(a0) by 4 ) ; A2 Pointer to destination data ( 252(a0) downto 32(a0) by 4) ; _scroll_right: save_all move.l array_ptr,a0 move #224,d1 move #256,d2 moveq #56,d3 moveq #8,d4 move small_mac,d0 ; Divide each param by 2 if small mac. beq @1 lsr #1,d1 lsr #1,d2 lsr #1,d3 lsr #1,d4 @1: subq #1,d3 subq #1,d4 move d2,d7 subq #1,d7 _sr_loop: lea (a0),a1 ; (these will be pre-decremented to their adda.w d1,a1 lea (a0),a2 ; correct starting values) adda.w d2,a2 move d3,d6 _sr_loop2: move.l -(a1),-(a2) ; A1 and A2 will each be decremented before ; being used the first time. dbf d6,_sr_loop2 move d4,d6 ; Now erase the first 32 bytes of the row. _sr_loop3: clr.l -(a2) dbf d6,_sr_loop3 adda.w d2,a0 ; Go to next row dbf d7,_sr_loop restore_all rts ; Subroutine to scroll the array towards the left. Every row of 256 ; bytes must be moved towards bottom of memory by 32 bytes. ; ; Reg. Use ; ---- ---------------------------------------------------------------- ; D0.l Current piece of data being moved/used to test small_mac ; D1.w 1/8 edge length ; D2.w 1/4 of 7/8 edge length (minus 1) ; D3.w 1/4 of 1/8 edge length (minus 1) ; D4.w edge length ; D6.w Inner loop counter ( 55 downto 0 ) ; D7.w Outer loop counter (current_row = 255 downto 0) ; A0 Pointer to beginning of current row ; A1 Pointer to source data ( 32(a0) to 256(a0) by 4 ) ; A2 Pointer to destination data ( 0(a0) to 224(a0) by 4) ; _scroll_left: save_all moveq #32,d1 moveq #56,d2 moveq #8,d3 move #256,d4 move small_mac,d0 ; Divide each param by 2 if small mac. beq @1 lsr.w #1,d1 lsr.w #1,d2 lsr.w #1,d3 lsr.w #1,d4 @1: subq #1,d2 subq #1,d3 move d4,d7 ; set up outer loop subq #1,d7 move.l array_ptr,a0 _sl_loop: lea (a0),a1 adda.w d1,a1 lea (a0),a2 move d2,d6 _sl_loop2: move.l (a1)+,(a2)+ ; A1 and A2 will each be decremented before ; being used the first time. dbf d6,_sl_loop2 move d3,d6 ; Now erase the first 32 bytes of the row. _sl_loop3: clr.l (a2)+ dbf d6,_sl_loop3 adda.w d4,a0 ; Go to next row dbf d7,_sl_loop restore_all rts ; Subroutine to scroll the array up. Rows 32 through 255 of the array ; must be moved towards bottom of memory by 32*256 or 8192 bytes. This ; operation involves 57344 bytes or 14336 longints of data. ; ; Reg. Use ; ---- ---------------------------------------------------------------- ; D0.l Current piece of data being moved. ; D1.w 7/8 number of long words in array ; D2.w 1/8 number of bytes in array ; D3.w 1/8 number of long words in array ; D7.w Loop counter (14336 downto 0) ; A0 Dest pointer ( array_start+0 to array_start+57344 by 32 ) ; A1 Source pointer ( array_start+8192 to array_start+65536 by 32 ) ; _scroll_up: save_all move.l array_ptr,a0 move #14336,d1 move #8192,d2 move #2048,d3 move small_mac,d0 ; Divide size by 4 if small mac. beq @1 lsr.w #2,d1 lsr.w #2,d2 lsr.w #2,d3 @1: subq #1,d1 subq #1,d3 lea (a0),a1 adda.w d2,a1 move d1,d7 _su_loop: move.l (a1)+,d0 move.l d0,(a0)+ dbf d7,_su_loop move d3,d7 ; Now have to clear out remaining 1/8 of array. _su_loop2: clr.l (a0)+ dbf d7,_su_loop2 restore_all rts ; Subroutine to scroll the array down. Rows 0 through 223 of the array ; must be moved towards top of memory by 32*256 or 8192 bytes. ; ; Reg. Use ; ---- ---------------------------------------------------------------- ; D0.l Current piece of data being moved. ; D1.l number of bytes in array. ; D2.l 7/8 number of bytes in array ; D3.w 7/8 number of long words in array (minus 1) ; D4.w 1/8 number of long words in array (minus 1) ; D7.w Loop counter (1791 downto 0) ; A0 Dest pointer ( array_start+65536 downto array_start+8192 by 32 ) ; A1 Source pointer ( array_start+57344 downto array_start+0 by 32 ) ; _scroll_down: save_all move.l #$10000,d1 move.l #$e000,d2 move #14336,d3 move #2048,d4 move small_mac,d0 ; Divide size by 4 if small mac. beq @1 lsr.l #2,d1 lsr.l #2,d2 lsr.w #2,d3 lsr.w #2,d4 @1: subq #1,d3 subq #1,d4 move.l array_ptr,a0 lea (a0),a1 adda.l d1,a0 ; a0 starts at end of array adda.l d2,a1 ; a1 starts 7/8 of the way up move d3,d7 _sd_loop: move.l -(a1),d0 move.l d0,-(a0) dbf d7,_sd_loop move d4,d7 ; Now have to clear out remaining 8192 bytes. _sd_loop2: clr.l -(a0) dbf d7,_sd_loop2 restore_all rts _show_table: save_all moveq #2,d1 jsr _set_pensize PenMode #PatCopy EraseRect edit_rect move #127,d5 ; loop 127 to 0 move #pic_v+254,d7 ; loop pic_v+254 to pic_v _st_loop: move.l color_table,a4 ; Get table entry. adda.w d5,a4 clr d4 move.b (a4),d4 move d4,d6 ; Convert to position add d6,d6 add #edit_h,d6 lea pat_table,a0 ; Set correct pattern asl #3,d4 adda.w d4,a0 move.l a0,-(sp) _PenPat MoveTo #edit_h+35,d7 Line #14,#0 MoveTo d6,d7 ; Draw indicator-mark PenPat black16 Line #0,#0 subq #2,d7 dbf d5,_st_loop restore_all rts edit_rect dc.w pic_v,edit_h,pic_v+256,edit_h+34 edit_frame dc.w pic_v-1,edit_h-1,pic_v+257,edit_h+34+16+1+1 edit_edge dc.w pic_v,edit_h-7,pic_v+256,edit_h-1 _edit_table: save_all moveq #2,d1 jsr _set_pensize PenMode #PatCopy lea old_tr_point,a1 moveq #-1,d0 move.l d0,(a1) _et_loop: GetMouse tr_point ; Get current coordinates of mouse. lea tr_point,a0 lea old_tr_point,a1 move.l (a1),d7 cmp.l (a0),d7 beq _et_mousecheck move.l (a0),(a1) move (a0),d7 move 2(a0),d6 compare d6,#edit_h ; Make sure point is kept within picture. bge @1 move #edit_h,d6 @1: compare d6,#edit_h+33 ble @2 move #edit_h+33,d6 @2: compare d7,#pic_v bge @3 move #pic_v,d7 @3: compare d7,#pic_v+255 ble _et_1 move #pic_v+255,d7 _et_1: move d7,d5 move d6,d4 sub #edit_h,d4 ; Compute value to store asr #1,d4 sub #pic_v,d5 ; Compute address to store in asr #1,d5 move.l color_table,a4 adda.w d5,a4 move.b d4,(a4) ; Store value in table lea pat_table,a0 ; Set correct pattern asl #3,d4 adda.w d4,a0 move.l a0,-(sp) _PenPat and #$fffe,d6 ; Draw horizontal bar in correct pattern and #$fffe,d7 MoveTo #edit_h+35,d7 Line #14,#0 MoveTo #edit_h,d7 ; Draw indicator-mark PenPat white17 Line #32,#0 MoveTo d6,d7 PenPat black16 Line #0,#0 _et_mousecheck: clr -(sp) StillDown tst (sp)+ bne _et_loop _et_end: restore_all rts ; Subroutine to do the dialog box for "Set Coordinates" command. ; _sc_dialog dc.l 0 _sc_item_hit dc.w 0 _sc_type dc.w 0 _sc_item dc.l 0 _sc_rect dc.w 0,0,0,0 _sc_real dc.l 0 _sc_imag dc.l 0 _sc_size dc.l 0 _sc_text dc.l 0,0,0,0,0,0,0,0 dc.l 0,0,0,0,0,0,0,0 dc.l 0,0,0,0,0,0,0,0 dc.l 0,0,0,0,0,0,0,0 dc.l 0,0,0,0,0,0,0,0 dc.l 0,0,0,0,0,0,0,0 dc.l 0,0,0,0,0,0,0,0 dc.l 0,0,0,0,0,0,0,0 ; _set_coords: save_all set_var _ee_count,#3 ; Our dialog causes update events. subq #4,sp move #DLOG_COORDS,-(sp) ; Dialog ID clr.l -(sp) ; window storage moveq.l #-1,d0 ; behind move.l d0,-(sp) _GetNewDialog move.l (sp)+,a0 ; Remember the dialog pointer. lea _sc_dialog,a1 move.l a0,(a1) ; Set the fields of the dialog to the current coordinates. ; move.l #$40000000,d0 move zoom_factor,d1 asr.l d1,d0 moveq #11,d4 lea _sc_text,a0 jsr _fixed_to_str lea _sc_text,a2 move.b #' ',1(a2) moveq #10,d7 jsr _sc_set_one move.l pic_center,d0 ; real asr.l #1,d0 ; _fixed_to_str_ still uses old format. moveq #11,d4 lea _sc_text,a0 jsr _fixed_to_str moveq #4,d7 jsr _sc_set_one move.l pic_center+4,d0 ; imag. asr.l #1,d0 ; _fixed_to_str_ still uses old format. moveq #11,d4 lea _sc_text,a0 jsr _fixed_to_str moveq #7,d7 jsr _sc_set_one ; Select all of the text in the first item. move.l _sc_dialog,-(sp) move #4,-(sp) clr.w -(sp) move.w #1000,-(sp) _SelIText _sc_event: ; Let them do something to the dialog ; clr.l -(sp) ; FilterProc pea _sc_item_hit ; ItemHit _ModalDialog ; Get the current values of each string, and set a flag if any ; is illegal. moveq #4,d7 jsr _sc_do_one lea _sc_real,a0 move.l d0,(a0) move d1,d6 moveq #7,d7 jsr _sc_do_one lea _sc_imag,a0 move.l d0,(a0) or d1,d6 moveq #10,d7 jsr _sc_do_one lea _sc_size,a0 move.l d0,(a0) or d1,d6 ; Test flag - it must be zero (i.e. all three strings valid) for ; OK button to work. tst d6 beq _sc_2 ; Flag not set -- check for both buttons jsr _sc_disable_ok bra _sc_1 _sc_2: jsr _sc_enable_ok ; See if they hit OK. move _sc_item_hit,d0 compare d0,#1 bne _sc_1 bra _sc_doit _sc_1: ; See if they hit Cancel. move _sc_item_hit,d0 compare d0,#2 bne _sc_event ; Not cancel - go back for another event. bra _sc_exit _sc_doit: ; OK hit -- go ahead and do the command. ; Size is treated as unsigned. move.l _sc_size,d0 ; multiply by 1.5 to make values like .99 become more than 1 so ; as to round towards nearest power of two. (approximately) move.l d0,d1 lsr.l #1,d1 add.l d1,d0 ; 31 zoom factor if only one shift to get zero. moveq #31,d1 @2: lsr.l #1,d0 beq @1 subq #1,d1 bra @2 @1: set_var zoom_factor,d1 lea pic_center,a0 ; Set center move.l _sc_real,(a0) move.l _sc_imag,4(a0) jsr _zoom_cmd _sc_exit: move.l _sc_dialog,-(sp) _DisposDialog restore_all rts ; part of _set_coords: gets string for one item in the dialog ; and converts it to a number. ; ; Reg. Input Output ; ---- ------------------------------ ------ ; D0.L ignored. The number (29 bits to right of ; binary point.) ; D1.W ignored. Zero unless format error. ; D7.W Item # of dialog item. ; ; _sc_do_one: move.l _sc_dialog,-(sp) move d7,-(sp) ; Item # pea _sc_type pea _sc_item pea _sc_rect _GetDItem move.l _sc_item,-(sp) pea _sc_text _GetIText lea _sc_text,a0 jsr _string_to_fixed rts ; part of _set_coords: sets string for one item in the dialog. ; ; Reg. Input Output ; ---- ------------------------------ ------ ; D7.W Item # of dialog item. ; ; _sc_set_one: move.l _sc_dialog,-(sp) move d7,-(sp) ; Item # pea _sc_type pea _sc_item pea _sc_rect _GetDItem move.l _sc_item,-(sp) pea _sc_text _SetIText rts ; part of _set_coords: disables the OK button. ; _sc_disable_ok: ; Disable the OK button. move.l _sc_dialog,-(sp) move #1,-(sp) ; Item # pea _sc_type pea _sc_item pea _sc_rect _GetDItem move.l _sc_item,-(sp) move #254,-(sp) _HiliteControl rts ; part of _set_coords: enables the OK button. ; _sc_enable_ok: ; Enable the OK button. move.l _sc_dialog,-(sp) move #1,-(sp) ; Item # pea _sc_type pea _sc_item pea _sc_rect _GetDItem move.l _sc_item,-(sp) clr.w -(sp) _HiliteControl rts ; Subroutine to do the "Set Nmax" command. ; _sn_nmax dc.w 0 ; _set_nmax: save_all set_var _ee_count,#3 ; Our dialog causes update events. subq #4,sp move #DLOG_NMAX,-(sp) ; Dialog ID clr.l -(sp) ; window storage moveq.l #-1,d0 ; behind move.l d0,-(sp) _GetNewDialog move.l (sp)+,a0 ; Remember the dialog pointer. lea _sc_dialog,a1 move.l a0,(a1) ; Set the edittext field to the current n.max ; move n_max,d0 lea _sc_text,a0 jsr _numtostr moveq #4,d7 jsr _sc_set_one ; Select all of the text. move.l _sc_dialog,-(sp) move #4,-(sp) clr.w -(sp) move.w #1000,-(sp) _SelIText _sn_event: ; Let them do something to the dialog ; clr.l -(sp) ; FilterProc pea _sc_item_hit ; ItemHit _ModalDialog ; Get the current values of each string, and set a flag if any ; is illegal. move.l _sc_dialog,-(sp) move #4,-(sp) ; Item # pea _sc_type pea _sc_item pea _sc_rect _GetDItem move.l _sc_item,-(sp) pea _sc_text _GetIText lea _sc_text,a0 jsr _string_to_long lea _sn_nmax,a0 move d0,(a0) tst d1 bne _sn_2 ; Error - check only for cancel. compare_l d0,#50 ; Don't allow less than 50 blt _sn_2 compare_l d0,#9999 ; ...or greater than 9999 bgt _sn_2 jsr _sc_enable_ok ; Check for OK button. move _sc_item_hit,d0 compare d0,#1 bne _sn_1 ; if not, check for Cancel bra _sn_doit _sn_2: ; we jump here if illegal entry in text field jsr _sc_disable_ok _sn_1: ; Check for cancel move _sc_item_hit,d0 compare d0,#2 bne _sn_event ; Not cancel - go back for another event. bra _sn_exit _sn_doit: ; OK hit -- go ahead and do the command. set_var n_max,_sn_nmax jsr _n_max_cmd _sn_exit: move.l _sc_dialog,-(sp) _DisposDialog restore_all rts include MZ-shades end