Daijishou icon indicating copy to clipboard operation
Daijishou copied to clipboard

Suggestion : Python Script to Import from Batocera to Anbernic

Open soaresden opened this issue 1 year ago • 0 comments

Hi !

Recently got an Anbernic 405M and i'm quite familiar with scrapping and stuff

The idea came to migrate a sample of my collection to Anbernic, I saw in the options to read xml from emulation station (I still didn't get how it read but stil...)

As you know, it's quite a pain to take and rename file one by one to get the cover.

So what I made on my side :

  • Step 1: fill a ROMS folder with like emulation station
  • Step 2 : Choose and copy the roms in them
  • Step 3 : Created a AnbernicImages (which have the same structure than roms, but only for images used)
  • Step 4 : run that script I made , be sure to edit the 3 variables at the beginning

image

import os
import shutil
import xml.etree.ElementTree as ET

ROMSBatocera = r"D:\batocera\roms"
ROMSAnbernic = r"E:\RETROARCH\ROMS"
DossierImagesFinal = r"E:\RETROARCH\AnbernicImages"

image_extensions = ['.png', '.jpg', '.jpeg', '.bmp']
video_extensions = ['.mp4', '.avi', '.mkv']

# Ask the user which images to copy
print("1/3 : Select the ImageType to Copy")
print("-------------------------------")
print("[I]mage")
print("[B]oxart")
print("[S]creenshot")
print("[C]artridge")
print("[M]ix")

image_types = {
    'i': 'image',
    'b': 'boxart',
    's': 'screenshot',
    'c': 'cartridge',
    'm': 'mix',
}
image_choices = input("? ").strip().lower()

# Ask the user if they want the fan art for Wallpaper Purposes?
print("2/3 : Do you want fanarts?")
print("[Y]es")
print("[N]o")
fanart_choice = input("? ").strip().lower()

# Ask the user if they want to copy videos
print("3/3 : Do you want to copy videos?")
print("[Y]es")
print("[N]o")
video_choice = input("? ").strip().lower()

# Create a folder for fanart if the user wants it
if fanart_choice == 'y':
    fanart_folder = os.path.join(DossierImagesFinal, "FANART")
    os.makedirs(fanart_folder, exist_ok=True)

# Loop through the directories in ROMSAnbernic
for folder in os.listdir(ROMSAnbernic):
    folder_path = os.path.join(ROMSAnbernic, folder)

    print(f"{folder}:")

    counterimage = 0
    counterfan = 0
    countervid = 0

    # Find the corresponding gamelist.xml in ROMSBatocera
    gamelist_path = os.path.join(ROMSBatocera, folder, 'gamelist.xml')

    if not os.path.exists(gamelist_path):
        continue

    # Parse the gamelist.xml
    tree = ET.parse(gamelist_path)
    root = tree.getroot()

    # Loop through the files in the folder
    for item in os.listdir(folder_path):
        item_path = os.path.join(folder_path, item)

        # Extract the filename from the item path
        item_filename = os.path.splitext(os.path.basename(item_path))[0].lower()

        # Loop through the game nodes and find the one with a matching path
        for game_node in root.findall(".//game"):
            game_path = game_node.find("path").text.lower()
            game_path_normal = game_node.find("path").text


            if item_filename in game_path:
                rom_filename = os.path.splitext(os.path.basename(game_path))[0]
                rom_filename_original = os.path.splitext(os.path.basename(game_path_normal))[0]

                # Loop through the image choices and copy the images if they exist
                for choice in image_choices:
                    image_type = image_types.get(choice)
                    if image_type:
                        imagenode = game_node.find(image_type)
                        if imagenode is not None:
                            ext = os.path.splitext(imagenode.text)[1]
                            source_image = os.path.join(ROMSBatocera, folder, imagenode.text.lstrip('./'))
                            source_image = source_image.replace("/", "\\")
                            destination_image = os.path.join(DossierImagesFinal, folder, rom_filename_original + ext)

                            if os.path.exists(source_image):
                                if not os.path.exists(os.path.dirname(destination_image)):
                                    # Create the destination directory if it doesn't exist
                                    os.makedirs(os.path.dirname(destination_image))

                                if os.path.exists(destination_image):
                                    # Compare the size
                                    imageSizeSource = os.path.getsize(source_image)
                                    imageSizeDestination = os.path.getsize(destination_image)

                                    if imageSizeSource != imageSizeDestination:
                                        shutil.copy(source_image, destination_image)
                                        counterimage = counterimage + 1
                                else:
                                    # Destination doesn't exist, so copy the file
                                    shutil.copy(source_image, destination_image)
                                    counterimage = counterimage + 1
                            else:
                                print(f"Source image does not exist: {source_image}")


                    # Copy fanart if it exists
                    if fanart_choice == 'y':
                        fanart_node = game_node.find("fanart")
                        if fanart_node is not None:
                            ext = os.path.splitext(fanart_node.text)[1]
                            source_fanart = os.path.join(ROMSBatocera, folder, fanart_node.text.lstrip('./'))
                            source_fanart = source_fanart.replace("/", "\\")
                            destination_fanart = os.path.join(fanart_folder, rom_filename_original + ext)

                            if os.path.exists(source_fanart) and not os.path.exists(destination_fanart):
                                shutil.copy(source_fanart, destination_fanart)
                                counterfan += 1

                    # Copy Video if it exists
                    if video_choice == 'y':
                        for ext in video_extensions:
                            video_node = game_node.find("video")
                            if video_node is not None and video_node.text.lower().endswith(ext):
                                source_video = os.path.join(ROMSBatocera, folder, video_node.text.lstrip('./'))
                                source_video = source_video.replace("/", "\\")
                                destination_video = os.path.join(DossierImagesFinal, folder, rom_filename_original + ext)

                                if os.path.exists(source_video) and (not os.path.exists(destination_video) or
                                    os.path.getsize(source_video) != os.path.getsize(destination_video)):
                                    shutil.copy(source_video, destination_video)
                                    countervid += 1

    print(f"{folder}: {counterimage} images copied, {counterfan} fanart copied, {countervid} videos")


print("Copying Complete Finished")


step5 - it will actually loop over all the roms you had copied, opened the gamelist and look for the imagetype you wanted and copied it with the name of the rom Step 6 - configure Daijishou to sync your roms/read the xml and the image to the folder created

As you notice is tedious to do so

Suggestion :

  • Make it reliable to understand the actual structure from batocera/emulation station like ./media/image/Wario Land  The Shake Dimension-mix.png should be readable by Daijishou ! with that, I shouldn't had to make this script because it appears it didn't worked to get the image. It should be the same name as the rom.

  • Use the possibility to load video instead of the youtube in the background

  • it is a pain to : Sync Folder/Sync XML/Sync Images, A one click solution with the XML should be done and sufficient

PS:

  • Later on maybe I will do the cleanup job to only rely on the rom you have and dont pollute with unecesserary file
  • Also, I wanted to have some fanarts to be able to choose the background with them
  • and anticipate the video feature as well :)

I hope you will read and learn from this suggestion

soaresden avatar Oct 27 '23 15:10 soaresden