Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
23 changes: 12 additions & 11 deletions .github/workflows/release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ on:
push:
tags: [ "*.*.*" ]


jobs:
windows:
if: startsWith(github.ref, 'refs/tags/')
Expand All @@ -17,6 +16,14 @@ jobs:
steps:
- uses: actions/checkout@v4

- name: verify tag is on main
run: |
git fetch origin main --quiet
if ! git merge-base --is-ancestor "${{ github.sha }}" origin/main; then
echo "'${{ github.ref_name }}' does not point to a commit on main. releases may only be cut from main."
exit 1
fi

- name: get current project version
run: |
# Not working
Expand All @@ -26,24 +33,18 @@ jobs:
#
# This is disgusting - need to assume nothing else in Cargo.toml has
# "version = x.x.x" from start of line
$project_version = cat .\cascade_app\Cargo.toml | grep -oE '^version = \"?[0-9]+\.[0-9]+\.[0-9]+\"' | grep -oE "[0-9]+\.[0-9]+\.[0-9]+"
$project_version = cat .\crates\cascade-app\Cargo.toml | grep -oE '^version = \"?[0-9]+\.[0-9]+\.[0-9]+\"' | grep -oE "[0-9]+\.[0-9]+\.[0-9]+"
"project_version=$project_version" | Out-File -FilePath $env:GITHUB_ENV -Append

- name: install nightly rust toolchain
uses: dtolnay/rust-toolchain@stable
with:
toolchain: nightly

- name: install required rustup components
run: |
rustup component add rustfmt --toolchain nightly
rustup target add x86_64-pc-windows-gnu
rustup target add x86_64-pc-windows-msvc

- name: cargo build
run: cargo build --target x86_64-pc-windows-gnu --release
run: cargo build --target x86_64-pc-windows-msvc --release

- name: create release
uses: softprops/action-gh-release@v1
with:
generate_release_notes: true
files: ./target/x86_64-pc-windows-gnu/release/cascade.exe
files: ./target/x86_64-pc-windows-msvc/release/cascade.exe
68 changes: 60 additions & 8 deletions .justfile
Original file line number Diff line number Diff line change
@@ -1,13 +1,65 @@
default: check test fmt

check:
cargo check
[group: "check"]
default: check

test:
cargo test --all -- --nocapture
[group: "check"]
check: check-code check-fmt check-lint check-udeps check-tests

fmt:
cargo fmt --all -- --check
[group: "check"]
check-code:
cargo check --workspace

[group: "check"]
check-tests:
cargo test --workspace

[group: "check"]
check-fmt:
cargo +nightly fmt --all -- --check

[group: "check"]
check-udeps:
cargo +nightly udeps --workspace --locked

[group: "check"]
check-lint:
cargo clippy

[group: "fix"]
fix: fix-fmt fix-lint

[group: "fix"]
fix-code:
cargo fix --workspace

[group: "fix"]
fix-fmt:
cargo +nightly fmt

[group: "fix"]
fix-lint:
cargo clippy --fix --allow-dirty

windows_target := "x86_64-pc-windows-msvc"


[group: "build"]
build:
cargo build --release --package cascade-app

[group: "build"]
[unix]
build-windows:
cargo build --target x86_64-pc-windows-gnu --release
cross build --release --target {{windows_target}} --package cascade-app

[group: "build"]
[windows]
build-windows: build

[group: "run"]
run:
cargo run --package cascade-app

[group: "run"]
run-cli:
cargo run --package cascade-cli
25 changes: 19 additions & 6 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,34 +2,47 @@
members = ["crates/*"]
resolver = "2"

[workspace.package]
edition = "2024"
rust-version = "1.88"
repository = "https://github.com/1borgy/cascade"
license = "MIT"

[workspace.dependencies]
cascade-backend = { path = "crates/cascade-backend" }
cascade-core = { path = "crates/cascade-core" }
cascade-crc = { path = "crates/cascade-crc" }
cascade-dump = { path = "crates/cascade-dump" }
cascade-lut = { path = "crates/cascade-lut" }
cascade-qb = { path = "crates/cascade-qb" }
cascade-save = { path = "crates/cascade-save" }
cascade-thugpro = { path = "crates/cascade-thugpro" }
cascade-test = { path = "crates/cascade-test" }
cascade-thaw = { path = "crates/cascade-thaw" }
cascade-thps3 = { path = "crates/cascade-thps3" }
cascade-thps4 = { path = "crates/cascade-thps4" }
cascade-thug = { path = "crates/cascade-thug" }
cascade-thug2 = { path = "crates/cascade-thug2" }
cascade-wad = { path = "crates/cascade-wad" }

