home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Creative Computers
/
CreativeComputers.iso
/
shareware
/
fractals
/
mandelsquare
/
mandelsquare-1.06.lha
/
Double.c
next >
Wrap
C/C++ Source or Header
|
1992-12-20
|
12KB
|
495 lines
/*
** MandelSquare - AmigaDOS 2.0/3.0 Mandelbrot set explorer
**
** Double.c, Display double-buffering routines
**
** Copyright ⌐ 1991-1992 by Olaf `Olsen' Barthel
** All Rights Reserved
*/
/* Double buffering info. */
struct DBI
{
struct Screen *Screen, /* Current display. */
*NewScreen; /* Local display. */
struct Window *NewWindow; /* Local window. */
struct ScreenBuffer *ScreenBuffer[2]; /* v39 double buffering info. */
struct MsgPort *ScreenPort; /* v39 double buffering sync port. */
struct BitMap *UncompBitMap; /* v39 uncompression bitmap */
struct BitMap *OriginalBitMap; /* Old display bitmap. */
struct Palette *OriginalPalette; /* Original display palette. */
struct Palette *BlackPalette; /* Paint it black. */
struct BitMap *BitMap[2]; /* v37 double buffering bitmaps. */
struct timerequest *TimeRequest; /* Timer io for inter-frame delays. */
struct MsgPort *TimePort;
};
/* Are we running under control of Kickstart 3.0 or higher? */
extern BYTE Is39;
/* Safe shared window closing routine. */
extern VOID CloseWindowSafely(struct Window *Window);
/* Bitmap allocation routines. */
extern VOID FreeCustomBitMap(struct BitMap *BitMap,BYTE Standard);
extern struct BitMap * AllocCustomBitMap(UWORD Depth,UWORD Width,UWORD Height,BYTE Standard);
/* Palette management. */
extern VOID FreePalette(struct Palette *Palette);
extern struct Palette * AllocPalette(LONG NumColours,BYTE TrueColour);
extern struct Palette * GetPalette(struct Screen *Screen,struct Palette *Palette);
extern VOID LoadPalette(struct Screen *Screen,struct Palette *Palette,LONG NumColours);
extern LONG GetPaletteSize(struct Palette *Palette);
extern BYTE GetPaletteTriplet(struct Palette *Palette,UBYTE *Triplet,LONG Index);
extern BYTE SetPaletteTriplet(struct Palette *Palette,UBYTE R,UBYTE G,UBYTE B,LONG Index);
extern ULONG GetPaletteEntry(struct Palette *Palette,LONG Index);
extern BYTE SetPaletteEntry(struct Palette *Palette,ULONG Entry,LONG Index);
/* Local routines. */
VOID FreeDBI(struct DBI *Info);
struct DBI * AllocDBI(struct Screen *Screen);
VOID SwapDBI(struct DBI *Info,BYTE Copy);
struct BitMap * GetDBI(struct DBI *Info);
VOID PaletteDBI(struct DBI *Info,struct Palette *Palette);
VOID StartDBI(struct DBI *Info,ULONG Jiffies);
VOID WaitDBI(struct DBI *Info);
/* FreeDBI(struct DBI *Info):
*
* Free double-buffering information.
*/
VOID
FreeDBI(struct DBI *Info)
{
WORD i;
/* Release timer io request. */
if(Info -> TimeRequest)
{
if(Info -> TimeRequest -> tr_node . io_Device)
CloseDevice(Info -> TimeRequest);
DeleteIORequest(Info -> TimeRequest);
}
/* Releae timer io reply port. */
if(Info -> TimePort)
DeleteMsgPort(Info -> TimePort);
/* Turn the screen black before we change
* the bitmap.
*/
if(Info -> BlackPalette && !Info -> NewScreen)
{
LoadPalette(Info -> Screen,Info -> BlackPalette,0);
FreePalette(Info -> BlackPalette);
}
/* Reinstall the original viewport bitmap. */
if(Info -> OriginalBitMap)
{
Info -> Screen -> ViewPort . RasInfo -> BitMap = Info -> OriginalBitMap;
MakeScreen(Info -> Screen);
RethinkDisplay();
}
/* Release the display bitmaps. */
for(i = 0 ; i < 2 ; i++)
{
if(Info -> BitMap[i])
FreeCustomBitMap(Info -> BitMap[i],FALSE);
}
/* Release the uncompression bitmap. */
if(Info -> UncompBitMap)
FreeCustomBitMap(Info -> UncompBitMap,TRUE);
/* Free the double-buffering information. */
for(i = 0 ; i < 2 ; i++)
{
if(Info -> ScreenBuffer[i])
FreeScreenBuffer(Info -> NewScreen,Info -> ScreenBuffer[i]);
}
/* Reset the screen palette. */
if(Info -> OriginalPalette && !Info -> NewScreen)
{
LoadPalette(Info -> Screen,Info -> OriginalPalette,0);
FreePalette(Info -> OriginalPalette);
}
/* Release the double buffering sync port. */
if(Info -> ScreenPort)
DeleteMsgPort(Info -> ScreenPort);
/* Close the window if any. */
if(Info -> NewWindow)
CloseWindowSafely(Info -> NewWindow);
/* Bring the original screen to the front. */
if(Info -> NewScreen)
{
ScreenToFront(Info -> Screen);
CloseScreen(Info -> NewScreen);
}
/* Free the info buffer. */
FreeVec(Info);
}
/* AllocDBI(struct Screen *Screen):
*
* Allocate double-buffering information handle.
*/
struct DBI *
AllocDBI(struct Screen *Screen)
{
struct DBI *Info;
/* Allocate the buffer. */
if(Info = (struct DBI *)AllocVec(sizeof(struct DBI),MEMF_ANY | MEMF_CLEAR))
{
Info -> Screen = Screen;
/* Get the screen palette. */
if(Info -> OriginalPalette = GetPalette(Screen,NULL))
{
/* Allocate blank palette. */
if(Info -> BlackPalette = AllocPalette(GetPaletteSize(Info -> OriginalPalette),FALSE))
{
BYTE Success;
WORD i;
/* Are we running under control of
* Kickstart 3.0 or higher?
*/
if(Is39)
{
struct Rectangle DisplayClip;
ULONG Mode;
/* Just in case... */
Success = FALSE;
/* Obtain the main screen mode ID. */
Mode = GetVPModeID(&Screen -> ViewPort);
/* Query the overscan dimensions,
* we wish to center the screen
* on the display if possible.
*/
if(QueryOverscan(Mode,&DisplayClip,OSCAN_VIDEO))
{
LONG Differ;
/* Determine intervening space. */
Differ = ((DisplayClip . MaxX - DisplayClip . MinX + 1) - Screen -> Width) / 2;
/* Adjust position. */
DisplayClip . MinX += Differ;
DisplayClip . MaxX -= Differ;
/* Open local screen,
* don't mess with the
* original screen.
*/
if(Info -> NewScreen = OpenScreenTags(NULL,
SA_Width, Screen -> Width,
SA_Height, Screen -> Height,
SA_DClip, &DisplayClip,
SA_Left, DisplayClip . MinX,
SA_Depth, Screen -> RastPort . BitMap -> Depth,
SA_DisplayID, Mode,
SA_Font, Screen -> Font,
SA_ShowTitle, FALSE,
SA_Quiet, TRUE,
SA_AutoScroll, TRUE,
SA_Behind, TRUE,
TAG_END))
{
struct Window *Window = Screen -> FirstWindow;
/* The simple way to make sure that
* the screen remains black.
*/
LoadPalette(Info -> NewScreen,Info -> BlackPalette,0);
/* Open a window our the local
* screen, just in case the user
* clicks the left mouse button.
*/
if(Info -> NewWindow = OpenWindowTags(NULL,
WA_Width, Screen -> Width,
WA_Height, Screen -> Height,
WA_Borderless, TRUE,
WA_Backdrop, TRUE,
WA_RMBTrap, TRUE,
WA_CustomScreen,Info -> NewScreen,
TAG_DONE))
{
/* Copy the input port. */
Info -> NewWindow -> UserPort = Window -> UserPort;
/* Install the standard main window IDCMP flags. */
ModifyIDCMP(Info -> NewWindow,IDCMP_MOUSEBUTTONS | IDCMP_MOUSEMOVE | IDCMP_MENUPICK | IDCMP_RAWKEY | IDCMP_VANILLAKEY | IDCMP_MENUVERIFY);
/* Clear the mouse pointer. */
SetPointer(Info -> NewWindow,Window -> Pointer,1,16,0,0);
/* Create the sync port. */
if(Info -> ScreenPort = CreateMsgPort())
{
Success = TRUE;
/* Allocate the double-buffering
* information.
*/
for(i = 0 ; Success && i < 2 ; i++)
{
if(Info -> ScreenBuffer[i] = AllocScreenBuffer(Info -> NewScreen,NULL,(i ? NULL : SB_SCREEN_BITMAP)))
{
Info -> ScreenBuffer[i] -> sb_DBufInfo -> dbi_DispMessage . mn_ReplyPort = Info -> ScreenPort;
BltBitMap(Screen -> RastPort . BitMap,0,0,Info -> ScreenBuffer[i] -> sb_BitMap,0,0,Info -> Screen -> Width,Info -> Screen -> Height,0xC0,0xFF,NULL);
}
else
Success = FALSE;
}
if(Success)
{
/* Allocate the temporary bitmap
* data is to be uncompressed in.
*/
if(Info -> UncompBitMap = AllocCustomBitMap(Screen -> RastPort . BitMap -> Depth,Screen -> Width,Screen -> Height,TRUE))
{
/* Bring the new screen to the front. */
ScreenToFront(Info -> NewScreen);
}
else
Success = FALSE;
}
}
}
}
}
}
else
{
Success = TRUE;
/* Allocate the double-buffering bitmaps. */
for(i = 0 ; Success && i < 2 ; i++)
{
if(!(Info -> BitMap[i] = AllocCustomBitMap(Screen -> RastPort . BitMap -> Depth,Screen -> Width,Screen -> Height,TRUE)))
Success = FALSE;
}
}
/* Successful so far? */
if(Success)
{
/* Create the timer io reply port. */
if(Info -> TimePort = CreateMsgPort())
{
/* Create the timer io request. */
if(Info -> TimeRequest = (struct timerequest *)CreateIORequest(Info -> TimePort,sizeof(struct timerequest)))
{
/* Open timer.device. */
if(!OpenDevice(TIMERNAME,UNIT_VBLANK,Info -> TimeRequest,0))
{
/* Remember the original viewport bitmap. */
if(!Is39)
Info -> OriginalBitMap = Screen -> ViewPort . RasInfo -> BitMap;
/* Swap the on-screen bitmaps. */
SwapDBI(Info,FALSE);
return(Info);
}
}
}
}
}
}
FreeDBI(Info);
}
return(NULL);
}
/* SwapDBI(struct DBI *Info,BYTE Copy):
*
* Swap the on-screen bitmaps.
*/
VOID
SwapDBI(struct DBI *Info,BYTE Copy)
{
/* Pre-v39 double-buffering? */
if(Info -> OriginalBitMap)
{
struct BitMap *Swap;
/* Install the `hidden' bitmap. */
Info -> Screen -> ViewPort . RasInfo -> BitMap = Swap = Info -> BitMap[0];
/* Rebuild screen copper list. */
MakeScreen(Info -> Screen);
RethinkDisplay();
/* Swap the bitmaps. */
Info -> BitMap[0] = Info -> BitMap[1];
Info -> BitMap[1] = Swap;
/* Copy the bitmap contents if necessary. */
if(Copy)
BltBitMap(Info -> BitMap[1],0,0,Info -> BitMap[0],0,0,Info -> Screen -> Width,Info -> Screen -> Height,0xC0,0xFF,NULL);
}
else
{
struct ScreenBuffer *Swap;
/* Blit the imagery to the hidden `bitmap'. */
BltBitMap(Info -> UncompBitMap,0,0,Info -> ScreenBuffer[0] -> sb_BitMap,0,0,Info -> NewScreen -> Width,Info -> NewScreen -> Height,0xC0,0xFF,NULL);
/* Install the hidden `bitmap'. */
ChangeScreenBuffer(Info -> NewScreen,Swap = Info -> ScreenBuffer[0]);
/* Swap the bitmaps. */
Info -> ScreenBuffer[0] = Info -> ScreenBuffer[1];
Info -> ScreenBuffer[1] = Swap;
/* Wait for bitmaps to get displayed. */
WaitPort(Info -> ScreenPort);
GetMsg(Info -> ScreenPort);
/* Copy the bitmap contents if necessary. */
if(Copy)
BltBitMap(Info -> ScreenBuffer[1] -> sb_BitMap,0,0,Info -> ScreenBuffer[0] -> sb_BitMap,0,0,Info -> NewScreen -> Width,Info -> NewScreen -> Height,0xC0,0xFF,NULL);
}
}
/* GetDBI(struct DBI *Info):
*
* Obtain the currently `hidden' bitmap.
*/
struct BitMap *
GetDBI(struct DBI *Info)
{
if(Info -> OriginalBitMap)
return(Info -> BitMap[0]);
else
return(Info -> UncompBitMap);
}
/* PaletteDBI(struct DBI *Info,struct Palette *Palette):
*
* Set the new colour palette.
*/
VOID
PaletteDBI(struct DBI *Info,struct Palette *Palette)
{
if(Info -> NewScreen)
LoadPalette(Info -> NewScreen,Palette,0);
else
LoadPalette(Info -> Screen,Palette,0);
}
/* StartDBI(struct DBI *Info,ULONG Jiffies):
*
* Start frame delay counter (1 jiffy = 1/60 s).
*/
VOID
StartDBI(struct DBI *Info,ULONG Jiffies)
{
Info -> TimeRequest -> tr_node . io_Command = TR_ADDREQUEST;
Info -> TimeRequest -> tr_time . tv_secs = Jiffies / 60;
Info -> TimeRequest -> tr_time . tv_micro = ((Jiffies % 60) * 1000000) / 60;
SendIO(Info -> TimeRequest);
}
/* WaitDBI(struct DBI *Info):
*
* Wait for timer to elapse.
*/
VOID
WaitDBI(struct DBI *Info)
{
WaitIO(Info -> TimeRequest);
}