mirror of
https://github.com/1dot13/source.git
synced 2026-07-29 13:52:17 +02:00
libsmacker is an open reimplementation of the parts of smackw32.dll needed to get frames and audio out of an .smk file. Vendoring it here is the first step to dropping the proprietary SMACKW32.LIB/SMACKW32.DLL dependency. Nothing links against it yet. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
171 lines
3.3 KiB
C
171 lines
3.3 KiB
C
/*
|
|
* libsmacker - A C library for decoding .smk Smacker Video files Copyright
|
|
* (C) 2012-2013 Greg Kennedy
|
|
*
|
|
* See smacker.h for more information.
|
|
*
|
|
* driver.c Driver program
|
|
*/
|
|
|
|
|
|
#include "smacker.h"
|
|
|
|
#include <stdio.h>
|
|
|
|
void
|
|
dump_bmp(const unsigned char *pal, const unsigned char *image_data, unsigned int w, unsigned int h, unsigned int framenum)
|
|
{
|
|
int i;
|
|
FILE *fp;
|
|
char filename [128];
|
|
unsigned int temp;
|
|
sprintf(filename, "bmp/out_%04u.bmp", framenum);
|
|
fp = fopen(filename, "wb");
|
|
if (!fp) { fprintf(stderr, "Failed to open %s for write\n", filename); return; }
|
|
fwrite("BM", 2, 1, fp);
|
|
temp = 1078 + (w * h);
|
|
fwrite(&temp, 4, 1, fp);
|
|
temp = 0;
|
|
fwrite(&temp, 4, 1, fp);
|
|
temp = 1078;
|
|
fwrite(&temp, 4, 1, fp);
|
|
temp = 40;
|
|
fwrite(&temp, 4, 1, fp);
|
|
fwrite(&w, 4, 1, fp);
|
|
fwrite(&h, 4, 1, fp);
|
|
temp = 1;
|
|
fwrite(&temp, 2, 1, fp);
|
|
temp = 8;
|
|
fwrite(&temp, 4, 1, fp);
|
|
temp = 0;
|
|
fwrite(&temp, 2, 1, fp);
|
|
temp = w * h;
|
|
fwrite(&temp, 4, 1, fp);
|
|
temp = 0;
|
|
fwrite(&temp, 4, 1, fp);
|
|
fwrite(&temp, 4, 1, fp);
|
|
temp = 256;
|
|
fwrite(&temp, 4, 1, fp);
|
|
temp = 256;
|
|
fwrite(&temp, 4, 1, fp);
|
|
temp = 0;
|
|
for (i = 0; i < 256; i++)
|
|
{
|
|
fwrite(&pal[(i * 3) + 2], 1, 1, fp);
|
|
fwrite(&pal[(i * 3) + 1], 1, 1, fp);
|
|
fwrite(&pal[(i * 3)], 1, 1, fp);
|
|
fwrite(&temp, 1, 1, fp);
|
|
}
|
|
|
|
for (i = h - 1; i >= 0; i--)
|
|
{
|
|
fwrite(&image_data[i * w], w, 1, fp);
|
|
}
|
|
|
|
fclose(fp);
|
|
}
|
|
|
|
int
|
|
main(int argc, char *argv[])
|
|
{
|
|
unsigned long w, h, f;
|
|
double usf;
|
|
smk s;
|
|
|
|
char filename [128];
|
|
|
|
FILE *fpo[7] = {NULL};
|
|
|
|
if (argc != 2)
|
|
{
|
|
printf("Usage: %s file.smk\n", argv[0]);
|
|
return -1;
|
|
}
|
|
/* s = smk_open(argv[1], SMK_MODE_DISK); */
|
|
s = smk_open_file(argv[1], SMK_MODE_MEMORY);
|
|
if (s == NULL)
|
|
{
|
|
printf("Errors encountered opening %s, exiting.\n", argv[1]);
|
|
return -1;
|
|
}
|
|
/* print some info about the file */
|
|
smk_info_all(s, NULL, &f, &usf);
|
|
smk_info_video(s, &w, &h, NULL);
|
|
|
|
printf("Opened file %s\nWidth: %lu\nHeight: %lu\nFrames: %lu\nFPS: %f\n", argv[1], w, h, f, 1000000.0 / usf);
|
|
|
|
unsigned char a_t, a_c[7], a_d[7];
|
|
unsigned long a_r[7];
|
|
|
|
smk_info_audio(s, &a_t, a_c, a_d, a_r);
|
|
|
|
int i;
|
|
for (i = 0; i < 7; i++)
|
|
{
|
|
printf("Audio track %d: %u bits, %u channels, %luhz\n", i, a_d[i], a_c[i], a_r[i]);
|
|
}
|
|
|
|
/* Turn on decoding for palette, video, and audio track 0 */
|
|
smk_enable_video(s, 1);
|
|
|
|
for (i = 0; i < 7; i++)
|
|
{
|
|
if (a_t & (1 << i))
|
|
{
|
|
smk_enable_audio(s, i, 1);
|
|
sprintf(filename, "out_%01d.raw", i);
|
|
fpo[i] = fopen(filename, "wb");
|
|
} else
|
|
{
|
|
fpo[i] = NULL;
|
|
}
|
|
}
|
|
|
|
//Get a pointer to first frame
|
|
|
|
smk_first(s);
|
|
|
|
unsigned long cur_frame;
|
|
|
|
smk_info_all(s, &cur_frame, NULL, NULL);
|
|
dump_bmp(smk_get_palette(s), smk_get_video(s), w, h, cur_frame);
|
|
|
|
for (i = 0; i < 7; i++)
|
|
{
|
|
if (fpo[i] != NULL)
|
|
{
|
|
fwrite(smk_get_audio(s, i), smk_get_audio_size(s, i), 1, fpo[i]);
|
|
}
|
|
}
|
|
printf(" -> Frame %lu\n", cur_frame);
|
|
|
|
|
|
for (cur_frame = 1; cur_frame < f; cur_frame ++)
|
|
{
|
|
smk_next(s);
|
|
/* smk_info_all(s, &cur_frame, NULL, NULL); */
|
|
|
|
dump_bmp(smk_get_palette(s), smk_get_video(s), w, h, cur_frame);
|
|
|
|
for (i = 0; i < 7; i++)
|
|
{
|
|
if (fpo[i] != NULL)
|
|
{
|
|
fwrite(smk_get_audio(s, i), smk_get_audio_size(s, i), 1, fpo[i]);
|
|
}
|
|
}
|
|
fprintf(stderr," -> Frame %lu\n", cur_frame);
|
|
//Advance to next frame
|
|
|
|
}
|
|
|
|
for (i = 0; i < 7; i++)
|
|
if (fpo[i] != NULL)
|
|
{
|
|
fclose(fpo[i]);
|
|
}
|
|
smk_close(s);
|
|
|
|
return 0;
|
|
}
|