2 Copyright (C) 2001-2006, William Joseph.
5 This file is part of GtkRadiant.
7 GtkRadiant is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 GtkRadiant is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GtkRadiant; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
24 #include "idatastream.h"
26 #include "bytestreamutils.h"
28 #include "stream/filestream.h"
32 #include "archivelib.h"
35 #include "string/string.h"
39 class WadArchive : public Archive
44 wad_record_t( unsigned int position, unsigned int stream_size, unsigned int file_size )
45 : m_position( position ), m_stream_size( stream_size ), m_file_size( file_size )
47 unsigned int m_position;
48 unsigned int m_stream_size;
49 unsigned int m_file_size;
59 typedef std::map<CopiedString, wad_record_t, StringLessNoCase> files_t;
62 FileInputStream m_wadfile;
64 EWadVersion wad_version( const char* identification ){
65 if ( strncmp( identification, "WAD2", 4 ) == 0 ) {
68 if ( strncmp( identification, "WAD3", 4 ) == 0 ) {
74 const char* type_for_version( EWadVersion version ){
87 int miptex_type_for_version( EWadVersion version ){
101 WadArchive( const char* name )
102 : m_name( name ), m_wadfile( name ){
103 if ( !m_wadfile.failed() ) {
105 istream_read_wadinfo( m_wadfile, wadinfo );
107 EWadVersion version = wad_version( wadinfo.identification );
108 int miptexType = miptex_type_for_version( version );
110 if ( version != eNotValid ) {
111 m_wadfile.seek( wadinfo.infotableofs );
113 for ( int i = 0; i < wadinfo.numlumps; ++i )
117 istream_read_lumpinfo( m_wadfile, lumpinfo );
118 if ( lumpinfo.type == miptexType ) {
119 strcpy( buffer, "textures/" );
120 strcat( buffer, lumpinfo.name );
121 strcat( buffer, type_for_version( version ) );
122 m_files.insert( files_t::value_type( buffer, wad_record_t( lumpinfo.filepos, lumpinfo.disksize, lumpinfo.size ) ) );
132 ArchiveFile* openFile( const char* name ){
133 files_t::iterator i = m_files.find( name );
134 if ( i != m_files.end() ) {
135 return StoredArchiveFile::create( name, m_name.c_str(), i->second.m_position, i->second.m_stream_size, i->second.m_file_size );
139 virtual ArchiveTextFile* openTextFile( const char* name ){
140 files_t::iterator i = m_files.find( name );
141 if ( i != m_files.end() ) {
142 return StoredArchiveTextFile::create( name, m_name.c_str(), i->second.m_position, i->second.m_stream_size );
146 bool containsFile( const char* name ){
147 return m_files.find( name ) != m_files.end();
149 void forEachFile( VisitorFunc visitor, const char* root ){
150 if ( root[0] == '\0' ) {
151 if ( visitor.directory( "textures/", 1 ) ) {
155 else if ( strcmp( root, "textures/" ) != 0 ) {
159 for ( files_t::iterator i = m_files.begin(); i != m_files.end(); ++i )
160 visitor.file( i->first.c_str() );
165 Archive* OpenArchive( const char* name ){
166 return new WadArchive( name );
173 class TestVisitor : public Archive::IVisitor
176 void visit( const char* name ){
183 Archive* archive = OpenArchive( "" );
187 Archive* archive = OpenArchive( "NONEXISTANTFILE" );
191 Archive* archive = OpenArchive( "c:/quake/id1/quake101.wad" );
192 ArchiveFile* file = archive->openFile( "textures/sky1.mip" );
194 unsigned char* buffer = new unsigned char[file->size()];
195 file->getInputStream().read( (InputStream::byte_type*)buffer, file->size() );
200 archive->forEachFile( Archive::VisitorFunc( &visitor, Archive::eFilesAndDirectories, 1 ), "" );
201 archive->forEachFile( Archive::VisitorFunc( &visitor, Archive::eFilesAndDirectories, 0 ), "" );
202 archive->forEachFile( Archive::VisitorFunc( &visitor, Archive::eFilesAndDirectories, 0 ), "textures/" );
203 archive->forEachFile( Archive::VisitorFunc( &visitor, Archive::eFilesAndDirectories, 1 ), "textures/" );