aboutsummaryrefslogtreecommitdiffstats
path: root/src/jake2/imageio/WAL.java
blob: 1c499ef11198f06d98e70c369037a5194208071d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
/*
 * Created on Nov 18, 2003
 *
 */
package jake2.imageio;

import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;

/**
 * @author cwei
 *
 */
public class WAL {

	public static final int HEADER_SIZE = 100;

	/*		struct wal_header
			{
				char    name[32];        // name of the texture
		 
				uint32  width;           // width (in pixels) of the largest mipmap level
				uint32  height;          // height (in pixels) of the largest mipmap level
		 
				int32   offset[4];       // byte offset of the start of each of the 4 mipmap levels
		
				char    next_name[32];   // name of the next texture in the animation
		
				uint32  flags;           // ?
				uint32  contents;        // ?
				uint32  value;           // ?
			};
	*/
	public static class Header {

		// size of byte arrays
		static final int NAME_SIZE = 32;
		static final int OFFSET_SIZE = 4;

		String name;
		int width;
		int height;
		int[] offset; // file offsets for the 4 mipmap images
		String nextName;
		int flags; // unused
		int contents; // unused
		int value; // unused

		public Header(byte[] headerBytes) {
			if (headerBytes == null || headerBytes.length != HEADER_SIZE) {
				throw new IllegalArgumentException("invalid quake2 wal header");
			}

			ByteBuffer b = ByteBuffer.wrap(headerBytes);
			// is stored as little endian
			b.order(ByteOrder.LITTLE_ENDIAN);

			byte[] tmp = new byte[NAME_SIZE];
			// fill header

			// name
			b.get(tmp);
			try {
				name = new String(tmp, "ISO-8859-1");
			} catch (UnsupportedEncodingException e) {
				name = new String(tmp);
			}
			// width
			width = b.getInt();
			assert(width >= 0) : "unsigned int bug"; // true means ok.
			// height
			height = b.getInt();
			assert(height >= 0) : "unsigned int bug"; // true means ok.
			// 4 offsets
			offset =
				new int[] { b.getInt(), b.getInt(), b.getInt(), b.getInt()};
			// nextName
			b.get(tmp);
			try {
				nextName = new String(tmp, "ISO-8859-1");
			} catch (UnsupportedEncodingException e1) {
				name = new String(tmp);
			}
			// unused entries
			flags = b.getInt();
			contents = b.getInt();
			value = b.getInt();

			// check some attributes
			checkHeader();
		}

		private void checkHeader() {
			// start of mipmaps
			int mipmap0 = HEADER_SIZE;
			int mipmap1 = mipmap0 + getWidth() * getHeight();
			int mipmap2 = mipmap1 + getWidth() / 2 * getHeight() / 2;
			int mipmap3 = mipmap2 + getWidth() / 4 * getHeight() / 4;

			if (offset[0] != mipmap0
				|| offset[1] != mipmap1
				|| offset[2] != mipmap2
				|| offset[3] != mipmap3) {
				throw new IllegalArgumentException("invalid quake2 wal header");
			}
		}

		/**
		 * @return
		 */
		public int getContents() {
			return contents;
		}

		/**
		 * @return
		 */
		public int getFlags() {
			return flags;
		}

		/**
		 * @return
		 */
		public int getHeight() {
			return height;
		}

		/**
		 * @return
		 */
		public String getName() {
			return name;
		}

		/**
		 * @return
		 */
		public String getNextName() {
			return nextName;
		}

		/**
		 * @return
		 */
		public int getOffset(int index) {
			if (index < 0 || index > 3) {
				throw new ArrayIndexOutOfBoundsException("mipmap offset range is 0 to 3");
			}
			return offset[index];
		}

		/**
		 * @return
		 */
		public int getValue() {
			return value;
		}

		/**
		 * @return
		 */
		public int getWidth() {
			return width;
		}

	}
}