/* Copyright © 1991 Lake Forest Logic Inc. */ /* SHAZAM: Macro Paint picture viewer version 1.1 */ /* This program is designed to display dynamic hires images created with Macro Paint, the 4096 color high-resolution paint program from Lake Forest Logic. The source code is provided so that others can support Macro Paint images in their viewer programs. There is quite a bit of room for improvement in this program but we felt it was important to release a usable viewer as soon as possible. 1/31/91 This program is version 1.1: bug reports and suggestions are welcome and may be sent to: Lake Forest Logic Inc. 28101 Ballard Road, Unit E Lake Forest, IL 60045 (708)816-6666 FAX: (708)680-0832 BBS: (708)680-0590 HST, 24 hours BIX: equack PLink: LFL*ERIK The program was compiled using SAS/C Version 5.10a. The command "LC -rr -L shazam" should suffice to compile and link it. Permission is granted to distribute this file for non-commercial purposes. Portions of the compiled code may be incorporated into your own programs (commercial or otherwise), but you may not distribute a modified version of this source file without permission. */ #include #include #include #include #include #include #include #include #include #include #include #include /* short hand */ #define NL (0) #define CINIT(c,n) { UCopperListInit(c,n); } #define CWAIT(c,a,b) { CWait(c,a,b);CBump(c); } #define CEND(c) { CWAIT(c,10000,255); } #define CMOVE(c,a,b) { CMove(c,(long)&a,b);CBump(c); } #define MakeID(a,b,c,d) ( (LONG)(a)<<24L | (LONG)(b)<<16L | (c)<<8 | (d) ) #define ID_FORM MakeID('F','O','R','M') #define ID_MPCT MakeID('M','P','C','T') #define ID_DYCP MakeID('D','Y','C','P') #define ID_CTBL MakeID('C','T','B','L') #define ID_BMHD MakeID('B','M','H','D') #define ID_CMAP MakeID('C','M','A','P') #define ID_BODY MakeID('B','O','D','Y') #define BUFSIZE (8192) #define UGetByte() (*source++) #define UPutByte(c) (*dest++ = (c)) /* some global data */ struct View *vshift; struct Screen *screen=0; struct NewScreen plane; struct GfxBase *GfxBase; struct IntuitionBase *IntuitionBase=0; struct ViewPort *vp; int COPHEIGHT; char DISPLAY=1,LACEME=0,OSCAN=16; UWORD inmap[64],*Coppers; UWORD colors[16]={0x000,0x111,0x222,0x333,0x444,0x555,0x666,0x777, 0x888,0x999,0xaaa,0xbbb,0xccc,0xddd,0xeee,0xfff}; struct Custom *custom; struct UCopList *ucop=0; struct BMHD { UWORD w, h; WORD x, y; UBYTE nPlanes; UBYTE masking; UBYTE compression; UBYTE pad1; UWORD transparentColor; UBYTE xAspect, yAspect; WORD pageWidth, pageHeight; }; /* function prototypes */ void Shazam(BPTR); void PutCop(void); void Chunker(BPTR,ULONG *,int); void GetScreen(struct BMHD *header); void UnScreen(void); char UnpackRLL(BYTE **,BYTE **,int,int); main(int argc,char **argv) { ULONG handle; printf("\n\233;1mSHAZAM\233;0m V1.1 © 1991 Lake Forest Logic Inc.\n\n"); if(argc<2) { printf(" Syntax: SHAZAM \n"); } else { handle=Open(argv[1],MODE_OLDFILE); if(!handle) { printf(" Error: unable to open file \233;32m%s\233;0m\n",argv[1]); return(1); } Shazam(handle); Close(handle); } printf("\n"); return(DISPLAY); } /* get started */ void Shazam(BPTR handle) { ULONG *buffer; int result; buffer=AllocMem(BUFSIZE,0); if(!buffer) { printf(" Error: not enough memory.\n"); DISPLAY=1; return; } result=Read(handle,buffer,12); if(result!=12) { printf(" Error: unable to read header.\n"); DISPLAY=1; return; } if(buffer[0]!=ID_FORM) { printf(" Error: not an IFF file.\n"); DISPLAY=1; return; } Chunker(handle,buffer,buffer[1]-4); UnScreen(); FreeMem(buffer,BUFSIZE); return; } /* chop up those IFF chunks */ void Chunker(BPTR handle,ULONG *buffer,int total) { int here,result,size,loop,planes,lines,bites,line,plane; struct BMHD *bmhd; UBYTE *collar, *source,*dest; here=0; custom=(struct Custom *) 0x00DFF000; while(hereBitMap.Rows; planes=screen->BitMap.Depth; bites=screen->BitMap.BytesPerRow; source=collar; for(line=0;lineBitMap.Planes[plane]+line*bites; result=UnpackRLL(&source,&dest,size,bites); if(result) { printf(" Error %d: unable to unpack BODY L:%d P:%d.\n", result,line,plane); DISPLAY=1; FreeMem(collar,size); here+=size+8; return; } } } FreeMem(collar,size); } } } else if(buffer[0]==ID_CMAP) { result=Read(handle,buffer,size); if(screen) { collar=(BYTE *)buffer; for(loop=0;loop>4)<<8)+((collar[loop*3+1]>>4)<<4)+(collar[loop*3+2]>>4); SetRGB4(&screen->ViewPort, loop,collar[loop*3]>>4,collar[loop*3+1]>>4,collar[loop*3+2]>>4); } } } else if(buffer[0]==ID_CTBL) { Coppers=AllocMem(size,0); if(!Coppers) DISPLAY=1; else { COPHEIGHT=size/32; result=Read(handle,Coppers,size); if(!DISPLAY) { colors[0]=Coppers[0]; colors[1]=Coppers[1]; colors[2]=Coppers[2]; colors[3]=Coppers[3]; LoadRGB4(&screen->ViewPort,colors,20); } } } else if(buffer[0]==ID_BMHD) { result=Read(handle,buffer,size); if(!DISPLAY) { bmhd=(struct BMHD *)buffer; GetScreen(bmhd); } else { printf(" Not a Macro Paint picture file.\n"); DISPLAY=1; } } else { if(size%BUFSIZE) { result=Read(handle,buffer,size%BUFSIZE); if(result!=size%BUFSIZE) { printf(" Error: unable to read chunk body.\n"); DISPLAY=1; return; } } if(size/BUFSIZE) for(loop=0;loopDyOffset; if(GfxBase->LibNode.lib_Version<36) /* dead reckoning */ { if((COPHEIGHT>>1)>GfxBase->NormalDisplayRows) vshift->DyOffset=14; } else { if((COPHEIGHT>>1)>GfxBase->NormalDisplayRows) vshift->DyOffset=22; } PutCop(); getchar(); vshift->DyOffset=preserve; FreeVPortCopLists(&screen->ViewPort); RemakeDisplay(); CloseScreen(screen); if(Coppers) FreeMem(Coppers,COPHEIGHT<<5); } if(IntuitionBase) CloseLibrary((struct Library *)IntuitionBase); if(GfxBase) CloseLibrary((struct Library *)GfxBase); } /* our copper list 'magic' */ void PutCop() { int line,creg,top; ucop=(struct UCopList *)AllocMem(sizeof(struct UCopList),MEMF_CLEAR); top=COPHEIGHT; if(LACEME) top=top/2; CINIT(ucop,top*13); for(line=0;linecolor[creg],Coppers[(line<<5)+creg]); } else { CMOVE(ucop,custom->color[creg],Coppers[(line<<4)+creg]); } } } CEND(ucop); printf("Press return.\n"); Forbid(); vp->UCopIns=ucop; Permit(); MakeScreen(screen); RethinkDisplay(); } /* throw up a screen */ void GetScreen(struct BMHD *header) { IntuitionBase=(struct IntuitionBase *)OpenLibrary("intuition.library",33); if(!IntuitionBase) { printf(" Error: unable to open Intuition!\n"); return; } GfxBase=(struct GfxBase *)OpenLibrary("graphics.library",33); if(!GfxBase) { printf(" Error: unable to open graphics.\n"); return; } plane.LeftEdge=0; plane.TopEdge=0; plane.DetailPen=2; plane.BlockPen=1; plane.Type=CUSTOMSCREEN|SCREENQUIET; plane.Font=0; plane.DefaultTitle="SHAZAM Screen"; plane.Gadgets=0; plane.CustomBitMap=0; plane.ViewModes=0; plane.Width=header->w; plane.Height=header->h; plane.Depth=header->nPlanes; plane.ViewModes|=HIRES; if(header->h>300) { plane.ViewModes|=LACE; LACEME=1; } if(header->w>640) OSCAN=14; screen=OpenScreen(&plane); vp=&screen->ViewPort; return; } /* BODY voodoo */ char UnpackRLL(BYTE **pSource,BYTE **pDest,int srcBytes0,int dstBytes0) { int srcBytes,dstBytes; BYTE *source, *dest, c; WORD n,minus128=-128; source=*pSource; dest=*pDest; srcBytes=srcBytes0; dstBytes=dstBytes0; while(dstBytes>0) { if((srcBytes-=1)<0) return(1); n=UGetByte(); if (n >= 0) { n += 1; if((srcBytes-=n)<0) return(2); if((dstBytes-=n)<0) return(3); do { UPutByte(UGetByte()); } while(--n>0); } else if(n!=minus128) { n = -n + 1; if((srcBytes-=1)<0) return(4); if((dstBytes-=n)<0) return(5); c = UGetByte(); do { UPutByte(c); } while(--n>0); } } *pSource=source; *pDest=dest; return(0); }