Pinball on 64-bit Alpha AXP Windows NT

This is a guest post from Yufeng Gao

One of the most popular OS built-in games is no doubt Pinball, known by its full name 3D Pinball for Windows – Space Cadet. It started out as Full Tilt! Pinball, developed by Cinematronics and published by Maxis. 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.

Windows XP was the last version of Windows to include Pinball, and Raymond Chen explained why it didn’t make it to Windows Vista 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.

In 2021, NCommander launched a series of investigations 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.

Not long after NCommander published his video, Raymond followed up with a post that filled in some gaps 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:

  • No 64-bit Windows was ever released for the Alpha AXP – Compaq killed Windows NT support before NT was ported to 64-bit
  • One 64-bit Alpha AXP NT build was leaked in 2023, but the included Pinball does not work, as it segfaults immediately upon running

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 fork of the ES40 emulator, as well as on QEMU. 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.

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 Dr. Watson, which takes core dumps and performs simple post-mortems. Something is better than nothing, as people would say.

Running Pinball gives the classic crash symptom immediately, with no graphics drawn:

Dr. Watson concludes that it died of a segfault:

It gave a nice dump of registers at the time of the fault:

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 

Some disassembly around the faulting instruction:

function: Otsstrlen
FAULT ->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

And a very useful stack backtrace:

*----> Stack Back Trace <----*

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 !<nosymbols> 
000003FFFFF8FCA0 0000000001064B0C 0000000001000000 0000000001002DC8 000003FFFFF8FAD8 0000000030010000 !<nosymbols> 
000003FFFFF8FED0 0000000068948C50 0000000001000000 0000000001002DC8 000003FFFFF8FAD8 0000000030010000 !<nosymbols> 
000003FFFFF8FFC0 0000000000000000 0000000001064800 0000000001002DC8 000003FFFFF8FAD8 0000000030010000 !BaseProcessStart 

Ok, so it died inside RegisterClassA, 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 WNDCLASSA 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.

From the stack trace, the return address of RegisterClassA was 0x100F914, inside the function splash_screen. A quick disassembly of the instructions preceding that address shows a WNDCLASSA structure being built with the following layout:

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)

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 style field followed by a 64-bit lpfnWndProc, and to satisfy the alignment requirements, a 4-byte padding should be inserted between style and lpfnWndProc to ensure that lpfnWndProc starts on an 8-byte boundary. RegisterClassA was expecting this padding, but Pinball lacked it, so it read data from the wrong offset and crashed.

To fix this, I simply bumped the offset of each field after style up by 4 bytes.

 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)

But that was not sufficient – Pinball calls RegisterClassA in 4 different places – Sound_Initsplash_screenWinMain and WaveMixStartup. I’d already patched the one in splash_screen, so I started going through the rest one by one.

The ones in Sound_Init and WinMain were identical to the one in splash_screen, but for some strange reason the one in WaveMixStartup already had the correct alignment:

00000000 u32 style         = 0
00000004 u32 <unused>      = <undefined>
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)

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.

Anyway, with the WNDCLASSA 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:

Crash log shows that the segfault happened deep in the Win32 audio system, while calling auxSetVolume:

*----> Stack Back Trace <----*

