From 2d86e3b7ff84841fa44502db1a74ab1f82b3e338 Mon Sep 17 00:00:00 2001
From: hgn <hgodden00@gmail.com>
Date: Wed, 18 Aug 2021 14:01:51 +0100
Subject: [PATCH] fixed instance loading forget to append basepath.. other path
 fixes (windows)

---
 csRadar.c  | 15 ++++------
 csRadar.h  |  5 ++--
 csrIO.h    | 82 +++++++++++++++++++++++++++++++++++++-----------------
 vfilesys.h |  7 ++---
 vmf.h      | 21 +++++++++++---
 5 files changed, 85 insertions(+), 45 deletions(-)

diff --git a/csRadar.c b/csRadar.c
index e3b5209..17f09a8 100644
--- a/csRadar.c
+++ b/csRadar.c
@@ -44,8 +44,6 @@ int main( int argc, char *argv[] )
 		if( (arg = csr_opt_arg( 'o' )) )
 		{
 			strcpy( api.output_path, arg );
-			csr_path_winunix( api.output_path );
-			
 			output_set = 1;
 		}
 		
@@ -151,17 +149,14 @@ int main( int argc, char *argv[] )
 			csr_stripext( api.output_path );
 		}
 		
-		char *base_name;
-		if( !(base_name = csr_findext( api.output_path, '/' ) ))
-		{
-			base_name = api.output_path;
-		}
-		
-		strcpy( api.vmf_name, base_name );
+		strcpy( api.vmf_name, csr_filename( api.output_path ) );
+		strcpy( api.vmf_folder, api.output_path );
+		csr_downlvl( api.vmf_folder );
 		
 		log_info( "output_path: '%s'\n", api.output_path );
 		log_info( "vmf_name: '%s'\n", api.vmf_name );
-
+		log_info( "vmf_folder: '%s'\n", api.vmf_folder );
+		
 		api.map = vmf_init( api.strings[0].str );
 		if( api.map )
 		{
diff --git a/csRadar.h b/csRadar.h
index 0415518..c54c24f 100644
--- a/csRadar.h
+++ b/csRadar.h
@@ -60,8 +60,9 @@ struct csr_api
 	float padding;
 	u32 resolution;
 	int write_txt;
-	char output_path[ 512 ];		// Full path eg. /home/harry/my_map.vmf
-	char vmf_name[ 128 ];			// Just the base name eg. my_map
+	char output_path[ 512 ];	// Full path to output eg. /home/harry/output
+	char vmf_name[ 128 ];		// Just the base name eg. my_map
+	char vmf_folder[ 512 ];		// Just the folder to the map eg. /home/harry/
 	EMSAA sampling_mode;
 	
 	float min_z;
diff --git a/csrIO.h b/csrIO.h
index 76bed7e..437a462 100644
--- a/csrIO.h
+++ b/csrIO.h
@@ -14,21 +14,30 @@ i64 fs_file_size( FILE *fileptr );
 // Path handling
 // -------------
 
-// Find file path extension, returns NULL if no ext (0x00)
+// Find file path extension, returns NULL if no ext (0x00) example: /test/file.jpg returns pointer to: jpg
 char *csr_findext( char *path, char const delim );
+char *csr_findsep( char *path ); // Same as above but operates on \ and /
 
 // gets rid of extension on string only left with (folder)+filename
 void csr_stripext( char *path );
 
 int csr_path_is_abs( char const *path );
 
-// Convert windows paths to unix.. sortof ( \something\\blahblah .. ) -> /something/blahblah/
-// Does not handle drive letters, idea is to increase windows compatibility will the other functions above
-void csr_path_winunix( char *path );
+// Remove one level (nop if can't) eg: /home/harry/test.file -> /home/harry/
+void csr_downlvl( char *path );
+
+// Get only the file name example: /test/file.jpg returns file.jpg
+char *csr_filename( char *path );
 
 // Implementation
 //=======================================================================================================================
 
+#ifdef _WIN32
+ #define CSR_FOLDER_CHAR '\\'
+#else
+ #define CSR_FOLDER_CHAR '/'
+#endif
+
 #ifdef CSR_EXECUTABLE
 
 i64 fs_file_size( FILE *fileptr )
@@ -127,12 +136,33 @@ char *csr_findext( char *path, char const delim )
 	return ptr;
 }
 
+// Find 'seperator'.. because folders can be / or \ on windows..
+char *csr_findsep( char *path )
+{
+	char *c, *ptr;
+
+	c = path;
+	ptr = NULL;
+	
+	while( *c )
+	{
+		if( *c == '/' || *c == '\\' )
+		{
+			ptr = c + 1;
+		}
+	
+		c ++;
+	}
+
+	return ptr;
+}
+
 void csr_stripext( char *path )
 {
 	char *point, *start;
 	
 	// Skip folders
-	if( !(start = csr_findext( path, '/' )) )
+	if( !(start = csr_findsep( path )) )
 	{
 		start = path;
 	}
@@ -146,29 +176,31 @@ void csr_stripext( char *path )
 	}
 }
 
-void csr_path_winunix( char *path )
+void csr_downlvl( char *path )
 {
-	char *idx, *wr;
-	wr = idx = path;
+	char *start_name, *c;
+
+	c = path;
+	while( *c )
+		c ++;
+	int len = c - path;
 	
-	while( *idx )
-	{
-		if( *idx == '\\' )
-		{
-			*idx = '/';
-		}
-		
-		if( idx > path )
-		{
-			if( *(idx -1) == '/' && *idx == '/') idx ++;
-		}
-		
-		*( wr ++ ) = *idx;
-		
-		idx ++;
-	}
+	if( len )
+		path[ len -1 ] = 0x00;
 	
-	*wr = 0x00;
+	if( (start_name = csr_findsep( path ) ))
+		*start_name = 0x00;
+	else
+		path[0] = 0x00;
+}
+
+char *csr_filename( char *path )
+{
+	char *base_name;
+	if( (base_name = csr_findsep( path ) ))
+		return base_name;
+		
+	return path;
 }
 
 int csr_path_is_abs( char const *path )
diff --git a/vfilesys.h b/vfilesys.h
index be7e319..fc4cec8 100644
--- a/vfilesys.h
+++ b/vfilesys.h
@@ -43,12 +43,11 @@ void fs_set_gameinfo( const char *path )
 	
 	// Set gamedir
 	strcpy( fs->gamedir, path );
-	csr_path_winunix( fs->gamedir );
-	*csr_findext( fs->gamedir, '/' ) = 0x00;
+	csr_downlvl( fs->gamedir );
 	
 	// Set exe dir
 	strcpy( fs->exedir, fs->gamedir );
-	strcat( fs->exedir, "../" );
+	csr_downlvl( fs->exedir );
 	
 	// Get all search paths from file
 	vdf_node *search_paths = vdf_next(vdf_next(vdf_next( info, "GameInfo", NULL ), "FileSystem", NULL ), "SearchPaths", NULL );
@@ -94,7 +93,7 @@ void fs_set_gameinfo( const char *path )
 	
 	if( !fs->vpk )
 	{
-		log_error( "Could not locate pak01_dir.vpk in %i searchpaths. Stock models will not load!", csr_sb_count( fs->searchpaths ) );
+		log_error( "Could not locate pak01_dir.vpk in %i searchpaths. Stock models will not load!\n", csr_sb_count( fs->searchpaths ) );
 	}
 
 	log_info( "fs_info:\n" );
diff --git a/vmf.h b/vmf.h
index 4fbe023..740a374 100644
--- a/vmf.h
+++ b/vmf.h
@@ -695,15 +695,24 @@ u32 vmf_init_subvmf( vmf_map *map, const char *subvmf );
 
 void vmf_load_all_instances( vmf_map *map, vdf_node *vmf )
 {
+	char nextvmf[ 512 ];
+	const char *base = kv_get( vmf, "csr_path", "" );
+
 	vdf_foreach( vmf, "entity", ent )
 	{
 		if( !strcmp( kv_get( ent, "classname", "" ), "func_instance" ))
 		{
 			// Entity is in use if file is specified, if not just ignore the entity.
-			const char *path = kv_get( ent, "file", "" );
-			if( strcmp( path, "" ) )
+			const char *path = kv_get( ent, "file", NULL );
+			
+			if( path )
 			{
-				if( (ent->user1 = vmf_init_subvmf( map, path )))
+				// Make relative path real
+				strcpy( nextvmf, base );
+				csr_downlvl( nextvmf );
+				strcat( nextvmf, path );
+				
+				if( (ent->user1 = vmf_init_subvmf( map, nextvmf )))
 				{
 					ent->user1 --;
 					ent->user = VMF_FLAG_IS_INSTANCE;
@@ -744,7 +753,9 @@ u32 vmf_init_subvmf( vmf_map *map, const char *subvmf )
 	strcpy( inst->name, subvmf );
 	
 	if( (inst->root = vdf_open_file( subvmf )) )
-	{		
+	{
+		vdf_kv_append( inst->root, "csr_path", subvmf );
+		
 		// Recursive load other instances
 		vmf_load_all_instances( map, inst->root );	
 		return id+1;
@@ -767,6 +778,8 @@ vmf_map *vmf_init( const char *path )
 		return NULL;
 	}
 	
+	vdf_kv_append( map->root, "csr_path", path );
+	
 	// Prepare instances
 	vmf_load_all_instances( map, map->root );
 	
-- 
2.25.1