Ultrabasic Readme 14/03/04
-----------------

Ultrabasic was programmed by Gabriel Fernandez, who abandoned its work in 2000, and Angelo Rosina, who continued developing it.


This language was created for people that already program in qbasic, this was not
designed for begginers.


Introduction
------------

Ultrabasic works in Pmode, so you can use all available system memory to store data
This includes arrays, strings, etc.

It can also build Windows executable, and has a "pseudo-console" that can simulate the DOS screen.

Some differences between Ultrabasic and Quickbasic
--------------------------------------------------

AND, OR are written THIS WAY &(AND), |(OR)

Example:
  IF a = 1 & b = 2 | c = 3 THEN

Second, ultrabasic works in pmode, so there aren't segments anymore. So there isn't DEF SEG.
Don't care about ES, DS values. Ultrabasic fills them with the correct values.

IMPORTANT !!!
  When you use inline asm code, if you edit the value of the ESI, EDI registers, you must 
restore them to their original value before returning the control tu ubasic.
  Ultrabasic use this registers to store important data.

Strings
-------

Each string created uses 500 bytes in mem(except from fixed strings), so they can have
a maximun data of 496. This can be changed easily, but I won't explain that in this
text since it is a little long(well, you only have to use to commands)

Note: Data that is processed can have a maximun of 32,200 bytes, but the stored that can
have a maximun of 496(again, except from fixed strings)

Example: a$ = string$(20000, "h") + "hi"
         ¦    \-----------------------/
   ¦------                ¦
This can have    This can have a maximun
a maximun of     of 32200 bytes.
496 bytes

Fixed strings are string created like: DIM a AS STRING * 60000

Type Structures:
----------------

Yeah !!!, ultrabasic support type structures
You can also nest them

SUBs/Functions
--------------

Subs and Functions are declared exactly like QB

DECLARE SUB b ()
DECLARE SUB a (par%)

SUB b ()
...
END SUB

SUB a (par%)
...
END SUB

Parameters are passed by value (except for UDT) by default. If you need to pass a parameter by reference, you need to use the BYREF keyword (in this ase, you can pass only variables and not expressions)
DECLARE SUB a (BYREF par%)


SUB a (BYREF par%)
...
END SUB


- For win32 programs:

  If you want to declare a sub from a dll you have to use

  DECLARE SUB/FUNCTION name(parameters) USEDLL(dll) Name_of_function_in_dll

  Example: DECLARE SUB Msgbox(hwnd, text$0, caption$0, type) USEDLL(user32.dll) MessageBoxA

  See, you only have to add the USEDLL command and then call it like a normal sub

  Also, most of the dll function when you pass a string, they require it to finish with a null
  char, so you have to use the put 0 at the end of the string to specify that it is a null char
  ended string(See the previous example).

Pointers
--------

Yeah, you can create a variable at any memory location, use
  DIM var [AS type] ATOFFSET(offset)

Note that ATOFFSET is a run-time keyword, so you can use variables and that kind of stuff as
the parameter.

  To change the offset of a fixed var, use the command
  Setnewoffset varname, newoffset&

You can get a variable pointer with VARPTR, a line pointer with LPTR and a sub/function with CODEPTR (for now, only for UltraBasic subs, not for DLL)

Math Operations:
----------------

Ultrabasic support the following math operations:

Integer operations		Float operations
------------------		----------------
/, \					/
*					*
+					+
-					-
NOT					SIN
XOR					COS
AND					TAN
OR					SQRT
>>, SHR
<<, SHL
MOD, %

VAL is supported, but be careful: if a non-numeric char is detected, the function will return a wrong value. In a floating-point expression, VAL supports numbers with decimal dot (like "31.7") but not with scientific notation. In an integer expression, decimal dot MUST NOT be used in string expression to be read with VAL.

COMPILER-TIME COMMANDS LIST:
-----------------------------

[*N next to the name means the NOT can be used with that keyword]

The following constants are create automatically by ultrabasic:
  DOS, DOS32, WIN, WIN32
It also create two constants that have the value of the current destination platform
They are: DESTOS, PLATFORM
This two constants change their value when a new platform is set.
Ultrabasic support a few of compiler-time commands that makes programmers life easier:

CONST
-----
  USAGE: 
    CONST name = value, name2 = value
  It declares a constant(This works exactly like qb)

%%INCLUDE
---------
  USAGE:
    %%INCLUDE: "name of file"

  Attach the specified file to the bas file. Included files can contain subroutines.