FramePtr ReturnAd Param#1  Param#2  Param#3  Param#4  Function Name
000003FFFFF8E9C0 0000000050306E84 00000000FFE5D420 0000000000000000 000003FFFFE5D420 0000000000000000 !<nosymbols> 
000003FFFFF8E9E0 00000000503034B8 00000000FFE5D420 0000000000000000 000003FFFFE5D420 0000000000000000 !<nosymbols> 
000003FFFFF8EA10 0000000050304B60 00000000FFE5D420 0000000000000000 000003FFFFE5D420 0000000000000000 !<nosymbols> 
000003FFFFF8EA90 0000000050305B8C 00000000FFE5D420 0000000000000000 000003FFFFE5D420 0000000000000000 !<nosymbols> 
000003FFFFF8EB20 000000000001AF78 00000000FFE5D420 0000000000000000 000003FFFFE5D420 0000000000000000 !<nosymbols> 
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 
[...]
000003FFFFF8FC60 0000000001012AB4 0000000000000000 000003FFFFE5DE00 000003FFFFE5D420 0000000000000000 !CreateWindowExA 
000003FFFFF8FCA0 0000000001064B0C 0000000000000000 000003FFFFE5DE00 000003FFFFE5D420 0000000000000000 !<nosymbols> 
000003FFFFF8FED0 0000000068948C50 0000000000000000 000003FFFFE5DE00 000003FFFFE5D420 0000000000000000 !<nosymbols> 
000003FFFFF8FFC0 0000000000000000 0000000001064800 000003FFFFE5DE00 000003FFFFE5D420 0000000000000000 !BaseProcessStart

The fault happened while trying to dereference a pointer in the register a0 (r16):

function: <nosymbols>
        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
FAULT ->00000000'50305680: a2100128 ldl a0,128(a0)
        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

The register dump shows the value of a0 at the time of the crash:

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   a0=00000000 ffe5d420   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 

Indeed, it was an invalid pointer! As you can see, it’s identical to the pointer in a2, 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.

I spent some time and pinned down the DLL responsible for the fault – mciseq.dll, and did some tracing. The truncation of a0 happened when a2 was moved into a0:

50306150    ZAPNOT  a2,#15,a0

ZAPNOT 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 15, which is 00001111 in binary. From this we can work out that the ZAPNOT instruction at 0x50306150 zeros the upper 4 bytes of a2, when it is copied into a0. This perfectly explains why, at the time of the fault, a0 contained a truncated version of the pointer in a2.

Of course, 0x50306150 was not the only place where it truncated 64-bit pointers, I found 6 truncations of the exact same type in mciseq.dll. 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:

Here’s proof that Pinball is indeed running on a 64-bit build of Alpha NT:

To make Pinball work on your NT build 2210 install, replace %ProgramFiles%\Windows NT\Pinball\pinball.exe and %windir%\system32\mciseq.dll with the following:

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 AXP64 directory of the install disc:

The Bug

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.

Below are the 2 reasons I could think of for not seeing the collision detector bug:

  • 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.
  • 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.

Of course, only Raymond himself could shed more light on this topic. It was fun (read: painful) debugging Pinball, as well as the NT kernel to fix the emulators – too much fun (read: pain) that I will never do it again.


Some trivia about me and pinball:

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.

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.

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.

Installing Windows XP on a Lenovo S20

This was a silly side project that got out of hand, building an XP physical machine to run some old software. Over in the UK, there is this fantastical store, CeX that sells all kinds of retro crap, often for cheap. Normally I wouldn’t care but with pc titles going from £0.50 to £3 it seemed like some fun 1990’s computing value right there!

I had been slowly amassing a collection of bargain bin, garbage tier games ‘from back in the day’ and while I had been running a few on VMware on Windows 10, with that sub £5 copy of Windows XP home, it sadly didn’t help with so many games being copy protected.

I would need a physical machine, and that is where this hunk of junk the S20 fell into place.

S20 is way overkill!

When it comes to Windows XP, the S20 is no slouch. With 12GB of RAM, a Nehalem 3Ghz Xeon W3550 @3Ghz, 2x 120GB SSD drives, and a functional optical disk, this makes for a great system. Rounding out the absurdity is a Nvidia Quadro 4000 with 2GB of VRAM. I’m pretty sure when XP was new I was still using a PII 233Mhz with 256Mb of RAM. So yeah, this is way overkill.

Since all the disks are SATA, the default install CD won’t work. As a matter of fact, not much works on the retail CD-ROM. I tried to use rufus but…

Setup cannot find the End User Licensing Agreement (EULA).

