# patcher9x fixes the CPU bugs that stop Windows 9x from running on modern hardware

> patcher9x is a floppy bootable patcher for Windows 3.11, 95, 98, 98 SE and Me that fixes the TLB invalidation bug, the divide by zero CPU speed test, the 512 MB memory ceiling, dirty control registers and the 4G resource bug. It can patch a running installation or the installation files themselves, and it is written in C with a DOS build profile.

**JHRobotics/patcher9x** — Patch for Windows 9x to fix CPU issues

- Repository: https://github.com/JHRobotics/patcher9x
- Stars: 1,235 · Forks: 58
- Language: C
- License: MIT
- Published: 2026-10-19 · Updated: 2026-10-19 · Language: en
- Canonical page: https://hysenlabs.com/projects/jhrobotics-patcher9x

## Four old bugs and one bootable patch

patcher9x is a patch for Windows 3.11, 95, 98, 98 SE and Me to fix CPU issues, and the readme frames it as a set of patches for the specific problems that make virtualising those systems difficult.

There are four of them. The TLB invalidation bug, the CPU speed limit bug, the issues with the memory limit, and the dirty control registers. The 4G resource patch is a fifth entry in the readme with its own section.

The delivery mechanism is unusual and worth understanding before anything else. The program contains the patches and can be booted from a floppy disk on a virtual machine. From there it can either apply the patch to the already installed system, or patch the installation files to create, in the readme's words, relatively bug-free installation media.

So there are two workflows. The first is a live patch of a running installation, which is what you want when you already have a machine and want it to boot. The second is patching the media before you install, which produces an installation that never had the bug in the first place, and which is the better answer when you are building a disk image for a virtual machine that other people will use.

The implementation is C, the licence is MIT, the default branch is main, and the last push was on 2026-05-03 with the most recent release v0.9.91 on 2025-12-22.

## The TLB invalidation bug is the one that stops a boot

The TLB invalidation section is first in the readme, and it is the failure that matters most for a virtual machine on current hardware.

MS Windows 98 may not run on newer CPUs, even in a virtual machine, due to the TLB invalidation bug, and the readme links to a description of it on the Stuffed Cow blog. There is an animation in the documentation showing the bug on Windows 98.

The practical statement is in the next paragraph. If you want to run a virtual machine without restrictions with Windows 98 on AMD Zen 2 and newer, the Ryzen 3000 and later, or on Intel Core 11th generation and newer, the code names Rocket Lake and Tiger Lake, you likely need this patch.

The word likely is doing work, and so is the age of the list. Zen 2 and Rocket Lake are the thresholds the readme names, but the underlying cause is in the CPU's translation lookaside buffer handling, and the list of affected generations in 2026 is longer than the readme enumerates. What has not changed is the symptom, which is a machine that hangs or refuses to start rather than a subtle error.

The patcher is also the reason the floppy image matters. A patch has to be applied to files inside a running operating system, and doing that from a modern shell is not possible, so the tool has to run in the same environment as the system it is repairing.

## The CPU speed test divides by zero on a fast processor

The second bug is stranger and produces a stranger symptom.

Windows 95 and 98 FE, the first edition, will not run on any CPU with a frequency of about 2 GHz and more, because of a dividing by zero in the CPU speed test. The readme links to a forum thread where the bug is described and located, and there is an animation of it on Windows 95.

The cause is a timing loop that assumes a particular number of clock cycles per instruction and divides by the difference. On a processor that is much faster than the assumption, the difference goes to zero and the machine divides by it.

The readme compares the patch with an older one, FIX95CPU, and the comparison is instructive. That older patch is only for Windows 95, it does not integrate the divide by zero protection, and it increments the number of cycles in the testing loop only ten times of the original, which the author thinks is probably not enough for future CPUs.

The patcher ships its own CPU test so you can check before you patch.

```bash
patcher9x -cputest
```

That is the sensible first command to run on a machine that will not boot, since it tells you whether the speed test is going to fail on this particular processor.

## The memory ceiling, PATCHMEM and the 16 MB option

Windows 9x cannot reliably work with more than about 512 MB of RAM, and the readme explains the mechanism rather than just stating the number.

