Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add Fyne UI back #83

Merged
merged 9 commits into from
Oct 13, 2024
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
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 13 additions & 5 deletions .github/workflows/on-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,19 @@ jobs:
with:
go-version: "^1.21.5"

- name: Get dependencies
run: |
sudo apt-get update \
&& sudo apt-get install gcc \
libgl1-mesa-dev libegl1-mesa-dev \
libgles2-mesa-dev libx11-dev xorg-dev \
libwayland-dev libxkbcommon-dev bc

- name: Build
run: go build .

- name: Rename archive
run: zip -r Pinecone_linux.zip data Pinecone
run: zip -r Pinecone_linux.zip data images Pinecone

- name: Upload Linux Bin
uses: djn24/add-asset-to-release@v2
Expand All @@ -32,7 +40,7 @@ jobs:

publish-binaries-mac-intel:
timeout-minutes: 20
runs-on: macos-latest
runs-on: macos-13

steps:
- name: Checkout
Expand All @@ -47,7 +55,7 @@ jobs:
run: GOOS=darwin GOARCH=amd64 go build -o Pinecone.app

- name: Zip App
run: zip -vr Pinecone_macos_intel.zip data Pinecone.app -x "*.DS_Store"
run: zip -vr Pinecone_macos_intel.zip data images Pinecone.app -x "*.DS_Store"

- name: Upload MacOS Bin
uses: djn24/add-asset-to-release@v2
Expand All @@ -72,7 +80,7 @@ jobs:
run: GOOS=darwin GOARCH=arm64 go build -o Pinecone.app

- name: Zip App
run: zip -vr Pinecone_macos_arm.zip data Pinecone.app -x "*.DS_Store"
run: zip -vr Pinecone_macos_arm.zip images data Pinecone.app -x "*.DS_Store"

- name: Upload MacOS Bin
uses: djn24/add-asset-to-release@v2
Expand All @@ -98,7 +106,7 @@ jobs:

- name: Zip Binary
shell: pwsh
run: Compress-Archive -Path "Pinecone.exe", "data" -DestinationPath "Pinecone_win.zip"
run: Compress-Archive -Path "Pinecone.exe", "data", "images" -DestinationPath "Pinecone_win.zip"
- name: Upload Win Bin
uses: djn24/add-asset-to-release@v2
with:
Expand Down
109 changes: 78 additions & 31 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,16 @@
<p align="center">I'm Cleet. Cletus T. Pine.</p>

# PineCone
* A content discovery tool, for original Xbox DLC and Title Updates.

- A content discovery tool, for original Xbox DLC and Title Updates.

# How-To
* Download the id_database.json
* Download the appropriate binary for your platform.
* Working Directory should look like this:
```

- Download the id_database.json
- Download the appropriate binary for your platform.
- Working Directory should look like this:

```sh
PineCone
|-- pinecone binary
|
Expand All @@ -24,35 +28,78 @@ PineCone
| |-- F (optional)
| |-- G (optional)
```

* Run your binary from the commandline. e.g: ./pinecone (or pinecone.exe) (optional flags: -fatxplorer (Windows only, mount E as X in fatxplorer))

- Run your binary from the commandline. e.g: ./pinecone (or pinecone.exe) (optional flags: -fatxplorer (Windows only, mount E as X in fatxplorer))

# About
* Our buddy Harcroft has been keeping a rolling list of missing content for nearly 20 years.
* The idea of this software is to cut out as much of the manual digging as possible, and expand on it as a tool to archive this data.

- Our buddy Harcroft has been keeping a rolling list of missing content for nearly 20 years.
- The idea of this software is to cut out as much of the manual digging as possible, and expand on it as a tool to archive this data.

# Hows this work?
* Drop UDATA and TDATA into a dump folder.
* Analyze the dump for userdata and DLC's, User Created Content, Content Update Files.
* (Optional) Analyze the dump for Homebrew content in a C E F G folder structure.

- Drop UDATA and TDATA into a dump folder.
- Analyze the dump for userdata and DLC's, User Created Content, Content Update Files.
- (Optional) Analyze the dump for Homebrew content in a C E F G folder structure.

# Todo
* Disect Disk images
* Import archived dumps
* Export output for easy viewing
* Add more flags for more specific searches
* Create "Homebrew" JSON file to identify homebrew content.
* Beautify output, to make it easier on the eyes.
# Experimental Flags
* -fatxplorer: This flag will use a mounted E drive on partition X to scan.
* -update: This flag updates only the JSON. Useful between builds without major changes.
* -statistics: This will output statistics of the JSON, i.e totals.
* -titleid=ABCD1234: This will output the JSON details on a specific TitleID when provided.

- Disect Disk images
- Import archived dumps
- Export output for easy viewing
- Add more flags for more specific searches
- Create "Homebrew" JSON file to identify homebrew content.
- Beautify output, to make it easier on the eyes.

# Flags

- `-f`/`--fatxplorer`: This flag will use a mounted E drive on partition X to scan.
- `-u`/`--update`: This flag updates only the JSON. Useful between builds without major changes.
- `-s`/`--statistics`: This will output statistics of the JSON, i.e totals.
- `-tID=ABCD1234`/`--titleid=ABCD1234`: This will output the JSON details on a specific TitleID when provided.
- `-l=path/to/dump`/`--location=path/to/dump`: Specify the directory where your dump is located
- `-g={true/false}`/`--gui={true/false}`: Enable the GUI interface (default = true)

# Example output

```sh
Pinecone v0.5.0
Please share output of this program with the Pinecone team if you find anything interesting!
Checking for Content...
====================================================================================================
============================================== Halo 2 ==============================================
Content is known and archived Bonus Map Pack
Content is known and archived Killtacular Pack
Content is known and archived Maptacular Pack
Content is known and archived Blastacular Pack
============================================ File Info =============================================
Title update found for Halo 2 (4d530064) (0000000300000803:RF English Update 5)
Path: dump\TDATA\4d530064\$u\default.xbe
SHA1: f1cc1ae660161f4439fc29ee131310a86e326447

