Ejemplo n.º 1
0
/***************************************************************************
	Make a directory in write path and set a variable to point to it.
***************************************************************************/
static void make_dir(char *dest, const char *dirname, const char *subdir)
{
	strcpy(dest, dirname);
	if (subdir != NULL)
	{
		strcat(dest, "/");
		strcat(dest, subdir);
	}
	{
		size_t l = strlen(dest);

		if (dest[l - 1] != '/')
		{
			dest[l] = '/';
			dest[l + 1] = '\0';
		}
	}
	PHYSFS_mkdir(dest);
	if (!PHYSFS_mkdir(dest))
	{
		debug(LOG_FATAL, "Unable to create directory \"%s\" in write dir \"%s\"!",
		      dest, PHYSFS_getWriteDir());
		exit(EXIT_FAILURE);
	}
}
Ejemplo n.º 2
0
static bool readSurfaces( const char *filename, std::vector< RenderSurface > &surfaces )
{
	uint64_t hashedName = HashedString( 0, filename );
	char outfile[256];
	PHYSFS_mkdir( "static_models/" );
	sprintf( outfile, "static_models/%08x_%08x.sm", (uint32_t)(hashedName>>32), (uint32_t)(hashedName&0xffffffff) );
	PHYSFS_File *model = PHYSFS_openRead( outfile );
	if ( model )
	{
		unsigned int ver, numSurf;
		PHYSFS_readULE32( model, &ver );
		PHYSFS_readULE32( model, &numSurf );
		surfaces.resize( numSurf );
		for ( uint32_t i=0; i<surfaces.size(); i++ )
		{
			RenderSurface &surf = surfaces[i];
			PHYSFS_readCStr( model, surf.name );
			std::string mat;
			PHYSFS_readCStr( model, mat );
			surf.mat = materialManager()->Load( mat.c_str() );

			ModelGeometry *geom = new ModelGeometry;
			surf.geom = geom;
			PHYSFS_readSLE32( model, &geom->m_numIndices );
			PHYSFS_readSLE32( model, &geom->m_numVerts );
			geom->m_indices = new unsigned short[geom->m_numIndices];
			geom->m_verts = new ModelVert[geom->m_numVerts];
			PHYSFS_read( model, geom->m_indices, sizeof(uint16_t)*geom->m_numIndices, 1 );
			PHYSFS_read( model, geom->m_verts, sizeof(geom->m_verts[0])*geom->m_numVerts, 1 );
		}
		PHYSFS_close( model );
		return true;
	}
	return false;
}
Ejemplo n.º 3
0
void save_screen_shot(int automap_flag)
{
	static int savenum=0;
	char savename[13+sizeof(SCRNS_DIR)];
	unsigned char *buf;

	if (!GameArg.DbgGlReadPixelsOk){
		if (!automap_flag)
			HUD_init_message_literal(HM_DEFAULT, "glReadPixels not supported on your configuration");
		return;
	}

	stop_time();

	if (!PHYSFSX_exists(SCRNS_DIR,0))
		PHYSFS_mkdir(SCRNS_DIR); //try making directory

	do
	{
		sprintf(savename, "%sscrn%04d.tga",SCRNS_DIR, savenum++);
	} while (PHYSFSX_exists(savename,0));

	if (!automap_flag)
		HUD_init_message(HM_DEFAULT, "%s 'scrn%04d.tga'", TXT_DUMPING_SCREEN, savenum-1 );

#ifndef OGLES
	glReadBuffer(GL_FRONT);
#endif

	buf = d_malloc(grd_curscreen->sc_w*grd_curscreen->sc_h*3);
	write_bmp(savename,grd_curscreen->sc_w,grd_curscreen->sc_h,buf);
	d_free(buf);

	start_time();
}
Ejemplo n.º 4
0
bool Resources::mkdir(const char* directory) {
    if(!PHYSFS_mkdir(directory)) {
        PError << "couldn't create directory '" << directory << "': " << PHYSFS_getLastError() << endl;
        return PFalse;
    };
    return PTrue;
}
Ejemplo n.º 5
0
static void writeSurfaces( const char *filename, std::vector< RenderSurface > &surfaces )
{
	uint64_t hashedName = HashedString( 0, filename );
	char outfile[256];
	PHYSFS_mkdir( "static_models/" );
	sprintf( outfile, "static_models/%08x_%08x.sm", (uint32_t)(hashedName>>32), (uint32_t)(hashedName&0xffffffff) );
	PHYSFS_File *model = PHYSFS_openWrite( outfile );
	if ( model )
	{
		PHYSFS_writeULE32( model, 0x090 );
		PHYSFS_writeULE32( model, surfaces.size() );
		for ( uint32_t i=0; i<surfaces.size(); i++ )
		{
			RenderSurface const &surf = surfaces[i];
			PHYSFS_writeCStr( model, surf.name.c_str() );
			PHYSFS_writeCStr( model, surf.mat->Name() );
			const ModelGeometry *geom = surf.geom;
			PHYSFS_writeSLE32( model, geom->m_numIndices );
			PHYSFS_writeSLE32( model, geom->m_numVerts );
			PHYSFS_write( model, geom->m_indices, sizeof(uint16_t)*geom->m_numIndices, 1 );
			PHYSFS_write( model, geom->m_verts, sizeof(geom->m_verts[0])*geom->m_numVerts, 1 );
		}
		PHYSFS_close( model );
	}
}
Ejemplo n.º 6
0
bool ResourceManager::setupWriteDir(const std::string& appWriteDirName)
{
    std::string userDir = PHYSFS_getUserDir();
    std::string dirName;
#ifndef WIN32
    dirName = stdext::format(".%s", appWriteDirName);
#else
    dirName = appWriteDirName;
#endif
    std::string writeDir = userDir + dirName;

    if(!PHYSFS_setWriteDir(writeDir.c_str())) {
        if(!PHYSFS_setWriteDir(userDir.c_str())) {
            g_logger.error("User directory not found.");
            return false;
        }
        if(!PHYSFS_mkdir(dirName.c_str())) {
            g_logger.error("Cannot create directory for saving configurations.");
            return false;
        }
        if(!PHYSFS_setWriteDir(writeDir.c_str())) {
            g_logger.error("Unable to set write directory.");
            return false;
        }
    }
    addToSearchPath(writeDir, true);
    //g_logger.debug(stdext::format("Setup write dir %s", writeDir));
    return true;
}
Ejemplo n.º 7
0
AddonManager::AddonManager(const std::string& addon_directory,
                           std::vector<Config::Addon>& addon_config) :
  m_downloader(),
  m_addon_directory(addon_directory),
  m_repository_url("https://raw.githubusercontent.com/SuperTux/addons/master/index-0_5.nfo"),
  m_addon_config(addon_config),
  m_installed_addons(),
  m_repository_addons(),
  m_has_been_updated(false),
  m_transfer_status()
{
  if(!PHYSFS_mkdir(m_addon_directory.c_str()))
  {
    std::ostringstream msg;
    msg << "Couldn't create directory for addons '"
        << m_addon_directory << "': " << PHYSFS_getLastError();
    throw std::runtime_error(msg.str());
  }

  add_installed_addons();

  // FIXME: We should also restore the order here
  for(auto& addon : m_addon_config)
  {
    if (addon.enabled)
    {
      try
      {
        enable_addon(addon.id);
      }
      catch(const std::exception& err)
      {
        log_warning << "failed to enable addon from config: " << err.what() << std::endl;
      }
    }
  }

  if(PHYSFS_exists(ADDON_INFO_PATH))
  {
    try
    {
        m_repository_addons = parse_addon_infos(ADDON_INFO_PATH);
    }
    catch(const std::exception& err)
    {
        log_warning << "parsing repository.nfo failed: " << err.what() << std::endl;
    }
  }
  else
  {
    log_info << "repository.nfo doesn't exist, not loading" << std::endl;
  }

  if (!g_config->repository_url.empty() &&
      g_config->repository_url != m_repository_url)
  {
    m_repository_url = g_config->repository_url;
  }
}
Ejemplo n.º 8
0
bool CResourceManager::CreateDirectory(const std::string& directory)
{
    if (PHYSFS_isInit())
    {
        return PHYSFS_mkdir(CleanPath(directory).c_str());
    }
    return false;
}
Ejemplo n.º 9
0
 void Mkdir(std::string path) {
     if (!IsLoaded()) {
         Logger::begin("Filesystem", Logger::LogLevel_Error) << "FS not loaded" << Logger::end();
         assert(false);
         return;
     }
     PHYSFS_mkdir(path.c_str());
 }