%%DESTOS, %%PLATFORM
--------------------
  USAGE:
    %%DESTOS: win32/dos32 OR win/dos
    %%PLATFORM: win32/dos32 OR win/dos

  Sets the exe destination OS(can be set from commandline too)

%%IFC *N
--------
  USAGE:
    %%IFC constant_name
        ....
    %%ENDIF

  This will compile the code inside the if blocks if the constant dos [not] exist.

%%IF *N
-------
  USAGE:
    %%IF condition1 <condition> condition2
    %%END IF
 
    You can use |(or), &(and) to mix conditions.
  Example:
    CONST printt = 1
    %%IF destos = win32 THEN
      %%IFC endonwin
        %%ERRORENDCOMP: "This program was designed for dos"
      %%ENDIF
    %%ENDIF

    CLS
    
    %%IF printt > 0 THEN
      PRINT "HI"
    %%ELSE
      PRINT "BYE"
    %%ENDIF

    END
%%ELSE
------
  USAGE:
    %%ELSE

  This must be used with %%IFC, %%IF

%%ENDIF
-------
  USAGE:
    %%ENDIF

  Ends a %%IFC, %%IF block

%%ENDCOMP
---------
  USAGE:
    %%ENDCOMP

  Ends the compilation of the program

%%ERRORENDCOMP
--------------
  USAGE:
    %%ERRORENDCOMP: "text"

  Ends the compilation of the program and shows the text.

%%NOZEROVARS
------------
  USAGE:
    %%NOZEROVARS

  This must be used before a SUB/FUNCTION.
  This will make the compiler to not generate the code to clear the memory location
  where the vars are stored. So when you create a variable, can have any value.
  This should be used to optimize the sub start up time.
  Example:

  DECLARE SUB a
  DECLARE SUB b

  a
  b

  %%NOZEROVARS
  SUB a
    PRINT str$(testvar)     ; This will print any value on the screen
  END SUB

  SUB b
    PRINT str$(testvar)     ; This will print 0 on the screen
  END SUB
Now, let's see the run-time commands:

RUN-TIME COMMANDS LIST:
---------------------

Note:
  * means that if you dont put the B at the end of the keyword name, it will automatically
use the byte mode: Example: OUT 30, 1 is the same thing that OUTB 30, 1
  *n means that you can use NOT with the condition.


_ASM
----

  USAGE: 	_ASM	
  Works under: 	Both	
  Run on: 	Start of line

  	Starts the inline assembler(NASM)	
_END ASM
--------

  USAGE: 	_END ASM	
  Works under: 	Both	
  Run on: 	Start of line

  	Ends the inline assembler	
ABS
---

  USAGE: 	ABS(value)	
  Works under: 	Both	
  Run on: 	F/Imath Parser

  	Returns the absolute number
ASC
---

  USAGE: 	ASC(string)	
  Works under: 	Both	
  Run on: 	Imath Parser

  	Returns the ascii number of the first char of a string	
ASM_FUNCTION
------------

  USAGE: 	ASM_FUNCTION name (parameters)	
  Works under: 	Both	
  Run on: 	Start of line

  	Define the start of an assembly function	
ASM_SUB
-------

  USAGE: 	ASM_SUB name (parameters)	
  Works under: 	Both	
  Run on: 	Start of line

  	Define the start of an assembly sub
        An assembly sub/function is written completely in asm.
        You must use DECLARE SUB/FUNCTION with asm routines, not
        DECLARE ASM_SUB/ASM_FUNCTION

  Example:
  DECLARE SUB Hi
  DECLARE FUNCTION Bye

  Hi
  a = bye
  print str$(a)

  ASM_SUB hi
    .data
    hellotext DB 'Hello$'
    bye DB 'Bye$'

    .code
    mov ah, 09
    mov edx, hellotext
    int 21h 
  END ASM_SUB

  ASM_FUNCTION Bye
    mov ah, 09
    mov edx, bye
    int 21h 
    mov eax, 100
  END_FUNCTION      

CASE
----

  USAGE: 	CASE value	
  Works under: 	Both	
  Run on: 	Start of line

  	Executes the code after it if the condition is true.	
CLOSE
-----

  USAGE: 	CLOSE [number]	
  Works under: 	Both	
  Run on: 	Start of line

  	Close a file that was opened. If not file was specified, this
	will close all the opened files.
CLS
---

  USAGE: 	CLS	
  Works under: 	Both	
  Run on: 	Start of line

  	Clears the screen	
CODEPTR
----

  USAGE: 	CODEPTR(sub)	
  Works under: 	Both	
  Run on: 	Imath Parser

  	Returns the offset of a SUB/Function