There is no strict barrier, but bugs in the FAT driver, VCACHE.VXD, cause more memory to result in the cache not fitting into system memory space, overwriting the memory of other drivers. With more RAM, the chance of hitting something important increases. There are also a few other bugs in the VMM.VXD loader and in VMM32.VXD itself.

The patch is a simple integration of Rudolph Loew's PATCHMEM. The reason the ceiling matters in a virtual machine is specific: normally 512 MB is enough for old hardware, but the design of virtual machine GPU adapters means you need at least 1 GB of RAM for 3D acceleration to work properly. So you cannot simply give the guest less memory, and on bare metal you cannot reduce it either, because smaller RAM modules are not available.

There is a second patch in the same family, called Load VXD above 16 MB, because some drivers need free space in the first 16 MB, and the system itself uses space there for memory tables. Increasing RAM does not help, because more memory means larger tables and therefore less free space. The patch frees some space below 16 MB by loading drivers above that point.

It is not enabled by default, and it is selected by name.

```bash
patcher9x -select default,16m
```

The same selection works from DOS, with the shorter name.

```bash
patch9x -select default,16m
```

There is also a shorter equivalent, described as the PATCHMEM compatible form.

```bash
patcher9x -m
```

And the patch can be applied on its own, or removed on its own.

```bash
patcher9x -select 16m
```

```bash
patcher9x -reverse -select 16m
```

That last form is the one to keep in your notes, because an uninstall is what you need when a patch is the thing causing a new problem.

## Control registers and the 4G resource bug

The dirty control registry patch and the 4G resource patch are smaller, but they produce the two most alarming failure messages on a modern machine.

The first is about BIOSes that do not sufficiently reset the CPU control registers, CR0 and CR2 to CR4, and the MSR registers. That can lead to a protection error message on system load. The patch works the same way as CREGFIX, but it is integrated into win.com.

The safety condition is stated and it is not obvious. It only works when the system is loaded from real mode. When you are using a DOS memory manager it is very dangerous to simply reset control registers, so when win.com is loaded in V86 mode the patch does not touch anything. When using a memory manager you need to run the original cregfix.com before the memory manager is loaded.

The 4G resource patch is about the BIOS memory map. When the system queries for reserved memory space, it assumes the results from the BIOS calls, with EAX set to 0E820h and INT 15h, are sorted. It also stops when it reaches a region with an address larger than 32 bits. Due to a nobody cares bug, results from many BIOSes are not sorted, and when the system reaches a region above the 32-bit address it stops processing the results and ignores all the following regions.

The consequence is that some I/O space can be used as regular RAM, and writes to that location are likely to be disastrous. The patch fixes the stop at the region address. The original patch was made by SweetLow, and the readme links a description of the problem with the resource manager on newer BIOSes.

## Which release has which bug, and why it matters

The Requirements section is unusually precise about which bug is where, and that precision is the practical content of the project.

The supported operating systems are Windows 3.11, Windows 95, Windows 98, Windows 98 SE and Windows Me.

Windows 3.11 has the CPU speed limit bug in NDIS.386, which prevents startup when networking is enabled, although it is still possible to start up with win /n. So on 3.11 the bug is dormant unless you want the network stack.

Windows 95, 98 and 98 SE have the CPU speed limit bug. Windows 98 SE is called out as a special case because it has divide by zero protection, but it also has a short loop test, so its timing information is probably useless and could potentially lead to other bugs. In other words, 98 SE does not crash, but it may report the wrong speed, and the patcher is still the answer for the TLB bug.

Windows 98, 98 SE and Me have the TLB invalidation bug. The Millennium edition has the bug in the code, but the author observes that the system calls this code very rarely, for example with a driver install or a system update, so the bug is not as obvious as in Windows 98. An older version of the patcher had a special mode for Windows Me, and in the current version it is no longer needed.

That last detail is a small measure of how well the project is maintained. The Me specific code path was removed once the author established that the general patch covered it.

## Updates overwrite the patches, and the tree shows how it is built

Two operational points close the picture, and both will bite you at the worst moment if you do not know about them.

