CHDK Wiki
(→‎Hello World: yes reyalP, works also on SD870 - palette issue ;))
Line 216: Line 216:
 
===Hello World===
 
===Hello World===
 
* sample from Alfredo & Orens documentation; the title says it all...
 
* 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 - 2009 ?): sucessfully tested on:
 
* may work on newer cameras (2008 - 2009 ?): sucessfully tested on:
:: SX10 (fe50), D10 (reyalp)
+
:: ''SX10 (fe50), D10 (reyalp), SD870 (fe50)''
 
* does not work on cameras without "LCDMsg_*" support:
 
* does not work on cameras without "LCDMsg_*" support:
:: SD400/Ixus50 (fe50)
+
:: ''SD400/Ixus50 (fe50)''
   
   

Revision as of 19:44, 15 August 2010

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.
  • The loading method described here does not appear to work on 2010 model cameras such as the SX210IS and SD1400/IXUS130.

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"
  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()

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.

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.

Keywords

The following keywords are known.

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

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

TODO does As datatype actually exist in this ?

For counter [ As datatype ] = start To end [ Step step ]
 [ statements ]
Next [ counter ]

Do-While/Do-Until

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

If-Then-Else

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

Functions and subroutines

Subroutines and functions appear to be equivalent, except that functions may return a value. This documentation uses subroutine to refer to both, unless the distinction is important. Event Procedures appear to be treated very similarly to user written functions.

Arguments may be literal values, variables, or function return values.

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

Calling a non-existent subroutine triggers an assert.

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

Subroutine declaration

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

Subroutine invocation

name(Arg1, Arg2)

Function declaration

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

Function invocation

var = name(Arg1, Arg2)

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. C escape sequences can be used. Tested:

\t \n \" \\ \xhh

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.

Useful scripts

CBasic dumper

  • A firmware dumper for DryOS cameras, written by reyalP


dim f,a,startadr=0,romsize

private sub Initialize()
	UI.CreatePublic()
	a=LCDMsg_Create()
	LCDMsg_SetStr(a,"Running")
	System.Create()
	
	if memcmp(0xFFC00004,"gaonisoy",8) = 0 then
		startadr = 0xFFC00000
		LCDMsg_SetStr(a,"FFC00000")
	else
		if memcmp(0xFF810004,"gaonisoy",8) = 0 then
			startadr = 0xFF810000
			LCDMsg_SetStr(a,"FF810000")
		else
			LCDMsg_SetStr(a,"start not found!")
			Wait(1000)
		end if
	end if
		
	if startadr <> 0 then
		romsize = 0xFFFFFFFC - startadr
		f=Fopen_Fut("A/PRIMARY.BIN","w")
		Fwrite_Fut(startadr,romsize,1,f)
		Fclose_Fut(f)
		LCDMsg_SetStr(a,"done")
	end if
end sub

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 - 2009 ?): sucessfully tested on:
SX10 (fe50), D10 (reyalp), SD870 (fe50)
  • does not work on cameras without "LCDMsg_*" support:
SD400/Ixus50 (fe50)


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

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