I got this strange error from the USB stick. It appears after some searching it’s seeing the CD-ROM and trying to load the rest of the installer from there. Further searches said don’t use Rufus, instead use “WinSetupFromUSB-1-10“. I figured if I was going to use something like this, that I’d want some crazy pirated/hacked up to date version of XP to compliment the whole hacked up experience, so I went with the seemingly reputable “Windows XP SP3 Integral Edition 2022-6-16“.

WinSetupFromUSB 1.10

Options seemed to be somewhat straightforward, make sure it targets your USB drive! not any external backups. It does recommend you reformat with NTFS & set the alignment for a much needed speed improvement. Other than checking a few boxes to make sure it’s got the BTS driver pack & it’s a 2000/XP/2003 from USB install it pretty much worked.

After rebooting to the USB, be sure to select the

By selecting this option it’ll inject the needed ‘modern’ disk drivers. Otherwise it just wont work (EULA error or inaccessible boot device).

If everything goes well it’ll have injected a tonne of drivers, allowing the install to work.

Once the text part of setup is completed, be sure to boot off the USB again, again choosing option 1 to Auto-detect and use SATA/RAID/SCSI, but then choose option 4 for the Second part of the Windows XP setup.

Windows PE?

From here the setup feels very Windows PE. I suspect it is, but it’ll continue basically unattended and on it’s own. From here you can just boot directly from the hard disk, once it’s finished installing. It will prompt for the USB stick again to add all the additional options

Optional options!

I didn’t know what to exclude or pick, So I just chose them all.

It did take about 20 minutes, but at least by the end I did have a very usable XP install.

Trying the first Quadro Driver I could find, and I got knocked down to 640×480 in 4bit colour. It sucked. I don’t know what the deal was.

320.92 is the version that worked for me!

Working Video

With video working, the next step is all the reaming device drivers. Ohver on Phils Computer Lab, he had mentioned snappy driver installer, but the first link I hit on google was some virus loaded thing. Luckily since this is a fresh install it wasn’t at all painful to shove the USB back in and format the machine. I think I was also spared a lot of damage as it was constantly failing with a “bcrypt.dll missing” error. Saved by being obsolete!

Instead, I found the one on sourceforge.net, and it was working as expected.

Adding the audio drivers took a few attempts at installing stuff, rebooting, trying the windows auto-detect, rebooting, re-running snappy driver, and a few more reboots, and I got the NVIDIA audio and the built in audio working.

Overkill XP

One thing is that some games fail entirely on XP. While GTA: Vice City had been running on Windows 10, it fails to do anything on XP. Older games with Win16 setup programs do run but Games like Links LS 1999 fail completely to run. I think the system has both too many cores, too much RAM, and it’s just plain too fast.

With all the talk of abandoning 8086/286/386 modes of operation, I thought it’d be a good time to build a box explicitly for 32bit gaming out of cast aside parts. The Lenovo S20 list price was an eye watering $3,645 USD, and the Quadro 4000 clocking in at $1,199 USD. This was not a casual machine for playing Mahjong Escape: Ancient China. But it’s kind of funny to know it does.

I have to throw some more stuff at it, but one could have only wished for a PC this fast in 2002.

Everyone seems to be losing their minds over the Windows XP Professional Key

algorithm being cracked.

But of course, how does that help me?

Unironically, I had purchased this for a whopping £4.68

No, really here’s the receipt. What a bargain!

Of course this is a legit copy with a legit key. But the online activation servers are all gone, and it looks like I’d have to call someone asking about my 22 year old copy of Windows, that I’ll load up and quickly forget.

Since I’m going to use QEMU, 0.90 with pcap support I thought I’d share the startup options:

set loopback=\Device\NPF_{3DF0EC5D-7FBE-46DF-ACF8-EF5D8679A473}
set vmnet1=\Device\NPF_{3BC364F4-5A15-405D-926C-C594383F0323}
qemu -m 512 -L pc-bios ^
-hda xphome.vmdk ^
-soundhw es1370 ^
-net nic,model=pcnet,macaddr=52:24:00:33:00:01 ^
-net pcap,devicename=%loopback% ^
%1 %2 %3 %4 %5 %6

