MinGW-w64

Well after yesterdays x86_64 excitement, I figured I’d take a look in the windows area to see about the 32bit vs 64bit performance on Windows…

I know this isn’t the ‘best’ test as I’m using VMWare Fusion on OS X and running Windows XP x64 sp2 (the 2007 edition, not the 2003 one).

If anyone wants to know how to get a 64bit gcc on windows, this is the best formula I’ve come up with so far.

First download a build of mingw-w64-bin_x86_64 from sourceforge… Right now I’m using a ‘Personal Build’ from sezero_20101003, because… it’s recent, and I would imagine a personal build has some hope of actually working.

I downloaded that, and extracted to the root of the C drive. Then I renamed the mingw64 to mingw.

Next up, I downloaded and installed MSYS 1.0.11, and installed that. I selected the default options, and of course specified my mingw is installed in

C:/mingw

After that, I install the MSYS DTK 1.0, again with default options.

The final part is some kind of editor, I like VIM but it’s… involved to download as the default package ‘vim-7.2-1-msys-1.0.11-bin.tar.lzma’ is in a 7zip compatible archive that needs a bit of tweaking to get a tar file out of. I can provide it here in gzip format, that you can simply extract within the msys command prompt in the /usr directory.

Now with all that done, you should be in business!

$ gcc -v
Using built-in specs.
Target: x86_64-w64-mingw32
Configured with: ../gcc44-svn/configure –host=x86_64-w64-mingw32 –target=x86_6
4-w64-mingw32 –disable-multilib –enable-checking=release –prefix=/mingw64 –w
ith-sysroot=/mingw64 –enable-languages=c,c++,fortran,objc,obj-c++ –enable-libg
omp –with-gmp=/mingw64 –with-mpfr=/mingw64 –disable-nls –disable-win32-regis
try
Thread model: win32
gcc version 4.4.5 20101001 (release) [svn/rev.164871 – mingw-w64/oz] (GCC)

 

But will it run Dungeon?

What is also cool, is that this build of mingw includes gfortran, which is a Fortran 95 compiler with various 2003 & 2008 enhancements. So for the heck of it, I’ve rebuilt the makefile from dungeon-2.5.6 and tweaked the machdep.f to at least call the ITIME function to get the current time. The resulting archive runs pretty well!

Windows XP x64 - dungeon

Yes, it runs! And without a *32 meaning this is a 64bit binary!

 

Onward with SIMH

So going back to SIMH as my benchmark, here is the vax780 with -O0/-O0

Dhrystone(1.1) time for 500000 passes = 18
This machine benchmarks at 27777 dhrystones/second
Dhrystone(1.1) time for 500000 passes = 20
This machine benchmarks at 25000 dhrystones/second
Dhrystone(1.1) time for 500000 passes = 19
This machine benchmarks at 26315 dhrystones/second

Which comparing it to the native x86_64 build is pretty good considering I’m running this in a VM (VMware Fusion!). Now the same test with -O1/-O1

Dhrystone(1.1) time for 500000 passes = 12
This machine benchmarks at 41666 dhrystones/second
Dhrystone(1.1) time for 500000 passes = 12
This machine benchmarks at 41666 dhrystones/second
Dhrystone(1.1) time for 500000 passes = 12
This machine benchmarks at 41666 dhrystones/second

Which is pretty good! Now for the finally with -O2/-O1

Dhrystone(1.1) time for 500000 passes = 12
This machine benchmarks at 41666 dhrystones/second
Dhrystone(1.1) time for 500000 passes = 12
This machine benchmarks at 41666 dhrystones/second
Dhrystone(1.1) time for 500000 passes = 12
This machine benchmarks at 41666 dhrystones/second

Which is interesting in that there is no appreciable difference in the -O2/-O1 vs the -O1/-O1 build. Although I kind of expect different results on a native machine. If anyone else cares to test, I’m going to make available the whole project here. This includes the source and the pre-built binaries.

Unzip it on a win64/win32 machine and it should be somewhat straightforward to build / run. You can alter the makefile and change the primary CC flags from O0 to O1 or O2 if you so wish… just run make and it’ll generate a vax780.exe . Then in the test directory you can bench your exe like this:

