<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>assembly &#8211; Virtually Fun</title>
	<atom:link href="https://virtuallyfun.com/category/assembly/feed/" rel="self" type="application/rss+xml" />
	<link>https://virtuallyfun.com</link>
	<description>Fun with Virtualization</description>
	<lastBuildDate>Tue, 02 Jun 2026 09:05:48 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=7.0</generator>
	<item>
		<title>Pinball on 64-bit Alpha AXP Windows NT</title>
		<link>https://virtuallyfun.com/2026/06/02/pinball-on-64-bit-alpha-axp-windows-nt/</link>
					<comments>https://virtuallyfun.com/2026/06/02/pinball-on-64-bit-alpha-axp-windows-nt/#respond</comments>
		
		<dc:creator><![CDATA[neozeed]]></dc:creator>
		<pubDate>Tue, 02 Jun 2026 06:54:42 +0000</pubDate>
				<category><![CDATA[assembly]]></category>
		<category><![CDATA[DEC Alpha]]></category>
		<category><![CDATA[games]]></category>
		<category><![CDATA[guest post]]></category>
		<category><![CDATA[microsoft windows]]></category>
		<category><![CDATA[Windows XP]]></category>
		<guid isPermaLink="false">https://virtuallyfun.com/?p=15787</guid>

					<description><![CDATA[This is a guest post from Yufeng Gao One of the most popular OS built-in games is no doubt&#160;Pinball, known by its full name&#160;3D Pinball for Windows – Space Cadet. It started out as&#160;Full Tilt! Pinball, developed by&#160;Cinematronics&#160;and published by&#160;Maxis. &#8230; <a href="https://virtuallyfun.com/2026/06/02/pinball-on-64-bit-alpha-axp-windows-nt/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph"><em>This is a guest post from <a href="https://thebrokenpipe.com/blog/author/brokenpipe/">Yufeng Gao</a></em></p>



<p class="wp-block-paragraph">One of the most popular OS built-in games is no doubt&nbsp;<a href="https://en.wikipedia.org/wiki/Full_Tilt!_Pinball#3D_Pinball_for_Windows_%E2%80%93_Space_Cadet">Pinball</a>, known by its full name&nbsp;<em>3D Pinball for Windows – Space Cadet</em>. It started out as&nbsp;<em>Full Tilt! Pinball</em>, developed by&nbsp;<a href="https://en.wikipedia.org/wiki/Cinematronics,_LLC">Cinematronics</a>&nbsp;and published by&nbsp;<a href="https://en.wikipedia.org/wiki/Maxis">Maxis</a>. It offered 3 tables, and one of them, Space Cadet, was licensed to Microsoft to be included in Microsoft Plus! 95 and, later, built into the Windows operating system.</p>



<figure class="wp-block-image size-full"><a href="https://virtuallyfun.com/wp-content/uploads/2026/06/pinball_gameplay.gif"><img fetchpriority="high" decoding="async" width="642" height="492" src="https://virtuallyfun.com/wp-content/uploads/2026/06/pinball_gameplay.gif" alt="" class="wp-image-15800"/></a></figure>



<p class="wp-block-paragraph">Windows XP was the last version of Windows to include Pinball, and Raymond Chen&nbsp;<a href="https://devblogs.microsoft.com/oldnewthing/20121218-00/?p=5803">explained why it didn’t make it to Windows Vista</a>&nbsp;on his blog. The reason was it had a collision detector bug when it was compiled for 64-bit Windows, which caused the ball to pass through various objects – falling off the screen through the plunger instead of being launched, for instance. The bug rendered the game unplayable, and Raymond and his colleague were unable to find a fix in a reasonable amount of time, so he removed it. At least that’s the story we were told, for about a decade.</p>



<p class="wp-block-paragraph">In 2021,&nbsp;<a href="https://www.youtube.com/c/NCommander">NCommander</a>&nbsp;launched&nbsp;<a href="https://www.youtube.com/watch?v=3EPTfOTC4Jw">a series of investigations</a>&nbsp;to challenge that, testing Pinball on various 64-bit (IA-64 and AMD64) builds of Windows XP and pre-release Vista. He found that the 64-bit versions of Pinball were all highly playable, with only very minor glitches, and speculated that the reason for its removal was that the UI did not fit into the Windows Vista design.</p>



<p class="wp-block-paragraph">Not long after NCommander published his video, Raymond followed up with a&nbsp;<a href="https://devblogs.microsoft.com/oldnewthing/20220106-00/?p=106122">post that filled in some gaps</a>&nbsp;in the story and shed more light on the bug. He said it was the 64-bit Alpha AXP version of Pinball that had the extremely bad collision detection bug. This claim had been unverifiable for the past 5 years, for the following reasons:</p>



<ul class="wp-block-list">
<li>No 64-bit Windows was ever released for the Alpha AXP – Compaq killed Windows NT support before NT was ported to 64-bit</li>



<li>One 64-bit Alpha AXP NT build was leaked in 2023, but the included Pinball does not work, as it segfaults immediately upon running</li>
</ul>



<p class="wp-block-paragraph">I’ve had an interest in the DEC Alpha for quite some time now, mainly out of my love for DEC architectures and my love for UNIX. VAX is the direct successor of PDP-11, and Alpha is the direct successor of VAX. Earlier, some Alpha emulation breakthroughs dropped, and I was pinged by a few friends that NT 4.0 could now run on a&nbsp;<a href="https://github.com/ES40-Emu/es40/">fork of the ES40 emulator</a>, as well as on&nbsp;<a href="https://github.com/TheBrokenPipe/qemu/tree/alphafix">QEMU</a>. I never thought Alpha NT would ever run under emulation, because unlike the familiar Tru64, Linux and the BSDs, NT uses its own custom PALcode and depends on ARC (Advanced RISC Computing) instead of SRM. Of course, people noted that the emulators couldn’t run the holy grail of Alpha NT – Windows (XP?) build 2210, because its kernel would panic with a memory management error in QEMU, or wouldn’t detect the keyboard and bug out in ES40. A few trips to hell in the symbol-less NT kernel and a few MMU emulation fixes later, I was able to patch up both QEMU and ES40 to boot that only surviving 64-bit build of Alpha NT.</p>



<figure class="wp-block-image size-full"><a href="https://virtuallyfun.com/wp-content/uploads/2026/06/image-1.png"><img decoding="async" width="923" height="728" src="https://virtuallyfun.com/wp-content/uploads/2026/06/image-1.png" alt="" class="wp-image-15789" srcset="https://virtuallyfun.com/wp-content/uploads/2026/06/image-1.png 923w, https://virtuallyfun.com/wp-content/uploads/2026/06/image-1-300x237.png 300w, https://virtuallyfun.com/wp-content/uploads/2026/06/image-1-768x606.png 768w, https://virtuallyfun.com/wp-content/uploads/2026/06/image-1-380x300.png 380w" sizes="(max-width: 923px) 100vw, 923px" /></a></figure>



<p class="wp-block-paragraph">After torturing my brain debugging a symbol-less NT kernel without a kernel debugger, I thought I’d give fixing Pinball a go, to make things worthwhile. One of the benefits of debugging a userland process is that, while there’s still no debugger, there is&nbsp;<a href="https://en.wikipedia.org/wiki/Dr._Watson_(debugger)">Dr. Watson</a>, which takes core dumps and performs simple post-mortems. Something is better than nothing, as people would say.</p>



<p class="wp-block-paragraph">Running Pinball gives the classic crash symptom immediately, with no graphics drawn:</p>


<div class="wp-block-image">
<figure class="aligncenter size-full"><a href="https://virtuallyfun.com/wp-content/uploads/2026/06/image-2.png"><img decoding="async" width="427" height="172" src="https://virtuallyfun.com/wp-content/uploads/2026/06/image-2.png" alt="" class="wp-image-15790" srcset="https://virtuallyfun.com/wp-content/uploads/2026/06/image-2.png 427w, https://virtuallyfun.com/wp-content/uploads/2026/06/image-2-300x121.png 300w" sizes="(max-width: 427px) 100vw, 427px" /></a></figure>
</div>


<p class="wp-block-paragraph">Dr. Watson concludes that it died of a segfault:</p>


<div class="wp-block-image">
<figure class="aligncenter size-full"><a href="https://virtuallyfun.com/wp-content/uploads/2026/06/image-3.png"><img loading="lazy" decoding="async" width="358" height="481" src="https://virtuallyfun.com/wp-content/uploads/2026/06/image-3.png" alt="" class="wp-image-15791" srcset="https://virtuallyfun.com/wp-content/uploads/2026/06/image-3.png 358w, https://virtuallyfun.com/wp-content/uploads/2026/06/image-3-223x300.png 223w" sizes="auto, (max-width: 358px) 100vw, 358px" /></a></figure>
</div>


<p class="wp-block-paragraph">It gave a nice dump of registers at the time of the fault:</p>



<pre class="wp-block-code"><code>State Dump for Thread Id 0x124

  v0=01002930 00000000   t0=00000000 00360000   t1=00000000 00000001
  t2=00000000 00360000   t3=00000000 00000000   t4=00000000 00000000
  t5=00000000 0000011c   t6=000003ff fff8f868   t7=00000000 00303030
  s0=000003ff fff8fac0   s1=01002930 00000000   s2=000003ff fff8fad8
  s3=00000000 00000000   s4=00000000 0106f2a8   s5=00000000 01000000
  fp=00000000 00000010   a0=01002930 00000000   a1=00000000 00000000
  a2=000003ff fff8fad8   a3=00000000 30010000   a4=00000000 69e17610
  a5=00000000 69e0a360   t8=000003ff fff8f868   t9=00000000 00000000
 t10=00000000 00300000  t11=00000000 00000002   ra=00000000 69e9d5c0
 t12=00000000 6a264710   at=ffffffff fffffe10   gp=00000000 00000000
  sp=000003ff fff8fa50 zero=00000000 00000000 fpcr=08000000 00000000
SoftFpcr=00000000 00000000  fir=6a264710
 psr=00000003
mode=1 ie=1 irql=0 </code></pre>



<p class="wp-block-paragraph">Some disassembly around the faulting instruction:</p>



<pre class="wp-block-code"><code>function: Otsstrlen
FAULT -&gt;00000000'6a264710: 2f700000 ldq_u t12,0(a0)
        00000000'6a264714: 239fffff lda at,-1(zero)
        00000000'6a264718: 4b90065c mskql at,a0,at
        00000000'6a26471c: 4600f000 and a0,#7,v0
        00000000'6a264720: 477c041b bis t12,at,t12
        00000000'6a264724: 43fb01fb cmpbge zero,t12,t12
        00000000'6a264728: 43e00520 subq zero,v0,v0
        00000000'6a26472c: f7600005 bne t12,00000000'6a264744 Otsstrlen+00000034
        00000000'6a264730: 2f700008 ldq_u t12,8(a0)
        00000000'6a264734: 42011410 addq a0,#8,a0
        00000000'6a264738: 40011400 addq v0,#8,v0
        00000000'6a26473c: 43fb01fb cmpbge zero,t12,t12</code></pre>



<p class="wp-block-paragraph">And a very useful stack backtrace:</p>



<pre class="wp-block-code"><code>*----&gt; Stack Back Trace &lt;----*

FramePtr ReturnAd Param#1  Param#2  Param#3  Param#4  Function Name
000003FFFFF8FA50 0000000069E9D5BC 0100293000000000 0000000000000000 000003FFFFF8FAD8 0000000030010000 !Otsstrlen 
000003FFFFF8FA50 0000000069E9DB64 0100293000000000 0000000000000000 000003FFFFF8FAD8 0000000030010000 !PostThreadMessageA 
000003FFFFF8FA90 0000000069E9C000 0100293000000000 0000000000000000 000003FFFFF8FAD8 0000000030010000 !SetClassLongA 
000003FFFFF8FB80 000000000100F914 000003FFFFF8FC58 0000000000000000 000003FFFFF8FAD8 0000000030010000 !RegisterClassA 
000003FFFFF8FBF0 0000000001012A1C 0000000001000000 0000000001002DC8 000003FFFFF8FAD8 0000000030010000 !&lt;nosymbols&gt; 
000003FFFFF8FCA0 0000000001064B0C 0000000001000000 0000000001002DC8 000003FFFFF8FAD8 0000000030010000 !&lt;nosymbols&gt; 
000003FFFFF8FED0 0000000068948C50 0000000001000000 0000000001002DC8 000003FFFFF8FAD8 0000000030010000 !&lt;nosymbols&gt; 
000003FFFFF8FFC0 0000000000000000 0000000001064800 0000000001002DC8 000003FFFFF8FAD8 0000000030010000 !BaseProcessStart </code></pre>



<p class="wp-block-paragraph">Ok, so it died inside&nbsp;<code>RegisterClassA</code>, a critical Win32 API function. That API function couldn’t have been the culprit, because if it were bugged, no GUI Win32 program would run at all. This means the only possible source of the error is its sole argument – a pointer to a&nbsp;<code>WNDCLASSA</code>&nbsp;struct. Needless to say, the pointer itself was valid, otherwise the API would’ve detected the invalid argument, or the segfault would’ve happened a lot sooner.</p>



<p class="wp-block-paragraph">From the stack trace, the return address of&nbsp;<code>RegisterClassA</code>&nbsp;was&nbsp;<code>0x100F914</code>, inside the function&nbsp;<code>splash_screen</code>. A quick disassembly of the instructions preceding that address shows a&nbsp;<code>WNDCLASSA</code>&nbsp;structure being built with the following layout:</p>



<pre class="wp-block-code"><code>00000000 u32 style         = 0
00000004 u64 lpfnWndProc   = splash_message_handler (0x100FE40)
0000000C u32 cbClsExtra    = 0
00000010 u32 cbWndExtra    = 8
00000014 u64 hInstance     = *0x106AE30
0000001C u64 hIcon         = NULL
00000024 u64 hCursor       = LoadCursorA(NULL, IDC_ARROW)
0000002C u64 hbrBackground = NULL
00000034 u64 lpszMenuName  = "" (0x1002710)
0000003C u64 lpszClassName = "3DPB_SPLASH_CLASS" (0x1002930)</code></pre>



<p class="wp-block-paragraph">Right off the bat, I noticed something wrong – the field alignment. It is a general requirement that fields be aligned to their size, as in 8-bit fields should be byte-aligned, 16-bit fields should be 16-bit (2-byte) aligned, 32-bit fields should be 32-bit (4-byte) aligned, and 64-bit fields should be 64-bit (8-byte) aligned. If you look at the offsets of the fields above, the 32-bit ones are indeed 4-byte aligned, but the 64-bit ones are not. At the start, we have a 32-bit&nbsp;<code>style</code>&nbsp;field followed by a 64-bit&nbsp;<code>lpfnWndProc</code>, and to satisfy the alignment requirements, a 4-byte padding should be inserted between&nbsp;<code>style</code>&nbsp;and&nbsp;<code>lpfnWndProc</code>&nbsp;to ensure that&nbsp;<code>lpfnWndProc</code>&nbsp;starts on an 8-byte boundary.&nbsp;<code>RegisterClassA</code>&nbsp;was expecting this padding, but Pinball lacked it, so it read data from the wrong offset and crashed.</p>



<p class="wp-block-paragraph">To fix this, I simply bumped the offset of each field after&nbsp;<code>style</code>&nbsp;up by 4 bytes.</p>



<pre class="wp-block-code"><code> 00000000 u32 style         = 0
-00000004 u64 lpfnWndProc   = splash_message_handler (0x100FE40)
+00000008 u64 lpfnWndProc   = splash_message_handler (0x100FE40)
-0000000C u32 cbClsExtra    = 0
+00000010 u32 cbClsExtra    = 0
-00000010 u32 cbWndExtra    = 8
+00000014 u32 cbWndExtra    = 8
-00000014 u64 hInstance     = *0x106AE30
+00000018 u64 hInstance     = *0x106AE30
-0000001C u64 hIcon         = NULL
+00000020 u64 hIcon         = NULL
-00000024 u64 hCursor       = LoadCursorA(NULL, IDC_ARROW)
+00000028 u64 hCursor       = LoadCursorA(NULL, IDC_ARROW)
-0000002C u64 hbrBackground = NULL
+00000030 u64 hbrBackground = NULL
-00000034 u64 lpszMenuName  = "" (0x1002710)
+00000038 u64 lpszMenuName  = "" (0x1002710)
-0000003C u64 lpszClassName = "3DPB_SPLASH_CLASS" (0x1002930)
+00000040 u64 lpszClassName = "3DPB_SPLASH_CLASS" (0x1002930)</code></pre>



<p class="wp-block-paragraph">But that was not sufficient – Pinball calls&nbsp;<code>RegisterClassA</code>&nbsp;in 4 different places –&nbsp;<code>Sound_Init</code>,&nbsp;<code>splash_screen</code>,&nbsp;<code>WinMain</code>&nbsp;and&nbsp;<code>WaveMixStartup</code>. I’d already patched the one in&nbsp;<code>splash_screen</code>, so I started going through the rest one by one.</p>



<p class="wp-block-paragraph">The ones in&nbsp;<code>Sound_Init</code>&nbsp;and&nbsp;<code>WinMain</code>&nbsp;were identical to the one in&nbsp;<code>splash_screen</code>, but for some strange reason the one in&nbsp;<code>WaveMixStartup</code>&nbsp;already had the correct alignment:</p>



<pre class="wp-block-code"><code>00000000 u32 style         = 0
00000004 u32 &lt;unused&gt;      = &lt;undefined&gt;
00000008 u64 lpfnWndProc   = WndProc (0x105CFA0)
00000010 u32 cbClsExtra    = 0
00000014 u32 cbWndExtra    = 0
00000018 u64 hInstance     = *0x106B818
00000020 u64 hIcon         = NULL
00000028 u64 hCursor       = LoadCursorA(NULL, IDC_ARROW)
00000030 u64 hbrBackground = GetStockObject(LTGRAY_BRUSH)
00000038 u64 lpszMenuName  = NULL
00000040 u64 lpszClassName = "WavMix32" (0x10050B0)</code></pre>



<p class="wp-block-paragraph">I can’t think of why the same struct would be aligned differently within the same binary, unless they came from different objects compiled with different flags or something.</p>



<p class="wp-block-paragraph">Anyway, with the&nbsp;<code>WNDCLASSA</code>&nbsp;struct alignment fixed in 3 of the 4 places, I ran Pinball again. This time it created the fullscreen window and attempted to draw the splash screen before dying of another segfault:</p>


<div class="wp-block-image">
<figure class="aligncenter size-full"><a href="https://virtuallyfun.com/wp-content/uploads/2026/06/image-4.png"><img loading="lazy" decoding="async" width="1024" height="740" src="https://virtuallyfun.com/wp-content/uploads/2026/06/image-4.png" alt="" class="wp-image-15792" srcset="https://virtuallyfun.com/wp-content/uploads/2026/06/image-4.png 1024w, https://virtuallyfun.com/wp-content/uploads/2026/06/image-4-300x217.png 300w, https://virtuallyfun.com/wp-content/uploads/2026/06/image-4-768x555.png 768w, https://virtuallyfun.com/wp-content/uploads/2026/06/image-4-415x300.png 415w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></figure>
</div>


<p class="wp-block-paragraph">Crash log shows that the segfault happened deep in the Win32 audio system, while calling&nbsp;<code>auxSetVolume</code>:</p>



<pre class="wp-block-code"><code>*----&gt; Stack Back Trace &lt;----*

FramePtr ReturnAd Param#1  Param#2  Param#3  Param#4  Function Name
000003FFFFF8E9C0 0000000050306E84 00000000FFE5D420 0000000000000000 000003FFFFE5D420 0000000000000000 !&lt;nosymbols&gt; 
000003FFFFF8E9E0 00000000503034B8 00000000FFE5D420 0000000000000000 000003FFFFE5D420 0000000000000000 !&lt;nosymbols&gt; 
000003FFFFF8EA10 0000000050304B60 00000000FFE5D420 0000000000000000 000003FFFFE5D420 0000000000000000 !&lt;nosymbols&gt; 
000003FFFFF8EA90 0000000050305B8C 00000000FFE5D420 0000000000000000 000003FFFFE5D420 0000000000000000 !&lt;nosymbols&gt; 
000003FFFFF8EB20 000000000001AF78 00000000FFE5D420 0000000000000000 000003FFFFE5D420 0000000000000000 !&lt;nosymbols&gt; 
000003FFFFF8EB60 0000000000025AFC 00000000FFE5D420 0000000000000000 000003FFFFE5D420 0000000000000000 !auxSetVolume 
000003FFFFF8EBD0 0000000000025F98 00000000FFE5D420 0000000000000000 000003FFFFE5D420 0000000000000000 !mixerSetControlDetails 
000003FFFFF8EC80 0000000000027214 00000000FFE5D420 0000000000000000 000003FFFFE5D420 0000000000000000 !mixerSetControlDetails 
000003FFFFF8ED30 0000000000030644 00000000FFE5D420 0000000000000000 000003FFFFE5D420 0000000000000000 !mciSendCommandW 
&#91;...]
000003FFFFF8FC60 0000000001012AB4 0000000000000000 000003FFFFE5DE00 000003FFFFE5D420 0000000000000000 !CreateWindowExA 
000003FFFFF8FCA0 0000000001064B0C 0000000000000000 000003FFFFE5DE00 000003FFFFE5D420 0000000000000000 !&lt;nosymbols&gt; 
000003FFFFF8FED0 0000000068948C50 0000000000000000 000003FFFFE5DE00 000003FFFFE5D420 0000000000000000 !&lt;nosymbols&gt; 
000003FFFFF8FFC0 0000000000000000 0000000001064800 000003FFFFE5DE00 000003FFFFE5D420 0000000000000000 !BaseProcessStart</code></pre>



<p class="wp-block-paragraph">The fault happened while trying to dereference a pointer in the register&nbsp;<code>a0</code>&nbsp;(<code>r16</code>):</p>



<pre class="wp-block-code"><code>function: &lt;nosymbols&gt;
        00000000'50305658: 00000000 halt
        00000000'5030565c: 00000000 halt
        00000000'50305660: 23deffe0 lda sp,-20(sp)
        00000000'50305664: b53e0000 stq s0,0(sp)
        00000000'50305668: b55e0008 stq s1,8(sp)
        00000000'5030566c: b57e0010 stq s2,10(sp)
        00000000'50305670: b75e0018 stq ra,18(sp)
        00000000'50305674: 47f00409 bis zero,a0,s0
        00000000'50305678: 47f1040a bis zero,a1,s1
        00000000'5030567c: 47ff040b bis zero,zero,s2
<strong>FAULT -&gt;00000000'50305680: a2100128 ldl a0,128(a0)</strong>
        00000000'50305684: 20500001 lda t1,1(a0)
        00000000'50305688: e440001b beq t1,00000000'503056f8 00000000'503056f8
        00000000'5030568c: d35ff6f8 bsr ra,00000000'50303270 00000000'50303270
        00000000'50305690: e4000019 beq v0,00000000'503056f8 00000000'503056f8
        00000000'50305694: 47e00411 bis zero,v0,a1
        00000000'50305698: 454b0801 xor s1,s2,t0
        00000000'5030569c: e4200005 beq t0,00000000'503056b4 00000000'503056b4
        00000000'503056a0: a2090128 ldl a0,128(s0)
        00000000'503056a4: d35ff722 bsr ra,00000000'50303330 00000000'50303330
        00000000'503056a8: 4160300b addl s2,#1,s2
        00000000'503056ac: 47e00411 bis zero,v0,a1</code></pre>



<p class="wp-block-paragraph">The register dump shows the value of&nbsp;<code>a0</code>&nbsp;at the time of the crash:</p>



<pre class="wp-block-code"><code>State Dump for Thread Id 0x150

  v0=000003ff ffe5de00   t0=00000000 00000000   t1=00000000 00000058
  t2=00000000 50306150   t3=00000000 0000015e   t4=00000000 00000001
  t5=00000000 00000001   t6=00000000 50300000   t7=00000000 00ed39fb
  s0=00000000 ffe5d420   s1=00000000 00000000   s2=00000000 00000000
  s3=00000000 00000000   s4=00000000 00000001   s5=00000000 50305a10
  fp=00000000 000123b8   <strong>a0=00000000 ffe5d420</strong>   a1=00000000 00000000
  a2=000003ff ffe5d420   a3=00000000 00000000   a4=00000000 00000000
  a5=00000000 cc5a4dbc   t8=00000001 00000000   t9=00000000 00000612
 t10=d1b71758 e219652c  t11=00000000 00000612   ra=00000000 50306e88
 t12=00000000 00000000   at=00000000 00010000   gp=00000000 00000000
  sp=000003ff fff8e9c0 zero=00000000 00000000 fpcr=89000000 00000000
SoftFpcr=00000000 00000000  fir=50305680
 psr=00000003
mode=1 ie=1 irql=0 </code></pre>



<p class="wp-block-paragraph">Indeed, it was an invalid pointer! As you can see, it’s identical to the pointer in&nbsp;<code>a2</code>, but with the entire top 32 bits zeroed. It must’ve been truncated by a bug somewhere, either in the audio subsystem or in Pinball itself.</p>



<p class="wp-block-paragraph">I spent some time and pinned down the DLL responsible for the fault –&nbsp;<code>mciseq.dll</code>, and did some tracing. The truncation of&nbsp;<code>a0</code>&nbsp;happened when&nbsp;<code>a2</code>&nbsp;was moved into&nbsp;<code>a0</code>:</p>



<pre class="wp-block-code"><code>50306150    ZAPNOT  a2,#15,a0</code></pre>



<p class="wp-block-paragraph"><code>ZAPNOT</code>&nbsp;is an interesting instruction – it takes a source register, a bitmask and a destination register, and it “zaps” (zeros) the bytes whose corresponding bit in the bitmask is 0. In this case, the bitmask is&nbsp;<code>15</code>, which is&nbsp;<code>00001111</code>&nbsp;in binary. From this we can work out that the&nbsp;<code>ZAPNOT</code>&nbsp;instruction at&nbsp;<code>0x50306150</code>&nbsp;zeros the upper 4 bytes of&nbsp;<code>a2</code>, when it is copied into&nbsp;<code>a0</code>. This perfectly explains why, at the time of the fault,&nbsp;<code>a0</code>&nbsp;contained a truncated version of the pointer in&nbsp;<code>a2</code>.</p>



<p class="wp-block-paragraph">Of course,&nbsp;<code>0x50306150</code>&nbsp;was not the only place where it truncated 64-bit pointers, I found 6 truncations of the exact same type in&nbsp;<code>mciseq.dll</code>. I have not the slightest clue why it decided to truncate pointers. If I had to guess, maybe they had pointer → integer → pointer casts for whatever reason, and that integer type was 32-bit. With all 6 truncations patched out, we have some Pinball for ourselves:</p>


<div class="wp-block-image">
<figure class="aligncenter size-full"><a href="https://virtuallyfun.com/wp-content/uploads/2026/06/image-5.png"><img loading="lazy" decoding="async" width="1024" height="768" src="https://virtuallyfun.com/wp-content/uploads/2026/06/image-5.png" alt="" class="wp-image-15793" srcset="https://virtuallyfun.com/wp-content/uploads/2026/06/image-5.png 1024w, https://virtuallyfun.com/wp-content/uploads/2026/06/image-5-300x225.png 300w, https://virtuallyfun.com/wp-content/uploads/2026/06/image-5-768x576.png 768w, https://virtuallyfun.com/wp-content/uploads/2026/06/image-5-400x300.png 400w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></figure>
</div>


<p class="wp-block-paragraph">Here’s proof that Pinball is indeed running on a 64-bit build of Alpha NT:</p>


<div class="wp-block-image">
<figure class="aligncenter size-full"><a href="https://virtuallyfun.com/wp-content/uploads/2026/06/image-6.png"><img loading="lazy" decoding="async" width="1024" height="768" src="https://virtuallyfun.com/wp-content/uploads/2026/06/image-6.png" alt="" class="wp-image-15794" srcset="https://virtuallyfun.com/wp-content/uploads/2026/06/image-6.png 1024w, https://virtuallyfun.com/wp-content/uploads/2026/06/image-6-300x225.png 300w, https://virtuallyfun.com/wp-content/uploads/2026/06/image-6-768x576.png 768w, https://virtuallyfun.com/wp-content/uploads/2026/06/image-6-400x300.png 400w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></figure>
</div>


<p class="wp-block-paragraph">To make Pinball work on your NT build 2210 install, replace&nbsp;<code>%ProgramFiles%\Windows NT\Pinball\pinball.exe</code>&nbsp;and&nbsp;<code>%windir%\system32\mciseq.dll</code>&nbsp;with the following:</p>



<ul class="wp-block-list">
<li>Patched&nbsp;<code><a href="https://thebrokenpipe.com/uploads/pinball_fix/pinball.exe">pinball.exe</a></code></li>



<li>Patched&nbsp;<code><a href="https://thebrokenpipe.com/uploads/pinball_fix/mciseq.dll">mciseq.dll</a></code></li>
</ul>



<p class="wp-block-paragraph">You could also patch the installation files and burn them to a new CD if you want Pinball to work out of the box on fresh installs – simply copy these files to the&nbsp;<code>AXP64</code>&nbsp;directory of the install disc:</p>



<ul class="wp-block-list">
<li>Patched&nbsp;<code><a href="https://thebrokenpipe.com/uploads/pinball_fix/PINBALL.EX_">PINBALL.EX_</a></code></li>



<li>Patched&nbsp;<code><a href="https://thebrokenpipe.com/uploads/pinball_fix/MCISEQ.DL_">MCISEQ.DL_</a></code></li>
</ul>



<h2 class="wp-block-heading">The Bug</h2>



<p class="wp-block-paragraph">Now I’m going to disappoint you with the fact that I did not find the collision detector bug Raymond talked about. With the struct alignment and pointer truncation issues patched, the game now works flawlessly. Ok, I’m not sure if it’s actually flawless, but I never saw any glitches in the few games I played. At the very least, the ball does not fall through the plunger, can be launched and bounces around the table just fine.</p>


<div class="wp-block-image">
<figure class="aligncenter size-full"><a href="https://virtuallyfun.com/wp-content/uploads/2026/06/image-7.png"><img loading="lazy" decoding="async" width="648" height="490" src="https://virtuallyfun.com/wp-content/uploads/2026/06/image-7.png" alt="" class="wp-image-15795" srcset="https://virtuallyfun.com/wp-content/uploads/2026/06/image-7.png 648w, https://virtuallyfun.com/wp-content/uploads/2026/06/image-7-300x227.png 300w, https://virtuallyfun.com/wp-content/uploads/2026/06/image-7-397x300.png 397w" sizes="auto, (max-width: 648px) 100vw, 648px" /></a></figure>
</div>


<p class="wp-block-paragraph">Below are the 2 reasons I could think of for not seeing the collision detector bug:</p>



<ul class="wp-block-list">
<li>The bug was introduced after build 2210. Build 2210 has Pinball installed by default and predates Windows XP by almost a year and a half, so it almost certainly predates Raymond removing it. In this build, Pinball doesn’t even run by default, so there’s no way they could’ve tested it and seen the bug. They probably only started testing Pinball later, after they fixed the struct alignment and pointer truncation issues.</li>



<li>The bug only manifests in free/release builds, not in checked/debug builds. Maybe it only shows up when the code is compiled with the more aggressive optimisation used by release builds – something that happens quite often when code has undefined behaviour or the compiler has bugs. This is less plausible, however, as I’m sure Raymond would’ve used debug builds when he attempted to debug it, and discovered any differences between debug and retail builds.</li>
</ul>



<p class="wp-block-paragraph">Of course, only Raymond himself could shed more light on this topic. It was fun (<em>read</em>: painful) debugging Pinball, as well as the NT kernel to fix the emulators – too much fun (<em>read</em>: pain) that I will never do it again.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p class="wp-block-paragraph">Some trivia about me and pinball:</p>



<p class="wp-block-paragraph">I spent a fair chunk of my kindergarten and pre-school days playing the various games my dad installed on our Windows XP home computer, however, there was one game that I never quite figured out how to play – Pinball. It came bundled with the OS, and the splash screen scared me every time I tried to open it up.</p>


<div class="wp-block-image">
<figure class="aligncenter size-full"><img loading="lazy" decoding="async" width="424" height="282" src="https://virtuallyfun.com/wp-content/uploads/2026/06/image-8.png" alt="" class="wp-image-15796" srcset="https://virtuallyfun.com/wp-content/uploads/2026/06/image-8.png 424w, https://virtuallyfun.com/wp-content/uploads/2026/06/image-8-300x200.png 300w" sizes="auto, (max-width: 424px) 100vw, 424px" /></figure>
</div>


<p class="wp-block-paragraph">The flipper looked like a pistol to my 3-year-old self, and the overall darkness of the splash screen just injected fear into me. I would open the game, close my eyes, count to 20, then open my eyes again, to skip past the splash screen.</p>



<p class="wp-block-paragraph">The first time I actually played a full game of pinball was on the first day of this year, when a friend of mine took me to an arcade. After playing pinball in real life, the Pinball game finally started to make sense.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://virtuallyfun.com/2026/06/02/pinball-on-64-bit-alpha-axp-windows-nt/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Yet another GCC 1.40 *SOME ASSEBMLY REQUIRED</title>
		<link>https://virtuallyfun.com/2026/02/08/yet-another-gcc-1-40-some-assebmly-required/</link>
					<comments>https://virtuallyfun.com/2026/02/08/yet-another-gcc-1-40-some-assebmly-required/#respond</comments>
		
		<dc:creator><![CDATA[neozeed]]></dc:creator>
		<pubDate>Sun, 08 Feb 2026 13:33:41 +0000</pubDate>
				<category><![CDATA[80386]]></category>
		<category><![CDATA[assembly]]></category>
		<category><![CDATA[gcc]]></category>
		<category><![CDATA[i386]]></category>
		<category><![CDATA[Win32]]></category>
		<guid isPermaLink="false">https://virtuallyfun.com/?p=15612</guid>

					<description><![CDATA[Oh sure I&#8217;ve done this ages ago, getting GCC 1.40 to compile with old Microsoft C compilers, and then target Win32, it&#8217;s not that &#8216;special&#8217;. But I thought I&#8217;d try to get them to build with MASM so I could &#8230; <a href="https://virtuallyfun.com/2026/02/08/yet-another-gcc-1-40-some-assebmly-required/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
										<content:encoded><![CDATA[
<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="779" src="https://virtuallyfun.com/wp-content/uploads/2026/02/Screenshot-2026-02-07-at-7.22.17-PM-1024x779.png" alt="" class="wp-image-15613" srcset="https://virtuallyfun.com/wp-content/uploads/2026/02/Screenshot-2026-02-07-at-7.22.17-PM-1024x779.png 1024w, https://virtuallyfun.com/wp-content/uploads/2026/02/Screenshot-2026-02-07-at-7.22.17-PM-300x228.png 300w, https://virtuallyfun.com/wp-content/uploads/2026/02/Screenshot-2026-02-07-at-7.22.17-PM-768x584.png 768w, https://virtuallyfun.com/wp-content/uploads/2026/02/Screenshot-2026-02-07-at-7.22.17-PM-395x300.png 395w, https://virtuallyfun.com/wp-content/uploads/2026/02/Screenshot-2026-02-07-at-7.22.17-PM.png 1210w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><figcaption class="wp-element-caption">phoon</figcaption></figure>



<p class="wp-block-paragraph">Oh sure I&#8217;ve done this ages ago, getting GCC 1.40 to compile with old Microsoft C compilers, and then target Win32, it&#8217;s not that &#8216;special&#8217;.  But I thought I&#8217;d try to get them to build with MASM so I could just distribute this with an assembler.  Spelling out the joke of some assembly required.</p>



<p class="wp-block-paragraph">Although I wasn&#8217;t going to target/host OS/2 I was ideally going straight to Win32, the MASM 6.11 assembler couldn&#8217;t assemble the MSVC 1.0 / MSC/386 8.0 compiler&#8217;s assembly output, I needed to use the MASM 7 from Visual C++ 2003; namely:</p>



<pre class="wp-block-code"><code>Microsoft (R) Macro Assembler Version 7.10.3077 Copyright (C) Microsoft Corporation. All rights reserved.</code></pre>



<p class="wp-block-paragraph">MASM 6.11 was having issues with pushing OFFSET&#8217;s ie:</p>



<pre class="wp-block-code"><code>push OFFSET _obstack</code></pre>



<p class="wp-block-paragraph">when they were defined as:</p>



<pre class="wp-block-code"><code>COMM _obstack:BYTE:024H</code></pre>



<p class="wp-block-paragraph">Chat GPT to the rescue knowing that later MASM&#8217;s will just handle it just fine.  And it was right!  I know AI gets a bad rep, but surprisingly (or not when you think about what it&#8217;s been trained on), it&#8217;s got some great insight to some old things like seemingly common software tools, and old environments.</p>



<p class="wp-block-paragraph">I didn&#8217;t bother trying to use Microsoft C/386 6.0 &amp; MASM386 5.1 to see if it&#8217;ll handle CC1, as that seems to be a bit extreme. and I wanted this to run on semi modern Win32 stuff.  More so that there isn&#8217;t a 64bit SMP aware OS/2 with a modern web browser.  Kind of sad to be honese, but it&#8217;s 2026, and here we are.</p>



<p class="wp-block-paragraph">I as always stick to the <a href="https://github.com/neozeed/gas-1.38-xenix-">Xenix GAS port</a> that outputs 386 OMF objects that earlier linker&#8217;s can happily auto-convert to coff and use on Win32.  One day I feel I should ask why they were cross compiling NT/i386 from OS/2 1.21 instead of using Xenix?!  Must have been some fundamental NTOS/2 thing I suppose.</p>



<p class="wp-block-paragraph">I guess a refresher for anyone comming in out of the cold here&#8217;s a really poorly done block diagram of what goes on when a traditional (GCC) compiler runs.  Explaniation is here: <a href="https://virtuallyfun.com/2024/01/08/so-it-turns-out-gcc-could-have-been-available-on-windows-nt-the-entire-time/">so it turns out GCC could have been available on Windows NT the entire time</a>.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="384" src="https://virtuallyfun.com/wp-content/uploads/2024/01/gcc-program-flow-1024x384.png" alt="GCC program flow" class="wp-image-13731" srcset="https://virtuallyfun.com/wp-content/uploads/2024/01/gcc-program-flow-1024x384.png 1024w, https://virtuallyfun.com/wp-content/uploads/2024/01/gcc-program-flow-300x112.png 300w, https://virtuallyfun.com/wp-content/uploads/2024/01/gcc-program-flow-768x288.png 768w, https://virtuallyfun.com/wp-content/uploads/2024/01/gcc-program-flow-1536x575.png 1536w, https://virtuallyfun.com/wp-content/uploads/2024/01/gcc-program-flow-500x187.png 500w, https://virtuallyfun.com/wp-content/uploads/2024/01/gcc-program-flow.png 1962w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p class="wp-block-paragraph">Long story there was that the Xenix GAS emits an ancient 386 OMF format that for unknown reaons the older Microsoft Linkers happily accept and auto convert into COFF, the file format of the future (Future being 1988).  I guess for better. or worse we never got NT/ELF.  Oh and speaking of further weird, the IBM version of their LINK386 doesn&#8217;t like the Xenix 386 OMF.  Bummer.</p>



<p class="wp-block-paragraph">One thing I found out is that the MASM v7 doesn&#8217;t output COFF by default, rather it&#8217;s 386 OMF!  you need to add the /coff flag to force it to be more Win32 friendly.  Kind of unexpected behaviour.</p>



<p class="wp-block-paragraph">I tried to make this simple as, clone the repo and run &#8216;build.cmd&#8217; it&#8217;ll link up GCC and then build the test programs, and clean up after itself.</p>



<p class="wp-block-paragraph"><a href="https://github.com/neozeed/gcc140-masm" target="_blank" rel="noreferrer noopener">https://github.com/neozeed/gcc140-masm</a></p>



<p class="wp-block-paragraph">I&#8217;d tried to emit assembly for the Xenix GAS, but for some reason it&#8217;s struggling with floating point.  I&#8217;m not sure, I tried using chat gpt to debug but it get&#8217;s confused on how this whole bizzare tool chain is working.  I guess I can&#8217;t blame it.</p>



<p class="wp-block-paragraph">Sorry it&#8217;s been a while, been feeling &#8216;life&#8217; lately.  I had some i7 project as a kicker for a retro Windows 10 build thing to do but watchign the RAM crissis unfold and well life&#8230; I just got feeling like it&#8217;s so irrelevant who&#8217;d care.  That and it&#8217;s insane watching $1.11 worth of DDR3 RAM now selling for $30++ &#8230;. and more and more chip manufacturers are exiting.  So it felt like maybe go back and do more with less.  Even a low end machine can assemble this in seconds!</p>
]]></content:encoded>
					
					<wfw:commentRss>https://virtuallyfun.com/2026/02/08/yet-another-gcc-1-40-some-assebmly-required/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Thunking for fun &#038; a lack of profit</title>
		<link>https://virtuallyfun.com/2024/02/19/thunking-for-fun-a-lack-of-profit/</link>
					<comments>https://virtuallyfun.com/2024/02/19/thunking-for-fun-a-lack-of-profit/#respond</comments>
		
		<dc:creator><![CDATA[neozeed]]></dc:creator>
		<pubDate>Mon, 19 Feb 2024 00:35:16 +0000</pubDate>
				<category><![CDATA[80386]]></category>
		<category><![CDATA[assembly]]></category>
		<category><![CDATA[gcc]]></category>
		<category><![CDATA[i386]]></category>
		<category><![CDATA[OS/2]]></category>
		<category><![CDATA[OS/2 2.0]]></category>
		<guid isPermaLink="false">https://virtuallyfun.com/?p=13988</guid>

					<description><![CDATA[So, with a renewed interest in OS/2 betas, I&#8217;d been getting stuff into the direction of doing some full screen video. I&#8217;d copied and pasted stuff before and gotten QuakeWorld running, and I was looking forward to this challenge. The &#8230; <a href="https://virtuallyfun.com/2024/02/19/thunking-for-fun-a-lack-of-profit/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">So, with a renewed interest in OS/2 betas, I&#8217;d been getting stuff into the direction of doing some full screen video.  I&#8217;d copied and pasted stuff before and gotten QuakeWorld running, and I was looking forward to this challenge.  The whole thing hinges on the VIO calls in OS/2 like VioScrLock, VioGetPhysBuf, VioScrUnLock etc etc.  I found a nifty sample program <a href="https://jeffpar.github.io/kbarchive/kb/059/Q59837/" target="_blank" rel="noreferrer noopener">Q59837</a> which shows how to map into the MDA card&#8217;s text RAM and clear it.</p>



<p class="wp-block-paragraph">It&#8217;s a 16bit program, but first I got it to run on EMX with just a few minor changes, like removing far pointers.  Great.  But I wanted to build it with my <a href="https://virtuallyfun.com/2024/02/11/targeting-os-2-with-visual-studio-2003/" target="_blank" rel="noreferrer noopener">cl386 experiments</a> and that went off the edge.  First there are some very slick macros, and Microsoft C just can&#8217;t deal with them.  Fine I&#8217;ll use <a href="https://virtuallyfun.com/2024/02/10/porting-gcc-to-32bit-os-2/" target="_blank" rel="noreferrer noopener">GCC</a>.  Then I had to get emximpl working so I could build an import library for VIO calls.  I exported the assembly from GCC, and mangled it enough to where I could link it with the old Microsoft linker, and things were looking good!  I could clear the video buffer on OS/2 2.00 GA.</p>



<p class="wp-block-paragraph">Now why was it working? What is a THUNK?  Well it turns out in the early OS/2 2.0 development, they were going to cut loose all the funky text mode video, keyboard &amp; mouse support and go all in on the graphical Presentation Manager.</p>



<figure class="wp-block-image size-full"><a href="/wp-content/uploads/2024/02/605-busy-desktop.png" target="_blank" rel="noreferrer noopener"><img loading="lazy" decoding="async" width="797" height="593" src="/wp-content/uploads/2024/02/605-busy-desktop.png" alt="" class="wp-image-13992" srcset="https://virtuallyfun.com/wp-content/uploads/2024/02/605-busy-desktop.png 797w, https://virtuallyfun.com/wp-content/uploads/2024/02/605-busy-desktop-300x223.png 300w, https://virtuallyfun.com/wp-content/uploads/2024/02/605-busy-desktop-768x571.png 768w, https://virtuallyfun.com/wp-content/uploads/2024/02/605-busy-desktop-403x300.png 403w" sizes="auto, (max-width: 797px) 100vw, 797px" /></a><figcaption class="wp-element-caption">Presentation Manager from OS/2 6.605</figcaption></figure>



<p class="wp-block-paragraph">Instead, they were going to leave that old stuff in the past, and 16bit only for keeping some backwards compatibility.  And the only way a 32bit program can use those old 16bit API&#8217;s for video/keyboard/mouse (etc) is to call from 32bit mode into 16bit mode, then copy that data out of 16bit mode into 32bit mode.  This round trip is called thunking, and well this sets up where it all goes wrong. </p>



<p class="wp-block-paragraph">Then I tried one of the earlier PM looking betas <a href="https://archive.org/details/os2-2.0-6.605" target="_blank" rel="noreferrer noopener">6.605</a>, and quickly it crashed!</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="887" height="292" src="/wp-content/uploads/2024/02/SYS_2070.png" alt="" class="wp-image-13989" srcset="https://virtuallyfun.com/wp-content/uploads/2024/02/SYS_2070.png 887w, https://virtuallyfun.com/wp-content/uploads/2024/02/SYS_2070-300x99.png 300w, https://virtuallyfun.com/wp-content/uploads/2024/02/SYS_2070-768x253.png 768w, https://virtuallyfun.com/wp-content/uploads/2024/02/SYS_2070-500x165.png 500w" sizes="auto, (max-width: 887px) 100vw, 887px" /><figcaption class="wp-element-caption">SYS2070:</figcaption></figure>



<p class="wp-block-paragraph">Well this was weird.  Obviously, I wanted to display help</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="895" height="362" src="/wp-content/uploads/2024/02/SYS_2070_2.png" alt="" class="wp-image-13990" srcset="https://virtuallyfun.com/wp-content/uploads/2024/02/SYS_2070_2.png 895w, https://virtuallyfun.com/wp-content/uploads/2024/02/SYS_2070_2-300x121.png 300w, https://virtuallyfun.com/wp-content/uploads/2024/02/SYS_2070_2-768x311.png 768w, https://virtuallyfun.com/wp-content/uploads/2024/02/SYS_2070_2-500x202.png 500w" sizes="auto, (max-width: 895px) 100vw, 895px" /><figcaption class="wp-element-caption">Explanation:</figcaption></figure>



<p class="wp-block-paragraph">This ended up being a long winded way of saying that there is missing calls from DOSCALL1.DLL.  Looking through all the EMX thunking code, I came to the <a href="https://github.com/neozeed/Q59837-mono/blob/main/thunk0.asm#L12" target="_blank" rel="noreferrer noopener">low level assembly</a>, that actually implemented the thunking.</p>



<pre class="wp-block-code"><code>EXTRN   DosFlatToSel:PROC
EXTRN   DosSelToFlat:PROC</code></pre>



<p class="wp-block-paragraph">After looking at the doscalls import library, sure enough they just don&#8217;t exist.  I did the most unspeakable thing and looked at the online help for guidance:</p>



<figure class="wp-block-image size-full"><a href="/wp-content/uploads/2024/02/no-vio.png" target="_blank" rel="noreferrer noopener"><img loading="lazy" decoding="async" width="738" height="197" src="/wp-content/uploads/2024/02/no-vio.png" alt="" class="wp-image-13991" srcset="https://virtuallyfun.com/wp-content/uploads/2024/02/no-vio.png 738w, https://virtuallyfun.com/wp-content/uploads/2024/02/no-vio-300x80.png 300w, https://virtuallyfun.com/wp-content/uploads/2024/02/no-vio-500x133.png 500w" sizes="auto, (max-width: 738px) 100vw, 738px" /></a><figcaption class="wp-element-caption">No VIO</figcaption></figure>



<p class="wp-block-paragraph">So it turns out that in the early beta phase, there was no support for any of the 16bit IO from 32bit mode.  There was no thunking at all.  You were actually expected to use Presentation Manager.</p>



<p class="wp-block-paragraph">YUCK</p>



<p class="wp-block-paragraph">For anyone crazy enough to care, I uploaded this onto github <a href="https://github.com/neozeed/Q59837-mono/" target="_blank" rel="noreferrer noopener">Q59837-mono</a></p>



<p class="wp-block-paragraph">It did work on the GA however so I guess I&#8217;m still on track there.  </p>
]]></content:encoded>
					
					<wfw:commentRss>https://virtuallyfun.com/2024/02/19/thunking-for-fun-a-lack-of-profit/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Targeting OS/2 with Visual Studio 2003</title>
		<link>https://virtuallyfun.com/2024/02/11/targeting-os-2-with-visual-studio-2003/</link>
					<comments>https://virtuallyfun.com/2024/02/11/targeting-os-2-with-visual-studio-2003/#comments</comments>
		
		<dc:creator><![CDATA[neozeed]]></dc:creator>
		<pubDate>Sun, 11 Feb 2024 09:08:22 +0000</pubDate>
				<category><![CDATA[assembly]]></category>
		<category><![CDATA[OS/2 2.0]]></category>
		<category><![CDATA[Visual C++]]></category>
		<category><![CDATA[Visual C++ toolkit 2003]]></category>
		<category><![CDATA[Visual Studio 2003]]></category>
		<category><![CDATA[Watcom C++]]></category>
		<category><![CDATA[Win32]]></category>
		<guid isPermaLink="false">https://virtuallyfun.com/?p=13926</guid>

					<description><![CDATA[No, it&#8217;s not a typo. This is a long-winded post, but the short version is that I found a working combination to get the C compiler from Visual Studio 2003 targeting OS/2. Once I&#8217;d learned how C compilers are a &#8230; <a href="https://virtuallyfun.com/2024/02/11/targeting-os-2-with-visual-studio-2003/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
										<content:encoded><![CDATA[
<figure class="wp-block-image size-full"><a href="/wp-content/uploads/2024/02/syneys-idea-of-visual-c-for-os2.jpg"><img loading="lazy" decoding="async" width="1024" height="1024" src="/wp-content/uploads/2024/02/syneys-idea-of-visual-c-for-os2.jpg" alt="" class="wp-image-13931" srcset="https://virtuallyfun.com/wp-content/uploads/2024/02/syneys-idea-of-visual-c-for-os2.jpg 1024w, https://virtuallyfun.com/wp-content/uploads/2024/02/syneys-idea-of-visual-c-for-os2-300x300.jpg 300w, https://virtuallyfun.com/wp-content/uploads/2024/02/syneys-idea-of-visual-c-for-os2-150x150.jpg 150w, https://virtuallyfun.com/wp-content/uploads/2024/02/syneys-idea-of-visual-c-for-os2-768x768.jpg 768w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a><figcaption class="wp-element-caption">Sydney&#8217;s idea of what Visual C++ for OS/2 should look like</figcaption></figure>



<p class="wp-block-paragraph">No, it&#8217;s not a typo.</p>



<p class="wp-block-paragraph">This is a long-winded post, but the short version is that I found a working combination to get the C compiler from Visual Studio 2003 targeting OS/2.</p>



<p class="wp-block-paragraph">Once I&#8217;d learned how C compilers are a collection of programs working in concert, I&#8217;d always wanted to force Microsoft C to work in that fashion, however it is born to be a compiler that integrates everything but linking. There has been a &#8220;/Fa&#8221; or output assembly option, but I&#8217;ve never gotten it to do anything useful.  I&#8217;m not that much into assembly but it seemed insurmountable.</p>



<p class="wp-block-paragraph">But for some reason this time things were different.</p>



<p class="wp-block-paragraph">This time I used:</p>



<p class="wp-block-paragraph"><strong>Microsoft (R) Macro Assembler Version 6.11</strong></p>



<p class="wp-block-paragraph">After the great divorce and the rise of Windows NT, Microsoft had shifted from the OMF format to COFF.  However somewhere buried in their old tools it still supports it, namely MASM.  For example, if I try to run LINK386 (the OS/2 Linker) against output from Visual C++ 2003 I get his</p>



<pre class="wp-block-code"><code>abandon.obj :  fatal error L1101: invalid object module
 Object file offset: 1  Record type: 4c</code></pre>



<p class="wp-block-paragraph">However if I output to assembly and then have MASM assemble that, and try the linker, I&#8217;m bombarded with errors like this:</p>



<pre class="wp-block-code"><code>warp.obj(warp.asm) :  error L2025: __real@4059000000000000 : symbol defined more than once
warp.obj(warp.asm) :  error L2029: '__ftol2' : unresolved external</code></pre>



<p class="wp-block-paragraph">If I was smart I&#8217;d have given up, there is pages and pages of this stuff.  But I&#8217;m not smart, so instead I decided to something different, and use SED, the stream editor, and try to patch out the errors.</p>



<p class="wp-block-paragraph">The ftol2 call is for newer CPU&#8217;s and any OS/2 library won&#8217;t have it.  But instead of binary editing symbols we can replace the ftol2 with ftol with this simple line:</p>



<pre class="wp-block-code"><code> sed -e 's/_ftol2/_ftol/g'</code></pre>



<p class="wp-block-paragraph">For some reason Visual C++ likes to make all it&#8217;s reals &#8220;public&#8221; meaning there can only be one, but yet there is so many.  Why not comment them all out?</p>



<pre class="wp-block-code"><code>sed -e 's/PUBLIC\t__real@/;PUBLIC\t__real@/g'</code></pre>



<p class="wp-block-paragraph">And there are various other annoying things, but again they can be all patched out.  Just as the older Windows 1991 Pre-release compilers also have weird syntax that MASM doesn&#8217;t understand.</p>



<pre class="wp-block-code"><code>astro.asm(59): error A2138: invalid data initializer</code></pre>



<p class="wp-block-paragraph">which goes into how Microsoft C used to initialize floating point constants:</p>



<pre class="wp-block-code"><code>CONST   SEGMENT  DWORD USE32 PUBLIC 'CONST'
$T20000         DQ      0a0ce51293ee845c8r    ; 1.157407407407407E-05
$T20001         DQ      0bffffd3441429ec5r    ; 2440587.499999667
CONST      ENDS</code></pre>



<p class="wp-block-paragraph">while I found that the C compiler in Xenix 386 initialises them like this:</p>



<pre class="wp-block-code"><code>$T20000         DQ      0a0ce51293ee845c8h    ; 1.157407407407407E-05
$T20001         DQ      0bffffd3441429ec5h    ; 2440587.499999667</code></pre>



<p class="wp-block-paragraph">This one was a little hard for me as I&#8217;m not a sed expert, but I did figure out how to mark the section, and then to replace it</p>



<pre class="wp-block-code"><code>sed -e "s/DQ\t&#91;0-9a-f]<em>r/&amp;XMMMMMMX/g" $</em>.a1 |  sed -e "s/rXMMMMMMX/H/g"</code></pre>



<p class="wp-block-paragraph">And so on.  At the moment my &#8216;mangle&#8217; script is now this:</p>



<pre class="wp-block-code"><code>.c.obj:
        $(CC) $(INC) $(OPT) $(DEBUG) /c /Fa$*.a $*.c
        wsl sed -e 's/FLAT://g' $*.a &gt; $*.a1
        wsl sed -e "s/DQ\t&#91;0-9a-f]*r/&amp;XMMMMMMX/g" $*.a1 \
        | wsl sed -e "s/rXMMMMMMX/H/g" \
        | wsl sed -e 's/call \t\&#91;/call DWORD PTR\&#91;/g' \
        | wsl sed -e 's/PUBLIC\t__real@/;PUBLIC\t__real@/g' \
        | wsl sed -e 's/_ftol2/_ftol/g' &gt; $*.asm
        ml /c $*.asm
        del $*.a $*.a1 $*.asm</code></pre>



<p class="wp-block-paragraph">This allows me to plug it into a Makefile, so I only have to edit it in one place.</p>



<p class="wp-block-paragraph">Not surprisingly, this allows the LINK from Visual C++ 1.0 to link the MASM generated object files and get a native Win32 executable.  Even from the oldest compiler I have from the Microsoft OS/2 2.00 Beta 2 SDK from 1989!</p>



<p class="wp-block-paragraph">But now that we have the C compilers being able to output to something we can edit and force into a Win32, there is a few more things and suddenly:</p>



<pre class="wp-block-code"><code>        C:\cl386-research\bin\13.10.6030\cl386 /u /w /G3 /O  /c /Faphoon.a phoon.c
C:\cl386-research\bin\13.10.6030\CL386.EXE: warning: invoking C:\cl386-research\bin\13.10.6030\CL.EXE
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 13.10.6030 for 80x86
Copyright (C) Microsoft Corporation 1984-2002. All rights reserved.

phoon.c
        wsl sed -e 's/FLAT://g' phoon.a &gt; phoon.a1
        wsl sed -e "s/DQ\t&#91;0-9a-f]*r/&amp;XMMMMMMX/g" phoon.a1  | wsl sed -e "s/rXMMMMMMX/H/g"  | wsl sed -e 's/call \t\&#91;/call DWORD PTR\&#91;/g'  | wsl sed -e 's/PUBLIC\t__real@/;PUBLIC\t__real@/g'  | wsl sed -e 's/_ftol2/_ftol/g' &gt; phoon.asm
        ml /c phoon.asm
Microsoft (R) Macro Assembler Version 6.11
Copyright (C) Microsoft Corp 1981-1993.  All rights reserved.

 Assembling: phoon.asm
        del phoon.a phoon.a1 phoon.asm
        msdos286 run286 C:\cl386-research\bin\ddk12\LINK386.EXE @phoon.lnk

Operating System/2 Linear Executable Linker
Version 2.01.012 Nov 02 1993
Copyright (C) IBM Corporation 1988-1993.
Copyright (C) Microsoft Corp. 1988-1993.
 All rights reserved.

Object Modules &#91;.obj]: astro.obj date_p.obj phoon.obj
Run File &#91;astro.exe]: phoon2 /NOE /NOI /NOD:OLDNAMES
List File &#91;nul.map]: nul.map
Libraries &#91;.lib]: ..\..\lib2\libc.lib +
Libraries &#91;.lib]: ..\..\lib2\os2386.lib
Definitions File &#91;nul.def]: nul.def;
LINK386 :  warning L4071: application type not specified; assuming WINDOWCOMPAT</code></pre>



<p class="wp-block-paragraph">I know it&#8217;s a bit of a word salad, but the key thing here is that using Visual C++ 2003&#8217;s compiler (version 13.10.6030), and outputting to assembly that we can edit, we can then use MASM to build objects that surprisingly LINK386 version 2.01.012 will link with.  I suspect this has to do with device drivers, and probably the majority of the OS/2 operating system.</p>



<p class="wp-block-paragraph">Anways, we&#8217;ve done the incredible, using the same object files, we made both a Win32 application, and an OS/2 application!</p>



<pre class="wp-block-code"><code>phoon-13.10.6030.exe: PE32 executable (console) Intel 80386, for MS Windows<br>phoon2.exe: MS-DOS executable, LX for OS/2 (console) i80386</code></pre>



<figure class="wp-block-image size-full"><a href="/wp-content/uploads/2024/02/phoon-on-os2-compiled-by-visual-cplus-plus-2003.png"><img loading="lazy" decoding="async" width="802" height="633" src="/wp-content/uploads/2024/02/phoon-on-os2-compiled-by-visual-cplus-plus-2003.png" alt="" class="wp-image-13927" srcset="https://virtuallyfun.com/wp-content/uploads/2024/02/phoon-on-os2-compiled-by-visual-cplus-plus-2003.png 802w, https://virtuallyfun.com/wp-content/uploads/2024/02/phoon-on-os2-compiled-by-visual-cplus-plus-2003-300x237.png 300w, https://virtuallyfun.com/wp-content/uploads/2024/02/phoon-on-os2-compiled-by-visual-cplus-plus-2003-768x606.png 768w, https://virtuallyfun.com/wp-content/uploads/2024/02/phoon-on-os2-compiled-by-visual-cplus-plus-2003-380x300.png 380w" sizes="auto, (max-width: 802px) 100vw, 802px" /></a><figcaption class="wp-element-caption">Phoon compiled by Visual C++ 2003 on OS/2 2.00</figcaption></figure>



<p class="wp-block-paragraph">Incidentally Happy CNY!</p>



<p class="wp-block-paragraph">Obviously, this is <em>VERY</em> cool stuff.</p>



<p class="wp-block-paragraph">I know the next question is do we have to rely on a 16bit linker?  How about Watcom?</p>



<pre class="wp-block-code"><code>C:\cl386-research\proj\trek&gt;wlink @trek.wlk
WATCOM Linker Version 10.0
Copyright by WATCOM International Corp. 1985, 1994. All rights reserved.
WATCOM is a trademark of WATCOM International Corp.
loading object files
searching libraries
Warning(1008): cannot open LIBC.lib : No such file or directory
Warning(1008): cannot open OLDNAMES.lib : No such file or directory
creating an OS/2 32-bit executable
</code></pre>



<p class="wp-block-paragraph">Ignore the warnings and <strong><em>YES</em></strong> <em>we can</em> Link from something much newer &amp; 32bit!  In this example I linked the old TREK game, also built with Visual C++ 2003.  The response file looks lke:</p>



<pre class="wp-block-code"><code>SYS os2v2
NAME trek2w
FILE abandon.obj,attack.obj,autover.obj,capture.obj,cgetc.obj,checkcond.obj
FILE check_out.obj,compkl.obj,computer.obj,damage.obj,damaged.obj,dcrept.obj
FILE destruct.obj,dock.obj,dumpgame.obj,dumpme.obj,dumpssradio.obj,events.obj
FILE externs.obj,getcodi.obj,getpar.obj,help.obj,impulse.obj,initquad.obj
FILE kill.obj,klmove.obj,lose.obj,lrscan.obj,main.OBJ,move.obj
FILE nova.obj,nullsleep.obj,out.obj,phaser.obj,play.obj,ram.obj
FILE ranf.obj,rest.obj,schedule.obj,score.obj,setup.obj,setwarp.obj
FILE shield.obj,snova.obj,srscan.obj,systemname.obj,torped.obj,utility.obj
FILE visual.obj,warp.obj,win.obj
LIBR ..\..\lib2\LIBC.LIB
LIBR ..\..\lib2\OS2386.LIB</code></pre>



<p class="wp-block-paragraph">It&#8217;s probably needing additional stack space, maybe some other stuff, or resources, maybe how to flag it&#8217;s windowing compatible.</p>



<figure class="wp-block-image size-full"><a href="/wp-content/uploads/2024/02/watcom-linked-trek.png" target="_blank" rel="noreferrer noopener"><img loading="lazy" decoding="async" width="770" height="412" src="/wp-content/uploads/2024/02/watcom-linked-trek.png" alt="" class="wp-image-13928" srcset="https://virtuallyfun.com/wp-content/uploads/2024/02/watcom-linked-trek.png 770w, https://virtuallyfun.com/wp-content/uploads/2024/02/watcom-linked-trek-300x161.png 300w, https://virtuallyfun.com/wp-content/uploads/2024/02/watcom-linked-trek-768x411.png 768w, https://virtuallyfun.com/wp-content/uploads/2024/02/watcom-linked-trek-500x268.png 500w" sizes="auto, (max-width: 770px) 100vw, 770px" /></a><figcaption class="wp-element-caption">TREK built by Visual C++ 2003, and Linked using Watcom C/C++ 10.0</figcaption></figure>



<p class="wp-block-paragraph">How do I get started, if I dare?!  First download and unpack <a href="https://archive.org/details/cl386-research-v2">cl386-research-v2</a>.  Ideally on the root of your C: drive, because why not?</p>



<p class="wp-block-paragraph">run the &#8216;env&#8217; command to set your environment up. Its pretty complicated but in the proj directly there is currently:</p>



<p class="wp-block-paragraph"><strong>*NOTE</strong> that I do use <strong>SED</strong> scripts, I have it set to use Linux in the WSL package.<br>I tried some Win32 sed but it didn&#8217;t work. So you need <strong>WSL</strong> or a working sed!</p>



<ul class="wp-block-list">
<li>bench</li>



<li>doom</li>



<li>info</li>



<li>phoon</li>



<li>trek</li>



<li>(<a href="https://github.com/neozeed/cl386-research" target="_blank" rel="noreferrer noopener">more stuff being added or updated on github</a>)</li>
</ul>



<p class="wp-block-paragraph">you can then go into each directory and run</p>



<pre class="wp-block-code"><code>make os2</code></pre>



<p class="wp-block-paragraph">and it&#8217;ll compile populate a floppy and launch the emulator</p>



<p class="wp-block-paragraph">Its all good fun.</p>



<p class="wp-block-paragraph">Read the Makefiles to configure a compiler, how to run it, and if you need to mangle the assembly. The 32bit new stuff needs to be mangled, the older stuff almost always works with just compile.</p>



<pre class="wp-block-code"><code># Version 6.00.054      1989
# https://archive.org/details/os-2-cd-rom_202401
PLATFORM = ddksrc</code></pre>



<p class="wp-block-paragraph">In this case it&#8217;ll select the platform from the &#8216;ddksdk&#8217; release. The next is if the compiler is OS/2 based or native win32. Basically 73g / windows 95 &amp; below are native Win32.</p>



<p class="wp-block-paragraph">In the above example we comment out the dos extended cross</p>



<pre class="wp-block-code"><code># dos exteded cross
CC =  $(EMU) $(DOSX) $(CL386ROOT)\$(PLATFORM)\cl386
# native CC
# CC =  $(CL386ROOT)\$(PLATFORM)\cl386</code></pre>



<p class="wp-block-paragraph">Next is the mangle strategy. In this case it&#8217;s an ancient OS/2 (like) compile so<br>try un commenting the &#8216;just compile&#8217; line</p>



<pre class="wp-block-code"><code># must include ONLY ONE strategey..
# for OS/2 it must have been assembled my MASM 6.11

include ..\-justcompile.mak
#include ..\-mangleassembly.mak
#include ..\-plainassembly.mak</code></pre>



<p class="wp-block-paragraph">save the makefile, and run</p>



<pre class="wp-block-code"><code>nmake os2</code></pre>



<p class="wp-block-paragraph">You can just close the emulator as after each run it&#8217;ll unpack a hard disk image, so nothing will be lost. or saved. It&#8217;s just for testing.  You may need to periodically clean the floppy drive, as that is the only way to transfer stuff in and out of the VM.</p>



<p class="wp-block-paragraph">What versions of CL386 have I found?  Well, it&#8217;s quite a few, although I know I&#8217;m missing quite a few.  </p>



<pre class="wp-block-code"><code>== c386 ============================
Microsoft C 5 386 Compiler

Microsoft C 5.2 286/386 Compiler -- Driver

@(#)C Compiler Apr 19 1990 11:48:30

Copyright (c) Microsoft Corp
1984-1989. All rights reserved.
  (press &lt;return&gt; to continue)
Microsoft 386 C Compiler. Version 1.00.075
Quick C Compiler Version 2.00.000
1.00.075

== ddk12 ============================

C 6.00 (Alpha) Aug 24 1990 19:12:31

Copyright (c) Microsoft Corp
1984-1989. All rights reserved.
  (press &lt;return&gt; to continue)
Microsoft 386 C Compiler. Version 6.00.054
Quick C Compiler Version 2.00.000
6.00.054

== ddk20 ============================

C 6.00 (Alpha) Aug 16 1990 23:04:06

Copyright (c) Microsoft Corp
1984-1989. All rights reserved.
  (press &lt;return&gt; to continue)
Microsoft 386 C Compiler. Version 6.00.054
Quick C Compiler Version 2.00.000
6.00.054

== ddksrc ============================

C 6.00 (Alpha) Aug 24 1990 19:21:49

Copyright (c) Microsoft Corp
1984-1989. All rights reserved.
  (press &lt;return&gt; to continue)
Microsoft 386 C Compiler. Version 6.00.054
Quick C Compiler Version 2.00.000
6.00.054

== nt-sep ============================

@(#)C Compiler 6.00 Feb 06 1991 17:15:19
@(#)C Compiler 6.00 May 13 1991 23:54:12
@(#)C Compiler 6.00 Jun 03 1991 15:16:22


Copyright (c) Microsoft Corp
1984-1991. All rights reserved.
  (press &lt;return&gt; to continue)
Microsoft 386 C Compiler. Version 6.00.077
Quick C Compiler Version 2.00.000
6.00.077

== nt-oct ============================

@(#)C Compiler 6.00 Jun 03 1991 15:16:22
@(#)C Compiler 6.00 Jun 13 1991 22:07:23
@(#)C Compiler 6.00 Oct 10 1991 00:42:24

Copyright (c) Microsoft Corp
1984-1991. All rights reserved.
  (press &lt;return&gt; to continue)
Microsoft 386 C Compiler. Version 6.00.080
Quick C Compiler Version 2.00.000
6.00.080

== nt-dec ============================
@(#)C Compiler 6.00 Jun 03 1991 15:16:22
@(#)C Compiler 6.00 Jun 13 1991 22:07:23
@(#)C Compiler 6.00 Oct 10 1991 00:42:24

Copyright (c) Microsoft Corp
1984-1991. All rights reserved.
  (press &lt;return&gt; to continue)
Microsoft 386 C Compiler. Version 6.00.081
Quick C Compiler Version 2.00.000
6.00.081

== 73g  ============================
1984-1993. All rights reserved.
Copyright (c) Microsoft Corp
8.00.3200
32-bit C/C++ Optimizing Compiler Version
Microsoft (R)


== msvc32s ============================

Microsoft 8.00.0000 - Copyright (C) 1986-1993 Microsoft Corp.
Microsoft 8.00.0000 - Copyright (C) 1986-1993 Microsoft Corp.
@(#) Microsoft C/C++ 32 bits x86 Compiler Version 8.00.XXXX

8.00.000

== 13.10.6030 ============================

Microsoft (R) C/C++ Compiler Version 13.10.6030
From my install of Visual Studio 2003 Enterprise</code></pre>



<p class="wp-block-paragraph">As you can see many of these earlier OS/2 compilers report the same versions but are in fact different builds on the inside.  I suspect Microsoft had to support one version, and an Alpha version of version 6 is as good as it got.  I would have imagined there were internal 32bit versions of 6 or 7, but I haven&#8217;t seen them.</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="960" height="609" src="/wp-content/uploads/2024/02/trek_3.gif" alt="" class="wp-image-13936"/><figcaption class="wp-element-caption">Compiling and running TREK</figcaption></figure>



<p class="wp-block-paragraph">Hopefully this gives some idea of how I tried to made a probably too modular build system to try all kinds of different compilers.  I might have to see if it&#8217;s possible to run the tools from the 1992 versions of Windows NT in this setup, perhaps they are interesting as well.</p>



<p class="wp-block-paragraph">One thing in my <a href="https://virtuallyfun.com/2024/02/10/porting-gcc-to-32bit-os-2/" target="_blank" rel="noreferrer noopener">porting GCC to OS/2 experience</a> is that the usability of the C compilers from 1991 were dramatically better than what Microsoft had given IBM at the time of the divorce.  No doubt the upcoming NTOS/2 project was placing a bigger demand on the tools team.</p>



<p class="wp-block-paragraph">If anyone has any access to other &#8216;cl386&#8217; compilers, or early OS/2 2.00 stuff, please let me know!  I&#8217;d love to do build/tests and see if my idea of distributing objects &#8216;just works&#8217;!</p>
]]></content:encoded>
					
					<wfw:commentRss>https://virtuallyfun.com/2024/02/11/targeting-os-2-with-visual-studio-2003/feed/</wfw:commentRss>
			<slash:comments>4</slash:comments>
		
		
			</item>
		<item>
		<title>Totally unfair comparison of Microsoft C</title>
		<link>https://virtuallyfun.com/2024/02/05/totally-unfair-comparison-of-microsoft-c/</link>
					<comments>https://virtuallyfun.com/2024/02/05/totally-unfair-comparison-of-microsoft-c/#respond</comments>
		
		<dc:creator><![CDATA[neozeed]]></dc:creator>
		<pubDate>Mon, 05 Feb 2024 03:15:48 +0000</pubDate>
				<category><![CDATA[80386]]></category>
		<category><![CDATA[assembly]]></category>
		<category><![CDATA[i386]]></category>
		<category><![CDATA[microsoft]]></category>
		<category><![CDATA[OS/2]]></category>
		<category><![CDATA[OS/2 2.0]]></category>
		<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[Win32]]></category>
		<guid isPermaLink="false">https://virtuallyfun.com/?p=13896</guid>

					<description><![CDATA[Because I hate myself, I tried to get the Microsoft OS/2 Beta 2 SDK&#8217;s C compiler building simple stuff for text mode NT. Because, why not?! Since the object files won&#8217;t link, we have to go in with assembly. And &#8230; <a href="https://virtuallyfun.com/2024/02/05/totally-unfair-comparison-of-microsoft-c/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">Because I hate myself, I tried to get the Microsoft OS/2 Beta 2 SDK&#8217;s C compiler building simple stuff for text mode NT.  Because, why not?!</p>



<p class="wp-block-paragraph">Since the object files won&#8217;t link, we have to go in with assembly.  And that of course doesn&#8217;t directly assemble, but it just needs a little hand holding:</p>



<pre class="wp-block-code"><code>Microsoft (R) Program Maintenance Utility   Version 1.40
Copyright (c) Microsoft Corp 1988-93. All rights reserved.

        cl386 /Ih /Ox /Zi /c /Fadhyrst.a dhyrst.c
Microsoft (R) Microsoft 386 C Compiler. Version 1.00.075
Copyright (c) Microsoft Corp 1984-1989. All rights reserved.

dhyrst.c
        wsl sed -e 's/FLAT://g' dhyrst.a &gt; dhyrst.a1
        wsl sed -e "s/DQ\t&#91;0-9a-f]*r/&amp;XMMMMMMX/g" dhyrst.a1  | wsl sed -e "s/rXMMMMMMX/H/g" &gt; dhyrst.asm
        ml /c dhyrst.asm
Microsoft (R) Macro Assembler Version 6.11
Copyright (C) Microsoft Corp 1981-1993.  All rights reserved.

 Assembling: dhyrst.asm
        del dhyrst.a dhyrst.a1 dhyrst.asm
        link -debug:full -out:dhyrst.exe dhyrst.obj libc.lib
Microsoft (R) 32-Bit Executable Linker Version 1.00
Copyright (C) Microsoft Corp 1992-93. All rights reserved.
</code></pre>



<p class="wp-block-paragraph">I use sed to remove the FLAT: directives which makes everything upset.  Also there is some weird confusion on how to pad float constants and encode them.</p>



<pre class="wp-block-code"><code>CONST   SEGMENT  DWORD USE32 PUBLIC 'CONST'
$T20001         DQ      0040f51800r    ;        86400.00000000000
CONST      ENDS</code></pre>



<p class="wp-block-paragraph">MASM 6.11 is very update with this.  I just padded it with more zeros, but it just hung.  I suspect DQ isn&#8217;t the right size?  I&#8217;m not 386 MASM junkie.  I&#8217;m at least getting the assembler to shut-up but it doesn&#8217;t work right. I&#8217;ll have to look more into it.</p>



<p class="wp-block-paragraph">Xenix 386 also includes an earlier version of Microsoft C / 386, and it formats the float like this:</p>



<pre class="wp-block-code"><code>CONST   SEGMENT  DWORD USE32 PUBLIC 'CONST'
$T20000         DQ      0040f51800H    ;        86400.00000000000
CONST      ENDS</code></pre>



<p class="wp-block-paragraph">So I had thought maybe if I replace the &#8216;r&#8217; with a &#8216;H&#8217; that might be enough?  The only annoying thing about the Xenix compiler is that it was K&amp;R so I spent a few minutes porting phoon to K&amp;R, dumped the assembly and came up with this sed string to find the pattern, mark it, and replace it (Im not that good at this stuff)</p>



<pre class="wp-block-code"><code>wsl sed -e "s/DQ\t&#91;0-9a-f]<em>r/&amp;XMMMMMMX/g" $</em>.a1 \
| wsl sed -e "s/rXMMMMMMX/H/g" > $*.asm</code></pre>



<p class="wp-block-paragraph">While it compiles with no issues, and runs, it just hangs.  I tried the transplanted Xenix assembly and it just hangs as well.  Clearly there is something to do with how to use floats.</p>



<p class="wp-block-paragraph">I then looked at whetstone, and after building it noticed this is the output compiling with Visual C++ 8.0</p>



<pre class="wp-block-code"><code>      0       0       0  1.0000e+000 -1.0000e+000 -1.0000e+000 -1.0000e+000
  12000   14000   12000 -1.3190e-001 -1.8218e-001 -4.3145e-001 -4.8173e-001
  14000   12000   12000  2.2103e-002 -2.7271e-002 -3.7914e-002 -8.7290e-002
 345000       1       1  1.0000e+000 -1.0000e+000 -1.0000e+000 -1.0000e+000
 210000       1       2  6.0000e+000  6.0000e+000 -3.7914e-002 -8.7290e-002
  32000       1       2  5.0000e-001  5.0000e-001  5.0000e-001  5.0000e-001
 899000       1       2  1.0000e+000  1.0000e+000  9.9994e-001  9.9994e-001
 616000       1       2  3.0000e+000  2.0000e+000  3.0000e+000 -8.7290e-002
      0       2       3  1.0000e+000 -1.0000e+000 -1.0000e+000 -1.0000e+000
  93000       2       3  7.5000e-001  7.5000e-001  7.5000e-001  7.5000e-001</code></pre>



<p class="wp-block-paragraph">However this is the output from C/386:</p>



<pre class="wp-block-code"><code>      0       0       0  5.2998e-315  1.5910e-314  1.5910e-314  1.5910e-314
  12000   14000   12000  0.0000e+000  0.0000e+000  0.0000e+000  0.0000e+000
  14000   12000   12000  0.0000e+000  0.0000e+000  0.0000e+000  0.0000e+000
 345000       1       1  5.2998e-315  1.5910e-314  1.5910e-314  1.5910e-314
 210000       1       2  6.0000e+000  6.0000e+000  0.0000e+000  0.0000e+000
  32000       1       2  5.2946e-315  5.2946e-315  5.2946e-315  5.2946e-315
 899000       1       2  5.2998e-315  5.2998e-315  0.0000e+000  0.0000e+000
 616000       1       2  5.3076e-315  5.3050e-315  5.3076e-315  0.0000e+000
      0       2       3  5.2998e-315  1.5910e-314  1.5910e-314  1.5910e-314
  93000       2       3  5.2972e-315  5.2972e-315  5.2972e-315  5.2972e-315</code></pre>



<p class="wp-block-paragraph">Great they look nothing alike. So something it totally broken.  I guess the real question is, does it even work on OS/2?</p>



<p class="wp-block-paragraph">Since I should post the NMAKE Makefile so I can remember how it can do custom steps so I can edit the intermediary files.  Isn&#8217;t C fun?!</p>



<pre class="wp-block-code"><code>INC = /Ih
OPT = /Ox
DEBUG = /Zi
CC = cl386

OBJ = dhyrst.obj

.c.obj:
	$(CC) $(INC) $(OPT) $(DEBUG) /c /Fa$*.a $*.c
	wsl sed -e 's/FLAT://g' $*.a &gt; $*.a1
	wsl sed -e "s/DQ\t&#91;0-9a-f]*r/&amp;XMMMMMMX/g" $*.a1 \
	| wsl sed -e "s/rXMMMMMMX/H/g" &gt; $*.asm
	ml /c $*.asm
	del $*.a $*.a1 $*.asm

dhyrst.exe: $(OBJ)
        link -debug:full -out:dhyrst.exe $(OBJ) libc.lib

clean:
        del $(OBJ)
        del dhyrst.exe
        del *.asm *.a *.a1</code></pre>



<p class="wp-block-paragraph">As you can see, I&#8217;m using /Ox or maximum speed!  So how does it compare?</p>



<pre class="wp-block-code"><code>Dhrystone(1.1) time for 180000000 passes = 20
This machine benchmarks at 9000000 dhrystones/second</code></pre>



<p class="wp-block-paragraph">And for the heck of it, how does Visual C++ 1.0&#8217;s performance compare?</p>



<pre class="wp-block-code"><code>Dhrystone(1.1) time for 180000000 passes = 7<br>This machine benchmarks at 25714285 dhrystones/second</code></pre>



<p class="wp-block-paragraph">That&#8217;s right the 1989 compiler is 35% the speed of the 1993 compiler. wow.  Also it turns out that MASM 6.11 actually can (mostly) assemble the output of this ancient compiler.  It&#8217;s nice when something kind of work.  I can also add that the Infocom &#8217;87 interpreter works as well. </p>



<p class="wp-block-paragraph">YAY!</p>
]]></content:encoded>
					
					<wfw:commentRss>https://virtuallyfun.com/2024/02/05/totally-unfair-comparison-of-microsoft-c/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Patching Touhou 6 (Embodiment of Scarlet Devil) to run on a 3dfx Voodoo 2</title>
		<link>https://virtuallyfun.com/2023/10/03/patching-touhou-6-embodiment-of-scarlet-devil-to-run-on-a-3dfx-voodoo-2/</link>
					<comments>https://virtuallyfun.com/2023/10/03/patching-touhou-6-embodiment-of-scarlet-devil-to-run-on-a-3dfx-voodoo-2/#comments</comments>
		
		<dc:creator><![CDATA[neozeed]]></dc:creator>
		<pubDate>Tue, 03 Oct 2023 14:58:08 +0000</pubDate>
				<category><![CDATA[80386]]></category>
		<category><![CDATA[assembly]]></category>
		<category><![CDATA[guest post]]></category>
		<category><![CDATA[i386]]></category>
		<category><![CDATA[Japanese software]]></category>
		<guid isPermaLink="false">https://virtuallyfun.com/?p=13313</guid>

					<description><![CDATA[This is a guest post from spaztron64 One thing that&#8217;s been bugging me for years at this point is the ability to run Touhou 6 on my PC-9821 V166. For a good few years I&#8217;ve been stuck with nothing more &#8230; <a href="https://virtuallyfun.com/2023/10/03/patching-touhou-6-embodiment-of-scarlet-devil-to-run-on-a-3dfx-voodoo-2/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">This is a guest post from <a href="https://lainnet.superglobalmegacorp.com/index.html">spaztron64</a></p>



<p class="wp-block-paragraph">One thing that&#8217;s been bugging me for years at this point is the ability to run Touhou 6 on my PC-9821 V166. For a good few years I&#8217;ve been stuck with nothing more than a Matrox Mystique graphics card in that thing, which can&#8217;t create a D3D6 HAL context for rendering the game&#8217;s 3D elements. In 2021 I snatched a 12MB 3dfx Voodoo 2, in hopes of being able to play more 3D games on that machine. There were two major problems&#8230;.<br><br>1) The USBHID.SYS driver for PC-98 Windows 9x conflicts haaaard with Voodoo drivers. Moving the cursor around corrupts memory and makes the system unstable or kills the driver in mere seconds of use </p>



<p class="wp-block-paragraph">2) None of the Touhou games support secondary Direct3D devices</p>



<p class="wp-block-paragraph">For those not in the know in regards to the second issue, DirectX allows you to use multiple DDraw and D3D capable GPUs on one system. By default it&#8217;ll set the video card outputting a signal on the primary monitor as the primary DirectX device, the secondary output as secondary, and so on. Most people only used one monitor on their Win9x PC back in the day, hooked up to their 2D capable card. The Voodoo 1 and 2 aren&#8217;t meant to act as 2D video cards, yet they had to support D3D initialization somehow, so they presented themselves as non-primary DirectX devices, usually secondary, in hopes that game developers would allow the end user to select their 3D accelerator of choice.</p>



<p class="wp-block-paragraph">This was standard practice at the tail end of the 1990s, but it was falling out of use at the turn of the millenium with the demise of 3dfx and the general lack of need for multiple graphics cards in one system for 3D gaming. This presented a problem, as games that technically&nbsp;<em>could</em>&nbsp;be played on a Voodoo 2&#8230; didn&#8217;t, as they could never be told to use it through normal means. Hacky solutions existed, like 3dfx&#8217;s unfinished, buggy attempt at a Voodoo 2 driver for Windows 2000 that allowed it to behave like a primary display adapter for general 2D and 3D use, but it&#8217;s notoriously unstable and isn&#8217;t possible to use on 9x. I&#8217;ve used this method before to play Touhou 6, Max Payne 1, GZDoom, GTA 3 and Vice City on the Voodoo 2 through Windows XP with mixed results.</p>



<p class="wp-block-paragraph">Once I got an NEC bus mouse for use on my PC-98, I could finally use the Voodoo 2 on it without constant crashing. This got me interested in trying to get Touhou 6 to work on it, which lead me to a path of pure pain.</p>



<p class="wp-block-paragraph">For starters, Touhou 6 is one of those games that only use primary DirectX devices, like the unsupported Mystique, so I had to somehow coax it into initializing the secondary device instead. My first approach to handling this was through direct binary patching. I didn&#8217;t know where to look for the init routines, so I asked 32th System for some heads up, and he pointed me to a rough location in process memory where the appropriate CreateDevice calls reside:</p>



<figure class="wp-block-image size-full"><a href="https://virtuallyfun.com/wp-content/uploads/2023/10/f1.png"><img loading="lazy" decoding="async" width="514" height="146" src="https://virtuallyfun.com/wp-content/uploads/2023/10/f1.png" alt="" class="wp-image-13314" srcset="https://virtuallyfun.com/wp-content/uploads/2023/10/f1.png 514w, https://virtuallyfun.com/wp-content/uploads/2023/10/f1-300x85.png 300w, https://virtuallyfun.com/wp-content/uploads/2023/10/f1-500x142.png 500w" sizes="auto, (max-width: 514px) 100vw, 514px" /></a></figure>



<p class="wp-block-paragraph">I then searched for the appropriate opcodes in the game binary, and patched all 6A 00 (push 0, A.K.A D3DADAPTER_DEFAULT) opcodes to be 6A 01 (push 1), forcing the game to init the secondary D3D device.</p>



<p class="wp-block-paragraph">While this initially did in fact work, the approach ultimately sucked for two reasons.<br><br>1) Static binary patching only works for that specific binary, and doesn&#8217;t carry across different versions.</p>



<p class="wp-block-paragraph">2) This requires manually patching every CreateDevice call, of which there are <em>many</em> in Touhou 6<br><br>It is at this point that I started sharing my progress with friends. jbit was quick to hop in and say &#8220;Why the fuck are you doing it this way? Just make a d3d8.dll wrapper DLL&#8221;. This was absolutely the smarter approach, I just didn&#8217;t know how to do it since I don&#8217;t know jack about DirectX programming. Fortunately, he handed me a little VS project he worked on called d3dcutter that, among other things, wrapped the CreateDevice function, which I promptly modified to always push 1 instead of 0 to the stack for the device selection parameter.</p>



<p class="wp-block-paragraph">This solved the two patching problems, and I had something to show for starters:</p>



<figure class="wp-block-video"><video height="360" style="aspect-ratio: 640 / 360;" width="640" controls src="https://virtuallyfun.com/wp-content/uploads/2023/10/f1.mp4"></video></figure>



<p class="wp-block-paragraph">Now, I&#8217;m sure you can tell that the performance is absolutely atrocious. This came as no surprise to me, as while the Voodoo can absolutely render the game at a full 60FPS most of the time, the dinky little Pentium MMX 166 struggles hard at doing triangle setup for the backgrounds every 16 milliseconds. Remember, 3dfx cards had no Hardware T&amp;L, so the game has to fall back to Software T&amp;L. I think the following wireframe screenshot will help illustrate the amount of work the CPU has to do every frame:</p>



<figure class="wp-block-image size-full"><a href="https://virtuallyfun.com/wp-content/uploads/2023/10/t2.png"><img loading="lazy" decoding="async" width="646" height="505" src="https://virtuallyfun.com/wp-content/uploads/2023/10/t2.png" alt="" class="wp-image-13316" srcset="https://virtuallyfun.com/wp-content/uploads/2023/10/t2.png 646w, https://virtuallyfun.com/wp-content/uploads/2023/10/t2-300x235.png 300w, https://virtuallyfun.com/wp-content/uploads/2023/10/t2-384x300.png 384w" sizes="auto, (max-width: 646px) 100vw, 646px" /></a></figure>



<p class="wp-block-paragraph">&#8220;Well, I&#8217;m in luck!&#8221;, one might think as they remember that older Touhou games support framerate division by 1/2 (30FPS) and 1/3 (20FPS) as options in custom.exe&#8230; There&#8217;s just one problem.</p>


<div class="wp-block-image">
<figure class="aligncenter size-full"><a href="https://virtuallyfun.com/wp-content/uploads/2023/10/t3.png"><img loading="lazy" decoding="async" width="362" height="289" src="https://virtuallyfun.com/wp-content/uploads/2023/10/t3.png" alt="" class="wp-image-13317" srcset="https://virtuallyfun.com/wp-content/uploads/2023/10/t3.png 362w, https://virtuallyfun.com/wp-content/uploads/2023/10/t3-300x240.png 300w" sizes="auto, (max-width: 362px) 100vw, 362px" /></a></figure>
</div>


<p class="wp-block-paragraph">The game just&#8230; fails to initialize the D3D HAL on the Voodoo 2 in the frame divided modes. Why? Beats me, I still haven&#8217;t figured it out and likely never will. Just more ZUNcode bullshit I suppose.</p>



<p class="wp-block-paragraph">I then figured out that framerate division is handled by a variable (that can be set even lower than 1/3, by the way) which could be set at runtime, even when the normal 60FPS mode is used. I suspected that the game uses a different initialization path for the two modes, so I once again tracked down opcodes that expect the variable to be set to 0 in process memory, this time with Cheat Engine, and patched them in the binary. Well guess fucking what, the game fails to initialize even when the regular init routines are modified to expect 30FPS or 20FPS frame division to be set.</p>



<p class="wp-block-paragraph">This approach simply wasn&#8217;t going to work. so I went with trying to set the variable at runtime. Unfortunately, I had to go back to version specific patching once more for this, since there&#8217;s no way to wrap this functionality through DLL means. Additionally, while this wasn&#8217;t hard to do with the game running in windowed mode with Cheat Engine on the side on a modern system, it was basically impossible on a Voodoo 2 equipped machine, as the game ran in fullscreen and it wasn&#8217;t possible to restore the window after an Alt+Tab.</p>



<p class="wp-block-paragraph">My final solution was to generate a trainer in Cheat Engine for version 1.02d of the game, as it&#8217;s the last one with a working logic speed limiter, that would forcibly set the frame divider variable at runtime with a hotkey:</p>


<div class="wp-block-image">
<figure class="aligncenter size-full"><a href="https://virtuallyfun.com/wp-content/uploads/2023/10/t4.png"><img loading="lazy" decoding="async" width="362" height="303" src="https://virtuallyfun.com/wp-content/uploads/2023/10/t4.png" alt="" class="wp-image-13318" srcset="https://virtuallyfun.com/wp-content/uploads/2023/10/t4.png 362w, https://virtuallyfun.com/wp-content/uploads/2023/10/t4-300x251.png 300w, https://virtuallyfun.com/wp-content/uploads/2023/10/t4-358x300.png 358w" sizes="auto, (max-width: 362px) 100vw, 362px" /></a></figure>
</div>


<p class="wp-block-paragraph">This finally allowed me to play the game in 1/3 framerate mode on the Voodoo 2.<br>This allows the game to run at full logic speed most of the time, as the CPU now has 40 miliseconds per frame for triangle setup, however there&#8217;s something wrong with how the card handles buffer swaps in this mode of operation, leading to a very back-and-forth stuttery image that&#8217;s very unpleasant to look at.</p>



<p class="wp-block-paragraph">Can we do better? Well yes! The game uses so-called STD scripts for certain stage-specific data setup, but also handling camera movement and geometry generation. Using Touhou Toolkit, I was able to unpack the appropriate DAT file, decompile all the STD scripts, remove all geometry commands, and recompile them for in-game use. As there are no more backgrounds to draw, there&#8217;s a trail effect left behind every frame, but thankfully custom.exe has an option to forcibly clear the back buffer every frame.</p>



<figure class="wp-block-video"><video controls src="https://lainnet.superglobalmegacorp.com/lainplay/videos/Wg8tj1KIYTs.mp4"></video></figure>



<p class="wp-block-paragraph">The end result? A nearly tripled framerate in 60FPS mode, recovered just by not drawing any 3D backgrounds. The game still lags when lots of bullets are on screen, but this doesn&#8217;t really come as a surprise.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://virtuallyfun.com/2023/10/03/patching-touhou-6-embodiment-of-scarlet-devil-to-run-on-a-3dfx-voodoo-2/feed/</wfw:commentRss>
			<slash:comments>6</slash:comments>
		
		<enclosure url="http://virtuallyfun.com/wp-content/uploads/2023/10/f1.mp4" length="0" type="video/mp4" />
<enclosure url="https://lainnet.superglobalmegacorp.com/lainplay/videos/Wg8tj1KIYTs.mp4" length="29811791" type="video/mp4" />

			</item>
		<item>
		<title>Building MS-DOS 2.11</title>
		<link>https://virtuallyfun.com/2023/08/06/building-ms-dos-2-11/</link>
					<comments>https://virtuallyfun.com/2023/08/06/building-ms-dos-2-11/#respond</comments>
		
		<dc:creator><![CDATA[neozeed]]></dc:creator>
		<pubDate>Sun, 06 Aug 2023 17:15:29 +0000</pubDate>
				<category><![CDATA[assembly]]></category>
		<category><![CDATA[MS-DOS]]></category>
		<category><![CDATA[source code]]></category>
		<guid isPermaLink="false">http://virtuallyfun.com/?p=13114</guid>

					<description><![CDATA[I thought I&#8217;d slap together some github thing with MS-DOS 2.11 that&#8217;s been made buildable thanks to a whole host of other smart people. The default stuff out there expects you to build it under MS-DOS using the long obsoleted &#8230; <a href="https://virtuallyfun.com/2023/08/06/building-ms-dos-2-11/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
										<content:encoded><![CDATA[
<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="722" height="427" src="https://virtuallyfun.com/wp-content/uploads/2023/08/dos-211-built-and-booted.png" alt="" class="wp-image-13115" srcset="https://virtuallyfun.com/wp-content/uploads/2023/08/dos-211-built-and-booted.png 722w, https://virtuallyfun.com/wp-content/uploads/2023/08/dos-211-built-and-booted-300x177.png 300w, https://virtuallyfun.com/wp-content/uploads/2023/08/dos-211-built-and-booted-500x296.png 500w" sizes="auto, (max-width: 722px) 100vw, 722px" /></figure>



<p class="wp-block-paragraph">I thought I&#8217;d slap together some github thing with MS-DOS 2.11 that&#8217;s been made buildable thanks to a whole host of other smart people.  The default stuff out there expects you to build it under MS-DOS using the long obsoleted &#8216;append&#8217; utility which can add directories to a search path.  Instead I created a bunch of makefiles that take advantage of <a rel="noreferrer noopener" href="http://takeda-toshiya.my.coocan.jp/msdos/" target="_blank">MS-DOS Player</a>, and let you build from Windows.</p>



<p class="wp-block-paragraph"><a href="https://github.com/neozeed/dos211">dos211: just the MS-DOS 2.11 sources, I re-aranged stuff and made it (slightly) easier to rebuild on Windows. (github.com)</a></p>



<p class="wp-block-paragraph">building should be somewhat straightforward, assuming you have the ms-dos player in your path.  JUST MAKE SURE YOU UNZIP as TEXT mode.  If you are getting a million errors you probably have them in github&#8217;s favourite unix mode.</p>



<pre class="wp-block-code"><code>D:\temp\dos211-main\bios>..\tools\make
msdos ..\tools\masm ibmbio.asm ibmbio.obj NUL NUL
The Microsoft MACRO Assembler , Version 1.25
 Copyright (C) Microsoft Corp 1981,82,83


Warning Severe
Errors  Errors
0       0
msdos ..\tools\masm sysimes.asm sysimes.obj NUL NUL
The Microsoft MACRO Assembler , Version 1.25
 Copyright (C) Microsoft Corp 1981,82,83


Warning Severe
Errors  Errors
0       0
msdos ..\tools\masm sysinit.asm sysinit.obj NUL NUL
The Microsoft MACRO Assembler , Version 1.25
 Copyright (C) Microsoft Corp 1981,82,83

DOSSYM in Pass 2

Warning Severe
Errors  Errors
0       0
msdos ..\tools\LINK IBMBIO+SYSINIT+SYSIMES;

   Microsoft Object Linker V2.00
(C) Copyright 1982 by Microsoft Inc.

Warning: No STACK segment

There was 1 error detected.
msdos ..\tools\exe2bin.exe IBMBIO IBMBIO.COM &lt; 70.TXT
Fix-ups needed - base segment (hex): 70
del -f ibmbio.obj    sysimes.obj   sysinit.obj ibmbio.exe

D:\temp\dos211-main\bios></code></pre>



<p class="wp-block-paragraph">As an example building the bios by running make.  For the impatiend you can download <a rel="noreferrer noopener" href="https://github.com/neozeed/dos211/releases/download/v1_0_0/dos211.zip" target="_blank">dos211.zip</a>, which includes a bootable 360kb disk image, and a 32Mb vmdk!</p>
]]></content:encoded>
					
					<wfw:commentRss>https://virtuallyfun.com/2023/08/06/building-ms-dos-2-11/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>32016 stand alone planetfall!</title>
		<link>https://virtuallyfun.com/2021/10/01/32016-stand-alone-planetfall/</link>
					<comments>https://virtuallyfun.com/2021/10/01/32016-stand-alone-planetfall/#respond</comments>
		
		<dc:creator><![CDATA[neozeed]]></dc:creator>
		<pubDate>Fri, 01 Oct 2021 18:01:46 +0000</pubDate>
				<category><![CDATA[assembly]]></category>
		<category><![CDATA[cross compiler]]></category>
		<category><![CDATA[games]]></category>
		<category><![CDATA[gcc]]></category>
		<category><![CDATA[Infocom]]></category>
		<category><![CDATA[NS32032]]></category>
		<guid isPermaLink="false">https://virtuallyfun.com/wordpress/?p=11398</guid>

					<description><![CDATA[What is it? It sure may not look like much but it was an adventure getting here. First, what is it? Well it&#8217;s the very simple NS32016 from here, with a few minor changes. I expanded the RAM from 256kb &#8230; <a href="https://virtuallyfun.com/2021/10/01/32016-stand-alone-planetfall/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
										<content:encoded><![CDATA[
<div class="wp-block-image"><figure class="aligncenter size-full"><a href="https://virtuallyfun.com/wp-content/uploads/2021/10/32016-standalone-planetfall.png"><img loading="lazy" decoding="async" width="979" height="512" src="https://virtuallyfun.com/wp-content/uploads/2021/10/32016-standalone-planetfall.png" alt="" class="wp-image-11399" srcset="https://virtuallyfun.com/wp-content/uploads/2021/10/32016-standalone-planetfall.png 979w, https://virtuallyfun.com/wp-content/uploads/2021/10/32016-standalone-planetfall-300x157.png 300w, https://virtuallyfun.com/wp-content/uploads/2021/10/32016-standalone-planetfall-768x402.png 768w, https://virtuallyfun.com/wp-content/uploads/2021/10/32016-standalone-planetfall-500x261.png 500w" sizes="auto, (max-width: 979px) 100vw, 979px" /></a><figcaption>InfoTaskForce&#8217;87 running on a simple NS32016 emulator</figcaption></figure></div>



<h2 class="wp-block-heading">What is it?</h2>



<p class="wp-block-paragraph">It sure may not look like much but it was an adventure getting here.</p>



<p class="wp-block-paragraph">First, what is it? Well it&#8217;s the <a rel="noreferrer noopener" href="http://cpu-ns32k.net/Emulator.html" target="_blank">very simple NS32016</a> from here, with a few minor <a rel="noreferrer noopener" href="https://github.com/neozeed/emul32k/commit/3cc7dd9b7ed9cad5be31b94e13abc7e05832df61" target="_blank">changes</a>.  I expanded the RAM from 256kb to a whopping 8MB.  Then I added simple character I/O allowing me to print messages to the screen.  Next looking at the <a rel="noreferrer noopener" href="http://wiki.sensi.org/dokuwiki/doku.php?id=ns32ktoolchain" target="_blank">toolchain</a> page, I used my old Linux to Windows GCC 4 cross compiler to build the appropriate Canadian cross compiler to the NS3216.</p>



<h2 class="wp-block-heading">Building the tools</h2>



<p class="wp-block-paragraph"><a rel="noreferrer noopener" href="/wordpress/2015/09/24/building-a-mips-compiler-for-windows-on-a-linux-vm/" target="_blank">A while back</a>, I had built a cross compiler from Linux to Windows using GCC 4.1 as the basis as it was the last version that didn&#8217;t have massive external dependencies. NS32016 support was dropped some time in the late 3.x or early 4.x GCC so it means we need to go old anyways. I arbitrary picked GCC 2.8.1 for this build, while using the recommended Binutils 2.27</p>



<p class="wp-block-paragraph">I cheated and just downloaded my existing <a rel="noreferrer noopener" href="https://vpsland.superglobalmegacorp.com/install/Linux-i386/linux-minw32.7z" target="_blank">linux-minw32.7z</a> cross compiler as I didn&#8217;t feel like rebuilding everything again, although it is all in the <em><a rel="noreferrer noopener" href="/wordpress/2015/09/24/building-a-mips-compiler-for-windows-on-a-linux-vm/" target="_blank">Building a MIPS Compiler for Windows on a Linux VM!</a></em> article.  I also used an old <a rel="noreferrer noopener" href="https://vpsland.superglobalmegacorp.com/install/Linux-i386/OSKit/i586-linux2-gcc4.1.2.tar.gz" target="_blank">Linux to Linux i586 32bit compiler</a> (back from the <a href="/wordpress/2020/09/03/building-oskit/" target="_blank" rel="noreferrer noopener">OSKit build!</a>) although you can use your hosts as well.</p>



<p class="wp-block-paragraph">configuring Binutils is pretty simple like this:</p>



<pre class="wp-block-code"><code>./configure --prefix=/cross --target=ns32k-pc532-netbsd --host=i686-mingw32 --build=i586-linux</code></pre>



<p class="wp-block-paragraph">You can try omitting the &#8211;build portion, Debian GNU Linux 10 seemed okay with Gcc 8 as the default system compiler.</p>



<p class="wp-block-paragraph">configuring GCC 2.8.1 was pretty similar:</p>



<pre class="wp-block-code"><code>./configure --target=ns32k-pc532-netbsd --prefix=/cross --disable-libssp --build=i586-linux --host=i686-mingw32</code></pre>



<p class="wp-block-paragraph">GCC 2.8.1 doesn&#8217;t quite know what we are doing so there is some flags we need to run off in auto-config.h namely</p>



<ul class="wp-block-list"><li>#define HAVE_BCMP 1</li><li>#define HAVE_BCOPY 1</li><li>#define HAVE_BZERO 1</li><li>#define HAVE_INDEX 1</li><li>#define HAVE_KILL 1</li><li>#define HAVE_RINDEX 1</li><li>#define HAVE_SYS_RESOURCE_H 1</li><li>#define HAVE_SYS_TIMES_H 1</li></ul>



<p class="wp-block-paragraph">You can just comment them out, or remove those lines all together.</p>



<p class="wp-block-paragraph">When it came to building GCC, I did run into issues with GCC 7/8 trying to build GCC 2.8.1.  I found it much easier to either have that Linux 4.1 compiler, or if you have access to Wine or WSL you can just run the Win32 binaries for the gen phases.</p>



<pre class="wp-block-code"><code>./configure --prefix=/cross --target=ns32k-pc532-netbsd --host=i686-mingw32
make CC=i686-mingw32-gcc xgcc cccp cc1 cc1obj</code></pre>



<p class="wp-block-paragraph">If you can run your own Win32 exe&#8217;s on Linux it&#8217;ll run just fine using the Linux to Windows GCC 4 cross.  Otherwise you will need to either patch GCC or make your own GCC 4 hosted Linux to Linux cross compiler like this:</p>



<pre class="wp-block-code"><code>make CC=i686-mingw32-gcc HOST_CC=i586-linux-gcc xgcc cccp cc1 cc1obj</code></pre>



<p class="wp-block-paragraph">Hopefully that worked enough, and now you have your cross compiler.  Now it&#8217;s time to build libgcc1.a</p>



<pre class="wp-block-code"><code>cp cccp cpp.exe<br>cp cc1 cc1.exe<br>cp xgcc xgcc.exe<br>cp ../binutils-2.27/gas/.libs/as-new.exe as.exe<br>cp ../binutils-2.27/binutils/.libs/ar.exe ar<br>cp ../binutils-2.27/binutils/.libs/ranlib.exe ranlib<br>make libgcc1.a TARGET_TOOLPREFIX="./" OLDCC=./xgcc.exe</code></pre>



<p class="wp-block-paragraph">Again you really want to be able to run the resulting programs on Linux but I guess you could script it out.  Naturally if you wanted to just use Linux, it&#8217;d be easier to make that cross compiler directly, although I&#8217;m not sure how much of GCC 2.8.1 I want to fight, or just get GCC 4 running on Linux and use that to port.</p>



<h2 class="wp-block-heading">crt0, somewhere for C to start</h2>



<p class="wp-block-paragraph">As <a href="http://wiki.sensi.org/dokuwiki/doku.php?id=ns32ktoolchain" target="_blank" rel="noreferrer noopener">mentioned a crt0.s</a> is missing but there was enough inspiration to come up with this:</p>



<pre class="wp-block-code"><code>#NO_APP
gcc_compiled.:
.text
        .align 1
.globl _start
_start:
        enter &#91;],0
#APP
#       setting the stack 256k under 8MB
        lprd sp,0x7c0000
        jsr _main
#NO_APP
L1:
        exit &#91;]
#       setting the stack 256k under 8MB
        lprd sp,0x7c0000
        bpt
        .align 1

#does nothing
.globl ___main
___main:
        ret 0

.globl _exit
_exit:
        bpt
        ret 0</code></pre>



<p class="wp-block-paragraph">I used a bit of the C example, and added some hooks that GCC was expecting namely a __main call that is made from main before it does anything (a place to init memory perhaps?), a place to catch an explicit exit call, along with setting the stack of course.</p>



<h2 class="wp-block-heading">Patching InfoTaskForce without malloc / disk access</h2>



<p class="wp-block-paragraph">It&#8217;s not going to win any awards, but it was really great to get it to run a simple program written in GCC.  Looking for something more fun, I took the old <a rel="noreferrer noopener" href="https://github.com/neozeed/InfoTaskForce-87" target="_blank">InfoTaskForce interpreter from &#8217;87</a>, and dug up my modification to run on cisco routers, and <a rel="noreferrer noopener" href="https://github.com/neozeed/InfoTaskForce-87/tree/Game-from-RAM" target="_blank">cooked up this version</a>, that adds enough of printf from Linux, a bogus malloc that just allocates from a fixed memory array (otherwise you have to actually know about your platform), and a fun trick with later binutils where you can import a <a rel="noreferrer noopener" href="https://github.com/neozeed/InfoTaskForce-87/commit/a8d5a59762edc71c4d9a78aa8adfb59a917f7a5c#diff-ab7c0d0209354eb93bf7490f9880d1dc9cadf3c14fd07c0c3af5a9ccb6f6a303" target="_blank">binary</a> file directly as an object!</p>



<p class="wp-block-paragraph">Neat!</p>



<p class="wp-block-paragraph">Since I don&#8217;t have any file I/O being able to have the game data in RAM is crucial.  I tried to tweak it so you could build the same working thing on Windows (maybe others?).</p>



<p class="wp-block-paragraph">So for anyone who wants to look at the standalone adventure <a rel="noreferrer noopener" href="https://github.com/neozeed/emul32k/releases/tag/ns3216-planetfall_v1.0" target="_blank">Win32 hosted tools are here</a>, although the emulator should be somewhat portable.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://virtuallyfun.com/2021/10/01/32016-stand-alone-planetfall/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Quick and dirty i8080 emulator in BASH!</title>
		<link>https://virtuallyfun.com/2019/09/22/quick-and-dirty-i8080-emulator-in-bash/</link>
					<comments>https://virtuallyfun.com/2019/09/22/quick-and-dirty-i8080-emulator-in-bash/#comments</comments>
		
		<dc:creator><![CDATA[neozeed]]></dc:creator>
		<pubDate>Sun, 22 Sep 2019 04:49:18 +0000</pubDate>
				<category><![CDATA[8080]]></category>
		<category><![CDATA[assembly]]></category>
		<guid isPermaLink="false">https://virtuallyfun.com/wordpress/?p=9787</guid>

					<description><![CDATA[Based on the Toledo 8080 processor emulator, it&#8217;s Peter Naszvadi&#8217;s i8080.sh! You will need bash version 4 for this to run. So for those of you in the 1990&#8217;s you are out of luck. And to make this fun, the &#8230; <a href="https://virtuallyfun.com/2019/09/22/quick-and-dirty-i8080-emulator-in-bash/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">Based on the <a href="https://nanochess.org/emulator.html">Toledo 8080 processor emulator</a>, it&#8217;s <a href="https://github.com/retrohun/blog/tree/master/dt/i8080emulatorinbash">Peter  Naszvadi&#8217;s i8080.sh</a>!</p>



<p class="wp-block-paragraph">You will need bash version 4 for this to run.  So for those of you in the 1990&#8217;s you are out of luck.</p>



<p class="wp-block-paragraph">And to make this fun, the 2kb basic &#8216;ROM&#8217; is bootstrapped into RAM for immediate execution! </p>



<pre>
$ ./8080.sh
Quick and dirty i8080 emulator by NASZVADI Peter, 2019.
Press Ctrl+C to quit anytime!
Initializing upper memory to NOPs
Initializing register values
Starting CPU emulation


OK
>10 PRINT "HIHI"
>RUN
HIHI

OK
>
</pre>



<p class="wp-block-paragraph">So we&#8217;ve seen emulation in javascript of all things, but now you can run 8080 instructions from bash of all things!</p>



<p class="wp-block-paragraph">And for anyone even more crazy there is always <a href="https://www.bdsoft.com/resources/bdsc.html">BDS C:</a> which was opened up back in 2002, a K&amp;R for the 8080 on CP/M!</p>
]]></content:encoded>
					
					<wfw:commentRss>https://virtuallyfun.com/2019/09/22/quick-and-dirty-i8080-emulator-in-bash/feed/</wfw:commentRss>
			<slash:comments>5</slash:comments>
		
		
			</item>
		<item>
		<title>Messing with the Monitor</title>
		<link>https://virtuallyfun.com/2019/04/09/messing-with-the-monitor/</link>
					<comments>https://virtuallyfun.com/2019/04/09/messing-with-the-monitor/#respond</comments>
		
		<dc:creator><![CDATA[neozeed]]></dc:creator>
		<pubDate>Tue, 09 Apr 2019 15:47:05 +0000</pubDate>
				<category><![CDATA[68000]]></category>
		<category><![CDATA[assembly]]></category>
		<category><![CDATA[cross compiler]]></category>
		<category><![CDATA[m68k]]></category>
		<guid isPermaLink="false">https://virtuallyfun.com/wordpress/?p=9325</guid>

					<description><![CDATA[So I was trapped in the Library for a bit, and spied this book. It&#8217;s not every often in 2019 you are going to find books about the 68000, as I&#8217;m sure any good library will have removed stuff like &#8230; <a href="https://virtuallyfun.com/2019/04/09/messing-with-the-monitor/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
										<content:encoded><![CDATA[<div class="wp-block-image">
<figure class="aligncenter"><img loading="lazy" decoding="async" width="417" height="500" src="https://virtuallyfun.com/wp-content/uploads/2019/04/The-68000-Microprocessor-Hardware-and-Software-Principles-and-Applications.jpg" alt="" class="wp-image-9327" srcset="https://virtuallyfun.com/wp-content/uploads/2019/04/The-68000-Microprocessor-Hardware-and-Software-Principles-and-Applications.jpg 417w, https://virtuallyfun.com/wp-content/uploads/2019/04/The-68000-Microprocessor-Hardware-and-Software-Principles-and-Applications-250x300.jpg 250w" sizes="auto, (max-width: 417px) 100vw, 417px" /><figcaption class="wp-element-caption">The 68000 Microprocessor (5th Edition) Hardcover Nov 25 2003<br> by James L. Antonakos (Author)</figcaption></figure>
</div>


<p class="wp-block-paragraph">So I was trapped in the Library for a bit, and spied this book.  It&#8217;s not every often in 2019 you are going to find books about the 68000, as I&#8217;m sure any good library will have removed stuff like this, and have it pulped ages ago.  But the amount of current technical books in English here is pretty damned slim to none, so I was all to happy to pickup this book for a week.</p>



<p class="wp-block-paragraph">The poor thing has been checked out 4 times in the last 15 years.  I guess the kids don&#8217;t know what they are missing.</p>



<p class="wp-block-paragraph">Anyways what was interesting in this book is that it has a CD-ROM, and on there is some lesson code from the book, along with an assembler that outputs to S-records of all things, and a small emulator that is meant to be compiled under MS-DOS.  It was trivial to isolate the passing of DOS interrupts from Unix/MinGW and get the simulator running on something modern.</p>



<p class="wp-block-paragraph">In Chapter 11 there is a brief walkthrough on building a board, which sounds like fun although I&#8217;m sure in 2019 finding parts will be.. challenging, along with a simple monitor program.</p>



<p class="wp-block-paragraph">The built in assembler can happily assemble the monitor, but it&#8217;s geared for talking to the obsolete hardware as specified in the book.  I just made a few small changes to instead have it&#8217;s console IO hook to the simulator&#8217;s TRAPs and I had the monitor running!</p>



<p class="wp-block-paragraph">I then took the echo test program, and modified it to run at a higher location in memory, along with exiting via the RTS instruction, so that it will exit when you press Q back to the monitor.  Then for the heck of it I further extended the monitor so you can Quit it, and return to the simulator.</p>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="979" height="512" src="https://virtuallyfun.com/wp-content/uploads/2019/04/antonakos-echo.png" alt="" class="wp-image-9326" srcset="https://virtuallyfun.com/wp-content/uploads/2019/04/antonakos-echo.png 979w, https://virtuallyfun.com/wp-content/uploads/2019/04/antonakos-echo-300x157.png 300w, https://virtuallyfun.com/wp-content/uploads/2019/04/antonakos-echo-768x402.png 768w" sizes="auto, (max-width: 979px) 100vw, 979px" /></figure>



<p class="wp-block-paragraph">Is this useful?  I&#8217;m pretty sure the answer is absolutely not.</p>



<p class="wp-block-paragraph">The CD-ROM is tiny, I thought it would be packed with goodies, but it&#8217;s 250kb compressed.</p>



<p class="wp-block-paragraph"><a href="https://archive.org/download/the-68000-microprocessor-hardware-and-software-principles-and-applications_cdrom/The68000MicroprocessorFifthEdition.zip">The68000MicroprocessorFifthEdition.zip</a></p>



<p class="wp-block-paragraph">If anything people using this book will probably have lost the CD-ROM and want the programs.</p>



<ul class="wp-block-list">
<li><strong>ISBN-10:</strong>&nbsp;0130195618</li>
</ul>



<p class="wp-block-paragraph">And my <a href="https://archive.org/details/the-68000-microprocessor-hardware-and-software-principles-and-applications_cdrom">horrible changes here</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://virtuallyfun.com/2019/04/09/messing-with-the-monitor/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
