Code archives/Miscellaneous/Save settings to correct location on Windows
This code has been declared by its author to be Public Domain code.
Download source code
| |||||
| This system allows you to save your application's preferences in the correct location on Windows Vista, 7/8 and upwards, whereas trying to save into your application's own folder may fail due to UAC settings/other filesystem behaviours on these OSes. Just amend ApplicationName and PrefsFilename globals to suit, then call LoadSettings (), SaveSettings () and GetPrefsFile (). Try the demo! Recommend reading the Usage notes first... For real-world usage, you'll have to modify LoadSettings and WriteSettingsFile to accommodate your game's variables/structure (eg. your variables may be in a class/Type rather than globals). | |||||
' ----------------------------------------------------------
' Reads and writes save-files in correct location on Windows!
' ----------------------------------------------------------
Rem
Usage:
1) Modify the ApplicationName and PrefsFilename globals to suit
your application. Can be left as defaults for demo.
2) Use only the three functions below:
LoadSettings () - loads your settings file, if it exists
SaveSettings () - creates folder in correct location (if needed);
creates prefs file in folder (if needed);
saves prefs!
GetPrefsFile () - returns path of prefs file, based on
ApplicationName and PrefsFilename.
Modify these two globals below to suit yourself!
Note on application name/prefs filename:
To avoid conflict with other applications,
probably best to use your developer/studio
name for ApplicationName (this is the folder
name) and the name of your game for
PrefsFilename (eg. "Rocket Raiders.cfg")
3) On running the demo, navigate to the folder name returned by GetPrefsFile ()
to see the folder/prefs file. Delete the folder to clean up after playing
around! Try re-running several times, and try deleting prefs file/folder
and re-running...
End Rem
' ----------------------------------------------------------
' N O T E S . . .
' ----------------------------------------------------------
' Just call SaveSettings to set up your save folder/file for the first time.
' You'll have to amend LoadSettings to accommodate your game's variables and/or structure.
' Amend WriteSettingsFile to suit your game. (SaveSettings is just a wrapper around this.)
SuperStrict
?Win32 ' Windows only!
Global ApplicationName:String = "AAA Example Game"
Global PrefsFilename:String = "prefs.txt"
' Some example variables to be saved/loaded:
Global Example_Lives:Int = 0
Global Example_Level:String = ""
' Uses an example save file of the form:
Rem
LIVES:Integer
LEVEL:String
... eg.
LIVES:5
LEVEL:Space
End Rem
' Windows special path constants:
Const CSIDL_PERSONAL:Int = $5 ' Use this instead of CSIDL_MYDOCUMENTS. I don't know why! Ask Microsoft...
Const CSIDL_APPDATA:Int = $1A
' From http://www.blitzbasic.com/codearcs/codearcs.php?code=2815
' See URL for more special folder locations!
Function GetSpecialFolder:String (folder:Int)
' Shell32 functions...
Global SHGetSpecialFolderLocation_ (hwndOwner:Byte Ptr, nFolder:Int, pidl:Byte Ptr) "win32"
Global SHGetPathFromIDList_ (pidl:Byte Ptr, bytearray:Byte Ptr) "win32"
' OLE32 functions...
Global CoTaskMemFree_ (pv:Byte Ptr)
' Assign function pointers...
Local shell32:Int = LoadLibraryA ("shell32.dll")
Local ole32:Int = LoadLibraryA ("ole32.dll")
Local result:Int = False
If shell32
SHGetSpecialFolderLocation_ = GetProcAddress (shell32, "SHGetSpecialFolderLocation")
SHGetPathFromIDList_ = GetProcAddress (shell32, "SHGetPathFromIDList")
If (Not SHGetSpecialFolderLocation_) Or (Not SHGetPathFromIDList_)
DebugLog "Failed to assign shell32 function pointer!"
Return ""
EndIf
Else
DebugLog "Failed to open shell32.dll!"
Return ""
EndIf
If ole32
CoTaskMemFree_ = GetProcAddress (ole32, "CoTaskMemFree")
If Not CoTaskMemFree_
DebugLog "Failed to assign ole32 function pointer!"
Return ""
EndIf
Else
DebugLog "Failed to open ole32.dll!"
Return ""
EndIf
Function GetSpecialFolder_Sub:String(folder_id:Int) ' JoshK's code brutally hacked-in!
Local idl:TBank = CreateBank (8)
Local pathbank:TBank = CreateBank (260)
Local n%
Local sp$
Local b:Int
If SHGetSpecialFolderLocation_ (Null, folder_id, BankBuf (idl)) = 0
SHGetPathFromIDList_ Byte Ptr PeekInt (idl, 0), BankBuf (pathbank)
For n = 0 To 259
b = PeekByte (pathbank, n)
If b = 0
CoTaskMemFree_ (Byte Ptr PeekInt (idl, 0))
Return sp
EndIf
sp$ = sp$ + Chr (b)
Next
Else
Return ""
EndIf
CoTaskMemFree_ (Byte Ptr PeekInt (idl, 0))
Return sp.Trim ()
End Function
If SHGetSpecialFolderLocation_ And SHGetPathFromIDList_ And CoTaskMemFree_
Return GetSpecialFolder_Sub (folder)
EndIf
End Function
' Helper function...
Function Quoted:String (in:String)
Return "~q" + in + "~q"
End Function
' Retrieves location of prefs file based on ApplicationName and PrefsFilename,
' whether or not they've been created yet...
Function GetPrefsFile:String ()
Local folder:String = GetSpecialFolder (CSIDL_APPDATA)
If folder = ""
folder = GetSpecialFolder (CSIDL_PERSONAL)
If folder = ""
folder = "C:" ' Gah! What's up with your system?!
EndIf
EndIf
If Right (folder, 1) <> "\" And Right (folder, 1) <> "/"
folder = folder + "\"
EndIf
Return folder + ApplicationName + "\" + PrefsFilename
End Function
' ----------------------------------------------------------
' Deletes settings file...
' ----------------------------------------------------------
Function DeleteSettings ()
DeleteFile (GetPrefsFile ())
End Function
' ----------------------------------------------------------
' Loads settings, if settings file exists...
' ----------------------------------------------------------
' Use SaveSettings to set up prefs folder/file!
Function LoadSettings ()
Local loadprefs:TStream = ReadFile (GetPrefsFile ())
If loadprefs
While Not Eof (loadprefs)
Local info:String = ReadLine (loadprefs)
' Example line:
' LEVEL:Space
Local splitter:Int = Instr (info, ":")
Local entry:String = Trim (Left (info, splitter - 1))
Local value:String = Trim (Mid (info, splitter + 1))
' Amend the Case entries and Example_Variables to suit your game!
Select entry
Case "LIVES"
' Read an Int...
Example_Lives = Int (value)
Case "LEVEL"
' Read a String...
Example_Level = value
Default
EndSelect
Wend
CloseFile loadprefs
Else
Print "Couldn't load preferences file! Does " + Quoted (GetPrefsFile ()) + " exist?"
EndIf
End Function
' ----------------------------------------------------------
' Save settings. Modify the highlighted section to suit!
' ----------------------------------------------------------
Function WriteSettingsFile (folder:String)
If Right (folder, 1) = "\" Or Right (folder, 1) = "/"
folder = folder [..Len (folder) - 1] ' FileType doesn't like end slashes on folders!
EndIf
Local savefile:String = folder + "\" + PrefsFilename
If FileType (folder) = FILETYPE_DIR
Local created:Int = CreateFile (savefile)
If created
Local saveprefs:TStream = WriteFile (savefile)
If saveprefs
' ----------------------------------------------------------
' *** MODIFY ME! ***
' ----------------------------------------------------------
' ----------------------------------------------------------
' The settings save section - amend to suit your game!
' ----------------------------------------------------------
WriteLine saveprefs, "LIVES:" + Example_Lives
WriteLine saveprefs, "LEVEL:" + Example_Level
' ----------------------------------------------------------
' *** END OF MODIFY ME! ***
' ----------------------------------------------------------
CloseFile saveprefs
Else
Print "Unable to create preferences file " + Quoted (savefile)
EndIf
EndIf
Else
Print "Unable to locate preferences folder " + Quoted (folder)
Print "Folder is " + FileType (folder)
Print "Folder is " + FileType ("C:\Users\James\AppData\Roaming\AAA Example Game\")
Print "Folder is " + FileType ("C:\Users\James\AppData\Roaming\AAA Example Game")
EndIf
End Function
' ----------------------------------------------------------
' Wrapper for WriteSettingsFile...
' ----------------------------------------------------------
Function SaveSettings ()
Local folder:String = ExtractDir (GetPrefsFile ())
folder = Replace (folder, "/", "\") ' WTF, ExtractDir?!
CreateDir folder$
Select FileType (folder$)
Case 0
Print "Unable to create preferences folder " + Quoted (folder)
Case FILETYPE_DIR
WriteSettingsFile folder
Case FILETYPE_FILE ' Unlikely!
Print "Unable to create preferences folder + " + Quoted (folder) + "; file with same name already exists!"
EndSelect
End Function
? ' End of ?Win32 section!
' ----------------------------------------------------------
' D E M O . . .
' ----------------------------------------------------------
' Some random level names for saving...
Local Level_Name:String [10]
Level_Name [0] = "Snow World"
Level_Name [1] = "Eiffel Tower"
Level_Name [2] = "Egypt"
Level_Name [3] = "Space"
Level_Name [4] = "Moon"
Level_Name [5] = "Hell"
Level_Name [6] = "Desert"
Level_Name [7] = "Circus"
Level_Name [8] = "Inca"
Level_Name [9] = "Alien Planet"
SeedRnd MilliSecs ()
Print ""
Print "Using " + GetPrefsFile () ' Just for info
' ----------------------------------------------------------
' Load settings... expected to fail if not already saved!
' ----------------------------------------------------------
Print ""
Print "Attempting to load settings..."
Print ""
LoadSettings
' ----------------------------------------------------------
' Show loaded settings... will be default null on first run
' ----------------------------------------------------------
Print ""
Print "Loaded settings:"
Print ""
Print "~t~tLives: " + Example_Lives
Print "~t~tLevel: " + Example_Level
Print ""
' ----------------------------------------------------------
' Randomly change settings...
' ----------------------------------------------------------
Print ""
Print "Randomly changing settings..."
Print ""
Example_Lives = Rand (1, 10)
Example_Level = Level_Name [Rand (0, 9)]
' ----------------------------------------------------------
' Save settings...
' ----------------------------------------------------------
Print ""
Print "Saving new settings..."
Print ""
SaveSettings
' ----------------------------------------------------------
' Reload saved settings...
' ----------------------------------------------------------
Print ""
Print "Attempting to reload saved settings..."
Print ""
LoadSettings
' ----------------------------------------------------------
' Show loaded settings...
' ----------------------------------------------------------
Print ""
Print "Loaded settings:"
Print ""
Print "~t~tLives: " + Example_Lives
Print "~t~tLevel: " + Example_Level
Print "" |
Comments
None.
Code Archives Forum