$ make
gcc -O0 -c -o VAX/vax_cpu.o VAX/vax_cpu.c -I. -DVM_VAX -DVAX_780 -DUSE_INT64 -DU
SE_ADDR64 -I VAX -I PDP11
gcc -O0 -c -o VAX/vax_cpu1.o VAX/vax_cpu1.c -I. -DVM_VAX -DVAX_780 -DUSE_INT64 –
DUSE_ADDR64 -I VAX -I PDP11
gcc -O0 -c -o VAX/vax_fpa.o VAX/vax_fpa.c -I. -DVM_VAX -DVAX_780 -DUSE_INT64 -DU
SE_ADDR64 -I VAX -I PDP11
VAX/vax_fpa.c: In function ‘op_cmpfd’:
VAX/vax_fpa.c:210: warning: integer constant is too large for ‘long’ type
VAX/vax_fpa.c:210: warning: integer constant is too large for ‘long’ type
VAX/vax_fpa.c:211: warning: integer constant is too large for ‘long’ type
VAX/vax_fpa.c:211: warning: integer constant is too large for ‘long’ type
VAX/vax_fpa.c: In function ‘op_cmpg’:
VAX/vax_fpa.c:233: warning: integer constant is too large for ‘long’ type
VAX/vax_fpa.c:233: warning: integer constant is too large for ‘long’ type
VAX/vax_fpa.c:234: warning: integer constant is too large for ‘long’ type
VAX/vax_fpa.c:234: warning: integer constant is too large for ‘long’ type
VAX/vax_fpa.c: In function ‘vax_fadd’:
VAX/vax_fpa.c:371: warning: integer constant is too large for ‘long’ type
VAX/vax_fpa.c:373: warning: integer constant is too large for ‘long’ type
VAX/vax_fpa.c:386: warning: integer constant is too large for ‘long’ type
VAX/vax_fpa.c: In function ‘unpackd’:
VAX/vax_fpa.c:525: warning: integer constant is too large for ‘long’ type
VAX/vax_fpa.c:525: warning: integer constant is too large for ‘long’ type
VAX/vax_fpa.c: In function ‘unpackg’:
VAX/vax_fpa.c:540: warning: integer constant is too large for ‘long’ type
VAX/vax_fpa.c:540: warning: integer constant is too large for ‘long’ type
VAX/vax_fpa.c: In function ‘norm’:
VAX/vax_fpa.c:548: warning: integer constant is too large for ‘long’ type
VAX/vax_fpa.c:548: warning: integer constant is too large for ‘long’ type
VAX/vax_fpa.c:548: warning: integer constant is too large for ‘long’ type
VAX/vax_fpa.c:549: warning: integer constant is too large for ‘long’ type
VAX/vax_fpa.c:549: warning: integer constant is too large for ‘long’ type
VAX/vax_fpa.c:557: warning: integer constant is too large for ‘long’ type
VAX/vax_fpa.c: In function ‘rpackfd’:
VAX/vax_fpa.c:574: warning: integer constant is too large for ‘long’ type
VAX/vax_fpa.c:575: warning: integer constant is too large for ‘long’ type
VAX/vax_fpa.c: In function ‘rpackg’:
VAX/vax_fpa.c:597: warning: integer constant is too large for ‘long’ type
gcc -O0 -c -o VAX/vax_cis.o VAX/vax_cis.c -I. -DVM_VAX -DVAX_780 -DUSE_INT64 -DU
SE_ADDR64 -I VAX -I PDP11
gcc -O0 -c -o VAX/vax_octa.o VAX/vax_octa.c -I. -DVM_VAX -DVAX_780 -DUSE_INT64 –
DUSE_ADDR64 -I VAX -I PDP11
gcc -O0 -c -o VAX/vax_cmode.o VAX/vax_cmode.c -I. -DVM_VAX -DVAX_780 -DUSE_INT64
-DUSE_ADDR64 -I VAX -I PDP11
gcc -O0 -c -o VAX/vax_mmu.o VAX/vax_mmu.c -I. -DVM_VAX -DVAX_780 -DUSE_INT64 -DU
SE_ADDR64 -I VAX -I PDP11
gcc -O0 -c -o VAX/vax_sys.o VAX/vax_sys.c -I. -DVM_VAX -DVAX_780 -DUSE_INT64 -DU
SE_ADDR64 -I VAX -I PDP11
gcc -O0 -c -o VAX/vax_syscm.o VAX/vax_syscm.c -I. -DVM_VAX -DVAX_780 -DUSE_INT64
-DUSE_ADDR64 -I VAX -I PDP11
gcc -O0 -c -o VAX/vax780_stddev.o VAX/vax780_stddev.c -I. -DVM_VAX -DVAX_780 -DU
SE_INT64 -DUSE_ADDR64 -I VAX -I PDP11
gcc -O0 -c -o VAX/vax780_sbi.o VAX/vax780_sbi.c -I. -DVM_VAX -DVAX_780 -DUSE_INT
64 -DUSE_ADDR64 -I VAX -I PDP11
gcc -O0 -c -o VAX/vax780_mem.o VAX/vax780_mem.c -I. -DVM_VAX -DVAX_780 -DUSE_INT
64 -DUSE_ADDR64 -I VAX -I PDP11
gcc -O0 -c -o VAX/vax780_uba.o VAX/vax780_uba.c -I. -DVM_VAX -DVAX_780 -DUSE_INT
64 -DUSE_ADDR64 -I VAX -I PDP11
gcc -O0 -c -o VAX/vax780_mba.o VAX/vax780_mba.c -I. -DVM_VAX -DVAX_780 -DUSE_INT
64 -DUSE_ADDR64 -I VAX -I PDP11
gcc -O0 -c -o VAX/vax780_fload.o VAX/vax780_fload.c -I. -DVM_VAX -DVAX_780 -DUSE
_INT64 -DUSE_ADDR64 -I VAX -I PDP11
gcc -O0 -c -o VAX/vax780_syslist.o VAX/vax780_syslist.c -I. -DVM_VAX -DVAX_780 –
DUSE_INT64 -DUSE_ADDR64 -I VAX -I PDP11
gcc -O0 -c -o PDP11/pdp11_rl.o PDP11/pdp11_rl.c -I. -DVM_VAX -DVAX_780 -DUSE_INT
64 -DUSE_ADDR64 -I VAX -I PDP11
gcc -O0 -c -o PDP11/pdp11_rq.o PDP11/pdp11_rq.c -I. -DVM_VAX -DVAX_780 -DUSE_INT
64 -DUSE_ADDR64 -I VAX -I PDP11
gcc -O0 -c -o PDP11/pdp11_ts.o PDP11/pdp11_ts.c -I. -DVM_VAX -DVAX_780 -DUSE_INT
64 -DUSE_ADDR64 -I VAX -I PDP11
gcc -O0 -c -o PDP11/pdp11_dz.o PDP11/pdp11_dz.c -I. -DVM_VAX -DVAX_780 -DUSE_INT
64 -DUSE_ADDR64 -I VAX -I PDP11
gcc -O0 -c -o PDP11/pdp11_lp.o PDP11/pdp11_lp.c -I. -DVM_VAX -DVAX_780 -DUSE_INT
64 -DUSE_ADDR64 -I VAX -I PDP11
gcc -O0 -c -o PDP11/pdp11_tq.o PDP11/pdp11_tq.c -I. -DVM_VAX -DVAX_780 -DUSE_INT
64 -DUSE_ADDR64 -I VAX -I PDP11
gcc -O0 -c -o PDP11/pdp11_xu.o PDP11/pdp11_xu.c -I. -DVM_VAX -DVAX_780 -DUSE_INT
64 -DUSE_ADDR64 -I VAX -I PDP11
gcc -O0 -c -o PDP11/pdp11_ry.o PDP11/pdp11_ry.c -I. -DVM_VAX -DVAX_780 -DUSE_INT
64 -DUSE_ADDR64 -I VAX -I PDP11
gcc -O0 -c -o PDP11/pdp11_cr.o PDP11/pdp11_cr.c -I. -DVM_VAX -DVAX_780 -DUSE_INT
64 -DUSE_ADDR64 -I VAX -I PDP11
gcc -O0 -c -o PDP11/pdp11_rp.o PDP11/pdp11_rp.c -I. -DVM_VAX -DVAX_780 -DUSE_INT
64 -DUSE_ADDR64 -I VAX -I PDP11
gcc -O0 -c -o PDP11/pdp11_tu.o PDP11/pdp11_tu.c -I. -DVM_VAX -DVAX_780 -DUSE_INT
64 -DUSE_ADDR64 -I VAX -I PDP11
gcc -O0 -c -o PDP11/pdp11_hk.o PDP11/pdp11_hk.c -I. -DVM_VAX -DVAX_780 -DUSE_INT
64 -DUSE_ADDR64 -I VAX -I PDP11
gcc -O0 -c -o PDP11/pdp11_io_lib.o PDP11/pdp11_io_lib.c -I. -DVM_VAX -DVAX_780 –
DUSE_INT64 -DUSE_ADDR64 -I VAX -I PDP11
gcc -O0 -c -o scp.o scp.c -I. -DVM_VAX -DVAX_780 -DUSE_INT64 -DUSE_ADDR64 -I VAX
-I PDP11
scp.c:470: warning: integer constant is too large for ‘long’ type
scp.c:470: warning: integer constant is too large for ‘long’ type
scp.c:470: warning: integer constant is too large for ‘long’ type
scp.c:470: warning: integer constant is too large for ‘long’ type
scp.c:471: warning: integer constant is too large for ‘long’ type
scp.c:471: warning: integer constant is too large for ‘long’ type
scp.c:471: warning: integer constant is too large for ‘long’ type
scp.c:471: warning: integer constant is too large for ‘long’ type
scp.c:472: warning: integer constant is too large for ‘long’ type
scp.c:472: warning: integer constant is too large for ‘long’ type
scp.c:472: warning: integer constant is too large for ‘long’ type
scp.c:472: warning: integer constant is too large for ‘long’ type
scp.c:473: warning: integer constant is too large for ‘long’ type
scp.c:473: warning: integer constant is too large for ‘long’ type
scp.c:473: warning: integer constant is too large for ‘long’ type
scp.c:473: warning: integer constant is too large for ‘long’ type
scp.c:474: warning: integer constant is too large for ‘long’ type
scp.c:474: warning: integer constant is too large for ‘long’ type
scp.c:474: warning: integer constant is too large for ‘long’ type
scp.c:474: warning: integer constant is too large for ‘long’ type
scp.c:475: warning: integer constant is too large for ‘long’ type
scp.c:475: warning: integer constant is too large for ‘long’ type
scp.c:475: warning: integer constant is too large for ‘long’ type
scp.c:475: warning: integer constant is too large for ‘long’ type
scp.c:476: warning: integer constant is too large for ‘long’ type
scp.c:476: warning: integer constant is too large for ‘long’ type
scp.c:477: warning: integer constant is too large for ‘long’ type
scp.c:477: warning: integer constant is too large for ‘long’ type
scp.c:478: warning: integer constant is too large for ‘long’ type
scp.c:478: warning: integer constant is too large for ‘long’ type
scp.c:479: warning: integer constant is too large for ‘long’ type
scp.c:479: warning: integer constant is too large for ‘long’ type
gcc -O0 -c -o sim_console.o sim_console.c -I. -DVM_VAX -DVAX_780 -DUSE_INT64 -DU
SE_ADDR64 -I VAX -I PDP11
gcc -O0 -c -o sim_fio.o sim_fio.c -I. -DVM_VAX -DVAX_780 -DUSE_INT64 -DUSE_ADDR6
4 -I VAX -I PDP11
gcc -O0 -c -o sim_timer.o sim_timer.c -I. -DVM_VAX -DVAX_780 -DUSE_INT64 -DUSE_A
DDR64 -I VAX -I PDP11
gcc -O0 -c -o sim_sock.o sim_sock.c -I. -DVM_VAX -DVAX_780 -DUSE_INT64 -DUSE_ADD
R64 -I VAX -I PDP11
gcc -O0 -c -o sim_tmxr.o sim_tmxr.c -I. -DVM_VAX -DVAX_780 -DUSE_INT64 -DUSE_ADD
R64 -I VAX -I PDP11
gcc -O0 -c -o sim_ether.o sim_ether.c -I. -DVM_VAX -DVAX_780 -DUSE_INT64 -DUSE_A
DDR64 -I VAX -I PDP11
gcc -O0 -c -o sim_tape.o sim_tape.c -I. -DVM_VAX -DVAX_780 -DUSE_INT64 -DUSE_ADD
R64 -I VAX -I PDP11
gcc -O0 -c -o VAX/vax_cpu2.o VAX/vax_cpu2.c -I. -DVM_VAX -DVAX_780 -DUSE_INT64 –
DUSE_ADDR64 -I VAX -I PDP11
gcc -O1 -c -o VAX/vax_cpu2.o VAX/vax_cpu2.c -I. -DVM_VAX -DVAX_780 -DUSE_INT64
-DUSE_ADDR64 -I VAX -I PDP11
gcc -o vax780 VAX/vax_cpu.o VAX/vax_cpu1.o VAX/vax_fpa.o VAX/vax_cis.o VAX/vax_
octa.o VAX/vax_cmode.o VAX/vax_mmu.o VAX/vax_sys.o VAX/vax_syscm.o VAX/vax780_st
ddev.o VAX/vax780_sbi.o VAX/vax780_mem.o VAX/vax780_uba.o VAX/vax780_mba.o VAX/v
ax780_fload.o VAX/vax780_syslist.o PDP11/pdp11_rl.o PDP11/pdp11_rq.o PDP11/pdp11
_ts.o PDP11/pdp11_dz.o PDP11/pdp11_lp.o PDP11/pdp11_tq.o PDP11/pdp11_xu.o PDP11/
pdp11_ry.o PDP11/pdp11_cr.o PDP11/pdp11_rp.o PDP11/pdp11_tu.o PDP11/pdp11_hk.o P
DP11/pdp11_io_lib.o scp.o sim_console.o sim_fio.o sim_timer.o sim_sock.o sim_tmx
r.o sim_ether.o sim_tape.o VAX/vax_cpu2.o -I. -DVM_VAX -DVAX_780 -DUSE_INT64 -DU
SE_ADDR64 -I VAX -I PDP11 -lwinmm -lwsock32

