1
1
Fork 0
mirror of https://github.com/DualBrain/QB64.git synced 2023-11-19 13:10:13 +00:00

More wiki experiment.

This commit is contained in:
Cory Smith 2022-12-24 19:12:43 -06:00
parent b87992c038
commit ca88ba2965
394 changed files with 39808 additions and 0 deletions

View file

@ -3,6 +3,7 @@
## Wiki
- **[PRINT](wiki/PRINT.md)**
- **[VIEW](wiki/VIEW.md)**
Although you can find several copies of the QB64 wiki on the internet, many of these exist as *backup copies* due to the past instability issues around QB64 .org and .net websites and (most likely) aren't currently maintained.

41
wiki/ABS.md Normal file
View file

@ -0,0 +1,41 @@
The [ABS](ABS) function returns the unsigned numerical value of a variable or literal value.
## Syntax
> positive = [ABS](ABS)(numericalValue)
## Description
* [ABS](ABS) always returns positive numerical values. The value can be any numerical type.
* Often used to keep a value positive when necessary in a program.
* Use [SGN](SGN) to determine a value's sign when necessary.
* **QB64** allows programs to return only positive [_UNSIGNED](_UNSIGNED) variable values using a [DIM](DIM) or [_DEFINE](_DEFINE) statement.
## Example(s)
Finding the absolute value of positive and negative numerical values.
```vb
a = -6
b = -7
c = 8
IF a < 0 THEN a = ABS(a)
b = ABS(b)
c = ABS(c)
PRINT a, b, c
```
```text
6 7 8
```
## See Also
* [SGN](SGN), [DIM](DIM)
* [_UNSIGNED](_UNSIGNED)
* [_DEFINE](_DEFINE)
* [Mathematical Operations](Mathematical-Operations)

1
wiki/ACCESS.md Normal file
View file

@ -0,0 +1 @@
See [OPEN](OPEN).

45
wiki/ALIAS.md Normal file
View file

@ -0,0 +1,45 @@
See [DECLARE LIBRARY](DECLARE-LIBRARY).
The [ALIAS](ALIAS) clause in a [DECLARE LIBRARY](DECLARE-LIBRARY) statement block tells the program the name of the procedure used in the external library.
## Syntax
> SUB *pseudoname* [ALIAS](ALIAS) *actualname* [(*parameters*)]
## Parameter(s)
* The *pseudo name* is the name of the [SUB](SUB) or [FUNCTION](FUNCTION) the QB64 program will use.
* The *actual name* is the same procedure name as it is inside of the DLL library.
* QB64 must use all parameters of imported procedures including optional ones.
## Description
* The ALIAS name clause is optional as the original library procedure name can be used.
* The procedure name does not have to be inside of quotes when using [DECLARE LIBRARY](DECLARE-LIBRARY).
* QB64 does not support optional parameters.
## Example(s)
Instead of creating a SUB with the Library statement inside of it, just rename it:
```vb
DECLARE LIBRARY
SUB MouseMove ALIAS glutWarpPointer (BYVAL xoffset&, BYVAL yoffset&)
END DECLARE
DO UNTIL _SCREENEXISTS: LOOP
PRINT "Hit a key..."
SLEEP
MouseMove 1, 1
```
> *Explanation:* When a Library procedure is used to represent another procedure name use ALIAS instead. Saves creating a SUB! Just place your name for the procedure first with the actual Library name after ALIAS.
## See Also
* [SUB](SUB), [FUNCTION](FUNCTION)
* [DECLARE LIBRARY](DECLARE-LIBRARY), [BYVAL](BYVAL)
* [DECLARE DYNAMIC LIBRARY](DECLARE-DYNAMIC-LIBRARY)

79
wiki/AND-(boolean).md Normal file
View file

@ -0,0 +1,79 @@
The [AND (boolean)](AND-(boolean)) conditonal operator is used to include another evaluation in an [IF...THEN](IF...THEN) or [Boolean](Boolean) statement.
## Syntax
> IF condition [AND (boolean)](AND-(boolean)) condition2
## Description
* If condition [AND (boolean)](AND-(boolean)) condition2 are true then the evaluation returns true (-1).
* condition and condition2 can also contain their own AND evaluations.
* Both the IF evaluation and the AND evaluation must be true for the statement to be true.
* Statements can use parenthesis to clarify an evaluation.
* [AND (boolean)](AND-(boolean)) and [OR (boolean)](OR-(boolean)) cannot be used to combine command line operations.
* Not to be confused with the [AND](AND) and [OR](OR) numerical operations.
**Relational Operators:**
| Symbol | Condition | Example Usage |
| -- | -- | -- |
| = | Equal | IF a = b THEN |
| <> | NOT equal | IF a <> b THEN |
| < | Less than | IF a < b THEN |
| > | Greater than | IF a > b THEN |
| <= | Less than or equal | IF a <= b THEN |
| >= | Greater than or equal | IF a >= b THEN |
## Example(s)
Using AND in an IF statement.
```vb
a% = 100
b% = 50
IF a% > b% AND a% < 200 THEN PRINT "True"
```
```text
True
```
*Explanation:* Both condition evaluations must be true for the code to be executed.
Using a AND a more complex way.
```vb
a% = 100
b% = 50
c% = 25
d% = 50
e% = 100
IF (a% > b% AND b% > c%) AND (c% < d% AND d% < e%) THEN
PRINT "True"
ELSE
PRINT "False"
END IF
```
```text
True
```
*Explanation:* The evaluations in the paranteses are evaluated first then the evaluation *of* the paranteses takes place, since all evaluations return True the IF...THEN evaluation returns True. If any of the evaluations returned False then the IF...THEN evaluation would also return False.
## See Also
* [AND](AND), [OR](OR) (logical operators)
* [OR (boolean)](OR-(boolean)), [XOR (boolean)](XOR-(boolean))
* [IF...THEN](IF...THEN)

93
wiki/AND.md Normal file
View file

@ -0,0 +1,93 @@
The logical [AND](AND) numerical operator compares two values in respect of their bits. If both bits at a certain position in both values are set, then that bit position is set in the result.
## Syntax
> result = firstvalue **[AND](AND)** secondvalue
## Description
* [AND](AND) compares the bits of the firstvalue against the bits of the secondvalue, the result is stored in the result variable.
* If both bits are on (1) then the result is on (1).
* All other conditions return 0 (bit is off).
* AND is often used to see if a bit is on by comparing a value to an exponent of 2.
* Can turn off a bit by subtracting the bit on value from 255 and using that value to AND a byte value.
The results of the bitwise logical operations, where *A* and *B* are operands, and *T* and *F* indicate that a bit is set or not set:
| A | B | | [NOT](NOT) B | A [AND](AND) B | A [OR](OR) B | A [XOR](XOR) B | A [EQV](EQV) B | A [IMP](IMP) B |
| - | - | - | - | - | - | - | - | - |
| T | T | | F | T | T | F | T | T |
| T | F | | T | F | T | T | F | F |
| F | T | | F | F | T | T | F | T |
| F | F | | T | F | F | F | T | T |
**[Relational Operations](Relational-Operations) return negative one (-1, all bits set) and zero (0, no bits set) for *true* and *false*, respectively.**
This allows relational tests to be inverted and combined using the bitwise logical operations.
## Example(s)
*Example 1:*
```text
101
AND
011
-----
001
```
> The 101 bit pattern equals 5 and the 011 bit pattern equals 3, it returns the bit pattern 001 which equals 1. Only the Least Significant Bits (LSB) match. So decimal values 5 AND 3 = 1.
*Example 2:*
```text
11111011
AND
11101111
----------
11101011
```
> Both bits have to be set for the resulting bit to be set. You can use the [AND](AND) operator to get one byte of a two byte integer this way:
> firstbyte = twobyteint AND 255
> Since 255 is 11111111 in binary, it will represent the first byte completely when compared with AND.
> To find the second (HI) byte's decimal value of two byte [INTEGER](INTEGER)s use: secondbyte = twobyteint \ 256
Finding the binary bits on in an [INTEGER](INTEGER) value.
```vb
DO
INPUT "Enter Integer value from -32768 to 32767 (Enter quits): ", INTvalue&
IF INTvalue& < -32768 OR INTvalue& > 32767 OR INTval& = 0 THEN EXIT DO
FOR exponent = 15 TO 0 STEP -1
IF (INTvalue& AND 2 ^ exponent) THEN PRINT "1"; ELSE PRINT "0";
NEXT
PRINT " "
LOOP UNTIL INTvalue& = 0 'zero entry quits
```
> Example output for 6055.
```text
0001011110100111
```
> *Note:* The value of 32767 sets 15 bits. -1 sets all 16 bits. Negative values will all have the highest bit set. Use [LONG](LONG) variables for input values to prevent overflow errors.
## See Also
* [OR](OR), [XOR](XOR), [NOT](NOT) (logical operators)
* [AND (boolean)](AND-(boolean))
* [Binary](Binary), [Boolean](Boolean)

17
wiki/APPEND.md Normal file
View file

@ -0,0 +1,17 @@
See [OPEN](OPEN).
[APPEND](APPEND) is used in an output type [OPEN](OPEN) statement to add data to the end of a file.
## Syntax
> [OPEN](OPEN) fileName$ **FOR APPEND** AS #1
## Description
* Creates an empty file using the filename if none exists.
* Mode places new data after the previous data in the file.
* Mode can use [PRINT (file statement)](PRINT-(file-statement)), [WRITE (file statement)](WRITE-(file-statement)) or [PRINT USING (file statement)](PRINT-USING-(file-statement)) to output file data or text.
## See Also
[OUTPUT](OUTPUT), [RANDOM](RANDOM), [INPUT (file mode)](INPUT-(file-mode)), [BINARY](BINARY)

29
wiki/AS.md Normal file
View file

@ -0,0 +1,29 @@
The [AS](AS) keyword defines a variable data [Variable Types](Variable-Types).
## Description
* AS defines the variable or array type AS [_BIT](_BIT), [_BYTE](_BYTE), [INTEGER](INTEGER), [LONG](LONG), [_INTEGER64](_INTEGER64), [SINGLE](SINGLE), [DOUBLE](DOUBLE), [_FLOAT](_FLOAT) or [STRING](STRING).
* Specifies a variable's [Variable Types](Variable-Types) in a declarative statement or parameter list using:
* [DIM](DIM) or [REDIM](REDIM)
* [DECLARE LIBRARY](DECLARE-LIBRARY)
* [SUB](SUB)
* [FUNCTION](FUNCTION)
* [TYPE](TYPE)
* [SHARED](SHARED)
* [COMMON SHARED](COMMON-SHARED)
* [STATIC](STATIC)
### Details
* Specifies a **[parameter](parameter)** variable's type in a [SUB](SUB) or [FUNCTION](FUNCTION) procedure. **Cannot be used to define a function's [Variable Types](Variable-Types)**
* Specifies an element's type in a user-defined data [TYPE](TYPE).
* Assigns a file number to a file or device in an [OPEN](OPEN) statement.
* Specifies a field name in a random-access record (see [FIELD](FIELD))
* Specifies a new file name when you rename a file (see [NAME](NAME))
* **NOTE: Many QBasic keywords can be used as variable names if they are created as [STRING](STRING)s using the suffix **$**. You cannot use them without the suffix, use a numerical suffix or use [DIM](DIM), [REDIM](REDIM), [_DEFINE](_DEFINE), [BYVAL](BYVAL) or [TYPE](TYPE) variable [AS](AS) statements.**
## See Also
* [DIM](DIM), [REDIM](REDIM)
* [_DEFINE](_DEFINE)
* [BYVAL](BYVAL), [TYPE](TYPE)
* [Variable Types](Variable-Types)

47
wiki/ASC-(statement).md Normal file
View file

@ -0,0 +1,47 @@
The [ASC (statement)](ASC-(statement)) statement allows a **QB64** program to change a character at any position of a [STRING](STRING) variable.
## Syntax
> [ASC (statement)](ASC-(statement))(stringExpression$[, position%]) = code%
## Description
* The stringExpression$ variable's value must have been previously defined and cannot be an empty string ("").
* position% is optional. If no position is used, the leftmost character at position 1 is assumed.
* position% cannot be zero or greater than the string's [LEN](LEN) or an [ERROR Codes](ERROR-Codes) will occur.
* The [ASCII](ASCII) replacement code% value can be any [INTEGER](INTEGER) value from 0 to 255.
* Some [ASCII](ASCII) control characters will not [PRINT](PRINT) a character or may format the [SCREEN](SCREEN). [_PRINTSTRING](_PRINTSTRING) can print them graphically.
## Example(s)
Demonstrates how to change existing text characters one letter at a time.
```vb
a$ = "YZC"
ASC(a$) = 65 ' CHR$(65) = "A"
ASC(a$, 2) = 66 ' CHR$(66) = "B"
PRINT a$ 'ABC
ASC(a$, 2) = 0 ' CHR$(0) = " "
PRINT a$
ASC(a$, 2) = ASC("S") ' get code value from ASC function
PRINT a$
```
```text
ABC
A C
ASC
```
## See Also
* [ASC](ASC) (function)
* [MID$ (statement)](MID$-(statement))
* [_PRINTSTRING](_PRINTSTRING)
* [INKEY$](INKEY$), [ASCII](ASCII)

176
wiki/ASC.md Normal file
View file

@ -0,0 +1,176 @@
The [ASC](ASC) function returns the [ASCII](ASCII) code number of a certain [STRING](STRING) text character or a keyboard press.
## Syntax
> code% = [ASC](ASC)(text$[, position%])
* text$ [STRING](STRING) character parameter must have a length of at least 1 byte or an error occurs.
* **In QB64** the optional byte position% [INTEGER](INTEGER) parameter greater than 0 can specify the ASCII code of any character in a string to be returned.
* If the optional position% parameter is omitted, ASC will return the [ASCII](ASCII) code of the first [STRING](STRING) character.
* [ASCII](ASCII) code [INTEGER](INTEGER) or [_UNSIGNED](_UNSIGNED) [_BYTE](_BYTE) values returned range from 0 to 255.
* ASC returns 0 when reading [ASCII](ASCII) 2 byte codes returned by [INKEY$](INKEY$) when the arrow, function, Home/Page keys are used.
* Use QB64's position% parameter to read the second byte if necessary. IF ASC(key$) <nowiki>=</nowiki> 0 THEN byte2 <nowiki>=</nowiki> ASC(key$, 2)
* In **QB64** ASC string byte position reads are about **5 times faster** than [MID$](MID$) when parsing strings. See [MID$](MID$) *Example 2*.
## Error(s)
* If the function is used to read an **empty string value** an illegal function call [ERROR Codes](ERROR-Codes) will occur. [INKEY$](INKEY$) returns an empty string when a key is not pressed.
* **QB64**'s position% parameters must range from 1 to the [LEN](LEN) of the string being read or an illegal function call [ERROR Codes](ERROR-Codes) will occur.
```text
' **ASCII Keyboard Codes**
'
**' Esc F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 Sys ScL Pause**
' 27 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +133 +134 - - -
**' `~ 1! 2@ 3# 4$ 5% 6^ 7& 8* 9( 0) -_ =+ BkSp Ins Hme PUp NumL / * -**
' 126 33 64 35 36 37 94 38 42 40 41 95 43 8 +82 +71 +73 - 47 42 45
** 96 49 50 51 52 53 54 55 56 57 48 45 61*
**' Tab Q W E R T Y U I O P [{ ]} \| Del End PDn 7Hme 8/▲ 9PU + **
' 9 81 87 69 82 84 89 85 73 79 80 123 125 124 +83 +79 +81 +71 +72 +73 43
** 113 119 101 114 116 121 117 105 111 112 91 93 92 55 56 57 *
**' CapL A S D F G H J K L ;: '" Enter 4/◄- 5 6/-►
' - 65 83 68 70 71 72 74 75 76 58 34 13 +75 +76 +77 **E**
** 97 115 100 102 103 104 106 107 108 59 39 52 53 54 * **n**
**' Shift Z X C V B N M ,< .> /? Shift ▲ 1End 2/▼ 3PD t**
' * 90 88 67 86 66 78 77 60 62 63 * +72 +79 +80 +81 **e**
** 122 120 99 118 98 110 109 44 46 47 49 50 51 * **r**
**' Ctrl Win Alt Spacebar Alt Win Menu Ctrl ◄- ▼ -► 0Ins .Del **
' * - * 32 * - - * +75 +80 +77 +82 +83 13
' * 48 46*
'
' ** *Italics* = LCase/NumLock On ____________ + = 2 Byte: CHR$(0) + CHR$(code)**
'
```
**[ASCII](ASCII)**
```text
**Two Byte Characters    Key                 CHR$(0) + "?" **
CHR$(0) + CHR$(16-50) [Alt] + letter
CHR$(0) + CHR$(59) [F1] ";"
CHR$(0) + CHR$(60) [F2] "<"
CHR$(0) + CHR$(61) [F3] "="
CHR$(0) + CHR$(62) [F4] ">"
CHR$(0) + CHR$(63) [F5] "?"
CHR$(0) + CHR$(64) [F6] "@"
CHR$(0) + CHR$(65) [F7] "A"
CHR$(0) + CHR$(66) [F8] "B"
CHR$(0) + CHR$(67) [F9] "C"
CHR$(0) + CHR$(68) [F10] "D"
CHR$(0) + CHR$(71) [Home] "G"
CHR$(0) + CHR$(72) [↑] Arrow "H"
CHR$(0) + CHR$(73) [Page Up] "I"
CHR$(0) + CHR$(75) [←] Arrow "K"
CHR$(0) + CHR$(76) [5 NumberPad] "L" (NumLock off in QB64)
CHR$(0) + CHR$(77) [→] Arrow "M"
CHR$(0) + CHR$(79) [End] "O"
CHR$(0) + CHR$(80) [↓] Arrow "P"
CHR$(0) + CHR$(81) [Page Down] "Q"
CHR$(0) + CHR$(82) [Insert] "R"
CHR$(0) + CHR$(83) [Delete] "S"
CHR$(0) + CHR$(84-93) [Shift] + F1-10
CHR$(0) + CHR$(94-103) [Ctrl] + F1-10
CHR$(0) + CHR$(104-113) [Alt] + F1-10
CHR$(0) + CHR$(114-119) [Ctrl] + keypad
CHR$(0) + CHR$(120-129) [Alt] + number
CHR$(0) + CHR$(130 or 131) [Alt] + _/- or +/= "é" or "â"
CHR$(0) + CHR$(133) [F11] "à"
CHR$(0) + CHR$(134) [F12] "å"
CHR$(0) + CHR$(135) [Shift] + [F11] "ç"
CHR$(0) + CHR$(136) [Shift] + [F12] "ê"
CHR$(0) + CHR$(137) [Ctrl] + [F11] "ë"
CHR$(0) + CHR$(138) [Ctrl] + [F12] "è"
CHR$(0) + CHR$(139) [Alt] + [F11] "ï"
CHR$(0) + CHR$(140) [Alt] + [F12] "î"
```
> In **QB64**, [CVI](CVI) can be used to get the [_KEYDOWN](_KEYDOWN) 2-byte code value. Example: IF _KEYDOWN([CVI](CVI)([CHR$](CHR$)(0) + "P")) THEN
## Example(s)
How ASC can be used to find any ASCII code in a string of characters using QB64.
```vb
PRINT ASC("A")
PRINT ASC("Be a rockstar")
PRINT ASC("QB64 is not only COMPATIBLE, it can find any part of the string!", 18)
```
*Returns:*
```text
65
66
67
```
*Explanation:* The ASCII code for "A" is 65 and the ASCII code for "B" is 66, ASCII code for "C" is 67 and the "C" is at position 18 in the string.
> *Note:* The ASCII code for "A" and "a" are different by the value of 32, "A" + 32 is "a", 65("A") + 32 = 97("a").
Reading the ASCII and two byte code combinations with ASC in **QB64**.
```vb
Q$ = CHR$(34) ' quote character
COLOR 10: LOCATE 5, 22: PRINT "Press some keys or combinations!"
COLOR 13: LOCATE 23, 30: PRINT "Escape key Quits"
DO
DO: SLEEP: key$ = INKEY$: LOOP UNTIL key$ <> "" ' prevent ASC empty string read error
code% = ASC(key$): COLOR 11: LOCATE 10, 10
IF code% THEN ' ASC returns any value greater than 0
PRINT "CHR$(" + LTRIM$(STR$(code%)) + ")" + SPACE$(13):
IF code% > 8 AND code% < 14 THEN code% = 32 ' unprintable control codes
COLOR 14: LOCATE 10, 50: PRINT CHR$(code%) + SPACE$(13)
ELSE: PRINT "CHR$(0) + CHR$(" + LTRIM$(STR$(ASC(key$, 2))) + ")"
COLOR 14: LOCATE 10, 50: PRINT "CHR$(0) + " + Q$ + CHR$(ASC(key$, 2)) + Q$
END IF
LOOP UNTIL code% = 27 * '
```
*Explanation:* The keypress read loop checks that ASC will not read an empty string. That would create a program error. [SLEEP](SLEEP) reduces CPU memory usage between keypresses. Normal byte codes returned are indicated by the IF statement when ASC returns a value. Otherwise the routine will return the two byte ASCII code. The extended keyboard keys(Home pad, Arrow pad and Number pad), Function keys or Ctrl, Alt or Shift key combinations will return two byte codes. Ctrl + letter combinations will return control character codes 1 to 26.
Reading only numerical values input by a program user.
```vb
DO: SLEEP ' requires a keypress to run loop once
K$ = INKEY$
code = ASC(K$)
IF code >= 48 AND code <= 57 THEN entry$ = entry$ + CHR$(code) ' numbers only
IF code = 46 AND flag = 0 THEN
entry$ = entry$ + K$: flag = 1: mark = LEN(entry$) ' decimal point
END IF
L = LEN(entry$) ' check entry length for possible backspace
IF code = 8 AND L > 0 THEN ' backspace pressed and entry has a length
entry$ = MID$(entry$, 1, L - 1) ' remove one character from entry$
IF L - 1 < mark THEN flag = 0 ' allow another decimal point if removed.
LOCATE 10, POS(0) - 1: PRINT SPACE$(1); ' remove character from screen
END IF
LOCATE 10, 10: PRINT entry$;
' display present entry to user(semicolon required for correct POS return)
LOOP UNTIL code = 13 AND L
```
*Explanation:* [SLEEP](SLEEP) waits for a keypress allowing background programs to use the processor time. It also keeps the press in the keyboard buffer for [INKEY$](INKEY$) to read and guarantees that ASC will not read an empty string value to create an error. Filtered codes 48 to 57 are only number characters. One decimal point is allowed by using the flag. Code 8 is a backspace request which is ignored if the entry has no characters. If it is allowed it removes the last character from the entry and the screen. The loop exits when the user presses the [Enter] key and the entry has a length.
## See Also
* [ASC (statement)](ASC-(statement))
* [_KEYHIT](_KEYHIT), [_KEYDOWN](_KEYDOWN)
* [MID$](MID$), [CHR$](CHR$), [INKEY$](INKEY$)
* [VAL](VAL), [STRING$](STRING$)
* [ASCII](ASCII), [_MAPUNICODE](_MAPUNICODE)
* [Scancodes](Scancodes)

1
wiki/ASCII-Table.md Normal file
View file

@ -0,0 +1 @@
See [ASCII](ASCII).

421
wiki/ASCII.md Normal file
View file

@ -0,0 +1,421 @@
## ASCII and Extended Codes
[MS-DOS code page 437](http://en.wikipedia.org/wiki/Code_page_437)
[ASCII Control 0 to 31](http://ascii.cl/control-characters.htm) \| ASCII Keyboard Character Codes 32 to 127
| Code | Character [key] | Code | Character | Code | Character | Code | Character |
| ---- | --------------- | ---- | --------- | ---- | --------- | ---- | --------- |
| 0 | (NUL) | 32 | \[[SPACE$](SPACE$)]| 64 | @ | 96 | ` |
| 1 | ☺ (SOH) | 33 | ! | 65 | A | 97 | a |
| 2 | ☻ (STX) | 34 | " | 66 | B | 98 | b |
| 3 | ♥ (ETX) | 35 | # | 67 | C | 99 | c |
| 4 | ♦ (EOT) | 36 | $ | 68 | D | 100 | d |
| 5 | ♣ (ENQ) | 37 | % | 69 | E | 101 | e |
| 6 | ♠ (ACK) | 38 | & | 70 | F | 102 | f |
| 7 | • (BEL) \[BEEP](BEEP)| 39 | ' | 71 | G | 103 | g |
| 8 | ◘ \[BackSpace] `**`| 40 | ( | 72 | H | 104 | h |
| 9 | ○ (HT) \[TAB] `**`| 41 | ) | 73 | I | 105 | i |
| 10 | ◙ (LineFeed) `**`| 42 | * | 74 | J | 106 | j |
| 11 | ♂ (VT) `**`| 43 | + | 75 | K | 107 | k |
| 12 | ♀ (FormFeed) `**`| 44 | , | 76 | L | 108 | l |
| 13 | ♪ (CR) \[Enter] `**`| 45 | - | 77 | M | 109 | m |
| 14 | ♫ (SO) | 46 | . | 78 | N | 110 | n |
| 15 | ¤ (SI) | 47 | / | 79 | O | 111 | o |
| 16 | ► (DLE) | 48 | 0 | 80 | P | 112 | p |
| 17 | ◄ (DC1) | 49 | 1 | 81 | Q | 113 | q |
| 18 | ↕ (DC2) | 50 | 2 | 82 | R | 114 | r |
| 19 | ‼ (DC3) | 51 | 3 | 83 | S | 115 | s |
| 20 | ¶ (DC4) | 52 | 4 | 84 | T | 116 | t |
| 21 | § (NAK) | 53 | 5 | 85 | U | 117 | u |
| 22 | ▬ (SYN) | 54 | 6 | 86 | V | 118 | v |
| 23 | ↨ (ETB) | 55 | 7 | 87 | W | 119 | w |
| 24 | ↑ (CAN) | 56 | 8 | 88 | X | 120 | x |
| 25 | ↓ (EM) | 57 | 9 | 89 | Y | 121 | y |
| 26 | → (SUB) [EOF](EOF) | 58 | : | 90 | Z | 122 | z |
| 27 | ← (ESC) \[Esc]| 59 | ; | 91 | [ | 123 | { |
| 28 | ∟ (FS) `**`| 60 | < | 92 | \ | 124 | \| |
| 29 | ↔ (GS) `**`| 61 | = | 93 | ] | 125 | } |
| 30 | ▲ (RS) `**`| 62 | > | 94 | ^ | 126 | ~ |
| 31 | ▼ (US) `**`| 63 | ? | 95 | _ | 127 | ¦ (DEL) `*` |
IBM, International, graphical, mathematical and other characters
| Code | Character | Code | Character | Code | Character | Code | Character
| ---- | --------------- | ---- | --------- | ---- | --------- | ---- | --------- |
| 128 | Ç | 160 | á | 192 | + | 224 | a |
| 129 | ü | 161 | í | 193 | - | 225 | ß |
| 130 | é | 162 | ó | 194 | - | 226 | G |
| 131 | â | 163 | ú | 195 | + | 227 | p |
| 132 | ä | 164 | ñ | 196 | - | 228 | S |
| 133 | à | 165 | Ñ | 197 | + | 229 | s |
| 134 | å | 166 | ª | 198 | ¦ | 230 | µ |
| 135 | ç | 167 | º | 199 | ¦ | 231 | t |
| 136 | ê | 168 | ¿ | 200 | + | 232 | F |
| 137 | ë | 169 | ¬ | 201 | + | 233 | T |
| 138 | è | 170 | ¬ | 202 | - | 234 | O |
| 139 | ï | 171 | ½ | 203 | - | 235 | d |
| 140 | î | 172 | ¼ | 204 | ¦ | 236 | 8 |
| 141 | ì | 173 | ¡ | 205 | - | 237 | f |
| 142 | Ä | 174 | « | 206 | + | 238 | e |
| 143 | Å | 175 | » | 207 | - | 239 | n |
| 144 | É | 176 | ¦ | 208 | - | 240 | = |
| 145 | æ | 177 | ¦ | 209 | - | 241 | ± |
| 146 | Æ | 178 | ¦ | 210 | - | 242 | = |
| 147 | ô | 179 | ¦ | 211 | + | 243 | = |
| 148 | ö | 180 | ¦ | 212 | + | 244 | ( |
| 149 | ò | 181 | ¦ | 213 | + | 245 | ) |
| 150 | û | 182 | ¦ | 214 | + | 246 | ÷ |
| 151 | ù | 183 | + | 215 | + | 247 | ˜ |
| 152 | ÿ | 184 | + | 216 | + | 248 | ° |
| 153 | Ö | 185 | ¦ | 217 | + | 249 | · |
| 154 | Ü | 186 | ¦ | 218 | + | 250 | · |
| 155 | ¢ | 187 | + | 219 | ¦ | 251 | v |
| 156 | £ | 188 | + | 220 | _ | 252 | n |
| 157 | ¥ | 189 | + | 221 | ¦ | 253 | ² |
| 158 | P | 190 | + | 222 | ¦ | 254 | ¦ |
| 159 | ƒ | 191 | + | 223 | ¯ | 255 | *NBSP* `***` |
* `*` DEL was used to erase paper tape data by punching out all of the 7 holes.**
* `**` Control characters 8 to 13 and 28 to 31 can move text formatting when [PRINT](PRINT) and do not display
* `***` NBSP is a Non-breaking Space used to indent text. Some browsers may handle this character differently**
[More information about ASCII Control Characters](http://www.lammertbies.nl/comm/info/ascii-characters.html)
[Unicode](Unicode)
## Control Characters
* [INKEY$](INKEY$) will return Control + letter key press combinations as the equivalent control characters or bold **function keys** listed below:
Code | C | Description | Code | C | Description
--- | --- | --- | --- | --- | ---
CTRL + A = CHR$(1) | ☺ | StartHeader (SOH) | CTRL + B = CHR$(2) | ☻ | StartText (STX)
CTRL + C = CHR$(3) | ♥ | EndText (ETX) | CTRL + D = CHR$(4) | ♦ | EndOfTransmit (EOT)
CTRL + E = CHR$(5) | ♣ | Enquiry (ENQ) | CTRL + F = CHR$(6) | ♠ | Acknowledge (ACK)
CTRL + G = CHR$(7) | `•` | Bell (BEL) | CTRL + H = CHR$(8) | ◘ | [Backspace] (BSP)
CTRL + I = CHR$(9) | `○` | Horiz.Tab [Tab] | CTRL + J = CHR$(10) | `◙` | LineFeed(printer) (LF)
CTRL + K = CHR$(11) | `♂` | Vert. Tab (VT) | CTRL + L = CHR$(12) | `♀` | FormFeed(printer) (FF)
CTRL + M = CHR$(13) | `♪` | [Enter] (CR) | CTRL + N = CHR$(14) | ♫ | ShiftOut (SO)
CTRL + O = CHR$(15) | ☼ | ShiftIn (SI) | CTRL + P = CHR$(16) | ► | DataLinkEscape (DLE)
CTRL + Q = CHR$(17) | ◄ | DevControl1 (DC1) | CTRL + R = CHR$(18) | ↕ | DeviceControl2 (DC2)
CTRL + S = CHR$(19) | ‼ | DevControl3 (DC3) | CTRL + T = CHR$(20) | ¶ | DeviceControl4 (DC4)
CTRL + U = CHR$(21) | § | NegativeACK (NAK) | CTRL + V = CHR$(22) | ▬ | Synchronous Idle (SYN)
CTRL + W = CHR$(23) | ↨ | EndTXBlock (ETB) | CTRL + X = CHR$(24) | ↑ | Cancel (CAN)
CTRL + Y = CHR$(25) | ↓ | EndMedium (EM) | CTRL + Z = CHR$(26) | → | End Of File(SUB) (EOF)
**Highlighted items will format text and not [PRINT](PRINT) the symbol. [_PRINTSTRING](_PRINTSTRING) can print in QB64**
* Control characters **1 to 26** can be used to simulate *Ctrl + letter* key shortcuts in Windows programs using [_SCREENPRINT](_SCREENPRINT).
* [_CONTROLCHR](_CONTROLCHR) OFF can also be used in QB64 to allow control characters to be printed without formatting the text.
**ASCII in Text and Printing**
* Characters **0**(NULL) and **255**(NBSP) can also be used to print spaces(**32**). Useful for making file names harder to delete too.
* Character **7** will create a [BEEP](BEEP) sound when printed in **QB64** or an error sound in QBasic using a **SCREEN 0** window.
* Character **8** is returned when the **Backspace** key is pressed.
* Characters **9 thru 13** and **28 thru 31** can affect screen or file text placements and do not display the character when [PRINT](PRINT):
* Character **9** will **Tab** space the cursor 8 column spaces when printed.
* Character **10** moves the cursor or *"line feeds"* the printer head down one row.
* Character **11** vertical tabs the cursor back to top left position of page or screen. Acts like [CLS](CLS).
* Character **12** acts like [CLS](CLS) when printed. *"Form feeds"* the page out of printers.
* Character **13** is the cursor or typing **"carriage return"** to the start of the line on left side. Returned when **Enter** key pressed.
* Character **28** designates a File Separator. Moves the print cursor one space right. Combination Ctrl + \
* Character **29** designates a Group Separator. Moves the print cursor one space left. Combination Ctrl + ]
* Character **30** designates a Record Separator. Moves the print cursor one row up. Combination Ctrl + ^
* Character **31** designates a Unit Separator. Moves the print cursor one row down. Combination Ctrl + _
* **QB64** can display all of the control characters without formatting the text using [_PRINTSTRING](_PRINTSTRING).
* Characters **13** and **10** can be combined to create the **CrLf** carriage return used in files or printing. crlf$ = CHR$(13) + CHR$(10).
* Character **16**, the data link escape(DLE) character, can designate that a control character is being sent from a [OPEN COM](OPEN-COM).
Example(s)
(DLE) \<XON> \<DATA PACKET> (DLE) \<XOFF> or (DLE) \<STX> \<DATA PACKET> (DLE) \<ETX>
* Character **17**, Device Control 1, is used with [OPEN COM](OPEN-COM) to mark the start of a transmission as "XON". The character is read.
* Character **19**, Device Control 3, is used with [OPEN COM](OPEN-COM) to mark the end of a transmission as "XOFF". The character is NOT read.
* Character **26** can be used to designate the end of a file. See [EOF](EOF).
* Character **27** **?** is returned when the **Escape** key is pressed.
**Control character [PRINT](PRINT) actions can be controlled using [_CONTROLCHR](_CONTROLCHR) OFF or ON in QB64.**
```vb
SCREEN 12
COLOR 14: PRINT "Press Control + letter key combinations."
DO
K$ = INKEY$
IF LEN(K$) THEN
code = ASC(K$)
IF code < 32 THEN _PRINTSTRING (220, 100), "Ctrl + " + CHR$(code + 64) + " = " + K$ + " "
END IF
LOOP UNTIL K$ = CHR$(27)
END
```
**ASCII Character Usage**
* Characters are one byte and take up one space(byte) in a [STRING](STRING) value or variable.
* Extended(non-keyboard) characters can be entered by holding down *Alt* key and entering the code number on the Number pad.
* [PRINT](PRINT)s text characters and symbols or formats the screen, printer or file.
* [BINARY](BINARY) files often store values below 256 in the one byte character. To read the value get the code with [ASC](ASC).
* Numerical values placed into a [BINARY](BINARY) or [RANDOM](RANDOM) file using a [GET](GET) or [PUT](PUT) variable, they will be stored in [_MK$](_MK$) format.
* Characters **176** to **223** can be used to create screen borders or boundaries in an ASCII game. See: [SCREEN (function)](SCREEN-(function))
* Character **253**(small 2) can be found as the first character byte of a [BSAVE](BSAVE)d image file opened in [BINARY](BINARY) mode.
* Character **255** can be used as the NBSP(non-breaking space) character on web pages to fill in extra spaces.
* Can be used to crudely encrypt a file so others cannot read it by shifting the code values. See [CHR$](CHR$) example 2.
## [ASC](ASC) Codes
**[ASC](ASC) cannot read empty [INKEY$](INKEY$) = "" loop reads! Check for them before reading [ASC](ASC) key press codes!**
```text
' **ASCII Keyboard Codes**
'
**' Esc F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 Sys ScL Pause**
' 27 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +133 +134 - - -
**' `~ 1! 2@ 3# 4$ 5% 6^ 7& 8* 9( 0) -_ =+ BkSp Ins Hme PUp NumL / * -**
' 126 33 64 35 36 37 94 38 42 40 41 95 43 8 +82 +71 +73 - 47 42 45
** 96 49 50 51 52 53 54 55 56 57 48 45 61*
**' Tab Q W E R T Y U I O P [{ ]} \| Del End PDn 7Hme 8/? 9PU + **
' 9 81 87 69 82 84 89 85 73 79 80 123 125 124 +83 +79 +81 +71 +72 +73 43
** 113 119 101 114 116 121 117 105 111 112 91 93 92 55 56 57 *
**' CapL A S D F G H J K L ;: '" Enter 4/?- 5 6/-?
' - 65 83 68 70 71 72 74 75 76 58 34 13 +75 +76 +77 **E**
** 97 115 100 102 103 104 106 107 108 59 39 52 53 54 * **n**
**' Shift Z X C V B N M ,< .> /? Shift ? 1End 2/? 3PD t**
' * 90 88 67 86 66 78 77 60 62 63 * +72 +79 +80 +81 **e**
** 122 120 99 118 98 110 109 44 46 47 49 50 51 * **r**
**' Ctrl Win Alt Spacebar Alt Win Menu Ctrl ?- ? -? 0Ins .Del **
' * - * 32 * - - * +75 +80 +77 +82 +83 13
' * 48 46*
'
' ** *Italics* = LCase/NumLock On ____________ + = 2 Byte: CHR$(0) + CHR$(code)**
'<sub>NOTE: The above commented table can be copied and pasted directly into the QB64 IDE</sub>
```
Use **ASC(RIGHT$(key$, 1))** or **ASC(key$, 2)** in QB64 to read a two byte code when **ASC(key$) = 0**
*** See the Two Byte Ctrl, Alt and Shift + Function key combinations below**
```vb
' Demo displays all ASCII codes and 2 byte code combinations
DO: K$ = INKEY$
IF K$ <> "" THEN 'ASC will return an error if an empty string is read!
IF ASC(K$) > 0 THEN
PRINT "CHR$(" + LTRIM$(STR$(ASC(K$))) + ")" 'display normal keypress codes
ELSE PRINT "CHR$(0) + CHR$(" + LTRIM$(STR$(ASC(K$, 2))) + ")" 'display 2 byte codes
END IF
END IF
LOOP UNTIL K$ = CHR$(27) 'escape key press exits
```
> *Note:* In QB64 [ASC](ASC)(K$, 2) can read the second byte of the 2 byte code when [ASC](ASC)(K$) reads the first byte as 0.
## Two Byte Codes
**Two Byte ASCII Keyboard Return Values**
* [INKEY$](INKEY$) returns both bytes when two byte keys or key combinations are pressed. The second byte = [RIGHT$](RIGHT$)(keypress$, 1)
* If the character returned is a two byte code, [ASC](ASC) will return 0. **Warning:** ASC cannot read empty [INKEY$](INKEY$) string values!
* In **QB64** only, [ASC](ASC)(keypress$, 2) can return the second byte code. Don't read empty string values!
* String values returned can be compared in an [IF...THEN](IF...THEN) or [SELECT CASE](SELECT-CASE) routine by using the actual string definitions such as:
> IF INKEY$ = CHR$(0) + CHR$(80) THEN row = row + 1 **or** IF INKEY$ = CHR$(0) + "P" THEN row = row + 1
```text
**Two Byte Character Codes Key CHR$(0) + "?" **
CHR$(0) + CHR$(16-50) [Alt] + letter
CHR$(0) + CHR$(59) [F1] ";"
CHR$(0) + CHR$(60) [F2] "<"
CHR$(0) + CHR$(61) [F3] "="
CHR$(0) + CHR$(62) [F4] ">"
CHR$(0) + CHR$(63) [F5] "?"
CHR$(0) + CHR$(64) [F6] "@"
CHR$(0) + CHR$(65) [F7] "A"
CHR$(0) + CHR$(66) [F8] "B"
CHR$(0) + CHR$(67) [F9] "C"
CHR$(0) + CHR$(68) [F10] "D"
CHR$(0) + CHR$(71) [Home] "G"
CHR$(0) + CHR$(72) [?] Up Arrow "H"
CHR$(0) + CHR$(73) [Page Up] "I"
CHR$(0) + CHR$(75) [?] Left Arrow "K"
CHR$(0) + CHR$(76) [5 NumberPad] "L" (NumLock off in QB64)
CHR$(0) + CHR$(77) [?] Right Arrow "M"
CHR$(0) + CHR$(79) [End] "O"
CHR$(0) + CHR$(80) [?] Down Arrow "P"
CHR$(0) + CHR$(81) [Page Down] "Q"
CHR$(0) + CHR$(82) [Insert] "R"
CHR$(0) + CHR$(83) [Delete] "S"
CHR$(0) + CHR$(84-93) [Shift] + F1-10
CHR$(0) + CHR$(94-103) [Ctrl] + F1-10
CHR$(0) + CHR$(104-113) [Alt] + F1-10
CHR$(0) + CHR$(114-119) [Ctrl] + keypad
CHR$(0) + CHR$(120-129) [Alt] + number
CHR$(0) + CHR$(130 or 131) [Alt] + _/- or +/= "é" or "â"
CHR$(0) + CHR$(133) [F11] "à"
CHR$(0) + CHR$(134) [F12] "å"
CHR$(0) + CHR$(135) [Shift] + [F11] "ç"
CHR$(0) + CHR$(136) [Shift] + [F12] "ê"
CHR$(0) + CHR$(137) [Ctrl] + [F11] "ë"
CHR$(0) + CHR$(138) [Ctrl] + [F12] "è"
CHR$(0) + CHR$(139) [Alt] + [F11] "ï"
CHR$(0) + CHR$(140) [Alt] + [F12] "î"
```
> In **QB64**, [CVI](CVI) can be used to get the [_KEYDOWN](_KEYDOWN) 2-byte code value. Example: **status = _KEYDOWN(CVI(CHR$(0) + "P"))**
**See [Scancodes](Scancodes) for other keyboard function keys.**
## Code Examples
Using arrow keys to move a text character. A change from a previous position tells program when to PRINT:
```vb
movey = 1: movex = 1 'text coordinates can never be 0
at$ = "@" 'text sprite could be almost any ASCII character
LOCATE movey, movex: PRINT at$;
DO
px = movex: py = movey 'previous positions
B$ = INKEY$
IF B$ = CHR$(0) + CHR$(72) AND movey > 1 THEN movey = movey - 1 'rows 1 to 23 only
IF B$ = CHR$(0) + CHR$(80) AND movey < 23 THEN movey = movey + 1
IF B$ = CHR$(0) + CHR$(75) AND movex > 1 THEN movex = movex - 1 'columns 1 to 80 only
IF B$ = CHR$(0) + CHR$(77) AND movex < 80 THEN movex = movex + 1
IF px <> movex OR py <> movey THEN 'only changes when needed
LOCATE py, px: PRINT SPACE$(1); 'erase old sprite
LOCATE movey, movex: PRINT at$; 'show new position
END IF
LOOP UNTIL B$ = CHR$(27) 'ESCape key exit
END
```
Routine displays all keypress codes including Ctrl, Alt and Shift combinations. Ctrl + letter = control codes 1 to 26.
```vb
* *
SCREEN 13
tmp$ = " CHR$(###),\\,\ \ "
tmp2$ = " CHR$(0) + CHR$(###) \ \"
COLOR 14: LOCATE 3, 3: PRINT "The code can tell what key is pressed"
COLOR 12: LOCATE 5, 14: PRINT CHR$(3); SPACE$(3);
COLOR 13: PRINT CHR$(5); SPACE$(3);
COLOR 12: PRINT CHR$(4); SPACE$(3);
COLOR 13: PRINT CHR$(6)
COLOR 10: LOCATE 7, 4: PRINT " Hit a key to find the ASCII Code"
COLOR 5: LOCATE 13, 1: PRINT " Codes below 33 are called control keys"
LOCATE 14, 1: PRINT " CHR$(0) + are 2 byte Extended key codes"
COLOR 13: LOCATE 16, 1: PRINT " Extended: Press Alt + numberpad: Enter"
LOCATE 18, 1: PRINT " Try some Ctrl, Alt, or Shift Combo's"
COLOR 5: LOCATE 20, 1: PRINT " INKEY$ is used to detect the key entry"
COLOR 2: LOCATE 22, 15: PRINT CHR$(1); " "; CHR$(2)
COLOR 4: LOCATE 24, 10: PRINT "To Quit hit the TAB key";
COLOR 9
DO
DO: SLEEP: A$ = INKEY$: LOOP UNTIL A$ <> "" 'legal ASC read keys
IF ASC(A$) > 0 THEN ' normal key codes
code% = ASC(A$)
SELECT CASE code%
CASE 7: Key$ = "Beep"
CASE 8: Key$ = "Backspace"
CASE 9: Key$ = "Tab Key"
CASE 10: Key$ = "Line Feed"
CASE 12: Key$ = "Form Feed"
CASE 13: Key$ = "Enter"
CASE 27: Key$ = "Escape"
CASE 32: Key$ = "Space Bar"
CASE 48 TO 57: Key$ = "Number"
CASE 65 TO 90: Key$ = "Uppercase"
CASE 97 TO 122: Key$ = "Lowercase"
CASE ELSE: Key$ = ""
END SELECT
SELECT CASE code% 'check for unprintable control combo characters
CASE 10 TO 13: Kcode% = 32
CASE ELSE: Kcode% = code%
END SELECT
COLOR 9: LOCATE 10, 5: PRINT USING tmp$; code%; CHR$(Kcode%); Key$;
END IF
IF ASC(A$) = 0 THEN 'two byte key codes
code% = ASC(RIGHT$(A$, 1)) 'QBasic code
'code% = ASC(A$, 2) 'QB64 code alternative
SELECT CASE code%
CASE 16 TO 50: Key$ = "Alt+ letter"
CASE 72: Key$ = CHR$(24) + " Arrow"
CASE 75: Key$ = CHR$(27) + " Arrow"
CASE 77: Key$ = CHR$(26) + " Arrow"
CASE 80: Key$ = CHR$(25) + " Arrow"
CASE 83: Key$ = "Delete"
CASE 59: Key$ = "F1"
CASE 60: Key$ = "F2"
CASE 61: Key$ = "F3"
CASE 62: Key$ = "F4"
CASE 63: Key$ = "F5"
CASE 64: Key$ = "F6"
CASE 65: Key$ = "F7"
CASE 66: Key$ = "F8"
CASE 67: Key$ = "F9"
CASE 68: Key$ = "F10"
CASE 71: Key$ = "Home"
CASE 73: Key$ = "Page " + CHR$(24)
CASE 79: Key$ = "End"
CASE 81: Key$ = "Page " + CHR$(25)
CASE 82: Key$ = "Insert"
CASE 83: Key$ = "Delete"
CASE 84 TO 93: Key$ = "Shift+ F"
CASE 94 TO 103: Key$ = "Ctrl+ F"
CASE 104 TO 113: Key$ = "Alt+ F"
CASE 114 TO 119: Key$ = "Ctrl + pad"
CASE 120 TO 129: Key$ = "Alt+ number"
CASE 132: Key$ = "Ctrl + pad"
CASE 133: Key$ = "F11"
CASE 134: Key$ = "F12"
CASE 135: Key$ = "Shift+ F11"
CASE 136: Key$ = "Shift+ F12"
CASE 137: Key$ = "Ctrl+ F11"
CASE 138: Key$ = "Ctrl+ F12"
CASE 139: Key$ = "Alt+ F11"
CASE 140: Key$ = "Alt+ F12"
CASE ELSE: Key$ = ""
END SELECT
LOCATE 10, 5: PRINT USING tmp2$; code%; Key$
END IF
LOOP UNTIL A$ = CHR$(9)
SOUND 400, 4
SLEEP 3
SYSTEM
```
<sub>Code by Ted Weissgerber</sub>
*Explanation:* The routine checks for a keypress and [SLEEP](SLEEP) guarantees that [ASC](ASC) will never read an empty string from INKEY$. When the keypress is determined to be two bytes ([ASC](ASC)(A$) = 0) the second SELECT CASE routine is used. You can even display non-keyboard extended characters. Just press Alt + numberpad code, release and press enter.
> Note: Ctrl + letter keys will list the contol keys as normal codes. EX: Ctrl + G will BEEP (CHR$(7)).
## References
*Printable ASCII Table:* [_PRINTIMAGE](_PRINTIMAGE) (see Example 2 on page)
## See Also
* [_KEYHIT](_KEYHIT), [_KEYDOWN](_KEYDOWN)
* [_MAPUNICODE](_MAPUNICODE), [_MAPUNICODE (function)](_MAPUNICODE-(function))
* [Code Pages](Code-Pages) (Various Unicode Languages)
* [ASC (statement)](ASC-(statement)) (QB64 only)
* [ASC](ASC), [INSTR](INSTR)
* [CHR$](CHR$), [INKEY$](INKEY$)
* [LEFT$](LEFT$), [MID$](MID$), [RIGHT$](RIGHT$)
* [PRINT](PRINT), [SCREEN](SCREEN)
* [MKI$](MKI$), [MKL$](MKL$), [MKS$](MKS$), [MKD$](MKD$), [_MK$](_MK$)
* [_PRINTSTRING](_PRINTSTRING), [_SCREENPRINT](_SCREENPRINT)
* [_CONTROLCHR](_CONTROLCHR) (turns control PRINT actions OFF/ON)
* [Scancodes](Scancodes)(keyboard), [Unicode](Unicode)(character table)
* [Text Using Graphics](Text-Using-Graphics)

93
wiki/ATN.md Normal file
View file

@ -0,0 +1,93 @@
The [ATN](ATN) or arctangent function returns the angle in radians of a numerical [TAN](TAN) value.
## Syntax
> radianAngle = [ATN](ATN)(tangent!)
## Parameter(s)
* The return is the tangent!'s angle in **radians**.
* tangent! [SINGLE](SINGLE) or [DOUBLE](DOUBLE) values are used by the function. EX:**Pi = 4 * ATN(1)**
## Description
* To convert from radians to degrees, multiply radians * (180 / <20>).
* The *tangent* value would be equal to the tangent value of an angle. Ex: **[TAN](TAN)(ATN(1)) = 1**
* The function return value is between -<2D> / 2 and <20> / 2.
## Example(s)
When the [TAN](TAN)gent value equals 1, the line is drawn at a 45 degree angle (.7853982 radians) where [SIN](SIN) / [COS](COS) = 1.
```vb
SCREEN 12
x = 100 * COS(ATN(1))
y = 100 * SIN(ATN(1))
LINE (200, 200)-(200 + x, 200 + y)
```
[ATN](ATN) can be used to define &pi; in [SINGLE](SINGLE) or [DOUBLE](DOUBLE) precision. The calculation cannot be used as a [CONST](CONST)ant.
```vb
Pi = 4 * ATN(1) 'SINGLE precision
Pi# = 4 * ATN(1#) 'DOUBLE precision
PRINT Pi, Pi#
```
> *Note:* You can use QB64's native [_PI](_PI) function.
Finds the angle from the center point to the mouse pointer.
```vb
SCREEN _NEWIMAGE(640, 480, 32)
x1! = 320
y1! = 240
DO
PRESET (x1!, y1!), _RGB(255, 255, 255)
dummy% = _MOUSEINPUT
x2! = _MOUSEX
y2! = _MOUSEY
LINE (x1, y1)-(x2, y2), _RGB(255, 0, 0)
LOCATE 1, 1: PRINT getangle(x1!, y1!, x2!, y2!)
_DISPLAY
_LIMIT 200
CLS
LOOP UNTIL INKEY$ <> ""
END
FUNCTION getangle# (x1#, y1#, x2#, y2#) 'returns 0-359.99...
IF y2# = y1# THEN
IF x1# = x2# THEN EXIT FUNCTION
IF x2# > x1# THEN getangle# = 90 ELSE getangle# = 270
EXIT FUNCTION
END IF
IF x2# = x1# THEN
IF y2# > y1# THEN getangle# = 180
EXIT FUNCTION
END IF
IF y2# < y1# THEN
IF x2# > x1# THEN
getangle# = ATN((x2# - x1#) / (y2# - y1#)) * -57.2957795131
ELSE
getangle# = ATN((x2# - x1#) / (y2# - y1#)) * -57.2957795131 + 360
END IF
ELSE
getangle# = ATN((x2# - x1#) / (y2# - y1#)) * -57.2957795131 + 180
END IF
END FUNCTION
```
## See Also
* [_PI](_PI) (QB64 function)
* [TAN](TAN) (tangent function)
* [SIN](SIN), [COS](COS)
* [Mathematical Operations](Mathematical-Operations)
* [Mathematical Operations](Mathematical-Operations)

View file

@ -0,0 +1,75 @@
**Circle.BI Include file or [SUB](SUB) to use when using [PAINT](PAINT) with pie charts or arc slices:**
```vb
'CIRCLE.BI
'**
'** QB64 replacement CIRCLE command.
'**
'** The CIRCLE command in QB64 has a few issues:
'**
'** - radian end points are not calculate properly when creating arcs
'** - center line to radian end points do not close properly due to previous bug listed
'**
'** This circle command replacement works very similiarly to the native CIRCLE command:
'**
'** SYNTAX: CIRCLES x%, y%, radius!, color~&, start_radian!, end_radian!, aspect_ratio!
'**
'** x% - center X coordinate of circle
'** y% - center Y coordinate of circle
'** radius! - the radius of the circle
'** color~& - the circle's color
'** start_radian! - the radian on circle curcunference to begin drawing at
'** end_radian! - the radian on circle circumference to end drawing at
'** aspect_ratio! - the aspect ratio of the circle
'**
'** **NOTE: unlike the native CIRCLE command, all arguments MUST be supplied.** For example,
'** with the native command this will draw a perfect circle with the default color,
'** start radian, end radian and aspect ratio:
'**
'** CIRCLE (319, 239), 100
'**
'** To do the same thing with this replacement command you must supply everything:
'**
'** CIRCLES 319, 239, 100, _RGB32(255, 255, 255), 0, 0, 0
'**
'** ACKNOWLEGEMENTS: The FOR/NEXT step formula was was written by Codeguy for Unseen
'** Machine's Visual library EllipseXS command. Specifically:
'** MinStep! = 1 / (2 * 3.1415926535 * Radius!)
'**
'**
'** Includes performance tweaks made by SMcNeill on 02/02/13 - specifically removing a few redundant * -1
'** statements and converting the FOR/NEXT loop to a DO loop for a ~3% increase in performance.
'**
'** Corrected bug in which variables being passed in were being modified and passed back - 02/02/13
'**
**SUB CIRCLES (cx%, cy%, r!, c~&, s!, e!, a!)**
DIM s%, e%, nx%, ny%, xr!, yr!, st!, en!, asp! ' local variables used
st! = s! ' copy start radian to local variable
en! = e! ' copy end radian to local variable
asp! = a! ' copy aspect ratio to local variable
IF asp! <= 0 THEN asp! = 1 ' keep aspect ratio between 0 and 4
IF asp! > 4 THEN asp! = 4
IF asp! < 1 THEN xr! = r! * asp! * 4 ELSE xr! = r! ' calculate x/y radius based on aspect ratio
IF asp! > 1 THEN yr! = r! * asp! ELSE yr! = r!
IF st! < 0 THEN s% = -1: st! = -st! ' remember if line needs drawn from center to start radian
IF en! < 0 THEN e% = -1: en! = -en! ' remember if line needs drawn from center to end radian
IF s% THEN ' draw line from center to start radian?
nx% = cx% + xr! * COS(st!) ' yes, compute starting point on circle's circumference
ny% = cy% + yr! * -SIN(st!)
LINE (cx%, cy%)-(nx%, ny%), c~& ' draw line from center to radian
END IF
IF en! <= st! THEN en! = en! + 6.2831852 ' come back around to proper location (draw counterclockwise)
stepp! = 0.159154945806 / r!
c! = st! ' cycle from start radian to end radian
DO
nx% = cx% + xr! * COS(c!) ' compute next point on circle's circumfrerence
ny% = cy% + yr! * -SIN(c!)
PSET (nx%, ny%), c~& ' draw the point
c! = c! + stepp!
LOOP UNTIL c! >= en!
IF e% THEN LINE -(cx%, cy%), c~& ' draw line from center to end radian if needed
**END SUB**
```

32
wiki/Apostrophe.md Normal file
View file

@ -0,0 +1,32 @@
The **apostrophe** allows explanatory comments, or remarks, to be inserted in a program. These may be included anywhere in the source code and extend to the end of the line. Comments are ignored when the program is run.
## Syntax
> [apostrophe](apostrophe) this is a comment
> [REM](REM) this is also a comment
## Description
* [REM](REM) can also be used to insert comments but may only be used as the last, or only, statement on a line.
* QBasic [metacommand](metacommand)s like [$INCLUDE]($INCLUDE) must be included in a comment using either [REM](REM) or [apostrophe](apostrophe).
* [Apostrophe](Apostrophe) comments, unavailable in earlier dialects of the BASIC language, are now generally favored over [REM](REM) statements for their greater flexibility.
* Comments are also useful for disabling code for program testing and debugging purposes.
## Example(s)
```vb
COLOR 11: PRINT "Print this...." ' PRINT "Don't print this program comment!"
```
```text
Print this....
```
## See Also
* [REM](REM)
* [$DYNAMIC]($DYNAMIC), [$STATIC]($STATIC), [$INCLUDE]($INCLUDE)

36
wiki/Argument.md Normal file
View file

@ -0,0 +1,36 @@
An **argument** or parameter is information that a [statement](statement), [sub (explanatory)](sub-(explanatory)), [function (explanatory)](function-(explanatory)) or [metacommand](metacommand) needs to carry out the task it has been given. Sometimes a argument can be optional and is not needed for the task to be carried out, in such case it will use a default instead of the argument when carrying out the task.
It is currently not possible to make arguments optional in user-defined [SUB](SUB)s or [FUNCTION](FUNCTION)s, but Galleon (the creator of QB64) is planning that functionality in the future.
Arguments that are optional will be enclosed with [ and ] brackets in syntax descriptions.
More than one argument or parameter are separated by commas.
## Example(s)
The color argument in PSET is optional
```vb
SCREEN 13
PSET (160, 100)
PSET (165, 100), 15
```
Must place a comma to seperate arguments if you use any other argument after it.
```vb
SCREEN 13
LINE (160, 100)-(170, 110), , B
LINE (162, 102)-(168, 108), 4, BF
```
As you can see in the above example some statements have special arguments like B and BF in this case (B stands for Box and BF stands for Box Fill), if the argument isn't used then it will create a ordinary line.
## See Also
* [SUB](SUB), [FUNCTION](FUNCTION)
* [Statement](Statement), [Function (explanatory)](Function-(explanatory)), [Sub (explanatory)](Sub-(explanatory)), [Metacommand](Metacommand), [Expression](Expression)

289
wiki/Arrays.md Normal file
View file

@ -0,0 +1,289 @@
### What are Arrays?
Arrays are simply variables with a number of elements that can each hold data in memory. To designate a certain element, integers denote the value's position in memory. Don't let talk about memory scare you! Basic does all of the work for you just by using the simple commands in this tutorial. Besides that, you have already been using memory since you created your first variable!
Arrays can store element bytes of information like any other variable depending on the type of the variable. The total memory bytes used by an array type can be determined using the table below multiplied by the number of array elements:
Standard QBasic/QuickBASIC types:
* [STRING](STRING) = 1 byte per character
* [INTEGER](INTEGER) = 2 bytes (signed Integer values from -32768 to 32767)
* [LONG](LONG) = 4 bytes (signed Integer values from -2147483648 to 2147483647)
* [SINGLE](SINGLE) = 4 bytes (up to 7 digit floating decimal point values)
* [DOUBLE](DOUBLE) = 8 bytes (up to 15 digit floating point values)
New types introduced by QB64
* [_BIT](_BIT) * 8 = 1 byte(signed Integer values of -1 or 0)
* [_BYTE](_BYTE) = 1 byte (signed Integer values from -128 to 127)
* [_INTEGER64](_INTEGER64) = 8 bytes (signed values from -9223372036854775808 to 9223372036854775807
* [_FLOAT](_FLOAT) = 10 bytes (better than Double accuracy)
While QBasic uses signed values **QB64** can use signed or [_UNSIGNED](_UNSIGNED) values for [_BIT](_BIT), [_BYTE](_BYTE), [INTEGER](INTEGER), [LONG](LONG) or [_INTEGER64](_INTEGER64) variable type values.
The array's variable type must be determined when the array is created. If no type is used, the default type is [SINGLE](SINGLE).
### When do I need an Array?
**When you find yourself creating several variables with numbers in their names.** This may seem simplistic, but normally programmers tend to use similar names to denote similar value types. This makes arrays perfect in many cases. You can get several values of the same type simply by referring to the element positions in an array. Plus you can have thousands of possibilities when needed.
Arrays can be created to hold values until they are needed. They can hold image or file data too! There are many possible uses!
The only drawback is that the data is lost when the program ends, but array data can be permanently stored in files when you want to save the data. All that you need is a simple loop to transfer the data sequencially or save the entire array to a [BINARY](BINARY) file using **QB64** with a simple [PUT](PUT) statement. You also can retrieve the array data using one [GET](GET).
### Creating Array Variables
First we need to create a place in memory for the array. To do that we have to tell Basic the array's name, type of values it will hold and how many values we need to access. This is called dimensioning an array.
How good are you at counting from zero? This might seem like a simple question, but think about this. How many elements would we have if they were numbered 0 through 10? If you said 11, then you were correct. Some people have problems counting when 0 is involved so Basic has an option to allow all arrays to start at 1.
[OPTION BASE](OPTION-BASE) 1 will cause all array dimensions to begin at 1, [OPTION BASE](OPTION-BASE) 0 will cause all dimensions to begin at 0. The default when just using the maximum array size is 0. Use whatever option you are comfortable with.
Arrays in QuickBASIC 4.5 and QBasic are limited to 32767 elements, while arrays in **QB64** are limited to 2147483647 elements (over 2 billion). When the 64-bit version of QB64 is implemented 9223372036854775807 elements will be the limit (but only on 64-bit systems).
[DIM](DIM) reserves the array's name, variable type and number of elements in memory before the array is used. DIM reserves a [STATIC](STATIC) (unchangeable) array unless the [$DYNAMIC]($DYNAMIC) (changeable) metacommand is used at the program's start or [REDIM](REDIM) was used to dimension the array originally.
Dimensions an array named 'Array' that is capable of holding 101 integer values including element 0.
```vb
DIM Array(100) AS INTEGER
```
An array starts at element 0 unless changed by [OPTION BASE](OPTION-BASE) 1 (which can set the start at 1), you can also define the start and end area by [DIM](DIM)ensioning within a range.
[DIM](DIM)ensioning with a range is possible also by using TO between the minimum and highest elements. Arrays can start and end at any element(index) value up to 32767. **QB64** allows larger array sizes!
dimensions an Integer array that can hold 100 values in indices 1 to 100.
```vb
DIM Array%(1 TO 100)
```
*Note:* The array type can also be designated by variable suffixes as % designates Integers above.
[REDIM](REDIM) can be used to redimension a dynamic array. Any information contained in the array before the REDIM will be lost...however. In order to use [REDIM](REDIM), the variable must have originally been dimensioned using [REDIM](REDIM), or a [$DYNAMIC]($DYNAMIC) metacommand must be placed at the top of the program.
*Example 3:*
```vb
OPTION BASE 1 ' placed before any arrays are dimensioned
REDIM Array$(1000) ' REDIM creates a dynamic array
```
**QB64** has a REDIM [_PRESERVE](_PRESERVE) action which can be used in a REDIM statement in order to preserve the data information in the array.
REDIM without the _PRESERVE action erases the array contents
```vb
REM $DYNAMIC
DIM array(20)
array(10) = 24
PRINT array(10)
REDIM _PRESERVE array(30)
PRINT array(10)
REDIM array(10)
PRINT array(10)
```
```text
24
24
0
```
[_PRESERVE](_PRESERVE) also allows the lowest index to be changed. The old starting index data value will always be in the lowest new index when the index range limits are changed.
Changing the starting index number using the [_PRESERVE](_PRESERVE) action moves the data.
```vb
REDIM Array$(1 TO 50)
Array$(1) = "I'm number one!"
Array$(50) = "I'm 50..."
REDIM _PRESERVE Array$(51 TO 100)
PRINT Array$(51) ' display new start index data
PRINT Array$(100) ' display new end data
```
```text
I'm number one!
I'm 50...
```
The memory segment address of the array is defined in [DEF SEG](DEF-SEG).
```vb
DEF SEG = VARSEG(array(0))
offset = VARPTR(array(0)) 'program designated offset element
```
NOTE: If [OPTION BASE](OPTION-BASE) 1 is used change the 0 to 1. The array start index can be changed when some other data is indexed in the array.
### Multi-Dimensional Arrays
Multiple dimensions are possible to create tables of values. QuickBASIC can use up to 60 dimensions. In **QB64** the number of dimensions possible depends on your system memory (a lot more than 60 dimensions). Array data can be saved and restored using file data.
**Otherwise the data is lost when a program closes.**
```text
** TWO DIMENSIONAL ARRAY TABLES**
Setting up a car sales Database: The sales for each month as represented in an array.
DIM Vehicle%(12, 4) ' Vehicle%(month%, type%)
Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec
** 1 2 3 4 5 6 7 8 9 10 11 12 ← Month index**
**Type index ↓** -----------------------------------------------
Cars **1:** 5 10 15 20 30 19 17 12 24 20 33 30
Trucks **2:** 3 8 7 10 15 9 11 8 15 10 16 11
Vans **3:** 4 6 8 9 7 10 9 7 9 8 10 7
SUV **4:** 10 8 8 5 10 8 6 8 10 11 9 8
To find monthly and yearly totals you could do something like this:
FOR month% = 1 TO 12
FOR type% = 1 TO 4
MonthlySales% = MonthlySales% + Vehicle%(month%, type%)
NEXT
YearlySales% = YearlySales% + MonthlySales%
PRINT "Monthly =", MonthlySales%; " Yearly ="; YearlySales%; " "
INPUT$(1) 'stop to view each month
MonthlySales% = 0 'zero month sales for next months total
NEXT
```
Creating a two-dimensional array. A comma separates each dimension size.
```vb
DIM Array(12, 10) ' 2 dimensions can hold 143 data values
```
One dimension could hold the month number and the other the number of items sold in 10 categories.
Dimensioning using index ranges.
```vb
DIM Array(1 TO 12, 1 TO 10) ' 2 dimensions can hold 120 data values
```
### Working with the Array Elements
Once an array is created, you have to put something in it. As you may have noticed, each element or index has an integer value associated with it. Array(number%) refers to just one element of the array no matter what type it is. **Arrays CAN have negative numbered elements!**
You can place data into an array using several methods. The slowest method is directly placing data from the user. You can even use the array as the [INPUT](INPUT) variable. It is recommended that ANY program user entries be limited to text as INPUT will give Redo from start errors if a user enters a string value when a numerical input was desired. Numerical string data can be converted from strings simply by using [VAL](VAL). This creates less user errors! NOTE: **QB64** does not return a "Redo from start" error as [INPUT](INPUT) monitors entries.
```vb
DO
INPUT "Enter your age: ", howold$
age% = VAL(howold$)
LOOP UNTIL age% > 0
Playerage%(user%) = age% 'saves the players age to an indexed player number
PRINT Playerage%(user%) 'print array element to screen to verify entry
user% = user% + 1 'increment user number when all data has been entered
```
You could use several arrays to hold the player's name, high scores, etc. Once the data is in the array, it can be used until the program ends. Then the data is lost, but you can store the data to a file before closing the program simply by using a loop. See next section.
**To pass array data to a [SUB](SUB) or [FUNCTION](FUNCTION) parameter, an empty element bracket passes all elements while a number only passes one specified element of the array.**
### Array Indexing
Arrays can be set up to hold more than one kind of data, by indexing the two or more kinds of data. To do this, the programmer reserves one set of element or index values for each kind of data. The type of values MUST be the same except when using a [TYPE](TYPE) definition value.
### Sorting Array Data
Arrays can be sorted numerically or alphabetically using various sorting routines. Commonly [SWAP](SWAP) is used to trade element values in descending or ascending order.
### Saving Array Data
Since variables and arrays exist in memory, data is lost when a program closes. To preserve program data you must either create a permanent [DATA](DATA) field or save the data to files.
The next time a program is used, it can [OPEN](OPEN) that file and quickly restore all of the array data using a loop or **QB64** can [GET](GET) the entire file's data in one GET. Use [LINE INPUT (file statement)](LINE-INPUT-(file-statement)) # to set the array sizes by counting the number of data rows in a file if you used a [WRITE](WRITE) **CSV**(comma separated values) or a [PRINT (file statement)](PRINT-(file-statement)) # sequencial file. The number of records in a [TYPE](TYPE) or [FIELD](FIELD) defined [RANDOM](RANDOM) access file can be found by dividing the record size into the [LOF](LOF). You may want to make the array slightly larger for new entries.
### Image Arrays
[INTEGER](INTEGER) arrays are used to hold image information when using the following graphic procedures: [GET (graphics statement)](GET-(graphics-statement)), [PUT (graphics statement)](PUT-(graphics-statement)), [BSAVE](BSAVE) and [BLOAD](BLOAD).
The [INTEGER](INTEGER) array size can be estimated by multiplying the height by the width of the image area. To find the actual size needed you can use the following routine to count backwards until something is found in the array. The example below returns the array size required to create a 20 by 20 image:
```vb
wide& = 20: deep& = 20 'change the sizes for any image area
DIM array(wide& * deep&) AS INTEGER
LINE (0, 0)-(wide& - 1, deep& - 1), 12, B 'the box border is all that you need to color.
GET (0, 0)-(wide& - 1, deep& - 1), array(0)
FOR s& = wide& * deep& TO 0 STEP -1
IF array(s&) THEN arraysize& = s&: EXIT FOR
NEXT
PRINT arraysize&
END
```
**Note: QB64 can [GET (graphics statement)](GET-(graphics-statement)) the entire SCREEN 12 area into one array!**
See also: [Creating Sprite Masks](Creating-Sprite-Masks)
### SHARED Arrays
When array data is used with [SUB](SUB) or [FUNCTION](FUNCTION) procedures they can be passed as parameters. When passed as parameters, a specific index or the entire array can be used. To specify an index, the array is passed with the element number. If the entire array is passed, the element brackets should be empty. Example: **SUB SubName (ArrayName() AS INTEGER)**
Arrays can also be [SHARED](SHARED) by all procedures by using [DIM](DIM) [SHARED](SHARED) when the array is created. This allows the array data to be used in the main procedure and all sub-procedures.
[COMMON](COMMON) allows Array data to be shared between program modules when used with [CHAIN](CHAIN). The two modules can share any variable values in a list of variables. The lists can use different variable names, but the types of values MUST be listed in the SAME order in both modules.
[COMMON SHARED](COMMON_SHARED) allows data to be shared between both modules and SUB or FUNCTION procedures.
Arrays can be created inside of [SUB](SUB) or [FUNCTION](FUNCTION) procedures by using [DIM](DIM) or [REDIM](REDIM). Also [SHARED](SHARED)(without DIM) can be used inside of a sub-procedure to share variable data with the Main program module ONLY. Other sub-procedures cannot reference the data. To share array data with other sub-procedures, array FUNCTIONS can be created that use the internal array elements as a parameter. **QB64 may allow sub-procedures to share values with other procedures soon!**
Arrays can be set as [STATIC](STATIC) to retain the values when a sub-procedure is exited. The values will be retained until changed inside of the procedure. If the procedure creates it's own array, you can use a STATIC True or False variable to determine when to [DIM](DIM) or [REDIM](REDIM) a STATIC array so that values are not lost every call. The *Ready%* variable below DIMs the array when the function is first used:
```vb
FUNCTION ScanKey% (scancode%)
STATIC Ready%, keyflags%()
IF NOT Ready% THEN REDIM keyflags%(0 TO 127): Ready% = -1
i% = INP(&H60) 'read keyboard states
IF (i% AND 128) THEN keyflags%(i% XOR 128) = 0
IF (i% AND 128) = 0 THEN keyflags%(i%) = -1
K$ = INKEY$
ScanKey% = keyflags%(scancode%)
IF scancode% = 0 THEN Ready% = 0 'allows program to reset all values to 0 with a REDIM
END FUNCTION
```
> *Explanation:* The STATIC *Ready%* value is always 0 when a procedure is first run. [NOT](NOT) zero makes the IF statement True so the array is created. The *Ready%* value is then changed to anything but zero to make NOT *Ready%* False when the procedure is called again. The FUNCTION is referenced just like an array would be. The value it returns is either 0 or -1 to verify that a certain key was released or pressed respectively. The keyboard status is also updated in the array each call. If the *scancode%* sent is 0(a key scan code that does not exist), the array is reset(re-dimensioned) on the next call as *Ready%* is reset to zero.
### Preserving Data
[_PRESERVE](_PRESERVE) can preserve data when [REDIM](REDIM) or [$DYNAMIC]($DYNAMIC) is used to create dynamic arrays. The current array data can be preserved while changing the array element size. Increasing the size will preserve data inside of existing indices in the resized array. If the size is decreased, only the existing indices values will be preserved. **The array [TYPE](TYPE) and number of array dimensions cannot be changed!**
**REDIM _PRESERVE ArrayName(1 TO 100)**

21
wiki/BEEP.md Normal file
View file

@ -0,0 +1,21 @@
The [BEEP](BEEP) statement produces a beep sound through the sound card.
## Syntax
> [BEEP](BEEP)
## Description
* [BEEP](BEEP) can be placed anywhere to alert the user that there is something to do or an error has occurred.
* **QB64** produces the actual "beep" sound through the PC's sound card, to emulate QBasic's beeping through the [PC speaker](https://en.wikipedia.org/wiki/PC_speaker).
## QBasic
* Older programs may attempt to produce a BEEP by printing [CHR$](CHR$)(7) to the screen. This is no longer supported in QB64 after **version 1.000**.
* You may have to replace instances of PRINT CHR$(7) in older programs to the [BEEP](BEEP) statement to maintain the legacy functionality.
## See Also
* [SOUND](SOUND), [PLAY](PLAY)
* [_SNDPLAY](_SNDPLAY) (play sound files)
* [_SNDRAW](_SNDRAW) (play frequency waves)

87
wiki/BINARY.md Normal file
View file

@ -0,0 +1,87 @@
See [OPEN](OPEN).
[BINARY](BINARY) is used in an [OPEN](OPEN) statement to work with the file or port device manipulating its bytes directly.
## Syntax
> [OPEN](OPEN) fileName$ [FOR](FOR) [BINARY](BINARY) [AS](AS) #fileNumber%
## Description
* [OPEN](OPEN) FOR BINARY creates the file if the fileName$ does not exist.
* fileName$ is the name of the file to open, but could also configure a port.
* #fileNumber% is the number that will represent the file when performing file operations.
* BINARY files use [GET](GET) and [PUT](PUT) to read or write the file at any byte position.
* In **version 1.000 and up** you can use [LINE INPUT](LINE-INPUT) in [BINARY](BINARY) mode for faster access to text file data.
* QBasic's [BSAVE](BSAVE) or BINARY save files can be read using BINARY mode.
* BINARY mode ignores any [LEN](LEN) = recordlength statement in the [OPEN](OPEN) statement.
* Ports can also be opened in [BINARY](BINARY) mode. See: [OPEN COM](OPEN-COM)
## Example(s)
Shows how a PUT variable value is converted to an [ASCII](ASCII) string [_MK$](_MK$) format in a BINARY file.
```vb
DIM int64 AS _INTEGER64
DIM byte8 AS STRING * 8
int64 = 12345678
PRINT int64
OPEN "temp64.tmp" FOR BINARY AS #1
PUT #1, , int64 'the file size will be 8 bytes
CLOSE
PRINT "Press a key to read the file!"
K$ = INPUT$(1)
OPEN "temp64.tmp" FOR BINARY AS #1
GET #1, , byte8 'GET the value as a string
PRINT "text string: "; byte8 'show that string is in _MK$ format
PRINT _CV(_INTEGER64, byte8) 'convert to numerical value
CLOSE
```
> *Note:* The numerical value does not need to be converted if the file is read using the same numerical variable type as written.
A binary file viewer that can view integer values. The type of value can be changed at [DIM](DIM).
```vb
SCREEN _NEWIMAGE(1000, 600, 256)
_SCREENMOVE _MIDDLE
DIM value AS INTEGER 'value type can be changed
LINE INPUT ; "Enter a BINARY filename to open: ", file$
PRINT " Press S to restart!"
IF LEN(file$) THEN OPEN file$ FOR BINARY AS #1 ELSE END
IF LOF(1) = 0 THEN PRINT "Empty file!": END
DO
FOR i = 1 TO 16
x = x + 1
GET #1, , value
IF EOF(1) THEN EXIT DO
PRINT value;
NEXT
PRINT CHR$(27); x; "@"; row
K$ = INPUT$(1)
IF UCASE$(K$) = "S" THEN CLS: x = 0: row = 0: PRINT "Restarted!": SEEK 1, 1
IF x = 256 THEN x = 0: row = row + 1: PRINT
LOOP UNTIL K$ = CHR$(27)
CLOSE #1
PRINT "Press Escape to exit!"
DO: _LIMIT 100
LOOP UNTIL INKEY$ = CHR$(27)
SYSTEM
```
## See Also
* [OPEN](OPEN), [CLOSE](CLOSE)
* [GET](GET), [PUT](PUT), [LINE INPUT](LINE-INPUT)
* [SEEK](SEEK) (function), [SEEK (statement)](SEEK-(statement))
* [INPUT (file mode)](INPUT-(file-mode)), [RANDOM](RANDOM), [APPEND](APPEND), [OUTPUT](OUTPUT)
* [Bitmaps](Bitmaps), [Binary](Binary) (numbers)

60
wiki/BLOAD.md Normal file
View file

@ -0,0 +1,60 @@
[BLOAD](BLOAD) loads a binary graphics file created by [BSAVE](BSAVE) to an array.
## Legacy Support
* **QB64 can load larger arrays directly from binary files using [PUT](PUT) # and [GET](GET) # without BLOAD. For that reason, BLOAD isn't recommended practice anymore and is supported to maintain compatibility with legacy code.**
## Syntax
> [BLOAD](BLOAD) fileName$, [VARPTR](VARPTR)(imageArray%(Parameter))
## Parameter(s)
* fileName$ is the name of the file that the image should be [BSAVE](BSAVE)d to.
* imageArray%(index) is the [INTEGER](INTEGER) [arrays](arrays) start index to store the image loaded.
## Description
* There must be an [INTEGER](INTEGER) array of adequate size (up to 26K) to hold the graphic data.
* A [DEF SEG](DEF-SEG) pointing to the array is required. [DEF SEG](DEF-SEG) = [VARSEG](VARSEG)(imageArray%(index))
* index is the starting image element of the Array. Can also include RGB color settings at the start index.
* Fullscreen images in [SCREEN](SCREEN) 12 require 3 file BLOADs. A 26K array can hold 1/3 of screen.
* Custom RGB color settings can be embedded(indexed) at the start of the image array.
* BLOAD can be used to load any array that was saved with [BSAVE](BSAVE), not just graphics.
* Array sizes are limited to 32767 Integer elements due to use of [VARPTR](VARPTR) in QBasic and **QB64**'s emulated conventional memory.
## Example(s)
Loading data to an array from a BSAVED file.
```vb
DEF SEG = VARSEG(Array(0))
BLOAD filename$, VARPTR(Array(LBOUND(Array))) ' changeable index
DEF SEG
```
> *Explanation:* Referance any type of array that matches the data saved. Can work with Integer, Single, Double, Long, fixed length Strings or [TYPE](TYPE) arrays. [LBOUND](LBOUND) determines the starting offset of the array or another index could be used.
Using a QB default colored image.
```vb
DEF SEG = VARSEG(Image%(0)) ' pointer to first image element of an array
BLOAD FileName$, VARPTR(Image%(0)) ' place data into array at index position 0
PUT(Col, Row), Image%(0), PSET ' Put the image on the screen from index 0
DEF SEG
```
> *Note:* [PSET](PSET) is used as a [PUT (graphics statement)](PUT-(graphics-statement)) action that places the image over any background objects.
## See Also
* [BSAVE](BSAVE), [OPEN](OPEN), [BINARY](BINARY)
* [PUT](PUT), [GET](GET) (file statement)
* [GET (graphics statement)](GET-(graphics-statement)), [PUT (graphics statement)](PUT-(graphics-statement))
* [VARSEG](VARSEG), [VARPTR](VARPTR)
* [DEF SEG](DEF-SEG)
* [Text Using Graphics](Text-Using-Graphics)

110
wiki/BSAVE.md Normal file
View file

@ -0,0 +1,110 @@
[BSAVE](BSAVE) saves the contents of an image array to a [BINARY](BINARY) file.
## Legacy Support
* QB64 can save larger arrays directly to binary files using [PUT](PUT) # and [GET](GET) # without [BSAVE](BSAVE). For that reason, use of [BSAVE](BSAVE) is no longer recommended practice but is supported to maintain compatibility with legacy code.
## Syntax
> [BSAVE](BSAVE) saveFile$, [VARPTR](VARPTR)(array(index)), fileSize&
## Parameter(s)
* saveFile$ is the STRING file name of the file designated to be created.
* array(index) is the image [arrays](arrays) that already holds the [GET (graphics statement)](GET-(graphics-statement)) image data.
* fileSize& must be a bit over twice the size of the elements used in an [INTEGER](INTEGER) [Arrays](Arrays).
## Description
* To place image data into the array, use [GET (graphics statement)](GET-(graphics-statement)) to store a box area image of the screen.
* [SCREEN](SCREEN) 12 can only GET 1/3 of the screen image at one time using a 26K array.
* Image arrays are [DIM](DIM)ensioned as [INTEGER](INTEGER). Use [DEFINT](DEFINT) when working with large graphic arrays.
* Any arrays can be saved, but image arrays are most common.
* [DEF SEG](DEF-SEG) = [VARSEG](VARSEG) must be used to designate the array segment position in memory.
* [VARPTR](VARPTR) returns the array index offset of the memory segment. Array sizes are limited to 32767 Integer elements due to the use of [VARPTR](VARPTR) in QBasic and **QB64**'s emulated conventional memory.
* [BSAVE](BSAVE) files can later be opened with [BLOAD](BLOAD).
## Example(s)
Saving array data to a file quickly.
```vb
LB% = LBOUND(Array)
bytes% = LEN(Array(LB%))
filesize& = ((UBOUND(Array) - LB%) + 1) * bytes%
DEF SEG = VARSEG(Array(0))
BSAVE filename$, VARPTR(Array(LB%)), filesize& ' changeable index
DEF SEG
```
> *Explanation:* Procedure determines the filesize from the array size automatically. [LBOUND](LBOUND) is used with [UBOUND](UBOUND) to determine array size and byte size. Works with any type of array except variable-length strings. Used for saving program data fast.
[BSAVE](BSAVE)ing a bitmap and calculating the file size
```vb
DEF SEG = VARSEG(Image(0))
PSET(BMPHead.PWidth - 1, BMPHead.PDepth - 1) 'color lower right corner if black
GET (0, 0)-(BMPHead.PWidth - 1, BMPHead.PDepth - 1), Image(NColors * 3) ' for 16 or 256 colors
FOR a& = 26000 TO 0 STEP -1
IF Image(a&) THEN ArraySize& = a&: EXIT FOR
NEXT
BSAVE SaveName$, VARPTR(Image(0)), (2 * ArraySize&) + 200 'file size
DEF SEG
```
> *Explanation:* The [FOR...NEXT](FOR...NEXT) loop reads backwards through the image array until it finds a value not 0. The [LONG](LONG) ArraySize& value is doubled and 200 is added. BMPhead.PWidth and BMPhead.PDepth are found by reading the bitmap's information header using a [TYPE](TYPE) definition. See [Bitmaps](Bitmaps).
Using [PUT](PUT) and [GET](GET) to write and read array data from a file without using BSAVE or [BLOAD](BLOAD):
```vb
KILL "example2.BIN" 'removes old image file!
SCREEN 13
OPTION BASE 0
REDIM Graphic%(1001) 'REDIM makes array resize-able later
LINE (0, 0)-(10, 10), 12, B 'create image
GET(0, 0)-STEP(10, 10), Graphic%() 'get image to array
FOR i% = 1000 TO 0 STEP -1 'reverse read array for size needed
IF Graphic%(i%) <> 0 THEN EXIT FOR 'find image color not black
NEXT
size% = i% + 4 'size plus 2 integers(4 bytes) for dimensions
REDIM _PRESERVE Graphic%(size%) 'resize existing array in QB64 only!
OPEN "example2.BIN" FOR BINARY AS #1 ' PUT to a file
PUT #1, , Graphic%()
CLOSE
OPEN "example2.BIN" FOR BINARY AS #2 'GET array and PUT to screen
DIM CopyBin%(LOF(2) \ 2) 'create new array sized by half of file size
GET #2, , CopyBin%()
PUT(100, 100), CopyBin%(), PSET
fsize% = LOF(2)
CLOSE
K$ = INPUT$(1) 'Press any key
FOR i = 0 TO 20 'read all 3 arrays
PRINT Graphic%(i); CopyBin%(i)
NEXT
PRINT "Array:"; size%, "File:"; fsize%
```
> *Explanation:* A 10 by 10 pixel box is saved to an array using the [GET (graphics statement)](GET-(graphics-statement)) and written to a BINARY file using [PUT](PUT) #1. Then [GET](GET) #1 places the file contents into another INTEGER array and places it on the screen with the [PUT (graphics statement)](PUT-(graphics-statement)).
> The array contents: 88 is the width in the GET array for [SCREEN](SCREEN) 13 which needs divided by 8 in that mode only. The area is actually 11 X 11. The array size needed can be found by looping backwards through the array until a color value is found. **IF array(i) <> 0 THEN EXIT FOR** (66 integers) or by dividing the created BINARY file size in half (134 bytes) when known to be array sized already.
## See Also
* [GET (graphics statement)](GET-(graphics-statement)), [PUT (graphics statement)](PUT-(graphics-statement))
* [BLOAD](BLOAD), [OPEN](OPEN), [BINARY](BINARY)
* [GET](GET), [PUT](PUT) (file statements)
* [VARSEG](VARSEG), [VARPTR](VARPTR)
* [DEF SEG](DEF-SEG), [TYPE](TYPE)
* [Text Using Graphics](Text-Using-Graphics)

1
wiki/BYVAL.md Normal file
View file

@ -0,0 +1 @@
See [DECLARE LIBRARY](DECLARE-LIBRARY).

47
wiki/Base-Comparisons.md Normal file
View file

@ -0,0 +1,47 @@
```text
**Comparing the Base Numbering Systems**
**Decimal (base 10) Binary (base 2) Hexadecimal (base 16) Octal (base 8)**
0 0000 0 0
1 0001 1 1
2 0010 2 2
3 0011 3 3
4 0100 4 4
5 0101 5 5
6 0110 6 6
7 0111 7 7 -- maxed
8 1000 8 10
maxed-- 9 1001 9 11
10 1010 A 12
11 1011 B 13
12 1100 C 14
13 1101 D 15
14 1110 E 16
15 ------------- 1111 <--- Match ---> F ---------------- 17 -- max 2
16 10000 10 20
When the Decimal value is 15, the other 2 base systems are all maxed out!
The Binary values can be compared to all of the HEX value digit values so
it is possible to convert between the two quite easily. To convert a HEX
value to Binary just add the 4 binary digits for each HEX digit place so:
F A C E
&HFACE = 1111 + 1010 + 1100 + 1101 = &B1111101011001101
To convert a Binary value to HEX you just need to divide the number into
sections of four digits starting from the right(LSB) end. If one has less
than 4 digits on the left end you could add the leading zeros like below:
&B101011100010001001 = 0010 1011 1000 1000 1001
hexadecimal = 2 + B + 8 + 8 + 9 = &H2B889
See the Decimal to Binary conversion function that uses **[HEX$](HEX$)** on the **[&H](&H)** page.
```
## See Also
* [HEX$](HEX$), [OCT$](OCT$), [VAL](VAL)
* [&H](&H) (hexadecimal), [&O](&O) (octal), [&B](&B) (binary)

369
wiki/Bitmaps.md Normal file
View file

@ -0,0 +1,369 @@
**Bitmaps** are image files with the .BMP file name extension.
* Bitmaps can use 1, 4, 8 or 24/32 bits per pixel(BPP) color palettes.
* Unlike QBasic, QB64 is capable of working with 24 bit per pixel color(16 million) bitmaps and can create 32 bit screens to use them with the [_NEWIMAGE](_NEWIMAGE) function.
* Text SCREEN mode 0 cannot be screen saved in QBasic or QB64.
* The structure of the Bitmap header can be placed in a [TYPE](TYPE) definition as below. This information can be used to find out the bitmap's **Width** and **Height** dimensions, **Bits Per Pixel** used and the **offset** of the actual image pixel data.
* It should be noted that **QB64's** [_LOADIMAGE](_LOADIMAGE) function can load bitmaps and other type of images directly into a program and be placed simply by using [_PUTIMAGE](_PUTIMAGE). [_NEWIMAGE](_NEWIMAGE) can create 256 or 32 bit [SCREEN (statement)](SCREEN-(statement)) modes to display those images.
## Bitmap Header
```vb
'Bitmap.BI can be included at start of program
TYPE BMPEntry **' Description Bytes QB64 Function**
ID AS STRING * 2 ' File ID("BM" text or 19778 AS Integer) 2 CVI("BM")
Size AS LONG ' Total Size of the file 4 LOF
Res1 AS INTEGER ' Reserved 1 always 0 2
Res2 AS INTEGER ' Reserved 2 always 0 2
Offset AS LONG ' Start offset of image pixel data 4 (add one for GET)
END TYPE ' Total 14
TYPE BMPHeader 'BMP header also used in Icon and Cursor files(.ICO and .CUR)
Hsize AS LONG ' Info header size (always 40) 4
PWidth AS LONG ' Image width 4 _WIDTH(handle&)
PDepth AS LONG ' Image height (doubled in icons) 4 _HEIGHT(handle&)
Planes AS INTEGER ' Number of planes (normally 1) 2
BPP AS INTEGER ' Bits per pixel(palette 1, 4, 8, 24) 2 _PIXELSIZE(handle&)
Compression AS LONG ' Compression type(normally 0) 4
ImageBytes AS LONG ' (Width + padder) * Height 4
Xres AS LONG ' Width in PELS per metre(normally 0) 4
Yres AS LONG ' Depth in PELS per metre(normally 0) 4
NumColors AS LONG ' Number of Colors(normally 0) 4 2 ^ BPP
SigColors AS LONG ' Significant Colors(normally 0) 4
END TYPE ' Total Header bytes = 40
```
```vb
'$INCLUDE: 'Bitmap.BI' 'use only when including a BI file
DIM SHARED ENT AS BMPEntry
DIM SHARED BMP AS BMPHeader
LINE INPUT "Enter a bitmap file name: ", file$ '<<<< enter a bitmap file name
OPEN file$ FOR BINARY AS #1
GET #1, 1, ENT 'get entry header(1 is first file byte in QB64 and Qbasic)
GET #1, , BMP 'get bitmap header information
PRINT "Size:"; ENT.Size; "bytes, Offset:"; ENT.Offset
PRINT BMP.PWidth; "X"; BMP.PDepth
PRINT "BPP ="; BMP.BPP
CLOSE #1
```
> *Explanation:* Use two [GET](GET)s to read all of the header information from the start of the bitmap file opened FOR [BINARY](BINARY). It reads all 54 bytes as [STRING](STRING), [INTEGER](INTEGER) and [LONG](LONG) type DOT variable values. [TYPE](TYPE) DOT variables do not require type suffixes!
*Snippet:* Use the DOT variable name values like this [GET (graphics statement)](GET-(graphics-statement)) after you load the bitmap image to the screen:
```vb
GET (0, 0)-(BMP.PWidth - 1, BMP.PDepth - 1), Image(48) 'index after 16 * 3 RGB palette colors(0 to 47)
```
The bitmap image is now stored in an [Arrays](Arrays) to [BSAVE](BSAVE) to a file. The RGB color information follows the file header as [ASCII](ASCII) character values read using [ASC](ASC). The color values could be indexed at the start of the Array with the image being offset to: index = NumberOfColors * 3. As determined by the [SCREEN (statement)](SCREEN-(statement)) mode used. In SCREEN 13(256 colors) the index would be 768.
```text
**BITMAP COMPRESSION METHODS**
**Value Identified by Compression method Comments**
0 BI_RGB none Most common
1 BI_RLE8 * RLE 8-bit/pixel Used only with 8-bit/pixel bitmaps
2 BI_RLE4 * RLE 4-bit/pixel Used only with 4-bit/pixel bitmaps
3 BI_BITFIELDS Bit field Used only with 16 and 32-bit/pixel bitmaps.
4 BI_JPEG JPEG Bitmap contains a JPEG image
5 BI_PNG PNG Bitmap contains a PNG image
* RLE stands for *Run Length Encoding* which counts the number of consecutive pixels
that are of the same color instead of assigning each pixel color separately.
```
## Image Data
```text
**Windows/OS2 Bitmaps**
┌─────────┐
│BMP Entry│
│ 14 Byte │
│─────────│
│ Bitmap │
│ Header │
│ 40 Byte │
└────┬────┘
┌─────────┬────┴────┬─────────┐
│ ┌───┴───┐ ┌───┴───┐ │
│ │ 4 BPP │ │ 8 BPP │ │
│ │Palette│ │Palette│ │
│ │64 Byte│ │1024 B │ │
┌───┴───┐ └───┬───┘ └───┬───┘ ┌───┴───┐
│ 1 BPP │ ┌───┴───┐ ┌───┴───┐ │24 BPP │
│ IMAGE │ │ IMAGE │ │ IMAGE │ │ IMAGE │
│ DATA │ │ DATA │ │ DATA │ │ DATA │
│(W*H)\8│ │(W*H)\2│ │(W*H)*1│ │(W*H)*3│
│ bytes │ │ bytes │ │ bytes │ │ bytes │
└───────┘ └───────┘ └───────┘ └───────┘
```
**Bits Per Pixel (BPP)**
BPP returns **1 bit**(Black and white), **4 bit**(16 colors), **8 bit**(256 colors) or **24 bit**(16 million colors) for each pixel. In QBasic 24 bit can only be in greyscale, but QB64 can display them as True Color. 24 bit is also often referred to as 32 bit, but each pixel uses three bytes of information for the Red, Green and Blue color intensity settings. Intensity settings are read as [ASCII](ASCII) characters using [ASC](ASC).
**Palette Data (4 and 8 Bit Only)**
* **Attribute** color intensities for **4** and **8 BPP** are set by the bitmap itself using the **Palette data** immediately following the bitmap header. The data is read as Blue, Green and Red color intensities with a one byte padder following each BGR setting. This is true for ALL Windows/OS2 bitmap color intensities including 24 bit, which reads the intensities directly from the **image pixel data**!
**The Four Bit Palette is 64 bytes and the Eight Bit is 1024 bytes. One Bit and 24/32 Bit have no palette data!**
Note: [_COPYPALETTE](_COPYPALETTE) may be required to adapt the [SCREEN](SCREEN) palette to the custom colors of the bitmap.
> Why BGR instead of RGB? Because the [LONG](LONG) [_RGBA32](_RGBA32) value with 0 [_ALPHA](_ALPHA) is written to a file as 4 [MKL$](MKL$) [ASCII](ASCII) characters.
```vb
SCREEN 13 '8 bit, 256 color screen mode
Q$ = CHR$(34)
INPUT "Enter a color number 1 to 255: ", colour
PRINT
OUT &H3C7, colour
red = INP(&H3C9) * 4
green = INP(&H3C9) * 4
blue = INP(&H3C9) * 4
alpha = 0 'alpha values > 127 in _RGBA or _RGBA32 should use _UNSIGNED LONG
COLOR _RGB(red, green, blue) 'returns closest attribute in 4 or 8 bit screen modes
rgba~& = _RGBA32(red, green, blue, alpha) 'alpha is actually highest byte
PRINT "RGBA ="; red; green; blue; alpha
PRINT "_RGBA32 ="; rgba~&; " &H"; HEX$(rgba~&)
_PRINTSTRING (40, 40), "BGR0 = " + Q$ + MKL$(rgba~&) + Q$ 'rightmost always CHR$(0) spacer
END
```
> *Note:* 16 colors at 4 bytes each = 64 bytes. 256 colors at 4 bytes each = 1024 bytes in the palette data with [CHR$](CHR$)(0) spacers.
**Warning! Use [_UNSIGNED](_UNSIGNED) [LONG](LONG) when comparing [_RGB](_RGB) or [_RGB32](_RGB32) full [_ALPHA](_ALPHA) values with [POINT](POINT) values!**
**Image Data**
* **Image data** starts immediately after the bitmap header with **One Bit** and **24 Bit** colors. Immediately after the palette data with **4 Bit** and **8 Bit** colors. Image pixel data is read starting with the data from the **BOTTOM** row of the image. This is another idiosyncrasy of the Windows/OS2 bitmap. The pixel columns thankfully are read left to right. You may notice the image being drawn from the bottom up in QBasic. The size of the data in a 24 Bit bitmap is almost triple the size of an 8 Bit one!
**NOTE: The header Offset sets the position as the byte preceding the image data!**
**Image Data Padding Prevents Image Skewing**
* Image data is **byte padded** for odd bitmap widths and a minimum pixel byte width as set below:
- **1 BPP:** minimum pixel widths of multiples of 32 (32 bits = 4 bytes) per row. Use: Padder bytes = 32 - (width MOD 32)
- **4 BPP:** minimum pixel widths of multiples of 8 (32 bits = 4 bytes) per row. Padder bytes = (8 - (width MOD 8)) \ 2
- **8 BPP:** minimum pixel widths of multiples of 4 (4 bytes) per row. Padder bytes = 4 - (width MOD 4)
- **24 BPP:** minimum pixel widths of multiples of 4 (3 bytes/pixel = 12 bytes) per row. Padder bytes = 4 - ((width * 3) MOD 4)
## One Bit:##
Since the pixel value is either on(white) or off(black), eight pixels can be stored in one byte of information. The total byte value determines which pixels are on or off. The **MSB**(highest)value is to the left and each pixel's on value decreases by an exponent of two down to a value of 1 for the **LSB**. However a minimum of 4 bytes of data must be used for each row of data, so a padder is used for other widths. The padder can be determined before the data is read using the following routine:
```vb
SUB OneBit 'Any Screen as Black and White
BitsOver = BMP.PWidth MOD 32 'check bitmap width for 4 byte or odd width
IF BitsOver THEN ZeroPAD$ = SPACE$((32 - BitsOver) \ 8) '16 and 48 wide have 2 byte padder
y = BMPHead.PDepth - 1: o$ = " "
GET #1, BMP.Offset, o$ ' offset is last byte of BMP header data (NO Palette)
a$ = " " 'define a one byte string to read ASCII characters
DO
x = 0
DO
GET #1, , a$
CharVAL = ASC(a$) 'ASCII value cannot use _BYTE
Bit = 128 'start at MSB
FOR BitCOUNT = 1 TO 8
IF CharVAL AND Bit THEN
PSET (x, y), _RGB(255, 255, 255) '_RGB works in 1, 4, 8 or 32 bit screen mode
ELSE PSET (x, y), _RGB(0, 0, 0) 'set pixels on as white
END IF
Bit = Bit / 2 'decrease exponent of 2 bit value
x = x + 1 'move one pixel to the right
NEXT BitCOUNT
LOOP WHILE x < BMP.PWidth
GET #1, , ZeroPAD$ 'skip the padder bytes if any
y = y - 1 'move up one row from bottom
LOOP UNTIL y = -1
END SUB * *
```
<sub>Code by Bob Seguin</sub>
> One bit pixels are also used to create [AND](AND) masks that can blend with a background for icons or cursors which are another form of bitmap. In fact, icons and cursors use a partial (40 byte) bitmap header! They just don't have the first 14 bytes of information. [PSET](PSET) can also use the B&W color values [_RGB](_RGB)(255, 255, 255) and [_RGB](_RGB)(0, 0, 0) when working in 4, 8 or 32 bit screen modes.
## Four Bit:##
Pixels can use 16 colors in QBasic legacy [SCREEN (statement)](SCREEN-(statement)) modes 7, 8, 9, 12 and 13. After the bitmap header, the color **palette** is read to set the color intensities as explained above. Then the individual pixel attributes are read from the **image data**. Each **pixel** uses half a byte of color **attribute** information. To determine the pixel's attribute, each "nibble" is read by dividing the byte's [ASCII](ASCII) value by 16 for the first pixel's value while the second pixel's value is found using [AND](AND) 15 as shown below:
```vb
SUB FourBIT ' 4 bit(16 color) Screens 7, 8, 9, 12 or 13
IF BMP.PWidth MOD 8 THEN ZeroPAD$ = SPACE$((8 - BMP.PWidth MOD 8) \ 2)
a$ = " "
OUT &H3C8, 0 'start at attribute 0
FOR Colr = 0 TO 15 'read palette data for intensities
GET #1, , a$: Blu = ASC(a$) \ 4 'intensity is divided by 4 to use OUT
GET #1, , a$: Grn = ASC(a$) \ 4
GET #1, , a$: Red = ASC(a$) \ 4
OUT &H3C9, Red 'NOTE: RGB settings could also be sent directly to an
OUT &H3C9, Grn 'array when the data is to be stored by a file using
OUT &H3C9, Blu 'BSAVE or with one PUT # to a BINARY file in QB64
GET #1, , a$ '--- skip unused spacer byte
NEXT Colr
o$ = " "
GET #1, BMP.Offset, o$ 'Offset is the last byte of palette data
y = BMP.PDepth - 1: a$ = " "
DO
x = 0 'image placed at left side of screen
DO
GET #1, , a$
HiNIBBLE = ASC(a$) \ &H10 'ASCII value divided by 16 colors
LoNIBBLE = ASC(a$) AND &HF 'ASCII value AND 15
PSET (x, y), HiNIBBLE
x = x + 1
PSET (x, y), LoNIBBLE
x = x + 1
LOOP WHILE x < BMPHead.PWidth
GET #1, , ZeroPAD$ 'skip padder bytes if any
y = y - 1 'move up one row from bottom
LOOP UNTIL y = -1
END SUB
```
<sub>Code by Bob Seguin</sub>
**How Nibble values are read**
Each half of a byte of image pixel data stores a color attribute value from 0 to 15 or from 0000 to 1111 in binary with 1 designating that the bit is on. So when the two halves are added the [Binary](Binary) byte value for two white pixels totals 111111111 binary or 255.
* To get the high nibble, divide the byte value by 16(&H10) using integer division: HiNibble = 255 \ 16 = 15
* To get the low nibble, use the byte value [AND](AND) 15(&HF) to get all set bit values up to 15: LoNibble = 255 AND 15 = 15
> [AND](AND) 15 will return any lower byte value while integer division by 16 will return any byte value over 15 as attributes 0 to 15.
> **QB64** can [GET (graphics statement)](GET-(graphics-statement)) a full Screen 12 image into one [BINARY](BINARY) file with [PUT](PUT) using an 80K [INTEGER](INTEGER) array instead of using 3 in QBasic!
## Eight Bit:
Pixels can use 256 colors in QBasic legacy [SCREEN (statement)](SCREEN-(statement)) mode 13 or a [_NEWIMAGE](_NEWIMAGE) Screen using 256 or "borrowing" screen 13. **Image data** is immediately after the 1024 bytes of **palette data** BGR intensity settings. Pixel **attributes** are each set by reading the byte's [ASCII](ASCII) value directly.
```vb
SUB EightBIT ' 8 Bit (256 color) Screen 13 Only
IF BMP.PWidth MOD 4 THEN ZeroPAD$ = SPACE$(4 - (BMP.PWidth MOD 4)) 'check for padder
a$ = " "
OUT &H3C8, 0 'start at attribute 0
FOR Colr = 0 TO 255
GET #1, , a$: Blu = ASC(a$) \ 4
GET #1, , a$: Grn = ASC(a$) \ 4
GET #1, , a$: Red = ASC(a$) \ 4
OUT &H3C9, Red
OUT &H3C9, Grn
OUT &H3C9, Blu
GET #1, , a$ '--- skip unused spacer byte
NEXT Colr
y = BMP.PDepth - 1: o$ = " "
GET #1, BMP.Offset, o$ 'Offset is last byte of palette data.
p$ = " "
DO: x = 0
DO
GET #1, , p$
PSET (x, y), ASC(p$)
x = x + 1
LOOP WHILE x < BMP.PWidth
GET #1, , ZeroPAD$ 'skip padder if any
y = y - 1 'move up one row from bottom
LOOP UNTIL y = -1
END SUB
```
<sub>Code by Bob Seguin</sub>
## Twenty Four Bit:
For screen modes created by [_NEWIMAGE](_NEWIMAGE) using 24 or 32 bit bitmaps. **Image data** starts immediately after the bitmap header. There is no palette data! Each BGR **color intensity** is one byte of the [ASCII](ASCII) code value directly. Values range from 0 to 255 using **QB64's** [_RGB](_RGB) or [_RGB32](_RGB32) functions to set the [PSET](PSET) colors as below:
```vb
SUB TrueCOLOR '24/32 BIT
IF ((BMP.PWidth * 3) MOD 4) <> 0 THEN '3 byte pixels
ZeroPAD$ = SPACE$((4 - ((BMP.PWidth * 3) MOD 4)))
END IF
y = BMP.PDepth - 1: o$ = " "
GET #1, BMP.Offset, o$ 'Offset is last byte of BMP header data
R$ = " "
G$ = " "
B$ = " "
DO
x = 0 'place image to left side of screen
DO
GET #1, , B$ 'intensities read in reverse order BGR like palette
GET #1, , G$
GET #1, , R$
red& = ASC(R$) 'read ASCII code value 0 to 255 (or use _UNSIGNED _BYTE)
green& = ASC(G$)
blue& = ASC(B$)
PSET (x, y), _RGB(red&, green&, blue&) 'legacy screens give closest 4 or 8 bit attribute
x = x + 1
LOOP WHILE x < BMP.PWidth
GET #1, , ZeroPAD$ 'skip padder if any
y = y - 1 'move up one row from bottom
LOOP UNTIL y = -1
END SUB
```
<sub>Code by Ted Weissgerber</sub>
> Why BGR instead of RGB? Because the [_RGB](_RGB) [LONG](LONG) value without [_ALPHA](_ALPHA) is written to the file backwards as [LEFT$](LEFT$)([MKL$](MKL$), 3).
**Converting to Grey Scale or Black and White**
The palettes can be set to greyscale by ignoring the actual **palette data** and/or averaging the pixel's RGB **image data**.
It may also be necessary when trying to view 24 BPP bitmaps in SCREEN 12 or 13.
*See:* [Grey Scale Bitmaps](Grey-Scale-Bitmaps)
## Creating Bitmaps
In [BINARY](BINARY) files, numerical data can also be converted to [ASCII](ASCII) characters by using [MKI$](MKI$) for [INTEGER](INTEGER)s or [MKL$](MKL$) for [LONG](LONG) values. [GET](GET) can convert [_MK$](_MK$) values to numerical values and [PUT](PUT) can convert numerical values to [STRING](STRING) values. When the [LONG](LONG) [MKL$](MKL$) color values are [PUT](PUT) into bitmaps the Red value is placed as the third [ASCII](ASCII) character and the blue becomes the first character. That not only happens to the BGR palette data, but the BGR 24 bit image color values [PUT](PUT) using the [LEFT$](LEFT$) 3 bytes.
```vb
pixelcolor$ = LEFT$(MKL$(_RGB(red%, green%, blue%)), 3)
```
After the header, the RGB **color intensity palette** settings for **16** and **256** color bitmaps are created using [MKL$](MKL$) [ASCII](ASCII) characters set backwards as Blue, Green, Red and [CHR$](CHR$)(0) as a spacer. Four and Eight BPP bitmaps require that format.
The actual 4 bit or 8 bit image is read as [ASCII](ASCII) color attributes from the image bottom to the top for proper bitmap formatting adding padder spacing when needed. 24/32 bit images use 3 color intensity values as [ASCII](ASCII) character bytes in BGR order.
*Bitmap creation SUB programs:*
* [SAVEIMAGE](SAVEIMAGE) (Galleon's Full Image Bitmap creator)
* [SaveIcon32](SaveIcon32) (Creates Icons from any image)
* [Program ScreenShots](Program-ScreenShots) (Member program for Qbasic's legacy screen modes)
* [ThirtyTwoBit SUB](ThirtyTwoBit-SUB) (QB64 32 bit Image area to bitmap)
## See Also
* [_LOADIMAGE](_LOADIMAGE), [_PUTIMAGE](_PUTIMAGE)
* [SCREEN (statement)](SCREEN-(statement))
* [TYPE](TYPE), [_ICON](_ICON)
* [Icons and Cursors](Icons-and-Cursors)
* [GIF Images](GIF-Images)
* [Resource Table Extraction](Resource-Table-Extraction)
* [$EXEICON]($EXEICON) (Icons viewed in Windows Explorer)

118
wiki/Bitwise-Operators.md Normal file
View file

@ -0,0 +1,118 @@
Bitwise operators are much like the regular mathematics operators (+, * etc.) but are defined in terms of the individual bits of their operands. The full list of bitwise operators, with a brief summary of its operation:
* AND: True if both inputs are true
* OR: True if one or both inputs are true
* NOT: Invert all bits
* XOR: True if exactly one input is true
* IMP: True if both inputs are the same
* EQV: True unless first input is true and second is false
## Syntax
With the exception of NOT, all the bitwise operators take two operands:
`result = value1 AND value2`
NOT goes before the value it operates on:
`result = NOT value1`
If *value1* or *value2* are non-integer numeric types, they are rounded to the nearest integer.
## Details
Bitwise operators work by comparing the corresponding bits in each of the input values to generate a single bit in the output value. The operators differ in how they do the comparison. The table below shows the output bit for each pair of input bits:
MISSING: Truth Table
Again, note that the NOT operator only has one operand. It is shown in the same table for convenience.
If one input has more bits than the other (say, an INTEGER vs a LONG) the shorter will be considered to have 0's in the missing bit positions if it is positive, or 1's if it is negative. This scheme comes about because of the [Two's Complement](https://en.wikipedia.org/wiki/Two%27s_complement) system for representing negative numbers. As a general rule, there should not be any surprises.
## Example(s)
Use **AND** to mask certain bits in a value. In this example, the 1's in the mask (y&) specify which bits in (x&) we are interested in, forcing all others to 0.
```vb
x& = VAL("&B101010") 'Arbitrary collection of bits
y& = VAL("&B001100") 'A bit mask
PRINT "Input 1: "; BIN$(x&, 6) '6 indicates we want 6 bits of output
PRINT "Input 2: "; BIN$(y&, 6)
PRINT "Output: "; BIN$(x& AND y&, 6)
'Converts the number n& to a string of binary digits, digits& long (padding or truncating as necessary).
FUNCTION BIN$ (n&, digits&)
FOR i& = digits& - 1 TO 0 STEP -1
IF (n& AND 2 ^ i&) THEN B$ = B$ + "1" ELSE B$ = B$ + "0"
NEXT
BIN$ = B$
END FUNCTION
```
```text
Input 1: 101010
Input 2: 001100
Output: 001000
```
Use **OR** to combine bit flags into a single value. The presence of a flag can then be tested by using the flag as a mask with **AND**:
```vb
'The trick here is to give each flag a value corresponding to a different bit being 1
FLAG_A& = VAL("&B0001")
FLAG_B& = VAL("&B0010")
FLAG_C& = VAL("&B0100")
FLAG_D& = VAL("&B1000")
flags& = FLAG_A& OR FLAG_C& 'Set flags A, C
'Use each flag as a bitmask to test for its presence:
IF flags& AND FLAG_A& THEN PRINT "Flag A is set"
IF flags& AND FLAG_B& THEN PRINT "Flag B is set"
IF flags& AND FLAG_C& THEN PRINT "Flag C is set"
IF flags& AND FLAG_D& THEN PRINT "Flag D is set"
```
```text
Flag A is set
Flag C is set
```
Use **XOR** to toggle a bit flag (that is, change its state to the opposite of what it was). This example is the same as the **OR** example above, but with one extra line added. This time we enable flags A & C, then toggle flags A & B. This will disable flag A and enable B.
```vb
'The trick here is to give each flag a value corresponding to a different bit being 1
FLAG_A& = VAL("&B0001")
FLAG_B& = VAL("&B0010")
FLAG_C& = VAL("&B0100")
FLAG_D& = VAL("&B1000")
flags& = FLAG_A& OR FLAG_C& 'Set flags A, C
flags& = flags& XOR FLAG_A& XOR FLAG_B& 'Toggle flags A, B
'Use each flag as a bitmask to test for its presence:
IF flags& AND FLAG_A& THEN PRINT "Flag A is set"
IF flags& AND FLAG_B& THEN PRINT "Flag B is set"
IF flags& AND FLAG_C& THEN PRINT "Flag C is set"
IF flags& AND FLAG_D& THEN PRINT "Flag D is set"
```
```text
Flag B is set
Flag C is set
```

87
wiki/Boolean.md Normal file
View file

@ -0,0 +1,87 @@
**Boolean** statements are numerical evaluations that return True (-1 or NOT 0) or False (0) values that can be used in other calculations.
*Basic Returns:*
* True evaluations return -1. [NOT](NOT) 0 = -1 in Basic. Can be used to increment a value.
* For positive True results, subtract it, multiply it by a negative value or use [ABS](ABS).
* False evaluations return 0. Watch out for [ERROR Codes](ERROR-Codes)!
MISSING: Relational Table
* When evaluating a True value, an IF value < 0 statement is NOT necessary for return values not 0.
** Truth table of the BASIC Logical Operators:**
MISSING: Logical Truth Table
**Boolean Conditional Operators:**
* [AND (boolean)](AND-(boolean)) can be used to add extra conditions to a boolean statement evaluation. Both must be True.
* [OR (boolean)](OR-(boolean)) can be used to add alternate conditions to a boolean statement evaluation. One must be True.
* Parenthesis are allowed inside of boolean statements to clarify an evaluation.
* **Note that Basic returns -1 for True and 0 for False.**
Using 2 different boolean evaluations to determine a leap year.
```vb
INPUT "Enter a year greater than 1583: ", annum$
Y = VAL(annum$)
leap1 = (Y MOD 4 = 0 AND Y MOD 100 <> 0) OR (Y MOD 400 = 0)
leap2 = (Y MOD 4 = 0) - (Y MOD 100 = 0) + (Y MOD 400 = 0)
PRINT "Year = "; annum$, "Leap1 = "; leap1, "Leap2 = "; leap2
```
*Explanation:* Both boolean evaluations will return -1 if the year is a leap year. It is not simply every four years as many people think. That is checked by the first evaluation (Y MOD 4 = 0) of each. In new century years like 1900 (which was not a leapyear) there is only one leap year every 400 years. 100 is used with [MOD](MOD) to see if there is a remainder. When that is true, the boolean return of that part of the first evaluation will be 0. The second returns -1 (which is actually added). In both evaluations the result of (Y MOD 400 = 0) indicates a century leap year.
Entry year = 2000
> leap1 = (-1 AND 0) OR -1 = -1 ' the AND evaluation returns False(0) so the OR value is used.
> leap2 = (-1) - (-1) + (-1) = -1 + 1 + -1 = -1
Entry year = 1900
> leap1 = (-1 AND 0) OR 0 = 0 OR 0 = 0
> leap2 = (-1) - (-1) + (0) = -1 + 1 + 0 = 0
Moving an [ASCII](ASCII) character using the arrow keys and boolean statements to determine the new coordinate.
```vb
SCREEN 12
COLOR 7
LOCATE 11, 20: PRINT "Using Screen 12 here to be in 80 X 30 coordinates mode"
LOCATE 13, 6: PRINT "Simple Example of Alternative programming without IF-THEN-ELSE Statements"
LOCATE 15, 1: PRINT "Use the four Cursor keys to move the yellow cursor, text will not be disturbed"
LOCATE 17, 12: PRINT "When you END the program with the ESC key, cursor will disappear"
cordx% = 40
cordy% = 15
DO
oldcordx% = cordx%
oldcordy% = cordy%
p% = SCREEN(cordy%, cordx%) 'get ASCII character code at present position
COLOR 14: LOCATE cordy%, cordx%: PRINT CHR$(178); 'print cursor character to position
WHILE cordx% = oldcordx% AND cordy% = oldcordy% AND k$ <> CHR$(27)
k$ = INKEY$
cordx% = cordx% + (k$ = (CHR$(0) + "K") AND cordx% > 1) + ABS(k$ = (CHR$(0) + "M") AND cordx% < 80)
cordy% = cordy% + (k$ = (CHR$(0) + "H") AND cordy% > 1) + ABS(k$ = (CHR$(0) + "P") AND cordy% < 30)
WEND
COLOR 7: LOCATE oldcordy%, oldcordx%: PRINT CHR$(p%); 'replace overwritten screen characters
LOOP UNTIL k$ = CHR$(27)
```
<sub>Code by AlgoreIthm</sub>
## See Also
* [IF...THEN](IF...THEN), [SELECT CASE](SELECT-CASE)
* [Binary](Binary), [ABS](ABS), [SGN](SGN)
* [AND](AND), [OR](OR), [XOR](XOR)

929
wiki/C-Libraries.md Normal file
View file

@ -0,0 +1,929 @@
**QB64** uses C++ to compile a BAS program into an executable program. The following is a list of the **C [FUNCTION](FUNCTION)s** that can be used.
**Note: C++ Header files should be placed in the QB64 folder and are not required after a program is compiled.**
## **C++ Variable Types**
| C Name | Description | Size | QB64 Type |
| ----------- | ----------------------- | ----------------- | ------------ |
|[_BYTE](_BYTE) | Character or small integer. | 1 byte | [_BYTE](_BYTE) |
|[INTEGER](INTEGER) | Short Integer(Word) | 2 byte | [INTEGER](INTEGER)|
|[LONG](LONG) | Integer(Dword) | 4 byte | [LONG](LONG) |
|[LONG](LONG) | Int32, Long integer or Long | 4 byte | [LONG](LONG) |
|[_INTEGER64](_INTEGER64) | Long long (Qword) | 8 byte | [_INTEGER64](_INTEGER64) |
|[Boolean](Boolean) | Boolean value true or false. | 1 byte | [_BYTE](_BYTE) |
|[SINGLE](SINGLE) | Floating point number | 4 byte | [SINGLE](SINGLE) |
|[DOUBLE](DOUBLE) | Double precision floating. | 8 byte | [DOUBLE](DOUBLE) |
|[_FLOAT](_FLOAT) | Long double precision float | 10 byte | [_FLOAT](_FLOAT) |
|[Unicode](Unicode) | Wide character([Unicode](Unicode)) | 2 or 4 |
|[_OFFSET](_OFFSET) | void pointer(void *) | ANY | [_OFFSET](_OFFSET)|
## C Functions and Subs
```vb
DECLARE LIBRARY
**'ctime.h**
FUNCTION clock () 'arithmetic type elapsed processor representing time.
FUNCTION difftime# (BYVAL time2 AS _UNSIGNED LONG, BYVAL time1 AS _UNSIGNED LONG)
'seconds between time2 and time1
**'ctype.h**
FUNCTION isalnum% (BYVAL c AS INTEGER) 'is an alphabet letter(isalpha(c) or isdigit(c))
FUNCTION isalpha% (BYVAL c AS INTEGER) 'is letter (isupper(c) or islower(c))
FUNCTION isdigit% (BYVAL c AS INTEGER) 'is a decimal digit
FUNCTION isgraph% (BYVAL c AS INTEGER) 'is a printing character other than space
FUNCTION islower% (BYVAL c AS INTEGER) 'is a lower-case letter
FUNCTION isprint% (BYVAL c AS INTEGER) 'is printing character. ASCII: &H20 (" ") to &H7E (~)
FUNCTION ispunct% (BYVAL c AS INTEGER) 'is printing character other than space, letter, digit
FUNCTION isspace% (BYVAL c AS INTEGER) 'is space, formfeed, newline, return, tab, vertical tab
FUNCTION isupper% (BYVAL c AS INTEGER) 'is upper-case letter
FUNCTION isxdigit% (BYVAL c AS INTEGER)'is a hexdecimal digit character(0 thru 9 or A thru F)
FUNCTION tolower% (BYVAL c AS INTEGER) 'return lower-case equivalent
FUNCTION toupper% (BYVAL c AS INTEGER) 'return upper-case equivalent
**'math.h**
FUNCTION acos# (BYVAL x AS DOUBLE)
FUNCTION asin# (BYVAL x AS DOUBLE)
FUNCTION atan# (BYVAL x AS DOUBLE) 'arc tangent of x does not designate the quadrant
FUNCTION atan2# (BYVAL y AS DOUBLE, BYVAL x AS DOUBLE) 'arc-tangent of y/x designates quadrant
FUNCTION cosh# (BYVAL x AS DOUBLE)
FUNCTION ldexp# (BYVAL base AS DOUBLE, BYVAL exponent AS INTEGER) 'base times 2 to exponent
FUNCTION pow# (BYVAL base AS DOUBLE, BYVAL exponent AS DOUBLE) 'base number raised to exponent
FUNCTION sinh# (BYVAL x AS DOUBLE)
FUNCTION tanh# (BYVAL x AS DOUBLE)
**'stdio.h** return non-zero INTEGER on failure.
FUNCTION remove% (filename AS STRING) 'removes specified file
FUNCTION rename% (oldname AS STRING, newname AS STRING) 'renames file oldname to newname.
**'stdlib.h**
FUNCTION atol& (str AS STRING) 'convert string to Long (errno not necessarily set)
FUNCTION atoi% (str AS STRING) 'convert string to Integer (errno not necessarily set)
FUNCTION atof# (str AS STRING) 'convert string to Double (errno not necessarily set)
FUNCTION rand& () 'random number
SUB srand (BYVAL seed AS _UNSIGNED LONG) 'random seeded number
**'string.h**
FUNCTION memchr& (BasePtr, value AS STRING, BYVAL Bytes AS LONG) ' returns pointer to first
'occurance of string in a set number of bytes at the memory block pointer designated.
FUNCTION memcmp (pointer1, pointer2, BYVAL Bytes AS _UNSIGNED LONG )
'compares pointer bytes. Returns 0 if match, positive if ptr1>ptr2, negative if ptr1<ptr2
SUB memcpy (DestPtr, SourcePtr, BYVAL Bytes AS _UNSIGNED LONG)
'copies the number of source bytes from source pointer to destination pointer
SUB memmove (DestPtr AS var_TYPE, SourcePtr AS var_TYPE, BYVAL bytesize AS LONG)
'moves a variable pointer value to destination from a source as a type byte size.
SUB memset (pointer AS **var_TYPE**, BYVAL value AS _UNSIGNED LONG, BYVAL nbytes AS _UNSIGNED LONG)
'The **var_TYPE** MUST match the type of the argument passed! Fills a block of memory. Sets the
'first bytes of the block of memory at pointer to the specified value as a character.
FUNCTION strcspn% (str1 AS STRING, str2 AS STRING)
'length of prefix of str1 consisting of characters not in str2.
FUNCTION strcmp% (str1 AS STRING, str2 AS STRING) 'compares str1 with str2, negative value if
'str1<str2, zero if str1=str2, positive if str1>str2
FUNCTION strncmp% (str1 AS STRING, str2 AS STRING, BYVAL Bytes AS INTEGER)'compares first byte
'characters of str1 and str2, negative if str1<str2, 0 if str1=str2, positive if str1>str2
SUB strncpy (dest AS STRING, source AS STRING, BYVAL Bytes AS INTEGER) 'Copies first
'bytes of source to destination. If source ends before number of bytes, dest padded with 0's
END DECLARE
```
How to use the [SUB](SUB) **memmove** to transfer [TYPE](TYPE) data when using Libraries.
```vb
TYPE a 'Note: the TYPE must be placed before the DECLARE LIBRARY if used in it!
b AS DOUBLE
c AS LONG
END TYPE
DECLARE LIBRARY
SUB memmove (Dest AS a, Source AS a, BYVAL bytesize AS LONG)
END DECLARE
DIM d(10) AS a
d(0).b = 1.5
d(0).c = 99
memmove d(10), d(0), LEN(d()) 'LEN gives the total byte size of the TYPE
PRINT d(10).b
PRINT d(10).c
```
```text
1.5
99
```
> *Explanation:* When a [TYPE](TYPE) variable is moved to another variable or array index, all [TYPE](TYPE) dot values are moved with it.
Creating different **memset** functions for each variable type to be used.
```vb
DECLARE LIBRARY
FUNCTION memsetB& ALIAS **memset** (p AS _BYTE, BYVAL c AS _UNSIGNED LONG, BYVAL n AS _UNSIGNED LONG)
FUNCTION memsetI& ALIAS **memset** (p AS INTEGER, BYVAL c AS _UNSIGNED LONG, BYVAL n AS _UNSIGNED LONG)
FUNCTION memsetL& ALIAS **memset** (p AS LONG, BYVAL c AS _UNSIGNED LONG, BYVAL n AS _UNSIGNED LONG)
END DECLARE
DIM Barray(1 TO 10) AS _BYTE
res& = memsetB(Barray(1), 65, 5)
FOR i = 1 TO 10
PRINT Barray(i); 'display BYTE array decimal values
NEXT
PRINT: PRINT
DIM Larray(1 TO 10) AS LONG
res& = memsetL(Larray(1), 65, 5)
FOR i = 1 TO 10
PRINT Larray(i); 'displays LONG array decimal values
NEXT i
PRINT
FOR i = 1 TO 10
PRINT " " + HEX$(Larray(i)); 'displays each byte value &H41 = 65
NEXT i
```
<sub>Code example by stylin</sub>
> *Explanation:* When 5 bytes are put into a 4 byte LONG array value, the fifth byte goes into the next array element.
## Bit Casting
Header file: *Cast.h*
```cpp
float bitcast(int t)
{
return *(float*)&t;
}
int swap_endian(unsigned int k)
{
return (k>>24)|((k<<8) & 0x00FF0000)|((k>>8) & 0x0000FF00)|(k<<24);
}
```
<sub>Courtesy of Darth Who</sub>
```vb
DECLARE LIBRARY "Cast"
FUNCTION bitcast## (BYVAL t AS LONG)
FUNCTION swap_endian (BYVAL k AS _UNSIGNED LONG)
END DECLARE
Value& = &HE7750340
PRINT HEX$(Value&)
PRINT bitcast##(Value&)
PRINT bitcast##(swap_endian(Value&))
```
## Fast Math
**Fastmath.h** header file. Library to speed up program calculations. Use with [DECLARE LIBRARY](DECLARE-LIBRARY) "Fastmath"
```cpp
using namespace std;
unsigned long xrander=123456789, yrander=362436069, zrander = 521288629;
unsigned long trander;
double compbase = 2.3025850929940456840179914546844d;
double basecomp = 1.0d;
int shift1 = 1;
int shift2 = 5;
int shift3 = 16;
float Fast_Sqrt(float val) //log2(n) approximation //this is not used in the LN approximation
{
//float chk
union
{
int tmp;
float val;
} vals;
vals.val = val;
vals.tmp -= 1<<23; // Remove last bit so 1.0 gives 1.0
// tmp is now an approximation to logbase2(val)
vals.tmp >>= 1; // divide by 2
vals.tmp += 1<<29; // add 64 to exponent: (e+127)/2 =(e/2)+63;
//vals.tmp = (1<<29) + (vals.tmp >> 1) - (1<<22) + 0x4C000; // I am working on a way to improve this value
// that represents (e/2)-64 but want e/2
return vals.val;
}
float Fast_InvSqrt( float number ) // originally by Silicon Graphics slightly higher accuracy variant below.
{
long i;
float x2, y;
const float threehalfs = 1.5F;
x2 = number * 0.5F;
y = number;
i = * ( long * ) &y; // evil floating point bit level hacking [sic]
i = 0x5f375a86 - ( i >> 1 ); // what the fuck? [sic] original silicon graphics constant: 0x5f3759df
y = * ( float * ) &i;
y = y * ( threehalfs - ( x2 * y * y ) ); // 1st iteration
//y = y * ( threehalfs - ( x2 * y * y ) ); // 2nd iteration, this can be removed
return y;
}
double Fast_Pow(double a, double b) //fastpower originally developed by Martin Ankerl
{
int tmp = (*(1 + (int *)&a));
int tmp2 = (int)(b * (tmp - 1072632447) + 1072632447);
double p = 0.0;
*(1 + (int * )&p) = tmp2;
//p = p * a / 2.71828F ; failed attempt to auto correct the accuracy
return tmp;
}
double Fast_Exp(double y) //2.87921
{
double d;
//*((int*)(&d) + 0) = 0;
*((int*)(&d) + 1) = (int)(1512775 * y + 1072632447);
return d;
}
double Fast_XLnX(double x) //Borchardt's algorithm only accurate close to the origin
{
union
{
int tmp;
float val;
} vals;
vals.val = x;
vals.tmp -= 1<<23; // Remove last bit so 1.0 gives 1.0
vals.tmp >>= 1; // divide by 2
vals.tmp += 1<<29; // add 64 to exponent: (e+127)/2 =(e/2)+63;
return 6.0F * x * (x - 1.0F) / (x + 4.0F * vals.val ++);
}
double Fast_LnX(double x)
{
union
{
int tmp;
float val;
} vals;
vals.val = x;
vals.tmp -= 1<<23; // Remove last bit so 1.0 gives 1.0
vals.tmp >>= 1; // divide by 2
vals.tmp += 1<<29; // add 64 to exponent: (e+127)/2 =(e/2)+63;
return 6.0F * x * (x - 1.0F) / (x * (x + 4.0F * vals.val ++));
}
double Fast_Log10 (double x)
{
union
{
int tmp;
float val;
} vals;
vals.val = x;
vals.tmp -= 1<<23; // Remove last bit so 1.0 gives 1.0
vals.tmp >>= 1; // divide by 2
vals.tmp += 1<<29; // add 64 to exponent: (e+127)/2 =(e/2)+63;
return 6.0F * x * (x - 1.0F) / (x * 2.302585092994F * (x + 4.0F * vals.val ++));
}
double Fast_LogPi (double x)
{
union
{
int tmp;
float val;
} vals;
vals.val = x;
vals.tmp -= 1<<23; // Remove last bit so 1.0 gives 1.0
vals.tmp >>= 1; // divide by 2
vals.tmp += 1<<29; // add 64 to exponent: (e+127)/2 =(e/2)+63;
return 6.0F * x * (x - 1.0F) / (x * 1.1447298858494F * (x + 4.0F * vals.val ++));
}
double Fast_Sin(double x) //currently only supports range between -3 * pi and 3 * pi
{
double sine;
//always wrap input angle to -PI..PI I know it is abit of a compicated algorithm but hey
int Piintdiv = x * 0.15915494309189F;
double Pix = x - 6.2831853071796F * Piintdiv;
if (Pix < -3.14159265F)
Pix += 6.28318531F;
else
if (Pix > 3.14159265F)
Pix -= 6.28318531F;
if (Pix < 0)
sine = (0.405284735F * Pix + 1.27323954F) * Pix;
//sine = 1.27323954 * x + .405284735 * x * x; // I do so love horner form
else
sine = (1.27323954 - 0.405284735 * Pix) * Pix;
return sine;
}
double Fast_Cos(double x)
{
double Cosine;
int Piintdiv = x * 0.15915494309189F;
double Pix = x - 6.2831853071796F * Piintdiv;
Pix += 1.57079632;
if (Pix < -3.14159265F)
Pix += 6.28318531F;
else
if (Pix > 3.14159265F)
Pix -= 6.28318531F;
if (Pix < 0)
Cosine = (1.27323954 + 0.405284735 * Pix) * Pix;
else
Cosine = (1.27323954 - 0.405284735 * Pix) * Pix;
return Cosine;
}
double Fast_Tan(double x)
{
double Cosine;
double sine;
//always wrap input angle to -PI..PI
if (x < -3.14159265F)
x += 6.28318531F;
else
if (x > 3.14159265F)
x -= 6.28318531F;
//compute sine
if (x < 0)
sine = (0.405284735F * x + 1.27323954F) * x; // I do so love horner form the alernative on the nex line is slower
//sine = 1.27323954 * x + .405284735 * x * x;
else
sine = (1.27323954 - 0.405284735 * x) * x;
x += 1.57079632;
if (x < 0)
Cosine = (1.27323954 + 0.405284735 * x) * x;
else
Cosine = (1.27323954 - 0.405284735 * x) * x;
return sine / Cosine;
}
double Fast_CoTan(double x)
{
double Cosine;
double sine;
//always wrap input angle to -PI..PI
if (x < -3.14159265F)
x += 6.28318531F;
else
if (x > 3.14159265F)
x -= 6.28318531F;
//compute sine
if (x < 0)
sine = (0.405284735F * x + 1.27323954F) * x; // I do so love horner form the alernative on the nex line is slower
//sine = 1.27323954 * x + .405284735 * x * x;
else
sine = (1.27323954 - 0.405284735 * x) * x;
x += 1.57079632;
if (x < 0)
Cosine = (1.27323954 + 0.405284735 * x) * x;
else
Cosine = (1.27323954 - 0.405284735 * x) * x;
return Cosine / sine;
}
double Fast_Sec(double x)
{
double Cosine;
x += 1.57079632;
if (x > 3.14159265)
x -= 6.28318531;
if (x < 0)
Cosine = (1.27323954 + 0.405284735 * x) * x;
else
Cosine = (1.27323954 - 0.405284735 * x) * x;
return 1 / Cosine;
}
double Fast_Csc(double x)
{
double sine;
//always wrap input angle to -PI..PI
if (x < -3.14159265F)
x += 6.28318531F;
else
if (x > 3.14159265F)
x -= 6.28318531F;
//compute sine
if (x < 0)
sine = (0.405284735F * x + 1.27323954F) * x;
//sine = 1.27323954 * x + .405284735 * x * x; // I do so love horner form
else
sine = (1.27323954 - 0.405284735 * x) * x;
return 1 / sine;
}
// |error| < 0.005
float Fast_Atan2(float y, float x)
{
float PIBY2_FLOAT = 1.5707963F;
float PI_FLOAT = 3.14159265F;
if (x ## 0.0f)
{
if (y > 0.0f) return PIBY2_FLOAT;
if (y ## 0.0f) return 0.0f;
return 0 - PIBY2_FLOAT;
}
float atan;
float z = y/x;
if ( fabsf( z ) < 1.0f )
{
atan = z/(1.0f + 0.28f*z*z);
if ( x < 0.0f )
{
if ( y < 0.0f ) return atan - PI_FLOAT;
return atan + PI_FLOAT;
}
}
else
{
atan = PIBY2_FLOAT - z/(z*z + 0.28f);
if ( y < 0.0f )
return atan - PI_FLOAT;
}
return atan;
}
float Fast_Atan(float y)
{
float x = 1.0F;
float PIBY2_FLOAT = 1.5707963F;
float PI_FLOAT = 3.14159265F;
float atan;
float z = y/x;
if (fabsf( z ) < 1.0f )
{
atan = z/(1.0f + 0.28f*z*z);
if ( x < 0.0f )
{
if ( y < 0.0f ) return atan - PI_FLOAT;
return atan + PI_FLOAT;
}
}
else
{
atan = PIBY2_FLOAT - z/(z*z + 0.28f);
if ( y < 0.0f )
return atan - PI_FLOAT;
}
return atan;
}
double Fast_ACos(double x)
{
float retval = (-0.69813170079773212F * x * x - 0.87266462599716477F) * x + 1.5707963267948966F;
return retval;
}
double Fast_ASin(double x)
{
float retval = (0.69813170079773212F * x * x + 0.87266462599716477F) * x;
return retval;
}
double Fast_SinH(double x)
{
double y = -x;
double k;
double d;
//*((int*)(&d) + 0) = 0;
*((int*)(&d) + 1) = (int)(1512775 * y + 1072632447);
//*((int*)(&k) + 0) = 0;
*((int*)(&k) + 1) = (int)(1512775 * x + 1072632447);
return (k - d) / 2;
}
double Fast_CosH(double x)
{
double y = -x;
double k;
double d;
//*((int*)(&d) + 0) = 0;
*((int*)(&d) + 1) = (int)(1512775 * y + 1072632447);
//*((int*)(&k) + 0) = 0;
*((int*)(&k) + 1) = (int)(1512775 * x + 1072632447);
return (k + d) / 2;
}
double Fast_TanH(double x) // from http://www.musicdsp.org/showone.php?id=238
{
//double xt;
if (x < -3)
{
return -1;
}
else if (x > 3)
{
return 1;
}
else
{
double xz = x * x;
return x * (27 + xz) / (27 + 9 * xz);
}
//return xt
}
double Fast_ATanH(double x)
{
double mlnx = 1-x;
double plnx = 1+x;
union
{
int tmp;
float val;
} vals;
union
{
int tmp;
float val;
} vals2;
vals.val = plnx;
vals.tmp -= 1<<23; // Remove last bit so 1.0 gives 1.0
vals.tmp >>= 1; // divide by 2
vals.tmp += 1<<29; // add 64 to exponent: (e+127)/2 =(e/2)+63;
vals2.val = mlnx;
vals2.tmp -= 1<<23; // Remove last bit so 1.0 gives 1.0
vals2.tmp >>= 1; // divide by 2
vals2.tmp += 1<<29; // add 64 to exponent: (e+127)/2 =(e/2)+63;
return (6.0F * mlnx * (mlnx - 1.0F) / (mlnx * (mlnx + 4.0F * vals.val ++)) - 6.0F * plnx * (plnx - 1.0F) / (plnx * (plnx + 4.0F * vals2.val ++))) * 0.5f;
}
double Fast_ACosH(double val)
{
double zsqrz;
//float chk
union
{
int tmp;
float val;
} vals;
union
{
int tmp;
float val;
} val2s;
vals.val = val + 1;
vals.tmp -= 1<<23; // Remove last bit so 1.0 gives 1.0
// tmp is now an approximation to logbase2(val)
vals.tmp >>= 1; // divide by 2
vals.tmp += 1<<29; // add 64 to exponent: (e+127)/2 =(e/2)+63;
val2s.val = val - 1;
val2s.tmp -= 1<<23; // Remove last bit so 1.0 gives 1.0
// tmp is now an approximation to logbase2(val)
val2s.tmp >>= 1; // divide by 2
val2s.tmp += 1<<29; // add 64 to exponent: (e+127)/2 =(e/2)+63;
zsqrz = val + vals.val * val2s.val;
return log(zsqrz);
}
double Fast_ASinH(double x)
{
union
{
int tmp;
float val;
} vals;
vals.val = x * x + 1;
vals.tmp -= 1<<23; // Remove last bit so 1.0 gives 1.0
// tmp is now an approximation to logbase2(val)
vals.tmp >>= 1; // divide by 2
vals.tmp += 1<<29; // add 64 to exponent: (e+127)/2 =(e/2)+63;
return log(x + vals.val);
}
double Fast_ASecH(double x)
{
double zsqrz;
//float chk
union
{
int tmp;
float val;
} vals;
union
{
int tmp;
float val;
} val2s;
vals.val = 1 / x + 1;
vals.tmp -= 1<<23; // Remove last bit so 1.0 gives 1.0
// tmp is now an approximation to logbase2(val)
vals.tmp >>= 1; // divide by 2
vals.tmp += 1<<29; // add 64 to exponent: (e+127)/2 =(e/2)+63;
val2s.val = 1 / x - 1;
val2s.tmp -= 1<<23; // Remove last bit so 1.0 gives 1.0
// tmp is now an approximation to logbase2(val)
val2s.tmp >>= 1; // divide by 2
val2s.tmp += 1<<29; // add 64 to exponent: (e+127)/2 =(e/2)+63;
zsqrz = 1 / x + vals.val * val2s.val;
return log(zsqrz);
}
double Fast_ACscH(double val)
{
double x = 1 / val;
union
{
int tmp;
float val;
} vals;
vals.val = x * x + 1;
vals.tmp -= 1<<23; // Remove last bit so 1.0 gives 1.0
// tmp is now an approximation to logbase2(val)
vals.tmp >>= 1; // divide by 2
vals.tmp += 1<<29; // add 64 to exponent: (e+127)/2 =(e/2)+63;
return log(x + vals.val);
}
double Fast_ACotH(double valts)
{
double x = 1 / valts;
double mlnx = 1-x;
double plnx = 1+x;
union
{
int tmp;
float val;
} vals;
union
{
int tmp;
float val;
} vals2;
vals.val = plnx;
vals.tmp -= 1<<23; // Remove last bit so 1.0 gives 1.0
vals.tmp >>= 1; // divide by 2
vals.tmp += 1<<29; // add 64 to exponent: (e+127)/2 =(e/2)+63;
vals2.val = mlnx;
vals2.tmp -= 1<<23; // Remove last bit so 1.0 gives 1.0
vals2.tmp >>= 1; // divide by 2
vals2.tmp += 1<<29; // add 64 to exponent: (e+127)/2 =(e/2)+63;
return (6.0F * mlnx * (mlnx - 1.0F) / (mlnx * (mlnx + 4.0F * vals.val ++)) - 6.0F * plnx * (plnx - 1.0F) / (plnx * (plnx + 4.0F * vals2.val ++))) / 2;
}
void Fast_RandInit(float x,int i,int j, int k)
{
float ftl;
float ftl2;
float ftl3;
ftl = 10000 * sin(x*7);
xrander = * ( long * ) &ftl;
ftl2 = 10000 * cos(x*3);
yrander = * ( long * ) &ftl2;
ftl3 = 10000 * sin(x*2);
zrander = * ( long * ) &ftl3;
if ((i ## 0)||(j ## 0)||( k ## 0 ))
{
shift1 = 1;
shift2 = 5;
shift3 = 16;
}
else
{
shift1 = i; //8 * sin(x) + 9;
shift3 = k; //8 * cos(x) + 9;
shift2 = j; //(shift1 + shift3) / 2;
}
}
inline float Fast_Rand(void) //based off of George Marsaglia's XORSHIFT algorithms
{ //
xrander ^= xrander << shift1;
xrander ^= xrander >> shift2;
xrander ^= xrander << shift3;
trander = xrander;
xrander = yrander;
yrander = zrander;
zrander = trander ^ xrander ^ yrander;
return float (zrander)/4294967295;
}
inline float Fast_Sign(float f)
{
float r = 1.0f;
(int&)r |= ((int&)f & 0x80000000);
return r;
}
double High_ATanH(double x)
{
return (log(1 + x) - log(1 - x)) / 2;
}
double High_ACosH(double x)
{
return log(x + sqrt(x + 1) * sqrt(x - 1));
}
double High_ASinH(double x)
{
return log(x + sqrt(x * x + 1));
}
double High_ASecH(double x)
{
double xz = 1 / x;
return log(sqrt(xz - 1) * sqrt(xz + 1) + xz);
}
double High_ACscH(double x)
{
return log(sqrt(1 + 1 / (x * x)) + 1 / x);
}
double High_ACotH(double x)
{
double xz = 1 / x;
return (log(1 + xz) - log(1 - xz)) / 2;
}
inline float High_Sign(float f)
{
//this may or may not be used in QB64 in the future
if (((int&)f & 0x7FFFFFFF)## 0)
{
return 0.0f;
}
else
{
float r = 1.0f;
(int&)r |= ((int&)f & 0x80000000);
return r;
}
}
int Misc_TrailZCount(unsigned int v)
{
//unsigned int v; // 32-bit word input to count zero bits on right
unsigned int c; // c will be the number of zero bits on the right,
// so if v is 1101000 (base 2), then c will be 3
// NOTE: if 0 ## v, then c = 31.
if (v & 0x1)
{
// special case for odd v (assumed to happen half of the time)
c = 0;
}
else
{
c = 1;
if ((v & 0xffff) ## 0)
{
v >>= 16;
c += 16;
}
if ((v & 0xff) ## 0)
{
v >>= 8;
c += 8;
}
if ((v & 0xf) ## 0)
{
v >>= 4;
c += 4;
}
if ((v & 0x3) ## 0)
{
v >>= 2;
c += 2;
}
c -= v & 0x1;
}
return c;
}
int Misc_Parity(int v)// is the number of 1 bits odd? true if so
{
//unsigned int v; // 32-bit word
v ^= v >> 1;
v ^= v >> 2;
v = (v & 0x11111111U) * 0x11111111U;
return (v >> 28) & 1;
}
int Misc_BitSet(int v)
//u//nsigned int v; // count the number of bits set in v
{
unsigned int c; // c accumulates the total bits set in v
for (c = 0; v; c++)
{
v &= v - 1; // clear the least significant bit set
}
return c;
}
long Misc_FloatToLong(float y) //1132462080
{
return * ( long * ) &y;
}
float Misc_LongToFloat(long y)
{
return * ( float * ) &y;
}
long Misc_UnSetRMBit(long x)
{
return x & (x - 1);
}
```
<sub>Library created by DarthWho</sub>
**[Latest Fast Math Update](http://dl.dropbox.com/u/12359848/fastmath.h)**
Using **trailzcount** to speed up the process of finding the prime factors of a number.
```vb
DECLARE LIBRARY "fastmath"
FUNCTION TrailZCount% ALIAS Misc_TrailZCount (BYVAL vals AS LONG)
END DECLARE
INPUT "enter a number: ", xt&
tabs = TrailZCount%(xt&)
PRINT "the prime factors of"; xt&; " are:";
IF tabs THEN
FOR i = 1 TO tabs
PRINT 2;
NEXT i
END IF
x& = xt& / (2 ^ tabs)
c& = 3
WHILE c& <= x&
WHILE x& MOD c& = 0
x& = x& / c&
PRINT c&;
WEND
c& = c& + 1
WEND
PRINT
```
Using **parity** to detect single bit errors simulated using **unsetrmbit**.
```vb
'parity checking code which may be used in order to detect a download error:
'will also use the bitset function to simulate a download error .bitset unsets the lowest set bit
'parity checking code which may be used in order to detect a download error:
'will also use the bitset function to simulate a download error .bitset unsets the lowest set bit
DECLARE LIBRARY "fastmath"
FUNCTION parity& ALIAS Misc_Parity (BYVAL val AS LONG)
FUNCTION unsetrmbit& ALIAS Misc_UnSetRMBit (BYVAL vals AS LONG)
END DECLARE
TYPE DLDATA
par AS _BIT
dataa AS LONG
END TYPE
DIM values(1) 'here is where the data is created
g& = 8
h& = 9
values.par(0) = parity&(g&)
values.dataa(0) = g&
values.par(1) = parity&(h&)
values.dataa(1) = h& 'transfer and error in values.dataa(1)
values.dataa(1) = unsetrmbit&(values.dataa(1)) 'checking for single bit errors in download
FOR i = 0 TO 1
IF values.par(i) = parity&(values.dataa(i)) THEN
PRINT "no single bit errors detected in in data packet"; i
ELSE
PRINT "error found in data packet"; i
END IF
NEXT
```
## See Also
* [DECLARE LIBRARY](DECLARE-LIBRARY), [BYVAL](BYVAL)
* [_OFFSET](_OFFSET), [_OFFSET (function)](_OFFSET-(function)) (lp, ptr and p names)
* [DLL Libraries](DLL-Libraries), [Windows Libraries](Windows-Libraries)
* [Libraries](Libraries)

22
wiki/CALL-ABSOLUTE.md Normal file
View file

@ -0,0 +1,22 @@
[CALL ABSOLUTE](CALL-ABSOLUTE) is used to access interrupts on the computer or execute assembly type procedures.
## Syntax
> [CALL ABSOLUTE](CALL-ABSOLUTE)([argumentList,] integerOffset)
## Legacy Support
* [CALL ABSOLUTE](CALL-ABSOLUTE) is implemented to support older code and is not recommended practice. To handle mouse input, the **use [_MOUSEINPUT](_MOUSEINPUT) and related functions**.
## Description
* [CALL](CALL) and parameter brackets are required in the statement.
* argumentList contains the list of arguments passed to the procedure.
* integerOffset contains the offset from the current code segment, set by [DEF SEG](DEF-SEG) and [SADD](SADD), to the starting location of the called procedure.
* **QB64** has the ABSOLUTE statement built in and requires no external library, like QuickBASIC did.
* **NOTE: QB64 does not support INT 33h mouse functions above 3 or [BYVAL](BYVAL) in an ABSOLUTE statement. Registers are emulated.**
## See Also
* [SADD](SADD), [INTERRUPT](INTERRUPT)
* [_MOUSEINPUT](_MOUSEINPUT)

62
wiki/CALL.md Normal file
View file

@ -0,0 +1,62 @@
[CALL](CALL) sends code execution to a subroutine procedure in a program. In **QB64** the subroutine doesn't need to be declared.
## Syntax
> [CALL](CALL) ProcedureName (parameter1, parameter2,...)]
### Alternative Syntax
> ProcedureName parameter1, parameter2,...]
* CALL requires [SUB](SUB) program parameters to be enclosed in brackets (parenthesis).
* CALL is not required to call a subprocedure. Use the SUB-procedure name and list any parameters without parenthesis.
* Neither syntax can be used to call [GOSUB](GOSUB) linelabel sub procedures.
* To pass parameters by value, instead of by reference, enclose passed variables in parenthesis.
## Example(s)
How parameters are passed in two [SUB](SUB) calls, one with CALL using brackets and one without CALL or brackets:
```vb
DIM a AS INTEGER 'value not shared with SUB
DIM SHARED b AS INTEGER 'value shared with any SUB
a = 1
b = 2
c = 3
CALL helloworld (a) 'a passed to c parameter with CALL
helloworld a 'a passed to c parameter w/o CALL
END
SUB helloworld (c) 'SUB parameter variables are always inside of brackets in SUB code
PRINT "Hello World!"
PRINT a, b, c
a = a + 1 'a is a SUB value of 0 when printed which may increase inside SUB only
b = b + 1 'b is a shared value which can increase anywhere
c = c + 1 'c is a SUB parameter value from a in calls which may increase inside SUB only
END SUB
```
*Returns:*
```text
Hello World!
0 2 1
Hello World!
0 3 1
```
> *Explanation:* Variable **a** that is outside of the subroutine isn't [SHARED](SHARED) so it will have no effect inside the subroutine, the variable a inside the subroutine is only valid inside the subroutine, and whatever value a has outside of it makes no difference within the subroutine.
> The variable **b** on the other hand is [SHARED](SHARED) with the subroutines and thus can be changed in the subroutine. The variable a is initiated with 0 as default when created, thus it will return 0 since it wasn't changed within the subroutine.
> The variable **c** is the [SUB](SUB) parameter variable that passes values into the sub. Its value could be changed by the passed parameter value or inside of the subroutine. The un-shared **c** variable value outside of the sub is irrelevant within the subroutine.
## See Also
* [SUB](SUB), [FUNCTION](FUNCTION)

1
wiki/CALLS.md Normal file
View file

@ -0,0 +1 @@
See [CALL](CALL).

56
wiki/CASE-ELSE.md Normal file
View file

@ -0,0 +1,56 @@
See [SELECT CASE](SELECT-CASE).
[CASE ELSE](CASE-ELSE) is used in a [SELECT CASE](SELECT-CASE) procedure as an alternative if no other [CASE](CASE) statements are true.
## Description
* [CASE ELSE](CASE-ELSE) should be listed at the bottom of the case list as it will supersede any case statements after it.
* Use it as a "safety net" or as an alternative for all values not covered in the [CASE](CASE) statements.
## Example(s)
```vb
a = 100
SELECT CASE a
CASE IS < 99: PRINT "a is < 99"
CASE 99: PRINT "a is 99"
CASE IS > 100: PRINT "a is > 100"
CASE ELSE
PRINT "a is 100"
END SELECT
```
```text
a is 100
```
```vb
a = 100
SELECT CASE a
CASE 10: PRINT "a is 10"
CASE 20: PRINT "a is 20"
CASE 30: PRINT "a is 30"
CASE ELSE: PRINT "a is something other than 10, 20 and 30"
END SELECT
```
```text
a is something other than 10, 20 and 30
```
## See Also
* [SELECT CASE](SELECT-CASE)
* [IF...THEN](IF...THEN), [ELSE](ELSE)

32
wiki/CASE-IS.md Normal file
View file

@ -0,0 +1,32 @@
See [SELECT CASE](SELECT-CASE).
[CASE IS](CASE-IS) can be used in a [SELECT CASE](SELECT-CASE) routine where you need to use relational conditional expressions.
## Syntax
> [CASE IS](CASE-IS) **{=|<|>|<=|>=|<>|[NOT](NOT)} expression**
## Description
* [AND (boolean)](AND-(boolean)) can be used to add extra conditions to a [CASE IS](CASE-IS) statement evaluation.
* [OR (boolean)](OR-(boolean)) can be used to add alternate conditions to a [CASE IS](CASE-IS) statement evaluation.
* Parenthesis are allowed in [CASE IS](CASE-IS) statements to clarify an evaluation.
* [CASE IS](CASE-IS) > 100 uses the greater than expression.
* [CASE IS](CASE-IS) <= 100 uses the less than or equal to expression.
* [CASE IS](CASE-IS) <> 100 uses the not equal to expression(same as [NOT](NOT) 100).
**Relational Operators:**
| Symbol | Condition | Example Usage |
| -- | -- | -- |
| = | Equal | IF a = b THEN |
| <> | NOT equal | IF a <> b THEN |
| < | Less than | IF a < b THEN |
| > | Greater than | IF a > b THEN |
| <= | Less than or equal | IF a <= b THEN |
| >= | Greater than or equal | IF a >= b THEN |
## See Also
* [CASE](CASE), [CASE ELSE](CASE-ELSE)
* [SELECT CASE](SELECT-CASE)

68
wiki/CASE.md Normal file
View file

@ -0,0 +1,68 @@
See [SELECT CASE](SELECT-CASE).
[CASE](CASE) is used within a [SELECT CASE](SELECT-CASE) block to specify a conditional value of the compared variable.
## Syntax
> [CASE](CASE) comparisonValues[:] {code}
## Description
*comparisonValues can be any literal string or number, depending on the value specified in the [SELECT CASE](SELECT-CASE) statement.
*Code is executed until the next case, so each case can handle multiple lines of code.
* [CASE](CASE) conditions are normally listed in some logical order going down the page.
* [CASE](CASE) order can affect the SELECT CASE code execution when more than one CASE can be true. This is specially true when multiple conditional operators, CASE IS or TO ranges are used.
* [CASE](CASE) lists can also be listed horizontally by using colon separators between cases.
* Supports individual CASE values and ranges or lists of values as below:
* [CASE](CASE) value
* [CASE](CASE) value1 [TO](TO) value2
* [CASE](CASE) value1, value2, value3
* [CASE IS](CASE-IS) value1 > value2
* [CASE ELSE](CASE-ELSE)
* The first time a [CASE](CASE) value matches the compared variable's value, that [CASE](CASE) code is executed and [SELECT CASE](SELECT-CASE) is exited, unless **EVERYCASE** is used.
## Example(s)
```vb
a = 100
SELECT CASE a
CASE 1, 3, 5, 7, 9: PRINT "Odd values under 10 will be shown."
CASE 10: PRINT "10 will be shown."
CASE 50: PRINT "50 will be shown."
CASE 100: PRINT "This will be shown. (a is 100)"
PRINT "(and this)"
CASE 150: PRINT "150 will be shown."
CASE IS < 150: PRINT "Less than 150 will be shown. (a which is 100 is under 150)"
CASE 50 TO 150: PRINT "50 to 150 will be shown. (a which is 100 is between 50 TO 150)"
END SELECT
```
*Returns:*
```text
This will be shown. (a is 100)
(and this)
```
> *Explanation:* [SELECT CASE](SELECT-CASE) compares the variable's value to each descending CASE until ONE is true, executes the [CASE](CASE) code and exits the SELECT CASE. [CASE](CASE) statements should be placed in a increasing or decreasing order for the best results.
> What happens is that since 5 isn't 100 then the code until the next CASE is ignored, the same obviously goes for 10 and 50 but then comes 100 which is what a is so the code in that [CASE](CASE) is executed.
* A [CASE](CASE) can list several values separated by commas for the same program option to be executed.
* [CASE IS](CASE-IS) is used when we need to compare the value to a conditional expression range such as a value is "=" equal to, "<" less than, ">" greater than, "<>" not equal to or [NOT](NOT) a value.
* A [CASE](CASE) range can be specified (in the example; 50 [TO](TO) 150) if needed.
*Note:* A [SELECT CASE](SELECT-CASE) block has to end with [END SELECT](END-SELECT).
## See Also
* [CASE ELSE](CASE-ELSE), [CASE IS](CASE-IS)
* [SELECT CASE](SELECT-CASE), [END SELECT](END-SELECT)
* [IF...THEN](IF...THEN)

38
wiki/CDBL.md Normal file
View file

@ -0,0 +1,38 @@
[CDBL](CDBL) converts a value to the closest [DOUBLE](DOUBLE)-precision value.
## Syntax
> doubleValue# = [CDBL](CDBL)(expression)
## Parameter(s)
* expression is any [TYPE](TYPE) of literal or variable numerical value or mathematical calculation.
## Description
* Rounds to the closest [DOUBLE](DOUBLE) floating decimal point value.
* Also can be used to define a value as [DOUBLE](DOUBLE)-precision up to 15 decimals.
## Example(s)
Prints a double-precision version of the single-precision value stored in the variable named A.
```vb
A = 454.67
PRINT A; CDBL(A)
```
```text
454.67 454.6700134277344
```
> The last 11 numbers in the double-precision number change the value in this example, since A was previously defined to only two-decimal place accuracy.
## See Also
* [CINT](CINT), [CLNG](CLNG)
* [CSNG](CSNG), [_ROUND](_ROUND)

42
wiki/CHAIN.md Normal file
View file

@ -0,0 +1,42 @@
[CHAIN](CHAIN) is used to change seamlessly from one module to another one in a program.
## Legacy Support
* The multi-modular technique goes back to when QBasic and QuickBASIC had module size constraints. In QB64 [CHAIN](CHAIN) has been implemented so that that older code can still be compiled, though **it is advisable to use single modules for a single project (not counting [$INCLUDE]($INCLUDE) libraries), for ease of sharing and also because the module size constraints no longer exist.**
## Syntax
> [CHAIN](CHAIN) moduleName$
## Parameter(s)
* moduleName$ is a variable or a literal [STRING](STRING) value in quotation marks with the optional EXE or BAS file name extension.
## Description
* CHAIN requires that both the invoking and called modules are of either .BAS or .EXE file types.
* In Windows, **QB64** will automatically compile a CHAIN referenced BAS file if there is no EXE file found.
* CHAIN looks for a file extension that is the same as the invoking module's extension.
* The module's filename extension is not required. To save editing at compile time just omit the extensions in the calls.
* To pass data from one module to the other use [COMMON SHARED](COMMON-SHARED). The COMMON list should match [Variable Types](Variable-Types)s and names.
* **QB64 does not retain the [SCREEN](SCREEN) mode like QBasic did.**
* Variable data can be passed in files instead of using [COMMON SHARED](COMMON-SHARED) values. **QB64** uses files to pass [COMMON](COMMON) lists.
* [Keywords currently not supported](Keywords-currently-not-supported-by-QB64)**.
## Example(s)
CHAIN looks for same file type extension as program module (BAS or EXE).
```vb
CHAIN "Level1"
```
*Explanation:* The file referred to is "Level1.BAS" if the program module using the call is a BAS file. If the program was compiled, it would look for "Level1.EXE".
## See Also
* [RUN](RUN)
* [COMMON](COMMON), [COMMON SHARED](COMMON-SHARED)
* [SHARED](SHARED)

66
wiki/CHDIR.md Normal file
View file

@ -0,0 +1,66 @@
The [CHDIR](CHDIR) statement changes the program's location from one working directory to another by specifying a literal or variable [STRING](STRING) path.
## Syntax
> [CHDIR](CHDIR) path$
## Description
* path$ is the new directory path the program will work in.
* path$ can be an absolute path (starting from the root folder) or relative path (starting from the current program location).
* If path$ specifies a non-existing path, a [ERROR Codes](ERROR-Codes) error will occur.
* **A QB64 [SHELL](SHELL) statement cannot use "CD " or "CHDIR " + path$ to change directories.**
## Example(s)
The following code is Windows-specific:
```vb
CHDIR "C:\" 'change to the root drive C (absolute path)
CHDIR "DOCUME~1" 'change to "C:\Documents and Settings" from root drive (relative path)
CHDIR "..\" 'change back to previous folder one up
```
> *Details:* **QB64** can use long or short (8.3 notation) file and path names.
Using the Windows API to find the current program's name and root path. The PATH$ is a shared function value.
```vb
_TITLE "My program"
PRINT TITLE$
PRINT PATH$
FUNCTION TITLE$ *=== SHOW CURRENT PROGRAM
SHARED PATH$ 'optional path information shared with main module only
DECLARE LIBRARY 'Directory Information using KERNEL32 provided by Dav
FUNCTION GetModuleFileNameA (BYVAL Module AS LONG, FileName AS STRING, BYVAL nSize AS LONG)
END DECLARE
FileName$ = SPACE$(256)
Result = GetModuleFileNameA(0, FileName$, LEN(FileName$)) '0 designates the current program
IF Result THEN 'Result returns the length or bytes of the string information
PATH$ = LEFT$(FileName$, Result)
start = 1
DO
posit = INSTR(start, PATH$, "\")
IF posit THEN last = posit
start = posit + 1
LOOP UNTIL posit = 0
TITLE$ = MID$(PATH$, last + 1)
PATH$ = LEFT$(PATH$, last)
ELSE TITLE$ = "": PATH$ = ""
END IF
END FUNCTION
```
> **Note:** The program's [_TITLE](_TITLE) name may be different from the actual program module's file name returned by Windows.
## See Also
* [SHELL](SHELL), [FILES](FILES)
* [MKDIR](MKDIR), [RMDIR](RMDIR)
* [$CONSOLE]($CONSOLE)

103
wiki/CHR$.md Normal file
View file

@ -0,0 +1,103 @@
The [CHR$](CHR$) function returns the character associated with a certain [ASCII](ASCII) as a [STRING](STRING).
## Syntax
> result$ = [CHR$](CHR$)(code%)
## Description
* Valid ASCII code% numbers range from 0 to 255.
* The character code of a character can be found using [ASC](ASC).
* Some control codes below 32 will not [PRINT](PRINT) or will move the screen cursor, unless [_CONTROLCHR](_CONTROLCHR) is used.
## Example(s)
Outputs the characters of several character codes:
```vb
PRINT CHR$(65); CHR$(65 + 32)
PRINT CHR$(66); CHR$(66 + 32)
```
```text
Aa
Bb
```
> Explanation: 65 is the ASCII code for "A" and 65 + 32 is the ASCII code for "a". 66 is the ASCII code for "B" and 66 + 32 is the ASCII code for "b"
To cut down on typing CHR$(???) all day, define often used characters as variables such as Q$ = CHR$(34) as shown.
```vb
DIM Q AS STRING * 1 'define as one byte string(get rid of $ type suffix too)
Q = CHR$(34) 'Q will now represent the elusive quotation mark in a string
PRINT "This text uses "; Q; "quotation marks"; Q; " that could have caused a syntax error!"
```
```text
This text uses "quotation marks" that could have caused a syntax error!
```
Using [ASC](ASC) and [CHR$](CHR$) to *encrypt* a text file size up to 32K bytes
```vb
OPEN FileName$ FOR INPUT AS #1 ' FileName to be encrypted
IF LOF(1) <= 32000 THEN Text$ = INPUT$(LOF(1), 1) ' get Text as one string
CLOSE #1
Send$ = "" ' clear value
FOR i = 1 TO LEN(Text$)
Letter$ = MID$(Text$, i, 1) ' get each character in the text
Code = ASC(Letter$)
IF (Code > 64 AND Code < 91) OR (Code > 96 AND Code < 123) THEN
Letter$ = CHR$(Code + 130) ' change letter's ASCII character by 130
END IF
Send$ = Send$ + Letter$ ' reassemble string with just letters encrypted
NEXT i
OPEN FileName$ FOR OUTPUT AS #1 ' erase FileName to be encrypted
PRINT #1, Send$ ' Text as one string
CLOSE #1
```
> *Warning: The routine above will change an original text file to be unreadable. Use a second file name to preserve the original file.*
*Example 4:'Decrypting** the above encrypted text file (32K byte file size limit).
```vb
OPEN FileName$ FOR INPUT AS #1 ' FileName to be decrypted
Text$ = INPUT$(LOF(1), 1) ' open Text as one string
CLOSE #1
Send$ = ""
FOR i = 1 TO LEN(Text$)
Letter$ = MID$(Text$, i, 1)
Code = ASC(Letter$)
IF (Code > 194 AND Code < 221) OR (Code > 226 AND Code < 253) THEN
Letter$ = CHR$(Code - 130) ' change back to a Letter character
END IF
Send$ = Send$ + Letter$ ' reassemble string as normal letters
NEXT i
OPEN FileName$ FOR OUTPUT AS #1 ' Erase file for decrypted text
PRINT #1, Send$ ' place Text as one string
CLOSE #1
```
> *Explanation:* Examples 3 and 4 encrypt and decrypt a file up to 32 thousand bytes. [INPUT$](INPUT$) can only get strings less than 32767 characters. The upper and lower case letter characters are the only ones altered, but the encryption and decryption rely on the fact that most text files do not use the code characters above 193. You could alter any character from ASCII 32 to 125 without problems using the 130 adder. No [ASCII](ASCII) code above 255 is allowed. Don't alter the codes below code 32 as they are control characters. Specifically, characters 13 and 10 (CrLf) may be used for line returns in text files.
## See Also
* [ASC](ASC), [ASC (statement)](ASC-(statement))
* [INKEY$](INKEY$)
* [ASCII](ASCII)

39
wiki/CINT.md Normal file
View file

@ -0,0 +1,39 @@
The [CINT](CINT) function rounds decimal point numbers up or down to the nearest [INTEGER](INTEGER) value.
## Syntax
> value% = [CINT](CINT)(expression)
## Parameter(s)
* expression is any [TYPE](TYPE) of literal or variable numerical value or mathematical calculation.
## Description
* Values greater than .5 are rounded up. Values lower than .5 are rounded down.
* *Warning:* Since [CINT](CINT) is used for integer values, the input values cannot exceed 32767 to -32768!
* Use [CLNG](CLNG) for [LONG](LONG) integer values exceeding [INTEGER](INTEGER) limitations.
* Note: When decimal point values are given to BASIC functions requiring [INTEGER](INTEGER)s the value will be [CINT](CINT)ed.
## Example(s)
Shows how CINT rounds values up or down as in "bankers' rounding".
```vb
a% = CINT(1.49): b% = CINT(1.50): c = 11.5
COLOR c: PRINT a%, b%, c
```
```text
1 2 11.5
```
## See Also
* [_ROUND](_ROUND), [_CEIL](_CEIL)
* [CLNG](CLNG), [CSNG](CSNG), [CDBL](CDBL)
* [INT](INT), [FIX](FIX)

148
wiki/CIRCLE.md Normal file
View file

@ -0,0 +1,148 @@
The [CIRCLE](CIRCLE) statement is used in graphic [SCREEN (statement)](SCREEN-(statement)) modes to create circles, arcs or ellipses.
## Syntax
> [CIRCLE](CIRCLE) [STEP]**(**column**,** row**),** radius%**,** [drawColor%][, startRadian!, stopRadian!] [, aspect!]
## Parameter(s)
* Can use [STEP](STEP) for relative coordinate moves from the previous graphic coordinates.
* Coordinates designate the center position of the circle. Can be partially drawn offscreen.
* radius% is an [INTEGER](INTEGER) value for half of the total circle diameter.
* drawColor% is any available color attribute in the [SCREEN (statement)](SCREEN-(statement)) mode used.
* startRadian! and stopRadian! can be any [SINGLE](SINGLE) value from 0 to 2 * &pi; to create partial circles or ellipses.
* aspect! [SINGLE](SINGLE) values of 0 to 1 affect the vertical height and values over 1 affect the horizontal width of an ellipse. Aspect = 1 is a normal circle.
## Description
* When using aspect! the startRadian! and stopRadian! commas must be included even if not used.
* Radians move in a counter clockwise direction from 0 to 2 * &pi;. Zero and 2 * &pi; are the same circle radian at 3 o'clock.
* Negative radian values can be used to draw lines from the end of an arc or partial ellipse to the circle center.
* Commas after the drawColor% parameter are not required when creating a normal circle. drawColor% can also be omitted to use the last color used in a draw statement.
* The graphic cursor is set to the center of the program window on program start for [STEP](STEP) relative coordinates.
* **CIRCLE can be used in any graphic screen mode, but cannot be used in the default screen mode 0 as it is text only.**
## Example(s)
Finding when the mouse is inside of a circular area:
```vb
SCREEN 12
r& = 200 'radius change circle size and position here
cx& = 320 'center x horizontal
cy& = 240 'center y vertical
DO
i = _MOUSEINPUT
x& = _MOUSEX
y& = _MOUSEY
xy& = ((x& - cx&) ^ 2) + ((y& - cy&) ^ 2) 'Pythagorean theorem
IF r& ^ 2 >= xy& THEN CIRCLE (cx&, cy&), r&, 10 ELSE CIRCLE (cx&, cy&), r&, 12
LOOP UNTIL INKEY$ = CHR$(27) 'escape key exit
```
> *Explanation:* The square of the circle radius will be greater than or equal to the sum of the square of the mouse coordinates minus the center position when the pointer is inside of the circle. In this example the circle color will change from red to green.
Program illustrates how the CIRCLE command using a negative radian value can be used to create the hands of a clock.
```vb
CONST PI = 3.141593 'The mathematical value of PI to six places. You can also use QB64's native _PI.
DIM clock(60) 'A dimensioned array to hold 60 radian points
clockcount% = 15 'A counter to keep track of the radians
'* Start at radian 2*PI and continue clockwise to radian 0
'* Since radian 2*PI points directly right, we need to start clockcount%
'* at 15 (for 15 seconds). The FOR/NEXT loop counts backwards in increments
'* of 60 giving us the 60 second clock points. These points are then stored
'* in the dimensioned array clock() to be used later.
'*
FOR radian = 2 * PI TO 0 STEP -(2 * PI) / 60
clock(clockcount%) = radian
clockcount% = clockcount% + 1
IF clockcount% = 61 THEN clockcount% = 1
NEXT radian
'* Change to a graphics screen and draw the clock face
SCREEN 7
CLS
LOCATE 1, 1
COLOR 14, 0
PRINT "Ritchie's Clock"
COLOR 9, 0
PRINT "Uses CIRCLE to"
PRINT "draw hands!"
COLOR 8, 0
CIRCLE (160, 100), 110, 8 'circle with radius of 110 and dark gray
CIRCLE (160, 100), 102, 8 'circle with radius of 102 and dark gray
PAINT (265, 100), 8, 8 'fill between the two dark gray circles with gray
CIRCLE (160, 100), 110, 7 'circle with radius of 110 and light gray
'*
'* Get the current time from the QuickBASIC built in variable TIME$
'* Since TIME$ is a string, we need to extract the hours, minutes and
'* seconds from it using LEFT$, RIGHT$ and MID$. Then, each of these
'* extractions need to be converted to a numeric value using VAL and
'* stored in their respective variables.
'*
seconds% = INT(VAL(RIGHT$(TIME$, 2))) 'extract seconds from TIME$
IF seconds% = 0 THEN seconds% = 60 'array counts 1 to 60 not 0 to 59
previoussecond% = seconds% 'hold current second for later use
minutes% = INT(VAL(MID$(TIME$, 4, 2))) 'extract minutes from TIME$
IF minutes% = 0 THEN minutes% = 60 'array counts 1 to 60 not 0 to 59
previousminute% = minutes% 'hold current minute for later use
hours% = INT(VAL(LEFT$(TIME$, 2))) 'extract hour from TIME$
IF hours% >= 12 THEN hours% = hours% - 12 'convert from military time
IF hours% = 0 THEN hours% = 12 'count from 1 to 12 not 0 to 11
previoushour% = hours% 'hold current hour for later use
'*
'* Start of main program loop
'*
DO
IF seconds% <> previoussecond% THEN 'has a second elapsed?
LOCATE 22, 17 'print the time on the screen at
PRINT TIME$; 'position 22, 17
'* Since a second has elapsed we need to erase the old second hand
'* position and draw the new position
CIRCLE (160, 100), 100, 0, -clock(previoussecond%), clock(previoussecond%)
CIRCLE (160, 100), 100, 15, -clock(seconds%), clock(seconds%)
previoussecond% = seconds% 'hold current second for later use
IF minutes% <> previousminute% THEN 'has a minute elapsed?
'* Since a minute has elapsed we need to erase the old hour hand position
CIRCLE (160, 100), 90, 0, -clock(previousminute%), clock(previousminute%)
previousminute% = minutes% 'hold current minute for later use
END IF
'*
'* Draw the current minute hand position
'*
CIRCLE (160, 100), 90, 14, -clock(minutes%), clock(minutes%)
IF hours% <> previoushour% THEN 'has an hour elapsed?
'* Since an hour has elapsed we need to erase the old hour hand position
CIRCLE (160, 100), 75, 0, -clock(previoushour% * 5), clock(previoushour% * 5)
previoushour% = hours% 'hold current hour for later use
END IF
'*
'* Draw the current hour hand position
'*
CIRCLE (160, 100), 75, 12, -clock(hours% * 5), clock(hours% * 5)
END IF
seconds% = VAL(RIGHT$(TIME$, 2)) 'extract time again and do all over
IF seconds% = 0 THEN seconds% = 60
minutes% = VAL(MID$(TIME$, 4, 2))
IF minutes% = 0 THEN minutes% = 60
hours% = VAL(LEFT$(TIME$, 2))
IF hours% >= 12 THEN hours% = hours% - 12
IF hours% = 0 THEN hours% = 12
LOOP UNTIL INKEY$ <> "" 'stop program if user presses a key
```
## See Also
* [STEP](STEP), [DRAW](DRAW)
* [LINE](LINE), [PSET](PSET), [PRESET](PRESET)
* [SCREEN](SCREEN), [SCREEN (function)](SCREEN-(function))
* [Alternative circle routine](Alternative-circle-routine) (member-contributed program)

39
wiki/CLEAR.md Normal file
View file

@ -0,0 +1,39 @@
The [CLEAR](CLEAR) statement clears all variable and array element values in a program.
## Syntax
> [CLEAR](CLEAR) [, ignored& , ignored&]
## Description
* All parameters are optional and ignored by **QB64**.
* Normally used to clear all program variable and [Arrays](Arrays) values where numerical values become zero and string values become empty ("").
* It does not clear [CONST](CONST) values.
* Closes all opened files.
* [$DYNAMIC]($DYNAMIC) or [REDIM](REDIM) arrays will need to be [REDIM](REDIM) or an [ERROR Codes](ERROR-Codes) will occur when referenced because they are removed.
## Example(s)
Using CLEAR to clear array elements from [STATIC](STATIC) arrays or arrays created using [DIM](DIM).
```vb
CLS
DIM array(10) 'create a $STATIC array
array(5) = 23
PRINT array(5)
CLEAR
PRINT array(5)
```
> *Note:* If you change DIM to REDIM a "Subscript out of range" error will occur because a [$DYNAMIC]($DYNAMIC) array is removed by CLEAR.
## See Also
* [ERASE](ERASE)
* [REDIM](REDIM), [_PRESERVE](_PRESERVE)
* [Arrays](Arrays), [&B](&B)

37
wiki/CLNG.md Normal file
View file

@ -0,0 +1,37 @@
The [CLNG](CLNG) function rounds decimal point numbers up or down to the nearest [LONG](LONG) integer value.
## Syntax
> value& = [CLNG](CLNG)(expression)
## Parameter(s)
* expression is any [TYPE](TYPE) of literal or variable numerical value or mathematical calculation.
## Description
* Used when integer values exceed 32767 or are less than -32768.
* Values greater than .5 are rounded up; .5 or lower are rounded down.
* CLNG can return normal [INTEGER](INTEGER) values under 32768 too.
* Use it when a number could exceed normal [INTEGER](INTEGER) number limits.
## Example(s)
```vb
a& = CLNG(2345678.51)
PRINT
```
```text
2345679
```
## See Also
* [CINT](CINT), [INT](INT)
* [CSNG](CSNG), [CDBL](CDBL)
* [_ROUND](_ROUND)

26
wiki/CLOSE.md Normal file
View file

@ -0,0 +1,26 @@
[CLOSE](CLOSE) closes an open file or port using the number(s) assigned in an [OPEN](OPEN) statement.
## Syntax
> [CLOSE](CLOSE) [fileNumber[, ...]]
## Parameter(s)
* fileNumber indicates the file or list of file numbers to close. When not specified, all open files are closed.
## Description
* A file must be closed when changing to another file mode.
* [CLOSE](CLOSE) files when they are no longer needed, in order to save memory.
* Files cannot be opened in the same [OPEN](OPEN) mode using another number until the first one is closed.
* Use holding variables for each file number returned by [FREEFILE](FREEFILE) so that the file reference is known.
* Will not return an error if a filenumber is already closed or was never opened. It does not verify that a file was closed.
* [CLEAR](CLEAR) can be used to close all open files.
* [CLOSE](CLOSE) can also be used to close an open TCP/IP connection using a handle returned by **QB64**.
## See Also
* [OPEN](OPEN), [OPEN COM](OPEN-COM)
* [_OPENCLIENT](_OPENCLIENT), [_OPENHOST](_OPENHOST)
* [_OPENCONNECTION](_OPENCONNECTION)
* [_SNDCLOSE](_SNDCLOSE)

61
wiki/CLS.md Normal file
View file

@ -0,0 +1,61 @@
The [CLS](CLS) statement clears the [_DEST](_DEST).
## Syntax
> [CLS](CLS) [method%] [, bgColor&]
## Parameter(s)
* method% specifies which parts of the page to clear, and can have one of the following values:
* CLS - clears the active graphics or text viewport or the entire text screen and refreshes bottom function [KEY LIST](KEY-LIST) line.
* CLS 0 - Clears the entire page of text and graphics. Print cursor is moved to row 1 at column 1.
* CLS 1 - Clears only the graphics view port. Has no effect for text mode.
* CLS 2 - Clears only the text view port. The print cursor is moved to the top row of the text view port at column 1.
* The bgColor& specifies the color attribute or palette index to use when clearing the screen in **QB64**.
## Description
* In legacy [SCREEN](SCREEN) modes bgColor& specifies the color attribute of the background.
* For 32-bit graphics mode, bgColor& specifies the [_RGB](_RGB) or [_RGBA](_RGBA) color to use.
* **32-bit screen surface backgrounds (black) have zero [_ALPHA](_ALPHA) so that they are transparent when placed over other surfaces.**
* Use [CLS](CLS) or [_DONTBLEND](_DONTBLEND) to make a new surface background [_ALPHA](_ALPHA) 255 or opaque.
* If not specified, bgColor& is assumed to be the current background color. 32-bit backgrounds will change to opaque.
* If bgColor& is not a valid attribute, an [ERROR Codes](ERROR-Codes) error will occur.
* Use [_PRINTMODE](_PRINTMODE) to allow the background colors to be visible through the text or the text background.
## Example(s)
Printing black text on a white background in QB64.
```vb
SCREEN 12
CLS , 15
_PRINTMODE _KEEPBACKGROUND 'keeps the text background visible
COLOR 0: PRINT "This is black text on a white background!"
K$ = INPUT$(1)
```
> *Explanation:* [_PRINTMODE](_PRINTMODE) can be used with [PRINT](PRINT) or [_PRINTSTRING](_PRINTSTRING) to make the text or the text background transparent.
You don't need to do anything special to use a .PNG image with alpha/transparency. Here's a simple example:
```vb
SCREEN _NEWIMAGE(640, 480, 32)
CLS , _RGB(0, 255, 0)
i = _LOADIMAGE(**"qb64_trans.png"**) 'see note below examples to get the image
_PUTIMAGE (0, 0), i 'places image at upper left corner of window w/o stretching it
```
> *Explanation:* When QB64 loads a .PNG file containing a transparent color, that color will be properly treated as transparent when _PUTIMAGE is used to put it onto another image. You can use a .PNG file containing transparency information in a 256-color screen mode in QB64. [CLS](CLS) sets the [_CLEARCOLOR](_CLEARCOLOR) setting using [_RGB](_RGB).
## See Also
* [SCREEN](SCREEN)
* [_RGB](_RGB), [_RGBA](_RGBA), [_RGB32](_RGB32), [_RGBA32](_RGBA32)
* [VIEW PRINT](VIEW-PRINT), [VIEW](VIEW)
* [_CLEARCOLOR](_CLEARCOLOR)

291
wiki/COLOR.md Normal file
View file

@ -0,0 +1,291 @@
The [COLOR](COLOR) statement is used to change the foreground and background colors for printing text.
## Syntax
> [COLOR](COLOR) [foreground&][, background&]
## Description
* background& colors are available in all QB64 color SCREEN modes.
* [SCREEN](SCREEN) mode 10 has only 3 white foreground attributes including flashing.
* To change the background& color only, use a comma and the desired color. Ex: [COLOR](COLOR) , background&
* Graphic drawing statements like [PSET](PSET), [PRESET](PRESET), [LINE](LINE), etc, also use the colors set by the [COLOR](COLOR) statement if no color is passed when they are called.
* The [$COLOR]($COLOR) metacommand adds named color constants for both text and 32-bit modes.
* [COLOR](COLOR) works when outputting text to [$CONSOLE]($CONSOLE).
* On macOS, colors in console mode will not match the VGA palette. See [https://en.wikipedia.org/wiki/ANSI_escape_code#8-bit 8-bit ANSI colors]
## Screen Mode Attributes
* **SCREEN 0** background& colors 0 to 7 can be changed each text character without affecting other text. Use [CLS](CLS) after a background color statement to create a fullscreen background color. 64 [DAC](DAC) hues with 16 high intensity blinking foreground (16 to 31) color attributes. See [_BLINK](_BLINK).
* See example 7 below for more SCREEN 0 background colors.
* **SCREEN 1** has **4 background color attributes**: 0 = black, 1 = blue, 2 = green, 3 = grey. White foreground color only.
* **SCREEN 2** is **monochrome** with white forecolor and black background.
* **SCREEN 7** can use 16 ([DAC](DAC)) colors with background colors. RGB settings can be changed in colors 0 to 7 using [_PALETTECOLOR](_PALETTECOLOR).
* **SCREEN 8** has 16 color attributes with 16 background colors.
* **SCREEN 9** can use up to 64 [DAC](DAC) color hues in 16 color attributes with background colors assigned to attribute 0 with a [_PALETTECOLOR](_PALETTECOLOR) swap. RGB settings can be changed in colors 0 to 5 and 7 using [_PALETTECOLOR](_PALETTECOLOR).
* **SCREEN 10** has **only 4 color attributes** with black background. COLOR 0 = black, 1 = grey, 2 = flash white and 3 = bright white.
* **SCREEN 11** is **monochrome** with white forecolor and a black background.
* **SCREEN 12** can use 16 color attributes with a black background. 256K possible RGB color hues. Background colors can be used with QB64.
* **SCREEN 13** can use 256 color attributes with a black background. 256K possible RGB hues.
* [PALETTE](PALETTE) swaps can be made in SCREEN 7 and 9 only. Those screens were [DAC](DAC) screen modes in QBasic.
* [_DEST](_DEST) can be used to set the destination page or image to color using **QB64**.
* [_DEFAULTCOLOR](_DEFAULTCOLOR) returns the current color being used on an image or screen page handle.
### 24/32-Bit colors using QB64
* Pixel color intensities for red, green, blue and alpha range from 0 to 255 when used with [_RGB](_RGB), [_RGBA](_RGBA), [_RGB32](_RGB32) and [RGBA32](RGBA32).
* Combined RGB function values returned are [LONG](LONG) values. **Blue intensity values may be cut off using [SINGLE](SINGLE) variables.**
* [_ALPHA](_ALPHA) transparency values can range from 0 as transparent up to 255 which is fully opaque.
* [_CLEARCOLOR](_CLEARCOLOR) can also be used to set a color as transparent.
* Colors can be mixed by using [_BLEND](_BLEND) (default) in 32-bit screen modes. [_DONTBLEND](_DONTBLEND) disables blending.
* **NOTE: Default 32-bit backgrounds are clear black or [_RGBA](_RGBA)(0, 0, 0, 0). Use [CLS](CLS) to make the black opaque.**
## RGB Palette Intensities
RGB intensity values can be converted to hexadecimal values to create the [LONG](LONG) [_PALETTECOLOR](_PALETTECOLOR) value in non-32-bit screens:
```vb
SCREEN 12
alpha$ = "FF" 'solid alpha colors only
OUT &H3C8, 0: OUT &H3C9, 0: OUT &H3C9, 0: OUT &H3C9, 20 'set black background to dark blue
PRINT "Attribute = Hex value Red Green Blue "
PRINT
COLOR 7
FOR attribute = 0 TO 15
OUT &H3C7, attribute 'set color attribute to read
red$ = HEX$(INP(&H3C9) * 4) 'convert port setting to 32 bit values
grn$ = HEX$(INP(&H3C9) * 4)
blu$ = HEX$(INP(&H3C9) * 4)
IF LEN(red$) = 1 THEN red$ = "0" + red$ '2 hex digits required
IF LEN(grn$) = 1 THEN grn$ = "0" + grn$ 'for low or zero hex values
IF LEN(blu$) = 1 THEN blu$ = "0" + blu$
hex32$ = "&H" + alpha$ + red$ + grn$ + blu$
_PALETTECOLOR attribute, VAL(hex32$) 'VAL converts hex string to a LONG 32 bit value
IF attribute THEN COLOR attribute 'exclude black color print
PRINT "COLOR" + STR$(attribute) + " = " + hex32$, red$, grn$, blu$ 'returns closest attribute
NEXT
```
```text
Attribute Hex value Red Green Blue
COLOR 0 = &HFF000050 00 00 50
COLOR 1 = &HFF0000A8 00 00 A8
COLOR 2 = &HFF00A800 00 A8 00
COLOR 3 = &HFF00A8A8 00 A8 A8
COLOR 4 = &HFFA80000 A8 00 00
COLOR 5 = &HFFA800A8 A8 00 A8
COLOR 6 = &HFFA85400 A8 54 00
COLOR 7 = &HFFA8A8A8 A8 A8 A8
COLOR 8 = &HFF545454 54 54 54
COLOR 9 = &HFF5454FC 54 54 FC
COLOR 10 = &HFF54FC54 54 FC 54
COLOR 11 = &HFF5454FC 54 FC FC
COLOR 12 = &HFFFC5454 FC 54 54
COLOR 13 = &HFFFC54FC FC 54 FC
COLOR 14 = &HFFFCFC54 FC FC 54
COLOR 15 = &HFFFCFCFC FC FC FC
```
> *Explanation:* The RGB intensity values are multiplied by 4 to get the [_RGB](_RGB) intensity values as [HEX$](HEX$) values. The individual 2 digit [HEX$](HEX$) intensity values can be added to "&HFF" to make up the 32-bit hexadecimal string value necessary for [VAL](VAL) to return to [_PALETTECOLOR](_PALETTECOLOR). The statement is only included in the example to show how that can be done with any 32-bit color value.
> **Note:** Black has a blue hex value of 50 due to the [OUT](OUT) background color setting which makes it dark blue.
### Reading and setting color port intensities using [INP](INP) and [OUT](OUT)
* Legacy code may use [INP](INP) and [OUT](OUT) to read or set color port intensities. **QB64** emulates VGA memory to maintain compatibility.
* The same can be achieved using [_PALETTECOLOR](_PALETTECOLOR) (**recommended practice**).
> **OUT &H3C7, attribute** 'Set port to read RGB settings with:
> **color_intensity = INP(&H3C9)** 'reads present intensity setting
> **OUT &H3C8, attribute** 'Set port to write RGB settings with:
> **OUT &H3C9, color_intensity** 'writes new intensity setting
* After every 3 reads or writes, changes to next higher color attribute. Loops can be used to set more than one attribute's intensities.
* Color port setting of red, green and blue intensities can be done in ascending order.
* Color port attribute intensity values range from 0 to 63 (1/4 of the 32-bit values) in QBasic's legacy 4 and 8 bit screen modes.
## Example(s)
Reading the default RGB color settings of color attribute 15.
```vb
OUT &H3C7, 15
red% = INP(&H3C9)
green% = INP(&H3C9)
blue% = INP(&H3C9)
PRINT red%, green%, blue%
```
```text
63 63 63
```
Changing the color settings of attribute 0 (the background) to dark blue in [SCREEN](SCREEN)s 12 or 13.
```vb
SCREEN 12
OUT &H3C8, 0 'set color port attribute to write
OUT &H3C9, 0 'red intensity
OUT &H3C9, 0 'green intensity
OUT &H3C9, 30 'blue intensity
OUT &H3C7, 0
PRINT INP(&H3C9); INP(&H3C9); INP(&H3C9)
END
```
```text
0 0 30
```
Printing in fullscreen SCREEN 0 mode with a color background under the text only.
```vb
SCREEN 0: _FULLSCREEN ' used for fullscreen instead of window
COLOR 30, 6: LOCATE 12, 4: PRINT "Hello!"
```
> *Result:* Hello! is printed in flashing high intensity yellow with brown background behind text only when in QBasic [_FULLSCREEN](_FULLSCREEN).
Using [CLS](CLS) after setting the background color in SCREEN 0 to make the color cover the entire screen.
```vb
SCREEN 0: _FULLSCREEN
COLOR , 7: CLS
COLOR 9: PRINT "Hello"
```
```text
Hello
```
> *Result:* The blue word Hello is printed to a totally grey background in [_FULLSCREEN](_FULLSCREEN).
Using a different foreground color for each letter:
```vb
SCREEN 0
COLOR 1: PRINT "H";
COLOR 3: PRINT "E";
COLOR 4: PRINT "L";
COLOR 5: PRINT "L";
COLOR 6: PRINT "O"
COLOR 9: PRINT "W";
COLOR 11: PRINT "O";
COLOR 12: PRINT "R";
COLOR 13: PRINT "L";
COLOR 14: PRINT "D"
```
```text
HELLO
WORLD
```
Doing the same as Example 5 but in only a few lines:
```vb
SCREEN 0
text$ = "HelloWorld"
FOR textpos = 1 TO LEN(text$)
COLOR textpos
IF textpos <> 5 THEN PRINT MID$(text$, textpos, 1);
IF textpos = 5 THEN PRINT MID$(text$, textpos, 1) 'start print on next row
NEXT
```
```text
Hello
World
```
> *Explanation:*Semicolon(;) means that the next PRINT happens on the same line, we don't want that when it comes to position 5 so when it is at position 5 the next PRINT will move to the next line (when it isn't at position 5 we want it to continue printing the letter side-by-side on the same line though).
Since SCREEN 0 only uses background colors 0 to 7 by default, use [_PALETTECOLOR](_PALETTECOLOR) to change color intensities of color 0.
```vb
_PALETTECOLOR 0, _RGB32(255, 255, 255) 'change color 0 intensity
_PALETTECOLOR 8, _RGB32(0, 0, 0) 'change color 8 intensity
COLOR 8: PRINT "Black on bright white!"
```
```text
Black on bright white!
```
----
> *Explanation:* Since QB64 does not have [DAC](DAC) [SCREEN](SCREEN) 0 limitations, changing color intensities for custom background colors is possible.
Changing light gray text in [SCREEN](SCREEN) 0 to a 32 bit custom color using a [LONG](LONG) HTML hexadecimal value:
```vb
COLOR 7
PRINT "Color 7 is gray"
K$ = INPUT$(1)
_PALETTECOLOR 7, &HFFDAA520 ' FF alpha makes the color translucent
PRINT "Color 7 is now Goldenrod in SCREEN 0!
```
```text
Color 7 is gray
Color 7 is now Goldenrod in SCREEN 0!
```
> *Explanation:* [_RGB32](_RGB32) could be used to make custom 32 bit colors or HTML values could be used after &HFF for solid colors.
## See Also
* [$COLOR]($COLOR) (metacommand)
* [_RGB](_RGB), [_RGBA](_RGBA), [_RGB32](_RGB32), [RGBA32](RGBA32).
* [_RED](_RED), [_GREEN](_GREEN), [_BLUE](_BLUE)
* [_RED32](_RED32), [_GREEN32](_GREEN32), [_BLUE32](_BLUE32)
* [_ALPHA](_ALPHA), [_ALPHA32](_ALPHA32), [_CLEARCOLOR](_CLEARCOLOR)
* [PRINT](PRINT), [LOCATE](LOCATE), [SCREEN](SCREEN)
* [POINT](POINT), [SCREEN (function)](SCREEN-(function))
* [OUT](OUT), [INP](INP), [PALETTE](PALETTE)
* [_BLINK](_BLINK)
* [_DEFAULTCOLOR](_DEFAULTCOLOR)
* [_BACKGROUNDCOLOR](_BACKGROUNDCOLOR)
* [_PALETTECOLOR](_PALETTECOLOR)
* [Windows Libraries](Windows-Libraries)
* [Hexadecimal Color Values](http://www.w3schools.com/html/html_colornames.asp)

1
wiki/COM.md Normal file
View file

@ -0,0 +1 @@
See [COM(n)](COM(n)).

89
wiki/COMMAND$.md Normal file
View file

@ -0,0 +1,89 @@
The **COMMAND$** function returns the command line argument(s) passed when a program is run.
## Syntax
> commandLine$ = [COMMAND$](COMMAND$)[(count%)]
## Description
* The [STRING](STRING) return value is anything typed after a program's executable file name in command line (or using the [RUN](RUN) statement).
* Unlike QuickBASIC, **QB64** does not return all [UCASE$](UCASE$) values so keep that in mind when checking parameters.
* In **QB64**, COMMAND$ works as an array to return specific elements passed to the command line. COMMAND$(2) would return the second parameter passed at the command line. Arguments can contain spaces if they are passed inside quotation marks. This can be used to properly retrieve file names and arguments which contain spaces.
* Use the [_COMMANDCOUNT](_COMMANDCOUNT) function to find the number of parameters passed to a program via the command line. See *Example 2* below.
## Example(s)
Compile both programs. ProgramA [RUN](RUN)s ProgramB with a parameter passed following the filename:
```vb
LOCATE 12, 36: PRINT "ProgramA"
LOCATE 23, 25: PRINT "Press any key to run ProgramB"
K$ = INPUT$(1)
RUN "ProgramB FS" 'pass FS parameter to ProgramB in QB64 or QB4.5
SYSTEM
```
> *ProgramB* checks for fullscreen parameter pass in QB64 and goes full screen.
```vb
LOCATE 17, 36: PRINT "ProgramB"
parameter$ = UCASE$(COMMAND$) 'UCASE$ is needed in QB64 only, as QB4.5 will always return upper case
LOCATE 20, 33: PRINT "Parameter = " + parameter$
IF LEFT$(parameter$, 2) = "FS" THEN _FULLSCREEN 'parameter changes to full screen
END
```
```text
ProgramB
Parameter = FS.EXE
```
Program gets the number of parameters passed to the program, and then prints those parameters to the screen one at a time.
```vb
count = _COMMANDCOUNT
FOR c = 1 TO count
PRINT COMMAND$(c) 'or process commands sent
NEXT
```
```text
-1
a data file
```
> *Explanation: If we start *ThisProgram.exe* with the command line **ThisProgram -l "a data file"**, COMMAND$ will return a single string of "-1 a data file" which might be hard to process and interpret properly, but COMMAND$(1) would return "-l" and COMMAND$(2) would return the quoted "a data file" option as separate entries for easier parsing and processing.
As part of the command array syntax, you can also just read the array to see how many commands were sent (or simply check [_COMMANDCOUNT](_COMMANDCOUNT)):
```vb
DO
count = count + 1
cmd$ = COMMAND$(count)
IF cmd$ = "" THEN EXIT DO 'read until an empty return
PRINT cmd$ 'or process commands sent
LOOP
count = count - 1 'save the number of parameters sent to this program when run
```
## See Also
* [SHELL](SHELL), [RUN](RUN)
* [UCASE$](UCASE$), [LCASE$](LCASE$)
* [_COMMANDCOUNT](_COMMANDCOUNT)

37
wiki/COMMON-SHARED.md Normal file
View file

@ -0,0 +1,37 @@
**COMMON SHARED** is used to pass variable values between 2 or more program modules and sub procedures within that module.
The multi-modular technique goes back to when QBasic and QuickBASIC had module size constraints. In QB64 it has been implemented so that that older code can still be compiled, though **it is advisable to use single modules for a single project (not counting [$INCLUDE]($INCLUDE) libraries), for ease of sharing and also because the module size constraints no longer exist.**
## Syntax
> **COMMON** [**SHARED**][/block_name/]variable_list
* COMMON statements must be made before any program code execution.
* The [SHARED](SHARED) statement allows the variable values to also be used in module [SUB](SUB) and [FUNCTION](FUNCTION) procedures.
* The list of variables(separated by commas) to pass MUST be in the same type order in ALL modules used!
* [COMMON](COMMON) variable list names(but not variable types) can change between modules.
* The list can hold any variable type.
* The list cannot define a variable's value, but can use [AS](AS) to designate the type.
* Use [DIM](DIM) [SHARED](SHARED) variables when working in a module to pass variable values to SUB procedures.
* Data files could be used as an alternative to using COMMON SHARED values.
* In **QB64** COMMON values are sent using files instead of memory presently.
* **Note: Values assigned to shared variables used as procedure call parameters will not be passed to other procedures! The shared variable value MUST be assigned INSIDE of the [SUB](SUB) or [FUNCTION](FUNCTION) procedure to be passed!**
## QBasic/QuickBASIC
* Quickbasic 4.5 required you to include BRUN45.EXE when you compile COMMON SHARED values between EXE modules.
* The COMMON block name designates a certain block of variables that certain program modules may use, the name must be within two forward slashes/ (Ex: /thename/ ). **[Keywords currently not supported by QB64](Keywords-currently-not-supported-by-QB64)**
## Example(s)
```vb
COMMON SHARED x%, y%, user$, speed!, score&
```
## See Also
* [CHAIN](CHAIN), [RUN](RUN)
* [COMMON](COMMON)
* [SHARED](SHARED)

24
wiki/COMMON.md Normal file
View file

@ -0,0 +1,24 @@
[COMMON](COMMON) shares common variable values with other linked or [CHAIN](CHAIN)ed modules.
## Legacy Support
* The multi-modular technique goes back to when QBasic and QuickBASIC had module size constraints. In QB64 [COMMON](COMMON) has been implemented so that that older code can still be compiled, though **it is advisable to use single modules for a single project (not counting [$INCLUDE]($INCLUDE) libraries), for ease of sharing and also because the module size constraints no longer exist.**
## Syntax
> [COMMON](COMMON) [SHARED] variableList
## Description
* COMMON must be called before any executable statements.
* [SHARED](SHARED) makes the variables shared within [SUB](SUB) and [FUNCTION](FUNCTION) procedures within that module.
* variableList is the list of common variables made available separated by commas.
* Remember to keep the variable type *order* the same in all modules, as the variables names don't matter.
* [COMMON SHARED](COMMON-SHARED) is most commonly used to share the variables with subs and functions of that module.
* **Note: Values assigned to shared variables used as procedure call parameters will not be passed to other procedures. The shared variable value must be assigned inside of the [SUB](SUB) or [FUNCTION](FUNCTION) procedure to be passed.**
## See Also
* [COMMON SHARED](COMMON-SHARED), [CHAIN](CHAIN)
* [DIM](DIM), [REDIM](REDIM), [SHARED](SHARED)
* [DEFSTR](DEFSTR), [DEFLNG](DEFLNG), [DEFINT](DEFINT), [DEFSNG](DEFSNG), [DEFDBL](DEFDBL)

80
wiki/CONST.md Normal file
View file

@ -0,0 +1,80 @@
The [CONST](CONST) statement globally defines one or more named numeric or string values which will not change while the program is running.
## Syntax
> [CONST](CONST) constantName = value[, ...]
## Parameter(s)
* constantName is the constant name or list of names assigned by the programmer.
* value is the value to initialize the global constant which cannot change once defined.
* If constantName specifies a numeric type, value must be a numeric expression containing literals and other constants.
* If constantName specifies a string type, the value must be a literal value.
## Description
* The constantName does not have to include a type suffix. The datatype is automatically infered by the compiler using the value.
* Constant values cannot reference a variable or [FUNCTION](FUNCTION) return values.
* The exception to the above are the internal functions: [_PI](_PI), [_ACOS](_ACOS), [_ASIN](_ASIN), [_ARCSEC](_ARCSEC), [_ARCCSC](_ARCCSC), [_ARCCOT](_ARCCOT), [_SECH](_SECH), [_CSCH](_CSCH), [_COTH](_COTH), [COS](COS), [SIN](SIN), [TAN](TAN), [LOG](LOG), [EXP](EXP), [ATN](ATN), [_D2R](_D2R), [_D2G](_D2G), [_R2D](_R2D), [_R2G](_R2G), [_G2D](_G2D), [_G2R](_G2R), [ABS](ABS), [SGN](SGN), [INT](INT), [_ROUND](_ROUND), [_CEIL](_CEIL), [FIX](FIX), [_SEC](_SEC), [_CSC](_CSC), [_COT](_COT), [ASC](ASC), [_RGB32](_RGB32), [_RGBA32](_RGBA32), [_RGB](_RGB), [_RGBA](_RGBA), [_RED32](_RED32), [_GREEN32](_GREEN32), [_BLUE32](_BLUE32), [_ALPHA32](_ALPHA32), [_RED](_RED), [_GREEN](_GREEN), [_BLUE](_BLUE), [_ALPHA](_ALPHA) (See Example 2 below).
* Constants cannot be reassigned values. They retain the same value throughout all of the program procedures.
* Constants defined in module-level code have [SHARED](SHARED) scope, so they can also be used in [SUB](SUB) or [FUNCTION](FUNCTION) procedures.
* Constants defined in [SUB](SUB) or [FUNCTION](FUNCTION) procedures are local to those procedures.
* [CLEAR](CLEAR) will not affect or change constant values.
## Example(s)
Display the circumference and area of circles:
```vb
' Declare a numeric constant approximately equal to the ratio of a circle's
' circumference to its diameter:
CONST PI = 3.141593
' Declare some string constants:
CONST circumferenceText = "The circumference of the circle is"
CONST areaText = "The area of the circle is"
DO
INPUT "Enter the radius of a circle or zero to quit"; radius
IF radius = 0 THEN END
PRINT circumferenceText; 2 * PI * radius
PRINT areaText; PI * radius * radius ' radius squared
PRINT
LOOP
```
```text
Enter the radius of a circle or zero to quit? *10*
The circumference of the circle is 62.83186
The area of the circle is 314.1593
Enter the radius of a circle or zero to quit? *123.456*
The circumference of the circle is 775.697
The area of the circle is 47882.23
Enter the radius of a circle or zero to quit? *0*
```
> *Explanation:* PI cannot change as it is a mathematical constant so it is fitting to define it as a constant. Trying to change PI will result in a calculation error.
*Example 2*: Using _RGB32 to set a constant's value.
```vb
CONST Red = _RGB32(255,0,0)
COLOR Red
PRINT "Hello World"
```
## See Also
* [DIM](DIM), [SHARED](SHARED)
* [STATIC](STATIC), [COMMON](COMMON)
* [_PI](_PI), [_RGB32](_RGB32), [_RGBA32](_RGBA32)
* [Windows 32 API constant values](http://doc.pcsoft.fr/en-US/?6510001)

113
wiki/COS.md Normal file
View file

@ -0,0 +1,113 @@
The [COS](COS) function returns the horizontal component or the cosine of an angle measured in radians.
## Syntax
> value! = [COS](COS)(radianAngle!)
## Parameter(s)
* The radianAngle! must be measured in radians.
## Description
* To convert from degrees to radians, multiply degrees * &pi; / 180.
* [COS](COS)INE is the horizontal component of a unit vector in the direction theta (&theta;).
* COS(x) can be calculated in either [SINGLE](SINGLE) or [DOUBLE](DOUBLE) precision depending on its argument.
> COS(4) = -.6536436 ...... COS(4#) = -.6536436208636119
## Example(s)
Converting degree angles to radians for QBasic's trig functions and drawing the line at the angle.
```vb
SCREEN 12
PI = 4 * ATN(1)
PRINT "PI = 4 * ATN(1) ="; PI
PRINT "COS(PI) = "; COS(PI)
PRINT "SIN(PI) = "; SIN(PI)
DO
PRINT
INPUT "Enter the degree angle (0 quits): ", DEGREES%
RADIANS = DEGREES% * PI / 180
PRINT "RADIANS = DEGREES% * PI / 180 = "; RADIANS
PRINT "X = COS(RADIANS) = "; COS(RADIANS)
PRINT "Y = SIN(RADIANS) = "; SIN(RADIANS)
CIRCLE (400, 240), 2, 12
LINE (400, 240)-(400 + (50 * SIN(RADIANS)), 240 + (50 * COS(RADIANS))), 11
DEGREES% = RADIANS * 180 / PI
PRINT "DEGREES% = RADIANS * 180 / PI ="; DEGREES%
LOOP UNTIL DEGREES% = 0
```
```text
PI = 4 * ATN(1) = 3.141593
COS(PI) = -1
SIN(PI) = -8.742278E-08
Enter the degree angle (0 quits): 45
RADIANS = DEGREES% * PI / 180 = .7853982
X = COS(RADIANS) = .7071068
Y = SIN(RADIANS) = .7071068
DEGREES% = RADIANS * 180 / PI = 45
```
> *Explanation:* When 8.742278E-08(.00000008742278) is returned by [SIN](SIN) or COS the value is essentially zero.
Creating 12 analog clock hour points using [CIRCLE](CIRCLE)s and [PAINT](PAINT)
```vb
PI2 = 8 * ATN(1) '2 * π
arc! = PI2 / 12 'arc interval between hour circles
SCREEN 12
FOR t! = 0 TO PI2 STEP arc!
cx% = CINT(COS(t!) * 70) ' pixel columns (circular radius = 70)
cy% = CINT(SIN(t!) * 70) ' pixel rows
CIRCLE (cx% + 320, cy% + 240), 3, 12
PAINT STEP(0, 0), 9, 12
NEXT
```
*Explanation:* The 12 circles are placed at radian angles that are 1/12 of 6.28318 or .523598 radians apart.
Creating a rotating spiral with COS and [SIN](SIN).
```vb
SCREEN _NEWIMAGE(640, 480, 32)
DO
LINE (0, 0)-(640, 480), _RGB(0, 0, 0), BF
j = j + 1
PSET (320, 240)
FOR i = 0 TO 100 STEP .1
LINE -(.05 * i * i * COS(j + i) + 320, .05 * i * i * SIN(j + i) + 240)
NEXT
PSET (320, 240)
FOR i = 0 TO 100 STEP .1
LINE -(.05 * i * i * COS(j + i + 10) + 320, .05 * i * i * SIN(j + i + 10) + 240)
NEXT
PSET (320, 240)
FOR i = 0 TO 100 STEP .1
PAINT (.05 * i * i * COS(j + i + 5) + 320, .05 * i * i * SIN(j + i + 5) + 240)
NEXT
_DISPLAY
_LIMIT 30
LOOP UNTIL INP(&H60) = 1 'escape exit
```
## See Also
* [_PI](_PI) (QB64 function)
* [SIN](SIN) (sine)
* [ATN](ATN) (arctangent)
* [TAN](TAN) (tangent)
*[Mathematical Operations](Mathematical-Operations)
* [Mathematical Operations](Mathematical-Operations)

35
wiki/CSNG.md Normal file
View file

@ -0,0 +1,35 @@
[CSNG](CSNG) converts a numerical value to the closest [SINGLE](SINGLE)-precision number.
## Syntax
> singleValue! = [CSNG](CSNG)(expression)
## Parameter(s)
* expression is any [TYPE](TYPE) of literal or variable numerical value or mathematical calculation.
## Description
* Returns the closest [SINGLE](SINGLE) decimal point value.
* Also used to define a value as [SINGLE](SINGLE)-precision up to 7 decimals.
## Example(s)
```vb
A# = 975.3421222#
PRINT A#, CSNG(A#)
```
```text
975.3421222      975.3421
```
## See Also
* [CDBL](CDBL), [CLNG](CLNG)
* [CINT](CINT), [INT](INT)
* [_ROUND](_ROUND)

44
wiki/CSRLIN.md Normal file
View file

@ -0,0 +1,44 @@
The [CSRLIN](CSRLIN) function returns the current text row position of the [PRINT](PRINT) cursor.
## Syntax
> row% = [CSRLIN](CSRLIN)
## Description
* The value returned is within the range of 1 to the current number of rows in the [SCREEN](SCREEN) mode used.
* In [SCREEN](SCREEN) 0 (text mode), the [_HEIGHT](_HEIGHT) function returns the number of text rows.
* In graphic modes, the number of available text rows can be calculated by dividing [_HEIGHT](_HEIGHT) (measured in pixels in graphic modes) by [_FONTHEIGHT](_FONTHEIGHT): ***totalRows%* = _HEIGHT / _FONTHEIGHT**
* In screen modes that support page flipping, the [CSRLIN](CSRLIN) function returns the vertical coordinate of the cursor on the active page.
* x = [POS](POS)(0) returns the column location of the cursor.
## Example(s)
A semicolon stops the print cursor immediately after the print.
```vb
LOCATE 5, 5: PRINT "HELLO ";
Y = CSRLIN 'save the row
X = POS(0) 'save the column
LOCATE 10, 10: PRINT "WORLD"
LOCATE Y, X 'restore saved position
PRINT "GOODBYE"
```
```text
HELLO GOODBYE
WORLD
```
> *Explanation:* "HELLO " is printed and the semicolon stops the cursor immediately after the text. The [CSRLIN](CSRLIN) variable records the current print cursor's text row in Y. The [POS](POS) function records the current print cursor's text column in X. The second [PRINT](PRINT) statement displays the comment "WORLD" on the 10th line of the screen. The last [LOCATE](LOCATE) statement restores the position of the cursor to the original line and column immediately after the first print.
## See Also
* [SCREEN](SCREEN), [LOCATE](LOCATE), [POS](POS)
* [_PRINTSTRING](_PRINTSTRING) (graphic print)

56
wiki/CVD.md Normal file
View file

@ -0,0 +1,56 @@
The [CVD](CVD) function decodes an 8-byte [STRING](STRING) generated by [MKD$](MKD$) (or read from a file) to [DOUBLE](DOUBLE) numeric values.
## Syntax
> result# = [CVD](CVD)(stringData$)
## Description
* *CV* functions ([CVD](CVD), [CVS](CVS), [CVI](CVI), [CVL](CVL), [CVDMBF](CVDMBF), [CVSMBF](CVSMBF)) are used to convert values encoded by *MK$* functions ([MKD$](MKD$), [MKS$](MKS$), [MKI$](MKI$), [MKL$](MKL$), [MKDMBF$](MKDMBF$), [MKSMBF$](MKSMBF$)).
* Variables of numerical types are also encoded when [PUT](PUT) to a [RANDOM](RANDOM) or [BINARY](BINARY)-access file.
* **QB64** has [_CV](_CV) and [_MK$](_MK$) functions which can also deal with extended [Data types](Data-types).
* [DOUBLE](DOUBLE) values can range up to 15 decimal point digits. Decimal point accuracy depends on whole value places taken.
## Example(s)
Reading an 8-byte encoded string n$ from a file and obtaining the decoded [DOUBLE](DOUBLE) value:
```vb
FIELD #1, 8 AS N$, 12 AS B$...
GET #1
Y# = CVD(N$)
```
> *Explanation:* Reads a field from file #1, and converts the first eight bytes (N$) into an double-precision number assigned to the variable Y#.
Showcases the reduced space to store an encoded number.
```vb
a# = 77000.24523213
PRINT "Value of a#:"; a#
b$ = MKD$(a#)
PRINT "Value of a# encoded using MKD$: "; b$
PRINT "The string above, decoded using CVD:"; CVD(b$)
```
```text
Value of a#: 77000.24523213
Value of a# encoded using MKD$: ñåxýâ╠‗@
The string above, decoded using CVD: 77000.24523213
```
> Since the representation of a double-precision number can use up to 15 ASCII characters (fifteen bytes), writing to a file using [MKD$](MKD$) conversion, and then reading back with the [CVD](CVD) conversion can save up to 7 bytes of storage space.
## See Also
* [MKD$](MKD$), [MKI$](MKI$), [MKS$](MKS$), [MKL$](MKL$), [MKDMBF$](MKDMBF$), [MKSMBF$](MKSMBF$)
* [CVI](CVI), [CVS](CVS), [CVL](CVL), [CVSMBF](CVSMBF), [CVDMBF](CVDMBF)
* [_CV](_CV), [_MK$](_MK$)

43
wiki/CVDMBF.md Normal file
View file

@ -0,0 +1,43 @@
The [CVDMBF](CVDMBF) function decodes an 8-byte [STRING](STRING) generated by [MKDMBF$](MKDMBF$) (or read from a file) to [DOUBLE](DOUBLE) numeric values.
## Syntax
> result# = [CVDMBF](CVDMBF)(stringData$)
## Description
* *CV* functions ([CVD](CVD), [CVS](CVS), [CVI](CVI), [CVL](CVL), [CVDMBF](CVDMBF), [CVSMBF](CVSMBF)) are used to convert values encoded by *MK$* functions ([MKD$](MKD$), [MKS$](MKS$), [MKI$](MKI$), [MKL$](MKL$), [MKDMBF$](MKDMBF$), [MKSMBF$](MKSMBF$)).
* **QB64** has [_CV](_CV) and [_MK$](_MK$) functions which can also deal with extended [Data types](Data-types).
* [DOUBLE](DOUBLE) values can range up to 15 decimal point digits. Decimal point accuracy depends on whole value places taken.
## Example(s)
Showcases the reduced space to store an encoded number.
```vb
a# = 77000.24523213
PRINT "Value of a#:"; a#
b$ = MKDMBF$(a#)
PRINT "Value of a# encoded using MKDMBF$: "; b$
PRINT "The string above, decoded using CVDMBF:"; CVDMBF(b$)
```
```text
Value of a#: 77000.24523213
Value of a# encoded using MKDmbf$: 5─c▼d▬æ
The string above, decoded using CVDMBF: 77000.24523213
```
> Since the representation of a double-precision number can use up to 15 ASCII characters (fifteen bytes), writing to a file using [MKDMBF$](MKDMBF$) conversion, and then reading back with the [CVDMBF](CVDMBF) conversion can save up to 7 bytes of storage space.
## See Also
* [MKD$](MKD$), [MKI$](MKI$), [MKS$](MKS$), [MKL$](MKL$), [MKDMBF$](MKDMBF$), [MKSMBF$](MKSMBF$)
* [CVI](CVI), [CVS](CVS), [CVD](CVD), [CVL](CVL), [CVSMBF](CVSMBF)
* [_CV](_CV), [_MK$](_MK$)

68
wiki/CVI.md Normal file
View file

@ -0,0 +1,68 @@
The [CVI](CVI) function decodes a 2-byte [STRING](STRING) generated by [MKI$](MKI$) (or read from a file) to [INTEGER](INTEGER) numeric values.
## Syntax
> result% = [CVI](CVI)(stringData$)
## Description
* *CV* functions ([CVD](CVD), [CVS](CVS), [CVI](CVI), [CVL](CVL), [CVDMBF](CVDMBF), [CVSMBF](CVSMBF)) are used to convert values encoded by *MK$* functions ([MKD$](MKD$), [MKS$](MKS$), [MKI$](MKI$), [MKL$](MKL$), [MKDMBF$](MKDMBF$), [MKSMBF$](MKSMBF$)).
* **QB64** has [_CV](_CV) and [_MK$](_MK$) functions which can also deal with extended [Data types](Data-types).
* [INTEGER](INTEGER) values can range from -32768 to 32767.
* Doesn't return [_UNSIGNED](_UNSIGNED) values.
## Example(s)
*Example 1:*
```vb
FIELD #1, 2 AS N$, 12 AS B$...
GET #1 'GET does not need a position or variable with successive FIELD buffer reads
Y = CVI(N$)
```
> *Explanation:* Reads a field from file #1, and converts the first two bytes (N$) into an integer number assigned to the variable Y.
> Since the representation of an integer number can use up to 5 ASCII characters (five bytes), writing to a file using [MKI$](MKI$) conversion, and then reading back with the [CVI](CVI) conversion can save up to 3 bytes of storage space.
How CVI converts the ASCII code values created by the MKI$ function.
```vb
SCREEN 12
DIM Q AS STRING * 1
Q = CHR$(34)
' create Print using templates to align the values returned
tmp1$ = "1st character code = ### * 1 = ### "
tmp2$ = "2nd character code = ### * 256 = ##### "
tmp3$ = " & "
tmp4$ = " CVI Total = ##### "
DO
COLOR 14: LOCATE 13, 20: INPUT "Enter an Integer from 1 to 32767(0 quits): ", number%
IF number% < 1 THEN EXIT DO
CLS
ASCII$ = MKI$(number%) ' create the 2 byte character string
COLOR 11
_PRINTSTRING (152, 240), "MKI$ creates 2 byte ASCII string: " + Q + ASCII$ + Q ' displays character(s)
asc1% = ASC(ASCII$) ' find the ASCII code values of each character
asc2% = ASC(ASCII$, 2) ' **QB64** allows ASC to read specific characters in a string
LOCATE 18, 20: PRINT USING tmp1$; asc1%; asc1%
LOCATE 19, 20: PRINT USING tmp2$; asc2%; asc2% * 256
LOCATE 20, 20: PRINT USING tmp3$; "-----"
LOCATE 21, 20: PRINT USING tmp4$; asc1% + (256 * asc2%)
LOOP
SYSTEM
```
> *Explanation:* All [ASCII](ASCII) characters can be displayed using [_PRINTSTRING](_PRINTSTRING) . The routine gets the [ASCII](ASCII) code, which is the actual value needed by [CVI](CVI). The first byte code is always between 0 and 255. The second byte can return 0 thru 127 and CVI multiplies that value by 256. This proves that you cannot just feed a string number value to [CVI](CVI) and get the result desired. ("90" gets decoded to 12345).
## See Also
* [MKD$](MKD$), [MKI$](MKI$), [MKS$](MKS$), [MKL$](MKL$), [MKDMBF$](MKDMBF$), [MKSMBF$](MKSMBF$)
* [CVS](CVS), [CVD](CVD), [CVL](CVL), [CVSMBF](CVSMBF), [CVDMBF](CVDMBF)
* [_CV](_CV), [_MK$](_MK$)

45
wiki/CVL.md Normal file
View file

@ -0,0 +1,45 @@
The [CVL](CVL) function decodes a 4-byte [STRING](STRING) generated by [MKL$](MKL$) (or read from a file) to [LONG](LONG) numeric values.
## Syntax
> result& = [CVL](CVL)(stringData$)
## Description
* *CV* functions ([CVD](CVD), [CVS](CVS), [CVI](CVI), [CVL](CVL), [CVDMBF](CVDMBF), [CVSMBF](CVSMBF)) are used to convert values encoded by *MK$* functions ([MKD$](MKD$), [MKS$](MKS$), [MKI$](MKI$), [MKL$](MKL$), [MKDMBF$](MKDMBF$), [MKSMBF$](MKSMBF$)).
* **QB64** has [_CV](_CV) and [_MK$](_MK$) functions which can also deal with extended [Data types](Data-types).
* [LONG](LONG) values can range from -2147483648 to 2147483647.
* Doesn't return [_UNSIGNED](_UNSIGNED) values.
## Example(s)
*Example 1: 4 byte [ASCII](ASCII) character strings show how CVL multipliers convert [MKL$](MKL$) values into a 4 byte [LONG](LONG) value.
```vb
PRINT CVL(CHR$(1) + STRING$(3, 0)) 'ASC(CHR$(1)) * 1 = 1
PRINT CVL(CHR$(0) + CHR$(1) + STRING$(2, 0)) 'ASC(CHR$(1)) * 256 = 256
PRINT CVL(STRING$(2, 0) + CHR$(1) + CHR$(0)) 'ASC(CHR$(1)) * 256 * 256 = 65536
PRINT CVL(STRING$(3, 0) + CHR$(1)) 'ASC(CHR$(1)) * 256 * 256 * 256 = 16777216
```
*Example 2:*
```vb
FIELD #1, 4 AS N$, 12 AS B$...
GET #1
Y& = CVL(N$)
```
> *Explanation:* Reads a field from file #1, and converts the first four bytes (N$) into a long integer value assigned to the variable Y&.
> Since the representation of a long number can use up to 10 ASCII characters (ten bytes), writing to a file using [MKL$](MKL$) conversion, and then reading back with the [CVL](CVL) conversion can save up to 6 bytes of storage space.
## See Also
* [MKD$](MKD$), [MKI$](MKI$), [MKS$](MKS$), [MKL$](MKL$), [MKDMBF$](MKDMBF$), [MKSMBF$](MKSMBF$)
* [CVI](CVI), [CVS](CVS), [CVD](CVD), [CVDMBF](CVDMBF), [CVSMBF](CVSMBF)
* [_CV](_CV), [_MK$](_MK$)

41
wiki/CVS.md Normal file
View file

@ -0,0 +1,41 @@
The [CVS](CVS) function decodes a 4-byte [STRING](STRING) generated by [MKS$](MKS$) (or read from a file) to [SINGLE](SINGLE) numeric values.
## Syntax
> result! = [CVS](CVS)(stringData$)
## Description
* *CV* functions ([CVD](CVD), [CVS](CVS), [CVI](CVI), [CVL](CVL), [CVDMBF](CVDMBF), [CVSMBF](CVSMBF)) are used to convert values encoded by *MK$* functions ([MKD$](MKD$), [MKS$](MKS$), [MKI$](MKI$), [MKL$](MKL$), [MKDMBF$](MKDMBF$), [MKSMBF$](MKSMBF$)).
* **QB64** has [_CV](_CV) and [_MK$](_MK$) functions which can also deal with extended [Data types](Data-types).
* [SINGLE](SINGLE) values can range up to 7 decimal point digits. Decimal point accuracy depends on whole value places taken.
## Example(s)
Showcases the reduced space to store an encoded number.
```vb
a! = 700.2213
PRINT "Value of a!:"; a!
b$ = MKDMBF$(a!)
PRINT "Value of a# encoded using MKS$: "; b$
PRINT "The string above, decoded using CVS:"; CVS(b$)
```
```text
Value of a!: 700.2213
Value of a# encoded using MKS: *♫/D
The string above, decoded using CVS: 700.2213
```
> Since the representation of a single-precision number can use up to 7 ASCII characters (seven bytes), writing to a file using [MKS$](MKS$) conversion, and then reading back with the [CVS](CVS) conversion can save up to 3 bytes of storage space.
## See Also
* [MKD$](MKD$), [MKI$](MKI$), [MKS$](MKS$), [MKL$](MKL$), [MKDMBF$](MKDMBF$), [MKSMBF$](MKSMBF$)
* [CVI](CVI), [CVD](CVD), [CVL](CVL), [CVDMBF](CVDMBF), [CVSMBF](CVSMBF)
* [_CV](_CV), [_MK$](_MK$)

41
wiki/CVSMBF.md Normal file
View file

@ -0,0 +1,41 @@
The [CVDMBF](CVDMBF) function decodes a 4-byte [STRING](STRING) generated by [MKSMBF$](MKSMBF$) (or read from a file) to [SINGLE](SINGLE) numeric values.
## Syntax
> result! = [CVSMBF](CVSMBF)(stringData$)
## Description
* *CV* functions ([CVD](CVD), [CVS](CVS), [CVI](CVI), [CVL](CVL), [CVDMBF](CVDMBF), [CVSMBF](CVSMBF)) are used to convert values encoded by *MK$* functions ([MKD$](MKD$), [MKS$](MKS$), [MKI$](MKI$), [MKL$](MKL$), [MKDMBF$](MKDMBF$), [MKSMBF$](MKSMBF$)).
* **QB64** has [_CV](_CV) and [_MK$](_MK$) functions which can also deal with extended [Data types](Data-types).
* [SINGLE](SINGLE) values can range up to 7 decimal point digits. Decimal point accuracy depends on whole value places taken.
## Example(s)
Showcases the reduced space to store an encoded number.
```vb
a! = 700.2213
PRINT "Value of a!:"; a!
b$ = MKSMBF$(a!)
PRINT "Value of a! encoded using MKSMBF$: "; b$
PRINT "The string above, decoded using CVSMBF:"; CVDMBF(b$)
```
```text
Value of a!: 700.2213
Value of a# encoded using MKSMBF$: *♫/è
The string above, decoded using CVSMBF: 700.2213
```
> Since the representation of a double-precision number can use up to 7 ASCII characters (seven bytes), writing to a file using [MKSMBF$](MKSMBF$) conversion, and then reading back with the [CVSMBF](CVSMBF) conversion can save up to 3 bytes of storage space.
## See Also
* [MKD$](MKD$), [MKI$](MKI$), [MKS$](MKS$), [MKL$](MKL$), [MKDMBF$](MKDMBF$), [MKSMBF$](MKSMBF$)
* [CVI](CVI), [CVS](CVS), [CVD](CVD), [CVL](CVL), [CVDMBF](CVDMBF)
* [_CV](_CV), [_MK$](_MK$)

11
wiki/Cavemen.md Normal file
View file

@ -0,0 +1,11 @@
**Cavemen** lived thousands of years ago in caves or primitive shelters.
* Using simple technology, such as clubs, they acquired food and women.
* They often used short utterances called grunts and snarls.
* In 7,000 BC they came up with the word [LET](LET). Linguists believe that this word was used in sentences such as "[Let](LET) GRRRR!" or "[Let](LET) MEEE!". Since then, the word [LET](LET) has featured prominently in the design of the BASIC programming language.
* Why are you here? Did you look up [LET](LET)? Too bad! Tell your teacher to actually teach you something!
## See Also
* [LET](LET) there be light!
* [Allow me to go back](LET)

894
wiki/Code-Pages.md Normal file
View file

@ -0,0 +1,894 @@
__NOTOC__
**UNICODE CODE PAGES**
This is a list of the current Code Pages supported by the **QB64 IDE**. The data can be copied to a file or made into a [DATA](DATA) field. Each section has a description of the Code Page, the data required for **characters 128 TO 255**, and a LINK to the Code Table.
> ::**NOTE: When copying data to create a CSV file, make sure the cursor ends up below last line at home!**
**See: [Code Pages](Code-Pages)**
Unicode characters can be inserted in Windows by holding down the **Alt key** and entering a **zero** followed by the character's **three-digit decimal code on the number pad**. By omitting the zero, characters from older code pages can be entered like code page 437 in the US and England or code page 850 in Western Europe. In some versions of Windows it is necessary to change the regional settings to another language before entering that region's page codes.
**Setting up a typing language in the QB64 IDE:**
> ::Step 1: In the OPTIONS menu select **DISPLAY**, then check the CUSTOM FONT check-box.
> ::Step 2: In the OPTIONS menu select **LANGUAGE**, then select a Code Page (CP850 for example) and click OK.
## Code Page Listings:
```text
[Code Pages](Code-Pages)
[Code Pages](Code-Pages) [Code Pages](Code-Pages) [Code Pages](Code-Pages) [Code Pages](Code-Pages)
[Code Pages](Code-Pages) [Code Pages](Code-Pages) [Code Pages](Code-Pages) [Code Pages](Code-Pages)
[Code Pages](Code-Pages) [Code Pages](Code-Pages) [Code Pages](Code-Pages) [Code Pages](Code-Pages)
[Code Pages](Code-Pages) [Code Pages](Code-Pages) [Code Pages](Code-Pages) [Code Pages](Code-Pages)
[Code Pages](Code-Pages) [Code Pages](Code-Pages) [Code Pages](Code-Pages) [Code Pages](Code-Pages)
[Code Pages](Code-Pages) [Code Pages](Code-Pages) [Code Pages](Code-Pages) [Code Pages](Code-Pages)
[Code Pages](Code-Pages)
[Code Pages](Code-Pages)
```
**See the [Unicode](Unicode) and [_MAPUNICODE](_MAPUNICODE) pages to setup a program language using the data below:**
## CP 437
United States MS DOS
```text
'Microsoft_pc_cp437
199,252,233,226,228,224,229,231,234,235,232,239,238,236,196,197
201,230,198,244,246,242,251,249,255,214,220,162,163,165,8359,402
225,237,243,250,241,209,170,186,191,8976,172,189,188,161,171,187
9617,9618,9619,9474,9508,9569,9570,9558,9557,9571,9553,9559,9565,9564,9563,9488
9492,9524,9516,9500,9472,9532,9566,9567,9562,9556,9577,9574,9568,9552,9580,9575
9576,9572,9573,9561,9560,9554,9555,9579,9578,9496,9484,9608,9604,9612,9616,9600
945,223,915,960,931,963,181,964,934,920,937,948,8734,966,949,8745
8801,177,8805,8804,8992,8993,247,8776,176,8729,183,8730,8319,178,9632,160
```
[http://en.wikipedia.org/wiki/Code_page_437 Code Table 437]
```text
**Western [ASC](ASC) code page differences**
"**ä**" is &H84 in **CP437**, &HE4 in Windows-**1252**, &HE4 in Unicode.
"**ö**" is &H94 in **CP437**, &HF6 in Windows-**1252**, &HF6 in Unicode.
"**÷**" is &HF6 in **CP437**, &HF7 in Windows-**1252**, &HF7 in Unicode.
"**Σ**" is &HE4 in **CP437**, , &H3A3 in Unicode.
```
## CP 737
Greek MS DOS displays Greek alphabet for algebraic formulas.
```text
'Microsoft_pc_cp737
913,914,915,916,917,918,919,920,921,922,923,924,925,926,927,928
929,931,932,933,934,935,936,937,945,946,947,948,949,950,951,952
953,954,955,956,957,958,959,960,961,963,962,964,965,966,967,968
9617,9618,9619,9474,9508,9569,9570,9558,9557,9571,9553,9559,9565,9564,9563,9488
9492,9524,9516,9500,9472,9532,9566,9567,9562,9556,9577,9574,9568,9552,9580,9575
9576,9572,9573,9561,9560,9554,9555,9579,9578,9496,9484,9608,9604,9612,9616,9600
969,940,941,942,970,943,972,973,971,974,902,904,905,906,908,910
911,177,8805,8804,938,939,247,8776,176,8729,183,8730,8319,178,9632,160
```
[http://en.wikipedia.org/wiki/Code_page_737 Code Table 737]
[Code Pages](Code-Pages)
## CP 775
Estonian, Lithuanian and Latvian languages.
```text
'Microsoft_pc_cp775
262,252,233,257,228,291,229,263,322,275,342,343,299,377,196,197
201,230,198,333,246,290,162,346,347,214,220,248,163,216,215,164
256,298,243,379,380,378,8221,166,169,174,172,189,188,321,171,187
9617,9618,9619,9474,9508,260,268,280,278,9571,9553,9559,9565,302,352,9488
9492,9524,9516,9500,9472,9532,370,362,9562,9556,9577,9574,9568,9552,9580,381
261,269,281,279,303,353,371,363,382,9496,9484,9608,9604,9612,9616,9600
211,223,332,323,245,213,181,324,310,311,315,316,326,274,325,8217
173,177,8220,190,182,167,247,8222,176,8729,183,185,179,178,9632,160
```
[http://en.wikipedia.org/wiki/Code_page_775 Code Table 775]
## CP 850
Western Europe, Spain, England
```text
'Microsoft_pc_cp850
199,252,233,226,228,224,229,231,234,235,232,239,238,236,196,197
201,230,198,244,246,242,251,249,255,214,220,248,163,216,215,402
225,237,243,250,241,209,170,186,191,174,172,189,188,161,171,187
9617,9618,9619,9474,9508,193,194,192,169,9571,9553,9559,9565,162,165,9488
9492,9524,9516,9500,9472,9532,227,195,9562,9556,9577,9574,9568,9552,9580,164
240,208,202,203,200,**305**,205,206,207,9496,9484,9608,9604,166,204,9600
211,223,212,210,245,213,181,254,222,218,219,217,253,221,175,180
173,177,8215,190,182,167,247,184,176,168,183,185,179,178,9632,160
```
[http://en.wikipedia.org/wiki/Code_page_850 Western European Unicode CP850] .......... [http://en.wikipedia.org/wiki/CP858 Western European CP858] (with Euro)
Euro currency sign: ASCII code = 213 Unicode value = 8364 (replaces 305)
[Code Pages](Code-Pages)
## CP 852
Central European languages that use Latin script such as Bosnian, Croatian, Czech, Hungarian, Polish, Romanian, Serbian or Slovak.
```text
'Microsoft_pc_cp852
199,252,233,226,228,367,263,231,322,235,336,337,238,377,196,262
201,313,314,244,246,317,318,346,347,214,220,356,357,321,215,269
225,237,243,250,260,261,381,382,280,281,172,378,268,351,171,187
9617,9618,9619,9474,9508,193,194,282,350,9571,9553,9559,9565,379,380,9488
9492,9524,9516,9500,9472,9532,258,259,9562,9556,9577,9574,9568,9552,9580,164
273,272,270,203,271,327,205,206,283,9496,9484,9608,9604,354,366,9600
211,223,212,323,324,328,352,353,340,218,341,368,253,221,355,180
173,733,731,711,728,167,247,184,176,168,729,369,344,345,9632,160
```
[http://en.wikipedia.org/wiki/Code_page_852 Code Table 852]
## CP 855
Cyrillic code page to be used under MS-DOS
```text
'Microsoft_pc_cp855
1106,1026,1107,1027,1105,1025,1108,1028,1109,1029,1110,1030,1111,1031,1112,1032
1113,1033,1114,1034,1115,1035,1116,1036,1118,1038,1119,1039,1102,1070,1098,1066
1072,1040,1073,1041,1094,1062,1076,1044,1077,1045,1092,1060,1075,1043,171,187
9617,9618,9619,9474,9508,1093,1061,1080,1048,9571,9553,9559,9565,1081,1049,9488
9492,9524,9516,9500,9472,9532,1082,1050,9562,9556,9577,9574,9568,9552,9580,164
1083,1051,1084,1052,1085,1053,1086,1054,1087,9496,9484,9608,9604,1055,1103,9600
1071,1088,1056,1089,1057,1090,1058,1091,1059,1078,1046,1074,1042,1100,1068,8470
173,1099,1067,1079,1047,1096,1064,1101,1069,1097,1065,1095,1063,167,9632,160
```
[http://en.wikipedia.org/wiki/Code_page_855 Code Table 855]
[Code Pages](Code-Pages)
## CP 857
Turkish MS DOS
```text
'Microsoft_pc_cp857
199,252,233,226,228,224,229,231,234,235,232,239,238,305,196,197
201,230,198,244,246,242,251,249,304,214,220,248,163,216,350,351
225,237,243,250,241,209,286,287,191,174,172,189,188,161,171,187
9617,9618,9619,9474,9508,193,194,192,169,9571,9553,9559,9565,162,165,9488
9492,9524,9516,9500,9472,9532,227,195,9562,9556,9577,9574,9568,9552,9580,164
186,170,202,203,200,0,205,206,207,9496,9484,9608,9604,166,204,9600
211,223,212,210,245,213,181,0,215,218,219,217,236,255,175,180
173,177,0,190,182,167,247,184,176,168,183,185,179,178,9632,160
```
[http://en.wikipedia.org/wiki/Code_page_857 Code Table]
## CP 860
Portuguese language. MS DOS
```text
'Microsoft_pc_cp860
199,252,233,226,227,224,193,231,234,202,232,205,212,236,195,194
201,192,200,244,245,242,218,249,204,213,220,162,163,217,8359,211
225,237,243,250,241,209,170,186,191,210,172,189,188,161,171,187
9617,9618,9619,9474,9508,9569,9570,9558,9557,9571,9553,9559,9565,9564,9563,9488
9492,9524,9516,9500,9472,9532,9566,9567,9562,9556,9577,9574,9568,9552,9580,9575
9576,9572,9573,9561,9560,9554,9555,9579,9578,9496,9484,9608,9604,9612,9616,9600
945,223,915,960,931,963,181,964,934,920,937,948,8734,966,949,8745
8801,177,8805,8804,8992,8993,247,8776,176,8729,183,8730,8319,178,9632,160
```
[http://en.wikipedia.org/wiki/Code_page_860 Code Table 860]
[Code Pages](Code-Pages)
## CP 861
Icelandic language (as well as other Nordic languages). MS DOS
```text
'Microsoft_pc_cp861
199,252,233,226,228,224,229,231,234,235,232,208,240,222,196,197
201,230,198,244,246,254,251,221,253,214,220,248,163,216,8359,402
225,237,243,250,193,205,211,218,191,8976,172,189,188,161,171,187
9617,9618,9619,9474,9508,9569,9570,9558,9557,9571,9553,9559,9565,9564,9563,9488
9492,9524,9516,9500,9472,9532,9566,9567,9562,9556,9577,9574,9568,9552,9580,9575
9576,9572,9573,9561,9560,9554,9555,9579,9578,9496,9484,9608,9604,9612,9616,9600
945,223,915,960,931,963,181,964,934,920,937,948,8734,966,949,8745
8801,177,8805,8804,8992,8993,247,8776,176,8729,183,8730,8319,178,9632,160
```
[http://en.wikipedia.org/wiki/Code_page_861 Code Table 861]
## CP 862
Hebrew letters in positions 809A hex, but otherwise it is identical to [Code Pages](Code-Pages). Now obsolete, see [Code Pages](Code-Pages)
```text
'Microsoft_pc_cp862
1488,1489,1490,1491,1492,1493,1494,1495,1496,1497,1498,1499,1500,1501,1502,1503
1504,1505,1506,1507,1508,1509,1510,1511,1512,1513,1514,162,163,165,8359,402
225,237,243,250,241,209,170,186,191,8976,172,189,188,161,171,187
9617,9618,9619,9474,9508,9569,9570,9558,9557,9571,9553,9559,9565,9564,9563,9488
9492,9524,9516,9500,9472,9532,9566,9567,9562,9556,9577,9574,9568,9552,9580,9575
9576,9572,9573,9561,9560,9554,9555,9579,9578,9496,9484,9608,9604,9612,9616,9600
945,223,915,960,931,963,181,964,934,920,937,948,8734,966,949,8745
8801,177,8805,8804,8992,8993,247,8776,176,8729,183,8730,8319,178,9632,160
```
[http://en.wikipedia.org/wiki/Code_page_862 Code Table 862]
[Code Pages](Code-Pages)
## CP 863
French language (mainly in Canada). MS DOS
```text
'Microsoft_pc_cp863
199,252,233,226,194,224,182,231,234,235,232,239,238,8215,192,167
201,200,202,244,203,207,251,249,164,212,220,162,163,217,219,402
166,180,243,250,168,184,179,175,206,8976,172,189,188,190,171,187
9617,9618,9619,9474,9508,9569,9570,9558,9557,9571,9553,9559,9565,9564,9563,9488
9492,9524,9516,9500,9472,9532,9566,9567,9562,9556,9577,9574,9568,9552,9580,9575
9576,9572,9573,9561,9560,9554,9555,9579,9578,9496,9484,9608,9604,9612,9616,9600
945,223,915,960,931,963,181,964,934,920,937,948,8734,966,949,8745
8801,177,8805,8804,8992,8993,247,8776,176,8729,183,8730,8319,178,9632,160
```
[http://en.wikipedia.org/wiki/Code_page_863 Code Table 863]
## CP 864
Arabic MS DOS
```text
'Microsoft_pc_cp864
176,183,8729,8730,9618,9472,9474,9532,9508,9516,9500,9524,9488,9484,9492,9496
946,8734,966,177,189,188,8776,171,187,65271,65272,0,0,65275,65276,0
160,173,65154,163,164,65156,0,0,65166,65167,65173,65177,1548,65181,65185,65189
1632,1633,1634,1635,1636,1637,1638,1639,1640,1641,65233,1563,65201,65205,65209,1567
162,65152,65153,65155,65157,65226,65163,65165,65169,65171,65175,65179,65183,65187,65191,65193
65195,65197,65199,65203,65207,65211,65215,65217,65221,65227,65231,166,172,247,215,65225
1600,65235,65239,65243,65247,65251,65255,65259,65261,65263,65267,65213,65228,65230,65229,65249
65149,1617,65253,65257,65260,65264,65266,65232,65237,65269,65270,65245,65241,65265,9632,0
```
[http://ascii-table.com/codepage.php?864 Code Table 864]
[Code Pages](Code-Pages)
## CP 865
Nordic languages (except Icelandic, for which CP861 is used). MS DOS
```text
'Microsoft_pc_cp865
199,252,233,226,228,224,229,231,234,235,232,239,238,236,196,197
201,230,198,244,246,242,251,249,255,214,220,248,163,216,8359,402
225,237,243,250,241,209,170,186,191,8976,172,189,188,161,171,164
9617,9618,9619,9474,9508,9569,9570,9558,9557,9571,9553,9559,9565,9564,9563,9488
9492,9524,9516,9500,9472,9532,9566,9567,9562,9556,9577,9574,9568,9552,9580,9575
9576,9572,9573,9561,9560,9554,9555,9579,9578,9496,9484,9608,9604,9612,9616,9600
945,223,915,960,931,963,181,964,934,920,937,948,8734,966,949,8745
8801,177,8805,8804,8992,8993,247,8776,176,8729,183,8730,8319,178,9632,160
```
[http://en.wikipedia.org/wiki/Code_page_865 Code Table 865]
## CP 866
Cyrillic alphabetical order code page to be used with MS-DOS
```text
'Microsoft_pc_cp866
1040,1041,1042,1043,1044,1045,1046,1047,1048,1049,1050,1051,1052,1053,1054,1055
1056,1057,1058,1059,1060,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070,1071
1072,1073,1074,1075,1076,1077,1078,1079,1080,1081,1082,1083,1084,1085,1086,1087
9617,9618,9619,9474,9508,9569,9570,9558,9557,9571,9553,9559,9565,9564,9563,9488
9492,9524,9516,9500,9472,9532,9566,9567,9562,9556,9577,9574,9568,9552,9580,9575
9576,9572,9573,9561,9560,9554,9555,9579,9578,9496,9484,9608,9604,9612,9616,9600
1088,1089,1090,1091,1092,1093,1094,1095,1096,1097,1098,1099,1100,1101,1102,1103
1025,1105,1028,1108,1031,1111,1038,1118,176,8729,183,8730,8470,164,9632,160
```
See [Code Pages](Code-Pages) and [Code Pages](Code-Pages) below
[http://en.wikipedia.org/wiki/Code_page_866 Code Table 866]
[Code Pages](Code-Pages)
## CP MIK
Cyrillic Bulgarian Pravetz 16 for MS-DOS
```text
'Microsoft_pc_cpMIK
1040,1041,1042,1043,1044,1045,1046,1047,1048,1049,1050,1051,1052,1053,1054,1055
1056,1057,1058,1059,1060,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070,1071
1072,1073,1074,1075,1076,1077,1078,1079,1080,1081,1082,1083,1084,1085,1086,1087
1088,1089,1090,1091,1092,1093,1094,1095,1096,1097,1098,1099,1100,1101,1102,1103
9492,9524,9516,9500,9472,9532,9571,9553,9562,9566,9577,9574,9568,9552,9580,9488
9617,9618,9619,9474,9508,8470,167,9559,9565,9496,9484,9608,9604,9612,9616,9600
945,223,915,960,931,963,181,964,934,920,937,948,8734,966,949,8745
8801,177,8805,8804,8992,8993,247,8776,176,8729,183,8730,8319,178,9632,160
```
See [Code Pages](Code-Pages) above and [Code Pages](Code-Pages) below
[http://en.wikipedia.org/wiki/MIK_Code_page#Code_page_layout Code Table MIK]
## CP 869
Greek MS DOS. Less popular than [Code Pages](Code-Pages)
```text
'Microsoft_pc_cp869
0,0,0,0,0,0,902,0,183,172,166,8216,8217,904,8213,905
906,938,908,0,0,910,939,169,911,178,179,940,163,941,942,943
970,912,972,973,913,914,915,916,917,918,919,189,920,921,171,187
9617,9618,9619,9474,9508,922,923,924,925,9571,9553,9559,9565,926,927,9488
9492,9524,9516,9500,9472,9532,928,929,9562,9556,9577,9574,9568,9552,9580,931
932,933,934,935,936,937,945,946,947,9496,9484,9608,9604,948,949,9600
950,951,952,953,954,955,956,957,958,959,960,961,963,962,964,900
173,177,965,966,967,167,968,901,176,168,969,971,944,974,9632,160
```
[http://en.wikipedia.org/wiki/Code_page_869 Code Table 869]
[Code Pages](Code-Pages)
## CP 874
Thai MS DOS and Windows
```text
'Microsoft_pc_cp874
8364,0,0,0,0,8230,0,0,0,0,0,0,0,0,0,0
0,8216,8217,8220,8221,8226,8211,8212,0,0,0,0,0,0,0,0
160,3585,3586,3587,3588,3589,3590,3591,3592,3593,3594,3595,3596,3597,3598,3599
3600,3601,3602,3603,3604,3605,3606,3607,3608,3609,3610,3611,3612,3613,3614,3615
3616,3617,3618,3619,3620,3621,3622,3623,3624,3625,3626,3627,3628,3629,3630,3631
3632,3633,3634,3635,3636,3637,3638,3639,3640,3641,3642,0,0,0,0,3647
3648,3649,3650,3651,3652,3653,3654,3655,3656,3657,3658,3659,3660,3661,3662,3663
3664,3665,3666,3667,3668,3669,3670,3671,3672,3673,3674,3675,0,0,0,0
```
[http://en.wikipedia.org/wiki/Windows-874 Code Table 874]
## CP 1250
WINDOWS in Central European and Eastern European languages that use Latin script, such as Polish, Czech, Slovak, Hungarian, Slovene, Bosnian, Croatian, Serbian (Latin script), Romanian and Albanian. It may also be used with the German language.
```text
'Microsoft_windows_cp1250
8364,0,8218,0,8222,8230,8224,8225,0,8240,352,8249,346,356,381,377
0,8216,8217,8220,8221,8226,8211,8212,0,8482,353,8250,347,357,382,378
160,711,728,321,164,260,166,167,168,169,350,171,172,173,174,379
176,177,731,322,180,181,182,183,184,261,351,187,317,733,318,380
340,193,194,258,196,313,262,199,268,201,280,203,282,205,206,270
272,323,327,211,212,336,214,215,344,366,218,368,220,221,354,223
341,225,226,259,228,314,263,231,269,233,281,235,283,237,238,271
273,324,328,243,244,337,246,247,345,367,250,369,252,253,355,729
```
[http://en.wikipedia.org/wiki/Windows-1250 Code Table 1250]
[Code Pages](Code-Pages)
## CP 1251
Cyrillic alphabet such as Russian, Bulgarian, Serbian Cyrillic and other languages. It is the most widely used for encoding the Bulgarian, Serbian and Macedonian languages.
```text
'Microsoft_windows_cp1251
1026,1027,8218,1107,8222,8230,8224,8225,8364,8240,1033,8249,1034,1036,1035,1039
1106,8216,8217,8220,8221,8226,8211,8212,0,8482,1113,8250,1114,1116,1115,1119
160,1038,1118,1032,164,1168,166,167,1025,169,1028,171,172,173,174,1031
176,177,1030,1110,1169,181,182,183,1105,8470,1108,187,1112,1029,1109,1111
1040,1041,1042,1043,1044,1045,1046,1047,1048,1049,1050,1051,1052,1053,1054,1055
1056,1057,1058,1059,1060,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070,1071
1072,1073,1074,1075,1076,1077,1078,1079,1080,1081,1082,1083,1084,1085,1086,1087
1088,1089,1090,1091,1092,1093,1094,1095,1096,1097,1098,1099,1100,1101,1102,1103
```
See [Code Pages](Code-Pages) and [Code Pages](Code-Pages) above
[http://en.wikipedia.org/wiki/Windows-1251 Code Table 1251]
## CP 1252
Windows Western languages with Latin alphabet, used by default in the legacy components of Microsoft Windows in English.
```text
'Microsoft_windows_cp1252
8364,0,8218,402,8222,8230,8224,8225,710,8240,352,8249,338,0,381,0
0,8216,8217,8220,8221,8226,8211,8212,732,8482,353,8250,339,0,382,376
160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175
176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191
192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207
208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223
224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239
240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255
```
[http://en.wikipedia.org/wiki/Windows-1252 Code Table 1252]
```text
**MS DOS [ASC](ASC) code page differences**
"**ä**" is &H84 in **CP437**, &HE4 in Windows-**1252**, &HE4 in Unicode.
"**ö**" is &H94 in **CP437**, &HF6 in Windows-**1252**, &HF6 in Unicode.
"**÷**" is &HF6 in **CP437**, &HF7 in Windows-**1252**, &HF7 in Unicode.
"**Σ**" is &HE4 in **CP437**, , &H3A3 in Unicode.
```
[Code Pages](Code-Pages)
## CP 1253
Greek (but not polytonic Greek) Not fully compatible with ISO 8859-7 (Ά is located differently).
```text
'Microsoft_windows_cp1253
8364,0,8218,402,8222,8230,8224,8225,0,8240,0,8249,0,0,0,0
0,8216,8217,8220,8221,8226,8211,8212,0,8482,0,8250,0,0,0,0
160,901,902,163,164,165,166,167,168,169,0,171,172,173,174,8213
176,177,178,179,900,181,182,183,904,905,906,187,908,189,910,911
912,913,914,915,916,917,918,919,920,921,922,923,924,925,926,927
928,929,0,931,932,933,934,935,936,937,938,939,940,941,942,943
944,945,946,947,948,949,950,951,952,953,954,955,956,957,958,959
960,961,962,963,964,965,966,967,968,969,970,971,972,973,974,0
```
[http://en.wikipedia.org/wiki/Windows-1253 Code Table 1253]
## CP 1254
Turkish
```text
'Microsoft_windows_cp1254
8364,0,8218,402,8222,8230,8224,8225,710,8240,352,8249,338,0,0,0
0,8216,8217,8220,8221,8226,8211,8212,732,8482,353,8250,339,0,0,376
160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175
176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191
192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207
286,209,210,211,212,213,214,215,216,217,218,219,220,304,350,223
224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239
287,241,242,243,244,245,246,247,248,249,250,251,252,305,351,255
```
[http://en.wikipedia.org/wiki/Windows-1254 Code Table 1254]
[Code Pages](Code-Pages)
## CP 1255
Hebrew Windows. Modern applications prefer [https://en.wikipedia.org/wiki/UTF-8 UTF-8] or [http://www.fileformat.info/info/charset/UTF-16/list.htm UTF-16] to Windows 1255.
```text
'Microsoft_windows_cp1255
8364,0,8218,402,8222,8230,8224,8225,710,8240,0,8249,0,0,0,0
0,8216,8217,8220,8221,8226,8211,8212,732,8482,0,8250,0,0,0,0
160,161,162,163,8362,165,166,167,168,169,215,171,172,173,174,175
176,177,178,179,180,181,182,183,184,185,247,187,188,189,190,191
1456,1457,1458,1459,1460,1461,1462,1463,1464,1465,0,1467,1468,1469,1470,1471
1472,1473,1474,1475,1520,1521,1522,1523,1524,0,0,0,0,0,0,0
1488,1489,1490,1491,1492,1493,1494,1495,1496,1497,1498,1499,1500,1501,1502,1503
1504,1505,1506,1507,1508,1509,1510,1511,1512,1513,1514,0,0,8206,8207,0
```
[http://en.wikipedia.org/wiki/Windows-1255 Code Table 1255]
## CP 1256
Arabic Latin Windows
```text
'Microsoft_windows_cp1256
8364,1662,8218,402,8222,8230,8224,8225,710,8240,1657,8249,338,1670,1688,1672
1711,8216,8217,8220,8221,8226,8211,8212,1705,8482,1681,8250,339,8204,8205,1722
160,1548,162,163,164,165,166,167,168,169,1726,171,172,173,174,175
176,177,178,179,180,181,182,183,184,185,1563,187,188,189,190,1567
1729,1569,1570,1571,1572,1573,1574,1575,1576,1577,1578,1579,1580,1581,1582,1583
1584,1585,1586,1587,1588,1589,1590,215,1591,1592,1593,1594,1600,1601,1602,1603
224,1604,226,1605,1606,1607,1608,231,232,233,234,235,1609,1610,238,239
1611,1612,1613,1614,244,1615,1616,247,1617,249,1618,251,252,8206,8207,1746
```
[http://msdn.microsoft.com/en-us/goglobal/cc305149.aspx Code Table 1256]
[Code Pages](Code-Pages)
## CP 1257
Estonian (although that can also be written with Windows-1252), Latvian and Lithuanian languages under Microsoft Windows. It is also possible to write Polish and German.
```text
'Microsoft_windows_cp1257
8364,0,8218,0,8222,8230,8224,8225,0,8240,0,8249,0,168,711,184
0,8216,8217,8220,8221,8226,8211,8212,0,8482,0,8250,0,175,731,0
160,0,162,163,164,0,166,167,216,169,342,171,172,173,174,198
176,177,178,179,180,181,182,183,248,185,343,187,188,189,190,230
260,302,256,262,196,197,280,274,268,201,377,278,290,310,298,315
352,323,325,211,332,213,214,215,370,321,346,362,220,379,381,223
261,303,257,263,228,229,281,275,269,233,378,279,291,311,299,316
353,324,326,243,333,245,246,247,371,322,347,363,252,380,382,729
```
[http://en.wikipedia.org/wiki/Windows-1257 Code Table 1257]
## CP 1258
Vietnamese. [https://en.wikipedia.org/wiki/UTF-8 UTF-8] is the preferred encoding for Vietnamese in modern applications.
```text
'Microsoft_windows_cp1258
8364,0,8218,402,8222,8230,8224,8225,710,8240,0,8249,338,0,0,0
0,8216,8217,8220,8221,8226,8211,8212,732,8482,0,8250,339,0,0,376
160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175
176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191
192,193,194,258,196,197,198,199,200,201,202,203,768,205,206,207
272,209,777,211,212,416,214,215,216,217,218,219,220,431,771,223
224,225,226,259,228,229,230,231,232,233,234,235,769,237,238,239
273,241,803,243,244,417,246,247,248,249,250,251,252,432,8363,255
```
[http://en.wikipedia.org/wiki/Windows-1258 Code Table 1258]
[Code Pages](Code-Pages)
## Unicode Mapping
**[_MAPUNICODE](_MAPUNICODE) can place the Unicode characters TO any [ASCII](ASCII) code space you desire (0 to 255)**.
Reading CSV data file: Comma separated values are read using [INPUT (file statement)](INPUT-(file-statement)). Code Page data is pasted directly into a file as CSV.
**File named CP863.CSV **
```text
Microsoft_pc_cp863
199,252,233,226,194,224,182,231,234,235,232,239,238,8215,192,167
201,200,202,244,203,207,251,249,164,212,220,162,163,217,219,402
166,180,243,250,168,184,179,175,206,8976,172,189,188,190,171,187
9617,9618,9619,9474,9508,9569,9570,9558,9557,9571,9553,9559,9565,9564,9563,9488
9492,9524,9516,9500,9472,9532,9566,9567,9562,9556,9577,9574,9568,9552,9580,9575
9576,9572,9573,9561,9560,9554,9555,9579,9578,9496,9484,9608,9604,9612,9616,9600
945,223,915,960,931,963,181,964,934,920,937,948,8734,966,949,8745
8801,177,8805,8804,8992,8993,247,8776,176,8729,183,8730,8319,178,9632,160
```
**QB64 BAS module:**
```vb
SCREEN 0
_FONT _LOADFONT("C:\Windows\Fonts\Cour.ttf", 20, "MONOSPACE") 'select monospace font
FileName$ = "CP863.CSV" **'<<<<<<< Enter Unicode CSV data text file name you created here!**
f = FREEFILE
OPEN FileName$ FOR INPUT AS #f
INPUT #f, CodePage$ 'read code page ID on first line of file
IF NOT EOF(f) THEN PRINT CodePage$ 'display code page number
FOR ascii = 128 TO 255 'assign unicode values to ascii 128 to 255 only
IF EOF(f) THEN EXIT FOR
INPUT #f, unicode&
IF unicode& = 0 THEN unicode& = 9744 'make undefined characters look like a box
_MAPUNICODE unicode& TO ascii 'replace ascii with unicode value
NEXT
CLOSE #f
FOR code = 128 TO 255
PRINT code; CHR$(code); 'display unicode characters
NEXT
END
```
> Simply copy the code page data after the page name into a text file, commas and all, and read the file with [INPUT (file statement)](INPUT-(file-statement)) #.
> [_MAPUNICODE](_MAPUNICODE) can place the Unicode characters TO any [ASCII](ASCII) code space you desire (0 to 255).
Reading code page as program [DATA](DATA): Simply place DATA before each CSV Code Page data line pasted into a program.
```vb
SCREEN 0
_FONT _LOADFONT("C:\Windows\Fonts\Cour.ttf", 20, "MONOSPACE") 'select monospace font
RESTORE **Microsoft_pc_cp863** 'or restore single DATA field w/o field name
FOR ascii = 128 TO 255 'assign unicode values to ascii 128 to 255 only
READ unicode&
IF unicode& = 0 THEN unicode& = 9744 'make undefined characters look like a box
_MAPUNICODE unicode& TO ascii 'replace ascii with unicode value
NEXT
FOR code = 128 TO 255
PRINT code; CHR$(code); 'display unicode characters
NEXT
END * *
Microsoft_pc_cp863: 'use as data field line label or comment out code page name
DATA 199,252,233,226,194,224,182,231,234,235,232,239,238,8215,192,167
DATA 201,200,202,244,203,207,251,249,164,212,220,162,163,217,219,402
DATA 166,180,243,250,168,184,179,175,206,8976,172,189,188,190,171,187
DATA 9617,9618,9619,9474,9508,9569,9570,9558,9557,9571,9553,9559,9565,9564,9563,9488
DATA 9492,9524,9516,9500,9472,9532,9566,9567,9562,9556,9577,9574,9568,9552,9580,9575
DATA 9576,9572,9573,9561,9560,9554,9555,9579,9578,9496,9484,9608,9604,9612,9616,9600
DATA 945,223,915,960,931,963,181,964,934,920,937,948,8734,966,949,8745
DATA 8801,177,8805,8804,8992,8993,247,8776,176,8729,183,8730,8319,178,9632,160
```
> Simply copy the code page data and paste it into your program then type DATA before each line following the page name.
> Uncomment the code page name to use it as a [DATA](DATA) field name followed by a colon to [RESTORE](RESTORE) when necessary.
> Unicode values can be taken from any of the above code page data to make custom extended code characters for a program.
[Code Pages](Code-Pages)
## Reference:
## See Also
* [_MAPUNICODE](_MAPUNICODE), [_MAPUNICODE (function)](_MAPUNICODE-(function))
* [Unicode](Unicode), [ASCII](ASCII), [CHR$](CHR$), [ASC](ASC)
* [_KEYHIT](_KEYHIT), [_KEYDOWN](_KEYDOWN)
* [Text Using Graphics](Text-Using-Graphics)

20
wiki/Colon.md Normal file
View file

@ -0,0 +1,20 @@
A **colon** can be used to separate two unrelated procedure statements on the same line.
## Usage
> COLOR 10: PRINT "Hello "; : COLOR 12: PRINT "World"
```text
Hello World
```
* Use colons to combine variable definition statements or screen [PRINT](PRINT).
* Some statements such as [END IF](END-IF) and [Metacommand](Metacommand)s require a new code line!
* Use [Semicolon](Semicolon) and [Comma](Comma) where appropriate in [PRINT](PRINT)s.
* Use an [underscore](underscore) at the end of a line to extend a line of code to the next line.
## See Also
* [Comma](Comma), [Semicolon](Semicolon)

52
wiki/Comma.md Normal file
View file

@ -0,0 +1,52 @@
The **comma** is used to [TAB](TAB) the cursor after a [PRINT](PRINT) statement's text to tab append another printed value.
## Usage
> INPUT "Name, age and sex(M or F): ", nm$, age%, sex$
* Commas in [PRINT](PRINT) statements [TAB](TAB) space values up to 15 column places with column 57 being the maximum per row.
* A comma following the prompt text in an [INPUT](INPUT) statement does not display a question mark. A [Semicolon](Semicolon) or no prompt does.
* Commas are also used between [INPUT](INPUT) statement variables when more than one input is required.
* [LINE INPUT](LINE-INPUT) can use a comma or [semicolon](semicolon) after the prompt text. Neither will display a [question mark](question-mark).
* Commas are used as [argument](argument) separators in many kinds of QBasic statements and [SUB](SUB) or [FUNCTION](FUNCTION) parameter lists.
* [WRITE](WRITE) statements use commas to separate values printed to the screen or sent to a file **without tab spacing them**.
* **Literal numerical values entered into program code, [DATA](DATA), files or user [INPUT](INPUT) cannot contain comma separators!**
## Example(s)
Comparing [TAB](TAB) to [comma](comma) tab spacing.
```vb
PRINT TAB(15); "T"
PRINT , "T"
```
Comparing PRINT and WRITE statement displays.
```vb
value1 = 23567: value2 = 45678: value3 = 354126
COLOR 14: LOCATE 2, 1: PRINT value1, value2, value3
COLOR 12: LOCATE 4, 1: WRITE value1, value2, value3
```
```text
23567 45678 354126
23567,45678,354126
```
> *Note:* [WRITE](WRITE) does not space any values. The commas separate the numerical values without the normal PRINT spacing.
## See Also
* [Semicolon](Semicolon), [Colon](Colon)
* [TAB](TAB), [SPC](SPC), [SPACE$](SPACE$)
* [PRINT](PRINT), [PRINT USING](PRINT-USING)
* [WRITE](WRITE), [INPUT](INPUT), [LINE INPUT](LINE-INPUT)

59
wiki/Concatenation.md Normal file
View file

@ -0,0 +1,59 @@
**Concatenation** is a process where literal or variable [STRING](STRING) values are combined using the [+](+) operator.
## Usage
> value$ = "Literal text" + string_variable$ + "more text."
* The [STRING](STRING) values added can be literal or string variable values or a string [FUNCTION](FUNCTION) value.
* When combining string values in a variable definition, concatenation MUST be used!
* Literal or variable numerical values cannot be used in string concatenation.
* A numerical value can be changed to a string value using the [STR$](STR$)(number), [CHR$](CHR$)(code), [HEX$](HEX$), [OCT$](OCT$), [MKI$](MKI$), [MKS$](MKS$), [MKD$](MKD$), [MKL$](MKL$), [_MK$](_MK$) or [VARPTR$](VARPTR$) functions.
* [PRINT](PRINT) does not require any concatenation, but it can be used instead of using [semicolon](semicolon)s where strings are combined ONLY.
* String values CANNOT be subtracted from a value! Use [LEFT$](LEFT$), [RIGHT$](RIGHT$) or [MID$](MID$) to get portions of a string value.
Adding quotation marks to a string value using concatenation. Variables cannot be defined using semicolons!
```vb
quote$ = CHR$(34) + "Hello World!" + CHR$(34)
PRINT "Bill Gates never said "; quote$; " when he answered the telephone!"
```
```text
Bill Gates never said "Hello World!" when he answered the telephone!
```
Inserting numerical values in a PRINT string with semicolons, PRINT USING and PRINT with concatenation.
```vb
name$ = "Billy"
boxes% = 102
sales! = 306.00
template$ = "& sold ### boxes for $$####,.##."
PRINT name$; " sold"; boxes%; "boxes for $"; sales!; "."
PRINT USING template$; name$; boxes%; sales!
PRINT name$ + " sold" + STR$(boxes%) + " boxes for $" + LTRIM$(STR$(sales!)) + "."
```
```text
Billy sold 102 boxes for $ 306 .
Billy sold 102 boxes for $306.00.
Billy sold 102 boxes for $306.
```
> *Explanation:* Printed numerical values using semicolons have a space on each side. [PRINT USING](PRINT-USING) properly formats the string and displays the cent values when they are zero. [STR$](STR$) converts the number to a string and excludes the right number space, but leaves the sign space. [LTRIM$](LTRIM$) eliminates the leading sign space between the string number and the $ dollar sign.
## See Also
* [PRINT](PRINT), [PRINT USING](PRINT-USING)
* [CHR$](CHR$), [STR$](STR$), [VARPTR$](VARPTR$)
* [Semicolon](Semicolon), [Comma](Comma)

47
wiki/Console-Window.md Normal file
View file

@ -0,0 +1,47 @@
QB64 has console window support using the following QB64 [Metacommand](Metacommand) or keyword:
## Syntax
> [$CONSOLE]($CONSOLE)
> [_CONSOLE](_CONSOLE) [{ON|OFF}]
* _CONSOLE OFF turns the console window off once a console has been established using the [$CONSOLE]($CONSOLE) [Metacommand](Metacommand).
* _CONSOLE ON should only be used AFTER the console window has been turned OFF previously.
* [_DEST](_DEST) CONSOLE can be used to send screen output to the console window using QB64 commands such as [PRINT](PRINT).
* [_SCREENHIDE](_SCREENHIDE) or [_SCREENSHOW](_SCREENSHOW)(after window is hidden) can be used to hide or display the main program window.
* The [$SCREENHIDE]($SCREENHIDE) [Metacommand](Metacommand) can hide the main program window throughout a program when only the console is used.
* The [$SCREENSHOW]($SCREENSHOW) [Metacommand](Metacommand) can be used to display the main program window in a section of code after being hidden.
* When the program ends in the console window, a "Press Enter to continue" message will appear using QB64.
**Copying console screen text**
Console Window text can be copied by highlighting the text holding down the left mouse button. Once text is highlighted, right click the console window title bar to open the *Edit >* menu and click *Copy*. *Paste* and *Select All* are also available in the menu.
## Example(s)
Copying console window text is as simple as a right click on highlighted text areas. Another right click will close console.
```vb
$SCREENHIDE
$CONSOLE
_DEST _CONSOLE
PRINT
PRINT "Copy this text by highlighting and right clicking!"
```
> *Note:* You may have to right click the title bar and select *Edit > Select All* to start a copy. Then re-highlight text area desired and right click *Edit > Copy* or press the *Enter* key. Right click in the title bar area only, not in the program window area!
> The copy procedure will also work in **CMD.EXE** console windows Run from the Start Menu or the **Command Prompt** shortcut.
*Note:* A second right click may Paste the clipboard text to the DOS command line instead of closing console.
## See Also
* [$SCREENHIDE]($SCREENHIDE), [$SCREENSHOW]($SCREENSHOW)
* [$CONSOLE]($CONSOLE), [_CONSOLE](_CONSOLE), [_DEST](_DEST)
* [C_Libraries#Console_Window](C-Libraries#Console_Window)

178
wiki/Controller-Devices.md Normal file
View file

@ -0,0 +1,178 @@
QB64 supports all kinds of keyboard, mouse, joystick, gamepad, steering wheel and other multi-stick controller input devices.
* **In order to read the device controls, the number of input devices MUST first be found using [_DEVICES](_DEVICES).**
* After the device count is determined we can find out the type of device, the device name and the type of controls available using the [_DEVICE$](_DEVICE$)(device_number) function. The function returns a [STRING](STRING) containing information about each numbered device.
> `"[CONTROLLER][[DEVICENAME] device description][BUTTON][AXIS][WHEEL]"`
* [_DEVICEINPUT](_DEVICEINPUT) can indicate a used device number or true when a specified device number is active.
> **device = _DEVICEINPUT** would return 1 for a keyboard event and 2 for a mouse event.
> **mouse = _DEVICEINPUT(2)** would return -1(true) when the mouse was moved, clicked or scrolled.
## [KEYBOARD]
Normally the number 1 device, it usually only has [[BUTTON](BUTTON)] controls. Program window must be in focus to read key activity.
> **[KEYBOARD][BUTTON]**
> [_LASTBUTTON](_LASTBUTTON)(1) will normally return 512 buttons.
> [_BUTTONCHANGE](_BUTTONCHANGE)(number) returns -1 when pressed, 1 when released and 0 when there is no event since the last read.
> [_BUTTON](_BUTTON)(number) returns -1 when a button is pressed and 0 when released.
```text
' **Keyboard Device Button Numbers**
'
**' Esc F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 SysReq ScrL Pause**
' 177 436 433 434 439 440 437 438 395 396 393 394 399 402 392 ---
' **`~ 1! 2@ 3# 4$ 5% 6^ 7& 8* 9( 0) -_ =+ BkSpc Insert Home PgUp NumL / * -**
' 246 155 156 153 154 159 160 157 158 147 134 135 151 174 447 448 446 386 417 418 423
' **Tab Q W E R T Y U I O P [{ ]} \| Delete End PgDn 7/Home 8/▲ 9/PU + **
' 163 219 221 207 220 218 211 223 195 197 198 241 247 242 213 445 435 429 430 419 424
' **CapL A S D F G H J K L ;: '" Enter 4/◄- 5 6/-► E**
' 391 203 217 202 208 205 206 196 193 194 145 141 167 426 431 432 **n**
' **Shift Z X C V B N M ,< .> /? Shift ▲ 1/End 2/▼ 3/PD t**
' 390 212 222 201 224 204 200 199 130 136 133 389 443 427 428 432 **e**
' **Ctrl Win Alt Spacebar Alt Win Menu Ctrl ◄- ▼ -► 0/Insert ./Del r**
' 412 413 410 182 409 414 405 411 442 444 441 86 420 421
'
```
## [MOUSE]
Normally the number 2 device, a mouse usually has [[AXIS](AXIS)], [[BUTTON](BUTTON)] and [[WHEEL](WHEEL)] controls. Pointer must be in program screen area.
> **[MOUSE][BUTTON][AXIS][WHEEL]**
> [_LASTAXIS](_LASTAXIS)(2) normally returns 2 axis representing the horizontal and vertical mouse, trackball, touch pad or touchscreen axis.
> [_AXIS](_AXIS)(number) returns a [SINGLE](SINGLE) value from -1 to 1 with 0 representing the axis center in normal movement mode.
> [_AXIS](_AXIS)(1) returns the horizontal axis position in normal movement mode only.
> [_AXIS](_AXIS)(2) returns the vertical axis position in normal movement mode only.
Program window pointer AXIS values change from 0 at the center to -1 or + 1 values at the window borders.
> [_LASTBUTTON](_LASTBUTTON)(2) will normally return 3 buttons when mouse has a center or scroll wheel button.
> [_BUTTONCHANGE](_BUTTONCHANGE)(number) returns -1 when pressed, 1 when released and 0 when there is no event since the last read.
> [_BUTTON](_BUTTON)(number) returns -1 when corresponding button is pressed and 0 when released.
> [_BUTTON](_BUTTON)(1) returns Left button presses like [_MOUSEBUTTON](_MOUSEBUTTON)(1) and [_BUTTONCHANGE](_BUTTONCHANGE)(1) returns events.
> [_BUTTON](_BUTTON)(2) returns Center button presses like [_MOUSEBUTTON](_MOUSEBUTTON)(3) and [_BUTTONCHANGE](_BUTTONCHANGE)(2) returns events.
> [_BUTTON](_BUTTON)(3) returns Right button presses like [_MOUSEBUTTON](_MOUSEBUTTON)(2) and [_BUTTONCHANGE](_BUTTONCHANGE)(3) returns events.
**Note that middle _BUTTON(2) is equivalent to [_MOUSEBUTTON](_MOUSEBUTTON)(3)!**
> [_LASTWHEEL](_LASTWHEEL)(2) will normally return 3 wheels where the first two return relative coordinate movements when set.
> [_WHEEL](_WHEEL)(number) returns -1 when wheel is scrolled up or forward and 1 when wheel is scrolled down or backward.
> [_WHEEL](_WHEEL)(1) returns relative horizontal pixel moves after [_MOUSEMOVEMENTX](_MOUSEMOVEMENTX) or Y enables relative mode.
> [_WHEEL](_WHEEL)(2) returns relative vertical pixel moves after [_MOUSEMOVEMENTX](_MOUSEMOVEMENTX) or Y enables relative mode.
> [_WHEEL](_WHEEL)(3) returns -1 when scroll wheel is moved forward or up and 1 when scrolled backward or down.
Relative WHEEL move values are negative when mouse is moved up or left. Positive when mouse is moved down or right.
WHEEL values can be added for a cumulative movement value when needed. Scroll reads can be off program screen.
## [CONTROLLER]
[NAME][manufacturer name](NAME][manufacturer name) may follow in the controller [_DEVICE$](_DEVICE$) string. Devices can be joysticks, game pads or multi-stick.
> `[CONTROLLER][[DeviceName]description][BUTTON][AXIS][WHEEL]`
Normally device numbers 3 or higher, controllers may have any number of [[AXIS](AXIS)], [[BUTTON](BUTTON)] and/or [[WHEEL](WHEEL)] controls.
> [_LASTAXIS](_LASTAXIS)(device_number) normally returns dual axis representing the horizontal and vertical axis or view point("top hat").
> [_AXIS](_AXIS)(number) returns a [SINGLE](SINGLE) value from -1 to 1 with 0 representing the axis center.
> [_AXIS](_AXIS)(1) returns the horizontal axis position.
> [_AXIS](_AXIS)(2) returns the vertical axis position.
**Note: Some slide controls may only have one axis!**
> [_LASTBUTTON](_LASTBUTTON)(device_number) will return the number of buttons or triggers a device has.
> [_BUTTONCHANGE](_BUTTONCHANGE)(number) returns -1 when pressed, 1 when released and 0 when there is no event since the last read.
> [_BUTTON](_BUTTON)(number) returns -1 when button number is pressed and 0 when released.
> [_LASTWHEEL](_LASTWHEEL)(device_number) will return the number of wheel controls a device has.
> [_WHEEL](_WHEEL)(number) returns -1 when wheel is scrolled up or forward and 1 when wheel is scrolled down or backward.
## Example
> Displays all keyboard, mouse and game controller button, axis and wheel control input values when each device is being used.
```vb
PRINT "Use relative mouse movement mode with ESC key exit only?(Y/N) ";
K$ = UCASE$(INPUT$(1))
PRINT K$
PRINT
FOR i = 1 TO _DEVICES 'DEVICES MUST be read first!
PRINT STR$(i) + ") " + _DEVICE$(i) + " Buttons:"; _LASTBUTTON(i); ",Axis:"; _LASTAXIS(i); ",Wheel:"; _LASTWHEEL(i)
NEXT
IF K$ = "Y" THEN dummy = _MOUSEMOVEMENTX 'enable relative mouse movement reads
PRINT
DO
x& = _DEVICEINPUT 'determines which device is currently being used
IF x& = 1 THEN
PRINT "Keyboard: ";
FOR b = 1 TO _LASTBUTTON(x&)
bb = _BUTTONCHANGE(b)
IF bb THEN PRINT b; bb; _BUTTON(b);
NEXT
PRINT
END IF
IF x& > 1 THEN ' skip keyboard reads
PRINT "Device:"; x&;
FOR b = 1 TO _LASTBUTTON(x&)
PRINT _BUTTONCHANGE(b); _BUTTON(b);
NEXT
FOR a = 1 TO _LASTAXIS(x&)
PRINT _AXIS(a); 'mouse axis returns -1 to 1 with 0 center screen
NEXT
FOR w = 1 TO _LASTWHEEL(x&)
PRINT _WHEEL(w); 'wheels 1 and 2 of mouse return relative pixel moves when enabled
NEXT
PRINT
END IF
LOOP UNTIL INKEY$ = CHR$(27) 'escape key exit
END
```
<sub>Code by Ted Weissgerber</sub>
> *Note:* When there is no device control to read, a [FOR...NEXT](FOR...NEXT) n = 1 TO 0 loop will not run thus avoiding a control function read error.
> Using [_MOUSEMOVEMENTX](_MOUSEMOVEMENTX) or Y will hide the mouse cursor and return relative mouse movements with the 1 and 2 [_WHEEL](_WHEEL) controls.
[_MOUSESHOW](_MOUSESHOW) will return the mouse coordinate reads to the [_AXIS](_AXIS) control after it is used!
## See Also
* [_DEVICEINPUT](_DEVICEINPUT), [_AXIS](_AXIS), [_BUTTON](_BUTTON), [_BUTTONCHANGE](_BUTTONCHANGE), [_WHEEL](_WHEEL)
* [_DEVICES](_DEVICES), [_DEVICE$](_DEVICE$), [_LASTAXIS](_LASTAXIS), [_LASTBUTTON](_LASTBUTTON), [_LASTWHEEL](_LASTWHEEL)
* [_MOUSEINPUT](_MOUSEINPUT), [_MOUSEX](_MOUSEX), [_MOUSEY](_MOUSEY), [_MOUSEBUTTON](_MOUSEBUTTON), [_MOUSEWHEEL](_MOUSEWHEEL)
* [_MOUSEMOVE](_MOUSEMOVE), [_MOUSEHIDE](_MOUSEHIDE), [_MOUSESHOW](_MOUSESHOW)
* [_MOUSEMOVEMENTX](_MOUSEMOVEMENTX), [_MOUSEMOVEMENTY](_MOUSEMOVEMENTY) (relative movement)
* [STRIG](STRIG) (button), [STICK](STICK) (axis)

View file

@ -0,0 +1,70 @@
Although QB64 has [_BYTE](_BYTE) and [_BIT](_BIT) variable types, there may be times that you just want to know which bits are on of off in the byte value or convert the value to a [Binary](Binary) number.
Bits are numbered from 0 to 7 and normally are read from the most significant bit(MSB = 7) to the least significant bit(LSB = 0).
> The following example shows how to convert an [_UNSIGNED](_UNSIGNED) [_BYTE](_BYTE) or [INTEGER](INTEGER) value(0 to 255) to a [Binary](Binary) [STRING](STRING) number in QBasic.
```vb
DIM byte as _UNSIGNED _BYTE
byte = 222
FOR bit = 7 to 0 STEP -1
IF byte AND 2 ^ bit THEN PRINT "1"; ELSE PRINT "0";
NEXT
```
> *Notes:* The above code can be adapted to place a value into a bit [Arrays](Arrays) for up to 8 flag values in a single Byte.
> How upper and lower [_BYTE](_BYTE) bits are read from an [INTEGER](INTEGER) value using whole decimal or [HEX$](HEX$) values.
```vb
SCREEN 12
COLOR 11: LOCATE 10, 2: PRINT " AH (High Register Byte Bits) AL (Low Register Byte Bits)"
COLOR 14: LOCATE 11, 2: PRINT " 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0"
COLOR 13: LOCATE 14, 2: PRINT " &H8000 4000 2000 1000 800 400 200 100 80 40 20 10 8 4 2 &H1"
COLOR 11: LOCATE 15, 2: PRINT "-32768 16384 8192 4096 2048 1024 512 256 128 64 32 16 8 4 2 1"
FOR i = 1 TO 16
CIRCLE (640 - (37 * i), 189), 8, 9 'place bit circles
NEXT
LINE (324, 160)-(326, 207), 11, BF 'line splits bytes
DO
IF Num THEN
FOR i = 15 TO 0 STEP -1
IF (Num AND 2 ^ i) THEN
PAINT (640 - (37 * (i + 1)), 189), 12, 9
Bin$ = Bin$ + "1"
ELSE: PAINT (640 - (37 * (i + 1)), 189), 0, 9
Bin$ = Bin$ + "0"
END IF
NEXT
COLOR 10: LOCATE 16, 50: PRINT "Binary ="; VAL(Bin$)
COLOR 9: LOCATE 16, 10: PRINT "Decimal ="; Num;: COLOR 13: PRINT " Hex = "; Hexa$
Hexa$ = "": Bin$ = ""
END IF
COLOR 14: LOCATE 17, 15: INPUT "Enter a decimal or HEX(&H) value (0 Quits): ", frst$
first = VAL(frst$)
LOCATE 17, 15: PRINT SPACE$(55)
IF first THEN
COLOR 13: LOCATE 17, 15: INPUT "Enter a second value: ", secnd$
second = VAL(secnd$)
LOCATE 16, 10: PRINT SPACE$(69)
END IF
Num = first + second
Hexa$ = "&H" + HEX$(Num)
LOOP UNTIL first = 0 OR Num > 32767 OR Num < -32768 OR (Num < -1 AND Num > -32768
END
```
<sub>Code by Ted Weissgerber</sub>
## See Also
* [Binary](Binary)
* [_SHL](_SHL), [_SHR](_SHR)
* [_BIT](_BIT), [&B](&B)
* [_BYTE](_BYTE)

View file

@ -0,0 +1,478 @@
## Icon Viewer and Bitmap Creator
The following program can be used to view Icon or Cursor images and save them as Bitmaps. When you answer Y the bitmap is saved with a black background so that it can be PUT using [XOR](XOR) on to the [AND](AND) image. The AND image will be black and white if the image is irregularly shaped(not a full box image). It is placed first using [PUT (graphics statement)](PUT-(graphics-statement)) with the AND action or can be placed using [_PUTIMAGE](_PUTIMAGE) with the color white [_ALPHA](_ALPHA) being set to 0. In that case, try just placing the XOR image with the color black 0 [_ALPHA](_ALPHA) with [_SETALPHA](_SETALPHA).
<sub>Code by Ted Weissgerber</sub>
```vb
'********************************* IconType.BI INCLUDE FILE ********************************
TYPE IconType 'Icon or cursor file header
Reserved AS INTEGER 'Reserved (always 0)
ID AS INTEGER 'Resource ID (Icon = 1, Cursor = 2)
Count AS INTEGER 'Number of icon bitmaps in Directory of icon entries array
END TYPE '6 bytes
TYPE ICONENTRY 'or unanimated Cursor entry (see ANI for animated cursors)
PWidth AS _BYTE 'Width of icon in pixels (USE THIS)
PDepth AS _BYTE 'Height of icon in pixels (USE THIS)
NumColors AS _BYTE 'Maximum number of colors: (2 or 16 colors. 256 or 24/32 bit = 0}
RES2 AS _BYTE 'Reserved. Not used (always 0)
HotSpotX AS INTEGER 'Icon: NumberPlanes(normally 0), Cursor: hotspot pixels from left
HotSpotY AS INTEGER 'Icon: BitsPerPixel(normally 0), Cursor: hotspot pixels from top
DataSize AS LONG 'Length of icon bitmap in bytes (USE THIS)
DataOffset AS LONG 'Offset byte position of icon bitmap data header in file(add 1)
END TYPE '16 bytes
TYPE ICONHEADER 'Bitmap type header found using entry DataOffset + 1
IconHSize AS LONG 'size of ICON header (always 40 bytes)
ICONWidth AS LONG 'bitmap width in pixels. (width and double height may be missing)
ICONDepth AS LONG 'Total map height in pixels (TWO TIMES the image height).
NumPlanes AS INTEGER 'number of color planes. Must be set to 1.
BPP AS INTEGER 'bits per pixel 1, 4, 8, 16, 24 or 32.(USE THIS for BPP)
Compress AS LONG 'compression method should always be 0.
RAWSize AS LONG 'size of the raw ICON image data(may only be XOR mask size).
Hres AS LONG 'horizontal resolution of the image(not normally used)
Vres AS LONG 'vertical resolution of the image(not normally used)
NumColors AS LONG 'number of colors in the color palette(not normally used)
SigColors AS LONG 'number of important colors used(not normally used)
END TYPE '40 byte
```
```vb
REM $INCLUDE: 'IconType.BI'
DEFINT A-Z
DIM Icon AS IconType
DIM SHARED Item, BPP
DIM SHARED wide&, deep&, bmp&, bmpStretch&
DIM Image(26000)
dst& = _NEWIMAGE(800, 600, 32)
SCREEN dst&
hdr$ = " & File ID = # ## Image(s) in file #######, bytes "
ico$ = " Size = ## X ## Colors = ## Planes = # BPP = ## "
cur$ = " Size = ## X ## Colors = ## HotSpot X = ## Y = ## "
dat$ = " DATA Size = #####, bytes DATA Offset = ######, "
bm1$ = " HeaderSize = ## MaskArea = ## X ## Planes = # BPP = ## "
bm2$ = " Compression = # RAW Data Size = ######, bytes "
LOCATE 20, 20: LINE INPUT "Enter an ICOn or CURsor file name: ", IconName$
L = LEN(IconName$)
IF L = 0 THEN SOUND 400, 4: SYSTEM
dot = INSTR(IconName$, ".")
IF dot = 0 THEN
Save$ = IconName$: IconName$ = IconName$ + ".ICO"
ELSE Save$ = LEFT$(IconName$, dot - 1)
END IF
OPEN IconName$ FOR BINARY AS #1
length& = LOF(1)
PRINT
IF length& THEN
GET #1, 1, Icon
SELECT CASE Icon.ID
CASE 1: IC$ = "Icon": ent$ = ico$
CASE 2: IC$ = "Cursor": ent$ = cur$
CASE ELSE: IC$ = "Bitmap?"
END SELECT
LOCATE 22, 20: PRINT USING hdr$; IC$; Icon.ID; Icon.Count; length&
IF Icon.Count THEN
count = Icon.Count
DIM SHARED Entry(count) AS ICONENTRY
DIM SHARED Header(count) AS ICONHEADER
FOR Item = 1 TO count '16 bytes each entry
GET #1, , Entry(Item)
NEXT
VIEW PRINT 24 TO 32
FOR Item = 1 TO count
GET #1, Entry(Item).DataOffset + 1, Header(Item) 'ADD 1 to offsets!
COLOR _RGB(255, 255, 0): LOCATE 24, 30
IF count > 1 THEN PRINT " IMAGE ENTRY #"; Item ELSE PRINT " IMAGE ENTRY"
COLOR _RGB(50, 200, 255)
PRINT USING ent$; Entry(Item).PWidth; Entry(Item).PDepth; Entry(Item).NumColors; Entry(Item).HotSpotX; Entry(Item).HotSpotY
PRINT USING dat$; Entry(Item).DataSize; Entry(Item).DataOffset
PRINT USING bm1$; Header(Item).IconHSize; Header(Item).ICONWidth; Header(Item).ICONDepth, Header(Item).NumPlanes; Header(Item).BPP
PRINT USING bm2$; Header(Item).Compress; Header(Item).RAWSize
PRINT
k$ = INPUT$(1) 'Palette(4 or 8BPP) and/or XOR mask starts immediately after an ICONHEADER
wide& = Entry(Item).PWidth: deep& = Entry(Item).PDepth: BPP = Header(Item).BPP
IF BPP > 8 THEN BitColor = 32 ELSE BitColor = 256 'assign for proper colors
bmpStretch& = _NEWIMAGE(4 * wide&, 4 * deep&, BitColor) 'set either 256 or 32
bmp& = _NEWIMAGE(wide&, deep&, BitColor) 'don't bother with _FREEIMAGE, reuse them!
SELECT CASE BPP
CASE 1: OneBit
CASE 4: FourBIT
CASE 8: EightBIT
CASE IS > 8: TrueCOLOR
END SELECT
IF BPP < 24 THEN _COPYPALETTE bmp&, bmpStretch&
_PUTIMAGE , bmp&, bmpStretch&
_DEST 0: _PUTIMAGE (100, 0), bmpStretch&
SOUND 600, 3
COLOR _RGB(255, 0, 255): LOCATE CSRLIN, 30: PRINT "Save as Bitmap? (Y/N)";
k$ = INPUT$(1)
k$ = UCASE$(k$)
PRINT k$ + SPACE$(1);
IF k$ = "Y" THEN
SaveFile$ = Save$ + LTRIM$(STR$(Item)) + ".BMP"
ThirtyTwoBit 0, 0, wide& - 1, deep& - 1, bmp&, SaveFile$
END IF
IF k$ = "Y" THEN PRINT "Saved!" ELSE PRINT "Not saved"
ANDMask
IF BPP < 24 THEN _COPYPALETTE bmp&, bmpStretch&
_PUTIMAGE , bmp&, bmpStretch&
_DEST 0: _PUTIMAGE (400, 0), bmpStretch&
IF k$ = "Y" THEN
ANDFile$ = Save$ + LTRIM$(STR$(Item)) + "BG.BMP"
ThirtyTwoBit 0, 0, wide& - 1, deep& - 1, bmp&, ANDFile$
END IF
k$ = INPUT$(1)
CLS
NEXT
VIEW PRINT
ELSE SOUND 400, 4: CLOSE #1: PRINT "No images entries found!": END
END IF
ELSE: CLOSE #1: SOUND 400, 4: KILL IconName$: END
END IF
CLOSE #1
END
SUB OneBit 'adapted from TheBob's Winbit 'B & W monochrome images ONLY (NO PALETTE data)
BitsOver = wide& MOD 32
IF BitsOver THEN ZeroPAD$ = SPACE$((32 - BitsOver) \ 8)
_DEST bmp&
y = deep& - 1: p$ = " "
DO
x = 0
DO
GET #1, , p$
ByteVAL = ASC(p$)
FOR Bit% = 7 TO 0 STEP -1 'read bits left to right
IF ByteVAL AND 2 ^ Bit% THEN PSET (x, y), 15 ELSE PSET (x, y), 0
x = x + 1
NEXT Bit%
LOOP WHILE x < wide&
GET #1, , ZeroPAD$ ' 'prevents odd width image skewing
y = y - 1 '
LOOP UNTIL y = -1
END SUB
SUB EightBIT 'adapted from TheBob's Winbit '256 palette data Colors (8 BPP)
IF wide& MOD 4 THEN ZeroPAD$ = SPACE$(4 - (wide& MOD 4))
_DEST bmp&
a$ = " ": u$ = " "
OUT &H3C8, 0
FOR Colr = 0 TO 255
GET #1, , a$: Blu = ASC(a$) \ 4
GET #1, , a$: Grn = ASC(a$) \ 4
GET #1, , a$: Red = ASC(a$) \ 4
OUT &H3C9, Red
OUT &H3C9, Grn
OUT &H3C9, Blu
GET #1, , u$ '--- unused byte
NEXT Colr
y = deep& - 1: p$ = " "
DO: x = 0
DO
GET #1, , p$
PSET (x, y), ASC(p$)
x = x + 1
LOOP WHILE x < wide&
GET #1, , ZeroPAD$ ' 'prevents odd width image skewing
y = y - 1
LOOP UNTIL y = -1
END SUB
SUB FourBIT 'adapted from TheBob's Winbit '16 palette data colors (4 BPP = 8 or 16 color)
_DEST bmp&
IF wide& MOD 8 THEN ZeroPAD$ = SPACE$((8 - wide& MOD 8) \ 2) 'prevents odd width image skewing
a$ = " ": u$ = " "
FOR Colr = 0 TO 15
OUT &H3C8, Colr
GET #1, , a$: Blu = ASC(a$) \ 4
GET #1, , a$: Grn = ASC(a$) \ 4
GET #1, , a$: Red = ASC(a$) \ 4
OUT &H3C9, Red
OUT &H3C9, Grn
OUT &H3C9, Blu
GET #1, , u$ '--- unused byte
NEXT Colr
y = deep& - 1: p$ = " "
DO
x = 0
DO
GET #1, , p$
HiNIBBLE = ASC(p$) \ &H10
LoNIBBLE = ASC(p$) AND &HF
PSET (x, y), HiNIBBLE
x = x + 1
PSET (x, y), LoNIBBLE
x = x + 1
LOOP WHILE x < wide&
GET #1, , ZeroPAD$ ' 'prevents odd width image skewing
y = y - 1
LOOP UNTIL y = -1
END SUB
SUB ANDMask ' 'AND MASK is B & W. Black area holds XOR colors, white displays background
BitsOver = wide& MOD 32
IF BitsOver THEN ZeroPAD$ = SPACE$((32 - BitsOver) \ 8) 'look for sizes not multiples of 32 bits
_DEST bmp&
IF BPP < 24 THEN PALETTE ' 'remove for a PUT using previous XOR mask palette data
y = deep& - 1: a$ = " ": p$ = " "
DO
x = 0
DO
GET #1, , a$
ByteVAL = ASC(a$) 'MSBit is left when calculating 16 X 16 cursor map 2 byte integer
FOR Bit% = 7 TO 0 STEP -1 'values despite M$ documentation that says otherwise!
IF ByteVAL AND 2 ^ Bit% THEN 'LONG values cannot be used in a cursor file!
IF BPP > 8 THEN PSET (x, y), _RGB32(255, 255, 255) ELSE PSET (x, y), 15
ELSE: IF BPP > 8 THEN PSET (x, y), _RGB32(0, 0, 0) ELSE PSET (x, y), 0
END IF
x = x + 1 '16 X 16 = 32 bytes, 32 X 32 = 128 bytes AND MASK SIZES
NEXT Bit% '48 X 48 = 288 bytes, 64 X 64 = 512 bytes, 128 X 128 = 2048 bytes
LOOP WHILE x < wide&
GET #1, , ZeroPAD$ '16 X 16 and 48 X 48 = 2 byte end padder per row in the AND MASK
y = y - 1 'adds 32 and 96 bytes respectively to the raw data size!
LOOP UNTIL y = -1
END SUB
SUB TrueCOLOR ' ' 16 Million colors. NO PALETTE! Colored by pixels (24 or 32 BPP)
_DEST bmp&
IF ((BMP.PWidth * 3) MOD 4) <> 0 THEN '3 byte pixels
ZeroPAD$ = SPACE$((4 - ((BMP.PWidth * 3) MOD 4)))
END IF
R$ = " ": G$ = " ": B$ = " "
y = deep& - 1
DO
x = 0
DO
GET #1, , B$ '3 bytes set RGB color intensities
GET #1, , G$
GET #1, , R$
red& = ASC(R$)
green& = ASC(G$)
blue& = ASC(B$)
PSET (x, y), _RGB(red&, green&, blue&) 'returns closest attribute in 4 or 8 bit
x = x + 1
LOOP WHILE x < wide&
GET #1, , ZeroPAD$ ' 'prevents odd width image skewing
y = y - 1
LOOP UNTIL y = -1
END SUB
REM $INCLUDE: '32BitSUB.BM'
```
```vb
'*********************************** 32BitSUB.BM INCLUDE FILE *******************************
SUB ThirtyTwoBit (x1%, y1%, x2%, y2%, image&, Filename$)
DIM Colors8%(255)
IF x1% > x2% THEN SWAP x1%, x2%
IF y1% > y2% THEN SWAP y1%, y2%
_SOURCE image&
pixelbytes& = _PIXELSIZE(image&)
IF pixelbytes& = 0 THEN BEEP: EXIT SUB 'no text screens
FileType$ = "BM"
QB64$ = "QB64" 'free advertiising in reserved bytes
IF pixelbytes& = 1 THEN OffsetBITS& = 1078 ELSE OffsetBITS& = 54 'no palette in 24/32 bit
InfoHEADER& = 40
PictureWidth& = (x2% - x1%) + 1 ' don't exceed maximum screen resolutions!
PictureDepth& = (y2% - y1%) + 1
NumPLANES% = 1
IF pixelbytes& = 1 THEN BPP% = 8 ELSE BPP% = 24
Compression& = 0
WidthPELS& = 3780
DepthPELS& = 3780
IF pixelbytes& = 1 THEN NumColors& = 256 '24/32 bit say none
IF (PictureWidth& AND 3) THEN ZeroPAD$ = SPACE$(4 - (PictureWidth& AND 3))
ImageSize& = (PictureWidth& + LEN(ZeroPAD$)) * PictureDepth&
FileSize& = ImageSIZE& + OffsetBITS&
f = FREEFILE
OPEN Filename$ FOR BINARY AS #f
PUT #f, , FileType$
PUT #f, , FileSize&
PUT #f, , QB64$
PUT #f, , OffsetBITS&
PUT #f, , InfoHEADER&
PUT #f, , PictureWidth&
PUT #f, , PictureDepth&
PUT #f, , NumPLANES%
PUT #f, , BPP%
PUT #f, , Compression&
PUT #f, , ImageSize&
PUT #f, , WidthPELS&
PUT #f, , DepthPELS&
PUT #f, , NumColors&
PUT #f, , SigColors& '51 offset
IF pixelbytes& = 1 THEN '4 or 8 BPP Palettes set for 256 colors
u$ = CHR$(0)
FOR c& = 0 TO 255 'PUT as BGR order colors
cv& = _PALLETTECOLOR(c&, image&)
Colr$ = CHR$(_BLUE32(cv&))
PUT #f, , Colr$
Colr$ = CHR$(_GREEN32(cv&))
PUT #f, , Colr$
Colr$ = CHR$(_RED32(cv&))
PUT #f, , Colr$
PUT #f, , u$ 'Unused byte
NEXT
END IF
FOR y% = y2% TO y1% STEP -1 'place bottom up
FOR x% = x1% TO x2%
c& = POINT(x%, y%)
IF pixelbytes& = 1 THEN
a$ = CHR$(c&)
Colors8%(ASC(a$)) = 1
ELSE : a$ = LEFT$(MKL$(c&), 3)
END IF
PUT #f, , a$
NEXT
PUT #f, , ZeroPAD$
NEXT
FOR n = 0 TO 255
IF Colors8%(n) = 1 THEN SigColors& = SigColors& + 1
NEXT n
PUT #f, 51, SigColors&
CLOSE #f
END SUB
```
<sub>Adapted from code by Bob Seguin</sub>
**NOTE: Black areas of an image may become "see through" unless another color attribute is used and set to black!**
> This can be done by changing another color attribute's RGB settings to 0 or almost 0 and creating a mask after using it in solid black areas of a 4 or 8 BPP palette image. This can also be done using [_PUTIMAGE](_PUTIMAGE) with 32 bit [_CLEARCOLOR](_CLEARCOLOR) settings.
*See the following page:* [Creating Sprite Masks](Creating-Sprite-Masks)
## Icon to Bitmap Conversion Function
The following program uses a conversion function with the [TYPE](TYPE) definitions inside of the function to eliminate an [$INCLUDE]($INCLUDE) library file.
```vb
SCREEN _NEWIMAGE(640, 480, 256)
_TITLE "Icon Converter"
icon$ = "daphne.ico" '<<<<<<<<< change icon file name
bitmap$ = "tempfile.bmp"
indx% = 5 '1 minimum <<<<<<< higher values than count get highest entry image in icon file
IF Icon2BMP(icon$, bitmap$, indx%) THEN
img& = _LOADIMAGE(bitmap$)
PRINT img&
IF img& < -1 THEN ' check that handle value is good before loading
_ICON img& ' place image in header
_PUTIMAGE (300, 250), img& 'place image on screen
_FREEIMAGE img& ' always free unused handles to save memory
'KILL bitmap$ ' comment out and/or rename to save the bitmaps
END IF
ELSE PRINT "Could not create bitmap!"
END IF
END
' ----------------------------------------------------
FUNCTION Icon2BMP% (filein AS STRING, fileout AS STRING, index AS INTEGER)
TYPE ICONTYPE ' Icon or cursor file header
Reserved AS INTEGER ' Reserved (always 0)
ID AS INTEGER ' Resource ID (Icon = 1, Cursor = 2)
Count AS INTEGER ' Number of icon bitmaps in Directory of icon entries array
END TYPE '6 bytes
TYPE ENTRYTYPE ' or unanimated Cursor entry (ANI are animated cursors)
Wide AS _UNSIGNED _BYTE ' Width of icon in pixels (USE THIS) Use _UNSIGNED over 127
High AS _UNSIGNED _BYTE ' Height of icon in pixels (USE THIS) Use _UNSIGNED over 127
NumColors AS _BYTE ' Maximum number of colors. (2, 8 or 16 colors. 256 or 24/32 bit = 0)
RES2 AS _BYTE ' Reserved. Not used (always 0)
HotSpotX AS INTEGER ' Icon: NumberPlanes(normally 0), Cursor: hotspot pixels from left
HotSpotY AS INTEGER ' Icon: BitsPerPixel(normally 0), Cursor: hotspot pixels from top
DataSize AS LONG ' Length of image data in bytes minus Icon and Entry headers (USE THIS)
Offset AS LONG ' Start Offset byte position of icon bitmap header(add 1 if TYPE GET)
END TYPE '16 bytes
TYPE PREHEADER ' Bitmap information not in icon BM header
BM AS INTEGER ' Integer value changed to "BM" by PUT
Size AS LONG ' Size of the data file(LOF)
Reser AS LONG' 2 reserved integers are zero automatically
BOffset AS LONG ' Start offset of pixel data(next byte)
END TYPE '14 bytes
TYPE BMPHEADER ' Bitmap type header found using entry DataOffset + 1
IconHSize AS LONG ' size of ICON header (always 40 bytes)
PWidth AS LONG ' bitmap width in pixels (signed integer).
PDepth AS LONG ' Total map height in pixels (signed integer is 2 times image height)
NumPlanes AS INTEGER ' number of color planes. Must be set to 1.
BPP AS INTEGER ' bits per pixel 1, 4, 8, 16, 24 or 32.(USE THIS)
Compress AS LONG ' compression method should always be 0.
RAWSize AS LONG ' size of the raw ICON image data(may only be XOR mask size).
Hres AS LONG ' horizontal resolution of the image(not normally used)
Vres AS LONG ' vertical resolution of the image(not normally used)
NumColors AS LONG ' number of colors in the color palette(not normally used)
SigColors AS LONG ' number of important colors used(not normally used)
END TYPE '40 bytes palette and image data immediately follow this header!
DIM ICON AS ICONTYPE, ENT AS ENTRYTYPE, PRE AS PREHEADER, BMP AS BMPHEADER
rf = FREEFILE
IF LCASE$(RIGHT$(filein, 4)) = ".ico" THEN 'check file extension is ICO only
OPEN filein FOR BINARY ACCESS READ AS rf
ELSE EXIT FUNCTION
END IF
GET rf, , ICON 'GET 6 byte icon header
IF ICON.ID <> 1 OR ICON.Count = 0 THEN CLOSE rf: EXIT FUNCTION
IF index > 0 AND index <= ICON.Count THEN entry = 16 * (index - 1) ELSE entry = 16 * (ICON.Count - 1)
PRINT ICON.Count, entry
SEEK rf, 1 + 6 + entry 'start of indexed Entry header selected
GET rf, , ENT 'GET 16 byte Entry Header set by index request or highest available
SEEK rf, 1 + ENT.Offset 'go to BMP header offset given in Entry header
GET rf, , BMP 'GET 40 byte icon bitmap header information
IF BMP.BPP <= 24 THEN pixelbytes = BMP.BPP / 8 ELSE pixelbytes = 3
IF BMP.BPP > 1 AND BMP.BPP <= 8 THEN palettebytes = 4 * (2 ^ BMP.BPP) ELSE palettebytes = 0
datasize& = (ENT.Wide * ENT.High * pixelbytes) + palettebytes 'no padder should be necessary
filesize& = datasize& + 14 + 40 ' data and palette + header
bmpoffset& = palettebytes + 54 ' data offset from start of bitmap
BMP.PWidth = ENT.Wide
BMP.PDepth = ENT.High
BMP.RAWSize = datasize& - palettebytes
PRE.BM = CVI("BM") 'integer value changes to "BM" in file
PRE.Size = filesize&
PRE.BOffset = bmpoffset& 'start of data after header and palette if used
wf = FREEFILE
OPEN fileout FOR BINARY AS wf
PUT wf, , PRE 'PUT 14 byte bitmap information
PUT wf, , BMP 'PUT 40 byte bitmap header information
SEEK rf, 1 + ENT.Offset + 40
dat$ = STRING$(datasize&, 0) 'create string variable the length of remaining image data
GET rf, , dat$ 'GET remaining palette and only the XOR image data after the indexed header
PUT wf, , dat$ 'PUT remaining data into new bitmap file
CLOSE rf, wf
Icon2BMP = ICON.Count 'function returns number of images available in icon file
END FUNCTION
```
<sub>Code by Ted Weissgerber</sub>
> *Note:* The index selected or the highest numbered icon image less than the index value is the image displayed.
## See Also
* [Creating Icons from Bitmaps](Creating-Icons-from-Bitmaps)
* [Bitmaps](Bitmaps), [Icons and Cursors](Icons-and-Cursors)
* [_CLEARCOLOR](_CLEARCOLOR)
* [_ALPHA](_ALPHA), [_ICON](_ICON)
* [SaveIcon32](SaveIcon32) (create icons from any image)

View file

@ -0,0 +1,90 @@
The following program can create a single icon from square bitmaps up to 128 X 128. Best to use sizes 32 X 32 or 64 X 64.
```vb
CONST dat = 14~&
DIM Dword AS _UNSIGNED LONG
DIM size AS _UNSIGNED LONG
DIM wide AS _UNSIGNED LONG
DIM high AS _UNSIGNED LONG
DIM Word AS _UNSIGNED INTEGER
DIM Byte AS _UNSIGNED _BYTE
DO
LINE INPUT "Enter existing BMP file name to convert to icon: ", BMP$
LOOP UNTIL _FILEEXISTS(BMP$)
DO
LINE INPUT "Enter ICO file name to create (must not exist): ", ICO$
LOOP UNTIL _FILEEXISTS(ICO$) = 0
OPEN BMP$ FOR BINARY ACCESS READ AS 1 'BITMAP name
OPEN ICO$ FOR OUTPUT AS 2 'destination icon name
CLOSE 2
OPEN ICO$ FOR BINARY AS 2
GET 1, 1 + 2, size 'skip "BM" in bitmap
size = size - 14 '14 bytes not used
Word = 0
PUT 2, 1, Word 'reserved
Word = 1
PUT 2, , Word 'resource id 1 as icon, 2 as cursor
PUT 2, , Word 'icon count in resource
GET 1, 1 + dat + 4, wide 'skip header size in BMP
SELECT CASE wide
CASE IS < &H100: Byte = wide '< 256
CASE &H100: Byte = 0
CASE ELSE: PRINT "bitmap is larger than 256 pixels.": END
END SELECT
PUT 2, , Byte 'width
GET 1, , high
SELECT CASE high
CASE IS < &H100: Byte = high '< 256
CASE &H100: Byte = 0 '256 = 0
CASE ELSE: PRINT "bitmap is larger than 256 pixels.": END
END SELECT
PUT 2, , Byte 'height
Byte = 0
GET 1, 1 + dat + 14, Word 'number of colors from BPP
IF Word < 8 THEN Byte = 2 ^ Word ELSE Byte = 0 '256 colors = 0, 4BPP = 16
PUT 2, , Byte 'num of colors
Byte = 0
Dword = 0
PUT 2, , Byte 'reserved as byte
PUT 2, , Dword 'reserved 2 hotspots = 0
Dword = size + (((wide * high) + 7) \ 8)
PUT 2, , Dword 'size of data
Dword = 22 '6 byte header + 16
PUT 2, , Dword 'offset
'copy bitmap header down 14 bytes, palette and image info, but double height
SEEK 1, 1 + dat 'BMP info header size
FOR Dword = 1 TO size 'actual BMP data from Header size on
GET 1, , Byte
IF Dword = 1 + 8 THEN
Word = high * 2 ' 2 times height
PUT 2, , Word
Dword = Dword + 1
GET 1, , Byte
ELSE
PUT 2, , Byte
END IF
NEXT
'add null AND bitmask for full square image
Byte = 0
BitsOver& = wide MOD 32 'pad the AND mask for minimum of 4 byte width
IF BitsOver& THEN ANDpad& = (32 - BitsOver&) ELSE ANDpad& = 0
FOR Dword = 1 TO high * (wide + ANDpad&) \ 8
PUT 2, , Byte
NEXT
CLOSE
SYSTEM
```
<sub>Adapted from code by Michael Calkins, Public domain, November 2011</sub>
## See Also
* [_ICON](_ICON), [$EXEICON]($EXEICON)
* [SaveIcon32](SaveIcon32) (saves any image to icon)
* [Icons and Cursors](Icons-and-Cursors)
* [Bitmaps](Bitmaps)

View file

@ -0,0 +1,55 @@
Sometimes your program may need to place a shaped sprite over background objects. To do that you cannot use the default [PUT (graphics statement)](PUT-(graphics-statement)) using XOR. [XOR](XOR) only works on black backgrounds! It distorts underlying colors. You could use the PSET option, but that places a square sprite only. To get irregularly shaped objects you need to create a "mask" of the sprite. After you have created your sprite with a BLACK background, GET the image to an [Arrays](Arrays). You can [BSAVE](BSAVE) it if you wish. Then create a mask of the sprite at the sprites current location. Use the GET box area coordinates(minX, maxX and minY, maxY) of sprite in the following routine:
<sub>Code by: Ted Weissgerber</sub>
```vb
FOR xx = minX TO maxX
FOR yy = minY TO maxY
IF POINT(xx, yy) = 0 THEN PSET (xx, yy), 15 ELSE PSET (xx, yy), 0
NEXT yy
NEXT xx
GET (minX, minY)-(maxX, maxY), Mask(0)
```
The mask routine simply changes all black portions of the sprite image to white and all other colors black. If your sprite uses black in it, you will need to assign the areas to another color attribute and change the RGB values to 0 using [OUT](OUT) or the background will show through the final image. Color 8 could be dark enough.
GET the background at the sprite's starting position before trying to place a sprite or move it when necessary. Next we position the mask and PUT it with the [AND](AND) option. Then the actual sprite is PUT over the mask as shown below:
```vb
GET (x, y)-(x + 60, y + 60), BG ' GET BG at start position before sprite is set
PUT (x, y), Mask, AND ' PUT mask at start position
PUT (x, y), Sprite ' XOR will work fine on a mask
```
The two PUTs use the same coordinate so moving objects is fairly simple. All you need is a keypress reading loop. Use INP(&H60) [Scancodes](Scancodes) for diagonal moves.
But what about the background? Once you create the background you will need to [GET (graphics statement)](GET-(graphics-statement)) the sprite's box area at the starting position. You can PUT the background back to erase the sprite when moving. PX and PY are the previous x and y positions before they were changed by the user in a keypress routine:
```vb
'user keypress or programmed coordinate changes
IF x <> PX OR y <> PY THEN ' look for a changed coordinate value
WAIT 936, 8 ' vertical retrace delay
PUT (PX, PY), BG, PSET ' replace previous BG first
GET (x, y)-(x + 60, y + 60), BG ' GET BG at new position before box is set
PUT (x, y), Mask, AND ' PUT mask at new position
PUT (x, y), Sprite ' XOR will work fine on the mask
END IF
PX = x: PY = y
```
In **QB64** [_CLEARCOLOR](_CLEARCOLOR) can also be used before using [_PUTIMAGE](_PUTIMAGE) to mask any sprite background color.
**See the [GET and PUT Demo](GET-and-PUT-Demo) to see how it works!**
## See Also
* [INP](INP), [Scancodes](Scancodes)(Example 3)
* [GET (graphics statement)](GET-(graphics-statement)), [PUT (graphics statement)](PUT-(graphics-statement))
* [Icons and Cursors](Icons-and-Cursors)
* [Creating Icons from Bitmaps](Creating-Icons-from-Bitmaps)

73
wiki/DAC.md Normal file
View file

@ -0,0 +1,73 @@
**DAC** stands for the QBasic Digital to Analog Converter color attributes used in screens 0, 7 and 9.
> ** IMPORTANT: QB64 screens do not use the DAC index!**
* DAC colors are preset and cannot be changed in QBasic easily(see example).
* DAC color attribute settings cannot be changed using [PALETTE](PALETTE) or [OUT](OUT) RGB statements.
* Screen 0 and 9 can use up to 64 DAC color hues. Only attributes 0 to 5 and 7 can have RGB values altered using [OUT](OUT).
* [PALETTE](PALETTE) swap statements can assign one attribute's DAC color setting to another attribute color in [SCREEN](SCREEN)s 0 to 9.
* Screen attributes 0 to 5 and 7 can have their RGB settings altered using OUT as shown in **Bold** below:
```text
  ***SCREEN 0 or 9 SCREEN 7***
  Attribute = DAC setting Attribute = DAC setting
  ** 0 to 5 = 0 to 5  0 to 5 = 0 to 5**
   6 = 20 ** 6 = 6**
 7 = 7 7 = 7**
 8 = 56 8 = 16
   9 = 57 9 = 17
10 = 58 10 = 18
11 = 59 11 = 19
12 = 60 12 = 20
13 = 61 13 = 21
14 = 62 14 = 22
15 = 63 15 = 23
**OUT can change RGB intensities where the DAC value matches the attribute value.**
```
Changing the DAC attributes to use [OUT](OUT) for custom colors.
```vb
SCREEN 9 'use 0, 7 or 9 only"
InitDAC% = INP(&H3DA) ' prepare DAC port for access
FOR attribute% = 6 TO 15 ' attributes 0 to 5 are already non-DAC
OUT &H3C0, attribute% ' send attribute to change
OUT &H3C0, attribute% ' change DAC value to normal number
NEXT attribute%"
OUT &H3C0, 32 ' close port access
```
> *Explanation:* The procedure is a MUST to import 4 BPP bitmap colors in SCREEN 7 or 9. The InitDAC% value is not used, but that code line opens the DAC color port. Now all color attributes 0 to 15 can be used for custom or imported bitmap RGB color settings.
Disabling blinking colors in fullscreen SCREEN 0 mode enabling high intensity only. ([DAC](DAC))
```vb
D = INP(&H3DA) 'prepares port for access
OUT &H3C0, &H30
OUT &H3C0, 4
```
> *Explanation:* Make attributes 8-15 available to both foreground AND background colors. In other words it will make fullscreen behave like windowed mode. For the same effect in QB64, use [_BLINK](_BLINK) OFF.
*Enabling:* The following code disables above code and returns SCREEN 0 blinking to normal.
```vb
D = INP(&H3DA) 'prepares port for access
OUT &H3C0, &H30
OUT &H3C0, 12
```
> **NOTE: QB64** allows blinking mode in both fullscreen and windowed modes **without** using the code above. To reenable blinking in QB64 after using [_BLINK](_BLINK) OFF, use [_BLINK](_BLINK) ON.
## See Also
* [SCREEN (statement)](SCREEN-(statement)), [COLOR](COLOR)
* [PALETTE](PALETTE)

92
wiki/DATA.md Normal file
View file

@ -0,0 +1,92 @@
The [DATA](DATA) statement creates a line of fixed program information separated by commas. The DATA can be later READ by the program at runtime.
## Syntax
> [DATA](DATA) [value1, value2, ...]
## Description
* DATA is used at the beginning of every data field line with commas separating the values that follow.
* Values can be any **literal** [STRING](STRING) or numerical type. **Variables cannot be used.**
* DATA fields can be placed and READ consecutively in the main program code body with or without line labels for [RESTORE](RESTORE).
* DATA is best placed after the main program code.
* **QB64** DATA can be placed inside a [SUB](SUB) or [FUNCTION](FUNCTION) procedures.
* [RESTORE](RESTORE) will only read the first data field if the DATA is not labeled or no label is specified in a RESTORE call.
* When using multiple DATA fields, label each data field with a line label so that each data pointer can be reset for multiple reads with **[RESTORE](RESTORE) *linelabel***.
* QBasic comma separations were flexible to allow column alignments when creating them. QB64 removes spacing between commas.
* [STRING](STRING) DATA values with end spaces, QBasic keywords and values that include the comma character must be enclosed in quotation marks.
* DATA fields can only be created by the programmer and cannot be changed by a user or lost.
* Comments after a data line require a colon before the comment.
* If a [READ](READ) statement attempts to read past the last data value, an [ERROR Codes](ERROR-Codes) will occur. Use end of data markers when necessary.
* **[DATA](DATA) fields can be placed after [SUB](SUB) or [FUNCTION](FUNCTION) procedures, but line labels are not allowed.**
## Example(s)
Creating two DATA fields that can be [READ](READ) repeatedly using [RESTORE](RESTORE) with the appropriate line label.
```vb
RESTORE Database2
READ A$, B$, C$, D$ 'read 4 string values from second DATA field
PRINT A$ + B$ + C$ + D$ 'note that quoted strings values are spaced
RESTORE Database1
FOR i = 1 TO 18
READ number% 'read first DATA field 18 times only
PRINT number%;
NEXT
END
Database1:
DATA 1, 0, 0, 1, 1, 0, 1, 1, 1
DATA 2, 0, 0, 2, 2, 0, 2, 2, 2 : ' DATA line comments require a colon
Database2:
DATA "Hello, ", "world! ", Goodbye, work!
```
```text
Hello world! Goodbyework!
1 0 0 1 1 0 1 1 1 2 0 0 2 2 0 2 2 2
```
How to [RESTORE](RESTORE) and [READ](READ) DATA in a [SUB](SUB) procedure in QB64. Line labels can be used for multiple DATA fields.
```vb
DIM SHARED num(10) 'shared array or must be passed as a parameter
ReadData 2 '<<<<<<< change value to 1 to read other data
FOR i = 1 TO 10
PRINT num(i);
NEXT
END
SUB ReadData (mode)
IF mode = 1 THEN RESTORE mydata1 ELSE RESTORE mydata2
FOR i = 1 TO 10
READ num(i)
NEXT
mydata1:
DATA 1,2,3,4,5,6,7,8,9,10
mydata2:
DATA 10,9,8,7,6,5,4,3,2,1
END SUB
```
```text
10 9 8 7 6 5 4 3 2 1
```
## See Also
* [READ](READ)
* [RESTORE](RESTORE)
* [SUB](SUB), [FUNCTION](FUNCTION)

View file

@ -0,0 +1 @@
See [DATE$](DATE$).

71
wiki/DATE$.md Normal file
View file

@ -0,0 +1,71 @@
The [DATE$](DATE$) function returns the current computer date as a string in the format "mm-dd-yyyy".
## Syntax
> today$ = [DATE$](DATE$)
## Description
* Returns the current computer date in the format "mm-dd-yyyy" (e.g., "12-25-2009").
## Example(s)
Displaying the weekday and current date.
```vb
PRINT DATE$
month$ = LEFT$(DATE$, 2): M = VAL(month$)
day$ = MID$(DATE$, 4, 2): D = VAL(day$)
day$ = STR$(D) ' eliminate any leading zeros
year$ = RIGHT$(DATE$, 4): Y = VAL(year$)
SELECT CASE M
CASE 1: Moon$ = "January"
CASE 2: Moon$ = "February"
CASE 3: Moon$ = "March"
CASE 4: Moon$ = "April"
CASE 5: Moon$ = "May"
CASE 6: Moon$ = "June"
CASE 7: Moon$ = "July"
CASE 8: Moon$ = "August"
CASE 9: Moon$ = "September"
CASE 10: Moon$ = "October"
CASE 11: Moon$ = "November"
CASE 12: Moon$ = "December"
END SELECT
PRINT "Today is " + WeekDay$(M, D, Y) + ", " + Moon$ + day$ + ", " + year$ + SPACE$(10)
DEFINT A-Z
FUNCTION WeekDay$ (M, D, Y)
IF M < 3 THEN M = M + 12: Y = Y - 1 'add 12 to Jan - Feb month, -1 year
C = Y \ 100: Y = Y MOD 100 'split century and year number
S1 = (C \ 4) - (2 * C) - 1 'century leap
S2 = (5 * Y) \ 4 '4 year leap
S3 = 26 * (M + 1) \ 10 'days in months
WkDay = (S1 + S2 + S3 + D) MOD 7 'weekday total remainder
IF WkDay < 0 THEN WkDay = WkDay + 7 'Adjust negative results to 0 to 6
SELECT CASE WkDay
CASE 0: day$ = "Sunday"
CASE 1: day$ = "Monday"
CASE 2: day$ = "Tuesday"
CASE 3: day$ = "Wednesday"
CASE 4: day$ = "Thursday"
CASE 5: day$ = "Friday"
CASE 6: day$ = "Saturday"
END SELECT
WeekDay$ = day$
END FUNCTION
```
```text
06-02-2010
Today is Wednesday, June 2, 2010
```
## See Also
* [TIME$](TIME$)
* [VAL](VAL), [STR$](STR$), [MID$](MID$), [LEFT$](LEFT$), [IF...THEN](IF...THEN)

View file

@ -0,0 +1,106 @@
**DECLARE DYNAMIC LIBRARY** allows you to dynamically link your program to functions in dynamically linkable libraries. At present, '**.dll**' , '**.so**' and '**.dylib**' files are supported. These libraries are loaded when your program begins. For **STATIC** library's '**.lib**', '**.h**', '**.hpp**', '**.a**', '**.o**' and '**.dylib**' files are also supported.
## Syntax
> **DECLARE** [**DYNAMIC**|**CUSTOMTYPE**|**STATIC**] **LIBRARY** [*"Library_file"*,_"other_lib_files"_]
>
>> {[SUB](SUB)|[FUNCTION](FUNCTION)} [*procedure_name* **ALIAS**] *library_procedure* (**BYVAL** *parameter(s)* [AS](AS) varType,...)
>>
>> ... 'other Library sub-procedures for named *DLL*
>
> **END DECLARE**
## Description
* The dynamic library file can be located in the QB64 folder (alongside your programs '.EXE'), in Windows' system32 folder, or in a relative/absolute path specified along with the library name.
* **Declarations must be made at the program start and only one file can be specified in each declaration block.**
* *Library_file* is the *library* file's name with a specified path when not in the QB64 or in the WINDOWS\SYSTEM32 folder. **Don't add the file extension**.
* *Library filename*s can be listed to combine more than one DLL or Header file name or path into one DECLARE LIBRARY block.
* *Procedure_name* is any procedure name you want to designate by using [ALIAS](ALIAS) with the *Library_procedure* name following.
* *Parameters* used by the Library procedure must be passed by value ([BYVAL](BYVAL)) except for [STRING](STRING) values.
* ***.h* header files cannot be used with DECLARE DYNAMIC LIBRARY. Existence of any *.h* file of the same name as the *.DLL* file will cause DECLARE DYNAMIC LIBRARY to fail.**
* **IMPORTANT:** [DECLARE DYNAMIC LIBRARY](DECLARE-DYNAMIC-LIBRARY) let's you specify any SUB/FUNCTION calling with the format you wish, but **if the size of the parameter list does not match the size expected within the library, then your code will probably cause a GPF (General Protection Fault).
* **STATIC** is the same as [DECLARE LIBRARY](DECLARE-LIBRARY) except that it prioritizes linking to static libraries (*.a/*.o) over shared object (*.so) libraries, if both exist. As Windows doesn't really use shared libraries (DLLs are a bit different) this does not affect Windows users.
* The [_OFFSET](_OFFSET) in memory can be used in **CUSTOMTYPE**, **STATIC** and **DYNAMIC LIBRARY** declarations.
* [SUB](SUB) procedures using DECLARE CUSTOMTYPE LIBRARY API procedures **may error**. Try DYNAMIC with the DLL name.
* Declarations can be made inside of [SUB](SUB) or [FUNCTION](FUNCTION) procedures. Declarations do not need to be at program start.
* **NOTE: It is up to the user to document and determine the suitability of all Libraries and procedures they choose to use. QB64 cannot guarantee that any procedure will work and cannot quarantee any troubleshooting help.**
## Availability
* Version 0.923 and up (Windows).
* Version 0.94 and up (Linux and macOS).
## Example(s)
This example plays Midi files using the *playmidi32.dll* documented here: [http://libertybasicuniversity.com/lbnews/nl110/midi3.htm Liberty Basic University]. Download the following DLL file to your main QB64 folder: [https://www.qb64.org/resources/Playmidi32.dll PlayMidi32.dll]
```vb
DECLARE DYNAMIC LIBRARY "playmidi32"
FUNCTION PlayMIDI& (filename AS STRING)
END DECLARE
result = PlayMIDI(".\samples\qb64\original\ps2battl.mid" + CHR$(0))
PRINT result
```
> **Note:** Filename needs to be [CHR$](CHR$)(0) terminated. QB64 [STRING](STRING)s are passed to external libraries as pointers to first character.
Using a CUSTOMTYPE LIBRARY to return the [Unicode](Unicode) version of the current running program's name.
```vb
SCREEN 12
DECLARE CUSTOMTYPE LIBRARY 'Directory Information using KERNEL32 provided by Dav
FUNCTION GetModuleFileNameA& (BYVAL hModule AS LONG, lpFileName AS STRING, BYVAL nSize AS LONG)
FUNCTION GetModuleFileNameW& (BYVAL hModule AS LONG, lpFileName AS STRING, BYVAL nSize AS LONG)
END DECLARE
'=== SHOW CURRENT PROGRAM
FileName$ = SPACE$(512)
Result = GetModuleFileNameA(0, FileName$, LEN(FileName$))
IF Result THEN PRINT "CURRENT PROGRAM (ASCII): "; LEFT$(FileName$, Result)
'load a unicode font
f = _LOADFONT("cyberbit.ttf", 24, "UNICODE")
_FONT f
Result = GetModuleFileNameW(0, FileName$, LEN(FileName$) \ 2)
LOCATE 2, 1
PRINT QuickCP437toUTF32$("CURRENT PROGRAM (UTF): ") + QuickUTF16toUTF32$(LEFT$(FileName$, Result * 2))
_FONT 16 'restore CP437 font
FUNCTION QuickCP437toUTF32$ (a$)
b$ = STRING$(LEN(a$) * 4, 0)
FOR i = 1 TO LEN(a$)
ASC(b$, i * 4 - 3) = ASC(a$, i)
NEXT
QuickCP437toUTF32$ = b$
END FUNCTION
FUNCTION QuickUTF16toUTF32$ (a$)
b$ = STRING$(LEN(a$) * 2, 0)
FOR i = 1 TO LEN(a$) \ 2
ASC(b$, i * 4 - 3) = ASC(a$, i * 2 - 1)
ASC(b$, i * 4 - 2) = ASC(a$, i * 2)
NEXT
QuickUTF16toUTF32$ = b$
END FUNCTION
```
> **Note:** SUB procedures using CUSTOMTYPE LIBRARY API procedures inside may error. Try DYNAMIC with "KERNEL32".
**QB64 version 1.000 and up produce standalone executables. External DLL files must be distributed with your program.**
**Note: QB64 versions prior to 1.000 require all default DLL files to either be with the program or in the C:\WINDOWS\SYSTEM32 folder.**
## See Also
* [DECLARE LIBRARY](DECLARE-LIBRARY)
* [SUB](SUB), [FUNCTION](FUNCTION)
* [BYVAL](BYVAL), [ALIAS](ALIAS)
* [_OFFSET (function)](_OFFSET-(function)), [_OFFSET](_OFFSET) (variable type)
* [C Libraries](C-Libraries), [DLL Libraries](DLL-Libraries), [Windows Libraries](Windows-Libraries)
* [Port Access Libraries](Port-Access-Libraries)

108
wiki/DECLARE-LIBRARY.md Normal file
View file

@ -0,0 +1,108 @@
The **DECLARE LIBRARY** declaration allows the use of external library [SUB](SUB) and [FUNCTION](FUNCTION) procedures supported by QB64.
## Syntax
> **DECLARE** [DYNAMIC|CUSTOMTYPE|STATIC] **LIBRARY** [{*"Library_filename"*|*"Headerfile"*}]
>
> {[SUB](SUB)|[FUNCTION](FUNCTION)} [*procedure_name* ALIAS] *library_procedure* ([BYVAL] *parameter AS*, ...)
>
> ... 'other SUBs or Functions as required
>
> **END DECLARE**
## Parameter(s)
* The Library_filename is needed if a Library is not already loaded by QB64. Do not include the *.DLL*, *LIB* or *.H* file extension.
* It's always a good idea to try declaring Windows API libraries without a Library_filename first, as most Windows headers are already included in QB64 source.
* Begin the Library_filename with **./** or **.\** to make it relative to the path where your source file is saved, so you can keep all your project files together.
* Procedure_name is any program procedure name you want to designate by using [ALIAS](ALIAS) with the Library_procedure name.
* Library procedure is the actual procedure name used inside of the library or header file.
### Library Types
* **[DECLARE DYNAMIC LIBRARY](DECLARE-DYNAMIC-LIBRARY)** links a program to functions in dynamically linkable libraries. At present, only .DLL files are supported
* **CUSTOMTYPE** is already implied when using [DECLARE DYNAMIC LIBRARY](DECLARE-DYNAMIC-LIBRARY). This type of library just allows the same flexibility to apply when referencing STATIC libraries that are used to refer to dynamic libraries. Supports shared object (*.so) libraries.
* **STATIC** is the same as [DECLARE LIBRARY](DECLARE-LIBRARY) except that it prioritizes linking to static libraries (*.a/*.o) over shared object (*.so) libraries, if both exist. As Windows doesn't use shared libraries (DLLs are different) this does not affect Windows users.
## Description
* The declaration can be used with C++ sub-procedures, Windows API and QB64 SDL (versions prior to 1.000)/OpenGL (version 1.000 and up) Libraries.
* *Library filename*s can be listed to combine more than one DLL or Header file name or path into one DECLARE LIBRARY block.
* C procedures can use a header file name. File code must be included with program code. Do not include the *.h* extension.
* *Parameters* used by the Library procedure must be passed by value ([BYVAL](BYVAL)) except for [STRING](STRING) characters.
* When using a procedure from an **unsupported** Dynamic Link Library (DLL file) use [DECLARE DYNAMIC LIBRARY](DECLARE-DYNAMIC-LIBRARY).
* The [_OFFSET](_OFFSET) in memory can be used in **CUSTOMTYPE**, **STATIC** and **DYNAMIC LIBRARY** declarations.
* Declarations can be made inside of [SUB](SUB) or [FUNCTION](FUNCTION) procedures. Declarations do not need to be at program start.
* **NOTE: It is up to the user to document and determine the suitability of all Libraries and procedures they choose to use! QB64 cannot guarantee that any procedure will work and cannot guarantee any troubleshooting help.**
## Example(s)
Using an **SDL** library procedure as a program SUB procedure to move the mouse pointer to a coordinate (works in versions prior to 1.000):
```vb
DECLARE LIBRARY
SUB SDL_WarpMouse (BYVAL column AS LONG, BYVAL row AS LONG) 'SDL procedure name
END DECLARE
SCREEN _NEWIMAGE(640, 480, 256) 'simulate screen 12 with 256 colors
RANDOMIZE TIMER
DO
_DELAY 1
x = RND * 640: y = RND * 480
LINE (x, y)-STEP(10, 10), RND * 100 + 32, BF
MouseMove x + 5, y + 5
LOOP UNTIL LEN(INKEY$) 'any keypress quits
END
SUB MouseMove (x AS LONG, y AS LONG)
SDL_WarpMouse x, y 'call SDL library procedure
END SUB
```
> *Explanation:* The SDL Library is included and loaded with QB64 versions prior to 1.000, so these procedures are directly available for use.
**Using [ALIAS](ALIAS) to create a program SUB or FUNCTION** using **QB64 SDL ONLY**
```vb
SCREEN 12
DECLARE LIBRARY
SUB MouseMove ALIAS SDL_WarpMouse (BYVAL column&, BYVAL row&)
END DECLARE
_DELAY 2
MouseMove 100, 100
_DELAY 2
MouseMove 200, 200
```
> *Explanation:* When a Library procedure is used to represent another procedure name use [ALIAS](ALIAS) instead. Saves creating a SUB!
Don't know if a C function is defined by C++ or QB64? Try using empty quotes.
```vb
DECLARE LIBRARY ""
FUNCTION addone& (BYVAL value&)
END DECLARE
```
> *Explanation:* The C function 'addone' exists in a library QB64 already links to, but it hasn't been defined as a C function or a QB64 function. By using "" we are telling QB64 the function exists in a library which is already linked to and that it must define the C function before calling it, as well as allowing QB64 code to call it. Trying the above code without the "" will fail.
> **Note: Which libraries are or aren't automatically used in the linking process is not formally defined, nor is it guaranteed to stay that way in future versions of QB64.**
**QB64 version 1.000 and up produce standalone executables. External DLL files must be distributed with your program.**
## See Also
* [DECLARE DYNAMIC LIBRARY](DECLARE-DYNAMIC-LIBRARY)
* [SUB](SUB), [FUNCTION](FUNCTION)
* [BYVAL](BYVAL), [ALIAS](ALIAS)
* [C Libraries](C-Libraries), [DLL Libraries](DLL-Libraries), [Windows Libraries](Windows-Libraries)
* [Port Access Libraries](Port-Access-Libraries)
* [SQL Client](SQL-Client)

802
wiki/DEF-SEG-=-0.md Normal file
View file

@ -0,0 +1,802 @@
The following **DOS BIOS** information can be used on Windows 9x machines. Not necessarily XP or NT! Each routine includes the hexadecimal and decimal registers.
> **NOTE: Few of these addresses are currenly accessable in QB64! Some may never be due to OS changes.**
> **DEF SEG = 0 LOW MEMORY PORT ADDRESSES**
> #### #### #### #### #### #### ####
> **PORT # | FUNCTION, DESCRIPTION OR COMMENTS FOR USE**
> #### #### #### #### #### #### #### #### #### #### =
## TIMER
* **&H42 (66)**
> SETS TIMER CHIP TO PRODUCE A FREQUENCY 20 TO 20,000 HZ:
```vb
A = INT(1193182 / F)
H = INT(A / 256)
L = A - H * 256
OUT 66, L: OUT 66, H
```
* **&H43 (67)**
> OUT 67, 182 PREPARES TIMER CHIP TO RECEIVE A VALUE.
* **&H46C - &H46E (1132 - 1134)**
> ticks& = PEEK (1132) + 256 * PEEK (1133) + 65536 + PEEK (1134)
> WILL PROVIDE THE NUMBER OF CLOCK TICKS SINCE MIDNIGHT 1 TO 1,533,039 (18.2 PER SEC)
> USING A ONE TICK TIMER LOOP:
```vb
DEF SEG = 0 ' set to PEEK and POKE TIMER
POKE (1132), 0 ' zero Timer ticks
DO
key = INP(&H60)
LOOP UNTIL PEEK(1132) >= 1 ' until one tick (@ 1/18th sec.) has passed
DEF SEG
```
* **&H470 = 1136)**
DETERMINING THE DATE n DAYS FROM NOW.
```vb
A$ = DATE$: PRINT A$ 'IMPORTANT! save original date!
IF n <= 255 THEN POKE 1136, n
IF n > 255 THEN
FOR D = 1 TO n: POKE 1136, 1: NEXT D
END IF
laterdate$ = DATE$
PRINT laterdate$ 'resulting date n days from today
DATE$ = A$ 'restore original computer date!
```
## HARDWARE
* **&H61 (97)**
> OUT 97,INP(97) OR 3 TO 'TURN THE SPEAKER ON.
> OUT 97,INP(97) OR 8 TO 'TURN THE CASSETTE MOTOR OFF.
> OUT 97,INP(97) AND 247 'TO TURN THE CASSETTE MOTOR ON.
> OUT 97,INP(97) AND 252 'TO TURN THE SPEAKER OFF.
> POKE (97),PEEK(97) OR 128 ' DISABLES PC/XT KEYBOARDS.
> POKE (97),PEEK(97) AND 127 ' ENABLES PC/XT KEYBOARDS.
## PRINTER
* **&H62 (98)**
> PEEK (98) PROVIDES CURRENT PRINTER WIDTH.
> POKE 98, w" SETS CURRENT PRINTER WIDTH TO w.
* **&H6C - &H6F (108 - 111)**
> POKE 108, 83: POKE 109, 255: POKE 110,0: POKE 111,240 'DISABLE CTRL-BRK.
> POKE 108, 240: POKE 109, 32: POKE 110,3: POKE 111,12 ' ENABLES CTRL-BRK.
## DISK
* **&H43F (1087)**
Determining the status of a drive motor:
```vb
IF PEEK(1087) AND 128 = 128 THEN PRINT "drive write in progress"
IF PEEK(1087) AND 15 = 0 THEN PRINT "No drive being written to"
```
Drive$ designated is A, B, C or D, and the letter must be in uppercase.
```vb
IF PEEK(1087) AND 2 ^ (ASC (Drive$) - 65) THEN PRINT "Drive: " Drive$
```
> **NOTE:** These value are not affected if an OUT was used to turn on the motor.
* **&H440 (1088)**
To turn on drive D for n seconds, where n is at MOST 14! :
```vb
POKE 1088, 18 + 2 * n
OUT 1010, 2 ^ (ASC("D") - 61) + ASC("D") - 53 '1010 = &H3F2
```
> **NOTE:** Location 1088 holds the countdown, in clock ticks, until the motor is shut off. To turn off all drives, send: OUT 1010, 12
* **&H445 (1093) **
track = PEEK(1093) 'determine the diskette track that was last accessed
* **&H446 (1094)**
head = PEEK(1094) 'determine which diskette head (0 or 1) was last accessed
* **&H447 (1095)**
sector = PEEK(1095) 'determine which diskette sector was last accessed
* **&H448 (1096)**
bytes = 128 * 2 ^ PEEK(1096) 'number of bytes per sector on a diskette
* **&H78 - &H7B (120 - 123)**
The diskette parameter table consists of 11 bytes
```vb
DEF SEG = 0
D = PEEK(120) + 256 * PEEK(121) ' get value of Diskette
DEF SEG = PEEK(122) + 256 * PEEK(123) 'set to derive the following table
track = (PEEK(D) AND 240) \ 8 'time(milliseconds) required for diskette drive to move track to track
HUT = (PEEK(D) AND 15) * 32 ' head unload time(milliseconds) after read or write has occurred
HLT = (PEEK(D + 1) AND 240) \ 4 'head load time (in milliseconds)
DirMode = (PEEK(D + 1) AND 15) 'Direct Memory Access mode
WT = PEEK(D + 2) 'wait time until turning the motor off
BPS = PEEK(D + 3) 'number of bytes per sector on the disk. FOR v = 0 TO 3: 128 * 2 ^ v bytes per sector,
SPT = PEEK(D + 4) 'number of sectors per track, usually 8 or 9
GapLen = PEEK(D + 5) 'gap length (in bytes) between sectors
DatLen = PEEK(D + 6) 'data length read or written into a sector when sector length not specified
GFLen = PEEK(D + 7) 'gap length used when formatting
FVal = PEEK(D + 8) 'value format operation uses to initialize diskette sectors, usually 256
HST = PEEK(D + 9) 'number of milliseconds for the heads to stabilize
MST = PEEK(D + 10) 'number of eighths of a second for motor startup
DEF SEG
```
> **WARNING: Changing the values of PEEK(D + 3) and PEEK(D + 4) can modify the way that diskettes are read and might require you to format your diskettes manually!**
* **&H504 (1284)**
If a single diskette drive is used for both drives A: and B:, current role is:
> PRINT "Current Drive: " + CHR$(65 + PEEK(1284))
* **&H475 (1141)**
numHD% = PEEK (1141) 'provides number of hard drives installed
* **&H413 - &H414 (1043-44)**
PEEK (1043) + 256 * PEEK(1044) 'indicates the RAM installed in kilobytes
* **&H3F2 (1010)**
OUT 1010, 12 'will turn off all drives
## PORTS
**PRINTER LPT Ports**
> &H411
> numLPT% = (PEEK (1041) AND 192) / 64 = the number of LPT printer adaptors installed.
> &H406, &H407
> firstLPT = PEEK(1030 + 2 * n) + PEEK(1031 + 2 * n) * 256
To swap two printers, interchange their initial port numbers.
Denote the first port associated with LPTn by Pn. The value
of P1 will be 956 if LPT1 is attached to the IBM monochrome display
and parallel printer adapter.
**RS-232 Serial port INTERFACE**
> &H411
The number of RS-232 cards attached can be found with: (PEEK(1041) AND 14)/2
> To determine the first of the seven ports associated with COMn:
> &H3FE, &H3FF
> PEEK(1022 + 2 * n) + 256 * PEEK(1023 + 2 * n).
> If this number is 0, then COMn is not available.
To swap two RS-232 interfaces, interchange their initial port numbers.
Denote the initial port associated with COMn by Pn (Base).
Normally, the value of P1 is 1016 and the value of P2 is 760.
Interrupt enabling: Base + 1 address
OUT Pn + 1, 1 enables an interrupt when a character has been received
OUT Pn + 1, 2 enables an interrupt when a character has been transmitted
OUT Pn + 1, 4 enables an interrupt when an error has occurred
OUT Pn + 1, 8 enables an interrupt when the modem status has changed
To enable several of the above interrupts at the same time, OUT the
sum of the associated numbers to port Pn + 1.
To identify interrupts, use the port number determined above Base + 2:
X = INP(Pn + 2).
IntSet% = X AND 1 'has a value of 1 as long as no interrupts have been
'issued because of communications port activity.
IntHi% = X AND 6 'is used to identify the highest priority interrupt
'pending, as indicated in the table "Interrupt Control
'Functions" in the IBM Technical Reference manual.
To establish the number of data bits (d), the number of stop bits (s), Base + 3
and the parity (p = 0 for no parity, p = 1 for odd parity, p = 3 for even parity),
Send: OUT Pn + 3, (d - 5) + (4 * (s - 1) + 8 * p).
To establish the baud rate: address = Base, Base + 1, Base + 3
H = INP(Pn + 3): OUT Pn + 3, H OR 128:
OUT Pn, DL: OUT Pn + 1, DH: OUT Pn + 3, H.
Use values DL = 128 and DH = 1 for 300
baud, and DL=96 and DH=0 for baud rate 1200.
Otherwise, DL = d MOD 256 and DH = d \ 256
Where d is the divisor number given by the IBM Technical Reference manual
in the table "Baud Rate at 1.853 MHz."
To produce a break signal: address = Base + 3
X = INP(Pn + 3)
OUT Pn + 3, X OR 64:PLAY "MF":SOUND 32767,6: SOUND 32767,1: OUT Pn+3,X.
The PLAY and SOUND statements produce a delay of 1/3 second.
To control the modem, use: address = Base + 4
OUT Pn + 4, 1 to assert that the data terminal is ready (DTR)
OUT Pn + 4, 2 to raise a request to send (RTS)
OUT Pn + 4, 16 to perform loopback testing
To accomplish several of the above tasks simultaneously, OUT the sum of the
associated numbers to port Pn + 4.
To determine the status of data transfer, begin with Base + 5:
LET X = INP(Pn + 5). Now:
idle% = X AND 64 'has a value of 64 if the transmitter shift register is idle
ready% = X AND 32 'is 32 if the transmitter holding register is ready to
'accept a character for transmission
break% = X AND 16 'has the value 16 if the received data input is held in the
'spacing state too long (that is, if a break was received)
nostop% = X AND 8 'has the value 8 if the received character did not have a
'valid stop bit; that is, if a framing error occurred
noPar% = X AND 4 'has the value 4 if the received character does not have correct
'parity
overR% = X AND 2 'is 2 if the received data destroyed the previous character
'(an overrun error)
RecRead% = X AND 1 'has value 1 if a character is ready to be read from received
'buffer register
INP(Pn) will read the ASCII value of a character from the serial port,
IF (INP(Pn + 5) AND 1) = 1 THEN char$ = CHR$(INP(Pn))
You can use OUT Pn, m to write the character with ASCII value m to the serial
read Base + 5 first:
IF (INP(Pn + 5) AND 32) = 32 THEN
To determine the status of the modem, use Base + 6:
X = INP(Pn + 6). Then:
X AND 128 has the value 128 if a Carrier signal has been detected
X AND 64 is 64 if the modem is ringing
X AND 32 has a value of 32 if the modem has asserted Data Set Ready
X AND 16 is 16 if the modem has asserted Clear to Send
X AND 8 is 8 if the Carrier Detect has changed state
X AND 4 has the value 4 if the Ring Indicator input has changed from On to Off
X AND 2 is 2 if the Data Set Ready input has changed state since last read
X AND 1 has a value of 1 if the Clear to Send input has changed since last read
&H3FE = 1022
> PROVIDES INFORMATION RELATED TO RS232 COMMUNICATIONS PORTS:
> PEEK(1022 + 2 * n) + PEEK(1023 + 2 * n) * 256
> WHERE COMn value = 0 IF COMn: IS NOT AVAILABLE.
> &H411 = 1041
> (PEEK (1041) AND 14)/2 'WILL PROVIDE NUMBER OF Serial RS232 PORTS INSTALLED.
> (PEEK (1041) AND 16)/16 'WILL PROVIDE NUMBER OF GAME PORTS INSTALLED.
> (PEEK (1041) AND 192)/64 'WILL PROVIDE NUMBER OF LPT Ports INSTALLED.
&H408 = 1032 | Provides Information on PRINTER PORTS (LPT)
> FOR i% = 1 TO 3
> lpt% = PEEK(&H408 + (i% - 1) * 2) + PEEK(&H408 + (i% - 1) * 2 + 1) * 256
> LOCATE , 23: PRINT "LPT"; HEX$(i%);
> IF lpt% = 0 THEN
> PRINT " not found"
> ELSE : PRINT " found at &H"; HEX$(lpt%); " ("; LTRIM$(STR$(lpt%)); ")"
> END IF
> IF lpt% = 888 THEN port378% = i% ' usually the LPT1 port printer address
> NEXT
## DISPLAY
> **DEF SEG = 0 MONITOR INFORMATION**
> #### #### #### #### #### ##
> To check the type of display:
> &H410 = 1040
> PEEK(1040) AND 48 = 0 ' is no monitors ' &H410
> PEEK(1040) AND 48 = 16 ' is a 40 x 25 graphics monitor
> PEEK(1040) AND 48 = 32 ' is a 80 x 25 graphics monitor
> PEEK(1040) AND 48 = 48 ' is a monochrome display
> To select a display:
> POKE 1040, PEEK(1040) OR 48 ' Monochrome
> SCREEN 0: WIDTH 80: LOCATE ,,1,0,0
> POKE 1040,(PEEK(1040) AND 207) OR 16 ' graphics
> SCREEN 1,0,0,0:WIDTH 80:LOCATE ,,1,0,0.
> &H44A, &H44B = 1098, 1099 ' (DEF SEG = 0)
> columns = PEEK(1098) + 256 * PEEK(1099) 'gives the present screen width in columns.
> (DEF SEG = 64)
> DEF SEG = &H40: textcols = PEEK(&H4A): DEF SEG
> &H44E, &H44F = 1102, 1103
Graphics screen contents stored in a buffer at:
> PEEK(1102) + 256 * PEEK(1103).
memory that physically resides on a graphics board.
> &H44C, &H44D = 1100, 1101
> PEEK(1100) + 256 * PEEK(1101) ' Buffer size
> The cursor locations for the various pages are given as follows:
> Let CR(n) and CC(n) be the Cursor Row and Cursor Column for page n.
> &H450, &H451 = 1004, 1005
> PEEK(1105) + 2 * n) ' has a value of CR(n) - 1,
> PEEK(1104 + 2 * n) ' has a value of CC(n) - 1.
> &H460 to &H462 = 1120 to 1122
> The shape of the cursor can be set as follows: LOCATE ,,,I,J.
> :PEEK(1121) AND 31 ' has value I
> :PEEK(1120) AND 31 ' has value J.
> :PEEK(1121) AND 32 ' = 32 then cursor is not displayed.
> :PEEK(1122) ' will equal the active visual page.
To determine the active 6845 index register:
&H463 &H464
"PEEK(1123) + 256 * PEEK(1124)" = 948 if monochrome display board in use.
= 980 for the color/graphics adapter.
To check the 6845 mode settings:
&H465
PEEK(1125) AND 1 has value 1 if in text mode, width 80
PEEK(1125) AND 2 has value 2 if in graphics mode
PEEK(1125) AND 4 has value 4 if color is disabled.
PEEK(1125) AND 8 has value 8 if video is enabled.
PEEK(1125) AND 16 has value 16 if in high-resolution graphics mode
PEEK(1125) AND 32 has value 32 if blinking is enabled
Background color and palette selected by COLOR bg,fc :
&H466
bg = (PEEK(1126) AND 15) 'background color
fc = (PEEK(1126) AND 32)/32 'fore color
bc = PEEK(1126) MOD 16 'border color
> &H410 = 1040
> :| (PEEK (1040) AND 1) * (1 + PEEK (1040)) \ 64 PROVIDES NUMBER OF DRIVES.
> :| PEEK (1040) AND 48
> :| 0 = NO MONITOR INSTALLED.
> :| 16 = 40 x 25 GRAPHICS.
> :| 32 = 80 x 25 GRAPHICS.
> :| 48 = MONOCHROME.
> :| "POKE (1040), PEEK(1040) OR 48" SELECTS MONOCHROME DISPLAY.
> :| "POKE (1040), PEEK(1040) AND 207 OR 32" SELECTS 80 x 25 GRAPHICS.
> ::NOTE: | SCREEN 0,0,0:WIDTH 80 SHOULD BE USED BEFORE CALLING MONOCHROME.
> ::NOTE: | SCREEN 1,0,0,0:WIDTH 80 SHOULD BE USED BEFORE CALLING 80 x 25 GRAPHICS
> ::NOTE: | SAVE VALUES IN PORTS 1097 THRU 1126 IN AN ARRAY FOR RESTORING IN THE EVENT THAT YOU WANT TO CHANGE BACK TO ORIGINAL DISPLAY WITH CONFIDENCE
> &H449 = 1097 PEEK (1097) PROVIDES DISPLAY MODE INFORMATION:
> : 0 = TEXT MODE, WIDTH 40, NO COLOR.
> : 1 = TEXT MODE, WIDTH 40, COLOR.
> : 2 = TEXT MODE, WIDTH 80, NO COLOR.
> : 3 = TEXT MODE, WIDTH 80, COLOR.
> : 4 = MEDIUM GRAPHICS MODE, COLOR.
> : 5 = MEDIUM GRAPHICS MODE, NO COLOR.
> : 6 = HIGH RESOLUTION GRAPHICS.
> : 7 = TEXT MODE, WIDTH 80, MONOCHROME.
> &H449 - &H44A = 1097-98
> : | POKE (1097),4:POKE (1098),40 ' PROVIDES SCREEN 2 WITH WIDTH 40.
> : | POKE (1097),6:POKE (1098),80 ' PROVIDES SCREEN 2 WITH WIDTH 80.
&H44C, &H44D, &H44E, &H44F = 1100-03 CONTAINS CONTENTS OF GRAPHICS MEMORY RESIDING ON THE DISPLAY CARD.
> : | SIZE = PEEK(1100) + 256 * PEEK(1101)
> : | LOCATION = PEEK(1102) + 256 * PEEK(1103)
> &H450 - &H451 = 1104-05 CONTAINS CURSON LOCATIONS FOR VARIOUS GRAPHICS MEMORY PAGES.
> :| COL = PEEK(1104 + 2 * n)
> :| ROW = PEEK(1105 + 2 * n)" WHERE n IS THE PAGE.
> &H460 = 1120
> :| J = PEEK (1120) AND 31 ' REFLECTS VALUE OF LOCATE ,,,I,J.
> &H461 = 1121
> :| I = PEEK (1121) AND 31 ' REFLECTS VALUE OF LOCATE ,,,I,J.
> :| PEEK (1121) AND 32 = 32 ' IF CURSOR ON / 0 IF OFF.
> :| POKE (1121),PEEK (1121) OR 32 ' TURNS OFF CURSOR.
> &H462 = 1122
> :| PEEK (1122) ' RETURNS THE NUMBER OF ACTIVE SCREEN PAGES.
> &H465 = 1125
> :| PEEK (1125) AND 1 = 1 ' IF ACTIVE CRT IS TEXT MODE WIDTH 80.
> :| PEEK (1125) AND 2 = 2 ' IF ACTIVE CRT IS IN GRAPHICS MODE.
> :| PEEK (1125) AND 4 = 4 ' IF ACTIVE CRT HAS COLOR DISABLED.
> :| PEEK (1125) AND 8 = 8 ' IF ACTIVE CRT HAS NOT BEEN BLANKED.
> :| PEEK (1125) AND 16 = 16 ' IF ACTIVE CRT IS IN HIGH RES. GRAPHICS.
> :| PEEK (1125) AND 32 = 32 ' IF ACTIVE CRT BLINKING IS ENABLED.
&H466 = 1126
> CONTAINS THE BACKGROUND COLOR AND PALETTE VALUES WHEN DISPLAY IS IN MEDIUM RESOLUTION.
> :| WHERE COLOR b, p:
> :| b = PEEK (1126) AND 15
> :| p = (PEEK(1126) AND 32)/32
> WHILE IN TEXT MODE, IT CONTAINS THE FOREGROUND AND BACKGROUND.
> :| WHERE COLOR f, b:
> :| f = PEEK (1126) AND 16
> :| b = PEEK(1126) MOD 16
> &H7C, &H7D, &H7E, &H7F, &H80 = 124 - 128
> :| CONTAINS EXTENDED CHARACTER SET 128 THRU 254 IN GRAPHICS MODE.
> :| "n = PEEK (124) + 256 * PEEK (125)" WILL BE CHR$(128).
> :| "n = PEEK (126) + 256 * PEEK (127)" WILL BE CHR$(129).
&H3BE = 985
> :| "POKE (985), x" CHANGES GRAPHICS COLOR WHERE x IS COLOR.
* **&H74 - 75 (116-117)** VIDEO PARAMETER TABLE.
> : **BE CAREFUL! - CHANGES HERE COULD PHYSICALLY DAMAGE A MONITOR!**
## KEYBOARD
> ::::**KEYBOARD Buffer**
> ::::#### ##
> &H41A = 1050: &H41C = 1052
> :Keyboard buffer begins at PEEK(1050) + 1024 and ends at PEEK(1052) + 1023.
> :Ordinary characters use every other location. Extended characters use two locations, the first location containing the null character (CHR$(0)).
> ::POKE 1050, PEEK(1052) ' clears the keyboard buffer.
> :Buffer contents can be read by PEEK without being removed from the buffer.
> ::::::::**CTRL-Break**
> &H6C, &H6D, &H6E, &H6F = 108 to 111
> :Before disabling Ctrl-Break, use PEEK to record the bytes in locations 108-111 !
> ::FOR I = 0 TO 3: Array(I) = PEEK(108 + I): NEXT I
> :To disable Ctrl-Break, enter:
> ::FOR I = 0 TO 3: POKE(108 + I), PEEK(112 + I): NEXT I.
> :To re-enable Ctrl-Break enter saved values from Array:
> ::FOR I = 0 TO 3: POKE(108 + I), Array(I): NEXT I
> &H471 = 1137
> :ChkCtrl% = PEEK(1137) AND 128 = 128 ' if Ctrl-Break used since start of a program.
> : NOTE: NT and XP computers will block some keyboard OUT changes!
> &H61 = 97
> :To disable the keyboard (PC & XT only), send OUT 97, INP(97) OR 128.
> :To enable the keyboard (PC & XT only), send OUT 97, INP(97) AND 127.
> &H21 = 33
To disable all keyboard interrupts: OUT 33, 130.
To enable keyboard interrupts: OUT 33, 128.
> For the PC-AT only, the green lights that indicate CapsLock, NumLock and the ScrollLock status can be turned on and off without altering any of the states.
> :: NOTE: NT or XP will block access to the keyboard lights!
> &H60 = 96
> The statement: OUT 96, 237: OUT 96, n produces the following results:
> ::n = 7 all indicators on
> ::n = 6 ScrollLock indicator off, others on
> ::n = 5 NumLock indicator off, others on
> ::n = 4 CapsLock indicator on, others off
> ::n = 3 CapsLock indicator off, others on
> ::n = 2 NumLock indicator on, others off
> ::n = 1 ScrollLock indicator on, others off
> ::n = 0 all indicators off
&H417 = 1047
> : PEEK (1047) AND 1 = 1 ' IF RIGHT SHIFT IS PRESSED
> : PEEK (1047) AND 2 = 2 ' IF LEFT SHIFT IS PRESSED
> : PEEK (1047) AND 4 = 4 ' IF CTRL KEY IS PRESSED.
> : PEEK (1047) AND 8 = 8 ' IF ALT KEY IS PRESSED.
> : PEEK (1047) AND 16 = 16 ' IF SCROLL LOCK IS ON / 0 IF OFF.
> : PEEK (1047) AND 32 = 32 ' IF NUMBER PAD IS ON / 0 IF OFF.
> : PEEK (1047) AND 64 = 64 ' IF CAPS LOCK IS ON / 0 IF OFF.
> : PEEK (1047) AND 128 = 128 ' IF INSERT MODE IS ON / 0 IF OFF.
> :::::ENABLING MODES(will not affect lights)
> : POKE (1047),PEEK (1047) OR 16 ' ENABLES SCROLL LOCK.
> : POKE (1047),PEEK (1047) OR 32 ' ENABLES NUMBER LOCK.
> : POKE (1047),PEEK (1047) OR 64 ' ENABLES CAPS LOCK.
> : POKE (1047),PEEK (1047) OR 128 ' ENABLES INSERT MODE.
> :::::DISABLING MODES(will not affect lights)
> : POKE (1047),PEEK (1047) AND 239 ' TURNS OFF SCROLL LOCK.
> : POKE (1047),PEEK (1047) AND 223 ' TURNS OFF NUMBER LOCK.
> : POKE (1047),PEEK (1047) AND 191 ' TURNS OFF CAPS LOCK.
> : POKE (1047),PEEK (1047) AND 127 ' TURNS OFF INSERT MODE.
> :::::ALTERNATING MODES(will not affect lights)
> : POKE (1047),PEEK (1047) XOR 16 ' CHANGES SCROLL LOCK MODE.
> : POKE (1047),PEEK (1047) XOR 32 ' CHANGES NUMBER LOCK MODE.
> : POKE (1047),PEEK (1047) XOR 64 ' CHANGES CAPS LOCK MODE.
> : POKE (1047),PEEK (1047) XOR 128 ' CHANGES INSERT MODE.
> :::::::XP codes for Alt and Ctrl
> ::: DEF SEG = 0
> ::: DO
> :::: IF PEEK(1047) MOD 16 = 8 THEN SOUND 1000, 1: REM Alt
> :::: IF PEEK(1047) MOD 16 = 4 THEN SOUND 100, 1: REM Ctrl
> :::: IF INKEY$ = CHR$(27) THEN EXIT DO
> ::: LOOP
> ::: DEF SEG
> &H41A = 1050
> : | KEYBOARD INPUT BUFFER STORED AT "PEEK(1050) + 1024" TO "PEEK(1052) + 1053"
> :: EACH CHARACTER HAS 2 BYTES RESERVED TO COVER EXTENDED CHARACTERS.
## OTHER
> &H50F = 1295
> :| POKE 1295,2
> :SYSTEM WILL LEAVE THE BASIC(A) FLAG SET TO INDICATE A SHELL TO DOS HAS OCCURRED AND PREVENT ACCESS TO BASIC(A) AGAIN.
> :::::**SPEAKER &H61**
> :::::###
To turn the speaker on, use: OUT 97,INP(97) OR 3
Conversely, to turn the speaker off: OUT 97, INP(97) AND 252
> :::::**CASETTE PORT CONTROL &H61**
> :::::#### #### #### #### =
To turn the cassette motor on: OUT 97,INP(97) AND 247
To turn the cassette motor off: OUT 97,INP(97) OR 8
> ::::**MISCELLANEOUS**
> ::::####
&H411
1041 (PEEK (1041) AND 16)/16 = number of game adaptors attached.
&H413
1043 PEEK(1043) + 256 * PEEK(1044) = size of RAM in KB.
&H46C
1132 PEEK(1132) + 256 * PEEK(1133) + 65536 PEEK(1134) = number of ticks since midnight.
With 18.2 ticks per second up to 1,533,039.
Memory locations 1264 to 1279 are not used by either DOS or BASIC.
Data can be passed from one program to another by POKEing and PEEKING.
&H50F
1295 To exit BASIC and complicate reinvoking it, you can:
POKE 1295, 2: SYSTEM.
Memory location 1295 is set to 2 when the BASIC command SHELL is executed.
&H510 - &H511
1296-7 The segment number of BASIC's data segment may be found with:
PEEK(1296) + 256 * PEEK(1297)
## BASICA
> :::::NOTE: DEF SEG BASIC(A) MEMORY PORT ADDRESSES
> :::**PORT # | FUNCTION, DESCRIPTION OR COMMENTS FOR USE**
> :::#### #### #### #### #### #### #### #### #### #### =
11-13 | USED BY BASIC(A) FOR RANDOM NUMBER GENERATION.
40 | CONTAINS LAST ERROR NUMBER IN BASIC(A).
41 | BASIC(A) SCROLLING LIMITER - SEE# 91 FOR MORE DETAILS.
44-45 | CONTAINS BASIC(A) ENVIRONMENT EQUATIONS.
46-47 | "PEEK (46)+256*PEEK(47)" RETURNS CURRENT BASIC(A) LINE NUMBER.
72 | "PEEK(72)" RETURNS CURRENT SCREEN MODE:
0 = TEXT MODE, WIDTH 40, COLOR BURST DISABLED.
1 = TEXT MODE, WIDTH 40, COLOR BURST ENABLED.
2 = TEXT MODE, WIDTH 80, COLOR BURST DISABLED.
3 = TEXT MODE, WIDTH 80, COLOR BURST ENABLED.
4 = MEDIUM RESOLUTION GRAPHICS, COLOR BURST ENABLED.
5 = MEDIUM RESOLUTION GRAPHICS, COLOR BURST DISABLED.
6 = HIGH RESOLUTION GRAPHICS, COLOR BURST DISABLED.
7 = MONOCHROME DISPLAY.
75 | "PEEK(75)" DETERMINES TEXT MODE FOREGROUND COLOR.
76 | "PEEK(76)" DETERMINES TEXT MODE BACKGROUND COLOR.
77 | "PEEK(77)" DETERMINES TEXT MODE BORDER COLOR.
78 | "PEEK(78) AND 3" DETERMINES MEDIUM RESOLUTION TEXT COLOR.
"POKE 78,c" SETS MEDIUM RES. TO COLOR c=(1/2/3) OF PALETTE.
81 | "POKE (81) AND 15" PROVIDES MEDIUM RES. BACKGROUND COLOR.
82 | "POKE (82) MOD 2" PROVIDES MEDIUM PALETTE.
86 | "POKE (86)" PROVIDES CURSOR ROW NUMBER.
87 | "POKE (87)" PROVIDES CURSOR COLUMN NUMBER.
91-92 | USED TO CREATE SCROLLING LIMITERS.
"POKE 41, c: POKE 91, a: POKE 92, b"
WHERE: a=STARTING LINE b=ENDING LINE c=NUMBER OF POSITIONS.
| "POKE 92,0" WILL PREVENT ALL SCROLLING.
| "POKE 92,25" WILL SCROLL ALL 25 LINES.
100 | "PEEK (100)" RETURNS 1 IF CASSETTE MOTOR OFF / 0 IF OFF.
113 | "PEEK (113)" DETERMINES IF SOFTKEYS DISPLAYED.
0 = IF SOFTKEYS NOT DISPLAYED.
1 = ALWAYS DISPAYED.
255 = INVOKED BY "KEY ON"
835-836 | "PEEK (835) + 256 * PEEK(836)" POINTS TO LAST STATEMENT EXECUTED.
837-838 | "PEEK (837) +256 * PEEK(838)" MEMORY LOCATION BY THE BASIC(A) STACK POINTER.
839-840 | "PEEK (839) + 256 * PEEK(840)" LINE NUMBER OF LAST BASIC(A) ERROR.
BASIC(A) STACK POINTER.
845-846 | "PEEK (845)+256*PEEK (846)" LINE NUMBER POINTED TO BY BASIC(A)
ON ERROR GOTO STATEMENT.
848-849 | "PEEK (848)+256*PEEK (849)" RETURNS BASIC(A) DATA SEGMENT.
862-863 | "PEEK (848)+256*PEEK (849)" POINTS TO NEXT BYTE OF LAST BASIC(A) DATA MOST
RECENLTY READ. (READ DATA LOOP)
1116 | "PEEK (1116)" RETURNS MINIMUM ALLOWABLE VALUE FOR ARRAY SUBSCRIPTS
1124 | "PEEK (1124) = 0 IF FILE IN MEMORY NOT PROTECTED.
1125 | "POKE 1125,255" PROTECTS BASIC(A) FILE IN MEMORY.
"PEEK (1125) AND 1" WILL = 1 IF ACTIVE CRT IS TEXT MODE WIDTH 80.
"PEEK (1125) AND 2" WILL = 2 IF ACTIVE CRT IS IN GRAPHICS MODE.
"PEEK (1125) AND 4" WILL = 4 IF ACTIVE CRT HAS COLOR DISABLED.
"PEEK (1125) AND 8" WILL = 8 IF ACTIVE CRT HAS NOT BEEN BLANKED.
"PEEK (1125) AND 16" WILL = 16 IF ACTIVE CRT IS IN HIGH RES. GRAPHICS.
"PEEK (1125) AND 32" WILL = 32 IF ACTIVE CRT BLINKING IS ENABLED.
1247 | "PEEK (1247)" REFLECTS NUMBER OF FILES SPECIFIED BY BASIC(A)/F
COMMAND LINE PARAMETER.
1248-49 | "PEEK (1248)+256*PEEK(1249)" POINTS TO FILE CONTROL BLOCKS.
1264 | "CHR$(64 + PEEK(1264)) POINTS TO DRIVE LAST ACCESSED BY BASIC(A)
1265 | "A$="":FOR I = 1 TO 10 :A$ = CHR$(PEEK(1265+I)):NEXT I"
POINTS TO FILE MOST RECENTLY ACCESSED BY BASIC(A).
1295 | "POKE 1295,2:SYSTEM" WILL LEAVE THE BASIC(A) FLAG SET TO INDICATE A
SHELL TO DOS HAS OCCURRED AND PREVENT ACCESS TO BASIC(A) AGAIN.
1296-97 | BASIC(A) DATA SEGMENT NUMBER MAY BE FOUND. "PEEK(1296) + 256 * PEEK(1297)"
1339-40 | "PEEK (1339) + 256 * PEEK (1340)"POINTS TO Y COORDINATE LAST USED.
1341-42 | "PEEK (1341)+256*PEEK (1342)"POINTS TO X COORDINATE LAST USED.
1619 TO | STRINGS OF 15 CHARACTERS SEPARATED BY A NULL CHARACTER ARE STORED
1772 HERE TO DEFINE THE VALUE OF THE SOFTKEYS. (FUNCTION KEYS 1 THRU 10).
1782 | "PEEK (1782) AND 3" PROVIDES THE CURRENT COLOR FOR DRAW STAT.
| "POKE 1782, 85 * c" WILL CHANGE DRAW COLOR TO c.
1794-95 | "PEEK (1794) + 256 * PEEK (1795)" PROVIDES PROGRAM SEGMENT PREFIX.
## REFERENCE
## See Also
* [PEEK](PEEK), [POKE](POKE)
* [INP](INP), [OUT](OUT)
* [Screen Memory](Screen-Memory)

25
wiki/DEF-SEG.md Normal file
View file

@ -0,0 +1,25 @@
[DEF SEG](DEF-SEG) is used to define the area in memory to access QB64's emulated conventional memory.
## Legacy Support
* **QB64 implements memory access using [_MEM](_MEM) and related functions. For that reason, [DEF SEG](DEF-SEG) isn't recommended practice anymore and is supported to maintain compatibility with legacy code.**
## Syntax
> [DEF SEG](DEF-SEG) [=][{segment|VARSEG(variable}]
## Description
* Used to set the pointer to a memory area of a variable/array or register.
* [PEEK](PEEK) and [POKE](POKE) require a segment memory address (often just 0) without using VARSEG.
* Important segments using [PEEK](PEEK) and [POKE](POKE) include &HB800 (text segment) and &HA000 (graphics segment).
* [BSAVE](BSAVE) and [BLOAD](BLOAD) require a VARSEG reference to the grahic array(0 index) used.
* Always use DEF SEG when the procedure is completed, in order to reset the segment to QBasic's default value.
* [DEF SEG](DEF-SEG), [VARSEG](VARSEG), [VARPTR](VARPTR), [PEEK](PEEK) and [POKE](POKE) access QB64's emulated 16 bit conventional memory block. **It is highly recommended to use QB64's [_MEM](_MEM) memory system to avoid running out of memory.**
## See Also
* [DEF SEG = 0](DEF-SEG-=-0)
* [VARPTR](VARPTR), [VARSEG](VARSEG)
* [PEEK](PEEK), [POKE](POKE)
* [BSAVE](BSAVE), [BLOAD](BLOAD)

39
wiki/DEFDBL.md Normal file
View file

@ -0,0 +1,39 @@
The [DEFDBL](DEFDBL) statement defines all variables with names starting with the specified letter (or letter range) AS [DOUBLE](DOUBLE) variables instead of the [SINGLE](SINGLE) type default.
## Legacy Support
* **DEF** statements ([DEFDBL](DEFDBL), [DEFSNG](DEFSNG), [DEFLNG](DEFLNG), [DEFINT](DEFINT), [DEFSTR](DEFSTR)) were used when storage space was a concern in older computers, as their usage could save up typing. Instead of `**DIM a AS DOUBLE, a2 AS DOUBLE, a3 AS DOUBLE**`, simply having `**DEFDBL A**` in the code before using variables starting with letter **A** would do the same job.
* **For clarity, it is recommended to declare variables with meaningful names**.
## Syntax
> [DEFDBL](DEFDBL) letter[-range], letter2[-range2], [...]
## Description
* letter (or range) can be from A-Z or any other range, like **G-M**.
* You can also use commas for specific undefined variable first letters.
* Variables [DIM](DIM)ensioned as another variable type or that use type suffixes are not affected by [DEFDBL](DEFDBL).
* [DEFDBL](DEFDBL) sets the [Variable Types](Variable-Types) of all variable names with the starting letter(s) or letter ranges when encountered in the progression of the program (even in conditional statement blocks not executed and subsequent [SUB](SUB) procedures).
* **Warning: QBasic keyword names cannot be used as numerical variable names with or without the type suffix.**
## QBasic
* QBasic's IDE would add DEF statements before any [SUB](SUB) or [FUNCTION](FUNCTION). QB64 (like QBasic) will change all variable types in subsequent sub-procedures to that default variable type without giving a [ERROR Codes](ERROR-Codes) warning or adding DEF statement to subsequent procedures. If you do not want that to occur, either remove that DEF statement or add the proper DEF type statements to subsequent procedures. May also affect [$INCLUDE]($INCLUDE) procedures.
## Example(s)
```vb
DEFDBL A, F-H, M
'With the above, all variables with names starting with A, F, G, H and M
'will be of type DOUBLE, unless they have a type suffix
'indicating another type or they are dimensioned differently
```
## See Also
* [DEFSNG](DEFSNG), [DEFLNG](DEFLNG), [DEFINT](DEFINT), [DEFSTR](DEFSTR)
* [_DEFINE](_DEFINE)

40
wiki/DEFINT.md Normal file
View file

@ -0,0 +1,40 @@
The [DEFINT](DEFINT) statement defines all variables with names starting with the specified letter (or letter range) AS [INTEGER](INTEGER) variables instead of the [SINGLE](SINGLE) type default.
## Legacy Support
* **DEF** statements ([DEFDBL](DEFDBL), [DEFSNG](DEFSNG), [DEFLNG](DEFLNG), [DEFINT](DEFINT), [DEFSTR](DEFSTR)) were used when storage space was a concern in older computers, as their usage could save up typing. Instead of `**DIM a AS INTEGER, a2 AS INTEGER, a3 AS INTEGER**`, simply having `**DEFINT A**` in the code before using variables starting with letter **A** would do the same job.
* **For clarity, it is recommended to declare variables with meaningful names**.
## Syntax
> [DEFINT](DEFINT) letter[-range], letter2[-range2], [...]
## Description
* letter (or range) can be from A-Z or any other range, like **G-M**.
* You can also use commas for specific undefined variable first letters.
* Variables [DIM](DIM)ensioned as another variable type or that use type suffixes are not affected by [DEFINT](DEFINT).
* [DEFINT](DEFINT) sets the [Variable Types](Variable-Types) of all variable names with the starting letter(s) or letter ranges when encountered in the progression of the program (even in conditional statement blocks not executed and subsequent [SUB](SUB) procedures).
* For [_UNSIGNED](_UNSIGNED) [INTEGER](INTEGER), use [_DEFINE](_DEFINE)
* **Warning: QBasic keyword names cannot be used as numerical variable names with or without the type suffix.**
## QBasic
* QBasic's IDE would add DEF statements before any [SUB](SUB) or [FUNCTION](FUNCTION). QB64 (like QBasic) will change all variable types in subsequent sub-procedures to that default variable type without giving a [ERROR Codes](ERROR-Codes) warning or adding DEF statement to subsequent procedures. If you do not want that to occur, either remove that DEF statement or add the proper DEF type statements to subsequent procedures. May also affect [$INCLUDE]($INCLUDE) procedures.
## Example(s)
```vb
DEFINT A, F-H, M
'With the above, all variables with names starting with A, F, G, H and M
'will be of type INTEGER, unless they have a type suffix
'indicating another type or they are dimensioned differently
```
## See Also
* [DEFSNG](DEFSNG), [DEFLNG](DEFLNG), [DEFDBL](DEFDBL), [DEFSTR](DEFSTR)
* [_DEFINE](_DEFINE)

40
wiki/DEFLNG.md Normal file
View file

@ -0,0 +1,40 @@
The [DEFLNG](DEFLNG) statement defines all variables with names starting with the specified letter (or letter range) AS [LONG](LONG) variables instead of the [SINGLE](SINGLE) type default.
## Legacy Support
* **DEF** statements ([DEFDBL](DEFDBL), [DEFSNG](DEFSNG), [DEFLNG](DEFLNG), [DEFINT](DEFINT), [DEFSTR](DEFSTR)) were used when storage space was a concern in older computers, as their usage could save up typing. Instead of `**DIM a AS LONG, a2 AS LONG, a3 AS LONG**`, simply having `**DEFLNG A**` in the code before using variables starting with letter **A** would do the same job.
* **For clarity, it is recommended to declare variables with meaningful names**.
## Syntax
> [DEFLNG](DEFLNG) letter[-range], letter2[-range2], [...]
## Description
* letter (or range) can be from A-Z or any other range, like **G-M**.
* You can also use commas for specific undefined variable first letters.
* Variables [DIM](DIM)ensioned as another variable type or that use type suffixes are not affected by [DEFLNG](DEFLNG).
* [DEFLNG](DEFLNG) sets the [Variable Types](Variable-Types) of all variable names with the starting letter(s) or letter ranges when encountered in the progression of the program (even in conditional statement blocks not executed and subsequent [SUB](SUB) procedures).
* For [_UNSIGNED](_UNSIGNED) [LONG](LONG), use [_DEFINE](_DEFINE)
* **Warning: QBasic keyword names cannot be used as numerical variable names with or without the type suffix.**
## QBasic
* QBasic's IDE would add DEF statements before any [SUB](SUB) or [FUNCTION](FUNCTION). QB64 (like QBasic) will change all variable types in subsequent sub-procedures to that default variable type without giving a [ERROR Codes](ERROR-Codes) warning or adding DEF statement to subsequent procedures. If you do not want that to occur, either remove that DEF statement or add the proper DEF type statements to subsequent procedures. May also affect [$INCLUDE]($INCLUDE) procedures.
## Example(s)
```vb
DEFLNG A, F-H, M
'With the above, all variables with names starting with A, F, G, H and M
'will be of type LONG, unless they have a type suffix
'indicating another type or they are dimensioned differently
```
## See Also
* [DEFSNG](DEFSNG), [DEFDBL](DEFDBL), [DEFINT](DEFINT), [DEFSTR](DEFSTR)
* [_DEFINE](_DEFINE)

40
wiki/DEFSNG.md Normal file
View file

@ -0,0 +1,40 @@
The [DEFSNG](DEFSNG) statement defines all variables with names starting with the specified letter (or letter range) AS [SINGLE](SINGLE) variables.
## Legacy Support
* **DEF** statements ([DEFDBL](DEFDBL), [DEFSNG](DEFSNG), [DEFLNG](DEFLNG), [DEFINT](DEFINT), [DEFSTR](DEFSTR)) were used when storage space was a concern in older computers, as their usage could save up typing. Instead of `**DIM a AS SINGLE, a2 AS SINGLE, a3 AS SINGLE**`, simply having `**DEFSNG A**` in the code before using variables starting with letter **A** would do the same job.
* **For clarity, it is recommended to declare variables with meaningful names**.
## Syntax
> [DEFSNG](DEFSNG) letter[-range], letter2[-range2], [...]
## Description
* Undeclared variables with no type suffix are of type [SINGLE](SINGLE) by default.
* letter (or range) can be from A-Z or any other range, like **G-M**.
* You can also use commas for specific undefined variable first letters.
* Variables [DIM](DIM)ensioned as another variable type or that use type suffixes are not affected by [DEFSNG](DEFSNG).
* [DEFSNG](DEFSNG) sets the [Variable Types](Variable-Types) of all variable names with the starting letter(s) or letter ranges when encountered in the progression of the program (even in conditional statement blocks not executed and subsequent [SUB](SUB) procedures).
* **Warning: QBasic keyword names cannot be used as numerical variable names with or without the type suffix.**
## QBasic
* QBasic's IDE would add DEF statements before any [SUB](SUB) or [FUNCTION](FUNCTION). QB64 (like QBasic) will change all variable types in subsequent sub-procedures to that default variable type without giving a [ERROR Codes](ERROR-Codes) warning or adding DEF statement to subsequent procedures. If you do not want that to occur, either remove that DEF statement or add the proper DEF type statements to subsequent procedures. May also affect [$INCLUDE]($INCLUDE) procedures.
## Example(s)
```vb
DEFSNG A, F-H, M
'With the above, all variables with names starting with A, F, G, H and M
'will be of type SINGLE, unless they have a type suffix
'indicating another type or they are dimensioned differently
```
## See Also
* [DEFDBL](DEFDBL), [DEFLNG](DEFLNG), [DEFINT](DEFINT), [DEFSTR](DEFSTR)
* [_DEFINE](_DEFINE)

39
wiki/DEFSTR.md Normal file
View file

@ -0,0 +1,39 @@
The [DEFSTR](DEFSTR) statement defines all variables with names starting with the specified letter (or letter range) AS [STRING](STRING) variables instead of the [SINGLE](SINGLE) type default.
## Legacy Support
* **DEF** statements ([DEFDBL](DEFDBL), [DEFSNG](DEFSNG), [DEFLNG](DEFLNG), [DEFINT](DEFINT), [DEFSTR](DEFSTR)) were used when storage space was a concern in older computers, as their usage could save up typing. Instead of `**DIM a AS STRING, a2 AS STRING, a3 AS STRING**`, simply having `**DEFSTR A**` in the code before using variables starting with letter **A** would do the same job.
* **For clarity, it is recommended to declare variables with meaningful names**.
## Syntax
> [DEFSTR](DEFSTR) letter[-range], letter2[-range2], [...]
## Description
* letter (or range) can be from A-Z or any other range, like **G-M**.
* You can also use commas for specific undefined variable first letters.
* Variables [DIM](DIM)ensioned as another variable type or that use type suffixes are not affected by [DEFSTR](DEFSTR).
* [DEFSTR](DEFSTR) sets the [Variable Types](Variable-Types) of all variable names with the starting letter(s) or letter ranges when encountered in the progression of the program (even in conditional statement blocks not executed and subsequent [SUB](SUB) procedures).
* **Warning: QBasic keyword names can only be used as string variable names when they are followed by the string type suffix ($).**
## QBasic
* QBasic's IDE would add DEF statements before any [SUB](SUB) or [FUNCTION](FUNCTION). QB64 (like QBasic) will change all variable types in subsequent sub-procedures to that default variable type without giving a [ERROR Codes](ERROR-Codes) warning or adding DEF statement to subsequent procedures. If you do not want that to occur, either remove that DEF statement or add the proper DEF type statements to subsequent procedures. May also affect [$INCLUDE]($INCLUDE) procedures.
## Example(s)
```vb
DEFSTR A, F-H, M
'With the above, all variables with names starting with A, F, G, H and M
'will be of type STRING, unless they have a type suffix
'indicating another type or they are dimensioned differently
```
## See Also
* [DEFSNG](DEFSNG), [DEFLNG](DEFLNG), [DEFINT](DEFINT), [DEFDBL](DEFDBL)
* [_DEFINE](_DEFINE)

133
wiki/DIM.md Normal file
View file

@ -0,0 +1,133 @@
The [DIM](DIM) statement is used to declare a variable or a list of variables as a specified data type or to dimension [$STATIC]($STATIC) or [$DYNAMIC]($DYNAMIC) [Arrays](Arrays).
## Syntax
*To declare variables:*
>
> [DIM](DIM) [SHARED] *variable*[{suffix|[AS](AS) [[_UNSIGNED](_UNSIGNED)] *type*}] [, *variable2*...]]
>
*To declare arrays:*
>
> [DIM](DIM) [SHARED] *array([lowest% [TO](TO)] highest%])*[{suffix|[AS](AS) [[_UNSIGNED](_UNSIGNED)] *type*}] [, *variable2*...]
>
QB64 *Alternative Syntax:*
>
> [DIM](DIM) [SHARED] [AS](AS) [[_UNSIGNED](_UNSIGNED)] *typevariable* [, *variable2*...]
>
> [DIM](DIM) [SHARED] [AS](AS) [[_UNSIGNED](_UNSIGNED)] *typearray([lowest% [TO](TO)] highest%])* [, *array2(elements)*...]
## Description
* Sets the [INTEGER](INTEGER) range of elements (indices) of a [STATIC](STATIC) array. If only one number is used, the [LBOUND](LBOUND) is 0 by default.
* When used before an array is dimensioned, **[OPTION BASE](OPTION-BASE) 1** can set the default [LBOUND](LBOUND) of arrays to 1.
* DIM [SHARED](SHARED) shares variable values with sub-procedures without passing the value in a parameter.
* Use the [AS](AS) keyword to define a variable or array *type* [AS](AS)...
* [INTEGER](INTEGER) (or use variable suffix **%**)
* [LONG](LONG) (or use variable suffix **&**)
* [SINGLE](SINGLE) (or use variable suffix **!** or no suffix by default)
* [DOUBLE](DOUBLE) (or use variable suffix **#**)
* [STRING](STRING) (or use variable suffix **$**). An AS multiplier can set the string [LEN](LEN). Ex: `DIM *variable* AS STRING * 8`
* **QB64** variable types:
* [_BIT](_BIT) (or use variable suffix **\`**). An AS multiplier can be used for multiple bits. Ex: `DIM *variable* AS _BIT * 8`
* [_BYTE](_BYTE) (or use variable suffix **%%**)
* [_INTEGER64](_INTEGER64) (or use variable suffix **&&**)
* [_FLOAT](_FLOAT) (or use variable suffix **##**)
* [_OFFSET](_OFFSET) (or use variable suffix **%&**)
* DIM [AS](AS) [_MEM](_MEM) (the _MEM type has no type suffix).
* **Note: When a variable has not been defined or has no type suffix, the type defaults to [SINGLE](SINGLE).**
* When using the **[AS](AS) type variable-list** syntax, type symbols cannot be used.
* When the [$DYNAMIC]($DYNAMIC) metacommand or [REDIM](REDIM) is used, array element sizes are changeable (not [$STATIC]($STATIC)).
* Use [REDIM](REDIM) instead of DIM to dimension arrays as dynamic without the $DYNAMIC metacommand.
* Use [REDIM](REDIM) [_PRESERVE](_PRESERVE) in **QB64** to retain previous array values when changing the size of an array.
* [REDIM](REDIM) [_PRESERVE](_PRESERVE) cannot change the number of array dimensions. An [ERROR Codes](ERROR-Codes) will occur.
* [$DYNAMIC]($DYNAMIC) arrays MUST be [REDIM](REDIM)ensioned if [ERASE](ERASE) or [CLEAR](CLEAR) are used, as the arrays are completely removed.
* All numerical variable types **except** SINGLE, DOUBLE and _FLOAT can be dimensioned as [_UNSIGNED](_UNSIGNED) (suffix ~) or positive only.
* **NOTE:** Many QBasic keyword variable names can be used with a [STRING](STRING) suffix ($). You cannot use them without the suffix, use a numerical suffix or use *DIM, [REDIM](REDIM), [_DEFINE](_DEFINE), [BYVAL](BYVAL) or [TYPE](TYPE) variable [AS](AS)* statements. **Although possible, it's recommended to avoid using reserved names.**
* **Warning: Do not use negative array upper bound index values, or OS access or "Out of Memory" [ERROR Codes](ERROR-Codes) will occur.**
## Example(s)
Defines Qt variable as a one byte fixed length string.
```vb
DIM Qt AS STRING * 1
```
Dimensions and types an array.
```vb
DIM Image(2000) AS INTEGER
```
Dimensions array with an [INTEGER](INTEGER) type suffix.
```vb
DIM Image%(2000)
```
Dimensions a range of [Arrays](Arrays) elements as [SHARED](SHARED) integers.
```vb
DIM SHARED Image(1 TO 1000) AS INTEGER
```
Dimensions variable as an [Arrays](Arrays) of 8 elements of the type [UNSIGNED](UNSIGNED) BIT.
```vb
DIM bit(8) AS _UNSIGNED _BIT
```
QB64 is more flexible than QBasic when it comes to "Duplicate Definition" errors. The following code does not error:
```vb
x = 1 'x is a SINGLE variable
PRINT x
DIM x AS LONG
PRINT x
```
> *Explanation:* The [SINGLE](SINGLE) variable can be differentiated from the [LONG](LONG) x variable by using suffixes like x! or x& in later code.
The following code will create a "Name already in use" **status error** in QB64 when the variable types are the same.
```vb
x = 1 'x is a SINGLE variable
PRINT x
DIM x AS SINGLE
PRINT x
```
> *Explanation:* QB64 gives an error because the creation of the new variable would make referring to the existing one impossible.
Using QB64's alternative syntax to declare multiple variables/arrays of the same type.
```vb
DIM AS LONG w, h, id, weight, index 'all of these variables are created as type LONG
DIM AS SINGLE x, y, z 'all of these variables are created as type SINGLE
```
## See Also
* [_DEFINE](_DEFINE), [_PRESERVE](_PRESERVE)
* [REDIM](REDIM), [TYPE](TYPE)
* [ERASE](ERASE), [CLEAR](CLEAR)
* [DEFINT](DEFINT), [DEFSNG](DEFSNG), [DEFLNG](DEFLNG), [DEFDBL](DEFDBL), [DEFSTR](DEFSTR)
* [Mathematical Operations](Mathematical-Operations), [Arrays](Arrays)
* [Variable Types](Variable-Types)
* [OPTION _EXPLICIT](OPTION--EXPLICIT)

27
wiki/DLL-Libraries.md Normal file
View file

@ -0,0 +1,27 @@
QB64 supports some DLL Library statements and functions. Currently the specified DLL file MUST either be in the **Windows System folder** (System32) or in the **QB64 folder!**
**NOTE:** Use them at your own risk! **QB64 CANNOT** provide specific DLL Library information or support! When using unsupported DLL files use [DECLARE LIBRARY](DECLARE-LIBRARY) and the name of an **inactive** library **without** the .DLL extension. The following statement and function routine examples have been provided by members "as is":
## Example(s)
This example plays Midi files using the *playmidi32.dll* documented here: [Liberty Basic University](http://libertybasicuniversity.com/lbnews/nl110/midi3.htm). Download the following DLL file to your main QB64 folder: [PlayMidi32.dll](https://www.qb64.org/resources/Playmidi32.dll)
```vb
DECLARE DYNAMIC LIBRARY "playmidi32"
FUNCTION PlayMIDI& (filename AS STRING)
END DECLARE
result = PlayMIDI(".\samples\qb64\original\ps2battl.mid" + CHR$(0))
PRINT result
```
> **Note:** Filename needs to be [CHR$](CHR$)(0) terminated. QB64 [STRING](STRING)s are passed to external libraries as pointers to first character.
## See Also
* [DECLARE DYNAMIC LIBRARY](DECLARE-DYNAMIC-LIBRARY), [BYVAL](BYVAL)
* [_OFFSET](_OFFSET), [_OFFSET (function)](_OFFSET-(function)) (lp, ptr and p names)
* [C Libraries](C-Libraries), [SDL Libraries](SDL-Libraries), [Windows Libraries](Windows-Libraries)
* [Libraries](Libraries)
* [Port Access Libraries](Port-Access-Libraries) (COM or LPT)

164
wiki/DO...LOOP.md Normal file
View file

@ -0,0 +1,164 @@
**DO...LOOP** statements are used in programs to repeat code or return to the start of a procedure.
## Syntax
*Syntax 1:*
> **[DO](DO)** [{**WHILE**|**UNTIL**} condition]
>> *{code}*
>>
>> ⋮
>>
> **[LOOP](LOOP)**
*Syntax 2:*
> **[DO](DO)**
>> *{code}*
>>
>> ⋮
>
> **[LOOP](LOOP)** [{**WHILE**|**UNTIL**} condition]
## Description
* **DO UNTIL or DO WHILE used with LOOP**: The condition is evaluated before running the loop code.
> [UNTIL](UNTIL) checks if the condition is false each time before running code.
> [WHILE](WHILE) checks if the condition is true each time before running code.
* **DO used with LOOP UNTIL or LOOP WHILE**: The code block will run at least once:
> [UNTIL](UNTIL) checks if the condition is false before running loop code again.
> [WHILE](WHILE) checks if the condition is true before running loop code again.
* NOTE: You cannot use a condition after both the DO and LOOP statements at the same time.
* Use **[EXIT](EXIT) DO** to exit a loop block even before the condition is met.
* Use [_CONTINUE](_CONTINUE) to skip the remaining lines in the iteration without leaving the loop.
* If you don't specify a condition, you must exit the loop block manually using **[EXIT](EXIT) DO**.
* If a loop never meets an exit condition requirement, it will never stop.
**Relational Operators:**
| Symbol | Condition | Example Usage |
| -- | -- | -- |
| = | Equal | IF a = b THEN |
| <> | NOT equal | IF a <> b THEN |
| < | Less than | IF a < b THEN |
| > | Greater than | IF a > b THEN |
| <= | Less than or equal | IF a <= b THEN |
| >= | Greater than or equal | IF a >= b THEN |
## Example(s)
Using WHILE to clear the keyboard buffer.
```vb
DO WHILE INKEY$ <> "": LOOP ' checks evaluation before running loop code
DO: LOOP WHILE INKEY$ <> "" ' checks evaluation after one run of loop code
```
Using UNTIL to clear the keyboard buffer.
```vb
DO UNTIL INKEY$ = "": LOOP ' checks evaluation before running loop code
DO: LOOP UNTIL INKEY$ = "" ' checks evaluation after one run of loop code
```
Using a one time DO loop to exit ANY of several FOR LOOPs, without using [GOTO](GOTO).
> SUB reads header contents of a [BSAVE](BSAVE) file that may include embedded RGB color settings before the image.
```vb
DEFINT A-Z
INPUT "Enter a BSAVE file name to read the file for screen mode:"', filenm$
CheckScreen filenm$
END
DEFINT A-Z
SUB CheckScreen (Filename$) 'find Screen mode (12 or 13) and image dimensions
DIM Bsv AS STRING * 1
DIM Header AS STRING * 6
Scr = 0: MaxColors = 0
OPEN Filename$ FOR BINARY AS #1
GET #1, , Bsv '1 check for small 2 character
GET #1, , Header '2 - 7 rest of file header
IF Bsv <> CHR$(253) THEN ' small 2 character denotes a BSAVE file
COLOR 12: LOCATE 15, 33: PRINT "Not a BSAVE file!": SLEEP 3: EXIT SUB
END IF
GET #1, , widN '8 no color info bmp sizes
GET #1, , depN '9 " " "
DO
IF widN > 63 OR depN > 63 THEN EXIT DO ' width and depth already found
FOR i = 10 TO 55 'check for Screen 12 embedded colors
GET #1, , RGB
tot12& = tot12& + RGB
'PRINT i; RGB; : SOUND 300, 1 'test sound slows loop in QB
IF RGB > 63 OR RGB < 0 THEN EXIT DO
IF i = 55 AND tot12& = 0 THEN EXIT DO
NEXT
GET #1, , wid12 '56
GET #1, , dep12 '57
IF wid12 > 63 OR dep12 > 63 THEN EXIT DO
FOR i = 58 TO 775 'check for Screen 13 embedded colors
GET #1, , RGB
tot13& = tot13& + RGB
'PRINT i; RGB; : SOUND 300, 1 'test
IF RGB > 63 OR RGB < 0 THEN EXIT DO
IF i = 775 AND tot13& = 0 THEN EXIT DO
NEXT
GET #1, , wid13 '776
GET #1, , dep13 '777
LOOP UNTIL 1 = 1 'TRUE statement exits one-time LOOP
CLOSE #1
COLOR 14: LOCATE 10, 25
SELECT CASE i
CASE IS < 56:
IF widN > 640 THEN
Scr = 13: MaxColors = 0
PRINT "Default Screen 13:"; widN \ 8; "X"; depN
ELSE
LOCATE 10, 15
PRINT "Screen 12 ("; widN; "X"; depN; ") OR 13 ("; widN \ 8; "X"; depN; ")"
DO: SOUND 600, 4
COLOR 13: LOCATE 12, 23 'ask if no data found. Prevents ERROR opening in wrong mode
INPUT "Enter a Screen mode 12 or 13 : ", Scrn$
Scr = VAL(Scrn$)
LOOP UNTIL Scr = 12 OR Scr = 13
END IF
IF Scr = 12 THEN MaxColors = 0: PWidth = widN: PDepth = depN
IF Scr = 13 THEN MaxColors = 0: PWidth = widN \ 8: PDepth = depN
CASE 56 TO 775
PRINT "Custom Screen 12:"; wid12; "X"; dep12
Scr = 12: MaxColors = 16: PWidth = wid12: PDepth = dep12
CASE 776: PRINT "Custom Screen 13:"; wid13 \ 8; "X"; dep13
Scr = 13: MaxColors = 256: PWidth = wid13 \ 8: PDepth = dep13
END SELECT
END SUB
```
> *Explanation:* The SUB procedure reads a file that was [BSAVE](BSAVE)d previously. If the RGB colors are stored before the image, the values can only be between 0 and 63. Higher values indicate that the image width and height are located there and that there are no stored color values to be read. SUB later displays the dimensions of the file image that [GET (graphics statement)](GET-(graphics-statement)) placed in the file array. The loop is set to only run once by creating **a TRUE [UNTIL](UNTIL) statement** such as 1 = 1. When a screen mode cannot be determined, the user must select one.
> Dimensions and location of width and height information indicates the screen mode as [SCREEN (statement)](SCREEN-(statement)) 13 if it has 768 RGB values and dimensions of 320 X 200 max. If the file only holds 64 settings and/or is larger than 320 X 200, it uses SCREEN 12 or 9. The procedure [EXIT](EXIT)s the DO LOOP early when the image size is found with or without custom color settings.
> Divide SCREEN 13 [GET (graphics statement)](GET-(graphics-statement)) widths by 8.
## See Also
* [EXIT DO](EXIT-DO)
* [WHILE...WEND](WHILE...WEND)
* [FOR...NEXT](FOR...NEXT)

28
wiki/DOUBLE.md Normal file
View file

@ -0,0 +1,28 @@
[DOUBLE](DOUBLE) type floating point numerical values use 8 bytes per value.
## Syntax
> [DIM](DIM) variable [AS](AS) [DOUBLE](DOUBLE)
## Description
* Literal or variable values can range up to 15 decimal point places.
* The variable suffix type is **#**.
* Use DOUBLE and [_FLOAT](_FLOAT) variables sparingly as they use a lot of program memory.
* Values returned may be expressed using exponential or [scientific notation](scientific-notation) using **E** for SINGLE or **D** for DOUBLE precision.
* Floating decimal point numerical values cannot be [_UNSIGNED](_UNSIGNED).
* Values can be converted to 8 byte [ASCII](ASCII) string values using [_MKD$](_MKD$) and back with [_CVD](_CVD).
* **When a variable has not been defined or has no type suffix, the value defaults to [SINGLE](SINGLE).**
* **Warning: QBasic keyword names cannot be used as numerical variable names with or without the type suffix.**
## QBasic
* Results of mathematical calculations may be approximate or slow in QuickBASIC 4.5.
## See Also
* [DIM](DIM), [DEFDBL](DEFDBL)
* [MKD$](MKD$), [CVD](CVD)
* [SINGLE](SINGLE), [_FLOAT](_FLOAT)
* [LEN](LEN)
* [Variable Types](Variable-Types)

176
wiki/DRAW.md Normal file
View file

@ -0,0 +1,176 @@
The [DRAW](DRAW) statement uses a [STRING](STRING) expression to draw lines on the screen.
## Syntax
> [DRAW](DRAW) drawString$
## Description
* The drawString$ can be [DRAW](DRAW) instructions in quotation marks or a [STRING](STRING) variable using [DRAW](DRAW) instructions.
* [DRAW](DRAW) starting coordinates can be set using [PSET](PSET), [PRESET](PRESET), [CIRCLE](CIRCLE) or [LINE](LINE) ending positions.
* Other graphic objects can be located at or relative to the last DRAW position using [STEP](STEP).
* [DRAW](DRAW) can inherit colors from other graphic statements such as [PSET](PSET), [LINE](LINE) and [CIRCLE](CIRCLE).
* Draw strings use letters followed by the number of pixels to move, an angle, coordinate or a color value.
* Draw strings are flexible with spacing. **Spacing is not required.** [DRAW](DRAW) will look for a number value after a valid letter.
* DRAW statements are not case sensitive.
* "**B**" (blind) before a line move designates that the line move will be hidden. Use to offset from a "P" or [PAINT](PAINT) border.
* "**C** n" designates the color attribute or [_RGB](_RGB) [STR$](STR$) numerical color value to be used in the draw statement immediately after.
* "**M** x, y" can move to another coordinate area of the screen. When a + or - sign is used before a coordinate, it is a relative coordinate move similar to using the [STEP](STEP) graphics keyword. DRAW "M+=" + [VARPTR$](VARPTR$)(variable%)
* "**N**" before a line move designates that the graphic cursor will return to the starting position after the line is drawn.
* "**P** f [, b]" is used to [PAINT](PAINT) enclosed objects. f denotes the fill color and b the border color, if needed.
* "**S** n" changes the pixel move size of the lines. Default is 4 (1 pixel) minimum. "S8" would double the pixel line moves.
* "**X**" + [VARPTR$](VARPTR$)(value) can draw another substring.
* Certain letter designations create line moves on the SCREEN. Each move is followed by the number of pixels:
* "**D** n" draws a line vertically DOWN n pixels.
* "**E** n" draws a diagonal / line going UP and RIGHT n pixels each direction.
* "**F** n" draws a diagonal \ line going DOWN and RIGHT n pixels each direction.
* "**G** n" draws a diagonal / LINE going DOWN and LEFT n pixels each direction.
* "**H** n" draws a diagonal \ LINE going UP and LEFT n pixels each direction.
* "**L** n" draws a line horizontally LEFT n pixels.
* "**R** n" draws a line horizontally RIGHT n pixels.
* "**U** n" draws a line vertically UP n pixels.
* Angles are used to rotate all subsequent draw moves.
* "**A** n" can use values of 1 to 3 to rotate up to 3 90 degree(270) angles.
* **TA** n" can use any n angle from -360 to 0 to 360 to rotate a DRAW (Turn Angle). "TA0" resets to normal.
* When [VARPTR$](VARPTR$) is used, DRAW functions such as **TA** angles use an equal sign: "TA=" + VARPTR$(angle%)
* The graphic cursor is set to the center of the program window on program start for [STEP](STEP) relative coordinates.
* **DRAW can be used in any graphic screen mode, but cannot be used in the default screen mode 0 as it is text only.**
## Example(s)
Placing an octagon shape DRAW across the the screen using PSET.
```vb
SCREEN 12
octagon$ = "C12 R10 F10 D10 G10 L10 H10 U10 E10" 'create a DRAW string value
SCREEN 12
FOR i% = 1 TO 11
PSET (i% * 50, 100), 15
_DELAY .5 ' delay for demo
DRAW octagon$ ' DRAW the octagon using variable
_DELAY .5 ' delay for demo
NEXT i%
```
*Explanation:* Once a DRAW string variable is created, it can be used to draw a shape throughout the program at any time.
Creating an analog clock's hour markers using "TA=" + [VARPTR$](VARPTR$)(angle).
```vb
SCREEN 12
FOR angle = 0 TO 360 STEP 30 ' 360/12 hour circles = 30 degrees apart
PSET (175, 250), 6 ' stay at center point of clock
DRAW "TA=" + VARPTR$(angle) + "BU100" ' move invisibly to set next circle's center point
CIRCLE STEP(0, 0), 5, 12 ' circle placed at end of blind line
DRAW "P9, 12" ' paint inside of circle
SLEEP 1 ' slowed for demo only
NEXT
```
*Explanation:* To place 12 circles in a circle each move is 30 degrees. PSET sets the center of the circular path every loop. TA moves counter-clockwise with positive degree angles. Once TA sets the angle a blind Up move is at that angle. The hour circles use the end point of the blind line as centers using the STEP relative coordinates of 0. After the circles are drawn, a draw "P" string paints the circle centers. DRAW paint strings use the last coordinate position also.
Creating a moving second hand for the clock above (SCREEN 12). (See [TIME$](TIME$) example 1)
```vb
DO: sec$ = RIGHT$(TIME$, 2) ' get actual seconds from TIME$ function
degree$ = STR$(VAL(sec$) * -6) ' 60 second moves. TA uses negative angles for clockwise moves
PSET (175, 250), 9 ' stay at clock center
DRAW "TA" + degree$ + "U90" ' up becomes TA directional line
DO: LOOP UNTIL RIGHT$(TIME$, 2) <> sec$ ' wait for a new second value
IF INKEY$ <> "" THEN EXIT DO ' any key exit
PSET (175, 250), 0 ' set at clock center to erase line
DRAW "TA" + degree$ + "U90" ' erases old second hand line using color 0 from PSET
LOOP
```
*Explanation:* The degrees to move from the original UP line move is calculated by dividing 360/60 seconds in a full rotation. That value of 6 is made negative to use TA correctly and multiplied by the [VAL](VAL)ue of seconds from the TIME$ function. The degree angle is converted by [STR$](STR$) to a string and added to the DRAW string using the [STRING](STRING) **concatenation +** operator. Do not use semicolons to create DRAW strings. Once the second hand is placed on the screen, a loop waits for the second value to change. It then erases the hand and it repeats the process again.
Creating digital displays using DRAW format strings to create the LED segments. (See [SELECT CASE](SELECT-CASE) example 5)
```vb
SCREEN 12
DO
LOCATE 1, 1: INPUT "Enter a number 0 to 9: ", num
CLS
SELECT CASE num
CASE 0, 2, 3, 5 TO 9: PSET (20, 20), 12
DRAW "E2R30F2G2L30H2BR5P12,12" 'top horiz
END SELECT
SELECT CASE num
CASE 0, 4 TO 6, 8, 9: PSET (20, 20), 12
DRAW "F2D30G2H2U30E2BD5P12,12" 'left top vert
END SELECT
SELECT CASE num
CASE 0, 2, 6, 8: PSET (20, 54), 12
DRAW "F2D30G2H2U30E2BD5P12, 12" 'left bot vert
END SELECT
SELECT CASE num
CASE 2 TO 6, 8, 9: PSET (20, 54), 12
DRAW "E2R30F2G2L30H2BR5P12, 12" 'middle horiz
END SELECT
SELECT CASE num
CASE 0 TO 4, 7 TO 9: PSET (54, 20), 12
DRAW "F2D30G2H2U30E2BD5P12,12" 'top right vert
END SELECT
SELECT CASE num
CASE 0, 1, 3 TO 9: PSET (54, 54), 12
DRAW "F2D30G2H2U30E2BD5P12,12" 'bottom right vert
END SELECT
SELECT CASE num
CASE 0, 2, 3, 5, 6, 8: PSET (20, 88), 12
DRAW "E2R30F2G2L30H2BR5P12,12" 'bottom horiz
END SELECT
LOOP UNTIL num > 9
```
> *Explanation:* The DRAW strings can be used more than once with different [PSET](PSET) positions to create more digits.
Using 32 bit or [_RGB](_RGB) color [STR$](STR$) values when using the DRAW C text statement
```vb
SCREEN _NEWIMAGE(800, 800, 12)
PRINT _ALPHA(10), _RED(10), _GREEN(10), _BLUE(10)
SLEEP
SCREEN _NEWIMAGE(800, 800, 32) 'comment out this line to use the non-32 bit screen mode 12
PRINT _ALPHA(10), _RED(10), _GREEN(10), _BLUE(10)
PSET (400, 400), 0 ' move to 320, 240... draw will start where pset leaves off
c = 14
DIM k AS _UNSIGNED LONG
k = _RGB(80, 255, 80)
FOR repeat = 1 TO 16
FOR p = 0 TO 359
c = c + 1: d = c / 14
DRAW "c" + STR$(k) + " ta" + STR$(p) + " bu " + STR$(d) + "l7 u7 r7 d7 bd " + STR$(d)
NEXT p
NEXT repeat
```
> *Explanation:* DRAW strings will ignore spaces between letters and numbers so string trimming is not necessary.
## See Also
* [LINE](LINE), [PSET](PSET), [PRESET](PRESET), [CIRCLE](CIRCLE)
* [PAINT](PAINT), [SCREEN (statement)](SCREEN-(statement))
* [COLOR](COLOR), [PLAY](PLAY)
* [TIME$](TIME$)

163
wiki/Data-types.md Normal file
View file

@ -0,0 +1,163 @@
Any [Expression](Expression), including [CONST](CONST) and [Variable](Variable) all have an associated type to describe their value. QB64 has various built-in data types used to represent number and text values. [#Numeric types](#Numeric types) represent number values, while [#String types](#String types) represent text values.
## Numeric types
QB64 supports several numeric types, capable of representing a wide range of numbers. There are two kinds of numeric data type: *integer types* and *floating-point types*.
### Integer types
Integer types represent integer (whole number) values, such as 1 and 100. They are divided into two flavors: *signed* and *unsigned*.
#### Signed Integer types
Signed integers can represent positive and negative integer (whole number) values, such as 3, 10 and -16. These values are stored as a series of bits in [two's complement form](http://en.wikipedia.org/wiki/Two's_complement), a common representation that makes them both straightforward and efficient to perform calculations with.
Signed integers are typically used in simple mathematical equations.
The range of values that these types can represent is based on their size, in bits; the greater number of bits, the larger positive and lesser negative value the types can represent.
The signed integer types are: [_BYTE](_BYTE), [INTEGER](INTEGER), [LONG](LONG), [_INTEGER64](_INTEGER64) and [_OFFSET](_OFFSET)
```vb
DIM n AS INTEGER
n = -1
PRINT n
```
```text
-1
```
#### Unsigned Integer types
Unsigned integers can represent positive integer values only, such as 3, 10 and 16. These values are also stored as a series of bits, but unlike signed integers, all of the bits contribute to their value. Thus, these types can represent larger positive integer values than their signed counterparts.
Unsigned integers are typically used to represent a simple quantity, like a *count* or a *length*. They are also often used as *bit masks*, where certain bits that make up the value represent separate information (such as the state of one or more *flags*).
Types: [_UNSIGNED](_UNSIGNED) [_BYTE](_BYTE), [_UNSIGNED](_UNSIGNED) [INTEGER](INTEGER), [_UNSIGNED](_UNSIGNED) [LONG](LONG), [_UNSIGNED](_UNSIGNED) [_INTEGER64](_INTEGER64), [_UNSIGNED](_UNSIGNED) [_OFFSET](_OFFSET)
```vb
' display the largest value representable by an _UNSIGNED INTEGER:
DIM n AS _UNSIGNED INTEGER
n = -1
PRINT n
```
```text
65535
```
#### _OFFSET Integer types
Offset Integer types can be any byte size integer value that can be used to designate pointer offset positions in memory. DO NOT TRANSFER offset values to other Integer types!
### Floating-point types
Floating-point types can represent both positive and negative number values, as well as fractional number values, such as 1.2 and -34.56.
Floating-point types are used in mathematical equations where fractional precision is important, such as trigonometry.
The floating-point types are: [SINGLE](SINGLE), [DOUBLE](DOUBLE) and [_FLOAT](_FLOAT).
```vb
f! = 76.0
c! = (5.0 / 9.0) * (f! - 32.0)
PRINT f! ; "degrees Fahrenheit is" ; c! ; "degrees Celcius."
```
```text
76 degrees Fahrenheit is 24.44444 degrees Celcius.
```
## String types
QB64 has built-in support for strings, which are contiguous sequences of characters represented as [_UNSIGNED](_UNSIGNED) [_BYTE](_BYTE) values. Strings are usually used to store and manipulate text, but can also be used as a general storage area for arbitrary data (like a binary file).
Strings have a property called *length*, which is the number of characters currently stored in the string, and QB64 supports two kinds of string types based on this property: *variable-length strings* and *fixed-length strings*.
### Variable-length strings
Variable length strings are undefined length string variables. Fixed length strings MUST be defined in a program before they are used. Undefined strings can be up to 32767 characters in QBasic.
```vb
message$ = "Hello"
message$ = message$ + " world!" 'add to string variables using string concatenation only!
PRINT message$
```
```text
Hello world!
```
### Fixed-length strings
Fixed length strings must be defined in a [DIM](DIM) statement, [SUB](SUB) or [FUNCTION](FUNCTION) parameter or [TYPE](TYPE) definition. The designated multiple is the maximum number of [STRING](STRING) character bytes that the variable or [Arrays](Arrays) can hold. Excess bytes will not be included. No error is created.
```vb
DIM message AS STRING * 5
message$ = "Hello"
message$ = message$ + " world!"
PRINT message$
```
```text
Hello
```
## Data type limits
The following table lists the numerical and string data types, their type suffix symbol, and the range of the values they can represent:
### Numerical Types
| Type Name | Symbol | Minimum Value | Maximum Value | Size (Bytes) |
| --------- | ------ | ------------- | ------------- | ------------ |
| _BIT | ` | -1 | 0 | 1/8 |
| _BIT * n | `n | -128 | 127 | n/8 |
| _UNSIGNED _BIT | ~` | 0 | 1 | 1/8 |
| _BYTE | %% | -128 | 127 | 1 |
| _UNSIGNED _BYTE | ~%% | 0 | 255 | 1 |
| INTEGER | % | -32,768 | 32,767 | 2 |
| _UNSIGNED INTEGER | ~% | 0 | 65,535 | 2 |
| LONG | & | -2,147,483,648 | 2,147,483,647 | 4 |
| _UNSIGNED LONG | ~& | 0 | 4,294,967,295 | 4 |
| _INTEGER64 | && | -9,223,372,036,854,775,808 | 9,223,372,036,854,775,807 | 8 |
| _UNSIGNED _INTEGER64 | ~&& | 0 | 18,446,744,073,709,551,615 | 8 |
| SINGLE | ! or none | -2.802597E-45 | +3.402823E+38 | 4 |
| DOUBLE | # | -4.490656458412465E-324 | +1.797693134862310E+308 | 8 |
| _FLOAT | ## | -1.18E4932 | +1.18E+4932 | 32 (10 used) |
| _OFFSET | %& | -9,223,372,036,854,775,808 | 9,223,372,036,854,775,807 | Use LEN |
| _UNSIGNED _OFFSET | ~%& | 0 | 18,446,744,073,709,551,615 | Use LEN |
| _MEM | none | combined memory variable type | N/A | Use LEN |
*Note: For the floating-point numeric types [SINGLE](SINGLE) (default when not assigned), [DOUBLE](DOUBLE) and [_FLOAT](_FLOAT), the minimum values represent the smallest values closest to zero, while the maximum values represent the largest values closest to ±infinity. OFFSET dot values are used as a part of the [_MEM](_MEM) variable type in QB64 to return or set the position in memory.*
### String Text Type
| Type Name | Symbol | Minimum Length | Maximum Length | Size (Bytes) |
| --------- | ------ | -------------- | -------------- | ------------ |
| STRING | $ | 0 | 2,147,483,647 | Use LEN |
| STRING * *n* | $n | 1 | 2,147,483,647 | n |
*Note: For the fixed-length string type [STRING * n](STRING), where n is an integer length value from 1 (one) to 2,147,483,647.*

15
wiki/Dollar-Sign.md Normal file
View file

@ -0,0 +1,15 @@
The **$** is used to denote QBasic [Metacommand](Metacommand)s or as a [STRING](STRING) variable type suffix.
## Usage
> $INCLUDE: 'QB.bi'
* [$STATIC]($STATIC) denotes that all arrays can only be dimensioned once using [DIM](DIM).
* [$DYNAMIC]($DYNAMIC) denotes that all arrays can be redimensioned using [REDIM](REDIM) ONLY.
* [$INCLUDE]($INCLUDE) includes a BI file or QBasic Library in a program. The file name requires a comment before and after the name.
* The [STRING](STRING) variable suffix MUST be used if the variable is not dimensioned in a DIM statement. The statement can also set a fixed string [LEN](LEN).
## See Also
* [DIM](DIM), [REDIM](REDIM)
* [Metacommand](Metacommand)

218
wiki/Downloading-Files.md Normal file
View file

@ -0,0 +1,218 @@
**HTTP/1.1** protocol downloads can be done using a **GET** request using the following format without HTTP:// in the url:
```text
CRLF$ = CHR$(13) + CHR$(10)
Request$ = "GET " + File_Path + " HTTP/1.1" + CRLF$ + "Host:" + Web_Address + CRLF$ + CRLF$
```
> Two carriage returns end the request to the [_OPENCLIENT](_OPENCLIENT) URL. The header that is returned from the site also ends with two carriage returns when there are no errors. The header will also include the requested file's byte size after "content-length:" as below:
```text
HTTP/1.1 200 OK
Server: dbws
Date: Tue, 25 Oct 2011 04:41:03 GMT
Content-Type: text/plain; charset=ascii
Connection: keep-alive
content-length: 4087
x-robots-tag: noindex,nofollow
accept-ranges: bytes
etag: 365n
pragma: public
cache-control: max-age=0
```
> Each row of text response sent is ended with a carriage return with the end of header having two. After that comes the file data.
> It is recommended that data be loaded immediately by using a [GET (TCP/IP statement)](GET-(TCP-IP-statement)) loop so that connections are not dropped during a [_DELAY](_DELAY).
> **A "raw" Download function that downloads an image directly off of a web page using the image name on that page.**
```vb
IF Download("www.qb64.net/qb64.png", "qb64logo.png", 10) THEN ' timelimit = 10 seconds
SCREEN _LOADIMAGE("qb64logo.png",32)
ELSE: PRINT "Couldn't download QB64 logo."
END IF
SLEEP
SYSTEM
' ---------- program end -----------
FUNCTION Download (url$, file$, timelimit) ' returns -1 if successful, 0 if not
url2$ = url$
x = INSTR(url2$, "/")
IF x THEN url2$ = LEFT$(url$, x - 1)
client = _OPENCLIENT("TCP/IP:80:" + url2$)
IF client = 0 THEN EXIT FUNCTION
e$ = CHR$(13) + CHR$(10) ' end of line characters
url3$ = RIGHT$(url$, LEN(url$) - x + 1)
x$ = "GET " + url3$ + " HTTP/1.1" + e$
x$ = x$ + "Host: " + url2$ + e$ + e$
PUT #client, , x$
t! = TIMER ' start time
DO
_DELAY 0.05 ' 50ms delay (20 checks per second)
GET #client, , a2$
a$ = a$ + a2$
i = INSTR(a$, "Content-Length:")
IF i THEN
i2 = INSTR(i, a$, e$)
IF i2 THEN
l = VAL(MID$(a$, i + 15, i2 - i -14))
i3 = INSTR(i2, a$, e$ + e$)
IF i3 THEN
i3 = i3 + 4 'move i3 to start of data
IF (LEN(a$) - i3 + 1) = l THEN
CLOSE client ' CLOSE CLIENT
d$ = MID$(a$, i3, l)
fh = FREEFILE
OPEN file$ FOR OUTPUT AS #fh: CLOSE #fh 'Warning! Clears data from existing file
OPEN file$ FOR BINARY AS #fh
PUT #fh, , d$
CLOSE #fh
Download = -1 'indicates download was successfull
EXIT FUNCTION
END IF ' availabledata = l
END IF ' i3
END IF ' i2
END IF ' i
LOOP UNTIL TIMER > t! + timelimit ' (in seconds)
CLOSE client
END FUNCTION
```
<sub>Code by Galleon</sub>
> **Downloading a [BINARY](BINARY) image file from a download link using [GET](GET) which requires the "content-length" in header.**
```vb
DEFINT A-Z
CR$ = CHR$(13) + CHR$(10) 'crlf carriage return line feed characters
' Change this to the file's public link
<nowiki>DownFile$ = "http://a5.sphotos.ak.fbcdn.net/hphotos-ak-snc7/293944_10150358253659788_151813304787_8043392_486717139_n.jpg?dl=1"</nowiki>
' Get base URL
BaseURL$ = DownFile$
IF INSTR(BaseURL$, "http://") THEN BaseURL$ = RIGHT$(BaseURL$, LEN(BaseURL$) - 7) 'trim http://
Path$ = MID$(BaseURL$, INSTR(BaseURL$, "/")) 'path to file
BaseURL$ = LEFT$(BaseURL$, INSTR(BaseURL$, "/") - 1) 'site URL
' Connect to base URL
PRINT "Connecting to "; BaseURL$; "...";
Client& = _OPENCLIENT("TCP/IP:80:" + BaseURL$)
IF Client& = 0 THEN PRINT "Failed to connect...": END
PRINT "Done."
' Send download request
PRINT "Sending download request...";
Request$ = "GET " + Path$ + " HTTP/1.1" + CR$ + "Host:" + BaseURL$ + CR$ + CR$
PUT #Client&, , Request$
PRINT "Done."
' Download the header
PRINT "Getting HTML header...";
Dat$ = ""
DO
_LIMIT 20
GET #Client&, , gDat$
Dat$ = Dat$ + gDat$
LOOP UNTIL INSTR(Dat$, CR$ + CR$) ' Loop until 2 CRLFs (end of HTML header) are found
PRINT "Done."
' Get file size
FileSizePos = INSTR(UCASE$(Dat$), "CONTENT-LENGTH: ") + 16
FileSizeEnd = INSTR(FileSizePos, Dat$, CR$)
FileSize& = VAL(MID$(Dat$, FileSizePos, (FileSizeEnd - FileSizePos) + 1))
PRINT "File size:"; FileSize&
PRINT "Downloading file...";
' Trim off HTML header
EndHeaderPos = INSTR(Dat$, CR$ + CR$) + 4
Dat$ = RIGHT$(Dat$, (LEN(Dat$) - EndHeaderPos) + 1)
' Get the file name tucked at the end of the URL if necessary
FOR S = LEN(DownFile$) TO 1 STEP -1
IF MID$(DownFile$, S, 1) = "/" THEN
OutFile$ = RIGHT$(DownFile$, (LEN(DownFile$) - S))
EXIT FOR
END IF
NEXT S
' Remove some kind of tag at the end of the file name in some URLs
IF INSTR(OutFile$, "?") THEN OutFile$ = LEFT$(OutFile$, INSTR(OutFile$, "?") - 1)
' Download the rest of the data
OPEN OutFile$ FOR OUTPUT AS #1: CLOSE #1 'Warning! Clears data from an existing file
OPEN OutFile$ FOR BINARY AS #1 'write data to binary image file
DO
_LIMIT 20
PUT #1, , Dat$
GET #Client&, , Dat$
LOOP UNTIL LOF(1) >= FileSize&
CLOSE #1, #Client&
PRINT "Done!"
```
<sub>Adapted from code by Jobert14</sub>
> **Note:** Some download links require that a **tag** be added after the file name. Remove that tag if it will be used as the file name.
> **Downloading a sequencial text file from a Drop Box download link using HTTP GET and the [GET (TCP/IP statement)](GET-(TCP-IP-statement)) statement.**
```vb
CrLf$ = CHR$(13) + CHR$(10) ' carriage return + line feed ASCII characters
Host = _OPENHOST("TCP/IP:319")
IF Host THEN
PRINT "> Server started succesfully."
'// Change this to the file's public link
IP_File$ = "dl.dropbox.com/u/8440706/QB64.INI" 'a Drop Box link
URL$ = LEFT$(IP_File$, INSTR(IP_File$, "/") - 1)
Path$ = MID$(IP_File$, INSTR(IP_File$, "/"))
Client& = _OPENCLIENT("TCP/IP:80:" + URL$)
IF Client& THEN
Request$ = "GET " + Path$ + " HTTP/1.1" + CrLf$ + "Host:" + URL$ + CrLf$ + CrLf$
PUT #Client&, , Request$
DO: _LIMIT 20 ' load response header
GET #Client&, , Dat$
Header$ = Header$ + Dat$
LOOP UNTIL INSTR(Header$, CrLf$ + CrLf$) ' Loop until 2 CRLFs (end of HTML header) are found
PRINT "Header Done."
' Get file size from header
SizePos = INSTR(UCASE$(Header$), "CONTENT-LENGTH:") + 16
SizeEnd = INSTR(SizePos, Header$, CrLf$)
FileSize& = VAL(MID$(Header$, SizePos, (SizeEnd - SizePos) + 1))
PRINT "File size is"; FileSize&; "bytes"
EndPos = INSTR(Header$, CrLf$ + CrLf$) + 4
Response$ = MID$(Header$, EndPos) ' get data after header already downloaded
start = 1 '// Get file name from original URL path if necessary
DO '// Change this to destination local file name and path...
posit = INSTR(start, IP_File$, "/")
IF posit THEN lastpos = posit: start = posit + 1
LOOP UNTIL posit = 0
File$ = MID$(IP_File$, lastpos + 1) 'beware of tag suffixes
OPEN File$ FOR BINARY AS #1
DO: _LIMIT 20
PUT #1, , Response$
GET #Client&, , Response$
LOOP UNTIL LOF(1) >= FileSize&
PRINT "File download completed!"
CLOSE #1
ELSE
PRINT "Failed to connect."
END IF
ELSE
PRINT "Failed to create server connection..."
END IF
```
<sub>Code suggested by Matt Kilgore</sub>

68
wiki/ELSE.md Normal file
View file

@ -0,0 +1,68 @@
[ELSE](ELSE) is used in [IF...THEN](IF...THEN) or [SELECT CASE](SELECT-CASE) statements to offer an alternative to other conditional statements.
## Syntax
*Single-line syntax:*
> [IF](IF) condition [THEN](THEN) *{code}* [ELSE](ELSE) *{alternative-code}*
*Block syntax:*
> [IF](IF) condition [THEN](THEN)
>> *{code}*
>>
>> ⋮
>>
> [ELSEIF](ELSEIF) condition2 [THEN](THEN)
>> *{code}*
>>
>> ⋮
>>
> [ELSE](ELSE)
>> *{alternative-code}*
>>
>> ⋮
>
> [END IF](END-IF)
## Description
* ELSE is used in a IF block statement to cover any remaining conditions not covered in the main block by IF or [ELSEIF](ELSEIF).
* [CASE ELSE](CASE-ELSE) covers any remaining conditions not covered by the other CASE statements.
* ELSE can also be used as a false comparison to a true IF statement when a condition will only be true or false.
* Other [IF...THEN](IF...THEN) statements can be inside of an ELSE statement.
## Example(s)
One line IF statement
```vb
IF x = 100 THEN PRINT "100" ELSE PRINT "Not 100"
```
Multiple line IF statement block
```vb
IF x = 100 THEN ' code executed MUST be on next statement line!
PRINT "100"
ELSE PRINT "Not 100"
END IF
```
To alternate between any two values (as long as the value after ELSE is the same as the condition)
```vb
IF a = 3 THEN a = 5 ELSE a = 3
```
## See Also
* [ELSEIF](ELSEIF)
* [IF...THEN](IF...THEN)

71
wiki/ELSEIF.md Normal file
View file

@ -0,0 +1,71 @@
[ELSEIF](ELSEIF) is used in an [IF...THEN](IF...THEN) block statement to offer an alternative condition.
## Syntax
> [IF](IF) condition [THEN](THEN)
>
>> *{code}*
>>
>> ⋮
>
> [ELSEIF](ELSEIF) condition2 [THEN](THEN)~
>
>> *{code}*
>>
>> ⋮
>
> [ELSE](ELSE)
>
>> *{alternative-code}*
>>
>> ⋮
>
> [END IF](END-IF)
## Description
* ELSEIF statements require a **separate** code block line with [THEN](THEN) for each alternative condition.
* There can be more than one [ELSE](ELSE) IF statement in a single-line IF statement.
* If there is only one possible alternative condition (such as 0 or [NOT](NOT) 0), use [ELSE](ELSE) instead.
* If the comparisons are based on multiple conditions being true, it may require many ELSEIF comparisons. ELSE could help cover some of those conditions.
* You can use [SELECT CASE](SELECT-CASE) when IF blocks have a long list of alterative ELSEIF conditions.
**Relational Operators:**
| Symbol | Condition | Example Usage |
| -- | -- | -- |
| = | Equal | IF a = b THEN |
| <> | NOT equal | IF a <> b THEN |
| < | Less than | IF a < b THEN |
| > | Greater than | IF a > b THEN |
| <= | Less than or equal | IF a <= b THEN |
| >= | Greater than or equal | IF a >= b THEN |
## Example(s)
IF statement using ELSE IF in one statement line.
```vb
IF x = 100 THEN COLOR 10: PRINT x ELSE IF x > 100 THEN COLOR 12: PRINT x ELSE PRINT "< 100"
```
IF statement block
```vb
IF x = 100 THEN ' must place ANY code on next line!
COLOR 10: PRINT x
ELSEIF x > 100 THEN COLOR 12: PRINT x
ELSE : PRINT "< 100"
END IF
```
## See Also
*[ELSE](ELSE), [END IF](END-IF)
*[IF...THEN](IF...THEN)

11
wiki/END-SELECT.md Normal file
View file

@ -0,0 +1,11 @@
The **END SELECT** statement ends a [SELECT CASE](SELECT-CASE) statement block.
## Syntax
> END SELECT
* The statement is required to end a SELECT CASE block or there will be an [ERROR Codes](ERROR-Codes).
## See Also
* [SELECT CASE](SELECT-CASE), [IF...THEN](IF...THEN)

56
wiki/END.md Normal file
View file

@ -0,0 +1,56 @@
The [END](END) statement terminates a program without an immediate exit or ends a procedure or statement block.
## Syntax
> [END](END) [returnCode%]
>
> [END](END) [IF](IF...THEN)
>
> [END](END) [TYPE](TYPE)
>
> [END](END) [SELECT](SELECT-CASE)
>
> [END](END) [SUB](SUB)
>
> [END](END) [FUNCTION](FUNCTION)
>
> [END DECLARE](DECLARE-LIBRARY)
## Description
* In **QB64**, [END](END) can be followed by a code that can be read by another module using the [SHELL (function)](SHELL-(function)) or [_SHELLHIDE](_SHELLHIDE) function (known as [https://blogs.msdn.microsoft.com/oldnewthing/20080926-00/?p=20743 **errorlevel**])
* When END is used to end a program, there is a pause and the message "Press any key to continue..." is displayed at the bottom of the program's window.
* If the program does not use END or [SYSTEM](SYSTEM), the program will still end with a pause and display "Press any key to continue...".
* In **QB64**, [SYSTEM](SYSTEM) will end the program immediately and close the window.
* The **QB64** [_EXIT (function)](_EXIT-(function)) can block a user's Ctrl + Break key presses and clicks on the window's close button (X button) until the program is ready to close.
## Example(s)
In QB64 you won't return to the IDE unless you are using it to run or edit the program module.
```vb
PRINT "Hello world!"
END
PRINT "Hello no one!"
```
*Returns:*
```text
Hello world!
Press any key to continue...
```
> *Explanation:*"Hello no one!" isn't returned because the program ended with the END statement no matter what is after that.
> The message "Press any key to continue..." is displayed after the program ends, both in QBasic and in **QB64**.
## See Also
* [SYSTEM](SYSTEM) (immediate exit)
* [SHELL (function)](SHELL-(function)), [_SHELLHIDE](_SHELLHIDE)
* [EXIT](EXIT) (statement), [_EXIT (function)](_EXIT-(function))

131
wiki/ENVIRON$.md Normal file
View file

@ -0,0 +1,131 @@
The [ENVIRON$](ENVIRON$) function returns a [STRING](STRING) environmental value from the Operating System's environmental settings list.
## Syntax
> setting$ = [ENVIRON$](ENVIRON$)({listIndex%|systemID$})
## Description
* The function can use an [INTEGER](INTEGER) listIndex% value or [STRING](STRING) systemID$ parameter.
* listIndex% refers to the number order of the environmental list. Returns are not in any particular numerical order.
* systemID$ is the specific [STRING](STRING) parameter requested. Returns only the specified environmental [STRING](STRING) setting (examples based on Windows):
* "BLASTER" = current Sound Blaster settings if installed.
* "COMPUTERNAME" or "USERDOMAIN" = OEM PC serial number or the computer name assigned by owner.
* "HOMEDRIVE" or "SystemDrive" = Windows root drive, normally C: on single partition drives.
* "HOMEPATH" = current user's Administrator or the single user's "OWNER" folder path.
* "OS" = Windows Operating System version. Often WindowsNT in modern computers.
* "PATH" = full path setting that Windows uses to look for file extensions in PATHEXT below.
* "PATHEXT = Windows extensions used: COM, EXE, BAT, CMD, VBS, VBE, JS, JSE, WSF, WSH, MSC
* "PROCESSOR_ARCHITECTURE" = x86 for 32 or 64 bit.
* "PROGRAMFILES" = path to *Program files* folder, normally "C:\PROGRAM FILES"
* "PROMPT" = normally "$P$G" on Windows NT.
* "SYSTEMROOT" or "windir" = path to the Windows folder including the drive letter like "C:\WINDOWS"
* "TEMP" or "TMP" = path to TEMP folder. "C:\TEMP" or the user specific temp folder on later versions.
* "USERNAME" = current Administrator name or "OWNER".
> *Note:* There are other possible system settings that are not listed or never used on older versions. Run *Example 1* below for a complete list in your system.
* *Note:* **QB64** may not return the same environment list as QBasic or SET did in DOS.
## Example(s)
Viewing the list of environmental parameter settings using a counter loop like SET does in DOS.
```vb
DO
i = i + 1
setting$ = ENVIRON$(i) ' get a setting from the list
PRINT setting$
IF i MOD 20 = 0 THEN PRINT "Press a key": SLEEP: CLS
LOOP UNTIL setting$ = ""
```
```text
ALLUSERSPROFILE=C:\ProgramData
COMPUTERNAME=TED-LAPTOP
ComSpec=C:\WINDOWS\system32\cmd.exe
HOMEDRIVE=C:
HOMEPATH=\Users\Ted
LOCALAPPDATA=C:\Users\Ted\AppData\Local
OS=Windows_NT
Path=C:\PROGRAMDATA\ORACLE\JAVA\JAVAPATH;C:\WINDOWS\SYSTEM32;C:\WINDOWS;
C:\WINDOWS\SYSTEM32\WBEM;C:\WINDOWS\SYSTEM32\WINDOWSPOWERSHELL\V1.0\;C:\
WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\WINDOWS\System32
\WindowsPowerShell\v1.0\
PATHEXT=.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC
PROCESSOR_ARCHITECTURE=x86
PROCESSOR_IDENTIFIER=x86 Family 6 Model 14 Stepping 8, GenuineIntel
ProgramFiles=C:\Program Files
PROMPT=$P$G
PSModulePath=C:\WINDOWS\system32\WindowsPowerShell\v1.0\Modules\
SystemRoot=C:\WINDOWS
TEMP=C:\Users\TED\AppData\Local\Temp
TMP=C:\Users\TED\AppData\Local\Temp
USERDOMAIN=TED-LAPTOP
USERNAME=Ted
USERPROFILE=C:\Users\Ted
```
> *Note:* Windows environmental settings are listed alphabetically, 20 at a time. **QB64 may not read all of them or may return an empty string.** The settings above were returned with SET in DOS. PROMPT returned nothing where SET returned $P$G.
Creating a shortcut on a user's desktop for QB64.EXE using the program's icon. Must be run in program's folder to work!
```vb
'=== Enter the EXE file and ICON or BMP image for the shortcut.
Program$ = "QB64.EXE" '<<<<<<<<<< Enter the **exact** program name for shortcut
ICON$ = "QB64ICON.BMP" '<<<<<<<<<< Enter icon or bitmap to use from program's folder
DeskTopShortcut Program$, ICON$
END '====== END DEMO CODE ======
SUB DeskTopShortcut (Program$, ICON$)
f = FREEFILE
SHELL _HIDE "CD > PRGMDIR.INF" 'get the current program path
OPEN "PRGMDIR.INF" FOR INPUT AS #f
LINE INPUT #f, PATH$
CLOSE #f
KILL "PRGMDIR.INF"
PATH$ = PATH$ + "\": FILE$ = PATH + Program$
PRINT PATH$ 'DEMO print
A$ = ENVIRON$("HOMEDRIVE") '=== Get Current User setting from Environment.
B$ = ENVIRON$("HOMEPATH")
C$ = A$ + B$ 'shortcut to user's desktop if found
IF C$ = "" THEN C$ = ENVIRON$("ALLUSERSPROFILE") 'try desktop for all users
PRINT C$ 'DEMO print
URLFILE$ = MID$(Program$, 1, INSTR(Program$, ".")) + "URL" 'change EXE to URL
IF C$ > "" THEN
SHORTCUT$ = C$ + "\Desktop\" + URLFILE$ 'create filename for the desktop
ELSE SHORTCUT$ = PATH$ + URLFILE$ 'if all else fails put in program folder
END IF
PRINT SHORTCUT 'DEMO print
OPEN SHORTCUT$ FOR APPEND AS #f
IF LOF(f) THEN CLOSE #f: EXIT SUB '=== if filesize is NOT Zero don't overwrite!
Q$ = CHR$(34) '=== Write URL Shortcut file info.
PRINT #f, "[InternetShortcut]" 'URL type
PRINT #f, "URL=" + Q$ + "file://" + FILE$ + Q$ 'URL program file
PRINT #f, "WorkingDirectory=" + Q$ + PATH$ + Q$ 'Working path
PRINT #f, "IconIndex = " + Q$ + "0" + Q$ '0 is first index
PRINT #f, "IconFile = " + Q$ + PATH$ + ICON$ + Q$ 'Icon path in working folder
CLOSE #f
END SUB
```
> *Explanation:* The SUB program finds the current program's path and user's desktop path. It then creates the shortcut on the desktop with a program icon. The custom icon should be in the program's folder. If an environmental path is not found, the shortcut is placed in the program's folder. The SUB can be added to any program.
> **NOTE:** A temorary file named PRGMDIR.INF is created and deleted in the example above.
## See Also
* [ENVIRON](ENVIRON) (statement), [_ENVIRONCOUNT](_ENVIRONCOUNT)
* [_DEVICES](_DEVICES), [_DEVICE$](_DEVICE$)
* [_LASTBUTTON](_LASTBUTTON), [_OS$](_OS$)
* [Windows Environment](Windows-Environment)
* [Windows Libraries](Windows-Libraries)

20
wiki/ENVIRON.md Normal file
View file

@ -0,0 +1,20 @@
The [ENVIRON](ENVIRON) statement is used to temporarily set or change an environmental string value.
## Syntax
> [ENVIRON](ENVIRON) stringExpression$
## Description
* The stringExpression$ must include the environmental parameter ID and the setting:
* Using an **=** sign: [ENVIRON](ENVIRON) "parameterID=setting"
* Using a space: [ENVIRON](ENVIRON) "parameterID setting"
* If the parameter ID did not previously exist in the environmental string table, it is appended to the end of the table.
* If a parameter ID did exist, it is deleted and the new value is appended to end of the list.
* The [_ENVIRONCOUNT](_ENVIRONCOUNT) function returns the number of key/value pairs that currently exist.
* Any changes made at runtime are discarded when your program ends.
## See Also
* [ENVIRON$](ENVIRON$), [_ENVIRONCOUNT](_ENVIRONCOUNT)
* [Windows Environment](Windows-Environment)

20
wiki/EOF.md Normal file
View file

@ -0,0 +1,20 @@
The [EOF](EOF) function indicates that the end of a file has been reached.
## Syntax
> endReached%% = EOF([#]fileNumber&)
## Description
* fileNumber& is the number of the file being read. **#** is not required.
* Returns 0 until the end of a file. This avoids a file read error.
* Returns -1 (true) at the end of the file.
* **Note that [GET](GET) can return invalid data at the end of a file.** Read [EOF](EOF) after a GET operation to see if the end of the file has been reached and discard last read.
## See Also
* [OPEN](OPEN)
* [LOF](LOF), [LEN](LEN)
* [INPUT (file statement)](INPUT-(file-statement))
* [LINE INPUT (file statement)](LINE-INPUT-(file-statement))
* [GET](GET), [PUT](PUT)

27
wiki/EQV.md Normal file
View file

@ -0,0 +1,27 @@
The [EQV](EQV) operator returns a value based on the *equivalence* of two conditions or values.
## Syntax
> result = firstValue [EQV](EQV) secondValue
## Description
* Returns true (-1) when both values are the same (*equivalent*).
* Turns a bit on if both bits are the same, turns a bit off if both bits are different.
The results of the bitwise logical operations, where *A* and *B* are operands, and *T* and *F* indicate that a bit is set or not set:
| A | B | | [NOT](NOT) B | A [AND](AND) B | A [OR](OR) B | A [XOR](XOR) B | A [EQV](EQV) B | A [IMP](IMP) B |
| - | - | - | - | - | - | - | - | - |
| T | T | | F | T | T | F | T | T |
| T | F | | T | F | T | T | F | F |
| F | T | | F | F | T | T | F | T |
| F | F | | T | F | F | F | T | T |
**[Relational Operations](Relational-Operations) return negative one (-1, all bits set) and zero (0, no bits set) for *true* and *false*, respectively.**
This allows relational tests to be inverted and combined using the bitwise logical operations.
## See Also
* [Binary](Binary)
* [Boolean](Boolean)

21
wiki/ERASE.md Normal file
View file

@ -0,0 +1,21 @@
The [ERASE](ERASE) statement is used to clear all data from an array. [$STATIC]($STATIC) [Arrays](Arrays) dimensions are not affected.
## Syntax
> ERASE *arrayName* [, *arrayName2*...]
## Description
* All string array elements become null strings ("") and all numerical array elements become 0.
* Multiple arrays can be erased using commas between the array names.
* [$DYNAMIC]($DYNAMIC) arrays must be [REDIM](REDIM)ensioned if they are referenced after erased.
* Dimension subprocedure arrays as [STATIC](STATIC) to use [ERASE](ERASE) and not have to REDIM.
* You do not have to include array brackets in an [ERASE](ERASE) call.
## See Also
* [DIM](DIM), [REDIM](REDIM)
* [CLEAR](CLEAR)
* [STATIC](STATIC)
* [$DYNAMIC]($DYNAMIC)
* [Arrays](Arrays)

1
wiki/ERDEV$.md Normal file
View file

@ -0,0 +1 @@
See [ERR](ERR).

Some files were not shown because too many files have changed in this diff Show more