๐Ÿ“˜ Hobby BASIC - Get Started

โœ… Conditionals in Hobby BASIC

1. IF...THEN...ELSE Statement

The IF...THEN...ELSE structure is used to control program flow based on conditions.

Example 1: Simple IF Statement

IF SCORE >= 50
    PRINT "You passed!"
ENDIF

Example 2: IF...ELSEIF...ELSE

IF (GRADE$ = "A" AND ATTENDANCE >= 90) OR AGE > 18
    PRINT "Great job!"
ELSEIF (GRADE$ = "B" OR AGE <= 18) AND ATTENDANCE >= 50
    PRINT "Good effort!"
ELSE
    PRINT "Keep improving!"
ENDIF

Example 3: Nested IF Statements

IF AGE >= 18
    IF COUNTRY$ = "USA" THEN PRINT "You can vote."
ELSE
    PRINT "You are too young to vote."
ENDIF

Example 4: Single-line IF with THEN

IF BALANCE < 0 THEN PRINT "Your account is overdrawn!" ELSE PRINT "Balance OK."

Example 5: IF without ELSE

IF LOGIN$ = "admin"
    PRINT "Access granted."
ENDIF

2. IIF Function

The IIF function evaluates a condition and returns one of two values.

Example 6: Basic IIF Usage

STATUS$ = IIF(SCORE >= 60, "Pass", "Fail")

Example 7: Numeric IIF Example

DISCOUNT = IIF(QUANTITY > 10, 1, 0)

Example 8: String Assignment with IIF

COUNTRY$ = IIF(COUNTRY$ = "", "Unknown", COUNTRY$)

3. SELECT...CASE...ENDSEL Statement

The SELECT...CASE structure simplifies multiple condition checks.

Example 9: Simple SELECT...CASE

INPUT "Enter day of week (1-7): ", DAY

SELECT CASE DAY
CASE IS 1 :
    PRINT "Monday"
    BREAK
CASE IS 2 :
    PRINT "Tuesday"
    BREAK
CASE IS 3 :
    PRINT "Wednesday"
    BREAK
CASE IS 4 :
    PRINT "Thursday"
    BREAK
CASE IS 5 :
    PRINT "Friday"
    BREAK
CASE IS 6,7 :
    PRINT "Weekend"
    BREAK
CASE :
    PRINT "Invalid day"
ENDSEL

Example 10: SELECT...CASE without parameter

SELECT CASE
CASE TEMP > 30 :
    PRINT "Hot"
    BREAK
CASE TEMP >= 20 AND TEMP <= 30 :
    PRINT "Warm"
    BREAK
CASE TEMP < 20 :
    PRINT "Cold"
    BREAK
ENDSEL

โœ… Loops and Control Statements

1. FOR...NEXT Loop

The FOR...NEXT loop in Hobby BASIC is used to repeat a block of code for a specific number of times.

Example 1: Basic FOR Loop with PASS

FOR I = 1 TO 5
    IF I = 3 THEN PASS
    PRINT I
NEXT I

Expected Output: 1 2 4 5

2. DO...UNTIL Loop

The DO...UNTIL loop executes a block of code repeatedly until a condition is met.

Example 2: DO Loop with PASS

I = 0
DO
    I = I + 1
    IF I = 2 THEN PASS
    PRINT I
UNTIL I = 4

Expected Output: 1 3 4

3. WHILE...ENDW Loop

The WHILE...ENDW loop repeats a block of code as long as the condition is true.

โœ๏ธ Note: Hobby BASIC uses ENDW instead of WEND.

Example 3: WHILE Loop

I = 1
WHILE I <= 5
    PRINT I
    I = I + 1
ENDW

Expected Output: 1 2 3 4 5

4. PASS Statement

The PASS statement is used to skip the current iteration of a loop. It is similar to the continue statement in C.

Example 4: Simple PASS Usage

FOR I = 1 TO 3
    PASS
    PRINT I
NEXT I

Expected Output: (Nothing printed)

5. BREAK Statement

The BREAK statement is used to exit a loop prematurely when a certain condition is met.

Example 5: Simple BREAK Usage

FOR I = 1 TO 9
    IF I = 5 THEN BREAK
    PRINT I
NEXT

Expected Output: 1 2 3 4

6. Nested Loops with BREAK and PASS

You can also use BREAK and PASS inside nested loops to control the flow.

Example 6: Nested Loops with PASS

FOR I = 1 TO 3
    FOR J = 1 TO 3
        IF J = 2 THEN PASS
        PRINT "I=", I, " J=", J
    NEXT J