I had high hopes for this thing. Clearly misplaced ambitions.

First up, it’s an upgrade version. So that means instead of installing XP I had to waste my time installing NT Workstation 3.51, then installing XP. Yuck. And of course it just want small FAT disks of the 2/4 gigabyte boundary type as it’s 1994. Not the bright future of 2002’s Windows XP.

I don’t know why Qemu 0.90 has issues with XP detecting the CD-ROM drive, but yeah that sucked. I wanted to load up some more insane SNA experiments, but there is no DLC / 802.2 driver for XP Home. wow.

At least once it’s satisfied, we can format the disk as one big happy partition, and we can get on with our lives.

Installation is rather uneventful, however we are instantly reminded that we have only 30 days to go. Since we have that nasty CD-ROM issue that means shutting down, and booting back up, but with this fun program on an ISO image, xp_activate.

I did try to make a call, to activate my Windows, but the connection was terrible and I’m not even sure if these numbers were right. No I mean I know they didn’t work.

So I did what all legit users end up doing, using the crack for my 21 year old copy of Windows.

And just a few clicks later, it was done.

Windows XP Home is activated.

I don’t know if it’s even really going to last, I didn’t try anything else, actually I already deleted it. And the XP folio is back on the bookshelf.

Not only is there no DLC, did you know you can’t uninstall TCP/IP? At least you can unbind it from your NIC. While it does have IPX/SPX there is no built in Netware client. When they said HOME they meant it!

Not as fun as Win64 Itanium, the earliest AMD64 Windows I can find

It does feel a lot like Windows XP for the Itanium, that strange half world of existence. It’s also from September 2003, the release image being named: 5.2.3790.1069.srv03_spbeta.030905-1850_amd64fre_client-professional_retail_en-us-AB1PXFRE_EN.iso

I’m sure if you google around you can easily find it.

To install you apparently need an early AMD 64 processor, otherwise it’ll trap on the installer. Back in 2004, I got a newly refurbished AMD Athlon 64 3200+ processor, from Tiger Direct. The machine was only a few months old, and I was able to get an early XP build for it. Oddly enough it’s simple enough to install on Qemu. I was able to use 0.90 & 7.20, jumping at extremes, although the PCI NIC IRQ’s do jump around on 0.90 preventing the networking from working.

I had a LOT of trouble getting a bootable hard disk image out of this for some reason. So I’ve found keeping C around 2,000 Megabytes, and installing MS-DOS 5/6 got me a bootable system. Also preserving the FAT disk. Not sure why but doing formats of FAT or NTFS always seemed to result in a non bootable disk

qemu-system-x86_64w.exe -cpu Opteron_G1-v1 -hda 2g.vmdk -m 512 -M pc-i440fx-2.0 -net nic,model=rtl8139,netdev=f00 -netdev user,id=f00,hostfwd=tcp::5555-:3389 -usb -usbdevice tablet  -accel tcg,thread=multi

Special thanks to RoyTam for the suggestion of the USB tablet & turning TCG multithreaded for v7+ of Qemu

Setting up is pretty normal.

You do get 360 days to use the beta. More than enough for simple testing. I’ve seen that the timebomb doesn’t work correctly so it may work forever. But it’s so rough around the edges, I can’t see anyone trying to run this native in 2023.

Notice it’s all AMD branding. Intel officially didn’t have their EMT64 Pentium 4’s, although IBM was pushing Intel hard to get them out the door. And I think they held off on a larger x86_64 launch as Intel had not publicly caved.

And in no time you are up and running. I find the mouse really weird on Qemu, so I always enable the remote desktop function and find it much easier to deal with.

One of the advantages of RDP is that audio redirection does work, so you can play pinball!