anyhow = "1.0"
byteorder = "1.4.3"
clap = { version = "4.5.16", features = ["derive"] }
color-eyre = "0.6"
count-write = "0.1.0"
crc = "3.0.1"
directories = "5.0.1"
encoding_rs = "0.8.35"
enum-iterator = "1.4.1"
env_logger = "0.11.6"
fern = { version = "0.6.2", features = ["colored"] }
filetime = "0.2.21"
hex-literal = "0.4.1"
image = "0.24.0"
indexmap = "2.7.0"
image = "0.25.0"
indexmap = { version = "2.7.0", features = ["serde"] }
log = "0.4.20"
rand = "0.9.1"
rfd = "0.12.1"
ron = "0.8.1"
serde = { version = "1.0.190", features = ["rc", "derive"] }
serde_json = "1.0.140"
suppaftp = "^6"
thiserror = "1.0.50"
time = { version = "0.3.30", features = ["local-offset", "formatting"] }
tokio = { version = "1.40.0", features = ["fs", "io-util"] }
Expand Down
2 changes: 2 additions & 0 deletions Cross.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[target.x86_64-pc-windows-msvc]
image = "ghcr.io/cross-rs/x86_64-pc-windows-msvc-cross:local"
51 changes: 14 additions & 37 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<div align="center">
<img src=".github/assets/banner.gif" width=65%>
<div>
<em>A bulk save modifier for THUG Pro.</em>
<em>A bulk save modifier for THPS3-THAW.</em>
</div>
</div>

Expand All @@ -21,51 +21,40 @@

## `⏬ installation`<a id="installation"></a>

