Add support for WAD2/WAD3 loading, as well as fixed PAK support.

This commit is contained in:
Marco Cawthorne 2022-01-23 12:11:44 -08:00
parent 36add9020c
commit c353639515
Signed by: eukara
GPG key ID: C196CD8BA993248A
34 changed files with 4518 additions and 820 deletions

View file

@ -110,6 +110,8 @@ virtual qtexture_t* getBump() const = 0;
virtual qtexture_t* getSpecular() const = 0; virtual qtexture_t* getSpecular() const = 0;
// get shader name // get shader name
virtual const char* getName() const = 0; virtual const char* getName() const = 0;
virtual const char* getWadName() const = 0;
virtual void setWadName( const char* name ) = 0;
virtual bool IsInUse() const = 0; virtual bool IsInUse() const = 0;
virtual void SetInUse( bool bInUse ) = 0; virtual void SetInUse( bool bInUse ) = 0;
// get the editor flags (QER_NOCARVE QER_TRANS) // get the editor flags (QER_NOCARVE QER_TRANS)

View file

@ -72,6 +72,12 @@ inline bool path_equal( const char* path, const char* other ){
#endif #endif
} }
/// \brief Returns true if \p path and \p other refer to the same file or directory, case insensitively.
/// O(n)
inline bool path_equal_i( const char* path, const char* other ){
return string_equal_nocase( path, other );
}
/// \brief Returns true if the first \p n bytes of \p path and \p other form paths that refer to the same file or directory. /// \brief Returns true if the first \p n bytes of \p path and \p other form paths that refer to the same file or directory.
/// If the paths are UTF-8 encoded, [\p path, \p path + \p n) must be a complete path. /// If the paths are UTF-8 encoded, [\p path, \p path + \p n) must be a complete path.
/// O(n) /// O(n)
@ -175,6 +181,12 @@ inline bool extension_equal( const char* extension, const char* other ){
return path_equal( extension, other ); return path_equal( extension, other );
} }
/// \brief Returns true if \p extension is of the same type as \p other, case insensitively.
/// O(n)
inline bool extension_equal_i( const char* extension, const char* other ){
return path_equal_i( extension, other );
}
template<typename Functor> template<typename Functor>
class MatchFileExtension class MatchFileExtension
{ {

View file

@ -1,11 +1,15 @@
all: all:
mkdir -p ../build/plugins mkdir -p ../build/plugins
cd archivezip && $(MAKE) cd archivezip && $(MAKE)
cd archivewad && $(MAKE)
cd archivepak && $(MAKE)
cd entity && $(MAKE) cd entity && $(MAKE)
cd image && $(MAKE) cd image && $(MAKE)
cd imagehl && $(MAKE)
cd iqmmodel && $(MAKE) cd iqmmodel && $(MAKE)
cd mapq3 && $(MAKE) cd mapq3 && $(MAKE)
cd model && $(MAKE) cd model && $(MAKE)
cd matsys && $(MAKE)
cd shaders && $(MAKE) cd shaders && $(MAKE)
cd vfspk3 && $(MAKE) cd vfspk3 && $(MAKE)
cd brushexport && $(MAKE) cd brushexport && $(MAKE)
@ -13,12 +17,16 @@ all:
clean: clean:
-rm -rf ../build/plugins -rm -rf ../build/plugins
cd archivezip && $(MAKE) clean cd archivezip && $(MAKE) clean
cd archivewad && $(MAKE) clean
cd archivepak && $(MAKE) clean
cd entity && $(MAKE) clean cd entity && $(MAKE) clean
cd image && $(MAKE) clean cd image && $(MAKE) clean
cd imagehl && $(MAKE) clean
cd iqmmodel && $(MAKE) clean cd iqmmodel && $(MAKE) clean
cd mapq3 && $(MAKE) clean cd mapq3 && $(MAKE) clean
cd model && $(MAKE) clean cd model && $(MAKE) clean
cd shaders && $(MAKE) clean cd shaders && $(MAKE) clean
cd matsys && $(MAKE) clean
cd vfspk3 && $(MAKE) clean cd vfspk3 && $(MAKE) clean
cd brushexport && $(MAKE) clean cd brushexport && $(MAKE) clean
cd prtview && $(MAKE) clean cd prtview && $(MAKE) clean

View file

@ -0,0 +1,23 @@
# WorldSpawn Plugin Makefile
PLUGIN_CFLAGS=$(CFLAGS) -I../../include -I../../libs -fPIC -fvisibility=hidden
PLUGIN_LDFLAGS=$(LDFLAGS) -shared
DO_CXX=$(CXX) $(PLUGIN_CFLAGS) -o $@ -c $<
.cpp.o:
$(DO_CXX)
WS_OBJS = \
archive.o plugin.o
# binary target
../../build/plugins/libarchivepak.so: $(WS_OBJS)
$(CXX) -o $@ $(WS_OBJS) $(PLUGIN_LDFLAGS)
# object files
archive.o: archive.cpp archive.h
plugin.o: plugin.cpp
clean:
-rm -f *.o ../../build/plugins/libarchivepak.so

View file

@ -0,0 +1,208 @@
/*
Copyright (C) 2001-2006, William Joseph.
All Rights Reserved.
This file is part of GtkRadiant.
GtkRadiant 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 2 of the License, or
(at your option) any later version.
GtkRadiant 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 GtkRadiant; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "archive.h"
#include "idatastream.h"
#include "cmdlib.h"
#include "bytestreamutils.h"
#include <algorithm>
#include "stream/filestream.h"
#include "iarchive.h"
#include "archivelib.h"
#include <map>
#include "string/string.h"
#include "fs_filesystem.h"
inline void buffer_findreplace( char* buffer, char find, char replace ){
while ( *buffer != '\0' )
{
if ( *buffer == find ) {
*buffer = replace;
}
++buffer;
}
}
#include "pak.h"
class PakArchive : public Archive
{
class PakRecord
{
public:
PakRecord( unsigned int position, unsigned int stream_size )
: m_position( position ), m_stream_size( stream_size ){
}
unsigned int m_position;
unsigned int m_stream_size;
};
typedef GenericFileSystem<PakRecord> PakFileSystem;
PakFileSystem m_filesystem;
FileInputStream m_pakfile;
CopiedString m_name;
public:
PakArchive( const char* name )
: m_pakfile( name ), m_name( name ){
if ( !m_pakfile.failed() ) {
pakheader_t header;
m_pakfile.read( reinterpret_cast<FileInputStream::byte_type*>( header.magic ), 4 );
header.diroffset = istream_read_uint32_le( m_pakfile );
header.dirsize = istream_read_uint32_le( m_pakfile );
if ( strncmp( header.magic, "PACK", 4 ) == 0 ) {
m_pakfile.seek( header.diroffset );
for ( unsigned int i = 0; i < header.dirsize; i += sizeof( pakentry_t ) )
{
pakentry_t entry;
m_pakfile.read( reinterpret_cast<FileInputStream::byte_type*>( entry.filename ), 0x38 );
entry.offset = istream_read_uint32_le( m_pakfile );
entry.size = istream_read_uint32_le( m_pakfile );
buffer_findreplace( entry.filename, '\\', '/' );
PakFileSystem::entry_type& file = m_filesystem[entry.filename];
if ( !file.is_directory() ) {
globalOutputStream() << "Warning: pak archive " << makeQuoted( m_name.c_str() ) << " contains duplicated file: " << makeQuoted( entry.filename ) << "\n";
}
else
{
file = new PakRecord( entry.offset, entry.size );
}
}
}
}
}
~PakArchive(){
for ( PakFileSystem::iterator i = m_filesystem.begin(); i != m_filesystem.end(); ++i )
delete i->second.file();
}
void release(){
delete this;
}
ArchiveFile* openFile( const char* name ){
PakFileSystem::iterator i = m_filesystem.find( name );
if ( i != m_filesystem.end() && !i->second.is_directory() ) {
PakRecord* file = i->second.file();
return StoredArchiveFile::create( name, m_name.c_str(), file->m_position, file->m_stream_size, file->m_stream_size );
}
return 0;
}
virtual ArchiveTextFile* openTextFile( const char* name ){
PakFileSystem::iterator i = m_filesystem.find( name );
if ( i != m_filesystem.end() && !i->second.is_directory() ) {
PakRecord* file = i->second.file();
return StoredArchiveTextFile::create( name, m_name.c_str(), file->m_position, file->m_stream_size );
}
return 0;
}
bool containsFile( const char* name ){
PakFileSystem::iterator i = m_filesystem.find( name );
return i != m_filesystem.end() && !i->second.is_directory();
}
void forEachFile( VisitorFunc visitor, const char* root ){
m_filesystem.traverse( visitor, root );
}
};
Archive* OpenArchive( const char* name ){
return new PakArchive( name );
}
#if 0
class TestArchive
{
public:
TestArchive(){
Archive* archive = OpenArchive( "c:/quake3/baseq3/pak0.pak" );
ArchiveFile* file = archive->openFile( "gfx/palette.lmp" );
if ( file != 0 ) {
char buffer[1024];
file->getInputStream().read( (InputStream::byte_type*)buffer, 1024 );
file->release();
}
archive->release();
}
};
TestArchive g_test;
#endif
#if 0
class TestArchive
{
class TestVisitor : public Archive::IVisitor
{
public:
void visit( const char* name ){
int bleh = 0;
}
};
public:
TestArchive(){
{
Archive* archive = OpenArchive( "" );
archive->release();
}
{
Archive* archive = OpenArchive( "NONEXISTANTFILE" );
archive->release();
}
{
Archive* archive = OpenArchive( "c:/quake/id1/pak0.pak" );
ArchiveFile* file = archive->openFile( "gfx/palette.lmp" );
if ( file != 0 ) {
char buffer[1024];
file->getInputStream().read( (InputStream::byte_type*)buffer, 1024 );
file->release();
}
TestVisitor visitor;
archive->forEachFile( Archive::VisitorFunc( &visitor, Archive::eFilesAndDirectories, 0 ), "" );
archive->forEachFile( Archive::VisitorFunc( &visitor, Archive::eFiles, 0 ), "progs/" );
archive->forEachFile( Archive::VisitorFunc( &visitor, Archive::eFiles, 0 ), "maps/" );
archive->forEachFile( Archive::VisitorFunc( &visitor, Archive::eFiles, 1 ), "sound/ambience/" );
archive->forEachFile( Archive::VisitorFunc( &visitor, Archive::eFilesAndDirectories, 1 ), "sound/" );
archive->forEachFile( Archive::VisitorFunc( &visitor, Archive::eDirectories, 1 ), "sound/" );
archive->forEachFile( Archive::VisitorFunc( &visitor, Archive::eFilesAndDirectories, 2 ), "sound/" );
archive->forEachFile( Archive::VisitorFunc( &visitor, Archive::eFilesAndDirectories, 2 ), "" );
archive->release();
}
}
};
TestArchive g_test;
#endif

View file

@ -0,0 +1,23 @@
/*
Copyright (C) 2001-2006, William Joseph.
All Rights Reserved.
This file is part of GtkRadiant.
GtkRadiant 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 2 of the License, or
(at your option) any later version.
GtkRadiant 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 GtkRadiant; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
class Archive;
Archive* OpenArchive( const char* name );

39
plugins/archivepak/pak.h Normal file
View file

@ -0,0 +1,39 @@
/*
Copyright (C) 2001-2006, William Joseph.
All Rights Reserved.
This file is part of GtkRadiant.
GtkRadiant 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 2 of the License, or
(at your option) any later version.
GtkRadiant 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 GtkRadiant; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#if !defined( INCLUDED_PAK_H )
#define INCLUDED_PAK_H
struct pakheader_t
{
char magic[4]; // Name of the new WAD format ("PACK")
unsigned int diroffset; // Position of WAD directory from start of file
unsigned int dirsize; // Number of entries * 0x40 (64 char)
};
struct pakentry_t
{
char filename[0x38]; // Name of the file, Unix style, with extension, 50 chars, padded with '\0'.
unsigned int offset; // Position of the entry in PACK file
unsigned int size; // Size of the entry in PACK file
};
#endif

View file

@ -0,0 +1,53 @@
/*
Copyright (C) 2001-2006, William Joseph.
All Rights Reserved.
This file is part of GtkRadiant.
GtkRadiant 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 2 of the License, or
(at your option) any later version.
GtkRadiant 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 GtkRadiant; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "iarchive.h"
#include "debugging/debugging.h"
#include "modulesystem/singletonmodule.h"
#include "archive.h"
class ArchivePakAPI
{
_QERArchiveTable m_archivepak;
public:
typedef _QERArchiveTable Type;
STRING_CONSTANT( Name, "pak" );
ArchivePakAPI(){
m_archivepak.m_pfnOpenArchive = &OpenArchive;
}
_QERArchiveTable* getTable(){
return &m_archivepak;
}
};
typedef SingletonModule<ArchivePakAPI> ArchivePakModule;
ArchivePakModule g_ArchivePakModule;
extern "C" void RADIANT_DLLEXPORT Radiant_RegisterModules( ModuleServer& server ){
initialiseModule( server );
g_ArchivePakModule.selfRegister();
}

View file

@ -0,0 +1,23 @@
# WorldSpawn Plugin Makefile
PLUGIN_CFLAGS=$(CFLAGS) -I../../include -I../../libs -fPIC -fvisibility=hidden
PLUGIN_LDFLAGS=$(LDFLAGS) -shared
DO_CXX=$(CXX) $(PLUGIN_CFLAGS) -o $@ -c $<
.cpp.o:
$(DO_CXX)
WS_OBJS = \
archive.o plugin.o
# binary target
../../build/plugins/libarchivewad.so: $(WS_OBJS)
$(CXX) -o $@ $(WS_OBJS) $(PLUGIN_LDFLAGS)
# object files
archive.o: archive.cpp archive.h
plugin.o: plugin.cpp
clean:
-rm -f *.o ../../build/plugins/libarchivewad.so

View file

@ -0,0 +1,211 @@
/*
Copyright (C) 2001-2006, William Joseph.
All Rights Reserved.
This file is part of GtkRadiant.
GtkRadiant 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 2 of the License, or
(at your option) any later version.
GtkRadiant 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 GtkRadiant; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "archive.h"
#include "idatastream.h"
#include "bytestreamutils.h"
#include <algorithm>
#include "stream/filestream.h"
#include "iarchive.h"
#include "archivelib.h"
#include <map>
#include "string/string.h"
#include "wad.h"
class WadArchive final : public Archive
{
class wad_record_t
{
public:
wad_record_t( unsigned int position, unsigned int stream_size, unsigned int file_size )
: m_position( position ), m_stream_size( stream_size ), m_file_size( file_size )
{}
unsigned int m_position;
unsigned int m_stream_size;
unsigned int m_file_size;
};
enum EWadVersion
{
eNotValid,
eWAD2,
eWAD3,
};
typedef std::map<CopiedString, wad_record_t, StringLessNoCase> files_t;
files_t m_files;
CopiedString m_name;
FileInputStream m_wadfile;
EWadVersion wad_version( const char* identification ){
if ( strncmp( identification, "WAD2", 4 ) == 0 ) {
return eWAD2;
}
if ( strncmp( identification, "WAD3", 4 ) == 0 ) {
return eWAD3;
}
return eNotValid;
}
const char* type_for_version( EWadVersion version ){
switch ( version )
{
case eWAD2:
return ".mip";
case eWAD3:
return ".hlw";
default:
break;
}
return "";
}
int miptex_type_for_version( EWadVersion version ){
switch ( version )
{
case eWAD2:
return TYP_MIPTEX;
case eWAD3:
return 67;
default:
break;
}
return -1;
}
public:
WadArchive( const char* name )
: m_name( name ), m_wadfile( name ){
if ( !m_wadfile.failed() ) {
wadinfo_t wadinfo;
istream_read_wadinfo( m_wadfile, wadinfo );
EWadVersion version = wad_version( wadinfo.identification );
int miptexType = miptex_type_for_version( version );
if ( version != eNotValid ) {
m_wadfile.seek( wadinfo.infotableofs );
for ( int i = 0; i < wadinfo.numlumps; ++i )
{
char buffer[32];
lumpinfo_t lumpinfo;
istream_read_lumpinfo( m_wadfile, lumpinfo );
if ( lumpinfo.type == miptexType ) {
strcpy( buffer, "textures/" );
strcat( buffer, lumpinfo.name );
strcat( buffer, type_for_version( version ) );
m_files.insert( files_t::value_type( buffer, wad_record_t( lumpinfo.filepos, lumpinfo.disksize, lumpinfo.size ) ) );
}
}
}
}
}
void release(){
delete this;
}
ArchiveFile* openFile( const char* name ){
files_t::iterator i = m_files.find( name );
if ( i != m_files.end() ) {
return StoredArchiveFile::create( name, m_name.c_str(), i->second.m_position, i->second.m_stream_size, i->second.m_file_size );
}
return 0;
}
virtual ArchiveTextFile* openTextFile( const char* name ){
files_t::iterator i = m_files.find( name );
if ( i != m_files.end() ) {
return StoredArchiveTextFile::create( name, m_name.c_str(), i->second.m_position, i->second.m_stream_size );
}
return 0;
}
bool containsFile( const char* name ){
return m_files.find( name ) != m_files.end();
}
void forEachFile( VisitorFunc visitor, const char* root ){
if ( root[0] == '\0' ) {
if ( visitor.directory( "textures/", 1 ) ) {
return;
}
}
else if ( strcmp( root, "textures/" ) != 0 ) {
return;
}
for ( files_t::iterator i = m_files.begin(); i != m_files.end(); ++i )
visitor.file( i->first.c_str() );
}
};
Archive* OpenArchive( const char* name ){
return new WadArchive( name );
}
#if 0
class TestArchive
{
class TestVisitor : public Archive::IVisitor
{
public:
void visit( const char* name ){
int bleh = 0;
}
};
public:
TestArchive(){
{
Archive* archive = OpenArchive( "" );
archive->release();
}
{
Archive* archive = OpenArchive( "NONEXISTANTFILE" );
archive->release();
}
{
Archive* archive = OpenArchive( "c:/quake/id1/quake101.wad" );
ArchiveFile* file = archive->openFile( "textures/sky1.mip" );
if ( file != 0 ) {
unsigned char* buffer = new unsigned char[file->size()];
file->getInputStream().read( (InputStream::byte_type*)buffer, file->size() );
delete[] buffer;
file->release();
}
TestVisitor visitor;
archive->forEachFile( Archive::VisitorFunc( &visitor, Archive::eFilesAndDirectories, 1 ), "" );
archive->forEachFile( Archive::VisitorFunc( &visitor, Archive::eFilesAndDirectories, 0 ), "" );
archive->forEachFile( Archive::VisitorFunc( &visitor, Archive::eFilesAndDirectories, 0 ), "textures/" );
archive->forEachFile( Archive::VisitorFunc( &visitor, Archive::eFilesAndDirectories, 1 ), "textures/" );
archive->release();
}
}
};
TestArchive g_test;
#endif

View file

@ -0,0 +1,23 @@
/*
Copyright (C) 2001-2006, William Joseph.
All Rights Reserved.
This file is part of GtkRadiant.
GtkRadiant 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 2 of the License, or
(at your option) any later version.
GtkRadiant 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 GtkRadiant; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
class Archive;
Archive* OpenArchive( const char* name );

View file

@ -0,0 +1,53 @@
/*
Copyright (C) 2001-2006, William Joseph.
All Rights Reserved.
This file is part of GtkRadiant.
GtkRadiant 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 2 of the License, or
(at your option) any later version.
GtkRadiant 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 GtkRadiant; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "iarchive.h"
#include "debugging/debugging.h"
#include "modulesystem/singletonmodule.h"
#include "archive.h"
class ArchiveWadAPI
{
_QERArchiveTable m_archivewad;
public:
typedef _QERArchiveTable Type;
STRING_CONSTANT( Name, "wad" );
ArchiveWadAPI(){
m_archivewad.m_pfnOpenArchive = &OpenArchive;
}
_QERArchiveTable* getTable(){
return &m_archivewad;
}
};
typedef SingletonModule<ArchiveWadAPI> ArchiveWadModule;
ArchiveWadModule g_ArchiveWadModule;
extern "C" void RADIANT_DLLEXPORT Radiant_RegisterModules( ModuleServer& server ){
initialiseModule( server );
g_ArchiveWadModule.selfRegister();
}

76
plugins/archivewad/wad.h Normal file
View file

@ -0,0 +1,76 @@
/*
Copyright (C) 2001-2006, William Joseph.
All Rights Reserved.
This file is part of GtkRadiant.
GtkRadiant 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 2 of the License, or
(at your option) any later version.
GtkRadiant 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 GtkRadiant; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#if !defined( INCLUDED_WAD_H )
#define INCLUDED_WAD_H
#include "bytestreamutils.h"
#include "idatastream.h"
#define CMP_NONE 0
#define CMP_LZSS 1
#define TYP_NONE 0
#define TYP_LABEL 1
#define TYP_LUMPY 64 // 64 + grab command number
#define TYP_PALETTE 64
#define TYP_QTEX 65
#define TYP_QPIC 66
#define TYP_SOUND 67
#define TYP_MIPTEX 68
typedef struct
{
char identification[4]; // should be WAD2 or 2DAW
int numlumps;
int infotableofs;
} wadinfo_t;
typedef struct
{
int filepos;
int disksize;
int size; // uncompressed
char type;
char compression;
char pad1, pad2;
char name[16]; // must be null terminated
} lumpinfo_t;
inline void istream_read_wadinfo( InputStream& istream, wadinfo_t& wadinfo ){
istream.read( reinterpret_cast<InputStream::byte_type*>( wadinfo.identification ), 4 );
wadinfo.numlumps = istream_read_int32_le( istream );
wadinfo.infotableofs = istream_read_int32_le( istream );
}
inline void istream_read_lumpinfo( InputStream& istream, lumpinfo_t& lumpinfo ){
lumpinfo.filepos = istream_read_int32_le( istream );
lumpinfo.disksize = istream_read_int32_le( istream );
lumpinfo.size = istream_read_int32_le( istream );
lumpinfo.type = istream_read_byte( istream );
lumpinfo.compression = istream_read_byte( istream );
lumpinfo.pad1 = istream_read_byte( istream );
lumpinfo.pad2 = istream_read_byte( istream );
istream.read( reinterpret_cast<InputStream::byte_type*>( lumpinfo.name ), 16 );
}
#endif

28
plugins/imagehl/Makefile Normal file
View file

@ -0,0 +1,28 @@
# WorldSpawn Plugin Makefile
GLIB_CFLAGS=$(shell pkg-config --cflags gtk+-2.0) -DGTK_TARGET=2
GLIB_LDFLAGS=$(shell pkg-config --libs gtk+-2.0)
PLUGIN_CFLAGS=$(CFLAGS) $(GLIB_CFLAGS) -I../../include -I../../libs -fPIC -fvisibility=hidden
PLUGIN_LDFLAGS=$(LDFLAGS) $(GLIB_LDFLAGS) -shared
DO_CXX=$(CXX) $(PLUGIN_CFLAGS) $(SHLIBCFLAGS) -o $@ -c $<
.cpp.o:
$(DO_CXX)
WS_OBJS = \
hlw.o imagehl.o mip.o sprite.o
# binary target
../../build/plugins/libimagehl.so: $(WS_OBJS)
$(CXX) -o $@ $(WS_OBJS) ../../libs/libuilib.a ../../libs/libgtkutil.a $(PLUGIN_LDFLAGS)
# object files
hlw.o: hlw.cpp hlw.h
imagehl.o: imagehl.cpp
mip.o: mip.cpp mip.h
sprite.o: sprite.cpp sprite.h
clean:
-rm -f *.o ../../build/plugins/libimagehl.so

153
plugins/imagehl/hlw.cpp Normal file
View file

@ -0,0 +1,153 @@
/*
Copyright (C) 1999-2006 Id Software, Inc. and contributors.
For a list of contributors, see the accompanying CONTRIBUTORS file.
This file is part of GtkRadiant.
GtkRadiant 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 2 of the License, or
(at your option) any later version.
GtkRadiant 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 GtkRadiant; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
// by Hydra - hydra@hydras-world.com
//
// HLW = Half-Life-WAD, I don't know if the actual in data in the WAD files
// has it's own name, so I'm just calling the individal textures .HLW files :)
//
// Thanks to the guys that made Wally for releasing an example WAD loader.
// without it this would not have been possible.
#include "hlw.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
typedef unsigned char byte;
#include "ifilesystem.h"
#include "imagelib.h"
/*
============================================================================
HLW IMAGE
HalfLife WAD files contain files that look like this:
Mip section
First mip
Mip header
First mip (width * height)
Second mip (width * height / 4)
Third mip (width * height / 16)
Fourth mip (width * height / 64)
Palette size (WORD)
Palette (Palette size * 3)
Padding (WORD)
============================================================================
*/
#define GET_MIP_DATA_SIZE( WIDTH, HEIGHT ) ( sizeof( WAD3_MIP ) + ( WIDTH * HEIGHT ) + ( WIDTH * HEIGHT / 4 ) + ( WIDTH * HEIGHT / 16 ) + ( WIDTH * HEIGHT / 64 ) )
typedef struct
{
char name[16];
unsigned int width, height;
unsigned int offsets[4]; // four mip maps stored
} WAD3_MIP, *LPWAD3_MIP;
/*
=========================================================
HLW LOADING
Hydra: this code isn't bullet proof and probably won't
like corrupt WAD files, but it works for now.
TODO: make it more robust.
=========================================================
*/
/*
=============
LoadHLW
=============
*/
Image* LoadHLWBuff( byte* buffer ){
byte *buf_p;
unsigned long mipdatasize;
int columns, rows;
byte *pixbuf;
int row, column;
byte *palette;
LPWAD3_MIP lpMip;
unsigned char red, green, blue, alphabyte;
lpMip = (LPWAD3_MIP)buffer; //!\todo Make endian-safe.
mipdatasize = GET_MIP_DATA_SIZE( lpMip->width,lpMip->height );
palette = buffer + mipdatasize + 2;
buf_p = buffer + lpMip->offsets[0];
columns = lpMip->width;
rows = lpMip->height;
RGBAImage* image = new RGBAImage( columns, rows );
for ( row = 0; row < rows; row++ )
{
pixbuf = image->getRGBAPixels() + row * columns * 4;
for ( column = 0; column < columns; column++ )
{
int palIndex;
palIndex = *buf_p++;
red = *( palette + ( palIndex * 3 ) );
green = *( palette + ( palIndex * 3 ) + 1 );
blue = *( palette + ( palIndex * 3 ) + 2 );
// HalfLife engine makes pixels that are BLUE transparent.
// So show them that way in the editor.
if ( blue == 0xff && red == 0x00 && green == 0x00 ) {
alphabyte = 0x00;
blue = 0x00; // don't set the resulting pixel to blue
}
else
{
alphabyte = 0xff;
}
*pixbuf++ = red;
*pixbuf++ = green;
*pixbuf++ = blue;
*pixbuf++ = alphabyte;
}
}
return image;
}
Image* LoadHLW( ArchiveFile& file ){
ScopedArchiveBuffer buffer( file );
return LoadHLWBuff( buffer.buffer );
}

30
plugins/imagehl/hlw.h Normal file
View file

@ -0,0 +1,30 @@
/*
Copyright (C) 1999-2006 Id Software, Inc. and contributors.
For a list of contributors, see the accompanying CONTRIBUTORS file.
This file is part of GtkRadiant.
GtkRadiant 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 2 of the License, or
(at your option) any later version.
GtkRadiant 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 GtkRadiant; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#if !defined ( INCLUDED_HLW_H )
#define INCLUDED_HLW_H
class Image;
class ArchiveFile;
Image* LoadHLW( ArchiveFile& file );
#endif

104
plugins/imagehl/imagehl.cpp Normal file
View file

@ -0,0 +1,104 @@
/*
Copyright (C) 2001-2006, William Joseph.
All Rights Reserved.
This file is part of GtkRadiant.
GtkRadiant 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 2 of the License, or
(at your option) any later version.
GtkRadiant 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 GtkRadiant; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "debugging/debugging.h"
#include "ifilesystem.h"
#include "iimage.h"
#include "hlw.h"
#include "mip.h"
#include "sprite.h"
#include "modulesystem/singletonmodule.h"
class ImageDependencies : public GlobalFileSystemModuleRef
{
};
class ImageHLWAPI
{
_QERPlugImageTable m_imagehlw;
public:
typedef _QERPlugImageTable Type;
STRING_CONSTANT( Name, "hlw" );
ImageHLWAPI(){
m_imagehlw.loadImage = LoadHLW;
}
_QERPlugImageTable* getTable(){
return &m_imagehlw;
}
};
typedef SingletonModule<ImageHLWAPI, ImageDependencies> ImageHLWModule;
ImageHLWModule g_ImageHLWModule;
class ImageMipAPI
{
_QERPlugImageTable m_imagemip;
public:
typedef _QERPlugImageTable Type;
STRING_CONSTANT( Name, "mip" );
ImageMipAPI(){
m_imagemip.loadImage = LoadMIP;
}
_QERPlugImageTable* getTable(){
return &m_imagemip;
}
};
typedef SingletonModule<ImageMipAPI, ImageDependencies> ImageMipModule;
ImageMipModule g_ImageMipModule;
class ImageSpriteAPI
{
_QERPlugImageTable m_imagesprite;
public:
typedef _QERPlugImageTable Type;
STRING_CONSTANT( Name, "spr" );
ImageSpriteAPI(){
m_imagesprite.loadImage = LoadIDSP;
}
_QERPlugImageTable* getTable(){
return &m_imagesprite;
}
};
typedef SingletonModule<ImageSpriteAPI, ImageDependencies> ImageSpriteModule;
ImageSpriteModule g_ImageSpriteModule;
extern "C" void RADIANT_DLLEXPORT Radiant_RegisterModules( ModuleServer& server ){
initialiseModule( server );
g_ImageHLWModule.selfRegister();
g_ImageMipModule.selfRegister();
g_ImageSpriteModule.selfRegister();
}

View file

@ -0,0 +1,30 @@
ImageHL
=======
Coding by Dominic Clifton - Hydra - hydra@hydras-world.com
What is it ?
------------
This GTKRadiant 1.2+ plugin handles the loading of textures from .WAD files.
I'll refer to these textures as .HLW files, even though they don't have any
extension when they're stored in the .WAD file itself.
You need a VFS plugin to go with this plugin that can open and read .WAD files
My VFSWAD plugin does just this.
Developer Notes
---------------
The project file will copy the compiled DLL file and this .TXT file to
"$(HLRADIANTDIR)modules" so make sure you have that environment variable
defined.
For my GTKRadiant 1.2 HalfLife game pack files I use the directory:
"E:\games\HalfLife\Tools\GTKR12N". Under which there are the directories
"modules" and "plugins"
Credits
-------
Thanks to the guys that made Wally for releasing an example WAD loader.
without it this would not have been possible.

203
plugins/imagehl/mip.cpp Normal file
View file

@ -0,0 +1,203 @@
/*
Copyright (C) 1999-2006 Id Software, Inc. and contributors.
For a list of contributors, see the accompanying CONTRIBUTORS file.
This file is part of GtkRadiant.
GtkRadiant 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 2 of the License, or
(at your option) any later version.
GtkRadiant 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 GtkRadiant; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "mip.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
typedef unsigned char byte;
#include "ifilesystem.h"
#include "imagelib.h"
#include "bytestreamutils.h"
/*
============================================================================
MIP IMAGE
Quake WAD files contain miptex files that look like this:
Mip section
First mip
Mip header
First mip (width * height)
Second mip (width * height / 4)
Third mip (width * height / 16)
Fourth mip (width * height / 64)
============================================================================
*/
#define GET_MIP_DATA_SIZE( WIDTH, HEIGHT ) ( sizeof( WAD3_MIP ) + ( WIDTH * HEIGHT ) + ( WIDTH * HEIGHT / 4 ) + ( WIDTH * HEIGHT / 16 ) + ( WIDTH * HEIGHT / 64 ) )
const int MIP_NAME_LENGTH = 16;
const int MIP_MIPMAP_COUNT = 4;
typedef struct
{
char name[MIP_NAME_LENGTH];
unsigned int width, height;
unsigned int offsets[MIP_MIPMAP_COUNT]; // four mip maps stored
} WAD3_MIP, *LPWAD3_MIP;
static const byte quakepalette[768] =
{
0x00,0x00,0x00, 0x0f,0x0f,0x0f, 0x1f,0x1f,0x1f, 0x2f,0x2f,0x2f,
0x3f,0x3f,0x3f, 0x4b,0x4b,0x4b, 0x5b,0x5b,0x5b, 0x6b,0x6b,0x6b,
0x7b,0x7b,0x7b, 0x8b,0x8b,0x8b, 0x9b,0x9b,0x9b, 0xab,0xab,0xab,
0xbb,0xbb,0xbb, 0xcb,0xcb,0xcb, 0xdb,0xdb,0xdb, 0xeb,0xeb,0xeb,
0x0f,0x0b,0x07, 0x17,0x0f,0x0b, 0x1f,0x17,0x0b, 0x27,0x1b,0x0f,
0x2f,0x23,0x13, 0x37,0x2b,0x17, 0x3f,0x2f,0x17, 0x4b,0x37,0x1b,
0x53,0x3b,0x1b, 0x5b,0x43,0x1f, 0x63,0x4b,0x1f, 0x6b,0x53,0x1f,
0x73,0x57,0x1f, 0x7b,0x5f,0x23, 0x83,0x67,0x23, 0x8f,0x6f,0x23,
0x0b,0x0b,0x0f, 0x13,0x13,0x1b, 0x1b,0x1b,0x27, 0x27,0x27,0x33,
0x2f,0x2f,0x3f, 0x37,0x37,0x4b, 0x3f,0x3f,0x57, 0x47,0x47,0x67,
0x4f,0x4f,0x73, 0x5b,0x5b,0x7f, 0x63,0x63,0x8b, 0x6b,0x6b,0x97,
0x73,0x73,0xa3, 0x7b,0x7b,0xaf, 0x83,0x83,0xbb, 0x8b,0x8b,0xcb,
0x00,0x00,0x00, 0x07,0x07,0x00, 0x0b,0x0b,0x00, 0x13,0x13,0x00,
0x1b,0x1b,0x00, 0x23,0x23,0x00, 0x2b,0x2b,0x07, 0x2f,0x2f,0x07,
0x37,0x37,0x07, 0x3f,0x3f,0x07, 0x47,0x47,0x07, 0x4b,0x4b,0x0b,
0x53,0x53,0x0b, 0x5b,0x5b,0x0b, 0x63,0x63,0x0b, 0x6b,0x6b,0x0f,
0x07,0x00,0x00, 0x0f,0x00,0x00, 0x17,0x00,0x00, 0x1f,0x00,0x00,
0x27,0x00,0x00, 0x2f,0x00,0x00, 0x37,0x00,0x00, 0x3f,0x00,0x00,
0x47,0x00,0x00, 0x4f,0x00,0x00, 0x57,0x00,0x00, 0x5f,0x00,0x00,
0x67,0x00,0x00, 0x6f,0x00,0x00, 0x77,0x00,0x00, 0x7f,0x00,0x00,
0x13,0x13,0x00, 0x1b,0x1b,0x00, 0x23,0x23,0x00, 0x2f,0x2b,0x00,
0x37,0x2f,0x00, 0x43,0x37,0x00, 0x4b,0x3b,0x07, 0x57,0x43,0x07,
0x5f,0x47,0x07, 0x6b,0x4b,0x0b, 0x77,0x53,0x0f, 0x83,0x57,0x13,
0x8b,0x5b,0x13, 0x97,0x5f,0x1b, 0xa3,0x63,0x1f, 0xaf,0x67,0x23,
0x23,0x13,0x07, 0x2f,0x17,0x0b, 0x3b,0x1f,0x0f, 0x4b,0x23,0x13,
0x57,0x2b,0x17, 0x63,0x2f,0x1f, 0x73,0x37,0x23, 0x7f,0x3b,0x2b,
0x8f,0x43,0x33, 0x9f,0x4f,0x33, 0xaf,0x63,0x2f, 0xbf,0x77,0x2f,
0xcf,0x8f,0x2b, 0xdf,0xab,0x27, 0xef,0xcb,0x1f, 0xff,0xf3,0x1b,
0x0b,0x07,0x00, 0x1b,0x13,0x00, 0x2b,0x23,0x0f, 0x37,0x2b,0x13,
0x47,0x33,0x1b, 0x53,0x37,0x23, 0x63,0x3f,0x2b, 0x6f,0x47,0x33,
0x7f,0x53,0x3f, 0x8b,0x5f,0x47, 0x9b,0x6b,0x53, 0xa7,0x7b,0x5f,
0xb7,0x87,0x6b, 0xc3,0x93,0x7b, 0xd3,0xa3,0x8b, 0xe3,0xb3,0x97,
0xab,0x8b,0xa3, 0x9f,0x7f,0x97, 0x93,0x73,0x87, 0x8b,0x67,0x7b,
0x7f,0x5b,0x6f, 0x77,0x53,0x63, 0x6b,0x4b,0x57, 0x5f,0x3f,0x4b,
0x57,0x37,0x43, 0x4b,0x2f,0x37, 0x43,0x27,0x2f, 0x37,0x1f,0x23,
0x2b,0x17,0x1b, 0x23,0x13,0x13, 0x17,0x0b,0x0b, 0x0f,0x07,0x07,
0xbb,0x73,0x9f, 0xaf,0x6b,0x8f, 0xa3,0x5f,0x83, 0x97,0x57,0x77,
0x8b,0x4f,0x6b, 0x7f,0x4b,0x5f, 0x73,0x43,0x53, 0x6b,0x3b,0x4b,
0x5f,0x33,0x3f, 0x53,0x2b,0x37, 0x47,0x23,0x2b, 0x3b,0x1f,0x23,
0x2f,0x17,0x1b, 0x23,0x13,0x13, 0x17,0x0b,0x0b, 0x0f,0x07,0x07,
0xdb,0xc3,0xbb, 0xcb,0xb3,0xa7, 0xbf,0xa3,0x9b, 0xaf,0x97,0x8b,
0xa3,0x87,0x7b, 0x97,0x7b,0x6f, 0x87,0x6f,0x5f, 0x7b,0x63,0x53,
0x6b,0x57,0x47, 0x5f,0x4b,0x3b, 0x53,0x3f,0x33, 0x43,0x33,0x27,
0x37,0x2b,0x1f, 0x27,0x1f,0x17, 0x1b,0x13,0x0f, 0x0f,0x0b,0x07,
0x6f,0x83,0x7b, 0x67,0x7b,0x6f, 0x5f,0x73,0x67, 0x57,0x6b,0x5f,
0x4f,0x63,0x57, 0x47,0x5b,0x4f, 0x3f,0x53,0x47, 0x37,0x4b,0x3f,
0x2f,0x43,0x37, 0x2b,0x3b,0x2f, 0x23,0x33,0x27, 0x1f,0x2b,0x1f,
0x17,0x23,0x17, 0x0f,0x1b,0x13, 0x0b,0x13,0x0b, 0x07,0x0b,0x07,
0xff,0xf3,0x1b, 0xef,0xdf,0x17, 0xdb,0xcb,0x13, 0xcb,0xb7,0x0f,
0xbb,0xa7,0x0f, 0xab,0x97,0x0b, 0x9b,0x83,0x07, 0x8b,0x73,0x07,
0x7b,0x63,0x07, 0x6b,0x53,0x00, 0x5b,0x47,0x00, 0x4b,0x37,0x00,
0x3b,0x2b,0x00, 0x2b,0x1f,0x00, 0x1b,0x0f,0x00, 0x0b,0x07,0x00,
0x00,0x00,0xff, 0x0b,0x0b,0xef, 0x13,0x13,0xdf, 0x1b,0x1b,0xcf,
0x23,0x23,0xbf, 0x2b,0x2b,0xaf, 0x2f,0x2f,0x9f, 0x2f,0x2f,0x8f,
0x2f,0x2f,0x7f, 0x2f,0x2f,0x6f, 0x2f,0x2f,0x5f, 0x2b,0x2b,0x4f,
0x23,0x23,0x3f, 0x1b,0x1b,0x2f, 0x13,0x13,0x1f, 0x0b,0x0b,0x0f,
0x2b,0x00,0x00, 0x3b,0x00,0x00, 0x4b,0x07,0x00, 0x5f,0x07,0x00,
0x6f,0x0f,0x00, 0x7f,0x17,0x07, 0x93,0x1f,0x07, 0xa3,0x27,0x0b,
0xb7,0x33,0x0f, 0xc3,0x4b,0x1b, 0xcf,0x63,0x2b, 0xdb,0x7f,0x3b,
0xe3,0x97,0x4f, 0xe7,0xab,0x5f, 0xef,0xbf,0x77, 0xf7,0xd3,0x8b,
0xa7,0x7b,0x3b, 0xb7,0x9b,0x37, 0xc7,0xc3,0x37, 0xe7,0xe3,0x57,
0x7f,0xbf,0xff, 0xab,0xe7,0xff, 0xd7,0xff,0xff, 0x67,0x00,0x00,
0x8b,0x00,0x00, 0xb3,0x00,0x00, 0xd7,0x00,0x00, 0xff,0x00,0x00,
0xff,0xf3,0x93, 0xff,0xf7,0xc7, 0xff,0xff,0xff, 0x9f,0x5b,0x53
};
/*
=============
LoadMIP
=============
*/
Image* LoadMIPBuff( byte* buffer ){
byte *buf_p;
int palettelength;
int columns, rows, numPixels;
byte *pixbuf;
int i;
byte *loadedpalette;
const byte *palette;
loadedpalette = 0;
PointerInputStream inputStream( buffer );
inputStream.seek( MIP_NAME_LENGTH );
columns = istream_read_int32_le( inputStream );
rows = istream_read_int32_le( inputStream );
int offset = istream_read_int32_le( inputStream );
if ( std::size_t( columns ) > 65536 && std::size_t( rows ) > 65536 ) {
return 0;
}
// unsigned long mipdatasize = GET_MIP_DATA_SIZE( columns, rows );
palettelength = vfsLoadFile( "gfx/palette.lmp", (void **) &loadedpalette );
if ( palettelength == 768 ) {
palette = loadedpalette;
}
else
{
loadedpalette = 0;
palette = quakepalette;
}
buf_p = buffer + offset;
numPixels = columns * rows;
RGBAImage* image = new RGBAImage( columns, rows );
//Sys_Printf("lpMip->width = %i, lpMip->height = %i, lpMip->offsets[0] = %i, lpMip->offsets[1] = %i, lpMip->offsets[2] = %i, lpMip->offsets[3] = %i, numPixels = %i\n", lpMip->width, lpMip->height, lpMip->offsets[0], lpMip->offsets[1], lpMip->offsets[2], lpMip->offsets[3], numPixels);
//for (i = 0; i < sizeof(*lpMip); i++)
// Sys_Printf("%02x", (int) ((unsigned char *)lpMip)[i]);
pixbuf = image->getRGBAPixels();
for ( i = 0; i < numPixels; i++ )
{
int palIndex = *buf_p++;
*pixbuf++ = palette[palIndex * 3];
*pixbuf++ = palette[palIndex * 3 + 1];
*pixbuf++ = palette[palIndex * 3 + 2];
*pixbuf++ = 0xff;
}
if ( loadedpalette != 0 ) {
vfsFreeFile( loadedpalette );
}
return image;
}
Image* LoadMIP( ArchiveFile& file ){
ScopedArchiveBuffer buffer( file );
return LoadMIPBuff( buffer.buffer );
}

30
plugins/imagehl/mip.h Normal file
View file

@ -0,0 +1,30 @@
/*
Copyright (C) 1999-2006 Id Software, Inc. and contributors.
For a list of contributors, see the accompanying CONTRIBUTORS file.
This file is part of GtkRadiant.
GtkRadiant 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 2 of the License, or
(at your option) any later version.
GtkRadiant 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 GtkRadiant; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#if !defined ( INCLUDED_MIP_H )
#define INCLUDED_MIP_H
class Image;
class ArchiveFile;
Image* LoadMIP( ArchiveFile& file );
#endif

221
plugins/imagehl/sprite.cpp Normal file
View file

@ -0,0 +1,221 @@
/*
Copyright (C) 1999-2006 Id Software, Inc. and contributors.
For a list of contributors, see the accompanying CONTRIBUTORS file.
This file is part of GtkRadiant.
GtkRadiant 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 2 of the License, or
(at your option) any later version.
GtkRadiant 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 GtkRadiant; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
// by Hydra - hydra@hydras-world.com
#include "sprite.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
typedef unsigned char byte;
#include "ifilesystem.h"
#include "imagelib.h"
/*
============================================================================
IDSP IMAGE (.spr files)
Some code copied straight from the Q1 source, also used the HalfLife SDK as
a reference.
============================================================================
*/
typedef enum {ST_SYNC = 0, ST_RAND } synctype_t;
typedef enum { SPR_SINGLE = 0, SPR_GROUP } spriteframetype_t;
typedef struct dspriteheader_s {
int ident;
int version;
} dspriteheader_t;
// Quake1
typedef struct {
int type;
float boundingradius;
int width;
int height;
int numframes;
float beamlength;
synctype_t synctype;
} dspritev1_t;
// Halflife
typedef struct {
int type;
int texFormat;
float boundingradius;
int width;
int height;
int numframes;
float beamlength;
synctype_t synctype;
} dspritev2_t;
typedef struct {
int origin[2];
int width;
int height;
} dspriteframe_t;
typedef struct {
short type;
} dspriteframetype_t;
/*
typedef struct {
byte rgb[256][3];
} dpalette_t;
*/
const int IDSPRITEHEADER = ( ( 'P' << 24 ) + ( 'S' << 16 ) + ( 'D' << 8 ) + 'I' );
// little-endian "IDSP"
/*
=============
LoadIDSP
=============
*/
Image* LoadIDSPBuff( byte *buffer ){
byte *buf_p;
int columns, rows;
byte *pixbuf;
int row, column;
byte *palette;
unsigned char red, green, blue, alphabyte;
dspriteheader_t *header;
dspritev1_t *pinv1;
dspritev2_t *pinv2;
dspriteframetype_t *pframetype;
int version;
int numframes;
dspriteframe_t *spriteframe;
header = (dspriteheader_t *)buffer;
if ( header->ident != IDSPRITEHEADER ) {
globalErrorStream() << "WARNING: IDSP file has wrong header\n";
return 0;
}
version = header->version;
if ( version != 1 && version != 2 ) {
globalErrorStream() << "WARNING: IDSP file has wrong version number "
"(" << version << " should be 1 or 2)\n";
return 0;
}
// initialise variables depending on the sprite version.
switch ( version )
{
case 1:
pinv1 = (dspritev1_t *)( header + 1 );
numframes = pinv1->numframes;
columns = pinv1->width;
rows = pinv1->height;
pframetype = (dspriteframetype_t *)( pinv1 + 1 );
break;
case 2:
pinv2 = (dspritev2_t *)( header + 1 );
numframes = pinv2->numframes;
columns = pinv2->width;
rows = pinv2->height;
pframetype = (dspriteframetype_t *)( pinv2 + 1 );
break;
default:
globalErrorStream() << "WARNING: IDSP file has unsupported version\n";
return 0;
}
if ( numframes > 1 ) {
globalErrorStream() << "WARNING: IDSP file has multiple frames, only the first frame will be used.\n";
}
// palette = buffer+mipdatasize+2;
// buf_p = buffer+lpMip->offsets[0];
RGBAImage* image = new RGBAImage( columns, rows );
#ifdef DEBUG
frametype = spriteframetype_t( pframetype->type );
if ( frametype == SPR_SINGLE ) {
globalOutputStream() << "Single Frame\n";
}
else if ( frametype == SPR_GROUP ) {
globalOutputStream() << "Group of Frames\n";
}
else
{
globalOutputStream() << "Bleh!\n"; // <-- we always get this, wtf!
}
#endif
palette = (byte *)( pframetype + 1 );
spriteframe = (dspriteframe_t *)( palette + ( 256 * 3 ) + 4 ); // what are those 4 extra bytes ? what's missing ?
buf_p = (byte *)( spriteframe + 1 );
for ( row = 0; row < rows; row++ )
{
pixbuf = image->getRGBAPixels() + row * columns * 4;
for ( column = 0; column < columns; column++ )
{
int palIndex;
palIndex = *buf_p++;
red = *( palette + ( palIndex * 3 ) );
green = *( palette + ( palIndex * 3 ) + 1 );
blue = *( palette + ( palIndex * 3 ) + 2 );
// HalfLife engine makes pixels that are BLUE transparent. (RGB = 0x0000FF)
// So show them that way in the editor.
if ( blue == 0xff && red == 0x00 && green == 0x00 ) {
alphabyte = 0xff; //FIXME: backwards? (so sprite models to render correctly)
blue = 0x00; // don't set the resulting pixel to blue
}
else
{
alphabyte = 0x00; //FIXME: backwards? (so sprite models to render correctly)
}
*pixbuf++ = red;
*pixbuf++ = green;
*pixbuf++ = blue;
*pixbuf++ = alphabyte;
}
}
return image;
}
Image* LoadIDSP( ArchiveFile& file ){
ScopedArchiveBuffer buffer( file );
return LoadIDSPBuff( buffer.buffer );
}

30
plugins/imagehl/sprite.h Normal file
View file

@ -0,0 +1,30 @@
/*
Copyright (C) 1999-2006 Id Software, Inc. and contributors.
For a list of contributors, see the accompanying CONTRIBUTORS file.
This file is part of GtkRadiant.
GtkRadiant 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 2 of the License, or
(at your option) any later version.
GtkRadiant 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 GtkRadiant; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#if !defined ( INCLUDED_SPRITE_H )
#define INCLUDED_SPRITE_H
class Image;
class ArchiveFile;
Image* LoadIDSP( ArchiveFile& file );
#endif

26
plugins/matsys/Makefile Normal file
View file

@ -0,0 +1,26 @@
# WorldSpawn Makefile
GLIB_CFLAGS=$(shell pkg-config --cflags gtk+-2.0) -DGTK_TARGET=2
GLIB_LDFLAGS=$(shell pkg-config --libs gtk+-2.0)
PLUGIN_CFLAGS=$(CFLAGS) $(GLIB_CFLAGS) -I../../include -I../../libs -fPIC -fvisibility=hidden
PLUGIN_LDFLAGS=$(LDFLAGS) $(GLIB_LDFLAGS) -shared
DO_CXX=$(CXX) $(PLUGIN_CFLAGS) -o $@ -c $<
.cpp.o:
$(DO_CXX)
WS_OBJS = \
shaders.o plugin.o
# binary target
../../build/plugins/libmatsys.so: $(WS_OBJS)
$(CXX) -o $@ $(WS_OBJS) $(PLUGIN_LDFLAGS)
# object files
shaders.o: shaders.cpp shaders.h
plugin.o: plugin.cpp
clean:
-rm -f *.o ../../build/plugins/libmatsys.so

92
plugins/matsys/plugin.cpp Normal file
View file

@ -0,0 +1,92 @@
/*
Copyright (C) 2001-2006, William Joseph.
All Rights Reserved.
This file is part of GtkRadiant.
GtkRadiant 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 2 of the License, or
(at your option) any later version.
GtkRadiant 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 GtkRadiant; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "ishaders.h"
#include "ifilesystem.h"
#include "itextures.h"
#include "iscriplib.h"
#include "qerplugin.h"
#include "string/string.h"
#include "modulesystem/singletonmodule.h"
#include "shaders.h"
class ShadersDependencies :
public GlobalFileSystemModuleRef,
public GlobalTexturesModuleRef,
public GlobalScripLibModuleRef,
public GlobalRadiantModuleRef {
ImageModuleRef m_bitmapModule;
public:
ShadersDependencies() :
m_bitmapModule("tga")
{
}
ImageModuleRef &getBitmapModule()
{
return m_bitmapModule;
}
};
class MaterialAPI {
ShaderSystem *m_shadersq3;
public:
typedef ShaderSystem Type;
STRING_CONSTANT(Name, "mat");
MaterialAPI(ShadersDependencies &dependencies)
{
g_shadersExtension = "mat";
g_shadersDirectory = "textures/";
g_enableDefaultShaders = false;
g_useShaderList = false;
g_bitmapModule = dependencies.getBitmapModule().getTable();
Shaders_Construct();
m_shadersq3 = &GetShaderSystem();
}
~MaterialAPI()
{
Shaders_Destroy();
}
ShaderSystem *getTable()
{
return m_shadersq3;
}
};
typedef SingletonModule<MaterialAPI, ShadersDependencies, DependenciesAPIConstructor<MaterialAPI, ShadersDependencies> > MaterialModule;
MaterialModule g_MaterialModule;
extern "C" void
#ifdef _WIN32
__declspec(dllexport)
#else
__attribute__((visibility("default")))
#endif
Radiant_RegisterModules(ModuleServer &server)
{
initialiseModule(server);
g_MaterialModule.selfRegister();
}

1578
plugins/matsys/shaders.cpp Normal file

File diff suppressed because it is too large Load diff

43
plugins/matsys/shaders.h Normal file
View file

@ -0,0 +1,43 @@
/*
Copyright (c) 2001, Loki software, inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
Neither the name of Loki software nor the names of its contributors may be used
to endorse or promote products derived from this software without specific prior
written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT,INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#if !defined( INCLUDED_SHADERS_H )
#define INCLUDED_SHADERS_H
void Shaders_Construct();
void Shaders_Destroy();
class ShaderSystem;
ShaderSystem &GetShaderSystem();
extern const char *g_shadersExtension;
extern const char *g_shadersDirectory;
extern bool g_enableDefaultShaders;
extern bool g_useShaderList;
struct _QERPlugImageTable;
extern _QERPlugImageTable *g_bitmapModule;
#endif

View file

@ -27,66 +27,117 @@
#include "string/string.h" #include "string/string.h"
#include "modulesystem/singletonmodule.h" #include "modulesystem/singletonmodule.h"
#include "shaders.h" #include "shaders.h"
class ShadersDependencies : class ShadersDependencies :
public GlobalFileSystemModuleRef, public GlobalFileSystemModuleRef,
public GlobalTexturesModuleRef, public GlobalTexturesModuleRef,
public GlobalScripLibModuleRef, public GlobalScripLibModuleRef,
public GlobalRadiantModuleRef { public GlobalRadiantModuleRef
{
ImageModuleRef m_bitmapModule; ImageModuleRef m_bitmapModule;
public: public:
ShadersDependencies() : ShadersDependencies() :
m_bitmapModule("tga") m_bitmapModule( "tga" ){
{
} }
ImageModuleRef& getBitmapModule(){
ImageModuleRef &getBitmapModule()
{
return m_bitmapModule; return m_bitmapModule;
} }
}; };
class MaterialAPI { class ShadersQ3API
ShaderSystem *m_shadersq3; {
ShaderSystem* m_shadersq3;
public: public:
typedef ShaderSystem Type; typedef ShaderSystem Type;
STRING_CONSTANT( Name, "quake3" );
STRING_CONSTANT(Name, "mat"); ShadersQ3API( ShadersDependencies& dependencies ){
g_shadersExtension = "shader";
MaterialAPI(ShadersDependencies &dependencies) g_shadersDirectory = "scripts/";
{
g_shadersExtension = "mat";
g_shadersDirectory = "textures/";
g_enableDefaultShaders = false;
g_useShaderList = false;
g_bitmapModule = dependencies.getBitmapModule().getTable(); g_bitmapModule = dependencies.getBitmapModule().getTable();
Shaders_Construct(); Shaders_Construct();
m_shadersq3 = &GetShaderSystem(); m_shadersq3 = &GetShaderSystem();
} }
~ShadersQ3API(){
~MaterialAPI()
{
Shaders_Destroy(); Shaders_Destroy();
} }
ShaderSystem* getTable(){
ShaderSystem *getTable()
{
return m_shadersq3; return m_shadersq3;
} }
}; };
typedef SingletonModule<MaterialAPI, ShadersDependencies, DependenciesAPIConstructor<MaterialAPI, ShadersDependencies> > MaterialModule; typedef SingletonModule<ShadersQ3API, ShadersDependencies, DependenciesAPIConstructor<ShadersQ3API, ShadersDependencies> > ShadersQ3Module;
MaterialModule g_MaterialModule;
extern "C" void ShadersQ3Module g_ShadersQ3Module;
#ifdef _WIN32
__declspec(dllexport)
#else class ShadersDoom3API
__attribute__((visibility("default")))
#endif
Radiant_RegisterModules(ModuleServer &server)
{ {
initialiseModule(server); ShaderSystem* m_shadersdoom3;
g_MaterialModule.selfRegister(); public:
typedef ShaderSystem Type;
STRING_CONSTANT( Name, "doom3" );
ShadersDoom3API( ShadersDependencies& dependencies ){
g_shadersExtension = "mtr";
g_shadersDirectory = "materials/";
g_enableDefaultShaders = false;
g_shaderLanguage = SHADERLANGUAGE_DOOM3;
g_useShaderList = false;
g_bitmapModule = dependencies.getBitmapModule().getTable();
Shaders_Construct();
m_shadersdoom3 = &GetShaderSystem();
}
~ShadersDoom3API(){
Shaders_Destroy();
}
ShaderSystem* getTable(){
return m_shadersdoom3;
}
};
typedef SingletonModule<ShadersDoom3API, ShadersDependencies, DependenciesAPIConstructor<ShadersDoom3API, ShadersDependencies> > ShadersDoom3Module;
ShadersDoom3Module g_ShadersDoom3Module;
class ShadersQuake4API
{
ShaderSystem* m_shadersquake4;
public:
typedef ShaderSystem Type;
STRING_CONSTANT( Name, "quake4" );
ShadersQuake4API( ShadersDependencies& dependencies ){
g_shadersExtension = "mtr";
g_shadersDirectory = "materials/";
g_enableDefaultShaders = false;
g_shaderLanguage = SHADERLANGUAGE_QUAKE4;
g_useShaderList = false;
g_bitmapModule = dependencies.getBitmapModule().getTable();
Shaders_Construct();
m_shadersquake4 = &GetShaderSystem();
}
~ShadersQuake4API(){
Shaders_Destroy();
}
ShaderSystem* getTable(){
return m_shadersquake4;
}
};
typedef SingletonModule<ShadersQuake4API, ShadersDependencies, DependenciesAPIConstructor<ShadersQuake4API, ShadersDependencies> > ShadersQuake4Module;
ShadersQuake4Module g_ShadersQuake4Module;
extern "C" void RADIANT_DLLEXPORT Radiant_RegisterModules( ModuleServer& server ){
initialiseModule( server );
g_ShadersQ3Module.selfRegister();
g_ShadersDoom3Module.selfRegister();
g_ShadersQuake4Module.selfRegister();
} }

File diff suppressed because it is too large Load diff

View file

@ -30,14 +30,26 @@
#if !defined( INCLUDED_SHADERS_H ) #if !defined( INCLUDED_SHADERS_H )
#define INCLUDED_SHADERS_H #define INCLUDED_SHADERS_H
void Shaders_Construct(); void Shaders_Construct();
void Shaders_Destroy(); void Shaders_Destroy();
class ShaderSystem; class ShaderSystem;
ShaderSystem &GetShaderSystem(); ShaderSystem& GetShaderSystem();
extern const char *g_shadersExtension;
extern const char *g_shadersDirectory; enum ShaderLanguage
{
SHADERLANGUAGE_QUAKE3,
SHADERLANGUAGE_DOOM3,
SHADERLANGUAGE_QUAKE4
};
extern const char* g_shadersExtension;
extern const char* g_shadersDirectory;
extern ShaderLanguage g_shaderLanguage;
extern bool g_enableDefaultShaders; extern bool g_enableDefaultShaders;
extern bool g_useShaderList; extern bool g_useShaderList;
struct _QERPlugImageTable; struct _QERPlugImageTable;
extern _QERPlugImageTable *g_bitmapModule; extern _QERPlugImageTable* g_bitmapModule;
#endif #endif

View file

@ -148,7 +148,26 @@ static Archive *InitPakFile(ArchiveModules &archiveModules, const char *filename
entry.archive = table->m_pfnOpenArchive(filename); entry.archive = table->m_pfnOpenArchive(filename);
entry.is_pakfile = true; entry.is_pakfile = true;
g_archives.push_back(entry); g_archives.push_back(entry);
globalOutputStream() << " pak file: " << filename << "\n"; globalOutputStream() << " " << path_get_extension(filename) << " file: " << filename << "\n";
return entry.archive;
}
return 0;
}
static Archive *InitWadFile(ArchiveModules &archiveModules, const char *filename)
{
const _QERArchiveTable *table = GetArchiveTable(archiveModules, path_get_extension(filename));
if (table != 0) {
archive_entry_t entry;
entry.name = filename;
entry.archive = table->m_pfnOpenArchive(filename);
entry.is_pakfile = false;
g_archives.push_back(entry);
globalOutputStream() << " wad file: " << filename << "\n";
return entry.archive; return entry.archive;
} }
@ -457,194 +476,155 @@ static void LoadDpkPakWithDeps(const char *pakname)
// Global functions // Global functions
// reads all pak files from a dir // reads all pak files from a dir
void InitDirectory(const char *directory, ArchiveModules &archiveModules) void InitDirectory( const char* directory, ArchiveModules& archiveModules ){
{
int j; int j;
g_numForbiddenDirs = 0; g_numForbiddenDirs = 0;
StringTokeniser st(GlobalRadiant().getGameDescriptionKeyValue("forbidden_paths"), " "); StringTokeniser st( GlobalRadiant().getGameDescriptionKeyValue( "forbidden_paths" ), " " );
for (j = 0; j < VFS_MAXDIRS; ++j) { for ( j = 0; j < VFS_MAXDIRS; ++j )
{
const char *t = st.getToken(); const char *t = st.getToken();
if (string_empty(t)) { if ( string_empty( t ) ) {
break; break;
} }
strncpy(g_strForbiddenDirs[g_numForbiddenDirs], t, PATH_MAX); strncpy( g_strForbiddenDirs[g_numForbiddenDirs], t, PATH_MAX );
g_strForbiddenDirs[g_numForbiddenDirs][PATH_MAX] = '\0'; g_strForbiddenDirs[g_numForbiddenDirs][PATH_MAX] = '\0';
++g_numForbiddenDirs; ++g_numForbiddenDirs;
} }
for (j = 0; j < g_numForbiddenDirs; ++j) { for ( j = 0; j < g_numForbiddenDirs; ++j )
char *dbuf = g_strdup(directory); {
if (*dbuf && dbuf[strlen(dbuf) - 1] == '/') { char* dbuf = g_strdup( directory );
dbuf[strlen(dbuf) - 1] = 0; if ( *dbuf && dbuf[strlen( dbuf ) - 1] == '/' ) {
dbuf[strlen( dbuf ) - 1] = 0;
} }
const char *p = strrchr(dbuf, '/'); const char *p = strrchr( dbuf, '/' );
p = (p ? (p + 1) : dbuf); p = ( p ? ( p + 1 ) : dbuf );
if (matchpattern(p, g_strForbiddenDirs[j], TRUE)) { if ( matchpattern( p, g_strForbiddenDirs[j], TRUE ) ) {
g_free(dbuf); g_free( dbuf );
break; break;
} }
g_free(dbuf); g_free( dbuf );
} }
if (j < g_numForbiddenDirs) { if ( j < g_numForbiddenDirs ) {
printf("Directory %s matched by forbidden dirs, removed\n", directory); printf( "Directory %s matched by forbidden dirs, removed\n", directory );
return; return;
} }
if (g_numDirs == VFS_MAXDIRS) { if ( g_numDirs == VFS_MAXDIRS ) {
return; return;
} }
strncpy(g_strDirs[g_numDirs], directory, PATH_MAX); strncpy( g_strDirs[g_numDirs], directory, PATH_MAX );
g_strDirs[g_numDirs][PATH_MAX] = '\0'; g_strDirs[g_numDirs][PATH_MAX] = '\0';
FixDOSName(g_strDirs[g_numDirs]); FixDOSName( g_strDirs[g_numDirs] );
AddSlash(g_strDirs[g_numDirs]); AddSlash( g_strDirs[g_numDirs] );
const char *path = g_strDirs[g_numDirs]; const char* path = g_strDirs[g_numDirs];
g_numDirs++; g_numDirs++;
{ {
archive_entry_t entry; g_archives.push_back( archive_entry_t{ path, OpenArchive( path ), false } );
entry.name = path;
entry.archive = OpenArchive(path);
entry.is_pakfile = false;
g_archives.push_back(entry);
} }
if (g_bUsePak) { if ( g_bUsePak ) {
GDir* dir = g_dir_open( path, 0, 0 );
GDir *dir = g_dir_open(path, 0, 0); if ( dir != 0 ) {
if (dir != 0) {
globalOutputStream() << "vfs directory: " << path << "\n"; globalOutputStream() << "vfs directory: " << path << "\n";
Archives archives; const char* ignore_prefix = "";
Archives archivesOverride; const char* override_prefix = "";
const char *ignore_prefix = "";
const char *override_prefix = "";
bool is_pk3_vfs, is_pk4_vfs, is_dpk_vfs;
is_pk3_vfs = GetArchiveTable(archiveModules, "pk3"); {
is_pk4_vfs = GetArchiveTable(archiveModules, "pk4");
is_dpk_vfs = GetArchiveTable(archiveModules, "dpk");
if (!is_dpk_vfs) {
// See if we are in "sp" or "mp" mapping mode // See if we are in "sp" or "mp" mapping mode
const char *gamemode = gamemode_get(); const char* gamemode = gamemode_get();
if (strcmp(gamemode, "sp") == 0) { if ( strcmp( gamemode, "sp" ) == 0 ) {
ignore_prefix = "mp_"; ignore_prefix = "mp_";
override_prefix = "sp_"; override_prefix = "sp_";
} else if (strcmp(gamemode, "mp") == 0) { }
else if ( strcmp( gamemode, "mp" ) == 0 ) {
ignore_prefix = "sp_"; ignore_prefix = "sp_";
override_prefix = "mp_"; override_prefix = "mp_";
} }
} }
for (;;) { Archives archives;
const char *name = g_dir_read_name(dir); Archives archivesOverride;
if (name == 0) { for (;; )
{
const char* name = g_dir_read_name( dir );
if ( name == 0 ) {
break; break;
} }
for (j = 0; j < g_numForbiddenDirs; ++j) { for ( j = 0; j < g_numForbiddenDirs; ++j )
const char *p = strrchr(name, '/'); {
p = (p ? (p + 1) : name); const char *p = strrchr( name, '/' );
if (matchpattern(p, g_strForbiddenDirs[j], TRUE)) { p = ( p ? ( p + 1 ) : name );
if ( matchpattern( p, g_strForbiddenDirs[j], TRUE ) ) {
break; break;
} }
} }
if (j < g_numForbiddenDirs) { if ( j < g_numForbiddenDirs ) {
continue; continue;
} }
const char *ext = strrchr(name, '.'); const char *ext = strrchr( name, '.' );
char tmppath[PATH_MAX];
if (is_dpk_vfs) { if ( ext && !string_compare_nocase_upper( ext, ".pk3dir" ) ) {
if (!!ext && !string_compare_nocase_upper(ext, ".dpkdir")) { if ( g_numDirs == VFS_MAXDIRS ) {
snprintf(tmppath, PATH_MAX, "%s%s/", path, name); continue;
tmppath[PATH_MAX] = '\0'; }
FixDOSName(tmppath); snprintf( g_strDirs[g_numDirs], PATH_MAX, "%s%s/", path, name );
AddSlash(tmppath); g_strDirs[g_numDirs][PATH_MAX] = '\0';
AddDpkPak(CopiedString(StringRange(name, ext)).c_str(), tmppath, false); FixDOSName( g_strDirs[g_numDirs] );
AddSlash( g_strDirs[g_numDirs] );
g_numDirs++;
{
g_archives.push_back( archive_entry_t{ g_strDirs[g_numDirs - 1], OpenArchive( g_strDirs[g_numDirs - 1] ), false } );
} }
} }
if (is_pk3_vfs || is_pk4_vfs) { if ( ( ext == 0 ) || *( ++ext ) == '\0' || GetArchiveTable( archiveModules, ext ) == 0 ) {
if (!!ext && (!string_compare_nocase_upper(ext, ".pk3dir")
|| !string_compare_nocase_upper(ext, ".pk4dir"))) {
snprintf(tmppath, PATH_MAX, "%s%s/", path, name);
tmppath[PATH_MAX] = '\0';
FixDOSName(tmppath);
AddSlash(tmppath);
AddPk3Dir(tmppath);
}
}
// GetArchiveTable() needs "pk3" if ext is ".pk3"
if ((ext == 0) || *(ext + 1) == '\0' || GetArchiveTable(archiveModules, ext + 1) == 0) {
continue; continue;
} }
// using the same kludge as in engine to ensure consistency // using the same kludge as in engine to ensure consistency
if (!string_empty(ignore_prefix) && strncmp(name, ignore_prefix, strlen(ignore_prefix)) == 0) { if ( !string_empty( ignore_prefix ) && strncmp( name, ignore_prefix, strlen( ignore_prefix ) ) == 0 ) {
continue; continue;
} }
if (!string_empty(override_prefix) && strncmp(name, override_prefix, strlen(override_prefix)) == 0) { if ( !string_empty( override_prefix ) && strncmp( name, override_prefix, strlen( override_prefix ) ) == 0 ) {
if (!string_compare_nocase_upper(ext, ".dpk")) { archivesOverride.insert( name );
if (is_dpk_vfs) {
archives.insert(name);
}
} else {
archivesOverride.insert(name);
}
continue; continue;
} }
archives.insert(name); archives.insert( name );
} }
g_dir_close(dir); g_dir_close( dir );
// add the entries to the vfs // add the entries to the vfs
char *fullpath; for ( Archives::iterator i = archivesOverride.begin(); i != archivesOverride.end(); ++i )
if (is_dpk_vfs) { {
for (Archives::iterator i = archives.begin(); i != archives.end(); ++i) { char filename[PATH_MAX];
const char *name = i->c_str(); strcpy( filename, path );
const char *ext = strrchr(name, '.'); strcat( filename, ( *i ).c_str() );
if (!string_compare_nocase_upper(ext, ".dpk")) { InitPakFile( archiveModules, filename );
CopiedString name_final = CopiedString(StringRange(name, ext)); }
fullpath = string_new_concat(path, name); for ( Archives::iterator i = archives.begin(); i != archives.end(); ++i )
AddDpkPak(name_final.c_str(), fullpath, true); {
string_release(fullpath, string_length(fullpath)); char filename[PATH_MAX];
strcpy( filename, path );
strcat( filename, ( *i ).c_str() );
InitPakFile( archiveModules, filename );
} }
} }
} else
if (is_pk3_vfs || is_pk4_vfs) { {
for (Archives::iterator i = archivesOverride.begin(); i != archivesOverride.end(); ++i) {
const char *name = i->c_str();
const char *ext = strrchr(name, '.');
if (!string_compare_nocase_upper(ext, ".pk3")
|| !string_compare_nocase_upper(ext, ".pk4")) {
fullpath = string_new_concat(path, i->c_str());
InitPakFile(archiveModules, fullpath);
string_release(fullpath, string_length(fullpath));
}
}
for (Archives::iterator i = archives.begin(); i != archives.end(); ++i) {
const char *name = i->c_str();
const char *ext = strrchr(name, '.');
if (!string_compare_nocase_upper(ext, ".pk3")
|| !string_compare_nocase_upper(ext, ".pk4")) {
fullpath = string_new_concat(path, i->c_str());
InitPakFile(archiveModules, fullpath);
string_release(fullpath, string_length(fullpath));
}
}
}
} else {
globalErrorStream() << "vfs directory not found: " << path << "\n"; globalErrorStream() << "vfs directory not found: " << path << "\n";
} }
} }
@ -812,7 +792,7 @@ void initialise()
void load() void load()
{ {
ArchiveModules &archiveModules = FileSystemQ3API_getArchiveModules(); ArchiveModules &archiveModules = FileSystemQ3API_getArchiveModules();
bool is_dpk_vfs = GetArchiveTable(archiveModules, "dpk"); bool is_dpk_vfs = 1;
if (is_dpk_vfs) { if (is_dpk_vfs) {
const char *pakname; const char *pakname;
@ -947,7 +927,6 @@ Archive *getArchive(const char *archiveName, bool pakonly)
if (pakonly && !(*i).is_pakfile) { if (pakonly && !(*i).is_pakfile) {
continue; continue;
} }
if (path_equal((*i).name.c_str(), archiveName)) { if (path_equal((*i).name.c_str(), archiveName)) {
return (*i).archive; return (*i).archive;
} }

View file

@ -3,9 +3,12 @@ all:
mkdir -p ../build/games mkdir -p ../build/games
mkdir -p ../build/gl mkdir -p ../build/gl
mkdir -p ../build/platform.game mkdir -p ../build/platform.game
mkdir -p ../build/goldsrc.game
cp -vf ./defaultkeys.ini ../build/defaultkeys.ini cp -vf ./defaultkeys.ini ../build/defaultkeys.ini
cp -vf ./platform.game/default_build_menu.xml ../build/platform.game/default_build_menu.xml cp -vf ./platform.game/default_build_menu.xml ../build/platform.game/default_build_menu.xml
cp -vf ./goldsrc.game/default_build_menu.xml ../build/goldsrc.game/default_build_menu.xml
cp -vf ./games/platform.game ../build/games/platform.game cp -vf ./games/platform.game ../build/games/platform.game
cp -vf ./games/goldsrc.game ../build/games/goldsrc.game
cp -vf ./gl/lighting_DBS_omni_fp.glp ../build/gl/lighting_DBS_omni_fp.glp cp -vf ./gl/lighting_DBS_omni_fp.glp ../build/gl/lighting_DBS_omni_fp.glp
cp -vf ./gl/lighting_DBS_omni_fp.glsl ../build/gl/lighting_DBS_omni_fp.glsl cp -vf ./gl/lighting_DBS_omni_fp.glsl ../build/gl/lighting_DBS_omni_fp.glsl
cp -vf ./gl/lighting_DBS_omni_vp.glp ../build/gl/lighting_DBS_omni_vp.glp cp -vf ./gl/lighting_DBS_omni_vp.glp ../build/gl/lighting_DBS_omni_vp.glp

View file

@ -0,0 +1,28 @@
<?xml version="1.0"?>
<game
type="q1"
name="GoldSrc"
enginepath_win32="C:/Sierra/Half-Life/"
enginepath_linux="/usr/local/games/halflife/"
enginepath_macos="/Applications/Half-Life/"
engine_win32="hl.exe"
engine_linux="hl_linux"
engine_macos="Half-Life.app"
basegame="valve"
basegamename="GoldSrc"
unknowngamename="Custom mod"
default_scale="1.0"
no_patch="1"
no_bsp_monitor="1"
show_wads="1"
archivetypes="pak wad"
texturetypes="tga jpg mip hlw"
modeltypes="vvm"
maptypes="worldspawn"
shaders="quake3"
entityclass="quake3"
entityclasstype="def"
entities="quake3"
brushtypes="halflife"
patchtypes="quake3"
/>

View file

@ -0,0 +1,26 @@
<?xml version="1.0"?>
<project version="2.0">
<var name="vmap">"[RadiantPath]vmap" -v<cond value="[MonitorAddress]"> -connect [MonitorAddress]</cond> -game platform -fs_basepath "[EnginePath]"<cond value="[GameName]"> -fs_game [GameName]</cond></var>
<build name="Fast Fullbright">
<command>[vmap] -custinfoparms -threads 4 -samplesize 8 "[MapFile]"</command>
<command>[vmap] -vis -v -fast "[MapFile]"</command>
</build>
<build name="Fast">
<command>[vmap] -custinfoparms -threads 4 -samplesize 8 "[MapFile]"</command>
<command>[vmap] -vis -v -fast "[MapFile]"</command>
<command>[vmap] -light -custinfoparms -v -samplesize 8 -fast -threads 4 -samples 4 -shade -shadeangle 60 -patchshadows "[MapFile]"</command>
</build>
<build name="Full">
<command>[vmap] -custinfoparms -threads 4 -samplesize 8 "[MapFile]"</command>
<command>[vmap] -vis "[MapFile]"</command>
<command>[vmap] -light -custinfoparms -samplesize 8 -fast -threads 4 -samples 4 -shade -shadeangle 60 -patchshadows "[MapFile]"</command>
</build>
</build>
</project>

View file

@ -156,6 +156,8 @@ void VFS_Refresh()
RefreshReferences(); RefreshReferences();
// also refresh texture browser // also refresh texture browser
TextureBrowser_RefreshShaders(); TextureBrowser_RefreshShaders();
// also show textures (all or common)
TextureBrowser_ShowStartupShaders( GlobalTextureBrowser() );
} }
void VFS_Restart() void VFS_Restart()