OmniOS / Illumos / Solaris / SunOS / ARM64 / AARCH64 on QEMU

(This is a guest post from Antoni Sawicki aka Tenox)

Ever since inception of Illumos I always wanted to get it working on ARM / AARCH64. But being under development it was somewhat difficult task. I previously tried building arm64-gate but there always was something not quite right. Turns out OmniOS has a ready to run image that one can boot under QEMU!

Download file from here: https://downloads.omnios.org/media/braich/

They also have a run shell command: https://downloads.omnios.org/media/braich/run

This is mine:

qemu-system-aarch64 \
-nographic \
-machine virt \
-accel tcg \
-m 3G \
-smp 2 \
-cpu cortex-a53 \
-bios u-boot.bin \
-netdev vmnet-shared,id=net0 \
-device virtio-net-device,netdev=net0 \
-device virtio-blk-device,drive=hd0 \
-drive file=braich-151055.raw,format=raw,id=hd0,if=none \
-device qemu-xhci \
-device usb-kbd \
-device usb-tablet \
-semihosting-config enable=on,target=native

I hope they continue development and at some point I will be able to run this on my home server / NAS !

MIPS RISC/os on MAME

(This is a guest post by Antoni Sawicki aka Tenox)

This is a very lazy post. I didn’t do anything here… I don’t exactly remember where it came from but I had this HDD dump of a pre-installed RISC/os 4.52 for MIPS Systems RC2030 lying around. It might have came from bitsavers and/or here? I was recently contacted by Enrique Tejeda Canobbio who managed to convert the image into a chd format and boot it up on MAME which has MIPS support!

MIPS Systems RC2030 on MAME

It turns out the disk image had some non trivial password set for the root account, but with help of hashcat and a decent GPU we got it cracked in 20 minutes or so. Here for your viewing pleasure is the fully working OS:

MIPS RISC/os 4.52 running on RS2030 on MAME

The system comes with a working C compiler and there are known some ports of various applications, also X11R5. I will post an update once I add some more stuff to the base image. For now just wanted to get this out in to the wild!

Download from here! Login root/root. The root password for the original image is Wivvle1!

Please post comments or ping me on Discord if you get networking or X11 working!

Installing HP-UX 11i v1 (11.11) 32bit PA1.1 on QEMU 10.1

(This is a guest post by Antoni Sawicki aka Tenox)

Definitely not the first person doing this. In fact this has been quite widely documented, in particular by astr0baby and openpa.net. Just my personal observations and tweaks.

Install

ISOs from 2006 MCOE work just fine

qemu-img create -f qcow2 hpux.img 20G

qemu-system-hppa \
-machine B160L \
-smp cpus=4 \
-accel tcg,thread=multi \
-boot d \
-drive if=scsi,bus=0,index=6,file=hpux.img,format=qcow2 \
-m 512 \
-d nochain \
-cdrom mcoe.1_5.iso \
-net nic,model=tulip \
-net user

I installed mostly the defaults, removed Java spyware and Web based management.

I recommend using advanced mode and editing File Systems to your desired size or just leaving /stand and / and deleting everything else. Otherwise, if you do defaults, you will be facing resizing them in single user mode later.

Forget any serial console, telnet stdio or forwarding X over SSH nonsense. Graphical console now works fully end to end without any issues, except for nsswitch.conf.

When trying to login via CDE you will get an error about unable to start desktop messaging system. Login either via text console or failsafe session. Copy /etc/nsswitch.files to /etc/nsswitch.conf. Also make sure that your hostname can resolve via /etc/hosts.

Once this is done you should be able to login via CDE:

If you left filesystem defaults, you will be facing this:

To fix this, add -boot menu=on to qemu parameters, run boot pri then answer yes to interact with IPL and then type hpux -is.

This will land you in single user mode where you can extend volumes like so:

# cat /etc/fstab
....
lvextend -L 4096 /dev/vg00/lvol7
extendfs /dev/vg00/lvol7
....

But ideally this should be done ahead of time during install in File Systems tabs (advanced mode).

I like to disable some slow starting and unnecessary services on startup, to do so go to /etc/rc.config.d and edit bunch of files changing value from =1 to =0. I typically disable SNMP, CIM and Mailserver, Webadmin, Diagnostics, EMS, nettl, icod, etc at minimum. Also some stubborn services need to be disabled by renaming or removing them from /sbin/rcX.d

Software Install

Note that this emulates PA-RISC 1.1 (32bit) and software built for PA-RISC 2.0 (64bit) will not work. Very little software is marked which platform is it for, so your mileage will vary. You will encounter errors and crashes. To avoid confusion check the binary with file(1) utility.

I have a bunch of handy tools like bash/gmake/gzip/gtar/ncftp bundled up here. There is GCC 4.0.2 here as a depot and here as a tarball. I also installed a bunch of tools and enhancements from Soft Pack and Apps cdroms.

Most importantly SimCity!

More games can be found here. However this emulated HP-UX doesn’t have working OpenGL so don’t expect much.

Finally, to shut down the os:

reboot -h

The ready to run image is available here. It works with QEMU 10.1. It has bash & gcc pre-installed. Login as root/root.

UNAUTHORIZED WINDOWS/386

I wanted to share something special, a friend of mine, Will, has been so busy working on this project and I wanted to share it here for everyone here first.

This is pretty technical, but still interesting deep look into one of Microsoft’s early 32bit/386 based programs that would go on to revolutionize the world, Windows/386! It brought the v86 virtual machine to normal people wrapped up in a nice GUI.

By Will Klees (CaptainWillStarblazer)

INTRODUCTION

I’m CaptainWillStarblazer, an author who has previously been featured on VirtuallyFun for my work on EmuWOW, which enabled running Win32 apps compiled for the MIPS and Alpha AXP architectures to run on x86 computers. While I was born in the 21st century, I have a keen interest in the computers of the past, particularly in the history of Microsoft. The foundations for the breakout success of Windows 3.0, 3.1, and 9x were laid with Windows/386, but until recently, the inner-workings of Windows/386 have not been well understood, and beyond the very high-level, exactly how it works have been considered an opaque black box, not ventured into with books (official or otherwise) like its successors. No longer.

FOREWORD

Before I begin, I would like to acknowledge that all of my work here was informed by the research of the late, great Geoff Chappell, who has many in-depth pages on this topic as well as many others that laid the groundwork for this post. His contributions to the scene are immeasurable, and I, along with many of you, stand on the shoulders of giants like him. It is unfortunate that up to this point, Windows/386 has not faced much reverse-engineering work (especially in comparison to the better-documented Windows 3.x and 95), but for the first time, it is being examined.

ARCHITECTURE OF WINDOWS/386

Windows/386 Loader (WIN386.EXE)

The structure of Windows/386 is broadly similar to later versions of Windows running in enhanced mode. The journey begins with WIN386.EXE, which is a standard MZ EXE. WIN386 first performs some checks to make sure that your machine can run Windows/386 (you have enough memory, the right version of DOS, you have an 80386, defending against early buggy 386 steppings, etc.), among them being whether your computer is currently executing in Virtual-8086 Mode. If you are, then that means that another piece of protected-mode software is already controlling the computer. From there, it checks if Windows/386 is already running, and if so, displays an error message. From there, it checks if the resident protected-mode software is a memory manager that it recognizes (either Compaqโ€™s CEMM or Microsoftโ€™s EMM386), and if so, uses the GEMMIS (Global EMM Import Specification) API to suck out all of the EMS mapping page tables from the LIMulator and then switch back into real-mode. If it doesnโ€™t recognize the protected-mode software, it at this point throws another error message.

