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

Building MS-DOS 4.00 under OS/2 2.x

Building & Booting DOS on OS/2!

Now that we’ve moved beyond the initial shockwave of the MS-DOS 4.00 source code dump, I thought it was time to try to pull off the ultimate trick of the time, building under OS/2 and using the exciting feature of the time “DOS from Drive A:” Long before VMware / Virtual PC for the PC OS/2 took Intel’s 80386’s hardware virtualization mode, “v86 mode” to the logical conclusion allowing you to boot native MS-DOS under OS/2. Sadly, the old 1989-1991 OS/2 betas do not include this feature. Although I have to wonder if it did exist and just wasn’t publicly available.

Many of the programs used to build MS-DOS are off the shelf, the MASM assembler, Microsoft C 5.1, and its associated tools are just retail versions. To change things up, I did use the 386MASM assembler just to see if it maintained MASM 5.1 compatibility. And it does. The only gotcha is that all the tools are *NOT* marked Presentation Manager compatible, so launching them from a window opens a full screen session. Very annoying!

exehdr

I’m guessing the fix is in a toolkit? Either way, in Microsoft C 6.0, the utility exehdr lets us modify an OS/2 executable so it’ll now be WINDOWCOMPAT. So at least it ‘feels’ better now.

One thing is for sure, building DOS under OS/2 is a lot more enjoyable than doing a native build as you can minimize the build task, although the MS-DOS only programs do pop up when it generates text indexes & tables. But you do retain some control of your machine during the build, which is great! Although E is a terrible editor for source code, and the one in 6.78 has a nasty bug where it’ll truncate large files. Were people really using text mode editors for everything back then? I guess i like the fonts of the GUI, despite having used machines of the era.

Otherwise, the end result is the same, you get a build of DOS 4.

I went ahead and tried to build using 6.78 and no doubt compiling DOS is an absolute torture test. So far, the DOS Box has locked OS/2 once, and PM Shell has crashed once as well.

I altered the Makefiles to use ‘rm’ instead of the built in ‘del’ command, because if you try to delete a file that doesn’t exist, del returns an error, which then triggers an end to the NMAKE process. Very annoying! However, the ‘rm’ included in Microsoft C 5.1 doesn’t suffer the same defect. Using 86Box with an 83Mhz Pentium OverDrive it took about 18 minutes to build DOS-4.

Building DOS 4 on OS/2 6.78

I did capture the video and converted it to a GIF so you can quickly see the reboot & the UI crashing. FUN!

Compiled under OS/2

And it even boots!

For anyone interested I’ve put zips on archive.org that can be extracted under OS/2. I also made a pkzip disk set incase loading a 6MB zip file is an issue.

Building MS-DOS 4.00 under OS/2 2.x : neozeede : Free Download, Borrow, and Streaming : Internet Archive

Compiling MS-DOS 4.0 from DOS 4.0, on a PS/2!

have patience. It does work. Even booting from the SPOCK SCSI CARD which all the other DOS4 images all failed.

The best way for a native build is the zip in the releases.

Release Now can boot from hard disk! · neozeed/dos400 (github.com)

With a 16Mhz 80386 it took 70 minutes. I just formatted a blank image on the gotek, copied IO.SYS, MSDOS.SYS and COMMAND.COM, then rebooted. went back to the compiled DOS 4, and re-formatted the floppy as a system disk so the attributes are set. (DOS 5 lets you change system files), and yeah. It can be done!

Let me spell out the steps, in this case I’m going to use Windows 10. I use the git from the WSL (Windows subsystem for Linux) I have DOSBox mount c:\dos as my c: drive . ZIP/UNZIP are Info-ZIP versions, you MUST have the Win32 native version!

- md \dos
- md \dos\temp
- wsl git clone https://github.com/microsoft/MS-DOS
- cd MS-DOS\v4.0
- zip -r \dos\temp\src.zip src\*.*
- cd \dos
- unzip -a -LL temp\src.zip
- start dosbox
- cd \src
- edit setenv.bat to reflect the paths:
  set BAKROOT=c:
  set LIB=%BAKROOT%\src\tools\bld\lib
  set INCLUDE=%BAKROOT%\src\tools\bld\inc
  set PATH=%PATH%;%BAKROOT%\src\tools
- setenv
- nmake
it will then fail in mapper on getmsg.asm change the 3 chars to a '-'
- nmake
- cd ..
- nmake

It will then fail building select

- edit select2.asm
- edit usa.inf
- nmake
- cd ..
- nmake

and now it’ll be done compiling.

continuing from dosbox, you need a 1.44mb fat formatted disk image somedos144.img . I used a dos 6.22 diskette, it needs the bootsector already in place to load io.sys/msdos.sys

