CHDK Wiki
Advertisement

Introduction

Canons firmware includes a scripting language, which appears to be a flavor of basic. Thanks to recent work by Alfredo Ortega and Oren Isacson of core labs, it is now known how to execute scripts in this language. They have made available their defcon presentation and some preliminary documentation, read more in this forum thread.

  • This script system is available on both VxWorks and DryOS cameras, although the functions available vary by OS and camera model.

Warning

WARNING:
The Canon scripting language provides access to functions which can cause permanent, unrecoverable damage to the camera !
This includes, but is not necessarily limited to modifying the internal flash ROM where the firmware is stored.

Executing Scripts

Based on Alfredo and Orens documentation.

This section contains information about the format and contents of the SD cards and basic script required for execution.

Format of the SD card

  • The SD card may be in FAT16 or FAT32 format.
  • The SD card must contain the following items:
  1. The string "SCRIPT" must be at offset 0x1F0 of the first sector (Boot sector).
  2. The file "script.req" must exist on the card's root directory, and must only contain the string "for DC_scriptdisk\n" (where the \n represents a newline character)
  3. The file "extend.m" must exist on the root directory. This file must contain the Canon BASIC script to execute.

Script extend.m

The script extend.m, residing on the root directory must contain the basic script. There are two callback subroutines called by the camera to initialize the execution:

private sub Initialize( )
' Init code
end sub
private sub terminate( )
' Ending code
end sub

The two subroutines will be called in order: First Initialize(), then terminate()

On some cameras (older, vxworks ?) terminate is not called.

Starting the script

Once an SD with this format is inserted on the Camera, the script is called when the camera is in playback mode, by pressing FUNC./SET.

On newer touch screen cameras, without a 'Func/Set' button, the script can be started by holding the zoom lever to the left (zoom out) while starting the camera in playback mode. After the camera has started release the zoom lever, then press it to the left again. Tested on Ixus 310 HS (Elph 500 HS).

Language documentation

Much of this is based on Alfredo and Orens original documentation.

General Information

The language consists of a structured BASIC-like core, together with a large number of functions exported from the firmware. These functions are also known as Event Procedures, and in many cases are the same functions used by CHDK. The same event procedures may also be called from CHDK Lua using the LUA/LUA_Reference/Native_Function_Calls. For historical reasons, the name used by CHDK may not match the event procedure name, or a function referred to in CHDK by an event procedure name may actually call a different firmware function.

It is unknown whether the language is entirely a Canon proprietary development or if it is derived from some other flavor of basic. Figuring this out would be useful.

The interpreter is very sensitive to syntax errors. Incorrect syntax usually triggers an ASSERT in the camera interpreter (which causes the camera to power down, use the Canon ROMLOG to diagnose) or cause it to display FAILED on the screen and then shut down.

note This documentation is based on experimental results from a few cameras. Different models or Canon OS versions may not behave identically.

Keywords

The following keywords are known.

sub public while else private if until dim then function extern do step loop for exit next to

Keywords are case insensitive.

In addition, there are at least two special function names, Initialize and terminate, described above.

Comments

a ' causes the remainder of the line to be treated as a comment

Operators

Relational: <, >, <=, >=

Equality: =, <>

Assignment: =

Arithmetic: +, -, *, /

Address/Pointer: &, * (like C, but see note)

Bitwise: &, |, <<, >> (like C, but see note)

notes

  1. Space and context are used to decide the meaning of some operatators. & and * are taken as pointer operators if there is no space between the operator and operand. If there is space, they are treated as multiplication and bitwise and.
  2. The = operator is treated as assignment or equality test depending on whether it appears in a conditional or not.
  3. Precedence is unknown

Control structures

In the condition below = is treated as an equality operator. Variables, functions, event procedures and literal values may also be used.

For-next

For counter = start To end
 [ statements ]
Next

Do-While/Do-Until

Do { While | Until } condition
 [ statements ]
 [ Exit Do ]
 [ statements ]
Loop

If-Then-Else

If condition Then
  [ statements ]
[else]
  [ statements ]
End If

Subroutines

Arguments to subroutines may be literal values, variables, or function return values. Unlike some flavors of BASIC, a subroutine may return a value. The function keyword also exists, but appears to be redundant and possibly broken.

Arguments are passed by value (but may contain pointers).

Calling a non-existent subroutine triggers an assert on some cameras (DryOS ?) and is ignored on others.

The meaning of the Public, Private and Extern keywords are not known.

Subroutine declaration

[ Public ] | [ Private ] Sub name (Arg1 , Arg2 )
  [ statements ]
  [ name = return_value ]
  [ Exit Sub ]
  [ statements ]
