Compare commits
40 Commits
17bbae0d66
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| 46be75cbec | |||
| df9f4a8ba7 | |||
| 9155493c0e | |||
| c32d45c63f | |||
| e53933200e | |||
|
|
8840a193a3 | ||
| c9a968d173 | |||
| b1f38400c3 | |||
| 889e99f301 | |||
| 9585f16f11 | |||
| f7c4603db1 | |||
| 9292d8db62 | |||
| b8dbfc9095 | |||
| f07a75276c | |||
| f336be5a0a | |||
| 841f8132bb | |||
| 5654fa0b9f | |||
| f21d05d245 | |||
| b5f2aa6925 | |||
| 12f01000dd | |||
| 168e536068 | |||
| 64230f5eb4 | |||
| 91a574bb04 | |||
| e877f5eaa6 | |||
| b3a949fe43 | |||
| a17f7d1b58 | |||
| efbf8585d2 | |||
| 3849a765e3 | |||
| 2bbf34bf70 | |||
| ca36fadad1 | |||
| a75f1ad06c | |||
| a54c1ea325 | |||
| 780a7d69b3 | |||
| 8dfed698bb | |||
| 040adf3b7e | |||
| 309aaec333 | |||
| 8af95d5287 | |||
| 9950188e0d | |||
| 3d91ebbbd7 | |||
| 52dbc56104 |
2
.gitignore
vendored
@@ -28,6 +28,7 @@ out/
|
||||
### Mac OS ###
|
||||
.DS_Store
|
||||
|
||||
### Binaries ###
|
||||
/firestar.zip
|
||||
/run-linux.sh
|
||||
/run-win32.bat
|
||||
@@ -37,3 +38,4 @@ out/
|
||||
/build/
|
||||
/.gradle/
|
||||
/gradle/
|
||||
!/gradle/wrapper/*
|
||||
10
.idea/artifacts/firestar_jar.xml
generated
@@ -6,10 +6,14 @@
|
||||
<element id="file-copy" path="$PROJECT_DIR$/META-INF/MANIFEST.MF" />
|
||||
</element>
|
||||
<element id="module-output" name="firestar.firestar.main" />
|
||||
<element id="extracted-dir" path="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.json/json/20240303/ebb88e8fb5122b7506d5cf1d69f1ccdb790d22a/json-20240303.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$USER_HOME$/.gradle/caches/modules-2/files-2.1/net.lingala.zip4j/zip4j/2.11.5/4214e396e3891cb19eded3ce5e584cba9032fdc3/zip4j-2.11.5.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.jetbrains.intellij.java/java-gui-forms-rt/203.7148.30/f0dbca371a2592689e541be912de6005939f9c7c/java-gui-forms-rt-203.7148.30.jar" path-in-jar="/" />
|
||||
<element id="dir-copy" path="$PROJECT_DIR$/firestar/src/main/resources" />
|
||||
<element id="extracted-dir" path="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.jetbrains.intellij.java/java-gui-forms-rt/203.7148.30/f0dbca371a2592689e541be912de6005939f9c7c/java-gui-forms-rt-203.7148.30.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$USER_HOME$/.gradle/caches/modules-2/files-2.1/io.github.java-diff-utils/java-diff-utils/4.12/1a712a91324d566eef39817fc5c9980eb10c21db/java-diff-utils-4.12.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$USER_HOME$/.gradle/caches/modules-2/files-2.1/net.lingala.zip4j/zip4j/2.11.5/4214e396e3891cb19eded3ce5e584cba9032fdc3/zip4j-2.11.5.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.apache.commons/commons-lang3/3.14.0/1ed471194b02f2c6cb734a0cd6f6f107c673afae/commons-lang3-3.14.0.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.apache.commons/commons-text/1.12.0/66aa90dc099701c4d3b14bd256c328f592ccf0d6/commons-text-1.12.0.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.json/json/20240303/ebb88e8fb5122b7506d5cf1d69f1ccdb790d22a/json-20240303.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.netbeans.external/org-apache-commons-io/RELEASE113/815893df5f31da2ece4040fe0a12fd44b577afaf/org-apache-commons-io-RELEASE113.jar" path-in-jar="/" />
|
||||
</root>
|
||||
</artifact>
|
||||
</component>
|
||||
10
.idea/libraries/apache_commons_io.xml
generated
Normal file
@@ -0,0 +1,10 @@
|
||||
<component name="libraryTable">
|
||||
<library name="apache.commons.io" type="repository">
|
||||
<properties maven-id="commons-io:commons-io:2.16.1" />
|
||||
<CLASSES>
|
||||
<root url="jar://$MAVEN_REPOSITORY$/commons-io/commons-io/2.16.1/commons-io-2.16.1.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES />
|
||||
</library>
|
||||
</component>
|
||||
11
.idea/libraries/apache_commons_text.xml
generated
Normal file
@@ -0,0 +1,11 @@
|
||||
<component name="libraryTable">
|
||||
<library name="apache.commons.text" type="repository">
|
||||
<properties maven-id="org.apache.commons:commons-text:1.12.0" />
|
||||
<CLASSES>
|
||||
<root url="jar://$MAVEN_REPOSITORY$/org/apache/commons/commons-text/1.12.0/commons-text-1.12.0.jar!/" />
|
||||
<root url="jar://$MAVEN_REPOSITORY$/org/apache/commons/commons-lang3/3.14.0/commons-lang3-3.14.0.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES />
|
||||
</library>
|
||||
</component>
|
||||
10
.idea/uiDesigner.xml
generated
@@ -32,17 +32,17 @@
|
||||
<item class="javax.swing.JPanel" icon="/com/intellij/uiDesigner/icons/panel.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3" />
|
||||
</item>
|
||||
<item class="javax.swing.JTextField" icon="/com/intellij/uiDesigner/icons/textField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
|
||||
<preferred-size width="150" height="-1" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JLabel" icon="/com/intellij/uiDesigner/icons/label.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="0" anchor="8" fill="0" />
|
||||
<initial-values>
|
||||
<property name="text" value="Label" />
|
||||
</initial-values>
|
||||
</item>
|
||||
<item class="javax.swing.JTextField" icon="/com/intellij/uiDesigner/icons/textField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
|
||||
<preferred-size width="150" height="-1" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JPasswordField" icon="/com/intellij/uiDesigner/icons/passwordField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
|
||||
<preferred-size width="150" height="-1" />
|
||||
|
||||
14
README.md
@@ -4,17 +4,17 @@
|
||||
|
||||
## Get Started: [>> CLICK HERE <<](https://git.worlio.com/bonkmaykr/firestar/wiki)
|
||||
|
||||

|
||||

|
||||
|
||||
# Installation
|
||||
The latest version of Firestar will always be available from [Releases](https://git.worlio.com/bonkmaykr/firestar/releases).
|
||||
If you aren't sure which file to get:
|
||||
- **Windows:** Download the latest installer [here](https://files.worlio.com/users/bonkmaykr/tools/firestar/latest/firestar_1.2_installer_windows.exe).
|
||||
- **Windows:** Download the latest installer [here](https://screwgravity.net/firestar/builds/stable/tetsuo/firestar_1.3_installer_winnt_x86-64.exe).
|
||||
- **Linux:** Install one of the packages from the [Releases](https://git.worlio.com/bonkmaykr/firestar/releases) page:
|
||||
- Ubuntu, Mint, PopOS: `sudo dpkg -i firestar_ver_arch.deb` or `gdebi firestar_ver_arch.deb`
|
||||
- Fedora, Mageia, OpenSUSE, AlmaLinux: `sudo rpm -i firestar-ver-arch.rpm`
|
||||
- Arch, EndeavourOS, CachyOS, Steam Deck: `sudo pacman -U firestar-ver-arch.pkg.tar.zst`
|
||||
- **All Platforms:** Grab the [Portable ZIP](https://files.worlio.com/users/bonkmaykr/tools/firestar/latest/firestar_dekka-1.2_portable.zip), extract it, and run the JAR file.
|
||||
- **All Platforms:** Grab the [JAR](https://screwgravity.net/firestar/builds/stable/tetsuo/firestar_1.3_portable.jar) and run it.
|
||||
|
||||
# System Requirements
|
||||
- Windows 8 or newer, Mac OS X 10.14 or older, any modern version of Linux/BSD
|
||||
@@ -50,8 +50,7 @@ Firestar uses the Gradle build system. We write our code and perform all our tes
|
||||
git clone https://git.worlio.com/bonkmaykr/firestar.git
|
||||
```
|
||||
|
||||
3. `cd` to `firestar/` and run `./gradlew build` to make a JAR or `./gradlew run` to test your code immediately.
|
||||
- On Windows systems make sure you're running `gradlew.bat` and not the Bash script instead.
|
||||
3. `cd` to `firestar/` and run `gradle build` to make a JAR or `gradle run` to test your code immediately.
|
||||
|
||||
# FAQ
|
||||
## Can I use this on a Vita without enso/HEN?
|
||||
@@ -102,7 +101,4 @@ Because many third-party programs for opening PSARC files either have no ability
|
||||
Cross-platform support with no hassle, a built-in UI framework, and I don't need to sell my soul like every Electron or React 'Native' developer is doing these days.
|
||||
|
||||
## Why the name "Firestar"?
|
||||
Firestar was a secret track in the original WipEout which you unlocked after beating the game at least once, the mod manager is just named after that. Major versions are named after pilots or tracks. Internal class names are named after Muppets characters as this is the same naming convention that Sony used to codename parts inside the PSVita's SOC.
|
||||
|
||||
## Fast Mode vs. Compatibility Mode
|
||||
"Fast Mode" was a legacy option that was scrapped before it could be developed. It skipped the creation of a PSARC file and simply dumped the final game assets to their destination folder. This works great for emulators, and doesn't require proprietary stolen SDKs from SCE. However the filesystem on the Playstation Vita really hated this method and would glitch out when this was done, causing textures to be corrupted once placed on the memory card. The WipEout engine has no fault tolerance for malformed or missing assets, so it just crashes instantly when it encounters one. This is where Compatibility mode comes from, which is the default setting for 2048.
|
||||
Firestar was a secret track in the original WipEout which you unlocked after beating the game at least once, the mod manager is just named after that. Major versions are named after pilots or tracks. Internal class names are named after Muppets characters as this is the same naming convention that Sony used to codename parts inside the PSVita's SOC.
|
||||
@@ -18,6 +18,8 @@ dependencies {
|
||||
implementation group: 'net.lingala.zip4j', name: 'zip4j', version: '2.11.5'
|
||||
implementation group: 'org.json', name: 'json', version: '20240303'
|
||||
implementation group: 'io.github.java-diff-utils', name: 'java-diff-utils', version: '4.12'
|
||||
implementation group: 'org.apache.commons', name: 'commons-text', version: '1.12.0'
|
||||
implementation group: 'org.netbeans.external', name: 'org-apache-commons-io', version: 'RELEASE113'
|
||||
|
||||
implementation 'com.jetbrains.intellij.java:java-gui-forms-rt:203.7148.30'
|
||||
antTask 'com.jetbrains.intellij.java:java-compiler-ant-tasks:203.7148.30'
|
||||
@@ -30,14 +32,15 @@ java {
|
||||
}
|
||||
|
||||
jar {
|
||||
manifest {
|
||||
attributes(
|
||||
'Main-Class': 'Main'
|
||||
)
|
||||
}
|
||||
from {
|
||||
configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) }
|
||||
}
|
||||
manifest {
|
||||
attributes(
|
||||
'Main-Class': 'Main'
|
||||
)
|
||||
}
|
||||
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
|
||||
from {
|
||||
configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) }
|
||||
}
|
||||
}
|
||||
|
||||
application {
|
||||
|
||||
110
firestar/src/main/java/Beaker.form
Normal file
@@ -0,0 +1,110 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="Beaker">
|
||||
<grid id="27dc6" binding="frameContainer" layout-manager="GridLayoutManager" row-count="2" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<margin top="0" left="0" bottom="0" right="0"/>
|
||||
<constraints>
|
||||
<xy x="20" y="20" width="772" height="129"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<background color="-2271221"/>
|
||||
</properties>
|
||||
<border type="none"/>
|
||||
<children>
|
||||
<grid id="20b72" layout-manager="GridLayoutManager" row-count="2" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<margin top="0" left="8" bottom="0" right="8"/>
|
||||
<constraints>
|
||||
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false">
|
||||
<minimum-size width="-1" height="20"/>
|
||||
<preferred-size width="-1" height="80"/>
|
||||
<maximum-size width="-1" height="80"/>
|
||||
</grid>
|
||||
</constraints>
|
||||
<properties>
|
||||
<background color="-15128227"/>
|
||||
<focusable value="false"/>
|
||||
<font size="8"/>
|
||||
<foreground color="-1"/>
|
||||
</properties>
|
||||
<border type="none"/>
|
||||
<children>
|
||||
<grid id="60002" layout-manager="GridLayoutManager" row-count="1" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<margin top="0" left="0" bottom="0" right="0"/>
|
||||
<constraints>
|
||||
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<opaque value="false"/>
|
||||
</properties>
|
||||
<border type="none"/>
|
||||
<children>
|
||||
<component id="9c218" class="javax.swing.JLabel">
|
||||
<constraints>
|
||||
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="10" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<focusable value="false"/>
|
||||
<font size="10"/>
|
||||
<foreground color="-1"/>
|
||||
<text value="© 2025 Canithesis Interactive"/>
|
||||
</properties>
|
||||
</component>
|
||||
<component id="4c79f" class="javax.swing.JLabel">
|
||||
<constraints>
|
||||
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="6" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<font size="10"/>
|
||||
<foreground color="-1"/>
|
||||
<text value="This program is not endorsed by Sony Computer Entertainment."/>
|
||||
</properties>
|
||||
</component>
|
||||
</children>
|
||||
</grid>
|
||||
<grid id="da84a" layout-manager="GridLayoutManager" row-count="1" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<margin top="0" left="0" bottom="0" right="0"/>
|
||||
<constraints>
|
||||
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<opaque value="false"/>
|
||||
</properties>
|
||||
<border type="none"/>
|
||||
<children>
|
||||
<component id="c04e4" class="javax.swing.JLabel">
|
||||
<constraints>
|
||||
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="9" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<focusable value="false"/>
|
||||
<font size="10"/>
|
||||
<foreground color="-1"/>
|
||||
<text value="https://screwgravity.net/firestar/"/>
|
||||
</properties>
|
||||
</component>
|
||||
<component id="b7dd0" class="javax.swing.JLabel">
|
||||
<constraints>
|
||||
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="5" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<font size="10"/>
|
||||
<foreground color="-1"/>
|
||||
<text value="Developed and GNU'd by bonkmaykr. FScript thanx to Wirlaburla"/>
|
||||
</properties>
|
||||
</component>
|
||||
</children>
|
||||
</grid>
|
||||
</children>
|
||||
</grid>
|
||||
<component id="19b7a" class="javax.swing.JLabel" binding="splashImg">
|
||||
<constraints>
|
||||
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false">
|
||||
<preferred-size width="640" height="400"/>
|
||||
</grid>
|
||||
</constraints>
|
||||
<properties>
|
||||
<text value=""/>
|
||||
</properties>
|
||||
</component>
|
||||
</children>
|
||||
</grid>
|
||||
</form>
|
||||
59
firestar/src/main/java/Beaker.java
Normal file
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Firestar Mod Manager
|
||||
* Copyright (C) 2025 Canithesis Interactive
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see https://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.io.IOException;
|
||||
|
||||
import static javax.swing.WindowConstants.DISPOSE_ON_CLOSE;
|
||||
|
||||
public class Beaker {
|
||||
Image logo;
|
||||
private JLabel splashImg;
|
||||
JFrame frame = new JFrame();
|
||||
JPanel frameContainer;
|
||||
|
||||
public Beaker() throws InterruptedException {
|
||||
try {
|
||||
logo = ImageIO.read(Main.class.getResourceAsStream("/splash"+(int)(Math.random()*10)+".png")).getScaledInstance(640, 400, Image.SCALE_SMOOTH);
|
||||
} catch (IOException e) {
|
||||
System.out.println("ERROR: Uhhhhhhhhhhh........... what?");
|
||||
return;
|
||||
}
|
||||
|
||||
frame.add(frameContainer); // initialize window contents -- will be handled by IntelliJ IDEA
|
||||
splashImg.setIcon(new ImageIcon(logo));splashImg.setText("");
|
||||
|
||||
// display window
|
||||
frame.setSize(640, 450);
|
||||
frame.setTitle("Firestar Mod Manager");
|
||||
frame.setUndecorated(true);
|
||||
frame.setResizable(false);
|
||||
frame.setAlwaysOnTop(true);
|
||||
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
|
||||
frame.setLayout(new GridLayout());
|
||||
frame.setLocationRelativeTo(null);
|
||||
frame.setVisible(true);
|
||||
|
||||
Thread.sleep(3000);
|
||||
|
||||
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
|
||||
frame.dispose();
|
||||
}
|
||||
}
|
||||
@@ -63,7 +63,7 @@
|
||||
<properties>
|
||||
<font name="Exo 2"/>
|
||||
<foreground color="-1"/>
|
||||
<text value=" If you add/remove DLC in the future, you will need to change this setting again."/>
|
||||
<text value="Downloading a game update will automatically download its previous versions."/>
|
||||
</properties>
|
||||
</component>
|
||||
</children>
|
||||
@@ -108,7 +108,7 @@
|
||||
</component>
|
||||
</children>
|
||||
</grid>
|
||||
<grid id="1000f" layout-manager="GridLayoutManager" row-count="2" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<grid id="1000f" layout-manager="GridLayoutManager" row-count="3" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<margin top="0" left="0" bottom="0" right="0"/>
|
||||
<constraints>
|
||||
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="7" hsize-policy="7" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
|
||||
@@ -120,55 +120,226 @@
|
||||
</properties>
|
||||
<border type="none"/>
|
||||
<children>
|
||||
<component id="ec9c0" class="javax.swing.JCheckBox" binding="patchCheck">
|
||||
<constraints>
|
||||
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="10" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<background color="-15128227"/>
|
||||
<font name="Exo 2"/>
|
||||
<foreground color="-1"/>
|
||||
<horizontalTextPosition value="11"/>
|
||||
<text value="Updates"/>
|
||||
</properties>
|
||||
</component>
|
||||
<component id="a6e9" class="javax.swing.JCheckBox" binding="baseCheck">
|
||||
<constraints>
|
||||
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="6" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<background color="-15128227"/>
|
||||
<font name="Exo 2"/>
|
||||
<foreground color="-1"/>
|
||||
<horizontalTextPosition value="10"/>
|
||||
<text value="Base game"/>
|
||||
</properties>
|
||||
</component>
|
||||
<component id="f3723" class="javax.swing.JCheckBox" binding="hdCheck">
|
||||
<constraints>
|
||||
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="5" fill="0" indent="0" use-parent-layout="false"/>
|
||||
<grid row="2" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="5" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<background color="-15128227"/>
|
||||
<focusPainted value="false"/>
|
||||
<font name="Exo 2"/>
|
||||
<foreground color="-1"/>
|
||||
<horizontalTextPosition value="10"/>
|
||||
<opaque value="false"/>
|
||||
<text value="HD Add-On Pack"/>
|
||||
<verticalTextPosition value="0"/>
|
||||
</properties>
|
||||
</component>
|
||||
<component id="5ed0c" class="javax.swing.JCheckBox" binding="furyCheck">
|
||||
<constraints>
|
||||
<grid row="1" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="9" fill="0" indent="0" use-parent-layout="false"/>
|
||||
<grid row="2" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="9" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<background color="-15128227"/>
|
||||
<focusPainted value="false"/>
|
||||
<font name="Exo 2"/>
|
||||
<foreground color="-1"/>
|
||||
<horizontalTextPosition value="11"/>
|
||||
<opaque value="false"/>
|
||||
<selected value="false"/>
|
||||
<text value="Fury Add-On Pack"/>
|
||||
<verticalTextPosition value="0"/>
|
||||
</properties>
|
||||
</component>
|
||||
<grid id="afeb1" layout-manager="GridLayoutManager" row-count="3" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<margin top="0" left="0" bottom="0" right="0"/>
|
||||
<constraints>
|
||||
<grid row="0" column="1" row-span="1" col-span="2" vsize-policy="0" hsize-policy="1" anchor="2" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<background color="-15128227"/>
|
||||
<opaque value="false"/>
|
||||
</properties>
|
||||
<border type="none"/>
|
||||
<children>
|
||||
<component id="6337e" class="javax.swing.JRadioButton" binding="baseCheck">
|
||||
<constraints>
|
||||
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="10" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<background color="-15128227"/>
|
||||
<focusPainted value="false"/>
|
||||
<font name="Exo 2"/>
|
||||
<foreground color="-1"/>
|
||||
<horizontalAlignment value="0"/>
|
||||
<horizontalTextPosition value="11"/>
|
||||
<opaque value="false"/>
|
||||
<text value="Base Game"/>
|
||||
</properties>
|
||||
</component>
|
||||
<component id="5c733" class="javax.swing.JRadioButton" binding="patchCheck2">
|
||||
<constraints>
|
||||
<grid row="1" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="2" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<background color="-15128227"/>
|
||||
<focusPainted value="false"/>
|
||||
<font name="Exo 2"/>
|
||||
<foreground color="-1"/>
|
||||
<label value="v1.04 (Latest)"/>
|
||||
<opaque value="false"/>
|
||||
<selected value="true"/>
|
||||
<text value="v1.04 (Latest)"/>
|
||||
</properties>
|
||||
</component>
|
||||
<component id="f9b10" class="javax.swing.JRadioButton" binding="patchCheck1">
|
||||
<constraints>
|
||||
<grid row="1" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="2" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<background color="-15128227"/>
|
||||
<focusPainted value="false"/>
|
||||
<font name="Exo 2"/>
|
||||
<foreground color="-1"/>
|
||||
<opaque value="false"/>
|
||||
<text value="v1.01+"/>
|
||||
</properties>
|
||||
</component>
|
||||
<component id="826d4" class="javax.swing.JLabel">
|
||||
<constraints>
|
||||
<grid row="0" column="0" row-span="1" col-span="3" vsize-policy="0" hsize-policy="0" anchor="0" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<background color="-15128227"/>
|
||||
<font name="Exo 2"/>
|
||||
<foreground color="-1"/>
|
||||
<opaque value="false"/>
|
||||
<text value="Select Game Version:"/>
|
||||
</properties>
|
||||
</component>
|
||||
<component id="26170" class="javax.swing.JCheckBox" binding="skipBaseCheck">
|
||||
<constraints>
|
||||
<grid row="2" column="0" row-span="1" col-span="3" vsize-policy="0" hsize-policy="3" anchor="0" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<background color="-15128227"/>
|
||||
<enabled value="false"/>
|
||||
<focusPainted value="false"/>
|
||||
<font name="Exo 2"/>
|
||||
<foreground color="-1"/>
|
||||
<label value="Don't redownload existing core game files"/>
|
||||
<text value="Don't redownload existing core game files"/>
|
||||
</properties>
|
||||
</component>
|
||||
</children>
|
||||
</grid>
|
||||
<component id="45b94" class="javax.swing.JLabel">
|
||||
<constraints>
|
||||
<grid row="1" column="1" row-span="1" col-span="2" vsize-policy="0" hsize-policy="0" anchor="2" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<background color="-15128227"/>
|
||||
<font name="Exo 2"/>
|
||||
<foreground color="-1"/>
|
||||
<horizontalTextPosition value="11"/>
|
||||
<selected value="false"/>
|
||||
<text value="Fury Add-On Pack"/>
|
||||
<opaque value="false"/>
|
||||
<text value="Select DLC Packs:"/>
|
||||
</properties>
|
||||
</component>
|
||||
<grid id="d53a4" binding="installedList" layout-manager="GridLayoutManager" row-count="1" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<margin top="0" left="0" bottom="0" right="0"/>
|
||||
<constraints>
|
||||
<grid row="0" column="0" row-span="3" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<focusable value="false"/>
|
||||
<opaque value="false"/>
|
||||
</properties>
|
||||
<border type="line" title="Installed Packs" title-justification="2" title-position="1">
|
||||
<font name="Exo 2"/>
|
||||
<title-color color="-1"/>
|
||||
<color color="-1"/>
|
||||
</border>
|
||||
<children>
|
||||
<grid id="e1f58" binding="installedListMargin" layout-manager="GridLayoutManager" row-count="5" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<margin top="4" left="16" bottom="4" right="16"/>
|
||||
<constraints>
|
||||
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<focusable value="false"/>
|
||||
<opaque value="false"/>
|
||||
</properties>
|
||||
<border type="none"/>
|
||||
<children>
|
||||
<component id="74ba9" class="javax.swing.JLabel" binding="ipcBase">
|
||||
<constraints>
|
||||
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<font name="Exo 2"/>
|
||||
<foreground color="-1"/>
|
||||
<horizontalAlignment value="2"/>
|
||||
<horizontalTextPosition value="11"/>
|
||||
<icon value="lightNegative.png"/>
|
||||
<text value="Base Game"/>
|
||||
</properties>
|
||||
</component>
|
||||
<component id="afce0" class="javax.swing.JLabel" binding="ipcPatch1">
|
||||
<constraints>
|
||||
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<font name="Exo 2"/>
|
||||
<foreground color="-1"/>
|
||||
<horizontalAlignment value="2"/>
|
||||
<horizontalTextPosition value="11"/>
|
||||
<icon value="lightNegative.png"/>
|
||||
<text value="Update v1.01"/>
|
||||
</properties>
|
||||
</component>
|
||||
<component id="209d6" class="javax.swing.JLabel" binding="ipcPatch2">
|
||||
<constraints>
|
||||
<grid row="2" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<font name="Exo 2"/>
|
||||
<foreground color="-1"/>
|
||||
<horizontalAlignment value="2"/>
|
||||
<horizontalTextPosition value="11"/>
|
||||
<icon value="lightNegative.png"/>
|
||||
<text value="Update v1.04"/>
|
||||
</properties>
|
||||
</component>
|
||||
<component id="dbb59" class="javax.swing.JLabel" binding="ipcDlcHD">
|
||||
<constraints>
|
||||
<grid row="3" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<font name="Exo 2"/>
|
||||
<foreground color="-1"/>
|
||||
<horizontalAlignment value="2"/>
|
||||
<horizontalTextPosition value="11"/>
|
||||
<icon value="lightNegative.png"/>
|
||||
<text value="HD Add-On Pack"/>
|
||||
</properties>
|
||||
</component>
|
||||
<component id="c1b3f" class="javax.swing.JLabel" binding="ipcDlcFury">
|
||||
<constraints>
|
||||
<grid row="4" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<font name="Exo 2"/>
|
||||
<foreground color="-1"/>
|
||||
<horizontalAlignment value="2"/>
|
||||
<horizontalTextPosition value="11"/>
|
||||
<icon value="lightNegative.png"/>
|
||||
<text value="Fury Add-On Pack"/>
|
||||
</properties>
|
||||
</component>
|
||||
</children>
|
||||
</grid>
|
||||
</children>
|
||||
</grid>
|
||||
</children>
|
||||
</grid>
|
||||
</children>
|
||||
|
||||
@@ -30,10 +30,19 @@ public class Bert implements ActionListener {
|
||||
private JPanel frameContainer;
|
||||
private JButton cancelbtn;
|
||||
private JButton downloadbtn;
|
||||
private JCheckBox patchCheck;
|
||||
private JCheckBox baseCheck;
|
||||
private JRadioButton baseCheck;
|
||||
private JRadioButton patchCheck1;
|
||||
private JRadioButton patchCheck2;
|
||||
private JCheckBox hdCheck;
|
||||
private JCheckBox furyCheck;
|
||||
private JCheckBox skipBaseCheck;
|
||||
private JPanel installedList;
|
||||
private JLabel ipcBase;
|
||||
private JLabel ipcPatch1;
|
||||
private JLabel ipcPatch2;
|
||||
private JLabel ipcDlcHD;
|
||||
private JLabel ipcDlcFury;
|
||||
private JPanel installedListMargin;
|
||||
private ButtonGroup radios = new ButtonGroup();
|
||||
|
||||
private JFrame invoker;
|
||||
@@ -54,8 +63,17 @@ public class Bert implements ActionListener {
|
||||
frame.setLocationRelativeTo(parent);
|
||||
frame.setAlwaysOnTop(true);
|
||||
|
||||
radios.add(baseCheck);
|
||||
radios.add(patchCheck1);
|
||||
radios.add(patchCheck2);
|
||||
|
||||
cancelbtn.addActionListener(this);
|
||||
downloadbtn.addActionListener(this);
|
||||
baseCheck.addActionListener(this);
|
||||
patchCheck1.addActionListener(this);
|
||||
patchCheck2.addActionListener(this);
|
||||
|
||||
refreshChecklist();
|
||||
|
||||
frame.setIconImage(Main.windowIcon);
|
||||
|
||||
@@ -74,6 +92,9 @@ public class Bert implements ActionListener {
|
||||
invoker.setEnabled(true);
|
||||
frame.dispose();
|
||||
}
|
||||
|
||||
if (new File(Main.inpath + "data2.psarc").exists())
|
||||
skipBaseCheck.setEnabled(true);
|
||||
}
|
||||
|
||||
public boolean reportWhenDownloaded(WilkinsCoffee setup) {
|
||||
@@ -87,34 +108,80 @@ public class Bert implements ActionListener {
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent actionEvent) {
|
||||
if (actionEvent.getSource() == baseCheck)
|
||||
skipBaseCheck.setEnabled(new File(Main.inpath + "data.psarc").exists()); else
|
||||
if (actionEvent.getSource() == patchCheck1)
|
||||
skipBaseCheck.setEnabled(new File(Main.inpath + "data1.psarc").exists()); else
|
||||
if (actionEvent.getSource() == patchCheck2)
|
||||
skipBaseCheck.setEnabled(new File(Main.inpath + "data2.psarc").exists()); else
|
||||
if (actionEvent.getSource() == cancelbtn) {
|
||||
invoker.setEnabled(true);
|
||||
frame.dispose();
|
||||
} else if (actionEvent.getSource() == downloadbtn) {
|
||||
ArrayList<Main.ArcTarget> arcs = new ArrayList<Main.ArcTarget>();
|
||||
ArrayList<Main.ArcKey> keys = new ArrayList<Main.ArcKey>();
|
||||
if (baseCheck.isSelected()) {
|
||||
arcs.add(Main.ArcTarget.BASE);
|
||||
keys.add(Main.ArcKey.BASE);
|
||||
System.out.println("Begin download of data (Game version 1.0)");
|
||||
|
||||
// Always download predecessors to ensure no missing files
|
||||
// Probably not necessary since I will be adding selective extraction to Gonzo,
|
||||
// and throw errors when a lower PSARC doesn't exist, but there's no real reason not to.
|
||||
//
|
||||
// Of course, to avoid additional download times, we should probably
|
||||
// avoid adding to the download list if a file already exists, unless explicitly
|
||||
// selected (the exact radio button). The user can redownload one at a time
|
||||
// but Firestar will not overwrite existing PSARCs otherwise.
|
||||
if (baseCheck.isSelected()) { // I have the base game
|
||||
if (!skipBaseCheck.isSelected() || !new File(Main.inpath + "data.psarc").exists()) {
|
||||
arcs.add(Main.ArcTarget.BASE);
|
||||
keys.add(Main.ArcKey.BASE);
|
||||
System.out.println("Queued download of data (Game version 1.0)");
|
||||
}
|
||||
}
|
||||
if (patchCheck.isSelected()) {
|
||||
arcs.add(Main.ArcTarget.LATEST);
|
||||
keys.add(Main.ArcKey.LATEST);
|
||||
System.out.println("Begin download of data2 (Game version 1.04)");
|
||||
if (patchCheck1.isSelected()) { // I updated it once after it came out and then didn't turn my vita on for thousands of years
|
||||
if (!new File(Main.inpath + "data.psarc").exists()) {
|
||||
arcs.add(Main.ArcTarget.BASE);
|
||||
keys.add(Main.ArcKey.BASE);
|
||||
System.out.println("Queued download of data (Game version 1.0)");
|
||||
}
|
||||
if (!skipBaseCheck.isSelected() || !new File(Main.inpath + "data1.psarc").exists()) {
|
||||
arcs.add(Main.ArcTarget.FIRST);
|
||||
keys.add(Main.ArcKey.FIRST);
|
||||
System.out.println("Queued download of data1 (Game version 1.01)");
|
||||
}
|
||||
}
|
||||
if (patchCheck2.isSelected()) { // I'm a normal fucking person
|
||||
if (!new File(Main.inpath + "data.psarc").exists()) {
|
||||
arcs.add(Main.ArcTarget.BASE);
|
||||
keys.add(Main.ArcKey.BASE);
|
||||
System.out.println("Queued download of data (Game version 1.0)");
|
||||
}
|
||||
if (!new File(Main.inpath + "data1.psarc").exists()) {
|
||||
arcs.add(Main.ArcTarget.FIRST);
|
||||
keys.add(Main.ArcKey.FIRST);
|
||||
System.out.println("Queued download of data1 (Game version 1.01)");
|
||||
}
|
||||
if (!skipBaseCheck.isSelected() || !new File(Main.inpath + "data2.psarc").exists()) {
|
||||
arcs.add(Main.ArcTarget.LATEST);
|
||||
keys.add(Main.ArcKey.LATEST);
|
||||
System.out.println("Queued download of data2 (Game version 1.04)");
|
||||
}
|
||||
}
|
||||
|
||||
// DLC are installed arbitrarily, separate of the game, and can remain as checkboxes with the old logic.
|
||||
// Likewise, the old overwrite policy applies. If the user selects these, it WILL download with no question.
|
||||
if (hdCheck.isSelected()) {
|
||||
arcs.add(Main.ArcTarget.ADDON_HD);
|
||||
keys.add(Main.ArcKey.ADDON_HD);
|
||||
System.out.println("Begin download of dlc1 (HD DLC)");
|
||||
System.out.println("Queued download of dlc1 (HD DLC)");
|
||||
}
|
||||
if (furyCheck.isSelected()) {
|
||||
arcs.add(Main.ArcTarget.ADDON_HD_FURY);
|
||||
keys.add(Main.ArcKey.ADDON_HD_FURY);
|
||||
System.out.println("Begin download of dlc2 (Fury DLC)");
|
||||
System.out.println("Queued download of dlc2 (Fury DLC)");
|
||||
}
|
||||
if (arcs.isEmpty()) {
|
||||
frame.setVisible(false);
|
||||
JOptionPane.showMessageDialog(invoker, "Select one or more asset packs.", "Error", JOptionPane.ERROR_MESSAGE);
|
||||
frame.setVisible(true);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -132,9 +199,13 @@ public class Bert implements ActionListener {
|
||||
key = Main.ArcKey.BASE.toString();
|
||||
arcname = "Base game";
|
||||
break;
|
||||
case FIRST :
|
||||
key = Main.ArcKey.FIRST.toString();
|
||||
arcname = "Update 1.01";
|
||||
break;
|
||||
case LATEST :
|
||||
key = Main.ArcKey.LATEST.toString();
|
||||
arcname = "Updates";
|
||||
arcname = "Update 1.04";
|
||||
break;
|
||||
case ADDON_HD :
|
||||
key = Main.ArcKey.ADDON_HD.toString();
|
||||
@@ -172,7 +243,7 @@ public class Bert implements ActionListener {
|
||||
Fozzie popup = new Fozzie();
|
||||
popup.displayTextOnly("Extracting " + arcname + "...", "Extracting");
|
||||
try {
|
||||
Process p = Main.exec(new String[]{"pkg2zip.exe", "-x", "asset.pkg", key.toString()}, Main.inpath);
|
||||
Process p = Main.exec(new String[]{Main.inpath + "pkg2zip.exe", "-x", "asset.pkg", key.toString()}, Main.inpath);
|
||||
InputStream debugin = new BufferedInputStream(p.getInputStream());
|
||||
OutputStream debugout = new BufferedOutputStream(System.out);
|
||||
int c;
|
||||
@@ -200,6 +271,9 @@ public class Bert implements ActionListener {
|
||||
if (type == Main.ArcTarget.BASE) {
|
||||
extracted = "app/PCSA00015";
|
||||
name = "data.psarc";
|
||||
} else if (type == Main.ArcTarget.FIRST) {
|
||||
extracted = "patch/PCSA00015";
|
||||
name = "data1.psarc";
|
||||
} else if (type == Main.ArcTarget.LATEST) {
|
||||
extracted = "patch/PCSA00015";
|
||||
name = "data2.psarc";
|
||||
@@ -226,7 +300,7 @@ public class Bert implements ActionListener {
|
||||
popup.setText("<html>Decrypting protected PFS:<br/>" + extracted + "</html>", "Decrypting");
|
||||
|
||||
try {
|
||||
Process p = Main.exec(new String[]{"psvpfsparser.exe", "-i", extracted, "-o", "./temp/", "-z", key.toString(), "-f", "cma.henkaku.xyz"}, Main.inpath);
|
||||
Process p = Main.exec(new String[]{Main.inpath + "psvpfsparser.exe", "-i", extracted, "-o", "./temp/", "-z", key.toString(), "-f", "cma.henkaku.xyz"}, Main.inpath);
|
||||
InputStream debugin = new BufferedInputStream(p.getInputStream());
|
||||
OutputStream debugout = new BufferedOutputStream(System.out);
|
||||
int c;
|
||||
@@ -276,4 +350,20 @@ public class Bert implements ActionListener {
|
||||
downloaderPopupThread.start();
|
||||
}
|
||||
}
|
||||
|
||||
private void refreshChecklist() {
|
||||
ImageIcon positive = new ImageIcon(Main.class.getResource("/lightPositive.png"));
|
||||
ImageIcon negative = new ImageIcon(Main.class.getResource("/lightNegative.png"));
|
||||
|
||||
if(new File(Main.inpath + "data.psarc").exists())
|
||||
ipcBase.setIcon(positive); else ipcBase.setIcon(negative);
|
||||
if(new File(Main.inpath + "data1.psarc").exists())
|
||||
ipcPatch1.setIcon(positive); else ipcPatch1.setIcon(negative);
|
||||
if(new File(Main.inpath + "data2.psarc").exists())
|
||||
ipcPatch2.setIcon(positive); else ipcPatch2.setIcon(negative);
|
||||
if(new File(Main.inpath + "dlc1.psarc").exists())
|
||||
ipcDlcHD.setIcon(positive); else ipcDlcHD.setIcon(negative);
|
||||
if(new File(Main.inpath + "dlc2.psarc").exists())
|
||||
ipcDlcFury.setIcon(positive); else ipcDlcFury.setIcon(negative);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -163,12 +163,15 @@ public class Clifford implements ActionListener {
|
||||
JOptionPane.showMessageDialog(frame, "Mod name cannot be empty.", "Error", JOptionPane.ERROR_MESSAGE);
|
||||
return;
|
||||
}
|
||||
|
||||
container.put("version", mod.version);
|
||||
container.put("friendlyName", mod.friendlyName);
|
||||
container.put("author", mod.author);
|
||||
container.put("description", mod.description);
|
||||
container.put("loaderversion", mod.loaderversion);
|
||||
container.put("game", mod.game);
|
||||
if (!mod.requires.isEmpty()) container.put("requires", mod.requires);
|
||||
if (!mod.extracts.isEmpty()) container.put("extracts", mod.extracts);
|
||||
|
||||
try {
|
||||
new ZipFile(System.getProperty("user.home") + "/.firestar/mods/" + mod.path.trim()).setComment(container.toString());
|
||||
@@ -196,7 +199,9 @@ public class Clifford implements ActionListener {
|
||||
JFileChooser fileChooser = new JFileChooser();
|
||||
fileChooser.setFileFilter(new FileNameExtensionFilter("Firestar Mod Package", "fstar"));
|
||||
if (fileChooser.showSaveDialog(frame) == JFileChooser.APPROVE_OPTION) {
|
||||
ZipFile zip = new ZipFile(fileChooser.getSelectedFile());
|
||||
File modFile = fileChooser.getSelectedFile();
|
||||
if (!modFile.getName().endsWith(".fstar")) modFile = new File(modFile.toString() + ".fstar");
|
||||
ZipFile zip = new ZipFile(modFile);
|
||||
boolean hasScript = false;
|
||||
try {
|
||||
zip.addFolder(new File(directory.getAbsolutePath() + "/data"));
|
||||
@@ -211,21 +216,39 @@ public class Clifford implements ActionListener {
|
||||
hasScript = true;
|
||||
}
|
||||
|
||||
ArrayList<String> requires = new ArrayList<>();
|
||||
ArrayList<String> extracts = new ArrayList<>();
|
||||
if (isSoundtrack) {
|
||||
requires.add("data2.psarc");
|
||||
extracts.add("data/plugins/music/Definition.xml");
|
||||
extracts.add("data/plugins/languages/american/entries.xml");
|
||||
extracts.add("data/plugins/languages/danish/entries.xml");
|
||||
extracts.add("data/plugins/languages/dutch/entries.xml");
|
||||
extracts.add("data/plugins/languages/english/entries.xml");
|
||||
extracts.add("data/plugins/languages/finnish/entries.xml");
|
||||
extracts.add("data/plugins/languages/french/entries.xml");
|
||||
extracts.add("data/plugins/languages/german/entries.xml");
|
||||
extracts.add("data/plugins/languages/italian/entries.xml");
|
||||
extracts.add("data/plugins/languages/japanese/entries.xml");
|
||||
extracts.add("data/plugins/languages/norwegian/entries.xml");
|
||||
extracts.add("data/plugins/languages/polish/entries.xml");
|
||||
extracts.add("data/plugins/languages/portuguese/entries.xml");
|
||||
extracts.add("data/plugins/languages/russian/entries.xml");
|
||||
extracts.add("data/plugins/languages/spanish/entries.xml");
|
||||
extracts.add("data/plugins/languages/swedish/entries.xml");
|
||||
}
|
||||
|
||||
JSONObject container = new JSONObject();
|
||||
container.put("version", Integer.parseInt(fVersion.getText()));
|
||||
container.put("friendlyName", fName.getText());
|
||||
container.put("author", fAuthor.getText());
|
||||
container.put("description", fDescription.getText());
|
||||
if (!requires.isEmpty()) container.put("requires", requires);
|
||||
if (!extracts.isEmpty()) container.put("extracts", extracts);
|
||||
// todo later versions: handle logic for setting this depending on the fscript version too.
|
||||
// firestar 1.3 can't generate any version other than v1 so this is not necessary right now, but will become necessary when fscript features are added.
|
||||
if (hasScript) {
|
||||
container.put("loaderversion", 1);
|
||||
if (isSoundtrack) {
|
||||
ArrayList<boolean[]> requiresTemp = new ArrayList<>();
|
||||
requiresTemp.add(new boolean[]{false, true, false, false});
|
||||
requiresTemp.add(new boolean[]{true, false, false, false});
|
||||
container.put("requires", requiresTemp); // Pull localization files for patching.
|
||||
}
|
||||
} else {
|
||||
container.put("loaderversion", 0);
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@ public class Ernie implements ActionListener {
|
||||
|
||||
private JFrame parent;
|
||||
|
||||
public Ernie(JFrame parent) {
|
||||
public Ernie(JFrame parent, boolean isManual) {
|
||||
this.parent = parent;
|
||||
frame.setIconImage(Main.windowIcon);
|
||||
byte[] urlraw = getFile(gitapi+"/releases?draft=false&pre-release=false");
|
||||
@@ -72,7 +72,9 @@ public class Ernie implements ActionListener {
|
||||
try {
|
||||
JSONArray releases = new JSONArray(new String(urlraw, Charset.forName("utf-8")));
|
||||
System.out.println("Updater: latest release is " + ((JSONObject)releases.get(0)).get("tag_name"));
|
||||
if (releases.length() >= 1 && !((JSONObject)releases.get(0)).get("tag_name").equals(Main.vtag)) {
|
||||
if (releases.length() >= 1
|
||||
&& (!Main.isNightly && (!((JSONObject)releases.get(0)).get("tag_name").equals(Main.vtag))
|
||||
|| (Main.isNightly && !((JSONObject)releases.get(0)).get("tag_name").equals(Main.vtagPrevious)))) {
|
||||
System.out.println("Updater: Your version is out of date.");
|
||||
frame.add(frameContainer);
|
||||
notnowbtn.addActionListener(this);
|
||||
@@ -97,7 +99,10 @@ public class Ernie implements ActionListener {
|
||||
}
|
||||
});
|
||||
frame.setVisible(true);
|
||||
} else { System.out.println("Updater: No updates."); }
|
||||
} else {
|
||||
System.out.println("Updater: No updates.");
|
||||
if (isManual) {JOptionPane.showMessageDialog(frame, "There are no updates at this time.", "Check for Updates", JOptionPane.INFORMATION_MESSAGE);}
|
||||
}
|
||||
} catch (IOException | JSONException ex) {
|
||||
Logger.getLogger(Ernie.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ public class Fozzie {
|
||||
frame.setIconImage(Main.windowIcon);
|
||||
frame.setVisible(true);
|
||||
|
||||
label.setText("Downloading \"" + dname + "\"");
|
||||
label.setText("Downloading " + dname);
|
||||
|
||||
try {
|
||||
URL fileURL = new URL(url);
|
||||
|
||||
@@ -25,12 +25,10 @@ import java.awt.*;
|
||||
import java.awt.event.WindowAdapter;
|
||||
import java.awt.event.WindowEvent;
|
||||
import java.io.*;
|
||||
import java.nio.file.DirectoryStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.nio.file.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@@ -108,24 +106,47 @@ public class Gonzo {
|
||||
}
|
||||
|
||||
private void CompatibilityRoutine() {
|
||||
// cleanup any failed deploys to avoid scripts running when they are not supposed to be
|
||||
Main.deleteDir(new File(System.getProperty("user.home") + "/.firestar/temp/"));
|
||||
|
||||
// create temporary working area for asset dump
|
||||
new File(System.getProperty("user.home") + "/.firestar/temp/").mkdirs();
|
||||
new File(System.getProperty("user.home") + "/.firestar/temparcs/").mkdirs();
|
||||
|
||||
// Work from bottom to top, mods on top always overwrite the ones on the bottom.
|
||||
List<Main.Mod> modsFlipped = new ArrayList<>(Main.Mods);
|
||||
Collections.reverse(modsFlipped);
|
||||
|
||||
// decide which files to dump
|
||||
List<String> dumpThese = new ArrayList<String>();
|
||||
if (data0) {dumpThese.add("data.psarc");oArcTarget = "data.psarc";}
|
||||
if (data1) {dumpThese.add("data1.psarc");oArcTarget = "data1.psarc";}
|
||||
if (data2) {dumpThese.add("data2.psarc");oArcTarget = "data2.psarc";}
|
||||
if (dlc1) {dumpThese.add("dlc1.psarc");oArcTarget = "dlc1.psarc";}
|
||||
if (dlc2) {dumpThese.add("dlc2.psarc");oArcTarget = "dlc2.psarc";}
|
||||
for (Main.Mod m : modsFlipped) {
|
||||
if (m.enabled) {
|
||||
System.out.println(m.friendlyName + " : " + m.requires.toString() + " : " + m.extracts.toString());
|
||||
for (String r : m.requires) if (!dumpThese.contains(r)) dumpThese.add(r);
|
||||
}
|
||||
}
|
||||
if (data0) oArcTarget = "data.psarc";
|
||||
if (data1) oArcTarget = "data1.psarc";
|
||||
if (data2) oArcTarget = "data2.psarc";
|
||||
if (dlc1) oArcTarget = "dlc1.psarc";
|
||||
if (dlc2) oArcTarget = "dlc2.psarc";
|
||||
dumpThese.remove(oArcTarget); dumpThese.add(oArcTarget); // Always dump the base game last. TODO should we allow mods to specify otherwise??
|
||||
System.out.println("List of files to dump: " + dumpThese);
|
||||
|
||||
// dump all assets to working area
|
||||
for (String s : dumpThese) {
|
||||
try {
|
||||
if (!(new File(Main.inpath + s).exists()))
|
||||
throw new IOException("A mod requested access to the archive \"" + s + "\" but it doesn't exist!");
|
||||
|
||||
System.out.println("Firestar is extracting " + s);
|
||||
consoleDisplay.append("Firestar is extracting " + s + "\n");
|
||||
//Process p = Runtime.getRuntime().exec(new String[]{"bash","-c","aplay /home/bonkyboo/kittens_loop.wav"}); // DEBUG
|
||||
Process p = Main.exec(new String[]{"../psp2psarc.exe", "extract", "-y", "../"+s}, System.getProperty("user.home") + "/.firestar/temp/");
|
||||
Process p;
|
||||
if (s.equals(oArcTarget)) p = Main.exec(new String[]{Main.inpath + "psp2psarc.exe", "extract", "-y", "../"+s}, System.getProperty("user.home") + "/.firestar/temp/");
|
||||
else {
|
||||
new File(System.getProperty("user.home") + "/.firestar/temparcs/" + s + "/").mkdirs();
|
||||
p = Main.exec(new String[]{Main.inpath + "psp2psarc.exe", "extract", "-y", "../../"+s}, System.getProperty("user.home") + "/.firestar/temparcs/" + s + "/");
|
||||
}
|
||||
final Thread ioThread = new Thread() {
|
||||
@Override
|
||||
public void run() {
|
||||
@@ -159,13 +180,37 @@ public class Gonzo {
|
||||
|
||||
// overwrite assets with custom ones from each mod and/or perform operations as specified in mod's delete list
|
||||
// todo: implement RegEx functions after delete.txt
|
||||
for (Main.Mod m : Main.Mods) {
|
||||
for (Main.Mod m : modsFlipped) {
|
||||
if (m.enabled) {
|
||||
try {
|
||||
System.out.println("Firestar is extracting " + m.friendlyName + " by " + m.author);
|
||||
consoleDisplay.append("Firestar is extracting " + m.friendlyName + " by " + m.author + "\n");
|
||||
new ZipFile(System.getProperty("user.home") + "/.firestar/mods/" + m.path).extractAll(System.getProperty("user.home") + "/.firestar/temp/");
|
||||
|
||||
if (!m.requires.isEmpty() && !m.extracts.isEmpty()) {
|
||||
for (String r : m.requires) {
|
||||
for (String e : m.extracts) {
|
||||
File f = new File(Main.inpath + "temparcs/" + r + "/" + e);
|
||||
File f2 = new File(Main.inpath + "temp/" + e);
|
||||
if (f2.exists()) {
|
||||
System.out.println("File \"" + e + "\" already exists in master PSARC. Ignoring.");
|
||||
consoleDisplay.append("File \"" + e + "\" already exists in master PSARC. Ignoring." + "\n");
|
||||
}
|
||||
else if (f.exists()) {
|
||||
Path src = Paths.get(Main.inpath + "temparcs/" + r + "/" + e);
|
||||
Path dest = Paths.get(Main.inpath + "temp/" + e);
|
||||
System.out.println("Copying extra file " + e + " from " + r);
|
||||
consoleDisplay.append("Copying extra file " + e + " from " + r + "\n");
|
||||
new File(dest.getParent().toString()).mkdirs();
|
||||
Files.copy(src, dest, StandardCopyOption.COPY_ATTRIBUTES);
|
||||
} else throw new IOException("A mod requested access to the file \"" + e + "\" from archive " + r + " but it wasn't there!");
|
||||
}
|
||||
}
|
||||
} else if (!m.extracts.isEmpty()) {
|
||||
System.out.println("WARNING: " + m.friendlyName + " by " + m.author + "tried to extract individual files without specifying a source PSARC in requires[]. Ignoring.");
|
||||
consoleDisplay.append("WARNING: " + m.friendlyName + " by " + m.author + "tried to extract individual files without specifying a source PSARC in requires[]. Ignoring." + "\n");
|
||||
}
|
||||
|
||||
File fscript = new File(Main.inpath + "temp/fscript");
|
||||
if (fscript.exists()) {
|
||||
System.out.println("Firestar is applying patches from " + m.friendlyName + " by " + m.author);
|
||||
@@ -209,7 +254,9 @@ public class Gonzo {
|
||||
} catch (Exception e) {
|
||||
System.out.println(e.getMessage());
|
||||
consoleDisplay.append("CRITICAL FAILURE: " + e.getMessage());
|
||||
JOptionPane.showMessageDialog(this.frame, "CRITICAL FAILURE: " + e.getMessage(), "Fatal Error", JOptionPane.ERROR_MESSAGE);
|
||||
if (e instanceof FirescriptFormatException) {JOptionPane.showMessageDialog(this.frame, "CRITICAL FAILURE: " + e.getMessage() + "\nOne of your mods has a broken FSCRIPT. It cannot be installed.", "Fatal Error", JOptionPane.ERROR_MESSAGE);} else {
|
||||
JOptionPane.showMessageDialog(this.frame, "CRITICAL FAILURE: " + e.getMessage(), "Fatal Error", JOptionPane.ERROR_MESSAGE);
|
||||
}
|
||||
frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
|
||||
AllowExit();
|
||||
return;
|
||||
@@ -223,7 +270,7 @@ public class Gonzo {
|
||||
} catch (IOException | FirescriptFormatException e) {
|
||||
System.out.println(e.getMessage());
|
||||
consoleDisplay.append("CRITICAL FAILURE: " + e.getMessage());
|
||||
JOptionPane.showMessageDialog(this.frame, "CRITICAL FAILURE: " + e.getMessage(), "Fatal Error", JOptionPane.ERROR_MESSAGE);
|
||||
JOptionPane.showMessageDialog(this.frame, "CRITICAL FAILURE: Internal FSCRIPT Error. " + e.getMessage() + "\nThis may indicate that Firestar has been corrupted and needs reinstalling.", "Fatal Error", JOptionPane.ERROR_MESSAGE);
|
||||
frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
|
||||
AllowExit();
|
||||
return;
|
||||
@@ -267,7 +314,7 @@ public class Gonzo {
|
||||
try {
|
||||
System.out.println("Firestar is compiling the final build");
|
||||
consoleDisplay.append("Firestar is compiling the final build" + "\n");
|
||||
Process p = Main.exec(new String[]{"../psp2psarc.exe", "create", "--skip-missing-files", "-j12", "-a", "-i", "-y", "--input-file=list.txt", "-o" + oArcTarget}, System.getProperty("user.home") + "/.firestar/temp/");
|
||||
Process p = Main.exec(new String[]{Main.inpath + "psp2psarc.exe", "create", "--skip-missing-files", "-j12", "-a", "-i", "-y", "--input-file=list.txt", "-o" + oArcTarget}, System.getProperty("user.home") + "/.firestar/temp/");
|
||||
final Thread ioThread = new Thread() {
|
||||
@Override
|
||||
public void run() {
|
||||
@@ -316,7 +363,9 @@ public class Gonzo {
|
||||
}
|
||||
try {
|
||||
File tmp = new File(System.getProperty("user.home") + "/.firestar/temp/");
|
||||
File tmp2 = new File(System.getProperty("user.home") + "/.firestar/temparcs/");
|
||||
Main.deleteDir(tmp);
|
||||
Main.deleteDir(tmp2);
|
||||
} catch (Exception e) {
|
||||
System.out.println("WARNING: Temporary files may not have been properly cleared.\n" + e.getMessage());
|
||||
consoleDisplay.append("WARNING: Temporary files may not have been properly cleared.\n" + e.getMessage());
|
||||
@@ -349,6 +398,7 @@ public class Gonzo {
|
||||
@Override
|
||||
public void windowClosing(WindowEvent e)
|
||||
{
|
||||
Main.deleteDir(new File(System.getProperty("user.home") + "/.firestar/temp/"));
|
||||
invoker.wrapUpDeployment();
|
||||
e.getWindow().dispose();
|
||||
}
|
||||
|
||||
@@ -18,12 +18,17 @@
|
||||
|
||||
import net.lingala.zip4j.ZipFile;
|
||||
import net.lingala.zip4j.exception.ZipException;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.json.*;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.*;
|
||||
import java.math.BigInteger;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.*;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
import javax.imageio.ImageIO;
|
||||
@@ -31,11 +36,16 @@ import javax.swing.*;
|
||||
|
||||
public class Main {
|
||||
// Build Information
|
||||
public static final String vstr = "Release 1.3";
|
||||
public static String vstr = "Release 1.3.1";
|
||||
public static final String vcode = "Tetsuo";
|
||||
public static final String vtag = "tetsuo-1.3"; // set to dekka-1.1 for testing
|
||||
public static final String vtag = "tetsuo-1.3.1"; // set to dekka-1.1 for testing
|
||||
public static final int vint = 1;
|
||||
|
||||
// Jenkins Build Information
|
||||
public static boolean isNightly = false;
|
||||
public static final String vtagPrevious = "tetsuo-1.3.1";
|
||||
public static String dateOfCompile = null;
|
||||
|
||||
// User Settings
|
||||
public static String outpath = System.getProperty("user.home") + "/.firestar/out/"; //game assets location
|
||||
public final static String inpath = System.getProperty("user.home") + "/.firestar/"; //firestar folder -- do not change this
|
||||
@@ -47,6 +57,7 @@ public class Main {
|
||||
|
||||
public enum ArcTarget { // install target for 2048, type used by downloader
|
||||
BASE("http://zeus.dl.playstation.net/cdn/UP9000/PCSA00015_00/NYEoaBGfiWymSEVZKxoyrKyBFsZNoFqxdyAIpZayZYuLLbCAArYrYXjPNhKCfXcONmhIZzZEeArycSrjiJOuNMWuWsDONUxMIQtMk.pkg"),
|
||||
FIRST("http://gs.ww.np.dl.playstation.net/ppkg/np/PCSA00015/PCSA00015_T5/a4b7d9e35ed56e86/UP9000-PCSA00015_00-WIPEOUT2048BASE0-A0104-V0100-059564fcab8ce66d19b5a563e92677e581313205-PE.pkg"),
|
||||
LATEST("http://gs.ww.np.dl.playstation.net/ppkg/np/PCSA00015/PCSA00015_T5/a4b7d9e35ed56e86/UP9000-PCSA00015_00-WIPEOUT2048BASE0-A0104-V0100-059564fcab8ce66d19b5a563e92677e581313205-PE.pkg"),
|
||||
ADDON_HD("http://zeus.dl.playstation.net/cdn/UP9000/PCSA00015_00/JYMqGNXUKqHEyNLjbOgrWcJdnQJUMzgadRFWekbWFBXAwMeGikOyiHkXKogKIfqGhtNwKgmNWwwcrJORmRUTDzylBPwjGVnVjyDfh.pkg"),
|
||||
ADDON_HD_FURY("http://zeus.dl.playstation.net/cdn/UP9000/PCSA00015_00/IAoJQaDpySenBmQCKiqecEPMzSdPfPcdXupxZXLTYYTuRgtsdTaHxbeejwGKRQpjJOKBdMMFzSoeEhsHYxNUasQrEzkZPeBxUEqnp.pkg");
|
||||
@@ -62,6 +73,7 @@ public class Main {
|
||||
|
||||
public enum ArcKey { // decryption keys for 2048, type used by downloader
|
||||
BASE("KO5ifR1dQ+eHBlgi6TI0Bdkf7hng6h8aYmRgYuHkCLQNn/9ufV+01fmzjNSmwuVHnO4dEBuN8cENACqVFcgA"),
|
||||
FIRST("KO5ifR1dQ+eHBlgi6TI0Bdkf7hng6h8aYmRgYuHkCLQNn/9ufV+01fmzjNSmwuVHnO4dEBuN8cENACqVFcgA"),
|
||||
LATEST("KO5ifR1dQ+eHBlgi6TI0Bdkf7hng6h8aYmRgYuHkCLQNn/9ufV+01fmzjNSmwuVHnO4dEBuN8cENACqVFcgA"),
|
||||
ADDON_HD("KO5ifR1dQ+eHBlgi6TI0Bdnv4uNsGG5kYGIR4Ojs7ejuis9/anXfuudVNvzgdu+9z1z+asJojA9uAACgRhTl"),
|
||||
ADDON_HD_FURY("KO5ifR1dQ+eHBlgi6TI0Bdnv4uNsFG5kYGIR4Ojs7ejuis9/3fydBRm3eCJX7biz/vVTm/2jMT64AQCCYhVy");
|
||||
@@ -85,8 +97,8 @@ public class Main {
|
||||
public int loaderversion = 0; //minimum required vint or feature level from Firestar
|
||||
public String author; // if null, "Author is unknown."
|
||||
public boolean enabled = true;
|
||||
public List<boolean[]> requires = new ArrayList<>(); // TODO: load optional "requires" array from mod meta if it exists. it will be base, patches, hd dlc, and fury dlc in that order.
|
||||
// TODO: save 'false true false false' in ost gen if necessary (patches change localization)
|
||||
public List<String> requires = new ArrayList<>();
|
||||
public List<String> extracts = new ArrayList<>();
|
||||
}
|
||||
|
||||
// Mods
|
||||
@@ -96,12 +108,26 @@ public class Main {
|
||||
public static Font fExo2;
|
||||
public static BufferedImage windowIcon;
|
||||
|
||||
public static void main(String[] args) {
|
||||
public static void main(String[] args) throws InterruptedException {
|
||||
// get Nightly information from Jenkins automatic builds
|
||||
if (Main.class.getResource("/jenkinsVersionString") != null) {
|
||||
System.out.println("=== This is a NIGHTLY BUILD! ===\n");
|
||||
try {
|
||||
vstr = "Nightly " + IOUtils.toString(Main.class.getResourceAsStream("/jenkinsVersionString"), StandardCharsets.UTF_8);
|
||||
dateOfCompile = IOUtils.toString(Main.class.getResourceAsStream("/jenkinsBuildDate"), StandardCharsets.UTF_8);
|
||||
System.out.println("Compiled on " + dateOfCompile);
|
||||
isNightly = true;
|
||||
} catch (Exception e) {
|
||||
System.out.println("ERROR: Something went wrong trying to get the autobuild information! defaulting to Release values\n\n");
|
||||
isNightly = false;
|
||||
}
|
||||
}
|
||||
|
||||
// license string
|
||||
System.out.printf("FIRESTAR MOD MANAGER for WipEout 2048\nversion " + vstr + " (codename " + vcode + ") major " + vint + "\n" +
|
||||
System.out.printf("FIRESTAR MOD MANAGER for WipEout 2048\n" + vstr + " (codename " + vcode + ") major " + vint + "\n" +
|
||||
"JVM host appears to be " + System.getProperty("os.name") +
|
||||
"\nRunning from " + System.getProperty("user.dir") +
|
||||
"\nCopyright (C) 2024 bonkmaykr\n\nThis program is free software: you can redistribute it and/or modify\n" +
|
||||
"\nCopyright (C) 2025 Canithesis Interactive\n\nThis program is free software: you can redistribute it and/or modify\n" +
|
||||
"it under the terms of the GNU General Public License as published by\n" +
|
||||
"the Free Software Foundation, either version 3 of the License, or\n" +
|
||||
"(at your option) any later version.\n" +
|
||||
@@ -114,7 +140,9 @@ public class Main {
|
||||
"You should have received a copy of the GNU General Public License\n" +
|
||||
"along with this program. If not, see https://www.gnu.org/licenses/.\n\n\n\n");
|
||||
|
||||
//begin
|
||||
// display splash screen
|
||||
new Beaker();
|
||||
|
||||
// load global assets
|
||||
try {
|
||||
fExo2 = Font.createFont(Font.TRUETYPE_FONT, Main.class.getResourceAsStream("/exo2.ttf"));
|
||||
@@ -216,10 +244,25 @@ public class Main {
|
||||
Main.writeConf();
|
||||
}
|
||||
|
||||
public static boolean downloadDependencies () { // todo: CHECKSUM!!!! THESE ARE EXECUTABLES!!!!!!!!!!! DON'T ALLOW MALWARE!!!!
|
||||
boolean downloader = new Fozzie().DownloadFile("https://bonkmaykr.worlio.com/http/firestar/firesdk.zip", System.getProperty("user.home") + "/.firestar/", "firesdk.zip");
|
||||
public static boolean downloadDependencies () {
|
||||
boolean downloader = new Fozzie().DownloadFile("https://bonkmaykr.worlio.com/http/firestar/fire13.zip", System.getProperty("user.home") + "/.firestar/", "firesdk.zip", "Firestar dependencies");
|
||||
if (!downloader) {return false;}
|
||||
|
||||
final String expectedMD5Hash = "306807955266724172476879569959042600238"; // Prevent a malicious web server takeover from installing malware on the user's computer.
|
||||
String downloadedMD5Hash = ""; // if this number does not match for ANY reason, cancel immediately and get a programmer.
|
||||
try {downloadedMD5Hash = new BigInteger(1, MessageDigest.getInstance("MD5").digest(Files.readAllBytes(Paths.get(Main.inpath + "firesdk.zip")))).toString();}
|
||||
catch (Exception e) {
|
||||
System.out.println("ERROR: Failed to download PSARC tool due to an internal problem.\n" + e.getMessage());
|
||||
JOptionPane.showMessageDialog(null, "The file failed to download.\nPlease check your network connection and try again.\n\n" + e.getMessage(), "Download Failed", JOptionPane.WARNING_MESSAGE);
|
||||
}
|
||||
if (!downloadedMD5Hash.equals(expectedMD5Hash)) {
|
||||
System.out.println("ERROR: Downloaded PSARC tool is invalid. Check your network connection and ensure the file is not corrupt or infected.");
|
||||
//Object[] options = {"Abort", "Retry"};
|
||||
//int result = JOptionPane.showOptionDialog(new JFrame(), "The downloaded file failed a security check.\nPlease ensure your network connection is stable.\n\nIf this issue persists, send an email to tech support\nat bonkmaykr@screwgravity.net.", "Download Cancelled", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE, null, options, options[0]);
|
||||
JOptionPane.showMessageDialog(null, "The downloaded file failed a security check.\nPlease ensure your network connection is stable.\n\nIf this issue persists, send an email to tech support\nat bonkmaykr@screwgravity.net.", "Download Cancelled", JOptionPane.WARNING_MESSAGE);
|
||||
return false;
|
||||
}
|
||||
|
||||
ZipFile sdk = new ZipFile(System.getProperty("user.home") + "/.firestar/firesdk.zip");
|
||||
try {
|
||||
sdk.extractAll(System.getProperty("user.home") + "/.firestar/");
|
||||
@@ -230,12 +273,9 @@ public class Main {
|
||||
}
|
||||
sdk.getFile().delete(); // cleanup
|
||||
|
||||
JOptionPane.showMessageDialog(null, "All remote dependencies satisfied.", "Download Completed", JOptionPane.INFORMATION_MESSAGE);
|
||||
return true;
|
||||
}
|
||||
|
||||
public static boolean callDownloaderStatically (String url, String folder, String name) {
|
||||
return new Fozzie().DownloadFile(url, folder, name);
|
||||
}
|
||||
|
||||
public static Process exec(String[] cmd, String cwd) throws IOException {
|
||||
Process p;
|
||||
@@ -250,4 +290,16 @@ public class Main {
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
public static void printProcessLogToStdOut(Process p) {
|
||||
try {
|
||||
final BufferedReader reader = new BufferedReader(
|
||||
new InputStreamReader(p.getInputStream()));
|
||||
String line = null;
|
||||
while ((line = reader.readLine()) != null) {System.out.println(line);}
|
||||
reader.close();
|
||||
} catch (final Exception e) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -31,8 +31,11 @@ import java.math.RoundingMode;
|
||||
import java.net.URI;
|
||||
import java.nio.file.*;
|
||||
import java.text.DecimalFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
import net.lingala.zip4j.*;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
@@ -172,7 +175,7 @@ public class MissPiggy implements ActionListener {
|
||||
frame.setLayout(new GridLayout());
|
||||
frame.setLocationRelativeTo(null);
|
||||
|
||||
if (Main.checkUpdates) { StartErnie(); }
|
||||
if (Main.checkUpdates) { StartErnie(false); }
|
||||
|
||||
frame.setVisible(true);
|
||||
}
|
||||
@@ -230,6 +233,16 @@ public class MissPiggy implements ActionListener {
|
||||
if (metadata.has("loaderversion")) {m.loaderversion = Integer.parseInt(metadata.get("loaderversion").toString());}
|
||||
if (metadata.has("game")) {m.game = metadata.get("game").toString();}
|
||||
|
||||
if (m.loaderversion >= 1) {
|
||||
// Firestar 1.3 features
|
||||
if (metadata.has("requires"))
|
||||
for (Object i : (ArrayList<Object>)((Map<String, Object>)metadata.toMap()).get("requires"))
|
||||
m.requires.add(i.toString());
|
||||
if (metadata.has("extracts"))
|
||||
for (Object i : (ArrayList<Object>)((Map<String, Object>)metadata.toMap()).get("extracts"))
|
||||
m.extracts.add(i.toString());
|
||||
}
|
||||
|
||||
//send to list
|
||||
Main.Mods.add(m);
|
||||
} catch (Exception e) {
|
||||
@@ -300,11 +313,11 @@ public class MissPiggy implements ActionListener {
|
||||
createSelectionEventListener();
|
||||
}
|
||||
|
||||
private void StartErnie() {
|
||||
private void StartErnie(boolean isManual) {
|
||||
new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
new Ernie(frame); // changed away from runnable in order to pass params to constructor -bonk
|
||||
new Ernie(frame, isManual); // changed away from runnable in order to pass params to constructor -bonk
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
@@ -332,7 +345,11 @@ public class MissPiggy implements ActionListener {
|
||||
|
||||
if (actionEvent.getSource() == toolsMenu.getItem(0)) {metaEditorGUI(modList.getSelectedIndex());} else
|
||||
if (actionEvent.getSource() == toolsMenu.getItem(1)) {generatorGUI();} else
|
||||
if (actionEvent.getSource() == toolsMenu.getItem(2)) {new Suggs(frame);} else
|
||||
if (actionEvent.getSource() == toolsMenu.getItem(2)) {
|
||||
if (!new File(Main.inpath + "at9tool.exe").exists() || !new File(Main.inpath + "ffmpeg.exe").exists())
|
||||
JOptionPane.showMessageDialog(frame, "Your AT9 encoders are missing.\nPlease select \"Get Dependencies\" in the Options menu.", "Error", JOptionPane.ERROR_MESSAGE);
|
||||
else new Suggs(frame);
|
||||
} else
|
||||
|
||||
if (actionEvent.getSource() == helpMenu.getItem(0)) {
|
||||
try {
|
||||
@@ -358,7 +375,7 @@ public class MissPiggy implements ActionListener {
|
||||
JOptionPane.showMessageDialog(frame, e.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
|
||||
}
|
||||
} else
|
||||
if (actionEvent.getSource() == helpMenu.getItem(5)) {StartErnie();} else
|
||||
if (actionEvent.getSource() == helpMenu.getItem(5)) {StartErnie(true);} else
|
||||
if (actionEvent.getSource() == helpMenu.getItem(6)) {new Rowlf(frame);}
|
||||
}
|
||||
|
||||
@@ -460,7 +477,6 @@ public class MissPiggy implements ActionListener {
|
||||
}
|
||||
|
||||
public void removeAllGUI() {
|
||||
// todo warning dialog that nukes list when Yes is clicked
|
||||
int result = JOptionPane.showConfirmDialog(frame, "Do you really want to delete all mods?", "Remove All", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE);
|
||||
|
||||
if (result == JOptionPane.YES_OPTION) {
|
||||
|
||||
@@ -47,15 +47,13 @@ import javax.xml.transform.TransformerFactory;
|
||||
import javax.xml.transform.dom.DOMSource;
|
||||
import javax.xml.transform.stream.StreamResult;
|
||||
import javax.xml.transform.OutputKeys;
|
||||
import org.w3c.dom.Attr;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.NamedNodeMap;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
|
||||
import org.w3c.dom.*;
|
||||
import org.xml.sax.SAXException;
|
||||
import org.apache.commons.text.StringEscapeUtils;
|
||||
|
||||
public class Rizzo {
|
||||
private final DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
|
||||
private Scanner scanner;
|
||||
private final int maxVer = 1;
|
||||
private int ver = 1;
|
||||
@@ -77,9 +75,9 @@ public class Rizzo {
|
||||
}
|
||||
|
||||
private boolean parseArgs(String[] args, Object context) throws FirescriptFormatException {
|
||||
System.out.println("Parsing Command: " + Arrays.toString(args));
|
||||
if (args.length > 0) {
|
||||
if (context == null) {
|
||||
System.out.println("Parsing Command: " + Arrays.toString(args));
|
||||
if (args[0].equalsIgnoreCase("fscript")) {
|
||||
ver = Integer.parseInt(args[1]); // We'll do shit with this later
|
||||
if (ver > maxVer) throw new FirescriptFormatException(args[0], "script too new");
|
||||
@@ -87,9 +85,9 @@ public class Rizzo {
|
||||
File newCtx = new File(workingDir + args[1]);
|
||||
System.out.println("Calling new parse: " + Arrays.toString(Arrays.copyOfRange(args, 2, args.length)));
|
||||
parseArgs(Arrays.copyOfRange(args, 2, args.length), newCtx);
|
||||
} else throw new FirescriptFormatException("fscript", "unknown command '" + args[0] + "'");
|
||||
} else throw new FirescriptFormatException("fscript", "command '" + args[0] + "' is unknown or used in inappropriate context");
|
||||
} else {
|
||||
System.out.println("Using context: " + context.getClass().getName() + "@" + context.hashCode());
|
||||
System.out.println("Parsing Command: " + Arrays.toString(args) + " using context: " + context.getClass().getName() + "@" + context.hashCode());
|
||||
if (args[0].equals("{")) {
|
||||
System.out.println("New context block: " + context.getClass().getName() + "@" + context.hashCode());
|
||||
parseScript(context);
|
||||
@@ -106,7 +104,6 @@ public class Rizzo {
|
||||
}
|
||||
} else if (args[0].equalsIgnoreCase("xml")) {
|
||||
try {
|
||||
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
|
||||
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
|
||||
// Mmmm, love me some INVALID XML corrections.
|
||||
ReplacingInputStream ris = new ReplacingInputStream(new ReplacingInputStream(new ReplacingInputStream(new FileInputStream(file), "\r\n", ""), "&", "&"), "\n", " ");
|
||||
@@ -123,15 +120,7 @@ public class Rizzo {
|
||||
transformer.setOutputProperty(OutputKeys.METHOD, "html");
|
||||
transformer.transform(source, result);
|
||||
// Look ma, I'm breaking XML standards!
|
||||
String xmlString = result.getWriter().toString()
|
||||
.replace("&", "&")
|
||||
.replace("<", "<")
|
||||
.replace(">", ">")
|
||||
.replace("	", "\t")
|
||||
.replace("", "\b")
|
||||
.replace(" ", "\n")
|
||||
.replace(" ", "\r")
|
||||
.replace("", "\f");
|
||||
String xmlString = StringEscapeUtils.unescapeHtml4(result.getWriter().toString());
|
||||
try (PrintStream ps = new PrintStream(output)) {
|
||||
ps.print(xmlString);
|
||||
}
|
||||
@@ -139,7 +128,7 @@ public class Rizzo {
|
||||
Logger.getLogger(Rizzo.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
} catch (SAXException | IOException | ParserConfigurationException ex) {
|
||||
Logger.getLogger(Rizzo.class.getName()).log(Level.SEVERE, null, ex);
|
||||
Logger.getLogger(Rizzo.class.getName()).log(Level.SEVERE, "This usually means there's non-standard formatting from the game developer which your FSCRIPT does not account for.", ex);
|
||||
}
|
||||
} else if (args[0].equalsIgnoreCase("str") || args[0].equalsIgnoreCase("xstr")) {
|
||||
try {
|
||||
@@ -206,49 +195,62 @@ public class Rizzo {
|
||||
} catch (FirescriptFormatException | PatchFailedException | IOException ex) {
|
||||
Logger.getLogger(Rizzo.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
} else throw new FirescriptFormatException("file", "unknown command '" + args[0] + "'");
|
||||
} else throw new FirescriptFormatException("file", "command '" + args[0] + "' is unknown or used in inappropriate context");
|
||||
} else if (args[0].equalsIgnoreCase("xml")) {
|
||||
System.out.println("fscript: XML called but file does not exist. Using placebo...");
|
||||
try {
|
||||
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
|
||||
parseArgs(Arrays.copyOfRange(args, 1, args.length), docBuilder.newDocument());
|
||||
} catch (ParserConfigurationException ex1) {
|
||||
Logger.getLogger(Rizzo.class.getName()).log(Level.SEVERE, null, ex1);
|
||||
throw new FirescriptFormatException("xml", "critical document failure");
|
||||
}
|
||||
} else System.out.println("fscript: file context not found, skipping.");
|
||||
} else if (context instanceof Document document) {
|
||||
if (args[0].equalsIgnoreCase("modify")) {
|
||||
Element elem = (Element)traverse(document, args[1]);
|
||||
parseArgs(Arrays.copyOfRange(args, 2, args.length), elem);
|
||||
} else if (args[0].equalsIgnoreCase("create")) {
|
||||
String newTag = args[1].substring(args[1].lastIndexOf(".")+1);
|
||||
String newID = "";
|
||||
if (newTag.contains("#")) {
|
||||
newID = newTag.substring(newTag.indexOf("#")+1);
|
||||
newTag = newTag.substring(0, newTag.indexOf("#"));
|
||||
}
|
||||
Element newElem = document.createElement(newTag);
|
||||
if (newID != null && newID.length() > 0) newElem.setAttribute("id", newID);
|
||||
traverse(document, args[1].substring(0, args[1].lastIndexOf("."))).appendChild(newElem);
|
||||
parseArgs(Arrays.copyOfRange(args, 2, args.length), newElem);
|
||||
} else if (args[0].equalsIgnoreCase("delete")) {
|
||||
Element elem = (Element)traverse(document, args[1]);
|
||||
elem.getParentNode().removeChild(elem);
|
||||
} else if (args[0].equalsIgnoreCase("merge")) {
|
||||
// We're basically copying the file context xml command but with another xml document.
|
||||
try {
|
||||
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
|
||||
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
|
||||
ReplacingInputStream ris = new ReplacingInputStream(new ReplacingInputStream(new ReplacingInputStream(new FileInputStream(new File(workingDir + args[1])), "\r\n", ""), "&", "&"), "\n", " ");
|
||||
Document outDoc = docBuilder.parse(ris);
|
||||
|
||||
NamedNodeMap nnm = outDoc.getDocumentElement().getAttributes();
|
||||
for (int x = 0; x < nnm.getLength(); x++) {
|
||||
Attr importedNode = (Attr) document.importNode(nnm.item(x), true);
|
||||
document.getDocumentElement().setAttributeNodeNS(importedNode);
|
||||
if (document.hasChildNodes()) {
|
||||
if (args[0].equalsIgnoreCase("modify")) {
|
||||
Element elem = (Element)traverse(document, args[1]);
|
||||
parseArgs(Arrays.copyOfRange(args, 2, args.length), elem);
|
||||
} else if (args[0].equalsIgnoreCase("create")) {
|
||||
String newTag = args[1].substring(args[1].lastIndexOf(".")+1);
|
||||
String newID = "";
|
||||
if (newTag.contains("#")) {
|
||||
newID = newTag.substring(newTag.indexOf("#")+1);
|
||||
newTag = newTag.substring(0, newTag.indexOf("#"));
|
||||
}
|
||||
Element newElem = document.createElement(newTag);
|
||||
if (newID != null && newID.length() > 0) newElem.setAttribute("id", newID);
|
||||
traverse(document, args[1].substring(0, args[1].lastIndexOf("."))).appendChild(newElem);
|
||||
parseArgs(Arrays.copyOfRange(args, 2, args.length), newElem);
|
||||
} else if (args[0].equalsIgnoreCase("delete")) {
|
||||
Element elem = (Element)traverse(document, args[1]);
|
||||
elem.getParentNode().removeChild(elem);
|
||||
} else if (args[0].equalsIgnoreCase("merge")) {
|
||||
// We're basically copying the file context xml command but with another xml document.
|
||||
try {
|
||||
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
|
||||
ReplacingInputStream ris = new ReplacingInputStream(new ReplacingInputStream(new ReplacingInputStream(new FileInputStream(new File(workingDir + args[1])), "\r\n", ""), "&", "&"), "\n", " ");
|
||||
Document outDoc = docBuilder.parse(ris); // throw new FirescriptFormatException("xml", "javax.xml.parsers self-destructed with error:\n" + e.getMessage() + "\nThis usually means you used a bad FSCRIPT, or there was non-standard formatting from the game developer.");
|
||||
|
||||
NodeList cn = outDoc.getDocumentElement().getChildNodes();
|
||||
for (int x = 0; x < cn.getLength(); x++) {
|
||||
Node importedNode = document.importNode(cn.item(x), true);
|
||||
document.getDocumentElement().appendChild(importedNode);
|
||||
NamedNodeMap nnm = outDoc.getDocumentElement().getAttributes();
|
||||
for (int x = 0; x < nnm.getLength(); x++) {
|
||||
Attr importedNode = (Attr) document.importNode(nnm.item(x), true);
|
||||
document.getDocumentElement().setAttributeNodeNS(importedNode);
|
||||
}
|
||||
|
||||
NodeList cn = outDoc.getDocumentElement().getChildNodes();
|
||||
for (int x = 0; x < cn.getLength(); x++) {
|
||||
Node importedNode = document.importNode(cn.item(x), true);
|
||||
document.getDocumentElement().appendChild(importedNode);
|
||||
}
|
||||
} catch (SAXException | IOException | ParserConfigurationException ex) {
|
||||
Logger.getLogger(Rizzo.class.getName()).log(Level.SEVERE, "This usually means there's non-standard formatting from the game developer which your FSCRIPT does not account for.", ex);
|
||||
}
|
||||
} catch (SAXException | IOException | ParserConfigurationException ex) {
|
||||
Logger.getLogger(Rizzo.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
} else throw new FirescriptFormatException("xml", "unknown command '" + args[0] + "'");
|
||||
} else throw new FirescriptFormatException("xml", "command '" + args[0] + "' is unknown or used in inappropriate context");
|
||||
} else {
|
||||
System.out.println("fscript: XML document has no child nodes. Skipping...");
|
||||
parseArgs(Arrays.copyOfRange(args, 1, args.length), document);
|
||||
}
|
||||
} else if (context instanceof Element element) {
|
||||
if (args[0].equalsIgnoreCase("set")) {
|
||||
if (args[1].equalsIgnoreCase("attribute"))
|
||||
@@ -347,6 +349,7 @@ public class Rizzo {
|
||||
ns = ((Element)parent).getChildNodes();
|
||||
for (int i = 0; i < ns.getLength(); i++) {
|
||||
Node n = ns.item(i);
|
||||
if (n instanceof Comment) continue;
|
||||
if (n.getNodeName().equals("#text")) continue;
|
||||
if (((Element)n).getAttribute("name").equals(name)) {
|
||||
newParent = (Element)n;
|
||||
|
||||
@@ -58,7 +58,8 @@ public class Rowlf {
|
||||
informationText.getCaret().setVisible(false);
|
||||
informationText.setFocusable(false);
|
||||
|
||||
versionLabel.setText("Version " + Main.vstr + " (" + Main.vcode + ")");
|
||||
versionLabel.setText(Main.vstr + " (" + Main.vcode + ")");
|
||||
//if (Main.isNightly) {versionLabel.setText(versionLabel.getText() + " built " + Main.dateOfCompile);}
|
||||
environmentLabel.setText("Running on Java " + System.getProperty("java.version") + " for " + System.getProperty("os.name"));
|
||||
|
||||
// display window
|
||||
|
||||
@@ -28,10 +28,7 @@ import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.WindowAdapter;
|
||||
import java.awt.event.WindowEvent;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintStream;
|
||||
import java.io.*;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
@@ -209,12 +206,14 @@ public class Suggs implements ActionListener, ListSelectionListener {
|
||||
}
|
||||
} else
|
||||
if (actionEvent.getSource() == spDeleteBtn) {
|
||||
dSTitle.setToolTipText(null);
|
||||
dSTitle.setText("no track");
|
||||
dSSize.setText("no size");
|
||||
sptrack = null;
|
||||
spDeleteBtn.setVisible(false);
|
||||
} else
|
||||
if (actionEvent.getSource() == mpDeleteBtn) {
|
||||
dMTitle.setToolTipText(null);
|
||||
dMTitle.setText("no track");
|
||||
dMSize.setText("no size");
|
||||
mptrack = null;
|
||||
@@ -337,7 +336,8 @@ public class Suggs implements ActionListener, ListSelectionListener {
|
||||
if (result == JFileChooser.APPROVE_OPTION) {
|
||||
File selectedFile = fileChooser.getSelectedFile();
|
||||
sptrack = selectedFile;
|
||||
dSTitle.setText(selectedFile.getName());
|
||||
dSTitle.setText(selectedFile.getName().substring(0, Math.min(selectedFile.getName().length(), 20)));
|
||||
if (selectedFile.getName().length() > 20) {dSTitle.setToolTipText(selectedFile.getName());}
|
||||
dSSize.setText(selectedFile.length() + " B");
|
||||
if (selectedFile.length() > 1023) {
|
||||
dSSize.setText((selectedFile.length() / 1024) + " KB");
|
||||
@@ -355,7 +355,8 @@ public class Suggs implements ActionListener, ListSelectionListener {
|
||||
if (result == JFileChooser.APPROVE_OPTION) {
|
||||
File selectedFile = fileChooser.getSelectedFile();
|
||||
mptrack = selectedFile;
|
||||
dMTitle.setText(selectedFile.getName());
|
||||
dMTitle.setText(selectedFile.getName().substring(0, Math.min(selectedFile.getName().length(), 20)));
|
||||
if (selectedFile.getName().length() > 20) {dMTitle.setToolTipText(selectedFile.getName());}
|
||||
dMSize.setText(selectedFile.length() + " B");
|
||||
if (selectedFile.length() > 1023) {
|
||||
dMSize.setText((selectedFile.length() / 1024) + " KB");
|
||||
@@ -433,19 +434,24 @@ public class Suggs implements ActionListener, ListSelectionListener {
|
||||
progressDialog.setText("Encoding track " + (i+1) + " out of " + tracklist.size() + "...");
|
||||
try {
|
||||
System.out.println("Encoding track #" + (i+1) + " \"" + oArtist + " - " + oTitle + "\"...");
|
||||
if (!at.path.getName().endsWith(".wav") && !at.path.getName().endsWith(".wave")) { // convert to WAV first if it's not readable by at9tool yet
|
||||
new File(Main.inpath + "temp/ffmpeg/").mkdirs();
|
||||
Process p = Main.exec(new String[]{Main.inpath + "ffmpeg.exe", "-y", "-i", at.path.getPath(), "ffmpeg/" + at.path.getName() + ".wav"}, Main.inpath + "temp/");
|
||||
p.waitFor();
|
||||
at.path = new File(Main.inpath + "temp/ffmpeg/" + at.path.getName() + ".wav");
|
||||
}
|
||||
if (normalizeVolumes) { // normalize tracks
|
||||
new File(Main.inpath + "temp/ffmpeg/").mkdirs();
|
||||
Process p = Main.exec(new String[]{Main.inpath + "ffmpeg.exe", "-y", "-i", at.path.getPath(), "-filter", "loudnorm=linear=true:i=-5.0:lra=7.0:tp=0.0", /* force sample rate to prevent Random Stupid Bullshit™ */"-ar", "44100", "ffmpeg/" + at.path.getName() + "_normalized.wav"}, Main.inpath + "temp/");
|
||||
final Thread ioThread = new Thread() {@Override public void run() {Main.printProcessLogToStdOut(p);}};
|
||||
ioThread.start();
|
||||
p.waitFor();
|
||||
at.path = new File(Main.inpath + "temp/ffmpeg/" + at.path.getName() + "_normalized.wav");
|
||||
} else { // convert to WAV first if it's not readable by at9tool yet
|
||||
new File(Main.inpath + "temp/ffmpeg/").mkdirs();
|
||||
Process p = Main.exec(new String[]{Main.inpath + "ffmpeg.exe", "-y", "-i", at.path.getPath(), "-ar", "44100", "ffmpeg/" + at.path.getName() + ".wav"}, Main.inpath + "temp/");
|
||||
final Thread ioThread = new Thread() {@Override public void run() {Main.printProcessLogToStdOut(p);}};
|
||||
ioThread.start();
|
||||
p.waitFor();
|
||||
at.path = new File(Main.inpath + "temp/ffmpeg/" + at.path.getName() + ".wav");
|
||||
}
|
||||
Process p = Main.exec(new String[]{Main.inpath + "at9tool.exe", "-e", "-br", "144", at.path.getPath(), "data/audio/music/" + trackno + "/music_stereo.at9"}, Main.inpath + "temp/");
|
||||
final Thread ioThread = new Thread() {@Override public void run() {Main.printProcessLogToStdOut(p);}};
|
||||
ioThread.start();
|
||||
p.waitFor();
|
||||
Main.deleteDir(new File(Main.inpath + "temp/ffmpeg/"));
|
||||
} catch (IOException | InterruptedException ex) {
|
||||
@@ -500,20 +506,25 @@ public class Suggs implements ActionListener, ListSelectionListener {
|
||||
if (sptrack.exists()) {
|
||||
try {
|
||||
System.out.println("Encoding singleplayer frontend track...");
|
||||
if (!sptrack.getName().endsWith(".wav") && !sptrack.getName().endsWith(".wave")) { // convert to WAV first if it's not readable by at9tool yet
|
||||
new File(Main.inpath + "temp/ffmpeg/").mkdirs();
|
||||
Process p = Main.exec(new String[]{Main.inpath + "ffmpeg.exe", "-y", "-i", sptrack.getPath(), "ffmpeg/" + sptrack.getName() + ".wav"}, Main.inpath + "temp/");
|
||||
p.waitFor();
|
||||
sptrack = new File(Main.inpath + "temp/ffmpeg/" + sptrack.getName() + ".wav");
|
||||
}
|
||||
if (normalizeVolumes) { // normalize tracks
|
||||
new File(Main.inpath + "temp/ffmpeg/").mkdirs();
|
||||
Process p = Main.exec(new String[]{Main.inpath + "ffmpeg.exe", "-y", "-i", sptrack.getPath(), "-filter", "loudnorm=linear=true:i=-10.0:lra=12.0:tp=-2.0", /* force sample rate to prevent Random Stupid Bullshit™ */"-ar", "44100", "ffmpeg/" + sptrack.getName() + "_normalized.wav"}, Main.inpath + "temp/");
|
||||
final Thread ioThread = new Thread() {@Override public void run() {Main.printProcessLogToStdOut(p);}};
|
||||
ioThread.start();
|
||||
p.waitFor();
|
||||
sptrack = new File(Main.inpath + "temp/ffmpeg/" + sptrack.getName() + "_normalized.wav");
|
||||
} else { // convert to WAV first if it's not readable by at9tool yet
|
||||
new File(Main.inpath + "temp/ffmpeg/").mkdirs();
|
||||
Process p = Main.exec(new String[]{Main.inpath + "ffmpeg.exe", "-y", "-i", sptrack.getPath(), "-ar", "44100", "ffmpeg/" + sptrack.getName() + ".wav"}, Main.inpath + "temp/");
|
||||
final Thread ioThread = new Thread() {@Override public void run() {Main.printProcessLogToStdOut(p);}};
|
||||
ioThread.start();
|
||||
p.waitFor();
|
||||
sptrack = new File(Main.inpath + "temp/ffmpeg/" + sptrack.getName() + ".wav");
|
||||
}
|
||||
new File(Main.inpath + "temp/data/audio/music/FEMusic").mkdirs();
|
||||
Process p = Main.exec(new String[]{Main.inpath + "at9tool.exe", "-e", "-br", "144", sptrack.getPath(), "data/audio/music/FEMusic/frontend_stereo.at9"}, System.getProperty("user.home") + "/.firestar/temp/");
|
||||
final Thread ioThread = new Thread() {@Override public void run() {Main.printProcessLogToStdOut(p);}};
|
||||
ioThread.start();
|
||||
p.waitFor();
|
||||
Main.deleteDir(new File(Main.inpath + "temp/ffmpeg/"));
|
||||
} catch (IOException | InterruptedException ex) {
|
||||
@@ -528,20 +539,25 @@ public class Suggs implements ActionListener, ListSelectionListener {
|
||||
try {
|
||||
assert(mptrack.exists());
|
||||
System.out.println("Encoding multiplayer frontend track...");
|
||||
if (!mptrack.getName().endsWith(".wav") && !mptrack.getName().endsWith(".wave")) { // convert to WAV first if it's not readable by at9tool yet
|
||||
new File(Main.inpath + "temp/ffmpeg/").mkdirs();
|
||||
Process p = Main.exec(new String[]{Main.inpath + "ffmpeg.exe", "-y", "-i", mptrack.getPath(), "ffmpeg/" + mptrack.getName() + ".wav"}, Main.inpath + "temp/");
|
||||
p.waitFor();
|
||||
mptrack = new File(Main.inpath + "temp/ffmpeg/" + mptrack.getName() + ".wav");
|
||||
}
|
||||
if (normalizeVolumes) { // normalize tracks
|
||||
new File(Main.inpath + "temp/ffmpeg/").mkdirs();
|
||||
Process p = Main.exec(new String[]{Main.inpath + "ffmpeg.exe", "-y", "-i", mptrack.getPath(), "-filter", "loudnorm=linear=true:i=-10.0:lra=12.0:tp=-2.0", /* force sample rate to prevent Random Stupid Bullshit™ */"-ar", "44100", "ffmpeg/" + mptrack.getName() + "_normalized.wav"}, Main.inpath + "temp/");
|
||||
final Thread ioThread = new Thread() {@Override public void run() {Main.printProcessLogToStdOut(p);}};
|
||||
ioThread.start();
|
||||
p.waitFor();
|
||||
mptrack = new File(Main.inpath + "temp/ffmpeg/" + mptrack.getName() + "_normalized.wav");
|
||||
} else { // convert to WAV first if it's not readable by at9tool yet
|
||||
new File(Main.inpath + "temp/ffmpeg/").mkdirs();
|
||||
Process p = Main.exec(new String[]{Main.inpath + "ffmpeg.exe", "-y", "-i", mptrack.getPath(), "-ar", "44100", "ffmpeg/" + mptrack.getName() + ".wav"}, Main.inpath + "temp/");
|
||||
final Thread ioThread = new Thread() {@Override public void run() {Main.printProcessLogToStdOut(p);}};
|
||||
ioThread.start();
|
||||
p.waitFor();
|
||||
mptrack = new File(Main.inpath + "temp/ffmpeg/" + mptrack.getName() + ".wav");
|
||||
}
|
||||
new File(Main.inpath + "temp/data/audio/music/FEDemoMusic").mkdirs();
|
||||
Process p = Main.exec(new String[]{Main.inpath + "at9tool.exe", "-e", "-br", "144", mptrack.getPath(), "data/audio/music/FEDemoMusic/frontend_stereo.at9"}, System.getProperty("user.home") + "/.firestar/temp/");
|
||||
final Thread ioThread = new Thread() {@Override public void run() {Main.printProcessLogToStdOut(p);}};
|
||||
ioThread.start();
|
||||
p.waitFor();
|
||||
Main.deleteDir(new File(Main.inpath + "temp/ffmpeg/"));
|
||||
} catch (IOException | InterruptedException ex) {
|
||||
|
||||
@@ -90,7 +90,9 @@
|
||||
<grid id="b015e" layout-manager="GridLayoutManager" row-count="1" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<margin top="0" left="0" bottom="0" right="0"/>
|
||||
<constraints>
|
||||
<grid row="4" column="1" row-span="1" col-span="2" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
|
||||
<grid row="4" column="1" row-span="1" col-span="2" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false">
|
||||
<maximum-size width="500" height="-1"/>
|
||||
</grid>
|
||||
</constraints>
|
||||
<properties>
|
||||
<opaque value="false"/>
|
||||
@@ -99,7 +101,7 @@
|
||||
<children>
|
||||
<component id="18770" class="javax.swing.JLabel" binding="fOutpath">
|
||||
<constraints>
|
||||
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="7" anchor="0" fill="0" indent="0" use-parent-layout="false"/>
|
||||
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<font name="Exo 2"/>
|
||||
@@ -109,7 +111,7 @@
|
||||
</component>
|
||||
<component id="fa1ee" class="javax.swing.JButton" binding="fOutpathChangebtn">
|
||||
<constraints>
|
||||
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="0" fill="0" indent="0" use-parent-layout="false"/>
|
||||
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<background color="-2271221"/>
|
||||
|
||||
@@ -67,7 +67,7 @@ public class Waldorf implements ActionListener {
|
||||
dwnSDKbtn.addActionListener(this);
|
||||
fOutpathChangebtn.addActionListener(this);
|
||||
|
||||
fOutpath.setText(Main.outpath);
|
||||
updateDOutpath(Main.outpath);
|
||||
checkUpdatesToggle.setSelected(Main.checkUpdates);
|
||||
|
||||
frame.setVisible(true);
|
||||
@@ -81,6 +81,13 @@ public class Waldorf implements ActionListener {
|
||||
});
|
||||
}
|
||||
|
||||
private void updateDOutpath(String path) {
|
||||
String s = path;
|
||||
if (s.startsWith(System.getProperty("user.home"))) {s = "~" + s.substring(System.getProperty("user.home").length());}
|
||||
if (s.length() > 50) {s = s.substring(0, Math.min(path.length(), 46)) + "...";fOutpath.setToolTipText(path);} else {fOutpath.setToolTipText(null);}
|
||||
fOutpath.setText(s);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent actionEvent) {
|
||||
if (actionEvent.getSource() == cancelbtn) {
|
||||
@@ -126,6 +133,10 @@ public class Waldorf implements ActionListener {
|
||||
JOptionPane.showMessageDialog(frame, "PSARC files purged.", "Delete PSARCs", JOptionPane.INFORMATION_MESSAGE);
|
||||
} else
|
||||
if (actionEvent.getSource() == dwnARCbtn) {
|
||||
if (!new File(Main.inpath + "pkg2zip.exe").exists() || !new File(Main.inpath + "psvpfsparser.exe").exists()) {
|
||||
JOptionPane.showMessageDialog(frame, "Your decryption tools are missing.\nPlease select \"Get Dependencies\" in the Options menu.", "Error", JOptionPane.ERROR_MESSAGE);
|
||||
return;
|
||||
}
|
||||
new Bert(invoker.frame);
|
||||
frame.dispose();
|
||||
} else
|
||||
@@ -147,7 +158,7 @@ public class Waldorf implements ActionListener {
|
||||
if (result == JFileChooser.APPROVE_OPTION) {
|
||||
if (fileChooser.getSelectedFile().isDirectory()) {
|
||||
tOutPath = fileChooser.getSelectedFile().getAbsolutePath()+"/";
|
||||
fOutpath.setText(tOutPath);
|
||||
updateDOutpath(tOutPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Before Width: | Height: | Size: 823 B After Width: | Height: | Size: 4.8 KiB |
|
Before Width: | Height: | Size: 851 B After Width: | Height: | Size: 5.0 KiB |
BIN
firestar/src/main/resources/splash0.png
Normal file
|
After Width: | Height: | Size: 362 KiB |
BIN
firestar/src/main/resources/splash1.png
Normal file
|
After Width: | Height: | Size: 326 KiB |
BIN
firestar/src/main/resources/splash10.png
Normal file
|
After Width: | Height: | Size: 319 KiB |
BIN
firestar/src/main/resources/splash2.png
Normal file
|
After Width: | Height: | Size: 362 KiB |
BIN
firestar/src/main/resources/splash3.png
Normal file
|
After Width: | Height: | Size: 299 KiB |
BIN
firestar/src/main/resources/splash4.png
Normal file
|
After Width: | Height: | Size: 374 KiB |
BIN
firestar/src/main/resources/splash5.png
Normal file
|
After Width: | Height: | Size: 294 KiB |
BIN
firestar/src/main/resources/splash6.png
Normal file
|
After Width: | Height: | Size: 293 KiB |
BIN
firestar/src/main/resources/splash7.png
Normal file
|
After Width: | Height: | Size: 238 KiB |
BIN
firestar/src/main/resources/splash8.png
Normal file
|
After Width: | Height: | Size: 429 KiB |
BIN
firestar/src/main/resources/splash9.png
Normal file
|
After Width: | Height: | Size: 318 KiB |
1287
firestar/src/main/resources/unused.fscript
Normal file
@@ -1 +1 @@
|
||||
netbeans.hint.jdkPlatform=JDK_22__System_
|
||||
netbeans.hint.jdkPlatform=JDK_17__System_
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
; Script generated by the Inno Setup Script Wizard.
|
||||
; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!
|
||||
|
||||
#define MyAppName "Firestar Mod Manager"
|
||||
#define MyAppVersion "1.2"
|
||||
#define MyAppPublisher "bonkmaykr"
|
||||
#define MyAppName "Firestar"
|
||||
#define MyAppVersion "1.3.1"
|
||||
#define MyAppPublisher "Canithesis Interactive"
|
||||
#define MyAppURL "https://screwgravity.net/firestar/"
|
||||
#define MyAppExeName "firestar.jar"
|
||||
#define MyAppAssocName "Firestar Mod Package"
|
||||
@@ -30,7 +30,7 @@ LicenseFile=Z:\home\bonkyboo\repos\firestar\LICENSE
|
||||
PrivilegesRequiredOverridesAllowed=dialog
|
||||
OutputDir=Z:\home\bonkyboo\repos\firestar\out\inno
|
||||
OutputBaseFilename=firestar
|
||||
SetupIconFile=Z:\home\bonkyboo\repos\firestar\titleIcon.ico
|
||||
SetupIconFile=Z:\home\bonkyboo\repos\firestar\programIcon.ico
|
||||
Compression=lzma
|
||||
SolidCompression=yes
|
||||
WizardStyle=modern
|
||||
@@ -43,8 +43,7 @@ Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{
|
||||
|
||||
[Files]
|
||||
Source: "Z:\home\bonkyboo\repos\firestar\out\artifacts\firestar_jar\{#MyAppExeName}"; DestDir: "{app}"; Flags: ignoreversion
|
||||
Source: "Z:\home\bonkyboo\repos\firestar\titleIcon.ico"; DestDir: "{app}"; Flags: ignoreversion
|
||||
Source: "Z:\home\bonkyboo\repos\firestar\resources\*"; DestDir: "{app}\resources"; Flags: ignoreversion recursesubdirs createallsubdirs
|
||||
Source: "Z:\home\bonkyboo\repos\firestar\programIcon.ico"; DestDir: "{app}"; Flags: ignoreversion
|
||||
; NOTE: Don't use "Flags: ignoreversion" on any shared system files
|
||||
|
||||
[Registry]
|
||||
@@ -55,6 +54,6 @@ Root: HKA; Subkey: "Software\Classes\{#MyAppAssocKey}\shell\open\command"; Value
|
||||
Root: HKA; Subkey: "Software\Classes\Applications\{#MyAppExeName}\SupportedTypes"; ValueType: string; ValueName: ".myp"; ValueData: ""
|
||||
|
||||
[Icons]
|
||||
Name: "{autoprograms}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; IconFilename: "{app}\titleIcon.ico";
|
||||
Name: "{autodesktop}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; IconFilename: "{app}\titleIcon.ico"; Tasks: desktopicon
|
||||
Name: "{autoprograms}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; IconFilename: "{app}\programIcon.ico";
|
||||
Name: "{autodesktop}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; IconFilename: "{app}\programIcon.ico"; Tasks: desktopicon
|
||||
|
||||
|
||||
BIN
programIcon.ico
Normal file
|
After Width: | Height: | Size: 189 KiB |
BIN
titleIcon.ico
|
Before Width: | Height: | Size: 180 KiB |