Administrator@JASON-4AC1B1EA0 /usr/src/simh
$ cd test/

Administrator@JASON-4AC1B1EA0 /usr/src/simh/test
$ ../vax780.exe bsd42.ini

VAX780 simulator V3.8-1
loading ra(0,0)boot
Boot
: ra(0,0)vmunix
199488+56036+51360 start 0x11a0
4.2 BSD UNIX #9: Wed Nov 2 16:00:29 PST 1983
real mem = 8384512
avail mem = 7073792
using 102 buffers containing 835584 bytes of memory
mcr0 at tr1
mcr1 at tr2
uba0 at tr3
hk0 at uba0 csr 177440 vec 210, ipl 15
rk0 at hk0 slave 0
rk1 at hk0 slave 1
uda0 at uba0 csr 172150 vec 774, ipl 15
ra0 at uda0 slave 0
ra1 at uda0 slave 1
zs0 at uba0 csr 172520 vec 224, ipl 15
ts0 at zs0 slave 0
dz0 at uba0 csr 160100 vec 300, ipl 15
dz1 at uba0 csr 160110 vec 310, ipl 15
dz2 at uba0 csr 160120 vec 320, ipl 15
dz3 at uba0 csr 160130 vec 330, ipl 15
root on ra0
WARNING: should run interleaved swap with >= 2Mb
Automatic reboot in progress…
Tue Nov 8 03:44:30 PST 1983
Can’t open checklist file: /etc/fstab
Automatic reboot failed… help!
erase ^?, kill ^U, intr ^C
# ./d2;./d2;./d2
Dhrystone(1.1) time for 500000 passes = 19
This machine benchmarks at 26315 dhrystones/second
Dhrystone(1.1) time for 500000 passes = 19
This machine benchmarks at 26315 dhrystones/second
Dhrystone(1.1) time for 500000 passes = 18
This machine benchmarks at 27777 dhrystones/second
# sync
# sync
# sync
#
Simulation stopped, PC: 80001629 (BNEQ 80001630)
sim> q
Goodbye

