38 Commits

Author SHA1 Message Date
46be75cbec Update README.md 2025-08-20 14:53:35 -04:00
df9f4a8ba7 Update Inno installer configuration 2025-03-11 13:45:07 -05:00
9155493c0e Remove busted splash 2025-03-11 10:29:28 -05:00
c32d45c63f Update version number 2025-03-11 10:25:16 -05:00
e53933200e Update linker settings 2025-03-10 13:01:59 -05:00
Downforce Agent
8840a193a3 These instructions are wrong. 2025-03-05 23:53:22 -05:00
c9a968d173 Display installed PSArcs in options screen 2025-02-25 19:37:37 -06:00
b1f38400c3 splash fixes 2025-02-23 16:32:46 -06:00
889e99f301 Splash screen 2025-02-22 15:45:26 -06:00
9585f16f11 Allow skipping patch download 2025-02-22 11:20:50 -06:00
f7c4603db1 Update Jenkins build info 2025-02-20 14:06:09 -06:00
9292d8db62 Check for dependencies before opening any menus that require them 2025-02-20 10:39:19 -06:00
b8dbfc9095 FINALLY - implement PSARC partial extraction (in the shittiest way, but it's all we can do right now) - 1.3 is about ready 2025-02-20 10:26:26 -06:00
f07a75276c Read/write requires[] and extracts[] 2025-02-20 09:08:23 -06:00
f336be5a0a enforce compatible sample rate for ATRAC9, stop duplicate conversion, (poorly) steal console output from ffmpeg and at9tool 2024-11-03 15:09:13 -06:00
841f8132bb I forgor 2024-10-04 13:14:19 -05:00
5654fa0b9f Checksum downloaded executables, don't quote download filenames 2024-10-04 13:12:34 -05:00
f21d05d245 sync changes to ide/comment from thinkpad 2024-10-03 15:30:41 -04:00
b5f2aa6925 Fix radios being multi-selectible in Bert 2024-10-03 10:42:08 -04:00
12f01000dd Allow downloading data1 from Bert 2024-09-20 21:33:26 -05:00
168e536068 fix XML parser self-destructing when it tries to get child elements belonging to a developer comment 2024-08-02 18:40:31 -05:00
64230f5eb4 Fix main list flipping itself backwards after a deploy 2024-08-02 18:26:39 -05:00
91a574bb04 Reverse extraction order so that bottom of mod list is lowest priority and vice versa 2024-08-02 17:17:07 -05:00
e877f5eaa6 better error dialog 2024-08-02 17:09:06 -05:00
b3a949fe43 better error dialog 2024-08-02 17:00:29 -05:00
a17f7d1b58 cleanup temporary files if gonzo has crashed or when user closes it 2024-08-02 16:22:48 -05:00
efbf8585d2 prepend exec commands with path (for windows) 2024-08-01 18:12:40 -05:00
3849a765e3 update README.md w/ SOP 2024-08-01 16:43:28 -05:00
2bbf34bf70 Create separate version ID for nightly auto-builds, shorten awkward "Version Release" string, add Apache Commons dependencies 2024-08-01 12:42:21 -05:00
ca36fadad1 Truncate overflowing strings 2024-07-30 15:11:18 -05:00
a75f1ad06c Update compiler instructions to not use gradle wrapper which is incorrect 2024-07-29 18:41:29 -04:00
a54c1ea325 Fix #7 2024-07-28 23:37:55 -05:00
780a7d69b3 Undistribute gradlew, will be moving to jenkins server and avoiding micro$oft BS 2024-07-28 06:35:58 -04:00
8dfed698bb Distribute GradleWrapper with source to allow github actions to function (2) 2024-07-27 12:47:16 -05:00
040adf3b7e Distribute GradleWrapper with source to allow github actions to function 2024-07-27 12:43:56 -05:00
309aaec333 Fixed compilation error on Intellij due to new library 2024-07-27 04:10:09 -05:00
8af95d5287 fix xml ignoring among other rizzo improvements 2024-07-26 21:31:41 -05:00
9950188e0d fix the mess of encodings 2024-07-26 21:05:56 -05:00
41 changed files with 2135 additions and 1494 deletions

2
.gitignore vendored
View File

@@ -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/*

View File

@@ -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
View 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
View 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
View File

@@ -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" />

View File

@@ -4,17 +4,17 @@
## Get Started: [>> CLICK HERE <<](https://git.worlio.com/bonkmaykr/firestar/wiki)
![](https://files.worlio.com/users/bonkmaykr/http/git/embed/2024-07-12_15-02.png)
![](https://files.worlio.com/users/bonkmaykr/http/git/embed/ScreenShot.'Main'.0x8000024.20250820.135157.png)
# Installation
The latest version of Firestar will always be available from [Releases](https://git.worlio.com/bonkmaykr/firestar/releases).
If you aren't sure which file to get:
- **Windows:** Download the latest installer [here](https://files.worlio.com/users/bonkmaykr/tools/firestar/latest/firestar_1.2_installer_windows.exe).
- **Windows:** Download the latest installer [here](https://screwgravity.net/firestar/builds/stable/tetsuo/firestar_1.3_installer_winnt_x86-64.exe).
- **Linux:** Install one of the packages from the [Releases](https://git.worlio.com/bonkmaykr/firestar/releases) page:
- Ubuntu, Mint, PopOS: `sudo dpkg -i firestar_ver_arch.deb` or `gdebi firestar_ver_arch.deb`
- Fedora, Mageia, OpenSUSE, AlmaLinux: `sudo rpm -i firestar-ver-arch.rpm`
- Arch, EndeavourOS, CachyOS, Steam Deck: `sudo pacman -U firestar-ver-arch.pkg.tar.zst`
- **All Platforms:** Grab the [Portable ZIP](https://files.worlio.com/users/bonkmaykr/tools/firestar/latest/firestar_dekka-1.2_portable.zip), extract it, and run the JAR file.
- **All Platforms:** Grab the [JAR](https://screwgravity.net/firestar/builds/stable/tetsuo/firestar_1.3_portable.jar) and run it.
# System Requirements
- Windows 8 or newer, Mac OS X 10.14 or older, any modern version of Linux/BSD
@@ -50,8 +50,7 @@ Firestar uses the Gradle build system. We write our code and perform all our tes
git clone https://git.worlio.com/bonkmaykr/firestar.git
```
3. `cd` to `firestar/` and run `./gradlew build` to make a JAR or `./gradlew run` to test your code immediately.
- On Windows systems make sure you're running `gradlew.bat` and not the Bash script instead.
3. `cd` to `firestar/` and run `gradle build` to make a JAR or `gradle run` to test your code immediately.
# FAQ
## Can I use this on a Vita without enso/HEN?
@@ -102,7 +101,4 @@ Because many third-party programs for opening PSARC files either have no ability
Cross-platform support with no hassle, a built-in UI framework, and I don't need to sell my soul like every Electron or React 'Native' developer is doing these days.
## Why the name "Firestar"?
Firestar was a secret track in the original WipEout which you unlocked after beating the game at least once, the mod manager is just named after that. Major versions are named after pilots or tracks. Internal class names are named after Muppets characters as this is the same naming convention that Sony used to codename parts inside the PSVita's SOC.
## Fast Mode vs. Compatibility Mode
"Fast Mode" was a legacy option that was scrapped before it could be developed. It skipped the creation of a PSARC file and simply dumped the final game assets to their destination folder. This works great for emulators, and doesn't require proprietary stolen SDKs from SCE. However the filesystem on the Playstation Vita really hated this method and would glitch out when this was done, causing textures to be corrupted once placed on the memory card. The WipEout engine has no fault tolerance for malformed or missing assets, so it just crashes instantly when it encounters one. This is where Compatibility mode comes from, which is the default setting for 2048.
Firestar was a secret track in the original WipEout which you unlocked after beating the game at least once, the mod manager is just named after that. Major versions are named after pilots or tracks. Internal class names are named after Muppets characters as this is the same naming convention that Sony used to codename parts inside the PSVita's SOC.

View File

@@ -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 {

View 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>

View 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();
}
}

View File

@@ -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>

View File

@@ -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);
}
}

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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);

View File

@@ -25,12 +25,10 @@ import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.*;
import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.TimeUnit;
@@ -108,24 +106,47 @@ public class Gonzo {
}
private void CompatibilityRoutine() {
// cleanup any failed deploys to avoid scripts running when they are not supposed to be
Main.deleteDir(new File(System.getProperty("user.home") + "/.firestar/temp/"));
// create temporary working area for asset dump
new File(System.getProperty("user.home") + "/.firestar/temp/").mkdirs();
new File(System.getProperty("user.home") + "/.firestar/temparcs/").mkdirs();
// Work from bottom to top, mods on top always overwrite the ones on the bottom.
List<Main.Mod> modsFlipped = new ArrayList<>(Main.Mods);
Collections.reverse(modsFlipped);
// decide which files to dump
List<String> dumpThese = new ArrayList<String>();
if (data0) {dumpThese.add("data.psarc");oArcTarget = "data.psarc";}
if (data1) {dumpThese.add("data1.psarc");oArcTarget = "data1.psarc";}
if (data2) {dumpThese.add("data2.psarc");oArcTarget = "data2.psarc";}
if (dlc1) {dumpThese.add("dlc1.psarc");oArcTarget = "dlc1.psarc";}
if (dlc2) {dumpThese.add("dlc2.psarc");oArcTarget = "dlc2.psarc";}
for (Main.Mod m : modsFlipped) {
if (m.enabled) {
System.out.println(m.friendlyName + " : " + m.requires.toString() + " : " + m.extracts.toString());
for (String r : m.requires) if (!dumpThese.contains(r)) dumpThese.add(r);
}
}
if (data0) oArcTarget = "data.psarc";
if (data1) oArcTarget = "data1.psarc";
if (data2) oArcTarget = "data2.psarc";
if (dlc1) oArcTarget = "dlc1.psarc";
if (dlc2) oArcTarget = "dlc2.psarc";
dumpThese.remove(oArcTarget); dumpThese.add(oArcTarget); // Always dump the base game last. TODO should we allow mods to specify otherwise??
System.out.println("List of files to dump: " + dumpThese);
// dump all assets to working area
for (String s : dumpThese) {
try {
if (!(new File(Main.inpath + s).exists()))
throw new IOException("A mod requested access to the archive \"" + s + "\" but it doesn't exist!");
System.out.println("Firestar is extracting " + s);
consoleDisplay.append("Firestar is extracting " + s + "\n");
//Process p = Runtime.getRuntime().exec(new String[]{"bash","-c","aplay /home/bonkyboo/kittens_loop.wav"}); // DEBUG
Process p = Main.exec(new String[]{"../psp2psarc.exe", "extract", "-y", "../"+s}, System.getProperty("user.home") + "/.firestar/temp/");
Process p;
if (s.equals(oArcTarget)) p = Main.exec(new String[]{Main.inpath + "psp2psarc.exe", "extract", "-y", "../"+s}, System.getProperty("user.home") + "/.firestar/temp/");
else {
new File(System.getProperty("user.home") + "/.firestar/temparcs/" + s + "/").mkdirs();
p = Main.exec(new String[]{Main.inpath + "psp2psarc.exe", "extract", "-y", "../../"+s}, System.getProperty("user.home") + "/.firestar/temparcs/" + s + "/");
}
final Thread ioThread = new Thread() {
@Override
public void run() {
@@ -159,13 +180,37 @@ public class Gonzo {
// overwrite assets with custom ones from each mod and/or perform operations as specified in mod's delete list
// todo: implement RegEx functions after delete.txt
for (Main.Mod m : Main.Mods) {
for (Main.Mod m : modsFlipped) {
if (m.enabled) {
try {
System.out.println("Firestar is extracting " + m.friendlyName + " by " + m.author);
consoleDisplay.append("Firestar is extracting " + m.friendlyName + " by " + m.author + "\n");
new ZipFile(System.getProperty("user.home") + "/.firestar/mods/" + m.path).extractAll(System.getProperty("user.home") + "/.firestar/temp/");
if (!m.requires.isEmpty() && !m.extracts.isEmpty()) {
for (String r : m.requires) {
for (String e : m.extracts) {
File f = new File(Main.inpath + "temparcs/" + r + "/" + e);
File f2 = new File(Main.inpath + "temp/" + e);
if (f2.exists()) {
System.out.println("File \"" + e + "\" already exists in master PSARC. Ignoring.");
consoleDisplay.append("File \"" + e + "\" already exists in master PSARC. Ignoring." + "\n");
}
else if (f.exists()) {
Path src = Paths.get(Main.inpath + "temparcs/" + r + "/" + e);
Path dest = Paths.get(Main.inpath + "temp/" + e);
System.out.println("Copying extra file " + e + " from " + r);
consoleDisplay.append("Copying extra file " + e + " from " + r + "\n");
new File(dest.getParent().toString()).mkdirs();
Files.copy(src, dest, StandardCopyOption.COPY_ATTRIBUTES);
} else throw new IOException("A mod requested access to the file \"" + e + "\" from archive " + r + " but it wasn't there!");
}
}
} else if (!m.extracts.isEmpty()) {
System.out.println("WARNING: " + m.friendlyName + " by " + m.author + "tried to extract individual files without specifying a source PSARC in requires[]. Ignoring.");
consoleDisplay.append("WARNING: " + m.friendlyName + " by " + m.author + "tried to extract individual files without specifying a source PSARC in requires[]. Ignoring." + "\n");
}
File fscript = new File(Main.inpath + "temp/fscript");
if (fscript.exists()) {
System.out.println("Firestar is applying patches from " + m.friendlyName + " by " + m.author);
@@ -209,7 +254,9 @@ public class Gonzo {
} catch (Exception e) {
System.out.println(e.getMessage());
consoleDisplay.append("CRITICAL FAILURE: " + e.getMessage());
JOptionPane.showMessageDialog(this.frame, "CRITICAL FAILURE: " + e.getMessage(), "Fatal Error", JOptionPane.ERROR_MESSAGE);
if (e instanceof FirescriptFormatException) {JOptionPane.showMessageDialog(this.frame, "CRITICAL FAILURE: " + e.getMessage() + "\nOne of your mods has a broken FSCRIPT. It cannot be installed.", "Fatal Error", JOptionPane.ERROR_MESSAGE);} else {
JOptionPane.showMessageDialog(this.frame, "CRITICAL FAILURE: " + e.getMessage(), "Fatal Error", JOptionPane.ERROR_MESSAGE);
}
frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
AllowExit();
return;
@@ -223,7 +270,7 @@ public class Gonzo {
} catch (IOException | FirescriptFormatException e) {
System.out.println(e.getMessage());
consoleDisplay.append("CRITICAL FAILURE: " + e.getMessage());
JOptionPane.showMessageDialog(this.frame, "CRITICAL FAILURE: " + e.getMessage(), "Fatal Error", JOptionPane.ERROR_MESSAGE);
JOptionPane.showMessageDialog(this.frame, "CRITICAL FAILURE: Internal FSCRIPT Error. " + e.getMessage() + "\nThis may indicate that Firestar has been corrupted and needs reinstalling.", "Fatal Error", JOptionPane.ERROR_MESSAGE);
frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
AllowExit();
return;
@@ -267,7 +314,7 @@ public class Gonzo {
try {
System.out.println("Firestar is compiling the final build");
consoleDisplay.append("Firestar is compiling the final build" + "\n");
Process p = Main.exec(new String[]{"../psp2psarc.exe", "create", "--skip-missing-files", "-j12", "-a", "-i", "-y", "--input-file=list.txt", "-o" + oArcTarget}, System.getProperty("user.home") + "/.firestar/temp/");
Process p = Main.exec(new String[]{Main.inpath + "psp2psarc.exe", "create", "--skip-missing-files", "-j12", "-a", "-i", "-y", "--input-file=list.txt", "-o" + oArcTarget}, System.getProperty("user.home") + "/.firestar/temp/");
final Thread ioThread = new Thread() {
@Override
public void run() {
@@ -316,7 +363,9 @@ public class Gonzo {
}
try {
File tmp = new File(System.getProperty("user.home") + "/.firestar/temp/");
File tmp2 = new File(System.getProperty("user.home") + "/.firestar/temparcs/");
Main.deleteDir(tmp);
Main.deleteDir(tmp2);
} catch (Exception e) {
System.out.println("WARNING: Temporary files may not have been properly cleared.\n" + e.getMessage());
consoleDisplay.append("WARNING: Temporary files may not have been properly cleared.\n" + e.getMessage());
@@ -349,6 +398,7 @@ public class Gonzo {
@Override
public void windowClosing(WindowEvent e)
{
Main.deleteDir(new File(System.getProperty("user.home") + "/.firestar/temp/"));
invoker.wrapUpDeployment();
e.getWindow().dispose();
}

View File

@@ -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;
}
}
}

View File

@@ -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) {

View File

@@ -47,15 +47,13 @@ import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.OutputKeys;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.*;
import org.xml.sax.SAXException;
import org.apache.commons.text.StringEscapeUtils;
public class Rizzo {
private final DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
private Scanner scanner;
private final int maxVer = 1;
private int ver = 1;
@@ -77,9 +75,9 @@ public class Rizzo {
}
private boolean parseArgs(String[] args, Object context) throws FirescriptFormatException {
System.out.println("Parsing Command: " + Arrays.toString(args));
if (args.length > 0) {
if (context == null) {
System.out.println("Parsing Command: " + Arrays.toString(args));
if (args[0].equalsIgnoreCase("fscript")) {
ver = Integer.parseInt(args[1]); // We'll do shit with this later
if (ver > maxVer) throw new FirescriptFormatException(args[0], "script too new");
@@ -87,9 +85,9 @@ public class Rizzo {
File newCtx = new File(workingDir + args[1]);
System.out.println("Calling new parse: " + Arrays.toString(Arrays.copyOfRange(args, 2, args.length)));
parseArgs(Arrays.copyOfRange(args, 2, args.length), newCtx);
} else throw new FirescriptFormatException("fscript", "unknown command '" + args[0] + "'");
} else throw new FirescriptFormatException("fscript", "command '" + args[0] + "' is unknown or used in inappropriate context");
} else {
System.out.println("Using context: " + context.getClass().getName() + "@" + context.hashCode());
System.out.println("Parsing Command: " + Arrays.toString(args) + " using context: " + context.getClass().getName() + "@" + context.hashCode());
if (args[0].equals("{")) {
System.out.println("New context block: " + context.getClass().getName() + "@" + context.hashCode());
parseScript(context);
@@ -106,7 +104,6 @@ public class Rizzo {
}
} else if (args[0].equalsIgnoreCase("xml")) {
try {
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
// Mmmm, love me some INVALID XML corrections.
ReplacingInputStream ris = new ReplacingInputStream(new ReplacingInputStream(new ReplacingInputStream(new FileInputStream(file), "\r\n", ""), "&", "&amp;"), "\n", "&#10;");
@@ -123,15 +120,7 @@ public class Rizzo {
transformer.setOutputProperty(OutputKeys.METHOD, "html");
transformer.transform(source, result);
// Look ma, I'm breaking XML standards!
String xmlString = result.getWriter().toString()
.replace("&amp;", "&")
.replace("&lt;", "<")
.replace("&gt;", ">")
.replace("&#9;", "\t")
.replace("&#8;", "\b")
.replace("&#10;", "\n")
.replace("&#13;", "\r")
.replace("&#12;", "\f");
String xmlString = StringEscapeUtils.unescapeHtml4(result.getWriter().toString());
try (PrintStream ps = new PrintStream(output)) {
ps.print(xmlString);
}
@@ -139,7 +128,7 @@ public class Rizzo {
Logger.getLogger(Rizzo.class.getName()).log(Level.SEVERE, null, ex);
}
} catch (SAXException | IOException | ParserConfigurationException ex) {
Logger.getLogger(Rizzo.class.getName()).log(Level.SEVERE, null, ex);
Logger.getLogger(Rizzo.class.getName()).log(Level.SEVERE, "This usually means there's non-standard formatting from the game developer which your FSCRIPT does not account for.", ex);
}
} else if (args[0].equalsIgnoreCase("str") || args[0].equalsIgnoreCase("xstr")) {
try {
@@ -206,49 +195,62 @@ public class Rizzo {
} catch (FirescriptFormatException | PatchFailedException | IOException ex) {
Logger.getLogger(Rizzo.class.getName()).log(Level.SEVERE, null, ex);
}
} else throw new FirescriptFormatException("file", "unknown command '" + args[0] + "'");
} else throw new FirescriptFormatException("file", "command '" + args[0] + "' is unknown or used in inappropriate context");
} else if (args[0].equalsIgnoreCase("xml")) {
System.out.println("fscript: XML called but file does not exist. Using placebo...");
try {
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
parseArgs(Arrays.copyOfRange(args, 1, args.length), docBuilder.newDocument());
} catch (ParserConfigurationException ex1) {
Logger.getLogger(Rizzo.class.getName()).log(Level.SEVERE, null, ex1);
throw new FirescriptFormatException("xml", "critical document failure");
}
} else System.out.println("fscript: file context not found, skipping.");
} else if (context instanceof Document document) {
if (args[0].equalsIgnoreCase("modify")) {
Element elem = (Element)traverse(document, args[1]);
parseArgs(Arrays.copyOfRange(args, 2, args.length), elem);
} else if (args[0].equalsIgnoreCase("create")) {
String newTag = args[1].substring(args[1].lastIndexOf(".")+1);
String newID = "";
if (newTag.contains("#")) {
newID = newTag.substring(newTag.indexOf("#")+1);
newTag = newTag.substring(0, newTag.indexOf("#"));
}
Element newElem = document.createElement(newTag);
if (newID != null && newID.length() > 0) newElem.setAttribute("id", newID);
traverse(document, args[1].substring(0, args[1].lastIndexOf("."))).appendChild(newElem);
parseArgs(Arrays.copyOfRange(args, 2, args.length), newElem);
} else if (args[0].equalsIgnoreCase("delete")) {
Element elem = (Element)traverse(document, args[1]);
elem.getParentNode().removeChild(elem);
} else if (args[0].equalsIgnoreCase("merge")) {
// We're basically copying the file context xml command but with another xml document.
try {
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
ReplacingInputStream ris = new ReplacingInputStream(new ReplacingInputStream(new ReplacingInputStream(new FileInputStream(new File(workingDir + args[1])), "\r\n", ""), "&", "&amp;"), "\n", "&#10;");
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", ""), "&", "&amp;"), "\n", "&#10;");
Document outDoc = docBuilder.parse(ris); // throw new FirescriptFormatException("xml", "javax.xml.parsers self-destructed with error:\n" + e.getMessage() + "\nThis usually means you used a bad FSCRIPT, or there was non-standard formatting from the game developer.");
NodeList cn = outDoc.getDocumentElement().getChildNodes();
for (int x = 0; x < cn.getLength(); x++) {
Node importedNode = document.importNode(cn.item(x), true);
document.getDocumentElement().appendChild(importedNode);
NamedNodeMap nnm = outDoc.getDocumentElement().getAttributes();
for (int x = 0; x < nnm.getLength(); x++) {
Attr importedNode = (Attr) document.importNode(nnm.item(x), true);
document.getDocumentElement().setAttributeNodeNS(importedNode);
}
NodeList cn = outDoc.getDocumentElement().getChildNodes();
for (int x = 0; x < cn.getLength(); x++) {
Node importedNode = document.importNode(cn.item(x), true);
document.getDocumentElement().appendChild(importedNode);
}
} catch (SAXException | IOException | ParserConfigurationException ex) {
Logger.getLogger(Rizzo.class.getName()).log(Level.SEVERE, "This usually means there's non-standard formatting from the game developer which your FSCRIPT does not account for.", ex);
}
} catch (SAXException | IOException | ParserConfigurationException ex) {
Logger.getLogger(Rizzo.class.getName()).log(Level.SEVERE, null, ex);
}
} else throw new FirescriptFormatException("xml", "unknown command '" + args[0] + "'");
} else throw new FirescriptFormatException("xml", "command '" + args[0] + "' is unknown or used in inappropriate context");
} else {
System.out.println("fscript: XML document has no child nodes. Skipping...");
parseArgs(Arrays.copyOfRange(args, 1, args.length), document);
}
} else if (context instanceof Element element) {
if (args[0].equalsIgnoreCase("set")) {
if (args[1].equalsIgnoreCase("attribute"))
@@ -347,6 +349,7 @@ public class Rizzo {
ns = ((Element)parent).getChildNodes();
for (int i = 0; i < ns.getLength(); i++) {
Node n = ns.item(i);
if (n instanceof Comment) continue;
if (n.getNodeName().equals("#text")) continue;
if (((Element)n).getAttribute("name").equals(name)) {
newParent = (Element)n;

View File

@@ -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

View File

@@ -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) {

View File

@@ -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"/>

View File

@@ -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);
}
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 823 B

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 851 B

After

Width:  |  Height:  |  Size: 5.0 KiB

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 362 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 326 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 319 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 362 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 299 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 374 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 294 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 293 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 238 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 429 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 318 KiB

File diff suppressed because it is too large Load Diff

View File

@@ -1 +1 @@
netbeans.hint.jdkPlatform=JDK_22__System_
netbeans.hint.jdkPlatform=JDK_17__System_

View File

@@ -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

Binary file not shown.

After

Width:  |  Height:  |  Size: 189 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 180 KiB