This document contains a complete set of specifications for the Bedrock 8-bit computer system, a stable and ultra-portable platform for creating compact applications that can run anywhere. The system can be implemented either as a thin emulator on top of any existing computer system, or as a minimal hardware board built around any basic microcontroller. A broad range of device interfaces allows each system to expose a variety of hardware capabilities.
The purpose of this document is to allow anyone to implement the complete system from scratch. Implementers should start by reading and implementing the architecture specification (required to run Bedrock programs), followed by any number of device specifications (required to give programs access to hardware).
This document is structured as a set of individual specifications that each specify an aspect of the Bedrock computer system. The most important specification is the architecture specification, which describes the base system; every other specification describes either standard tooling, data formats, or devices for exposing hardware capabilities to existing systems.
The core specifications form the foundation of the Bedrock computer system. They describe how to write, run, and inspect programs, and how to interface with virtual devices or physical device boards.
The device specifications describe the twelve standard devices that connect to the first twelve slots of the Bedrock device bus, providing programs with access to hardware capabilities. These devices are optional enhancements that are not required to be implemented, however most programs will be of limited use unless at least a couple of these devices are available to the system. Devices are expected to be omitted on a case-by-case basis if the necessary hardware is unavailable.
0x0System device specification Provides system information, and controls for sleeping, forking, and resetting the system.
The auxiliary device specifications describe devices that can connect to any of the final four slots of the Bedrock device bus, providing specialised functionality beyond the requirements of most programs. These devices are optional enhancements that are not required or even expected to be implemented.
GPIO device specification Provides 32 general purpose IO pins, 4 analogue inputs, and 4 analogue outputs.
This is the third revision of the specification, released on TODO: Add date. It has been rewritten in a more linear format to be easier to read and includes specifications for the previously unspecified tone and waveform devices.
Byte A byte is an 8-bit value representing an integer in the range 0 to 255. This is the base unit of data for Bedrock.
Double A double is a 16-bit value representing an integer in the range 0 to 65535. It is stored as a pair of bytes in big-endian order, with the high-order byte coming before the low-order byte.
Array An array is a fixed-length block of bytes, with each byte addressed by its position in the array. The address of the first byte in the array is zero.
Pointer A pointer is an integer that references a specific byte in an array. The value of the pointer is equal to the address of the referenced byte.
Signed value TODO: How do I do this? Devices need signed values, the core does not. All values are treated as unsigned unless otherwise stated. A signed 8-bit value represents an integer in the range -128 to 127, and a signed 16-bit value represents an integer in the range -32768 to 32767. Need a thing talking about the offset range though. Define as a remapping of the high range?? 0x0000 to 0x7FFF maps to the range / represents the range 0 to 32767, 0x8000 to 0xFFFF is -32768 to -1. This is important. Unsigned by default though.
Bit TODO. Highest order, lowest order??
Unicode TODO. Unicode scalar value. Where to find more information. The U+0000 syntax.
Bitwise-shift To bitwise-shift a value left by one bit, set each bit of the value to the original state of the next lower bit, and unset the lowest bit. To bitwise-shift right, set each bit to the original state of the next higher bit, and unset the highest bit. Repeat n times to rotate n bits.
Bitwise-rotate To bitwise-rotate a value left by one bit, set each bit of the value to the original state of the next lower bit, and set the lowest bit to the original state of the highest bit. To bitwise-rotate right, set each bit to the original state of the next higher bit, and set the highest bit to the original state of the lowest bit. Repeat n times to rotate n bits.
Bitwise-OR The bitwise-OR operation takes two equal-sized input values and returns a same-sized output value. Each input value bit corresponds to the bit at the same position in the output value. Each output bit is set only if at least one of the corresponding input bits is set.
Bitwise-XOR The bitwise-XOR operation takes two equal-sized input values and returns a same-sized output value. Each input value bit corresponds to the bit at the same position in the output value. Each output bit is set only if exactly one of the corresponding input bits is set.
Bitwise-AND The bitwise-AND operation takes two equal-sized input values and returns a same-sized output value. Each input value bit corresponds to the bit at the same position in the output value. Each output bit is set only if both of the corresponding input bits are set.
Bitwise-NOT The bitwise-NOT operation takes one input value and returns a same-sized output value. Each input value bit corresponds to the bit at the same position in the output value. Each output bit is set only if the corresponding input bit is not set.
Overflow Overflow occurs when a value increases beyond the range representable by the underlying bytes.
Underflow Underflow occurs when a value decreases below the range representable by the underlying bytes.
Wrapping A value that wraps will roll around to the opposite end of its representable range on overflow or underflow, as if the highest representable value is directly followed by the lowest representable value.
Access A memory address or device port is accessed when it is read from or written to.
Implementation defined A value or behaviour that depends on the constraints or design of the underlying hardware or software. Implementations are free to choose any sensible value or behaviour. TODO: rework this at the end.
Undefined behaviour Behaviour that should not be triggered, can break the system / unstable / . Expected to never be triggered. A system is free to do anything at all, which could include corrupting data.
This section specifies the full architecture and instruction set of the Bedrock computer system. A system that implements this section will be able to correctly run all Bedrock programs. For useful operation, many programs will also require one or more devices to be implemented and connected to the device bus, which will allow programs to interact with users or other systems.
The program memory is an array of 65536 bytes that holds the current program. To load a program, set every byte of program memory to zero, set the stack and instruction pointers to zero, reset every device on the device bus to their initial states, and then copy each byte of the program into program memory starting from address zero, truncating the program to fit.
To read a double from program memory, read the high byte of the double from the given address and the low byte from the following address. To write a double to program memory, write the high byte of the double to the given address and the low byte to the following address. Reading or writing a double from address 0xFFFF will cause undefined behaviour.
Systems with fewer than 65536 bytes of program memory are partially supported. Accessing an unimplemented memory address will cause undefined behaviour.
A Bedrock system contains two stacks, called the working stack and the return stack. Each stack is an array of 256 bytes with an 8-bit stack pointer. The initial value of the pointer is zero. To push a byte to a stack, write the byte to the array address referenced by the pointer and then increment the pointer. To pop a byte from a stack, decrement the pointer and then return the byte at the referenced address. Overflowing or underflowing the stack pointer will cause undefined behaviour.
To push a double to a stack, first push the high byte of the double to the stack and then push the low byte. To pop a double from a stack, pop two bytes; the first byte popped is the low byte of the double and the second byte popped is the high byte.
Systems with fewer than 256 bytes of memory per stack are partially supported. Accessing an unimplemented memory address will cause undefined behaviour.
The device bus is an array of 256 ports, which are grouped into 16 slots. Each port is a channel for sending and receiving bytes from a connected device, and each slot is a contiguous group of 16 ports that can connect a single device to the system. Reading from a port will send a read request containing the port number to the connected device, pausing the system until the request has completed and then returning a byte from the device. Writing a byte to a port will send a write request containing the port number and byte to the connected device, pausing the system until the request has completed. If a request is sent to a port that isn’t currently connected to a device, the request will complete immediately, returning a value of zero if it was a read request.
To read a double from the device bus, first read the high byte of the double from the given port and then read the low byte from the following port. To write a double to the device bus, first write the high byte of the double to the given port and then write the low byte to the following port. Reading or writing a double from port 0xFF will cause undefined behaviour.
The first twelve slots of the device bus are reserved for a standard set of devices (see the device specifications). The final four slots of the device bus are reserved for implementation-defined devices (called auxiliary devices).
The processor executes the current program using a 16-bit instruction pointer. To execute the next instruction of the program, read a byte from the program memory address referenced by the instruction pointer, then increment the instruction pointer, and then execute the instruction represented by that byte. Overflowing the instruction pointer will cause undefined behaviour. To run the program, repeatedly execute the next instruction until the system halts.
The upper three bits of an instruction byte are the mode flags.
If bit 0x80 is set, swap the working stack and the return stack for the duration of this instruction.
If bit 0x40 is set, values listed without an explicit size for the operation will be doubles, otherwise bytes.
If bit 0x20 is set, the first value to be popped by this instruction will instead be read from the program memory address referenced by the instruction pointer, incrementing the pointer with each byte read.
The lower five bits of an instruction byte represent the operation to perform, as per the following list. WST means “working stack”, RST means “return stack”, IP means “instruction pointer”. Arithmetic wraps on overflow and underflow. All values are unsigned. Pushing and popping is to the working stack by default.
0x00 — Halt the system if no mode flag is set, otherwise do nothing.
0x01 — Pop x from RST, push x to WST.
0x02 — Pop x from WST.
0x03 — Pop x from RST, push x to RST, push x to WST.
0x04 — Pop x, push x, x.
0x05 — Pop y, x, push x, y, x.
0x06 — Pop y, x, push y, x.
0x07 — Pop z, y, x, push y, z, x.
0x08 — Pop double a, write a to IP.
0x09 — Pop double a, push IP to RST, write a to IP.
0x0A — Pop double a, pop t. If t is not zero, write a to IP.
0x0B — Pop double a, pop t. If t is not zero, push IP to RST, write a to IP.
0x0C — Pop double a, read v from memory address a, push v.
0x0D — Pop double a, pop v, write v to memory address a.
0x0E — Pop byte p, read v from device port p, push v.
0x0F — Pop byte p, pop v, write v to device port p.
0x10 — Pop y, x, push result of y plus x.
0x11 — Pop y, x, push result of y minus x.
0x12 — Pop x, push result of x plus 1.
0x13 — Pop x, push result of x minus 1.
0x14 — Pop y, x. If x is less than y, push byte 0xFF, else 0x00.
0x15 — Pop y, x. If x is greater than y, push byte 0xFF, else 0x00.
0x16 — Pop y, x. If x is equal to y, push byte 0xFF, else 0x00.
0x17 — Pop y, x, push x, y. If x is not equal to y, push byte 0xFF, else 0x00.
0x18 — Pop byte y, pop x, push result of x bitwise-shifted left by y bits.
0x19 — Pop byte y, pop x, push result of x bitwise-shifted right by y bits.
0x1A — Pop byte y, pop x, push result of x bitwise-rotated left by y bits.
0x1B — Pop byte y, pop x, push result of x bitwise-rotated right by y bits.
A source file is a sequence of characters, with each character being a single Unicode scalar value. To assemble a program, first prepend the pre-defined macros code block to the source file, then parse the source file as a sequence of tokens, convert each token to a sequence of bytes, and concatenate the sequences of bytes to create the assembled program. If the source file is invalid according to the rules of the assembler, no program will be created.
A token is a sequence of characters from the source file that represents a single language element. The address of a token is equal to the number of bytes preceding it in the assembled program.
To parse the source file as a sequence of tokens, iterate over the characters of the source file and collect them into tokens according to the following rules:
The characters U+0000 to U+0020 are ignored if no token is currently being parsed.
The characters ', ", or ( start a span token. Collect all characters up to and including the matching terminator, ending the token. The matching terminators for ', ", and ( are ', ", and ), respectively. The source file is invalid if a matching terminator is not found.
All other characters start a word token. If the character is ), [, ], {, }, ;, or :, no further characters are collected, ending the token. Otherwise, collect all characters up to and including the next :, or up to and excluding the next (, ), [, ], {, }, ;, or character in the range U+0000 to U+0020, or up to the end of the source file, whichever comes first, ending the token.
The first character of a token determines how it will be assembled into a sequence of bytes, as follows:
(, ), [, and ] denote a comment, which assembles to nothing. The source file is invalid if it contains a token starting with ).
{ and } denote an opening or closing block delimiter, respectively. A closing block delimiter matches the closest previous unmatched opening block delimiter, forming a matched pair. The opening delimiter assembles to a double with value equal to the address of the closing delimiter. The closing delimiter assembles to nothing. The source file is invalid if it contains an unmatched block delimiter, or if a delimiter inside a macro definition is matched with a delimiter outside that definition, or if the address of a closing delimiter is greater than 0xFFFF. The maximum nesting depth for blocks is implementation defined.
@ and & denote a global or local label definition, respectively. The remaining characters of the token are called the identifier. The name of a global label definition is given by the identifier. The name of a local label definition is given by the name of the most recent global label definition (or an empty string if none), followed by the / character (U+002F), followed by the identifier. A label definition assembles to nothing. The source file is invalid if a label definition shares a name with another label or macro definition, or if the name of a label definition is empty or longer than 63 characters, or if the address of a label definition is greater than 0xFFFF. The maximum number of label definitions supported by the assembler is implementation defined.
% and ; denote a macro definition or macro terminator, respectively. A macro definition matches the next macro terminator, and the sequence of tokens between the two is called the macro body. The name of a macro definition is given by the remaining characters of the macro definition token. The macro definition, macro body, and macro terminator each assemble to nothing. The source file is invalid if it contains an unmatched macro definition or macro terminator, or if a macro body contains a label or macro definition, or if a macro definition shares a name with another label or macro definition, or if the name of a macro definition is empty or longer than 63 characters. The maximum number of macro definitions supported by the assembler is implementation defined.
' and " denote a raw or terminated string, respectively. The remaining characters of the token, excluding the final character, are called the string content. A raw string assembles to the string content as a UTF-8 encoded byte sequence. A terminated string assembles to the string content as a UTF-8 encoded byte sequence, followed by a zero byte.
# denotes a padding element. The remaining characters of the token are called the pad value, and represent an integer value in hexadecimal. A padding element assembles to a sequence of zero bytes with length equal to this value. The source file is invalid if the pad value is not exactly two or four characters long, or if the pad value contains characters that don’t fall within the ranges 0 to 9, a to f, or A to F.
If the first character of a token is any other character, then the token is either a literal or a symbol:
A literal is exactly two or four characters long, where each character falls within the ranges 0 to 9, a to f, or A to F. The characters of the token represent an integer value in hexadecimal. A two or four character literal assembles to a byte or a double, respectively, with value equal to this value.
Any other token is a symbol. The name of a symbol is given by the characters of the token. If the name begins with the ~ character (U+007E), replace this character with the name of the most recent global label (or an empty string if none), followed by the / character (U+002F). If the name of a symbol matches the name of a previous or future label definition, it assembles to a double with value equal to the address of that label definition. If the name of a symbol is equal to the name of a previous macro definition, replace the token with a copy of the tokens in the associated macro body and assemble. The name of any symbol inside a macro body is determined when the macro definition is first parsed. The source file is invalid if the name of a symbol is longer than 63 characters, or if the name is not equal to the name of a label or macro definition, or if the name is equal to the name of a macro definition that comes after the symbol token in the source file.
This section specifies a format for embedding machine-readable metadata into a Bedrock program. This allows Bedrock programs to be automatically distinguished from other file types, and provides a method for systems to access basic program information.
The presence of the 10-byte marker sequence E8 00 18 42 45 44 52 4F 43 4B at the start of a file indicates that the file is a Bedrock program and that the following 14-byte section of the program represents a table of pointers to program metadata values. Each pointer in the table is a double representing the program address where a corresponding metadata element can be found. A pointer value of zero indicates that the corresponding element has not been provided.
The program identifier is a UTF-8 encoded string followed by a zero byte. The string contains the program name, followed by the / character (U+002F), followed by the program version. The program name and version must not contain the / character (U+002F) or any character in the range U+0000 to U+001F. The maximum length of the program identifier is 255 bytes, excluding the zero byte. The address of the program identifier is given by the double at address 0x000A.
The author list is a UTF-8 encoded string followed by a zero byte. The string is a concatenated list of the names of all program authors, with every name but the last followed by the newline character U+000A. The name of each author must not contain any character in the range U+0000 to U+001F. The maximum length of each name is 255 bytes, excluding the newline character and zero byte. The address of the author list is given by the double at address 0x000C.
The description is a UTF-8 encoded string followed by a zero byte. The string is a brief description that summarises the category and purpose of the program. The description must not contain any character in the range U+0000 to U+001F. The maximum length of the description is 255 bytes, excluding the zero byte. The address of the description is given by the double at address 0x000E.
The release date is a sequence of three bytes representing the date when this version of the program was authored. The first byte in the sequence represents the number of full years elapsed since the start of the year 2000, the second byte represents the number of full months elapsed since the start of the year, and the third byte represents the number of full days elapsed since the start of the month. The address of the release date is given by the double at address 0x0010.
The device list is a UTF-8 encoded string followed by a zero byte. The string is a concatenated list of the names of the auxiliary devices expected by this program, with every name but the last followed by the newline character U+000A. The name of each auxiliary device must not contain any character in the range U+0000 to U+001F. The maximum length of each name is 255 bytes, excluding the newline character and zero byte. The maximum number of names in the list is four. The order of names in the list represents the order in which the corresponding devices are expected to be connected to slots 0xC to 0xF of the device bus. The address of the device list is given by the double at address 0x0012.
The small icon is a sequence of 72 bytes representing a 24x24 pixel monochrome program icon. Each group of 8 bytes in the sequence represents an 8x8 pixel monochrome sprite, with sprites ordered left-to-right in rows of three, and rows ordered from top to bottom. Each byte in a sprite represents a row of eight pixels, with rows ordered top to bottom, and each bit represents a pixel in that row, ordered left to right from highest bit to lowest. Each set bit represents a pixel drawn using the foreground colour, and each unset bit using the background colour. The address of the small icon is given by the double at address 0x0014.
The large icon is a sequence of 512 bytes representing a 64x64 pixel monochrome program icon. Each group of 8 bytes in the sequence represents an 8x8 monochrome pixel sprite (as per the small icon description), with sprites ordered left-to-right in rows of eight, and rows ordered from top to bottom. The address of the large icon is given by the double at address 0x0016.
This section specifies the standard system device of the Bedrock computer system. This device connects to slot 0x0 of the device bus.
The system device provides access to information about the Bedrock system, and allows a program to sleep, fork, and reset the system. Implementions need to be able to query devices on the device bus for their name, connection state, and wake flag.
A device map is a 16-bit value that represents the 16 slots on the device bus. Each bit of a device map represents a slot on the device bus, ordered high to low.
A text buffer is an array of bytes with an associated pointer. The array contains a UTF-8 encoded string followed by a zero byte. The initial value of the pointer is zero, and the maximum value of the pointer is at least one greater than the address of the zero byte. Reading a byte from the text buffer will return the byte at the array address referenced by the pointer, and then the pointer will increment. Reading a byte when the value of the pointer is greater than the address of the zero byte will cause undefined behaviour. Restarting the text buffer will set the value of the pointer to zero.
This device contains six text buffers: a system identifier text buffer, a system authors text buffer, and a device name text buffer for each slot 0xC to 0xF on the device bus.
The system identifier text buffer contains a string that identifies this Bedrock system implementation. The string contains the implementation name, followed by the / character (U+002F), followed by the implementation version. The implementation name and version must not contain the / character (U+002F) or any character in the range U+0000 to U+001F. The maximum length of the string is 255 bytes.
The system authors text buffer contains a string that identifies the authors of this Bedrock system implementation. The string is a concatenated list of the names of the system authors, with every name but the last followed by the newline character U+000A. The name of each author must not contain any character in the range U+0000 to U+001F. The maximum length of each name is 255 bytes, and the maximum number of names in the list is 16.
Each device name text buffer contains a string that represents the name of the device currently connected to the corresponding slot. The string must not contain any character in the range U+0000 to U+001F. The maximum length of the string is 255 bytes. If no device is connected to the corresponding slot or if no device name is available, the string will be empty. Connecting or disconnecting a device from the slot will set the pointer of the text buffer to zero.
0x00–0x01 Writing to this port group will request that the system be put to sleep. Write access is atomic.
0x02 Reading from this port will return the slot number of the device that most recently woke the system from sleep. If the system has not yet been woken from sleep, the value returned will be 0x00.
0x03 Writing a non-zero value to this port will create a new Bedrock system instance, with separate core and devices to the current instance, and then the program memory of the current instance will be copied into the new instance. If a new instance cannot be created, the current instance will be reset as if a zero value had been written to this port. Writing a zero value to this port will reset this Bedrock system instance, by setting the instruction pointer and stack pointers to zero, leaving the program memory unmodified, and resetting all devices to their initial states.
0x04 This port is associated with the device name text buffer for slot 0xC. Reading from this port will read and return a byte from the associated text buffer. Writing any value to this port will set the pointer of the associated text buffer to zero.
0x05 This port is associated with the device name text buffer for slot 0xD. The behaviour is the same as for port 0x04.
0x06 This port is associated with the device name text buffer for slot 0xE. The behaviour is the same as for port 0x04.
0x07 This port is associated with the device name text buffer for slot 0xF. The behaviour is the same as for port 0x04.
0x08 This port is associated with the system identifier text buffer. The behaviour is the same as for port 0x04.
0x09 This port is associated with the system authors text buffer. The behaviour is the same as for port 0x04.
0x0A–0x0B Reading from this port group will return the number of bytes of program memory implemented on this system. If the number of bytes implemented is 65536, the value returned will be 0x0000.
0x0C This port is associated with the working stack of the Bedrock system. Reading from this port will return the number of bytes of memory implemented for the associated stack on this system. If the number of bytes implemented is 256, the value returned will be 0x00.
0x0D This port is associated with the return stack of the Bedrock system. The behaviour is the same as for port 0x0C.
0x0E–0x0F Reading from this port group returns a device map, where each bit of the map is set only if a device is connected to the corresponding slot on the device bus.
This device provides access to up to 16 megabytes of additional memory. The memory managed by this device uses a separate address space to the program memory.
Memory is allocated in 256-byte chunks, called pages, which form a contiguous array of bytes starting from memory address zero. Pages are allocated and deallocated from the end of this array. Accessing an unallocated memory address will cause undefined behaviour. When a page is allocated, the value of each byte on that page is zero. The initial number of pages allocated is zero, and the minimum and maximum numbers of pages that can be allocated are implementation defined.
Memory is accessed via two independent read-write heads (called head 1 and head 2). Each head contains an unsigned 16-bit page offset value and an unsigned 16-bit address offset value. The memory address that will be accessed by a given head is calculated by multiplying the page offset by 256 and then adding the address offset, causing undefined behaviour if the result exceeds the range of an unsigned 24-bit integer.
0x10–0x11 Reading from this port group will return the number of pages allocated. Writing to this port group will request that the number of pages allocated be changed to the value written. Pages will be sequentially allocated or deallocated until either the requested value or an implementation defined minimum or maximum value is reached. Write access is atomic.
0x12–0x13 This port group is associated with head 1. Reading from this port group will return the page offset of the associated head. Writing to this port group will set the page offset of the associated head to the value written.
0x14–0x15 This port group is associated with head 1. Reading from this port group will return the address offset of the associated head. Writing to this port group will set the address offset of the associated head to the value written.
0x16 This port is associated with head 1. Reading from this port will return the byte stored at the memory address referenced by the associated head, and then will increment the address offset of the associated head by 1, wrapping to zero on overflow.
0x17 This port is an alias for port 0x16.
0x18–0x19 Writing to this port group will request that a number of pages be copied equal to the value written. The initial source and destination page are given by the page offset value of head 2 and head 1, respectively. The contents of the source page will be copied into the destination page, the page following the source or destination page will become the new source or destination page, respectively, and the process will repeat until the requested number of pages has been copied. Copying to or from an unallocated page will cause undefined behaviour. Write access is atomic.
0x1A–0x1B This port group is associated with head 2. The behaviour is the same as for port group 0x12–0x13.
0x1C–0x1D This port group is associated with head 2. The behaviour is the same as for port group 0x14–0x15.
0x1E This port is associated with head 2. The behaviour is the same as for port 0x16.
Multiplication, division, and coordinate conversion operations are performed using a set of four unsigned 16-bit input values, called the x, y, r, and t operands. The initial value of each operand is zero.
The x and y operands represent a point in the cartesian coordinate system called the cartesian point. The x coordinate of this point is given by the x operand, and the y coordinate is given by the y operand. The x and y operands are treated as signed values for this purpose.
The r and t operands represent a point in the polar coordinate system called the polar point. The r coordinate of this point is given by the r operand, and the t coordinate is given by the t operand.
The cartesian coordinate system represents a point as the distance travelled from the origin along a horizontal axis and a vertical axis. A point is represented by an x coordinate, which gives the distance travelled along the horizontal axis as a signed 16-bit integer, and a y coordinate, which gives the distance travelled along the vertical axis as a signed 16-bit integer. The x and y coordinates of the origin are both zero.
The polar coordinate system represents a point as a radius measured between the origin and the point, and as an angle measured counter-clockwise around the origin from the positive horizontal axis to the point (starting towards the positive vertical axis). A point is represented by an r coordinate, which gives the length of the radius as an unsigned 16-bit integer, and a t coordinate, which gives the angle as an unsigned 16-bit integer. The r and t coordinates of the origin are both zero.
The distance units of the x, y, and r coordinates are all of equal length. The angle unit of the t coordinate is measured as one 65536th of a full turn. The origins of the two coordinate systems coincide.
Some points cannot be losslessly converted between coordinate systems. If either coordinate of a point would be fractional after conversion, that coordinate will instead be rounded down to the nearest integer (rounding towards zero). If either coordinate of a point would exceed the range of the type used to represent it after conversion (-32768 to 32767 inclusive for cartesian coordinates, 0 to 65535 inclusive for polar coordinates), a value of zero will be returned instead for both coordinates.
0x20–0x21 Reading from this port group will return the x coordinate of the polar point after conversion to the cartesian coordinate system. Writing to this port will set the value of the x operand to the value written.
0x22–0x23 Reading from this port group will return the y coordinate of the polar point after conversion to the cartesian coordinate system. Writing to this port will set the value of the y operand to the value written.
0x24–0x25 Reading from this port group will return the r coordinate of the cartesian point after conversion to the polar coordinate system. Writing to this port will set the value of the r operand to the value written.
0x26–0x27 Reading from this port group will return the t coordinate of the cartesian point after conversion to the polar coordinate system. Writing to this port will set the value of the t operand to the value written.
0x28–0x2B Reading from this port group will return the product of the x and y operands.
0x2C–0x2D Reading from this port group will return the quotient of the integer division of the x operand by the y operand. If the y operand is zero, the value returned will be zero.
0x2E–0x2F Reading from this port group will return the remainder of the integer division of the x operand by the y operand. If the y operand is zero, the value returned will be zero.
This device tracks the current date and time in the local timezone, with a resolution of one second.
The date and time can be set to a different value if supported by the host system. When writing to a port that would set a component of the date or time, the component associated with that port will be changed to the value written, with all other components left unchanged. Values which would exceed the maximum value of that component are ignored.
This device contains four identical countdown timers, called timers 1 through 4. The resolution of each timer is one 256th of a second, called a tick. Each timer is represented by an unsigned 16-bit integer, representing the number of ticks remaining until that timer expires. Each timer will decrement by one for every tick elapsed, stopping once zero is reached. A timer expires when the value transitions from one to zero in this manner. The initial value of each timer is zero.
0x30 Reading from this port will return the number of full years elapsed since the start of the year 2000. The value returned from the year 2256 onwards is implementation-defined. Writing to this port will attempt to set the year component of the date and time to the value written. The maximum value is 255.
0x31 Reading from this port will return the number of full months elapsed since the start of the year. Writing to this port will attempt to set the month component of the date and time to the value written. The maximum value is 11.
0x32 Reading from this port will return the number of full days elapsed since the start of the month. Writing to this port will attempt to set the day component of the date and time to the value written. The maximum value is 28 when the month component is 1 and the year component is evenly divisible by 4, otherwise is 27 when the month component is 1, otherwise is 29 when the month component is 3, 5, 8, or 10, otherwise is 30.
0x33 Reading from this port will return the number of full hours elapsed since the start of the day. Writing to this port will attempt to set the hour component of the date and time to the value written. The maximum value is 23.
0x34 Reading from this port will return the number of full minutes elapsed since the start of the hour. Writing to this port will attempt to set the minute component of the date and time to the value written. The maximum value is 59.
0x35 Reading from this port will return the number of full seconds elapsed since the start of the minute. Writing to this port will attempt to set the second component of the date and time to the value written. The maximum value is 59. The value during a leap second is implementation defined.
0x36–0x37 Reading from this port group will return the number of ticks elapsed since the system started or was last reset. The value will wrap on overflow. Read access is atomic.
0x38–0x39 This port group is associated with timer 1. Reading from this port group will return the number of ticks remaining until the associated timer expires. Writing to this port group will set the number of ticks remaining until the associated timer expires to the value written. Read and write access is atomic.
0x3A–0x3B This port group is associated with timer 2. The behaviour is the same as for port group 0x38–0x39.
0x3C–0x3D This port group is associated with timer 3. The behaviour is the same as for port group 0x38–0x39.
0x3E–0x3F This port group is associated with timer 4. The behaviour is the same as for port group 0x38–0x39.
This section specifies the standard stream device of the Bedrock computer system. This device connects to slot 0x8 of the device bus.
The stream device provides access to two bi-directional bytestream interfaces, one for communicating with a local system, and the other for connecting to a remote system via a network path. TODO