One “shock” when trying to build a development system that could re-build my old code with just readily legally available tools (ideally most via Aminet) was the re-discovery that some of my own tools used my own library, aardvark.library. At some point I had moved this to an “defunct” folder on my real A500/A1200, of which only fragments of my final backup is currently available to me. There should be a CD-R somewhere with my final A1200 environment…

The second shock was I was unable to re-build the library, for a myriad of reasons.

I had decided to make a library that would make it easier to handle trackdisk.device and historically, on Workbench 1.3 (and earlier) systems the documentation says that “I/O ports” and “I/O requests” should be created by code in something called “amiga.lib”. So I used “amiga.lib”.

I needed to rebuild “aardvark.library” so I could rebuild two disk writing tools I needed to rebuild my first target project, “PutBoot” and “TDWrite2”.

When I tried using PhxAss and BLink to using build my library with amiga.lib BLink crashed… hard…

I spent 2 days towards the end of February 2021 fiddling with BLink switches, trying different assemblers and linkers, corrupting my hard drive file (backups are useful, people!) and so on… Real trouble. It wasn’t just the library I was working on, but my disk writing tools and even my first revisited project. I revisited my experiments a couple of weeks later (mid March) and tweaked some more.

I thought it would be quick to set up an environment, do a quick test on a known working “project” before starting to re-visit a project I never finished back in the 90s, and instead it took be two to three days worth of work to get to the point of being able to write a custom floppy disk boot block with my resurrected tools and longer to be happy I had a configuration I would use moving forward.

During this process I started thinking about amiga.lib and whether I needed to keep using it. A browse of exec.library documentation highlighted “Version 36” Exec (Kickstart 2.0) introduced range of system calls that “new code” could use instead of amiga.lib.

So instead of CreatePort (amiga.lib) I can use CreateMsgPort (Exec v36+), instead of CreateExtIO I can use CreateIORequest, and corresponding “Delete” calls. This lead to some interesting “soft” crashes and debugging, but I got it working. Invaluable tools included a debugger called “DT” (sticking with legal tools and Aminet) and a modern clone of HP’s “16C” calculator. Why did HP create a programmer’s calculator capable of 64-bit processing in the early 80s? Working with 32-bit math in hex was so useful. Check out SwissMicros DM16L for more info.

Turns out if you make calls to another library from your own you need to restore the “pointer to yourself” that you overwrite making the system call. Oops. Wasn’t a problem when I was using amiga.lib, just a blob of code that linked to my own.

So what did I do to get a working build of my library?

First of all, working around a few oddities of the “original” NDK39 files I created a couple of custom includes, execfuncdef.i and callmacros.i relating to system calls and the way you define them.

This is my new “execfuncdef.i” which I put into an “include” folder and the top of my programming source tree. I “include” it first.

; required for exec/exec_lib.i

FUNCDEF         MACRO
_LVO\1          EQU     FUNC_CNT
FUNC_CNT        SET     FUNC_CNT-6
                ENDM
FUNC_CNT        SET     5*-6

This is my starter “callmacros.i”, again into my “include” folder. This is now typically my second include.

; to make OS calls easier to read

CALLEXEC        MACRO
                move.l  4.w,a6
                jsr     _LVO\1(a6)
                ENDM

CALLDOS         MACRO
                move.l  _DOSBase,a6
                jsr     _LVO\1(a6)
                ENDM

Not directly related to the library, but a file I discovered very quickly I had “lost” over time, a file “my_macros.i” which I know had some macros that help with creating “copper lists” in code. I probably had some other things in here originally. Because I had to reverse engineer the macros from an old “binary file” I left a note at the end.

; reverse engineered - hope this is okay

cmove           MACRO
                dc.w    \2
                dc.w    \1
                ENDM
cwait           MACRO
                dc.b    \1
                dc.b    \2
                dc.w    $fffe
                ENDM
cend            MACRO
                dc.w    $ffff,$fffe
                ENDM
;cmove value reg bin reg value
;cwait a,b bin a,b,ff,fe
;cend bin ffff fffe

After creating some needed custom include files, more to fix an issue with one of the assemblers I tried, I renamed two macros in my library source code “push” and “pop” to “pushall” and “popall”. This caused a lot of changes.

I discovered for some reason the NDK39 includes didn’t include a BAUD_MIDI value, so I defined it myself to support the MIDI routines also in my library.

Ripped out “external references” related to amiga.lib.

Replaced the calls to amiga.lib functions to Exec calls using CALLEXEC. This caused a bug because calling Exec means changing the A6 register, and there was a case of my code not aware A6 was no longer my own library pointer as it had been when I’d used amiga.lib.