- cd \src
- md bin
- cpy bin
- imgmount a somedos144.img -t floppy
- a:
- del *.*
- copy c:\src\bin\io.sys
- copy c:\src\bin\msdos.sys
- copy c:\src\bin\http://command.com
- boot -l a:

And now I’ve booted MS-DOS 4.00 from within DOBOX!

Also as interest to most people there is a bug in msload.asm, where DOS 4.0 won’t boot on a lot of machines, from VMware, Qemu and even my PS/2. It’s a small fix to the IO.SYS initial stack being too small. Props to Michal Necasek for the fix!

For further guidance here is a video spelling it all out:

MZ is back, baby! – Source to MS-DOS 4.0 / European DOS / Multi-tasking DOS drivers released!

MZ is back!

I’ts MS-DOS 4.0 Internal Work #2.06 – May 23, 1984, with copyrights from both IBM & Microsoft.

I don’t have time to make any comment much further other than having had been listing to people in on making this happen, and it’s been a long struggle to make this all happen, and it’s so amazing to see their hard work make it out into the wild!

DOS 4 is the basis of what would eventually become OS/2, just as I’m sure that it’s use of NE executables will reveal a far tighter integration with Windows, giving hints of the future that should have been!

Hopefully, like the LINK4 support I had stumbled onto a while back, we can build more robust applications!

Scott Hanselman

** EDIT So it’s just DOS 4.00, with a lot of information on EU/MT DOS4. There is now a blog post over on Scott Hanselman – Scott Hanselman’s Blog‘s talking about the details of this release!

Credit goes to starfrost, this was nearly a year in the works!

*** EDIT it’s now live over on cloudblogs.microsoft.com, Open sourcing MS-DOS 4.0

Ive been able to bulid it from source, and I put up the changes on github (really minor changes)

neozeed/dos400: Microsoft DOS 4.00 (github.com)

Rebuilding Darwin from source: Part 3 Debian makes the world go ’round

In the previous posts, we’ve gone through the excruciating fun of installing Rhapsody DR2, and of course built the Rhapsody kernel from source. But now it’s time to build the software that can build software.

Enter the apt*

Of course we can’t just start building apt, rather we need to start at the 1990’s super star scripting language that revolutionized massive, shared code libraries, accelerating web development, and building the modern web, of course I’m talking about PERL.

Even back in the original effort building Perl was a slog. Even with temporary wins with miniperl it quickly fell apart from missing symbols. When it comes to the system libraries Darwin is not complete, rather it’s a lot of amputations from OPENSTEP. Which of course, itself was amputated from NeXTSTEP. I’m not sure what held back NeXTSTEP from being ‘open’ back when ‘open’ meant published specifications, not open source, or open in any other sense of the way, like The Open Group being a gatekeeping organization that is NOT open at all.

Anyways, Perl from the Darwin 0.1 downloads & the 0.3 CD-ROM don’t build. I gave up and moved to the OS X Server version and that one did build! As much as I could diff them out and find the breaking difference, honestly, it’s just easier to stick with what works.

/pub/Darwin/PublicSource/Darwin

I should point out that the source to Darwin was preserved on this now defunct site “next.68k.org”, which in turn was also preserved on the defunct site “nextftp.onionmixer.net“. Amazing how mirrors go. Other fun things on the ftp site include MacOSX-Server public sources, which did include the Perl that we built.

Darwin 0.3

Darwin 0.3 however was pressed onto CD-ROM, and distributed out to the masses. It took me a short while to get a tip to a hidden server that had a copy, which really was a massive breakthrough as it had a far more complete set of files than the 0.1 ftp dump. However at the same time there are files in the 0.1 dump that are not in the 0.3. Was there ever a 0.2? I have no idea, the mailing lists don’t seem to have been preserved so I really don’t know. Does anyone have any other ftp site archives? Not to my knowledge but I’d be more than happy to be wrong.

With a working Perl the next thing to do is to patch the buildtools & dpkg to not be PowerPC centric. It’s no secret that all the official effort going on was to get OpenSTEP up and running on Apple PowerPC’s and to transition away from OPENSTEP to Rhapsody, the MacOS 8 Platinum feeling type OS, where everyone was going to love the ‘Coca’ API, and dump the old MacOS stuff or be forced to run it in the ‘BlueBox’ MacOS 8 emulator. Obviously this future didn’t happen as developers were not interested in rewriting for Steve’s decade+ fever dream of a Unix for the ‘rest of us’, instead they wanted their existing software to ‘just work’ and the Carbon API had to be created, along with a drastically different and modern looking OS X.