```
Local JSON file exists.
Loading JSON data...
Traversing directory structure...
Found folder for "Advent Rising".
Advent Rising has unarchived content found at: TDATA/4d4a0009/$c/4d4a000900000003
Title ID 50430001 not present in JSON file. May want to investigate!
Traversing directory structure for Title Updates...
TDATA/4d4a0009/$u/test.xbe: 87088e689b192c389693b3db38d5f26f2c4d55ae

# Building from source

## Dependencies

- `go` 1.21.5 or later
- `fyne` 2.4.3 or later
- `gofumpt` 0.6.0 or later (our preferred formatter)

## Build instructions

1. Install the `fyne` CLI tool

```sh
go install fyne.io/fyne/v2/cmd/fyne@latest
```

2. Install `gofumpt` CLI tool

```sh
go install mvdan.cc/gofumpt@latest
```

3. Run `go mod tidy` in the root directory to install all dependencies
4. Run `go build .`. WARNING: First compile will take a long time. Be patient!
2 changes: 1 addition & 1 deletion cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ func printTotalStats() {
fmt.Println("Total Archived Items:", totalArchivedItems)
}

func promptForDownload(url string) bool {
func cliPromptForDownload(url string) bool {
var response string
fmt.Printf("The required JSON data is not found. It can be downloaded from %s\n", url)
fmt.Print("Do you want to download it now? (yes/no): ")
Expand Down
82 changes: 63 additions & 19 deletions fileparse.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,14 @@ import (
"crypto/sha1"
"encoding/json"
"fmt"
"image/color"
"io"
"os"
"path/filepath"
"strings"

"github.com/fatih/color"
"fyne.io/fyne/v2/theme"
fatihColor "github.com/fatih/color"
)

func getSHA1Hash(filePath string) (string, error) {
Expand Down Expand Up @@ -54,10 +56,18 @@ func contains(slice []string, val string) bool {

func checkForContent(directory string) error {
if _, err := os.Stat(directory); os.IsNotExist(err) {
printInfo(color.FgYellow, "%s directory not found\n", directory)
printInfo(fatihColor.FgYellow, "%s directory not found\n", directory)
return fmt.Errorf("%s directory not found", directory)
}

logOutput := func(s string) {
if !guiEnabled {
printInfo(fatihColor.FgYellow, s+"\n")
} else {
addText(theme.PrimaryColorNamed(theme.ColorYellow), s)
}
}

err := filepath.Walk(directory, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
Expand All @@ -68,7 +78,11 @@ func checkForContent(directory string) error {
titleID := strings.ToLower(info.Name())
titleData, ok := titles.Titles[titleID]
if ok {
printHeader(titleData.TitleName) // Process known titles as before
// Process known titles as before
if guiEnabled {
addHeader(titleData.TitleName)
}
printHeader(titleData.TitleName)
}

// Check and potentially process $c subdirectory
Expand All @@ -81,7 +95,7 @@ func checkForContent(directory string) error {
return err
}
} else {
printInfo(color.FgYellow, "DLC content found in unrecognized directory: %s\n", subDirDLC)
logOutput(fmt.Sprintf("DLC content found in unrecognized directory: %s\n", subDirDLC))
}
}

Expand All @@ -95,7 +109,9 @@ func checkForContent(directory string) error {
return err
}
} else {
printInfo(color.FgYellow, "Updates found in unrecognized directory: %s\n", subDirUpdates)
if guiEnabled {
}
logOutput(fmt.Sprintf("Updates found in unrecognized directory: %s\n", subDirUpdates))
}
}

Expand Down Expand Up @@ -140,7 +156,10 @@ func processDLCContent(subDirDLC string, titleData TitleData, titleID string, di

contentID := strings.ToLower(subContent.Name())
if !contains(titleData.ContentIDs, contentID) {
printInfo(color.FgRed, "Unknown content found at: %s\n", subContentPath)
if guiEnabled {
addText(theme.ErrorColor(), "Unknown content found at: %s", subContentPath)
}
printInfo(fatihColor.FgRed, "Unknown content found at: %s\n", subContentPath)
continue
}

Expand All @@ -159,9 +178,17 @@ func processDLCContent(subDirDLC string, titleData TitleData, titleID string, di

subContentPath = strings.TrimPrefix(subContentPath, directory+"/")
if archivedName != "" {
printInfo(color.FgGreen, "Content is known and archived (%s)\n", archivedName)
if guiEnabled {
addText(theme.PrimaryColorNamed(theme.ColorGreen), "Content is known and archived %s", archivedName)
}
printInfo(fatihColor.FgGreen, "Content is known and archived %s\n", archivedName)

} else {
printInfo(color.FgYellow, "%s has unarchived content found at: %s\n", titleData.TitleName, subContentPath)
if guiEnabled {
addText(theme.ErrorColor(), "%s has unarchived content found at: %s", titleData.TitleName, subContentPath)
}
printInfo(fatihColor.FgYellow, "%s has unarchived content found at: %s\n", titleData.TitleName, subContentPath)

}
}

Expand All @@ -183,19 +210,32 @@ func processUpdates(subDirUpdates string, titleData TitleData, titleID string, d
filePath := filepath.Join(subDirUpdates, f.Name())
fileHash, err := getSHA1Hash(filePath)
if err != nil {
printInfo(color.FgRed, "Error calculating hash for file: %s, error: %s\n", f.Name(), err.Error())
if guiEnabled {
addText(theme.ErrorColor(), "Error calculating hash for file: %s, error: %s", f.Name(), err.Error())
}
printInfo(fatihColor.FgRed, "Error calculating hash for file: %s, error: %s\n", f.Name(), err.Error())

continue
}

for _, knownUpdate := range titleData.TitleUpdatesKnown {
for knownHash, name := range knownUpdate {
if knownHash == fileHash {
if guiEnabled {
addHeader("File Info")
addText(theme.PrimaryColorNamed(theme.ColorGreen), "Known and Archived Title update found for %s (%s) (%s)", titleData.TitleName, titleID, name)
filePath = strings.TrimPrefix(filePath, directory+"/")
addText(theme.PrimaryColorNamed(theme.ColorGreen), "Path: %s", filePath)
addText(theme.PrimaryColorNamed(theme.ColorGreen), "SHA1: %s", fileHash)
addText(color.Transparent, separator)
}
printHeader("File Info")
printInfo(color.FgGreen, "Title update found for %s (%s) (%s)\n", titleData.TitleName, titleID, name[17:])
printInfo(fatihColor.FgGreen, "Known and Archive Title update found for %s (%s) (%s)\n", titleData.TitleName, titleID, name)
filePath = strings.TrimPrefix(filePath, directory+"/")
printInfo(color.FgGreen, "Path: %s\n", filePath)
printInfo(color.FgGreen, "SHA1: %s\n", fileHash)
printInfo(fatihColor.FgGreen, "Path: %s\n", filePath)
printInfo(fatihColor.FgGreen, "SHA1: %s\n", fileHash)
fmt.Println(separator)

knownUpdateFound = true
break
}
Expand All @@ -205,16 +245,20 @@ func processUpdates(subDirUpdates string, titleData TitleData, titleID string, d
}
}

if knownUpdateFound {
break
}

if !knownUpdateFound {
if guiEnabled {
addHeader("File Info")
addText(theme.ErrorColor(), "Unknown Title Update found for %s (%s)", titleData.TitleName, titleID)
filePath = strings.TrimPrefix(filePath, directory+"/")
addText(theme.ErrorColor(), "Path: %s", filePath)
addText(theme.ErrorColor(), "SHA1: %s", fileHash)
}
printHeader("File Info")
printInfo(color.FgRed, "Unknown Title Update found for %s (%s)\n", titleData.TitleName, titleID)
printInfo(fatihColor.FgRed, "Unknown Title Update found for %s (%s)\n", titleData.TitleName, titleID)
filePath = strings.TrimPrefix(filePath, directory+"/")
printInfo(color.FgRed, "Path: %s\n", filePath)
printInfo(color.FgRed, "SHA1: %s\n", fileHash)
printInfo(fatihColor.FgRed, "Path: %s\n", filePath)
printInfo(fatihColor.FgRed, "SHA1: %s\n", fileHash)

}
}

Expand Down
Loading