{"id":13546850,"url":"https://github.com/JHRobotics/patcher9x","last_synced_at":"2025-04-02T19:31:54.300Z","repository":{"id":37337666,"uuid":"494014308","full_name":"JHRobotics/patcher9x","owner":"JHRobotics","description":"Patch for Windows 9x to fix CPU issues","archived":false,"fork":false,"pushed_at":"2024-04-15T20:23:35.000Z","size":823,"stargazers_count":762,"open_issues_count":21,"forks_count":38,"subscribers_count":27,"default_branch":"main","last_synced_at":"2024-11-03T15:38:12.396Z","etag":null,"topics":["patch","virtual-machine","windows-95","windows-98","windows-me"],"latest_commit_sha":null,"homepage":"","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/JHRobotics.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG","contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"ko_fi":"jhrobotics"}},"created_at":"2022-05-19T09:57:19.000Z","updated_at":"2024-11-03T15:28:25.000Z","dependencies_parsed_at":"2024-01-16T17:35:30.437Z","dependency_job_id":"38909e6a-cf54-454d-9fe6-1aea3630f3f6","html_url":"https://github.com/JHRobotics/patcher9x","commit_stats":null,"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JHRobotics%2Fpatcher9x","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JHRobotics%2Fpatcher9x/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JHRobotics%2Fpatcher9x/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JHRobotics%2Fpatcher9x/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/JHRobotics","download_url":"https://codeload.github.com/JHRobotics/patcher9x/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246880058,"owners_count":20848802,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["patch","virtual-machine","windows-95","windows-98","windows-me"],"created_at":"2024-08-01T12:00:46.168Z","updated_at":"2025-04-02T19:31:53.049Z","avatar_url":"https://github.com/JHRobotics.png","language":"C","funding_links":["https://ko-fi.com/jhrobotics"],"categories":["C"],"sub_categories":[],"readme":"# Patch for Windows 95/98/98 SE/Me to fix CPU issues\r\nVirtualization of Microsoft Windows 9x systems is a bit problematic due to 2 major bugs:\r\n[TLB invalidation bug](#patch-for-windows-98me-to-fix-tlb-invalidation-bug) and [CPU speed limit bug](#patch-for-windows-9598-to-fix-cpu-speed-limit-bug).\r\n\r\nThis program contains a set of patches to fix these bugs, and can be booted from a floppy on a virtual machine. It either applies the patch to the installed system, or it patches the installation files in order to create (relatively) bug-free installation media.\r\n\r\n## Patch for Windows 98/Me to fix TLB invalidation bug\r\n\r\nMS Windows 98 won't run on newer CPU (even in a virtual machine) due to the \"TLB invalidation bug\". The bug is described here: https://blog.stuffedcow.net/2015/08/win9x-tlb-invalidation-bug/\r\n\r\n![Bug animation on Windows 98](/doc/shell32.gif)\r\n\r\nIf you want to run a virtual machine without restriction with Windows 98 on AMD Zen 2 and newer (Ryzen 3000+) or Intel Core 11th generation and newer (code names Rocket Lake, Tiger Lake), you probably need this patch.\r\n\r\n## Patch for Windows 95/98 to fix CPU speed limit bug\r\n\r\nWindows 95 and 98 FE (first edition) won't run on any CPU with frequency of ~2GHz and more due to dividing by zero in the CPU speed test. The bug is described and located here: https://www.betaarchive.com/forum/viewtopic.php?t=29224\r\n\r\n![Bug animation on Windows 95](/doc/ndis.gif)\r\n\r\nThere is also an older patch for this bug [FIX95CPU](http://www.tmeeco.eu/9X4EVER/GOODIES/FIX95CPU_V3_FINAL.ZIP), but it's only for Windows 95, doesn't integrate the \"divide by zero\" protection and also it's incrementing the number of cycles in the testing loop only 10 times of original which probably isn't enough for future CPUs. You can test your CPU speed with this command:\r\n\r\n```\r\npatcher9x -cputest\r\n```\r\n\r\n## Requirements\r\n\r\nCurrently supported operation systems:\r\n\r\n- Windows 95\r\n- Windows 98\r\n- Windows 98 SE\r\n- Windows Me\r\n\r\nWindows 95, 98 and 98 SE have the CPU speed limit bug. Windows 98 SE is 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.\r\n\r\nWindows 98, 98 SE and Me have the TLB invalidation bug. The Millennium edition has this bug in the code, but from my observation, the system calls this code very rarely (for example with driver install/system update), so the bug isn't as obvious as in Windows 98. An older version of my patcher program also has a special mode for Windows Me, but in the current version it is no longer needed.\r\n\r\nSome updates install newer version of some files, for example `VMM.VXD`: Q242161 (98 FE), Q288430 (98 SE), ME296773 (Me); `NTKERN.VXD`, `IOS.VXD`, `ESDI_506.PDR`, `SCSIPORT.PDR` and `NDIS.VXD`: Unofficial FIX95CPU. The patcher is compatible with these updates but is required to apply patches again after install. The best way is probably to run patcher from Windows (DOS or 32-bit version) before reboot - Windows 9x does not have any system files protection and you can overwrite system files in the running system. If you do not catch it and the system is rebooted to an error message, you will need to boot from a bootable floppy and start the patcher from it.\r\n\r\n## Updating\r\n\r\nIf you already applied this patch, you don't to need install patcher update - currently all the changes are for the patcher program, the patched code is the same. If you want to overwrite previous patches, you can safely run the patcher again and it automatically determines which files are suitable for patching and which are already patched.\r\n\r\n## Download\r\n\r\nBinary files and bootable floppy image are in [Releases](https://github.com/JHRobotics/patcher9x/releases/)\r\n\r\nIMA file is a bootable floppy (FREEDOS) usable in a virtual machine to simple boot and patch the installed system. Binaries for win32 are Windows 98 compatible, so they can be run from safe mode (Hold CTRL on start-up). Binaries for other systems are for creating patched installation (in theory you can mount virtual HDD image and patch installed system on it, but doing it using boot the floppy is much simpler).\r\n\r\nThe tool has also been packaged for Nix/NixOS:\r\n`$ nix develop nixpkgs#patcher9x`\r\nor\r\n`$ nix-shell -p patcher9x`\r\n\r\n## Installation\r\n\r\nThe simplest way is by downloading bootable floppy image. After booting (you will see `A:\\`), run:\r\n```\r\npatch9x\r\n```\r\nPatch will be run in interactive mode and the default strategy (*patch files, VMM32.VXD will be patched directly*) is probably the best way even for later updates. After rebooting operation system should start successfully.\r\n\r\n![Successfuly working Windows 98 - Intel](/doc/intel-i5-1135.gif)\r\n\r\n![Successfuly working Windows 98 - AMD](/doc/amd-5-3500u.png)\r\n\r\n## Operation modes\r\n\r\n### Interactive mode\r\nThis is default mode, the program asking questions and user answear. You can just double click on EXE (or type `patch9x` to DOS command prompt) and program guide to you in patching process. For Linux build, the help is prinded if no arguments are given (default behaviour for UNIX programs) so you need specify *path*.\r\n\r\n### Automatic mode\r\nSame as interactive but don't ask anything. Can be enabled with `-auto` switch and *path* to CAB files or 9x WINDOWS/SYSTEM directory needs to be specified.\r\n\r\n### Batch mode\r\nIn this mode program operate with single steps. Examples:\r\n\r\nExtract `VMM32.VXD` from instalation media\r\n```\r\npatcher9x --cabs-extract D:\\WIN98 VMM32.VXD\r\n```\r\n\r\nExtract VMM.VXD from VMM32.VXD\r\n```\r\npatcher9x --vxd-extract VMM32.VXD VMM.VXD\r\n```\r\n\r\nPatch individual File\r\n```\r\npatcher9x --patch-tlb VMM.VXD\r\n```\r\n\r\nPatch VXD archive\r\n```\r\npatcher9x --patch-all VMM32.VXD\r\n```\r\n\r\n## Boot floppy\r\nBoot floppy now contain CD driver and few utilities to prepare system disk. If you wish run Windows Installer from boot floppy, add `/NM` switch to `setup.exe` (because of different memory manager, the setup cannot determine real RAM size). Utilities are listed in [boot/info.txt](boot/info.txt).\r\n\r\n## Patching installation media\r\nCopy the content of *win9x* folder (or *win95* - for Windows 95 or *win98* - for Windows 98)\r\nfrom a CD / extract it from an ISO image. Then run: \r\n```\r\npatcher9x /path/to/folder/win98\r\n```\r\nIf the patch is successful, you can copy the modified files back to the image. These are the files marked with the 'N' flag in the patcher output. Or it will be one of these:\r\n- `VMM32.VXD`\r\n- `VMM.VXD`\r\n- `NTKERN.VXD`\r\n- `IOS.VXD`\r\n- `ESDI_506.PDR`\r\n- `SCSIPORT.PDR`\r\n- `NDIS.VXD`\r\n\r\nThe Windows installer primarily takes files from the installation folder and if it can't find them, it'll scan the CAB archives instead.\r\n\r\nFor Windows 95, it is better to patch the installation media, or you will need to install the patch twice - after the first reboot and again after the installation of the network.\r\n\r\n**Please note, that file `VMM32.VXD` from installation IS NOT THE SAME as the file in `Windows/system` folder. Don't interchange them! See the _Patching process_ section to know more about the VMM files.**\r\n\r\n## More informations\r\n\r\nCheck **patcher9x** thread at Vogons: https://www.vogons.org/viewtopic.php?f=24\u0026t=88284\r\n\r\nCheck GPU driver for Windows 9x: https://github.com/JHRobotics/softgpu\r\n\r\n## Build from source\r\n\r\nTo build from source you need:\r\n- GNU C compiler compatible C compiler (minimal version 4.6, MinGW or DJGPP works)\r\n- Flat assembler (https://flatassembler.net/)\r\n- GNU Make (minimal version 3.81)\r\n\r\nTo build the binary for your computer, simply type:\r\n```\r\nmake\r\n```\r\n\r\nTo cross compile, specify the `HOST_CC` and `GUEST_CC` variables to choose compiler, for example cross compiling to 32bit Windows:\r\n```\r\nmake HOST_CC=gcc GUEST_CC=mingw-w64-i686-gcc\r\n```\r\n\r\nTo produce a production binary, add `RELEASE=1` to `make`.\r\n\r\nAfter compiling, you can strip the binary (reduce some space):\r\n```\r\nmake strip\r\n```\r\n\r\nThere is a special profile for DOS cross-compilation -- if you have DJGPP compiler, you can produce the DOS executable this way:\r\n```\r\nmake RELEASE=1 PROFILE=djgpp\r\nmake strip\r\n```\r\n\r\nMinGW compiled programs are linked with `msvcrt.dll` by default. To eliminate this depency (`msvcrt.dll` is missing all Windows 9x versions where isn't IE 4 or better), this project can use my [NOCRT](https://github.com/JHRobotics/nocrt) library. Use `make PROFILE=nocrt` or `make PROFILE=nocrt64` to compile program for Windows with depency only to `kernel32.dll`.\r\n\r\n**Executable file name for most real operation systems is called `patcher9x`. For DOS, it is called `patch9x.exe`  because file names are limited to 8+3 characters.**\r\n\r\n## Patching process\r\n\r\n### TLB invalidation bug patching\r\n\r\nThe patch itself is relatively simple: injecting 2 instructions (`mov ecx,cr3` and `mov cr3,ecx`) to the code in the `VMM.VXD` driver. The patch totally modifies 29 bytes in this file (for Windows 98). \r\n\r\nThe problem is that `VMM.VXD` isn't in a normal state on the HDD. `VMM.VXD` is a part of `VMM32.VXD` which is a compressed archive of several `VXD` drivers. `VMM32.VXD` isn't a generic file -- it is generated by the installer exclusively for your HW configuration.\r\n\r\nThe system for loading drivers first searches in the `SYSTEM\\VMM32` folder, and if the driver isn't there, it will search in the `VMM32.VXD` file.\r\n\r\nIf you want to know more about the code, see file [FlushMappedCacheBlock.asm](vmm/FlushMappedCacheBlock.asm)\r\n\r\n[More info about W3/W4 files](doc/VXDLIB_UTF8.txt)\r\n\r\n### CPU speed limit bug patching\r\n\r\nIn the beginning, I increased the number of cycles of older patches by 8 times (80 times more than the original code and in the case of NDIS.VXD, 100 times more than the original code). I also injected a small \"divide by zero\" protection, which looks like this:\r\n```\r\nVMMcall Get_System_Time ; original - system time (in ms) to EAX\r\nsub eax,esi             ; original - compare with last time in ESI\r\njnz skip_inc            ; new      - skip if result is non-zero\r\n  inc eax               ; new      - increase zero result by one\r\nskip_inc:\r\n```\r\n\r\nThere are two variants of this code - one for `NDIS.VXD` and one for all other system files.\r\n\r\nThe new number of test cycles is now *80 000 000* -- in older patches it was *10 000 000*, but a 4-year-old Ryzen 5 1400 CPU only needs 3 ms to run it through, so if you have a CPU which is 3 times faster[^1] you could have a problem here.\r\n\r\nIf you want to know more about the code, see file [speed.inc](cpuspeed/speed.inc)\r\n\r\n[^1]: Single thread performance in `LOOP` instruction, number of cores, special instructions etc. are irrelevant.\r\n\r\n## Development\r\n\r\nIn future I would like include ~~patch \"CPU speed limit\" (95, 98 FE)~~ and patch 48-bit LBA (95, 98, ME). Memory limit patch I want include too.\r\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FJHRobotics%2Fpatcher9x","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FJHRobotics%2Fpatcher9x","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FJHRobotics%2Fpatcher9x/lists"}