-    $flags->{'RC_CFLAGS'} = '-arch i386 -arch ppc ' . &liststring (@cflags);
-    $flags->{'RC_ARCHS'} = 'i386 ppc';
+    $flags->{'RC_CFLAGS'} = '-arch i386 ' . &liststring (@cflags);
+    $flags->{'RC_ARCHS'} = 'i386';

Frequently in the build tools it’s a matter of looking for ppc/powerpc and replacing them with i386. It’s really no surprise that Darwin always built on intel, and it had to, as it’s life depended on it. Back when NeXT hit their first real big stumbling blocks of being a vertical platform is that they just couldn’t compete in the hardware space. But dumping the 68k based black boxes, they could now take their software and port it to the much more coveted RISC platforms, and shipping with NeXTSTEP 3.3 they supported both SPARC & HPPA. There had always been talks of further platforms like MIPS or DEC Alpha, but these never materialized, much like the i860 which had been relegated to a simple Postscript co-processor.

Anyways.. Keeping with yesterday’s setup, and of course the .darwin-builder-04-23-2024.iso CD-ROM with all the stuff we need, let’s DOIT!

phase 2 completed

With phase 3 completed we are now ready to build the rest of the system. I hope you are excited! As I’m sure hoping you kept the original disk layout from the prior setup, or I’ve totally trashed your system by now.

I should say that deb files are just specially tagged ‘ar’ archives, that contain a data & control files telling apt how to process them. In this case I’ve taken the cc_783.1-1_i386-apple-darwin.deb file and modified it to contain the OS X 10.0 modified CC compiler. Apt had stumbled on building it, and I’m not interested into troubleshooting why or how. Basically, use ar to extract the contents of the deb, then tar to expand the data, replace the files, tar to put the files back into the data tar file, and ar to rebuild the archive.

ar r cc_783.1-1_i386-apple-darwin.deb debian-binary control.tar.gz data.tar.gz

In this case, debian-binary is a text file that simply contains ‘2.0’. Amazing!

The first thing to do is build a manifest of what needs to be built. I just simply extract all the ‘fixed’ source that I’d used last time to build Darwin, apply patches were needed, and then kick off the process with a darwin-buildall.

ls -l | awk '{print "dir /usr/src/"$9 " all"}' | tail -n +2 | grep -v gdb |grep -v cc- > /tmp/manifest.txt

In this case I skip building the C compiler, as it takes too long, and I’ve already done it. If you really want to do it, you can do so at your own leisure. GDB has issues building, and I haven’t even begun to tackle them. As you can guess the format of the manifest is pretty simple:

dir /usr/src/CoreOSMakefiles-1/ all
dir /usr/src/Csu-1/ all
dir /usr/src/Libc-1/ all
dir /usr/src/LibcAT-1/ all

Debian uses deb’s to populate a fake root directory in order to cross compile the packages. This is like installing multiple copies of the operating system, and that is why we use a separate scratch disk. This can consume several gigabytes when it’s done.

Also this presented the chicken/egg problem with how do you make debs from a system that needs debs? Thankfully NCommander had done extensive work with Debian / Canonical and was able to fake enough of a ‘build-base’ fakery that satisfied the build system just enough to start building stuff. In this weird way all roads lead back to the first build-base. Thankfully we live in the future where VMs are fast, and virtual disks are cheap.

I then create the /built directory, where the compiled deb’s will be populated, and copy in my modified compiler Debian into the built directory so that it’s used in all the compiling. On the CD-ROM I have 2 selections of deb files, the ‘deb’ directory from when I’d originally done this back in 2017, and the ‘fresh’ directory that I’ve just built. You can always manually source where the debs some come.

Kicking off the build is as simple as running:

darwin-buildall /tmp/manifest.txt /source/fresh /built

This will take.. a while. It’s a lot of files to copy & expand, and compiling takes a fair bit of a toll on the olde CPU.

By default, 118 of the 127 can be built.

  • boot-2 the sarld won’t compile as.. there is nothing to compile. I’m lost. Also some driverkit headers didn’t make it into the packe!
  • cvs-1 is upset about bison grammar not being in usr local lib?!
  • flex is also upset about bison grammar locations.
  • libgpp ppc/ppc-nextstep/_G_config.h missing?!
  • perl.. should be patched __environ vs _environ
  • bootstrap-cmds “multiple definitions of symbol _migcom_untypd_VERS_STRING”
  • volfs seems plain broken but subdirecotories okay?
  • netinfo missing netinfo.defs and headers?! arpa/nameser.h missing (can just touch)

That just leaves AppleTalk & HFS not building. Which I believe is period correct.

The good news is that the kernel that was built boots up seemingly fine.

Rhapsody Kernel 5.5

The NeXTSTEP, of course is to now setup a new disk image, and see what is involved in booting up!

Rebuilding Darwin from source: Part 2 Building the kernel

