Skip to content

Instantly share code, notes, and snippets.

@Le0xFF
Created June 19, 2025 06:13
Show Gist options
  • Save Le0xFF/c62a4cf38af580d15524539ea4e9f276 to your computer and use it in GitHub Desktop.
Save Le0xFF/c62a4cf38af580d15524539ea4e9f276 to your computer and use it in GitHub Desktop.
PICO-8 Cartridge Downloader
#!/usr/bin/env perl
# 19.06.2025
# PICO-8 Cartridge downloader
# Original Script: https://www.lexaloffle.com/bbs/?pid=157397#p
# I'm not the creator of this script.
# I just updated and beauty-fied it to my own taste.
# If desired, modify the "Variables" section, to decide where
# to store downloaded cartridges and how many page the script should look for.
use strict;
use warnings;
use feature 'say';
use HTTP::Tiny;
use File::Path 'mkpath';
#############
# Variables #
#############
# URL where to download from
my $indexURL = "https://www.lexaloffle.com/bbs/?cat=7&sub=2"; # Featured
# Last page to download from
my $lastPage = 99;
# Destination directory, where cartridges will be downloaded to
my $destDir = "pico8";
########
# Main #
########
say "";
say "===============================";
say "= Pico-8 Cartridge Downloader =";
say "===============================";
say "";
# Initialize connection
my $indexConnection = HTTP::Tiny->new;
# Get HTML of all pages
my $indexHTML = "";
for (my $i = 1; $i <= $lastPage; $i++)
{
say "Getting HTML page " . $i . " of " . $lastPage;
$indexHTML .= ($indexConnection->get($indexURL . "&page=" . $i))->{content};
}
# Run the downloader on each cartridge page
my @allTids = ($indexHTML =~ m/tid=([0-9]+)/g);
my $numOfTids = scalar @allTids; # Save the number of cartridges found
my $currentTid = 1;
say "\nFound a total of: " . $numOfTids . " cartridges.";
for my $tid (@allTids)
{
my $url = "https://www.lexaloffle.com/bbs/?tid=" . $tid;
downloadCartridge($url, $tid, $numOfTids, $currentTid);
$currentTid++;
}
say "";
say "Goodbye!";
say "";
###############
# Subroutines #
###############
# Downloads the cartridge on the passed URL
sub downloadCartridge
{
# Extracting arguments passed to subroutine
my $providedUrl = $_[0];
my $providedTid = $_[1];
my $providedNumOfTid = $_[2];
my $providedCurrentTid = $_[3];
my $ua = HTTP::Tiny->new;
my $re = "(\/bbs\/cposts\/[a-z0-9]{1,}\/([a-zA-Z0-9_]{1,})-{0,}([0-9]){0,}\.p8\.png)";
my $res = $ua->get(shift);
if ($res->{content} =~ $re)
{
my ($url, $name) = ('https://www.lexaloffle.com' . $1, $2);
my $version = 0;
if (defined $3)
{
if (length($3) > 0)
{
$version = $3;
}
}
mkpath($destDir);
my $filename = lc $name;
$filename =~ s/\s+/-/g;
my $path = $destDir . '/' . $filename . '.p8.png';
say "\nDownloading cartridge: " . $providedCurrentTid . " of " . $providedNumOfTid;
say "======================";
say "TitleID: \t" . $providedTid;
say "URL: \t\t" . $url;
say "Name: \t\t" . $name;
say "Version: \t" . $version;
say "Destination: \t" . $path;
if (-e $path)
{
# If cartridge exists, skip it
say "\t\tSkipping already existing cartridge";
} else
{
# Save cartridge by mirroriring web page to destination
$ua->mirror($url, $path);
}
} else
{
say "\nCould not find game data: invalid URL!";
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment