static void setup_wav_header(snd_pcm_t *pcm, struct wav_fmt *fmt) { fmt->fmt = TO_LE16(0x01); fmt->chan = TO_LE16(pcm->channels); fmt->rate = TO_LE32(pcm->rate); fmt->bwidth = pcm->frame_bits / 8; fmt->bps = fmt->bwidth * pcm->rate; fmt->bits = snd_pcm_format_width(pcm->format); fmt->bps = TO_LE32(fmt->bps); fmt->bwidth = TO_LE16(fmt->bwidth); fmt->bits = TO_LE16(fmt->bits); }
static void dumpResource(FILE *fp, int type, int index, const ResourceEntry *re) { fprintf(stdout, "Resource size %d flags 0x%x id 0x%x type 0x%x\n", re->size, re->flags, re->id, type); FILE *out; char name[32]; snprintf(name, sizeof(name), "%s%d", resourceTypeName(type), index); const int pos = ftell(fp); fseek(fp, re->offset, SEEK_SET); uint8_t *buf = (uint8_t *)malloc(re->size); if (buf) { fread(buf, 1, re->size, fp); switch (type) { case kResTypeIcon: out = fopen(name, "wb"); if (out) { // icons are stored with DIB header uint8_t header[BITMAPFILEHEADER_SIZE]; header[0] = 'B'; header[1] = 'M'; TO_LE32(header + 2, BITMAPFILEHEADER_SIZE + re->size); TO_LE16(header + 6, 0); TO_LE16(header + 8, 0); TO_LE32(header + 10, BITMAPFILEHEADER_SIZE + BITMAPINFOHEADER_SIZE + 16 * 4); fwrite(header, 1, sizeof(header), out); // Fixup dimensions to 32x32, the lower 32 rows contain garbage if (buf[0] == 40 && buf[4] == 32 && buf[8] == 64) { fprintf(stdout, "Fixing up dimensions to 32x32\n"); buf[8] = 32; } fwrite(buf, 1, re->size, out); fclose(out); } break; case kResTypeData: out = fopen(name, "wb"); if (out) { fwrite(buf, 1, re->size, out); fclose(out); } break; } free(buf); } fseek(fp, pos, SEEK_SET); }
/** * Generic .PCX file image writer. * @param name Filename, including extension. * @param callb Callback function for generating lines of pixels. * @param userdata User data, passed on to \a callb. * @param w Width of the image in pixels. * @param h Height of the image in pixels. * @param pixelformat Bits per pixel (bpp), either 8 or 32. * @param palette %Colour palette (for 8bpp images). * @return File was written successfully. * @see ScreenshotHandlerProc */ static bool MakePCXImage(const char *name, ScreenshotCallback *callb, void *userdata, uint w, uint h, int pixelformat, const Colour *palette) { FILE *f; uint maxlines; uint y; PcxHeader pcx; bool success; if (pixelformat == 32) { DEBUG(misc, 0, "Can't convert a 32bpp screenshot to PCX format. Please pick another format."); return false; } if (pixelformat != 8 || w == 0) return false; f = fopen(name, "wb"); if (f == NULL) return false; memset(&pcx, 0, sizeof(pcx)); /* setup pcx header */ pcx.manufacturer = 10; pcx.version = 5; pcx.rle = 1; pcx.bpp = 8; pcx.xmax = TO_LE16(w - 1); pcx.ymax = TO_LE16(h - 1); pcx.hdpi = TO_LE16(320); pcx.vdpi = TO_LE16(320); pcx.planes = 1; pcx.cpal = TO_LE16(1); pcx.width = pcx.pitch = TO_LE16(w); pcx.height = TO_LE16(h); /* write pcx header */ if (fwrite(&pcx, sizeof(pcx), 1, f) != 1) { fclose(f); return false; } /* use by default 64k temp memory */ maxlines = Clamp(65536 / w, 16, 128); /* now generate the bitmap bits */ uint8 *buff = CallocT<uint8>(w * maxlines); // by default generate 128 lines at a time. y = 0; do { /* determine # lines to write */ uint n = min(h - y, maxlines); uint i; /* render the pixels into the buffer */ callb(userdata, buff, y, w, n); y += n; /* write them to pcx */ for (i = 0; i != n; i++) { const uint8 *bufp = buff + i * w; byte runchar = bufp[0]; uint runcount = 1; uint j; /* for each pixel... */ for (j = 1; j < w; j++) { uint8 ch = bufp[j]; if (ch != runchar || runcount >= 0x3f) { if (runcount > 1 || (runchar & 0xC0) == 0xC0) { if (fputc(0xC0 | runcount, f) == EOF) { free(buff); fclose(f); return false; } } if (fputc(runchar, f) == EOF) { free(buff); fclose(f); return false; } runcount = 0; runchar = ch; } runcount++; } /* write remaining bytes.. */ if (runcount > 1 || (runchar & 0xC0) == 0xC0) { if (fputc(0xC0 | runcount, f) == EOF) { free(buff); fclose(f); return false; } } if (fputc(runchar, f) == EOF) { free(buff); fclose(f); return false; } } } while (y != h); free(buff); /* write 8-bit colour palette */ if (fputc(12, f) == EOF) { fclose(f); return false; } /* Palette is word-aligned, copy it to a temporary byte array */ byte tmp[256 * 3]; for (uint i = 0; i < 256; i++) { tmp[i * 3 + 0] = palette[i].r; tmp[i * 3 + 1] = palette[i].g; tmp[i * 3 + 2] = palette[i].b; } success = fwrite(tmp, sizeof(tmp), 1, f) == 1; fclose(f); return success; }
/** * Generic .BMP writer * @param name file name including extension * @param callb callback used for gathering rendered image * @param userdata parameters forwarded to \a callb * @param w width in pixels * @param h height in pixels * @param pixelformat bits per pixel * @param palette colour palette (for 8bpp mode) * @return was everything ok? * @see ScreenshotHandlerProc */ static bool MakeBMPImage(const char *name, ScreenshotCallback *callb, void *userdata, uint w, uint h, int pixelformat, const Colour *palette) { uint bpp; // bytes per pixel switch (pixelformat) { case 8: bpp = 1; break; /* 32bpp mode is saved as 24bpp BMP */ case 32: bpp = 3; break; /* Only implemented for 8bit and 32bit images so far */ default: return false; } FILE *f = fopen(name, "wb"); if (f == NULL) return false; /* Each scanline must be aligned on a 32bit boundary */ uint bytewidth = Align(w * bpp, 4); // bytes per line in file /* Size of palette. Only present for 8bpp mode */ uint pal_size = pixelformat == 8 ? sizeof(RgbQuad) * 256 : 0; /* Setup the file header */ BitmapFileHeader bfh; bfh.type = TO_LE16('MB'); bfh.size = TO_LE32(sizeof(BitmapFileHeader) + sizeof(BitmapInfoHeader) + pal_size + bytewidth * h); bfh.reserved = 0; bfh.off_bits = TO_LE32(sizeof(BitmapFileHeader) + sizeof(BitmapInfoHeader) + pal_size); /* Setup the info header */ BitmapInfoHeader bih; bih.size = TO_LE32(sizeof(BitmapInfoHeader)); bih.width = TO_LE32(w); bih.height = TO_LE32(h); bih.planes = TO_LE16(1); bih.bitcount = TO_LE16(bpp * 8); bih.compression = 0; bih.sizeimage = 0; bih.xpels = 0; bih.ypels = 0; bih.clrused = 0; bih.clrimp = 0; /* Write file header and info header */ if (fwrite(&bfh, sizeof(bfh), 1, f) != 1 || fwrite(&bih, sizeof(bih), 1, f) != 1) { fclose(f); return false; } if (pixelformat == 8) { /* Convert the palette to the windows format */ RgbQuad rq[256]; for (uint i = 0; i < 256; i++) { rq[i].red = palette[i].r; rq[i].green = palette[i].g; rq[i].blue = palette[i].b; rq[i].reserved = 0; } /* Write the palette */ if (fwrite(rq, sizeof(rq), 1, f) != 1) { fclose(f); return false; } } /* Try to use 64k of memory, store between 16 and 128 lines */ uint maxlines = Clamp(65536 / (w * pixelformat / 8), 16, 128); // number of lines per iteration uint8 *buff = MallocT<uint8>(maxlines * w * pixelformat / 8); // buffer which is rendered to uint8 *line = AllocaM(uint8, bytewidth); // one line, stored to file memset(line, 0, bytewidth); /* Start at the bottom, since bitmaps are stored bottom up */ do { uint n = min(h, maxlines); h -= n; /* Render the pixels */ callb(userdata, buff, h, w, n); /* Write each line */ while (n-- != 0) { if (pixelformat == 8) { /* Move to 'line', leave last few pixels in line zeroed */ memcpy(line, buff + n * w, w); } else { /* Convert from 'native' 32bpp to BMP-like 24bpp. * Works for both big and little endian machines */ Colour *src = ((Colour *)buff) + n * w; byte *dst = line; for (uint i = 0; i < w; i++) { dst[i * 3 ] = src[i].b; dst[i * 3 + 1] = src[i].g; dst[i * 3 + 2] = src[i].r; } } /* Write to file */ if (fwrite(line, bytewidth, 1, f) != 1) { free(buff); fclose(f); return false; } } } while (h != 0); free(buff); fclose(f); return true; }