//********************************************************************************** // REJECT.EXE - Reject data table builder for DOOM // Copyright (C) 1994 L.M.WITEK // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 1, or (at your option) // any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. //********************************************************************************** #include #include #include #include "debug.hpp" #include "pwad.hpp" /********************************************************************************* ** ** AUTHOR: L.M.Witek DATE:26-May-1994 ** ** FUNCTION: CTOR for PWAD class. Opens the PWAD and builds an internal ** dirctory for records in the PWAD. ** ** ENTRY: name of the pwad to open. ** *********************************************************************************/ CPWad::CPWad (XString name) : file (name, O_RDWR | O_BINARY), currentmap(0) { if (file.IsOpen()) { // -=- read the pwad header -=- cout << "Opened '" << name << "'" << endl; cdebug.out << "Opened '" << name << "'" << endl; file.Read (&header, sizeof(PWAD_HEADER)); if (memcmp ("PWAD", header.signature, 4) != 0) { cout << "Not a PWAD!" << "\n"; cdebug.out << "Not a PWAD!" << "\n"; Fail (); return; } else { cdebug.out << "File size: " << file.Size() << endl; cdebug.out << "Directory Offset: " << header.dir_offset << endl; cdebug.out << "Directory Entries: " << header.dir_entries << endl; } // -=- read the directory -=- file.Seek (header.dir_offset); MemHandle dirbuff = file.Read (header.dir_entries * sizeof(DIR_ENTRY)); if (dirbuff.Size () != (header.dir_entries * sizeof(DIR_ENTRY))) { cout << "Error Reading PWAD Directory." << endl; cdebug.out << "Error Reading PWAD Directory." << endl; Fail (); } else { cout << "Building directory...." << flush; // -=- go through each dir entry and add it to our internal dir -=- DIR_ENTRY *entry_ptr = (DIR_ENTRY *)dirbuff.Buffer(); for (int n = 0; n < header.dir_entries; n++) { AddEntry (entry_ptr[n]); } cout << "Done." << endl; // -=- print out directory used for debugging -=- CDirEntry *de; CDirEntry *sde; de = (CDirEntry *)directory.FirstItem (); while (de) { cdebug.out << de->GetKey() << " " << de->Size() << " bytes\t @" << de->Offset() << endl; sde = (CDirEntry *)de->subdir.FirstItem (); while (sde) { cdebug.out << " " << sde->GetKey() << " " << sde->Size() << " bytes\t @" << sde->Offset() << endl; sde = (CDirEntry *)sde->Next(); } de = (CDirEntry *)de->Next(); } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- } } else { cout << "Cannot open '" << name << "'" << endl; cdebug.out << "Cannot open '" << name << "'" << endl; Fail (); } } void CPWad::AddEntry (DIR_ENTRY &entry) { char namebuf[9]; namebuf[8] = 0; memcpy (namebuf, entry.resource_name, 8); XString name (namebuf); // -=- test for map level marker -=- if ((name[0] == 'E') && (name[2] == 'M') && (entry.resource_size == 0)) { // -=- add map header entry to dir and set up current map -=- directory.AddItem (currentmap = new CDirEntry (name, 0, 0)); } else { // -=- put all map related records in the list in the sub dir of the map -=- // -=- all other items go in the main dir -=- if ((name == "THINGS") || (name == "LINEDEFS") || (name == "SIDEDEFS") || (name == "VERTEXES") || (name == "SEGS" ) || (name == "SSECTORS") || (name == "NODES" ) || (name == "SECTORS" ) || (name == "REJECT") || (name == "BLOCKMAP")) { currentmap->subdir.AddItem (new CDirEntry (name, entry.resource_offset, entry.resource_size)); } else { directory.AddItem (new CDirEntry (name, entry.resource_offset, entry.resource_size)); currentmap = 0; } } } MemHandle CPWad::Read (XString map, XString item) { CDirEntry *entry = (CDirEntry *)directory[map]; if (entry) { entry = (CDirEntry *)entry->subdir[item]; if (entry) { file.Seek (entry->Offset()); MemHandle data = file.Read (entry->Size()); if (data.Size() == entry->Size()) { cdebug.out << "Read From PWAD " << map << " " << item << " " << data.Size() << " bytes" << endl; return data; } } } cerr << "Read From PWAD " << map << " " << item << " FAILED!! " << endl; cdebug.out << "Read From PWAD " << map << " " << item << " FAILED!! " << endl; return 0; } int CPWad::Write (MemHandle data, XString map, XString item) { CDirEntry *entry = (CDirEntry *)directory[map]; if (entry) { entry = (CDirEntry *)entry->subdir[item]; if (entry) { file.Seek (entry->Offset()); if (data.Size() == entry->Size()) { int status = file.Write (data); cdebug.out << "Write to PWAD " << map << " " << item << " " << data.Size() << " bytes" << endl; return status; } } } cerr << "Write to PWAD " << map << " " << item << " FAILED!! " << endl; cdebug.out << "Write to PWAD " << map << " " << item << " FAILED!! " << endl; return -1; } MemHandle CPWad::Read (XString item) { CDirEntry *entry = (CDirEntry *)directory[item]; if (entry) { file.Seek (entry->Offset()); MemHandle data = file.Read (entry->Size()); if (data.Size() == entry->Size()) return data; } return 0; }