Paranoia2/utils/makewad/lmptex.cpp
2020-08-31 19:50:41 +03:00

155 lines
4.4 KiB
C++

/*
lmptex.cpp - prepare and store lmptex into the wad
Copyright (C) 2018 Uncle Mike
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
*/
#include "conprint.h"
#include <windows.h>
#include <direct.h>
#include <fcntl.h>
#include <stdio.h>
#include <math.h>
#include <io.h>
#include "cmdlib.h"
#include "stringlib.h"
#include "filesystem.h"
#include "imagelib.h"
#include "makewad.h"
#include "miptex.h"
bool LMP_WriteLmptex( const char *lumpname, rgbdata_t *pix, bool todisk )
{
bool result;
lmp_t *lmp;
// check for all the possible problems
if( !pix || !FBitSet( pix->flags, IMAGE_QUANTIZED ))
return false;
// lmp may have any dimensions
if( pix->width < IMAGE_MINWIDTH || pix->width > IMAGE_MAXWIDTH || pix->height < IMAGE_MINHEIGHT || pix->height > IMAGE_MAXHEIGHT )
return false; // to small or too large
// calculate gamma corrected linear palette
for( int i = 0; i < 256; i++ )
{
// setup palette
lbmpalette[i*3+0] = pix->palette[i*4+0];
lbmpalette[i*3+1] = pix->palette[i*4+1];
lbmpalette[i*3+2] = pix->palette[i*4+2];
}
size_t pixels = pix->width * pix->height;
size_t lumpsize = sizeof( lmp_t ) + pixels + sizeof( short ) + 768;
byte *lumpbuffer, *lump_p;
// all the lumps must be aligned by 4
// or Wally will stop working properly
lumpsize = (lumpsize + 3) & ~3;
lumpbuffer = lump_p = (byte *)Mem_Alloc( lumpsize );
lmp = (lmp_t *)lumpbuffer;
// fill the header
lmp->width = pix->width;
lmp->height = pix->height;
lump_p += sizeof( lmp_t );
// write lmptex
memcpy( lump_p, pix->buffer, pixels );
lump_p += pixels;
// write out palette
*(unsigned short *)lump_p = 256; // palette size
lump_p += sizeof( short );
memcpy( lump_p, lbmpalette, 768 );
lump_p += 768;
size_t disksize = (( lump_p - lumpbuffer ) + 3) & ~3;
if( lumpsize != disksize )
MsgDev( D_ERROR, "%s is corrupted (buffer is %s bytes, written %s)\n", lumpname, Q_memprint( lumpsize ), Q_memprint( disksize ));
if( todisk ) result = COM_SaveFile( lumpname, lumpbuffer, lumpsize );
else result = W_SaveLump( output_wad, lumpname, lumpbuffer, lumpsize, TYP_GFXPIC, ATTR_NONE ) >= 0;
Mem_Free( lumpbuffer );
return result;
}
bool LMP_CheckForReplace( dlumpinfo_t *find, rgbdata_t *image, int &width, int &height )
{
// NOTE: we can replace this lump but this is unsafe
if( find != NULL )
{
size_t lumpsize = ((sizeof( lmp_t ) + ( width * height ) + sizeof( short ) + 768) + 3) & ~3;
switch( GetReplaceLevel( ))
{
case REP_IGNORE:
MsgDev( D_ERROR, "LMP_CreateLmptex: %s already exist\n", find->name );
if( image ) Mem_Free( image );
return false;
case REP_NORMAL:
if( FBitSet( find->attribs, ATTR_READONLY ))
{
// g-cont. i left this limitation as a protect of the replacement of compressed lumps
MsgDev( D_ERROR, "W_ReplaceLump: %s is read-only\n", find->name );
if( image ) Mem_Free( image );
return false;
}
if( lumpsize != find->size )
{
MsgDev( D_ERROR, "W_ReplaceLump: %s.lmp [%s] should be [%s]\n",
find->name, Q_memprint( lumpsize ), Q_memprint( find->size ));
if( image ) Mem_Free( image );
return false;
}
break;
case REP_FORCE:
if( lumpsize != find->size )
{
size_t oldpos;
lmp_t test;
oldpos = tell( W_GetHandle( output_wad ) ); // don't forget restore original position
if( lseek( W_GetHandle( output_wad ), find->filepos, SEEK_SET ) == -1 )
{
MsgDev( D_ERROR, "W_ReplaceLump: %s is corrupted\n", find->name );
lseek( W_GetHandle( output_wad ), oldpos, SEEK_SET );
if( image ) Mem_Free( image );
return false;
}
if( read( W_GetHandle( output_wad ), &test, sizeof( test )) != sizeof( test ))
{
MsgDev( D_ERROR, "W_ReplaceLump: %s is corrupted\n", find->name );
lseek( W_GetHandle( output_wad ), oldpos, SEEK_SET );
if( image ) Mem_Free( image );
return false;
}
// get new sizes from the saved lump to resample current
lseek( W_GetHandle( output_wad ), oldpos, SEEK_SET );
height = test.height;
width = test.width;
}
break;
}
}
return true;
}