The RISC OS Printing System (part 3)

In Part 2, the different levels, control and communication were outlined. In this part, I wish to add more detail on how this is achieved and show the way the whole system is controlled by !Prin ers.

Passing on SWIs

The PDriver module passes on most of its own SWI commands to either the PDriverPS or PDriverDP module. This at first sight could be done by PDriverPS and PDriverDP having their own set of SWIs, but t is would mean any new PDriverXX module couldn't be added to the system without re-coding PDriver. Instead a registering system is used.

When a PDriverXX module starts up, it 'registers' its presence to PDriver by calling SWI PDriver_ DeclareDriver. This SWI has the following entry conditions:

R0 is a pointer to the reason code handler for passed  on SWIs

R1 is a pointer to the PDriverXX modules private word (a memory location unique for a module)

R2 is the PDriverXX modules number (0 for  PostScript, 1 Epson Dot Matrix compatible, etc)

PDriver stores these and uses them to pass on any of its SWI calls. Those of you who are fluent in module coding will recognise the similarity between a reason code handler and a SWI code h ndler. For those of you who find this rather confusing, just think of the reason code handler as the place in memory where the PDriverXX's code starts for decoding the SWI calls being assed on. This means PDriverXX modules don't have their own SWIs but act as extensions to PDrivers SWIs.

What if PDriver starts up after any PDriverXX modules?

Since PDriverXX modules don't have SWIs, a different approach is used. When PDriver starts up it issues a service call. Service calls are special messages that RISC OS uses to communicate w th modules. Any module can have a memory location where any service code is placed. So service calls are offered to all modules allowing them to act on them. On receiving the service call Service_PDr ver-Starting (PDriver starting up), any PDriverXX modules call the SWI PDriver_DeclareDriver and so again all PDriverXX modules will be registered with PDriver. There are similar service calls a d PDriver SWIs for the modules PDriverXX and PDriver dying (shutting down).

Registering PDumpers

The PDumpers use the same method of registering with a PDriverXX module. The SWI PDriver_ MiscOpForDriver and service call Service_ PDumperStarting are used. So PDriverXX modules know how to pas on any reason codes to any selected PDumper module.

Redirecting commands

As we saw in the previous parts, any printing system must be able to use and modify normal operating system graphic and output SWIs to produce a printed output.

This is achieved by claiming vectors. Quite a few RISC OS SWIs are vectored; this means RISC OS doesn't jump to the start of the SWI code when the SWI is called, but to a memory locati n that points to the start of the SWI code (I hope those of you who are familiar with this concept will bear with me while I try and explain this).

If this memory location has its contents changed to point to some other code, then the SWI that uses this vector will have its action changed. In fact, RISC OS doesn't use one location for ach vectored SWI but a table of locations which are called in a strict order. If a module claims a SWI vector, on calling that SWI, the new code is executed first, the original code ma be executed next or the SWI may return back to the program that called it. This is very useful for the printing system.

For example, consider the sprite plotting SWI. How would any printer be able to make sense of SWI OS_SpriteOp 10 'load a sprite file' or, OS_SpriteOp 16 'get sprite from user co-ordinates'?

For OS_SpriteOp 10, we still need to be able to load sprite files but the printer doesn't need this call.

For OS_SpriteOp 16, when printing, this call makes no sense!! (We have no screen when printing.)

Luckily, the OS_SpriteOp SWI is vectored (SpriteV) and the printing system can therefore modify this vector so all calls, when printing, are 'inspected' before any action is taken.

For OS_SpriteOp 10, the printing system ignores it (this is called 'passing it on'), but for OS_SpriteOp 16, the printing system causes an error to occur, which stops the printing.

There are many such SWIs (Font SWIs, Colour-Trans SWIs, Draw SWIs, even lower level calls like OS_Write and OS_Byte) which all need to have their vectors claimed by the printing system. Needless to say, this is very complicated and is beyond the scope of these articles. If you wish to understand vectors, read the PRMs... and good luck!

To cut a long story short, the printing system uses vectors to re-direct printable output SWI commands, modifying them as required.

Front-ends and back-ends

The whole printing system is controlled by the user via the !Printers application.

This allows the user to select a printer, paper size, printing resolutions and quality. All this must be done under the WIMP, so a multitasking program (in Basic) is used. This is called the front-en . Back­ends are extensions to the main program; they allow the main program to display the required configuration window for a class of printer together with its settings. If you look in the !Printers application directory, or if you have RISC OS 3.7 (and RISC OS 4?) look in !Boot.Choices.Printers (failing that, click <menu> on the Apps icon on your iconbar nd Open $, then look in Resources .Printers ) and you should find a dp or ps or lj directory.

Opening one of these you will see a set of files: Template , PrData and the directory Resources . Opening the Resources directory reveals a set of files; !Sprites , !Sprites22 , etc, and a Basic listing called Support . This is the back-end listing for this class of printer (not much in RISC OS 3.7 since all common back-ends are in the main !r nimage listing in ROM!). All the other files are the required sprite images, window templates, etc for this class of printer. So when you select a different class of printer, !Printers loads in and u es the new support listing and relevant files.

The support listing uses a set of Basic functions/procedures. The listing below is the start of the support for the dp class of printer for RISC OS 3.1+ and !Printers version 1.53.

REM>squished.SupportDP
DEFFNdp_support(dp_o%)
LOCALdp_aa%,dp_e%,dp_i%,dp_m%,dp_g%,dp_f%,dp__%,dp_u%
dp_aa%=dp_o%!0:dp_e%=dp_o%!4
dp_i%=dp_o%!8:dp_f%=dp_o%!12
dp__%=dp_o%!16:dp_u%=dp_o%!20
IF dp_i% THEN
dp_m%=FNprinter_find_prdata_entry(dp_e%,$dp_i%!8)
dp_g%=dp_i%!16
ENDIF
CASEdp_aa%OF
WHEN-1:PROCdp_g
WHEN-2:PROCdp_h
WHEN-3:PROCdp_i
WHEN-4:PROCdp_j
WHEN-5:PROCdp_k
WHEN-6:PROCdp_l
WHEN-7:PROCdp_m
WHEN-8:PROCdp_n
WHEN3:PROCdp_o
WHEN6:PROCdp_p
WHEN8:PROCdp_q
WHEN9:PROCdp_r
WHEN17,18:PROCdp_s
ENDCASE
=FALSE

Notice how all the PROCs, FNs and variable names start with 'dp_'; this is a convention and allows other classes of printer to define their own unique procedures, etc. Any new procedures must al o be defined in the support file. The actual programming details I will leave to a later date.

Changing the printer system

Any of the modules down to the Dumpers can be altered or replaced as long as the above starting conditions are obeyed. It is unlikely that the PDriver module would be replaced unless any new printing SWIs needed to be added. This would have to be done with care so as not to make the printing system incompatible with older applications. Other modules can be and are updated. For example, the module PDriverPS could be replaced if a new variation of PostScript needed to be added. Extra PDumper modules are added to cater for new bit image printers (usually inkjets). If a new class of printer is to be added, a new back-end will also be required.

Simpler changes use the PrintEdit program to alter the data given to the Dumpers, e.g. modifying the colour rendering, or using different Esc codes to give different dithering. Most inkjets understan more than one set of codes for the same resolution.

Well that's it for now. Next time, I will show how to use the PrintEdit program and start to look at where the data for each printer is held on disc.


Source: Archive Magazine 13.6
Publication: Archive Magazine
Contributor: Brian Pickard