Re-creating the steps from 7 years ago the first phase was to build the Darwin kernel. Like everything else, once you know what is involved, it’s not all that difficult. But as always finding out the steps to get there is half the fun!

I’m going to assume if you want to follow along, that you’ve completed the first part of this exercise, and you have a Rhapsody DR 2 system up and running. Due to some issues I’ve had with creating a lot of files & filesystem corruption, we are going to create and add two more disks to the system. On Qemu we need to add them via the CLI:

qemu-img create -f vmdk source.vmdk 8G
qemu-img create -f vmdk scratch.vmdk 8G

Adding them to the command line gives us something like this:

qemu -L pc-bios -m 512 ^
-k en-us ^
-rhapsodymouse ^
-hda rhapsody.vmdk ^
-hdb source.vmdk ^
-hdd scratch.vmdk ^
-cdrom darwin-builder-04-23-2024.iso ^
-fda nic.flp ^
-net nic,model=ne2k_pci,vlan=1 ^
-net socket,udp=127.0.0.1:5001,remote=127.0.0.1:5000,vlan=1 ^
-boot c ^
%1 %2 %3 %4 %5 %6 %7

Additionally you’ll also need to download the current ‘darwin builder’ ISO that I’ve put up on sourceforge. As of today it is darwin-builder-04-23-2024.iso

Step one is to boot into single user mode. As we need to prep & format the disks under Darwin before the system starts up.

We need to check the hard disk, and then create the device names for the third hard disk.

fsck -y /dev/rhd0a
mount -w /
cd /dev
./MAKEDEV hd2

Now we need to run the ‘disk’ command which will abstract the whole volume creation. There are numerous flags, but we don’t need all that many.

disk -i -l 'src' /dev/rhd1a
disk -i -l 'scratch' /dev/rhd2a

The output scrolls off the screen, so I didn’t capture it, but you’ll see all the inodes being created, it’s a lot of output!

With the disks created, we can now shut down the VM

shutdown -h now

and then restart Qemu, and let it boot up normally. We’ll get to the login screen, login as the root user.

The first thing I’d recommend is to drag the Terminal.app from /System/Administration to the desktop to make it easier to get to. Rhapsody, unlike NeXTSTEP & OPENSTEP doesn’t have any dock, as the goal back then was to make Rhapsody look and feel more like Platinum MacOS.

The next thing to do is to make the system very insecure by allowing remote root logins. It’s just easier to deal with. You could use sed or just copy the one I provided from the CD-ROM.

cp /source/ttys /etc

And with that in place, its easy enough to telnet into the VM so you can copy/paste stuff in and out with ease!

You should now be able to verify that all 3 disks are mounted:

# mount | grep hd.a
/dev/hd0a on / (local)
/dev/hd1a on /src (local)
/dev/hd2a on /scratch (local)

From here it should be very simple to kick off the build process:

/source/phase1.sh

And this will kick off the build, recreating all the fun steps I’d gone through so many years ago. These projects now are building in the following order:

  • kernel-1
  • driverkit-139.1-1
  • cc-798
  • bootstrap_cmds-1
  • objc-1

The first phase of the script will unpack both the kernel & driverkit and install their respective header files into the OS. NeXT a bunch of symlinks are created to link the system to the driverkit. Next I decided to build the ObjectiveC compiler from 10.0, hoping it’s more bugfixed and slightly more optimized than what was available back in 1999. Building the compiler is a little involved, as a good GCC tradition is to be cross compiled first, then re-compile itself with itself, then do that again and verify that the 3rd recompile outputs the same as the second one. Yes it’s a thing. Yes it’s slow. Yes you are lucky to live in the future, this was really painful back in the day.

With the kernel compiled, we can then compile the bootstrap commands, and the objectiveC runtime that is used by the kernel. Nothing too exciting here.

DriverKit however….

The PCMCIA code was not included in any of the 0.x Darwins, so for laptop enthusiasts you are basically SOL. As a matter of fact, a lot of weird stuff was pruned out, that either could be ‘touched’ or borrowed from the PowerPC port and massaged into place. Luckily I had at least figured out a simple fix for PCIKernBus.h so at least PCI works.

Likewise for the kernel, there was some guessing on the EISA config, which also overlaps ISA, along with having to remove the PCMCIA cardbus .. bus.

APM crash

I had issues with the APM (Advanced Power Management), another laptopisim I suspect. I had to amputate that.

for testing purposes

Naturally the cpuid code is broken much like early NT (I wonder if both were contributed by intel?), so it doesn’t detect any half way modern Pentium processors correctly which causes it to fall all the way back to the i386, which unfortunately, Rhapsody is compiled as 486 (remember NeXTSTEP had fat binaries allowing you to recompile for different processors and ship a single binary that can be ‘lipo’d into the appropriate one for the host). So being degraded to a 386 means nothing works.

