docs(reference): 01-building-apps — SIBO/Workabout MX programming reference
This commit is contained in:
@@ -0,0 +1,573 @@
|
||||
# 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) |
|
||||
Reference in New Issue
Block a user