BASIC DOCUMENTATION FOR PL1 VERSION 1.8 (MARCH 1996) ---------------------------------------------------- PL1 is 100% freeware, but ONLY for PERSONAL USE (NOT for BUSINESS USE in any way). A small donation ($10) is appreciated to show me you like PL1. Just to encourage me to support PL1 now and in the future. If you are not able to sent me a donation, sent me a postcard instead. All rights are reserved. PL1 is provided "as is" without any guarantee of any kind. PL1 is an acronym for Portfolio Language one and should not be confused with PL/1 (another old programming language not for the Atari Portfolio). The names Atari and Portfolio are registered trademarks of Atari Corporation. REQUIREMENTS ------------ Disk: about 12 Kb to store PL1.COM space to store programs Memory: about 12 Kb to load PL1.COM about 128 bytes stack for PL1 itself about 256 bytes stack to run a program space to load programs space to store variables PL1 will use 63Kb totally at maximum (1 Kb is left free) Environment: DOS version 2.11 or higher Preferable a Portfolio FEATURES OF PL1 --------------- - Cheap (donation of $10 is appreciated) - Fast (about 10x faster than PBASIC) - Small (less than 12 Kb) and small sized programs (mostly smaller than equivalent machine code) - Dynamic memory and supporting functions (including use of pointers and pointer arithmetic) - String type and string manipulation functions - Double precision floating point arithmetic - File functions - Graphics functions (including CIRCLE command and scalable font) - Structured programming (IF, WHILE, FOR, and PROC) - Automatic indentation and line numbering - Easy interfacing to machine code (INT and CALL) - Works on all DOS compatible platforms When run on a Portfolio the following applies: - Fast screen refresh using direct hardware in/output in graphics mode - Support of TONE and DIAL commands (ignored when executed on a standard PC) - Support of PORT, BLINK, RATE and WAIT commands (ignored when executed on a standard PC) - In EDIT mode the build-in line editor of the Portfolio is used (see your Portfolio manual for key-strokes) The presence of a Portfolio is automatically detected. INTRODUCTION TO THE CONCEPTS BEHIND PL1 --------------------------------------- PL1 is a powerfull but not an easy language. If you're not an experienced programmer and/or you don't need the power of PL1, then use PBASIC of BJ Gleason instead. To see the power of PL1 try the following PBASIC program: FOR index2 = 1 to 100 PRINT index2 FOR index1 = 1 to 10000 result = index1 + index2 result = index1 - index2 NEXT NEXT and compare the speed and size to the following equivalent PL1 program: FOR 100 1 index2 index2 % STR PRINT NL FOR 10000 1 index1 index2 % 1 + result = index1 % 1 - result = ENDFOR ENDFOR Language Size Speed ------------------- --------- ----------- PL1 version 1.8 89 bytes 20 seconds PBASIC version 4.91 140 bytes 200 seconds Tested on a COMPAQ prolinea 4/66 (80486/66Mhz). I could not execute this test on my Portfolio, because PBASIC version 4.91 does not run on my 128 Kb Portfolio. Notes: - When range checking is disabled PL1 is even faster. (see PROP command) - For large programs the size advantage becomes even bigger (see text below for explanation) This difference in speed and size is there because the underlying concepts of PBASIC and PL1 are different. PBASIC is a text-interpreter and PL1 is a semi-compiler. PL1 does not store text, but semi-compiled code. When entering a line in PL1 all keywords and identifiers are tokenized (translated in numbers) and then stored. All identifiers (variable names) are stored only once in a symbol table and reference by an index number. Token and identifier numbers are represented by one byte only. It is obvious that this technic of storing a program saves a lot of space compared to plain text. The resulting programs are mostly even smaller than the equivalent programs in machine code. And there's more, all jump's (occuring in FOR's, IF's, WHILE's and PROC's) are resolved before the actual program- run is started (this fase is called the scan). This means that when during the run-fase for example a FOR-statement is executed the place to jump back from the ENDFOR to the FOR is known. So no computing or scanning is required anymore, PL1 jumps directly to the correct token. An interpreter that uses this technics (tokenizing and pre- scanning) is called a semi-compiler. A semi-compiler combines the advantages of interpreting and compiling. An interpreted program (like many BASIC-dialecs) is easily changed (just retype/add/delete lines and run) but is slower than compiled code. Compiled code is fast, because it is normally machine code but not easily changed (you have to re-compile and re-link the program all over again). A semi-compiled program is easily changed and has a reasonable speed. WHY IS PL1 ITSELF SO SMALL? --------------------------- PL1 itself is so small because is was written 100% in assembler and things were kept as simple as possible. The assembler code counts about 8500 lines. The size of PL1 version 1.8 is less than 12 Kb. PL1 has no expression evalutor. All arithmetic operations are done using a stack (like in FORTH). This is one of the reasons why PL1 is not simple (intuitive) to use and one of the reasons why PL1 is small. After a short while you will get used to this. You have to re-write all your expresions from the usual in-fix to post- fix notation. Some HP calculators used post-fix notation as well. The words 'in' and 'post' refer to the position of the operator. Below you can find an example of an in- fix expression followed by the equivalent post-fix expression: in-fix: ( 10 + 12 ) * ( 2 - 4 / a ) post-fix: 10 12 + 2 4 a / - * Note that parenthesis are never needed when using post-fix notation. To give you a feeling of post-fix notation I will decribe the above post-fix example in words using the stack- paradigm: 1. Push the values 10 and 12 on stack, 2. Add the two numbers on top of the stack and replace them by the result, 3. Push the numbers 2 and 4 on stack, 4. Push the value of the variable 'a' on stack, 5. Divide the two numbers on top of the stack and replace them by the result, 6. Subtract the two numbers on top of the stack and replace them by the result, 7. Multiply the two numbers on top of the stack and replace them by the result. On top of the stack remains the result of the complete expression. Suppose the variable 'a' has the value 2, then after each step the stack looks as follows: | | | | 2| | | | | | | 4| 4| 2| | | |12| | 2| 2| 2| 0| | |10|22|22|22|22|22| 0| bottom of stack +--+--+--+--+--+--+--+ step 1 2 3 4 5 6 7 THE THREE MODES OF PL1 ---------------------- PL1 has three modes: command-, run- and edit-mode. When started PL1 is in command-mode. You can enter run- and edit-mode by giving the commands RUN and EDIT. Below the properties of the three modes will be described. Command-mode ------------ You can recognize command-mode by the prompt '>'. In command mode the following commands are valid: EDIT SAVE SIZE TEXT RUN LOAD STACK MERGE NEW BYE PROP Below you can find how to use these commands. EDIT EDIT EDIT The EDIT command brings you in the editor, which will be described in the section edit-mode. If a line number or procedure name is specifies, the editor starts at the specified location. RUN RUN RUN Start the program. You can interrupt a program by pressing the Ctrl and Alt key simultanously. When a line number or procedure name is specified, tracing will be enabled when that the specified point in the program is reached. When tracing is enabled each line is printed BEFORE execution. After the line number, the number of bytes on the stack will be printed. Tracing is not possible if break checking is disabled (see PROP command below). Tracing can be stopped by pressing the Esc key. Any other key steps to next line. NEW Erases program and symbol table. SAVE Saves the program in memory using the specified file name. LOAD Loads a program using the specified file name into memory. BYE Returns you to the DOS command line. SIZE Prints the actual size of the program (without the size of the name table) and the number of names used in the program. STACK STACK Prints the size of the stack (default 256 bytes). Or modifies the size of the stack to the number of bytes. The size of the size is SAVEd with the program (not the stack itself). An integer or pointer needs two bytes on stack and a floating point number needs eight bytes on stack. PROP PROP Prints the program property byte value or modifies it. This value is bit code as follows: 128 no break checking when running 64 no range checking when running 1 protect program other bits are reserved for future use (you can set them, but you should not do that for future compatibility) Setting bit 1 is irreversable. After setting this bit you cannot EDIT the program anymore. However tracing is still possible. If you don't want anyone to see your program, disable break checking as well (property value 128+1=129). TEXT Save the program in memory as plain text using file name. Note that this makes it possible to print your program. MERGE Merge the specified text file after the program in memory. Enter the NEW command first if you don't want to merge the specified file with an existing program in memory. Note that this is a simple way to build your program using pre- written procedures, just merge all needed procedures and write a main line. The TEXT and MERGE commands make it possible to edit your program using a standard ASCII text-editor (for example the build-in editor of the Portfolio). This makes it easy to copy/move large blocks easily. For all commands that work with a file name applies that there is no default file suffix. Run mode -------- You can enter run mode by giving the RUN-command or by running PL1 with a program file name as command line. For example: PL1 SNAKE It is possible to redirect the input and output. Remember you can interrupt a program by pressing Ctrl and Alt together (except when break checking is disabled). Edit mode --------- The EDIT command brings you in edit-mode. In this mode you can view and edit your program. You can use the following key strokes: Enter Insert a new line Escape Return to command mode Cursor Up Scroll one line up Cursor Down Scroll one line down PgUp Scroll one page up PgDn Scroll one page down Home Jump to first page End Jump to last page Delete Delete current line Cursor Right Edit current line Backspace Insert last deleted/entered/changed line at current position Ctrl-R Run program To add new lines at the end of the program, position the cursor after the last line and press enter. To start a new program, enter edit-mode and press enter. On the Portfolio you can enter empty lines, on a standard PC you cannot. Entering an empty line on a standard PC aborts multi-line edit. On the Portfolio you can abort editting a line by pressing the escape key. On the Portfolio you can edit an existing line using the build in line editor (see your Portfolio manual for key strokes). On a standard PC this is not possible (you have to retype the line). The maximum line length (text) is 80 characters. When you edit a long line on the Portfolio, the line will scroll. A small triangle at the end of the line shows on the Portfolio that a line is longer than can be show. You can put as many keywords on a line as you like. Each line takes one extra byte (an empty line is stored as one byte). All keywords must be entered in lower case (PL1 will convert them automatically to upper case) and must be separated by one space. You can add comments to your program using a semi-colon (;) as separator. When writing a program you can use keywords and operators described below. All operators work on the top of the stack (see the text about post-fix notation above). Generally, if a keyword description indicates that for example x, y and z should be on stack, then z should be on top of the stack. Constants --------- All constants are stored in the program and pushed on the stack when encountered during run. Use plain numbers to specify integers. Example: 3 12345 Prefix binary numbers by '0b' and hex numbers by '0x'. A binary number is stored as a byte and a hex number is stored as an integer. Examples: 0b01010101 ;binary number 0xab81 ;hex number Prefix floating point constants by '#'. Examples: #6.28 #6e-19 #-7.1 #1.2e67 Use single quotes to specify character constants. Example: 'c' 'h' 'a' 'r' Use double quotes to specify string constants. The pointer to the string is pushed on stack. Strings are prefixed by a length byte (this restricts the string length to 255 characters). Static strings cannot be altered. You can use a backslash to specify hex control characters in a string. Example: "Hello world\0d\0a" Calculation ----------- + addition (integer) - subtraction (integer) * multiplication (integer) / division (integer) ++ increase by one (integer, pointer on stack) -- decrease by one (integer, pointer on stack) MOD remainer of division (integer) .+ addition (floating point) .- subtraction (floating point) .* multiplication (floating point) ./ division (floating point) .PI push PI (3.1415...) on the stack .INT truncate floating point number (result is floating point too) .ABS take absolute value of floating poinrt number (result is floating point too) .POW calculate 10^x (x is an integer, the result is a floating point number) .SIGN get sign of floating point number (-1.0 is negative, 0.0 is zero and 1.0 is positive) Note that the ++ and -- operator are intended for use on a variable (on top of the stack should be a pointer to an integer and not the integer itself). All floating point routines were designed by me. They are not very fast, because they are double precision. But double precision calculation makes astronomical/astrological calculations possible on the Portfolio. (see provided example 'astro3' which calculates in real time the local star time, the ascending and mid-heaven; see same example for calculation of sine, etc) Comparision ----------- < less than (integer) <= less than or equal to (integer) <> not equal to (integer) >= greater than or equal to (integer) > greater than (integer) == equal to (integer) .? compare to floating point numbers All integer compares return 0 (=false) or 1 (=true). The floating point compare returns -1 (less than), 0 (equal to) or 1 (greater than). Boolean and bitwise operators ----------------------------- ! logical not (integer) & (bitwise) and (integer) | (bitwise) or (integer) XOR (bitwise) xor (integer) neg two-complement (integer) >> shift right (integer; number of bits on stack) << shift left (integer; number of bits on stack) Note that the bitwise and, or and xor are usable as logical operators as well (because true and false are represented by one and zero). Assigment and dereferencing --------------------------- = assign integer := assign byte % dereference integer (load integer on top of stack) @ dereference byte (load byte on top of stack) .= assign floating point number . dereference floating point number (load floating point number on top of stack) name push pointer to variable storage on top of stack All memory (variable) write accesses are range checked (unless disabled with the PROP command). Example: assign 10-b to variable 'a': 0001 10 b % - a = In words: push the number 10 on the stack, push the pointer to the variable 'b' on stack, replace the pointer on the top of the stack by the value pointed at (the value pointed at is loaded) subtract the two numbers on top of the stack and replace them by the result, push the pointer to the variable 'a' on stack, store the value below the top of the stack to the storage pointed to by the top of the stack and drop both the value and pointer off the stack Note that variable storage for integers is automatically allocated and initialized to zero. Furthermore note that variables that start with a dot (.) are considered pointers to floating point numbers. Space for floating point numbers (8 bytes per number) is allocated automatically too. The pointers to these numbers are set automatically again. Converting ---------- ITOF convert integer to floating point number FTOI convert floating point number to integer STR convert integer to ASCII string (leaves pointer to static string on stack) VAL convert ASCII string to integer .STR convert floating point number to ASCII string (leaves pointer to static string on stack) .VAL convert ASCII string to floating point number DIGIT set conversion width for STR (negative means print unsigned) .DIG set conversion width for .STR Stack manipulation ------------------ DUP duplicate integer at top of stack DROP drop intege at top of stack SWAP swap two integers at top of stack .DUP duplicate floating point number at top of stack .SWAP swap two floating point numbers at top of stack Use four integer DROP's to drop a floating point number from the top of the stack. Screen I/O ---------- PRINT print string pointed to by value at top of stack NL prints carriage return and line feed (new line) INPUT input string (pointer and length on stack) KEY wait for keystroke and pushes value of key to the top of stack (extended keys give negative values) PRESS check if key was pressed (0=no, 1=yes) (retrieve value of key with KEY) BLINK set cursor blink mode to value on top of stack (Portfolio only, ignored on a standard PC; 0=off; 1=underline; 2=block) GRAPH switch to graphics mode TEXT switch to text mode PLOT plot pixel at x, y (y at top of stack) MOVE move to x, y (y at top of stack) (works in text mode too) LINE line to x, y (y at top of stack) COLOR set color to value on top of stack (if bit 7 is set, an XOR will be performed) FONT set new font (pointer to font data at top of stack, returns pointer to previous font on stack, use zero as new font pointer to retrieve current font only, font data is organize as 8 bytes per character) MAG set font magnification factor (on top of stack) CIRCLE draw circle x, y, r (radius at top of stack) PIXEL returns color of pixel at x, y (y at top of stack) POS returns current cursor position (y at top of stack, works in graphics mode too) CLS clear screen (text and graphic mode, does NOT change cursor position; use MOVE command) SPRITE not supported (yet) When you try to print after the last character on the last line when in graphics mode, the cursor is moved to (0,0), no scroll will be performed. Note that you can print characters at any position when in graphics mode. You can print a character using it's ASCII code as follows: char % 8 << 1 | var = var PRINT (variable char contains the ASCII value for the character) You can use the following procedure to make use of the menu function built in your Portfolio: PROC menu IF PORT ! "Only for Portfolio" PRINT NL STOP ENDIF 18 ALLOC reg = 0 SEG reg % 12 + = ;ds 0 SEG reg % 14 + = ;es 320 ALLOC scr = 0x0800 reg % = ;ax 0 reg % 2 + = ;bx 0x0727 reg % 4 + = ;cx 0 reg % 6 + = ;dx scr % reg % 8 + = ;si reg % 0x0060 INT ;save screen 0x0f01 reg % = ;ax 0 reg % 2 + = ;bx 0 reg % 4 + = ;cx 1 + reg % 8 + = ;si 8 << | reg % 6 + = ;dx "\00\00" 1 + reg % 10 + = ;di POS reg % 0x0060 INT MOVE ; menu reg % @ 0x0802 reg % = ;ax 0 reg % 2 + = ;bx 0x0727 reg % 4 + = ;cx 0 reg % 6 + = ;dx scr % reg % 8 + = ;si reg % 0x0060 INT ;restore screen reg % FREE scr % FREE ENDPROC Example: 5 1 "Title\00One\00Two\00\00" menu DO STR PRINT NL Structured programming ---------------------- IF ELSE ENDIF WHILE ENDWHILE examples: IF a % 10 - 5 == "a-10=5" PRINT NL ELSE "something else is true" PRINT NL ENDIF WHILE POS DROP 10 < "x-position is less than 5" PRINT NL ENDWHILE can be anything until end of line, except for structured programming keywords. The IF or WHILE is executed, only if the top of stack is a non-zero value. This condition value is dropped before execution. The ELSE part for the IF statement is optionally. Note that is optionally, for example the following is allowed (and sometimes sensible): a % 10 - 5 == WHILE ; do someting a % 10 - 5 == ENDWHILE The IF- and WHILE-statements do not use any stack space. FOR ENDFOR can be anything until end of line except for structured programming keywords. Again is optionally. On stack should be the end-bound the starting- value and a pointer to the control-variable (last on top). Example: FOR 10 1 x x % STR PRINT " " PRINT ENDFOR You cannot modify the bounds of the FOR-statement, once set. The FOR-statement does not use any stack space. PROC ENDPROC DO The only thing allowed after the PROC-keyword is a name (and a comment). This name is considered as a normal integer value, except that it will be initialized during the scan with the address of the starting line of the procedure. You can use this name with the DO keyword to call the procedure. Note that the actual procedure the DO-statement calls can be altered run-time by providing different procedure pointers. Futhermore note that the DO-statement can be part of an expression and the a procedure can be entered with anything on stack and can return with anything on stack. Example 1: PROC add_one 1 + ENDPROC 10 add_one DO STR PRINT NL Example 2: PROC add_one 1 + ENDPROC PROC add_two 2 + ENDPROC 10 IF a % 5 == add_one ELSE add_two ENDIF DO STR PRINT NL Each executing of a DO-statement takes three bytes from the control-stack, two for the address of the line, one for the token within the line. The control-stack is growing towards the expression stack (the STACK-command defines the space for both stacks). Sound ----- TONE play a note (note and duration on stack, duration in 10 ms units) Notes are coded. Following codes come from the Atari Portfolio Technical Reference Manual, copyrighted by the Atari Corporation: Code Note Frequency (Hz) 48 D#5 622.3 49 E5 659.3 50 F5 698.5 51 F#5 740.0 52 G5 784.0 53 G#5 830.6 54 A5 880.0 55 A#5 932.3 56 B5 987.8 57 C6 1046.5 58 C#6 1108.7 41 D6 1174.7 59 D#6 1244.5 60 E6 1318.5 61 F6 1396.9 14 F#6 1480.0 62 G6 1568.0 44 G#6 1661.2 63 A6 1760.0 4 A#6 1864.7 5 B6 1975.5 37 C7 2093.0 47 C#7 2217.5 6 D7 2349.3 7 D#7 2489.0 DIAL dials a phone number (pointer to string on stack) Valid digits are: 0 1 2 3 4 5 6 7 8 9 A B C D * # Note: both keywords are for use on the Portfolio only, they are ignored on a standard PC. File I/O -------- CREATE create file (pointer to file name on top of stack, will be replaced by file handle, negative file handle if error) OPEN open file (pointer to file name and mode value on stack; mode 0=read, 1=write, 2=both; file name and mode value will be replaced by file handle, negative file handle if error) SEEK seek to position within file relative from current position (handle and positive or negative offset on stack, returns non-zero if error) READ read from file (handle, length and pointer to buffer on stack, non-zero return if error) WRITE write to file (handle, length and pointer to buffer on stack, non-zero return if error) CLOSE close file (handle on top of stack) String/memory ------------- ALLOC allocate dynamic memory (size on top of stack, will be replace by pointer to memory; allocated memory is initialized to zeros; maximum block size is 32767 bytes; strategy is first fit) FREE free dynamic memory (pointer on top of stack) *CPY copy memory (source and destination pointer and length on stack) $CMP compare two strings (string pointer on stack, -1=less than, 0=equal, 1=greater than) $CPY copy string (source and destination pointers on stack) $CAT concatenate string (source and destination pointers on stack) All string and memory write accesses are checked (unless range checking is disabled, see PROP command). Other keywords -------------- CALL call machine code, pointer to code on top of stack; the CS of PL1 is allways used. (call [si] to pop ax from PL1-stack; call [si+2] to push ax on PL1-stack; don't change the segment registers; other registers are free to use; remember to make your code relocatable, use short jumps and/or branches only) TIME returns pointer to time string on stack, format: HHMMSS (this is a static string) DATE returns pointer to date string on stack format: YYMMDD (this is a static string) RAND returns a pseudo-random integer on stack IN input from port (address on stack) OUT output to port (address and value on stack) WAIT halts processor until next clock tick (delays about 1 or 128 seconds, depending on refresh mode of Portfolio; consumes less power) RATE set clock tick speed of Portfolio (0 = tick every 128 sec; 1 = tick every second) JIFFIE returns the value of the standard jiffie clock STOP stops program execution DELAY delay for number of milliseconds on top of stack, works only correctly on a Portfolio OFF turn Portfolio off (ignored on a standard PC) PORT returns 1 on stack for Portfolio, else 0 SEG get/set segment address for PEEK and POKE; returns previous segment; use 0 as addess to read the address only; this address is initialized to the DS of PL1 PEEK reads byte pointed to be value on top of stack (using the segment address set with SEG) POKE write byte (address and value on stack) INT generate software interrupt, pointer to register buffer and interrupt number should be on stack the register buffer is 18 bytes long and has the following layout: Offset Holding 0 AX 2 BX 4 CX 6 DX 8 SI 10 DI 12 DS 14 ES 16 Flags This buffer is read to set the registers before executing the specified interrupt (on top of the stack). This buffer is written to store the registers after executing the interrupt. Normally PL1 will check any memory write for you, which makes it impossible to screw things up. But when you are using CALL, POKE or INT you are on your own, so be carefull. Just another open door: INT 60h/61h only work on the Portfolio, your PC will probably crash. Example using SEG and PEEK (print ROM signature). Note also the way a ASCII character is printed. 0xf000 SEG DROP FOR 0xffef 0xffea p p % PEEK 8 << 1 | v = v PRINT ENDFOR NL ERROR MESSAGES -------------- syntax at .... error in using structured programming keywords (e.g. IF without ENDIF, etc) the program structured is checked in the scan (just before program run commences) overflow result of arithmetic expression (most likely floating point) too large stack overflow you tried to put something on stack, while the stack was full stack underflow you tried to get someting from stack, while the stack was empty control overflow you tried to execute a DO-statement, while the stack was full control underflow should never happen (possibly a bug in PL1) illegal token should never happen (possibly a bug in PL1) no data you tried to reference a variable or memory with a bad pointer bad proc you tried to call a procedure with a bad pointer no memory you tried to allocate memory but there was not enough memory anymore invalid block you tried to free memory with a bad pointer no number you tried to convert a ASCII string to a number, which was not a number divide by 0 you tried to divide by zero, which is not allowed (defined) not graph you tried to execute a graphics statement in text mode DISTRIBUTED FILES ----------------- PL1.COM The language PL1.DOC Documentation SNAKE Little example game SNAKE.HI Hiscore file for example game (beat me!) ASTRO3 Astrologic calculations (example of sine, etc) ASTRO.BIN Astrologic font file STAIN Graphics example program SIGNA Example program, print ROM signature MENU Example program: using menu's HOW TO CONTACT ME OR TO REPORT PROBLEMS? ---------------------------------------- Sent E-mail to: M.Bokhorst@ect.nl (internet) or mail to: M. Bokhorst Opera 70 3335 EH Zwijndrecht The Netherlands KNOWN PROBLEMS -------------- Do not use hotkeys to start built-in applications, or your Portfolio will crash. Can anybody tell me why this happens? Merge returns the message 'syntax error at ....' when there's no more memory left. Names are still added to the name table when there's no more memory left. WHATS NEW? ---------- 1.6: New keywords: OFF INT SEG PEEK POKE Possibility to undelete previously deleted line (using Backspace key) 1.6a: WAIT improved (Portfolio is put into stand-by mode) 1.6b: New keyword: RATE Ctrl-R in edit-mode will run program Last editted/inserted line is remembered 1.7: Size returns now number of available (free) bytes Adding lines when no memory result in error now Backspace in editor works again New keyword: PORT 1.8: Memory was not initialized correctly in versions before, giving not predictable results. A checksum is calculated and shown when starting up (should be 87 for version 1.8)