Administrator@JASON-4AC1B1EA0 /usr/src/simh/test
$

The d0,d1,d2 are the dhyrstone benchmark compiled with -O0, -O1, and -O2 respectively. This gives you a chance to observe various optimizations in the GCC 2.7.2.2 for the VAX.

gcc on the x86_64

Today I thought I’d isolate the portion of simh that crashes 4.X BSD, when SIMH is built with GCC. I managed to find that the “op_ldpctx” and “op_mtpr” procedures of vax_cpu1.c become unstable when built with -O2 flags.

So I extracted the two procedures so I could then built the remainder of SIMH with GCC’s O2 flags. Before going too far, I first went to verify that the results would be consistent with the i386/32bit binaries…

However the results were.. interesting. By default SIMH will build with -O0 flags for the VAX giving the following dhrystone benchmark in 4.3 UWisc BSD:

Dhrystone(1.1) time for 500000 passes = 24
This machine benchmarks at 20833 dhrystones/second
Dhrystone(1.1) time for 500000 passes = 24
This machine benchmarks at 20833 dhrystones/second
Dhrystone(1.1) time for 500000 passes = 24
This machine benchmarks at 20833 dhrystones/second

24 seconds, not so hot. Then the same thing with -O1 flags…

Dhrystone(1.1) time for 500000 passes = 18
This machine benchmarks at 27777 dhrystones/second
Dhrystone(1.1) time for 500000 passes = 18
This machine benchmarks at 27777 dhrystones/second
Dhrystone(1.1) time for 500000 passes = 18
This machine benchmarks at 27777 dhrystones/second

18 seconds! pretty good, thats a 33% increase! Now for my hybrid -O2/-O1

Dhrystone(1.1) time for 500000 passes = 17
This machine benchmarks at 29411 dhrystones/second
Dhrystone(1.1) time for 500000 passes = 17
This machine benchmarks at 29411 dhrystones/second
Dhrystone(1.1) time for 500000 passes = 17
This machine benchmarks at 29411 dhrystones/second

A 5% increase over the -O1 … Nothing too big, but still an INCREASE.

Now for the real fun, I re-ran these bulid factors with the x86_64 compiler.

The -O0/-O0 combination came in at 19 seconds!!

Dhrystone(1.1) time for 500000 passes = 19
This machine benchmarks at 26315 dhrystones/second
Dhrystone(1.1) time for 500000 passes = 19
This machine benchmarks at 26315 dhrystones/second
Dhrystone(1.1) time for 500000 passes = 19
This machine benchmarks at 26315 dhrystones/second

This is pretty amazing considering everything we do should make it faster… The next thing I tried was the -O1/-O1 combination and go the following:

Dhrystone(1.1) time for 500000 passes = 12
This machine benchmarks at 41666 dhrystones/second
Dhrystone(1.1) time for 500000 passes = 13
This machine benchmarks at 38461 dhrystones/second
Dhrystone(1.1) time for 500000 passes = 13
This machine benchmarks at 38461 dhrystones/second

A 12.5 second average! This blew the doors off of the -O2/-O1 on the i386! Naturally I was hoping for at least a 5% increase going to the -O2/-O1 flags on the x86_64, however I got this…

Dhrystone(1.1) time for 500000 passes = 14
This machine benchmarks at 35714 dhrystones/second
Dhrystone(1.1) time for 500000 passes = 13
This machine benchmarks at 38461 dhrystones/second
Dhrystone(1.1) time for 500000 passes = 12
This machine benchmarks at 41666 dhrystones/second

And I ran it numerous times, but the bottom line is that the O2 flags actually produces a SLOWER SIMH on OS X 10.6.4 then -O1 flags… The whole exercise is a tad perplexing to me, to say the least, but unless you bench it, you’ll never know if the compiler is getting confused somewhere, and going to throw a loop. I should also point out that SIMH will not run with full -O2 flags as there is something in the code that breaks under optimization so this very well may not hold true 100% of the time, but at the same point things still have to be tested…

Taking Clipper to the Harbour

In the last instance, I left with an example of running a Clipper 87 program compiled with a simple C routine, then rebuilt that with Clipper 5.3 using both a 286 & 386 Dos extender.

The next step will be taking that program and making a win32 exe.

And for that we are going to use this great program harbour.

Much like f2c, harbour translates dBase PRG files into either C, or a p-code VM just like clipper did. For this example, I just downloaded Harbour from sourceforge, and installed it in my c:\hmg directory.

Porting applications is pretty straight forward, however Harbour needs a ‘main’ procedure to exist in order to work correctly. So the first change to my simple clipper program is to create wrap my simple Clipper program in a main procedure.

HI.PRG

procedure main
? “hello from clipper”
? “”
c_hi()
return

Now the C program needs some changes as well. Notice how this looks very different from the old c program, but at the same time, it’s not too different. Also because harbour translates the clipper into C, stdio is now working correctly so I can use printf.

HI_C.C

#include “hbvmpub.h”
#include “hbinit.h”

HB_FUNC( C_HI )
{
printf(“hi from C\n”);
}

Now to setup the environment, translate the clipper, build the c program and link them together….

\hmg\MINGW\mingwvars.bat

\hmg\HARBOUR\bin\harbour.exe hi.prg -m

gcc hi_c.c -I\hmg\harbour\include -c