bad CPU type in library!

yay.

Luckily patching the cpuid was pretty simple just force it always to be a Pentium. It is 1999 afterall.

I’ve done my best to make this a single script to run, and all being well you’ll get something that looks like errors, but it should be fine?!

System/Library/Frameworks/System.framework/Versions/B/Headers/bsd/i386/table.h
System/Library/Frameworks/System.framework/Versions/B/Headers/bsd/i386/types.h
System/Library/Frameworks/System.framework/Versions/B/Headers/bsd/i386/user.h
System/Library/Frameworks/System.framework/Versions/B/Headers/bsd/i386/vmparam.h
private/
private/dev/
private/dev/MAKEDEV
private/tftpboot/
private/tftpboot/mach_kernel
mach_kernel
tar: private/dev: Could not change access and modification times: Permission denied
tar: private/dev: Cannot change mode to 0755: Permission denied
tar: private/dev: Cannot chown to uid 0 gid 0: Permission denied
tar: Error exit delayed from previous errors

A quick look around shows that there is tgz files indicating that things have been compiled. I did backup the old original kernel as “rhapsody-gcc.tgz” in case you ever need it. Can’t imagine why but who knows?

qemu:13# ls -l /usr/src/*.tgz
-rw-r--r--  1 root  wheel   173706 Apr 23 15:25 /usr/src/bootstrap_cmds.bin.tgz
-rw-r--r--  1 root  wheel  2184460 Apr 23 15:33 /usr/src/cc-798-bin.tgz
-rw-r--r--  1 root  wheel  2747289 Apr 23 15:36 /usr/src/driverkit-kern-bin.tgz
-rw-r--r--  1 root  wheel  1264957 Apr 23 15:26 /usr/src/kernel-driverkit-hdrs.tgz
-rw-r--r--  1 root  wheel   116343 Apr 23 15:26 /usr/src/objc-bin.tgz
-rw-r--r--  1 root  wheel  2173005 Apr 23 15:26 /usr/src/rhapsody-gcc.tgz
qemu:14# ls -l /mach_kernel*
-r--r--r--  2 root  wheel  1459520 Apr 23 15:36 /mach_kernel
-r--r--r--  1 root  wheel  1404116 Apr 23 15:38 /mach_kernel-rhapsody

You should now be able to reboot into the kernel that you’d compiled!

Next up is Phase 2, where we compile the tools to enter the dark magic that is the Debian build system. Yes, you read that right, Apple/NeXT was all in on Debian.

Porting Sarien to OS/2 Presentation Manager

Originally with all the buildup of compilers & GCC ports to OS/2, I had a small goal of getting Sarien running on OS/2. I did have it running on both a 286 & 386 DOS Extender, so the code should work fine, right?

To recap, years ago I had done a QuakeWorld port to OS/2 using the full screen VIO mode, a legacy hangover from 16bit OS/2. It works GREAT on the released 2.00 GA version. I went through the motion of getting the thunking from 32bit mode to 16bit mode, to find out that it doesn’t exist in the betas!

No VIO for you!
No VIO access from 32bit

So that meant I was going to have to break down and do something with Presentation Manager.

So the first thing I needed was a program I could basically uplift into what I needed, and I found it through FastGPI.

Donald Graft’s FastGPI

While it was originally built with GCC, I had rebuilt it using Visual C++ 2003 for the math, and the Windows NT 1991 compiler for the front-end. As you can see it works just fine. While I’m not a graphical programmer by any stretch, the source did have some promise in that it creates a bitmap in memory, alters it a runtime, and blits (fast binary copy) it to the Display window. Just what I need!

  for (y = 0; y < NUM_MASSES_Y; y++)
  {
    for (x = 0; x < NUM_MASSES_X; x++)
    {
      disp_val = ((int) current[x][y] + 16);
      if (disp_val > 32) disp_val = 32;
      else if (disp_val < 0) disp_val = 0;
      Bitmap[y*NUM_MASSES_X+x] = RGBmap[disp_val];
    }
  }

It goes through the X/Y coordinate plane of the calculated values, and stores them as an RGB mapping into the bitmap. Seems simple enough right?

  DosRequestMutexSem(hmtxLock, SEM_INDEFINITE_WAIT);

  /* This is the key to the speed. Instead of doing a GPI call to set the
     color and a GPI call to set the pixel for EACH pixel, we get by
     with only two GPI calls. */
  GpiSetBitmapBits(hpsMemory, 0L, (LONG) (NUM_MASSES_Y-2), &Bitmap[0], pbmi);
  GpiBitBlt(hps, hpsMemory, 3L, aptl, ROP_SRCCOPY, BBO_AND);

  DosReleaseMutexSem(hmtxLock);

