Importing and exporting
Everything here happens in OpsLink — a browser on any device on your network. There are three ways in, and they do different jobs:
| where it is | what it is for | |
|---|---|---|
| Send a table | Library → Import | One table at a time, from the device you are holding. A .vpx, a .zip or a .vpxz package |
| Add a file | Library → the table → Files | Everything else that belongs to a table you already have: its ROM, backglass, PuP pack, alt sound, artwork. You choose the slot, so nothing is guessed |
| Bulk import | Library → Import | A whole directory of tables and backglasses you already own, done in one pass, best effort and fully reported |
| Take this table with you | Library → the table | The way out: packages a table back into one .vpxz file you can move somewhere else |
The first two are the normal path. Send the table, then open it and fill in the rest — that separation is what stops vPinOps guessing at your files, because the moment you pick a slot yourself there is nothing left to guess. Bulk import is the migration tool: reach for it when you already have a library laid out by something else.
1 · Send a table
Section titled “1 · Send a table”This is the normal way, and it is one table at a time. From OpsLink: Library → Import → Send a table from this device.
Three things go in:
.vpx | the table on its own |
.vpx inside a .zip | the usual download shape — vPinOps opens this one |
.vpxz | a packaged table: the whole folder, zipped. Comes across exactly as packed |
Sending is not importing, and that catches people, so here is the whole loop:
- Send it. Library → Import → Send a table from this device → Choose a file… The file is copied to the machine and put in a holding folder called the inbox. Nothing has been imported and nothing in your library has changed yet.
- Send more, if you want. Sending is one file at a time, but they stack up. Queue up five tables and deal with them in one go — you do not have to finish one before starting the next.
- Then tell it to look. Back on the Import page there is now a section headed Waiting in your inbox with a button: Look at these N file(s). Press it. That is the step people miss, because a send that worked looks finished.
- Check the preview. Everything in the inbox is read at once, so you see all five together — the name it worked out for each, the alternatives it considered, and a box to type your own.
- Press Import. Nothing is written to your library until you do.
2 · Then fill it in — the table’s Files
Section titled “2 · Then fill it in — the table’s Files”Open Library, tap the table, and scroll to Files → Add a file. Choose the slot, upload, done. It goes where you said, because you said so — no matching, no guessing, no name rules.
These pages call it the drawer, which is just a shorter name for that Files section.
| slot | what goes in it |
|---|---|
| The table folder | .directb2s backglass, .ini, .vbs — the table’s own files |
medias/ | art and video, including the kinds vPinOps does not display itself |
music/ | the table’s music |
pinmame/roms/ | this table’s own ROM, if you want it to travel with the table |
pinmame/nvram/ | its saved scores |
altsound/ · serum/ · vni/ · pupvideos/ | alternate sound and colour-DMD packages |
scripts/ | scripts the table needs |
A packaged table (.vpxz) — everything comes across
Section titled “A packaged table (.vpxz) — everything comes across”A .vpxz is your whole table folder, zipped: table, medias/, music/, the table’s own asset
folders, companions, and its pinmame/ folder if the packager had one.
All of it is imported exactly as packaged. Nothing is renamed, nothing is moved, nothing is left behind — including the ROM, if the package brought one. It stays where the package put it.
Why it is not tidied up: that package already works on a desktop, a cab and a phone. The community built it that way and Visual Pinball runs it that way. Rearranging a thing that works on four platforms is how you break it on the fifth. If you later want your ROMs consolidated into one shared folder, that is your decision and its own action — never something an import does to you.
Bulk import — the other tool
Section titled “Bulk import — the other tool”If you already have a directory of tables and backglasses, point vPinOps at it and it will do its best on all of them at once. This is a different job from sending one table, and it makes a different promise: best effort, fully reported.
It builds the structure, matches what it can, suggests names you can override, and names every file it could not place, with the reason. The measure is not a percentage — it is that nothing vanishes. Measured on a real 235-table library: every one of its 406 files was either placed or explained.
What it places
Section titled “What it places”| what | file types | where it ends up |
|---|---|---|
| The table | .vpx | the table folder, keeping its own filename |
| A packaged table | .vpxz, *.vpx.zip | unpacked into the folder |
| Backglass | .directb2s | beside the table, renamed onto a name the table will find |
| Companions | .ini · .vbs · .info · .scv | beside the table |
| Media | images .png .apng .jpg .jpeg .webp .bmp .gif · video .mp4 .m4v .webm .mov .mkv .avi .f4v .wmv | medias/(Kind) <table>.<ext> |
Media is only placed when the filename says which surface it is for
Section titled “Media is only placed when the filename says which surface it is for”These words are recognised anywhere in the name — and nothing else:
| word in the filename | surface |
|---|---|
wheel, logo | Wheel |
playfield, table, pf | Playfield |
backglass, bg | Backglass |
dmd | DMD |
fulldmd | FullDMD |
realdmd | RealDMD |
topper | Topper |
MyTable wheel.png is placed. MyTable art.png is not — it is reported rather than guessed at,
because a wrong guess puts somebody’s playfield on their topper. Put that one in the drawer instead.
What bulk import leaves for you — and it tells you about every one
Section titled “What bulk import leaves for you — and it tells you about every one”Almost everything here has a home in the drawer. Bulk import guesses from filenames, so it only places what a name can prove; the drawer needs no guessing because you pick the slot. Nothing is ever silently skipped — every file below is listed with its reason.
| what bulk import leaves | where it goes instead |
|---|---|
A plain .zip / .7z / .rar that does not name a table | Bulk import will not guess what is inside one. Extract it and drop the contents in — or, if it is a pack, send the zip to the matching drawer bay, which does unpack it |
A ROM (mm_109c.zip) | The pinmame/roms bay, or your shared PinMAME folder — leave it zipped either way |
Audio (.mp3, .ogg, .wav, …) | The music bay, or altsound for an altsound pack |
Media with no surface — cab.png, flyer.png | The filename has to say which screen it is for, and these do not. A wrong guess puts a cabinet photo on your playfield. Pick the slot yourself in the medias bays |
A table’s own asset folder — SomeTableDMD/, pupvideos/, altsound/ | The pupvideos, altsound, serum, vni and scripts bays. ⚠ The folder keeps its own name, because the table’s script refers to it by name — vPinOps will tell you if that name does not look like the ROM, and will not rename it for you |
A .pov file | Nowhere — it is refused outright. VPX no longer creates them, and on this build a .pov without a per-table .ini crashes the table on load. The file is refused; the table is not. Set your view in VPX’s F12 menu instead |
Laying the folder out to get the best result
Section titled “Laying the folder out to get the best result”- Extract your downloads first for bulk import. A
.vpxit can see beats a.zipit will not open. - One folder is enough. Subfolders are read, so a folder-per-download is fine and so is a flat pile.
- A subfolder containing exactly one table owns everything in it, whatever those files are called. That is the most reliable arrangement, because names stop mattering.
- In a flat pile, matching is by name, helped by a catalogue of 2,554 machines.
- Put your ROMs in your shared PinMAME
roms/folder — ROMs and nvram.
It never
Section titled “It never”- downloads tables, ROMs or backglasses — you bring those
- creates a table folder on top of one that already exists. Bulk import refuses rather than merging two tables into one folder. ⚠ This is about creating a table, not about adding to it — the drawer writes into an existing table’s folder all day, which is what it is for
- guesses which screen an unnamed image belongs on
- renames or overwrites media you put there yourself
Taking a table back out
Section titled “Taking a table back out”Every table’s own page has a Take this table with you row. It packages that table’s folder into a
single .vpxz — the same format import reads, so anything you export here can be imported anywhere
that reads packages, including back into this cab.
What travels: the table, its media, your saved scores, and its ROM if the ROM is inside the table’s own folder. Most tables come out at a few hundred MB.
Two scopes, in the dropdown beside the button:
| Everything | The whole folder. This is the default |
| Smaller — no artwork | Leaves out the frontend art vPinOps shows between games, and Visual Pinball’s texture cache — roughly a fifth off most tables. The .directb2s backglass still travels. Whatever imports it will have no wheel art until you fetch media |
Not yet verified — do not rely on these
Section titled “Not yet verified — do not rely on these”- A whole PinUP Popper library through bulk import. A flat directory of tables, backglasses and
ROMs. It should work and has not been run against a real one. ⚠ There is now a community tool
that turns a Popper library into
.vpxzpackages — if you have one, that route is the one we can actually stand behind, because a package imports exactly. - That every placed backglass loads. B2S’s resolution chain is read from source but not yet driven end to end on a test rig.
- Loading an exported
.vpxzon a phone. Export itself is driven — a real table out, and back in through our own importer. Visual Pinball Standalone does ship iOS and Android builds, so the target is real, but we have not put one of our packages on a phone and played it, so we do not claim it.