home *** CD-ROM | disk | FTP | other *** search
Wrap
/** Revision Header * Header built automatically - do not edit! ************* * * (C) Copyright 1991 by Olaf `Olsen' Barthel, all rights reserved * * Name .....: MandelSquare * Created ..: Monday 26-Aug-91 11:20 * Revision .: 3 * * Date Author Comment * ========= ======== ==================== * 16-Sep-91 Olsen Added animation replay feature * 12-Sep-91 Olsen Several enhancements & bug fixes * 26-Aug-91 Olsen Created this file! * ***************************************************************************/ #include "MandelSquare.h" UBYTE VersTag[] = VERSTAG; /* Menu IDs */ enum { MEN_OPEN=17,MEN_SAVE,MEN_SAVEAS,MEN_PRI0,MEN_PRI1,MEN_PRI2,MEN_PLAY,MEN_START,MEN_STOP,MEN_SCROLL,MEN_FRAME,MEN_INCLUDE,MEN_RESOLUTION,MEN_ABOUT,MEN_QUIT, MEN_ZOOM,MEN_CLIP,MEN_RERUN,MEN_PRECISE,MEN_COORDS,MEN_PALETTE,MEN_SPEC,MEN_RUN }; /* Screen width & height must be a multiple of 32. */ #define PLUS 32 /* Dimensions of the coords control panel. */ #define COORDS_WIDTH 256 #define COORDS_HEIGHT 120 /* Dimensions of the palette control panel. */ #define PALETTE_WIDTH 245 #define PALETTE_HEIGHT 53 /* Dimensions of the scroll amount control panel. */ #define SCROLL_WIDTH 175 #define SCROLL_HEIGHT 45 /* Two handy macros to set the window mouse pointer. */ #define SetWait(Window) SetPointer((Window),&Stopwatch[0],16,16,-6,0) #define SetClear(Window) SetPointer((Window),&ClearData[0],1,16,0,0) /* Just to avoid enforcer hits... */ #define BailOut() if(!Gadget) return(NULL); /* In Plot.asm, Iterate.asm & WaitLine.asm */ extern VOID __asm Plot(register __a0 struct BitMap *,register __d0 WORD X,register __d1 WORD Y,register __d2 WORD Colour); extern BYTE __asm Test(register __a0 struct BitMap *,register __d0 WORD X,register __d1 WORD Y); extern BYTE __stdargs Iterate(double RealValue,double ImaginaryValue); extern VOID __asm WaitLine(register __d1 Line); /* In Mandelbrot.c */ VOID __regargs DrawSquare(struct RastPort *RPort,WORD X,WORD Y,WORD Width); VOID __regargs DrawLine(struct RastPort *RPort,UWORD FromX,UWORD FromY,UWORD ToX,UWORD ToY); VOID IterationSetup(VOID); VOID GetScreenPalette(VOID); LONG __saveds CycleServer(VOID); VOID GfxCleanup(VOID); LONG GfxSetup(VOID); VOID __regargs CloseAll(LONG ReturnCode); VOID OpenAll(VOID); VOID __regargs CopyLine(struct BitMap *BitMap,WORD Line); VOID GetTime(VOID); VOID BlockWindow(VOID); VOID ReleaseWindow(VOID); BYTE GetFile(UBYTE *Title,UBYTE *Directory,UBYTE *Name,UBYTE *Buffer,UBYTE *Pattern,BYTE SaveFlag); WORD __stdargs MyEasyRequest(UBYTE *Gadgets,UBYTE *Text,...); VOID FadeTo(struct ViewPort *VPort,UWORD *From,UWORD *To,UBYTE NumColours,UBYTE ToCol,UBYTE FromCol); ULONG __regargs Random(LONG MaxValue); struct Gadget * CreateAllCoordsGadgets(struct Gadget **GadgetArray,struct Gadget **GadgetList,APTR VisualInfo,UWORD TopEdge); struct Gadget * CreateAllPaletteGadgets(struct Gadget **GadgetArray,struct Gadget **GadgetList,APTR VisualInfo,UWORD TopEdge); struct Gadget * CreateAllScrollGadgets(struct Gadget **GadgetArray,struct Gadget **GadgetList,APTR VisualInfo,UWORD TopEdge); VOID InfoText(VOID); WORD CalculateFrames(double MinReal,double MinImaginary,double Size); VOID RunAnim(VOID); VOID StopAnim(VOID); VOID Coords(VOID); VOID Palette(VOID); VOID MaxScrollPanel(VOID); VOID AreaZoom(VOID); VOID Zoom(VOID); VOID HandleEvent(VOID); VOID Mandelbrot(double MinReal,double MinImaginary,double RealStep,double ImaginaryStep,LONG Left,LONG Top,LONG Width,LONG Height); VOID RunMandelbrot(double MinReal,double MaxReal,double MinImaginary,double MaxImaginary,LONG Width,LONG Height); VOID RunAreaMandelbrot(double RealStep,double ImaginaryStep); VOID __stdargs main(VOID); /* In playanim.lib */ VOID ClosePreLoadIFF(VOID); BYTE OpenPreLoadIFF(BPTR file); VOID DeleteBuffer(VOID); BYTE CreateBuffer(VOID); VOID SwapBits(VOID); BYTE PlayAnim(VOID); /* In saveanim.lib */ BYTE AnimOpen(UBYTE *Name,struct ViewPort *VPort,struct RastPort *RPort); BYTE AnimAdd(struct RastPort *RPort); VOID AnimClose(VOID); /* In ReadILBM.c */ struct IFFHandle * __regargs OpenImageFile(UBYTE *Name); VOID __regargs CloseImageFile(struct IFFHandle *Handle); BYTE __regargs ReadImageBody(struct IFFHandle *Handle,struct BitMap *BitMap,struct BitMapHeader *BitMapHeader); BYTE __regargs ReadImageHeader(struct IFFHandle *Handle,ULONG *ViewModes,BYTE *NumCols,UWORD *Colours,struct BitMapHeader *BitMapHeader,struct MandelInfo *MandelInfo); VOID __regargs DeleteBitMap(struct BitMap *BitMap); struct BitMap * __regargs CreateBitMap(BYTE Depth,UWORD Width,UWORD Height); /* In WriteILBM.c */ LONG SaveBitMap(struct BitMap *BitMap,struct ViewPort *VPort,LONG LeftEdge,LONG TopEdge,LONG Width,LONG Height,LONG ParentWidth,LONG ParentHeight,STRPTR Name,struct MandelInfo *MandelInfo); /* Shared and global library data. */ struct IntuitionBase *IntuitionBase; struct GfxBase *GfxBase; struct Library *GadToolsBase; struct Library *IFFParseBase; struct Library *AslBase; struct Library *TimerBase; struct Library *IconBase; /* Timer data. */ struct timerequest *TimeRequest; struct MsgPort *TimePort; /* Window & Screen data. */ struct Screen *Screen; struct Window *Window; struct RastPort *RPort; struct ViewPort *VPort; APTR VisualInfo; struct BitMap *BackupBitMap; struct Menu *Menu; /* Current process and Window Pointer. */ struct Process *ThisProcess; APTR OldPtr; BYTE OldPri; /* Colour cycling data. */ struct Interrupt *CycleInterrupt; BYTE DoCycle = FALSE,Forward,Wheel = 0,Add = 0; /* Some strings. */ UBYTE LastName[256],NameBuffer[256],DummyBuffer[256],AnimSaveName[256],AnimPlayName[256]; /* Table of spectral colours. */ UWORD Table[80]; /* Some more colour tables. */ UWORD ScreenPalette[32],SinPalette[32],WheelPalette[32]; /* Calculation data. */ LONG MaxIteration = 32; double RealStep,ImaginaryStep; double RealWidth = 4.5,ImaginaryHeight = 4.5; double MinReal,MinImaginary; double MainMinReal,MainMinImaginary,MainRealWidth,MainImaginaryHeight; double MaxScroll = 4; double LastSize,LastMinReal,LastMinImaginary; /* Size and position of the screen. */ UWORD AreaLeft,AreaTop,AreaWidth,AreaHeight; /* Various flags. */ BYTE Running = FALSE,NewCoords = FALSE,AreaActive = FALSE,GotClip = FALSE, NewMode = FALSE,Frame = FALSE,Include = TRUE,Faster = TRUE,UseWheel = FALSE, Precise = FALSE,HoldIt = FALSE,AnimRunning = FALSE,FullPicture,AnimOpened = FALSE; /* A range of colour intensities and the colour transition table. */ BYTE Range[32],*Wave; /* The levels of the palette colour sliders. */ BYTE RedLevel = 27,GreenLevel = 22,BlueLevel = 17; /* A global MandelInfo structure to be prepared for the * MAND chunk. */ struct MandelInfo MandelInfo; /* Rendering data. */ LONG Mode = LORES_KEY,Depth = 5,Square = 256; /* The TextFont structure contained in Font.c */ extern struct TextFont DigitFont; /* A single line bitmap whose planes are to be located * in fast ram. */ struct BitMap LineBitMap; /* Global image data. */ struct BitMap *GlobalBitMap; struct BitMapHeader GlobalHeader; ULONG GlobalMode; /* The initial colour table the program uses. */ UWORD ColourTable[32] = { 0x0000,0x0FFF,0x04BE,0x03AE, 0x019D,0x007D,0x016C,0x034B, 0x043A,0x0619,0x0707,0x0916, 0x0A34,0x0B43,0x0C61,0x0D70, 0x0D91,0x0EA3,0x0EB4,0x0FC6, 0x0FD7,0x0FD9,0x0EEA,0x0EEB, 0x0DFC,0x0DFD,0x0CFD,0x0BEE, 0x0AEE,0x09DF,0x07DF,0x06CF }; /* The standard font to be use throughout the * whole program. */ struct TextAttr DefaultFont = { (UBYTE *)"topaz.font", 8, FS_NORMAL, FPF_ROMFONT }; /* Definitions for the pull-down menu used by the program. */ struct NewMenu MandelbrotMenu[] = { { NM_TITLE, "Project", 0 , 0, 0, (APTR)0}, { NM_ITEM, "Open Picture...", "O", 0, 0, (APTR)MEN_OPEN}, { NM_ITEM, "Save Picture", 0 , 0, 0, (APTR)MEN_SAVE}, { NM_ITEM, "Save Picture As...", "S", 0, 0, (APTR)MEN_SAVEAS}, { NM_ITEM, NM_BARLABEL, 0 , 0, 0, (APTR)0}, { NM_ITEM, "Priority", 0 , 0, 0, (APTR)0}, { NM_SUB, "-5", 0 , CHECKIT|MENUTOGGLE,~1, (APTR)MEN_PRI0}, { NM_SUB, " 0", 0 , CHECKIT|CHECKED|MENUTOGGLE,~2, (APTR)MEN_PRI1}, { NM_SUB, "+5", 0 , CHECKIT|MENUTOGGLE,~4, (APTR)MEN_PRI2}, { NM_ITEM, NM_BARLABEL, 0 , 0, 0, (APTR)0}, { NM_ITEM, "Replay Animation...", "!", 0, 0, (APTR)MEN_PLAY}, { NM_ITEM, NM_BARLABEL, 0 , 0, 0, (APTR)0}, { NM_ITEM, "Begin Animation...", "B", 0, 0, (APTR)MEN_START}, { NM_ITEM, "End Animation", "E", 0, 0, (APTR)MEN_STOP}, { NM_ITEM, "Set Scroll Amount...", "A", 0, 0, (APTR)MEN_SCROLL}, { NM_ITEM, "Include Frame", 0 , CHECKIT|MENUTOGGLE,0, (APTR)MEN_FRAME}, { NM_ITEM, "Include Coordinates", 0 , CHECKIT|CHECKED|MENUTOGGLE,0, (APTR)MEN_INCLUDE}, { NM_ITEM, NM_BARLABEL, 0 , 0, 0, (APTR)0}, { NM_ITEM, "Change Resolution", "X", 0, 0, (APTR)MEN_RESOLUTION}, { NM_ITEM, NM_BARLABEL, 0 , 0, 0, (APTR)0}, { NM_ITEM, "About...", "?", 0, 0, (APTR)MEN_ABOUT}, { NM_ITEM, NM_BARLABEL, 0 , 0, 0, (APTR)0}, { NM_ITEM, "Quit...", "Q", 0, 0, (APTR)MEN_QUIT}, { NM_TITLE, "Calculation", 0 , 0, 0, (APTR)0}, { NM_ITEM, "Magnify...", "M", 0, 0, (APTR)MEN_ZOOM}, { NM_ITEM, "Detail...", "D", 0, 0, (APTR)MEN_CLIP}, { NM_ITEM, "Recalculate...", "R", 0, 0, (APTR)MEN_RERUN}, { NM_ITEM, "Precise Calculation", 0 , CHECKIT|MENUTOGGLE,0, (APTR)MEN_PRECISE}, { NM_ITEM, NM_BARLABEL, 0 , 0, 0, (APTR)0}, { NM_ITEM, "Coordinates...", "C", 0, 0, (APTR)MEN_COORDS}, { NM_ITEM, NM_BARLABEL, 0 , 0, 0, (APTR)0}, { NM_ITEM, "Palette...", "P", 0, 0, (APTR)MEN_PALETTE}, { NM_ITEM, "Spectral Colours", 0 , CHECKIT|MENUTOGGLE,0, (APTR)MEN_SPEC}, { NM_ITEM, NM_BARLABEL, 0 , 0, 0, (APTR)0}, { NM_ITEM, "Toggle Calculation", ".", 0, 0, (APTR)MEN_RUN}, { NM_TITLE, "Depth", 0 , 0, 0, (APTR)0}, { NM_ITEM, " 32", "0", CHECKIT|CHECKED, ~ 1, (APTR)5}, { NM_ITEM, " 64", "1", CHECKIT, ~ 2, (APTR)6}, { NM_ITEM, " 128", "2", CHECKIT, ~ 4, (APTR)7}, { NM_ITEM, " 256", "3", CHECKIT, ~ 8, (APTR)8}, { NM_ITEM, " 512", "4", CHECKIT, ~ 16, (APTR)9}, { NM_ITEM, " 1024", "5", CHECKIT, ~ 32, (APTR)10}, { NM_ITEM, " 2048", "6", CHECKIT, ~ 64, (APTR)11}, { NM_ITEM, " 4096", "7", CHECKIT, ~128, (APTR)12}, { NM_ITEM, " 8192", "8", CHECKIT, ~256, (APTR)13}, { NM_ITEM, "16384", "9", CHECKIT, ~512, (APTR)14}, { NM_END, 0, 0 , 0, 0, (APTR)0} }; /* Run-dump of the stopwatch mouse pointer. */ UWORD __chip Stopwatch[(2 + 16) * 2] = { 0x0000,0x0000, 0x0400,0x07C0, 0x0000,0x07C0, 0x0100,0x0380, 0x0000,0x07E0, 0x07C0,0x1FF8, 0x1FF0,0x3FEC, 0x3FF8,0x7FDE, 0x3FF8,0x7FBE, 0x7FFC,0xFF7F, 0x7EFC,0xFFFF, 0x7FFC,0xFFFF, 0x3FF8,0x7FFE, 0x3FF8,0x7FFE, 0x1FF0,0x3FFC, 0x07C0,0x1FF8, 0x0000,0x07E0, 0x0000,0x0000 }; /* Definitions for a clear sprite. */ UWORD __chip ClearData[(2 + 1) * 2] = { 0x0000,0x0000, 0x0000,0x0000, 0x0000,0x0000 }; /* Run-dump of the picture icon image data. */ USHORT Picture1Data[700] = { 0x0000,0x0000,0x0000,0x0000,0x0010,0x0000,0x0000,0x0000, 0x0000,0x0030,0x0000,0x0000,0x0000,0x0000,0x0030,0x0000, 0x0000,0x0000,0x0000,0x0030,0x0000,0x0000,0x0000,0x0000, 0x0030,0x0000,0x0000,0x0000,0x4000,0x0030,0x0000,0x0000, 0x0000,0x0000,0x0030,0x0000,0x0000,0x0000,0x0400,0x0030, 0x0000,0x0000,0x0000,0x1C00,0x0030,0x0000,0x0000,0x0000, 0x0000,0x0030,0x0000,0x0000,0x0000,0x4800,0x0030,0x0000, 0x0000,0x0000,0xC000,0x0030,0x0000,0x0000,0x0005,0x8000, 0x0030,0x0000,0x0000,0x0001,0x0300,0x0030,0x0000,0x0000, 0x0001,0x0200,0x0030,0x0000,0x0000,0x0001,0x0200,0x0030, 0x0000,0x0000,0x0100,0x0020,0x0030,0x0000,0x0000,0x002F, 0x8E80,0x8030,0x0000,0x0000,0x0328,0x0080,0x0030,0x0000, 0x0000,0x0260,0x002E,0xC030,0x0000,0x0000,0x0200,0x0008, 0x8030,0x0000,0x0000,0x0200,0x0000,0x8030,0x0000,0x0000, 0x1600,0x0000,0x0030,0x0000,0x0000,0x1400,0x0000,0x8030, 0x0000,0x2000,0x1000,0x0000,0x0030,0x0000,0x0040,0x3000, 0x0000,0x9030,0x0000,0x4000,0x2000,0x0000,0x3030,0x0000, 0x0080,0x6000,0x0000,0x6030,0x0000,0x0FB0,0x4000,0x0000, 0x0030,0x0000,0x0800,0xC000,0x0000,0x2030,0x0000,0x0800, 0x0000,0x0000,0x6030,0x0000,0x1800,0xC000,0x0000,0x4030, 0x0000,0x3000,0x8000,0x0000,0x4030,0x0001,0x2000,0x8000, 0x0000,0xC030,0x0003,0x6000,0x0000,0x0000,0x8030,0x0F82, 0x0000,0x0000,0x0001,0x0030,0x0020,0x0000,0x0000,0x0000, 0x0030,0x0008,0x0000,0x0000,0x0000,0x0030,0x0000,0x2000, 0x0000,0x0000,0x0030,0x0003,0x8000,0x8000,0x0000,0x4030, 0x0006,0x0000,0x8000,0x0000,0x4030,0x0000,0x4800,0x0000, 0x0000,0x0030,0x0000,0x0802,0x4000,0x0000,0x2030,0x0000, 0x0006,0x4000,0x0000,0x6030,0x0000,0x060C,0x0000,0x0000, 0x0030,0x0000,0x3C78,0x0000,0x0000,0x0030,0x0000,0x20C0, 0x0000,0x0000,0x1030,0x0000,0x2000,0x1800,0x0000,0xF030, 0x0000,0x4000,0x0000,0x0001,0x8030,0x0000,0x0000,0x2000, 0x0001,0x0030,0x0000,0x0000,0x0200,0x0000,0x0030,0x0000, 0x0000,0x0200,0x0000,0x0030,0x0000,0x0000,0x0200,0x0000, 0x4030,0x0000,0x0000,0x0080,0x003E,0xC030,0x0000,0x0000, 0x0180,0x0120,0x8030,0x0000,0x0000,0x0D19,0x8360,0x8030, 0x0000,0x0000,0x0101,0x0200,0x0030,0x0000,0x0000,0x0001, 0x0200,0x0030,0x0000,0x0000,0x0000,0x0000,0x0030,0x0000, 0x0000,0x0000,0x0300,0x0030,0x0000,0x0000,0x0005,0x0E00, 0x0030,0x0000,0x0000,0x0001,0x1800,0x0030,0x0000,0x0000, 0x0000,0x0000,0x0030,0x0000,0x0000,0x0000,0x2000,0x0030, 0x0000,0x0000,0x0000,0x2C00,0x0030,0x0000,0x0000,0x0000, 0x2000,0x0030,0x0000,0x0000,0x0000,0x0000,0x0030,0x0000, 0x0000,0x0000,0x0000,0x0030,0x0000,0x0000,0x0000,0x0000, 0x0030,0x7FFF,0xFFFF,0xFFFF,0xFFFF,0xFFF0, 0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFE0,0xD555,0x5555,0x5555, 0x5555,0x5540,0xD555,0x5555,0x5555,0x5555,0x5540,0xD555, 0x5555,0x5555,0x5555,0x5540,0xD555,0x5555,0x5555,0x5555, 0x5540,0xD555,0x5555,0x5555,0x1555,0x5540,0xD555,0x5555, 0x5555,0x3555,0x5540,0xD555,0x5555,0x5555,0x8155,0x5540, 0xD555,0x5555,0x5555,0x8155,0x5540,0xD555,0x5555,0x5557, 0x0555,0x5540,0xD555,0x5555,0x555C,0x0555,0x5540,0xD555, 0x5555,0x5550,0x0155,0x5540,0xD555,0x5555,0x5558,0x5155, 0x5540,0xD555,0x5555,0x5558,0x5855,0x5540,0xD555,0x5555, 0x7558,0x59D5,0x5540,0xD555,0x5555,0x6DF8,0x7197,0x5540, 0xD555,0x5555,0x6080,0x401E,0x5540,0xD555,0x5555,0x4000, 0x5010,0x5540,0xD555,0x5555,0x5015,0x5500,0x5540,0xD555, 0x5555,0x5115,0x5540,0x1540,0xD555,0x5555,0xF155,0x5554, 0x5540,0xD555,0x5555,0x8155,0x5551,0x5540,0xD555,0xD555, 0x8155,0x5554,0x5540,0xD555,0x1555,0x8155,0x5556,0x5540, 0xD555,0x9755,0x8555,0x5554,0x1540,0xD555,0x1E35,0x0555, 0x5555,0x0540,0xD555,0x0005,0x1555,0x5555,0x0540,0xD555, 0x4005,0x1555,0x5555,0x1540,0xD555,0xC040,0x1555,0x5555, 0x1540,0xD555,0x0550,0x1555,0x5555,0x1540,0xD555,0x8554, 0x5555,0x5555,0x1540,0xD55B,0x8556,0x1555,0x5557,0x1540, 0xD558,0x0554,0x5555,0x5556,0x1540,0xFFF0,0x1555,0x5555, 0x5554,0x1540,0xC000,0x1555,0x5555,0x555D,0x5540,0xD001, 0x5555,0x5555,0x5550,0x5540,0xD541,0xD555,0x5555,0x5555, 0x5540,0xD550,0x1557,0x5555,0x5554,0x5540,0xD558,0x1556, 0x5555,0x5555,0x5540,0xD550,0x1556,0x5555,0x5555,0x1540, 0xD551,0x055C,0x5555,0x5555,0x1540,0xD555,0x05F0,0x5555, 0x5555,0x9540,0xD555,0x4580,0x1555,0x5555,0x1540,0xD555, 0xC000,0x1555,0x5555,0x1540,0xD555,0x8001,0x1555,0x5555, 0x9540,0xD555,0x0005,0x1555,0x5557,0x1540,0xD555,0x1515, 0x8555,0x5556,0x0540,0xD555,0x5555,0x8555,0x555C,0x0540, 0xD555,0x1555,0x0555,0x5550,0x5540,0xD555,0x5555,0x4155, 0x5574,0x5540,0xD555,0x5555,0x5155,0x5564,0x5540,0xD555, 0x5555,0x7155,0x55C6,0x5540,0xD555,0x5555,0x403D,0x5F80, 0x1540,0xD555,0x5555,0x7001,0x5800,0x1540,0xD555,0x5555, 0x4040,0x5014,0x5540,0xD555,0x5555,0x5040,0x5015,0x5540, 0xD555,0x5555,0x5458,0x5955,0x5540,0xD555,0x5555,0x5558, 0x5955,0x5540,0xD555,0x5555,0x5558,0x7155,0x5540,0xD555, 0x5555,0x5550,0x6055,0x5540,0xD555,0x5555,0x5550,0x0155, 0x5540,0xD555,0x5555,0x5554,0x0555,0x5540,0xD555,0x5555, 0x5555,0x8555,0x5540,0xD555,0x5555,0x5555,0x8555,0x5540, 0xD555,0x5555,0x5555,0x1155,0x5540,0xD555,0x5555,0x5555, 0x5555,0x5540,0xD555,0x5555,0x5555,0x5555,0x5540,0xD555, 0x5555,0x5555,0x5555,0x5540,0xD555,0x5555,0x5555,0x5555, 0x5540,0x8000,0x0000,0x0000,0x0000,0x0000 }; /* Definitions for the picture icon image. */ struct Image Picture1Image = { 0,0, 76,70,2, (USHORT *)&Picture1Data[0], 0x03,0x00, (struct Image *)NULL }; /* Tool types for the picture project icon. */ char *PictureToolTypes[] = { "FILETYPE=ILBM", NULL }; /* The name of the project's default tool (will be filled * in later). */ UBYTE DefaultTool[256]; /* Definitions for the picture project icon. */ struct DiskObject PictureIcon = { WB_DISKMAGIC, WB_DISKVERSION, (struct Gadget *)NULL, 0,0, 76,70, 0x0004, 0x0003, 0x0001, (APTR)&Picture1Image, (APTR)NULL, (struct IntuiText *)NULL, NULL, (APTR)NULL, NULL, (APTR)NULL, WBPROJECT, (char *)NULL, PictureToolTypes, NO_ICON_POSITION, NO_ICON_POSITION, (struct DrawerData *)NULL, (char *)NULL, 20000 }; /* Run-dump of the anim icon image data. */ UWORD Anim1Data[700] = { 0x0000,0x0000,0x0000,0x0000,0x0010,0x0000,0x0000,0x0000, 0x0000,0x0030,0x0000,0x0000,0x0000,0x0000,0x0030,0x0000, 0x0000,0x0000,0x0000,0x0030,0x0000,0x0000,0x0000,0x0000, 0x0030,0x0000,0x0000,0x0000,0x4000,0x0030,0x0000,0x0000, 0x0000,0x0000,0x0030,0x0000,0x0000,0x0000,0x0400,0x0030, 0x0000,0x0000,0x0000,0x1C00,0x0030,0x0000,0x0000,0x0000, 0x0000,0x0030,0x0000,0x0000,0x0000,0x4800,0x0030,0x0000, 0x0000,0x0000,0xC000,0x0030,0x0000,0x0000,0x0005,0x8000, 0x0030,0x0000,0x0000,0x0001,0x0300,0x0030,0x0000,0x0000, 0x0001,0x0200,0x0030,0x0000,0x0000,0x0001,0x0200,0x0030, 0x0000,0x0000,0x0100,0x0020,0x0030,0x0000,0x0000,0x002F, 0x8E80,0x8030,0x0000,0x0000,0x0328,0x0080,0x0030,0x0000, 0x0000,0x0260,0x002E,0xC030,0x0003,0xFFD0,0x0200,0x0008, 0x8030,0x0002,0x0010,0x0200,0x0000,0x8030,0x0002,0x0010, 0x1600,0x0000,0x0030,0x0002,0x0010,0x1400,0x0000,0x8030, 0x0002,0x2010,0x1000,0x0000,0x0030,0x0002,0x0010,0x3000, 0x0000,0x9030,0x0002,0x4010,0x2000,0x0000,0x3030,0x0002, 0x0010,0x6000,0x0000,0x6030,0x0002,0x0F10,0x4000,0x0000, 0x0030,0x0002,0x0810,0xC000,0x0000,0x2030,0x0002,0x0810, 0x0000,0x0000,0x6030,0x0002,0x0010,0xC000,0x0000,0x4030, 0x0000,0x0010,0x8000,0x0000,0x4030,0x0003,0xFFF0,0x8000, 0x0000,0xC030,0x0003,0x6000,0x0000,0x0000,0x8030,0x0F82, 0x0000,0x0000,0x0001,0x0030,0x0020,0x0000,0x0000,0x0000, 0x0030,0x0008,0x0000,0x0000,0x0000,0x0030,0x0000,0x2000, 0x0000,0x0000,0x0030,0x0003,0x8000,0x8000,0x0000,0x4030, 0x0006,0x0000,0x8000,0x0000,0x4030,0x0000,0x4800,0x0000, 0x0000,0x0030,0x0000,0x0802,0x4000,0x0000,0x2030,0x0000, 0x0006,0x4000,0x0000,0x6030,0x0000,0x060C,0x0000,0x0000, 0x0030,0x0000,0x3C78,0x0000,0x0000,0x0030,0x0000,0x20C0, 0x0000,0x0000,0x1030,0x0000,0x2000,0x1800,0x0000,0xF030, 0x0000,0x400C,0x0000,0x0C01,0x8030,0x0000,0x001C,0x2000, 0x1E01,0x0030,0x0000,0x001C,0x0200,0x0C00,0x0030,0x0000, 0x001E,0x0200,0x0000,0x0030,0x0000,0x003E,0x0DF0,0x7C1F, 0xF830,0x0000,0x003E,0x0FF8,0xFC1F,0xFC30,0x0000,0x0037, 0x0F18,0x0D1D,0xCC30,0x0000,0x0073,0x0E19,0x8D59,0xCC30, 0x0000,0x0073,0x0E19,0x0C19,0xCC30,0x0000,0x0063,0x8C19, 0x0C19,0xCC30,0x0000,0x00E1,0x8C18,0x0C19,0xCC30,0x0000, 0x00FF,0x8C18,0x0D19,0xCC30,0x0000,0x00FF,0xCC19,0x0C19, 0xCC30,0x0000,0x01C1,0xCC19,0x0C19,0xCC30,0x0000,0x01C0, 0xCC18,0x0C19,0xCC30,0x0000,0x0180,0xEC18,0x2C19,0xCC30, 0x0000,0x0180,0xEC18,0x2C19,0xCC30,0x0000,0x0100,0x6C18, 0x2C18,0x8C30,0x0000,0x0000,0x0000,0x0000,0x0030,0x0000, 0x0000,0x0000,0x0000,0x0030,0x0000,0x0000,0x0000,0x0000, 0x0030,0x7FFF,0xFFFF,0xFFFF,0xFFFF,0xFFF0, 0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFE0,0xD555,0x5555,0x5555, 0x5555,0x5540,0xD555,0x5555,0x5555,0x5555,0x5540,0xD555, 0x5555,0x5555,0x5555,0x5540,0xD555,0x5555,0x5555,0x5555, 0x5540,0xD555,0x5555,0x5555,0x1555,0x5540,0xD555,0x5555, 0x5555,0x3555,0x5540,0xD555,0x5555,0x5555,0x8155,0x5540, 0xD555,0x5555,0x5555,0x8155,0x5540,0xD555,0x5555,0x5557, 0x0555,0x5540,0xD555,0x5555,0x555C,0x0555,0x5540,0xD555, 0x5555,0x5550,0x0155,0x5540,0xD555,0x5555,0x5558,0x5155, 0x5540,0xD555,0x5555,0x5558,0x5855,0x5540,0xD555,0x5555, 0x7558,0x59D5,0x5540,0xD555,0x5555,0x6DF8,0x7197,0x5540, 0xD555,0x5555,0x6080,0x401E,0x5540,0xD555,0x5555,0x4000, 0x5010,0x5540,0xD55F,0xFFC5,0x5015,0x5500,0x5540,0xD558, 0x0005,0x5115,0x5540,0x1540,0xD558,0x0005,0xF155,0x5554, 0x5540,0xD559,0x5545,0x8155,0x5551,0x5540,0xD559,0xD545, 0x8155,0x5554,0x5540,0xD559,0x1545,0x8155,0x5556,0x5540, 0xD559,0x9745,0x8555,0x5554,0x1540,0xD559,0x1E45,0x0555, 0x5555,0x0540,0xD559,0x0045,0x1555,0x5555,0x0540,0xD559, 0x4045,0x1555,0x5555,0x1540,0xD559,0xC040,0x1555,0x5555, 0x1540,0xD559,0x0540,0x1555,0x5555,0x1540,0xD559,0x8544, 0x5555,0x5555,0x1540,0xD559,0xFFC6,0x1555,0x5557,0x1540, 0xD550,0x0004,0x5555,0x5556,0x1540,0xFFF0,0x0005,0x5555, 0x5554,0x1540,0xC000,0x1555,0x5555,0x555D,0x5540,0xD001, 0x5555,0x5555,0x5550,0x5540,0xD541,0xD555,0x5555,0x5555, 0x5540,0xD550,0x1557,0x5555,0x5554,0x5540,0xD558,0x1556, 0x5555,0x5555,0x5540,0xD550,0x1556,0x5555,0x5555,0x1540, 0xD551,0x055C,0x5555,0x5555,0x1540,0xD555,0x05F0,0x5555, 0x5555,0x9540,0xD555,0x4580,0x1555,0x5555,0x1540,0xD555, 0xC000,0x1555,0x5555,0x1540,0xD555,0x8001,0x1555,0x5555, 0x9540,0xD555,0x0005,0x1555,0x5557,0x1540,0xD555,0x1515, 0x8555,0x5556,0x0540,0xD555,0x5551,0x8555,0x515C,0x0540, 0xD555,0x1545,0x0555,0x4150,0x5540,0xD555,0x5551,0x4155, 0x5274,0x5540,0xD555,0x5551,0x5155,0x4D64,0x5540,0xD555, 0x5542,0x7005,0x01C0,0x0540,0xD555,0x5528,0x4D15,0x7D9C, 0xC140,0xD555,0x5528,0x6248,0x8002,0x1140,0xD555,0x5505, 0x4100,0x0005,0x0140,0xD555,0x5550,0x4040,0x4001,0x4140, 0xD555,0x5550,0x4240,0x4141,0x4140,0xD555,0x5502,0x8140, 0x4141,0x4140,0xD555,0x54A0,0x0140,0x6141,0x4140,0xD555, 0x5480,0x0140,0x6041,0x4140,0xD555,0x543F,0x4140,0x0141, 0x4140,0xD555,0x5501,0x0140,0x0141,0x4140,0xD555,0x5554, 0x0141,0x8141,0x4140,0xD555,0x5414,0xA141,0x8141,0x4140, 0xD555,0x5414,0x8141,0x0141,0x4140,0xD555,0x5555,0x6D59, 0x4D58,0x8D40,0xD555,0x5455,0x1145,0x5145,0x5140,0xD555, 0x5555,0x5555,0x5555,0x5540,0xD555,0x5555,0x5555,0x5555, 0x5540,0x8000,0x0000,0x0000,0x0000,0x0000 }; /* Definitions for the anim icon image. */ struct Image Anim1Image = { 0,0, 76,70,2, (UWORD *)&Anim1Data[0], 0x03,0x00, (struct Image *)NULL }; /* Tool types for the anim project icon. */ char *AnimToolTypes[] = { "FILETYPE=ANIM", NULL }; /* Definitions for the anim project icon. */ struct DiskObject AnimIcon = { WB_DISKMAGIC, WB_DISKVERSION, (struct Gadget *)NULL, 23,15, 76,70, 0x0004, 0x0003, 0x0001, (APTR)&Anim1Image, (APTR)NULL, (struct IntuiText *)NULL, NULL, (APTR)NULL, NULL, (APTR)NULL, WBPROJECT, (char *)NULL, AnimToolTypes, NO_ICON_POSITION, NO_ICON_POSITION, (struct DrawerData *)NULL, (char *)NULL, 20000 }; /* DrawSquare(): * * Draws a square rectangle at a given position. */ VOID __regargs DrawSquare(struct RastPort *RPort,WORD X,WORD Y,WORD Width) { Move(RPort,X,Y); Draw(RPort,X + Width - 1,Y); Draw(RPort,X + Width - 1,Y + Width - 1); Draw(RPort,X,Y + Width - 1); Draw(RPort,X,Y); } /* DrawLine(): * * Draw a simple line from a to b. */ VOID __regargs DrawLine(struct RastPort *RPort,UWORD FromX,UWORD FromY,UWORD ToX,UWORD ToY) { Move(RPort,FromX,FromY); Draw(RPort,ToX,ToY); } /* IterationSetup(): * * Sets up the iterations menu, checkmarks the currently * selected number of iterations, uncheckmarks all the * others. */ VOID IterationSetup() { struct MenuItem *Item; Window -> Flags |= WFLG_RMBTRAP; if(Item = ItemAddress(Menu,FULLMENUNUM(2,0,0))) { while(Item) { if((1 << (ULONG)GTMENUITEM_USERDATA(Item)) == MaxIteration) Item -> Flags |= CHECKED; else Item -> Flags &= ~CHECKED; Item = Item -> NextItem; } } Window -> Flags &= ~WFLG_RMBTRAP; } /* GetScreenPalette(): * * Copies the current screen palette to a buffer. */ VOID GetScreenPalette() { WORD i; for(i = 0 ; i < 32 ; i++) ScreenPalette[i] = GetRGB4(VPort -> ColorMap,i); } /* CycleServer(): * * The interrupt server routine which handles the * colour cycling. */ LONG __saveds CycleServer() { STATIC BYTE Count = 0; if(Count++ == 2) { if(DoCycle && !HoldIt) { if(UseWheel) { BYTE AltWheel = Wheel,i; WheelPalette[0] = 0x000; WheelPalette[1] = 0xFFF; if(Forward) { for(i = 2 ; i < 32 ; i++) { WheelPalette[i] = Table[AltWheel]; AltWheel = (AltWheel + 1) % 75; } Wheel = (Wheel + 1) % 75; } else { for(i = 2 ; i < 32 ; i++) { WheelPalette[i] = Table[AltWheel]; AltWheel = (AltWheel + 1) % 75; } if(Wheel) Wheel--; else Wheel = 74; } LoadRGB4(VPort,WheelPalette,1 << Depth); } else { UWORD NewPalette[32]; BYTE i,Wrap = (1 << Depth) - 2,AltAdd = Add; NewPalette[0] = 0x000; NewPalette[1] = 0xFFF; if(Forward) { for(i = 2 ; i < (1 << Depth) ; i++) { NewPalette[i] = SinPalette[AltAdd + 2]; AltAdd = (AltAdd + 1) % Wrap; } Add = (Add + 1) % Wrap; } else { for(i = 2 ; i < (1 << Depth) ; i++) { NewPalette[i] = SinPalette[AltAdd + 2]; AltAdd = (AltAdd + 1) % Wrap; } if(Add) Add--; else Add = Wrap - 1; } LoadRGB4(VPort,NewPalette,1 << Depth); } } Count = 0; } return(0); } /* GfxCleanup(): * * Frees the graphics resources allocated by the * program. */ VOID GfxCleanup() { ThisProcess -> pr_WindowPtr = OldPtr; if(LineBitMap . Planes[0]) { FreeVec(LineBitMap . Planes[0]); LineBitMap . Planes[0] = NULL; } DoCycle = FALSE; Delay(5); if(Screen) ScreenToBack(Screen); if(Window) { ClearMenuStrip(Window); CloseWindow(Window); Window = NULL; } if(Menu) { FreeMenus(Menu); Menu = NULL; } if(VisualInfo) { FreeVisualInfo(VisualInfo); VisualInfo = NULL; } if(Screen) { CloseScreen(Screen); Screen = NULL; } } /* GfxSetup(): * * Allocates the graphics resources the program requires. */ LONG GfxSetup() { struct Rectangle DisplayClip; LONG Differ; WORD i,c = 0,r = 15,g = 0,b = 0; double a,p; BYTE AltWheel = Wheel,Wrap = (1 << Depth) - 2; struct ColorSpec *ColorSpec; a = PI / (double)((1 << Depth) - 2); /* Build a range of colour intensities mapped to the * sine wave amplitude. */ for(p = 0.0, i = 0 ; (p < PI) && (i < (1 << Depth) - 2) ; p += a, i++) Range[i] = (BYTE)(sin(p) * 15 - 0.3); SinPalette[0] = 0x000; SinPalette[1] = 0xFFF; /* Combine all three colour ranges into a single palette. */ for(i = 0 ; i < Wrap ; i++) { SinPalette[2 + i] = Range[(RedLevel + i) % Wrap] << 8; SinPalette[2 + i] |= Range[(GreenLevel + i) % Wrap] << 4; SinPalette[2 + i] |= Range[(BlueLevel + i) % Wrap]; } /* Create the spectral colour table. */ for(i = 0 ; i < 16 ; i++) Table[c++] = (r << 8) | ((g++) << 4) | b; g = 15; r--; for(i = 0 ; i < 15 ; i++) Table[c++] = ((r--) << 8) | (g << 4) | b; r = 0; g--; b++; for(i = 0 ; i < 15 ; i++) Table[c++] = (r << 8) | ((g--) << 4) | (b++); g = 0; b = 15; r++; for(i = 0 ; i < 15 ; i++) Table[c++] = ((r++) << 8) | (g << 4) | b; r = 15; b--; for(i = 0 ; i < 14 ; i++) Table[c++] = (r << 8) | (g << 4) | (b--); /* Set up the spectral colour palette. */ WheelPalette[0] = 0x000; WheelPalette[1] = 0xFFF; for(i = 2 ; i < 32 ; i++) { WheelPalette[i] = Table[AltWheel]; AltWheel = (AltWheel + 1) % 75; } /* Create the colour transition table. */ for(i = 0 ; i < 16384 ; i++) Wave[i] = 2 + (i % ((1 << Depth) - 2)); /* Create the main screen, first query how wide the * current overscan settings allow a screen to be. */ if(!QueryOverscan(Mode,&DisplayClip,OSCAN_TEXT)) return(RETURN_FAIL + 12); /* Open a centered screen. */ Differ = ((DisplayClip . MaxX - DisplayClip . MinX + 1) - Square) >> 1; DisplayClip . MinX += Differ; DisplayClip . MaxX -= Differ; /* Allocate a couple of colour specification structures. */ if(!(ColorSpec = (struct ColorSpec *)AllocVec(sizeof(struct ColorSpec) * ((1 << Depth) + 1),MEMF_PUBLIC|MEMF_CLEAR))) { /* Open a screen with monochrome system imagery. */ if(!(Screen = OpenScreenTags(NULL, SA_Width, Square, SA_Height, Square, SA_DClip, &DisplayClip, SA_Left, DisplayClip . MinX, SA_Depth, Depth, SA_DisplayID, Mode, SA_Font, &DefaultFont, SA_ShowTitle, FALSE, SA_Quiet, TRUE, SA_AutoScroll, TRUE, SA_Behind, TRUE, TAG_END))) return(RETURN_FAIL + 13); } else { /* Set up the colour specifications to open * an entirely black screen. */ for(i = 0 ; i < (1 << Depth) ; i++) ColorSpec[i] . ColorIndex = i; ColorSpec[i] . ColorIndex = -1; /* Open a screen with monochrome system imagery. */ if(!(Screen = OpenScreenTags(NULL, SA_Width, Square, SA_Height, Square, SA_DClip, &DisplayClip, SA_Left, DisplayClip . MinX, SA_Depth, Depth, SA_DisplayID, Mode, SA_Font, &DefaultFont, SA_ShowTitle, FALSE, SA_Quiet, TRUE, SA_AutoScroll, TRUE, SA_Behind, TRUE, SA_Colors, ColorSpec, TAG_END))) { FreeVec(ColorSpec); return(RETURN_FAIL + 13); } else FreeVec(ColorSpec); } /* Set up the remaining data. */ if(!(VisualInfo = GetVisualInfo(Screen,TAG_DONE))) return(RETURN_FAIL + 14); if(!(Menu = CreateMenus(MandelbrotMenu, GTMN_FrontPen, 0, TAG_DONE))) return(RETURN_FAIL + 15); if(!LayoutMenus(Menu, VisualInfo, GTMN_TextAttr, &DefaultFont, TAG_DONE)) return(RETURN_FAIL + 16); if(!(Window = OpenWindowTags(NULL, WA_Width, Screen -> Width, WA_Height, Screen -> Height, WA_Borderless, TRUE, WA_Backdrop, TRUE, WA_IDCMP, IDCMP_MOUSEBUTTONS | IDCMP_MOUSEMOVE | IDCMP_MENUPICK | IDCMP_RAWKEY | IDCMP_VANILLAKEY | IDCMP_MENUVERIFY, WA_RMBTrap, TRUE, WA_CustomScreen,Screen, TAG_END))) return(RETURN_FAIL + 17); /* Create a bitmap which is exactly as wide as the * main screen, but only a single line high. */ InitBitMap(&LineBitMap,Depth,Square,1); /* Allocate space for the bitmap, note that the * bitplanes are to reside in fast ram. */ if(LineBitMap . Planes[0] = AllocVec(LineBitMap . BytesPerRow * LineBitMap . Depth,MEMF_PUBLIC|MEMF_CLEAR|MEMF_FAST)) { for(i = 1 ; i < LineBitMap . Depth ; i++) LineBitMap . Planes[i] = &LineBitMap . Planes[i - 1][LineBitMap . BytesPerRow]; } SetMenuStrip(Window,Menu); OffMenu(Window,FULLMENUNUM(0,9,0)); RPort = &Screen -> RastPort; VPort = &Screen -> ViewPort; SetRast(RPort,0); Window -> Flags &= ~WFLG_RMBTRAP; ThisProcess -> pr_WindowPtr = (APTR)Window; return(0); } /* CloseAll(LONG ReturnCode): * * Close all remaining resources and terminate the program. */ VOID __regargs CloseAll(LONG ReturnCode) { SetTaskPri(ThisProcess,OldPri); if(GlobalBitMap) { DeleteBitMap(GlobalBitMap); GlobalBitMap = NULL; } StopAnim(); if(CycleInterrupt) { DoCycle = FALSE; if(CycleInterrupt -> is_Code) RemIntServer(INTB_VERTB,CycleInterrupt); FreeVec(CycleInterrupt); } if(Wave) FreeVec(Wave); GfxCleanup(); if(BackupBitMap) DeleteBitMap(BackupBitMap); if(TimeRequest) { if(TimeRequest -> tr_node . io_Device) CloseDevice(TimeRequest); DeleteIORequest(TimeRequest); } if(TimePort) DeleteMsgPort(TimePort); if(IconBase) CloseLibrary(IconBase); if(AslBase) CloseLibrary(AslBase); if(IFFParseBase) CloseLibrary(IFFParseBase); if(GadToolsBase) CloseLibrary(GadToolsBase); if(GfxBase) CloseLibrary(GfxBase); if(IntuitionBase) CloseLibrary(IntuitionBase); exit(ReturnCode); } /* OpenAll(): * * Open libraries and other data which does not * require changing when the display modes are * altered. */ VOID OpenAll() { ThisProcess = (struct Process *)FindTask(NULL); OldPri = SetTaskPri(ThisProcess,0); OldPtr = ThisProcess -> pr_WindowPtr; if(!(IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",37))) CloseAll(RETURN_FAIL + 0); if(!(GfxBase = (struct GfxBase *)OpenLibrary("graphics.library",37))) CloseAll(RETURN_FAIL + 1); if(!(GadToolsBase = OpenLibrary("gadtools.library",37))) CloseAll(RETURN_FAIL + 2); if(!(IFFParseBase = OpenLibrary("iffparse.library",37))) CloseAll(RETURN_FAIL + 3); if(!(AslBase = OpenLibrary("asl.library",37))) CloseAll(RETURN_FAIL + 4); if(!(TimePort = (struct MsgPort *)CreateMsgPort())) CloseAll(RETURN_FAIL + 5); if(!(TimeRequest = (struct timerequest *)CreateIORequest(TimePort,sizeof(struct timerequest)))) CloseAll(RETURN_FAIL + 6); if(OpenDevice(TIMERNAME,UNIT_VBLANK,TimeRequest,0)) CloseAll(RETURN_FAIL + 7); if(!(BackupBitMap = CreateBitMap(5,25 * 8,8))) CloseAll(RETURN_FAIL + 8); if(!(CycleInterrupt = AllocVec(sizeof(struct Interrupt),MEMF_PUBLIC|MEMF_CLEAR))) CloseAll(RETURN_FAIL + 9); if(!(Wave = (BYTE *)AllocVec(16384,MEMF_PUBLIC|MEMF_CLEAR))) CloseAll(RETURN_FAIL + 10); if(!(IconBase = OpenLibrary("icon.library",37))) CloseAll(RETURN_FAIL + 11); TimerBase = &TimeRequest -> tr_node . io_Device -> dd_Library; CycleInterrupt -> is_Node . ln_Name = "Mandelbrot Cycling"; CycleInterrupt -> is_Node . ln_Type = NT_INTERRUPT; CycleInterrupt -> is_Code = (APTR)CycleServer; AddIntServer(INTB_VERTB,CycleInterrupt); } /* CopyLine(struct BitMap *BitMap,WORD Line): * * Copies the contents of the single line bitmap to a given * line on screen. */ VOID __regargs CopyLine(struct BitMap *BitMap,WORD Line) { WORD i; Line *= BitMap -> BytesPerRow; for(i = 0 ; i < BitMap -> Depth ; i++) CopyMemQuick(BitMap -> Planes[i],&RPort -> BitMap -> Planes[i][Line],BitMap -> BytesPerRow); } /* GetTime(): * * Asks the timer.device for the current system time. */ VOID GetTime() { TimeRequest -> tr_node . io_Command = TR_GETSYSTIME; DoIO(TimeRequest); } /* BlockWindow(): * * Blocks the menu bar of the window and sets the busy * mouse pointer. */ VOID BlockWindow() { HoldIt = TRUE; SetWait(Window); Window -> Flags |= WFLG_RMBTRAP; } /* ReleaseWindow(): * * Reenables the menu bar of the window and resets the * mouse pointer to the default mouse pointer. */ VOID ReleaseWindow() { ClearPointer(Window); Window -> Flags &= ~WFLG_RMBTRAP; HoldIt = FALSE; } /* GetFile(): * * Get a file name using the asl.library file requester. */ BYTE GetFile(UBYTE *Title,UBYTE *Directory,UBYTE *Name,UBYTE *Buffer,UBYTE *Pattern,BYTE SaveFlag) { struct FileRequester *AslFileRequest; BYTE Result = FALSE; LONG Flags; if(!Directory[0]) NameFromLock(ThisProcess -> pr_CurrentDir,Directory,256); if(Pattern) { Flags = FILF_PATGAD; if(!Pattern[0]) Pattern = "~(#?.info)"; } else { Flags = 0; Pattern = "~(#?.info)"; } if(SaveFlag) Flags |= FILF_SAVE; if(AslFileRequest = (struct FileRequester *)AllocAslRequestTags(ASL_FileRequest, ASL_Window, Window, ASL_File, Name, ASL_Dir, Directory, ASL_Hail, Title, ASL_FuncFlags, Flags, ASL_Pattern, Pattern, ASL_OKText, SaveFlag ? "Save" : "Open", ASL_LeftEdge, 0, ASL_TopEdge, 0, ASL_Width, Screen -> Width, ASL_Height, Screen -> Height, TAG_DONE)) { if(RequestFile(AslFileRequest)) { if(AslFileRequest -> rf_File[0]) { strcpy(Buffer,AslFileRequest -> rf_Dir); AddPart((UBYTE *)Buffer,(UBYTE *)AslFileRequest -> rf_File,256); Result = TRUE; } } } FreeFileRequest(AslFileRequest); return(Result); } /* MyEasyRequest(): * * EasyRequestArgs stub routine. */ WORD __stdargs MyEasyRequest(UBYTE *Gadgets,UBYTE *Text,...) { struct EasyStruct Easy; WORD Result; ULONG IDCMP = NULL; va_list VarArgs; Easy . es_StructSize = sizeof(struct EasyStruct); Easy . es_Flags = NULL; Easy . es_Title = (UBYTE *)"MandelSquare"; Easy . es_TextFormat = (UBYTE *)Text; Easy . es_GadgetFormat = (UBYTE *)Gadgets; va_start(VarArgs,Text); Result = EasyRequestArgs(Window,&Easy,&IDCMP,VarArgs); va_end(VarArgs); return(Result); } /* FadeTo(): * * Fades from one colour table to another. */ VOID FadeTo(struct ViewPort *VPort,UWORD *From,UWORD *To,UBYTE NumColours,UBYTE ToCol,UBYTE FromCol) { UWORD FromTemp[32]; UWORD ToTemp[32]; UBYTE i,j; BYTE R1,G1,B1,R2,G2,B2; if(NumColours > 32) NumColours = 32; if(From) CopyMem(&From[0],&FromTemp[0],sizeof(UWORD) * NumColours); else memset(&FromTemp[0],FromCol,sizeof(UWORD) * NumColours); if(To) CopyMem(&To[0],&ToTemp[0],sizeof(UWORD) * NumColours); else memset(&ToTemp[0],ToCol,sizeof(UWORD) * NumColours); for(j = 0 ; j < 16 ; j++) { for(i = 0 ; i < NumColours ; i++) { R1 = (FromTemp[i] >> 8) & 0xF; G1 = (FromTemp[i] >> 4) & 0xF; B1 = (FromTemp[i]) & 0xF; R2 = (ToTemp[i] >> 8) & 0xF; G2 = (ToTemp[i] >> 4) & 0xF; B2 = (ToTemp[i]) & 0xF; if(R1 > R2) R1--; if(G1 > G2) G1--; if(B1 > B2) B1--; if(R1 < R2) R1++; if(G1 < G2) G1++; if(B1 < B2) B1++; FromTemp[i] = (R1 << 8) | (G1 << 4) | B1; } Delay(2); LoadRGB4(VPort,FromTemp,NumColours); } } /* Random(LONG MaxValue) * * Small random number generator. */ ULONG __regargs Random(LONG MaxValue) { STATIC ULONG RandomSeed = 213567657; RandomSeed = RandomSeed * custom . vhposr + 8754331; return(RandomSeed % MaxValue); } /* CreateAllCoordsGadgets(): * * Creates all gadgets required by the coordinates control panel. */ struct Gadget * CreateAllCoordsGadgets(struct Gadget **GadgetArray,struct Gadget **GadgetList,APTR VisualInfo,UWORD TopEdge) { struct Gadget *Gadget; struct NewGadget NewGadget; UWORD Counter = 0; UBYTE Buffer[40]; if(Gadget = CreateContext(GadgetList)) { NewGadget . ng_Width = COORDS_WIDTH - 20; NewGadget . ng_Height = 14; NewGadget . ng_GadgetText = "Real Part (X-Coordinate)"; NewGadget . ng_TextAttr = &DefaultFont; NewGadget . ng_VisualInfo = VisualInfo; NewGadget . ng_GadgetID = Counter; NewGadget . ng_Flags = PLACETEXT_ABOVE; NewGadget . ng_LeftEdge = 10; NewGadget . ng_TopEdge = 2 + TopEdge + 14; sprintf(Buffer,"%g",MinReal); GadgetArray[Counter++] = Gadget = CreateGadget(STRING_KIND,Gadget,&NewGadget, GTST_MaxChars, 40, GTST_String, Buffer, STRINGA_Justification, STRINGCENTER, TAG_DONE); BailOut(); NewGadget . ng_GadgetText = "Imaginary Part (Y-Coordinate)"; NewGadget . ng_GadgetID = Counter; NewGadget . ng_TopEdge = Gadget -> TopEdge + Gadget -> Height + 4 + 15; sprintf(Buffer,"%g",MinImaginary); BailOut(); GadgetArray[Counter++] = Gadget = CreateGadget(STRING_KIND,Gadget,&NewGadget, GTST_MaxChars, 40, GTST_String, Buffer, STRINGA_Justification, STRINGCENTER, TAG_DONE); NewGadget . ng_GadgetText = "Width & Height"; NewGadget . ng_GadgetID = Counter; NewGadget . ng_TopEdge = Gadget -> TopEdge + Gadget -> Height + 4 + 15; sprintf(Buffer,"%g",RealWidth); BailOut(); GadgetArray[Counter++] = Gadget = CreateGadget(STRING_KIND,Gadget,&NewGadget, GTST_MaxChars, 40, GTST_String, Buffer, STRINGA_Justification, STRINGCENTER, TAG_DONE); NewGadget . ng_Width = 68; NewGadget . ng_Height = 12; NewGadget . ng_GadgetText = "Accept"; NewGadget . ng_GadgetID = Counter; NewGadget . ng_Flags = 0; NewGadget . ng_TopEdge = COORDS_HEIGHT - 3 - NewGadget . ng_Height; BailOut(); GadgetArray[Counter++] = Gadget = CreateGadget(BUTTON_KIND,Gadget,&NewGadget, TAG_DONE); NewGadget . ng_GadgetText = "Cancel"; NewGadget . ng_GadgetID = Counter; NewGadget . ng_LeftEdge = COORDS_WIDTH - 10 - NewGadget . ng_Width; BailOut(); GadgetArray[Counter++] = Gadget = CreateGadget(BUTTON_KIND,Gadget,&NewGadget, TAG_DONE); } return(Gadget); } /* CreateAllPaletteGadgets(): * * Creates all gadgets required by the palette control panel. */ struct Gadget * CreateAllPaletteGadgets(struct Gadget **GadgetArray,struct Gadget **GadgetList,APTR VisualInfo,UWORD TopEdge) { struct Gadget *Gadget; struct NewGadget NewGadget; UWORD Counter = 0; if(Gadget = CreateContext(GadgetList)) { NewGadget . ng_Width = 60; NewGadget . ng_Height = 12; NewGadget . ng_GadgetText = "Red "; NewGadget . ng_TextAttr = &DefaultFont; NewGadget . ng_VisualInfo = VisualInfo; NewGadget . ng_GadgetID = Counter; NewGadget . ng_Flags = PLACETEXT_LEFT; NewGadget . ng_LeftEdge = 18 + 8 * strlen(NewGadget . ng_GadgetText); NewGadget . ng_TopEdge = 1 + TopEdge; GadgetArray[Counter++] = Gadget = CreateGadget(SLIDER_KIND,Gadget,&NewGadget, GTSL_Min, 0, GTSL_Max, (1 << Depth) - 3, GTSL_Level, RedLevel, TAG_DONE); NewGadget . ng_GadgetText = "Green"; NewGadget . ng_GadgetID = Counter; NewGadget . ng_TopEdge = Gadget -> TopEdge + Gadget -> Height + 3; BailOut(); GadgetArray[Counter++] = Gadget = CreateGadget(SLIDER_KIND,Gadget,&NewGadget, GTSL_Min, 0, GTSL_Max, (1 << Depth) - 3, GTSL_Level, GreenLevel, TAG_DONE); NewGadget . ng_GadgetText = "Blue "; NewGadget . ng_GadgetID = Counter; NewGadget . ng_TopEdge = Gadget -> TopEdge + Gadget -> Height + 3; BailOut(); GadgetArray[Counter++] = Gadget = CreateGadget(SLIDER_KIND,Gadget,&NewGadget, GTSL_Min, 0, GTSL_Max, (1 << Depth) - 3, GTSL_Level, BlueLevel, TAG_DONE); } return(Gadget); } /* CreateAllScrollGadgets(): * * Creates all the gadgets required by the scroll amount * control panel. */ struct Gadget * CreateAllScrollGadgets(struct Gadget **GadgetArray,struct Gadget **GadgetList,APTR VisualInfo,UWORD TopEdge) { struct Gadget *Gadget; struct NewGadget NewGadget; UWORD Counter = 0; if(Gadget = CreateContext(GadgetList)) { NewGadget . ng_Width = 44; NewGadget . ng_Height = 14; NewGadget . ng_GadgetText = "Scroll Amount"; NewGadget . ng_TextAttr = &DefaultFont; NewGadget . ng_VisualInfo = VisualInfo; NewGadget . ng_GadgetID = Counter; NewGadget . ng_Flags = 0; NewGadget . ng_LeftEdge = (strlen(NewGadget . ng_GadgetText) + 2) * 8 + 1; NewGadget . ng_TopEdge = 1 + TopEdge; GadgetArray[Counter++] = Gadget = CreateGadget(INTEGER_KIND,Gadget,&NewGadget, GTIN_MaxChars, 3, GTIN_Number, (LONG)MaxScroll, TAG_DONE); NewGadget . ng_Width = 52; NewGadget . ng_Height = 12; NewGadget . ng_GadgetText = "Accept"; NewGadget . ng_GadgetID = Counter; NewGadget . ng_Flags = 0; NewGadget . ng_LeftEdge = 10; NewGadget . ng_TopEdge = SCROLL_HEIGHT - 3 - NewGadget . ng_Height; BailOut(); GadgetArray[Counter++] = Gadget = CreateGadget(BUTTON_KIND,Gadget,&NewGadget, TAG_DONE); NewGadget . ng_GadgetText = "Cancel"; NewGadget . ng_GadgetID = Counter; NewGadget . ng_LeftEdge = SCROLL_WIDTH - 10 - NewGadget . ng_Width; BailOut(); GadgetArray[Counter++] = Gadget = CreateGadget(BUTTON_KIND,Gadget,&NewGadget, TAG_DONE); } return(Gadget); } /* InfoText(): * * Renders a small position and size information text into * the left bottom corner of the screen. */ VOID InfoText() { struct TextFont *OldFont; UBYTE Buffer[80]; WORD i; struct RastPort *RPort = Window -> RPort; BlockWindow(); OldFont = RPort -> Font; SetFont(RPort,&DigitFont); SetAPen(RPort,1); sprintf(Buffer,"(/%1.04e )/%1.04e %1.04e*%1.04e",MinReal,MinImaginary,RealWidth,ImaginaryHeight); for(i = 0 ; i < strlen(Buffer) ; i++) { if(Buffer[i] == 'e') Buffer[i] = '$'; } SetDrMd(RPort,JAM1); Move(RPort,1,Window -> Height - 2); Text(RPort,Buffer,strlen(Buffer)); SetFont(RPort,OldFont); SetDrMd(RPort,JAM2); } /* CalculateFrames(): * * Precalculates the number of pictures to be generated * when zooming to a specific location in the Mandelbrot * set. */ WORD CalculateFrames(double MinReal,double MinImaginary,double Size) { double Data[3],Div,Value,FourPixels,GlobalSize,GlobalMinReal,GlobalMinImaginary; BYTE i,Render; WORD Count = 0; GlobalSize = LastSize; GlobalMinReal = LastMinReal; GlobalMinImaginary = LastMinImaginary; do { Data[0] = GlobalSize - Size; Data[1] = MinReal - GlobalMinReal; Data[2] = MinImaginary - GlobalMinImaginary; Value = fabs(Data[0]); Render = FALSE; for(i = 0 ; i < 3 ; i++) { if(Data[i] != 0.0) Render = TRUE; if(fabs(Data[i]) > Value) Value = fabs(Data[i]); } if(Render) { FourPixels = MaxScroll * (GlobalSize / (double)Screen -> Width); Div = Value; if(Value > FourPixels) Value = FourPixels; Div /= Value; GlobalSize -= Data[0] / Div; GlobalMinReal += Data[1] / Div; GlobalMinImaginary += Data[2] / Div; Count++; } } while(Render); return(Count); } /* CheckAbort(): * * Provides a safe callback routine to allow the anim * player to check for a user abort. */ BYTE CheckAbort() { if(SetSignal(0,0) & (1 << Window -> UserPort -> mp_SigBit)) { struct IntuiMessage *Massage; ULONG Class,Code; while(Massage = (struct IntuiMessage *)GT_GetIMsg(Window -> UserPort)) { Class = Massage -> Class; Code = Massage -> Code; GT_ReplyIMsg(Massage); if((Class == IDCMP_MOUSEBUTTONS && !(Code & IECODE_UP_PREFIX)) || Class == IDCMP_VANILLAKEY) return(TRUE); } } else return(FALSE); } /* ReplayAnim(): * * Loads and replays an animation file. */ BYTE ReplayAnim() { BYTE Success = FALSE; UBYTE *DummyChar; strcpy(DummyBuffer,AnimPlayName); DummyChar = PathPart(DummyBuffer); *DummyChar = 0; if(GetFile("Replay Animation",DummyBuffer,FilePart(AnimPlayName),DummyBuffer,"~(#?.info)",FALSE)) { BPTR File; if(File = Open(DummyBuffer,MODE_OLDFILE)) { if(CreateBuffer()) { if(OpenPreLoadIFF(File)) { strcpy(AnimPlayName,DummyBuffer); SetClear(Window); SwapBits(); Success = TRUE; while(PlayAnim()); ClosePreLoadIFF(); } else MyEasyRequest("Continue","Could not read file\n%s.",FilePart(DummyBuffer)); SetWait(Window); DeleteBuffer(); } else MyEasyRequest("Continue","Not enough memory for\ndisplay buffer."); Close(File); } else MyEasyRequest("Continue","Error opening file\n%s.",FilePart(DummyBuffer)); } return(Success); } /* RunAnim(): * * This routine calculates the single animation frames and * stores them in the anim file. */ VOID RunAnim() { double Data[3],Value,Div,SomePixels; BYTE Render,i; LastSize = RealWidth; LastMinReal = MinReal; LastMinImaginary = MinImaginary; NewCoords = FALSE; while(AnimRunning && !NewCoords) Zoom(); /* Coords();*/ if(NewCoords) { if(!AnimOpened) { UBYTE *DummyChar; AnimRunning = FALSE; strcpy(DummyBuffer,AnimSaveName); DummyChar = PathPart(DummyBuffer); *DummyChar = 0; if(GetFile("Begin Animation",DummyBuffer,FilePart(AnimSaveName),DummyBuffer,"~(#?.info)",FALSE)) { if(Frame) { WORD X,Y,Width; double Pixel; Pixel = LastSize / (double)Screen -> Width; X = (WORD)(fabs(LastMinReal - MainMinReal) / Pixel); Y = (WORD)(fabs(LastMinImaginary - MainMinImaginary) / Pixel); Width = (WORD)(MainRealWidth / Pixel); if(X || Y || Width != Screen -> Width) { SetAPen(Window -> RPort,1); DrawSquare(Window -> RPort,X,Y,Width); } } if(Include) InfoText(); if(AnimOpened = AnimOpen(DummyBuffer,VPort,RPort)) { if(!ThisProcess -> pr_CLI) PutDiskObject(DummyBuffer,&AnimIcon); OffMenu(Window,FULLMENUNUM(0, 0,0)); OffMenu(Window,FULLMENUNUM(0, 1,0)); OffMenu(Window,FULLMENUNUM(0, 2,0)); OffMenu(Window,FULLMENUNUM(0, 8,0)); OnMenu (Window,FULLMENUNUM(0, 9,0)); OffMenu(Window,FULLMENUNUM(0,11,0)); OffMenu(Window,FULLMENUNUM(0,12,0)); OffMenu(Window,FULLMENUNUM(0,14,0)); OffMenu(Window,FULLMENUNUM(1, 0,0)); OffMenu(Window,FULLMENUNUM(1, 1,0)); OffMenu(Window,FULLMENUNUM(1, 2,0)); OffMenu(Window,FULLMENUNUM(1, 5,0)); OffMenu(Window,FULLMENUNUM(1, 7,0)); OffMenu(Window,FULLMENUNUM(1, 8,0)); OffMenu(Window,FULLMENUNUM(1,10,0)); AnimRunning = TRUE; strcpy(AnimSaveName,DummyBuffer); } } } if(AnimRunning) { RealWidth = LastSize; ImaginaryHeight = LastSize; MinReal = LastMinReal; MinImaginary = LastMinImaginary; LastSize = MainRealWidth; LastMinReal = MainMinReal; LastMinImaginary = MainMinImaginary; do { Data[0] = RealWidth - LastSize; Data[1] = LastMinReal - MinReal; Data[2] = LastMinImaginary - MinImaginary; Value = fabs(Data[0]); Render = FALSE; for(i = 0 ; i < 3 ; i++) { if(Data[i] != 0.0) Render = TRUE; if(fabs(Data[i]) > Value) Value = fabs(Data[i]); } if(Render) { SomePixels = MaxScroll * (RealWidth / (double)Screen -> Width); Div = Value; if(Value > SomePixels) Value = SomePixels; Div /= Value; RealWidth -= Data[0] / Div; ImaginaryHeight -= Data[0] / Div; MinReal += Data[1] / Div; MinImaginary += Data[2] / Div; RealStep = RealWidth / (double)Window -> Width; ImaginaryStep = ImaginaryHeight / (double)Window -> Height; AreaActive = FALSE; Running = TRUE; FullPicture = TRUE; SetRast(Window -> RPort,0); Mandelbrot(MinReal,MinImaginary,RealStep,ImaginaryStep,0,0,Window -> Width >> 1,Window -> Height >> 1); Mandelbrot(MinReal,MinImaginary,RealStep,ImaginaryStep,Window -> Width >> 1,0,Window -> Width >> 1,Window -> Height >> 1); Mandelbrot(MinReal,MinImaginary,RealStep,ImaginaryStep,0,Window -> Height >> 1,Window -> Width >> 1,Window -> Height >> 1); Mandelbrot(MinReal,MinImaginary,RealStep,ImaginaryStep,Window -> Width >> 1,Window -> Height >> 1,Window -> Width >> 1,Window -> Height >> 1); if(FullPicture) { BlockWindow(); if(Frame) { WORD X,Y,Width; double Pixel; Pixel = RealWidth / (double)Screen -> Width; X = (WORD)(fabs(MinReal - LastMinReal) / Pixel); Y = (WORD)(fabs(MinImaginary - LastMinImaginary) / Pixel); Width = (WORD)(LastSize / Pixel); if(X || Y || Width != Screen -> Width) { SetAPen(Window -> RPort,1); DrawSquare(Window -> RPort,X,Y,Width); } } if(Include) InfoText(); AnimAdd(RPort); ReleaseWindow(); } if(!AnimRunning) break; } } while(Render); if(!Render) { MoveScreen(Screen,0,-Screen -> TopEdge); ScreenToFront(Screen); ActivateWindow(Window); Delay(10); DisplayBeep(Screen); } } AreaActive = FALSE; Running = FALSE; } else StopAnim(); } /* StopAnim(): * * Stops the animation generation. */ VOID StopAnim() { if(AnimRunning) { AnimRunning = FALSE; OnMenu (Window,FULLMENUNUM(0, 0,0)); OnMenu (Window,FULLMENUNUM(0, 1,0)); OnMenu (Window,FULLMENUNUM(0, 2,0)); OnMenu (Window,FULLMENUNUM(0, 8,0)); OffMenu(Window,FULLMENUNUM(0, 9,0)); OnMenu (Window,FULLMENUNUM(0,11,0)); OnMenu (Window,FULLMENUNUM(0,12,0)); OnMenu (Window,FULLMENUNUM(0,14,0)); OnMenu (Window,FULLMENUNUM(1, 0,0)); OnMenu (Window,FULLMENUNUM(1, 1,0)); OnMenu (Window,FULLMENUNUM(1, 2,0)); OnMenu (Window,FULLMENUNUM(1, 5,0)); OnMenu (Window,FULLMENUNUM(1, 7,0)); OnMenu (Window,FULLMENUNUM(1, 8,0)); OnMenu (Window,FULLMENUNUM(1,10,0)); AnimClose(); AnimOpened = FALSE; } } /* Coords(): * * This routine implements the coordinates control panel. */ VOID Coords() { struct Gadget *GadgetList = NULL; struct Gadget *GadgetArray[5]; struct Window *CoordsWindow; double TempMinReal,TempMinImaginary, TempRealWidth,TempImaginaryHeight; BYTE MadeChanges = FALSE; TempMinReal = MinReal; TempMinImaginary = MinImaginary; TempRealWidth = RealWidth; TempImaginaryHeight = ImaginaryHeight; if(CreateAllCoordsGadgets(&GadgetArray[0],&GadgetList,VisualInfo,Screen -> WBorTop + Screen -> Font -> ta_YSize + 1)) { if(CoordsWindow = OpenWindowTags(NULL, WA_Width, COORDS_WIDTH, WA_Height, COORDS_HEIGHT, WA_Top, (Screen -> Height - COORDS_HEIGHT) >> 1, WA_Left, (Screen -> Width - COORDS_WIDTH) >> 1, WA_Activate, TRUE, WA_DragBar, FALSE, WA_CloseGadget, TRUE, WA_RMBTrap, TRUE, WA_IDCMP, IDCMP_CLOSEWINDOW | BUTTONIDCMP | STRINGIDCMP, WA_Title, "Coordinates", WA_CustomScreen,Screen, TAG_DONE)) { struct IntuiMessage *Massage; ULONG Class; struct Gadget *Gadget; BYTE Terminated = FALSE; AddGList(CoordsWindow,GadgetList,(UWORD)-1,(UWORD)-1,NULL); RefreshGList(GadgetList,CoordsWindow,NULL,(UWORD)-1); GT_RefreshWindow(CoordsWindow,NULL); ActivateGadget(GadgetArray[0],CoordsWindow,NULL); while(!Terminated) { WaitPort(CoordsWindow -> UserPort); while(!Terminated && (Massage = (struct IntuiMessage *)GT_GetIMsg(CoordsWindow -> UserPort))) { Class = Massage -> Class; Gadget = (struct Gadget *)Massage -> IAddress; GT_ReplyIMsg(Massage); if(Class == IDCMP_CLOSEWINDOW) Terminated = TRUE; if(Class == IDCMP_GADGETUP) { double Value; switch(Gadget -> GadgetID) { case 3: if(MadeChanges) { MinReal = TempMinReal; MinImaginary = TempMinImaginary; RealWidth = TempRealWidth; ImaginaryHeight = TempImaginaryHeight; RealStep = RealWidth / (double)Window -> Width; ImaginaryStep = ImaginaryHeight / (double)Window -> Height; MainMinReal = MinReal; MainMinImaginary = MinImaginary; MainRealWidth = RealWidth; MainImaginaryHeight = ImaginaryHeight; NewCoords = TRUE; Running = FALSE; AreaActive = FALSE; } Terminated = TRUE; break; case 4: Terminated = TRUE; break; default:Value = atof(((struct StringInfo *)Gadget -> SpecialInfo) -> Buffer); MadeChanges = TRUE; switch(Gadget -> GadgetID) { case 0: TempMinReal = Value; break; case 1: TempMinImaginary = Value; break; case 2: TempRealWidth = Value; TempImaginaryHeight = Value; break; } break; } } } } CloseWindow(CoordsWindow); } } FreeGadgets(GadgetList); } /* Palette(): * * This routine implements the palette control panel. */ VOID Palette() { struct Gadget *GadgetList = NULL; struct Gadget *GadgetArray[3]; struct Window *Window; if(CreateAllPaletteGadgets(&GadgetArray[0],&GadgetList,VisualInfo,Screen -> WBorTop + Screen -> Font -> ta_YSize + 1)) { if(Window = OpenWindowTags(NULL, WA_Width, PALETTE_WIDTH, WA_Height, PALETTE_HEIGHT, WA_Top, (Screen -> Height - PALETTE_HEIGHT) >> 1, WA_Left, (Screen -> Width - PALETTE_WIDTH) >> 1, WA_Activate, TRUE, WA_DragBar, TRUE, WA_CloseGadget, TRUE, WA_RMBTrap, TRUE, WA_IDCMP, IDCMP_CLOSEWINDOW | SLIDERIDCMP, WA_CustomScreen,Screen, WA_Title, "Palette", TAG_DONE)) { struct IntuiMessage *Massage; ULONG Class,Code; struct Gadget *Gadget; BYTE Terminated = FALSE; WORD i,Width = 120 / ((1 << Depth) - 2),Top = Screen -> WBorTop + Screen -> Font -> ta_YSize + 2; AddGList(Window,GadgetList,(UWORD)-1,(UWORD)-1,NULL); RefreshGList(GadgetList,Window,NULL,(UWORD)-1); GT_RefreshWindow(Window,NULL); for(i = 2 ; i < (1 << Depth) ; i++) { SetAPen(Window -> RPort,i); RectFill(Window -> RPort,111 + 8 + (i - 2) * Width,Top,111 + 8 + (i - 1) * Width - 1,Window -> Height - Window -> BorderBottom - 2); } if(DoCycle) { DoCycle = FALSE; GetScreenPalette(); FadeTo(&Screen -> ViewPort,ScreenPalette,SinPalette,1 << Depth,0,0); } else DoCycle = FALSE; UseWheel = FALSE; while(!Terminated) { WaitPort(Window -> UserPort); while(!Terminated && (Massage = (struct IntuiMessage *)GT_GetIMsg(Window -> UserPort))) { Class = Massage -> Class; Code = Massage -> Code; Gadget = (struct Gadget *)Massage -> IAddress; GT_ReplyIMsg(Massage); if(Class == IDCMP_CLOSEWINDOW) Terminated = TRUE; if(Class == IDCMP_MOUSEMOVE) { WORD Wrap = (1 << Depth) - 2; switch(Gadget -> GadgetID) { case 0: RedLevel = Code; break; case 1: GreenLevel = Code; break; case 2: BlueLevel = Code; break; } SinPalette[0] = 0x000; SinPalette[1] = 0xFFF; for(i = 0 ; i < Wrap ; i++) { SinPalette[2 + i] = Range[(RedLevel + i) % Wrap] << 8; SinPalette[2 + i] |= Range[(GreenLevel + i) % Wrap] << 4; SinPalette[2 + i] |= Range[(BlueLevel + i) % Wrap]; } LoadRGB4(&Screen -> ViewPort,SinPalette,1 << Depth); } } } CloseWindow(Window); } } FreeGadgets(GadgetList); } /* MaxScrollPanel(): * * This routine implements the scroll amount control panel. */ VOID MaxScrollPanel() { struct Gadget *GadgetList = NULL; struct Gadget *GadgetArray[3]; struct Window *ScrollWindow; if(CreateAllScrollGadgets(&GadgetArray[0],&GadgetList,VisualInfo,Screen -> WBorTop + Screen -> Font -> ta_YSize + 1)) { if(ScrollWindow = OpenWindowTags(NULL, WA_Width, SCROLL_WIDTH, WA_Height, SCROLL_HEIGHT, WA_Top, (Screen -> Height - SCROLL_HEIGHT) >> 1, WA_Left, (Screen -> Width - SCROLL_WIDTH) >> 1, WA_Activate, TRUE, WA_DragBar, TRUE, WA_DepthGadget, TRUE, WA_CloseGadget, TRUE, WA_RMBTrap, TRUE, WA_CustomScreen,Screen, WA_IDCMP, IDCMP_CLOSEWINDOW | IDCMP_ACTIVEWINDOW | BUTTONIDCMP | INTEGERIDCMP, WA_Title, "Set Scroll Amount", TAG_DONE)) { struct IntuiMessage *Massage; ULONG Class; struct Gadget *Gadget; BYTE Terminated = FALSE; AddGList(ScrollWindow,GadgetList,(UWORD)-1,(UWORD)-1,NULL); RefreshGList(GadgetList,ScrollWindow,NULL,(UWORD)-1); GT_RefreshWindow(ScrollWindow,NULL); ActivateGadget(GadgetArray[0],ScrollWindow,NULL); while(!Terminated) { WaitPort(ScrollWindow -> UserPort); while(!Terminated && (Massage = (struct IntuiMessage *)GT_GetIMsg(ScrollWindow -> UserPort))) { Class = Massage -> Class; Gadget = (struct Gadget *)Massage -> IAddress; GT_ReplyIMsg(Massage); if(Class == IDCMP_CLOSEWINDOW) Terminated = TRUE; if(Class == IDCMP_ACTIVEWINDOW) ActivateGadget(GadgetArray[0],ScrollWindow,NULL); if(Class == IDCMP_GADGETUP) { if(Gadget -> GadgetID == 2) Terminated = TRUE; else { LONG Value = ((struct StringInfo *)GadgetArray[0] -> SpecialInfo) -> LongInt; BYTE GoodValue = TRUE; if(Value < 1) { GoodValue = FALSE; Value = 1; } if(Value >= Screen -> Width) { GoodValue = FALSE; Value = Screen -> Width - 1; } if(GoodValue) { MaxScroll = (double)Value; Terminated = TRUE; } else { GT_SetGadgetAttrs(GadgetArray[0],ScrollWindow,NULL, GTIN_Number,Value, TAG_DONE); DisplayBeep(Screen); ActivateGadget(GadgetArray[0],ScrollWindow,NULL); } } } } } CloseWindow(ScrollWindow); } } FreeGadgets(GadgetList); } /* AreaZoom(): * * This routine handles the selection of an area on screen * to recalculate later. */ VOID AreaZoom() { struct IntuiMessage *Massage; ULONG Class,Code; UWORD X,Y,LastX,LastY; SetClear(Window); Code = NULL; Window -> Flags |= WFLG_RMBTRAP; ReportMouse(TRUE,Window); SetAPen(RPort,1); SetDrMd(RPort,COMPLEMENT); LastX = Window -> MouseX; LastY = Window -> MouseY; DrawLine(RPort,LastX,0,LastX,Screen -> Height - 1); DrawLine(RPort,0,LastY,Screen -> Width - 1,LastY); while(Code != SELECTUP) { WaitPort(Window -> UserPort); if(Massage = (struct IntuiMessage *)GetMsg(Window -> UserPort)) { Class = Massage -> Class; Code = Massage -> Code; X = Massage -> MouseX; Y = Massage -> MouseY; ReplyMsg(&Massage -> ExecMessage); if(Class == IDCMP_MOUSEMOVE) { if(LastX != X) { DrawLine(RPort,LastX,0,LastX,Screen -> Height - 1); DrawLine(RPort,X,0,X,Screen -> Height - 1); } if(LastY != Y) { DrawLine(RPort,0,LastY,Screen -> Width - 1,LastY); DrawLine(RPort,0,Y,Screen -> Width - 1,Y); } LastX = X; LastY = Y; } if(Class == IDCMP_MOUSEBUTTONS) { if(Code == SELECTDOWN) { UWORD Left,Top,Width = 0,Height = 0; BYTE DidBox = FALSE; Left = X; Top = Y; DrawLine(RPort,LastX,0,LastX,Screen -> Height - 1); DrawLine(RPort,0,LastY,Screen -> Width - 1,LastY); while(Code != SELECTUP) { WaitPort(Window -> UserPort); while(Massage = (struct IntuiMessage *)GetMsg(Window -> UserPort)) { Class = Massage -> Class; Code = Massage -> Code; Y = Massage -> MouseY; X = Massage -> MouseX; ReplyMsg(&Massage -> ExecMessage); if(Class == IDCMP_MOUSEMOVE) { if(Y > Top && X > Left) { if(DidBox) { Move(RPort,Left,Top); Draw(RPort,Left + Width - 1,Top); Draw(RPort,Left + Width - 1,Top + Height - 1); Draw(RPort,Left,Top + Height - 1); Draw(RPort,Left,Top + 1); } Width = X - Left + 1; Height = Y - Top + 1; Move(RPort,Left,Top); Draw(RPort,Left + Width - 1,Top); Draw(RPort,Left + Width - 1,Top + Height - 1); Draw(RPort,Left,Top + Height - 1); Draw(RPort,Left,Top + 1); DidBox = TRUE; } Code = NULL; } } } if(DidBox) { Move(RPort,Left,Top); Draw(RPort,Left + Width - 1,Top); Draw(RPort,Left + Width - 1,Top + Height - 1); Draw(RPort,Left,Top + Height - 1); Draw(RPort,Left,Top + 1); } SetDrMd(RPort,JAM1); if(Width >= 2 && Height >= 2) { AreaLeft = Left; AreaTop = Top; AreaWidth = Width; AreaHeight = Height; NewCoords = TRUE; Running = FALSE; AreaActive = TRUE; } } } } } ReportMouse(FALSE,Window); Window -> Flags &= ~WFLG_RMBTRAP; ClearPointer(Window); } /* Zoom(): * * This routine handles the selection of an area on screen * to zoom to later. Note that the area will be square. */ VOID Zoom() { struct IntuiMessage *Massage; ULONG Class,Code; UWORD X,Y,LastX,LastY; SetClear(Window); Code = NULL; Window -> Flags |= WFLG_RMBTRAP; ReportMouse(TRUE,Window); SetAPen(RPort,1); SetDrMd(RPort,COMPLEMENT); LastX = Window -> MouseX; LastY = Window -> MouseY; DrawLine(RPort,LastX,0,LastX,Screen -> Height - 1); DrawLine(RPort,0,LastY,Screen -> Width - 1,LastY); while(Code != SELECTUP) { WaitPort(Window -> UserPort); if(Massage = (struct IntuiMessage *)GetMsg(Window -> UserPort)) { Class = Massage -> Class; Code = Massage -> Code; X = Massage -> MouseX; Y = Massage -> MouseY; ReplyMsg(&Massage -> ExecMessage); if(Class == IDCMP_MOUSEMOVE) { if(LastX != X) { DrawLine(RPort,LastX,0,LastX,Screen -> Height - 1); DrawLine(RPort,X,0,X,Screen -> Height - 1); } if(LastY != Y) { DrawLine(RPort,0,LastY,Screen -> Width - 1,LastY); DrawLine(RPort,0,Y,Screen -> Width - 1,Y); } LastX = X; LastY = Y; } if(Class == IDCMP_MOUSEBUTTONS) { if(Code == SELECTDOWN) { UWORD Left,Top,Width = 0,Height = 0; BYTE DidBox = FALSE; DrawLine(RPort,LastX,0,LastX,Screen -> Height - 1); DrawLine(RPort,0,LastY,Screen -> Width - 1,LastY); Left = X; Top = Y; SetAPen(RPort,1); SetDrMd(RPort,COMPLEMENT); while(Code != SELECTUP) { WaitPort(Window -> UserPort); while(Massage = (struct IntuiMessage *)GetMsg(Window -> UserPort)) { Class = Massage -> Class; Code = Massage -> Code; Y = Massage -> MouseY; ReplyMsg(&Massage -> ExecMessage); if(Class == IDCMP_MOUSEMOVE) { if(Y > Top) { if(DidBox) { Move(RPort,Left,Top); Draw(RPort,Left + Width - 1,Top); Draw(RPort,Left + Width - 1,Top + Height - 1); Draw(RPort,Left,Top + Height - 1); Draw(RPort,Left,Top + 1); } Width = Height = Y - Top + 1; Move(RPort,Left,Top); Draw(RPort,Left + Width - 1,Top); Draw(RPort,Left + Width - 1,Top + Height - 1); Draw(RPort,Left,Top + Height - 1); Draw(RPort,Left,Top + 1); DidBox = TRUE; } Code = NULL; } } } if(DidBox) { Move(RPort,Left,Top); Draw(RPort,Left + Width - 1,Top); Draw(RPort,Left + Width - 1,Top + Height - 1); Draw(RPort,Left,Top + Height - 1); Draw(RPort,Left,Top + 1); } SetDrMd(RPort,JAM1); if(Width >= 2 && Height >= 2) { BYTE Val; SetWait(Window); if(AnimRunning) Val = MyEasyRequest("Yes|Abort|No","Transition will consist\nof %ld images.\n\nDo you wish to use the\ncurrent coordinates?",CalculateFrames(MinReal + (double)Left * RealStep,MinImaginary + (double)Top * ImaginaryStep,(double)Width * RealStep)); else Val = MyEasyRequest("Yes|No","Do you wish to use the\ncurrent coordinates?"); switch(Val) { case 0: break; case 1: MinReal = MinReal + (double)Left * RealStep; MinImaginary = MinImaginary + (double)Top * ImaginaryStep; RealWidth = (double)Width * RealStep; ImaginaryHeight = (double)Height * ImaginaryStep; RealStep = RealWidth / (double)Window -> Width; ImaginaryStep = ImaginaryHeight / (double)Window -> Height; MainMinReal = MinReal; MainMinImaginary = MinImaginary; MainRealWidth = RealWidth; MainImaginaryHeight = ImaginaryHeight; NewCoords = TRUE; Running = FALSE; AreaActive = FALSE; break; case 2: Running = FALSE; StopAnim(); break; } } } } } } ReportMouse(FALSE,Window); Window -> Flags &= ~WFLG_RMBTRAP; ClearPointer(Window); } /* HandleEvent(): * * The global input event (menus, key, mouse, etc.) handler. */ VOID HandleEvent() { struct IntuiMessage *Massage; struct MenuItem *Item; ULONG Class,Code,Qualifier,MenuItem,Selected; UBYTE *DummyChar; BYTE Waiting = FALSE; SetSignal(0,1 << Window -> UserPort -> mp_SigBit); do { while(Massage = (struct IntuiMessage *)GetMsg(Window -> UserPort)) { Class = Massage -> Class; Code = Massage -> Code; Qualifier = Massage -> Qualifier; ReplyMsg(&Massage -> ExecMessage); if(Class == IDCMP_MENUVERIFY) Waiting = HoldIt = TRUE; if(Class == IDCMP_VANILLAKEY) { if(Code == '\t') { if(!DoCycle) { Forward = TRUE; DoCycle = TRUE; } else DoCycle = FALSE; } } if(Class == IDCMP_RAWKEY) { UWORD Palette[32]; BYTE AltWheel = Wheel,i; if(Code == CURSORLEFT) { DoCycle = FALSE; Palette[0] = 0x000; Palette[1] = 0xFFF; if(UseWheel) { if(Wheel) Wheel--; else Wheel = 74; for(i = 2 ; i < 32 ; i++) { Palette[i] = Table[AltWheel]; AltWheel = (AltWheel + 1) % 75; } } else { BYTE AltAdd = Add,Wrap = (1 << Depth) - 2; if(Add) Add--; else Add = Wrap - 1; for(i = 2 ; i < (1 << Depth) ; i++) { Palette[i] = SinPalette[AltAdd + 2]; AltAdd = (AltAdd + 1) % Wrap; } } LoadRGB4(VPort,Palette,1 << Depth); } if(Code == CURSORRIGHT) { DoCycle = FALSE; Palette[0] = 0x000; Palette[1] = 0xFFF; if(UseWheel) { Wheel = (Wheel + 1) % 75; for(i = 2 ; i < 32 ; i++) { Palette[i] = Table[AltWheel]; AltWheel = (AltWheel + 1) % 75; } } else { BYTE AltAdd = Add,Wrap = (1 << Depth) - 2; Add = (Add + 1) % Wrap; for(i = 2 ; i < (1 << Depth) ; i++) { Palette[i] = SinPalette[AltAdd + 2]; AltAdd = (AltAdd + 1) % Wrap; } } LoadRGB4(VPort,Palette,1 << Depth); } if(Code == CURSORUP) { Forward = TRUE; DoCycle = TRUE; } if(Code == CURSORDOWN) { Forward = FALSE; DoCycle = TRUE; } } if(Class == IDCMP_MENUPICK) { Waiting = HoldIt = FALSE; if(GotClip) { BltBitMap(BackupBitMap,0,0,RPort -> BitMap,(Square - 25 * 8) >> 1,(Square - 8) >> 1,8 * 25,8,0xC0,0xFF,NULL); GotClip = FALSE; } MenuItem = Code; while(MenuItem != MENUNULL) { if(Item = ItemAddress(Menu,MenuItem)) { Selected = (ULONG)MENU_USERDATA(Item); switch(Selected) { case MEN_OPEN: BlockWindow(); strcpy(NameBuffer,LastName); DummyChar = PathPart(NameBuffer); *DummyChar = 0; if(GetFile("Open Picture",NameBuffer,FilePart(LastName),NameBuffer,"~(#?.info)",FALSE)) { struct IFFHandle *Handle; struct BitMap *BitMap; if(Handle = OpenImageFile(NameBuffer)) { struct BitMapHeader BitMapHeader; struct MandelInfo TempMandelInfo; BYTE Colours = 1 << Depth,GotImage = FALSE; if(ReadImageHeader(Handle,&GlobalMode,&Colours,ColourTable,&BitMapHeader,&TempMandelInfo)) { if(BitMapHeader . w == Window -> Width && BitMapHeader . h == Window -> Height) { if(BitMap = CreateBitMap(BitMapHeader . nPlanes,BitMapHeader . w,BitMapHeader . h)) { if(ReadImageBody(Handle,BitMap,&BitMapHeader)) { WORD i,Height = Screen -> Height; if(GetVPModeID(&Screen -> ViewPort) & LACE) Height >>= 1; DoCycle = FALSE; GetScreenPalette(); FadeTo(&Screen -> ViewPort,ScreenPalette,ColourTable,1 << Depth,0,0); switch(Random(6)) { case 0: for(i = 0 ; i < (Square >> 1) ; i++) { WaitLine(Height); BltBitMapRastPort(BitMap,0,2 * i, RPort,0,2 * i, Screen -> Width,1,0xC0); BltBitMapRastPort(BitMap,0,Square - 1 - 2 * i,RPort,0,Square - 1 - 2 * i,Screen -> Width,1,0xC0); } break; case 1: for(i = 0 ; i < (Square >> 1) ; i++) { WaitLine(Height); BltBitMapRastPort(BitMap,2 * i,0, RPort,2 * i,0,1, Screen -> Height,0xC0); BltBitMapRastPort(BitMap,Square - 1 - 2 * i,0,RPort,Square - 1 - 2 * i,0,1,Screen -> Height,0xC0); } break; case 2: for(i = 0 ; i < (Square >> 1) ; i++) { WaitLine(Height); BltBitMapRastPort(BitMap,i,i,RPort,i,i,((Square >> 1) - i) * 2,1,0xC0); BltBitMapRastPort(BitMap,i,Square - 1 - i,RPort,i,Square - 1 - i,((Square >> 1) - i) * 2,1,0xC0); BltBitMapRastPort(BitMap,i,i,RPort,i,i,1,((Square >> 1) - i) * 2,0xC0); BltBitMapRastPort(BitMap,Square - 1 - i,i,RPort,Square - 1 - i,i,1,((Square >> 1) - i) * 2,0xC0); } break; case 3: for(i = (Square >> 1) - 1 ; i >= 0 ; i--) { WaitLine(Height); BltBitMapRastPort(BitMap,i,i,RPort,i,i,((Square >> 1) - i) * 2,1,0xC0); BltBitMapRastPort(BitMap,i,Square - 1 - i,RPort,i,Square - 1 - i,((Square >> 1) - i) * 2,1,0xC0); BltBitMapRastPort(BitMap,i,i,RPort,i,i,1,((Square >> 1) - i) * 2,0xC0); BltBitMapRastPort(BitMap,Square - 1 - i,i,RPort,Square - 1 - i,i,1,((Square >> 1) - i) * 2,0xC0); } break; case 4: for(i = 0 ; i < Square ; i++) { WaitLine(Height); BltBitMapRastPort(BitMap, i, 0,RPort, i, 0,1,(Square >> 1),0xC0); BltBitMapRastPort(BitMap,Square - 1 - i,(Square >> 1),RPort,Square - 1 - i,(Square >> 1),1,(Square >> 1),0xC0); } break; case 5: for(i = 0 ; i < Square ; i++) { WaitLine(Height); BltBitMapRastPort(BitMap, 0, i,RPort, 0, i,(Square >> 1),1,0xC0); BltBitMapRastPort(BitMap,(Square >> 1),Square - 1 - i,RPort,(Square >> 1),Square - 1 - i,(Square >> 1),1,0xC0); } break; } Wheel = 0; for(i = 0 ; i < 75 ; i++) { if(ColourTable[2] == Table[i]) { Wheel = i; break; } } if(TempMandelInfo . Iterations) { MainMinReal = MinReal = TempMandelInfo . MinReal; MainMinImaginary = MinImaginary = TempMandelInfo . MinImaginary; MainRealWidth = RealWidth = TempMandelInfo . RealWidth; MainImaginaryHeight = ImaginaryHeight = TempMandelInfo . ImaginaryHeight; MaxIteration = TempMandelInfo . Iterations; IterationSetup(); RealStep = RealWidth / (double)Window -> Width; ImaginaryStep = ImaginaryHeight / (double)Window -> Height; } else MyEasyRequest("Continue","Could not read image\ncoordinates, previous values\nremain untouched."); strcpy(LastName,NameBuffer); Running = FALSE; AreaActive = FALSE; GotImage = TRUE; } else MyEasyRequest("Continue","Error reading file\n%s.",FilePart(NameBuffer)); DeleteBitMap(BitMap); } else MyEasyRequest("Continue","Not enough memory!"); } else { if(BitMapHeader . w == BitMapHeader . h && !(BitMapHeader . h % 4)) { if(BitMap = CreateBitMap(BitMapHeader . nPlanes,BitMapHeader . w,BitMapHeader . h)) { if(ReadImageBody(Handle,BitMap,&BitMapHeader)) { WORD i; Wheel = 0; for(i = 0 ; i < 75 ; i++) { if(ColourTable[2] == Table[i]) { Wheel = i; break; } } if(TempMandelInfo . Iterations) { MainMinReal = MinReal = TempMandelInfo . MinReal; MainMinImaginary = MinImaginary = TempMandelInfo . MinImaginary; MainRealWidth = RealWidth = TempMandelInfo . RealWidth; MainImaginaryHeight = ImaginaryHeight = TempMandelInfo . ImaginaryHeight; MaxIteration = TempMandelInfo . Iterations; RealStep = RealWidth / (double)Window -> Width; ImaginaryStep = ImaginaryHeight / (double)Window -> Height; } else MyEasyRequest("Continue","Could not read image\ncoordinates, previous values\nremain untouched."); strcpy(LastName,NameBuffer); Running = FALSE; AreaActive = FALSE; NewMode = TRUE; DoCycle = FALSE; GlobalBitMap = BitMap; GlobalHeader = BitMapHeader; } else { MyEasyRequest("Continue","Error reading file\n%s.",FilePart(NameBuffer)); DeleteBitMap(BitMap); } } else MyEasyRequest("Continue","Not enough memory!"); } else MyEasyRequest("Continue","Picture has wrong size!"); } } else MyEasyRequest("Continue","Error reading file\n%s.",FilePart(NameBuffer)); CloseImageFile(Handle); } else MyEasyRequest("Continue","Could not open file\n%s.",FilePart(NameBuffer)); } ReleaseWindow(); break; case MEN_SAVE: BlockWindow(); if(NameBuffer[0]) goto SaveIt; case MEN_SAVEAS:BlockWindow(); strcpy(NameBuffer,LastName); DummyChar = PathPart(NameBuffer); *DummyChar = 0; if(GetFile("Save Picture As",NameBuffer,FilePart(LastName),NameBuffer,"~(#?.info)",TRUE)) { SaveIt: MandelInfo . MinReal = MinReal; MandelInfo . MinImaginary = MinImaginary; MandelInfo . RealWidth = RealWidth; MandelInfo . ImaginaryHeight = ImaginaryHeight; MandelInfo . Iterations = MaxIteration; if(!SaveBitMap(RPort -> BitMap,&Screen -> ViewPort,0,0,Window -> Width,Window -> Height,Screen -> Width,Screen -> Height,NameBuffer,&MandelInfo)) MyEasyRequest("Continue","Could not save file\n%s.",FilePart(NameBuffer)); else { if(!ThisProcess -> pr_CLI) PutDiskObject(NameBuffer,&PictureIcon); strcpy(LastName,NameBuffer); } } ReleaseWindow(); break; case MEN_PRI0: SetTaskPri(ThisProcess,-5); break; case MEN_PRI1: SetTaskPri(ThisProcess,0); break; case MEN_PRI2: SetTaskPri(ThisProcess,5); break; case MEN_PLAY: BlockWindow(); ReplayAnim(); ReleaseWindow(); break; case MEN_START: if(!AnimRunning) { Running = FALSE; FullPicture = FALSE; AnimRunning = TRUE; } break; case MEN_STOP: BlockWindow(); StopAnim(); Running = FALSE; FullPicture = FALSE; ReleaseWindow(); break; case MEN_SCROLL:BlockWindow(); MaxScrollPanel(); ReleaseWindow(); break; case MEN_FRAME: if(Item -> Flags & CHECKED) Frame = TRUE; else Frame = FALSE; break; case MEN_INCLUDE: if(Item -> Flags & CHECKED) Include = TRUE; else Include = FALSE; break; case MEN_RESOLUTION: NewMode = TRUE; Running = FALSE; DoCycle = FALSE; break; case MEN_ABOUT: BlockWindow(); MyEasyRequest("So what?"," MandelSquare\n\nYet another Mandelbrot set\n exploration program\n\n Written by\n Olaf `Olsen' Barthel\n\n ⌐ Copyright 1991\n"); ReleaseWindow(); break; case MEN_QUIT: BlockWindow(); if(MyEasyRequest("Yes|No","Do you really wish to\nleave this program?")) CloseAll(RETURN_OK); ReleaseWindow(); break; case MEN_ZOOM: Zoom(); break; case MEN_CLIP: AreaZoom(); Faster = TRUE; break; case MEN_RERUN: AreaZoom(); Faster = FALSE; break; case MEN_PRECISE: if(Item -> Flags & CHECKED) Precise = TRUE; else Precise = FALSE; break; case MEN_COORDS:BlockWindow(); Coords(); ReleaseWindow(); break; case MEN_PALETTE: BlockWindow(); Palette(); ReleaseWindow(); break; case MEN_SPEC: DoCycle = FALSE; if(Item -> Flags & CHECKED) UseWheel = TRUE; else UseWheel = FALSE; GetScreenPalette(); if(UseWheel) FadeTo(&Screen -> ViewPort,ScreenPalette,WheelPalette,1 << Depth,0,0); else FadeTo(&Screen -> ViewPort,ScreenPalette,SinPalette,1 << Depth,0,0); break; case MEN_RUN: Running ^= TRUE; if(!Running) FullPicture = FALSE; break; default: if(Selected >= 1 && Selected <= 16) MaxIteration = (1 << Selected); break; } MenuItem = Item -> NextSelect; } else break; } } } if(Waiting) WaitPort(Window -> UserPort); } while(Waiting); } #if 0 /* Iterate(double RealValue,double ImaginaryValue): * * This is the `C' version of the Iterate routine * present in Iterate.asm. I've commented it out * and included it only for historical reasons. */ BYTE Iterate(double RealValue,double ImaginaryValue) { double Real = 0,Imaginary = 0,RealTemp,ImaginaryTemp; WORD i = 0; for(;;) { ImaginaryTemp = Imaginary * Imaginary; RealTemp = Real * Real; if(fabs(RealTemp + ImaginaryTemp) > 4.0) return(Wave[i]); if(++i >= MaxIteration) return(0); Imaginary = 2.0 * Real * Imaginary + ImaginaryValue; Real = RealTemp - ImaginaryTemp + RealValue; } } #endif /* Mandelbrot(): * * The recursive image generation routine. */ VOID Mandelbrot(double MinReal,double MinImaginary,double RealStep,double ImaginaryStep,LONG Left,LONG Top,LONG Width,LONG Height) { if(SetSignal(0,0) & (1 << Window -> UserPort -> mp_SigBit)) HandleEvent(); if(Running) { BYTE Colours[4],LastColour,Ident = TRUE; WORD Positions[4][2],i; /* Set up pixel positions. */ Positions[0][0] = Left; Positions[0][1] = Top; Positions[1][0] = Left + Width - 1; Positions[1][1] = Top; Positions[2][0] = Left + Width - 1; Positions[2][1] = Top + Height - 1; Positions[3][0] = Left; Positions[3][1] = Top + Height - 1; for(i = 0 ; i < 4 ; i++) { /* Calculate colour values for each pixel. */ Colours[i] = Iterate(MinReal + RealStep * (double)Positions[i][0],MinImaginary + ImaginaryStep * (double)Positions[i][1]); /* Are all colour identical? */ if(Ident) { if(!i) LastColour = Colours[i]; else { if(Colours[i] != LastColour) Ident = FALSE; else LastColour = Colours[i]; } } } /* If all colour happen to be identical, fill the * are in the given colour. */ if(Ident) { /* If extra precision is selected, also check * if all the pixels on the margin of the * current square are in the same colour. */ if(Precise) { WORD j,PositionBackup[4][2]; CopyMem(Positions,PositionBackup,sizeof(PositionBackup)); for(i = 0 ; i < Width - 1 ; i++) { PositionBackup[0][0]++; PositionBackup[1][1]++; PositionBackup[2][0]--; PositionBackup[3][1]--; for(j = 0 ; j < 4 ; j++) { if(Iterate(MinReal + RealStep * (double)PositionBackup[j][0],MinImaginary + ImaginaryStep * (double)PositionBackup[j][1]) != Colours[0]) goto Full; } } } /* If necessary fill the square. */ if(Colours[0]) { if(RPort -> FgPen != Colours[0]) SetAPen(RPort,Colours[0]); RectFill(RPort,Left,Top,Left + Width - 1,Top + Height - 1); } } else { /* If not already down at minimum level, * split the square again. */ Full: if(Width > 2 && Height > 2) { Mandelbrot(MinReal,MinImaginary,RealStep,ImaginaryStep,Left,Top,Width >> 1,Height >> 1); Mandelbrot(MinReal,MinImaginary,RealStep,ImaginaryStep,Left + (Width >> 1),Top,Width >> 1,Height >> 1); Mandelbrot(MinReal,MinImaginary,RealStep,ImaginaryStep,Left,Top + (Height >> 1),Width >> 1,Height >> 1); Mandelbrot(MinReal,MinImaginary,RealStep,ImaginaryStep,Left + (Width >> 1),Top + (Height >> 1),Width >> 1,Height >> 1); } else { register struct BitMap *BitMap = RPort -> BitMap; /* Set the pixels. */ for(i = 0 ; i < 4 ; i++) { if(Colours[i]) Plot(BitMap,Positions[i][0],Positions[i][1],Colours[i]); } } } } } /* RunMandelbrot(): * * This is the recursive image generation driver, it * remembers the time it took to generate the image and * calls the recursive image generation routine. */ VOID RunMandelbrot(double MinReal,double MaxReal,double MinImaginary,double MaxImaginary,LONG Width,LONG Height) { double RealStep,ImaginaryStep; UBYTE TimeBuffer[40]; struct timeval TimeVal; GetTime(); TimeVal = TimeRequest -> tr_time; RealStep = (MaxReal - MinReal) / (double)Width; ImaginaryStep = (MaxImaginary - MinImaginary) / (double)Height; FullPicture = TRUE; Mandelbrot(MinReal,MinImaginary,RealStep,ImaginaryStep,0,0,Window -> Width >> 1,Window -> Height >> 1); Mandelbrot(MinReal,MinImaginary,RealStep,ImaginaryStep,Window -> Width >> 1,0,Window -> Width >> 1,Window -> Height >> 1); Mandelbrot(MinReal,MinImaginary,RealStep,ImaginaryStep,0,Window -> Height >> 1,Window -> Width >> 1,Window -> Height >> 1); Mandelbrot(MinReal,MinImaginary,RealStep,ImaginaryStep,Window -> Width >> 1,Window -> Height >> 1,Window -> Width >> 1,Window -> Height >> 1); GetTime(); SubTime(&TimeRequest -> tr_time,&TimeVal); BltBitMap(RPort -> BitMap,(Square - 25 * 8) >> 1,(Square - 8) >> 1,BackupBitMap,0,0,8 * 25,8,0xC0,0xFF,NULL); GotClip = TRUE; SetAPen(RPort,1); SetDrMd(RPort,JAM1); TimeVal = TimeRequest -> tr_time; sprintf(TimeBuffer,"Duration %2d:%02d:%02d Minutes",(TimeVal . tv_secs % 86400) / 3600,(TimeVal . tv_secs % 3600) / 60,TimeVal . tv_secs % 60); Move(RPort,(Square - 25 * 8) >> 1,((Square - 8) >> 1) + 6); Text(RPort,TimeBuffer,25); Running = FALSE; } /* RunAreaMandelbrot(double RealStep,double ImaginaryStep): * * This is the iterative image generation routine, * unlike the routines above it generates the image * pixel by pixel and is not limited to a square * drawing area. */ VOID RunAreaMandelbrot(double RealStep,double ImaginaryStep) { double RealValue,ImaginaryValue; WORD x,y; UBYTE TimeBuffer[40]; struct BitMap *BitMap = RPort -> BitMap; struct timeval TimeVal; BYTE Colour; GetTime(); TimeVal = TimeRequest -> tr_time; ImaginaryValue = MinImaginary + ImaginaryStep * (double)AreaTop; /* `Faster' actually only means that before a pixel * is drawn the approriate spot is checked to see * if there is not already a pixel in place. */ if(Faster) { for(y = 0 ; (y < AreaHeight) && Running ; y++) { RealValue = MinReal + RealStep * (double)AreaLeft; for(x = 0 ; (x < AreaWidth) && Running ; x++) { if(!Test(BitMap,AreaLeft + x,AreaTop + y)) { if((Colour = Iterate(RealValue,ImaginaryValue))) Plot(BitMap,AreaLeft + x,AreaTop + y,Colour); } RealValue += RealStep; if(SetSignal(0,0) & (1 << Window -> UserPort -> mp_SigBit)) HandleEvent(); } ImaginaryValue += ImaginaryStep; } } else { /* These loops will calculate the image pixel * by pixel without skipping already set areas. * The first check insures that the drawing area * is as wide as the screen which means that * we are able to generate the pixels in fast * ram and to copy them to chip ram when done. */ if(AreaWidth == Window -> Width && LineBitMap . Planes[0]) { BitMap = &LineBitMap; for(y = 0 ; (y < AreaHeight) && Running ; y++) { RealValue = MinReal + RealStep * (double)AreaLeft; for(x = 0 ; (x < AreaWidth) && Running ; x++) { if((Colour = Iterate(RealValue,ImaginaryValue))) Plot(BitMap,AreaLeft + x,0,Colour); else Plot(BitMap,AreaLeft + x,0,0); RealValue += RealStep; if(SetSignal(0,0) & (1 << Window -> UserPort -> mp_SigBit)) HandleEvent(); } if(Running) CopyLine(BitMap,AreaTop + y); ImaginaryValue += ImaginaryStep; } } else { for(y = 0 ; (y < AreaHeight) && Running ; y++) { RealValue = MinReal + RealStep * (double)AreaLeft; for(x = 0 ; (x < AreaWidth) && Running ; x++) { if((Colour = Iterate(RealValue,ImaginaryValue))) Plot(BitMap,AreaLeft + x,AreaTop + y,Colour); RealValue += RealStep; if(SetSignal(0,0) & (1 << Window -> UserPort -> mp_SigBit)) HandleEvent(); } ImaginaryValue += ImaginaryStep; } } } GetTime(); SubTime(&TimeRequest -> tr_time,&TimeVal); BltBitMap(RPort -> BitMap,(Square - 25 * 8) >> 1,(Square - 8) >> 1,BackupBitMap,0,0,8 * 25,8,0xC0,0xFF,NULL); GotClip = TRUE; SetAPen(RPort,1); SetDrMd(RPort,JAM1); TimeVal = TimeRequest -> tr_time; sprintf(TimeBuffer,"Duration %2d:%02d:%02d Minutes",(TimeVal . tv_secs % 86400) / 3600,(TimeVal . tv_secs % 3600) / 60,TimeVal . tv_secs % 60); Move(RPort,(Square - 25 * 8) >> 1,((Square - 8) >> 1) + 6); Text(RPort,TimeBuffer,25); Running = FALSE; Faster = TRUE; } /* main(): * * The notorious main routine. */ VOID __stdargs main() { struct IFFHandle *Handle; struct BitMap *BitMap; BYTE GotImage = FALSE,IsAnim = FALSE; /* Open the required resources. */ OpenAll(); MinReal = -RealWidth / 2; MinImaginary = -ImaginaryHeight / 2; DummyBuffer[0] = 0; /* Pick up any selected images if run from Workbench. */ if(!ThisProcess -> pr_CLI) { extern struct WBStartup *WBenchMsg; DefaultTool[0] = 0; /* Build new default tool name. */ if(NameFromLock(WBenchMsg -> sm_ArgList[0] . wa_Lock,DefaultTool,256)) { if(!AddPart(DefaultTool,WBenchMsg -> sm_ArgList[0] . wa_Name,256)) DefaultTool[0] = 0; } if(!DefaultTool[0]) strcpy(DefaultTool,"MandelSquare"); PictureIcon . do_DefaultTool = DefaultTool; AnimIcon . do_DefaultTool = DefaultTool; /* Called with Workbench arguments? */ if(WBenchMsg -> sm_NumArgs > 1) { /* Construct the full name. */ if(NameFromLock(WBenchMsg -> sm_ArgList[1] . wa_Lock,DummyBuffer,256)) { if(!AddPart(DummyBuffer,WBenchMsg -> sm_ArgList[1] . wa_Name,256)) DummyBuffer[0] = 0; else { struct DiskObject *Icon; /* Read the icon and try to figure * out whether the corresponding * file is an animation or just * a plain image. */ if(Icon = GetDiskObject(DummyBuffer)) { UBYTE *Value; if(Value = FindToolType(Icon -> do_ToolTypes,"FILETYPE")) { if(!stricmp(Value,"ANIM")) IsAnim = TRUE; } FreeDiskObject(Icon); } } } else DummyBuffer[0] = 0; } } /* No chance, use the default image. */ if(!DummyBuffer[0]) strcpy(DummyBuffer,"MandelSquare.Title"); /* Try to read the selected image. */ if(Handle = OpenImageFile(DummyBuffer)) { struct BitMapHeader BitMapHeader; struct MandelInfo TempMandelInfo; BYTE Colours = 1 << Depth; ULONG MyMode = Mode; if(ReadImageHeader(Handle,&MyMode,&Colours,ColourTable,&BitMapHeader,&TempMandelInfo)) { LONG Error; if(TempMandelInfo . Iterations) { MinReal = TempMandelInfo . MinReal; MinImaginary = TempMandelInfo . MinImaginary; RealWidth = TempMandelInfo . RealWidth; ImaginaryHeight = TempMandelInfo . ImaginaryHeight; MaxIteration = TempMandelInfo . Iterations; } if(BitMapHeader . w == BitMapHeader . h && !(BitMapHeader . h % 4)) { Square = BitMapHeader . w; Mode = MyMode; Depth = BitMapHeader . nPlanes; } if(BitMap = CreateBitMap(BitMapHeader . nPlanes,BitMapHeader . w,BitMapHeader . h)) { if(ReadImageBody(Handle,BitMap,&BitMapHeader)) GotImage = TRUE; else DeleteBitMap(BitMap); } if(Error = GfxSetup()) { if(GotImage) DeleteBitMap(BitMap); CloseImageFile(Handle); CloseAll(Error); } else { if(GotImage) { BltBitMapRastPort(BitMap,0,0,RPort,0,0,Screen -> Width,Screen -> Height,0xC0); DeleteBitMap(BitMap); } } IterationSetup(); } CloseImageFile(Handle); } else { struct Rectangle DisplayClip; LONG Error,Height; /* No title image, so let's produce one. * At first determine the maximum screen * size. */ if(QueryOverscan(Mode,&DisplayClip,OSCAN_TEXT)) { WORD p = 0; Height = (((DisplayClip . MaxY - DisplayClip . MinY + 1) + 3) >> 2) << 2; Square = 0; while(Square < Height) { p++; Square += PLUS; } if(Square > Height) { p--; Square -= PLUS; } if(p & 1) Square -= PLUS; } else { if(Mode == LORES_KEY) Square = 256; else Square = 512; } if(Error = GfxSetup()) CloseAll(Error); } /* Are we supposed to load and replay an animation file? */ if(IsAnim) { BPTR File; SetWait(Window); Window -> Flags |= WFLG_RMBTRAP; if(File = Open(DummyBuffer,MODE_OLDFILE)) { if(CreateBuffer()) { if(OpenPreLoadIFF(File)) { strcpy(AnimPlayName,DummyBuffer); SetClear(Window); SwapBits(); ActivateWindow(Window); ScreenToFront(Screen); while(PlayAnim()); ClosePreLoadIFF(); } DeleteBuffer(); LoadRGB4(&Screen -> ViewPort,ColourTable,1 << Depth); } Close(File); } Window -> Flags &= ~WFLG_RMBTRAP; ClearPointer(Window); } else { if(!GotImage) { /* Set up working data. */ MainMinReal = MinReal; MainMinImaginary = MinImaginary; MainRealWidth = RealWidth; MainImaginaryHeight = ImaginaryHeight; /* Present the screen. */ LoadRGB4(&Screen -> ViewPort,ColourTable,1 << Depth); ScreenToFront(Screen); ActivateWindow(Window); Running = TRUE; NewCoords = FALSE; /* Generate the image. */ RunMandelbrot(MinReal,MinReal + RealWidth,MinImaginary,MinImaginary + ImaginaryHeight,Window -> Width,Window -> Height); } else { strcpy(LastName,DummyBuffer); /* Present the screen. */ ScreenToFront(Screen); BlockWindow(); ActivateWindow(Window); /* Fade in the image. */ FadeTo(&Screen -> ViewPort,NULL,ColourTable,1 << Depth,0,0); ReleaseWindow(); } RealStep = (RealWidth) / (double)Window -> Width; ImaginaryStep = (ImaginaryHeight) / (double)Window -> Height; } /* The main input loop. */ FOREVER { WaitPort(Window -> UserPort); HandleEvent(); /* New display mode? */ if(NewMode) { struct Rectangle DisplayClip; LONG Error,Height; /* Remember colour table. */ CopyMem(ColourTable,SinPalette,sizeof(UWORD) * 32); /* We have a bitmap to copy to the * screen. */ if(GlobalBitMap) { GfxCleanup(); Mode = GlobalMode; Depth = GlobalHeader . nPlanes; Square = GlobalHeader . w; NewMode = FALSE; if(Error = GfxSetup()) CloseAll(Error); else { BltBitMapRastPort(GlobalBitMap,0,0,RPort,0,0,Screen -> Width,Screen -> Height,0xC0); DeleteBitMap(GlobalBitMap); GlobalBitMap = NULL; ScreenToFront(Screen); BlockWindow(); ActivateWindow(Window); if(UseWheel) FadeTo(&Screen -> ViewPort,NULL,WheelPalette,1 << Depth,0,0); else FadeTo(&Screen -> ViewPort,NULL,SinPalette,1 << Depth,0,0); NewCoords = FALSE; Running = FALSE; AreaActive = FALSE; IterationSetup(); ReleaseWindow(); } } else { /* Open new screen with maximum * available text overscan dimensions. */ if(Mode == LORES_KEY) { Mode = HIRESLACE_KEY; Depth = 4; } else { Mode = LORES_KEY; Depth = 5; } if(QueryOverscan(Mode,&DisplayClip,OSCAN_TEXT)) { WORD p = 0; Height = (((DisplayClip . MaxY - DisplayClip . MinY + 1) + 3) >> 2) << 2; Square = 0; while(Square < Height) { p++; Square += PLUS; } if(Square > Height) { p--; Square -= PLUS; } if(p & 1) Square -= PLUS; } else { if(Mode == LORES_KEY) Square = 256; else Square = 512; } NewMode = FALSE; GfxCleanup(); if(Error = GfxSetup()) CloseAll(Error); else { if(UseWheel) LoadRGB4(&Screen -> ViewPort,WheelPalette,1 << Depth); else LoadRGB4(&Screen -> ViewPort,SinPalette,1 << Depth); ScreenToFront(Screen); ActivateWindow(Window); MinReal = MainMinReal; MinImaginary = MainMinImaginary; RealWidth = MainRealWidth; ImaginaryHeight = MainImaginaryHeight; RealStep = (RealWidth) / (double)Window -> Width; ImaginaryStep = (ImaginaryHeight) / (double)Window -> Height; NewCoords = TRUE; AreaActive = FALSE; IterationSetup(); } } } /* Run the animation routine? */ while(AnimRunning) { RunAnim(); if(!AnimRunning) { Running = FALSE; NewCoords = FALSE; } } /* Restart with new coordinates. */ if(NewCoords) { Running = TRUE; NewCoords = FALSE; } /* Run the image generation routines. */ if(Running) { if(AreaActive) RunAreaMandelbrot(RealStep,ImaginaryStep); else { SetRast(RPort,0); RunMandelbrot(MinReal,MinReal + RealWidth,MinImaginary,MinImaginary + ImaginaryHeight,Window -> Width,Window -> Height); } } } }