It then locks the screen memory, and then sets up the copy & uses the magical GpiBitBlt to copy it to the video memory, then releases the lock. This all looks like something I can totally use!

I then have it call the old ‘main’ procedure form Sarien as a thread, and have it source the image from the Sarien temporary screen buffer

disp_val = ((int) screen_buffer[y*NUM_MASSES_X+x] );

Which all looks simple enough!

Y/X instead of X/Y!

And WOW it did something! I of course, have no keyboard, so can’t hit enter, and I screwed up the coordinates. I turned off the keyboard read, flipped the X/Y and was greeted with this!

Welcome to OS/2 where the memory is the total opposite of what you expect.

And it’s backwards. And upside down. But it clearly is rendering into FastGPI’s gray palette! I have to admit I was really shocked it was running! At this point there is no timer, so it runs at full speed (I’m using Qemu 0.80 which is very fast) and even if there was keyboard input it’d be totally unplayable in this reversed/reversed state.

The first thing to do is to flip the display. I tried messing with how the bitmap was stored, but it had no effect. Instead, I had to think about how to draw it backwards in RAM.

  {
    for (x = 0; x < NUM_MASSES_X; x++)
    {
      disp_val = ((int) screen_buffer[y*NUM_MASSES_X+x] );	//+ 16);
      if (disp_val > 32) disp_val = 32;
      else if (disp_val < 0) disp_val = 0;
      Bitmap[((NUM_MASSES_Y-y)*(NUM_MASSES_X))-(NUM_MASSES_X-x)] = RGBmap[disp_val];
    }
  }
Running in the correct orientation

Now comes the next fun part, colour.

I had made the decision that since I want to target as many of the OS/2 2.0 betas as possible they will be running at best in 16 colour mode, so I’ll stick to the CGA 4 colour modes. So the first thing I need is to find out what the RGB values CGA can display.

This handy image is from the The 8-Bit Guy’s video “CGA Graphics – Not as bad as you thought!” but here are the four possible sets:

All the possible CGA choices

And of course I got super lucky with finding this image:

So now I could just manually populate the OS/2 palette with the appropriate CGA mapping, just like how it worked in MS-DOS:

First define the colours:

#define CGA_00 0x000000
#define CGA_01 0x0000AA
#define CGA_02 0x00AA00
#define CGA_03 0x00AAAA
#define CGA_04 0xAA0000
#define CGA_05 0xAA00AA
#define CGA_06 0xAA5500
#define CGA_07 0xAAAAAA
#define CGA_08 0x555555
#define CGA_09 0x5555FF
#define CGA_10 0x55FF55
#define CGA_11 0x55FFFF
#define CGA_12 0xFF5555
#define CGA_13 0xFF55FF
#define CGA_14 0xFFFF55
#define CGA_15 0xFFFFFF

Then map the 16 colours onto the CGA 4 colours:

OS2palette[0]=CGA_00;
OS2palette[1]=CGA_11;
OS2palette[2]=CGA_11;
OS2palette[3]=CGA_11;
OS2palette[4]=CGA_13;
OS2palette[5]=CGA_13;
OS2palette[6]=CGA_13;
OS2palette[7]=CGA_15;
OS2palette[8]=CGA_00;
OS2palette[9]=CGA_11;
OS2palette[10]=CGA_11;
OS2palette[11]=CGA_11;
OS2palette[12]=CGA_13;
OS2palette[13]=CGA_13;
OS2palette[14]=CGA_13;
OS2palette[15]=CGA_15;
CGA on PM!

So now it’s looking right but there is no timer so on modern machines via emulation it runs at warp speed. And that’s where OS/2 shows its origins is that it’s timer ticks about every 32ms, so having a high resolution timer is basically out of the question. There may have been options later one, but those most definitively will not be an option for early betas. I thought I could do a simple thread that counts and sleeps, as hooking events and alarms again suffer from the 32ms tick resolution problem so maybe a sleeping thread is good enough.

static void Timer(){
for(;;){
	DosSleep(20);
	clock_ticks++;
	}
}

And it crashed. Turns out that I wasn’t doing the threads correctly and was blowing their stack. And somehow the linker definition file from FastGPI kept sneaking back in, lowering the stack as well.

Eventually I got it sorted out.

The next big challenge came of course from the keyboard. And I really struggled here as finding solid documentation on how to do this is not easy to come by. Both Bing/google want to suggest articles about OS/2 and why it failed (hint it’s the PS/2 model 60), but nothing much on actually being useful about it.

Eventually through a lot of trial and error, well a lot of errors I had worked uppon this:

    case WM_CHAR:
      if (SHORT1FROMMP(parm1) & KC_KEYUP)
        break;
