mirror of
https://github.com/fabiangreffrath/woof.git
synced 2025-09-22 11:22:18 -04:00
implement support for DBIGFONT lump in FON2 format (#1575)
* add SLADE copyright * adapt V_LinearToTransPatch from Eternity Engine This will be useful for PNG support. * nit-pick: sort copyright holders in README.md --------- Co-authored-by: Fabian Greffrath <fabian@greffrath.com>
This commit is contained in:
parent
80704d11fc
commit
5ca3c41045
@ -149,6 +149,7 @@ Copyright:
|
|||||||
© 2005-2006 by Florian Schulze, Colin Phipps, Neil Stevens, Andrey Budko;
|
© 2005-2006 by Florian Schulze, Colin Phipps, Neil Stevens, Andrey Budko;
|
||||||
© 2005-2018 Simon Howard;
|
© 2005-2018 Simon Howard;
|
||||||
© 2006 Ben Ryves;
|
© 2006 Ben Ryves;
|
||||||
|
© 2008-2019 Simon Judd;
|
||||||
© 2017 Christoph Oelckers;
|
© 2017 Christoph Oelckers;
|
||||||
© 2019 Fernando Carmona Varo;
|
© 2019 Fernando Carmona Varo;
|
||||||
© 2020 Alex Mayfield;
|
© 2020 Alex Mayfield;
|
||||||
|
@ -57,6 +57,7 @@ set(WOOF_SOURCES
|
|||||||
m_fixed.h
|
m_fixed.h
|
||||||
m_input.c m_input.h
|
m_input.c m_input.h
|
||||||
m_io.c m_io.h
|
m_io.c m_io.h
|
||||||
|
mn_font.c mn_font.h
|
||||||
mn_menu.c mn_menu.h
|
mn_menu.c mn_menu.h
|
||||||
mn_setup.c mn_setup.h
|
mn_setup.c mn_setup.h
|
||||||
m_misc.c m_misc.h
|
m_misc.c m_misc.h
|
||||||
|
223
src/mn_font.c
Normal file
223
src/mn_font.c
Normal file
@ -0,0 +1,223 @@
|
|||||||
|
//
|
||||||
|
// SLADE - It's a Doom Editor
|
||||||
|
// Copyright(C) 2008 - 2019 Simon Judd
|
||||||
|
// Copyright(C) 2024 Roman Fomin
|
||||||
|
//
|
||||||
|
// 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 2
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
// DESCRIPTION:
|
||||||
|
// Load and draw ZDoom FON2 fonts
|
||||||
|
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "doomtype.h"
|
||||||
|
#include "i_video.h"
|
||||||
|
#include "m_swap.h"
|
||||||
|
#include "r_defs.h"
|
||||||
|
#include "v_video.h"
|
||||||
|
#include "w_wad.h"
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
uint16_t width;
|
||||||
|
patch_t *patch;
|
||||||
|
} fon2_char_t;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
byte magic[4];
|
||||||
|
uint16_t charheight;
|
||||||
|
byte firstc;
|
||||||
|
byte lastc;
|
||||||
|
byte constantw;
|
||||||
|
byte shading;
|
||||||
|
byte palsize;
|
||||||
|
byte kerning; // flag field, but with only one flag
|
||||||
|
} fon2_header_t;
|
||||||
|
|
||||||
|
static fon2_char_t *chars = NULL;
|
||||||
|
static int numchars;
|
||||||
|
static int height;
|
||||||
|
static int firstc;
|
||||||
|
static int kerning;
|
||||||
|
|
||||||
|
#define FON2_SPACE 12
|
||||||
|
|
||||||
|
boolean MN_LoadFon2(const byte *gfx_data, int size)
|
||||||
|
{
|
||||||
|
if (size < (int)sizeof(fon2_header_t))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const fon2_header_t *header = (fon2_header_t *)gfx_data;
|
||||||
|
if (memcmp(header->magic, "FON2", 4))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
height = SHORT(header->charheight);
|
||||||
|
if (height == 0)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const byte *p = gfx_data + sizeof(fon2_header_t);
|
||||||
|
|
||||||
|
if (header->kerning)
|
||||||
|
{
|
||||||
|
kerning = SHORT(*(int16_t *)p);
|
||||||
|
p += 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
firstc = header->firstc;
|
||||||
|
numchars = header->lastc - header->firstc + 1;
|
||||||
|
chars = malloc(numchars * sizeof(*chars));
|
||||||
|
|
||||||
|
for (int i = 0; i < numchars; ++i)
|
||||||
|
{
|
||||||
|
chars[i].width = SHORT(*(uint16_t *)p);
|
||||||
|
// The width information is enumerated for each character only if they
|
||||||
|
// are not constant width. Regardless, move the read pointer away after
|
||||||
|
// the last.
|
||||||
|
if (!(header->constantw) || (i == numchars - 1))
|
||||||
|
{
|
||||||
|
p += 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build translation table for palette.
|
||||||
|
byte *playpal = W_CacheLumpName("PLAYPAL", PU_CACHE);
|
||||||
|
byte *translate = malloc(header->palsize + 1);
|
||||||
|
for (int i = 0; i < header->palsize + 1; ++i)
|
||||||
|
{
|
||||||
|
int r = *p++;
|
||||||
|
int g = *p++;
|
||||||
|
int b = *p++;
|
||||||
|
translate[i] = I_GetPaletteIndex(playpal, r, g, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 0 is transparent, last is border color
|
||||||
|
byte color_key = translate[0];
|
||||||
|
|
||||||
|
// The picture data follows, using the same RLE as FON1 and IMGZ.
|
||||||
|
for (int i = 0; i < numchars; ++i)
|
||||||
|
{
|
||||||
|
// A big font is not necessarily continuous; several characters
|
||||||
|
// may be skipped; they are given a width of 0.
|
||||||
|
if (!chars[i].width)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
int numpixels = chars[i].width * height;
|
||||||
|
byte *data = malloc(numpixels);
|
||||||
|
byte *d = data;
|
||||||
|
byte code = 0;
|
||||||
|
int length = 0;
|
||||||
|
|
||||||
|
while (numpixels)
|
||||||
|
{
|
||||||
|
code = *p++;
|
||||||
|
if (code < 0x80)
|
||||||
|
{
|
||||||
|
length = code + 1;
|
||||||
|
for (int k = 0; k < length; ++k)
|
||||||
|
{
|
||||||
|
d[k] = translate[p[k]];
|
||||||
|
}
|
||||||
|
d += length;
|
||||||
|
p += length;
|
||||||
|
numpixels -= length;
|
||||||
|
}
|
||||||
|
else if (code > 0x80)
|
||||||
|
{
|
||||||
|
length = 0x101 - code;
|
||||||
|
code = *p++;
|
||||||
|
memset(d, translate[code], length);
|
||||||
|
d += length;
|
||||||
|
numpixels -= length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
chars[i].patch = V_LinearToTransPatch(data, chars[i].width, height,
|
||||||
|
color_key);
|
||||||
|
free(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(translate);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean MN_DrawFon2String(int x, int y, byte *cr, const char *str)
|
||||||
|
{
|
||||||
|
if (!numchars)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int c, cx;
|
||||||
|
|
||||||
|
cx = x;
|
||||||
|
|
||||||
|
while (*str)
|
||||||
|
{
|
||||||
|
c = *str++;
|
||||||
|
|
||||||
|
c = toupper(c) - firstc;
|
||||||
|
if (c < 0 || c >= numchars)
|
||||||
|
{
|
||||||
|
cx += FON2_SPACE;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (chars[c].width)
|
||||||
|
{
|
||||||
|
V_DrawPatchTranslated(cx, y, chars[c].patch, cr);
|
||||||
|
cx += chars[c].width + kerning;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cx += FON2_SPACE + kerning;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int MN_GetFon2PixelWidth(const char *str)
|
||||||
|
{
|
||||||
|
if (!numchars)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int len = 0;
|
||||||
|
int c;
|
||||||
|
|
||||||
|
while (*str)
|
||||||
|
{
|
||||||
|
c = *str++;
|
||||||
|
|
||||||
|
c = toupper(c) - firstc;
|
||||||
|
if (c < 0 || c > numchars)
|
||||||
|
{
|
||||||
|
len += FON2_SPACE; // space
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
len += chars[c].width + kerning;
|
||||||
|
}
|
||||||
|
len -= kerning;
|
||||||
|
return len;
|
||||||
|
}
|
30
src/mn_font.h
Normal file
30
src/mn_font.h
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
//
|
||||||
|
// SLADE - It's a Doom Editor
|
||||||
|
// Copyright(C) 2008 - 2019 Simon Judd
|
||||||
|
// Copyright(C) 2024 Roman Fomin
|
||||||
|
//
|
||||||
|
// 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 2
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
// DESCRIPTION:
|
||||||
|
// Load and draw ZDoom FON2 fonts
|
||||||
|
|
||||||
|
#ifndef MN_FONT
|
||||||
|
#define MN_FONT
|
||||||
|
|
||||||
|
#include "doomtype.h"
|
||||||
|
|
||||||
|
boolean MN_LoadFon2(const byte *gfx_data, int size);
|
||||||
|
|
||||||
|
boolean MN_DrawFon2String(int x, int y, byte *cr, const char *str);
|
||||||
|
|
||||||
|
int MN_GetFon2PixelWidth(const char *str);
|
||||||
|
|
||||||
|
#endif
|
@ -44,10 +44,11 @@
|
|||||||
#include "m_input.h"
|
#include "m_input.h"
|
||||||
#include "m_io.h"
|
#include "m_io.h"
|
||||||
#include "m_misc.h"
|
#include "m_misc.h"
|
||||||
#include "mn_snapshot.h"
|
|
||||||
#include "m_swap.h"
|
#include "m_swap.h"
|
||||||
|
#include "mn_font.h"
|
||||||
#include "mn_menu.h"
|
#include "mn_menu.h"
|
||||||
#include "mn_setup.h"
|
#include "mn_setup.h"
|
||||||
|
#include "mn_snapshot.h"
|
||||||
#include "p_saveg.h"
|
#include "p_saveg.h"
|
||||||
#include "r_defs.h"
|
#include "r_defs.h"
|
||||||
#include "r_draw.h"
|
#include "r_draw.h"
|
||||||
@ -1727,8 +1728,8 @@ static menuitem_t SetupMenu[] = {
|
|||||||
// [FG] alternative text for missing menu graphics lumps
|
// [FG] alternative text for missing menu graphics lumps
|
||||||
{1, "M_GENERL", MN_General, 'g', "GENERAL", SETUP_MENU_RECT(0)},
|
{1, "M_GENERL", MN_General, 'g', "GENERAL", SETUP_MENU_RECT(0)},
|
||||||
{1, "M_KEYBND", MN_KeyBindings, 'k', "KEY BINDINGS", SETUP_MENU_RECT(1)},
|
{1, "M_KEYBND", MN_KeyBindings, 'k', "KEY BINDINGS", SETUP_MENU_RECT(1)},
|
||||||
{1, "M_COMPAT", MN_Compat, 'd', "DOOM COMPATIBILITY", SETUP_MENU_RECT(2)},
|
{1, "M_COMPAT", MN_Compat, 'c', "COMPATIBILITY", SETUP_MENU_RECT(2)},
|
||||||
{1, "M_STAT", MN_StatusBar, 's', "STATUS BAR / HUD", SETUP_MENU_RECT(3)},
|
{1, "M_STAT", MN_StatusBar, 's', "STATUS BAR/HUD", SETUP_MENU_RECT(3)},
|
||||||
{1, "M_AUTO", MN_Automap, 'a', "AUTOMAP", SETUP_MENU_RECT(4)},
|
{1, "M_AUTO", MN_Automap, 'a', "AUTOMAP", SETUP_MENU_RECT(4)},
|
||||||
{1, "M_WEAP", MN_Weapons, 'w', "WEAPONS", SETUP_MENU_RECT(5)},
|
{1, "M_WEAP", MN_Weapons, 'w', "WEAPONS", SETUP_MENU_RECT(5)},
|
||||||
{1, "M_ENEM", MN_Enemy, 'e', "ENEMIES", SETUP_MENU_RECT(6)},
|
{1, "M_ENEM", MN_Enemy, 'e', "ENEMIES", SETUP_MENU_RECT(6)},
|
||||||
@ -1871,7 +1872,7 @@ void MN_SetNextMenuAlt(ss_types type)
|
|||||||
|
|
||||||
static void M_DrawSetup(void)
|
static void M_DrawSetup(void)
|
||||||
{
|
{
|
||||||
MN_DrawTitle(124, 15, "M_OPTTTL", "OPTIONS");
|
MN_DrawTitle(108, 15, "M_OPTTTL", "OPTIONS");
|
||||||
}
|
}
|
||||||
|
|
||||||
/////////////////////////////
|
/////////////////////////////
|
||||||
@ -1936,6 +1937,12 @@ void M_Init(void)
|
|||||||
messageLastMenuActive = menuactive;
|
messageLastMenuActive = menuactive;
|
||||||
quickSaveSlot = -1;
|
quickSaveSlot = -1;
|
||||||
|
|
||||||
|
int lumpnum = W_CheckNumForName("DBIGFONT");
|
||||||
|
if (lumpnum > 0)
|
||||||
|
{
|
||||||
|
MN_LoadFon2(W_CacheLumpNum(lumpnum, PU_CACHE), W_LumpLength(lumpnum));
|
||||||
|
}
|
||||||
|
|
||||||
// Here we could catch other version dependencies,
|
// Here we could catch other version dependencies,
|
||||||
// like HELP1/2, and four episodes.
|
// like HELP1/2, and four episodes.
|
||||||
|
|
||||||
@ -3126,8 +3133,11 @@ void M_Drawer(void)
|
|||||||
{
|
{
|
||||||
if (alttext)
|
if (alttext)
|
||||||
{
|
{
|
||||||
MN_DrawStringCR(x, y + 8 - MN_StringHeight(alttext) / 2, cr,
|
if (!MN_DrawFon2String(x, y, cr, alttext))
|
||||||
NULL, alttext);
|
{
|
||||||
|
MN_DrawStringCR(x, y + 8 - MN_StringHeight(alttext) / 2, cr,
|
||||||
|
NULL, alttext);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (name[0])
|
else if (name[0])
|
||||||
|
@ -33,6 +33,7 @@
|
|||||||
#include "m_input.h"
|
#include "m_input.h"
|
||||||
#include "m_misc.h"
|
#include "m_misc.h"
|
||||||
#include "m_swap.h"
|
#include "m_swap.h"
|
||||||
|
#include "mn_font.h"
|
||||||
#include "mn_menu.h"
|
#include "mn_menu.h"
|
||||||
#include "p_mobj.h"
|
#include "p_mobj.h"
|
||||||
#include "r_bmaps.h"
|
#include "r_bmaps.h"
|
||||||
@ -47,6 +48,7 @@
|
|||||||
#include "sounds.h"
|
#include "sounds.h"
|
||||||
#include "v_video.h"
|
#include "v_video.h"
|
||||||
#include "w_wad.h"
|
#include "w_wad.h"
|
||||||
|
#include "z_zone.h"
|
||||||
|
|
||||||
static int M_GetKeyString(int c, int offset);
|
static int M_GetKeyString(int c, int offset);
|
||||||
static void DrawMenuString(int cx, int cy, int color);
|
static void DrawMenuString(int cx, int cy, int color);
|
||||||
@ -1533,7 +1535,7 @@ void MN_DrawStatusHUD(void)
|
|||||||
inhelpscreens = true; // killough 4/6/98: Force status bar redraw
|
inhelpscreens = true; // killough 4/6/98: Force status bar redraw
|
||||||
|
|
||||||
DrawBackground("FLOOR4_6"); // Draw background
|
DrawBackground("FLOOR4_6"); // Draw background
|
||||||
MN_DrawTitle(59, 2, "M_STAT", "STATUS BAR / HUD");
|
MN_DrawTitle(59, 2, "M_STAT", "STATUS BAR/HUD");
|
||||||
DrawTabs();
|
DrawTabs();
|
||||||
DrawInstructions();
|
DrawInstructions();
|
||||||
DrawScreenItems(current_menu);
|
DrawScreenItems(current_menu);
|
||||||
@ -1730,8 +1732,6 @@ static const char *default_complevel_strings[] = {
|
|||||||
|
|
||||||
setup_menu_t comp_settings1[] = {
|
setup_menu_t comp_settings1[] = {
|
||||||
|
|
||||||
{"Compatibility", S_SKIP | S_TITLE, M_X, M_SPC},
|
|
||||||
|
|
||||||
{"Default Compatibility Level", S_CHOICE | S_LEVWARN, M_X, M_SPC,
|
{"Default Compatibility Level", S_CHOICE | S_LEVWARN, M_X, M_SPC,
|
||||||
{"default_complevel"}, m_null, input_null, str_default_complevel},
|
{"default_complevel"}, m_null, input_null, str_default_complevel},
|
||||||
|
|
||||||
@ -1792,7 +1792,7 @@ void MN_DrawCompat(void)
|
|||||||
inhelpscreens = true;
|
inhelpscreens = true;
|
||||||
|
|
||||||
DrawBackground("FLOOR4_6"); // Draw background
|
DrawBackground("FLOOR4_6"); // Draw background
|
||||||
MN_DrawTitle(52, 2, "M_COMPAT", "DOOM COMPATIBILITY");
|
MN_DrawTitle(52, 2, "M_COMPAT", "COMPATIBILITY");
|
||||||
DrawInstructions();
|
DrawInstructions();
|
||||||
DrawScreenItems(current_menu);
|
DrawScreenItems(current_menu);
|
||||||
|
|
||||||
@ -3712,11 +3712,16 @@ void MN_DrawTitle(int x, int y, const char *patch, const char *alttext)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// patch doesn't exist, draw some text in place of it
|
// patch doesn't exist, draw some text in place of it
|
||||||
M_snprintf(menu_buffer, sizeof(menu_buffer), "%s", alttext);
|
if (!MN_DrawFon2String(
|
||||||
DrawMenuString(
|
SCREENWIDTH / 2 - MN_GetFon2PixelWidth(alttext) / 2,
|
||||||
SCREENWIDTH / 2 - MN_StringWidth(alttext) / 2,
|
y, NULL, alttext))
|
||||||
y + 8 - MN_StringHeight(alttext) / 2, // assumes patch height 16
|
{
|
||||||
CR_TITLE);
|
M_snprintf(menu_buffer, sizeof(menu_buffer), "%s", alttext);
|
||||||
|
DrawMenuString(
|
||||||
|
SCREENWIDTH / 2 - MN_StringWidth(alttext) / 2,
|
||||||
|
y + 8 - MN_StringHeight(alttext) / 2, // assumes patch height 16
|
||||||
|
CR_TITLE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
209
src/v_video.c
209
src/v_video.c
@ -1065,9 +1065,216 @@ void V_RestoreBuffer(void)
|
|||||||
dest_screen = I_VideoBuffer;
|
dest_screen = I_VideoBuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
byte row_off;
|
||||||
|
byte *pixels;
|
||||||
|
} vpost_t;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
vpost_t *posts;
|
||||||
|
} vcolumn_t;
|
||||||
|
|
||||||
|
#define M_ARRAY_INIT_CAPACITY 16
|
||||||
|
#include "m_array.h"
|
||||||
|
|
||||||
|
#define PUTBYTE(r, v) \
|
||||||
|
*r = (uint8_t)(v); \
|
||||||
|
++r
|
||||||
|
|
||||||
|
#define PUTSHORT(r, v) \
|
||||||
|
*(r + 0) = (byte)(((uint16_t)(v) >> 0) & 0xff); \
|
||||||
|
*(r + 1) = (byte)(((uint16_t)(v) >> 8) & 0xff); \
|
||||||
|
r += 2
|
||||||
|
|
||||||
|
#define PUTLONG(r, v) \
|
||||||
|
*(r + 0) = (byte)(((uint32_t)(v) >> 0) & 0xff); \
|
||||||
|
*(r + 1) = (byte)(((uint32_t)(v) >> 8) & 0xff); \
|
||||||
|
*(r + 2) = (byte)(((uint32_t)(v) >> 16) & 0xff); \
|
||||||
|
*(r + 3) = (byte)(((uint32_t)(v) >> 24) & 0xff); \
|
||||||
|
r += 4
|
||||||
|
|
||||||
//
|
//
|
||||||
// SCREEN SHOTS
|
// Converts a linear graphic to a patch with transparency. Mostly straight
|
||||||
|
// from psxwadgen, which is mostly straight from SLADE.
|
||||||
//
|
//
|
||||||
|
patch_t *V_LinearToTransPatch(const byte *data, int width, int height,
|
||||||
|
int color_key)
|
||||||
|
{
|
||||||
|
vcolumn_t *columns = NULL;
|
||||||
|
|
||||||
|
// Go through columns
|
||||||
|
uint32_t offset = 0;
|
||||||
|
for (int c = 0; c < width; c++)
|
||||||
|
{
|
||||||
|
vcolumn_t col = {0};
|
||||||
|
vpost_t post = {0};
|
||||||
|
post.row_off = 0;
|
||||||
|
boolean ispost = false;
|
||||||
|
boolean first_254 = true; // first 254 pixels use absolute offsets
|
||||||
|
|
||||||
|
offset = c;
|
||||||
|
byte row_off = 0;
|
||||||
|
for (int r = 0; r < height; r++)
|
||||||
|
{
|
||||||
|
// if we're at offset 254, create a dummy post for tall doom gfx
|
||||||
|
// support
|
||||||
|
if (row_off == 254)
|
||||||
|
{
|
||||||
|
// Finish current post if any
|
||||||
|
if (ispost)
|
||||||
|
{
|
||||||
|
array_push(col.posts, post);
|
||||||
|
post.pixels = NULL;
|
||||||
|
ispost = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Begin relative offsets
|
||||||
|
first_254 = false;
|
||||||
|
|
||||||
|
// Create dummy post
|
||||||
|
post.row_off = 254;
|
||||||
|
array_push(col.posts, post);
|
||||||
|
|
||||||
|
// Clear post
|
||||||
|
row_off = 0;
|
||||||
|
ispost = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the current pixel is not transparent, add it to the current
|
||||||
|
// post
|
||||||
|
if (data[offset] != color_key)
|
||||||
|
{
|
||||||
|
// If we're not currently building a post, begin one and set its
|
||||||
|
// offset
|
||||||
|
if (!ispost)
|
||||||
|
{
|
||||||
|
// Set offset
|
||||||
|
post.row_off = row_off;
|
||||||
|
|
||||||
|
// Reset offset if we're in relative offsets mode
|
||||||
|
if (!first_254)
|
||||||
|
{
|
||||||
|
row_off = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start post
|
||||||
|
ispost = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the pixel to the post
|
||||||
|
array_push(post.pixels, data[offset]);
|
||||||
|
}
|
||||||
|
else if (ispost)
|
||||||
|
{
|
||||||
|
// If the current pixel is transparent and we are currently
|
||||||
|
// building a post, add the current post to the list and clear
|
||||||
|
// it
|
||||||
|
array_push(col.posts, post);
|
||||||
|
post.pixels = NULL;
|
||||||
|
ispost = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Go to next row
|
||||||
|
offset += width;
|
||||||
|
++row_off;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the column ended with a post, add it
|
||||||
|
if (ispost)
|
||||||
|
{
|
||||||
|
array_push(col.posts, post);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the column data
|
||||||
|
array_push(columns, col);
|
||||||
|
|
||||||
|
// Go to next column
|
||||||
|
++offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t size = 0;
|
||||||
|
|
||||||
|
// Calculate needed memory size to allocate patch buffer
|
||||||
|
size += 4 * sizeof(int16_t); // 4 header shorts
|
||||||
|
size += array_size(columns) * sizeof(int32_t); // offsets table
|
||||||
|
|
||||||
|
for (int c = 0; c < array_size(columns); c++)
|
||||||
|
{
|
||||||
|
for (int p = 0; p < array_size(columns[c].posts); p++)
|
||||||
|
{
|
||||||
|
size_t post_len = 0;
|
||||||
|
|
||||||
|
post_len += 2; // two bytes for post header
|
||||||
|
post_len += 1; // dummy byte
|
||||||
|
post_len += array_size(columns[c].posts[p].pixels); // pixels
|
||||||
|
post_len += 1; // dummy byte
|
||||||
|
|
||||||
|
size += post_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
size += 1; // room for 0xff cap byte
|
||||||
|
}
|
||||||
|
|
||||||
|
byte *output = malloc(size);
|
||||||
|
byte *rover = output;
|
||||||
|
|
||||||
|
// write header fields
|
||||||
|
PUTSHORT(rover, width);
|
||||||
|
PUTSHORT(rover, height);
|
||||||
|
// This is written to afterwards
|
||||||
|
PUTSHORT(rover, 0);
|
||||||
|
PUTSHORT(rover, 0);
|
||||||
|
|
||||||
|
// set starting position of column offsets table, and skip over it
|
||||||
|
byte *col_offsets = rover;
|
||||||
|
rover += array_size(columns) * 4;
|
||||||
|
|
||||||
|
for (int c = 0; c < array_size(columns); c++)
|
||||||
|
{
|
||||||
|
// write column offset to offset table
|
||||||
|
uint32_t offs = (uint32_t)(rover - output);
|
||||||
|
PUTLONG(col_offsets, offs);
|
||||||
|
|
||||||
|
// write column posts
|
||||||
|
for (int p = 0; p < array_size(columns[c].posts); p++)
|
||||||
|
{
|
||||||
|
// Write row offset
|
||||||
|
PUTBYTE(rover, columns[c].posts[p].row_off);
|
||||||
|
|
||||||
|
// Write number of pixels
|
||||||
|
int numpixels = array_size(columns[c].posts[p].pixels);
|
||||||
|
PUTBYTE(rover, numpixels);
|
||||||
|
|
||||||
|
// Write pad byte
|
||||||
|
byte lastval = numpixels ? columns[c].posts[p].pixels[0] : 0;
|
||||||
|
PUTBYTE(rover, lastval);
|
||||||
|
|
||||||
|
// Write pixels
|
||||||
|
for (int a = 0; a < numpixels; a++)
|
||||||
|
{
|
||||||
|
lastval = columns[c].posts[p].pixels[a];
|
||||||
|
PUTBYTE(rover, lastval);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write pad byte
|
||||||
|
PUTBYTE(rover, lastval);
|
||||||
|
|
||||||
|
array_free(columns[c].posts[p].pixels);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write 255 cap byte
|
||||||
|
PUTBYTE(rover, 0xff);
|
||||||
|
|
||||||
|
array_free(columns[c].posts);
|
||||||
|
}
|
||||||
|
|
||||||
|
array_free(columns);
|
||||||
|
|
||||||
|
// Done!
|
||||||
|
return (patch_t *)output;
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// V_ScreenShot
|
// V_ScreenShot
|
||||||
|
@ -182,6 +182,9 @@ void V_DrawBackground(const char *patchname);
|
|||||||
|
|
||||||
int V_BloodColor(int blood);
|
int V_BloodColor(int blood);
|
||||||
|
|
||||||
|
struct patch_s *V_LinearToTransPatch(const byte *data, int width, int height,
|
||||||
|
int color_key);
|
||||||
|
|
||||||
void V_ScreenShot(void);
|
void V_ScreenShot(void);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
x
Reference in New Issue
Block a user