C166/ST10 Toolchain v8.0r2



This release note covers version v8.0r2. It describes the changes and new features of all TASKING C166/ST10 products since v7.5r1.

In this release note several important notes are made to point out changes that require special attention.

The following sections are included in this release note:


Summary of changes between v8.0r1 and v8.0r2:

Summary of changes between v7.5r6 and v8.0r1:

Summary of changes between v7.5r5 and v7.5r6:

Summary of changes between v7.5r2 and v7.5r5:

Summary of changes between v7.5r1 and v7.5r2:



The EDE in v8.0 is highly improved and reorganized. The menu structure has changed: all items previously included in the EDE menu are now distributed over the other menus. All dialogs for setting the options are now integrated in a single Project Options dialog, accessible from the Project menu. Many pages in the project options dialog include a grid to ease the control of options for the tools. For example the memory definition for the locator.

The following files are now completely generated from EDE:

Startup code
The startup code is now entirely generated from EDE. The startup code from the library is no longer used. The option to include the startup code in the project and to generate the start.asm is by default enabled.
CrossView Configuration File
The configuration file for CrossView Pro is now entirely generated. The file is named _project.cfg. Project options like execution environment determine the contents of this file.

The register settings for the startup code are now organized per register. You can make changes to the register by typing the full value or by changing individual bit fields. Register settings made for the startup code are reflected in the configuration file to allow correct startup of the execution environment. Some registers, such as the Fast Interrupt registers have an additional special page at the end of the list of registers to easy settings.

Flash Setup is added and CrossView Pro can be configured to download the application into Flash. See the description of Flash support from CrossView Pro in this readme file for more information.

It is now possible to specify a directory in EDE for all output files of the tools in the Project | Directories... dialog.

When the project options are changed before a build is started, EDE will build what's necessary. For example if compiler options are changed, build will recompile all C files in the project, even if the file stamps are up to date. This prevents forgetting to rebuild when options are changed. When the CrossView Pro debugger is started when the project is out of date, EDE will notify you before starting the debugger.

Several dialogs now have so-called What's This Help. These dialogs have a small button with question mark [?] on the title bar of the dialog. You can click this button and then click an option in the dialog to get help on that option.


Although EDE converts the settings from your project file of previous versions, it is still recommended to double check your project options and register settings.

Smart Linking specifications of previous versions of the C166/ST10 EDE are not converted. You do have to define the specification again.

The startup code is now fully generated from EDE. This also means that EDE no longer generates a macro definition include file. If you are using the macros as generated by previous versions of EDE, it is recommended to keep using the file as generated from that version and to maintain the file manually. It is no longer possible to include DAvE generated macros in assembly files from EDE. If you are using this it is recommended to include the DAvE generated macro file in your source by using a $INCLUDE control. EDE supports integration with DAvE by importing the DAvE generated project file.

The memory reserved for debug monitors now fully depends on the selected execution environment. If custom memory reservations are required these should be reserved as normal memory reservations.



The C++ compiler is now accompanied by the Standard Template Library (STLport). The libraries are installed in the standard lib directory and include files can be found in include.stl. These libraries and include files will be used by default for C++ sources. These libraries are available for the small and large memory model for extended architectures and XC16x and Super10. The user stack model is not supported with these libraries.
If needed the libraries can be rebuilt in any variant by using the makefile in the lib/src.stl/lib directory, where lib represents the variant to be built.
The STL is linked to the application by two libraries:

stl166model.lib - the majority of the STL functions.

stlo166model.lib - an optional part of the STL. If this file is omitted  the functionality of the STL is reduced and the size of the application is reduced significantly. When this part is not linked, using the <string>, <iostream>, <istream>, <ostream> or <fstream> headers will result in errors and the monetary, locale and number punctuation support are not available.

The control program cc166 supports two new options to disable linking the STLport libraries:

  -nostl  - do not link any of  the STL files

  -nostlo - do not link the optional STL part



Data Flow Analysis Peephole

A new optimization phase has been added to the C compiler: Data Flow Analysis Peephole (DFAP). This phase replaces the peephole phase of previous versions of the compiler. The main difference is that DFAP analyzes the data flow, which makes it possible to do more thorough optimizations than before. You can enable the DFAP on the command line with the -Ov option. Or from EDE on the Optimizations page. By default the DFAP is disabled. When the DFAP is enabled the compilation process may take longer than with previous versions of the compiler. How much, depends on the characteristics of the compiled code.

