Guest User

Untitled

a guest
Jul 7th, 2016
54
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. <#
  2. .SYNOPSIS
  3.     FF7 PC to Gaming Device Synchronizer
  4. .DESCRIPTION
  5.     Connects via FTP to a compatible gaming device that utilizes a common format for memory cards, compares the age of the
  6.       targeted save file versus the age of the save file in the local save path and then synchronizes the two save files,
  7.       including the conversion between file types and the modification of the metadata.xml file.
  8. .NOTES
  9.     Author: n1ckn4m3 - my.n1ckn4m3@gmail.com
  10. .DEPENDENCIES
  11.     PSFTP Module by Michal Gajda: https://gallery.technet.microsoft.com/scriptcenter/PowerShell-FTP-Client-db6fe0cb
  12.     FF7Save Converter: http://www.zophar.net/utilities/genutil/ff7-savegame-converter.html
  13. .USAGE
  14.     * Download and Import the PSFTP Module and ensure that Import-Module PSFTP successfully completes
  15.     * Create a working directory for the script and copy the contents of the FF7Save.zip to that directory, as well as this script
  16.     ** Make sure that the user account running the script has write access to the working directory you've chosen, else you'll need to elevate privileges for the script to work
  17.     * Update the script variables to be accurate for your environment.  Key ones include $WORKINGDIR, $SAVESLOT, $ANDROIDSAVE, $ANDROIDFTP, $ANDROIDDIR, $USERNAME, and $PASSWORD
  18.     * MAKE BACKUP COPIES OF YOUR SAVE FILES FIRST.  The script does this, but considering it replaces files, better safe than sorry.  I accept no liability if you overwrite
  19.         saves or nuke a 400 hour perfect game, or if your HDD turns into a megalomanical robot trying to take over the world.  In short, use at your own risk.  Provided free with
  20.         no warranty of fitness for any purpose, implied or otherwise.
  21. #>  
  22.  
  23. # I tried doing this without this module and it was hacky, ugly, and stupid.  Thanks, guy who wrote this module.
  24. Import-Module PSFTP
  25.  
  26. # Working Directory.  Change this to whatever you'd like, just make sure it has the FF7 Save converter in it, that it exists, and that it's writable by your user account.
  27. $WORKINGDIR = ([environment]::getfolderpath(“mydocuments”)) + "\Square Enix\FF7 Save Sync\"
  28.  
  29. # General Script Variables
  30. $SAVESLOT = "00" # Use the physical save slot ID, e.g., for save00.ff7, use 00 - NOT 1 - the script relies on this
  31. $SAVEDIRS = Get-ChildItem ([environment]::getfolderpath(“mydocuments”))"Square Enix\Final Fantasy VII Steam\"
  32. $LOCALSAVE = $SAVEDIRS[1].FullName + "\save" + $SAVESLOT + ".ff7"
  33. $LOCALBACKUP = $LOCALSAVE + ".backup"
  34. $WORKINGLOCALSAVE = $WORKINGDIR + "save" + $SAVESLOT + ".ff7"
  35. $LOCALSAVEFILE = "save"+$SAVESLOT+".ff7"
  36.  
  37. # Metadata.XML Specific Variables
  38. $MD5SALT = $WORKINGDIR + "md5salt.bin"
  39. $METADATAXML = $SAVEDIRS[1].FullName + "\Metadata.xml"
  40. $METADATABACKUP = $METADATAXML + ".backup"
  41. $WORKINGMETADATAXML = $WORKINGDIR + "Metadata.xml"
  42. $WORKINGLOCALMD5 = $WORKINGDIR + "save" + $SAVESLOT + ".ff7.md5"  
  43.  
  44. # Metadata.XML Lookup - Save Slot to XML Line ID
  45. If ($SAVESLOT -eq "00"){ $XMLLINE = 18 ; $SAVEID = 1}
  46. If ($SAVESLOT -eq "01"){ $XMLLINE = 36 ; $SAVEID = 2}
  47. If ($SAVESLOT -eq "02"){ $XMLLINE = 54 ; $SAVEID = 3}
  48. If ($SAVESLOT -eq "03"){ $XMLLINE = 72 ; $SAVEID = 4}
  49. If ($SAVESLOT -eq "04"){ $XMLLINE = 90 ; $SAVEID = 5}
  50. If ($SAVESLOT -eq "05"){ $XMLLINE = 108 ; $SAVEID = 6}
  51. If ($SAVESLOT -eq "06"){ $XMLLINE = 126 ; $SAVEID = 7}
  52. If ($SAVESLOT -eq "07"){ $XMLLINE = 144 ; $SAVEID = 8}
  53. If ($SAVESLOT -eq "08"){ $XMLLINE = 162 ; $SAVEID = 9}
  54. If ($SAVESLOT -eq "09"){ $XMLLINE = 180 ; $SAVEID = 10}
  55.  
  56. # Android .MCD file locations and names, update to reflect yours.  Backup should be in the same directory to streamline but I suppose it would be fine anywhere.
  57. $ANDROIDDIR = "/mnt/external_sd/MEMCARDS/"
  58. $ANDROIDSAVEFILE = "ff7_pc.mcd"
  59. $ANDROIDSAVE = $ANDROIDDIR + $ANDROIDSAVEFILE
  60. $ANDROIDBACKUP = $ANDROIDDIR + $ANDROIDSAVEFILE + ".backup"
  61. $WORKINGANDROIDSAVE = $WORKINGDIR + $ANDROIDSAVEFILE
  62. $WORKINGANDROIDBACKUP = $WORKINGDIR + $ANDROIDSAVEFILE + ".backup"
  63.  
  64. #FTP Support Variables, update to reflect your specifics.
  65. $ANDROIDFTP="ftp://gpdxd:31337"
  66. $USERNAME = "<username>"
  67. $PASSWORD = "android" | ConvertTo-SecureString -asPlainText -Force
  68. $CREDENTIAL = New-Object System.Management.Automation.PSCredential($USERNAME,$PASSWORD)
  69.  
  70. # Set Save Sync Directory
  71. Set-Location $WORKINGDIR
  72.  
  73. # Delete working copies of saves if they exist
  74. If (Test-Path $WORKINGLOCALSAVE){Remove-Item $WORKINGLOCALSAVE}
  75. If (Test-Path $WORKINGANDROIDSAVE){Remove-Item $WORKINGANDROIDSAVE}
  76. If (Test-Path $WORKINGANDROIDBACKUP){Remove-Item $WORKINGANDROIDBACKUP}
  77. If (Test-Path $WORKINGMETADATAXML){Remove-Item $WORKINGMETADATAXML}
  78. If (Test-Path $WORKINGDIR\local.txt){Remove-Item $WORKINGDIR\local.txt}
  79. If (Test-Path $WORKINGDIR\remote.txt){Remove-Item $WORKINGDIR\remote.txt}
  80. If (Test-Path $WORKINGDIR\local.cmd){Remove-Item $WORKINGDIR\local.cmd}
  81. If (Test-Path $WORKINGDIR\remote.cmd){Remove-Item $WORKINGDIR\remote.cmd}
  82.  
  83. # Create remote.txt to feed into FF7 Converter when Remote File is newer
  84. $REMOTETXT="1",$ANDROIDSAVEFILE,$SAVEID,"4",$LOCALSAVEFILE,$SAVEID,"1"
  85. $REMOTETXT | Set-Content -Path $WORKINGDIR\remote.txt
  86. $REMOTECMD = "ff7save < remote.txt"
  87. $REMOTECMD | Set-Content -Path $WORKINGDIR\remote.cmd
  88.  
  89. # Create local.txt to feed into FF7 Converter when Local File is newer
  90. $LOCALTXT="4",$LOCALSAVEFILE,$SAVEID,"1",$ANDROIDSAVEFILE,$SAVEID,"1"
  91. $LOCALTXT | Set-Content -Path $WORKINGDIR\local.txt
  92. $LOCALCMD = "ff7save < local.txt"
  93. $LOCALCMD | Set-Content -Path $WORKINGDIR\local.cmd
  94.  
  95. # Copy Local Save to Save Sync Directory
  96. Copy-Item $LOCALSAVE $WORKINGLOCALSAVE
  97.  
  98. #Initiate Connection to Android Device, break script if we can't connect.
  99. Try {
  100.   Set-FTPConnection -Credentials $CREDENTIAL -Server $ANDROIDFTP -Session AndroidFF7SyncSession -UsePassive -ErrorAction Stop | Out-Null
  101. }
  102.  
  103. Catch {
  104.   Write-Host "No response from FTP server, check variables and network connectivity.  Aborting synchronization."
  105.   # Clean up after ourselves, even if stuff goes south pretty early.
  106.   If (Test-Path $WORKINGLOCALSAVE){Remove-Item $WORKINGLOCALSAVE}
  107.   If (Test-Path $WORKINGANDROIDSAVE){Remove-Item $WORKINGANDROIDSAVE}
  108.   If (Test-Path $WORKINGANDROIDBACKUP){Remove-Item $WORKINGANDROIDBACKUP}
  109.   If (Test-Path $WORKINGLOCALMD5){Remove-Item $WORKINGLOCALMD5}
  110.   If (Test-Path $MD5SALT){Remove-Item $MD5SALT}
  111.   If (Test-Path $WORKINGDIR\local.txt){Remove-Item $WORKINGDIR\local.txt}
  112.   If (Test-Path $WORKINGDIR\remote.txt){Remove-Item $WORKINGDIR\remote.txt}
  113.   If (Test-Path $WORKINGDIR\local.cmd){Remove-Item $WORKINGDIR\local.cmd}
  114.   If (Test-Path $WORKINGDIR\remote.cmd){Remove-Item $WORKINGDIR\remote.cmd}
  115.   Break
  116. }
  117.  
  118. # Since we know we can connect now, let's finish setting up the FTP session.
  119. $FTPSession = Get-FTPConnection -Session AndroidFF7SyncSession
  120.  
  121. # Download Remote Save to Save Sync Directory and create working copy of backup
  122. Get-FTPItem -Session $FTPSession -Path $ANDROIDSAVE -LocalPath $WORKINGANDROIDSAVE | Out-Null
  123. Copy-Item $WORKINGANDROIDSAVE $WORKINGANDROIDBACKUP
  124.  
  125. # Check Timestamp of Remote Save vs. Local Save
  126. $RemoteTimestamp = [datetime](Get-FTPChildItem -Session $FTPSession -Path /mnt/external_sd/MEMCARDS/ff7_pc.mcd).ModifiedDate
  127. $LocalTimestamp = [datetime](Get-ItemProperty -Path $WORKINGLOCALSAVE -Name LastWriteTime).lastwritetime
  128.  
  129. # If Remote Save is newer, back up local save and replace
  130. If ($RemoteTimestamp -gt $LocalTimestamp) {
  131.   If (Test-Path $LOCALBACKUP){Remove-Item $LOCALBACKUP}
  132.   Copy-Item $WORKINGLOCALSAVE $LOCALBACKUP
  133.   CMD /C "remote.cmd" | Out-Null # Convert .MCD format FF7 save to .FF7 save format save
  134.   Remove-Item $LOCALSAVE ## Replace save00.ff7
  135.   Copy-Item $WORKINGLOCALSAVE $LOCALSAVE
  136.   Write-Host "Remote save was newer.  Local save has been backed up and replaced."
  137.  
  138.   # Generate MD5 "salt" (not really a salt, but whatever) for Metadata.XML generation later
  139.   $PROFILEID = $SAVEDIRS[1].Name
  140.   $PROFILEID = $PROFILEID.Trim("user_")
  141.   $PROFILEIDARRAY = $PROFILEID.ToCharArray();
  142.   $BYTES = New-Object Byte[] 7
  143.   $HEXARRAY=[int[]][char[]]$PROFILEIDARRAY
  144.   $LOOP=0
  145.   ForEach ($HEXLINE in $HEXARRAY){
  146.     $BYTES[$LOOP]=$HEXLINE
  147.     $LOOP = $LOOP + 1
  148.   }
  149.   [IO.File]::WriteAllBytes($MD5SALT,$BYTES)
  150.  
  151.   # Metadata.XML support code
  152.   $COPYCMD = "copy /b save" + $SAVESLOT + ".ff7+md5salt.bin save" + $SAVESLOT + ".ff7.md5"
  153.   CMD /C $COPYCMD | Out-Null # Concatenate existing save file w/ md5 "salt" to allow signature generation
  154.   $MD5HASH = (Get-FileHash -Path "save" + $SAVESLOT + ".ff7.md5" -Algorithm md5).Hash
  155.   $PREPPEDHASH = "    <signature>"+$MD5HASH.ToLower()+"</signature>"
  156.   $METADATAContent = Get-Content -Path $METADATAXML
  157.   $METADATAContent[$XMLLINE] = $PREPPEDHASH # This value is only accurate if you're targeting the first save file.
  158.   Copy-Item $METADATAXML $METADATABACKUP
  159.   $METADATAContent | Set-Content -Path $METADATAXML
  160.  
  161.   # Re-set proper modified time, as downloading it changed it to 'right now'.
  162.   $MODIFIEDSAVE = Get-Item $LOCALSAVE
  163.   $MODIFIEDSAVE.LastWriteTime = $RemoteTimestamp
  164. }
  165.  
  166. # If Local save is newer, back up remote save and replace
  167. If ($LocalTimestamp -gt $RemoteTimestamp) {
  168.   # Re-upload downloaded ff7_pc.mcd to ff7_pc.mcd backup
  169.   Add-FTPItem -Session $FTPSession -Path $ANDROIDDIR -LocalPath $WORKINGANDROIDBACKUP -Overwrite | Out-Null
  170.   CMD /C "local.cmd" | Out-Null # Convert .ff7 format FF7 save to .MCD save format save
  171.   Add-FTPItem -Session $FTPSession -Path $ANDROIDDIR -LocalPath $WORKINGANDROIDSAVE -Overwrite | Out-Null
  172.   Write-Host "Local save was newer.  Remote save has been backed up and replaced."
  173. }
  174.  
  175. If ($LocalTimestamp -eq $RemoteTimestamp) {
  176.   Write-Host "Timestamps the same, sync complete."
  177. }
  178.  
  179. # Clean up after ourselves.
  180. If (Test-Path $WORKINGLOCALSAVE){Remove-Item $WORKINGLOCALSAVE}
  181. If (Test-Path $WORKINGANDROIDSAVE){Remove-Item $WORKINGANDROIDSAVE}
  182. If (Test-Path $WORKINGANDROIDBACKUP){Remove-Item $WORKINGANDROIDBACKUP}
  183. If (Test-Path $WORKINGLOCALMD5){Remove-Item $WORKINGLOCALMD5}
  184. If (Test-Path $WORKINGDIR\local.txt){Remove-Item $WORKINGDIR\local.txt}
  185. If (Test-Path $WORKINGDIR\remote.txt){Remove-Item $WORKINGDIR\remote.txt}
  186. If (Test-Path $WORKINGDIR\local.cmd){Remove-Item $WORKINGDIR\local.cmd}
  187. If (Test-Path $WORKINGDIR\remote.cmd){Remove-Item $WORKINGDIR\remote.cmd}
Add Comment
Please, Sign In to add comment