NEXT I

Expected Output:

I=1 J=1
I=1 J=3
I=2 J=1
I=2 J=3
I=3 J=1
I=3 J=3

7. Complex Example: Search for Prime Numbers

In this example, we will search for prime numbers up to a limit using BREAK and PASS.

Example 7: Search for Prime Numbers

LIMIT = 20
PRINT "Prime numbers up to ", LIMIT
PRINT 2, " ";

FOR NUM = 3 TO LIMIT STEP 2
    ISPRIME = 1
    I = 3
    WHILE I * I <= NUM
        IF NUM % I = 0
            ISPRIME = 0
            BREAK
        ENDIF
        I = I + 2
    ENDW
    IF ISPRIME THEN PRINT NUM;
NEXT

Expected Output:

Prime numbers up to 20
2 3 5 7 11 13 17 19

โœ… Functions in Hobby BASIC

1. Searching for a Value in an Array

This function searches for a target value in an array and returns its index if found.

Example: searchArray Function

sub searchArray(arr[], target)
    arr[].FIND target
    rets V0
ends

dim numbers[50].RND 50
searchValue = 10

index = searchArray(numbers[], searchValue)

if index <> 0
    PRINT "Value ", searchValue, " found at position ", index - 1
else
    PRINT "Value ", searchValue, " not found in the array"
endif

2. Loading File Content into an Array

This function loads lines of text from a file into an array.

Example: loadFileIntoArray Function

sub loadFileIntoArray(filePath$, lines$[])
    if SIZE(filePath$) = -1 then rets -1
    lines$[].FILE filePath$
    rets V0
ends

dim fileBuffer$[100].ZERO

lineCount = loadFileIntoArray("Licence.txt", byref fileBuffer$[])

if lineCount = -1
    PRINT "Error: File not found"
    end
endif

for i = 0 to lineCount - 1
    PRINT fileBuffer$[i]
next

3. Swapping Two Values

This function swaps two values using a temporary variable.

Example: swapValues Function

sub swapValues(x, y)
    local temp = x
    x = y
    y = temp
ends

firstValue = 5
secondValue = 10

swapValues(byref firstValue, byref secondValue)

PRINT "After swapping: ", firstValue, " and ", secondValue

4. Checking if a String is a Palindrome

This function checks if a string is a palindrome (reads the same forwards and backwards).

Example: checkPalindrome Function

sub checkPalindrome(inputString$)

    local reversedString$
    local cleanedInput$

    cleanedInput$ = REPLACE(inputString$, " ", "")

    reversedString$ = REVERSE(cleanedInput$)

    if UCASE(reversedString$) = UCASE(cleanedInput$)
        rets "The string is a palindrome!"
    else
        rets "The string is not a palindrome!"
    endif
ends

result$ = checkPalindrome("Rotator")
PRINT result$

โœ… The Stack in Hobby BASIC

In Hobby BASIC, the stack operates in a LIFO (Last In, First Out) manner and consists of 262,140 double words. You can manipulate it using the basic PUSH and POP commands or directly through the stack[] array.

โœ๏ธ Note: The stack[] array and the internal stack are the same. Any operation on stack[] directly affects the stack. However, commands like FILL, SHUFFLE, SORT, etc., do not update the internal stack pointer, so use them with care.

Example: Basic PUSH and POP

push 100
push 'A'
pop x

This sends 100 and the ASCII of 'A' to the stack, and retrieves 'A' into x.

Example: Multiple PUSH and Top Check

push 1, 2, 3, 'A'
top = PEEK(10)              ! Get top of the stack
print CHR(stack[top - 1])   ! Prints 'A'
pop 4                       ! pop 4 times

Sorting the Stack

x = 0
dim stack[10]               ! reinitialize stack with 10 elements
times 10 push x++           ! pushes 0..9 onto the stack
stack[].SORTD               ! now stack[] = [9, 8, โ€ฆ, 0]

for i = 0 to 9
    print stack[i]
next

Expected Output: 9 8 7 6 5 4 3 2 1 0 (Descending order)

Value Replacement

dim stack[5]
push 10, 20, 30, 20, 40
stack[].REPLACE 20, 99
times 5 pop x : print x

Expected Output: 40 99 30 99 10

Extra: Stack SHUFFLE

dim stack[5]
push 1, 2, 3, 4, 5
stack[].SHUFFLE
times 5 pop x : print x

โœ๏ธ Note: SHUFFLE randomly shuffles stack values. The result will vary.

Handling the Circular Stack

The Hobby BASIC stack is circular. When it becomes full, new values start replacing older ones from the beginning of the array.

Example: Circular Stack Behavior

dim stack[5]
push 1, 2, 3, 4, 5
push 6, 7
top = PEEK(10)
size = 5
for i = 0 to size - 1
    print stack[i]
next

Expected Output: 6 7 3 4 5

Reading Top to Bottom with Wrap-around

๐Ÿ”„ Always use mod to handle circular wrapโ€‘around when reading from top to bottom.
for i = 1 to 5
    idx = (top - i + size) mod size
    print stack[idx]
next

Expected Output: 7 6 5 4 3

Alternative: Simple POP

times 5 pop x : print x

Expected Output: 7 6 5 4 3

The stack in Hobby BASIC is a powerful tool. Its circular nature makes it highly efficient not only for simple PUSH and POP operations but also for advanced manipulations like sorting, shuffling, and value replacements using the stack[] array.

โœ… Drawing Tool Guide

Introduction

This drawing tool is developed in Hobby BASIC and designed specifically for use within the Hobby BASIC environment. DRAW can load, create, edit, and save ANSI images.

Image

Basic Controls

The Attributes Picker

Click on the BG or FG labels to select background or foreground color.

Then choose one of the 16 available colors from the color picker.

๐Ÿ’ก Right-click on the labels to swap the foreground and background colors.

If an area is selected, the color swap will apply to that area automatically.

โœ๏ธ Note: This method overrides color number 8 (GRAY) as it is used for temporary storage.

The Color Dialog Box

Right-click on the color picker to open the color dialog box.

Any change you make to one of the 16 basic colors in the console will affect the entire DRAW window.

Remember, DRAW itself is a console window made with Hobby BASIC.

๐ŸŽจ About Color Schemes

When you save an image in DRAW, the program automatically stores the associated color scheme in the DATA\TEMP folder. The scheme is saved as a plain text file (.TXT) with the same name as your image. To load this scheme, use Option 3 from the main menu.

Function Keys

๐Ÿ“Œ Windows 10 & 11 Compatibility

For the program to function correctly, enable the Use Legacy Console option:

  1. Right-click the app title bar and select Properties.
  2. Enable Use Legacy Console.
  3. Restart the console.

โœ… Creating Snapshots

Introduction

The DRAW program, Hobby BASIC's drawing tool, offers three options when starting:

โš ๏ธ Note: Options 1 and 2 define the font and canvas size used during your drawing session. Make sure to choose the correct mode when loading an image you previously created, to match its original dimensions.

Loading an ANSI Image

For example, if we save an image named TEST.ANS in the DATA\MEDIA\ANSI\ folder, we can load it as follows:

! ROWS = 80
! COLS = 25

screen 80, 50, 0
cls
ansi PATH("DATA\MEDIA\ANSI\TEST.ANS")
inkey

The critical setting here is ROWS, which must be 80.

Saving a Portion of an Image

The following code creates a new ANSI image, TEST1.ANS, with a size of 40x25 from the original TEST.ANS file.

screen 80, 50, 0
cls
ansi PATH("DATA\MEDIA\ANSI\TEST.ANS")
ansi 0, 0, 40, 25, PATH("DATA\MEDIA\ANSI\TEST1.ANS")
inkey

Loading the Cropped Image

To load TEST1.ANS, the console window must match the image size:

screen 40, 25, 0
cls
ansi PATH("DATA\MEDIA\ANSI\TEST1.ANS")
inkey

โ„น๏ธ Using SNAP for More Flexibility

SNAP loads a snapshot file at position x, y, or saves a rectangular area of the screen to a file. Snapshot files require the .HB extension. SNAP allows us to load an image of any size into a console window of any dimensions (as long as it fits within the window).

Creating and Loading a Snapshot

To load TEST.ANS and create a snapshot named TEST.HB with a size of 40x25, use the following code:

screen 80, 50, 0
cls
ansi PATH("DATA\MEDIA\ANSI\TEST.ANS")
snap 0, 0, 40, 25, PATH("DATA\SNAP\TEST.HB")
inkey

Now, we can load this snapshot at any position within the console window:

screen 80, 50, 0
cls
snap 10, 10, PATH("DATA\SNAP\TEST.HB")
inkey

๐Ÿ“˜ Hobby BASIC - Try These

๐Ÿ“Œ Built-in Functions Overview

Useful one-liners and built-in functions:

print ABS(-10)                ! 10
print RND()%100               ! random number 0-99
print STR(25) + " years"      ! "25 years"
print FORMAT(1, 23456)        ! "22,9 KB"
print PAD("42", '0', 5)       ! "00042"
print EXTRACT("abc123!@#", 0) ! "123"

๐Ÿ‘‰ Use PAUSE or INKEY to prevent the window from closing.

๐Ÿงต Strings in Hobby BASIC

String manipulation with built-ins:

a$ = "Hello World"
print LEFT(a$, 5)         ! "Hello"
print RIGHT(a$, 5)        ! "World"
print REVERSE(a$)         ! "dlroW olleH"
a$(0) = 'h'               ! Change first char (0-based)

๐Ÿงฎ Arrays (1D & 2D)

Working with arrays and array functions:

dim nums[5] = 5, 3, 1, 4, 2
nums[].SORTA
nums[].OUT 3

nums[].REPLACE 3, 99
nums[].OUT 3

! 2D example:
dim matrix[2, 2] = 1, 2, 3, 4
print matrix[0, 0], matrix[1, 1]  ! prints 1 4

๐ŸŽจ Console Drawing & Screen Tools

Manipulate screen output using built-in commands:

cls
color 1, 14
print "Yellow on Blue!"

paint 0, 0, 80, 25, 'ฮ‘', 1
invert 10, 10, 15, 5
redraw 10, 10, 15, 5, 'ฮ‘', '-'

๐Ÿ“‚ File & Snapshot Utilities

Working with files and snapshots:

! Load text from file
dim lines$[16]
lines$[].FILE "LICENCE.TXT"
for i = 0 to SIZE(lines$[]) - 1
  print lines$[i]
next

! Save a portion of screen
snap 0, 0, 40, 15, PATH("DATA\SNAP\TEST.HB")

! Load the snapshot
snap 10, 10, PATH("DATA\SNAP\TEST.HB")

๐Ÿ” Mini Lab: Digital Clock

Create a simple digital clock:

while 1
  print at 0, 0, LEFT(PATH(10), 8)    ! system time
  wait 1000
endw

๐Ÿ—บ๏ธ Mini Mini Lab: Three Points

! Define a Coord structure for 3 points
type Coord (x, y) 3

! Assign coordinates to each point
Coord:[0].x = 10 : Coord:[0].y = 5    ! Point 0 at (10,5)
Coord:[1].x = 20 : Coord:[1].y = 15   ! Point 1 at (20,15)
Coord:[2].x = 30 : Coord:[2].y = 25   ! Point 2 at (30,25)

! Loop through and print each point
for i = 0 to 2
    print "Point ", i, ": (", Coord:[i].x, ", ", Coord:[i].y, ")"
next

โŒจ๏ธ Keyboard Input

Wait for a key press and display the key code:


LOOP#
    inkey

    ! V0 = Keycode
    ! V1 = SHIFT,  ALT,  CTRL, etc.
    ! V2 = F1..F12,  INS,  DEL,  HOME,  Arrows Keys
    
    print "Key:", V0, " Mod:", V1, " Extra:", V2

    if V0 = 13 then print "Enter was pressed"
    if V0 = 27 then end     ! Exit with Esc

    goto LOOP

๐Ÿ–ฑ๏ธ Mouse Tracking

Track mouse position and button state:


while 1
    mouse

    ! V0 = mouse x
    ! V1 = mouse y
    ! V2 = button: 1 left,  2 right,  4 double-click
            
    print "X:", V0, " Y:", V1, " Btn:", V2

    if V2 = 2 then print "Right click!"
    if V2 = 1 then break    ! Left click to exit

    wait 1
endw

๐Ÿ› ๏ธ DEBUG() Window Example

Use the DEBUG window to visualize variable contents in real time:

dim values[5] = 10, 20, 30, 40, 50

for i = 0 to 4
  DEBUG(i, values[i])  ! show key-value pairs in debugger
next

๐Ÿ“˜ About Hobby BASIC

Hobby BASIC is a lightweight yet surprisingly powerful BASIC interpreter for the Windows console, written entirely in x86 assembly.
It enables the creation of games with ANSI graphics in the console, which is quite unusual.
What began in 2015 as a personal fun project continues to evolve to this day.

This quick guide offers just a small glimpse of what Hobby BASIC can do.
๐Ÿ‘‰ To download it and learn more, visit the Hobby BASIC topic on the Flat Assembler forum.

๐Ÿ”š Conclusion

This guide covers the fundamental concepts of Hobby BASIC, from conditions and loops to functions and drawing tools. With this knowledge, you can start creating your own programs.