This check for early buggy 386 steppings was retained by Microsoft even into Windows 8.1, surprisingly enough. The system can also check for 386 chips with bad 32-bit multiplication, though it only warns the user of potential issues, it doesnโ€™t fail to run like if you are running a Model 1 Stepping 0 chip.

[photo of the code checking for the buggy 386]

Finally, it begins loading the Virtual DOS Machine Manager (VDMM) into memory from the file WIN386.386. This file is not an OS/2 Linear Executable like the 386 files from later versions of Windows (that format did not yet exist), rather it is the 32-bit x.out executable format from Xenix-386 (thank you, Michal Necasek!), which makes sense as it was the only 32-bit executable format that Microsoft would have a linker for at the time (and interoperated well with Microsoft’s OMF-based tools, such as MASM). Among the features of this format is that it contains a rather-lengthy symbol table. Not only does this aid reverse-engineering, however, itโ€™s also a key part of the loading process. The WIN386.EXE loader will populate parts of the loaded image with important data using these symbols.

Virtual DOS Machine Manager and Virtual Device Drivers (WIN386.386)

WIN386.386 contains a statically-linked binary image of the VDMM itself as well of all of the virtual device drivers. Disassembling the source code of Windows/386 was an interesting exercise. On my repo, I have a partial disassembly of EGA.3EX, the WIN386.EXE loader for the EGA version of WIN386.386, which is a standard MS-DOS executable and as such easily examined by reverse-engineering tools. However, the 32-bit x.out format used by Windows/386 is not readily supported by any reverse-engineering tools that I am aware of. While it would be possible to write an Ida or Ghidra plugin, I figured the simplest solution was to convert it to a more standard executable format that could be understood; COFF. After extracting the 16-bit entry stub into a small flat binary to be disassembled on its own, the COFF file could finally be opened (in reality, tools didnโ€™t seem to like the COFF file very much, so I had to use GNU objcopy to convert it to ELF so that tools would like it) and examined.

[photo of the conversion program]
[objdump or dumpbin examining the resulting COFF image]

WIN386.386 starts execution in real-mode with a short stub that prepares the Global Descriptor Table, loads the page directory, switches into protected-mode, and does a far jump to the 32-bit entry point. At this point, it starts WIN86.COM (loaded by WIN386.EXE) to start a real-mode copy of Windows in the first VM, otherwise known as the “System VM”.

Two valuable resources for examining the code of Windows/386 have turned out to be the source code for MEMM (Microsoft Expanded Memory Manager, better known by its final name EMM386) from the MS-DOS 4.0 repository, and the Windows 3.0 DDK sample VxDs. It is obvious from comparing the Windows/386 disassembly to portions of the MEMM source code that portions of MEMM, both for EMS emulation and for the V86 monitor in particular, were simply lifted wholesale into Windows/386, and code comments even make reference to this. Amusingly, MEMM was assembled using the MASM 4.00 assembler which has poor support for the 80386, so copious amounts of macros are used to add in 386 instructions. Perhaps the most interesting EMM386-related finding, however, was that parts of EMM386 were written in C. This seemed obvious given the leading underscore and __cdecl-style calling convention in several Windows/386 functions, but examining the code finds it to be true.

[emm386 c & 32-bit corresponding asm]

Based on my examination, it appears that if you took the EMM386 C code and compiled it for a 32-bit flat model (EMM386’s code was compiled for a 16:16 far pointer model), you’d get the assembly in Windows/386. This is interesting because Windows/386 was previously thought to be written entirely in assembly, and the Microsoft 386 C compiler was in its infancy when Windows/386 was being written. It’s not entirely unbelievable, however, since Xenix-386, the earliest known user of the compiler, came out around the same time as Windows/386.

The other handy reference while disassembling Windows/386 has actually been the Windows 3.0 DDK. Since the VDMM contains all of the virtual device drivers statically linked into it, and many of Windows 3.0โ€™s virtual device drivers can trace their beginnings to Windows/386, thereโ€™s often a strong correspondence. Many APIs have changed, however, including how VxDs call each other. In Windows/386, itโ€™s just a simple call, while their status as separate modules in Windows 3.0 requires a VxDCall; a special interrupt that causes the VMM to transfer control to another VxD.

[comparing between a Windows 3.0 VxD and a Windows 2.03 VxD]

Examination of the MapLinear function finds that the memory map for Windows/386 2.xx is essentially identical to Windows 3.0. The first 4MB is the private per-VM arena (so chosen as it allows a task-switch to be as simple as altering the first PDE in the page directory, rather than having to switch page directories), then the 4-20MB range identity-maps the first 16MB of physical memory, and the VDMM is loaded at the 20MB mark.

As a quick example of one of the code paths in Windows/386, when Windows/386 needs to return an entry point to a client application (such as through the INT 2FH AX=1602H API), it needs some way to cause a client calling that entry point in Virtual 8086 Mode to trap into protected mode. As documented by Raymond Chen, they found that the quickest way to do this was via the invalid opcode fault, and the invalid opcode they chose for this was 63H, or ARPL. As part of a mechanism that is still in place in Windows 95, when a VM executes an ARPL instruction, it’ll trap into the VDMM, vectoring through the IDT to vm_trap06.

[photo of the IDT]
[photo of vm_trap06]

From there, it determines if the fault came from a VM or not. If not, it executes the Windows/386 error handler, but if it did, it calls into VmFault. VmFault looks up the faulting opcode through a table and invokes the appropriate handler for it. The appropriate handler for ARPL is called Patch_Fault. From there, it determines what kind of call this is, and if you’re lucky, it’ll end up in TS_VMDA_Call, which is described in the next section.

[photo of VmFault]
[photo of Patch_Fault]

The System VM – Windows 2 and WINOLDAP

The code running inside of the system VM is almost identical to a standard real-mode Windows 2.xx install, with one exception: WINOLDAP. Responsible for executing MS-DOS (โ€œoldโ€) applications, WINOLDAP is totally different in Windows/386 (and as such, not functional if you try to load WIN86.COM directly from real-mode on its own, which otherwise provides a perfectly workable real-mode Windows experience), making heavy use of 386 instructions and of the “Virtual DOS Applications” (VDA, otherwise known as VMDOSAPP) API (accessed via INT 2FH AX=1601H in Windows/386 2.03 and 2.11) which is made available exclusively to the system VM, allowing WINOLDAP to control the execution of other virtual machines.

[photos of the dispatch tables and routines for VDA]
[example app using VDA]

While the details of this API certainly changed for Windows 3.0 and for later versions, WINOLDAP continued to work in fundamentally the same way, with the DOS application running in the System VM (intended to be Windows) being uniquely privileged to control operations in other virtual machines. Given that many people have figured out how to make Windows/386 start applications other than Windows itself (such as COMMAND.COM), this means that nothing would stop a sufficiently enterprising developer from developing a text-based MS-DOS application that leveraged this API to provide multitasking. In fact, this is likely how Raymond Chenโ€™s โ€œcharacter-mode task switcherโ€ functioned. WINOLDAP is worthy of further examination to determine exactly how it works, and perhaps to develop a multitasking MS-DOS. Obviously, this API, intended to have only Windows as a client, is totally undocumented other than by myself and Geoff Chappell, but further work could reveal its secrets.

In addition to the VDA API, Windows/386 also provided a much more limited API to callers in other virtual machines (accessed via INT 2FH AX=1602H), that appears to still be available in Windows 3.0 and is primarily responsible for networking.

For most of my experimentation, I actually sidestepped booting Windows altogether so that I could run my own code in the System VM. This is fairly simple; all you need to do is copy COMMAND.COM over WIN86.COM, then start WIN386, and viola! You’re running COMMAND.COM in Virtual 8086 Mode! Probably the most notable change is that if you didn’t already have any LIM EMS memory, you do now.

LOST WINDOWS/386 DDK

While no DDK for Windows/386 2.xx has been located, hints have been scattered for its existence. Most notably, the Windows 3.0 386 Virtual Device Adaptation Guide provides guidance on the differences between Windows/386 2.xx and Windows 3.0, and how to port virtual display drivers from one to the other, suggesting that Microsoft did provide tools to enable third-party developers to write Windows/386 virtual device drivers. Itโ€™s not difficult to imagine what this DDK would have looked like. Likely distributed alongside the regular Windows/286 real-mode DDK, the Windows/386-specific portions would include the 32-bit capable MASM5, along with early versions of MAPSYM32, WDEB386, and the Xenix x.out ld link editor. Very likely, Microsoft provided sample code for each of the VxDs included with Windows/386 (including the CGA, EGA, and Hercules VDDs), as well as a precompiled OMF object containing the VDMM itself, and then one would link everything together.

It bears repeating that the documentation on porting virtual device drivers from Windows/386 2.xx to Windows 3.0 was limited solely to virtual display drivers. The only other references to Windows/386 2.xx in the Virtual Device Adaptation Guide discuss the Windows/386 API callable by DOS applications running in a DOS box (many device drivers and applications, including network stacks, were Windows/386 aware). This could mean that other types of drivers could be more easily reassembled for Windows 3.0 without documentation, but I doubt it. As it stands, most of the virtual device drivers included in Windows/386 were fairly generic; the COM port, timer, PIC, keyboard, and other such devices work almost identically in every PC-compatible computer. On the other hand, the display driver is the one major component that Windows would need to interact with and that would significantly change between different types of machines. Additionally, due to the statically-linked nature of Windows/386 at this point, having more than one VxD as the variable factor could balloon into a smorgasbord of different combinations of drivers statically linked into the WIN386.386 image. As such, it stands to reason that the only driver built by third-parties (though no such driver has yet been located) is a virtual display driver. This lines up with Microsoftโ€™s own distribution of Windows/386, as the disks include separate 386 files for each supported display (the appropriate file being copied for your machine based on your selection during setup) and a matching 3EX file that gets copied to become the WIN386.EXE loader, and display drivers (also including their own complete Windows/386 images, obviously based on customizing the EGA/VGA VDD) have been found for other display adapters as well. This is compounded by the fact that during SETUP (including for real-mode Windows), the 16-bit display driver is statically linked into the Windows kernel (in other words, you can only load a display driver during SETUP) for the “fast-boot” configuration (though this can be disabled for a “slow-boot” on debug versions, more similar to how Windows 3.0 and above boot). A lot of reading between the lines is needed here, but it does seem that the only customization Microsoft intended was for OEMs to provide their own virtual display drivers.

BREAKING INTO WINDOWS/386

In absence of the Windows/386 DDK and its associated debugger, options are fairly limited as to peeking into the internals of Windows/386 while it is active. Promise was initially found in WIN386.EXE making a call to INT 68H (the WDEB386 real-mode interface, also used by the Deb386 debugger developed for EMM386 that no doubt was the immediate ancestor of WDEB386, as well as by compatible debuggers such as SoftICE) with AH=43H (D386_Identify, typically the first call made when initializing a program that uses WDEB386), no doubt trying to call out to its version of WDEB386, if present. However, the version of WDEB386 from Windows 3.1 only partially worked. While a CTRL-C could break into WDEB386 at any time, it could only trace through Virtual 8086 Mode code (always breaking at an ARPL VM-86 breakpoint), and whenever you tried to resume execution using the G command, Windows/386 would exit.

As a result, I had to improvise my own debugger, which required me to gain the ability to execute my own 32-bit code within Windows/386, which has never before been achieved. I immediately decided to adopt a similar approach to WDEB386; leave the debugger behind in conventional memory before Windows/386 starts up, and then have it call into me, so I quickly set about writing a small TSR. The TSR hooked INT 69H with a routine called Intrude that would patch the IDT of Windows/386 (found via traversing the image symbol table) to point to my own code for interrupt vector 0 (the divide exception handler). That way, whenever a divide exception occurred, it would vector into my own code.

The next question you may be wondering about is how I got Windows/386 to invoke an INT 69H in the first place? The answer lies in the real-mode initialization stub of WIN386.386; the part that switches into protected-mode. Examine the listing below:

Enable_A20:

01B7 803EBD00F8 CMP BYTE PTR [Computer_Type],0F8H ; Check for fast A20 support

01BC 7707 JA Enable_A20_Slow

01BE E492 IN AL,92H ; Fast A20 enable

01C0 0C02 OR AL,2 ; Set bit 1 (A20 line control)

01C2 E692 OUT 92H,AL ; Output back to port 92H

01C4 C3 RET

Enable_A20_Slow:

01C5 B4DF MOV AH,0DFH

01C7 EB12 JMP Set_A20

By the time Enable_A20 is called, which checks the computer type from the BIOS, most of the data structures needed to enter Windows/386 have already been set up, so I patched Windows/386 to simply remove Fast A20 support and always use the slow code, putting an INT 69H in the slack space. In other words, it replaces the instruction at TEXT16:01B7 with an INT 69H (CD 69). Since the original instruction is 5 bytes long, the remaining three are padded with NOP (90). The instruction at TEXT16:01BC is then altered to be an unconditional jump (EB) to always invoke the slow A20 line control. Since the loaded object is always at offset 400H in the file, and the offsets appear to be the same for all versions of Windows/386 on all devices, the changes are:

5B7: 80 -> CD

5B8: 3E -> 69

5B9: BD -> 90

5BA: 00 -> 90

5BB: F8 -> 90

5BC: 77 -> EB

The trouble at this point was that, while my program did work, it left the protected-mode code sitting in conventional memory, and part of the System VM’s inherited address space and thus subject to corruption. As a result, I wanted to move it up into extended memory, out of the reach of any pesky DOS programs. My first thought was to use XMS memory through HIMEM.SYS, which was introduced with Windows/386 2.11 to facilitate access to the HMA for Windows. Unfortunately, while this did sort of work, it turns out that Windows/386 (which if you’ll recall was initially designed before XMS or HIMEM.SYS) does not respect XMS allocations made before Windows loads, and thus considers them part of its extended memory pool (a fact I was taught by the fact that it corrupts the first two DWORDs of every 64K memory block starting after the HMA as part of its memory test). It is also important to realize that Windows/386 2.11 does not provide virtual XMS services to any client VMs (though Windows 3.0 and later versions do), except for HMA access to the System VM only (Windows/286 2.11 also used the HMA on 80286 and above systems, hence the “286” name, though it otherwise worked fine on XT-class machines, and since Windows/386 ran Windows/286 in the System VM, it made sense to also support the HMA there).

