source: trunk/src/opengl/glide/sst1/texus/write.c

Last change on this file was 2885, checked in by sandervl, 26 years ago

Created new Voodoo 1 Glide dir

File size: 11.5 KB
Line 
1/*
2** THIS SOFTWARE IS SUBJECT TO COPYRIGHT PROTECTION AND IS OFFERED ONLY
3** PURSUANT TO THE 3DFX GLIDE GENERAL PUBLIC LICENSE. THERE IS NO RIGHT
4** TO USE THE GLIDE TRADEMARK WITHOUT PRIOR WRITTEN PERMISSION OF 3DFX
5** INTERACTIVE, INC. A COPY OF THIS LICENSE MAY BE OBTAINED FROM THE
6** DISTRIBUTOR OR BY CONTACTING 3DFX INTERACTIVE INC(info@3dfx.com).
7** THIS PROGRAM IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
8** EXPRESSED OR IMPLIED. SEE THE 3DFX GLIDE GENERAL PUBLIC LICENSE FOR A
9** FULL TEXT OF THE NON-WARRANTY PROVISIONS.
10**
11** USE, DUPLICATION OR DISCLOSURE BY THE GOVERNMENT IS SUBJECT TO
12** RESTRICTIONS AS SET FORTH IN SUBDIVISION (C)(1)(II) OF THE RIGHTS IN
13** TECHNICAL DATA AND COMPUTER SOFTWARE CLAUSE AT DFARS 252.227-7013,
14** AND/OR IN SIMILAR OR SUCCESSOR CLAUSES IN THE FAR, DOD OR NASA FAR
15** SUPPLEMENT. UNPUBLISHED RIGHTS RESERVED UNDER THE COPYRIGHT LAWS OF
16** THE UNITED STATES.
17**
18** COPYRIGHT 3DFX INTERACTIVE, INC. 1999, ALL RIGHTS RESERVED
19*/
20
21#include <stdio.h>
22#include <stdlib.h>
23#include <string.h>
24#include <math.h>
25
26#include "texusint.h"
27
28/*
29 * The only two file formats we can write are: 3df and tga.
30 */
31static char *Version = "1.1";
32static char* aspect_names[] = { "8 1", "4 1", "2 1", "1 1",
33 "1 2", "1 4", "1 8" };
34
35/*************************************** tga files ****************************/
36/*
37 * Write a tga file from an ARGB8888 mipmap.
38 */
39static FxBool
40txWriteTGA( FILE *stream, TxMip *txMip)
41{
42
43 struct {
44 FxU8 IDLength;
45 FxU8 ColorMapType;
46 FxU8 ImgType;
47 FxU8 CMapStartLo;
48 FxU8 CMapStartHi;
49 FxU8 CMapLengthLo;
50 FxU8 CMapLengthHi;
51 FxU8 CMapDepth;
52 FxU8 XOffSetLo;
53 FxU8 XOffSetHi;
54 FxU8 YOffSetLo;
55 FxU8 YOffSetHi;
56 FxU8 WidthLo;
57 FxU8 WidthHi;
58 FxU8 HeightLo;
59 FxU8 HeightHi;
60 FxU8 PixelDepth;
61 FxU8 ImageDescriptor;
62 } tgaHeader;
63
64 FxU8 *data, *p;
65 FxU32 *data32;
66 int outW, outH, w, h, i;
67
68 if (txMip->format != GR_TEXFMT_ARGB_8888) {
69 txPanic("TGA Image: Write: input format must be ARGB8888.");
70 }
71 if ( stream == NULL ) {
72 txPanic("Bad file handle");
73 return FXFALSE;
74 }
75
76 outW = txMip->width;
77 outH = txMip->height;
78 if (txMip->depth > 1) outW += outW/2;
79
80 tgaHeader.IDLength = 0;
81 tgaHeader.ColorMapType = 0;
82 tgaHeader.ImgType = 0x2;
83 tgaHeader.CMapStartLo = 0;
84 tgaHeader.CMapStartHi = 0;
85 tgaHeader.CMapLengthLo = 0;
86 tgaHeader.CMapLengthHi = 0;
87 tgaHeader.CMapDepth = 0;
88 tgaHeader.XOffSetLo = 0;
89 tgaHeader.XOffSetHi = 0;
90 tgaHeader.YOffSetLo = 0;
91 tgaHeader.YOffSetHi = 0;
92 tgaHeader.WidthHi = (FxU8)((outW >> 8) & 0xFF);
93 tgaHeader.WidthLo = (FxU8) (outW & 0xFF);
94 tgaHeader.HeightHi = (FxU8)((outH >> 8) & 0xFF);
95 tgaHeader.HeightLo = (FxU8) (outH & 0xFF);
96 tgaHeader.PixelDepth = 32;
97 tgaHeader.ImageDescriptor = 0x20; // image always right side up.
98
99
100 if ( fwrite( &tgaHeader, 1, 18, stream ) != 18 ) {
101 txPanic("TGA Header stream write error");
102 return FXFALSE;
103 }
104
105 /*
106 * Allocate memory to hold all mipmaps, and copy the mipmaps.
107 */
108 p = data = txMalloc(outW * outH * 4);
109 memset(data, 0, outW * outH * 4);
110
111 /* Copy level 0 into malloc'd area */
112 txRectCopy( data, outW * 4, txMip->data[0], txMip->width * 4,
113 txMip->width * 4, txMip->height);
114
115 p += (txMip->width * 4);
116
117 /* Copy the rest of the levels to the right of level 0 */
118 w = txMip->width;
119 h = txMip->height;
120 for (i=1; i< txMip->depth; i++) {
121 // printf("Copying: level = %d\n", i);
122 if (w > 1) w >>= 1;
123 if (h > 1) h >>= 1;
124 txRectCopy(p, outW * 4, txMip->data[i], w * 4, w * 4, h);
125 p += ( h * outW * 4);
126 }
127
128 /* Write out the data */
129 data32 = (FxU32 *) data;
130 for (i=outW*outH; i; i--) {
131 putc(((*data32 ) & 0xff) , stream);
132 putc(((*data32 >> 8) & 0xff) , stream);
133 putc(((*data32 >> 16) & 0xff) , stream);
134 putc(((*data32 >> 24) & 0xff) , stream);
135 data32++;
136 }
137 return FXTRUE;
138}
139
140
141/*************************************** 3df files ****************************/
142/* Write word, msb first */
143
144static FxBool
145_txWrite16 (FILE *stream, FxU16 data)
146{
147 FxU8 byte[2];
148
149 byte[0] = (FxU8) ((data >> 8) & 0xFF);
150 byte[1] = (FxU8) ((data ) & 0xFF);
151
152 return (fwrite (byte, 2, 1, stream) != 1) ? FXFALSE : FXTRUE;
153}
154
155/* Write long word, msb first */
156
157static FxBool
158_txWrite32 (FILE *stream, FxU32 data)
159{
160 FxU8 byte[4];
161
162 byte[0] = (FxU8) ((data >> 24) & 0xFF);
163 byte[1] = (FxU8) ((data >> 16) & 0xFF);
164 byte[2] = (FxU8) ((data >> 8) & 0xFF);
165 byte[3] = (FxU8) ((data ) & 0xFF);
166
167 return (fwrite (byte, 4, 1, stream) != 1) ? FXFALSE : FXTRUE;
168}
169
170/* Write NCC table */
171static FxBool
172_txWrite3dfNCCTable (FILE *stream, FxU32 *yab)
173{
174 int i;
175
176 for (i = 0; i < 16; i++)
177 if (!_txWrite16 (stream, (FxU16) (yab[i] & 0x00ff))) return FXFALSE;
178
179 for (i = 0; i < 12; i++)
180 if (!_txWrite16 (stream, (FxU16) (yab[16+i] & 0xffff))) return FXFALSE;
181
182 for (i = 0; i < 12; i++)
183 if (!_txWrite16 (stream, (FxU16) (yab[28+i] & 0xffff))) return FXFALSE;
184
185 return FXTRUE;
186}
187
188static FxBool
189_txWrite3dfPalTable (FILE *stream, FxU32 *pal)
190{
191 int i;
192
193 for (i=0; i<256; i++) {
194 if (!_txWrite32 (stream, pal[i])) return FXFALSE;
195 }
196 return FXTRUE;
197}
198
199static FxBool
200txWrite3df (FILE *stream, TxMip *txMip)
201{
202 FxU32 i;
203 FxU32 n_pixels;
204 int small_lod, large_lod, aspect;
205
206 /* Write out the header */
207 large_lod = (txMip->width > txMip->height) ? txMip->width : txMip->height;
208 small_lod = large_lod >> (txMip->depth - 1);
209 aspect = txAspectRatio(txMip->width, txMip->height);
210
211 // printf("Format = %d\n", txMip->format);
212 // printf("Format = %s\n", Format_Name[txMip->format]);
213
214 // printf("Writing header...\n");
215 if (EOF == fprintf (stream,
216 "3df v%s\n%s\nlod range: %d %d\naspect ratio: %s\n",
217 Version,
218 Format_Name[txMip->format],
219 small_lod,
220 large_lod,
221 aspect_names[aspect])) return FXFALSE;
222
223 /* write out ncc table if necessary */
224 // printf("Writing NCC...\n");
225 if ((txMip->format == GR_TEXFMT_YIQ_422) ||
226 (txMip->format == GR_TEXFMT_AYIQ_8422)) {
227 if (!_txWrite3dfNCCTable (stream, txMip->pal)) return FXFALSE;
228 }
229
230 else if ((txMip->format == GR_TEXFMT_P_8) ||
231 (txMip->format == GR_TEXFMT_AP_88)) {
232 if (!_txWrite3dfPalTable (stream, txMip->pal)) return FXFALSE;
233 }
234
235
236 /* write out mipmap image data */
237 // printf("Writing mipmaps (%d bytes)...\n", txMip->size);
238 if (txMip->format < GR_TEXFMT_16BIT) {
239 n_pixels = txMip->size;
240 if (n_pixels != fwrite (txMip->data[0], 1, n_pixels, stream)) {
241 printf("Bad Bad Bad!\n");
242 return FXFALSE;
243 }
244 }
245 else if (txMip->format < GR_TEXFMT_32BIT) {
246 FxU16* data = (FxU16 *) txMip->data[0];
247 n_pixels = txMip->size >> 1;
248
249 for (i = 0; i < n_pixels; i ++)
250 if (FXFALSE == _txWrite16 (stream, *data++)) return FXFALSE;
251 }
252 else {
253 FxU32* data = (FxU32*) txMip->data[0];
254 n_pixels = txMip->size >> 2;
255
256 for (i = 0; i < n_pixels; i ++)
257 if (FXFALSE == _txWrite32 (stream, *data++)) return FXFALSE;
258 }
259 return FXTRUE;
260}
261
262void
263txMipWrite(TxMip *txMip, char *file, char *ext, int split)
264{
265 int tgaformat;
266 FILE *stream;
267 char filename[128];
268 int i, w, h;
269 TxMip splitImg;
270
271 if ((txMip->width & (txMip->width - 1)) ||
272 (txMip->height & (txMip->height - 1))) {
273 txPanic("txMipWrite: size not power of 2!");
274 }
275
276 if (strcmp(ext, ".tga") && strcmp(ext, ".3df")) {
277 txPanic("txMipWrite: Bad output format");
278 }
279
280 tgaformat = (strcmp(ext, ".tga") == 0);
281 if (tgaformat && (txMip->format != GR_TEXFMT_ARGB_8888)) {
282 txPanic("txMipWrite: TGA format must be ARGB_8888");
283 }
284
285 /* If not split, write out a single file */
286 if (!split) {
287 strcpy(filename, file);
288 strcat(filename, ext);
289 if( txVerbose )
290 {
291 printf("Writing file \"%s\" (format: %s)\n",
292 filename, Format_Name[txMip->format]);
293 }
294 stream = fopen(filename, "wb");
295 if (stream == NULL) {
296 txPanic("Unable to open output file.");
297 }
298 if (tgaformat) {
299 if (!txWriteTGA( stream, txMip)) {
300 txPanic("txMipWrite: Write failed.");
301 }
302 } else {
303 if (!txWrite3df( stream, txMip)) {
304 txPanic("txMipWrite: Write failed.");
305 }
306 }
307 fclose(stream);
308 return;
309 }
310
311 /* Otherwise, we need to write out separate output files */
312 w = txMip->width;
313 h = txMip->height;
314
315 for (i=0; i<txMip->depth; i++) {
316 char suffix[2];
317
318 splitImg = *txMip; // Copy everything first, including palette.
319
320 // Then change stuff.
321 splitImg.format = txMip->format;
322 splitImg.width = w;
323 splitImg.height = h;
324 splitImg.size = w * h * GR_TEXFMT_SIZE( txMip->format );
325 splitImg.depth = 1;
326 splitImg.data[0] = txMip->data[i];
327
328 // manufacture a new name.
329 suffix[0] = '0' + i;
330 suffix[1] = 0;
331 strcpy(filename, file);
332 strcat(filename, suffix);
333 strcat(filename, ext);
334 stream = fopen(filename, "wb");
335 if (stream == NULL) {
336 txPanic("Unable to open output file.");
337 }
338 if (tgaformat) {
339 if (!txWriteTGA( stream, &splitImg)) {
340 txPanic("txMipWrite: Write failed.");
341 }
342 } else {
343 if (!txWrite3df( stream, &splitImg)) {
344 txPanic("txMipWrite: Write failed.");
345 }
346 }
347 fclose(stream);
348 if (w > 1) w >>= 1;
349 if (h > 1) h >>= 1;
350 }
351}
352
353FxBool txWrite( Gu3dfInfo *info, FILE *fp, FxU32 flags )
354{
355 TxMip mip;
356
357 mip.format = info->header.format;
358 mip.width = info->header.width;
359 mip.height = info->header.height;
360#ifdef GLIDE3
361 mip.depth = info->header.large_lod - info->header.small_lod + 1;
362#else
363 mip.depth = info->header.small_lod - info->header.large_lod + 1;
364#endif
365 mip.size = info->mem_required;
366 mip.data[0] = info->data;
367 if( mip.format == GR_TEXFMT_P_8 || mip.format == GR_TEXFMT_AP_88 )
368 {
369 memcpy( mip.pal, info->table.palette.data, sizeof( FxU32 ) * 256 );
370 }
371 if( mip.format == GR_TEXFMT_YIQ_422 || mip.format == GR_TEXFMT_AYIQ_8422 )
372 {
373 txNccToPal( mip.pal, &info->table.nccTable);
374 }
375 switch( flags & TX_WRITE_MASK )
376 {
377 case TX_WRITE_3DF:
378 if( !txWrite3df( fp, &mip ) )
379 return FXFALSE;
380 break;
381 case TX_WRITE_TGA:
382 if( mip.format == GR_TEXFMT_YIQ_422 ||
383 mip.format == GR_TEXFMT_AYIQ_8422 )
384 {
385 txPanic( "Don't know how to write NCC textures\n" );
386 }
387 if( !txWriteTGA( fp, &mip ) )
388 return FXFALSE;
389 break;
390 default:
391 txPanic( "Unknown texture write format" );
392 break;
393 }
394 return FXTRUE;
395}
Note: See TracBrowser for help on using the repository browser.