I remember these old Czech Čtyřlístek games from my childhood, when they showed up as part of Nesquik cereal promotions. My brother and I used to play them together, and years later I wanted to see whether my son could play them too. That quickly turned into a practical problem. My personal machines run Linux or macOS, and when I tried using a Windows 11 computer from work, that did not run them either.
If you are not Czech, Čtyřlístek is a long-running Czech comics series for kids. Over time it also spawned a line of PC CD-ROM games, and that is the corner of it I wanted to revive here.
There are approximately 20 games in that broader series, but I deliberately narrowed this project to three titles I found in my drawer on CDs:
- Čtyřlístek: Zítra se bude tapetovat (
tapetovat) - Čtyřlístek: Sami doma (
sami) - Čtyřlístek: Silák Bobík (
silak)
The short names are the labels I used in scripts, logs, and runtime tooling. They are easier to work with than the full game titles when building images, patching files, and switching between test runs.
This post is the technical story of what failed, what finally worked, and what still needs improvement.
TL;DR
- Windows 11 compatibility mode was not reliable enough.
- Windows XP in UTM was not able to run DirectX.
- Full browser emulation with
v86proved the UX idea, but performance was too poor for actual play. - The workable setup became Docker + Wine + Xvnc + noVNC, with a small control layer around it.
- All three games now launch in a browser, but video streaming performance is still the main constraint.
Screenshot placeholder: project overview / launcher screen. Suggested shot: the browser UI listing
tapetovat,sami, andsilak, with launch controls and current status visible.
The Goal
- Get all three games to launch reliably.
- Avoid depending on a dedicated legacy Windows machine.
- Make the games accessible through a browser for fast sharing and testing.
- Keep the setup reproducible enough to reuse for other Čtyřlístek titles later.
In practice, each game exposed different legacy assumptions around installation flow, filesystem layout, codecs, and DirectX-era behavior.
Attempt 1: Running Them on Windows 11
The first attempt was the obvious one: run the original media directly on Windows 11 on laptop I have.
I was able to install games just fine but they crashed on startup even with different compatibility mode settings. So I have abbandoned the idea.
Attempt 2: UTM + Windows XP
The next step was a virtualized Windows XP environment in UTM. On paper, that sounds like the right answer: period-correct operating system, period-correct software expectations.
But I have found out in a hard way after 1.5 hours tinkering with UTM and installing Win XP that UTM does not support DirectX which the games need.
Attempt 3: Full Browser Emulation with v86
After that I moved to a browser-first direction using v86 project. I build a Linux i386 root filesystem, run Wine inside emulated x86, exposed a web UI for booting and launching games.
This stage mattered because it proved the shape of the final experience:
- the browser UX made sense,
- game selection and diagnostics were workable,
- the whole flow could be shared and reproduced remotely.
But it was painful to do any kind of debug of optimization since I had to wait long times to build it and test it. It was useful as a prototype, not as the final way to play the games.
Attempt 4: Docker + Wine + Xvnc + noVNC
The practical solution ended up being:
- run Wine natively inside Docker using a
linux/386image, - render through Xvnc,
- stream the desktop to the browser through noVNC,
- add a small API/control layer for launch, stop, status, and audio handling.
The important architectural shift was simple: drop the heavy full-CPU emulation layer, but keep browser access. I was able to sort out issues with missing fonts, playing old avi videos used in game, issues with sounds, etc. More on that later.
Screenshot placeholder: architecture or runtime view. Suggested shot: either a simple diagram of Docker -> Wine -> Xvnc -> noVNC, or a live browser session with one game already running.
Runtime and Path Problems Solved Along the Way
Some of the hardest problems were not about emulation at all. They were just environment mismatches:
- path assumptions such as
C:\runtime-*andC:\Program Files\..., so I added aliases and symlinks, - stale processes when switching between games, so stop and cleanup behavior had to become stricter,
- font and
ddrawedge cases, so the Wine setup and launch defaults needed hardening.
These changes made launch behavior much more predictable across all three titles.
The CPSE + AVI Rabbit Hole
The nastiest issue was menu AVI playback in sami and silak, with errors such as:
CPSE: Stream open file failedCan't create multimedia stream instance- DirectShow graph failure
RenderEx -> 0x80040218
This legacy AMStream path remained unreliable in the current environment, even with normalized or simplified test clips. The practical fix was to patch the runtime executables and disable menu_*.avi references for known builds. That bypassed the crashing menu-video path and made the games playable again.
That is not perfect from a preservation point of view, but it is the right tradeoff from a "works now, reproducibly" point of view.
Screenshot placeholder: failure analysis or debugging evidence. Suggested shot: a side-by-side of the broken menu-video behavior, or a terminal/log view showing the
CPSE/ DirectShow failure during investigation.
Performance and Current State
Once the games were functionally running, the main problem stopped being compatibility and became responsiveness. At that point the work shifted from "can this game start at all?" to "can this feel reasonably playable in a browser?"
Most of the effort went into reducing delay and smoothing out the stream. I moved the audio path to an AudioWorklet-first approach, added a bounded low-latency jitter buffer, reduced audio chunk burst size on the relay path, and tuned the VNC defaults for localhost use. I also improved the metrics HUD so I could actually see what was happening during a run instead of guessing from feel alone.
That got the project into a much better state than the earlier versions. All three games now launch from the browser, the installer path is bypassed, audio latency is noticeably better, and the menu AVI crash blocker is worked around. The remaining weak spot is video delivery: under load the stream is still visibly choppy, currently somewhere in the low-20 FPS range. So the honest summary is that the project is now functional and usable, but still clearly performance-constrained.
Screenshot placeholder: current playable result. Suggested shot: one of the games running in-browser with the performance/metrics overlay visible, so the reader can see both the result and the remaining limitation.
Conclusion
There is still room to improve the technical side of this setup. I can probably get more out of the streaming path by tuning ddraw modes per game, cutting more render and encode overhead, or eventually replacing noVNC transport with something more efficient. But that is no longer the main point.
The main milestone is already there: these old Czech games are playable again in a modern browser workflow. More importantly, they are no longer just a preservation experiment sitting on my machine. My son and I actually play them now.
At this point, the hardest obstacle is no longer Wine, DirectShow, Docker, or streaming latency. It is teaching him how to control the game with a mouse, because until now he has only really played games on a mobile phone. That is a much better kind of problem to have.