1 /* $Id: mine.c,v 1.2 2004-12-19 14:52:48 btb 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
23 static char rcsid[] = "$Id: mine.c,v 1.2 2004-12-19 14:52:48 btb Exp $";
35 #include "bm.h" // for MAX_TEXTURES
47 #include "ui.h" // Because texpage.h need UI_WINDOW type
48 #include "texpage.h" // For texpage_goto_first
56 #define REMOVE_EXT(s) (*(strchr( (s), '.' ))='\0')
58 int CreateDefaultNewSegment();
59 int save_mine_data(CFILE * SaveFile);
60 int save_mine_data_compiled_new(FILE * SaveFile);
62 static char current_tmap_list[MAX_TEXTURES][13];
64 // -----------------------------------------------------------------------------
66 // 1. Write file info, header info, editor info, vertex data, segment data,
67 // and new_segment in that order, marking their file offset.
68 // 2. Go through all the fields and fill in the offset, size, and sizeof
69 // values in the headers.
71 int med_save_mine(char * filename)
74 char ErrorMessage[256];
76 SaveFile = cfopen( filename, CF_WRITE_MODE );
81 _splitpath( filename, NULL, NULL, fname, NULL );
83 sprintf( ErrorMessage, \
84 "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"
87 sprintf( ErrorMessage, "ERROR: Unable to open %s\n", filename );
88 MessageBox( -2, -2, 1, ErrorMessage, "Ok" );
92 save_mine_data(SaveFile);
94 //==================== CLOSE THE FILE =============================
101 // -----------------------------------------------------------------------------
102 // saves to an already-open file
103 int save_mine_data(CFILE * SaveFile)
105 int header_offset, editor_offset, vertex_offset, segment_offset, doors_offset, texture_offset, walls_offset, triggers_offset; //, links_offset;
106 int newseg_verts_offset;
107 int newsegment_offset;
111 warn_if_concave_segments();
113 for (i=0;i<NumTextures;i++)
114 strncpy(current_tmap_list[i], TmapInfo[i].filename, 13);
116 //=================== Calculate offsets into file ==================
118 header_offset = cftell(SaveFile) + sizeof(mine_fileinfo);
119 editor_offset = header_offset + sizeof(mine_header);
120 texture_offset = editor_offset + sizeof(mine_editor);
121 vertex_offset = texture_offset + (13*NumTextures);
122 segment_offset = vertex_offset + (sizeof(vms_vector)*Num_vertices);
123 newsegment_offset = segment_offset + (sizeof(segment)*Num_segments);
124 newseg_verts_offset = newsegment_offset + sizeof(segment);
125 walls_offset = newseg_verts_offset + (sizeof(vms_vector)*8);
126 triggers_offset = walls_offset + (sizeof(wall)*Num_walls);
127 doors_offset = triggers_offset + (sizeof(trigger)*Num_triggers);
129 //===================== SAVE FILE INFO ========================
131 mine_fileinfo.fileinfo_signature= 0x2884;
132 mine_fileinfo.fileinfo_version = MINE_VERSION;
133 mine_fileinfo.fileinfo_sizeof = sizeof(mine_fileinfo);
134 mine_fileinfo.header_offset = header_offset;
135 mine_fileinfo.header_size = sizeof(mine_header);
136 mine_fileinfo.editor_offset = editor_offset;
137 mine_fileinfo.editor_size = sizeof(mine_editor);
138 mine_fileinfo.vertex_offset = vertex_offset;
139 mine_fileinfo.vertex_howmany = Num_vertices;
140 mine_fileinfo.vertex_sizeof = sizeof(vms_vector);
141 mine_fileinfo.segment_offset = segment_offset;
142 mine_fileinfo.segment_howmany = Num_segments;
143 mine_fileinfo.segment_sizeof = sizeof(segment);
144 mine_fileinfo.newseg_verts_offset = newseg_verts_offset;
145 mine_fileinfo.newseg_verts_howmany = 8;
146 mine_fileinfo.newseg_verts_sizeof = sizeof(vms_vector);
147 mine_fileinfo.texture_offset = texture_offset;
148 mine_fileinfo.texture_howmany = NumTextures;
149 mine_fileinfo.texture_sizeof = 13; // num characters in a name
150 mine_fileinfo.walls_offset = walls_offset;
151 mine_fileinfo.walls_howmany = Num_walls;
152 mine_fileinfo.walls_sizeof = sizeof(wall);
153 mine_fileinfo.triggers_offset = triggers_offset;
154 mine_fileinfo.triggers_howmany = Num_triggers;
155 mine_fileinfo.triggers_sizeof = sizeof(trigger);
157 // Write the fileinfo
158 cfwrite( &mine_fileinfo, sizeof(mine_fileinfo), 1, SaveFile );
160 //===================== SAVE HEADER INFO ========================
162 mine_header.num_vertices = Num_vertices;
163 mine_header.num_segments = Num_segments;
165 // Write the editor info
166 if (header_offset != cftell(SaveFile))
167 Error( "OFFSETS WRONG IN MINE.C!" );
169 cfwrite( &mine_header, sizeof(mine_header), 1, SaveFile );
171 //===================== SAVE EDITOR INFO ==========================
172 mine_editor.current_seg = Cursegp - Segments;
173 mine_editor.newsegment_offset = newsegment_offset;
174 mine_editor.newsegment_size = sizeof(segment);
176 // Next 3 vars added 10/07 by JAS
177 mine_editor.Curside = Curside;
179 mine_editor.Markedsegp = Markedsegp - Segments;
181 mine_editor.Markedsegp = -1;
182 mine_editor.Markedside = Markedside;
184 mine_editor.Groupsegp[i] = Groupsegp[i] - Segments;
186 mine_editor.Groupside[i] = Groupside[i];
188 if (editor_offset != cftell(SaveFile))
189 Error( "OFFSETS WRONG IN MINE.C!" );
190 cfwrite( &mine_editor, sizeof(mine_editor), 1, SaveFile );
192 //===================== SAVE TEXTURE INFO ==========================
194 if (texture_offset != cftell(SaveFile))
195 Error( "OFFSETS WRONG IN MINE.C!" );
196 cfwrite( current_tmap_list, 13, NumTextures, SaveFile );
198 //===================== SAVE VERTEX INFO ==========================
200 if (vertex_offset != cftell(SaveFile))
201 Error( "OFFSETS WRONG IN MINE.C!" );
202 cfwrite( Vertices, sizeof(vms_vector), Num_vertices, SaveFile );
204 //===================== SAVE SEGMENT INFO =========================
206 if (segment_offset != cftell(SaveFile))
207 Error( "OFFSETS WRONG IN MINE.C!" );
208 cfwrite( Segments, sizeof(segment), Num_segments, SaveFile );
210 //===================== SAVE NEWSEGMENT INFO ======================
212 if (newsegment_offset != cftell(SaveFile))
213 Error( "OFFSETS WRONG IN MINE.C!" );
214 cfwrite( &New_segment, sizeof(segment), 1, SaveFile );
216 if (newseg_verts_offset != cftell(SaveFile))
217 Error( "OFFSETS WRONG IN MINE.C!" );
218 cfwrite( &Vertices[New_segment.verts[0]], sizeof(vms_vector), 8, SaveFile );
220 //==================== CLOSE THE FILE =============================
228 #define COMPILED_MINE_VERSION 0
230 void dump_fix_as_short( fix value, int nbits, CFILE * SaveFile )
235 int_value = (int)(value>>nbits);
236 if( int_value > 0x7fff ) {
237 short_value = 0x7fff;
238 mprintf((1, "Warning: Fix (%8x) won't fit in short. Saturating to %8x.\n", int_value, short_value<<nbits));
240 else if( int_value < -0x7fff ) {
241 short_value = -0x7fff;
242 mprintf((1, "Warning: Fix (%8x) won't fit in short. Saturating to %8x.\n", int_value, short_value<<nbits));
245 short_value = (short)int_value;
247 cfwrite( &short_value, sizeof(short_value), 1, SaveFile );
250 //version of dump for unsigned values
251 void dump_fix_as_ushort( fix value, int nbits, CFILE * SaveFile )
257 mprintf((1, "Warning: fix (%8x) is signed...setting to zero.\n", value));
258 Int3(); //hey---show this to Matt
262 int_value = value >> nbits;
264 if( int_value > 0xffff ) {
265 short_value = 0xffff;
266 mprintf((1, "Warning: Fix (%8x) won't fit in unsigned short. Saturating to %8x.\n", int_value, short_value<<nbits));
269 short_value = int_value;
271 cfwrite( &short_value, sizeof(short_value), 1, SaveFile );
274 int New_file_format_save = 1;
276 // -----------------------------------------------------------------------------
277 // saves compiled mine data to an already-open file...
278 int save_mine_data_compiled(FILE * SaveFile)
280 short i,segnum,sidenum;
281 ubyte version = COMPILED_MINE_VERSION;
284 if (New_file_format_save)
285 return save_mine_data_compiled_new(SaveFile);
289 warn_if_concave_segments();
291 if (Highest_segment_index >= MAX_GAME_SEGMENTS) {
293 sprintf(message, "Error: Too many segments (%i > %i) for game (not editor)", Highest_segment_index+1, MAX_GAME_SEGMENTS);
294 MessageBox( -2, -2, 1, message, "Ok" );
297 if (Highest_vertex_index >= MAX_GAME_VERTICES) {
299 sprintf(message, "Error: Too many vertices (%i > %i) for game (not editor)", Highest_vertex_index+1, MAX_GAME_VERTICES);
300 MessageBox( -2, -2, 1, message, "Ok" );
303 //=============================== Writing part ==============================
304 cfwrite( &version, sizeof(ubyte), 1, SaveFile ); // 1 byte = compiled version
305 cfwrite( &Num_vertices, sizeof(int), 1, SaveFile ); // 4 bytes = Num_vertices
306 cfwrite( &Num_segments, sizeof(int), 1, SaveFile ); // 4 bytes = Num_segments
307 cfwrite( Vertices, sizeof(vms_vector), Num_vertices, SaveFile );
309 for (segnum=0; segnum<Num_segments; segnum++ ) {
310 // Write short Segments[segnum].children[MAX_SIDES_PER_SEGMENT]
311 cfwrite( &Segments[segnum].children, sizeof(short), MAX_SIDES_PER_SEGMENT, SaveFile );
312 // Write short Segments[segnum].verts[MAX_VERTICES_PER_SEGMENT]
313 cfwrite( &Segments[segnum].verts, sizeof(short), MAX_VERTICES_PER_SEGMENT, SaveFile );
314 // Write ubyte Segments[segnum].special
315 cfwrite( &Segments[segnum].special, sizeof(ubyte), 1, SaveFile );
316 // Write byte Segments[segnum].matcen_num
317 cfwrite( &Segments[segnum].matcen_num, sizeof(ubyte), 1, SaveFile );
318 // Write short Segments[segnum].value
319 cfwrite( &Segments[segnum].value, sizeof(short), 1, SaveFile );
320 // Write fix Segments[segnum].static_light (shift down 5 bits, write as short)
321 dump_fix_as_ushort( Segments[segnum].static_light, 4, SaveFile );
322 //cfwrite( &Segments[segnum].static_light , sizeof(fix), 1, SaveFile );
324 // Write the walls as a 6 byte array
325 for (sidenum=0; sidenum<MAX_SIDES_PER_SEGMENT; sidenum++ ) {
328 if (Segments[segnum].sides[sidenum].wall_num<0)
329 wallnum = 255; // Use 255 to mark no walls
331 wallnum = Segments[segnum].sides[sidenum].wall_num;
332 Assert( wallnum < 255 ); // Get John or Mike.. can only store up to 255 walls!!!
334 byte_wallnum = (ubyte)wallnum;
335 cfwrite( &byte_wallnum, sizeof(ubyte), 1, SaveFile );
338 for (sidenum=0; sidenum<MAX_SIDES_PER_SEGMENT; sidenum++ ) {
339 if ( (Segments[segnum].children[sidenum]==-1) || (Segments[segnum].sides[sidenum].wall_num!=-1) ) {
340 // Write short Segments[segnum].sides[sidenum].tmap_num;
341 cfwrite( &Segments[segnum].sides[sidenum].tmap_num, sizeof(short), 1, SaveFile );
342 // Write short Segments[segnum].sides[sidenum].tmap_num2;
343 cfwrite( &Segments[segnum].sides[sidenum].tmap_num2, sizeof(short), 1, SaveFile );
344 // Write uvl Segments[segnum].sides[sidenum].uvls[4] (u,v>>5, write as short, l>>1 write as short)
345 for (i=0; i<4; i++ ) {
346 dump_fix_as_short( Segments[segnum].sides[sidenum].uvls[i].u, 5, SaveFile );
347 dump_fix_as_short( Segments[segnum].sides[sidenum].uvls[i].v, 5, SaveFile );
348 dump_fix_as_ushort( Segments[segnum].sides[sidenum].uvls[i].l, 1, SaveFile );
349 //cfwrite( &Segments[segnum].sides[sidenum].uvls[i].l, sizeof(fix), 1, SaveFile );
359 // -----------------------------------------------------------------------------
360 // saves compiled mine data to an already-open file...
361 int save_mine_data_compiled_new(FILE * SaveFile)
363 short i, segnum, sidenum, temp_short;
364 ubyte version = COMPILED_MINE_VERSION;
368 warn_if_concave_segments();
370 if (Highest_segment_index >= MAX_GAME_SEGMENTS) {
372 sprintf(message, "Error: Too many segments (%i > %i) for game (not editor)", Highest_segment_index+1, MAX_GAME_SEGMENTS);
373 MessageBox( -2, -2, 1, message, "Ok" );
376 if (Highest_vertex_index >= MAX_GAME_VERTICES) {
378 sprintf(message, "Error: Too many vertices (%i > %i) for game (not editor)", Highest_vertex_index+1, MAX_GAME_VERTICES);
379 MessageBox( -2, -2, 1, message, "Ok" );
382 //=============================== Writing part ==============================
383 cfwrite( &version, sizeof(ubyte), 1, SaveFile ); // 1 byte = compiled version
384 temp_short = Num_vertices;
385 cfwrite( &temp_short, sizeof(short), 1, SaveFile ); // 2 bytes = Num_vertices
386 temp_short = Num_segments;
387 cfwrite( &temp_short, sizeof(short), 1, SaveFile ); // 2 bytes = Num_segments
388 cfwrite( Vertices, sizeof(vms_vector), Num_vertices, SaveFile );
390 for (segnum=0; segnum<Num_segments; segnum++ ) {
392 for (sidenum=0; sidenum<MAX_SIDES_PER_SEGMENT; sidenum++) {
393 if (Segments[segnum].children[sidenum] != -1)
394 bit_mask |= (1 << sidenum);
397 if ((Segments[segnum].special != 0) || (Segments[segnum].matcen_num != 0) || (Segments[segnum].value != 0))
398 bit_mask |= (1 << MAX_SIDES_PER_SEGMENT);
400 cfwrite( &bit_mask, sizeof(ubyte), 1, SaveFile );
402 for (sidenum=0; sidenum<MAX_SIDES_PER_SEGMENT; sidenum++) {
403 if (bit_mask & (1 << sidenum))
404 cfwrite( &Segments[segnum].children[sidenum], sizeof(short), 1, SaveFile );
407 cfwrite( &Segments[segnum].verts, sizeof(short), MAX_VERTICES_PER_SEGMENT, SaveFile );
409 if (bit_mask & (1 << MAX_SIDES_PER_SEGMENT)) {
410 cfwrite( &Segments[segnum].special, sizeof(ubyte), 1, SaveFile );
411 cfwrite( &Segments[segnum].matcen_num, sizeof(ubyte), 1, SaveFile );
412 cfwrite( &Segments[segnum].value, sizeof(short), 1, SaveFile );
415 dump_fix_as_ushort( Segments[segnum].static_light, 4, SaveFile );
417 // Write the walls as a 6 byte array
419 for (sidenum=0; sidenum<MAX_SIDES_PER_SEGMENT; sidenum++ ) {
421 if (Segments[segnum].sides[sidenum].wall_num >= 0) {
422 bit_mask |= (1 << sidenum);
423 wallnum = Segments[segnum].sides[sidenum].wall_num;
424 Assert( wallnum < 255 ); // Get John or Mike.. can only store up to 255 walls!!!
427 cfwrite( &bit_mask, sizeof(ubyte), 1, SaveFile );
429 for (sidenum=0; sidenum<MAX_SIDES_PER_SEGMENT; sidenum++ ) {
430 if (bit_mask & (1 << sidenum))
431 cfwrite( &Segments[segnum].sides[sidenum].wall_num, sizeof(ubyte), 1, SaveFile );
434 for (sidenum=0; sidenum<MAX_SIDES_PER_SEGMENT; sidenum++ ) {
435 if ( (Segments[segnum].children[sidenum]==-1) || (Segments[segnum].sides[sidenum].wall_num!=-1) ) {
436 ushort tmap_num, tmap_num2;
438 tmap_num = Segments[segnum].sides[sidenum].tmap_num;
439 tmap_num2 = Segments[segnum].sides[sidenum].tmap_num2;
443 cfwrite( &tmap_num, sizeof(ushort), 1, SaveFile );
445 cfwrite( &tmap_num2, sizeof(ushort), 1, SaveFile );
447 for (i=0; i<4; i++ ) {
448 dump_fix_as_short( Segments[segnum].sides[sidenum].uvls[i].u, 5, SaveFile );
449 dump_fix_as_short( Segments[segnum].sides[sidenum].uvls[i].v, 5, SaveFile );
450 dump_fix_as_ushort( Segments[segnum].sides[sidenum].uvls[i].l, 1, SaveFile );