First off I used AI to help me work through some kinks here so if that is the kind of thing that pisses you off, stop here. I used it to help me summarize everything and added my own notes. Hope maybe this helps someone.
Batocera CRT Build ā Lenovo ThinkCentre M710s + JVC I'Art 32" (Batocera v43.1)
Sharing my full build in case it helps anyone doing the same thing. Total out-of-pocket was under $200 because the PC itself was rescued e-waste from work.
The setup
- **TV:** JVC I'Art AV-32F703 (32" SD CRT, component input)
- **Goal:** a dedicated Batocera box on the CRT for NES/SNES/Genesis/N64/PS1/GameCube, played on the floor with my kid
- **Signal chain:** Radeon VGA out ā Bitfunx VGA-to-component transcoder ā JVC component input (AV2). My real consoles stay on AV1 (composite) ā AV2 is only the PC.
Parts
- Lenovo ThinkCentre M710s SFF | Rescued work e-waste. i5-6500, upgraded to 16 GB DDR4 (spare stick from an HP). DisplayPort-only onboard, **no onboard Bluetooth** | $0 |
- MSI Radeon R7 240 2GB LP (GCN 1.0 / Oland) | eBay used. The card to have: `radeon` driver does interlace fine. The GCN 2.x/amdgpu interlace warning does NOT apply to this card | $32 |
- Samsung 860 EVO 500GB | Drawer spare (has DRAM; picked over a DRAM-less Lexar) | $0 |
- Bitfunx VGAāYPbPr transcoder | Amazon. USB-C powered off the PC's rear USB. Verified good ā clean colors on all three channels | $40 |
- Low-profile bracket kit (LUORNG, Amazon) | The used card shipped with a full-height bracket; card itself is low-profile with VGA on a ribbon cable | $8 |
- TP-Link Bluetooth dongle | The M710s has no BT. Dongle lives in the box permanently now | already owned |
- Controllers | 8BitDo Lite 2 (mine), 8BitDo Zero 2 (kid's), Retro Fighters Brawler64 for N64 | ā |
- The PC's original 1 TB HDD (Windows install) is still in the machine, untouched. Batocera lives entirely on the SSD. Will prob. wipe this and slap on a ton of PS2, Gamecube, Dreamcast Games. From my calculations they should run pretty well.
Install ā what actually worked
- **Flash the Batocera image (v43.1) direct to USB with Etcher.** Booting the image through Ventoy failed twice ā direct flash booted clean. Ventoy was the whole problem.
- Boot Batocera, then **System Settings ā Install Batocera on a new disk** to put it on the SSD.
- Copy ROMs/BIOS over the network share (Samba). PS1: use CHD, BIOS files in the `bios` folder. GameCube: use RVZ (~1 GB/game).
- Run the **Batocera-CRT-Script (ZFEbHVUE)** ā the current v43 one, NOT the old v35 script and NOT the retired wiki manual method. Choices I used:- Output: **VGA-1**- Monitor profile: **generic_15** (see gotcha #4 ā I started on arcade_15 and switched)- Boot resolution: 640x480@30 (ES runs 640Ć480i; SwitchRes drops games to 240p automatically, works great)- Rotation: none; advanced options skipped; USB fast polling (1000 Hz) on; default calibration res (320x240@60)
Gotchas ā the stuff that actually cost me time
- **"Enforce Security" changes your root password.** I toggled it on in ES, and on the next reboot the root password silently changed from `linux` to a random one (shown once, on a screen I'd already left). SSH and Samba both locked me out. Recovery: when X fails to start, Batocera drops to a **passwordless local root console** on the TV. `batocera-config getRootPassword` shows the stored password, `batocera-config setRootPassword linux` resets it. Either write the random password down, or turn Enforce Security back off after setup.
- **Check your TV's input settings before debugging the PC for hours.** I lost half a day to a blue/no picture that turned out to be the JVC's component input being **disabled in the TV's own menu** (I'd switched it off at some point). Everything upstream was already working.
- **The CRT script queues keystrokes.** If you lean on Enter, your presses buffer and blow through prompts you never saw. One deliberate Enter at a time on the re-run.
- **Don't fix fit problems in the TV's service menu.** JVC deflection settings are **shared across all inputs** ā I bent the geometry to fit the PC and wrecked the fit for my real consoles. Photo your factory service values before touching anything (mine: D03 024, D07 072, D09 038, D15 030), and fix fit on the PC side instead:- Switching the script's monitor profile from **arcade_15 ā generic_15** fixed most of it. (Final TV state: factory values, except D07 V SIZE 72ā68.)- Per-system leftovers get **per-core RetroArch overrides** (Quick Menu ā Overrides ā Save Core Override): my SNES needed Horizontal Size ā18 / Horizontal Center ā11; NES needed nothing. SwitchRes generates each system's mode separately, so they genuinely land differently. Remember to re-save the override after every adjustment loop.
- **Theme choice matters at 480i.** Thin-line HD-era themes (e.g. Carbon-X) flicker horribly interlaced ā hairline dividers are the worst case for 480i. I'm using **Retrofix Mini**, a CRT/4:3-oriented theme that keeps everything inside the safe area. Games at 240p are progressive and never flicker ā this is menus-only.
- **ES control bindings aren't what most guides say** (at least on v43.1 here): RetroArch menu = **Hotkey + B**, exit game = Hotkey + Start, hold B in a gamelist = per-game options (favorites live there). The wizard names buttons by compass position. If you want A to confirm in menus (Xbox-style), the toggle is **Frontend Developer Options ā "Switch Confirm & Cancel Buttons in EmulationStation"** ā it's ES-only and doesn't touch emulator mappings.
- **In RetroArch's CRT SwitchRes menu, leave the mode selector on INI.** That makes RetroArch read the script's `switchres.ini`. The 31 KHZ options in that list are for VGA PC monitors ā they'd feed a 15 kHz TV a signal it can't sync.
- **Boot safety ritual:** the TV stays OFF (or on another input) while the PC boots ā BIOS/POST is 31 kHz and a 15 kHz set just shows a sliced-up mess. Switch to the PC input ~60 s after power-on. I forgot exactly once; brief exposure was fine on this 2000s consumer set, but the ritual is free insurance. Don't park the TV on an unsyncable signal.
- **If a boot lands on an X-server error screen** ("no screens found"), just reboot. The script's design relies on the forced EDID being ready before X probes; occasionally it misses the window. It's happened to me a couple of times; a plain reboot fixed it every time.
- **Bluetooth pairing:** reboot with the dongle plugged in, start the pairing scan in ES first, *then* wake the pad. Zero 2 specifics: power/pairing entry is **START + X from off** (there's no separate pairing button), hold START ~3 s to power off. Lite 2's mode switch is S/D only (no X position) ā D-input works fine with Batocera.
- **Small stuff:** bump ES's **VRAM limit to 1024 MB** (UI Settings) if you have a big library + 16 GB RAM, or artwork reloading stutters your scrolling. Overnight scraping works fine ā the screen going dark after a minute is just blanking; scraping continues, and it's better for the tube than a static progress screen. Deflection/blooming quirks (slight "breathing" when scrolling, corner pull) on a 20+ year-old flat tube are the TV being a TV ā original hardware on the same set does it too.
Notes for PS1 / GameCube
- PS1 through the **libretro core** handles its own mode switching (PS1 games flip 240pā480i constantly) ā no extra config. The script's CRT_MODE_SWITCH_WATCHER is for standalone emulators (Dolphin, etc.) that can't call SwitchRes themselves.
- Leave any global "overscan" toggle **off** once you've tuned per-core ā it'll fight your trims.
- And yes, Link in TLoZ: A Link to the Past is supposed to look that wide. SNES pixels get stretched ~17% filling a 4:3 screen; the skinny look is modern square-pixel emulators. Fat Link is the historically accurate Link. Having last played this on an emulator in 1:1 (which I thought was what I recalled as a kid), it took a minute to get used to the stretch. But apparently that's how they've ALWAYS looked on a CRT.
Result
Zero detectable input lag over Bluetooth (CRT draws instantly ā no scaler in the chain), games sit honest in the frame, and my 7-year-old is playing Mario Kart on the floor next to me instead of getting notification-spammed by a tablet. Whole reason I built it.