0% found this document useful (0 votes)
61 views375 pages

Panasonic_HHC_Programmers_Manual

This manual provides technical information for programming applications on the Panasonic/Quasar Hand-Held Computer (HHC) using the SNAP language, a variant of FORTH. It assumes familiarity with SNAP and optionally 6502 assembler, detailing the HHC architecture, software development, and various programming techniques. The document is a preliminary edition, with ongoing reviews and known omissions, and encourages feedback for improvements.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
61 views375 pages

Panasonic_HHC_Programmers_Manual

This manual provides technical information for programming applications on the Panasonic/Quasar Hand-Held Computer (HHC) using the SNAP language, a variant of FORTH. It assumes familiarity with SNAP and optionally 6502 assembler, detailing the HHC architecture, software development, and various programming techniques. The document is a preliminary edition, with ongoing reviews and known omissions, and encourages feedback for improvements.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 375

A PROGRAMMER' S MANUAL

FOR THE HAND-HELD COMPUTER

Friends Amis, Inc.


505 Beach St.
San Francisco, CA 94112
3 September 1981

(c) 1981 Friends Amis, Inc.


"...eimpr
PREFACE

WHAT THIS MANUAL IS FOR

This manual contains technical information which you must


know in order to write application programs for the
Panasonic/Quasar Hand-Held Computer (HHC), designed and
programmed by Friends Amis, Incorporated.

HHC software is written in SNAP, a variant of FORTH. For the


sake of efficiency, selected passages of code may be written in
6502 assembler.

This manual does not try to teach you to program in SNAP or


6502 assembler. It assumes you are familiar with these languages
(although 6502 assembler is optional), and presents the
information you need to work with the SNAP dialect of FORTH, and
with the 6502 assembler embedded in SNAP.

CURRENT STATUS OF THE MANUAL

The HHC software was recently completed at the time of this


preliminary edition. Reviews of the information contained in
this manual are still underway, and there is known missing
information. Some information will be further detailed in a
later edition. Reports of errors or omissions would be greatly
appreciated.
You need additional documentation to make effective use of
development tool software supplied by Friends Amis.

If in doubt about the meaning or accuracy of any information


in this manual, contact Friends Amis for more information.

(c) 1981 Friends Amis, Inc. 3 September 81


NNW

NIIIIIP.
TABLE OF CONTENTS

INTRODUCTION

1-1 WHAT THIS DOCUMENT IS FOR


1-1 HOW THIS DOCUMENT IS ORGANIZED
1-2 WHAT THIS DOCUMENT ASSUMES
1-3 HHC ARCHITECTURE
1-3 The Hardware
1-6 The Software
1-9 The Function Of Interrupts
1-10 HOW SNAP DIFFERS FROM FORTH
1-10 SNAP Is a Cross-compiled Language
1-11 SNAP Code Goes In ROM
1-11 SNAP Object Code Does Not Use CFA's
1-11 SNAP Source Code Is Not Stored In Screens
1-13 HOW HHC APPLICATION PROGRAMS ARE DEVELOPED
1-13 The Development System
1-13 The Cross-Compiler and Down-Loader
1-14 Summary
1-17 THE GLOSSARIES
1-17 How the Glossaries Are Organized
1-17 How Vocabularies Are Identified In the Glossaries
1-17 Glossary Notation
1-18 (Glossary Format)
1-20 (Text Format)

GENERAL TECHNICAL INFORMATION

2-1 MEMORY MAP


2-3 DATA REPRESENTATION
2-5 SNAP CODE STRUCTURE ON THE HHC
2-5 What a Tag Is
2-6 Short and Long Tags
2-7 The Structure Of Tag Tables
2-8 The Tag Table Vector
2-8 How the Interpreter Uses the Tag Tables
2-10 Initializing the Tag Table Vector: The Header
2-14 The Mother Word and the Tag Table Vector Initializatin Word
2-15 A Tag Table Over 256 Entries Long
2-16 A Program that Occupies Multiple Capsules
2-17 Note On Data Capsules
2-17 Note On Slow ROM
2-17 Assigning Long and Short Tags To Words
2-13 Note On Tag Table Overflow
2-19 Note On Colon Definitions: :C
2-19 Note On Forward References
2-20 CONSTANTS
2-20 Symbolic Constants
2-20 Colon Definitions As Constants
2-22 ALLOCATING RAM, PART I: THE TEMPORARY STORAGE AREA (TSA)
2-22 How To Use a TSA
2-22 An Example
2-22 Types Of TSA Variables
2-23 Notes On Using the TSA
2-24 Releasing TSA's
2-24 About the Size of the Temporary Stack

(c) 1981 Friends Amis, Inc. 1 3 September 81


TABLE OF CONTENTS

2-26 ALLOCATING RAM, PART II: DYNAMIC ALLOCATION


2-26 Is There Enough Room?
2-26 How Much Room Is There, Anyway?
2-28 ALLOCATING SPACE IN Ron
2-29 A CAUTION REGARDING STACKS
2-30 RESTARTING A PROGRAM
2-30 The CLEAR Key
2-30 Changing the Restart Word
2-31 Software Simulation of the CLEAR Key
2-31 Ending a Program
2-32 LATCH BYTE

THE KEYBOARD

3-2 HARDWARE ARCHITECTURE


3-2 Hidden and Immediate Keys
3-2 Special Keys On the Keyboard
3-4 Keyboard Codes
3-5 Operation of the LOCK Key
3-6 PROGRAM-DEFINED KEYBOARD TRANSLATION TABLES
3-6 Coding a Keyboard Translation Table
3-6 Adopting a New Keyboard Translation Table
3-9 EXPECT: KEYBOARD INPUT
3-11 EXPECT Modes
3-12 Example 1
3-12 A Variation: Getting the Address of EOLWD
3-12 Example 2: Editing Text
3-13 Example 3: Changing the End-of-Line Character
3-14 KEY AND RELATED WORDS
3-14 Note on Battery-Conserving Code
3-16 SIMULATING KEYBOARD INPUT FROM A PROGRAM
3-16 Structure Of the Keyboard Buffer
3-17 The Pushkey Buffer
3-17 Operations On the Buffers
3-18 Function Keys
3-19 ("Typing" a Function Key)

THE LCD

4-2 I/O WORDS


4-2 EMIT
4-3 "Random Access" Output To the LCD
4-3 Graphics Output
4-5 Program-defined Blips
4-6 ALTERNATE CHARACTER SETS
4-6 Defining a Character Translation Table
4-7 Informing the HHC of the Table's Address
4-8 Restoring the Standard Table
4-8 Defining a Floating Accent Translation Table
4-9 Informing the HHC Of the Accent Table's Address
4-9 A Note on Alternate Character Sets and the Printer
4-9 Defining an Alternate Cursor Pattern
4-11 ROTATION MODE
4-12 THE STOP/SPEED KEY
4-13 SLAVING PERIPHERALS TO THE LCD

(c) 1981 Friends Amis, Inc. 2 3 September 81


TABLE OF CONTENTS

4-13 FLAME-ON
4-13 Vectored I/O; (EMIT)
4-15 BLIPS
4-16 BEEPS AND SQUEAKS

THE VIRTUAL FILE SYSTEM

5-1 VIRTUAL FILE CONCEPTS


5-2 FILE TYPES
5-3 VIRTUAL FILE OPERATIONS
5-3 OPEN: Opening an Existing File
5-3 MAKE: Creating and Opening a New File
5-3 READ: Reading a Text File
5-4 WRITE: Replacing an Existing Record In a Text File
5-4 INSERT: Inserting a New Record In a Text File
5-5 REC-CNT and INSERT: Appending a New Record To a Text File
5-5 DELETE: Deleting a Record From a Text File
5-6 ?FILE and REVISE: Allocating Space In a Non-Text File
5-6 More REVISE: Adding and Deleting Space In a Non-Text File
5-7 CFILE and DELETE-FILE: Deleting a File
5-7 Renaming a File
5-8 GET-TYPE: Testing and Setting File Type
5-9 LOOKUP: Look Up N'th File
5-10 The Virtual File Editor
5-11 THE VIRTUAL FILE SPACE
5-11 Structure of Virtual File Space
5-12 (Format of a Text File)
5-13 (Format of a Non-Text File)

PERIPHERAL I/O AND TIMER SERVICES

6-1 EVENT CONTROL BLOCKS


6-1 Introducing Asynchronous Processing
6-1 The Event Control Block: Keeping Processes In Step
6-2 Other Uses For ECBs
6-3 More About ECBs
6-4 Using ECBs
6-5 INTRODUCTION TO PERIPHERAL I/O
6-5 Software: Architecture
6-5 Software: In General
6-5 (ECB's and Asynchronous I/O)
6-6 (Steps In Doing I/O)
6-7 PERIPHERAL I/O OPERATIONS
6-7 The ATTACH Operation
6-7 RIP: Request Input
6-8 ROP: Request Output
6-8 Relation of RIP and ROP to KEY and EMIT
6-9 Opening and Closing Devices
6-9 (ROPEN and RCLOSE)
6-10 (Functions of ROPEN and RCLOSE)
6-10 RCTL: Control and Status Operations
6-11 A Note on Multiple Waits
6-12 The System Device Table (SDT)
6-13 PARAMETER VALUES
6-13 Hardware Device Codes

(c) 1981 Friends Amis, Inc. 3 3 September 81


TABLE OF CONTENTS

6-13 Logical Unit Numbers


6-13 ECE Return Codes
6-15 OUTLINE OF PERIPHERAL I/O WORDS
6-16 CONTROL CHARACTERS
6-16 ASCII Control Characters
6-16 Escape Control Sequences
6-18 The Keyboard
6-18 The LCD
6-18 (Technical Information)
6-19 The Micro Printer
6-19 (General Information)
6-19 (Technical Information)
6-20 Video Interface
6-21 (General Information)
6-21 (Technical Information)
6-21 Modem
6-21 (General Information)
6-21 (Technical Information)
6-23 (Device Initialization)
6-23 Format Of the Modem File
6-23 (Initialization Call)
6-24 (Set XON/XOFF Status)
6-25 (Get Device Status)
6-25 Serial Interface Adaptor (RS-232 Interface)
6-25 (General Information)
6-26 (Technical Information)
6-27 (Device Initialization)
6-28 (Initialization)
6-29 (POKE Call)
6-29 (PEEK Call)
6-30 (Useful PCB_ Offsets With PEEK and POKE)
6-31 (Get Status Call)
6-33 TIMER SERVICES
6-33 The Real-time Clock
6-33 The Real-time Clock
6-33 Using Timer Facilities
6-33 The Auto-Off Facility

FLOATING POINT OPERATIONS

7-1 INTERNAL STORAGE


7-2 ERROR HANDLING AND SPECIAL CASES
7-3 Defining New Special Case Types
7-3 Some Missing Operations
7-4 Defining Floating Point Constants
7-6 FLOATING POINT OPERATIONS WITHOUT SPECIAL CASE CHECKING
7-6 Calling the Non-Checking Version of F+
7-6 Calling the Non-Checking Versions of F* and F/
7-8 GLOSSARY

SAMPLE PROGRAMS

8-1 SAMPLE 1: ORDER ENTRY PROGRAM


8-1 Use (Technical)
8-1 (Inventory File)

1981 Friends Amis, Inc. 4 3 September 81


TABLE OF CONTENTS

8-1 (Format Of the Inventory File)


8-2 (The Order File)
8-3 Use (Customer Interface)
8-4 (Print Order Function)
8-5 (Print Summary Function)
8-5 Program Structure
8-7 (The Header)
8-7 (Modifying the Header)
8-8 (Utilities)
8-8 (Data and Constants)
8-9 (I/O Words)
8-9 (Order Entry Function)
8-10 (Print Order Function)
8-10 (Function Menu)
8-11 (File Initialization Function)
8-11 (Main Program Menu)
8-11 (Modifying the Function Menu)
8-13 SAMPLE 2: SKETCH PROGRAM
8-13 Use
8-13 (The Editing Functions)
8-14 (Safety Features)
8-14 (Edit Mode)
8-15 Program Design
8-15 (Data)
8-16 (The Program)
8-18 SAMPLE 3: INFLATION CALCULATOR
8-18 Use
8-18 Program Design

THE SNAP ASSEMBLER

9-2 OVERVIEW
9-4 THE ASSEMBLY PROCESS
9-4 The Assembler Does Not Work In Compile Mode
9-5 Getting In and Out Of the Assembler Vocabulary
9-6 OPCODES
9-8 OPERANDS
9-8 Addressing Modes
9-10 FLOW OF CONTROL
9-10 IF . . . ELSE . . . ENDIF
9-10 The Condition Specifier
9-10 The UNTIL Loop
9-11 The WHILE Loop
9-11 The AGAIN Loop
9-12 HHC CALLING CONVENTIONS
9-12 SETUP
9-12 Low Level Procedures
9-12 Jumping To CODE Words
9-13 Return to Caller From a CODE Word
9-13 Leaving a CODE Word
9-13 Calling a SNAP Word From a CODE Word
9-14 (Assembling Low Level Procedures Outside SNAP)
9-15 HHC CODING CONVENTIONS
9-15 Using the Parameter Stack
9-16 Using the Return Stack

(c) 1981 Friends Amis, 5 3 SepteMber-81


TABLE OF CONTENTS

9-16 Temporary Storage


9-16 The SNAP Instruction Pointer
9-16 Hardware Register Usage
9-18 SECURITY
9-19 EXAMPLES
9-19 Example 1: SETUP
9-19 Example 2: U*
9-21 Example 3: SHIFT
GLOSSARIES

10-1 HHC WORDS


10-1 Beginning with 1 !' through 1 @'
10-20 A
10-24 B
10-26 C
10-33 D
10-38 E
10-45 F
1U-52 G
10-54 H
10-55 I
10-58 J
10-59 K
10-61 L
10-67 M
10-70 N
10-72 0
10-73 P
10-76 R
10-82 S
10-94 T
10-99 U
10-101 V
10-102 W
10-103 X
10-104 Y
10-105 Z
10-106 Beginning With Characters After 'Z'
10-108 OBJECT-TIME WORDS
10-112 ASSEMBLER GLOSSARY
10-112 "NEXT" Words
10-113 "RTS" Words
10-115 Other Words

APPENDIX A: THE HHC CHARACTER SET

INDEX

(c) 1981 Friends Amis, Inc. 6 3 September 81


INTRODUCTION

WHAT THIS DOCUMENT IS FOR

This document describes the HHC computer from the point of


view of a programmer writing applications to be distributed in
capsule ROMs. It also contains information that is useful to
developers of lower level software (e.g., device drivers).

HOW THIS DOCUMENT IS ORGANIZED

1. This introduction describes the HHC in general terms,


outlining the major parts of the system and explaining how
they relate to each other.
2. "General Technical Information" discusses various aspects
of programming for the HHC, such as memory management,
internal program structure, and stack space.
3. "I/O and Timer Services" is an extension of "General
Technical Information" concerned only with these two
closely related areas.
4. "Floating Point Operations" describes the floating point
arithmetic package implemented on the HHC.
5. "Developing Programs For the EEC" discusses the mechanics
of developing a program: how to edit, compile and test a
program on the development system.

6. "The SNAP Assembler" discusses the assembler provided with


the SNAP system, which permits you to write critical parts
of HHC programs in machine language.

7. "Glossaries" contains glossaries of all the SNAP words


involved in the HHC system.)

(c) 1981 Friends Amis, Inc. 1-1 3 September 81


INTRODUCTION

WHAT THIS DOCUMENT ASSUMES

This document assumes that you nave a wor<ing Knowledge 3f


some dialect of FORTH, and have access to Friends-Amis for
answers to technical questions raised by your work.
Prior to or concurrently with reading this document, you
should develop a working familiarity with the HHC from a user's
point of view.

(c) 1981 Friends Amis, Inc. 1-2 3 September 81


INTRODUCTION

HHC ARCHITECTURE

The HHC's needs for compactness and low power consumption


have resulted in a very unusual achitecture in both hardware and
software. It is important for you to understand the major
features of this architecture if you are to program the HHC
effectively.

The Hardware

The HHC is a self-contained microcomputer system built around


a 1 mHz 6502 microprocessor. It utilizes a full 64K address
space. The structure of the address space is complex; various
parts of it are occupied by RAM, ROM, plug-in program capsules,
memory-mapped I/O devices, etc. A very rough map of the address
space is shown in Figure 1-1, and a detailed map is shown in
Chapter Two.
Compared to other microcomputers, the HHC has much ROM and
little RAM. This is due to cost and power constraints, and the
need to support a full operating system without oeripheral
storage.

The HHC's intrinsic* I/O devices are a one-line LCD display,


which can rotate from right to left like a light sign; a set of
LCD INDICATORS which are displayed as motionless pointers below
the text on the LCD display; and a variable-pitch SQUEAKER.

- System components that are integral parts of the HHC, or may


be treated as though they were when they are attached, are
often called "intrinsic." The HHC has "intrinsic RAM,"
"intrinsic ROM," and several "intrinsic applications," which
are application programs stored in intrinsic ROM. Things that
are not intrinsic are purchased as accessories and plugged
in. For example, additional programs may be purchased in ROM
capsules and plugged in; additional RAM may also be plugged
in.

(c) 1981 Friends Amis, Inc. 1-3 3 September 81


INTRODUCTION

Intrinsic input consists of a typewriter-like keyboard with


several special purpose keys such as "on," "off," "shift,"
"function," and "helb."

Additional devices `peripherals', may be attached througn a


bus socket on the side of the HHC. Such peripherals are
controlled through a standard set of I/O words.

(c) 1981 Friends Amiss, Inc. 1-4 3 September 81


INTRODUCTION

0000-07FF Intrinsic (built-in) RAM. Used for variables and


scratch space by operating system; also for virtual
file space.
0800-1FFF RAM capsule space. Part or all of this space may be
filled with additional RAM that is plugged in to the
HHC in capsule form. RAM capsules provide more space
for variables and virtual files.
2000-3FFF Device control ROMs. A device control ROM is
physically part of the device it controls, and so is
connected to the HHC when the device is plugged in.
The proper device control ROM for a given I/O
operation is selected by bank switching. Up to 16
different ROMs may be bank switched into this space.

4000-7FFF Capsule and I/O bank space. ROM capsules are read from
this space. Contents of this space is controlled by
bank switching; the space may be filled by any two of
the 3 capsule sockets on the back of the HHC, and/or
sockets in a ROM expander. Bank switching also permits
access to the HHC's memory-mapped I/O hardware.

8000-BFFF Space for RAM expander(s).

C000-FFFF Intrinsic ROM. Contains the nucleus; interrupt


processor; file manager; and intrinsic applications
("memory bank" editor, pocket secretary, etc).

FIGURE 1-1

MEMORY MAP

(c) 1981 Friends Amis, Inc. 1-5 3 September 81


INTRODUCTION

The Software

All the HHC's software is built around an intec)rezi7e


language called SNAP. SNAP is a highly tailored variant of FORTH.
Much of the nucleus is written in it; so is virtually all of the
applications code.

Major components of the HHC software are listed below. Their


relationships are shown graphically in Figure 1-2.

The SNAP INTERPRETER is written in low-level code (i.e., in


machine code). It interprets the parts of the software that are
written in SNAP.

The PERIPHERAL INTERFACE connects programs to I/O devices. It


communicates with programs through a standardized set of SNAP
words, and communicates with I/O devices through standardized
calls to device-specific I/O driver routines. Its functions
include attaching peripherals to programs, logically binding
peripherals to one another, and translating I/O requests between
the programs' device-independent formats and the I/O devices'
device-specific formats. Closely associated with the peripheral
interface are the INTERRUPT HANDLER and the TIMER HANDLER.

The INTRINSIC I/O DRIVERS communicate between the peripheral


interface and the intrinsic I/O devices. They are sometimes
treated as parts of the peripheral interface itself.
The PRIMARY MENU DRIVER is the user's primary interface with
the operating system. IL. gains control when the CLEAR key is
pressed twice. It cycles through the primary menu and allow the
user to choose one of the menu items: intrinsic applications,
program capsules, etc.

The FILE SYSTEM enables programs to do "I/O" to "virtual


files" stored in RAM, or to real files if an appropriate
peripheral is available.

The items listed above constitute the NUCLEUS, that is, the
intrinsic portion of the operating system.

The INTRINSIC APPLICATIONS are application programs that are


built into the HHC. They are the CALCULATOR, the POCKET
SECRETARY, and the FILE EDITOR.

The CAPSULE PROGRAMS are applications kept in plug-in ROM


capsules. When a ROM capsule is plugged into the HHC, it may be
bank-switched into the HHC's address space by the nucleus.

PERIPHERAL I/O DRIVERS communicate between the peripheral


interface and peripheral devices. They perform the same function
as the intrinsic I/O drivers, but for plug-in peripherals instead
of intrinsic devices. They reside in ROM that is physically 'cart
of each peripheral device. The nucleus bank-switches each

(c) 1981 Friends Amis, Inc. 1-6 3 September 81


INTRODUCTION

device's I/O driver into the HHC's address space when I/O to that
device is requested.

(c) 1981 Friends Ainis, Inc. 1-7 3 September 81


INTRODUCTION

:ntrinsic Applications Aoolications


j in RCM capsLiles

A A A A I A
i 1 i I I
i 1 1 I I
1 I i

V V
I I I 'Peripheral
Peripheral I/O I/O inter-
drivers 'face; inter- I I File
I I I Irupt handler; system Menu
timer driver

1
Intrinsic1<---- < WW1 OEM MI=

I/0 drvrsl

SNAP interoreter

FIGURE 1-2

HHC SOFTWARE ARCHITECTURE

Arrows indicate important flows of control (calling module to


called module). The interrupt handler and SNAP interpreter
interact closely with all parts of the system.

(c) 1981 Friends Amis, Inc. 1-8 3 September 81


INTRODUCTION

The Function Of Interrupts

The HHC uses interrupts very extensively. Interrupts can come


from two sources: peripherals and the HHC's clock or timers.
The HHC actually turns itself on in response to any event
such as a keystroke, processes the event, and then turns itself
off again to conserve power. This is an important feature of the
HHC's design, since the HHC is powered by 5 AA batteries (IEC
designation R6 or equiv.), and these batteries will run the 6502
for only a few hours.
Any event which requires the CPU's attention, such as a
keystroke, a timer expiration, or a message from a peripheral
device, generates an interrupt. This causes the interrupt
hardware to turn the CPU on.
Note that the HHC's ON and OFF switches are not electrical
controls in the conventional sense; they are ordinary keyboard
keys, which the HHC is programmed to respond to by turning itself
"on" and "off."
When the HHC is "off," the timer and RAM still receive power.
This enables the HHC to "remember" the time of day, appointment
calendar, etc., even after the power is turned off. Since the
timer and RAM all use CMOS technology, the power consumption is
very low.

(c) 1981 Friends Amis, Inc. 1-9 3 September 81


INTRODUCTION

HOW SNAP DIFFERS FROM FORTH

SNAP Is a Cross-compiled Language

Unlike standard FORTH systems, the SNAP interpreter on the


HHC has no outer interpreter; thus it cannot interpret a SNAP
word entered through the keyboard, nor can it define a new word.
Furthermore, SNAP words have no headers; this makes it impossible
to use the name of a word to locate its definition at run time.

Most conventional compiled languages make a sharp distinction


between "compile time" and "run time." One of the major features
of FORTH is that it blurs this distinction; you can use "run
time" facilities at compile time, and vice versa. Because of the
HHC's lack of an outer interpreter, this sharp compile/run time
distinction does apply to SNAP.

The compiler that generates SNAP code for use in capsules is


a CROSS-COMPILER; the system it compiles for (the HHC running
SNAP) is different from the system it is executed on (the Apple
running FORTH). The system it compiles for is called the TARGET
system; the system it is executed on is called the HOST system.

Many operations in the cross-compiler can be performed in two


ways: for the target, or for the host. For example, when you
define a word, you can define it into the host's dictionary or
the target's dictionary. If you define it into the host's
dictionary, it can used outside of target colon definitions, and
executed at compile time. If You define it into the target's
dictionary, it can be used only inside target colon definitions,
and can be executed only at run time (on the HHC).

The host/target distinction is sometimes subtle and


confusing. Luckily, you need not master it in order to write
programs in SNAP. Most of the time you can trust the cross-
compiler to do the right thing. For example, if you write a
"conventional" colon definition, the cross-compiler will compile
a word into the target dictionary; this is usually what you want
(indeed, you may never need to compile a word into the host
dictionary until you become quite advanced). But you do need a
general understanding of the distinction if the HHC's cross-
compiling rituals are to make any sense to you, and you will have
to master it if you want to utilize the full power of SNAP.

In the beginning, you will spend most of your time thinking


about word definitions that compile into the target vocabulary.
You will use the compile-time vocabulary only for controlling the
cross-compiler and manipulating files; you can safely think of it
as a command language rather than a programming language. After
you have become comfortable with the quirks of SNAP, you can
address the further quirks of the cross-compiler with some
confidence.

(c) 1981 Friends Amis, Inc. 1-10 3 September 81


INTRODUCTION

A good rule of thumb to follow is that anything outside a


colon definition, and any word forced out of immediate mode witn
words like [COMPILE], should be approached with caution. Things
that are inside a colon definition and are fully compiled to SNAP
code will generally perform at run time the way you (as a FORTH
programmer) expect.

SNAP Code Goes In ROM

A second major difference between SNAP and FORTH is that SNAP


code is executed from ROM. This means that you cannot compile
colon definitions and variable definitions into the same
dictionary, as you would normally do in FORTH.
SNAP uses a different set of defining words for variables and
constants, and has a different set of rules for using them. This
is discussed more fully in the chapter on "General Technical
Information."

SNAP Object Code Does Not Use CFA's

A third major difference between SNAP and FORTH is in SNAP's


format for compiled code. Most FORTHs compile a colon definition
into a series of two-b te code field addresses, which the
interpreter calls 1„1,44HeVsubroutines. SNAP compiles a colon
definition into a series of TAGS, which are used to fetch
execution addresses from a table at run time. The most commonly
used words are represented by one-byte tags, yielding more
compact code. The compiled-code format of SNAP is described fully
in "General Technical Information."

SNAP Source Code Is Not Stored In Screens

A major difference between the SNAP and FORTH programming


environments is that the SNAP development system stores source
code and other data in files, rather than screens.

The number of files that may be stored on a disk is


effectively unlimited. Files are identified by mnemonic names,
rather than by numbers.

The system makes each file only as long as necessary to hold


the data contained in it. The length of a file is unlimited, and
may change dynamically.

SNAP source files use a variable length line. This means that
you can increase the legibility of your programs by using as much
white space as you want without suffering any oenaity from wasted
storage. The system improves storage efficiency further by

(c) 1981 Friends Naas, Inc. 1-11 3 September 81


INTRODUCTION

compressing multiple blanks embedded in lines, and re-expanding


them automatically when a file is edited or listed. The maximum
length of a source file line ;imposed by the text editor, not the
file format itself) is Si characters.

(c) 1981 Friends Ainis, Inc. 1-12 3 September 81


INTRODUCTION

HOW HHC APPLICATION PROGRAMS ARE DEVELOPED

The Development System

The SNAP processor on the HHC has no outer interpreter. This


means that it can only execute compiled code; it cannot accept a
SNAP word from the keyboard and interpret it, nor can it compile
a program.
Because of these lacks, HHC programs are developed and tested
on a separate development system. This system is currently
implemented on the Apple II.
The development system's software is based on a conventional
FORTH interpreter. An HHC EMULATOR runs under FORTH as an
application program. When you are developing an HHC program in
SNAP, you generally use the FORTH environment for program editing
and housekeeping. You use the HHC environment for testing.
The emulator is essentially the same as the SNAP system that
runs on the HHC itself. It has its own inner interpreter, based
on SNAP code's tag structure rather than FORTH code's address
structure. Since both the HHC and the Apple use a 6302 processor,
most parts of the emulator run just the same way on the Apple as
on the HHC.
Unlike SNAP on the HHC, the emulator has an outer interpreter
that can interpret SNAP code and compile colon definitions. This
makes it possible to use a fairly traditional FORTH approach to
programming in SNAP, despite the fact that SNAP runs on the HHC
17 71..Tqa classical compiled language, with the compiler out of the
picture at run time.

The Cross-Compiler and Down-Loader

The CROSS-COMPILER and DOWN-LOADER are used for final


testing, after a program has been largely debugged on the
emulator. By putting a program on the HHC itself, they eliminate
the few hardware and software differences that could prevent a
Program from being tested completely with the emulator, or cause
a program to execute correctly on the emulator but not on the
HHC.
The cross-compiler (also known as METASNAP) compiles SNAP
source code into SNAP object code, which it stores on disk.
The down-loader transmits SNAP object code to a SIM (a 6302-
based single-board microcomputer). The SIM writes the SNAP object
code into a TEST CAPSULE containing battery powered RAM. The test
capsule is plugged into the HHC as though it were a ROM capsule,
so that the program may be executed.

(c) 1981 Friends Amis, Inc. 1-13 3 September 81


INTRODUCTION

The HHC's CPU chip is replaced by a plug cabled to the SIM.


The SIM executes the program as though it were the HHC's CPU, but
gives the user some machine-level debugging facilities that are
transparent to the HHC: machine level trace, breakpoint facility,
register inspection, etc.

Summary

To recap, here is how an HHC program is written and tested,


step by step:

1. The program is entered and edited using the development


system's text editor.
2. The program is compiled and tested under the emulator. When
errors are found, they are corrected with the text editor.

3. When the program runs correctly on the development system,


it is cross-compiled into object code for the HHC.
4. The cross-compiled SNAP program is copied to a test capsule
with the down-loader and SIM.

5. The test capsule is plugged into the HHC; the SIM is


plugged into the HHC's CPU socket; the program undergoes
final testing.

"Programming for the HHC" explains in detail how to use the


development system for editing programs and debugging with the
emulator. Some other parts of the development system -- tne
down-loader and SIM, for example -- are beyond the scope of
this document.

(c) 1981 Friends Amis, Inc. 1-14 3 September 81


INTRODUCTION

emulated
P,M.P.s* &
ROM capsules SNAP
0 emulator
File editor (displaces
x & utilties FORTH)
x (run under FORTH)

source
files, etc.
file :
0 FORTH interpreter
system:
X

Figure 1-3
Overall Structure
of the Development System

Programmable Memory Peripherals.

(c) 1981 Friends Amis, Inc. 1-15 3 September 81


INTRODUCTION

source files
0 File editor
x
x •

ANNOMINIP.111111.M.M

emulated
P.M.P.s* & Copying utility
ROM capsules
0

x
x

"LOAD"

V •

Use
Memo pad "SNAP capsule"
editor to debug

Figure 1-4
Using the Development System
to Test a Program

Solid arrows indicate flow of data.

Dashed arrows indicate flow of control.

Programmable Memory Peripherals.

(c) 1981 Friends Amis, Inc. 1-16 3 September 81


INTRODUCTION

THE GLOSSARIES

How the Glossaries Are Organized

The "Glossaries" chapter is divided into several sections


according to the functions of the words. These sections are:

1. HHC words. Most of the words that you can use in a SNAP
program are described here. This includes both executable
words (e.g., OVER, DUP, DROP) and compile-time words (e.g.,
';', and 1 ( 1 ).
2. Emulator control words. These are words you can use to
control the operation of the emulator, but would NOT use in a
program.

3. FORTH system words. These are words you can use in the
development system's FORTH environment, but cannot use in
the emulator or in a SNAP program.
4. Object time words. These are words in the HHC's vocabulary
that are generated by the compiler, but are never written
in source programs. They implement program control
structures and literal constants.

In addition, "mini-glossaries" containing subsets of the


glossaries above are distributed tnroughout the other sections of
the book, in order to be near the parts of the text that describe
them.

How Vocabularies Are Identified In the Glossaries

Because of the ways "parallel worlds" nature of the HHC and


the development system, the question "which vocabulary is a word
in?" is not of great importance in SNAP. It is more useful to
ask, "Which environment is a word in?" and this is the question
that the glossaries answer.
The glossaries expand the concept of "environment" to include
the use of words in the cross-compiler.

Glossary Notation

SNAP words are always capitalized. Where there may be


confusion about where a word ends and punctuation begins, the
word is enclosed in apostrophes. Example: 'REFRESH.' is a word
ending with a period.

(c) 1981 Friends Amis, Inc. 1-17 3 September 81


INTRODUCTION

(Glossary Format)

Here is an example of a glossary entry with a description of


each part:
t? ..,...--

OVER ( X Y --- X Y X ) , note


Copies the second word on the stack to the top of t,e
stack.

OVER
The word being described.

( X Y--- X Y X)
Shows stack input to the left of the hyphens, and
stack output to the right. This example shows that the
word expects two items on the stack, and leaves three.

Conventions for naming the stack items are intuitive


rather than formal. Descriptive names, such as "LEN"
for a length, are used where appropriate. Where no
descriptive name suggests itself, the following
conventions are used:
A for an address.
B for a boolean (true/false).
C for a character.
..D suffix indicating a double-length (32-bit)
operand, e.g., ND for a double-lengtn integer.

FL for a byte of bit flags.

FP for a floating point number.


L for a length or byte count.

N an integer.
U an unsigned integer.

X,Y,Z 16-bit quantities of unspecified type.

[] enclose an operand that may or may not be


present. Example: '( X --- X [X] )'. X may or may
not be duplicated.
The sequence I( . . --- [X] B ) ' customarily
means that X is present if 3 is TRUE, and absent

(c) 1981 Friends Amis, Inc. 1-18 3 September 81


INTRODUCTION

if B is FALSE.

If the same name appears on both sides of the hvohens,


it represents sam e value value is not
changed).
If a name appears on the left side of the hyphens, and
appears on the right side with a prime after it, it
represents a corresponding (but changed) value.
Example:

( A L --- A L' )

If two or more values of the same type appear in the


same specification, they are distinguished by numbers.
Example:
( N1 N2 --- N3 )

note
Notes explain how this word fits into the HHC system.

none
If an entry in the HHC glossary has no note, the
implication is that the word is a colon definition in
the target dictionary (i.e., on the HHC), and works
identically in the HHC and the emulator.
In other glossaries, "no note" has no particular
implication. (Observe that it would be absurd for "no
note" to have the same implication in the FORTH
glossary, for example, as in the HHC glossary! A word
in the FORTH glossary is, ipso facto, not in the
target dictionary.)

S
The word is a symbolic constant. It may return the
address of some fixed data item in RAM or ROM. More
commonly it returns a scalar constant, such as the
number of dot columns in the LCD, or the binary value
that represents a particular ASCII character.

Dn
The word is a data item. It returns the address of
data at a fixed location in RAM. "n" is the length of
the data in bytes.

C
Control word. This word is used in a target colon
definition and compiles to target code, but does NOT
compile one-for-one to a corresponding SNAP tag. An
example is the word LITERAL, which takes one word
from the stack at compile time and compiles to a CLIT
or LIT followed by a one- or two-byte constant, the
constant's value being the value taken from the

(c) 1981 Friends Amis, Inc. 1-19 3 September 81


INTRODUCTION

stack

Immediate word; executes at compile time ,vhe tner used


inside a target colon definition or elsewhere.
Customarily used only inside a target colon
definition.

L
Label. Returns an address on the stack AT COMPILE
TIME. This address is most often the entry point to a
subroutine that is called from low-level words, using
the standard 6302 calling linkage rather than the
SNAP (high-level) linkage.

Labels are used as the operands of instructions and


pseudo-instructions in the SNAP assembler.
COMP
Cross-compiler word; not for use inside target colon
definitions.

NOTE
There is something else to note about this word. See
the following description.

On the second and following lines of the glossary entry is a


description of the word.

If a paragraph of the description is of little interest to


the applications programmer, it ls enclosed in parentheses,
and it is placed at the end of the description if that is
logically possible.

(Text Format)

In some parts of the text, a less formal kind of notation is


used to describe words. The object is to give a description of
the linkage in one indented line, without disturbing the flow of
the text. Here is an example of this kind of notation:

x y OVER x y z
OVER copies the second word on the stack to
the top of the stack.

(c) 1981 Friends Amis, Inc. 1-20 3 September 81


GENERAL TECHNICAL INFORMATION

MEMORY MAP

The CPU can address 64K of memory. The address space is


partitioned among several different kinds of memory. The major
kinds are described in the following memory map.

0000-0210 (The end is approximate.) Nucleus variable space.

The parameter stack space is in this area; it is about


OA8E bytes long, and ends at OFEH (OFFH is used for
housekeeping). The parameter stack grows down from the
top of the parameter stack space. I/O device routines
allocate their storage up from the bottom.

The return stack space starts at 100H and is about 40H


bytes long. The return stack grows down from the top;
the loop stack grows up from the bottom. Note that
this is a deviation from f-j..42422Th in which loop
values are stored on the return stack itself.
J^k-IAL/
0210-07FF (The beginning is approximate.) Intrinsic RAM. Used to
hold virtual files (see the section on I/O) and the
temporary stack (see the discussion of temporary
storage areas). Virtual files grow up from the bottom
of this space. The temporary stack grows down from the
top.

0800-1FFF Space for plug-in RAM capsules. Up to 3 capsules may


plugged in, increasing the size of intrinsic RAM to
approximately 8K (address 0210-1FFF.)
2000-3FFF Device control ROMs. A device control ROM is
physically part of the device it controls, and so is
connected to the HHC when the device is plugged in.
The proper device control ROM for a given I/O
operation is selected by bank switching. Up to 16
different ROMs may be bank switched into this space.

The HHC cannot address all of the ROM that is


physically on-line at the same time. Two ROM sockets
(16K) at a time are bank-switched into the capsule
space. This is done with the SET .BANK word.

4000-7FFF Capsule space. ROM capsules are accessed through this


space.
There are 4 capsule sockets in the back of the HHC,
and more in the ROM expander peripheral. Each socket
can hold an 8K ROM capsule containing programs.
Contents of the capsule space is controlled by bank
switching; the space may be contain any two of the 3
capsule sockets on the back of the HHC, and/or the

(c) 1981 Friends Amis, Inc. 2-1 3 September 81


GENERAL TECHNICAL INFORMATION

sockets in a ROM expander.

The capsule space can also be bank switched to access


t he HC's memory-mapped I/O hardware. This is an
operating system function; application programs should
not bank-switch the I/O hardware into the capsule
space. CAUTION: attempts to store into this space will
address the I/O hardware regardless of what memory
bank is switched in. Never try to write to ROM!

8000-BFFF Extrinsic RAM space. Programmable Memory Peripherals


which plug into the HHC bus occupy this part of the
address space.

C000-FFFF Intrinsic ROM. Contains the nucleus; interrupt


processor; file manager; and intrinsic applications
(pocket secretary, file editor, and calculator).

(c) 1981 Friends Amis, Inc. 2-2 3 September 81


GENERAL TECHNICAL INFORMATION

DATA REPRESENTATION

Integers are represented with the high-order byte oriented


toward the top of the address space:

16-bit integer:

in memory: HHHHHHHHLLLLLLLL
adr+1 adr

on stack: HHHHHHHHLLLLLLLL

32-bit integer:

in memory: HHHHHHHH3333333322222222LLLLLLLL
adr+3 adr+2 adr+1 adr

on stack: HHHHHHHH33333333 (tip)


22222222LLLLLLLL (tip-1)

Floating point numbers are represented by 8-byte Quantities


containing a sign bit, a 7-bit exponent, and a 56-bit mantissa.
See the chapter on floating point arithmetic for more
information.
Characters, when stacked, occupy the low-order half of a
stack entry. The high-order half is zero.
SNAP has a standardized string data type. A string consists
of a length byte giving the number of characters in the string (0
to 255) followed by the string in ASCII. String constants may be
defined with the word 'STRING"'; it is used like this:

STRING" value" cccc

'value' is the value of the string constant. The first character


follows the word 'STRING"' and one blank; the next "" marks the
end of the string. 'cccc' is the string constant's name.
Alternatively, the word S" may be used to define a string
literal:

(c) 1981 Friends Amis, Inc. 2-3 3 September 81


GENERAL TECHNICAL INFORMATION

HERE
S"
== cccc

(This form is used to define tables of strings; for single


values, STRING" is preferable.)
Boolean values are 0 for FALSE and non-0 for TRUE. When a
SNAP word generates a Boolean TRUE, it always uses the value 1.

(c) 1981 Friends Amis, Inc. 2-4 3 September 81


GENERAL TECHNICAL INFORMATION

SNAP CODE STRUCTURE ON THE HHC

One of the main features of SNAP is ics use of a string of


TAGS to represent the code in a compiled colon definition. When
the SNAP interpreter executes a colon definition, it uses each
tag as an index into a TAG TABLE, which points to the code that
defines the word. This arrangement results in more compact
compiled code.

What a Tag Is

Most implementations of FORTH compile each colon definition


to a string of code field addresses (CFAs). For example, this
colon definition:

: UPDATE TODAY @ TOTAL + ;

might be compiled to:

address contents meaning

1A62 15C3 (the address of TODAY)


1A64 0242 (the address of @)
1A66 OFF3 (the address of TOTAL)
1A68 0456 (the address of +)
1A6A 0411 (address of a word that returns control to
the word that invoked UPDATE)

SNAP compiles a colon definition to a string of one-byte


tags. Each tag is an index into a TAG TABLE, wnich contains the
addresses of word definitions. SNAP might compile UPDATE to:

address contents meaning

IA62 C4 (tag for TODAY)


1A63 08 (tag for @)
1A64 C3 (tag for TOTAL)
1A65 OA (tag for +)
1A66 07 (tag for a word that returns control to the
word that invoked UPDATE)

The tag table that the interpreter used to execute UPDATE might
look like this:
tag
address contents represented meaning

(c) 1981 Friends Amis, Inc. 2-5 3 September 81


GENERAL TECHNICAL INFOfMATION

1800 OS** 00

180E 0411 07 (address of "end-of-definition")


1810 0242 08 (address of @)
1812 xxxx 09
1814 0456 OA (address of +)

1986
• OFF3 C3 (address of TOTAL)
1988 15C3 C4 (address of TODAY)

If we use CFAs, each reference to a word in a colon


definition consumes 2 bytes of memory. If we use SNAP's tags, the
first reference to a word consumes 3 bytes of memory: one for the
tag itself, and two for the corresponding entry in the tag table.
Each subsequent reference consumes only one byte of memory. Thus,
the two techniques are equally efficient for a tag that is
referenced twice; the tag technique is more efficient for a tag
that is referenced more than twice, and the more times the tag is
referenced, the greater the tag's advantage becomes.

Short and Long Tags

A little thought should convince you that this cannot be all


there is to the HHC's tag facility. A program as sophisticated as
the HHC's operating system could not possibly be defined with the
256 tags that one-byte tags would allow.

In fact, the HHC uses certain tag values (01H through 08H) as
"escape tags" which mean, "use the following byte as an index
into another tag table, and execute the word pointed to by the
appropriate entry in that table."
For all practical purposes, we can treat a tag 01H to 07H,
followed by another byte, as a single LONG TAG. We will
distinguish an "ordinary" tag (value OOH or 03H to OFFH) by
calling it a SHORT TAG.

For example, suppose the HHC interpreter encounters the


following code while executing a word:

OC 02 15 07 03 SF

OC is an ordinary tag; the interpreter looks it up in the

(c) 1981 Friends Amis, Inc. 2-6 3 September 81


GENERAL TECHNICAL INFORMATION

regular tag table.

02 is an "escape tag;" the interpreter looks up the NEXT


value --1 in a tag table dedicated to tags that start with
02.
07 is also an escape tag; the interpreter looks up the next
value, 03, in a tag table dedicated to tags that start with 07.
5F is an ordinary tag; the interpreter looks it up in the
regular tag table.
Since short tags are both more space-efficient and more time-
efficient than long tags, they are assigned to the words that are
used most frequently in the HHC system. Long tags are assigned to
words that are less frequently used.

The Structure Of Tag Tables

The HHC uses several tag tables to execute SNAP code. These
tables are:

* The SHORT INTRINSIC TABLE, used for tags OUR through OBFH.
This table is in intrinsic ROM; its entries represent short
tags that are part of the HHC's intrinsic software (nucleus,
device routines, and intrinsic applications).
* TABLE #1, containing long tags that begin with 01H. This
table is in intrinsic ROM; its entries represent long tags
that are part of the HHC's intrinsic software.

* The SHORT EXTRINSIC TABLE, used for tags OCOH through OFFH.
This table is in an extrinsic program (i.e., in a ROM capsule
or a SNAP program in a virtual file). Its entries represent
short tags that are part of the extrinsic program.

* Seven other tables, named TABLE #2 through TABLE #8. These


tables are used for long tags that begin with 02H through
08H. They are defined in an extrinsic orogram. Their entries
represent long tags that are part of the extrinsic program.

By convention, these tag tables are reserved for specific


uses:
#2,#3 For application capsules.

#4,#5,#6 For "library" capsules containing words that


application capsules may execute. An application
capsule may use these tables if it does not need
any library capsules.

47 For a library of debugging words that you can use

(c) 1981 Friends Amis, Inc. 2-7 3 September 81


GENERAL TECHNICAL INFORMATION

in immediate mode on the development system


(Snapple).
43 For internal use by "I A - system.

Each of the extrinsic tables (the short extrinsic table and


tables #2 through #8) may or may not exist in any given
application program. If a table exists, it may be of any length
sufficient to hold the tags defined by it.

The Tag Table Vector

The interpreter finds the tag tables through a TAG TABLE


VECTOR, which consists of 9 entries kept in RAM.
Entry 0 points to the short extrinsic table; entries 1
through 8 point to tables 1 through 8. Any entry corresponding to
a non-existent table has an unpredictable (i.e., meaningless)
value.
The short intrinsic table is not represented in the vector;
for the sake of speed, its address is hard-coded into the
interpreter.

How the Interpreter Uses the Tag Tables

To interpret a tag, the SNAP interpreter picks up its valae,


doubles it, and uses it as a displacement into the short
intrinsic table or the short extrinsic table, as appropriate. The
interpreter jumps to the address contained in the entry that the
displacement points to.
For a short tag, the jump goes directly to the definition of
the word represented by the tag. If the word is a CODE word, the
jump goes to whatever was assembled from the word's definition.
If the word is a colon word, the jump goes to a BREAK instruction
followed by a string of tags compiled from the word's definition.
The BREAK instruction calls the interpreter to interpret tne
following tags, much as a call to DOCOL or DOCOLON would in a
conventional implementation of FORTH.
For a long tag, the jump goes to a routine that picks up the
second byte of the tag, doubles it, and uses 'it as a displacement
into the proper tag table (1 through 8, as determined by the
first byte of the tag). The routine jumps to the address
contained in the entry that the displacement points to, just as
the interpreter itself would do for a short tag.

(c) 1981 Friends Amis, Inc. 2-8 3 September 81


GENERAL TECHNICAL INFORMATION

TAG TABLE VECTOR

memory
address banK
short
I intrinsic
short 81 table
extrinsic
1 80

2 81 CAPSULE #1
memory bank 1
3 84 - - :
program long
(empty) header 1 table #1

(empty)
short
(empty) extrinsic
(empty) long table
#2
(empty)

CAPSULE #2
memory bank 4

program
header

long table
#3

INTRINSIC RAM CAPSULE ROM INTRINSIC ROM

FIGURE 2-1

Structure Of the Tag Table

(c) 1981 Friends Amis, Inc. 2-9 3 September 81


GENERAL TECHNICAL INFORMATION

Initializing the Tag Table Vector: The Header

Customarily an application program contains tW3 tag tables,


the short extrinsic table and one long table. The first word in
the long table is, by definition, the program's entry point. This
word is often called the MOTHER WORD.

The second word in the long table should initialize the tag
table vector to point to the short tag table, and to any
additional long tag tables the program may need, whether in this
capsule or in some other. The mother word should call this word
before executing any word that is not in the (primary) long tag
table.

A program must begin with a HEADER containing several pieces


of information about the capsule in a standardized format. Figure
2-2 shows the source code customarily used to construct a header
for a program that will execute from a ROM capsule.

When the HHC is to execute your application, it picks up tne


number and address of your (primary) long tag table from the
header, and uses them to initialize the appropriate entry in the
tag table vector. Then it FLEEs to your program.

When you load your program under Snapple (a version of SNAP


which runs on the development system, and is equipped with an
outer interpreter), Snapple initializes the tag table vector the
same way. In addition, it executes the second word in the long
tag table. If the second word contains no bugs, this initializes
the tag table vector for all the other tag tables your pcogram
uses. Thus you can immediately run any word in your program
without further worry about whether or not the proper tag table
has been initialized. (But note, the second word in the long tag
table will be executed again if you execute the mother word!
Don't write anything in the second word that will hurt your
program if it is done twice.)

Setting Up the Header

The following comments explain the steps in setting up the


header:

1. ROMADDR is a symbol for the address at which ROM capsules


begin in the HHC address space. ROMADDR SETORG tells the
SNAP compiler that the capsule begins at that address.

2. The first thing in the capsule must be a string consisting


of the text 'COPYRIGHT yyyy BY nnnnnnn', where "yvvy" is
the year of publication and "nnnnnnn" is the name of the
owner of the copyright.

(c) 1981 Friends Ainis, Inc. 2-10 3 September 81


GENERAL TECHNICAL INFORMATION

3. ROMID is the target address where a string containing the


ROM capsule's name should go. ROMID TO DP-V stores that
address into the virtual dictionary pointer, whicn tells
the SNAP compiler where in the target address space the
next piece of compiled code should go.

The following string is the program's name, which will


identify the program in the HHC's primary menu when the ROM
capsule is plugged into the HHC. The string may be any
length up to 255 characters, but good practice limits its
length to 24 characters, so that the menu driver can
display it on the LCD without scrolling.

4. CSPEED gives the address of a location in the header where


the HHC expects to find flags describing the type of ROM
capsule this is. PROGBIT CSPEED C!-V sets that byte in the
ROM capsule's address space to a value that means "this is
an executable program stored in fast ROM."

5. SHORTAGS is the number of entries the capsule's short


intrinsic tag table should allow for. LONGTAGS is the
number of entries the capsule's long tag table should allow
for. (The standard header provides for only one long
table.) LONGSEG specifies the table number to be assigned
to the long tag table.

6. This line defines a symbol named TABLEADR, which gives the


target space address of the tag table about to be defined.

7. This line calculates the address of the long tag table


(HERE-V, the compiler's current location in the target
space, plus the length of the short extrinsic table) and
stores it at ROMVECT.

8. This line takes the number of the tag table addressed by


ROMVECT and stores it at ROMEXT.

At run time, the nucleus initializes the tag table vector


entry indicated by ROMEXT (the entry for long tag table #2,
in this case) to point to the tag table addressed by
ROMVECT.

9. This line allocates the short and long tag tables.

SHINT is a pre-defined symbol giving the number of first


short tag that will be defined.

SHORTAGS is the desired length, in entries, of the short


extrinsic tag table.

LONGSEG 256 * is the number we want the compiler to assign


to the first long tag that it defines. (Note, if we were
talking hexadecimal, 256 would become 100!)

LONGTAGS is the desired length, in entries, of the long tag

(c) 1981 Friends Ainis, Inc. 2-11 3 September 81


GENERAL TECHNICAL INFORMATION

table.

_A .TABLE allocates and initializes the 'nble.

M.PYTHON is the name of tne tag table. If this symbol


appears later in the program, it makes the SNAP compiler
begin compiling colon definitions into that tag table.
(The name does NOT have the conventional function of
stacking the address of the tag table it names. Because of
its function, the name can be used meaningfully only
outside colon definitions.)
10. MY-ENTRY-POINT is going to be the name of the mother word.
'LONG MY-ENTRY-POINT' ensures that MY-ENTRY-POINT will be
given a long tag, and reserves space for it in the tag
table. Since no long tags have been defined yet, MY-ENTRY-
POINT is assigned the first tag in the long tag table. (A
complete explanation of the word LONG, is given below.)
11. MY-TABLE-SETUP is going to be the name of the tag table
initialization word. 'LONG MY-TABLE-SETUP' assigns MY-
TABLE-SETUP the second tag in the long tag table.

(c) 1981 Friends Amis, Inc. 2-12 3 September 81


GENERAL TECHNICAL INFORMATION

\ THIS IS A HEADER FOR AN APPLICATION PROGRAM.


ROMADDR SETORG (comment 11
S" COPYRIGHT FRIENDS AMIS, --C. 1981" :comment 2
ROMID TO OP--'I comment 1 ,
3" APPLICATION PROGRAM NAME"
PROGBIT CSPEED CI-V comment 4}
64 == SHORTAGS comment 5}
100 == LONGTAGS
2 == LONGSEG
HERE-V == TABLEADR {comment 61
HERE-V SHORTAGS DUP + ROMVECT I-V comment 71
LONGSEG ROMEXT CI-V comment 8}
SHINT SHORTAGS LONGSEG 256 * LONGTAGS TAG.TABLE M.PYTHON
{comment 9}
LONG MY-ENTRY-POINT {comment 10}
LONG MY-TABLE-SETUP {comment 11}

FIGURE 2-2
Header For an Application Program

(c) 1981 Friends Amis, Inc. 2-13 3 September 81


GENERAL TECHNICAL INFORMATION

The Mother Word and the Tag Table Vector Initializatin Word

Recall that the second tag in the long tag table ,is
initialize the tag table vector to point to the snort extrinsic
table, and to any additional long tables that the program uses;
and the mother word must execute the second tag before using any
of those tables.

Figure 2-3 shows how the mother word and the second word
could be set up, assuming a header like the one in Figure 2-2.

The first line in MY-TABLE-SETUP stores the address of the


short tag table in entry #0 of the tag table vector. (Recall that
the first byte of each entry holds the bank ID of the table; so
we must add 1 to the address of the entry to get the address
where the table address is to be stored.)

The second line stacks the number of the long tag table, and
multiplies it by 3, giving the offset of the tag table vector
entry that represents the long tag table.

The third line fetches the first byte from the tag table
vector entry that represents the long tag table. This contains
the bank ID of this capsule (which applies to both the long
extrinsic table and the short extrinsic table).

The fourth line stores the bank ID of this capsule in entry 0


of the tag table vector.

The first line of MY-ENTRY-POINT executes MY-TABLE-SETUP,


ensuring that the tag table vector will be fully set up before
any tags in the short tag table are used. The second line
executes a word called EVERYTHING-ELSE, which presumably does
everything else in the program.

: MY-TABLE-SETUP (S ) \ THE SECOND WORD IN THE LONG TABLE


TABLEADR TVECTO 1+ ! T.T.V. ENTRY 0 = SHORT TABLE ADR.
ROMEXT C@ DUP DUP + + + \ OFFSET OF MAJOR TABLE'S ENTRY.
TVECTO + C@ \ BANK ID FROM MAJOR TABLE'S ENTRY.
TVECTO C! \ STORE IT IN ENTRY O.

MY-ENTRY-POINT (S ) \ THE MOTHER WORD


MY-TABLE-SETUP \ CALLS THE SECOND WORD
EVERYTHING-ELSE ; \ THEN DOES EVERYTHING ELSE.

FIGURE 2-3
A Tag Table Vector Initialization Word
and a Mother Word

(c) 1981 Friends Amis, Inc. 2-14 3 September 81


GENERAL TECHNICAL INFORMATION

A Tag Table Over 256 Entries Long

A long tag table may be over 256 entries long. If it is, you
must initialize anotner tag taole vector entry for eacn
additional segment of up to 256 entries. This consists simply of
storing a segment's address and bank ID in the proper entry in
the vector.

For example, suppose you define a tag table with 520 entries,
and specify that the first tag is to be number 200H (and you set
ROMEXT to 2). The nucleus will initialize tag table vector entry
#2 for the part of the to table that contains tags 200H through
2FFH. You must include code in the tag table vector
initialization word to initialize tag table vector entry #3 for
the part of the table that contains tags 300H through 3FFH, and
tag tale vector entry #4 for the part of the table that contains
tags 400H through 407H.

Figure 2-4 shows an example of code that performs this


initialization.

MY-TABLE-SETUP (S ) \ THE SECOND WORD IN THE LONG TABLE


\ INIT. TAG TABLE VECTOR FOR SHORT EXTRINSIC TABLE,
TABLEADR TVECTO 1+ I
ROMEXT C@ DUP DUP + + +
TVECTO + C@
TVECTO CI
\ INIT. FOR 2ND & 3RD SEGMENTS OF LONG TABLE.
ROMEXT C@ DUP DUP + + + \ OFFSET OF 1ST SEGMENT'S ENTRY.
TVECTO + >R R= ADDRESS OF ENTRY.
R C@ R 1+ @ \ STACK BANK ID, 1ST SEGMENT'S ADR.
512 + 2DUP 512 + \ 2ND & 3RD SEGMENTS' ID/ADR.
R 7 + R 6 + C! \ INIT. TABLE FOR 3RD SEGMENT.
R 4 + I R> 3 + CI \ INIT. TABLE FOR 2ND SEGMENT.

FIGURE 2-4
Initializing the Tag Table Vector
For a Second Tag Table

(c) 1981 Friends Amis, Inc. 2-15 3 September 81


GENERAL TECHNICAL INFORMATION

A Program that Occupies Multiple Capsules

It is possible for a single program to occupy two or more ROM


capsules. This might be necessary because the program is jst too
big to fit in one capsule. Or, it might be convenient because
several programs in separate capsules all use a set of common
subprograms, kept in one additional capsule.

When a program occupies two or more capsules, the HHC must


switch memory banks whenever a word in one capsule uses a word in
the other. This is because every ROM capsule must start at the
same point in the address space; since two ROM capsules would
share the same set of addresses, only one at a time could be in
the HHC's address space.

If one capsule calls another in this way, each capsule must


have its own long tag table. Only one of them (customarily the
MASTER capsule -- the one containing the program's highest-level
word) may have a short extrinsic table.

The master capsule must initialize the tag table(s) for the
SLAVE capsule(s). Assuming a slave capsule has a standard-format
capsule header, you can initialize the vector in the following
way:

1. Assume that there is a capsule in memory bank 0, and move


the capsule's name to an area in RAM that you have
allocated as work space. (The address of the name string's
length byte is given by ROMID. Move whatever length you
need to tell whether or not the capsule is the one you
want.)

The AREA word, described elsewhere in this chapter, may be


used to allocate RAM. BIGMOVE, described in the glossary,
may be used to move data to RAM from a memory bank not
currently in the address space.

2. If the capsule name is unintelligible or says this is not


the capsule you want, try the next memory bank. Continue
until you find the capsule you want, or until you have
examined memory banks 0 through 07FH.

If you find the capsule you want, fetch its tag table
address (kept at ROMVECT in the header) and its taole
number (one byte long, kept at ROMEXT). Store its address
and bank ID in the appropriate tag table vector entry.
IMPORTANT: when you store the bank ID in the tag table
vector entry, turn on the 80's bit to indicate that the
bank ID refers to a ROM bank. If you do not do this, the
HHC will think the capsule is in a RAM bank.

4. If you do not find the capsule you want, give an

(c) 1981 Friends Amis, Inc. 2-16 3 September 81


GENERAL TECHNICAL INFORMATION

appropriate error message.

If the slave capsule has more than one tag table, you can
call a word in the slave capsule itself to initialize the
vector for additional tables. Alternatively, you can set up a
convention of your own which enables the master capsule to find
additional tables in the slave.

When a tag in one capsule refers to a tag table in another


capsule, the HHC's interpreter detects that fact when it gets the
tag table vector entry for the required tag table, and finds that
the table is in a memory bank not currently in the address space.
Before trying to use the table, the interpreter switches the
required memory bank into the address space. Thus, the HHC
provides automatic bank switching for tag tables (and thus for
code) in different memory banks.

Note On Data Capsules

If a ROM capsule is a slave, you will not want it to appear


in the HHC's menu. To signal the HHC that a capsule should not go
in the menu, let the PROGBIT bit in the CSPEED byte remain OFF.

A capsule in which PROGBIT is off is called a DATA CAPSULE.


This is a misnomer, since such a capsule may contain executable
code as well as data, but it suggests the fact that the capsule
does not contain a complete, executable program.

Note On Slow ROM

ROM capsules come in sizes of 2K, 4K, 8K, and 16K bytes. All
but the largest size use FAST ROM, which can be read any time the
HHC wants to access it. The 16K capsules must use SLOW ROM, which
cannot be accessed for several milliseconds after it is bank-
switched into the address space. If your program is to be stored
in a slow ROM capsule, you must signal that limitation to the
HHC's software by turning on another bit in the header flag byte.

To turn on the proper oit, replace the statement labelled by


comment 4 in Figure 2-2 with the following:

PROGBIT CSLOW OR CSPEED C'. -V

turning on the CSLOW bit in CSPEED indicates slow ROM.

Assigning Long and Short Tags To Words

(c) 1981 Friends Amis, Inc. 2-17 3 September 81


GENERAL TECHNICAL INFORMATION

By using SNAP compiler directives, you can control which of


tags are assigned short tags and which are assigned long
tags. This is useful, since you can optimize your program for
space oy assigning short tags to the words tnat are most
frequently CODED, or optimize it for speed by assigning short
tags the words that are most frequently EXECUTED. (These two
goals conflict only if there are not enough short tags to go
around.)

The compiler always begins assigning short tags to the words


it compiles, working up from the initial short tag value given as
a TAG.TABLE parameter. It continues assigning short tags until it
is directed to use long tags, or until it runs out of space in
the short extrinsic tag table.

The compiler directive LONG guarantees that a specific name


will be assigned a long tag:

LONG name

LONG is used BEFORE the name is defined. It actually reserves


space in the (current) long tag table for the specified name,
incrementing the counter that determines what tag number will be
assigned to the next-defined tag.

The directive SHORT guarantees that a specific name will be


assigned a short tag:

SHORT name

Like LONG, it is used before the name is defined. It reserves


space in the short extrinsic tag table.

LONG.TAGS specifies that all following words should be


assigned long tags (unless they have been guaranteed short tags
by SHORT). Similarly, SHORT.TAGS specifies that all following
tags should be assigned short tags (unless they have been
guaranteed long tags by LONG).

Note On Tag Table Overflow

If the short extrinsic tag table becomes full, the compiler


issues a warning message and starts defining long tags instead of
short tags.

If the (current) long tag table becomes full, the compiler


issues an error message and aborts.

(c) 1981 Friends Amis, Inc. 2-18 3 September 81


GENERAL TECHNICAL INFORMATION

Note On Colon Definitions: :C

If you have a long-tag word that is called only once, you can
save a byte in your program by defining it with ':C' instead of
1 :1. This is a useful trick if your program is just barely too
big to fit in a ROM capsule, and every byte counts.
If you define a word with :C, the definition of the word is
compiled, but the word is NOT assigned a tag. Any reference to
the word in another colon definition will compile to the short
tag '(CALL)', followed by the 2-byte address of the word's
definition.

This saves a byte because we have made the reference to the


word one byte longer (a short tag and a 2-byte address instead of
a long tag) while removing one entry from the long tag table
(permitting us to make the segment 2 bytes shorter).

Note On Forward References

If you refer to a word before you define it, the SNAP


compiler does NOT abort, as most FORTH compilers do. It assumes
that the word will be defined later as a :C word.
If the word is later defined as a :C word, the compiler gives
you an advisory message and patches the definition's address into
the reference(s) it has already compiled.

If the word is never defined, OR if it is later defined as an


ordinary colon word, the compiler cannot resolve the forward
reference. It gives an error message at the end of the
compilation which identifies the word as unresolved.

If you want to make a forward reference to a colon


definition word, "predefine" the word by declaring it with LONG
or SHORT before the first reference to it.

(c) 1981 Friends Amis, Inc. 2-19 3 September 81


GENERAL TECHNICAL INFORMATION

CONSTANTS

Symbolic Constants

Instead of FORTH's conventional defining word CONSTANT, SNAP


has a word called 1 ==', which defines a SYMBOLIC CONSTANT.

A symbolic constant does not compile a word that appears in


the object code; rather, it causes the compiler to compile any
reference to the defined symbol as the symbol's value.

Here is an example of '==' in use:

64 == BFR.LEN

This defines a symbolic constant named BFR.LEN whose value is 64.


After the compiler has processed this definition, the following
two code fragments will compile to the same sequence of tags:

BFR 64 ERASE

BFR BFR. LEN ERASE

Colon Definitions As Constants

You can get effect more similar to that of a conventional


FORTH constant by creating a colon definition that stacks a
constant value, like this:

: BFR.LEN 64 ;

or even like this:

: 64 64 ;

If you give such a colon definition a short tag it may reduce


your program's size, because while a DEFINITION of a symbolic
constant consumes no memory at run time, a REFERENCE to a
symbolic constant consumes slightly more memory than a reference
to a colon definition.

(c) 1981 Friends Amis, Inc. 2-20 3 September 81


GENERAL TECHNICAL INFORMATION

DEFINITION REFERENCE
CONSUMES CONSUMES

SYMBOLIC CONSTANT O bytes 2 bytes (0(=k<=253)


3 bytes (other values)

COLON DEFINITION 4 bytes (0<=k<=255) 1 byte


WITH SHORT TAG 5 bytes (other values)

If you refer to a value several times, using a short-tag


colon definition will make your program slightly smaller (but
slightly slower). If you refer to the value only once or twice, a
symbolic constant will be both more compact and faster.

(c) 1981 Friends Amis, Inc. 2-21 3 September 81


GENERAL TECHNICAL INFORMATION

ALLOCATING RAM, PART I: THE TEMPORARY STORAGE AREA (TSA)

You allocate variables for an application program by creating


a TEMPORARY STORAGE AREA (TSA).

A TSA is an area in RAM that is allocated at run time from


the TEMPORARY STACK. A TSA is allocated dynamically at run time.
This avoids the problem that would occur if SNAP attempted to
allocate working storage in the conventional FORTH fashion: that
every application woulhave its own exclusive area in RAM, and
soon all the RAM would e used up.
'
1.

How To Use a TSA

To use a TSA, you must' (1) define it at compile time, and (2)
allocate it at run time.

You define a TSA at compile time with the AREA word. AREA is
followed by another word which becomes the name of a word which
AREA defines; you may execute this word to allocate the TSA. AREA
is followed by variable definitions, and then ENDAREA. (See the
example below.) You must compile this sequence before any code
which allocates or refers to the TSA.

You allocate a TSA at run time by using the TSA's allocation


word (the name that followed the AREA word) your program. The
allocation word returns a boolean: TRUE if it succeeded in
allocating the TSA, FALSE if there was not enough free RAM for it
to do so.

An Example

This example shows how you could define and allocate a TSA.

AREA TSAWURD \ DECLARE TSA FOR WURD.


VAR WURD.TEMPC \ CTRL BYTE HOLDING AREA
VAR WURD ,PTR \ CHAR PTR
ENDAREA

WURD (S )
TSAWURD NOTIF ALLOC TSA & TEST SUCCESS.
." NO SPACE!" ENDIF
.. •

Types Of TSA Variables

(c) 1981 Friends Amis, Inc. 2-22 3 September 81


GENERAL TECHNICAL INFORMATION

Here are the words that may be used to allocate RAM in a TSA.

yaw-
CVAR coo
defines a one-byte variable named "ccc".

n CVECTOR ccc
Defines an array named "ccc" containing "n" byte elements.

DVAR ccc
Defines a two-word variable named "ccc".

FVAR ccc
Defines a floating point (8 byte) variable named "ccc".

n STRING ccc
Defines a character string variable with room for "n"
characters, named "ccc".

VAR ccc
Defines a one-word variable named "ccc".

n VECTOR ccc
Defines an array named "ccc" containing "n" word elements.

Notes On Using the TSA

If the allocation word returns TRUE, it has allocated the TSA


from the temporary stack. The TSA will remain allocated until the
user presses the CLEAR key, or until the program executes the
LETGO word (see glossary).

When the TSA is allocated, its contents are NOT initialized.


This means that if a particular variable should have an initial
value (e.g., zero), you should initialize it after allocating the
TSA.
The variables in a TSA are allocated in reverse order; i.e.,
the first-defined variable has the highest address, and the last-
defined variable has the lowest address. (This makes sense when
you recall that the temporary stack grows down from the top of
the temporary stack space.)
It is good practice to initialize the TSA one variable (or
one vector) at a time. Do not calculate the total length of the
TSA and do a one-shot initialization with a word like FILL. On
the simulator, one-shot initialization is likely to be
disasterous, because it will wipe out the FORTH headers that are
created by each defining word!
At compile time, the storage words defined in the TSA are
global. It is your responsibility to ensure that the TSA is
allocated before any of the variables in it are referenced.

(c) 1981 Friends Ainis, Inc. 2-23 3 September 81


GENERAL TECHNICAL INFORMATION

Releasing 7SA's

When a TSA is allocated, it "hides" all previously allocated


TSA's. You can think of TSA's as entries that are pushed onto the
temporary stack; only the tip entry (i.e., the one most recently
allocated and not yet released) is available at any time.
Because of this, your program must release TSA's if it needs
more than one TSA.
You release a TSA with the LETGO word. LETGO takes no
parameters from the stack, and leaves none:

LETGO

LETGO releases the TSA most recently allocated and not yet
released. In other words, it acts like a DROP that applies to the
temporary stack, dropping one whole TSA at a time.

About the Size of the Temporary Stack

The temporary stack is allocated down from the top of


intrinsic RAM. Virtual file space is allocated up from
(approximately) the beginning of page 2. Each of these entities
may grow until the two meet. Thus, the amount of space available
for the temporary stack is a function of the amount of intrinsic
RAM that is provided, and of the amount of intrinsic RAM being
used for virtual files.

The minimum configuration of the HHC has 2K of intrinsic RAM,


so 1.3K of RAM will be available for the temporary stack and
virtual files. The file system has an overhead of aoout 100 bytes
in intrinsic RAM, so the maximum amount of temporary stack space
an application can have on a minimum configuration HHC is about
1.4K. If an application is to be runnable on a minimum
configuration HHC (highly desirable in most cases), it should use
no more intrinsic RAM space than this.
CAUTION: always check the boolean value returned by the TSA
word to be sure the TSA was successfully allocated. It it was
not, give the user a meaningful error message and stop. Do not
let the program try to run; it will not work.

Do not confuse the temporary stack with the regular SNAP


stack that most SNAP words operate on. The latter stack is simply
called "the stack," or when a more explicit term is needed, tne
"PARAMETER STACK." it is allocated in the 6302's page 0, not page

(c) 1981 Friends Ainis, Inc. 2-24 3 September 81


GENERAL TECHNICAL INFORMATION

2.

(c) 1981 Friends Amis, Inc. 2-25 3 September 81


GENERAL TECHNICAL INFORMATION

ALLOCATING RAM, PART II: DYNAMIC ALLOCATION

A TSA cannot meet all of a Grogram': possible needs for RAM.


Sometimes you cannot say how much RAM a program will need at tne
time you compile it. This might be because the amount of space
the program will need is highly dependent on the data it is
given, or because the program can use as much RAM as it can get.
(A sort program is an example of the latter case.)

When you cannot predict your program's space requirements at


compile time, you must allocate RAM dynamically at run time.
You can allocate RAM dynamically from the tempor a ry stack
with the word GRAB. The linkage to GRAB is:

n GRAB [adr] b

"n" is the amount of RAM you want to allocate. If GRAB allocates


this amount of RAM successfully, it returns "adr," the address of
the RAM, and TRUE. If GRAB does not allocate the RAM
successfully, it returns FALSE.

Is There Enough Room?

You can tell whether a certain amount of RAM is available


without trying allocate it by using the word ?ROOM. The linkage
to ?ROOM is:

n ?ROOM b

"n" is a number of bytes of intrinsic RAM. "b" is TRUE if this


amount of RAM is available, and FALSE if it is not.

How Much Room Is There, Anyway?

Suppose you need to know exactly how much intrinsic RAM is


available? You can find out with the AVAIL word. The linkage to
AVAIL is:

AVAIL n

is the amount of intrinsic RAM that is available, in bytes.

For example, suppose you wanted to allocate as much intrinsic

(c) 1981 Friends Amis, Inc. 2-26 3 September 81


GENERAL TECHNICAL INFORMATION

RAM as you could, leaving 500 bytes free for virtual files. You
could do so like this:

AVAIL 300 - GRAB DROP

Recall that intrinsic RAM is shared by the temporary stack and


the virtual file system, so adding data to a virtual file will
decrease the amount of space available for your TSA.

(c) 1981 Friends Amis, Inc. 2-27 3 September 81


GENERAL TECHNICAL INFORMATION

ALLOCATING SPACE IN ROM

The commonest and simplest way to allocate sr;ace in ROM is


do so implicitly with colon definitions and code definitions.
Sometimes it is necessary to allocate ROM space explicitly.
For example, you may have to build a table or some other data
structure that your program will reference.

You can do this with standard FORTH dictionary management


words, such as 'ALLOT', and 'HERE'. In the simulator, these
words operate just as they would in FORTH. In the cross-compiler,
these words (in the ULTRA vocabulary) refer to the address space
of the HHC. For example, HERE stacks the address where the next-
defined word will begin WHEN LOADED ON THE HHC.
The word LABEL creates a symbol whose value is the current
value of the target-machine dictionary pointer. It is useful for
giving a name to an area in ROM:

LABEL EXTAB
HEX 00 C, 4A C, 25 C,

A reference to EXTAB in a colon definition will stack the


address of the first byte in the table (at run time).
An alternate way to label a table is to stack HERE before
compiling the table, and assign it to a constant when done:

HERE
00 C, 4A C, 25 C,
33 C, 21 C,
== EXTAB

Note that 'HERE == EXTAB' would not work properly in the


simulator. The definition of EXTAB would take up space in the
dictionary, so that it would point to itself, rather than to the
first byte of the table.

Note that you CANNOT use dictionary management words ITS


HERE in colon definitions. Since your compiled code will be in
ROM at run time, the concept of a run-time dictionary pointer is
meaningless!

(c) 1981 Friends Amis, Inc. 2-28 3 September 81


GENERAL TECHNICAL INFORMATION

A CAUTION REGARDING STACKS


1111.41-6
Now
50'
In Utrecht. FORTH, the DO •.. LOOP ind e x and I:mit are kept on
the return stack. The simulator also allocates TSA soace from the
return stack; that is, the return stack assumes the function of
the temporary stack.

In the HHC, on the other hand, return values, loop


parameters, and TSA space are kept on three SEPARATE stacks. This
means that certain coding techniques which will work on the
simulator will fail on the HHC; an example is using R> and >R to
modifiy a loop's limit while in the loop. Such coding techniques
are mostly filthy, and should be avoided in any case!

Keep the simulator's three-in-one stack structure in mind


when you debug your programs. It may explain some puzzling
results you get.

Cc) 1981 Friends Amis, Inc. 2-29 3 September 81


GENERAL TECHNICAL INFORMATION

RESTARTING A PROGRAM

The CLEAR Key

The CLEAR key is the ultimate corrector of mistakes on the


HHC. It can reset the system to its GROUND STATE, the primal
state from which all other things come. There is little you (or a
user) can do to the HHC's software that cannot be fixed by
pressing CLEAR.

Pressing the CLEAR key ONCE makes the system perform a SOFT
CLEAR. A soft clear consists of the following functions:

1. Empties the parameter stack, loop stack, and return stack.


2. Resets most aspects of the HHC's status. Cancels all timers
except the pocket secretary; clears LCD and most blips; re-
initializes certain RAM locations used by nucleus.

3. Restarts the current application by executing the tag in


SOFTAG. If SOFTAG is empty, the HHC does a hard clear.

Pressing the CLEAR key a second consecutive time makes the


system perform a HARD CLEAR. In a hard clear, the system performs
the following steps:

1. Empties the parameter stack, loop stack, and return stack


(same as for soft clear).
2. Resets most aspects of the HHC's status. Cancels all timers
except the pocket secretary; clears LCD and most blips; re-
initializes certain RAM locations used by nucleus (same as
for soft clear).

3. Empties the temporary stack.


4. Resets, unattaches and unbinds all peripherals; releases all
RAM reserved as workspace for the peripheral I/O drivers.

5. Zeroes SOFTAG and places the machine in the ground state.

Changing the Restart Word

The system variable SOFTAG contains x tag that the system is


to execute when it must restart your application {e.g., when the
CLEAR key is pressed once). The system initially sets SOFTAG to
your application's mother tag; thus, if you do not reset SOFTAG,

(c) 1981 Friends Amts, Inc. 2-30 3 September 81


GENERAL TECHNICAL INFORMATION

pressing CLEAR once will restart the application at its main


entry ooint. You can change this tag in two ways:

1. Directly, by storing a new tag value into SOFTAG. rJse the


word 'X (in compiled code) to get the tag of a word:

[ 'X restart-word ] LITERAL SOFTAG !

2. By FLEEing to the word. This executes the word and


simultaneously stores its tag in SOFTAG:
[ 'X restart-word ] LITERAL FLEE

If an application presents the user with various modes of


operation, you may want CLEAR to restart the current mode, rather
than restart the whole application. You can accomplish this
conveniently by entering the submode by FLEEing to an appropriate
word, and thus changing the value of SOFTAG.

Software Simulation of the CLEAR Key

You can get the effect of a soft clear in your program by


executing the word SOFT.CLR; or of a hard clear by executing
HARD.CLR. You can get the exact effect of pressing the CLEAR key
(i.e., a soft or a hard clear) by executing CLEAR.

Ending a Program

There are three ways you can end an application program.

The first way is place the main processing part of the


program in an endless loop, that is, not to end the program at
all. This is a logical choice for an endless-task program such as
a calculator.
The second way is to let the mother-tag word finish executing
and return control to the system. This returns the HHC to the
state it was in before the mother-tag word was executed. For
example, if the mother-tag word was executed from the primary
menu, returning control to the system returns the system to the
mother-tag menu.
The third way is to execute the word CLEAR, SOFT.CLR, or
HARD.CLR.

(c) 1981 Friends Amis, Inc. 2-31 3 September 81


GENERAL TECHNICAL INFORMATION

LATCH BYTE

The LATCH BYTE is a oyte of flags kept in the lower Part of


the address space. It is set by nucleus routines, and
interrogated directly by the hardware.

Application programs should never set the latch directly.


They should use the ANDLATCH and ORLATCH words.

Application programs generally should not interrogate the


latch, since one of the HHC's design specifications is that
hardware status should be totally transparent to applications.
Should it be necessary to interrogate the latch, however, it
should not be interrograted directly; programs should interrogate
LATCHS ("latch shadow"), which is kept equal to the system status
byte by software.

WORD VALUE MEANING


(HEX)

CAPON 4 1=> give capsules power, 0=> don't.


DISPON 8 1=> LCD on, 0=> display off.
SLOMEM 10 1=> addressing slow ROM, 0=> normal.
BEEPER 20 high/low DC to speaker. Software can
toggle this bit to generate audio.
CPUON 40 1=> CPU power on, 0=> off.
DMASK 80 selects function of memory mapped area
for keyboard/LCD functions. 1=>
keyboard, 0=> LCD.

(c) 1981 Friends Amis, Inc. 2-32 3 September 81


THE HHC KEYBOARD

The keyboard is, very roughly, a QWERTY design. Some changes


have been made to allow for the keyboard's small size, and the
fact that it is not intended for touch typing. For example, the
"space bar" is only three keys wide, and the ENTER (carriage
return) key is near the lower right corner.
The keyboard does not have a "control" key, but does have two
"shift" keys. One of these, named SHIFT, controls alphabetic
case; pressing it gives upper case letter, and releasing it gives
lower case letters. The other key, named SECOND SHIFT, gives
special symbols, which are separately marked on the keyboard.
Pressing SHIFT has no effect on keys that are not alphabetic;
similarly, pressing SECOND SHIFT has no effect on keys that are
not marked with special symbols.

(c) 1981 Friends Amis, Inc. 3-1 3 September 81


THE HHC KEYBOARD

HARDWARE ARCHITECTURE

Each time a key is oressed it generates a non-maskable


interrupt which is serviced by a macnine code routine in tne
nucleus. This routine accumulates keystrokes in a buffer from
which words such as KEY or RIP word may fetch them, first-in-
first-out.

Hidden and Immediate Keys

At the hardware level, all keyboard keys generate input in


the same way: they put a one-bit-on code in one of 8 fixed
hardware locations, indicating which key has been pressed.
The nucleus translates some of these codes to ASCII and
places them in the keyboard buffer, from which words such as KEY
may take them. The nucleus acts on other codes (such as LOCK and
I/O) directly; these codes never make it to the buffer. The keys
that generate such codes are called HIDDEN keys. Some of the
hidden keys (such as I/O) have an immediate effect on the HHC,
i.e., their effects do not filter through the keyboard buffer;
the keys that generate these codes are called IMMEDIATE keys.

Special Keys On the Keyboard

ENTER
Performs tne function more commonly called CARRIAGE
RETURN. An "ordinary" character key; generates an ASCII
code.
Cursor up, down, left, and right (I, r, <-, ->)
These keys are labelled with arrows oointing in the
appropriate directions. They are ordinary keys.

A program may use the cursor control keys for any purpose,
but they have two conventional meanings. First, if a
program uses cursor control on the video display (or on a
"virtual CRT" windowed by the LCD), it uses these keys to
move the cursor. Second, if a program uses a menu which
the user advances one step at a time, "down" is used to
advance the menu, and "up" is used to back it up. "Right"
and "left" may be used to advance and back up a subsidiary
menu. The paradigm is a page of a book, which is read top-
to-bottom and left-to-right.

ON and OFF
Turn the HHC on and off. Both are immediate keys.
Note that the effects of these keys are programmed; the
keys do not actually turn the power on and off.

(c) 1981 Friends Antis, Inc. 3-2 3 September 81


THE HHC KEYBOARD

When the HHC is "off," only the ON key will turn it on


again; out the CMOS RAM, downcouncer, ecc., still get
power. When turned back on, the HHC will "remember" the
current time, the contents of virtual files, the .00cket
secretary's appointments, etc.
I/O key
Suspends the program that is running and presents a menu
through which the user may attach/detach I/O devices. When
the user leaves the I/O menu, the program continues
running.
An immediate key.
CLEAR
Pressing the CLEAR key once causes a "soft clear." It
aborts the application that is executing and FLEEs to the
word designated by SOFTADR. (This restarts the application
unless the application has changed the value of SOFTAG
itself.)
Pressing the CLEAR key a second consecutive time causes a
"hard clear." It resets the HHC to the ground state, from
which it proceeds to the primary menu.
An immediate key.
STOP/SPEED
This key suspends the program that is running. While it is
suspended, the user may press a numeric key to change the
scrolling rate of the display and resume execution. (This
action stores a value in a system variable, SPEED.)
An immediate key.
SHIFT
Case-shifts the next keystroke entered. An immediate key.
SHIFT may, but need not, be held down while the next
keystroke is entered.
LOCK
"Locks" the next key pressed. Exception: the sequence
SHIFT LOCK locks SHIFT, not the key pressed after LOCK.
SHIFT LOCK causes every following character to be entered
in upper case until the SHIFT key is pressed again.
Locking any other key makes the LOCK-KEY word "read" the
same key over and over until another key is pressed. (See
further details below.)
A hidden key.

(c) 1981 Friends Amis, Inc. 3-3 3 September 81


THE HHC KEYBOARD

SECOND SHIFT
A shift key to shift the keyboard into a third case (in
addition to lower and upper case). All punctuation,
special characters, Pr. c., are in this case.

A hidden key.

HELP
Waits for the next keystroke, interprets that keystroke as
a command, and displays an explanation of the command. (It
does not execute the command.)
Note that HELP is asynchronous with the application
program and totally transparent to it.

Pressing HELP twice in a row is equivalent to pressing


CLEAR.
An immediate key.

DELETE
Used by the memo pad to delete characters from LCD. Other
programs may use this key for any purpose.

INSERT
Used by the memo pad to insert characters on LCD. Other
programs may use this key for any purpose.
SEARCH
Used by the memo pad to search for a character string.
Other programs may use this key for any purpose.

ROTATE
Customarily used by applications to control rotation of
the display, but may be used for any purpose.

Cl, C2, C3, and C4


May be used by applications for any purpose.

Fl, F2, and F3


Definable function keys. May be used for any purpose.

Keyboard Codes

The codes generated by the keyboard (with its standard


translation table) are roughly a superset of ASCII. All the ASCII
printable characters that appear in the HHC's character set have
the standard ASCII codes.
A table of codes generated by the keyboard and its standard
translation table is included in one of the appendixes to this
book.

(c) 1981 Friends Amis, Inc. 3-4 3 September 81


THE HHC KEYBOARD

Operation of the LOCK Key

If the SHIFT and LOCK keys are pressed consecutively (either


key first), the SHIFT LOCK BIT is toggled. When this bit is on,
the I/O routines shift any key that is pressed.
When LOCK is pressed at any other time, it turns on the LOCK
BIT. This causes the next keystroke entered to be returned
repeatedly, whenever the LOCK-KEY word is executed. When another
key is pressed the lock bit is turned off, ending the repeat.
When the SHIFT key is pressed at any other time, it causes
the next keystroke entered to be shifted.
Words whose functions are affected by the LOCK key are ?LOCK
and LOCK-KEY. Note that the KEY word is NOT affected by this use
of the LOCK key; that is, if the user tries to "lock" a character
by pressing LOCK, then a character key, he will succeed only if
the program is doing its input with LOCK-KEY.
NOTE: the shift-locking function of the LOCK key is not
supported by the simulator.

(c) 1981 Friends Amis, Inc. 3-5 3 September 81


THE HHC KEYBOARD

PROGRAM-DEFINED KEYBOARD TRANSLATION TABLES

An application program can define its own keyboard


translation table; this allows it to define the binary codes that
the keyboard keys will generate. This is useful when the logic of
the application requires that the keyboard be made to operate in
some non-standard way (e.g., like a terminal keyboard, with a
CONTROL key). The same result could be achieved by programming
character translation into the application, but a keyboard
translation table is more efficient and uses less memory.
You use a keyboard translation table by (1) coding the table
at compile time, and (2) giving the HHC the table's address at
run time.

Coding a Keyboard Translation Table

A keyboard translation table consists of 196 one-byte entries


in ROM. (You could theoretically put the table in intrinsic RAM,
although this would be a profligate use of RAM. You could not put
it in swappable RAM, i.e., in a Programmable Memory Peripheral.)

Each key on the keyboard generates a RAW KEYBOARD CODE


between OOH and 3FH. SHIFT or SHIFT LOCK adds 40H to each raw
keyboard code. SECOND SHIFT adds 80H.

The raw keyboard codes generated by each key on the keyboard


are shown in the diagram in Figure 3-1.

Each time a keystroke is processed, the raw keyboard code is


used as a displacement into the character translation table; the
contents of the table entry (i.e., the translated code) is placed
in a buffer, from which it is passed to the user by KEY, LOCK-
KEY, etc.

For example, suppose the user presses the key in the lower
left corner of the keyboard (the 'Cl' key). This key generates a
raw keyboard code of 31H. The HHC places the contents of byte
number 31H of the current keyboard translation table (where the
first byte in the table is "number 0") in the keyboard buffer. If
the user presses the same key, but in a shifted state, the raw
keyboard code is 71H, and the HHC places the contents of byte
number 71H in the buffer.

Adopting a New Keyboard Translation Table

To adopt a new keyboard translation table, store the table's


address in the system variable 'KBVECT'.

The following code fragment illustrates how to define a

(c) 1981 Friends Amis, Inc. 3-6 3 September 31


THE HHC KEYBOARD

keyboard translation table and adopt it:

HEX
LABEL your-keybd
00 C, -V KEYBD CODE 00 IS NOT GENERATED.
4A C,-V KEYBD CODE 01 GENERATES 4A.
2C C,-V KEYBD CODE 02 GENERATES 2C.
\ AND SO FORTH.
: ADOPT-KBD
your-keybd KBVECT \ ADOPT NEW KEYBD TABLE.

To restore the standard keyboard table, execute:

KBSET KBVECT I

(c) 1981 Friends Amis, Inc. 3-7 3 September 81


THE HHC KEYBOARD

-01- -02- -03- -04- -OS- -06- -07- -08- -09- -OA- -uB- -0C- -OD-
! 21 " 22 4 23 s 24 % 25 & 26 ' 27 ( 28 ) 29 _ 5F HELP ^ I/O
1 31 2 32 3 33 4 34 5 33 6 36 7 37 -- -- -- 14 80 -n-,....
1 31 2 32 3 33 4 34 3 33 6 36 7 37 8 38 9 39 0 33

-11- -12- -13- -14- -15- -16- -17- -18- -19- -1A- -18- -1C- -1D-
% 25 + 28 - 2D x 92 T 91 = 3D <- stop ->
Q 51 W 57 E 45 R 52 T 54 Y 59 U 55 I 49 0 4F P 50 81 /spd 82
q 71 w 77 e 65 r 72 t 74 y 79 u 75 i 69 o 6F p 70 OE

-21- -22- -23- -24- -23- -26- -27- -28- -29- -2A- -2B- -2C- -2D-
\ 5C t 7B 1 7D [ 5B I 5D < 3C > 3E Fl
.10 OM
SRCH * ROT
A 41 S 53 D 44 F 46 G 47 H 48 J 4A K 4B L 4C 15 89 83 07
a 61 s 73 d 64 f 66 g 67 h 68 j 6A k 6B 1 6C

-39- -3A- -3B- -3C- -30- -20- -10- -33- -OE- -1E- -2E- -3E- -38-
^ 5E - 7E 60 @ 40 I 7C * 2A ; 38 : 3A F2 INSRT DEL LOCK
Z SA X 58 C 43 V 56 B 42 N 4E M 4D -- 16 84 85 86
z 7A x 78 c 63 v 76 b 62 n 6E m 6D , 2C . 2E

-31- -32- -36- -37- -34- i 35 I -OF- -1F- i---3F---1 -2F-


Ci C2 C3 C4 / 60 I SPACE 1 2ND F3 I ENTER I SHFT
8C 8D 8E 8F -- I 20 1 SHFT 17 I I 8A
? 3F I i 8B i i

FIGURE 3-1

THE HHC KEYBOARD

FIRST LINE: raw keyboard code (unshifted).


SECOND LINE: second-shifted character & ASCII code.
THIRD LINE: shifted character & ASCII code.
FOURTH LINE: unshifted ASCII character & code.

For keys where shift and second-shift are not significant, the
second line shows the ASCII code or key function and the third line
shows the input value, character code.

(c) 1981 Friends Amis, Inc. 3-8 3 September 81


THE HHC KEYBOARD

EXPECT: KEYBOARD INPUT

The EXPECT word is a convenient means for reading aline from


the keyboard. It is similar in function to the EXPECT word in
FORTH, but has a more elaborate linkage, and can edit a line of
text as well as accept one as input.

You can use EXPECT like this:

adr len init initc eol mode EXPECT adr len' eolchar mode'

adr
Address of the buffer where EXPECT is to deposit the line it
reads. The operating system provides a buffer named &LBUF
which you may for this purpose.

len
Length of the buffer indicated by 'adr'. The maximum allowed
length is 256. (The length of &LBUF is 80.)

EXPECT will deposit up to 'len' characters in the buffer.


Unlike the FigFORTH word EXPECT, it will NOT deposit NULLs
after the last character.
init
410w
1
Length of initial text in buffer. If init=0, EXPECT reads a
completely new line. If init>0, EXPECT considers the buffer
to contain linit' characters, and displays that many
characters on the LCD before beginning to read input.

initc
Initial position of cursor.

If initc=0, EXPECT scrolls the cursor through the line from


tne beginning to the end, stopping when it reaches the end or
when the user presses any key.

If 0<initc<init, the cursor is placed in position (initc-1),


origin 0. For example, if initc=3, the cursor is placed in
position #2 (over the third character in the buffer).

If initc>=init, the cursor is placed just after the last


character in the buffer.
If initc>26, EXPECT cannot position the cursor without
scrolling the beginning of the line off the left edge of the
LCD. In this case it scrolls the line as much as necessary to
bring position (initc-1) under the cursor. It positions the
cursor in the right half of the LCD (if (initc-1) is near the
end of the text) or in the approximate center of the LCD (if
not).

(c) 1981 Friends Amis, Inc. 3-9 3 September 81


THE HHC KEYBOARD

eol
Address of a word written to detect the end-of-line (EOL)
character.
EXPECT calls this EOL word each time a character is read from
the keyboard. EXPECT finishes editing the line when the EOL
word finds an EOL character.
The linkage to the EOL word is:
(C B)
where C is a character that has been read from the keyboard,
and B is TRUE iff the character is an EOL character.
mode
The initial editing mode EXPECT should operate in. The
following symbolic constants represent the possible modes:
%OVR Overstrike. This is EXPECT's "normal" mode.
Each input character replaces the character under
the cursor, and causes the cursor to move right.
If the cursor is at end-of-line, each input
character is appended to the line.
The left- and right-cursor keys move the cursor; but
an attempt to move the cursor past the beginning or
end of the text will not succeed, and will make the
HHC beep.
%INSERT Insert. Each input character is inserted just before
the character under the cursor. All following
characters are bumped one position to the right.
EXPECT returns to overstrike mode after receiving
one character.
The normal cursor is replaced by an "insert" cursor,
which looks like a filled-in rectangle with
alternate dots on and off.
If the cursor is at end-of-line, each input
character is appended to the line.
%DELETE Delete. The "cursor left" key deletes the character
to the left of the cursor; the "cursor right" key
deletes the character under the cursor. Any other
key is considered an error, and causes EXPECT to
beep.
The normal cursor is replaced by a "delete" cursor,
which looks like an outline of a rectangle, with the
interior clear,

(c) 1981 Friends Amis, Inc. 3-10 3 September 81


THE HHC KEYBOARD

EXPECT returns to overstrike mode after receiving


one character.

%LI Lock-insert mode. Identical to insert mode except


that EXPECT does not return to overstrike mode after
receiving one character.

%LD Lock-delete mode. Identical to delete mode except


that EXPECT does not return to overstrike mode after
receiving one character.
len'
Length of the text in the buffer when EXPECT finished
processing.
eolchar
The character which caused the EOL word to return TRUE. If
EXPECT stopped processing because the buffer was full,
l eolcharl is zero.

mode'
Editing mode that applied to the last character received from
the keyboard.

EXPECT Modes

Note that the "mode" parameter in a call to EXPECT sets only


the INITIAL mode of EXPECT, that is, the mode that applies to the
first keystroke processed. Each keystroke may change the mode.

As was explained above, "overstrike" is EXPECT's "normal"


mode of operation. "Insert" and "delete" modes each revert to
"overstrike" after processing one character. "Insert-lock" and
"delete-lock" modes do not.

The user can change EXPECT's mode from the keyboard as


follows:

The INSERT and DELETE keys put EXPECT in "insert" and


"delete" modes, respectively, for one keystroke. The key
sequences "INSERT, LOCK" and "DELETE, LOCK" put EXPECT in
"insert-lock" and "delete-lock" modes.
When EXPECT is in "insert-lock" mode, pressing INSERT again
will return it to "overstrike." When EXPECT is in "delete-lock"
mode, pressing DELETE again will return it to "overstrike."
When EXPECT is in "insert-lock" mode, pressing DELETE will
place it in "delete" mode for one character, after which it will
revert to "insert-lock." When EXPECT is in "delete-lock" mode,
pressing INSERT will place it in "insert" mode for one character,
after which it will revert to "delete-lock."

(c) 1981 Friends Amis, Inc. 3-11 3 September 81


THE HHC KEYBOARD

Example 1

Here is a simple example of how EXPECT may set up and


used.

HERE
: EOLWD (S C B )
&CR = ;
(P TRUE IFF C IS A CARRIAGE RETURN.)
== A(EOLWD) \ ADR OF EOLWD.

: CALL-EXPECT (S /MD MOM


ADR LEN )
&LBUF L'MIB \ A/L BUFFER
0 0 \ INIT INITC (NULL INITIAL
A(EOLWD) %OVR \ TEXT); EOL, MODE
EXPECT
2DROP \ DROP EOLCHAR & MODE'


(P CALL EXPECT & RETURN ADR/LEN OF DATA READ.)

This example contains two colon definitions. The first is an


EOL word that will be used by EXPECT. The second calls EXPECT and
returns the address and length of a line of text.

The symbolic constant A(EOLWD) has as its valae the address


of the definition of EOLWD. (Notice the HERE before ': EOLWD',
which stacks that address before EOLWD is compiled!)

A Variation: Getting the Address of EOLWD

An alternative way to write this code would be to omit 'HERE


•. . == A(EOLWD), and replace the reference to A(EOLWD) in CALL-
EXPECT with "X EOLWD". 'X is an immediate word that compiles an
in-line constant equal to the next word's tag, just as tree FORTH
word ' (tick) compiles an in-line constant equal to the next
word's PFA.

Example 2: Editing Text

Suppose we wanted to modify this code to perform a slightly


different function. We have a piece of text that we want to place
in the buffer before EXPECT is called; we want EXPECT to display
this text and position the cursor at the end of it, then allow
the user to back up the cursor in order to edit tne text.

(c) 1981 Friends Amis, Inc. 3-12 3 September 81


THE HHC KEYBOARD

We could accomplish this by redefining CALL-EXPECT like this:

: CALL-EXPECT (S --- ADR LEN )


\ MOVE INITIAL MESSAGE INTO BUFFER.
MSGPTR COUNT \ A/L OF MESSAGE.
&LBUF SWAP MOVE \ MOVE MESSAGE TO BUFFER.
\ CALL EXPECT.
&LBUF L'MIB \ A/L OF BUFFER,
MSGPTR C@ 0 \ INIT, INITC,
A(EOLWD) %OVR \ EOL, MODE;
EXPECT
2DROP \ DROP EOLCHAR & MODE'

(P CALL EXPECT & RETURN ADR/LEN OF DATA READ.)

Example 3: Changing the End-of-Line Character

Suppose we wanted to treat blank, as well as ENTER, as an


end-of-line character? We could do so by redefining EOLWD like
this:
HERE ==
: EOLWD (S C --- B )
DUP &CR = SWAP BL = OR ;
A(EOLWD)

(c) 1981 Friends Amis, Inc. 3-13 3 September 81


THE BBC KEYBOARD

KEY AND RELATED WORDS

When you need to do input a character at a time, you can ase


KEY just as you would in FORTH. The word ?KEY determines whether
a keystroke is waiting in the keyboard buffer.
Two other useful words for character input are ?LOCK and
?LOCK-KEY. ?LOCK returns a boolean indicating whether the lock
bit is on. ?LOCK-KEY returns the next character in the input
buffer, except that when the user has locked a character (by
pressing the LOCK key and then a character key), the word returns
the same character over and over until another key is pressed.

Note on Battery-Conserving Code

It is not good practice to write SNAP code that loops


indefinitely while testing for a condition. The place where this
sort of code comes up most often is in testing for a keystroke;
for example:

BEGIN
REPETITIVE-TASK
?KEY UNTIL
•••

This sort of loop is bad because it keeps the HHC'S CPU on


continuously while the HHC is not being used. This drains the
HHC's batteries. In the worst case, it can force the user to
recharge the batteries every few hours of use.
As an alternative to this sort of code, you can use the word
NAP to put the HHC "to sleep" for a specific length of time, or
until a keystroke becomes available, whichever occurs first.

The linkage to NAP is:

sec ticks NAP [c] b

"sec" and "ticks" are the number of seconds and ticks (256 ths of
a second) the HHC is to nap.
If a keystroke becomes available before the specified
interval expires, the nap ends immediately. "c", the value of the
keystroke, is stacked; "b" is TRUE.

If no keystroke becomes available before the specified


interval expires, the nap ends at the end of the interval. "c" is
not stacked; "b" is FALSE.

(c) 1981 Friends Amis, Inc. 3-14 3 September 81


THE HHC KEYBOARD

Here is an example of code that uses NAP to perform a


repetitive task approximately every 1/13 second until a keystroke
becomes available:

BEGIN
REPETITIVE-TASK
0 27 NAP
UNTIL \ AT EXIT, CHARACTER IS ON STACK.

(c) 1981 Friends Amis, Inc. 3-15 3 September 81


THE HHC KEYBOARD

SIMULATING KEYBOARD INPUT FROM A PROGRAM

The HHC stores keystrokes that it has not vet processed in a


KEYBOARD BUFFER. You can look ahead at the contents of this
buffer before you do a KEY or LOCKKEY, and you can put characters
into the buffer, so that your program, in effect, is pressing
keys on the keyboard.

Structure Of the Keyboard Buffer

The keyboard buffer is addressed by the symbol KQ; it is 8


bytes long. The HHC places the first character typed in the 7th
byte, the second in the 6th byte, etc. After the 8th character
typed has been placed in the 0th byte, the 9th character typed is
placed in the 7th byte (assuming the 1st character typed has been
read by the program), and so on.

The HHC maintains two pointers to the keyboard buffer. The


"store" pointer contains the offset (0 to 7) of the byte where
the next character typed on the keyboard will be stored; it is
one byte long, and is addressed by the symbol KQI. The "fetch"
pointer contains the offset of the byte where the next character
read by the program will come from; it is one byte long, and is
addressed by the symbol KQO.
For example, suppose you have just entered your program and
nothing has been typed yet. (This is an oversimplification, since
something had to have been typed for you to have gotten to your
program from the primary menu. The discussion of the process is
accurate, however.) The keyboard buffer and its pointers look
like this:
KQ
KQI
KQO

Now suppose you type in 3 characters, 'ABC'. Your program


does a KEY,so that you have input 3 characters, and your program
has read one. Now the buffer looks like this:

C B A KQ
KQI
KQO

You continue typing in the alphabet, and your program


continues reading characters. At some later time when you nave
typed the alphabet through J and your program has read it through
E, the buffer looks like this:

(c) 1981 Friends Amis, Inc. 3-16 3 September 81


THE HHC KEYBOARD

HGFEDCJI KQ
T KQI
I KQO

The Pushkey Buffer

The HHC has a second buffer, called a PUSHKEY BUFFER, which


it uses to hold characters that are "pushed" back into the input
stream by a program.

Whenever your program does a KEY or LOCKKEY, the HHC returns


any characters that are in the pushkey buffer before going to the
keyboard buffer. Thus, any characters you store in the pushkey
buffer will be read BEFORE characters typed in through the
keyboard, even if the keyboard characters go into their buffer
first.

The pushkey buffer is addressed by the symbol PKQ; it is 4


characters long. It is used as a LIFO queue (the last character
put in is the first taken out). The "bottom" of the buffer, where
the first character is pushed, is at PKQ; the "top," where the
last character may be pushed, is at PKQ+3.

A one-byte counter at PKCT indicates the number of characters


vs. already in the buffer. Its value may be 0 to 4. A value of 0
means the pushkey buffer is empty; 4 means the pushkey buffer is
full, and there is no more space for characters to be pushed into
it.

For example, if you push a '2', then a 'G' into the buffer,
the buffer looks like tnis:

2 G ......_ PKQ
PKCT = 2

The next KEY or LOCKKEY will get the 'G'; the one after that
will get the '2':

2PKQ
..... _ .....
PKCT = 1

..................M.....P
PKQ
PKCT = 0 (empty)

Operations On tne Buffers

(c) 1981 Friends Amis, Inc. 3-17 3 September 81


THE BBC KEYBOARD

TO INSPECT THE KEYBOARD BUFFER, compare the values of KQI and


KQO. If they are equal, the keyboard buffer is empty. If not, use
them to extract the contents of the keyboard buffer.
TO INSPECT THE PUSHKEY BUFFER, examine the pushkey pointer.
If it is 0, the pushkey buffer is empty. If it is not zero, use
it to extract the contents of the pushkey buffer.

TO STORE A CHARACTER AT THE TOP OF THE KEYBOARD BUFFER, so


that it will be the next character to come out: first, check to
make sure that the buffer is not full. Then move the value of KQO
backwards one location, and store the character to the location
that KQO now points to. (Remember to wrap KQO around to the
beginning of the buffer if moving it backwards moves it past the
end.)
Do NOT try to put a character into the "bottom" of the
keyboard buffer by storing into the location indicated by KQI and
then advancing KQI. If you do this, there is always a risk that
the device driver for the keyboard will get an interru p t and
store a character in the buffer between the time you fetch KQI
and the time you store it back. If that happens, your character
will overlay the one from the keyboard.

TO PUT A CHARACTER INTO THE PUSHKEY BUFFER, use the PUSHKEY


word:
Linkage????

Function Keys

The definitions of the three function keys are kept in an


area addressed by the symbol FUNDEF. The structure of the area
is:

OFFSET FROM
FUNDEF CONTENTS

0 Length of Fl definition in characters


1-13 Fl definition (up to 15 characters long)
16 Length of F2 definition in characters
17-31 F2 definition (up to 13 characters long)
32 Length of F3 definition in characters
33-47 F3 definition (up to 13 characters long)

The locations that contain the function key definitions are:

You can change the definition of a function key oy storing


appropriate values into the that function key's definition area.

(c) 1981 Friends Amis, Inc. 3-18 3 September 81


THE HHC KEYBOARD

("Typing" a Function Key)

You can "type" a function key by storing it in the keyboard


buffer, but the preferred way to do it is to store the length of
the desired key's definition in the byte at FUNCT, and the offset
of the definition (1, 17, or 33) in the byte at FUNY.

When you "type" a function key in this way, your program will
read it before any of the characters in the keyboard buffer or the
pushkey buffer.

You cannot "type" a function key by storing it into the


pushkey buffer. If you try, your program will read the ASCII code
that represents the function key (15H, 16H, or 17H) instead of the
function key's current definition.

(c) 1981 Friends Amis, Inc. 3-19 3 September 81


THE LCD DISPLAY & BEEPER

The HHC's primary output device is the liquid crystal display


(LCD) on its front panel.
The LCD is a matrix of dots, 159 wide x 8 high, which may be
turned on (black) and off (clear) in any comoination. A high-
level set of I/O words for the LCD allow you to do ASCII I/O. In
this context the LCD consists of 26 character positions, each 5
columns wide and followed by one empty column, with 3 extra
columns of dots at the right end.
The dot columns are addressed left to right as #0 through
#158. The character positions are addressed left to right as #0
through #25.
The LCD has a CURSOR which is normally displayed as a solid
black rectangle flashing in a character position. The cursor may
be turned on and off by the program, using the words START.CURSOR
and STOP.CURSOP. It may be positioned on the display with POSN.
Its displayed representation may be redefined (see below).
The LCD's character set is roughly a superset of ASCII. It is
described in detail in one of the appendices to this book.

(c) 1981 Friends Amis, Inc. 4-1 3 September 81


THE LCD DISPLAY & BEEPER

I/O WORDS

You may approach display I/O on several levels. We will


describe each level, beginning with the highest.

EMIT

You may use EMIT to display characters on the LCD as though


it were a little dumb video display with horizontal scrolling.
The HHC's EMIT allows you a number of unusual controls over
the way each character is displayed. You can display a character
in inverse video; with flash (blink); from an alternate, program-
defined character set; with a floating accent mark; or in any
combination of these modes.
You control the display mode of a character by turning on
bits in the high-order byte of the parameter that you pass to
EMIT (which contains the character to be displayed in the low-
order byte). The functions of the bits in this byte are:
SYMBOLIC
BIT CONSTANT FUNCTION
80H CNEG 1=> reverse video, 0=> standard.
40H CFLSH 1=> flash character, 0=> no flash.
20H CQMK 1=> flash character alternating with I s
0=>
no flash.
10H CALT 1=> use alternate character set, 0=> use
standard set.
8-1 aM111 ..1111
value determines what floating accent be
superimposed on the character. See details
below.

For example, you can display a character in inverse video


like this:

C@ \ THE CHARACTER.
CNEG \ INVERSE VIDEO FLAG.
SQUISH EMIT \ COMBINE & OUTPUT.

The value of the low-order nybble of the nigh-order byte


represents a FLOATING ACCENT which will be superimposed on the
character as it is displayed.
The image of a floating accent is obtained from a table which
your application program must define. Details on how to define a
floating accent table are given in a later section.

(c) 1981 Friends Amis, Inc. 4-2 3 September 81


THE LCD DISPLAY & BEEPER

"Random Access" Output To the LCD

The HHC forms an image on the LCD by displaying the contents


of two buffers, each of which contains one byte per character
position. You can place a character in any position (in effect,
"random access" output) by storing data directly into these
buffers.
The two buffers are the CHARACTER DISPLAY BUFFER, containing
ASCII characters, and the CHARACTER CONTROL BUFFER, containing
control bytes.

You can store characters in the buffers with the aid of the
CHARBUF and CTRLBUF words:
n CHARBUF adr
n CTRLBUF adr

Each word accepts a character position (0 to 25) and returns the


address of the corresponding byte in the appropriate buffer.

After modifying the contents of the buffers, you must execute


UPDISP to make the HHC update the LCD.

For example, to display an inverse video character with an


umlaut in position 18 of the LCD:

C@ \ THE CHARACTER
18 CHARBUF C! \ STORE IT IN CHARACTER BUFFER
3 CNEG OR \ THE CONTROL BYTE
18 CTRLBUF C! \ STORE IT IN CONTROL BUFFER
UPDISP \ UPDATE DISPLAY

Note that you can find out what is on the LCD by FETCHING
from the addresses given by CHARBUF and CTRLBUF. For example, to
capitalize the character in position #0:

0 CHARBUF C@ \ PUSH CHARACTER


L>U \ FORCE UPPER CASE
0 CHARBUF C! \ STORE IT BACK
UPDISP \ UPDATE DISPLAY

Graphics Output

At the dot level, the image on the LCD is determined by the


contents of the LCD display buffer. This is a memory-mapped area
159 bytes long, each byte controlling the contents of one dot
column in the LCD. The buffer is addressed by ythe word DSPLY.

(c) 1981 Friends Amis, Inc. 4-3 3 September 81


THE LCD DISPLAY & BEEPER

The low-addressed byte of the display buffer represents the


leftmost dot column in the LCD; the high-addressed byte
represents the rightmost column. Within each byte, each biz
represents one dot; the highest-order bit represents the bottom
dot and the lowest-order bit represents the top dot. In each
bit, a 1 makes the dot dark, and a 0 makes the dot clear.

You can manipulate the LCD buffer, and thus the dots, with
the word DMOVE. DMOVE works like MOVE, but performs special
processing necessary to move information into and out of the LCD
display buffer. Its linkage is:

from to len DMOVE

"from" is the address of an area containing one or more bytes of


data to be moved to the LCD buffer; "to" is the address in the
buffer the data is to be moved to; "len" is the number of bytes
to be moved.

For example, to update dot columns 79-158 (approximately the


right half of the LCD) from a location addressed by RHALF, you
could execute the following code:

RHALF DSPLY 79 + 80 DMOVE

You need not execute UPDISP to update the display.

Note that you can use DMOVE to read the contents of the LCD,
as well as to write it. Simply specify a "from" address that is
in the LCD buffer, and a "to" address that is elsewhere.
CAUTION: before starting to use DMOVE, clear the LCD b y
executing the following code:

LCD.CR \ CLEARS LCD AT 'DMOVE' LEVEL.


STOP. CURSOR \ MAKES CURSOR INVISIBLE.
26 BUFPOSN C! \ MOVES CURSOR TO CHAR POSN 26.

When you are ready to begin writing characters to the LCD


again (e.g., with EMIT), execute the following code:

LCD.CR \ CLEARS LCD AT 'DMOVE' LEVEL.


START .CURSOR \ MAKES CURSOR VISIBLE AGAIN.
CR \ MOVES CURSOR BACK TO LEFT EDGE.

NOTE: '26 BUFPOSN C!' moves the cursor into character


position 26. This places is half in dot columns 156-158, and nalf

(c) 1981 Friends Amis, Inc. 4-4 3 September 81


THE LCD DISPLAY & BEEPER

off the LCD. With the cursor in this position, dot columns 156-
158 are NOT available for your use. This is necessary because (1)
'gm. an HHC bug makes it impossible to write to dot columns under the
cursor, and (2) it is impossible to move the cursor entirely off
the LCD.

Program-defined Blips

When you are using character-oriented words such as EMIT to


write to the LCD, neither the cursor, nor any character, will
ever appear in dot columns 156-158. In this situation you can use
DMOVE to put your own, program-defined "blips" in these columns.
If you use DMOVE to create your own blips, you must be
careful to refresh the blips whenever EMIT causes the LCD to
rotate. Although columns 156-158 never contain characters, they
DO rotate along with the rest of the display.
When the display rotates left (the usual case), clear columns
156-158 first, so that the blips will not rotate into columns
150-152. After the rotation, restore the blips to columns 156-158
(which will initially be empty).
When the display rotates right the blips need not be cleared,
since they will rotate off the LCD. Simply restore them after
rotation.
CAUTION: DMOVE is not compatible with the higher (character-
oriented) levels of LCD words when used to modify columns #0 to
#152; that is, in all cases except when used to display user-
defined olips. Do not try to mix DMOVE with character I/O words.
Clear the LCD immediately before switching from character-
oriented I/O to DMOVE, or vice versa, as described above.

CAUTION: EXPECT uses columns 136-153 to indicate a line of


text that overflows the LCD. Avoid using these columns in a way
that might conflict with EXPECT.

(c) 1981 Friends Amis, Inc. 4-5 3 September 81


THE LCD DISPLAY & BEEPER

ALTERNATE CHARACTER SETS

The HHC allows you to define your own character set for
displaying characters on the LCD, To define your own character
set, you must (1) create a character translation table containing
a dot-pattern definition for each displayable character, and (2)
inform the HHC of its location.

Defining a Character Translation Table

The HHC displays each character in a 5x8 matrix on the LCD.


Thus, a complete character set table consists of 192 5-byte
entries. The entries define the dot patterns to be displayed for
each character.
Each entry consists of one byte for each column of dots that
makes up the character being defined. The bytes, from first to
last, represent the dot columns from left to right.

Each byte consists of one bit for each dot that makes up the
column being defined. The bits, from high-order to low-order,
represent the dots from bottom to top.
For example, consider the standard character set used in the
simulator as of this writing. Entry #20H, representing "space,"
is all zero. The following 5-byte entry, representing 'I', is

00000
o**oo
o**oo
o**oo
00 DE DE 00 00 , producing: o**oo
oocoo
o**oo
o**oo

The entry representing 7' is


00000
00000
0000 *
000*o
40 20 10 08 04 , producing: oo*oo
o*000
*0000
00000

The entry representing 'B' is


00000
****0

(c) 1981 Friends Amis, Inc. 4-6 3 September 81


THE LCD DISPLAY & BEEPER

o*oo*
o*oo*
vivo 82 FE 92 92 6C , producing: 0***0
o*oo*
o*oo*
****o

Notice that the top row of dots is not used for ordinary
characters in the standard character set; it is reserved for
accent signs.
The standard baseline (the line the letters appear to rest
on) is at the bottom row of dots. "Lower case letters" are
actually small caps, so none of the standard characters have
descenders.

The standard X-height (the height of a lower case letter) is


5 rows of dots.
A CHARACTER TRANSLATION TABLE WITH A NONSTANDARD DOMAIN: if
binary values through OBFH are not going to be displayed, the
table need not be a full 192 characters long. The programmer
bears the risk that his code will send an unexpected high value
to the LCD, and display random data beyond the end of the table.

A CONVENIENT HELP WORD: the following word is a useful help


for defining an entry in a character set table and accent table:

H: ,CHAR \ COL1 COL2 COL3 COL4 COLS


0 5 DO I ROLL C, -1 +LOOP

It is used like this:

HEX
00 00 00 00 00 ,CHAR \ SPACE
00 DE DE 00 00 ,CHAR '•
00 06 00 06 00 ,CHAR "
• • •

(NOTE: 'H:' defines a word in such a way that the definition


is available when you compile your code (in the simulator or the
cross-compiler) but not when you execute it (in the simulator or
the HHC). Its function is identical to that of a macro in a
conventional compiled or assembled language.)

Informing the HHC of the Table's Address

To make your table the standard character set translation


table, store its address at CHVECTI:
my-char-table CHVECT1 I

(c) 1981 Friends Amis, Inc. 4-7 3 September 31


THE LCD DISPLAY & BEEPER

Similarly, to make your table the alternate character set


translation table, store its address at CHVECT2.
You can display a character from the alternate character set
translation table by using EMIT with the CALT bit turned on in
the high-order byte.

When you change the character translation table and/or accent


table, your change will become visible as soon as the LCD is
modified (e.g., by an EMIT that causes it to rotate).

Restoring the Standard Table

To restore the original LCD character set as the standard


character set, store CHAR.DOT.PATTERN in CHVECT1:

CHAR.DOT.PATTERN CHVECT1 !

Similarly, to restore the original LCD character set as the


alternate character set, store CHAR.DOT.PATTERN in CHVECT2.
All the character sets are restored to their original
settings by aCIZAR.

Defining a Floating Accent Translation Table

Just as you can define your own translation table for


HHC's character set, you can define a translation cable for the
floating accents.

The accent table has the same structure as the character set
table, except that it has a maximum of 16 entries. Each entry
defines a character that will be superimposed on a text character
when that text character is displayed with the appropriate accent
bits turned on in the high-order byte.
Although there is no default floating accent table, there is
a set of standard meanings for the accent-character bit values:

0 no accent
1 accent agout
2 accent grave
3 umlaut
4 circumflex
3 inverted circumflex
6 tilde
7 bar

(c) 1981 Friends Amis, Inc. 4-8 3 September 81


THE LCD DISPLAY & BEEPER

Informing the HHC Of the Accent Table's Address

To make your accent table the currently-used accent table,


store its address at ACVECT. There is no way to designate differ-
ent accent tables for the standard and alternate character sets.
Since the HHC has no default floating accent table, there is
nothing analogous to CHAR.DOT.PATTERN that you can restore into
ACVECT. You can only store zero into ACVECT to "undefine" your
accent table.

A Note on Alternate Character Sets and the Printer

If you BIND the printer to the LCD so that whatever output is


sent to the LCD appears on the printer as well, then any
alternate character set you define for the LCD will affect the
printer too.
Control bytes will also affect the printer when it is bound
to the LCD, provided they make sense for it. For example, a
control byte request for a floating accent or inverse display
will be obeyed by the printer; a request for flashing characters
will be ignored.

Defining an Alternate Cursor Pattern

The HHC's standard cursor pattern is a 5x8 block of dots


that are all black. The cursor blinks to permit the user to see
the character underneath it.

You can create an alternate pattern for the cursor by


defining a 5-byte area in the same format as an entry in an
alternate character set table.
To instruct the HHC to use an alternate cursor pattern,
store the pattern definition's address in the location CURSOR:

YOUR-CURSOR-DEFINITION ^ CURSOR 1

The alternate cursor pattern will become visible tne next time a
high-level I/O operation is done on the LCD.
To restore the standard cursor oattern, store CURDOTS in
CURSOR:
CURDOTS CURSOR 1
Again, the cursor pattern will become visible the next time a

(c) 1981 Friends Amis, Inc, 4-9 3 September 81


THE LCD DISPLAY & BEEPER

high-level I/O operation is done on the LCD.

(c) 1981 Friends Amis, Inc. 4-10 3 September 81


THE LCD DISPLAY & BEEPER

ROTATION MODE

You can change the way in which the LCD responds to overflow
(EMITing a character when the cursor is past the last character
position) by storing a value into the byte at (ROTMODE).

Meaningful values you can stored at (ROTMODE) are:

0: "Fill mode." After the LCD is full, the HHC erases


everything and starts filling the LCD again, left to
right.

l: "Rotate mode." after the LCD is full, the HHC shifts


characters off the left end to make room for more
characters on the right. (This is the HHC's normal
rotation mode.
2: "Rotate and fill mode." Same as rotate mode except that
carriage returns are ignored. The HHC never clears the
LCD.

Note that rotation mode is NOT reset by a CLEAR.

(c) 1981 Friends Amis, Inc. 4-11 3 September 81


THE LCD DISPLAY & BEEPER

THE STOP/SPEED KEY

The STOP/SPEED key works by storing a value into a byte


addressed by the symbol 'SPEED'. You can change the speed of the
HHC's menu rotation, LCD rotation, and keyboard auto-repeat by
storing a different value in this byte.

The meaning of the byte at SPEED is:

value STOP/SPEED setting

10 1 (slowest setting)
9 2
8
7 4
6
5 6
4 7
3 8
2 9
1 0 (fastest setting)
0 faster than fastest STOP/SPEED setting

(c) 1981 Friends Amis, Inc. 4-12 3 September 81


THE LCD DISPLAY & BEEPER

SLAVING PERIPHERALS TO THE LCD

FLAME-ON

In applications which do not make explicit use of


peripherals, it is a common practice to attach all peripherals
that are connected to the HHC and slave them to the LCD. Then
output that is sent to the LCD will be sent to each peripheral as
well.
The word FLAME.ON performs this attach-and-slave service.
It is generally executed during the initialization of an
application. When FLAME.ON is executed it scans the HHC bus for
all peripherals that are connected, attaches them, and slaves
them to the LCD.
FLAME.ON will attach a device that is physically connected to
the HHC whether or not the device is turned on (through the I/O
menu). Until a device is turned on, however, it will not actually
be slaved to the LCD. If a device is connected to the HHC when
FLAME.ON is executed, but is not turned on until later, it will
be slaved to the LCD when it is turned on; if it is later turned
off, it will be un-slaved again. (But the reverse is not true;
you cannot slave a device to the LCD by connecting the device
after an application has been initialized. Indeed, if you connect
a device to the HHC at any time, the HHC operating system will do
a hard clear!)

Vectored I/O; (EMIT)

A different technique makes it convenient for you to slave a


specific device to the LCD. You can slave and un-slave tnis
device during execution if you wish to do so.

The technique makes use of the words (EMIT) and 'EMIT. (EMIT)
is the HHC's "inner EMIT" word, which performs all the functions
normally associated with EMIT. 'EMIT is the "EMIT vector"
variable, which normally contains the tag of (EMIT).

The sole function of EMIT is to call the word identified by


'EMIT. Since this is normally (EMIT), EMIT normally performs all
the functions of (EMIT) -- that is, it writes a character to the
LCD with the usual sort of character generation, rotation, etc.
You can change the function of EMIT simply by changing the
value of 'EMIT. This is called REVECTORING the word EMIT. EMIT is
described as a VECTORED I/O WORD.
Here is an example of how to revector EMIT so that it writes
a character to a peripheral (presumably attached and opened
elsewhere) AND disIDlays the character on the LCD with (EMIT).

(c) 1981 Friends Amis, Inc. 4-13 3 September 81


THE LCD DISPLAY & BEEPER

: MY-EMIT (S C --- ) \ REPLACEMENT FOR EMIT


DUP MY-ECB ROP DROP \ WRITE TO PERIPHERAL.
(EMIT) ; \ WRITE TO LCD.

: TURN-ON-MY-EMIT (S ) \ REVECTOR EMIT


'X MY-EMIT 'EMIT !

: TURN-OFF-MY-EMIT (S ) \ UN-REVECTOR EMIT


'X (EMIT) 'EMIT ! ;

TURN-ON-MY-EMIT stores the tag of MY-EMIT at 'EMIT. TURN-OFF-


MY-EMIT stores the tag of (EMIT) at 'EMIT.

While 'EMIT contains the tag of MY-EMIT, any call to EMIT


will result in a call to MY-EMIT rather than (EMIT). MY-EMIT will
(1) write the character on the stack to the device addressed by
MY-ECB, and (2) display the character with (EMIT), as usual.

The convenient thing about vectored I/O is that adding it to


an existing program is completely "clean." No matter how many
places EMIT appears in the program, revectoring changes EMIT's
function globally. At the same time, redirected I/O can be turned
on or off, at run time, by executing a single word.

Cc) 1981 Friends Amis, Inc. 4-14 3 September 81


THE LCD DISPLAY & BEEPER

BLIPS

BLIPS are stationary indicators which may be displayed below


the text line on the LCD display. There is a fixed set of blips
with fixed meanings.
The blips may be turned on and off by changing the HHC's BLIP
MASK with the words ANDBLIP and ORBLIP.
The following words are symbolic constants which should be
used to control the bits in the blip mask. On the LCD, the
lowest-order bit is represented on the left, and the highest-
order bit on the right.

Value
Word (hex) Meaning

BATBLIP 01 Battery is low.


SHFTBLIP 02 Keyboard in SHIFT (or SHIFT LOCK)
state.
LOCKBLIP 04 Keyboard in LOCK state.
2SHFTBLIP 08 Keyboard in SECOND SHIFT state.
RECBLIP 10 EXPECT is in delete mode.
MEMBLIP 20 EXPECT is in insert mode.
ALRMBLIP 40 An alarm is "ringing."
RUNBLIP 80 Carrier detect on modem.

It is not good practice to use most of the blips, since the


HHC's intrinsic software will continue to use them as though it
had exclusive control. Thus the olips will not be accurate
reflections of either their standard meanings or your non-
standard ones. This caution applies with somewhat less force to
RECBLIP and MEMBLIP, which are used only by EXPECT, and taus are
used only by application programs.

NOTE: there are three columns of dots at the right edge of


the LCD matrix that are not used to display characters; they may
be used to display additional, user-defined "blips." See the
description of LCD graphics, below, for details.

(c) 1981 Friends Amis, Inc. 4-15 3 September 81


THE LCD DISPLAY & BEEPER

BEEPS AND SQUEAKS

The HHC has a small built-in speaker which it may use to make
various kinds of noise.

A BEEP is a noise of fixed pitch and duration which is


analogous to the bell on a conventional terminal. You can create
a beep by executing the word BEEP, or by sending a 07H (control-
G) to the LCD.

A SQUEAK is a noise of controllable pitch and duration. It is


made by the I/O word SQUEAK. (See details in glossary.)

(c) 1981 Friends Amis, Inc. 4-16 3 September 31


THE VIRTUAL FILE SYSTEM

The VIRTUAL FILE SYSTEM is a part of the nucleus that stores


data in RAM. From a software point of view, it is a random access
file system; thus the name, "virtual file system."

The virtual file system is a convenient way of storing small


amounts of data, including executable programs. Because of the
HHC's low-drain CMOS RAM, it can preserve data when the HHC is
"turned off." It is available to every HHC user without the
purchase of any peripherals, although a minimal HHC can offer
only about 1.25K of storage.

VIRTUAL FILE CONCEPTS

The virtual file system can store any number of files. A file
may contain up to 8K characters (counting storage-format
overhead) and an unlimited number of records, subject to the
limit of the amount of memory that is available. Any record may
be any length from 0 to 255 characters. (The 8K limit is imposed
by the size of a Programmable Memory Peripheral, not by the file
system's data structure. At some point in the future the limit
will increase to 16K.)

Each file is identified externally by a name, which may be


from 1 to 255 characters long. The name may consist of any
combination of characters. (Applications should impose reasonable
requirements for a well-formed file name.)

Each file begins with a HEADER which contains the file name
and various housekeeping information such as the length of the
file. This is followed by the data held in the file.

All files are random-access. If records are defined, they are


numbered sequentially with origin 0. Any record may be read or
written by number.

Since files are stored contiguously in RAM, writing to a file


generally causes other files (and other records in the same file)
to move up or down in RAM. Because of this, you should never
assume that a record is in the same place from one read or write
to the next. Always do a new I/O operation to get the record's
current address. For the same reason, never use an absolute
address as a pointer to data in a file (e.g., from an index
elsewhere in the file); use a record number, or some other
invariant record identifier, and an offset from the beginning of
the record to the data.

(c) 1981 Friends Amis, Inc. 5-1 3 September 81


THE VIRTUAL FILE SYSTEM

FILE TYPES

Virtual files may have certain FILE TYPES which descrioe


their contents in various ways. A file may have any combination
of types, or it may have none.

A file with the INVISIBLE type is not shown on the file


editor's menu. The HHC software may use it, since files are
identified by name in calls to the virtual file handler (see
OPEN, below), but the user cannot get at the file, since it has
no menu number. The clock-secretary's calendar file is one
example of an invisible file.

The second type a file can have is the TEMPORARY type. A


temporary file is fair game for deletion by any application
program that wants to increase the amount of free file space. In
a future release of the HHC system, temporary files may be
deleted automatically at each hard clear. (Note, files containing
no records, and files containing no records with non-zero length,
may also be deleted by CLEAR.)

The third type a file can have is the EXECUTABLE type. An


executable file contains machine code and/or SNAP code. It is not
divided into records. (Note: to date there is no software for
creating or executing an executable file.)

The fourth type a file can have is the TEXT type. A text file
is divided into records (lines), each of which is 0-255
characters long. (Details of file format are given below.) The
lines are generally expected to consist of ASCII text. The file
editor permits the user to edit a text file; it does not Permit
him to execute any other kind of file, except for record 4-1
(which contains the file name).

(c) 1981 Friends Amis, Inc. 5-2 3 September 81


THE VIRTUAL FILE SYSTEM

VIRTUAL FILE OPERATIONS

The HHC allows I/O to only one virtual file at a time. At any
time, the file that virtual I/O words will access is called the
CURRENT FILE.

Since all I/O is random-access and is very fast, this is a


detail of the linkage rather than a restriction.

OPEN: Opening an Existing File

To select an existing file as the current file, execute OPEN.


The linkage is:

adr len OPEN b

"adr len" are the address and length of a file name. "b" is TRUE
if the file was opened successfully, and FALSE if not.

OPEN fails when the requested file does not exist.

MAKE: Creating and Opening a New File

You cannot select a new (previously non-existent) file with


OPEN. For that purpose you must use MAKE. The linkage to MAKE is:

adr len MAKE b

"adr len" are the address and length of a file name. "b" is TRUE
if the file was created and selected successfully, and FALSE if
not.

Note that there is no harm in OPENing a file immediately


after MAKEing it. Thus, it is reasonable to MAKE a file in one
part of a program, and OPEN WRITE WRITE WRITE in another
part, without bothering to test for a brand new file that need
not be OPENed.

NOTE: the HHC gives no protection against MAKEing multiple


files with the same name. Therefore if the existence of a file is
in doubt, you should always try to OPEN it before MAKEing it.

READ: Reading a Text File

(c) 1981 Friends Amis, Inc. 5-3 3 September 81


THE VIRTUAL FILE SYSTEM

You fetch a record from the current file with READ. The
linkage is:

adr len recnum READ len' l (success}


adr len recnum READ 0 {failure}

"adr len" are the address and length of a buffer where READ is to
deposit the record. "recnum" is the number of the record being
requested.
If READ is successful, "len" is the length of record as it
was deposited in the buffer. If the record is no longer than
"len," then the whole record is moved to "adr," and "len" is the
length of the record. If the record is longer than "len," then it
is truncated to length "len," and "len'" equals "len." You get no
warning that the record has been truncated.

READ fails if record "recnum" does not exist.

WRITE: Replacing an Existing Record In a Text File

You replace an existing record in the current file with


WRITE. The linkage is:

adr len recnum WRITE b

"adr len" are the address and length of the record to be written.
(Note, it may be any length up to 255 characters; it may be
longer than the record it replaces.) "recnum" is the number of
the record to be replaced.

If WRITE is successful, "b" is TRUE; if not, "b" is FALSE.

WRITE fails if record "recnum" does not exist, or if the new


record is longer than the old one and there is not enough room in
the virtual file space to hold it.

INSERT: inserting a New Record in a Text File

You insert a new record in the current file with INSERT. The
linkage is:

adr len recnum INSERT b

"adr len" are the address and lengtn of the record to be

(c) 1981 Friends Amis, Inc. 5-4 3 September 81


THE VIRTUAL FILE SYSTEM

inserted. It may be any length up to 255 characters. "recnum" is


the number of the existing record BEFORE which the new record
should be inserted.

The inserted record becomes record number "recnum;" the


record that was previously "recnum" becomes "recnum+1," and so
forth.

If record "recnum-l" does not exist, INSERT inserts the new


record at the end of the file.

INSERT fails if there in not enough room in the virtual file


space to insert the record.

If INSERT is successful, "b" is TRUE; if not, "b" is FALSE.

REC-CNT and INSERT: Appending a New Record To a Text File

The word REC-CNT returns the number of records in the current


file:

REC-CNT n

The best way to insert a record at the end of a file is to


use the number of records (which is 1 greater than the record
law number of the last record) as "recnum:"

adr len REC-CNT INSERT b

Recall that any non-existant record number will add a record


at the end of a file. Using REC-CNT guarantees a non-existant
record number no matter what the size of the file is, and also
makes the code's intention clear.

DELETE: Deleting a Record From a Text File

You delete a record from the current file with DELETE. The
linkage is:

recnum DELETE b

"recnum" is the number of the record to be deleted. The following


record (formerly number "recnum+1") becomes number "recnum," the
former "recnum+2" becomes "recnum+1;" and so forth.

Now If DELETE is successful, "5" is TRUE; if not, "b" is FALSE.

(c) 1981 Friends Amis, Inc. 5-5 3 September 81


THE VIRTUAL FILE SYSTEM

DELETE fails if record "recnum" does not exist.

?FILE and REVISE: Allocating Space In a Non-Text File

The I/O words described above -- READ, WRITE, and so on --


work only with text files. It is meaningless to apply READ to a
non-text file, for example, because the function of READ is to
read a record, and non-text files have no records by definition.
Suppose you have just created a non-text file, and you need
to place data in it. You first must find the address of the file
header. You do this by using ?FILE. The format of ?FILE is:

adr len ?FILE [adri] b

Here, "adr len" are the address and length of the file's name.
If the file exists, "adr" is the address of the first byte in
its header, and "b" is TRUE. If the file does not exist, "adr'"
is absent and "b" is FALSE.

If ?FILE finds the file, execute the following code to


convert the "adr" returned by ?FILE to the ceiling of the header
(which is the address of the first data byte, if any):

4 + COUNT

Once you have got the ceiling of the file header, you must
allocate enough file space for the data. You do this with REVISE.
The format of REVISE is:

adr len REVISE b

"adr" is the ceiling of the header; "len" is amount of data you


want to make scace for, in bytes. "b" indicates success or
failure of the operation. REVISE fails when tnere is not enough
space to allocate the space.

If REVISE succeeds, you can place data in the file with MOVE
or any other appropriate method.

More REVISE: Adding and Deleting Space In a Non-Text File

You can also use REVISE to expand a non-text file. This is


because the actual function of REVISE is to open up a "hole" in a

Cc) 1981 Friends Amis, Inc. 5-6 3 September 81


THE VIRTUAL FILE SYSTEM

file by moving everything after the "hole" a specified number of


bytes upward and updating all affected pointers.
leo
To use REVISE in this manner, you only need to change the
value of "adr" so that it points at the spot where you want to
open up a hole, rather than to the ceiling of the file header.
To allocate space in a new file (which initially contains
zero bytes of data), use the ceiling of the file header as "adr."
(See the file format description below.)
To delete part of a non-text file, simply give REVISE a
negative value for "len." It will delete "len" bytes from the
file, beginning at "adr."
CAUTION: REVISE does no validity checking on the values of
"adr" and "len." If you give it invalid values, it may destroy
the structure of the file space, or even destroy data that is
outside the file space.
CAUTION: bear in mind that the location of one file can
change when another file is made longer or shorter. If you are
working with several files, ALWAYS locate each file with ?FILE
each time you open it. Do not assume that an address obtained the
last time it was open is still valid.

CFILE and DELETE-FILE: Deleting a File

You delete a file with DELETE-FILE. The linkage is:

filenum DELETE-FILE b

"filenum" is a number that the HHC uses internally to identify


a file. "b" is TRUE if the file was successfully deleted, and
FALSE if not.

You can fetch the file number of the current file with CFILE:

CFILE filenum

Thus, to delete a file, you should (1) open it (making it the


current file), (2) execute CFILE to get its file number, (3)
execute DELETE-FILE to delete it, and (4) process DELETE-FILE's
return code.

Renaming a File

(c) 1981 Friends Amis, Inc. 5-7 3 September 81


THE VIRTUAL FILE SYSTEM

Every file has a "record #-1 (number minus 1)" which contains
its name. To rename a file, simply change the contents of this
record. You can do this from the file editor or from your own
program.

For example, here is SNAP code to change the name of the


current file to the value of a string named ITS-NEW-NAME:

ITS-NEW-NAME COUNT -1 WRITE

You need not create record #-1 in a new file; the system creates
it automatically.

Every file has a record #-1 -- even non-text files, which


otherwise have no record structure (see below).

GET-TYPE: Testing and Setting File Type

You can test and set the type of the current file by storing
a byte at the address given by GET-TYPE. The linkage is:

GET-TYPE adr

The byte stored at GET-TYPE consists of bit flags for the


various file types you can set. If a bit flag is on, the file
has that type. The bit flags are represented by the following
symbolic constants:

%BASIC
For a Microsoft Basic program file. (Basic source
programs are stored in tokenized form rather than as
pure ASCII text.)

%EXECUTABLE
For "executable." The file contains an executable SNAP
program.
%TEMPORARY
For "temporary," In a future version of the HHC system,
the file will be deleted at the next hard CLEAR. (Note
that a non-temporary file will also be deleted at CLEAR
if it contains no records, or if it contains no non-
null records.)

%TEXT
For "text." The file contains text. This is the only
tyoe of file that the file editor will ocerate on
(except for the renaming operation; see below). Notice

(c) 1981 Friends Amis, Inc. 5-8 3 September 81


THE VIRTUAL FILE SYSTEM

that %TEXT and %EXECUTABLE are logically exclusive.

For example, to make the current file invisible, execute:

%INVISIBLE GET-TYPE C!

You can OR these symbols together to set any combination of types


that makes sense:

%INVISIBLE %EXECUTABLE OR GET-TYPE C!

You can OR them into the value of GET-TYPE to add a new type to
those already set:

GET-TYPE C@ %TEMPORARY OR GET-TYPE C!

Executing '0 GET-TYPE C!' resets ALL the types; that is, it
makes the current file non-invisible, non-temporary, non-
executable, and non-text.

LOOKUP: Look Up N'th File

You can get the name of the n'th file in the current file
space with LOOKUP. The linkage is:

n LOOKUP (al b

where "n" is the sequence number of the desired file. If such a


file exists, "a" is the address of the first byte of the file,
(i.e., the first byte of the "length of this file" field), and
"b" is TRUE. If no such file exists, "a" is absent and "b" is
FALSE.

(c) 1981 Friends Amis, Inc. 5--9 3 September 81


THE VIRTUAL FILE SYSTEM

The Virtual File Editor

An application program can call the virtual file editor by


executing EDIT-FILE. This lets the user of your application edit
a file without leaving the application, returning to the
application when done.

The linkage to EDIT-FILE is fully described in the glossary.

Note that when you call EDIT-FILE you can specify your own
end-of-line and end-of-edit characters. This lets you modify the
behavior of EDIT-FILE to fit situations where RETURN as an end-
of-line character would not make sense.

(c) 1981 Friends Amis, Inc. 5-10 3 September 81


THE VIRTUAL FILE SYSTEM

THE VIRTUAL FILE SPACE

There are two virtual file spaces: intrinsic and extrinsic.

The INTRINSIC VIRTUAL FILE SPACE is located between


approximately 200H and 1FFFH. The first 1.5K is in built-in RAM;
the remainder is in RAM capsules (or else it does not exist).

Virtual files grow up from the bottom of the virtual file


space; the temporary stack, which shares the space, grows down
from the top. When the two meet, both are considered full. Thus
the amount of space available for virtual files is a function of
(1) the amount of RAM capsule space the user has added to his
machine, and (2) the amount of space taken up by the temporary
stack at any moment.

Typically the temporary stack takes about 0.25K. This leaves


about 1.25K for virtual files. Adding RAM capsules does nothing
to increase software's demands on the temporary stack, so in most
cases it will increase the space available for virtual files by
the amount of RAM space added.

If a request for more file space cannot be satisfied because


the virtual file space is full, the HHC will display a message
saying FILE SPACE FULL. If a request for more temporary stack
space cannot be satisfied because the virtual file space is full,
the HHC will display no message, but will return a FALSE to the
word that requested the space.

The EXTRINSIC VIRTUAL FILE SPACE is whatever space is


available in . a Programmable Memory Peripheral. This space is not
shared by any other part of the system, and so its size is equal
to the size of the Programmable Memory Peripheral.

Note that more than one Programmable Memory Peripheral may be


plugged in to the HHC at a time, but only one may be used at a
time. This is because all of the Programmable Memory Peripherals
must be bank-switched into the same address space. This means
that it is rather difficult to use a Programmable Memory
Peripheral as ordinary RAM. (Such use is not recommended, since
it interferes with the file system -- and vice versa.)

Structure of Virtual File Space

In general, it is good practice to manipulate virtual files


only through the words that the file system supplies for that
purpose. In some cases, however, applications must examine or
even modify the virtual file space directly. The following
information on the structure of the virtual file space is for use
in those cases.

The intrinsic and extrinsic virtual file spaces each begin

(c) 1981 Friends Amis, Inc. 5-11 3 September 81


THE VIRTUAL FILE SYSTEM

with a header in the following format:


bytes contents
0-3 Hexadecimal A5A5A3A5.

The file system checks these bytes frequently; if


they contain any other value, the file system assumes
that the HHC has just been cold-started, and
initializes the file space. THIS DELETES ALL FILES.
4-5 Total length of file space (counting from the first
'ASH' to the last byte available for files).

At present this field is maintained and used only in


the extrinsic file space, but it is present in the
intrinsic file space too, and may be used in the
future.

6-7 Amount of file space used, i.e., offset of the first


free byte from the first 'ASH'.
8-9 Number of files in the file space.
10+ Virtual files.

Virtual files are stored contiguously in the order in which


they were created. Inside the file system, the first file is
identified as #0, the second as #1, etc. (Externally, files
are identified only by name.)

(Format of a Text File)

bytes contents
.....___
0-1 Length of this file in bytes (including this field).
2 Type code (set by GET-TYPE C!).
3 Length of file name (not including length byte
itself).
4-xx File name (1 to 255 characters long).
xx+1 + Records. Each record consists of a length byte giving
the length of the record (not including the length
byte itself) , followed by the data.

Note that the first data record is record 40. The


file name may be considered "record 4-1." You can
rename a file by changing the contents of record 4-1
-- even for a non-text file, wnich has no other

(c) 1981 Friends Amis, Inc. 5-12 3 September 81


THE VIRTUAL FILE SYSTEM

records.

(Format of a Non-Text File)

A non-text file contains machine code and/or SNAP code. It


has no record structure after record #-1 (the file name); the
rest of the file's contents are totally arbitrary.
At present the HHC has no intrinsic facility for executing an
executable file. This is due to space constraints. A command for
executing an executable file will be included in any capsule
capable of creating one.

bytes contents
0-1 Length of this file in bytes (including this field).
2 Type code (set wih GET-TYPE).
3 Length of file name.
4-xx File name (1 to 255 characters long). Note that
executable and non-executable files have the same
structure up to this point.
xx+1 + Data.
The format is very similar to that of a ROM capsule,
except that there is no header containing address of
tag table, copyright notice, etc.

The first item in the format is the extrinsic tag


table for this file. Its length is arbitrary (up to
the maximum imposed by the design of the tag
concept). The first entry in the table (representing
tag 80H) MUST be file's entry point; the nucleus
executes the program in the file by FLEEing to an SOH
tag. Following entries define the subordinate words
in the file.
Following the tag table is the SNAP code defining the
program. The SNAP code can drop into low-level code
by using the technique described in the chapter
"General Technical Information." BUT NOTE that since
a file never has a fixed location in the address
space, low level code in an executable file may not
use absolute addressing to refer to itself.

The following words may be used to get information about the


file spaces:

(c) 1981 Friends Amis, Inc. 5-13 3 September 81


THE VIRTUAL FILE SYSTEM

&EXTRINSIC ( )
Indicates whether the current file space is the extrinsic
or the intrinsic file space. 3=TRUE -> extrinsic, B=FALSE
-> intrinsic.
FSPACE ( ADR )
Returns the address of the beginning of the first file in
the current file space.
FILELEN ( --- LEN )
Returns the length of the current file space.
AVAIL ( N )
Returns the number of free bytes in the current file
space.
FILEORG ( ADR )
Returns the address of the first free location in the
current file space.

FILESPACE ( ADR )
Returns the address of the beginning of intrinsic file
space. (The extrinsic file space, if present, always
begins at location 4000H; but it is NOT bank-switched into
the address space except when needed.)
TP ADR )
Returns the address of a two-byte area which contains the
address of the end of intrinsic file space, i.e., the
address of the lowest byte currently occupied by the
temporary stack.

?ROOM ( N B )
Returns TRUE if N bytes of space is available in the
current file space, and FALSE if not.

(c) 1981 Friends Ainis, Inc. 5-14 3 September 81


PERIPHERAL I/O & TIMER SERVICES

EVENT CONTROL BLOCKS

Introducing Asynchronous Processing

Many I/O operations are inherently time-dependent. After


starting an operation, a computer must wait until the operation
is complete before it can start another, related operation.
Simply halting the computer while an I/O operation is in
progress is a simple way to deal with time dependency. Most
current microcomputer systems work this way; but the technique is
inefficient, and it often gives the computer a maddening tendency
to miss keystrokes, etc., while waiting for an I/O operation
elsewhere.
The HHC uses a more sophisticated technique. While the it is
waiting for an I/O operation to complete, it continues processing
the application program that started the operation. The
application program may even initiate more I/O operations on
other devices. When an I/O operation completes, it generates an
INTERRUPT, that is, a hardware signal that causes the HHC to
suspend what it is doing and give the I/O operation whatever
attention it needs. (This is called SERVICING THE INTERRUPT.)
Then the HHC resumes processing application program. The
interrupt is transparent to the application program, and that
program's author never need be concerned with it.
There is no way to predict what part of an application will
be executing when an interrupt occurs. Thus I/O operations and
application-program execution proceed in parallel, but cannot be
synchronized. This arrangement is called ASYNCHRONOUS PROCESSING;
the I/O operation (or any other time-dependent function that is
handled the same way) is called an ASYNCHRONOUS PROCESS.
If the idea of asynchronous processing seems confusing, think
of a dot moving along a path between two points. The progress of
the dot represents the execution of an application program,
moving from its initiation to its conclusion.
At some point the dot splits in two, and one part proceeds on
its course while the other goes off in another direction. This
represents the application program starting an asynchronous
process (e.g., an I/O operation) and then continuing to execute
while the I/O operation is under way.
At some later point the dots combine again, and proceed
toward their goal as a single unit. This represents the
conclusion of the I/O operation.

The Event Control Block: Keeping Processes In Step

(c) 1981 Friends Amis, Inc. 6-1 3 September 81


PERIPHERAL I/O & TIMER SERVICES

Although I/O on the HHC is asynchronous, there has to be some


way to keep different processes in step. For example, suppose
your program starts an input operation. Sooner or later it
reaches a point where it needs the information that the input
operation was meant to procure. At that point, the program must
be able to tell whether the input operation is complete, and if
not, wait until it completes.

The mechanism that the HHC uses to keep processes in step is


the EVENT CONTROL BLOCK (ECB).

When an application program wants to do I/O, it executes an


appropriate SNAP word to start the I/O operation, and it passes
an ECB to the HHC's operating system as a parameter of that word.
The ECB often contains information about the operation to be
performed; in an output operation, for example, it contains a
character to be output. While the I/O operation is under way, the
operating system keeps track of the ECB's associated with it; we
say that the ECB is QUEUED.

The operating system starts the requested operation and turns


off a WAIT bit (also called a TRAFFIC BIT) in the ECB. Then it
returns control to the application program. The program can
continue processing up to the point where it must wait for the
requested operation to finish. Then it executes the WAIT word,
passing the same ECB to the operating system as a parameter.
If the requested operation completes before the application
program does its WAIT, it causes an interrupt; the HHC services
the interrupt and turns on the wait bit in the associated ECB.
(We say that it POSTS the ECB). Then, when the application does
its WAIT, the system finds the wait bit on, and so knows that the
operation being waited on fs already complete; it returns control
to the application program immediately.

On the other hand, if the requested operation does not


complete before the application program does its WAIT, the WAIT
causes the HHC to "go to sleep." Whenever an interrupt occurs,
the HHC wakes up, services the interrupt, and checks to see if
any process (e.g., the application program) is WAITing on that
ECB. If so, it returns control to the process in question; if
not, it goes back to sleep.
_

In this way, the application program that does a WAIT on an


ECB is guaranteed that when it gets control back, the ozeration
associated with the ECB wiii be complete -- even though tne
application has not checked whether the operation is complete
already, and has no way of knowing when it will be complete if it
presently is not.

Other Uses For ECBs

So far we have discussed ECBs largely in the context of I/O

(c) 1981 Friends Amis, Inc. 6-2 3 September 31


PERIPHERAL I/O & TIMER SERVICES

operations. This is the main use for them on the HHC. ECBs can
have other functions, though; they are useful wherever one
process needs to wait for an asynchronous EVEN: .7_0 occur. The
completion of an I/O operation is one kind of event.

The HHC also uses ECBs to provide timer services. For


example, if an application program wants to "sleep" for a
specified period of time, it can execute a SET.DELAY or
SET.DELAY.LONG, with an ECB containing the desired length of
sleep as a parameter. Then it can execute a WAIT on the ECB. It
will go to sleep until the specified interval has elapsed. At the
end of the interval an event will occur, the operating system
will post the ECB, and the application will wake up.

More About ECBs

An ECB has three main parts. They are:

1. The wait bit. This is the first (80's) bit of the first
byte.

2. The RETURN CODE field. This comprises the remaining 7 bits


of the first byte. When the operating system posts the ECB,
it places a code in this field indicating how the operation
completed. A zero generally indicates normal completion,
and other values indicate various types of errors. More
details are given in a table below.

3. Other data. The operation associated with the ECB


determines the number of bytes needed, and their functions.

The format of an ECB is:

byte.bit contents

0.0 Wait bit. 0=> waiting; 1=> event has occurred.

0.1-0.7 Return code. Indicates manner in which the


queued operation ended. Codes are listed
below.

1+ Operation-dependent information. Details are


given in the discussion of each operation.

return
code (hex) meaning
00 Successful operation.
01 Invalid logical device number (not 0-7) (I/0 onlv).

(c) 1981 Friends Amis, Inc, 6-3 3 September 81


PERIPHERAL I/O & TIMER SERVICES

02 Logical device number not assigned (I/O only).


03 Invalid device type (I/O only).
04 Control ROM absent, or its contents are invalid
(I/O only).
05 Prior operation still pending for device (I/O
only).
06 RAM needed to perform operation is not available.
07-FF Additional codes, where defined, are device-
specific. See information on individual devices
later in this chapter.

Using ECBs

To use an ECB, you first must allocate and initialize it.


An ECB may be allocated in any way, and may be anywhere in
intrinsic RAM. An ECB should NOT be located in a Programmable
Memory Peripheral, which might be bank-selected out of the
address space when the ECB is needed.

We recommend that you not try to share space between ECBs and
other program elements; if you make errors in keeping the uses
separate, they are likely to be hard to debug.

Also, do not use the same ECB for two or more types of
operations, even on the same device. If two operations should
happen concurrently on the same ECB, the results are
unpredictable (and generally unpleasant).

When you queue an ECB, the system automatically zeroes the


wait bit. Thus you need not zero this Pit explicitly. (But if the
event has already occurred when the ECB is queued, the system
will turn the wait bit ON? This is logically impossible in I/O
operations, but can happen with some other types of asynchronous
operations, such as setting timers.)

Execute a WAIT to make your application wait until the event


occurs and the ECB is posted; or execute a WAITM to make your
application wait until any one of two or more events occurs and
the corresponding ECB is posted.

When your program gets back control after a WAIT, it


generally should check the return code to determine whether the
operation it was WAITing for was terminated normally, and should
take appropriate action if not.

CAUTION: if you accidentally wait on an ECB that was never


queued, or on an erroneous location that looks like an unposted
ECB, your program will go into an endless wait. The only way to
recover will be to press CLEAR.

(c) 1981 Friends Amis, Inc. 6-4 3 September 81


PERIPHERAL I/O & TIMER SERVICES

INTRODUCTION TO PERIPHERAL I/O

Peripherals may ce olJgged into the HHC through its external


bus socket, or through a I/O adaptor plugged into the bus socket.
(The I/O adaptor is technically a peripheral device itself.)

Detailed information about the hardware and software


characteristics of each peripheral is given after the next few
sections, which describe device-independent aspects of software.

Software: Architecture

Peripheral devices are accessed through the peripheral


interface, which provides a consistent set of high level words
for opening and closing, input and output, and control.
The high level words call lower-level device routines in
standardized locations in ROM. Physically, each device routine
ROM is part of the device itself. Logically, each ROM is bank-
switched into the HHC's address space when the device is used.

Software: In General

The HHC uses three kinds of data items to control I/O


operations: hardware device codes, logical unit numbers, and
ECBs.
A HARDWARE DEVICE CODE is a one-byte value w hich an
application program may use to request access to a particular
type of device. Each type of device (or class of types of
devices) that can be attached to the HHC has a unique hardware
device code.
A LOGICAL UNIT NUMBER is a number from 0 to 7 which is
assigned to a specific device for the time that an application
program uses that device. The program uses the logical unit
number to identify the device in I/O operations.
An ECB (event control block) is an area of storage that is
used to pass information between a program and the device
routines that control a device. it is described in more detail
above.

(ECB's and Asynchronous I/O)

Most I/O operations are only INITIATED by an operation such


as RIP (Request Input, which reads a character) or ROP (Request
Output, which writes a character). Once initiated, control

(c) 1981 Friends Antis , Inc. 6-5 3 September 81


PERIPHERAL I/O & TIMER SERVICES

returns to the word after the RIP or ROP or whatever. The program
can continue executing, if that is logically possible, while the
7 /0 operation is going forward. We say that the I/O operation is
ASYNCHRONOUS because its progress is not synchronized with the
execution of the program that initiated it.

When the I/O operation is complete, the I/O hardware


generates an interrupt. This causes the HHC software to suspend
execution of your program, process the interrupt, and then allow
your program to continue executing as though nothing had
happened.

In this context, "processing the interrupt" means that the


system determines what I/O operation has completed, and how it
has completed (normally, with end-of-file, with an error, etc).
It puts an appropriate return code in the operation's ECB and
posts the ECB.

When your program needs the results of the I/O operation it


has initiated, it must execute a WAIT on the ECB. WAIT checks
whether the ECB has been posted yet. If not, WAIT halts execution
of your program until the ECB is posted. The linkage to WAIT is:

ecb WAIT

"ecb" is the address of the ECB you used to initiate the


operation.

You determine the outcome of the operation by inspecting the


ECB return code. If it is zero, the operation succeeded. If not,
tne operation failed; the value of the code identifies the
reason.

(Steps In Doing I/0)

To do I/O on a peripheral device, you must (1) use ATTACH to


associate a device with a logical unit number; (2) in some cases,
use ROPEN to prepare the device for 170; (3) use RIP to do input
or ROP to do output; and, when done, (4) in some cases, use
RCLOSE to close the device.

(c) 1981 Friends Amis, Inc. 6-6 3 September 81


PERIPHERAL I/O & TIMER SERVICES

PERIPHERAL I/O OPERATIONS

The ATTACH Operation

Your program must ATTACH a peripheral device before using it.


This means the program must tell the HHC that it needs a certain
type of device, and wants to associate the device with a certain
logical unit number.
You attach a device with the ATTACH word. Its linkage is:

devcode lun ATTACH b

"devcode" is the device type code of the desired device.


Valid codes and their meanings are listed below, and may also be
found with the table of characteristics of each device.
"lun" is the logical unit number to be attached to this
device. Valid numbers are 0 through 7.
"b" is a boolean that is TRUE if the ATTACH operation has
succeeded, and FALSE if it has not.
You do NOT have to do a WAIT after ATTACH. (Since ATTACH uses
no ECB, there is no way you could do one!)

NOTE: logical unit #0 is the system input unit, normally


attached to the keyboard. Unit #1 is the system output unit,
normally attached to the LCD. These two logical unit numbers need
not be attached before use, although they may be reattached to
different devices. Logical units #2 through #7 have no "normal"
attachments.

When CLEAR is pressed, logical units #0 and #1 are reset to


the keyboard and LCD, respectively. Logical units #2 through #7
are reset to "undefined."

RIP: Request Input

Once a device is attached, you may initiate a read operation


(if reading makes sense for the device) with RIP (Request InPut).
Each time you use RIP, you initiate an operation which will read
one character from a device.

The linkage to RIP is:

ecb lun RIP b

(c) 1981 Friends Amis, Inc. 6-7 3 September 81


PERIPHERAL I/O & TIMER SERVICES

"ecb" is the address of the ECB to use for this input


operation. The ECB must be at least 2 bytes long.

"lun" is the logical unit number you wish to read on.

"b" is a boolean that is TRUE if the RIP has succeeded, and


FALSE if it has not. If the RIP has not succeeded, the ECB return
code indicates the cause of the failure.
If RIP succeeds, do a WAIT on the ECB before the input
character is needed. If WAIT gives a return code of zero,
indicating success, byte 1 of the ECB contains the character
read.

ROP: Request Output

Once a device has been attached, you may request a write


operation (if writing makes sense) with the ROP (Request OutPut)
word. Each time you use ROP, you initiate an operation to write
one character to a device.

The linkage to ROP is:

ecb lun ROP b

"ecb" is the address of an ECB to use for this output


operation. The ECB must be at least 2 bytes long. Byte 1 of the
ECB should contain the character to be written.

"lun" is the logical unit number you wish to write on.

"b" is a boolean that is TRUE if the ROP has succeeded, and


FALSE if it has not. If the ROP has not succeeded, the ECB return
code indicates the reason.

If ROP succeeds, do a WAIT on the ECB before initiating the


next ROP on the same device.

Relation of RIP and ROP to KEY and EMIT

We have stated that RIP reads from the system input device
(normally the keyboard), and the ROP writes to the system output
device (normally the LCD). The KEY word also reads from the
system input device, and the EMIT word writes to the system
output device. What is the relationship between these two sets of
words?
The relationship is this: KEY does a RIP with logical unit

(c) 1981 Friends Amis, Inc. 6-8 3 September 81


PERIPHERAL I/O & TIMER SERVICES

#0, and EMIT does a ROP with logical unit #1. If these logical
units are reassigned, KEY and EMIT will send their output to
different devices, just as RIP and ROP will.
The only important differences between KEY/EMIT and RIP/ROP
is that KEY and EMIT belong to a larger group of words which do
I/O only on logical units #0 and #1, but which support a greater
range of operations on those devices than RIP and ROP do. For
example, the LOCK-KEY word is similar to KEY, but will return the
same character over and over while the LOCK key is in effect.
Outside the context of peripheral I/O, we say that words like
KEY read from the keyboard, and words like EMIT write to the LCD.
What we really mean is that words like KEY read from logical unit
#0, which is normally the keyboard, and words like EMIT write to
logical unit #1, which is normally the LCD. Keep this in mind as
you deal with those words!

Opening and Closing Devices

Opening and closing are two I/O operations which you must
perform for some devices.
OPENING means preparing the device for I/O, after attaching
it but before doing the first RIP or ROP.
CLOSING means "cleaning up" after the last ROP, e.g., writing
out the last record to a record-oriented device, etc.

(ROPEN and RCLOSE)

A device may be opened and closed with the ROPEN and RCLOSE
words, respectively:

ecb lun ROPEN b


ecb lun RCLOSE b

"ecb" is the address of an ECB to use for this open or close


ooeration. The ECB must be at least one byte long. Byte 0 of the
ECB should be set to 0.
"lun" is the logical unit number you wish to open or close.

"b" is a Boolean that is TRUE if the open or close has been


initiated successfully, and FALSE if it has not. If the operation
has not been initiated successfully, the ECB return code
indicates the cause of the failure.

(c) 1981 Friends Ainis, Inc. 6-9 3 September 81


PERIPHERAL I/O & TIMER SERVICES

Use a WAIT after ROPEN or RCLOSE to halt program execution


until the open or close operation is complete.

(Functions of ROPEN and RCLOSE)

The functions of ROPEN and RCLOSE differ for different


devices. They are described in the sections describing the
characteristics of each device, below.

The device routine for each HHC device performs an ROPEN


automatically when the device is first used (e.g., by RIP or
ROP). Thus, an explicit ROPEN is generally not necessary. You may
need to do one in some specific situations, e.g., when you want
to force the HHC to open the device sooner than it normally
would.

Similarly, an explicit RCLOSE is generally not necessary; its


functions are performed automatically by CLEAR.

When you write I/O routines that are intended to be device


independent, you should not use ROPEN or RCLOSE. Use these words
only in device-specific routines, when you are addressing a
device that requires opening and/or closing in a particular
situation.

RCTL: Control and Status Operations

You can send control information to a device, or read status


information from a device, with tne RCTL (Request ConTroL) word.
Its linkage is:

ecb lun RCTL b

"ecb" is the address of an ECB to use for this control


operation. The length of the ECB is device dependent. Byte 1 of
the ECB should contain a code specifying the control or status
operation to be performed. (See values with device descriptions.)

"lun" is the logical unit number you wish to operate on.

"b" is a boolean that is TRUE if the RCTL was successful, and


FALSE if not. If the operation was not successful, the ECB return
code indicates the cause of the failure.

If the operation is a "read status" type of operation, and


completed successfully, byte 1 of the ECB contains the
information requested.
RCTL should not be followed by WAIT.

(c) 1981 Friends Amis, Inc. 6-10 3 September 81


PERIPHERAL I/O & TIMER SERVICES

A Note on Multiple Waits

The HHC can wait on a list of ECBs, as well as on a single


ECB. It does this with the WAITM (WAIT Multiple) word. WAITM
waits until any one of a list of ECBs is posted, and indicates
which ECB was posted.

WAITM is useful for programs which use several devices, and


must be able to attend to an asynchronous operation on any of
them. For example, consider a modem program, which must be able
to read a character from the keyboard and write it to a modem, or
read a character from the modem and write it to the LCD. A
logical way to set up such a program would be to do a RIP on the
keyboard and another RIP on the modem, then do a WAITM on both
ECBs. Whichever input device delivered a character first would
end the wait and get attention.

See the I/O glossary for details on the use of WAITM.

(c) 1981 Friends Amis, Inc. 6-11 3 September 81


PERIPHERAL I/O & TIMER SERVICES

The System Device Table (SDT)

The HHC keeps track of LUN attachments through tne SYSTEM


DEVICE TABLE (SDT). The SDT's address is given by the symbol
'SDT'.

The SDT is 8 bytes long. Byte 0 represents LUN #0, byte 1


represents LUN #1, and so forth.

Each byte contains a relative pointer to a control block


which describes the device that the LUN is attached to. A pointer
of 0 represents the keyboard; 6 represents the LCD; OCH, 12H,
18H,, represent peripherals. A pointer of OFFH represents an
unattached LUN.

You can "unattach" a LUN by storing OFFH in its SDT entry.


Then you can use ATTACH to attach another device to the LUN.

NOTE: do not press any key on the HHC's keyboard which LUN #0
is attached to a peripheral device. If you do so, the HHC may
"freeze up" and execute only one Basic statement each time you
press a keyboard key. If this happens, the HHC will remain
"frozen" until you do a hard CLEAR or reattach LUN #0 to the
keyboard.

(c) 1981 Friends Amis, Inc. 6-12 3 September 81


PERIPHERAL I/O & TIMER SERVICES

PARAMETER VALUES

Hardware Device Codes

A hardware device code is a one-byte value. Each valid value


defines a type of device or a class of devices that may be
attached to the HHC.
Device codes defined for the HHC are:

input output
code code device

41H LCD
31H keyboard
82H 42H modem
43H video
44H Micro Printer
85H 45H reserved for expansion
86H 46H Serial Interface Adaptor
47H speech synthesizer (not yet avail.)
88H 48H reserved for expansion
89H 49H reserved for expansion
4AH reserved for expansion
8BH reserved for expansion

The 20's bit through the l's bit are used to distinguish
device types. The 80's and 40's bit are used to indicate whether
the device may be used for input or output. If the 86's bit is
on, the device may be used for input; if the 40's bit is on, the
device may be used for output.

Logical Unit Numbers

Valid logical unit numbers are 0 through 7.


40 is the system input device, defaulting to the keycoard.

#1 is the system output device, defaulting to the LCD.

#2 through 47 have no inherent functions, and default to


"unassigned."

ECB Return Codes

Following are the codes which are returned in bits 0.1-0.7 of


an ECB wnich is posted after an I/O operation:

(c) 1981 Friends Amis, Inc. 6-13 3 September 81


PERIPHERAL I/O & TIMER SERVICES

code meaning
0 Successful operation.
1 Logical device number invalid (not 0-7).
2 Logical device number not assigned.
3 Invalid device type code.
4 Device control ROM absent, or contents invalid.
5 Operation already pending on this device.
6 No RAM available for device (ROPEN).

7-255 Device dependent codes; see individual device


descriptions.

(c) 1981 Friends Amis, Inc. 6-14 3 September 81


PERIPHERAL I/O & TIMER SERVICES

OUTLINE OF PERIPHERAL I/O WORDS

Following is a table which summarizes the words that relate


to peripheral I/O and their linkages.

linkage ECB length; contents


input WORD output after 1st byte

devcode lun ATTACH b No ECB; no wait used.


ecb lun ROPEN b 1

ecb lun RIP b 2; 1=character read.


ecb lun ROP b 2; 1=character to write.
ecb lun RCTL b length varies; no WAIT needed.

Byte 1=control code indicating


operation to perform.

For a "read status" type oper-


ation, bytes 2,3,4...= status
information returned by the
operation.
ecb lun RCLOSE b 1

(c) 1981 Friends Amis, Inc. 6-15 3 September 81


PERIPHERAL I/O & TIMER SERVICES

CONTROL CHARACTERS

CONTROL CHARACTERS may be included in a character string sent


to an output device (e.g., the TV adapter) to perform control
functions such as cursor movement.

Not all control characters have meaning for all devices. If a


control character is sent to a device that does not support it,
the character will generally be ignored.

ASCII Control Characters

SYMBOLIC
CONSTANT HEX MEANING
&BSP 08 backspace
&LF OA line feed
OC form feed
&CR OD carriage return
&ESC 1B escape (starts escape control sequences, below)
80 cursor up
81 cursor left
82 cursor right
83 cursor down

Escape Control Sequences

Escape control sequences provide an extended range of control


characters. Each sequence is 3 bytes long:
BYTE MEANING
0 1B, escape, begins escape control sequence. Use the
symbolic equate &ESC to represent this code.
1 opcode.
2 data; meaning depends on opcode.

Each control sequence's opcode is represented by a symbolic


equate. These equates and their meanings are given in the
following mini-glossary, and in the main glossary. The data byte
is ignored in each case except where a use for it is explicitly
mentioned.

Note that not all escape control sequences are supported by


all devices. Each device ignores escape control sequences that it
does not support.

ESCCC Set Control Character Mode. If the data byte is TRUE,


subsequent control characters sent to the device will be

(c) 1981 Friends Amis, Inc. 6-16 3 September 81


PERIPHERAL I/O & TIMER SERVICES

displayed, not executed; if FALSE, subsequent control


characters sent to the device will be executed, not
displayed.
ESCDC Display Character Absolute. The next data character will
be displayed, even if it is a control character that
would normally be executed. For example, if the next
character is ODF (carriage return) and it would normally
cause a physical end-of-line on the device, it causes no
carriage end-of-line, but is written as an inverse J.
ESCDR Delete Right. The character under the cursor is deleted;
following characters on the line are moved left. The data
byte is used as a fill character at the end of the line.
ESCFL Flush I/O Buffer. Characters in the device's I/O buffer
are written (if being output) or dumped (if being input),
emptying the buffer. (This operation is generally applied
only to output devices that write a line of data at a
time. Writing a line would normally be triggered by a CR
character.)
ESCHM Home Cursor. This normally returns the cursor to the
upper left corner of a device with a two-dimensional
display.
ESCIR Insert Right. The data byte is displayed at the cursor.
The character under the cursor, and all following
characters on the line, are pushed to the right.
ESCSF Set Flash Mode. Subsequent output will be displayed in
flashing characters. Reverses the effect of ESCUF.
ESCSI Set inverse Mode. Subsequent output is displayed in
inverse. Reverses the effect of ESCUI.
ESCUF Set Unflash Mode. All subsequent output is displayed in
non-flashing characters, until the mode is changed by
ESCSF. Reverses the effect of ESCSF.
ESCUI Set Uninverse Mode. Subsequent output will be displayed
normally (non-inverse). Reverses the effect of ESCSI.
ESCUN "LCD unescape." On the LCD, the data byte is displayed
(as in ESCDA). On all other devices, it is ignored.

ESCWB Set Word Break. The data byte defines the word break
character that can trigger automatic word wrap. (This
means that when an output line becomes longer than a
device's line length, the device automatically starts a
new line and moves the last word of the old line to the
start of the new line so that the word will not straddle
a line break.)

The word oreak cnaracter is initially blank (20H) in all

(c) 1981 Friends Amis, Inc. 6-17 3 September 81


PERIPHERAL I/O & TIMER SERVICES

cases.

Setting the word break character to OFFH 7:.:fris automatic


word breaking off.

The Keyboard

(No information yet -- must be filled in.)

The LCD

The LCD is not strictly a peripheral, but it may be used in


many of the same ways. It obeys many of the standard control
codes and escape control sequences. It may be used as a
peripheral by writing to logical unit number 1 (which is attached
to the LCD by default).

(Technical Information)

DEVICE CODE: 41H

ECB LENGTH: 2 bytes

DEVICE-SPECIFIC ECB RETURN CODES: none. LCD I/O is performed


synchronously; I/O operations always succeed, and
post the ECB immediately.

I/O OPERATIONS:

ROPEN Unneeded.
RIP Not applicable.
ROP Outputs the character stored in byte I (origin-0) of
the ECB.
RCTL Not applicable.

RCLOSE Unneeded.

CONTROL CHARACTERS USED:


07 Makes the HHC beep.
08 Destuctive backpace.
OC Form feed; ignored (NOT displayed as inverse video L).

(c) 1981 Friends Amis, Inc. 6-18 3 September 81


PERIPHERAL I/O & TIMER SERVICES

OD Carriage return; clears display.


IB Begin escape control sequence.
Am. 80 Cursor Up. Displays as 'T'.
81 Cursor Left (non-destructive backspace).
82 Cursor Right (non-destructive space).
83 Cursor Down. Displays as '*',

ESCAPE CONTROL SEQUENCES: supports all escape control sequences.


Note that the data byte of ESCUN is displayed on the
LCD (as in ESCDC); it is ignored on all other devices.

The Micro Printer

(General Information)

The Micro Printer is of the thermal dot matrix printer. It


prints 15-character lines in a 1" column on rolls of paper 1.4"
wide, at 7 lines/inch. The printer's speed is 250
characters/second. It is powered by 4 "AA" batteries, or the bus.
The Micro Printer prints two lines at a time. It uses a 30-
character buffer, which enables it to print a line of data long
enough to fill the LCD, with a little bit left over for word
wrapping.
The Micro Printer allocates about 50 bytes of working space
at the tip of the temporary stack. This space contains the two-
line buffer and some data that the printer's device routine uses.
The Micro Printer uses the same character-forming software as
the LCD. It uses the same 5x8 dot matrix, and forms characters
with the same standard character set. When slaved to the LCD, it
is capable of printing with alternate character-set tables.
The Micro Printer is not capable of printing the kind of
graphics you can do with DMOVE, even when it is slaved to the
LCD. You can print a non-standard character set, including
"character graphics," by slaving the Micro Printer to the LCD and
using an appropriate alternate character set (or changing the
standard character set).

(Technical Information)

DEVICE CODE: 44H

ECB LENGTH: 2 bytes

(c) 1981 Friends Ainis, Inc. 6-19 3 September 81


PERIPHERAL I/O & TIMER SERVICES

DEVICE-SPECIFIC ECB RETURN CODES: none

I/O OPERATIONS:

ROPEN Unneeded. If used, allocates the 50-byte workspace


that the Micro Printer device routine needs from the
temporary stack.
RIP Not applicable.
ROP Outputs the character stored in byte 1 (origin-0) of
the ECB.
RCTL Not applicable.

RCLOSE Unneeded (unless last line of output ends without a


CR). If the printer buffer is not empty, flushes the
buffer and simulates a CR.

CONTROL CHARACTERS USED:

07 Bell; ignored.
08 Backspace. Moves the printer buffer pointer left one
character and deletes the last character in the
buffer.
OA Line feed. The printer treats this code as a no-op.
(Carriage return causes an automatic line feed.
OC Form feed. Writes and empties the printer buffer and
advances the paper 5 lines.
OD Carriage return. Makes the printer print an accumulated
line of output and do a line feed.(Note that tne line
feed character is NOT supported.) After the or inter
has printed the contents of the buffer, the buffer is
reset to all-blanks.
13 Escape. Marks the beginning of an escape control
sequence.
80 Cursor Up. Displays as 'I"
81 Cursor Left. Moves the printer buffer pointer left one
character. The last character in the buffer is not
deleted, but will be overwritten by the next output
character.
82 Cursor Right. Moves the printer buffer pointer right
one character without changing the contents of the
buffer.
83 Cursor Down. Displays as 'V.

ESCAPE CONTROL SEQUENCES: ESCCC ESCDC ESCDR ESCFL ESCHM ESCIR


ESCUN ESCWB

Video Interface

(c) 1981 Friends Amis, Inc. 6-20 3 September 81


PERIPHERAL I/O & TIMER SERVICES

(General Information)

The video interface operates a black and white or color


television set via an RF modulator, or operates a black and white
or color monitor directly. It has 1.5K of internal RAM, which
enables it to maintain two alternate screen images, software
selectable. The interface draws power from an AC adaptor, not
from the HHC bus.
There is a 96-character set including ASCII, Katakana, &
graphics characters in 7x9 dot matrix. Lower case characters have
true descenders.
The text mode screen format is 16 lines x 32 characters. Text
colors are green (initial) or orange (alternate) on black ground.
Inverse video displays black on orange or green ground;
characters may be flashing or steady.
There are several graphics modes offering different
resolutions and capabilities.
The video interface is described in detail in a separate
document.

(Technical Information)

DEVICE CODE: 43H

For other technical information, see separate document.

Modem

(General Information)

The modem (actually an acoustic coupler) supports


asynchronous communications at 110 and 300 baud (software
selectable). It has the following software selectable options:
full/half duplex, originate/answer, with 5 to 8 data bits, 1 or 2
stop bits, and even/odd/no parity.

(Technical Information)

DEVICE CODE: input 82H; output 42H

(c) 1981 Friends Amis, Inc. 6-21 3 September 81


PERIPHERAL I/O & TIMER SERVICES

ECB LENGTH: 4 bytes for RCTL; 2 bytes for input & output

DEVICE-SPECIFIC ECB RETURN CODES:

07 Input buffer is within 5 characters of overflowing.


(Occurs on input operations only). Usual cause: the
host is ignoring XOFF.
08 through OF
Interpreted bitwise. If the return code is expressed as
0000 1pfv,
p=0 means a parity error occurred.
f=0 means a framing error occurred.
v=0 means an overrun error occurred.
OF Input buffer is overflowing.
10 Output buffer overflow.

I/O OPERATIONS:

ROPEN No function. See RCTL.


RIP Inputs a character and stores it in byte 1 of the ECB.
ROP Outputs the character stored in byte 1 of the ECB.
RCTL Used to perform the followingoperations:
--initializing modem for I/O.
--changing status of modem.
--querying status of modem.
Byte 1 of the ECB determines what operation will be
performed. The meaning of bytes 2 & 3 varies from one
operation to another. (See details below.)

RCLOSE No function.

CONTROL CHARACTERS USED:

11H XON (resume-transmission signal in standard XON/XOFF


protocol).

Through RCTL, you can specify whether the modem is to


observe XON/XOFF protocol for receiving data and for
transmitting data.

When the modem observes the protocol for reception


and/or transmission, it handles tne protocol entirely
in the device driver; thus the protocol is transparent
to the application program.
When the modem ignores the protocol for transmission,
it becomes capable of receiving binary codes 11H and
13H as data. The system the HHC is communicating with

(c) 1981 Friends Amis, Inc. 6-22 3 September 81


PERIPHERAL I/O & TIMER SERVICES

must be capable of receiving data continuously, since


the HHC will treat an XOFF as a data byte.
When the modem ignores the protocol for reception, the
system it is communicating with may safely assume that
when it receives binary codes 11H and 13H, they are
data, not protocol signals. The HHC must be capable of
receiving data continuously, since the device driver
will not send an XOFF when the modem's buffer is
nearly full.

13H XOFF (cease-transmission signal in standard XON/XOFF


protocol). See XON for details.

ESCAPE CONTROL SEQUENCES: none

(Device Initialization)

The modem must be initialized before you can begin doing I/O
on it. Initialization sets hardware options such as data rate,
parity, etc., to values compatible with the host system.

A routine in the device control ROM initializes the modem


automatically when the modem is turned on with the I/O key, when
the user presses ON, and when a hard clear occurs.

The modem is initialized from a file whose name consists of


the non-ASCII characters OFEH,OCFH. This file is created by the
telecomputing program. The telecomputing program creates the file
when the user configures the program to talk to a particular
host.

Format Of the Modem File

You can re-initialize the modem, if you wish to do so, with


an initialization call to RCTL. If you do this, you may want to
use the "standard" configuration in the modem initialization file
as a starting point.

The modem initialization file contains one record. Read the


record and move its first two bytes to bytes 2 and 3 of the modem
ECB; set the value of CTLPCA in byte 1; then do an RCTL on the
ECB. You may ignore the rest of the file's record; it is
meaningful only to the telecomputing program.

(Initialization Call)

Here is the ECB format for a "device initialization" call to

(c) 1981 Friends Amis, Inc. 6-23 3 September 81


PERIPHERAL I/O & TIMER SERVICES

RCTL:

BYTE BIT Meaning for call to RCTL

0 Traffic bit & return code (standard ECB


format).
1 Function code; must be set to the value of the
symbolic constant CTLPCA.
2 80 ignored.
40 1->use breaktone; 0-> don't.
20 Data rate. 1-> 300 baud; 0-> 110 baud.
10-08 Character length in bits. 00-> 5 bits; 01-> 6
bits; 10-> 7 bits; 11-> 8 bits.
04 1-> suppress parity check; 0->don't.
02 1-> even parity; 0-> odd parity.
01 Number of stop bits 1-> 2 bits; 0-> 1 bit.
3 80 Used internally by device driver. Should
always be set to 0.
40 1-> enable input IRQ; 0-> disable. (Must be
set to 1 if modern is to detect subsequent
input.)
20 ignored.
10 1-> enable modem receiver; 0-> disable.
08 1-> enable modem transmitter; 0-> disable.
04 1-> set originate mode; 0-> set answer mode.
02-01 ignored.

Format of this table is inconsistent with the o- ?s


in the section on the RS-232 interface, foilowing.
Which is preferable? Are the symbols listed for RS-
232 actually available to the application
programmer?
(Set XON/XOFF Status)

"Set XON/XOFF status" is an optional RCTL operation. Its


purpose is to disable the XON/XOFF protocol for reception and/or
transmission. A device initialization call always enables tne
protocol going both ways; if you do not perform a "set device
status" operation after a "device initialization" operation, tne
protocol will simply stay enabled.

Here is the ECB format for a "set XON/XOFF status" call to


RCTL:

BYTE BIT Meaning for call to RCTL


Now

(c) 1981 Friends Amis, Inc. 6-24 3 September 81


PERIPHERAL I/O & TIMER SERVICES

0 Traffic bit & return code (standard ECB


format).

1 Function code; must be set to the value of the


symbolic constant CTLXSTAT.
2 80 1-> enable protocol for transmission; 0->
disable.
40 1-> enable protocol for reception; 0->
disable.
20-01 Used internally; should always be set to 0.

(Get Device Status)

"Get device status" returns information about the current


status of the modem in the ECB.
Here is the ECB format for a "get device status" call to
RCTL:

BYTE BIT Meaning for call to RCTL

0 Traffic bit & return code (standard ECB


format). Return code is always 0.
1 Input to call: function code. Must be set to
the value of the symbolic constant CTLSTATUS.
Return from call: protocol status. Indicates
whether XON/XOFF protocol is being observed
for input and/or output. Bit assignments are
the same as for ECB byte 2 of the CTLXSTAT
function.

2 80-20 Ignored. Should be set to 0.


10 1-> no carrier detected. 0-> carrier detected.
08 1-> last read's parity OK (or not being
checked); 0-> parity error.
04 1-> last read's framing OK; 0-> framing error.
02 1-> last read no overrun error; 0-> overrun
error.
01 Ignored.

Serial Interface Adaptor (RS-232 Interface)

(General Information)

The Serial Interface Adaptor supports full RS-232 protocol

(c) 1981 Friends Amis, Inc. 6-25 3 September 81


PERIPHERAL I/O & TIMER SERVICES

for input and output. It is switch-selectable for all standard


data rates up to 9,600 baud. Characteristics such as character
length and parity may be set through software. The modem's device
control ROM has built-in hardware support for XON/XOFF and
ETX/ACK protocols.

(Technical Information)

DEVICE CODE: input 86H; output 46H

ECB LENGTH: 4 bytes for RCTL; 2 bytes for input & output

DEVICE-SPECIFIC ECB RETURN CODES:

07 Input buffer is within 5 characters of overflowing.


(Occurs on input operations only). Usual cause: the
remote system or device is ignoring transmission
protocol.
08 through OF
Interpreted bitwise. If the return code is expressed as
0000 1pfv,
p=0 means a parity error occurred.
f=0 means a framing error occurred.
v=0 means an overrun error occurred.
OF Input buffer overflow.
10 Output buffer overflow.

I/O OPERATIONS:

ROPEN Clears any pending input and output operations.

RIP Inputs a character and stores it in byte 1 of the ECB.

ROP Outputs the character stored in byte 1 of the ECB.

RCTL Used to initialize the modem for I/O, and to modify and
query its status.

Byte 1 of the ECB determines what operation will oe


performed. The meaning of bytes 2 & 3 varies from one
operation to another. (See details below.)

RCLOSE No function.

CONTROL CHARACTERS USED:

11H, symbolic constant &XON


XON. Same function as in the modem when XON/XOFF protocol is
used. Otherwise treated as a data character. See the

(c) 1981 Friends Amis, Inc. 6-26 3 September 81


PERIPHERAL I/O & TIMER SERVICES

description of modem control characters for details.

13H, symbolic constant &XOFF

XOFF (cease-transmission signal in standard XON/XOFF


protocol). See description of modem control characters for
details.
03H, symbolic constant &ETX
ETX. Used in ETX/ACK protocol to mark the end of a
transmission.
In ETX/ACK protocol, the transmitting computer or device
sends a message known to be short enough for the receiver to
accept and process without losing characters. The transmitter
ends the message with an ETX code. When the receiver has
processed the entire message and is ready for another one, it
sends an ACK code. This signals the transmitter that it may
send another message.

06H, symbolic constant &ACK


ACK. Used in ETX/ACK protocol to acknowledge a transmission.
See 03H, ETX, for details.

ESCAPE CONTROL SEQUENCES: none

*NW
(Device Initialization)

The Serial Interface Adaptor must be initialized before you


can begin doing I/O on it. Initialization sets hardware options
such as word length, parity, etc., to values compatible with the
peripheral connected to the interface.

A routine in the device control ROM initializes the modem


automatically when the modem is turned on with the I/O key, when
the user presses ON, and when a hard clear occurs.

The modem is initialized from an invisible file whose name


consists of the non-ASCII characters OFBH,OCFH. This file is
created by a configuration program build into the interface.

Unlike the modem initialization file, the Serial Interface


Adaptor initialization file can contain a separate set of
initialization data for the bus socket on the HHC (slot 40) and
for each socket in the I/O adaptor (slots #1 through 46). Thus,
th user can change the interface's default configuration just by
plugging it into a different slot.
There are four types of calls to RCTL for the modem:

i. Initialization: sets interface characteristics such as

(c) 1981 Friends Amis, Inc. 6-27 3 September 81


PERIPHERAL I/O & TIMER SERVICES

number of data bits and parity.


2. POKE: sets a value in the control block used by the
device's control ROM (the PCA).
3. PEEK: retrieves a value from the PCA.

4. STATUS: retrieves data about the interface's current


configuration.

(Initialization)

Here is the ECB format for an "initialization" call to RCTL:

SYMBOLIC
BYTE BIT CONSTANT Meaning for call to RCTL

0 Unused.
1 Function code. Use the symbolic
constant CTLPCA.
2 80 PWRON 1->device power on, 0->off.
40 BRKBIT 1->use breaktone; 0-> don't.
20 unused.
10-08 DTBT Character length in bits. 00-> 5 bits;
01-> 6 bits; 10-> 7 bits; 11-> 8
bits.
04 NOPTY 1->suppress parity check; 0->don't.
02 EVENPTY 1->even parity; 0->odd.
01 STBT Number of stop bits; 1-> 2 bits; 0-> 1
bit.

There's an inconsistency between the information I


have for the sense of the parity on/off and parity
odd/even bits for the RS-232 and the modem. Should
they be the same? If so, which way are they?
3 80 RESETBIT 0->reset read; 1->don't. In normal
use, should always be set to 1.
40 RCVENAB 1-> enable input IRQ; 0-> disable.
(Must be set to i if serial interface
is to detect subsequent input.)
20 XMTENAB 1-> enable output IRQ; 0-> disable.
10 DTRENAB 1-> DTR signal on; 0-> off.
03-01 ignored.

SYMBOLIC
BYTE BIT CONSTANT Meaning for return from RCTL
.1.1 ...a Nap.

(c) 1981 Friends Amis, Inc. 6-28 3 September 81


PERIPHERAL I/O & TIMER SERVICES

0 Traffic bit & return code.


1-3 Unchanged.

(POKE Call)

SYMBOLIC
BYTE BIT CONSTANT Meaning for call to RCTL

0 Unused.
1 Function code. Use the symbolic
constant CTLPOKE.
2 Offset of PCA field to be POKEd. See
the description of PEEK for useful
offsets.

3 Value to POKE.

SYMBOLIC
BYTE BIT CONSTANT Meaning for return from RCTL
Now
0 Traffic bit & return code.
1-3 Unchanged.

(PEEK Call)

SYMBOLIC
BYTE BIT CONSTANT Meaning for call to RCTL
.11=11,01.0.11=5.110

0 Unused.

1 Function code. Use the symbolic


constant CTLPEEK.
2 Offset of PCA field to be POKEd. See
table of useful values below.

3 Unused.

SYMBOLIC
BYTE BIT CONSTANT Meaning for return from RCTL

(c) 1981 Friends Amis, Inc. 6-29 3 September 81


PERIPHERAL I/O & TIMER SERVICES

0 Traffic bit & return code.


1-2 Unused.
3 Unchanged.

(Useful PCA Offsets With PEEK and POKE)

OFFSET CONSTANT MEANING

0 IQI Offset from origin of input queue where


next character received will be stored.
1 IQO Offset from origin of input queue where
next character read by the program will be
fetched.
2 IQC Number of characters in input queue.
3 OQI Offset from origin of output queue where
next character written by program will be
stored.
4 0Q0 Offset from origin of output queue where
next character transmitted will be
fetched.
5 OQC Number of characters in output queue.
6 IQ First byte of input queue. Length of queue
is OCH, symbolic constant IQLEN.
12H OQ First byte of output queue. Lengthof aueue
is 46H, symbolic constant OQLEN.
58H ERSAV Save of error code from last asynchronous
I/O operation.
39H ETXCT Number of characters processed since last
ETX was transmitted/received, Meaningful
only if ETX/ACK protocol is being used.
5CH RSOFT Software option byte. Meanings of bits:
80 SENDXX 1-> enable XON/XOFF for transmission;
0-> disable,
40 RCVEXX 1-> enable XON/XOFF for reception; 0->
disable.
20 ETXACK 1-> enable ETX/ACK.
10 RSTRCVE 1-> auto release from RXOFF state.

(c) 1981 Friends Amis, Inc. 6-30 3 September 81


PERIPHERAL I/O & TIMER SERVICES

08 TERMINAL 1-> Use serial interface input to


simulate HHC keyboard.
04 RAUTOLF 1-> Auto line feed; when CR is written
to the interface, the interface
transmits CR/LF to the peripheral.
02 HHCESC 1-> Let escape control sequences go
through the interface; 0-> filter them
out.
01 IGBIT 1-> zero 80's bit in each byte, 0->
transmit it.
5DH ETXLN ETX message length.
5EH XSTAT XON/XOFF flags.
80 Unused.
40 SXOFF An XOFF has been sent.
20 RXOFF An XOFF has been received, or an ETX
has been sent; output is delayed.
10 ETXXMIT Next output to be ETX.
08 XONXMIT Next output to be XON.
04 XOFFXMIT Next output to be XOFF.
02 LFXMIT Perform auto line feed.
01 CTLIN 1 -> USTAT and MSTAT (two other fields
in the PCA) are current.

The relationship between LFXMIT, RAUTOLF, and


VAUTOLF is not clear. When would the program set
one, when the other? When read one, wrien the
other, when both?

(Get Status Call)

Here is the ECB format for a "get device status" call to


RCTL:

SYMBOLIC
BYTE BIT CONSTANT Meaning for call to RCTL

0 Unused.
1 Function code. Use the symbolic
constant CTLSTATUS.
2 -3 Unused.

SYMBOLIC
BYTE BIT CONSTANT Meaning for return from RCTL
-- .10

(c) 1981 Friends Amis, Inc. 6-31 3 September 81


PERIPHERAL I/O & TIMER SERVICES

0 Traffic bit & return code.


Status byte. Meanings of bits are:

80 INTACT 1->IRQ asserted, 0->not.


40 RCVINT 1->UART data read, 0->not.
20 unused
10 CARDET 1->carriet detect, 0->no carrier.
08 PTYERR 1->parity err detected, 0->no err.
04 FRMERR 1->framing err detected, 0->no err.
02 OVRNERR 1->overrun err detected, 0->no err.
01 unused

I see no way duplex and echo can be set. Is there


any function for this? Is it hardware? If so, why
no detection of speed, which is also hardware?

What happens if DETCAR is on and the carrier is no


detected?

2-3 Unused.

1.1111IP

(c) 1981 Friends Amis, Inc. 6-32 3 September 81


PERIPHERAL & TIMER SERVICES

TIMER SERVICES

The Real-time Clock

The HHC's basic clock facilities are a hardware counter that


counts down continuously whether the HHC is on or not, and a
software TIME OF CENTURY CLOCK which stores a binary
representation of the elapsed time since 1 January 1980 in a 5
byte field. The time of century clock may be used to display the
current date and time.
Application programs may define timers which will generate an
event at a specified time. The HHC maintains a queue of ECBs
representing the time of century clock and any timers which the
application has defined.
The basic timing units are seconds and CLOCK TICKS. A clock
tick equals 1/256 second.
The hardware counter is set to count down from its maximum
interval or the least interval remaining in any timer, whichever
is less. When it reaches zero it generates an interrupt, allowing
the CPU to update all the timer ECB's by processing each entry in
the timer queue.

Using Timer Facilities

To get the time of century, use GET.GMT (for Greenwich ,I can


Time) or GET.LOCAL (for local time.—currently the same as GMT).
To create a timer, allocate an ECB 6 bytes long. Set the
timer interval and queue the ECB with SET.DELAY or
SET.DELAY.LONG; or set the time when the timer is to go off with
STORE.TIME and queue the ECB with SET.TIMER.

To cancel a timer and dequeue its ECB, use CANCEL.TIMER.

To wait for a timer to go off, use WAIT or WAITM on the


timer's ECB.
NOTE: all timer ECB's except those belonging to the pocket
secretary are cancelled and posted when CLEAR is pressed, or when
the task that started them finishes executing.

The Auto-Off Facility

The HHC's AUTO-OFF facility conserves battery power by


turning the HHC off automatically when no keystroke has been
entered for a period between 10 and 20 minutes.

(c) 1981 Friends Amis, Inc. 6-33 3 September 81


PERIPHERAL I/O & TIMER SERVICES

The auto-off facility uses a control bit and a 10-minute


timer. Every time a keystroke is entered, the bit is turned on;
every time the timer expires, the bit is turned off. If the timer
expires and the bit is found to be already off, the HHC turns
itself off.
This is fine for most kinds of applications, but occasionally
there is a legitimate need to run the HHC for long periods of
time without any keystrokes being entered. One example is a
telecommunications program, which may transmit or receive a long
file without keyboard intervention.

For these situations, the HHC provides two words for


manipulating the auto-off control bit. The AOENB ("auto-off
enable") word turns the bit off; the AOTOKE word turns the bit on
(as though a key had been pressed).
To "disable" the auto-off facility, simply execute AOTOKE
periodically. For example, if you are writing a modem program,
you might execute AUTOKE every time you process a carriage
return.

(c) 1981 Friends Amis, Inc. 6-34 3 September 81


FLOATING POINT

INTERNAL STORAGE

The format used to represent a floating point number is:

byte.bit contents

0.0 Sign bit; 0 -> positive, 1 -> negative.


0.1-1.3 Exponent. Stored in binary format with base-10
biased representation.
1.4-7.7 Mantissa. Stored in packed-decimal, digit-
normalized form. The mantissa's implied decimal
point is between the first and second decimal
digits.

Byte 0 is oriented toward low memory. On the parameter stack,


therefore, bytes 0 and 1 are on top.
The exponent represents values from 10 --1024 to 101023.
The mantissa allows 13 decimal digits of significance. Since
all arithmetic operations truncate the result, however, the last
digit is more properly viewed as a guard digit on a mantissa with
12 decimal digits of significance.
The mantissa's packed-decimal format saves substantial
amounts of CPU time during internal/external conversions, and
also makes rounding errors more comprehensible to users used to
decimal arithmetic. Since the 6302's packed-BCD arithmetic is
about as fast as its binary arithmetic, there is no speed
penalty.

(c) 1981 Friends Amis, Inc. 7-1 3 September 81


FLOATING POINT

ERROR HANDLING AND SPECIAL CASES

When the HHC executes floating point words, a variety of


nasty things can happen. The software flags all error conditions
by setting bits 1.4-1.7 (the first decimal digit of the mantissa)
to zero, and bits 0.1-0.7 to a code indicating the type of error
that has occurred. A floating point number set in this way is
called a SPECIAL CASE.

Thus, an erroneous operation is indicated by the VALUE of the


result. This causes an interesting (potentially confusing) quirk
in terminology; the names of error conditions are also the names
of the corresponding special cases. For example, an operation
that raises in a zero divide condition returns the "zero divide"
special case as its result, and this value may be stored in a FP
variable, from which it may be displayed or used in further
operations.
Possible values of the error code are:

value meaning
0 ZERO. The numeric value 0.0.
Arithmetic operations which produce 0 always set the
sign bit to 0 (positive). The user may push a
negative 0 on the stack if he wishes; the software
will treat it the same as a positive 0.
The ASCII representation of ZERO is '0'.
1 UNDERFLOW; 10 - -1024 > result > O. An underflow
converted to ASCII is represented as
2 OVERFLOW; result > 110**1023. An overflow converted to
ASCII is represented as 'V'.
3 COMPLEX NUMBER; occurs when an attempt is made to
take the square root of a negative number, or when a
complex number is used in a calculation. A complex
number converted to ASCII is represented as
4 ZERO DIVIDE; occurs wnen a number, overflow, or
underflow is divided by a 0 or by a zero divide. A
zero divide converted to ASCII is represented as
3 ENIGMA; any undecidable result not covered above,
e.g., the result of converting your name to a
floating point number. A zero divide converted to
ASCII is represented as

6-FF Undefined. Application programs may use these values


to represent their own "special cases." See notes

(c) 1981 Friends Amis, Inc. 7-2 3 September 81


FLOATING POINT

below.

Operations on special cases and valid floating point numbers


generally obey the rule that THE TYPE OF THE RESULT IS THE SAME
AS THE TYPE OF THE HIGHER-VALUED SPECIAL CASE OPERAND. The
rationale is to propagate the "worst" error through any chain of
floating point operations. Exceptions to the rule are:

1. Operations resulting in overflow or underflow, which produce


a special case although both operands are numbers.
2. Division by zero, which produces a zero divide (code 4)
although the higher-valued operand is zero (code 0).

3. Taking an even root of a negative number, which produces a


complex number although both operands are numbers.
4. Adding/subtracting a valid number and zero: the result is a
valid number although zero is a special case.

Defining New Special Case Types

You can use special case codes 6 to OFFH to represent your


own special cases.
The word FSTANDTYPE, which extracts the special case code
from a floating point number, reports any of these codes as an
enigma (code 5). All other floating point operations Process them
according to the standard rules given above.

Some Missing Operations

Do to space restrictions in the HHC's ROM, several rather


basic functions are absent from the floating point vocabulary.
Following are suggested substitutes for these absent words.
TEST FOR EQUALITY: the 'F=' word, which might be expected to
perform this function, is absent. The only floating point
comparison word on the HHC is 'F('. 'F=' may be defined like
this:

: F= ( FPI FP2 --- B )


FOVER FOVER F< >T FSWAP F< T> OR 0= ;

NEGATE: a floating point number on the stack may be negated


(its sign may be reversed) like this:

(c) 1981 Friends Amis, Inc. 7-3 3 September 81


FLOATING POINT

HEX
: FNEGATE ( --- FPI' )
80 XOR ;
DECIMAL

SETTING A SPECIAL CASE: if you have a need to define your own


special cases (with codes 6 through OFFH), you will need a way to
turn a floating point number into a special case. The following
word will do so:

HEX
: FP>SC (S FP N FP' )
007F AND >T 0F80 AND T> OR ;
(P FP = A FLOATING POINT NUMBER; N = DESIRED SPECIAL
CASE CODE DESIRED; FP' = FP TURNED INTO THE SPECIAL
CASE.)
DECIMAL

Or, if you have no need to preserve the last 6 bytes of the


mantissa, drop the floating point number and stack a special case
like this:

: FSC (S N --- FP )
007F AND 0 0 0 ;
(P N IS THE SPECIAL CASE CODE DESIRED; FP IS THE
SPECIAL CASE VALUE.)

Defining Floating Point Constants

The SNAP compiler has no built-in mechanism for compiling a


floating point constant from ASCII notation such as '1.25'. You
must convert the constant to a hexadecimal number yourself, and
code it as such.
To convert a floating point constant from ASCII to hex, you
can use the ASC>FP word in th SNAP emulator. Here is an example
of how you might do this:

HERE S" 0.5" (you tyPel


OK [emulator replies}
COUNT FP>ASC 2DROP fyou type)
OK lit replies}
HEX . . . F53F 0 0 0 OK [you type; it replies}

This tells you that the hexadecimal equivalent of 0.5 is 00u0


0000 0000 F53F (the last word in the number gets Lr
printed first).

(c) 1981 Friends Amis, Inc. 7-4 3 September 81


FLOATING POINT

To define a constant with this value in a SNAP program, you


could write

HERE-V
0 ,-V 0 ,-V 0 ,-V F53F ,-V == FP0.5

Or, to code the constant in-line:

: BLXFLT ( --- )
•• •
FLIT [ 0 ,-V 0 ,-V 0 ,-V F53F ,-V ]
• ' •

(c) 1981 Friends Amis, Inc. 7-5 3 September 81


FLOATING POINT

FLOATING POINT OPERATIONS WITHOUT SPECIAL CASE CHECKING

The HHC's software includes three words that do floating


point addition, multiplication and division without checking for
special cases. These words are about 4 times faster than the
corresponding words that do check for special cases. When you
know an operation will not result in a special case, you can
safely improve your program's performance by using the non-
checking words.

The non-checking words are not in the HHC's tag table. If you
want to use them, your program must define words that locate them
by referring to near-by words that are in the tag table. (You
cannot safely code a non-checking word's address into your
program, since the address may change from one version of the HHC
to another. A change in the address of an intrinsic word does not
force application programs to be recompiled, so long as the tag
table does not change.)

Following is the code you need to call the non-checking


floating point words:

Calling the Non-Checking Version of F+

CODEC (F+)
'X FNEGATE >< FF AND 2*
IDICT SHINT 2* + + DUP

LDA,
1+ LDY,

LABEL (FIETS)

N 10 + STA,
DEY,
N 11 + STY,
FE # LDY,

N 10 + )y LDA,
N 12 + STA,
INY,
N 10 + )Y LDA,
N 13 + STA,

N 12 + ) JMP,

Calling the Non-Checking Versions of F* and F/

CODEC (F*)
'X F/ >< FF AND 2*

(c) 1981 Friends Amis, Inc. 7-6 3 September 81


FLOATING POINT

IDICT SHINT 2* + + DUP

LDA,
1+ LDY,

(FIETS) BNE,

CODEC (F/)
'X FROUND >< FF AND 2*
IDICT SHINT 2* + + DUP
LDA,
1+ LDY,
(FIETS) BNE,

CODEC LEGAL?
TOP 1+ LDA,
F # AND,
0= IF,
TOP LDA,
0= NOT IF,
ILL,QUAN # LDA,
>EXROR JMP,
THEN,
8 # LDY,
BEGIN,
TOP STA,
INX,
DEY,
0= UNTIL,
TXA,
8 1- 4 SBC,
TAX,
THEN,
IDICT ( 'X EXIT )
) JMP,

(c) 1981 Friends Amis, Inc. 7-7 3 September 81


FLOATING POINT

GLOSSARY

Following is a brief glossary of words that relate to


floating point operations. See the "Glossary" chapter for more
complete descriptions of these words.

(F*) ( FP1 FP2 --- FP3 )


(F+) ( FP1 FP2 --- FP3 )
(F/) ( FP1 FP2 --- FP3 )
Internal words which perform floating point
multiplication, addition and division, without special-
case checking. If given special case operands, they
produce unpredictable results; (F/) may loop if its
divisor is zero.
NOTE: that no (F-) instruction exists. To subtract, use
'80 XOR (F+)' (in hexadecimal base).
NOTE: these words are not in the EIHC's tag table. The
compiler handles them as special cases by finding each
word's address in the code for the corresponding standard
word, and compiling a (CALL) to the address.

10EXP ( N --- EXP )


Extracts the exponent from a floating point number that is
on the stack.
N is the position of the floating point number, relative
to the tip of the stack. If tne number is immediately
below N, then N should be 1 (since N itself occludes
position 0!). If the number is below N and one other
floating point number, then N should be 3, and so forth.
EXP is the exponent from the number.

ASC>FP ( ADR LEN --- FP ENDLOC NDIGITS )


Converts a floating point number from ASCII format to
internal format.
ADR LEN are the address and length of the ASCII format
number.

FP is the floating point value. ENDLOC is the address of


the first location beyond the [valid part of the] number.
NDIGITS is the number of significant digits in the number.
If ENDLOC<ADR+LEN, ASC>FP encountered an error during the
conversion; ENDLOC points to the first character
considered erroneous, and FP and NDIGITS reflect the value
of the number up to that point.

(c) 1981 Friends Amis, Inc. 7-8 3 September 81


FLOATING POINT

F! ( FP ADR --- )
A. Stores a floating point number.

FIt ( FP N --- FP N )
A word used by FP>ASC to assist in formatting the ASCII
representation of a floating point number.

F* ( FPI FP2 --- FP3 )


Leaves product of two floating point numbers. Performs
special case handling.

F+ ( FPI FP2 --- FP3 )


Leaves sum of two floating point numbers. Performs special
case handling.

F@ ( ADR --- FP )
Fetchs a floating point number.

F- ( FP1 FP2 --- FP3 )


Leaves difference of two floating point numbers.

F. ( FP NDIGITS --- N )
Displays a floating point number in standard notation (not
exponential notation).

FP is the number to display. NDIGITS is the number of


significant digits to display. N is the actual number of
digits displayed.

F.EXT ( N M --- )
Used after F. to extend a floating point number to a
specified length.

N is the length of a floating point number just displayed.


(It is the value left on the stack by 'F.'.) M is the
desired length. F.EXT extends the number to tne desired
length by displaying M-N zeroes.

F/ ( FP1 FP2 --- FP3 )


Leaves quotient of two floating point numbers. Performs
special case handling.

F< ( FP1 FP2 --- B )


Tests if FP1 < FP2.

(c) 1981 Friends Amis, Inc. 7-9 3 September 81


FLOATING POINT

FABS ( FP --- FP' )


Sets absolute value of floating point number.

FDROP ( FP --- )
Drops four words (one floating point number) from the
stack.

FDUP ( FP --- FP FP )
Duplicates the floating point number (four words) on the
top of stack.

FLIT ( --- FP )
"Floating point literal." Places the next four words after
this tag on the stack, and passes control around the
words.
At run time, FLIT works like the run-time words LIT (which
stacks a word literal) and CLIT (which stacks a character
literal). FLIT is listed here as well as with the run-time
words because the compiler currently cannot generate it
automatically from a floating point constant.
To use FLIT to compile a floating point number, use the
following words:
FLIT [ nl , -V n2 ,-V n3 , -V n4 , -V
where nl to n4 are the values of the four words that make
up the floating point constant, FP.

FNEGATE ( FP --- FP' )


Stacks the negative of FP (i.e., -1*FP).

FOVER ( FP1 FP2 FP1 FP2 FP1 )


Copies the second floating point number on the stack to
the top of the stack.

FP>ASC ( FP NDIGITS ADR LEN NEXP )


Converts a floating point number from internal form to
exponential notation.

FP is the number to be converted. NDIGITS is the number of


significant digits desired in the result.
ADR LEN are the address and length of the mantissa, wnich
is in ASCII. NEXP is the exponent, which is a (binary)
integer.

(c) 1981 Friends Amis, Inc. 7-10 3 September 81


FLOATING POINT

FROUND ( FP NDIGITS FENCE --- FP' NDIGITS' )


vow Rounds a floating point number to a specified number of
digits.
FP is the number to be rounded.
NDIGITS is the desired number of significant digits.
FENCE is the desired position of the last significant
(i.e., possibly non-zero) digit in the rounded number,
relative to the decimal point. A positive value of FENCE
indicates that the last significant digit is to be left of
the decimal point; a negative value of FENCE indicates it
is to be to the right. For example, to round a dollars-
and-cents figure to a whole number of cents, use FENCE=-2;
to round the gross national product to the nearest million
dollars, use FENCE=6.
FP' is the rounded number.
NDIGITS' is the actual number of significant digits.
NOTE: FP is not actually rounded. The last significant
digit is fixed so that when the number is printed with
NDIGITS significant digits (and truncation) it will APPEAR
rounded.
Example: we round 1234.567 to 5 significant digits, with
FENCE=-1. FROUND changes the number to 1234.667. When
printed with NDIGITS=5, this appears as 1234.6.
Another example: we round 1234.367 to 2 significant
digits, with FENCE=2. FROUND leaves the number unchanged.
When printed with NDIGITS=2, the number appears as 1200.

FSTANDTYPE ( N --- TYPE )


Returns the special-case type of a floating point number
on the stack.
N is the stack position at which the number starts. For
example, if the number starts immediately under N, then N
should be 1 (N itself occupies position OM. If the number
starts under N and one other floating point number, then N
should be 5, and so forth.
The possible values of TYPE are:
0 -> valid non-zero number.
1 -> zero.
2 -> underflow.
3 -> overflow.
4 -> complex number.
5 -> zero divide.

(c) 1981 Friends Amis, Inc. 7-11 3 September 81


FLOATING POINT

6 -> enigma or user-defined code (number contains a


codes 6 to FF).
Notice that the codes representing special cases are all 1
greater than the numbers of the cases they represent. This
is because "valid number" and "zero" have distinct codes.

FSWAP ( FP1 FP2 FP2 FPI )


Swaps two floating point numbers.

FVAR ( )
A defining word. Used in a TSA to reserve 8 bytes of
storage for a floating point variable. For example:

FVAR ERRVAL

This reserves a 8 bytes for a variable named ERRVAL.

(c) 1981 Friends Amis, Inc. 7-12 3 September 81


SAMPLE PROGRAMS

This chapter contains several annotated HHC a:,


- Plication
programs written in SNAP.
These programs serve two functions. First, they can serve as
reference points as you develop your own SNAP coding style.
Second, they contain many passages of ready-made code that you
can copy in order to solve some of the common problems you will
encounter, such as how to display a standard-format HHC menu.

SAMPLE i: ORDER ENTRY PROGRAM

The order entry program lets a customer of a hypothetical


retail store order goods through an HHC. It guides the customer
through the process of identifying himself, then displays a list
of goods available and lets the customer enter the quantity he
wants to order for each item.
The program is designed to be entirely self-teaching; that
is, a customer who knows nothing about it can use it without
referring to any instructions outside those provided by the
program itseit.

Use (Technical)

(Inventory File)

The HHC must have an INVENTORY FILE in its virtual file space
cetore the order entry program may be used. This rile aerines the
items the customer will be able to order. The name of the file
must be '0:E.INW.
There are two ways you can create the inventory file: by
running a separate program from the capsule's main menu, or by
using the file editor.
The separate program in the capsule's main menu is titled
something like - create order entry tile." This program creates an
inventory file containing three hard-coded records, for
- binocular bump pads," "titfin guns," and - nypnogiyphs."
If you want to create a larger or more realistic file (e.g.,
for demonstrating the HHC at a trade show), use the tile edizor
and follow the file format explained in the next section.

(Format Of the Inventory File)

The inventory file contains one record per item. The order of
the records is unimportant, except that it aetermines the oraer

(c) 1981 Friends Nmis, Inc. 8-1 3 September 81


SAMPLE PROGRAMS

in which the items will be Presented to tne customer.

The format of a record is:

name-of-item\qty-price\qty-priceX...\qty-price

"name-of-item" is the name of the item this record represents.

Each "qty-price" gives a range of quantities and a unit price


for orders in that range. The ranges should be contiguous; the
range of the left-most "qty-price" should begin at quantity=1,
and the range of the right-most "qty-price" should be open-ended.
For example:

Tiffin guns\1-3 $55.00\4-9 $47.50\l0+ $40.00

The format of each "qty-price" should conform to the example


above. In particular, observe the following rules:

1. Fields should be separated by backslashes. The last field


should NOT be followed by a backslash.

2. Each quantity range except the last should consist of two


numbers separated by a hyphen, with no spaces.
3. The last quantity range should consist of a beginning number
followed by a '+' sign and a blank.

4. The quantity and dollar amount should be separated by one


blank and a '$'.
5. Each price should consist of a dollar figure, a decimal
point, and two "cents" digits.

(The Order File)

The HHC must have an ORDER FILE in its virtual file space in
which to record orders. Unlike the inventory file, the order file
need not be prepared beforehand; the program will create i:
automatically if it does not exist.
The name of the order file is '0.E.ORDER'.

The order file consists of a series of record groups. Each


record group contains information about one order.

Each record group begins with one record containing the name
and address of the person making the order. This is followed oy

(c) 1981 Friends Amis, Inc. 8-2 3 September 81


SAMPLE PROGRAMS

one record per item ordered.


The format of the name-and-address record is:

name\adr-line-1\adr-line-2\...\adr-line-n

For example:

Joe Schlumpf\PO BOX O\Dogpatch, AK

The address may have up to 5 lines.

The format of an item-ordered record is:

inv# qty price

where "inv#" is the origin-0 number of the inventory file record


identifying the item being ordered; "qty" is the quantity
ordered; and "price" is the unit price in cents that applies to
the quantity ordered.
For example, suppose a customer orders 15 of the the item in
record #3 of the inventory file, and the unit price for orders of
15 is $20.00. The item-ordered record will be:

3 15 2000

When the order file is nearly full (less than 100 bytes
remaining in the file space), an attempt to start the inventory
program will produce a warning message like this on the LCD:

FILE SPACE LOW


PLEASE NOTIFY A SALESMAN

The two lines of the warning will appear alternately until the
someone presses CLEAR. The "salesman" should copy the order file
to a Programmable Memory Peripheral if he wants to keep it; then
he should delete it. (The program specs state that the salesman
will use an "upload" function to send the order file to a host
system, where orders would be processed. To date the upload
function has not been implemented, because the modem was not
ready for use the last time the program was modified.)

Use (Customer Interface)

(c) 1981 Friends Amis, Inc. 8-3 3 September 81


SAMPLE PROGRAMS

When you start the order entry program, it gives you a menu
with 3 options: "take an order," "print last order," and uorint
summary of orders." Select "take an order."

Next the program prompts you for your name and address. If
the address has fewer than 5 lines, enter a null line after the
last line of the address.

Next the program asks you if you want instructions. If you


answer Y for "yes," it displays brief instructions on how to run
the program. The instructions are displayed one line at a time.
You may terminate the instructions by pressing the S key.

The program then displays the name of the first item in the
inventory file. You can scroll the inventory file forward with
the V key, and backward with the I key. The file is circular;
i.e. the record after the last is the first, and the record
before the first is the last. The program displays a warning
message before wrapping in either direction.

You can order any item by entering the desired quantity while
that item is being displayed, and pressing ENTER. Alternatively,
you can just press ENTER. Then the program displays the first
quantity-price range and the associated price. You can scroll the
quantity-price ranges with the K- and -> keys. Again, you can
order an item by entering the desired quantity and pressing
ENTER; or you can just press ENTER, in which case the program
orompts you for a quantity.

After you enter the quantity, the program computes the


extended price (product of quantity and applicable unit ofice)
and displays it.

When you are done looking at the extended price, you may
return to the inventory menu by pressing any key.

When you are done entering the order, press the E (for "end")
key. The program displays the total, sales tax (at 6%), and sum
of total and tax.

(Print Order Function)

This function prints the order most recently entered.

To use this function, you must have an 80-column printer


attached to the HHC through a Serial Interface Adaptor. The
printer should be loaded with 9-1/2 x 11" paper, ideally with
pre-orinted order forms which Friends-Amis ordered from NESS
computer supply for this purpose.

As of this writing, the printer does not have to nave a "form

(c) 1981 Friends Amis, Inc. 8-4 3 September 81


SAMPLE PROGRAMS

feed" feature. But there has been talk of making making the
program go to a new page by doing a form feed instead of by
.. counting carriage returns. This is because at trade shows, the
demonstrators tended to alternate this application with others,
and when they used the printer the forms got out of alignment.
Check to see if the program has been modified to do form feeds
before trying to use a printer that does not support that
feature.

(Print Summary Function)

This function prints a one-line summary of each order that


has been entered since the order file was last dumped.
To use this function, you must have an 80-column printer
attached to the HHC through a Serial Interface Adaptor. The
printer should be loaded with 9-1/2 x 11" paper.

Program Structure

The order entry program is actually several programs in a


single capsule. There is one program for each of the following
functions: taking an order, printing the most recent order, and
printing a summary of all orders.
To avoid confusion, we will use the word PROGRAM to refer to
all the software in a capsule. We will use the word FUNCTION to
refer to the distinct parts that one program may consist of; we
would say, for example, that the order entry program has 4
functions.

The HHC has no facility for selecting individual functions,


so the capsule itself must select them in some manner. It
customarily does this by presenting another menu, which operates
just like the primary menu and the application menu in the HHC.
(See Figure B-1.)

111110,-

(c) 1981 Friends Amis, Inc. 8-5 3 September 81


SAMPLE PROGRAMS

primary menu

/ \
/ \

/ \

I application menu I

/ \

.1.1.111

I order entry I
i function menu
i I

i I 1 print I I print I I upload


I take I i last I I order I orders
I an order i I order i I summary I (unimole- I
i i 1 1 , I I ....._ rented)

Figure 6-1

Program With Function Menu

(c) 1981 Friends Amis, Inc. 8-6 3 September 81


SAMPLE PROGRAMS

(The Header)

The first thing compiled in any application program is the


program header. This includes the copyright notice (which must be
present if the HHC is to agree to execute the program) and the
tag table.
For a detailed explanation of the header's format, see the
discussion of the header in the chapter on "General Technical
Information."
We set the base to hex, and set the target dictionary pointer
to ROMADDR (4000H, the beginning of the capsule space).
Then we compile a string constant containing the copyright
notice.
We set the target dictionary pointer to ROMID, and compile a
string constant giving the title of the capsule. The title will
appear in the primary menu when this program's capsule is plugged
into the HHC. When the customer selects this capsule from the
HHC's application menu, the HHC will display the title before
passing control to the mother tag of the capsule.
We define th label MY.TAGTABLE, which will stack the address
of the tag table. THen we compile the tag table. It has room for the
maximum number of short tags (40H) and 88H long tags, beginning
with tag number 200H.
We store the address of the tag table at ROMVECT, and the
number of the tag table at ROMEXT. We set 80H (the value of
PROGBIT) in CSPEED, to indicate what the capsule contains:
an executable program in fast ROM.

We specify that the mother word, MAIN.MAN, and the tag table
vector initialization word, CAP.INIT, will be represented by long
tags. The first and second tags in the long tag table,
respectively, are reserved for them.

Finally, we reset the base to DECIMAL.

(Modifying the Header)

Here are the modifications to the standard header format that


you may wish to make:

1. Change the copyright message to reflect the current year. (DO


NOT make any changes in the message's format.)
2. Change the size of the long tag table.

(c) 1981 Friends Amis, Inc. 8-7 3 September 81


SAMPLE PROGRAMS

3. Change the names of the tag table and the strings. Ordinarily
none of these names are referred to, so changing them will
have no ripple effect.

(Utilities)

The words defined in this section are ones that are likely to
be useful in other applications.

Most of these words relate to formatting numbers for I/O, and


to managing keyboard input. Notice the definition of the EOL
word, which is used later in a call to EXPECT.

(Data and Constants)

Here begin words specifically written for the order entry


application. The major words are:

* INBUF#, a buffer used for all input operations from files.


* KBBUF, a buffer used for all input operations from the
keyboard.

* OUTBUF, a buffer used for all output operations.


* The device numbers and ECB's of the modem (MDMxxx) and
printer (PTRxxx).
Notice that the ECB's are declared as string variables. This
is the most convenient way to declare variables of a specific
length, even if the variables will not be used as strings.
Remember, STRING allocates an actual amount of space one byte
greater than the length, to allow for a length byte.

* Variables for storing different aspects of the state of the


program, such as the number of the inventory item currently
being displayed (O.CURITM).

One colon definition (O.INBUF) is included in this section


because its function is to define a "variable" located one byte
past the beginning of one of the buffers (INBUF4). INBUF is
the buffer actually used for input operations. INBUF4 is present
to allow one byte of space before the beginning of INBUF to told
a binary zero. The binary zero acts as a record delimiter during
backward scans of a string held in the buffer.

Why not simply allocate a separately named one-byte field


before INBUF? Because the HHC does not allocate TSA variables in
the order they are declared! It happens to allocate them in

(c) 1981 Friends Amis, Inc. 8-8 3 September 81


SAMPLE PROGRAMS

reverse order. Rather than write a tricky piece of code which


allocates a delimiter byte AFTER INBUF to make the byte compile
into the address space BEFORE INBUF, we have chosen to allocate a
single field and then sub-divide it by writing a colon
definition. The resulting code is somewhat obscure, but it frees
us from dependence on a detail of the cross-compiler's
implementation.

(I/O Words)

The next section of the program contains words relating to


I/O.

(Order Entry Function)

Here, at long last, comes the guts of the order entry


program.
It will be a useful exercise for you to read the entire
program well enough to understand the function of each word. We
will only point out some tricks and global considerations that
will help you understand the code.
FIND and -FIND are NOT related to the FORTH dictionary
search. (Recall that there is nothing like a dictionary in SNAP
at run time.) They scan a string for a delimiter character. FIND
scans forward; -FIND scans backward. Either one is stopped by a
binary zero, which signifies end-of-string.
FIND and -FIND are used to move forward and backward within
inventory file records. For example, when the HHC is displaying
the first quantity-price field in an inventory item, it has a
"current position" pointer (0.CURITM) which is pointing at that
item:

Tiffin guns\1-3 $55.00\4-9 $47.50\10+ $40.00

When tne customer presses the -> key, the program calls FIND to
move the pointer forward to the next backslash; then it moves the
pointer one byte further to the beginning of the following field.

FETCH.PRICE is used after an item is ordered to find the


price that applies to whatever quantity of that item the customer
has specified.
MOVEDN, MOVEUP, MOVEL, and MOVER ("move down, up, left, and
right") allow the customer to "move around" in the inventory
ogram's state variables to reflect the
file. They update the pr
reauested motion, and update the LCD display. They are called by

(c) 1981 Friends Amis, Inc. 8-9 3 September 81


SAMPLE PROGRAMS

INVKEY, which reads a key from the keyboard and acts on it while
the customer is looking at inventory information and ordering
items.

INVKEY calls ORDER.ITEM when the customer orders an item. If


the customer orders by simply keying in a number, INVKEY receives
the first character of the number; it passes the character to
ORDER.ITEM on the stack. If the customer orders by pressing ENTER
and then keying in a number, INVKEY gets the ENTER and has no
character to pass to ORDER.ITEM; it indicates this by passing
ORDER.ITEM a binary zero.
INIT.ORDER initializes the program's state variables at the
start of each order. Recall that HHC variables are NEVER
initialized automatically; they are allocated on the temporary
stack, and they initially contain whatever garbage was left there
by other programs.

(Print Order Function)

The next part of the program implements the print-an-order


function.

(Function Menu)

The next part of the program is the function menu. It takes


advantage of some standard HHC utilities which all applications
can use to create standard format menus.
The first definition in the function menu is O.PGMS, which
executes the functions represented by the menu options. It takes
one item on the stack, a number indicating which option to
execute. A 0 indicates the first option, a 1 indicates the
second, etc.
The second definition is a table of string constants,
O.MSGLST. The strings identify the menu options, and correspond
to the options executed by 0.PGMS,
The third definition, O.MSG, types one of the strings in
O.MSGLST. The string it types is determined by the number passed
to O.MSG on the stack.

The fourth definition, O.MSGS, allows for wraparound in the


message display. Given a number, it determines whether the number
represents a message. If so, it displays the message and returns
TRUE. If not, it returns FALSE.

The fifth definition, ORDER. MENU, oerforms the entire


function of the program except for initialization. It stacks a I
(the origin-1 number of the first option to display), the address

(c) 1981 Friends Amis, Inc. 8-10 3 September 81


SAMPLE PROGRAMS

of O.PGMS, and the address of O.MSGS. Then it calls an HHC word,


MENU-DRIVER, that performs all the processing associated with a
standard HHC menu.
The sixth definition, ORDER.ENTRY, performs initialization
for the order entry program, and executes ORDER.MENU. Notice that
it sets the tag number of ORDER.MENU at SOFTAG. This makes
ORDER.MENU the word that will be executed by a soft clear.

(File Initialization Function)

Next is a short section of code which implements the file


initialization function. This creates the inventory file that
offers hypnoglyphs, tiffin guns, etc.

(Main Program Menu)

Last is a section of code that implements the top-level menu


for this program. This logic of this code is the same as the
logic of the preceding menu.
CAP.INIT initializes the tag table vector's short extrinsic
table entry. (Recall that the HHC emulator in the development
system will execute this word, the second word in the long tag
table, before the mother word is ever executed.)
MAIN.MAN is the mother word. The first thing it does is call
execute CAP.INIT, which makes it safe to execute short rags. Then
it sets up a call to the menu driver for the capsule's too-level
menu.

(Modifying the Function Menu)

You can adapt the function menu to your own applications


quite easily. Copy the code from O.PGMS through O.MENU, with the
following modifications:

1. Replace the IF.ITS lines in O.PGMS with equivalent lines that


execute your program's functions.

2. Replace the strings in O.MSGLST with eauivalent strings that


describe your program's functions. Note, there should be the
same number of string in O.MSGLST as there are IF. lines
in 0.PGMS, and they should be in the same order.

3. Change the '4' in O.MSGS to the number of IF.ITS lines you


have in O.PGMS.

(c) 1981 Friends Amis, Inc. 8-11 3 September 81


SAMPLE PROGRAMS

4. Change the names of the words to follow any naming


conventions you have adopted for your program. Be sure to
change all references to the changed names.

(c) 1981 Friends finis , Inc. 8-12 3 September 81


SAMPLE PROGRAMS

SAMPLE 2: SKETCH PROGRAM

The sketch program allows the user to "sketch" a picture on


the HHC's LCD. There are functions to save pictures in files,
restore them, etc.

Use

When you run SKETCH, you get a function menu with the
following entries:

MAKE NEW PICTURE


MODIFY EXISTING PICTURE
CONTINUE W/ SAME PICTURE
SAVE THE PICTURE
DELETE A SAVED PICTURE

The operation of SKETCH is organized around two important


concepts. The first concept is EDIT MODE. This is a mode of
operation in which SKETCH lets you create or modify a picture.
Several of the SKETCH menu functions put SKETCH into edit mode.
There is a command in edit mode for returning to the function
menu.
The second important concept is the CURRENT FILE. This is the
picture file which SKETCH is currently working with. SKETCH can
have a current file even when not in edit mode; it is the file
that SKETCH will operate on if you select the function "CONTINUE
WITH SAME PICTURE" or "SAVE CURRENT PICTURE."

(The Editing Functions)

MAKE NEW PICTURE lets you enter the name of a file in which
SKETCH will save the picture you create. SKETCH creates this file
and makes it the current file, and places you in edit mode so
that you can create a picture.
MODIFY EXISTING PICTURE lets you enter the name of an
existing picture file. SKETCH makes this file the current file,
reads the file, and displays the file on the LCD. Then it places
you in edit mode so that you can modify the picture.
CONTINUE W/ SAME PICTURE enters edit mode without changing
the current file.
SAVE THE PICTURE saves the current picture file, including
any modifications you have made to it. After editing a picture
and returning to the program's menu, you save the edited cicture

(c) 1981 Friends Amis, Inc. 8-13 3 September 81


SAMPLE PROGRAMS

by selecting this menu option.

DELETE A SAVED PICTURE lets you enter the name of an existing


picture file. This file becomes the current file, and then is
deleted.

(Safety Features)

If you create or edit a file, and then work on another file


without saving the first one, whatever you have done to the first
file will be lost. This is because nothing is actually written to
the file until you run the SAVE function.

But SKETCH always warns you when you ask it to do anything


which may make you lose work in this way. For example, suppose
you edit one file, then try to edit another file without saving
the first file. SKETCH will ask you if you want to save the first
file before editing the second one. If you reply Y (for "yes"),
SKETCH saves the current file before proceeding. If you reply N
(for "no"), SKETCH proceeds anyway; but when the new file becomes
the current file, any changes you made to the original file are
lost.

SKETCH also stops you from running any functions that do not
make sense. For example, you cannot MAKE NEW PICTURE with the
same name as an existing picture; nor can you CONTINUE WITH SAME
PICTURE after DELETE SAVED PICTURE (because the current file is
the one just deleted).

(Edit Mode)

In edit mode, SKETCH displays a special cursor that consists


of only one dot. You can move the cursor around with the
following keys:

SNAPPLE HHC function


<- <- Move left I column.
-> -> Move right 1 colJinn.
T I' Move up I row.
^G t Move down 1 row.

In its initial "draw" state, the cursor leaves a "trail" of


black dots behind it as it moves. This is how you draw a picture.
SKETCH has two other states: "neutral" and "erase." In
neutral state, the cursor leaves no trail. In "erase" state, the
cursor leaves a trail of clear dots. This enables you to correct
errors in your oicture without starting over.

(c) 1981 Friends Amis, Inc. 8-14 3 September 81


SAMPLE PROGRAMS

You can change the state of SKETCH with the following keys:

SNAPPLE HHC function

F INSERT Puts SKETCH in draw mode (its initial


mode).
RETURN ENTER Puts SKETCH in neutral mode.
^X DELETE Puts SKETCH in erase mode.

There are two additional commands. One makes SKETCH begin


rotating the entire picture from left to right. The other ends
EDIT mode, and returns you to the program's menu.

SNAPPLE HHC function

"B ROTATE Begins rotating the picture left to


right.
e or E e or E End edit mode, returning to menu.

Here is a summary of all the edit mode commands:

SNAPPLE HHC function

<- <- Move left 1 column.


-> -> Move right I column.
Move up I row.
^G * Move down I row.
INSERT Puts SKETCH in draw mode (its initial
mode).
RETURN ENTER Puts SKETCH in neutral mode.
^X DELETE Puts SKETCH in erase mode.
^ 13 ROTATE Begins rotating the picture left to
right.
e or E e or E Ends edit mode, returning to menu.

Program Design

The program is organized in roughly the same way as the order


entry program in example 1. There is a header; then generally
useful utility routines; then data and program-specific utility
routines; then the routines which implement y the program's
functions; then a menu driver.

(Data)

(c) 1981 Friends Amis, Inc. 8-15 3 September 81


SAMPLE PROGRAMS

A picture file contains one 136-character record. Each


character in the record represents one column in the LCD display.
Each bit in each character represents one dot in a column of the
display.

Note: the last 3 columns of the LCD are not used because of a
bug in the HHC's cursor handling code. Although SKETCH makes the
cursor invisible, the HHC insists that the cursor is present
somewhere in the LCD, and will not allow any dots to be turned on
in that position. SKETCH puts the cursor in position 26 of the
LCD, of which only 3 dot columns are visible, because this is the
last objectionable place for the bug to appear.
The current picture file is kept in PICBUF, a "string"
variable in the TSA. BUF>LCD copies it from there directly to the
LCD buffer, with !DISPLAY. Editing is actually done on the data
in the LCD buffer, using @DISPLAY to fetch the contents of a byte
(i.e., a column of dots) and !DISPLAY to store one. The contents
of the LCD buffer is moved back to PICBUF just before SKETCH
leaves edit mode (see EXEC.KEY).

The variable FNAME holds the name of the current file; the
variable L'NAME holds the length of the name.
The variable PICSTAT holds a code indicating the current
contents of the picture file buffer:

0 -> empty (no current picture).


1 -> loaded (there is a picture).
2 -> changed (picture has been edited since loaded).

(The Program)

The mother word is SKETCH; it calls a menu driver structured


just like the one in Example 1. This calls a separate word for
each function.

DRAW is the word that implements edit mode. Each of the words
that puts SKETCH into edit mode does so by executing DRAW.
DRAW consists of a loop that Processes one keystroke per
iteration. Each keystroke is passed to EXEC.KEY for processing.
DRAW and EXEC.KEY maintain all relevent state variables on
the stack. Working from the root toward the tip, they are:

X
X-co-ordinate of cursor (0 to 135).
Y
Y-co-ordinate of cursor. This is expressed as a bit
mask which maybe applied to a byte in the picture file

(c) 1981 Friends Amis, Inc. 8-16 3 September 81


SAMPLE PROGRAMS

buffer representing one column in the picture. A value


of 1 represents the top bit, 2 the next bit down . . .
80H represents the bottom bit.
M
Edit sub-mode. A value of 2 represents "delete;" 1
represents "draw;" 0 represents "neutral" (neither
erase nor draw.)

In addition, WAIT.KEY receives a keystroke on the stack, and


leaves a boolean indicating whether or not DRAW is to return to
the function menu driver.
Notice the use of NAP in WAIT.KEY. This is how SKETCH blinks
the cursor while it is waiting for you to press a key. Each
iteration of the BEGIN . . . UNTIL loop toggles the cursor and
does one 64-tick (0.25 second) NAP. When NAP is ended by a
keystroke, rather than by timer expiration, the loop ends, the
cursor is turned off, and WAIT.KEY returns control to DRAW.
Also notice the extensive use of colon definitions for common
functions. For example, .FILE.NAME is an 8-word definition that
displays the current file's name; it is used in several of the
function words. For another example, .NOFILE does nothing but
print a string constant. We could have made .NOFILE a string
constant and coded ".NOFILE COUNT TYPE" for each reference to it;
but that would take two extra tags in each reference, with no
gain in simplicity or generality. It is usually good practice to
make extensive use of colon definitions for repetitive fragments
of code; it makes your programs shorter, easier to write, and
easier to read.

(c) 1981 Friends Amis, Inc. 8-17 3 September 81


SAMPLE PROGRAMS

SAMPLE 3: INFLATION CALCULATOR

The inflation calculator computes the price of an item with a


specified initial value after a specified period of inflation at
a constant, specified rate.
This program is interesting mainly because it illustrates
some fundamental techniques for working with floating point data.

Use

The program compounds inflation monthly.


The program presents a menu which lets you select among the
following operations:

Specify annual rate of inflation; for example, to specify


10.5%, enter '10.5'.
Specify time in months.
Specify principal amount in dollars & cents; for example, to
specify $36.50, enter '36.50'.
Display rate, time, and principal amount most recently
entered.
Compute inflated amount from rate, time, and principal amount
most recently entered.

To perform a computation, select "annual rate," "time in


months," and "principal amount;" enter an appropriate value for
each. Then select "compute."
After performing one computation, you can perform another
computation by changing one or more factors and selecting
"compute" again.

Program Design

The program has the same general structure as the programs in


previous examples.
The program's data include several declarations of floating
point constants: FP1200 (value 1200.0), FPO (value 0.0), and FP1
(value 1.0). Notice that these constants must be defined in
hexadecimal notation, each constant 4 2-byte words long, because
SNAP has no word for defining a floating-point constant directly.

(c) 1981 Friends Amis, Inc. 8-18 3 September 81


SAMPLE PROGRAMS

You can find the proper hexadecimal value to represent a


given floating point quantity by using the simulator
interactively to convert a floating point number from ASCII
format to binary format. Here is an example. (The text you type
in is shown here in lower case, but would naturally be entered in
upper case.)

OK
hex OK [puts you in base 16.}
string" 1200." asc1200 OK (defines an ASCII constant.}
asc12 00 count asc> fp 2drop OK {converts it to FP. }
. . 0 0 0 1244 OK [types it.}

Notice that ". . ." types the floating point value from the
stack tip word first, which is the reverse of the way you would
use it in a program. For example, the dialog above tells you that
to define a floating point constant with the value 1200.0, you
should code:

HEX HERE
1244 , 0 , 0 , 0 == NAME-OF-THE-CONSTANT

In the TSA, the three variables I.TX, I.RX and I.PX indicate
whether the time, rate, and principal amount have been entered
vet. The variables I.T, I.R and I.P contain the time in months,
the annual rate, and the principal amount, when they have been
entered. I.MR contains the monthly rate, calculated from the
annual rate.

The function menu contains entries for:

ENTER INITIAL PRICE


ENTER ANNUAL INFLATION RATE
ENTER TIME IN MONTHS
DISPLAY INPUT
COMPUTE RESULT

Each of the three "enter" functions calls a word that prompts


you for a value, converts it to internal form, stores it in the
appropriate variable (I.T, etc), and sets the appropriate
"entered" switch (I.TX, etc).
DISPLAY INPUT and COMPUTE RESULT perform the obvious
functions.

(c) 1981 Friends Amis, Inc. 8-19 3 September 81


1111P.

NEW

All*
Friends Amis, Inc. SKETCH/INFL 09-SEP-81 PAGE 1

***********************************

* HEADER & COMMON CODE


* FOR SNAP DEMONSTRATION PROGRAMS *
* (C) 1981, BY FRIENDS AMIS, INC. *
***********************************

\ ***** THE HEADER *****


HEX
ROMADDR SETORG \ CAPSULE SPACE

S" COPYRIGHT FRIENDS AMIS, INC. 1981"


ROMID TO DP-V
S" SKETCH/INFLATION DEMO"
LABEL MY.TAGTABLE
SHINT 040 200 088 TAG .TABLE TABLE.OF.TAGS
MY.TAGTABLE 80 + ROMVECT !-V
2 ROMEXT C!-V
80 CSPEED C!-V
ALL CAPSULES MUST HAVE TWO FIXED TAGS. THE FIRST DEFINED
\ TAG IS THE MAIN ENTRY, CALLED WHEN THE CAPSULE IS RUN FROM THE
HHC MENU. THE SECOND INITIALIZES TAG TABLES, AND POSSIBLY OTHER
\ PARTS OF THE PROGRAM, SO WORDS IN THE CAPSULE CAN BE CALLED WITH
\ ENTERING THROUGH THE FIRST TAG.
LONG MAIN. MAN \ ENTRY POINT
LONG CAP.INIT \ CAPSULE INITIALIZATION: SET UP SHORT TAG TABLE

DECIMAL

***** KEYBOARD SYMBOLS


HEX
1A
22
24
25
2E
45
4E ==

53
59
5C
****** MISCELLANEOUS ROUTINES *****
: ?EOL (S C )
&CR = ;
(P END-OF-LINE-CHARACTER ROUTINE FOR
EXPECT.)
Friends Am is , Inc . SKETCH/INFL 09-SEP-81 PAGE 2

?EOL == 'EOL

•Y/N (S B)
BEGIN KEY L>U
%Y CASE 1 1 ELSE
%N CASE 0 1 ELSE
DROP 0 ENDIF ENDIF
UNTIL ;
(P PROMPT USER FOR A 'Y' OR 'N )

: 0! (S ADR )
0 SWAP ! ;
(P STORES 0 IN THE WORD AT ADR. )
•• •.
. I, •
••
(P WRITES COLON-SPACE TO LCD. )

: PRO (S a•O

"

KEY DROP
BEGIN ?KEY WHILE KEY DROP REPEAT
(P PROMPT USER TO PRESS ANY KEY TO
PROCEED WITH INSTRUCTIONS. )

: LASTKEY (S C )
KEY
BEGIN ?KEY WHILE DROP KEY REPEAT

(P DRAINS THE KEYBD BUFFER & RETURNS THE


LAST KEY IN THE BUFFER. )
Friends Amis, Inc. SKETCH/INFL 09—SEP-81 PAGE 3

***** ARITHMETIC UTILITIES *****

HEX
: DIGIT (S C [N] B )
7F AND 30 —
DUP BASE C@ U< IF
1
ELSE DROP 0 ENDIF ;
DECIMAL

(P CONVERTS AN ASCII DIGIT TO BINARY


ACCORDING TO THE CURRENT NUMERIC BASE
[GIVEN BY THE VALUE OF BASE]. IF C IS
VALID, N IS ITS BIN. VALUE & B IS TRUE;
IF C IS INVALID, N IS ABSENT & B IS
FALSE. )

ASC>N (S ADR LEN --- N ADR' )


BOUNDS \ CEIL ADR
OVER 0 2SWAP \ CEIL N CELL ADR
DO \ DO FOR EACH CHAR
I C@ DIGIT IF \ IS IT A DIGIT?
SWAP 10 * \ YES; ADD TO N.
ELSE SWAPDROP I \ NO.
SWAP LEAVE ENDIF
LOOP
SWAP ;

(P CONVERTS AN UNSIGNED NUMBER FROM


ASCII TO SHORT BINARY. THE ASCII NUMBER
IS AT ADR LEN. N IS THE RESULT. ADR' IS
THE ADDRESS OF THE NEXT POS.N AFTER THE
LAST VALID DIGIT; THUS IF ALL DIGITS ARE
VALID, ADR'=ADR+LEN; ELSE ADR'<ADR+LEN. )

: (D.CHK) (S W D W D' )
0 MAX OVER 1— MIN ;
(P INT.L WORD FOR N>ASC CONVERSION.
FORCES 0<=D<=W-1.)

: (WD.CHK) (S W D W' D' )


SWAP 1 MAX 12 MIN SWAP (D.CHK) ;
(P INT.L WORD FOR N>ASC CONVERSION.
FORCES 1<=W<=12 & 0<=D<=W-1.)

HEX

DN>ASC(D) (S DN D ADR LEN )


12 SWAP (D.CHK) SWAPDROP \ CHECK D.
3 PICK 2SWAP DABS D SIGN DN.
<#
4 PICK 0 ?DO 4 LOOP \ FORMAT DEC PART
vow- 2E HOLD \ PROCESS DEC PT.
2DUP OR IF #S WHOLEPART.
ELSE 4 PICK 0= IF 4 ENDIF ENDIF
Friends Amis, Inc. SKETCH/INFL 09-SEP-81 PAGE 4

ROT SIGN #> ROT DROP ; \ DO # & SIGN.

(P CONVERTS A LONG INTEGER TO ASCII. DN


IS THE INTEGER; D IS THE # OF DIGITS TO
PUT RIGHT OF THE DECIMAL POINT. ADR LEN
POINT TO THE RESULT, WHICH IS AS LONG AS
NECESSARY TO HOLD THE NUMBER.)

: DN>ASC(W,D) (S DN W D --- ADR LEN )


(WD.CHK) \ CHECK W & D.
SWAP OVER >R >R \ DN D; D,W -> R.
aN>ASC(D) \ ADR LEN
R - NEGATE ?DUP IF \ ADR W-LEN
DUP 0< IF \ W<>LEN.
DROP DUP R 2A FILL \ OVERFLOW!!!
R> 2DUP + R> - 1- \ FILL W/"'S
2E SWAP C! \ & SET DECPT.
ELSE >R R - DUP R> \ LEN<W;
20 FILL R> R> DROP \ LPAD W/BLANKS
ENDIF
ELSE R> R> DROP ENDIF ; \ LEN=W.

DECIMAL

(P CONVERTS A LONG INTEGER TO ASCII. DN


IS THE INTEGER; W IS THE DESIRED WIDTH;
D IS THE # OF DIGITS TO PUT RIGHT OF THE
DECIMAL POINT. ADR LEN POINT TO RESULT.
IF TOO SHORT, RESULT IS PADDED LEFT W/
BLANKS; IF TOO LONG, FIELD LOOKS LIKE
*****.**1 )

: .FP(N) (S FP N --- )
>R
14 R 1+ MINUS FROUND
F.
R> F.EXT ;
(P DISPLAYS FP WITH N DIGITS RIGHT OF THE DECIMAL POINT.)
Friends kmis, Inc. SKETCH/INFL 09-SEP-81 PAGE 5

*************************************

* "SKETCH" LCD GRAPHICS PROGRAM


J SACHS 4 JUN 81
*************************************

***** CONSTANTS *****

156 == L'LCD L'LCD IN DOT COLUMNS.


26 == L'FNAME \ L'FILE NAME BUFFER.

***** VARIABLES *****

AREA SK.AREA

L'LCD 1+ STRING PICBUF \ PICTURE BUFFER.


L'FNAME 1+ STRING FNAME FILENAME BFR.
VAR L'NAME L' INPUT FILENAME.
CVAR PICSTAT PICBUF STATUS
0 -> EMPTY
1 -> LOADED
\ 3 -> CHANGED SINCE LOADED
CVAR PICCOL TEMP.STOR. AN LCD COLUMN.

ENDAREA

: SK.INIT (S )
PICBUF L'LCD ERASE
FNAME L'FNAME &BL FILL
0 L'NAME ! 0 PICSTAT C, •
(P INITIALIZE PROGRAM. )

FILE.NAME (S [A L] B )
CR ." ENTER PICTURE FILE NAME."
FNAME L'FNAME ADR MAXLEN
L'NAME @ DUP \ A ML INITL INITL
'EOL %OVR \ A ML IL IL EOL M
EXPECT 2DROP \ A L
DUP L'NAME ! \ UPDATE NAME LEN.
DUP IF \ALI
ELSE 2DROP 0 ENDIF ; 0
(P DISPLAY LAST-ENTERED FILE NAME &
PROMPT USER FOR NEW FILENAME. )

: .FILE.NAME (S )
%" EMIT FNAME L'NAME @ TYPE %" EMIT SPACE
(P TYPE FILE NAME ENCLOSED IN QUOTES.

.NOFILE ." NO FILE PRESENT" ;


Nempr (P TYPES "NO FILE PRESENT." )

.NOFIND ." CAN'T FIND THAT FILE"


Friends Amis, Inc. SKETCH/INFL 09-SEP-81 PAGE 6

(P TYPES "CAN'T FIND THAT FILE." )

: @DISPLAY (S CN F )
DSPLY + PICCOL 1 DMOVE PICCOL C@ ;
(P STACK COL. IMAGE F FROM LCD COLUMN BUFFER.

: !DISPLAY (S F CN )
SWAP PICCOL C!
DSPLY + PICCOL SWAP 1 DMOVE ;
(P PUT COLUMN IMAGE F INTO LCD COLUMN BUFFER.)

: BUF>LCD (S )
PICBUF DSPLY L'LCD DMOVE ;
(P REFRESH LCD FROM PICTURE BUFFER.)

: LCD>BUF (S )
DSPLY PICBUF L'LCD DMOVE ;
(P REFRESH PICTURE BUFFER FROM LCD.)

ERASE .LCD (S )
PICBUF L'LCD ERASE BUF>LCD ;
(P ERASE THE BUFFER & CLEAR THE LCD.)

: LEAVE .DOT (S X Y MODE --- X Y MODE )


DUP IF WHAT MODE?
\ INSERT OR ERASE.
>R RPUSH M
OVER @DISPLAY OVER X Y COLIMAGE Y
R 1- IF \ WHAT MODE?
-1 XOR ( COM ) AND 2=ERASE.
ELSE OR \ 1=INSERT.
ENDIF \ X Y COLIMAGE'
3 PICK !DISPLAY R> UPDT LCD; X Y M
ENDIF ;
(P CURSOR IS LEAVING [X,Y]. SET THE
CORRESPONDING LCD BIT TO:
MODE=0[NEUTRAL]->N0 CHANGE.
MODE=1[INSERT] ->1.
MODE=2[ERASE] ->0. )

: WAIT. KEY (S X Y MODE ---


X Y MODE KEY )
3 PICK @DISPLAY \ X Y M COL
DUP >R \ RPUSH COL
BEGIN
3 PICK XOR \ FLIP CRSR BIT
DUP 5 PICK !DISPLAY \ UPDATE LCD.
64 0 NAP \ WAIT A WHILE.
UNTIL
SWAPDROP R> \XYMK('
5 PICK !DISPLAY ; \ RESTORE LCD.
(P BLINK CURSOR DOT UNTIL A KEYSTROKE IS
RECEIVED. THEN LEAVE DISPLAY IN ITS
ORIGINAL STATE. )
Friends Amis, Inc. SKETCH/INFL 09—SEP-81 PAGE 7

mow : MC. ROTX (S X Y M X' Y M )


L'LCD 1— @DISPLAY \ SAVE LAST COLUMN.
DS PLY DUP 1+ L'LCD 1—
DMOVE \ MOVE THE REST.
0 !DISPLAY \ SET 1ST COLUMN.
ROT 1+ L'LCD MOD ROT ROT ; ROT CRSR.
(P ROTATES THE DISPLAY RIGHT ONE DOT
COLUMN. )

: MC.ROT (S X Y M --- X' Y M )


BEGIN
MC. ROT.X
64 0 NAP UNTIL DROP ;
(P ROTATES DISPLAY UNTIL KEY HIT. )

EXEC .,KEY(S X Y M KEY --- X' Y' M' B )


&< CASE LEAVE.DOT LEFT
ROT 1— 0 MAX ROT ROT 0 ELSE
&> CASE LEAVE.DOT \ RIGHT
ROT 1+ LILCD 1— MIN ROT ROT 0 ELSE
&U CASE LEAVE.DOT \ UP
SWAP 2/ 1 MAX SWAP 0 ELSE
&D CASE LEAVE.DOT DOWN
SWAP 2* 128 MIN SWAP 0 ELSE
&CR CASE DROP 0 0 ELSE NEUT.
&I CASE DROP 1 0 ELSE \ INSRT
mow &K CASE DROP 2 0 ELSE \ DEL
&R CASE MC.ROT 0 ELSE \ ROT
L>U %E CASE
LCD>BUF 2DROP DROP 1 ELSE \ EXIT
DROP 0 ENDIF ENDIF ENDIF ENDIF ENDIF
ENDIF ENDIF ENDIF ENDIF
(P GIVEN A KEYSTROKE, UPDATES THE
PROGRAM'S STATE [EXCEPT FOR DISPLAY
UPDATE, WHICH IS DONE BY WAIT.KEY]. B=
TRUE —> END SKETCH MODE.)

DRAW (S )
LCD.CR BUF>LCD STOP. CURSOR
26 BUFPOSN C! \ JOHN FORKER'S BUG
L'LCD 2/ 16 1 \ INITIAL X Y MODE
BEGIN
WAIT.KEY \ WAIT FOR KEY
EXEC .KEY \ PROCESS THE KEY
UNTIL 'E' KEY ENDS FTN.
LCD.CR START. CURSOR
(P "DRAW" FUNCTION. )
Friends Amis, Inc. SKETCH/INFL 09-SEP-81 PAGE 8

***** PICTURE STATUS CHECKERS *****

HEX

: ?PICLOAD (S B )
PICSTAT C@ 1 AND ;
(P DETERMINES IF A PICTURE IS LOADED. )

: !PICMOD (S )
PICSTAT C@ 3 OR PICSTAT C! ;
(P FLAGS PICTURE BUFFER AS LOADED &
MODIFIED. )

: !PICUNMOD (S )
PICSTAT C@ FD AND PICSTAT C! ;
(P FLAGS PICTURE AS UNMODIFIED. )

: !PICUNLOAD (S )
PICSTAT C@ FC AND PICSTAT C! ;
(P FLAGS PIC. AS UNLOADED & UNMODIFIED. )

DECIMAL

: CONT.PIC (S )
?PICLOAD NOTIF
CR .NOFILE EXIT ENDIF
!PICMOD DRAW ;
(P CONTINUE DRAWING A PICTURE ALREADY IN
THE BUFFER.)

SAVE.PIC (S )
?PICLOAD NOTIF
CR .NOFILE EXIT ENDIF
!PICUNMOD
0 DELETE DROP
PICBUF L' LCD 0 INSERT DROP
CR .FILE .NAME ." SAVED" ;
(P SAVE A PICTURE FROM THE LCD BUFFER TO
THE CURRENT FILE. NOTE, THIS IS CALLED
BY 1 ?SAVEFIRSTT AS WELL AS BY THE MENU
DRIVER. )

?SAVEFIRST (S )
PICSTAT C@ 2 AND IF
CR ." SAVE " .FILE.NAME ." FIRST?"
Y/1\1 IF
SAVE.PIC ENDIF
ENDIF
!PICUNLOAD
(P PROMPTS USER TO SAVE CURRENT PICTURE
IF IT IS FLAGGED AS MODIFIED. IT UNLOADS
THE FILE EVEN IF IT DOESN'T SAVE, SINCE
ITS CALLER IS GOING TO DESTROY THE
CONTENTS OF THE FILE NAME BUFFER. )
Friends Amis, Inc. SKETCH/INFL 09-SEP-81 PAGE 9

New GET. PIC (S )


?SAVEFIRST !PICUNLOAD
FILE.NAME IF \ READ FILENAME.
OPEN IF TRY TO OPEN.
PICBUF READ REC#0,
L'LCD 1+ 0 L'LCD+1.
READ IF
L'LCD = IF \ IF LEN=LCD IT'S
!PICMOD DRAW OK.
FOLLOWING ARE ERROR CONDITIONS.
ELSE CR
." THAT ISN'T A PICTURE FILE"
ENDIF REC#0 LEN WRONG
ELSE CR ." THAT FILE IS EMPTY"
ENDIF \ READ FAILED.
ELSE CR .NOFIND
ENDIF \ OPEN FAILED.
ENDIF ;
(P GET A PICTURE FILE & READ THE PICTURE
INTO THE BUFFER. )

MAKE.PIC (S )
?SAVEFIRST !PICUNLOAD
FILE.NAME IF \ GET FNAME.
2DUP OPEN NOT IF \ SHOULDN'T FIND IT.
MAKE IF SHOULD MAKE IT.
PICBUF L'LCD 0 INSERT \ ENUF SPACE?
IF !PICMOD ERASE .LCD DRAW \ YES.
\ FOLLOWING ARE ERROR CONDITIONS.
ELSE CR ." NO ROOM TOMAKE FILE"
CFILE DELETE-FILE ENDIF
ELSE CR ." CAN'T MAKE FILE"
ENDIF
ELSE CR ." FILE ALREADY EXISTS"
2DROP ENDIF
ENDIF ;
(P MAKE A NEW PICTURE FILE [SHOULD NOT
ALREADY EXIST]. )

DEL. PIC (S )
?SAVEF IRST
FILE.NAME IF ASK NAME.
OPEN IF \ TRY OPEN.
!PICUNLOAD
CFILE DELETE-FILE \ IT WORKED
CR .FILE.NAME ." DELETED"
ELSE
CR .NOFIND ENDIF
ENDIF ;
(P DELETE A PICTURE FILE. )

law ***** MENU *****

HERE
Friends Amis, Inc. SKETCH/INFL 09-SEP-81 PAGE 10

S" MAKE NEW PICTURE"


S" MODIFY EXISTING PICTURE"
Su CONTINUE W/ SAME PICTURE"
S" SAVE THE PICTURE"
S" DELETE A SAVED PICTURE"
== SK.MLIST

: SK.KEY
IF.ITS 0 MAKE.PIC ENDIF
IF.ITS 1 GET.PIC ENDIF
IF.ITS 2 CONT.PIC ENDIF
IF 3 SAVE.PIC ENDIF
IF.ITS 4 DEL.PIC ENDIF
DROP FALSE ;

SK.DS ( N )
SK.MLIST @SA TYPE ;

SK.MTXT ( N )
5 <IF [ 'X SK.DS ] LITERAL TRUE
ELSE FALSE ENDIF ;

SK.MENU (
SK.INIT
BEGIN
1 [ 'X SK.KEY ] LITERAL
( 'X SK.MTXT ] LITERAL
MENU-DRIVER
AGAIN ;
(P EVERYTHING EXCEPT INITIALIZATION.)

HEX

: SKETCH
SK.AREA ?ENOUGH-ROOM
[ 'X SK.MENU LITERAL FLEE

DECIMAL
Friends Amis, Inc. SKETCH/INFL 09-SEP-81 PAGE 11

\ *****************************************
\ * INFLATION CALCULATOR DEMO PROGRAM *
* J SAC HS 4 JUN 81 *
\ *****************************************

\ ***** CONSTANTS *****

HEX
HOST
HERE 3140 , 20 , 0 , 0 , == FP1200
HERE 0 , 0 , 0 , 0 , == FPO
HERE 0140 , 0 , 0 , 0 , == FP1
SNAP
DECIMAL

\ ***** TSA *****

AREA I.TSA
CVAR I.TX \ TIME ENTERED?
CVAR I.RX \ RATE ENTERED?
CVAR I. PX \ PRICE ENTERED?
VAR I.T \ TIME (MONTHS)
FVAR I.R \ ANNUAL RATE.
FVAR I.MR \ COMP. MONTHLY %
FVAR I.P \ PRICE
ENDAREA
Friends Amis, Inc. SKETCH/INF L 09-SEP-81 PAGE 12

\ ***** MISCELLANEOUS HELP WORDS *****

: READINBUF (S --- ADR LEN )


&LBUF 80 0 0 'EOL %OVR EXPECT 2DROP ;
(P READS A LINE FROM KEYBOARD. )

: . ENTER (S --- ) .11 ENTER ii ;


(P TYPES THE WORD 'ENTER ' . )

: ........
(S --- ) . 11 .........11
;
(P TYPES A DOUBLE HYPHEN. )

: I. INVKEY (S --- )
CR . " THAT'S AN INVALID KEY. " ;
(P TYPES "THAT'S AN INVALID KEY. " )

: I. ERR (S --- )
CR ." THAT ISN'T VALID." ;
(P TYPES "THAT ISN'T VALID. )
Friends Amis, Inc. SKETCH/INFL 09-SEP-81 PAGE 13

v. \ ***** MENU OPTIONS & ASSOCIATED WORDS *****

I. RE VU (S )
CR ." PRICE = "
I.PX C@ IF %$ EMIT I.P F@ 2 .FP(N)
ELSE .-- ENDIF
CR ." RATE _
I.RX C@ IF I.R F@ 2 .FP(N) %% EMIT
ELSE .-- ENDIF
CR ." TIME _
I.TX C@ IF I.T @ . ." MONTHS"
ELSE .-- ENDIF ;
(P REVIEWS FACTORS SET SO FAR.)

: I. TIME (S )
.: SPACE
READINBUF \ READ KEYBD.
?DUP NOTIF DROP EXIT ENDIF LL-> QUIT
2DUP + >R ASC>N R> N END' END
<IF I.ERR DROP EXIT ENDIF \ VALID?
DUP 0< IF I.ERR DROP EXIT ENDIF N<0?
DUP 9999 > IF I.ERR DROP EXIT ENDIF
I.T ! 1 I.TX C! ;
(P ACCEPTS & VALIDATES TIME IN MONTHS.)

v. : H.N.B.E. ." HASN'T BEEN ENTERED."


(P TYPES "HASN'IT BEEN ENTERED.")

I.DATA? (S B )
I.PX C@ I.RX C@ I.TX C@ AND AND
DUP NOTIF
CR ." CAN'T COMPUTE RESULT"
CR ." BECAUSE"
I.PX C@ NOTIF
CR PRICE " H.N.B.E. ENDIF
I.RX C@ MOTIF
CR ." RATE H.N.B.E. ENDIF
I.TX C@ NOTIF
CR . n TIME " H.N.B.E. ENDIF
ENDIF ;
(P ENSURES THAT ALL 3 FACTORS HAVE BEEN
ENTERED BEFORE COMPUTING INFLATION. )

I. PRICE (S )

READINBUF \ READ PRICE


?DUP MOTIF DROP EXIT ENDIF \ NULL?
2DUP + >R \ CE IL -> R.
ASC>FP DROP CVT -> FP.
R> < IF I.ERR FDROP ERR, DATA.
ELSE FDUP FPO F@ F< IF
loop I.ERR FDROP \ ERR, <0.
ELSE I.P F! 1 I.PX C! \ GOOD.
ENDIF ENDIF ;
Friends Amis, Inc. SKETCH/INFL 09-SEP-81 PAGE 14

(P READS & STORES PRICE.)

: I. RATE (S --- )

READINBUF
?DUP MOTIF DROP EXIT ENDIF \ NULL?
2DUP --1- >EZ
ASC>FP DROP
R> < IF I.ERR FDROP
ELSE FDUP I.R F! FP1200 F@ F/
I.MR F! 1 I.RX C!
ENDIF ;
(P ACCEPTS & SAVES ANNUAL INTEREST RATE;
COMPUTES & SAVES MONTHLY COMPOUND INTER-
EST RATE.)

: I.COMP (S --- )
I.DATA? IF
CR ." FINAL PRICE = $"
I.MR F@ FP1 F@ F+ I.P F@
I.T @ 0 DO
FOVER F*
LOOP
2 .FP(N) SPACE FDROP
LASTKEY DROP
ENDIF ;
(P COMPUTES & PRINTS INFLATED PRICE. )
Friends Amis, Inc. SKETCH/INFL 09-SEP-81 PAGE 15

\ ***** MENU *****

: I.MKEY (S N --- 0 )
IF.ITS 0 I. PRICE ENDIF
IF.ITS 1 I.RATE ENDIF
IF.ITS 2 I.TIME ENDIF
IF.ITS 3 I.REVU ENDIF
IF.ITS 4 I.COMP ENDIF
DROP FALSE ;

HERE
S" ENTER INITIAL PRICE"
S" ENTER ANNUAL INFL. RATE"
S" ENTER TIME IN MONTHS"
S" DISPLAY INPUT"
S" COMPUTE RESULT"
== I.MLIST

: I.DS (S N --- )
I.MLIST @SA TYPE ;

: I.MTXT (S N --- )
5 <IF [ 'X I.DS ] LITERAL TRUE
ELSE FALSE ENDIF ;

: I.INIT (S --- )
FLAME. ON
0 I.PX C! 0 I.TX C! 0 I.RX C!
(P INITIALIZES THE PROGRAM. )

: I.MENU (S ........... )
I. INIT
BEGIN
1 [ 'X I.MKEY ] LITERAL
[ 'X I.MTXT ] LITERAL
MENU-DRIVER
AGAIN ;
(P EVERYTHING EXCEPT INITIALIZATION.)

: INFLATION (S --- )
I.TSA ?ENOUGH-ROOM
[ 'X I.MENU ] LITERAL SOFTAG
I.MENU ;
(P MOTHER WORD.)
Friends Amis, Inc. SKETCH/INFL 09-SEP-81 PAGE 16

\ *****************************************x********
\ * TRAILER & MAIN MENU FOR DEMONSTRATION PROGRAMS *
\ * SKETCH - INFLATION *
\ **************************************************

HEX

: ESKEY (S N --- B )
IF.ITS 0 INFLATION ENDIF
IF.ITS 1 SKETCH ENDIF
DROP FALSE ; \ CONTINUE

DECIMAL

\ MENU TITLE TABLE


HERE
S" INFLATION CALCULATOR" \ 0
S" THE ELECTRIC SKETCHPAD"
== ESMENU

: .ES (S N --- ) ESMENU @SA TYPE ;

: ESDSP (S N --- )
2 <IF [ 'X .ES ] LITERAL TRUE
ELSE FALSE ENDIF

CAP.INIT \ SECOND TAG TO SET UP TAG TABLE


MY.TAGTABLE TVECTO 1
[ TVECTO 8 + ] LITERAL C@
[ TVECTO 2 + ] LITERAL C1 ;

: MAIN.MAN (S --- ) \ FIRST TAG-ENTRY POINT


CAP.INIT
BEGIN
1 [ 'X ESKEY ] LITERAL
[ 'X ESDSP ] LITERAL
MENU-DRIVER
AGAIN ;
Friends Amis, Inc. 0.E-EXAMPLE 09-S EP-81 PAGE 1

\ ***********************************
\ * HEADER & COMMON CODE *
\ * FOR SNAP DEMONSTRATION PROGRAMS *
\ * J SACHS -- 23 JUN 81 *
\ ***********************************

\ ***** THE HEADER *****

HEX
ROMADDR SETORG \ CAPSULE SPACE

S" COPYRIGHT FRIENDS AMIS, INC. 1981"

ROMID TO DP-V
S" ORDER ENTRY DEMO"

LABEL MY.TAGTABLE
SHINT 040 200 088 TAG. TABLE TABLE.OF.TAGS
MY.TAGTABLE 80 + ROMVECT !-V
2 ROMEXT C!-V
80 CSPEED C!-V
LONG MAIN. MAN \ ENTRY POINT
LONG CAP.INIT \ CAPSULE INITIALIZATION: SET UP SHORT TAG TABLE

DEC IMAL

\ ***** KEYBOARD SYMBOLS

HEX
1A == ^Z
22 == %"
24 == %$
25 == %%
2E == &.
45 == %E
4E == %N
53 == %S
59 == %Y
5C == &\
DEC IMAL

\ ****** MISCELLANEOUS ROUTINES *****

: ?EOL (S C --- B )
&CR = ;
(P END-OF-LINE-CHARACTER ROUTINE FOR
EXPECT. )

'X ?EOL == 'EOL

•Y/N (S --- B)
BEGIN KEY L>U
%Y CASE 1 1 ELSE
,40.. %N CASE 0 1 ELSE
DROP 0 ENDIF ENDIF
Friends Amis, Inc. 0.E-EXAMPLE 09-SEP-81 PAGE 2

UNTIL ;
(P PROMPT USER FOR A 'Y' OR 'N'.)

: 0! (S ADR --- )
0 SWAP ! ;
(P STORES 0 IN THE WORD AT ADR.)
II II
: ;
(P WRITES COLON-SPACE TO LCD.)

: PRO
.1I ....... > II
KEY DROP
BEGIN ?KEY WHILE KEY DROP REPEAT
(P PROMPT USER TO PRESS ANY KEY TO
PROCEED WITH INSTRUCTIONS.)

: LASTKEY (S --- C )
KEY
BEGIN ?KEY WHILE DROP KEY REPEAT

(P DRAINS THE KEYBD BUFFER & RETURNS THE


LAST KEY IN THE BUFFER.)
Friends Amis, Inc. 0.E-EXAMPLE 09-SEP-81 PAGE 3

\ ***** ARITHMETIC UTILITIES *****

HEX
: GETDIGIT (S C [N] B )
7F AND 30 -
DUP BASE C@ U< IF
1
ELSE DROP 0 ENDIF ;
DECIMAL

(P CONVERTS AN ASCII DIGIT TO BINARY


ACCORDING TO THE CURRENT NUMERIC BASE
[GIVEN BY THE VALUE OF BASE]. IF C IS
VALID, N IS ITS BIN. VALUE & B IS TRUE;
IF C IS INVALID, N IS ABSENT & B IS
FALSE.)

: ASC>N (S ADR LEN --- N ADR' )


BOUNDS \ CEIL ADR
OVER 0 2SWAP CEIL N CEIL ADR
DO \ DO FOR EACH CHAR
I C@ GETDIGIT IF \ IS IT A DIGIT?
SWAP 10 * + \ YES; ADD TO N.
ELSE SWAPDROP I \ NO.
SWAP LEAVE ENDIF
LOOP
SWAP ;

(P CONVERTS AN UNSIGNED NUMBER FROM


ASCII TO SHORT BINARY. THE ASCII NUMBER
IS AT ADR LEN. N IS THE RESULT. ADR' IS
THE ADDRESS OF THE NEXT POS.N AFTER THE
LAST VALID DIGIT; THUS IF ALL DIGITS ARE
VALID, ADR'=ADR+LEN; ELSE ADR'<ADR+LEN.)

: (D.CHK) (S W D W D' )
0 MAX OVER 1- MIN ;
(P INT.L WORD FOR N>ASC CONVERSION.
FORCES. 0<=D<=W-1.)

: (WD.CHK) (S W D W' D' )


SWAP 1 MAX 12 MIN SWAP (D.CHK) ;
(P INT.L WORD FOR N>ASC CONVERSION.
FORCES 1<=W<=12 & 0<=D<=W-1.)

HEX

DN>ASC(D) (S DN D ADR LEN )


12 SWAP (D.CHK) SWAPDROP \ CHECK D.
3 PICK 2SWAP DABS D SIGN DN.
<#
4 PICK 0 ?DO # LOOP \ FORMAT DEC PART
2E HOLD \ PROCESS DECPT.
2DUP OR IF #S WHOLE PART.
ELSE 4 PICK 0= IF # ENDIF ENDIF
Friends Amis, Inc. 0.E-EXAMPLE 09-S EP-81 PAGE 4

ROT SIGN #> ROT DROP ; \ DO # & SIGN.

(P CONVERTS A LONG INTEGER TO ASCII. DN


IS THE INTEGER; D IS THE # OF DIGITS TO
PUT RIGHT OF THE DECIMAL POINT. ADR LEN
POINT TO THE RESULT, WHICH IS AS LONG AS
NECESSARY TO HOLD THE NUMBER.)

DN>ASC(W,D) (S DN W D ADR LEN )


(WD.CHK) \ CHECK W & D.
SWAP OVER >R >R DN D; D,W -> R.
DN>ASC(D) ADR LEN
R - NEGATE ?DUP IF \ ADR W-LEN
DUP 0< IF \ W<>LEN.
DROP DUP R 2A FILL \ OVERFLOW!!!
R> 2DUP + R> - 1- \ FILL W/"'S
2E SWAP C! \ & SET DECPT.
ELSE >R R - DUP R> \ LEN<W;
20 FILL R> R> DROP \ LPAD W/BLANKS
ENDIF
ELSE R> R> DROP ENDIF ; \ LEN=W.

DECIMAL

(P CONVERTS A LONG INTEGER TO ASCII. DN


IS THE INTEGER; W IS THE DESIRED WIDTH;
D IS THE # OF DIGITS TO PUT RIGHT OF THE
DECIMAL POINT. ADR LEN POINT TO RESULT.
IF TOO SHORT, RESULT IS PADDED LEFT W/
BLANKS; IF TOO LONG, FIELD LOOKS LIKE
f*****.**, .)

: .FP(N) (S FP N )
>R
14 R 1+ MINUS FROUND
F.
R> F.EXT ;
(P DISPLAYS FP WITH N DIGITS RIGHT OF THE DECIMAL POINT.)
Friends Amis, Inc. 0.E-EXAMPLE 09-SEP-81 PAGE 5

************************************

ORDER ENTRY APPLICATION


J SAC HS 4 JUN 81
************************************

\ ***** CONSTANTS *****

120 == 0.L'OUTBUF L'OUTPUT BFR


120 == O.L'INBUF L'INPUT BFR
16 == 0.L'KBBUF L'KEYBD BFR

HEX

STRING" 0.E.INV" 0.INV INVENTORY FILE NAME


STRING" 0.E.INP" 0.INP \ DATA FILE NAME

42 == MDM.D# \ MODEM DEVICE #


46 == PTR.D# \ PRINTER.

2 == MDM.U# MODEM UNIT #.


3 == PTR.U# \ PRINTER.

AREA 0.TSA

0.L I OUTBUF 2+ STRING 0.0UTBUF \ OUT BFR


0.L'INBUF 2+ STRING 0.INBUF# IPT BFR
0.L'KBBUF STRING 0.KBBUF
4 STRING MDM.ECB \ MODEM ECB
A
STRING PTR.ECB \ PRINT ECB
VAR VID.ECB \ VIDEO ECB

VAR 0.CURITM \ CURRENT INVENTORY ITEM#


VAR 0.CURFLD ADR NEXT FLD IN INBUF
VAR O. QTY \ QUANTITY OF THIS ITEM
VAR 0.PRICE \ PRICE OF THIS ITEM
DVAR 0.TOTAL \ TOTAL PRICE
VAR O.1STITEM REC# THIS ORDER'S 1ST ITEM
VAR 0.NAME REC# THIS ORDER'S CUSTOMER NAME

\ PRINTER VARIABLES
VAR LINE# VAR PAGELEN
VAR COL# VAR LINELEN

ENDAREA

•0.INBUF 0.INBUF# 1+

DECIMAL

***** MISCELLANEOUS UTILITIES


HEX
Friends Amis, Inc. 0.E-EXAMPLE 09-SEP-81 PAGE 6

: .C.B.A ." CAN'T BE ATTACHED!" ,


.

: OPEN.L ( --- B )
PTR.D# PTR.U# ATTACH IF \ TRY ATTACH.
PTR.ECB PTR.U# ROPEN \ TRY OPEN.
ELSE FALSE ENDIF ;
(P "OPEN" EPSON PRINTER.)

: EMIT.L ( C --- )
1 COL# +1
5C CASE 2F ENDIF
PTR.ECB WAIT PTR.ECB 1+ C!
PTR.ECB PTR.U# ROP DROP ;
(P EMIT CHARACTER TO EPSON PRINTER.)

: TYPE.L ( A L --- )
OVER + SWAP ?DO I C@ EMIT.L LOOP ;
(P "TYPE" A STRING TO EPSON PRINTER.)

: CR.L ( --- )
&CR EMIT.L
COL# 0! 1 LINE# +!
: SPACES.L ( N --- )
0 ?DO &BL EMIT.L LOOP ;

DECIMAL
Friends Amis, Inc. 0.E-EXAMPLE 09-SEP-81 PAGE 7

MISCELLANEOUS UTILITIES *****

: . AT

OPEN.INV ( )
O.INV COUNT OPEN NOTIF
CR ." NO INVENTORY FILE!" ENDIF

OPEN. ORDER ( ) 0.INP COUNT 2DUP


OPEN NOTIF MAKE DROP %TEXT GET-TYPE
C! ELSE 2DROP ENDIF ;

PROMPT>OUTBUF (S B )
O.OUTBUF COUNT SWAP OVER + LN CL
0.L'OUTBUF ROT - \ CL LEN-REMAIN
&LBUF SWAP CL &LBUF LEN-REMAIN
0 0 'EOL %OVR EXPECT \ CL +A +L E' K M
2DROP \ CL +A +L
>R SWAP R CMOVE R> \ MOVE IT; +L
0.0UTBUF +C! 1 ; INCR LENBYTE
(P READS A STRING FROM KEYBD & APPENDS
IT TO 0.0UTBUF.)

: +OUTBUF (S C )
0.0UTBUF COUNT + C! 1 0.0UTBUF +C! ;
(P APPENDS A CHARACTER TO 0.0UTBUF.)

: STR>OUTBUF (S ADR LEN --- )


0.0UTBUF COUNT SWAP OVER + TO-LN TO
0.L I OUTBUF ROT - TO TO-LN-REMAINING
ROT MIN ADR TO LN
DUP 0.0UTBUF +C! CMOVE ; \ MOVE & INCR
(P APPEND A STRING TO 0.0UTBUF.)

FIND (S ADR C [ADR'] B )


SWAP BEGIN \ C ADR
2DUP C@ C ADR C C'
>R R = R> 0= OR 0= \ C 1 =C OR NUL
WHILE 1+ REPEAT
SWAP OVER C@ = IF \ LEAVE ADR 1
1 ELSE DROP 0 ENDIF ; OR 0.
(P FIND 1ST OCCURENCE OF CHAR C AT/AFTER
ADR. IF NULL IS FOUND 1ST, ADR' IS
ABSENT & B IS FALSE.)

HEX
HERE
S" PRESS '5' KEY TO START."
S" FOR NEXT ITEM PRESS X." \ UPARROW
-2 ALLOT-V 33 C, &. C,
S" FOR LAST ITEM PRESS X." DOWNARROW
-2 ALLOT-V 80 C, &. C,
S" FOR NEXT PRICE PRESS XXX." ->
'4110,
-4 ALLOT-V &ESC C, ESCDC C, 82 C, &. C,
S" FOR LAST PRICE PRESS XXX." <-
Friends Amis, Inc. 0.E-EXAMPLE 09-SEP-81 PAGE 8

-4 ALLOT-V &ESC C, ESCDC C, 81 C, &. C,


S" TO ORDER AN ITEM,"
S" PRESS ENTER,"
S" THEN TYPE QUANTITY,"
S" AND PRESS ENTER AGAIN.
S" TO END ORDER,"
S" PRESS 'E' KEY."
0 C,
== 0.HLST
DECIMAL

: 0.HELP ( --- )
O.HLST BEGIN
DUP C@ NOTIF DROP 0.HLST ENDIF
COUNT 2DUP CR TYPE
+
?KEY IF KEY L>U %S = ELSE 0 ENDIF
UNTIL DROP
(P ROTATE THROUGH 0.HLST UNTIL USER
PRESSES 'S'.)

\ ***** TAKE AN ORDER. *****

: INIT. ORDER (S - )
0 0 0.TOTAL 2!
0.CURITM 0! 0.CURFLD 0!
0.INBUF# 0!
LINE4 0! COL# 0!
66 PAGELEN ! 35 LINELEN !
(P INITIALIZATION FOR AN ORDER.)
Friends Amis, Inc. 0.E-EXAMPLE 09-S EP-81 PAGE 9

-FIND (S ADR C [ADR B)


SWAP BEGIN
2DUP C@
>R R = R> 0= OR 0=
WHILE 1- REPEAT
SWAP OVER C@ = IF
1 ELSE DROP 0 ENDIF ;
(P LIKE FIND BUT SCANS RIGHT TO LEFT. )

: . TYPE " TYPE

: N>OUTBUF (S N )
S>D <# # #S #> STR>OUTBUF ;
(P CONVERTS A NUMBER TO ASCII & APPENDS
IT TO 0.0UTBUF.)

: D. $&C (S DN )
&. HOLD 2DUP OR IF \ .
#S ENDIF &$ HOLD #> TYPE ; $
(P INTERPRETS N AS A NUMBER OF CENTS &
PRINTS A PRICE IN THE FORM 1 $DD.CC 1 .)

: PROMPT.NAME (S )
OPEN. ORDER
REC-CNT 0.NAME
0 0.0UTBUF C! &\ +OUTBUF
CR ." YOUR NAME: "
PROMPT>OUTBUF DROP &\ +OUTBUF
CR ." HOUSE ADDRESS:
PROMPT>OUTBUF DROP &\ +OUTBUF
CR ." CITY, STATE ZIPCODE:
PROMPT>OUTBUF DROP
O.OUTBUF COUNT REC-CNT INSERT DROP ;
(P PROMPTS FOR NAME & ADDRESS AT START
OF AN ORDER.)

HEX

: LAST . FLD (S ADR ADR )


BEGIN
DUP 5C FIND
WHILE SWAP DROP 1+ REPEAT ;
(P MOVE PTR FROM 1ST PRICE FIELD TO LAST
PRICE FIELD IN AN INVENTORY RECORD. )

: \FIND (S ADR ADR' )


SC FIND DROP 1+ ;
(P FIND BEGINNING OF NEXT FIELD, DELIMITED
BY A BACKSLASH.)

: FETCH .PRICE (S N )
0.INBUF 1+ \FIND \ SKIP NAME FLD
BEGIN \ SEARCH QTY/$S
DUP 7F ASC>N SWAP DROP \ AMIN AMAX-1
1+ 7F ASC>N DROP \ A-MIN MAX
Friends Amis, Inc. 0.E-EXAMPLE 09-SEP-81 PAGE 10

DUP 0 > SWAP A-MIN ?MAX MAX


0.QTY @ < \ A-MIN ?MAX ?<
AND WHILE \ UNTIL MAX>QTY
\FIND REPEAT \ ADV FIELD.
DUP 5C FIND IF \ POINT TO I V
SWAP DROP ELSE \ OR NULL
0 FIND DROP ENDIF \ DELIMITER.
2- DUP 2 ASC>N DROP \ A-CC CC
SWAP 1- DUP \ CC C-$$ C-$$
20 -FIND DROP 1+ \ CC C-$$ A-$$
DUP C@ 24 = IF 1+ ENDIF \ SKIP 1 $ 1 .
SWAP OVER - ASC>N DROP \ CC $$
64 * + ; TOTAL IN CC
(P LOCATES 1ST PRICE FIELD W/MAX-QTY>=
0.QTY & RETURNS ITS PRICE IN CENTS.)

RECORD.ITEM (S
0 0.0UTBUF C! \ NULL >OUTPUT.
0.CURITM @ N>OUTBUF ITEM# >OUTPUT
20 +OUTBUF \ BLANK >OUTPUT
0.QTY @ N>OUTBUF \ QTY >OUTPUT
20 +OUTBUF \ BLANK >OUTPUT
0.PRICE @ N>OUTBUF \ UNIT PRICE
OPEN. ORDER
0.0UTBUF COUNT REC-CNT INSERT DROP
OPEN.INV ;
(P WRITES AN ORDERED ITEM TO THE ORDER
FILE.)

DEC IMAL

: WRAPMSG (S )
CR ." YOU HAVE REACHED THE
DUP 0< IF ." START" ELSE • END"
ENDIF
CR ." OF THE INVENTORY LIST."
CR ." THE NEXT ITEM YOU SEE"
CR ." WILL BE THE "
DUP 0< IF
." LAST." ELSE ." FIRST." ENDIF
0 > IF
CR ." PRESS 'E' TO END ORDER."
ENDIF ;
(P INVENTORY LIST WRAP MESSAGE. 3=1 ->
WRAP FROM END TO START; 8=-1 -> WRAP
FROM BEGINNING TO END.)

: INVREAD (S )
OPEN.INV \ OPEN INV. FILE.
0.INBUF 0.L'INBUF \ READ CUR. RCD.
0.CURITM @ READ DROP
0.INBUF 0 SWAP C! \ PUT NUL AT END.
0.INBUF 0.CURFLD ! ; \ SET FIELD ADR.
(P READS CURRENT RECORD FROM INVENTORY
FILE INTO INBUF.)
Friends Amis, Inc. 0.E-EXAMPLE 09-SEP-81 PAGE 11

INVDISP (S )
0.CURFLD @ DUP &\ \ A A '\'
FIND NOTIF \ A A' (A('\')).
DUP 0 FIND DROP ENDIF
OVER \ A L
CR TYPE ; \ TYPE IT.
(P DISPLAYS CURRENT FIELD OF CURRENT
RECORD.)

: MOVEDN (S )
OPEN.INV 0.CURITM @ 1+ \ ITEM #.
DUP REC-CNT < NOTIF > MAX.?
1 WRAPMSG DROP 0 ENDIF \ YES; WRAP.
0.CURITM ! \ STORE #.
INVREAD ; \ READ RCD.
(P MOVE DOWN TO NEXT INVENTORY ITEM.)

MOVEUP (S )
OPEN. INV 0.CURITM @ 1- \ ITEM #.
DUP 0< IF < 0?
-1 WRAPMSG DROP \ YES; WRAP.
DROP REC-CNT 1-
ENDIF
0.CURITM ! \ STORE #.
INVREAD ; \ READ RCD.
(P MOVE UP TO PREVIOUS INVENTORY ITEM.)

MOVEL (S )
O.CURFLD @ 2- \ A(LAST CHR) PRV FLD.
DUP C@ NOTIF \ IS THERE ONE?
DROP \ NO.
0.INBUF 0 FIND DROP 1- \ C(RCD)-1.
ENDIF
&\ -FIND IF 1+ \ GO BACK TO
ELSE 0.INBUF ENDIF \ TO START IF NONE.
0.CURFLD ! ; \ SET A(FIELD).
(P MOVE LEFT 1 FIELD IN CURRENT INVENTORY RECORD.)

: MOVER (S )
0.CURFLD @ &\ FIND IF
1+ A(NEXT FIELD).
ELSE 0.INBUF ENDIF \ NONE; USE STRT
0.CURFLD ! ; \ SET A(FIELD).
(P MOVE RIGHT 1 FIELD IN CURRENT INVENT-
ORY RECORD.)

ORDER. ITEM (S C )
&LBUF C! \ SAVE 1ST CH
CR ." ENTER QUANTITY: "
&LBUF 10 OVER C@ IF 1 2 ELSE 0 0 ENDIF
'EOL %OVR EXPECT 2DROP \ READ ++
2DUP fi >R ASC>N CVT ->N UM
R> = IF VALID?
DUP O. QTY ! \ YES; SAVE
Friends Amis, Inc. 0.E-EXAMPLE 09-S EP-81 PAGE 12

FETCH.PRICE DUP O. PRICE 1 \ QTY,


S>D ROT SD* \ PRICE,
2DUP O. TOTAL 2@
D+ O. TOTAL 2! \ CUM. TOT;
CR . '1 EXTENDED PRICE IS " D. $&C
RECORD . ITEM MOVE DN \ RCD & ADV
ELSE
CR . " THAT'S NOT A VALID NUMBER."
ENDIF ;
(P PROMPTS FOR QTY; SAVES QTY, DISCOUNTED
PR ICE CUMULATIVE TOTAL; DIS PLAYS EXTENDED
PRICE; RECORDS ITEM IN FILE . )
Friends Amis, Inc. 0.E-EXAMPLE 09-SEP-81 PAGE 13

INVKEY (S B )
KEY L>U
IF.ITS &< MOVEL 1 ENDIF MOVE LEFT
IF.ITS &> MOVER 1 ENDIF MOVE RIGHT
IF.ITS &U MOVE UP 1 ENDIF MOVE UP
IF.ITS &D MOVEDN 1 ENDIF \ MOVE DOWN
IF.ITS &CR
0 ORDER.ITEM 1 ENDIF ENTER
DUP GETDIGIT IF \ A DIGIT.
DROP DUP ORDER.ITEM 1 ENDIF
IF.ITS %a 0 ENDIF \ END.
SWAPDROP ;
(P PROCESS USER RESPONSE.)

***** PRINT ORDER SUMMARY *****

RETRIEVE.ITEM (S A L --- A L' )


2DUP + 0 SWAP CI \ PUT NULL AFTER RC
ASC>N ITEM#: N CEIL
SWAP 0.CURITM ! SAVE ITEM#; CEIL
1+ 0.L T INBUF ASC>N \ QTY: N CEIL
SWAP 0.QTY ! \ SAVE QTY; CEIL
1+ 0.L'INBUF ASC>N PRICE (CC):N CEIL
DROP 0.PRICE ! \ SAVE PRICE.
OPEN.INV \ OPEN INV. FILE.
0.INBUF DUP 0.L'INBUF INBFR: A A L'
0.CURITM @ READ 2DROP ITEM RCD: A
DUP \FIND 1- OVER - ;
(P RETRIEVE ITEM: GIVEN ORDER RECORD IN
INBUF, SETS 0.CURITM, O. QTY & 0.PRICE &
RETURNS ADR/LEN OF NAME OF ITEM [WHICH
IS IN INBUF].)

: SUMMARY.NAME (S A L )
1- SWAP 1+ SWAP TYPE.L CR.L ;
(P PRINT A NAME RECORD IN THE QUEUE
SUMMARY.)

SUMMARY .ITEM (S A L )
RETRIEVE.ITEM \ FORMAT RECORD.
0.QTY a S>D 5 0 DN>ASC(W,D) 1-
TYPE.L 2 SPACES.L
>R R TYPE.L
28 R> - 1 MAX SPACES.L
].PRICE @ S>D 6 2 DN>ASC(W,D) TYPE.L
3 SPACES.L
0.PRICE @ S>D 0.QTY @ SD*
3 2 DN>ASC(W,D) TYPE.L CR.L
(P PRINT AN ITEM RECORD IN THE QUEUE
SUMMARY.)
Friends Amis, Inc. (LE-EXAMPLE 09-SEP-81 PAGE 14

HEX

PRINT .SUMMARY (S )
INIT.ORDER
80 PTR.ECB C!
OPEN. ORDER CR.L
REC-CNT 0 ?DO
OPEN.ORDER
0.INBUF DUP 0.L'INBUF I READ DROP
OVER C@ &\ =
IF SUMMARY.NAME
ELSE SUMMARY.ITEM
ENDIF
LOOP
CR ;
(P PRINT A SUMMARY OF THE ORDER QUEUE.)
DECIMAL

: PROMPT .ORDER (S )
OPEN. ORDER
REC-CNT 0.1STITEM ! \ START WRITE HERE
INVREAD \ READ 1ST INV RCD
BEGIN INVDISP INVKEY WHILE REPEAT ;
(P PROMPT USER FOR HIS ORDER; CONTINUE
UNTIL INVKEY RETURNS 0, INDICATING LAST
ITEM ENTERED.)

REVIEW.ORDER (S )
CR ." SUMMARY OF YOUR ORDER:"
OPEN. ORDER
REC-CNT 0.1STITEM =a ?DO FOR EACH RCD
OPEN. ORDER
0.INBUF DUP 0.L'INBUF READ,
I READ DROP TYPE NAME,
RETRIEVE .ITEM CR TYPE \ GET DATA,
.: SPACE 0.QTY @ . .AT \ TYPE QTY,
0.PRICE @ S>D D.S&C \ PRICE, ":"
0.PRICE @ S>D \ EXTENDED
0.QTY @ SD* D. $&C PRICE.
LOOP ;
(P REVIEWS THE ORDER AFTER LAST ITEM HAS
BEEN ENTERED)

•SHOW .TOTALS (S )
CR ." TOTAL IS " 0. TOTAL 2@ D. $&C
O. TOTAL 2@ 6 SD* 100 UM/ SWAP DROP S>D
CR ." SALES TAX a 6% IS " 2DUP D. $&C
0.TOTAL 2@
CR ." TOTAL TAX IS " D.$&C
(P SHOWS TOTAL, TAX, & TOTAL+TAX.)

: ACCEPT, ORDER? (S )
CR ." TAKE ORDER AS SHOWN (Y/N)?"
Y/N IF
Friends Amis, Inc. 0.E-EXAMPLE 09-SEP-81 PAGE 15

CR ." THANK YOU FOR YOUR ORDER!"


ELSE
CR .'I CANCELLING ORDER."
OPEN .ORDER REC-CNT
BEGIN
DUP O. NAME @ < NOT
WHILE
DUP DELETE DROP
1-
REPEAT
DROP
ENDIF ;
(P ASK USER IF THE ORDER JUST ENTERED
SHOULD BE ACCEPTED.)
Friends Amis, Inc. 0.E-EXAMPLE 09-SEP-81 PAGE 16

\ ***** PRINT AN ORDER *****

DN>$&C (S DN L --- A L'


>R DN ; R= W
0 # # &. HOLD FMT . CC
2DUP OR IF #S ENDIF FMT $$$$
&$ HOLD #> FMT '$'; A L
R> OVER - >R N'BLNKS TO ADD
R 0 > IF
R + SWAP R - SWAP A-N L+N
OVER R> &BL FILL \ ***** PRINT AN ORDER

• DN>$&C (S DN L --- A L'


>R DN; R= W
# # &. HOLD FMT .CC
2DUP OR IF #S ENDIF FMT $$$$
&$ HOLD #> FMT '$'; A L
R> OVER - >R N'BLNKS TO ADD
R 0 > IF
R + SWAP R - SWAP \ A-N L+N
OVER R> &BL FILL \ BLANK FILL.
ELSE R> DROP ENDIF ;
(P GIVEN A DOUBLE NUMBER & DESIRED LEN,
FORMATS THE NUMBER AS $NNNN.NN & RETURNS
ADR/LEN. NOTE, L' WILL BE LONGER THAN L
IFF DN WON'T FIT IN L POSITIONS.)

SKIP.TO.COLUMN (S N .11, .11

DUP COL# @ > IF \ ANY WORK TO DO?


DUP LINELEN a > \ YES; TOO MUCH?
IF DROP CR.L \ YES; DO CR.
ELSE \ NO; DO
COL# N-COLNUM
DO &BL EMIT.L LOOP \ SPACES.
ENDIF
ELSE DROP \ NO WORK TO DO.
ENDIF ;
(P SKIP TO COLUMN N ON EPSON PRINTER.)

: FORM.FEED (S
BEGIN
CR. L \ DO CR'S
LINE# a PAGELEN \ UNTIL END
< WHILE REPEAT
LINE# 0! ; \ OF PAGE.
(P DO "FORM FEED" ON EPSON PRINTER BY
CR'S UNTIL LINE#=PAGELEN.)

•SKIP.TO.LINE
DUP LINE; @ > IF \ ANY WORK TO DO?
DUP PAGELEN @ > \ YES; TOO MUCH?
IF DROP FORM.FEED \ YES; FF.
ELSE \ NO; EMIT
LINE# N-LINE#
DO CR.L LOOP \ CR'S.
Friends Amis, Inc. 0.E-EXAMPLE 09-S EP-81 PAGE 17

ENDIF
ELSE DROP \ NO WORK TO DO.
ENDIF ;
(P SKIP TO LINE N ON EPSON PRINTER. )

HEX

PR .CUST (S )
OPEN. ORDER
O. INBUF DUP O. L INBUF
O. NAME @ READ DROP \ GET NAM , ADR
OVER + SC SWAP C! \ TERMINATE
1+ \ SKIP 1ST BACKSLASH
3 0 DO *** RISKY
DUP \FIND
SWAP 2DUP - 1- \ CIEL OLD CIEL-OLD
OC SKIP.TO.COLUMN
TYPE.L CR.L \ LINE OF CUST
LOOP DROP ;
(P PRINT A CUSTOMER'S ORDER.)

: RTYP.L (S A L MAXLEN COL )


SKIP. TO. COLUMN
OVER - 0 ?DO
&BL EMIT.L \ PAD FIELD
LOOP
TYPE.L ; \ NOTE: L > MAXLEN
\ IS PERMITTED

DEC IMAL

\ EXTENDED PRICE COLUMN


: EX. PR
3 72 RTYP.L
Friends Amis, Inc. 0.E-EXAMPLE 09-SEP-81 PAGE 18

HERE
S" THE PANASONIC HAND HELD COMPUTER"
== THE.HHC

HERE
S" ORDER ENTRY DEMONSTRATION PROGRAM"
== 0.E.D.P.

: PR.0.1 (S )
6 SKIP.TO.LINE
12 SKIP.TO.COLUMN
THE.HHC COUNT TYPE.L CR.L
12 SKIP.TO.COLUMN
0.E.D.P. COUNT TYPE.L CR.L
13 SKIP.TO.LINE
PR. OUST ;
(P PRINTS HEADING & NAME ON AN ORDER
FORM.)

PR.0.2 (S )
24 SKIP.TO.LINE
OPEN. ORDER
REC-CNT 0.1STITEM @ ?DO
OPEN. ORDER
0.INBUF DUP 0.L'INBUF I READ DROP
RETRIEVE.ITEM
0.QTY @ S>D 5 0 DN>ASC(W,D)
1- 5 1 RTYP.L
O.CURITM @ 230 +
S>D 4 0 DN>ASC(W,D) 1-
4 21 RTYP.L OVER C@ EMIT.L
30 SKIP.TO.COLUMN TYPE.L
0.PRICE @ S>D
7 DN>$&C 8 60 RTYP.L
0.PRICE @ S>D
0.QTY @ SD* 2DUP
0.TOTAL 2@ D+ 0.TOTAL 2!
7 DN>S&C EX.PR CR.L
LOOP ;
(P PRINTS THE ITEMS-ORDERED PART OF AN
ORDER FORM.)

PR.0.3 (S )
58 SKIP.TO.LINE
0.TOTAL 2@
7 DN>S&C EX.PR
61 SKIP.TO.LINE
0.TOTAL 2@ 5 SD*
100 UM/ SWAP DROP S>D
2DUP 7 DN>S&C EX.PR
64 SKIP.TO.LINE
O.TOTAL 2@ 0+
7 DN>S&C EX.PR CR.L ;
(P PRINT TOTALS PART OF AN ORDER FORM.)
Friends Amis, Inc. 0.E—EXAMPLE 09—SEP-81 PAGE 19

HEX

: PRINT.ORDER (S --- )
80 PTR.ECB C!
INIT. ORDER
PR.0.1 PR.0.2 PR.0.3
FORM .FEED ;
(P PRINT AN ORDER.)

DECIMAL

\ ***** MENU *****

: TAKE .ORDER (S --- )


INIT.ORDER PROMPT. NAME 0.HELP
PROMPT. ORDER REVIEW .ORDER SHOW .TOTALS
ACCEPT.ORDER? ;
(P TAKE AN ORDER [CALLED BY MAIN MENU].)

•0.PGMS
IF.ITS 0 TAKE .ORDER ENDIF
IF.ITS 1 PRINT.ORDER ENDIF
IF.ITS 2 PRINT .SUMMARY ENDIF
DROP FALSE ;

HERE
S" TAKE AN ORDER"
,nor S" PRINT LAST ORDER"
S" PRINT SUMMARY OF ORDERS"
== 0.MSGLST

: O. MSG
0.MSGLST @SA TYPE ;

•0.MSGS
3 <IF [ 'X 0.MSG ] LITERAL TRUE
ELSE FALSE ENDIF ;

•ORDER. MENU
INIT.ORDER \ INITIALIZATION!
100 ?ROOM NOTIF
BEGIN
. " FILE SPACE LOW" CR
. " PLEASE NOTIFY A SALESMAN" CR
AGAIN
ENDIF
BEGIN
1 [ 'X 0.PGMS ] LITERAL
[ 'X 0.MSGS ] LITERAL
MENU—DRIVER
AGAIN ;
(P WHOLE PROGRAM EXCEPT INITIALIZATION. 'FLEE'
GOES HERE, & CONTROL RETURNS HERE ,THEN 'CLEAR'
IS PRESSED.)
Friends Amis, Inc. 0.E-EXAMPLE 09-SEP-81 PAGE 20

HEX
•ORDER. ENTRY
0.TSA ?ENOUGH-ROOM
80 PTR.ECB C!
80 POZECB C!
0.1STITEM 0! 0.NAME 0!
OPEN. L
[ 'X ORDER.MENU ] LITERAL SOFTAG !
ORDER.MENU ;
(P MOTHER WORD FOR ORDER ENTRY.)
DECIMAL
Friends Amis, Inc. 0.E-EXAMPLE 09-SEP-81 PAGE 21

\ ****************************************
\ * BUILD INVENTORY FILE FOR ORDER ENTRY *
\ * J SAC HS 4 JUN 81 *
\ ****************************************

HERE
S" BINOCULAR BUMP PADS\1-5 .50\6-10 .40\11+ .35"
S" TIFFIN GUNS\1-3 55.00\4-8 40.00\9+ 30.00"
S" HYPNOGLYPHS\1-9 10.00\10+ 8.00"
HOST 0 , SNAP
== LINES

: PUT.IT.OUT ( --- )
0.INV COUNT MAKE DROP
%TEXT GET-TYPE C!
LINES BEGIN
DUP COUNT REC-CNT INSERT DROP
COUNT +
DUP C@ WHILE REPEAT
DROP ;
Friends Amis, Inc. 0.E-EXAMPLE 09-SEP-81 PAGE 22

\ **************************************************
\up
\ * TRAILER & MAIN MENU FOR DEMONSTRATION PROGRAMS *
\ * ORDER ENTRY *
\ **************************************************

: ESKEY (S N --- B )
IF.ITS 0 PUT.IT.OUT ENDIF
IF.ITS 1 ORDER. ENTRY ENDIF
DROP FALSE ; \ CONTINUE

\ MENU TITLE TABLE


HERE
S" ORDER ENTRY CREATE FILE"
S" ORDER ENTRY APPLICATION"
== ESMENU

: .ES (S N --- ) ESMENU @SA TYPE

: ESDSP (S N --- )
2 <IF ( 'X .ES ] LITERAL TRUE
ELSE FALSE ENDIF
;
\ SET UP TAG TABLE VECTORS
: CAP. INIT \ CALL BY SNAP INTERPRETER AND OTHERS TO SEI
MY.TAGTABLE TVECTO ! \ TABLES AND OTHER INITIALIZATION WITH
( TVECTO 8 + ] LITERAL C@ \ WITHOUT ENTERING THE MAIN ROUTINE -....
( TVECTO 2 + 3 LITERAL C! ;

: MAIN.MAN (S --- )
CAP. INIT
BEGIN
1 'X ESKEY
'X ESDSP
MENU-DRIVER
AGAIN ;

DECIMAL
THE SNAP ASSEMBLER

This chapter does NOT attempt to teach you how to write


assembler programs for the 6502. Assuming you already nave that
I~~ skill, it teaches you how to use the SNAP assembler.
If you want to learn about 6502 assembler programming, get a
book on that topic, such as Programming the 6502, by Rodney Zaks.

(c) 1981 Friends Amis, Inc. 9-1 3 September 81


THE SNAP ASSEMBLER

OVERVIEW

The SNAP assembler is provided for coding routines that would


run too slowly if written as colon definitions. It is designed so
that assembler code may be written in a manner similar to SNAP
code. Routines may be written first in SNAP, and then recoded in
assembler when experience shows that more efficiency is needed
(and where it is needed).

To put the assembly process in context, it is useful to look


at a typical assembler language word definition. Following is the
definition of CMOVE, which moves a specified number of bytes from
one location to another, low-addressed byte first.

CODE GRAB ( N [A] B )


TOP 1+ LDA, \ SEE IF REQ < 256...
0= IF, \ CONTINUE IF REQ < 256
TOP LDA ACC=SIZE REQUESTED
>GETMEMT JSR, \ ATTEMPT GRAB
CS IF, \ CONTINUE IF SUCCESSFUL
TOP STY, \ PUT ADDR ONTO STACK
TOP 1+ STA,
1 # LDA, \ SET ACC =TRUE
PUSHOA JMP, RETURN TRUE.
ENDIF,
ENDIF,
PUTFLS JMP, \ RETURN FALSE.
ENDCODE

We will go into detail about the meaning of this code a


little later. For now, notice the following things:

I. The word definition begins with CODE and the name of the word
being defined, and ends with ENDCODE; this is analogous to a
high level definition beginning with I:I and the name of the
word, and ending with

2. Processing is done with words similar to 6502 opcodes LDA,


JSR, CPY, etc. -- but all of these words end with commas.

3. Flow of execution is controlled with words similar to those


used in SNAP proper: BEGIN, UNTIL, IF, ENDIF, etc.

...t2
Two Types of Routines

Routines written in assembler can be divided into two types.


First is the CODE WORD. This type is defined with the
CODE . . . ENDCODE words. It can be called Just like a colon
definition.

(c) 1981 Friends Amis, Inc. 9-2 3 September 81


THE SNAP ASSEMBLER

The second type of assembler routine is the LOW LEVEL


PROCEDURE. It uses the standard 6502 subroutine linkage (call
with JSR„ return with RTS,). It can be called only from a CODE
word or from another low level procedure.

(c) 1981 Friends Amis, Inc. 9-3 3 September 81


THE SNAP ASSEMBLER

THE ASSEMBLY PROCESS

The word CODE creates a tag table entry for an assembler word
definition, and also initiates the assembly process. We will call
a word defined by CODE a CODE DEFINITION or a CODE WORD.
The assembly process consists of interpreting code with the
context vocabulary set to ASSEMBLER.
The ASSEMBLER vocabulary contains definitions of the words
that make up assembler programs (e.g., it contains the 6502
opcodes). The primary function of these words is to deposit
machine code in the target address space.
If the SNAP interpreter fails to find a word in the ASSEMBLER
vocabulary, it goes on to search the current vocabulary (if any),
then the SNAP or ULTRA vocabulary; then it tries to interpret the
word as a number; then it gives an "undefined word" error. Note
that these are exactly the same rules that the SNAP interpreter
follows at other times!

The Assembler Does Not Work In Compile Mode

It is important to understand that the interpreter is NOT in


compile mode while it is assembling a CODE word. Because of this,
words used in CODE definitions can function differently from the
same words used in colon definitions.
During assembly, each assembler word is EXECUTED. If it is a
label, it stacks an address. If it is an opcode, It generates a
6502 instruction. Other kinds of assembler words select an
addressing mode, etc.

For example, consider the following assembler code, which


generates one machine instruction:

N 2+ )Y STA,

When the CODE definition containing tnis code is inter'oreted, :he


code is EXECUTED, producing the following results:

1. N stacks the address of N.


2. 2+ adds 2 to the address of N.
3. )Y indicates that this instruction should use indirect
indexed Y addressing.
4. STA, generates a Store Accumulator (STA) operation, using

(c) 1981 Friends Amis, Inc. 9-4 3 September 81


THE SNAP ASSEMBLER

indirect indexed Y addressing, with an address field taken


from the tip of stack -- value N+2.

Getting In and Out Of the Assembler Vocabulary

CODE makes the ASSEMBLER vocabulary the SNAP compiler's


context vocabulary; it also defines a CODE word (i.e., it makes
an entry in the current tag table). ENDCODE resets the context
vocabulary to be the same as the current vocabulary.
If you write several CODE words in succession, it is not
strictly necessary to end each one with ENDCODE, but it is good
practice to do so for the sake of clarity.
You can also make the ASSEMBLER vocabulary the context
vocabulary by executing ASSEMBLER. This has the same effect as
CODE, except that it does not make an entry in the tag table. It
is used for defining low level procedures.

(c) 1981 Friends Amis, Inc. 9-5 3 September 81


THE SNAP ASSEMBLER

OPCODES

The assembler recognizes the full 6502 instruction sec. It


uses the standard 6502 mnemonics with a comma (I,') suffixed to
each. There are three reasons for the comma:

1. It shows the conclusion of a group of words that corresponds


to one line of code in a conventional assembler language.
2. ',' places data in the dictionary; therefore, ending a word
with ',' emphasizes the fact that code is being generated.

3. The op codes 'ADC,' and 'ADD,' are distinguished from the


hexadecimal numbers 'ADC' and 'ADD'.

Figure 7-1 shows the 6502 opcodes in the forms that they are
recognized by the SNAP assembler.

(c) 1981 Friends Amis, Inc. 9-6 3 September 81


THE SNAP ASSEMBLER

BCC, CLV, SED,


BCS, DEX, SEI,
BEQ, DEY, TAX,
BMI, INX, TAY,
BNE, INY, TSX,
BPL, PHA, TXS,
BRK, PHP, TXA,
BVC, PLA, TYA,
BVS, PLP,
CLC, RTI,
CLD, RTS,
CLI, SEC,

One-mode Opcodes

ADC, EOR, ORA,


AND, INC, ROL,
ASL, JMP, ROT,
BIT, JSR, SBC,
CMP, LDA, STA,
CPX, LDX, STX,
CPY, LDY, STY,
DEC, LSR,

Multi-mode Opcodes

FIGURE 7-1
6502 SNAP ASSEMBLER OPCODES

(c) 1981 Friends Amis, Inc. 9-7 3 September 81


THE SNAP ASSEMBLER

OPERANDS

Assembler operands are generally labels that represent a


location in ROM or in the part of RAM that is Permanently
allocated. You can define your own symbols to use as assembler
operands, but to do so correctly, you must understand the
consequences of the rule that the interpreter is not in compile
mode while assembling.
For example, you cannot use a symbolic equate as an assembler
operand, because a symbolic equate generates a SNAP tag when it
executes. (Recall that symbolic equates are defined as immediate
words.)

Addressing Modes

The assembler has a complete set of words for specifying


addressing modes. Each of these words applies to the next opcode
assembled. It is customary to use these words between the operand
and the opcode.

The addressing-mode specifiers are shown in Figure 7-2.

(c) 1981 Friends Amis, Inc. 9-8 3 September 81


THE SNAP ASSEMBLER

WORD MODE OPERAND

.A accumulator none
immediate 3 bits only
,X indexed X z-page or absolute
,Y indexed Y z-page or absolute
X) indexed indirect X z-page
)Y indirect indexed Y z-page
indirect absolute
none memory z-page or absolute

Figure 7-2(a)

Assembler Addressing Modes

WORD SNAP NOTATION CONVENTIONAL NOTATION

.A ROL, ROL A
1 # LDY, LDY #1
,X N ,X STA, STA N,X
,y N ,Y CMP, CMP N,Y
X) 6 X) ADC, ADC (06,X)
)Y N )Y STA, STA (N) ,Y
N 2+ ) JMP, JMP (N+2)
none NEXT JMP, JMP NEXT

Figure 7-2(b)

Examples of Addressing Modes

(c) 1981 Friends Amis, Inc. 9-9 3 September 81


THE SNAP ASSEMBLER

FLOW OF CONTROL

IF . . . ELSE • . ENDIF

The SNAP assembler is designed to be used without the


conditional jump instructions that are customarily used by
assembler programmers. In place of these, it offers a set of
structured transfer-of-control operations similar to those in
high level SNAP. For example, an IF-THEN-ELSE clause looks like
this:

N LDA,
0= IF, N 1+ ADD,
ELSE, N 2+ ADD,
ENDIF,

As in a colon definition, the code assembled between 'IF,' and


'ELSE,' is executed if a condition is true; the code between
'ELSE,' and 'ENDIF,' is executed if the condition is false. If
only the "true" code is present, 'ELSE,' is absent and the "true"
code is delimited by 'ENDIF,'.

'IF,' assembles to a conditional jump around the "true" code.


'ELSE,' assembles to an unconditional jump around the "false"
code.

The Condition Specifier

The condition that 'IF,' and other conditional operations


test is the 6502's processor status condition code.

A conditional operation such as 'IF,' must be Preceded by a


CONDITION SPECIFIER indicating what condition counts as "true."
The assembler recognizes the following conditional specifiers:

SPECIFIER PROCESSOR
WORD STATUS TEST NATURE OF TEST

CS C=1 carry flag set


0< N=1 byte less than zero
0= Z=1 byte equal to zero
CS NOT ,_, carry flag clear
0< NOT N=l byte not less than zero
0= NOT 1=1 byte not equal to zero
VS NOT V=1 overflow flag not set

71-1‘. UNTIL Loop

(c) 1981 Friends Amis, Inc. 9-10 3 September 81


THE SNAP ASSEMBLER

The structure of the UNTIL loop is:

BEGIN,
TOP LDA, N ,Y STA,
INX, INY, N 1- CPY,
0= UNTIL,

The significance of the condition specifier before 'UNTIL,' is


the same as for 'IF,'.

The WHILE Loop

Just as the assembler has an UNTIL loop, it has a WHILE loop.

The structure of the WHILE loop is:

BEGIN,
TOP LDA, N ,Y STA,
0= WHILE,
INX, INY, N 1- CPY,
REPEAT,

The significance of the condition specifier before 'WHILE,' is


the same as for I rjNTIL,' and 'IF,'.

The AGAIN Loop

You can specify a non-terminating loop with BEGIN, and


AGAIN,:

BEGIN,
CALLED-PROCEDURE-1 JSR, 0= IF, NEXT JMP, ENDIF,
CALLED-PROCEDURE-2 JSR, 0= IF, NEXT JMP, ENDIF,
CALLED-PROCEDURE-3 JSR, 0= IF, NEXT JMP, ENDIF,
•• •
AGAIN,

(c) 1981 Friends Amis, Inc. 9-11 3 September 81


THE SNAP ASSEMBLER

HHC CALLING CONVENTIONS

SETUP

The HHC has a low level procedure named SETUP which pops
input values off the parameter stack and stores them in a
workarea in RAM.
On entry to SETUP, the accumulator should contain the number
of 16-bit values to be popped. This number may be in the range 1
to 8.

SETUP pops the parameter values to a 16-byte area named N.


The tip value is popped to N, the next to N+2, and so on.
CAUTION: it is not safe to assume that the contents of N will be
preserved across any call to a lower-level word or procedure!

Low Level Procedures

When you define a low level procedure, you must identify its
entry point with a LABEL. You can do this with the LABEL word.
For example:

HEX
LABEL CKCPYRT
OiC EDY,
BEGIN,
ROMADDR ,Y LDA,
CPYRTMSG ,Y CMP,
0= NOT IF, RTS, ENDIF,
DEY,
0= UNTIL, RTS,

This piece of code defines a low level procedure named CKCPYRT,


which can be called from a CODE definition according to the
normal 6502 calling convention:

CKCPYRT JSR,

Jumping To CODE Words

In addition to jumping to a low level procedure begin with


LABEL, you can jump to any CODE word; when :he CODE word is none
executing, it will pass control to NEXT.

For example, consider the definition of CMOVE, given earlier

(c) 1981 Friends Am is, Inc. 9-12 3 September 81


THE SNAP ASSEMBLER

in this chapter. It ends by jumping to DROP, which is a SNAP


word. DROP deletes the tip entry from the stack, and jumps to
NEXT. Here is the HHC's definition of DROP:

CODE DROP
INX, INX, UN BX BSP,
NEXT JMP,

Return to Caller From a CODE Word

The last executable instruction in your CODE word should


return control to the SNAP inner loop, which advances execution
from one tag in a colon definition (e.g., the colon definition
calling your CODE word) to the next.
The simplest way to return control is to jump to NEXT:

NEXT JMP,

This returns control directly to the inner loop.


Many CODE words end by jumping to some other location, where
a piece of low level code performs some common operation and then
passes control on to NEXT. For example, CMOVE ends by jumping to
DROP; the code at DROP removes the tip entry from the parameter
stack, and then jumps to NEXT.
Labels that CODE words may usefully jump to are given in the
assembler section of the glossary.

Leaving a CODE Word

To leave a CODE word before the end of the word, simply


execute a 'NEXT JMP,' or the equivalent in the middle of the word
(e.g., inside an 'IF, . . ENDIF,').
To leave a low level procedure at any point, execute
1 RTS,'.

Calling a SNAP Word From a CODE Word

It is often useful for a CODE word to call a high level


(i.e., SNAP) word.
The following example shows how this is done. The columns of
dots represent assembler code; the words between them represent a

(c) 1981 Friends Amis, Inc. 9-13 3 September 81


THE SNAP ASSEMBLER

Passage of SNAP code that will be executed in-line.

(:P)
SNAP words go here..
(;P)


'(:P)' assembles a 'BRK,' instruction. At run time, the


'BRK,' causes a transfer of control to an interpreter routine
that pushes the return address onto the return stack and goes to
NEXT. NEXT begins interpreting the following SNAP code.

lJ 1 switches SNAP from immediate mode to compile mode.

The SNAP code to be executed comes between']' and It may


consist of any number of SNAP words.
'(;P)' compiles to code that pops the return address off the
return stack and transfers control to it.

CAUTION!: the symbols that begin and end the high level code
are '] [1 , not 1 []'. This oddity is due to the fact that the
symbols 1 1] 1 were originally intended to escape FROM compile mode
in order to execute some statements (e.g., to compute tne value
of a svmbol at compile time). Here they are being used to escaPe
INTO compile mode, so their order must be reversed.

(Assembling Low Level Procedures Outside SNAP)

If you have the misfortune to be assembling code in a stand-


alone environment, without the aid of SNAP, you can write high
level code by starting with a 'BRK,' followed by a list of tags
for the high level words you want to execute, and ending witn the
tag for 1 (;P)1. You must find the tags for 1 (;P)' and the high
level words you want to execute by locking at a comcile log for
tne HHC nucleus. See the document on the cross-compiler :or
information on how to read this log.

CAUTION! be sure to use a CURRENT log, since the numeric


values of tags are liable to change from one compile to the next.

(c) 1981 Friends Amis, Inc. 9-14 3 September 81


THE SNAP ASSEMBLER

HHC CODING CONVENTIONS

Using the Parameter Stack

The parameter stack is located on page 0; it grows down from


location OFEH. (Location OFFH is used to store the stack pointer
when the CPU is turned off.) The stack pointer is customarily
kept in register X; it points to the tip (next-to-pop) entry on
the stack.
To drop an entry from the stack, increment X by 2. To push an
entry onto the stack, decrement X by 1 and store the high-order
half of the entry at the location indicated by X; then decrement
X by 1 again and store the low-order half of the entry.
The tip and next-after-tip stack values are referenced so
often that the assembler allows you to refer to them with the
labels TOP and SEC.

THIS: IS EQUIVALENT OR THIS CONVENTIONAL


TO THIS, ASSEMBLER CODE:

TOP LDA, 0 X) LDA, LDA (0,X)


TOP 1+ LDA, 1 X) LDA, LDA (1,X)
SEC LDA, 2 X) LDA, LDA (2,X)
SEC 1+ LDA, 3 X) LDA, LDA (3,X)

It is often convenient to end a word by jumping to one of tne


following low level procedures or CODE words, all of which end by
jumping to NEXT:

POP Drops the tip entry on the stack.


2POP Drops the tip two entries on the stack.

PUSH Pushes a new entry on the stack. The low byte of the
entry contains the value in the accumulator. The
high byte contains the tip byte of the return stack.
The tip byte of the return stack (NOT a whole entry)
is dropped.
PUSHOA Pushes a new entry on the stack. The low byte of the
entry contains the value in the accumulator. The
high byte contains zero.
PUT Drops the tip entry on the stack, th.,n does a PUSH.

PUTOA Droos the tip entry on the stack, then does


PUSHOA.

(c) 1981 Friends Amis, Inc. 9-15 3 September 81


THE SNAP ASSEMBLER

PUTFLS Drops the tip entry on the stack and pushes a 0


(boolean FALSE).

PUTTRU Drops the tip entry on the stack and pushes a 1


(boolean TRUE).

Several other low level procedures are listed in the


assembler glossary.

Using the Return Stack

SNAP's return stack is the 6502's hardware stack. Thus, the


return stack may contain both SNAP return addresses, pushed and
popped by NEXT, and low level procedure return addresses, pushed
by JSR's and popped by RTS's.

You can use the machine instructions 'PHA,' and 'PLA,' to


push data on the return stack and pop it off, one byte at a time.

Temporary Storage

The HHC has several storage areas in page-0 RAM that are
available for use by low level code.

XSAVE, already mentioned, is a one-byte area set aside f or


storing the X register. A CODE word or low level crocedure may
use it for any purpose, but may not safely assume that it will be
preserved across any call to a lower-level routine.

N is a 16 byte area which a CODE word or low level procedure


may use for any purpose. You may not safely assume that N will be
preserved across any call to a lower-level routine.

The SNAP Instruction Pointer

The SNAP instruction pointer is kept in RAM at a location


addressed by the label 'IP'. It contains the address of the tag
that will be interpreted next by the inner loop (NEXT).

Hardware Register Usage

SNAP observes the following register usage conventions:

REGISTER ON ENTRY CONTAINS ON RETURN MUST CONTAIN

X Address of tip entry on Same, updated to reflect

(c) 1981 Friends Amis, Inc. 9-16 3 September 81


THE SNAP ASSEMBLER

parameter stack. entries added or dropped.


New Y 0 Does not matter.
S 1 less than address of Same.
tip entry on return
stack.
A Unpredictable. Does not matter.
arith. Binary mode. Binary mode.
mode

(c) 1981 Friends Amis, Inc. 9-17 3 September 81


THE SNAP ASSEMBLER

SECURITY

The assembler makes several tests for errors in the code it


assembles:

1. The parameter stack must have the same depth at the end of a
definition as it had at the beginning.

2. Conditionals must be properly nested and paired.


3. The address mode and operand associated with each opcode must
be valid for that code.

One error NOT trapped by the assembler is referencing a


synonym of a word you want, in the wrong vocabulary. For example,
a reference to '0=' will ordinarily reference a word which has
meaning only in assembler code. If you want to reference the SNAP
'0=' , you must switch vocabularies.

(c) 1981 Friends Amis, Inc. 9-18 3 September 81


THE SNAP ASSEMBLER

EXAMPLES
law
Below are several examples of CODE words and low level
procedures to help you become familiar with the SNAP assembler
and the techniques of writing low level code for the HHC.

After each example are annotations which expand on the


comments in the code. The annotations are keyed to the line
numbers that accompany the code.

Example 1: SETUP

SETUP is the procedure, described above, which pops a


specified number of entries from the parameter stack to the work
area, N. The tip entry goes to N, the next entry to N+2, etc.

0 LABEL SETUP \ Y=0 ON EXIT; X IS UPDATED.


1 0 # LDY, .A ASL, N 1- STA,
2 BEGIN,
3 TOP LDA, N ,Y STA,
4 INX, INY, N 1- CPY,
5 0= UNTIL,
6 0 # LDY, CLC, RTS,

0. Recall that X points to the tip of the stack. Since some


number of entries are being popped off the stack, X mus--. 1- be
,_Ipdated.
0 is loaded into Y. A contains the number of words to pop;
is shifted left 1 bit, producing the number of bytes to poo.
This is stored at N-1.
3. The tip byte of the stack is loaded into A and then stored at
(N,Y).
4. Both X and Y are incremented. Y is compared to the contents
of N-1, the number of bytes to pop.
3. Until Y = (N-1) (the meaning of 0= after a compare), we loop
back to line 2 to pop the next byte.
6. When we have popped the proper number of bytes, we load Y=0,
clear the carry flag, and return to the caller.

Example 2: U*

U* multiplies two 16-bit unsigned numbers, and leaves a 32-


,
440- bit unsigned product.

(c) 1981 Friends Antis, Inc. 9-19 3 September 81


THE SNAP ASSEMBLER

0 HEX
1 CODE U* ( U1 U2 --- DU )
2 SEC LDA, N STA, SEC STY,
3 SEC 1+ LDA, N 1+ STA, SEC 1+ STY,
4 10 # LDY,
5 BEGIN,
6 TOP 2+ ASL,
7 TOP 3 + ROL, TOP ROL, TOP 1+ ROL,
8 CS IF,
9 CLC,
10 N LDA, TOP 2+ ADC, TOP 2+ STA,
11 N 1+ LDA, TOP 3 + ADC, TOP 3+ STA,
12 CS IF,
13 TOP INC,
14 0= IF,
15 TOP 1+ INC,
16 ENDIF,
17 ENDIF,
18 ENDIF,
19 DEY,
20 0= UNTIL
21 NEXT JMP,
22 ENDCODE

Consider the stack on entry to U. It looks like this (L and


H stand for "low byte" and "high byte"):

SO S1

\

i
1 U2L U2H 1 UlL U1H
1 I

I<---tip of stack high memory --->

U* first moves Ul to a scratch area, N, and zeroes it on • e


stack:

UIL U1H

(c) 1981 Friends Amis, Inc. 9-20 3 September 81


THE SNAP ASSEMBLER

SO S1

1 i 1
I U2L U2H I 0 0 I
i 1 .
. 1
I<---tip of stack high memory --->

Next U* begins a loop♦ The loop shifts the tip 4 bytes of the
stack (SO/S1) left one bit. A 0 goes into the lowest bit of Si,
and the highest bit of SO goes into the carry flag, C. Then, if C
is set (i.e., if the bit shifted out of SO was 1) it adds Ul to
Si.

The loop is executed 16 times, once for each bit in U2. When
it is done, U2 has been shifted out of existence, and SO/S1
contains the product, DU.

2-3. Ui is copied from S1 to N. Si is set to O. (The value of


Y is always set to 0 by NEXT.)

4. Y is set to 16. This is the number of times the loop


will iterate.

ya•- 5-7. The loop begins. The 32-bit unit SO/S1 is shifted left
one bit. Notice how S1 is addressed as 'TOP 2+ and 'TOP
3 +', rather than 'SEC' and 'SEC 1+'. This makes no
difference in the assembled code, but it emphasizes that
we are treaing S1 as an extension of SO, and not as a.
separate 16-bit parameter.
8-11. If C (the bit just shifted out of SO) is 1, we add Ui to
Si.

12-17. If there was a carry out of Si, we increment SO.

19-20. End of the loop. Y is decremented; we loop until Y=0,


then we jump to NEXT.

Example 3: SHIFT

SHIFT shifts a word, X, left a specified number of bits, N.


If N is negative, X is shifted right.

0 CODE SHIFT ( X NS --- X' )


1 TOP 1+ LDA,
2 0< NOT IF,
3 BEGIN,

(c) 1981 Friends Amis, Inc. 9-21 3 September 81


THE SNAP ASSEMBLER

4 TOP LDA, 0= NOT WHILE,


5 SEC ASL, SEC 1+ ROL,
6 TOP DEC,
7 REPEAT,
8 POP JMP,
9 ENDIF,
10 BEGIN,
11 TOP LDA, 0= NOT WHILE,
12 SEC 1+ LSR, SEC ROR,
13 TOP INC,
14 REPEAT,
15 POP JMP,
16 ENDCODE

The word loads NS's high byte (NSH) into A. It uses the
"negative" or "sign" flag to choose a left shift (N=0) or a right
shift (N=1). Then it executes one of two loops to shift X the
proper number of bits in the proper direction.

1. Loads NSH into A.

2. If the load set N=0, the left-shifting loop is executed.

3-4. Begin the left-shifting loop. If NSL has been


decremented to 0, escape from the loop; else proceed.
5-7. Shift NS left one bit; decrement NSL and repeat. End of
the left-shifting loop.

6. Jump to POP. POP will drop NS and jump to NEXT.

10-15. The right-shifting loop. Control falls to here if the IF


. . ENDIF in 2-9 is not executed. The procedure is the
same, except that we shift right, not left. N<0, so we
increment it toward zero.

(c) 1981 Friends Amis, Inc. 9-22 3 September 81


GLOSSARY

The following glossaries are designed for reference. They


will NOT provide an introduction to SNAP, even if you are fluent
in FORTH. Read the preceding chapters for introductory material
before you try to use the glossaries.

HHC WORDS

Beginning with '!' through '@

( X A --- )
Stores X at A. Pronounced "store" or "bang."

!-V ( X A --- ) COMP


Stores X at A in the cross-compiler's target address
space. Pronounced "store-dash-V" or "bang-dash-V."

( ND1 ND2 )
Used to convert binary numbers to ASCII. See description
of <# for details.

( ND --- A L )
Used to convert binary numbers to ASCII. See description
of <# for details.

#DECB ( A )
(Stacks address of DECB, a timer ECB used by the LCD
display routines. #DECB is a short tag; thus you should
use #DECB instead of DECB to save a byte in your code.)

4S ( ND1 ND2 )
Used to convert binary numbers to ASCII. See description
of <# for details.

%BASIC ( --- FL ) NOTE,=


File-type mask used with GET-TYPE to designate the
"Microsoft BASIC program file" attribute. NOTE: %BASIC is
the customary symbol for this mask, but the symbol is not
pre-defined. If you need it, define it as 10H.

%DELETE ( N)
"Delete mode" mask for EXPECT's mode parameter. See EXPECT
for details.

%EXECUTE ( N )

(c) 1981 Friends Amis, Inc. 10-1 29 October 81


GLOSSARY

File-type mask used with GET-TYPE to designate the


"executable" attribute.

%INSERT (--- N) .
"Insert mode" mask for EXPECT's mode parameter. See EXPECT
for details.

%INVISIBLE ( --- N )
File-type mask used with GET-TYPE to designate the
"invisible" attribute.

%LD ( ___ N )
"Lock-delete mode" mask for EXPECT's mode parameter. See
EXPECT for details.

%LI ( --- N )
"Lock-insert mode" mask for EXPECT's mode parameter. See
EXPECT for details.

%OVR ( m N)
"Overstrike mode" mask for EXPECT's mode parameter. See
EXPECT for details.

%TEMPORARY ( --- N )
File-type mask used with GET-TYPE to designate the
"temporary" attribute. (Not presently used.)

%TEXT ( --- N )
File-type mask used with GET-TYPE to designate the "text"
attribute.

&2SH ( --- c )
(The binary value input by the 2nd SHIFT key. Application
programs never get to see this keystroke; it is filtered
out by the I/O routines in the nucleus.
(Note that the 2nd SFT key normally is processed by the
keyboard handling routines in the nucleus, so that an
application program never sees it.)

&< ( ___ C )
The binary value input by the "cursor left" key.

&> ( m c )
The binary value input by the "cursor right" key.

(c) 1981 Friends Amis, Inc. 10-2 29 October 81


GLOSSARY

&APS ( --- A ) V6
A 6-byte area in page 0 which is available for use by
application programs. This area is not used by any part of
the HHC*I s operating system. It is destroyed only by a hard
clear.

&BL ( )
The binary value input by the "space" key. The name stands
for "blank."
See the description of 20H.

&BSP ( )
The binary value input representing the ASCII character
"backspace" (not represented on the HHC keyboard).

&C1 ( )
&C2 ( )
&C3 ( )
&C4 ( )
The binary values input by the HHC keys "Cl," "C2," "C3,"
and "C4."

&CFILE ( A) V2
Pointer to the currently open virtual file. If no file has
been opened since the most recent soft or hard clear, the
pointer is zero.

&CR ( )
The binary value input by the ENTER key. It represents the
ASCII control character RETURN. Sent to an output device,
performs a carriage return; sending this character to the
LCD is equivalent to doing a CR.

&CSR ( )
The binary value input by the "search" key.

&D ( )
The binary value input by the "cursor down" key.

&ESC ( )
The binary value representing the ASCII control character
ESCAPE. Not represented on the HHC keyboard. Sen to an
output device, it begins an escape control sequence.

(c) 1981 Friends Amis, Inc. 10-3 29 October 81


GLOSSARY

&EXTRINSIC ( --- A ) V1
Indicates whether the current virtual file space is the
extrinsic or the intrinsic file space (i.e., in a
Programmable Memory Peripheral or in intrinsic RAM). A
zero value means intrinsic. A non-zero value indicates
extrinsic; the value is the number of the RAM bank
currently selected.

&FP ( A) V6
A temporary storage area used by floating point code
words. It is safe for application programs to use, but its
contents may be destroyed by the execution of any floating
point word.

&HLP ( )
The binary value input by the HELP key.

&I ( )
The binary value input by the INSERT key.

&IO ( )
The binary value input by the I/O key.

&K ( )
The binary value input by the DELETE key.

&KL ( N)
("Delete line" keyboard code. Not used in the current
version of the HHC.)

&LBUF ( A) V80
An 80-character area which you may use as an input buffer
for EXPECT.

&LF ( )
The value of the ASCII control character LINE FEED (not
represented on the HHC keyboard).

&LK ( )
(The binary value input by the LOCK key. Application
programs never get to see this keystroke; it is filtered
out by the I/O routines in the nucleus.

(Note that the LOCK key normally is processed by the


keyboard handling routines in the nucleus, so that an

(c) 1981 Friends Amis, Inc. 10-4 29 October 81


GLOSSARY

application program does not see it.)

&LOCK ( --- FL ) V1
(A byte used by EXPECT to implement its handling of the
LOCK key.)

&MEM ( A ) V8
(Used by the intrinsic calculator for "memory." Do not use
this area; if you do, you will destroy the contents of the
calculator's memory. HHC specs state that the memory
persists across hard clears.)

&MODE ( --- FL ) V1
(A byte used by EXPECT to implement its handling of the
INSERT and DELETE keys.)

&R ( )
The binary value input by the ROTATE key.

&SLEN ( A) V1
A data area available to application programs for any
purpose.
(Search pattern length. Used by the SEARCH key function in
the intrinsic file editor.)

&SH ( )
(The binary value input by the SHIFT key. Application
programs never get to see this keystroke; it is filtered
out by the I/O routines in the nucleus.)

&SPAT ( A) V12
A data area available to application programs for any
purpose.
(Search pattern. Used by the SEARCH key function in the
intrinsic file editor.)

&STP ( )
The binary value input by the STOP/SPEED key.

&U ( )
The binary value input by the "cursor up" key.

vow 'ABORT IMO ORM


A ) V2

(c) 1981 Friends Amis, Inc. 10-5 29 October 81


GLOSSARY

Tag of a word that is to be called when a serious logical


error occurs in the HHC software. Examples of conditions
that cause an abort are stack underflow or overflow and
return stack underflow or overflow.
'ABORT normally contains the tag of the word ABORT. You
can change it to get control when a serious error occurs
and perform your own error processing. 'ABORT is reset to
ABORT by a hard clear.

'C ( ___ A ) I
Compiles code to stack the address of the entry point to a
colon definition, i.e., the address of the first tag
following the BREAK instruction that begins the colon
definition. For example, to stack the address of the entry
point to the colon definition MENU-DRIVER:
'C MENU-DRIVER
'C may be used to stack the address of a word that is to
be executed by (CALL) later in the program.

'EMIT ( ___ A ) V2
An area containing the tag of a word which EMIT will call
to do all of its processing. This area normally contains
the tag of (EMIT), and is reset to that tag by a soft
clear.
You can "redefine" EMIT for your application by repointing
'EMIT to another word of your choice.
The following code illustrates the use of 'EMIT. After it
is executed, EMIT will execute FOOBAR instead (EMIT). It
will continue to do so until 'EMIT is changed again, or
until the next soft clear.

: FOOBAR . . .

: INITIALIZATION-WORD
4 • •

'X FOOBAR 'EMIT !


• • *

'FILE-COND ( --- A ) V2
An area used to store the tag of a file-selecting word
that the menu driver is to use to determine which files
are to be listed in a menu.
The linkage to the file-selecting word must be:

(c) 1981 Friends Amis, Inc. 10-6 29 October 81


GLOSSARY

( A B )

where A is the address of a file and B is TRUE if the file


is to be listed in the menu, or FALSE if it is not.
The default file-selecting word returns TRUE for non-
invisible files and FALSE for invisible files. This
results in the HHC's usual behavior, which is to list all
files except invisible files. You can change this behavior
by storing the tag of a word of your choice in 'FILE-COND.

'FILEORG ( N )
Stacks the tag of the word (FILEORG).

'KEY ___ A ) V2
An area containing the tag of a word which KEY will call
to do all of its processing. This area normally contains
the tag of (KEY), and is reset to that tag by a soft
clear.
You can redefine KEY's function by writing your own char-
acter processing routine and storing its definition tag at
'KEY.
See 'EMIT for linkage details.

( A ) I
Compiles code to stack the address of the BREAK instruc-
tion that begins the following colon definition. For
example, to stack the address of the colon definition
MENU-DRIVER:
'V MENU-DRIVER
See also 'C.

'X ( --- TAG )


Returns tag of the following word. Example of use:
'X YOUR-TOP-WORD FLEE
This returns the tag of the word YOUR -TOP -WORD, and then
FLEEs to it. FLEEing transfers control to YOUR-TOP-WORD,
and also stores its address (or tag) at SOFTADR, causing
YOUR -TOP -WORD to be re-executed if the CLEAR key is
pressed.
'X may be used either inside or outside a target colon
definition.

(c) 1981 Friends Amis, Inc. 10-7 29 October 81


GLOSSARY

( )
Begins a comment. The comment will be ended by the first
encountered (whether or not surrounded by blanks).
Note, is not a vocabulary word; it is just a character
that 'C scans for.
See also '\'.

(D.) ( DN --- A L )
Formats a double integer in ASCII, using the current base
(see BASE). A L point to the ASCII formatted number.

(EMIT) (C )
Performs the entire character output function of EMIT. The
address of (EMIT) is normally stored at 'EMIT.
You can redefine EMIT's function by writing your own
character processing routine and storing its tag at 'EMIT.

(F*) ( FP1 FP2 FP3 ) C,NOTE


(F+) ( FP1 FP2 FP3 ) C,NOTE
(F/) ( FP1 FP2 FP3 ) C,NOTE
Internal words which perform floating point
multiplication, addition and division, without special-
case checking. If given special case operands, they
produce unpredictable results; (F/) may loop if its
divisor is zero.
Because these words do no special-case checking, they are
about four times faster than their standard counterparts,
F*, F+ and F/. Use them in contexts where the operands may
safely be assumed valid.
NOTE: that no (F-) instruction exists. To subtract, use
'80 XOR (F+)' (in hexadecimal base).
NOTE: these words are not in the HHC's tag table. You must
define calls them in your source code if you wish to use
them. Appropriate calls are described in the chapter on
"Floating Point Operations."

(FILEORG) ( --- A )
Stacks address of the current virtual file space. See
FILESPACE.

(FREEZE) ( A) V1
Number of the first character position of LCD that
participates in rotation. The normal value is 0, causing
the entire LCD to rotate. You can "freeze" the left part
of the LCD by setting (FREEZE) to a non-zero value.

(c) 1981 Friends Amis, Inc. 10-8 29 October 81


GLOSSARY

(FREEZE) is reset to 0 by a hard clear.

(KEY) .1=111MMOINIP C )

Performs the entire character output function of KEY. The


address of (KEY) is normally stored at 'KEY.
You can redefine KEY's function by writing your own
character processing routine and storing its tag at 'KEY.

(P ( ) COMP,NOTE
Begins a documentary comment. The comment is ended by the
first encountered, just as a 'C comment is.
(P is used after the definition of a word, to provide a
text description of the word. For example:

: 2SWAPDROP (S DX DY DY )
2SWAP 2DROP ;
(P DROPS SECOND DOUBLE WORD ON THE STACK.)

A utility program (yet to be implemented) will extract


documentary comments from the source screen and print
them, creating a glossary for a program.
gm. It is good practice to use documentary comments on every
colon definition in your program.

(ROTMODE) ( --- A ) V1
A variable that controls how the LCD will be rotated when
the cursor is past the last character column and another
character is written with EMIT. Meaningful values are:
0: fill mode
1: rotate mode (the normal setting)
2: rotate and fill mode
Note that (ROTMODE) is not reset by a hard clear.
For details of use, see the discussion of "Rotation Mode"
in the chapter on the LCD.

(S ( ) I,NOTE
Begins a documentary comment. The comment is ended by the
first encountered, just as a 'C comment is.
'(S' is used within a colon definition (customarily after
the defining word and name), to describe the things that
the word expects and leaves on the parameter stack. See
the description of (P for an example.

(c) 1981 Friends Amis, Inc. 10-9 29 October 81


GLOSSARY

( N1 N2 --- N3 )
N3 = N1 * N2.

*/MOD ( N1 N2 N3 --- N4 N5 )
N4 = remainder of (N1*N2)/N3.
N5 = quotient of (Nl*N2)/N3.
Intermediate result is a double number.

+ ( N1 N2 --- N3 ) C
N3 = N1 + N2.

+! ( N A --- ) C
Adds N to the word found at A and stores the sum back at
A. Pronounced "plus-store." Equivalent to
SWAP OVER @ + SWAP !

+C! ( N A --- ) C
Adds N to the byte found at A and stores the sum back at
A. Pronounced "plus-C-store." Equivalent to
SWAP OVER C@ + SWAP C!

+LOOP ( N --- ) CTRL


Used to terminate a DO loop when the index is to
incremented by a value other than 1.
N is added to the index. If the new index value < limit,
control returns to the first word after the corresponding
DO. If the new index value >= limit, the loop parameters
are discarded and control passes to the next word after
+LOOP.

+USED ( N --- )
(Internal word used by the file system.)

I ( N --- ) COMP
A synonym for ',-V'.

I-V ( X --- ) COMP


Stores X at the location in the cross-compiler's target
address space that is indicated by the virtual dictionary
pointer; increments the virtual dictionary pointer by 2.

(c) 1981 Friends Amis, Inc. 10-10 29 October 81


GLOSSARY

- ( N1 N2 --- N3 ) C
N3 = N1 - N2.

-1 0 1 2 3 4 5 6 7 8 9 ( --- N) C,NOTE
These small numbers are used so often that they are
defined by name in the dictionary as constants.

. ( N --- )
Display a number (16-bit two's complement notation) in
ASCII, according to the current BASE. A trailing space
follows the number. Pronounced "dot."

.n ( --- ) NOTE
Prints a string constant. The constant is the text
following ." and one blank, up to the next "".
If used in a colon definition, ." compiles to the (.")
word, a two-byte pointer to the end of the string
constant, and the string constant.
Here is an example of how .II is used in a program:
." two words"
The string constant is accompanied by a call to a routine
which will print the string at run time.
If used in immediate mode, prints the string immediately.
The maximum number of characters that may appear in the
string is 255.
NOTE: I ." compiles to '(.") 1 followed by the constant to be
printed.
." compiles to '(.")'.

.R ( N1 N2 --- )
Display N1 (16-bit two's complement notation) in ASCII,
according to the current BASE. The number is right-aligned
in a field N2 positions wide.
If the "natural" width of the number exceeds N2, no
truncation occurs, and no leading spaces are printed.

/ ( N1 N2 --- N3 )
N3 = N1 / N2. Remainder is dropped.
If N2=0 and Ni<0 then N3=1. If N2=0 and Nl>=0 then N3=-1.

(c) 1981 Friends Amis, Inc. 10-11 29 October 81


GLOSSARY

/MOD ( N1 N2 --- N3 N4 )
N3 = remainder of N1/N2.
N4 = quotient of N1/N2.

If N1<0 or N2<0, /MOD may produce results that are not


meaningful.

0< (N F) C
Test if N < 0.

0= (N B)
Test if N = 0.

1+ (N N' )
N' = N + 1.

1 (N - - N' )
N' = N - 1.

10EXP (N EXP )
Extracts the unbiased exponent from a floating point
number that is on the stack.
N is the position of the floating point number, relative
to the tip of the stack. If the number is immediately
below N, then N should be 1 (since N itself occupies
position 0!). If the number is below N and one other
floating point number, then N should be 5, and so forth.
EXP is the unbiased exponent from the number.

E.g., '3.14 1 10EXP' leaves a zero on the tip of the


stack, since 3.14 = 3.14*10^0. '314. 1 10EXP' leaves a 2
on the tip of the stack, since 314 = 3.14*10'2.

2! ( X Y A --- )
Stores X at A+2 and Y at A. (The reverse order of storage
reflects the 6502's convention of orienting the low-order part
of a number toward the low end of memory.)

2* ( N N' )
N' = N + N.

2+ ( N N' )
N' = N + 2.

(c) 1981 Friends Amis, Inc. 10-12 29 October 81


GLOSSARY

2- ( N N' )
N' = N - 2.

2/ ( N N' )
N' = N / 2. Note that the result is truncated downward,
not toward zero; thus, for example, "-3 2/" leaves -2, and
"-1 2/" leaves -1.

20H ( N ) NOTE
Stacks the value 20H.
NOTE: 20H produces the same result as &BL: it stacks the
numeric value 20H (which is also the ASCII character
"blank"). 20H generates a short tag (one byte of code);
&BL generates a CLIT followed by 20H (two bytes of code).

2@ ( A --- X Y )
Fetches X was at A+2 and Y was at A.

2DROP ( XD ) C
Drops top double entry on stack.

2DUP ( XD XD XD )
Copies top double entry on stack.

20VER ( XD YD XD YD XD )
Copies 2nd double entry on stack.

2PICK ( XDy XD3 XD2 XD1 y XDy XD3 XD2 XD1 XDy )
Copies y'th double entry on stack to the top.

2ROLL ( XDy XD3 XD2 XD1 y XD3 XD2 XD1 XDy )


Moves y'th double entry on stack to the top.
3 2ROLL is equivalent to 2ROT .

2ROT ( XD YD ZD YD ZD XD )
Moves 3rd double entry on stack to top.

2SHFTBLIP ( --- MASK )


A mask for the "second shift" blip. See ANDBLIP for
details.

(c) 1981 Friends Antis, Inc. 10-13 29 October 81


GLOSSARY

2 SWAP ( XD YD --- YD XD )
Exchanges top 2 double entries on stack.

30H ( ___ N )
Stacks the value 30H.

80H ( ____ N )
Stacks the value 80H.

( ___ ) DEF
Used to begin a colon definition. Used in the form
: cccc dddddddd... ;
creates a dictionary entry defining word "cccc" with
definition "ddddddd..."
(Compiling is done by the text interpreter as long as
STATE is non-zero. The CONTEXT vocabulary is set to the
CURRENT vocabulary. Words with the precedence bit set are
executed rather than compiled.)

:C ( --- ) DEF
Used like 1 :1 , but defines a word without creating an
entry for it in any tag table. When the compiler
encounters such a word, it compiles the tag of '(CALL)',
followed by the address of the word. This makes your
program one byte shorter if you refer to the word only
once in your program.
If you refer to a word before you define it, the compiler
assumes that the word will be defined later as a :C word.
If the word is later defined as a :C word, the compiler
gives you an advisory message and patches the definition's
address into the reference(s) it has already compiled.
If the word is never defined, OR if it is later defined as
an ordinary colon word, the compiler cannot resolve the
forward reference. It gives an error message at the end of
the compilation which identifies the word as unresolved.
If you want to make a forward reference to a colon
definition word, "predefine" the word by declaring it with
LONG or SHORT before the first reference to it.

:0 ( --- ) DEF
(Like 1 :1 , but does not add the defined word to the cross-
compiler's symbol table. The word is thus an "internal
word," not available for use by application programs. :0

(c) 1981 Friends Amis, Inc. 10-14 29 October 81


GLOSSARY

is used only in HHC intrinsic code.)

:P ( ) DEF
Defines a passage of high level code that is callable by a
JSR from a low level routine. It is used like this:
:P high-level-name
snap words go here . • •
;P

LABEL any-label

• \ X= A(tip of parameter stack).


high-level-name JSR,

:P creates a label named by the following word. At run


time, the program loads the X register with the address of
the tip of the parameter stack, and JSR's to the label
defined by :P.
:P assembles a 'BRK,' instruction. At run time, the 'BRK,'
causes a transfer of control to an interpreter routine
that pushes the return address onto the return stack and
goes to NEXT. NEXT begins interpreting the following SNAP
code.
;P assembles code that pops the return address off the
return stack and transfers control to it.

( ) CTRL
Used to terminate a colon definition. See I:I.

;P ( ) CTRL
Terminates a passage of high level code that is callable
from low level code. See ':P' for details and example of
use.

( N1 N2 --- B )
Test if 'NI <N2'.

<# - )
Used to convert a number from binary to ASCII. Associated
words are # , #S , SIGN , and #> .
The conversion process uses the text output buffer.
<# performs setup for conversion.

(c) 1981 Friends Amis, Inc. 10-15 29 October 81


GLOSSARY

# generates the next ASCII character and stores it in the


t.o.b. Conversion is performed according to the current
value of BASE. (NOTE: BASE is a character variable on the
HHC! Treating as a character variable will produce correct
results on both the HHC and the simulator. Treating as a
word variable will produce correct results on the
simulator, and unpredictable results on the HHC.)
Conversion is performed right to left (i.e., least to most
significant digit). The word takes a double integer from
the stack, divides it by BASE, deposits the ASCII
representation of the remainder in the buffer, and leaves
the quotient on the stack.
#S repeats # until the remainder is zero (but always
executes it at least once).
SIGN deposits a minus sign in the t.o.b. if the sign
indicator (an integer on the stack below the double
integer being converted) is negative, and drops the sign
indicator from the stack.
HOLD takes a character from the stack and deposits it in
the t.o.b., adjusting pointers so that the next word will
not overlay it. For example, if BASE is set to 16, "2E
HOLD" may be used to insert a decimal point in the number.
#> drops the quotient; leave the address and length of the
ASCII number on the stack.
The use of these words is best explained by documenting
sequences of words as though they were single words.
<# #S #> ( DU --- A L )
Converts a non-negative double integer to ASCII
representation in current BASE.
<# # #S #> ( DU --- A L )
Converts a non-negative double integer to ASCII
representation in current BASE. The number is padded
with leading zeros, if necessary, to a length of 2.
(Using the # word N times will cause the number to
be padded to a length of N+1.)
DUP ROT ROT DABS <# #S SIGN #> ( DN --- A L )
Converts a signed double integer to ASCII
representation. If the number is negative it is
given a leading minus sign.
DUP S->D DABS <# #S SIGN #> ( N --- A L )
Converts a signed integer to ASCII representation.
DUP ROT ROT DABS ( DN --- A L )
<# # # 2E HOLD #S SIGN 24 HOLD #>

(c) 1981 Friends Amis, Inc. 10-16 29 October 81


GLOSSARY

Converts a signed double integer to ASCII. A minimum


of 3 digits are produced. "2E HOLD" inserts a
decimal point (period) before the next-to-last
digit. SIGN inserts a minus sign before the first
digit if the number is negative. "24 HOLD" inserts a
dollar sign before the first digit and sign (if
any).
Typical formatting action for this sequence would
be: 2595 to '$25.95'; 95 to '$0.95'; 1 to '$0.01';
-5 to '$-0.05'; -13950 to '$-139.50'.
NOTE: BASE should be 16 at compile time so that "2E"
and "24" will be interpreted correctly. BASE should
be 10 at run time so that the numbers will be
printed in decimal.

<> ( N1 N2 B)
Test if 'N1 <> N2' (N1 not equal to N2).

<IF ( X Y--- ) CTRL


Executes the following code, up to ELSE or ENDIF, if X<Y.
Equivalent to '< IF'.

( N1 N2 --- B )
vsw Test if 'N1 = N2'.

= = ( X --- ) DEF
Defines a symbolic constant. Used like this:
5 == TBCDONE
TBCDONE is defined as a compile time symbol with the value
5. Wherever TBCDONE appears in the source program, the
value 5 is compiled into the object code.
== is used to name values in order to make code more
understandable. It is the SNAP equivalent of an assembler
equate. It is the most efficient way of defining a
constant (equal in run-time efficiency to a literal
constant), but is less compact than a "constant" defined
with a colon definition.

=IF ( X Y ) CTRL
Executes the following code, up to ELSE or ENDIF, if X=Y.
Equivalent to '= IF'.

( N1 N2 --- B )
Test if 'N1 > N2'.

(c) 1981 Friends Amis, Inc. 10-17 29 October 81


GLOSSARY

>R ( X --- )
Pushes X onto the top of the return stack.

?DO ( LIMIT INITIAL --- ) NOTE ,CTRL


Used to begin a DO loop. Identical to DO, except that it
does not execute the code inside the loop at all if,
initially, INITIAL >= LIMIT.
NOTE: a bug in the nucleus causes ?DO to function
incorrectly if the difference between INITIAL and LIMIT is
greater than 8000H.

?DUP ( X --- X [X] ) C


If X is nonzero, DUPs it, else does nothing.

?ENOUGH-ROOM ( B )
Use ?ENOUGH-ROOM after ?ROOM to give a stubborn error
message if there is not enough room in the intrinsic file
space to allocate a TSA.
If enough room exists, B is TRUE and ?ENOUGH-ROOM does
nothing.
If not enough room exists, B is FALSE and ?ENOUGH-ROOM
presents the user with a menu of non-invisible tiles. The
user may choose to delete any one of these files. If he
selects a file to delete, the HHC will clear itself after
deleting the file.
If the user does not select a file to delete, the only way
for him to escape from the ?ENOUGH-ROOM menu is to clear
the HHC himself.

?FILE ( A L [A'] B )
Given the name of a virtual file, returns its address.
A L are the address and length of the file's name. If the
file exists in the current file space, A' is the address
of its header, and B is TRUE. If the file does not exist
in the current file space, A' is absent and B is FALSE.

?KEY ( B )
Return TRUE if a keystroke is available for KEY, else
return FALSE.

?KEY-HIT ( B )
If a keystroke is waiting to be read, reads the keystroke,

(c) 1981 Friends Amis, Inc. 10-18 29 October 81


GLOSSARY

throws it away, and returns TRUE. If no keystroke is


waiting to be read, returns FALSE.

?RANGE ( N MIN MAX --- N B )


Returns TRUE if MIN<=VAL<=MAX, FALSE if not.

?ROOM (N B)
Determines whether there is enough room in intrinsic RAM
to allocate N bytes of storage. If there is enough room, B
is TRUE; else B is FALSE.

?SF ( A --- B )
Given the address of a file (i.e., of the file-length
word), determines whether the file is an executable SNAP
file.

( A --- X )
Stacks the word stored at A.

@SA N A --- A' )


"Fetch string array." A is the address of an array of
count-format string, such as the one that would be
compiled by this code:

HERE
S" STRING ARRAY ELEMENT #0"
S" STRING ARRAY ELEMENT #1"
S" STRING ARRAY ELEMENT #2"
5" STRING ARRAY ELEMENT #3"
== EXAMPLE.STRING.ARRAY

N is an index to the array.

A' is the address of string #N in the string array at A.

Example:

2 EXAMPLE.STRING.ARRAY @SA COUNT TYPE


would type, 'STRING ARRAY ELEMENT #2' on the LCD.

@SA is used in the standard linkage to MENU-DRIVER. See


the description of MENU-DRIVER for an example.

(c) 1981 Friends Amis, Inc. 10-19 29 October 81


GLOSSARY

A
A>B ( C --- N )
Performs ASCII character to binary conversion according to
the following rules:
'0' through '9' are converted to 0 through 9.
'A' through 'Z' and 'a' through 'z' are converted to 10
through 36.
All other input values are converted to binary zero.
A>B is convenient for interpreting a cnaracter indicating
the user's selection from a menu.

ABORT ( ___ ) C
The word normally executed when a serious error occurs.
See 'ABORT for more information.
(JSR's to the label BREAK. BREAK displays the message
"RESET" and then performs a nard clear.)

ABS ( N --- N' )


N' = ABS(N).

ACVECT ( ____ A ) V2
Stacks the address of the address of the current LCD
accent table. You may give the HHC a new LCD accent table
by changing the contents of ACVECT.

AGAIN ( --- ) CTRL


Used in a colon definition in the form
BEGIN ... AGAIN
At run time, AGAIN forces execution to return to the
corresponding BEGIN. Execution cannot leave this loop
(unless 'R> DROP' is executed one level below).
(At compile time, AGAIN expects two items on the stack:
"A N --- ". It generates a (BRANCH) with an offset from
HERE to A. N is used for compile-time error checking.)

ALL-EMIT ( C --- ) C
(Sends a character to the LCD and to all attached periph-
eral devices. FLAME-ON stores the tag of this word in
'EMIT. See 'EMIT.)

(c) 1981 Friends Amis, Inc. 10-20 29 October 81


GLOSSARY

ALRMBLIP ( --- N )
A mask for the "alarm" blip. See ANDBLIP for aetalls.

AND ( X Y --- Z ) C
Bitwise logical AND.

ANDBLIP ( N --- ) C
ANDs the low-order byte of N into the LCD blip byte. If a
bit is i in N, the corresponding blip is unchanged; if a
bit is 0 in N, the corresponding blip is turned otf.

Following are the symbolic constants that may be used to


designate the bits in the blip byte:

BATBLIP '*' blip; may be defined by user


SHFTBLIP keyboard in snorted state
2SHFTBLIP keyboard in second-shifted state
LOCKBLIP keyboard in locked state
RECBLIP "delete" blip (not used by system)
MEMBLIP "insert" blip (not used by system)
ALRMBLIP "alarm" blip (used only by POCSEC)
RUNBLIP CPU running

To turn on a blip, turn on the corresponding bit with


ORBLIP. Similarly, to turn off a blip, turn off the
corresponding bit with the complement of the corresponding
bit mask and ANDBLIP.

The HHC nucleus manipulates BATBLIP, SHFTBLIP, 2SHFTBLIP,


LOCKBLIP, RUNBLIP and ALRMBLIP asynchronously with
applications, so it is NOT a good idea for applications to
try to use those blips. RECBLIP and MEMBLIP are safer;
only the file editor uses them among the HHC's intrinsic
software, and so an application that uses them is less
unlikely to get into trouble.

AOECB ( m A) V6
A 6-byte area containing a timer ECB used by the auto-off
function.

AOENB ( --- FL )
A flag in FLAG3 that controls the auto-off feature. 1 ->
the feature is enabled; 0 -> the feature is disabled.

AOTOKE ( --- FL ) =
A flag in FLAG3 that is used by the auto-off feature. 1 ->
an event has occurred that warrants resetting the auto off
timer; 0 -> no such event has occurred. The bit is
checked, and the timer may be reset, every 30 seconds. The
timer is set to a 10 minute interval; if it reaches the

(c) 1981 Friends Amis, Inc. 10-21 29 October 81


GLOSSARY

end of the interval, the HHC is turned off.


Note that AOTOKE is meaningful only when AOENB is 1.

AP ( A) V2
A variable which points to the ceiling of the current TSA.

AREA ( ) DEF
Used to define and temporary storage area (TSA) at compile
time, and allocate it at run time.
The user may create his own variables within the TSA with
words such as VAR, DVAR, CVAR, and VECTOR.
The area is terminated by the word ENDAREA.
See the section on TSA's in "General Technical
Information" for details.

ASC>FP ( A L FP ENDLOC NDIGITS )


Converts a floating point number from ASCII format to
internal format.
A and L are the address and length of the ASCII format
number. L must be in the range 0<=L<=255.
FP is the floating point value. ENDLOC is the address of
the first location beyond the [valid part of the] number.
NDIGITS is the number of digits and leading zeros in the
number.
If ENDLOC<A+L, ASC>FP encountered an error during the
conversion; ENDLOC points to the first character
considered erroneous, and FP and NDIGITS reflect the value
of the number up to that point.

ASSEMBLER ( ) COMP
Name of a vocabulary containing an assembler that
assembles into the host machine's address space. See the
chapter on "The SNAP Assembler" for details.

ASSEMBLER-V ( ) COMP
Name of a vocabulary containing an assembler that
assembles into the target machine's address space.

ATTACH ( DEVCODE LUN B)


Attaches a device of the type specified by device code
DEVCODE to logical unit number DEV#. B indicates success
or failure of the operation.

(c) 1981 Friends Amis, Inc. 10-22 29 October 81


GLOSSARY

ATTACHX ( DEVCODE LUN B)


Identical to ATTACH except for behavior if a device of the
requested type is already attached to a LUN. ATTACH
unattaches the device and reattaches it to the specified
LUN. ATTACHX ignores the device and searches for another
of the same type, returning B=FALSE if it cannot find one.

AVAIL ( N)
Returns the number of free bytes in the current file
space. If the intrinsic file space is current, N is
reduced by a safety factor to allow room for numeric
conversions between the temporary stack and the tiles.
For the total number of bytes in the current file space,
see FILELEN.

(c) 1981 Friends Amis, Inc. 10-23 29 October 81


GLOSSARY

B>A ( C --- N )
Performs binary to ASCII character conversion according to
the following rules:
0 through 9 are converted to '0' through '9'.
10 through 36 are converted to 'A' through 'Z'. 37 is
converted to 1 [ 1 (the next ASCII character after 'Z'), 38
is converted to '\', and so on.
B>A is the inverse of A>B.

BASE ( ____ A ) V1
The current number base used for input and output
conversion. Initial value is 10.

BATBLIP ( --- MASK ) =


A mask for the "battery low" blip. See ANDBLIP tor
details.

BEEP ( --- )
Produces a "beep" on the HHC's noise maker. Equivalent to
sending 07H (ASCII "bell" code) to the LCD.
If LCD output is redirected to another device (by changing
the value of 'EMIT, for example), BEEP is redirected too.

BEEPER ( ___. N ) .
A mask which may be ANDed into the system control byte to
isolate the squeaker bit. It the bit is 1, a DC-high
voltage is placed on the squeaker. If the bit is 0, a DC-
low voltage is placed on the squeaker. A program can make
sounds by switching the bit on and off.

BEGIN ( --- ) CTRL


Begins an iterative loop in a colon definition. Used in
one of the forms:
BEGIN —. UNTIL
BEGIN —. AGAIN
BEGIN ... WHILE ... REPEAT
BEGIN —. UNTIL loops until UNTIL finds a 1 on the stack.
Then it passes control to the next word after UNTIL.
BEGIN ... AGAIN loops forever, unles terminated by EXIT,
by ?EXIT, or by R> DROP one level below. (Such use of R>

(c) 1981 Friends Amis, Inc. 10-24 29 October 81


GLOSSARY

is NOT good practice.)


BEGIN —. WHILE —. REPEAT loops until WHILE finds a 0 on
the stack. Then it passes control to the next word after
REPEAT.
(At compile time, BEGIN leaves its return address and an
error checking code on the stack for UNTIL, AGAIN, or
REPEAT to use.)

BIGMOVE ( BANK FROMADR TOADR LEN --- )


Moves a block of data to or from a bank-switched area of
memory (which need not be in the address space when
BIGMOVE is called).
BANK is the bank ID of the bank-switched area, which may
be either the source or the target of the move. FROMADR is
the address of the source; TOADR is the address of the
target; LEN is the length to move.
The HHC determines whether BANK applies to FROMADR or
TOADR by examining the two addresses. Only one of them may
be in a bank-switched part of the address space.

BLANKS (AN )
Deposits N blanks in RAM, beginning at address A.
maw Equivalent to '32 FILL'.

BOUNDS ( N1 N2 --- N2' N1 )


Used to set up the initial and limit for a DO loop.
Converts an address and length to ceiling (i.e., final
value + 1) andaddress (i.e., initial value).

BUFPOSN ( A ) V1
Gives the cursor's current character position in the
display, i.e., the position where the next character
EMITed will appear. The left-most position is #0.
Application programs may move the cursor by changing this
variable via the word POSN.

(c) 1981 Friends Amis, Inc. 10-25 29 October 81


GLOSSARY

C! ( C A --- ) C
Stores C at address A. Pronounced "C-store."

C!-V ( C A --- ) COMP


Stores C at A in the cross-compiler's target address
space.
C I ( C --- ) COMP
A synonym for C,-V.

C,-V ( C --- ) COMP


Stores C at the location in the cross-compiler's target
address space that is indicated by the virtual dictionary
pointer; increments the virtual dictionary pointer by 1.

C@ ( A --- C ) C
Fetches the character stored at address A.

CALC ( --- )
Executes the intrinsic calculator.

CALL ( A --- )
Executes the definition at address 'A'. 'A' points to the
first tag in the definition to be executed.

CALT ( --- N )
A mask for the "alternate character set" bit in the high-
order byte of an EMIT parameter. If the bit is on, EMIT
displays a character from the alternate character set. If
the bit is off, EMIT displays a character from the
standard character set.

CAN.LIST ( A C B --- )
Cancels one or more ECB's.
A is the address of a list of ECB addresses; each address
points to an ECB to be cancelled or preserved (see B,
below).
C is the length of the ECB list, in words.
B=FALSE means "cancel every ECB in the list." B=TRUE means
"preserve every ECB in the list, but cancel every other
ECB."

(c) 1981 Friends Amis, Inc. 10-26 29 October 81


GLOSSARY

CANCEL ( ECBADR )
Post ECB as completed, regardless of whether the
associated event has occurred.

CAPON ( N)
A mask which may be ANDed into the system control byte to
isolate the capsule-power bit. If the bit is 1, the
hardware is giving the capsules power. If the bit is 0,
the hardware is not giving the capsules power.

CASE (XY LX] ) CTRL


Denotes the beginning of a CASE clause.
If X=Y, X and Y are dropped and control passes to the next
word after CASE. IF X<>Y, Y is dropped and execution skips
to the matching ELSE or ENDIF. For example:
: .DIGIT (N )
0 CASE ." ZERO " ELSE
1 CASE ." ONE ELSE
2 CASE ." TWO ELSE
." NOT A VALID CHOICE DROP
ENDIF ENDIF ENDIF
Note that the CASE construction requires one ENDIF per
CASE.

For a more convenient CASE-like structure, see IF.ITS.

CASE-ESC ( )
(A jump table used by LCD support routines to process
escape codes.)

CBIT --- FL )
(A flag bit in FLAG2 used to indicate whether the cursor
is on. As the cursor flashes, this bit is toggled on and
off. Tested by >ENCODE.)

CEMIT (C )
(Emits a character to the video and LCD. Usable only in
the calculator, which binds the video.)

CFILE ( A)
Returns the address of the current virtual file. After a
clear and before any file has been opened, the address is
zero. CFILE is used to identify the file in various I/O
operations, most importantly in DELETE-FILE.

(c) 1981 Friends Amis, Inc. 10-27 29 October 81


GLOSSARY

CFLSH ( --- MASK ) =


A mask for the "flash" bit in the high-order byte of an
EMIT parameter. If the bit is on, EMIT displays a
character flashing on and off. If the bit is off, displays
a character without flashing.

CGRTN ( --- ) C
(Internal word used by EMIT to trap and process the
carriage return character.)

CH ( ___ A ) V2
(Internal word used by the keyboard decoding routine.)

CHESAV ( ___ A ) V2
(Address of the current I/O ECB. Used internally by I/O
routines.)

CHSAV ( --- A ) V1
(Character being output to a BINDed peripheral. Used
internally by I/O routines.)

CHVECT1 ( _ 4_ A ) V2
Stacks the address of the address of the current LCD
primary character set table. You can change the HHC's
primary character set by changing the contents of CHVECT1.

CHVECT2 (--- A) V2
Stacks the address of the address of the current LCD
alternate character set table. You can change the HHC's
alternate character set by changing the contents of
CHVECT2.

CLEAR ( --- ) C
Simulates the effect of the user pressing the CLEAR key
once. This effect is a hard clear if this is the second
CLEAR (from software or keyboard) since any other keyboard
key was pressed; otherwise it is a soft clear.
See also SOFT.CLR and HARD.CLR.

CLR.BITS ( A X --- )
Changes the value of the word at A by turning off each bit
that corresponds to a bit that is on in X. See also TOGGLE
and SET.BITS.

(c) 1981 Friends Amis, Inc. 10-28 29 October 81


GLOSSARY

CMOVE ( FROM TO LEN --- ) C


Moves LEN bytes from address FROM to address TO. The bytes
are moved one at a time, lowest first. Thus, CMOVE will
cause the field to overlay itself if TO is greater than
FROM but less than FROM+LEN .
MOVE is a similar instruction that does not overlay data.

CNEG ( --- N )
A mask for the "negative" bit in the high-order byte of an
EMIT parameter. If the bit is on, EMIT displays a
character in inverse video. If the bit is off, EMIT
displays a character in the usual way.

CODE ( --- ) DEF


Used to create a CODE word (consisting of machine language
code instead of SNAP code). See the chapter on the SNAP
assembler for more information.

CODEC ( --- ) DEF


Defines a CODE word that has no tag. Used the same way as
CODE. The defined word is called the same way as a word
defined by ':C'.

COLD.START ( X X X ... X --- ) C


(Called during a cold start of the HHC. Among other
functions, it empties the parameter stack.)

COMPILE-V ( --- ) COMP,NOTE


Used in immediate mode, causes the following word to be
compiled into the target address space. See T: for an
example of use.

CONSTANT ( X --- ) COMP


Defines a constant. Used like this:
80 CONSTANT RECLEN
RECLEN is defined as a constant with the value i0.

COUNT ( A --- A' LEN )


Converts the address of a string to the address of the
string's value and the length of the string's value.

CPUON ( ____ N ) =
A mask which may be ANDed into the system
control byte to isolate the CPU-on bit. It the bit is 1,

(c) 1981 Friends Amis, Inc. 10-29 29 October 81


GLOSSARY

the CPU is on. If the bit is 0, the CPU is off.

CQMK ( m N )
A mask for the "flash/question-mark" bit in the high-order
byte of an EMIT parameter. If the bit is on, EMIT
displays a character alternating with a 'V. If the bit is
off, EMIT displays a character in the usual way.

CR ( )
---

Causes a carriage return on the LCD (or other device


attached to LUN #0). If the device is the LCD, clears the
cursor from the freeze point (if any) to the right edge,
and returns the cursor to its original position (depending
on rotation mode).

If the the most recent keystroke was input after the most
recent LCD character was displayed, CR causes an immediate
carriage return.
If the most recent LCD character was displayed after the
most recent keystroke was input, CR works by turning on a
flag which is later tested by the LCD output routines. The
next time a character is sent to the LCD, the routines
test this flag to see if a carriage return is pending; if
so, they do the carriage return (and reset the flag)
before writing the character.
In addition, each time a character is written to the LCD,
a timer is set; and if user writes a CR and then another
character before the timer expires, the routines wait
until the timer expires before doing the carriage return.
This gives the user a guaranteed minimum length of time to
look at a line on the LCD after it is completely displayed
and before it is erased.

CRBIT ( --- FL ) .
(Bit in FLAG2. 1 -> an LCD carriage return is pending.)

CRESTORE ( --- )
Pops two words from the return stack to the parameter
stack, then stores the low character of the first word at
the address indicated by the second word. See SAVE.

CSBIT ( --- N )
A mask for the byte in a ROM capsule at the address given
by CSPEED. If the bit is on, this ROM capsule has slow
ROM. If the bit is off, this ROM capsule has fast ROM.

CSPEED ( ___ A ) K1

(c) 1981 Friends Amis, Inc. 10-30 29 October 81


GLOSSARY

A field in the header of a ROM capsule. This field


contains bit flags which describe the capsule. The
following symbols represent bit masks for the bits
currently used:
PROGBIT I: capsule contains a program. 0: capsule
contains data.
CSLOW 1: capsule uses slow ROM. 0: capsule uses fast
(normal) ROM.

CTABLE ( N--- ) DEF


Used to define a character table in ROM. The table must be
initialized by storing data into it, for example:
4 CTABLE TRIBBLE
3 C, 2 C, 1 C, 0 C,
N is used by the compiler to check the range of constant
subscripts in references to CTABLE.

CTEXT ( A) K1,NOTE
Tag table number of the primary external tag table of an
application in a control ROM.
Note that the value of the "constant" will vary depending
v~~ on what control ROM is currently in the address space.

CTRFLAG2 ( --- A ) K1
(Control ROM byte containing complex I/O flags.)

CTRFLAGS ( --- A ) Kl
(Control ROM byte containing the peripheral's hardware
device type code.)

CTRID ( A) Kl
The address in a control ROM where the name of the device
the ROM is for (e.g., 'MODEM') is stored in count format.

CTROM ( A)
Stacks the address of the part of the address space where
device control ROMs go.

CURBIT ( --- FL )
(A bit in FLAG2. 1 -> turn the cursor on.)

CURCTL ( A) V1

(c) 1981 Friends Amis, Inc. 10-31 29 October 81


GLOSSARY

Bank ID of the ROM bank currently switched into the


peripheral control ROM address space.

CURRAM ( A) V1
Bank ID of the RAM bank currently switched into the
extrinsic RAM space.

CURROM ( A) V1
Bank ID of the ROM bank currently switched into the ROM
capsule space.

CVAR ( ) DEF
Used in a TSA to reserve one byte of storage for a
variable. For example:
CVAR ERRFLG
This reserves a one byte for a variable named ERRFLG.

CVECTOR ( N ) DEF
Used in a TSA to reserve N bytes of storage for an array
of byte-length values. For example:
CVECTOR ERRCODES

This reserves 8 bytes for an array of 8 byte-length values


named ERRTBL.
At run time, the vector expects one item on the stack; it
interprets this item as an origin-0 index. For example,
7 ERRTBL
would stack the address of the 7th (and last) element of
the vector, ERRTBL.

(c) 1981 Friends Amis, Inc. 10-32 29 October 81


GLOSSARY

D+ ( ND1 ND2 ND3 )


ND3 = ND1 + ND2.

D- ( ND1 ND2 ND3 )


ND3 = ND1 ND2.

D.R ( DN N )
Display DN in ASCII, according to the current BASE. The
number is right-aligned in a field N positions wide.
If the "natural" width of the number exceeds N, no
truncation occurs, and no leading spaces are printed.

D= ( ND1 ND2 B)
Compares two double numbers. B is TRUE iff ND1 = ND2.

DABS ( ND --- ND' )


ND' = ABS(ND).

DBUF A) V27
Character buffer for the LCD. Contains ASCII cnaracters
representing the 27 character positions of the LCD. (Only
the first half of the 27th position is aisplayed.)
DBUF is used internally to manage LCD display. It is not
normally used by applications.

(Putting a character in DBUF does not update the LCD until


the next time the affected part of the LCD is reaisplayed.
See 'UPDISP'.
(See also DBUF1.)

DBUF1 ( A) V27
Control buffer for the LCD. Each byte contains bit flags
that control whether the character in the corresponding
byte of DBUF is displayed with blink, flashing, etc. The
control byte normally is deposited in DBUF1 by EMIT, which
gets it from the high-order byte of its parameter.
See also DBUF and UPDISP.

DBUFL ( N )
The length of the LCD in characters (27).

(c) 1981 Friends Amis, Inc. 10-33 30 October 81


GLOSSARY

DECB ( A) V6
(A timer ECB used by the LCD control routines. See #DECB.)

DECIMAL ( ) COMP ,NOTE


Sets BASE to 10. This causes output words such as '.' and
'R.', and conversion words such as '<# #S #>', to display
numbers in base 10.
NOTE: use DECIMAL only outside colon definitions, to set
the compile-time base. In SNAPPLE, DECIMAL is defined in
the target vocabulary, and functions as a normal target
definition; but in the cross-compiler, DECIMAL is an
immediate word.

DEL.CH.R (N )
Shifts the right part of the LCD display left one
character. the character in position N+1 is shifted to
position N; all following characters are shifted after it.
The contents of the last position is not disturbed; the
original contents of position N is lost. SEE ALSO
INS.CH.R.

DELETE (N B)
Deletes the N'th record in the current virtual file; B is
TRUE. If the N'th record does not exist, B is false.

DELETE-FILE ( A --- )
Deletes a file. A is the address of the first byte of the
file to be deleted.
Use ?FILE to find the address of the first byte of the
file, given its name.

DISP.CH (N N' )
(Used internally by (EMIT) to display a character. Given
buffer position of cursor before display, returns buffer
position of cursor after display.)

DISPON ( N)
A mask which may be ANDed into the system control byte to
isolate the LCD display bit. If the bit is 1, the LCD
display is on. If the bit is 0, the LCD display is off.

DLITERAL ( DX --- )
At compile time, takes a 32-bit value from the stack and
compiles it into the code. At execution time, this 32-bit
value is treated in whatever way its context dictates.

(c) 1981 Friends Amis, Inc. 10-34 30 October 81


GLOSSARY

See LITERAL for examples of use.


NW

DMODE ( ........ A ) VI
Stacks the address of a byte containing the current
default display mode, i.e., the mode in which EMIT will
display a character if the high byte of the parameter word
is zero. The value of DMODE is interpreted the same as the
value of the high byte of an EMIT parameter.

DMOVE ( FROM TO LEN --- ) C


"Display move." Used to read and write the LCD at the dot
level.
You write the LCD at the dot level by moving data from the
LCD buffer, a memory-mapped area, to RAM. You read the LCD
at the dot level by moving data from RAM or ROM to the LCD
buffer.
The LCD buffer is 159 bytes long. The buffer's address is
given by the symbolic constant DSPLY. Each byte represents
one LCD dot column; the byte at DSPLY represents the
leftmost dot column, and the byte at DSPLY+158 represents
the rightmost dot column.
Within each byte of the buffer, the high-order bit (80's
mi. bit) represents the bottom dot, and the low-order bit (l's
bit) represents the top dot.
FROM is the address data is to be moved from; TO is the
address data is to be moved to. Either FROM or TO should
be an address in the LCD buffer. LEN is the number of
bytes of data to be moved, that is, the number of dot
columns to be read or written.
CAUTION: before starting to use DMOVE, clear the LCD by
executing the following code:
LCD.CR \ CLEARS LCD AT 'DMOVE' LEVEL.
STOP.CURSOR \ MAKES CURSOR INVISIBLE.
26 BUFPOSN C! \ MOVES CURSOR TO CHAR POSN 26.
When you are ready to begin writing characters to the LCD
again (e.g., with EMIT), execute the following code:
LCD.CR \ CLEARS LCD AT 'DMOVE' LEVEL.
START .CURSOR \ MAKES CURSOR VISIBLE AGAIN.
CR \ MOVES CURSOR BACK TO LEFT EDGE.
NOTE: '26 BUFPOSN CP moves the cursor into character
position 26. This places it half in dot columns 156-158,
and half off the LCD. With the cursor in this position,
Alm. dot columns 156-158 are NOT available for your use. This

(c) 1981 Friends Amis, Inc. 10-35 30 October 81


GLOSSARY

is necessary because (1) an HHC bug makes it impossible to


write to dot columns under the cursor, and (2) it is
impossible to move the cursor entirely off the LCD.

DNEGATE ( ND --- ND' ) C


ND' = -1 * ND.

DO ( LIMIT INITIAL --- ) CTRL ,NOTE


Used to begin a DO loop.
Used in the construction:
DO ... LOOP or
DO ... INCR +LOOP

iterates the code between DO and LOOP or +LOOP until the


loop limit is reached.
The initial value of the loop index is INITIAL. Each time
LOOP is reached, the index is incremented by 1. Each time
+LOOP is reached, the index is incremented by INCR.
If LOOP is used, or if +LOOP is used with a positive INCR,
iteration continues until control returns to DO with index
>= LIMIT. If +LOOP is used with a negative INCR, iteration
continues until control returns to DO with index <= LIMIT.
Within a loop, the word 'I' will copy the index onto the
stack. Within two nested loops, the word 'J' will copy the
index of the outer loop onto the stack.
Within a loop, the word LEAVE will reset the LIMIT to the
current value of the index, forcing the loop to terminate
at the end of the current iteration.
See also '?DO'.
LIMIT, INITIAL, INCR, and I are all 16-bit integers.

(When compiling within a colon definition, DO compiles


(DO) and leaves the address of the following dictionary
location and a code for error checking: " --- A N".)
(At execution time, (DO) initializes the index, and pushes
the index and LIMIT onto the return stack.)
NOTE: a bug in the SNAP interpreter causes DO to work
incorrectly if LIMIT - INITIAL >= 8000H.

DP ( ___ A ) COMP
A synonym for DP-V.

(c) 1981 Friends Amis, Inc. 10-36 30 October 81


GLOSSARY

DROP ( X --- ) C
Drops the top entry from stack.

DSIZE ( ___ N ) =
Size of LCD in characters (the value is 26).

DSPFLAG ( --- FL )
(Bit in the HDT byte 0; 1 -> this HDT is for the LCD.)

DSPLY ( ____ A )
Address of the 159-byte memory mapped LCD I/O area. You
can read from and write to the LCD at the dot level by
moving data to and froom this area with DMOVE.

DUP ( X --- X X ) C
Duplicates X.

DVAR ( --- ) DEF


Used in a TSA to reserve 4 bytes of storage for a long
numeric variable. For example:
DVAR ERRCOUNT

This reserves a two words for a variable named ERRCOUNT.

DVCON ( --- FL ) =
(Bit in the HDT byte 1; 1 -> this device is on, or will be
turned on the next time DVCSET is called. See DVCSET.)

DVCSET ( --- ) C
(Scans the HDT's and turns all devices on or off,
depending on the value of the DVCON bit.)

DVSAV ( ____ A ) V1
(Page 0 location used by I/O routines to store the on/off
status of a device during an I/O operation.)

(c) 1981 Friends Amis, Inc. 10-37 30 October 81


GLOSSARY

E-L ( TAG N --- [A] B )


Locates the N'th file in the current file space that
satisfies the criteria of the file-selecting word
associated with TAG. (See the discussion of 'FILE-COND
regarding file-selecting words.)
If the file exists, A is its address and B is TRUE. If the
file does not exist, A is absent and B is FALSE.

EDIT-FILE ( MAXLEN EOFADR EOLADR LINE# --- )


Invokes the file editor on the current file.
MAXLEN is the maximum length a record may have.
EOFADR is the address of a word which takes an input
character from the stack and returns TRUE iff that
character indicates "end of file."
EOLADR is the address of a word that takes an input
character from the stack and returns TRUE iff that
character indicates "end of line." The word EOL is most
commonly used.
LINE# is the number of the first line (i.e., the first
record) in the file to be edited. Note that the user may
move the cursor forward or backward from this line if he
wishes.
Note that EOFADR is called only when EOLADR returns TRUE.
Thus every character that is to be recognized as an EOF
character must also be recognized as an EOL character.

ELSE ( --- ) CTRL


Used to separate the THEN clause and ELSE clause in an IF
construction.
Used in the form:
IF tttt... ELSE eeee... ENDIF
If the entry IF takes off the stack is TRUE, "tttt..." is
executed and "eeee..." is skipped. If it is FALSE,
"tttt..." is skipped and "eeee..." is executed.
(At compile time, the form is "Al N1 --- A2 N2". ELSE
compiles a BRANCH and reserves space for its offset, which
will point past "eeee..." Then it resolves the pending
forward branch from the IF by computing the offset from Al
to HERE (which is where "eeee..." will start), and inserts
that offset in the space IF reserved at Al.)

(c) 1981 Friends Amis, Inc. 10-38 30 October 81


GLOSSARY

EMIT (C )
Send character C to display.
The high-order byte of C is normally zero, but may be set
to other values to display the character in unusual ways.
For example, the CNEG bit may be set to display the
character in inverse video. See the text description of
EMIT for more information.

EMIT.ESC ( DATACHAR CTRLCHAR )


EMITs an escape control sequence with the escape control
character CTRLCHAR and the data character DATACHAR.
Equivalent to 'HEX 113 EMIT EMIT EMIT'.

ENCODE ( )
Used internally to manage LCD display. Not normally used
15y applications.
(Converts ASCII character to LCD dots.)
ENDAREA (--- ) COMP
Used to terminate a TSA. All of the VAR's etc., defined
between AREA and ENDAREA are allocated in the TSA.

ENDIF ( ) CTRL
Used to terminate an IF construction or a CASE
construction.
Used in the form:
IF tttt... ELSE eeee... ENDIF or
IF tttt... ENDIF or
a CASE aaaa... ELSE
b CASE bbbb... ELSE
c CASE cccc... ELSE
xxxx...
ENDIF ENDIF ENDIF
Note, in the last form there must be one ENDIF matching
each CASE.
(At compile time, the form is "A N ---". A is the address
of the space reserved for a branch past the ENDIF by ELSE
or IF. ENDIF inserts HERE at A. N is used for error
checking.)

vo. EOL ( C B )

(c) 1981 Friends Amis, Inc. 10-39 30 October 81


GLOSSARY

The HHC's standard end-of-line word for EXPECT and EDIT-


FILE. An end-of-line word defines what characters will be
considered to end a line of input when read by EXPECT. See
EXPECT for details of how to use the word.
EOL accepts 4 characters as end-of-line characters: ENTER,
r, il, and SEARCH.

ERASE ( A LEN --- )


Clear an area at A, of length LEN bytes. Each byte in the
area is set to binary 0.

ESCCC ( ___ N ) =
Escape control sequence opcode "Set Control Character
Mode." If the data byte is TRUE, subsequent control
characters sent to the device will be displayed, not
executed; if FALSE, subsequent control characters sent to
the device will be executed, not displayed.

ESCDC ( --- N ) =
Escape control sequence opcode "Display Character." The
next data character will be displayed, even if it is a
control character that would normally be executed. For
example, if the next character is OAF (carriage return)
and it would normally cause a physical end-of-line on the
device, it causes no carriage end-of-line, but is written
as an inverse J.

ESCDR ( --- N ) =
Escape control sequence opcode "Delete Right." The
character under the cursor is deleted; following
characters on the line are moved left. The data byte is
used as a fill character at the end of the line.

ESCFL ( m N ) =
Escape control sequence opcode "Flush I/O Buffer."
Characters in the device's I/O buffer are read or written,
emptying the buffer. (This operation is generally applied
only to output devices that write a line of data at a
time. Writing a line would normally be triggered by a CR
character.)

ESCHM ( _____ N ) =
Escape control sequence opcode "Home Cursor." This
normally returns the cursor to the upper left corner of a
device with a two-dimensional display.

ESCIR ( m N ) =

(c) 1981 Friends Amis, Inc. 10-40 30 October 81


GLOSSARY

Escape control sequence opcode "Insert Right." The data


byte is displayed at the cursor. The character under the
cursor, and all following characters on the line, are
pushed to the right.

ESCSF ( ....... N )
Escape control sequence opcode "Set Flash Mode."
Subsequent output will be displayed in flashing
characters. Reverses the effect of ESCUF.

ESCSI ( ___ N )
Escape control sequence opcode "Set Inverse Mode."
Subsequent output is displayed in inverse. Reverses the
effect of ESCUI.

ESCUF ( --- N )
Escape control sequence opcode "Set Unflash Mode." All
subsequent output is displayed in non-flashing characters,
until the mode is changed by ESCSF. Reverses the effect of
ESCSF.

ESCUI ( ____ N )
Escape control sequence opcode "Set Uninverse Mode."
Subsequent output will be displayed normally ( non-
inverse). Reverses the effect of ESCSI.

ESCUN ( ____ N )
Escape control sequence opcode "LCD unescape." On the LCD,
the data byte is written normally. On all other devices,
it is ignored.

ESCWB ( ___ N )
Escape control sequence opcode "Set Word Break." The data
byte defines the word break character that can trigger
automatic word wrap. (This means that when an output line
becomes longer than a device's line length, the device
automatically starts a new line and moves the last word of
the old line to the start of the new line so that the word
will not straddle a line break.)
The word break character is initially blank (20H) in all
cases.
Setting the word break character to OFFH turns automatic
word breaking off.

EVECT ( ___ A )
(Stacks address of a JMP instruction used by the inner

(c) 1981 Friends Amis, Inc. 10-41 30 October 81


GLOSSARY

loop to decod tag tables.)

EVFLAG ( _p.m._ A ) In
(Event processor service flag. 1 -> call event processor
the next time the inner loop is executed. 0 -> do not call
event processor.
(This byte may not have any value except 0 or 1. It is
changed with increment and decrement instructions, so that
an interrupt cannot occur while it is being updated.)

EVFLAG1 ( --- A ) V1
(Event processor service flag. 1 -> an event is being
processed. This flag prevents the HHC from re-entering the
event processor when an event occurs while another event
is being processed.)

EXECUTE ( TAG --- ) C


Executes the word denoted by the TAG.
Here is a simple (and pointless) example of how EXECUTE
can be used:

: YOUR-TOP-WORD ...
'X YOUR-TOP-WORD EXECUTE

This code fragment executes a word named YOUR-TOP-WORD.


'X YOUR-TOP-WORD stacks the tag of YOUR-TOP-WORD.
See also FLEE.

EXIT ( --- ) C
Used inside a colon definition, terminates execution of
that colon definition, returning control immediately to
its caller. The contents of the parameter stack is not
disturbed.
NOTE: do NOT use ;S in this context, as you would in
FigFORTH.
NOTE: do NOT use EXIT inside a DO loop. It will produce
random results, since DO uses the return stack to store
the loop index and limit.

EXPECT (ALICEM---AL' E'KM' )


Reads a line of text from the keyboard. EXPECT permits the
user to edit the line of text extensively. EXPECT can also

(c) 1981 Friends Amis, Inc. 10-42 30 October 81


GLOSSARY

display a line of initial text, and allow the user to add


to it and/or edit it.
A: Address of the buffer where EXPECT is to deposit the
line it reads. This buffer can be &LBUF.
L: Length of the buffer indicated by 'adr'. The maximum
allowed length is 256. (The length of &LBUF is 80.)
EXPECT will deposit up to 'len' characters in the
buffer. Unlike the FigFORTH word EXPECT, it will NOT
deposit NULLs after the last character.
I: Length of initial text in buffer. If init=0, EXPECT
reads a completely new line. If init>0, EXPECT
considers the buffer to contain l inie characters, and
displays that many characters on the LCD before
beginning to read input.
C: Initial position of cursor.
If initc=0, EXPECT scrolls the cursor through the line
from the beginning to the end, stopping when it
reaches the end or when the user presses any key.
If 0<initc<init, the cursor is placed in position
(initc-1), origin 0. For example, if initc=3, the
cursor is placed in position #2 (over the third
character in the buffer).
If initc>=init, the cursor is placed just after the
last character in the buffer.
If initc>26, EXPECT cannot position the cursor without
scrolling the beginning of the line off the left edge
of the LCD. In this case it scrolls the line as much
as necessary to bring position (initc-1) under the
cursor. It positions the cursor in the right half of
the LCD (if (initc-1) is near the end of the text) or
in the approximate center of the LCD (if not).
E: Address of a word written to detect the end-of-line
(EOL) character.
EXPECT calls this EOL word each time a character is
read from the keyboard. EXPECT finishes editing the
line when the EOL word finds an EOL character.
The linkage to the EOL word is:
( C --- B )
where C is a character that has been read from the
keyboard, and B is TRUE iff the character is an EOL
character.

(c) 1981 Friends Amis, Inc. 10-43 30 October 81


GLOSSARY

M: The initial editing mode EXPECT should operate in. The


following symbolic constants represent the possible
modes:
%OVR Overstrike. This is EXPECT's "normal" mode.
Each input character replaces the character
under the cursor, and causes the cursor to
move right.
If the cursor is at end-of-line, each input
character is appended to the line.
The left- and right-cursor keys move the
cursor; but an attempt to move the cursor past
the beginning or end of the text will not
succeed, and will make the HHC beep.
%INSERT Insert. Each input character is inserted just
before the character under the cursor. All
following characters are bumped one position
to the right. EXPECT returns to overstrike
mode after receiving one character.
If the cursor is at end-of-line, each input
character is appended to the line.
%DELETE Delete. The "cursor left" key deletes the
character to the left of the cursor; the
"cursor right" key deletes the character under
the cursor. Any other key is considered an
error, and causes EXPECT to beep.
EXPECT returns to overstrike mode after
receiving one character.
%LI Lock-insert mode. Identical to insert mode
except that EXPECT does not return to
overstrike mode after receiving one character.
%LD Lock-delete mode. Identical to delete mode
except that EXPECT does not return to
overstrike mode after receiving one character.
L': Length of the text in the buffer when EXPECT finished
processing.
K: The character which caused the EOL word to return
TRUE.
M': Editing mode that applied to the last character
received from the keyboard.

(c) 1981 Friends Amis, Inc. 10-44 30 October 81


GLOSSARY

F! ( FP A --- )
Stores a floating point number.

F# ( FP N --- FP N )
Used by FP>ASC to assist in formatting the ASCII
representation of a floating point number.
(Used between <# and #> to put a digit of the mantissa in
the TOB. To format the entire mantissa, FP>ASC executes a
loop for N from number of significant digits desired minus
1, to 0. For each digit, if the digit is not a trailing 0,
F# converts the digit to ASCII, deposits it at the address
indicated by HLD, and decrements HLD by 1.)

F* ( FP1 FP2 FP3 )


Leaves the product of two floating point numbers.
Performs special case handling.

F+ ( FP1 FP2 FP3 )


Leaves the sum of two floating point numbers. Performs
special case handling.

F- ( FP1 FP2 FP3 )


Leaves the difference of two floating point numbers.
Performs special case handling.

F. ( FP NDIGITS N)
Displays a floating point number in standard notation (not
exponential notation).
FP is the number to display. NDIGITS is the number of
significant digits to display. N is the number of digits
displayed after the decimal point.
In the case where FP can be displayed exactly in fewer
than NDIGITS digits, the result is padded to NDIGITS
digits with zeroes to the right of the decimal point.
In the case where the integer part of FP cannot be
displayed in NDIGITS digits, the result includes whatever
number of trailing zeroes is necessary to display a
correct (rounded) result. These zeroes are not considered
"significant."
To display a number in exponential notation, use FP>ASC
and TYPE.

(c) 1981 Friends Amis, Inc. 10-45 30 October 81


GLOSSARY

F.EXT ( N M --- )
Used after 'F.' to extend a floating point number to a
specified length.
N is the length of a floating point number just displayed.
(It is the value left on the stack by 'F.'.) M is the
desired length. F.EXT extends the number to the desired
length by displaying M-N zeroes.

F/ ( FP1 FP2 --- FP3 )


Leaves quotient of two floating point numbers. Performs
special case handling.

F< ( FP1 FP2 --- B )


Tests if FP1 < FP2.

F@ ( A --- FP )
Fetches a floating point number.

FAGS ( FP --- FP' )


Sets absolute value of floating point number.

FALSE ( m B ) =
Pushes a FALSE onto the stack. The binary value of FALSE
is 0. FALSE is a synonym for 0.

FALSIFY ( X --- FALSE )


Drops the tip word on the stack and stacks a FALSE (0).

FAST.CR ( --- )
Performs a carriage return on the LCD immediately.
Distinguish FAST.CR from CR, which sets flags which will
cause a carriage return to occur at some future time.

FDROP ( FP --- )
Drops four words (one floating point number).

FDUP ( FP --- FP FP )
Duplicates the floating point number (four words) on the
top of stack.

FECB ( m A) V6
(A timer ECB used by the LCD control routines to control
cursor flashing.)

(c) 1981 Friends Amis, Inc. 10-46 30 October 81


GLOSSARY

FFFF ( N )
Stacks the value OFFFFH (-1). Note that FFFF is actually a
synonym for the colon word -1.

FILELEN ( --- LEN )


Returns length of the current virtual file space (i.e.,
of the intrinsic or extrinsic file space -- NOT the length
of the current file).
If the intrinsic file space is current, its length is
reduced by a safety factor to allow room for numeric
conversions between the end of the last file and the tip
of the temporary stack.
For the amount of free space remaining in the current file
space, see AVAIL.

FILEORG ( A)
Address of the origin of the current virtual file space
(i.e., of the intrinsic or extrinsic file space).

FILESPACE ( --- A ) V
An internal word in the virtual file system.
(Stacks address where the intrinsic virtual file space
begins.)

FILL ( A LEN C )
Fill an area in memory at address A, length LEN, with the
byte value C.

FLAG1 ( A)
(A byte of flags relating to keyboard status.)

FLAG2 ( A) V1
A byte of flags relating to keyboard and LCD status. It
controls the function of the function keys, the functions
of the SHIFT, 2nd SFT and LOCK keys, and the LCD rotat-
ion/carriage return delay, among other things. See FUNBIT
and PASSRAW.

FLAG3 ( A) V1
A byte of flags relating to various functions of timer
interrupts. It controls the auto-off feature, among other
things. See AOTOKE and AOENB.

(c) 1981 Friends Amis, Inc. 10-47 30 October 81


GLOSSARY

FLAME.ON ( )
Attaches all available output devices and binds them to
the LCD. Use this word if you want your application to
echo the LCD's display on anything that happens to be
available, e.g., the video.
Once the available devices are bound to the LCD, they
remain so until the next soft clear.

FLEE ( TAG --- )


Sets SOFTAG equal to TAG, then executes the word
identified by the tag. Note, control never returns to the
word that executed the FLEE; the word FLEE'd to returns
control directly to the operating system.
Here is a simple example of how FLEE can be used:
'X YOUR-TOP-WORD FLEE
The primary menu starts an application by doing a FLEE, so
that pressing the CLEAR key while the application is
running will restart the application. If an application
has several sub-modes, it may use FLEE to start each of
the sub-modes, so that pressing CLEAR will re-start a sub-
mode instead of re-starting the whole application.

FLEE.CAP ( )
Executes the mother tag of the external tag table in the
capsule currently switched into the capsule address space.

FLEE.CROM ( DEVCODE )
FLEEs to the application program, if any, stored in the
control ROM for the peripheral with the specified software
device code.

FLIM ( A )
Returns the address of the first free byte in the current
virtual file space.

FLIP ( X --- X' ) C


Exchanges the high- and low-order bytes of X.

FLIT ( --- FP )
"Floating point literal." Places the next four words after
this tag on the stack, and passes control around the
words.
At run time, FLIT works like the run-time words LIT (which

(c) 1981 Friends Amis, Inc. 10-48 30 October 81


GLOSSARY

stacks a word literal) and CLIT (which stacks a character


literal). FLIT is listed here as well as with the run-time
words because the compiler currently cannot generate it
automatically from a floating point constant.
To use FLIT to compile a floating point number, use the
following words:
FLIT 1 n1 ,-V n2 ,-V n3 ,-V n4 ,-V
where n1 to n4 are the values of the four words that make
up the floating point constant, FP.

FNEGATE ( FP --- FP' )


Stacks the negative of FP (i.e., -1*FP).

FOVER ( FP1 FP2 FP1 FP2 FP1 )


Copies the second floating point number on the stack to
the top of the stack.

FP ( A) V2
The address of the first free byte in in the current file
space. Maintained by the file system.

FP>ASC ( FP NDIGITS --- A L NEXP )


Converts a floating point number from internal form to
exponential notation.
FP is the number to be converted. NDIGITS is the number of
significant digits desired in the result.
A L are the address and length of the mantissa, which
is in ASCII. NEXP is the exponent, which is a (binary)
integer.
A special case returns an exponent of zero, and a mantissa
with the following value:
0 is 0
underflow is U
overflow is V
complex is i
zero divide is Z
other is ?

FROUND ( FP NDIGITS FENCE --- FP' NDIGITS' )


Used before F. to round a floating point number to a
specified number of digits.
1. FP is the number to be rounded.

(c) 1981 Friends Amis, Inc. 10-49 30 October 81


nr- SSARY

NDIGITS is the maximum desired number of significant


digits.
FENCE is the desired position of the last significant
(i.e., possibly non-zero) digit in the rounded number,
relative to the decimal point. The value of FENCE is
interpreted as follows:

-2 last significant digit is in 0.1's column.


-1 last significant digit is in l's column.
0 last significant digit is in 10's column.
1 last significant digit is in 100's column
2 last significant digit is in 1000's column.

FP' is the rounded number.


NDIGITS' is the actual number of significant digits.
NOTE: FP is not actually rounded. The last significant
digit is fixed so that when the number is printed with
NDIGITS' significant digits (and truncation) it will
APPEAR rounded.
Example: we want to print 1234.567 with 5 significant
digits, leaving one digit right of the decimal point. We
can do this as follows:
1234.567 5 -2 FROUND F.
FROUND changes the number to 1234.667, and leaves a 5 on
the stack. F. prints 1234.6 and leaves a 1 on the stack.
Another example: we want to print 1234.567 with 2
significant digits, with the last significant digit 3 left
of the decimal point. We can do this as tollows:
1234.567 2 1 FROUND F.
FROUND leaves the number as 1234.567 and leaves a 4 on the
stack. F. prints 1200 and leaves a 0 on the stack.

FSPACE ( A )
Returns the address of the first file in the current file
space. If the file space is empty, returns the address
where the first file will go.

FSTANDTYPE ( N --- TYPE )


Returns the special-case type of a floating point number.

(c) 1981 Friends Amis, Inc. 10-50 30 October 81


GLOSSARY

N is the stack position at which the number starts. For


example, if the number starts immediately under N, then N
should be 1 (N itself occupies position 0!). If the number
starts under N and one other floating point number, then N
should be 5, and so forth.
The possible values of TYPE are:
0 -> valid non-zero number.
1 -> zero.
2 -> underflow.
3 -> overflow.
4 -> complex number.
5 -> zero divide.
-> enigma or user-defined code (number contains a
codes 6 to 7F).
Notice that the codes representing special cases are all 1
greater than the numbers of the cases they represent. This
is because "valid number" and "zero" have distinct codes.

FSWAP ( FP1 FP2 FP2 FP1 )


Swaps two floating point numbers.

FUNBIT ( --- FL )
A flag in FLAG2 which controls operation of the function
keys. 1 -> the keys are processed normally. 0 -> the keys
are ignored; they do not have their normal "macro"
functions, nor are they passed through the keyboard buffer
as distinct characters.

FVAR ) DEF
Used in a TSA to reserve 8 bytes of storage for a floating
point variable. For example:
FVAR ERRVAL
This reserves a 8 bytes for a variable named ERRVAL.

(c) 1981 Friends Amis, Inc. 10-51 30 October 81


GLOSSARY

GET-TYPE ( --- A )
Returns the address of the file-type byte for the current
virtual file. You can read the file-type byte with C@ and
set it with C!.
The value of the file-type byte is the logical OR of the
file-type attributes that apply to this file. The symbolic
constants defining the file-type attributes are:
%INVISIBLE: file will not be displayed in file selection
menus.
%TEMPORARY: file will be deleted automatically at next
CLEAR. (Auto-delete support not currently
implemented.)
%EXECUTABLE: file contains executable SNAP code.
(Execution support not currently
implemented.)
%TEXT: file contains ASCII text. (This is the only
type of file that may be edited. Note that
%TEXT and %EXECUTABLE are logically
incompatible.)
%BASIC file contains a Microsoft Basic program. The
program is stored in ASCII except for Basic
keywords, which are represented by one-byte
binary codes. NOTE: the symbol %BASIC is not
pre-defined. If you need it, assign it the
value 10H.
NOTE: this word compiles into TWO tags, representing the
words &CFILE and 2+.

GET.GMT ( --- DSEC TICKS ) C


Get time of year. DSEC is an unsigned double integer
giving seconds since midnight on 1 January 1980. TICKS is
an unsigned integer giving clock ticks.

GET.LOCAL ( --- DSEC )


Get time of year.
(At some future time, GET.LOCAL may return local time, and
GET.GMT, Greenwich Mean Time. For now they return the same
time.)

GMT ( ____ A ) V4
Time of century of the next timer interrupt, in seconds.

(c) 1981 Friends Amis, Inc. 10-52 28 October 81


GLOSSARY

GMT points one byte past GMTF; that is, GMT points to the
2nd byte of the 5-byte area at GMTF.

GMTF ( A ) V5
Time of century of the next timer interrupt, in clock
ticks.
GMTF may be used to get a time of century that is more
accurate than that obtainable with GET.GMT, the usual
choice for getting time of century. GET.GMT is accurate
only as of the most recent interrupt.
To get an accurate time of century, do a SET.DELAY for a
short time period (e.g., 0.1 second). Immediately after
setting the delay, check to see that the delay has not yet
expired (i.e., the associated ECB is not yet posted). If
not, get the time with GMTF; it is in the future by no
more than the duration of the delay that you set.

GRAB ( N --- [A] B )


Determines whether there is enough space in intrinsic RAM
to allocate N bytes of storage space. If there is enough
space, returns the address of the space and TRUE. If there
is not enough space, returns FALSE.
.41w The allocated space is, in effect, an extension to the
current TSA. If the program releases the TSA with LETGO,
it will release the space allocated by GRAB, as well.

GROUND.MENU ( --- A )
(A list of count-format strings used by the menu driver to
display the names of the intrinsic applications in the
primary menu.)

(c) 1981 Friends Amis, Inc. 10-53 28 October 81


GLOSSARY

H: ( ) COMP
"Host definition." Used like defines a word that is
to be available during compilation (by the simulator or
cross-compiler) but not during execution (by the simulator
or the HHC). The equivalent of a macro definition in
conventional assembled or compiled languages.

HARD.CLR ( )
Performs a hard clear, as though the user had pressed the
CLEAR key twice in succession.

HDTSAV ( A)
(An internal word used by the I/O routines.)

HDTSZ ( N )
(The size of an HDT in bytes (6).)

HERE ( A) COMP
A synonym for HERE-V.

HERE-V ( A --- ) COMP


Stacks the address in the cross-compiler's target address
space where the next piece of compiled code will go.

HEX ( ) COMP,NOTE
Sets BASE to 16. This causes output words such as 1.1 and
'R.', and conversion words such as '<# #S #>', to display
numbers in base 16.
NOTE: use HEX only outside colon definitions, to set the
compile time base. In SNAPPLE, HEX is defined in the
target vocabulary, and functions as a normal target
definition; but in the cross-compiler, HEX is an immediate
word.

HINTFLAG ( --- FL )
(An unused bit flag mask.)

HOLD (C )
Used to insert an ASCII character into an ASCII number
being created by "<# #S #>". May be used to insert a
decimal point, for example. See "<#" for details.

(c) 1981 Friends Amis, Inc. 10-54 28 October 81


GLOSSARY

I ( N)
Used in a DO loop to copy the loop index onto the stack.

I/O ( A)
(Address of the "I/O page," a memory mapped region used by
device drivers and intrinsic I/O routines. Note that the
so-called I/O page does not begin on a 6502 page boundary.

IDICT ( A)
Stacks the address of the short intrinsic tag table.
You can stack the entry point of a word represented by a
short intrinsic tag (OOH to OBFH) by loading the word at
the following address, where "tn" represents the tag
number:
IDICT tn 2* +
You can stack the entry point of a word represented by a
long intrinsic tag (100H to 1FFH) by loading the word at
the following address, where "tn" represents the tag
number:
HEX
IDICT SHINT + SHINT +
tn 100 - 2*

IF (B ) CTRL
Used to begin an IF construction.
Used in the form:
IF tttt... ELSE eeee... ENDIF or
IF tttt... ENDIF
If B is TRUE, "tttt..." is executed and "eeee..." (if any)
is skipped. If B is false, "tttt..." is skipped and
"eeee..." (if any) is executed.
(At compile time, the form is "--- A N". IF compiles a
OBRANCH and reserves 2 bytes after it where ELSE or ENDIF
can insert the offset to branch to if B is FALSE. A is the
addres of the reserved space; N is used for error
checking.)
See also LONG.IF.

(c) 1981 Friends Amis, Inc. 10-55 28 October 81


GLOSSARY

IF.ITS ( N N ) CTRL
A CASE-like statement used to make a choice based on a
numeric value. IF.ITS is useful where clarity or
compactness is more important than etticiency, and where
the possible values are scattered. It is most often used
to execute code based on a menu selection.
The word is used like this:
X @ \ VALUE TO CHOOSE WITH.
IF.ITS 1 code-for-choice-1 ENDIF
IF.ITS 2 code-for-choice-2 ENDIF
IF.ITS 3 code-for-choice-3 ENDIF

IF.ITS n choice-n ENDIF


DROP
The word IF.ITS must be followed by a constant or symbolic
constant in the range 0-255, inclusive. If N is equal to
the constant, IF.ITS executes the code between the
constant and the ENDIF.

INS.CH.R (N )
Shifts the right part of the LCD display right one
character. the character in position N is shifted to
position N+1; all following characters are shifted after
it. The original contents of the last position is lost;
the contents of position N is not disturbed. SEE ALSO
DE.CH.R.

INSERT ( A L N B )
Inserts a new record before the N'th record of the current
virtual file. The new record consists of the data at
address A, length L. B is TRUE.
To add a record to the end of the tile, use N = the number
of records in the file (one greater than the record number
of the last record). The word REC-CNT returns this value.
If N is greater than the number of records in the file
(i.e., if record N-1 does not exist), no record is
inserted and B is FALSE.

INTFLAG ( --- FL )
(A flag in PCA byte 3. 0 -> an interrupt is being
requested from this peripheral; 1 -> no interrupt is being
requested.)

IOSAV ( A) V1
(Used internally by I/O routines to hold a code identify-

(c) 1981 Friends Amis, Inc. 10-56 28 October 81


GLOSSARY

ing the peripheral controller ROM entry point to call.)

IPBANK ( ___ A ) V1
(Bank ID of the memory bank the tag now being interpreted
is in.)

IPBIT ( --- FL ) =
(A bit in FLAG2. 1 -> the HHC is in input mode; i.e., a
keystroke has been encountered since the list EMIT was
executed.)

IRQVECT ( --- A ) =
Address of a JMP instruction that jumps to the entry point
of a user IRQ routine. The normal user IRQ routine is a
null routine; that is, it just returns to its caller. You
can intercept IRQ's by changing IRQVECT to jump to your
own IRQ handler.

IRQX ( ___ A ) V1
(Area where the nucleus saves the X register before
calling the IRQ handler in a peripheral control ROM. The X
register always points to the PCA in this context.
(See also IRQY.)

IRQXV ( ___ A ) =
(Address of a JMP instruction that jumps to the entry
point of the IRQ routine in the peripheral controller ROM
currently switched into the address space.)

IRQY ( ___ A ) V1
(Area where the nucleus saves the Y register before
calling the IRQ handler in a peripheral control ROM. The Y
register always points to the HDT in this context.
(See also IRQX.)

IVECT1 ( ___ A ) V1
(Used internally by inner loop to decode tags.)

IVECT2 ( ___ A ) V1
(Used internally by inner loop to decode tags.)

(c) 1981 Friends Amis, Inc. 10-57 28 October 81


GLOSSARY

J ( N) C,NOTE
Copies the value of the index of the second outer nested
DO loop onto the stack.

Note: in other implementations of FORTH, there is a


restriction that both loops and the reterence to 'J' must
be in the same colon definition. In SNAP, this restriction
does not apply.

JUMP-TAB ( N ) DEF
Defines a "jump table" that can be used to execute one of
several words depending on the value of a word on the
stack.

JUMP-TAB is used like this:

4 JUMP-TAB FOUR.WORDS
WORD1
WORD2
WORD3
WORD4
This example defines a jump table with 4 entries, named
FOUR.WORDS. The entries in the jump table are four words
(defined elsewhere, with tags) named WORD1, WORD2, WORD3,
and WORD4.

A jump table defined by JUMP-TAB is used like this:

: JUMPING.LIZARDS ( )

JUMP.TO.ME @ FOUR.WORDS

In this example, JUMP-TO-ME is presumably a variable


containing a jump table index between 0 and 3. If the
index is 0, the illustrated line of code executes WORD1;
if the index is 1, the code executes WORD2; and so forth.

CAUTION! A jump table word defined by JUMP-TAB does not do


its own range checking. Executing a jump table word with
an invalid index produces unpredictable results. You can
conveniently check the range before executing a jump table
word by using ?RANGE.

(c) 1981 Friends Amis, Inc. 10-58 28 October 81


GLOSSARY

KB ( ___ A ) =
(Address of the keyboard's hardware I/O area. When the
user presses a key, a binary value is stored somewhere in
this area. The "raw keyboard code" is derived from the
value that is stored and the address of the byte that the
value is stored in.)

KBFLAG ( --- FL ) =
(A flag in HDT byte 0. 1 -> this HDT represents the
keyboard.)

KBSET ( _a_ A ) K2
The standard keyboard translation table. To make the
standard table the current table, execute:
KBSET KBVECT !

KBVECT ( ___ A ) V2
Address of the current keyboard translation table. You can
change the HHC's current keyboard translation table by
changing the contents of KBVECT.

KECB ( --- A ) V2
(An ECB used by the keyboard input routines.)

KEY ( ....._ c ) NOTE


Read key. (Actually read from keyboard buffer.)
If the user has pressed LOCK and SHIFT, or if he has just
pressed SHIFT, the keystroke returned is case-shifted.
Note, case shifting is done on the simulator by pressing
the ESCAPE key.

KQ ( --- A ) V8
The keyboard buffer. This is a ring buffer with KQI
pointing to input (from keyboard) and KQO pointing to
output (to KEY).

KQHI ( ____ N ) =
Length of the keyboard buffer in characters. This is the
maximum number of characters that the HHC can buffer
between keyboard input and program processing. The current
value is 8.

(c) 1981 Friends Amis, Inc. 10-59 28 October 81


GLOSSARY

KQI ( A) V1
The keyboard buffer input pointer. Contains the aisplace-
ment of the byte in the keyboard buffer where the next
character read from the keyboard will be stored. Note that
keys are stored backwards, e.g., the value of KQI is
initially 7, then becomes 6, 5, 4, .— 0, 7, ...
See also KQ, KQO.

KQO ( A) V1
The keyboard buffer output pointer. Contains the displace-
ment of the byte in the keyboard buffer from which the
next character passed to KEY will be tetched.
The buffer is empty when KQO and KQI (the input pointer)
are equal.
See also KQ, KQI.

(c) 1981 Friends Amis, Inc. 10-60 28 October 81


GLOSSARY

L>U (C C' )
Converts a lower case character to upper case. L>U has no
effect on characters which are not lower case.

LASTFLAG ( --- FL )
(A flag in HDT byte 0. 1 -> this is the last HDT in the
HDT list.)

LATCH ( A ) V1,NOTE
(Stacks address of the LATCH, a special one-byte segment
of the address space whose bit settings control various
aspects of the HHC's hardware status. Symbolic constants
defining the functions of the bits in LATCH are:

(Any program which needs to read the latch should do so by


fetching LATCHS, a copy of the latch that is kept current
by software. The latch is implemented with write-only
hardware, and cannot be fetched directly.
(Application programs should not try to manipulate the
latch. System programs that need to manipulate the latch
should do so indirectly by using the words ANDLATCH and
ORLATCH, which update LATCHS.

VALUE
WORD (HEX) MEANING
n/a 1 Indicate which intrinsic capsule
n/a 2 capsule socket (if any) is currently bank-
switched into the address space. Values
00B, 01B, and 10B represent sockets 0, 1,
and 2. Value 11B has no meaning.
CAPON 4 1-> an intrinsic capsule socket is bank-
switched into the address space. 0 -> a
capsule socket in a ROM expander is bank-
switched into the address space.
DISPON 8 1-> HHC is turned on, 0-> off.
SLOMEM 10 1-> addressing slow ROM, 0-> normal.
BEEPER 20 High/low DC to speaker. Software can toggle
this bit to generate audio.
CPUON 40 1-> CPU power on, 0-> off.
DMASK 80 Selects function of memory mapped area for
keyboard/LCD functions. 1-> LCD control,
0->keyboard control.
(Note that the latch is write-only. To interrogate the
latch's status you must read LATCHS, below.)

411,0. LATCHS ( A) Vi

(c) 1981 Friends Amis, Inc. 10-61 28 October 81


GLOSSARY

The "latch shadow," a copy of the latch maintained by the


HHC nucleus. A program which needs to interrogate the
latch must do so by reading this byte.

LATSAV ( --- A ) V1
(A byte in N used internally by I/O routines to save latch
byte settings.)

LCD.CR ( --- ) C
(A word used internally by LCD I/O routines to perform the
function of the "carriage return" character.)

LEAVE ( ___ ) C
Used to force early termination of iteration in a DO loop.
LEAVE sets the loop limit equal to the current value of
the index. This causes termination of the loop at the end
of the current iteration. NOTE, it does NOT cause
immediate termination of the loop.

LETGO ( --- )
Releases the TSA most recently allocated and not yet
released. This permits you to use variables defined in the
first-allocated remaining TSA. You may also re-use the
space in the released TSA (by allocating a new TSA, for
example).

LITERAL ( N --- ) ',NOTE


At compile time, compiles a LIT, then compiles N into the
target address space.
The intended use of LITERAL is to perform compile time
calculations, and compile a 16-bit result into the code:
: wwww xxxx... [ x y + ] LITERAL xxxx... ;
"wwww" is the name of the word being defined and "xxxx..."
is other code that appears in the definition.
"cccc" is code which is to be executed at compile time. It
should leave a 16-bit value on the stack. LITERAL compiles
the value into the program as a constant.
EXAMPLE: suppose FL1 and FL2 are symbolic constants (see
definition of '==') representing bit flags. The following
code will test FLCODE to see if either FL1 or FL2 is on,
performing only one logical test at run time.
: wwww xxxx...
[ FL1 FL2 OR J LITERAL FLCODE C@ AND ...

(c) 1981 Friends Amis, Inc. 10-62 28 October 81


GLOSSARY

LOBAT ( A ) V1
(A byte whose 80's bit is turned on to indicate the
"battery low" condition.)
LOC.NXT.CAP ( B)
Searches through ROM ID's for the next available ROM
capsule after the one now switched into the capsule
address space.

To search all ROM ID's for ROM capsules, execute -1


SET.ROM. This sets the "current ROM ID" to -1 (a meaning-
less value) but does not affect the ROM actually switched
into the address space.
Now execute 'LOC.NXT.CAP'. LOC.NXT.CAP returns TRUE,
switches the first available capsule (in ROM ID order)
into the capsule address space, and stores that capsule's
ROM ID in CURROM.
Continue executing LOC.NXT.CAP until it returns FALSE.
FALSE indicates that there are no more capsules available.
The capsule address space is not switched and CURROM is
not changed.
Note that you cannot execute LOC.NXT.CAP from a program in
,.. a ROM capsule, since LOC.NXT.CAP will switch the ROM
containing the program out of the address space!
See also CURROM, LOC.PRG.

LOC.PRG (N [ [N'] B'] B )


Searches through ROM ID's for a program in a ROM capsule
or a peripheral controller ROM.
N is a number identifying the program to be switched in.
If 'P' is the number of programs available, N may have any
value from 0 to P-1.
If program #N is available (i.e., if 0<=N<=P-1), B is
TRUE; B' is present, and N' may be present. If not, B is
FALSE; B' and N' are both omitted.
If the program is in a peripheral control ROM, B' is 1 and
N' is present. If not, B' is 0 and N' is absent.
N' is the software device code of the peripheral control
ROM containing the program. You can FLEE to the program by
placing this code on the stack and executing FLEE.CROM.

See LOC.NEXT.CAP, FLEE.CROM.

(c) 1981 Friends Amis, Inc. 10-63 28 October 81


GLOSSARY

LOCATE ( BIGADDR BIGLEN SMADR SMLEN --- [DISP] B )


Locates a substring in a string.
BIGADDR and BIGLEN are the address and length of the
string to be searched. SMADR and SMLEN are the address and
length of the string to be searched for.
If the string is found, DISP is the origin-zero
displacement of the substring, and B is TRUE.
If the string is not found, DISP is absent and B is FALSE.

LOCK.IT ( --- FL )
(A flag in FLAG1. 1 -> LOCK key is in effect, 0 -> not.)

LOCKBLIP ( --- MASK )


A mask for the "lock" ("keyboard locked") blip. See
ANDBLIP for details.

LOCKED? ( --- FL )
(A flag in FLAG1. 1 -> we're locked in SHIFT or 2nd SFT
mode, 0 -> we're not. Meaningful only when SHIFT? is
true.)

LONG ( .11.1.000.111M )
COMP
Instructs the compiler to reserve a long tag number for a
specific word, and assign that tag number to the word
regardless of whether it is assigning long or short tags
to other words when the word is defined. LONG is used like
this:
LONG word
It must be used BEFORE the word in question is defined.
Use LONG before the first colon definition in your program
to identify the word that is to be the program's entry
point. This works because SNAP uses the first tag in the
program's long tag table vector to be the entry point.

LONG.ELSE ( --- ) CTRL


See LONG.IF.

LONG.ENDIF ( --- ) CTRL


See LONG.IF.

(c) 1981 Friends Amis, Inc. 10-64 28 October 81


GLOSSARY

LONG.IF B ) CTRL
Use LONG.IF, LONG.ELSE and LONG.ENDIF in place of IF, ELSE
and ENDIF when the code between IF and ELSE or between ELSE
400. and ENDIF is more than 255 bytes long. These words generate
jumps with two-byte displacements, rather than the one-byte
displacements generated by IF, ELSE and ENDIF.
When you need to use LONG.IF, etc., the compiler will
inform you by giving you an error message in response to
IF, ELSE, and ENDIF.

LONG.REPEAT ( ) CTRL
See LONG.WHILE.

LONG.TAGS ( ) COMP
Instructs the compiler to compile defining words into long
tags until further notice. LONG.TAGS is the opposite of
SHORT. TAGS.

LONG.WHILE ( B ) CTRL
Use LONG.WHILE and LONG.REPEAT in place of WHILE and REPEAT
when the code between WHILE and REPEAT or between BEGIN and
REPEAT is more than 255 bytes long. These words generate
jumps with two-byte displacements, rather than the one-byte
displacements generated by IF, ELSE and ENDIF.
When you need to use LONG.WHILE and LONG.REPEAT the
compiler will inform you by giving you an error message in
response to WHILE and REPEAT.
Note that there is no LONG.BEGIN word; BEGIN serves both
the short and long forms of the WHILE loop.

Note also that there are no LONG.UNTIL and LONG.AGAIN


words; you must use LONG.WHILE and LONG.REPEAT.

LOOKUP ( N [A] B )
Returns the address of the N'th file in the current file
space.
If file N exists, A is the address of the file (i.e., of
the "length of file" field) and B is TRUE. If file N does
not exist, A is absent and B is FALSE.

LOOP ( ) CTRL
Used to terminate a DO loop.
The index is incremented by 1. If the new index value <
limit, control returns to the first word after the
corresponding DO. If the new index value >= limit, the

(c) 1981 Friends Amis, Inc. 10-65 28 October 81


GLOSSARY

loop parameters are discarded and control passes to the


next word after LOOP.

LP ( A ) 171
(Displacement of the first free byte on the loop stack
from the beginning of page 1. Add 100H to this value to
get the address of the first free byte on the loop stack.
(If the address of the base of the loop stack is given by
LSTK; thus, if the value of LP is equal to LSTK, the loop
stack is empty.)

LSTK ( A )
(The address of the base of the loop stack.)

(c) 1981 Friends Antis, Inc. 10-66 28 October 81


GLOSSARY

M* ( N1 N2 --- ND )
ND = N1 * N2.

M/ ( ND N1 --- N2 N3 )
N2 = signed remainder of ND/N1. (The remainder takes its
sign from the dividend.)
N3 = signed quotient of ND/N1.

M/MOD ( UD1 U2 --- U3 UD4 )


U3 = remainder of UD1/U2.
UD4= quotient of UD1/U2.

MAKE (AL B)
Creates a new virtual file.
A and L are the address and length of the file name. B is
TRUE if the file can be created; FALSE if it already
exists or if there is no space for it.

MAX ( N1 N2 --- N3 )
N3 = the greater of N1,N2.

MAXBANK ( N)
(The maximum number of RAM and ROM banks that the HHC may
support at one time. The current value is 64.)

MAXDEV N )
The maximum logical unit number that the HHC can support;
one greater than the highest valid logical unit number.
The current value is 16.

MEMBLIP ( --- MASK )


A mask for the "insert" blip. See ANDBLIP for details.

MENU-DRIVER ( N TAG1 TAG2 )


Main entry point to the HHC's standard menu driver word.
After setting up appropriate tables and lower-level words,
you can call MENU-DRIVER to display a standard HHC menu
that presents (and executes) the functions your
application program is to perform.
N is the number of the menu item MENU-DRIVER is to display
first. (The usual value is 1.)

(c) 1981 Friends Amis, Inc. 10-67 28 October 81


GLOSSARY

TAG1 is the tag of a word with the following linkage:


( N --- N ) {N a valid menu option number}
( N --- 0 ) {iq not a valid menu option number}
If N is a valid option number, the word executes code to
process that option. (Get the tag of the word width 'X.)
TAG2 is the tag of a word with the following linkage:

( N --- B )
If N is a valid option number, the word displays the text
(not including the leading number) of the option message;
B is TRUE. If N is not a valid option number, the word
displays nothing; B is FALSE.

See the sample programs elsewhere in this document for


examples showing the use MENU-DRIVER.
NOTE: MENU-DRIVER executes an endless loop; there is no
way to escape from it except by pressing CLEAR.
NOTE: MENU-DRIVER leaves things on the stack when it calls
the word at TAG2, and expects them to be there -- at the
top of the stack -- when control is returned! Because of
this, MENU-DRIVER will behave unpredictably if a word
implementing one of your lower-level functions leaves
garbage on the stack when it returns control. This can
cause a puzzling error; the symptom is that when a word is
called directly it appears to work right, but when it is
called through MENU-DRIVER, the program dies when the word
returns control.

MIN ( N1 N2 --- N3 )
N3 = the lesser of Ni,N2.

MINUS ( N --- N' ) C


A synonym for NEGATE.

MOD ( N1 N2 --- N3 )
N3 = N1 modulo N2 (remainder of N1/N2). Sign of N3 is same
as Ni.

MOVE ( Al A2 L --- )
Move data from Al to A2, length L. The move is managed so
that the data cannot overlay itself, no matter what values
of Al, A2, and L are used. This allows overlapping source
and destination areas to be MOVEd successfully.

(c) 1981 Friends Amis, Inc. 10-68 28 October 81


GLOSSARY

L is an unsigned integer; thus a "negative" length will be


interpreted as a length > 32565. This is a sure way to
wipe out a program.
CMOVE is a similar instruction that will overlay data if
Al < A2 < Al+N.

(c) 1981 Friends Amis, Inc. 10-69 28 October 81


GLOSSARY

NAP ( TICKS SEC --- [Cl B )


Go to sleep for specified time or until a keystroke is
entered.
SEC is seconds to sleep. TICKS is the number of clock
ticks to sleep; it must be in the range 0-255.
If the nap is ended by time expiration, C is absent and B
is FALSE.
If the nap is ended by a keystroke, C is the character
entered and B is TRUE. A subsequent KEY or equivalent word
will NOT get the same character.

NATTACH ( A) VI
(A counter used internally by BIND.)

NEGATE (N N' ) C
N' = -1 * N.

NEVER ( X --- FALSE )


Drops one word from the stack and returns FALSE.

NEXT ( A) V3
(Address of a JMP instruction that points to the SNAP
inner loop. Changed by the HHC's nucleus to handle certain
types of interrupt conditions.)

NEXTV ( A) V1
(Address of a variable used to repoint NEXT to bank
switching code when SNAP must execute a tag defined in
another memory bank.)

NFILES ( A)
Stacks the address of a word containing the number of
files existing in the current file space.

NMIVECT ( A) V2
(Non-maskable interrupt vector. May be changed to point to
a low level NMI processing routine. The default NMI
processing routine is a null routine; is returns control
immediately to the caller.)

NOP =la .11•0


C

(c) 1981 Friends Amis, Inc. 10-70 29 October 81


GLOSSARY

"No operation." Generates an HHC tag which has no effect


when executed.
If a program is being executed from RAM (in Snapple or the
SNAP capsule), such a tag is useful as a placeholder for
space where another tag can be patched in at run time.
Patching code in this way is not a legitimate coding
technique, but is occasionally useful during debugging.

NOT ( X --- X' )


Reverses results of a previous logical test. Functionally
identical to 0= . Changes 0 to 1, non-zero to 0.

NOTIF ( B --- ) CTRL


Equivalent to '0= IF'. For example:
A @ NOTIF XYZ ENDIF
XYZ is executed if the contents of A is zero.

NREC ( N --- [A L] B )
An internal word in the virtual file system.
(Finds a record in the current virtual file. N is the
number of the record. If the record is found, A L are its
address and length; B is TRUE. If the record is not found,
A L are absent; B is FALSE.

(c) 1981 Friends Amis, Inc. 10-71 29 October 81


GLOSSARY

ONFLAG ( A) V1
(A byte used to turn the CPU on and off. The 80's bit
controls the on/off status.)

OPEN (AL B)
Opens an existing virtual file.
A and L are the address and length of the file name. B is
TRUE if the file is found; FALSE if not.

OPEN-FILE (N )
(Opens the N'th file in the current file space. Used
internally by OPEN.)

OP FLAG ( --- FL )
(A flag in HDT byte 1. 1 -> this HDT represents a device
capable of output.)

OR (XY Z) C
Performs a bitwise logical OR.

ORBLIP (N )
ORs the low-order byte of N into the LCD blip mask. If a
bit is 1 in N, the corresponding blip is turned on; if a
bit is 0 in N, the corresponding blip is unchanged.
For a list of symbolic constants that may be used to
designate the bits, see ANDBLIP.

OVER ( X Y --- X Y X ) C
Copies 2nd entry on stack.

(c) 1981 Friends Amis, Inc. 10-72 29 October 81


GLOSSARY

PACKUP ( --- DN ) NOTE


Converts a date and time to a time of century expressed in
seconds.
Before executing PACKUP, you must store the date and time
you wish to convert in &LBUF. Each element is stored as a
one-byte binary number:
&LBUF
byte store this
0 month (0 to 11 for January to December)
1 day (0 to 30 for days 1 to 31)
2 year (0 to 99 for 1980 to 2079)
3 AM/PM (0 for AM, 1 for PM)
4 hour (1 to 12 for 1:mm:ss to 12:mm:ss)
5 minute (0 to 59 for hh:00:ss to hh:59:ss)
6 second (0 to 59 for hh:mm:00 to hh:mm:59)
NOTE: PACKUP is a tagless word. It must be executed with
(CALL). To locate its entry point, add 4 to the address of
the entry point of the word represented by tag 104H. The
following word may be used to call PACKUP:
HEX
: PACKUP (S --- DN )
\ ADR OF TAG TABLE ENTRY FOR WORD 104H.
[ IDICT SHINT + SHINT + 8 + ] LITERAL
@ \ A(ENTRY PT) FOR WORD W/TAG 104H.
4 + \ A (ENTRY PT) FOR PACKUP.
(CALL) ; \ (CALL) IT.

See also TC!.

PASSRAW ( --- FL )
A bit in FLAG2 which controls the operation of the SHIFT,
2nd SFT, and LOCK keys. 1 -> the keys have their normal
functions. 0 -> the keys place binary codes in the
keyboard buffer, like ordinary character keys.

PATLEN ( ....... L )
(Length of the "pattern" used to re-initialize several
I/O-related vectors, such as the address of the keyboard
translation table, during a clear.)

PCASAV ( ___ A ) V1
(A byte in N used internally by I/O routines to save the
displacement of the current PCA.)

(c) 1981 Friends Amis, Inc. 10-73 29 October 81


GLOSSARY

PCH ( A) V1
(Value of the previous raw keyboard character code. Used
internally by keyboard debouncing routines.)

PENDFLAG ( --- FL )
(A flag in HDT type 1. 1 -> I/O operation is pending on
this device.)

PICK Xy X3 X2 X1 y Xy ... X3 X2 X1 Xy )
Copies y'th entry on stack to the top.

PIPFLAG ( --- FL )
(A flag in PCA byte 0. 1 -> this PCA represents a device
capable of doing input.)

PKCT ( A ) V1
The pushkey buffer pointer. Contains the number of char-
acters currently in the pushkey buffer, PKQ. If the value
is 0, the buffer is empty, and the next character in the
input stream will come from the keyboard buffer. If the
value is 4, the pushkey buffer is full.
See also PKQ.

PKEY ( A) VI
(A location in which input characters are deposited when a
RIP is done on the keyboard.)

PKQ ( A) V4
The pushkey buffer. This is a 4-byte stack containing
characters "pushed" into the keyboard input stream by the
program.
The stack grows upward; thus the first character pushed
into the buffer goes at PKQ, and the 4th (and last) char-
acter pushed into the buffer goes at PKQ+3.
See also PKCT.

POP FLAG ( --- FL )


(A flag in PCA byte 0. 1 -> this PCA represents a device
capable of doing output.)

POSN ( N )
Used internally to manage LCD display. Not normally used

(c) 1981 Friends Amis, Inc. 10-74 29 October 81


GLOSSARY

by applications.
(Positions cursor in character position N. The next EMIT
or -EMIT will put a character where the cursor then is.

POZECB ( ___ A ) V6
The timer ECB used by NAP. In synchronous routines it is
safe to use this ECB for any purpose such that NAP cannot
be executed while it is in use. (This means mainly words
that perform a waiting function similar to NAP.)

PROGBIT ( ___ F ) =
A bit mask for CSPEED. See CSPEED for details.

PSECB ( ____ A ) V6
(Timer ECB used by the clock controller. If any clock
controller alarms are defined, this ECB is in the timer
queue, and contains the time of the next alarm to come
due. If no alarms are defined, this ECB is all-zero and is
not in the timer queue.
When the timer represented by this ECB is exhausted the
HHC issues its trumpet fanfare and resets the timer for
now plus 10 minutes. When the clock controller cancels the
alarm that has come due, it also adjusts the ECB to
reflect the next remaining alarm in the queue (if any).

PUSHKEY ( C --- ) C
Pushes a character into the pushkey buffer. See PKQ, PKCT.

(c) 1981 Friends Amis, Inc. 10-75 29 October 81


GLOSSARY

R ( )
Copies X from top of return stack.

R> ( )
Pops X from top of return stack.

RAM.N (N B )
Given the relative bank ID of a RAM bank, N, tries to
switch the RAM bank into the extrinsic RAM address space.
Available RAM banks are numbered consecutively from 1.
If the RAM bank exists, RAM.N switches it in and returns
B=TRUE. If not, RAM.N returns B=FALSE.

RAMADDR ( A )
Address of the beginning of the extrinsic RAM address
space (8000H).

RAMS IT ( --- FL )
(A bit in FLAG3 indicating whether to do a hard clear when
exiting from the I/O key processor. 1 -> do a hard clear;
0 -> do no clear.

(A hard clear is necessary if a virtual file is open and


the user has used the I/O key to change the current file
space.)

RAMEXFLAG ( --- FL )
(A flag in PCA byte 0. 1 -> the PCA represents a program-
mable memory peripheral.)

RCLOSE ( ECBADR LUN B)


Initiates a "close" operation on the device identified by
logical unit number LUN, using an ECB at ECBADR. B
indicates success or failure of the operation.
A successful RCLOSE must be followed (eventually) by a
WAIT and a test for successful conclusion of the closing
operation.
RCLOSE is not normally needed by applications, since the
CLEAR key forces an RCLOSE on all tiles.

RCSAV ( A)
(A byte in N used internally by I/O routines to save an

(c) 1981 Friends Amis, Inc. 10-76 29 October 81


GLOSSARY

ECB return code.)

RCTL ( ECBADR LUN --- B ) C


Initiate a "read status" or "write control" operation on
the device identified by logical unit number LUN, using an
ECB at ECBADR. B indicates success or failure of the
operation.
The ECB must be 2 bytes long. The second byte contains a
command code indicating the type of control operation to
be performed.
A successful RCTL must be followed (eventually) by a WAIT
and a test for successful conclusion of the operation.
If the operation is a "read status" type, byte 1 of the
ECB contains the status byte on return from a successful
WAIT.

READ ( A L N --- [L'] B )


Read a record from the current virtual file.
A L are the address & length of a buffer area in RAM. N is
a record number.

lis. If the record exists, READ moves the record to A,


truncating it to length L if necessary. L' is the length
of the record (after truncation if any); B is TRUE.
If the record does not exist, the data at A is not
changed. L' is absent and B is false.

REC-CNT ( --- N )
Returns number of records in the current virtual file.
This may be used to add a record to the end of the file,
like this:
adr len REC-CNT INSERT drop

RECBLIP ( --- MASK ) =


A mask for the "delete" blip. See ANDBLIP for details.

REFRESH ( --- ) C
Used internally to manage the LCD display. Not normally
used by applications.
(Checks contents of LCD display buffer; ensures that all
characters that are marked "flash on" in the control
vow buffer are, in fact, flashing.)

(c) 1981 Friends Amis, Inc. 10-77 29 October 81


GLOSSARY

(Use this word if you have updated CHARBUF directly, and


want the LCD to show its current contents.)

REPEAT ( ) CTRL ,NOTE


Ends a BEGIN loop in a colon definition. Used in the torm:
BEGIN ... WHILE ... REPEAT
BEGIN ... WHILE .— REPEAT loops until WHILE finds a 0 on
the stack. Then it passes control to the next word after
REPEAT.
(At compile time, the format is "Al N1 A2 N2 ---". A2 is
the address of the area reserved by WHILE for a OBRANCH
offset; REPEAT computes the offset and stores it in the
reserved area. Al is the address of the code following
BEGIN; REPEAT compiles a BRANCH with an offset to that
code. N1 and N2 are used for error checking.)

REST.KEY ( )
(Restores variables indicating status of keyboard from
values saved on the return stack. See SAVE.KEY.)

RESTORE ( )
Restores a word in memory, stored by SAVE. Note, does not
leave the address on the stack. See SAVE.

RESTORE .RAM ( )
(Switches the current RAM bank into the address space.
Used by the I/O key to restore the current RAM bank atter
switching in each available bank while displaying the I/O
menu.)

RESTORE .TASK ( )
Restores variables indicating HHC status that are saved by
SAVE.TASK. See SAVE.TASK.

REVISE (AN B)
Adds or deletes space within non-text virtual files. (Also
used internally by the file system to insert and delete
records in text files.)

If N>0, creates an open space N bytes long at A by taking


all the data between A and the end of the last virtual
file, and moving it N bytes up.
If N<O, "deletes" a space ABS(N) bytes long at A by taking
all the data between A+ABS(N) and the end of the last
virtual file, and moving it ABS(N) bytes down.

(c) 1981 Friends Amis, Inc. 10-78 29 October 81


GLOSSARY

RIP ( ECBADR LUN B )


Initiate a read operation on the device identified by
logical unit number LUN, using an ECB at ECBADR. B
indicates success or failure of the operation.
A successful RIP must be followed (eventually) by a WAIT
and a test for successful conclusion of the operation.
The ECB must be 2 bytes long. On return from a successful
WAIT, the second byte contains the character that has been
read.

ROLL ( Xy ... X3 X2 X1 y ... X3 X2 X1 Xy ) C


Moves y'th entry on stack to the top.
'3 ROLL' is equivalent to 'ROT'.

ROLLBIT ( --- FL )
(A flag in FLAG1 used by the keyboard decoding routine to
support keyboard rollover.)

ROMADDR ( A )
Stacks the location at which ROM capsules begin in the HHC
address space. Used in a capsule header like this
ROMADDR SETORG

to tell the SNAP compiler that the capsule begins at that


address.

ROMEXFLAG ( --- FL )
A flag in the PCA byte 0. 1 -> this PCA represents a ROM
extender.

ROME XT ( A ) K1
The location in a ROM capsule header which contains the
number (2 through 7) of the capsule's primary long tag
table. See ROMVECT for more information.

ROMID ( A ) K1
The location in a ROM capsule header where a string
containing the ROM capsule's name should begin. Used like
this•
ROMID TO DP-V
to store that address into the virtual dictionary pointer

(c) 1981 Friends Amis, Inc. 10-79 29 October 81


GLOSSARY

before compiling the string.

ROMVECT ( A ) K2
The location in the header of a ROM capsule which contains
the address of the capsule's primary long tag table. When
the HHC executes the program in the capsule, it stores
this address in the proper entry of the tag table vector.
The proper entry is the one indicated by ROMEXT.

ROP ( ECBADR LUN B )


Initiate a write operation on the device identified by
logical unit number LUN, using an ECB at ECBADR. B
indicates success or failure of the operation.
The ECB must be 2 bytes long. The second byte holds the
character to be written.
A successful ROP must be followed by a WAIT and a test for
successful completion of the write operation.

ROPEN ( ECBADR LUN B )


Initiate an "open" operation on the device identified by
logical unit number LUN, using an ECB at ECBADR. B
indicates success or failure of the operation.
A successful ROPEN must be followed by a WAIT and a test
for successful completion of the operation.
Not normally needed by applications, since the first RIP,
ROP, or RCTL forces an ROPEN on the file.

ROT (XY YZX)


Moves 3rd entry on stack to top.

RP! ( )
Empties the return stack.

RP @ ( A)
Stacks the current value of the return stack pointer,
i.e., the address of the current tip entry on the return
stack. May be used with caution to fetch data from the
return stack.

RSTK ( A )
(Address of the base of the return stack.)

RUNBIT ( --- FL )

(c) 1981 Friends Amis, Inc, 10-80 29 October 81


GLOSSARY

A bit in FLAG2 which controls the STP/SPD delay for


rotation and carriage returns. 1 -> the delay is performed
normally. 0 -> the delay is disabled; CR's and rotation
occur immediately.

RUNBLIP ( --- MASK )


A mask for the "modem carrier detect" bit. See ANDBLIP for
details.

(c) 1981 Friends Amis, Inc. 10-81 29 October 81


GLOSSARY

S" ( ) I,NOTE
Begins the definition of a count format string constant
(i.e., a constant consisting of a one-byte length field
followed by an ASCII value). Used like this:
S" TEXT OF THE MESSAGE"
The value of the constant begins with the first character
after S" and one blank. It is terminated by the next "
character in the input stream.
Used outside a colon definition, S" simply deposits a
string value in the target address space. To get the
address of the string (at compile time), stack HERE before
defining the string. Here is an example which defines a
table consisting of 3 strings, terminated by a null
string, with the label C-TABLE representing the target
address of the first string:
HERE
S" FIRST STRING"
5" SECOND STRING"
S" THIRD STRING"
"
== C-TABLE
To define a single string constant, the word STRING" is
preferred.
Used inside a colon definition, S" defines a string value,
and also generates code to branch around the value and
stack its address. Use S" in this way only when you have a
good reason to do so. It is generally better practice to
define a separate, labelled string constant and refer to
it by name, since the same value can then be used in more
than once place.
NOTE: a bug in the current version of the development
system causes multiple blanks in a file to be compressed
to single blanks, even when they appear in an S" value. As
a result, values containing multiple blanks, or a single
leading blank, will be stored incorrectly. (A single
leading blank will be combined with the preceding blank
that delimits S", and so will disappear.)
NOTE: a bug in the current version of the development
system makes it impossible to represent a null string
value with 'S" If you try to do so, the compiler will
ignore the second and begin looking for the string
delimiter with the first following character (presumably
another blank). This can make a large section of a program
fail to compile for no apparent reason.

(c) 1981 Friends Amis, Inc. 10-82 29 October 81


GLOSSARY

S+ (ALN A' L' )


Returns the address and length of a substring extending
from a specified character in a string to the end of the
string.
A and L are the address and length of the string. N is the
origin-0 number of the character where the substring
starts (0<=N<L).
A' and L' are the address and length of the substring
extending from character #N of the string to the end of
the string.

S.T ( )
Shows a date and time in the format used by the clock
controller's "time" function. Does not update the time.
Before executing S.T, you must store the time you wish to
display in the 39th and 40th words of &LBUF. The time
should be time of century in seconds. For example, to
display the current time:
GET. GMT DROP &LBUF 39 + 2! S.T

S= ( Al Ll A2 L2 --- B )
Compares the string defined by Al/Li to the string defined
by A2/L2. B is TRUE iff the two strings are equal.

S>D ( N --- ND )
N is converted to a double integer.

SAVE ( A --- )
Saves address A and the contents of the word at address A
on the temporary stack. The contents of the word may be
restored to memory by RESTORE.

SAVE.KEY ( )
(Saves variables indicating status of keyboard on the
return stack. See REST.KEY.)

SAVE .TASK ( )
(Saves the a number of variables that determine attributes
of the HHC's status.
(Saved variables include (ROTMODE) and (FREEZE); 'KEY and
'EMIT; characters displayed on the LCD (but not their
display attributes, e.g., reverse image); cursor position;

(c) 1981 Friends Amis, Inc. 10-83 29 October 81


GLOSSARY

and the capsule ROM's bank ID.


(Used the preserve the HHC's status by the I/O key
routine. Variables are restored by RESTORE.KEY.)

SCROLL ( )
Used internally to manage LCD display. Not normally used
by applications.
(Rotates the LCD display left by 1 character. Matching dot
columns at the right end of the display are cleared. The
display output pointer, BUFPOSN, is shifted left with the
display.)

SCROLR )
Used internally to manage LCD display. Not normally used
by applications.
(Same as SCROLL, but scrolls right.)

SD* ( ND1 N ND2 )


ND2 = ND1 * N.

SDT ( A)
Stacks the address of the system device table (SDT). The
SDT contains one one-byte entry per logical unit number
(LUN), stored in LUN order.
Each entry is the displacement from the beginning of the
hardware device table (HDT) area to the HDT for the device
connected to this LUN. A value of 0 indicates the
keyboard; 6 represents the LCD; OCH, 12H, 18H, ...
represent peripherals; OFFH represents an unattached LUN.

SECS N )
Puts the HHC to sleep for N seconds.

SET-BLIPS ( )
(An internal word used by EXPECT to refresh the INSERT and
DELETE blips.)

SET.BITS ( A X --- )
Changes the value of the word at A by turning on each bit
that corresponds to a bit that is on in X. See also TOGGLE
and CLR.BITS.

SET.CONSTANT N DEF

(c) 1981 Friends Amis, Inc. 10-84 29 October 81


GLOSSARY

A defining word used to notify the cross-compiler that a


certain word stacks the constant value N, and should be
compiled from references to that constant.
SET.CONSTANT lets you make your code more compact by
taking advantage of tags which stack constant values
instead of compiling longer references to CLIT or LIT.
For example, suppose you defined the following word:
: 2-10 1024 ;
Later you could notify the compiler that the word '2-10'
stacks the constant value 1024 by executing the following
code:
1024 SET.CONSTANT 2-10
Then, whenever the cross-compiler encountered the constant
value 1024, it would compile the tag for '2 -10' (one or
two bytes, depending on whether the tag was short or long)
instead of the tag for LIT (one byte) plus the constant
value 1024 (two bytes).
An alternative way to achieve the same result is to define
a colon definition with the same name as the constant it
replaces:
: 1024 1024 ;
This alternative has the advantage of simplicity, but it
has two disadvantages. First, it prevents you from giving
the constant a mnemonic name. Second, it prevents you from
changing the value of the constant, once it is defined,
except by the extremely dirty means of defining a word
like 1024 that stacks some value other than the one it
appears to represent.
See also CONSTANT and 1 =='.

SET.CROM ( DEVCODE --- B ) C


(Switches the control ROM for the peripheral with
(hardware or software) device code DEVCODE into the
peripheral control ROM address space. B indicates whether
such a control ROM was available or not. DEVCODE may be
either a hardware or software device code.)

SET. DELAY ( TICKS ECBADR --- )


Set expiration time in a timer ECB, and queue the ECB.
TICKS is an unsigned integer giving delay in clock ticks.
The maximum delay allowed is 65,535 ticks, or about 4
minutes, 16 seconds.

(c) 1981 Friends Amis, Inc. 10-85 29 October 81


GLOSSARY

SET.DELAY.LONG ( TICKS SEC ECBADR )


Set expiration time in a timer ECB, and queue the ECB.
DSEC is an unsigned DOUBLE integer giving delay in
seconds. TICKS is an unsigned integer giving additional
delay in clock ticks; it must be in the range 0-255.

SET.FLSH ( )
Causes any following EMIT with zero in the character
parameter's high byte to display a flashing character. SEE
ALSO UNSET.INV and SET.INV.

SET.INV
Causes any following EMIT with zero in the character
parameter's high byte to display a character in inverse
image form. SEE ALSO UNSET.INV and SET.FLSH.

SET.RAM ( N --- TYPE ) C


Used by capsule controller in nucleus. Not ordinarily used
by application programs.
(Bank-switches memory bank N into the extrinsic RAM space.
TYPE is an integer indicating what type of memory bank N
was found to contain.
(If TYPE=0, bank N was empty or nonfunctional, or
contained ROM. The bank-switching did not take place.
(If TYPE=2, bank N contains RAM, and was bank-switched
into the RAM capsule space (beginning at 8000H).
(The usual method of using SET.RAM is to test every memory
bank in turn for the desired type of memory. Since it is a
firm rule that any RAM capsule may be plugged into any
socket, you must test every bank (#1 to OFFH) Until you
find the capsule you want. At present only the first few
bank numbers are used, but others may be used in the
future.)

SET .ROM ( N --- TYPE ) C


Used by capsule controller in nucleus. Not ordinarily used
by application programs.
(Similar in function to SET.RAM, but bank-switches memory
bank N into the ROM capsule space.
(If TYPE=0, bank N was empty or nonfunctional, or
contained RAM. The bank-switching did not take place.
(If TYPE=1, bank N contains ROM, and was bank-switched
into the ROM capsule space (beginning at 4000H.

(c) 1981 Friends Amis, Inc. 10-86 29 October 81


GLOSSARY

(Note that when you want to bank switch in a ROM capsule,


you generally are looking for a particular capsule. Thus,
you must test the contents of the ROM after switching it
in, to see if it is the right one. If not, keep
searching!)

SET.RP ( -- ) C
(Empties the return stack.)

SET.SP ( X --- ) C
Sets the parameter stack pointer to the address indicated
by the low-order byte of X (relative to the start of page
1). This may be used WITH CAUTION to empty the stack to a
predetermined level, regardless of how many entries have
since been pushed onto it.
To get a value of X, use SP@. For example, in the
following piece of code:
SP@ SDEPTH 1
.
.
.
SDEPTH @ SET.SP
SET.SP@ sets the stack to the depth that it had immed-
iately before SP@ was executed.
CAUTION: if SET.SP moves the stack pointer AWAY from the
root of the stack, effectively adding entries to the
stack, the added entries will be meaningless.

SET.TIMER ( ECBADR --- )


Queue a timer ECB. The ECB contains the time at which the
ECB should be posted, measured in clock ticks from the
beginning of 1 January 1980.

SETBANKS ( X --- )
The two bytes of X are interpreted as bank ID's. The high-
order byte is used to switch a ROM bank into the ROM
capsule address space. The low-order byte is used to
switch a RAM bank into the extrinsic RAM address space.

SETORG ( A --- ) COMP


Instructs the compiler that following code is to be
compiled starting at address A in the target address
space. See ROMADDR.

(c) 1981 Friends Amis, Inc. 10-87 29 October 81


GLOSSARY

SHFTBLIP ( --- MASK )


A mask for the "shift" blip. See ANDBLIP for details.

SHIFT ( X N --- X' )


Shifts X left by N positions. A negative N causes a shift
right.

SHIFT? ( --- FL )
(A bit in FLAG1. 1 -> we're in SHIFT or 2nd SFT mode; 0 ->
we're not. If SHIFT? is TRUE, WHICH? tells which mode
we're in.
See also WHICH? and LOCKED?

SHINT ( N)
A symbol giving the number of the first short tag that is
free for use in the short extrinsic tag table. Used with
TAG.TABLE to set up a ROM capsule header that contains a
short extrinsic tag table.

SHORT ( ) COMP
Informs the compiler that a word, to be defined later, is
to be assigned a short tag. The compiler reserves the next
available entry in the short tag table for the specified
word at the time when SHORT is processed.

Here is an example of SHORT being used to reserve a short


tag for a word named ORDER.COOK:
SHORT ORDER.COOK

SHORT.TAGS ( ) COMP
Causes the cross-compiler to begin using short tags to
compile definitions (assuming space for short tags remains
in the current tag table). This is the cross-compiler's
initial mode of operation.

SHOW.TIME ( ) NOTE
Shows the current time in the format used by the clock
controller's "time" function; updates the time each
second.

Uses &LBUF, the buffer provided for EXPECT, as a work


area.
NOTE: to leave this word, you must do a soft clear.

SIGN (ND D)

(c) 1981 Friends Amis, Inc. 10-88 29 October 81


GLOSSARY

Used in conjunction with <# # #> to convert an integer's


sign to ASCII form.
N is a sign indicator. If N is negative, SIGN puts a '-'
before the ASCII number in the text output buffer. If N is
non-negative, SIGN puts nothing in the buffer.
See the description of '<#' for examples of SIGN in use.

SIZERAM ( N) C
(Used by the CLEAR key to determine the size of a RAM.)

SL ( A) V1
"Stack limit." The displacement from the beginning of page
1 to the first word below the limit of the parameter
stack. (Recall that the parameter stack grows down from
the top of page 1.)
In base 16,
SL C@ 100 + 2+

gives the address of the lowest word where a parameter


stack entry may be stored.
Note that the value of SL may change if peripherals
allocate work space from the bottom of the parameter stack
area with GETMEM. (This does not happen at present, but
may happen in the future.)

SLPFLG ( A) V1
(A byte used to control "sleep," i.e., the turning off of
the CPU.)

SMART-POSN ( N )
Moves the LCD cursor to character position N. SMART-POSN
functions by EMITing a string of <-'s or ->'s.

SNAP-FILE ( )
(Implements the "run SNAP programs" option from the
primary menu.)

SOFT.CLR
Performs a soft clear, as though the user had pressed the
CLEAR key once.

SOFT. EMIT ( C )
Same function as EMIT, but treats all control characters

(c) 1981 Friends Amis, Inc. 10-89 29 October 81


GLOSSARY

(including the cursor control codes beginning at 80H, and


escape control sequences beginning with 1BH) as display-
able characters. For example, 81H (normally a non-
destructive backspace) is displayed as '<-'; 1BH (normally
"escape") as an inverse image IP; ODH (normally "carriage
return") as an inverse video 'M'.

SOFTAG ) V2
The tag that was executed when the current application was
entered. Set by FLEE.
This tag will be re-executed if the application is re-
started by a soft clear.
SOFTAG may be changed directly, or by another FLEE.
See also SOFTROM, SOFTCTL, and SOFTVECT.

SOFTCTL ( A ) V1
Bank ID of the peripheral control ROM that was selected
when the current application was entered. Set by FLEE.
This control ROM will be re-selected if the application is
restarted by a soft clear.
SOFTCTL may be changed directly by the application
program.
See also SOFTROM, SOFTVECT, and SOFTAG.

SOFTFLAG ( A ) V1
A location whose contents determines whether the next
clear will be a soft clear or a hard clear.
If the contents of SOFTFLAG is 5AH, the next clear will be
hard. If the contents of SOFTFLAG is anything else, the
next clear will be soft.
A soft clear set SOFTFLAG to 5AH; any other keystroke sets
it to 0.
An application can prevent hard clears from taking place
by resetting SOFTFLAG as soon as the restart word indicat-
ed by SOFTAG is executed. (CAUTION: this violates the
HHC's customary user interface design, and forces the user
to take drastic steps, such as unplugging a program
capsule, if the program malfunctions or he forgets how to
use it.)

SOFTROM V1
Bank ID of the capsule ROM that was selected when the

(c) 1981 Friends Amis, Inc. 10-90 29 October 81


GLOSSARY

current application was entered. Set by FLEE.


IMP

This capsule ROM will be re-selected if the application is


restarted by a soft clear.
SOFTROM may be changed directly by the application
program.
See also SOFTCTL, SOFTVECT, and SOFTAG.

SP@ ( A ) C
Returns the address of the tip of the parameter stack,
i.e., of the lowest entry on the stack.

SPACE ( )
Displays a space on the current output device (normally
the LCD).

SPACES (N )
Displays N spaces on the current output device (normally
the LCD).

SPEED ( A) VI
mow A number that controls speed of EMIT, CR, menu rotation,
etc.
The value of SPEED is set by the STOP/SPEED key like this:
value STOP/SPEED setting
10 1 (slowest setting)
9 2

2 9 (second fastest setting)


1 0 (fastest setting)
0 faster than fastest STOP/SPEED setting

SPINIT ( A)
Stacks the address of the root of the parameter stack. To
empty the stack, execute the following code:
SPINIT SET.SP

SQUEAK ( PITCH TIME --- )


Squeaks at pitch PITCH for time TIME through the speaker.
PITCH is an integer from 0 to 36. 1 gives the lowest note
and 36 gives the highest note; 0 gives the sound of

(c) 1981 Friends Amis, Inc. 10-91 29 October 81


GLOSSARY

silence. 32 is approximately middle C; a difference of 1


is approximately one semitone.
TIME is an integer; the time unit is about 5.88 msec.
There are 10,200 counts/minute, of 170 counts/second.

START.CURSOR ( )
Enables flashing cursor (makes it visible).

STKBIT ( --- FL )
(A bit in FLAG1 that indicates HHC status is on the return
stack.)

STM ( )
Performs the entire "set time" function of the clock
controller. It returns control to its caller when the user
presses ENTER (if he wants to set the time) or gives up
control to a soft clear (if he wants to escape from the
word without setting the time).
Application programs may call this word to let the user
set the HHC's clock without going to the clock controller.

STOP.CURSOR ( )
Disables flashing cursor (makes it invisible).

STRING (N ) DEF
Used in a TSA to reserve storage for a string.
The word reserves N bytes. By convention, this is space
for a string up to N-1 bytes long, preceded by a count
byte containing the string's actual length. For example:
24 STRING ERRMSG
This reserves 24 bytes for a string named ERRMSG.

STRING" ( ) DEF
Defines a string constant. Input up to the next double
quote is prefixed with a length byte and moved to virtual
memory. The next word is defined to be the string's name.
For example:
STRING" PLEASE WAIT..." WAITMSG
When the string's name is referenced at run time, the
string's address (the address of the count byte) is placed
on the stack.

Cc) 1981 Friends Amis, Inc. 10-92 29 October 81


GLOSSARY

See the notes on bugs in the current version, contained in


the discussion of S".

SWAP ( X Y Y X ) C
Exchanges top 2 entries on the stack.

SWAPDROP ( X Y Y )
Drops the second entry on the stack.

(c) 1981 Friends Amis, Inc. 10-93 29 October 81


GLOSSARY

T! ( )
Initializes (empties) the temporary stack. NOTE:
application programs should NOT use this word.

T: ( ) DEF
"Target colon." When a word defined by T: appears in a
colon definition, it is executed (not compiled into the
colon definition). This is useful for defining a "compile
time macro" that compiles more than one tag, or compiles
data into a colon definition.
Here is an example of a T: from the HHC nucleus. It
defines the word GET-TYPE, which compiles to two tags: the
tag for CFILE, and the tag for 2+:
T: GET-TYPE ( --- A )
COMPILE-V CFILE COMPILE-V 2+ T;
T: is also useful for creating an "alias" for a word; that
is, for specifying that a certain word in the source
program is to be compiled to another word. Here is an
example of this sort of use:
T: NOT COMPILE 0= T;
This code makes NOT an alias for 0=. Wherever NOT appears
in the source program, the tag for 0= will be compiled
into the target.

T; ) COMP ,NOTE
Used to terminate a T: definition. See T: for details.

TO ( m A) V1
T1 ( --- A ) V1
T2 ( ___ A ) V1
T3 ( --- A ) V1
T4 ( m A) Vi
T5 ( A) V1
T6 ( m A) V1
T7 ( --- A ) V1
T8 ( m A) V1
(Work space used by low level nucleus routines to maintain
the HHC's time of century clock. Hands off!)

TABLE (N ) DEF
Used to create a word-element table in ROM. The table must
be initialized by storing data into it, for example:

(c) 1981 Friends Amis, Inc. 10-94 29 October 81


GLOSSARY

4 TABLE TRIBBLE
3 I 2 I 1 I 0 I

N is used by the compiler to check the range of constant


subscripts in references to TABLE.

TAG.TABLE ( SHINT SHORTS LINT LONGS --- ) DEF


Used in a ROM capsule header to create a tag table.
SHINT is the tag to be assigned to the first entry in the
short extrinsic tag table. You should use the symbol
'SHINT', which represents the first tag number that is
available for a short extrinsic tag.
SHORTS is the desired length, in entries, of the short
extrinsic tag table.
LINT is the tag to be assigned to the first entry in the
long extrinsic tag table. If the table is to be table #2
(as is customary for the primary long tag table in a ROM
capsule), use the value 200H.
LONGS is the desired length, in entries, of the long tag
table.
The word TAG.TABLE must be followed by a word that becomes
the name of the tag table. If you use this word later in
the program, it has the effect of making this tag table
the current long tag table, i.e., the one that the
compiler will compile long tags into. (The word will NOT
stack the address of the table.)
Here is an example of the word TAG.TABLE being used to
create a short tag table with the maximum number of
entries (SHINT through OFFH), and a long tag table, table
#2, with 80H entries, named BIGBIRD.
HEX
SHINT 100 SHINT - 200 80 TAG.TABLE BIGBIRD

TC! ( BYTE OFFSET --- )


A convenient way of setting up the parameter list for
PACKUP. Stores the byte BYTE at offset OFFSET into &LBUF.
NOTE: TC! is represented by a tag, but its name is not
available to applications through the cross-compiler's
symbol table. You can make it function like a "normal" tag
at compile time like this:
HEX
T: TC!
Al C,-V
T,

(c) 1981 Friends Amis, Inc. 10-95 29 October 81


GLOSSARY

TDKFLAG ( --- FL )
(A flag in HDT byte 0: 1 -> this HDT belongs to the LCD or
keyboard.)

THEN ( ) CTRL
A synonym for ENDIF.

THI ( A )
(High order byte of the hardware timer. See TLO, TMID.)

TIMEFLAG ( --- FL )
(A bit in FLAG2 used by the HHC nucleus to help support
timer updating.

TLO ( A )
(Low order byte of the hardware timer. See THI, TMID.)

TMID ( )
(Middle order byte of the hardware timer. See THI, TLO.)

TOGGLE ( A X --- )
Changes the value of the word at A by reversing each bit
that corresponds to a bit that is on in X. See also
SET.BITS and CLR.BITS.

TP ( A ) V2
An internal variable in the virtual file system.
(Ceiling of the last virtual file in the intrinsic virtual
file space. 'TP @' stacks the ceiling of the last virtual
file, i.e., the address of the first free byte of
intrinsic virtual file space.)
I see a conflict within my notes, which give both this
definition and "address of the tip of the temporary
stack." Which is correct, and what variable gives the
other value?

TPSAFE? ( N--- A I 0 )
Determines if there is enough space in intrinsic RAM to
allocate N bytes of storage space. If there is, A is the
address of the space; if there is not, 0 is returned.
Note that TPSAFE? does not allocate the space; it merely
returns the address at which space WILL be allocated, if

(c) 1981 Friends Amis, Inc. 10-96 29 October 81


GLOSSARY

you allocate it. To allocate space, see GRAB.

TQUEUE ( A) V12
Timer queue. Consists of 6 2-byte entries, each containing
the address of a timer ECB or 0.
Each unexpired timer ECB in the system is represented in
this queue. Whenever a timer interrupt occurs, the queue
is searched for expired ECB's; if any are found, they are
posted and removed from the queue. Each unexpired ECB is
updated to reflect the amount of time remaining until it
expires.

TRUE ( --- TRUE )


Stacks a Boolean TRUE. The numeric value of TRUE is 1.

TURN .OFF ( )
(Turns the HHC off as if the OFF key had been pressed.
Applications should not use this word; it will cause the
HHC to execute the word pointed to by 'ABORT. See 'ABORT,
ABORT.)

TVECTO ( A ) V24
Stacks the address of the first entry in the tag table
vector (the entry representing the short extrinsic tag
table).
The table consists of 8 entries: #0 for the short
extrinsic tag table, #1 for the long intrinsic tag table,
and #2 through #7 for long extrinsic tag tables. For
further details, see the discussion of tag tables in the
chapter on "General Technical Information."
Each entry in the tag table is 3 bytes long:
byte bit contents
0 80 l->tag table is in ROM, 0->in RAM.
40-01 Bank ID of memory bank containing the tag
table.
1-2 Address of the tag table.

TYPE (AL )
Displays characters from memory, starting at address A,
for length L.
Control characters may be included in the character string
to perform control functions on the TV adapter if the
No. adapter is bound to the display. These control codes have
no effect on the LCD.

(c) 1981 Friends Amis, Inc. 10-97 29 October 81


GLOSSARY

See the section on control characters for details.

TYPEDROP ( X A L )
Types the string at address A, length L, and drops X.

(c) 1981 Friends Amis, Inc. 10-98 29 October 81


GLOSSARY

U* ( Ul U2 UD )
UD = Ul * U2.

U< ( Ul U2 --- B )
Tests if Ul < U2.

UD< ( UD1 UD2 B )


Tests if UD1 < UD2.

UDMIN ( UD1 UD2 UD3 )


UD3 = the smaller of UD1 and UD2.

UM/ ( UD Ul --- U2 U3 )
U2 = unsigned remainder of UD/U1.
U3 = unsigned quotient of UD/U1.

UNCOMMITTED ( --- A ) V16


(A data area in low RAM reserved for future expansion of
the HHC nucleus. It currently is not used by any part of
the HHC system. Application programs should not use it.)

UNPACK ( DN --- SEC MIN HOUR AMPM YEAR DAY MONTH) NOTE
Given a time of century in seconds, "unpacks" it into a
date and time in standard form.
All of the results are short integers.
HOUR is the hour on a 12-hour clock.
AMPM is a boolean; it is FALSE for "AM", and "TRUE" for
PM.
YEAR is origin-1980 (i.e., 1980 is year 0, 1981 is year 1
. . . 2000 is year 20 . . . 2079 is year 99).
NOTE: UNPACK is a tagless word. It must be executed with
(CALL). To locate its entry point, add 3 to the address of
the entry point of the word represented by tag 0A1H. The
following word may be used to call UNPACK:
HEX
: UNPACK (S DN --- SEC MIN HR AMPM YR DAY MO )
\ ADR OF TAG TABLE ENTRY FOR WORD 0A1H.
IDICT OA1 + ()Al + ] LITERAL
A(ENTRY PT) FOR WORD W/TAG 0A1H.
3 + A(ENTRY PT) FOR UNPACK.

(c) 1981 Friends Amis, Inc. 10-99 29 October 81


GLOSSARY

(CALL) ; \ (CALL) IT.

UNSET.FLSH ( )
Reverses the effect of a preceding SET.FLSH, if any.

UNSET.INV ( )
Reverses the effect of a preceding SET.INV, if any.

UNTIL (N ) CTRL
Ends a BEGIN loop in a colon definition.
Occurs in a colon definition in the form
BEGIN ... UNTIL
BEGIN ... UNTIL loops until UNTIL finds a 1 on the stack.
Then it passes control to the next word after UNTIL.
(At compile time, the format is "A N ---". UNTIL compiles
(OBRANCH) and an offset from A to HERE. N is an error
checking code.)

UPDISP
Updates the LCD after the contents of the LCD character
buffer or the LCD control buffer has been modified.

USED ( A)
Stacks the address of a 2-byte area containing the number
of bytes used in the current file space.
For the number of bytes free in the current file space,
see AVAIL.

(c) 1981 Friends Amis, Inc. 10-100 29 October 81


GLOSSARY

VAR DEF
Used in a TSA to reserve one word of storage for a
variable. For example:
VAR ERRCODE
This reserves a word for a variable named ERRMSG.

VECTOR ( N--- ) DEF


Used in a TSA to reserve 2*N bytes of storage for an array
of word-length values. For example:
8 VECTOR ERRTBL

This reserves 16 bytes for an array of 8 word-length


values named ERRTBL.
At run time, the vector expects one item on the stack; it
interprets this item as an origin-0 index. For example,

7 ERRTBL
would stack the address of the 7th (and last) element of
maw the vector, ERRTBL.

(c) 1981 Friends Amis, Inc. 10-101 29 October 81


GLOSSARY

WAIT ( ECBADR --- ) C


Wait for ECB to be posted.

WAITM ( ECBADR[N-1] ... ECBADR1 ECBADRO N --- N' ) C


Multiple wait. Waits for any of the "N" ECBs to be posted.
N' is the number of the ECB whose posting ended the wait.
For example, if the value of N' is 0, that means that ECB
#0 (the first one in the WAITM request) was posted.

WHICH? ( --- FL ) .
(A flag in FLAG1. If SHIFT? is TRUE, indicating that the
HHC is in SHIFT or 2nd SFT mode, WHICH? indicates which
mode it is in: 1 -> SHIFT mode, 0 -> 2nd SFT mode.)

WHILE ( N --- ) CTRL ,NOTE


Ends iteration of a BEGIN loop in a colon definition.
Occurs in a colon definition in the form

BEGIN ... WHILE ... REPEAT


BEGIN .— WHILE .— REPEAT loops until WHILE finds a 0 on
the stack. Then it passes control to the next word after
REPEAT.
(At compile time, the format is "Al N1 --- Al N1 A2 N2 ---
"WHILE compiles a (OBRANCH) and reserves a 2-byte space
for the offset to the code after REPEAT. A2 is the address
of the space reserved; Al is the address of the code
following BEGIN. N1 and N2 are used for error checking.)
See also LONG.WHILE.

WRITE ( A L N --- B )
Replaces record #N of the current virtual file with the
data at address A, length L.
If record #N already exists, B is true. If record #N does
not already exist, the new record is NOT WRITTEN and B is
false.
To write a record where none exists, use INSERT.

(c) 1981 Friends Amis, Inc. 10-102 29 October 81


GLOSSARY

X1SAV ( A) V1
(Used by peripheral I/O routines to save the X register.)

XOR (XY Z) C
Bitwise logical exclusive OR.

XSAVE ( A) V1
A one-byte area set aside for storing the X register. A
CODE word or low level procedure may use it for any
purpose. But note that any lower level routine may destroy
its contents; if your code calls a lower level routine
that is not part of your own program, assume that XSAVE
will be destroyed by the call, even if it currently
appears to be preserved.

(c) 1981 Friends Amis, Inc. 10-103 29 October 81


GLOSSARY

YOFF ( A )
(Address of a location in the I/O page. A store into this
address causes the Y-driver to stop asserting IRQ.)

(c) 1981 Friends Amis, Inc. 10-104 29 October 81


GLOSSARY

Z ( A ) V9
(Work space in low RAM, used by IRQ processing routines.)

(c) 1981 Friends Amis, Inc. 10-105 29 October 81


GLOSSARY

Beginning With Characters After 'Z'

( --- ) I
Switches SNAP from compile mode to execute mode. This word
has two uses. One is to execute some words while
compiling. This is most commonly done to resolve the value
of an expression at compile time. For example:
HEX
80 == ALL.DONE
40 == PART.DONE
: FOOBAR ( xxxxxxxx... )
...
FLAGBYTE C@ [ ALL.DONE PART.DONE OR ] LIT AND IF
...

The code 'ALL.DONE PART.DONE OR' is executed (in the


middle of the compilation of FOOBAR). It leaves a value on
the stack which LIT stores into the dictionary as a
literal, so that the line beginning with FLAGBYTE executes
as though it read like this:
FLAGBYTE C@ CO AND IF
The second use of '[' is to return SNAP to execute mode
after compiling apiece of high level code outside a colon
definition. This is most commonly done when a code (i.e.,
assembler) definition must call a high level (i.e., SNAP)
word. The technique is explained in the chapter "General
Technical Information."

[COMPILE] ( ___ ) COMP


Used in a colon definition in the form:
: wwww xxxx... [COMPILE] word xxxx... ;
[COMPILE] forces compilation of the word immediately
following, even if that word is an IMMEDIATE word which
normally would be executed at compile time.

\ ( ___ ) I
Makes the rest of this source screen line a comment.
Example:
2DUP + 1- \ POINT TO THE LAST BYTE.
'\' must be followed by a blank. No terminating delimiter
is needed.

(c) 1981 Friends Amis, Inc. 10-106 29 October 81


GLOSSARY

( --- ) COMP
Switches SNAP from execute mode to compile mode. Used with
ip to switch SNAP from compile mode to execute mode, then
back to compile mode; or from execute mode to compile
mode, then back to execute mode. See description of 'P.

-CURSOR ( ___ A ) V2
Stacks the address of the address of the current cursor
image definition. You can define a new cursor image by
executing the following words:
YOUR-CURSOR-DEFINITION -CURSOR !
where YOUR-CURSOR-DEFINITION stacks the address of a 5-
byte cursor image definition block.
The address of the HHC's standard cursor definition is
given by CURDOTS. -CURSOR is reset to CURDOTS by a hard
clear.

-HDT ( ___ A ) V2
Address of the first HDT.

(c) 1981 Friends Amis, Inc. 10-107 29 October 81


GLOSSARY

OBJECT-TIME WORDS

(+LOOP) ( N --- ) C
Compiled from +LOOP. Increments loop index by N and tests
for loop completion.

(.") ( --- ) C
Compiled from 1 ." (dot-quote). Displays the COUNT format
string that follows (.") in the program; passes control
around the string.

(;P) (--- ) C
Compiled from ';'. Pops IP from the return stack and goes
to NEXT.

(<IF) ( N1 N2 --- ) C
Compiled from <I F. If Nl<N2, executes the following code.
If Nl>=N2, passes control around the following code to the
point representing the matching ELSE or ENDIF.

(=IF) ( N1 N2 --- ) C
Compiled from =IF. If N1=N2, executes the following code.
If Nl<>N2, passes control around the following code to the
point representing the matching ELSE or ENDIF.

(?DO) ( N1 N2 --- ) C
Compiled from ?DO.

(AGAIN) ( --- ) C
Compiled from REPEAT and AGAIN. Followed by a one-byte
unsigned displacement which is subtracted from the address
of the displacement to get the address of the correspond-
ing BEGIN.

(CASE) ( B --- ) C
Compiled from CASE. If B is TRUE, executes the following
code. If B is FALSE, branches around the following code to
the point representing the next CASE, the matching ELSE,
or the matching ENDIF.

(CALL) ( m ) C
Compiled from any reference to a colon definition that was
defined with ':C' instead of 1 :1 . Interprets the next two
bytes as an address, and "calls" the colon definition
beginning at that address.

(c) 1981 Friends Amis, Inc. 10-108 29 October 81


GLOSSARY

(DO) ( N1 N2 --- ) C
Compiled from DO. Moves loop control parameters to the
return stack.

(ELSE) C
Compiled from ELSE. Followed by a one-byte unsigned number
giving the displacement from the displacement byte to the
ENDIF.

(IF) ( B --- ) C
Compiled from IF. Followed by a one-byte unsigned number
giving the displacement from the displacement byte to the
ELSE (if any) or ENDIF.
If B is FALSE, does nothing. If B is TRUE, passes control
to the point representing the matching ELSE or ENDIF.

(IF.ITS) ( N --- N ) C
Compiled from IF.ITS. If N is equal to the constant
compiled after IF.ITS, passes control to the code
following the constant. If N is not equal to the constant,
passes control to the point representing the matching
ENDIF.
yew

(LOOP) ( --- ) C
Compiled from LOOP. Increments loop index and tests for
loop completion.

(NOTIF) ( B --- ) C
Compiled from NOTIF. Followed by a one-byte unsigned
number giving the displacement from the displacement byte
to the ELSE (if any) or ENDIF.
If B is TRUE, does nothing. If B is FALSE, passes control
to the point representing the matching ELSE or ENDIF.

(UNTIL) ( B --- ) C
Compiled from UNTIL. Followed by a one-byte unsigned
displacement. If B is TRUE, passes control back to the
corresponding BEGIN, which is at the address of the
displacement minus the value of the displacement. If B is
FALSE, passes control to the address of the displacement
+1.

<JUMP-TAB> ( N --- ) C
'`' Compiled from JUMP-TAB. Executes the N'th word in the jump
table.

(c) 1981 Friends Amis, Inc. 10-109 29 October 81


GLOSSARY

?JUMP ( B --- ) C
Compiled from LONG.IF and LONG.WHILE. Followed by a 2-byte
signed displacement.
If B is TRUE, passes control to the address of the dis-
placement plus the value of the displacement. If B is
FALSE, passes control to the address of the displacement
+2.

CLIT ( m c ) C
Compiled from a literal with a value in the range O-OFFH.
Followed by one byte giving the value of the literal. At
run time, CLIT stacks the contents of the next byte, left-
padded with a zero byte.

CLIT2 ( --- N ) C
Compiled from a literal with a value in the range 200H-
2FFH. Followed by one byte giving the value of the literal
minus 200H.

CLIT3 ( --- N ) C
Compiled from a literal with a value in the range 300H-
3FFH. Followed by one byte giving the value of the literal
minus 300H.

FLIT ( --- FP ) C
"Floating point literal." At run time, FLIT works like the
run-time words LIT (which stacks a word literal) and CLIT
(which stacks a character literal). However, the compiler
currently cannot generate it automatically from a floating
point constant.
To use FLIT to compile a floating point number, use the
following words:
FLIT [ nl ,-V n2 ,-V n3 ,-V n4 ,-V ]
where nl to n4 are the values of the four words that make
up the floating point constant, FP.

JUMP ( --- ) C
A run time support word generated by LONG.ELSE and
LONG.REPEAT. Followed by a 2-byte signed displacement.
(Transfers control to the address of the displacement plus
the value of the displacement.
(This word may also be used to patch compiled high-level

(c) 1981 Friends Amis, Inc. 10-110 29 October 81


GLOSSARY

code, although (CALL) is usually more convenient because


it returns control to the point after the patch.)

LIT ( _a_ N ) C
Compiled from a literal that cannot be compiled to a CLIT,
CLIT2, or CLIT3. Followed by two bytes giving the value of
the literal. At run time, LIT stacks the contents of the
next two bytes.

(c) 1981 Friends Amis, Inc. 10-111 29 October 81


GLOSSARY

ASSEMBLER GLOSSARY

This glossary includes all words that are customarily used in


low level code, whether or not part of the ASSEMBLER vocabulary,
except the following:

1. Opcodes.
2. SNAP compile-time words used in address calculations, such
as 2+.

"Sn" refers to the "n"th entry on the stack. For example, the
tip entry is "SO;" the next-to-tip entry is "Sl."

"NEXT" Words

These words pass control directly to NEXT when they are done
executing. Call them with a ',IMP,' instruction.

(2POP)
Pops the top 2 words off the stack.

(POP)
Pops the tip word off the stack.

(POPPUT)
Pops the tip word of the stack; replaces the second word
on the stack. The replacement value is constructed from
AC (high byte) and one byte popped off the return stack
(low byte).

(PUSH)
Pushes a word onto the stack. The word is constructed from
the contents of the accumulator (high byte) and one byte
popped off the return stack (low byte).

(PUSHOA)
Pushes a word onto the stack. The word is constructed from
a zero (high byte) and AC (low byte).

(PUT)
Replaces the tip word on the stack. The replacement value
is constructed from AC (high byte) and one byte popped off
the return stack (low byte).

(c) 1981 Friends Amis, Inc. 10-112 30 October 81


GLOSSARY

(PUTOA)
Replaces the tip word on the stack. The replacement value
is constructed from a zero (high byte) and AC (low byte).

(PUTFLS)
Replaces the tip word on the stack. The replacement value
is FALSE (zero).

(PUTTRU)
Replaces the tip word on the stack. The replacement value
is TRUE (1).

(SLEEP)
Puts the HHC to sleep the next interrupt (from the timer,
keyboard, etc.) will wake it up.

"RTS" Words

These words return to their calls with an RTS, instruction.


Call then with JSR,.

(SCOMP)
Performs a signed algebraic comparison of the two words on
the tip of the stack.
On return, the words are still on the stack, but their
signs are reversed.
On return, the CPU flags are set as follows:
tip word = 2nd word Z=1
tip word > 2nd word Z=0, C=0
tip word < 2nd word Z=O, C=1
For unsigned comparison, see (UCOMP).

(SETUP)
Pops a variable number of input values off the parameter
stack and stores them in the workarea N.

On entry to SETUP, AC should contain the number of 16-bit


values to be popped. This number may be in the range 1 to
8. SO will be popped to N, S1 to N+2, and so forth.
SETUP can be a useful procedure to call on entry to a CODE
word; for example, to pop 3 entries off the parameter

(c) 1981 Friends Amis, Inc. 10-113 30 October 81


GLOSSARY

stack into N, N+2, and N+4:


CODE WORD-WITH-3-PARAMETERS
3 # LDA, SETUP JSR,
•• •

(UCOMP)
Performs an unsigned algebraic comparison of the two words
on the tip of the stack.
On return, the words are still on the stack, and are
unchanged.
On return, the CPU flags are set as follows:
tip word = 2nd word Z=1
tip word > 2nd word Z=0, C=0
tip word < 2nd word Z=O, C=1
For signed comparison, see (SCOMP).

GETMEM
(A subroutine formerly used by peripheral controller
routines to allocate space from the bottom of the param-
eter stack area in page 1. Peripheral controller routines
now use GETMEMT to get space from the temporary stack
instead.
(On entry, AC contains the number of bytes required.
(On return, AC contains the address of the space if the
space was available, or zero if not.)

GETMEMT
A subroutine used by peripheral controller routines to
allocate space from the temporary stack.
On entry, AC contains the number of bytes required.
On return, AC contains the address of the space if the
space was available, or zero if not.
GETMEMT is intended for use by peripheral controller
routines. Application programs should allocate a TSA, or
use the high level word GRAB if a TSA is inappropriate.

POSTECB
Posts an ECB for an I/O operation.
On entry, Y contains the address of the HDT associated
with the device. AC contains the return code to post in

(c) 1981 Friends Amis, Inc. 10-114 30 October 81


GLOSSARY

bits 0.1-0.7 of the ECB.


On return, Y contains the address of the HDT +1.

Other Words

# ( ___ )
Addressing mode specifier for "immediate" mode.

) ( ___ )
Addressing mode specifier for absolute mode.

YY ( ___ )
Addressing mode specifier for "indirect indexed Y" mode.

,x
Addressing mode specifier for "indexed X" mode.

,Y
Addressing mode specifier for "indexed Y" mode.

.A
Addressing mode specifier for "accumulator" mode.

0<
Condition specifier for processor status N=1 ("byte less
than zero)."

0=
Condition specifier for processor status Z=1 ("byte equals
zero").

AGAIN,
Used in a CODE word in the form:
BEGIN, . . . AGAIN,

marks the end of a loop that will be executed


indefinitely. The only clean way to escape from this kind
of loop is to execute a NEXT JMP, (if in a CODE word) or a
RTS, (if in a low level procedure).
AGAIN, assembles to an unconditional jump back to the
,Nsow point marked by BEGIN,.

(c) 1981 Friends Amis, Inc. 10-115 30 October 81


GLOSSARY

ASSEMBLER
Name of the ASSEMBLER vocabulary. Using this word makes
ASSEMBLER the context vocabulary.
Use ASSEMBLER to begin assembling code without making an
entry in the tag table, i.e., to assemble a low level
procedure which CODE words can call with a JSR,.

BEGIN,
Used in a CODE word in the form:

BEGIN, . . . cc UNTIL,
or
BEGIN, . . . cc WHILE, . . . REPEAT,
or
BEGIN, . . . AGAIN,
marks the beginning of a loop that will be executed
iteratively (a) until condition specifier "cc" before
UNTIL, is satisfied, (b) until the condition specifier
"cc" before WHILE, is not satisfied, or (c) indefinitely,
if AGAIN, is used.
BEGIN, does not assemble any machine instructions; its
sole function is to mark the target of a jump from UNTIL,
REPEAT, or AGAIN,.

CODE
A defining word used in the form:
CODE <name> . . . ENDCODE
Creates a tag table entry for <name> and makes the
ASSEMBLER vocabulary the context vocabulary.

CS
Condition specifier for processor status C=1 ("test carry
set").

ELSE,
Used in a CODE word in the form:
cc IF, . . . ELSE, . . . ENDIF,
marks the end of a section of code to be executed if
condition specifier "cc" is satisfied, and the beginning
of a section of code to be executed if "cc" is not
satisfied."
ELSE, assembles to an unconditional jump to the code

(c) 1981 Friends Amis, Inc. 10-116 30 October 81


GLOSSARY

following ENDIF,.
110111.-

ENDCODE
Ends a CODE definition (begun by the word CODE), just as
';' ends a colon definition (begun by th word 1 :1 ).
Performs error checking to make sure that all conditionals
are properly paired and that the stack is the same depth
as when the CODE word began; resets the context vocabulary
to be the same as the current vocabulary.

ENDIF,
Used in a CODE word in the form:
cc IF, . . . ELSE, . . . ENDIF, or
cc IF, . . . ENDIF,
marks the end of a conditional-execution section of code.
In the first case, the code between IF, and ELSE, is
executed if condition specifier "cc" is satisfied, and the
code between ELSE, and ENDIF, is executed if not. In the
second case, the code between IF, and ENDIF, is executed
if "cc" is satisfied, and no code is executed if not.
ENDIF, does not assemble to any code; its function is to
mark the target for an unconditional jump from ELSE,.

IF,
Used in a CODE word in the form:
cc IF, . . . ELSE, . . . ENDIF, or
cc IF, . . . ENDIF,
marks the beginning of a section of code to be executed if
condition specifier "cc" is satisfied.
IF, assembles to a conditional jump instruction to the
code after ELSE, or ENDIF,; the condition used depends on
the preceding "cc."

IP
Stacks the address of a two-byte area in low RAM which
contains the address of the lowest level colon definition
tag currently being executed.

LABEL
Defines a "label" whose value is the current value of the
dictionary pointer. It is used like this:
Nimp. LABEL symbol

(c) 1981 Friends Amis, Inc. 10-117 30 October 81


GLOSSARY

This defines a word named "symbol" which will push the


label's value onto the stack.
LABEL may be used to mark the beginning of a table or
other area in ROM whose address may be needed at run time.
For example, this code:
LABEL X.CTRL.TABLE
04 C, 18 C, FF C, C2 C, ...
defines a byte-element table with entries 04,18,FF,C2,...

'LABEL symbol' is equivalent to 'HERE-V == symbol'. == is


customarily used for a symbol that will be used by high
level code; LABEL is customarily used for a symbol that
will be used by low level code.

N
Stacks the address of a 20-byte area which a CODE word or
low level procedure may use for any purpose. Its customary
use is to hold parameters popped off the stack. See
(SETUP).
A procedure may not safely assume that N will be preserved
across any call to a lower-level routine.

NEXT
A label representing a JMP, to the entry point of the SNAP
inner interpreter. A CODE word must return control to SNAP
by jumping to NEXT:
NEXT JMP,

NOT
Reverses the condition specified by the preceding
condition specifier. May be applied to any condition
specifier. For example,
0= IF, N STA, ENDIF,
executes the STA, if the "equal to zero" condition is
satisfied;
0= NOT IF, N STA, ENDIF,
executes the STA, if the "equal to zero" condition is NOT
satisfied.

REPEAT,
Used in a CODE word in the form:

(c) 1981 Friends Amis, Inc. 10-118 30 October 81


GLOSSARY

BEGIN, . . . cc WHILE, . . . REPEAT,


marks the end of a loop that will be executed iteratively
until condition specifier "cc" fails to be satisfied.
REPEAT, assembles to an unconditional jump back to the
point marked by BEGIN,.

SEC
Same as TOP, but addresses the second (next-to-tip) entry
on the parameter stack. See TOP.

TOP
Addresses the low byte of the tip entry of the parameter
stack by stacking a zero address and setting the
addressing mode to "indexed indirect X." (By convention, X
points to the tip entry of the parameter stack.) For
example,
TOP LDA,
is equivalent to
0 X) LDA,
mip, and loads the low byte of the tip entry into AC.

TOPDEC
Subtracts 1 from the signed value of SO. Returns to
caller.

TOPINC
Adds 1 to the signed value of SO. Returns to caller.

UCOMP
Compares SO and S1 as unsigned numbers. The result is
turned in the Z and C flags. The meanings of the flags are
the same as for SCOMP.
Returns to caller.

UNTIL,
Used in a CODE word in the form:
BEGIN, . . . cc UNTIL,
marks the end of a loop that will be executed iteratively
until condition specifier "cc" is satisfied.

(c) 1981 Friends Amis, Inc. 10-119 30 October 81


GLOSSARY

UNTIL, assembles to a conditional jump back to the point


marked by BEGIN,; the condition used depends on "cc."

WHILE,
Used in a CODE word in the form:
BEGIN, . . . cc WHILE, . . . REPEAT,
marks the termination test in a loop that will be executed
iteratively until condition specifier "cc" fails to be
satisfied.
WHILE, assembles to a conditional jump to the point marked
by REPEAT,; the condition used depends on "cc."

X)
Addressing mode specifier for "indexed indirect X" mode.

XSAVE
A one-byte area set aside for storing the X register. A
CODE word or low level procedure may use it for any
purpose. But note that any lower level routine may destroy
its contents; if your code calls a lower level routine
that is not part of your own program, assume that XSAVE
will be destroyed by the call, even if it currently
appears to be preserved.

(c) 1981 Friends Amis, Inc. 10-120 30 October 81


APPENDIX A: THE HHC ASCII CHARACTER SET

This table lists control characters, binary values 0 through


1FH.
lamp
The meanings of the columns in the table are:

* VALUE: the binary value that represents this character.


* NOTES: 'I' indicates an immediate key. 'H' indicates a hidden
key.
* HHC NAME: the name used to identify this character in the HHC
system.
* ASCII NAME: the name or desciiption used to identify this
character in "pure" ASCII.
* HHC KEY: key on the HHC keyboard that inputs this character.
* HHC GRAPHIC: the graphic symbol that represents this character
when the character is displayed on the LCD. For characters
that have a control function, you must use the "ESCDC" escape
control sequence to display the character.
* LCD ACTION: control function performed by this character when
it is sent to the LCD. If this column is empty, the character
has no control function; it displays the graphic symbol listed
under "HHC graphic."

(c) 1981 Friends Amis, Inc. A-1 3 September 81


APPENDIX A: THE HHC ASCII CHARACTER SET

HHC ASCII
value notes name name

0 NUL, Null
1 SOH, Start of heading
2 STX, Start of text
3 ETX, End of text
4 EOT, End of transmission
5 ENQ, Enquiry
6 ACK, Acknowledge
7 Rotate; Bell BEL, Bell

8 Backspace BS, Backspace


9 HT, Horizontal tab
A Line feed LF, Line feed
B IH I/O VT, Vertical tab

C Form feed FF, Form feed


D Enter CR, Carriage return
E IH Stop/Speed SO, Shift out
F SI, Shift in
10 DLE, Data link escape
11 DC1, Device control 1
12 DC2, Device control 2
13 DC3, Device control 3
14 IH Help DC4, Device control 4
15 Fl NAK, Negative acknowledge
16 F2 SYN, Synchronous isle
17 F3 ETB, End of transmission block
18 CAN, Cancel
19 EM, End of medium
lA SUB, Substitute
1B Escape ESC, Escape

1C FS, File separator


1D GS, Group separator
lE RS, Record separator
1F US, Unit separator

(c) 1981 Friends Amis, Inc. A-2 3 September 81


APPENDIX A: THE HHC ASCII CHARACTER SET

numeric HHC HHC LCD


value key graphic action

0 inverse-image @
1 inverse-image A
2 inverse-image B
3 inverse-image C
4 inverse-image D
5 inverse-image E
6 inverse-image F
7 Rotate inverse-image G "beep"
8 inverse-image H Backspace cursor; erase character
under cursor after backspace.
9 inverse-image I
10 inverse-image J
11 I/O inverse-image K
12 inverse-image L
13 Enter inverse-image M Erase LCD; move cursor to left edge.
14 Stop/Speedl inverse-image N
15 inverse-image 0
16 inverse-image P
17 inverse-image Q
18 inverse-image R
19 inverse-image S
20 Help inverse-image T
21 F11- inverse-image U
22 F21 inverse-image V
23 F31 inverse-image w
24 inverse-image X
25 inverse-image Y
26 inverse-image Z
27 inverse-image [ Begins an escape control sequence.
28 inverse-image
29 inverse-image 1
30 inverse-image
31 inverse-image

(c) 1981 Friends Amis, Inc. A-3 3 September 81


APPENDIX A: THE HHC ASCII CHARACTER SET

Displayable Characters

The HHC's use of characters 20H through 7EH conforms exactly


to the ASCII standard.

HHC keybd
value character name

20 space
21 exclamation mark
22 quotation mark
23 pound sign

24 $ dollar sign
25 % percent sign
26 & ampersand
27 i apostrophe

28 ( left parenthesis
29 ) right parenthesis
2A * asterisk, star, or "times" sign
2B + plus sign

2C , comma
2D - hyphen, dash, or minus sign
2E . period
2F / slash

30 0
31 1
32 2
33 3

34 4
35 5
36 6
37 7

38
39 9
3A • colon
33 • semicolon

3C < left angle bracket or "less than" sign


3D = equal sign
3E > right angle bracket or "greater than" sign
3F ? question mark
rQ
40
41 A
42
43

(c) 1981 Friends Amis, Inc. A-4 3 September 81


APPENDIX A: THE HHC ASCII CHARACTER SET

44 D
45 E
46 F
47 G

48 H
49 I
4A J
4B K

4C L
4D M
4E N
4F 0

50 P
51 Q
52 R
53 S

54 T
55 U
56 V
57 w

58 X
59 Y
5A Z
5B [ left bracket

SC \ backslash
5D j right bracket
SE caret
SF underscore
.
60 grave
61 a
62 b
63 c

64 d
65 e
-
66 f
67 g

68 h
69 i
6A j
6B k

6C 1
6D m
6E n
OF o

(c) 1981 Friends Amis, Inc. A-5 3 September 81


APPENDIX A: THE HHC ASCII CHARACTER SET

70 p
71 g
72 r
73 s
74 t
75 u
76 v
77 w
78 x
79 y
7A z
7B t left brace

7C 1 vertical bar
70 } right brace
7E tilde

(c) 1981 Friends Amis, Inc. A-6 3 September 81


APPENDIX A: THE HHC ASCII CHARACTER SET

Additional Characters

The HHC uses characters from 07FH up as displayable characters


and control characters.

In "pure" ASCII, character 07FH represents the control


character "delete." Characters above 07FH are undefined.

HHC HHC HHC LCD


value note name key graphic action
----- .10WO ..IM ---

7F "insert"
cursor
80 up arrow I T
81 left 4 4 Backspaces cursor; does not
arrow disturb character under cursor
after move.
82 right * Advances cursor; does not
arrow disturb character that was
under cursor before move.
83 down 17 t
arrow
34 "AM" INSERT a
m
symbol
85 "PM" DELETE o
rn
symbol

36 H super- LOCK M
script M
87 division
sign
88 "times" x
sign
89 block SEARCH 1
cursor

8A H "delete" CASE 117


cursor SHIFT

8B "a" with Cl a
umlaut

(c) 1981 Friends Amis, Inc. A-7 3 September 81


APPENDIX A: THE MC ASCII CHARACTER SET

8C "o" with C2
umlaut

8D "u" with C3
umlaut

8E "n" with C4 n
tilde

8F H second
shift

90-92 are undefined.


93-9C represent specia'l symbols designed by Matsushita for use with the
Katakana character set.
9D-DF represent standard Katakana characters.

EO-FF are undefined.

(c) 1981 Friends Amis, Inc. A-8 3 September 81


INDEX

'EMIT
Vectored I/O and, 4-13
(EMIT) , 4-13
(ROTMODE) , 4-11
:C definition, 2-19
?KEY, 3-14
?LOCK, 3-5
?ROOM, 2-26

Addressing mode, assembler, 9-8


Alternate character pattern for cursor, 4-9
Alternate character set for LCD, 4-6
Applies to printer, 4-9
AREA (TSA word), 2-22
ASCII, 3-4
Character set, A-4
DELETE character, A-7
ASCII character set, A-1
ASSEMBLER vocaoulary, 9-4, 9-5
Asynchronous I/O, 6-5
Asynchronous processing, 6-1
ATTACH, 6-7
POKE and, 6-12
Auto-off facility, 6-34
AVAIL, 2-26

B
Bank switching, 2-17, 10-70, 10-71
Programmable Memory Peripheral, 3-11
Tag table vector controls, 2-16
BASIC file type, 5-8
Battery
Conserving, 3-14
Beep, 4-16
BIND, 4-9
Blips, 4-15
Last 3 columns of LCD, 4-5
BREAK instruction, 2-8
C
C1/C2/C3/C4 keys, 3-4
Capsule
Memory map, 2-1
Character
Displayable character set, A-4
Numeric representation, 2-4
Character control buffer, 4-3
Character display buffer, 4-3
Character translation table, 3-6
LCD, 4-6

(c) 1981 Friends Antis, Inc. index-1 3 September 81


INDEX

CLEAR, 10-25
&APS destroyed by, 10-3
Does not reset rotation mode, 4-11
Hard, 2-30, 2-31, 10-49
Soft, 2-30, 2-31, 10-72
CLEAR key, 2-30, 2-31, 3-3, 5-10, 6-7
Restarting an application, 2-30
CLEAR stack, 2-30
Clock, 6-33
Clock tick, 6-33
CODE
Definition, 9-4
Word, 9-4
Code structure of SNAP, 2-5
CODE word, 9-2
Complex number, 7-2
Condition specifier, 9-10
Constant, 2-20
Control byte
Peripheral, 6-10
Control characters
Peripheral, 6-16
Control key, 3-1
Cross-compiler, 1-10, 1-13
CSLOW, 2-17
CSPEED, 2-11, 2-17
Current file, 5-3
Cursor
Alternate character pattern, 4-9
Image definition, 10-61, 10-86
LCD, 4-1
LCD graphics and, 4-4
Cursor control keys, 3-2

D
Data capsule, 2-17
Decompiler, 10-87
Delete cursor, 3-10
DELETE key, 3-4, 3-11
Development system, 1-13
DMOVE
Use with EMIT, 4-5
Dots in LCD, 4-1
Double word
Representation of, 2-3
Down-loader, 1-13
DP-V, 2-11
DSPLY, 4-3
Dynamic allocation of RAM, 2-26

(c) 1981 Friends Amis, Inc. index-2 3 September 81


INDEX

ECB, 6-1, 6-2


Allocating, 6-4
Format of, 6-3
Peripheral I/O, 6-5
Posting, 6-6
Return code, 6-13, see Return code
Timer, 6-33
WAITM, 6-11
EMIT, 4-2, 10-30
Display mode set by, 4-2
ROP and, 6-8
Vectoring, 4-13
Emulator, 1-13
ENDAREA (TSA word), 2-22
Enigma
Floating point, 7-2
ENTER key, 3-2
EOL word
EXPECT, 3-10, 10-39
Escape control sequence, 10-3
Escape control sequences, 6-16
ETX/ACK protocol
Serial Interface Adaptor, 6-27
Event control block, see ECB
Executable file, 10-48
EXECUTABLE file type, 5-2, 5-8
• EXPECT,
Dot graphics and, 4-5
Extrinsic
Virtual file space, 5-11
Extrinsic RAM, 2-2, 10-70
Extrinsic ROM, 10-71

F1/F2/F3 keys, 3-4


File
Current, 5-3
Header, 5-1
Multiple files with same name, 5-3
Non-text, 5-6, 5-8, 5-13
Output causes other files to move, 3-1
Files, 1-6
Automatic deletion of, 5-2
Virtual, 5-1
FLAME.ON, 4-13
Flash display, 6-17
FLEE, 2-30
Floating accent
EMIT linkage, 4-2
Table, 4-8

(c) 1981 Friends Amis, Inc. index-3 3 September 81


INDEX

Floating point
Numeric representation, 2-3
Representation of, 7-1
Special case, 7-2
Forward reference, 2-19
Function key
Defining a, 3-18
Precedence over keyboard & pushkey buffers, 3-19
Typing from program, 3-19
Function vs. program, 8-5

Glossary
Format of, 1-17
GRAB, 2-26
Graphics
EXPECT and, 4-5
LCD, 4-3, 10-30
Ground state, 2-30

H: (host definition) , 4-7


Hardware device code, 6-5, 6-13
Header, 2-10, 8-7
File, 5-1
HELP key, 3-4
Hidden keys, 3-2
Host definition, 4-7
Host system, 1-1,..)

I
I/O
Drivers, 1 -6
intrinsic, 1-3
Peripheral drivers, 1-6
I/O bank, 1-5
I/O key, 3-3
Immediate keys, 3-2
Insert cursor, 3-10
INSERT key, 3-4, 3-11
Integer
Representation of, 2-3
Interrupt, 6-1, 6-6
Interrupts, 1-9
In 1-3
Applications, 1-6
RAM, 2-1, 2-24
Rom, 2-2
Virtual file abace, 5-11
Intrinsic I/O, 1-3
Inverse d? splay, 6-17

(c) 1981 Friends Amis, Inc. index-4 3 September 81


INDEX

Invisible file, 10-43


INVISIBLE file type, 3-8

KBVECT, 3-6
KEY, 3-5
RIP and, 6-8
Keyboard, 3-1, 6-12, see also names of individual keys
Additional characters, A-7
Character translation table, 3-6
Displayable character set, A-4
Hardware of, 3-2
Hidden and immediate keys, 3-2
Input with EXPECT, 3-9
Keyboard buffer, 3-16
Logical unit number 0, 6-7
Raw keyboard code, 3-6, 3-8
RIP versus KEY, 6-8

Label, 9-12
Latch, 10-54
Latch byte, 2-32
LCD, 4-1
Additional characters, A-7
As a peripheral, 6-18
Blips, 4-15
Character control buffer, 4-3
Character display buffer, 4-3
Character translation table, 4-6
Cursor, 4-1, 4-9
Display buffer, 4-3
Displayable character set, A-4
Displaying accent marks, 4-8
Graphics, 4-3
Logical unit number 1, 6-7
ROP versus EMIT, 6-8
Slaving peripherals to, 4-13
STOP/SPEED control, 4-12
Used as data buffer, 3-16
LCD buffer, 10-30
LCD graphics, 10-30
L7TGO, 2-24
Liquid crystal display, see LCD
LOCK key, 3-3
LOCK-KEY, 3-3, 6-9
Logical unit number, 6-5, 6-7, 6-13
LONG, 2-13, 2-19
Long tag, 2-6
How executed, 2-8
LONG,TAGS, 2-18
Loop stack
Size of, 2-1

(c) 1981 Friends Amis, Inc. index-5 3 September 81


INDEX

Low level procedure, 9-3, 9-12


LUN
Keyboard and LUN 40, 6-12
Unattaching and reattaching, 6-12

Master capsule, 2-16


Memory bank, 2-17
Memory map, 2-1
Menu driver, 8-10
MetaSnap, see Cross-compiler
Micro Printer, 6-19
Modem, 6-21
Modem initialization file, name of, 6-23
Mother tag, 8-7
Mother word, 2-10, 2-14

NAP, 3-14
No-text file, 5-8
Non-text file, 5-6
Format of, 5-13
Nucleus, 1-6

ON/OFF keys, 3-2


Order entry program, 8-1
Overflow
Floating point, 7-2

Parameter stack, 2-24


CODE word use of, 9-13
Size of, 2-1
PCA, 6-30
Peripheral
Interface, 1-6
Peripheral control area, see PCA
Peripherals, 1-4
I/O drivers, 1-6
Pher ipheral
Slaving to LCD, 4-13
Posting an ECB, 6-2
Power, 1-9
Printer, 4-9
PRCGBIT, 2-11, 2-1 7
Program function keys, 3-4
Program header, see Header
Program vs. function, 8-5
Programmable Memory Pericheral
Virtual files, 5-11

(c) 1981 Friends Amis, Inc. index-6 3 September 81


INDEX

Pushkey buffer, 3-17


Precedence over keyboard buffer, 3-17

Queueing an ECB, 6-2


Queuing an ECB, 6-4

RAM, see also Temporary storage area


Dynamic allocation of, 2-26
Extrinsic, 2-2, 10-70
Intrinsic, 2-1, 2-24
Memory map, 2-1
Raw keyboard code, 3-6, 3-8
RCLOSE, 6-9
RCTL (Request Control), 6-10
Real-time clock, 6-33
REC-CNT, 10-51
Record number, 5-1
Restarting an application, 2-30
Return code, 6-3, 6-13
Return code in ECB, 6-3
Return stack, 2-29
CODE word use of, 9-16
Size of, 2-1
RIP (Request Input) , 6-7
ROM
Allocating space in, 2-28
Effect of write to, 2-2
Extrinsic, 10-71
Intrinsic, 2-2
Memory map, 2-1
Slow, 2-17
ROMADDR, 2-10
ROMID, 2-11
ROP (Request Output), 6-8
ROPEN, 6-9
ROTATE key, 3-4
Rotation mode, 4-11
RS-232 interface, see Serial Interface Adaptor

SDT
Addresses in, 6-12
SEARCH key, 3-4
SECOND SHIFT key, 3-1, 3-4
Serial Interface Adaptor, 6-25
Name of initialization file, 6-27
Servicing an interrupt, 6-1
SETORG, 2-10
SHIFT bit, 3-5
ltior SHIFT key, 3-1, 3-3, 3-5, 3-6

(c) 1981 Friends Amis, Inc. index-7 3 September 81


INDEX

SHIFT LOCK bit, 3-5


SHIFT LOCK key, 3-5, 3-6
SHINT, 2-11
SHORT, 2-13, 2-19
Short tag, 2-6
How executed, 2-8
SHORT.TAGS, 2-18
SIM computer, 1-13
Simulator
Does not support shift-lock, 3-5
Incompatibility with HHC, 2-29
Slave capsule, 2-16
Slow ROM, 2-17
SNAP
Code structure, 2-5
Decompiler for, 10-87
Differs from FORTH, 1-10
SNAP interpreter, 1-6
Snapple
Tag table initialization, 2-10
SOFTAG, 2-30
Special case, 7-2, 10-46
Program-defined, 7-3
Specifiers
Addressing mode, 9-8
Squeak, 4-16
Status, 6502 processor, 9-10
STOP/SPEED key, 3-3, 4-12
String representation, 2-3
Symbolic constant, 2-20

T
Tag, 1-11
SNAP code structure , 7-5
Tag table, 2-5, 8-7
41, 2-7
2 through f8, 2-7
Initializing, 2-1U
Master capsule, 2-16
Overflow of, 2-18
Short extrinsic, 2-7
Slave capsule, 2-16
Structure of, 2-7
vector, 2-3, 10-78
TAG.TABLE, 2-11
Target system, 1-10
Temporary file, 10-48
TEMPORARY file type, 5-2, 5-8
Temporary stack, 5-11, see Temporary storage area
Used by Micro Printer, 6-19
Temporary storage area, 2-22
Test cabsule, 1-13
Text file, 10-48
TEXT file tote, 5-2, 5-8

(c) 1981 Friends Amis, Inc. index-8 3 September 81


INDEX

Tick, see Clock tick


Time of century clock, 6-33
Timer, 0-33
ECB, 6-33
ECB format, 6-3
Traffic bit, 6-2, see Wait bit
TSA, see Temporary storage area
Overflow of, 2-24
Size of temporary stack, 2-24
Temporary stack, 2-24, 2-29
Variables allocated in reverse order, 8-8
Types of virtual files, 5-2, 5-8

Unattaching a LUN, 6-12


Underflow
Floating point, 7-2

Vectored I/O, 4-13


Video interface, 6-21
Virtual file
Attributes of, 10-48
Memory map, 2-1
Virtual file space, 5-11
Structure of, 5-11
Now Virtual Files, 1-6, 5-1
Editor, 5-10
Virtual memory, 2-28
TR

WAIT, 6-2
Wait bit, 6-2, 6-4
WAITM, 6-11
Word
Representation of, 2-3
Word break character, 6-17

XCN/XOFF crotocol
1odem, 0-22, 6-24

Zero divide
Floating point, 7-2

(c) 1981 Friends Amis, Inc. index-9 3 September 81


,

You might also like