WimpBasic module

Author: C J Bazley (for APDL)
Date: 18 Oct 2017
Revision: 8

About the module

The WimpBasic module provides SWIs for initialising WimpBasic programs and dynamically linking them with a run-time library, which it contains. These SWIs are used by the 'wblinker' program that is automatically included inside every application created using the WimpBasic desktop development environment.

Change history

Version 2.10

The run-time library and module code have been re-compiled to be 32-bit compatible, using RISCOS Ltd's generic shared C library stubs to avoid onerous external dependencies.

On a 32-bit versions of RISC OS, the SWIs WimpBasic_Stubs and WimpBasic_Link will now return an error if they are unable to synthesise a branch instruction because the target address is too far.

WimpBasic_Stubs has been extended with additional flags to generate a 'trampoline' that consists of load-PC instructions rather than PC-relative branch instructions. This allows any 32 bit address to be reached but requires an additional client-supplied buffer to hold a table of function addresses. Also a trampoline may now be generated for a non- optimised program (for use with WimpBasic_Link).

The SWI WimpBasic_Info has been extended to allow clients to determine the buffer size required for WimpBasic_Stubs so that all library functions are included in the trampoline.

WimpBasic_Link has been extended with an additional flag to make it link a program with a client-supplied trampoline rather than directly to the relevant library functions (for 32 bit compatibility).

An error will be returned on finalisation (thus refusing to die) if any programs are believed to be linked with the module. This safety mechanism had been disabled for unknown reasons in the last public release of the module (version 2.09, 21 Jul 1999) and possibly other versions. A loophole has been closed where the client count was not incremented for optimised programs linked using WimpBasic_Stubs. For completeness, the planned SWI WimpBasic_OkToDie has been implemented.

Errors from SWIs are now looked up in a messages file that is compiled into the module binary and registered with ResourceFS on initialisation of the module. A service call handler has been added to re-register this file if ResourceFS is restarted. The default messages can be overridden by setting system variable WimpBasic$Path to point to a directory containing an alternative file 'Messages'.

Error numbers are now unique and taken from an officially-allocated block (previous versions of the module used '0' for all errors). The standard error number &1E6 and 'BadSWI' message are now used for unrecognised SWI numbers.

Version 2.11

Upon initialisation, the WimpBasic module will now check for the CallASWI module, if running on a version of RISC OS earlier than 3.7. If it is not present then it attempts to load it from System$Path. If it cannot be loaded then the WimpBasic module refuses to initialise. (Version 2.10 also relied upon SWI &71 but this dependency was not enforced.)

Version 2.12

Fixed overzealous detection of branch-out-of-range errors during link; had been faulting branches from 'positive' to 'negative' addresses (when treated as signed 2's complement) and vice-versa.

Version 2.13

Fixed a longstanding bug where the DrawAction command would erroneously set GCOL actions in the range 69-82 (patterns) instead of correctly mapping Store, And, AndNot etc. to the basic logical plot actions (0-7).

Fixed a longstanding bug where the built-in FileTypeNumber function didn't work because the wrong address was passed to SWI OS_FSControl 31.

Changed the implementation of the Cls command when output is directed to a window; although the queue of pending graphics commands is still flushed, commands are then added to reinstate the prevailing draw action, colours (foreground, background & font), draw mode (filled or outline), graphics origin, text font and size. The graphics cursor will be reset to 0,0.

This fixes a longstanding problem where the Background command was effectively useless unless output was direct to screen (because it only affects the colour to be used by the next Cls).

The Cls command now frees any memory claimed for a queue of pending graphics commands as well as flushing it (previously, memory usage could only grow and never shrink).

Fixed longstanding bugs in Cls and Origin commands which caused an arbitrary word of memory in the heap to be corrupted if output was being cached for the printer.

The Font command no longer updates the current font when graphics output is instead being cached for printer or window. Also it no longer marks a huge area of the output window (±10000 from the graphics origin) as requiring redraw on the next Refresh or Update command.

Fixed a longstanding bug in the Circle command, which had been ignoring the graphics origin (as set by Origin) when output was directed to the screen.

Fixed a longstanding bug in the Point By command, which had been modifying the supplied coordinates according to the current Origin (whereas they are relative to the last graphics cursor position).

Fixed a bug in the Rectangle... To command (to copy or move an area) when the source rectangle was specified by only three parameters. However current versions of the compiler cannot yet cope with this syntax.

Fixed a longstanding bug in the Plot command, which was modifying the supplied coordinates according to the current Origin regardless of whether the action code indicated relative or absolute coordinates. The coordinates are no longer modified unless bit 4 of the code is set.

Executing Refresh or Update commands whilst output is directed to a window that is closed will no longer cause 'Illegal window handle' errors.

Fixed a memory leak when a window to which graphics output had been redirected was closed and then subsequently re-opened. The queue of pending graphics commands was not deallocated; this now happens when the window is closed.

Version 2.14

When outputting to screen a DrawAction command will now immediately enforce the new plot action whilst keeping the current graphics foreground colour (previously it didn't take effect until the next Foreground or Background command). This is consistent with output to a window or printer.

The DrawAction command no longer affects the background graphics colour (used on Cls), only the foreground colour.

Fixed a longstanding bug with output to a window or printer, where a DrawAction command would reset the graphics foreground colour to the last colour set (even if that was a Background command). Also, a cached DrawAction command could result in an indeterminate foreground colour being set, if executed prior to the first Background or Foreground command.

Version 2.15

Restored expected layout of the client program's static data (had changed in version 2.14), for compatibility with earlier versions of 'WBlinker'.

Version 2.16

Fixed bugs where client programs with no sprites file caused illegal reads from zero page in memory. If those memory accesses did not cause a data abort then they typically resulted in the program claiming an excessive amount of memory.

SWI calls

WimpBasic_Link (SWI &4A180)

Initialises a program and links it with the WimpBasic run-time library.

On entry
R0 = flags
bit 0 - if set, do NOT copy static data pointer from &8000 to &8004 and stack pointer from &813C to &8000
bit 1 - if set, link with trampoline at R4 (must have been initialised by WimpBasic_Stubs)
R1 = pointer to program's static data
R2 = pointer to start of program
R3 = size of program (in bytes)
R4 = pointer to trampoline (if flags bit 1 set)
On exit

R0 - R4 preserved

Interrupts

Interrupt status is unchanged

Processor Mode

Processor is in SVC mode

Re-entrancy

SWI is not re-entrant

Use

This call initialises a non-optimised WimpBasic program and links it to the run-time library by synthesising PC-relative branch instructions where appropriate. Originally these were direct branches to library code but a trampoline may now alternatively be used.

On a 32 bit OS this SWI should be called with flags bit 1 set and R4 pointing to a trampoline via which to access the library; otherwise an error will be returned if a library function is out of range (branch instructions only have a range of ±32 MB). The same error will result if the trampoline is too far from the program code.

Unless flags bit 0 is set then the program's static data pointer is copied from &8000 to &8004 and its stack pointer is copied from &813C to &8000 (to support versions of WimpBasic older than 1.4).

If no error occurs then an internal count of the number of programs linked with the WimpBasic run-time library is incremented.

Before version 2.10 of the module any non-zero value of R0 was interpreted as though only bit 0 was set (because R0 was not originally envisaged as a bit field). In practice only values 0 and 1 were used.

Related SWIs

WimpBasic_DeLink (SWI &4A181)

De-registers a program from the WimpBasic module.

On entry

All registers undefined

On exit

All registers preserved

Interrupts

Interrupt status is unchanged

Processor Mode

Processor is in SVC mode

Re-entrancy

SWI is not re-entrant

Use

This call decrements an internal count of the number of programs linked with the WimpBasic run-time library. The counter is prevented from going negative, although this should never occur with correctly written programs.

Typically this SWI should be called in the exit handler of a program that has previously registered with the module using SWI WimpBasic_Link (or WimpBasic_Stubs with flags bit 1 clear).

Related SWIs

WimpBasic_Stubs (SWI &4A182)

Creates a trampoline via which to access WimpBasic library functions.

On entry
R0 = flags
bit 0 - if set, make LDR PC,[PC,#n] trampoline (instead of branch instructions) and store function addresses in buffer at R2.
bit 1 - if set, make trampoline for non-optimised program.
R1 = pointer to buffer for trampoline
R2 = pointer to buffer for address table (if flags bit 0 set)
On exit

R0 - R2 preserved

Interrupts

Interrupt status is unchanged

Processor Mode

Processor is in SVC mode

Re-entrancy

SWI is not re-entrant

Use

This call initialises a trampoline (and optionally an address table) via which a WimpBasic program can access functions in the run-time library. Originally it was used only to link optimised programs (which require a trampoline) but on a 32 bit OS it is also used to support WimpBasic_Link.

On a 32 bit OS this SWI should be called with flags bit 0 set and R2 pointing to a buffer in which to write the required address table; otherwise an error will be returned if a library function is out of range (branch instructions only have a range of ±32 MB). An error will also result if the offset from trampoline to address table cannot be encoded in a PC-relative load instruction.

The word at [R1,#-4] must be readable and have been initialised as a branch instruction to the word-aligned address immediately following the trampoline. This is used by the WimpBasic module to determine the length of the buffer. If present, the address table buffer is assumed to be the same length.

If the no. of p-codes supported by this version of the WimpBasic module (see WimpBasic_Info 1) exceeds the buffer length then a truncated trampoline will be generated and no error returned.

If called with flags bit 1 set then the trampoline will include different versions of various functions suitable for calling from non-optimised code (usually including a short pre-amble). The p-codes affected are P_INITIALISE (+0), P_DEFFN (+568), P_DEFPROC (+80), P_ENDPROC (+24), P_FN_RETURN (+572), P_NEXT (+504) and P_CREATE_MENU (+20).

If no error occurs and flags bit 1 is clear then an internal count of programs linked with the WimpBasic run-time library is incremented. (If generating a trampoline for a non-optimised program then it is expected SWI WimpBasic_Link will subsequently be called, thus incrementing the count).

No flags were supported until version 2.10 of the module (i.e. this SWI always produced branch instructions for an optimised program).

Related SWIs

WimpBasic_OkToDie (SWI &4A184)

Returns the number of programs registered with the WimpBasic module.

On entry

All registers undefined

On exit
R0 = number of registered programs
Interrupts

Interrupt status is unchanged

Processor Mode

Processor is in SVC mode

Re-entrancy

SWI is re-entrant

Use

This call returns the number of programs currently believed to be linked with the WimpBasic run-time library. If the returned value is greater than 0 then any subsequent attempt to kill the WimpBasic module will fail with an error message.

This SWI was not supported until version 2.10 of the module.

Related SWIs

WimpBasic_Info (SWI &4A185)

Query the WimpBasic module for miscellaneous information.

On entry
R0 = reason code
On exit

Registers depend upon the reason code

Interrupts

Interrupt status is unchanged

Processor Mode

Processor is in SVC mode

Re-entrancy

SWI is re-entrant

Use

This call provides an extendible mechanism by which a program can query the WimpBasic module for information. The particular action is given by the reason code in R0, as follows:

R0 Action
0 Read expected size of program's static data
1 Read number of p-codes known to this version of module
2 Read version number of module

Unknown reason codes cause an error to be returned, except in versions prior to 2.10 where -1 is instead returned in R0.

Related SWIs

None

WimpBasic_Info 0 (SWI &4A185)

Returns the expected size of a WimpBasic program's static data.

On entry
R0 = 0 (reason code)
On exit
R0 = expected size of program's static data (in bytes)
Use

This call can be used to determine how much space to allocate for a WimpBasic program's static data. However since this data must be initialised externally, the usefulness of this call is currently restricted to checking the returned value against the size expected by the program doing the initialisation.

WimpBasic_Info 1 (SWI &4A185)

Returns number of p-codes known to this version of WimpBasic module.

On entry
R0 = 1 (reason code)
On exit
R0 = number of known p-codes
Use

This call can be used to determine how much space to allocate before calling SWI WimpBasic_Stubs to generate a trampoline (and associated address table, if 32 bit compatibility is required). The total number of bytes required for address table and trampoline (with pre-pended branch instruction) can be calculated as (number of p-codes × 2 + 1) × 4.

By this mechanism, the 'wblinker' program included in WimpBasic applications need not be modified to support programs that use a greater range of p-codes (although a newer version of the WimpBasic module would need to be *RMEnsure'd in !Run).

Note that optimised programs already include space for a trampoline and therefore the extra required for an address table can instead be decoded from the preceding branch instruction.

This reason code is only supported in 2.10 and subsequent versions of the module.

WimpBasic_Info 2 (SWI &4A185)

Returns the version number of the WimpBasic module.

On entry
R0 = 2 (reason code)
On exit
R0 = version number of WimpBasic module × 100
Use

This call can be used to check the version number of the WimpBasic module before relying upon any features introduced in later versions. It returns the version number multiplied by 100 (to make it an integer).

This reason code is only supported in 2.10 and subsequent versions of the module.

Errors

&81A713 "Branch out of range" May be returned by SWIs WimpBasic_Link or WimpBasic_Stubs.
&81A714 "Address table too far" May be returned by SWI WimpBasic_Stubs.
&81A715 "Unknown WimpBasic_Info reason code" May be returned by SWI WimpBasic_Info.
&81A716 "WimpBasic can't die. <n> tasks registered" May be returned by module's finalisation code.
&81A717 "Internal error IP<n>.<n>" May be returned by SWI WimpBasic_Link.
&81A718 "Internal error UP<n>.<n>" May be returned by SWI WimpBasic_Link.