Ejemplo n.º 10
0
void
vsFile::EnsureWriteDirectoryExists( const vsString &writeDirectoryName ) // static method
{
	if ( !DirectoryExists(writeDirectoryName) )
	{
		int mkdirResult = PHYSFS_mkdir( writeDirectoryName.c_str() );
		vsAssert( mkdirResult != 0, vsFormatString("Failed to create directory '%s%s%s': %s",
				PHYSFS_getWriteDir(), PHYSFS_getDirSeparator(), writeDirectoryName.c_str(), PHYSFS_getLastError()) );
	}
}
Ejemplo n.º 11
0
bool FileSystem::CreateDirectory(const Path & path)
{
	auto genericString = path.generic_string();
	int returnCode = PHYSFS_mkdir(genericString.c_str()) != 0;

	if (returnCode == 0)
	{
		GetContext().GetLogger()->log(LOG_LOG, "Failed to create directory, error: %s", PHYSFS_getLastError());
		//printf("Failed to create directory, error: %s\n", PHYSFS_getLastError());
	}

	return returnCode != 0;
}
Ejemplo n.º 12
0
/********************************
* EntityCompiler_ExtractRoutines
* count the anomunt of entities
@ data: int *
@ origdir:
@ fname:
*/
static void EntityCompiler_ExtractRoutines(void * data, const char *origdir, const char *fname)
{
	if ( g_str_has_suffix(fname, ".inc") && !g_str_has_prefix(fname, "private_") )
	{
		gchar * internal_file_path = g_strdup_printf("%s/%s", origdir, fname);
		gchar * content = NULL;

		PHYSFS_mkdir(origdir);
		PHYSFS_delete( internal_file_path );
		if ( Meg_file_get_contents(internal_file_path, &content, NULL, NULL) )
			Meg_file_set_contents(internal_file_path, content, -1, NULL);
	}
}
Ejemplo n.º 13
0
bool physfsDrive::MakeDir(const char * dir) {
	char newdir[CROSS_LEN];
	strcpy(newdir,basedir);
	strcat(newdir,dir);
	CROSS_FILENAME(newdir);
	dirCache.ExpandName(newdir);
	normalize(newdir,basedir);
	if (PHYSFS_mkdir(newdir)) {
		CROSS_FILENAME(newdir);
		dirCache.CacheOut(newdir,true);
		return true;
	}
	return false;
}
Ejemplo n.º 14
0
static int cmd_mkdir(char *args)
{
    if (*args == '\"')
    {
        args++;
        args[strlen(args) - 1] = '\0';
    } /* if */

    if (PHYSFS_mkdir(args))
        printf("Successful.\n");
    else
        printf("Failure. reason: %s.\n", PHYSFS_getLastError());

    return(1);
} /* cmd_mkdir */
Ejemplo n.º 15
0
AddonManager::AddonManager(const std::string& addon_directory,
                           std::vector<Config::Addon>& addon_config) :
  m_downloader(),
  m_addon_directory(addon_directory),
  m_repository_url("https://raw.githubusercontent.com/SuperTux/addons/master/index-0_4_0.nfo"),
  m_addon_config(addon_config),
  m_installed_addons(),
  m_repository_addons(),
  m_has_been_updated(false),
  m_transfer_status()
{
  PHYSFS_mkdir(m_addon_directory.c_str());

  add_installed_addons();

  // FIXME: We should also restore the order here
  for(auto& addon : m_addon_config)
  {
    if (addon.enabled)
    {
      try
      {
        enable_addon(addon.id);
      }
      catch(const std::exception& err)
      {
        log_warning << "failed to enable addon from config: " << err.what() << std::endl;
      }
    }
  }

  if(PHYSFS_exists(ADDON_INFO_PATH))
  {
    try
    {
        m_repository_addons = parse_addon_infos(ADDON_INFO_PATH);
    }
    catch(const std::exception& err)
    {
        log_warning << "parsing repository.nfo failed: " << err.what() << std::endl;
    }
  }
  else
  {
    log_info << "repository.nfo doesn't exist, not loading" << std::endl;
  }
}
Ejemplo n.º 16
0
bool physfsFile::prepareWrite() {
	const char *wdir = PHYSFS_getWriteDir();
	if (wdir == NULL) {
		LOG_MSG("PHYSFS could not fulfill write request: no write directory set.");
		return false;
	}
	//LOG_MSG("Goto write (%s at %i)",pname,PHYSFS_tell(fhandle));
	const char *fdir = PHYSFS_getRealDir(pname);
	PHYSFS_uint64 pos = PHYSFS_tell(fhandle);
	char *slash = strrchr(pname,'/');
	if (slash && slash != pname) {
		*slash = 0;
		PHYSFS_mkdir(pname);
		*slash = '/';
	}
	if (strcmp(fdir,wdir)) { /* we need COW */
		//LOG_MSG("COW",pname,PHYSFS_tell(fhandle));
		PHYSFS_file *whandle = PHYSFS_openWrite(pname);
		if (whandle == NULL) {
			LOG_MSG("PHYSFS copy-on-write failed: %s.",PHYSFS_getLastError());
			return false;
		}
		char buffer[65536];
		PHYSFS_sint64 size;
		PHYSFS_seek(fhandle, 0);
		while ((size = PHYSFS_read(fhandle,buffer,1,65536)) > 0) {
			if (PHYSFS_write(whandle,buffer,1,(PHYSFS_uint32)size) != size) {
				LOG_MSG("PHYSFS copy-on-write failed: %s.",PHYSFS_getLastError());
				PHYSFS_close(whandle);
				return false;
			}
		}
		PHYSFS_seek(whandle, pos);
		PHYSFS_close(fhandle);
		fhandle = whandle;
	} else { // megayuck - physfs on posix platforms uses O_APPEND. We illegally access the fd directly and clear that flag.
		//LOG_MSG("noCOW",pname,PHYSFS_tell(fhandle));
		PHYSFS_close(fhandle);
		fhandle = PHYSFS_openAppend(pname);
#ifndef WIN32
		fcntl(**(int**)fhandle->opaque,F_SETFL,0);
#endif
		PHYSFS_seek(fhandle, pos);
	}
	return true;
}
Ejemplo n.º 17
0
Archivo: luac.c Proyecto: jcubic/ToME
/*
 * Compiles src lua source to dest lua bytecode
 * Bytecode is quicker to load as it is preparsed and optimized.
 * This function does NOT understands ToME virtual paths they
 * need to be converted first, this is intentionnal
 */
