Show total game progress instead of per file progress

This commit is contained in:
Xpl0itU 2023-12-22 12:15:43 +01:00
parent 4a480f5e97
commit db3eb601e5
2 changed files with 49 additions and 20 deletions

View file

@ -10,13 +10,15 @@ import (
) )
type ProgressWindow struct { type ProgressWindow struct {
Window *gtk.Window Window *gtk.Window
box *gtk.Box box *gtk.Box
gameLabel *gtk.Label gameLabel *gtk.Label
bar *gtk.ProgressBar bar *gtk.ProgressBar
cancelButton *gtk.Button cancelButton *gtk.Button
cancelled bool cancelled bool
cancelFunc context.CancelFunc cancelFunc context.CancelFunc
totalToDownload int64
totalDownloaded int64
} }
func (pw *ProgressWindow) SetGameTitle(title string) { func (pw *ProgressWindow) SetGameTitle(title string) {
@ -28,11 +30,12 @@ func (pw *ProgressWindow) SetGameTitle(title string) {
} }
} }
func (pw *ProgressWindow) UpdateDownloadProgress(downloaded, total, speed int64, filePath string) { func (pw *ProgressWindow) UpdateDownloadProgress(downloaded, speed int64, filePath string) {
glib.IdleAdd(func() { glib.IdleAdd(func() {
pw.cancelButton.SetSensitive(true) pw.cancelButton.SetSensitive(true)
pw.bar.SetFraction(float64(downloaded) / float64(total)) currentDownload := downloaded + pw.totalDownloaded
pw.bar.SetText(fmt.Sprintf("Downloading %s (%s/%s) (%s/s)", filePath, humanize.Bytes(uint64(downloaded)), humanize.Bytes(uint64(total)), humanize.Bytes(uint64(speed)))) pw.bar.SetFraction(float64(currentDownload) / float64(pw.totalToDownload))
pw.bar.SetText(fmt.Sprintf("Downloading %s (%s/%s) (%s/s)", filePath, humanize.Bytes(uint64(currentDownload)), humanize.Bytes(uint64(pw.totalToDownload)), humanize.Bytes(uint64(speed))))
}) })
for gtk.EventsPending() { for gtk.EventsPending() {
gtk.MainIteration() gtk.MainIteration()
@ -58,6 +61,18 @@ func (pw *ProgressWindow) SetCancelled() {
pw.cancelFunc() pw.cancelFunc()
} }
func (pw *ProgressWindow) SetDownloadSize(size int64) {
pw.totalToDownload = size
}
func (pw *ProgressWindow) SetTotalDownloaded(total int64) {
pw.totalDownloaded = total
}
func (pw *ProgressWindow) AddToTotalDownloaded(toAdd int64) {
pw.totalDownloaded += toAdd
}
func createProgressWindow(parent *gtk.ApplicationWindow) (*ProgressWindow, error) { func createProgressWindow(parent *gtk.ApplicationWindow) (*ProgressWindow, error) {
win, err := gtk.WindowNew(gtk.WINDOW_TOPLEVEL) win, err := gtk.WindowNew(gtk.WINDOW_TOPLEVEL)
if err != nil { if err != nil {

View file

@ -24,10 +24,13 @@ const (
type ProgressReporter interface { type ProgressReporter interface {
SetGameTitle(title string) SetGameTitle(title string)
UpdateDownloadProgress(downloaded, total int64, speed int64, filePath string) UpdateDownloadProgress(downloaded, speed int64, filePath string)
UpdateDecryptionProgress(progress float64) UpdateDecryptionProgress(progress float64)
Cancelled() bool Cancelled() bool
SetCancelled() SetCancelled()
SetDownloadSize(size int64)
SetTotalDownloaded(total int64)
AddToTotalDownloaded(toAdd int64)
} }
func calculateDownloadSpeed(downloaded int64, startTime, endTime time.Time) int64 { func calculateDownloadSpeed(downloaded int64, startTime, endTime time.Time) int64 {
@ -70,7 +73,6 @@ func downloadFile(ctx context.Context, progressReporter ProgressReporter, client
} }
defer file.Close() defer file.Close()
total := resp.ContentLength
buffer := make([]byte, bufferSize) buffer := make([]byte, bufferSize)
var downloaded int64 var downloaded int64
@ -101,7 +103,7 @@ func downloadFile(ctx context.Context, progressReporter ProgressReporter, client
downloaded += int64(n) downloaded += int64(n)
endTime := time.Now() endTime := time.Now()
speed = calculateDownloadSpeed(downloaded, startTime, endTime) speed = calculateDownloadSpeed(downloaded, startTime, endTime)
progressReporter.UpdateDownloadProgress(downloaded, total, speed, filePath) progressReporter.UpdateDownloadProgress(downloaded, speed, filePath)
} }
break break
} }
@ -112,6 +114,7 @@ func downloadFile(ctx context.Context, progressReporter ProgressReporter, client
func DownloadTitle(cancelCtx context.Context, titleID, outputDirectory string, doDecryption bool, progressReporter ProgressReporter, deleteEncryptedContents bool, logger *Logger) error { func DownloadTitle(cancelCtx context.Context, titleID, outputDirectory string, doDecryption bool, progressReporter ProgressReporter, deleteEncryptedContents bool, logger *Logger) error {
titleEntry := getTitleEntryFromTid(titleID) titleEntry := getTitleEntryFromTid(titleID)
progressReporter.SetTotalDownloaded(0)
progressReporter.SetGameTitle(titleEntry.Name) progressReporter.SetGameTitle(titleEntry.Name)
outputDir := strings.TrimRight(outputDirectory, "/\\") outputDir := strings.TrimRight(outputDirectory, "/\\")
@ -168,6 +171,22 @@ func DownloadTitle(cancelCtx context.Context, titleID, outputDirectory string, d
return err return err
} }
var titleSize uint64
var contentSizes []uint64
for i := 0; i < int(contentCount); i++ {
contentDataLoc := 0xB04 + (0x30 * i)
var contentSizeInt uint64
if err := binary.Read(bytes.NewReader(tmdData[contentDataLoc+8:contentDataLoc+8+8]), binary.BigEndian, &contentSizeInt); err != nil {
return err
}
titleSize += contentSizeInt
contentSizes = append(contentSizes, contentSizeInt)
}
progressReporter.SetDownloadSize(int64(titleSize))
cert, err := GenerateCert(tmdData, contentCount, progressReporter, client, cancelCtx) cert, err := GenerateCert(tmdData, contentCount, progressReporter, client, cancelCtx)
if err != nil { if err != nil {
if progressReporter.Cancelled() { if progressReporter.Cancelled() {
@ -218,6 +237,7 @@ func DownloadTitle(cancelCtx context.Context, titleID, outputDirectory string, d
} }
return err return err
} }
progressReporter.AddToTotalDownloaded(int64(contentSizes[i]))
if tmdData[offset+7]&0x2 == 2 { if tmdData[offset+7]&0x2 == 2 {
filePath = filepath.Join(outputDir, fmt.Sprintf("%08X.h3", id)) filePath = filepath.Join(outputDir, fmt.Sprintf("%08X.h3", id))
@ -229,13 +249,7 @@ func DownloadTitle(cancelCtx context.Context, titleID, outputDirectory string, d
} }
content.Hash = tmdData[offset+16 : offset+0x14] content.Hash = tmdData[offset+16 : offset+0x14]
content.ID = fmt.Sprintf("%08X", id) content.ID = fmt.Sprintf("%08X", id)
tmdDataReader.Seek(int64(offset+8), 0) content.Size = int64(contentSizes[i])
if err := binary.Read(tmdDataReader, binary.BigEndian, &content.Size); err != nil {
if progressReporter.Cancelled() {
break
}
return err
}
if err := checkContentHashes(outputDirectory, content, cipherHashTree); err != nil { if err := checkContentHashes(outputDirectory, content, cipherHashTree); err != nil {
if progressReporter.Cancelled() { if progressReporter.Cancelled() {
break break