From: Holger Schemel Date: Fri, 4 Sep 1998 02:06:03 +0000 (+0200) Subject: rnd-19980904-1 X-Git-Tag: 1.2.0^2~88 X-Git-Url: https://git.artsoft.org/?a=commitdiff_plain;h=4b0f1eb4220d2dbe4cffb288f745661b32c96a5b;p=rocksndiamonds.git rnd-19980904-1 --- diff --git a/src/Makefile b/src/Makefile index 27bcd6fc..4edb1937 100644 --- a/src/Makefile +++ b/src/Makefile @@ -59,7 +59,11 @@ SRCS = main.c \ sound.c \ joystick.c \ cartoons.c \ - gfxloader.c \ + gfxload.c \ + gifload.c \ + gif.c \ + send.c \ + new.c \ random.c OBJS = main.o \ @@ -76,7 +80,11 @@ OBJS = main.o \ sound.o \ joystick.o \ cartoons.o \ - gfxloader.o \ + gfxload.o \ + gifload.o \ + gif.o \ + send.o \ + new.o \ random.o all: $(OBJS) diff --git a/src/events.c b/src/events.c index 4fecf144..edce9a9c 100644 --- a/src/events.c +++ b/src/events.c @@ -13,6 +13,7 @@ ***********************************************************/ #include "events.h" +#include "init.h" #include "screens.h" #include "tools.h" #include "game.h" @@ -54,6 +55,9 @@ void EventLoop(void) case FocusOut: HandleFocusEvent((XFocusChangeEvent *) &event); break; + case ClientMessage: + HandleClientMessageEvent((XClientMessageEvent *) &event); + break; default: break; } @@ -97,6 +101,9 @@ void ClearEventQueue() case FocusOut: HandleFocusEvent((XFocusChangeEvent *) &event); break; + case ClientMessage: + HandleClientMessageEvent((XClientMessageEvent *) &event); + break; default: break; } @@ -129,6 +136,9 @@ void SleepWhileUnmapped() case MapNotify: window_unmapped = FALSE; break; + case ClientMessage: + HandleClientMessageEvent((XClientMessageEvent *) &event); + break; default: break; } @@ -218,6 +228,13 @@ void HandleFocusEvent(XFocusChangeEvent *event) } } +void HandleClientMessageEvent(XClientMessageEvent *event) +{ + if ((event->window == window) && + (event->data.l[0] == XInternAtom(display, "WM_DELETE_WINDOW", FALSE))) + CloseAll(); +} + void HandleButton(int mx, int my, int button) { static int old_mx = 0, old_my = 0; @@ -284,7 +301,9 @@ void HandleKey(KeySym key, int key_status) case XK_KP_Left: #endif case XK_KP_4: +#ifndef MSDOS case XK_J: +#endif case XK_j: joy |= JOY_LEFT; break; @@ -293,7 +312,9 @@ void HandleKey(KeySym key, int key_status) case XK_KP_Right: #endif case XK_KP_6: +#ifndef MSDOS case XK_K: +#endif case XK_k: joy |= JOY_RIGHT; break; @@ -302,7 +323,9 @@ void HandleKey(KeySym key, int key_status) case XK_KP_Up: #endif case XK_KP_8: +#ifndef MSDOS case XK_I: +#endif case XK_i: joy |= JOY_UP; break; @@ -311,7 +334,9 @@ void HandleKey(KeySym key, int key_status) case XK_KP_Down: #endif case XK_KP_2: +#ifndef MSDOS case XK_M: +#endif case XK_m: joy |= JOY_DOWN; break; @@ -339,35 +364,47 @@ void HandleKey(KeySym key, int key_status) case XK_KP_3: joy |= JOY_DOWN | JOY_RIGHT; break; +#ifndef MSDOS case XK_S: /* Feld entfernen */ +#endif case XK_s: joy |= JOY_BUTTON_1 | JOY_LEFT; break; +#ifndef MSDOS case XK_D: +#endif case XK_d: joy |= JOY_BUTTON_1 | JOY_RIGHT; break; +#ifndef MSDOS case XK_E: +#endif case XK_e: joy |= JOY_BUTTON_1 | JOY_UP; break; +#ifndef MSDOS case XK_X: +#endif case XK_x: joy |= JOY_BUTTON_1 | JOY_DOWN; break; case XK_Shift_L: /* Linker Feuerknopf */ +#ifndef MSDOS case XK_Control_L: case XK_Alt_L: case XK_Meta_L: +#endif joy |= JOY_BUTTON_1; break; case XK_Shift_R: /* Rechter Feuerknopf */ +#ifndef MSDOS case XK_Control_R: case XK_Alt_R: case XK_Meta_R: case XK_Mode_switch: case XK_Multi_key: case XK_B: /* (Bombe legen) */ +#endif case XK_b: joy |= JOY_BUTTON_2; break; @@ -500,7 +537,9 @@ void HandleKey(KeySym key, int key_status) printf("ScrollStepSize == %d (1/1)\n", ScrollStepSize); break; +#ifndef MSDOS case XK_Q: +#endif case XK_q: Dynamite = 1000; break; @@ -573,6 +612,29 @@ void HandleKey(KeySym key, int key_status) Delay(1000000); } + break; + + case XK_z: + { + static int test_picture_pos = 0; + + printf("test picture %d\n", test_picture_pos); + + XCopyArea(display,test_pix[test_picture_pos],window,gc, + 0,0, 100,100, + 0,0); + /* + XCopyArea(display,test_clipmask[test_picture_pos],window,gc, + 0,0, 100,100, + 100,0); + */ + XFlush(display); + XSync(display,FALSE); + Delay(1000000); + + test_picture_pos = (test_picture_pos + 1) % test_picture_count; + } + break; #endif diff --git a/src/events.h b/src/events.h index 700f8ae2..88c627d9 100644 --- a/src/events.h +++ b/src/events.h @@ -26,6 +26,8 @@ void HandleButtonEvent(XButtonEvent *); void HandleMotionEvent(XMotionEvent *); void HandleKeyEvent(XKeyEvent *); void HandleFocusEvent(XFocusChangeEvent *); +void HandleClientMessageEvent(XClientMessageEvent *event); + void HandleNoXEvent(void); void HandleButton(int, int, int); diff --git a/src/files.c b/src/files.c index bbd282a3..9a50079c 100644 --- a/src/files.c +++ b/src/files.c @@ -221,8 +221,13 @@ void LoadLevelTape(int level_nr) char cookie[MAX_FILENAME]; FILE *file; +#ifndef MSDOS sprintf(filename,"%s/%s/%d.tape", level_directory,leveldir[leveldir_nr].filename,level_nr); +#else + sprintf(filename,"%s/%s/%d.tap", + level_directory,leveldir[leveldir_nr].filename,level_nr); +#endif if ((file=fopen(filename,"r"))) { @@ -521,8 +526,13 @@ void SaveLevelTape(int level_nr) FILE *file; BOOL new_tape = TRUE; +#ifndef MSDOS sprintf(filename,"%s/%s/%d.tape", level_directory,leveldir[leveldir_nr].filename,level_nr); +#else + sprintf(filename,"%s/%s/%d.tap", + level_directory,leveldir[leveldir_nr].filename,level_nr); +#endif /* Testen, ob bereits eine Aufnahme existiert */ if ((file=fopen(filename,"r"))) @@ -694,6 +704,7 @@ void LoadJoystickData() if (joystick_status==JOYSTICK_OFF) return; +#ifndef MSDOS if (!(file=fopen(JOYDAT_FILE,"r"))) return; @@ -716,6 +727,9 @@ void LoadJoystickData() fclose(file); CheckJoystickData(); +#else + load_joystick_data(JOYDAT_FILE); +#endif } void SaveJoystickData() @@ -726,6 +740,7 @@ void SaveJoystickData() if (joystick_status==JOYSTICK_OFF) return; +#ifndef MSDOS CheckJoystickData(); if (!(file=fopen(JOYDAT_FILE,"w"))) @@ -746,4 +761,8 @@ void SaveJoystickData() fclose(file); chmod(JOYDAT_FILE, JOYDAT_PERMS); +#else + save_joystick_data(JOYDAT_FILE); +#endif + } diff --git a/src/game.c b/src/game.c index 424ca530..802c9f5b 100644 --- a/src/game.c +++ b/src/game.c @@ -57,12 +57,14 @@ void GetPlayerConfig() scroll_delay_on = SETUP_SCROLL_DELAY_ON(player.setup); soft_scrolling_on = SETUP_SOFT_SCROLL_ON(player.setup); +#ifndef MSDOS if (joystick_nr != old_joystick_nr) { if (joystick_device) close(joystick_device); InitJoystick(); } +#endif } void InitGame() @@ -3674,7 +3676,13 @@ void PlaySoundLevel(int x, int y, int sound_nr) return; volume = PSND_MAX_VOLUME; +#ifndef MSDOS stereo = (sx-SCR_FIELDX/2)*12; +#else + stereo = PSND_MIDDLE+(2*sx-(SCR_FIELDX-1))*5; + if(stereo > PSND_MAX_RIGHT) stereo = PSND_MAX_RIGHT; + if(stereo < PSND_MAX_LEFT) stereo = PSND_MAX_LEFT; +#endif if (!IN_SCR_FIELD(sx,sy)) { diff --git a/src/gfxload.c b/src/gfxload.c new file mode 100644 index 00000000..05e72a15 --- /dev/null +++ b/src/gfxload.c @@ -0,0 +1,1121 @@ +/*********************************************************** +* Rocks'n'Diamonds -- McDuffin Strikes Back! * +*----------------------------------------------------------* +* ©1995 Artsoft Development * +* Holger Schemel * +* 33659 Bielefeld-Senne * +* Telefon: (0521) 493245 * +* eMail: aeglos@valinor.owl.de * +* aeglos@uni-paderborn.de * +* q99492@pbhrzx.uni-paderborn.de * +*----------------------------------------------------------* +* gfxload.c * +***********************************************************/ + +#ifndef MSDOS +#include "gfxload.h" + + + + + + +extern Window window; +extern void Delay(long); + + + + + + +#ifdef DEBUG +/* +#define DEBUG_GIF +#define DEBUG_ILBM +*/ +#endif + +struct IFF_ILBM_FORM_big_endian +{ + char magic_FORM[4]; + unsigned char chunk_size[4]; + char magic_ILBM[4]; +}; + +struct IFF_ILBM_BMHD_big_endian +{ + char Width[2], Height[2]; + char LeftEdge[2], TopEdge[2]; + char Depth; + char Mask; + char Compression; + char pad1; + char transparentColor[2]; + char xAspect, yAspect; + char pageWidth[2], pageHeight[2]; +}; + +struct IFF_ILBM_BMHD +{ + unsigned int Width, Height; + int LeftEdge, TopEdge; + unsigned int Depth; + unsigned int Mask; + unsigned int Compression; + unsigned char pad1; + unsigned int transparentColor; + unsigned int xAspect, yAspect; + int pageWidth, pageHeight; +}; + +static int ConvertXImageDepth(Display *, XImage **); +static int Read_GIF_to_Pixmap_or_Bitmap(Display *, char *, Pixmap *, int); + +#define READ_GIF_TO_BITMAP 0 +#define READ_GIF_TO_PIXMAP 1 + +int Read_GIF_to_Bitmap(Display *display, char *filename, Pixmap *pixmap) +{ + return(Read_GIF_to_Pixmap_or_Bitmap(display, filename, + pixmap, READ_GIF_TO_BITMAP)); +} + +int Read_GIF_to_Pixmap(Display *display, char *filename, Pixmap *pixmap) +{ + return(Read_GIF_to_Pixmap_or_Bitmap(display, filename, + pixmap, READ_GIF_TO_PIXMAP)); +} + +int Read_GIF_to_Pixmap_or_Bitmap(Display *display, char *filename, + Pixmap *pixmap, int mode) +{ + XImage *image = NULL; + Pixmap new_pixmap = 0; + int return_code; + + *pixmap = 0; + return_code = Read_GIF_to_XImage(display, filename, &image); + if (return_code != GIF_Success) + return(return_code); + + if (image) + { + int screen = DefaultScreen(display); + Drawable root = RootWindow(display,screen); + int depth = DefaultDepth(display, screen); + int width = image->width; + int height = image->height; + + if (mode == READ_GIF_TO_BITMAP) + { + int i,x,y; + unsigned long black_pixel = BlackPixel(display,screen); + int bytes_per_line = (width+7) / 8; + int size = bytes_per_line * height; + char *data, *ptr; + + data = (char *)malloc(size); + if (!data) + return(GIF_NoMemory); + + ptr = data; + for(i=0;i filesize) + return(GIF_FileInvalid); + } + while(ch1); + + free(RawGIF); /* We're done with the raw data now... */ + +#ifdef DEBUG_GIF + fprintf(stderr, "done\n"); + fprintf(stderr, " Decompressing... "); +#endif + + /* Allocate the X Image */ + ImageData = (byte *) malloc(Width*Height); + if (!ImageData) + return(GIF_NoMemory); + + new_image = XCreateImage(display,visual,8,ZPixmap,0,ImageData, + Width,Height,8,Width); + if (!new_image) + return(GIF_NoMemory); + + BytesPerScanline = Width; + + + /* Decompress the file, continuing until you see the GIF EOF code. + * One obvious enhancement is to add checking for corrupt files here. + */ + + Code = ReadCode(); + while (Code != EOFCode) + { + /* Clear code sets everything back to its initial value, then reads the + * immediately subsequent code as uncompressed data. + */ + + if (Code == ClearCode) + { + CodeSize = InitCodeSize; + MaxCode = (1 << CodeSize); + ReadMask = MaxCode - 1; + FreeCode = FirstFree; + CurCode = OldCode = Code = ReadCode(); + FinChar = CurCode & BitMask; + AddToPixel(FinChar); + } + else + { + /* If not a clear code, then must be data: + * save same as CurCode and InCode + */ + + CurCode = InCode = Code; + + /* If greater or equal to FreeCode, not in the hash table yet; + * repeat the last character decoded + */ + + if (CurCode >= FreeCode) + { + CurCode = OldCode; + OutCode[OutCount++] = FinChar; + } + + /* Unless this code is raw data, pursue the chain pointed to by CurCode + * through the hash table to its end; each code in the chain puts its + * associated output code on the output queue. + */ + + while (CurCode > BitMask) + { + if (OutCount > 1024) + return(GIF_FileInvalid); + + OutCode[OutCount++] = Suffix[CurCode]; + CurCode = Prefix[CurCode]; + } + + /* The last code in the chain is treated as raw data. */ + + FinChar = CurCode & BitMask; + OutCode[OutCount++] = FinChar; + + /* Now we put the data out to the Output routine. + * It's been stacked LIFO, so deal with it that way... + */ + + for (i = OutCount - 1; i >= 0; i--) + AddToPixel(OutCode[i]); + OutCount = 0; + + /* Build the hash table on-the-fly. No table is stored in the file. */ + + Prefix[FreeCode] = OldCode; + Suffix[FreeCode] = FinChar; + OldCode = InCode; + + /* Point to the next slot in the table. If we exceed the current + * MaxCode value, increment the code size unless it's already 12. If it + * is, do nothing: the next code decompressed better be CLEAR + */ + + FreeCode++; + if (FreeCode >= MaxCode) + { + if (CodeSize < 12) + { + CodeSize++; + MaxCode *= 2; + ReadMask = (1 << CodeSize) - 1; + } + } + } + Code = ReadCode(); + } + + free(Raster); + +#ifdef DEBUG_GIF + fprintf(stderr, "done\n"); + fprintf(stderr," %d colors used\n",numused); +#endif + + if (file != stdin) + fclose(file); + + if (ColorDicking(display) != GIF_Success) + return(GIF_ColorFailed); + + *image = new_image; + return(GIF_Success); +} + + +/* Fetch the next code from the raster data stream. The codes can be + * any length from 3 to 12 bits, packed into 8-bit bytes, so we have to + * maintain our location in the Raster array as a BIT Offset. We compute + * the byte Offset into the raster array by dividing this by 8, pick up + * three bytes, compute the bit Offset into our 24-bit chunk, shift to + * bring the desired code to the bottom, then mask it off and return it. + */ + +static int ReadCode() +{ + int RawCode, ByteOffset; + + ByteOffset = BitOffset / 8; + RawCode = Raster[ByteOffset] + (0x100 * Raster[ByteOffset + 1]); + if (CodeSize >= 8) + RawCode += (0x10000 * Raster[ByteOffset + 2]); + RawCode >>= (BitOffset % 8); + BitOffset += CodeSize; + return(RawCode & ReadMask); +} + + +static void AddToPixel(byte Index) +{ + if (YC= Height) + { + Pass++; + YC = 4; + } + break; + + case 1: + YC += 8; + if (YC >= Height) + { + Pass++; + YC = 2; + } + break; + + case 2: + YC += 4; + if (YC >= Height) + { + Pass++; + YC = 1; + } + break; + + case 3: + YC += 2; + break; + + default: + break; + } + } + } +} + + +static int ColorDicking(Display *display) +{ + /* we've got the picture loaded, we know what colors are needed. get 'em */ + + register int i,j; + static byte lmasks[8] = {0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80}; + byte lmask, *ptr; + int screen = DefaultScreen(display); + Colormap cmap = DefaultColormap(display,screen); + int dispcells = DisplayCells(display,screen); + + int strip = 0; + int nostrip = 0; + + if (!HasColormap) + return(GIF_Success); + /* no need to allocate any colors if no colormap in GIF file */ + + /* Allocate the X colors for this picture */ + + if (nostrip) + { + /* nostrip was set. try REAL hard to do it */ + for (i=j=0; i>8)) + + abs(g - (ctab[j].green>>8)) + + abs(b - (ctab[j].blue>>8)); + if (d=0; i--) + if (used[i]) + XFreeColors(display,cmap,cols+i,1,0L); + } + else + break; + } + +#ifdef DEBUG_GIF + if (j && strip<8) + fprintf(stderr,"%s: stripped %d bits\n",progname,strip); +#endif + + if (strip==8) + { + fprintf(stderr,"UTTERLY failed to allocate the desired colors.\n"); + for (i=0; idepth == %d\n", + (*image)->depth); + printf("DefaultDepth(display, screen) == %d\n", + DefaultDepth(display, screen)); + + + + + if ((*image)->depth != depth) + { + XImage *old_image, *new_image; + + Visual *visual = DefaultVisual(display,screen); + + int width = (*image)->width; + int height = (*image)->height; + register int dwx, dwy; + byte *data; + + + + + + printf("ConvertXImageDepth: ---------> CONVERTING...\n"); + + + + + + + data = (byte *)malloc(width * height * depth); + old_image = *image; + +#if 1 + new_image = XCreateImage(display,visual,depth, + ZPixmap,0,data,width,height,8,0); +#else + new_image = XGetImage(display,RootWindow(display,screen), + 0,0,width,height,0xffffffff,ZPixmap); +#endif + + if (!new_image) + return(GIF_NoMemory); + + if (old_image->depth == 8 && new_image->depth == 4) + { + /* speedup for the most common format change */ + + register byte *sptr = (byte *)old_image->data; + register byte *dptr = (byte *)new_image->data; + + for (dwy=1; dwy<=height; dwy++) + { + for (dwx=1; dwx 4 bit */ + { + unsigned long pixel_value; + + for (dwx=0; dwx 0xff) + printf("pixel = %lx", pixel_value); + + XPutPixel(new_image, dwx, dwy, pixel_value); + } + } + } + + free(old_image->data); + old_image->data = NULL; + XDestroyImage(old_image); + + *image = new_image; + } + + return(GIF_Success); +} + + +static unsigned long be2long(unsigned char *be) /* big-endian -> long int */ +{ + return((be[0]<<24) | (be[1]<<16) | (be[2]<<8) | be[3]); +} + +static unsigned short be2short(unsigned char *be) /* big-endian -> short int */ +{ + return((be[0]<<8) | be[1]); +} + +static struct IFF_ILBM_BMHD *ConvertBMHD(unsigned char *header_data) +{ + struct IFF_ILBM_BMHD_big_endian *bmhd_be; + struct IFF_ILBM_BMHD *bmhd; + + bmhd_be = (struct IFF_ILBM_BMHD_big_endian *)header_data; + bmhd = (struct IFF_ILBM_BMHD *)malloc(sizeof(struct IFF_ILBM_BMHD)); + if (!bmhd) + return(NULL); + + bmhd->Width = be2short(bmhd_be->Width); + bmhd->Height = be2short(bmhd_be->Height); + bmhd->LeftEdge = be2short(bmhd_be->LeftEdge); + bmhd->TopEdge = be2short(bmhd_be->TopEdge); + bmhd->Depth = (int)bmhd_be->Depth; + bmhd->Mask = (int)bmhd_be->Mask; + bmhd->Compression = (int)bmhd_be->Compression; + bmhd->pad1 = bmhd_be->pad1; + bmhd->transparentColor = be2short(bmhd_be->transparentColor); + bmhd->xAspect = (int)bmhd_be->xAspect; + bmhd->yAspect = (int)bmhd_be->yAspect; + bmhd->pageWidth = be2short(bmhd_be->pageWidth); + bmhd->pageHeight = be2short(bmhd_be->pageHeight); + + return(bmhd); +} + +static unsigned char MSBitFirst2LSBitFirst(unsigned char msb_byte) +{ + unsigned char lsb_byte = 0; + int i; + + for(i=7;i>=0;i--) + { + lsb_byte |= (msb_byte & 1) << i; + msb_byte >>= 1; + } + + return(lsb_byte); +} + +int Read_ILBM_to_Bitmap(Display *display, char *filename, Pixmap *pixmap) +{ + Pixmap new_pixmap = 0; + int screen = DefaultScreen(display); + Drawable root = RootWindow(display,screen); + struct IFF_ILBM_FORM_big_endian *form_header; + struct IFF_ILBM_BMHD *bitmap_header; + unsigned long file_len, body_len; + unsigned char *file_data, *bitmap_data; + unsigned char *file_ptr, *bitmap_ptr, *body_ptr; + unsigned char byte_count, byte_value; + int i,x,y,z; + int width, height, depth; + int bytes_per_line, bitmap_size; + FILE *file; + + if (!(file = fopen(filename,"r"))) + return(ILBM_OpenFailed); + + if (fseek(file,0,SEEK_END) < 0) + { + fclose(file); + return(ILBM_ReadFailed); + } + + file_len = ftell(file); + rewind(file); + + if (!(file_data = (unsigned char *)malloc(file_len))) + { + fclose(file); + return(ILBM_NoMemory); + } + + if (fread(file_data,1,file_len,file) != file_len) + { + free(file_data); + fclose(file); + return(ILBM_ReadFailed); + } + + fclose(file); + + form_header = (struct IFF_ILBM_FORM_big_endian *)file_data; + + if (strncmp(form_header->magic_FORM,"FORM",4) || + file_len != be2long(form_header->chunk_size)+8 || + strncmp(form_header->magic_ILBM,"ILBM",4)) + { +#ifdef DEBUG_ILBM + printf("%s: IFF chunk 'FORM' and/or 'ILBM' not found.\n",filename); +#endif + free(file_data); + return(ILBM_FileInvalid); + } + + bitmap_header = NULL; + body_ptr = NULL; + file_ptr = file_data + 12; + + while(file_ptr < (unsigned char *)(file_data + file_len)) + { + if (!strncmp(file_ptr,"BMHD",4)) + { +#ifdef DEBUG_ILBM + printf("%s: IFF chunk 'BMHD' found.\n",filename); +#endif + bitmap_header = ConvertBMHD(file_ptr + 8); + file_ptr += be2long(file_ptr + 4) + 8; + continue; + } + else if (!strncmp(file_ptr,"BODY",4)) + { +#ifdef DEBUG_ILBM + printf("%s: IFF chunk 'BODY' found.\n",filename); +#endif + body_ptr = file_ptr + 8; + body_len = be2long(file_ptr + 4); + file_ptr += be2long(file_ptr + 4) + 8; + continue; + } + else + { +#ifdef DEBUG_ILBM + printf("%s: IFF chunk '%c%c%c%c' found (but not used).\n",filename, + file_ptr[0],file_ptr[1],file_ptr[2],file_ptr[3]); +#endif + /* other chunk not recognized here */ + file_ptr += be2long(file_ptr + 4) + 8; + continue; + } + } + + if (!bitmap_header || !body_ptr) + { +#ifdef DEBUG_ILBM + printf("%s: IFF chunk 'BMHD' and/or 'BODY' not found.\n",filename); +#endif + free(file_data); + return(ILBM_FileInvalid); + } + + width = bitmap_header->Width; + height = bitmap_header->Height; + depth = bitmap_header->Depth; + +#ifdef DEBUG_ILBM + if (depth > 1) + printf("%s: %d bitplanes found; using only the first plane.\n", + filename,depth); +#endif + + bytes_per_line = ((width + 15) / 16) * 2; + bitmap_size = bytes_per_line * height; + + bitmap_data = (char *)malloc(bitmap_size); + if (!bitmap_data) + { + free(file_data); + free(bitmap_header); + return(ILBM_NoMemory); + } + + bitmap_ptr = bitmap_data; + for(i=0;iCompression) + { + while(x++ < bytes_per_line) + *bitmap_ptr++ |= MSBitFirst2LSBitFirst(*body_ptr++); + } + else + { + while(x < bytes_per_line) + { + byte_count = *body_ptr++; + + if (byte_count <= 128) + { + for(i=0;i +#include +#include +#include +#include + +#define GIF_Success 0 +#define GIF_OpenFailed -1 +#define GIF_ReadFailed -2 +#define GIF_FileInvalid -3 +#define GIF_NoMemory -4 +#define GIF_ColorFailed -5 + +#define ILBM_Success 0 +#define ILBM_OpenFailed -1 +#define ILBM_ReadFailed -2 +#define ILBM_FileInvalid -3 +#define ILBM_NoMemory -4 +#define ILBM_ColorFailed -5 + +int Read_ILBM_to_Bitmap(Display *, char *, Pixmap *); +int Read_GIF_to_Bitmap(Display *, char *, Pixmap *); +int Read_GIF_to_Pixmap(Display *, char *, Pixmap *); +int Read_GIF_to_XImage(Display *, char *, XImage **); + +#endif +#endif diff --git a/src/gfxloader.c b/src/gfxloader.c deleted file mode 100644 index 9a28f435..00000000 --- a/src/gfxloader.c +++ /dev/null @@ -1,1155 +0,0 @@ -/*********************************************************** -* Rocks'n'Diamonds -- McDuffin Strikes Back! * -*----------------------------------------------------------* -* ©1995 Artsoft Development * -* Holger Schemel * -* 33659 Bielefeld-Senne * -* Telefon: (0521) 493245 * -* eMail: aeglos@valinor.owl.de * -* aeglos@uni-paderborn.de * -* q99492@pbhrzx.uni-paderborn.de * -*----------------------------------------------------------* -* gfxloader.c * -***********************************************************/ - -#include "gfxloader.h" - - - - - - -extern Window window; -extern void Delay(long); - - - - - - -#ifdef DEBUG -/* -#define DEBUG_GIF -#define DEBUG_ILBM -*/ -#endif - -struct IFF_ILBM_FORM_big_endian -{ - char magic_FORM[4]; - unsigned char chunk_size[4]; - char magic_ILBM[4]; -}; - -struct IFF_ILBM_BMHD_big_endian -{ - char Width[2], Height[2]; - char LeftEdge[2], TopEdge[2]; - char Depth; - char Mask; - char Compression; - char pad1; - char transparentColor[2]; - char xAspect, yAspect; - char pageWidth[2], pageHeight[2]; -}; - -struct IFF_ILBM_BMHD -{ - unsigned int Width, Height; - int LeftEdge, TopEdge; - unsigned int Depth; - unsigned int Mask; - unsigned int Compression; - unsigned char pad1; - unsigned int transparentColor; - unsigned int xAspect, yAspect; - int pageWidth, pageHeight; -}; - -static int ConvertXImageDepth(Display *, XImage **); -static int Read_GIF_to_Pixmap_or_Bitmap(Display *, char *, Pixmap *, int); - -#define READ_GIF_TO_BITMAP 0 -#define READ_GIF_TO_PIXMAP 1 - - -int Read_GIF_to_Bitmap(Display *display, char *filename, Pixmap *pixmap) -{ - printf("Read_GIF_to_Bitmap\n"); - - - - - return(Read_GIF_to_Pixmap_or_Bitmap(display, filename, - pixmap, READ_GIF_TO_BITMAP)); -} - -int Read_GIF_to_Pixmap(Display *display, char *filename, Pixmap *pixmap) -{ - printf("Read_GIF_to_Pixmap\n"); - - - - - return(Read_GIF_to_Pixmap_or_Bitmap(display, filename, - pixmap, READ_GIF_TO_PIXMAP)); -} - -int Read_GIF_to_Pixmap_or_Bitmap(Display *display, char *filename, - Pixmap *pixmap, int mode) -{ - XImage *image = NULL; - Pixmap new_pixmap = 0; - int return_code; - - *pixmap = 0; - return_code = Read_GIF_to_XImage(display, filename, &image); - if (return_code != GIF_Success) - return(return_code); - - if (image) - { - int screen = DefaultScreen(display); - Drawable root = RootWindow(display,screen); - int depth = DefaultDepth(display, screen); - int width = image->width; - int height = image->height; - - if (mode == READ_GIF_TO_BITMAP) - { - int i,x,y; - unsigned long black_pixel = BlackPixel(display,screen); - int bytes_per_line = (width+7) / 8; - int size = bytes_per_line * height; - char *data, *ptr; - - data = (char *)malloc(size); - if (!data) - return(GIF_NoMemory); - - ptr = data; - for(i=0;i filesize) - return(GIF_FileInvalid); - } - while(ch1); - - free(RawGIF); /* We're done with the raw data now... */ - -#ifdef DEBUG_GIF - fprintf(stderr, "done\n"); - fprintf(stderr, " Decompressing... "); -#endif - - /* Allocate the X Image */ - ImageData = (byte *) malloc(Width*Height); - if (!ImageData) - return(GIF_NoMemory); - - new_image = XCreateImage(display,visual,8,ZPixmap,0,ImageData, - Width,Height,8,Width); - if (!new_image) - return(GIF_NoMemory); - - BytesPerScanline = Width; - - - /* Decompress the file, continuing until you see the GIF EOF code. - * One obvious enhancement is to add checking for corrupt files here. - */ - - Code = ReadCode(); - while (Code != EOFCode) - { - /* Clear code sets everything back to its initial value, then reads the - * immediately subsequent code as uncompressed data. - */ - - if (Code == ClearCode) - { - CodeSize = InitCodeSize; - MaxCode = (1 << CodeSize); - ReadMask = MaxCode - 1; - FreeCode = FirstFree; - CurCode = OldCode = Code = ReadCode(); - FinChar = CurCode & BitMask; - AddToPixel(FinChar); - } - else - { - /* If not a clear code, then must be data: - * save same as CurCode and InCode - */ - - CurCode = InCode = Code; - - /* If greater or equal to FreeCode, not in the hash table yet; - * repeat the last character decoded - */ - - if (CurCode >= FreeCode) - { - CurCode = OldCode; - OutCode[OutCount++] = FinChar; - } - - /* Unless this code is raw data, pursue the chain pointed to by CurCode - * through the hash table to its end; each code in the chain puts its - * associated output code on the output queue. - */ - - while (CurCode > BitMask) - { - if (OutCount > 1024) - return(GIF_FileInvalid); - - OutCode[OutCount++] = Suffix[CurCode]; - CurCode = Prefix[CurCode]; - } - - /* The last code in the chain is treated as raw data. */ - - FinChar = CurCode & BitMask; - OutCode[OutCount++] = FinChar; - - /* Now we put the data out to the Output routine. - * It's been stacked LIFO, so deal with it that way... - */ - - for (i = OutCount - 1; i >= 0; i--) - AddToPixel(OutCode[i]); - OutCount = 0; - - /* Build the hash table on-the-fly. No table is stored in the file. */ - - Prefix[FreeCode] = OldCode; - Suffix[FreeCode] = FinChar; - OldCode = InCode; - - /* Point to the next slot in the table. If we exceed the current - * MaxCode value, increment the code size unless it's already 12. If it - * is, do nothing: the next code decompressed better be CLEAR - */ - - FreeCode++; - if (FreeCode >= MaxCode) - { - if (CodeSize < 12) - { - CodeSize++; - MaxCode *= 2; - ReadMask = (1 << CodeSize) - 1; - } - } - } - Code = ReadCode(); - } - - free(Raster); - -#ifdef DEBUG_GIF - fprintf(stderr, "done\n"); - fprintf(stderr," %d colors used\n",numused); -#endif - - if (file != stdin) - fclose(file); - - if (ColorDicking(display) != GIF_Success) - return(GIF_ColorFailed); - - *image = new_image; - return(GIF_Success); -} - - -/* Fetch the next code from the raster data stream. The codes can be - * any length from 3 to 12 bits, packed into 8-bit bytes, so we have to - * maintain our location in the Raster array as a BIT Offset. We compute - * the byte Offset into the raster array by dividing this by 8, pick up - * three bytes, compute the bit Offset into our 24-bit chunk, shift to - * bring the desired code to the bottom, then mask it off and return it. - */ - -static int ReadCode() -{ - int RawCode, ByteOffset; - - ByteOffset = BitOffset / 8; - RawCode = Raster[ByteOffset] + (0x100 * Raster[ByteOffset + 1]); - if (CodeSize >= 8) - RawCode += (0x10000 * Raster[ByteOffset + 2]); - RawCode >>= (BitOffset % 8); - BitOffset += CodeSize; - return(RawCode & ReadMask); -} - - -static void AddToPixel(byte Index) -{ - if (YC= Height) - { - Pass++; - YC = 4; - } - break; - - case 1: - YC += 8; - if (YC >= Height) - { - Pass++; - YC = 2; - } - break; - - case 2: - YC += 4; - if (YC >= Height) - { - Pass++; - YC = 1; - } - break; - - case 3: - YC += 2; - break; - - default: - break; - } - } - } -} - - -static int ColorDicking(Display *display) -{ - /* we've got the picture loaded, we know what colors are needed. get 'em */ - - register int i,j; - static byte lmasks[8] = {0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80}; - byte lmask, *ptr; - int screen = DefaultScreen(display); - Colormap cmap = DefaultColormap(display,screen); - int dispcells = DisplayCells(display,screen); - - int strip = 0; - int nostrip = 0; - - if (!HasColormap) - return(GIF_Success); - /* no need to allocate any colors if no colormap in GIF file */ - - /* Allocate the X colors for this picture */ - - if (nostrip) - { - /* nostrip was set. try REAL hard to do it */ - for (i=j=0; i>8)) + - abs(g - (ctab[j].green>>8)) + - abs(b - (ctab[j].blue>>8)); - if (d=0; i--) - if (used[i]) - XFreeColors(display,cmap,cols+i,1,0L); - } - else - break; - } - -#ifdef DEBUG_GIF - if (j && strip<8) - fprintf(stderr,"%s: stripped %d bits\n",progname,strip); -#endif - - if (strip==8) - { - fprintf(stderr,"UTTERLY failed to allocate the desired colors.\n"); - for (i=0; idepth == %d\n", - (*image)->depth); - printf("DefaultDepth(display, screen) == %d\n", - DefaultDepth(display, screen)); - - - - - if ((*image)->depth != depth) - { - XImage *old_image, *new_image; - /* - Visual *visual = DefaultVisual(display,screen); - */ - int width = (*image)->width; - int height = (*image)->height; - register int dwx, dwy; - byte *data; - - - - - - printf("ConvertXImageDepth: ---------> CONVERTING...\n"); - - - - - - - data = (byte *)malloc(width * height * depth); - old_image = *image; - - /* - new_image = XCreateImage(display,visual,depth, - ZPixmap,0,data,width,height,8,0); - */ - - new_image = XGetImage(display,RootWindow(display,screen), - 0,0,width,height,0xffffffff,ZPixmap); - - - if (!new_image) - return(GIF_NoMemory); - - if (old_image->depth == 8 && new_image->depth == 4) - { - /* speedup for the most common format change */ - - register byte *sptr = (byte *)old_image->data; - register byte *dptr = (byte *)new_image->data; - - for (dwy=1; dwy<=height; dwy++) - { - for (dwx=1; dwx 4 bit */ - { - unsigned long pixel_value; - - for (dwx=0; dwx 0xff) - printf("pixel = %lx", pixel_value); - - XPutPixel(new_image, dwx, dwy, pixel_value); - } - } - } - - free(old_image->data); - old_image->data = NULL; - XDestroyImage(old_image); - - *image = new_image; - } - - return(GIF_Success); -} - - -static unsigned long be2long(unsigned char *be) /* big-endian -> long int */ -{ - return((be[0]<<24) | (be[1]<<16) | (be[2]<<8) | be[3]); -} - -static unsigned short be2short(unsigned char *be) /* big-endian -> short int */ -{ - return((be[0]<<8) | be[1]); -} - -static struct IFF_ILBM_BMHD *ConvertBMHD(unsigned char *header_data) -{ - struct IFF_ILBM_BMHD_big_endian *bmhd_be; - struct IFF_ILBM_BMHD *bmhd; - - bmhd_be = (struct IFF_ILBM_BMHD_big_endian *)header_data; - bmhd = (struct IFF_ILBM_BMHD *)malloc(sizeof(struct IFF_ILBM_BMHD)); - if (!bmhd) - return(NULL); - - bmhd->Width = be2short(bmhd_be->Width); - bmhd->Height = be2short(bmhd_be->Height); - bmhd->LeftEdge = be2short(bmhd_be->LeftEdge); - bmhd->TopEdge = be2short(bmhd_be->TopEdge); - bmhd->Depth = (int)bmhd_be->Depth; - bmhd->Mask = (int)bmhd_be->Mask; - bmhd->Compression = (int)bmhd_be->Compression; - bmhd->pad1 = bmhd_be->pad1; - bmhd->transparentColor = be2short(bmhd_be->transparentColor); - bmhd->xAspect = (int)bmhd_be->xAspect; - bmhd->yAspect = (int)bmhd_be->yAspect; - bmhd->pageWidth = be2short(bmhd_be->pageWidth); - bmhd->pageHeight = be2short(bmhd_be->pageHeight); - - return(bmhd); -} - -static unsigned char MSBitFirst2LSBitFirst(unsigned char msb_byte) -{ - unsigned char lsb_byte = 0; - int i; - - for(i=7;i>=0;i--) - { - lsb_byte |= (msb_byte & 1) << i; - msb_byte >>= 1; - } - - return(lsb_byte); -} - -int Read_ILBM_to_Bitmap(Display *display, char *filename, Pixmap *pixmap) -{ - Pixmap new_pixmap = 0; - int screen = DefaultScreen(display); - Drawable root = RootWindow(display,screen); - struct IFF_ILBM_FORM_big_endian *form_header; - struct IFF_ILBM_BMHD *bitmap_header; - unsigned long file_len, body_len; - unsigned char *file_data, *bitmap_data; - unsigned char *file_ptr, *bitmap_ptr, *body_ptr; - unsigned char byte_count, byte_value; - int i,x,y,z; - int width, height, depth; - int bytes_per_line, bitmap_size; - FILE *file; - - - - - - printf("Read_ILBM_to_Bitmap\n"); - - - - - if (!(file = fopen(filename,"r"))) - return(ILBM_OpenFailed); - - if (fseek(file,0,SEEK_END) < 0) - { - fclose(file); - return(ILBM_ReadFailed); - } - - file_len = ftell(file); - rewind(file); - - if (!(file_data = (unsigned char *)malloc(file_len))) - { - fclose(file); - return(ILBM_NoMemory); - } - - if (fread(file_data,1,file_len,file) != file_len) - { - free(file_data); - fclose(file); - return(ILBM_ReadFailed); - } - - fclose(file); - - form_header = (struct IFF_ILBM_FORM_big_endian *)file_data; - - if (strncmp(form_header->magic_FORM,"FORM",4) || - file_len != be2long(form_header->chunk_size)+8 || - strncmp(form_header->magic_ILBM,"ILBM",4)) - { -#ifdef DEBUG_ILBM - printf("%s: IFF chunk 'FORM' and/or 'ILBM' not found.\n",filename); -#endif - free(file_data); - return(ILBM_FileInvalid); - } - - bitmap_header = NULL; - body_ptr = NULL; - file_ptr = file_data + 12; - - while(file_ptr < (unsigned char *)(file_data + file_len)) - { - if (!strncmp(file_ptr,"BMHD",4)) - { -#ifdef DEBUG_ILBM - printf("%s: IFF chunk 'BMHD' found.\n",filename); -#endif - bitmap_header = ConvertBMHD(file_ptr + 8); - file_ptr += be2long(file_ptr + 4) + 8; - continue; - } - else if (!strncmp(file_ptr,"BODY",4)) - { -#ifdef DEBUG_ILBM - printf("%s: IFF chunk 'BODY' found.\n",filename); -#endif - body_ptr = file_ptr + 8; - body_len = be2long(file_ptr + 4); - file_ptr += be2long(file_ptr + 4) + 8; - continue; - } - else - { -#ifdef DEBUG_ILBM - printf("%s: IFF chunk '%c%c%c%c' found (but not used).\n",filename, - file_ptr[0],file_ptr[1],file_ptr[2],file_ptr[3]); -#endif - /* other chunk not recognized here */ - file_ptr += be2long(file_ptr + 4) + 8; - continue; - } - } - - if (!bitmap_header || !body_ptr) - { -#ifdef DEBUG_ILBM - printf("%s: IFF chunk 'BMHD' and/or 'BODY' not found.\n",filename); -#endif - free(file_data); - return(ILBM_FileInvalid); - } - - width = bitmap_header->Width; - height = bitmap_header->Height; - depth = bitmap_header->Depth; - -#ifdef DEBUG_ILBM - if (depth > 1) - printf("%s: %d bitplanes found; using only the first plane.\n", - filename,depth); -#endif - - bytes_per_line = ((width + 15) / 16) * 2; - bitmap_size = bytes_per_line * height; - - bitmap_data = (char *)malloc(bitmap_size); - if (!bitmap_data) - { - free(file_data); - free(bitmap_header); - return(ILBM_NoMemory); - } - - bitmap_ptr = bitmap_data; - for(i=0;iCompression) - { - while(x++ < bytes_per_line) - *bitmap_ptr++ |= MSBitFirst2LSBitFirst(*body_ptr++); - } - else - { - while(x < bytes_per_line) - { - byte_count = *body_ptr++; - - if (byte_count <= 128) - { - for(i=0;i -#include -#include -#include -#include - -#define GIF_Success 0 -#define GIF_OpenFailed -1 -#define GIF_ReadFailed -2 -#define GIF_FileInvalid -3 -#define GIF_NoMemory -4 -#define GIF_ColorFailed -5 - -#define ILBM_Success 0 -#define ILBM_OpenFailed -1 -#define ILBM_ReadFailed -2 -#define ILBM_FileInvalid -3 -#define ILBM_NoMemory -4 -#define ILBM_ColorFailed -5 - -int Read_ILBM_to_Bitmap(Display *, char *, Pixmap *); -int Read_GIF_to_Bitmap(Display *, char *, Pixmap *); -int Read_GIF_to_Pixmap(Display *, char *, Pixmap *); -int Read_GIF_to_XImage(Display *, char *, XImage **); - -#endif diff --git a/src/gif.c b/src/gif.c new file mode 100644 index 00000000..2462e139 --- /dev/null +++ b/src/gif.c @@ -0,0 +1,632 @@ + +/* gif.c: + * + * adapted from code by kirk johnson (tuna@athena.mit.edu). most of this + * code is unchanged. -- jim frost 12.31.89 + * + * gifin.c + * kirk johnson + * november 1989 + * + * routines for reading GIF files + * + * Copyright 1989 Kirk L. Johnson (see the included file + * "kljcpyrght.h" for complete copyright information) + */ + +#define GIF_C + +#include "xli.h" +#include "gif.h" + +#define PUSH_PIXEL(p) \ +{ \ + if (pstk_idx == PSTK_SIZE) \ + return GIFIN_ERR_PSO; \ + else \ + pstk[pstk_idx++] = (p); \ +} + +/* + * push a string (denoted by a code) onto the pixel stack + * (returns the code of the first pixel in the string in ps_rslt) + */ + +int ps_rslt; /* return result */ + +#define GIFIN_PUSH_STRING(code) \ +{ \ + int ps_code; \ + ps_code = code; \ + \ + while (((unsigned int)ps_code) < STAB_SIZE && prefix[ps_code] != NULL_CODE) \ + { \ + PUSH_PIXEL(extnsn[ps_code]); \ + ps_code = prefix[ps_code]; \ + } \ + \ + if (((unsigned int)ps_code) >= STAB_SIZE) \ + return GIFIN_ERR_TAO; \ + PUSH_PIXEL(extnsn[ps_code]); \ + ps_rslt = extnsn[ps_code]; \ + if (((unsigned int)ps_rslt) >= STAB_SIZE) \ + return GIFIN_ERR_TAO; \ +} + +/* + * Look up the ascii message coresponding to + * the error number. + */ +static char *get_err_string(int errno) +{ + int i; + for (i=0;gif_err_strings[i].err_no != 0;i++) + { + if (gif_err_strings[i].err_no == errno) + return gif_err_strings[i].name; + } + return ""; +} + + +static int interlace_start[4] = /* start line for interlacing */ +{ + 0, 4, 2, 1 +}; + +static int interlace_rate[4] = /* rate at which we accelerate vertically */ +{ + 8, 8, 4, 2 +}; + +static BYTE file_open = 0; /* status flags */ +static BYTE image_open = 0; + +static FILE *ins; /* input stream */ + +static int root_size; /* root code size */ +static int clr_code; /* clear code */ +static int eoi_code; /* end of information code */ +static int code_size; /* current code size */ +static int code_mask; /* current code mask */ +static int prev_code; /* previous code */ + +static long work_data; /* working bit buffer */ +static int work_bits; /* working bit count */ + +static BYTE buf[256]; /* byte buffer */ +static int buf_cnt; /* byte count */ +static int buf_idx; /* buffer index */ + +static int table_size; /* string table size */ +static int prefix[STAB_SIZE]; /* string table : prefixes */ +static int extnsn[STAB_SIZE]; /* string table : extensions */ + +static BYTE pstk[PSTK_SIZE]; /* pixel stack */ +static int pstk_idx; /* pixel stack pointer */ + + +static int gifin_rast_width; /* raster width */ +static int gifin_rast_height; /* raster height */ +static BYTE gifin_g_cmap_flag; /* global colormap flag */ +static int gifin_g_pixel_bits; /* bits per pixel, global colormap */ +static int gifin_g_ncolors; /* number of colors, global colormap */ +static BYTE gifin_g_cmap[3][256]; /* global colormap */ +static BYTE gifin_g_cmap_sorted; /* global colormap sorted (GIF89a only) */ +static int gifin_bg_color; /* background color index */ +static int gifin_color_bits; /* bits of color resolution */ +static double gifin_aspect; /* pixel aspect ratio (width/height) */ +static int gifin_version; /* gif file version */ + +static int gifin_img_left; /* image position on raster */ +static int gifin_img_top; /* image position on raster */ +static int gifin_img_width; /* image width */ +static int gifin_img_height; /* image height */ +static BYTE gifin_l_cmap_flag; /* local colormap flag */ +static int gifin_l_pixel_bits; /* bits per pixel, local colormap */ +static int gifin_l_ncolors; /* number of colors, local colormap */ +static BYTE gifin_l_cmap[3][256]; /* local colormap */ +static BYTE gifin_interlace_flag; /* interlace image format flag */ + +/* + * open a GIF file, using s as the input stream + */ + +static int gifin_open_file(FILE *s) +{ + int errno; + /* make sure there isn't already a file open */ + if (file_open) + return GIFIN_ERR_FAO; + + /* remember that we've got this file open */ + file_open = 1; + ins = s; + + /* check GIF signature */ + if (fread(buf, 1, GIF_SIG_LEN, ins) != GIF_SIG_LEN) + return GIFIN_ERR_EOF; + + buf[GIF_SIG_LEN] = '\0'; + if (strcmp((char *) buf, GIF_SIG) == 0) + gifin_version = GIF87a; + else if(strcmp((char *) buf, GIF_SIG_89) == 0) + gifin_version = GIF89a; + else + return GIFIN_ERR_BAD_SIG; + + /* read screen descriptor */ + if (fread(buf, 1, GIF_SD_SIZE, ins) != GIF_SD_SIZE) + return GIFIN_ERR_EOF; + + /* decode screen descriptor */ + gifin_rast_width = (buf[1] << 8) + buf[0]; + gifin_rast_height = (buf[3] << 8) + buf[2]; + gifin_g_cmap_flag = (buf[4] & 0x80) ? 1 : 0; + gifin_color_bits = (((int)(buf[4] & 0x70)) >> 4) + 1; + gifin_g_pixel_bits = (buf[4] & 0x07) + 1; + gifin_bg_color = buf[5]; + gifin_aspect = 1.0; + + if (gifin_version == GIF87a) + { + if (buf[4] & 0x08 || buf[6] != 0) + return GIFIN_ERR_BAD_SD; + } + else + { + gifin_g_cmap_sorted = ((buf[4] & 0x08) != 0); + if (buf[6] != 0) + gifin_aspect = ((double)buf[6] + 15.0) / 64.0; + } + + /* load global colormap */ + if (gifin_g_cmap_flag) + { + gifin_g_ncolors = (1 << gifin_g_pixel_bits); + + if ((errno = gifin_load_cmap(gifin_g_cmap, gifin_g_ncolors)) != GIFIN_SUCCESS) + return errno; + } + else + { + gifin_g_ncolors = 0; + } + + /* done! */ + return GIFIN_SUCCESS; +} + + +/* + * open next GIF image in the input stream; returns GIFIN_SUCCESS if + * successful. if there are no more images, returns GIFIN_DONE. (might + * also return various GIFIN_ERR codes.) + */ + +static int gifin_open_image() +{ + int i; + int separator; + int errno; + + /* make sure there's a file open */ + if (!file_open) + return GIFIN_ERR_NFO; + + /* make sure there isn't already an image open */ + if (image_open) + return GIFIN_ERR_IAO; + + /* remember that we've got this image open */ + image_open = 1; + + /* skip over any extension blocks */ + do + { + separator = fgetc(ins); + if (separator == GIF_EXTENSION) + { + if ((errno = gifin_skip_extension()) != GIFIN_SUCCESS) + return errno; + } + } + while (separator == GIF_EXTENSION); + + /* check for end of file marker */ + if (separator == GIF_TERMINATOR) + return GIFIN_DONE; + + /* make sure we've got an image separator */ + if (separator != GIF_SEPARATOR) + return GIFIN_ERR_BAD_SEP; + + /* read image descriptor */ + if (fread(buf, 1, GIF_ID_SIZE, ins) != GIF_ID_SIZE) + return GIFIN_ERR_EOF; + + /* decode image descriptor */ + gifin_img_left = (buf[1] << 8) + buf[0]; + gifin_img_top = (buf[3] << 8) + buf[2]; + gifin_img_width = (buf[5] << 8) + buf[4]; + gifin_img_height = (buf[7] << 8) + buf[6]; + gifin_l_cmap_flag = (buf[8] & 0x80) ? 1 : 0; + gifin_interlace_flag = (buf[8] & 0x40) ? 1 : 0; + gifin_l_pixel_bits = (buf[8] & 0x07) + 1; + + /* load local colormap */ + if (gifin_l_cmap_flag) + { + gifin_l_ncolors = (1 << gifin_l_pixel_bits); + + if ((errno = gifin_load_cmap(gifin_l_cmap, gifin_l_ncolors)) != GIFIN_SUCCESS) + return errno; + } + else + { + gifin_l_ncolors = 0; + } + + /* initialize raster data stream decoder */ + root_size = fgetc(ins); + clr_code = 1 << root_size; + eoi_code = clr_code + 1; + code_size = root_size + 1; + code_mask = (1 << code_size) - 1; + work_bits = 0; + work_data = 0; + buf_cnt = 0; + buf_idx = 0; + + /* initialize string table */ + for (i=0; i>= code_size; + work_bits -= code_size; + + /* interpret the code */ + if (code == clr_code) + { + /* reset decoder stream */ + code_size = root_size + 1; + code_mask = (1 << code_size) - 1; + prev_code = NULL_CODE; + table_size = eoi_code + 1; + } + else if (code == eoi_code) + { + /* Ooops! no more pixels */ + return GIFIN_ERR_EOF; + } + else if (prev_code == NULL_CODE) + { + GIFIN_PUSH_STRING(code); + prev_code = code; + } + else + { + if (code < table_size) + { + GIFIN_PUSH_STRING(code); + first = ps_rslt; + } + else + { + place = pstk_idx; + PUSH_PIXEL(NULL_CODE); + GIFIN_PUSH_STRING(prev_code); + first = ps_rslt; + pstk[place] = first; + } + + if((errno = gifin_add_string(prev_code, first)) != GIFIN_SUCCESS) + return errno; + prev_code = code; + } + } + + /* pop a pixel off the pixel stack */ + *pel = (int) pstk[--pstk_idx]; + + /* done! */ + return GIFIN_SUCCESS; +} + +/* + * close an open GIF file + */ + +static int gifin_close_file() +{ + /* make sure there's a file open */ + if (!file_open) + return GIFIN_ERR_NFO; + + /* mark file (and image) as closed */ + file_open = 0; + image_open = 0; + + /* done! */ + return GIFIN_SUCCESS; +} + +/* + * load a colormap from the input stream + */ + +static int gifin_load_cmap(BYTE cmap[3][256], int ncolors) +{ + int i; + + for (i=0; i 0); + + /* done! */ + return GIFIN_SUCCESS; +} + +/* + * read a new data block from the input stream + */ + +static int gifin_read_data_block() +{ + /* read the data block header */ + buf_cnt = fgetc(ins); + + /* read the data block body */ + if (fread(buf, 1, buf_cnt, ins) != buf_cnt) + return GIFIN_ERR_EOF; + + buf_idx = 0; + + /* done! */ + return GIFIN_SUCCESS; +} + + +/* + * add a new string to the string table + */ + +static int gifin_add_string(int p, int e) +{ + prefix[table_size] = p; + extnsn[table_size] = e; + + if ((table_size == code_mask) && (code_size < 12)) + { + code_size += 1; + code_mask = (1 << code_size) - 1; + } + + table_size += 1; + if (table_size > STAB_SIZE) + return GIFIN_ERR_TAO; + return GIFIN_SUCCESS; +} + +/* these are the routines added for interfacing to xli + */ + +/* tell someone what the image we're loading is. this could be a little more + * descriptive but I don't care + */ + +static void tellAboutImage(char *name) +{ + printf("\n%s:\n %dx%d %s%s image with %d colors\n", + name, gifin_img_width, gifin_img_height, + (gifin_interlace_flag ? "interlaced " : ""), + gif_version_name[gifin_version], + (gifin_l_cmap_flag ? gifin_l_ncolors : gifin_g_ncolors)); +} + +Image *gifLoad(char *fullname) +{ + FILE *zf; + Image *image; + int x, y, pixel, pass, scanlen; + byte *pixptr, *pixline; + int errno; + + if (!(zf = fopen(fullname,"r"))) + { + perror("gifLoad"); + return(NULL); + } + + if ((gifin_open_file(zf) != GIFIN_SUCCESS) || /* read GIF header */ + (gifin_open_image() != GIFIN_SUCCESS)) /* read image header */ + { + printf("gifin_open_file or gifin_open_image failed!\n"); + + gifin_close_file(); + fclose(zf); + return(NULL); + } + + tellAboutImage(fullname); + + image= newRGBImage(gifin_img_width, gifin_img_height, (gifin_l_cmap_flag ? + gifin_l_pixel_bits : + gifin_g_pixel_bits)); + image->title= dupString(fullname); + + /* if image has a local colormap, override global colormap + */ + + if (gifin_l_cmap_flag) + { + for (x= 0; x < gifin_l_ncolors; x++) + { + image->rgb.red[x]= gifin_l_cmap[GIF_RED][x] << 8; + image->rgb.green[x]= gifin_l_cmap[GIF_GRN][x] << 8; + image->rgb.blue[x]= gifin_l_cmap[GIF_BLU][x] << 8; + } + image->rgb.used= gifin_l_ncolors; + } + else + { + for (x= 0; x < gifin_g_ncolors; x++) + { + image->rgb.red[x]= gifin_g_cmap[GIF_RED][x] << 8; + image->rgb.green[x]= gifin_g_cmap[GIF_GRN][x] << 8; + image->rgb.blue[x]= gifin_g_cmap[GIF_BLU][x] << 8; + } + image->rgb.used= gifin_g_ncolors; + } + + /* interlaced image -- futz with the vertical trace. i wish i knew what + * kind of drugs the GIF people were on when they decided that they + * needed to support interlacing. + */ + + if (gifin_interlace_flag) + { + scanlen= image->height * image->pixlen; + + /* interlacing takes four passes to read, each starting at a different + * vertical point. + */ + + for (pass= 0; pass < 4; pass++) + { + y= interlace_start[pass]; + scanlen= image->width * image->pixlen * interlace_rate[pass]; + pixline= image->data + (y * image->width * image->pixlen); + while (y < gifin_img_height) + { + pixptr= pixline; + for (x= 0; x < gifin_img_width; x++) + { + if ((errno = gifin_get_pixel(&pixel)) != GIFIN_SUCCESS) + { + fprintf(stderr, "gifLoad: %s - Short read within image data, '%s'\n", fullname, get_err_string(errno)); + y = gifin_img_height; x = gifin_img_width; + } + valToMem(pixel, pixptr, image->pixlen); + pixptr += image->pixlen; + } + y += interlace_rate[pass]; + pixline += scanlen; + } + } + } + else + { + /* not an interlaced image, just read in sequentially + */ + + if(image->pixlen == 1) /* the usual case */ + { + pixptr= image->data; + for (y= 0; y < gifin_img_height; y++) + for (x= 0; x < gifin_img_width; x++) + { + if ((errno = gifin_get_pixel(&pixel)) != GIFIN_SUCCESS) + { + fprintf(stderr, "gifLoad: %s - Short read within image data, '%s'\n", fullname, get_err_string(errno)); + y = gifin_img_height; x = gifin_img_width; + } + valToMem(pixel, pixptr, 1); + pixptr += 1; + } + } + else /* less ususal case */ + { + pixptr= image->data; + for (y= 0; y < gifin_img_height; y++) + for (x= 0; x < gifin_img_width; x++) + { + if ((errno = gifin_get_pixel(&pixel)) != GIFIN_SUCCESS) + { + fprintf(stderr, "gifLoad: %s - Short read within image data, '%s'\n", fullname, get_err_string(errno)); + y = gifin_img_height; x = gifin_img_width; + } + valToMem(pixel, pixptr, image->pixlen); + pixptr += image->pixlen; + } + } + } + + gifin_close_file(); + fclose(zf); + + return(image); +} diff --git a/src/gif.h b/src/gif.h new file mode 100644 index 00000000..89c252fa --- /dev/null +++ b/src/gif.h @@ -0,0 +1,121 @@ + +/* gif.h: + * + * gifin.h + * kirk johnson + * november 1989 + * external interface to gifin.c + * + * Copyright 1989 Kirk L. Johnson (see the included file + * "kljcpyrght.h" for complete copyright information) + */ + +/* + * gifin return codes + */ +#define GIFIN_SUCCESS 0 /* success */ +#define GIFIN_DONE 1 /* no more images */ + +#define GIFIN_ERR_BAD_SD -1 /* bad screen descriptor */ +#define GIFIN_ERR_BAD_SEP -2 /* bad image separator */ +#define GIFIN_ERR_BAD_SIG -3 /* bad signature */ +#define GIFIN_ERR_EOD -4 /* unexpected end of raster data */ +#define GIFIN_ERR_EOF -5 /* unexpected end of input stream */ +#define GIFIN_ERR_FAO -6 /* file already open */ +#define GIFIN_ERR_IAO -7 /* image already open */ +#define GIFIN_ERR_NFO -8 /* no file open */ +#define GIFIN_ERR_NIO -9 /* no image open */ +#define GIFIN_ERR_PSO -10 /* pixel stack overflow */ +#define GIFIN_ERR_TAO -11 /* table overflow */ +#define GIFIN_ERR_BAD_DES -12 /* bad image descriptor */ + +#define GIFIN_ERR_BAD_SD_STR "Bad screen descriptor" +#define GIFIN_ERR_BAD_SEP_STR "Bad image separator" +#define GIFIN_ERR_BAD_SIG_STR "Bad signature" +#define GIFIN_ERR_EOD_STR "Unexpected end of raster data" +#define GIFIN_ERR_EOF_STR "Unexpected end of input stream" +#define GIFIN_ERR_FAO_STR "File already open" +#define GIFIN_ERR_IAO_STR "Image already open" +#define GIFIN_ERR_NFO_STR "No file open" +#define GIFIN_ERR_NIO_STR "No image open" +#define GIFIN_ERR_PSO_STR "Pixel stack overflow" +#define GIFIN_ERR_TAO_STR "Table overflow" +#define GIFIN_ERR_BAD_DES_STR "Bad image descriptor" + +typedef struct { + int err_no; + char *name; + } gif_err_string; + +#ifdef GIF_C +gif_err_string gif_err_strings[] = { + {GIFIN_ERR_BAD_SD, GIFIN_ERR_BAD_SD_STR}, + {GIFIN_ERR_BAD_SEP, GIFIN_ERR_BAD_SEP_STR}, + {GIFIN_ERR_BAD_SIG, GIFIN_ERR_BAD_SIG_STR}, + {GIFIN_ERR_EOD, GIFIN_ERR_EOD_STR}, + {GIFIN_ERR_EOF, GIFIN_ERR_EOF_STR}, + {GIFIN_ERR_FAO, GIFIN_ERR_FAO_STR}, + {GIFIN_ERR_IAO, GIFIN_ERR_IAO_STR}, + {GIFIN_ERR_NFO, GIFIN_ERR_NFO_STR}, + {GIFIN_ERR_NIO, GIFIN_ERR_NIO_STR}, + {GIFIN_ERR_PSO, GIFIN_ERR_PSO_STR}, + {GIFIN_ERR_TAO, GIFIN_ERR_TAO_STR}, + {GIFIN_ERR_BAD_DES, GIFIN_ERR_BAD_DES_STR}, + {0} + }; +#endif + +/* + * colormap indices + */ + +#define GIF_RED 0 +#define GIF_GRN 1 +#define GIF_BLU 2 + +/* + * typedef BYTE for convenience + */ + +typedef unsigned char BYTE; + +static int gifin_open_file(); +static int gifin_open_image(); +static int gifin_get_pixel(); +#if 0 +static int gifin_close_image(); +#endif +static int gifin_close_file(); +static int gifin_load_cmap(); +static int gifin_skip_extension(); +static int gifin_read_data_block(); +static int gifin_add_string(); + +/* #defines, typedefs, and such + */ + +#define GIF_SIG "GIF87a" +#define GIF_SIG_89 "GIF89a" + +#define GIF87a 0 /* Gif file version type */ +#define GIF89a 1 /* Gif file version type */ + +#define GIF_SIG_LEN 6 /* GIF signature length */ +#define GIF_SD_SIZE 7 /* GIF screen descriptor size */ +#define GIF_ID_SIZE 9 /* GIF image descriptor size */ + +#define GIF_SEPARATOR ',' /* GIF image separator */ +#define GIF_EXTENSION '!' /* GIF extension block marker */ +#define GIF_TERMINATOR ';' /* GIF terminator */ + +#define STAB_SIZE 4096 /* string table size */ +#define PSTK_SIZE 4096 /* pixel stack size */ + +#define NULL_CODE -1 /* string table null code */ + +#ifdef GIF_C +char *gif_version_name[] = { + GIF_SIG, + GIF_SIG_89 + }; +#endif diff --git a/src/gifload.c b/src/gifload.c new file mode 100644 index 00000000..89c06ae5 --- /dev/null +++ b/src/gifload.c @@ -0,0 +1,113 @@ +/*********************************************************** +* Rocks'n'Diamonds -- McDuffin Strikes Back! * +*----------------------------------------------------------* +* ©1995 Artsoft Development * +* Holger Schemel * +* 33659 Bielefeld-Senne * +* Telefon: (0521) 493245 * +* eMail: aeglos@valinor.owl.de * +* aeglos@uni-paderborn.de * +* q99492@pbhrzx.uni-paderborn.de * +*----------------------------------------------------------* +* gifload.c * +***********************************************************/ + +#ifndef MSDOS +#include "gifload.h" + +#include "xli.h" + + + +extern Pixmap test_pix[]; +extern Pixmap test_clipmask[]; +extern int test_picture_count; + + + + +int Read_GIF_to_Image(Display *display, Window window, char *filename) +{ + Image *image, *image_mask; + XImageInfo *ximageinfo, *ximageinfo_mask; + Pixmap pixmap, pixmap_mask; + int screen; + Visual *visual; + unsigned int depth; + + /* load GIF file */ + if (!(image = gifLoad(filename))) + { + printf("Loading GIF image failed -- maybe no GIF...\n"); + exit(1); + } + + if (image->depth > 8) + { + printf("Sorry, GIFs with more than 256 colors are not supported.\n"); + exit(1); + } + + /* minimize colormap */ + compress(image); + + screen = DefaultScreen(display); + visual = DefaultVisual(display, screen); + depth = DefaultDepth(display, screen); + + /* convert internal image structure to X11 XImage */ + if (!(ximageinfo = imageToXImage(display, screen, visual, depth, image))) + { + fprintf(stderr, "Cannot convert Image to XImage.\n"); + exit(1); + } + + if (ximageinfo->cmap != DefaultColormap(display, screen)) + { + printf("--> '%s' gets own colormap\n", filename); + + XSetWindowColormap(display, window, ximageinfo->cmap); + } + + /* convert XImage to Pixmap */ + if ((pixmap = ximageToPixmap(display, window, ximageinfo)) == None) + { + fprintf(stderr, "Cannot convert XImage to Pixmap.\n"); + exit(1); + } + + + printf("test_picture_count == %d\n", test_picture_count); + + + test_pix[test_picture_count] = pixmap; + + + /* create mono image for masking */ + image_mask = monochrome(image); + + /* convert internal image structure to X11 XImage */ + if (!(ximageinfo_mask = imageToXImage(display, screen, visual, depth, + image_mask))) + { + fprintf(stderr, "Cannot convert Image to XImage.\n"); + exit(1); + } + + /* convert XImage to Pixmap */ + if ((pixmap_mask = ximageToPixmap(display, window, ximageinfo_mask)) == None) + { + fprintf(stderr, "Cannot convert XImage to Pixmap.\n"); + exit(1); + } + + + test_clipmask[test_picture_count] = pixmap_mask; + + test_picture_count++; + + + return(GIF_Success); +} + +#endif diff --git a/src/gifload.h b/src/gifload.h new file mode 100644 index 00000000..06074967 --- /dev/null +++ b/src/gifload.h @@ -0,0 +1,39 @@ +/*********************************************************** +* Rocks'n'Diamonds -- McDuffin Strikes Back! * +*----------------------------------------------------------* +* ©1995 Artsoft Development * +* Holger Schemel * +* 33659 Bielefeld-Senne * +* Telefon: (0521) 493245 * +* eMail: aeglos@valinor.owl.de * +* aeglos@uni-paderborn.de * +* q99492@pbhrzx.uni-paderborn.de * +*----------------------------------------------------------* +* gifload.h * +***********************************************************/ + +#ifndef GIFLOAD_H +#define GIFLOAD_H + +#ifndef MSDOS +#include +#include +#include +#include +#include + +#define GIF_Success 0 +#define GIF_OpenFailed -1 +#define GIF_ReadFailed -2 +#define GIF_FileInvalid -3 +#define GIF_NoMemory -4 +#define GIF_ColorFailed -5 + +int Read_GIF_to_Image(Display *, Window, char *); +int Read_GIF_to_Bitmap(Display *, char *, Pixmap *); +int Read_GIF_to_Pixmap(Display *, char *, Pixmap *); +int Read_GIF_to_XImage(Display *, char *, XImage **); + +#endif + +#endif diff --git a/src/init.c b/src/init.c index 134cf74a..2eced3e3 100644 --- a/src/init.c +++ b/src/init.c @@ -19,14 +19,15 @@ #include "tools.h" #include "files.h" #include "joystick.h" -#include "gfxloader.h" +#include "gfxload.h" +#include "gifload.h" #include #ifdef DEBUG -/* + #define DEBUG_TIMING -*/ + #endif struct PictureFileInfo @@ -93,6 +94,7 @@ void InitSound() if (sound_status==SOUND_OFF) return; +#ifndef MSDOS if (access(sound_device_name,W_OK)<0) { fprintf(stderr,"%s: cannot access sound device - no sounds\n",progname); @@ -114,9 +116,16 @@ void InitSound() sound_loops_allowed = TRUE; sound_loops_on = TRUE; #endif +#else + sound_loops_allowed = TRUE; + sound_loops_on = TRUE; +#endif for(i=0;ipicture_filename) { + + + + + + sprintf(basefilename,"%s%s",pic->picture_filename,".gif"); + DrawInitText(basefilename,150,FC_YELLOW); + sprintf(filename,"%s/%s",GFX_PATH,basefilename); + +#ifdef DEBUG_TIMING + count1 = Counter(); +#endif + + Read_GIF_to_Image(display, window, filename); + +#ifdef DEBUG_TIMING + count2 = Counter(); + printf("GIF LOADING %s IN %.2f SECONDS\n", + filename,(float)(count2-count1)/100.0); +#endif + + + + + + sprintf(basefilename,"%s%s",pic->picture_filename,picture_ext); DrawInitText(basefilename,150,FC_YELLOW); +#ifdef MSDOS + rest(100); +#endif MSDOS sprintf(filename,"%s/%s",GFX_PATH,basefilename); #ifdef DEBUG_TIMING @@ -440,9 +533,19 @@ void LoadGfx(int pos, struct PictureFileInfo *pic) #ifdef XPM_INCLUDE_FILE xpm_att[pos].valuemask = XpmCloseness; + xpm_att[pos].closeness = 65535; + + /* xpm_att[pos].closeness = 20000; + */ + +#if 0 xpm_err = XpmReadFileToPixmap(display,window,filename, &pix[pos],&shapemask,&xpm_att[pos]); +#else + xpm_err = XpmSuccess; +#endif + switch(xpm_err) { case XpmOpenFailed: @@ -501,10 +604,11 @@ void LoadGfx(int pos, struct PictureFileInfo *pic) #ifdef DEBUG_TIMING count2 = Counter(); - printf("LOADING %s IN %.2f SECONDS\n", + printf("XPM LOADING %s IN %.2f SECONDS\n", filename,(float)(count2-count1)/100.0); #endif +#if 0 if (!pix[pos]) { fprintf(stderr, "%s: cannot read graphics file '%s'.\n", @@ -512,14 +616,22 @@ void LoadGfx(int pos, struct PictureFileInfo *pic) CloseAll(); exit(-1); } +#endif + } /* zugehörige Maske laden (wenn vorhanden) */ if (pic->picture_with_mask) { +#ifdef MSDOS + xbm_err = BitmapSuccess; + clipmask[pos] = DUMMY_MASK; + goto msdos_jmp; +#else sprintf(basefilename,"%s%s",pic->picture_filename,picturemask_ext); DrawInitText(basefilename,150,FC_YELLOW); sprintf(filename,"%s/%s",GFX_PATH,basefilename); +#endif #ifdef DEBUG_TIMING count1 = Counter(); @@ -527,8 +639,16 @@ void LoadGfx(int pos, struct PictureFileInfo *pic) #ifdef XPM_INCLUDE_FILE +#if 0 xbm_err = XReadBitmapFile(display,window,filename, &width,&height,&clipmask[pos],&hot_x,&hot_y); +#else + xbm_err = BitmapSuccess; +#endif + +#ifdef MSDOS +msdos_jmp: +#endif switch(xbm_err) { case BitmapSuccess: @@ -588,6 +708,7 @@ void LoadGfx(int pos, struct PictureFileInfo *pic) filename,(float)(count2-count1)/100.0); #endif +#if 0 if (!clipmask[pos]) { fprintf(stderr, "%s: cannot read graphics file '%s'.\n", @@ -595,7 +716,12 @@ void LoadGfx(int pos, struct PictureFileInfo *pic) CloseAll(); exit(-1); } +#endif + } + + pix[pos] = test_pix[test_picture_count-1]; + clipmask[pos] = test_clipmask[test_picture_count-1]; } void InitElementProperties() diff --git a/src/joystick.c b/src/joystick.c index 3855400d..7bf648ed 100644 --- a/src/joystick.c +++ b/src/joystick.c @@ -90,6 +90,7 @@ int Joystick() if (joystick_status==JOYSTICK_OFF) return(0); +#ifndef MSDOS if (read(joystick_device, &joy_ctrl, sizeof(joy_ctrl)) != sizeof(joy_ctrl)) { fprintf(stderr,"%s: cannot read joystick settings - no joystick support\n", @@ -131,6 +132,9 @@ int Joystick() result |= JOY_BUTTON_2; return(result); +#else + return(0); +#endif } int JoystickButton() diff --git a/src/main.c b/src/main.c index eed56094..2395ec1b 100644 --- a/src/main.c +++ b/src/main.c @@ -18,6 +18,10 @@ #include "sound.h" #include "joystick.h" +#ifdef MSDOS +#include +#endif + Display *display; int screen; Window window; @@ -25,6 +29,12 @@ GC gc, clip_gc[NUM_PIXMAPS]; Pixmap pix[NUM_PIXMAPS]; Pixmap clipmask[NUM_PIXMAPS]; + +Pixmap test_pix[NUM_PICTURES]; +Pixmap test_clipmask[NUM_PICTURES]; +int test_picture_count = 0; + + #ifdef XPM_INCLUDE_FILE XpmAttributes xpm_att[NUM_PICTURES]; #endif @@ -188,6 +198,10 @@ int main(int argc, char *argv[]) if (argc>1) level_directory = argv[1]; +#ifdef MSDOS + _fmode = O_BINARY; +#endif + OpenAll(argc,argv); EventLoop(); CloseAll(); diff --git a/src/main.h b/src/main.h index aff6db83..5969bfc4 100644 --- a/src/main.h +++ b/src/main.h @@ -15,11 +15,13 @@ #ifndef MAIN_H #define MAIN_H +#ifndef MSDOS #define XK_MISCELLANY #define XK_LATIN1 #include #include +#include #include #include #include @@ -27,6 +29,9 @@ #ifdef XPM_INCLUDE_FILE #include XPM_INCLUDE_FILE #endif +#else +#include "msdos.h" +#endif // von #ifndef MSDOS #include #include @@ -37,13 +42,20 @@ typedef int BOOL; -#define TRUE 1 -#define FALSE 0 +#ifndef FALSE +#define FALSE 0 +#define TRUE (!FALSE) +#endif -#define WIN_XPOS 0 -#define WIN_YPOS 0 #define WIN_XSIZE 672 #define WIN_YSIZE 560 +#ifndef MSDOS +#define WIN_XPOS 0 +#define WIN_YPOS 0 +#else +#define WIN_XPOS (XRES-WIN_XSIZE)/2 +#define WIN_YPOS (YRES-WIN_YSIZE)/2 +#endif #define SCR_FIELDX 17 #define SCR_FIELDY 17 #define MAX_BUF_XSIZE (SCR_FIELDX + 2) @@ -56,10 +68,18 @@ typedef int BOOL; #define MAX_LEV_FIELDX 128 #define MAX_LEV_FIELDY 128 +#ifndef MIN #define MIN(a,b) ((a)<(b) ? (a) : (b)) +#endif +#ifndef MAX #define MAX(a,b) ((a)>(b) ? (a) : (b)) +#endif +#ifndef ABS #define ABS(a) ((a)<0 ? -(a) : (a)) +#endif +#ifndef SIGN #define SIGN(a) ((a)<0 ? -1 : ((a)>0 ? 1 : 0)) +#endif #define SCROLLX(a) ((a)-scroll_x) #define SCROLLY(a) ((a)-scroll_y) #define UNSCROLLX(a) ((a)+scroll_x) @@ -250,6 +270,13 @@ extern XImage *image[]; extern Pixmap clipmask[]; extern Pixmap pix[]; + +extern Pixmap test_pix[]; +extern Pixmap test_clipmask[]; +extern int test_picture_count; + + + #ifdef XPM_INCLUDE_FILE extern XpmAttributes xpm_att[]; #endif @@ -935,10 +962,17 @@ extern char *progname; #define JOYDAT_PATH GAME_DIR #endif +#ifndef MSDOS #define SCORE_FILENAME "ROCKS.score" #define NAMES_FILENAME "ROCKS.names" #define LEVDIR_FILENAME "ROCKS.levelinfo" #define JOYDAT_FILENAME "ROCKS.joystick" +#else +#define SCORE_FILENAME "ROCKS.sco" +#define NAMES_FILENAME "ROCKS.nam" +#define LEVDIR_FILENAME "ROCKS.lev" +#define JOYDAT_FILENAME "ROCKS.joy" +#endif #define JOYDAT_FILE JOYDAT_PATH "/" JOYDAT_FILENAME @@ -982,8 +1016,13 @@ extern char *progname; #define MB_MENU_MARK TRUE #define MB_MENU_INITIALIZE (-1) #define MB_LEFT 1 +#ifdef MSDOS +#define MB_MIDDLE 4 +#define MB_RIGHT 2 +#else #define MB_MIDDLE 2 #define MB_RIGHT 3 +#endif /* values for key_status */ #define KEY_NOT_PRESSED FALSE diff --git a/src/new.c b/src/new.c new file mode 100644 index 00000000..0491352d --- /dev/null +++ b/src/new.c @@ -0,0 +1,170 @@ + +/* new.c: + * + * functions to allocate and deallocate structures and structure data + * + * jim frost 09.29.89 + * + * Copyright 1989, 1991 Jim Frost. + * See included file "copyright.h" for complete copyright information. + */ + +#include "xli.h" + +/* this table is useful for quick conversions between depth and ncolors + */ + +unsigned long DepthToColorsTable[] = +{ + /* 0 */ 1, + /* 1 */ 2, + /* 2 */ 4, + /* 3 */ 8, + /* 4 */ 16, + /* 5 */ 32, + /* 6 */ 64, + /* 7 */ 128, + /* 8 */ 256, + /* 9 */ 512, + /* 10 */ 1024, + /* 11 */ 2048, + /* 12 */ 4096, + /* 13 */ 8192, + /* 14 */ 16384, + /* 15 */ 32768, + /* 16 */ 65536, + /* 17 */ 131072, + /* 18 */ 262144, + /* 19 */ 524288, + /* 20 */ 1048576, + /* 21 */ 2097152, + /* 22 */ 4194304, + /* 23 */ 8388608, + /* 24 */ 16777216 +}; + +char *dupString(char *s) +{ + char *d; + + if (!s) + return(NULL); + + d = (char *)lmalloc(strlen(s) + 1); + strcpy(d, s); + return(d); +} + +void newRGBMapData(RGBMap *rgb, unsigned int size) +{ + rgb->used = 0; + rgb->size = size; + rgb->compressed = FALSE; + rgb->red = (Intensity *)lmalloc(sizeof(Intensity) * size); + rgb->green = (Intensity *)lmalloc(sizeof(Intensity) * size); + rgb->blue = (Intensity *)lmalloc(sizeof(Intensity) * size); +} + +void freeRGBMapData(RGBMap *rgb) +{ + lfree((byte *)rgb->red); + lfree((byte *)rgb->green); + lfree((byte *)rgb->blue); +} + +Image *newBitImage(unsigned int width, unsigned int height) +{ + Image *image; + unsigned int linelen; + + image = (Image *)lmalloc(sizeof(Image)); + image->type = IBITMAP; + image->title = NULL; + newRGBMapData(&(image->rgb), (unsigned int)2); + *(image->rgb.red)= *(image->rgb.green) = *(image->rgb.blue)= 65535; + *(image->rgb.red + 1)= *(image->rgb.green + 1) = *(image->rgb.blue + 1)= 0; + image->rgb.used = 2; + image->width = width; + image->height = height; + image->depth = 1; + linelen = ((width + 7) / 8); + image->data = (unsigned char *)lcalloc(linelen * height); + return(image); +} + +Image *newRGBImage(unsigned int width, unsigned int height, unsigned int depth) +{ + Image *image; + unsigned int pixlen, numcolors; + + if (depth == 0) /* special case for `zero' depth image, which is */ + depth = 1; /* sometimes interpreted as `one color' */ + pixlen = ((depth+7) / 8); + numcolors = depthToColors(depth); + image = (Image *)lmalloc(sizeof(Image)); + image->type = IRGB; + image->title = NULL; + newRGBMapData(&(image->rgb), numcolors); + image->width = width; + image->height = height; + image->depth = depth; + image->pixlen = pixlen; + image->data = (unsigned char *)lmalloc(width * height * pixlen); + return(image); +} + +void freeImageData(Image *image) +{ + if (image->title) + { + lfree((byte *)image->title); + image->title= NULL; + } + freeRGBMapData(&(image->rgb)); + lfree(image->data); +} + +void freeImage(Image *image) +{ + freeImageData(image); + lfree((byte *)image); +} + +byte *lmalloc(unsigned int size) +{ + byte *area; + + if (size == 0) + { + size = 1; + } + if (!(area = (byte *)malloc(size))) + { + fprintf(stderr, "Out of memory!\n"); + exit(1); + } + + return(area); +} + +byte *lcalloc(unsigned int size) +{ + byte *area; + + if (size == 0) + { + size = 1; + } + if (!(area = (byte *)calloc(1, size))) + { + fprintf(stderr, "Out of memory!\n"); + exit(1); + } + + return(area); +} + +void lfree(byte *area) +{ + free(area); +} diff --git a/src/random.c b/src/random.c index e85a9f02..b2fa0d41 100644 --- a/src/random.c +++ b/src/random.c @@ -21,7 +21,9 @@ * It was reworked for the GNU C Library by Roland McGrath. */ +#ifndef MSDOS #include +#endif #include #include #include diff --git a/src/screens.c b/src/screens.c index 13bf5fab..90305d7e 100644 --- a/src/screens.c +++ b/src/screens.c @@ -25,6 +25,10 @@ #include "joystick.h" #include "cartoons.h" +#ifdef MSDOS +extern unsigned char get_ascii(KeySym); +#endif + void DrawHeadline() { int x1 = SX+(SXSIZE - strlen(GAMETITLE_STRING) * FONT1_XSIZE) / 2; @@ -700,6 +704,7 @@ void HandleTypeName(int newxpos, KeySym key) return; } +#ifndef MSDOS if ((key>=XK_A && key<=XK_Z) || (key>=XK_a && key<=XK_z && xpos=XK_a && key<=XK_z) ascii = 'a'+(char)(key-XK_a); +#else + if((ascii = get_ascii(key)) && xposwidth, cimage->height); + if (cimage->title) + { + image->title= (char *)lmalloc(strlen(cimage->title) + 13); + sprintf(image->title, "%s (monochrome)", cimage->title); + } + + spl = cimage->pixlen; + dll = (image->width / 8) + (image->width % 8 ? 1 : 0); + + sp = cimage->data; + dp = image->data; + + for (y= 0; y < cimage->height; y++) + { + for (x= 0; x < cimage->width; x++) + { + dp2 = dp + (x / 8); /* dp + x/8 */ + color= memToVal(sp, spl); + + if (cimage->rgb.red[color] > 0x0000 || + cimage->rgb.green[color] > 0x0000 || + cimage->rgb.blue[color] > 0x0000) + bitmap_pixel = 0x00; + else + bitmap_pixel = 0x80; + + *dp2 |= bitmap_pixel >> ( x % 8); + sp += spl; + } + + dp += dll; /* next row */ + } + + printf("done\n"); + + return(image); +} + +static unsigned int *buildIndex(unsigned int width, + unsigned int zoom, + unsigned int *rwidth) +{ + float fzoom; + unsigned int *index; + unsigned int a; + + if (!zoom) + { + fzoom= 100.0; + *rwidth= width; + } + else + { + fzoom= (float)zoom / 100.0; + *rwidth= (unsigned int)(fzoom * width + 0.5); + } + index= (unsigned int *)lmalloc(sizeof(unsigned int) * *rwidth); + for (a= 0; a < *rwidth; a++) + { + if (zoom) + *(index + a)= (unsigned int)((float)a / fzoom + 0.5); + else + *(index + a)= a; + } + return(index); +} + +Image *zoom(Image *oimage, unsigned int xzoom, unsigned int yzoom) +{ + Image *image; + unsigned int *xindex, *yindex; + unsigned int xwidth, ywidth; + unsigned int x, y, xsrc, ysrc; + unsigned int pixlen; + unsigned int srclinelen; + unsigned int destlinelen; + byte *srcline, *srcptr; + byte *destline, *destptr; + byte srcmask, destmask, bit; + Pixel value; + + if ((!xzoom || xzoom==100) && (!yzoom || yzoom==100)) + return(oimage); + + if (!xzoom) + printf(" Zooming image Y axis by %d%%...", yzoom); + else if (!yzoom) + printf(" Zooming image X axis by %d%%...", xzoom); + else if (xzoom == yzoom) + printf(" Zooming image by %d%%...", xzoom); + else + printf(" Zooming image X axis by %d%% and Y axis by %d%%...", + xzoom, yzoom); + fflush(stdout); + + xindex= buildIndex(oimage->width, xzoom, &xwidth); + yindex= buildIndex(oimage->height, yzoom, &ywidth); + + switch (oimage->type) + { + case IBITMAP: + image= newBitImage(xwidth, ywidth); + for (x= 0; x < oimage->rgb.used; x++) + { + *(image->rgb.red + x)= *(oimage->rgb.red + x); + *(image->rgb.green + x)= *(oimage->rgb.green + x); + *(image->rgb.blue + x)= *(oimage->rgb.blue + x); + } + image->rgb.used= oimage->rgb.used; + destline= image->data; + destlinelen= (xwidth / 8) + (xwidth % 8 ? 1 : 0); + srcline= oimage->data; + srclinelen= (oimage->width / 8) + (oimage->width % 8 ? 1 : 0); + for (y= 0, ysrc= *(yindex + y); y < ywidth; y++) + { + while (ysrc != *(yindex + y)) + { + ysrc++; + srcline += srclinelen; + } + srcptr= srcline; + destptr= destline; + srcmask= 0x80; + destmask= 0x80; + bit= srcmask & *srcptr; + for (x= 0, xsrc= *(xindex + x); x < xwidth; x++) + { + if (xsrc != *(xindex + x)) + { + do + { + xsrc++; + if (!(srcmask >>= 1)) + { + srcmask= 0x80; + srcptr++; + } + } + while (xsrc != *(xindex + x)); + + bit= srcmask & *srcptr; + } + if (bit) + *destptr |= destmask; + if (!(destmask >>= 1)) + { + destmask= 0x80; + destptr++; + } + } + destline += destlinelen; + } + break; + + case IRGB: + image= newRGBImage(xwidth, ywidth, oimage->depth); + for (x= 0; x < oimage->rgb.used; x++) + { + *(image->rgb.red + x)= *(oimage->rgb.red + x); + *(image->rgb.green + x)= *(oimage->rgb.green + x); + *(image->rgb.blue + x)= *(oimage->rgb.blue + x); + } + image->rgb.used= oimage->rgb.used; + + pixlen= oimage->pixlen; + destptr= image->data; + srcline= oimage->data; + srclinelen= oimage->width * pixlen; + for (y= 0, ysrc= *(yindex + y); y < ywidth; y++) + { + while (ysrc != *(yindex + y)) + { + ysrc++; + srcline += srclinelen; + } + + srcptr = srcline; + value = memToVal(srcptr, image->pixlen); + + for (x=0, xsrc= *(xindex + x); xtitle = dupString(oimage->title); + lfree((byte *)xindex); + lfree((byte *)yindex); + + printf("done\n"); + + return(image); +} + +void compress(Image *image) +{ + unsigned char *used, fast[32][32][32]; + unsigned int dmask; /* Depth mask protection */ + Pixel *map; + unsigned int next_index; + Intensity *red = image->rgb.red, + *green = image->rgb.green, + *blue = image->rgb.blue; + Intensity r,g,b; + unsigned int x, y, badcount = 0, dupcount = 0, unusedcount = 0; + unsigned char *pixptr, *pixend; + + if (!RGBP(image) || image->rgb.compressed) + return; + + printf(" Compressing colormap..."); + fflush(stdout); + + used = (unsigned char *)lcalloc(sizeof(unsigned char) * depthToColors(image->depth)); + dmask = (1 << image->depth) -1; /* Mask any illegal bits for that depth */ + map = (Pixel *)lcalloc(sizeof(Pixel) * depthToColors(image->depth)); + + /* init fast duplicate check table */ + for(r=0;r<32;r++) + for(g=0;g<32;g++) + for(b=0;b<32;b++) + fast[r][g][b] = 0; + + /* do pass 1 through the image to check index usage */ + + pixptr = image->data; + pixend = pixptr + (image->height * image->width); + for(;pixptr < pixend; pixptr++) + used[(*pixptr) & dmask] = 1; + + /* count the bad pixels */ + for (x = image->rgb.used; x < depthToColors(image->depth); x++) + if (used[x]) + badcount++; + + /* figure out duplicates and unuseds, and create the new mapping */ + next_index = 0; + for (x = 0; x < image->rgb.used; x++) + { + if (!used[x]) + { + unusedcount++; + continue; /* delete this index */ + } + + /* check for duplicate */ + r = red[x]; + g = green[x]; + b = blue[x]; + if (fast[r>>11][g>>11][b>>11]) /* if matches fast check */ + { + /* then do a linear search */ + for (y = x+1; y < image->rgb.used; y++) + { + if (r == red[y] && g == green[y] && b == blue[y]) + break; + } + if (y < image->rgb.used) /* found match */ + { + map[x] = y; + dupcount++; + continue; /* delete this index */ + } + fast[r>>11][g>>11][b>>11] = 1; + } + /* will map to this index */ + map[x] = next_index; + next_index++; + } + + /* change the image pixels */ + pixptr = image->data; + pixend = pixptr + (image->height * image->width); + for(;pixptr < pixend; pixptr++) + *pixptr = map[(*pixptr) & dmask]; + + /* change the colormap */ + for (x = 0; x < image->rgb.used; x++) + { + if (!used[x]) + continue; + red[map[x]] = red[x]; + green[map[x]] = green[x]; + blue[map[x]] = blue[x]; + } + image->rgb.used = next_index; + + /* clean up */ + lfree(map); + lfree(used); + + if (badcount) + printf("%d out-of-range pixels, ", badcount); + + if (!unusedcount && !dupcount) + printf("no improvment\n"); + else + { + if (dupcount) + printf("%d duplicate%s and %d unused color%s removed...", + dupcount, (dupcount == 1 ? "" : "s"), + unusedcount, (unusedcount == 1 ? "" : "s")); + printf("%d unique color%s\n", + next_index, (next_index == 1 ? "" : "s")); + } + + image->rgb.compressed= TRUE; /* don't do it again */ +} + + + + +Pixmap ximageToPixmap(Display *disp, Window parent, XImageInfo *ximageinfo) +{ + Pixmap pixmap; + + pixmap = XCreatePixmap(disp, parent, + ximageinfo->ximage->width, ximageinfo->ximage->height, + ximageinfo->depth); + + ximageinfo->drawable = pixmap; + + sendXImage(ximageinfo, 0, 0, 0, 0, + ximageinfo->ximage->width, ximageinfo->ximage->height); + return(pixmap); +} + +/* find the best pixmap depth supported by the server for a particular + * visual and return that depth. + * + * this is complicated by R3's lack of XListPixmapFormats so we fake it + * by looking at the structure ourselves. + */ + +static unsigned int bitsPerPixelAtDepth(Display *disp, int scrn, + unsigned int depth) +{ +#if defined(XlibSpecificationRelease) && (XlibSpecificationRelease >= 4) + /* the way things are */ + XPixmapFormatValues *xf; + int nxf, a; + + xf = XListPixmapFormats(disp, &nxf); + for (a = 0; a < nxf; a++) + { + if (xf[a].depth == depth) + { + int bpp; + bpp = xf[a].bits_per_pixel; + XFree(xf); + return (unsigned int) bpp; + } + } + XFree(xf); +#else /* the way things were (X11R3) */ + unsigned int a; + + for (a= 0; a < disp->nformats; a++) + if (disp->pixmap_format[a].depth == depth) + return(disp->pixmap_format[a].bits_per_pixel); +#endif + + /* this should never happen; if it does, we're in trouble + */ + + fprintf(stderr, "bitsPerPixelAtDepth: Can't find pixmap depth info!\n"); + exit(1); +} + +/* + visual: visual to use + ddepth: depth of the visual to use +*/ +XImageInfo *imageToXImage(Display *disp, + int scrn, + Visual *visual, + unsigned int ddepth, + Image *image) +{ + Pixel *redvalue, *greenvalue, *bluevalue; + unsigned int a, c=0, x, y, linelen, dpixlen, dbits; + XColor xcolor; + XGCValues gcv; + XImageInfo *ximageinfo; + Image *orig_image; + + static Colormap our_default_cmap = 0; + static Pixel *our_default_index; + static int free_cmap_entries, max_cmap_entries; + int use_cmap_entry; + + if (!our_default_cmap) + { +#if 0 + our_default_cmap = DefaultColormap(disp, scrn); +#endif + + our_default_cmap = XCreateColormap(disp, RootWindow(disp, scrn), + visual, AllocNone); + our_default_index = (Pixel *)lmalloc(sizeof(Pixel) * NOFLASH_COLORS); + + for (a=0; adisp= disp; + ximageinfo->scrn= scrn; + ximageinfo->depth= 0; + ximageinfo->drawable= None; + ximageinfo->index= NULL; + ximageinfo->rootimage= FALSE; /* assume not */ + ximageinfo->foreground= ximageinfo->background= 0; + ximageinfo->gc= NULL; + ximageinfo->ximage= NULL; + + /* do color allocation + */ + + switch (visual->class) + { + case TrueColor: + case DirectColor: + { + Pixel pixval; + unsigned int redcolors, greencolors, bluecolors; + unsigned int redstep, greenstep, bluestep; + unsigned int redbottom, greenbottom, bluebottom; + unsigned int redtop, greentop, bluetop; + + redvalue= (Pixel *)lmalloc(sizeof(Pixel) * 256); + greenvalue= (Pixel *)lmalloc(sizeof(Pixel) * 256); + bluevalue= (Pixel *)lmalloc(sizeof(Pixel) * 256); + +#if 1 + if (visual == DefaultVisual(disp, scrn)) + ximageinfo->cmap= DefaultColormap(disp, scrn); + else + ximageinfo->cmap= XCreateColormap(disp, RootWindow(disp, scrn), + visual, AllocNone); +#else + ximageinfo->cmap = our_default_cmap; +#endif + + retry_direct: /* tag we hit if a DirectColor allocation fails on + * default colormap */ + + /* calculate number of distinct colors in each band + */ + + redcolors= greencolors= bluecolors= 1; + for (pixval= 1; pixval; pixval <<= 1) + { + if (pixval & visual->red_mask) + redcolors <<= 1; + if (pixval & visual->green_mask) + greencolors <<= 1; + if (pixval & visual->blue_mask) + bluecolors <<= 1; + } + + /* sanity check + */ + + if ((redcolors > visual->map_entries) || + (greencolors > visual->map_entries) || + (bluecolors > visual->map_entries)) + { + fprintf(stderr, "Warning: inconsistency in color information (this may be ugly)\n"); + } + + redstep = 256 / redcolors; + greenstep = 256 / greencolors; + bluestep = 256 / bluecolors; + redbottom = greenbottom = bluebottom = 0; + redtop = greentop = bluetop = 0; + for (a= 0; a < visual->map_entries; a++) + { + if (redbottom < 256) + redtop= redbottom + redstep; + if (greenbottom < 256) + greentop= greenbottom + greenstep; + if (bluebottom < 256) + bluetop= bluebottom + bluestep; + + xcolor.red= (redtop - 1) << 8; + xcolor.green= (greentop - 1) << 8; + xcolor.blue= (bluetop - 1) << 8; + if (! XAllocColor(disp, ximageinfo->cmap, &xcolor)) + { + /* if an allocation fails for a DirectColor default visual then + * we should create a private colormap and try again. + */ + + if ((visual->class == DirectColor) && + (visual == DefaultVisual(disp, scrn))) + { +#if 1 + ximageinfo->cmap = XCreateColormap(disp, RootWindow(disp, scrn), + visual, AllocNone); +#else + our_default_cmap = XCopyColormapAndFree(disp, our_default_cmap); + ximageinfo->cmap = our_default_cmap; +#endif + goto retry_direct; + } + + /* something completely unexpected happened + */ + + fprintf(stderr, "imageToXImage: XAllocColor failed on a TrueColor/Directcolor visual\n"); + lfree((byte *)redvalue); + lfree((byte *)greenvalue); + lfree((byte *)bluevalue); + lfree((byte *)ximageinfo); + return(NULL); + } + + /* fill in pixel values for each band at this intensity + */ + + while ((redbottom < 256) && (redbottom < redtop)) + redvalue[redbottom++]= xcolor.pixel & visual->red_mask; + while ((greenbottom < 256) && (greenbottom < greentop)) + greenvalue[greenbottom++]= xcolor.pixel & visual->green_mask; + while ((bluebottom < 256) && (bluebottom < bluetop)) + bluevalue[bluebottom++]= xcolor.pixel & visual->blue_mask; + } + } + break; + + default: /* Not TrueColor or DirectColor */ + + ximageinfo->index= (Pixel *)lmalloc(sizeof(Pixel) * (image->rgb.used+NOFLASH_COLORS)); + + + /* get the colormap to use. + */ + + ximageinfo->cmap = our_default_cmap; + + /* allocate colors shareable (if we can) + */ + + for (a= 0; a < image->rgb.used; a++) + { + int i; + XColor xcolor2; + + xcolor.red= *(image->rgb.red + a); + xcolor.green= *(image->rgb.green + a); + xcolor.blue= *(image->rgb.blue + a); + + for (i=max_cmap_entries-1; i>=free_cmap_entries; i--) + { + xcolor2.pixel = *(our_default_index + i); + XQueryColor(disp, ximageinfo->cmap, &xcolor2); + + if ((xcolor.red >> 8) == (xcolor2.red >> 8) && + (xcolor.green >> 8) == (xcolor2.green >> 8) && + (xcolor.blue >> 8) == (xcolor2.blue >> 8)) + break; + } + + use_cmap_entry = i; + + if (use_cmap_entry < free_cmap_entries) + free_cmap_entries--; + + if (free_cmap_entries < 0) + { + printf("imageToXImage: too many global colors!\n"); + exit(0); + } + + xcolor.pixel = use_cmap_entry; + *(ximageinfo->index + a) = xcolor.pixel; + XStoreColor(disp, ximageinfo->cmap, &xcolor); + } + + ximageinfo->no = a; /* number of pixels allocated in default visual */ + + printf("still %d free colormap entries\n", free_cmap_entries); + } + + + + /* create an XImage and related colormap based on the image type + * we have. + */ + + printf(" Building XImage..."); + fflush(stdout); + + switch (image->type) + { + case IBITMAP: + { + byte *data; + + /* we copy the data to be more consistent + */ + + linelen = ((image->width + 7) / 8); + data= lmalloc(linelen * image->height); + + memcpy((char *)data, (char *)image->data, linelen * image->height); + + gcv.function= GXcopy; + ximageinfo->ximage= XCreateImage(disp, visual, 1, XYBitmap, + 0, (char *)data, image->width, image->height, + 8, linelen); + + /* use this if you want to use the bitmap as a mask */ + ximageinfo->depth = image->depth; + + if(visual->class == DirectColor || visual->class == TrueColor) + { + Pixel pixval; + dbits= bitsPerPixelAtDepth(disp, scrn, ddepth); + dpixlen= (dbits + 7) / 8; + pixval= redvalue[image->rgb.red[0] >> 8] | + greenvalue[image->rgb.green[0] >> 8] | + bluevalue[image->rgb.blue[0] >> 8]; + ximageinfo->background = pixval; + pixval= redvalue[image->rgb.red[1] >> 8] | + greenvalue[image->rgb.green[1] >> 8] | + bluevalue[image->rgb.blue[1] >> 8]; + ximageinfo->foreground = pixval; + } + else /* Not Direct or True Color */ + { + ximageinfo->foreground = BlackPixel(disp,scrn); + ximageinfo->background = WhitePixel(disp,scrn); + } + ximageinfo->ximage->bitmap_bit_order= MSBFirst; + ximageinfo->ximage->byte_order= MSBFirst; + + break; + } + + case IRGB: + { + /* modify image data to match visual and colormap + */ + + byte *data, *destptr, *srcptr; + + dbits = bitsPerPixelAtDepth(disp, scrn, ddepth); /* bits per pixel */ + dpixlen = (dbits + 7) / 8; /* bytes per pixel */ + + ximageinfo->ximage = XCreateImage(disp, visual, ddepth, ZPixmap, 0, + NULL, image->width, image->height, + 8, image->width * dpixlen); + + data = (byte *)lmalloc(image->width * image->height * dpixlen); + ximageinfo->depth = ddepth; + ximageinfo->ximage->data = (char *)data; + ximageinfo->ximage->byte_order = MSBFirst; + srcptr = image->data; + destptr = data; + + switch (visual->class) + { + case DirectColor: + case TrueColor: + { + Pixel pixval; + + for (y=0; yheight; y++) + { + for (x=0; xwidth; x++) + { + pixval = memToVal(srcptr, 1); + pixval = redvalue[image->rgb.red[pixval] >> 8] | + greenvalue[image->rgb.green[pixval] >> 8] | + bluevalue[image->rgb.blue[pixval] >> 8]; + valToMem(pixval, destptr, dpixlen); + srcptr += 1; + destptr += dpixlen; + } + } + break; + } + + default: + { + if (dpixlen == 1) /* most common */ + { + for (y=0; yheight; y++) + { + for (x=0; xwidth; x++) + { + *destptr = ximageinfo->index[c + *srcptr]; + srcptr++; + destptr++; + } + } + } + else /* less common */ + { + for (y=0; yheight; y++) + { + for (x=0; xwidth; x++) + { + register unsigned long temp; + temp = memToVal(srcptr, 1); + valToMem(ximageinfo->index[c + temp], destptr, dpixlen); + srcptr += 1; + destptr += dpixlen; + } + } + } + } + break; + } + } + } + + printf("done\n"); + + if (redvalue) + { + lfree((byte *)redvalue); + lfree((byte *)greenvalue); + lfree((byte *)bluevalue); + } + + if (image != orig_image) + freeImage(image); + return(ximageinfo); +} + +/* Given an XImage and a drawable, move a rectangle from the Ximage + * to the drawable. + */ + +void sendXImage(XImageInfo *ximageinfo, + int src_x, int src_y, int dst_x, int dst_y, + unsigned int w, unsigned int h) +{ + XGCValues gcv; + + /* build and cache the GC + */ + + if (!ximageinfo->gc) + { + gcv.function = GXcopy; + if (ximageinfo->ximage->depth == 1) + { + gcv.foreground = ximageinfo->foreground; + gcv.background = ximageinfo->background; + ximageinfo->gc = XCreateGC(ximageinfo->disp, ximageinfo->drawable, + GCFunction | GCForeground | GCBackground, + &gcv); + } + else + ximageinfo->gc = XCreateGC(ximageinfo->disp, ximageinfo->drawable, + GCFunction, &gcv); + } + + XPutImage(ximageinfo->disp, ximageinfo->drawable, ximageinfo->gc, + ximageinfo->ximage, src_x, src_y, dst_x, dst_y, w, h); +} + +/* free up anything cached in the local Ximage structure. + */ + +void freeXImage(Image *image, XImageInfo *ximageinfo) +{ + if (ximageinfo->index != NULL) /* if we allocated colors */ + { + if (ximageinfo->no > 0 && !ximageinfo->rootimage) /* don't free root colors */ + XFreeColors(ximageinfo->disp, ximageinfo->cmap, ximageinfo->index, ximageinfo->no, 0); + lfree(ximageinfo->index); + } + if (ximageinfo->gc) + XFreeGC(ximageinfo->disp, ximageinfo->gc); + lfree((byte *)ximageinfo->ximage->data); + ximageinfo->ximage->data= NULL; + XDestroyImage(ximageinfo->ximage); + lfree((byte *)ximageinfo); + /* should we free private color map to ??? */ +} diff --git a/src/sound.c b/src/sound.c index 3ee23f30..516892b5 100644 --- a/src/sound.c +++ b/src/sound.c @@ -13,9 +13,13 @@ ***********************************************************/ #include "sound.h" +#ifdef MSDOS +extern void sound_handler(struct SoundControl); +#endif /*** THE STUFF BELOW IS ONLY USED BY THE SOUND SERVER CHILD PROCESS ***/ +#ifndef MSDOS static struct SoundControl playlist[MAX_SOUNDS_PLAYING]; static struct SoundControl emptySoundControl = { @@ -28,18 +32,27 @@ static char premix_right_buffer[SND_BLOCKSIZE]; static int premix_last_buffer[SND_BLOCKSIZE]; static unsigned char playing_buffer[SND_BLOCKSIZE]; static int playing_sounds = 0; +#else +struct SoundControl playlist[MAX_SOUNDS_PLAYING]; +struct SoundControl emptySoundControl; +int playing_sounds; +#endif void SoundServer() { + int i; +#ifndef MSDOS struct SoundControl snd_ctrl; fd_set sound_fdset; - int i; close(sound_pipe[1]); /* no writing into pipe needed */ +#endif for(i=0;ilongest) { @@ -317,6 +334,10 @@ void SoundServer_InsertNewSound(struct SoundControl snd_ctrl) longest_nr=i; } } +#ifdef MSDOS + voice_set_volume(playlist[longest_nr].voice, 0); + deallocate_voice(playlist[longest_nr].voice); +#endif playlist[longest_nr] = emptySoundControl; playing_sounds--; } @@ -337,6 +358,11 @@ void SoundServer_InsertNewSound(struct SoundControl snd_ctrl) { playlist[i].fade_sound = FALSE; playlist[i].volume = PSND_MAX_VOLUME; +#ifdef MSDOS + playlist[i].loop = PSND_LOOP; + voice_stop_volumeramp(playlist[i].voice); + voice_ramp_volume(playlist[i].voice, playlist[i].volume, 1000); +#endif } } return; @@ -355,13 +381,21 @@ void SoundServer_InsertNewSound(struct SoundControl snd_ctrl) if (!playlist[i].active || playlist[i].nr != snd_ctrl.nr) continue; +#ifndef MSDOS actual = 100 * playlist[i].playingpos / playlist[i].data_len; +#else + actual = playlist[i].playingpos; +#endif if (actual>=longest) { longest=actual; longest_nr=i; } } +#ifdef MSDOS + voice_set_volume(playlist[longest_nr].voice, 0); + deallocate_voice(playlist[longest_nr].voice); +#endif playlist[longest_nr] = emptySoundControl; playing_sounds--; } @@ -373,6 +407,14 @@ void SoundServer_InsertNewSound(struct SoundControl snd_ctrl) { playlist[i] = snd_ctrl; playing_sounds++; +#ifdef MSDOS + playlist[i].voice = allocate_voice(Sound[snd_ctrl.nr].sample_ptr); + if(snd_ctrl.loop) + voice_set_playmode(playlist[i].voice, PLAYMODE_LOOP); + voice_set_volume(playlist[i].voice, snd_ctrl.volume); + voice_set_pan(playlist[i].voice, snd_ctrl.stereo); + voice_start(playlist[i].voice); +#endif break; } } @@ -402,12 +444,18 @@ void SoundServer_StopSound(int nr) for(i=0;iname,sound_ext); +#ifndef MSDOS if (!(file=fopen(filename,"r"))) { fprintf(stderr,"%s: cannot open sound file '%s' - no sounds\n", @@ -661,6 +722,17 @@ BOOL LoadSound(struct SoundInfo *snd_info) } return(FALSE); +#else + snd_info->sample_ptr = load_sample(filename); + if(!snd_info->sample_ptr) + { + fprintf(stderr,"%s: cannot read sound file '%s' - no sounds\n", + progname,filename); + fclose(file); + return(FALSE); + } + return(TRUE); +#endif // von #ifndef MSDOS } void PlaySound(int nr) @@ -703,12 +775,16 @@ void PlaySoundExt(int nr, int volume, int stereo, BOOL loop) snd_ctrl.data_ptr = Sound[nr].data_ptr; snd_ctrl.data_len = Sound[nr].data_len; +#ifndef MSDOS if (write(sound_pipe[1], &snd_ctrl, sizeof(snd_ctrl))<0) { fprintf(stderr,"%s: cannot pipe to child process - no sounds\n",progname); sound_status=SOUND_OFF; return; } +#else + sound_handler(snd_ctrl); +#endif } void FadeSound(int nr) @@ -749,12 +825,16 @@ void StopSoundExt(int nr, int method) snd_ctrl.stop_sound = TRUE; } +#ifndef MSDOS if (write(sound_pipe[1], &snd_ctrl, sizeof(snd_ctrl))<0) { fprintf(stderr,"%s: cannot pipe to child process - no sounds\n",progname); sound_status=SOUND_OFF; return; } +#else + sound_handler(snd_ctrl); +#endif } void FreeSounds(int max) @@ -765,7 +845,11 @@ void FreeSounds(int max) return; for(i=0;i +#ifdef MSDOS +extern BOOL wait_for_vsync; +#endif + void SetDrawtoField(int mode) { if (mode == DRAW_BUFFERED && soft_scrolling_on) @@ -84,6 +88,9 @@ void BackToFront() if (redraw_mask & REDRAW_FIELD) { +#ifdef MSDOS + wait_for_vsync = TRUE; +#endif if (game_status != PLAYING || redraw_mask & REDRAW_FROM_BACKBUFFER) XCopyArea(display,backbuffer,window,gc, REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, @@ -116,6 +123,9 @@ void BackToFront() if (redraw_mask & REDRAW_DOORS) { +#ifdef MSDOS + wait_for_vsync = TRUE; +#endif if (redraw_mask & REDRAW_DOOR_1) XCopyArea(display,backbuffer,window,gc, DX,DY, DXSIZE,DYSIZE, @@ -1469,6 +1479,9 @@ BOOL AreYouSure(char *text, unsigned int ays_state) case FocusOut: HandleFocusEvent((XFocusChangeEvent *) &event); break; + case ClientMessage: + HandleClientMessageEvent((XClientMessageEvent *) &event); + break; default: break; } @@ -1553,6 +1566,10 @@ unsigned int MoveDoor(unsigned int door_state) static unsigned int door2 = DOOR_CLOSE_2; int x, start, stepsize = 4, door_anim_delay = stepsize*5000; +#ifdef MSDOS + stepsize = 2; +#endif + if (door_state == DOOR_GET_STATE) return(door1 | door2); @@ -1656,7 +1673,9 @@ unsigned int MoveDoor(unsigned int door_state) } BackToFront(); +#ifndef MSDOS Delay(door_anim_delay); +#endif if (game_status==MAINMENU) DoAnimation(); diff --git a/src/xli.h b/src/xli.h new file mode 100644 index 00000000..1bdf6691 --- /dev/null +++ b/src/xli.h @@ -0,0 +1,154 @@ + +/* xli.h: + * + * jim frost 06.21.89 + * + * Copyright 1989 Jim Frost. See included file "copyright.h" for complete + * copyright information. + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +typedef unsigned long Pixel; /* what X thinks a pixel is */ +typedef unsigned short Intensity; /* what X thinks an RGB intensity is */ +typedef unsigned char byte; /* unsigned byte type */ + +#define FALSE 0 +#define TRUE (!FALSE) + +/* Display device dependent Information structure */ +typedef struct +{ + int width; /* Display width and height */ + int height; + + Display *disp; + int scrn; + Colormap colormap; +} DisplayInfo; + +/* This struct holds the X-client side bits for a rendered image. */ +typedef struct +{ + Display *disp; /* destination display */ + int scrn; /* destination screen */ + int depth; /* depth of drawable we want/have */ + Drawable drawable; /* drawable to send image to */ + Pixel *index; /* array of pixel values allocated */ + int no; /* number of pixels in the array */ + int rootimage; /* True if is a root image - eg, retain colors */ + Pixel foreground; /* foreground and background pixels for mono images */ + Pixel background; + Colormap cmap; /* colormap used for image */ + GC gc; /* cached gc for sending image */ + XImage *ximage; /* ximage structure */ +} XImageInfo; + +/* Function declarations */ +void sendXImage(); /* send.c */ +XImageInfo *imageToXImage(); +Pixmap ximageToPixmap(); +void freeXImage(); + + +typedef struct rgbmap { + unsigned int size; /* size of RGB map */ + unsigned int used; /* number of colors used in RGB map */ + int compressed; /* image uses colormap fully */ + Intensity *red; /* color values in X style */ + Intensity *green; + Intensity *blue; +} RGBMap; + +/* image structure + */ + +typedef struct { + char *title; /* name of image */ + unsigned int type; /* type of image */ + RGBMap rgb; /* RGB map of image if IRGB type */ + unsigned int width; /* width of image in pixels */ + unsigned int height; /* height of image in pixels */ + unsigned int depth; /* depth of image in bits if IRGB type */ + unsigned int pixlen; /* length of pixel if IRGB type */ + byte *data; /* data rounded to full byte for each row */ + float gamma; /* gamma of display the image is adjusted for */ +} Image; + +#define IBITMAP 0 /* image is a bitmap */ +#define IRGB 1 /* image is RGB */ + +#define BITMAPP(IMAGE) ((IMAGE)->type == IBITMAP) +#define RGBP(IMAGE) ((IMAGE)->type == IRGB) + +#define depthToColors(n) DepthToColorsTable[((n) < 24 ? (n) : 24)] + +/* + * Architecture independent memory to value conversions. + * Note the "Normal" internal format is big endian. + */ + +#define memToVal(PTR,LEN) ( \ +(LEN) == 1 ? (unsigned long)( *( (byte *)(PTR)) ) : \ +(LEN) == 2 ? (unsigned long)(((unsigned long)(*( (byte *)(PTR)) ))<< 8) \ + + ( *(((byte *)(PTR))+1) ) : \ +(LEN) == 3 ? (unsigned long)(((unsigned long)(*( (byte *)(PTR)) ))<<16) \ + + (((unsigned long)(*(((byte *)(PTR))+1)))<< 8) \ + + ( *(((byte *)(PTR))+2) ) : \ + (unsigned long)(((unsigned long)(*( (byte *)(PTR)) ))<<24) \ + + (((unsigned long)(*(((byte *)(PTR))+1)))<<16) \ + + (((unsigned long)(*(((byte *)(PTR))+2)))<< 8) \ + + ( *(((byte *)(PTR))+3) ) ) + +#define valToMem(VAL,PTR,LEN) ( \ +(LEN) == 1 ? (*( (byte *)(PTR) ) = ( VAL ) ) : \ +(LEN) == 2 ? (*( (byte *)(PTR) ) = (((unsigned long)(VAL))>> 8), \ + *(((byte *)(PTR))+1) = ( VAL ) ) : \ +(LEN) == 3 ? (*( (byte *)(PTR) ) = (((unsigned long)(VAL))>>16), \ + *(((byte *)(PTR))+1) = (((unsigned long)(VAL))>> 8), \ + *(((byte *)(PTR))+2) = ( VAL ) ) : \ + (*( (byte *)(PTR) ) = (((unsigned long)(VAL))>>24), \ + *(((byte *)(PTR))+1) = (((unsigned long)(VAL))>>16), \ + *(((byte *)(PTR))+2) = (((unsigned long)(VAL))>> 8), \ + *(((byte *)(PTR))+3) = ( VAL ) )) + + +/* functions */ + +void cleanUpWindow(); /* window.c */ +char imageInWindow(); + +int visualClassFromName(); +char *nameOfVisualClass(); + +extern unsigned long DepthToColorsTable[]; /* new.c */ +char *dupString(); +Image *newBitImage(); +Image *newRGBImage(); +void freeImage(); +void freeImageData(); +void newRGBMapData(); +void freeRGBMapData(); +byte *lcalloc(); +byte *lmalloc(); +void lfree(); + +Image *gifLoad(); +Image *monochrome(); +Image *zoom(); + +void compress(); /* compress.c */ + +int xliOpenDisplay(); +void tellAboutDisplay(DisplayInfo *); +void xliCloseDisplay(DisplayInfo *);