gcc -mconsole hi.c hi_c.c -I\hmg\harbour\include -mconsole -Wl,–start-group -lhbextern -lhbdebug -lhbvm -lhbrtl -lhblang -lhbcpage -lgtcgi -lgtpca -lgtstd -lgtwin -lgtwvt -lgtgui -lhbrdd -lhbuddall -lhbusrrdd -lrddntx -lrddcdx -lrddnsx -lrddfpt -lhbrdd -lhbhsx -lhbsix -lhbmacro -lhbcplr -lhbpp -lhbcommon -lkernel32 -luser32 -lgdi32 -ladvapi32 -lws2_32 -lwinspool -lcomctl32 -lcomdlg32 -lshell32 -luuid -lole32 -loleaut32 -lmpr -lwinmm -lmapi32 -limm32 -lmsimg32 -lwininet -lhbpcre -lhbzlib -Wl,–end-group -ohi.exe -LC:/hmg/HARBOUR/lib

And running this gives me:

C:\temp>hi

hello from clipper
hi from C

C:\temp>

Now I know there is all kinds of front ends and other fun stuff, however I think it’s good to know how the thing actually works…

What is even more cool about Harbour is that once you get your program working there, it can be easily rebuilt for OS/2, Linux, Win32, Win64, Windows CE and a few other platforms where GCC is available.

And the best part is that they won’t soak up 100% of your CPU!!!

BSD-games & Solaris fun.

I was getting bored with a stock Solaris 2.4 system, so I decided to load up some basic BSD games. Since I like the torture of it, I went to build them from source.

OH MY GOD.

I don’t mean to complain too much, but holy crap, the configuration for the BSD games package is INSANE.

After answering what feels like 100+ questions (it very well may be) you can eventually try to build BSD-games… but much to my dismay the 2.x series all hinges on you basically having a GNU environment, and well… I didn’t want to spend that much time just to run robots & fortune.

So thanks to this great page, there is some hints on building BSD=games 1.5 for Solaris… But where on earth to find something this old?! This is the weird thing, all of this older free software is being destroyed wholesale… I know right now people just don’t care, but there most certainly is this ‘digital’ divide that is coming, where most of our current history will be lost forever… Hell if nukes fell tomorrow, good luck to anyone decoding a DVD… And god help them if they succeeded. It certainly wouldn’t be worth the effort.

Anyways, with a bunch of searching I found a site in Germany with the goods.

Now the real fun starts…

I’m using gcc 2.8.1, because that is what was in the GNAT package. Anyways for some programs I was encountering errors like this:

gcc extern.o init_field.o main.o make_level.o move.o move_robs.o play_level.o query.o rnd_pos.o score.o flush_in.o -lncurses -lnsl -lsocket -L/usr/ucblib -R/usr/ucblib -lucb -o robots
Undefined first referenced
symbol in file
_tty main.o
_pfast main.o
_echoit main.o
_tty_ch main.o
_rawmode main.o
ld: fatal: Symbol referencing errors. No output written to robots
make: *** [robots] Error 1

I know.. .WTF?! So after building & rebuilding ncurses, I found on some obscure Fortran list that the linker in Solaris is… weird. So to save anyone the hell, here is the “correct” string in this instance.

gcc extern.o init_field.o main.o make_level.o move.o move_robs.o play_level.o query.o rnd_pos.o score.o flush_in.o -L/usr/ucblib -R/usr/ucblib -lcurses -ltermcap -lucb -lncurses -o robots

Notice the difference? Yeah, the big one, is that now it linked. The position of the -L & -R really matters to the SUN linker.

Another error I was getting (in this example from tetris) was this:

In file included from screen.c:59:
screen.h:62: parse error before `__P’
screen.h:63: parse error before `__P’
screen.h:64: parse error before `__P’
screen.h:65: parse error before `__P’
screen.h:66: parse error before `__P’
screen.h:67: parse error before `__P’
screen.h:68: parse error before `__P’

I assume in the future (or was it the past?) that this __P macro would be standard with GCC? Maybe it’s a linux-isim? I don’t know. What I do know is this block

#undef __P
#ifndef __P
#if __STDC__
#define __P(protos) protos
#else
#define __P(protos) ()
#endif
#endif

Will fix it.

Another weird error revolves around setjmp.h . Now I know in Solaris some headers have to be included in a certain order or all hell will break loose, or the part you are looking for just won’t be included. But I just mined out the relevant parts to get what I wanted…

In file included from /usr/ucbinclude/setjmp.h:44,
from screen.c:47:
/usr/include/sys/ucontext.h:24: parse error before `sigset_t’
/usr/include/sys/ucontext.h:24: warning: no semicolon at end of struct or union
/usr/include/sys/ucontext.h:25: warning: data definition has no type or storage class
/usr/include/sys/ucontext.h:28: parse error before `}’
/usr/include/sys/ucontext.h:28: warning: data definition has no type or storage class

So I just removed the reference to setjmp.h & instead put in this:

#define _JBLEN 10 /* ABI value */
typedef int jmp_buf[_JBLEN];

And it was happy. Now I know this is a HORRIBLE “FIX” but heh, sometimes you just want the dammed thing to compile!

Next I was getting these weird sigset_t errors…

screen.c: In function `stopset’:
screen.c:238: `sigset_t’ undeclared (first use in this function)
screen.c:238: (Each undeclared identifier is reported only once
screen.c:238: for each function it appears in.)
screen.c:238: parse error before `sigset’
screen.c:242: `sigset’ undeclared (first use in this function)
screen.c:244: parse error before `)’

And again I just mashed in the definition of:

typedef struct { /* signal set type */
unsigned long __sigbits[4];
} sigset_t;

Lastly was another error revolving around sig_t … So just inserting this:

typedef void (*sig_t) (int);

Into the code, got it to stop complaining.

So the upshot is that after manually linking a bunch of these programs, and manually installing the binaries & datafiles (Solaris 2.4’s install doesn’t work the way BSD-games 1.5 expects…) I finally could do this:

UNIX(r) System V Release 4.0 (solaris24)

login: rootb
Password:
Last login: Sat Dec 12 19:01:49 from qemunat
bash# fortune
There can be no twisted thought without a twisted molecule.
— R. W. Gerard
bash#

Now the big question…. Was it worth it?

Yeah sure, I learned a valuable lesson about the linker. The rest, not so valuable.

200th post!, and using ADA to fix your system…

Wow, so I was about to post this when I check to see how many posts I’ve done, and this will put me at 200.

It’s hard to believe it all started out on running Netware 3.12 on Qemu 0.9.0.

Ok, now let’s get on with today’s fun.

I’ve recently managed to get Solaris 2.4 running on Qemu, and it’s been all great, but I’d love to build some programs for it! Now there are binary builds of GCC for Solaris 2.4, but they are about 17MB compressed, and I think it was about 80 uncompressed!

