1 – Exec.library. Meilleure compatibilité avec 68060, meilleure compatibilité avec émulateurs MAC révisé, plus besoin de prepareemul ,ROMWack internal debugger modifié, retrait de code « task free » inutilisé dans Exec, debug FreePooled(), AVL tree support enlevé.
2 – Expansion.library battclock.ressource, utility.library, cia.ressource modifiés compatibilité meilleure avec 68060, versions 68020 et 68000 de utility library réunies.
3 – Scsi.device (scsi.device comme son nom ne l’indique pas est en fait un port IDE) corrections de bug, compatible commandes LBA48, atapi et cartes compact Flash, commandes 64-bits TD64 compatible, support encore meilleur des gros disques durs modernes.
4 – Graphics.library corrigé et nettoyé en profondeur, fonctions blitter débugguées ClearRegionRectangle() simplifié, plus rapide,
conversions « chunky to planar » totalement réécrites et désormais entièrement faites par le CPU plutôt que le blitter, vitesse doublée, bugs mémoire liés au changement de résolution corrigés.
5 – Intuition.library, compatibilité avec SAS/C compiler, fenêtres intuition peuvent être sorties de l’écran, les fenêtres sont placées sous le pointeur de la souris.
6. Layers.library, gameport.device, keyboard.device, input.device,
timer.device and console.device
Let’s continue right here. For layers.library, there is nothing to
report as already mentioned. It is newly-compiled with better settings,
some fine-tuning and a bug in InstallClipRects (). The problem was
that at least one program assumed that layers.library recalculated the
ClipRects when installing a ClipRect. Layers V45 did that only if the
ClipRect differed from the one currently installed. Said software,
however, has changed the Cliprect « under the butt » of layers and then
reinstalled. You just do not do that…
Gameport, input and keyboard devices are unchanged except for details.
That was a coherent ROM module, but for the sake of better modularity,
I pulled them apart, and they are now individually built. Furthermore,
they now support NSD. I’m not a fan of that, but at least you have a
Just like the timer.device, which is unchanged except for NSD support.
Console.device also includes NSD support, a fix in CSIm (the sequence
that changes the crayons in the console), and another fix to handle
semaphores that was just a bit confused there. Otherwise, it is
identical to the version that came with 3.9.
7. FastFileSystem (FFS)
More new components. The FFS, FastFileSystem. This is still the
Amiga FFS, based on the same assembly code we had before, with a
couple of bugs fixed here and there, plus a couple of new features.
First, some bug fixes: The bitmap size computation contained an
off-by-one error, which, in rare cases, triggered running the
disk-validator every time the FFS was booted. There are now additional
size checks for the size of the volume name.
Concerning filename sizes: The FFS now supports two new « flavours »,
namely DOS\06 and DOS\07, which support « long filenames » using the
same layout as in AOS 4. Filenames can now be 106 characters long.
This means, in worst case scenarios, that the FFS needs to allocate an
extra block for holding the comment as well, which required additional
Another new feature is that the FFS speaks TD64, NSD and SCSI natively;
there is no longer the need for NSDPatch as FFS is (in most cases)
capable of figuring out the command set itself. Hence, if you run a
hostadapter based on the omniscsi, or the Oktagon, or Phase5 boards,
large partitions and large harddrives are no longer a problem.
Just a small warning: If you make your partitions large, I also
recommend enlarging the block size. I suggest 4K blocks for
flash-based media, as otherwise the bitmap grows too large and thus
slows down system booting as it initially goes through a minimal
validation step requiring the entire bitmap to be held in memory.
Furthermore, 4K blocks also help wear-leveling of the flash disk as
they organize their internal memory in larger pages than the usual 512
SCSI transfer needs to be enabled manually, but HDToolBox can do that
for you. Or you can use the mount option « DirectSCSI=1 » if you mount
Concerning mount options, there are two new ones: « EnableNSD » enables
usage of the NSD command set, which is « on » by default, but can be
turned off in case the firmware of the hostadapter has problems with
it, and « Superfloppy », which allows automatic sizing on removable
media. Say you have a ZIP drive that supports both 100MB and 250MB
media, *do not* put an RDB on it; mount it with « Superfloppy=1 » and
FFS will figure out the drive geometry itself, and also resize the
drive geometry, just as it does when switching between high density
and double density disks.
Last but not least, there is one « hidden » feature we do not support
officially, and this is DOS\08. Nobody remembers how, but OS 3.9
already supported it, albeit incompletely. It is an FFS variant that
supports long filenames limited to 54 characters, but is backwards
compatible to the older flavours of FFS such that you can easily
upgrade from DOS\03 to DOS\08, gain additional length, but do not need
to reformat. However, unlike the OS 3.9 variant, this version works.
We still do not support it officially as Diskdoctor (another story for
another article) does not support it, but otherwise it works well.
8. Bootmenu and Syscheck
A few more components. On the one hand, we have the bootmenu, which is
also responsible for displaying non-existent expansion boards in case
of a misconfigured system. Similar to that of OS 3.9, bootmenu can
switch between PAL, NTSC and 31kHz modes, but the latter is only
available on AGA and not ECS machines. Interestingly, the 3.9 variant
had tried to install DBLPal on the ECS boxes, which of course did not
If you boot from the 31kHz modes, you should still load the
appropriate monitor driver, because otherwise the modes are missing
the names. Logically, the ROM has no localization information, which
only loads into the system with the monitor drivers.
Unlike the bootmenu of 3.9, Nessie is missing (I already said that
there are no Easter eggs this year), but Syscheck does not show the
boards that can not integrate it as a « defect », but only as not
configured. This happens, for example, if there is not enough space in
the AutoConfig area. The screen only turns red when the memory on one
of the RAM expansions is really malfunctioning.
9. WBFind and RAMLib
A completely new ROM component is « WBFind », even if one does not find
it under this name in ROM, but instead under « workbench.library » and
« icon.library ». The purpose of this component is as follows: As soon
as someone tries to initialize one of the above components, this
component makes sure that the corresponding library is searched for
and initialized on all mounted media, and it is also responsible for
the nice « Please insert a volume containing …. in any drive »
Two comments for the experts: First, this sounds redundant, since the
OS itself can load libraries from hard disk, so why add WBFind? And
second, why those names? WBFind previously existed on the A4000T.
First: The difference is that « ramlib »–this is the part that normally
loads the libraries from disk–looks only in LIBS:. But we wanted a
mechanism where Workbench can be loaded from the Install3.1.4 disk if
you did not read the manual again and forgot to install it; ergo, the
advanced search path, and WBFind.
Second: Yes, that was the case with the A4000T, where ROM space was
too small. But the implementation was a completely different one;
namely, as a patch in OpenLibrary (), which then extended the search
path itself. Unfortunately, this approach had the disadvantage that it
was a patch, and this in particular collided with other patches in
OpenLibrary. If you install things like BetterOpenLibs for instance,
deinstalling workbench.library will de-install BetterOpenLibs after
uninstalling the patch, and that may not be the point of the matter.
On the other hand, « WBFind » works without any patches and loads the
library « piggyback » on the back of a ROM component of the same name
instead of RAMLib.
Speaking of RAMLib, there were two minimal changes: First, RAMLib no
longer uses SIGF_SINGLE because it needs several libraries in its init
code itself. This has already been fixed in 3.9 times by SetPatch, but
is now official. Second, the stack is increased, giving the init
functions of loaded libraries a little more « air. »
One of my favourite playgrounds is, of course, Shell. Since I bumped
the version number, there must be something new. The new feature is
that pipes are built-in, so you no longer need support from external
commands. This sounds like a minor change, but the big advantage is
that any such external command does not have to repeat parsing of the
rather obscure Shell syntax. Shell itself does it all. In particular,
this goes for all the strange rules on backticks, asterisks and quotes
that are easy to get wrong.
Pipes require support from Queue-Handler, which is included in 3.1.4
as a handler that needs to be stored in L: and has to be mounted on
startup. Be aware that you need to use this particular pipe handler,
and not any of the alternatives you find in Aminet. The Queue-Handler
in 3.1.4 was completely rewritten from scratch and unrelated to
Commodore’s implementation or any of the versions on Aminet that all
have their little problems. The most prominent problem is handling of
« break », i.e. if you abort one of the ends of a pipe. Queue-Handlers
typically forget to terminate the other end of the pipe, causing CPU
hogs or other problems, so make sure you get the right handler.
The syntax is as it used to be: A « | » connects the output of the left
program to the input of the right program, such that, for example:
list | more
pipes the output of list through the pager. Additionally, we have « || »
as command, which concatenates the output of the programs to the left
of the double-bar to the program on the right, creating a new common
Last but not least, there is one new built-in command, and that is (.
No, no typo, the name of the command is really an opening bracket. It
takes ) as the last argument and executes all commands within the
brackets in a sub-Shell. This sounds curious, but has its use in
combinations such as:
(list || dir) | more
which concatenates the output of list and dir, and then sends it to
Pipes have other uses, of course. For example, the commands « sort » and
« search » also operate in pipes, such that:
list | sort
gives a sorted output of list. There is no new option required for
list for doing it–the existing commands are sufficient. Similarly,
« search » in a pipe looks for a particular string coming through the
pipe, and if so, prints it.
A couple of features had to wait as they came in too late. In my
private experimental version, there is also a variant of the Execute
command that can also read its input from the pipe, such that:
list lformat= »…. » | execute
executes a command sequence constructed by « list » without requring a
Also, Tab expansion had to wait. There is a little bit of experimental
code around (here and there) and a design as well that works quite
differently from the currently existing hacks. In particular, I
dislike the idea that the console has to do the expansion, because it
(again) has to parse the pesky Shell syntax, and getting this parsing
right is non-trivial. So the Shell shall do it, and this is precisely
the idea. One way or another, it requires modifications to the console
and also the Shell, and we ran out of time.
11. Ram-Handler, diskfont.library, asl.library and bullet.library
The ROM components would almost have been dealt with, because nothing
has changed with dos.library. The Ram-Handler has done a bit,
especially the treatment of soft links, which now works, and the Ram
Disk shows actual utilization and not just 100%.
Of course, there are still disk-based components and holes; maybe I’ll
start with diskfont.library and asl.library. Diskfont had a bug
(‘built’ by me) in the 3.9 variant that caused the tags of fonts to
not land properly in the cache. Luckily, there are hardly any fonts
that use this feature to carry around additional metadata. Otherwise,
the cache still exists, but has been given a new version number and
will be rebuilt once at the first call.
The Diskfont API, which is compatible with OS 4.0, has been enhanced
with features that allow direct access to a glyph engine such as
« bullet » (for Compugraphic fonts). Under 3.1.4 this does not use a
program, but at least you can now let letters render individually, if
it feels responsible for a component.
ASL has learned a few new tags from OS 4.0, but is largely unchanged.
It’s just compiled a bit differently and has become shorter–perhaps
like some other components as well.
We once had in diskfont and ASL (as a remnant of OS 4.0) support for
« code pages » in the code, so you could not only be able to use fonts
like Latin-1. I have to admit, though, that this experiment backfired
so much that all this stuff flew back. This requires much more
thorough investigation of all the side effects and implications that
go down to the file system (unfortunately), and I still do not have a
really good idea how that could work. At least not like we tried it.
The bullet.library (Compugraphic) has not changed much except for a
few minor optimizations. Here, Olaf had thoroughly cleaned up.
Nevertheless, this is the rather terrible legacy code that Commodore
probably bought cheaply. In particular, the code has the problem of
using variables with external binding (commonly called « global
variables ») so that two tasks that use bullet at the same time step on
each other’s feet. Olaf fixed that with some magic and craftsmanship,
and that version is in 3.1.4.
The most important change for Compugraphic is not in the
bullet.library, but in the inconspicuous « if.uc » file, which contains
the translation tables from ISO-Latin to Compugraphic encoding.
Apparently partially incomplete, so that certain fonts were rendered
incomplete. One of our beta testers (Mikhail) has made a point of
completing the spreadsheet after coding out the code. In fact, the
whole corner « Compugraphic » is rather undocumented and opaque.
12. Workbench.library and icon.library
On to the next components: workbench.library and icon.library. If you
look in the ROM contents, you will find two components with these
respective names. However, they are not really the libraries; but
loaders. Hence, if someone opens one of the libraries, what the ROM
really does is load the corresponding component from disk. The A4000T
already did something similar, though the corresponding component was
called « WBFind ».
So, a few questions (maybe):
*) Why is this done in the first place? After all, the « RAMLib » OS
component is already responsible for loading components from disk, so
why create a new component for that?
*) Why is it done differently than in the A4000T?
First of all, RAMLib unfortunately only looks in the ROM, and in LIBS:,
but this is probably not enough. We also want to provide a option so
the user can re-insert the « Install » disk and get workbench.library
from there and have a bootable system in all cases.
Secondly, the A4000T « WBFind » component worked differently. It
installed a patch in OpenLibrary() such that OpenLibrary also looked
in different paths, and then removed the patch as soon as Workbench
was loaded. This sounds trivial enough, but it caused a problem in the
event that the Startup-sequence installs something into OpenLibrary().
Then, if WBFind removes its patch, it typically also removes any other
patch that was installed in the Startup-sequence, and that is
something that certainly causes a surprise. A typical « victim » of
WBFind on the A4000T is BetterOpenLibs. One more reason for avoiding
patches whenever possible.
RAMLib itself also has some (minor) changes. First of all, it no
longer uses SIGF_SINGLE for its own process communication. This is
because some LibInit() functions of disk-based components use this bit
itself. Secondly, the stack size of RAMLib has been extended to give
such libraries a bit more « headroom ».
Why all of this in the first place? First of all, there’s simply not
enough ROM space. One could, in principle, base this on the specific
Amiga model which of the two libraries are in ROM and which are in RAM,
but this complicates deployment a lot, and also reduces testability as
(in any support case) one would need to ask, « Which ROM type is
deployed? ». So keep it simple and use the same configuration for all
Secondly, and (probably more importantly), it is easier to update the
two components without touching the ROM. In fact, I would have
preferred to remove other components from ROM, such as audio.device,
the mathffp.library and mathieeesingbas.library. None of them are
required to bootstrap the system, and it would have made upgrading
them easier as well.
Not this time, though. We will probably do that later, as Olaf was
afraid that some third-party firmware may depend on them. We may get
more experimental later. For workbench.libary and icon.library, we at
least had some experience that this does not harm anything.
13. Math libraries
Math stuff. Yes, there are new math libraries (again). Two of the math
libraries are unfortunately in ROM. mathieeesingbas and mathffp. For
reasons beyond me, mathieeesingbas was even initialized during
bootstrap, even if it was not needed. This had several bad side
effects, such as having a non-FPU version of the library on the 68060
as the library became active before SetPatch, so the 68060.library had
to clean up behind it. Another problem was that there were (again)
multiple versions of the same library, i.e. with different build
options depending on the target model. Now, there is one unified code
per library, and not multiple.
As far as mathffp is concerned, the library ran (on purpose) into a
division by zero exception in case someone wanted to divide a floating
point value by zero. This is, however, not the way floating point
should work. Instead, it should return INF or -INF. Now, mathffp does
not have either, so instead HUGE_VAL or -HUGE_VAL is returned. Then
again, mathffp is not very suitable for numerics in the first place as
it does not have denormalized numbers either. The whole documentation
for mathffp was quite opaque, too; for example, it claimed that
FFPSub() subtracts one argument from another (so far, so good), but
not which argument from which. For some strange reason, the arguments
were documented the wrong way around compared to the IEEE version,
causing even more confusion. So this was cleaned up–namely, the
documentation. The RAM counterpart (mathtrans) was only mildly
extended to use a larger Cordic table for log and exp such that
results are a bit more precise. Yet, the whole mathffp/trans library
collection failed any serious test(s) regarding numerical stability,
so just avoid, avoid, avoid…
Mathieeesingbas I already mentioned, but there is one additional trick
the IEEE libraries learned. Similar to « jumpy, the magic timer device »
we now also have « jumpy, the magic math libraries »: That is, if at
some point after math libraries initialization, the FPU becomes
available, the math libraries reinitialize themselves and switch to
the FPU code. And vice versa. There is still support for the
fpsp.resource which comes with the MuLib libraries, so that did not
Mathieeesingtrans did not change, except that it was a major headache
to compile it, given that the SAS/C compiler actually does not support
single precision IEEE math. This is probably the topic of another
episode as it required major magic and trickery.
Mathieeedoubbas and singbas only changed insofar as they configure the
FPU a little differently, namely « extended precision, round to zero. »
The results of the computation are still the same as the last
operation in each call to the math code–still implying a rounding to
double or single precision–but the advantage of the different
rounding mode is that a task can open both libraries simultaneously
without a conflict, which was not possible before. You either had to
use single or double precision, but could not mix them (safely,
without much additional trickery). « Round to zero » is not a very
sophisticated rounding mode, though it fits the CPU implementation of
the math libraries and is thus consistent. Probably not quite ideal,
I do not recall any changes to mathieeedoubtrans.
Datatypes: There is a new datatypes.library which inherits numerous
vectors from the OS 4.0 datatypes, including functionality to read the
source from memory rather than a file. Actually, if you ask me, this
is probably a bit overdesigned as existing features in the dos.library
could do the same. But, well, why not…
The datatypes themselves are beyond what’s in OS 3.9, with many, many
issues addressed. Both the 8svx.datatype and sound.datatype can now
play stereo. Actually, sound.datatype somehow made strange assumptions
about the memory type (« if it is not Fast RAM, it must be Chip RAM »)
that were not entirely true. It only worked because the compiler did
not optimize so well and the code contained plenty of duplication. One
issue, however: The SVX (without « 8 ») datatype from Aminet does not
like it, simply because it does not follow the right protocol when
allocating memory for the sound.datatype, so just delete this. 8svx
will take over.
The picture.datatype can handle RTG graphics just fine (as did the
3.9 counterpart), but had issues fixed concerning the placement of the
graphics. If the image height was less than the screen height, the
graphics would be rendered incorrectly. There is one difference,
though; namely the interpretation of
ENV:classes/datatypes/picture/forcev43. What used to be a simple « yes »
or « no » choice is now a list of programs that should be promoted to
the V43 (OS 3.5) interface which allows rendering of RTG graphics.
The list contains the usual suspects by default (« MultiView » and
« IPrefs »), but can be enlarged as needed. See the FAQ for details.
Animation had a lot of issues, and caused a lot of trouble. First,
buffering was simply incorrect such that one could not « go back » in an
animation without causing strange artifacts. Then, it was a CPU hog
because the main loader engine used « busy waiting »–a really bad
design in a multitasking operating system. It also had issues
rendering screen formats not native to the system which are now
automatically promoted. Thus, a HAM8 anim will now render correctly on
an RTG screen on an ECS machine, or will even be requantized on an ECS
screen. Hence, many more anims now play fine.
The anim.datatype (which uses the animation.datatype) also had issues
concerning the interpretation of the frame count; namely, it could be
off by two frames.
What we did not modernize (but only bugfix) were the gradientslider
and colorwheel gadgets. Sorry, this was just too much work. But at
least, both gadgets now interoperate with ReAction, which did not work
very well with the previous (V40) versions; so that’s at least
There is neither a new text.datatype, so there is unfortunately no
« copy/paste » in text. This is because we do not have ReAction, and the
version that supports this requires ReAction. Too bad. Some parts
would need to be rewritten to work on GadTools, but there was no time
What was common to all datatypes was, however, incorrect locking in
the library handling functions such as LibOpen or LibExpunge. All
implementations had race conditions which could leave a task running
in one of the functions while the library is flushed under its feed.
This was also fixed all along.
There are a couple of changes in (and around) ARexx. First, the
rexxsyslib.library worked fine in reopening the
mathieeedoubbas.library over and over again, but unfortunately ignored
the result, and only used the first library base. However, with the
new « jumpy, the magic math library » the library base might have
changed because the FPU was turned on. Not any more.
Then, we had a bug in FindDevice() which prevented ARexx from locating
scripts in multi-assigned… (ahem) assigns. Instead of using
dos.library functions, ARexx there used Forbid()-locking for the
Finally, we had an issue in WORD(). It only took two arguments, and
not two or three arguments; so this was fixed.
Also, there are changes for all the commands in Rexxc. They now use
ReadArgs() consistently, and hence support « ? » as an argument to query
the arguments they take. « Rx » is a special case, but had special
issues. If you ever tried to execute a script from « Ram Disk » like
rx « Ram Disk:script.rexx »
you probably know. The above does not do what you think, but tries to
execute the string in quotes as ARexx commands directly. To resolve
that, « rx » takes a new argument « script » that enforces the argument in
quotes to be a script and nothing else. This requires the new
rexxsyslib.library as well. Hence:
rx script « Ram Disk:script.rexx »
does the right thing, and is also used by the Shell implicitly for
ARexx scripts. The « script » argument brings another change, namely the
interpretation of the script arguments. It then uses « Shell-style »
syntax, meaning that « * » » is the quote, because * is the escape
character, unlike in rexx, where « » » » would indicate the quote (count
the quotes!). This is useful because:
rx script « Ram Disk:script.rexx » « $arg »
expands correctly, even if the variable $arg contains blanks or
quotes–which are escaped by the Shell with an asterisk; not a double
Last but not least, since OS 3.9, rexxsyslib.library contained the
« RVI » (ARexx variable interface) which allows setting Rexx variables
from Rexx hosts. This used to be in amiga.lib (for strange reasons).
The OS tools such as Workbench and Ed (but also Multiview and some
datatypes) no longer link against amiga.lib, but use the RVI in the
rexxsyslib.library directly, avoiding code duplication.
More news on devices. We start with a seemingly harmless device:
clipboard.device. It (temporarily) keeps characters for copy and paste
operations, or offloads it to disk. Strangely, it defaults to the Ram
Disk, which is probably not a good idea if RAM is low. Anyhow. The
clipboard.device is new. Really new. The problem with the old design
was that it used Forbid()/Disable() locking, and hence did not work
« so well » with multitasking. I am not even clear whether this always
worked as intended, as the clipboard.device also made file operations
to write clips to disk, and hence broke forbids.
The v45 clipboard.device uses semaphores. This is a bit touchy as one
must not run into a semaphore conflict, aka « deadlock ». It seems I
There are a couple of minor tweaks in the serial.device, especially to
take precautions for some 68040 systems where blocking interrupts by
writing to custom chips may leave a chance for a « delay slot » into
which an interrupt may still be triggered. CMD_WRITE was also
unnecessarily slow by requiring going through an interrupt for
writing the first character. This is no longer necessary. Parity
check was partially missing on CMD_READ, depending on the
There are only a few changes in the parallel.device. The device used
to add a sleeper port to the public port list, though who should look
for it there as it is only used for internal operations? In fact, this
was only used to initialize the port; so it was not needed.
What is common to all devices is that they support NSDQuery, i.e.
support requesting the device command set. I am not a big fan of this
mechanism as it has a couple of design issues, but it is too late to
fix this, so we keep it (unfortunately).
The printer.device is a story of its own, so I will report separately.
A longer story.
The mfm.device for CrossDOS trashed registers on some calls. It could
also crash in case the code failed to initialize the disk geometry.
CrossDOS does, but not necessarily any other user. Also, its stack was
really too small.
Last but not least, narrator.device: No, it is not part of 3.1.4.
Unfortunately. I was able to contact its owner, SoftVoice, who are
still in business. Unfortunately, they were not willing to license it,
so we have to do without it. Too bad. The same goes for the
translator.library. In case you wonder, SoftVoice also provided S.A.M.
(on C64 and the Atari 8-bit series). I would have loved to see, err,
hear, narrator again.
Handlers are one level above devices, and reside in L:. Their
interface stems from Tripos, and hence a lot of BCPL legacy is found
here. The very last snippet of BCPL code is, however, finally gone.
3.1.4 includes a completely new Aux-Handler that was written from
scratch in C. For those that do not know: Aux is the « serial »
counterpart of CON:. Unlike SER:, which only reads and writes
characters, AUX: also buffers lines and includes a couple of keyboard
shortcuts for editing text. Hence, you can start a new Shell on a
serial terminal with:
The AUX: handler here now also handles ^C through ^F more carefully,
and ACTION_WAIT_FOR_CHAR allows buffering of multiple requests.
Speaking of SER:, this is implemented by the Port-Handler, which is
also responsible for PAR: and PRT:. It is also new and fixes many
issues. The previous version crashed if multiple read or write
requests were piled up, and hence did not support asynchronous I/O at
all. It also tries to identify the nature of the device it talks to,
and hence changes its interface to either speak « parallel », « serial »
or « printer » language, even if you connect it to another device–which
is also a new feature. If you open « SER: » with the additional « path
name » NOWAIT (i.e. Open(« SER:NOWAIT »)), then SER: will not block when
no characters are in the input buffer of the serial port. It will
The full set of options encoded in the path name is
« BAUD/N,CONTROL,RAW/S,NOWAIT/S,TRANSPARENT/S,UNIT/K/N », where « BAUD »
sets the serial speed, and CONTROL sets the serial parameters, e.g.
« 8N1 » is 8-bit, no parity, 1 stop bit. NOWAIT we discussed above. RAW
turns off the translation from LF to LF/CR pairs for the printer, and
TRANSPARENT disables the translation of Amiga-specific (ANSI) control
characters to printer-specific sequences. UNIT sets the unit number.
For some strange reason, the old Port-Handler neither supported
ACTION_WAIT_FOR_CHAR, which was a logical packet to support,
especially with the serial console. Strange…
Also, a ^C sent to the requesting process aborts the I/O interface. If
you previously sent a string to PAR:, but the printer was not ready,
the system deadlocked because the process cannot be aborted waiting
for PAR: to return, which it never did…this changed now, and even a
« LIST >PAR: » can be safely aborted.
Speaking of speaking, there is a revised Speak-Handler, though no
narrator.device for it. There is not much new, except for a couple of
minor fixes. ^C to abort speaking did not work quite right, it also
stayed in memory permanently, and parsing of opt/ as well.
The queue-handler is completely new and unrelated to any former
QUEUE-Handler. It handles abortion of queues (« broken pipes »)
correctly now, and this is the queue-handler you should use for the
new shell. Even though there is no « IN: » or « OUT: » as in OS 4, there
is « PIPE: ». That is:
type s:foo | type pipe: hex
is a complicated way to type s:foo in hex. The « PIPE: » filename of the
second « type » command accesses the input pipe.
list lformat= »… » | execute PIPE:
creates a list of commands with list, and executes it with « execute ».
Here, PIPE: also accesses the input stream (reading end) of the pipe.
PIPE: can also be used as the writing end of a pipe, i.e.
type s:foo to PIPE: | type pipe: hex
works too; just more complicated. Hence, no need for « IN: » or « OUT: »,
just write « PIPE: » and it will figure out into which end of the pipe
the stream will go–reading or writing.
Other than that, there are also named pipes, as before. They can be
read or write by name. For example:
type s:foo to pipe:bar &
type pipe:bar hex
starts the first command in the background, and then reads from the
same pipe, with type again. Even more complicated than before, but
does just the same…
There are more new handlers: CrossDOS, and the CDFileSystem. I will
cover them later in a separate blog.
Shell Pipes: We had this already. It is an old feature in a new
interface–there is no longer the Pipe command because the Shell
handles it all by itself. The advantage is that there is no need to go
through a second-step parsing, which is particularly tricky with the
awkward Shell language. Depending on the Pipe command you used, some
recognized tokens like STDIN: or STDOUT: to access the input or output
stream directly. Note well that there is no « device » named STDIN: or
STDOUT:, this was simply « guessing and token recognition », to allow
such things as:
list | type stdin: hex
which would give a directory listing in hex. Don’t ask what this is
good for; it is just the simplest example I could think of. « Type »
does not support « reading » from stdin, so you had to use this token.
With 3.1.4, there is no « Pipe » command, and there is no longer any
magic token that represents a stream. But you can do the same by
similar means, by a feature of the qeue-handler. If it is opened
without any filename, it rather reads or writes (depending on how it
is opened) from the currently active input or output pipe.
Sounds complicated? Not really, it is quite straightforward. The above
list | type pipe: hex
Hence, list pipes its output to the pipe, and « type » picks it up there,
via « PIPE: ». There is no ambiguitity and « PIPE: » is context-sensitive;
i.e. you can run the same in two Shells Simultaneously without any
chance of confusion because « PIPE: » knowns where the input or output
comes from or goes to, and PIPE: also knows whether it should operate
from the reading or writing end of the pipe because the program opens
the stream either for reading or writing. In the above case, for
reading of course, so it connects to the output of list.
Morale of the story: Just replace STDIN: or STDOUT: (if your « pipe
command of the day » supported that) by PIPE: and all will be good.
I believe I’ve already provided some details on CrossDOS, but I’m
doing it again and going a bit more into depth. CrossDOS is also
pretty much new, at least many major parts have been exchanged, and
there is unfortunately still one bug left we need to fix in a
follow-up release (tentatively, 126.96.36.199). The big picture is that
CrossDOS is now multithreaded, same as FFS, and it can handle large
volumes (though, due to the bug, not long FATs). That means, it
supports FAT16, FAT24 and (that is the new part) FAT32. It also
includes support for long filenames, something called « VFAT » in the
Linux world. The last M$ patents on this stuff ran out February of
2018, so we are safe.
« Multithreaded » means that CrossDOS can fire off an I/O operation such
as reading a long file, and can still respond to other incoming
requests. As long as the requests can be handled from cache–and
CrossDOS does have a cache–they can be answered immediately. Previous
CrossDOS releases tried this in a clumpsy way, by always starting two
processes. One handled « ACTION_DISK_INFO », and forwarded all other
requests to a second task. This would at least avoid slowing down the
frequent disk check by Workbench which triggers exactly this packet,
but otherwise didn’t help much. The new CrossDOS is a single process;
not two, but it uses a technique called « coroutines », something it
shares with FFS and the CDFileSystem (more on this in another episode).
For normal routines, you have subroutines A, B, C where A calls B,
then B calls C, C returns to B, and B returns to A. Coroutines work
differently. From A’s perspective, A calls B, and–from inside B–B
calls A. A typical example for this (and this is how it works in just
another project of mine, ViNCEd) is the parsing of CSI sequences, e.g.
CSIx;ym to set the font color and font attributes in the console.
Here we have one function B that calls A to get a new character, then,
if this is a CSI or ESC, it reads the next–OK, is it a
number?–parses the number, then continues parsing to the next
semicolon, then when the final letter arrives, it has all the
parameters it needs to collect, and calls the corresponding
lower-level function to set the attributes. So, the
parser–here B–needs the data letter-by-letter or digit-by-digit.
Unfortunately, this is not the way the data arrives. Instead, the user
writes data into the console, and probably not even in complete
sequences. There is nothing wrong writing the CSI with a single write
call, then writing the digits in a second call, and then writing the
final letter in a last call. So, from that perspective, the function
that receives all the requests from the user–and this is A–gets data
in chunks, and then calls into B. So from the perspective of
dos.library, the top-level is A, which collects user requests, and
calls into the parser B. From the parser perspective, namely B, it
needs to call A to retrieve the next character. Clearly, this doesn’t
work with classical subroutines, because either A or B would need to
be turned « inside out ».
There are two solutions for this problem. One solution is « state
machines », which are hard to debug and complicated to write, but
classical and work with the methods of high-level languages such as C,
and the other solution is « coroutines », which is a long forgotten art
form, probably best described in Knuth’s « The Art of Computer
Programming », which is not supported by C, but requires a small
assembly stub. It is (or was) supported by BCPL, as implemented in
Tripos, and probably one of the reasons why the OFS used it. FFS uses
its own coroutine functions, and so does CrossDOS and CDFileSystem.
There is more to share about CrossDOS. My experience with it is that
most people assume that it works like FAT95, but it does not. FAT95 is
not multithreaded, and it is not quite as capable as CrossDOS. Again,
we need to take a detour for the details. On the Amiga, partitions are
indicated by the Rigid Disk Block, a couple of blocks at the start of
a disk that specifies where the partitions start and end. This rigid
disk block is to be interpreted by the firmware of the host adapter.
This is, for example, the Guru ROM, or the GVP boot ROM, or even part
of the scsi.device. It is not the FFS or OFS that deals with it.
Floppies don’t use a Rigid Disk Block, and removable media such as ZIP
should not use it either (this is a bad idea; more later).
Of course, PCs don’t use a Rigid Disk Block. They use a BIOS Master
Boot Record (MBR) partiton table (though with UEFI, not anymore; they
use yet another structure). The problem is: the hostadapter cannot
read this structure (there is not even a hostadapter there), so nobody
in the OS feels responsible for the MBR partition table. So CrossDOS
has to jump in. It can be run in two modes:
– Using the drive entirely as if it would be a floppy (this is the
« superfloppy » mode).
– Interpreting the partition table, then handling one partition of the
drive. It then needs to know which partition it should be responsible
Back when CrossDOS was implemented, the new « SuperFloppy » flag in the
MountList did not exist, so they looked for other solutions, which is
the DosType field in the MountList.
So, if the DosType is MSD\0, it is a SuperFloppy; no partitions are
assumed, and the whole disk is just one file system. This is identical
to setting « SuperFloppy = 1 » in the MountList. There is a second
equivalent DosType, namely MDD\0 which does the same thing. This is
probably some legacy mechanism to switch between single and double
density, but it is no longer in use and the two are now equivalent.
One single file system per device.
If the DosType is MSH\0, a MBR partition table is instead assumed to
be on the drive, and then « SuperFloppy » must be 0; i.e. off. Of course,
then CrossDOS needs to know which partition to access, and there is no
such field in the MountList. Instead, it uses the name of the handler.
If the device name ends with C, it is the first partition; if it ends
with D, it is the second partition; and so on. This is probably to
mirror the typical Dos « partition names » where C: is the first
partition on the internal hard disk, D: the second, and so on. Hence,
you cannot name the devices as you like, but the name of the icon in
DEVS:DOSDrivers needs to end with the right character names.
Thus, to keep it short, three things need to be fixed to switch over
from FAT95 to CrossDOS:
a) Change the FileSystem entry in the MountList to
b) Change the DosType to 0x4d534800 for MBR-partitioned drives or
0x4d534400 for SuperFloppies (or keep 0x4d534800 and add
« SuperFloppy = 1 »).
c) Change the name of the icon such that the last letter indicates the
FAT95 uses a different DosType, namely 0x46415400, and uses a
different way to indicate partitions, and people often forget to
change this. In particular, FAT95 uses the last digit of the DosType
to indicate the partition number, i.e. 0x46415401 is the next
There is, however, something wrong with this hack, and what FAT95
attempts here is a bad idea. And for this, we need another excursion,
and this is the FileSystem.resource. This is an invention that came
into life with v34 (Kick 1.3) and autobooting. The problem it tries to
solve is that if you have a hard disk with many partitions and a
floppy, then each of these devices clearly needs a file system.
However, without any further trick, the same file system needs to be
loaded once per partition, hence for a three-partition drive and two
floppies, five copies of the FFS would have to be loaded into RAM.
This is clearly a very bad, wasteful idea.
Instead, we have the FileSystem.resource, which « buffers » file systems.
So, whenever a partition is mounted, the Mount command (or the
firmware of the host adapter) checks in this resource for a file
system with the same DosType as the one it needs for mounting the
partition, and if it finds one, it just recycles what it finds there.
Hence, there are three CrossDOS entries in the FileSystem.resource
once you mount a CrossDOS device, installed there by CrossDOS itself:
MSH\0, MSD\0 and MDD\0, and all three point to the same CrossDOS code.
Now, consider the same for FAT95: Instead, you could have as many as
255 entries in the FileSystem resource for that: One for FAT\0, the
first partition, one for FAT\1, the second partition and so on, up to
FAT\255, the 256th partition. This is clearly not practical. FAT95
misuses the DosType for something it was not designed for, and its
authors probably forgot about the implications it has for the
In the meantime, CrossDOS had one bug fixed, namely that the version
that came with 3.1.4 accepted only FATs (directories) with at most 16
blocks in size. This was part of a legacy check mechanism to identify
corrupt disks, but is no longer relevant for today, so it got removed.
CrossDOS now *also* supports the FAT\xx DosType just because I know
that only a minority of users read instructions, or even this text,
but there is no entry (for reasons given above) for this DosType in
the FileSystem.resource, so the code isn’t shared. It just loads
CrossDOS again from disk, wasting your memory.
Avoid the waste, change the DosType.
Concerning file systems, there is a third one that comes with 3.1.4,
and that is the CDFileSystem that reads CD-ROMs. The V45 version has
almost nothing in common with the original Commodore version. It is a
close cousin of the OS 4 version, though, and borrowed many features
from it. At the same time, it is both ahead and behind it, but the
story is a bit complicated…
Similar to FFS and CrossDOS, it is multithreaded, which is a new
feature. That is, if a CD-read is triggered, the file system remains
responsive and can answer requests as long as the corresponding CD
blocks are in cache. What the CDFileSystem caches are administrative
blocks; not data blocks. That is similar to FFS. This multithreading
is new, compared to both the OS 3.1 and the OS 4.0 version, and just a
consistent new feature in all file systems.
It also supports the « DirectSCSI » flag. Regularly, the CDFileSystem
attempts to read from the CD (or DVD) by means of CMD_READ. However,
not all hostadapters support 2048 block sectors (as required) CD-ROM
data track access, and hence, this control flag turns out to be quite
useful here as well. Previous solutions for the same problem used the
« control » entry in the MountList, though details depended on the
Despite cache and multithreading, the CDFileSystem features a third
mechanism to speed up access, and this is « read ahead ». If a program
does not attempt to read a large amount of blocks one after another,
but is rather asking data block by block, this would imply that the
CD-ROM has to start and stop reading, slowing down the transfer. The
CDFileSystem instead now automatically loads block N+1 into cache when
block N is read such that this access can then be satisfied quickly.
Multiple extensions made it into the 3.1.4 version compared to the 3.1
version: Joliet support (the proprietary « we don’t read standards »
standard from Microsoft for long filenames), and Rock Ridge (the
universally-accepted except on Windows version for long filenames),
plus the Amiga-specific extension for protection flags (a proprietary,
though popular and necessary extension). They all came in from the
OS 4 version.
What also came in through OS 4 is support for audio tracks. That is,
audio tracks appear as « AIFF » files on the CD file system and then can
be played through MultiView, though an AIFF datatype (which, sorry to
say, we did not include). Well, mostly OS 4, as there is more to say.
OS 4 does not « read ahead » and « multithread » for audio, and
unfortunately, there are about 30 different ways of obtaining audio
data from a CD-ROM (I love standards, you can select between so many
of them). OS 4 had about support for three. The 3.1.4 version has a
rather delicate algorithm to try them out, then stick to the one that
worked, so you don’t need to configure this in the MountList.
What also came in from OS 4 is support for UDF, which is the file
format used by DVDs. It is a bit more modern than the ISO format,
though UDF support includes caching, which it did not in OS 4, so it
should hopefully perform better. Actually, UDF support was much more
polished in the 3.1.4 version.
There are other things that did not make it into this version, though,
simply because we ran out of time, or haven’t had material for testing.
The OS 4 version also supports the simple video format (CDXA) but no
support in the file system. The problem here is lack of documentation,
and lack of test material. There are multiple track formats a CD can
be formatted in; not just 2048 byte sectors and 2352 audio blocks. It
was–to me–completely unclear which format these disks take. As this
is a rather exotic format, I decided to ditch it. As soon as I know
more, I might reconsider, but so far no-one has really complained.
The OS 4 variant also supported HFS and HFS+, the « we do make
proprietary formats » format from Apple. Unfortunately, I don’t have
any fruit in the house, and neither test data to assess it;
furthermore, the OS 4 code was dependent on some GNU specific
extensions to ANSI C such as function definitions within functions
(today, one would probably call that « closures ») which first had to be
restructured to fit into ANSI-C to make it compile with SAS. Well, in
the end, this all looked too risky, with no test data, and only a
« best guess interpretation » what this GNU C should mean, so it was
also ditched. It would have extended the work by probably another
month, and this was hard to justify.
There are probably a couple of « strange » CD drives still alive in some
machines that do not play by « any rule » (i.e. any formulated standard)
that we may have forgotten, or for which we have no clear idea how to
detect or support. For example, it is at least known that some (really
old) CD drives return audio data as « big endian ». While this sounds
plausible on the Amiga, the MMC audio specs specifically require
little endian, and thus the endian switch is always made. Of course,
with rather bad side effects on such drivers that play in the wrong
(or right?) order. As there are no clear guidelines at this time as to
how to identify such ancient beasts (nor an idea how to drive them),
there is no support for them either. If you have to happen such a
thing, let me know, we’ll probably find a solution. But, again, they
probably all died out 10 years ago already…
There are also a couple of other tiny bugs here and there found during
the review of the OS 4 code, so actually, overall code quality should
have been improved–that, plus multithreading–should hopefully give
you a rather stable and fast CD experience. It is actually more of a
« four file systems in one package » right now.
Just one word of warning: Do not expect CD audio to work on WinUAE. It
won’t. The problem is that WinUAE does not emulate MMC commands nor
the CD-ROM TOC correctly, so no data comes through. That’s not the
fault of the CDFileSystem.
21. Animation.datatype and anim.datatype
Maybe a bit more in-depth information on one of the datatypes, the
animation.datatype and anim.datatype. Actually, they sound related,
but their job is a bit different. The animation.datatype is the
generic base to play animations, in the same way as the
picture.datatype shows pictures. The anim.datatype is specifically
there for interpreting IFF ANIM files, and therefore related to the
ILBM datatype, which are IFF pictures. Besides ANIM, the only other
datatype « on top » of the animation.datatype is the CDXL.datatype,
which plays very simple animations, small movie clips more than video
(given the resolution and bit depth Amigas can handle).
Animation was one of the things we debugged for too long, the ratio
between bugs and actual code was… quite surprising, to put it mildly.
First, you need to understand how this thing works: animation launches
two tasks, one that continuously pulls data from disk and puts it into
a ring buffer–via the anim.datatype or anything else that reads files
that represent video–and a second task that plays the frames. The
problem with the 3.1 version is that there is absolutely no
synchronization: Both tasks access the same data structures, without
even using a semaphore. Clearly, this cannot work. When one task
accesses a data structure while the other is modifying it, you are
asking for problems.
Olaf had this fixed for 3.9, so there are now semaphores for the ring
buffer. Unfortunately, the problems did not stop there, so the 3.9
version is not working very well at all. One of the anoyances was that
decoding of frames worked when playing forward, but due to the
dependencies between frames in the ANIM format (« P-frames » as one
would call them) you could not reliably seek backwards. You were often
left with junk on the screen because the decoder used the wrong
reference. Which was fixed, of course.
A second interesting effect was that most anims played with two frames
too much. This is one of the « features » of IFF ANIM, namely that the
last two frames reconstruct to images that are identical to the first
two–the reason for this is that DPaint wants to enable players to
play the anims in a loop, without having to go through a full decode
of the first two frames (« I-frames »). So the last two frames are
predictive frames that go back to the initial two frames. There are
two frames; not one, because ANIM uses a front-buffer (shown on the
screen) and a back-buffer (in which data is computed), and swaps
between them for every frame. Which was exactly why seeking backwards
did not work reliably.
Then we have screen modes that may turn out to be a problem: For
example, HAM8 can not be played « as is » on an OCS/ECS machine. It
could be played if colors are quantized down to a restricted palette,
and it could be even played in original quality if RTG graphics were
available. Only that the datatype did not attempt any of that. This
also changed, and we got (for a couple of additional cases) custom
« renderers » that reduce the quality to be able to display the
animation on Workbench, or on an RTG screen. Previously, the datatype
would only show an error requester.
Synchronization between the two threads (loader and renderer) was also
a bit… strange. One would typically do that with message parsing:
« I’m ready to take four frames, preload them from disk », and so on.
This natural Amiga communication protocol was apparently too
much–instead, the datatype uses about four signals, depending on what
the loader should do (load, stop abort, preload, exit…).
Unfortunately, if the player is busy, and does not require any extra
frames, the loader… just busy-waits and burns CPU time the renderer
could use for showing frames.
Needless to say, I stopped this and I’m halting the loader task now if
it has nothing to load, so the datatype is no longer a CPU hog. You
saw this problem on 3.1 and on 3.9 even that the scroll-bar was quite
« quirky » to use–it sometimes did not react, the mouse pointer was
frozen, just because the CPU was locked on the player thread and the
input.device (responsible for moving the pointer) did not get the CPU
until the player released a critical semaphore of Intuition, because
it was busy waiting for the loader, and the loader was busy… doing
nothing. Great job, folks.
Since the animation.datatype was written by the same guy as the
sound.datatype, similar problems continued there… but more on this
Quite a while ago, I already reported on the printer.device, and that
it was the most nerve-wracking experience we had with 3.1.4. So far,
I’ve always believed that graphics.library is bad; but despite its
smaller size, printer.device made more trouble–for multiple reasons.
First, there is the OS 3.1 printer device and the new development from
Haage & Partner for OS 3.9. Unfortunately, we do not have the 3.9
version, so this was not an option. The 3.0 version was not an option
either as it does not support printing of RTG graphics–it has no clue
about it. Then, there is the V58 or so version from OS 4.x, but this
was not an option either because it was full of code only supported
and meaningful in 4.x, such as library base access.
Hence, no good options for development. We settled for an intermediate
version which was before the integration of many OS 4 specific
constructions, but branched off from the V40 version from 3.1. It
turned out that this wasn’t a good option either, but the best we had.
The first problem we noticed was that buffer management was broken.
Actually, broken in ways similar to the 3.9 version. If you had an old
slow pin-printer, you may have noticed strange artifacts at the left
of the page. This happens because the printer driver renders into the
output buffer while the printer is printing it, and as old parallel
printers are relatively slow, the printer isn’t ready before the line
buffer is touched again, so 3.9 was actually unusable with anything
with a slow parallel interface.
Another gimic of the 3.9 version was that it supports multiple
printers. This was re-implemented in the OS 4.x variant, and we had it.
But it had a bad side-effect in that whenever you opened the printer
device, it would reload the printer driver from disk. This is probably
not much of an issue with hard disk users as of today, but it is
clearly an annoyance if you want to print from floppy as it causes a
« please insert … in any drive », everytime you want to print. Our
printer device is now smarter and buffers drivers.
Unfortunately, more issues in printer drivers remained: They all have
an initialization code that opens core libraries and returns a failure
code in case initialization failed. Though the printer.device never
checked… so if initialization failed, the printer.device would fall
over. Unfortunately, someone (ehem, Olaf) must have misread the
documentation when implementing the HP printer drivers for 3.9.
Instead of an error code and 0 for success, they return 1 for OK and
0 for error, quite the reverse of what is needed. This was never
noticed in 3.9 because there was never any check, but for V45, there
is a check and hence printer drivers from 3.9 just do not work in
3.1.4. However, we updated all of them, and the 3.1 drivers are okay
in this respect. Just do not use the 3.9 drivers.
Then, Floyd-Steinberg dithering did not work as it required a larger
buffer than it allocated, and then left artifacts on the right-hand
side of the page; at least for low resolutions. This kind of thing
happens if you never attempted to print with a old-style needle
printer with a stunning resolution of 90dpi. Ok, so this was noticed
by our beta team (thanks!) and fixed as well.
In 3.1 and 3.9, the printer.device checks for out of paper and offline
conditions, but in 3.1, you never could abort printing. Yes, there was
a nag requester « Printer is out of paper… », but if you attempted to
abort printing, it just came back. The error was never propagated
« upwards » in the code, and the only thing you could do is either
insert paper–or reboot the machine. Even worse, it checked the
parallel port pins just the wrong way around and hence always reported
the wrong error. « Out of paper » if the printer was offline, and
« offline » if the printer was out of paper. The OS 4 version also has
this inverted, and while Olaf invested quite some time to make the
printer abort printing, it was neither completely successful. Just
going through all the layers of the software, and checking
consistently for abortion conditions is quite a hassle.
My tests with my antique NEC P6 seem to be succesful in so far as that
aborting a print now really aborts it. This is a bit touchy–you
cannot simply « pull the rug » in the middle of an Esc-sequence which
prints a dot graphic because if you want to continue printing later,
the new commands would then be understood as part of the Esc-sequence
graphics that were unfinished and part of the aborted first printer
job. Apparently, Olaf missed this–you cannot just abort printing
« anytime », you can only abort after the end of a control sequence.
Printing with HP printer drivers also turned out to be a hassle, even
though we had updated sources (thankfully provided by Olaf who also
wrote them for 3.9). Whenever we tried, graphics came out just garbled.
It took a while until we found the reason: There was a silent
interface change from 3.1 to OS 4.x in how graphics is exchanged
between the printer.device and its drivers. In 3.1 and below, the
expansion of graphics (i.e. magnification to the printer resolution)
is split between the printer.device and the driver. What the driver
receives is a « run-length » compressed version of the low-resolution
graphics and the run sizes, i.e. two arrays: The graphics data, and
the expansion factors for each pixel. For OS 4.x, the expansion
factors are always 1, and the graphics is expanded by the
printer.device. This enables use of old printer drivers with the new
printer.device, but not using new printer drivers that do not handle
expansion with the old V40 code of the printer.device we had. Hence, I
also updated the HP drivers from Olaf to support the type of runlength
coding used in the 3.1 world.
Then, we had similar bugs for downscaling graphics instead of
upscaling graphics. If you downscale in x direction by a factor of sx,
and in y direction by a factor of sy, the printer.device uses a rather
naive « box filter » for the downscaling; i.e. it sums up all pixel
values in boxes of size sx times sy, and then divides by the box size.
Or rather, it should. In fact, it divided by sx+sy instead of sx*sy,
which does, of course, just give nonsense. Strangely, no-one noticed
All this averaging and downscaling has several implications on HAM
graphics as well: Here, the printer.device has to emulate the custom
chip hardware and has to « hold and modify » pixel values itself. This
is all simple if you just have single pixels, but if you also have to
take averages over pixels for downscaling, things can go wrong–and
did go wrong. So HAM printing was broken in V40, and probably still
broken in OS 4.x (not that these machines have HAM in the first place).
The printer.device also supports a primitive form of « color correction »
that, essentially, attempts to adjust between the different gamma
exponents of screen and printer, and the different color densities.
It’s all a bit naive, but whatever… it should work, which it did not
if downscaling was involved. Actually, the way it works is that it
modifies the palette before printing the image, hence it still does
not work with True color graphics or HAM, both of which do not have a
palette. Speaking of true-color images, printing these images sideways
was broken, too, and just generated nonsense.
So, this was really an extremely bug-ridden piece of code, and I
believe there was not a single source file that remained untouched. It
should be fairly ok now.
More words of warning: as mentioned, do not use the OS 3.9 printer
drivers. They simply won’t work as their initialization code returns
the error indicator just the wrong way around. Use the 3.1.4 supplied
drivers, which were all refactored–not only the HP drivers, also the
Epson and NEC drivers were updated and cleaned up and tested. (Guess
who has an NEC?). In worst case, use the OS 3.1 driver, or send me a
line if you want it updated and are willing to help with testing.
However, they should continue to work unchanged.
A second (not-) change is the preferences system. OS 3.1.4 uses the
OS 3.1 preferences system, which means that there are separate
preference files for the printer and the printer graphics
configuration as these are two different preference programs. In 3.9,
this all moved to a single program and a single file. While the
printer.device of 3.1.4 supports and reads the 3.9 preferences files
just fine (it is just another IFF dialect) the 3.1 settings from the
second preferences file override the 3.9 settings. So, either use the
3.1.4 preferences program consistently, or delete the printer
preferences in ENVARC: and only use the 3.9 preferences program. Both
works, but do not mix them. In case of doubt, delete the printer
preferences from ENVARC: and create new ones; this will work.
A feature we do not have is the printer preferences preview. This was
added in the 3.9 printer.device–namely to generate a preview using
the latest settings–but documentation on how to do that is missing.
Hence, no preview for 3.9 preferences. As soon as we find out, we may
23. Printer drivers
The post was long enough, but I still forgot something…
HP LaserJet printer drivers… The LaserJets, and actually most modern
printers are page-printers; not line printers. That is, they receive
an entire page, and then print it once it is complete, unlike the
old-style needle-printers that printed graphics line-by-line as it
This has an impact on how printer drivers work, and this may be a bit
confusing at first: whenever the printer driver closes down, it has to
eject a form feed as otherwise nothing is printed at all. Hence, if
you redirect several commands to PRT: such as:
the output of list and dir will appear on separate pages for the
LaserJet and DeskJet printers simply because the Shell closes the
redirection file after each command.
The alternative would have been not to print the form feed, but this
would mean that you probably do not get *any* output at all until you
run a command that manually prints a form feed.
I decided against this. This is error prone, and even worse, « service
prone ». Consider the bug reports on « my printer does not work » if
there is no output, even though there is clearly a redirection to PRT:
in the Shell. It is one of the decisions « you cannot simply do it
There is a second strange « gotcha » in the printer drivers for the HP
printers, and this is due to PPaint (Cloanto, do you read?). This
program tries to outsmart the printer driver to allow borderless
printing on some printers, at least. For this, it first reconfigures
the page size to « wide tractor », no matter what the user configured as
page size, and then computes the page limits manually, and prints
« white » in those page areas that are, according to PPaint’s
computation, within the printable area.
Now, there is no « wide tractor » paper option for the HP printers. Only
A3 and A4, US Letter and US Legal. So the HP drivers have to « outsmart »
PPaint and emulate such a page. Of course, the printer cannot print on
wide tractor settings, but at least it can return the page definitions
such paper would have if it fit into the printer, and this is good
enough to make PPaint happy and let it indicate and let you choose the
correct page size.
So, in case you wonder: There is a wide tractor setting in the printer
preferences for the HP printer drivers; but simply do not use. It’s a
dummy, just to keep some programs happy.
24. Icon.library (in depth)
I hadn’t updated this thread for a while due to lack of time, and I
might have forgotten one thing or another, so here is another tiny
change that will hopefully make life easier: the icon.library.
This is a version derived from the 3.9 version, but with two small
changes. For 3.9, the icon.library allowed configuration of the
« maximum filename size » so it knew where to cut off names in case a
« .info » file for the icon has to be attached. This feature is gone.
Well, actually, it is no longer required, and it was a bad idea. It is
a bad idea because the user hardly knows how long the filenames are
allowed to grow, and even worse, this maximum size depends on the file
system the icon.library is working with, so it cannot be « correct » for
all combinations. If you had an (old) CrossDOS version in the system,
then the filename limit would be « 8 » (the .info is mapped to .INF by
the 3.1 version of CrossDOS). You surely don’t want to set this limit
to « 8 » just to be able to use CrossDOS.
So, new rules apply: icon.library does not limit the filename size at
all. Instead, it now always checks whether or not it can create icons
correctly under the name you give them, and it checks before writing
an .info file whether or not this filename potentially conflicts with
something that already exists on disk–which conflicts because the
filename of the icon and the filename of something else become
identical after truncating to the maximum length. And this truncation
is the job of the file system.
So what is the « maximum filename size » in Workbench Prefs good for?
It’s really only cosmetic. The only thing it does is limit the maximum
size of the input dialogs Workbench accepts; nothing more. If a
program attempts to create a longer filename, that’s all good,
provided icon.library can create such a file and the file is different
from the base (i.e. non-icon) file.
When renaming files, Workbench has a heuristic method of truncating
filenames for the « Copy_Of_ » renaming of files. It also tests whether
or not it can create a unique name by prepending « Copy_Of_ », and since
it cannot test all possible lengths of filenames, it checks for some
typical maximum filenames. 30 characters for DOS\1 through DOS\5, 54
characters for DOS\8 and 106 characters for DOS\6 and DOS\7.
So, no need to fiddle with the maximum filename size at all–it’s all
Another change is this « place icons in Fast RAM » setting of OS 3.9.
That’s also gone for good. Again, because the user cannot know whether
the graphics system of the screen Workbench is running on supports
this option, as it may depend on the screenmode as well. It’s a bad
idea to delegate a decision to a user for something the user, in
general, cannot know, so the switch went away. Instead, Workbench runs
a small test when opening (or re-opening) its screen whether icons can
be placed into Fast RAM–and if so–it simply does it. No need to
configure anything; it’s automatic.
Finally, how do you move icons to Fast RAM? Well, for graphics cards,
this is what already automatically happens. For native systems, I *do
not* recommend FBlit as this program is known to cause multiple
problems as its patch set is incomplete and has defects. There are two
options: Either, you run the native (AGA) driver of CybergraphX, or
you run the native driver of Picasso96.
There is a P96 driver for the ECS/AGA chipset? Yes, there is. Check
Aminet. A relatively recent P96 version is sufficient. With P96 and
this « driver » installed, icons will go to Fast RAM.
Frankly, it’s not much of a driver, but it does exactly what you want
it to do.