Skip to content

Commit 94ce4ff

Browse files
committed
0.1.0 - initial commit
0 parents  commit 94ce4ff

File tree

5 files changed

+268
-0
lines changed

5 files changed

+268
-0
lines changed

.gitignore

Whitespace-only changes.

README.md

+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# rpgsave-decode
2+
3+
A tool to decode RPG Maker MV save files.
4+
5+
`.rpgsave` files are json files compressed with [lz-string](https://pieroxy.net/blog/pages/lz-string/index.html) to base64.
6+
7+
## Usage
8+
9+
Drag and drop a `.rpgsave` file onto `rpgsave-decode.exe` or run the following command:
10+
11+
```
12+
rpgsave-decode <input>
13+
```
14+
15+
> `rpgsave-decode` will automatically output to a `.json` file of the same name. **(indented for readability)**
16+
17+
Releases can be found [here](https://github.com/gteditor99/rpgsave-decrpyt/releases).
18+
19+
## Building
20+
21+
`rpgsave-decode` is a `golang` project. To build it, you will need to have `golang` installed.
22+
23+
Clone the repository:
24+
25+
```bash
26+
git clone https://github.com/gteditor99/rpgsave-decrpyt.git
27+
```
28+
29+
Build the project:
30+
31+
```bash
32+
go build
33+
```
34+
35+
## Misc
36+
37+
`rpgsave-decode` depends on [@daku10/go-lz-string](https://github.com/daku10/go-lz-string) for decompression.
38+
39+
## License
40+
41+
`rpgsave-decode` is licensed under the `MIT` license. See `LICENSE` for more information.

go.mod

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
module rpgsave-decrypt
2+
3+
go 1.21.0
4+
5+
require (
6+
github.com/charmbracelet/log v0.3.1
7+
github.com/daku10/go-lz-string v0.0.5
8+
)
9+
10+
require (
11+
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
12+
github.com/charmbracelet/lipgloss v0.9.1 // indirect
13+
github.com/go-logfmt/logfmt v0.6.0 // indirect
14+
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
15+
github.com/mattn/go-isatty v0.0.18 // indirect
16+
github.com/mattn/go-runewidth v0.0.15 // indirect
17+
github.com/muesli/reflow v0.3.0 // indirect
18+
github.com/muesli/termenv v0.15.2 // indirect
19+
github.com/rivo/uniseg v0.2.0 // indirect
20+
golang.org/x/exp v0.0.0-20231006140011-7918f672742d // indirect
21+
golang.org/x/sys v0.13.0 // indirect
22+
)

go.sum

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k=
2+
github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8=
3+
github.com/charmbracelet/lipgloss v0.9.1 h1:PNyd3jvaJbg4jRHKWXnCj1akQm4rh8dbEzN1p/u1KWg=
4+
github.com/charmbracelet/lipgloss v0.9.1/go.mod h1:1mPmG4cxScwUQALAAnacHaigiiHB9Pmr+v1VEawJl6I=
5+
github.com/charmbracelet/log v0.3.1 h1:TjuY4OBNbxmHWSwO3tosgqs5I3biyY8sQPny/eCMTYw=
6+
github.com/charmbracelet/log v0.3.1/go.mod h1:OR4E1hutLsax3ZKpXbgUqPtTjQfrh1pG3zwHGWuuq8g=
7+
github.com/daku10/go-lz-string v0.0.5 h1:YlSBoUZVgJyBHBXnzc36K7F1uXk/hdfhYsCSbM/bgmg=
8+
github.com/daku10/go-lz-string v0.0.5/go.mod h1:owrAu1j2+lHjvp+ztCttIsK07WxD9l7fpKdVrm4k9Jg=
9+
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
10+
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
11+
github.com/go-logfmt/logfmt v0.6.0 h1:wGYYu3uicYdqXVgoYbvnkrPVXkuLM1p1ifugDMEdRi4=
12+
github.com/go-logfmt/logfmt v0.6.0/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs=
13+
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
14+
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
15+
github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY=
16+
github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
17+
github.com/mattn/go-isatty v0.0.18 h1:DOKFKCQ7FNG2L1rbrmstDN4QVRdS89Nkh85u68Uwp98=
18+
github.com/mattn/go-isatty v0.0.18/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
19+
github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk=
20+
github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U=
21+
github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
22+
github.com/muesli/reflow v0.3.0 h1:IFsN6K9NfGtjeggFP+68I4chLZV2yIKsXJFNZ+eWh6s=
23+
github.com/muesli/reflow v0.3.0/go.mod h1:pbwTDkVPibjO2kyvBQRBxTWEEGDGq0FlB1BIKtnHY/8=
24+
github.com/muesli/termenv v0.15.2 h1:GohcuySI0QmI3wN8Ok9PtKGkgkFIk7y6Vpb5PvrY+Wo=
25+
github.com/muesli/termenv v0.15.2/go.mod h1:Epx+iuz8sNs7mNKhxzH4fWXGNpZwUaJKRS1noLXviQ8=
26+
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
27+
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
28+
github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
29+
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
30+
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
31+
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
32+
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
33+
golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI=
34+
golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo=
35+
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
36+
golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
37+
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
38+
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
39+
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

main.go

+166
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
package main
2+
3+
/* rpgsave-decrypt
4+
cli tool to decompress RPG Maker MV save files.
5+
6+
`.rpgsave` files are compressed using lz-string, then encoded in base64.
7+
@daku10's go-lz-string library is used to decompress the save file.
8+
9+
usage:
10+
either:
11+
1. drag and drop the save file onto the executable
12+
2. rpgsave-decode.exe <save file path>
13+
*/
14+
15+
import (
16+
"bufio"
17+
"bytes"
18+
"encoding/json"
19+
"fmt"
20+
"os"
21+
"strconv"
22+
"strings"
23+
24+
"github.com/charmbracelet/log"
25+
lzstring "github.com/daku10/go-lz-string" // migrated from @pieroxy/lz-string-go upon issues with decoding (issues with int -> string conversion?)
26+
)
27+
28+
func main() {
29+
logger := log.NewWithOptions(os.Stderr, log.Options{
30+
ReportCaller: true,
31+
ReportTimestamp: true,
32+
})
33+
// set log level
34+
logger.SetLevel(log.DebugLevel)
35+
logger.Info("starting rpgsave-decode")
36+
// get file path from command line args
37+
args := os.Args[1:]
38+
if len(args) == 0 {
39+
logger.Error("no file path provided")
40+
logger.Info("press enter to exit")
41+
bufio.NewReader(os.Stdin).ReadBytes('\n')
42+
os.Exit(1)
43+
}
44+
filePath := args[0]
45+
logger.Print("file path: " + filePath)
46+
// open file
47+
file, err := os.Open(filePath)
48+
if err != nil {
49+
logger.Error("error opening file")
50+
logger.Error(err)
51+
logger.Info("press enter to exit")
52+
bufio.NewReader(os.Stdin).ReadBytes('\n')
53+
os.Exit(1)
54+
}
55+
// read file
56+
fileInfo, err := file.Stat()
57+
if err != nil {
58+
logger.Error("error reading file")
59+
logger.Error(err)
60+
logger.Info("press enter to exit")
61+
bufio.NewReader(os.Stdin).ReadBytes('\n')
62+
os.Exit(1)
63+
}
64+
fileSize := fileInfo.Size()
65+
logger.Print("file size: " + fmt.Sprint(fileSize))
66+
fileBytes := make([]byte, fileSize)
67+
_, err = file.Read(fileBytes)
68+
if err != nil {
69+
logger.Error("error reading file")
70+
logger.Error(err)
71+
logger.Info("press enter to exit")
72+
bufio.NewReader(os.Stdin).ReadBytes('\n')
73+
os.Exit(1)
74+
}
75+
// // decode base64
76+
// log.Info("decoding base64")
77+
// decodedBytes, err := base64.StdEncoding.DecodeString(string(fileBytes))
78+
// if err != nil {
79+
// log.Error("error decoding base64")
80+
// log.Error(err)
81+
// os.Exit(1)
82+
// }
83+
// deprecated, lzstring.DecompressFromBase64 does this automatically
84+
85+
86+
// decompress
87+
logger.Info("decompressing")
88+
decompressedBytes, err := lzstring.DecompressFromBase64(string(fileBytes))
89+
// write to file
90+
logger.Info("writing to file")
91+
fileName := strings.Split(filePath, ".")[0]
92+
fileName += ".json"
93+
logger.Print("file name: " + fileName)
94+
if _, err := os.Stat(fileName); err == nil {
95+
logger.Warn("file", fileName, " exits, overwrite? (y/n)")
96+
overwrite, _ := bufio.NewReader(os.Stdin).ReadString('\n')
97+
overwrite = strings.TrimSpace(overwrite)
98+
if overwrite == "y" {
99+
logger.Info("trunicating file", fileName)
100+
err := os.Remove(fileName)
101+
if err != nil {
102+
logger.Error("error deleting file")
103+
logger.Error(err)
104+
logger.Info("press enter to exit")
105+
bufio.NewReader(os.Stdin).ReadBytes('\n')
106+
os.Exit(1)
107+
}
108+
109+
110+
} else {
111+
logger.Info("not overwriting")
112+
logger.Info("press enter to exit")
113+
bufio.NewReader(os.Stdin).ReadBytes('\n')
114+
os.Exit(0)
115+
}
116+
}
117+
118+
// pretty print json
119+
logger.Info("pretty printing json")
120+
var jsonData []byte
121+
// json Indent
122+
jsonData, err = json.MarshalIndent(decompressedBytes, "", " ")
123+
if err != nil {
124+
logger.Error("error marshaling JSON")
125+
logger.Error(err)
126+
logger.Info("press enter to exit")
127+
bufio.NewReader(os.Stdin).ReadBytes('\n')
128+
os.Exit(1)
129+
}
130+
// unquote
131+
jsonDataStr, err := strconv.Unquote(string(jsonData))
132+
if err != nil {
133+
logger.Error("error unquoting JSON")
134+
logger.Error(err)
135+
logger.Info("press enter to exit")
136+
bufio.NewReader(os.Stdin).ReadBytes('\n')
137+
os.Exit(1)
138+
}
139+
jsonData = []byte(jsonDataStr)
140+
141+
// Indent
142+
var indentedData bytes.Buffer
143+
err = json.Indent(&indentedData, jsonData, "", " ")
144+
if err != nil {
145+
logger.Error("error marshaling JSON")
146+
logger.Error(err)
147+
logger.Info("press enter to exit")
148+
bufio.NewReader(os.Stdin).ReadBytes('\n')
149+
os.Exit(1)
150+
}
151+
jsonData = indentedData.Bytes()
152+
153+
// write to file
154+
err = os.WriteFile(fileName, jsonData, 0644)
155+
if err != nil {
156+
logger.Error("error writing to file")
157+
logger.Error(err)
158+
logger.Info("press enter to exit")
159+
bufio.NewReader(os.Stdin).ReadBytes('\n')
160+
os.Exit(1)
161+
}
162+
logger.Info("done!")
163+
logger.Info("press enter to exit")
164+
bufio.NewReader(os.Stdin).ReadBytes('\n')
165+
166+
}

0 commit comments

Comments
 (0)