PageRenderTime 1ms CodeModel.GetById 45ms app.highlight 25ms RepoModel.GetById 1ms app.codeStats 0ms

/src/com/yifanlu/PSXperiaTool/Interface/CommandLine.java

https://github.com/BoTToEsP/PSXperia
Java | 262 lines | 222 code | 23 blank | 17 comment | 45 complexity | 60cbe696c438e3c413ca62f380fe248b MD5 | raw file
  1/*
  2 * PSXperia Converter Tool - Logging
  3 * Copyright (C) 2011 Yifan Lu (http://yifan.lu/)
  4 *
  5 * This program is free software: you can redistribute it and/or modify
  6 * it under the terms of the GNU General Public License as published by
  7 * the Free Software Foundation, either version 3 of the License, or
  8 * (at your option) any later version.
  9 *
 10 * This program is distributed in the hope that it will be useful,
 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 13 * GNU General Public License for more details.
 14 *
 15 * You should have received a copy of the GNU General Public License
 16 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 17 */
 18
 19package com.yifanlu.PSXperiaTool.Interface;
 20
 21import com.android.sdklib.internal.build.SignedJarBuilder;
 22import com.yifanlu.PSXperiaTool.Extractor.CrashBandicootExtractor;
 23import com.yifanlu.PSXperiaTool.Logger;
 24import com.yifanlu.PSXperiaTool.PSImageExtract;
 25import com.yifanlu.PSXperiaTool.PSXperiaTool;
 26
 27import java.io.File;
 28import java.io.FileInputStream;
 29import java.io.FileOutputStream;
 30import java.io.IOException;
 31import java.security.GeneralSecurityException;
 32import java.util.Arrays;
 33import java.util.InputMismatchException;
 34import java.util.Properties;
 35import java.util.Stack;
 36import java.util.regex.Matcher;
 37import java.util.regex.Pattern;
 38import java.util.zip.DataFormatException;
 39
 40public class CommandLine {
 41    private static class InvalidArgumentException extends Exception {
 42        private String mMessage;
 43
 44        public InvalidArgumentException(String message) {
 45            this.mMessage = message;
 46        }
 47
 48        public String getMessage() {
 49            return this.mMessage;
 50        }
 51    }
 52
 53    public static void verifyTitleID(String toVerify) throws InputMismatchException {
 54        Pattern pattern = Pattern.compile("^[A-Za-z0-9_]+$");
 55        Matcher matcher = pattern.matcher(toVerify);
 56        if (!matcher.find())
 57            throw new InputMismatchException("Title ID can only contain alphanumberic characters and underscores.");
 58    }
 59
 60    public static void main(String[] args) {
 61        Logger.setLevel(Logger.DEBUG);
 62        if (args.length < 1)
 63            printHelp();
 64        String toDo = args[0];
 65        try {
 66            if (toDo.equals("extract") || toDo.equals("x"))
 67                doExtractData(args);
 68            if (toDo.equals("convert") || toDo.equals("c"))
 69                doConvertImage(args);
 70            if (toDo.equals("decompress") || toDo.equals("d"))
 71                doDecompressImage(args);
 72
 73        } catch (InputMismatchException ex) {
 74            Logger.error("Input error: %s", ex.getMessage());
 75            ex.printStackTrace();
 76        } catch (InvalidArgumentException ex) {
 77            Logger.error("Invalid argument: %s", ex.getMessage());
 78            printHelp();
 79        } catch (IOException ex) {
 80            Logger.error("IO error, Java says: %s", ex.getMessage());
 81            ex.printStackTrace();
 82        } catch (InterruptedException ex) {
 83            Logger.error("Process exec Error, Java says: %s", ex.getMessage());
 84            ex.printStackTrace();
 85        } catch (DataFormatException ex) {
 86            Logger.error("Data format error, Java says: %s", ex.getMessage());
 87            ex.printStackTrace();
 88        } catch (GeneralSecurityException ex) {
 89            Logger.error("Error signing JAR, Java says: %s", ex.getMessage());
 90            ex.printStackTrace();
 91        } catch (SignedJarBuilder.IZipEntryFilter.ZipAbortException ex) {
 92            Logger.error("Error signing JAR, Java says: %s", ex.getMessage());
 93            ex.printStackTrace();
 94        } catch (UnsupportedOperationException ex) {
 95            Logger.error("Unsupported exception: %s", ex.getMessage());
 96            ex.printStackTrace();
 97        }
 98    }
 99
100    public static void doExtractData(String[] args) throws InvalidArgumentException, IOException {
101        if (args.length < 4)
102            throw new InvalidArgumentException("Not enough input.");
103
104        Stack<String> stack = new Stack<String>();
105        stack.addAll(Arrays.asList(args));
106        File outputDir = new File(stack.pop());
107        File inputZpak = new File(stack.pop());
108        File inputApk = new File(stack.pop());
109
110        while (!stack.empty()) {
111            String argument = stack.pop();
112            if (argument.startsWith("-")) {
113                if (argument.equals("-v") || argument.equalsIgnoreCase("--verbose")) {
114                    Logger.setLevel(Logger.ALL);
115                    continue;
116                }
117                Logger.warning("Unknown option %s", argument);
118            }
119        }
120        (new CrashBandicootExtractor(inputApk, inputZpak, outputDir)).extractApk();
121        System.exit(0);
122    }
123
124    public static void doConvertImage(String[] args) throws InvalidArgumentException, IOException, InterruptedException, GeneralSecurityException, SignedJarBuilder.IZipEntryFilter.ZipAbortException {
125        if (args.length < 3)
126            throw new InvalidArgumentException("Not enough input.");
127
128        Stack<String> stack = new Stack<String>();
129        stack.addAll(Arrays.asList(args));
130        File outputDir = new File(stack.pop());
131        File inputFile = new File(stack.pop());
132        String titleId = stack.pop();
133
134        Properties settings = new Properties();
135        settings.loadFromXML(PSXperiaTool.class.getResourceAsStream("/resources/defaults.xml"));
136        settings.put("KEY_TITLE_ID", titleId);
137        File currentDir = new File(".");
138        File dataDir = new File(currentDir, "/data");
139
140        Stack<String> stringList = new Stack<String>();
141        while (!stack.empty()) {
142            String argument = stack.pop();
143            if (argument.startsWith("-")) {
144                if (argument.equals("-v") || argument.equalsIgnoreCase("--verbose")) {
145                    Logger.setLevel(Logger.ALL);
146                    continue;
147                } else if (argument.equals("-D")) {
148                    dataDir = new File(stringList.pop());
149                    stringList.empty();
150                } else if (argument.equals("--load-xml")) {
151                    File xml = new File(stringList.pop());
152                    settings.loadFromXML(new FileInputStream(xml));
153                    stringList.empty();
154                } else if (argument.equals("--game-name")) {
155                    String name = stackToString(stringList);
156                    settings.put("KEY_DISPLAY_NAME", name);
157                    settings.put("KEY_TITLE", name);
158                } else if (argument.equals("--description")) {
159                    settings.put("KEY_DESCRIPTION", stackToString(stringList));
160                } else if (argument.equals("--publisher")) {
161                    settings.put("KEY_PUBLISHER", stackToString(stringList));
162                } else if (argument.equals("--developer")) {
163                    settings.put("KEY_DEVELOPER", stackToString(stringList));
164                } else if (argument.equals("--icon-file")) {
165                    settings.put("IconFile", new File(stringList.pop()));
166                    stringList.empty();
167                } else if (argument.equals("--store-type")) {
168                    settings.put("KEY_STORE_TYPE", stackToString(stringList));
169                } else if (argument.equals("--analog-mode")) {
170                    String str = stringList.pop();
171                    if (str.equals("true"))
172                        settings.put("KEY_ANALOG_MODE", "YES");
173                    stringList.empty();
174                } else {
175                    stringList.push(argument);
176                }
177            } else {
178                stringList.push(argument);
179            }
180        }
181
182        verifyTitleID(titleId);
183        PSXperiaTool tool = new PSXperiaTool(settings, inputFile, dataDir, outputDir);
184        tool.startBuild();
185
186        System.exit(0);
187    }
188
189    private static String stackToString(Stack<String> stack) {
190        String str = "";
191        while (!stack.isEmpty()) {
192            str += stack.pop() + " ";
193        }
194        str = str.replaceAll("^\"", "");
195        str = str.replaceAll("\"$", "");
196        return str;
197    }
198
199    public static void doDecompressImage(String[] args) throws InvalidArgumentException, IOException, DataFormatException {
200        if (args.length < 3)
201            throw new InvalidArgumentException("Not enough input.");
202
203        Stack<String> stack = new Stack<String>();
204        stack.addAll(Arrays.asList(args));
205        File outputFile = new File(stack.pop());
206        File inputFile = new File(stack.pop());
207
208        while (!stack.empty()) {
209            String argument = stack.pop();
210            if (argument.startsWith("-")) {
211                if (argument.equals("-v") || argument.equalsIgnoreCase("--verbose")) {
212                    Logger.setLevel(Logger.ALL);
213                    continue;
214                }
215                Logger.warning("Unknown option %s", argument);
216            }
217        }
218        FileInputStream in = new FileInputStream(inputFile);
219        FileOutputStream out = new FileOutputStream(outputFile);
220        PSImageExtract extract = new PSImageExtract(in);
221        extract.uncompress(out);
222        out.close();
223        in.close();
224        System.exit(0);
225    }
226
227    public static void printHelp() {
228        System.out.println("PSXPeria Converter Tool");
229        System.out.println("");
230        System.out.println("Usage:");
231        System.out.println("  Extract and patch data files");
232        System.out.println("  psxperia e[x]tract [-v|--verbose] input.apk input-data.zpak output");
233        System.out.println("    [-v|--verbose]    Verbose output");
234        System.out.println("    input.apk         Either com.sony.playstation.ncua94900_1.apk or com.sony.playstation.ncea00344_1.apk");
235        System.out.println("    input-data.zpak   Either NCUA94900_1_1.zpak or NCEA00344_1_1.zpak (must match region of APK)");
236        System.out.println("    output            Directory to extract the files");
237        System.out.println("");
238        System.out.println("  Convert ISO to Xperia Play APK and ZPAK");
239        System.out.println("  psxperia [c]onvert [OPTIONS] titleId image.iso output");
240        System.out.println("    titleId           An unique ID, usually from the game in the format NCXAXXXXX_1");
241        System.out.println("    image.iso         Input PSX image. You must rip it on your own!");
242        System.out.println("    output            Directory to output files");
243        System.out.println("    Options (unset options will be set to defaults):");
244        System.out.println("      -v|--verbose    Verbose output, including image creation progress");
245        System.out.println("      -D directory    Custom location for extracted data files, default is \"./data\"");
246        System.out.println("      --load-xml      Load options from Java properties XML");
247        System.out.println("      --game-name     Name of the game");
248        System.out.println("      --description   Description of the game");
249        System.out.println("      --publisher     Publisher of the game");
250        System.out.println("      --developer     Developer of the game");
251        System.out.println("      --icon-file     Path to image for icon");
252        System.out.println("      --store-type    Where to find this title (any string will do)");
253        System.out.println("      --analog-mode   true|false, Turn on/off analog controls (game must support it).");
254        System.out.println("");
255        System.out.println("  Convert image.ps to ISO");
256        System.out.println("  psxperia [d]ecompress [-v|--verbose] input.ps output.iso");
257        System.out.println("    [-v|--verbose]    Verbose output");
258        System.out.println("    input.ps          image.ps from ZPAK");
259        System.out.println("    output.iso        ISO file to generate");
260        System.exit(0);
261    }
262}