Updates to v1.1. Fixes a few bugs and refactors

This commit is contained in:
Kamron Batman
2020-02-24 22:14:27 -08:00
parent e15494dcbf
commit 2513578425
5 changed files with 185 additions and 150 deletions

View File

@@ -1,9 +1,19 @@
#!/usr/bin/env bash
GOOS=windows GOARCH=amd64 go build -o ./build/windows/pcd2wc4.exe
GOOS=darwin GOARCH=amd64 go build -o ./build/darwin/pcd2wc4
GOOS=linux GOARCH=amd64 go build -o ./build/linux/pcd2wc4
rm -rf ./build
GOOS=windows GOARCH=amd64 go build -ldflags="-s -w" -o ./build/windows/pcd2wc4.exe
GOOS=darwin GOARCH=amd64 go build -ldflags="-s -w" -o ./build/darwin/pcd2wc4
GOOS=linux GOARCH=amd64 go build -ldflags="-s -w" -o ./build/linux/pcd2wc4
upx --brute ./build/darwin/pcd2wc4
upx --brute ./build/linux/pcd2wc4
upx --brute ./build/windows/pcd2wc4.exe
cp README.md ./build/darwin
cp README.md ./build/linux
cp README.md ./build/windows
cp README.md ./build/windows
zip -j -9 ./build/pcd2wc4_v1.1_darwin.zip ./build/darwin/*
zip -j -9 ./build/pcd2wc4_v1.1_linux.zip ./build/linux/*
zip -j -9 ./build/pcd2wc4_v1.1_windows.zip ./build/windows/*

View File

@@ -2,17 +2,14 @@ package main
import (
"bufio"
"encoding/binary"
. "github.com/projectpokemon/PCD2WC4/util"
"io"
"log"
"os"
"path/filepath"
"strings"
"regexp"
"sync"
)
const version = "1.0.0"
const version = "1.1.0"
func main() {
log.Printf("PCD to WC4 by Sabresite v%s%s", version, LineBreak)
@@ -30,9 +27,33 @@ func main() {
wait.Add(1)
go func(ch chan string) {
for f := range ch {
log.Printf("Processing file %s%s", f, LineBreak)
processFile(f, ch)
for p := range ch {
log.Printf("Processing %s%s", p, LineBreak)
fi, isDir := GetFileStat(p, regexp.MustCompile("\\.pcd$"), 856)
if isDir {
go func(dir string) {
for file := range GetFiles(dir) {
ch <- file
}
}(p)
continue
}
if fi == nil { continue }
f, err := os.Open(p)
if err != nil {
log.Printf("Error: Unable to open file %s%s", p, LineBreak)
continue
}
saveData := ConvertWondercard(f)
_ = f.Close()
if saveData == nil { return }
SaveWondercard(saveData, p[0:len(p)-4] + ".wc4")
}
// Signal
@@ -50,147 +71,9 @@ func main() {
end()
}
func processFile(p string, ch chan<- string) {
info, err := os.Stat(p)
if os.IsNotExist(err) {
log.Printf("File: %s does not exist%s", p, LineBreak)
return
}
if os.IsPermission(err) {
log.Printf("File: %s cannot be accessed%s", p, LineBreak)
return
}
if !strings.HasSuffix(p, ".pcd") {
log.Printf("File: %s is not a PCD file%s", p, LineBreak)
return
}
if info.Size() != 856 {
log.Printf("File: %s is not the correct size%s", p, LineBreak)
return
}
if info.IsDir() {
getFiles(info.Name(), ch)
return
}
f, err := os.Open(info.Name())
if err != nil {
log.Printf("%v%s", err, LineBreak)
return
}
saveData := convertWondercard(f)
_ = f.Close()
if saveData != nil {
// Save the data
newPath := p[0:len(p)-4] + ".wc4"
newFile, err := os.Create(newPath)
if err != nil {
log.Printf("File: Error opening new file file %s%s", newPath, LineBreak)
return
}
writer := bufio.NewWriter(newFile)
if _, err := writer.Write(saveData); err != nil {
log.Printf("File: Error writing new file %v%s", err, LineBreak)
return
}
if err := writer.Flush(); err != nil {
log.Printf("File: Error flushing new file %v%s", err, LineBreak)
return
}
_ = newFile.Close()
log.Printf("Created %s%s", newPath, LineBreak)
}
}
func convertWondercard(f *os.File) []byte {
r := bufio.NewReader(f)
buf := make([]byte, 856)
_, err := io.ReadFull(r, buf)
if err != nil {
log.Printf("Error reading data for %s%s", f.Name(), LineBreak)
return nil
}
pkmBuf := buf[8:244]
pid := binary.LittleEndian.Uint32(pkmBuf[0:4])
seed := uint32(binary.LittleEndian.Uint16(pkmBuf[6:8]))
shiftValue := ((pid & 0x3E000) >> 0xD) % 24
decryptBuf := make([]byte, 228)
prng := NewPokemonRng(seed)
// Decrypt
for i := 0; i < 228; i += 2 {
if i == 128 { prng = NewPokemonRng(pid) }
v := binary.LittleEndian.Uint16(pkmBuf[i+8:i+10])
binary.LittleEndian.PutUint16(decryptBuf[i:i+2], v ^ prng.Next().H())
}
// Unshuffle the blocks
newBlocks := make([]byte, 228)
for block := 0; block < 4; block++ {
pos := 32 * blockPositions[block][shiftValue]
blockPos := block * 32
nextBlockPos := (block+1) * 32
copy(newBlocks[blockPos:nextBlockPos], decryptBuf[pos:32+pos])
}
// Copy party stuff
copy(newBlocks[128:228], decryptBuf[128:228])
wcBuf := make([]byte, 856)
copy(wcBuf[0:16], buf[0:16])
copy(wcBuf[16:244], newBlocks)
copy(wcBuf[244:], buf[244:])
return wcBuf
}
func getFiles(dir string, ch chan<- string) {
walk := func (path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
f := info.Name()
if strings.HasSuffix(f, ".pcd") {
ch <- f
}
return nil
}
err := filepath.Walk(dir, walk)
if err != nil {
log.Printf("%v%s", err, LineBreak)
}
}
func end() {
log.Print("Press any key to exit...")
reader := bufio.NewReader(os.Stdin)
_, _, _ = reader.ReadRune()
os.Exit(0)
}
var blockPositions = [][]int{
{0, 0, 0, 0, 0, 0, 1, 1, 2, 3, 2, 3, 1, 1, 2, 3, 2, 3, 1, 1, 2, 3, 2, 3},
{1, 1, 2, 3, 2, 3, 0, 0, 0, 0, 0, 0, 2, 3, 1, 1, 3, 2, 2, 3, 1, 1, 3, 2},
{2, 3, 1, 1, 3, 2, 2, 3, 1, 1, 3, 2, 0, 0, 0, 0, 0, 0, 3, 2, 3, 2, 1, 1},
{3, 2, 3, 2, 1, 1, 3, 2, 3, 2, 1, 1, 3, 2, 3, 2, 1, 1, 0, 0, 0, 0, 0, 0},
}

View File

53
util/files.go Normal file
View File

@@ -0,0 +1,53 @@
package util
import (
"log"
"os"
"path/filepath"
"regexp"
)
func GetFiles(dir string) <-chan string {
ch := make(chan string, 1)
go func(d string, fch chan<- string) {
walk := func (path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
fch <- path
return nil
}
_ = filepath.Walk(d, walk)
close(fch)
}(dir, ch)
return ch
}
func GetFileStat(p string, pattern *regexp.Regexp, size int64) (info os.FileInfo, isDir bool) {
info, err := os.Stat(p)
if os.IsNotExist(err) {
log.Printf("File: %s does not exist%s", p, LineBreak)
return
}
if os.IsPermission(err) {
log.Printf("File: %s cannot be accessed%s", p, LineBreak)
return
}
if !pattern.MatchString(p) {
return
}
if size > -1 && info.Size() != size {
return
}
isDir = info.IsDir()
return
}

89
wc.go Normal file
View File

@@ -0,0 +1,89 @@
package main
import (
"bufio"
"encoding/binary"
. "github.com/projectpokemon/PCD2WC4/util"
"io"
"log"
"os"
)
var blockPositions = [][]int{
{0, 0, 0, 0, 0, 0, 1, 1, 2, 3, 2, 3, 1, 1, 2, 3, 2, 3, 1, 1, 2, 3, 2, 3},
{1, 1, 2, 3, 2, 3, 0, 0, 0, 0, 0, 0, 2, 3, 1, 1, 3, 2, 2, 3, 1, 1, 3, 2},
{2, 3, 1, 1, 3, 2, 2, 3, 1, 1, 3, 2, 0, 0, 0, 0, 0, 0, 3, 2, 3, 2, 1, 1},
{3, 2, 3, 2, 1, 1, 3, 2, 3, 2, 1, 1, 3, 2, 3, 2, 1, 1, 0, 0, 0, 0, 0, 0},
}
func ConvertWondercard(f *os.File) []byte {
r := bufio.NewReader(f)
buf := make([]byte, 856)
_, err := io.ReadFull(r, buf)
if err != nil {
log.Printf("Error reading data for %s%s", f.Name(), LineBreak)
return nil
}
pkmBuf := buf[8:244]
pid := binary.LittleEndian.Uint32(pkmBuf[0:4])
seed := uint32(binary.LittleEndian.Uint16(pkmBuf[6:8]))
shiftValue := ((pid & 0x3E000) >> 0xD) % 24
decryptBuf := make([]byte, 228)
prng := NewPokemonRng(seed)
// Decrypt
for i := 0; i < 228; i += 2 {
if i == 128 { prng = NewPokemonRng(pid) }
v := binary.LittleEndian.Uint16(pkmBuf[i+8:i+10])
binary.LittleEndian.PutUint16(decryptBuf[i:i+2], v ^ prng.Next().H())
}
// Unshuffle the blocks
newBlocks := make([]byte, 228)
for block := 0; block < 4; block++ {
pos := 32 * blockPositions[block][shiftValue]
blockPos := block * 32
nextBlockPos := (block+1) * 32
copy(newBlocks[blockPos:nextBlockPos], decryptBuf[pos:32+pos])
}
// Copy party stuff
copy(newBlocks[128:228], decryptBuf[128:228])
wcBuf := make([]byte, 856)
copy(wcBuf[0:16], buf[0:16])
copy(wcBuf[16:244], newBlocks)
copy(wcBuf[244:], buf[244:])
return wcBuf
}
func SaveWondercard(saveData []byte, newPath string) {
// Save the data
newFile, err := os.Create(newPath)
if err != nil {
log.Printf("File: Error opening new file file %s%s", newPath, LineBreak)
return
}
writer := bufio.NewWriter(newFile)
if _, err := writer.Write(saveData); err != nil {
log.Printf("File: Error writing new file %v%s", err, LineBreak)
return
}
if err := writer.Flush(); err != nil {
log.Printf("File: Error flushing new file %v%s", err, LineBreak)
return
}
_ = newFile.Close()
log.Printf("Created %s%s", newPath, LineBreak)
}