Download on GitHub:
https://github.com/HardCade/hardcade/releases===========================================================================================
CRT-MAME-ARCADE-2D Perceptual Sync 0.168 V1.8
================================================================================================
Development Version December 2025
© 2025 Hardcade Olivier Mileo
===========================================================================================
DESCRIPTION
===============================================================================================================
CRT-MAME-ARCADE-2D Perceptual Sync is a specialized version of MAME 0.168 optimized for 2D arcade gaming on 15 kHz CRT monitors and modern LCD screens running WinXP-32 with an ATI or NVIDIA graphics card and crt_emu drivers or soft15khz.
This edition focuses on minimizing input lag, reducing file size, and improving video synchronization for an authentic arcade experience.
Two complementary CRT synchronization approaches are offered:
→ MANUAL MODE "Perceptual Sync": Precise adjustment of the Slider Refresh Rate to 4 decimal places (±0.0001 Hz) for total timing control. Ideal for purists who want to calibrate each game individually and achieve strictly authentic hardware timing with virtually invisible, fixed tearing.
→ AUTOMATIC MODE "Adaptive Sync" (currently being developed) : VSync DirectDraw Low-Level that automatically adapts to the actual refresh rate of your CRT (like Snes9x/RetroArch). Ultra-smooth scrolling guaranteed regardless of your model (58 Hz, 60 Hz, 61 Hz...), without any manual adjustments required. MAME adjusts its speed to perfectly match your screen.
Choose your approach: absolute manual control or effortless automatic smoothness.
Both methods eliminate screen tearing and guarantee an optimal CRT experience.
// PHILOSOPHY:
Why "CRT-MAME-ARCADE-2D Perceptual Sync" when other emulators like GROOVYMAME already exist?
Whether you're emulating at 15kHz with new or older hardware, the synchronization between the emulation and the display
is never 100% perfect in practice. Even if the modelline is calculated to exactly match the original game's frame rate,
sometimes, even when adhering to the precise values of the MAME video drivers, the timing interpreted by your hardware will be more or less
off from the timing it should actually adopt to be perfectly aligned with the game's timing.
There are always discrepancies (large or small) due to:
- Hardware tolerances (CRT monitor, graphics card)
- Inaccuracies in clocks and oscillators
- Rounding in calculations, operating system
These discrepancies are random depending on your hardware, even if you use THE perfect modelline that mathematically respects
the values imposed by the MAME game system. Despite this, the synchronization drifts more or less over time,
creating that tearing line that "walks" slowly or quickly across the screenit can take several minutes or even tens of
minutes to cross the entire screen. This is generally considered acceptable because:
The line moves so slowly that it's barely noticeable in-game.
It's infinitely better than classic tearing with multiple rapidly moving lines.
Adding V-sync eliminates it at the cost of one frame of input lag, but if our modelline is too far off
the perfect timing, we'll get choppy scrolling. Some users further refine their modellines or slightly adjust
the refresh rate to minimize this phenomenon, but micro-tearing often remains.
Perceptual Sync is the philosophy of a CRT display mode that prioritizes perceived visual stability
(zero mobile tearing, smooth scrolling) rather than the absolute accuracy of the theoretical refresh rate.
It's a CRT display doctrine based on human perception, not mathematical perfection.
Perceptual Sync prioritizes perceived smoothness and image stability on CRTs.
Slight variations in refresh rate (≤0.0001 to 0.5 Hz) are intentionally tolerated to eliminate mobile screen tearing.
🔴 What Perceptual Sync DOES NOT try to do
❌ Be mathematically exact
❌ Be frame perfect
❌ Imitate GroovyMAME
❌ Convince theoretical purists
👉 It stands by its choices.
In other words: What the eye sees is more important than what the numbers say.
// The fundamental principles:
- The refresh rate does NOT need to be exact if a variation of: ±0.0001 to 0.5 Hz (configurable) is tolerated
👉 Result: imperceptibly different refresh rate, stable image.
// Absolute priority on tearing stability:
- Tearing enabled or disabled with Vsync activated
But: fixed, stuck outside the visible area if possible, or always in the same place
👉 Static tearing is psychologically invisible.
/ // No chasing the perfect modelline:
- No dynamic calculations
- No mode creation
- No real-time adjustments
👉 Once the mode is chosen → and the refresh rate slider is fine-tuned, leave it alone!
// The player takes precedence over the timer:
- Emulation respects gameplay
- Not the atomic clock
- No perceptible drift in-game
========================================================================================
MAIN FEATURES
=================================================================================================
INPUT & LATENCE
────────────────
Late Input Polling Reduced input lag
Unbuffered DirectInput Direct polling of device state
Removal of GPU frame queue (D3D9)
VIDEO & SYNCHRONIZATION
────────────────────────
DirectDraw Low-Level VSync Minimal latency on CRTs (Windows XP)
D3D9 Real VSync Eliminates screen tearing at no extra cost
Disabling implicit frameskip Smooth scrolling on CRTs
Automatic rounding
Rate Tick Resolution Optimization
INTERFACE & CONFIGURATION
──────────────────────────
Saved Screen Refresh Rate slider in CFG + precision to 4 decimal places instead of the default 3
Optimized 2D ARCADE Build Lightweight executable (no 3D games, mechanics, casino, mahjong, computer, consoles...)
No OpenGL, No BGFX, No Network support, No MIDI sound, No LUA (Script)
========================================================================================
DETAILED TECHNICAL MODIFICATIONS
==================================================================================== =====
┌─────────────────────────────────────────────────────────────────────────────────────────────────
│ LATE INPUT POLLING
└────────────────── ──────────────────── ─────────────────── ────────────────────
THE DirectInput inputs are polled as late as possible in the frame,
just before video rendering. This avoids using inputs from the previous frame (N-1).
Modified file: src/osd/windows/video.cpp
Function: windows_osd_interface::update(bool skip_redraw)
┌────────────────── ──────────────────── ─────────────────── ────────────────────
│ DIRECTINPUT NO BUFFERED
└────────────────────────────────────────────────────────────────────────────────────────────────
Buffer Disabled DirectInput events (DIPROP_BUFFERSIZE = 0).
Direct reading via GetDeviceState eliminates 1 to 3 ms of latency.
Modified file: src/osd/windows/input.cpp
┌───────────────────────── ──────────────────────────────────────────────────────────
│ DISABLING IMPLICIT FRAMESKIP (CRT)
└────────────────── ──────────────────── ─────────────────── ────────────────────
MAME Version 0.168 applies an internal frameskip even with `frameskip=0` when no video changes are detected. This behavior degrades CRT scrolling.
The implicit frameskip is disabled when `frameskip=0` is explicit.
Compatible with DDraw, Windows XP, and 15 kHz CRTs.
Modified file: src/emu/video.cpp
┌─────────────────────────────── ──────────────────────── ────────────────────────
│ DELETING THE GPU QUEUE FRAME (D3D9)
└────────────────── ──────────────────── ─────────────────── ────────────────────
Configuration D3D9:
SwapEffect = D3DSWAPEFFECT_COPY
BackBufferCount = 1
Result: -1 frame of actual display latency.
Modified file: src/osd/windows/ddrawd3d.cpp
┌──────────────────────── ───────────────────────────────────────────────────────────
│ SLIDER SCREEN REFRESH RATE HIGH PRECISION & SAVE
└───────────────────────────────────────────────────────────────────────────────────────────
Save and Reload Automatic user frequency adjustment in
cfg/[game_name].cfg, with ultra-fine CRT refresh rate tuning down to 0.0001 Hz, display and saving to 4 decimal places.
Key Functions:
Arrow keys only → ±1.0000 Hz
SHIFT + arrow keys → ±0.1000 Hz
ALT + arrow keys → ±0.0010 Hz
SPACE + arrow keys → ±0.0001 Hz
CTRL + arrow keys → ±1.0000 Hz (fast)
Added Functions:
config_load_screen_refresh() src/emu/video.cpp
config_save_screen_refresh() src/emu/video.cpp
Modified Functions:
slider_refresh() src/emu/ui/ui.cpp
Base 10000 to Hz conversion for 4 decimal places
Accurate rounding and saving of CFG to 4 decimal places
Display FPS in 4 decimal places
ui_menu_sliders::handle() src/emu/ui/sliders.cpp
Spacebar handling for ultra-fine increments
slider_init() src/emu/ui/ui.cpp
Slider refresh increment changed to 1 (0.0001 Hz)
Affected files:
src/emu/screen.cpp / screen.h
src/emu/video.cpp
src/emu/ui/ui.cpp
src/emu/ui/sliders.cpp
┌────────────────────────── ───────────────────────── ──────────────────────────
│ D3D9 REAL VSYNC (NO (TEARING)
└─────────────────────────────────────────────────────────────────────────────────────────────
Forces Hardware VSync Real D3D9 (PresentationInterval = D3DPRESENT_INTERVAL_ONE)
Independent of classic MAME VSync. Eliminates screen tearing without CPU overhead.
INI option: crtvsync 0|1
0 Original MAME behavior (default)
1 Hardware D3D9 VSync enabled
Recommended use: 31kHz LCD or CRT monitors (adds ~1 frame of lag on CRTs)
Modified files:
src/osd/windows/winmain.cpp
src/osd/windows/video.h / video.cpp
src/osd/windows/ddrawd3d.cpp
┌────────────────── ──────────────────── ─────────────────── ────────────────────
│ DIRECTDRAW LOW-LEVEL VSYNC (CRT) V3
└────────────────── ──────────────────── ─────────────────── ────────────────────
Low level DirectDraw VSync mode For 15 kHz CRT monitors under Windows XP.
Direct rendering in the primary surface synchronized to the Vertical Blank.
INI Option: ddraw_lowlevel_vsync 0|1
0 Classic MAME behavior (default)
1 Low-level DirectDraw VSync
⚠ Only active if waitvsync = 0
⚠ Automatically disabled if triple buffering is enabled
Functionality:
1. Waits for the VBL via WaitForVerticalBlank(DDWAITVB_BLOCKEND)
2. Direct lock of the primary surface
3. Scans primitives (blending/alpha detection)
4. Renders membuffer or direct as needed
5. Controlled copy of membuffer → primary surface
6. Unlocks and bypasses MAME blit
7. Completely disables MAME throttling (update_throttle bypass)
Automatic synchronization like Snes9x:
MAME automatically adapts to the actual CRT refresh rate
Works with ANY modeline (58 Hz, 60 Hz, 61 Hz...)
The VBlank CRT dictates the timing → always smooth scrolling
No need to manually adjust the refresh rate slider
The emulation speed adjusts to match the screen refresh rate
Example:
Native CPS2 game: 59.637 Hz
Modeline CRT: 60.000 Hz
→ MAME runs at 60 Hz (100.6% speed) → perfectly smooth scrolling
Native CPS2 game: 59.637 Hz
Modeline CRT: 58.000 Hz
→ MAME runs at 58 Hz (97.3% speed) → perfectly smooth scrolling
Supported formats:
8-bit, 16-bit, and 32-bit formats
Full blending and alpha effects
32-bit RGB (0x00ff0000) 16-bit 565 (0xf800), 15-bit 555 (0x7c00)
Handling of lost areas (Alt+Tab)
GPU Compatibility (Windows XP):
✓ Excellent: NVIDIA TNT/GeForce 2/3/4/FX, ATI Radeon 7000-9800,
Matrox G200/G400/G450/G550
~ Partial: Intel iGPU i815/i845/i865 (emulated VBL)
✗ Not tested: Vista+ / WDDM Drivers
Result:
Latency reduced by approximately 1 frame
Automatic perfect CRT synchronization (Snes9x/RetroArch type)
Zero tearing, ultra-smooth scrolling regardless of the modeline
No need to manually fine-tune each game
Modified Files:
src/osd/modules/render/drawdd.cpp
src/emu/video.cpp (update_throttle bypass)
src/emu/emuopts.cpp / emuopts.h
┌────────────────── ──────────────────── ─────────────────── ────────────────────
│ OPTIMIZED 2D BUILD CLEANING ARCADE.LST
└──────────────────────────────────────────────────────────────────────────────────────────
Light version Specialized for classic 2D arcade games on 15 kHz CRT monitors.
Systems removed:
✗ All 3D games (Model 2/3, Naomi, Taito Type X, etc.)
✗ Casino systems (slot machines, video poker)
✗ Mahjong games
✗ Non-arcade "machine" systems (computers, consoles)
✗ Mechanical game systems, etc.
Supported systems (2D only):
✓ Capcom CPS1/CPS2/CPS3
✓ Neo Geo MVS
✓ Konami (GX, Classic)
✓ Sega System 16/18/24
✓ Taito (F2, F3)
✓ Cave (CV1000, PGM)
✓ Irem M72/M92
✓ Toaplan, Psikyo, Data East
✓ Namco System 1/2
✓ 8-bit classics (Pac-Man, Donkey Kong, Galaga, etc.)
Result: Smaller executable, faster compilation, targeted 2D CRT list.
Modified file: src/mame/arcade.lst
┌──────────────────────────── ──────────────────────── ─────────────────────────
│ DISABLING UI LUA
└──────────────────────────────────────────────────────────────────────────────────────────
Lua's periodic call The `periodic_check` and `frame_hook` lines are now commented out to avoid any impact on performance or menus.
======================================================================================
COMPATIBILITY
=================================================================================================
OS: Windows XP / 7 / 8 / 10
Renderers: DDraw (XP), D3D9, GDI
Monitors: 15 kHz CRT, 31 kHz LCD
=======================================================================================
CREDITS
============================================================================================================
Development: Olivier Mileo
Project: CRT-MAME ARCADE-2D 0.168 Edition
Base: MAME 0.168
© 2025 Hardcade All rights reserved
=========================================================================================
Download on GitHub:
https://github.com/HardCade/hardcade/releases