At first I built a new “makelib.sh” C-Shell script to use PhxAss and PhxLnk instead of Devpac and BLink, but eventually settled on creating a Makefile for “vasm” and “vlink” from the VBCC suite. This file would include options for the assembler to find my own includes first, then NDK include files.

Also moved some old legacy files into a sub-folder (for historic reference) and renamed the main source file which I think I had to do to get the Makefile to work.

To accompany this article there are two LhA archives. These are not required if you use the “quick setup” scripts.

To manually setup, download these two archives to the “AmigaDev_XFER” hard drive area of FS-UAE and extract.

Cd Work:
MakeDir prg
Cd prg
Lha x xfer:t81t_include.lha
Lha x xfer:aardvark_lib.lha

We will build up the “prg” directory on the “Work” partition over time, starting with the three custom include files (only two needed for this project, and the library code. The “quick setup” scripts add a couple of other bits too, which we’ll look at in the next blog post.

The “Makefile” for the library expects the “Work:prg/include” path for custom include files (two places) and the version linked to this blog post is configured to use the AmigaOS 3.2 NDK files. You could adjust the path to use the NDK39 files based on the original instructions. Both appear to work equally well here.

# AmigaOS 3.2 version
ASFLAGS=-devpac -Fhunk -IWork:prg/include -IWorkbench:NDK32/Include_I

# AmigaOS 3.1 with 3.9 NDK version
ASFLAGS=-devpac -Fhunk -IWork:prg/include -IWork:NDK39/Include/include_i

A better option, and is the route taken by the “quick” scripts previously provided, is to have set up an “assign” and refer to it in the Makefiles. Notice the “quick” scripts are based on the 50/50 hard drive partition split and the NDK files are copied to the Workbench (system) drive.

# This line goes into S:User-Startup for AmigaOS 3.1 with 3.9 NDK
Assign >NIL: ndkasminc: Workbench:NDK39/Include/include_i

# This line goes into S:User-Startup for AmigaOS 3.2
Assign >NIL: ndkasminc: Workbench:NDK32/Include_I

# This is the new ASFLAGS line for Makefiles
ASFLAGS=-devpac -Fhunk -IWork:prg/include -Indkasminc:

To build and “install” the library, a fairly typical sequence in the modern world is used.

Make
Make install

Let’s take a look at the Makefile to see how it is structured. We’ll use this as a sort of “template”.

# Makefile for aardvark.library

AS=vasmm68k_mot
ASFLAGS=-devpac -Fhunk -IWork:prg/include -Indkasminc:

LD=vlink
LDFLAGS=-b amigahunk

%.o: %.s
        $(AS) $(ASFLAGS) -o $@ $<

aardvark.library: aardvark_library.o
        $(LD) $(LDFLAGS) -o $@ $<

all: aardvark.library

install:
        Copy aardvark.library Libs:
        Copy aardvark_lib.i Work:prg/include

clean:
        Delete aardvark_library.o
        Delete aardvark.library

First of all this sets the AS variable to “vasmm68k_mot”. This is the “vasm” assembler for “m68k” CPUs with “Motorola” syntax.

Next up the standard flags passed to the assembler. We start with “-devpac” because the original sources were written and used with HiSoft’s Devpac assembler. Next we specify “-Fhunk” to tell the assembler to generate Amiga “hunk” object files. Then we put in two include paths, first our own files, then the NDK using an assign we use to insulate ourselves from NDK layout differences.

Next we specify the linker, “vlink”. Both “vasm” and “vlink” come from the “vbcc” C compiler package.

The final variable contains flags for the linker and here we only need/want one “-b amigahunk” which tells the linker to produce a standard Amiga executable in its “hunk” format.

Now we start on rules. The first rule tells the make tool how to make object files from source files, and the second how to make aardvark.library from the object file aardvark_library.o. The “recipe” lines underneath as you may know should start with a “tab” character. Basically just call the assembler/linker with the standard flags.

The “all” rule tells the make tool what to do if just called with “make”. Build aardvark.library.

The “install” rule tells the make tool what to do if called with “make install”. The aardvark.library file is copied to the Amiga “Libs:” assign and the custom include file is copied to our own include directory.

The “clean” rule tells the make tool what to do if called with “make clean”. This removes “binary” files created by the Makefile and was used before making an LhA file ready to “distribute” on this blog.

This is step one on the path to rebuilding an old T81T production, code to write to custom format floppy disks. Now we need something to drive this code.

#14: I created a library? Why did I create a library?