]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - plugins/imageq2/wal.cpp
reformat code! now the code is only ugly on the *inside*
[xonotic/netradiant.git] / plugins / imageq2 / wal.cpp
1 /*
2    Copyright (C) 2001-2006, William Joseph.
3    All Rights Reserved.
4
5    This file is part of GtkRadiant.
6
7    GtkRadiant is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11
12    GtkRadiant is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with GtkRadiant; if not, write to the Free Software
19    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20  */
21
22 #include "wal.h"
23
24 #include "ifilesystem.h"
25
26 #include "os/path.h"
27 #include "stream/stringstream.h"
28 #include "bytestreamutils.h"
29 #include "imagelib.h"
30
31 const int QUAKE2_WAL = 0;
32 const int HERETIC2_M8 = 1;
33
34 typedef unsigned char byte;
35
36 struct pcx_header_t {
37     char manufacturer;
38     char version;
39     char encoding;
40     char bits_per_pixel;
41 };
42
43 void LoadPCXPalette(const char *filename, byte palette[768])
44 {
45     byte *buffer;
46     int length = vfsLoadFile(filename, (void **) &buffer);
47     if (buffer == 0) {
48         return;
49     }
50
51     const pcx_header_t *pcx = reinterpret_cast<const pcx_header_t *>( buffer );
52
53     if (pcx->manufacturer != 0x0a
54         || pcx->version != 5
55         || pcx->encoding != 1
56         || pcx->bits_per_pixel != 8) {
57         return;
58     }
59
60     memcpy(palette, buffer + length - 768, 768);
61
62     vfsFreeFile(buffer);
63 }
64
65 const int WAL_NAME_LENGTH = 32;
66 const int WAL_MIPMAP_COUNT = 4;
67 struct wal_header_t {
68     char name[WAL_NAME_LENGTH];
69     unsigned width, height;
70     unsigned offsets[WAL_MIPMAP_COUNT];       // four mip maps stored
71     char animname[WAL_NAME_LENGTH];         // next frame in animation chain
72     int flags;
73     int contents;
74     int value;
75 };
76
77 const int M8_NAME_LENGTH = 32;
78 const int M8_MIPMAP_COUNT = 16;
79 struct m8_header_t {
80     int version;
81     char name[M8_NAME_LENGTH];
82     unsigned width[M8_MIPMAP_COUNT], height[M8_MIPMAP_COUNT];   // width and height of each mipmap
83     unsigned offsets[M8_MIPMAP_COUNT];             // 16 mip maps stored
84     char animname[M8_NAME_LENGTH];                // next frame in animation chain
85     byte palette[768];                // palette stored in m8
86     int flags;
87     int contents;
88     int value;
89 };
90
91 Image *LoadMipTex(byte *buffer, byte TypeofTex)
92 {
93     int w, h, offset, flags, contents, value;
94     byte palette[768];
95     byte *source;
96
97     PointerInputStream inputStream(buffer);
98
99     if (TypeofTex == HERETIC2_M8) {
100         inputStream.seek(4 + M8_NAME_LENGTH); // version, name
101         w = istream_read_int32_le(inputStream);
102         inputStream.seek(4 * (M8_MIPMAP_COUNT - 1)); // remaining widths
103         h = istream_read_int32_le(inputStream);
104         inputStream.seek(4 * (M8_MIPMAP_COUNT - 1)); // remaining heights
105         offset = istream_read_int32_le(inputStream);
106         inputStream.seek(4 * (M8_MIPMAP_COUNT - 1)); // remaining offsets
107         inputStream.seek(M8_NAME_LENGTH); // animname
108         inputStream.read(palette, 768);
109         flags = istream_read_int32_le(inputStream);
110         contents = istream_read_int32_le(inputStream);
111         value = istream_read_int32_le(inputStream);
112         source = buffer + offset;
113     } else {
114         LoadPCXPalette("pics/colormap.pcx", palette);
115
116         inputStream.seek(WAL_NAME_LENGTH); // name
117         w = istream_read_int32_le(inputStream);
118         h = istream_read_int32_le(inputStream);
119         offset = istream_read_int32_le(inputStream);
120         inputStream.seek(4 * (WAL_MIPMAP_COUNT - 1)); // remaining offsets
121         inputStream.seek(WAL_NAME_LENGTH); // animname
122         flags = istream_read_int32_le(inputStream);
123         contents = istream_read_int32_le(inputStream);
124         value = istream_read_int32_le(inputStream);
125         source = buffer + offset;
126     }
127
128     RGBAImageFlags *image = new RGBAImageFlags(w, h, flags, contents, value);
129
130     byte *dest = image->getRGBAPixels();
131     byte *end = source + (w * h);
132     for (; source != end; ++source, dest += 4) {
133         *(dest + 0) = palette[*source * 3 + 0];
134         *(dest + 1) = palette[*source * 3 + 1];
135         *(dest + 2) = palette[*source * 3 + 2];
136         *(dest + 3) = 255;
137     }
138
139     return image;
140 }
141
142 Image *LoadWal(ArchiveFile &file)
143 {
144     ScopedArchiveBuffer buffer(file);
145     return LoadMipTex(buffer.buffer, QUAKE2_WAL);
146 }
147
148 Image *LoadM8(ArchiveFile &file)
149 {
150     ScopedArchiveBuffer buffer(file);
151     return LoadMipTex(buffer.buffer, HERETIC2_M8);
152 }