Compare commits
45 Commits
b4b8b1ced5
...
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 | |||
| 17bbae0d66 | |||
| 4aa017f7ac | |||
| a57e5695a5 | |||
| 009f406a4b | |||
| 2d7e0a1cb0 |
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" />
|
||||
|
||||
79
README.md
@@ -1,47 +1,75 @@
|
||||

|
||||
|
||||
**Firestar is a cross-platform Java-based mod manager for WipEout 2048**, which runs on a desktop/laptop computer and aims to allow easy installation of mods for users with very little hassle. It is compatible with both real PSVita hardware, as well as emulators.
|
||||
**Firestar is a cross-platform Java-based mod manager for WipEout 2048**, which runs on a desktop/laptop computer and aims to allow easy installation of mods with very little hassle. It is compatible with both real PSVita hardware, as well as with emulators.
|
||||
|
||||
## Get Started: [>> CLICK HERE <<](https://git.worlio.com/bonkmaykr/firestar/wiki)
|
||||
## 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.
|
||||
|
||||
- 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 [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
|
||||
- If you have a Mac running 10.15 Catalina or newer, you should use Crossover to run the Windows version of Firestar instead.
|
||||
- If you have a Mac running 10.15 Catalina or newer, you should use Crossover to run the Windows version of Firestar instead.
|
||||
- Java 17 or above.
|
||||
- **Non-Windows systems only**: WINE
|
||||
- **Version 1.3 and above only:** [Visual C++ 2012 libraries](http://www.microsoft.com/en-au/download/confirmation.aspx?id=30679)
|
||||
- Do NOT install Firestar directly to your PSVita's storage. Some of it's file operations do not play nice with FAT filesystems.
|
||||
|
||||
# Building
|
||||
You are always free to copy the Firestar source code and compile the latest work-in-progress version for yourself.
|
||||
Firestar uses the Gradle build system. We write our code and perform all our tests on Linux, but these same steps should apply to all major operating systems.
|
||||
|
||||
## With Intellij IDEA
|
||||
1. Create a new project cloned from this Git repo
|
||||
2. Open the run configurations editor by clicking "Default" in the top right corner and selecting "Edit Configurations".
|
||||
3. Set the JDK to Java 17, the module to firestar.firestar.main and the main class to Firestar's Main class.
|
||||
4. Go to Modify Options > Add before launch task, then add a Gradle "clean" task
|
||||
5. Go there again and add a Gradle "build" task
|
||||
6. Delete the default build task that has now appeared as step 1.
|
||||
7. Save your options and click the Play button to compile and test.
|
||||
|
||||
## From the command line
|
||||
1. Ensure you have both Git and Gradle installed on your system.
|
||||
- Windows: Visit [git-scm.com](https://git-scm.com/downloads) and the [Gradle Installation Guide](https://gradle.org/install/).
|
||||
- Linux/BSD: Install the `git` and `gradle` packages from your package manager. For example:
|
||||
- Arch-based: `sudo pacman -Sy git gradle` (if this breaks your computer then run -Syu to rectify it)
|
||||
- Debian-based: `sudo apt install git gradle`
|
||||
- Mac: Figure it out! None of us on the dev team use Macs and we can't be assed to.
|
||||
2. Open the terminal and clone the git repo. This will download the Firestar source code to a `firestar/` folder in your current working directory.
|
||||
|
||||
```
|
||||
git clone https://git.worlio.com/bonkmaykr/firestar.git
|
||||
```
|
||||
|
||||
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?
|
||||
No. You need a modded Vita in order to use this. Hacking a Vita is super easy these days, but if you don't want to, you can always use Vita3K instead.
|
||||
|
||||
## Where do I download mods?
|
||||
There's no #1 place for Firestar mods as of now, but we can give you a few sample mods to test out if you are interested in seeing the program in action:
|
||||
There's no #1 place for Firestar mods as of now, but we can give you a few sample mods to test out if you are interested in seeing the program in action:
|
||||
- [XP Rebalance](https://files.worlio.com/users/bonkmaykr/patches/2048/XPhack2.fstar): Reduces the amount of grinding required to level up for players who can't access the online campaign. **Leaderboard safe version!**
|
||||
- [Pepsi Mod](https://files.worlio.com/users/bonkmaykr/http/reddit/pepsi_agility.fstar): Gives the FEISAR Agility ship a Pepsi makeover.
|
||||
- [Gold AG-SYS Speed](https://files.worlio.com/users/bonkmaykr/patches/2048/gold3.fstar): Better Than Chrome™
|
||||
- [Continue?](https://files.worlio.com/users/bonkmaykr/patches/2048/continue.fstar): Allows you to exit the pause menu without taking your thumb off the throttle. By ThatOneBonk
|
||||
- [HD Skin](https://files.worlio.com/users/bonkmaykr/patches/2048/hd_skin.fstar): Recolors the UI to look like WipEout HD. By ThatOneBonk
|
||||
- [HD Skin](https://files.worlio.com/users/bonkmaykr/patches/2048/hd_skin.fstar): Recolors the UI to look like WipEout HD. By ThatOneBonk
|
||||
- [Custom Soundtrack](https://files.catbox.moe/pcvfxj.fstar): A custom playlist I put together. This music is copyrighted, don't play it on stream
|
||||
|
||||
## What do I need to make my own mods?
|
||||
For making your own mods, we recommend grabbing one of the many leaked PS Vita SDKs off of Archive.org since it has many of the tools you will need. I recommend using Photoshop CS5 for textures, since Sony officially provides a texture export plugin for CS5 in their SDK. There is also an included at9tool which can help with replacing sounds and music.
|
||||
|
||||
Many things like HUDs, custom translations, and even some game variables are kept in XML format and can be edited in any normal text editor like Microsoft Notepad, GNU Nano, GEdit or KWrite. (Please play nice when you're online.)
|
||||
|
||||
For making your own mods, we recommend grabbing one of the many leaked PS Vita SDKs off of Archive.org since it has many of the tools you will need. I recommend using Photoshop CS5 for textures, since Sony officially provides a texture export plugin for CS5 in their SDK. There is also an included at9tool which can help with replacing sounds and music.
|
||||
|
||||
Many things like HUDs, custom translations, and even some game variables are kept in XML format and can be edited in any normal text editor like Microsoft Notepad, GNU Nano, GEdit or KWrite. (Please play nice when you're online.)
|
||||
|
||||
As for models and custom tracks, we don't have a concrete way of modifying those just yet, but work is being done on that, so stay tuned.
|
||||
|
||||
## (Non-Windows) About WINE Compatibility
|
||||
@@ -58,22 +86,19 @@ Firestar is built on top of the following additional software:
|
||||
- [pkg2zip](https://github.com/mmozeiko/pkg2zip) & [psvpfsparser](https://github.com/motoharu-gosuto/psvpfstools), for (legal) asset decryption from Playstation Network.
|
||||
- [libcurl](https://curl.se/libcurl/), allows psvpfsparser to communicate with Henkaku's F00D server.
|
||||
- psp2psarc, Sony's proprietary PSARC compression/decompression utility.
|
||||
- at9tool, Sony's proprietary ATRAC9 codec.
|
||||
|
||||
- at9tool, Sony's proprietary ATRAC9 codec.
|
||||
|
||||
*_WINE, ffmpeg, and the Java Runtime are pulled as package dependencies on Linux systems._
|
||||
†_Libraries baked directly into the executable._
|
||||
†_Libraries baked directly into the executable._
|
||||
|
||||
All of these, save for psp2psarc, appear in Tetsuo (1.3) and onwards. The licenses for Sony's psp2psarc and at9tool are polar opposite from Firestar's own GPL, so you should not expect Firestar to be a completely "libre" application (but then again, you're a WipEout player, the free software movement clearly isn't a huge concern). The open source nature of Firestar is provided with the hopes of allowing others to critique, audit, and improve upon the software, not necessarily for idealogical reasons.
|
||||
|
||||
All of these, save for psp2psarc, appear in Tetsuo (1.3) and onwards. The licenses for Sony's psp2psarc and at9tool are polar opposite from Firestar's own GPL, so you should not expect Firestar to be a completely "libre" application (but then again, you're a WipEout player, the free software movement clearly isn't a huge concern). The open source nature of Firestar is provided with the hopes of allowing others to critique, audit, and improve upon the software, not necessarily for idealogical reasons.
|
||||
|
||||
Ideally, in the future, all of this functionality can be built into Firestar natively without any fancy tricks.
|
||||
## Why use a leaked Playstation SDK?
|
||||
Because many third-party programs for opening PSARC files either have no ability to create new ones or are prone to corruption bugs. Using the one made by the developers of the file format is the best option as it's what the game developers would have used. Obviously this creates all kinds of legal grey areas, so I can't distribute Sony's proprietary software next to my code. It's downloaded separately during the setup process.
|
||||
|
||||
## Why Java?
|
||||
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.
|
||||
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.
|
||||
|
||||
## 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.
|
||||
## 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.
|
||||
@@ -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);
|
||||
|
||||
@@ -20,16 +20,15 @@ import net.lingala.zip4j.ZipFile;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.border.TitledBorder;
|
||||
import javax.swing.text.DefaultCaret;
|
||||
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;
|
||||
|
||||
@@ -77,6 +76,9 @@ public class Gonzo {
|
||||
frame.setAlwaysOnTop(true);
|
||||
frame.setVisible(true);
|
||||
|
||||
DefaultCaret caret = (DefaultCaret) consoleDisplay.getCaret();
|
||||
caret.setUpdatePolicy(DefaultCaret.ALWAYS_UPDATE);
|
||||
|
||||
File psarcHandle = new File(Main.inpath + "data.psarc");
|
||||
data0 = psarcHandle.isFile();
|
||||
psarcHandle = new File(Main.inpath + "data1.psarc");
|
||||
@@ -104,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() {
|
||||
@@ -155,15 +180,41 @@ 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);
|
||||
consoleDisplay.append("Firestar is applying patches from " + m.friendlyName + " by " + m.author + "\n");
|
||||
new Rizzo(new FileInputStream(fscript), Main.inpath + "temp/"); // Lets rizz this mod up
|
||||
fscript.delete();
|
||||
}
|
||||
@@ -171,6 +222,8 @@ public class Gonzo {
|
||||
if (new File(System.getProperty("user.home") + "/.firestar/temp/delete.txt").isFile()) {
|
||||
System.out.println("Firestar is deleting files that conflict with " + m.friendlyName + " by " + m.author);
|
||||
consoleDisplay.append("Firestar is deleting files that conflict with " + m.friendlyName + " by " + m.author + "\n");
|
||||
System.out.println("WARNING: delete.txt is DEPRECATED. If using a mod with loaderversion >= 1 then this is bad practice, please use FSCRIPTs instead.");
|
||||
consoleDisplay.append("WARNING: delete.txt is DEPRECATED. If using a mod with loaderversion >= 1 then this is bad practice, please use FSCRIPTs instead.");
|
||||
|
||||
String deleteQueue = new String(Files.readAllBytes(Paths.get(System.getProperty("user.home") + "/.firestar/temp/delete.txt")));
|
||||
if (Main.windows) {deleteQueue = new String(Files.readAllBytes(Paths.get(System.getProperty("user.home") + "\\.firestar\\temp\\delete.txt")));} // might be unnecessary
|
||||
@@ -195,14 +248,15 @@ public class Gonzo {
|
||||
}
|
||||
}
|
||||
|
||||
// cleanup so we don't run it again for the next mod unless needed
|
||||
// this is not necessary but good practice
|
||||
// cleanup so we don't run it again for the next mod
|
||||
new File(System.getProperty("user.home") + "/.firestar/temp/delete.txt").delete();
|
||||
}
|
||||
} 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;
|
||||
@@ -216,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;
|
||||
@@ -260,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() {
|
||||
@@ -309,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());
|
||||
@@ -342,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) {
|
||||
|
||||
@@ -31,7 +31,6 @@ import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.io.StringWriter;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
@@ -47,15 +46,14 @@ import javax.xml.transform.TransformerException;
|
||||
import javax.xml.transform.TransformerFactory;
|
||||
import javax.xml.transform.dom.DOMSource;
|
||||
import javax.xml.transform.stream.StreamResult;
|
||||
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 javax.xml.transform.OutputKeys;
|
||||
|
||||
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", " ");
|
||||
@@ -118,16 +115,12 @@ public class Rizzo {
|
||||
|
||||
StreamResult result = new StreamResult(new StringWriter());
|
||||
DOMSource source = new DOMSource(doc);
|
||||
|
||||
|
||||
// WipEout 2048 will pretend to be happy with these self-closed tags but in actuality, it is screaming on the inside.
|
||||
transformer.setOutputProperty(OutputKeys.METHOD, "html");
|
||||
transformer.transform(source, result);
|
||||
// Look ma, I'm breaking XML standards!
|
||||
String xmlString = result.getWriter().toString()
|
||||
.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);
|
||||
}
|
||||
@@ -135,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 {
|
||||
@@ -202,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"))
|
||||
@@ -343,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 |