End Sub

Subroutine invocation

[var =] name(Arg1, Arg2)

Subroutines must be declared before the first invocation in the file. No forward declaration syntax is known.

Event Procedures appear to be treated very similarly to user written subroutines. You may use ExecuteEventProcedure() to safely attempt to call an event procedure which might not be registered. If the event procedure is not registered, the return value will be -1. On some cameras ExecuteEventProcedure itself must be registered by calling SystemEventInit.

The above syntax can be used substituting function for sub, but only if lower case. exit function is not recognized.

Identifiers

Identifiers include subroutines, functions and variables defined by the script, as well as event procedures exported by the firmware.

All of these identifiers are case sensitive. The variables A and a are completely independent. Note: The special initialize subroutine may be named Initialize() or initialize(), but only because the canon code checks for both. initializE() is not recognized, and terminate() is only recognized in lower case.

The exact rules for identifiers have not been determined. Some event procedures have a . in the name (e.g System.Create), but this does not appear to be significant to the language.

Variables

Scope

Variables may be local, global or subroutine parameters.

Global variables are declared and optionally assigned using the dim keyword outside of any subroutine. Using dim inside a subroutine triggers an ASSERT.

Variables used in a subroutine without being declared are local to that subroutine.

Subroutine parameters appear to act like local variables, unless the parameter name is the same as a global. In that case, the global is set when the subroutine is called.

Values

Variables may be assigned numbers or strings, including values returned by event procedures.

Numeric literals may be given in decimal or C hex notation.

String literals are delimited by double quotes. Some C escape sequences can be used. The following are verified on D10 and a540:

\t \n \" \\

Hex \xHH and octal \NNN escapes do not appear to work, although they may be handled by some functions.

The value of an unassigned variable appears to be zero.

Variables or literal values are treated as pointers when the underlying function expects a pointer or string.

Array and structure types are not known to exist. The typical basic DIM var(10) syntax for arrays does not appear to work.

Useful scripts

CBasic dumper

Dump camera firmware to file. See Canon Basic/Scripts/Dumper

CBasic loader

Load and run an ARM binary. See Canon Basic/Scripts/Loader

Hello World

  • sample from Alfredo & Orens documentation; the title says it all...
  • note: capture an image with light colors first (e.g. a "white" image), the text color may be black or very dark ;)
  • may work on newer cameras (2008 - 2010): sucessfully tested on:
SX10 (fe50), D10 (reyalp), SD870 (fe50), SD4000IS (pixeldoc), SD960IS (tobi), SD1400IS / IXUS 130 (emlyn), A470 / G10 / A580 (aortega)
  • does not work on cameras without "LCDMsg_*" support:
SD400 (fe50)
  • work with A1100 IS 100c build CHDK 0.9.9 Jun 23 2010 14:25:15 a1100 100c GCC 3.4.6
  • with script line added " LCDMsg_ChangeColor(a ,6) " after SetStr
       A1100 (david1116)
       S95 (fetidpants)


private sub sayHello()
	a=LCDMsg_Create()
	LCDMsg_SetStr(a,"Hello World!")
end sub

private sub Initialize()
	UI.CreatePublic()
	sayHello()
end sub


private sub Initialize()
 SystemEventInit()
 UI_RegistDebugEventProc()
 ControlViewEvent(0x18E, "Hello, world!")
 Wait(1000)
 ControlViewEvent(0x68, 0) ' Hide the message
end sub

RomLog

Get the canon crash log from onboard flash to SD card. See Canon Basic/Scripts/Romlog

LED Test

  • script does show the value of the active LED, maybe usefull for CHDK function ubasic_set_led.
  • You might need to change the value for the display color (cl), see also Canon Basic/Reference.
  • sucessfully tested on:
A720IS (msl), SD1400IS / IXUS 130 (emlyn), SD940 (with change color : dim cl=2)
dim a,b,c
dim cl=1

private sub Initialize()

    System.Create()
    Driver.Create()
    UI.CreatePublic()

    a=LCDMsg_Create()
    LCDMsg_ChangeColor(a,cl)
    LCDMsg_SetStr(a,"LED Test")
    Wait(2000)
 
    b=LCDMsg_Create()
    LCDMsg_ChangeColor(b,cl)
    LCDMsg_Move(b,300,50)

    for c=0 to 15  
        LCDMsg_SetNum(b,c)
        BeepDrive(3)
        Wait(500)
        LEDDrive(c,0)
        Wait(2000)
        LEDDrive(c,1)
    next

    Wait(2000)
    LCDMsg_SetStr(a,"Test End")

end sub

private sub Terminate()

end sub
Advertisement