Two pragmas are introduced to switch the DFAP on or off: from the source code. This is only effective if the -Ov option is used.
    #pragma dfap
    #pragma nodfap

The instruction scheduler is now also based on the DFAP, which improves level of scheduling. For example instructions can now be moved outside if- and loop-constructions. The instruction scheduler can be enabled with the new -Om option or from the Optimizations page in EDE. The instruction scheduler is only active for Super10 and C166S V2 based processors. By default the instruction scheduler is enabled.

Startup Code

The startup code has been reorganized and cleaned up. EDE now completely generates the startup code instead of including the start.asm from the lib\src directory. For users not using the EDE, the startup code in lib\src changed in the following way:

start.asm is replaced by:

These startup codes include the following header files from the include directory:

The file procdir.asm and start.asm are no longer included in the product. The macros to control the startup code are compatible with previous versions.


When not  using EDE, references to start.asm and start.obj in an existing project must be changed to match the names as described above.

Constant String Overlaying

By default string constants are allocated in the memory model's default memory space. The following new pragma can be used to overrule this:
#pragma stringmem memory-space 
memory-space string location
_near near ROM
_xnear xnear ROM
_far far ROM
_shuge shuge ROM
_huge huge ROM
default memory model default
The "default" argument will allocate strings in the memory model's default memory space. In the small memory model this also means that the -OE/e option is effective. The pragma can appear anywhere in the source and will remain active until the pragma is used again to set a different memory space.

Improved Packed Structure Support and Unaligned Global and Static Variables


The support of packed structures is slightly changed and has incompatibilities with v7.5, as described below.

The packed structure support is improved. The _noalign keyword is added, which makes it possible to have unaligned access to all types of global and static variables.


_noalign int i;
_noalign int j = 2;
_noalign int * p; 
 int * _noalign p;

Using definitions like:  _packed struct s; struct s; will now yield an error, while this was allowed in v7.5. Pointers to _packed structure or union members must now be qualified as _noalign, while in v7.5 this was _packed. So  _packed int *p; must be modified into  _noalign int *p;

A packed structure or union is now no longer unaligned by definition. If the packed structure is allowed to be allocated unaligned the _noalign keyword should be used:

typedef _packed struct ps 
    char c;
    int i; 
} tS; tS st0; /* aligned packed structure */

_noalign tS st1; /* possibly unaligned packed structure */ 

Reentrant Return of Structures

In compiler versions before v8.0 a struct/union is returned in a static global memory area, one per function. The memory space where the return value is allocated in, is the default memory space for the used memory model. Depending on the memory space, R4 (_near) or R4/R5 (_far) holds a pointer to the static memory area.
Whenever a struct/union is small enough to fit in an (long) int, the value will be returned in R4 or R4/R5.

In v8.0  a struct/union is returned on the user stack. The user stack area is allocated directly on top of the stack parameters:


R0 ==>

struct/union return value
Function arguments (optional)

The stack space is to be maintained by the caller. Upon return R4 holds a pointer to the stack block. This can always be a 16-bit pointer since the user stack is in a short addressable memory space for all memory models. For the non-segmented models it is an _near pointer, for the segmented memory models it is an _xnear pointer.
Whenever a struct/union is small enough to fit in an (long) int, the value will be returned in R4 or R4/R5.

The new implementation allows recursive and reentrant calls to functions returning a struct/union. Because the return value is now allocated dynamically some global memory is saved. Since the user stack area is always short addressable a struct/union return value can be accessed more efficiently in the new implementation.

The new implementation does not affect the debug-ability of an application, nor are there changes to the generated symbolic debug information. Since the c166 compiler uses a separate call and data stack, a stack trace can be made as usual. The return value of a function is not accessible 'through debug information' until the return value is assigned to some object. This behavior does not differ from the previous implementation.

Adjusting the way struct/union return values are handled is a change in the calling convention. Precompiled functions using struct/union return values can therefore not be reused prior to recompilation. Also, in case of hand coded assembly changes may be required.

Wide Character Support

Wide characters are now supported. The implementation conforms to the ANSI-C standard. The compiler now initializes wchar_t strings as words, two header files are added, wchar.h and wctype.h. See the C Compiler User's Guide for an overview of the supported functions.