COLOR
-----

  USAGE: 	COLOR fg, bg	
  Works under: 	Both	
  Run on: 	Start of line

  	Sets the screen color	
CONST
-----

  USAGE: 	CONST name = value[, name2 = value2...]	
  Works under: 	Both	
  Run on: 	Start of line

  	Defines a constant	
COS
---

  USAGE: 	COS(number)	
  Works under: 	Both	
  Run on: 	Fmath Parser

  	Returns the cosine of a number	
CPUFLAGS
--------

  USAGE: 	CPUFLAGS	
  Works under: 	Both	
  Run on: 	Imath Parser

  	Return the value of the CPUFLAGS(PUSHFD)	
DEC
---

  USAGE: 	DEC var_name	
  Works under: 	Both	
  Run on: 	Start of line

  	Decreases a the value of a variable by 1	
        Doesn't work with arrays
DECLARE
-------

  USAGE: 	DECLARE SUB/FUNCTION name (pars)	
  Works under: 	Both	
  Run on: 	Start of line

  	Declares a sub/function	
DEFxxx
------

  USAGE: 	DEFxxx letter1-letter2	
  Works under: 	Both	
  Run on: 	Start of line

  	You know what this does, check qbasic help
	Note that long values are faster that integer values.

  Example: DEFINT A-Z

DIM
---

  USAGE: 	DIM name [AS type] [ATOFFSET(offset)]	
  Works under: 	Both	
  Run on: 	Start of line

  	Defines a variable/string/array	
DO*n
----

  USAGE: 	DO [WHILE/UNTIL] cond1 <cond> cond2	
  Works under: 	Both	
  Run on: 	Start of line

  	Starts a DO-LOOP block	
ELSE
----

  USAGE: 	ELSE	
  Works under: 	Both	
  Run on: 	Start of line

  	Executes the code after it if the condition was false.	
ELSEIF*n
--------

  USAGE: 	ELSEIF cond1 <cond> cond2 THEN	
  Works under: 	Both	
  Run on: 	Start of line

  	Evaluates another condition insed a IF block	
EOF
---

  USAGE: 	EOF(filenumber)	
  Works under: 	Both	
  Run on: 	Imath Parser

  	Return 0 if you havent reached the end of the file	
FOR
---

  USAGE: 	FOR var = value TO value2 [STEP value]	
  Works under: 	Both	
  Run on: 	Start of line

  	Start a FOR-NEXT block	
FUNCTION
--------

  USAGE: 	FUNCTION name (parameters)	
  Works under: 	Both	
  Run on: 	Start of line

  	Define the start of a function	
GET
---

  USAGE: 	GET file, [filepos], [bytes], offset_to_store	
  Works under: 	Both	
  Run on: 	Start of line

  	Reads data from a file	
        If you omit the bytes parameter, this function works exactly like qb.
        (Will store the data at the variable/string given)
        If not, it will read the amount of bytes specified in [bytes] and will
        store them at the offset given.
GOSUB
-----

  USAGE: 	GOSUB label	
  Works under: 	Both	
  Run on: 	Start of line

  	Calls a line, that returns with the RET keyword.	
GOTO
----

  USAGE: 	GOTO label	
  Works under: 	Both	
  Run on: 	Start of line

  	Jumps to a line	
IF*n
----

  USAGE: 	IF cond1 <cond> cond2 THEN	
  Works under: 	Both	
  Run on: 	Start of line

  	Starts a IF-ENDIF block	

  Example:
    IF a = 1  | b = 1 THEN
      r = 1
    ELSEIF b = 2  & c = 2 THEN
      r = 2
    ELSE
      r = 3
    END IF

INC
---

  USAGE: 	INC var_name	
  Works under: 	Both	
  Run on: 	Start of line

  	Increases a the value of a variable by 1	
        Doesn't work with arrays
INPB*
-----

  USAGE: 	INPB(portnumber)	
  Works under: 	DOS	
  Run on: 	Imath Parser

  	Reads a value from a port(byte)	
INPD
----

  USAGE: 	INPD(portnumber)	
  Works under: 	DOS	
  Run on: 	Imath Parser

  	Reads a value from a port(dword)	
INPW
----

  USAGE: 	INPW(portnumber)	
  Works under: 	DOS	
  Run on: 	Imath Parser

  	Reads a value from a port(word)	
