Click here to Skip to main content
15,745,737 members
Articles / Programming Languages / XML
Technical Blog
Posted 5 Apr 2023

Tagged as


12 bookmarked

Exploring PCx86, an IBM PC Emulator Written in JavaScript

Rate me:
Please Sign up or sign in to vote.
5.00/5 (9 votes)
13 May 2023CPOL4 min read
Exploring PCx86 - IBM PC emulator written in JavaScript
In this post, we explore an IBM PC emulator written in JavaScript - PCx86.

I came across PCjs, a JavaScript-based emulator that supports many different vintage computer architectures and spent last week setting up my first web-based PC XT and PC AT emulators with it. Starting with the examples available on PCjs github repository, I copied the required XML, CSS, XSL and JS files to my project and used the following HTML code:

		<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
		<title> | /apps/pcx86/examples/example1.html</title>
		<meta charset="utf-8">
		<link rel="stylesheet" type="text/css" href="components.css">
		<script type="text/javascript" src="pcx86.js"></script>
	<body style="font-family: Helvetica, Arial, sans-serif;">
		<div id="pcxt"></div>
		<script type="text/javascript">
			embedPCx86("pcxt", "pcxt.xml", "components.xsl");

Make sure the name of the div matches the value passed to embedPCx86, otherwise, there will just be a blank page. Here, pcxt.xml specifies the settings for RAM, BIOS, floppy drive and other settings:

<?xml version="1.0" encoding="UTF-8"?>
<machine id="example1" type="pcx86" width="720px">
	<computer id="pc" name="IBM PC"/>
	<cpu id="cpu8088" model="8088" autostart="true"/>
	<ram id="ramLow" addr="0x00000" size="0x10000"/>
	<rom id="romBASIC" addr="0xf6000" size="0x8000" file="ibm-basic-1.00.json"/>
	<rom id="romBIOS" addr="0xfe000" size="0x2000" file="1981-04-24.json"/>
	<keyboard id="keyboard"/>
	<video id="videoMDA" screenWidth="720" 
     screenHeight="350" fontROM="ibm-mda-cga.json">
			<title>Monochrome Display</title>
	<chipset id="chipset" model="5150" sw1="01000001" sw2="11110000"/>

It is important to ensure that all files mentioned in the XML (BIOS image, floppy disk image, etc.) as well as PCx86 supporting files (available from versions/pcx86 folder) are present in the correct folder, otherwise, there will be cryptic error messages. In particular, if some CSS/XSL files are missing, the JS code responsible for initializing the HTML canvas to display the emulator will fail, and the code will report a very misleading error: “Missing <canvas> support. Please try a newer web browser.”

As PCjs only accept BIOS/disk image in JSON format, it is important to convert the binary images first. You can refer to this and this on how to perform the conversion. Additionally, refer to PCjs online examples here for the necessary configuration entries to emulate different types of machines.

With the correct configuration, I was able to quickly launch the PC XT emulator in my browser:


Serial mouse emulation also works properly with CuteMouse, although the browser text cursor is also shown together with the DOS cursor. This can probably be fixed with CSS styles. Regardless, the cursor is not a big issue for me as I tend to ignore the browser cursor after a while.

One thing I noticed is that sound sometimes doesn’t play in Google Chrome despite the emulator working perfectly otherwise. The reason for this can be found from a message in Chrome console:

The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page.

It seems that audio playback will be disallowed by Chrome unless the user explicitly interacts with the emulator before the audio playback. In the case of the PC XT emulator, you will need to click the emulator before the POST beep for audio to be played subsequently. To fix the issue, open chrome://flags and set “Autoplay policy” to “No user gesture is required”:


Alternatively, just use Firefox, which worked during my tests. As for Internet Explorer, I couldn’t get audio playback to work, even with the latest version.

A challenge is to save the current state of the virtual machine, especially the modified hard disk image, so that we can restore the same state even after the browser is restarted. Although this is normally simple for other emulators such as DosBox since disk images are updated directly, PCjs works on a JSON array of the image content and emulator state can only be saved by invoking the “Save Machine” menu option. Unfortunately, this did not work due to a bug in PCjs that uses hard-coded path to the pcx86.js script. As a workaround, I use CSS to hide the default “Save Machine” link and implement my own menu:

<a href="#" onclick='savePC("pcxt", "pcx86.js")'>Save Machine</a>

Here, pcxt is the name of the emulator and pcx86.js is the path to the pcx86.js script. With this workaround, machine state can be saved under Firefox. A JavaScript file that describes the current state of the emulator will be downloaded and PCjs will also show you the code snippet that can be used to reload the saved state.

Unfortunately, there is no way to simply extract the modified hard disk image without saving the state of the entire machine. The savePC() function will also fail in Chrome with an immediate “Download Failed – Network Error” failure. In Internet Explorer and Firefox, the feature works properly.

When using with CGA display, I also noticed that PCjs seems to ignore the screenWidth and screenHeight attribute of the video tag, and always shows the emulator using 100% screen width. If this is an issue, use the following JavaScript code to set the emulator to your preferred width:

setTimeout(function() {
   document.getElementById('ibm5160').setAttribute("style", "width:50%");
}, 500);

The setTimeOut function is needed to introduce a small delay; otherwise our style changes will simply be reverted by PCjs initialization code.

For those who are interested, I have prepared a PCx86 instance that emulates an BM PC AT 80286 @ 8MHz with 640 KB RAM, dual 1.44MB floppy drives and CGA display. The two floppy disks, accessible as A: and B:, contain MS-DOS 6.22 together with CheckIt, Turbo Pascal 5.5, Norton Commander and many games. Feel free to try it out!
(Hint: Depending on your screen resolution, you might want to resize the browser window so that the entire emulator screen is visible.)


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Written By
Technical Writer ToughDev
Singapore Singapore
Since 2008, ToughDev has been publishing technical sharing articles on a wide range of topics from software development to electronics design. Our interests include, but are not limited to, Android/iOS programming, VoIP products, embedded design using Arduino/PIC microcontrollers, reverse-engineering, retro-computing, and many others. We also perform product reviews, both on new and vintage products, and share our findings with the community. In addition, our team also develops customized software/hardware solutions highly adapted to suit your needs. Contact us for more information.

Comments and Discussions

SuggestionAudio requires user gesture to start Pin
ahmad_51116-May-23 23:50
professionalahmad_51116-May-23 23:50 
QuestionIt still amazes me... Pin
Marc Clifton13-May-23 2:01
mvaMarc Clifton13-May-23 2:01 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.