mirror of
https://github.com/DrBeef/Raze.git
synced 2024-11-23 12:32:21 +00:00
84173ee09b
The main bulk of this is the new start screen code. To make this work in Raze some more work on the startup procedure is needed. What this does provide is support for the DOS end-of-game text screens in Duke and SW on non-Windows systems.
381 lines
12 KiB
C++
381 lines
12 KiB
C++
|
|
/*
|
|
** startuptexture.cpp
|
|
** Texture class for Hexen's startup screen
|
|
**
|
|
**---------------------------------------------------------------------------
|
|
** Copyright 2022 Christoph Oelckers
|
|
** 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 "files.h"
|
|
#include "filesystem.h"
|
|
#include "bitmap.h"
|
|
#include "imagehelpers.h"
|
|
#include "image.h"
|
|
|
|
#define ST_NOTCH_WIDTH 16
|
|
#define ST_NOTCH_HEIGHT 23
|
|
|
|
#define ST_NETNOTCH_WIDTH 4
|
|
#define ST_NETNOTCH_HEIGHT 16
|
|
|
|
struct StrifeStartupInfo
|
|
{
|
|
char name[9];
|
|
uint8_t width, height;
|
|
};
|
|
|
|
static StrifeStartupInfo StrifeRawPics[] =
|
|
{
|
|
{ "STRTPA1", 32, 64},
|
|
{ "STRTPB1", 32, 64},
|
|
{ "STRTPC1", 32, 64},
|
|
{ "STRTPD1", 32, 64},
|
|
{ "STRTLZ1", 16, 16},
|
|
{ "STRTLZ2", 16, 16},
|
|
{ "STRTBOT", 48, 48}
|
|
};
|
|
|
|
// there is only one palette for all these images.
|
|
static uint8_t startuppalette8[16];
|
|
static uint32_t startuppalette32[16];
|
|
|
|
//==========================================================================
|
|
//
|
|
//
|
|
//
|
|
//==========================================================================
|
|
|
|
class FStartupTexture : public FImageSource
|
|
{
|
|
public:
|
|
FStartupTexture (int lumpnum);
|
|
TArray<uint8_t> CreatePalettedPixels(int conversion) override;
|
|
int CopyPixels(FBitmap *bmp, int conversion) override;
|
|
};
|
|
|
|
class FNotchTexture : public FImageSource
|
|
{
|
|
public:
|
|
FNotchTexture (int lumpnum, int width, int height);
|
|
TArray<uint8_t> CreatePalettedPixels(int conversion) override;
|
|
int CopyPixels(FBitmap *bmp, int conversion) override;
|
|
};
|
|
|
|
class FStrifeStartupTexture : public FImageSource
|
|
{
|
|
public:
|
|
FStrifeStartupTexture (int lumpnum, int w, int h);
|
|
TArray<uint8_t> CreatePalettedPixels(int conversion) override;
|
|
};
|
|
|
|
class FStrifeStartupBackground : public FImageSource
|
|
{
|
|
public:
|
|
FStrifeStartupBackground (int lumpnum);
|
|
TArray<uint8_t> CreatePalettedPixels(int conversion) override;
|
|
};
|
|
|
|
//==========================================================================
|
|
//
|
|
// Use the same function as raw textures to eliminate Doom patches
|
|
//
|
|
//==========================================================================
|
|
|
|
bool CheckIfRaw(FileReader & data, int desiredsize);
|
|
|
|
//==========================================================================
|
|
//
|
|
// loads all raw images for Hexen's and Strife's startup screens
|
|
//
|
|
//==========================================================================
|
|
|
|
FImageSource *StartupPageImage_TryCreate(FileReader & file, int lumpnum)
|
|
{
|
|
if (fileSystem.CheckFileName(lumpnum, "STARTUP"))
|
|
{
|
|
if (!CheckIfRaw(file, 153648)) return nullptr;
|
|
return new FStartupTexture(lumpnum);
|
|
}
|
|
if (fileSystem.CheckFileName(lumpnum, "NOTCH"))
|
|
{
|
|
if (!CheckIfRaw(file, ST_NOTCH_WIDTH * ST_NOTCH_HEIGHT / 2)) return nullptr;
|
|
return new FNotchTexture(lumpnum, ST_NOTCH_WIDTH, ST_NOTCH_HEIGHT);
|
|
}
|
|
if (fileSystem.CheckFileName(lumpnum, "NETNOTCH"))
|
|
{
|
|
if (!CheckIfRaw(file, ST_NETNOTCH_WIDTH * ST_NETNOTCH_HEIGHT / 2)) return nullptr;
|
|
return new FNotchTexture(lumpnum, ST_NETNOTCH_WIDTH, ST_NETNOTCH_HEIGHT);
|
|
}
|
|
if (fileSystem.CheckFileName(lumpnum, "STARTUP0"))
|
|
{
|
|
if (!CheckIfRaw(file, 64000)) return nullptr;
|
|
return new FStrifeStartupBackground(lumpnum);
|
|
}
|
|
for(auto& sst : StrifeRawPics)
|
|
{
|
|
if (fileSystem.CheckFileName(lumpnum, sst.name))
|
|
{
|
|
if (!CheckIfRaw(file, sst.width * sst.height)) return nullptr;
|
|
return new FStrifeStartupTexture(lumpnum, sst.width, sst.height);
|
|
}
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
|
|
//==========================================================================
|
|
//
|
|
//
|
|
//
|
|
//==========================================================================
|
|
|
|
FStartupTexture::FStartupTexture (int lumpnum)
|
|
: FImageSource(lumpnum)
|
|
{
|
|
Width = 640;
|
|
Height = 480;
|
|
bUseGamePalette = false;
|
|
|
|
FileData lump = fileSystem.ReadFile (SourceLump);
|
|
const uint8_t *source = (const uint8_t *)lump.GetMem();
|
|
|
|
// Initialize the bitmap palette.
|
|
// the palette is static so that the notches can share it.
|
|
// Note that if the STARTUP image gets replaced, the notches will be all black unless they get replaced as well!
|
|
for (int i = 0; i < 16; ++i)
|
|
{
|
|
PalEntry pe;
|
|
pe.r = source[i * 3 + 0];
|
|
pe.g = source[i * 3 + 1];
|
|
pe.b = source[i * 3 + 2];
|
|
pe.a = 63;
|
|
// Convert from 6-bit per component to 8-bit per component.
|
|
pe.d= (pe.d << 2) | ((pe.d >> 4) & 0x03030303);
|
|
startuppalette8[i] = ColorMatcher.Pick(pe);
|
|
startuppalette32[i] = pe;
|
|
}
|
|
}
|
|
|
|
//==========================================================================
|
|
//
|
|
// PlanarToChunky
|
|
//
|
|
// Convert a 4-bpp planar image to chunky pixels.
|
|
//
|
|
//==========================================================================
|
|
|
|
template<class T>
|
|
void PlanarToChunky(T* dest, const uint8_t* src, const T* remap, int width, int height)
|
|
{
|
|
int y, x;
|
|
const uint8_t* src1, * src2, * src3, * src4;
|
|
size_t plane_size = width / 8 * height;
|
|
|
|
src1 = src;
|
|
src2 = src1 + plane_size;
|
|
src3 = src2 + plane_size;
|
|
src4 = src3 + plane_size;
|
|
|
|
for (y = height; y > 0; --y)
|
|
{
|
|
for (x = width; x > 0; x -= 8)
|
|
{
|
|
dest[0] = remap[((*src4 & 0x80) | ((*src3 & 0x80) >> 1) | ((*src2 & 0x80) >> 2) | ((*src1 & 0x80) >> 3)) >> 4];
|
|
dest[1] = remap[((*src4 & 0x40) >> 3) | ((*src3 & 0x40) >> 4) | ((*src2 & 0x40) >> 5) | ((*src1 & 0x40) >> 6)];
|
|
dest[2] = remap[(((*src4 & 0x20) << 2) | ((*src3 & 0x20) << 1) | ((*src2 & 0x20)) | ((*src1 & 0x20) >> 1)) >> 4];
|
|
dest[3] = remap[((*src4 & 0x10) >> 1) | ((*src3 & 0x10) >> 2) | ((*src2 & 0x10) >> 3) | ((*src1 & 0x10) >> 4)];
|
|
dest[4] = remap[(((*src4 & 0x08) << 4) | ((*src3 & 0x08) << 3) | ((*src2 & 0x08) << 2) | ((*src1 & 0x08) << 1)) >> 4];
|
|
dest[5] = remap[((*src4 & 0x04) << 1) | ((*src3 & 0x04)) | ((*src2 & 0x04) >> 1) | ((*src1 & 0x04) >> 2)];
|
|
dest[6] = remap[(((*src4 & 0x02) << 6) | ((*src3 & 0x02) << 5) | ((*src2 & 0x02) << 4) | ((*src1 & 0x02) << 3)) >> 4];
|
|
dest[7] = remap[((*src4 & 0x01) << 3) | ((*src3 & 0x01) << 2) | ((*src2 & 0x01) << 1) | ((*src1 & 0x01))];
|
|
dest += 8;
|
|
src1 += 1;
|
|
src2 += 1;
|
|
src3 += 1;
|
|
src4 += 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
//==========================================================================
|
|
//
|
|
//
|
|
//
|
|
//==========================================================================
|
|
|
|
TArray<uint8_t> FStartupTexture::CreatePalettedPixels(int conversion)
|
|
{
|
|
FileData lump = fileSystem.ReadFile (SourceLump);
|
|
const uint8_t *source = (const uint8_t *)lump.GetMem();
|
|
const uint8_t *remap = ImageHelpers::GetRemap(conversion == luminance);
|
|
|
|
|
|
TArray<uint8_t> Work(Width*Height, true);
|
|
TArray<uint8_t> Pixels(Width*Height, true);
|
|
PlanarToChunky(Work.Data(), source + 48, startuppalette8, Width, Height);
|
|
ImageHelpers::FlipNonSquareBlockRemap(Pixels.Data(), Work.Data(), Width, Height, Width, remap);
|
|
return Pixels;
|
|
}
|
|
|
|
//==========================================================================
|
|
//
|
|
//
|
|
//
|
|
//==========================================================================
|
|
|
|
int FStartupTexture::CopyPixels(FBitmap *bmp, int conversion)
|
|
{
|
|
FileData lump = fileSystem.ReadFile (SourceLump);
|
|
const uint8_t *source = (const uint8_t *)lump.GetMem();
|
|
PlanarToChunky((uint32_t*)bmp->GetPixels(), source + 48, startuppalette32, Width, Height);
|
|
return 0;
|
|
}
|
|
|
|
//==========================================================================
|
|
//
|
|
//
|
|
//
|
|
//==========================================================================
|
|
|
|
FNotchTexture::FNotchTexture (int lumpnum, int width, int height)
|
|
: FImageSource(lumpnum)
|
|
{
|
|
Width = width;
|
|
Height = height;
|
|
bUseGamePalette = false;
|
|
}
|
|
|
|
//==========================================================================
|
|
//
|
|
//
|
|
//
|
|
//==========================================================================
|
|
|
|
TArray<uint8_t> FNotchTexture::CreatePalettedPixels(int conversion)
|
|
{
|
|
FileData lump = fileSystem.ReadFile (SourceLump);
|
|
const uint8_t *source = (const uint8_t *)lump.GetMem();
|
|
const uint8_t *remap = ImageHelpers::GetRemap(conversion == luminance);
|
|
|
|
TArray<uint8_t> Work(Width*Height, true);
|
|
TArray<uint8_t> Pixels(Width*Height, true);
|
|
for(int i=0; i * Width * Height / 2; i++)
|
|
{
|
|
Work[i * 2] = startuppalette8[source[i] >> 4];
|
|
Work[i * 2 + 1] = startuppalette8[source[i] & 15];
|
|
}
|
|
ImageHelpers::FlipNonSquareBlockRemap(Pixels.Data(), Work.Data(), Width, Height, Width, remap);
|
|
return Pixels;
|
|
}
|
|
|
|
//==========================================================================
|
|
//
|
|
//
|
|
//
|
|
//==========================================================================
|
|
|
|
int FNotchTexture::CopyPixels(FBitmap *bmp, int conversion)
|
|
{
|
|
FileData lump = fileSystem.ReadFile (SourceLump);
|
|
const uint8_t *source = (const uint8_t *)lump.GetMem();
|
|
|
|
auto Work = (uint32_t*)bmp->GetPixels();
|
|
for(int i = 0; i < Width * Height / 2; i++)
|
|
{
|
|
Work[i * 2] = startuppalette32[source[i] >> 4];
|
|
Work[i * 2 + 1] = startuppalette32[source[i] & 15];
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
//==========================================================================
|
|
//
|
|
//
|
|
//
|
|
//==========================================================================
|
|
|
|
FStrifeStartupTexture::FStrifeStartupTexture (int lumpnum, int w, int h)
|
|
: FImageSource(lumpnum)
|
|
{
|
|
Width = w;
|
|
Height = h;
|
|
}
|
|
|
|
//==========================================================================
|
|
//
|
|
//
|
|
//
|
|
//==========================================================================
|
|
|
|
TArray<uint8_t> FStrifeStartupTexture::CreatePalettedPixels(int conversion)
|
|
{
|
|
FileData lump = fileSystem.ReadFile (SourceLump);
|
|
const uint8_t *source = (const uint8_t *)lump.GetMem();
|
|
TArray<uint8_t> Pixels(Width*Height, true);
|
|
const uint8_t *remap = ImageHelpers::GetRemap(conversion == luminance);
|
|
ImageHelpers::FlipNonSquareBlockRemap(Pixels.Data(), source, Width, Height, Width, remap);
|
|
return Pixels;
|
|
}
|
|
|
|
//==========================================================================
|
|
//
|
|
//
|
|
//
|
|
//==========================================================================
|
|
|
|
FStrifeStartupBackground::FStrifeStartupBackground (int lumpnum)
|
|
: FImageSource(lumpnum)
|
|
{
|
|
Width = 320;
|
|
Height = 200;
|
|
}
|
|
|
|
//==========================================================================
|
|
//
|
|
// this image is very messy but let's prepare it just like Strife does
|
|
// so that the screen can be replaced with a whole image.
|
|
//
|
|
//==========================================================================
|
|
|
|
TArray<uint8_t> FStrifeStartupBackground::CreatePalettedPixels(int conversion)
|
|
{
|
|
TArray<uint8_t> source(64000, true);
|
|
memset(source.Data(), 0xF0, 64000);
|
|
auto lumpr = fileSystem.OpenFileReader(SourceLump);
|
|
lumpr.Seek(57 * 320, FileReader::SeekSet);
|
|
lumpr.Read(source.Data() + 41 * 320, 95 * 320);
|
|
|
|
TArray<uint8_t> Pixels(Width*Height, true);
|
|
const uint8_t *remap = ImageHelpers::GetRemap(conversion == luminance);
|
|
ImageHelpers::FlipNonSquareBlockRemap(Pixels.Data(), source.Data(), Width, Height, Width, remap);
|
|
return Pixels;
|
|
}
|