As a result, I used the “expand-down” memory allocation method of determining the amount of installed extended memory using INT 15H AH=88H, and then hooking that interrupt to report 132K less memory than there was before, and using the last 132K of extended memory for my own purposes. Since INT 15H AH=88H can report up to 64MB of installed extended memory, while INT 15H AH=87H to copy into extended memory only supports up to 16MB, I had to write my own routines to copy into extended memory by switching into protected-mode and then back. As a result, W386DBG has to be loaded before any memory manager that places the machine into Virtual 8086 Mode, such as EMM386, or anything that allocates XMS memory (not that any such programs are likely to be used alongside Windows/386, as just as I stated earlier, the XMS memory would be corrupted).

As you can see, if you cause a divide exception in DEBUG.COM, it’ll print out “W386DBG” in the upper-right of the screen and then hang the computer. This won’t work for a software INT 0, because software interrupts from Virtual 8086 Mode vector through the GPF handler.

[photo of the program launching]
[photo of the hang with the VBox debugger showing where we hung]

Note that while we lack any debug version of the VDMM (along with any symbols that it may contain or debug messages it may output), the VDMM itself does as stated earlier have a considerable symbol table, and we have debug versions of Windows 2 as part of its DDK, which were meant to be used with SYMDEB and include symbols, so at least we can have full debugging capabilities for the 16-bit components of Windows, simply by loading debug Windows 2 into the System VM, as no doubt one was intended to do when developing device drivers for Windows/386. Obviously, W386DBG is not yet a functional debugger, but it has gained the ability to grab control from Windows/386, which is perhaps the most important part.

INTO THE FUTURE WITH WINDOWS VERSION 3.0

Lately, I have become interested in turning my attention to the Windows 3.0 version 14 debug release that shipped to ISVs in early 1989. As one would expect, it shows many similarities to Windows 2.xx, but is already well on the way to becoming the Windows 3.0 that we know.

Notably, the WIN386.386 file is now gone, having been merged into WIN386.EXE as with the final version of Windows 3.0, meaning that the same DOS executable both loads the VMM and contains it. However, the VMM itself (pointed to by the e_lfanew field in the MZ header) is not an OS/2 2.0 Cruiser Linear Executable like the final version (or, more properly, the W3 format which contains multiple LE VxDs within it), but rather another bespoke format with a โ€œW386โ€ signature that I have not yet torn into yet. All of the VxDs are still statically linked at this point, but the symbol file is showing movement toward the VMM we know from Windows 3.0.

I havenโ€™t disassembled all of the real-mode entry portion of WIN386 yet (this will allow me to fully understand the file format), but an interesting piece of code new to this build checks to make sure not only that the DOS major version is at least 3 (3 being the minimum DOS version) but also less than 10, as 10 is the major DOS version reported by OS/2 1.xโ€™s 3xBox, making Windows/386 3.0.14 OS/2-aware (and avoidant).

One piece of Windows 3.0-related history that was recently discovered was the manual for Murray Sargentโ€™s Scroll-Screen-Tracer debugger. The debugger is far too rich in features to begin to go over them, but among its incredible DOS-extending features include support for debugging applications in Virtual 8086 Mode (a la SoftICE), debugging Windows, and debugging regular MS-DOS applications running in the 80286โ€™s Protected Mode, much as was described in โ€œSaving Windows from the OS/2 Bulldozerโ€.

Interestingly, the DOS extender provided by WIN386, along with PKERNEL.EXE (the protected-mode Windows kernel) seem to have more in common with the 80286 DOS extender, DOSX.EXE, from Windows 3.0, along with the 80286 standard mode kernel, KRNL286.EXE, than they do with the enhanced mode counterparts.

For example, like in the final version of Windows 3.0, DOSX (in this case, WIN386) switches into protected-mode before loading PKERNEL/KRNL286, giving it the unique distinction of being an MZ executable that starts in protected-mode, using a stub to start executing the NE portion of the file. By contrast, in Windows 3.1 (and 3.0 enhanced mode), the DOS extender switches back into real / Virtual 8086 Mode before loading the kernel, which then uses DPMI to switch into protected-mode.

Along with translation for DOS API services, according to Michal Necasek of the OS/2 Museum, WIN386 appears to provide some sort of selector management interface via INT 31H that could be considered a sort of proto-DPMI. Disassembling both WIN386 and PKERNEL promises to be an interesting exercise. Not much is known about the early history of DPMI, but the first sign of it outside of Microsoft appears to date to Fall 1989:

I will never forget how startled I was when I encountered the DOS-Protected Mode Interface (DPMI) in its primordial form for the first time. I was sitting in a Microsoft OS/2 2.0 ISV seminar in the Fall of 1989, with my mind only about half-engaged during an uninspiring session about OS/2 2.0’s Multiple Virtual DOS Machines (MVDMs), when the speaker mentioned in passing that OS/2 2.0 would support a new interface for the execution of DOS Extender applications. This casual remark focused my mind remarkably…

After the speaker finished, I went up to him and asked for more information, explaining that his mystery interface was about to have a severe impact on a book project near and dear to my heart. In a couple of hours, the Microsoftie returned with a thick document entitled “DOS Protected Mode Interface Specification, Version 0.04” still warm from the Xerox machine and generously garnished with “CONFIDENTIAL” warning messages. I suspect I made a most amusing spectacle, as I flipped through the pages with my eyes bulging out and my jaw dropping to the floor. The document I had been handed was nothing less than the functional specification of a protected-mode version of MS-DOS!

Microsoft originally defined the DPMI in two layers: a set of low-level functions for interrupt management, mode switching, and extended memory management; and a higher-level interface that provided access to MS-DOS, ROM BIOS, and mouse driver functionality via protected-mode execution of Int 21H, Int 10H, Int 33H, and so on. The higher-level DPMI functions were implemented, of course, in terms of the lower-level DPMI functions and the extant real-mode DOS and ROM BIOS interface.

Ray Duncan, Extending DOS, 2d ed., 1992, pp. 433-438

Obviously, by this point, Microsoft, who was still heavily invested in OS/2, planned to implement DPMI into OS/2 2.0, though they would not do so for about a year afterwards. Desiring crossover with the protected-mode DOS apps that would run on Windows (most crucially, Windows itself) was no doubt a desire for the OS/2 development team. I was surprised to learn that DPMI was already by this point mature enough to have even a preliminary specification released. Moreover, Microsoft went on to, at the behest of DOS Extender vendors, such as Phar Lap and Rational Systems, excise from the DPMI specification all of the higher-level DOS Extender components, and “DPMI 0.9” was born, containing only the low-level building blocks of a DOS Extender. As Andrew Schulman went on to say, the DOS Extender portions of DPMI ended up being split off into their own document:

Microsoft has an internal document (“MS-DOS API Extensions for DPMI Hosts,” October 31, 1990) that devotes about 30 pages to the Windows 3.0 DOS extenders… For example, the 1990 document discusses the 32-bit DOS extender provided by DOSMGR. The DOS file read and write calls (INT 21h functions 3Fh and 40h) have the count register (ECX) extended to 32-bits, allowing 32-bit programs to perform DOS file I/O of more than 64K at a time.

