├── .gitignore ├── .gitmodules ├── .idea ├── .name ├── ant.xml ├── artifacts │ └── PSXperiaTool.xml ├── compiler.xml ├── copyright │ └── profiles_settings.xml ├── encodings.xml ├── libraries │ └── Libraries.xml ├── misc.xml ├── modules.xml └── vcs.xml ├── PSXperiaTool.iml ├── README ├── resources ├── android-framework.jar ├── defaults.xml ├── icon.png ├── patches │ ├── 3B6A23C1 │ │ └── config.xml │ ├── 6C7C966B │ │ ├── config.xml │ │ ├── filelist.txt │ │ ├── game-patch.bin │ │ ├── libjava-activity.so.jbpatch │ │ └── stringReplacements.txt │ ├── 76C201D8 │ │ ├── config.xml │ │ ├── filelist.txt │ │ ├── game-patch.bin │ │ ├── libjava-activity.so.jbpatch │ │ └── stringReplacements.txt │ ├── 7C33475B │ │ ├── config.xml │ │ ├── filelist.txt │ │ ├── game-patch.bin │ │ ├── libjava-activity.so.jbpatch │ │ └── stringReplacements.txt │ ├── BB542581 │ │ ├── config.xml │ │ ├── filelist.txt │ │ └── stringReplacements.txt │ └── E7BCB6D5 │ │ ├── config.xml │ │ ├── filelist.txt │ │ └── stringReplacements.txt └── signApk.keystore └── src ├── META-INF └── MANIFEST.MF └── com └── yifanlu └── PSXperiaTool ├── ApkBuilder.java ├── Extractor └── CrashBandicootExtractor.java ├── Interface ├── CommandLine.java ├── GUI.java └── Strings.properties ├── Logger.java ├── PSImage.java ├── PSImageCreate.java ├── PSImageExtract.java ├── PSXperiaTool.java ├── ProgressMonitor.java ├── StringReplacement.java └── ZpakCreate.java /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .idea/workspace.xml 3 | .idea/uiDesigner.xml 4 | data/ 5 | resources/libjava-activity-wrapper.so 6 | resources/aapt* 7 | lib/ 8 | out/ 9 | output/ 10 | ps-image-temp/ 11 | src/com/yifanlu/PSXperiaTool/Test/PrivateTest.java 12 | temp/ -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "wrapper-library"] 2 | path = wrapper-library 3 | url = git@github.com:yifanlu/PSXPeria-Wrapper.git 4 | -------------------------------------------------------------------------------- /.idea/.name: -------------------------------------------------------------------------------- 1 | PSXperiaTool -------------------------------------------------------------------------------- /.idea/ant.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/artifacts/PSXperiaTool.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | $PROJECT_DIR$/out/artifacts/PSXperiaTool 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /.idea/copyright/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/libraries/Libraries.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 35 | 36 | http://www.w3.org/1999/xhtml 37 | 38 | 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /PSXperiaTool.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | PSXperia Emulator Converter Tool 2 | 1.0 Release 3 | By Yifan Lu (http://yifan.lu/) 4 | ======================================== 5 | 6 | This tool will take a PSX image that you legally own and convert it to be playable on the Xperia Play with the emulator extracted from the packaged game "Crash Bandicoot." 7 | 8 | If you just want to use the tool, make sure you have Java installed and download the binaries from GitHub (https://github.com/yifanlu/PSXperia/downloads). 9 | Open "PSXperiaTool.jar" or the helper script ("psxperiatool-gui" or "psxperiatool-gui-windows.bat") if you cannot open .jar files. 10 | You can also use the helper scripts "psxperiatool" and "psxperiatool-windows.bat" from the command line for command line mode (see below). 11 | After converting, in the output folder that you selected, you'll find an APK file and a "data" folder. Install the APK on your Xperia Play phone and merge the "data" folder with "Android/data" on the SD card of your phone. 12 | 13 | For detailed directions, check out the wiki: https://github.com/yifanlu/PSXperia/wiki. 14 | 15 | Compiling Instructions 16 | ======================================== 17 | 18 | To compile, you need to copy the following to the "lib" directory 19 | * apktool.jar from http://code.google.com/p/android-apktool/ 20 | * commons-io-2.0.1.jar from http://commons.apache.org/io/download_io.cgi 21 | * sdklib.jar from Android SDK (under tools/lib) 22 | * swing-layout-1.0.4.jar from Netbeans (under platform/modules/ext) 23 | * jbdiff.jar from http://freecode.com/projects/jbdiff 24 | 25 | You also need a copy of "aapt" from Android SDK (under platform-tools) 26 | * OSX version named aapt-osx 27 | * Windows version named aapt-windows.exe 28 | * Linux version named aapt-linux 29 | Put these in the "resources" directory 30 | 31 | Finally, you need my PSXperia wrapper library (compiled) in the "resources" directory 32 | 33 | To run the GUI, use "java -jar PSXperiaTool.jar" 34 | To run the command line tool, use "java -cp PSXperiaTool.jar com.yifanlu.PSXperiaTool.Interface.CommandLine" to see usage directions, which is also listed below for your convenience. 35 | 36 | Usage: 37 | Extract and patch data files 38 | psxperia e[x]tract [-v|--verbose] input.apk input-data.zpak output 39 | [-v|--verbose] Verbose output 40 | input.apk Either com.sony.playstation.ncua94900_1.apk or com.sony.playstation.ncea00344_1.apk 41 | input-data.zpak Either NCUA94900_1_1.zpak or NCEA00344_1_1.zpak (must match region of APK) 42 | output Directory to extract the files 43 | 44 | Convert PSX Image to Xperia Play APK and ZPAK 45 | psxperia [c]onvert [OPTIONS] titleId image.iso output 46 | titleId An unique ID, usually from the game in the format NCXAXXXXX_1 47 | image.iso Input PSX image. Does not have to be an ISO, and valid PSX image will do. You must rip it on your own! 48 | output Directory to output files 49 | Options (unset options will be set to defaults): 50 | -v|--verbose Verbose output, including image creation progress 51 | -D directory Custom location for extracted data files, default is "./data" 52 | --load-xml Load options from Java properties XML 53 | --game-name Name of the game 54 | --description Description of the game 55 | --publisher Publisher of the game 56 | --developer Developer of the game 57 | --icon-file Path to image for icon 58 | --store-type Where to find this title (any string will do) 59 | --analog-mode true|false, Turn on/off analog controls (game must support it). 60 | 61 | Convert image.ps to PSX Image 62 | psxperia [d]ecompress [-v|--verbose] input.ps output.iso 63 | [-v|--verbose] Verbose output 64 | input.ps image.ps from ZPAK 65 | output.iso ISO file to generate 66 | 67 | 68 | -------------------------------------------------------------------------------- /resources/android-framework.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yifanlu/PSXperia/3be12b3ef25daf3d976bac9dac5a74fb709a46be/resources/android-framework.jar -------------------------------------------------------------------------------- /resources/defaults.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Default Strings 5 | All 6 | Publisher 7 | Emulated PSX game. 8 | Developer 9 | PSOne Game 10 | NCXA00000_1 11 | PSOne Game 12 | AMP 13 | NO 14 | false 15 | 16 | -------------------------------------------------------------------------------- /resources/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yifanlu/PSXperia/3be12b3ef25daf3d976bac9dac5a74fb709a46be/resources/icon.png -------------------------------------------------------------------------------- /resources/patches/3B6A23C1/config.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Config File 5 | Crash Bandicoot 6 | 1.0.0 7 | EUR 8 | 3B6A23C1 9 | no 10 | 11 | -------------------------------------------------------------------------------- /resources/patches/6C7C966B/config.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Config File 5 | Crash Bandicoot 6 | 1.0.1 T 7 | EUR 8 | 6C7C966B 9 | libjava-activity_NCEA00344_T_1.so 10 | 94081C77 11 | libjava-activity.so.jbpatch 12 | game-patch.bin 13 | 14 | -------------------------------------------------------------------------------- /resources/patches/6C7C966B/filelist.txt: -------------------------------------------------------------------------------- 1 | /assets/AndroidManifest.xml 2 | /assets/ZPAK/assets/default/bitmaps/default.jpg 3 | /assets/ZPAK/assets/default/bitmaps/icon.png 4 | /assets/ZPAK/assets/ebitmaps/default.jpg 5 | /assets/ZPAK/assets/menu_arrow_left_disable.dds 6 | /assets/ZPAK/assets/menu_arrow_left_normal.dds 7 | /assets/ZPAK/assets/menu_arrow_left_press.dds 8 | /assets/ZPAK/assets/menu_arrow_right_disable.dds 9 | /assets/ZPAK/assets/menu_arrow_right_normal.dds 10 | /assets/ZPAK/assets/menu_arrow_right_press.dds 11 | /assets/ZPAK/assets/menu_assign_controller_1.dds 12 | /assets/ZPAK/assets/menu_assign_controller_2.dds 13 | /assets/ZPAK/assets/menu_assign_controller_3.dds 14 | /assets/ZPAK/assets/menu_assign_controller_4.dds 15 | /assets/ZPAK/assets/menu_assign_controller_5.dds 16 | /assets/ZPAK/assets/menu_assign_controller_6.dds 17 | /assets/ZPAK/assets/menu_button_disable.dds 18 | /assets/ZPAK/assets/menu_button_normal.dds 19 | /assets/ZPAK/assets/menu_button_press.dds 20 | /assets/ZPAK/assets/menu_check_box_active.dds 21 | /assets/ZPAK/assets/menu_check_box_normal.dds 22 | /assets/ZPAK/assets/menu_edit_disable.dds 23 | /assets/ZPAK/assets/menu_edit_normal.dds 24 | /assets/ZPAK/assets/menu_frame_alert.dds 25 | /assets/ZPAK/assets/menu_frame_normal.dds 26 | /assets/ZPAK/assets/menu_frame_selected.dds 27 | /assets/ZPAK/assets/menu_grip_h_normal.dds 28 | /assets/ZPAK/assets/menu_grip_h_press.dds 29 | /assets/ZPAK/assets/menu_grip_v_normal.dds 30 | /assets/ZPAK/assets/menu_grip_v_press.dds 31 | /assets/ZPAK/assets/menu_list_cursor.dds 32 | /assets/ZPAK/assets/menu_list_separator.dds 33 | /assets/ZPAK/assets/menu_panel.dds 34 | /assets/ZPAK/assets/menu_radio_bt_normal.dds 35 | /assets/ZPAK/assets/menu_radio_bt_selected.dds 36 | /assets/ZPAK/assets/menu_separator.dds 37 | /assets/ZPAK/assets/menu_slider.dds 38 | /assets/ZPAK/assets/menu_slider_bar_active.dds 39 | /assets/ZPAK/assets/menu_slider_bar_disable.dds 40 | /assets/ZPAK/assets/menu_slider_bar_normal.dds 41 | /assets/ZPAK/assets/menu_slider_disable.dds 42 | /assets/ZPAK/assets/menu_slider_press.dds 43 | /assets/ZPAK/assets/menu_stat_sys_battery_0.dds 44 | /assets/ZPAK/assets/menu_stat_sys_battery_10.dds 45 | /assets/ZPAK/assets/menu_stat_sys_battery_100.dds 46 | /assets/ZPAK/assets/menu_stat_sys_battery_20.dds 47 | /assets/ZPAK/assets/menu_stat_sys_battery_40.dds 48 | /assets/ZPAK/assets/menu_stat_sys_battery_60.dds 49 | /assets/ZPAK/assets/menu_stat_sys_battery_80.dds 50 | /assets/ZPAK/assets/menu_stat_sys_battery_charge_anim0.dds 51 | /assets/ZPAK/assets/menu_stat_sys_battery_charge_anim1.dds 52 | /assets/ZPAK/assets/menu_stat_sys_battery_charge_anim2.dds 53 | /assets/ZPAK/assets/menu_stat_sys_battery_charge_anim3.dds 54 | /assets/ZPAK/assets/menu_stat_sys_battery_charge_anim4.dds 55 | /assets/ZPAK/assets/menu_stat_sys_battery_charge_anim5.dds 56 | /assets/ZPAK/assets/menu_stat_sys_battery_unknown.dds 57 | /assets/ZPAK/assets/menu_status_area.dds 58 | /assets/ZPAK/assets/menu_text_bg.dds 59 | /assets/ZPAK/assets/menu_title_icon.dds 60 | /assets/ZPAK/assets/menu_title_separator.dds 61 | /assets/ZPAK/assets/menu_warning.dds 62 | /assets/ZPAK/assets/menu_warning_e_de.dds 63 | /assets/ZPAK/assets/menu_warning_e_en.dds 64 | /assets/ZPAK/assets/menu_warning_e_es.dds 65 | /assets/ZPAK/assets/menu_warning_e_fr.dds 66 | /assets/ZPAK/assets/menu_warning_e_it.dds 67 | /assets/ZPAK/assets/menu_warning_j-1024x480.dds 68 | /assets/ZPAK/assets/menu_yellow_frame.dds 69 | /assets/ZPAK/data/params.bin 70 | /assets/ZPAK/metadata.xml 71 | /classes.dex 72 | /config/config.xml 73 | /config/filelist.txt 74 | /config/game-patch.bin 75 | /config/stringReplacements.txt 76 | /lib/armeabi/libjava-activity-patched.so 77 | /lib/armeabi/libjava-activity_NCEA00344_T_1.so 78 | /lib/armeabi/libzplatform_o1.so 79 | /res/drawable/controller_icon.png 80 | /res/drawable/custom_horizontal.xml 81 | /res/drawable/icon.png 82 | /res/drawable/title_icon.png 83 | /res/layout/cn.xml 84 | /res/layout/download_alert_dialog_progress.xml 85 | /res/layout/download_progress_dialog.xml 86 | /res/layout/manualview.xml 87 | /res/values/ids.xml 88 | /res/values/public.xml 89 | /res/values/strings.xml 90 | /res/values/styles.xml 91 | /res/values-cs-rCZ/strings.xml 92 | /res/values-da-rDK/strings.xml 93 | /res/values-de/strings.xml 94 | /res/values-el-rGR/strings.xml 95 | /res/values-en-rGB/strings.xml 96 | /res/values-es/strings.xml 97 | /res/values-es-rUS/strings.xml 98 | /res/values-fi-rFI/strings.xml 99 | /res/values-fr/strings.xml 100 | /res/values-it/strings.xml 101 | /res/values-ja-rJP/strings.xml 102 | /res/values-ko/strings.xml 103 | /res/values-nb-rNO/strings.xml 104 | /res/values-nl-rNL/strings.xml 105 | /res/values-pl-rPL/strings.xml 106 | /res/values-pt/strings.xml 107 | /res/values-pt-rPT/strings.xml 108 | /res/values-ru/strings.xml 109 | /res/values-sv-rSE/strings.xml 110 | /res/values-zh-rCN/strings.xml 111 | /res/values-zh-rTW/strings.xml 112 | /resources.arsc 113 | /ZPAK/data/ps1_rom.bin 114 | /ZPAK/metadata.xml 115 | -------------------------------------------------------------------------------- /resources/patches/6C7C966B/game-patch.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yifanlu/PSXperia/3be12b3ef25daf3d976bac9dac5a74fb709a46be/resources/patches/6C7C966B/game-patch.bin -------------------------------------------------------------------------------- /resources/patches/6C7C966B/libjava-activity.so.jbpatch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yifanlu/PSXperia/3be12b3ef25daf3d976bac9dac5a74fb709a46be/resources/patches/6C7C966B/libjava-activity.so.jbpatch -------------------------------------------------------------------------------- /resources/patches/6C7C966B/stringReplacements.txt: -------------------------------------------------------------------------------- 1 | com\.sony\.playstation\.[a-zA-Z0-9_]+ 2 | com\.sony\.playstation\.\{TITLE_ID\} 3 | parental_rating=\".*\" 4 | parental_rating=\"\{PARENTAL_RATING\}\" 5 | parental_control=\".*\" 6 | parental_control=\"\{PARENTAL_RATING\}\" 7 | \.*\ 8 | \{ANALOG_MODE}\ 9 | \.*\ 10 | \\{FILTERED_PUBLISHER\}\ 11 | \.*\ 12 | \\{FILTERED_DEVELOPER\}\ 13 | \.*\ 14 | \\{FILTERED_DISPLAY_NAME\}\ 15 | \.*\ 16 | \\{FILTERED_TITLE\}\ 17 | \.*\ 18 | \\{FILTERED_DESCRIPTION\}\ 19 | \.*\ 20 | \\{FILTERED_PUBLISHER\}\ 21 | \.*\ 22 | \\{FILTERED_DEVELOPER\}\ 23 | \.*\ 24 | \\{TITLE_ID\}\ 25 | \.*\ 26 | \\{STORE_TYPE\}\ 27 | \.*\ 28 | \\{PARENTAL_RATING\}\ 29 | \true\ 30 | \\{CONTAINS_MANUAL\}\ 31 | \.*\ 32 | \file:///sdcard/Android/data/com.sony.playstation.\{TITLE_ID\}/files/content/\{TITLE_ID\}.zpak\ 33 | \.*\ 34 | \\{FILTERED_DISPLAY_NAME\}\ 35 | \.*\ 36 | \\{FILTERED_DESCRIPTION\}\ 37 | -------------------------------------------------------------------------------- /resources/patches/76C201D8/config.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Config File 5 | Crash Bandicoot 6 | 1.0.3 7 | USA 8 | 76C201D8 9 | libjava-activity.so 10 | ED6AEC44 11 | libjava-activity.so.jbpatch 12 | game-patch.bin 13 | 14 | -------------------------------------------------------------------------------- /resources/patches/76C201D8/filelist.txt: -------------------------------------------------------------------------------- 1 | /config/config.xml 2 | /config/game-patch.bin 3 | /assets/AndroidManifest.xml 4 | /assets/ZPAK/assets/default/bitmaps/default.jpg 5 | /assets/ZPAK/assets/default/bitmaps/icon.png 6 | /assets/ZPAK/assets/ebitmaps/default.jpg 7 | /assets/ZPAK/assets/menu_arrow_left_disable.dds 8 | /assets/ZPAK/assets/menu_arrow_left_normal.dds 9 | /assets/ZPAK/assets/menu_arrow_left_press.dds 10 | /assets/ZPAK/assets/menu_arrow_right_disable.dds 11 | /assets/ZPAK/assets/menu_arrow_right_normal.dds 12 | /assets/ZPAK/assets/menu_arrow_right_press.dds 13 | /assets/ZPAK/assets/menu_assign_controller_1.dds 14 | /assets/ZPAK/assets/menu_assign_controller_2.dds 15 | /assets/ZPAK/assets/menu_assign_controller_3.dds 16 | /assets/ZPAK/assets/menu_assign_controller_4.dds 17 | /assets/ZPAK/assets/menu_assign_controller_5.dds 18 | /assets/ZPAK/assets/menu_assign_controller_6.dds 19 | /assets/ZPAK/assets/menu_button_normal.dds 20 | /assets/ZPAK/assets/menu_button_press.dds 21 | /assets/ZPAK/assets/menu_check_box_active.dds 22 | /assets/ZPAK/assets/menu_check_box_normal.dds 23 | /assets/ZPAK/assets/menu_list_cursor.dds 24 | /assets/ZPAK/assets/menu_list_separator.dds 25 | /assets/ZPAK/assets/menu_panel.dds 26 | /assets/ZPAK/assets/menu_radio_bt_normal.dds 27 | /assets/ZPAK/assets/menu_radio_bt_selected.dds 28 | /assets/ZPAK/assets/menu_separator.dds 29 | /assets/ZPAK/assets/menu_slider.dds 30 | /assets/ZPAK/assets/menu_slider_bar_active.dds 31 | /assets/ZPAK/assets/menu_slider_bar_normal.dds 32 | /assets/ZPAK/assets/menu_slider_press.dds 33 | /assets/ZPAK/assets/menu_stat_sys_battery_0.dds 34 | /assets/ZPAK/assets/menu_stat_sys_battery_10.dds 35 | /assets/ZPAK/assets/menu_stat_sys_battery_100.dds 36 | /assets/ZPAK/assets/menu_stat_sys_battery_20.dds 37 | /assets/ZPAK/assets/menu_stat_sys_battery_40.dds 38 | /assets/ZPAK/assets/menu_stat_sys_battery_60.dds 39 | /assets/ZPAK/assets/menu_stat_sys_battery_80.dds 40 | /assets/ZPAK/assets/menu_stat_sys_battery_charge_anim0.dds 41 | /assets/ZPAK/assets/menu_stat_sys_battery_charge_anim1.dds 42 | /assets/ZPAK/assets/menu_stat_sys_battery_charge_anim2.dds 43 | /assets/ZPAK/assets/menu_stat_sys_battery_charge_anim3.dds 44 | /assets/ZPAK/assets/menu_stat_sys_battery_charge_anim4.dds 45 | /assets/ZPAK/assets/menu_stat_sys_battery_charge_anim5.dds 46 | /assets/ZPAK/assets/menu_stat_sys_battery_unknown.dds 47 | /assets/ZPAK/assets/menu_status_area.dds 48 | /assets/ZPAK/assets/menu_text_bg.dds 49 | /assets/ZPAK/assets/menu_title_icon.dds 50 | /assets/ZPAK/assets/menu_title_separator.dds 51 | /assets/ZPAK/assets/menu_warning.dds 52 | /assets/ZPAK/assets/menu_warning_j.dds 53 | /assets/ZPAK/assets/menu_warning_e_de.dds 54 | /assets/ZPAK/assets/menu_warning_e_en.dds 55 | /assets/ZPAK/assets/menu_warning_e_es.dds 56 | /assets/ZPAK/assets/menu_warning_e_fr.dds 57 | /assets/ZPAK/assets/menu_warning_e_it.dds 58 | /assets/ZPAK/assets/menu_yellow_frame.dds 59 | /assets/ZPAK/assets/menu_yellow_grip_normal.dds 60 | /assets/ZPAK/assets/menu_yellow_grip_pressed.dds 61 | /assets/ZPAK/data/params.bin 62 | /assets/ZPAK/metadata.xml 63 | /classes.dex 64 | /lib/armeabi/libjava-activity-patched.so 65 | /lib/armeabi/libjava-activity.so 66 | /lib/armeabi/libzplatform.so 67 | /res/drawable/controller_icon.png 68 | /res/drawable/custom_horizontal.xml 69 | /res/drawable/icon.png 70 | /res/drawable/title_icon.png 71 | /res/layout/cn.xml 72 | /res/layout/download_alert_dialog_progress.xml 73 | /res/layout/download_progress_dialog.xml 74 | /res/layout/manualview.xml 75 | /res/values/ids.xml 76 | /res/values/public.xml 77 | /res/values/strings.xml 78 | /res/values/styles.xml 79 | /res/values-cs-rCZ/strings.xml 80 | /res/values-da-rDK/strings.xml 81 | /res/values-de/strings.xml 82 | /res/values-el-rGR/strings.xml 83 | /res/values-en-rGB/strings.xml 84 | /res/values-es/strings.xml 85 | /res/values-es-rUS/strings.xml 86 | /res/values-fi-rFI/strings.xml 87 | /res/values-fr/strings.xml 88 | /res/values-it/strings.xml 89 | /res/values-ja-rJP/strings.xml 90 | /res/values-ko/strings.xml 91 | /res/values-nb-rNO/strings.xml 92 | /res/values-nl-rNL/strings.xml 93 | /res/values-pl-rPL/strings.xml 94 | /res/values-pt/strings.xml 95 | /res/values-pt-rPT/strings.xml 96 | /res/values-ru/strings.xml 97 | /res/values-sv-rSE/strings.xml 98 | /res/values-zh-rCN/strings.xml 99 | /res/values-zh-rTW/strings.xml 100 | /ZPAK/data/ps1_rom.bin 101 | /ZPAK/metadata.xml 102 | -------------------------------------------------------------------------------- /resources/patches/76C201D8/game-patch.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yifanlu/PSXperia/3be12b3ef25daf3d976bac9dac5a74fb709a46be/resources/patches/76C201D8/game-patch.bin -------------------------------------------------------------------------------- /resources/patches/76C201D8/libjava-activity.so.jbpatch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yifanlu/PSXperia/3be12b3ef25daf3d976bac9dac5a74fb709a46be/resources/patches/76C201D8/libjava-activity.so.jbpatch -------------------------------------------------------------------------------- /resources/patches/76C201D8/stringReplacements.txt: -------------------------------------------------------------------------------- 1 | com\.sony\.playstation\.[a-zA-Z0-9_]+ 2 | com\.sony\.playstation\.\{TITLE_ID\} 3 | parental_rating=\".*\" 4 | parental_rating=\"\{PARENTAL_RATING\}\" 5 | parental_control=\".*\" 6 | parental_control=\"\{PARENTAL_RATING\}\" 7 | \.*\ 8 | \{ANALOG_MODE}\ 9 | \.*\ 10 | \\{FILTERED_PUBLISHER\}\ 11 | \.*\ 12 | \\{FILTERED_DEVELOPER\}\ 13 | \.*\ 14 | \\{FILTERED_DISPLAY_NAME\}\ 15 | \.*\ 16 | \\{FILTERED_TITLE\}\ 17 | \.*\ 18 | \\{FILTERED_DESCRIPTION\}\ 19 | \.*\ 20 | \\{FILTERED_PUBLISHER\}\ 21 | \.*\ 22 | \\{FILTERED_DEVELOPER\}\ 23 | \.*\ 24 | \\{TITLE_ID\}\ 25 | \.*\ 26 | \\{STORE_TYPE\}\ 27 | \.*\ 28 | \\{PARENTAL_RATING\}\ 29 | \true\ 30 | \\{CONTAINS_MANUAL\}\ 31 | \.*\ 32 | \file:///sdcard/Android/data/com.sony.playstation.\{TITLE_ID\}/files/content/\{TITLE_ID\}.zpak\ 33 | \.*\ 34 | \\{FILTERED_DISPLAY_NAME\}\ 35 | \.*\ 36 | \\{FILTERED_DESCRIPTION\}\ 37 | -------------------------------------------------------------------------------- /resources/patches/7C33475B/config.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Config File 5 | Crash Bandicoot 6 | 1.0.3 7 | EUR 8 | 7C33475B 9 | libjava-activity.so 10 | ADB184B5 11 | libjava-activity.so.jbpatch 12 | game-patch.bin 13 | 14 | -------------------------------------------------------------------------------- /resources/patches/7C33475B/filelist.txt: -------------------------------------------------------------------------------- 1 | /config/config.xml 2 | /config/game-patch.bin 3 | /assets/AndroidManifest.xml 4 | /assets/ZPAK/assets/default/bitmaps/default.jpg 5 | /assets/ZPAK/assets/default/bitmaps/icon.png 6 | /assets/ZPAK/assets/ebitmaps/default.jpg 7 | /assets/ZPAK/assets/menu_arrow_left_disable.dds 8 | /assets/ZPAK/assets/menu_arrow_left_normal.dds 9 | /assets/ZPAK/assets/menu_arrow_left_press.dds 10 | /assets/ZPAK/assets/menu_arrow_right_disable.dds 11 | /assets/ZPAK/assets/menu_arrow_right_normal.dds 12 | /assets/ZPAK/assets/menu_arrow_right_press.dds 13 | /assets/ZPAK/assets/menu_assign_controller_1.dds 14 | /assets/ZPAK/assets/menu_assign_controller_2.dds 15 | /assets/ZPAK/assets/menu_assign_controller_3.dds 16 | /assets/ZPAK/assets/menu_assign_controller_4.dds 17 | /assets/ZPAK/assets/menu_assign_controller_5.dds 18 | /assets/ZPAK/assets/menu_assign_controller_6.dds 19 | /assets/ZPAK/assets/menu_button_normal.dds 20 | /assets/ZPAK/assets/menu_button_press.dds 21 | /assets/ZPAK/assets/menu_check_box_active.dds 22 | /assets/ZPAK/assets/menu_check_box_normal.dds 23 | /assets/ZPAK/assets/menu_list_cursor.dds 24 | /assets/ZPAK/assets/menu_list_separator.dds 25 | /assets/ZPAK/assets/menu_panel.dds 26 | /assets/ZPAK/assets/menu_radio_bt_normal.dds 27 | /assets/ZPAK/assets/menu_radio_bt_selected.dds 28 | /assets/ZPAK/assets/menu_separator.dds 29 | /assets/ZPAK/assets/menu_slider.dds 30 | /assets/ZPAK/assets/menu_slider_bar_active.dds 31 | /assets/ZPAK/assets/menu_slider_bar_normal.dds 32 | /assets/ZPAK/assets/menu_slider_press.dds 33 | /assets/ZPAK/assets/menu_stat_sys_battery_0.dds 34 | /assets/ZPAK/assets/menu_stat_sys_battery_10.dds 35 | /assets/ZPAK/assets/menu_stat_sys_battery_100.dds 36 | /assets/ZPAK/assets/menu_stat_sys_battery_20.dds 37 | /assets/ZPAK/assets/menu_stat_sys_battery_40.dds 38 | /assets/ZPAK/assets/menu_stat_sys_battery_60.dds 39 | /assets/ZPAK/assets/menu_stat_sys_battery_80.dds 40 | /assets/ZPAK/assets/menu_stat_sys_battery_charge_anim0.dds 41 | /assets/ZPAK/assets/menu_stat_sys_battery_charge_anim1.dds 42 | /assets/ZPAK/assets/menu_stat_sys_battery_charge_anim2.dds 43 | /assets/ZPAK/assets/menu_stat_sys_battery_charge_anim3.dds 44 | /assets/ZPAK/assets/menu_stat_sys_battery_charge_anim4.dds 45 | /assets/ZPAK/assets/menu_stat_sys_battery_charge_anim5.dds 46 | /assets/ZPAK/assets/menu_stat_sys_battery_unknown.dds 47 | /assets/ZPAK/assets/menu_status_area.dds 48 | /assets/ZPAK/assets/menu_text_bg.dds 49 | /assets/ZPAK/assets/menu_title_icon.dds 50 | /assets/ZPAK/assets/menu_title_separator.dds 51 | /assets/ZPAK/assets/menu_warning.dds 52 | /assets/ZPAK/assets/menu_warning_j.dds 53 | /assets/ZPAK/assets/menu_warning_e_de.dds 54 | /assets/ZPAK/assets/menu_warning_e_en.dds 55 | /assets/ZPAK/assets/menu_warning_e_es.dds 56 | /assets/ZPAK/assets/menu_warning_e_fr.dds 57 | /assets/ZPAK/assets/menu_warning_e_it.dds 58 | /assets/ZPAK/assets/menu_yellow_frame.dds 59 | /assets/ZPAK/assets/menu_yellow_grip_normal.dds 60 | /assets/ZPAK/assets/menu_yellow_grip_pressed.dds 61 | /assets/ZPAK/data/params.bin 62 | /assets/ZPAK/metadata.xml 63 | /classes.dex 64 | /lib/armeabi/libjava-activity-patched.so 65 | /lib/armeabi/libjava-activity.so 66 | /lib/armeabi/libzplatform.so 67 | /res/drawable/controller_icon.png 68 | /res/drawable/custom_horizontal.xml 69 | /res/drawable/icon.png 70 | /res/drawable/title_icon.png 71 | /res/layout/cn.xml 72 | /res/layout/download_alert_dialog_progress.xml 73 | /res/layout/download_progress_dialog.xml 74 | /res/layout/manualview.xml 75 | /res/values/ids.xml 76 | /res/values/public.xml 77 | /res/values/strings.xml 78 | /res/values/styles.xml 79 | /res/values-cs-rCZ/strings.xml 80 | /res/values-da-rDK/strings.xml 81 | /res/values-de/strings.xml 82 | /res/values-el-rGR/strings.xml 83 | /res/values-en-rGB/strings.xml 84 | /res/values-es/strings.xml 85 | /res/values-es-rUS/strings.xml 86 | /res/values-fi-rFI/strings.xml 87 | /res/values-fr/strings.xml 88 | /res/values-it/strings.xml 89 | /res/values-ja-rJP/strings.xml 90 | /res/values-ko/strings.xml 91 | /res/values-nb-rNO/strings.xml 92 | /res/values-nl-rNL/strings.xml 93 | /res/values-pl-rPL/strings.xml 94 | /res/values-pt/strings.xml 95 | /res/values-pt-rPT/strings.xml 96 | /res/values-ru/strings.xml 97 | /res/values-sv-rSE/strings.xml 98 | /res/values-zh-rCN/strings.xml 99 | /res/values-zh-rTW/strings.xml 100 | /ZPAK/data/ps1_rom.bin 101 | /ZPAK/metadata.xml 102 | -------------------------------------------------------------------------------- /resources/patches/7C33475B/game-patch.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yifanlu/PSXperia/3be12b3ef25daf3d976bac9dac5a74fb709a46be/resources/patches/7C33475B/game-patch.bin -------------------------------------------------------------------------------- /resources/patches/7C33475B/libjava-activity.so.jbpatch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yifanlu/PSXperia/3be12b3ef25daf3d976bac9dac5a74fb709a46be/resources/patches/7C33475B/libjava-activity.so.jbpatch -------------------------------------------------------------------------------- /resources/patches/7C33475B/stringReplacements.txt: -------------------------------------------------------------------------------- 1 | com\.sony\.playstation\.[a-zA-Z0-9_]+ 2 | com\.sony\.playstation\.\{TITLE_ID\} 3 | parental_rating=\".*\" 4 | parental_rating=\"\{PARENTAL_RATING\}\" 5 | parental_control=\".*\" 6 | parental_control=\"\{PARENTAL_RATING\}\" 7 | \.*\ 8 | \{ANALOG_MODE}\ 9 | \.*\ 10 | \\{FILTERED_PUBLISHER\}\ 11 | \.*\ 12 | \\{FILTERED_DEVELOPER\}\ 13 | \.*\ 14 | \\{FILTERED_DISPLAY_NAME\}\ 15 | \.*\ 16 | \\{FILTERED_TITLE\}\ 17 | \.*\ 18 | \\{FILTERED_DESCRIPTION\}\ 19 | \.*\ 20 | \\{FILTERED_PUBLISHER\}\ 21 | \.*\ 22 | \\{FILTERED_DEVELOPER\}\ 23 | \.*\ 24 | \\{TITLE_ID\}\ 25 | \.*\ 26 | \\{STORE_TYPE\}\ 27 | \.*\ 28 | \\{PARENTAL_RATING\}\ 29 | \true\ 30 | \\{CONTAINS_MANUAL\}\ 31 | \.*\ 32 | \file:///sdcard/Android/data/com.sony.playstation.\{TITLE_ID\}/files/content/\{TITLE_ID\}.zpak\ 33 | \.*\ 34 | \\{FILTERED_DISPLAY_NAME\}\ 35 | \.*\ 36 | \\{FILTERED_DESCRIPTION\}\ 37 | -------------------------------------------------------------------------------- /resources/patches/BB542581/config.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Config File 5 | Crash Bandicoot 6 | 1.0.1 7 | EUR 8 | BB542581 9 | libjava-activity.so 10 | A4D2788D 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /resources/patches/BB542581/filelist.txt: -------------------------------------------------------------------------------- 1 | /assets/AndroidManifest.xml 2 | /assets/ZPAK/assets/default/bitmaps/default.jpg 3 | /assets/ZPAK/assets/default/bitmaps/icon.png 4 | /assets/ZPAK/assets/ebitmaps/default.jpg 5 | /assets/ZPAK/assets/menu_arrow_left_disable.dds 6 | /assets/ZPAK/assets/menu_arrow_left_normal.dds 7 | /assets/ZPAK/assets/menu_arrow_left_press.dds 8 | /assets/ZPAK/assets/menu_arrow_right_disable.dds 9 | /assets/ZPAK/assets/menu_arrow_right_normal.dds 10 | /assets/ZPAK/assets/menu_arrow_right_press.dds 11 | /assets/ZPAK/assets/menu_assign_controller_1.dds 12 | /assets/ZPAK/assets/menu_assign_controller_2.dds 13 | /assets/ZPAK/assets/menu_assign_controller_3.dds 14 | /assets/ZPAK/assets/menu_assign_controller_4.dds 15 | /assets/ZPAK/assets/menu_assign_controller_5.dds 16 | /assets/ZPAK/assets/menu_assign_controller_6.dds 17 | /assets/ZPAK/assets/menu_button_normal.dds 18 | /assets/ZPAK/assets/menu_button_press.dds 19 | /assets/ZPAK/assets/menu_check_box_active.dds 20 | /assets/ZPAK/assets/menu_check_box_normal.dds 21 | /assets/ZPAK/assets/menu_list_cursor.dds 22 | /assets/ZPAK/assets/menu_list_separator.dds 23 | /assets/ZPAK/assets/menu_panel.dds 24 | /assets/ZPAK/assets/menu_radio_bt_normal.dds 25 | /assets/ZPAK/assets/menu_radio_bt_selected.dds 26 | /assets/ZPAK/assets/menu_separator.dds 27 | /assets/ZPAK/assets/menu_slider.dds 28 | /assets/ZPAK/assets/menu_slider_bar_active.dds 29 | /assets/ZPAK/assets/menu_slider_bar_normal.dds 30 | /assets/ZPAK/assets/menu_slider_press.dds 31 | /assets/ZPAK/assets/menu_stat_sys_battery_0.dds 32 | /assets/ZPAK/assets/menu_stat_sys_battery_10.dds 33 | /assets/ZPAK/assets/menu_stat_sys_battery_100.dds 34 | /assets/ZPAK/assets/menu_stat_sys_battery_20.dds 35 | /assets/ZPAK/assets/menu_stat_sys_battery_40.dds 36 | /assets/ZPAK/assets/menu_stat_sys_battery_60.dds 37 | /assets/ZPAK/assets/menu_stat_sys_battery_80.dds 38 | /assets/ZPAK/assets/menu_stat_sys_battery_charge_anim0.dds 39 | /assets/ZPAK/assets/menu_stat_sys_battery_charge_anim1.dds 40 | /assets/ZPAK/assets/menu_stat_sys_battery_charge_anim2.dds 41 | /assets/ZPAK/assets/menu_stat_sys_battery_charge_anim3.dds 42 | /assets/ZPAK/assets/menu_stat_sys_battery_charge_anim4.dds 43 | /assets/ZPAK/assets/menu_stat_sys_battery_charge_anim5.dds 44 | /assets/ZPAK/assets/menu_stat_sys_battery_unknown.dds 45 | /assets/ZPAK/assets/menu_status_area.dds 46 | /assets/ZPAK/assets/menu_text_bg.dds 47 | /assets/ZPAK/assets/menu_title_icon.dds 48 | /assets/ZPAK/assets/menu_title_separator.dds 49 | /assets/ZPAK/assets/menu_warning.dds 50 | /assets/ZPAK/assets/menu_warning_e_de.dds 51 | /assets/ZPAK/assets/menu_warning_e_en.dds 52 | /assets/ZPAK/assets/menu_warning_e_es.dds 53 | /assets/ZPAK/assets/menu_warning_e_fr.dds 54 | /assets/ZPAK/assets/menu_warning_e_it.dds 55 | /assets/ZPAK/assets/menu_yellow_frame.dds 56 | /assets/ZPAK/assets/menu_yellow_grip_normal.dds 57 | /assets/ZPAK/assets/menu_yellow_grip_pressed.dds 58 | /assets/ZPAK/data/params.bin 59 | /assets/ZPAK/metadata.xml 60 | /classes.dex 61 | /lib/armeabi/libjava-activity-patched.so 62 | /lib/armeabi/libjava-activity.so 63 | /lib/armeabi/libzplatform.so 64 | /res/drawable/controller_icon.png 65 | /res/drawable/custom_horizontal.xml 66 | /res/drawable/icon.png 67 | /res/drawable/title_icon.png 68 | /res/layout/cn.xml 69 | /res/layout/download_alert_dialog_progress.xml 70 | /res/layout/download_progress_dialog.xml 71 | /res/layout/manualview.xml 72 | /res/values/ids.xml 73 | /res/values/public.xml 74 | /res/values/strings.xml 75 | /res/values/styles.xml 76 | /res/values-cs-rCZ/strings.xml 77 | /res/values-da-rDK/strings.xml 78 | /res/values-de/strings.xml 79 | /res/values-el-rGR/strings.xml 80 | /res/values-en-rGB/strings.xml 81 | /res/values-es/strings.xml 82 | /res/values-es-rUS/strings.xml 83 | /res/values-fi-rFI/strings.xml 84 | /res/values-fr/strings.xml 85 | /res/values-it/strings.xml 86 | /res/values-ja-rJP/strings.xml 87 | /res/values-ko/strings.xml 88 | /res/values-nb-rNO/strings.xml 89 | /res/values-nl-rNL/strings.xml 90 | /res/values-pl-rPL/strings.xml 91 | /res/values-pt/strings.xml 92 | /res/values-pt-rPT/strings.xml 93 | /res/values-ru/strings.xml 94 | /res/values-sv-rSE/strings.xml 95 | /res/values-zh-rCN/strings.xml 96 | /res/values-zh-rTW/strings.xml 97 | /ZPAK/data/ps1_rom.bin 98 | /ZPAK/metadata.xml 99 | -------------------------------------------------------------------------------- /resources/patches/BB542581/stringReplacements.txt: -------------------------------------------------------------------------------- 1 | com\.sony\.playstation\.[a-zA-Z0-9_]+ 2 | com\.sony\.playstation\.\{TITLE_ID\} 3 | parental_rating=\".*\" 4 | parental_rating=\"\{PARENTAL_RATING\}\" 5 | parental_control=\".*\" 6 | parental_control=\"\{PARENTAL_RATING\}\" 7 | \.*\ 8 | \{ANALOG_MODE}\ 9 | \.*\ 10 | \\{FILTERED_PUBLISHER\}\ 11 | \.*\ 12 | \\{FILTERED_DEVELOPER\}\ 13 | \.*\ 14 | \\{FILTERED_DISPLAY_NAME\}\ 15 | \.*\ 16 | \\{FILTERED_TITLE\}\ 17 | \.*\ 18 | \\{FILTERED_DESCRIPTION\}\ 19 | \.*\ 20 | \\{FILTERED_PUBLISHER\}\ 21 | \.*\ 22 | \\{FILTERED_DEVELOPER\}\ 23 | \.*\ 24 | \\{TITLE_ID\}\ 25 | \.*\ 26 | \\{STORE_TYPE\}\ 27 | \.*\ 28 | \\{PARENTAL_RATING\}\ 29 | \true\ 30 | \\{CONTAINS_MANUAL\}\ 31 | \.*\ 32 | \file:///sdcard/Android/data/com.sony.playstation.\{TITLE_ID\}/files/content/\{TITLE_ID\}.zpak\ 33 | \.*\ 34 | \\{FILTERED_DISPLAY_NAME\}\ 35 | \.*\ 36 | \\{FILTERED_DESCRIPTION\}\ 37 | -------------------------------------------------------------------------------- /resources/patches/E7BCB6D5/config.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Config File 5 | Crash Bandicoot 6 | 1.0.1 7 | USA 8 | E7BCB6D5 9 | libjava-activity.so 10 | CB990C5D 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /resources/patches/E7BCB6D5/filelist.txt: -------------------------------------------------------------------------------- 1 | /assets/AndroidManifest.xml 2 | /assets/ZPAK/assets/default/bitmaps/default.jpg 3 | /assets/ZPAK/assets/default/bitmaps/icon.png 4 | /assets/ZPAK/assets/ebitmaps/default.jpg 5 | /assets/ZPAK/assets/menu_arrow_left_disable.dds 6 | /assets/ZPAK/assets/menu_arrow_left_normal.dds 7 | /assets/ZPAK/assets/menu_arrow_left_press.dds 8 | /assets/ZPAK/assets/menu_arrow_right_disable.dds 9 | /assets/ZPAK/assets/menu_arrow_right_normal.dds 10 | /assets/ZPAK/assets/menu_arrow_right_press.dds 11 | /assets/ZPAK/assets/menu_assign_controller_1.dds 12 | /assets/ZPAK/assets/menu_assign_controller_2.dds 13 | /assets/ZPAK/assets/menu_assign_controller_3.dds 14 | /assets/ZPAK/assets/menu_assign_controller_4.dds 15 | /assets/ZPAK/assets/menu_assign_controller_5.dds 16 | /assets/ZPAK/assets/menu_assign_controller_6.dds 17 | /assets/ZPAK/assets/menu_button_normal.dds 18 | /assets/ZPAK/assets/menu_button_press.dds 19 | /assets/ZPAK/assets/menu_check_box_active.dds 20 | /assets/ZPAK/assets/menu_check_box_normal.dds 21 | /assets/ZPAK/assets/menu_list_cursor.dds 22 | /assets/ZPAK/assets/menu_list_separator.dds 23 | /assets/ZPAK/assets/menu_panel.dds 24 | /assets/ZPAK/assets/menu_radio_bt_normal.dds 25 | /assets/ZPAK/assets/menu_radio_bt_selected.dds 26 | /assets/ZPAK/assets/menu_separator.dds 27 | /assets/ZPAK/assets/menu_slider.dds 28 | /assets/ZPAK/assets/menu_slider_bar_active.dds 29 | /assets/ZPAK/assets/menu_slider_bar_normal.dds 30 | /assets/ZPAK/assets/menu_slider_press.dds 31 | /assets/ZPAK/assets/menu_stat_sys_battery_0.dds 32 | /assets/ZPAK/assets/menu_stat_sys_battery_10.dds 33 | /assets/ZPAK/assets/menu_stat_sys_battery_100.dds 34 | /assets/ZPAK/assets/menu_stat_sys_battery_20.dds 35 | /assets/ZPAK/assets/menu_stat_sys_battery_40.dds 36 | /assets/ZPAK/assets/menu_stat_sys_battery_60.dds 37 | /assets/ZPAK/assets/menu_stat_sys_battery_80.dds 38 | /assets/ZPAK/assets/menu_stat_sys_battery_charge_anim0.dds 39 | /assets/ZPAK/assets/menu_stat_sys_battery_charge_anim1.dds 40 | /assets/ZPAK/assets/menu_stat_sys_battery_charge_anim2.dds 41 | /assets/ZPAK/assets/menu_stat_sys_battery_charge_anim3.dds 42 | /assets/ZPAK/assets/menu_stat_sys_battery_charge_anim4.dds 43 | /assets/ZPAK/assets/menu_stat_sys_battery_charge_anim5.dds 44 | /assets/ZPAK/assets/menu_stat_sys_battery_unknown.dds 45 | /assets/ZPAK/assets/menu_status_area.dds 46 | /assets/ZPAK/assets/menu_text_bg.dds 47 | /assets/ZPAK/assets/menu_title_icon.dds 48 | /assets/ZPAK/assets/menu_title_separator.dds 49 | /assets/ZPAK/assets/menu_warning.dds 50 | /assets/ZPAK/assets/menu_warning_e_de.dds 51 | /assets/ZPAK/assets/menu_warning_e_en.dds 52 | /assets/ZPAK/assets/menu_warning_e_es.dds 53 | /assets/ZPAK/assets/menu_warning_e_fr.dds 54 | /assets/ZPAK/assets/menu_warning_e_it.dds 55 | /assets/ZPAK/assets/menu_yellow_frame.dds 56 | /assets/ZPAK/assets/menu_yellow_grip_normal.dds 57 | /assets/ZPAK/assets/menu_yellow_grip_pressed.dds 58 | /assets/ZPAK/data/params.bin 59 | /assets/ZPAK/metadata.xml 60 | /classes.dex 61 | /lib/armeabi/libjava-activity-patched.so 62 | /lib/armeabi/libjava-activity.so 63 | /lib/armeabi/libzplatform.so 64 | /res/drawable/controller_icon.png 65 | /res/drawable/custom_horizontal.xml 66 | /res/drawable/icon.png 67 | /res/drawable/title_icon.png 68 | /res/layout/cn.xml 69 | /res/layout/download_alert_dialog_progress.xml 70 | /res/layout/download_progress_dialog.xml 71 | /res/layout/manualview.xml 72 | /res/values/ids.xml 73 | /res/values/public.xml 74 | /res/values/strings.xml 75 | /res/values/styles.xml 76 | /res/values-cs-rCZ/strings.xml 77 | /res/values-da-rDK/strings.xml 78 | /res/values-de/strings.xml 79 | /res/values-el-rGR/strings.xml 80 | /res/values-en-rGB/strings.xml 81 | /res/values-es/strings.xml 82 | /res/values-es-rUS/strings.xml 83 | /res/values-fi-rFI/strings.xml 84 | /res/values-fr/strings.xml 85 | /res/values-it/strings.xml 86 | /res/values-ja-rJP/strings.xml 87 | /res/values-ko/strings.xml 88 | /res/values-nb-rNO/strings.xml 89 | /res/values-nl-rNL/strings.xml 90 | /res/values-pl-rPL/strings.xml 91 | /res/values-pt/strings.xml 92 | /res/values-pt-rPT/strings.xml 93 | /res/values-ru/strings.xml 94 | /res/values-sv-rSE/strings.xml 95 | /res/values-zh-rCN/strings.xml 96 | /res/values-zh-rTW/strings.xml 97 | /ZPAK/data/ps1_rom.bin 98 | /ZPAK/metadata.xml 99 | -------------------------------------------------------------------------------- /resources/patches/E7BCB6D5/stringReplacements.txt: -------------------------------------------------------------------------------- 1 | com\.sony\.playstation\.[a-zA-Z0-9_]+ 2 | com\.sony\.playstation\.\{TITLE_ID\} 3 | parental_rating=\".*\" 4 | parental_rating=\"\{PARENTAL_RATING\}\" 5 | parental_control=\".*\" 6 | parental_control=\"\{PARENTAL_RATING\}\" 7 | \.*\ 8 | \{ANALOG_MODE}\ 9 | \.*\ 10 | \\{FILTERED_PUBLISHER\}\ 11 | \.*\ 12 | \\{FILTERED_DEVELOPER\}\ 13 | \.*\ 14 | \\{FILTERED_DISPLAY_NAME\}\ 15 | \.*\ 16 | \\{FILTERED_TITLE\}\ 17 | \.*\ 18 | \\{FILTERED_DESCRIPTION\}\ 19 | \.*\ 20 | \\{FILTERED_PUBLISHER\}\ 21 | \.*\ 22 | \\{FILTERED_DEVELOPER\}\ 23 | \.*\ 24 | \\{TITLE_ID\}\ 25 | \.*\ 26 | \\{STORE_TYPE\}\ 27 | \.*\ 28 | \\{PARENTAL_RATING\}\ 29 | \true\ 30 | \\{CONTAINS_MANUAL\}\ 31 | \.*\ 32 | \file:///sdcard/Android/data/com.sony.playstation.\{TITLE_ID\}/files/content/\{TITLE_ID\}.zpak\ 33 | \.*\ 34 | \\{FILTERED_DISPLAY_NAME\}\ 35 | \.*\ 36 | \\{FILTERED_DESCRIPTION\}\ 37 | -------------------------------------------------------------------------------- /resources/signApk.keystore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yifanlu/PSXperia/3be12b3ef25daf3d976bac9dac5a74fb709a46be/resources/signApk.keystore -------------------------------------------------------------------------------- /src/META-INF/MANIFEST.MF: -------------------------------------------------------------------------------- 1 | Manifest-Version: 1.0 2 | Main-Class: com.yifanlu.PSXperiaTool.Interface.GUI 3 | 4 | -------------------------------------------------------------------------------- /src/com/yifanlu/PSXperiaTool/ApkBuilder.java: -------------------------------------------------------------------------------- 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 . 17 | */ 18 | 19 | package com.yifanlu.PSXperiaTool; 20 | 21 | import com.android.sdklib.internal.build.SignedJarBuilder; 22 | 23 | import java.io.*; 24 | import java.security.*; 25 | import java.security.cert.CertificateException; 26 | import java.security.cert.X509Certificate; 27 | import java.util.Arrays; 28 | 29 | public class ApkBuilder { 30 | private static final String ALIAS = "signPSXperia"; 31 | private static final char[] KEYSTORE_PASSWORD = {'p', 'a', 's', 's', 'w', 'o', 'r', 'd'}; 32 | private static final char[] ALIAS_PASSWORD = {'p', 'a', 's', 's', 'w', 'o', 'r', 'd'}; 33 | public static final String VERSION = "0.3 Beta 2"; 34 | 35 | private File mInputDir; 36 | private File mOutputApk; 37 | 38 | public ApkBuilder(File inputDir, File outputApk){ 39 | this.mInputDir = inputDir; 40 | this.mOutputApk = outputApk; 41 | } 42 | 43 | public void buildApk() throws IOException, InterruptedException, GeneralSecurityException, SignedJarBuilder.IZipEntryFilter.ZipAbortException { 44 | String os = System.getProperty("os.name"); 45 | Logger.verbose("Your OS: %s", os); 46 | File aaptTool; 47 | if(os.equals("Mac OS X")) 48 | aaptTool = new File("./aapt-osx"); 49 | else if(os.startsWith("Windows")) 50 | aaptTool = new File("./aapt-windows.exe"); 51 | else if(os.equals("Linux")) 52 | aaptTool = new File("./aapt-linux"); 53 | else { 54 | Logger.warning("Does not understand OS name '%s', assuming to be Linux", os); 55 | aaptTool = new File("./aapt-linux"); 56 | } 57 | InputStream in = PSXperiaTool.class.getResourceAsStream("/resources/" + aaptTool.getName()); 58 | Logger.verbose("Extracting %s", aaptTool.getPath()); 59 | writeStreamToFile(in, aaptTool); 60 | in.close(); 61 | aaptTool.setExecutable(true); 62 | 63 | File androidFrameworkJar = new File("./android-framework.jar"); 64 | Logger.verbose("Extracting %s", androidFrameworkJar.getPath()); 65 | in = PSXperiaTool.class.getResourceAsStream("/resources/android-framework.jar"); 66 | writeStreamToFile(in, androidFrameworkJar); 67 | in.close(); 68 | 69 | File tempApk = new File(mOutputApk.getPath() + ".unsigned"); 70 | 71 | String[] cmd = new String[12]; 72 | cmd[0] = (aaptTool.getPath()); 73 | cmd[1] = ("package"); 74 | cmd[2] = ("-f"); 75 | cmd[3] = ("-F"); 76 | cmd[4] = (tempApk.getPath()); 77 | cmd[5] = ("-S"); 78 | cmd[6] = ((new File(mInputDir, "/res")).getPath()); 79 | cmd[7] = ("-M"); 80 | cmd[8] = ((new File(mInputDir, "/assets/AndroidManifest.xml")).getPath()); 81 | cmd[9] = ("-I"); 82 | cmd[10] = (androidFrameworkJar.getPath()); 83 | cmd[11] = (mInputDir.getPath()); 84 | Logger.debug("Running command: " + Arrays.toString(cmd).replaceAll("\\,", "")); 85 | runCmdWithOutput(cmd); 86 | 87 | Logger.info("Signing apk %s to %s", tempApk.getPath(), mOutputApk.getPath()); 88 | signApk(tempApk); 89 | 90 | Logger.verbose("Cleaning up signing stuff."); 91 | tempApk.delete(); 92 | androidFrameworkJar.delete(); 93 | aaptTool.delete(); 94 | } 95 | 96 | private void writeStreamToFile(InputStream in, File outFile) throws IOException { 97 | Logger.verbose("Writing to: %s", outFile.getPath()); 98 | FileOutputStream out = new FileOutputStream(outFile); 99 | byte[] buffer = new byte[1024]; 100 | int n; 101 | while((n = in.read(buffer)) != -1){ 102 | out.write(buffer, 0, n); 103 | } 104 | out.close(); 105 | } 106 | 107 | public static void runCmdWithOutput(String[] cmd) throws IOException, InterruptedException { 108 | Process ps = Runtime.getRuntime().exec(cmd); 109 | BufferedReader in = new BufferedReader(new InputStreamReader(ps.getErrorStream())); 110 | String line; 111 | while ((line = in.readLine()) != null) { 112 | Logger.debug(line); 113 | } 114 | in.close(); 115 | if (ps.waitFor() != 0) { 116 | throw new IOException("Executable did not return without error."); 117 | } 118 | } 119 | 120 | private void signApk(File unsignedApk) throws IOException, GeneralSecurityException, SignedJarBuilder.IZipEntryFilter.ZipAbortException { 121 | FileInputStream in = new FileInputStream(unsignedApk); 122 | FileOutputStream out = new FileOutputStream(mOutputApk); 123 | KeyStore ks = getKeyStore(); 124 | PrivateKey key = (PrivateKey)ks.getKey(ALIAS, ALIAS_PASSWORD); 125 | X509Certificate cert = (X509Certificate)ks.getCertificate(ALIAS); 126 | SignedJarBuilder builder = new SignedJarBuilder(out, key, cert); 127 | builder.writeZip(in, null); 128 | builder.close(); 129 | out.close(); 130 | in.close(); 131 | } 132 | 133 | private KeyStore getKeyStore() throws KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException { 134 | KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType()); 135 | InputStream is = PSXperiaTool.class.getResourceAsStream("/resources/signApk.keystore"); 136 | ks.load(is, KEYSTORE_PASSWORD); 137 | return ks; 138 | } 139 | } 140 | -------------------------------------------------------------------------------- /src/com/yifanlu/PSXperiaTool/Extractor/CrashBandicootExtractor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * PSXperia Converter Tool - Extractor 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 . 17 | */ 18 | 19 | package com.yifanlu.PSXperiaTool.Extractor; 20 | 21 | import brut.androlib.AndrolibException; 22 | import brut.androlib.res.AndrolibResources; 23 | import brut.androlib.res.data.ResTable; 24 | import brut.androlib.res.util.ExtFile; 25 | import com.yifanlu.PSXperiaTool.*; 26 | import org.apache.commons.io.FileUtils; 27 | import org.apache.commons.io.filefilter.WildcardFileFilter; 28 | import ie.wombat.jbdiff.JBPatch; 29 | 30 | import java.io.*; 31 | import java.net.URISyntaxException; 32 | import java.net.URL; 33 | import java.util.Map; 34 | import java.util.Properties; 35 | import java.util.TreeMap; 36 | import java.util.zip.ZipEntry; 37 | import java.util.zip.ZipInputStream; 38 | 39 | public class CrashBandicootExtractor extends ProgressMonitor { 40 | private static final int TOTAL_STEPS = 8; 41 | private File mApkFile; 42 | private File mZpakData; 43 | private File mOutputDir; 44 | private static final int BLOCK_SIZE = 1024; 45 | private static final Map STRING_REPLACEMENT_MAP = new TreeMap(); 46 | 47 | public CrashBandicootExtractor(File apk, File zPakData, File outputDir) { 48 | this.mApkFile = apk; 49 | this.mOutputDir = outputDir; 50 | this.mZpakData = zPakData; 51 | setTotalSteps(TOTAL_STEPS); 52 | } 53 | 54 | public void extractApk() throws IOException, URISyntaxException { 55 | Logger.info("Starting extraction with PSXPeria Extractor version %s", PSXperiaTool.VERSION); 56 | verifyFiles(); 57 | processConfig(); 58 | decodeValues(); 59 | FileFilter filterCompiledRes = new FileFilter() { 60 | public boolean accept(File file) { 61 | if(file.getParent() == null || file.getParentFile().getParent() == null) 62 | return true; 63 | File parent = file.getParentFile(); 64 | return (!parent.getName().equals("res")) && (!parent.getParentFile().getName().equals("res")); 65 | } 66 | }; 67 | nextStep("Extracting APK"); 68 | extractZip(mApkFile, mOutputDir, filterCompiledRes); 69 | extractZpaks(); 70 | cleanUp(); 71 | moveResourceFiles(); 72 | patchStrings(); 73 | patchEmulator(); 74 | nextStep("Done."); 75 | } 76 | 77 | private void verifyFiles() throws IOException { 78 | nextStep("Verifying files"); 79 | if (!mApkFile.exists()) 80 | throw new FileNotFoundException("Cannot find APK file: " + mApkFile.getPath()); 81 | if (!mZpakData.exists()) 82 | throw new FileNotFoundException("Cannot find ZPAK file: " + mZpakData.getPath()); 83 | if (!mOutputDir.exists()) 84 | mOutputDir.mkdirs(); 85 | if(mOutputDir.list().length > 0) 86 | Logger.warning("The output directory is not empty! Whatever is in this folder will be included in all generated APKs."); 87 | //FileUtils.cleanDirectory(mOutputDir); 88 | } 89 | 90 | private void processConfig() throws IOException, UnsupportedOperationException { 91 | long crc32 = ZpakCreate.getCRC32(mApkFile); 92 | String crcString = Long.toHexString(crc32).toUpperCase(); 93 | InputStream inConfig = null; 94 | if((inConfig = PSXperiaTool.class.getResourceAsStream("/resources/patches/" + crcString + "/config.xml")) == null){ 95 | throw new FileNotFoundException("Cannot find config for this APK (CRC32: " + crcString + ")"); 96 | } 97 | Properties config = new Properties(); 98 | config.loadFromXML(inConfig); 99 | inConfig.close(); 100 | Logger.info( 101 | "Identified " + config.getProperty("game_name", "Unknown Game") + 102 | " " + config.getProperty("game_region") + 103 | " Version " + config.getProperty("game_version", "Unknown") + 104 | ", CRC32: " + config.getProperty("game_crc32", "Unknown") 105 | ); 106 | if(config.getProperty("valid", "yes").equals("no")) 107 | throw new UnsupportedOperationException("This APK is not supported."); 108 | Logger.verbose("Copying config files."); 109 | FileUtils.copyInputStreamToFile(PSXperiaTool.class.getResourceAsStream("/resources/patches/" + crcString + "/config.xml"), new File(mOutputDir, "/config/config.xml")); 110 | FileUtils.copyInputStreamToFile(PSXperiaTool.class.getResourceAsStream("/resources/patches/" + crcString + "/filelist.txt"), new File(mOutputDir, "/config/filelist.txt")); 111 | FileUtils.copyInputStreamToFile(PSXperiaTool.class.getResourceAsStream("/resources/patches/" + crcString + "/stringReplacements.txt"), new File(mOutputDir, "/config/stringReplacements.txt")); 112 | String emulatorPatch = config.getProperty("emulator_patch", ""); 113 | String gamePatch = config.getProperty("iso_patch", ""); 114 | if(!gamePatch.equals("")){ 115 | FileUtils.copyInputStreamToFile(PSXperiaTool.class.getResourceAsStream("/resources/patches/" + crcString + "/" + gamePatch), new File(mOutputDir, "/config/game-patch.bin")); 116 | } 117 | if(!emulatorPatch.equals("")){ 118 | FileUtils.copyInputStreamToFile(PSXperiaTool.class.getResourceAsStream("/resources/patches/" + crcString + "/" + emulatorPatch), new File(mOutputDir, "/config/" + emulatorPatch)); 119 | } 120 | } 121 | 122 | private void extractZip(File zipFile, File output, FileFilter filter) throws IOException { 123 | Logger.info("Extracting ZIP file: %s to: %s", zipFile.getPath(), output.getPath()); 124 | if(!output.exists()) 125 | output.mkdirs(); 126 | ZipInputStream zip = new ZipInputStream(new FileInputStream(zipFile)); 127 | ZipEntry entry; 128 | while ((entry = zip.getNextEntry()) != null) { 129 | File file = new File(output, entry.getName()); 130 | if (file.isDirectory()) 131 | continue; 132 | if(filter != null && !filter.accept(file)) 133 | continue; 134 | Logger.verbose("Unzipping %s", entry.getName()); 135 | FileUtils.touch(file); 136 | FileOutputStream out = new FileOutputStream(file.getPath()); 137 | int n; 138 | byte[] buffer = new byte[BLOCK_SIZE]; 139 | while ((n = zip.read(buffer)) != -1) { 140 | out.write(buffer, 0, n); 141 | } 142 | out.close(); 143 | zip.closeEntry(); 144 | Logger.verbose("Done extracting %s", entry.getName()); 145 | } 146 | zip.close(); 147 | Logger.debug("Done extracting ZIP."); 148 | } 149 | 150 | private void extractZpaks() throws IOException { 151 | nextStep("Extracting ZPAKS"); 152 | WildcardFileFilter ff = new WildcardFileFilter("*.zpak"); 153 | File[] candidates = (new File(mOutputDir, "/assets")).listFiles((FileFilter)ff); 154 | if(candidates == null || candidates.length < 1) 155 | throw new FileNotFoundException("Cannot find the default ZPAK under /assets"); 156 | else if(candidates.length > 1) 157 | Logger.warning("Found more than one default ZPAK under /assets. Using the first one."); 158 | File defaultZpak = candidates[0]; 159 | extractZip(defaultZpak, new File(mOutputDir, "/assets/ZPAK"), null); 160 | FileFilter filter = new FileFilter() { 161 | public boolean accept(File file) { 162 | if(file.getName().equals("image.ps")) 163 | return false; 164 | if(file.getParentFile() == null) 165 | return true; 166 | if(file.getParentFile().getName().equals("manual")) 167 | return false; 168 | return true; 169 | } 170 | }; 171 | extractZip(mZpakData, new File(mOutputDir, "/ZPAK"), filter); 172 | defaultZpak.delete(); 173 | } 174 | 175 | private void decodeValues() throws IOException { 176 | nextStep("Decoding values"); 177 | try { 178 | AndrolibResources res = new AndrolibResources(); 179 | ExtFile extFile = new ExtFile(mApkFile); 180 | ResTable resTable = res.getResTable(extFile); 181 | res.decode(resTable, extFile, mOutputDir); 182 | } catch (AndrolibException ex) { 183 | ex.printStackTrace(); 184 | throw new IOException(ex); 185 | } 186 | } 187 | 188 | private void cleanUp() throws IOException { 189 | nextStep("Removing unneeded files."); 190 | (new File(mOutputDir, "/AndroidManifest.xml")).delete(); 191 | FileUtils.deleteDirectory(new File(mOutputDir, "/META-INF")); 192 | Logger.verbose("Done cleaning up."); 193 | } 194 | 195 | private void moveResourceFiles() throws IOException { 196 | nextStep("Adding new files."); 197 | InputStream defaultIcon = PSXperiaTool.class.getResourceAsStream("/resources/icon.png"); 198 | writeStreamToFile(defaultIcon, new File(mOutputDir, "/assets/ZPAK/assets/default/bitmaps/icon.png")); 199 | defaultIcon = PSXperiaTool.class.getResourceAsStream("/resources/icon.png"); 200 | writeStreamToFile(defaultIcon, new File(mOutputDir, "/res/drawable/icon.png")); 201 | defaultIcon.close(); 202 | Logger.verbose("Done adding new files."); 203 | } 204 | 205 | private void writeStreamToFile(InputStream in, File outFile) throws IOException { 206 | Logger.verbose("Writing to: %s", outFile.getPath()); 207 | FileOutputStream out = new FileOutputStream(outFile); 208 | byte[] buffer = new byte[BLOCK_SIZE]; 209 | int n; 210 | while((n = in.read(buffer)) != -1){ 211 | out.write(buffer, 0, n); 212 | } 213 | out.close(); 214 | } 215 | 216 | private void fillReplacementMap() throws IOException { 217 | Logger.verbose("Filling string replacement map with resource data."); 218 | File file = new File(mOutputDir, "/config/stringReplacements.txt"); 219 | InputStream in = new FileInputStream(file); 220 | BufferedReader reader = new BufferedReader(new InputStreamReader(in)); 221 | String line1, line2; 222 | while((line1 = reader.readLine()) != null && (line2 = reader.readLine()) != null){ 223 | if(line1.isEmpty()) 224 | continue; 225 | Logger.verbose("Replacing %s with %s.", line1, line2); 226 | STRING_REPLACEMENT_MAP.put(line1, line2); 227 | } 228 | reader.close(); 229 | in.close(); 230 | file.delete(); 231 | } 232 | 233 | private void patchStrings() throws IOException { 234 | nextStep("Patching XML strings with tags."); 235 | if(STRING_REPLACEMENT_MAP.isEmpty()){ 236 | fillReplacementMap(); 237 | } 238 | StringReplacement strReplace = new StringReplacement(STRING_REPLACEMENT_MAP, mOutputDir); 239 | strReplace.execute(PSXperiaTool.FILES_TO_MODIFY); 240 | Logger.verbose("String replacement done."); 241 | } 242 | 243 | private void patchEmulator() throws IOException { 244 | Logger.info("Verifying the emulator binary."); 245 | Properties config = new Properties(); 246 | config.loadFromXML(new FileInputStream(new File(mOutputDir, "/config/config.xml"))); 247 | String emulatorName = config.getProperty("emulator_name", "libjava-activity.so"); 248 | File origEmulator = new File(mOutputDir, "/lib/armeabi/" + emulatorName); 249 | String emulatorCRC32 = Long.toHexString(FileUtils.checksumCRC32(origEmulator)); 250 | if(!emulatorCRC32.equalsIgnoreCase(config.getProperty("emulator_crc32"))) 251 | throw new UnsupportedOperationException("The emulator checksum is invalid. Cannot patch. CRC32: " + emulatorCRC32); 252 | File newEmulator = new File(mOutputDir, "/lib/armeabi/libjava-activity-patched.so"); 253 | File emulatorPatch = new File(mOutputDir, "/config/" + config.getProperty("emulator_patch", "")); 254 | if(emulatorPatch.equals("")){ 255 | Logger.info("No patch needed."); 256 | FileUtils.moveFile(origEmulator, newEmulator); 257 | }else{ 258 | Logger.info("Patching emulator."); 259 | newEmulator.createNewFile(); 260 | JBPatch.bspatch(origEmulator, newEmulator, emulatorPatch); 261 | emulatorPatch.delete(); 262 | } 263 | FileUtils.copyInputStreamToFile(PSXperiaTool.class.getResourceAsStream("/resources/libjava-activity-wrapper.so"), origEmulator); 264 | } 265 | } 266 | -------------------------------------------------------------------------------- /src/com/yifanlu/PSXperiaTool/Interface/CommandLine.java: -------------------------------------------------------------------------------- 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 . 17 | */ 18 | 19 | package com.yifanlu.PSXperiaTool.Interface; 20 | 21 | import com.android.sdklib.internal.build.SignedJarBuilder; 22 | import com.yifanlu.PSXperiaTool.Extractor.CrashBandicootExtractor; 23 | import com.yifanlu.PSXperiaTool.Logger; 24 | import com.yifanlu.PSXperiaTool.PSImageExtract; 25 | import com.yifanlu.PSXperiaTool.PSXperiaTool; 26 | 27 | import java.io.File; 28 | import java.io.FileInputStream; 29 | import java.io.FileOutputStream; 30 | import java.io.IOException; 31 | import java.net.URISyntaxException; 32 | import java.security.GeneralSecurityException; 33 | import java.util.Arrays; 34 | import java.util.InputMismatchException; 35 | import java.util.Properties; 36 | import java.util.Stack; 37 | import java.util.regex.Matcher; 38 | import java.util.regex.Pattern; 39 | import java.util.zip.DataFormatException; 40 | 41 | public class CommandLine { 42 | private static class InvalidArgumentException extends Exception { 43 | private String mMessage; 44 | 45 | public InvalidArgumentException(String message) { 46 | this.mMessage = message; 47 | } 48 | 49 | public String getMessage() { 50 | return this.mMessage; 51 | } 52 | } 53 | 54 | public static void verifyTitleID(String toVerify) throws InputMismatchException { 55 | Pattern pattern = Pattern.compile("^[A-Za-z0-9_]+$"); 56 | Matcher matcher = pattern.matcher(toVerify); 57 | if (!matcher.find()) 58 | throw new InputMismatchException("Title ID can only contain alphanumberic characters and underscores."); 59 | } 60 | 61 | public static void main(String[] args) { 62 | Logger.setLevel(Logger.DEBUG); 63 | if (args.length < 1) 64 | printHelp(); 65 | String toDo = args[0]; 66 | try { 67 | if (toDo.equals("extract") || toDo.equals("x")) 68 | doExtractData(args); 69 | if (toDo.equals("convert") || toDo.equals("c")) 70 | doConvertImage(args); 71 | if (toDo.equals("decompress") || toDo.equals("d")) 72 | doDecompressImage(args); 73 | 74 | } catch (InputMismatchException ex) { 75 | Logger.error("Input error: %s", ex.getMessage()); 76 | ex.printStackTrace(); 77 | } catch (InvalidArgumentException ex) { 78 | Logger.error("Invalid argument: %s", ex.getMessage()); 79 | printHelp(); 80 | } catch (IOException ex) { 81 | Logger.error("IO error, Java says: %s", ex.getMessage()); 82 | ex.printStackTrace(); 83 | } catch (InterruptedException ex) { 84 | Logger.error("Process exec Error, Java says: %s", ex.getMessage()); 85 | ex.printStackTrace(); 86 | } catch (DataFormatException ex) { 87 | Logger.error("Data format error, Java says: %s", ex.getMessage()); 88 | ex.printStackTrace(); 89 | } catch (GeneralSecurityException ex) { 90 | Logger.error("Error signing JAR, Java says: %s", ex.getMessage()); 91 | ex.printStackTrace(); 92 | } catch (SignedJarBuilder.IZipEntryFilter.ZipAbortException ex) { 93 | Logger.error("Error signing JAR, Java says: %s", ex.getMessage()); 94 | ex.printStackTrace(); 95 | } catch (UnsupportedOperationException ex) { 96 | Logger.error("Unsupported exception: %s", ex.getMessage()); 97 | ex.printStackTrace(); 98 | } catch (Exception ex) { 99 | Logger.error("Exception: %s", ex.getMessage()); 100 | ex.printStackTrace(); 101 | } 102 | } 103 | 104 | public static void doExtractData(String[] args) throws InvalidArgumentException, IOException, URISyntaxException { 105 | if (args.length < 4) 106 | throw new InvalidArgumentException("Not enough input."); 107 | 108 | Stack stack = new Stack(); 109 | stack.addAll(Arrays.asList(args)); 110 | File outputDir = new File(stack.pop()); 111 | File inputZpak = new File(stack.pop()); 112 | File inputApk = new File(stack.pop()); 113 | 114 | while (!stack.empty()) { 115 | String argument = stack.pop(); 116 | if (argument.startsWith("-")) { 117 | if (argument.equals("-v") || argument.equalsIgnoreCase("--verbose")) { 118 | Logger.setLevel(Logger.ALL); 119 | continue; 120 | } 121 | Logger.warning("Unknown option %s", argument); 122 | } 123 | } 124 | (new CrashBandicootExtractor(inputApk, inputZpak, outputDir)).extractApk(); 125 | System.exit(0); 126 | } 127 | 128 | public static void doConvertImage(String[] args) throws InvalidArgumentException, IOException, InterruptedException, GeneralSecurityException, SignedJarBuilder.IZipEntryFilter.ZipAbortException { 129 | if (args.length < 3) 130 | throw new InvalidArgumentException("Not enough input."); 131 | 132 | Stack stack = new Stack(); 133 | stack.addAll(Arrays.asList(args)); 134 | File outputDir = new File(stack.pop()); 135 | File inputFile = new File(stack.pop()); 136 | String titleId = stack.pop(); 137 | 138 | Properties settings = new Properties(); 139 | settings.loadFromXML(PSXperiaTool.class.getResourceAsStream("/resources/defaults.xml")); 140 | settings.put("KEY_TITLE_ID", titleId); 141 | File currentDir = new File("."); 142 | File dataDir = new File(currentDir, "/data"); 143 | 144 | Stack stringList = new Stack(); 145 | while (!stack.empty()) { 146 | String argument = stack.pop(); 147 | if (argument.startsWith("-")) { 148 | if (argument.equals("-v") || argument.equalsIgnoreCase("--verbose")) { 149 | Logger.setLevel(Logger.ALL); 150 | continue; 151 | } else if (argument.equals("-D")) { 152 | dataDir = new File(stringList.pop()); 153 | stringList.empty(); 154 | } else if (argument.equals("--load-xml")) { 155 | File xml = new File(stringList.pop()); 156 | settings.loadFromXML(new FileInputStream(xml)); 157 | stringList.empty(); 158 | } else if (argument.equals("--game-name")) { 159 | String name = stackToString(stringList); 160 | settings.put("KEY_DISPLAY_NAME", name); 161 | settings.put("KEY_TITLE", name); 162 | } else if (argument.equals("--description")) { 163 | settings.put("KEY_DESCRIPTION", stackToString(stringList)); 164 | } else if (argument.equals("--publisher")) { 165 | settings.put("KEY_PUBLISHER", stackToString(stringList)); 166 | } else if (argument.equals("--developer")) { 167 | settings.put("KEY_DEVELOPER", stackToString(stringList)); 168 | } else if (argument.equals("--icon-file")) { 169 | settings.put("IconFile", new File(stringList.pop())); 170 | stringList.empty(); 171 | } else if (argument.equals("--store-type")) { 172 | settings.put("KEY_STORE_TYPE", stackToString(stringList)); 173 | } else if (argument.equals("--analog-mode")) { 174 | String str = stringList.pop(); 175 | if (str.equals("true")) 176 | settings.put("KEY_ANALOG_MODE", "YES"); 177 | stringList.empty(); 178 | } else { 179 | stringList.push(argument); 180 | } 181 | } else { 182 | stringList.push(argument); 183 | } 184 | } 185 | 186 | verifyTitleID(titleId); 187 | PSXperiaTool tool = new PSXperiaTool(settings, inputFile, dataDir, outputDir); 188 | tool.startBuild(); 189 | 190 | System.exit(0); 191 | } 192 | 193 | private static String stackToString(Stack stack) { 194 | String str = ""; 195 | while (!stack.isEmpty()) { 196 | str += stack.pop() + " "; 197 | } 198 | str = str.replaceAll("^\"", ""); 199 | str = str.replaceAll("\"$", ""); 200 | return str; 201 | } 202 | 203 | public static void doDecompressImage(String[] args) throws InvalidArgumentException, IOException, DataFormatException { 204 | if (args.length < 3) 205 | throw new InvalidArgumentException("Not enough input."); 206 | 207 | Stack stack = new Stack(); 208 | stack.addAll(Arrays.asList(args)); 209 | File outputFile = new File(stack.pop()); 210 | File inputFile = new File(stack.pop()); 211 | 212 | while (!stack.empty()) { 213 | String argument = stack.pop(); 214 | if (argument.startsWith("-")) { 215 | if (argument.equals("-v") || argument.equalsIgnoreCase("--verbose")) { 216 | Logger.setLevel(Logger.ALL); 217 | continue; 218 | } 219 | Logger.warning("Unknown option %s", argument); 220 | } 221 | } 222 | FileInputStream in = new FileInputStream(inputFile); 223 | FileOutputStream out = new FileOutputStream(outputFile); 224 | PSImageExtract extract = new PSImageExtract(in); 225 | extract.uncompress(out); 226 | out.close(); 227 | in.close(); 228 | System.exit(0); 229 | } 230 | 231 | public static void printHelp() { 232 | System.out.println("PSXPeria Converter Tool"); 233 | System.out.println(""); 234 | System.out.println("Usage:"); 235 | System.out.println(" Extract and patch data files"); 236 | System.out.println(" psxperia e[x]tract [-v|--verbose] input.apk input-data.zpak output"); 237 | System.out.println(" [-v|--verbose] Verbose output"); 238 | System.out.println(" input.apk Either com.sony.playstation.ncua94900_1.apk or com.sony.playstation.ncea00344_1.apk"); 239 | System.out.println(" input-data.zpak Either NCUA94900_1_1.zpak or NCEA00344_1_1.zpak (must match region of APK)"); 240 | System.out.println(" output Directory to extract the files"); 241 | System.out.println(""); 242 | System.out.println(" Convert PSX Image to Xperia Play APK and ZPAK"); 243 | System.out.println(" psxperia [c]onvert [OPTIONS] titleId image.iso output"); 244 | System.out.println(" titleId An unique ID, usually from the game in the format NCXAXXXXX_1"); 245 | System.out.println(" image.iso Input PSX image. Does not have to be an ISO, and valid PSX image will do. You must rip it on your own!"); 246 | System.out.println(" output Directory to output files"); 247 | System.out.println(" Options (unset options will be set to defaults):"); 248 | System.out.println(" -v|--verbose Verbose output, including image creation progress"); 249 | System.out.println(" -D directory Custom location for extracted data files, default is \"./data\""); 250 | System.out.println(" --load-xml Load options from Java properties XML"); 251 | System.out.println(" --game-name Name of the game"); 252 | System.out.println(" --description Description of the game"); 253 | System.out.println(" --publisher Publisher of the game"); 254 | System.out.println(" --developer Developer of the game"); 255 | System.out.println(" --icon-file Path to image for icon"); 256 | System.out.println(" --store-type Where to find this title (any string will do)"); 257 | System.out.println(" --analog-mode true|false, Turn on/off analog controls (game must support it)."); 258 | System.out.println(""); 259 | System.out.println(" Convert image.ps to PSX Image"); 260 | System.out.println(" psxperia [d]ecompress [-v|--verbose] input.ps output.iso"); 261 | System.out.println(" [-v|--verbose] Verbose output"); 262 | System.out.println(" input.ps image.ps from ZPAK"); 263 | System.out.println(" output.iso PSX Image to generate"); 264 | System.exit(0); 265 | } 266 | } 267 | -------------------------------------------------------------------------------- /src/com/yifanlu/PSXperiaTool/Interface/GUI.java: -------------------------------------------------------------------------------- 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 . 17 | */ 18 | 19 | package com.yifanlu.PSXperiaTool.Interface; 20 | 21 | import com.android.sdklib.internal.build.SignedJarBuilder; 22 | import com.yifanlu.PSXperiaTool.Extractor.CrashBandicootExtractor; 23 | import com.yifanlu.PSXperiaTool.Logger; 24 | import com.yifanlu.PSXperiaTool.PSXperiaTool; 25 | import com.yifanlu.PSXperiaTool.ProgressMonitor; 26 | import org.apache.commons.io.FileUtils; 27 | 28 | import javax.imageio.ImageIO; 29 | import javax.swing.*; 30 | import java.awt.image.BufferedImage; 31 | import java.io.File; 32 | import java.io.FileOutputStream; 33 | import java.io.IOException; 34 | import java.io.PrintStream; 35 | import java.net.URISyntaxException; 36 | import java.security.GeneralSecurityException; 37 | import java.util.InputMismatchException; 38 | import java.util.Properties; 39 | 40 | public class GUI extends javax.swing.JFrame { 41 | 42 | /** 43 | * Creates new form GUI 44 | */ 45 | public GUI() { 46 | initComponents(); 47 | } 48 | 49 | /** 50 | * This method is called from within the constructor to 51 | * initialize the form. 52 | * WARNING: Do NOT modify this code. The content of this method is 53 | * always regenerated by the Form Editor. 54 | */ 55 | @SuppressWarnings("unchecked") 56 | // //GEN-BEGIN:initComponents 57 | private void initComponents() { 58 | 59 | tabbedPane = new javax.swing.JTabbedPane(); 60 | informationPanel = new javax.swing.JPanel(); 61 | licenseCheck1 = new javax.swing.JCheckBox(); 62 | licenseCheck2 = new javax.swing.JCheckBox(); 63 | licenseCheck3 = new javax.swing.JCheckBox(); 64 | licenseCheck4 = new javax.swing.JCheckBox(); 65 | textScrollPane = new javax.swing.JScrollPane(); 66 | licenseText = new javax.swing.JTextArea(); 67 | extractPanel = new javax.swing.JPanel(); 68 | extractInformation = new javax.swing.JLabel(); 69 | apkFileLabel = new javax.swing.JLabel(); 70 | apkFileInput = new javax.swing.JTextField(); 71 | zpakFileInput = new javax.swing.JTextField(); 72 | extractOutputInput = new javax.swing.JTextField(); 73 | zpakFileLabel = new javax.swing.JLabel(); 74 | extractOutputLabel = new javax.swing.JLabel(); 75 | chooseZpakFile = new javax.swing.JButton(); 76 | chooseApkFile = new javax.swing.JButton(); 77 | chooseOutputDir = new javax.swing.JButton(); 78 | extractProgress = new javax.swing.JProgressBar(); 79 | extractButton = new javax.swing.JButton(); 80 | extractStatus = new javax.swing.JLabel(); 81 | createPanel = new javax.swing.JPanel(); 82 | chooseData = new javax.swing.JButton(); 83 | dataInput = new javax.swing.JTextField(); 84 | dataLabel = new javax.swing.JLabel(); 85 | isoLabel = new javax.swing.JLabel(); 86 | isoInput = new javax.swing.JTextField(); 87 | chooseIso = new javax.swing.JButton(); 88 | chooseIcon = new javax.swing.JButton(); 89 | convertOutputInput = new javax.swing.JTextField(); 90 | convertOutputLabel = new javax.swing.JLabel(); 91 | chooseConvertOutput = new javax.swing.JButton(); 92 | convertSeparator = new javax.swing.JSeparator(); 93 | loadXmlButton = new javax.swing.JButton(); 94 | gameInformationLabel = new javax.swing.JLabel(); 95 | titleIdLabel = new javax.swing.JLabel(); 96 | titleIdInput = new javax.swing.JTextField(); 97 | nameInput = new javax.swing.JTextField(); 98 | nameLabel = new javax.swing.JLabel(); 99 | developerInput = new javax.swing.JTextField(); 100 | developerLabel = new javax.swing.JLabel(); 101 | publisherLabel = new javax.swing.JLabel(); 102 | publisherInput = new javax.swing.JTextField(); 103 | descriptionLabel = new javax.swing.JLabel(); 104 | descriptionTextPane = new javax.swing.JScrollPane(); 105 | descriptionTextInput = new javax.swing.JTextArea(); 106 | convertProgress = new javax.swing.JProgressBar(); 107 | parentalRatingLabel = new javax.swing.JLabel(); 108 | parentalRatingInput = new javax.swing.JTextField(); 109 | storeTypeLabel = new javax.swing.JLabel(); 110 | storeTypeInput = new javax.swing.JTextField(); 111 | analogModeCheckbox = new javax.swing.JCheckBox(); 112 | convertButton = new javax.swing.JButton(); 113 | getTitleIdButton = new javax.swing.JButton(); 114 | iconImagePreview = new javax.swing.JLabel(); 115 | convertStatus = new javax.swing.JLabel(); 116 | 117 | setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE); 118 | setTitle("PSXperia Tool"); 119 | setName("PSXperia Tool"); // NOI18N 120 | setPreferredSize(new java.awt.Dimension(800, 540)); 121 | setResizable(false); 122 | setSize(new java.awt.Dimension(800, 540)); 123 | addWindowListener(new java.awt.event.WindowAdapter() { 124 | public void windowOpened(java.awt.event.WindowEvent evt) { 125 | formWindowOpened(evt); 126 | } 127 | }); 128 | 129 | tabbedPane.setPreferredSize(new java.awt.Dimension(800, 530)); 130 | 131 | licenseCheck1.setText("Yes, I own a Xperia Play and the Crash Bandicoot APK"); 132 | 133 | licenseCheck2.setText("Yes, I own the game(s) I will convert and have permission to use them"); 134 | 135 | licenseCheck3.setText("Yes, I will not distribute/redistribute any of the files generated by this tool"); 136 | 137 | licenseCheck4.setText("Yes, I understand this is a free tool and does not come with any warranties"); 138 | 139 | licenseText.setColumns(20); 140 | licenseText.setEditable(false); 141 | licenseText.setLineWrap(true); 142 | licenseText.setRows(5); 143 | licenseText.setText("This tool is designed to allow you to convert PSX game(s) that you OWN and have permission to USE on your Android phone by modifying the files from the \"Crash Bandicoot\" game that is included with the Xperia Play. You must own these files too and the phone to obtain the necessary files. Please understand that piracy hurts the game industry and prevents developers from earning money for their hard work, so do not distribute any files you create with this tool. Finally, know that this tool is completely free and open source and should not be sold as is or part of any package. If you understand all of this, check the boxes and highlight my name below to enable the tool.\n\n-Yifan Lu\nhttp://yifan.lu/\nhttp://github.com/yifanlu/PSXperia\n"); 144 | licenseText.setWrapStyleWord(true); 145 | licenseText.addCaretListener(new javax.swing.event.CaretListener() { 146 | public void caretUpdate(javax.swing.event.CaretEvent evt) { 147 | licenseTextCaretUpdate(evt); 148 | } 149 | }); 150 | textScrollPane.setViewportView(licenseText); 151 | 152 | org.jdesktop.layout.GroupLayout informationPanelLayout = new org.jdesktop.layout.GroupLayout(informationPanel); 153 | informationPanel.setLayout(informationPanelLayout); 154 | informationPanelLayout.setHorizontalGroup( 155 | informationPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) 156 | .add(informationPanelLayout.createSequentialGroup() 157 | .addContainerGap() 158 | .add(informationPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) 159 | .add(textScrollPane, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 739, Short.MAX_VALUE) 160 | .add(licenseCheck4) 161 | .add(licenseCheck3) 162 | .add(licenseCheck2) 163 | .add(licenseCheck1)) 164 | .addContainerGap()) 165 | ); 166 | informationPanelLayout.setVerticalGroup( 167 | informationPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) 168 | .add(org.jdesktop.layout.GroupLayout.TRAILING, informationPanelLayout.createSequentialGroup() 169 | .addContainerGap() 170 | .add(textScrollPane, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 328, Short.MAX_VALUE) 171 | .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) 172 | .add(licenseCheck1) 173 | .addPreferredGap(org.jdesktop.layout.LayoutStyle.UNRELATED) 174 | .add(licenseCheck2) 175 | .addPreferredGap(org.jdesktop.layout.LayoutStyle.UNRELATED) 176 | .add(licenseCheck3) 177 | .addPreferredGap(org.jdesktop.layout.LayoutStyle.UNRELATED) 178 | .add(licenseCheck4) 179 | .addContainerGap()) 180 | ); 181 | 182 | tabbedPane.addTab("Information", informationPanel); 183 | 184 | java.util.ResourceBundle bundle = java.util.ResourceBundle.getBundle("com/yifanlu/PSXperiaTool/Interface/Strings"); // NOI18N 185 | extractInformation.setText(bundle.getString("extract.directions")); // NOI18N 186 | 187 | apkFileLabel.setText(bundle.getString("extract.apkfile")); // NOI18N 188 | 189 | zpakFileLabel.setText(bundle.getString("extract.zpakfile")); // NOI18N 190 | 191 | extractOutputLabel.setText(bundle.getString("extract.output")); // NOI18N 192 | 193 | chooseZpakFile.setText(bundle.getString("extract.choose")); // NOI18N 194 | chooseZpakFile.addActionListener(new java.awt.event.ActionListener() { 195 | public void actionPerformed(java.awt.event.ActionEvent evt) { 196 | chooseZpakFileActionPerformed(evt); 197 | } 198 | }); 199 | 200 | chooseApkFile.setText(bundle.getString("extract.choose")); // NOI18N 201 | chooseApkFile.addActionListener(new java.awt.event.ActionListener() { 202 | public void actionPerformed(java.awt.event.ActionEvent evt) { 203 | chooseApkFileActionPerformed(evt); 204 | } 205 | }); 206 | 207 | chooseOutputDir.setText(bundle.getString("extract.choose")); // NOI18N 208 | chooseOutputDir.addActionListener(new java.awt.event.ActionListener() { 209 | public void actionPerformed(java.awt.event.ActionEvent evt) { 210 | chooseOutputDirActionPerformed(evt); 211 | } 212 | }); 213 | 214 | extractButton.setText(bundle.getString("extract.extract")); // NOI18N 215 | extractButton.addActionListener(new java.awt.event.ActionListener() { 216 | public void actionPerformed(java.awt.event.ActionEvent evt) { 217 | extractButtonActionPerformed(evt); 218 | } 219 | }); 220 | 221 | org.jdesktop.layout.GroupLayout extractPanelLayout = new org.jdesktop.layout.GroupLayout(extractPanel); 222 | extractPanel.setLayout(extractPanelLayout); 223 | extractPanelLayout.setHorizontalGroup( 224 | extractPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) 225 | .add(org.jdesktop.layout.GroupLayout.TRAILING, extractPanelLayout.createSequentialGroup() 226 | .addContainerGap() 227 | .add(extractPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.TRAILING) 228 | .add(org.jdesktop.layout.GroupLayout.LEADING, extractStatus, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 739, Short.MAX_VALUE) 229 | .add(org.jdesktop.layout.GroupLayout.LEADING, extractInformation, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 739, Short.MAX_VALUE) 230 | .add(extractPanelLayout.createSequentialGroup() 231 | .add(extractPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) 232 | .add(org.jdesktop.layout.GroupLayout.TRAILING, extractPanelLayout.createSequentialGroup() 233 | .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED, 5, Short.MAX_VALUE) 234 | .add(extractPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) 235 | .add(extractOutputLabel) 236 | .add(zpakFileLabel) 237 | .add(apkFileLabel)) 238 | .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) 239 | .add(extractPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.TRAILING, false) 240 | .add(org.jdesktop.layout.GroupLayout.LEADING, zpakFileInput) 241 | .add(org.jdesktop.layout.GroupLayout.LEADING, extractOutputInput) 242 | .add(org.jdesktop.layout.GroupLayout.LEADING, apkFileInput, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 562, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))) 243 | .add(org.jdesktop.layout.GroupLayout.TRAILING, extractProgress, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 639, Short.MAX_VALUE)) 244 | .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) 245 | .add(extractPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) 246 | .add(extractButton) 247 | .add(chooseOutputDir) 248 | .add(chooseApkFile) 249 | .add(chooseZpakFile)))) 250 | .addContainerGap()) 251 | ); 252 | extractPanelLayout.setVerticalGroup( 253 | extractPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) 254 | .add(extractPanelLayout.createSequentialGroup() 255 | .addContainerGap() 256 | .add(extractInformation, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE) 257 | .add(18, 18, 18) 258 | .add(extractPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) 259 | .add(extractPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE) 260 | .add(apkFileInput, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE) 261 | .add(chooseApkFile)) 262 | .add(apkFileLabel)) 263 | .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) 264 | .add(extractPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) 265 | .add(extractPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE) 266 | .add(zpakFileInput, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE) 267 | .add(chooseZpakFile)) 268 | .add(zpakFileLabel)) 269 | .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) 270 | .add(extractPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) 271 | .add(extractPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE) 272 | .add(extractOutputInput, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE) 273 | .add(chooseOutputDir)) 274 | .add(extractOutputLabel)) 275 | .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED, 167, Short.MAX_VALUE) 276 | .add(extractPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.TRAILING) 277 | .add(extractProgress, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE) 278 | .add(extractButton)) 279 | .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) 280 | .add(extractStatus, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 15, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE) 281 | .addContainerGap()) 282 | ); 283 | 284 | extractInformation.getAccessibleContext().setAccessibleName(bundle.getString("extractDirections")); // NOI18N 285 | 286 | tabbedPane.addTab("Extract", extractPanel); 287 | 288 | chooseData.setText(bundle.getString("convert.choose")); // NOI18N 289 | chooseData.addActionListener(new java.awt.event.ActionListener() { 290 | public void actionPerformed(java.awt.event.ActionEvent evt) { 291 | chooseDataActionPerformed(evt); 292 | } 293 | }); 294 | 295 | dataInput.setToolTipText(bundle.getString("convert.extracted_data.tooltip")); // NOI18N 296 | 297 | dataLabel.setText(bundle.getString("convert.extracted_data")); // NOI18N 298 | 299 | isoLabel.setText(bundle.getString("convert.iso_input")); // NOI18N 300 | 301 | chooseIso.setText(bundle.getString("convert.choose")); // NOI18N 302 | chooseIso.addActionListener(new java.awt.event.ActionListener() { 303 | public void actionPerformed(java.awt.event.ActionEvent evt) { 304 | chooseIsoActionPerformed(evt); 305 | } 306 | }); 307 | 308 | chooseIcon.setText("Change Icon"); 309 | chooseIcon.addActionListener(new java.awt.event.ActionListener() { 310 | public void actionPerformed(java.awt.event.ActionEvent evt) { 311 | chooseIconActionPerformed(evt); 312 | } 313 | }); 314 | 315 | convertOutputLabel.setText(bundle.getString("convert.output_directory")); // NOI18N 316 | 317 | chooseConvertOutput.setText(bundle.getString("convert.choose")); // NOI18N 318 | chooseConvertOutput.addActionListener(new java.awt.event.ActionListener() { 319 | public void actionPerformed(java.awt.event.ActionEvent evt) { 320 | chooseConvertOutputActionPerformed(evt); 321 | } 322 | }); 323 | 324 | loadXmlButton.setText(bundle.getString("convert.load_xml")); // NOI18N 325 | loadXmlButton.setToolTipText(bundle.getString("common.disabled_control")); // NOI18N 326 | loadXmlButton.setEnabled(false); 327 | 328 | gameInformationLabel.setText(bundle.getString("convert.game_information")); // NOI18N 329 | 330 | titleIdLabel.setText(bundle.getString("convert.title_id")); // NOI18N 331 | 332 | titleIdInput.setToolTipText(bundle.getString("convert.title_id.tooltip")); // NOI18N 333 | 334 | nameInput.setToolTipText(bundle.getString("convert.name.tooltip")); // NOI18N 335 | 336 | nameLabel.setText(bundle.getString("convert.name")); // NOI18N 337 | 338 | developerInput.setToolTipText(bundle.getString("convert.developer.tooltip")); // NOI18N 339 | 340 | developerLabel.setText(bundle.getString("convert.developer")); // NOI18N 341 | 342 | publisherLabel.setText(bundle.getString("convert.publisher")); // NOI18N 343 | 344 | publisherInput.setToolTipText(bundle.getString("convert.publisher.tooltip")); // NOI18N 345 | 346 | descriptionLabel.setText("Description:"); 347 | 348 | descriptionTextInput.setColumns(20); 349 | descriptionTextInput.setLineWrap(true); 350 | descriptionTextInput.setRows(5); 351 | descriptionTextInput.setWrapStyleWord(true); 352 | descriptionTextPane.setViewportView(descriptionTextInput); 353 | 354 | parentalRatingLabel.setText(bundle.getString("convert.parental_rating")); // NOI18N 355 | 356 | parentalRatingInput.setToolTipText(bundle.getString("convert.parental_rating.tooltip")); // NOI18N 357 | 358 | storeTypeLabel.setText(bundle.getString("convert.store_type")); // NOI18N 359 | 360 | storeTypeInput.setToolTipText(bundle.getString("convert.store_type.tooltip")); // NOI18N 361 | 362 | analogModeCheckbox.setText(bundle.getString("convert.analog_mode")); // NOI18N 363 | analogModeCheckbox.setToolTipText(bundle.getString("convert.analog_mode.tooltip")); // NOI18N 364 | 365 | convertButton.setText(bundle.getString("convert.convert")); // NOI18N 366 | convertButton.addActionListener(new java.awt.event.ActionListener() { 367 | public void actionPerformed(java.awt.event.ActionEvent evt) { 368 | convertButtonActionPerformed(evt); 369 | } 370 | }); 371 | 372 | getTitleIdButton.setText(bundle.getString("convert.get_title_id")); // NOI18N 373 | getTitleIdButton.setToolTipText(bundle.getString("common.disabled_control")); // NOI18N 374 | getTitleIdButton.setEnabled(false); 375 | 376 | iconImagePreview.setBorder(javax.swing.BorderFactory.createEtchedBorder()); 377 | 378 | org.jdesktop.layout.GroupLayout createPanelLayout = new org.jdesktop.layout.GroupLayout(createPanel); 379 | createPanel.setLayout(createPanelLayout); 380 | createPanelLayout.setHorizontalGroup( 381 | createPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) 382 | .add(org.jdesktop.layout.GroupLayout.TRAILING, createPanelLayout.createSequentialGroup() 383 | .addContainerGap() 384 | .add(createPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.TRAILING) 385 | .add(org.jdesktop.layout.GroupLayout.LEADING, convertStatus, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 739, Short.MAX_VALUE) 386 | .add(org.jdesktop.layout.GroupLayout.LEADING, createPanelLayout.createSequentialGroup() 387 | .add(createPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.TRAILING) 388 | .add(org.jdesktop.layout.GroupLayout.LEADING, createPanelLayout.createSequentialGroup() 389 | .add(createPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) 390 | .add(isoLabel) 391 | .add(dataLabel) 392 | .add(convertOutputLabel)) 393 | .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) 394 | .add(createPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) 395 | .add(convertOutputInput, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 332, Short.MAX_VALUE) 396 | .add(isoInput, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 332, Short.MAX_VALUE) 397 | .add(dataInput, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 332, Short.MAX_VALUE)) 398 | .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) 399 | .add(createPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) 400 | .add(chooseData) 401 | .add(chooseIso) 402 | .add(chooseConvertOutput))) 403 | .add(org.jdesktop.layout.GroupLayout.LEADING, convertSeparator, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 552, Short.MAX_VALUE) 404 | .add(createPanelLayout.createSequentialGroup() 405 | .add(gameInformationLabel) 406 | .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED, 123, Short.MAX_VALUE) 407 | .add(getTitleIdButton) 408 | .addPreferredGap(org.jdesktop.layout.LayoutStyle.UNRELATED) 409 | .add(loadXmlButton)) 410 | .add(org.jdesktop.layout.GroupLayout.LEADING, createPanelLayout.createSequentialGroup() 411 | .add(createPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) 412 | .add(nameLabel) 413 | .add(developerLabel) 414 | .add(descriptionLabel)) 415 | .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) 416 | .add(createPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) 417 | .add(descriptionTextPane, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 465, Short.MAX_VALUE) 418 | .add(createPanelLayout.createSequentialGroup() 419 | .add(nameInput, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 235, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE) 420 | .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) 421 | .add(titleIdLabel) 422 | .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) 423 | .add(titleIdInput, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 160, Short.MAX_VALUE)) 424 | .add(createPanelLayout.createSequentialGroup() 425 | .add(developerInput, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 149, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE) 426 | .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) 427 | .add(publisherLabel) 428 | .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) 429 | .add(publisherInput, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 238, Short.MAX_VALUE))))) 430 | .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) 431 | .add(createPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) 432 | .add(iconImagePreview, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 175, Short.MAX_VALUE) 433 | .add(createPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING, false) 434 | .add(org.jdesktop.layout.GroupLayout.TRAILING, chooseIcon, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) 435 | .add(parentalRatingLabel) 436 | .add(parentalRatingInput) 437 | .add(storeTypeLabel) 438 | .add(storeTypeInput)) 439 | .add(analogModeCheckbox, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 174, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))) 440 | .add(createPanelLayout.createSequentialGroup() 441 | .add(convertProgress, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 637, Short.MAX_VALUE) 442 | .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) 443 | .add(convertButton) 444 | .add(2, 2, 2))) 445 | .addContainerGap()) 446 | ); 447 | createPanelLayout.setVerticalGroup( 448 | createPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) 449 | .add(createPanelLayout.createSequentialGroup() 450 | .addContainerGap() 451 | .add(createPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.TRAILING) 452 | .add(createPanelLayout.createSequentialGroup() 453 | .add(createPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) 454 | .add(createPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE) 455 | .add(chooseData) 456 | .add(dataInput, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)) 457 | .add(dataLabel)) 458 | .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) 459 | .add(createPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) 460 | .add(createPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE) 461 | .add(isoInput, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE) 462 | .add(chooseIso)) 463 | .add(isoLabel)) 464 | .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) 465 | .add(createPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) 466 | .add(convertOutputLabel) 467 | .add(createPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE) 468 | .add(convertOutputInput, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE) 469 | .add(chooseConvertOutput))) 470 | .add(18, 18, 18) 471 | .add(convertSeparator, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 10, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE) 472 | .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED, 12, Short.MAX_VALUE) 473 | .add(createPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE) 474 | .add(loadXmlButton) 475 | .add(gameInformationLabel) 476 | .add(getTitleIdButton))) 477 | .add(iconImagePreview, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 177, Short.MAX_VALUE)) 478 | .add(18, 18, 18) 479 | .add(createPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) 480 | .add(titleIdInput, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE) 481 | .add(titleIdLabel) 482 | .add(nameInput, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE) 483 | .add(chooseIcon) 484 | .add(nameLabel)) 485 | .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) 486 | .add(createPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) 487 | .add(createPanelLayout.createSequentialGroup() 488 | .add(parentalRatingLabel) 489 | .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) 490 | .add(parentalRatingInput, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE) 491 | .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) 492 | .add(storeTypeLabel) 493 | .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) 494 | .add(storeTypeInput, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE) 495 | .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) 496 | .add(analogModeCheckbox)) 497 | .add(createPanelLayout.createSequentialGroup() 498 | .add(createPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) 499 | .add(developerLabel) 500 | .add(developerInput, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE) 501 | .add(publisherLabel) 502 | .add(publisherInput, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)) 503 | .add(18, 18, 18) 504 | .add(createPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) 505 | .add(descriptionTextPane, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 93, Short.MAX_VALUE) 506 | .add(descriptionLabel)))) 507 | .add(18, 18, 18) 508 | .add(createPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.TRAILING) 509 | .add(convertButton) 510 | .add(convertProgress, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)) 511 | .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) 512 | .add(convertStatus, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 14, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE) 513 | .addContainerGap()) 514 | ); 515 | 516 | tabbedPane.addTab("Convert", createPanel); 517 | 518 | org.jdesktop.layout.GroupLayout layout = new org.jdesktop.layout.GroupLayout(getContentPane()); 519 | getContentPane().setLayout(layout); 520 | layout.setHorizontalGroup( 521 | layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) 522 | .add(tabbedPane, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 800, Short.MAX_VALUE) 523 | ); 524 | layout.setVerticalGroup( 525 | layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) 526 | .add(layout.createSequentialGroup() 527 | .add(tabbedPane, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 528, Short.MAX_VALUE) 528 | .addContainerGap()) 529 | ); 530 | 531 | pack(); 532 | }// //GEN-END:initComponents 533 | 534 | private void setFieldsFromProperties(Properties settings) { 535 | nameInput.setText(settings.getProperty("KEY_DISPLAY_NAME")); 536 | titleIdInput.setText(settings.getProperty("KEY_TITLE_ID")); 537 | developerInput.setText(settings.getProperty("KEY_DEVELOPER")); 538 | publisherInput.setText(settings.getProperty("KEY_PUBLISHER")); 539 | parentalRatingInput.setText(settings.getProperty("KEY_PARENTAL_RATING")); 540 | storeTypeInput.setText(settings.getProperty("KEY_STORE_TYPE")); 541 | descriptionTextInput.setText(settings.getProperty("KEY_DESCRIPTION")); 542 | analogModeCheckbox.setSelected(settings.getProperty("KEY_ANALOG_MODE").equals("YES") ? true : false); 543 | mIconImage = (File) settings.get("IconFile"); 544 | } 545 | 546 | private void setPropertiesFromFields(Properties settings) { 547 | settings.setProperty("KEY_DISPLAY_NAME", nameInput.getText()); 548 | settings.setProperty("KEY_TITLE_ID", titleIdInput.getText()); 549 | settings.setProperty("KEY_DEVELOPER", developerInput.getText()); 550 | settings.setProperty("KEY_PUBLISHER", publisherInput.getText()); 551 | settings.setProperty("KEY_PARENTAL_RATING", parentalRatingInput.getText()); 552 | settings.setProperty("KEY_STORE_TYPE", storeTypeInput.getText()); 553 | settings.setProperty("KEY_DESCRIPTION", descriptionTextInput.getText()); 554 | settings.setProperty("KEY_ANALOG_MODE", analogModeCheckbox.isSelected() ? "YES" : "NO"); 555 | if (mIconImage != null) 556 | settings.put("IconFile", mIconImage); 557 | } 558 | 559 | private void formWindowOpened(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_formWindowOpened 560 | try { 561 | tabbedPane.setEnabled(false); 562 | 563 | // Start logging 564 | Logger.setGUIFrame(this); 565 | Logger.setLevel(Logger.DEBUG); 566 | try { 567 | File log = new File(mCurrentDir, "psxperia.log"); 568 | if(log.exists()) 569 | log.delete(); 570 | log.createNewFile(); 571 | PrintStream stream = new PrintStream(log); 572 | Logger.setOutput(stream); 573 | } catch (IOException ex) { 574 | Logger.error("Cannot create log file"); 575 | } 576 | 577 | dataInput.setText((new File(mCurrentDir, "/data")).getPath()); 578 | extractOutputInput.setText((new File(mCurrentDir, "/data")).getPath()); 579 | convertOutputInput.setText((new File(mCurrentDir, "/output")).getPath()); 580 | if ((new File(mCurrentDir, "LICENSED")).exists()) { 581 | tabbedPane.setEnabled(true); 582 | tabbedPane.setSelectedIndex(2); 583 | } 584 | mSettings = new Properties(); 585 | mSettings.loadFromXML(PSXperiaTool.class.getResourceAsStream("/resources/defaults.xml")); 586 | setFieldsFromProperties(mSettings); 587 | mThis = this; 588 | } catch (IOException ex) { 589 | Logger.error("Cannot read default settings."); 590 | ex.printStackTrace(); 591 | } 592 | 593 | }//GEN-LAST:event_formWindowOpened 594 | 595 | private void licenseTextCaretUpdate(javax.swing.event.CaretEvent evt) {//GEN-FIRST:event_licenseTextCaretUpdate 596 | String selected = licenseText.getSelectedText(); 597 | if (selected != null && selected.endsWith("Yifan Lu")) { 598 | if (licenseCheck1.isSelected() && licenseCheck2.isSelected() && licenseCheck3.isSelected() & licenseCheck4.isSelected()) { 599 | tabbedPane.setEnabled(true); 600 | try { 601 | FileOutputStream out = new FileOutputStream(new File(mCurrentDir, "LICENSED")); 602 | out.write(1); 603 | out.close(); 604 | } catch (IOException ex) { 605 | Logger.error("Cannot save license status."); 606 | ex.printStackTrace(); 607 | } 608 | } 609 | } 610 | }//GEN-LAST:event_licenseTextCaretUpdate 611 | 612 | private void chooseApkFileActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_chooseApkFileActionPerformed 613 | FILE_CHOOSER.setFileSelectionMode(JFileChooser.FILES_ONLY); 614 | int returnVal = FILE_CHOOSER.showOpenDialog(this); 615 | if (returnVal == JFileChooser.APPROVE_OPTION) { 616 | File file = FILE_CHOOSER.getSelectedFile(); 617 | apkFileInput.setText(file.getPath()); 618 | } 619 | }//GEN-LAST:event_chooseApkFileActionPerformed 620 | 621 | private void chooseZpakFileActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_chooseZpakFileActionPerformed 622 | FILE_CHOOSER.setFileSelectionMode(JFileChooser.FILES_ONLY); 623 | int returnVal = FILE_CHOOSER.showOpenDialog(this); 624 | if (returnVal == JFileChooser.APPROVE_OPTION) { 625 | File file = FILE_CHOOSER.getSelectedFile(); 626 | zpakFileInput.setText(file.getPath()); 627 | } 628 | }//GEN-LAST:event_chooseZpakFileActionPerformed 629 | 630 | private void chooseOutputDirActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_chooseOutputDirActionPerformed 631 | FILE_CHOOSER.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); 632 | int returnVal = FILE_CHOOSER.showOpenDialog(this); 633 | if (returnVal == JFileChooser.APPROVE_OPTION) { 634 | File file = FILE_CHOOSER.getSelectedFile(); 635 | extractOutputInput.setText(file.getPath()); 636 | dataInput.setText(file.getPath()); 637 | } 638 | }//GEN-LAST:event_chooseOutputDirActionPerformed 639 | 640 | private void chooseDataActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_chooseDataActionPerformed 641 | FILE_CHOOSER.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); 642 | int returnVal = FILE_CHOOSER.showOpenDialog(this); 643 | if (returnVal == JFileChooser.APPROVE_OPTION) { 644 | File file = FILE_CHOOSER.getSelectedFile(); 645 | extractOutputInput.setText(file.getPath()); 646 | dataInput.setText(file.getPath()); 647 | } 648 | }//GEN-LAST:event_chooseDataActionPerformed 649 | 650 | private void chooseIconActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_chooseIconActionPerformed 651 | FILE_CHOOSER.setFileSelectionMode(JFileChooser.FILES_ONLY); 652 | int returnVal = FILE_CHOOSER.showOpenDialog(this); 653 | if (returnVal == JFileChooser.APPROVE_OPTION) { 654 | File file = FILE_CHOOSER.getSelectedFile(); 655 | if (!file.getName().endsWith(".png")) { 656 | Logger.warning("Invalid PNG image."); 657 | return; 658 | } 659 | try { 660 | BufferedImage image = ImageIO.read(file); 661 | iconImagePreview.setIcon(new ImageIcon(image)); 662 | mIconImage = file; 663 | } catch (IOException ex) { 664 | Logger.error("Cannot load image!"); 665 | ex.printStackTrace(); 666 | } 667 | } 668 | }//GEN-LAST:event_chooseIconActionPerformed 669 | 670 | private void chooseIsoActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_chooseIsoActionPerformed 671 | FILE_CHOOSER.setFileSelectionMode(JFileChooser.FILES_ONLY); 672 | int returnVal = FILE_CHOOSER.showOpenDialog(this); 673 | if (returnVal == JFileChooser.APPROVE_OPTION) { 674 | File file = FILE_CHOOSER.getSelectedFile(); 675 | isoInput.setText(file.getPath()); 676 | } 677 | }//GEN-LAST:event_chooseIsoActionPerformed 678 | 679 | private void chooseConvertOutputActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_chooseConvertOutputActionPerformed 680 | FILE_CHOOSER.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); 681 | int returnVal = FILE_CHOOSER.showOpenDialog(this); 682 | if (returnVal == JFileChooser.APPROVE_OPTION) { 683 | File file = FILE_CHOOSER.getSelectedFile(); 684 | convertOutputInput.setText(file.getPath()); 685 | } 686 | }//GEN-LAST:event_chooseConvertOutputActionPerformed 687 | 688 | private void convertButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_convertButtonActionPerformed 689 | Runnable run = new Runnable() { 690 | public void run() { 691 | try { 692 | mThis.setEnabled(false); 693 | convertButton.setEnabled(false); 694 | CommandLine.verifyTitleID(titleIdInput.getText()); 695 | setPropertiesFromFields(mSettings); 696 | File inputFile = new File(isoInput.getText()); 697 | File dataDir = new File(dataInput.getText()); 698 | File outputDir = new File(convertOutputInput.getText()); 699 | PSXperiaTool tool = new PSXperiaTool(mSettings, inputFile, dataDir, outputDir); 700 | ProgressMonitor.ProgressCallback callback = new ProgressMonitor.ProgressCallback() { 701 | 702 | public void nextStep(String string) { 703 | convertStatus.setText(string); 704 | } 705 | 706 | public void stepsTook(int current, int max) { 707 | convertProgress.setMaximum(max); 708 | convertProgress.setValue(current); 709 | } 710 | }; 711 | tool.setCallback(callback); 712 | tool.startBuild(); 713 | convertProgress.setValue(0); 714 | convertButton.setEnabled(true); 715 | mThis.setEnabled(true); 716 | } catch (InputMismatchException ex) { 717 | Logger.error("Input error: %s", ex.getMessage()); 718 | ex.printStackTrace(); 719 | } catch (InterruptedException ex) { 720 | Logger.error("Cannot run build commands, are \"aapk\" and \"jarsigner\" in your system's PATH variable? Java says: %s", ex.getMessage()); 721 | ex.printStackTrace(); 722 | } catch (IOException ex) { 723 | Logger.error("Cannot build APK! Java says: %s", ex.getMessage()); 724 | ex.printStackTrace(); 725 | } catch (GeneralSecurityException ex) { 726 | Logger.error("Error signing JAR, Java says: %s", ex.getMessage()); 727 | ex.printStackTrace(); 728 | } catch (SignedJarBuilder.IZipEntryFilter.ZipAbortException ex) { 729 | Logger.error("Error signing JAR, Java says: %s", ex.getMessage()); 730 | ex.printStackTrace(); 731 | } finally { 732 | convertProgress.setValue(0); 733 | convertButton.setEnabled(true); 734 | mThis.setEnabled(true); 735 | } 736 | } 737 | }; 738 | (new Thread(run)).start(); 739 | }//GEN-LAST:event_convertButtonActionPerformed 740 | 741 | private void extractButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_extractButtonActionPerformed 742 | Runnable run = new Runnable() { 743 | public void run() { 744 | try { 745 | mThis.setEnabled(false); 746 | extractButton.setEnabled(false); 747 | File inputApk = new File(apkFileInput.getText()); 748 | File inputZpak = new File(zpakFileInput.getText()); 749 | File outputDataDir = new File(extractOutputInput.getText()); 750 | if (!inputApk.exists()) { 751 | Logger.error("Cannot find APK file!"); 752 | return; 753 | } 754 | if (!inputZpak.exists()) { 755 | Logger.error("Cannot find ZPAK file!"); 756 | return; 757 | } 758 | CrashBandicootExtractor extract = new CrashBandicootExtractor(inputApk, inputZpak, outputDataDir); 759 | ProgressMonitor.ProgressCallback callback = new ProgressMonitor.ProgressCallback() { 760 | 761 | public void nextStep(String string) { 762 | extractStatus.setText(string); 763 | } 764 | 765 | public void stepsTook(int current, int max) { 766 | extractProgress.setMaximum(max); 767 | extractProgress.setValue(current); 768 | } 769 | }; 770 | extract.setCallback(callback); 771 | extract.extractApk(); 772 | extractProgress.setValue(0); 773 | extractButton.setEnabled(true); 774 | mThis.setEnabled(true); 775 | } catch (IOException ex) { 776 | Logger.error("Cannot extract APK! Java says %s", ex.getMessage()); 777 | ex.printStackTrace(); 778 | } catch (UnsupportedOperationException ex) { 779 | Logger.error("Unsupported exception: %s", ex.getMessage()); 780 | ex.printStackTrace(); 781 | } catch (Exception ex) { 782 | Logger.error("Exception: %s", ex.getMessage()); 783 | ex.printStackTrace(); 784 | } finally { 785 | extractProgress.setValue(0); 786 | extractButton.setEnabled(true); 787 | mThis.setEnabled(true); 788 | } 789 | } 790 | }; 791 | (new Thread(run)).start(); 792 | }//GEN-LAST:event_extractButtonActionPerformed 793 | 794 | /** 795 | * @param args the command line arguments 796 | */ 797 | public static void main(String args[]) { 798 | 799 | /* Create and display the form */ 800 | java.awt.EventQueue.invokeLater(new Runnable() { 801 | 802 | public void run() { 803 | new GUI().setVisible(true); 804 | } 805 | }); 806 | 807 | } 808 | 809 | private JFrame mThis; 810 | private static final JFileChooser FILE_CHOOSER = new JFileChooser(); 811 | private static final File mCurrentDir = new File(new File(".").getAbsolutePath()); 812 | private File mIconImage; 813 | private Properties mSettings; 814 | // Variables declaration - do not modify//GEN-BEGIN:variables 815 | private javax.swing.JCheckBox analogModeCheckbox; 816 | private javax.swing.JTextField apkFileInput; 817 | private javax.swing.JLabel apkFileLabel; 818 | private javax.swing.JButton chooseApkFile; 819 | private javax.swing.JButton chooseConvertOutput; 820 | private javax.swing.JButton chooseData; 821 | private javax.swing.JButton chooseIcon; 822 | private javax.swing.JButton chooseIso; 823 | private javax.swing.JButton chooseOutputDir; 824 | private javax.swing.JButton chooseZpakFile; 825 | private javax.swing.JButton convertButton; 826 | private javax.swing.JTextField convertOutputInput; 827 | private javax.swing.JLabel convertOutputLabel; 828 | private javax.swing.JProgressBar convertProgress; 829 | private javax.swing.JSeparator convertSeparator; 830 | private javax.swing.JLabel convertStatus; 831 | private javax.swing.JPanel createPanel; 832 | private javax.swing.JTextField dataInput; 833 | private javax.swing.JLabel dataLabel; 834 | private javax.swing.JLabel descriptionLabel; 835 | private javax.swing.JTextArea descriptionTextInput; 836 | private javax.swing.JScrollPane descriptionTextPane; 837 | private javax.swing.JTextField developerInput; 838 | private javax.swing.JLabel developerLabel; 839 | private javax.swing.JButton extractButton; 840 | private javax.swing.JLabel extractInformation; 841 | private javax.swing.JTextField extractOutputInput; 842 | private javax.swing.JLabel extractOutputLabel; 843 | private javax.swing.JPanel extractPanel; 844 | private javax.swing.JProgressBar extractProgress; 845 | private javax.swing.JLabel extractStatus; 846 | private javax.swing.JLabel gameInformationLabel; 847 | private javax.swing.JButton getTitleIdButton; 848 | private javax.swing.JLabel iconImagePreview; 849 | private javax.swing.JPanel informationPanel; 850 | private javax.swing.JTextField isoInput; 851 | private javax.swing.JLabel isoLabel; 852 | private javax.swing.JCheckBox licenseCheck1; 853 | private javax.swing.JCheckBox licenseCheck2; 854 | private javax.swing.JCheckBox licenseCheck3; 855 | private javax.swing.JCheckBox licenseCheck4; 856 | private javax.swing.JTextArea licenseText; 857 | private javax.swing.JButton loadXmlButton; 858 | private javax.swing.JTextField nameInput; 859 | private javax.swing.JLabel nameLabel; 860 | private javax.swing.JTextField parentalRatingInput; 861 | private javax.swing.JLabel parentalRatingLabel; 862 | private javax.swing.JTextField publisherInput; 863 | private javax.swing.JLabel publisherLabel; 864 | private javax.swing.JTextField storeTypeInput; 865 | private javax.swing.JLabel storeTypeLabel; 866 | private javax.swing.JTabbedPane tabbedPane; 867 | private javax.swing.JScrollPane textScrollPane; 868 | private javax.swing.JTextField titleIdInput; 869 | private javax.swing.JLabel titleIdLabel; 870 | private javax.swing.JTextField zpakFileInput; 871 | private javax.swing.JLabel zpakFileLabel; 872 | // End of variables declaration//GEN-END:variables 873 | } 874 | -------------------------------------------------------------------------------- /src/com/yifanlu/PSXperiaTool/Interface/Strings.properties: -------------------------------------------------------------------------------- 1 | # To change this template, choose Tools | Templates 2 | # and open the template in the editor. 3 | 4 | extractDirections=You need to extract some files from the Crash Bandicoot APK that came with your Xperia Play.
\nThe APK is named either com.sony.playstation.ncua94900_1.apk or com.sony.playstation.ncea00344_1.apk and can be found in the "/system/app" folder of your Android phone's internal memory.
\nThe data ZPAK file is found on your phone's SD card under "/Android/data/com.sony.playstation.NCUA94900_1/files/content" or "/Android/data/com.sony.playstation.NCEA00344_1/files/content" 5 | extract.apkfile=APK File: 6 | extract.zpakfile=ZPAK File: 7 | extract.output=Output: 8 | # To change this template, choose Tools | Templates 9 | # and open the template in the editor. 10 | extract.directions=You need to extract some files from the Crash Bandicoot APK that came with your Xperia Play.
The APK is named either com.sony.playstation.ncua94900_1.apk or com.sony.playstation.ncea00344_1.apk and can be found in the "/system/app" folder of your Android phone's internal memory.
The data ZPAK file is found on your phone's SD card under "/Android/data/com.sony.playstation.NCUA94900_1/files/content" or "/Android/data/com.sony.playstation.NCEA00344_1/files/content" 11 | extract.choose=Choose 12 | extract.extract=Extract 13 | convert.extracted_data=Extracted Data: 14 | convert.iso_input=PSX Image Input: 15 | convert.output_directory=Output Directory: 16 | convert.choose=Choose 17 | convert.game_information=Game Information 18 | convert.get_title_id=Get Title ID From ISO 19 | convert.load_xml=Load From XML 20 | convert.name=Name: 21 | convert.title_id=Title ID: 22 | convert.developer=Developer: 23 | convert.publisher=Publisher 24 | convert.parental_rating=Parental Rating: 25 | convert.store_type=Store Type 26 | convert.analog_mode=Analog Mode 27 | convert.convert=Convert 28 | convert.extracted_data.tooltip=Use the extract tool if you don't have this. 29 | common.disabled_control=This control is not implemented. 30 | convert.name.tooltip=This will show up under the icon. 31 | convert.title_id.tooltip=Any unique string. Recommended to be PSX title id. 32 | convert.developer.tooltip=Developer of the game. Not required. 33 | convert.publisher.tooltip=Publisher of the game. Not required. 34 | convert.parental_rating.tooltip=Not required. Any string. 35 | convert.store_type.tooltip=Not required. Any string. 36 | convert.analog_mode.tooltip=Enables analog controller on supported games. 37 | -------------------------------------------------------------------------------- /src/com/yifanlu/PSXperiaTool/Logger.java: -------------------------------------------------------------------------------- 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 . 17 | */ 18 | 19 | package com.yifanlu.PSXperiaTool; 20 | 21 | import javax.swing.JFrame; 22 | import javax.swing.JOptionPane; 23 | import java.io.OutputStream; 24 | import java.io.PrintStream; 25 | 26 | public class Logger { 27 | public static final int ALL = 0x4; 28 | public static final int DEBUG = 0x3; 29 | public static final int INFO = 0x2; 30 | public static final int WARNING = 0x1; 31 | public static final int ERROR = 0x0; 32 | private static Logger ourInstance = new Logger(); 33 | private static int mLevel; 34 | private static JFrame mFrame; 35 | 36 | public Logger() { 37 | this.mLevel = ERROR; 38 | } 39 | 40 | public static void setOutput(PrintStream out){ 41 | System.setOut(out); 42 | } 43 | 44 | public static Logger getInstance() { 45 | return ourInstance; 46 | } 47 | 48 | public static void setLevel(int level) { 49 | mLevel = level; 50 | } 51 | 52 | public static int getLevel() { 53 | return mLevel; 54 | } 55 | 56 | public static void setGUIFrame(JFrame frame){ 57 | mFrame = frame; 58 | } 59 | 60 | public static void verbose(String input) { 61 | verbose("%s", input); 62 | } 63 | 64 | public static void debug(String input) { 65 | debug("%s", input); 66 | } 67 | 68 | public static void info(String input) { 69 | info("%s", input); 70 | } 71 | 72 | public static void warning(String input) { 73 | warning("%s", input); 74 | } 75 | 76 | public static void error(String input) { 77 | error("%s", input); 78 | } 79 | 80 | public static void verbose(String format, Object... input) { 81 | if (mLevel >= ALL) 82 | System.out.printf("%s" + format + "\n", addObjectToArray("[V] ", input)); 83 | } 84 | 85 | public static void debug(String format, Object... input) { 86 | if (mLevel >= DEBUG) 87 | System.out.printf("%s" + format + "\n", addObjectToArray("[D] ", input)); 88 | } 89 | 90 | public static void info(String format, Object... input) { 91 | if (mLevel >= INFO) 92 | System.out.printf("%s" + format + "\n", addObjectToArray("[I] ", input)); 93 | } 94 | 95 | public static void warning(String format, Object... input) { 96 | if (mLevel >= WARNING){ 97 | System.out.printf("%s" + format + "\n", addObjectToArray("[W] ", input)); 98 | if(mFrame != null) 99 | JOptionPane.showMessageDialog(mFrame, String.format(format, input), "Warning", JOptionPane.WARNING_MESSAGE); 100 | } 101 | } 102 | 103 | public static void error(String format, Object... input) { 104 | if (mLevel >= ERROR){ 105 | System.out.printf("%s" + format + "\n", addObjectToArray("[E] ", input)); 106 | if(mFrame != null) 107 | JOptionPane.showMessageDialog(mFrame, String.format(format, input), "Error", JOptionPane.ERROR_MESSAGE); 108 | } 109 | } 110 | 111 | private static Object[] addObjectToArray(Object obj, Object[] arr) { 112 | Object[] newArr = new Object[arr.length + 1]; 113 | newArr[0] = obj; 114 | System.arraycopy(arr, 0, newArr, 1, arr.length); 115 | return newArr; 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /src/com/yifanlu/PSXperiaTool/PSImage.java: -------------------------------------------------------------------------------- 1 | /* 2 | * PSXperia Converter Tool - Generic PSImage functions 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 . 17 | */ 18 | 19 | package com.yifanlu.PSXperiaTool; 20 | 21 | import java.io.InputStream; 22 | 23 | public abstract class PSImage { 24 | public interface ProgressCallback { 25 | public void bytesReadChanged(int delta); 26 | 27 | public void bytesWrittenChanged(int delta); 28 | } 29 | 30 | public final static int BLOCK_SIZE = 0x1000; 31 | public final static long PART_SIZE = 0x9300; 32 | public final static int PART_BS = 0x700; 33 | protected final static byte[] HEADER = {0x07, 0x70, (byte)((0xFF)&(0xFE)), (byte)((0xFF)&(0xDA)), 0x03, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; 34 | protected InputStream mIn; 35 | protected byte[] mBuff; 36 | protected int mBytesWritten; 37 | protected int mBytesRead; 38 | private ProgressCallback mCallback; 39 | 40 | public PSImage() { 41 | this.mIn = null; 42 | this.mBuff = null; 43 | } 44 | 45 | protected PSImage(InputStream in) { 46 | this.mIn = in; 47 | this.mBuff = new byte[BLOCK_SIZE]; 48 | } 49 | 50 | protected void check() throws IllegalArgumentException { 51 | if (mIn == null || mBuff == null) 52 | throw new IllegalArgumentException("Not enough data to start!"); 53 | } 54 | 55 | public void setCallback(ProgressCallback call) { 56 | mCallback = call; 57 | } 58 | 59 | public void removeCallback() { 60 | mCallback = null; 61 | } 62 | 63 | protected synchronized void addBytesRead(int num) { 64 | mBytesRead += num; 65 | if (mCallback != null) 66 | mCallback.bytesReadChanged(num); 67 | } 68 | 69 | protected synchronized void addBytesWritten(int num) { 70 | mBytesWritten += num; 71 | if (mCallback != null) 72 | mCallback.bytesWrittenChanged(num); 73 | } 74 | 75 | public synchronized int getBytesRead() { 76 | return mBytesRead; 77 | } 78 | 79 | public synchronized int getBytesWritten() { 80 | return mBytesWritten; 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/com/yifanlu/PSXperiaTool/PSImageCreate.java: -------------------------------------------------------------------------------- 1 | /* 2 | * PSXperia Converter Tool - PSImage creation 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 . 17 | */ 18 | 19 | package com.yifanlu.PSXperiaTool; 20 | 21 | import java.io.*; 22 | import java.nio.ByteBuffer; 23 | import java.nio.ByteOrder; 24 | import java.util.ArrayList; 25 | import java.util.Iterator; 26 | import java.util.zip.Deflater; 27 | import java.util.zip.DeflaterOutputStream; 28 | 29 | public class PSImageCreate extends PSImage { 30 | public final static byte[] TOC_HEADER = {0x04, 0x00, 0x00, 0x00}; 31 | public final static byte[] TOC_CONST = {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00}; 32 | private ArrayList mEntries; 33 | 34 | public PSImageCreate(InputStream in) { 35 | super(in); 36 | } 37 | 38 | public void compress(OutputStream out) throws IOException { 39 | check(); 40 | Logger.info("Beginning PSImage compression."); 41 | mEntries = new ArrayList(); 42 | out.write(HEADER); 43 | mBytesRead = 0; 44 | mBytesWritten = HEADER.length; 45 | while (mIn.available() != 0) { 46 | InputStream in = splitPart(); 47 | compressPart(in, out); 48 | in.close(); 49 | } 50 | (new File("temp.dat")).deleteOnExit(); 51 | } 52 | 53 | protected FileInputStream splitPart() throws IOException { 54 | Logger.verbose("Splitting image."); 55 | FileOutputStream out = new FileOutputStream("temp.dat"); 56 | byte[] buff = new byte[PART_BS]; 57 | int n; 58 | long count = PART_SIZE / PART_BS; 59 | while (count-- > 0) { 60 | if ((n = mIn.read(buff, 0, PART_BS)) == -1) 61 | break; 62 | addBytesRead(n); 63 | out.write(buff, 0, n); 64 | } 65 | out.close(); 66 | Logger.verbose("Done splitting image."); 67 | return new FileInputStream("temp.dat"); 68 | } 69 | 70 | protected void compressPart(InputStream in, OutputStream out) throws IOException { 71 | Logger.verbose("Compressing part."); 72 | Deflater defl = new Deflater(Deflater.DEFAULT_COMPRESSION); 73 | DeflaterOutputStream zOut = new DeflaterOutputStream(out, defl); 74 | // temp, Deflate.getBytesWritten() is broken 75 | mEntries.add((int) ((FileOutputStream) out).getChannel().size()); 76 | // 77 | byte[] buff = new byte[PART_BS]; 78 | int n; 79 | while ((n = in.read(buff, 0, PART_BS)) != -1) { 80 | zOut.write(buff, 0, n); 81 | } 82 | addBytesWritten((int) defl.getBytesWritten()); 83 | zOut.finish(); 84 | Logger.verbose("Done compressing part."); 85 | } 86 | 87 | public void writeTocTable(OutputStream out) throws IOException { 88 | Logger.info("Generating image TOC."); 89 | int size = (0x18 + 0x4 * mEntries.size()); 90 | ByteBuffer bb = ByteBuffer.allocate(size); 91 | bb.order(ByteOrder.LITTLE_ENDIAN); 92 | bb.put(TOC_HEADER); 93 | bb.putInt(getBytesRead()); 94 | bb.put(TOC_CONST); 95 | bb.putInt(mEntries.size()); 96 | Iterator it = mEntries.iterator(); 97 | while (it.hasNext()) { 98 | bb.putInt(it.next()); 99 | } 100 | out.write(bb.array()); 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /src/com/yifanlu/PSXperiaTool/PSImageExtract.java: -------------------------------------------------------------------------------- 1 | /* 2 | * PSXperia Converter Tool - PSImage Extraction 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 . 17 | */ 18 | 19 | package com.yifanlu.PSXperiaTool; 20 | 21 | import java.io.IOException; 22 | import java.io.InputStream; 23 | import java.io.OutputStream; 24 | import java.util.zip.DataFormatException; 25 | import java.util.zip.Inflater; 26 | 27 | public class PSImageExtract extends PSImage { 28 | public PSImageExtract(InputStream in) { 29 | super(in); 30 | } 31 | 32 | public void uncompress(OutputStream out) throws IOException, DataFormatException { 33 | Logger.info("Extracting PS Image [BETA! This tool WILL return with an exception, even if successful]."); 34 | check(); 35 | mIn.skip(HEADER.length); 36 | mBytesRead = HEADER.length; 37 | mBytesWritten = 0; 38 | Inflater inf = new Inflater(); 39 | int n; 40 | byte[] buff = new byte[BLOCK_SIZE]; 41 | try 42 | { 43 | while ((n = inf.inflate(buff, 0, BLOCK_SIZE)) != -1) { 44 | out.write(buff, 0, n); 45 | addBytesWritten(n); 46 | 47 | if (inf.finished() || inf.needsDictionary()) { 48 | int remainder = inf.getRemaining(); 49 | changeBuffer(remainder); 50 | inf.reset(); 51 | inf.setInput(mBuff, 0, remainder); 52 | } else if (inf.needsInput()) { 53 | fill(inf); 54 | } 55 | } 56 | }catch(DataFormatException ex){ 57 | out.write(new byte[]{0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}); 58 | out.write(mBuff); 59 | byte[] b = new byte[1024]; 60 | mIn.read(b); 61 | out.write(b); 62 | out.close(); 63 | throw ex; 64 | } 65 | Logger.debug("Extraction done."); 66 | } 67 | 68 | protected void fill(Inflater inf) throws IOException { 69 | Logger.verbose("Filling buffer with compressed data."); 70 | if (mBuff.length < BLOCK_SIZE) 71 | mBuff = new byte[BLOCK_SIZE]; 72 | int n = mIn.read(mBuff, 0, BLOCK_SIZE); 73 | if (n == -1) { 74 | throw new IOException("Unexpected end of ZLIB input stream"); 75 | } 76 | inf.setInput(mBuff, 0, BLOCK_SIZE); 77 | addBytesRead(n); 78 | } 79 | 80 | protected void changeBuffer(int remaining) throws IOException { 81 | Logger.verbose("End of segment, shifting buffer and trying next segment."); 82 | int bs = mBuff.length; 83 | byte[] newBuff = new byte[remaining]; 84 | int i, j; 85 | i = bs - remaining; 86 | j = 0; 87 | while (i < bs) { 88 | newBuff[j++] = mBuff[i++]; 89 | } 90 | mBuff = newBuff; 91 | } 92 | 93 | } 94 | -------------------------------------------------------------------------------- /src/com/yifanlu/PSXperiaTool/PSXperiaTool.java: -------------------------------------------------------------------------------- 1 | /* 2 | * PSXperia Converter Tool - Main backend 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 . 17 | */ 18 | 19 | package com.yifanlu.PSXperiaTool; 20 | 21 | import com.android.sdklib.internal.build.SignedJarBuilder; 22 | import org.apache.commons.io.FileUtils; 23 | 24 | import java.io.*; 25 | import java.nio.ByteBuffer; 26 | import java.nio.ByteOrder; 27 | import java.security.GeneralSecurityException; 28 | import java.util.*; 29 | 30 | public class PSXperiaTool extends ProgressMonitor { 31 | public static final String VERSION = "2.0 Beta"; 32 | public static final String[] FILES_TO_MODIFY = { 33 | //"/AndroidManifest.xml", 34 | "/assets/AndroidManifest.xml", 35 | "/assets/ZPAK/metadata.xml", 36 | "/res/values/strings.xml", 37 | "/ZPAK/metadata.xml" 38 | }; 39 | 40 | private File mInputFile; 41 | private File mDataDir; 42 | private File mTempDir = null; 43 | private File mOutputDir; 44 | private Properties mProperties; 45 | private static final int TOTAL_STEPS = 9; 46 | 47 | public PSXperiaTool(Properties properties, File inputFile, File dataDir, File outputDir) { 48 | mInputFile = inputFile; 49 | mDataDir = dataDir; 50 | mProperties = properties; 51 | mOutputDir = outputDir; 52 | Logger.info("PSXperiaTool initialized, outputting to: %s", mOutputDir.getPath()); 53 | setTotalSteps(TOTAL_STEPS); 54 | } 55 | 56 | public void startBuild() throws IOException, InterruptedException, GeneralSecurityException, SignedJarBuilder.IZipEntryFilter.ZipAbortException { 57 | Logger.info("Starting build with PSXPeria Converter version %s", VERSION); 58 | checkData(mDataDir); 59 | mTempDir = createTempDir(mDataDir); 60 | copyIconImage((File) mProperties.get("IconFile")); 61 | //BuildResources br = new BuildResources(mProperties, mTempDir); 62 | replaceStrings(); 63 | patchGame(); 64 | generateImage(); 65 | generateDefaultZpak(); 66 | //buildResources(br); 67 | generateOutput(); 68 | nextStep("Deleting temporary directory"); 69 | FileUtils.deleteDirectory(mTempDir); 70 | nextStep("Done."); 71 | } 72 | 73 | private File createTempDir(File dataDir) throws IOException { 74 | nextStep("Creating temporary directory."); 75 | File tempDir = new File(new File("."), "/.psxperia." + (int) (Math.random() * 1000)); 76 | if (tempDir.exists()) 77 | FileUtils.deleteDirectory(tempDir); 78 | if (!tempDir.mkdirs()) 79 | throw new IOException("Cannot create temporary directory!"); 80 | FileUtils.copyDirectory(dataDir, tempDir); 81 | Logger.debug("Created temporary directory at, %s", tempDir.getPath()); 82 | return tempDir; 83 | } 84 | 85 | private void checkData(File dataDir) throws IllegalArgumentException, IOException { 86 | nextStep("Checking to make sure all files are there."); 87 | if(!mDataDir.exists()) 88 | throw new FileNotFoundException("Cannot find data directory!"); 89 | File filelist = new File(mDataDir, "/config/filelist.txt"); 90 | if(!filelist.exists()) 91 | throw new FileNotFoundException("Cannot find list to validate files!"); 92 | InputStream fstream = new FileInputStream(filelist); 93 | BufferedReader reader = new BufferedReader(new InputStreamReader(fstream)); 94 | String line; 95 | while((line = reader.readLine()) != null){ 96 | if(line.isEmpty()) 97 | continue; 98 | File check = new File(mDataDir, line); 99 | if(!check.exists()) 100 | throw new IllegalArgumentException("Cannot find required data file: " + line); 101 | } 102 | Properties config = new Properties(); 103 | config.loadFromXML(new FileInputStream(new File(mDataDir, "/config/config.xml"))); 104 | Logger.info( 105 | "Using data from " + config.getProperty("game_name", "Unknown Game") + 106 | " " + config.getProperty("game_region") + 107 | " Version " + config.getProperty("game_version", "Unknown") + 108 | ", CRC32: " + config.getProperty("game_crc32", "Unknown") 109 | ); 110 | Logger.debug("Done checking data."); 111 | } 112 | 113 | private void copyIconImage(File image) throws IllegalArgumentException, IOException { 114 | nextStep("Copying icon if needed."); 115 | if (image == null || !(image instanceof File)){ 116 | Logger.verbose("Icon copying not needed."); 117 | return; 118 | } 119 | if (!image.exists()) 120 | throw new IllegalArgumentException("Icon file not found."); 121 | FileUtils.copyFile(image, new File(mTempDir, "/res/drawable/icon.png")); 122 | FileUtils.copyFile(image, new File(mTempDir, "/assets/ZPAK/assets/default/bitmaps/icon.png")); 123 | Logger.debug("Done copying icon from %s", image.getPath()); 124 | } 125 | 126 | public void replaceStrings() throws IOException { 127 | nextStep("Replacing strings."); 128 | Map replacement = new TreeMap(); 129 | Iterator it = mProperties.keySet().iterator(); 130 | while (it.hasNext()) { 131 | String key = (String) it.next(); 132 | Object value = mProperties.getProperty(key); 133 | if (!(value instanceof String)) 134 | continue; 135 | if (!(key.startsWith("KEY_"))) 136 | continue; 137 | String find = ((String) key).substring("KEY_".length()); 138 | Logger.verbose("Found replacement key: %s, replacing with: %s", find, value); 139 | replacement.put("\\{" + find + "\\}", (String) value); 140 | replacement.put("\\{FILTERED_" + find + "\\}", StringReplacement.filter((String) value)); 141 | } 142 | StringReplacement strReplace = new StringReplacement(replacement, mTempDir); 143 | strReplace.execute(FILES_TO_MODIFY); 144 | Logger.debug("Done replacing strings."); 145 | } 146 | 147 | private void patchGame() throws IOException { 148 | /* 149 | * Custom patch format (config/game-patch.bin) is as follows: 150 | * 0x8 byte little endian: Address in game image to start patching 151 | * 0x8 byte little endian: Length of patch 152 | * If there are more patches, repeat after reading the length of patch 153 | * Note that all games will be patched the same way, so if a game is broken before patching, it will still be broken! 154 | */ 155 | nextStep("Patching game."); 156 | File gamePatch = new File(mTempDir, "/config/game-patch.bin"); 157 | if(!gamePatch.exists()) 158 | return; 159 | Logger.info("Making a copy of game."); 160 | File tempGame = new File(mTempDir, "game.iso"); 161 | FileUtils.copyFile(mInputFile, tempGame); 162 | RandomAccessFile game = new RandomAccessFile(tempGame, "rw"); 163 | InputStream patch = new FileInputStream(gamePatch); 164 | while(true){ 165 | byte[] rawPatchAddr = new byte[8]; 166 | byte[] rawPatchLen = new byte[8]; 167 | if(patch.read(rawPatchAddr) + patch.read(rawPatchLen) < rawPatchAddr.length + rawPatchLen.length) 168 | break; 169 | ByteBuffer bb = ByteBuffer.wrap(rawPatchAddr); 170 | bb.order(ByteOrder.LITTLE_ENDIAN); 171 | long patchAddr = bb.getLong(); 172 | bb = ByteBuffer.wrap(rawPatchLen); 173 | bb.order(ByteOrder.LITTLE_ENDIAN); 174 | long patchLen = bb.getLong(); 175 | 176 | game.seek(patchAddr); 177 | while(patchLen --> 0){ 178 | game.write(patch.read()); 179 | } 180 | } 181 | mInputFile = tempGame; 182 | game.close(); 183 | patch.close(); 184 | Logger.debug("Done patching game."); 185 | } 186 | 187 | private void generateImage() throws IOException { 188 | nextStep("Generating PSImage."); 189 | FileInputStream in = new FileInputStream(mInputFile); 190 | FileOutputStream out = new FileOutputStream(new File(mTempDir, "/ZPAK/data/image.ps")); 191 | FileOutputStream tocOut = new FileOutputStream(new File(mTempDir, "/image_ps_toc.bin")); 192 | PSImageCreate ps = new PSImageCreate(in); 193 | PSImage.ProgressCallback progress = new PSImage.ProgressCallback() { 194 | int mBytesRead = 0, mBytesWritten = 0; 195 | 196 | public void bytesReadChanged(int delta) { 197 | mBytesRead += delta; 198 | jump(mBytesRead); 199 | Logger.verbose("Image bytes read: %d", mBytesRead); 200 | } 201 | 202 | public void bytesWrittenChanged(int delta) { 203 | mBytesWritten += delta; 204 | Logger.verbose("Compressed PSImage bytes written: %d", mBytesWritten); 205 | } 206 | }; 207 | // progress management 208 | int oldSteps = getSteps(); 209 | setTotalSteps((int)in.getChannel().size()); 210 | jump(0); 211 | 212 | ps.setCallback(progress); 213 | ps.compress(out); 214 | ps.writeTocTable(tocOut); 215 | out.close(); 216 | tocOut.close(); 217 | in.close(); 218 | 219 | setTotalSteps(TOTAL_STEPS); 220 | jump(oldSteps); 221 | 222 | Logger.debug("Done generating PSImage"); 223 | Logger.debug("Deleting temporary patched game."); 224 | FileUtils.deleteQuietly(new File(mTempDir, "game.iso")); 225 | 226 | Logger.info("Generating ZPAK."); 227 | File zpakDirectory = new File(mTempDir, "/ZPAK"); 228 | File zpakFile = new File(mTempDir, "/" + mProperties.getProperty("KEY_TITLE_ID") + ".zpak"); 229 | FileOutputStream zpakOut = new FileOutputStream(zpakFile); 230 | ZpakCreate zcreate = new ZpakCreate(zpakOut, zpakDirectory); 231 | zcreate.create(true); 232 | FileUtils.deleteDirectory(zpakDirectory); 233 | Logger.debug("Done generating ZPAK at %s", zpakFile.getPath()); 234 | } 235 | 236 | private void generateDefaultZpak() throws IOException { 237 | nextStep("Generating default ZPAK."); 238 | File defaultZpakDirectory = new File(mTempDir, "/assets/ZPAK"); 239 | File zpakFile = new File(mTempDir, "/assets/" + mProperties.getProperty("KEY_TITLE_ID") + ".zpak"); 240 | FileOutputStream zpakOut = new FileOutputStream(zpakFile); 241 | ZpakCreate zcreate = new ZpakCreate(zpakOut, defaultZpakDirectory); 242 | zcreate.create(false); 243 | zpakOut.close(); 244 | FileUtils.deleteDirectory(defaultZpakDirectory); 245 | Logger.debug("Done generating default ZPAK at %s", zpakFile.getPath()); 246 | } 247 | 248 | private void generateOutput() throws IOException, InterruptedException, GeneralSecurityException, SignedJarBuilder.IZipEntryFilter.ZipAbortException { 249 | nextStep("Done processing, generating output."); 250 | String titleId = mProperties.getProperty("KEY_TITLE_ID"); 251 | if (!mOutputDir.exists()) 252 | mOutputDir.mkdir(); 253 | File outDataDir = new File(mOutputDir, "/data/com.sony.playstation." + titleId + "/files/content"); 254 | if (!outDataDir.exists()) 255 | outDataDir.mkdirs(); 256 | Logger.debug("Moving files around."); 257 | FileUtils.cleanDirectory(outDataDir); 258 | FileUtils.moveFileToDirectory(new File(mTempDir, "/" + titleId + ".zpak"), outDataDir, false); 259 | FileUtils.moveFileToDirectory(new File(mTempDir, "/image_ps_toc.bin"), outDataDir, false); 260 | Logger.verbose("Deleting config from temp directory."); 261 | FileUtils.deleteDirectory(new File(mTempDir, "/config")); 262 | File outApk = new File(mOutputDir, "/com.sony.playstation." + titleId + ".apk"); 263 | 264 | ApkBuilder build = new ApkBuilder(mTempDir, outApk); 265 | build.buildApk(); 266 | 267 | Logger.info("Done."); 268 | Logger.info("APK file: %s", outApk.getPath()); 269 | Logger.info("Data dir: %s", outDataDir.getPath()); 270 | 271 | } 272 | 273 | 274 | } 275 | -------------------------------------------------------------------------------- /src/com/yifanlu/PSXperiaTool/ProgressMonitor.java: -------------------------------------------------------------------------------- 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 . 17 | */ 18 | 19 | package com.yifanlu.PSXperiaTool; 20 | 21 | public class ProgressMonitor { 22 | public interface ProgressCallback { 23 | public void nextStep(String message); 24 | public void stepsTook(int steps, int total); 25 | } 26 | private ProgressCallback mCallback; 27 | private int mTotalSteps = 0; 28 | private int mSteps = 0; 29 | 30 | public void setCallback(ProgressCallback callback){ 31 | mCallback = callback; 32 | } 33 | 34 | public void setTotalSteps(int steps){ 35 | this.mTotalSteps = steps; 36 | } 37 | 38 | public int getSteps(){ 39 | return mSteps; 40 | } 41 | 42 | public void jump(int steps){ 43 | this.mSteps = steps; 44 | if(mCallback != null){ 45 | mCallback.stepsTook(mSteps, mTotalSteps); 46 | } 47 | } 48 | 49 | public void nextStep(String message){ 50 | Logger.info(message); 51 | mSteps++; 52 | if(mCallback != null){ 53 | mCallback.nextStep(message); 54 | mCallback.stepsTook(mSteps, mTotalSteps); 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/com/yifanlu/PSXperiaTool/StringReplacement.java: -------------------------------------------------------------------------------- 1 | /* 2 | * PSXperia Converter Tool - String search & replacement 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 . 17 | */ 18 | 19 | package com.yifanlu.PSXperiaTool; 20 | 21 | import org.apache.commons.io.FileUtils; 22 | 23 | import java.io.*; 24 | import java.util.Iterator; 25 | import java.util.Map; 26 | 27 | public class StringReplacement { 28 | private static Map mFrameworkList; 29 | private Map mMap; 30 | private File mDataDir; 31 | 32 | public StringReplacement(Map map, File dataDir) { 33 | this.mMap = map; 34 | this.mDataDir = dataDir; 35 | } 36 | 37 | public void execute(String[] filesToModify) throws IOException { 38 | Logger.debug("Replacing strings in XML data."); 39 | for (String name : filesToModify) { 40 | File f = new File(mDataDir, name); 41 | replaceStringsIn(f); 42 | } 43 | Logger.debug("Done with string replacement."); 44 | } 45 | 46 | public void replaceStringsIn(File file) throws IOException { 47 | String name = file.getPath(); 48 | BufferedReader reader = new BufferedReader(new FileReader(file)); 49 | BufferedWriter writer = new BufferedWriter(new FileWriter(name + ".tmp")); 50 | Logger.debug("Writing to temporary file: %s", name + ".tmp"); 51 | String line; 52 | while ((line = reader.readLine()) != null) { 53 | Logger.verbose("Data line before replacement: %s", line); 54 | Iterator keys = mMap.keySet().iterator(); 55 | while (keys.hasNext()) { 56 | String key = keys.next(); 57 | String value = mMap.get(key); 58 | line = line.replaceAll(key, value); 59 | } 60 | Logger.verbose("Data line after replacement: %s", line); 61 | writer.write(line); 62 | writer.newLine(); 63 | } 64 | reader.close(); 65 | writer.close(); 66 | file.delete(); 67 | FileUtils.moveFile(new File(name + ".tmp"), file); 68 | Logger.debug("Successfully cleaned up and done with string replacement."); 69 | } 70 | 71 | public static String filter(String value) { 72 | return value.replaceAll("\\'", "\\\\\\\\'").replaceAll("\\\"", "\\\\\\\\\""); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/com/yifanlu/PSXperiaTool/ZpakCreate.java: -------------------------------------------------------------------------------- 1 | /* 2 | * PSXperia Converter Tool - Zpak creation 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 . 17 | */ 18 | 19 | package com.yifanlu.PSXperiaTool; 20 | 21 | import org.apache.commons.io.FileUtils; 22 | import org.apache.commons.io.filefilter.IOFileFilter; 23 | import org.apache.commons.io.filefilter.TrueFileFilter; 24 | 25 | import java.io.File; 26 | import java.io.FileInputStream; 27 | import java.io.IOException; 28 | import java.io.OutputStream; 29 | import java.util.Iterator; 30 | import java.util.zip.CRC32; 31 | import java.util.zip.CheckedInputStream; 32 | import java.util.zip.ZipEntry; 33 | import java.util.zip.ZipOutputStream; 34 | 35 | public class ZpakCreate { 36 | 37 | public static final int BLOCK_SIZE = 1024; 38 | private OutputStream mOut; 39 | private File mDirectory; 40 | private byte[] mBuffer; 41 | 42 | public ZpakCreate(OutputStream out, File directory) { 43 | this.mOut = out; 44 | this.mDirectory = directory; 45 | this.mBuffer = new byte[BLOCK_SIZE]; 46 | } 47 | 48 | public void create(boolean noCompress) throws IOException { 49 | Logger.info("Generating zpak file from directory %s with compression = %b", mDirectory.getPath(), !noCompress); 50 | IOFileFilter filter = new IOFileFilter() { 51 | public boolean accept(File file) { 52 | if (file.getName().startsWith(".")) { 53 | Logger.debug("Skipping file %s", file.getPath()); 54 | return false; 55 | } 56 | return true; 57 | } 58 | 59 | public boolean accept(File file, String s) { 60 | if (s.startsWith(".")) { 61 | Logger.debug("Skipping file %s", file.getPath()); 62 | return false; 63 | } 64 | return true; 65 | } 66 | }; 67 | Iterator it = FileUtils.iterateFiles(mDirectory, filter, TrueFileFilter.INSTANCE); 68 | ZipOutputStream out = new ZipOutputStream(mOut); 69 | out.setMethod(noCompress ? ZipEntry.STORED : ZipEntry.DEFLATED); 70 | while (it.hasNext()) { 71 | File current = it.next(); 72 | FileInputStream in = new FileInputStream(current); 73 | ZipEntry zEntry = new ZipEntry(current.getPath().replace(mDirectory.getPath(), "").substring(1).replace("\\","/")); 74 | if (noCompress) { 75 | zEntry.setSize(in.getChannel().size()); 76 | zEntry.setCompressedSize(in.getChannel().size()); 77 | zEntry.setCrc(getCRC32(current)); 78 | } 79 | out.putNextEntry(zEntry); 80 | Logger.verbose("Adding file %s", current.getPath()); 81 | int n; 82 | while ((n = in.read(mBuffer)) != -1) { 83 | out.write(mBuffer, 0, n); 84 | } 85 | in.close(); 86 | out.closeEntry(); 87 | } 88 | out.close(); 89 | Logger.debug("Done with ZPAK creation."); 90 | } 91 | 92 | public static long getCRC32(File file) throws IOException { 93 | CheckedInputStream cis = null; 94 | long fileSize = 0; 95 | // Computer CRC32 checksum 96 | cis = new CheckedInputStream(new FileInputStream(file), new CRC32()); 97 | 98 | fileSize = file.length(); 99 | 100 | byte[] buf = new byte[128]; 101 | while (cis.read(buf) != -1) ; 102 | 103 | long checksum = cis.getChecksum().getValue(); 104 | cis.close(); 105 | Logger.verbose("CRC32 of %s is %d", file.getPath(), checksum); 106 | return checksum; 107 | } 108 | } 109 | --------------------------------------------------------------------------------