From bae16c41fd728ac411bee9baef69433d508ecc63 Mon Sep 17 00:00:00 2001 From: Jari Vetoniemi Date: Thu, 17 Feb 2022 04:38:05 +0900 Subject: rtp support wip --- src/pw/cloudef/rpg/Launcher.java | 1 + src/pw/cloudef/rpg/Rtp.java | 133 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 134 insertions(+) create mode 100644 src/pw/cloudef/rpg/Rtp.java (limited to 'src/pw/cloudef/rpg') diff --git a/src/pw/cloudef/rpg/Launcher.java b/src/pw/cloudef/rpg/Launcher.java index ab2e9b2..1a5659d 100644 --- a/src/pw/cloudef/rpg/Launcher.java +++ b/src/pw/cloudef/rpg/Launcher.java @@ -52,6 +52,7 @@ public class Launcher extends Activity { GameType type = GameType.UNKNOWN; while (zipEntries.hasMoreElements()) { String fname = ((ZipEntry)zipEntries.nextElement()).getName(); + Log.d("pw.cloudef.rpg", fname); try { String base = fname.split(".+?/(?=[^/]+$)")[1]; String name = base.split("\\.(?=[^\\.]+$)")[0]; diff --git a/src/pw/cloudef/rpg/Rtp.java b/src/pw/cloudef/rpg/Rtp.java new file mode 100644 index 0000000..e647cdb --- /dev/null +++ b/src/pw/cloudef/rpg/Rtp.java @@ -0,0 +1,133 @@ +package pw.cloudef.rpg; +import android.app.Activity; +import android.content.Intent; +import android.os.Bundle; +import android.net.Uri; +import android.system.Os; +import android.util.Log; +import java.io.File; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.FileOutputStream; +import java.nio.charset.Charset; +import java.util.zip.ZipFile; +import java.util.zip.ZipEntry; +import java.util.Enumeration; + +public class Rtp extends Activity { + protected String rtpDir() { + return getApplicationContext().getFilesDir().toPath().toString() + "/rtp"; + } + + protected String workDir() { + return getApplicationContext().getCacheDir().toPath().toString() + "/temp"; + } + + protected String zipPath() { + return workDir() + "/rtp.zip"; + } + + protected void shell(String cmd) { + try { Runtime.getRuntime().exec(cmd); } catch (Exception e) {} + } + + protected void rm(String path) { + shell("rm -rf '" + path + "'"); + } + + protected void run(String cmd, String args, String input) { + shell("'" + getApplicationContext().getApplicationInfo().nativeLibraryDir + "/" + cmd + "' " + args + " '" + workDir() + "/" + input + "'"); + } + + protected boolean matches(String name, String[] wants) { + for (int i = 0; i < wants.length; ++i) if (name.equals(wants[i])) return true; + return false; + } + + protected void unzip(File file, String[] wants, String dest) { + ZipFile zipFile; + try { + zipFile = new ZipFile(file, java.util.zip.ZipFile.OPEN_READ, Charset.forName("Windows-31J")); + } catch (Exception e) { + Log.d("pw.cloudef.rpg", e.toString()); + return; + } + + try { + Enumeration zipEntries = zipFile.entries(); + while (zipEntries.hasMoreElements()) { + final ZipEntry entry = (ZipEntry)zipEntries.nextElement(); + if (!matches(entry.getName(), wants)) continue; + InputStream input = zipFile.getInputStream(entry); + String base = entry.getName().split(".+?/(?=[^/]+$)")[1]; + File out = new File(dest, base); + if (!out.getCanonicalPath().startsWith(dest)) + throw new Exception("Zip path traversal detected"); + out.mkdirs(); + OutputStream output = new FileOutputStream(out); + byte[] buf = new byte[8 * 1024]; + for (int read = 0; (read = input.read(buf)) != -1;) output.write(buf, 0, read); + output.close(); input.close(); + break; + } + } catch (Exception e) { + Log.d("pw.cloudef.rpg", e.toString()); + } + + try { zipFile.close(); } catch (Exception e) {} + } + + protected String rtpId() { + return getIntent().getExtras().getString("id"); + } + + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + try { + InputStream input = getContentResolver().openInputStream(getIntent().getData()); + File file = new File(zipPath()); + file.mkdirs(); + OutputStream output = new FileOutputStream(file); + byte[] buf = new byte[8 * 1024]; + for (int read = 0; (read = input.read(buf)) != -1;) output.write(buf, 0, read); + output.close(); input.close(); + if (rtpId().equals("2000") || rtpId().equals("2003")) { + String prefix = (rtpId().equals("2003") ? "2003" : ""); + // STEP 1 unzip + unzip(file, new String[]{prefix + "RTPセットアップ/" + rtpId() + "RTP.exe"}, workDir()); + // STEP 2 cabextract + run("libcabextract.so", "-d '" + workDir() + "' -e CP932 ", rtpId() + "RTP.exe"); + // STEP 3 unshield + run("libunshield.so", "-d '" + workDir() + "' -e CP932 x", "data1.cab"); + run("libunshield.so", "-d '" + workDir() + "' -e CP932 x", "data2.cab"); + } else if (rtpId().equals("XP")) { + // STEP 1 unzip + unzip(file, new String[]{"RPGXP_RTP103/Setup.exe"}, workDir()); + // STEP 2 innoextract + run("libinnoextract.so", "-d '" + workDir() + "' -I app ", "Setup.exe"); + // STEP 3 move to RTP dir + shell("mv '" + workDir() + "/app' '" + rtpDir() + "/XP'"); + } else if (rtpId().equals("VX")) { + // STEP 1 unzip + unzip(file, new String[]{"RPGVX_RTP202/setup.exe"}, workDir()); + // STEP 2 innoextract + run("libinnoextract.so", "-d '" + workDir() + "' -I app ", "setup.exe"); + // STEP 3 move to RTP dir + shell("mv '" + workDir() + "/app' '" + rtpDir() + "/VX'"); + } else if (rtpId().equals("VXAce")) { + // STEP 1 unzip + unzip(file, new String[]{"RPGVXAce_RTP100/Setup.exe", "RPGVXAce_RTP100/Setup-1.bin"}, workDir()); + // STEP 2 innoextract + run("libinnoextract.so", "-d '" + workDir() + "' -I app ", "Setup.exe"); + // STEP 3 move to RTP dir + shell("mv '" + workDir() + "/app' '" + rtpDir() + "/VXAce'"); + } else { + throw new Exception("Unknown RTP"); + } + } catch (Exception e) { + Log.d("pw.cloudef.rpg", e.toString()); + } + // rm(workDir()); + finishAndRemoveTask(); + } +} -- cgit v1.2.3