1 /* $Id: mine.c,v 1.7 2005-02-25 14:55:49 chris Exp $ */
3 THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
4 SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO
5 END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
6 ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
7 IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
8 SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
9 FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
10 CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS
11 AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
12 COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED.
17 * Mine specific editing functions, such as load_mine, save_mine
22 static char rcsid[] = "$Id: mine.c,v 1.7 2005-02-25 14:55:49 chris Exp $";
39 #include "bm.h" // for MAX_TEXTURES
51 #include "ui.h" // Because texpage.h need UI_WINDOW type
52 #include "texpage.h" // For texpage_goto_first
59 #define REMOVE_EXT(s) (*(strchr( (s), '.' ))='\0')
61 int CreateDefaultNewSegment();
62 int save_mine_data(CFILE * SaveFile);
63 int save_mine_data_compiled_new(FILE * SaveFile);
65 static char current_tmap_list[MAX_TEXTURES][13];
67 // -----------------------------------------------------------------------------
69 // 1. Write file info, header info, editor info, vertex data, segment data,
70 // and new_segment in that order, marking their file offset.
71 // 2. Go through all the fields and fill in the offset, size, and sizeof
72 // values in the headers.
74 int med_save_mine(char * filename)
77 char ErrorMessage[256];
79 SaveFile = cfopen( filename, CF_WRITE_MODE );
82 #if 0 //ndef __linux__
84 _splitpath( filename, NULL, NULL, fname, NULL );
86 sprintf( ErrorMessage, \
87 "ERROR: Cannot write to '%s'.\nYou probably need to check out a locked\nversion of the file. You should save\nthis under a different filename, and then\ncheck out a locked copy by typing\n\'co -l %s.lvl'\nat the DOS prompt.\n"
90 sprintf( ErrorMessage, "ERROR: Unable to open %s\n", filename );
91 MessageBox( -2, -2, 1, ErrorMessage, "Ok" );
95 save_mine_data(SaveFile);
97 //==================== CLOSE THE FILE =============================
104 // -----------------------------------------------------------------------------
105 // saves to an already-open file
106 int save_mine_data(CFILE * SaveFile)
108 int header_offset, editor_offset, vertex_offset, segment_offset, doors_offset, texture_offset, walls_offset, triggers_offset; //, links_offset;
109 int newseg_verts_offset;
110 int newsegment_offset;
114 warn_if_concave_segments();
116 for (i=0;i<NumTextures;i++)
117 strncpy(current_tmap_list[i], TmapInfo[i].filename, 13);
119 //=================== Calculate offsets into file ==================
121 header_offset = cftell(SaveFile) + sizeof(mine_fileinfo);
122 editor_offset = header_offset + sizeof(mine_header);
123 texture_offset = editor_offset + sizeof(mine_editor);
124 vertex_offset = texture_offset + (13*NumTextures);
125 segment_offset = vertex_offset + (sizeof(vms_vector)*Num_vertices);
126 newsegment_offset = segment_offset + (sizeof(segment)*Num_segments);
127 newseg_verts_offset = newsegment_offset + sizeof(segment);
128 walls_offset = newseg_verts_offset + (sizeof(vms_vector)*8);
129 triggers_offset = walls_offset + (sizeof(wall)*Num_walls);
130 doors_offset = triggers_offset + (sizeof(trigger)*Num_triggers);
132 //===================== SAVE FILE INFO ========================
134 mine_fileinfo.fileinfo_signature= 0x2884;
135 mine_fileinfo.fileinfo_version = MINE_VERSION;
136 mine_fileinfo.fileinfo_sizeof = sizeof(mine_fileinfo);
137 mine_fileinfo.header_offset = header_offset;
138 mine_fileinfo.header_size = sizeof(mine_header);
139 mine_fileinfo.editor_offset = editor_offset;
140 mine_fileinfo.editor_size = sizeof(mine_editor);
141 mine_fileinfo.vertex_offset = vertex_offset;
142 mine_fileinfo.vertex_howmany = Num_vertices;
143 mine_fileinfo.vertex_sizeof = sizeof(vms_vector);
144 mine_fileinfo.segment_offset = segment_offset;
145 mine_fileinfo.segment_howmany = Num_segments;
146 mine_fileinfo.segment_sizeof = sizeof(segment);
147 mine_fileinfo.newseg_verts_offset = newseg_verts_offset;
148 mine_fileinfo.newseg_verts_howmany = 8;
149 mine_fileinfo.newseg_verts_sizeof = sizeof(vms_vector);
150 mine_fileinfo.texture_offset = texture_offset;
151 mine_fileinfo.texture_howmany = NumTextures;
152 mine_fileinfo.texture_sizeof = 13; // num characters in a name
153 mine_fileinfo.walls_offset = walls_offset;
154 mine_fileinfo.walls_howmany = Num_walls;
155 mine_fileinfo.walls_sizeof = sizeof(wall);
156 mine_fileinfo.triggers_offset = triggers_offset;
157 mine_fileinfo.triggers_howmany = Num_triggers;
158 mine_fileinfo.triggers_sizeof = sizeof(trigger);
160 // Write the fileinfo
161 cfwrite( &mine_fileinfo, sizeof(mine_fileinfo), 1, SaveFile );
163 //===================== SAVE HEADER INFO ========================
165 mine_header.num_vertices = Num_vertices;
166 mine_header.num_segments = Num_segments;
168 // Write the editor info
169 if (header_offset != cftell(SaveFile))
170 Error( "OFFSETS WRONG IN MINE.C!" );
172 cfwrite( &mine_header, sizeof(mine_header), 1, SaveFile );
174 //===================== SAVE EDITOR INFO ==========================
175 mine_editor.current_seg = Cursegp - Segments;
176 mine_editor.newsegment_offset = newsegment_offset;
177 mine_editor.newsegment_size = sizeof(segment);
179 // Next 3 vars added 10/07 by JAS
180 mine_editor.Curside = Curside;
182 mine_editor.Markedsegp = Markedsegp - Segments;
184 mine_editor.Markedsegp = -1;
185 mine_editor.Markedside = Markedside;
187 mine_editor.Groupsegp[i] = Groupsegp[i] - Segments;
189 mine_editor.Groupside[i] = Groupside[i];
191 if (editor_offset != cftell(SaveFile))
192 Error( "OFFSETS WRONG IN MINE.C!" );
193 cfwrite( &mine_editor, sizeof(mine_editor), 1, SaveFile );
195 //===================== SAVE TEXTURE INFO ==========================
197 if (texture_offset != cftell(SaveFile))
198 Error( "OFFSETS WRONG IN MINE.C!" );
199 cfwrite( current_tmap_list, 13, NumTextures, SaveFile );
201 //===================== SAVE VERTEX INFO ==========================
203 if (vertex_offset != cftell(SaveFile))
204 Error( "OFFSETS WRONG IN MINE.C!" );
205 cfwrite( Vertices, sizeof(vms_vector), Num_vertices, SaveFile );
207 //===================== SAVE SEGMENT INFO =========================
209 if (segment_offset != cftell(SaveFile))
210 Error( "OFFSETS WRONG IN MINE.C!" );
211 cfwrite( Segments, sizeof(segment), Num_segments, SaveFile );
213 //===================== SAVE NEWSEGMENT INFO ======================
215 if (newsegment_offset != cftell(SaveFile))
216 Error( "OFFSETS WRONG IN MINE.C!" );
217 cfwrite( &New_segment, sizeof(segment), 1, SaveFile );
219 if (newseg_verts_offset != cftell(SaveFile))
220 Error( "OFFSETS WRONG IN MINE.C!" );
221 cfwrite( &Vertices[New_segment.verts[0]], sizeof(vms_vector), 8, SaveFile );
223 //==================== CLOSE THE FILE =============================
231 #define COMPILED_MINE_VERSION 0
233 void dump_fix_as_short( fix value, int nbits, CFILE * SaveFile )
238 int_value = (int)(value>>nbits);
239 if( int_value > 0x7fff ) {
240 short_value = 0x7fff;
241 mprintf((1, "Warning: Fix (%8x) won't fit in short. Saturating to %8x.\n", int_value, short_value<<nbits));
243 else if( int_value < -0x7fff ) {
244 short_value = -0x7fff;
245 mprintf((1, "Warning: Fix (%8x) won't fit in short. Saturating to %8x.\n", int_value, short_value<<nbits));
248 short_value = (short)int_value;
250 cfwrite( &short_value, sizeof(short_value), 1, SaveFile );
253 //version of dump for unsigned values
254 void dump_fix_as_ushort( fix value, int nbits, CFILE * SaveFile )
260 mprintf((1, "Warning: fix (%8x) is signed...setting to zero.\n", value));
261 Int3(); //hey---show this to Matt
265 int_value = value >> nbits;
267 if( int_value > 0xffff ) {
268 short_value = 0xffff;
269 mprintf((1, "Warning: Fix (%8x) won't fit in unsigned short. Saturating to %8x.\n", int_value, short_value<<nbits));
272 short_value = int_value;
274 cfwrite( &short_value, sizeof(short_value), 1, SaveFile );
277 int New_file_format_save = 1;
279 // -----------------------------------------------------------------------------
280 // saves compiled mine data to an already-open file...
281 int save_mine_data_compiled(FILE * SaveFile)
283 short i,segnum,sidenum;
284 ubyte version = COMPILED_MINE_VERSION;
287 if (New_file_format_save)
288 return save_mine_data_compiled_new(SaveFile);
292 warn_if_concave_segments();
294 if (Highest_segment_index >= MAX_SEGMENTS) {
296 sprintf(message, "Error: Too many segments (%i > %i) for game (not editor)", Highest_segment_index+1, MAX_SEGMENTS);
297 MessageBox( -2, -2, 1, message, "Ok" );
300 if (Highest_vertex_index >= MAX_VERTICES) {
302 sprintf(message, "Error: Too many vertices (%i > %i) for game (not editor)", Highest_vertex_index+1, MAX_VERTICES);
303 MessageBox( -2, -2, 1, message, "Ok" );
306 //=============================== Writing part ==============================
307 cfwrite( &version, sizeof(ubyte), 1, SaveFile ); // 1 byte = compiled version
308 cfwrite( &Num_vertices, sizeof(int), 1, SaveFile ); // 4 bytes = Num_vertices
309 cfwrite( &Num_segments, sizeof(int), 1, SaveFile ); // 4 bytes = Num_segments
310 cfwrite( Vertices, sizeof(vms_vector), Num_vertices, SaveFile );
312 for (segnum=0; segnum<Num_segments; segnum++ ) {
313 // Write short Segments[segnum].children[MAX_SIDES_PER_SEGMENT]
314 cfwrite( &Segments[segnum].children, sizeof(short), MAX_SIDES_PER_SEGMENT, SaveFile );
315 // Write short Segments[segnum].verts[MAX_VERTICES_PER_SEGMENT]
316 cfwrite( &Segments[segnum].verts, sizeof(short), MAX_VERTICES_PER_SEGMENT, SaveFile );
317 // Write ubyte Segment2s[segnum].special
318 cfwrite(&Segment2s[segnum].special, sizeof(ubyte), 1, SaveFile);
319 // Write byte Segment2s[segnum].matcen_num
320 cfwrite(&Segment2s[segnum].matcen_num, sizeof(ubyte), 1, SaveFile);
321 // Write short Segment2s[segnum].value
322 cfwrite(&Segment2s[segnum].value, sizeof(short), 1, SaveFile);
323 // Write fix Segment2s[segnum].static_light (shift down 5 bits, write as short)
324 dump_fix_as_ushort(Segment2s[segnum].static_light, 4, SaveFile);
325 //cfwrite(&Segment2s[segnum].static_light, sizeof(fix), 1, SaveFile);
327 // Write the walls as a 6 byte array
328 for (sidenum=0; sidenum<MAX_SIDES_PER_SEGMENT; sidenum++ ) {
331 if (Segments[segnum].sides[sidenum].wall_num<0)
332 wallnum = 255; // Use 255 to mark no walls
334 wallnum = Segments[segnum].sides[sidenum].wall_num;
335 Assert( wallnum < 255 ); // Get John or Mike.. can only store up to 255 walls!!!
337 byte_wallnum = (ubyte)wallnum;
338 cfwrite( &byte_wallnum, sizeof(ubyte), 1, SaveFile );
341 for (sidenum=0; sidenum<MAX_SIDES_PER_SEGMENT; sidenum++ ) {
342 if ( (Segments[segnum].children[sidenum]==-1) || (Segments[segnum].sides[sidenum].wall_num!=-1) ) {
343 // Write short Segments[segnum].sides[sidenum].tmap_num;
344 cfwrite( &Segments[segnum].sides[sidenum].tmap_num, sizeof(short), 1, SaveFile );
345 // Write short Segments[segnum].sides[sidenum].tmap_num2;
346 cfwrite( &Segments[segnum].sides[sidenum].tmap_num2, sizeof(short), 1, SaveFile );
347 // Write uvl Segments[segnum].sides[sidenum].uvls[4] (u,v>>5, write as short, l>>1 write as short)
348 for (i=0; i<4; i++ ) {
349 dump_fix_as_short( Segments[segnum].sides[sidenum].uvls[i].u, 5, SaveFile );
350 dump_fix_as_short( Segments[segnum].sides[sidenum].uvls[i].v, 5, SaveFile );
351 dump_fix_as_ushort( Segments[segnum].sides[sidenum].uvls[i].l, 1, SaveFile );
352 //cfwrite( &Segments[segnum].sides[sidenum].uvls[i].l, sizeof(fix), 1, SaveFile );
362 // -----------------------------------------------------------------------------
363 // saves compiled mine data to an already-open file...
364 int save_mine_data_compiled_new(FILE * SaveFile)
366 short i, segnum, sidenum, temp_short;
367 ubyte version = COMPILED_MINE_VERSION;
371 warn_if_concave_segments();
373 if (Highest_segment_index >= MAX_SEGMENTS) {
375 sprintf(message, "Error: Too many segments (%i > %i) for game (not editor)", Highest_segment_index+1, MAX_SEGMENTS);
376 MessageBox( -2, -2, 1, message, "Ok" );
379 if (Highest_vertex_index >= MAX_VERTICES) {
381 sprintf(message, "Error: Too many vertices (%i > %i) for game (not editor)", Highest_vertex_index+1, MAX_VERTICES);
382 MessageBox( -2, -2, 1, message, "Ok" );
385 //=============================== Writing part ==============================
386 cfwrite( &version, sizeof(ubyte), 1, SaveFile ); // 1 byte = compiled version
387 temp_short = Num_vertices;
388 cfwrite( &temp_short, sizeof(short), 1, SaveFile ); // 2 bytes = Num_vertices
389 temp_short = Num_segments;
390 cfwrite( &temp_short, sizeof(short), 1, SaveFile ); // 2 bytes = Num_segments
391 cfwrite( Vertices, sizeof(vms_vector), Num_vertices, SaveFile );
393 for (segnum=0; segnum<Num_segments; segnum++ ) {
395 for (sidenum=0; sidenum<MAX_SIDES_PER_SEGMENT; sidenum++) {
396 if (Segments[segnum].children[sidenum] != -1)
397 bit_mask |= (1 << sidenum);
400 if ((Segment2s[segnum].special != 0) || (Segment2s[segnum].matcen_num != 0) || (Segment2s[segnum].value != 0))
401 bit_mask |= (1 << MAX_SIDES_PER_SEGMENT);
403 cfwrite( &bit_mask, sizeof(ubyte), 1, SaveFile );
405 for (sidenum=0; sidenum<MAX_SIDES_PER_SEGMENT; sidenum++) {
406 if (bit_mask & (1 << sidenum))
407 cfwrite( &Segments[segnum].children[sidenum], sizeof(short), 1, SaveFile );
410 cfwrite( &Segments[segnum].verts, sizeof(short), MAX_VERTICES_PER_SEGMENT, SaveFile );
412 if (bit_mask & (1 << MAX_SIDES_PER_SEGMENT)) {
413 cfwrite(&Segment2s[segnum].special, sizeof(ubyte), 1, SaveFile);
414 cfwrite(&Segment2s[segnum].matcen_num, sizeof(ubyte), 1, SaveFile);
415 cfwrite(&Segment2s[segnum].value, sizeof(short), 1, SaveFile);
418 dump_fix_as_ushort(Segment2s[segnum].static_light, 4, SaveFile);
420 // Write the walls as a 6 byte array
422 for (sidenum=0; sidenum<MAX_SIDES_PER_SEGMENT; sidenum++ ) {
424 if (Segments[segnum].sides[sidenum].wall_num >= 0) {
425 bit_mask |= (1 << sidenum);
426 wallnum = Segments[segnum].sides[sidenum].wall_num;
427 Assert( wallnum < 255 ); // Get John or Mike.. can only store up to 255 walls!!!
430 cfwrite( &bit_mask, sizeof(ubyte), 1, SaveFile );
432 for (sidenum=0; sidenum<MAX_SIDES_PER_SEGMENT; sidenum++ ) {
433 if (bit_mask & (1 << sidenum))
434 cfwrite( &Segments[segnum].sides[sidenum].wall_num, sizeof(ubyte), 1, SaveFile );
437 for (sidenum=0; sidenum<MAX_SIDES_PER_SEGMENT; sidenum++ ) {
438 if ( (Segments[segnum].children[sidenum]==-1) || (Segments[segnum].sides[sidenum].wall_num!=-1) ) {
439 ushort tmap_num, tmap_num2;
441 tmap_num = Segments[segnum].sides[sidenum].tmap_num;
442 tmap_num2 = Segments[segnum].sides[sidenum].tmap_num2;
446 cfwrite( &tmap_num, sizeof(ushort), 1, SaveFile );
448 cfwrite( &tmap_num2, sizeof(ushort), 1, SaveFile );
450 for (i=0; i<4; i++ ) {
451 dump_fix_as_short( Segments[segnum].sides[sidenum].uvls[i].u, 5, SaveFile );
452 dump_fix_as_short( Segments[segnum].sides[sidenum].uvls[i].v, 5, SaveFile );
453 dump_fix_as_ushort( Segments[segnum].sides[sidenum].uvls[i].l, 1, SaveFile );