One annoying thing (to me) is that the SysFader process will hang all the time locking explorer.exe . Along with that it’ll leave phantom UI elements haning around like the Run… above. Yes, its annoying!

The solution is of course System Properties, and Performance, and either disable the Fade elements, or just turn off all the ‘eye candy’ which basically doesn’t really exist for this release anyways.

While there is some DirectX support, it is most likely just simple GDI passthrough, and of course no acceleration as the OpenGL screensavers run incredibly slow.

And thanks to betawiki.net for some hints & tips. I haven’t tried the VMware path, since AFAIK there is no other NIC drivers for this release.

As mentioned, hardware support is VERY limited. The single audio driver is a MPU401 port. This obviously was meant for an exceptionally limited audience.

The one thing I cannot find, is any version of a Platform SDK that targets AMD64 so early. The earliest I can find is version 14 from 2005.

The 2005 compiler does have this note:

The Microsoft® C/C++ AMD64 Processor Family-targeting compiler is a cross-compiler targeting the AMD64 processor family. The compiler runs on an x86 or AMD64 computer running Microsoft Windows® XP or Microsoft Windows® Server 2003. It is the compiler used for Microsoft® internal development and is used for building Microsoft Windows NT®, Microsoft SQL Server®, and other major applications. For debugging we suggest the use of WinDbg for AMD64. Visual Studio Whidbey will support the use of the Visual Studio debugger for debugging AMD64 applications.

2005-06 – 2944.0 – Platform SDK for Windows Server 2003 SP1 (April 2005 Edition)

With the compiler being:

Microsoft (R) C/C++ Optimizing Compiler Version 14.00.40310.41 for AMD64
Copyright (C) Microsoft Corporation. All rights reserved.

If anyone knows of anything earlier, I’d love to know! If only for the sake of messing around with it.

AMD64 Pinball extravaganza!

With all the talk of 64bit versions of Pinball I thought I’d share simple script to extract Pinball from an XP x64 CD-ROM so you can take it with you. It’s portable so thats nice too, although it doesn’t use any wad/pak/zip files so all the assets are loose files:

expand f:\amd64\font.da_ font.dat
expand f:\amd64\pinball.da_ pinball.dat
expand f:\amd64\pinball.ex_ pinball.exe
expand f:\amd64\pinball.in_ pinball.inf
expand f:\amd64\pinball.mi_ pinball.mid
expand f:\amd64\pinball2.mi_ pinball2.mid
expand f:\amd64\sound1.wa_ sound1.wav
expand f:\amd64\sound104.wa_ sound104.wav
expand f:\amd64\sound105.wa_ sound105.wav
expand f:\amd64\sound108.wa_ sound108.wav
expand f:\amd64\sound111.wa_ sound111.wav
expand f:\amd64\sound112.wa_ sound112.wav
expand f:\amd64\sound12.wa_ sound12.wav
expand f:\amd64\sound13.wa_ sound13.wav
expand f:\amd64\sound131.wa_ sound131.wav
expand f:\amd64\sound136.wa_ sound136.wav
expand f:\amd64\sound14.wa_ sound14.wav
expand f:\amd64\sound16.wa_ sound16.wav
expand f:\amd64\sound17.wa_ sound17.wav
expand f:\amd64\sound18.wa_ sound18.wav
expand f:\amd64\sound181.wa_ sound181.wav
expand f:\amd64\sound19.wa_ sound19.wav
expand f:\amd64\sound20.wa_ sound20.wav
expand f:\amd64\sound21.wa_ sound21.wav
expand f:\amd64\sound22.wa_ sound22.wav
expand f:\amd64\sound24.wa_ sound24.wav
expand f:\amd64\sound240.wa_ sound240.wav
expand f:\amd64\sound243.wa_ sound243.wav
expand f:\amd64\sound25.wa_ sound25.wav
expand f:\amd64\sound26.wa_ sound26.wav
expand f:\amd64\sound27.wa_ sound27.wav
expand f:\amd64\sound28.wa_ sound28.wav
expand f:\amd64\sound29.wa_ sound29.wav
expand f:\amd64\sound3.wa_ sound3.wav
expand f:\amd64\sound30.wa_ sound30.wav
expand f:\amd64\sound34.wa_ sound34.wav
expand f:\amd64\sound35.wa_ sound35.wav
expand f:\amd64\sound36.wa_ sound36.wav
expand f:\amd64\sound38.wa_ sound38.wav
expand f:\amd64\sound39.wa_ sound39.wav
expand f:\amd64\sound4.wa_ sound4.wav
expand f:\amd64\sound42.wa_ sound42.wav
expand f:\amd64\sound43.wa_ sound43.wav
expand f:\amd64\sound45.wa_ sound45.wav
expand f:\amd64\sound49.wa_ sound49.wav
expand f:\amd64\sound49d.wa_ sound49d.wav
expand f:\amd64\sound5.wa_ sound5.wav
expand f:\amd64\sound50.wa_ sound50.wav
expand f:\amd64\sound528.wa_ sound528.wav
expand f:\amd64\sound53.wa_ sound53.wav
expand f:\amd64\sound54.wa_ sound54.wav
expand f:\amd64\sound55.wa_ sound55.wav
expand f:\amd64\sound560.wa_ sound560.wav
expand f:\amd64\sound563.wa_ sound563.wav
expand f:\amd64\sound57.wa_ sound57.wav
expand f:\amd64\sound58.wa_ sound58.wav
expand f:\amd64\sound6.wa_ sound6.wav
expand f:\amd64\sound65.wa_ sound65.wav
expand f:\amd64\sound68.wa_ sound68.wav
expand f:\amd64\sound7.wa_ sound7.wav
expand f:\amd64\sound713.wa_ sound713.wav
expand f:\amd64\sound735.wa_ sound735.wav
expand f:\amd64\sound8.wa_ sound8.wav
expand f:\amd64\sound827.wa_ sound827.wav
expand f:\amd64\sound9.wa_ sound9.wav
expand f:\amd64\sound999.wa_ sound999.wav
expand f:\amd64\table.bm_ table.bmp
copy f:\amd64\WAVEMIX.inf WAVEMIX.INF

Naturally you’ll want to substitute F:\ with whatever drive letter your CD-ROM/ISO file is mounted on.

And thanks to a long needed feature in Windows 10 you can verify that yes indeed it is a 64bit version.

Or skip the pain, and download the first currently available AMD64 version here: pinball-3790-1069.7z

Isn’t that awesome?! Obviously ARM64 users are left out in the dark, as far as I know there was no ARM64 versions of Windows XP. As a matter of fact, was there any public versions of Windows XP for ARM? Naturally the Surface RT shipped with 8.0

Anyways at long last we can have our 64bit pinball despite the weird bugs, and how the plunger is mostly hidden no doubt due to yet more weird floating point/integer size inconsistencies

Anglofying & running Japanese Lemmings for Windows

On one of my later trips I picked up this fun title, Lemmings!

And looking at the back of the box, what fun it contains!

Support PC-98, Epsons, IBM’s, IBM PC/AT.. Probably FM Towns as well

One interesting thing about 1995, is that with the rise of Windows 95, this marked the end of the specialized PC market in Japan. Just as WING/Direct X basically killed off the DIY driver/extender environment on MS-DOS, by being able to abstract the hardware it removed any meaningful difference between an EPSON PC vs a PC-98, FM Towns, or even the lowly IBM AT/386.

This being a Win32 includes both WING & Win32s. A perfect snapshot of an early Win32 commercial game circa 1995, as you needed to cater to that massive Windows 3.1 install base, although so many were rushing to Windows 95. Naturally this also means that the setup program is a Win16 app, once more again to preserve that bridge of the Windows 3.1 & Windows 95 world.

