574 lines
23 KiB
Markdown
574 lines
23 KiB
Markdown
# Building Applications on the Psion SIBO / Workabout in C
|
||
|
||
A reference for developing C applications for the Psion SIBO family (HC, MC,
|
||
Series 3/3a/3c, Siena, Workabout) using the SIBO C SDK and the TopSpeed C
|
||
compiler.
|
||
|
||
Sourced from the *SIBO 'C' Software Development Kit — General Programming Manual*
|
||
(v2.30, March 1999) and the *SIBO Hardware Development Kit* (May 1995) LDD
|
||
sections. Claims are drawn only from those documents; where a point is not
|
||
stated in the source it is marked as such.
|
||
|
||
> **Workabout MX note.** The manual (SDK v2.30) names the *Workabout* and
|
||
> *Siena* but does not mention a distinct "Workabout MX" model. Everything here
|
||
> that applies to the Workabout applies to the MX at the SIBO/EPOC-16 level.
|
||
> Anything genuinely MX-specific is called out explicitly; unmarked material is
|
||
> generic SIBO and holds for the MX unless noted.
|
||
|
||
---
|
||
|
||
## 1. Architecture and programming model
|
||
|
||
A SIBO machine is "a battery-powered portable computer that is based on the SIBO
|
||
architecture ... designed to minimise the size, weight and power consumption"
|
||
(General, ch. 2). Key hardware components named by the manual:
|
||
|
||
- A power-management system that "selectively powers subsystems under software control".
|
||
- Solid State Disks (SSDs) — "fast low-power silicon-based mass storage with no moving parts".
|
||
- Asynchronous serial interface running at "Mega bit rates".
|
||
- **"An 8086 class of processor (or any compatible processor such as an 80286)"** (General, ch. 2).
|
||
- Hardware protection: "address trapping of out-of-range writes and a watch-dog timer on interrupts being disabled".
|
||
- Real-time clock, ROM-resident system software, graphics LCD, and (on some models) a touch-sensitive digitising pad.
|
||
|
||
The hardware is "primarily implemented in custom ICs called ASICs ... surface-mounted static CMOS ICs throughout."
|
||
|
||
> **CPU note / uncertainty.** The manual describes the CPU only as "an 8086
|
||
> class of processor (or any compatible processor such as an 80286)". The
|
||
> commonly cited V30-class part (NEC V30 / V30H, an 8086-compatible) is **not
|
||
> named in these source documents**; treat "V30-class" as background, not a
|
||
> manual quotation. The programming-relevant fact is what the manual does state:
|
||
> it is an 8086-class, 16-bit, real-mode-segmented CPU with no 8087.
|
||
|
||
The operating system is **EPOC** (here the 16-bit EPOC that runs on SIBO; not
|
||
the later 32-bit EPOC32). Features listed (General, ch. 2):
|
||
|
||
- Preemptive multi-tasking; MS-DOS-compatible and installable file systems.
|
||
- Asynchronous services and client-server architecture (file server, window server).
|
||
- A comprehensive I/O system with many built-in I/O devices and **dynamically loadable device drivers**.
|
||
- A **reentrant function library**; "multiple processes of the same program share a single copy of the code"; code-shared dynamic link libraries.
|
||
|
||
> The terms are distinguished in the manual: *SIBO* = the hardware
|
||
> architecture; *EPOC* = the operating system designed for it. On SIBO
|
||
> machines "the system software resides on an in-built ROM."
|
||
|
||
### Fatal errors (panics)
|
||
|
||
When the system detects a condition it believes can only be a bug, it
|
||
"terminates the process with a 'panic number' in the range 0 to 255 ... There is
|
||
no way for applications to avoid being terminated when a panic has been started."
|
||
Panic-number ranges (General, ch. 2):
|
||
|
||
| Range | Source |
|
||
|-------|--------|
|
||
| 0–80, and 255 | PLIB library |
|
||
| 81–129 | Window Server library |
|
||
| 130–160 | OLIB object library |
|
||
| 160–254 | non-ROM code (e.g. the ISAM library) |
|
||
|
||
`panic 80` specifically often means a program "failed to locate SYS$8087.LDD"
|
||
(the floating-point emulator LDD) — see §5.
|
||
|
||
### Why TopSpeed C (small model)
|
||
|
||
Applications are written, compiled and linked on a PC and then run/debugged on
|
||
the SIBO machine. The compiler and linker are the **TopSpeed C** system
|
||
(Clarion Software Corporation). The SDK requires the *small code model* of
|
||
TopSpeed:
|
||
|
||
> "`#model small jpi` — The code is to be compiled in small model (code and
|
||
> data segments each restricted to 64K), with the jpi (TopSpeed C) convention
|
||
> of using registers to pass parameters to subroutines." (General, ch. 3)
|
||
|
||
You may install other TopSpeed code models, but "they will not be used by the
|
||
SIBO SDK." Small model matches the 8086-class segmented architecture: a single
|
||
64K code segment and a single 64K data segment, with `CS`/`DS`/`SS` behaving as
|
||
a "pure small model" where "`ds=es=ss`" (General, ch. 4). The `jpi` calling
|
||
convention (register parameter passing) is mandatory for SIBO builds.
|
||
|
||
Because there is no 8087, "all floating point is performed by software emulation
|
||
of the 8087" (General, ch. 4).
|
||
|
||
---
|
||
|
||
## 2. CLIB vs PLIB
|
||
|
||
Two C libraries are available:
|
||
|
||
**CLIB** — "a version of the TopSpeed C library for the EPOC operating system
|
||
... a version of the standard ANSI C library." Benefits: portability (existing C
|
||
ports easily) and less to learn. Documented in the *TopSpeed C Library
|
||
Reference*, with SIBO caveats in *Notes on CLIB*.
|
||
|
||
**PLIB** — Psion's proprietary C library, providing "only very thin shells over
|
||
functionality that is present in the ROM." Functions are prefixed `p_`.
|
||
|
||
The manual "strongly urges" developers to consider PLIB over CLIB:
|
||
|
||
- "many of the ROM-based EPOC system services are not available from CLIB (eg
|
||
asynchronous I/O, inter-process messaging, the window server graphics functions)"
|
||
- "executables are larger in CLIB and the process takes a larger data segment."
|
||
|
||
CLIB is a "much 'thicker' library"; its subsystems "typically require large
|
||
static buffers and tables." You can freely mix PLIB and CLIB calls (unless using
|
||
the object-oriented UI dynamic libraries). The Window Server library is `WLIB`
|
||
(`wlib.lib`, functions `g...`/`w...`, header `wlib.h`), automatically linked
|
||
when needed.
|
||
|
||
CLIB omissions worth knowing (Notes on CLIB): many BIOS/DOS/graphics/far-pointer
|
||
functions are not implemented. `getRealHandle(int handle)` converts a CLIB file
|
||
handle to a PLIB handle. CLIB startup auto-opens a console channel assigned to
|
||
`stdin`/`stdout`/`stderr`; you can suppress it by defining `p_xwind` and setting
|
||
the global `_winHandle`.
|
||
|
||
### Standard SIBO C types
|
||
|
||
The manual's example code uses a standard set of SIBO C types in place of raw C
|
||
types. (These are defined in the SDK headers — `plib.h`/`stddefs`; the General
|
||
manual uses them but their formal definitions live in the PLIB Reference.)
|
||
Observed usage:
|
||
|
||
| Type | Meaning (from usage in the manual) |
|
||
|---------|-------------------------------------|
|
||
| `TEXT` | character / text byte (e.g. `TEXT *pb;`, `TEXT subname[P_FNAMESIZE];`) |
|
||
| `UBYTE` | unsigned 8-bit byte |
|
||
| `WORD` | signed 16-bit word |
|
||
| `UWORD` | unsigned 16-bit word (e.g. `UWORD answer;`) |
|
||
| `INT` | signed integer (return type of `main`) |
|
||
| `UINT` | unsigned integer (e.g. `UINT lcdtype;`) |
|
||
| `VOID` | void (e.g. `main(VOID)`) |
|
||
|
||
> **Uncertainty.** The exact widths/signedness of each typedef are not spelled
|
||
> out in the General manual; they are defined in the SDK headers / PLIB
|
||
> Reference. The mappings above reflect how the manual uses them and standard
|
||
> SIBO conventions. Use the uppercase SIBO types rather than raw C types in
|
||
> SIBO code.
|
||
|
||
### Storage-class macros
|
||
|
||
The example code uses uppercase storage-class macros instead of bare C storage
|
||
classes. These make the code portable across the segmented model and the SDK's
|
||
linkage conventions.
|
||
|
||
| Macro | Used for | Manual examples |
|
||
|-------|----------|-----------------|
|
||
| `GLDEF_C` | **global definition** of code (a function you define, visible externally) | `GLDEF_C INT main(VOID)`, `GLDEF_C VOID main(VOID)` |
|
||
| `GLREF_C` | **global reference** to code / an external symbol (declared elsewhere) | `GLREF_C TEXT *DatCommandPtr;` |
|
||
| `GLDEF_D` | global definition of data | (data counterpart of `GLDEF_C`) |
|
||
| `GLREF_D` | global reference to data defined in another module | `GLREF_D TEXT *DatCommandPtr;` |
|
||
| `LOCAL_C` | file-local (`static`) function | `LOCAL_C VOID QueueKey(VOID)`, `LOCAL_C VOID CancelTimer(VOID)` |
|
||
| `LOCAL_D` | file-local (`static`) data | (data counterpart of `LOCAL_C`) |
|
||
|
||
> `_C` suffix = code/function, `_D` suffix = data; `GL...` = global (external
|
||
> linkage), `LOCAL_...` = module-private. The General manual shows `GLDEF_C`,
|
||
> `GLREF_C`, `GLREF_D`, and `LOCAL_C` directly; `GLDEF_D`/`LOCAL_D` are the data
|
||
> counterparts (formal definitions in the PLIB Reference).
|
||
|
||
### Program entry point
|
||
|
||
A PLIB program's entry point is `main`, written with the SIBO macros:
|
||
|
||
```c
|
||
#include <plib.h>
|
||
|
||
GLDEF_C INT main(VOID)
|
||
{
|
||
p_printf("Hello World");
|
||
p_getch();
|
||
return (0);
|
||
}
|
||
```
|
||
|
||
A CLIB program uses ordinary ANSI style with `<stdio.h>`:
|
||
|
||
```c
|
||
#include <stdio.h>
|
||
|
||
int main(VOID)
|
||
{
|
||
printf("Hello World");
|
||
getchar();
|
||
return (0);
|
||
}
|
||
```
|
||
|
||
(Both `hello.c` and `p_hello.c` are taken verbatim from General ch. 3.)
|
||
|
||
---
|
||
|
||
## 3. Project (`.pr`) files
|
||
|
||
The compile/link cycle is driven by TopSpeed **project files** (extension
|
||
`.pr`). The minimal CLIB project (`hello.pr`):
|
||
|
||
```
|
||
#system epoc img
|
||
#model small jpi
|
||
|
||
#compile hello
|
||
#link hello
|
||
```
|
||
|
||
The minimal PLIB project (`p_hello.pr`):
|
||
|
||
```
|
||
#system epoc img
|
||
#set epocinit=iplib
|
||
#model small jpi
|
||
|
||
#compile p_hello
|
||
#link p_hello
|
||
```
|
||
|
||
### Directives
|
||
|
||
- **`#system epoc img`** — "The end outcome of the build is a `.img` file, as
|
||
defined in the Epoc-customised part of the TopSpeed configuration (alternative
|
||
`#system`s include `dos` and `win`)." Required in every SIBO project file.
|
||
|
||
- **`#model small jpi`** — small code model + jpi register calling convention
|
||
(see §1). Required in every SIBO project file.
|
||
|
||
- **`#set epocinit=iplib`** — selects the startup object and stack size. **Must
|
||
precede `#model`.** It "specifies whether you are using the CLIB or PLIB
|
||
startup object files, and it specifies the stack size." Allowed values:
|
||
|
||
| Value | Startup | Stack |
|
||
|-------|---------|-------|
|
||
| `iclib` | CLIB | 8k (recommended for CLIB) |
|
||
| `iclib4` | CLIB | 4k |
|
||
| `iclib2` | CLIB | 2k |
|
||
| `iplib` | PLIB | 4k (recommended for PLIB) |
|
||
| `iplib8` | PLIB | 8k |
|
||
| `iplib2` | PLIB | 2k |
|
||
|
||
If unset, defaults to `iclib`. You **must** use CLIB startup if you use any
|
||
CLIB I/O functions; if you use no CLIB functions at all, "you should always
|
||
use the PLIB startup." (Non-I/O CLIB functions such as memory allocation can
|
||
be used with PLIB startup.)
|
||
|
||
- **`#compile <name>`** — compile a source module. If ambiguous, add the `.c`
|
||
extension (e.g. `#compile query.c`), because the system also treats `.a`
|
||
(assembler) and `.rc` files as candidate sources and errors if two candidates
|
||
exist.
|
||
|
||
- **`#link <name>`** — link everything. Its effect: link all `#compile`d files,
|
||
plus the startup module and standard libraries, plus anything named by
|
||
`#pragma link`, giving the executable the name in the `#link` statement. The
|
||
`#link` name need not match the `.pr` filename nor any module name.
|
||
|
||
- **`#dolink <name.lib>`** — used **instead of** `#link` to build a **library**.
|
||
It stops the system linking in a startup object and standard libraries. The
|
||
explicit `.lib` extension overrides the default `.img` implied by `#system
|
||
epoc img` (see §4).
|
||
|
||
- **`#pragma link (<file>)`** — link an extra object file or library not
|
||
searched automatically. Examples: `#pragma link (hwif.lib)` (HWIF is not
|
||
auto-searched), `#pragma link (utils.lib)` (a custom library, found along the
|
||
`ts.red` search path).
|
||
|
||
- **`#pragma debug (vid=>full)`** — insert before any `#compile` to build with
|
||
full source-level debug info (equivalent to the `/v2` command-line flag).
|
||
|
||
### Overriding image attributes
|
||
|
||
Three project variables (also settable as `/s...` on the command line):
|
||
|
||
| Variable | Meaning | Default |
|
||
|----------|---------|---------|
|
||
| `%version` | image version number | `0x100f` |
|
||
| `%priority` | initial process priority | `0x80` |
|
||
| `%heapsize` | initial and minimum heap, in **paragraphs** (`0x80` = `0x800` bytes = 2 KB) | `0x80` |
|
||
|
||
Set via a line like `#set heapsize=0x180` or `tsc /m app /sheapsize=0x180`. The
|
||
OS refuses to start an instance without `heapsize` free heap, and never shrinks
|
||
the heap below it.
|
||
|
||
### Multi-module and parameterised projects
|
||
|
||
Multi-file program (`triple.c`, `utils1.c`, `utils2.c`):
|
||
|
||
```
|
||
#system epoc img
|
||
#set epocinit=iplib
|
||
#model small jpi
|
||
|
||
#compile triple
|
||
#compile utils1
|
||
#compile utils2
|
||
|
||
#link triple
|
||
```
|
||
|
||
Assembler modules are allowed alongside C (`#compile afile` assembles
|
||
`afile.a`); assembler modules must follow the rules in the PLIB Reference.
|
||
|
||
A reusable generic project uses the `%main` macro (`unnamed.pr`):
|
||
|
||
```
|
||
#system epoc img
|
||
#set epocinit=iplib
|
||
#model small jpi
|
||
#compile %main
|
||
#link %main
|
||
```
|
||
|
||
invoked as `tsc /m unnamed.pr /smain=%1` (TopSpeed `/s` sets the macro from a
|
||
batch parameter). Conditional/parameterised builds are handled in the shipped
|
||
batch files (`cc.bat`, `make.bat`, `checkvid.bat`, `vid.bat`), which key
|
||
compilation off a `%jpivid%` env var (`v2` = full debug, `v0` = none) and pick
|
||
a per-app `.pr` if one exists, else `unnamed.pr`.
|
||
|
||
### Invoking the compiler: `tsc /m`
|
||
|
||
Build and link in one step:
|
||
|
||
```
|
||
tsc /m hello
|
||
```
|
||
|
||
"`/m` ... is that the project file is executed in 'make' mode, with files not
|
||
being recompiled or relinked needlessly." For source-level debugging add `/v2`:
|
||
|
||
```
|
||
tsc /m hello /v2
|
||
```
|
||
|
||
Other flags seen: `/fp<project>` selects the project file (e.g.
|
||
`tsc app.c /fpunnamed`); with no `/m` (and no `/l`) the project runs in
|
||
"compile" mode (compile only, always, no link). `%version`, `%priority`,
|
||
`%heapsize`, `%main` are passed as `/s<name>=<value>`.
|
||
|
||
> **`tsc` vs `tscx`.** `tsc` does not use expanded memory "and may cause
|
||
> problems, particularly when linking large applications." If linking fails,
|
||
> replace `tsc` with **`tscx`** (which uses expanded memory) in the batch files.
|
||
|
||
### Configuration files behind the build
|
||
|
||
The SIBO build config lives in two files (do **not** edit their pragmas):
|
||
|
||
- `tsprj.txt` — "compiled" with `tscfg` before use; the SDK version extends
|
||
Clarion's to add the `Epoc img` system type.
|
||
- `stdepoc.h` — "always the first include file in any source module."
|
||
|
||
Header/library search paths come from the redirection file **`ts.red`** (maps
|
||
`*.H`, `*.LIB`, `*.PR`, etc. to `.` then the `\sibosdk\...` directories).
|
||
|
||
---
|
||
|
||
## 4. Build outputs: images, libraries, device drivers
|
||
|
||
The image file is produced from an intermediary `.exe` by the Psion tool
|
||
**`emake.exe`** (automated by the project system). "Essentially, `.img` files
|
||
are to Epoc what `.exe` files are to MS-DOS." `emake` runs (per `tsprj.txt`):
|
||
|
||
```
|
||
emake -b %afl% -o%name% -s -v%version% -p%priority% -h%heapsize% -%epoctype% %name%.exe
|
||
```
|
||
|
||
The `%epoctype` variable selects the output kind:
|
||
|
||
| `%epoctype` | Output | Extension |
|
||
|-------------|--------|-----------|
|
||
| `t1` (default) | image file | `.img` |
|
||
| `t2` | logical device driver | `.ldd` |
|
||
| `t3` | physical device driver | `.pdd` |
|
||
| `t4` | dynamic library | `.dyl` |
|
||
|
||
### Images (`.img` / `.app`)
|
||
|
||
`.img` and `.app` are "strictly speaking ... no real difference"; both are
|
||
image files. By convention a `.app` has one to four embedded **add-files**:
|
||
|
||
- `.pic` — icon
|
||
- `.rsc` or `.rzc` (compressed) — resource file
|
||
- `.shd` — shell data (Series 3 only)
|
||
|
||
Add-files are embedded by `emake` when an **add-file list** (`.afl`, a text file
|
||
naming one to four files, e.g. `tele.afl`) with the matching base name exists at
|
||
build time. Renaming the result to `.app` is a convention (not automatic). A
|
||
`.dfl` file similarly embeds DYL files.
|
||
|
||
Inspect an image with `edump <name>` (shows version, code/data segment sizes,
|
||
stack, heap, priority, checksums, add-file offsets, DYL table). Re-edit an
|
||
existing image's add-files/priority/heap/version *without rebuilding* using
|
||
`eremake.exe` (e.g. to swap in a French resource file):
|
||
|
||
```
|
||
eremake -afrquery -o..\french\query.app query.app
|
||
```
|
||
|
||
### Libraries (`.lib`)
|
||
|
||
Build a static library with `#dolink` (see §3):
|
||
|
||
```
|
||
#system epoc img
|
||
#set epocinit=iplib
|
||
#model small jpi
|
||
#compile utils1
|
||
#compile utils2
|
||
#dolink utils.lib
|
||
```
|
||
|
||
`#dolink` (not `#link`) prevents startup/standard-library linking, and the
|
||
explicit `.lib` overrides the default `.img`. Consumers pull it in with
|
||
`#pragma link (utils.lib)`.
|
||
|
||
### Loadable device drivers (`.LDD` / `.PDD`)
|
||
|
||
At a high level, LDDs and PDDs are just image-type outputs of `emake`
|
||
(`%epoctype=t2` → `.ldd`, `t3` → `.pdd`). Detail from the *Hardware Development
|
||
Kit* (§9):
|
||
|
||
All SIBO hardware "is controlled by logical and physical device drivers."
|
||
Layering:
|
||
|
||
```
|
||
APPLICATION SOFTWARE
|
||
Psion C / PLIB call interface
|
||
LOGICAL DEVICE DRIVER (LDD)
|
||
PHYSICAL DEVICE DRIVER (PDD)
|
||
PHYSICAL HARDWARE
|
||
```
|
||
|
||
- A **PDD** "contains the code required for talking directly with the hardware"
|
||
— low-level, hardware-specific services.
|
||
- An **LDD** "performs the logical processing that transforms these low level
|
||
services into the high level services used by an application."
|
||
- The same LDD is often paired with a per-hardware PDD; an LDD may also talk to
|
||
hardware directly, making a separate PDD unnecessary.
|
||
|
||
> **Language note.** "Psion device drivers are written in 8086 assembler and
|
||
> follow a prescribed structure" (HDK §9). Device drivers are **not** ordinary C
|
||
> programs — the C SDK / PLIB is the *client* side (`p_loadldd()`, `p_open()`,
|
||
> `p_close()`, `p_iow()`). The `.ldd`/`.pdd` build path exists in the project
|
||
> system, but the driver *source* is assembler.
|
||
|
||
**Naming and channels.** An LDD name is three characters + colon (e.g. `TTY:`
|
||
serial). A PDD name is the owning LDD's three chars + `.` + three more + colon
|
||
(e.g. `TTY.UAR`, the ASIC5 UART driver). Open a channel via `p_open`:
|
||
|
||
```c
|
||
p_open(&pcb, "LED:", -1); /* LDD; -1 = ignore open mode */
|
||
p_open(&pcb, "TTY.UAR:", -1); /* a PDD directly (unusual) */
|
||
p_open(&pcb, "PAR:A", -1); /* channel qualifier 'A' */
|
||
```
|
||
|
||
Typically an application opens only the LDD, which opens its PDD during
|
||
initialisation. I/O requests reach the driver's **strategy vector**, which maps
|
||
to the PLIB `p_iow()` call. Installable drivers are loaded dynamically
|
||
(`DevLoadLDD` service; do not call `DevInstall` directly) without resetting the
|
||
machine, and can replace resident ROM drivers of the same name (the table is
|
||
searched from the most-recently-installed end). EPOC handles "a maximum of 32
|
||
device drivers on a Series3 machine and 48 on other machines."
|
||
|
||
**LDD structure (HDK §9).** Single code segment, no data segments (wrapped by
|
||
`CodeSeg`/`EndCodeSeg`); begins with a `LibEnt` structure (2-byte
|
||
`LDDSignature`, 8-byte zero-terminated name *without* trailing colon, 2-byte
|
||
vector count ≥ 8, then the vector table). The **eight mandatory LDD functions**,
|
||
in order:
|
||
|
||
1. `DevFuncInstall` — on installation
|
||
2. `DevFuncRemove` — on removal
|
||
3. `DevFuncHold` — temporarily disable
|
||
4. `DevFuncResume` — re-enable
|
||
5. `DevFuncReset` — application terminated without closing channel
|
||
6. `DevFuncUnits` — query number of supported units/channels
|
||
7. `DevFuncOpen` — open a channel
|
||
8. `DevFuncStrategy` — access functionality via the I/O system
|
||
|
||
All are called FAR by the OS and must return with a FAR return.
|
||
|
||
**PDD structure (HDK §9).** Also single code segment, no data segments; starts
|
||
with a `LibEnt` (`PDDSignature`). **Two mandatory functions** — `DevFuncInstallPDD`
|
||
and `DevFuncRemovePDD` — with typically two more (`DevFuncOpenPDD`,
|
||
`DevFuncStrategyPDD`). PDD internal variables must live in the driver's own code
|
||
segment so hardware can be freed after a client process terminates.
|
||
|
||
---
|
||
|
||
## 5. Floating-point emulator (relevant to any build)
|
||
|
||
Because SIBO has no 8087, floating point is emulated. Under EPOC the emulator is
|
||
an LDD, `SYS$8087.LDD` (in `\sibosdk\lib\`), loaded and freed automatically —
|
||
saving ~8K per program and allowing sharing between processes. The C startup
|
||
(`r_emul.a`) looks for the LDD in the program's directory, then via the `EMS`
|
||
environment variable (case-sensitive). A program that dies with **panic 80**
|
||
before starting has "almost certainly failed to locate `SYS$8087.LDD`"; fixes:
|
||
copy the LDD next to the program, set `EMS`, or remove the floating-point
|
||
dependency. Note "floating point instructions can easily be generated
|
||
unexpectedly ... if the recommended build configuration pragmas are 'improved'"
|
||
— another reason not to touch the pragmas.
|
||
|
||
---
|
||
|
||
## 6. Resources / resource compiler
|
||
|
||
The General manual covers resources only lightly, as **add-files**: a `.rsc`
|
||
(or compressed `.rzc`) resource file can be embedded into a `.app` via the
|
||
`.afl` add-file list (§4). Multi-lingual applications isolate all text in a
|
||
resource file so a translated `.rzc` can be swapped in with `eremake` without
|
||
recompiling.
|
||
|
||
> **Not in this manual.** The resource *compiler* itself and the resource
|
||
> source (`.rss`) syntax are **not** described in the General Programming Manual.
|
||
> The manual points to the *Resource Files* chapter of the *Additional System
|
||
> Information* manual (not provided here) for that detail. Do not assume resource
|
||
> compiler behaviour beyond the add-file mechanism described above.
|
||
|
||
---
|
||
|
||
## 7. Detecting the machine at runtime
|
||
|
||
Most SIBO machines are distinguished by screen size via `p_getlcd()` /
|
||
`p_geticda()` (General ch. 7). Values include:
|
||
|
||
| Constant | Value | Display / machine |
|
||
|----------|-------|-------------------|
|
||
| `E_LCD_640_400` | 0 | 640x400 — MC 400 |
|
||
| `E_LCD_640_200_SMALL` | 1 | 640x200 — MC 200 |
|
||
| `E_LCD_160_80` | 4 | 160x80 — HC |
|
||
| `E_LCD_240_80` | 5 | 240x80 — Series 3 |
|
||
| `E_LCD_480_160` | 11 | 480x160 — Series 3a / 3c |
|
||
| **`E_LCD_240_100`** | **12** | **240x100 — Workabout** |
|
||
| `E_LCD_240_160` | 14 | 240x160 — Siena |
|
||
|
||
> **Workabout / MX.** The manual lists the Workabout as the 240x100 machine
|
||
> (`E_LCD_240_100`, value 12). It does not list a separate MX entry; an MX with
|
||
> the same screen reports the same LCD type. Series 3a vs 3c (same screen size)
|
||
> are told apart with `p_returnexpansionportinfo()` on EPOC ≥ `0x390F` — the
|
||
> pattern generalises if you must disambiguate same-screen models. Do not
|
||
> hardcode screen dimensions; query the LCD type.
|
||
|
||
---
|
||
|
||
## Quick reference
|
||
|
||
```
|
||
# Minimal PLIB app
|
||
#system epoc img # -> .img output (Epoc image)
|
||
#set epocinit=iplib # PLIB startup, 4k stack (MUST precede #model)
|
||
#model small jpi # 64K code + 64K data, register calling convention
|
||
#compile myapp
|
||
#link myapp
|
||
|
||
# Build (make mode) tsc /m myapp
|
||
# Build with source debug tsc /m myapp /v2
|
||
# Large link needs XMS tscx /m myapp
|
||
# Override heap tsc /m myapp /sheapsize=0x180
|
||
# Inspect image edump myapp
|
||
# Re-embed add-files/version eremake ...
|
||
```
|
||
|
||
| Extension | What it is |
|
||
|-----------|-----------|
|
||
| `.pr` | TopSpeed project file |
|
||
| `.c` / `.a` | C source / assembler source |
|
||
| `.img` / `.app` | EPOC image / image with embedded add-files |
|
||
| `.lib` | static library (`#dolink`) |
|
||
| `.ldd` / `.pdd` | logical / physical device driver (assembler source) |
|
||
| `.dyl` | dynamic library |
|
||
| `.rsc` / `.rzc` | resource file / compressed resource file |
|
||
| `.pic`, `.shd`, `.afl` | icon, shell data, add-file list |
|
||
| `ts.red` | header/library redirection (search paths) |
|