pm_keypress=1;
      switch (SHORT1FROMMP(parm1))
      {
      	case VK_LEFT:
	key_from=KEY_LEFT;
	break;
	case VK_RIGHT:
	key_from=KEY_RIGHT;
	break;
	case VK_UP:
	key_from=KEY_UP;
	break;
	case VK_DOWN:
	key_from=KEY_DOWN;
	break;

	case KC_VIRTUALKEY:
	default:
	key_from=SHORT1FROMMP(parm2);
	break;
      } 

I had cheated and just introduced 2 new variables, key_from, pm_keypress to signal a key had been pressed and which key it was. I had issues mapping certain keys so it was easier to just manually map the VK_ mapping from OS/2 into the KEY_ for Sarien. So it triggers only on single key down events, and handles only one at a time. So for fast typers this sucks, but I didn’t want to introduce more mutexes, more locking and queues or DIY circular buffers. I’m at the KISS stage still.

I’m not sure why it was dropping letters, I would hit ‘d’ all I wanted and it never showed up. I then recompiled the entire thing and with the arrow keys now mapped I could actually move!

Roger walks for the first time!

And just like that, Roger Wilco now walks.

From there I added the savegame fixes I did for the 286/386 versions, along with trying to not paint every frame with a simple frame skip and…

Sarien for OS/2 running at 16Mhz

And it’s basically unplayable on my PS/2 model 80. Even with the 32bit XGA-2 video card.

I had to give it a shot under 86Box, to try the CGA/EGA versions:

CGA

It’s weird how the image distorts! Although the black and white mapping seems to work fine.

Sarien on EGA

I should also point out that the CGA/EGA versions are running on OS/2 2.0 Beta 6.123, which currently is the oldest beta I can get a-hold of. So at the least I did reach my goal of having a 32bit version for early OS/2.

I would imagine it running okay on any type of Pentium system, however. So, what would the advantage of this, vs just running the original game in a dos box? Well, it is a native 32bit app. This is the future that was being sold to us back in 1990. I’m sure the native assembly that Sierra used was far more efficient and would have made more sense to just be a full screened 16bit VIO application.

So how long did it take to get from there to here? Shockingly not that much time, 02/20/2024 6:02 PM for running FastGPI, to 02/20/2024 10:56 PM For the first image being displayed in Presentation Manager, and finally 02/21/2024 10:39 PM to when I was first able to walk. As you can see, that is NOT a lot of time. Granted I have a substantially faster machine today than what I’d have in 1990 (I didn’t get a 286 until late 91? early 92?), compiling Sarien on the PS/2 takes 30-40 minutes and that’s with the ultra-fast BlueSCSI, compared to even using MS-DOS Player I can get a build in about a minute without even compiling in parallel.

I’ve put the source over on github: neozeed/sarienPM: Sarien for OS/2 (github.com)

I think the best way to distribute this is in object form, so I’ve created both a zip & disk image containing the source & objects, so you can link natively on your machine, just copy the contents of the floppy somewhere and just run ‘build.cmd’ which will invoke the system linker, LINK386 to do it’s job. I have put both the libc & os2386 libraries on the disk so it should just work about everywhere. Or it did for me!

So that’s my quick story over the last few days working on & off on this simple port of Sarien to OS/2 Presentation Manager. As always, I want to give thanks to my Patrons!

NASA Saturn V LVDC

I really can’t add anything to this excellent resource for preserving the LVDC!

https://www.ibiblio.org/apollo/LVDC.html#gsc.tab=0

Note that this is NOT the Apollo guidance, rather this is the IBM provided ballistic launch programs. As told, it’d be a terrible ICBM program as it’s geared towards getting payloads into orbit, such as Skylab & Apollo.

And I really cannot add anything as I’m not an american citizen:

We’re currently treating LVDC code as if it is restricted for export from the U.S. by the International Traffic in Arms Regulations (ITAR).  If you legally qualify as a “U.S. person” and can provide evidence of that status, contact us directly to arrange to receive a copy of the code.
From the ibibilo page

Well at least it’s not completely lost as the last time I checked on this, all the LVDC’s were at the bottom of the ocean, and no printouts survived. At least some printouts have been found.

All I can do is call attention to it.

Zork for the PDP-11 / RT-11 recreated

I know this is a weird one, but I’ve always wanted to run Infocom games from ever since I found out it was a thing.

The cover of the RT-11 Zork that sold on ebay for $2,348.31

I know you maybe thinking of the FORTRAN port of the full Zork game, which does run on the same system. But this is NOT the FORTRAN reverse engineered game, rather it’s a port of the Z-Machine to the RT-11 / PDP-11.

