diff --git a/source/graphics/Color.cpp b/source/graphics/Color.cpp index ce3ace90d1..d87297641a 100644 --- a/source/graphics/Color.cpp +++ b/source/graphics/Color.cpp @@ -17,3 +17,25 @@ static u32 fallback_ConvertRGBColorTo4ub(const RGBColor& src) // on IA32, this is replaced by an SSE assembly version in ia32.cpp u32 (*ConvertRGBColorTo4ub)(const RGBColor& src) = fallback_ConvertRGBColorTo4ub; + +// Assembler-optimized function for color conversion +#if CPU_IA32 +extern "C" u32 sse_ConvertRGBColorTo4ub(const RGBColor& src); +#endif + +void ColorActivateFastImpl() +{ + if(0) + { + } +#if CPU_IA32 + else if (ia32_cap(SSE)) + { + ConvertRGBColorTo4ub = sse_ConvertRGBColorTo4ub; + } +#endif + else + { + debug_printf("No SSE available. Slow fallback routines will be used.\n"); + } +} diff --git a/source/graphics/Color.h b/source/graphics/Color.h index 6fc48225e8..c5f0416c98 100755 --- a/source/graphics/Color.h +++ b/source/graphics/Color.h @@ -38,7 +38,13 @@ struct SColor4ub SColor4ub(u8 _r, u8 _g, u8 _b, u8 _a) : R(_r), G(_g), B(_b), A(_a) { } }; +// exposed as function pointer because it is set at init-time to +// one of several implementations depending on CPU caps. extern u32 (*ConvertRGBColorTo4ub)(const RGBColor& src); +// call once ia32_init has run; detects CPU caps and activates the best +// possible codepath. +extern void ColorActivateFastImpl(); + #endif diff --git a/source/graphics/ObjectManager.cpp b/source/graphics/ObjectManager.cpp index 955842da5f..736e7fa9f2 100755 --- a/source/graphics/ObjectManager.cpp +++ b/source/graphics/ObjectManager.cpp @@ -191,12 +191,12 @@ static void GetObjectName_ThunkCb(const char* path, const DirEnt* UNUSED(ent), v void CObjectManager::GetAllObjectNames(std::vector& names) { - VFSUtil::EnumDirEnts("art/actors/", VFSUtil::RECURSIVE, "*.xml", + vfs_dir_enum("art/actors/", VFS_DIR_RECURSIVE, "*.xml", GetObjectName_ThunkCb, &names); } void CObjectManager::GetPropObjectNames(std::vector& names) { - VFSUtil::EnumDirEnts("art/actors/props/", VFSUtil::RECURSIVE, "*.xml", + vfs_dir_enum("art/actors/props/", VFS_DIR_RECURSIVE, "*.xml", GetObjectName_ThunkCb, &names); } diff --git a/source/lib/res/file/vfs.cpp b/source/lib/res/file/vfs.cpp index ce4d7cda9c..7104994551 100755 --- a/source/lib/res/file/vfs.cpp +++ b/source/lib/res/file/vfs.cpp @@ -239,6 +239,85 @@ LibError vfs_dir_next_ent(const Handle hd, DirEnt* ent, const char* filter) } +// call for each entry matching (see vfs_next_dirent) in +// directory ; if flags & VFS_DIR_RECURSIVE, entries in +// subdirectories are also returned. +// +// note: EnumDirEntsCB path and ent are only valid during the callback. +LibError vfs_dir_enum(const char* start_path, uint flags, const char* user_filter, + DirEnumCB cb, void* context) +{ + debug_assert((flags & ~(VFS_DIR_RECURSIVE)) == 0); + const bool recursive = (flags & VFS_DIR_RECURSIVE) != 0; + + char filter_buf[VFS_MAX_PATH]; + const char* filter = user_filter; + bool user_filter_wants_dirs = true; + if(user_filter) + { + if(user_filter[0] != '/') + user_filter_wants_dirs = false; + + // we need subdirectories and the caller hasn't already requested them + if(recursive && !user_filter_wants_dirs) + { + snprintf(filter_buf, sizeof(filter_buf), "/|%s", user_filter); + filter = filter_buf; + } + } + + + // note: FIFO queue instead of recursion is much more efficient + // (less stack usage; avoids seeks by reading all entries in a + // directory consecutively) + + std::queue dir_queue; + dir_queue.push(file_make_unique_fn_copy(start_path)); + + // for each directory: + do + { + // get current directory path from queue + // note: can't refer to the queue contents - those are invalidated + // as soon as a directory is pushed onto it. + PathPackage pp; + (void)pp_set_dir(&pp, dir_queue.front()); + dir_queue.pop(); + + Handle hdir = vfs_dir_open(pp.path); + if(hdir <= 0) + { + debug_warn("vfs_open_dir failed"); + continue; + } + + // for each entry (file, subdir) in directory: + DirEnt ent; + while(vfs_dir_next_ent(hdir, &ent, filter) == 0) + { + // build complete path (DirEnt only stores entry name) + (void)pp_append_file(&pp, ent.name); + const char* atom_path = file_make_unique_fn_copy(pp.path); + + if(DIRENT_IS_DIR(&ent)) + { + if(recursive) + dir_queue.push(atom_path); + + if(user_filter_wants_dirs) + cb(atom_path, &ent, context); + } + else + cb(atom_path, &ent, context); + } + + vfs_dir_close(hdir); + } + while(!dir_queue.empty()); + + return ERR_OK; +} + /////////////////////////////////////////////////////////////////////////////// // diff --git a/source/lib/res/file/vfs.h b/source/lib/res/file/vfs.h index 7743fb6423..7a0e4f7417 100755 --- a/source/lib/res/file/vfs.h +++ b/source/lib/res/file/vfs.h @@ -321,6 +321,25 @@ extern LibError vfs_dir_close(Handle& hd); extern LibError vfs_dir_next_ent(Handle hd, DirEnt* ent, const char* filter = 0); + +// called by EnumDirEnts for each entry in a directory (optionally those in +// its subdirectories as well), passing their complete path+name, the info +// that would be returned by vfs_next_dirent, and user-specified context. +// note: path and ent parameters are only valid during the callback. +typedef void (*DirEnumCB)(const char* path, const DirEnt* ent, void* context); + +enum DirEnumFlags +{ + VFS_DIR_RECURSIVE = 1 +}; + +// call for each entry matching (see vfs_next_dirent) in +// directory ; if flags & VFS_DIR_RECURSIVE, entries in +// subdirectories are also returned. +extern LibError vfs_dir_enum(const char* path, uint enum_flags, const char* filter, + DirEnumCB cb, void* context); + + // // file // diff --git a/source/lib/res/file/vfs_optimizer.cpp b/source/lib/res/file/vfs_optimizer.cpp index b1c1c51eb8..f9f8f66b74 100644 --- a/source/lib/res/file/vfs_optimizer.cpp +++ b/source/lib/res/file/vfs_optimizer.cpp @@ -28,8 +28,6 @@ #include "file_internal.h" -#include "ps/VFSUtil.h" - // enough for 64K unique files - ought to suffice. typedef u16 FileId; static const FileId NULL_ID = 0; @@ -159,7 +157,7 @@ public: // TODO: only add entries from mount points that have // VFS_MOUNT_ARCHIVE flag set (avoids adding screenshots etc.) - VFSUtil::EnumDirEnts("", VFSUtil::RECURSIVE, 0, EntCb, &file_nodes); + vfs_dir_enum("", VFS_DIR_RECURSIVE, 0, EntCb, &file_nodes); // MAX_IDS is a rather large limit on number of files, but must not // be exceeded (otherwise FileId overflows). diff --git a/source/lib/sysdep/cpu.cpp b/source/lib/sysdep/cpu.cpp index 345b4c5fea..120b9ba189 100644 --- a/source/lib/sysdep/cpu.cpp +++ b/source/lib/sysdep/cpu.cpp @@ -63,9 +63,6 @@ void cpu_init() // the result as required by ANSI C. however, FPU calculation // results were changed significantly, so it had to be disabled. //ia32_control87(IA32_RC_CHOP, IA32_MCW_RC); - - // If possible, hook up capability-sensitive assembler routines - ia32_hook_capabilities(); #endif // detects CPU clock frequency and capabilities, which are prerequisites diff --git a/source/lib/sysdep/ia32.cpp b/source/lib/sysdep/ia32.cpp index a908a98289..bc5e3699b1 100755 --- a/source/lib/sysdep/ia32.cpp +++ b/source/lib/sysdep/ia32.cpp @@ -32,12 +32,6 @@ #include "lib/sysdep/win/wtime.h" #endif -#define NO_COLOR - -#ifndef NO_COLOR -#include "graphics/Color.h" -#endif - #include #include @@ -684,30 +678,6 @@ LibError ia32_get_call_target(void* ret_addr, void** target) } -//----------------------------------------------------------------------------- - -#ifndef NO_COLOR -// Assembler-optimized function for color conversion -extern "C" { -u32 sse_ConvertRGBColorTo4ub(const RGBColor& src); -} -#endif - -void ia32_hook_capabilities() -{ -#ifndef NO_COLOR - if (ia32_cap(SSE)) - { - ConvertRGBColorTo4ub = sse_ConvertRGBColorTo4ub; - } - else - { - debug_printf("No SSE available. Slow fallback routines will be used.\n"); - } -#endif -} - - //---------------------------------------------------------------------------- // built-in self test //---------------------------------------------------------------------------- diff --git a/source/lib/sysdep/ia32.h b/source/lib/sysdep/ia32.h index a212e67730..02facc107f 100755 --- a/source/lib/sysdep/ia32.h +++ b/source/lib/sysdep/ia32.h @@ -113,7 +113,6 @@ extern bool ia32_cap(CpuCap cap); extern void ia32_get_cpu_info(void); -extern void ia32_hook_capabilities(void); //----------------------------------------------------------------------------- diff --git a/source/ps/GameSetup/GameSetup.cpp b/source/ps/GameSetup/GameSetup.cpp index bd6f38b3a5..3d0df68c45 100644 --- a/source/ps/GameSetup/GameSetup.cpp +++ b/source/ps/GameSetup/GameSetup.cpp @@ -693,6 +693,8 @@ static void InitRenderer() vp.m_Width=g_xres; vp.m_Height=g_yres; g_Renderer.SetViewport(vp); + + ColorActivateFastImpl(); } static void InitSDL() diff --git a/source/ps/Interact.cpp b/source/ps/Interact.cpp index 2cd949b511..43a6345dc6 100755 --- a/source/ps/Interact.cpp +++ b/source/ps/Interact.cpp @@ -882,7 +882,7 @@ static void LoadUnitUIThunk( const char* path, const DirEnt* UNUSED(ent), void* } int CSelectedEntities::loadUnitUITextures() { - THROW_ERR( VFSUtil::EnumDirEnts( "art/textures/ui/session/icons/", VFSUtil::RECURSIVE, + THROW_ERR( vfs_dir_enum( "art/textures/ui/session/icons/", VFS_DIR_RECURSIVE, NULL, LoadUnitUIThunk, &m_unitUITextures ) ); return 0; } diff --git a/source/ps/VFSUtil.cpp b/source/ps/VFSUtil.cpp index ef04d84529..2d6c728177 100755 --- a/source/ps/VFSUtil.cpp +++ b/source/ps/VFSUtil.cpp @@ -41,82 +41,3 @@ bool VFSUtil::FindFiles (const CStr& dirname, const char* filter, FileList& file } - -// call for each entry matching (see vfs_next_dirent) in -// directory ; if , entries in subdirectories are -// also returned. -// -// note: EnumDirEntsCB path and ent are only valid during the callback. -LibError VFSUtil::EnumDirEnts(const CStr start_path, int flags, const char* user_filter, - EnumDirEntsCB cb, void* context) -{ - debug_assert((flags & ~(RECURSIVE)) == 0); - const bool recursive = (flags & RECURSIVE) != 0; - - char filter_buf[VFS_MAX_PATH]; - const char* filter = user_filter; - bool want_dir = true; - if(user_filter) - { - if(user_filter[0] != '/') - want_dir = false; - - // we need subdirectories and the caller hasn't already requested them - if(recursive && !want_dir) - { - snprintf(filter_buf, sizeof(filter_buf), "/|%s", user_filter); - filter = filter_buf; - } - } - - - // note: FIFO queue instead of recursion is much more efficient - // (less stack usage; avoids seeks by reading all entries in a - // directory consecutively) - - std::queue dir_queue; - dir_queue.push(file_make_unique_fn_copy(start_path.c_str())); - - // for each directory: - do - { - // get current directory path from queue - // note: can't refer to the queue contents - those are invalidated - // as soon as a directory is pushed onto it. - PathPackage pp; - (void)pp_set_dir(&pp, dir_queue.front()); - dir_queue.pop(); - - Handle hdir = vfs_dir_open(pp.path); - if(hdir <= 0) - { - debug_warn("vfs_open_dir failed"); - continue; - } - - // for each entry (file, subdir) in directory: - DirEnt ent; - while(vfs_dir_next_ent(hdir, &ent, filter) == 0) - { - // build complete path (DirEnt only stores entry name) - (void)pp_append_file(&pp, ent.name); - const char* atom_path = file_make_unique_fn_copy(pp.path); - - if(DIRENT_IS_DIR(&ent)) - { - if(recursive) - dir_queue.push(atom_path); - - if(want_dir) - cb(atom_path, &ent, context); - } - else - cb(atom_path, &ent, context); - } - - vfs_dir_close(hdir); - } - while(!dir_queue.empty()); - - return ERR_OK; -} diff --git a/source/ps/VFSUtil.h b/source/ps/VFSUtil.h index 4056cb7e31..aea9fc7d30 100755 --- a/source/ps/VFSUtil.h +++ b/source/ps/VFSUtil.h @@ -13,23 +13,4 @@ typedef std::vector FileList; // On failure, logs an error and returns false. extern bool FindFiles(const CStr& dirname, const char* filter, FileList& files); - -// called by EnumDirEnts for each entry in a directory (optionally those in -// its subdirectories as well), passing their complete path+name, the info -// that would be returned by vfs_next_dirent, and user-specified context. -// note: path and ent parameters are only valid during the callback. -typedef void (*EnumDirEntsCB)(const char* path, const DirEnt* ent, - void* context); - -enum EnumDirEntsFlags -{ - RECURSIVE = 1 -}; - -// call for each entry matching (see vfs_next_dirent) in -// directory ; if flags & RECURSIVE, entries in subdirectories are -// also returned. -extern LibError EnumDirEnts(const CStr path, int flags, const char* filter, - EnumDirEntsCB cb, void* context); - } // namespace VFSUtil diff --git a/source/ps/scripting/JSInterface_VFS.cpp b/source/ps/scripting/JSInterface_VFS.cpp index e09bec0b6b..59e3255ebc 100644 --- a/source/ps/scripting/JSInterface_VFS.cpp +++ b/source/ps/scripting/JSInterface_VFS.cpp @@ -99,12 +99,12 @@ JSBool JSI_VFS::BuildFileList( JSContext* cx, JSObject* UNUSED(obj), uintN argc, if( !ToPrimitive( cx, argv[2], recursive ) ) return( JS_FALSE ); } - int flags = recursive? VFSUtil::RECURSIVE : 0; + int flags = recursive? VFS_DIR_RECURSIVE : 0; // build array in the callback function BuildFileListState state(cx); - VFSUtil::EnumDirEnts( path, flags, filter, BuildFileListCB, &state ); + vfs_dir_enum( path, flags, filter, BuildFileListCB, &state ); *rval = OBJECT_TO_JSVAL( state.filename_array ); return( JS_TRUE ); diff --git a/source/simulation/BaseEntityCollection.cpp b/source/simulation/BaseEntityCollection.cpp index 3836576e86..7028e6de4c 100755 --- a/source/simulation/BaseEntityCollection.cpp +++ b/source/simulation/BaseEntityCollection.cpp @@ -30,7 +30,7 @@ static void LoadFileThunk( const char* path, const DirEnt* UNUSED(ent), void* co int CBaseEntityCollection::loadTemplates() { // Load all files in entities/ and its subdirectories. - THROW_ERR( VFSUtil::EnumDirEnts( "entities/", VFSUtil::RECURSIVE, "*.xml", + THROW_ERR( vfs_dir_enum( "entities/", VFS_DIR_RECURSIVE, "*.xml", LoadFileThunk, this ) ); return 0; } diff --git a/source/simulation/BaseFormationCollection.cpp b/source/simulation/BaseFormationCollection.cpp index 64acd34444..f3ee6f4ec4 100644 --- a/source/simulation/BaseFormationCollection.cpp +++ b/source/simulation/BaseFormationCollection.cpp @@ -30,7 +30,7 @@ static void LoadFormationThunk( const char* path, const DirEnt* UNUSED(ent), voi int CBaseFormationCollection::loadTemplates() { // Load all files in entities/formations and subdirectories. - THROW_ERR( VFSUtil::EnumDirEnts( "entities/formations", VFSUtil::RECURSIVE, "*.xml", + THROW_ERR( vfs_dir_enum( "entities/formations", VFS_DIR_RECURSIVE, "*.xml", LoadFormationThunk, this ) ); return 0; }