The first is that some updates install newer versions of the same files the patcher modifies. The list includes VMM.VXD, with Q242161 for 98 FE, Q288430 for 98 SE and ME296773 for Me, and NTKERN.VXD, IOS.VXD, ESDI_506.PDR, SCSIPORT.PDR and NDIS.VXD, the last group from the unofficial FIX95CPU. The patcher is compatible with these updates but is required to apply the patches again after the install.

The recommended timing is worth following. The best way is probably to run the patcher from Windows, the DOS or 32-bit version, before reboot, because Windows 9x does not have any system file protection and you can overwrite system files in the running system. If you miss the window and the system reboots to an error message, you have to boot from a bootable floppy and start the patcher from it.

The second point is how the build works. The Makefile compiles two binaries, a host version and a guest version, and the guest one is built for DOS. A djgpp profile swaps the compiler for i586-pc-msdosdjgpp-gcc and renames the output to patch9x.exe, while a nocrt profile builds without the C runtime, linking against kernel32 and user32 instead, with -nostdlib and -nodefaultlibs. The FASM assembler is used for the boot sector, and there is a boot/ directory for it and a builder/ directory for the image construction.

The patch variants are checked in as headers, cpuspeed_patch_v1 through v8 and the ndis variants, and the vmm/ directory holds the VMM patches with several generations for different Windows releases. The g4resfix/, rloew/, crfix/ and pe/ directories hold the imported work, and mspack/ is the compression library.

Releases are frequent, with v0.9.91, v0.9.90 and v0.9.88 in the last months of 2025.

## Conclusion

Adopt patcher9x when you run Windows 9x as a guest in a virtual machine or on bare metal and the CPU is too new for the operating system to handle, since the TLB invalidation and divide by zero bugs are the difference between a boot and no boot. Do not adopt it as a general purpose Windows fix, because it targets specific old releases and specific driver files. Verify first which of the four bugs your machine actually hits, since the readme states that Windows 98 SE has divide by zero protection but a short loop test whose timing information is probably useless, and check whether an update such as Q242161 has replaced VMM.VXD under your installation, in which case the patch has to be applied again.

## FAQ

### What does patcher9x do?

It is a set of patches for Windows 3.11, 95, 98, 98 SE and Me that fix the TLB invalidation bug, the CPU speed limit divide by zero, the memory limit issues, dirty control registers and the 4G resource bug. It can be booted from a floppy disk and can patch either an installed system or the installation files.

### Why does Windows 98 fail to run on a modern CPU?

Because of the TLB invalidation bug, which the readme says may prevent Windows 98 from running on newer CPUs even in a virtual machine. The readme names AMD Zen 2 and newer, the Ryzen 3000 and later, and Intel Core 11th generation and newer, the Rocket Lake and Tiger Lake generations, as the thresholds where you likely need the patch.

### How do I check whether the CPU speed test will fail?

Run patcher9x -cputest. The bug is a divide by zero in the CPU speed test that stops Windows 95 and Windows 98 FE from running on any CPU of about 2 GHz and faster.

### How do I enable the patch that loads VXD drivers above 16 MB?

Run patcher9x -select default,16m, or the shorter PATCHMEM compatible form patcher9x -m. From DOS the command is patch9x -select default,16m. The patch can be applied alone with patcher9x -select 16m and removed with patcher9x -reverse -select 16m.

### Does patcher9x support Windows Me?

Yes, Windows Me is listed as supported. It has the TLB invalidation bug in the code, but the author observes the system calls that code very rarely, so the bug is less obvious than in Windows 98, and an older version of the patcher had a Me specific mode that the current version no longer needs.

### Do Windows updates overwrite the patcher9x patches?

Some updates install newer versions of the files the patcher modifies, including VMM.VXD with Q242161, Q288430 and ME296773, and several other drivers. The patcher stays compatible but the patches have to be applied again after such an install, ideally by running it from Windows before rebooting.

## Sources

- [Issues](https://github.com/JHRobotics/patcher9x/issues)
- [JHRobotics/patcher9x on GitHub](https://github.com/JHRobotics/patcher9x)
- [License: MIT](https://github.com/JHRobotics/patcher9x/blob/main/LICENSE)
- [README](https://github.com/JHRobotics/patcher9x/blob/main/README.md)
- [Releases](https://github.com/JHRobotics/patcher9x/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/jhrobotics-patcher9x
