一键导入
using-bbcbasic
Syntax and usage for BASIC on RISC OS. Use this whenever you are creating, editing or reviewing BASIC code (files which end in `,fd1`).
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Syntax and usage for BASIC on RISC OS. Use this whenever you are creating, editing or reviewing BASIC code (files which end in `,fd1`).
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
Guidance for registering RISC OS allocations with the RISC OS Open allocation service. Use when the user wants to register a module name, SWI chunk, error block, *command, filetype, system variable, or any other RISC OS allocation. Also use when the user asks "how do I register X", "I need to allocate X", or wants to send an allocation request to RISC OS Open.
Create, extend, review, and repair RISC OS CI pipelines, especially GitHub Actions and GitLab CI files, optional matching `.robuild.yaml` or `.robuild.yml` files for build-service jobs, 32-bit and 64-bit builds, build-service testing, artifact packaging, and draft releases. Use when Codex needs to work on `.github/workflows/*.yml`, `.gitlab-ci.yml`, `example-ci.yml`, `.robuild.yaml`, `.robuild.yml`, `riscos-project create-ci`, build.riscos.online integration, or RISC OS packaging/testing patterns for AIF, RM, and library-export projects.
Create useful pull requests or merge requests with clear reviewer-focused descriptions. Use when opening a PR or MR, especially when the description should explain the problem, summarise the changes, and record testing in a standard structure.
How to design modules for RISC OS. Use when creating new modules, designing interfaces to modules, porting a library to be used in a new module, or extending the existing interfaces of modules.
Port C projects to RISC OS using `riscos-cport`, RISC OS makefiles, and Norcroft/RISC OS build validation. Use when a repository needs a RISC OS library or command-line port, especially when you need to create a `RISCOS/` tree, generate `Makefile,fe1` files, or repair source for the RISC OS toolchain.
Read and translate RISC OS ObjAsm/ARM assembly into another language, PyModule, tests, or interface documentation. Use when converting `s/*` assembler modules, reconstructing SWI behaviour, validating comments against generated tables/disassembly, or proving binary-compatible data layout and boundary behaviour.
| name | using-bbcbasic |
| description | Syntax and usage for BASIC on RISC OS. Use this whenever you are creating, editing or reviewing BASIC code (files which end in `,fd1`). |
| metadata | {"author":"gerph@gerph.org"} |
| license | MIT |
| allowed-tools | Bash(riscos-build-run:*) Bash(host-open:*) |
BASIC programs in textual format have a filename which ends with ,fd1 and does not have an extension. Prefer creating textual format files.
BASIC programs in tokenised format have a filename which ends with ,ffb and does not have an extension. Never edit tokenised files. Tokenised files can be decoded with:
riscos-basicdetokenise -i PROGRAM,ffb -o OUTPUT,fd1 riscos-basicdetokenise -i PROGRAM,ffb
Always use the -i form. Do not call riscos-basicdetokenise PROGRAM,ffb
without -i; that only prints the syntax message.
Line numbers should not be used.
Start programs with:
REM >filename REM purpose ON ERROR ERROR EXT ERR, REPORT$ + " at line " + STR$(ERL/10)
To run a program run the command:
riscos-build-run PROGRAM,fd1 --command "run PROGRAM"
INPUT will not work within programs executed this way (the system will reset).To save a screenshot as a PNG use:
*ScreenSave -native
To run the program and return a screenshot, use a command like:
riscos-build-run PROGRAM,fd1 --command "run PROGRAM" --command "screensave -native screen" --return-file screen --return-to screen.png
To show the user a screenshot, use the shell command host-open screen.png.
When reviewing or porting tokenised BASIC libraries:
riscos-basicdetokenise -i <file> before reasoning about symbol names, menu strings, or record-field use.riscos-basicdetokenise <file> without -i as wrong; it does not detokenise the file.: character, but this is discouraged.IF statements, FOR, REPEAT and WHILE loops should be indented by 2 characters.DEFPROC<name> or DEFPROC<name>(param1,param2,...), and are invoked with PROC<name>$, for example name$.%, for example cows%.Graphics co-ordinates on RISC OS use:
Before you declare anything complete when drawing graphics, check that you've really got the co-ordinates right.
To select a resolution, use:
MODE "X<xpixels> Y<ypixels> C<colours>"
For tests that require a specific colour depth, prefer an explicit mode string such as MODE "X640 Y480 C256" rather than relying on a numeric mode number. Numeric modes vary by environment and may not have the expected depth.
For paletted modes (where you can change the colours) you would usually use a 16 colour mode
like MODE 27, which is 640x480 pixels.
If you are using colour, always check that the colours you are using are what comes out - often the red and green components have been confused.
To clear the screen to a paletted colour, set the background colour first:
GCOL 0,128+colour
CLG
To plot triangles, use:
MOVE <x0>,<y0>
MOVE <x1>,<y1>
PLOT 85,<x2>,<y2>
To flood fill, use:
PLOT 133, <x>, <y>
For more information on the graphics system, use the skill riscos-output which describes graphics calls, VDU sequences, colour selection, fonts and sprites in much more detail.
In 256 colour modes, select colours using the OS_SetColour SWI call. This is necessary because the GCOL interface require the use of TINT in a 256 colour mode, which makes for a much more complex colour selection.
Do not use GCOL 0, RND(255) (the colour numbers for 256 colour modes in GCOL are only selectable up to number 63, with the tint providing the remaining 2 bits). Use SYS "OS_SetColour", 0, RND(255) instead.
When selecting colours, you can use RGB colour selection by using the call SYS "ColourTrans_SetGCOL", &BBGGRR00,,,0,0 to set the foreground graphics colour to the closest RGB colour. To set the graphics background colour to a RGB colour, use SYS "ColourTrans_SetGCOL", &BBGGRR00,,,128,0, and then CLG to clear the whole screen.
The ColourTrans calls are preferred over the GCOL calls as they allow the code to be safe for use in any screen mode.
Text co-ordinates on RISC OS use:
To write text on the screen at the text cursor, use VDU 31, <xchar>, <ychar>. Text characters are
8 pixels by 8 pixels.
To write text on the screen at the graphics cursor, use VDU 5 to enable writing to the graphics
cursor, then PRINT the text, and finally VDU 4 to return to the text cursor.
System calls can be made with the SYS keyword, which can be given a string or a number for the
SWI to call, followed by values for the input registers. For example, to call OS_ReadModeVariable
with R0=-1 and R1=3, and return R2 into ncols you would use
SYS "OS_ReadModeVariable",-1,3 TO ,,ncols.
If you want to check for errors, use the X-prefixed version of the SWI name, and return the flags,
in the form SYS "Xswiname", r0,r1,r2,... TO r0,r1,r2 ;flags%. Bit 0 of flags% will be set if an error (V flag) was returned.
If the error was returned, the error number will be in the memory at r0+0, which you can read with r0!0.
Up to 10 registers can be passed into the SWI and returned.
Example usage of non-erroring SWI call:
REM BBC BASIC - use X-SWIs for error handling
SYS "XTimer_ReturnNumber", 0 TO r0%,r1%,r2%;flags%
IF flags% AND 1 THEN
error_num% = r0%!0 : REM Error number at R0+0
PRINT "Error returned: &";~error_num%
ELSE
PRINT "Timers count: ";r0%
ENDIF
It is redundant to use X-SWIs and raise errors if nothing is being handled.
Wrong:
SYS "XModule_Parse", file$ TO h%; flags%
IF (flags% AND 1) THEN SYS "OS_GenerateError", h%
Correct:
SYS "Module_Parse", file$ TO h%
This implicitly raises the error.
C calls can be translated to BASIC SYS calls. A C call using _swix takes a SWI number (which is always called as an X-SWI), input registers (_IN(reg)) or a range of input registers (_INR(low, high)), and output registesr (_OUT(reg)) or a range of output registesr (_OUTR(low, high)). For example a C call like:
_kernel_oserror *err;
err = _swix(OS_Plot, _INR(0, 2), inr0, inr1, inr2);
Might be represented in BASIC as:
SYS "XOS_Plot", inr0%, inr1%, inr2% TO err% ;flags%
IF flags% AND 1 THEN
REM error pointer is in err%
ENDIF
A C call using _swi will raise an error if it fails. It is therefore equivalent to the non-X version of a SWI. A C call like:
_swi(DrawFile_Render, _INR(0, 5), flags%, drawdata%, size%, matrix%, rect%);
Would be directly equivalent to:
SYS "DrawFile_Render", flags%, drawdata%, size%, matrix%, rect%
The _kernel_swi convention passes 10 registers in a _kernel_swi_regs structure,
and returns them into a second structure. Usually the output registers are the same.
The SWIs are always called as X-SWIs, even it they are not specified as such.
For example:
_kernel_oserror *err;
_kernel_swi_regs regs;
regs.r[0] = inr0;
regs.r[1] = inr1;
regs.r[2] = inr2;
err = _kernel_swi(OS_Plot, ®s, ®s);
Is equivalent to:
SYS "XOS_Plot", inr0%, inr1%, inr2% TO err% ;flags%
IF flags% AND 1 THEN
REM error pointer is in err%
ENDIF
byte% = ?ptr%byte% = ?(ptr% + 4) or byte% = ptr%?4 (never byte% = 4?ptr%)word% = !ptr%word% = !(ptr% + 4) or word% = ptr%!4 (never word% = 4!ptr%)str$ = $ptr%str$ = $(ptr% + 4) (never str$ = $ptr%+4)0-terminated strings are not easily readable with operators, and are usually implemented by a helper function at the end of the file:
DEFFNstring0(ptr%)
LOCAL s$
SYS "OS_IntOn",ptr% TO s$
= s$
?ptr% = byte%?(ptr% + 4) = byte% or ptr%?4 = byte% (never 4?ptr% = byte%)!ptr% = word%!(ptr% + 4) = word% or ptr%!4 = word% (never 4!ptr% = word%)$ptr% = str$$(ptr% + 4) = str$ (never $ptr%+4 = str$)0-terminated strings are not easily writable with operators, and are usually implemented writing a string with an 0, and then overwriting the CR afterwards (if needed). For example, to write the string Hi! to memory, followed by a 0-terminator you might use:
$ptr% = "Hi!"+CHR$0
For programs which need C-like dynamic allocation, especially desktop applications which keep many buffers or variable-sized structures alive for a long time, see references/heaplib.md.
The skill also includes a reusable plain-text copy of the non-debug library at assets/HeapLib/HeapLib,fd1.
Bad variable names:
If the program reports a syntax error, for a variable assignment or use, check the variable name.
Variable names must not start with a BASIC keyword, and will report Syntax error if they see this.
Do not:
ORBIT = 5
PICTURE$ = "filename"
PROCESS = TRUE
TANGENT = 0
VALUE% = 10
Instead use variables in lower case to avoid the problem:
orbit = 5
picture$ = "filename"
process = TRUE
tangent = 0
value% = 10
Unknown location of the problem:
If an error occurs, but the program does not report at line <number>, this may mean that there is no error handler to help in this process. If the line number is given, but is far too high for the program, this may mean that the error handler is not reporting the right number. BASIC will renumber lines, in increments of 10, so we must divide the error line (ERL) by 10.
Early in the file there should be an error handler like:
ON ERROR ERROR EXT ERR, REPORT$ + " at line " + STR$(ERL/10)
This will cause the program to exit.
Syntax error on lines with comments:
It has been common to not use : separator for statements and comments.
Do not:
name$ = "bob" REM user's name
circles = 7 REM how many to draw
Instead do this:
name$ = "bob" : REM user's name
circles = 7 : REM how many to draw
Using a 256 colour mode with GCOL:
Using GCOL to select colours in a 256 colour mode does not work as you expect. Colours are selected in the form GCOL <base-colour> TINT <tint> where is a value from 0-63 and is a value 0, 64, 128, or 192 for each of the lower bits of the colour. The tint adds progressive lightness to the colour.
Instead of this, use OS_SetColour, eg SYS "OS_SetColour",0,<colour> which allows the full 256 colour range to be used.
Tilde (~) is a PRINT format modifier only:
The ~ prefix formats a number as hexadecimal, but it is only valid as a format modifier
directly inside a PRINT statement (or PRINT ... ; chain). It cannot be used inside a
string expression.
PRINT ~n% : REM OK - prints n% in hex
PRINT "val: ";~n% : REM OK - prints "val: " then hex n%
To embed a hexadecimal number inside a string, use STR$~:
msg$ = "value is &" + STR$~n% : REM correct
msg$ = "value is &" + ~n% : REM WRONG - syntax error
ON ERROR LOCAL cannot be used at top level:
ON ERROR LOCAL installs a local error handler that is only valid inside a PROC or FN.
Using it at the top level of a program (outside any procedure) causes a
"badly nested error handler" error.
Use ON ERROR (without LOCAL) at top level, or move the guarded code into a PROC:
REM at top level, use the plain form:
ON ERROR ERROR EXT ERR, REPORT$ + " at line " + STR$(ERL/10)
For per-call error trapping without a procedure boundary, use X-prefixed SWIs and check
bit 0 of the flags variable instead of relying on ON ERROR LOCAL.
When BASIC is used for smoke tests or SWI probes:
--command runs OSCLI, not BASIC statements.SYS, MODE, loops, and assertion logic in the BASIC file itself.Run command.