/* Standard C Includes */ #include <stdlib.h> #include <stdio.h> #include <conio.h> #include <ctype.h> #include <string.h> /* User Defined Includes */ #include "fileutil.h" #include "cmstring.h" #include "daggen.h" #include "dagfile.h" #include "dagdata.h" /* The main data for loading... */ DAG_FILE dagfile; #define DEBUG TRUE /*========== Class DAG_RECORD Constructor =================================*/ BASE_RECORD::BASE_RECORD (void) { data = NULL; size = 0; num_sizes = 0; type = 0; data_length = 0; offset = 0; loaded = FALSE; } /*========== End of Class DAG_RECORD Constructor ==========================*/ /*========== Class DAG_RECORD Destructor ==================================*/ void BASE_RECORD::destroy (void) { if (data) { delete data; data = NULL; } size = 0; loaded = FALSE; num_sizes = 0; data_length = 0; type = 0; offset = 0; } /*========== End of Class DAG_RECORD Destructor ===========================*/ /*========== Attempts to Read The Default Field Data ======================*/ boolean BASE_RECORD::load_record (FILE *f) { /* Make sure there is something to load from */ if (!f) { err_code = ERR_FILE; return (FALSE); } /* Make sure a good record size is present */ if (size < 5) { write_log_entry ("Invalid field size of %d received (Offset = %lu)!", size, ftell(f)); err_code = ERR_INDEX; return (FALSE); } /* Allocate the memory */ data_length = (short) size - 5; data = create_ptr (data_length); /* Read data from file, or attempt to */ if (fread(data, sizeof(char), data_length, f) != data_length) { write_log_entry ("Read past EOF"); err_code = ERR_READ; return (FALSE); } loaded = TRUE; err_code = ERR_NONE; return (TRUE); } /*========== End of Function BASE_RECORD::load_record() ===================*/ /*========== Saves Only the Record Data ===================================*/ boolean BASE_RECORD::save_record (FILE *f) { /* Make sure ther eis something to write to */ if (!f) { err_code = ERR_FILE; return (FALSE); } /* Something to write? */ if (!data || !data_length) { err_code = DF_ERR_NODATA; return (TRUE); } if (fwrite (data, sizeof(char), data_length, f) != data_length) { err_code = ERR_WRITE; return (FALSE); } err_code = ERR_NONE; return (TRUE); } /*========== End of Function BASE_RECORD::save_record() ===================*/ /*========== Class DAG_FILE Constructor ===================================*/ DAG_FILE::DAG_FILE (void) { short i; /* Loop counter */ for (i = 0; i < MAX_RECORDS; i++) records[i] = NULL; post_data = NULL; post_length = 0; num_records = 0; } /*========== End of Class DAG_FILE Constructor ============================*/ /*========== Class DAG_FILE Destructor ====================================*/ void DAG_FILE::destroy (void) { short i; /* Loop counter */ if (post_data) { delete post_data; post_data = NULL; } for (i = 0; i < MAX_RECORDS; i++) { if (records[i]) { delete records[i]; records[i] = NULL; } } post_length = 0; num_records = 0; } /*========== End of Class DAG_FILE Destructor =============================*/ /*========== Attempts to Delete a Record ==================================*/ boolean DAG_FILE::del_record (const short pos) { short i; /* Make sure it's a valid position */ if (pos < 0 || pos >= num_records || !records[pos]) { err_code = ERR_INDEX; return (FALSE); } /* Delete the record */ delete records[pos]; /* Move everything */ for (i = pos; i < num_records; i++) { records[i] = records[i + 1]; } num_records--; err_code = ERR_NONE; return (TRUE); } /*========== End of Function DAG_FILE::del_record() =======================*/ /*========== Attempts to Load a Savetree.DAT File into Memory =============*/ boolean DAG_FILE::load (const char *filename, const short type) { FILE *f; /* File pointer */ boolean done = FALSE; /* Loop counter */ long size; #if DEBUG long offset; #endif short num_sizes, rec_type; /* Display the memory status */ write_log_entry ("Heap is %s", get_heapstring()); write_log_entry ("Used/Free/Total Memory: %lu/%lu/%lu bytes", get_memused(), get_memleft(), get_memtotal()); /* Attempt to open the file for reading */ if (!(f = openfile(filename, "rb"))) { err_code = ERR_FILE; return (FALSE); } /* Clear any data currently in memory */ destroy(); /* Read in the 19 byte header */ if (fread(pre_data, sizeof(char), 19, f) != 19) { err_code = ERR_READ; fclose (f); return (FALSE); } /* Read in records */ while (!done && !feof(f)) { num_sizes = 0; #if DEBUG offset = ftell(f); #endif /* Read in the first size field */ size = read_long(f); /* Need to look for a second field? */ if (!size) { num_sizes++; /* Read in the first size field, Check for End of Fields */ size = read_long(f); if (!size) done = TRUE; } /* Read the main type of record */ rec_type = fgetc(f); if (!size) rec_type = DF_EOF; /* Create the record */ if (rec_type == DF_ITEM) { if (!(records[num_records] = new ITEM_RECORD)) bug (MEM_ERR_MSG, "DAG_FILE::load() - records[] (*ITEM_RECORD = %d)", sizeof(ITEM_RECORD)); } else if (rec_type == DF_CHAR) { if (!(records[num_records] = new CHAR_RECORD)) bug (MEM_ERR_MSG, "DAG_FILE::load() - records[] (*CHAR_RECORD = %d)", sizeof(CHAR_RECORD)); } else if (rec_type == DF_GUILD) { if (!(records[num_records] = new GUILD_RECORD)) bug (MEM_ERR_MSG, "DAG_FILE::load() - records[] (*GUILD_RECORD = %d)", sizeof(GUILD_RECORD)); } else { /* Default unknown type */ if (!(records[num_records] = new BASE_RECORD)) bug (MEM_ERR_MSG, "DAG_FILE::load() - records[] (*BASE_RECORD = %d)", sizeof(BASE_RECORD)); } /* Assign the loaded values */ records[num_records]->offset = ftell(f); records[num_records]->type = rec_type; records[num_records]->size = size; records[num_records]->num_sizes = num_sizes; /* Read the actual record */ if (type && rec_type != 0x07 && (type & DFRT_ALL || records[num_records]->type == DF_ITEM && type & DFRT_ITEM || records[num_records]->type == DF_CHAR && type & DFRT_CHAR || records[num_records]->type == DF_GUILD && type & DFRT_GUILD)) { /* Load the actual record data */ if (!records[num_records]->load_record (f)) { if (!err_code) err_code = ERR_READ; fclose (f); return (FALSE); } } /* The strange field... */ else if (rec_type == 0x07) { fseek (f, -1, SEEK_CUR); done = TRUE; } else { /* Read nothing, Move to the end of the field */ fseek (f, records[num_records]->size - 1, SEEK_CUR); records[num_records]->data_length = 0; } #if DEBUG write_log_entry (" Record %3u (0x%06lX) :Type = 0x%02X, Size = %4lu", num_records, offset, (unsigned int)records[num_records]->type, records[num_records]->size); #endif num_records++; if (num_records >= MAX_RECORDS) done = TRUE; } /* Read the rest of the data */ size = get_filesize(f) - ftell(f); if (size >= 0xFFFFl) { err_code = DF_ERR_TOOMUCH; fclose (f); return (FALSE); } post_length = (unsigned short) size; post_data = create_ptr (post_length); fread (post_data, sizeof(char), post_length, f); #if DEBUG write_log_entry ("%u bytes left in file", post_length); #endif fclose (f); /* Display the memory status */ write_log_entry ("Heap is %s", get_heapstring()); write_log_entry ("Used/Free/Total Memory: %lu/%lu/%lu bytes", get_memused(), get_memleft(), get_memtotal()); err_code = ERR_NONE; return (TRUE); } /*========== End of Function DAG_FILE::load() =============================*/ /*========== Attempts to Save the Data File ===============================*/ boolean DAG_FILE::save (const char *load_file, const char *save_file, const short type) { FILE *fi, *fo; /* File pointers */ unsigned long size; short i, j; /* Loop counters */ char *buf = NULL; /* Input/Output buffer */ /* Attempt to open the two files */ if (!(fi = openfile (load_file, "rb"))) { err_code = ERR_FILE; return (FALSE); } if (!(fo = openfile (save_file, "wb"))) { err_code = ERR_FILE; fclose (fi); return (FALSE); } /* Write the header information */ if (fwrite(pre_data, sizeof(char), 19, fo) != 19) { err_code = ERR_WRITE; fclose (fi); fclose (fo); return (FALSE); } /* Write the records */ for (i = 0; i < num_records; i++) { /* Write the record header */ for (j = 0; j < records[i]->num_sizes; j++) write_long (fo, 0); write_long(fo, records[i]->size); /* The special record??? */ if (records[i]->type == 0x07) break; if (records[i]->type != DF_EOF) { if (fputc (records[i]->type, fo) == EOF) goto WRITE_ERROR; } /* Write the data it from the input file */ if (!type || !records[i]->loaded) { /* Move to field offset */ fseek (fi, records[i]->offset, SEEK_SET); /* Make sure there is a valid size.... */ size = records[i]->size - 1; if (size > 1) { buf = create_ptr ((unsigned int) size); if (fread (buf, sizeof(char), (short)size, fi) != size) goto WRITE_ERROR; if (fwrite (buf, sizeof(char), (short)size, fo) != size) goto WRITE_ERROR; delete buf; buf = NULL; } } else { if (!records[i]->save_record (fo)) goto WRITE_ERROR; } } /* Write the trailing bytes */ if (post_length && post_data) { if (fwrite (post_data, sizeof(char), post_length, fo) != post_length) goto WRITE_ERROR; } fclose (fi); fclose (fo); err_code = ERR_NONE; return (TRUE); WRITE_ERROR: err_code = ERR_WRITE; if (buf) delete buf; fclose (fi); fclose (fo); return (FALSE); } /*========== End of Function DAG_FILE::save() =============================*/ /*========== Attempts to Load a Character Record ==========================*/ boolean CHAR_RECORD::load_record (FILE *f) { unsigned long l; /* Make sure there is something to read from */ if (!f) { err_code = ERR_FILE; return (FALSE); } /* Read the pre-data header */ if (fread(pre_data, sizeof(char), 70, f) != 70) { err_code = ERR_READ; return (FALSE); } /* Read the characters name */ if (fread(name, sizeof(char), 32, f) != 32) { err_code = ERR_READ; return (FALSE); } str = read_int(f); intel = read_int(f); wil = read_int(f); agi = read_int(f); end = read_int(f); per = read_int(f); spd = read_int(f); luc = read_int(f);; if (fread (mid_data, sizeof(char), 85, f) != 85) { err_code = ERR_READ; return (FALSE); } gold = read_long(f); #if DEBUG write_log_entry ("Found Character '%s', Gold = %ld", name, gold); #endif /* Read the rest of the data */ l = size - 208; if (l > 0) { data_length = (unsigned short) l; data = create_ptr ((unsigned short) l); if (fread(data, sizeof(char), data_length, f) != l) { err_code = ERR_READ; return (FALSE); } } else data_length = 0; /* Make sure we haven't read past the eof */ if (feof(f)) { err_code = ERR_READ; return (FALSE); } loaded = TRUE; return (TRUE); } /*========== End of Function CHAR_RECORD::load_record() ===================*/ /*========== Attempts to Save a Character Record ==========================*/ boolean CHAR_RECORD::save_record (FILE *f) { /* Make sure there is something to read from */ if (!f) { err_code = ERR_FILE; return (FALSE); } /* Read the pre-data header */ if (fwrite(pre_data, sizeof(char), 70, f) != 70) { err_code = ERR_WRITE; return (FALSE); } /* Read the characters name */ if (fwrite(name, sizeof(char), 32, f) != 32) { err_code = ERR_WRITE; return (FALSE); } write_int(f, str); write_int(f, intel); write_int(f, wil); write_int(f, agi); write_int(f, end); write_int(f, per); write_int(f, spd); write_int(f, luc); if (fwrite (mid_data, sizeof(char), 85, f) != 85) { err_code = ERR_WRITE; return (FALSE); } write_long(f, gold); /* Write the rest of the data */ if (data_length > 0) { if (fwrite(data, sizeof(char), data_length, f) != data_length) { err_code = ERR_WRITE; return (FALSE); } } err_code = ERR_NONE; return (TRUE); } /*========== End of Function CHAR_RECORD::save_record() ===================*/ /*========== Loads a Guild Data from a File ===============================*/ boolean GUILD_RECORD::load_record (FILE *f) { long offset; /* Make sure there is something to read from */ if (!f) { err_code = ERR_FILE; return (FALSE); } /* Save the current offset in file */ offset = ftell(f); /* Start reading things */ u1 = read_int(f); u2 = read_int(f); u3 = read_int(f); u4 = read_long(f); u5 = read_long(f); u6 = read_long(f); u7 = read_int(f); u8 = read_int(f); u9 = read_int(f); u10 = read_int(f); u11 = read_int(f); u12 = read_int(f); u13 = read_int(f); u14 = read_int(f); u15 = read_int(f); u16 = read_int(f); u17 = read_int(f); u18 = read_long(f); u19 = read_long(f); u20 = read_long(f); u21 = read_int(f); u22 = read_long(f); u23 = read_long(f); u24 = read_long(f); u25 = read_long(f); u26 = read_int(f); u27 = fgetc(f); guild_id = read_int(f); u28 = fgetc(f); u29 = fgetc(f); u30 = fgetc(f); u31 = fgetc(f); u32 = fgetc(f); u33 = read_long(f); /* Read the rest of the data, if any */ offset = size - 1 - (ftell(f) - offset); if (offset > 0) { data_length = (short) offset; data = create_ptr (data_length); if (fread(data, sizeof(char), data_length, f) != data_length) { err_code = ERR_READ; return (FALSE); } } else data_length = 0; /* Make sure we haven't exceed the EOF */ if (feof(f)) { err_code = ERR_READ; return (FALSE); } /* Return success */ loaded = TRUE; err_code = ERR_NONE; return (TRUE); } /*========== End of Function GUILD_RECORD::load_record() ==================*/ /*========== Saves Guild Data to File =====================================*/ boolean GUILD_RECORD::save_record (FILE *f) { /* Make sure there is something to write to */ if (!f) { err_code = ERR_FILE; return (FALSE); } /* Write the rest of the data, if any */ if (data_length && data) { if (fwrite (data, sizeof(char), data_length, f) != data_length) { err_code = ERR_WRITE; return (FALSE); } } err_code = ERR_NONE; return (TRUE); } /*========== End of Function GUILD_RECORD::save_record() ==================*/ /*========== Attempts to Compute the Cost of the Item =====================*/ long ITEM_RECORD::compute_cost (void) { int i = 0, j; long cost = 10; /* Make sure there is something to compare to */ if (!this || !loaded) return (0); /* Search for the item's base cost */ j = find_item (group, subgroup); if (j != -1) cost = items[j]->cost; /* Is this a piece of armor/weapon */ if (group == 0x02) { i = 0; while (armor_mult[i].material != -1) { if (armor_mult[i].material == material && (armor_mult[i].constr == -1 || armor_mult[i].constr == construction)) { cost *= armor_mult[i].mult; break; } i++; } } else if (group == 0x03) { i = 0; while (weapon_mult[i].material != -1) { if (weapon_mult[i].material == material && (weapon_mult[i].constr == -1 || weapon_mult[i].constr == construction)) { cost *= weapon_mult[i].mult; break; } i++; } } /* Now, find the costs for the enchantments */ for (i = 0; i < 10; i++) { if (enchantments[i] != -1) { j = find_enchantment (enchantments[i]); if (j != -1) cost += enchants[j]->cost; } } return (cost); } /*========== End of Function ITEM_RECORD::compute_cost() ==================*/ /*========== Loads an Item from a File ====================================*/ boolean ITEM_RECORD::load_record (FILE *f) { short i; /* Loop counter */ long offset; /* Make sure there is something to read from */ if (!f) { err_code = ERR_FILE; return (FALSE); } /* Save the current offset in file */ offset = ftell(f); /* Start reading things */ if (fread (null1, sizeof(char), 30, f) != 30) { err_code = ERR_READ; return (FALSE); } placement = read_int(f); if (fread (null2, sizeof(char), 22, f) != 22) { err_code = ERR_READ; return (FALSE); } index1 = read_long (f); index2 = read_long (f); null3 = read_long (f); token1 = read_long (f); if (fread (name, sizeof(char), 32, f) != 32) { err_code = ERR_READ; return (FALSE); } group = read_int (f); subgroup = read_int (f); cost = read_long (f); null4 = read_int (f); id = fgetc (f); null5 = fgetc (f); wear = read_int (f); max_wear = read_int (f); null6 = read_int (f); picture1 = read_int (f); picture2 = read_int (f); material = fgetc(f); construction = fgetc (f); color = fgetc (f); weight = fgetc (f); null7 = fgetc (f); null8 = read_int (f); enchant_pts = read_int (f); null9 = read_long (f); for (i = 0; i < 10; i++) enchantments[i] = read_long (f); /* Read the rest of the data, if any */ offset = size - 1 - (ftell(f) - offset); if (offset > 0) { data_length = (short) offset; data = create_ptr (data_length); if (fread(data, sizeof(char), data_length, f) != data_length) { err_code = ERR_READ; return (FALSE); } } else data_length = 0; /* Make sure we haven't exceed the EOF */ if (feof(f)) { err_code = ERR_READ; return (FALSE); } /* Return success */ err_code = ERR_NONE; loaded = TRUE; return (TRUE); } /*========== End of Function ITEM_RECORD::load_record() ===================*/ /*========== Saves an Item to File ========================================*/ boolean ITEM_RECORD::save_record (FILE *f) { short i; /* Loop counter */ /* Make sure there is something to write to */ if (!f) return (FALSE); /* Write all the fields */ /* Start reading things */ if (fwrite (null1, sizeof(char), 30, f) != 30) return (FALSE); write_int (f, placement); if (fwrite (null2, sizeof(char), 22, f) != 22) return (FALSE); write_long (f, index1); write_long (f, index2); write_long (f, null3); write_long (f, token1); if (fwrite (name, sizeof(char), 32, f) != 32) return (FALSE); write_int (f, group); write_int (f, subgroup); write_long (f, cost); write_int (f, null4); fputc(id, f); fputc (null5, f); write_int (f, wear); write_int (f, max_wear); write_int (f, null6); write_int (f, picture1); write_int (f, picture2); fputc (material, f); fputc (construction, f); fputc (color, f); fputc (weight, f); fputc (null7, f); write_int (f, null8); write_int (f, enchant_pts); write_long (f, null9); for (i = 0; i < 10; i++) write_long (f, enchantments[i]); /* Write the rest of the data, if any */ if (data_length && data) { if (fwrite (data, sizeof(char), data_length, f) != data_length) return (FALSE); } return (TRUE); } /*========== End of Function ITEM_RECORD::save_record() ===================*/ /*========== Searchs the enchantment array for a match ====================*/ short find_enchantment (const long id) { int i; short type = id & 0xFFFF; short sub_type = (id >> 16) & 0xFFFF; for (i = 0; i < num_enchants; i++) { if (enchants[i]->type == type && (enchants[i]->subtype == sub_type || enchants[i]->subtype == ENALL)) { return (i); } } if (id == -1) return (i); else { write_log_entry ("Unknown Enchantment: %d / %d", type, sub_type); return (-1); } } /*========== End of Function find_enchantment() ===========================*/ /*========== Searchs Through the item_type Array for a Match ==============*/ short find_item (const short group, const short sub_group) { int i; for (i = 0; i < num_items; i++) { if (items[i]->group != -1 && group == items[i]->group && (sub_group == -1 || sub_group == items[i]->sub_group)) return (i); } if (group == -1 && sub_group == -1) return (i); else { write_log_entry ("Unknown Item: %d / %d", group, sub_group); return (-1); } } /*========== End of Function find_item() ==================================*/ /*========== Searches for a Picture in the picture_types[] array ==========*/ short find_picture (const ITEM_RECORD *item) { short i; for (i = 0; i < num_pictures; i++) { if (pictures[i]->index == item->picture1) return (i); } write_log_entry ("Unknown Picture = 0x%04X, Item = '%s'", item->picture1, item->name); return (-1); } /*========== End of Function find_picture() ===============================*/