Well the obvious thing to do is just install it on a legacy 32bit OS, and what better than Windows XP?

Lemmings happily running under Windows XP via VMWare.

Now to run it on something like Windows 10, it’s just a matter of copying the WINLEMM.INI into %sysroot%, along with placing a copy of WING32.DLL into the %sysroot%\SysWOW64 directory and you are good to go!

Japanese Lemmings on English Windows 10

Sadly the character encoding in Windows is still really lacking and doesn’t render all that great. However that had me thinking as almost a decade ago I did find a demo of Lemmings for Windows. Could it be possible to just overlay the executables & DLL’s to produce an English commercial version?

Surprisingly the answer is yes. I wasn’t sure what to expect, but it’s as simple as that!

The game is mostly playable, some parts are just coded to run as fast as possible, as no doubt nobody was imagining 1+ Ghz machines. So the intro, warp & suicide are almost instant.

It’s something to keep the kids entertained for a day in recent events. It’s been a LONG CNY.

Origin of the Windows XP ‘Bliss’ wallpaper

Charles O’Rear’s Bliss

You’ve probably seen this iconic image everywhere at one point.  This is Charles O’Rear’s picture simply titled ‘bliss’ that was bought by Microsoft in 2000 and used as the default wallpaper for Windows XP.

https://www.youtube.com/watch?v=AVXY8OEZAEQ
Interview with Charles

I found this interview of him recently and thought it was interesting enough for a quick post.

MIDI Mayhem on Windows 10

So I know it’s ‘probably’ the super cheap generic USB to MIDI dongal I got on the cheap, but it just doesn’t work on Windows 10.

Using DOSBox, I get the following output when cycling between devices on the console:

MIDI:Opened device:win32
MIDI:win32 selected Microsoft GS Wavetable Synth
MIDI:Opened device:win32
MIDI:win32 selected USB2.0-MIDI
MIDI:Opened device:none
MIDI:win32 selected MIDIOUT2 (USB2.0-MIDI)
MIDI:Opened device:none

As you can see it clearly can see the USB device, but when it opens the device it fails. And yes I’ve tried Administrator.  And for the hell of it, I fire up Windows XP on VMWare, connect the USB dongal, and amazingly:

MIDI:Opened device:win32
MIDI:win32 selected USB Audio Device
MIDI:Opened device:win32
MIDI:win32 selected USB Audio Device [2]
MIDI:Opened device:win32
MIDI:win32 selected Microsoft GS Wavetable SW Synth
MIDI:Opened device:win32

Yes, I can open the out port just fine.  So now I run a virtualizer to run my emulator to drive a physical peripheral… Ugh.  Has MIDI been this messed up all along and I never noticed?

Oh yeah, the GS Wavetable Synth works fine, as did MUNT before I uninstalled it, thinking it was somehow interfering with anything.

I know I’m using this fine device, the QinHeng USB MIDI adapter, which apparently is notorious crap, but my recently acquired Yamaha MU 80, works fine with it on Windows XP.

QinHeng USB MIDI adapter

QinHeng USB MIDI adapter

Ugh.

Retro computing for $99

I was cruising around New Capital Computer Plaza, looking for some cisco console cables, and I saw a bunch of old Xeon desktop computers for sale.  Prices were in the 250-500 USD range, which seemed pricey to me.  And keeping in mind that my desktop is already a Xeon E3-1230, it did seem kind of pointless.  But then I saw this Dell Precision 490 for about $99 USD.

Dell Precision 490

Dell Precision 490

Great, so what are the general specs?

Well, the ‘nice’ thing about Dell is that they keep all their old stuff online, so looking at the specsheet we can see It’s not a bad machine for something circa 2006.  Even archive.org has the old pricing online too!