Well that sounds great, except for 2 major limitations:

1. For some reason Solaris doesn’t want to mount any ISO I give it… I’m still kind of lost there.
2. The only networking I can get working is the usermode NAT, and Solaris 2.4’s ftp client/server is just too old for passive mode.

So what the heck can I do?

Well back in college we had this RS/6000 that was cool, *BUT* for some reason I don’t recall it couldn’t build and use mtools (among other things) but from what we had heard is that if we had gcc, it’d run fine. Except without a working C compiler, how does one get GCC running on a RISC machine?

Well, thanks to the fine people that maintain GNAT, the GNU ADA translator, they provide some ready to run versions of GCC. Well not to complain but as the years drag on, lots of mirrors are gone, and there are only a handful of copies left, but they currently have:

*Dec Alpha OSF4
*HP HPPA HPUX 10.20
*i386 Solaris 2.6
*SUN Sparc Solaris 2.5.1
*IBM PowerPC AIX 4.1

And let me tell you, if you were ever given any of the above machines, you’ll be so grateful for this massive leg-up! Now these are *NOT* full development systems, as they are geared towards translation, they are lacking the libc/include files. You’ll have to source those from somewhere, but thankfully as part of the Solaris install there is an option for headers and libraries.

So, while this is all very good, how do you get this stuff to run on your SPARC?

Well.. It’s tedious! but this method is what I used to get gcc running on the RS/6000 years ago, and on the sparc. Unpack that GNAT distribution, then use uuencode/uudecode on the minimal files.. Then paste them into a console window and be sure to have turned messages off!… It’s not “sexy” but it works!

Naturally since there is no gzip for Solaris (you’d have to send one over first!) don’t bother compressing anything with gzip/bzip2… although you could us the old unix compress command, which is what I ended up doing.

So at a minimum the following files are needed to build some programs…

cc1 crt1.o crtend.o crtn.o libgcc.a
cpp crtbegin.o crti.o gcc

Yes, really!

# cat one.c

