Playing Alley Cat, a classic MS-DOS game, from your web browser

0.00 avg. rating (0% score) - 0 votes

Last week I explored gabonator’s Visual C++ and Javascript port of Alley Cat, one of my favourite DOS games. The project, despite being apparently abandoned since 2014, is still exciting to me as I love the idea of being able to play classic MS-DOS games the modern way without having to start any emulator. The idea also reminds me of SDLPoP, another similar and still active project which develops an SDL version of Prince of Persia using mostly knowledge gained from the disassembly process.

In a nutshell, the author used The Interactive Disassembler (IDA) to generate the ASM code for the original Alley Cat executable and then used another tool to convert the assembly code to its C equivalent. Although the output is in C syntax, it is still cryptic as it still contains register-like variables and methods with hexadecimal names:

alleycat_asm

However, this is where things become interesting. Instead of spending time understanding the logic and rewriting the code in a more readable (and maintainable manner), the author implements a miniature 8086 emulator in C which can be used to run the converted code. Assembly instructions such as push and pop are also written as C methods:

asm_int

With this approach, there is no need to modify the converted code, except perhaps to fix places where the converter did not do a good job, mostly obscure jumps that cannot be automatically translated into C code. Graphics calls are then modified to update a centralized CGA frame buffer, declared as a bitmap, to be drawn on screen when necessary:

CFrameBuffer()
{
	HDC hDC;
	BITMAPINFO bitmapinfo;
	hDC=CreateCompatibleDC(NULL);
	bitmapinfo.bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
	bitmapinfo.bmiHeader.biWidth=Width;
	bitmapinfo.bmiHeader.biHeight=-Height; /* top-down */
	bitmapinfo.bmiHeader.biPlanes=1;
	bitmapinfo.bmiHeader.biBitCount=32;
	bitmapinfo.bmiHeader.biCompression=BI_RGB;
	bitmapinfo.bmiHeader.biSizeImage=0;
	bitmapinfo.bmiHeader.biClrUsed=256;
	bitmapinfo.bmiHeader.biClrImportant=256;
	m_pBuffer = NULL;
	m_ourbitmap=CreateDIBSection(hDC,&bitmapinfo,DIB_RGB_COLORS,&m_pBuffer,0,0);
	m_pDC=CreateCompatibleDC(NULL);
	m_Old=SelectObject(m_pDC,m_ourbitmap);
	DeleteDC(hDC);

	FillMemory(m_pBuffer, sizeof(DWORD)*Width*Height, 0xb0);
}

PC speaker functions are also converted to Visual C’s Beep() function. The ported C code also loads the original .EXE into memory to simulate how an .EXE file is loaded on MS-DOS. Using a similar approach, the code is then converted to JavaScript to be executed on a browser.

Unfortunately, although I tried hard to replicate the author’s progress, the provided C code is missing several important pieces. Several functions are present in the JavaScript port, but not in the C codes, which indicates that the uploads were most likely incomplete. The JavaScript port still works to show the intro screen (see this for a demo) but hangs afterwards since its development was never completed.

Although I do not have the time to continue with the project, I was impressed by the efforts spent in porting the intro screen to JavaScript. After all, the converted C functions are cryptic and do not have meaningful names. I however do not think that this is an efficient approach since the final C codes are simply assembly instructions converted to C and not maintainable. I decided to go with PCjs, a JavaScript based PC emulator, and build a PC XT image that can boot Alley Cat in a browser, ready to play in just a few seconds.

This can be done with just the following HTML code:

<body style="font-family: Helvetica, Arial, sans-serif; display: none">
 <div id="ibm5160" style="width: 50%; height: 50%;"></div>
 <script type="text/javascript">
 embedPCx86('ibm5160','machine.xml','components.xsl','{autoMount:{}}');

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

 setTimeout(function() {
 document.title = "Alley Cat in a web browser";
 document.body.style.display = "block";
 }, 5000);
 </script>

 <!-- <a href="#" onclick="javascript:savePC('ibm5160', 'pcx86.js')">Save Machine</a> -->
 </body>

And the following machine configuration file:

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="machine.xsl"?>
<machine id="ibm5160" type="pcx86" border="1" pos="center" background="default">
	<name pos="center">Alley Cat in a web browser</name>
	<computer id="xt-cga-640k" name="IBM PC XT"/>
	<ram id="ramLow" addr="0x00000" test="false" size="0xa0000" comment="0xa0000 (640Kb) size overrides SW1|ROM BIOS memory test has been disabled"/>
	<rom id="romBIOS" addr="0xfe000" size="0x2000" file="XTBIOS-REV1.json"/>
	<video ref="ibm-cga-keygrid.xml"/>
	<cpu id="cpu8088" model="8088" pos="left" padLeft="8px" padBottom="8px">
	</cpu>
	<fdc id="fdcNEC" autoMount='{A: {name: "AlleyCat", path: "alleycat.json"}}' pos="left">
	</fdc>
	<keyboard ref="us83-softkeys.xml"/>
	<chipset id="chipset" model="5160" sw1="01001001"/>
	<serial id="com1" adapter="1"/>
	<serial id="com2" adapter="2"/>
	<mouse serial="com2"/>

</machine>

Where alleycat.json is the bootable version of AlleyCat, converted to JSON using PCjs instructions. To hide the PC XT boot process, the HTML body is hidden at load and only made visible by JavaScript codes after a few seconds, after the machine has finished loading. With this, Alley Cat can load nicely in the browser after just a few seconds and the entire game is playable:

alleycat_browser

The same approach can be used to make other DOS games playable in the browser without much effort. For those you are interested, the above setup can be access via this link. The ported C++ and JavaScript codes can be downloaded here.

 

See also

Exploring PCx86, an IBM PC emulator written in JavaScript

0.00 avg. rating (0% score) - 0 votes
ToughDev

ToughDev

A tough developer who likes to work on just about anything, from software development to electronics, and share his knowledge with the rest of the world.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>