Home
Downloads
Licenses Contact

OshonSoft

20th Anniversary

2021 - 20th Anniversary of the
OSHONSOFT PROJECT
OshonSoft © 2001 - 2024

6502 Simulator IDE
BASIC Compiler Reference Manual


Table Of Contents:

General info


About variables


Mathematical and logical operations


Standard Basic language elements


Complex expressions evaluation


Memory access


Subroutines


Bit-oriented language elements


String data type related basic elements


Communication with memory mapped I/O ports


Structured language support (procedures and functions)


C64 related basic elements


#define directive parameters


• General info

Basic compiler editor is composed of editor panel (for user program editing) and source explorer (for easy navigation through all elements of user program - variables, symbols, constants, subroutines, procedures and functions). Editor formats and colorizes entered lines of user program, that simplifies the debugging process.

In all the user-defined program element names, that is in all the variable names, names of the procedures, functions, subroutines, constants, symbols and labels, both lower-case and upper-case characters can be used, along with the underscore and numeric characters. A numeric character will not be accepted by the compiler to be the leading character in the element name.

The primary output of the compiler is an assembler source file. However, with an appropriate command from the menu it can be assembled and even loaded in the simulator with a single click. Menu commands and options are rich, as well as the commands from the right-click pop-up menus for the editor and source explorer. Basic compiler's assembler output contains many useful comment lines, that makes it very helpful for educational purposes, also.

Show Warnings
If Show Warnings option is enabled, in the Warnings window Basic compiler will show information about unused declarations, subroutines, procedures and functions in the user basic program.

Do Not Compile Unused Code
If this option is enabled, Basic compiler will not compile unused declarations, subroutines, procedures and functions, in order to save memory resources.

Initialize Variables On Declaration
If this option is enabled, Basic compiler will reset to zero all memory locations allocated for variables, at the position of their declaration in the basic program. This option is useful for beginners, because RAM memory is filled with random values at device power-up, and it is easy to make a mistake to assume that all variables are reset to zero at power-up. Experienced users can save some program memory, by disabling this option and taking control of variable initial values by user program where necessary.

Optimize Variables Declaration
This option will turn on the compiler internal routine that will optimize the variables declaration order based on the usage frequency of the variables. In this way, the most frequently used variables will be stored in higher RAM memory locations, resulting in possibly smaller size of the generated code.

Dynamic Temporary Variables Management
If dynamic management is enabled, temporary variables created by compiler will not reserve allocated RAM memory permanently. Allocated memory will be released immediately after use, thus minimizing the total RAM memory required to compile the program. As a consequence, temporary compiler variables will not be listed in the Watch Variables tool.

• About variables

The following data types are supported:
Boolean (or Bit) - 1-byte, True or False
Short - 1-byte integers in the range -128 to 127
UShort - 1-byte unsigned integers in the range 0 to 255
Integer - 2-byte integers in the range -32,768 to 32,767
UInteger - 2-byte unsigned integers in the range 0 to 65,535
Long - 4-byte integers in the range -2,147,483,648 to 2,147,483,647
ULong - 4-byte unsigned integers in the range 0 to 4,294,967,295
Single - 4-byte single precision floating point numbers, 7 digits precision
String - arrays of bytes containing ASCII character codes, 8-100 bytes (plus one string termination byte) long
Short, UShort, Integer, UInteger, Long and ULong variable types will be sometimes referred to as 'all integer data types'.
With Single variable type added to the list, those variable types will be sometimes referred to as 'all numeric data types'.
Byte can be used as an alias for UShort. Word can be used as an alias for UInteger.

Variables can be global (declared in the main program, before the End statement) or local (declared in subroutines, procedures and functions). Variable name used for a variable with global scope can be used again for local variable names. The compiler will reserve separate memory locations for them. There are no other limits for the total number of variables, but the available RAM memory. Variables are declared using DIM statement:
   Dim a As Bit
   Dim b As Short
   Dim c As Integer
   Dim d As Long
   Dim e As Single
   Dim str_var As String

Dim statement allows multiple declarations in one line of code by using comma-separated list of variable names:
   Dim c1, c2, c3 As Integer

It is possible to use one-dimensional arrays for all variable types (except String). For example:
   Dim a(100) As Integer
declares an array of 100 Integer variables with array index in the range [0-99].

It is possible to make conversions between all numeric data types by simple assignment statements:
   Dim a As Long
   Dim b As Single
   b = 123.456
   a = b
This will result in variable A holding integer value 123.

High and low byte of a UInteger (Integer) variable can be addressed by .HB and .LB extensions (dot notation):
   Dim x As Short
   Dim y As Integer
   x = y.HB
   x = y.LB  'This statement is equivalent to x = y
   y.HB = x
   y.LB = x
   y = x  'This statement will also extend the sign to high byte of y variable

High word (composed by bytes 3 and 2) and low word (composed by bytes 1 and 0) of a ULong (Long, Single) variable can be addressed by .HW and .LW extensions. Byte 0 can be addressed by .LB and byte 1 by .HB extensions. The third and the fourth byte of ULong, Long and Single variables can be addressed by .3B and .4B extensions. For example:
   Dim i As UShort
   Dim j As UInteger
   Dim x As ULong
   i = x.LB
   j = x.HW