Register Files

The register definition header files are updated to match the new assembler register definition files. See also Register Files and Internal Register Set.

Improved Register Bank Definition

The -r option and pragma regdef are improved to provide full control over the register bank allocation from the C compiler. The interface for the -r option and the pragma regdef are slightly changed. See for more information the user's guide update at the end of this document.

Scheduler Updated for DIV Instruction

For the XC16x and Super10 the instruction scheduler now assumes that there are 17 cycles between the DIV instruction and the availability of the result. To avoid pipeline stalls the compiler will try to schedule as much instructions as possible between the the DIV instruction and using its result.



Register Files and Internal Register Set

All register files (*.def) are rewritten to include all bit and bitfield definitions and to add descriptions to all definitions. The syntax of the DEFR, DEFA and DEFB directives is extended for this purpose and DEFVAL and DEFBF directives are added. DEFBF defines a bitfield consisting of more than one bit and DEFVAL defines the possible values for a bit or bitfield. The assembler ignores the DEFBF and DEFVAL directives, but CrossView Pro uses them to display the registers and all bitfields with descriptions and values.

The internal register set of assembler is now limited to core registers only. The following registers are internally defined in the assembler:


If the EXTMAC, EXTEND2 or EXTEND22 control is enabled, the following registers are added:


The NOMOD166 control is no longer necessary when defining a register file with the STDNAMES control. For the 8xC166 this means that, just like with other derivatives, the register file must be used.


The changes in the internal register set  require the use of an STDNAMES control for all derivatives, including the 8xC166.

Some register or bit names changed to match the names used in the Infineon or STMicroelectronics user's manuals. The register definition header files (reg*.h) for the C compiler are derived from the  assembler register definition files, so that the names of registers all match. Changed register or bit names may result in an error that these names are undefined. To solve this you should change the names of the registers to match the names in the register definition file.

Macros to suppress certain devices in the C register file definition (e.g., REG167_NOCPU) are sometimes named different than with previous versions. Usually these macros are used to be able to define some registers from the application code. If this is used the compiler may reports errors on multiply defined registers. This means the macro definitions must be changed to match the ones used in the used register definition include file.

Due to the updated register files, the register window in CrossView Pro sometimes displays other registers than defined with a previous version of the tools. You can change this with the register window setup.


The DBFILL, DWFILL and DDWFILL directives are added for initializing a range of addresses with a fixed value. The arguments of these directive are the number of values to initialize and the value.

C Preprocessor for Assembly files

The control program cc166 now has a new option, -cprep to use the C preprocessor instead of the macro preprocessor (m166) on assembly files. By preprocessing assembly files with the C preprocessor it is possible to use a set of  #defines that are shared between C code and assembly code.


The macropreprocessor m166 has a new INCLUDEPATH control. With this control the search path for include files can be specified. This control is additional to the M166INC environment variable. See the full description in the user's guide update at the end of this document.


The assembler a166 is extended with a new EXPANDREGBANK control. With this control enabled register banks are automatically updated with registers used in the code. See for more information the full description in the user's guide update at the end of this document.

New DEFX Register Definition Directive

A new DEFX assembler directive is added to the assembler for defining registers that are outside the system page. For the assembler this directive is treated similar to an EQU direcitve. The CrossView Pro debugger also knows registers defined with the DEFX directive. The usage of the DEFX directive is similar to that of the DEFA directive:

name DEFX address [,attribute] [,method, reset, comment] ]

Fill Gaps in Memory Ranges with User Defined Value

The MEMORY control of the linker/locator l166 has an optional definition of a fill pattern for filling gaps between sections in a specified memory range. You can specify either to fill only the gaps between the sections or to fill out the full memory range. See for more information the full description in the user's guide update at the end of this document.
The Project Options dialog in EDE has an updated Linker/Locator - memory page, where the fill pattern can be added to a memory range.



Symbolic Register Support

CrossView Pro no longer uses the binary format register files (.dat) but now directly reads the .def file. This means also that the register manager (rm166) is no longer included in the product. The new register .def files include symbolic information on the registers. Registers with symbolic display are indicated in the register window with a small icon before the register name. If you click on this icon, the symbolic register window will pop up. This window will show the bit fields that are present in the register. Each bit field can be edited individually.

