Viacom New Media Graphics File Format
Jump to navigation
Jump to search
Viacom New Media Graphics File Format
Format type | Tileset |
---|---|
Hardware | VGA |
Max tile count | 232-1 |
Palette | Internal |
Tile names? | No |
Minimum tile size (pixels) | 0×0 |
Maximum tile size (pixels) | Unlimited |
Plane count | 1 |
Plane arrangement | Linear |
Transparent pixels? | Palette-based |
Hitmap pixels? | No |
Metadata? | None |
Supports sub-tilesets? | No |
Compressed tiles? | Yes |
Hidden data? | Yes |
Games |
Beavis and Butthead In Virtual Stupidity stores its graphics externally in .VNM/.000 files. This information here is preliminary and needs verification and is subject to change.
VNM_HEADER: VNM File Header
Data Type | Description |
---|---|
UINT32LE Signature | File Signature (should match 0x564E4D1A aka "VNM\x1A") |
UINT32LE Flags | Possibly file information flags. |
UINT32LE Size | Size Of Data |
UINT32LE OffsetPal | Offset to Pal Data. |
UINT32LE OffsetUnknown1 | Offset to currently Unknown Data. |
UINT32LE OffsetUnknown2 | Offset to currently Unknown Data. |
UINT32LE OffsetImages | Offset to VNM_IMAGE array. |
UINT32LE PalIndexFirst | First Valid Index in Colour Palette. |
UINT32LE PalIndexSize | Count of Palette Indexes stored in file at OffsetPal. |
UINT32LE ImageCount | Count of Images stored in file at OffsetImages. |
VNM_IMAGE: VNM Image Header
Data Type | Description |
---|---|
UINT32LE Offset | Offset in file to where raw image data starts. |
UINT32LE Type | 0 = Bitmap, 1 = Sprite |
UINT32LE Width | Width of this Image |
UINT32LE Height | Height of this Image. |
UINT32LE XPos | XPos of this Image. |
UINT32LE YPos | YPos of this Image. |
Example code
This is test code that decompresses/decodes/extracts Sprite 196 from VNM raw data in the BBLOOGIE Mini-game. Image can be seen in the infobox.
An somewhat explained version of the raw data is below.
F800 19 FD00 18F700 0F FB F901 18 19 FF00 18FF0117 19 F801 0E 10 FD00 0F FA07 19 18 18 17 18 19 17 19 F801 0E 10 FD00 0F FA08 19 17 19 19 17 19 18 18 19 FF00 19 FB05 0F 11 0F 11 0F 10 FB0B 19 18 17 19 18 17 18 18 17 19 17 18 FB05 10 11 10 11 0E 11 FB0C 18 18 19 19 18 17 18 19 17 19 17 19 18 FC04 11 0E 0F 10 0E FF FC0D 19 17 19 18 19 19 17 18 19 17 18 17 19 18 FD05 10 0E 11 10 11 0F FF FC0D 19 17 19 18 19 17 18 19 17 18 19 17 19 17 FD05 10 0F 11 11 10 11 FF FC0D 18 17 19 17 18 17 19 18 17 18 19 18 19 19 FC04 11 10 10 0F 10 FF FC0E 18 18 19 17 17 19 19 18 17 18 19 19 18 19 18 FD03 11 0F 0F 10 FE FC0E 19 18 19 18 19 18 19 18 17 18 19 18 17 18 19 FD02 11 11 10 FD FC0E 19 18 19 18 19 17 19 19 17 18 19 17 17 19 19 FD02 11 10 0F FD FC0E 19 17 18 10 0F 18 19 17 18 19 19 18 17 19 19 FD02 11 0F 10 FD FC0E 18 17 19 0F 0E 0F 18 18 19 0F 10 18 17 19 18 FD02 11 0F 10 FD FC0E 19 17 19 0E 0E 0E 0E 0E 0E 0E 0E 0F 18 19 18 FD02 11 0E 10 FD FC0E 19 18 10 0E 0F 0F 0E 0E 0E 0E 0F 0F 10 17 19 FD02 11 0E 10 FD FC0E 18 19 0F 10 11 11 10 0E 0F 10 11 10 0F 17 19 FD02 11 0E 10 FD FC0E 17 19 0E 0F 10 10 11 0F 10 11 10 0F 0E 18 19 FD02 11 0E 10 FD FC0E 19 17 10 0E 0F 0E 0F 0E 10 0F 0E 0E 0E 19 18 FD02 11 0E 10 FD FC0E 18 11 0F 0E 0E 0F 10 0E 0E 10 0F 0E 0E 19 17 FD02 11 0E 10 FD FB0D 10 0F 0E 0E 10 11 0F 11 10 10 0E 0F 10 17 FD02 10 0E 11 FD FB0C 11 10 0F 0E 0E 0F 10 10 0F 0F 0E 0F 0FFC02 10 0E 11 FD FA0B 11 0F 0E 0E 0E 0F 0F 0F 0E 0E 0F 11FC02 0E 0F 11 FD FA0B 11 10 0F 0E 0F 20 10 20 0F 0E 0F 11FD02 10 0E 10 FC F90A 10 0F 0E 10 20 20 20 10 0F 10 11FD02 0E 0F 11 FC F909 11 0F 0E 11 15 16 15 11 0F 10FD02 10 0E 10 FB F909 11 0F 0E 11 1C 1C 1C 11 0F 11FD02 0E 0F 11 FB F808 10 0F 10 11 1C 11 10 0F 11FE02 10 0E 10 FA F807 10 0F 0F 10 11 10 0F 10FE03 10 0E 0F 11 FA F807 11 10 0F 0E 0F 0E 0F 11FF041B 10 0E 10 11 FA F70B 11 10 0F 0E 0F 10 11 17 1B 10 0F 11 F9 F70B 11 10 10 10 10 11 17 1B 1A 1B 10 11 F9 F60A 11 10 0F 10 11 1C 1B 1A 1A 1B 1B F9 F70B 1B 1B 10 10 10 1B 1C 1B 1A 1A 1A 1C F9 F90D 1B 1B 1A 1A 1B 1B 1B 1A 1B 1A 1A 1A 1B 1C F9 FA0D 1B 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1B 1C F8 FB0E 1B 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1B 1C F8 FC0E 1B 1A 1A 1A 1B 1A 1A 1A 1A 1A 1A 1A 1A 1B 1C F7 FC0E 1B 1A 1A 1B 1C 1B 1A 1A 1A 1A 1A 1A 1B 1B 1C F7 FD0F 10 10 1B 1B 1C 1B 1B 1A 1A 1A 1A 1A 1A 1B 1B 1C F7 FD0F 10 0F 10 1C 1C 1B 1A 1A 1A 1A 1A 1A 1A 1B 1B 1C F7 FE03 10 0E 10 11FF0A1C 1B 1A 1A 1A 1A 1A 1A 1A 1B 1C F6 FE02 10 0F 11 FE0A1C 1B 1A 1A 1A 1A 1A 1A 1A 1B 1C F6 FF03 10 0E 10 11 FE0A1C 1B 1A 1A 1A 1A 1A 1A 1A 1B 1C F6 FF02 10 0F 11 FD0A 1C 1B 1A 1A 1A 1A 1A 1A 1A 1B 1C F6 FF02 10 10 11 FD0A 1C 1B 1A 1A 1A 1A 1A 1A 1A 1B 1C F6 02 10 0F 10 FC0A 1C 1B 1A 1A 1A 1A 1A 1A 1A 1B 1C F6 02 10 0E 11 FC0A 1C 1B 1A 1A 1A 1A 1A 1A 1A 1B 1C F6 02 10 0E 11 FC0A 1C 1B 1A 1A 1A 1A 1A 1A 1A 1B 1C F6 02 10 0E 11 FC0A 1C 1B 1A 1A 1A 1A 1A 1A 1A 1B 1C F6 02 10 0E 11 FD0B1C 1B 1A 1A 1A 1A 1A 1A 1A 1A 1B 1C F6 02 10 0F 11 FD0B1C 1B 1A 1A 1A 1A 1A 1A 1A 1A 1B 1C F6 02 10 10 11 FD0B1C 1B 1A 1A 1A 1A 1A 1A 1A 1A 1B 1C F6 03 10 0F 0F 10 FE0B1C 1B 1A 1A 1A 1A 1A 1A 1A 1A 1B 1C F6 04 11 0E 10 0F 10FF0B1C 1B 1B 1A 1A 1A 1A 1A 1A 1B 1B 1C F6 03 11 0E 0F 11 FE0B1C 1C 1C 1B 1B 1B 1B 1B 1B 1C 1C 1C F6 03 11 0F 0E 10 FE0B22 22 22 21 21 21 21 21 21 21 22 22 F6 FF02 11 11 11 FE0B22 21 21 20 20 20 20 20 20 20 21 22 F6 FA0B 22 21 20 20 20 20 20 20 20 20 21 22 F6 FA0B 22 21 20 20 20 21 20 20 20 20 21 22 F6 FA0B 22 21 20 20 21 22 21 20 20 20 21 22 F6 FA0B 22 21 20 20 21 22 22 21 20 20 21 22 F6 FA0B 22 21 21 21 21 22 22 21 21 21 21 22 F6 F909 11 10 0F 10 11 11 10 0F 10 11 F5 F909 11 0F 0E 0F 11 11 0F 0E 0F 11 F5 F909 11 0F 0E 0F 11 11 0F 0E 0F 11 F5 F909 11 0F 0E 0F 11 11 0F 0E 0F 11 F5 F909 11 0F 0E 0F 11 11 0F 0E 0F 11 F5 F909 11 10 0E 0F 11 11 0F 0E 10 11 F5 F807 11 0E 0F 11 11 0F 0E 11 F4 F807 11 0E 0F 11 11 0F 0E 11 F4 F807 11 0E 0F 11 11 0F 0E 11 F4 F807 11 0E 0F 11 11 0F 0E 11 F4 F807 11 0E 10 11 11 10 0E 11 F4 F802 16 16 16 FE02 16 16 16 F4 F802 16 15 16 FE02 16 15 16 F4 F802 16 15 16 FE02 16 15 16 F4 F802 16 15 16 FE02 16 15 16 F4 F807 1C 1C 1C 1C 1C 1C 1C 1C F4 FA0B 1C 1B 1A 1B 1B 1C 1C 1B 1B 1A 1B 1C F6 FB0D 1C 1B 1A 1B 1B 1C 1C 1C 1C 1B 1B 1A 1B 1C F7 FB04 1C 1C 1C 1C 1C FC04 1C 1C 1C 1C 1C F7
Some current BETA demo code is below. Fully functional.
//
// .VNM/.000 Image Extractor - by Napalm
// BETA - Please do not use this in production mods
//
// License: Creative Commons Attribution-Share Alike 2.0 UK: England & Wales
// http://creativecommons.org/licenses/by-sa/2.0/uk/
//
// If you use this all or part of my code please credit me as the license states.
//
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pshpack2.h>
typedef struct _BITMAPFILEHDR {
unsigned short type;
unsigned long size;
unsigned short reserved1;
unsigned short reserved2;
unsigned long offset;
} BITMAPFILEHDR;
typedef struct _BITMAPINFOHDR {
unsigned long size;
signed long width;
signed long height;
unsigned short planes;
unsigned short bitcount;
unsigned long compression;
unsigned long image_size;
signed long x_per_meter;
signed long y_per_meter;
unsigned long colors_used;
unsigned long colors_important;
} BITMAPINFOHDR;
#include <poppack.h>
typedef struct _VNMSPRITE {
unsigned long offset; // to bitmap/frame data
unsigned long type; // 0 = Bitmap, 1 = Sprite
signed long width;
signed long height;
signed long x;
signed long y;
} VNMSPRITE;
typedef struct _VNMHEADER {
unsigned long signature; // 0x564E4D1A 'VNM\x1A' // 1.10 version?
unsigned long zero; // 0 ? start of file? always zero?
unsigned long size; // 324764 ? size of file
unsigned long paletteoffset;
unsigned long offset1; // fixed 256 long array of something?
unsigned long offset2; // fixed 256 long array of something?
unsigned long spriteoffset; //
unsigned long palettestart; // 10 start palette index?
unsigned long palettesize; // 236 number of palette entries?
signed long spritecount; // 212 number of sprite index?
} VNMHEADER;
void extractpalette(unsigned long *palette, unsigned char *data,
unsigned long start, unsigned long size)
{
unsigned char buffer[4];
unsigned long index;
buffer[3] = 0;
memset(palette, 0, sizeof(unsigned long) * 256);
for(index = start; index < (start + size); index++){
buffer[0] = (data[2] << 2);
buffer[1] = (data[1] << 2);
buffer[2] = (data[0] << 2);
data += 3;
palette[index] = *(unsigned long *)buffer;
}
}
void extractbitmap(FILE *bmp, unsigned char *buffer,
VNMSPRITE *spr, BITMAPINFOHDR *bmpinfo, long rounding)
{
unsigned char *line = (buffer + spr->offset + bmpinfo->image_size);
char zerobuffer[4] = { 0 };
while(line > buffer + spr->offset){
line -= spr->width;
fwrite(line, 1, spr->width, bmp);
if(rounding)
fwrite(zerobuffer, 1, rounding, bmp);
}
}
void extractsprite(FILE *bmp, unsigned char *buffer,
VNMSPRITE *spr, BITMAPINFOHDR *bmpinfo, long rounding, int transparent)
{
unsigned long *index = (unsigned long *)(buffer + spr->offset);
unsigned char *row;
char zerobuffer[4] = { 0 };
int y, j, pixel, count, width, escape;
escape = (0x100 - spr->width);
for(y = (spr->height - 1); y >= 0; y--){
row = (buffer + index[y]);
j = width = spr->width;
while(j > 0){
pixel = *row++;
if(pixel >= escape){
count = (0x100 - pixel);
pixel = transparent;
row++; // whats this byte for?
while(count-- && j--)
fputc(pixel, bmp);
}else if(j == width && pixel < escape){
width++;
}else{
fputc(pixel, bmp);
j--;
}
}
if(rounding)
fwrite(zerobuffer, 1, rounding, bmp);
}
}
void initbmpheaders(BITMAPFILEHDR *filehdr, BITMAPINFOHDR *infohdr)
{
memset(filehdr, 0, sizeof(BITMAPFILEHDR));
memset(infohdr, 0, sizeof(BITMAPINFOHDR));
infohdr->size = sizeof(BITMAPINFOHDR);
infohdr->planes = 1;
infohdr->bitcount = 8; // BI_8_BIT
infohdr->compression = 0; // BI_RGB
filehdr->type = 'MB';
filehdr->offset = sizeof(BITMAPFILEHDR) +
infohdr->size + (sizeof(unsigned long) * 256);
}
int main(int argc, char *argv[])
{
unsigned long palette[256], *index;
unsigned char *buffer;
BITMAPFILEHDR bmpfile;
BITMAPINFOHDR bmpinfo;
VNMHEADER *hdr;
VNMSPRITE *spr;
FILE *vnm, *bmp;
long size, i, rounding;
char name[32];
vnm = fopen(argv[1], "rb");
if(!vnm){
perror(argv[1]);
exit(1);
}
fseek(vnm, 0, SEEK_END);
size = ftell(vnm);
fseek(vnm, 0, SEEK_SET);
buffer = (unsigned char *)malloc(size);
if(!buffer){
perror("malloc filesize");
exit(1);
}
fread(buffer, 1, size, vnm);
fclose(vnm);
hdr = (VNMHEADER *)buffer;
if(hdr->signature != 0x564E4D1A && hdr->signature != 0x1A4D4E56){
perror("invalid vnm signature");
free(buffer);
exit(1);
}
extractpalette(palette, buffer + hdr->paletteoffset, hdr->palettestart, hdr->palettesize);
initbmpheaders(&bmpfile, &bmpinfo);
index = (unsigned long *)(buffer + hdr->spriteoffset);
for(i = 0; i < hdr->spritecount; i++){ //
spr = (VNMSPRITE *)(buffer + index[i]);
printf("spr %#3d: %c(%#3d,%#3d)-(%#3d,%#3d)\n", i, ((spr->type) ? 'S':'B'),
spr->x, spr->y, spr->width, spr->height);
rounding = (spr->width % 4);
if(rounding > 0) rounding = (4 - rounding);
bmpinfo.width = spr->width;
bmpinfo.height = spr->height;
bmpinfo.image_size = ((spr->width + rounding) * spr->height);
bmpfile.size = (bmpfile.offset + bmpinfo.image_size);
sprintf(name, "output\\%03d.bmp", i);
bmp = fopen(name, "wb");
if(!bmp){
sprintf(name, "error opening %03d.bmp", i);
perror(name);
exit(1);
}
fwrite(&bmpfile, sizeof(bmpfile), 1, bmp);
fwrite(&bmpinfo, sizeof(bmpinfo), 1, bmp);
fwrite(palette, sizeof(palette), 1, bmp);
if(spr->type)
extractsprite(bmp, buffer, spr, &bmpinfo, rounding, 189); // 187
else
extractbitmap(bmp, buffer, spr, &bmpinfo, rounding);
fclose(bmp);
}
free(buffer);
return 0;
}
Credits
This file format was reverse engineered by Napalm.