Setting up PC XT/AT BIOS building and testing environment in arm64 macOS 12

2021-11-28

Note: These are my personal notes when trying to set up the environment on my ARM64 (M1) macOS 12 machine. May not be correct, and may not work with newer/ older version of software/ operating system. The best way is still to do these on a i386/amd64 Linux machine.

PCem

PCem is a good tool for emulating early PC systems. While the development of PCem is stopped and the general focus has shifted to 86Box, PCem has an unofficial macOS port available. To build and run it on macOS 12 with MacPorts (refer to README for homebrew usage):

$ sudo port install libsdl2 openal-soft wxWidgets-3.0
$ git clone https://github.com/PCemOnMac/PCemV17macOS
$ cd PCemV17macOS
$ ./configure --enable-release-build --with-wxdir=/opt/local/Library/Frameworks/wxWidgets.framework/Versions/wxWidgets/3.0/bin
$ make

After that, the binary pcem should be generated (with x86 to arm64 JIT as well).

Place ROMs in ~/Library/Application Support/PCem/roms

Bochs BIOS

Bochs BIOS uses bcc for compiling the BIOS, which could be a good thing, especially there is obviously no 32-bit x86 gcc on arm64 M1 environment. The only issue is that bcc (part of dev86) is not packaged either by MacPorts or homebrew, so it needs to be compiled and installed.

$ git clone https://github.com/lkundrak/dev86
$ cd dev86

The makefile.in needs to be modified to not error on implicit function declaration (due to type mismatch):

--- a/makefile.in
+++ b/makefile.in
@@ -43,7 +43,7 @@ WALL  =-Wall -Wtraditional -Wshadow -Wpointer-arith \
 CFLAGS =$(GCCFLAG) $(WALL) -O2 -g
 #else
 WALL  =-Wall -Wstrict-prototypes
-CFLAGS =$(GCCFLAG) -O2 -fno-strict-aliasing
+CFLAGS =$(GCCFLAG) -O2 -fno-strict-aliasing -Wno-error=implicit-function-declaration
 #endif

 #endif

There will be some errors in unproto/io_tok.c complaining about return in non-void function without a value, open the file and patch them to return 0.

--- a/unproto/tok_io.c
+++ b/unproto/tok_io.c
@@ -228,7 +228,7 @@ static int do_control()
            }
            out_line = in_line = line;          /* synchronize */
            out_path = in_path = path;          /* synchronize */
-           return;
+           return 0;

 #ifdef IGNORE_DIRECTIVES

@@ -247,7 +247,7 @@ static int do_control()
                        do {
                            tok_free(t);
                        } while (t->tokno != '\n' && (t = tok_get()));
-                       return;
+                       return 0;
                    }
                }
            }
@@ -259,12 +259,12 @@ static int do_control()
            do {
                tok_flush(t);
            } while (t->tokno != '\n' && (t = tok_get()));
-           return;
+           return 0;

        case 0:
            /* Hit EOF, punt. */
            put_ch('#');
-           return;
+           return 0;
        }
     }
 }

Then go on to build it. In the feature setting, disable everything. It would then stop at building libcc.a. This is good enough for the purpose of building BIOSes. Manually install the built compiler:

$ sudo cp bcc/bcc /opt/local/bin
$ sudo cp bcc/bcc-cc1 /opt/local/bin
$ sudo cp cpp/bcc-cpp /opt/local/bin
$ sudo cp as/as86 /opt/local/bin

Now it's ready for building Bochs BIOS.

After building, it could be run in PCem, using for example AMI 386DX clone configuration:

/uploads/blog/2021/1638109820005-image.png