/* Copyright © 1991 Lake Forest Logic Inc. */ /* SHAZAM: Macro Paint picture viewer version 1.0 */ /* 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 support Macro Paint images in their viewer programs. The 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/30/91 This program is version 1.0: 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 file without permission. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #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); } struct View *vshift; struct Screen *screen=0; struct NewScreen plane; struct GfxBase *GfxBase; struct IntuitionBase *IntuitionBase=0; struct ViewPort *vp; UWORD inmap[64],*Coppers; char DISPLAY=1,LACEME=0,OSCAN=16,OSTART=4,TRUNK=1; int COPHEIGHT; #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)) struct Custom *custom; struct UCopList *ucop=0; struct QBMHD { UWORD w, h; /* raster width & height in pixels */ WORD x, y; /* position for this image */ UBYTE nPlanes; /* # source bitplanes */ UBYTE masking; /* masking technique */ UBYTE compression; /* compression algoithm */ UBYTE pad1; /* UNUSED. For consistency, put 0 here.*/ UWORD transparentColor; /* transparent "color number" */ UBYTE xAspect, yAspect; /* aspect ratio, a rational number x/y */ WORD pageWidth, pageHeight; /* source "page" size in pixels */ }; void QDV(BPTR); void PutCop(void); void Chunker(BPTR,ULONG *,int); void GetScreen(struct QBMHD *header); void UnScreen(void); char UnpackRLL(BYTE **,BYTE **,int,int); main(int argc,char **argv) { ULONG handle; printf("\n\233;1mSHAZAM\233;0m V1.0 © 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); } QDV(handle); Close(handle); } printf("\n"); return(DISPLAY); } void QDV(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; } void Chunker(BPTR handle,ULONG *buffer,int total) { int here,result,size,loop,planes,lines,bites,line,plane; struct QBMHD *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) { SetRGB4(&screen->ViewPort, 0,(Coppers[0]>>8)&15,(Coppers[0]>>4)&15,Coppers[0]&15); SetRGB4(&screen->ViewPort, 1,(Coppers[1]>>8)&15,(Coppers[1]>>4)&15,Coppers[1]&15); SetRGB4(&screen->ViewPort, 2,(Coppers[2]>>8)&15,(Coppers[2]>>4)&15,Coppers[2]&15); SetRGB4(&screen->ViewPort, 3,(Coppers[3]>>8)&15,(Coppers[3]>>4)&15,Coppers[3]&15); SetRGB4(&screen->ViewPort, 4,4,4,4); SetRGB4(&screen->ViewPort, 5,5,5,5); SetRGB4(&screen->ViewPort, 6,6,6,6); SetRGB4(&screen->ViewPort, 7,7,7,7); SetRGB4(&screen->ViewPort, 8,8,8,8); SetRGB4(&screen->ViewPort, 9,9,9,9); SetRGB4(&screen->ViewPort,10,10,10,10); SetRGB4(&screen->ViewPort,11,11,11,11); SetRGB4(&screen->ViewPort,12,12,12,12); SetRGB4(&screen->ViewPort,13,13,13,13); SetRGB4(&screen->ViewPort,14,14,14,14); SetRGB4(&screen->ViewPort,15,15,15,15); } } } else if(buffer[0]==ID_BMHD) { result=Read(handle,buffer,size); if(!DISPLAY) { bmhd=(struct QBMHD *)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;loop>1)>GfxBase->NormalDisplayRows) { shifted=((COPHEIGHT>>1)-GfxBase->NormalDisplayRows)>>1; vshift->DyOffset-=shifted; } PutCop(); getchar(); if(!TRUNK) vshift->DyOffset+=shifted; FreeVPortCopLists(&screen->ViewPort); RemakeDisplay(); CloseScreen(screen); if(Coppers) FreeMem(Coppers,COPHEIGHT<<5); } if(IntuitionBase) CloseLibrary((struct Library *)IntuitionBase); if(GfxBase) CloseLibrary((struct Library *)GfxBase); } void PutCop() { int line,creg,top; ucop=(struct UCopList *)AllocMem(sizeof(struct UCopList),MEMF_CLEAR); top=COPHEIGHT; if(LACEME) top=top/2; if(TRUNK) if(top>GfxBase->NormalDisplayRows) top=GfxBase->NormalDisplayRows; 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(); } void GetScreen(struct QBMHD *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; } 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); }