mirror of
https://github.com/ZDoom/qzdoom-gpl.git
synced 2024-12-14 22:21:32 +00:00
226a513e6e
SVN r2228 (trunk)
397 lines
10 KiB
C++
397 lines
10 KiB
C++
/*
|
|
** buildtexture.cpp
|
|
** Handling Build textures
|
|
**
|
|
**---------------------------------------------------------------------------
|
|
** Copyright 2004-2006 Randy Heit
|
|
** All rights reserved.
|
|
**
|
|
** Redistribution and use in source and binary forms, with or without
|
|
** modification, are permitted provided that the following conditions
|
|
** are met:
|
|
**
|
|
** 1. Redistributions of source code must retain the above copyright
|
|
** notice, this list of conditions and the following disclaimer.
|
|
** 2. Redistributions in binary form must reproduce the above copyright
|
|
** notice, this list of conditions and the following disclaimer in the
|
|
** documentation and/or other materials provided with the distribution.
|
|
** 3. The name of the author may not be used to endorse or promote products
|
|
** derived from this software without specific prior written permission.
|
|
**
|
|
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
|
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
**---------------------------------------------------------------------------
|
|
**
|
|
**
|
|
*/
|
|
|
|
#include "doomtype.h"
|
|
#include "files.h"
|
|
#include "r_local.h"
|
|
#include "w_wad.h"
|
|
#include "templates.h"
|
|
#include "cmdlib.h"
|
|
#include "st_start.h"
|
|
|
|
static TArray<BYTE *> BuildTileFiles;
|
|
|
|
//==========================================================================
|
|
//
|
|
// A texture defined in a Build TILESxxx.ART file
|
|
//
|
|
//==========================================================================
|
|
|
|
class FBuildTexture : public FTexture
|
|
{
|
|
public:
|
|
FBuildTexture (int tilenum, const BYTE *pixels, int width, int height, int left, int top);
|
|
~FBuildTexture ();
|
|
|
|
const BYTE *GetColumn (unsigned int column, const Span **spans_out);
|
|
const BYTE *GetPixels ();
|
|
void Unload ();
|
|
|
|
protected:
|
|
const BYTE *Pixels;
|
|
Span **Spans;
|
|
};
|
|
|
|
|
|
//==========================================================================
|
|
//
|
|
//
|
|
//
|
|
//==========================================================================
|
|
|
|
FBuildTexture::FBuildTexture (int tilenum, const BYTE *pixels, int width, int height, int left, int top)
|
|
: Pixels (pixels), Spans (NULL)
|
|
{
|
|
Width = width;
|
|
Height = height;
|
|
LeftOffset = left;
|
|
TopOffset = top;
|
|
CalcBitSize ();
|
|
mysnprintf (Name, countof(Name), "BTIL%04d", tilenum);
|
|
UseType = TEX_Build;
|
|
}
|
|
|
|
//==========================================================================
|
|
//
|
|
//
|
|
//
|
|
//==========================================================================
|
|
|
|
FBuildTexture::~FBuildTexture ()
|
|
{
|
|
if (Spans != NULL)
|
|
{
|
|
FreeSpans (Spans);
|
|
Spans = NULL;
|
|
}
|
|
}
|
|
|
|
//==========================================================================
|
|
//
|
|
//
|
|
//
|
|
//==========================================================================
|
|
|
|
void FBuildTexture::Unload ()
|
|
{
|
|
// Nothing to do, since the pixels are accessed from memory-mapped files directly
|
|
}
|
|
|
|
//==========================================================================
|
|
//
|
|
//
|
|
//
|
|
//==========================================================================
|
|
|
|
const BYTE *FBuildTexture::GetPixels ()
|
|
{
|
|
return Pixels;
|
|
}
|
|
|
|
//==========================================================================
|
|
//
|
|
//
|
|
//
|
|
//==========================================================================
|
|
|
|
const BYTE *FBuildTexture::GetColumn (unsigned int column, const Span **spans_out)
|
|
{
|
|
if (column >= Width)
|
|
{
|
|
if (WidthMask + 1 == Width)
|
|
{
|
|
column &= WidthMask;
|
|
}
|
|
else
|
|
{
|
|
column %= Width;
|
|
}
|
|
}
|
|
if (spans_out != NULL)
|
|
{
|
|
if (Spans == NULL)
|
|
{
|
|
Spans = CreateSpans (Pixels);
|
|
}
|
|
*spans_out = Spans[column];
|
|
}
|
|
return Pixels + column*Height;
|
|
}
|
|
|
|
//===========================================================================
|
|
//
|
|
// AddTiles
|
|
//
|
|
// Adds all the tiles in an artfile to the texture manager.
|
|
//
|
|
//===========================================================================
|
|
|
|
void AddTiles (void *tiles)
|
|
{
|
|
// int numtiles = LittleLong(((DWORD *)tiles)[1]); // This value is not reliable
|
|
int tilestart = LittleLong(((DWORD *)tiles)[2]);
|
|
int tileend = LittleLong(((DWORD *)tiles)[3]);
|
|
const WORD *tilesizx = &((const WORD *)tiles)[8];
|
|
const WORD *tilesizy = &tilesizx[tileend - tilestart + 1];
|
|
const DWORD *picanm = (const DWORD *)&tilesizy[tileend - tilestart + 1];
|
|
BYTE *tiledata = (BYTE *)&picanm[tileend - tilestart + 1];
|
|
|
|
for (int i = tilestart; i <= tileend; ++i)
|
|
{
|
|
int pic = i - tilestart;
|
|
int width = LittleShort(tilesizx[pic]);
|
|
int height = LittleShort(tilesizy[pic]);
|
|
DWORD anm = LittleLong(picanm[pic]);
|
|
int xoffs = (SBYTE)((anm >> 8) & 255) + width/2;
|
|
int yoffs = (SBYTE)((anm >> 16) & 255) + height/2;
|
|
int size = width*height;
|
|
FTextureID texnum;
|
|
FTexture *tex;
|
|
|
|
if (width <= 0 || height <= 0) continue;
|
|
|
|
tex = new FBuildTexture (i, tiledata, width, height, xoffs, yoffs);
|
|
texnum = TexMan.AddTexture (tex);
|
|
while (size > 0)
|
|
{
|
|
*tiledata = 255 - *tiledata;
|
|
tiledata++;
|
|
size--;
|
|
}
|
|
StartScreen->Progress();
|
|
|
|
if ((picanm[pic] & 63) && (picanm[pic] & 192))
|
|
{
|
|
int type, speed;
|
|
|
|
switch (picanm[pic] & 192)
|
|
{
|
|
case 64: type = 2; break;
|
|
case 128: type = 0; break;
|
|
case 192: type = 1; break;
|
|
default: type = 0; break; // Won't happen, but GCC bugs me if I don't put this here.
|
|
}
|
|
|
|
speed = (anm >> 24) & 15;
|
|
speed = MAX (1, (1 << speed) * 1000 / 120); // Convert from 120 Hz to 1000 Hz.
|
|
|
|
R_AddSimpleAnim (texnum, picanm[pic] & 63, type, speed);
|
|
}
|
|
|
|
// Blood's rotation types:
|
|
// 0 - Single
|
|
// 1 - 5 Full
|
|
// 2 - 8 Full
|
|
// 3 - Bounce (looks no different from Single; seems to signal bouncy sprites)
|
|
// 4 - 5 Half (not used in game)
|
|
// 5 - 3 Flat (not used in game)
|
|
// 6 - Voxel
|
|
// 7 - Spin Voxel
|
|
|
|
int rotType = (anm >> 28) & 7;
|
|
if (rotType == 1)
|
|
{
|
|
spriteframe_t rot;
|
|
rot.Texture[0] =
|
|
rot.Texture[1] = texnum;
|
|
for (int j = 1; j < 4; ++j)
|
|
{
|
|
rot.Texture[j*2] =
|
|
rot.Texture[j*2+1] =
|
|
rot.Texture[16-j*2] =
|
|
rot.Texture[17-j*2] = texnum.GetIndex() + j;
|
|
}
|
|
rot.Texture[8] =
|
|
rot.Texture[9] = texnum.GetIndex() + 4;
|
|
rot.Flip = 0x00FC;
|
|
tex->Rotations = SpriteFrames.Push (rot);
|
|
}
|
|
else if (rotType == 2)
|
|
{
|
|
spriteframe_t rot;
|
|
rot.Texture[0] =
|
|
rot.Texture[1] = texnum;
|
|
for (int j = 1; j < 8; ++j)
|
|
{
|
|
rot.Texture[16-j*2] =
|
|
rot.Texture[17-j*2] = texnum.GetIndex() + j;
|
|
}
|
|
rot.Flip = 0;
|
|
tex->Rotations = SpriteFrames.Push (rot);
|
|
}
|
|
}
|
|
}
|
|
|
|
//===========================================================================
|
|
//
|
|
// CountTiles
|
|
//
|
|
// Returns the number of tiles provided by an artfile
|
|
//
|
|
//===========================================================================
|
|
|
|
static int CountTiles (void *tiles)
|
|
{
|
|
int version = LittleLong(*(DWORD *)tiles);
|
|
if (version != 1)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
int tilestart = LittleLong(((DWORD *)tiles)[2]);
|
|
int tileend = LittleLong(((DWORD *)tiles)[3]);
|
|
|
|
return tileend >= tilestart ? tileend - tilestart + 1 : 0;
|
|
}
|
|
|
|
//===========================================================================
|
|
//
|
|
// R_CountBuildTiles
|
|
//
|
|
// Returns the number of tiles found. Also loads all the data for
|
|
// R_InitBuildTiles() to process later.
|
|
//
|
|
//===========================================================================
|
|
|
|
int R_CountBuildTiles ()
|
|
{
|
|
int numartfiles = 0;
|
|
char artfile[] = "tilesXXX.art";
|
|
int lumpnum;
|
|
int numtiles;
|
|
int totaltiles = 0;
|
|
|
|
lumpnum = Wads.CheckNumForFullName ("blood.pal");
|
|
if (lumpnum >= 0)
|
|
{
|
|
// Blood's tiles are external resources. (Why did they do it like that?)
|
|
FString rffpath = Wads.GetWadFullName (Wads.GetLumpFile (lumpnum));
|
|
int slashat = rffpath.LastIndexOf ('/');
|
|
if (slashat >= 0)
|
|
{
|
|
rffpath.Truncate (slashat + 1);
|
|
}
|
|
else
|
|
{
|
|
rffpath += '/';
|
|
}
|
|
|
|
for (; numartfiles < 1000; numartfiles++)
|
|
{
|
|
artfile[5] = numartfiles / 100 + '0';
|
|
artfile[6] = numartfiles / 10 % 10 + '0';
|
|
artfile[7] = numartfiles % 10 + '0';
|
|
|
|
FString artpath = rffpath;
|
|
artpath += artfile;
|
|
|
|
FILE *f = fopen (artpath, "rb");
|
|
if (f == NULL)
|
|
{
|
|
break;
|
|
}
|
|
|
|
size_t len = Q_filelength (f);
|
|
BYTE *art = new BYTE[len];
|
|
if (fread (art, 1, len, f) != len || (numtiles = CountTiles(art)) == 0)
|
|
{
|
|
delete[] art;
|
|
}
|
|
else
|
|
{
|
|
BuildTileFiles.Push (art);
|
|
totaltiles += numtiles;
|
|
}
|
|
fclose (f);
|
|
}
|
|
}
|
|
|
|
for (; numartfiles < 1000; numartfiles++)
|
|
{
|
|
artfile[5] = numartfiles / 100 + '0';
|
|
artfile[6] = numartfiles / 10 % 10 + '0';
|
|
artfile[7] = numartfiles % 10 + '0';
|
|
lumpnum = Wads.CheckNumForFullName (artfile);
|
|
if (lumpnum < 0)
|
|
{
|
|
break;
|
|
}
|
|
|
|
BYTE *art = new BYTE[Wads.LumpLength (lumpnum)];
|
|
Wads.ReadLump (lumpnum, art);
|
|
|
|
if ((numtiles = CountTiles(art)) == 0)
|
|
{
|
|
delete[] art;
|
|
}
|
|
else
|
|
{
|
|
BuildTileFiles.Push (art);
|
|
totaltiles += numtiles;
|
|
}
|
|
}
|
|
return totaltiles;
|
|
}
|
|
|
|
//===========================================================================
|
|
//
|
|
// R_InitBuildTiles
|
|
//
|
|
// [RH] Support Build tiles!
|
|
//
|
|
//===========================================================================
|
|
|
|
void R_InitBuildTiles ()
|
|
{
|
|
for (unsigned int i = 0; i < BuildTileFiles.Size(); ++i)
|
|
{
|
|
AddTiles (BuildTileFiles[i]);
|
|
}
|
|
}
|
|
|
|
//===========================================================================
|
|
//
|
|
// R_DeinitBuildTiles
|
|
//
|
|
//===========================================================================
|
|
|
|
void R_DeinitBuildTiles ()
|
|
{
|
|
for (unsigned int i = 0; i < BuildTileFiles.Size(); ++i)
|
|
{
|
|
delete[] BuildTileFiles[i];
|
|
}
|
|
BuildTileFiles.Clear();
|
|
}
|