The Scott-Free Gfx Format An attempt of an explaination By Andreas Aumayr $VER: 1.00, 29/Dec/1997 Contents: I) Introduction II) Hunk structure IIa) Info hunk IIb) Offset hunk IIc) Logic hunk IId) Data hunk III) Action 89 IV) Tools V) Conclusion I) Introduction This gfx format is the result of a sometimes lengthy discussion between Paul David Doherty and myself. Our aim was to create a simple but nevertheless flexible structure with all the graphics information put into one single file. Certainly we completely failed in our mission but we have an independent "Scott-Free-Gfx-File-Format" now and at least it's just a single file :-) II) Hunk structure There are 4 hunks and these are: a) Info hunk b) Offset hunk c) Logic hunk d) Data hunk IIa) Info hunk Has just the right complexity for an easy beginning. It only includes information about the picture size = width * height and number of pictures. //Check if gfx are available gfx_in_file = fopen(gfx_file,"rb"); if (gfx_in_file == NULL) GFX = FALSE; //Fetch GFX info from binary file (if GFX == TRUE :-)) gfx_width = fgetc(gfx_in_file)*256 + fgetc(gfx_in_file); gfx_height = fgetc(gfx_in_file)*256 + fgetc(gfx_in_file); nroom = fgetc(gfx_in_file); // Number of rooms (+1 if showPIC // starts with 0 and not 1 !!!) nac89 = fgetc(gfx_in_file); // Number of Action89 pics fgetc(gfx_in_file); // Number of extended (conditional) room pics // (rooms can have more than 1 pic) IIb) Offset hunk Includes byte offsets from byte 0 of the gfx file to each of the pic data (pic data is in hunk d). Each offset is 3 bytes long. If a room has no picture, offset is set to zero (Scott Free Amiga closes the picture window in those rare cases). If there is absolutely nothing to do, offset is 255. This is my prefered case :-). If two or more different rooms share the same pic, offset is the same, too (thus file length is a bit shorter). First offset (offset for pic 0) is always the offset to the darkness-pic. count = fgetc(gfx_in_file); // number of offsets // = number of pics go = malloc(sizeof(unsigned long) * count); // allocate mem // for offsets fread(&in_dat[0],1,count*3,gfx_in_file); // fetch offsets for (i=0; i= ii) { if (rp[Room].pnr[j] == 0) { // no picture if (pic_w_hdl) { win_pos_ver = pic_w_hdl->LeftEdge; // save window position win_pos_hor = pic_w_hdl->TopEdge; CloseWindow(pic_w_hdl); pic_w_hdl = 0; } last_pic = -128; // remember: no last pic return(FALSE); } if (rp[Room].pnr[j] == 255) return(FALSE); // 255 = do nothing if (last_pic >= 0) { if ((go[last_pic] == go[rp[Room].pnr[j]])) return(FALSE); } switch ((int)(rp[Room].what[j]/10)) { case PIC: // Show Pic Open_Pic(rp[Room].pnr[j],PIC); return(TRUE); case COC: // colour cycling, not implemented yet break; case OVL: // overlay picture yes = 1; if (last_pic != Room) { for (i=0; i=size) return; } repeat = rle_dat[j++]-128; for (count=0; count < repeat; count++) picture[i++] = rle_dat[j]; j++; } 2) LDP: Pictures are stored as a sequence of drawing commands (MOVE, DRAW and FILL). Thus the picture size is very small compared to the the bitmap format. Overlay pictures are not supported. Use the source below for reading and drawing of picture data: void Draw_Pic(UBYTE pic_nr, UBYTE mode) { UBYTE command,col; UWORD x,y; Check_Win(); if (pic_w_hdl) { if (mode) { if ((fgetc(gfx_in_file) != NEWPIC) || (fgetc(gfx_in_file) != pic_nr)) { GFX_Off(); EasyRequest(act_w_hdl,&NoGFX,NULL,"GFX datafile corrupt\nor wrong datafile (NEWPIC/COL).\nGFX will be switched off."); if (pic_w_hdl) CloseWindow(pic_w_hdl); pic_w_hdl = 0; return; } col = fgetc(gfx_in_file); SetPen(col); // set background color RectFill(rastPort,border_width,bar_height,gfx_width-1+border_width,gfx_height-1+bar_height); col=(col==0)?7:0; SetPen(col); // set drawing color DrawPicFrame(); // draw frame as border for FILL if (FASTCOLOURS) { SafeSetOutlinePen(rastPort,col+4); } else { SafeSetOutlinePen(rastPort,Pens[col]); // set bordercolor for FLOOD 0 } command = fgetc(gfx_in_file); while (command != NEWPIC) { switch (command) { case MOVE: y = fgetc(gfx_in_file) + bar_height; x = fgetc(gfx_in_file) + border_width; Move(rastPort,x,y); break; case FILL: col = fgetc(gfx_in_file); y = fgetc(gfx_in_file) + bar_height; x = fgetc(gfx_in_file) + border_width; SetPen(col); Flood(rastPort,0,x,y); break; default: //DRAW x = fgetc(gfx_in_file) + border_width; Draw(rastPort,x,command + bar_height); break; } command = fgetc(gfx_in_file); } } else { //it's dark out there SetPen(0); //black RectFill(rastPort,border_width,bar_height,gfx_width-1+border_width,gfx_height-1+bar_height); DrawPicFrame(); // just to be on the safe side } } III) Action 89 ... or how to look at something. Sometimes there are special pictures for some very special objects in the game. Try to "look at dragon" in Adventureland as an example. These pictures are stored right behind the default room pictures in the data hunk (and that means on the other hand right before the conditional room pictures). IV) Tools All of those bitmap gfx-files are created with the help of some converting tools on my Amiga 3000. Source code is available at request, but be aware that this stuff is very Amiga specific because of the extensive use of datatypes. However, the basics are to take (snapshot) those bitmap gfx picture for picture from one or more of the original adventures (PDD's part and loads of work). Then merge them together with the gfx-logic (after converting, compressing and formatting) into one huge file and that's it. Sounds quite easy, doesn't it? Additionally there is a little tool to create LDP gfx files (basically written by David Lodge who discovered the LDP format) out of *.sna files (Sinclair Spectrum snapshots). And yes, this proggy even exists for Windooze machines. V) Conclusion Oh well, what a mess. If you still know what's going on, don't blame me. But if you ever need further assistance you can always contact me and I'll be glad to help you. E-Mail: anden@ping.at Snail : Andreas Aumayr Weidenweg 22 A-4210 Engerwitzdorf Austria