home *** CD-ROM | disk | FTP | other *** search
-
- /***********************************************************************\
- * 2View V1.50 *
- * A simple, fast ILBM viewer, for use under AmigaOS V2.x. *
- * Written and ©1991-1992 by Dave Schreiber. All Rights Reserved. *
- * *
- * Usage: *
- * 2View FILE/A/M,FROM/K,SECS=SECONDS/K/N,TICKS/K/N,LOOP/S,PRINT *
- * *
- * Where the following arguments are defined as follows: *
- * FILE - The name of one (or more) IFF ILBM files *
- * FROM - A file containing a list of filenames. Used instead of FILE *
- * SECS - Number of seconds to display a file *
- * TICKS - Number of ticks (1/60ths of a second) *
- * LOOP - When finished showing the last pictures, start over *
- * PRINT - Print each picture as it is shown *
- * *
- * To compile (with SAS/C V5.10a): *
- * lc -v 2View ARexx *
- * lc -v -b0 Misc *
- * asm 2ViewAsm.a *
- * blink with 2View.lnk *
- * *
- * Version history: *
- * 1.50 - Rewrote the subroutine that reads the ILBM from disk in *
- * assembly language, for speed. Added support for SHAM and *
- * Macro Paint images, and for color cycling (both *
- * traditional (CRNG, i.e. continutout cycle ranges) and *
- * DPaint-IV style cycling (DRNG, i.e. non-continuous cycle *
- * ranges). A 'tick' (as used with the "TICK" keyword, above)*
- * has been redefined as 1/60th of a second. Finally, the *
- * source code in 2View.c has been split into two files *
- * (2View.c and Misc.c). *
- * Released 3/24/92 *
- * *
- * 1.11 - Improved error reporting (with this version, if the user *
- * run 2View from Workbench and there's an error, a requester *
- * is put up. Previously, the user was not notified at all *
- * of the error). *
- * Released 9/11/91 *
- * *
- * 1.10 - Added support for Workbench, ARexx, scrollable bitmaps, *
- * and printing. Also, the user can now use CTRL-C to advance*
- * to the next frame, and CTRL-D to abort a playlist. *
- * Released 9/3/91 *
- * *
- * 1.00 - Original version. Released 7/24/91 *
- * *
- \************************************************************************/
-
-
- unsigned long availBytes,curPos,bufSize;
-
- /*Include files*/
-
- #include <exec/types.h>
- #include <libraries/iffparse.h>
- #include <dos/dos.h>
- #include <dos/dosasl.h>
- #include <intuition/intuition.h>
- #include <exec/memory.h>
- #include <workbench/startup.h>
- #include <graphics/gfxbase.h>
-
- /*Prototypes*/
- #include <clib/exec_protos.h>
- #include <clib/intuition_protos.h>
- #include <clib/iffparse_protos.h>
-
- /*Pragmas*/
- #include <pragmas/exec_pragmas.h>
- #include <pragmas/intuition_pragmas.h>
- #include <pragmas/graphics_pragmas.h>
- #include <pragmas/iffparse_pragmas.h>
- #include <pragmas/dos_pragmas.h>
-
- /*Other include files*/
- #include "iff.h"
- #include "2View.h"
- #include "arexx.h"
-
- /*Libraries we'll need*/
- struct Library *IFFParseBase=NULL;
- struct Library *IntuitionBase=NULL;
- struct GfxBase *GfxBase=NULL;
-
- /*Provided by the compiler*/
- extern struct Library *SysBase;
- extern struct Library *DOSBase;
-
- /*Generic screen and window definitions. They will be used to define*/
- /*the screen and window that the various pictures will be shown on*/
- struct NewScreen newScreen=
- {
- 0,0,0,0,0,1,0,NULL,CUSTOMSCREEN|SCREENBEHIND|AUTOSCROLL,NULL,NULL,NULL,
- NULL
- };
-
- struct NewWindow newWindow =
- {
- 0,0,0,0,0,1,MENUDOWN|SELECTDOWN|ACTIVEWINDOW|VANILLAKEY,
- RMBTRAP|BORDERLESS|NOCAREREFRESH,NULL,NULL,NULL,NULL,NULL,
- 0,0,640,400,CUSTOMSCREEN
- };
-
- struct Screen *screen=NULL;
- struct Window *window=NULL;
-
- UWORD *storage;
- int counter;
-
- /*A true here indicates the current ILBM file is compressed*/
- BYTE Compression;
-
- /*An error message that used in various places*/
- char *errorMsg="An error occured while reading";
-
- /*The version string. Do a 'version 2View' to display it*/
- char *version="$VER: QView V1.50 (24.3.92)";
-
- /*Just so that the © message is part of the actual program*/
- char *copyRightMsg="Copyright 1991-1992 by Dave Schreiber. All Rights Reserved.";
-
- BYTE ExitFlag=FALSE; /*'Exit now' flag*/
- UWORD ticks=0; /*Delay requested by user.*/
-
- /*The previous screen and window*/
- struct Window *prevWindow=NULL;
- struct Screen *prevScreen=NULL;
-
- /*Data for a blank pointer*/
- UWORD chip fakePointerData[]={0,0,0,0,0};
-
- struct IFFHandle *iff=NULL; /*IFF handle*/
- BPTR pL=NULL; /*Playlist file pointer*/
- BOOL masking,print,toFront,printPics;
- extern struct WBStartup *WBenchMsg;
-
- char *playListFilename=NULL;
-
- /*Variables that have to be global so that ARexx.c can access them*/
- ButtonTypes rexxAbort=none;
- extern void dispRexxPort(void);
- extern void dnRexxPort();
- long arexxSigBit;
- UWORD ticksRemaining=0;
- BOOL loop=FALSE;
- BYTE specialModes;
-
- char *picFilename;
- char trashBuf[512]; /* A place to dump mask information */
- char *buf=trashBuf;
-
- void _main();
-
- struct TagItem TagList[]=
- {
- /* This defines what part of the displayed picture is shown. It's */
- /* necessary to have a line like this in here in order to get */
- /* 2.0 autoscrolling to work. */
- {SA_Overscan,OSCAN_VIDEO},
- {TAG_DONE,NULL}
- };
-
- char *about1="2View";
- char *about2="Please";
-
- extern struct EasyStruct erError1Line;
- BOOL cycle=FALSE;
- UBYTE numColors;
- UWORD destMap[32];
- UBYTE numCycleColors;
- UBYTE rate;
-
- /* The assembly-language reader routine */
- extern int ReadIntoBitMapAsm(PLANEPTR,APTR,struct IFFHandle *,
- ULONG,ULONG,UWORD,UBYTE,UBYTE,UBYTE);
-
- char **filenames;
- UWORD numFilenames=0,numSlots;
-
- void _main()
- {
- UWORD c;
- LONG args[7];
- char **filenames;
- char curFilename[140];
- BYTE playList; /*True if a playlist is being used, false otherwise*/
-
- /*Initialize the argument buffers to NULL*/
- for(c=0;c<7;c++)
- args[c]=NULL;
-
- /*Open the libraries*/
- IFFParseBase=(struct Library *)OpenLibrary("iffparse.library",0L);
- if(IFFParseBase==NULL)
- {
- cleanup();
- exit(50);
- }
-
- IntuitionBase=(struct Library *)OpenLibrary("intuition.library",0L);
- if(IntuitionBase==NULL)
- {
- cleanup();
- exit(75);
- }
-
- GfxBase=(struct GfxBase *)OpenLibrary("graphics.library",0L);
- if(GfxBase==NULL)
- {
- cleanup();
- exit(85);
- }
-
- /*Get the arguments*/
- if(WBenchMsg==NULL)
- {
- ParseArgs(args);
-
- /*If a playlist filename was provided, store it for later use*/
- if(args[4]!=NULL)
- {
- playListFilename=(char *)args[4];
- playList=TRUE;
- }
- else /*Otherwise, read the filenames from the command line*/
- playList=FALSE;
-
- /*If a time was provided (in ticks), use it*/
- if(args[1]!=NULL)
- ticks=*(ULONG *)args[1]*50;
-
- /*If a time was provided (in seconds), use it (overrides ticks)*/
- if(args[2]!=NULL && *(ULONG *)args[2]!=0)
- ticks=*(ULONG *)args[2];
-
- /*If neither a picture filename, nor a playlist filename, was*/
- /*specified, print an error and exit.*/
- if(args[0]==NULL && !playList)
- {
- printError("Please enter one or more filenames","");
- cleanup();
- exit(45);
- }
-
- /*Determine if we should print the pictures we display or not*/
- printPics=(args[5]!=NULL);
-
- /*Get the pointer to the list of filename*/
- filenames=(char **)args[0];
-
- /*Will we loop back to the beginning once we finish displaying all*/
- /*the pictures?*/
- loop=(args[3]!=NULL);
- }
- else
- if(WBenchMsg->sm_NumArgs==1)
- {
- EasyRequest(NULL,&erError1Line,NULL,
- "2View V1.50 (March 24, 1992)",
- "Written by Dave Schreiber");
- cleanup();
- exit(0);
- }
-
-
- /* Initialize the ARexx port */
- arexxSigBit=initRexxPort();
- if(arexxSigBit==0)
- {
- cleanup();
- exit(47);
- }
-
- /*Allocate the IFF structure*/
- iff=AllocIFF();
-
- /*If the allocation failed, abort*/
- if(iff==NULL)
- {
- printError("Couldn't allocate necessary resources","");
- cleanup();
- exit(100);
- }
-
- /*Run until we run out of filenames, or the user aborts*/
- while(!ExitFlag)
- {
- picFilename=curFilename; /*Get a pointer to the filename buffer*/
-
- /*Check to see if we're running from Workbench. If so, and the*/
- /*user provided names of pictures to display (by clicking on their*/
- /*icons), display those pictures*/
- if(WBenchMsg!=NULL && WBenchMsg->sm_NumArgs>1)
- {
- CurrentDir(WBenchMsg->sm_ArgList[1].wa_Lock);
- picFilename=WBenchMsg->sm_ArgList[1].wa_Name;
- }
- else if(playList) /*If a playlist is being used*/
- {
- pL=Open(playListFilename,MODE_OLDFILE); /*Open the playlist*/
-
- if(pL==NULL) /*If we couldn't open the playlist, abort*/
- {
- printError("Can't open playlist","");
- cleanup();
- exit(199);
- }
-
- do /*Loop until we run out of playlist, or get a valid name*/
- {
- if(FGets(pL,picFilename,140)==NULL) /*If end-of-file*/
- picFilename=NULL; /*Set as NULL as a flag*/
- }
- while(picFilename!=NULL && picFilename[0]==0x0A);
-
- if(picFilename!=NULL) /*If not NULL, it's a valid filename*/
- picFilename[strlen(picFilename)-1]=NULL; /*Remove the linefeed*/
- }
- else /*Otherwise, if a playlist isn't being used, get the current*/
- picFilename=filenames[0]; /*filename*/
-
-
- /*Loop while the user hasn't requested an abort, and while*/
- /*there are still files to display*/
- for(c=0;!ExitFlag && picFilename!=NULL;c++)
- {
- if((iff->iff_Stream=Open(picFilename,MODE_OLDFILE))==NULL)
- { /*If the ILBM file can't be opened...*/
-
- /*Print an error...*/
- printError("Can't open: ", picFilename);
-
- cleanup();
- exit(200);
- }
-
- InitIFFasDOS(iff); /*The IFF file will be read from disk*/
-
- OpenIFF(iff,IFFF_READ); /*Make iffparse.library aware of the*/
- /*ILBM file*/
-
- /*Read in the file and display*/
- ReadAndDisplay(picFilename,iff);
-
- CloseIFF(iff); /*Release iffparse's hold on the file*/
-
- Close(iff->iff_Stream); /*Close the file*/
-
- /*Get the next filename, either from Workbench,*/
- if(WBenchMsg!=NULL)
- {
- if(WBenchMsg->sm_NumArgs > c+2)
- {
- CurrentDir(WBenchMsg->sm_ArgList[c+2].wa_Lock);
- picFilename=WBenchMsg->sm_ArgList[c+2].wa_Name;
- }
- else
- picFilename=NULL;
- }
- else if(playList) /*The playlist*/
- {
- do
- {
- if(FGets(pL,picFilename,140)==NULL)
- picFilename=NULL;
- }
- while(picFilename!=NULL && picFilename[0]==0x0A);
-
- if(picFilename!=NULL)
- picFilename[strlen(picFilename)-1]=NULL;
- }
- else /*or the command line*/
- picFilename=filenames[c+1];
- }
-
- /*We're finished with this run of pictures*/
- if(playList) /*Close playlist, if open*/
- Close(pL);
- pL=NULL;
-
- if(!loop && !printPics) /*If the loop flag wasn't given, exit*/
- ExitFlag=TRUE;
- }
-
- /*Time to exit, so close stuff*/
-
- cleanup();
- exit(0); /*And exit*/
- }
-
- LONG ilbmprops[] = { ID_ILBM,ID_CMAP,ID_ILBM,ID_BMHD,ID_ILBM,ID_CAMG,
- ID_ILBM,ID_CRNG,ID_ILBM,ID_DRNG,ID_ILBM,ID_SHAM,
- ID_ILBM,ID_CTBL };
-
- /*Read in an ILBM file and display it*/
- void ReadAndDisplay(char *filename,struct IFFHandle *iff)
- {
- int error;
- UBYTE *bodyBuffer; /*Pointer to buffer holding 'BODY' chunk info*/
- ULONG ViewModes; /*Holds the viewmodes flags*/
- UWORD c;
- ButtonTypes button;
- UBYTE cycleTable[32];
- UBYTE countDown;
-
- /*Structures required for IFF parsing*/
- struct StoredProperty *bmhd,*cmap,*camg,*crng,*drng,*sham,*ctbl;
- struct ContextNode *bodyContext;
-
- /*IntuiMessage...*/
- struct IntuiMessage *mesg;
-
- /*Indentify chunks that should be stored during parse*/
- /*(in this case, CMAP, BMHD, CRNG, DRNG, CAMG, and SHAM)*/
- error=PropChunks(iff,ilbmprops,7);
-
- /*If there was an error, print a message and return*/
- if(error!=0)
- {
- printError(errorMsg,filename);
- ExitFlag=TRUE;
- return;
- }
-
- /*Tell iffparse to stop at a 'BODY' chunk*/
- error=StopChunk(iff,ID_ILBM,ID_BODY);
-
- /*Error handling yet again*/
- if(error!=0 && error!=-1)
- {
- printError(errorMsg,filename);
- ExitFlag=TRUE;
- return;
- }
-
- /*Do the actual parsing*/
- error=ParseIFF(iff,IFFPARSE_SCAN);
-
- /*Check for errors yet again*/
- if(error!=0 && error !=-1)
- {
- printError(errorMsg,filename);
- ExitFlag=TRUE;
- return;
- }
-
- /*Get the chunks that were found in the file*/
- bmhd = FindProp(iff,ID_ILBM,ID_BMHD); /*Bitmap information*/
- cmap = FindProp(iff,ID_ILBM,ID_CMAP); /*Color map*/
- camg = FindProp(iff,ID_ILBM,ID_CAMG); /*Amiga viewmode information*/
- crng = FindProp(iff,ID_ILBM,ID_CRNG); /*Color-cycling ranges*/
- drng = FindProp(iff,ID_ILBM,ID_DRNG); /*New (DPaint IV) color-cycling*/
- sham = FindProp(iff,ID_ILBM,ID_SHAM); /*SHAM color tables*/
- ctbl = FindProp(iff,ID_ILBM,ID_CTBL); /*Macro Paint color table info*/
-
- /*Get the descriptor for the BODY chunk*/
- bodyContext=CurrentChunk(iff);
-
- /*If there wasn't a BMHD, CMAP, or BODY chunk, abort*/
- if(!bmhd | !cmap | !bodyContext)
- {
- printError(filename,"is corrupted or is not in Amiga ILBM format");
- ExitFlag=TRUE;
- return;
- }
-
- /*Prepare to determine screen modes*/
- newScreen.ViewModes=NULL;
-
- /*If there was a CAMG chunk, use it to get the viewmodes*/
- if(camg!=NULL)
- {
- ViewModes=( ((CAMG *)(camg->sp_Data))->viewmodes );
-
- if(ViewModes & HAM)
- newScreen.ViewModes|=HAM;
-
- if(ViewModes & EXTRA_HALFBRITE)
- newScreen.ViewModes|=EXTRA_HALFBRITE;
-
- if(ViewModes & LACE)
- newScreen.ViewModes|=LACE;
-
- if(ViewModes & HIRES)
- newScreen.ViewModes|=HIRES;
- }
-
-
- if(crng==NULL)
- if(drng==NULL) /*No color cycling*/
- numCycleColors=0;
- else /* DPaint-IV--style color cycling*/
- numCycleColors=interpretDRNG(cycleTable,(DRNG *)(drng->sp_Data),&rate);
- else /*DPaint I-III--style color cycling*/
- numCycleColors=interpretCRNG( cycleTable,(CRNG *)(crng->sp_Data),&rate);
-
- if(numCycleColors != 0)
- cycle=TRUE; /*Start cycling if there are colors to cycle*/
- else
- cycle=FALSE;
-
- /*Interpret the BMHD chunk*/
- getBMHD((struct BitMapHeader *)bmhd->sp_Data);
-
- /*Don't open an interlace screen if the image is in SHAM mode*/
- /*(the Amiga OS doesn't properly handle user copper lists on */
- /*interlaced screens for some reason)*/
- if(sham!=NULL)
- newScreen.ViewModes&=~LACE;
-
- /*Open a screen, defined by the BMHD and CAMG chunks*/
- screen=OpenScreenTagList(&newScreen,TagList);
-
- /*If the screen couldn't be opened, abort*/
- if(screen==NULL)
- {
- printError("Cannot open screen!","");
- ExitFlag=TRUE;
- return;
- }
-
- /*This more properly centers the screen, for some reason */
- MoveScreen(screen,1,1);
- MoveScreen(screen,-1,-1);
-
- /*Set the window dimensions from the screen dimensions*/
- newWindow.Screen=screen;
- newWindow.Width=newScreen.Width;
- newWindow.Height=newScreen.Height;
-
- /*Open the window*/
- window=OpenWindow(&newWindow);
-
- /*Abort if the window couldn't be opened*/
- if(window==NULL)
- {
- printError("Cannot open window!","");
-
- ExitFlag=TRUE;
- return;
- }
-
- /*Allocate enough memory to hold the BODY data*/
- /*We want to find out what the biggest block of memory is. If*/
- /*we have enough memory to hold the entire body chunk, we'll load*/
- /*the whole thing into memory and decompress from there. If not,*/
- /*we'll load as much as we can and refill the buffer when it*/
- /*empties*/
- /*We do a Forbid() to keep anyone from allocating memory between*/
- /*the AvailMem() and AllocMem() calls. This way, we're guaranteed*/
- /*that a memory block of the size given by Availmem() can be */
- /*allocated. For this reason, we don't need to check the result*/
- /*of the AllocMem(); we're guaranteed that it worked*/
- Forbid();
- bufSize=AvailMem(MEMF_LARGEST);
- bufSize=MIN(bufSize,bodyContext->cn_Size+1);
- if(bufSize==0) /*It'll never happen, but just in case...*/
- {
- Permit();
- ExitFlag=TRUE;
- return;
- }
-
- bodyBuffer=AllocMem(bufSize,0L);
- Permit();
-
- availBytes = bufSize;
- curPos = bufSize;
-
- /*Blank out the pointer*/
- SetPointer(window,fakePointerData,1,16,0,0);
-
- /*Set the screen colors to those provided in the CMAP chunk*/
- setScreenColors(screen,cmap->sp_Data,newScreen.Depth,destMap,&numColors);
-
- /*Uncompress an ILBM and copy it into the bitmap*/
- if(ReadIntoBitmapAsm(&(screen->BitMap.Planes),bodyBuffer,iff,bufSize,
- (ULONG)screen->BitMap.BytesPerRow,
- screen->BitMap.Rows,
- screen->BitMap.Depth,(Compression==1) ? 1 : 0,
- (masking) ? 1 : 0))
- {
- printError(errorMsg,"");
- cleanup();
- exit(2000);
- }
-
-
- /*Activate the window, and flush any IDCMP message*/
- ActivateWindow(window);
- while((mesg=(struct IntuiMessage *)GetMsg(window->UserPort))!=NULL)
- ReplyMsg((struct Message *)mesg);
-
-
- /*If this is a SHAM image, setup the copper list appropriately*/
- if(sham!=NULL)
- {
- specialModes=SHAM;
- setupSHAM(screen,(UWORD *)(sham->sp_Data));
- }
- else
- /*If this is a MacroPaint image, setup the copper list*/
- if(ctbl!=NULL)
- {
- specialModes=MACROPAINT;
- setupDynHires(screen,(UWORD *)(ctbl->sp_Data));
- }
- else
- /* Otherwise, this is a normal ILBM*/
- specialModes=NORMAL;
-
- /*Bring the screen to the front*/
- ScreenToFront(screen);
-
- /*If the user used the 'print' flag on the command line, print*/
- /*the picture (but not if this is a SHAM or MacroPaint image)*/
- if(printPics && specialModes == NORMAL)
- dumpRastPort(&(screen->RastPort),&(screen->ViewPort));
-
- print=TRUE;
-
- /*Close the previous window and screen*/
- if(prevWindow!=NULL)
- CloseWindow(prevWindow);
- if(prevScreen!=NULL)
- CloseScreen(prevScreen);
-
- /*Free the buffer that holds the BODY chunk information*/
- FreeMem(bodyBuffer,bufSize);
-
- /*Store the current window & screen structures, so they can be*/
- /*closed later*/
- prevWindow=window;
- prevScreen=screen;
-
- screen=NULL;
- window=NULL;
-
- rexxAbort=none;
- countDown=rate;
- if(ticks==0) /*If ticks==0, this means that no delay was specified*/
- { /*by the user. So just wait for him to click a button*/
- int prevTopEdge=prevScreen->TopEdge;
-
- while((button=checkButton())==none && rexxAbort==none)
- {
- /*Wait for 1/60th of a second*/
- WaitTOF();
-
- /*Refresh the SHAM copper list if required*/
- if(prevTopEdge!=prevScreen->TopEdge && sham!=NULL)
- {
- prevTopEdge=prevScreen->TopEdge;
- setupSHAM(prevScreen,(UWORD *)(sham->sp_Data));
- }
-
- /*Refresh the MacroPaint copper list if required*?
- if(prevTopEdge!=prevScreen->TopEdge && ctbl!=NULL)
- {
- prevTopEdge=prevScreen->TopEdge;
- setupDynHires(prevScreen,(UWORD *)(ctbl->sp_Data));
- }
-
- /*If its time to cycle the colors, then cycle them*/
- if(cycle && numCycleColors!=0 && --countDown==0)
- {
- cycleColors(cycleTable,destMap,numCycleColors,numColors);
- countDown=rate;
- }
- dispRexxPort();
- }
-
- /*Check to see if the user wants to abort*/
- if(button==menu || rexxAbort==menu)
- ExitFlag=TRUE;
- }
- else /*Otherwise, wait for the specified amount of time*/
- {
- for(c=0;c<ticks;c++)
- {
- /*Wait 1/60th of a second*/
- WaitTOF();
-
- /*Cycle colors if necessary*/
- if(cycle && numCycleColors!=0 && --countDown==0)
- {
- cycleColors(cycleTable,destMap,numCycleColors,numColors);
- countDown=rate;
- }
-
- dispRexxPort(); /*Check ARexx port*/
-
- button=checkButton(); /*After each 25 ticks, check to see if*/
- if(button==menu || rexxAbort==menu) /*the user wants to abort*/
- {
- ExitFlag=TRUE;
- return;
- }
- if(button==select || rexxAbort==select) /*Or advance prematurely*/
- return;
- }
- }
- }
-
- /*End of 2View.c*/
-
-