mirror of
https://github.com/ZDoom/wadext.git
synced 2024-11-28 06:42:19 +00:00
768 lines
26 KiB
C++
768 lines
26 KiB
C++
//
|
|
//---------------------------------------------------------------------------
|
|
//
|
|
// Copyright(C) 2016 Christoph Oelckers
|
|
// All rights reserved.
|
|
//
|
|
// 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.
|
|
//
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with this program. If not, see http://www.gnu.org/licenses/
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
//
|
|
// Portions of this file from ZDoom under the following license:
|
|
/*
|
|
** m_png.cpp
|
|
** Routines for manipulating PNG files.
|
|
**
|
|
**---------------------------------------------------------------------------
|
|
** Copyright 2002-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 <stdio.h>
|
|
#include "zlib/zlib.h"
|
|
#include "wadext.h"
|
|
#include "resourcefile.h"
|
|
#include "fileformat.h"
|
|
#include "tarray.h"
|
|
|
|
#pragma warning(disable:4996)
|
|
|
|
const uint8_t doompal[]={
|
|
0, 0, 0, 31, 23, 11, 23, 15, 7, 75, 75, 75,255,255,255, 27,
|
|
27, 27, 19, 19, 19, 11, 11, 11, 7, 7, 7, 47, 55, 31, 35, 43,
|
|
15, 23, 31, 7, 15, 23, 0, 79, 59, 43, 71, 51, 35, 63, 43, 27,
|
|
255,183,183,247,171,171,243,163,163,235,151,151,231,143,143,223,
|
|
135,135,219,123,123,211,115,115,203,107,107,199, 99, 99,191, 91,
|
|
91,187, 87, 87,179, 79, 79,175, 71, 71,167, 63, 63,163, 59, 59,
|
|
155, 51, 51,151, 47, 47,143, 43, 43,139, 35, 35,131, 31, 31,127,
|
|
27, 27,119, 23, 23,115, 19, 19,107, 15, 15,103, 11, 11, 95, 7,
|
|
7, 91, 7, 7, 83, 7, 7, 79, 0, 0, 71, 0, 0, 67, 0, 0,
|
|
255,235,223,255,227,211,255,219,199,255,211,187,255,207,179,255,
|
|
199,167,255,191,155,255,187,147,255,179,131,247,171,123,239,163,
|
|
115,231,155,107,223,147, 99,215,139, 91,207,131, 83,203,127, 79,
|
|
191,123, 75,179,115, 71,171,111, 67,163,107, 63,155, 99, 59,143,
|
|
95, 55,135, 87, 51,127, 83, 47,119, 79, 43,107, 71, 39, 95, 67,
|
|
35, 83, 63, 31, 75, 55, 27, 63, 47, 23, 51, 43, 19, 43, 35, 15,
|
|
239,239,239,231,231,231,223,223,223,219,219,219,211,211,211,203,
|
|
203,203,199,199,199,191,191,191,183,183,183,179,179,179,171,171,
|
|
171,167,167,167,159,159,159,151,151,151,147,147,147,139,139,139,
|
|
131,131,131,127,127,127,119,119,119,111,111,111,107,107,107, 99,
|
|
99, 99, 91, 91, 91, 87, 87, 87, 79, 79, 79, 71, 71, 71, 67, 67,
|
|
67, 59, 59, 59, 55, 55, 55, 47, 47, 47, 39, 39, 39, 35, 35, 35,
|
|
119,255,111,111,239,103,103,223, 95, 95,207, 87, 91,191, 79, 83,
|
|
175, 71, 75,159, 63, 67,147, 55, 63,131, 47, 55,115, 43, 47, 99,
|
|
35, 39, 83, 27, 31, 67, 23, 23, 51, 15, 19, 35, 11, 11, 23, 7,
|
|
191,167,143,183,159,135,175,151,127,167,143,119,159,135,111,155,
|
|
127,107,147,123, 99,139,115, 91,131,107, 87,123, 99, 79,119, 95,
|
|
75,111, 87, 67,103, 83, 63, 95, 75, 55, 87, 67, 51, 83, 63, 47,
|
|
159,131, 99,143,119, 83,131,107, 75,119, 95, 63,103, 83, 51, 91,
|
|
71, 43, 79, 59, 35, 67, 51, 27,123,127, 99,111,115, 87,103,107,
|
|
79, 91, 99, 71, 83, 87, 59, 71, 79, 51, 63, 71, 43, 55, 63, 39,
|
|
255,255,115,235,219, 87,215,187, 67,195,155, 47,175,123, 31,155,
|
|
91, 19,135, 67, 7,115, 43, 0,255,255,255,255,219,219,255,187,
|
|
187,255,155,155,255,123,123,255, 95, 95,255, 63, 63,255, 31, 31,
|
|
255, 0, 0,239, 0, 0,227, 0, 0,215, 0, 0,203, 0, 0,191,
|
|
0, 0,179, 0, 0,167, 0, 0,155, 0, 0,139, 0, 0,127, 0,
|
|
0,115, 0, 0,103, 0, 0, 91, 0, 0, 79, 0, 0, 67, 0, 0,
|
|
231,231,255,199,199,255,171,171,255,143,143,255,115,115,255, 83,
|
|
83,255, 55, 55,255, 27, 27,255, 0, 0,255, 0, 0,227, 0, 0,
|
|
203, 0, 0,179, 0, 0,155, 0, 0,131, 0, 0,107, 0, 0, 83,
|
|
255,255,255,255,235,219,255,215,187,255,199,155,255,179,123,255,
|
|
163, 91,255,143, 59,255,127, 27,243,115, 23,235,111, 15,223,103,
|
|
15,215, 95, 11,203, 87, 7,195, 79, 0,183, 71, 0,175, 67, 0,
|
|
255,255,255,255,255,215,255,255,179,255,255,143,255,255,107,255,
|
|
255, 71,255,255, 35,255,255, 0,167, 63, 0,159, 55, 0,147, 47,
|
|
0,135, 35, 0, 79, 59, 39, 67, 47, 27, 55, 35, 19, 47, 27, 11,
|
|
0, 0, 83, 0, 0, 71, 0, 0, 59, 0, 0, 47, 0, 0, 35, 0,
|
|
0, 23, 0, 0, 11, 0, 0, 0,255,159, 67,255,231, 75,255,123,
|
|
255,255, 0,255,207, 0,207,159, 0,155,111, 0,107,167,107,107,
|
|
};
|
|
|
|
const uint8_t hereticpal[]={
|
|
2, 2, 2, 2, 2, 2, 16, 16, 16, 24, 24, 24, 31, 31, 31, 36,
|
|
36, 36, 44, 44, 44, 48, 48, 48, 55, 55, 55, 63, 63, 63, 70, 70,
|
|
70, 78, 78, 78, 86, 86, 86, 93, 93, 93,101,101,101,108,108,108,
|
|
116,116,116,124,124,124,131,131,131,139,139,139,146,146,146,154,
|
|
154,154,162,162,162,169,169,169,177,177,177,184,184,184,192,192,
|
|
192,200,200,200,207,207,207,210,210,210,215,215,215,222,222,222,
|
|
228,228,228,236,236,236,245,245,245,255,255,255, 50, 50, 50, 59,
|
|
60, 59, 69, 72, 68, 78, 80, 77, 88, 93, 86, 97,100, 95,109,112,
|
|
104,116,123,112,125,131,121,134,141,130,144,151,139,153,161,148,
|
|
163,171,157,172,181,166,181,189,176,189,196,185, 20, 16, 36, 24,
|
|
24, 44, 36, 36, 60, 52, 52, 80, 68, 68, 96, 88, 88,116,108,108,
|
|
136,124,124,152,148,148,172,164,164,184,180,184,200,192,196,208,
|
|
208,208,216,224,224,224, 27, 15, 8, 38, 20, 11, 49, 27, 14, 61,
|
|
31, 14, 65, 35, 18, 74, 37, 19, 83, 43, 19, 87, 47, 23, 95, 51,
|
|
27,103, 59, 31,115, 67, 35,123, 75, 39,131, 83, 47,143, 91, 51,
|
|
151, 99, 59,160,108, 64,175,116, 74,180,126, 81,192,135, 91,204,
|
|
143, 93,213,151,103,216,159,115,220,167,126,223,175,138,227,183,
|
|
149,230,190,161,233,198,172,237,206,184,240,214,195, 62, 40, 11,
|
|
75, 50, 16, 84, 59, 23, 95, 67, 30,103, 75, 38,110, 83, 47,123,
|
|
95, 55,137,107, 62,150,118, 75,163,129, 84,171,137, 92,180,146,
|
|
101,188,154,109,196,162,117,204,170,125,208,176,133, 37, 20, 4,
|
|
47, 24, 4, 57, 28, 6, 68, 33, 4, 76, 36, 3, 84, 40, 0, 97,
|
|
47, 2,114, 54, 0,125, 63, 6,141, 75, 9,155, 83, 17,162, 95,
|
|
21,169,103, 26,180,113, 32,188,124, 20,204,136, 24,220,148, 28,
|
|
236,160, 23,244,172, 47,252,187, 57,252,194, 70,251,201, 83,251,
|
|
208, 97,251,214,110,251,221,123,250,228,136,157, 51, 4,170, 65,
|
|
2,185, 86, 4,213,118, 4,236,164, 3,248,190, 3,255,216, 43,
|
|
255,255, 0, 67, 0, 0, 79, 0, 0, 91, 0, 0,103, 0, 0,115,
|
|
0, 0,127, 0, 0,139, 0, 0,155, 0, 0,167, 0, 0,179, 0,
|
|
0,191, 0, 0,203, 0, 0,215, 0, 0,227, 0, 0,239, 0, 0,
|
|
255, 0, 0,255, 52, 52,255, 74, 74,255, 95, 95,255,123,123,255,
|
|
155,155,255,179,179,255,201,201,255,215,215, 60, 12, 88, 80, 8,
|
|
108,104, 8,128,128, 0,144,152, 0,176,184, 0,224,216, 44,252,
|
|
224,120,240, 37, 6,129, 60, 33,147, 82, 61,165,105, 88,183,128,
|
|
116,201,151,143,219,173,171,237,196,198,255, 2, 4, 41, 2, 5,
|
|
49, 6, 8, 57, 2, 5, 65, 2, 5, 79, 0, 4, 88, 0, 4, 96,
|
|
0, 4,104, 2, 5,121, 2, 5,137, 6, 9,159, 12, 16,184, 32,
|
|
40,200, 56, 60,220, 80, 80,253, 80,108,252, 80,136,252, 80,164,
|
|
252, 80,196,252, 72,220,252, 80,236,252, 84,252,252,152,252,252,
|
|
188,252,244, 11, 23, 7, 19, 35, 11, 23, 51, 15, 31, 67, 23, 39,
|
|
83, 27, 47, 99, 35, 55,115, 43, 63,131, 47, 67,147, 55, 75,159,
|
|
63, 83,175, 71, 91,191, 79, 95,207, 87,103,223, 95,111,239,103,
|
|
119,255,111, 23, 31, 23, 27, 35, 27, 31, 43, 31, 35, 51, 35, 43,
|
|
55, 43, 47, 63, 47, 51, 71, 51, 59, 75, 55, 63, 83, 59, 67, 91,
|
|
67, 75, 95, 71, 79,103, 75, 87,111, 79, 91,115, 83, 95,123, 87,
|
|
103,131, 95,255,223, 0,255,191, 0,255,159, 0,255,127, 0,255,
|
|
95, 0,255, 63, 0,244, 14, 3, 55, 0, 0, 47, 0, 0, 39, 0,
|
|
0, 23, 0, 0, 15, 15, 15, 11, 11, 11, 7, 7, 7,255,255,255,
|
|
};
|
|
|
|
|
|
|
|
const uint8_t hexenpal[]={
|
|
2, 2, 2, 4, 4, 4, 15, 15, 15, 19, 19, 19, 27, 27, 27, 28,
|
|
28, 28, 33, 33, 33, 39, 39, 39, 45, 45, 45, 51, 51, 51, 57, 57,
|
|
57, 63, 63, 63, 69, 69, 69, 75, 75, 75, 81, 81, 81, 86, 86, 86,
|
|
92, 92, 92, 98, 98, 98,104,104,104,112,112,112,121,121,121,130,
|
|
130,130,139,139,139,147,147,147,157,157,157,166,166,166,176,176,
|
|
176,185,185,185,194,194,194,203,203,203,212,212,212,221,221,221,
|
|
230,230,230, 29, 32, 29, 38, 40, 37, 50, 50, 50, 59, 60, 59, 69,
|
|
72, 68, 78, 80, 77, 88, 93, 86, 97,100, 95,109,112,104,116,123,
|
|
112,125,131,121,134,141,130,144,151,139,153,161,148,163,171,157,
|
|
172,181,166,181,189,176,189,196,185, 22, 29, 22, 27, 36, 27, 31,
|
|
43, 31, 35, 51, 35, 43, 55, 43, 47, 63, 47, 51, 71, 51, 59, 75,
|
|
55, 63, 83, 59, 67, 91, 67, 75, 95, 71, 79,103, 75, 87,111, 79,
|
|
91,115, 83, 95,123, 87,103,131, 95, 20, 16, 36, 30, 26, 46, 40,
|
|
36, 57, 50, 46, 67, 59, 57, 78, 69, 67, 88, 79, 77, 99, 89, 87,
|
|
109, 99, 97,120,109,107,130,118,118,141,128,128,151,138,138,162,
|
|
148,148,172, 62, 40, 11, 75, 50, 16, 84, 59, 23, 95, 67, 30,103,
|
|
75, 38,110, 83, 47,123, 95, 55,137,107, 62,150,118, 75,163,129,
|
|
84,171,137, 92,180,146,101,188,154,109,196,162,117,204,170,125,
|
|
208,176,133, 27, 15, 8, 38, 20, 11, 49, 27, 14, 61, 31, 14, 65,
|
|
35, 18, 74, 37, 19, 83, 43, 19, 87, 47, 23, 95, 51, 27,103, 59,
|
|
31,115, 67, 35,123, 75, 39,131, 83, 47,143, 91, 51,151, 99, 59,
|
|
160,108, 64,175,116, 74,180,126, 81,192,135, 91,204,143, 93,213,
|
|
151,103,216,159,115,220,167,126,223,175,138,227,183,149, 37, 20,
|
|
4, 47, 24, 4, 57, 28, 6, 68, 33, 4, 76, 36, 3, 84, 40, 0,
|
|
97, 47, 2,114, 54, 0,125, 63, 6,141, 75, 9,155, 83, 17,162,
|
|
95, 21,169,103, 26,180,113, 32,188,124, 20,204,136, 24,220,148,
|
|
28,236,160, 23,244,172, 47,252,187, 57,252,194, 70,251,201, 83,
|
|
251,208, 97,251,221,123, 2, 4, 41, 2, 5, 49, 6, 8, 57, 2,
|
|
5, 65, 2, 5, 79, 0, 4, 88, 0, 4, 96, 0, 4,104, 4, 6,
|
|
121, 2, 5,137, 20, 23,152, 38, 41,167, 56, 59,181, 74, 77,196,
|
|
91, 94,211,109,112,226,127,130,240,145,148,255, 31, 4, 4, 39,
|
|
0, 0, 47, 0, 0, 55, 0, 0, 67, 0, 0, 79, 0, 0, 91, 0,
|
|
0,103, 0, 0,115, 0, 0,127, 0, 0,139, 0, 0,155, 0, 0,
|
|
167, 0, 0,185, 0, 0,202, 0, 0,220, 0, 0,237, 0, 0,255,
|
|
0, 0,255, 46, 46,255, 91, 91,255,137,137,255,171,171, 20, 16,
|
|
4, 13, 24, 9, 17, 33, 12, 21, 41, 14, 24, 50, 17, 28, 57, 20,
|
|
32, 65, 24, 35, 73, 28, 39, 80, 31, 44, 86, 37, 46, 95, 38, 51,
|
|
104, 43, 60,122, 51, 68,139, 58, 77,157, 66, 85,174, 73, 94,192,
|
|
81,157, 51, 4,170, 65, 2,185, 86, 4,213,119, 6,234,147, 5,
|
|
255,178, 6,255,195, 26,255,216, 45, 4,133, 4, 8,175, 8, 2,
|
|
215, 2, 3,234, 3, 42,252, 42,121,255,121, 3, 3,184, 15, 41,
|
|
220, 28, 80,226, 41,119,233, 54,158,239, 67,197,246, 80,236,252,
|
|
244, 14, 3,255, 63, 0,255, 95, 0,255,127, 0,255,159, 0,255,
|
|
195, 26,255,223, 0, 43, 13, 64, 61, 14, 89, 90, 15,122,120, 16,
|
|
156,149, 16,189,178, 17,222,197, 74,232,215,129,243,234,169,253,
|
|
61, 16, 16, 90, 36, 33,118, 56, 49,147, 77, 66,176, 97, 83,204,
|
|
117, 99, 71, 53, 2, 81, 63, 6, 96, 72, 0,108, 80, 0,120, 88,
|
|
0,128, 96, 0,149,112, 1,181,136, 3,212,160, 4,255,255,255,
|
|
};
|
|
|
|
const uint8_t strifepal[]={
|
|
0, 0, 0,231,227,227,223,219,219,215,211,211,207,203,203,199,
|
|
195,195,191,191,191,183,183,183,179,175,175,171,167,167,163,159,
|
|
159,155,151,151,147,147,147,139,139,139,131,131,131,123,123,123,
|
|
119,115,115,111,111,111,103,103,103, 95, 95, 95, 87, 87, 87, 79,
|
|
79, 79, 71, 71, 71, 67, 63, 63, 59, 59, 59, 51, 51, 51, 43, 43,
|
|
43, 35, 35, 35, 27, 27, 27, 19, 19, 19, 11, 11, 11, 7, 7, 7,
|
|
187,191,183,179,183,171,167,179,159,163,171,147,155,167,139,147,
|
|
159,127,139,155,119,131,147,107,127,143,103,119,135, 91,115,131,
|
|
83,107,123, 75,103,119, 67, 99,111, 63, 91,107, 55, 87, 99, 47,
|
|
83, 95, 43, 75, 87, 35, 71, 83, 31, 67, 75, 27, 63, 71, 23, 59,
|
|
63, 19, 51, 59, 15, 47, 51, 11, 43, 47, 7, 39, 43, 7, 31, 35,
|
|
7, 27, 31, 0, 23, 23, 0, 15, 19, 0, 11, 11, 0, 7, 7, 0,
|
|
219, 43, 43,203, 35, 35,191, 31, 31,175, 27, 27,163, 23, 23,147,
|
|
19, 19,135, 15, 15,119, 11, 11,107, 7, 7, 91, 7, 7, 79, 0,
|
|
0, 63, 0, 0, 51, 0, 0, 39, 0, 0, 23, 0, 0, 11, 0, 0,
|
|
235,231, 0,231,211, 0,215,179, 0,199,151, 0,183,127, 0,167,
|
|
103, 0,151, 83, 0,135, 63, 0,119, 47, 0,103, 35, 0, 87, 23,
|
|
0, 71, 11, 0, 55, 7, 0, 39, 0, 0, 23, 0, 0, 11, 0, 0,
|
|
183,231,127,163,215,111,143,199, 95,127,183, 79,107,171, 67, 91,
|
|
155, 55, 75,139, 43, 63,123, 35, 47,111, 27, 35, 95, 19, 23, 79,
|
|
11, 15, 67, 7, 7, 51, 7, 0, 35, 0, 0, 19, 0, 0, 7, 0,
|
|
199,207,255,183,187,239,163,171,219,151,155,203,135,139,187,123,
|
|
127,171,107,111,155, 95, 99,139, 83, 83,123, 67, 71,107, 55, 59,
|
|
91, 47, 47, 75, 35, 35, 59, 23, 23, 43, 15, 15, 27, 0, 0, 11,
|
|
199,191,147,179,171,131,167,155,119,155,139,111,143,127, 99,131,
|
|
111, 91,119, 99, 79,107, 87, 71, 91, 71, 59, 79, 59, 51, 67, 47,
|
|
43, 55, 39, 35, 43, 27, 27, 31, 19, 19, 19, 11, 11, 7, 7, 0,
|
|
143,195,211,123,179,195,107,167,183, 91,155,167, 75,139,155, 59,
|
|
127,139, 47,115,127, 35,103,115, 27, 91, 99, 19, 79, 87, 11, 67,
|
|
71, 7, 55, 59, 0, 43, 43, 0, 31, 31, 0, 19, 19, 0, 7, 7,
|
|
211,191,175,203,179,163,195,171,151,191,159,143,183,151,131,175,
|
|
143,123,171,135,115,163,123,103,155,115, 95,151,107, 87,143, 99,
|
|
79,139, 91, 71,131, 83, 67,123, 75, 59,119, 67, 51,111, 59, 47,
|
|
103, 55, 39, 99, 47, 35, 91, 43, 31, 83, 35, 27, 79, 31, 23, 71,
|
|
27, 19, 63, 19, 15, 59, 15, 11, 51, 11, 7, 43, 7, 7, 39, 7,
|
|
0, 31, 0, 0, 27, 0, 0, 19, 0, 0, 11, 0, 0, 7, 0, 0,
|
|
211,199,187,203,191,179,195,183,171,191,175,163,183,167,155,175,
|
|
159,147,171,151,139,163,143,135,155,139,127,151,131,119,143,123,
|
|
111,135,115,107,131,107, 99,123,103, 95,115, 95, 87,111, 87, 83,
|
|
103, 83, 75, 95, 75, 71, 91, 67, 63, 83, 63, 59, 79, 55, 51, 71,
|
|
51, 47, 63, 43, 43, 59, 39, 39, 51, 35, 31, 43, 27, 27, 39, 23,
|
|
23, 31, 19, 19, 23, 15, 15, 19, 11, 11, 11, 7, 7, 7, 7, 0,
|
|
239,239, 0,231,215, 0,227,191, 0,219,171, 0,215,151, 0,211,
|
|
131, 0,203,111, 0,199, 91, 0,191, 75, 0,187, 59, 0,183, 43,
|
|
0,255, 0, 0,223, 0, 0,191, 0, 0,159, 0, 0,127, 0, 0,
|
|
0, 47, 47,139,199,103,107,171, 75, 79,143, 55, 55,115, 35, 35,
|
|
87, 19, 19, 63, 11,215,223,255,187,203,247,143,167,219, 99,131,
|
|
195, 63, 91,167,203,203,203,215,215,215,223,223,223,235,235,235,
|
|
};
|
|
|
|
#pragma pack(1)
|
|
struct IHDR
|
|
{
|
|
uint32_t Width;
|
|
uint32_t Height;
|
|
uint8_t BitDepth;
|
|
uint8_t ColorType;
|
|
uint8_t Compression;
|
|
uint8_t Filter;
|
|
uint8_t Interlace;
|
|
};
|
|
#pragma pack()
|
|
|
|
|
|
uint8_t palette[768];
|
|
const uint8_t *ppal = NULL;
|
|
bool done;
|
|
|
|
const uint8_t *GetPalette(int flags)
|
|
{
|
|
if (ppal) return ppal;
|
|
int pplump = mainwad->FindLump("PLAYPAL");
|
|
if (pplump >= 0)
|
|
{
|
|
WadItemList w(pplump);
|
|
memcpy(palette, w.Address(), 768);
|
|
ppal = palette;
|
|
}
|
|
else
|
|
{
|
|
if (flags&DO_HERETIC_PAL) ppal = hereticpal;
|
|
else if (flags&DO_HEXEN_PAL) ppal = hexenpal;
|
|
else if (flags&DO_STRIFE) ppal = strifepal;
|
|
else ppal = doompal;
|
|
}
|
|
return ppal;
|
|
}
|
|
|
|
inline uint32_t BigLong(uint32_t nLongNumber)
|
|
{
|
|
return (((nLongNumber & 0x000000FF) << 24) + ((nLongNumber & 0x0000FF00) << 8) +
|
|
((nLongNumber & 0x00FF0000) >> 8) + ((nLongNumber & 0xFF000000) >> 24));
|
|
}
|
|
|
|
inline const uint32_t *GetCRCTable() { return (const uint32_t *)get_crc_table(); }
|
|
inline uint32_t CalcCRC32(const uint8_t *buf, unsigned int len)
|
|
{
|
|
return crc32(0, buf, len);
|
|
}
|
|
inline uint32_t AddCRC32(uint32_t crc, const uint8_t *buf, unsigned int len)
|
|
{
|
|
return crc32(crc, buf, len);
|
|
}
|
|
inline uint32_t CRC1(uint32_t crc, const uint8_t c, const uint32_t *crcTable)
|
|
{
|
|
return crcTable[(crc & 0xff) ^ c] ^ (crc >> 8);
|
|
}
|
|
|
|
|
|
//==========================================================================
|
|
//
|
|
// M_AppendPNGChunk
|
|
//
|
|
// Writes a PNG-compliant chunk to the file.
|
|
//
|
|
//==========================================================================
|
|
|
|
bool M_AppendPNGChunk(FILE *file, uint32_t chunkID, const void *_chunkData, uint32_t len)
|
|
{
|
|
const uint8_t *chunkData = (uint8_t*)_chunkData;
|
|
uint32_t head[2] = { BigLong((unsigned int)len), chunkID };
|
|
uint32_t crc;
|
|
|
|
if (fwrite(head, 1, 8, file) == 8 &&
|
|
(len == 0 || fwrite(chunkData, 1, len, file) == len))
|
|
{
|
|
crc = CalcCRC32((uint8_t *)&head[1], 4);
|
|
if (len != 0)
|
|
{
|
|
crc = AddCRC32(crc, chunkData, len);
|
|
}
|
|
crc = BigLong((unsigned int)crc);
|
|
return fwrite(&crc, 1, 4, file) == 4;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
//==========================================================================
|
|
//
|
|
// M_SaveBitmap
|
|
//
|
|
// Given a bitmap, creates one or more IDAT chunks in the given file.
|
|
// Returns true on success.
|
|
//
|
|
//==========================================================================
|
|
#define PNG_WRITE_SIZE 32768
|
|
#define MAXWIDTH 8192
|
|
|
|
bool M_SaveBitmap(const uint8_t *from, int width, int height, int pitch, FILE *file)
|
|
{
|
|
uint8_t temprow[1][1 + MAXWIDTH * 3];
|
|
uint8_t buffer[PNG_WRITE_SIZE];
|
|
z_stream stream;
|
|
int err;
|
|
int y;
|
|
|
|
stream.next_in = Z_NULL;
|
|
stream.avail_in = 0;
|
|
stream.zalloc = Z_NULL;
|
|
stream.zfree = Z_NULL;
|
|
err = deflateInit(&stream, 9);
|
|
|
|
if (err != Z_OK)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
y = height;
|
|
stream.next_out = buffer;
|
|
stream.avail_out = sizeof(buffer);
|
|
|
|
temprow[0][0] = 0;
|
|
|
|
while (y-- > 0 && err == Z_OK)
|
|
{
|
|
memcpy(&temprow[0][1], from, width);
|
|
// always use filter type 0 for paletted images
|
|
stream.next_in = temprow[0];
|
|
stream.avail_in = width + 1;
|
|
|
|
from += pitch;
|
|
|
|
err = deflate(&stream, (y == 0) ? Z_FINISH : 0);
|
|
if (err != Z_OK)
|
|
{
|
|
break;
|
|
}
|
|
while (stream.avail_out == 0)
|
|
{
|
|
if (!M_AppendPNGChunk(file, MAKE_ID('I', 'D', 'A', 'T'), buffer, sizeof(buffer)))
|
|
{
|
|
return false;
|
|
}
|
|
stream.next_out = buffer;
|
|
stream.avail_out = sizeof(buffer);
|
|
if (stream.avail_in != 0)
|
|
{
|
|
err = deflate(&stream, (y == 0) ? Z_FINISH : 0);
|
|
if (err != Z_OK)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
while (err == Z_OK)
|
|
{
|
|
err = deflate(&stream, Z_FINISH);
|
|
if (err != Z_OK)
|
|
{
|
|
break;
|
|
}
|
|
if (stream.avail_out == 0)
|
|
{
|
|
if (!M_AppendPNGChunk(file, MAKE_ID('I','D','A','T'), buffer, sizeof(buffer)))
|
|
{
|
|
return false;
|
|
}
|
|
stream.next_out = buffer;
|
|
stream.avail_out = sizeof(buffer);
|
|
}
|
|
}
|
|
|
|
deflateEnd(&stream);
|
|
|
|
if (err != Z_STREAM_END)
|
|
{
|
|
return false;
|
|
}
|
|
return M_AppendPNGChunk(file, MAKE_ID('I', 'D', 'A', 'T'), buffer, sizeof(buffer) - stream.avail_out);
|
|
}
|
|
|
|
|
|
//==========================================================================
|
|
//
|
|
//
|
|
//
|
|
//==========================================================================
|
|
|
|
void WritePNG(const uint8_t *bufferRGBA, int width, int height, int leftofs, int topofs, const char *filename)
|
|
{
|
|
int numpix = width * height;
|
|
bool hastrans = false;
|
|
TMap<uint32_t, uint8_t> palmap;
|
|
uint8_t *bufferPaletted = new uint8_t[numpix];
|
|
uint8_t palette[768];
|
|
for (int i = 0; i < numpix; i++)
|
|
{
|
|
if (bufferRGBA[i * 4 + 3] == 0)
|
|
{
|
|
hastrans = true;
|
|
break;
|
|
}
|
|
}
|
|
int curcol = 0;
|
|
if (hastrans)
|
|
{
|
|
palmap[0] = 0;
|
|
palette[0] = palette[1] = palette[2] = 0;
|
|
curcol++;
|
|
}
|
|
for (int i = 0; i < numpix; i++)
|
|
{
|
|
const uint8_t *pix = &bufferRGBA[i * 4];
|
|
uint32_t rgba = pix[0] + 256 * pix[1] + 256 * 256 * pix[2] + 256 * 256 * 256 * pix[3];
|
|
uint8_t *pIndex = palmap.CheckKey(rgba);
|
|
uint8_t index;
|
|
if (pIndex != NULL) index = *pIndex;
|
|
else
|
|
{
|
|
palmap[rgba] = curcol;
|
|
index = curcol;
|
|
palette[curcol * 3] = pix[0];
|
|
palette[curcol * 3+1] = pix[1];
|
|
palette[curcol * 3+2] = pix[2];
|
|
curcol++;
|
|
}
|
|
bufferPaletted[i] = index;
|
|
}
|
|
|
|
FILE * f = fopen(filename, "wb");
|
|
if (f == NULL) return;
|
|
|
|
const char sig[] = "\x89PNG\r\n\x1a\n";
|
|
IHDR ihdr;
|
|
|
|
ihdr.Width = BigLong(width);
|
|
ihdr.Height = BigLong(height);
|
|
ihdr.BitDepth = 8;
|
|
ihdr.ColorType = 3;
|
|
ihdr.Compression = 0;
|
|
ihdr.Filter = 0;
|
|
ihdr.Interlace = 0;
|
|
|
|
fwrite(sig, 1, 8, f);
|
|
M_AppendPNGChunk(f, MAKE_ID('I', 'H', 'D', 'R'), &ihdr, sizeof(ihdr));
|
|
if (leftofs != 0 || topofs != 0)
|
|
{
|
|
uint32_t ofs[] = { BigLong(leftofs), BigLong(topofs) };
|
|
M_AppendPNGChunk(f, MAKE_ID('g', 'r', 'A', 'b'), ofs, 8);
|
|
}
|
|
if (curcol > 0)
|
|
{
|
|
M_AppendPNGChunk(f, MAKE_ID('P', 'L', 'T', 'E'), palette, curcol * 3);
|
|
}
|
|
if (hastrans)
|
|
{
|
|
char nul = 0;
|
|
M_AppendPNGChunk(f, MAKE_ID('t', 'R', 'N', 'S'), &nul, 1);
|
|
}
|
|
|
|
M_SaveBitmap(bufferPaletted, width, height, width, f);
|
|
|
|
static const uint8_t iend[12] = { 0,0,0,0,73,69,78,68,174,66,96,130 };
|
|
fwrite(iend, 1, 12, f);
|
|
fclose(f);
|
|
}
|
|
|
|
|
|
bool FlatToPng(int options, const uint8_t *data, int length, const char *pngpath)
|
|
{
|
|
int width, height;
|
|
|
|
// This uses the same logic as ZDoom, except for the 320x200 case which is for Raven's fullscreen images
|
|
switch (length)
|
|
{
|
|
default:
|
|
case 64 * 64: width = height = 64; break;
|
|
case 8 * 8: width = height = 8; break;
|
|
case 16 * 16: width = height = 16; break;
|
|
case 32 * 32: width = height = 32; break;
|
|
case 128 * 128: width = height = 128; break;
|
|
case 256 * 256: width = height = 256; break;
|
|
case 64000: width = 320; height = 200; break;
|
|
}
|
|
|
|
uint8_t *image = new uint8_t[width * height * 4];
|
|
|
|
const unsigned char *bytes = (const unsigned char *)data;
|
|
const uint8_t *palette = GetPalette(options);
|
|
|
|
for (int y = 0; y<height; y++) for (int x = 0; x<width; x++)
|
|
{
|
|
const unsigned char data = bytes[x + y*width];
|
|
unsigned char *ddata = &image[(x + y*width) * 4];
|
|
|
|
ddata[0] = palette[data * 3 + 0];
|
|
ddata[1] = palette[data * 3 + 1];
|
|
ddata[2] = palette[data * 3 + 2];
|
|
ddata[3] = 255;
|
|
}
|
|
|
|
WritePNG(image, width, height, 0, 0, pngpath);
|
|
delete[]image;
|
|
return true;
|
|
}
|
|
|
|
|
|
|
|
/****************************
|
|
PatchToPng
|
|
*****************************/
|
|
|
|
|
|
bool IsHack(const uint8_t *data, int length)
|
|
{
|
|
// Check if this patch is likely to be a problem.
|
|
// It must be 256 pixels tall, and all its columns must have exactly
|
|
// one post, where each post has a supposed length of 0.
|
|
const patch_t *realpatch = (const patch_t *)data;
|
|
const uint32_t *cofs = realpatch->columnofs;
|
|
int x, x2 = realpatch->width;
|
|
|
|
if (realpatch->height == 256)
|
|
{
|
|
for (x = 0; x < x2; ++x)
|
|
{
|
|
const column_t *col = (column_t*)((uint8_t *)realpatch + cofs[x]);
|
|
if (col->topdelta != 0 || col->length != 0)
|
|
{
|
|
return false; // It's not bad!
|
|
}
|
|
col = (column_t *)((uint8_t *)col + 256 + 4);
|
|
if (col->topdelta != 0xFF)
|
|
{
|
|
return false; // More than one post in a column!
|
|
}
|
|
}
|
|
if (x == x2)
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool PatchToPng(int options, const uint8_t *ldata, int length, const char *pngpath)
|
|
{
|
|
const unsigned char *palette = GetPalette(options);
|
|
|
|
const column_t *maxcol;
|
|
int x;
|
|
|
|
const patch_t *patch = (const patch_t *)ldata;
|
|
|
|
int height = patch->height;
|
|
int width = patch->width;
|
|
uint8_t *image = new uint8_t[width * height * 4];
|
|
memset(image, 0, width*height * 4);
|
|
|
|
maxcol = (const column_t *)((const uint8_t *)patch + length - 3);
|
|
|
|
// detect broken patches
|
|
if (IsHack(ldata, length))
|
|
{
|
|
// Draw the image to the buffer
|
|
for (x = 0; x < width; ++x)
|
|
{
|
|
const uint8_t *in = (const uint8_t *)patch + patch->columnofs[x] + 3;
|
|
|
|
for (int y = height; y > 0; --y)
|
|
{
|
|
unsigned char *ddata = &image[(x + y*width) * 4];
|
|
ddata[0] = palette[*in * 3 + 0];
|
|
ddata[1] = palette[*in * 3 + 1];
|
|
ddata[2] = palette[*in * 3 + 2];
|
|
ddata[3] = 255;
|
|
in++;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
|
|
// Draw the image to the buffer
|
|
for (x = 0; x < width; ++x)
|
|
{
|
|
const column_t *column = (const column_t *)((const uint8_t *)patch + patch->columnofs[x]);
|
|
int top = -1;
|
|
|
|
while (column < maxcol && column->topdelta != 0xFF)
|
|
{
|
|
if (column->topdelta <= top)
|
|
{
|
|
top += column->topdelta;
|
|
}
|
|
else
|
|
{
|
|
top = column->topdelta;
|
|
}
|
|
|
|
int len = column->length;
|
|
|
|
if (len != 0)
|
|
{
|
|
if (top + len > height) // Clip posts that extend past the bottom
|
|
{
|
|
len = height - top;
|
|
}
|
|
if (len > 0)
|
|
{
|
|
const uint8_t *in = (const uint8_t *)column + 3;
|
|
for (int i = 0; i < len; ++i)
|
|
{
|
|
unsigned char *ddata = &image[(x + (top+i)*width) * 4];
|
|
ddata[0] = palette[in[i] * 3 + 0];
|
|
ddata[1] = palette[in[i] * 3 + 1];
|
|
ddata[2] = palette[in[i] * 3 + 2];
|
|
ddata[3] = 255;
|
|
}
|
|
}
|
|
}
|
|
column = (const column_t *)((const uint8_t *)column + column->length + 4);
|
|
}
|
|
}
|
|
}
|
|
|
|
WritePNG(image, width, height, patch->leftoffset, patch->topoffset, pngpath);
|
|
delete[]image;
|
|
return true;
|
|
}
|
|
|
|
|
|
struct DoomSoundHead
|
|
{
|
|
unsigned short three;
|
|
unsigned short samplerate;
|
|
unsigned short samples;
|
|
unsigned short zero;
|
|
};
|
|
|
|
struct WavSoundHead
|
|
{
|
|
char riff[4];
|
|
unsigned size;
|
|
char wave[4];
|
|
char fmt[4];
|
|
unsigned x10;
|
|
unsigned short x01;
|
|
unsigned short channels;
|
|
unsigned rate;
|
|
unsigned bytesPerSecond;
|
|
unsigned short bytesPerSample;
|
|
unsigned short bitsPerSample;
|
|
char data[4];
|
|
unsigned length;
|
|
|
|
WavSoundHead()
|
|
{
|
|
riff[0] = 'R'; riff[1] = 'I'; riff[2] = 'F'; riff[3] = 'F';
|
|
wave[0] = 'W'; wave[1] = 'A'; wave[2] = 'V'; wave[3] = 'E';
|
|
fmt[0] = 'f'; fmt[1] = 'm'; fmt[2] = 't'; fmt[3] = ' ';
|
|
x10 = 0x10; // length of format chunk
|
|
x01 = 0x01;
|
|
channels = 1;
|
|
bytesPerSample = 1; // 8 bit mono
|
|
bitsPerSample = 8; // 8 bit mono
|
|
data[0] = 'd'; data[1] = 'a'; data[2] = 't'; data[3] = 'a';
|
|
}
|
|
|
|
};
|
|
|
|
bool DoomSndToWav(const uint8_t *data, int length, const char *filename)
|
|
{
|
|
|
|
DoomSoundHead *head = (DoomSoundHead *)data;
|
|
uint32_t headSize = sizeof(DoomSoundHead);
|
|
uint32_t dataSize = length - headSize;
|
|
|
|
WavSoundHead wh;
|
|
wh.length = dataSize;
|
|
wh.size = dataSize + 36;
|
|
wh.rate = wh.bytesPerSecond = head->samplerate;
|
|
|
|
FILE *f = fopen(filename, "wb");
|
|
if (f != NULL)
|
|
{
|
|
fwrite(&wh, 1, sizeof(WavSoundHead), f);
|
|
fwrite(data + headSize, 1, dataSize, f);
|
|
fclose(f);
|
|
return true;
|
|
}
|
|
return false;
|
|
};
|