home *** CD-ROM | disk | FTP | other *** search
- ############################################################################
- # #
- # ExpCode utility #
- # #
- #==========================================================================#
- # #
- # by David Radford #
- # #
- #==========================================================================#
- # #
- # These files are a part of !CompUtils and may not be distributed #
- # separately other than as laid down in the !ReadMe file. #
- # #
- ############################################################################
-
- Overview
- ========
-
- This directory contains a short piece of code called ExpCode (in several
- 'flavours'), which will expand compressed samples produced using the
- !Compress application or one of the Compress utilities. It is intended for
- use by programmers who wish to use squashed samples in their own programs.
- ExpCode is basically just Expand with some additional code added to tailor
- it for main use of Expand: decompressing a sample straight from a file to
- memory. It reduces the flexibility of Expand but is much easier to use.
-
-
- The ExpCode utility
- ===================
-
- ExpCode provides an interface with the Expand utility, designed to reduce
- the amount of programming YOU have to do to a minimum when you just require
- the simplest function of Expand.
-
- There is a version of ExpCode for each version of Expand ie. one for each
- group of sample types (Type0-2, Type6) together with a Universal version
- which will decompress anything. Naturally, the Universal version is much
- larger than the others.
-
- ExpCode, like Expand, has a general header at the start used for passing
- parameters. Where possible this has been designed to conform as closely as
- possible to the one used by Expand. The layout is as follows:
-
- +0 branch instruction to ExpCode_InitCode
- +4 branch instruction to ExpCode_ProcessCode
- +8 filetype for compressed samples
- +12 pointer to the source buffer (user provided)
- +16 length of source buffer (user provided)
- +20 pointer to the destination buffer (user provided)
- +24 length of destination buffer (user provided)
- +28 ptr to source filename (user provided)
- +32 sample period of output sample
- +36 output flags (user provided)
- +40 length of final sample
- +44 offset into file of actual data (user provided)
-
- Your program can decompress a sample in a series of simple steps:
-
- 1) Reserve space for a source buffer (no minimum, but less than 256 bytes
- would probably cripple performance).
- 2) Set +12 to point to this buffer.
- 3) Set +16 to the length of this buffer.
- 4) Set +28 to point to the filename of the sample to decompress.
- 5) Set +36 (flags) as for Expand. Refer to the documentation in Expand's
- directory for details.
- 6) Set +44 to the offset into the file of the actual data (usually zero).
- Non-zero values are useful for sample libraries, or for adding some
- extra information of your own to the start of the file.
- 7) Call +0 to initialise the code. This sets up the values at +32 and +40.
- After the call, R0 is zero and the V flag is clear if no error occurred,
- otherwise the V flag is set and R0 points to a standard error block. If
- an error has occurred you should abort the operation.
- 8) Use the value at +40 to create space to store the final sample.
- 9) Set +20 to point to this area of memory.
- 10) Set +24 to the length of the area, which must be greater than or equal
- to the value at +40.
- 11) Call +4 to decompress the sample in your chosen format. After the call,
- R0 and the V flag have been set up in the same manner as in step 6.
-
- All samples are decompressed without the sample period byte that Armadeus
- files provide at the start, but since the value is returned in the header
- you can add this to the output yourself if you want to produce Armadeus
- files.
-
- The data offset at +44 may need some explaining. Normally you will just
- leave this value as zero. However, it is a fact that the amount of space
- taken up by several small files on a floppy disc is greater than the sum of
- their lengths. This is because a file always takes up a whole number of
- sectors on a disc. If each sector is 1024 bytes long, a file of size 4123
- would actually occupy 5120 bytes of disc space (5*1024). This obviously
- means that some space is wasted.
-
- A way of getting round this problem is to add the files together into one
- large file (a sample library). This makes more efficient use of the
- available disc space. As you do this, make a list of the positions of each
- of the small files in the library. These file offsets can then be supplied
- at +44, with a pointer to the file name of the library at +28, and the
- sample will be decompressed exactly as if it were a separate file.
-
- Details of a standard file format for library files can be found in the
- documentation in the LoadSample directory. The LoadSample module fully
- supports this format, as does SamplePlayer (from !Player) after version
- 1.23.
-
-
- Technical details
- =================
-
- (Basic and C programmers can ignore all this information.)
-
- Both machine code routines require R14 to give a return address. All
- registers are preserved (except R14 and R0), and a temporary stack is set up
- inside ExpCode for use by Expand, so you needn't worry about R13 containing
- a stack pointer.
-
- The exception to this is if you want to call ExpCode from a non-user mode
- such as SVC mode (eg. for *commands, SWI handlers, module initialisation
- code, etc.), since the internal stack used by ExpCode in USR mode is not
- large enough to cope with the demands of RISC OS interrupt-driven routines
- as well. If ExpCode is entered in a non-user mode it will automatically
- detect this and NOT use it's own stack, but instead use the stack pointer
- passed in R13.
-
- There is a potential problem when ExpCode is being used in IRQ mode (or FIQ
- mode for that matter) with interrupts enabled, since r14_irq can suddenly
- become corrupt. To avoid this change the ARM to either SVC or USR mode
- before calling ExpCode. This problem doesn't apply when using ExpCode from
- Basic of course.
-
-
- Output flags
- ============
-
- See the documentation with Expand for a description of the output flags. Any
- flags modified by Expand (eg. the status flags in the top few bits of the
- word) will be returned correctly to your program through ExpCode's header.
-
-
- Filetypes
- =========
-
- The filetype for compressed samples is not Acorn-allocated and could have to
- change in the future. To make upgrading easier, the filetype should not be
- assumed to be &350 but should be read from ExpCode's header.
-
-
- Using ExpCode with your own programs
- ====================================
-
- Basic
- -----
-
- Choose an appropriate ExpCode file and copy it into your application's
- directory. You can load it using something like this:
-
- SYS "OS_File",5,"<App$Dir>.ExpCode" TO a%,,,,l%
- IF a%<>1 THEN l%=16
- DIM expcode% l%
- SYS "OS_File",255,"<App$Dir>.ExpCode",expcode%,0
-
- and the code can be called with:
-
- CALL expcode%+0
- or
- CALL expcode%+4
-
-
- Assembler
- ---------
-
- When including ExpCode in your own programs there is no reason why it has to
- be kept as a separate file in your application's directory. It is actually
- designed to be embedded somewhere in the middle of your own code. Refer to
- the Technical Details section for more information on calling ExpCode from
- machine code programs.
-
-
- ObjAsm
- ------
-
- Users of Acorn's Desktop Assembler will find an AOF version of ExpCode in
- the 'asm' sub-directory. A header file is provided to IMPORT all the symbols
- you'll need. All you have to do is include the line:
-
- GET CompUtils:ExpCode.asm.h.Universal
-
- at the start of your source code, then add the appropriate object file to
- the list of objects and libraries to be linked. There is one object file
- for each group of sample types supported (eg. Type0-2, Type6, etc) plus a
- 'Universal' version incorporating all of these. Only one header file
- is provided (Universal) because the header would be the same for each object
- file anyway. By the way, only one ExpCode object can be linked to your code,
- unlike Compress. If you need two or more then use the Universal version.
-
- The header file imports symbols for the start of the ExpCode header
- (ExpCode) and each of the two entry points (ExpCode_InitCode and
- ExpCode_ProcessCode). It also defines symbols for offsets from the start of
- the header to various entries in the header (eg. ExpCode_SrcBufferPtr,
- ExpCode_SamplePeriod, etc). So, to read the sample period you would use
- something like this:
-
- LDR R0,=ExpCode
- LDR R1,[R0,#ExpCode_SamplePeriod]
-
- The first instruction transfers the address of ExpCode's header into R0,
- then the second instruction transfers the contents of the sample period
- entry into R1. To call ExpCode use:
-
- BL ExpCode_InitCode
- or
- BL ExpCode_ProcessCode
-
- Apart from these symbols, the header file also defines a series of symbols
- for various bits in the output flags eg. OUTPUT_LINEAR, FILE_IS_16BIT, etc.
- These should be used in preference to actual values (eg. 1<<2 or 4+2+1)
- where possible to allow these to be changed in the future, should the need
- arrise. It can also be used to highlight trouble spots, if a bit's meaning
- changes.
-
-
- C/APCS
- ------
-
- For C users, a header file and a series of object files can be been found
- in the 'cc' sub-directory. Only one header file is provided (Universal)
- because all the decompressors have an identical user interface, so the
- Universal version can be used for any of them. An object file is provided
- for each group of sample types (eg. Type0-2, Type6, etc) plus a Universal
- version combining all of these. Only one of these object files can be linked
- with your code; if you want more than one then use the Universal version
- instead.
-
- The object code is APCS-compliant (obviously) so can be used from any APCS
- language, such as Pascal, C++, etc. You would have to write your own header
- file though - the one provided is for C, and should be included in your
- source with:
-
- #include "CompUtils:ExpCode.cc.h.Universal"
-
- It defines the entries in ExpCode's header as global variables that can be
- accessed just like normal variables eg.
-
- int filetype;
- int count;
- char *buffer;
- char bytes[16];
-
- filetype = ExpCode_SampleType;
- buffer = ExpCode_SrcBufferPtr;
- for (count = 0; count < 16; count++)
- bytes[count] = buffer[count];
-
- Apart from these variables, the header file also defines a series of symbols
- for various bits in the output flags eg. OUTPUT_LINEAR, FILE_IS_16BIT, etc.
- These should be used in preference to actual values (eg. 1<<2 or 4+2+1)
- where possible to allow these to be changed in the future, should the need
- arrise. It can also be used to highlight trouble spots: if a bit's meaning
- changes then so would the name attached to it, and the compiler would spot
- the fact that the symbol no longer exists.
-
- The two entry points are defined as functions with no arguments and
- returning a pointer to a structure of type 'os_error' (a null pointer if no
- error occured). This is just like most of the RISC OS library functions.
-
-
- Bugs
- ====
-
- There may well be some bugs lurking around, particularly in the ObjAsm and C
- versions of ExpCode (I never use these myself). They have been tested with
- the example programs so they should work, but you never know. Please report
- any bugs, omissions or suggestions for improvement to one of the addresses
- in the main !ReadMe file.
-
-
- (c) David Radford
-
-
-