Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Initial commit.

  • Loading branch information...
commit 56375987c727f3d3cc6effd4edd9a8f3d3a0105c 0 parents
@Furyhunter authored
22 .gitattributes
@@ -0,0 +1,22 @@
+# Auto detect text files and perform LF normalization
+* text=auto
+
+# Custom for Visual Studio
+*.cs diff=csharp
+*.sln merge=union
+*.csproj merge=union
+*.vbproj merge=union
+*.fsproj merge=union
+*.dbproj merge=union
+
+# Standard to msysgit
+*.doc diff=astextplain
+*.DOC diff=astextplain
+*.docx diff=astextplain
+*.DOCX diff=astextplain
+*.dot diff=astextplain
+*.DOT diff=astextplain
+*.pdf diff=astextplain
+*.PDF diff=astextplain
+*.rtf diff=astextplain
+*.RTF diff=astextplain
163 .gitignore
@@ -0,0 +1,163 @@
+#################
+## Eclipse
+#################
+
+*.pydevproject
+.project
+.metadata
+bin/
+tmp/
+*.tmp
+*.bak
+*.swp
+*~.nib
+local.properties
+.classpath
+.settings/
+.loadpath
+
+# External tool builders
+.externalToolBuilders/
+
+# Locally stored "Eclipse launch configurations"
+*.launch
+
+# CDT-specific
+.cproject
+
+# PDT-specific
+.buildpath
+
+
+#################
+## Visual Studio
+#################
+
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+
+# User-specific files
+*.suo
+*.user
+*.sln.docstates
+
+# Build results
+[Dd]ebug/
+[Rr]elease/
+*_i.c
+*_p.c
+*.ilk
+*.meta
+*.obj
+*.pch
+*.pdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.vspscc
+.builds
+*.dotCover
+
+## TODO: If you have NuGet Package Restore enabled, uncomment this
+#packages/
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opensdf
+*.sdf
+
+# Visual Studio profiler
+*.psess
+*.vsp
+
+# ReSharper is a .NET coding add-in
+_ReSharper*
+
+# Installshield output folder
+[Ee]xpress
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish
+
+# Others
+[Bb]in
+[Oo]bj
+sql
+TestResults
+*.Cache
+ClientBin
+stylecop.*
+~$*
+*.dbmdl
+Generated_Code #added for RIA/Silverlight projects
+
+# Backup & report files from converting an old project file to a newer
+# Visual Studio version. Backup files are not needed, because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+
+
+
+############
+## Windows
+############
+
+# Windows image file caches
+Thumbs.db
+
+# Folder config file
+Desktop.ini
+
+
+#############
+## Python
+#############
+
+*.py[co]
+
+# Packages
+*.egg
+*.egg-info
+dist
+build
+eggs
+parts
+bin
+var
+sdist
+develop-eggs
+.installed.cfg
+
+# Installer logs
+pip-log.txt
+
+# Unit test / coverage reports
+.coverage
+.tox
+
+#Translations
+*.mo
+
+#Mr Developer
+.mr.developer.cfg
+
+# Mac crap
+.DS_Store
18 readme.mkd
@@ -0,0 +1,18 @@
+Custom PSO2 Patcher
+===================
+
+Simple patcher for Phantasy Star Online 2 that supports alternate mirrors and
+can pick up where it left off.
+
+Currently not for common use. Need to write a GUI first.
+
+How to use
+----------
+
+change the field default values in jp.pso2.PSOPatcher to point to the paths you
+want to update. the defaults work for 32-bit Windows Vista and 7 installations
+but you will need to change the download path to get it working for XP, etc
+
+run jp.pso2.PSO2Patcher
+
+no easy way to run it without the jdk yet
35 src/jp/pso2/MD5Sum.java
@@ -0,0 +1,35 @@
+package jp.pso2;
+
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.security.MessageDigest;
+
+public class MD5Sum {
+ public static byte[] createChecksum(String filename) throws Exception {
+ InputStream fis = new FileInputStream(filename);
+
+ byte[] buffer = new byte[1024];
+ MessageDigest complete = MessageDigest.getInstance("MD5");
+ int numRead;
+
+ do {
+ numRead = fis.read(buffer);
+ if (numRead > 0) {
+ complete.update(buffer, 0, numRead);
+ }
+ } while (numRead != -1);
+
+ fis.close();
+ return complete.digest();
+ }
+
+ public static String getMD5Checksum(String filename) throws Exception {
+ byte[] b = createChecksum(filename);
+ String result = "";
+
+ for (int i=0; i < b.length; i++) {
+ result += Integer.toString( ( b[i] & 0xff ) + 0x100, 16).substring( 1 );
+ }
+ return result;
+ }
+}
177 src/jp/pso2/PSO2Patcher.java
@@ -0,0 +1,177 @@
+package jp.pso2;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.net.URL;
+import java.nio.channels.Channels;
+import java.nio.channels.FileChannel;
+import java.nio.channels.ReadableByteChannel;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Scanner;
+
+public class PSO2Patcher implements Runnable {
+
+ private String location = "http://patch01.pso2gs.net/patch_prod/patches/";
+ private String downloadDir = "C:/Users/" + System.getProperty("user.name") + "/Documents/SEGA/PHANTASYSTARONLINE2/download/";
+ private String installPath = "C:/Program Files/SEGA/PHANTASYSTARONLINE2/pso2_bin/";
+
+ private List<PatchFile> launcherFiles;
+ private List<PatchFile> patchFiles;
+
+ private List<PatchFile> updatedFiles = new LinkedList<PatchFile>();
+
+ @Override
+ public void run() {
+ System.out.println("PSO2 Patcher");
+ System.out.println("Downloading from " + location);
+ System.out.println("Saving to " + downloadDir);
+ System.out.println("Installing to " + installPath);
+
+ parseLauncherList();
+ parsePatchList();
+
+ System.out.println("Checking launcher files");
+ boolean res;
+ res = downloadPatches(launcherFiles);
+ if (res) {
+ System.out.println("Installing updated launcher files");
+
+ installFiles(updatedFiles);
+ updatedFiles.clear();
+ }
+
+ System.out.println("Checking patch files");
+ res = downloadPatches(patchFiles);
+ if (res) {
+ System.out.println("Installing updated patch files");
+
+ installFiles(updatedFiles);
+ updatedFiles.clear();
+ }
+
+ // download version.ver
+ try {
+ System.out.println("Downloading version.ver");
+ ReadableByteChannel rbc = Channels.newChannel(new URL(location + "version.ver").openStream());
+ File fff = new File(new File(downloadDir).getParent() + "version.ver");
+ FileOutputStream fos = new FileOutputStream(fff);
+ fos.getChannel().transferFrom(rbc, 0, 1 << 24);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ System.out.println("Patching complete!");
+ }
+
+ private boolean downloadPatches(List<PatchFile> patches) {
+ boolean changed = false;
+ for (PatchFile f : patches) {
+ File lf = new File(installPath + f.localPathNoPat);
+ try {
+ // check md5sum
+ String md5 = MD5Sum.getMD5Checksum(lf.getAbsolutePath()).toUpperCase();
+ if (md5.equals(f.md5sum)) {
+ System.out.println("File " + f.localPathNoPat + " is up to date.");
+ continue;
+ }
+ } catch (Exception e) {
+ // file doesn't exist at destination
+ }
+
+ lf = new File(downloadDir + f.localPath);
+ try {
+ // check md5sum
+ String md5 = MD5Sum.getMD5Checksum(lf.getAbsolutePath()).toUpperCase();
+ if (md5.equals(f.md5sum)) {
+ System.out.println("Using existing download to patch " + f.localPathNoPat);
+ updatedFiles.add(f);
+ changed = true;
+ continue;
+ }
+ } catch (Exception e) {
+ // file doesn't exist in predownloads
+ }
+
+ // download the patch because the files are different
+ try {
+ changed = true;
+ System.out.println("Downloading " + ((double)f.fileSize/1048576) + " MiB of data for " + f.localPath + "...");
+ ReadableByteChannel rbc = Channels.newChannel(f.url.openStream());
+ File fff = new File(downloadDir + f.localPath);
+ fff.getParentFile().mkdirs();
+ FileOutputStream fos = new FileOutputStream(fff);
+ fos.getChannel().transferFrom(rbc, 0, f.fileSize);
+ fos.close();
+ rbc.close();
+ updatedFiles.add(f);
+ } catch (Exception e) {
+ System.out.println("Error downloading file " + f.localPath + ": " + e.getMessage());
+ e.printStackTrace();
+ System.exit(1);
+ }
+ }
+ return changed;
+ }
+
+ private void parseLauncherList() {
+ System.out.println("Downloading launcherlist");
+ launcherFiles = new LinkedList<PatchFile>();
+
+ try {
+ URL url = new URL(location + "launcherlist.txt");
+ Scanner s = new Scanner(url.openStream());
+
+ while (s.hasNextLine()) {
+ PatchFile p = new PatchFile(s.nextLine(), location);
+ launcherFiles.add(p);
+ }
+ } catch (IOException e) {
+ System.out.println("Failed to download and parse patchlist");
+ e.printStackTrace();
+ System.exit(1);
+ }
+ }
+
+ private void parsePatchList() {
+ System.out.println("Downloading patchlist");
+ patchFiles = new LinkedList<PatchFile>();
+
+ try {
+ URL url = new URL(location + "patchlist.txt");
+ Scanner s = new Scanner(url.openStream());
+
+ while (s.hasNextLine()) {
+ PatchFile p = new PatchFile(s.nextLine(), location);
+ patchFiles.add(p);
+ }
+
+ } catch (IOException e) {
+ System.out.println("Failed to download and parse patchlist");
+ e.printStackTrace();
+ System.exit(1);
+ }
+ }
+
+ private void installFiles(List<PatchFile> files) {
+ for (PatchFile f : files) {
+ FileChannel source = null;
+ FileChannel dest = null;
+ try {
+ System.out.println("Installing " + f.localPathNoPat);
+ source = new FileInputStream(new File(downloadDir + f.localPath)).getChannel();
+ dest = new FileOutputStream(new File(installPath + f.localPathNoPat)).getChannel();
+ dest.transferFrom(source, 0, source.size());
+ source.close();
+ dest.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ public static void main(String[] args) {
+ new PSO2Patcher().run();
+ }
+}
27 src/jp/pso2/PatchFile.java
@@ -0,0 +1,27 @@
+package jp.pso2;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Scanner;
+
+public class PatchFile {
+ public URL url;
+ public String localPath;
+ public String localPathNoPat;
+ public long fileSize;
+ public String md5sum;
+
+ public PatchFile(String line, String location) {
+ Scanner s = new Scanner(line);
+ localPath = s.next();
+ localPathNoPat = localPath.substring(0, localPath.indexOf(".pat"));
+ fileSize = s.nextLong();
+ md5sum = s.next();
+
+ try {
+ url = new URL(location + localPath);
+ } catch (MalformedURLException e) {
+ e.printStackTrace();
+ }
+ }
+}
Please sign in to comment.
Something went wrong with that request. Please try again.