Improved OCDS Support

The support for OCDS in CrossView Pro is improved. New JTAG drivers are included. The debugger is improved in handling error situations and incorrect target configurations. Software breakpoints are now supported. From the breakpoint dialog you can define whether CrossView Pro should only use software breakpoints, only use hardware breakpoints or  use hardware breakpoints first and then, if no more hardware breakpoints are available, software breakpoints.

New Execution Environments

Several new execution environment have been added:

ROM/RAM monitor support is added for execution environments with OCDS:

CrossView Pro now supports the Phytec parallel port wiggler for the phyCORE boards.

Improved Simulator for XC16x/Super10

With version v8.0r2 The TASKING instruction set simulator has been improved for XC16x/Super10 support. This implies that the simulation is faster, that profiling and coverage are supported and that the timer peripherals are supported. The simulator does not take the processor's pipeline into account. Instruction cycles are counted in best case values and the fastest memory is assumed.

Flexible Simulator Memory Mapping

The simulator now supports three variants of mapping the simulator memory:

  1. Using explicit mapping in the configuration file. This method is the only method available in versions before v8.0r2
  2. Dynamic mapping. Memory is allocated as soon as it is accessed (read or write) from instructions or by a download. This means that the full memory range of the processor is always available.
  3. Using the map file. The contents of the map file is used to map the RAM, ROM and SFR areas. This method is used by default when CrossView Pro is started from EDE.

Using the map file can be controlled as follows:

When "using the map file" is enabled, a map file is used which has the same name as the absolute (.abs) file of the application, but with suffix .map.

When not using the map file, CrossView Pro will look into the target configuration file (.cfg) for memory mappings. If no mappings are given in the configuration file, the memory will be mapped dynamically.

When a memory location is accessed that is not mapped, CrossView Pro will stop execution just after the instruction that caused the problem and issues the message: "Program stopped: bus error on write to address XXXXX". This is usually caused by a problem in your program (for example, an incorrect pointer). Also using addresses in a program without  allocating memory for it may result in this error.


OSEK RADM Supports ORTI 2.0 and 2.1

The OSEK RTOS Aware Debug Module (RADM) now supports both the ORTI v2.0 an v2.1 specifications.

Compare Application

CrossView Pro can now compare an (application) file with the application downloaded in the target. This can be useful when you want to check if the program code has been changed, for example due to uninitialized pointers. To compare an application: From the File menu select Compare Application...

Flash Memory Support

With CrossView Pro v8.0 you can download an application file to Flash memory. Before you download the file, you must specify the type of Flash devices you use in your system and the address range(s) used by these devices. CrossView Pro downloads a Flash programming monitor to the target to execute the Flash programming algorithm. This Flash programming monitor is included in source in the mon directory of the installed product.

To configure the used Flash chips before starting CrossView Pro from EDE:

  1. From the Project menu select Project Options...
  2. In the left pane, select Application and then Flash Setup
  3. Configure your Flash in one of the pages.
  4. In the left pane, select CrossView Pro and then Initialization
  5. Make sure the Program Flash when downloading checkbox is enabled.
  6. Click OK to close the dialog.

To configure Flash from CrossView Pro:

  1. From the Target menu select Flash Setup...
  2. Configure your Flash chips.

Use the online help in CrossView Pro for more information.

CrossView also supports the on-chip Flash devices.

CrossView Pro on Windows 95 & Windows NT

CrossView Pro requires the DLL ws2_32.dll which is not standard available on Windows 95 systems without any service pack installed. If you start up CrossView Pro and get a message that it cannot find the ws2_32.dll, you should either install Windows 95 Service Pack 1 or download the DLL

CrossView Pro requires the DLL shlwapi.dll which is not standard available on Windows 95 and Windows NT. When starting up CrossView Pro from the start menu you will get the message that it cannot find the shlwapi.dll. From EDE, CrossView Pro will simply not start. To solve this problem, you should install Internet Explorer version 5.0 or higher. These versions of Internet Explorer will install the shlwapi.dll.


Processors Added

The following processors are added:


For all processors assembler register files (.def) and C header files (.h) are added, and simulator configurations are added.


C166S V1

The Infineon C166S V1 core is now supported by a dedicated C compiler option (-x1) and assembler control (EXTEND1). The silicon problems registered as CR105685 CR105840 CR107344 are part of the default behavior of the core and are now covered by the -x1 compiler option and EXTEND1 assembler control.