Andrew Schulman, Unauthorized Windows 95, 1994, pp. 151-52

On the PCjs website, Version 0.04 from March 1991 of the MS-DOS API Extensions for DPMI Hosts can be found, and it is obviously quite a preliminary document. What it seems is that DPMI was designed simply to expose the Windows DOS Extender (used by the Windows kernel) to other DOS protected-mode software. DPMI sits on the AH=16H Windows/386 part of the INT 2FH multiplex (W386_Int_Multiplex), with the “Get Protected Mode Switch Entry Point” API from DPMI even being documented as part of INT2FAPI.INC from the Windows 3.0 DDK as W386_Get_PM_Switch_Addr. The “Get Selector to Base of LDT” API from the MS-DOS API Extensions document is even part of INT2FAPI.INC as W386_Get_LDT_Base_Sel. DPMI was defined as an interface for protected-mode DOS software to interface with the Windows (and OS/2) DOS Extenders, and ultimately a subset of the Windows DOS Extender API got standardized and duplicated by other vendors; in effect, DPMI hosts implement a genericized version of the Windows DOS Extender.

If you’re interesting in looking at my code and seeing future developments in the disassembly and W386DBG, check it out at https://github.com/BHTY/WIN386.

A modern re-implementation of RCPD (Remote Copy Daemon)

(This is a guest post by Antoni Sawicki aka tenox)

TL;DR
RCPD plays nicely with NAT, re-implemented as a stand alone daemon, from scratch, without ined, r-daemons. Fully open, no security or authentication. Docker friendly.

I often find myself needing to copy a file or two, in or out of an emulated system with some weird networking setup like qemu net user, SLiRP, NAT, etc. Or from/to a physical machine, but having server running in a Docker container, sometimes on a Mac, which has even weirder network contraptions.

Most of the old file transfer protocols like FTP have tendency to open a reverse connection from the server back to the client, which doesn’t play very well with NAT. Even TFTP (who would have thought!) requires nf_conntrack, STUN, proxies, connection helpers, punching holes, UPnP and other nonsense. While they can be individually worked out, it’s rather not universal. Vintage OS SSH/SCP is either non existent or ciphers are too old to play well with modern SSH server. NFS is mostly OK but it has it’s own quirks and you can’t run it in a Docker container. I seen people doing shit like this. I’m also guilty of using Kermit to transfer files over network from time to time. Overall quite frustrating situation.

It turns out that the rcp protocol is very easy on NAT, as it uses just a single, outgoing TCP connection. Not only it worked in all my use cases, but also Berkeley r-commands are ubiquitous on pretty much all vintage OSes that I work with. From Unix, VMS to Windows NT. There are ports to OS/2, DOS and everything else. A recent practical example was how Neozeed and I copied a VBScript in to Windows 2000 64bit install.

The server side however is somewhat of a challenge. It has been obsolete for quite some time now. For starters, R-daemons require inetd, which is mostly not a thing on modern Unix. Then there are actual rshd/rexec/rlogin/rcpd daemons. I spent several hours trying to hack netkit-rsh and rsh-redone to play nicely in Docker, without good results. Even if it could be done, there still are /etc/hosts.equiv, ~/.rhosts and other bullshit “security” contraptions to deal with.

Annoyed with all this nonsense decided to write RCPD from scratch. Docker friendly, fully open, no security or authentication of any kind. I also didn’t want remote shell (rsh/rlogin/rexec), just the file copy part. The original rcpd was using rshd under the hood. This is now completely eliminated and the shell stuff is synthetically generated to satisfy the protocol.

Now if I want to copy a file in to a vintage system I can simply do this:

That’s it. It just worksโ„ข with net user and Docker on a Mac vmnet.

The best part that the whole thing has been written and debugged entirely by Claude!

Available from https://github.com/tenox7/rcpd

WRP 4.8.0 – Simple HTML Mode with Image Support!

(this is a guest post by Antoni Sawicki aka Tenox)

Previously I wrote a boring lengthy article about need for “simple html mode” in WRP. Today I want to introduce addition of images to this contraption! You can now browse modern web like it was in 1994!

The say that image is better than 1000 words, so here we go:

WRP 4.8.0 via Netscape 4.8 on SGI IRIX
WRP 4.8.0 via Mosaic 2.7 on HPUX 9.07

You can regulate the image size and make them however big you want, also PNG, GIF and JPEG of course:

WRP 4.8.0 on HPUX 9.07
WRP 4.8.0 via Netscape 1.0 on SunOS 4.1.4 on QEMU

The simple html mode is still quite buggy and needs a lot of fixes. I see some 400 errors here and there, Captha problems, etc. I think these can be all fixed in time.

You can download latest WRP from Github!

Please report bugs and issues!

Installing older version of QEMU on MacOS using Homebrew

(this is a guest post by Antoni Sawicki aka Tenox)

I often need to install a specific / older version of QEMU on a Mac using Homebrew. If you search for how to do it, typical answers are create a local tap, extract some files and other nonsense. Building from sources is equally retarded because configure can’t easily find includes and libraries installed by Homebrew.

This is how to do it in a simplest possible way. Find QEMU Homebrew Formula file on Github. Then click history on the top right corner. Browse for the desired version. Then on the right of the version, click a little icon saying “View code at this point”. It should show you an older version of the same formula. You can click download raw file or copy the URL and use curl to fetch it. Then simply run brew install ~/Downloads/qemu.rb or wherever you saved it. Magic! Hope it helps!

WRP – Simple HTML / Reader Mode

(this is a guest post by Antoni Sawicki aka Tenox)

TL;DR
WRP now allows rendering web pages in to a simplified HTML, compatible with old browsers (in addition to Image Map).

Netscape 4.x on IRIX 5.3 using WRP 4.7

Long version
WRP or “Web Rendering Proxy” is a proxy server that allows to use vintage web browsers on the modern web. Originally inspired by Opera Mini/Turbo rendering proxy for mobile devices. I wanted a similar service that would translate modern web pages, but in to it’s older HTML version. This not only proved very difficult, but I realized that the web is advancing in a way that it would not be very future proof. I’m talking about dynamic pages, JavaScript generated content and WASM. Instead, I took a different approach – generating a screenshot of a page with clickable Image Map. This allows to faithfully represent a fully rendered web page on a vintage machine + allow to click anywhere on it and perform actions. At a cost of performance. Rendering GIF or JPEG and transferring over network feels rather slow and clunky.

I have been using WRP for some 10 years now. I began to realize that, this approach, while pretty awesome for show and bragging, is not very practical for day to day use. In fact, my use of web browsers on vintage workstations typically revolves around reading documentation, blogs, wikis and other, “mostly text” websites. It would be much better if these were not clunky screenshots but rather some form of text output.

I again started poking around the original idea of simplified HTML. Looked at various reader modes, print to PDF, etc. In particular, I have noticed recent advancements in so called “web scraping”, extraction and html to markdown conversion services. Likely fueled by the recent AI/LLM craze, as robots scrape the web to learn about humans. What caught my attention are various “html to markdown” services. They can fully render dynamic JS pages and extract contents as it was in a browser. Also, Markdown, if you think about it, is in fact a simplified HTML.

