As mentioned before, an extension is simply an XC=BASIC source code file. You can define procedures, functions and constants in your extension just the way you'd do it in an XC=BASIC program.
To avoid naming collisions, you should choose a quasi namespace for the extension and prepend all your symbols with this string. For example, if you're about to write an extension that does math calculations, choose a namespace, let's say, math_
and prepend all constants, procedures and functions with the string math_
:
rem * Math extension rem * by John Doe rem * namespace: math_ const MATH_PI% = 3.14159265359 const MATH_E% = 2.71828182845 fun math_pow(base!, exponent!) result = cast(base!) for i! = 1 to exponent! - 1 result = result * base! next i! return result endfun
Since procedures can be called using the procedure name only, they are perfect for defining new commands. Combining with the ASM directive, you can write assembly code for your new commands. For example:
rem * Border coloring extension rem * by John Doe rem * namespace: bg_ const BG_BORDER = $d020 proc bg_color(color!) asm " lda {self}.color sta _BG_BORDER " endproc
Thereafter, any program using this extension can issue the new command:
include "path/to/extension.bas" bg_color 13
Notice that bg_color 13
is equivalent to call bg_color(13)
.
Simply use the FUN ... ENDFUN block to define new functions.
To speed things up, you should write functions in assembly language. To be able to do this, you need to know how to access XC=BASIC symbols and features in assembly. The following table serves as a guide:
Type | XC=BASIC symbol | Assembly symbol |
---|---|---|
Constant | EXAMPLE | _EXAMPLE |
Global variable | example | _example |
Local variable | example | _procname.example or {self}.example within the procedure |
Argument of procedure or function | example | _procname.example or {self}.example within the procedure |
The following example attempts to demonstrate how to write a function in assembly language.
rem ** This function returns one if fire button rem ** in joystick port #1 or port#2 is pressed, zero otherwise const JOY_PORT2 = $dc00 const JOY_PORT1 = $dc01 fun joy_firepressed!(port!) dim result! asm " ; This is how to refer to a function's argument lda {self}.port ; Port #2 becomes 0, Port #1 remains 1 and #%00000001 tax ; This is how to refer to a global constant lda.wx _JOY_PORT2 eor #%11111111 and #%00010000 lsr lsr lsr lsr ; A now holds the return value of our function ; Write it to the variable 'result!' sta {self}.result " return result! endfun
When you're done with your extension, please follow these steps:
xcb-ext-<extension_name>.bas
xcb-ext-<extension_name>
, upload your files and notify me in email (feketecsaba [at] gmail) about the new extension and I'll add it to the extensions/
folder as a submodule