Mine came with a Xeon 5160, 8GB of ram, 250 GB disk, and an ATI HD 4850

  • Dell Precision Workstation 490 Desktop – 32bit $2,852
  • Dual Core Intel® Xeon® Processor 5160 3.00GHz, 4MB L2,1333 [add $930]
  • 4GB, DDR2 SDRAM FBD Memory, 533MHz, ECC (4 DIMMS) [add $570]
  • 4GB, DDR2 SDRAM FBD Memory, 533MHz, ECC (4 DIMMS) [add $570]
  • 250GB SATA 3.0Gb/s,7200 RPM NCQ Hard Drive with 8MB DataBurst Cache™ [add $90]

By my calculations this machine was about $5,012 USD, and that isn’t including the after market video card, which would be about $180 USD when it was new in 2008, bringing the total MSRP on this thing to $5,192 USD!

Of course it is now 2016, and this machine is 10 years old, with an 8 year old video card.  Also of interest is that it came licensed for Windows XP x64, which was the first publicly available AMD64 OS from Microsoft.  Unlike traditional Windows XP, this 64bit version is actually built around Windows server 2003.

The computer came with a pirated copy of Windows 7, which I wanted to promptly remove.  I have an old MSDN copy of Windows XP x64 that I wanted to install, however the optical drive is broken, and I needed to install from USB.  Thankfully even though this machine is old, it can boot from USB devices.  The first step was to download WinSetupFromUSB 1.2 to get XP onto a USB stick.  Naturally once I had booted from USB, the disk controller wasn’t supported.  The BIOS screen revealed that it was a:

Serial ATA AHCI BIOS, Version iSrc 1.02.25 07222007. Copyright (c) 2003-2006 Intel Corporation. Copyright (c) 2003-2006 Dell, Inc. Controller …

This translated into the Intel iaStor product, and I was able to slipstream in the last version from 2009, 8.9.0.123 into the USB by using nlite.

I have to say that once I had removed the gratuitous pirated Chinese Windows 7, and installed XP that this machine was pretty damned snappy!  As always I updated to service pack 2.

The onboard NIC is a Broadcom NetXtreme 57xx gigabit NIC, which unlike the ‘gigabit’ NIC on my newer desktop, this one actually works at 1Gb.

With Windows XP installed, I went to the AMD/ATI site, and found the download for the HD 4xxx series, and went ahead and installed Steam.

I have to say that Half-Life 2 runs GREAT.  According to it’s onboard FPS counter I was getting anywhere around 60-180 FPS.  Pretty awesome.  Fallout 3 runs pretty snappy too.  I tried Deus Ex: Human Revolution, and much to my surprise this vintage 2011 game runs on my 2006 Windows XP x64 setup.

What about the overall internet experience?  Well this being Windows XP, You are pretty limited by the traditional browsers.  Internet Explorer 6 is the default browser which to say it’s dated is an understatement.  I prefer Internet Explorer 7 over 6, but they are both so old it doesn’t matter. Internet Explorer 8 is also an option. The last version of Google Chrome to support Windows XP was 49.0.2623.75.  Chrome 49 plays youtube just fine, Scripted Amiga is a little pokey, but does run.

And how does this thing compare to my normal desktop?  Running Geekbench 2, I get a score of 3396 vs 10864.  Now keep in mind this $99 machine only has a dual core processor, while my newer machine has a quad core + hyper threading CPU.  An interesting comparison is with the Xeon E5320 CPU, with the Dell eking out a victory.

Installing additional software was possible via Virtual Clone Drive, while I did have ISO images of stuff I’ve had physical media of in the past, a broken drive wasn’t going to help me read anything.

I didn’t activate it, but Windows 10 will run on this machine as well.  I’ll probably upgrade by getting a second JD210 heat sink (I already found another 5160 processor for $10)

It’s a great machine for sub $100.  I’d hate to have spent over $5,000 on this thing, but it’s kind of cool to see that a 10 year old machine like this can still be sort of usable.  Of course updating the software will certainly go a long way in making it really usable.