INT
---

  USAGE: 	INT int_numer, offset_of_interrupt_table	
  Works under: 	DOS	
  Run on: 	Start of line

  	Runs a interrupt

  The interrupt table is:

	TYPE intcallstruct
	  eax AS LONG
	  ebx AS LONG
	  ecx AS LONG
	  edx AS LONG
	  esi AS LONG
	  edi AS LONG
	END TYPE

  Right now ultrabasic don't store the values of the regs after the int was called.
  Of course I will add that in the future.

INT
---

  USAGE: 	INT(number)	
  Works under: 	Both	
  Run on: 	Imath Parser

  	Converts a number into a integer	
INT16
-----

  USAGE: 	INT16 int_numer, offset_of_interrupt_table	
  Works under: 	DOS	
  Run on: 	Start of line

  	Runs a real mode interrupt	

  Interrupt table for rmode int vcall:

	TYPE rintcallstruct
	  edi AS LONG
	  esi AS LONG
	  ebp AS LONG
	  esp AS LONG
	  ebx AS LONG
	  edx AS LONG
	  ecx AS LONG
	  eax AS LONG
	  flags AS INTEGER
	  es AS INTEGER
	  ds AS INTEGER
	  fs AS INTEGER
	  gs AS INTEGER
	  ip AS INTEGER
	  cs AS INTEGER
	  sp AS INTEGER
	  ss AS INTEGER
	  morespace AS STRING * 200
	END TYPE

LEN
---

  USAGE: 	LEN(string)	
  Works under: 	Both	
  Run on: 	Imath Parser

  	Returns the size of a string	
LOCATE
------

  USAGE: 	LOCATE y, x	
  Works under: 	Both	
  Run on: 	Start of line

  	Sets the cursor location	
LOF
---

  USAGE: 	LOF(filenumber)	
  Works under: 	Both	
  Run on: 	Imath Parser

  	Returns the size of a file	
LOOP*n
------

  USAGE: 	LOOP [WHILE/UNTIL] cond1 <cond> cond2	
  Works under: 	Both	
  Run on: 	Start of line

  	Ends a DO-LOOP block	
LPTR
----

  USAGE: 	LPTR(label)	
  Works under: 	Both	
  Run on: 	Imath Parser

  	Returns the offset of a label	
MEMCOPYB*
---------

  USAGE: 	MEMCOPYB readoffset, writeoffset, bytes	
  Works under: 	Both	
  Run on: 	Start of line

  	Copies an area of memory to another(Byte mode)	
MEMCOPYD
--------

  USAGE: 	MEMCOPYD readoffset, writeoffset, bytes	
  Works under: 	Both	
  Run on: 	Start of line

  	Copies an area of memory to another(Dword mode)	
MEMCOPYW
--------

  USAGE: 	MEMCOPYW readoffset, writeoffset, bytes	
  Works under: 	Both	
  Run on: 	Start of line

  	Copies an area of memory to another(Word mode)	
MEMFILLB*
---------

  USAGE: 	MEMFILLB offset, value, bytes	
  Works under: 	Both	
  Run on: 	Start of line

  	Fills the memory with the value(Byte mode)	
MEMFILLD
--------

  USAGE: 	MEMFILLD offset, value, bytes	
  Works under: 	Both	
  Run on: 	Start of line

  	Fills the memory with the value(Dword mode)	
MEMFILLW
--------

  USAGE: 	MEMFILLW offset, value, bytes	
  Works under: 	Both	
  Run on: 	Start of line

  	Fills the memory with the value(Word mode)	
NEXT
----

  USAGE: 	NEXT [var]	
  Works under: 	Both	
  Run on: 	Start of line

  	Ends a FOR-NEXT block	
OPEN
----

  USAGE: 	OPEN file FOR mode AS number	
  Works under: 	Both	
  Run on: 	Start of line

  	Opens a file.	
OUTB*
-----

  USAGE: 	OUT portnumber, value	
  Works under: 	DOS	
  Run on: 	Start of line

  	Writes a byte to a port	
OUTD
----

  USAGE: 	OUTD portnumber, value	
  Works under: 	DOS	
  Run on: 	Start of line

  	Writes a doubleword to a port	
OUTW
----

  USAGE: 	OUTW portnumber, value	
  Works under: 	DOS	
  Run on: 	Start of line

  	Writes a word to a port	
PEEKB*
------

  USAGE: 	PEEKB(offset)	
  Works under: 	Both	
  Run on: 	Imath Parser

  	Reads the value from a memory location(byte)	
PEEKD
-----

  USAGE: 	PEEKD(offset)	
  Works under: 	Both	
  Run on: 	Imath Parser

  	Reads the value from a memory location(dword)	
