├── .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 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
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 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
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