The libraries for the extended architecture (ext) should be used in combination with the C166S V1.



MiniTASK Example Added

The new MiniTASKexample is a small time slicing multitasker. Being completely written in assembly, it is extremely small and fast. It is not a replacement for a full-blown RTOS. It does not provide means for inter-process communication, neither does it shield processes from each other. In an embedded system however, this often is a non-issue. Load balancing and being able to run parts of the software "in the background" often are important.

You can freely use the code of this example in your C166/ST10 application. The example contains an extensive readme file on configuring the code of MiniTASK for your application.



C Compiler -r Option and pragma regdef




regdef [regdef | nr]


name :
the name of the register bank for this module
c :
common flag
the register bank definition


With the -r option you can specify the name of the register bank in the module. When the C-flag is added the register bank will be declared common. The regdef argument is specified as a comma separated list of register ranges. A range is defined as: Rx[-Ry]

When a register bank is declared common, the resulting range must consist of consecutive registers, starting from R0. In all cases R0 must be present in the register definition. If not, the compiler will add this register and generate a message. The register definition will remain valid until the next #pragma regdef in the source.

When only the name and optional common flag are used in the -r option, a full register bank consisting of R0-R15 will be the default.

When the -r option is used without any arguments, the REGDEF directive for this module will be omitted. Note that register banks originating from the _using() function qualifier will still be generated. Interrupt functions to do not have the _using() qualifier use the module' register bank. Since this bank will be omitted, no code will be generated in the interrupt frame to switch register banks.

With #pragma regdef the used register set can be redefined. A pragma setting will remain active until the next #pragma regdef. The syntax for regdef is the same as in the -r option. As an alternative the number of registers, starting from R0 may be specified.

When different register sets are used for different functions, the compiler will combine the register sets for the same register bank.

When #pragma regdef is used without arguments, or with argument 0, the REGDEF directive for interrupt functions will be omitted, even if the _using() qualifier is used. In this case the compiler will not generate code in the interrupt frame to switch global register banks.


When the register set that the compiler can use for code  generation is limited this can result in larger code. When the  register set is too small the compiler may not be able to   generate code at all. In this case assertion errors can be expected. This is a known restriction and the register set should be increased prior to reporting the assertion error.


c166 -rmybank sample.c

This option declares a register bank with name "mybank". Unless otherwise specified with #pragma regdef, the register bank will consist of R0-R15.


c166 -r,r0,r3-r5,r10-r15 sample.c

This option causes all functions (non-interrupt and interrupt) to use the registers from the given set.


#pragma regdef r0,r1
void _interrupt( 0x10 ) _using( SOMEBANK ) ISR0( void )
        . . . 
#pragma regdef r0,r2
void _interrupt( 0x11 ) _using( SOMEBANK ) ISR1( void )
        . . .   
#pragma regdef r0,r3
#pragma regdef
void _interrupt( 0x12 ) _using( OTHERBANK ) ISR2( void )
        . . . 

The functions ISR0 and ISR1 will use registerbank SOMEBANK. Function ISR0 will only use registers R0 and R1. Function ISR1 will only use registers R0 and R2. The compiler will combine the used register sets and generate the following REGDEF directive:  SOMEBANK REGDEF R0-R2

Function ISR2 will only use the registers R0 and R3. Since #pragma regdef without arguments is used, the compiler will not generate a REGDEF directive, nor will code be generated to perform a context switch.


c166 -rcomnbank,c,R0,R1,R2-R5 sample.c

This option declares a common register bank with the name "comnbank": COMNBANK COMREG R0-R5.


Assembler EXPANDREGBANK control










Normally, each module uses a single register bank, defined using REGDEF, REGBANK or COMREG directives. Several of these directives may be used, but the assembler will combine all definitions with the declarations and issue appropriate warnings if register are not present where they should be. The NOEXPANDREGBANK control allows overriding this behavior and prevents the assembler from expanding the various register definitions and declarations with the register that are actually used in the code.

When a module contains several routines that use independent register  banks, this control can be used to override the default assumption that  all code in a single module uses the same register bank. The user is responsible for allocating the correct registers to the register bank  used at runtime. Failing to allocate registers can result in use of register areas from different banks due to memory overlap.

