#### # # # #
# # # # # The FreeWare C library for
# # ## ### # # # # ### RISC OS machines
# # # # # # # # # # # ----------------------------------
# # #### ### ## # # # # Originally by Jason Williams,
# # # # # # # # # # Julian Smith, and many others.
#### ### ### # # ##### # ### Now maintained by Rick Murray.
Last updated: 26th July 2015
Before we begin...
I'd rather hack code right now, so this document is a blah looking wall of text with no quick links or pictures or anything cute like that; but if you just want to see what's new then click here.
There is an unofficial release available if you'd like to play!
What is DeskLib?
DeskLib is a library for use with RISC OS. If you have the Desktop Development Environment (also available as part of the NutPi pack), then you can make use of DeskLib.
Why would you want to? Easy. Because the standard RISC_OSLib library is fairly simple and has weird named structure elements. Some people would be even less kind - one person describing an earlier version as "Note that the RISC_OSLib library (on average) is mediocre (half of it is brilliant, but is badly let down by the other half)" in a rather entertaining document.
DeskLib? DeskLib is a bit old now - my mission is to modernise it - but even then you can benefit from a cleaner, clearer library with a wonderful event based Wimp system where you can attach handler functions to icons and such. RISC OS doesn't do the likes of VisualBasic, but this is the closest I've seen to a non-painful way of writing programs. I was a pretty instant convert after a long time struggling to do simple things with RISC_OSLib. That was like 20 years ago, I've not looked back.
But, wait, isn't there an updated DeskLib?
Yes. A newer version is available at http://www.riscos.info/index.php/DeskLib; however that version is going off in its own direction and future releases will be ELF only (meaning that it will only work with GCC). Indeed, a lot of things have changed to support GCC's not-quite-RISC-OS way of working, such as naming header files with a '/h' suffix instead of them being in an 'h' subdirectory, plus a future library in an ELF file - pretty much guarantees that the "RISC OS library" will not work with the official toolchain.
My version, currently, is targeted at the DDE on 32 bit machines. I am also currently modifying the code so that a version of the library can also be made available for 26 bit machines - while I personally believe that it is high time to move on from quarter century old hardware, there are many still using RISC OS Select/Adjust on their RiscPCs (or via emulation) for a variety of reasons from the long-expired political to "my favourite app doesn't run on new machines". While a version of DeskLib exists for them, it is the version from circa 1993 and won't have any of the updates. My plan is for a version of the library to run on both old and new hardware. It is up to app developers to decide if they want to target older and newer machines. For my part, I intend to give them the choice.
As for GCC - there are no plans to support GCC at the moment. I would like to offer an ELF version of my library, but if a future GCC cannot read source code laid out in standard RISC OS layout, it may prove impractical to build using GCC. These are problems for another day...
Original 32 bit conversion
I made an updated version of DeskLib circa 2004, and revised it to work correctly on 32 bit systems in 2013.
It contains the following enhancements:
- Backtrace library (based upon Desk 3.20)
- Enhancements to ColourTrans
- New CPU detection code (very outdated now - only understands as far as an ARM710!)
- Important bug fix to Dialog
- New DynamArea library (based upon Desk 3.20)
- Enhancements to File
- Enhancements to Hourglass
- New KernelSWIs library (based upon Desk 3.20)
- Enhancements to Menu
- New Misc library (will probably be retired soon and contents moved elsewhere)
- Enhancements to Module
- Enhancements to Resource
- Enhancements to Str
- Enhancements to Wimp
- Enhancements to Window
I was never planning to take on updating DeskLib, I was happy to leave it to the guys behind the GCCSDK (the riscos.info version) however the decision to move to an ELF only library is not one that I agree with. Sure, GCC is a free compiler and it is a useful choice to have a free compiler and good library for it; however there are plenty of people with the DDE who will no longer have a version of DeskLib available for them (v2.80 will be the last ALF release). With this in mind, I am looking to update DeskLib primarily for supporting the DDE and all those who use it. Now and in the future.
I have a rough roadmap for changes to apply to the original v2.30 source code, which are (roughly, and in no specific order (did I mention this was roughly a rough idea?)):
green strokethrough = DONE, red strokethough = abandoned, modification comments are in 'coffee' (they didn't have a 'tea' colour ☹))
- Backtrace -
merge in modifications present in my server to search for the backtrace frame correctly on StrongARM processors; plus to also terminate backtracing at main() (as anything prior is within CLib). Make Backtrace work with normal DeskLib file handles.
Existing functions work as they have before; a new simpler backtrace BackTrace_Simple() can output to a file (DeskLib file handle) or screen).
- ColourTran - support
ReadPalette, [Set|Return]FontColours, and Set [Opp] TextColour.
Decided ReadPalette had less and less relevance with modern non-paletted displays, and OppositeTextColour was too esoteric.
- CPU - [note: this is low importance] Extend CPU_ID and CPU_Type to understand ARMv4+. Add CPU_HALType which will return NULL (no HAL present) or a composite word describing the hardware, or bit 31 set if a HAL but hardware not identifiable. Update CPU_Class()?
- Debug - rename as DebugOld; though the additional libraries may or may not be ported - no decision as yet.
- Debug (new) - more or less the same thing, but works with DADebug and is to be directly included in the main library.
- Env (new library for miscellaneous "environment" things): Add all of...
OSgeneric() to return generic OS version (300 - RISC OS 3.xx; 350 - 3.50 to 3.70; 400 - RISC OS 4 *and* 6 :-P ; 500 - RISC OS 5); OSversion() to return exact OS version; WimpVersion() to return Wimp version; IsModule() returns TRUE if the module specified is presently loaded, else FALSE; IsTask() returns TRUE if the specified task is presently running, else FALSE; IsHAL() returns TRUE if a HAL version, else FALSE; PlatformType() returns NULL or a value defining the current platform type. The platform type is read from the HAL. Older versions of RISC OS will be NULL (but you can probably make some guesses based upon the OSversion); IsPi() returns TRUE if this is a RaspberryPi, else FALSE. [determine by processor type; as the Pi family keeps getting larger...]; IsVFP() returns TRUE if VFP extensions are present, else FALSE; IsNEON() returns TRUE if NEON extensions are present, else FALSE; ReadUID() returns machine unique ID [usu. MAC address on later machines]; DelayMicro() will ask the HAL to delay a specified number of MICROseconds (has no effect on non-HAL machines).
- Error - add Error_ReportFancy() to support RISC OS 3.5 extended options. Standard Error_Report will call Error_ReportFancy if running on a capable machine; the default icon will be an exclamation mark and the app's icon. Add Error_ReportWithButtons() to provide buttons other than OK and Cancel. Add Error_AskQuestion() to veneer to ReportWithButtons.
- Event - remove RISC OS 2 compatibility. Event_Initialise() will perform a startup suitable for RISC OS 3.10 upwards. Event_InitCustom() will do the same thing but allow you to specify the desired Wimp version, such as for the nested WindowManager. Add Event_PollIdle() to perform the same thing as Event_Poll(), only with the idle delay.
- File - add File_ReadString() to read a [CR]LF terminated string from the file. File_WriteString() will call File_WriteBytes() as necessary. Expand File_CreateDirectory() with File_EnsurePath() which will step through the path given creating directories until the path is valid. File_Canonicalise() will convert a file reference to an absolute path, ie "Choices:Boot" will become something like "SDFS::RISCOSpi.$.!BOOT.Choices.boot". [actually, this will just call Filing_CanonicalisePath() ;-)] File_CanonicaliseAndParse() will determine the full correct path and also return a struct with a pointer to the start of the filesystem (and its length), the start of the disc name (and its length), the start of the path (and length) and the start of the filename (and length). [to check - File_IsDirectory() behaviour on image files with relevant FS loaded / not loaded]
- Font - ConvertToOS and ConvertToPoints to veneer to existing (mostly in lowercase for some reason). Add Font_PaintBlended() and Font_Paint3Blended() to support background blending. Note that the original Font_Paint() may internally call Font_Paint3() [so is not going to be RISC OS 2 compatible any more], it is retained purely because the API is simpler - put this text at this location, for when no fancy stuff is required.
- Font (more) - Add Font_EnumerateCharacters() to allow Unicode characters to be looked up. [would it be feasible to do a Font_PaintUTF() which will output in the current font but if it finds a UTF-8 character that is not supported in the file, to try to switch to Cyberbit (?or?) to display it [use Font_ReadDefn to match current font size] (otherwise fall back to '?')? [does Font_LookupFont return more in R2 nowadays?]
- Icon - add ShadeAll(), UnshadeAll, and DeselectAll() as quick ways to set a known state.
- Kbd - [do we need any changes to support extra keys like WinKey?]
- Menu - FontMenu and FontMenuDecode will be the same. No more RISC OS 2 code. Add Menu_ForceClose() to remove an open menu.
- Net - new library; add all of...
Lookup() - convert hostname to IP address. LaunchURL() - try to start the *http* URL in various ways for various browsers. [if OS is RISC OS 5, it will use a simpler system; I recall getting a URL started with Browse, Fresco, and Oregano could be a bit convoluted] EncodeURL - given an input consisting of domain and path, it will build an http compliant URL (including escaping stuff in the path if need be). Will have an option to select https instead.
- Resource - Add ChoicesRead() and ChoicesWrite() to build appropriate filenames for accessing your choices file based upon "group" name (given), your application name (assumed), and a leafname (given). If the input is NULL,NULL then there will be no group, your application will be the subdir, and the file will be called "Choices". Will cope correctly with reading from Choices$Dir and writing to Choices$Write. ;-)
- Screen - add ReadModeVariable() to read display information.
Add ReadState() to return a struct giving screen dimensions, colours, etc.
DeskLib has been taught about mode specifier blocks; abandoned Screen_ReadState() as this information is available from Screen_CacheModeInfo, only it's a bit messy in its implementation (but is already used in various parts of DeskLib).
- Serial -
[check NonZeroPollWord code as it is probably NOT 32 bit safe due to being entered by word values - fix this] What sort of level of serial support is present on HAL devices? Can we talk to the serial port of Beagle or Pi? Can it be handled via this code? [though, note, these serial ports are Tx/Rx only]
- SerialBlk - ? proposal to support serial blockdrivers?
- Sprite -
duplicate every SpriteOp veneer with "Ptr" suffix to accept a pointer to a sprite (the current routines expect a sprite name). Check if MemorySize correctly calculates size requirements for "deep" sprites. Modify MemorySize and Create to handle mode specifiers.
The pointer functions actually use a 'P' suffix instead of 'Ptr' to be more compatible with the other DeskLib; now understands mode specifiers and sprite specifiers]
- Time - ReadClock() to actually read the current system time. ConvertTimeToOrdinals() to convert a five byte time to a localtime ordinals block. ConvertTimeToUTCOrdinals() as above, but UTC time. ConvertTimeFormats() to convert many to many (more flexible; but RISC OS 5.20+ only). Returns with -1 if SWI not supported; else returns with R0 = NULL or pointer to error block. ReadOffsetFromUTC() to read offset from UTC in centi-seconds; including daylight savings correction if applicable.
- UTF8 - ? Support of UTF-8 may implicate a new library, for things such as counting characters in a UTF-8 string, working out a byte position for a given character, and so on.
- Wimp - ProcessKey should strip apart UTF-8 codes to send them as multiples. Add new functions for enhanced ReportError use. Add ResizeIcon(). Is it feasible to fix SetCaretPosition() to work correctly on UTF-8 strings?
Look at SetMode() re. mode selector blocks. Add TextOp().
Wimp_Poll[Idle] completely rewritten. Saving FP state is assumed, and is handed off to the Wimp to do. We don't. Accordingly,
Wimp_CorruptFPStateOnPoll() are dummy functions. Really, that's not been relevant since RISC OS 2!
- Window - add IsOpen() to return TRUE if window is open, else FALSE, and HasFocus() to return TRUE if window has input focus, else FALSE.
Major changes in a nutshell
- All RISC OS 2 specific code will be removed. RISC OS 2 will no longer be supported. RISC OS 3.10 may or may not be supported - the earliest system expected to be officially supported will be RISC OS 3.50.
- The "DDL" variation of DeskLib will be removed.
- Numerous enhancements to support changes in RISC OS after RISC OS 3.10 was released!
Fancy new DeskLib release
There is no official release of either the library nor the source code at this time, as the modifications are a work in progress.
I have put up an early example build desklib230rm32-20150726.zip (234KiB) but note that this has had very little testing. It should be okay (I have linked a couple of my own programs with it)...
Changelog for the new versions of DeskLib RM/32
2015/07/10 (Rick Murray)
- Removed the many copies of "Macros", "SwiNos", and "RegDefs" used in the assembler veneers and set everything to point to one master copy.
- Updated "SwiNos" (and the C "SWIs") to know all the SWIs on a typical RISC OS 5 system.
- Assembler code now uses "ENTER" and "EXIT" macros around functions, so code can more easily be built for 26 bit or 32 bit targets.
- Fixed File.s.GetType to flow better, and added code to correctly return the filetype as zero if the file has Load/Exec addresses and no filetype.
- BUG? Looks like Filing_SingleFullDirEntry() and Filing_SingleFullDirEntry2() may be back to front - the "2" suffixed versions do not extract the filename but the non-"2" versions do (then call the "2" version). [THIS HAS NOT BEEN FIXED PENDING VERIFICATION]
- BUG? Ditto Filing_SingleDirEntry().
- BUG? Single2 and SingleFull2 set R3 to 256. Error?
- Filter library routines now call X version SWIs. This may be a little bit paranoid as the Filter SWIs claim to preserve ALL registers; though a look at the source code (...castle.RiscOS.Sources.Desktop.Filter.s.SWIS) indicates that R0 will be an error block if the initial RMA workspace claim failed, and that if the Filter could not be set up then it WILL return with V set. So the SWIs may or may not point to an error block, but V will be set on an error so calling the X version is the best bet.
- [conversions done as far as Font]
2015/07/11 (Rick Murray)
- Changed MsgTrans code to use standard definitions instead of doing its own thing.
- [converted from Font to PDriver]
2015/07/12 (Rick Murray)
- [converted from PDriver to WimpSWIs; which means conversion is complete!]
2015/07/13 (Rick Murray)
- Fixed bug in
ColourTrans_ReturnColourNumber() that was incorrectly returning -1 if there was NOT an error. Duh.
2015/07/24 (Rick Murray)
- Moved build to APCS32 directory (instead of Static). Removed unnecessary 'h' directories, and all of the DLL stuff.
DLL code will be removed as it is encountered - it is benign.
2015/07/26 (Rick Murray)
BackTrace_Simple() to output to file or screen; the backtrace is 26/32 bit compatible and correctly caters for peculiarities of the StrongARM.
- Modified existing
BackTrace functions to be 26 / 32 bit compatible.
Sprite_MemorySize() now correctly calculates the sprite size for "deep" sprites, and also uses a lookup table for the palette sizes so it can return meaningful results even if the mode itself is not available to RISC OS (for example, MODE 12 on a Pi will go to MODE 15 as the hardware does not support 16 colour modes (ditto for other modes ... 0→15, 2→28, and so on).
- Many new
Sprite_XXX() calls with a 'P' suffix (akin to GCC DeskLib naming) to provide Sprite Ops that can accept a Pointer to a sprite, and not just a name.
- Noticed that
Sprite_Get() loaded its registers incorrectly. Because of the use of APCS names, it perhaps wasn't noticed that R5 was missed and the data for R5-R7 was loaded into R6-R8 instead. Fixed.
- DeskLib has been taught about mode specifier blocks; screen and sprite functions accept them (plus the BPP/DPI way of specifying sprites); as should
Wimp_SetMode (but you shouldn't be using that!).
Resource_LoadSprites() will now ask the Wimp what sort of sprites file it would like to use. If this call fails (ancient WIMP), it will revert to looking for itself - first checking for Sprites22 if a 1:1 screen mode is in use, reverting to Sprites.
File_Size() now allows image files to be 'sized'. It also now returns -1 on an error, so it is possible to distinguish between a zero sized file and an error; as a zero length file is a lot more likely than a 4GiB file.
- Completely rewrote
Wimp_Poll[Idle](). The Wimp can save the FP registers for us, so we don't need an awful lot of code to do it ourselves. Now the poll routine is sleek and simple.
- Got sick of updating "h_doc" and "h" for every change. So now "h_doc" is "h", and that's all there is.
I am also redesigning the build process so that it can be built for APCS-32 (as it is now), APCS-R (for older machines), and maybe (some day in the future) GCC-ELF if the GCC compiler doesn't choke on the files-in-directories method of file storage.
All that remains to say is...
MOV PC, LR