PCW Today "Langford" #6
Pig in a Poke

Column IndexAnsible Information HomeLangford HomePCW Today

You always think you can give it up, take the cold-turkey cure until at last the craving goes away, but again and again there's a dread tendency to backslide. Just one more tiny little indulgence won't do any harm....

I'm talking about programming, of course. A friend once warned me in menacing tones: "Software is a disease. Never get into software." He spoke from experience, having written his own word processor from scratch in BASIC. Although I laughed ("They laughed when I sat at the keyboard, but then I began to hack the operating system!"), it was already too late. I'd invested in Borland Turbo Pascal 3.0, which had begun to affect the punctuation of my very thoughts. It is a bad sign when you end sentences with semicolons.

Turbo Pascal was a revelation. It created .COM program files quickly and easily, and came in different flavours for all the computers I was using in the mid- to late 1980s: Apricot, PC and even a CP/M version for the PCW. Our infamous indexing program AnsibleIndex used all three, starting as an add-on for Apricot SuperWriter, mutating dramatically to work with PCW LocoScript, and eventually following LocoScript Pro to the PC.

I thought I'd finished with PCW programming after version 4.50 of AnsibleIndex, the one that handled the subtly changed document format of LocoScript 4. However, the temptation keeps returning, and any little thing can set it off.

For example, a copy of the British Amstrad PCW Club's magazine The Disc Drive came my way this year, and I noticed a piece by one Rod Shinkfield on something doubtless known to our more learned readers, but which I'd never heard about: CP/M's secret Limbo group, where the deleted files go.

When writing AnsibleIndex I'd naturally had to tackle access to disk groups 0 to 7. CP/M nominally has 16, numbered 0 to 15; Loco uses the second eight as its own Limbo groups. Turbo offers a neat facility for including "in-line assembler" -- machine code instructions -- so you can write a machine-coded BDOS call to select any normal group through CP/M's "Set User" function.

The occult CP/M Limbo, weirdly, is group 249 (F9 in hexadecimal). You can get to any of groups 0 to 15 with the CP/M command USER, but both USER 249 and USER F9 give error messages. The Disc Drive revealed an unlikely access method using POKE commands in BASIC to tweak the PCW's memory, sticking the byte value 229 into each of the addresses 66480, 64432, 64348 and 64040.

This was ingenious, but a bit cumbersome -- loading up BASIC and all -- and I thought it would be much more fun to pervert the PCW memory with a little Turbo Pascal routine. Turbo provides a built-in array called Mem which maps on to the program-area memory and can be read from or written to with an ordinary Pascal "assign" statement:

 Mem[66480]:= 229;

Oops! That gives an error warning, because the array index has to be a 16-bit Integer variable, whose allowed range is -32,768 to 32,767. (Turbo Pascal version 4.0 introduced Word variables, with the often more useful range 0 to 65,535.) We have to tinker with the address numbers, subtracting 65,536 from each to get "negative" values which look fanciful but do in fact work:

Program Limbo;
 Mem[-1056]:= 229;
 Mem[-1104]:= 229;
 Mem[-1188]:= 229;
 Mem[-1496]:= 229;

This compiles in Turbo Pascal to give LIMBO.COM, which when run in CP/M does indeed magically transport you to the secret F9 group -- as conveyed by the fact that the prompt changes from A> to F9A>. Rod Shinkfield suggests deleting a copy of PIP.COM so it'll be available in the Limbo group, ready for a command like PIP DELETED.DOC[G0]=DELETED.DOC to copy a Limbo file back to group 0. A neat idea. You escape to A> normality with USER 0.

Unfortunately most people don't own Turbo Pascal; and even for those who do, the above still isn't the most elegant approach. This is because of the size of Turbo's run-time library, a collection of standard functions and procedures which means that even a program which literally does nothing at all will still take up 8.5k or so of disk space and spend much longer than necessary loading.

However, most (all?) owners of the old-style PCWs have an assembler program supplied as one of the CP/M utilities. So, obsessively, I looked up my mouldering grimoires of assembly language, and came up with a text file called LIMBO.ASM, containing the following:

MVI M,229

POKE 64480
POKE 64432
POKE 64348
POKE 64040

The POKE macro loads the index register with the supplied address ADDR, and shoves 229 into that address. (I could equally well have written four pairs of LXI and MVI commands, but I'm showing off.) JMP 0 terminates the tiny program. I like the Turbo text editor for assembler programming; if you use LocoScript, the document needs to be converted to ASCII format.

With MAC.COM and HEXCOM.COM from the CP/M utilities disk, the command MAC LIMBO does the assembly, generating the intermediate file LIMBO.HEX -- and HEXCOM LIMBO then produces LIMBO.COM. This tiny resulting program does exactly the same as the bulky Pascal one already described, but in 23 bytes rather than 8.5k.

Until, of course, driven by renewed obsessiveness, I found myself laboriously adding a BDOS "print string" command to ensure that LIMBO.COM displays the all-important message "Copyright (c) Ansible Information, 1999". Yes, software is most definitely a disease.

Column IndexAnsible Information HomeLangford HomePCW Today