00001
00018
00019
00020 #include "lev_files.h"
00021
00022 #include <sys/stat.h>
00023 #include "globals.h"
00024 #include "arr_utils.h"
00025 #include "memfile.h"
00026 #include "obj_column_def.h"
00027 #include "obj_slabs.h"
00028 #include "obj_things.h"
00029 #include "bulcommn.h"
00030 #include "obj_column.h"
00031 #include "lev_data.h"
00032 #include "lev_script.h"
00033
00037 typedef short (*mapfile_io_func)(struct LEVEL *lvl,char *fname);
00038
00042 typedef short (*mapfile_iomsg_func)(struct LEVEL *lvl,struct MEMORY_FILE *mem,char *err_msg);
00043
00049 char *levfile_error(int errcode)
00050 {
00051
00052 static char *const errors[] = {
00053 "File too small",
00054 "Bad data",
00055 "Bad file name",
00056 "Cant allocate mem",
00057 "Cant open for writing",
00058 "Write error",
00059 "Verification error",
00060 "Internal error",
00061 "Map rejected",
00062 };
00063 static char *const warnings[] = {
00064 "Bad items count",
00065 "Unknown problem",
00066 };
00067
00068 if ((errcode>ERR_FILE_TOOSMLL)&&(errcode<WARN_BAD_COUNT))
00069 {
00070 return memfile_error(errcode);
00071 }
00072 if (errcode<=ERR_FILE_TOOSMLL)
00073 {
00074 errcode = ERR_FILE_TOOSMLL-errcode;
00075
00076
00077 const int max_code=(sizeof(errors)/sizeof(*errors) - 1);
00078 if ((errcode < 0) || (errcode > max_code) )
00079 errcode = max_code;
00080 return errors[errcode];
00081 }
00082 if (errcode>=WARN_BAD_COUNT)
00083 {
00084 errcode = WARN_BAD_COUNT-errcode;
00085 const int max_code=(sizeof(warnings)/sizeof(*warnings) - 1);
00086
00087
00088 if ((errcode < 0) || (errcode > max_code) )
00089 errcode = max_code;
00090 return warnings[errcode];
00091 }
00092 }
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00173 short load_tng(struct LEVEL *lvl,char *fname)
00174 {
00175 message_log(" load_tng: started");
00176 int tng_num;
00177 int i, j;
00178 unsigned char *thing;
00179 if (lvl==NULL) return ERR_INTERNAL;
00180
00181 struct MEMORY_FILE *mem;
00182 short result;
00183 result = memfile_readnew(&mem,fname,MAX_FILE_SIZE);
00184 if (result != MFILE_OK)
00185 return result;
00186
00187 if (mem->len<SIZEOF_DK_TNG_HEADER)
00188 { memfile_free(&mem); return ERR_FILE_TOOSMLL; }
00189 result=ERR_NONE;
00190
00191 tng_num = read_int16_le_buf(mem->content);
00192
00193 unsigned long expect_size=tng_num*SIZEOF_DK_TNG_REC+SIZEOF_DK_TNG_HEADER;
00194 if (mem->len != expect_size)
00195 {
00196 message_log(" load_tng: File length %d, expected %lu (%d things)",mem->len,expect_size,tng_num);
00197
00198 if (((lvl->optns.load_redundant_objects&EXLD_THING)==EXLD_THING)||(mem->len < expect_size))
00199 tng_num=(mem->len-SIZEOF_DK_TNG_HEADER)/SIZEOF_DK_TNG_REC;
00200 result=WARN_BAD_COUNT;
00201 }
00202
00203 for (i=0; i < tng_num; i++)
00204 {
00205 unsigned char *thing = create_thing_empty();
00206 int offs=SIZEOF_DK_TNG_REC*i+SIZEOF_DK_TNG_HEADER;
00207 memcpy(thing, mem->content+offs, SIZEOF_DK_TNG_REC);
00208 thing_add(lvl,thing);
00209 }
00210 if (tng_num != lvl->tng_total_count)
00211 {
00212 message_error("Internal error in load_tng: tng_num=%d tng_total=%d", tng_num, lvl->tng_total_count);
00213 return ERR_INTERNAL;
00214 }
00215 memfile_free(&mem);
00216 return result;
00217 }
00218
00225 short load_clm(struct LEVEL *lvl,char *fname)
00226 {
00227 message_log(" load_clm: started");
00228 int i, j;
00229 if ((lvl==NULL)||(lvl->clm==NULL)) return ERR_INTERNAL;
00230
00231 struct MEMORY_FILE *mem;
00232 short result;
00233 result = memfile_readnew(&mem,fname,MAX_FILE_SIZE);
00234 if (result != MFILE_OK)
00235 return result;
00236
00237 if (mem->len < SIZEOF_DK_CLM_HEADER)
00238 { memfile_free(&mem); return ERR_FILE_TOOSMLL; }
00239 memcpy(lvl->clm_hdr, mem->content+0, SIZEOF_DK_CLM_HEADER);
00240 int num_clms=read_int32_le_buf(mem->content+0);
00241 if (mem->len != SIZEOF_DK_CLM_REC*num_clms+SIZEOF_DK_CLM_HEADER)
00242 { memfile_free(&mem); return ERR_FILE_BADDATA; }
00243 if (num_clms>COLUMN_ENTRIES)
00244 { memfile_free(&mem); return ERR_FILE_BADDATA; }
00245 for (i=0; i<num_clms; i++)
00246 {
00247 int offs=SIZEOF_DK_CLM_REC*i+SIZEOF_DK_CLM_HEADER;
00248 memcpy(lvl->clm[i], mem->content+offs, SIZEOF_DK_CLM_REC);
00249 }
00250 memfile_free(&mem);
00251 return ERR_NONE;
00252 }
00253
00261 short load_apt(struct LEVEL *lvl,char *fname)
00262 {
00263 message_log(" load_apt: started");
00264 int i;
00265 unsigned char *actnpt;
00266 if ((lvl==NULL)||(lvl->apt_lookup==NULL)) return ERR_INTERNAL;
00267
00268 struct MEMORY_FILE *mem;
00269 short result;
00270 result = memfile_readnew(&mem,fname,MAX_FILE_SIZE);
00271 if (result != MFILE_OK)
00272 return result;
00273
00274 if (mem->len < SIZEOF_DK_APT_HEADER)
00275 { memfile_free(&mem); return ERR_FILE_TOOSMLL; }
00276 result=ERR_NONE;
00277 long apt_num;
00278 apt_num = read_int32_le_buf(mem->content+0);
00279
00280 unsigned long expect_size=apt_num*SIZEOF_DK_APT_REC+SIZEOF_DK_APT_HEADER;
00281 if (mem->len != expect_size)
00282 {
00283 message_log(" load_apt: File length %d, expected %lu (%d items)",mem->len,expect_size,apt_num);
00284
00285 if (((lvl->optns.load_redundant_objects&EXLD_ACTNPT)==EXLD_ACTNPT)||(mem->len < expect_size))
00286 apt_num=(mem->len-SIZEOF_DK_APT_HEADER)/SIZEOF_DK_APT_REC;
00287 result=WARN_BAD_COUNT;
00288 }
00289 for (i=0; i < apt_num; i++)
00290 {
00291 actnpt=(unsigned char *)malloc(SIZEOF_DK_APT_REC);
00292 if (actnpt==NULL)
00293 {
00294 message_error("Cannot allocate mem for loading action points");
00295 return ERR_CANT_MALLOC;
00296 }
00297 memcpy (actnpt, mem->content+SIZEOF_DK_APT_REC*i+SIZEOF_DK_APT_HEADER, SIZEOF_DK_APT_REC);
00298 actnpt_add(lvl,actnpt);
00299 }
00300 if (apt_num != lvl->apt_total_count)
00301 {
00302 message_error("Internal error in load_apt: apt_num=%d apt_total=%d", apt_num, lvl->apt_total_count);
00303 return ERR_INTERNAL;
00304 }
00305 memfile_free(&mem);
00306 return result;
00307 }
00308
00315 short load_inf(struct LEVEL *lvl,char *fname)
00316 {
00317 message_log(" load_inf: started");
00318 struct MEMORY_FILE *mem;
00319 short result;
00320 result = memfile_readnew(&mem,fname,MAX_FILE_SIZE);
00321 if (result != MFILE_OK)
00322 return result;
00323
00324 if (mem->len != 1)
00325 { memfile_free(&mem); return ERR_FILE_BADDATA; }
00326 lvl->inf=mem->content[0];
00327 memfile_free(&mem);
00328 return ERR_NONE;
00329 }
00330
00337 short load_vsn(struct LEVEL *lvl,char *fname)
00338 {
00339 message_log(" load_vsn: started");
00340 struct MEMORY_FILE *mem;
00341 short result;
00342 result = memfile_readnew(&mem,fname,MAX_FILE_SIZE);
00343 if (result != MFILE_OK)
00344 return result;
00345
00346 if (mem->len != 1)
00347 { memfile_free(&mem); return ERR_FILE_BADDATA; }
00348 unsigned char vsn;
00349 vsn=mem->content[0];
00350 memfile_free(&mem);
00351 if ((vsn==1)&&((lvl->format_version==MFV_DKSTD)||(lvl->format_version==MFV_DKGOLD)))
00352 return ERR_NONE;
00353 if ((vsn==2)&&((lvl->format_version==MFV_DKXPAND)))
00354 return ERR_NONE;
00355 return ERR_FILE_BADDATA;
00356 }
00357
00364 short load_wib(struct LEVEL *lvl,char *fname)
00365 {
00366 message_log(" load_wib: started");
00367
00368 struct MEMORY_FILE *mem;
00369 short result;
00370 result = memfile_readnew(&mem,fname,MAX_FILE_SIZE);
00371 if (result != MFILE_OK)
00372 return result;
00373
00374 if ((mem->len!=lvl->subsize.x*lvl->subsize.y))
00375 { memfile_free(&mem); return ERR_FILE_BADDATA; }
00376
00377 int sx, sy;
00378 unsigned long addr;
00379 for (sy=0; sy<lvl->subsize.y; sy++)
00380 {
00381 addr = sy*lvl->subsize.x;
00382 for (sx=0; sx<lvl->subsize.x; sx++)
00383 {
00384 set_subtl_wib(lvl,sx,sy,mem->content[addr+sx]);
00385 }
00386 }
00387 memfile_free(&mem);
00388 return ERR_NONE;
00389
00390
00391 }
00392
00399 short load_slb(struct LEVEL *lvl,char *fname)
00400 {
00401 message_log(" load_slb: started");
00402
00403 struct stat attrib;
00404 if (stat(fname,&attrib) == 0)
00405 {
00406 lvl->info.creat_date=attrib.st_mtime;
00407 lvl->info.lastsav_date=lvl->info.creat_date;
00408 int name_len=strlen(default_map_name)+10;
00409 char *name_text=malloc(name_len);
00410 if (name_text!=NULL)
00411 {
00412 strftime(name_text,name_len, default_map_name, localtime(&(lvl->info.creat_date)) );
00413 set_lif_name_text(lvl,name_text);
00414 }
00415 }
00416
00417 struct MEMORY_FILE *mem;
00418 short result;
00419 result = memfile_readnew(&mem,fname,MAX_FILE_SIZE);
00420 if (result != MFILE_OK)
00421 return result;
00422
00423 if ((mem->len != 2*lvl->tlsize.x*lvl->tlsize.y))
00424 { memfile_free(&mem); return ERR_FILE_BADDATA; }
00425
00426 int i, k;
00427 unsigned long addr=0;
00428 for (i=0; i<lvl->tlsize.y; i++)
00429 {
00430 addr = 2*lvl->tlsize.x*i;
00431 for (k=0; k<lvl->tlsize.x; k++)
00432 set_tile_slab(lvl,k,i,read_int16_le_buf(mem->content+addr+k*2));
00433 }
00434 memfile_free(&mem);
00435
00436 return ERR_NONE;
00437
00438
00439 }
00440
00447 short load_own(struct LEVEL *lvl,char *fname)
00448 {
00449 message_log(" load_own: started");
00450
00451 struct MEMORY_FILE *mem;
00452 short result;
00453 result = memfile_readnew(&mem,fname,MAX_FILE_SIZE);
00454 if (result != MFILE_OK)
00455 return result;
00456
00457 if ((mem->len!=lvl->subsize.x*lvl->subsize.y))
00458 { memfile_free(&mem); return ERR_FILE_BADDATA; }
00459
00460 int sx, sy;
00461 unsigned long addr;
00462 for (sy=0; sy<lvl->subsize.y; sy++)
00463 {
00464 addr = sy*lvl->subsize.x;
00465 for (sx=0; sx<lvl->subsize.x; sx++)
00466 {
00467 set_subtl_owner(lvl,sx,sy,mem->content[addr+sx]);
00468 }
00469 }
00470 memfile_free(&mem);
00471 return ERR_NONE;
00472
00473
00474 }
00475
00482 short load_dat(struct LEVEL *lvl,char *fname)
00483 {
00484 message_log(" load_dat: started");
00485 short result;
00486 const unsigned int line_len=2*lvl->subsize.x;
00487
00488 struct MEMORY_FILE *mem;
00489 result = memfile_readnew(&mem,fname,MAX_FILE_SIZE);
00490 if (result != MFILE_OK)
00491 return result;
00492
00493 if ((mem->len != line_len*lvl->subsize.y))
00494 { memfile_free(&mem); return ERR_FILE_BADDATA; }
00495
00496
00497 int sx, sy;
00498 unsigned char *addr;
00499 for (sy=0; sy<lvl->subsize.y; sy++)
00500 {
00501 addr = mem->content+sy*line_len;
00502 for (sx=0; sx<lvl->subsize.x; sx++)
00503 {
00504 set_dat_val(lvl,sx,sy,read_int16_le_buf(addr+sx*2));
00505 }
00506 }
00507
00508 memfile_free(&mem);
00509
00510 return ERR_NONE;
00511 }
00512
00519 short load_txt(struct LEVEL *lvl,char *fname)
00520 {
00521 message_log(" load_txt: started");
00522 lvl->script.lines_count=0;
00523
00524 struct MEMORY_FILE *mem;
00525 short result;
00526 result = memfile_readnew(&mem,fname,MAX_FILE_SIZE);
00527 if (result != MFILE_OK)
00528 return result;
00529
00530
00531 if (mem->len < 2)
00532 { memfile_free(&mem); return ERR_FILE_TOOSMLL; }
00533 unsigned char *content=mem->content;
00534 unsigned char *ptr=mem->content;
00535 unsigned char *ptr_end=mem->content+mem->len;
00536 int lines_count=0;
00537
00538 while (ptr>=content)
00539 {
00540 ptr=memchr(ptr, 0x0a, (char *)ptr_end-(char *)ptr );
00541 lines_count++;
00542 if (ptr!=NULL) ptr++;
00543 }
00544 lvl->script.txt=(char **)malloc(lines_count*sizeof(unsigned char *));
00545 lvl->script.list=(struct DK_SCRIPT_COMMAND **)malloc(lines_count*sizeof(struct DK_SCRIPT_COMMAND *));
00546 ptr=mem->content;
00547 int currline;
00548 currline=0;
00549
00550 while (currline<lines_count)
00551 {
00552 if (ptr>=ptr_end) ptr=ptr_end-1;
00553 unsigned char *nptr=memchr(ptr, 0x0a, ptr_end-ptr );
00554
00555 while ((ptr<nptr)&&((unsigned char)ptr[0]<0x20)&&((unsigned char)ptr[0]!=0x09)) ptr++;
00556 if (nptr==NULL)
00557 nptr=ptr_end;
00558 int linelen=(char *)nptr-(char *)ptr;
00559
00560 while ((linelen>0)&&((unsigned char)ptr[linelen-1]<=0x20)) linelen--;
00561 lvl->script.txt[currline]=(unsigned char *)malloc((linelen+1)*sizeof(unsigned char));
00562 lvl->script.list[currline]=NULL;
00563 memcpy(lvl->script.txt[currline],ptr,linelen);
00564 lvl->script.txt[currline][linelen]='\0';
00565 ptr=nptr+1;
00566 currline++;
00567 }
00568
00569 int nonempty_lines=lines_count-1;
00570
00571 while ((nonempty_lines>=0)&&((lvl->script.txt[nonempty_lines][0])=='\0'))
00572 nonempty_lines--;
00573 currline=lines_count-1;
00574 while (currline>nonempty_lines)
00575 {
00576 free(lvl->script.txt[currline]);
00577 currline--;
00578 }
00579 lines_count=nonempty_lines+1;
00580 lvl->script.txt=(char **)realloc(lvl->script.txt,lines_count*sizeof(unsigned char *));
00581 lvl->script.list=(struct DK_SCRIPT_COMMAND **)realloc(lvl->script.list,lines_count*sizeof(struct DK_SCRIPT_COMMAND *));
00582 lvl->script.lines_count=lines_count;
00583 memfile_free(&mem);
00584 decompose_script(&(lvl->script),&(lvl->optns.script));
00585 script_decomposed_to_params(&(lvl->script),&(lvl->optns.script));
00586 return ERR_NONE;
00587 }
00588
00596 short load_lgt(struct LEVEL *lvl,char *fname)
00597 {
00598 message_log(" load_lgt: started");
00599 unsigned char *stlight;
00600 if ((lvl==NULL)||(lvl->lgt_lookup==NULL))
00601 return ERR_INTERNAL;
00602
00603 struct MEMORY_FILE *mem;
00604 short result;
00605 result = memfile_readnew(&mem,fname,MAX_FILE_SIZE);
00606 if (result != MFILE_OK)
00607 return result;
00608
00609 if (mem->len < SIZEOF_DK_LGT_HEADER)
00610 { memfile_free(&mem); return ERR_FILE_TOOSMLL; }
00611
00612 result=ERR_NONE;
00613 lvl->lgt_total_count=0;
00614 long lgt_num;
00615 lgt_num = read_int32_le_buf(mem->content+0);
00616 unsigned long expect_size=lgt_num*SIZEOF_DK_LGT_REC+SIZEOF_DK_LGT_HEADER;
00617
00618 if (mem->len != expect_size)
00619 {
00620 message_log(" load_lgt: File length %d, expected %lu (%d items)",mem->len,expect_size,lgt_num);
00621
00622 if (((lvl->optns.load_redundant_objects&EXLD_STLGHT)==EXLD_STLGHT)||(mem->len < expect_size))
00623 lgt_num=(mem->len-SIZEOF_DK_LGT_HEADER)/SIZEOF_DK_LGT_REC;
00624 result=WARN_BAD_COUNT;
00625 }
00626 int i;
00627 for (i=0; i<lgt_num; i++)
00628 {
00629 stlight=(unsigned char *)malloc(SIZEOF_DK_LGT_REC);
00630 if (stlight==NULL)
00631 {
00632 message_error("Cannot allocate mem for loading static lights");
00633 return ERR_CANT_MALLOC;
00634 }
00635 memcpy (stlight, mem->content+SIZEOF_DK_LGT_REC*i+SIZEOF_DK_LGT_HEADER, SIZEOF_DK_LGT_REC);
00636 stlight_add(lvl,stlight);
00637 }
00638 if (lgt_num != lvl->lgt_total_count)
00639 {
00640 message_error("Internal error in load_lgt: lgt_num=%d lgt_total=%d", lgt_num, lvl->lgt_total_count);
00641 return ERR_INTERNAL;
00642 }
00643 memfile_free(&mem);
00644 return result;
00645 }
00646
00655 short load_wlb(struct LEVEL *lvl,char *fname)
00656 {
00657 message_log(" load_wlb: started");
00658
00659 struct MEMORY_FILE *mem;
00660 short result;
00661 result = memfile_readnew(&mem,fname,MAX_FILE_SIZE);
00662 if (result != MFILE_OK)
00663 return result;
00664
00665 if (mem->len != lvl->tlsize.x*lvl->tlsize.y)
00666 { memfile_free(&mem); return ERR_FILE_BADDATA; }
00667 int i,j;
00668 for (i=0;i<lvl->tlsize.y;i++)
00669 for (j=0;j<lvl->tlsize.x;j++)
00670 {
00671 int mempos=i*lvl->tlsize.x+j;
00672 lvl->wlb[j][i]=mem->content[mempos];
00673 }
00674 memfile_free(&mem);
00675 return ERR_NONE;
00676 }
00677
00685 short load_flg(struct LEVEL *lvl,char *fname)
00686 {
00687 message_log(" load_flg: started");
00688 const unsigned int line_len=2*lvl->subsize.x;
00689
00690 struct MEMORY_FILE *mem;
00691 short result;
00692 result = memfile_readnew(&mem,fname,MAX_FILE_SIZE);
00693 if (result != MFILE_OK)
00694 return result;
00695
00696 if ((mem->len!=line_len*lvl->subsize.y))
00697 { memfile_free(&mem); return ERR_FILE_BADDATA; }
00698
00699 int sx, sy;
00700 unsigned long addr;
00701 for (sy=0; sy<lvl->subsize.y; sy++)
00702 {
00703 addr = sy*line_len;
00704 for (sx=0; sx<lvl->subsize.x; sx++)
00705 {
00706 set_subtl_flg(lvl,sx,sy,read_int16_le_buf(mem->content+addr+sx*2));
00707 }
00708 }
00709 memfile_free(&mem);
00710 return ERR_NONE;
00711 }
00712
00720 short load_lif(struct LEVEL *lvl,char *fname)
00721 {
00722 message_log(" load_lif: started");
00723 short result;
00724
00725 char **lines=NULL;
00726 int lines_count=0;
00727 result=load_text_file(&lines,&lines_count,fname);
00728 if (result!=ERR_NONE)
00729 {
00730 return result;
00731 }
00732
00733 char *line_data=NULL;
00734 int currline;
00735 for (currline=0;currline<lines_count;currline++)
00736 {
00737 free(line_data);
00738 line_data=strdup_trim(lines[currline]);
00739 if ((line_data!=NULL)&&(line_data[0]!='\0')) break;
00740 }
00741 free_text_file(&lines,&lines_count);
00742
00743 char *namepos=NULL;
00744 if ((line_data!=NULL)&&(line_data[0]!='\0'))
00745 namepos=(char *)strchr(line_data,',');
00746 if ((namepos==NULL)||(strlen(namepos)<2))
00747 { free(line_data); return ERR_FILE_BADDATA; }
00748
00749 char *str=strdup_trim(namepos+1);
00750 if (str!=NULL)
00751 set_lif_name_text(lvl,str);
00752 free(line_data);
00753 return ERR_NONE;
00754 }
00755
00763 short script_load_and_execute(struct LEVEL *lvl,struct MEMORY_FILE *mem,char *err_msg)
00764 {
00765 message_log(" script_load_and_execute: started");
00766 sprintf(err_msg,"No error");
00767 short result;
00768
00769 if (mem->len < 2)
00770 {
00771 result=ERR_FILE_TOOSMLL;
00772 strncpy(err_msg,levfile_error(result),LINEMSG_SIZE);
00773 return result;
00774 }
00775 unsigned char *content=mem->content;
00776 unsigned char *ptr=mem->content;
00777 unsigned char *ptr_end=mem->content+mem->len;
00778
00779 int lines_count=0;
00780 while (ptr>=content)
00781 {
00782 ptr=memchr(ptr, 0x0a, (char *)ptr_end-(char *)ptr );
00783 lines_count++;
00784 if (ptr!=NULL) ptr++;
00785 }
00786 ptr=mem->content;
00787 int currline=0;
00788 result=ERR_NONE;
00789 char *line;
00790 while (currline<lines_count)
00791 {
00792 if (ptr>=ptr_end) ptr=ptr_end-1;
00793 unsigned char *nptr=memchr(ptr, 0x0a, ptr_end-ptr );
00794
00795 while ((ptr<nptr)&&((unsigned char)ptr[0]<0x20)&&((unsigned char)ptr[0]!=0x09)) ptr++;
00796 if (nptr==NULL)
00797 nptr=ptr_end;
00798 int linelen=(char *)nptr-(char *)ptr;
00799
00800 while ((linelen>0)&&((unsigned char)ptr[linelen-1]<=0x20)) linelen--;
00801
00802 line=(unsigned char *)malloc((linelen+1)*sizeof(unsigned char *));
00803 memcpy(line,ptr,linelen);
00804 line[linelen]='\0';
00805 short res=execute_script_line(lvl,line,err_msg);
00806 if (!res)
00807 {
00808 sprintf(err_msg+strlen(err_msg),", line %d",currline+1);
00809 result=ERR_FILE_BADDATA;
00810 }
00811 free(line);
00812 ptr=nptr+1;
00813 currline++;
00814 }
00815 return result;
00816 }
00817
00825 short script_load_and_execute_file(struct LEVEL *lvl,char *fname,char *err_msg)
00826 {
00827 message_log(" script_load_and_execute_file: started");
00828
00829 struct MEMORY_FILE *mem;
00830 short result;
00831 result = memfile_readnew(&mem,fname,MAX_FILE_SIZE);
00832 if (result != MFILE_OK)
00833 {
00834 strncpy(err_msg,memfile_error(result),LINEMSG_SIZE);
00835 return result;
00836 }
00837 result=script_load_and_execute(lvl,mem,err_msg);
00838 memfile_free(&mem);
00839 return result;
00840 }
00841
00850 short load_text_file(char ***lines,int *lines_count,char *fname)
00851 {
00852 message_log(" load_text_file: started");
00853
00854 struct MEMORY_FILE *mem;
00855 short result;
00856 result = memfile_readnew(&mem,fname,MAX_FILE_SIZE);
00857 if (result != MFILE_OK)
00858 { return result; }
00859
00860
00861 if (mem->len < 2)
00862 { memfile_free(&mem); return ERR_FILE_TOOSMLL; }
00863 unsigned char *content=mem->content;
00864 unsigned char *ptr=mem->content;
00865 unsigned char *ptr_end=mem->content+mem->len;
00866
00867 while (ptr>=content)
00868 {
00869 ptr=memchr(ptr, 0x0a, (char *)ptr_end-(char *)ptr );
00870 (*lines_count)++;
00871 if (ptr!=NULL) ptr++;
00872 }
00873 (*lines)=(char **)realloc((*lines),(*lines_count)*sizeof(unsigned char *));
00874 ptr=mem->content;
00875 int currline;
00876 currline=0;
00877
00878 while (currline<(*lines_count))
00879 {
00880 if (ptr>=ptr_end) ptr=ptr_end-1;
00881 unsigned char *nptr=memchr(ptr, 0x0a, ptr_end-ptr );
00882
00883 while ((ptr<nptr)&&((unsigned char)ptr[0]<0x20)&&((unsigned char)ptr[0]!=0x09)) ptr++;
00884 if (nptr==NULL)
00885 nptr=ptr_end;
00886 int linelen=(char *)nptr-(char *)ptr;
00887
00888 while ((linelen>0)&&((unsigned char)ptr[linelen-1]<=0x20)) linelen--;
00889 (*lines)[currline]=(unsigned char *)malloc((linelen+1)*sizeof(unsigned char));
00890 memcpy((*lines)[currline],ptr,linelen);
00891 (*lines)[currline][linelen]='\0';
00892 ptr=nptr+1;
00893 currline++;
00894 }
00895
00896 int nonempty_lines=(*lines_count)-1;
00897
00898 while ((nonempty_lines>=0) && (((*lines)[nonempty_lines][0])=='\0'))
00899 nonempty_lines--;
00900 currline=(*lines_count)-1;
00901 while (currline>nonempty_lines)
00902 {
00903 free((*lines)[currline]);
00904 currline--;
00905 }
00906 (*lines_count)=nonempty_lines+1;
00907 (*lines)=(char **)realloc((*lines),(*lines_count)*sizeof(unsigned char *));
00908 memfile_free(&mem);
00909 return ERR_NONE;
00910 }
00911
00918 short write_slb(struct LEVEL *lvl,char *fname)
00919 {
00920 message_log(" write_slb: starting");
00921 FILE *fp;
00922 int i, k;
00923 fp = fopen (fname, "wb");
00924 if (fp==NULL)
00925 return ERR_CANT_OPENWR;
00926 for (k=0; k < lvl->tlsize.y; k++)
00927 {
00928 for (i=0; i < lvl->tlsize.x; i++)
00929 {
00930 write_int16_le_file(fp,get_tile_slab(lvl,i,k));
00931 }
00932 }
00933 fclose (fp);
00934 return ERR_NONE;
00935 }
00936
00943 short write_own(struct LEVEL *lvl,char *fname)
00944 {
00945 message_log(" write_own: starting");
00946
00947 FILE *fp;
00948 fp = fopen (fname, "wb");
00949 if (fp==NULL)
00950 return ERR_CANT_OPENWR;
00951
00952 int sx,sy;
00953 for (sy=0; sy<lvl->subsize.y; sy++)
00954 {
00955 for (sx=0; sx<lvl->subsize.x; sx++)
00956 {
00957 fputc (get_subtl_owner(lvl,sx,sy), fp);
00958 }
00959 }
00960 fclose (fp);
00961 return ERR_NONE;
00962 }
00963
00970 short write_dat(struct LEVEL *lvl,char *fname)
00971 {
00972 message_log(" write_dat: starting");
00973 const unsigned int line_len=2*lvl->subsize.x;
00974
00975 FILE *fp;
00976 fp = fopen (fname, "wb");
00977 if (fp==NULL)
00978 return ERR_CANT_OPENWR;
00979
00980 int sx,sy;
00981 for (sy=0; sy<lvl->subsize.y; sy++)
00982 {
00983 for (sx=0; sx<lvl->subsize.x; sx++)
00984 {
00985 write_int16_le_file(fp,get_dat_val(lvl,sx,sy));
00986 }
00987 }
00988 fclose (fp);
00989 return ERR_NONE;
00990 }
00991
00998 short write_flg(struct LEVEL *lvl,char *fname)
00999 {
01000 message_log(" write_flg: starting");
01001 const unsigned int line_len=2*lvl->subsize.x;
01002
01003 FILE *fp;
01004 fp = fopen (fname, "wb");
01005 if (fp==NULL)
01006 return ERR_CANT_OPENWR;
01007
01008 int sx,sy;
01009 for (sy=0; sy<lvl->subsize.y; sy++)
01010 {
01011 for (sx=0; sx<lvl->subsize.x; sx++)
01012 {
01013 write_int16_le_file(fp,get_subtl_flg(lvl,sx,sy));
01014 }
01015 }
01016 fclose (fp);
01017 return ERR_NONE;
01018 }
01019
01026 short write_clm(struct LEVEL *lvl,char *fname)
01027 {
01028 message_log(" write_clm: starting");
01029 FILE *fp;
01030 int i;
01031 fp = fopen (fname, "wb");
01032 if (fp==NULL)
01033 return ERR_CANT_OPENWR;
01034 write_int32_le_buf(lvl->clm_hdr+0,COLUMN_ENTRIES);
01035 fwrite(lvl->clm_hdr, SIZEOF_DK_CLM_HEADER, 1, fp);
01036 for (i=0; i<COLUMN_ENTRIES; i++)
01037 fwrite(lvl->clm[i], SIZEOF_DK_CLM_REC, 1, fp);
01038 fclose (fp);
01039 return ERR_NONE;
01040 }
01041
01048 short write_wib(struct LEVEL *lvl,char *fname)
01049 {
01050 message_log(" write_wib: starting");
01051
01052 FILE *fp;
01053 fp = fopen (fname, "wb");
01054 if (fp==NULL)
01055 return ERR_CANT_OPENWR;
01056 int i, j;
01057 for (i=0; i < lvl->subsize.y; i++)
01058 {
01059 for (j=0; j<lvl->subsize.x; j++)
01060 fputc (get_subtl_wib(lvl,j,i), fp);
01061 }
01062 fclose (fp);
01063 return ERR_NONE;
01064 }
01065
01072 short write_apt(struct LEVEL *lvl,char *fname)
01073 {
01074 message_log(" write_apt: starting");
01075
01076 const int arr_entries_x=lvl->tlsize.x*MAP_SUBNUM_X;
01077 const int arr_entries_y=lvl->tlsize.y*MAP_SUBNUM_Y;
01078
01079 FILE *fp;
01080 fp = fopen (fname, "wb");
01081 if (fp==NULL)
01082 return ERR_CANT_OPENWR;
01083 write_int32_le_file (fp,lvl->apt_total_count);
01084 int cy, cx, k;
01085 for (cy=0; cy<arr_entries_y; cy++)
01086 {
01087 for (cx=0; cx<arr_entries_x; cx++)
01088 {
01089 int num_subs=get_actnpt_subnums(lvl,cx,cy);
01090 for (k=0; k<num_subs; k++)
01091 {
01092 char *actnpt=get_actnpt(lvl,cx,cy,k);
01093 fwrite (actnpt, SIZEOF_DK_APT_REC, 1, fp);
01094 }
01095 }
01096 }
01097 fclose (fp);
01098 return ERR_NONE;
01099 }
01100
01107 short write_tng(struct LEVEL *lvl,char *fname)
01108 {
01109 message_log(" write_tng: starting");
01110
01111 const int arr_entries_x=lvl->tlsize.x*MAP_SUBNUM_X;
01112 const int arr_entries_y=lvl->tlsize.y*MAP_SUBNUM_Y;
01113
01114 FILE *fp;
01115 int cx, cy, k;
01116 fp = fopen (fname, "wb");
01117 if (fp==NULL)
01118 return ERR_CANT_OPENWR;
01119
01120 write_int16_le_file(fp, lvl->tng_total_count);
01121
01122 for (cy=0; cy < arr_entries_y; cy++)
01123 for (cx=0; cx < arr_entries_x; cx++)
01124 for (k=0; k < get_thing_subnums(lvl,cx,cy); k++)
01125 fwrite (get_thing(lvl,cx,cy,k), SIZEOF_DK_TNG_REC, 1, fp);
01126 fclose (fp);
01127 return ERR_NONE;
01128 }
01129
01137 short write_inf(struct LEVEL *lvl,char *fname)
01138 {
01139 message_log(" write_inf: starting");
01140 FILE *fp;
01141 int i, j, k;
01142 fp = fopen (fname, "wb");
01143 if (fp==NULL)
01144 return ERR_CANT_OPENWR;
01145 fputc ((lvl->inf) & 255, fp);
01146 fclose (fp);
01147 return ERR_NONE;
01148 }
01149
01157 short write_vsn(struct LEVEL *lvl,char *fname)
01158 {
01159 message_log(" write_vsn: starting");
01160 FILE *fp;
01161 int i, j, k;
01162 fp = fopen (fname, "wb");
01163 if (fp==NULL)
01164 return ERR_CANT_OPENWR;
01165 unsigned char vsn;
01166 switch (lvl->format_version)
01167 {
01168 case MFV_DKSTD:
01169 case MFV_DKGOLD:
01170 vsn=1;
01171 break;
01172 case MFV_DKXPAND:
01173 vsn=2;
01174 break;
01175 default:
01176 vsn=0;
01177 break;
01178 }
01179 fputc (vsn, fp);
01180 fclose (fp);
01181 return ERR_NONE;
01182 }
01183
01191 short write_txt(struct LEVEL *lvl,char *fname)
01192 {
01193 message_log(" write_txt: starting");
01194 return write_text_file(lvl->script.txt,lvl->script.lines_count,fname);
01195 }
01196
01203 short write_lgt(struct LEVEL *lvl,char *fname)
01204 {
01205 message_log(" write_lgt: starting");
01206
01207 const int arr_entries_x=lvl->tlsize.x*MAP_SUBNUM_X;
01208 const int arr_entries_y=lvl->tlsize.y*MAP_SUBNUM_Y;
01209
01210 FILE *fp;
01211 fp = fopen (fname, "wb");
01212 if (fp==NULL)
01213 return ERR_CANT_OPENWR;
01214 write_int32_le_file (fp,lvl->lgt_total_count);
01215 int cy, cx, k;
01216 for (cy=0; cy<arr_entries_y; cy++)
01217 {
01218 for (cx=0; cx<arr_entries_x; cx++)
01219 {
01220 int num_subs=get_stlight_subnums(lvl,cx,cy);
01221 for (k=0; k<num_subs; k++)
01222 {
01223 char *stlight=get_stlight(lvl,cx,cy,k);
01224 fwrite (stlight, SIZEOF_DK_LGT_REC, 1, fp);
01225 }
01226 }
01227 }
01228 fclose (fp);
01229 return ERR_NONE;
01230 }
01231
01239 short write_wlb(struct LEVEL *lvl,char *fname)
01240 {
01241 message_log(" write_wlb: starting");
01242 FILE *fp;
01243 fp = fopen (fname, "wb");
01244 if (fp==NULL)
01245 return ERR_CANT_OPENWR;
01246 int i, j;
01247 for (i=0; i < lvl->tlsize.y; i++)
01248 {
01249 for (j=0; j < lvl->tlsize.x; j++)
01250 fputc(lvl->wlb[j][i], fp);
01251 }
01252 fclose(fp);
01253 return ERR_NONE;
01254 }
01255
01263 short write_lif(struct LEVEL *lvl,char *fname)
01264 {
01265 message_log(" write_lif: starting");
01266
01267 long lvl_num;
01268 char *fname_num=fname;
01269 while (((*fname_num)!='\0')&&(!isdigit(*fname_num))) fname_num++;
01270 lvl_num=atol(fname_num);
01271
01272 char **lines=(char **)malloc(2*sizeof(char *));
01273 int lines_count=0;
01274 lines[lines_count]=malloc(LINEMSG_SIZE+1);
01275 sprintf(lines[lines_count],"%02d, %s",lvl_num,get_lif_name_text(lvl));
01276 lines_count++;
01277
01278 short result;
01279 result=write_text_file(lines,lines_count,fname);
01280 text_file_free(lines,lines_count);
01281 return result;
01282 }
01283
01291 short write_adi_script(struct LEVEL *lvl,char *fname)
01292 {
01293 message_log(" write_adi_script: starting");
01294
01295 char **lines=NULL;
01296 int lines_count=0;
01297 add_stats_to_script(&lines,&lines_count,lvl);
01298 add_graffiti_to_script(&lines,&lines_count,lvl);
01299 add_custom_clms_to_script(&lines,&lines_count,lvl);
01300 short result;
01301 result=write_text_file(lines,lines_count,fname);
01302 text_file_free(lines,lines_count);
01303 return result;
01304 }
01305
01312 short write_nfo(struct LEVEL *lvl,char *fname)
01313 {
01314 message_log(" write_nfo: starting");
01315
01316 char **lines=NULL;
01317 int lines_count=0;
01318 char *line;
01319 char *tmp1;
01320 int plr_items[PLAYERS_COUNT];
01321 int i,k,imax;
01322 line=(char *)malloc(LINEMSG_SIZE*sizeof(char));
01323
01324 sprintf(line,"Name: %s %d.%d.%d",get_lif_name_text(lvl),
01325 lvl->info.ver_major,lvl->info.ver_minor,lvl->info.ver_rel);
01326 text_file_linecp_add(&lines,&lines_count,line);
01327 if ((lvl->info.author_text!=NULL)&&(lvl->info.author_text[0]!='\0'))
01328 tmp1=lvl->info.author_text;
01329 else
01330 tmp1="Anonymous";
01331 sprintf(line,"Author: %s",tmp1);
01332 if ((lvl->info.editor_text!=NULL)&&(lvl->info.editor_text[0]!='\0'))
01333 sprintf(line+strlen(line),", Editor: %s",lvl->info.editor_text);
01334 strcat(line,", Created on ");
01335 strftime(line+strlen(line),LINEMSG_SIZE/2, "%d %b %Y",
01336 gmtime(&lvl->info.creat_date) );
01337 text_file_linecp_add(&lines,&lines_count,line);
01338 strcpy(line,"Keepers: ");
01339
01340 for (i=0; i < PLAYERS_COUNT; i++)
01341 plr_items[i]=0;
01342 owned_things_count(plr_items,lvl,THING_TYPE_ITEM,ITEM_SUBTYPE_DNHEART);
01343 k=0;
01344 for (i=0; i < PLAYERS_COUNT; i++)
01345 if (plr_items[i]>0)
01346 {
01347 if (k) strcat(line,", ");
01348 strcat(line,get_owner_type_colorname(i));
01349 k=1;
01350 }
01351 text_file_linecp_add(&lines,&lines_count,line);
01352 strcpy(line,"Pool: ");
01353 imax=creatures_cmd_arrsize();
01354 k=0;
01355 for (i=0; i < imax; i++)
01356 if (lvl->script.par.creature_pool[i]>0)
01357 {
01358 if (k) strcat(line,", ");
01359 strcat(line,get_creature_subtype_fullname(i));
01360 k=1;
01361 if (strlen(line)>50)
01362 {
01363 text_file_linecp_add(&lines,&lines_count,line);
01364 strcpy(line," ");
01365 k=0;
01366 }
01367 }
01368 if (strlen(line)>2)
01369 text_file_linecp_add(&lines,&lines_count,line);
01370 strcpy(line,"Objects on map:");
01371 text_file_linecp_add(&lines,&lines_count,line);
01372 sprintf(line,"Creatures: %d, Traps: %d, Doors: %d, Items: %d",
01373 lvl->stats.creatures_count,lvl->stats.traps_count,
01374 lvl->stats.doors_count,lvl->stats.items_count);
01375 text_file_linecp_add(&lines,&lines_count,line);
01376 sprintf(line,"Dungeon hearts: %d, Hero gates: %d, Special Boxes: %d",
01377 lvl->stats.dn_hearts_count,lvl->stats.hero_gates_count,
01378 lvl->stats.things_count[THING_CATEGR_SPECIALBOX]);
01379 text_file_linecp_add(&lines,&lines_count,line);
01380 strcpy(line,"Description:");
01381 text_file_linecp_add(&lines,&lines_count,line);
01382 if ((lvl->info.desc_text!=NULL)&&(lvl->info.desc_text[0]!='\0'))
01383 tmp1=lvl->info.desc_text;
01384 else
01385 tmp1="No description.";
01386 imax=strlen(tmp1);
01387 do {
01388 i=50;
01389 strcpy(line," ");
01390 strncpy(line+2,tmp1,i);
01391 line[i+2]='\0';
01392 k=(strrchr(line,' ')-line);
01393 if (k>(i>>1))
01394 {i=k;line[i]='\0';}
01395 text_file_linecp_add(&lines,&lines_count,line);
01396 i--;
01397 tmp1+=i;
01398 imax-=i;
01399 } while (imax>i);
01400 if (imax>0)
01401 {
01402 strcpy(line," ");
01403 strcpy(line+2,tmp1);
01404 text_file_linecp_add(&lines,&lines_count,line);
01405 }
01406 free(line);
01407 short result;
01408 result=write_text_file(lines,lines_count,fname);
01409 text_file_free(lines,lines_count);
01410 return result;
01411 }
01412
01420 short write_text_file(char **lines,int lines_count,char *fname)
01421 {
01422 FILE *fp;
01423 int i;
01424 fp = fopen (fname, "wb");
01425 if (fp==NULL)
01426 return ERR_CANT_OPENWR;
01427 int last_line=lines_count-1;
01428 for (i=0;i<last_line;i++)
01429 {
01430 fputs(lines[i],fp);
01431 fputs("\r\n",fp);
01432 }
01433 if (last_line>=0)
01434 {
01435 fputs(lines[last_line],fp);
01436 if (lines[last_line][0] != '\0')
01437 fputs("\r\n",fp);
01438 }
01439 fclose(fp);
01440 return ERR_NONE;
01441 }
01442
01452 short save_mapfile(struct LEVEL *lvl,char *mfname,char *fext,mapfile_io_func write_file,int *saved_files,short *result)
01453 {
01454 short file_result;
01455 char *fname;
01456 fname = (char *)malloc(strlen(mfname)+5);
01457 if (fname==NULL)
01458 {
01459 message_error("save_mapfile: Out of memory");
01460 file_result=ERR_CANT_MALLOC;
01461 (*result)=file_result;
01462 return file_result;
01463 }
01464 sprintf (fname, "%s.%s", mfname,fext);
01465 file_result=write_file(lvl,fname);
01466 if (file_result==ERR_NONE)
01467 {
01468 (*saved_files)++;
01469 } else
01470 if (file_result<ERR_NONE)
01471 {
01472 message_error("Error: %s when saving \"%s\"",levfile_error(file_result), fname);
01473 (*result)=file_result;
01474 } else
01475 if (file_result>ERR_NONE)
01476 {
01477 char *ifname;
01478 ifname=prepare_short_fname(fname,24);
01479 message_info_force("Warning: %s when saving \"%s\"",levfile_error(file_result), ifname);
01480 free(ifname);
01481 (*saved_files)++;
01482 if ((*result)>=ERR_NONE)
01483 (*result)=file_result;
01484 }
01485 free(fname);
01486 return file_result;
01487 }
01488
01498 short save_dk1_map(struct LEVEL *lvl)
01499 {
01500 message_log(" save_dk1_map: started");
01501
01502 short result=ERR_NONE;
01503 int saved_files=0;
01504 int total_files=0;
01505 save_mapfile(lvl,lvl->savfname,"slb",write_slb,&saved_files,&result);
01506 total_files++;
01507 save_mapfile(lvl,lvl->savfname,"own",write_own,&saved_files,&result);
01508 total_files++;
01509 save_mapfile(lvl,lvl->savfname,"dat",write_dat,&saved_files,&result);
01510 total_files++;
01511 save_mapfile(lvl,lvl->savfname,"clm",write_clm,&saved_files,&result);
01512 total_files++;
01513 save_mapfile(lvl,lvl->savfname,"tng",write_tng,&saved_files,&result);
01514 total_files++;
01515 save_mapfile(lvl,lvl->savfname,"apt",write_apt,&saved_files,&result);
01516 total_files++;
01517 save_mapfile(lvl,lvl->savfname,"wib",write_wib,&saved_files,&result);
01518 total_files++;
01519 save_mapfile(lvl,lvl->savfname,"inf",write_inf,&saved_files,&result);
01520 total_files++;
01521 save_mapfile(lvl,lvl->savfname,"txt",write_txt,&saved_files,&result);
01522 total_files++;
01523 save_mapfile(lvl,lvl->savfname,"lgt",write_lgt,&saved_files,&result);
01524 total_files++;
01525 save_mapfile(lvl,lvl->savfname,"wlb",write_wlb,&saved_files,&result);
01526 total_files++;
01527 save_mapfile(lvl,lvl->savfname,"flg",write_flg,&saved_files,&result);
01528 total_files++;
01529 save_mapfile(lvl,lvl->savfname,"lif",write_lif,&saved_files,&result);
01530 total_files++;
01531 save_mapfile(lvl,lvl->savfname,"vsn",write_vsn,&saved_files,&result);
01532 total_files++;
01533 save_mapfile(lvl,lvl->savfname,"adi",write_adi_script,&saved_files,&result);
01534 total_files++;
01535
01536 if ((result==ERR_NONE)||(strlen(lvl->fname)<1))
01537 {
01538 strncpy(lvl->fname,lvl->savfname,DISKPATH_SIZE);
01539 lvl->fname[DISKPATH_SIZE-1]=0;
01540 }
01541 lvl->stats.saves_count++;
01542 message_log(" save_dk1_map: properly saved %d out of %d map files",saved_files,total_files);
01543 return result;
01544 }
01545
01546 short save_nfo_file(struct LEVEL *lvl)
01547 {
01548 message_log(" save_dk1_map: started");
01549 int saved_files=0;
01550 short result=ERR_NONE;
01551 return save_mapfile(lvl,lvl->fname,"nfo",write_nfo,&saved_files,&result);
01552 }
01553
01565 short save_dke_map(struct LEVEL *lvl)
01566 {
01567 message_log(" save_dke_map: started");
01568
01569 short result=ERR_NONE;
01570 int saved_files=0;
01571 int total_files=0;
01572
01573 message_error("Error: Save not supported for extender map format");
01574 result=ERR_INTERNAL;
01575
01576
01577
01578
01579
01580
01581
01582
01583
01584
01585
01586
01587
01588
01589
01590
01591
01592
01593
01594
01595
01596
01597
01598
01599
01600
01601
01602
01603 save_mapfile(lvl,lvl->savfname,"vsn",write_vsn,&saved_files,&result);
01604 total_files++;
01605 save_mapfile(lvl,lvl->savfname,"adi",write_adi_script,&saved_files,&result);
01606 total_files++;
01607
01608 if ((result==ERR_NONE)||(strlen(lvl->fname)<1))
01609 {
01610 strncpy(lvl->fname,lvl->savfname,DISKPATH_SIZE);
01611 lvl->fname[DISKPATH_SIZE-1]=0;
01612 }
01613 lvl->stats.saves_count++;
01614 message_log(" save_dke_map: properly saved %d out of %d map files",saved_files,total_files);
01615 return result;
01616 }
01617
01631 short user_save_map(struct LEVEL *lvl,short prior_save)
01632 {
01633 short result;
01634 struct IPOINT_2D errpt={-1,-1};
01635 if (level_verify(lvl,"save",&errpt)==VERIF_ERROR)
01636 return ERR_VERIF;
01637
01638
01639
01640 update_slab_owners(lvl);
01641 struct LEVSTATS *stats=get_lvl_stats(lvl);
01642 if (stats->saves_count==0)
01643 {
01644 if (prior_save)
01645 inc_info_ver_major(lvl);
01646 else
01647 inc_info_ver_minor(lvl);
01648 } else
01649 {
01650 if (prior_save)
01651 inc_info_ver_minor(lvl);
01652 else
01653 inc_info_ver_rel(lvl);
01654 }
01655 switch (lvl->format_version)
01656 {
01657 case MFV_DKSTD:
01658 case MFV_DKGOLD:
01659 result=save_dk1_map(lvl);
01660 break;
01661 case MFV_DKXPAND:
01662 result=save_dke_map(lvl);
01663 break;
01664 default:
01665 message_error("Error: Save not supported for this map format version");
01666 result=ERR_INTERNAL;
01667 break;
01668 }
01669 return result;
01670 }
01671
01682 short load_mapfile(struct LEVEL *lvl,char *fext,mapfile_io_func load_file,
01683 int *loaded_files,short *result,short flags)
01684 {
01685 short file_result;
01686 char *fname;
01687 message_log("load_mapfile: loading %s file",fext);
01688 fname = (char *)malloc(strlen(lvl->fname)+strlen(fext)+3);
01689 if (fname==NULL)
01690 {
01691 file_result=ERR_CANT_MALLOC;
01692 if (flags&LFF_IGNORE_INTERNAL)
01693 {
01694 message_log("load_mapfile: Out of memory");
01695 } else
01696 {
01697 message_error("load_mapfile: Out of memory");
01698 (*result)=file_result;
01699 }
01700 return file_result;
01701 }
01702 sprintf(fname, "%s.%s", lvl->fname, fext);
01703 file_result=load_file(lvl,fname);
01704
01705 if (file_result==ERR_NONE)
01706 {
01707 (*loaded_files)++;
01708 } else
01709 if (file_result<ERR_NONE)
01710 {
01711 if (flags&LFF_IGNORE_CANNOT_LOAD)
01712 {
01713 if (((*result)==ERR_NONE)&&(!(flags&LFF_DONT_EVEN_WARN)))
01714 message_info_force("Warning: %s when loading \"%s\"",levfile_error(file_result), fname);
01715 } else
01716 {
01717 message_error("Error: %s when loading \"%s\"",levfile_error(file_result), fname);
01718 (*result)=file_result;
01719 }
01720 } else
01721 if (file_result>ERR_NONE)
01722 {
01723 char *ifname;
01724 ifname=prepare_short_fname(fname,24);
01725 if (flags&LFF_IGNORE_CANNOT_LOAD)
01726 {
01727 if ((*result)==ERR_NONE)
01728 message_info_force("Warning: %s when loading \"%s\"",levfile_error(file_result), ifname);
01729 } else
01730 {
01731 message_info_force("Warning: %s when loading \"%s\"",levfile_error(file_result), ifname);
01732 if ((*result)>=ERR_NONE)
01733 (*result)=file_result;
01734 }
01735 free(ifname);
01736 (*loaded_files)++;
01737 }
01738 free(fname);
01739 return file_result;
01740 }
01741
01753 short load_mapfile_msg(struct LEVEL *lvl,char *fext,mapfile_iomsg_func load_file,
01754 int *loaded_files,short *result,short flags)
01755 {
01756 short file_result;
01757 char *fname;
01758 char *err_msg;
01759 message_log("load_mapfile_msg: loading %s file",fext);
01760 fname = (char *)malloc(strlen(lvl->fname)+strlen(fext)+3);
01761 err_msg=(char *)malloc(LINEMSG_SIZE);
01762 if ((fname==NULL)||(err_msg==NULL))
01763 {
01764 file_result=ERR_CANT_MALLOC;
01765 if (flags&LFF_IGNORE_INTERNAL)
01766 {
01767 message_log("load_mapfile_msg: Out of memory");
01768 } else
01769 {
01770 message_error("load_mapfile_msg: Out of memory");
01771 (*result)=file_result;
01772 }
01773 free(fname);
01774 free(err_msg);
01775 return file_result;
01776 }
01777 sprintf(fname, "%s.%s", lvl->fname, fext);
01778 err_msg[0]='\0';
01779
01780 struct MEMORY_FILE *mem;
01781 file_result = memfile_readnew(&mem,fname,MAX_FILE_SIZE);
01782 if (file_result != MFILE_OK)
01783 {
01784 if (flags&LFF_IGNORE_CANNOT_LOAD)
01785 {
01786 if (flags&LFF_DONT_EVEN_WARN)
01787 message_log(" load_mapfile_msg: %s when reading \"%s\"",memfile_error(file_result), fname);
01788 else
01789 message_info_force("Warning: %s when reading \"%s\"",memfile_error(file_result), fname);
01790 } else
01791 {
01792 message_error("Error: %s when reading \"%s\"",memfile_error(file_result), fname);
01793 (*result)=file_result;
01794 }
01795 free(fname);
01796 free(err_msg);
01797 return file_result;
01798 }
01799 file_result=load_file(lvl,mem,err_msg);
01800 memfile_free(&mem);
01801
01802 if (file_result==ERR_NONE)
01803 {
01804 (*loaded_files)++;
01805 } else
01806 if (file_result<ERR_NONE)
01807 {
01808
01809
01810 if ((load_file==script_load_and_execute)&&(file_result==ERR_FILE_BADDATA))
01811 {
01812 char *warn_fname;
01813 warn_fname=prepare_short_fname(fname,24);
01814 message_info_force("ADI script warning: %s in \"%s\" (ignored)", err_msg, warn_fname);
01815 free(warn_fname);
01816 } else
01817 if (flags&LFF_IGNORE_CANNOT_LOAD)
01818 {
01819 if (((*result)==ERR_NONE)&&(!(flags&LFF_DONT_EVEN_WARN)))
01820 message_info_force("Warning: %s when loading \"%s\"",err_msg, fname);
01821 } else
01822 {
01823 message_error("Error: %s when loading \"%s\"",err_msg, fname);
01824 (*result)=file_result;
01825 }
01826 } else
01827 if (file_result>ERR_NONE)
01828 {
01829 char *warn_fname;
01830 warn_fname=prepare_short_fname(fname,24);
01831 if (flags&LFF_IGNORE_CANNOT_LOAD)
01832 {
01833 if ((*result)==ERR_NONE)
01834 message_info_force("Warning: %s when loading \"%s\"",err_msg, warn_fname);
01835 } else
01836 {
01837 message_info_force("Warning: %s when loading \"%s\"",err_msg, warn_fname);
01838 if ((*result)>=ERR_NONE)
01839 (*result)=file_result;
01840 }
01841 free(warn_fname);
01842 (*loaded_files)++;
01843 }
01844 free(err_msg);
01845 free(fname);
01846 return file_result;
01847 }
01848
01857 short load_dk1_map(struct LEVEL *lvl)
01858 {
01859 message_log(" load_dk1_map: started");
01860 short result=ERR_NONE;
01861 level_free(lvl);
01862 level_clear(lvl);
01863 if ((lvl->fname==NULL)||(strlen(lvl->fname)<1))
01864 {
01865 result=ERR_FILE_BADNAME;
01866 message_error("Error: Can't load - bad map name");
01867 return result;
01868 }
01869 int loaded_files=0;
01870 int total_files=0;
01871 short file_result;
01872
01873 if (result>=ERR_NONE)
01874 load_mapfile(lvl,"slb",load_slb,&loaded_files,&result,LFF_IGNORE_NONE);
01875 if (result>=ERR_NONE)
01876 load_mapfile(lvl,"own",load_own,&loaded_files,&result,LFF_IGNORE_NONE);
01877 if (result>=ERR_NONE)
01878 load_mapfile(lvl,"tng",load_tng,&loaded_files,&result,LFF_IGNORE_NONE);
01879
01880 if (result>=ERR_NONE)
01881 load_mapfile(lvl,"dat",load_dat,&loaded_files,&result,LFF_IGNORE_ALL);
01882 if (result>=ERR_NONE)
01883 load_mapfile(lvl,"apt",load_apt,&loaded_files,&result,LFF_IGNORE_ALL);
01884 if (result>=ERR_NONE)
01885 load_mapfile(lvl,"lgt",load_lgt,&loaded_files,&result,LFF_IGNORE_ALL);
01886 if (result>=ERR_NONE)
01887 load_mapfile(lvl,"clm",load_clm,&loaded_files,&result,LFF_IGNORE_ALL);
01888 if (result>=ERR_NONE)
01889 load_mapfile(lvl,"wib",load_wib,&loaded_files,&result,LFF_IGNORE_ALL);
01890
01891
01892 if (result>=ERR_NONE)
01893 load_mapfile(lvl,"txt",load_txt,&loaded_files,&result,LFF_IGNORE_ALL);
01894 if (result>=ERR_NONE)
01895 load_mapfile(lvl,"inf",load_inf,&loaded_files,&result,LFF_IGNORE_ALL);
01896 if (result>=ERR_NONE)
01897 load_mapfile(lvl,"wlb",load_wlb,&loaded_files,&result,LFF_IGNORE_WITHOUT_WARN);
01898 if (result>=ERR_NONE)
01899 load_mapfile(lvl,"flg",load_flg,&loaded_files,&result,LFF_IGNORE_WITHOUT_WARN);
01900 if (result>=ERR_NONE)
01901 load_mapfile(lvl,"lif",load_lif,&loaded_files,&result,LFF_IGNORE_WITHOUT_WARN);
01902 if (result>=ERR_NONE)
01903 load_mapfile(lvl,"vsn",load_vsn,&loaded_files,&result,LFF_IGNORE_WITHOUT_WARN);
01904 if (result>=ERR_NONE)
01905 load_mapfile_msg(lvl,"adi",script_load_and_execute,&loaded_files,&result,LFF_IGNORE_WITHOUT_WARN);
01906
01907 if (result<ERR_NONE)
01908 {
01909 message_log(" load_dk1_map: failed");
01910 return result;
01911 }
01912 if ((result>=ERR_NONE)&&(strlen(lvl->savfname)<1))
01913 {
01914 strncpy(lvl->savfname,lvl->fname,DISKPATH_SIZE);
01915 lvl->savfname[DISKPATH_SIZE-1]=0;
01916 }
01917 message_log(" load_dk1_map: finished");
01918 return result;
01919 }
01920
01930 short load_dke_map(struct LEVEL *lvl)
01931 {
01932 message_log(" load_dke_map: started");
01933 short result=ERR_NONE;
01934 level_free(lvl);
01935 level_clear(lvl);
01936 if ((lvl->fname==NULL)||(strlen(lvl->fname)<1))
01937 {
01938 result=ERR_FILE_BADNAME;
01939 message_error("Error: Can't load - bad map name");
01940 return result;
01941 }
01942 int loaded_files=0;
01943 int total_files=0;
01944 short file_result;
01945
01946 message_error("Error: Load not supported for extended map format");
01947 result=ERR_INTERNAL;
01948
01949
01950
01951
01952
01953
01954
01955
01956
01957
01958
01959
01960
01961
01962
01963
01964
01965
01966
01967
01968
01969
01970
01971
01972
01973
01974
01975
01976
01977
01978
01979
01980 if (result>=ERR_NONE)
01981 load_mapfile(lvl,"vsn",load_vsn,&loaded_files,&result,LFF_IGNORE_WITHOUT_WARN);
01982 if (result>=ERR_NONE)
01983 load_mapfile_msg(lvl,"adi",script_load_and_execute,&loaded_files,&result,LFF_IGNORE_WITHOUT_WARN);
01984 if (result<ERR_NONE)
01985 {
01986 message_log(" load_dke_map: failed");
01987 return result;
01988 }
01989 if ((result>=ERR_NONE)&&(strlen(lvl->savfname)<1))
01990 {
01991 strncpy(lvl->savfname,lvl->fname,DISKPATH_SIZE);
01992 lvl->savfname[DISKPATH_SIZE-1]=0;
01993 }
01994 message_log(" load_dke_map: finished");
01995 return result;
01996 }
01997
02005 short user_load_map(struct LEVEL *lvl,short new_on_error)
02006 {
02007 short result;
02008 switch (lvl->format_version)
02009 {
02010 case MFV_DKSTD:
02011 case MFV_DKGOLD:
02012 result=load_dk1_map(lvl);
02013 break;
02014 case MFV_DKXPAND:
02015 result=load_dke_map(lvl);
02016 break;
02017 default:
02018 message_error("Error: Load not supported for this map format version");
02019 result=ERR_INTERNAL;
02020 break;
02021 }
02022 if ((result<ERR_NONE)&&(new_on_error))
02023 {
02024 free_map(lvl);
02025 start_new_map(lvl);
02026 }
02027 update_level_stats(lvl);
02028 return result;
02029 }
02030
02039 short load_map_preview(struct LEVEL *lvl)
02040 {
02041 char *fnames;
02042 short result=ERR_NONE;
02043 level_free(lvl);
02044 level_clear(lvl);
02045 if ((lvl->fname==NULL)||(strlen(lvl->fname)<1))
02046 {
02047 result=ERR_FILE_BADNAME;
02048 message_error("load_map_preview: Bad file name");
02049 return result;
02050 }
02051 int loaded_files=0;
02052 short global_result=ERR_NONE;
02053 if (result>=ERR_NONE)
02054 result=load_mapfile(lvl,"slb",load_slb,&loaded_files,&global_result,LFF_IGNORE_ALL);
02055 if (result>=ERR_NONE)
02056 result=load_mapfile(lvl,"own",load_own,&loaded_files,&global_result,LFF_IGNORE_ALL);
02057 if (strlen(lvl->savfname)<1)
02058 {
02059 strncpy(lvl->savfname,lvl->fname,DISKPATH_SIZE);
02060 lvl->savfname[DISKPATH_SIZE-1]=0;
02061 }
02062 update_level_stats(lvl);
02063 return result;
02064 }
02065
02073 short write_def_clm_source(struct LEVEL *lvl,char *fname)
02074 {
02075 FILE *fp;
02076 int i,k;
02077 fp = fopen (fname, "w");
02078 if (!fp)
02079 {
02080 message_error("Can't open \"%s\" for writing", fname);
02081 return false;
02082 }
02083
02084
02085 const int arr_entries_x=lvl->tlsize.x*MAP_SUBNUM_X;
02086 const int arr_entries_y=lvl->tlsize.y*MAP_SUBNUM_Y;
02087
02088 unsigned char *clmentry;
02089 struct COLUMN_REC *clm_rec;
02090 clm_rec=create_column_rec();
02091 for (i=0; i<COLUMN_ENTRIES; i++)
02092 {
02093 clmentry = (unsigned char *)(lvl->clm[i]);
02094 get_clm_entry(clm_rec, clmentry);
02095 int csum=read_int16_le_buf(clmentry+2);
02096
02097
02098
02099
02100 {
02101
02102
02103
02104
02105
02106
02107
02108
02109
02110
02111
02112
02113
02114
02115
02116
02117
02118
02119
02120
02121
02122
02123
02124
02125
02126
02127 fprintf(fp,"COLUMN(%4d,%5d,%2d,%2d,%2d, 0x%02x, 0x%03x,%2d,",
02128 i,(unsigned short)(clm_rec->use), clm_rec->permanent, clm_rec->lintel,
02129 clm_rec->height, clm_rec->solid, clm_rec->base, clm_rec->orientation);
02130 fprintf(fp," 0x%03x, 0x%03x, 0x%03x, 0x%03x, 0x%03x, 0x%03x, 0x%03x, 0x%03x) u=%d u0=%d\n",
02131 clm_rec->c[0],clm_rec->c[1],clm_rec->c[2],clm_rec->c[3],
02132 clm_rec->c[4],clm_rec->c[5],clm_rec->c[6],clm_rec->c[7],
02133 lvl->clm_utilize[i],(unsigned short)(clm_rec->use-(lvl->clm_utilize[i])));
02134
02135
02136
02137
02138
02139
02140
02141
02142
02143
02144
02145
02146 }
02147 }
02148 free_column_rec(clm_rec);
02149 fclose (fp);
02150 return true;
02151 }
02152
02160 short write_def_tng_source(struct LEVEL *lvl,char *fname)
02161 {
02162 FILE *fp;
02163 int i,k;
02164 fp = fopen (fname, "w");
02165 if (!fp)
02166 {
02167 message_error("Can't open \"%s\" for writing", fname);
02168 return false;
02169 }
02170
02171
02172 const int arr_entries_x=lvl->tlsize.x*MAP_SUBNUM_X;
02173 const int arr_entries_y=lvl->tlsize.y*MAP_SUBNUM_Y;
02174 int cx,cy;
02175 for (cy=0; cy < arr_entries_y; cy++)
02176 for (cx=0; cx < arr_entries_x; cx++)
02177 for (k=0; k < get_thing_subnums(lvl,cx,cy); k++)
02178 {
02179 unsigned char *thing=get_thing(lvl,cx,cy,k);
02180 int spos_x=get_thing_subtile_x(thing);
02181 int spos_y=get_thing_subtile_y(thing);
02182 int sen_tl=get_thing_sensitile(thing);
02183 unsigned short tngtype=get_thing_type(thing);
02184
02185 if ( (sen_tl!=((spos_x/MAP_SUBNUM_Y-1)+(spos_y/MAP_SUBNUM_Y-1)*lvl->tlsize.x)) &&
02186 (sen_tl!=((spos_x/MAP_SUBNUM_Y-1)+(spos_y/MAP_SUBNUM_Y+0)*lvl->tlsize.x)) &&
02187 (sen_tl!=((spos_x/MAP_SUBNUM_Y-1)+(spos_y/MAP_SUBNUM_Y+1)*lvl->tlsize.x)) &&
02188 (sen_tl!=((spos_x/MAP_SUBNUM_Y+0)+(spos_y/MAP_SUBNUM_Y-1)*lvl->tlsize.x)) &&
02189 (sen_tl!=((spos_x/MAP_SUBNUM_Y+0)+(spos_y/MAP_SUBNUM_Y+0)*lvl->tlsize.x)) &&
02190 (sen_tl!=((spos_x/MAP_SUBNUM_Y+0)+(spos_y/MAP_SUBNUM_Y+1)*lvl->tlsize.x)) &&
02191 (sen_tl!=((spos_x/MAP_SUBNUM_Y+1)+(spos_y/MAP_SUBNUM_Y-1)*lvl->tlsize.x)) &&
02192 (sen_tl!=((spos_x/MAP_SUBNUM_Y+1)+(spos_y/MAP_SUBNUM_Y+0)*lvl->tlsize.x)) &&
02193 (sen_tl!=((spos_x/MAP_SUBNUM_Y+1)+(spos_y/MAP_SUBNUM_Y+1)*lvl->tlsize.x)) )
02194 {
02195 int tl_x=spos_x/MAP_SUBNUM_X;
02196 int tl_y=spos_y/MAP_SUBNUM_Y;
02197 fprintf(fp,"stl %3d,%3d tl %2d,%2d", spos_x, spos_y,
02198 tl_x, tl_y);
02199 fprintf(fp," s %d,%d", spos_x-tl_x*MAP_SUBNUM_X, spos_y-tl_y*MAP_SUBNUM_Y);
02200 fprintf(fp," stlpos %3d,%3d",
02201 get_thing_subtpos_x(thing), get_thing_subtpos_y(thing));
02202 fprintf(fp," alt %3d altstl %d",
02203 get_thing_subtpos_h(thing),get_thing_subtile_h(thing));
02204 fprintf(fp," typ %5s",get_thing_type_shortname(tngtype));
02205 switch (tngtype)
02206 {
02207 case THING_TYPE_DOOR:
02208 fprintf(fp," knd %s",get_door_subtype_fullname(get_thing_subtype(thing)));
02209 break;
02210 case THING_TYPE_TRAP:
02211 fprintf(fp," knd %s",get_trap_subtype_fullname(get_thing_subtype(thing)));
02212 break;
02213 case THING_TYPE_ITEM:
02214 fprintf(fp," knd %s",get_item_subtype_fullname(get_thing_subtype(thing)));
02215 break;
02216 }
02217 fprintf(fp,"\n");
02218 for (i=0; i < SIZEOF_DK_TNG_REC; i++)
02219 {
02220 fprintf(fp," %02X", (unsigned int)thing[i]);
02221 }
02222 fprintf(fp,"\n");
02223 for (i=0; i < SIZEOF_DK_TNG_REC; i++)
02224 {
02225 fprintf(fp," %3d", (unsigned int)thing[i]);
02226 }
02227 fprintf(fp,"\n\n");
02228 }
02229 }
02230 fclose (fp);
02231 return true;
02232 }