After doing some research, in couple of evenings and less that 100 lines of code I got a basic version going. The principle is as follows: First capture the page HTML, convert to Markdown, do some manipulation like adding link prefixes and remove images (we’ll come back to that later). Then render Markdown back to HTML. Wrap it in a vintage HTML header an off we go. The results are amazing!!

This image has an empty alt attribute; its file name is w2-1024x819.png

For the “mostly text” pages this is way better than screenshot mode. Not only is way faster and more responsive, you can select and copy text, but also you use the old web browser more like it was originally intended. At any time, if you want to view the screenshot mode, you can simply switch back to PNG/GIF/JPG mode with couple of clicks.

Another interesting aspect of this is extensibility and potential for improvement. For the screenshot mode there just isn’t that much stuff you could add. It’s just a screenshot. For Markdown and simple HTML there’s a million things one could add. Both down and up converters offer a wide variety of plugins and filters. We can improve formatting, layout, processing, add translation and other features. Perhaps also different features based on client browser version. Maybe even input forms and …images.

Lets talk about images. Right now they are completely deleted from markdown. This is for several reasons, compatibility, performance, load time, size, formatting, etc. I’m thinking that perhaps images could be added in some converted form. For example downsized to a small JPG or maybe converted in to ASCII art. Suggestions more than welcome!

Netscape 3.x on OpenVMS 8.x using WRP 4.7 looking at VSI VMS Documentation!

Download from here: https://github.com/tenox7/wrp/releases/tag/4.7.0

To switch to Reader / Simple HTML mode simply change image type to “TXT”. This can also be done using -t txt flag.

Happy browsing!

In Defense of the Mac Pro 2023

guest post by neozeed‘s nephew

There are a few reasons to get an M2 Mac Pro and although many will say the Studio is a better buy for value: that’s only true if you’re not after these important considerations:

  • The ability to install your own *bootable* SSD: nearly every major Mac reviewer ignored this insanely important feature.
  • The ability to install internal storage (and go beyond 8 TB), period: do we really want a cocktail of external HDDs attached? I don’t!
  • The ability to install an internal USB A licensing dongle: unless you’re sharing your dongle over the network with 3rd party software from an RPi hiding in a closet (you should try VirtualHere if you want cross-platform dongle sharing it’s great), you don’t want to accidentally shear it off costing thousands of dollars of lost licensing.
  • The Magic Keyboard and (black) Magic Mouse are bundled (this is not the case with the Mac Studio or the MacBook Pro adding a substanstial cost. However, since the AppleCare+ is more expensive for the Mac Pro over the Mac Studio you could argue these costs cancel themselves out… unless you’re Icarus with a wax wallet instead of wax wings and never purchase AppleCare+).

Recently ‘GoFetch’ made the headlines, but it’s irrelevant for a variety of reasons in my opinion: 1) you won’t have WAN-exploitable instances of GoFetch in the real world, 2) it does indeed affect some Intel processors and probably others. The way all processors are designed now with speculative execution, CVE-after-CVE is unavoidable so the sensationalization has worn out its appeal. Even the once-ironclad AMD processors are afflicted with a bunch of nasty CVEs now too. \rant

Mac Pro vs PS/2 Model 95

After an eye-watering $8000: refurbished base model with AppleCare+ ๐Ÿคฎ๐Ÿ’ธ๐Ÿ’ธ, we’re greeted with our new friend. The Cheese Grater (2023 Mac Pro) has befriended the Ardent Tool of Capitalism (PS/2 Model 95)! It’s odd how both share silly nicknames and a very similar height sans handles. Both systems symbolize the same sentiment that Louis Ohland shared many years ago: “Think of a business computer being used for purely personal reasons. Fist pump at the man! Isn’t using a corporate tool because you can an expression of free will?”*

*Louis Ohland is the guy who nicknamed the PS/2 Model 95, the Ardent Tool of Capitalism.

Q&A

Q: will I grate cheese on both of them?

A: only if you clean up the cheese residue for me. Are Personal System/2s even food-safe???

Storage

Sonnet M.2 4×4 NVMe PCI-e

The first thing we’ll need to do is install an NVMe PCI-e card. I’m going with the overly-priced “Sonnet M.2 4×4”, because the 2×4 card is nearly the same price making it a horribly valued product and we may as well expand this thing with four NVMes to get our money’s worth. It’s not really clear if the Sonnet M.2 4×4’s controller outperforms the Sonnet M.2 2×4 (they don’t use the same one), but both operate on gen 3 and the NVMes themselves are gen 3 so none of it really matters. There are much cheaper NVMe PCI-e cards but most are not compatible with Macs, you’re paying the tax for the fancy firmware… otherwise buy a much cheaper card if you’re on Windows or Linux. The card only came in a pink ‘static suppressant bag’ instead of a true antistatic bag which is laughable at how much sonnet is charging, and Amazon appears to have taken a bite out of the box.

For the primary boot NVMe we’re going with a 2TB 970 EVO Plus. I know Louis Rossmann decried them as being unreliable after he torched a bunch in some custom gaming rigs with sketchy PSUs, but they’re good drives if you don’t kill them with dirty PSU voltage rails. Always use quality PSUs folks. This is why many Maxtors failed due to the ST SMOOTH chips receiving power from PSUs outputting higher than 12v, and not the drives themselves… same thing applies today when you eclipse 12v on your power rails. I’ve also been running one in a ThinkPad for more than a year and it’s been fine.

For the remaining tertiary storage we’re going with some WD Green SN350s: solely because they’re compatible with macOS — the macOS compatibility with NVMes is very specific unfortunately. Otherwise I would have went with more TeamGroup 4TB drives as they’re one of the best value for money (particularly the TM8FP4004T0C101, it uses better NANDs than the more expensive and inferior 4TB offerings from Crucial and WD). Yeah… the cost of NVMe disks isn’t absolute, sometimes cheaper ones use better NANDs and you can be fleeced by brand recognition and false-positive specs on gen4 which I imagine is what Crucial capitalizes on.

[If you don’t know what I’m talking about: the Crucial and Western Digital NVMe drives always cheap out and use QLC NANDs instead of proper TLC NANDs as TeamGroup and Samsung do; and obviously they’re not going to advertise they’re cheating you and will price their products the same as the competition. Very similar to the whole SMR/CMR debacle, why would Western Digital tell you you’re buying something cheaper at a premium cost??? Caching is an entirely different thing separate to this and usually only the Samsung drives have ‘true’ dedicated cache logic, which is why I’m using the 970 EVO Plus as a boot/OS NVMe]

reinstalling MacOS

Fortunately we don’t need a second mac to perform OS reinstallation so the ‘Apple Configurator’ is not needed. The procedure is as simple as this: Press & hold power button until the recovery menu pops up, choose ‘continue’, choose reinstall OS, choose the new drive (in this case the Samsung drive I just formatted as “OS”). I know a lot of people raise an eyebrow requiring a second mac for when the system does actually need to be completely restored if it can’t boot into the internal recovery mode; just when you haven’t paid Apple enough you also need a second Mac to perform recovery and restoration. Even neozeed himself encountered this problem and with a heavy sigh (a very heavy sigh) and mild disbelief, set up a macOS VM for restoration since he only owns one. ๐Ÿ˜‚

