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"
37 #include "string/string.h"
41 class WadArchive : public Archive
46 wad_record_t( unsigned int position, unsigned int stream_size, unsigned int file_size )
47 : m_position( position ), m_stream_size( stream_size ), m_file_size( file_size )
49 unsigned int m_position;
50 unsigned int m_stream_size;
51 unsigned int m_file_size;
61 typedef std::map<CopiedString, wad_record_t, StringLessNoCase> files_t;
64 FileInputStream m_wadfile;
66 EWadVersion wad_version( const char* identification ){
67 if ( strncmp( identification, "WAD2", 4 ) == 0 ) {
70 if ( strncmp( identification, "WAD3", 4 ) == 0 ) {
76 const char* type_for_version( EWadVersion version ){
89 int miptex_type_for_version( EWadVersion version ){
103 WadArchive( const char* name )
104 : m_name( name ), m_wadfile( name ){
105 if ( !m_wadfile.failed() ) {
107 istream_read_wadinfo( m_wadfile, wadinfo );
109 EWadVersion version = wad_version( wadinfo.identification );
110 int miptexType = miptex_type_for_version( version );
112 if ( version != eNotValid ) {
113 m_wadfile.seek( wadinfo.infotableofs );
115 for ( int i = 0; i < wadinfo.numlumps; ++i )
119 istream_read_lumpinfo( m_wadfile, lumpinfo );
120 if ( lumpinfo.type == miptexType ) {
121 strcpy( buffer, "textures/" );
122 strcat( buffer, lumpinfo.name );
123 strcat( buffer, type_for_version( version ) );
124 m_files.insert( files_t::value_type( buffer, wad_record_t( lumpinfo.filepos, lumpinfo.disksize, lumpinfo.size ) ) );
134 ArchiveFile* openFile( const char* name ){
135 files_t::iterator i = m_files.find( name );
136 if ( i != m_files.end() ) {
137 return StoredArchiveFile::create( name, m_name.c_str(), i->second.m_position, i->second.m_stream_size, i->second.m_file_size );
141 virtual ArchiveTextFile* openTextFile( const char* name ){
142 files_t::iterator i = m_files.find( name );
143 if ( i != m_files.end() ) {
144 return StoredArchiveTextFile::create( name, m_name.c_str(), i->second.m_position, i->second.m_stream_size );
148 bool containsFile( const char* name ){
149 return m_files.find( name ) != m_files.end();
151 void forEachFile( VisitorFunc visitor, const char* root ){
152 if ( root[0] == '\0' ) {
153 if ( visitor.directory( "textures/", 1 ) ) {
157 else if ( strcmp( root, "textures/" ) != 0 ) {
161 for ( files_t::iterator i = m_files.begin(); i != m_files.end(); ++i )
162 visitor.file( i->first.c_str() );
167 Archive* OpenArchive( const char* name ){
168 return new WadArchive( name );
175 class TestVisitor : public Archive::IVisitor
178 void visit( const char* name ){
185 Archive* archive = OpenArchive( "" );
189 Archive* archive = OpenArchive( "NONEXISTANTFILE" );
193 Archive* archive = OpenArchive( "c:/quake/id1/quake101.wad" );
194 ArchiveFile* file = archive->openFile( "textures/sky1.mip" );
196 unsigned char* buffer = new unsigned char[file->size()];
197 file->getInputStream().read( (InputStream::byte_type*)buffer, file->size() );
202 archive->forEachFile( Archive::VisitorFunc( &visitor, Archive::eFilesAndDirectories, 1 ), "" );
203 archive->forEachFile( Archive::VisitorFunc( &visitor, Archive::eFilesAndDirectories, 0 ), "" );
204 archive->forEachFile( Archive::VisitorFunc( &visitor, Archive::eFilesAndDirectories, 0 ), "textures/" );
205 archive->forEachFile( Archive::VisitorFunc( &visitor, Archive::eFilesAndDirectories, 1 ), "textures/" );