s32b tome_compile_lua(char *src)
{
	char *split;
	char dest[2048];
	Proto *tf;
	PHYSFS_file *dump;

	/* Clear error state */
	PHYSFS_getLastError();

        /* A new empty lua state */
	compile_lua_state = lua_open(0);

	tf = load(src);

        /* If we dump we need to optimize */
	if (tome_compile_lua_optimizing) luaU_optchunk(tf);

	/* Dump to a file */

	if (tome_compile_lua_stripping) strip(tf);

	/* Make up the destination file .lua => .lb */
	strncpy(dest, src, 2048);
	dest[strlen(dest) - 2] = 'b';
	dest[strlen(dest) - 1] = '\0';

	/* Make sure distination exists */
	split = strrchr(dest, '/');
	*split = '\0';
	PHYSFS_mkdir(dest);
	*split = '/';

	dump = efopen(dest, "wb");
	if (dump == NULL)
		quit("Could not compile lua: error writting");
	PHYSFS_getLastError();
	luaU_dumpchunk_file(tf, dump);
	my_fclose(dump);

	/* Clean up */
/* For a strange reasons this totaly panics lua ... 	lua_close(compile_lua_state); */

	return 0;
}
Ejemplo n.º 18
0
// ----------------------------------------------------------------------------
void Editor::readConfigFile(IFileSystem* file_system)
{
    IXMLReader* xml_reader = file_system->createXMLReader(path(PHYSFS_getBaseDir())
                                                                    + "config.xml");

    if (!xml_reader)
    {
        path dir = PHYSFS_getUserDir();
        m_config_loc = dir + "/.stk-te";
        xml_reader = file_system->createXMLReader(m_config_loc + "/config.xml");
        if (!xml_reader)
        {
            PHYSFS_setWriteDir(dir.c_str());
            PHYSFS_mkdir(".stk-te");
            return;
        }
    }
    else m_config_loc = PHYSFS_getBaseDir();

    const stringw node_name(L"data_dir");
    const stringw res(L"res");
    const stringw exe(L"exe");
    while (xml_reader->read())
    {
        if (xml_reader->getNodeType() == EXN_ELEMENT)
        {
            if (res.equals_ignore_case(xml_reader->getNodeName()))
            {
                m_screen_size = dimension2du(
                    atol(((stringc)xml_reader->getAttributeValueSafe(L"x")).c_str()),
                    atol(((stringc)xml_reader->getAttributeValueSafe(L"y")).c_str()));
            }
            else  if (node_name.equals_ignore_case(xml_reader->getNodeName()))
            {
                m_data_loc = xml_reader->getAttributeValueSafe(L"path");
                m_icons_loc = m_data_loc + "editor/icons/";
            }
            else if (exe.equals_ignore_case(xml_reader->getNodeName()))
            {
                m_exe_loc = xml_reader->getAttributeValueSafe(L"path");
            }
        }
    }
    xml_reader->drop();
} // readConfigFile
Ejemplo n.º 19
0
// ----------------------------------------------------------------------------
void Editor::initDataLoc()
{
    IFileSystem* file_system = m_device->getFileSystem();
    if (!file_system->addFileArchive((m_data_loc + "editor/xml").c_str(),
        false, false, EFAT_FOLDER, "", &m_xml_dir))
    {
        std::cerr << "Bad news: i couldn't find the xml directory.\n";
        std::cerr << "Maybe the whole editor folder is missing? :(\n";
        exit(-1);
    }
    file_system->addFileArchive(m_data_loc, false, false, EFAT_FOLDER);
    m_valid_data_dir = true;

    initAfterDataDirKnown();

    path p = m_data_loc.c_str();
    p += "editor/maps";
    m_maps_path = new c8[p.size() + 1];
    strcpy(m_maps_path, p.c_str());

    if (!PHYSFS_exists(p.c_str()))
    {
        std::cerr << "Warning: maps directory doesn't exist. Creating...\n";
        PHYSFS_setWriteDir(m_data_loc.c_str());
        PHYSFS_mkdir("editor/maps");
    }

    p = m_data_loc.c_str();
    p += "music";
    m_music_loc = new c8[p.size() + 1];
    strcpy(m_music_loc, p.c_str());

    m_track_dir = m_data_loc.c_str();
    m_track_dir += "tracks/";

    file_system->changeWorkingDirectoryTo(m_def_wd);

    m_tex_sel = TexSel::getTexSel();
    m_toolbox = ToolBox::getToolBox();

    file_system->addFileArchive((m_data_loc + "editor").c_str(),
        false, false, EFAT_FOLDER);

} // setDataLoc
Ejemplo n.º 20
0
void
VideoSystem::do_take_screenshot()
{
  SDLSurfacePtr surface = make_screenshot();
  if (!surface) {
    log_warning << "Creating the screenshot has failed" << std::endl;
    return;
  }

  const std::string screenshots_dir = "/screenshots";
  if (!PHYSFS_exists(screenshots_dir.c_str())) {
    if (!PHYSFS_mkdir(screenshots_dir.c_str())) {
      log_warning << "Creating '" << screenshots_dir << "' failed" << std::endl;
      return;
    }
  }

  auto find_filename = [&]() -> boost::optional<std::string>
    {
      for (int num = 0; num < 1000000; ++num)
      {
        std::ostringstream oss;
        oss << "screenshot" << std::setw(6) << std::setfill('0') << num << ".png";
        const std::string screenshot_filename = FileSystem::join(screenshots_dir, oss.str());
        if (!PHYSFS_exists(screenshot_filename.c_str())) {
          return screenshot_filename;
        }
      }
      return boost::none;
    };

  auto filename = find_filename();
  if (!filename)
  {
    log_info << "Failed to find filename to save screenshot" << std::endl;
  }
  else
  {
    if (SDLSurface::save_png(*surface, *filename)) {
      log_info << "Wrote screenshot to \"" << *filename << "\"" << std::endl;
    }
  }
}
Ejemplo n.º 21
0
/**Initialize the PhysFS system
 * \return Nonzero on success. */