Macropreprocessor INCLUDEPATH  Control









Description: Sets an alternative include search path for the preprocessor. Multiple search directories may be specified by separating them using a semi-colon (Windows) or colon (Unix). If a file specified using the INCLUDE control cannot be found in the current directory, it is first searched in the directories specified using this control. If it is not found there either, the directories specified by the M166INC environment variable are searched. After that, a file not found error is issued. Multiple specifications of this control overwrite the previous specification. Only the last specification takes effect.


Search the product include and library source directories for included files:

m166 INCLUDEPATH(C:\Program Files\Tasking\c166 v8.0\include;C:\Program Files\Tasking\c166 v8.0\lib\src) 


Updated Linker/Locator MEMORY Control

The MEMORY control is updated with the FILLALL and FILLGAPS attributes for the ROM ranges.


MEMORY( memory-control, ... )

MEMORY memory-control




Locate general




With the MEMORY control you can specify which areas in the target memory are ROM, RAM or internal RAM.

memory-control must be specified as:

The arguments addr1 and addr2 specify the first and last address in a range.

With the ROM sub-control you can specify which address ranges are ROM. All sections and other memory elements with the ROM attribute will only be located in these ranges. When the ROM sub-control is not specified, all ranges which are not RAM or IRAM are specified as ROM.

With the RAM sub-control you can specify which address ranges are RAM. All sections and other memory elements with the RAM attribute will only be located in these ranges. When the RAM sub-control is not specified, all ranges which are not ROM are specified as RAM.

When you specify the IRAM sub-control (default), the locator marks the internal RAM area as RAM. The size of the internal RAM is specified with the IRAMSIZE control. When the IRAM sub-control is specified with the addr argument, the start address of the internal RAM is specified. The end address of the internal RAM is always 0FFFFh. When addr is specified it overrules a previous (or the default) IRAMSIZE control. The addr argument should be lower than 0FE00h to ensure the SFR area can always be located.

When you specify the NOIRAM sub-control, the locator does not mark the internal RAM as a RAM range. This allows you to place code in internal RAM, which is for instance needed for bootstrap code.

With the ROM sub-control you can specify a byte or word size fill value for gaps between sections or for the whole memory range. With FILLGAPS(value) attribute only gaps between sections are filled. Such gaps are introduced for example by section alignment, certain section orders or absolute sections. When using the FILLALL(value) attribute all areas not used by sections in the specified ROM range are filled with the value. The value can be a value of one byte or one word. With a word value, the high byte is used to fill the even addresses and the low byte is used to fill the odd addresses. In case the high byte is zero the value should be represented as hex pattern enclosed in single quotes. Some example values are:

0xFF  - byte fill value

0xA55A -  word fill value, odd addresses are filled with 5A, even addresses are filled with A5

0x00FF - same as 0xFF

0FFh - same as 0xFF

255 - same as 0xFF

'00FF' - word fill value with zeros on even addresses and FF on odd addresses.

A section or memory element gets the ROM attribute when it contains initialized memory, otherwise it gets the RAM attribute. In the assembler there are only a few directives which allocate not initialized memory: DBIT, DS, DSB, DSW, DSDW, ORG and EVEN in a section other than CODE.

When the ROM or the RAM sub-control is used the memory layout is defined and the CLASSES control is superfluous, so the locator sets the control NOCHECKCLASSES.


MEMORY( ROM( 0h TO 3fffh, 8000h TO 0BFFFh ),
    RAM( 4000h TO 7FFFh, 0C000h TO 0FFFFh ) )
MEMORY( ROM( 0h TO 7fffh ),
   RAM( 8000h TO 0FFFFh ) 
   IRAM( 0F600h )
   ROM( 10000h TO 13fffh ) )
; fill gaps between sections with FF
MEMORY ROM( 0x000000 TO 0x007FFF FILLGAPS(0xFF) )
; fill whole range with TRAP #0 instructions
MEMORY ROM( 0x000000 TO 0x007FFF FILLALL(0x9B00) ) 

New Linker/Locator Control CODEINROM






Locate general




The CODEINROM control will force the locator to put all code sections in ROM memory. In versions older than v7.5r2, the locator put code sections of size 0 into RAM. Using NOCODEINROM will switch back to that behavior.

@(#)readme.html 1.17