Also this is NOT a 3rd party reverse engineering effort, it is the official Infocom Z-Machine source.

;       Proprietary documentation of:
;
;               Infocom, Inc.
;               55 Wheeler St.
;               Cambridge, MA 02138
;
;       Copyright (C) 1982, 1983 Infocom, Inc.  All rights reserved.

Yes it’s the real deal!

Ok so what or where to do this?! First you need SIMH or any other good PDP-11 emulator, a copy of RT-11, and of course the source to the interpreter oddly enough named PDP11.ZIP. Just keep in mind that this is NOT a pk-zip file, it’s a text file. It’s Macro-11 assembler source.

First you need a very simple config/type in to the SIMH PDP-11 emulator:

attach rk0 rtv4_rk.dsk
attach ptr pdp11.zip
boot rk

All being well you should boot into RT-11.

Now we copy the source into the machine through the paper tape reader. Just type in ‘COPY PC: ZIP.MAC’

.COPY PC: ZIP.MAC
 Files copied:
PC:            to DK:ZIP.MAC

.

This will create a .mac or macro assembler source file. The extension matters as it will tell the compiler what file it is and what to do. But luckily this is a single file, and assembles quite easily. As a tip to Unix folk, I found that making the assembly source in MS-DOS CR/LF made life easier.

Compiling & linking is very straightforward

.COMPILE ZIP.MAC
ERRORS DETECTED:  0

.LINK ZIP.OBJ

. 

Now we need to import a game file. I usually test with Planetfall, so I grabbed the data file, and placed it into the working directory and then attached it to the emulator

Simulation stopped, PC: 152644 (BR 152622)
sim> att ptr planetfa
sim> c


.COPY PC: PLANET.IML
 Files copied:
PC:            to DK:PLANET.IML

.

Notice the filenames are short, very 8.3 for some strange coincidence! Also I named it planet.iml, as that is what the interpreter is expecting. Now we can just run the zip and point it to the game data file!

.RUN ZIP
Line width (default is 80, end with LF for status line):
File name (current default is DK:$GAME$.IML) *dk:planet.iml
PLANETFALL
Infocom interactive fiction - a science fiction story
Copyright (c) 1983 by Infocom, Inc. All rights reserved.
PLANETFALL is a trademark of Infocom, Inc.
Release 37 / Serial number 851003

And there we go! We are now running Planetfall on our simulated PDP-11!

There is quite a few great 80’s systems in the github repository, I have no doubt the rest can be built, but I thought I’d tackle a system that was another bigfoot, a thing of pure legend!

Building MS-DOS 2.11

I thought I’d slap together some github thing with MS-DOS 2.11 that’s been made buildable thanks to a whole host of other smart people. The default stuff out there expects you to build it under MS-DOS using the long obsoleted ‘append’ utility which can add directories to a search path. Instead I created a bunch of makefiles that take advantage of MS-DOS Player, and let you build from Windows.

dos211: just the MS-DOS 2.11 sources, I re-aranged stuff and made it (slightly) easier to rebuild on Windows. (github.com)

building should be somewhat straightforward, assuming you have the ms-dos player in your path. JUST MAKE SURE YOU UNZIP as TEXT mode. If you are getting a million errors you probably have them in github’s favourite unix mode.

D:\temp\dos211-main\bios>..\tools\make
msdos ..\tools\masm ibmbio.asm ibmbio.obj NUL NUL
The Microsoft MACRO Assembler , Version 1.25
 Copyright (C) Microsoft Corp 1981,82,83


Warning Severe
Errors  Errors
0       0
msdos ..\tools\masm sysimes.asm sysimes.obj NUL NUL
The Microsoft MACRO Assembler , Version 1.25
 Copyright (C) Microsoft Corp 1981,82,83


Warning Severe
Errors  Errors
0       0
msdos ..\tools\masm sysinit.asm sysinit.obj NUL NUL
The Microsoft MACRO Assembler , Version 1.25
 Copyright (C) Microsoft Corp 1981,82,83

DOSSYM in Pass 2

Warning Severe
Errors  Errors
0       0
msdos ..\tools\LINK IBMBIO+SYSINIT+SYSIMES;

   Microsoft Object Linker V2.00
(C) Copyright 1982 by Microsoft Inc.

Warning: No STACK segment

There was 1 error detected.
msdos ..\tools\exe2bin.exe IBMBIO IBMBIO.COM < 70.TXT
Fix-ups needed - base segment (hex): 70
del -f ibmbio.obj    sysimes.obj   sysinit.obj ibmbio.exe

D:\temp\dos211-main\bios>

As an example building the bios by running make. For the impatiend you can download dos211.zip, which includes a bootable 360kb disk image, and a 32Mb vmdk!