Download `cascade.exe` from [here](https://github.com/1borgy/cascade/releases/latest).
Download and run `cascade.exe` from the [latest GitHub release](https://github.com/1borgy/cascade/releases/latest).

## `⚡️ usage`<a id="usage"></a>

> [!WARNING]
> I highly recommend making a manual backup of your saves! Though `cascade` has been rigorously
> tested against community CAS packs, the possibility of save corruption still exists.
> [!TIP]
> Use `ctrl+-` and `ctrl+=` to resize the UI.

Upon opening Cascade, you will be greeted with three columns.
Cascade's UI contains three columns: "from", "to", and "queue".

### `from`

The "from" column allows you to select the save to copy from. You may choose to copy trickset,
scales, or both.
The "from" column allows you to select the save to copy from, which components to copy (scales, trickset), and which game to target.

### `to`

The "to" column allows you to select which saves to copy to.

Cascade will automatically detect your save folder at `%localappdata%/THUG Pro/Save`.
If you have it installed elsewhere, or want to copy saves to a different folder, you will need to
select the desired folder manually.
Cascade will automatically detect THUG Pro saves at `%localappdata%/THUG Pro/Save`. For other games
or install locations, you may need to select the desired folder manually.

### `queue`

The "queue" column shows which save files are currently queued to be modified, as well as their
most recent modification status. Upon pressing the start (▶️) button, all saves in the queue will
The "queue" column shows which save files will be modified, as well as their most recent
modification status. Upon pressing the start (▶️) button, all saves in the queue will
be backed up then modified in-place.

If modification of a save is successful, it will turn green. If modification of a save results in
an error, it will turn red. If you encounter an error while modifying saves, please
an error, it will turn red. If you encounter an error while modifying saves, please
[contact me](#contact).

> [!TIP]
> Use `ctrl+-` and `ctrl+=` to resize the UI.

> [!TIP]
> Create an empty file named `cascade.toml` in the same directory as the executable to use a
> portable install. Otherwise, cascade will store files at `%localappdata%/cascade`.

## `💾 backups`<a id="backups"></a>

If you want to revert a cascade run, backups are stored at `%localappdata%/cascade/backup`.
Simply pick which backup you want to use and drag its contents into your saves folder.
Each entry in this folder is labeled with the date and time of modification.
Every time CAS files are modified, Cascade stores datetime-labeled backups at `%localappdata%/cascade/backup`.
To restore a backup, drag its contents into your saves folder.

## `📣 contact`<a id="contact"></a>

Expand Down Expand Up @@ -115,12 +104,7 @@ Cascade would not exist without the following people, so shoutout to them:

# `🛠️ development`<a id="development"></a>

Building cascade requires nightly rust.

```bash
rustup toolchain install nightly
rustup override set nightly
```
**TODO**

To cross-compile for windows:

Expand All @@ -138,10 +122,3 @@ To run the UI:

```bash
cargo run -p cascade-app
```

To create random CASes:

```bash
cargo run -p cascade-cli randomize-bulk --input-dir .local/saves --output-dir .local/rand --female -n 10
```
1 change: 1 addition & 0 deletions assets/lut/compress-thaw.ron
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
(compress8:["skater_m_lower_legs","skater_m_head","skater_m_torso","skater_m_legs","skater_m_hair","skater_m_backpack","skater_m_jaw","kneepads","socks","elbowpads","skater_f_head","skater_f_torso","skater_f_legs","skater_f_hair","skater_f_backpack","skater_m_lower_legs","skater_m_hat_hair","part","skater_m_hands","chest_tattoo","back_tattoo","left_forearm_tattoo","right_forearm_tattoo","left_bicep_tattoo","left_leg_tattoo","right_leg_tattoo","use_default_scale","right_bicep_tattoo","Skin","value","desc_id","h","s","v","use_default_hsv","skater_f_lower_legs","skater_f_hat_hair","Scale","skater_f_hands","display_name","stance","pushstyle","profile","name","trickstyle","age","is_pro","hometown","is_locked","is_head_locked","points_available","Air","run","ollie","Speed","spin","Switch","rail_balance","lip_balance","manual_balance","sponsors","trick_mapping","default_trick_mapping","max_specials","specials","Air_CircleD","Air_CircleDL","Air_CircleDR","Air_CircleL","Air_CircleR","Air_CircleU","Air_CircleUL","Air_CircleUR","Air_D_D_Circle","Air_D_D_Square","Air_L_L_Circle","Air_L_L_Square","Air_R_R_Circle","Air_R_R_Square","Air_SquareD","Air_SquareDL","Air_SquareDR","Air_SquareL","Air_SquareR","Air_SquareU","Air_SquareUL","Air_SquareUR","Air_U_U_Circle","Air_U_U_Square","ExtraSlot1","ExtraSlot2","JumpSlot","Lip_TriangleD","Lip_TriangleDL","Lip_TriangleDL","Lip_TriangleDR","Lip_TriangleDR","Lip_TriangleL","Lip_TriangleR","Lip_TriangleU","Lip_TriangleUL","Lip_TriangleUL","Lip_TriangleUR","Lip_TriangleUR","SpAir_D_L_Circle","SpAir_D_L_Square","SpAir_D_R_Circle","SpAir_D_R_Square","SpAir_D_U_Circle","SpAir_D_U_Square","SpAir_L_D_Circle","SpAir_L_D_Square","SpAir_L_R_Circle","SpAir_L_R_Square","SpAir_L_U_Circle","SpAir_L_U_Square","SpAir_R_D_Circle","SpAir_R_D_Square","SpAir_R_L_Circle","SpAir_R_L_Square","SpAir_R_U_Circle","SpAir_R_U_Square","SpAir_U_D_Circle","SpAir_U_D_Square","SpAir_U_L_Circle","SpAir_U_L_Square","SpAir_U_R_Circle","SpAir_U_R_Square","SpGrind_D_L_Triangle","SpGrind_D_R_Triangle","SpGrind_D_U_Triangle","SpGrind_L_D_Triangle","SpGrind_L_R_Triangle","SpGrind_L_U_Triangle","SpGrind_R_D_Triangle","SpGrind_R_L_Triangle","SpGrind_R_U_Triangle","SpGrind_U_D_Triangle","SpGrind_U_L_Triangle","SpGrind_U_R_Triangle","SpLip_D_L_Triangle","SpLip_D_R_Triangle","SpLip_D_U_Triangle","SpLip_L_D_Triangle","SpLip_L_R_Triangle","SpLip_L_U_Triangle","SpLip_R_D_Triangle","SpLip_R_L_Triangle","SpLip_R_U_Triangle","SpLip_U_D_Triangle","SpLip_U_L_Triangle","SpLip_U_R_Triangle","SpLip_U_U_Triangle","SpMan_D_L_Triangle","SpMan_D_R_Triangle","SpMan_D_U_Triangle","SpMan_L_D_Triangle","SpMan_L_R_Triangle","SpMan_L_U_Triangle","SpMan_R_D_Triangle","SpMan_R_L_Triangle","SpMan_R_U_Triangle","SpMan_U_D_Triangle","SpMan_U_L_Triangle","SpMan_U_R_Triangle","x","y","z","trickslot","trickname","Unassigned","uv_scale","uv_rot","uv_u","uv_v","sleeves","shoes","front_logo","back_logo","glasses","Hat","helmet","Accessories","hat_logo","helmet_logo","board","griptape","deck_graphic","accessory1","accessory2","accessory3","shoe_laces","bare_torso","hasBeaten","head_tattoo","custom","headtop_bone_group","jaw_bone_group","nose_bone_group","head_bone_group","torso_bone_group","stomach_bone_group","upper_arm_bone_group","lower_arm_bone_group","hands_bone_group","upper_left_bone_group","lower_leg_bone_group","feet_bone_group","board_bone_group","object_scaling","regular","goofy","never_mongo","mongo_when_switch","always_mongo","street","vert","first_name","skater_index","default_appearance","is_male","flip_speed","on","Trick","dur","Blend","from","percent","trickType","idletime","start","order","hold","backwards","deg_dir","left_eye","right_eye","nose","lips","width","height","GapName","GapCount","GapScore","SkaterStartPos","SkaterStartDir","level","valid","value","number","initials","win_record",],compress16:[])
1 change: 1 addition & 0 deletions assets/lut/compress-thps3.ron
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
(compress8:["body_type","head","hat","hair","jaw","glasses","torso","legs","kneepads","elbowpads","backpack","shoes","boardup","boarddown","helmet","hat_logo","helmet_logo","front_logo","back_logo","accessories","chest_tattoo","back_tattoo","left_arm_tattoo","right_arm_tattoo","socks","left_leg_tattoo","right_leg_tattoo","special_item","special_item_2","skin","value","desc","h","s","v","use_default_hsv","height_scale","weight_scale","scale","scaling_mode","display_name","stance","pushstyle","profile","name","trickstyle","age","is_pro","hometown","is_locked","is_head_locked","points_available","air","hangtime","ollie","speed","spin","switch","rail_balance","lip_balance","manual_balance","sponsors","trick_mapping","default_trick_mapping","max_specials","specials","Air_CircleD","Air_CircleDL","Air_CircleDR","Air_CircleL","Air_CircleR","Air_CircleU","Air_CircleUL","Air_CircleUR","Air_D_D_Circle","Air_D_D_Square","Air_L_L_Circle","Air_L_L_Square","Air_R_R_Circle","Air_R_R_Square","Air_SquareD","Air_SquareDL","Air_SquareDR","Air_SquareL","Air_SquareR","Air_SquareU","Air_SquareUL","Air_SquareUR","Air_U_U_Circle","Air_U_U_Square","ExtraSlot1","ExtraSlot2","JumpSlot","Lip_TriangleD","Lip_TriangleDL","Lip_TriangleDL","Lip_TriangleDR","Lip_TriangleDR","Lip_TriangleL","Lip_TriangleR","Lip_TriangleU","Lip_TriangleUL","Lip_TriangleUL","Lip_TriangleUR","Lip_TriangleUR","SpAir_D_L_Circle","SpAir_D_L_Square","SpAir_D_R_Circle","SpAir_D_R_Square","SpAir_D_U_Circle","SpAir_D_U_Square","SpAir_L_D_Circle","SpAir_L_D_Square","SpAir_L_R_Circle","SpAir_L_R_Square","SpAir_L_U_Circle","SpAir_L_U_Square","SpAir_R_D_Circle","SpAir_R_D_Square","SpAir_R_L_Circle","SpAir_R_L_Square","SpAir_R_U_Circle","SpAir_R_U_Square","SpAir_U_D_Circle","SpAir_U_D_Square","SpAir_U_L_Circle","SpAir_U_L_Square","SpAir_U_R_Circle","SpAir_U_R_Square","SpGrind_D_L_Triangle","SpGrind_D_R_Triangle","SpGrind_D_U_Triangle","SpGrind_L_D_Triangle","SpGrind_L_R_Triangle","SpGrind_L_U_Triangle","SpGrind_R_D_Triangle","SpGrind_R_L_Triangle","SpGrind_R_U_Triangle","SpGrind_U_D_Triangle","SpGrind_U_L_Triangle","SpGrind_U_R_Triangle","SpLip_D_L_Triangle","SpLip_D_R_Triangle","SpLip_D_U_Triangle","SpLip_L_D_Triangle","SpLip_L_R_Triangle","SpLip_L_U_Triangle","SpLip_R_D_Triangle","SpLip_R_L_Triangle","SpLip_R_U_Triangle","SpLip_U_D_Triangle","SpLip_U_L_Triangle","SpLip_U_R_Triangle","SpLip_U_U_Triangle","SpMan_D_L_Triangle","SpMan_D_R_Triangle","SpMan_D_U_Triangle","SpMan_L_D_Triangle","SpMan_L_R_Triangle","SpMan_L_U_Triangle","SpMan_R_D_Triangle","SpMan_R_L_Triangle","SpMan_R_U_Triangle","SpMan_U_D_Triangle","SpMan_U_L_Triangle","SpMan_U_R_Triangle"],compress16:[])
1 change: 1 addition & 0 deletions assets/lut/compress-thps4.ron
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
(compress8:["body_type","head","hat","hair","jaw","glasses","torso","legs","kneepads","elbowpads","backpack","shoes","boardup","boarddown","helmet","hat_logo","helmet_logo","front_logo","back_logo","accessories","chest_tattoo","back_tattoo","left_arm_tattoo","right_arm_tattoo","socks","left_leg_tattoo","right_leg_tattoo","special_item","special_item_2","skin","value","desc","h","s","v","use_default_hsv","height_scale","weight_scale","scale","scaling_mode","display_name","stance","pushstyle","profile","name","trickstyle","age","is_pro","hometown","is_locked","is_head_locked","points_available","air","hangtime","ollie","speed","spin","switch","rail_balance","lip_balance","manual_balance","sponsors","trick_mapping","default_trick_mapping","max_specials","specials","Air_CircleD","Air_CircleDL","Air_CircleDR","Air_CircleL","Air_CircleR","Air_CircleU","Air_CircleUL","Air_CircleUR","Air_D_D_Circle","Air_D_D_Square","Air_L_L_Circle","Air_L_L_Square","Air_R_R_Circle","Air_R_R_Square","Air_SquareD","Air_SquareDL","Air_SquareDR","Air_SquareL","Air_SquareR","Air_SquareU","Air_SquareUL","Air_SquareUR","Air_U_U_Circle","Air_U_U_Square","ExtraSlot1","ExtraSlot2","JumpSlot","Lip_TriangleD","Lip_TriangleDL","Lip_TriangleDL","Lip_TriangleDR","Lip_TriangleDR","Lip_TriangleL","Lip_TriangleR","Lip_TriangleU","Lip_TriangleUL","Lip_TriangleUL","Lip_TriangleUR","Lip_TriangleUR","SpAir_D_L_Circle","SpAir_D_L_Square","SpAir_D_R_Circle","SpAir_D_R_Square","SpAir_D_U_Circle","SpAir_D_U_Square","SpAir_L_D_Circle","SpAir_L_D_Square","SpAir_L_R_Circle","SpAir_L_R_Square","SpAir_L_U_Circle","SpAir_L_U_Square","SpAir_R_D_Circle","SpAir_R_D_Square","SpAir_R_L_Circle","SpAir_R_L_Square","SpAir_R_U_Circle","SpAir_R_U_Square","SpAir_U_D_Circle","SpAir_U_D_Square","SpAir_U_L_Circle","SpAir_U_L_Square","SpAir_U_R_Circle","SpAir_U_R_Square","SpGrind_D_L_Triangle","SpGrind_D_R_Triangle","SpGrind_D_U_Triangle","SpGrind_L_D_Triangle","SpGrind_L_R_Triangle","SpGrind_L_U_Triangle","SpGrind_R_D_Triangle","SpGrind_R_L_Triangle","SpGrind_R_U_Triangle","SpGrind_U_D_Triangle","SpGrind_U_L_Triangle","SpGrind_U_R_Triangle","SpLip_D_L_Triangle","SpLip_D_R_Triangle","SpLip_D_U_Triangle","SpLip_L_D_Triangle","SpLip_L_R_Triangle","SpLip_L_U_Triangle","SpLip_R_D_Triangle","SpLip_R_L_Triangle","SpLip_R_U_Triangle","SpLip_U_D_Triangle","SpLip_U_L_Triangle","SpLip_U_R_Triangle","SpLip_U_U_Triangle","SpMan_D_L_Triangle","SpMan_D_R_Triangle","SpMan_D_U_Triangle","SpMan_L_D_Triangle","SpMan_L_R_Triangle","SpMan_L_U_Triangle","SpMan_R_D_Triangle","SpMan_R_L_Triangle","SpMan_R_U_Triangle","SpMan_U_D_Triangle","SpMan_U_L_Triangle","SpMan_U_R_Triangle"],compress16:[])
Loading
Loading