Skip to content

Commit

Permalink
v0.3.2 commit
Browse files Browse the repository at this point in the history
* Extract ROM Covers
* Change ROM covers
  • Loading branch information
EricGoldsteinNz committed Jul 30, 2023
1 parent d1201c2 commit 62104c5
Show file tree
Hide file tree
Showing 4 changed files with 163 additions and 21 deletions.
2 changes: 1 addition & 1 deletion build.bat
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
@echo off
set ver=0.3.1
set ver=0.3.2
rem build script for the distributable versions of tadpole
if not exist "venv\" (
py -m venv venv
Expand Down
163 changes: 150 additions & 13 deletions tadpole.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,12 +116,12 @@ def loadROMsToTable():

def catchTableCellClicked(clickedRow, clickedColumn):
print(f"clicked view thumbnail for {clickedRow},{clickedColumn}")
if clickedColumn == 2:
if clickedColumn == 2: #view thumbnail
drive = window.combobox_drive.currentText()
system = window.combobox_console.currentText()
gamename = window.tbl_gamelist.item(clickedRow, 0).text()
viewThumbnail(os.path.join(drive, system, gamename))
elif clickedColumn == 3:
elif clickedColumn == 3: #change thumbnail
drive = window.combobox_drive.currentText()
system = window.combobox_console.currentText()
gamename = window.tbl_gamelist.item(clickedRow, 0).text()
Expand All @@ -143,9 +143,21 @@ def catchTableCellClicked(clickedRow, clickedColumn):


def viewThumbnail(rom_path):
window.window_thumbnail = thumbnailWindow()
window.window_thumbnail.loadThumbnail(rom_path)
window.window_thumbnail.show()
window.window_thumbnail = thumbnailWindow(rom_path)
result = window.window_thumbnail.exec()
if result:
newLogoFileName = window.window_thumbnail.new_viewer.path
print(f"user tried to load image: {newLogoFileName}")
if newLogoFileName is None or newLogoFileName == "":
print("user cancelled image select")
return

try:
tadpole_functions.changeZXXThumbnail(rom_path, newLogoFileName)
except tadpole_functions.Exception_InvalidPath:
QMessageBox.about(window, "Change ROM Cover", "An error occurred.")
return
QMessageBox.about(window, "Change ROM Logo", "ROM cover successfully changed")

def BGM_change(source=""):
# Check the selected drive looks like a Frog card
Expand Down Expand Up @@ -647,20 +659,145 @@ def UpdatetoV1_5(self):


# Subclass Qidget to create a thumbnail viewing window
class thumbnailWindow(QWidget):
class thumbnailWindow(QDialog):
"""
This window should be called without a parent widget so that it is created in its own window.
"""
def __init__(self):
def __init__(self, filepath):
super().__init__()
layout = QVBoxLayout()
self.thumbnail = QLabel()
layout.addWidget(self.thumbnail)
self.setLayout(layout)

def loadThumbnail(self, filepath):

self.setWindowIcon(QIcon(self.style().standardIcon(QStyle.StandardPixmap.SP_DesktopIcon)))
self.setWindowTitle(f"Thumbnail - {filepath}")
# self.thumbnail.setPixmap(QPixmap.fromImage(tadpole_functions.getThumbnailFromZXX(filepath)))

# Setup Main Layout
self.layout_main = QVBoxLayout()
self.setLayout(self.layout_main)

# set up current image viewer
self.layout_main.addWidget(QLabel("Current Image"))
self.current_viewer = ROMCoverViewer(self)
self.layout_main.addWidget(self.current_viewer, Qt.AlignCenter)

self.layout_main.addWidget(QLabel(" ")) # spacer

# set up new image viewer
self.layout_main.addWidget(QLabel("New Image"))
self.new_viewer = ROMCoverViewer(self, changeable=True)
self.layout_main.addWidget(self.new_viewer, Qt.AlignCenter)

# Main Buttons Layout (Save/Cancel)
self.layout_buttons = QHBoxLayout()
self.layout_main.addLayout(self.layout_buttons)

#Save Existing Cover To File Button
self.button_write = QPushButton("Save Existing to File")
self.button_write.clicked.connect(self.WriteImgToFile)
self.layout_buttons.addWidget(self.button_write)

# Save Button
self.button_save = QPushButton("Overwrite Cover")
self.button_save.setDefault(True)
self.button_save.setDisabled(True) # set disabled by default; need to wait for user to select new image
self.button_save.clicked.connect(self.accept)
self.layout_buttons.addWidget(self.button_save)

# Cancel Button
self.button_cancel = QPushButton("Cancel")
self.button_cancel.clicked.connect(self.reject)
self.layout_buttons.addWidget(self.button_cancel)

# Load Initial Image
self.current_viewer.load_from_ROM(filepath)

def WriteImgToFile(self):
newCoverFileName = QFileDialog.getSaveFileName(window,
'Save Cover',
'c:\\',
"Image files (*.png)")[0]

if newCoverFileName is None or newCoverFileName == "":
print("user cancelled save select")
return
try:
tadpole_functions.extractImgFromROM(self.current_viewer.path, newCoverFileName)
except tadpole_functions.Exception_InvalidPath:
QMessageBox.about(window, "Save ROM Cover", "An error occurred.")
return
QMessageBox.about(window, "Save ROM Cover", "ROM cover successfully")



class ROMCoverViewer(QLabel):
"""
Args:
parent (thumbnailWindow): Parent widget. Used to enable/disable controls on parent.
changeable (bool): If True, will allow importing new image. If False, will just allow static display.
"""
def __init__(self, parent, changeable=False):
super().__init__(parent)

self.changeable = changeable
self.path = "" # Used to store path to the currently-displayed file

self.setStyleSheet("background-color: white;")
self.setMinimumSize(144, 208) # resize to Froggy ROM logo dimensions
self.setFixedSize(144, 208) # resize to Froggy ROM logo dimensions

if self.changeable:
self.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
self.setText("Click to Select New Image")

def mousePressEvent(self, ev):
"""
Overrides built-in function to handle mouse click events. Prompts user for image path and loads same.
"""
if self.changeable: # only do something if image is changeable
file_name = QFileDialog.getOpenFileName(self, 'Open file', '',
"Images (*.jpg *.png *.webp);;RAW (RGB565 Little Endian) Images (*.raw)")[0]
if len(file_name) > 0: # confirm if user selected a file
self.load_image(file_name)

def load_from_ROM(self, pathToROM: str):
"""
Extracts image from the bios and passes to load image function.
Args:
drive (str): Path to the root of the Froggy drive.
"""
print(f"loading cover from {pathToROM}")
with open(pathToROM, "rb") as rom_file:
rom_content = bytearray(rom_file.read())
with open(os.path.join(basedir, "temp_rom_cover.raw"), "wb") as image_file:
image_file.write(rom_content[0:((144*208)*2)])

self.load_image(os.path.join(basedir, "temp_rom_cover.raw"))

def load_image(self, path: str) -> bool:
"""
Loads an image into the viewer. If the image is loaded successfully, may enable the parent Save button based
on the changeable flag.
Args:
path (str): Path to the image. Can be .raw or other format. If .raw, assumed to be in RGB16 (RGB565 Little
Endian) format used for Froggy boot logos. Must be 512x200 pixels or it will not be accepted/displayed.
Returns:
bool: True if image was loaded, False if not.
"""
if os.path.splitext(path)[1] == ".raw": # if raw image, assume RGB16 (RGB565 Little Endian)
with open(path, "rb") as f:
img = QImage(f.read(), 144, 208, QImage.Format_RGB16)
else: # otherwise let QImage autodetection do its thing
img = QImage(path)
if (img.width(), img.height()) != (144, 208):
img = img.scaled(144, 208, Qt.IgnoreAspectRatio, Qt.SmoothTransformation) #Rescale new boot logo to correct size
self.path = path # update path
self.setPixmap(QPixmap().fromImage(img))

if self.changeable: # only enable saving for changeable dialogs; prevents enabling with load from bios
self.parent().button_save.setDisabled(False)
return True


# Subclass Qidget to create a change shortcut window
Expand Down
11 changes: 8 additions & 3 deletions tadpole_functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import shutil
import hashlib
import zipfile
import io
from PyQt5.QtGui import *
from PyQt5.QtCore import *
import struct
Expand Down Expand Up @@ -129,10 +128,10 @@ def QImageToRGB565Logo(inputQImage):
def getThumbnailFromZXX(filepath):
"""
file_handle = open(filepath, 'rb') #rb for read bytes
zxx_content = bytearray(file_handle.read(os.path.getsize(filepath)))#can probably reduce this to 288*104*2
zxx_content = bytearray(file_handle.read(os.path.getsize(filepath)))#can probably reduce this to 208*104*2
file_handle.close()
thumbnailQImage = QImage()
for y in range (0, 288):
for y in range (0, 208):
for x in range (0, 104):
#TODO
intColor =
Expand Down Expand Up @@ -439,3 +438,9 @@ def downloadFileFromGithub(outFile, url):
with open(outFile, 'wb') as f:
print(f'downloading {url} to {outFile}')
f.write(r.content)

def extractImgFromROM(romFilePath, outfilePath):
with open(romFilePath, "rb") as rom_file:
rom_content = bytearray(rom_file.read())
img = QImage(rom_content[0:((144*208)*2)], 144, 208, QImage.Format_RGB16)
img.save(outfilePath)
8 changes: 4 additions & 4 deletions versioninfo
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
VSVersionInfo(
ffi=FixedFileInfo(
filevers=(0, 3, 1, 0),
prodvers=(0, 3, 1, 0),
filevers=(0, 3, 2, 0),
prodvers=(0, 3, 2, 0),
mask=0x3f,
flags=0x0,
OS=0x4,
Expand All @@ -15,12 +15,12 @@ VSVersionInfo(
u'080904B0',
[StringStruct(u'CompanyName', u'EricGoldstein'),
StringStruct(u'FileDescription', u'tadpole'),
StringStruct(u'FileVersion', u'0.3.1'),
StringStruct(u'FileVersion', u'0.3.2'),
StringStruct(u'InternalName', u'tadpole'),
StringStruct(u'LegalCopyright', u'by EricGoldstein 2023'),
StringStruct(u'OriginalFilename', u'tadpole.exe'),
StringStruct(u'ProductName', u'tadpole'),
StringStruct(u'ProductVersion', u'0.3.1')])
StringStruct(u'ProductVersion', u'0.3.2')])
]),
VarFileInfo([VarStruct(u'Translation', [2057, 1200])])
]
Expand Down

0 comments on commit 62104c5

Please sign in to comment.