From fbba2e463dcfce129628175fa25d02a57a038f53 Mon Sep 17 00:00:00 2001 From: janwas Date: Sun, 16 May 2004 03:31:29 +0000 Subject: [PATCH] merged in rich's demo This was SVN commit r236. --- source/lib/res/file.cpp | 96 +++-- source/lib/res/vfs.cpp | 14 +- source/lib/sysdep/win/win.cpp | 6 +- source/lib/sysdep/win/wsdl.cpp | 10 + source/lib/sysdep/win/wsdl.h | 7 +- source/main.cpp | 59 +-- source/terrain/TextureManager.cpp | 402 +++++++++--------- source/terrain/terrainMain.cpp | 652 +++++++++++++++--------------- 8 files changed, 648 insertions(+), 598 deletions(-) diff --git a/source/lib/res/file.cpp b/source/lib/res/file.cpp index 9f46ec48af..c62107e15f 100755 --- a/source/lib/res/file.cpp +++ b/source/lib/res/file.cpp @@ -96,13 +96,14 @@ static int mk_native_path(const char* const path, char* const n_path) } -// rationale for data dir being root: -// xxxxxxxx yyyyyyyyy zzzzzzzzzz sandbox; vfs users (untrusted scripts) can't overwrite critical game files +// rationale for data dir being root: untrusted scripts must not be allowed +// to overwrite critical game (or worse, OS) files. the VFS prevents any +// accesses to files above this directory. int file_set_root_dir(const char* argv0, const char* root_dir) { // security check: only allow attempting to set root dir once - // (prevents malicious scripts from overwriting important files - // above the intended VFS root) + // (this is called early at startup, so any subsequent + // call is most likely malicious). static bool already_attempted; if(already_attempted) { @@ -131,10 +132,10 @@ int file_set_root_dir(const char* argv0, const char* root_dir) if(chdir(path) < 0) return -errno; - char* native_root = path; // reuse path[] (no longer needed) - CHECK_ERR(mk_native_path(root_dir, native_root)); + char* n_root = path; // reuse path[] (no longer needed) + CHECK_ERR(mk_native_path(root_dir, n_root)); - if(chdir(native_root) < 0) + if(chdir(n_root) < 0) return -errno; return 0; @@ -148,25 +149,26 @@ int file_set_root_dir(const char* argv0, const char* root_dir) // need to store entries returned by readdir so they can be sorted. struct DirEnt { - std::string name; - uint flags; - ssize_t size; + const std::string name; + const uint flags; + const ssize_t size; - DirEnt(const char* _name, uint _flags, ssize_t _size) + DirEnt(const char* const _name, const uint _flags, const ssize_t _size) : name(_name), flags(_flags), size(_size) {} }; -typedef std::vector DirEnts; -typedef DirEnts::iterator DirEntsIt; +typedef std::vector DirEnts; +typedef DirEnts::const_iterator DirEntIt; -static bool dirent_less(DirEnt& d1, DirEnt& d2) - { return d1.name.compare(d2.name) < 0; } +static bool dirent_less(const DirEnt* const d1, const DirEnt* const d2) + { return d1->name.compare(d2->name) < 0; } -// rationale: we pass the directory entry name only to the callback - -// not the absolute path, nor prepended. some users don't need it, -// and would need to strip it. this routine generates the absolute path, -// but in native form - can't use that. -int file_enum(const char* dir, FileCB cb, uintptr_t user) +// we give the callback the directory-entry-name only - not the +// absolute path, nor prepended. rationale: some users don't need it, +// and would need to strip it. there are not enough users requiring it to +// justify that. this routine does actually generate the absolute path +// for use with stat, but in native form - can't use that. +int file_enum(const char* const dir, const FileCB cb, const uintptr_t user) { char n_path[PATH_MAX+1]; n_path[PATH_MAX] = '\0'; @@ -174,14 +176,15 @@ int file_enum(const char* dir, FileCB cb, uintptr_t user) // 0-terminate simplifies filename strncpy below. CHECK_ERR(mk_native_path(dir, n_path)); - // all entries are enumerated (adding to list), sorted, then passed to cb + // all entries are enumerated (adding to this container), + // std::sort-ed, then all passed to cb. DirEnts dirents; int stat_err = 0; int cb_err = 0; int ret; - DIR* os_dir = opendir(n_path); + DIR* const os_dir = opendir(n_path); if(!os_dir) return -1; @@ -190,15 +193,19 @@ int file_enum(const char* dir, FileCB cb, uintptr_t user) char* fn_start = n_path + n_path_len; *fn_start++ = DIR_SEP; - struct dirent* ent; - while((ent = readdir(os_dir))) + struct dirent* os_ent; + while((os_ent = readdir(os_dir))) { - const char* fn = ent->d_name; + const char* fn = os_ent->d_name; strncpy(fn_start, fn, PATH_MAX-n_path_len); - // stat needs the relative path. this is easier than changing + // stat needs the full path. this is easier than changing // directory every time, and should be fast enough. + // BTW, direct strcpy is faster than path_append - + // we save a strlen every iteration. + // no need to go through file_stat - + // we already have the native path. struct stat s; ret = stat(n_path, &s); if(ret < 0) @@ -225,23 +232,29 @@ int file_enum(const char* dir, FileCB cb, uintptr_t user) else if(!(s.st_mode & S_IFREG)) continue; - dirents.push_back(DirEnt(fn, flags, size)); + const DirEnt* const ent = new DirEnt(fn, flags, size); + dirents.push_back(ent); } closedir(os_dir); std::sort(dirents.begin(), dirents.end(), dirent_less); - for(DirEntsIt it = dirents.begin(); it != dirents.end(); ++it) + DirEntIt it; + for(it = dirents.begin(); it != dirents.end(); ++it) { - const char* name_c = it->name.c_str(); - const uint flags = it->flags; - const ssize_t size = it->size; + const DirEnt* const ent = *it; + const char* name_c = ent->name.c_str(); + const uint flags = ent->flags; + const ssize_t size = ent->size; ret = cb(name_c, flags, size, user); if(ret < 0) if(cb_err == 0) cb_err = ret; } + for(it = dirents.begin(); it != dirents.end(); ++it) + delete *it; + if(cb_err < 0) return cb_err; return stat_err; @@ -832,7 +845,7 @@ Handle file_start_io(File* f, size_t user_ofs, size_t user_size, void* user_p) return -1; } - size_t bytes_left = f->size - user_ofs; // > 0 + const size_t bytes_left = f->size - user_ofs; // > 0 int op = (f->flags & FILE_WRITE)? LIO_WRITE : LIO_READ; // don't read beyond EOF @@ -841,6 +854,7 @@ Handle file_start_io(File* f, size_t user_ofs, size_t user_size, void* user_p) u64 block_id = block_make_id(f->fn_hash, user_ofs); + // reset to 0 if transferring more than 1 block. // allocate IO slot Handle hio = io_alloc(); @@ -852,8 +866,9 @@ Handle file_start_io(File* f, size_t user_ofs, size_t user_size, void* user_p) // notes: io->cached, io->pending and io->block are already zeroed; // cb will receive the actual IO request (aligned offset and size). - +#ifdef PARANOIA debug_out("file_start_io hio=%I64x ofs=%d size=%d\n", hio, user_ofs, user_size); +#endif // aio already safely handles unaligned buffers or offsets. // when reading zip files, we don't want to repeat a read @@ -875,7 +890,9 @@ debug_out("file_start_io hio=%I64x ofs=%d size=%d\n", hio, user_ofs, user_size); // if already cached, we're done if(size == BLOCK_SIZE && block_retrieve(block_id, io->block) == 0) { - debug_out("file_start_io: cached! block # = %d\n", block_id & 0xffffffff); +#ifdef PARANOIA +debug_out("file_start_io: cached! block # = %d\n", block_id & 0xffffffff); +#endif io->cached = 1; return hio; } @@ -922,7 +939,9 @@ fail: int file_wait_io(const Handle hio, void*& p, size_t& size) { +#ifdef PARANOIA debug_out("file_wait_io: hio=%I64x\n", hio); +#endif int ret = 0; @@ -1003,7 +1022,9 @@ int file_discard_io(Handle& hio) ssize_t file_io(File* const f, const size_t raw_ofs, size_t raw_size, void** const p, const FILE_IO_CB cb, const uintptr_t ctx) // optional { +#ifdef PARANOIA debug_out("file_io fd=%d size=%d ofs=%d\n", f->fd, raw_size, raw_ofs); +#endif CHECK_FILE(f) @@ -1100,8 +1121,6 @@ debug_out("file_io fd=%d size=%d ofs=%d\n", f->fd, raw_size, raw_ofs); const int MAX_IOS = 2; Handle ios[MAX_IOS] = { 0 }; -if(ios[0] || ios[1])abort(); - int head = 0; int tail = 0; int pending_ios = 0; @@ -1119,11 +1138,6 @@ if(ios[0] || ios[1])abort(); ssize_t err = +1; // loop terminates if <= 0 -static int seq; -seq++; -if(seq == 4) -seq=4; - for(;;) { // queue not full, data remaining to transfer, and no error: diff --git a/source/lib/res/vfs.cpp b/source/lib/res/vfs.cpp index 8f18e8d00b..4572a95be0 100755 --- a/source/lib/res/vfs.cpp +++ b/source/lib/res/vfs.cpp @@ -883,21 +883,30 @@ Handle vfs_open(const char* fn, uint flags /* = 0 */) Handle h = h_alloc(H_VFile, fn, 0, flags); // pass file flags to init +#ifdef PARANOIA debug_out("vfs_open fn=%s %I64x\n", fn, h); -return h; +#endif + + return h; } inline int vfs_close(Handle& h) { +#ifdef PARANOIA debug_out("vfs_close %I64x\n", h); +#endif + return h_free(h, H_VFile); } ssize_t vfs_io(Handle hf, size_t ofs, size_t size, void*& p) { +#ifdef PARANOIA debug_out("vfs_io ofs=%d size=%d\n", ofs, size); +#endif + H_DEREF(hf, VFile, vf); // (vfs_open makes sure it's not opened for writing if zip) @@ -913,7 +922,10 @@ debug_out("vfs_io ofs=%d size=%d\n", ofs, size); Handle vfs_load(const char* fn, void*& p, size_t& size) { +#ifdef PARANOIA debug_out("vfs_load fn=%s\n", fn); +#endif + p = 0; // vfs_io needs initial 0 value size = 0; // in case open or deref fails diff --git a/source/lib/sysdep/win/win.cpp b/source/lib/sysdep/win/win.cpp index 819d445107..fcb8afb0af 100755 --- a/source/lib/sysdep/win/win.cpp +++ b/source/lib/sysdep/win/win.cpp @@ -164,9 +164,9 @@ static inline void pre_main_init() atexit(at_exit); - // real SDL will do this as well. no matter. - // ignore BoundsChecker warning here. - freopen("stdout.txt", "wt", stdout); + // no point redirecting stdout yet - the current directory + // may be incorrect (file_set_root not yet called). + // (w)sdl will take care of it anyway. } diff --git a/source/lib/sysdep/win/wsdl.cpp b/source/lib/sysdep/win/wsdl.cpp index 910bad1923..0b298c4b41 100755 --- a/source/lib/sysdep/win/wsdl.cpp +++ b/source/lib/sysdep/win/wsdl.cpp @@ -366,6 +366,16 @@ int SDL_GL_SetAttribute(SDL_GLattr attr, int value) } +int SDL_Init(Uint32 flags) +{ + FILE* const ret = freopen("stdout.txt", "w", stdout); + if(!ret) + debug_warn("SDL_Init freopen failed"); + + return 0; +} + + /* * set video mode wxh:bpp if necessary. * w = h = bpp = 0 => no change. diff --git a/source/lib/sysdep/win/wsdl.h b/source/lib/sysdep/win/wsdl.h index 7384063357..393e710195 100755 --- a/source/lib/sysdep/win/wsdl.h +++ b/source/lib/sysdep/win/wsdl.h @@ -14,12 +14,17 @@ extern "C" { #endif + +#define Uint32 u32 + /* SDL_Init flags */ #define SDL_INIT_VIDEO 0 #define SDL_INIT_AUDIO 0 #define SDL_INIT_TIMER 0 #define SDL_INIT_NOPARACHUTE 0 +extern int SDL_Init(Uint32 flags); + extern void SDL_Quit(); @@ -86,8 +91,6 @@ extern int __stdcall SDL_WarpMouse(int, int); /* macros */ -#define SDL_Init - #define SDL_GRAB_ON 0 #define SDL_WM_GrabInput(a) #define SDL_GetError() "" diff --git a/source/main.cpp b/source/main.cpp index df4a2dcdae..5631bd327f 100755 --- a/source/main.cpp +++ b/source/main.cpp @@ -47,45 +47,54 @@ extern void terr_init(); extern void terr_update(float time); extern bool terr_handler(const SDL_Event& ev); +extern int allow_reload(); +extern int dir_add_watch(const char* const dir, bool watch_subdirs); -static void write_sys_info() + + +static int write_sys_info() { get_gfx_info(); struct utsname un; uname(&un); - freopen("stdout.txt", "w", stdout); + + FILE* const f = fopen("../system/system_info.txt", "w"); + if(!f) + return -1; + // .. OS - printf("%s %s (%s)\n", un.sysname, un.release, un.version); + fprintf(f, "%s %s (%s)\n", un.sysname, un.release, un.version); // .. CPU - printf("%s, %s", un.machine, cpu_type); + fprintf(f, "%s, %s", un.machine, cpu_type); if(cpu_freq != 0.0f) { if(cpu_freq < 1e9) - printf(", %.2f MHz\n", cpu_freq*1e-6); + fprintf(f, ", %.2f MHz\n", cpu_freq*1e-6); else - printf(", %.2f GHz\n", cpu_freq*1e-9); + fprintf(f, ", %.2f GHz\n", cpu_freq*1e-9); } else - printf("\n"); + fprintf(f, "\n"); // .. memory - printf("%lu MB RAM; %lu MB free\n", tot_mem/MB, avl_mem/MB); + fprintf(f, "%lu MB RAM; %lu MB free\n", tot_mem/MB, avl_mem/MB); // .. graphics card - printf("%s\n", gfx_card); - printf("%s\n", gfx_drv); + fprintf(f, "%s\n", gfx_card); + fprintf(f, "%s\n", gfx_drv); // .. network name / ips char hostname[100]; // possibly nodename != hostname gethostname(hostname, sizeof(hostname)); - printf("%s\n", hostname); + fprintf(f, "%s\n", hostname); hostent* h = gethostbyname(hostname); if(h) { struct in_addr** ips = (struct in_addr**)h->h_addr_list; for(int i = 0; ips && ips[i]; i++) - printf("%s ", inet_ntoa(*ips[i])); - printf("\n"); + fprintf(f, "%s ", inet_ntoa(*ips[i])); + fprintf(f, "\n"); } - fflush(stdout); + + fclose(f); } @@ -149,12 +158,6 @@ static bool handler(const SDL_Event& ev) case SDLK_ESCAPE: quit = true; break; - - - case '1': - case SDLK_F1: - res_reload("art/textures/terrain/types/grass/Base1.tga"); - break; } break; @@ -348,8 +351,13 @@ void ParseArgs(int argc, char* argv[]) int main(int argc, char* argv[]) { - ParseArgs(argc,argv); +file_set_root_dir(argv[0], "../data"); +argc=2; + argv[1] = "-m=test01.pmp"; + + ParseArgs(argc,argv); +/* chdir("\\games\\bf\\ScreenShots"); int a,b; char fn[100]; @@ -395,12 +403,14 @@ sprintf(fn, "ScreenShot%d.jpg", i); if(access(fn, F_OK) < 0) break; } -*/ + __asm cpuid __asm rdtsc __asm mov b, eax int c = b-a; +*/ + lib_init(); // set 24 bit (float) FPU precision for faster divides / sqrts @@ -451,8 +461,8 @@ int c = b-a; new CConfig; - file_set_root_dir(argv[0], "../data"); vfs_mount("", "mods/official/", 0); + dir_add_watch("mods\\official", false); #ifndef NO_GUI // GUI uses VFS, so this must come after VFS init. @@ -507,6 +517,9 @@ in_add_handler(terr_handler); { g_Config.Update(); + allow_reload(); + + // TODO: limiter in case simulation can't keep up? #if 0 double time1 = get_time(); diff --git a/source/terrain/TextureManager.cpp b/source/terrain/TextureManager.cpp index 892072cc99..a296cc88c2 100755 --- a/source/terrain/TextureManager.cpp +++ b/source/terrain/TextureManager.cpp @@ -1,201 +1,201 @@ -#include "TextureManager.h" -#include "lib.h" -#include "ogl.h" -#include "res/tex.h" -#ifdef _WIN32 -#include -#endif -#include - -const char* SupportedTextureFormats[] = { "png", "dds", "tga", "bmp" }; - - -CTextureManager g_TexMan; - - -CTextureManager::CTextureManager() -{ - m_TerrainTextures.reserve(32); -} - -void CTextureManager::AddTextureType(const char* name) -{ - m_TerrainTextures.resize(m_TerrainTextures.size()+1); - STextureType& ttype=m_TerrainTextures.back(); - ttype.m_Name=name; - ttype.m_Index=m_TerrainTextures.size()-1; -} - -CTextureEntry* CTextureManager::FindTexture(const char* filename) -{ - // check if file already loaded - for (uint k=0;km_Name,filename)==0) { - return ttype.m_Textures[i]; - } - } - } - - return 0; -} - -CTextureEntry* CTextureManager::FindTexture(Handle handle) -{ - for (uint k=0;km_Handle) { - return ttype.m_Textures[i]; - } - } - } - - return 0; -} - -CTextureEntry* CTextureManager::AddTexture(const char* filename,int type) -{ - assert((uint)typem_Name=filename; - texentry->m_Handle=h; - texentry->m_Type=type; - - // upload texture for future GL use - tex_upload(h,GL_LINEAR_MIPMAP_LINEAR); - - // setup texture to repeat - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); - - // get root color for coloring minimap by querying root level of the texture - // (this should decompress any compressed textures for us), - // then scaling it down to a 1x1 size - // - an alternative approach of just grabbing the top level of the mipmap tree fails - // (or gives an incorrect colour) in some cases: - // - suspect bug on Radeon cards when SGIS_generate_mipmap is used - // - any textures without mipmaps - // we'll just take the basic approach here: - int width,height; - glGetTexLevelParameteriv(GL_TEXTURE_2D,0,GL_TEXTURE_WIDTH,&width); - glGetTexLevelParameteriv(GL_TEXTURE_2D,0,GL_TEXTURE_HEIGHT,&height); - - unsigned char* buf=new unsigned char[width*height*4]; - glGetTexImage(GL_TEXTURE_2D,0,GL_BGRA_EXT,GL_UNSIGNED_BYTE,buf); - gluScaleImage(GL_BGRA_EXT,width,height,GL_UNSIGNED_BYTE,buf, - 1,1,GL_UNSIGNED_BYTE,&texentry->m_BaseColor); - delete[] buf; - - // add entry to list .. - m_TerrainTextures[type].m_Textures.push_back(texentry); - - // .. and return it - return texentry; -} - -void CTextureManager::DeleteTexture(CTextureEntry* entry) -{ - // find entry in list - std::vector& textures=m_TerrainTextures[entry->m_Type].m_Textures; - - typedef std::vector::iterator Iter; - Iter i=std::find(textures.begin(),textures.end(),entry); - if (i!=textures.end()) { - textures.erase(i); - } - delete entry; -} - -void CTextureManager::LoadTerrainTextures(int terraintype,const char* fileext) -{ -#ifdef _WIN32 - struct _finddata_t file; - long handle; - - // build pathname - CStr pathname("mods\\official\\art\\textures\\terrain\\types\\"); - pathname+=m_TerrainTextures[terraintype].m_Name; - pathname+="\\"; - - CStr findname(pathname); - findname+="*."; - findname+=fileext; - - // Find first matching file in directory for this terrain type - if ((handle=_findfirst((const char*) findname,&file))!=-1) { - - AddTexture(file.name,terraintype); - - // Find the rest of the matching files - while( _findnext(handle,&file)==0) { - AddTexture((const char*) file.name,terraintype); - } - - _findclose(handle); - } -#endif -} - -void CTextureManager::BuildTerrainTypes() -{ -#ifdef _WIN32 - struct _finddata_t file; - long handle; - - // Find first matching directory in terrain\textures - if ((handle=_findfirst("mods\\official\\art\\textures\\terrain\\types\\*",&file))!=-1) { - - if ((file.attrib & _A_SUBDIR) && file.name[0]!='.') { - AddTextureType(file.name); - } - - // Find the rest of the matching files - while( _findnext(handle,&file)==0) { - if ((file.attrib & _A_SUBDIR) && file.name[0]!='.') { - AddTextureType(file.name); - } - } - - _findclose(handle); - } -#endif -} - -void CTextureManager::LoadTerrainTextures() -{ - // find all the terrain types by directory name - BuildTerrainTypes(); - - // now iterate through terrain types loading all textures of that type - for (uint i=0;i +#endif +#include + +const char* SupportedTextureFormats[] = { "png", "dds", "tga", "bmp" }; + + +CTextureManager g_TexMan; + + +CTextureManager::CTextureManager() +{ + m_TerrainTextures.reserve(32); +} + +void CTextureManager::AddTextureType(const char* name) +{ + m_TerrainTextures.resize(m_TerrainTextures.size()+1); + STextureType& ttype=m_TerrainTextures.back(); + ttype.m_Name=name; + ttype.m_Index=m_TerrainTextures.size()-1; +} + +CTextureEntry* CTextureManager::FindTexture(const char* filename) +{ + // check if file already loaded + for (uint k=0;km_Name,filename)==0) { + return ttype.m_Textures[i]; + } + } + } + + return 0; +} + +CTextureEntry* CTextureManager::FindTexture(Handle handle) +{ + for (uint k=0;km_Handle) { + return ttype.m_Textures[i]; + } + } + } + + return 0; +} + +CTextureEntry* CTextureManager::AddTexture(const char* filename,int type) +{ + assert((uint)typem_Name=filename; + texentry->m_Handle=h; + texentry->m_Type=type; + + // upload texture for future GL use + tex_upload(h,GL_LINEAR_MIPMAP_LINEAR); + + // setup texture to repeat + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + + // get root color for coloring minimap by querying root level of the texture + // (this should decompress any compressed textures for us), + // then scaling it down to a 1x1 size + // - an alternative approach of just grabbing the top level of the mipmap tree fails + // (or gives an incorrect colour) in some cases: + // - suspect bug on Radeon cards when SGIS_generate_mipmap is used + // - any textures without mipmaps + // we'll just take the basic approach here: + int width,height; + glGetTexLevelParameteriv(GL_TEXTURE_2D,0,GL_TEXTURE_WIDTH,&width); + glGetTexLevelParameteriv(GL_TEXTURE_2D,0,GL_TEXTURE_HEIGHT,&height); + + unsigned char* buf=new unsigned char[width*height*4]; + glGetTexImage(GL_TEXTURE_2D,0,GL_BGRA_EXT,GL_UNSIGNED_BYTE,buf); + gluScaleImage(GL_BGRA_EXT,width,height,GL_UNSIGNED_BYTE,buf, + 1,1,GL_UNSIGNED_BYTE,&texentry->m_BaseColor); + delete[] buf; + + // add entry to list .. + m_TerrainTextures[type].m_Textures.push_back(texentry); + + // .. and return it + return texentry; +} + +void CTextureManager::DeleteTexture(CTextureEntry* entry) +{ + // find entry in list + std::vector& textures=m_TerrainTextures[entry->m_Type].m_Textures; + + typedef std::vector::iterator Iter; + Iter i=std::find(textures.begin(),textures.end(),entry); + if (i!=textures.end()) { + textures.erase(i); + } + delete entry; +} + +void CTextureManager::LoadTerrainTextures(int terraintype,const char* fileext) +{ +#ifdef _WIN32 + struct _finddata_t file; + long handle; + + // build pathname + CStr pathname("mods\\official\\art\\textures\\terrain\\types\\"); + pathname+=m_TerrainTextures[terraintype].m_Name; + pathname+="\\"; + + CStr findname(pathname); + findname+="*."; + findname+=fileext; + + // Find first matching file in directory for this terrain type + if ((handle=_findfirst((const char*) findname,&file))!=-1) { + + AddTexture(file.name,terraintype); + + // Find the rest of the matching files + while( _findnext(handle,&file)==0) { + AddTexture((const char*) file.name,terraintype); + } + + _findclose(handle); + } +#endif +} + +void CTextureManager::BuildTerrainTypes() +{ +#ifdef _WIN32 + struct _finddata_t file; + long handle; + + // Find first matching directory in terrain\textures + if ((handle=_findfirst("mods\\official\\art\\textures\\terrain\\types\\*",&file))!=-1) { + + if ((file.attrib & _A_SUBDIR) && file.name[0]!='.') { + AddTextureType(file.name); + } + + // Find the rest of the matching files + while( _findnext(handle,&file)==0) { + if ((file.attrib & _A_SUBDIR) && file.name[0]!='.') { + AddTextureType(file.name); + } + } + + _findclose(handle); + } +#endif +} + +void CTextureManager::LoadTerrainTextures() +{ + // find all the terrain types by directory name + BuildTerrainTypes(); + + // now iterate through terrain types loading all textures of that type + for (uint i=0;i - -// TODO: fix scrolling hack - framerate independent, use SDL -//#include "win.h" // REMOVEME - -void InitScene (); -void InitResources (); -void RenderScene (); - -extern bool keys[512]; // SDL also defines non-ascii keys; 512 should be enough - - -CMatrix3D g_WorldMat; -CRenderer g_Renderer; -CTerrain g_Terrain; -CCamera g_Camera; -CLightEnv g_LightEnv; - -int SelPX, SelPY, SelTX, SelTY; -int g_BaseTexCounter = 0; -int g_SecTexCounter = 1; -int g_TransTexCounter = 0; - -int g_TickCounter = 0; -double g_LastTime; - - -const int NUM_ALPHA_MAPS = 13; - -int mouse_x=50, mouse_y=50; - -void terr_init() -{ - int xres,yres; - get_cur_resolution(xres,yres); - g_Renderer.Open(xres,yres,32); - - SViewPort vp; - vp.m_X=0; - vp.m_Y=0; - vp.m_Width=xres; - vp.m_Height=yres; - g_Camera.SetViewPort(&vp); - - InitResources (); - InitScene (); -} - -void terr_update(float time) -{ - CVector3D right(time*60,0,time*60); - CVector3D up(time*60,0,-time*60); - - if (mouse_x >= g_xres-2) - g_Camera.m_Orientation.Translate(right); - if (mouse_x <= 3) - g_Camera.m_Orientation.Translate(right*-1); - - if (mouse_y >= g_yres-2) - g_Camera.m_Orientation.Translate(up); - if (mouse_y <= 3) - g_Camera.m_Orientation.Translate(up*-1); - - - - float fov = g_Camera.GetFOV(); - float d = DEGTORAD(0.4f); - if(keys[SDLK_KP_MINUS]) - if (fov+d < DEGTORAD(90)) - g_Camera.SetProjection(1, 1000, fov + d); - if(keys[SDLK_KP_PLUS]) - if (fov-d > DEGTORAD(20)) - g_Camera.SetProjection(1, 1000, fov - d); - - g_Camera.UpdateFrustum (); -} - - - - - - -bool terr_handler(const SDL_Event& ev) -{ - switch(ev.type) - { - case SDL_MOUSEMOTION: - mouse_x = ev.motion.x; - mouse_y = ev.motion.y; - break; - - case SDL_KEYDOWN: - switch(ev.key.keysym.sym) - { - case 'W': - if (g_Renderer.GetTerrainRenderMode()==WIREFRAME) { - g_Renderer.SetTerrainRenderMode(SOLID); - } else { - g_Renderer.SetTerrainRenderMode(WIREFRAME); - } - break; - - case 'H': - // quick hack to return camera home, for screenshots (after alt+tabbing) - g_Camera.SetProjection (1, 1000, DEGTORAD(20)); - g_Camera.m_Orientation.SetXRotation(DEGTORAD(30)); - g_Camera.m_Orientation.RotateY(DEGTORAD(-45)); - g_Camera.m_Orientation.Translate (100, 150, -100); - break; - -/* case 'L': - g_HillShading = !g_HillShading; - break;*/ - -// tile selection - case SDLK_DOWN: - if(++SelTX > 15) - if(SelPX == g_Terrain.GetPatchesPerSide()-1) - SelTX = 15; - else - SelTX = 0, SelPX++; - break; - - case SDLK_UP: - if(--SelTX < 0) - if(SelPX == 0) - SelTX = 0; - else - SelTX = 15, SelPX--; - break; - case SDLK_RIGHT: - if(++SelTY > 15) - if(SelPY == g_Terrain.GetPatchesPerSide()-1) - SelTY = 15; - else - SelTY = 0, SelPY++; - break; - - case SDLK_LEFT: - if(--SelTY < 0) - if(SelPY == 0) - SelTY = 0; - else - SelTY = 15, SelPY--; - break; - - - case SDLK_KP0: - { - CMiniPatch *MPatch = &g_Terrain.GetPatch(SelPY, SelPX)->m_MiniPatches[SelTY][SelTX]; - /*if (!MPatch->Tex2) - { - MPatch->m_AlphaMap = AlphaMaps[g_TransTexCounter]; - MPatch->Tex2 = BaseTexs[g_SecTexCounter]; - } - else - { - MPatch->Tex2 = 0; - MPatch->m_AlphaMap = 0; - }*/ - break; - } - - /*case SDLK_KP1: - { - CMiniPatch *MPatch = &g_Terrain.GetPatch(SelPY, SelPX)->m_MiniPatches[SelTY][SelTX]; - - g_BaseTexCounter++; - if (g_BaseTexCounter > 4) - g_BaseTexCounter = 0; - - MPatch->Tex1 = BaseTexs[g_BaseTexCounter]; - break; - } - - case SDLK_KP2: - { - CMiniPatch *MPatch = &g_Terrain.m_Patches[SelPY][SelPX].m_MiniPatches[SelTY][SelTX]; - - if (MPatch->Tex2) - { - g_SecTexCounter++; - if (g_SecTexCounter > 4) - g_SecTexCounter = 0; - - MPatch->Tex2 = BaseTexs[g_SecTexCounter]; - } - - break; - } - - case SDLK_KP3: - { - CMiniPatch *MPatch = &g_Terrain.m_Patches[SelPY][SelPX].m_MiniPatches[SelTY][SelTX]; - - if (MPatch->m_AlphaMap) - { - g_TransTexCounter++; - if (g_TransTexCounter >= NUM_ALPHA_MAPS) - g_TransTexCounter = 0; - - MPatch->m_AlphaMap = AlphaMaps[g_TransTexCounter]; - } - - break; - }*/ - - } - } - - return false; -} - - - - -void InitScene () -{ - // setup default lighting environment - g_LightEnv.m_SunColor=RGBColor(1,1,1); - g_LightEnv.m_Rotation=DEGTORAD(270); - g_LightEnv.m_Elevation=DEGTORAD(45); - g_LightEnv.m_TerrainAmbientColor=RGBColor(0,0,0); - g_LightEnv.m_UnitsAmbientColor=RGBColor(0.4f,0.4f,0.4f); - g_Renderer.SetLightEnv(&g_LightEnv); - - // load terrain - Handle ht = tex_load("terrain.raw"); - if(ht > 0) - { - const u8* p; - int w; - int h; - - tex_info(ht, &w, &h, NULL, NULL, (void **)&p); - - printf("terrain.raw: %dx%d\n", w, h); - - u16 *p16=new u16[w*h]; - u16 *p16p=p16; - while (p16p < p16+(w*h)) - *p16p++ = (*p++) << 8; - - g_Terrain.Resize(20); - g_Terrain.SetHeightMap(p16); - - delete[] p16; - - tex_free(ht); - } - - // get default texture to apply to terrain - CTextureEntry* texture=0; -for (uint ii=0;iim_MiniPatches[j][i].Tex1=texture ? texture->m_Handle :0; - } - } - } - } - - g_Camera.SetProjection (1, 1000, DEGTORAD(20)); - g_Camera.m_Orientation.SetXRotation(DEGTORAD(30)); - g_Camera.m_Orientation.RotateY(DEGTORAD(-45)); - - g_Camera.m_Orientation.Translate (100, 150, -100); - - SelPX = SelPY = SelTX = SelTY = 0; -} - -void InitResources() -{ -#ifndef _WIN32 - g_TexMan.AddTextureType("grass"); - g_TexMan.AddTexture("Base1.tga", 0); -#else - g_TexMan.LoadTerrainTextures(); - g_ObjMan.LoadObjects(); -#endif - - const char* fns[CRenderer::NumAlphaMaps] = { - "art/textures/terrain/alphamaps/special/blendcircle.png", - "art/textures/terrain/alphamaps/special/blendlshape.png", - "art/textures/terrain/alphamaps/special/blendedge.png", - "art/textures/terrain/alphamaps/special/blendedgecorner.png", - "art/textures/terrain/alphamaps/special/blendedgetwocorners.png", - "art/textures/terrain/alphamaps/special/blendfourcorners.png", - "art/textures/terrain/alphamaps/special/blendtwooppositecorners.png", - "art/textures/terrain/alphamaps/special/blendlshapecorner.png", - "art/textures/terrain/alphamaps/special/blendtwocorners.png", - "art/textures/terrain/alphamaps/special/blendcorner.png", - "art/textures/terrain/alphamaps/special/blendtwoedges.png", - "art/textures/terrain/alphamaps/special/blendthreecorners.png", - "art/textures/terrain/alphamaps/special/blendushape.png", - "art/textures/terrain/alphamaps/special/blendbad.png" - }; - - g_Renderer.LoadAlphaMaps(fns); -} +#include "Matrix3D.h" +#include "Renderer.h" +#include "Terrain.h" +#include "LightEnv.h" +#include "TextureManager.h" +#include "ObjectManager.h" +#include "Prometheus.h" + +#include "time.h" +#include "sdl.h" +#include "res/tex.h" +#include "detect.h" + +#include + +// TODO: fix scrolling hack - framerate independent, use SDL +//#include "win.h" // REMOVEME + +void InitScene (); +void InitResources (); +void RenderScene (); + +extern bool keys[512]; // SDL also defines non-ascii keys; 512 should be enough + + +CMatrix3D g_WorldMat; +CRenderer g_Renderer; +CTerrain g_Terrain; +CCamera g_Camera; +CLightEnv g_LightEnv; + +int SelPX, SelPY, SelTX, SelTY; +int g_BaseTexCounter = 0; +int g_SecTexCounter = 1; +int g_TransTexCounter = 0; + +int g_TickCounter = 0; +double g_LastTime; + + +const int NUM_ALPHA_MAPS = 13; + +int mouse_x=50, mouse_y=50; + +void terr_init() +{ + int xres,yres; + get_cur_resolution(xres,yres); + g_Renderer.Open(xres,yres,32); + + SViewPort vp; + vp.m_X=0; + vp.m_Y=0; + vp.m_Width=xres; + vp.m_Height=yres; + g_Camera.SetViewPort(&vp); + + InitResources (); + InitScene (); +} + +void terr_update(float time) +{ + CVector3D right(time*60,0,time*60); + CVector3D up(time*60,0,-time*60); + + if (mouse_x >= g_xres-2) + g_Camera.m_Orientation.Translate(right); + if (mouse_x <= 3) + g_Camera.m_Orientation.Translate(right*-1); + + if (mouse_y >= g_yres-2) + g_Camera.m_Orientation.Translate(up); + if (mouse_y <= 3) + g_Camera.m_Orientation.Translate(up*-1); + + + + float fov = g_Camera.GetFOV(); + float d = DEGTORAD(0.4f); + if(keys[SDLK_KP_MINUS]) + if (fov+d < DEGTORAD(90)) + g_Camera.SetProjection(1, 1000, fov + d); + if(keys[SDLK_KP_PLUS]) + if (fov-d > DEGTORAD(20)) + g_Camera.SetProjection(1, 1000, fov - d); + + g_Camera.UpdateFrustum (); +} + + + + +bool terr_handler(const SDL_Event& ev) +{ + switch(ev.type) + { + case SDL_MOUSEMOTION: + mouse_x = ev.motion.x; + mouse_y = ev.motion.y; + break; + + case SDL_KEYDOWN: + switch(ev.key.keysym.sym) + { + case 'W': + if (g_Renderer.GetTerrainRenderMode()==WIREFRAME) { + g_Renderer.SetTerrainRenderMode(SOLID); + } else { + g_Renderer.SetTerrainRenderMode(WIREFRAME); + } + break; + + case 'H': + // quick hack to return camera home, for screenshots (after alt+tabbing) + g_Camera.SetProjection (1, 1000, DEGTORAD(20)); + g_Camera.m_Orientation.SetXRotation(DEGTORAD(30)); + g_Camera.m_Orientation.RotateY(DEGTORAD(-45)); + g_Camera.m_Orientation.Translate (100, 150, -100); + break; + +/* case 'L': + g_HillShading = !g_HillShading; + break;*/ + +// tile selection + case SDLK_DOWN: + if(++SelTX > 15) + if(SelPX == g_Terrain.GetPatchesPerSide()-1) + SelTX = 15; + else + SelTX = 0, SelPX++; + break; + + case SDLK_UP: + if(--SelTX < 0) + if(SelPX == 0) + SelTX = 0; + else + SelTX = 15, SelPX--; + break; + case SDLK_RIGHT: + if(++SelTY > 15) + if(SelPY == g_Terrain.GetPatchesPerSide()-1) + SelTY = 15; + else + SelTY = 0, SelPY++; + break; + + case SDLK_LEFT: + if(--SelTY < 0) + if(SelPY == 0) + SelTY = 0; + else + SelTY = 15, SelPY--; + break; + + + case SDLK_KP0: + { + CMiniPatch *MPatch = &g_Terrain.GetPatch(SelPY, SelPX)->m_MiniPatches[SelTY][SelTX]; + /*if (!MPatch->Tex2) + { + MPatch->m_AlphaMap = AlphaMaps[g_TransTexCounter]; + MPatch->Tex2 = BaseTexs[g_SecTexCounter]; + } + else + { + MPatch->Tex2 = 0; + MPatch->m_AlphaMap = 0; + }*/ + break; + } + + /*case SDLK_KP1: + { + CMiniPatch *MPatch = &g_Terrain.GetPatch(SelPY, SelPX)->m_MiniPatches[SelTY][SelTX]; + + g_BaseTexCounter++; + if (g_BaseTexCounter > 4) + g_BaseTexCounter = 0; + + MPatch->Tex1 = BaseTexs[g_BaseTexCounter]; + break; + } + + case SDLK_KP2: + { + CMiniPatch *MPatch = &g_Terrain.m_Patches[SelPY][SelPX].m_MiniPatches[SelTY][SelTX]; + + if (MPatch->Tex2) + { + g_SecTexCounter++; + if (g_SecTexCounter > 4) + g_SecTexCounter = 0; + + MPatch->Tex2 = BaseTexs[g_SecTexCounter]; + } + + break; + } + + case SDLK_KP3: + { + CMiniPatch *MPatch = &g_Terrain.m_Patches[SelPY][SelPX].m_MiniPatches[SelTY][SelTX]; + + if (MPatch->m_AlphaMap) + { + g_TransTexCounter++; + if (g_TransTexCounter >= NUM_ALPHA_MAPS) + g_TransTexCounter = 0; + + MPatch->m_AlphaMap = AlphaMaps[g_TransTexCounter]; + } + + break; + }*/ + + } + } + + return false; +} + + + + +void InitScene () +{ + // setup default lighting environment + g_LightEnv.m_SunColor=RGBColor(1,1,1); + g_LightEnv.m_Rotation=DEGTORAD(270); + g_LightEnv.m_Elevation=DEGTORAD(45); + g_LightEnv.m_TerrainAmbientColor=RGBColor(0,0,0); + g_LightEnv.m_UnitsAmbientColor=RGBColor(0.4f,0.4f,0.4f); + g_Renderer.SetLightEnv(&g_LightEnv); + + // load terrain + Handle ht = tex_load("terrain.raw"); + if(ht > 0) + { + const u8* p; + int w; + int h; + + tex_info(ht, &w, &h, NULL, NULL, (void **)&p); + + printf("terrain.raw: %dx%d\n", w, h); + + u16 *p16=new u16[w*h]; + u16 *p16p=p16; + while (p16p < p16+(w*h)) + *p16p++ = (*p++) << 8; + + g_Terrain.Resize(20); + g_Terrain.SetHeightMap(p16); + + delete[] p16; + + tex_free(ht); + } + + // get default texture to apply to terrain + CTextureEntry* texture=0; +for (uint ii=0;iim_MiniPatches[j][i].Tex1=texture ? texture->m_Handle :0; + } + } + } + } + + g_Camera.SetProjection (1, 1000, DEGTORAD(20)); + g_Camera.m_Orientation.SetXRotation(DEGTORAD(30)); + g_Camera.m_Orientation.RotateY(DEGTORAD(-45)); + + g_Camera.m_Orientation.Translate (100, 150, -100); + + SelPX = SelPY = SelTX = SelTY = 0; +} + +void InitResources() +{ +#ifndef _WIN32 + g_TexMan.AddTextureType("grass"); + g_TexMan.AddTexture("Base1.tga", 0); +#else + g_TexMan.LoadTerrainTextures(); + g_ObjMan.LoadObjects(); +#endif + + const char* fns[CRenderer::NumAlphaMaps] = { + "art/textures/terrain/alphamaps/special/blendcircle.png", + "art/textures/terrain/alphamaps/special/blendlshape.png", + "art/textures/terrain/alphamaps/special/blendedge.png", + "art/textures/terrain/alphamaps/special/blendedgecorner.png", + "art/textures/terrain/alphamaps/special/blendedgetwocorners.png", + "art/textures/terrain/alphamaps/special/blendfourcorners.png", + "art/textures/terrain/alphamaps/special/blendtwooppositecorners.png", + "art/textures/terrain/alphamaps/special/blendlshapecorner.png", + "art/textures/terrain/alphamaps/special/blendtwocorners.png", + "art/textures/terrain/alphamaps/special/blendcorner.png", + "art/textures/terrain/alphamaps/special/blendtwoedges.png", + "art/textures/terrain/alphamaps/special/blendthreecorners.png", + "art/textures/terrain/alphamaps/special/blendushape.png", + "art/textures/terrain/alphamaps/special/blendbad.png" + }; + + g_Renderer.LoadAlphaMaps(fns); +}