#include <stdio.h>
void main(void)
{
printf(“hi\n”);
}
# gcc -v one.c -o one
Using builtin specs.
gcc version 2.8.1
cpp -lang-c -v -undef -D__GNUC__=2 -D__GNUC_MINOR__=8 -Dsparc -Dsun -Dunix -D__svr4__ -D__SVR4 -D__sparc__ -D__sun__ -D__unix__ -D__svr4__ -D__SVR4 -D__sparc -D__sun -D__unix -Asystem(unix) -Asystem(svr4) -D__GCC_NEW_VARARGS__ -Acpu(sparc)
-Amachine(sparc) one.c /var/tmp/cca000KP.i
GNU CPP version 2.8.1 (sparc)
#include “…” search starts here:
#include <s…> search starts here:
/usr/include
End of search list.
cc1 /var/tmp/cca000KP.i -quiet -dumpbase one.c -version -o /var/tmp/cca000KP.s
GNU C version 2.8.1 (sparc-sun-solaris2.5.1) compiled by GNU C version 2.8.1.
one.c: In function `main’:
one.c:4: warning: return type of `main’ is not `int’
/usr/ccs/bin/as -V -Qy -s -o /var/tmp/cca000KP1.o /var/tmp/cca000KP.s
/usr/ccs/bin/as: SC3.1 dev 09 May 1994
/usr/ccs/bin/ld -V -Y P,/usr/ccs/lib:/usr/lib -Qy -o one /lib/crt1.o /lib/crti.o /usr/ccs/lib/values-Xa.o /lib/crtbegin.o -L/usr/ccs/bin -L/usr/ccs/lib /var/tmp/cca000KP1.o -lgcc -lc -lgcc /lib/crtend.o /lib/crtn.o
ld: Software Generation Utilities (SGU) SunOS/ELF (LK-1.4 (S/I))
# ./one
hi
#

After an hour of struggling with uuencode, and pasting the results with putty into Qemu running Solaris 2.4 I’ve managed to cook up the following programs:

gzip-1.24
httpd-0.5
ircII-4.4
lynx-2.8.2
make-3.75
unzip-5.52

And I’ve got to admit, that using lynx to download new stuff is a VAST improvement! So for the hell of it, I went ahead and built my favorite f2c/libf2c & dungeon-2.5.6!

Solaris 2.4 running dungeon

So there it is, Dungeon in all of its “glory”.

Now one important ‘tip’ to share, is that if you follow this path, it’s possible to run into some weird vararg issues… The problem is that gcc works better with it’s own headers for varargs, not any OS version… Everyone recommends you build GCC on your machine yourself to get all the headers in place. The GNAT packages do include the needed vararg stuff, you can simply change the lines that use something like this:

#include <varargs.h>

to

#include “/tmp/gnu/varargs.h”

And life will be good.. That’s basically what I was needing to get lynx to run.

Well, that’s the end of this adventure, hope to post at least another 200 more!

Frotz on Xenix

Well after having some fun with gcc, I wanted to try something a little more… “fun”. I’ve had good luck in the past with ‘dumb frotz‘ on the old BSD stuff (4.2/4.3 etc) but surprisingly I had no luck at all with gcc & xenix.

Well that was rather odd.

So in some crazed attempt I tried the regular version of Unix Frotz 2.32. Xenix was lacking the memmove procedure, but thanks to an old post here, I was able to get it running under Xenix.

Ok, fair warning it is SLOW. It’ runs the cpu into 1.0 levels… I don’t know why. My attempts at building gdb and using it from that old Soviet site hasn’t met with much luck.

Oh, and it was easier to massage some make files with gnumake.

But it does run!

If anyone want’s to give it a whirl it’s available here.

Build a DLL

Well this is leading up to a new release of my SIMH projects. The issue that I’ve had with the SLiRP code (usermode NAT) is that it only works when built with GCC, and ONLY when you have no optimizations. Naturally you will loose all optimizations with SIMH if you build the entire project like that. And of course you cannot use Visual C++ to build SIMH, because while it’s faster they use different object files.

So while thinking about what a bummer it is, and how to try to debug SLiRP with Visual Studio, today I had a ‘better’ idea. Well ‘better’ in that I can do this way quicker.

Instead I’ll build SLiRP as a DLL, and have Visual C++ call that!

Ok, now that sounds crazy, but the first thing I’d need is a simple ‘test’ case. First let’s build a dll in MinGW. It took a bit of googling but then I found this super simple example.

dll.c

__declspec(dllexport) int hi(void)
{
return 3;
}

Ok, it doesn’t do that much, but you get the idea. Now we have to compile this with MinGW.

gcc -c dll.c
gcc -shared -o test.dll dll.o

Ok, now this will first compile the C file into an object file, then the linker will set it up as a DLL. Notice that I’m not building the ‘.a’ export file for this DLL. Visual C++ wouldn’t like it anyways, so I don’t need it.

Next, using Visual C++ (I would *assume* just about every version can do this..) I re-build the DLL to create the export library. Yes I know this is weird, but it is the quickest way I know to do this.

cl /c /LD dll.c
link /DLL dll.obj

Cool, now we’ve built dll.c as a DLL under both MinGW & Visual C++. Now for a ‘test’ program to drive our ‘staticly linked’ dynamic link library.

test.c

void main(void)
{
int j=hi();
printf(“%d\n”,j);
}

Ok, now with that out of the way, let’s compile & link!

cl test.c dll.lib

Cool, now we’ll have a test.exe!

Let’s run it!

c:\msys\1.0\src\dlltest>cl test.c dll.lib
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 15.00.21022.08 for 80×86
Copyright (C) Microsoft Corporation. All rights reserved.

test.c
Microsoft (R) Incremental Linker Version 9.00.21022.08
Copyright (C) Microsoft Corporation. All rights reserved.

/out:test.exe
test.obj
dll.lib

c:\msys\1.0\src\dlltest>test
3

Wow that was exciting! Now for the people paying attention, you’ll remember that the test.exe was linked against dll.lib which was built with the Microsoft compiler, and is calling the Microsoft generated dll.dll. Yes you are correct. But always test with a known positive, before you throw in the negative I say…

c:\msys\1.0\src\dlltest>move test.dll dll.dll
Overwrite c:\msys\1.0\src\dlltest\dll.dll? (Yes/No/All): y
1 file(s) moved.

c:\msys\1.0\src\dlltest>test
3

Holy crap! It worked!!!!

That’s right, now I have built a very simple test program that’ll call a DLL function built with MinGW!

And that, is how you can get around a kooky problem where some programs build with one version of a compiler tweaked one way, and you want to use those bits in another program built another way.

Just ask any language refugee from the 1980’s how hard this was to do on the PC platform.. While VMS had a common library spec for all languages, not every platform (MS-DOS,UNIX) was as lucky. But with the rise of things like Windows with DLL’s, and of course NT thanks to the VMS crew it’s in modern systems today.

Let me tell you, linking Quick Basic to C was… not all that much fun. And Turbo C++ was right out!

Anyways I’ll leave you with this much, and at the worst case, much like making bootable CD’s, it’s a good note for me to find this stuff later when I need it.

DJGPP on DOSBOX…

Well I was originally looking around at the new & exciting 16bit support for HX, but so far I’m having little luck… It seems all the ‘cool’ OS/2 stuff it should do just crashes out on me…

I’m hoping to get something going eventually.

In the meantime, I had to check to see if an old MS-DOS favorite, DJGPP was still around.. And not only is it still there, but they now support GCC 4.42!

DJGPP, is simply put a port of GCC to MS-DOS. The best part, is that the compiler, libraries, and even the dos extender are all FREE. The sad thing is that DJGPP hit popularity around the mid 90’s with the rise of Windows 95, and the internet… Kind of killing 32bit MS-DOS applications… However Quake 1 shipped as a djgpp/cwsdpmi application… I’m sure there are others.

So at any rate, I was intrigued that it was still around, so I fired up DOSBox, then downloaded the zips according to the zip picker, read the readme, setup the environment, and I was off and away compiling my trivial hello world.

Sadly for me, I couldn’t sleep, so I then just grabbed the f2c/dungeon stuff and did a compile… I only had to tweak a few things, mostly a garbled long file name thing, but in no time… It was running.

 

I did manage to crash dosbox building the libf2c, but luckily changing gcc to use the -O0 (no optimizations) it was able to build the library… It’s kind of sad generating a 150kb ‘hello world’ type application, but thats the price for essentially statically linking everything….

MS-DOS isn’t the most modern thing out there…. I always wonder if those kids writing a 32bit ms-dos like os ever got anywhere…

Zork via FORTRAN

I don’t know why I even started down this path, but anyways I felt the urge today to break out some Fortran.  The problem is that I acquired Microsoft Fortran 5.0 in university, however… it’s on 5 1/4” diskettes!!!

So that wasn’t going to happen.

So I figured there had to be some kind of GNU Fortran compiler, and there is.. G77.  However it needs to be tied into a release of GCC.  Which sounds great, but I was hoping to build this on a few different platforms, and on my AMD 64 platform it’s GCC 3.3 (SUA), and on my NeXT it’s 2.5.8..  Even in the notes it says you’ll need about 100MB of space to build it, which is also a nice way of saying it’ll take FOREVER.

Then I remembered something we used on the RS/6000 because it was more ‘combatable’ then the Microsoft stuff, as it was derived from the first Unix Fortran compilers… f2c.

First you’ll need the source, which thankfully is still up on the original site  This part is a bit tedious as the source is not in a single easy to get file.  You’ll need to get the source from here.  Once you’ve downloaded the files, I’d recommend saving them somewhere else.. You don’t want to have to right click like wild to get them…  Alternatively I’ll host them all here to save someone all that effort.

Building f2c is really quite simple on any UNIX’like platform.  First you’ll need the f2c source, and unpack it somewhere….  Then you *MAY* have to adjust the makefile.u for the CC/CFLAGS variables as your C compiler may not be gcc or cc, also you may or may not want the –O flags (optimize).  On my NeXT I turned off the optimizations, since this is a 33Mhz machine, and I don’t want to wait all day, and I ran it with –O0 -pipe.  Then just simply run

make –f makefile.u f2c

bash-2.01$ make -f makefile.u f2c
cc -c -O0 -pipe main.c
cc -c -O0 -pipe init.c
cc -c -O0 -pipe gram.c
cc -c -O0 -pipe lex.c
cc -c -O0 -pipe proc.c
cc -c -O0 -pipe equiv.c
cc -c -O0 -pipe data.c
cc -c -O0 -pipe format.c
cc -c -O0 -pipe expr.c
cc -c -O0 -pipe exec.c
cc -c -O0 -pipe intr.c
cc -c -O0 -pipe io.c
cc -c -O0 -pipe misc.c
cc -c -O0 -pipe error.c
cc -c -O0 -pipe mem.c
cc -c -O0 -pipe names.c
cc -c -O0 -pipe output.c
cc -c -O0 -pipe p1output.c
cc -c -O0 -pipe pread.c
cc -c -O0 -pipe put.c
cc -c -O0 -pipe putpcc.c
cc -c -O0 -pipe vax.c
cc -c -O0 -pipe formatdata.c
cc -c -O0 -pipe parse_args.c
cc -c -O0 -pipe niceprintf.c
cc -c -O0 -pipe cds.c
if cc sysdeptest.c; then echo ‘/*OK*/’ > sysdep.hd; elif cc -DNO_MKDTEMP sysdept
est.c; then echo ‘#define NO_MKDTEMP’ >sysdep.hd; else echo ‘#define NO_MKDTEMP’
>sysdep.hd; echo ‘#define NO_MKSTEMP’ >>sysdep.hd; fi
ld: Undefined symbols:
_mkdtemp
rm -f a.out
cc -c -O0 -pipe sysdep.c
cc -c -O0 -pipe version.c
cc  main.o init.o gram.o lex.o proc.o equiv.o data.o format.o  expr.o exec.o int
r.o io.o misc.o error.o mem.o names.o  output.o p1output.o pread.o put.o putpcc.
o vax.o formatdata.o  parse_args.o niceprintf.o cds.o sysdep.o version.o  -o f2c

All being well, you’ll have a new & exciting f2c executable.  I manually just copy the f2c into /usr/local/bin & the f2c.h to /usr/local/include.

Next you’ll need the f2c io library.  Thankfully this one IS zipped up and it’s available here.  Alternatively I’ve got a copy here (better). *NOTE that the ‘official’ version of the lib doesn’t extract to a sub directory… Grr  Extract the library source, and again you may need to modify the makefile to suit your compiler (CC/CFLAGS).  Then go ahead and make the library.

make –f makefile.u

cc -c -DSkip_f2c_Undefs -O0 -pipe etime_.c
ld -r -x -o etime_.xxx etime_.o
mv etime_.xxx etime_.o
ar r libf2c.a f77vers.o i77vers.o main.o s_rnge.o abort_.o exit_.o getarg_.o iar
gc_.o getenv_.o signal_.o s_stop.o s_paus.o system_.o cabs.o ctype.o derf_.o der
fc_.o erf_.o erfc_.o sig_die.o uninit.o pow_ci.o pow_dd.o pow_di.o pow_hh.o pow_
ii.o pow_ri.o pow_zi.o pow_zz.o c_abs.o c_cos.o c_div.o c_exp.o c_log.o c_sin.o
c_sqrt.o z_abs.o z_cos.o z_div.o z_exp.o z_log.o z_sin.o z_sqrt.o r_abs.o r_acos
.o r_asin.o r_atan.o r_atn2.o r_cnjg.o r_cos.o r_cosh.o r_dim.o r_exp.o r_imag.o
r_int.o r_lg10.o r_log.o r_mod.o r_nint.o r_sign.o r_sin.o r_sinh.o r_sqrt.o r_
tan.o r_tanh.o d_abs.o d_acos.o d_asin.o d_atan.o d_atn2.o d_cnjg.o d_cos.o d_co
sh.o d_dim.o d_exp.o d_imag.o d_int.o d_lg10.o d_log.o d_mod.o d_nint.o d_prod.o
d_sign.o d_sin.o d_sinh.o d_sqrt.o d_tan.o d_tanh.o i_abs.o i_dim.o i_dnnt.o i_
indx.o i_len.o i_mod.o i_nint.o i_sign.o lbitbits.o lbitshft.o h_abs.o h_dim.o h
_dnnt.o h_indx.o h_len.o h_mod.o h_nint.o h_sign.o l_ge.o l_gt.o l_le.o l_lt.o h
l_ge.o hl_gt.o hl_le.o hl_lt.o ef1asc_.o ef1cmc_.o f77_aloc.o s_cat.o s_cmp.o s_
copy.o backspac.o close.o dfe.o dolio.o due.o endfile.o err.o fmt.o fmtlib.o fte
ll_.o iio.o ilnw.o inquire.o lread.o lwrite.o open.o rdfmt.o rewind.o rsfe.o rsl
i.o rsne.o sfe.o sue.o typesize.o uio.o util.o wref.o wrtfmt.o wsfe.o wsle.o wsn
e.o xwsne.o dtime_.o etime_.o
ar: creating libf2c.a
ranlib libf2c.a

This will take longer then f2c.. Or at least it did on my NeXT.

Then I just copied the library libf2c.a into /usr/local/lib then ran ranlib over the library again.

Ok now we should be able to build a FORTRAN program.  Let’s try something small.

      program hello
      print *, ‘Hello!’
      end

I’ve tried to preserve the leading 6 blank spaces.  You should be able to copy the above program, and save it as hello.f  Now we should be able to translate, compile and run the program!

bash-2.01$ f2c hello.f
hello.f:
   MAIN hello:
bash-2.01$ cc hello.c -lf2c -o hello
bash-2.01$ file hello
hello:  Mach-O executable (for architecture m68k) not stripped
bash-2.01$ ./hello
Hello!

Awesome!  Now let’s try something much bigger, say some old Fortran source to the old ‘dungeon’ game, better known as Zork!  This source is available all over the place as dungeon-2.5.6.tar.gz, and I’ll provide a link as well here.

Download, and extract the files (gzip –dc dungeon-2.5.6.tar.gz|tar –xvf –) and you’ll have your dungeon directory.  Building this should be pretty simple, if the above program built and ran without errors.  On my SUA (Vista) machine, I had to force the –I/usr/local/include flags to find the f2c.h..  So you may need some tweaking it all depends.

Again on my NeXT I changed the CFLAGS to –O0 –pipe.  On my Vista SUA I had to specify that CC=gcc.

Once done, go ahead and run make.

\ar d libdungeon.a dmain.o np2.o
\ranlib libdungeon.a
cc -s -o dungeon dmain.o np2.o -L. -ldungeon -lf2c -lm
f2c -A -C -Nn802 textcnv.f
textcnv.f:
   MAIN:
cc -O0 -pipe -c textcnv.c
cc -o textcnv textcnv.o –lf2c

If all went well that should be how the last lines look.  We should now have a dungeon executable!

bash-2.01$ file dungeon
dungeon:        Mach-O executable (for architecture m68k)

Awesome!

So let’s enter the game, shall we?

bash-2.01$ ./dungeon
Welcome to Dungeon.                    This version created 30-AUG-90.
You are in an open field west of a big white house with a boarded
front door.
There is a small mailbox here.
>

So, now we have built the f2c translation package, and managed to build a trivial hello world program, and something a little more complex like Dungeon/Zork.

Now I can play with my numerical recipes book with my pseudo Fortran kit.