Memory map that will be used by the compiler is set using two parameters: RAMEND and ROMSTART. By default ROMSTART is set to $C000, and RAMEND to $BFFF for the 48K RAM with 16K ROM system. If needed, the new correct values should be assigned to these parameters using the #define directive (alias: Define). Variables will be allocated by the compiler to the memory locations in the defined RAM space, and the compiled code will start from the first ROM memory location. RAMEND value must be always less then ROMSTART parameter value. The compiler will automatically fix the user parameter values selection if it is not consistent:
   #define ROMSTART = $8000

Constants can be used in decimal number system with no special marks, in hexadecimal number system with leading 0x or leading $ notation (or with H at the end) and in binary system with leading % mark (or with B at the end). ASCII value of a character can be expressed in string format (e.g. "A"). Keywords True and False are also available for Boolean type constants. For example:
   Dim a As Boolean
   Dim b As Short
   Dim c As Integer
   a = True
   b = %01010101
   c = 0x55aa
   c = "C"

Constants can be assigned to symbolic names using CONST directive. Constants can be global or local. One example:
   Dim a As Single
   Const pi = 3.14159
   a = pi

It is possible to use comments in basic source programs. The comments must begin with single quote symbol (') and may be placed anywhere in the program.
Comment sign '//' is an alternative for the standard single quote sign.

Lines of assembler source code may be placed anywhere in basic source program and must begin with ASM: prefix. If labels are used, no space should be left between the ASM: prefix and the label. For example:
   ASM:        NOP
   ASM:LABEL1: LDA #$34

Symbolic names of all variables and constants (global and local) can be used as the arguments of the assembler instructions. The compiler will replace that symbolic name with the proper variable address or constant value:
   Dim varname As Short
   varname = 0
   ASM:        LDA #$55
   ASM:        STA VARNAME

If large amount of assembler code should be used, it can be loaded from an external assembler file and included to the current program by using IncludeASM directive. Its only argument is a string containing the path to the external .ASM file. This can be the full path or only the file name, if the external file is located in the same folder as the current basic program file. During the compilation process the external assembler code will be appended to the current program at its end, and not at the position of the directive. Multiple files can be included with separate IncludeASM directives. External assembler files should not contain ASM: prefix used for inline assembler code. It is also strongly suggested not to use ORG directives in the external assembler code. For example:
   IncludeASM "test.asm"
   IncludeASM "d:\example\test2.asm"

• Mathematical and logical operations

Five arithmetic operations (+, -, *, /, MOD) are available for all numeric data types. MOD operation is not applicable for Single data type variables. The compiler is able to compile all possible complex arithmetic expressions, including those containing math functions and user-defined functions. The compiler will accept all numeric data types for both the arguments and the result of the operation. For example:
   Dim a As Long
   Dim b As Long
   Dim c As Long
   a = 1234
   b = 2345
   b = a * b
   c = a * 100 - (a + b)

Square root of an uinteger number (0-65535 range) can be calculated using SQR function. The compiler will accept all numeric data types for both the argument and the result of the operation.
   Dim x As Integer
   Dim x2 As Single
   x = 3600
   x = Sqr(x)
   x2 = 22500
   x2 = Sqr(x2)

There are eight single precision mathematical functions (EXP, LN, LOG, SIN, COS, SQRT, TAN, POW) that can be used with Single data type variables. All math functions can also be used in complex math expressions. The compiler will accept all numeric data types for both the arguments and the result of the operation.
For example:
   Dim a As Single
   a = 2
   a = Sqrt(a)

Another example:
   Dim x1 As Integer
   Dim x2 As Single
   Dim x3 As Single

   x1 = 1
   While x1 < 6
      x2 = Sin(x1)
      x3 = Cos(x1)
      x1 = x1 + 1
   Wend

For Bit-Boolean and all numeric data type variables four basic logical operations are supported. For example:
Example 1:
   Dim a As Boolean
   Dim b As Boolean
   Dim c As Boolean
   a = True
   b = False
   c = Not a
   c = a And b
   c = a Or b
   c = a Xor b

Example 2:
   Dim a As ULong
   a = 0x55
   a = Not a

SHIFTLEFT and SHIFTRIGHT functions can be used to shift bit-level representation of a number left and right. The first argument is input variable or constant and the second argument is number of shifts to be performed. These functions can be also used in the form of operators.
Example:
   Dim var as UShort
   var = %00000011

   goleft:
      var = ShiftLeft(var, 1)
      If var = %11000000 Then Goto goright
   Goto goleft

   goright:
      var = var ShiftRight 1
      If var = %00000011 Then Goto goleft
   Goto goright

• Standard Basic language elements

Unconditional jumps are performed by GOTO statement. It uses line label name as argument. Line labels can be global or local. Line labels must be followed by colon mark ':'. Here is one example:
   Dim a As Long
   a = 0
   loop: a = a + 1
   Goto loop

Four standard BASIC structures are supported: FOR-TO-STEP-NEXT, WHILE-WEND, IF-THEN-ELSE-ENDIF and SELECT CASE-CASE-ENDSELECT. Here are several examples:
Example 1:
   Dim a As Integer
   Dim b(100) As Single
   For a = 0 To 99
      b(a) = a
   Next a

Example 2:
   Dim a As Long
   a = 100000
   While a > 0
      a = a - 1
   Wend

Example 3:
   Dim x1 As Single
   Dim yeq As Boolean
   Dim yne As Boolean
   Dim ygt As Boolean
   Dim ygte As Boolean
   Dim ylte As Boolean
   Dim ylt As Boolean

   For x1 = 12.25 To 12.75 Step 0.25
      yeq = False
      yne = False
      ygt = False
      ygte = False
      ylte = False
      ylt = False
      If x1 = 12.5 Then yeq = True
      If x1 <> 12.5 Then yne = True
      If x1 > 12.5 Then ygt = True
      If x1 >= 12.5 Then ygte = True
      If x1 <= 12.5 Then ylte = True
      If x1 < 12.5 Then ylt = True
   Next x1

Example 4:
   Dim x As UShort
   loop:
      Select Case x
      Case 255
         x = 1
      Case <= 127
         x = x + 1
      Case Else
         x = 255
      EndSelect
   Goto loop

For statement will accept all numeric data types for the running variable. Exit For statement provides a way to exit a For-Next loop. It transfers control to the statement following the Next statement.

After IF-THEN statement in the same line can be placed almost every other possible statement and then ENDIF is not used. There are no limits for the number of nested statements of any kind. Six standard comparison operators are available: =, <>, >, >=, <, <=.
Also, the compiler is able to evaluate complex expressions (both math/arithmetics and string expressions) on both sides of the comparison operator in While and If-Then statements.

Case statement will accept complex expressions, multiple comma-separated conditions, ranges of values in the form exp1 To exp2:
   Select Case x
   Case 255, 254, < y * 2
   Case y + 1, y + 2, y + 5 To y + 10

• Complex expressions evaluation

Complex expressions evaluation engine can evaluate all possible and meaningful expressions containing any number of supported operators, operands, functions and parentheses.

The expression evaluation engine will accept both Basic and C-inspired syntax for the operators.
Here is the list of all supported operators with their alternative forms:
- Arithmetic operators: +, -, *, /, % (Mod), ++ (post or pre-increment), -- (post or pre-decrement), unary +, unary -
- Assignment operators: =, +=, -=, *=, /=
- Comparison operators: == (=), != (<>), <, <=, >, >=
- Logical operators: unary ! (Not), && (And), || (Or)
- Bitwise operators: unary ~ (Not), & (And), | (Or), ^ (Xor), << (ShiftLeft), >> (ShiftRight)

The dot operator (.) is available for addressing individual bytes and words in variables. There is also # unary operator (ascii print) used to get the decimal string representation of the operand.

On low level, implemented expression evaluation engine is C-language based, following C standards for operator precedence.
In assignment statements, the engine will initially consider Not, And and Or as bitwise operators.
In condition expressions of While and If-Then statements, Not, And and Or will be initially considered as logical operators.
This information may only be important from an operator precedence perspective. Actually, the expression evaluation engine will not generate errors related to the distinction between logical and bitwise operators. The operation performed is determined by the type of the operands.

Complex expressions are generally accepted everywhere. Complex expressions can be used as direct arguments when calling procedures and functions in the code, and in all statements where comma-separated list of arguments is accepted, like Print statement.
While statement will accept all possible complex expressions that evaluate to Bit data type. The same is valid for If-Then statement. Case statement can also contain complex expressions.
For statement will accept all possible complex expressions for the initial expression, for the To argument, and for the optional Step argument as well.

Illustrative lines of code:
   Print #func1(i * 2 + 1), 32, #a1++, 32, #--a2
   Case 2, 3, >= 10 + j
   If l1 = CLong w1 * 1000 Then i = 0
   For i = j + 1 To k * 2 + 1 Step 2

The compiler will accept lines containing the expression without the assignment operator. The expression will just be evaluated if possible, and if not, the Syntax error message will be displayed. So, it is possible to have lines of code like these ones:
   i++
   #(j + k)
   x > y

Along with the standard basic For-Next loops, it is possible to use the C-like CFor-CNext loops. Init expression, condition expression and loop expression should be separated by the semicolon ';' symbol. In addition, the init and loop expressions can contain multiple statements separated by commas.
For example:
   Dim i As Short
   Dim j As Short
   Dim k As Short
   k = 0
   CFor (i = 1; i < 7; i++)
      k++
   CNext
   k = 0
   CFor (i = 5, j = 10; i + j < 20; i++, j++)
      k++
   CNext

'#' (ascii print) symbol is now treated as a unary operator returning string data type, so it can be used in complex expressions like these ones:
   s1 = #(a1 + a2 * a3)
   s1 = "abcd" + #a2 + s2 + s3

Unary operators are treated as functions. The opposite is also true. So, the evaluation engine will accept the following format, also:
   y = Sin x

Complex expressions evaluation engine accepts all meaningful combinations of dot operator extensions (like .LB) and bit indexes with dot operator. The dot operator for extensions and bit indexes can be used with array members and all other applicable expressions. It is treated as a binary operator with the highest binary operator precedence.
For example:
   Dim i As Short
   Dim xlng(4) As Long
   For i = 1 To 4
      xlng(i - 1).LW.LB = 1
      xlng(i - 1).LW.HB = 1
      xlng(i - 1).HW.LB = 1
      xlng(i - 1).HW.HB = 1
   Next i

If needed, temporary system variables will be declared and used during the expression evaluation. Optimal management of temporary variables has been achieved by the evaluation engine.

Data type promotion

Numeric data types are ordered from the lowest to the highest in the following sequence: Short, Integer, Long, Single. Particular arithmetic or logical operation is performed on the higher data type level of the operands (variables and constants).
In case when only arithmetic operators remain until the end of the evaluation, the evaluation engine will promote the data type of temporary variables to the result variable data type. So, one can freely write:
   Dim w1 As Integer
   Dim l1 As Long
   Dim s1 As Single
'w1 / 1000 will be calculated on the single data type level; desired precision will be achieved
   s1 += w1 / 1000 + 3.14
   s1 = w1 / 1000 + 3.14
'w1 * 1000 will be calculated on the long data type level; desired precision will be achieved
   l1 = w1 * 1000 + 500

However, that will not happen in case of comparison operators, like in the example:
   Dim w1 As Integer
   Dim l1 As Long
   Dim s1 As Single
'left-hand side will be evaluated to single; right-hand side to integer; desired precision will be probably lost
   While s1 - 1 = w1 / 1000
   Wend
'left-hand side will be evaluated to long; right-hand side to integer; desired precision will be probably lost
   While l1 - 1 = w1 * 1000
   Wend

For similar situations, one can make use of the data type conversion functions (unary operators): CShort, CInteger, CLong, CUShort, CUInteger, CULong, CSingle.
This is the updated example:
   While s1 + 1 = CSingle w1 / 1000
   Wend
   While l1 + 1 = CLong w1 * 1000
   Wend

• Memory access

Standard BASIC elements for accessing memory are available: POKE statement and PEEK function. For the address argument the variables of all numeric data types will be accepted, including the UInteger range constants. The compiler will also accept UShort range constants for the data argument of the POKE statement. For the PEEK function the result variable can be of any numeric data type. For example:
   Dim a As UInteger
   Dim b As UInteger
   Dim c As UInteger
   For a = 0 To 15
      b = Peek(a)
      c = 240 + a
      Poke c, b
   Next a

• Subroutines

Structured basic programs can be written with subroutines. When using subroutines, the main routine must be ended with END statement, and subroutines must be placed after END statement in program. END statement is compiled as an infinite loop (if unofficial instructions are enabled, the JAM instruction will be used). Subroutines should be declared with SUB statement followed by the subroutine name. All variables declared in a subroutine have local scope, so they don't need to have unique names. Subroutines must be ended with END SUB statement. They can be conditionally exited with EXIT SUB statement. Calls to subroutines are implemented with GOSUB statement.
For backward compatibility, global scope line labels will still be recognized as subroutine declarations, GOSUB statements will also accept the line label names as arguments and RETURN statement can be used for the final return from a subroutine. Users need to take care that the program structure is consistent when using local scope line label as GOSUB argument (the compiler will accept that, however an applicable warning will be generated).
Here are two examples:
Example 1:
   Dim x1 As Integer
   Dim x2 As Integer
   Dim x3 As Integer
   For x1 = 0 To 10
      Gosub calculate_x2x3
   Next x1
   End

   Sub calculate_x2x3
   x2 = 100 + x1
   If x1 > 5 Then Exit Sub
   x3 = x2
   End Sub

Example 2:
   Dim a As Integer
   Dim b As Integer

   b = 100
   Gosub fillmemory
   b = 101
   Gosub fillmemory
   End

   fillmemory:
   For a = 20000 To 21000
      Poke a, b
   Next a
   Return

• Bit-oriented language elements

SetBit, ResetBit and InvertBit statements can be used to set, reset or invert individual bits in Short or UShort data type variables. The first argument is target bit number and it must be a constant in the range 0-7 or a variable of any numeric data type. The second argument must be a Short or UShort variable that will be the target of the operation.
   Dim a As UShort
   a = 0xf0
   SetBit 0, a
   ResetBit 7, a
   InvertBit 0, a

By using TestBit function with syntax TestBit(<target_bit>, <target_var>) it is possible to copy to a Bit variable the value contained in the specific bit of a Short or UShort variable. The first argument is target bit number and it must be a constant in the range 0-7 or any numeric variable.
MakeBit statement is used with syntax MakeBit <target_bit>, <target_var>, <new_bit_value>. It will copy the new bit value argument (Bit type variable or constant) to the specified target bit. Target variable argument must be a Short or UShort data type variable. For example:
   Dim a(8) As Bit
   Dim b1 As Short
   Dim b2 As UShort
   Dim i As Integer

   b1 = 0x55
   b2 = 0xaa
   For i = 7 To 0 Step -1
      a(i) = TestBit(i, b1)
   Next i
   For i = 0 To 7
      a(i) = TestBit(i, b2)
   Next i

   b1 = 0
   b2 = 0
   a(0) = 1
   a(1) = 0
   a(2) = 1
   a(3) = 0
   a(4) = 1
   a(5) = 0
   a(6) = 1
   a(7) = 0
   For i = 0 To 7
      MakeBit i, b1, a(i)
      MakeBit i, b2, True
   Next i

• String data type related basic elements

All declared string variables will reserve fixed number of bytes in memory. That number is set by #define directive and STRING_MAX_LENGTH parameter. Allowed range for the parameter value is 8-100; the default value is 16. String variables will take one extra memory byte containing zero value to define end of string (string termination byte).
   #define STRING_MAX_LENGTH = 8

It is also possible to specify the length of each declared string variable by adding [length] suffix to the variable name:
   Dim string_var[3] As String
   string_var = "ABC"
This feature can be used in cases when available memory is critical, and when it is certain that a string variable will not hold string longer than the specified length during the program execution.

Special string pointer (StrPtr) data type is available for advanced strings related programming. String pointers are UInteger type variables holding the address of a string variable. String pointer value can be assigned and dynamically changed with SetStrPtr statement. String pointers can be used everythere along with String variables and constants. ByRef String arguments of procedures and functions are implemented using string pointers
minimizing the required RAM memory. One example:
   Dim s1 As String
   Dim p1 As StrPtr
   s1 = "aa"
   SetStrPtr p1 = s1
   p1 = p1 + "bb"

String constants should begin and end with the double quotation marks. There are four symbolic string constants available: Qt (or """") for the double quotation mark (ASCII code 34), CrLf for the carriage return - line feed sequence (ASCII codes 13-10), Cr for the carriage return (ASCII code 13) and Lf for the line feed character (ASCII code 10). User-defined names for the string constants with the Const directive can also be used.
   Dim string_var As String
   string_var = Qt + "abcde" + """" + CrLf

Decimal string representation of any data type variable is assigned to a string variable using the # prefix. For Single data type variables, SINGLE_DECIMAL_PLACES parameter value is used in this operation (alias: PRINT_SINGLE_DIGITS). This parameter is used to define the number of decimal places taken after the decimal point in decimal representation of Single variables. Valid parameter values are in the range 1-6. The default value is 3. Single values greater than 8388607 or lower than 0.00000191 are considered to be out of the print range and will be printed with one 'E' character.
For example:
   #define SINGLE_DECIMAL_PLACES = 2
   Dim string_var As String
   Dim string_var2 As String
   Dim pi As Single
   Dim i As Word
   i = 12345
   string_var = "Number: " + #i
   pi = 3.14159
   string_var2 = #pi

Len() function returns the number of characters in a string variable or constant:
   Dim i As Word
   i = Len("abcde")
Variable i will contain the number 5.

Asc() function returns the numeric value representing the ASCII character code corresponding to the first letter in a string variable or constant:
   Dim i As Word
   i = Asc("ABC")
Variable i will contain the number 65.

Chr() function returns an one-char long string containing the character that is associated with the ASCII character code provided.
For example:
   Dim string_var As String
   Dim i As Word
   i = Asc("A")
   string_var = Chr(i + 1)
Variable string_var will contain the string "B".

LeftStr() function returns a string containing the specified number of characters from the left side of an input string. The first argument of the function is an input string expression from which the leftmost characters are returned. The second argument is a numeric expression indicating how many characters to return. If 0, a zero-length string ("") is returned. If greater than or equal to the number of characters in the input string, the entire string is returned.
RightStr() function returns a string containing the specified number of characters from the right side of an input string. The first argument of the function is an input string expression from which the rightmost characters are returned. The second argument is a numeric expression indicating how many characters to return. If 0, a zero-length string ("") is returned. If greater than or equal to the number of characters in the input string, the entire string is returned.
MidStr() function returns a string containing the specified number of characters from an input string. The first argument of the function is an input string expression from which the characters are returned. The second argument is a numeric expression specifying character position in the input string at which the part to be taken begins (the first character of the string is at position 1). The third argument is a numeric expression indicating the number of characters to return. The returned part of the string will not go beyond the end of the input string.
For example:
   Dim string_var As String
   Dim string_var1 As String
   Dim string_var2 As String
   Dim string_var3 As String
   string_var = "123456789"
   string_var1 = LeftStr(string_var, 2)
   string_var2 = MidStr(string_var, 3, 3)
   string_var3 = RightStr(string_var, 4)
Variable string_var1 will contain the string "12".
Variable string_var2 will contain the string "345".
Variable string_var3 will contain the string "6789".

LTrim() function returns a string containing a copy of an input string argument without leading spaces.
RTrim() function returns a string containing a copy of an input string argument without trailing spaces.
   Dim string_var As String
   string_var = "   abc   "
   string_var = RTrim(LTrim(string_var))
Variable string_var will contain the string "abc".

LTrimChr() function strips characters from the beginning of an input string.
RTrimChr() function strips characters from the end of an input string.
The first argument is the input string. The character to be stripped is specified by the ASCII character code as the second argument of the function.
   string_var = RTrimChr("aaaAAAaaa", "a")

FillStr() function returns a string containing a repeating character string of the length specified. The first argument of the function is the ASCII character code used to build the return string. The second argument is a numeric expression specifying the length of the returned string.
For example:
   Dim string_var As String
   Dim i As Byte
   i = 3
   string_var = FillStr("a", i) + FillStr(65, i)
Variable string_var will contain the string "aaaAAA".

InStr() function returns a number (stores it in any integer data type variable) specifying the position of the first occurrence of the ASCII character code (the second argument of the function) within an input string expression provided as the first argument of the function. The first character of the string is at position 1. If the ASCII character code has not been found in the input string, the function will return 0.
   Dim string_var As String
   Dim i As Word
   string_var = "123456ABCD"
   i = InStr(string_var, Asc("A"))
Variable i will contain the number 7.

InStrRev() function returns a number specifying the position of the last occurrence of a character (specified by the ASCII character code as the second argument of the function) within an input string expression (the first argument).
   byte_var = InStrRev("cccbbbaaa", "c")
Variable byte_var will contain the number 3.

ReverseStr() function returns the reversed string from an input string expression.
   string_var = ReverseStr("12345")
Variable string_var will contain the string "54321".

CountChr() function returns a number specifying the number of occurrences of a character (specified by the ASCII character code as the second argument of the function) within an input string expression (the first argument).
For example:
   string_var = "ababababa"
   byte_var = CountChr(string_var, "a")
Variable byte_var will contain the number 5.

ReplaceChr() function returns a string in which the specified character has been replaced with another character. The first argument is the string expression containing the character to replace, the second argument is the character being searched for, and the third argument is the replacement character.
   string_var = ReplaceChr("222111222", "1", "3")

LCase() function returns an input string argument converted to lowercase. Only uppercase letters are converted to lowercase; all lowercase letters and non-letter characters remain unchanged.
UCase() function returns an input string argument converted to uppercase. Only lowercase letters are converted to uppercase; all uppercase letters and non-letter characters remain unchanged.
For example:
   string_var = "aba123aza"
   string_var = UCase(string_var)
   string_var = LCase("ABa123aZA")

LShiftStr() and RShiftStr() functions can be used to shift the characters in the input string expression (the first argument) to the left or to the right. The second argument of the function is the character (specified by the ASCII character code) that will be put on the last character position for the LShiftStr() function, or on the first character position for the RShiftStr() function, so the length of the input string will not be changed.

LRotateStr() and RRotateStr() functions can be used to rotate the characters in the input string expression (the only argument) to the left or to the right.
Here is one example:
   string_var = "123456789"
   string_var = LShiftStr(string_var, "a")
   string_var = LShiftStr(string_var, "b")
   string_var = RRotateStr(string_var)
Variable string_var will contain the string "b3456789a".

HexStr() function returns a 4-chars long string representing the hexadecimal value of a number. The argument is expected to be in the Word (UInteger) data type range (2-byte unsigned numbers, 0-65535, 0000-FFFF).
   word_var = 43811
   string_var = HexStr(word_var)
Variable string_var will contain the string "AB23".

DecFromHex() function returns decimal value of a number provided in the form of a hexadecimal string.
   word_var = DecFromHex("FFFF")
Variable word_var will contain the number 65535.

There are four functions available that can be used to convert a string variable into a numeric data type variable.
All four functions expect one input string argument containing decimal string representation of a numeric variable.
StrValB() function returns a UShort data type variable, StrValW() returns a UInteger variable, StrValL() returns ULong, and StrValS() returns Single data type variable.
Here is one example:
   #define STRING_MAX_LENGTH = 10
   Dim string_var As String
   Dim b_var As UShort
   Dim w_var As UInteger
   Dim l_var As ULong
   Dim s_var As Single
   b_var = StrValB("13")
   string_var = "54321"
   w_var = StrValW(string_var)
   l_var = StrValL("1234567890")
   string_var = "-123.56"
   s_var = StrValS(string_var)

The compiler is able to compile all possible complex expressions containing string constants, variables and functions.
For example:
   Dim string_var As String
   Dim string_var2 As String
   string_var = "123456789"
   string_var2 = LeftStr(string_var, Len(string_var) - 6) + MidStr(string_var, 4, 6) + Chr(Asc(RightStr(string_var, 1)) - 9)
After the execution of this example, string_var2 variable will contain the string "1234567890".

Two standard comparison operators are available for string data type in conditional statements: =, <>.
   Dim string_var As String
   Dim i As Word
   i = 1
   string_var = "abcd"
   If LeftStr("abcde", 4) <> string_var Then i = 2 Else i = 3
Variable i will contain the number 3 after the execution of the example.

The compiler is also able to evaluate complex string expressions in conditional statements.
One example (ASCII code for digit 1 is 49):
   Dim st_var As String
   Dim i As Word
   i = 1
   st_var = "123456"
   If LeftStr(st_var, 1) + MidStr(st_var, 2, 2) + RightStr(st_var, 3) = Chr(48 + Len("a")) + "23456" Then i = 2

For experienced users, it is worth noting that a string variable can actually be treated as a ushort array, if needed.
For example:
   string_var = "1234567"
   string_var(3) = "a"
After the execution of this example, string_var variable will contain the string "123a567".

• Communication with memory mapped I/O ports

The communication with the outside world is done through the memory mapped I/O ports using GET function and PUT and PRINT statements. The argument of GET function is the port number and must be a constant value in the UInteger range [0-65535]. It can be used to assign the value received on the port to a variable of any integer data type. For example:
   Dim a As Integer
   a = Get($a000)

PUT statement can be used to send data to the specified memory mapped port. The data can be UShort constant value in the range [0-255] or contained in a variable of any integer data type. Only the lowest byte of the variable is sent to the port. For example:
   Dim a As Integer
   a = 200
   Put $a001, a

PRINT statement can be used to send string variables, string constants and decimal string representations of all data type variables to the specified port address. There are no limits for the number of comma-separated arguments used in the statement.
Here is an example:
   Dim a As Single
   a = 123.456
   Print $a001, "The number is "
   Print $a001, a
   Print $a001, CrLf

This can also be done using only one PRINT statement:
   Print $a001, "The number is ", a, CrLf

Another example:
   #define PRINT_SINGLE_DIGITS = 4

   Dim x2 As Single
   Dim x1 As Long

   x2 = -123.45678
   x1 = x2

   Print $1234, "Long = ", x1 * 10, CrLf
   Print $1234, "Single = ", x2 - 7, CrLf

• Structured language support (procedures and functions)

Procedures can be declared with PROC statement. They can contain up to 30 arguments (comma separated list) and all available data types can be used for argument variables. Argument variables are declared locally, so they do not need to have unique names in relation to the rest of user basic program, that makes very easy to re-use once written procedures in other basic programs. Procedures can be conditionally exited with EXIT statement. They must be ended with END PROC statement and must be placed after END statement in program. Calls to procedures are implemented with CALL statement. The passed arguments can be variables, numeric constants or complex numeric expressions. For example:
   Dim x As Integer
   For x = 0 To 255
      Call port_display(x)
   Next x
   End

   Proc port_display(arg1 As Integer)
   Print $a001, "THE NUMBER IS ", arg1, CrLf
   End Proc

All facts stated for procedures are valid for functions, also. Functions can be declared with FUNCTION statement. They can contain up to 30 arguments and argument variables are declared locally. Functions can be exited with EXIT statement and must be ended with END FUNCTION. The value returned by a function should be assigned to the function name in the function code, or provided as argument of ReturnValue statement. The name of the function is declared as a global variable, so if the function is called with CALL statement, after its execution the function variable will contain the result. Standard way of function calls in assignment statements can be used, also. One simple example:
   Dim x As Integer
   Dim y As Integer
   For x = 0 To 100
      y = square(x) + 1
   Next x
   End

   Function square(arg1 As Integer) As Integer
   square = arg1 * arg1
   'or ReturnValue arg1 * arg1
   End Function

The default mechanism is to pass an argument to a procedure by value. Either no prefix or ByVal prefix can be used for that argument. The procedure will use the argument value and will not change the input value of the calling variable. There are two passing mechanisms for passing arguments to procedures by reference - ByRef and ByRefOut. When ByRef prefix is used to pass a variable argument to a procedure, the procedure will use the input variable value, but it can also change the value of the variable during the procedure execution. The calling variable will be exposed to change. When ByRefOut prefix is used for the procedure argument, the input value of the calling variable will not be passed to the procedure at all. The procedure will only return an output value to the calling code through that argument. So, ByRefOut mechanism should be used when the procedure has a genuine need to output only a value to the calling code, and in that way the result will be a more optimized code compared to the use of the standard ByRef mechanism. ByRef and ByRefOut can be used for function arguments as well.
One test example:
   Dim in_only As Short
   Dim inc_me As Short
   Dim add_inc_me_and_in_only As Short

   in_only = 5
   inc_me = 10
   Call testbyref(in_only, inc_me, add_inc_me_and_in_only)
   'after this call
   'inc_me = 11
   'add_inc_me_and_in_only = 16
   End

   Proc testbyref(arg1 As Short, ByRef arg2 As Short, ByRefOut arg3 As Short)
      arg2 = arg2 + 1
      arg3 = arg1 + arg2
   End Proc

Procedures (and functions) can also be called without the Call statement. In that case, the procedure name should be followed by the comma-separated list of arguments.
The lines of code with the same effect:
   Call port_display(x)
   port_display x

Basic source code from an external file can be included to the current program by using INCLUDE directive. Its only argument is a string containing the path to the external .BAS file. This can be the full path or only the file name, if the external file is located in the same folder as the current basic program file. During the compilation process the external basic source will be appended to the current program. Multiple files can be included with separate INCLUDE directives. To maintain the overall basic code structure, it is strongly suggested that the external file contains global declarations, subroutines, procedures and functions, only. Here is one very simple example for the demonstration:
main.bas:
   Dim i As Integer
   Dim j As Integer

   Include "inc1.bas"
   Include "inc2.bas"

   For i = 1 To 10
      j = func1(i, 100)
      Call proc1(j)
   Next i
   End

inc1.bas:
   Dim total As Integer

   Proc proc1(i As Integer)
   total = total + i
   End Proc

inc2.bas:
   Function func1(i As Integer, j As Integer) As Integer
   func1 = i + j
   End Function

• C64 related basic elements

The integrated basic compiler features also the special set of Commodore 64 related statements that can be used to generate working C64 PRG files ready to be simulated together with the C64 ROM image.

In order to use any of the C64 related statement, one must set the value of the C64_TARGET parameter to 1 using the #define directive. That will also set the compiler to make the needed modifications in the generated ASM file, so that the code does not interfere with the memory locations relevant to the C64 ROM. Finally, that will also set the integrated assembler to generate C64 PRG file in addition to the standard assembler output. If C64_TARGET is set to 1, ROMSTART parameter will be set to $A000, and RAMEND to $9FFF by the compiler to match the C64 setup.

When the compiled basic program uses C64 related statements, the result is that the generated OBJ (HEX) files could not directly be simulated in the simulator, because those statements reference certain C64 ROM routines. For the simulation of the generated code, C64 ROM must be loaded into the simulator and the C64 system needs to be initialized using the Commodore 64 Rom I/O Terminal tool. Then, the PRG file that is also generated by the basic compiler should be loaded using the Load PRG command on the C64 I/O Terminal tool.

C64_Cls statement clears the C64 screen video memory using the appropriate C64 ROM routine. The cursor is set at position 1,1 (upper-left corner).

C64_CursorSet statement position the cursor at the desired location on the screen. It has two comma-separated arguments, The first is the column number in the range 1-40, the second argument is the screen raw number in the range 1-25. Both arguments will accept constant values, but also the variables of all integer data types with Single included.

C64_Print statement can be used to display string constants and decimal string representations of variables on the C64 screen at the current cursor position. String constants in the double quotation marks are accepted including the compiler symbolic string constants like CrLf. User-defined names for the string constants with the Const directive can also be used. Variables of all the supported data types can be used as arguments to display their decimal string representations. There are no limits for the number of the comma-separated arguments used in the statement. The lowercase letters will be changed to uppercase.
Here is an example:
   #define C64_TARGET = 1
   #define PRINT_SINGLE_DIGITS = 5

   Dim x1 As Integer
   Dim x2 As UInteger
   Dim x3 As Short
   Dim x4 As UShort
   Dim x5 As Boolean
   Dim x6 As Long
   Dim x7 As ULong
   Dim x8 As Single

   Const welcome = "Display the values of the variables:"
   C64_Cls
   C64_Print welcome, CrLf

   x1 = -31456
   C64_CursorSet 3, 5
   C64_Print "Integer = ", x1, CrLf
   x2 = 65535
   C64_CursorSet 4, 6
   C64_Print "UInteger = ", x2, CrLf
   x3 = -68
   C64_CursorSet 5, 7
   C64_Print "Short = ", x3, CrLf
   x4 = 251
   C64_CursorSet 6, 8
   C64_Print "UShort = ", x4, CrLf
   x5 = False
   C64_CursorSet 7, 9
   C64_Print "Boolean = ", x5, CrLf

   x6 = -1234567890
   C64_CursorSet 8, 10
   C64_Print "Long = ", x6, CrLf
   x7 = 4123456789
   C64_CursorSet 9, 11
   C64_Print "ULong = ", x7, CrLf

   x8 = -123.456
   C64_CursorSet 10, 12
   C64_Print "Single = ", x8, CrLf

C64_PRG_HEADER is the #define directive parameter that sets the starting location in the C64 ram memory where the generated code should be stored to. The default value is $4000. Its value defines the way how the PRG file should be executed - it is used for the C64 basic SYS command argument. In order to be able to execute the compiled PRG file with the RUN command, the user should set the C64_PRG_ADDSYS parameter value to 1. The compiler will then embed the appropriate SYS statement at the beginning of the PRG file. If C64_PRG_ADDSYS is set to 1, C64_PRG_HEADER parameter will be automatically set to $0801 by the compiler.

C64_GetChar statement will check the number of characters in the C64 keyboard buffer queue. If there is a character waiting, its 1-byte code will be loaded to the variable argument. All integer data types will be accepted for the C64_GetChar statement argument. If the keyboard buffer is empty, the value 0 will be returned.
C64_InputChar is a similar statement to C64_GetChar. The difference is that the Input statement will wait until a key has been pressed on the keyboard. Also, there are no limits for the number of the comma-separated arguments used in the statement.
C64_PutChar statement is used to display a character on the C64 screen at the current cursor position. The arguments can be the character code constants, or the character codes stored in any of the integer data type variables. Also accepts multiple comma-separated arguments.
For example:
   #define C64_TARGET = 1
   #define C64_PRG_ADDSYS = 1

   Dim x1 As Integer

   C64_Cls
   C64_Print "Press a key to start the play.", Cr
   loop1:
      C64_GetChar x1
   If x1 = 0 Then Goto loop1
   C64_Print "Now, the pressed keys", Cr
   C64_Print "will be echoed twice.", Cr

   loop2:
      C64_InputChar x1
      If x1 = "@" Then Goto endlab
      C64_PutChar x1, x1
   Goto loop2
   endlab:

• #define directive parameters

Here is the list of all available parameters for the #define directive, along with their default values and allowed ranges of values:

ROMSTART - (default value: $C000, allowed range: $0400-$FC00)
RAMEND - (default value: $BFFF, allowed range: $03FF-$FBFF)
The default values for these parameters are set for the 48K RAM with 16K ROM system.

STRING_MAX_LENGTH - (default value: 16, allowed range: 8-100)
Used to allocate memory for String variables.

SINGLE_DECIMAL_PLACES - (default value: 3, allowed range: 1-6)
Used to determine the number of digits that will be printed after the decimal point for the Single data type variables.

C64_TARGET - (default value: 0, allowed range: 0-1)
C64_PRG_ADDSYS - (default value: 0, allowed range: 0-1)
C64_PRG_HEADER - (default value: $4000, allowed range: $0801-$9FFF)
These parameters are explained in the C64 related basic elements section. Used for the generation of the C64 PRG files.

The compiler will automatically fix the user parameter values selection if it is not consistent.
RAMEND value must be always less then ROMSTART parameter value.
If C64_TARGET = 1, ROMSTART parameter will be set to $A000, and RAMEND to $9FFF.
And, if C64_PRG_ADDSYS = 1, C64_PRG_HEADER parameter will be set to $0801.