Once this is completed we’ll no longer be using the proprietary SSD that’s present on the Mac Pro. It DOES still need to be present in the system for the computer to POST (Apple marries it against the security IC so it’s intrinsic and serialized to the computer based on configured storage), but presumably as it won’t be written to anymore it’ll never become exhausted from write cycles… and even if it did fail over time, as a result of ordering the bottom-of-the-barrel 1TB model I could just buy another ‘cheap’ 1TB card which would allow the system to resume POSTing once again. If the soldered-in RAM or CPU fails then it’s game over; as much micro-soldering as I do, I refuse to purchase even more tools to swap out underfilled BGA ICs… and then of course you have to hope employees at Foxconn actually managed to sneak out unused genuine ones to be resold on AliExpress or eBay. *sigh*

With us now being able to use our own bootable SSD, the primary failure and annoyance of ARM-based Macs is now mitigated. For the Mac Studio you could buy backup replacement SSDs to constantly replace as they wear out (they would have to match what storage size the system was preconfigured with), but keep in mind I can add 8TB cheaply and have my own bootable SSD. And in the event you need to do data recovery or read the drive on another system, anything — even your grandma’s phonograph — can read NVMes so it’s much less of a hassle. As much as I hate to say it I think the Mac Studio makes less sense over the Mac Pro BECAUSE of the storage… you’re already buying an overpriced computer, may as well go the full distance for proper storage? Everyone’s living in the honeymoon phase right now while all of the NANDs are under warranty and still functioning… but once they start failing it’ll be a nasty money pit at best, or unfixable at worst. And do you know how many people make one computer their whole life and allow it to spontaneously fail with no backups?

ARE YOU NOT ENTERTAINED?

An ARM-based Mac using internal NVMes, is that not a nice thing? ARE YOU NOT ENTERTAINED? And no need to pay ~$2000 for 8TB. I did have to shell out $400 for the stupid SoNNeT card and $400 for the SSDs… buuut if I paid $2000 worth of SSDs I would far eclipse 8TB. In this screenshot you can also see the ‘OS’ Samsung SSD now the primary ‘Startup disk’. Fortunately, Apple’s utility automatically switched it over after I reinstalled the OS to this drive shockingly enough, so nothing more needed even on that.

Internal USB, perfect for Dongles:

Installing the iLok dongle

The iLok licensing dongle installs nicely inside the internal USB A port. Kind of reminds me of those internal VMware USB A ports meant for the ESX installation… and then you know they’d eventually go bad or corrupt themselves and the internal IT of that company never makes a backup so then you need to reconfigure ESX from scratch… good times. What? I’m not salty, not salty at all. The Sonnet NVMe card being installed on the first slot (bottom) does seem to bring more attention to the fact there’s so many unpopulated PCI-e slots.

What should be used as the display option?

1. The Dell UltraSharp U3224KB 6K actually has a few potential compatibility problems with macOS or the hardware (it’s not really well-known as Dell support gave up troubleshooting it), so you’ll get various screen distortions. It’s also possibly one of the most UGLY products I’ve ever seen in my life… the web camera looks like a malignancy, and I absolutely can’t stand silver-painted plastic. Complain about Apple’s prices all you want, at least they use nice materials.

2. The Pro Display XDR is just a little bit too much for my taste and sometimes temperamental as it’s such a complicated display (contrary to popular mythology it does not use OLED technology so it shouldn’t burn out over time). I honestly don’t think I would encounter any problems if I bought a Pro Display XDR but the cost is too much.

It’s Free Real Estate –

3. That basically leaves us with the Studio Display. A lot of the 3rd party Samsung/ASUS/LG 4K or 5K offerings have dramatically inferior colour or a larger pixel size… and there’s still the potential aspect of compatibility since non-Apple hardware sometimes doesn’t play nicely. While the Studio Display is much-maligned with its high cost and strangely attached power plug, its DPI is the same as the Pro Display XDR you just get less screen real-estate and inferior contrast which I don’t care too much about. It will still look much better than your garden variety LG 27โ€ 4K UHD Ultrafine because the colour is calibrated very well and it gets decently bright… again… I wish YouTube reviewers would point some of these things out instead assume that every display is equivalent to Apple’s offerings when they’re not. And in the event, you do find the 5K 27″ displays from other manufacturers they’re still at 60Hz. The refurbished Studio Display I had my eye on from Apple is no longer available, so I’ll be waiting for a bit until they stock another one… or maybe they’ll get a heavily marked down Pro Display XDR…. in the meantime, I’m stuck using one of my gaming monitors which has 240Hz and strobing to reduce ghosting, which does work on macOS!.. and makes macOS look so different since I’m used to how it looks with all of the ghosting all the time.

Another little something that’s rarely discussed: the nano-texture glass option causes a slight ‘frosting’ which is especially noticeable on text… it’s only meant as a compromise if you’re working in a literal sun room, sometimes more expensive does not mean better. This is exemplified with the M2 MacBook Air situation: if you opted for the superior GPU it ended up running more slowly because of the thermal throttling so the lower-end GPU option is more performant, lol. Of course Apple doesn’t always disclose these caveats or finer details, but their divisions responsible for publishing the products may not be privy to them.

Peripherals:

Onto the peripherals: I will indeed be using the Magic Mouse… before your jaw drops and you grab some tomatoes while calling me a heretic, let me explain. The Magic Mouse is one of the few peripherals with velocity sensitive 360ยบ scrolling AND fully integrated in the UI of the operating system. This is extraordinarily similar and analogous to IBM’s ScrollPoint which also offered dynamic 360ยบ scrolling and to a lesser extent the TrackPoint scrolling but which only offers vertical and horizontal. Needless to say 360ยบ scrolling and horizontal scrolling is something I use all the time and cannot fathom why we still even have (notched!) mouse wheels. It’s bizarrely a mouse Apple seemingly designed specifically for me and nobody else, I imagine average or larger hands would be extremely uncomfortable with it and Apple really should offer a larger version to encompass a better demographic.

Men & Mice

The Magic Mouse and ScrollPoint Pro share very similar design philosophies in the way we scroll. I also made another strange discovery when I was looking for some more flat slick mousepads since the Magic Mice don’t work well on cloth ones at all, and that are these 3M ‘Precise’ mouse pads: AMAZON LINK.

Apparently the 3M mouse pads have a reflective material which allows the lasers to use less strength and thus supposedly saves 50% battery life, some Magic Mouse users affirmed this, so we’ll see how this goes down. It’s kind of surprising I’ve never heard of any tech reviewers mention these because saving 50% of battery life on a wireless mouse is huge.

Keyboards..

There’s a lot of good reasons to NOT use Bluetooth keyboards due to wireless keylogging, there’s not going to be anyone with that talent in rural Canada so I’m in the clear. You could buy a Matias keyboard but they’re actually worse in many aspects than the 1st party Apple keyboards: the legend printing is of dramatically worse quality, the surface of the keycaps don’t have that special velvety texture, and the snappiness of the scissor switches is probably worse. While I have many mechanical keyboards, I don’t care so much about it anymore. The Apple Magic Keyboard is just a little bit too flat for my tastes today so I ordered a “ESC Flip PRO Computer Keyboard Stand”, which can stick on the back and give you different height adjustments if needed.

onboard LEDs everywhere.

