I Built a Custom Sega CD FMV Codec: 320×224 Fullscreen Video at 30 FPS

CAVC is an open-source FMV codec built from scratch for unmodified Sega CD hardware, delivering 320×224 fullscreen video at 30 FPS with 22.05 kHz audio.

I built a custom FMV codec from scratch for the Mega-CD (known as the Sega CD outside Japan). It can play 320×224 fullscreen video at 30 FPS with 22.05 kHz audio, and it runs on unmodified hardware. The source code is available too. This was, of course, AI-agentic coding—thanks, 5-6.Sol and Fable.

Classic Sega CD FMV often means a small window, a low frame rate, and heavily compressed audio. I wanted to find out how far the original hardware could be pushed if I aimed for fullscreen 30 FPS. That simple question was the motivation.

The codec is called CAVC—short for Constraint-Aware Video Codec. It is designed around the constraints that matter on real hardware: the two 68000 CPUs across the Genesis/Mega Drive and Sega CD, the split RAM architecture, available DMA bandwidth, and the strict 150 KiB/s bandwidth limit of the 1× CD-ROM drive.

The best way to see the result is to watch it. I used the Sonic Jam opening as the main comparison and included a capture from real hardware.

Main comparison: Sonic Jam opening

What the Main Comparison Shows

The split-screen comparison plays four sources at once:

  • CAVC playback in Genesis Plus GX, shown in the largest panel
  • The source footage from the TrueMotion AVI included in the Sega Saturn version of Sonic Jam
  • The original Sega CD version for comparison
  • A real-hardware capture from an actual Japanese Mega Drive 2 and Mega-CD 2

The fourth panel is the one I cared about most. I did not want to stop at “it runs in an emulator”; I fed the same stream to real hardware and verified that it played back there as well. If that part failed, the whole project would have been a theoretical exercise.

The original Sonic Jam source video is 288×200.

CAVC Specifications

  • Resolution: Up to 320×224 in H40 mode, filling the full active display area
  • Frame rate: 30 FPS, with 15 FPS and 24 FPS also supported
  • Audio: 22.05 kHz ADPCM
  • Color: Dynamic palette switching during playback
  • Target hardware: Unmodified Sega CD / Mega-CD hardware

Additional Footage

Beyond the main comparison, I prepared several other videos. Each one is embedded here so you can watch it without leaving the article.

Sonic Jam Opening — 288×200 at 30 FPS

For Sonic Jam, there is a detailed visual analysis and encoding breakdown, followed by a standalone Genesis Plus GX capture.

Sonic Jam: visual analysis and encoding breakdown
Sonic Jam: standalone Genesis Plus GX footage

Bad Apple!! — 320×224 Fullscreen at 30 FPS

Bad Apple!! is played at 320×224 fullscreen and 30 FPS. These are the comparison, analysis, and standalone emulator videos.

Bad Apple!!: comparison
Bad Apple!!: analysis
Bad Apple!!: Genesis Plus GX footage

Lunar: The Silver Star Opening — 320×224 Fullscreen at 24 FPS

CAVC can also take advantage of the Genesis VDP’s hardware scrolling. This is especially effective in scenes with sustained horizontal camera movement, such as the opening of Lunar: The Silver Star. Instead of redrawing the entire screen every frame, the codec can scroll the existing image with the VDP, reducing the amount of new visual data that must be transferred. The final fade-out is handled with palette fading instead of re-encoding the image for each brightness step.

Lunar: The Silver Star — comparison
Lunar: The Silver Star — analysis
Lunar: The Silver Star — emulator footage

Tears of Steel — 320×168 Live Action at 24 FPS

Live-action footage is especially challenging, but I think the result remains reasonably watchable.

Tears of Steel: comparison
Tears of Steel: analysis
Tears of Steel: emulator footage

Source Code

The encoder is written in Python, while the player that runs on the console is written in 68000 assembly. The repository also includes tools for generating analysis videos, so you can inspect the decisions being made as each image is assembled.

GitHub repository: akiyan/segacd-fmv-cavc

This is the English version of my original Japanese article. I also shared a shorter write-up on Reddit.

If you have any thoughts or questions, feel free to reach out to @akiyan.