Skip to content
shali1995Public

About

One-tap PSP / PS Vita game store for hacked Vitas. Client only — games come from community-hosted stores.

Resources

Stars

13 stars

Watchers

0 watching

Forks

Latest commit

 

History

3 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

PEPEstore

A one-tap game store for the PS Vita. Browse PSP and PS Vita games with real cover art, download them over Wi-Fi, and install them straight to the console — no PC, no cables, no wall of plain-text links.

PEPEstore is a client. It hosts nothing. No games, no catalogs, no cover art live in this app or on this repo. Everything comes from third-party "stores" maintained by the community — game catalogs hosted on people's own GitHub repos. This project is the reader; the sources belong to whoever makes them. Only download games you legally own.

Built by Shalva Efremashvili — because PKGj gave me a wall of text with no covers, and half my games weren't even on it. So I built this. No ads, no paywalls, no BS.

Telegram: @PEPESTOREVITA — find stores, request games, report bugs.

🤖 Built with AI, start to finish (and proud of it)

PEPEstore was 100% vibe-coded. Every line (the Lua, the C module, the store system, this README) was written with AI, A to Z. No apologies, no asterisks.

If that fact makes your eye twitch: cool, the app still works, the covers still load, and your Vita doesn't care who typed the semicolons. 🐸

And here's the part that'll really annoy the right people: AI contributions are not just allowed, they're encouraged. Open a PR written by ChatGPT, Claude, Copilot, whatever, and I'll review it on whether it works, not on which meat-or-silicon wrote it. Humans welcome too, obviously. Ship good code; that's the only rule.

"But a real dev would..." a real dev did: they pointed the tools and shipped the thing you're reading about. Results > gatekeeping.


Browse Details
Filters Downloads


Install

  1. Grab PEPEstore.vpk from the Releases page.
  2. Install it with VitaShell (or your bubble installer of choice).
  3. Launch it — it starts empty ("No stores yet"). You add a store to get games (below).

Requirements: a hacked Vita (HENkaku/enso). To launch downloaded PS Vita games you also need the NoNpDrm kernel plugin. PSP games run through Adrenaline.

Using it — adding a store

The app ships with nothing. To get games you add a store, which is just a public GitHub repo:

  1. Press START → Stores → Add a store.
  2. Type the store's username/reponame (e.g. shali1995/psp-webroms) and confirm.
  3. It downloads the store, and its games appear in the browse list (filter by Store).

Update / remove a store from the same Stores screen. Updates only re-download what changed.

Where do you find stores? In the community — join the Telegram: @PEPESTOREVITA. Anyone can publish one (see below), so the list grows and broken sources get fixed by the people who use them.


How it works

When you add a store by username/reponame, the app fetches it from raw.githubusercontent.com/<user>/<repo>/main/ and merges its games in. Browsing and covers are fully offline — only the moment you press Download touches the network, through that store's resolver. Nothing about any specific site is baked into the app.


Make your own store (for devs)

A store is a public GitHub repo with five files at its root. Build them however you like (any language) — you're just producing these files, then git push.

store.json      manifest — what the app reads first
catalog.lua     the game database
cov_index.lua   where each cover sits inside covers.pak
covers.pak      all the cover thumbnails in one file
resolver.lua    turns a game into a real download URL (the only "live" code)

1. store.json — the manifest

{
  "id": "my-psp-store",
  "name": "My PSP Store",
  "author": "yourname",
  "platform": "psp",
  "repo": "yourname/my-psp-store",
  "store_version": 1,
  "files": [
    { "name": "catalog.lua",   "version": 1, "size": 1234, "sha256": "..." },
    { "name": "cov_index.lua", "version": 1, "size": 1234, "sha256": "..." },
    { "name": "covers.pak",    "version": 1, "size": 1234, "sha256": "..." },
    { "name": "resolver.lua",  "version": 1, "size": 1234, "sha256": "..." }
  ]
}
  • platform — "psp" or "psvita" (decides the install path).
  • repo — your user/repo, so in-app Update knows where to check.
  • Versioning: every file has a version. To ship an update, change a file and bump its version (and store_version). The app re-downloads only the files whose version changed — tweak resolver.lua, bump it, and users pull ~2 KB instead of the whole cover pack.

2. catalog.lua — the game database

A Lua file returning an array of games. A game's position in the array is its cover index. Only display_name, console, and a way to download are required; everything else just enriches the detail page.

