WimpBasic module (version 2.16)
-------------------------------
Documented by C.Bazley for APDL, 26th December 2005
Last updated 15th October 2017

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 included inside every application
  created using the WimpBasic desktop development environment.


Overview of changes in 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.

  The SWI 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).

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

  The SWI 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).

  Enabled existing code to return an error 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.
  Closed a loophole where the client count was not incremented for optimised
  programs linked using SWI WimpBasic_Stubs. For completeness, the planned
  SWI WimpBasic_OkToDie has also 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.


Overview of changes in version 2.11
-----------------------------------

  Now checks for the CallASWI module on versions of RISC OS earlier than 3.7
  and if not present attempts to load it from System$Path. If the CallASWI
  module cannot be loaded then the WimpBasic module refuses to initialise.
  (Version 2.10 also relied upon SWI &71 but this dependency was not
  enforced.)


Overview of changes in 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.


Overview of changes in 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.


Overview of changes in 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.


Overview of changes in version 2.15
-----------------------------------

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


Overview of changes in 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

    Registers 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
    WimpBasic_Stubs
    WimpBasic_OkToDie


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_Link
    WimpBasic_Stubs
    WimpBasic_OkToDie


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_Link
    WimpBasic_DeLink
    WimpBasic_OkToDie


WimpBasic_OkToDie
(SWI &4A184)

    Returns the number of programs registered with the WimpBasic module

  On entry

    All registers undefined

  On exit

    R0 = no. of registered applications

  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 it returns a value greater than
    0 in R0 then any 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_Link
    WimpBasic_DeLink
    WimpBasic_Stubs


WimpBasic_Info
(SWI &4A185)

  Query the WimpBasic module for miscellaneous information

  On entry

    R0 = reason code
    Other registers depend upon the 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 of WimpBasic_Info 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
    of the module prior to 2.10 where this SWI simply returns -1 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 no. of
    bytes required for address table and trampoline (with pre-pended branch
    instruction) can be calculated as (no. of p-codes * 2 + 1) * 4.

    By this method 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 version number of 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"
        (returned by SWI WimpBasic_Link and SWI WimpBasic_Stubs)

&81A714 "Address table too far"
        (returned by SWI WimpBasic_Stubs)

&81A715 "Unknown WimpBasic_Info reason code"
        (returned by SWI WimpBasic_Info)

&81A716 "WimpBasic can't die. <n> tasks registered"
        (returned by module's finalisation code)

&81A717 "Internal error IP<n>.<n>"
        (returned by SWI WimpBasic_Link)

&81A718 "Internal error UP<n>.<n>"
        (returned by SWI WimpBasic_Link)
