



================================================================================

    H A L C Y O N   I N S T R U M E N T   &   C O N T R O L

================================================================================




                         MODEL HC-33 FLIGHT COMPUTER

                        PROGRAMMER'S REFERENCE MANUAL

                    Including the Ship Peripheral Interface




                     +----------------------------------+
                     |                                  |
                     |    32-BIT  *  16 REGISTERS       |
                     |    35 INSTRUCTIONS  *  8 KB RAM  |
                     |    1 KB DAILY WORMHOLE LINK      |
                     |                                  |
                     +----------------------------------+




                     Publication No. HIC-0033-A
                     First Edition

                     For use with command ships of the Halcyon
                     Prospector class and compatible hulls.




                     RETAIN THIS MANUAL WITH THE SHIP RECORDS.
                     THE COMPUTER CANNOT BE REPROGRAMMED
                     AFTER LAUNCH.  READ BEFORE YOU FLY.




--------------------------------------------------------------------------------
NOTICE

The information in this manual is subject to change at the discretion of
Halcyon Instrument & Control.  Constants quoted as "standard" are the values
set at the factory; belt operators may adjust them.  Halcyon accepts no
liability for ships lost to the Star, to the Belt, or to programmer error.
The last of these is by far the most common.

Halcyon and the Halcyon crescent are trademarks of Halcyon Instrument &
Control.  All other names are the property of their respective owners.
--------------------------------------------------------------------------------




================================================================================
CONTENTS
================================================================================

  1.  INTRODUCTION
        1.1  What the HC-33 Is
        1.2  Specifications
        1.3  A Day in the Life of a Ship
        1.4  Conventions Used in This Manual

  2.  ARCHITECTURE
        2.1  Registers
        2.2  Program Memory
        2.3  Data Memory and the Memory Map
        2.4  The Stack
        2.5  Execution, Ticks and the Cycle Budget
        2.6  Processor States

  3.  INSTRUCTION SET
        3.1  Instruction Format
        3.2  Summary of Instructions
        3.3  Instruction Reference
        3.4  Missing Instructions and How to Live Without Them

  4.  THE ASSEMBLER
        4.1  Source Format
        4.2  Directives and Pseudo-Instructions
        4.3  Numbers and Names
        4.4  Running the Assembler

  5.  PERIPHERALS
        5.1  The Port Interface
        5.2  Units and Conventions
        5.3  System Clock
        5.4  Navigation Unit
        5.5  Main Engine
        5.6  Scanner
        5.7  Mining Laser and Cargo Hold
        5.8  Dropoff Station and Market
        5.9  Wormhole Link
        5.10 Math Coprocessor

  6.  OPERATIONS
        6.1  Life Cycle of a Ship
        6.2  The Daily Run
        6.3  Ground Interface

  7.  THE SHIP AND ITS ENVIRONMENT
        7.1  The Prospector Hull
        7.2  Space, Orbits and the Star
        7.3  Fuel and Delta-V

  8.  PROGRAMMING NOTES

  9.  SAMPLE PROGRAMS

  APPENDIX A   Opcode Table
  APPENDIX B   Port Map
  APPENDIX C   Standard Equate File
  APPENDIX D   Fault Conditions
  APPENDIX E   Quick Reference Card




================================================================================
CHAPTER 1   INTRODUCTION
================================================================================

1.1  WHAT THE HC-33 IS
------------------------

The HC-33 is the flight computer fitted to every Halcyon command ship.  It is
a small, slow, utterly predictable 32-bit processor.  It has no operating
system, no clock interrupts and no operator.  Once your ship leaves the dock
the HC-33 is the only intelligence on board.

You cannot fly the ship.  You can only tell the computer, in advance, how to
fly the ship.  The program is written by you, assembled on the ground into
raw machine code, and sealed into the computer's program memory before launch.
From that moment it is fixed for the life of the ship.

The computer talks to the outside world through two channels:

  o  PERIPHERAL PORTS, which connect it to the engine, scanner, mining laser
     and the rest of the ship.  (Chapter 5.)

  o  THE WORMHOLE LINK, a message channel through which you may send the
     computer exactly one kilobyte per day and receive exactly one kilobyte
     per day.  The link has no delay.  The content is entirely up to you and
     your program.  (Section 5.9.)

Because the link is so narrow, a good program is one that can run the ship
for days on its own and needs only a few bytes of guidance from home.


1.2  SPECIFICATIONS
------------------------

  Word size ............................ 32 bits, two's complement
  Registers ............................ 16 general purpose (r15 = stack ptr)
  Instruction length ................... 4 bytes, fixed
  Instruction set ...................... 35 instructions
  Program memory (ROM) ................. 4096 bytes standard (1024 words)
  Data memory (RAM) .................... 8192 bytes standard
  Wormhole buffers ..................... 1024 bytes uplink, 1024 bytes downlink
  Cycle budget ......................... 2000 cycles per tick, standard
  Ticks per day ........................ 1440 standard (one tick = 60 s)
  Effective speed ...................... 33.3 cycles per second of ship time
  Cycles per day ....................... 2,880,000
  I/O .................................. IN and OUT to 16-bit port numbers
  Byte order ........................... little-endian

  NOTE:  The program size, RAM size, cycle budget and tick rate are settings
  of the belt, not of the computer.  Your belt operator can tell you the
  values in force.  This manual quotes the standard values.


1.3  A DAY IN THE LIFE OF A SHIP
------------------------

Once every day the belt is simulated from start to finish.  For your ship the
day runs as follows:

  1.  Any waiting uplink is placed in the computer's uplink buffer.
  2.  The day is divided into ticks.  On each tick, the computer runs
      until it executes a YIELD or uses up its cycle budget.
  3.  After the computer has stopped, the ship's physical world advances by
      one tick: the engine fires, the Star pulls, the ship moves, the mining
      laser works.
  4.  After the last tick the contents of the downlink buffer are captured
      and made available to you.

At standard settings that is 1440 rounds of "think, then move".  Between days
nothing happens to your ship: it is frozen with its registers and memory intact.


1.4  CONVENTIONS USED IN THIS MANUAL
------------------------

  ra, rb ......... any of the sixteen registers r0..r15
  imm ............ a signed 16-bit immediate value, -32768 .. 32767
  port ........... a port number, 0..32767 (all standard ports are below 256)
  [rb+imm] ....... the RAM byte address obtained by adding imm to register rb
  <- ............. "is assigned"
  0x ............. prefix for hexadecimal numbers

Text in this manual marked NOTE is helpful.  Text marked CAUTION describes
something that can cost you a ship.




================================================================================
CHAPTER 2   ARCHITECTURE
================================================================================

The HC-33 is a HARVARD MACHINE: program and data live in separate memories.
The program cannot be read or written by the program itself.


2.1  REGISTERS
------------------------

There are sixteen 32-bit registers, r0 through r15.  They are interchangeable
except for r15, which the CALL, RET, PUSH and POP instructions use as the
STACK POINTER.  The assembler accepts the name SP as a synonym for r15.

There is also a PROGRAM COUNTER, which holds the byte address of the next
instruction.  It cannot be read or written directly; it is changed only by
jumps, branches, CALL and RET.

There are no condition flags.  Comparison and branching are a single
operation (BEQ, BNE, BLT, BGE), so no state is left behind.

At launch every register is zero, except r15, which holds the size of RAM
(8192) so that the stack starts empty at the top of memory.


2.2  PROGRAM MEMORY
------------------------

The program occupies up to 4096 bytes (1024 instructions) starting at byte
address 0.  Each instruction is four bytes, so a program is always a whole
number of words.  Program addresses are byte addresses and are always a
multiple of four.

If execution runs off the end of the program the computer HALTS.  This is not
a fault.


2.3  DATA MEMORY AND THE MEMORY MAP
------------------------

RAM is byte addressable from address 0 and is standard 8192 bytes.  Words and
half-words are stored least-significant byte first.  No alignment is
required.  Any access outside RAM is a FAULT.

                    +-------------------------+ 8192
                    |                         |
                    |   STACK (grows down)    |   r15 starts here
                    |            |            |
                    |            v            |
                    |                         |
                    |   .  .  .  .  .  .  .  |
                    |                         |
                    |   GENERAL DATA          |
                    |   (about 6 KB)          |
                    +-------------------------+ 2048
                    |   DOWNLINK BUFFER  (TX) |
                    |   1024 bytes            |
                    +-------------------------+ 1024
                    |   UPLINK BUFFER    (RX) |
                    |   1024 bytes            |
                    +-------------------------+ 0

The two wormhole buffers are ordinary RAM.  The link hardware writes the
uplink into the bottom kilobyte before the first tick of the day and copies
the second kilobyte out at the end of the day.  Your program may read and
write both buffers freely.  The buffer boundaries are 0, 1024 and 2048 at
standard settings.

RAM is not cleared between days, and there is no reset.

CAUTION:  There is no memory protection.  A runaway stack, or a store through
a bad pointer, will happily overwrite your own buffers or data.


2.4  THE STACK
------------------------

The stack grows downward from the top of RAM.  PUSH first subtracts four from
r15 and then stores a word at the new address.  POP loads the word at r15 and
then adds four.  CALL pushes the address of the instruction following it and
jumps.  RET pops an address and jumps to it.

Popping from an empty stack, or pushing past the bottom of RAM, is a fault.
Nothing stops the stack from growing down into your data.


2.5  EXECUTION, TICKS AND THE CYCLE BUDGET
------------------------

Time on the HC-33 is measured in TICKS.  On each tick the computer is given a
CYCLE BUDGET, standard 2000 cycles, and runs until one of these happens:

  o  the program executes YIELD;
  o  the budget is used up;
  o  the program HALTs or FAULTs.

Most instructions cost one cycle.  MUL costs two.  DIV and MOD cost eight.
The budget is checked before each instruction, so the last instruction of a
tick may overrun the budget by a few cycles.

WHEN THE BUDGET RUNS OUT THE COMPUTER IS NOT RESET.  It is simply stopped
where it was, and on the next tick it carries on from the very next
instruction.  A long calculation is therefore spread across as many ticks as
it needs.  Meanwhile the ship goes on moving, which may or may not be what
you want.

YIELD ends the computer's turn immediately and gives up the rest of the
budget.  The next tick begins with the instruction after the YIELD.  A
typical control program is a loop that reads sensors, decides, writes the
controls, YIELDs, and jumps back to the top.

CAUTION:  The ship's controls are LATCHED.  Throttle, azimuth and pitch keep
whatever value was last written to them until you write another.  A ship whose
computer has halted or faulted continues to burn at its last setting until it
runs out of fuel.


2.6  PROCESSOR STATES
------------------------

At any moment the computer is in one of four states:

  RUNNING   Executing, or interrupted by the end of its budget.
  YIELDED   Gave up the rest of the tick with YIELD.  Resumes next tick.
  HALTED    Executed HALT or ran off the end of the program.  Permanent.
  FAULTED   Executed an illegal instruction or made an illegal access.
            Permanent.

HALTED and FAULTED are final.  The processor never runs again, its engine
settings are frozen, and there is no way to restart it.  Appendix D lists the
fault conditions.




================================================================================
CHAPTER 3   INSTRUCTION SET
================================================================================

3.1  INSTRUCTION FORMAT
------------------------

Every instruction is one 32-bit word:

     31                16 15    12 11     8 7               0
    +--------------------+--------+--------+-----------------+
    |       IMM16        |   RA   |   RB   |     OPCODE      |
    +--------------------+--------+--------+-----------------+

  OPCODE   bits 0-7     which instruction (Appendix A)
  RB       bits 8-11    second register field
  RA       bits 12-15   first register field
  IMM16    bits 16-31   signed 16-bit immediate, sign-extended to 32 bits

The word is stored in program memory least-significant byte first, so the
four bytes of an instruction appear in the file as:

    byte 0 = opcode     byte 1 = (RA * 16) + RB     bytes 2-3 = IMM16, low first

Unused fields are zero.  You will normally never build these words by hand;
the assembler does it for you.

Jump and branch offsets are counted in INSTRUCTIONS, not bytes, and are
relative to the instruction FOLLOWING the jump.  An offset of zero therefore
continues at the next instruction, and an offset of -1 jumps to the
instruction just executed.  The reach is 32K instructions either way, which
is more than the whole program memory.


3.2  SUMMARY OF INSTRUCTIONS
------------------------

  CONTROL         NOP   YIELD   HALT   JMP   BEQ   BNE   BLT   BGE   CALL   RET
  LOAD CONSTANT   LDI   LUI
  REGISTER        MOV   ADD   SUB   MUL   DIV   MOD   AND   OR   XOR
                  SHL   SHR   SAR   ADDI
  STACK           PUSH  POP
  MEMORY          LDB   LDH   LDW   STB   STH   STW
  INPUT/OUTPUT    IN    OUT


3.3  INSTRUCTION REFERENCE
------------------------

All arithmetic is 32-bit two's complement and WRAPS on overflow.  No
instruction sets flags.

NOP                                                                    1 cycle
     No operation.

YIELD                                                                  1 cycle
     End this tick.  Execution resumes with the next instruction on the next
     tick.

HALT                                                                   1 cycle
     Stop the computer permanently.

LDI  ra, imm                                                           1 cycle
     ra <- imm (sign-extended)
     Loads a constant from -32768 to 32767.

LUI  ra, imm                                                           1 cycle
     ra <- (imm << 16) OR (ra AND 0xFFFF)
     Replaces the upper half of ra and keeps the lower half.  LDI followed by
     LUI builds any 32-bit constant; the assembler's LI does exactly this.

MOV  ra, rb                                                            1 cycle
     ra <- rb

ADD  ra, rb                                                            1 cycle
     ra <- ra + rb

SUB  ra, rb                                                            1 cycle
     ra <- ra - rb

MUL  ra, rb                                                           2 cycles
     ra <- ra * rb  (low 32 bits of the product)

DIV  ra, rb                                                           8 cycles
     ra <- ra / rb  (signed, truncated toward zero)
     Dividing by zero is a FAULT.  Dividing by -1 negates ra.

MOD  ra, rb                                                           8 cycles
     ra <- ra REM rb  (signed; the sign of the result follows ra)
     Modulus by zero is a FAULT.  Modulus by -1 gives zero.

AND  ra, rb                                                            1 cycle
OR   ra, rb                                                            1 cycle
XOR  ra, rb                                                            1 cycle
     Bitwise operations: ra <- ra AND/OR/XOR rb.

SHL  ra, rb                                                            1 cycle
SHR  ra, rb                                                            1 cycle
SAR  ra, rb                                                            1 cycle
     Shift ra left (SHL), right logical with zero fill (SHR) or right
     arithmetic with sign fill (SAR).  The shift count is the low five bits
     of rb, so only counts 0..31 are possible.

ADDI ra, imm                                                           1 cycle
     ra <- ra + imm  (imm sign-extended)

JMP  imm                                                               1 cycle
     PC <- next instruction + imm * 4

BEQ  ra, rb, imm                                                       1 cycle
BNE  ra, rb, imm                                                       1 cycle
BLT  ra, rb, imm                                                       1 cycle
BGE  ra, rb, imm                                                       1 cycle
     If the condition holds, PC <- next instruction + imm * 4.
     Conditions: ra = rb, ra <> rb, ra < rb, ra >= rb.  BLT and BGE compare as
     SIGNED numbers.  In assembly source, imm is normally a label.

CALL imm                                                               1 cycle
     Push the address of the next instruction, then jump as for JMP.
     Faults if the stack cannot be pushed.

RET                                                                    1 cycle
     Pop an address from the stack and jump to it.  Faults on an empty stack.

PUSH ra                                                                1 cycle
     r15 <- r15 - 4;  memory word at [r15] <- ra

POP  ra                                                                1 cycle
     ra <- memory word at [r15];  r15 <- r15 + 4

LDB  ra, [rb+imm]                                                      1 cycle
LDH  ra, [rb+imm]                                                      1 cycle
LDW  ra, [rb+imm]                                                      1 cycle
     Load a byte, half-word (2 bytes) or word (4 bytes) from RAM address
     rb + imm.  Bytes and half-words are ZERO-EXTENDED.  Fault if any part of
     the access lies outside RAM.

STB  ra, [rb+imm]                                                      1 cycle
STH  ra, [rb+imm]                                                      1 cycle
STW  ra, [rb+imm]                                                      1 cycle
     Store the low byte, half-word or word of ra at RAM address rb + imm.
     Note that ra is the SOURCE.  Fault if outside RAM.

IN   ra, port                                                          1 cycle
     ra <- the value of the peripheral port.  Ports that do not exist read
     as zero.

OUT  port, ra                                                          1 cycle
     Write ra to the peripheral port.  Writes to ports that do not exist, or
     that are read-only, are ignored.

NOTE:  In IN and OUT the port number occupies the immediate field.  Port
numbers should be kept below 32768.


3.4  MISSING INSTRUCTIONS AND HOW TO LIVE WITHOUT THEM
------------------------

The HC-33 is a small machine.  Everything below is done with what exists.

  Negate ra ........... ldi r9, 0  /  sub r9, ra  /  mov ra, r9
  Invert bits ......... ldi r9, -1  /  xor ra, r9
  Zero a register ..... ldi ra, 0
  Branch if ra > rb ... blt rb, ra, label
  Branch if ra <= rb .. bge rb, ra, label
  Branch if ra = 0 .... keep a zero in some register and use BEQ
  Compare to constant . load the constant into a register first
  Absolute value ...... ldi r9, 0 / bge ra, r9, skip / sub r9, ra / mov ra, r9
  Unsigned compare .... not available; keep values below 2^31
  Computed jump ....... not available; use a chain of compares

A register may be used for an unusual purpose provided you keep track of it.
Conventional practice: r0 as a permanent zero for base addressing, r1-r7 as
scratch, r8-r14 as saved values, r15 as the stack pointer.  This is a habit,
not a rule.




================================================================================
CHAPTER 4   THE ASSEMBLER
================================================================================

Programs are written in assembly language and converted to machine code by
the assembler ASM.  The output is the raw binary program that is uplinked to
the ship (Chapter 6).

4.1  SOURCE FORMAT
------------------------

One statement per line.  A line may hold a label, an instruction, or both.

     label:      mnemonic  operand, operand      ; comment

  o  Case does not matter in mnemonics and register names.  It DOES matter in
     labels and constant names.
  o  Comments start with a semicolon (;) or a hash (#) and run to the end of
     the line.
  o  Labels end with a colon and may stand alone on a line.  A label names
     the position of the next instruction.
  o  Operands are separated by commas.
  o  Memory operands are written [rb], [rb+off] or [rb-off].  There must be
     no arithmetic beyond a single register and a single offset.
  o  Registers are r0 to r15.  SP is another name for r15.

Examples:

     start:   ldi   r1, 100
              add   r1, r2
              beq   r1, r2, start
              ldw   r3, [r2+8]
              stb   r3, [sp-4]
              in    r4, 0x10
              out   0x20, r4

4.2  DIRECTIVES AND PSEUDO-INSTRUCTIONS
------------------------

.EQU  name  value
     Defines a constant.  The name may then be used in place of a number
     anywhere a number is expected, including as a port number or a memory
     offset.  A definition may appear anywhere, but its value may refer only
     to constants defined on earlier lines; in practice put all .EQU lines at
     the top.

LI  rd, value
     Load a full 32-bit constant.  The assembler always generates TWO
     instructions (LDI then LUI) so that labels and branch distances are never
     surprised.  The value must be a number or a constant name, not a label.

Jump, branch and CALL instructions take a label.  They also accept a plain
number, which is then used unchanged as the instruction offset.

LDI, LUI and ADDI accept values from -32768 to 65535.

CAUTION:  The immediate is stored in 16 bits and SIGN-EXTENDED by the machine.
LDI r1, 65535 therefore loads -1, and ADDI r1, 40000 subtracts 25536.  If you
want a large positive value, use LI.

4.3  NUMBERS AND NAMES
------------------------

Numbers may be written in decimal (100, -7), hexadecimal (0x64) or binary
(0b1100100).  A number with a leading zero and no other prefix is read as
OCTAL:  010 is eight, not ten.  This has cost many programmers an afternoon.

There is no expression evaluation.  Write 1028, not 1024+4.

4.4  RUNNING THE ASSEMBLER
------------------------

     asm  prog.s  >  prog.bin

reads the source file and writes the binary program to standard output.
Errors are reported with the line number and the assembler stops at the first.
The size of the file must be a multiple of four (it always is) and must not
exceed the program memory of your belt (4096 bytes standard).  The ground
interface rejects programs that are too large.

Typical assembler messages:

   line 12: unknown mnemonic "lod"
   line 15: bad register "r16"
   line 20: immediate 70000 out of 16-bit range (use li)
   line 31: bad number or unknown name "LOOP"
   line 40: offset 40000 out of range




================================================================================
CHAPTER 5   PERIPHERALS
================================================================================

5.1  THE PORT INTERFACE
------------------------

Everything the ship can sense or do is reached through PORTS.  A port is a
numbered 32-bit register outside the computer's memory, accessed with IN and
OUT.

  in   r1, 0x10        ; read port 0x10 (position X) into r1
  out  0x20, r2        ; write r2 to port 0x20 (throttle)

Ports come in two kinds, and it matters which:

  o  An INPUT port can be read.  Writing to it has no effect.
  o  An OUTPUT port can be written.  READING AN OUTPUT PORT RETURNS ZERO,
     not the last value written.  If you need to remember what you sent,
     keep a copy in a register or in RAM.

A port that does not exist reads as zero and ignores writes.  No port
operation ever faults.  Port numbers are grouped by function in blocks of 16
(0x10), as listed below and collected in Appendix B.

There are no interrupts.  The computer must poll.

5.2  UNITS AND CONVENTIONS
------------------------

Every port value is a signed 32-bit integer.  There are no fractions.

  Distances and positions ...... kilometres (km)
  Velocities ................... metres per second (m/s)
  Angles ....................... milliradians (1000 = 1 radian, 3142 = pi)
  Mass ......................... kilograms (kg)
  Time ......................... ticks, and days
  Money ........................ credits

Fractional readings are ROUNDED DOWN (toward minus infinity).  A position of
-0.4 km reads as -1; 0.9 km reads as 0.  So position is known to no better
than one kilometre and velocity to no better than one metre per second.

COORDINATES.  The frame is fixed in space and centred on the Star.  It is
right-handed.  The X and Y axes lie in the ECLIPTIC, the plane in which the
Station orbits.  The Z axis is perpendicular to it, positive "north".

  AZIMUTH is the direction in the XY plane, measured from +X towards +Y.
  ELEVATION (called PITCH on the engine) is the angle above the XY plane,
  positive towards +Z.

  Azimuth 0, pitch 0 ........ along +X
  Azimuth 1571, pitch 0 ..... along +Y
  Azimuth any, pitch 1571 ... along +Z

5.3  SYSTEM CLOCK
------------------------

  0x00  TICK   input   Tick number within the current day, 0 upwards.
  0x01  DAY    input   Day number.  The first day of the belt is day 0.
  0x02  TICKS  input   Ticks per day (standard 1440).

The ship does not have a wristwatch.  These three ports are how a program
knows when it is.  Tick length is 86400 divided by TICKS seconds.


5.4  NAVIGATION UNIT
------------------------

Reports the ship's position relative to the Star, and its velocity.

  0x10  POSX   input   Position X, km
  0x11  POSY   input   Position Y, km
  0x12  POSZ   input   Position Z, km
  0x13  VELX   input   Velocity X, m/s
  0x14  VELY   input   Velocity Y, m/s
  0x15  VELZ   input   Velocity Z, m/s

The belt lies between 1,500,000 and 3,000,000 km from the Star, so the
positions fit comfortably in a word.  Velocity is the ship's velocity in the
fixed frame, not relative to anything else.


5.5  MAIN ENGINE
------------------------

The engine produces thrust along a direction chosen by two angles, at a power
chosen by the throttle.

  0x20  THROTTLE  output  Engine power, 0 to 1000 (permille of full thrust).
                          Values above 1000 act as 1000; zero or negative
                          switches the engine off.
  0x21  AZIMUTH   output  Thrust direction azimuth, milliradians.
  0x22  PITCH     output  Thrust direction elevation, milliradians.
  0x23  FUEL      input   Fuel remaining, kg.
  0x24  MASS      input   Total ship mass (hull + fuel + cargo), kg.

THE ENGINE FIRES ALONG THE DIRECTION GIVEN, for the whole of the tick, at
the throttle in effect when the computer stopped.  Direction is:

     ( cos(pitch) cos(azimuth),  cos(pitch) sin(azimuth),  sin(pitch) )

The three controls are latched, as described in section 2.5.  Set them once
and the ship keeps burning.  Set THROTTLE to zero to coast.

Thrust and fuel.  For a Prospector at standard tick length:

  Full thrust ................ 6000 newtons
  Exhaust velocity ........... 30,000 m/s
  Fuel used at full throttle . 12 kg per tick  (thrust x tick / exhaust vel.)
  Acceleration ............... thrust / mass, 0.33 to 0.75 m/s^2

Fuel use is proportional to throttle.  When fuel runs out the engine falls
silent; the throttle setting is remembered but has no effect.  If the tank has
less fuel than a full tick needs, the engine delivers a proportionally
shortened burn.

CAUTION:  Fuel is your ship's only means of changing course.  There is no
way to refuel.  See section 7.3 before designing a manoeuvre.


5.6  SCANNER
------------------------

The scanner tracks one asteroid at a time, which you choose by number.
Asteroids are numbered from 1.  The standard belt has 500.  The scanner has
unlimited range: every asteroid in the belt is visible from anywhere in it.

  0x30  SELECT   output  Asteroid number to track.  Zero, or a number that
                         does not exist, clears the selection.
  0x31  NEAREST  input   Number of the asteroid nearest to the ship.

The following ports describe the TRACKED asteroid and all read zero if none
is tracked.

  0x32  RELX     input   Position of the target relative to the ship, X, km
  0x33  RELY     input   ... Y, km
  0x34  RELZ     input   ... Z, km
  0x35  RELVX    input   Velocity of the target relative to the ship, X, m/s
  0x36  RELVY    input   ... Y, m/s
  0x37  RELVZ    input   ... Z, m/s
  0x38  DIST     input   Straight-line distance to the target, km
  0x40  ORE0     input   Iron remaining in the target, kg
  0x41  ORE1     input   Nickel remaining, kg
  0x42  ORE2     input   Ice remaining, kg
  0x43  ORE3     input   Platinum remaining, kg
  (0x44-0x47 exist for future ores and read zero.)

Relative values are TARGET MINUS SHIP: RELX is positive if the target is on
the +X side of you.  To fly towards the target, point the engine along
(RELX, RELY, RELZ).  To match its velocity, apply a thrust along
(RELVX, RELVY, RELVZ).

NEAREST is decided among all asteroids by true three-dimensional distance;
if two are exactly equally near, the lower number wins.

NOTE:  Every asteroid in the belt moves at the same speed, 3 km/s (section
7.2).  For a ship travelling at that speed, the velocity of a target relative
to the ship is therefore decided by the difference in DIRECTION of travel, not
by any difference in speed.


5.7  MINING LASER AND CARGO HOLD
------------------------

  0x50  MINE       output  Non-zero: mine the tracked asteroid.  Zero: stop.
  0x51  CARGO      input   Total mass in the hold, kg.
  0x52  CARGOCAP   input   Capacity of the hold, kg (Prospector: 6000).
  0x58  CARGO0     input   Iron in the hold, kg
  0x59  CARGO1     input   Nickel in the hold, kg
  0x5A  CARGO2     input   Ice in the hold, kg
  0x5B  CARGO3     input   Platinum in the hold, kg
  (0x5C-0x5F exist for future ores and read zero.)

The laser stays on, once MINE has been set, until MINE is set to zero.  In
each tick in which ALL of the following are true, it moves ore from the
asteroid into the hold:

  o  an asteroid is tracked and still has ore;
  o  the asteroid is within 5 km of the ship;
  o  the ship's velocity relative to the asteroid is at most 100 m/s;
  o  the hold is not full.

The Prospector mines 10 kg per tick.  The ore taken is a mixture in the same
proportions as the asteroid's remaining ore.  You cannot choose what to mine.
The conditions are tested at the END of the tick, after the ship has moved.

To fill an empty hold takes 600 ticks, 10 hours of ship time.

Ore has to be brought to the Station before it is worth anything.  An asteroid
does not replenish.

NOTE:  The scanner reports whole kilometres (rounded down).  The range to
mine is 5 km.  Aim for the middle of the range; do not try to close to the
last kilometre.


5.8  DROPOFF STATION AND MARKET
------------------------

The Station is the belt's only dropoff point.  It sits on a circular orbit in
the ecliptic, half way through the belt, at a radius of 2,250,000 km.  Your
ship is launched from it.

  0x60  STNX    input   Position of the Station relative to the ship, X, km
  0x61  STNY    input   ... Y, km
  0x62  STNZ    input   ... Z, km
  0x63  STNVX   input   Velocity of the Station relative to the ship, X, m/s
  0x64  STNVY   input   ... Y, m/s
  0x65  STNVZ   input   ... Z, m/s
  0x66  SELL    output  Non-zero: sell the entire hold.
  0x67  EARNED  input   Credits earned by this ship so far

As with the scanner, relative values are STATION MINUS SHIP.

Writing a non-zero value to SELL sells everything in the hold at once, if
ALL of the following are true, and otherwise does nothing (there is no error
signal):

  o  the ship is within 20 km of the Station;
  o  its velocity relative to the Station is at most 100 m/s;
  o  the hold is not empty.

The hold is emptied, the credits go to your account, and EARNED goes up.

PRICES.  Each ore has a standard price per kilogram.  The price FALLS as ore
floods the market and recovers as it is used up.  Prices are set once per day
and do not change during the day, so it does not matter when in the day you
sell.

     ore        number    standard price       price is halved at
                          (credits per kg)     supply of (kg)
     ----------------------------------------------------------------
     iron          0             2                  400,000
     nickel        1             6                  200,000
     ice           2             3                  300,000
     platinum      3           300                    5,000

     price = standard price x half-point / (half-point + supply)

"Supply" is a running total of the ore sold by everyone.  At the end of each
day today's sales are added to it and 10 percent of the old total is
forgotten.  A price never falls below one credit.  Current prices are
available from the ground interface (section 6.3).  Your program cannot read
them: it must be told, by uplink, if it should care.


5.9  WORMHOLE LINK
------------------------

The link is a pair of one-kilobyte buffers in RAM and two ports.

  0x70  UPNEW   input   1 if an uplink arrived for today and has not been
                        acknowledged, else 0.
        UPNEW   output  Any value: acknowledge (clear the flag).
  0x71  UPLEN   input   Length of today's uplink in bytes, 0 to 1024.

UPLINK.  Before tick 0 of the day, the uplink is copied to RAM addresses 0 to
UPLEN-1.  Bytes beyond the end of the message are left as they were.  UPNEW is
set and stays set until acknowledged or until the day ends.  An uplink is
meant for the day on which it arrives; the flag is cleared at the end of every
day whether or not you noticed.

If you send more than one uplink in a day, only the last is delivered.

DOWNLINK.  At the end of the last tick of the day the ENTIRE transmit buffer,
RAM addresses 1024 to 2047, is captured and made available to you.  It is
always exactly 1024 bytes.  Whatever is in it is sent; the link does not care
whether it was written today.

The wormhole has no delay and is not affected by distance.  It is affected by
size: the buffers are all you have.  The format of the data is entirely your
own invention.  The link does not check it, compress it, or understand it.

NOTE:  A ship that is destroyed sends no more downlinks.  Its last message
remains on file.  A ship that has merely halted still sends its buffer,
unchanged, every day.


5.10  MATH COPROCESSOR
------------------------

The HC-33 cannot take a square root or an arctangent.  The coprocessor
can, at no cost in cycles.  Write the operands, then read the answer.

  0x80  MATHX      output  Operand x
  0x81  MATHY      output  Operand y
  0x82  MATHZ      output  Operand z
  0x83  ATAN2      input   atan2(y, x), in milliradians (-3142 to 3141)
  0x84  HYPOT      input   sqrt(x*x + y*y)
  0x85  NORM3      input   sqrt(x*x + y*y + z*z)

Operands are whole numbers, and results are rounded down.  The internal
arithmetic is wide enough that squaring even large operands cannot overflow,
so you may feed it positions in kilometres directly.  ATAN2 of (0, 0) is zero.

To find the direction from the ship to a target (dx, dy, dz):

     azimuth = ATAN2 with x = dx, y = dy
     range   = HYPOT with x = dx, y = dy
     pitch   = ATAN2 with x = range, y = dz

Sample program 3 (Chapter 9) does exactly this.




================================================================================
CHAPTER 6   OPERATIONS
================================================================================

6.1  LIFE CYCLE OF A SHIP
------------------------

A ship is always in one of four conditions.

  INVENTORY   Built and waiting on the dock.  It can be given a program.
  LAUNCHING   Cleared to launch.  It will enter the belt on the next daily run.
              Its program can no longer be changed.
  ACTIVE      In the belt.
  DESTROYED   Lost.  It cannot be recovered.

On registration each player is issued one command ship, in INVENTORY, with
no program.

  1.  Write a program and assemble it.
  2.  Upload it.  It replaces any earlier program.  Repeat as often as you
      like.
  3.  Launch.  There is no going back.
  4.  On the next daily run the ship is placed at the Station, moving with the
      Station, with full tanks and a zeroed computer, and the program starts.

A launched ship can be sent an uplink, and you can collect its downlink, but
that is all.  You cannot alter the program, recall the ship, or restart it.

A ship is destroyed if it comes within 200,000 km of the Star.


6.2  THE DAILY RUN
------------------------

The belt is simulated once per day, in a single run for every ship.  The run is
DETERMINISTIC: the same belt, the same programs and the same uplinks always
produce the same day, bit for bit.  There is no luck in it.

Order of events within the run:

  1.  Ships waiting to launch are placed at the Station.
  2.  Uplinks are delivered to their ships.
  3.  For each tick of the day, for each ship in order of ship number:
        a.  the computer runs until it yields or exhausts its budget;
        b.  the engine fires and the Star pulls: velocity, then position, are
            updated;
        c.  the mining laser, if on, works.
  4.  Downlinks are captured, and the market is updated for tomorrow.

Ships do not collide with one another or with asteroids.  They cannot see each
other.  Each ship's sales, however, feed the same market as everybody else's.


6.3  GROUND INTERFACE
------------------------

You reach your ship over the HTTP interface of the belt operator.  Every
request except registration and the market carries your API key:

     Authorization: Bearer <your key>

  POST  /register                   {"name": "yourname"}
        Create a player and its command ship.  The reply gives the player
        number, the API KEY (shown once only: keep it) and the ship number.

  GET   /me                         Your name, your credits, the current day.

  GET   /market                     Current ore prices, in the order iron,
                                    nickel, ice, platinum.  No key needed.

  GET   /ships                      Your ships: number, condition, program size
                                    in bytes, and day of the latest downlink.

  PUT   /ships/{n}/program          Body: the assembled program, raw bytes.
        Allowed only while the ship is in INVENTORY.  The program must be
        between 4 and 4096 bytes and a multiple of four.

  POST  /ships/{n}/launch           Launch the ship on the next run.  The ship
        must be in INVENTORY and have a program.

  PUT   /ships/{n}/uplink           Body: up to 1024 raw bytes.  Replaces any
        message queued for the next run.  Allowed while LAUNCHING or ACTIVE.

  GET   /ships/{n}/downlink         The latest downlink, exactly 1024 raw
        bytes.  The header X-Downlink-Day tells you which day's run
        produced it.  A ship's first downlink appears after its first day.

Typical use:

     asm miner.s > miner.bin
     curl -X PUT -H "Authorization: Bearer $KEY" \
          --data-binary @miner.bin  http://belt.example/ships/1/program
     curl -X POST -H "Authorization: Bearer $KEY" \
          http://belt.example/ships/1/launch

An uplink queued today is delivered at the START of the next run and is the
day's message; the downlink you collect afterwards was written during that
run.  In steady state you therefore exchange one kilobyte in each direction
per day, as the name of the link says.

Errors are reported in the usual way: 401 for a missing or wrong key, 404 for
a ship that is not yours, 409 when the ship is in the wrong condition for the
request, 413 when your data is too large, 400 for malformed data.




================================================================================
CHAPTER 7   THE SHIP AND ITS ENVIRONMENT
================================================================================

7.1  THE PROSPECTOR HULL
------------------------

  Dry mass ............................. 8000 kg
  Fuel tank ............................ 4000 kg
  Hold ................................. 6000 kg
  Total mass, full tank, empty hold .... 12,000 kg
  Total mass, empty tank, full hold .... 14,000 kg
  Engine ............................... 6000 N, exhaust velocity 30 km/s
  Mining laser ......................... 10 kg per tick

The ship is a point.  It has no orientation of its own; the engine simply
pushes in whatever direction the two angles command.  There are no
thrusters, no spin, no fuel used to turn.


7.2  SPACE, ORBITS AND THE STAR
------------------------

The Star sits at the origin and pulls on everything with an acceleration

                              a  =  v^2 / r

directed towards it, where r is the distance from the Star and v is a
constant, the ORBIT SPEED, standard 3 km/s.  (In a real solar system the pull
falls with the square of the distance.  In the belt it falls only with the
distance.  Ask a cosmologist.)

The remarkable consequence is that a body on a circular orbit at ANY radius
travels at exactly the same speed, v.  Every asteroid, the Station, and any
ship that has matched their motion, all travel at 3 km/s.  What differs is the
time taken to go round:

     radius (km)                            period of one orbit
     ------------------------------------------------------
     1,500,000    (inner edge of belt)       36.4 days
     2,250,000    (the Station)              54.5 days
     3,000,000    (outer edge of belt)       72.7 days

Asteroids travel on circles, in slightly different planes.  Each orbit is tilted
from the ecliptic by up to about 0.2 radian (11 degrees), most of them by a
good deal less, so the belt is a thick disc with the Station in the middle.  At
the outer edge an asteroid may lie as much as 600,000 km above or below the
ecliptic.
Asteroids are not disturbed by anything you do; they follow their circles for
ever.

A ship in free flight has a great deal of velocity and very little spare
acceleration.  At the Station's radius the Star pulls at about 4 millimetres
per second squared; your engine, at 0.33 to 0.75 m/s^2, is around a hundred
times stronger.  The engine is the master, but the Star never relents, and a
ship left alone drifts from its orbit at once if its velocity differs from
3 km/s.  A ship at 3 km/s, moving tangentially, stays on its circle for ever
and needs no fuel to do it.

CAUTION:  A ship that comes within 200,000 km of the Star is destroyed.  A
ship that is too slow at the wrong radius falls inward and will not stop
until it hits this limit.


7.3  FUEL AND DELTA-V
------------------------

The total change of velocity available from one tank is given by

     dv  =  exhaust velocity  x  ln( mass before / mass after )

For a Prospector with an empty hold and full tank:

     30 km/s  x  ln( 12000 / 8000 )   =   about 12.2 km/s

That is roughly four times the orbit speed.  Nothing is ever free: every
metre per second gained going out must be paid again to slow down, and every
kilogram of ore carried home makes the ship heavier to turn around.  The
engine at full power uses the whole tank in 333 ticks, a little over five
hours of ship time, and yet the day is 24.  Plan accordingly.

A rendezvous takes two burns: one to intercept, and one to match velocity.  A
program that only does the first will arrive, at speed, and pass on.  See the
comments in sample program 3.




================================================================================
CHAPTER 8   PROGRAMMING NOTES
================================================================================

1.  THE BUDGET IS A BUDGET.  At standard settings a tick allows 2000 cycles.
    A loop that copies the full kilobyte uplink a byte at a time uses over
    5000, and needs three ticks.  That is fine, as long as the rest of the
    program can cope with the ship moving on meanwhile.  If a control loop
    matters, keep it short and let the slow work run between calls.

2.  ALWAYS YIELD.  A program with no YIELD uses its whole budget every tick,
    all day.  Its main loop will read the sensors dozens of times per tick and
    see the same numbers each time, since the world does not move until the
    computer stops.  Finish your work, YIELD, and start again next tick.

3.  32 BITS IS NOT MANY.  Positions of two million kilometres times a
    velocity of a few thousand metres per second overflows a word at once.
    MUL wraps silently.  Scale before you multiply, or divide first.

4.  THE PORTS ROUND DOWN.  The error is up to one kilometre and one metre per
    second on every reading.  Differences of nearby readings are meaningless.
    Distance, sampled over a few ticks, is a much better guide to closing
    speed than the RELV ports on a slow approach.

5.  PORTS ARE NOT MEMORY.  Output ports cannot be read back.  Keep a copy of
    every control value you might need.

6.  THE WORLD ONLY MOVES BETWEEN TICKS.  Whatever you write to the engine takes
    effect when the computer stops for the tick and stays in force until you
    write something else.  Do not expect any reaction in the readings until
    your next YIELD.

7.  DEFEND AGAINST FAULTS.  A faulted computer is dead, and the engine
    remains latched at its last throttle.  Check array bounds.  Never divide
    by a value that might be zero.  Never POP more than you PUSHed.

8.  DO NOT WASTE THE UPLINK.  A kilobyte a day is 1024 bytes.  A program can
    use it to change a target number, a threshold, or a mode.  It cannot
    carry the whole belt.  Design the ship so that most days need no uplink at
    all.

9.  TEST ON THE GROUND.  The belt is deterministic.  A program that misbehaves
    once will misbehave in exactly the same way every time, so a run of the
    belt simulator, on the same belt seed, will find the fault.  Do this
    before you launch.

10. AN IDLE SHIP IS A SAFE SHIP.  A program that does nothing at all keeps
    the ship on its launch orbit for ever.  You can only do worse.




================================================================================
CHAPTER 9   SAMPLE PROGRAMS
================================================================================

The three programs below are complete.  Each has been assembled and run.
Program sizes are those of the assembled binary.


PROGRAM 1:  ECHO                                                     52 bytes
------------------------

Sends back whatever you send.  A useful first test of the link: uplink a
message, wait for the next run, and read the same message in the downlink.

Notice how the copy loop uses the UPLEN port to stop at the length of the
message, and how the acknowledge (OUT to UPNEW) comes last, so that the flag
stays set for as long as the copy is unfinished.  A full kilobyte takes three
ticks to copy at standard settings; the computer simply carries on where it
left off (section 2.5).

  ; ECHO -- copy each day's uplink into the downlink buffer.
  ;
          .equ    RX      0               ; uplink buffer
          .equ    TX      1024            ; downlink buffer
          .equ    P_UPNEW 0x70            ; uplink-arrived flag / acknowledge
          .equ    P_UPLEN 0x71            ; uplink length in bytes

  wait:   in      r1, P_UPNEW
          ldi     r2, 0
          beq     r1, r2, sleep           ; nothing new today
          in      r4, P_UPLEN
          ldi     r5, 0                   ; r5 = byte index
  copy:   bge     r5, r4, done
          ldb     r6, [r5+RX]
          stb     r6, [r5+TX]
          addi    r5, 1
          jmp     copy
  done:   out     P_UPNEW, r1             ; acknowledge
  sleep:  yield
          jmp     wait


PROGRAM 2:  TELEMETRY                                                52 bytes
------------------------

Reports tick number, fuel, and position to home.  The five words appear in the
downlink at byte offsets 0, 4, 8, 12 and 16, least-significant byte first.
Because it overwrites them every tick, what you receive is the ship's state as
sampled at the start of the last tick of the day.

  ; TELEMETRY -- every tick, write tick number, fuel and position to the
  ; downlink buffer as five 32-bit words.
  ;
          .equ    P_TICK  0x00
          .equ    P_POSX  0x10
          .equ    P_POSY  0x11
          .equ    P_POSZ  0x12
          .equ    P_FUEL  0x23
          .equ    T_TICK  1024            ; TX + 0
          .equ    T_FUEL  1028            ; TX + 4
          .equ    T_X     1032            ; TX + 8
          .equ    T_Y     1036            ; TX + 12
          .equ    T_Z     1040            ; TX + 16

          ldi     r0, 0                   ; r0 = 0, the base register
  loop:   in      r1, P_TICK
          stw     r1, [r0+T_TICK]
          in      r1, P_FUEL
          stw     r1, [r0+T_FUEL]
          in      r1, P_POSX
          stw     r1, [r0+T_X]
          in      r1, P_POSY
          stw     r1, [r0+T_Y]
          in      r1, P_POSZ
          stw     r1, [r0+T_Z]
          yield
          jmp     loop


PROGRAM 3:  PURSUE                                                   72 bytes
------------------------

Selects the nearest asteroid, points the engine at it, and burns at full
throttle.  The bearing is recomputed every tick with the math coprocessor.

This program is a beginning, not an end.  It will reach its target and fly
straight past it at several kilometres per second, and it will burn its whole
tank in about five hours doing so.  A working program brakes: it must compare
its velocity with the target's (RELVX, RELVY, RELVZ), turn the engine towards
the difference, and throttle back as the distance closes.  It must also
watch its fuel.  That is left as an exercise.

  ; PURSUE -- point the engine at the nearest asteroid and burn.
  ; Crude: it makes no attempt to match velocity, so it will fly straight past.
  ;
          .equ    P_THROTTLE      0x20
          .equ    P_AZIMUTH       0x21
          .equ    P_PITCH         0x22
          .equ    P_SELECT        0x30
          .equ    P_NEAREST       0x31
          .equ    P_RELX          0x32
          .equ    P_RELY          0x33
          .equ    P_RELZ          0x34
          .equ    P_MATHX         0x80
          .equ    P_MATHY         0x81
          .equ    P_ATAN2         0x83
          .equ    P_HYPOT         0x84

          in      r1, P_NEAREST           ; id of the nearest asteroid
          out     P_SELECT, r1            ; track it
          ldi     r7, 1000
          out     P_THROTTLE, r7          ; full power

  aim:    in      r1, P_RELX              ; where is it?
          in      r2, P_RELY
          in      r3, P_RELZ
          out     P_MATHX, r1
          out     P_MATHY, r2
          in      r4, P_ATAN2             ; azimuth = atan2(dy, dx)
          out     P_AZIMUTH, r4
          in      r5, P_HYPOT             ; horizontal range = hypot(dx, dy)
          out     P_MATHX, r5
          out     P_MATHY, r3
          in      r6, P_ATAN2             ; elevation = atan2(dz, range)
          out     P_PITCH, r6
          yield
          jmp     aim


================================================================================
APPENDIX A   OPCODE TABLE
================================================================================

  hex  mnemonic  operands              cycles   operation
  ---  --------  --------------------  ------   -------------------------------
  00   NOP                                1      no operation
  01   YIELD                              1      end this tick
  02   HALT                               1      stop permanently
  03   LDI       ra, imm                  1      ra <- sign-extended imm
  04   LUI       ra, imm                  1      ra <- imm<<16 | (ra & 0xFFFF)
  05   MOV       ra, rb                   1      ra <- rb
  06   ADD       ra, rb                   1      ra <- ra + rb
  07   SUB       ra, rb                   1      ra <- ra - rb
  08   MUL       ra, rb                   2      ra <- ra * rb
  09   DIV       ra, rb                   8      ra <- ra / rb   (fault if 0)
  0A   MOD       ra, rb                   8      ra <- ra rem rb (fault if 0)
  0B   AND       ra, rb                   1      ra <- ra & rb
  0C   OR        ra, rb                   1      ra <- ra | rb
  0D   XOR       ra, rb                   1      ra <- ra ^ rb
  0E   SHL       ra, rb                   1      ra <- ra << (rb & 31)
  0F   SHR       ra, rb                   1      ra <- ra >> (rb & 31), logical
  10   SAR       ra, rb                   1      ra <- ra >> (rb & 31), signed
  11   ADDI      ra, imm                  1      ra <- ra + imm
  12   JMP       imm                      1      pc <- next + imm*4
  13   BEQ       ra, rb, imm              1      if ra = rb  branch
  14   BNE       ra, rb, imm              1      if ra <> rb branch
  15   BLT       ra, rb, imm              1      if ra < rb  branch (signed)
  16   BGE       ra, rb, imm              1      if ra >= rb branch (signed)
  17   CALL      imm                      1      push next; jump
  18   RET                                1      pop pc
  19   PUSH      ra                       1      sp -= 4; [sp] <- ra
  1A   POP       ra                       1      ra <- [sp]; sp += 4
  1B   LDB       ra, [rb+imm]             1      ra <- byte, zero-extended
  1C   LDH       ra, [rb+imm]             1      ra <- half-word, zero-extended
  1D   LDW       ra, [rb+imm]             1      ra <- word
  1E   STB       ra, [rb+imm]             1      byte <- ra
  1F   STH       ra, [rb+imm]             1      half-word <- ra
  20   STW       ra, [rb+imm]             1      word <- ra
  21   IN        ra, port                 1      ra <- port
  22   OUT       port, ra                 1      port <- ra

  Any opcode of 23 hex or above is illegal and faults the computer.

  Pseudo-instruction (assembler only):
       LI        rd, value                2      LDI rd, low16 ; LUI rd, high16


================================================================================
APPENDIX B   PORT MAP
================================================================================

  port  name       dir  description                                     units
  ----  ---------  ---  ----------------------------------------------  -----
  SYSTEM
  0x00  TICK       in   tick within the day                             ticks
  0x01  DAY        in   day number                                      days
  0x02  TICKS      in   ticks per day                                   ticks

  NAVIGATION
  0x10  POSX       in   position X (Star at origin)                     km
  0x11  POSY       in   position Y                                      km
  0x12  POSZ       in   position Z                                      km
  0x13  VELX       in   velocity X                                      m/s
  0x14  VELY       in   velocity Y                                      m/s
  0x15  VELZ       in   velocity Z                                      m/s

  ENGINE
  0x20  THROTTLE   out  0..1000, latched                                permille
  0x21  AZIMUTH    out  thrust direction, latched                       mrad
  0x22  PITCH      out  thrust elevation, latched                       mrad
  0x23  FUEL       in   fuel remaining                                  kg
  0x24  MASS       in   total mass                                      kg

  SCANNER
  0x30  SELECT     out  asteroid to track (0 = none)
  0x31  NEAREST    in   number of nearest asteroid
  0x32  RELX       in   target minus ship, X                            km
  0x33  RELY       in   target minus ship, Y                            km
  0x34  RELZ       in   target minus ship, Z                            km
  0x35  RELVX      in   target velocity minus ship, X                   m/s
  0x36  RELVY      in   ... Y                                           m/s
  0x37  RELVZ      in   ... Z                                           m/s
  0x38  DIST       in   distance to target                              km
  0x40  ORE0       in   iron in target                                  kg
  0x41  ORE1       in   nickel in target                                kg
  0x42  ORE2       in   ice in target                                   kg
  0x43  ORE3       in   platinum in target                              kg

  MINING AND HOLD
  0x50  MINE       out  non-zero = laser on, latched
  0x51  CARGO      in   hold contents                                   kg
  0x52  CARGOCAP   in   hold capacity                                   kg
  0x58  CARGO0     in   iron in hold                                    kg
  0x59  CARGO1     in   nickel in hold                                  kg
  0x5A  CARGO2     in   ice in hold                                     kg
  0x5B  CARGO3     in   platinum in hold                                kg

  STATION
  0x60  STNX       in   station minus ship, X                           km
  0x61  STNY       in   ... Y                                           km
  0x62  STNZ       in   ... Z                                           km
  0x63  STNVX      in   station velocity minus ship, X                  m/s
  0x64  STNVY      in   ... Y                                           m/s
  0x65  STNVZ      in   ... Z                                           m/s
  0x66  SELL       out  non-zero = sell hold (if docked)
  0x67  EARNED     in   credits earned by this ship

  WORMHOLE LINK
  0x70  UPNEW      i/o  in: uplink pending;  out: acknowledge
  0x71  UPLEN      in   uplink length                                   bytes

  MATH COPROCESSOR
  0x80  MATHX      out  operand x
  0x81  MATHY      out  operand y
  0x82  MATHZ      out  operand z
  0x83  ATAN2      in   atan2(y, x)                                     mrad
  0x84  HYPOT      in   sqrt(x^2 + y^2)
  0x85  NORM3      in   sqrt(x^2 + y^2 + z^2)

  All other ports read zero and ignore writes.


================================================================================
APPENDIX C   STANDARD EQUATE FILE
================================================================================

Paste this at the top of any program.  Unused equates cost nothing.

          .equ    RX              0               ; uplink buffer
          .equ    TX              1024            ; downlink buffer
          .equ    RAMTOP          8192            ; initial stack pointer

          .equ    P_TICK           0x00
          .equ    P_DAY            0x01
          .equ    P_TICKS          0x02
          .equ    P_POSX           0x10
          .equ    P_POSY           0x11
          .equ    P_POSZ           0x12
          .equ    P_VELX           0x13
          .equ    P_VELY           0x14
          .equ    P_VELZ           0x15
          .equ    P_THROTTLE       0x20
          .equ    P_AZIMUTH        0x21
          .equ    P_PITCH          0x22
          .equ    P_FUEL           0x23
          .equ    P_MASS           0x24
          .equ    P_SELECT         0x30
          .equ    P_NEAREST        0x31
          .equ    P_RELX           0x32
          .equ    P_RELY           0x33
          .equ    P_RELZ           0x34
          .equ    P_RELVX          0x35
          .equ    P_RELVY          0x36
          .equ    P_RELVZ          0x37
          .equ    P_DIST           0x38
          .equ    P_ORE0           0x40
          .equ    P_ORE1           0x41
          .equ    P_ORE2           0x42
          .equ    P_ORE3           0x43
          .equ    P_MINE           0x50
          .equ    P_CARGO          0x51
          .equ    P_CARGOCAP       0x52
          .equ    P_CARGO0         0x58
          .equ    P_CARGO1         0x59
          .equ    P_CARGO2         0x5A
          .equ    P_CARGO3         0x5B
          .equ    P_STNX           0x60
          .equ    P_STNY           0x61
          .equ    P_STNZ           0x62
          .equ    P_STNVX          0x63
          .equ    P_STNVY          0x64
          .equ    P_STNVZ          0x65
          .equ    P_SELL           0x66
          .equ    P_EARNED         0x67
          .equ    P_UPNEW          0x70
          .equ    P_UPLEN          0x71
          .equ    P_MATHX          0x80
          .equ    P_MATHY          0x81
          .equ    P_MATHZ          0x82
          .equ    P_ATAN2          0x83
          .equ    P_HYPOT          0x84
          .equ    P_NORM3          0x85


================================================================================
APPENDIX D   FAULT CONDITIONS
================================================================================

A fault stops the computer permanently.  The cause is recorded on the ship
but is not reported to you; the symptom is a ship that no longer responds.

  ILLEGAL OPCODE
      The instruction word's opcode is 23 hex or greater.  Usually means the
      program has run into data, or the binary was not produced by ASM.

  DIVISION BY ZERO
      DIV or MOD with a zero divisor.

  MEMORY ACCESS OUT OF RANGE
      A load or store, a PUSH, a POP, a CALL or a RET touched an address
      below 0 or above the end of RAM.  Includes a pop from an empty stack and
      a return with nothing to return to.

  Not faults:  arithmetic overflow (wraps), shifts of 32 or more (the count
  is masked), writing to a port that does not exist, running off the end of
  the program (HALT), commanding a throttle greater than 1000 (clamped).


================================================================================
APPENDIX E   QUICK REFERENCE CARD
================================================================================

+------------------------------------------------------------------------------+
| HC-33 QUICK REFERENCE                                                        |
+------------------------------------------------------------------------------+
| REGISTERS  r0-r14 general   r15 = SP (starts at 8192)                        |
| MEMORY     0-1023 uplink   1024-2047 downlink   2048-8191 data + stack       |
| WORD       32 bit, little-endian, no flags                                   |
+------------------------------------------------------------------------------+
| ldi ra,imm    lui ra,imm    li rd,val   mov ra,rb                            |
| add sub mul div mod and or xor shl shr sar   ra,rb       addi ra,imm         |
| jmp L   beq/bne/blt/bge ra,rb,L   call L   ret   push ra   pop ra            |
| ldb/ldh/ldw ra,[rb+imm]    stb/sth/stw ra,[rb+imm]                           |
| in ra,port    out port,ra    yield    halt    nop                            |
+------------------------------------------------------------------------------+
| COSTS      most 1    mul 2    div,mod 8         BUDGET 2000/tick             |
| UNITS      km   m/s   milliradians   kg          READINGS ROUND DOWN         |
+------------------------------------------------------------------------------+
| 00 tick  01 day  02 ticks/day                                                |
| 10-12 pos km   13-15 vel m/s                                                 |
| 20 throttle 0-1000   21 azimuth   22 pitch   23 fuel   24 mass               |
| 30 select   31 nearest   32-34 rel pos   35-37 rel vel   38 dist   40-43 ore |
| 50 mine   51 cargo   52 cap   58-5B cargo by ore                             |
| 60-62 stn pos   63-65 stn vel   66 sell   67 earned                          |
| 70 uplink flag / ack   71 uplink length                                      |
| 80 x  81 y  82 z   83 atan2   84 hypot   85 norm3                            |
+------------------------------------------------------------------------------+
| MINE  within 5 km,  rel speed <= 100 m/s        10 kg/tick                   |
| SELL  within 20 km, rel speed <= 100 m/s        whole hold                   |
| STAR  a = v^2/r, v = 3 km/s.  Inside 200,000 km = destroyed.                 |
+------------------------------------------------------------------------------+


                              * * *  END OF MANUAL  * * *

--------------------------------------------------------------------------------
HALCYON INSTRUMENT & CONTROL                          Publication HIC-0033-A
Printed in the Outer System.                          First Edition