return {
  { id="final-fantasy", display_name="Final Fantasy", console="psp",
    cover_url="https://…",                 -- online fallback if no packed cover
    downloads=69200, size="1.04 G", rating=3.2, genre={"Role-Playing"},
    publisher={"Square Enix"}, region="Japan", released="June 26, 2007",
    description="A horrible cloak blankets the planet…",
    variants={                             -- the rows shown in the download picker
      { idx=1, filename="Final Fantasy (Japan).zip", size="1.04 G",
        container="zip", region="Japan", title_id=nil, version=nil, languages={},
        url="https://…" },                 -- what the resolver receives as `variant`
      -- …one per region / version
    } },
  -- …one table per game
}
  • console — "psp" → installed to ux0:pspemu (ISO/EBOOT); "psvita" → installed as a bubble.
  • variants[] — each is a download option. container is the file type (zip, 7z, …); drm (e.g. "NoNpDrm") shows as the chip in the picker; url is whatever your resolver needs.
  • Game #1 in the array uses cov_index[1], #2 uses cov_index[2], etc.

3. covers.pak + cov_index.lua — the art

covers.pak is every cover JPEG concatenated into one file (use 200×320 to match the app). cov_index.lua maps each game's array position → {byteOffset, length} into that file:

return { [1]={0,31500}, [2]={31500,27961}, [3]={59461,18030}, … }

Build it by appending each JPEG to the pak and recording where it landed. Missing covers just fall back to cover_url (or a placeholder).

4. resolver.lua — how downloads are found

The heart of a store. The app calls it when the user hits Download:

-- ctx.get(url, referer) -> page body (or nil) · ctx.urlenc(s) -> url-encoded string
return {
  name = "My PSP Store",
  resolve = function(ctx, game, variant)   -- variant = the picked row (or nil for single-file)
    -- return  url, referer   (or  nil, "reason")
  end,
}

Two common styles:

-- A) PRE-RESOLVED: the direct URL is already in the catalog, just hand it back (no network)
resolve = function(ctx, game, variant)
  local u = (variant and variant.url) or game.download_url
  if u and u ~= "" then return u, "https://the-site.example/" end
  return nil, "no url"
end
-- B) ON-DEVICE: the catalog stores a listing-page URL; fetch it and scrape the real link live
resolve = function(ctx, game, variant)
  local html = ctx.get(variant.url, "https://the-site.example/")
  if not html then return nil, "page fetch failed" end
  local link = html:match('href="(https?://[^"]+%.zip)"')
  if not link then return nil, "no link found" end
  return ctx.urlenc(link), variant.url   -- 2nd value = Referer for the download
end

5. Publish

Push the five files to a public GitHub repo. Users add it as yourname/reponame. Bump versions to ship updates.

⚠️ On-device limits (read this)

The Vita runs plain HTTP + Lua string-matching only — no JavaScript engine, no Cloudflare bypass. If a site builds its download link with JavaScript, or sits behind a Cloudflare "checking your browser" / CAPTCHA wall, it cannot be resolved on-device. Pick sites where the link is in the HTML (or one listing/redirect hop away), or pre-resolve the URLs into catalog.lua when you build it. (A store author can front a tricky site with their own server-side resolver — that's on them, not the client.)


What it supports / doesn't

Supports: PSP ISO / CSO / EBOOT.PBP (PSN & Minis) · PS Vita NoNpDrm .7z dumps · .7z (streamed, constant-RAM) / .zip / .rar · any source reachable by plain HTTP.

Doesn't: JavaScript-gated or Cloudflare-protected sites · Vitamin retail VPKs (retail-locked, no license — the installer refuses them to avoid a crash) · PSN .pkg (encrypted, not implemented).

Build

See BUILD.md. Engine is lpp-vita; PEPEstore is the Lua app + assets in vpk/ (ready-to-package: index.lua, font, icons, loading screen, sounds, sce_sys) plus a native module in module/ (libcurl downloads, libarchive extraction, scePromoterUtility install). Build the engine+module, drop the compiled eboot.bin into vpk/, zip it → done. The app bundles no catalog/covers — the store model provides those.

Credits

lpp-vita (Rinnegatamante) · libcurl · libarchive · liblzma · VitaShell (TheFloW) · pkgj · NOBORU (Creckeryop) · ONElua.

License

GPL-3.0 — copy, modify and redistribute freely, but derivatives must stay open source under the same license. See LICENSE.

About

One-tap PSP / PS Vita game store for hacked Vitas. Client only — games come from community-hosted stores.

Resources

Stars

13 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages