FreeBASIC
FreeBASIC is a free and open-source multi-platform compiler for the BASIC programming language, supporting procedural, object-oriented, and meta-programming paradigms with a syntax highly compatible to Microsoft QuickBASIC and other variants.[1] It enables the creation of console and graphical applications, libraries, and executables that run natively on supported systems without requiring an integrated development environment.[2]
Initiated in September 2004 by developer Andre Victor as a code-compatible alternative to the discontinued Microsoft QuickBASIC, FreeBASIC quickly became self-hosting by November of that year and achieved its first public release (version 0.01) on November 30, 2004.[3] Key contributors include Angelo Mottola for graphics library enhancements and Daniel R. Verkamp for the DOS port, with ongoing development led by a team including dkl since 2010.[3] The project, hosted on SourceForge since October 2004, has evolved to include 64-bit support starting with version 1.00.0 in 2014, Unicode handling (UTF-8, UTF-16, UTF-32), and optimizations comparable to GCC-generated code.[3] The latest stable release is version 1.10.1, released on December 25, 2023, with development of version 1.20.0 ongoing as of November 2025; it is licensed under the GNU General Public License (GPL).[4][5]
FreeBASIC targets i386-based architectures across Windows, Linux, DOS, and Xbox, utilizing GNU binutils for assembly, linking, and archiving to ensure portability.[2] It offers two primary dialects: "-lang qb" for near-complete QuickBASIC compatibility (including features like line numbers and GOSUB) and the default "-lang fb" mode, which incorporates C-style elements such as pointers, inline assembly, and a preprocessor while remaining case-insensitive.[2] The language supports a wide range of data types, including integers (Byte to Longint), floating-point (Single, Double), and strings (fixed-length, variable up to 2GB, Wstring for wide characters), along with user-defined types (UDTs) that enable nested structures, unions, multi-dimensional arrays (up to 8 dimensions), and procedure pointers for advanced object-oriented programming.[2]
Notable features include thin bindings to C runtime libraries, partial C++ support, and integrations with popular APIs such as SDL for multimedia, OpenGL for graphics, GTK+ for interfaces, and the Windows API, allowing developers to build cross-platform applications with minimal modifications.[1] Debugging is facilitated through GDB integration, and the compiler produces compact binaries, including smaller DOS executables in recent versions.[3] Written entirely in FreeBASIC, the compiler exemplifies the language's maturity and serves as a toolset for creating software ranging from simple scripts to complex games and utilities, maintaining BASIC's accessibility while extending its capabilities to modern paradigms.[2]
History and Development
Origins and Early Development
FreeBASIC was founded in 2004 by Andre Victor, known online as V1ctor, as a free and open-source alternative to Microsoft QuickBASIC, initially targeting 32-bit Windows platforms.[6] The project originated from Victor's prior work on QuickBASIC extensions, such as libraries for enhanced floating-point performance and SVGA graphics support.[7]
The core goal was to maintain syntactic compatibility with QuickBASIC, allowing existing codebases to compile with minimal changes, while introducing modern capabilities absent in its predecessor.[6] Key additions included support for pointers to enable direct memory manipulation and dynamic allocation functions for flexible resource management, bridging the gap between legacy BASIC simplicity and contemporary programming needs.[6] This approach positioned FreeBASIC as an evolution of the QBASIC and QuickBASIC lineage, preserving their accessible dialect for procedural programming.[7]
In its formative years, development remained a solitary effort by Victor, who bootstrapped the initial compiler using Visual Basic for DOS before transitioning to self-compilation.[7] Community involvement emerged later, drawn by the project's open-source ethos and fidelity to QuickBASIC's ecosystem.[7] From inception, FreeBASIC adopted the GNU General Public License version 2 or later (GPLv2+), ensuring its compiler, runtime libraries, and tools remained freely modifiable and distributable.[6]
Key Milestones and Releases
FreeBASIC's development has seen several pivotal advancements in platform support and version stability. In December 2004, Angelo Mottola (known online as Lillo) contributed the initial port to Linux, expanding the compiler beyond its Windows origins and enabling cross-platform compilation capabilities.[8] This was followed in January 2005 by the DOS port, developed by Daniel R. Verkamp, which utilized the DJGPP toolchain to support 32-bit protected-mode execution under DOS and compatible environments like FreeDOS.[8][9]
Between 2006 and 2010, the project benefited from significant contributions by developers including Angelo Mottola (Lillo), who focused on Windows-specific enhancements, graphics library improvements, and overall code maturation.[10] During this period, experimental support for 64-bit targets began to emerge in internal discussions, though full implementation came later; additionally, an early Xbox port for the original console was achieved in July 2005 using version 0.13, allowing basic executable generation but remaining experimental. The Xbox port remains experimental and unmaintained since around 2010 due to evolving platform architectures like the Xbox 360.[11]
Major releases marked key stability and feature milestones, transitioning FreeBASIC from QuickBASIC compatibility toward a more independent, multi-platform language. The following table summarizes principal versions:
| Version | Release Date | Key Notes |
|---|
| 0.90.0 | August 6, 2006 | Initial multi-platform maturity with mature -gen GCC backend, extensive bug fixes for Win32 graphics and DOS I/O, and OOP enhancements.[3] |
| 1.00.0 | September 24, 2014 | Stable milestone release celebrating 10 years; introduced full 64-bit support for Windows and Linux (requiring GCC), reduced DOS binary sizes, and numerous bug fixes.[3] |
| 1.05.0 | January 31, 2016 | Focused on bug fixes and minor refinements to core functionality.[3] |
| 1.06.0 | February 18, 2019 | Primarily addressed bug fixes for reliability across platforms.[3] |
| 1.10.1 | December 25, 2023 | Latest stable release as of 2025, incorporating bug fixes, updated build tools, and improved cross-platform compatibility; includes both 32-bit and 64-bit compilers in default Windows packages.[12] |
Since 2023, development has progressed on the master branch toward version 1.20.0, emphasizing enhanced code generation reliability and backend improvements, with critical fixes merged from the 1.10 branch; as of November 2025, no official release has occurred.[5]
Current Status and Community
FreeBASIC continues to be maintained by the FreeBASIC Development Team, with leadership under Jeff Marshall since 2017, following Daniel Klauer (dkl) from 2010 to 2017 and founder Andre Victor from 2004 to 2010; contributions accepted through the project's GitHub repository and official forums.[13] The project, which originated in 2004, has seen steady volunteer involvement from a core group of 28 contributors on GitHub, focusing on bug fixes, documentation updates, and platform compatibility enhancements.[13]
The community remains active primarily on the freebasic.net forums, where users discuss compiler issues, share code snippets, and propose improvements, with ongoing threads on bug reports and feature requests extending into late 2025.[14] Peak online activity reached 2,756 users on September 11, 2025, reflecting sustained engagement among hobbyists, educators, and developers interested in BASIC programming.[14] Forum sections dedicated to general discussion and project-related topics host thousands of posts, including recent conversations on stability and tool integrations as of November 2025.[15]
As of November 2025, no major stable release has occurred since version 1.10.1, issued on December 25, 2023, with development efforts emphasizing stability and reliability for this version.[16] An experimental branch for version 1.20.0, initiated in 2023, incorporates backend improvements such as updated code generation and bug squashes, with community-built snapshots available and referenced in forum posts throughout 2025.[5][17]
The compiler integrates with GNU Binutils for cross-compilation across platforms like Windows, Linux, and DOS, enabling multi-platform builds without native dependencies on each target.[18] FreeBASIC maintains its design philosophy of manual memory management, eschewing automatic garbage collection to align with its QuickBASIC heritage and provide fine-grained control for performance-critical applications.[18]
Looking ahead, community discussions highlight interest in bolstering C++ interoperability through refined bindings and backend optimizations, though the project lacks a formalized public roadmap.[19]
Language Fundamentals
FreeBASIC supports 32-bit and 64-bit variants of Windows and Linux as primary operating systems, along with protected-mode DOS environments such as FreeDOS, and FreeBSD.[20][21] The compiler also targets other Unix-like systems including NetBSD and OpenBSD through cross-compilation options.[21] While early versions included support for the Xbox console, this has been discontinued due to lack of maintenance following the departure of the original porter.[22] Architecturally, FreeBASIC generates code directly for x86 (i386) and x86-64 processors, with support for 32-bit and 64-bit ARM architectures achieved by emitting intermediate C code for compilation.[21][23]
Cross-compilation is facilitated by integrating with GNU Binutils, allowing the compiler to produce binaries for different platforms from a host system by using target-specific assembler, linker, and related tools.[24] The FreeBASIC compiler itself is written entirely in FreeBASIC, making it self-hosting and highly portable without reliance on non-portable external tools.[20] For DOS targets, it requires a DPMI server like CWSDPMI.exe to enable 32-bit protected-mode execution on 16-bit DOS systems.[25]
To ensure backward compatibility with legacy BASIC variants, FreeBASIC provides a QuickBASIC compatibility mode activated via the -lang qb compiler flag, which enables full support for QuickBASIC syntax including unstructured GOSUB/[RETURN](/page/RETURN) statements, the ON ERROR handler, and legacy graphics statements like GFX.[26][27] This mode omits modern FreeBASIC features such as variable dimensioning requirements and line numbers to closely emulate QuickBASIC behavior.[26] In contrast, the default -lang fb mode incorporates extensions while maintaining core BASIC compatibility.[20]
Compiled FreeBASIC programs have no runtime dependencies beyond standard OS libraries, such as msvcrt.dll on Windows, libc and libpthread on Linux, or DPMI services on DOS.[25] The compiler supports both static and dynamic linking options, allowing developers to produce standalone executables or libraries that link against system shared objects as needed.[24]
FreeBASIC handles Unicode through support for UTF-8, UTF-16LE/BE, and UTF-32LE/BE encodings in source files and headers, with automatic conversion to ASCII where applicable.[20] The WSTRING type facilitates wide-character strings for Unicode text processing.[28] Multi-threading is implemented via platform-specific OS APIs, such as Win32 threads on Windows and POSIX pthreads on Linux and Unix variants, using built-in functions like ThreadCreate for spawning concurrent processes.[29][30] This approach ensures portability across supported platforms without introducing additional runtime overhead.[29]
Core Features and Paradigms
FreeBASIC is a multi-paradigm programming language that supports procedural programming, object-oriented programming through user-defined types (UDTs), and metaprogramming via preprocessor directives.[6] The procedural paradigm allows for structured code organization using subroutines and functions, maintaining compatibility with QuickBASIC syntax for straightforward imperative programming.[31] Object-oriented features are implemented using UDTs, which can include methods, constructors, and destructors; inheritance is achieved via the Extends keyword, enabling derived types to inherit fields and methods from base types, while polymorphism is supported through virtual procedures and runtime type information (RTTI) derived from the built-in Object type.[32][33] Operator overloading is available for UDTs, allowing custom definitions of operators like +, -, and Cast to enhance expressiveness, with both global and member operator declarations permitted.[34] Metaprogramming capabilities include text-replacement macros defined with #DEFINE for single-line substitutions and #MACRO/#ENDMACRO for multi-line expansions, facilitating code generation and abstraction at compile time.[35][36]
The language provides a rich set of built-in data types for handling various data needs. Integer types range from 8-bit Byte and unsigned UByte to 64-bit LongInt and ULongInt, with Integer and UInteger adapting to platform pointer size (32-bit or 64-bit).[2][37] Floating-point types include 32-bit Single, 64-bit Double, and extended-precision Long Double (size varying by platform: 80-bit, 96-bit, or 128-bit).[2] String types support dynamic allocation up to 2 GB with String for ANSI/UTF-8 characters and WString for wide characters (Unicode), alongside null-terminated ZString.[31][2] Although lacking a native Variant type, FreeBASIC supports variant-like behavior through the Any type or custom UDTs that can hold multiple data kinds, compatible with COM/OLE automation.[38][39]
Memory management in FreeBASIC is manual, without built-in garbage collection, requiring explicit allocation and deallocation using Alloc and Free functions.[6] Pointers follow C-like syntax with unlimited indirection levels, enabling direct memory access and dynamic data structures.[31] Arrays support up to eight dimensions with a total size limit of 2 GB, including dynamic and fixed-size variants for flexible data handling.[31] Procedure pointers allow runtime binding to subroutines and functions, supporting callbacks and higher-order programming.[37]
Additional core capabilities include inline assembly using GNU Assembler (GAS) with Intel syntax for low-level optimizations within Asm blocks.[40] The compiler optionally transcompiles FreeBASIC code to C via the -gen gcc backend, which leverages GCC for further compilation and optimizations, improving portability and performance on supported platforms.[41] This backend generates native executables with GCC-like optimizations, such as inlining and loop unrolling, while the default -gen gas directly emits assembly for efficient x86/x86_64 code generation.[41][31]
Syntax and Dialects
Basic Syntax Elements
FreeBASIC programs follow a line-based structure where code executes sequentially from top to bottom without requiring an explicit main procedure or an END statement to terminate the program, though the END statement can be used optionally to exit and return control to the operating system with an error code.[42][20] This design aligns with traditional BASIC dialects, allowing implicit program flow while supporting modular organization through procedures. Variables and data structures are declared using statements like Dim for scalars, arrays, or dynamic allocations, and Type for user-defined types (UDTs), which encapsulate fields of various data types into a single composite structure.[43][44][45]
Control flow in FreeBASIC is managed through conditional and iterative statements that assume familiarity with QuickBASIC syntax. The If...Then statement evaluates a condition and executes a block if true, optionally with Else or ElseIf for alternatives; for multiple conditions, Select Case compares an expression against literal values or ranges in Case clauses.[46][47] Loops include While...Wend for condition-checked iterations, Do...Loop variants (Do While/Until...Loop or Loop While/Until) for flexible entry/exit testing, and For...Next for counted iterations over a range with optional Step increments.[48][49][50] Procedures are defined with Sub for void routines or Function for returning values, while Declare prototypes external or forward declarations to enable modular code without immediate implementation.[51][52][53]
Operators in FreeBASIC support standard arithmetic operations such as addition (+), subtraction (-), multiplication (*), division (/), integer division (), modulus (Mod), exponentiation (^), and negation (-); these apply to numeric types with promotion rules for mixed operands.[54] Logical operators include And (conjunction), Or (disjunction), Xor (exclusive or), Eqv (equivalence), Imp (implication), and Not (negation), which perform bitwise or boolean evaluations depending on context.[55] String concatenation uses the & operator (or + in some dialects, but & is preferred for clarity), appending operands without spaces or type conversion issues.[56] FreeBASIC maintains compatibility with QuickBASIC statements like Gosub for subroutine calls.[20]
Comments are added using a single apostrophe (') or Rem for inline or line-start remarks, which ignore the rest of the line; in the FB dialect, multi-line comments are delimited by /* and */.[57][58] Error handling employs On Error to set a global or local handler routine, jumping to a label or line on runtime errors like division by zero or file I/O failures; Resume returns control to the error line or next, while the Err function retrieves the error code and Erl the line number.[59][60][61]
Preprocessor directives facilitate conditional compilation and code inclusion, beginning with # and processed before compilation. #Include inserts external source files at the directive's position, #Define creates macros for text substitution, and #If (with #Else, #Elif, #Endif) compiles blocks based on constant expressions or defined symbols via #Ifdef/#Ifndef.[62][63][35]
The following example illustrates basic syntax elements in a simple program that declares variables, uses control flow, and handles a potential error:
Dim As [Integer](/page/Integer) counter = 0
Dim As [String](/page/String) message = "Hello"
' Increment and check counter
For counter = 1 To 5
If counter [Mod](/page/Mod) 2 = 0 Then
Print message & " (even: "; counter; ")"
Else
Select Case counter
Case 1
Print message & " (first)"
Case 3, 5
Print message & " (odd: "; counter; ")"
End Select
End If
Next
' Error handling example
On Error Goto ErrorHandler
Dim As Integer result = 10 \ 0 ' Division by zero
Resume Next
ErrorHandler:
Print "Error "; Err; " at line "; Erl
Resume Next
Dim As [Integer](/page/Integer) counter = 0
Dim As [String](/page/String) message = "Hello"
' Increment and check counter
For counter = 1 To 5
If counter [Mod](/page/Mod) 2 = 0 Then
Print message & " (even: "; counter; ")"
Else
Select Case counter
Case 1
Print message & " (first)"
Case 3, 5
Print message & " (odd: "; counter; ")"
End Select
End If
Next
' Error handling example
On Error Goto ErrorHandler
Dim As Integer result = 10 \ 0 ' Division by zero
Resume Next
ErrorHandler:
Print "Error "; Err; " at line "; Erl
Resume Next
This code demonstrates declarations, loops, conditionals, operators, comments, and error handling without requiring dialect-specific features.[43][64][59]
Dialect Variants
FreeBASIC supports multiple dialects that adjust the language's syntax and feature set to balance compatibility with legacy BASIC interpreters like QuickBASIC and QBasic against modern programming capabilities. These dialects are selected via the -lang compiler option or the #lang preprocessor directive in source code, allowing developers to tailor the compilation process to specific needs such as porting old code or leveraging contemporary features.[65][66]
The default dialect, -lang fb, provides full access to FreeBASIC's modern extensions, including object-oriented programming with classes and inheritance, namespaces, templates, and stricter type checking that prohibits implicit variable declarations and type suffixes on variables (though numeric literals can use suffixes like f for single-precision floats). This mode disables legacy constructs such as DEFINT, GOSUB/[RETURN](/page/Return), COMMON SHARED, and OPTION statements to enforce cleaner, more robust code, while enabling advanced paradigms like operator overloading and scope blocks. It is recommended for new projects aiming for production-quality software with enhanced safety and extensibility.[67][65]
In contrast, the -lang qb dialect prioritizes compatibility with QuickBASIC and QBasic by restricting the language to legacy features and enabling QB-specific statements such as SCREEN for graphics modes, COLOR for text attributes, and implicit variable handling where undeclared variables default to single-precision floats. This mode excludes modern elements like multi-threading, classes, namespaces, and variable initialization in declarations, while supporting core features like pointers and dynamic memory allocation, permitting forward-referenced function calls with CALL and treating DATA statements as literal strings without quotes. It impacts available keywords by reserving QB-style ones and limits library access to avoid conflicts with extended features, making it suitable for direct ports of older BASIC code.[67][26][65]
The -lang deprecated dialect offers backward compatibility with FreeBASIC versions prior to 0.17b (specifically up to 0.16b), allowing obsolete constructs like COMMON SHARED for global variable sharing across modules, GOSUB/RETURN for unstructured subroutines, and ON GOSUB for indirect jumps, but it discourages use due to its planned removal in future releases. This mode supports features from early FreeBASIC but prohibits advancements such as classes, operator overloading, and constructors/destructors within TYPE definitions, resulting in a less secure and maintainable codebase compared to other dialects. Developers are advised to migrate to -lang fblite (a hybrid that builds on deprecated features while adding limited modern support like GOSUB via Option Gosub) for ongoing legacy compatibility without the deprecation risks.[67][65]
Switching dialects via compiler flags like -lang qb or the #lang "qb" directive in code affects not only syntax parsing—such as enabling periods in variable names or numeric labels in QB mode—but also the availability of keywords and libraries, potentially requiring code adjustments for cross-dialect portability. For instance, QB-specific statements like SCREEN and COLOR are unavailable in fb mode, while fb's templates and OOP are inaccessible in qb or deprecated modes.[65][66][26]
The trade-offs among dialects reflect their design goals: -lang qb facilitates rapid prototyping and legacy porting by mimicking QuickBASIC's forgiving syntax but sacrifices advanced paradigms and safety features, whereas -lang fb supports production development with robust tools like stricter checking and OOP at the cost of requiring explicit declarations and excluding unstructured control flows. The deprecated dialect, while useful for maintaining very old FreeBASIC code, offers minimal benefits for new work and may introduce maintenance challenges due to its obsolescence.[67][65]
Libraries and Graphics
Standard Libraries
FreeBASIC's standard libraries consist of built-in runtime functions and header files that provide bindings to the C runtime library (CRT), system APIs, and select external libraries, enabling core programming tasks without external dependencies. These libraries emphasize compatibility with QBASIC and C conventions, focusing on essential utilities rather than a comprehensive collection like the C++ Standard Template Library.[68][69]
The CRT bindings, included via the crt.bi header file, offer C-style interfaces for fundamental operations, with sub-headers like stdio.bi, math.bi, and string.bi organizing prototypes by category. For file I/O, CRT functions such as fopen, fread, and fwrite handle stream-based reading and writing, while FreeBASIC's built-in statements like Open (for modes including input, output, binary, and random access), Input (for reading values or lines), and Print (for formatted output) provide a more BASIC-oriented approach. Mathematical computations are supported by built-in functions including Sin (sine of an angle in radians), Cos (cosine), and Sqr (square root), supplemented by CRT equivalents like sin_, cos_, and sqrt in math.bi. String manipulation includes built-in functions such as Left (extracts leftmost characters), Right (extracts rightmost characters), and Instr (finds the first occurrence of a substring), alongside CRT utilities like strcat (concatenation), strlen (length), and strcpy (copying).[68][70][71][72]
System-level libraries address platform interactions through dedicated headers. Console I/O can use built-in Input and Print or CRT functions like printf and scanf via stdio.bi. Threading support includes built-in functions such as ThreadCreate (starts a new thread with a procedure pointer and parameters) and Mutex (via MutexCreate, MutexLock, and MutexUnlock for synchronization). On Windows, the windows.bi header and win/ subdirectory provide bindings to the Windows API, including functions like MessageBox for GUI elements. For Linux and other Unix-like systems, POSIX compliance is achieved through CRT headers, enabling standard system calls.[69][73][74]
External bindings are implemented as thin header files (.bi) in the inc/ directory, allowing direct access to popular APIs without requiring full wrapper libraries. These include headers for SDL (multimedia and input handling), Allegro (game development utilities), GTK+ (GUI toolkit), and OpenGL (3D graphics rendering via GL/gl.bi), where developers link against the respective shared or static libraries using compiler options or #inclib directives.[75][69]
Header files serve as the primary mechanism for library integration, containing declarations, constants, and prototypes that can be included with #include once "filename.bi" to enable function calls across platforms. The runtime library, particularly crt.bi, extends this with utilities for memory management, including C-style dynamic allocation via malloc, free, and realloc, alongside FreeBASIC's built-in Allocate, Deallocate, New, and Delete for heap-based objects and arrays. Error and exception handling is managed through the ON ERROR statement, which redirects runtime errors (e.g., file not found) to a labeled handler or resumes execution, with the Err variable capturing error codes.[76][77][59]
FreeBASIC's graphics capabilities are primarily provided by the built-in FBgfx library, a cross-platform software rasterizer that enables 2D rendering without requiring hardware acceleration by default.[78] This library recreates QuickBASIC-era graphics commands while adding support for modern features like multiple backbuffers for page flipping and direct memory access via ScreenPtr and ScreenLock.[78] Key drawing functions include Line for straight lines, Circle for ellipses and arcs, and PSet for individual pixels, allowing developers to construct complex visuals programmatically.[78] Sprite management is handled through Get and Put operations, which capture and blit image data between buffers or the screen.[78]
Graphics modes are initialized using the SCREEN statement, which supports QB-compatible mode numbers (e.g., mode 13 for 320x200 with 256 colors) or extended resolutions via flags for windowed, fullscreen, or OpenGL modes.[79] On Windows, FBgfx leverages DirectX as its backend for efficient rendering, while on Linux it uses OpenGL, though both prioritize software rendering over GPU acceleration unless explicitly bound to external APIs.[78] Resolutions range from legacy VGA standards like 640x480 up to high-definition sizes such as 3200x1800, depending on system capabilities, with no strict upper limit imposed by the library itself but practical constraints from memory and hardware.[80] In the QB dialect (-lang qb), legacy statements like DRAW for vector-based figure drawing and PAINT for flood-filling enclosed areas are fully available, ensuring compatibility with older QuickBASIC codebases.[81][82]
For multimedia, FreeBASIC offers basic audio support through the PLAY statement, which generates tones, musical notes, and simple melodies using MIDI or PCM modes, akin to QuickBASIC's implementation.[83] Advanced audio handling, including playback of formats like MP3, OGG, MOD, and WAV with effects such as 3D positioning and streaming, requires binding to external libraries like FMOD or BASS, both of which have official headers included in FreeBASIC distributions.[84][85] FMOD supports a wide range of formats and platforms (Win32 and Linux) with features like channel management and tag reading, while BASS provides similar functionality with beta Linux support and easy integration for music loading and playback.[84][85] Native video playback or capture is not supported, necessitating third-party libraries for such needs.
Although FBgfx enables rudimentary 3D effects through software-based projections and transformations, it lacks built-in GPU shaders, hardware-accelerated rendering, or advanced 3D primitives, relying on external bindings to OpenGL or Direct3D for complex scenes.[78] In QB mode, graphics availability aligns closely with QuickBASIC limitations, such as integer-only coordinates in DRAW, but extends to higher color depths and resolutions unavailable in the original.[81] Overall, these tools prioritize simplicity and portability for 2D applications, with multimedia extensions filling gaps in audio processing.[78]
Programming Examples
Simple Programs
FreeBASIC's straightforward syntax enables beginners to create functional programs quickly, starting with basic output and control structures. The following examples illustrate fundamental operations in the default -lang fb dialect, where variables must be explicitly declared using the Dim statement.
A quintessential introductory program is the "Hello World" example, which outputs a greeting to the console and pauses before terminating. This snippet demonstrates the Print statement for display, Sleep for user-visible delay, and End to conclude execution:
Print "Hello, World!"
Sleep
End
Print "Hello, World!"
Sleep
End
When compiled and run, it prints "Hello, World!" and waits for a keypress.[86]
Variable declaration and basic arithmetic operations are handled through the Dim keyword, which allocates memory for typed variables such as Integer, a 32-bit signed data type suitable for whole numbers.[44] Consider this example that declares an integer, performs multiplication, and outputs the result:
Dim x As Integer = 5
Print x * 2
Sleep
End
Dim x As Integer = 5
Print x * 2
Sleep
End
Executing this yields "10" on the console, showcasing assignment, arithmetic operators, and integration with Print.[44]
For interactive programs, FreeBASIC supports user input via the Input statement within looping constructs like Do...Loop, allowing repeated data entry until a condition is met. This example prompts for numbers in a loop, summing them until the user enters zero:
Dim num As Integer, total As Integer = 0
Print "Enter numbers (0 to stop):"
Do
Input "", num
If num <> 0 Then total += num
Loop While num <> 0
Print "Total: "; total
End
Dim num As Integer, total As Integer = 0
Print "Enter numbers (0 to stop):"
Do
Input "", num
If num <> 0 Then total += num
Loop While num <> 0
Print "Total: "; total
End
The program accumulates inputs and displays the sum, highlighting conditional checks and loop control for basic user interaction.[87][88]
File operations in FreeBASIC use the Open statement to access text files for output, Write or Print for content addition, and Close to finalize. The following creates and writes to a simple text file:
Open "example.txt" For Output As #1
[Print](/page/Print) #1, "This is a test line."
Close #1
[Print](/page/Print) "File written."
Sleep
End
Open "example.txt" For Output As #1
[Print](/page/Print) #1, "This is a test line."
Close #1
[Print](/page/Print) "File written."
Sleep
End
Upon running, it generates "example.txt" containing the specified line, demonstrating sequential file handling without advanced error checking.[89]
Advanced Usage Examples
FreeBASIC enables sophisticated object-oriented programming via user-defined types that support constructors, destructors, and operator overloading, allowing for reusable and extensible code structures similar to classes in other languages.[34][90]
The following example defines a basic 2D vector type with a default constructor, a parameterized constructor, and an overloaded addition operator. It includes a destructor for cleanup and demonstrates instantiation, operation, and output, with error checking for valid values.
freebasic
Type Vector2D
Public:
x As Single
y As Single
Declare Constructor()
Declare Constructor(ByVal xx As Single, ByVal yy As Single)
Declare Operator + (ByRef other As Vector2D) As Vector2D
Declare Destructor()
Private:
Declare Sub Validate()
End Type
Constructor Vector2D()
This.x = 0.0f
This.y = 0.0f
This.Validate()
End Constructor
Constructor Vector2D(ByVal xx As Single, ByVal yy As Single)
This.x = xx
This.y = yy
This.Validate()
End Constructor
Sub Vector2D.Validate()
If [Abs](/page/ABS)(This.x) > 1e6 Or [Abs](/page/ABS)(This.y) > 1e6 Then
[Print](/page/Print) "Error: Vector values too large."
This.x = 0.0f
This.y = 0.0f
End If
End Sub
Operator Vector2D.+ (ByRef other As Vector2D) As Vector2D
Return Type(This.x + other.x, This.y + other.y)
End Operator
Destructor Vector2D()
' Cleanup if extended with dynamic resources
End Destructor
' Usage example
Dim v1 As Vector2D(3.0f, 4.0f)
Dim v2 As Vector2D(1.0f, 2.0f)
Dim v3 As Vector2D = v1 + v2
Print "Result: ("; v3.x; ", "; v3.y; ")" ' Outputs: (4, 6)
[Sleep](/page/Sleep)
Type Vector2D
Public:
x As Single
y As Single
Declare Constructor()
Declare Constructor(ByVal xx As Single, ByVal yy As Single)
Declare Operator + (ByRef other As Vector2D) As Vector2D
Declare Destructor()
Private:
Declare Sub Validate()
End Type
Constructor Vector2D()
This.x = 0.0f
This.y = 0.0f
This.Validate()
End Constructor
Constructor Vector2D(ByVal xx As Single, ByVal yy As Single)
This.x = xx
This.y = yy
This.Validate()
End Constructor
Sub Vector2D.Validate()
If [Abs](/page/ABS)(This.x) > 1e6 Or [Abs](/page/ABS)(This.y) > 1e6 Then
[Print](/page/Print) "Error: Vector values too large."
This.x = 0.0f
This.y = 0.0f
End If
End Sub
Operator Vector2D.+ (ByRef other As Vector2D) As Vector2D
Return Type(This.x + other.x, This.y + other.y)
End Operator
Destructor Vector2D()
' Cleanup if extended with dynamic resources
End Destructor
' Usage example
Dim v1 As Vector2D(3.0f, 4.0f)
Dim v2 As Vector2D(1.0f, 2.0f)
Dim v3 As Vector2D = v1 + v2
Print "Result: ("; v3.x; ", "; v3.y; ")" ' Outputs: (4, 6)
[Sleep](/page/Sleep)
This code is compilable under the QB dialect and highlights initialization, overload resolution, and basic error handling.[34][90]
For graphics programming, FreeBASIC's built-in FBgfx library provides hardware-accelerated rendering with support for multiple resolutions, color depths, and drawing primitives.[79] The example below sets up a 320x200 screen in 8-bit color mode, uses a drawing loop to render animated lines with a cycling color palette, and includes cleanup on exit.
freebasic
#Include "fbgfx.bi"
ScreenRes 320, 200, 8
ScreenSet(0, 1) ' Double buffering
Dim As [Integer](/page/Integer) page = 0
Dim As [Single](/page/Single) angle = 0.0f
Dim As UByte color = 1
Do
ScreenSet(page, (page Xor 1))
ScreenSync
Cls ' Clear with [black](/page/Black)
Locate 10, 10
Print "Animated Lines - Press any key to exit"
' Draw rotating lines with color
Dim As [Integer](/page/Integer) x1 = 160 + [Cos](/page/Cos)(angle) * 100
Dim As [Integer](/page/Integer) y1 = 100 + [Sin](/page/Sin)(angle) * 50
Line (160, 100)-(x1, y1), color, 0 ' Thin line
Line (x1, y1)-(x1 + 50, y1 + 50), (color + 1) [Mod](/page/Mod) 16, B ' Filled [box](/page/Box)
angle += 0.1f
color = (color + 1) [Mod](/page/Mod) 16 ' Cycle palette
page Xor= 1
If Inkey <> "" Then Exit Do
Sleep 50, 1 ' [Frame rate control](/page/Frame_rate_control)
Loop
Screen 0 ' Cleanup to console
#Include "fbgfx.bi"
ScreenRes 320, 200, 8
ScreenSet(0, 1) ' Double buffering
Dim As [Integer](/page/Integer) page = 0
Dim As [Single](/page/Single) angle = 0.0f
Dim As UByte color = 1
Do
ScreenSet(page, (page Xor 1))
ScreenSync
Cls ' Clear with [black](/page/Black)
Locate 10, 10
Print "Animated Lines - Press any key to exit"
' Draw rotating lines with color
Dim As [Integer](/page/Integer) x1 = 160 + [Cos](/page/Cos)(angle) * 100
Dim As [Integer](/page/Integer) y1 = 100 + [Sin](/page/Sin)(angle) * 50
Line (160, 100)-(x1, y1), color, 0 ' Thin line
Line (x1, y1)-(x1 + 50, y1 + 50), (color + 1) [Mod](/page/Mod) 16, B ' Filled [box](/page/Box)
angle += 0.1f
color = (color + 1) [Mod](/page/Mod) 16 ' Cycle palette
page Xor= 1
If Inkey <> "" Then Exit Do
Sleep 50, 1 ' [Frame rate control](/page/Frame_rate_control)
Loop
Screen 0 ' Cleanup to console
This 18-line snippet demonstrates screen initialization, page flipping for smooth animation, primitive drawing with Line, color manipulation, and proper mode restoration to prevent hangs.[79][91]
FreeBASIC integrates external libraries like SDL2 through provided bindings, enabling cross-platform window management and event handling without relying solely on FBgfx.[92] The SDL2 header allows creation of resizable windows and polling for events such as quit signals, with error checking via null pointers.
freebasic
#Include Once "SDL2/SDL.bi"
#Include Once "SDL2/SDL_main.bi"
If SDL_Init(SDL_INIT_VIDEO) <> 0 Then
Print "SDL_Init Error: " & SDL_GetError()
End 1
End If
Var As SDL_Window Ptr window = SDL_CreateWindow("SDL Window Example", _
SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 480, _
SDL_WINDOW_SHOWN Or SDL_WINDOW_RESIZABLE)
If window = 0 Then
Print "Window Creation Error: " & SDL_GetError()
SDL_Quit()
End 1
End If
Dim As SDL_Event event
Dim As Integer running = 1
While running
While SDL_PollEvent(@event)
Select Case event.type
Case SDL_QUIT
running = 0
Case SDL_KEYDOWN
If event.key.keysym.sym = SDL_SCANCODE_ESCAPE Then running = 0
End Select
Wend
' Render loop placeholder (e.g., clear and draw)
SDL_Delay(16) ' ~60 [FPS](/page/FPS)
Wend
SDL_DestroyWindow(window)
SDL_Quit()
#Include Once "SDL2/SDL.bi"
#Include Once "SDL2/SDL_main.bi"
If SDL_Init(SDL_INIT_VIDEO) <> 0 Then
Print "SDL_Init Error: " & SDL_GetError()
End 1
End If
Var As SDL_Window Ptr window = SDL_CreateWindow("SDL Window Example", _
SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 480, _
SDL_WINDOW_SHOWN Or SDL_WINDOW_RESIZABLE)
If window = 0 Then
Print "Window Creation Error: " & SDL_GetError()
SDL_Quit()
End 1
End If
Dim As SDL_Event event
Dim As Integer running = 1
While running
While SDL_PollEvent(@event)
Select Case event.type
Case SDL_QUIT
running = 0
Case SDL_KEYDOWN
If event.key.keysym.sym = SDL_SCANCODE_ESCAPE Then running = 0
End Select
Wend
' Render loop placeholder (e.g., clear and draw)
SDL_Delay(16) ' ~60 [FPS](/page/FPS)
Wend
SDL_DestroyWindow(window)
SDL_Quit()
This example, approximately 15 lines, shows SDL initialization, window creation with flags, event polling in a loop for quit and key events, and resource cleanup to avoid leaks; it compiles with the SDL2 library linked.[92]
Multi-threading in FreeBASIC uses ThreadCreate to spawn parallel tasks, with mutexes ensuring safe access to shared resources like console output during computations.[93][94] The following demonstrates creating multiple threads for simulated parallel pi approximation (using simple integrals), synchronized via a mutex, with handles stored for waiting and final cleanup.
freebasic
Const As [Integer](/page/Integer) MAX_THREADS = 4
Dim Shared As Any Ptr pi_mutex
Dim Shared As [Double](/page/Double) pi_total = 0.0
Sub ComputePiSlice(ByVal data As Any Ptr)
Dim As Integer id = CInt(data)
Dim As Double slice = 0.0, step = 1.0 / (MAX_THREADS * 1000000)
Dim As Double x
For i As Integer = id To 999999 Step MAX_THREADS
x = (i + 0.5) * step
slice += 4.0 * (1.0 / (1.0 + x * x))
Next
slice *= step
MutexLock(pi_mutex)
pi_total += slice
Print "Thread"; id; "computed slice:"; slice
MutexUnlock(pi_mutex)
End Sub
pi_mutex = MutexCreate()
If pi_mutex = 0 Then Print "Mutex creation failed": End 1
Dim As Any Ptr threads(MAX_THREADS - 1)
For i As [Integer](/page/Integer) = 0 To MAX_THREADS - 1
threads(i) = ThreadCreate(@ComputePiSlice, CPtr(Any Ptr, i))
If threads(i) = 0 Then
[Print](/page/Print) "Thread creation failed for"; i
Exit For
End If
Next
For i As [Integer](/page/Integer) = 0 To MAX_THREADS - 1
If threads(i) <> 0 Then ThreadWait(threads(i))
Next
[Print](/page/Print) "Approximate pi (sum slices):"; pi_total
MutexDestroy(pi_mutex)
Sleep
Const As [Integer](/page/Integer) MAX_THREADS = 4
Dim Shared As Any Ptr pi_mutex
Dim Shared As [Double](/page/Double) pi_total = 0.0
Sub ComputePiSlice(ByVal data As Any Ptr)
Dim As Integer id = CInt(data)
Dim As Double slice = 0.0, step = 1.0 / (MAX_THREADS * 1000000)
Dim As Double x
For i As Integer = id To 999999 Step MAX_THREADS
x = (i + 0.5) * step
slice += 4.0 * (1.0 / (1.0 + x * x))
Next
slice *= step
MutexLock(pi_mutex)
pi_total += slice
Print "Thread"; id; "computed slice:"; slice
MutexUnlock(pi_mutex)
End Sub
pi_mutex = MutexCreate()
If pi_mutex = 0 Then Print "Mutex creation failed": End 1
Dim As Any Ptr threads(MAX_THREADS - 1)
For i As [Integer](/page/Integer) = 0 To MAX_THREADS - 1
threads(i) = ThreadCreate(@ComputePiSlice, CPtr(Any Ptr, i))
If threads(i) = 0 Then
[Print](/page/Print) "Thread creation failed for"; i
Exit For
End If
Next
For i As [Integer](/page/Integer) = 0 To MAX_THREADS - 1
If threads(i) <> 0 Then ThreadWait(threads(i))
Next
[Print](/page/Print) "Approximate pi (sum slices):"; pi_total
MutexDestroy(pi_mutex)
Sleep
This 20-line code spawns four threads for parallel computation, uses mutex-locking for thread-safe printing and accumulation to avoid interleaving and race conditions, waits on all handles for completion, and destroys the mutex, ensuring no resource leaks; it requires the threaded runtime (-mt).[93]