PEEKW
-----

  USAGE: 	PEEKW(offset)	
  Works under: 	Both	
  Run on: 	Imath Parser

  	Reads the value from a memory location(word)	
POKEB*
------

  USAGE: 	POKEB offset, value	
  Works under: 	Both	
  Run on: 	Start of line

  	Write a value to memory(Byte mode)	
POKED
-----

  USAGE: 	POKED offset, value	
  Works under: 	Both	
  Run on: 	Start of line

  	Write a value to memory(Dword mode)	
POKES
-----

  USAGE: 	Pokes Memorylocation&, text	
  Works under: 	Both	
  Run on: 	Start of line

  	Pokes a string to memory	
POKEW
-----

  USAGE: 	POKEW offset, value	
  Works under: 	Both	
  Run on: 	Start of line

  	Write a value to memory(Word mode)	
PRINT
-----

  USAGE: 	PRINT text	
  Works under: 	Both	
  Run on: 	Start of line

  	Put a text on the screen	
PUSH
----

  USAGE: 	PUSH value	
  Works under: 	Both	
  Run on: 	Start of line

  	Push a value into the stack	
	This is usefull to pass values to an asm routine.

  Example:

	a = 0A0000h
	PUSH a
	_ASM
	  POP eax
	  mov dword [eax], 0F0F0F0Fh
        _END ASM

PUT
---

  USAGE: 	PUT file, [filepos], [bytes], offset_to_read	
  Works under: 	Both	
  Run on: 	Start of line

  	Writes data to a file	
        If you omit the bytes parameter, this function works exactly like qb.
        (Will write the data from the variable/string given)
        If not, it will write the amount of bytes specified in [bytes] from the
        offset given.

SELECT CASE
-----------

  USAGE: 	SELECT CASE cond	
  Works under: 	Both	
  Run on: 	Start of line

  	Start a SELECT CASE block	

  Example:

	SELECT CASE a
	  CASE 1
	    PRINT "HI"
	  CASE ELSE
	    PRINT "BYE"
	END SELECT

SETNEWOFFSET
------------

  USAGE: 	SETNEWOFFSET name_of_var, newoffset&	
  Works under: 	Both	
  Run on: 	Start of line

  	Sets the new offset of a pointer	

  Example:

	SETNEWOFFSET Var1, 04

SETVECT
-------

  USAGE: 	SETVECT interrupt, address
  Works under: 	DOS	
  Run on: 	Start of line

	Sets the interrupt address
	You can fill address with a memory address, or with a 
	label/sub/function using LPTR or CODEPTR

SGN
---

  USAGE: 	SNG(value)	
  Works under: 	Both	
  Run on: 	Imath Parser

  	Returns the sign of the number(works exactly like qb)	
SIN
---

  USAGE: 	SIN(number)	
  Works under: 	Both	
  Run on: 	Fmath Parser

  	Returns the sine of a number	
SQRT
----

  USAGE: 	SQRT(number)	
  Works under: 	Both	
  Run on: 	Fmath Parser

  	Returns the square root of a number	
SUB
---

  USAGE: 	SUB name (parameters)	
  Works under: 	Both	
  Run on: 	Start of line

  	Define the start of a sub	
TAN
---

  USAGE: 	TAN(number)	
  Works under: 	Both	
  Run on: 	Fmath Parser

  	Returns the tangent of a number	
TIMER
-----

  USAGE: 	TIMER	
  Works under: 	DOS	
  Run on: 	Fmath Parser

  	Return the number of seconds since midnight.
        Only works if it is the first keyword in a math operation.
        I will fix that in the future
  Example:
    a! = TIMER
    b! = 2 + TIMER <---- This wont work

VAL
----

  USAGE: 	VAL(string)	
  Works under: 	Both	
  Run on: 	F/Imath Parser

  	Returns the value of a string
	
VARPTR/SADD
-----------

  USAGE: 	VARPTR(varname)	
  Works under: 	Both	
  Run on: 	Imath Parser

  	Returns the offset of a variable	

Contact
-------

  Check my website at:
    http://www.geocities.com/angros47

  E-Mail: angros47@yahoo.it

Thanks
------

A lot of people help me that I can't remember them all.

  Let's see:

      Michael Tippach for creating WDOSX, the best dos extender
      The NASM people that created the best assembler(and it is free) !!!
      Merlin for give me good dx tutorials
      Christopher Mattern because he sent me some great ideas.
      Blitz for giving me ideas about pointers
      The creator of ALINK
      The creator of OllyDbg, the best FREE debugger for windows.
      Michael Tomte for working on the Ide.
      And all the people I forgot.