int Filesystem::Init( const char* argv0 ) {
	int retval;
	if ( (retval = PHYSFS_init(argv0)) == 0 )
		LogMsg(ERR,"Error initializing PhysicsFS. Reason: %s\n",PHYSFS_getLastError());

	if ( (retval = PHYSFS_setSaneConfig("games", "epiar", NULL, 0, 0 ) ) == 0 )
		LogMsg(ERR,"Could not set sane paths for PhysFS: %s\n", PHYSFS_getLastError());

	// Set up userDir
	if ( (retval = PHYSFS_mkdir("Resources/Definitions/") ) == 0 )
		LogMsg(ERR,"Could not set up the user dir: %s\n", PHYSFS_getLastError());

#ifdef DATADIR
	// If using autotools, include this prefix to help binary find data files for cases where 'make install' was used
	if ( (retval = PHYSFS_addToSearchPath(DATADIR, 1)) == 0 )
		LogMsg(INFO,"Not using DATADIR directory due to error, probably 'make install' not run yet. Reason: %s\n", PHYSFS_getLastError());
#endif /* DATADIR */
	
	return retval;
}
Ejemplo n.º 22
0
void probeDir(const std::string& dirname)
{
    if (PHYSFS_isDirectory(dirname.c_str()) == 0)
    {
        if (PHYSFS_exists(dirname.c_str()))
        {
            PHYSFS_delete(dirname.c_str());
        }
        if (PHYSFS_mkdir(dirname.c_str()))
        {
            std::cout << PHYSFS_getWriteDir() <<
                dirname << " created" << std::endl;
        }
        else
        {
            std::cout << "Warning: Creation of" << 
                PHYSFS_getWriteDir() << dirname <<
                " failed!" << std::endl;
        }
    }
}
Ejemplo n.º 23
0
static void levTestLoad(const char* level)
{
	static char savegameName[80];
	bool retval;

	retval = levLoadData(level, NULL, GTYPE_SCENARIO_START);
	ASSERT(retval, "levLoadData failed selftest");
	ASSERT(checkResearchStats(), "checkResearchStats failed selftest");
	ASSERT(checkStructureStats(), "checkStructureStats failed selftest");
	fprintf(stdout, "\t\tLoaded: %s\n", level);
	strcpy(savegameName, "selftest/");
	PHYSFS_mkdir(savegameName);
	strcat(savegameName, level);
	strcat(savegameName, ".gam");
	retval = saveGame(savegameName, GTYPE_SAVE_START);
	ASSERT(retval, "saveGame failed selftest");
	strcpy(savegameName, "selftest/");	// we need to recreate string, because saveGame clobbered it
	strcat(savegameName, level);
	strcat(savegameName, ".gam");
	retval = levReleaseAll();
	assert(retval == true);
	fprintf(stdout, "\t\tSaved: %s\n", savegameName);
}
Ejemplo n.º 24
0
bool physfsDrive::FileCreate(DOS_File * * file,const char * name,Bit16u attributes) {
	char newname[CROSS_LEN];
	strcpy(newname,basedir);
	strcat(newname,name);
	CROSS_FILENAME(newname);
	dirCache.ExpandName(newname);
	normalize(newname,basedir);

	/* Test if file exists, don't add to dirCache then */
	bool existing_file=PHYSFS_exists(newname);
	
	char *slash = strrchr(newname,'/');
	if (slash && slash != newname) {
		*slash = 0;
		if (!PHYSFS_isDirectory(newname)) return false;
		PHYSFS_mkdir(newname);
		*slash = '/';
	}

	PHYSFS_file * hand=PHYSFS_openWrite(newname);
	if (!hand){
		LOG_MSG("Warning: file creation failed: %s (%s)",newname,PHYSFS_getLastError());
		return false;
	}

	/* Make the 16 bit device information */
	*file=new physfsFile(name,hand,0x202,newname,true);
	(*file)->flags=OPEN_READWRITE;
	if(!existing_file) {
		strcpy(newname,basedir);
		strcat(newname,name);
		CROSS_FILENAME(newname);
		dirCache.AddEntry(newname, true);
	}
	return true;
}
Ejemplo n.º 25
0
bool FileSystem::mkdir(const std::string& dirname)
{
	return PHYSFS_mkdir(dirname.c_str());
}
Ejemplo n.º 26
0
static void getPlatformUserDir(char * const tmpstr, size_t const size)
{
#if defined(WZ_OS_WIN)
//  When WZ_PORTABLE is passed, that means we want the config directory at the same location as the program file
	DWORD dwRet;
	wchar_t tmpWStr[MAX_PATH];
#ifndef WZ_PORTABLE
	if ( SUCCEEDED( SHGetFolderPathW( NULL, CSIDL_PERSONAL|CSIDL_FLAG_CREATE, NULL, SHGFP_TYPE_CURRENT, tmpWStr ) ) )
	{
#else
	if (dwRet = GetCurrentDirectoryW(MAX_PATH, tmpWStr))
	{
		if(dwRet > MAX_PATH)
		{
			debug(LOG_FATAL, "Buffer exceeds maximum path to create directory. Exiting.");
			exit(1);
		}
#endif
		if (WideCharToMultiByte(CP_UTF8, 0, tmpWStr, -1, tmpstr, size, NULL, NULL) == 0)
		{
			debug(LOG_FATAL, "Config directory encoding conversion error.");
			exit(1);
		}
		strlcat(tmpstr, PHYSFS_getDirSeparator(), size);
	}
	else
#elif defined(WZ_OS_MAC)
	FSRef fsref;
	OSErr error = FSFindFolder(kUserDomain, kApplicationSupportFolderType, false, &fsref);
	if (!error)
		error = FSRefMakePath(&fsref, (UInt8 *) tmpstr, size);
	if (!error)
		strlcat(tmpstr, PHYSFS_getDirSeparator(), size);
	else
#endif
	if (PHYSFS_getUserDir())
	{
		strlcpy(tmpstr, PHYSFS_getUserDir(), size); // Use PhysFS supplied UserDir (As fallback on Windows / Mac, default on Linux)
	}
	// If PhysicsFS fails (might happen if environment variable HOME is unset or wrong) then use the current working directory
	else if (getCurrentDir(tmpstr, size))
	{
		strlcat(tmpstr, PHYSFS_getDirSeparator(), size);
	}
	else
	{
		debug(LOG_FATAL, "Can't get UserDir?");
		abort();
	}
}


static void initialize_ConfigDir(void)
{
	char tmpstr[PATH_MAX] = { '\0' };

	if (strlen(configdir) == 0)
	{
		getPlatformUserDir(tmpstr, sizeof(tmpstr));

		if (!PHYSFS_setWriteDir(tmpstr)) // Workaround for PhysFS not creating the writedir as expected.
		{
			debug(LOG_FATAL, "Error setting write directory to \"%s\": %s",
			      tmpstr, PHYSFS_getLastError());
			exit(1);
		}

		if (!PHYSFS_mkdir(WZ_WRITEDIR)) // s.a.
		{
			debug(LOG_FATAL, "Error creating directory \"%s\": %s",
			      WZ_WRITEDIR, PHYSFS_getLastError());
			exit(1);
		}

		// Append the Warzone subdir
		sstrcat(tmpstr, WZ_WRITEDIR);
		sstrcat(tmpstr, PHYSFS_getDirSeparator());

		if (!PHYSFS_setWriteDir(tmpstr))
		{
			debug( LOG_FATAL, "Error setting write directory to \"%s\": %s",
			tmpstr, PHYSFS_getLastError() );
			exit(1);
		}
	}
	else
	{
		sstrcpy(tmpstr, configdir);

		// Make sure that we have a directory separator at the end of the string
		if (tmpstr[strlen(tmpstr) - 1] != PHYSFS_getDirSeparator()[0])
			sstrcat(tmpstr, PHYSFS_getDirSeparator());

		debug(LOG_WZ, "Using custom configuration directory: %s", tmpstr);

		if (!PHYSFS_setWriteDir(tmpstr)) // Workaround for PhysFS not creating the writedir as expected.
		{
			debug(LOG_FATAL, "Error setting write directory to \"%s\": %s",
			      tmpstr, PHYSFS_getLastError());
			exit(1);
		}

		// NOTE: This is currently only used for mingw builds for now.
#if defined (WZ_CC_MINGW)
		if (!OverrideRPTDirectory(tmpstr))
		{
			// since it failed, we just use our default path, and not the user supplied one.
			debug(LOG_ERROR, "Error setting exception hanlder to use directory %s", tmpstr);
		}
#endif
	}

	// User's home dir first so we allways see what we write
	PHYSFS_addToSearchPath( PHYSFS_getWriteDir(), PHYSFS_PREPEND );

	PHYSFS_permitSymbolicLinks(1);

	debug(LOG_WZ, "Write dir: %s", PHYSFS_getWriteDir());
	debug(LOG_WZ, "Base dir: %s", PHYSFS_getBaseDir());
}
Ejemplo n.º 27
0
int realmain(int argc, char *argv[])
{
	// The libcrypto startup stuff... May or may not actually be needed for anything at all.
	ERR_load_crypto_strings();  // This is needed for descriptive error messages.
	OpenSSL_add_all_algorithms();  // Don't actually use the EVP functions, so probably not needed.
	OPENSSL_config(nullptr);  // What does this actually do?
#ifdef WZ_OS_WIN
	RAND_screen();  // Uses a screenshot as a random seed, on systems lacking /dev/random.
#endif

	wzMain(argc, argv);
	int utfargc = argc;
	const char** utfargv = (const char**)argv;

#ifdef WZ_OS_MAC
	cocoaInit();
#endif

	debug_init();
	debug_register_callback( debug_callback_stderr, NULL, NULL, NULL );
#if defined(WZ_OS_WIN) && defined(DEBUG_INSANE)
	debug_register_callback( debug_callback_win32debug, NULL, NULL, NULL );
#endif // WZ_OS_WIN && DEBUG_INSANE

	// *****
	// NOTE: Try *NOT* to use debug() output routines without some other method of informing the user.  All this output is sent to /dev/nul at this point on some platforms!
	// *****
	if (!getUTF8CmdLine(&utfargc, &utfargv))
	{
		return EXIT_FAILURE;
	}
	QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8"));	// make Qt treat all C strings in Warzone as UTF-8

	setupExceptionHandler(utfargc, utfargv, version_getFormattedVersionString());

	/*** Initialize PhysicsFS ***/
	initialize_PhysicsFS(utfargv[0]);

	/*** Initialize translations ***/
	initI18n();

	// find early boot info
	if (!ParseCommandLineEarly(utfargc, utfargv))
	{
		return EXIT_FAILURE;
	}

	/* Initialize the write/config directory for PhysicsFS.
	 * This needs to be done __after__ the early commandline parsing,
	 * because the user might tell us to use an alternative configuration
	 * directory.
	 */
	initialize_ConfigDir();

	/*** Initialize directory structure ***/
	make_dir(ScreenDumpPath, "screenshots", NULL);
	make_dir(SaveGamePath, "savegames", NULL);
	PHYSFS_mkdir("savegames/campaign");
	PHYSFS_mkdir("savegames/skirmish");
	make_dir(MultiCustomMapsPath, "maps", NULL); // MUST have this to prevent crashes when getting map
	PHYSFS_mkdir("music");
	PHYSFS_mkdir("logs");		// a place to hold our netplay, mingw crash reports & WZ logs
	PHYSFS_mkdir("userdata");	// a place to store per-mod data user generated data
	memset(rulesettag, 0, sizeof(rulesettag)); // tag to add to userdata to find user generated stuff
	make_dir(MultiPlayersPath, "multiplay", NULL);
	make_dir(MultiPlayersPath, "multiplay", "players");

	if (!customDebugfile)
	{
		// there was no custom debug file specified  (--debug-file=blah)
		// so we use our write directory to store our logs.
		time_t aclock;
		struct tm *newtime;
		char buf[PATH_MAX];

		time( &aclock );					// Get time in seconds
		newtime = localtime( &aclock );		// Convert time to struct
		// Note: We are using fopen(), and not physfs routines to open the file
		// log name is logs/(or \)WZlog-MMDD_HHMMSS.txt
		snprintf(buf, sizeof(buf), "%slogs%sWZlog-%02d%02d_%02d%02d%02d.txt", PHYSFS_getWriteDir(), PHYSFS_getDirSeparator(),
			newtime->tm_mon + 1, newtime->tm_mday, newtime->tm_hour, newtime->tm_min, newtime->tm_sec );
		debug_register_callback( debug_callback_file, debug_callback_file_init, debug_callback_file_exit, buf );

		// FIXME: Change this to LOG_WZ on next release
		debug(LOG_INFO, "Using %s debug file", buf);
	}

	// NOTE: it is now safe to use debug() calls to make sure output gets captured.
	check_Physfs();
	debug(LOG_WZ, "Warzone 2100 - %s", version_getFormattedVersionString());
	debug(LOG_WZ, "Using language: %s", getLanguage());
	debug(LOG_WZ, "Backend: %s", BACKEND);
	debug(LOG_MEMORY, "sizeof: SIMPLE_OBJECT=%ld, BASE_OBJECT=%ld, DROID=%ld, STRUCTURE=%ld, FEATURE=%ld, PROJECTILE=%ld",
	      (long)sizeof(SIMPLE_OBJECT), (long)sizeof(BASE_OBJECT), (long)sizeof(DROID), (long)sizeof(STRUCTURE), (long)sizeof(FEATURE), (long)sizeof(PROJECTILE));


	/* Put in the writedir root */
	sstrcpy(KeyMapPath, "keymap.map");

	// initialise all the command line states
	war_SetDefaultStates();

	debug(LOG_MAIN, "initializing");

	PhysicsEngineHandler engine;	// register abstract physfs filesystem

	loadConfig();

	// parse the command line
	if (!ParseCommandLine(utfargc, utfargv))
	{
		return EXIT_FAILURE;
	}

	// Save new (commandline) settings
	saveConfig();

	// Find out where to find the data
	scanDataDirs();

	// Now we check the mods to see if they exist or not (specified on the command line)
	// They are all capped at 100 mods max(see clparse.c)
	// FIX ME: I know this is a bit hackish, but better than nothing for now?
	{
		char *modname;
		char modtocheck[256];
		int i = 0;
		int result = 0;

		// check global mods
		for(i=0; i < 100; i++)
		{
			modname = global_mods[i];
			if (modname == NULL)
			{
				break;
			}
			ssprintf(modtocheck, "mods/global/%s", modname);
			result = PHYSFS_exists(modtocheck);
			result |= PHYSFS_isDirectory(modtocheck);
			if (!result)
			{
				debug(LOG_ERROR, "The (global) mod (%s) you have specified doesn't exist!", modname);
			}
			else
			{
				info("(global) mod (%s) is enabled", modname);
			}
		}
		// check campaign mods
		for(i=0; i < 100; i++)
		{
			modname = campaign_mods[i];
			if (modname == NULL)
			{
				break;
			}
			ssprintf(modtocheck, "mods/campaign/%s", modname);
			result = PHYSFS_exists(modtocheck);
			result |= PHYSFS_isDirectory(modtocheck);
			if (!result)
			{
				debug(LOG_ERROR, "The mod_ca (%s) you have specified doesn't exist!", modname);
			}
			else
			{
				info("mod_ca (%s) is enabled", modname);
			}
		}
		// check multiplay mods
		for(i=0; i < 100; i++)
		{
			modname = multiplay_mods[i];
			if (modname == NULL)
			{
				break;
			}
			ssprintf(modtocheck, "mods/multiplay/%s", modname);
			result = PHYSFS_exists(modtocheck);
			result |= PHYSFS_isDirectory(modtocheck);
			if (!result)
			{
				debug(LOG_ERROR, "The mod_mp (%s) you have specified doesn't exist!", modname);
			}
			else
			{
				info("mod_mp (%s) is enabled", modname);
			}
		}
	}

	if (!wzMain2(war_getFSAA(), war_getFullscreen(), war_GetVsync()))
	{
		return EXIT_FAILURE;
	}
	int w = pie_GetVideoBufferWidth();
	int h = pie_GetVideoBufferHeight();

	char buf[256];
	ssprintf(buf, "Video Mode %d x %d (%s)", w, h, war_getFullscreen() ? "fullscreen" : "window");
	addDumpInfo(buf);

	debug(LOG_MAIN, "Final initialization");
	if (!frameInitialise())
	{
		return EXIT_FAILURE;
	}
	if (!screenInitialise())
	{
		return EXIT_FAILURE;
	}
	if (!pie_LoadShaders())
	{
		return EXIT_FAILURE;
	}
	war_SetWidth(pie_GetVideoBufferWidth());
	war_SetHeight(pie_GetVideoBufferHeight());

	pie_SetFogStatus(false);
	pie_ScreenFlip(CLEAR_BLACK);

	pal_Init();

	pie_LoadBackDrop(SCREEN_RANDOMBDROP);
	pie_SetFogStatus(false);
	pie_ScreenFlip(CLEAR_BLACK);

	if (!systemInitialise())
	{
		return EXIT_FAILURE;
	}

	//set all the pause states to false
	setAllPauseStates(false);

	// Copy this info to be used by the crash handler for the dump file
	ssprintf(buf,"Using Backend: %s", BACKEND);
	addDumpInfo(buf);
	ssprintf(buf,"Using language: %s", getLanguageName());
	addDumpInfo(buf);

	// Do the game mode specific initialisation.
	switch(GetGameMode())
	{
		case GS_TITLE_SCREEN:
			startTitleLoop();
			break;
		case GS_SAVEGAMELOAD:
			initSaveGameLoad();
			break;
		case GS_NORMAL:
			startGameLoop();
			break;
		default:
			debug(LOG_ERROR, "Weirdy game status, I'm afraid!!");
			break;
	}

#if defined(WZ_CC_MSVC) && defined(DEBUG)
	debug_MEMSTATS();
#endif
	debug(LOG_MAIN, "Entering main loop");
	wzMain3();
	saveConfig();
	systemShutdown();
#ifdef WZ_OS_WIN	// clean up the memory allocated for the command line conversion
	for (int i=0; i<argc; i++)
	{
		const char*** const utfargvF = &utfargv;
		free((void *)(*utfargvF)[i]);
	}
	free(utfargv);
#endif
	wzShutdown();
	debug(LOG_MAIN, "Completed shutting down Warzone 2100");
	return EXIT_SUCCESS;
}
Ejemplo n.º 28
0
//****************************************************************************************
// Challenge menu
//*****************************************************************************************
bool addChallenges()
{
    char			sPath[PATH_MAX];
    const char *sSearchPath	= "challenges";
    UDWORD			slotCount;
    static char		sSlotCaps[totalslots][totalslotspace];
    static char		sSlotTips[totalslots][totalslotspace];
    static char		sSlotFile[totalslots][totalslotspace];
    char **i, **files;

    (void) PHYSFS_mkdir(sSearchPath); // just in case

    psRequestScreen = widgCreateScreen(); // init the screen
    widgSetTipFont(psRequestScreen, font_regular);

    /* add a form to place the tabbed form on */
    W_FORMINIT sFormInit;
    sFormInit.formID = 0;				//this adds the blue background, and the "box" behind the buttons -Q
    sFormInit.id = CHALLENGE_FORM;
    sFormInit.style = WFORM_PLAIN;
    sFormInit.x = (SWORD) CHALLENGE_X;
    sFormInit.y = (SWORD) CHALLENGE_Y;
    sFormInit.width = CHALLENGE_W;
    // we need the form to be long enough for all resolutions, so we take the total number of items * height
    // and * the gaps, add the banner, and finally, the fudge factor ;)
    sFormInit.height = (slotsInColumn * CHALLENGE_ENTRY_H + CHALLENGE_HGAP * slotsInColumn) + CHALLENGE_BANNER_DEPTH + 20;
    sFormInit.disableChildren = true;
    sFormInit.pDisplay = intOpenPlainForm;
    widgAddForm(psRequestScreen, &sFormInit);

    // Add Banner
    sFormInit.formID = CHALLENGE_FORM;
    sFormInit.id = CHALLENGE_BANNER;
    sFormInit.x = CHALLENGE_HGAP;
    sFormInit.y = CHALLENGE_VGAP;
    sFormInit.width = CHALLENGE_W - (2 * CHALLENGE_HGAP);
    sFormInit.height = CHALLENGE_BANNER_DEPTH;
    sFormInit.disableChildren = false;
    sFormInit.pDisplay = displayLoadBanner;
    sFormInit.UserData = 0;
    widgAddForm(psRequestScreen, &sFormInit);

    // Add Banner Label
    W_LABINIT sLabInit;
    sLabInit.formID		= CHALLENGE_BANNER;
    sLabInit.id		= CHALLENGE_LABEL;
    sLabInit.style		= WLAB_ALIGNCENTRE;
    sLabInit.x		= 0;
    sLabInit.y		= 3;
    sLabInit.width		= CHALLENGE_W - (2 * CHALLENGE_HGAP);	//CHALLENGE_W;
    sLabInit.height		= CHALLENGE_BANNER_DEPTH;		//This looks right -Q
    sLabInit.pText		= "Challenge";
    widgAddLabel(psRequestScreen, &sLabInit);

    // add cancel.
    W_BUTINIT sButInit;
    sButInit.formID = CHALLENGE_BANNER;
    sButInit.x = 8;
    sButInit.y = 8;
    sButInit.width		= iV_GetImageWidth(IntImages, IMAGE_NRUTER);
    sButInit.height		= iV_GetImageHeight(IntImages, IMAGE_NRUTER);
    sButInit.UserData	= PACKDWORD_TRI(0, IMAGE_NRUTER , IMAGE_NRUTER);

    sButInit.id = CHALLENGE_CANCEL;
    sButInit.pTip = _("Close");
    sButInit.pDisplay = intDisplayImageHilight;
    widgAddButton(psRequestScreen, &sButInit);

    // add slots
    sButInit = W_BUTINIT();
    sButInit.formID		= CHALLENGE_FORM;
    sButInit.width		= CHALLENGE_ENTRY_W;
    sButInit.height		= CHALLENGE_ENTRY_H;
    sButInit.pDisplay	= displayLoadSlot;

    for (slotCount = 0; slotCount < totalslots; slotCount++)
    {
        sButInit.id		= slotCount + CHALLENGE_ENTRY_START;

        if (slotCount < slotsInColumn)
        {
            sButInit.x	= 22 + CHALLENGE_HGAP;
            sButInit.y	= (SWORD)((CHALLENGE_BANNER_DEPTH + (2 * CHALLENGE_VGAP)) + (
                                      slotCount * (CHALLENGE_VGAP + CHALLENGE_ENTRY_H)));
        }
        else if (slotCount >= slotsInColumn && (slotCount < (slotsInColumn *2)))
        {
            sButInit.x	= 22 + (2 * CHALLENGE_HGAP + CHALLENGE_ENTRY_W);
            sButInit.y	= (SWORD)((CHALLENGE_BANNER_DEPTH + (2 * CHALLENGE_VGAP)) + (
                                      (slotCount % slotsInColumn) * (CHALLENGE_VGAP + CHALLENGE_ENTRY_H)));
        }
        else
        {
            sButInit.x	= 22 + (3 * CHALLENGE_HGAP + (2 * CHALLENGE_ENTRY_W));
            sButInit.y	= (SWORD)((CHALLENGE_BANNER_DEPTH + (2 * CHALLENGE_VGAP)) + (
                                      (slotCount % slotsInColumn) * (CHALLENGE_VGAP + CHALLENGE_ENTRY_H)));
        }
        widgAddButton(psRequestScreen, &sButInit);
    }

    // fill slots.
    slotCount = 0;

    sstrcpy(sPath, sSearchPath);
    sstrcat(sPath, "/*.ini");

    debug(LOG_SAVE, "Searching \"%s\" for challenges", sPath);

    // add challenges to buttons
    files = PHYSFS_enumerateFiles(sSearchPath);
    for (i = files; *i != NULL; ++i)
    {
        W_BUTTON *button;
        char description[totalslotspace];
        char highscore[totalslotspace];
        const char *name, *difficulty, *map, *givendescription;
        inifile *inif;

        // See if this filename contains the extension we're looking for
        if (!strstr(*i, ".ini"))
        {
            // If it doesn't, move on to the next filename
            continue;
        }

        /* First grab any high score associated with this challenge */
        inif = inifile_load(CHALLENGE_SCORES);
        sstrcpy(sPath, *i);
        sPath[strlen(sPath) - 4] = '\0';	// remove .ini
        sstrcpy(highscore, "no score");
        if (inif)
        {
            char key[64];
            bool victory;
            int seconds;

            ssprintf(key, "%s:Player", sPath);
            name = inifile_get(inif, key, "NO NAME");
            ssprintf(key, "%s:Victory", sPath);
            victory = inifile_get_as_bool(inif, key, false);
            ssprintf(key, "%s:Seconds", sPath);
            seconds = inifile_get_as_int(inif, key, -1);
            if (seconds > 0)
            {
                getAsciiTime(key, seconds * GAME_TICKS_PER_SEC);
                ssprintf(highscore, "%s by %s (%s)", key, name, victory ? "Victory" : "Survived");
            }
            inifile_delete(inif);
        }

        ssprintf(sPath, "%s/%s", sSearchPath, *i);
        inif = inifile_load(sPath);
        inifile_set_current_section(inif, "challenge");
        if (!inif)
        {
            debug(LOG_ERROR, "Could not open \"%s\"", sPath);
            continue;
        }
        name = inifile_get(inif, "Name", "BAD NAME");
        map = inifile_get(inif, "Map", "BAD MAP");
        difficulty = inifile_get(inif, "difficulty", "BAD DIFFICULTY");
        givendescription = inifile_get(inif, "description", "");
        ssprintf(description, "%s, %s, %s. %s", map, difficulty, highscore, givendescription);

        button = (W_BUTTON*)widgGetFromID(psRequestScreen, CHALLENGE_ENTRY_START + slotCount);

        debug(LOG_SAVE, "We found [%s]", *i);

        /* Set the button-text */
        sstrcpy(sSlotCaps[slotCount], name);		// store it!
        sstrcpy(sSlotTips[slotCount], description);	// store it, too!
        sstrcpy(sSlotFile[slotCount], sPath);		// store filename
        inifile_delete(inif);

        /* Add button */
        button->pTip = sSlotTips[slotCount];
        button->pText = sSlotCaps[slotCount];
        button->pUserData = (void *)sSlotFile[slotCount];
        slotCount++;		// go to next button...
        if (slotCount == totalslots)
        {
            break;
        }
    }
    PHYSFS_freeList(files);

    challengesUp = true;

    return true;
}
Ejemplo n.º 29
0
 bool mkdir(const char *const dirname)
 {
     return PHYSFS_mkdir(dirname);
 }
Ejemplo n.º 30
0
// Initialise PhysicsFS, set up basic search paths and add arguments from .ini file.
// The .ini file can be in either the user directory or the same directory as the program.
// The user directory is searched first.
void PHYSFSX_init(int argc, char *argv[])
{
#if defined(__unix__)
	const char *path = NULL;
#endif
#ifdef macintosh	// Mac OS 9
	char base_dir[PATH_MAX];
	int bundle = 0;
#else
#define base_dir PHYSFS_getBaseDir()
#endif
	
	PHYSFS_init(argv[0]);
	atexit(PHYSFSX_deinit);
	PHYSFS_permitSymbolicLinks(1);
	
#ifdef macintosh
	strcpy(base_dir, PHYSFS_getBaseDir());
	if (strstr(base_dir, ".app:Contents:MacOSClassic"))	// the Mac OS 9 program is still in the .app bundle
	{
		char *p;
		
		bundle = 1;
		if (base_dir[strlen(base_dir) - 1] == ':')
			base_dir[strlen(base_dir) - 1] = '\0';
		p = strrchr(base_dir, ':'); *p = '\0';	// path to 'Contents'
		p = strrchr(base_dir, ':'); *p = '\0';	// path to bundle
		p = strrchr(base_dir, ':'); *p = '\0';	// path to directory containing bundle
	}
#endif
	
#if (defined(__APPLE__) && defined(__MACH__))	// others?
	chdir(base_dir);	// make sure relative hogdir paths work
#endif
	
#if defined(__unix__)
	char fullPath[PATH_MAX + 5];
# if !(defined(__APPLE__) && defined(__MACH__))
	path = "~/.d2x-rebirth/";
# else
	path = "~/Library/Preferences/D2X Rebirth/";
# endif
	
	if (path[0] == '~') // yes, this tilde can be put before non-unix paths.
	{
		const char *home = PHYSFS_getUserDir();
		
		strcpy(fullPath, home); // prepend home to the path
		path++;
		if (*path == *PHYSFS_getDirSeparator())
			path++;
		strncat(fullPath, path, PATH_MAX + 5 - strlen(home));
	}
	else
		strncpy(fullPath, path, PATH_MAX + 5);
	
	PHYSFS_setWriteDir(fullPath);
	if (!PHYSFS_getWriteDir())
	{                                               // need to make it
		char *p;
		char ancestor[PATH_MAX + 5];    // the directory which actually exists
		char child[PATH_MAX + 5];               // the directory relative to the above we're trying to make
		
		strcpy(ancestor, fullPath);
		while (!PHYSFS_getWriteDir() && ((p = strrchr(ancestor, *PHYSFS_getDirSeparator()))))
		{
			if (p[1] == 0)
			{                                       // separator at the end (intended here, for safety)
				*p = 0;                 // kill this separator
				if (!((p = strrchr(ancestor, *PHYSFS_getDirSeparator()))))
					break;          // give up, this is (usually) the root directory
			}
			
			p[1] = 0;                       // go to parent
			PHYSFS_setWriteDir(ancestor);
		}
		
		strcpy(child, fullPath + strlen(ancestor));
		for (p = child; (p = strchr(p, *PHYSFS_getDirSeparator())); p++)
			*p = '/';
		PHYSFS_mkdir(child);
		PHYSFS_setWriteDir(fullPath);
	}
	
	PHYSFS_addToSearchPath(PHYSFS_getWriteDir(), 1);
#endif
	
	PHYSFS_addToSearchPath(base_dir, 1);
	InitArgs( argc,argv );
	PHYSFS_removeFromSearchPath(base_dir);
	
	if (!PHYSFS_getWriteDir())
	{
		PHYSFS_setWriteDir(base_dir);
		if (!PHYSFS_getWriteDir())
			Error("can't set write dir: %s\n", PHYSFS_getLastError());
		else
			PHYSFS_addToSearchPath(PHYSFS_getWriteDir(), 0);
	}
	
	//tell PHYSFS where hogdir is
	if (GameArg.SysHogDir)
		PHYSFS_addToSearchPath(GameArg.SysHogDir,1);
#if defined(__unix__)
	else if (!GameArg.SysNoHogDir)
		PHYSFS_addToSearchPath(SHAREPATH, 1);
#endif
	
	PHYSFSX_addRelToSearchPath("data", 1);	// 'Data' subdirectory
	
	// For Macintosh, add the 'Resources' directory in the .app bundle to the searchpaths
#if defined(__APPLE__) && defined(__MACH__)
	{
		ProcessSerialNumber psn = { 0, kCurrentProcess };
		FSRef fsref;
		OSStatus err;
		
		err = GetProcessBundleLocation(&psn, &fsref);
		if (err == noErr)
			err = FSRefMakePath(&fsref, (ubyte *)fullPath, PATH_MAX);
		
		if (err == noErr)
		{
			strncat(fullPath, "/Contents/Resources/", PATH_MAX + 4 - strlen(fullPath));
			fullPath[PATH_MAX + 4] = '\0';
			PHYSFS_addToSearchPath(fullPath, 1);
		}
	}
#elif defined(macintosh)
	if (bundle)
	{
		base_dir[strlen(base_dir)] = ':';	// go back in the bundle
		base_dir[strlen(base_dir)] = ':';	// go back in 'Contents'
		strncat(base_dir, ":Resources:", PATH_MAX - 1 - strlen(base_dir));
		base_dir[PATH_MAX - 1] = '\0';
		PHYSFS_addToSearchPath(base_dir, 1);
	}
#endif
}