Both the iLok and Sonnet NVMe card have so many LEDs on them you can see the lightshow through the rear of the ‘grater’ now.

Now my plans are to use this thing for at least a decade to get my money’s worth: will 64GB of RAM be enough? To that I say: 64GB ought to be enough for anybody. The only major hindrance will be the forced software obsolescence when the Apple overlords declare it will not be receiving anymore updates… and then you know things like the Roland Cloud and other major vendor software will cease to get updates and functionally work. It’s appalling at how all software is heavily DRMed and requires a live account to work against. At the very least when WWIII breaks out I’ll have plenty of premium aluminum to donate to the state, forged by Tim Apple himself!

For the record I was never really an ‘Apple person’, but they’ve finally fixed all of the problems (mice have two buttons and the keyboard layout is restored to be more IBM-like) and made a product that fulfills everything I’ve ever wanted… AND forced developers to program for ARM: so now my Stallman-not-approved-absolutely-proprietary audio software runs incredibly well on a non-x86 platform. Astounding. Yeah there were some 3rd party mice that had two buttons for Macs ‘back in the day’ but a good portion of the *software* and games weren’t programmed for a real right click rendering it useless. I remember watching a ‘making-of’ video of the Myst developers pushing down Ctrl with the mouse to right click EVERY SINGLE TIME in their 3D modelling software and nearly fell off my chair… it’s quite jarring when you need to press a button on the keyboard at the same time with clicking the mouse so I’ve no idea how they tolerated that. Maybe they loved doing it? Who knows.

It’s crazy how much changes, and how much is the same

[PC-98] How an obscure fighting game for Japanese PCs can ruin your day

This is a guest post from spaztron64

Sometime in June 2023, I came across aย Twitter postย byย kuma_neko24ย where he detailed his struggles in getting Policenauts to work on his PC-9821 V166. As I own the exact same machine, I figured I should give it a shot myself and report the results.
Unfortunately, while I was experimenting, I had hit a strange situation where certain executable files would randomly corrupt themselves and become unusable:

I figured the game might’ve been the culprit, but after restoring the most recent backup, the same thing happened not long after, without even trying to play the game. I’ve done Memtests of the SDRAM, as well as block level diagnosis of the CF card, and they were fine, so I attributed it to a corrupt filesystem.

I then restored a much older backup, and moved over all the known good files from the recent backup. Things seemed fine for a while, but then the exact same situation happened again. I decided to look into the issue in more detail, and I’ve noticed that affected files like WIN.COM and KRNL386.EXE were 3KB larger…. as we’ll see later, this should’ve been an immediate red flag, but I yet again brushed it off as a bad filesystem or CF card.

Fast forward to March 2024, and I got myself a set of new CompactFlash cards. I had once again restored the last known good backup, and for about a day everything seemed alright, until….

Needless to say, all my previous hypotheses turned out to be wrong. As such, I investigated yet again into the corrupted files, and used windiff to take a closer look into what actually changed. Let’s take a look at WIN.COM, SCANREG.EXE and KRNL386.EXE:

We can observe the following pattern:

  1. The files always grow in size
  2. windiff shows that the header is modified and that a bunch of garbage is added at EOF
  3. It’s always the same exact garbage
  4. Additional examinations show that MEM.EXE also has these modifications
  5. MZ headers are present, so it’s certainly executable code

By every metric, this isn’t a set of accidental corruptions, these are deliberate infections.

I then proceeded to take a sample of the suspiciously added code, did a byte scan of every file on the card, and isolated the following programs as infected:

  • A:\WINDOWS\WIN.COM
  • A:\WINDOWS\COMMAND\MEM.EXE
  • A:\WINDOWS\COMMAND\SCANREG.EXE
  • A:\WINDOWS\SYSTEM\KRNL386.EXE
  • B:\RECYCLED\DB51.EXE
  • B:\WIN31\WIN.COM
  • B:\WIN31\SYSTEM\DOSX.EXE
  • B:\SBVGM\VGMPlay.exe
  • B:\GAMES\FIGHTING\DGA\DGP.EXE

Most of these are self-explanatory, apart from the last two.
VGMPlay is a program by Scali that allows playback of OPN(A) and OPL3 VGM files even on PC-98s without a SoundBlaster 16/98. I know this program is not the culprit, since the original program I got is clean.
DGP, on the other hand, is a different story, and it needs a bit of a foreword.


Duelists and queens!

DGP is a shorthand for “Duelist Gaiden Plus”, which refers to the game “Queen of Duelist Gaiden Alpha Plus”.

The original Queen of Duelist is a rubbish game not worth anybody’s time or any further mentions.
Queen of Duelist Gaiden Alpha is the 1994 sequel, which is a significantly better game, and arguably one of the best fighters for any personal computer at the time, featuring:

  • 10 fully voiced characters
  • Adjustable game speed
  • Dual PWM sampling over the integrated PC beeper speaker
  • Decent performance on a 286, and more

At the end of 1994, Agumix released an upgrade for the game called “Queen of Duelist Gaiden Alpha+”, which introduces some quality of life improvements. This update requires the original Gaiden Alpha to already be installed, although it doesn’t do any differential patching, it just replaces existing files with newer variants, and adds the DGP.EXE executable to be used instead of DGA.EXE. Shockingly, all of my older backups containing the patch, as well as the dump of the disk itself (available on Neo Kobe PC-9801) contain the suspicious code.

I didn’t expect it to return any results at first, but I uploaded DGP.EXE to VirusTotal for scanning, and well…

Who would’ve thought, the update was distributed with a copy of the Yankee Doodle virus embedded within!

Yankee Doodle is a very simple COM and EXE self-injecting virus from 1989. When executed, it resides in memory and infects COM and EXE files that use certain INT 21h DOS API calls, which include the files in the above list. It’s payload is normally supposed to play the Yankee Doodle tune through the PC speaker at 17h every day, but on PC-98 what it does instead is catastrophically fail and crash the entire system. It’s infection routines, however, do work.

A thing worth pointing out is that the infection routine is not automated. It will only engage when executing other programs from DOS manually. This should never be possible after starting the game, since there’s no way to return to the DOS command line without a full system reboot…

… unless you tried to start the game with not enough free memory, after which the game will dump you back to DOS. Pretty much every DOS user would, in situations like this, start MEM (preferrably with the /C and /P flags) to check what uses so much memory and how little remains free.

Sadly, for us, Yankee Doodle remains memory resident in this case, and it infects MEM as soon as it’s run, which explains how it got infected. Now every time you check your memory, the virus will be waiting to spread further.


Well, now what?

No known clean copy of the Plus version is known to be in circulation, and the only available source currently is the compromised disk image on Neo Kobe.
Additionally, nobody knows if the game was originally distributed with the infection, or if the person sharing a dump of the game around through P2P back in the 1990s had infected his copy.
As such, unless an original physical copy is found on auction, dumped, and confirmed clean, the only solution is to patch out the infectious payload from the game. Until then, do not play Queen of Duelist Gaiden Alpha Plus on your PC-98 machine!

EDIT 2024-03-31:
Fortunately it appears that the “Alt 1” dump available on Neo Kobe has a clean copy of DGP.EXE.
DrNyquist has also confirmed that this torrent also has a clean dump.

Conclusion: steer clear of the primary dump on Neo Kobe, use the others mentioned above.