catto@bach.ecn.purdue.edu (Erin S Catto) (05/29/91)
I am just posting the document below; I have nothing to do with its
contents. All stated below is good for Super Chip.
This document is also a good starting point to learn chip programming.
----------------------------------------------------------------------
Chipper V1.12 is a simple assembler for the HP48SX Chip-8 language.
Written by Christian Egeberg (egeberg@solan.unit.no) 2/11 .. 7/11-'90,
using Turbo Pascal V5.5, and Turbo Debugger V2.0 in 386 virtual mode.
In order to use Chipper V1.12 you need the following:
* An IBM compatible PC, preferably with 512k or more.
* A Hewlett Packard 48SX Calculator.
* A PC to HP48SX serial cable.
* A Kermit compatible PC based communication program.
* The CHIP-48 interpreter for HP48SX.
CHIP-48 is a video game language interpreter written by Andreas Gustafsson
(gson@niksula.hut.fi). It utilizes the original CHIP-8 instruction set
commonly used by RCA CDP1802 based home computers in the late 1970's.
CHIP-48 should be available by anonymous ftp from vega.hut.fi, directory
/pub/misc/hp48sx/asap.
CHIP-48 programs have access to 4k bytes of memory, addressed from #000 to
#FFF. The programs start at address #200, because of the memory requirements
of the original CHIP-8 interpreter. Instructions are 16 bits long and start
at even memory locations.
CHIP-48 has 16 general registers, named V0, V1, V2, ... , VE, VF. These are
8 bits wide. The VF register works as carry flag and collision indicator,
and is modified by certain instructions. A 16 bit I register also exists.
The lower 12 bits of this register are typically used as a memory pointer.
A delay timer and a sound timer is provided as well. These are 8 bits wide
and decrement around 60 times per second, until a value of 0 is reached.
The HP48SX beeper will buzz until the sound timer reaches 0.
CHIP-48 screen resolution is 64 pixels horisontal and 32 pixels vertical.
Screen origin is the upper left corner. A sprite is 8 pixels wide and from 1
to 15 pixels high. That is also from 1 to 15 bytes large. Upper row in the
first byte, leftmost pixel in the most significant bit. Sprites are XOR-ed
onto the background. If this causes any pixel to be erased, VF is set to
#01, else VF will be #00.
CHIP-48 programs may access 16 keys numbered from #0 to #F. The HP48SX
keyboard mapping is shown below:
( 7 ) -> #1 ( 8 ) -> #2 ( 9 ) -> #3 ( / ) -> #C
( 4 ) -> #4 ( 5 ) -> #5 ( 6 ) -> #6 ( * ) -> #D
( 1 ) -> #7 ( 2 ) -> #8 ( 3 ) -> #9 ( - ) -> #E
( 0 ) -> #A ( . ) -> #0 ( _ ) -> #B ( + ) -> #F
The following table contains valid CHIP-48 instruction codes and their
syntax in Chipper V1.12. NNN indicates a 12 bit address. KK is an 8 bit
constant. X and Y denote 4 bit register numbers. Hexadecimal characters
represent themselves. WordExpr means an expression resulting in a 16 bit
constant. AddrExpr is an expression resulting in a 12 bit address. ByteExpr
results in an 8 bit constant, NibbleExpr makes a 4 bit constant, and Expr is
a general expression. Char is an ASCII character. String is a sequence of
ASCII characters. Text in curly brackets is optional. Instruction codes are
written most significant byte first, least significant byte last.
#0NNN SYS AddrExpr ; Call 1802 code at NNN (not HP48SX)
#00E0 CLS ; Clear display
#00EE RET ; Return from subroutine (16 levels)
#1NNN JP AddrExpr ; Jump to NNN
#2NNN CALL AddrExpr ; Call subroutine at NNN (16 levels)
#3XKK SE VX, ByteExpr ; Skip next instruction if VX = KK
#4XKK SNE VX, ByteExpr ; Skip next instruction if VX <> KK
#5XY0 SE VX, VY ; Skip next instruction if VX = VY
#6XKK LD VX, ByteExpr ; VX := KK
#7XKK ADD VX, ByteExpr ; VX := VX + KK
#8XY0 LD VX, VY ; VX := VY, VF updates
#8XY1 OR VX, VY ; VX := VX OR VY, VF updates
#8XY2 AND VX, VY ; VX := VX AND VY, VF updates
#8XY3 XOR VX, VY ; VX := VX XOR VY, VF updates
#8XY4 ADD VX, VY ; VX := VX + VY, VF := carry
#8XY5 SUB VX, VY ; VX := VX - VY, VF := NOT borrow
#8XY6 SHR VX {, VY} ; VX := VX SHR 1, VF := carry
#8XY7 SUBN VX, VY ; VX := VY - VX, VF := NOT borrow
#8XYE SHL VX {, VY} ; VX := VX SHL 1, VF := carry
#9XY0 SNE VX, VY ; Skip next instruction if VX <> VY
#ANNN LD I, AddrExpr ; I := NNN
#BNNN JP V0, AddrExpr ; Jump to NNN + V0
#CXKK RND VX , ByteExpr ; VX := random AND KK
#DXYN DRW VX, VY, NibbleExpr ; Draw N byte sprite from [I] at VX, VY
; ... VF := collision
#EX9E SKP VX ; Skip next instruction if key VX down
#EXA1 SKNP VX ; Skip next instruction if key VX up
#FX07 LD VX, DT ; VX := delaytimer
#FX0A LD VX, K ; VX := key, wait for keypress
#FX15 LD DT, VX ; Delaytimer := VX
#FX18 LD ST, VX ; Soundtimer := VX
#FX1E ADD I, VX ; I := I + VX
#FX29 LD F, VX ; Point I to 5 byte sprite char for VX
#FX33 LD B, VX ; Store BCD of VX in [I], [I+1], [I+2]
#FX55 LD [I], VX ; Store V0 .. VX in [I] .. [I+X]
#FX65 LD VX, [I] ; Read V0 .. VX from [I] .. [I+X]
Additional Chipper V1.12 directives are:
SYMBOL = Expr ; Assign value to symbol
SYMBOL EQU Expr ; Assign value to symbol
DB ByteExpr {, ...} ; Define byte(s) at current address
DW WordExpr {, ...} ; Define word(s) at current address
DA String ; Define string at current address
DS ByteExpr ; Define ByteExpr uninitialized
; ... bytes at current address
ORG AddrExpr ; Set current address to AddrExpr
END ; This directive is ignored
INCLUDE SourceFileName ; Includes one more sourcefile
Chipper V1.12 accepts one label, or symbol, per line of source. This should
start with an alphabetic character, and not contain non alphanumeric
characters, otherwise the expression parser may get a bit confused. All
symbols will be converted to upper case, and may be prefixed by an
underscore character and / or suffixed by a colon. These will be stripped
off before the symbol is used. Each symbol contains a 32 bit signed integer
value, set to current address, unless defined by the = or EQU directives.
A symbol name or string containing lower case characters or non alphanumeric
characters (not in symbol names, I have told you that), should be contained
within apostrophes. Two apostrophes following eachother will produce one
resultant apostrophe. Some string examples:
'11/6-'68' ; Is an unterminated string starting with 11/6-68
11/6-''68 ; Evaluates to 11/6-'68
Christian Egeberg ; Evaluates to CHRISTIAN EGEBERG
'Christian Egeberg' ; Evaluates to Christian Egeberg
This, is a test ; Evaluates to THIS
; ... and IS A TEST
This',' is a test ; Evaluates to THIS, IS A TEST
'This, is a test' ; Evaluates to This, is a test
'''' ; Evaluates to '''
'' ; Evaluates to '
A symbol primitive may be one of the following:
SymbolName ; for instance LOOP
DecimalValue ; for instance 1106
#HexadecimalValue ; for instance #452
$BinaryValue ; for instance $10001010010
@OctalValue ; for instance @2122
"Character ; for instance "'c'
? ; This is always assigned to current address
An expression may consist of symbol primitives and the following operators.
Horisontal lines denote different priorities. Operators sharing priority
level are evaluated left to right:
( ; Start parentheses expression
) ; End of parentheses expression
-----------------------------------
+ ; Unary plus sign
- ; Unary minus sign
~ ; Bitwise NOT operator
-----------------------------------
! ; Power of operator
< ; Shift left number of bits
> ; Shift right number of bits
-----------------------------------
* ; Multiply
/ ; Divide
-----------------------------------
+ ; Add
- ; Subtract
-----------------------------------
& ; Bitwise AND operator
| ; Bitwise OR operator
^ ; Bitwise XOR operator
-----------------------------------
\ ; Low priority divide
% ; Modulus operator
Some expression examples:
(? + 15 \ 16) * 16 ; Is a paragraph (16 bytes) alignment
"'c' + @2 % #20 ; Resolves to 5
-3 * -( -7 + ~3) ; Resolves to -33
-3 * -( -7 + ~3) & #FF ; Resolves to 223
( 2 + 1 )! 2 ^ $1101 > 2 ; Resolves to 10
(2+1)!2^$1101>2 ; Resolves to 10
TABLESTART + 4 * ITEMSIZE ; Resolves
Remarks are prefixed by semicolons, as in the above examples. Note that
Chipper V1.12 performs a word alignment after every line of source code.
This means that for instance two single parameter DB directives in rapid
succession will have an uninitialized separator byte between them. Avoid
this by defining any multiple of two bytes per DB directive.
A note concerning the CHIP-48 instruction set. The LD VX, [I] and LD [I], VX
instructions will change the value of the I register if VX is different from
V0. Actually, I think it is set to the address of the last byte / register
read or written. This may lead to rather obscure bugs. It took me a day's
worth of debugging to figure out why Blinky died, moving upwards on the
second screen, after updating a 16 bit score counter in memory... I had
overwritten the first byte of the Blinky facing up sprite definition, and
thus caused a collision detect.
Chipper V1.12 fatal error messages:
No source file found ; Incorrect source file name
Unable to open file ; Disk problem, no write access
Outside legal address range ; Current address outside #200 .. #FFF
Chipper V1.12 warning messages:
Incorrect number of parameters ; Too few or too many parameters
No directive found ; Two symbols defined on same line
No symbol associated ; = or EQU without a symbol
Attempt to redefine existing symbol ; Symbol already exists, discarded
Badly defined parameter ; Undefined symbol or bad syntax
; ... in expression
Parameter out of range ; Value too large or too small
Register not found ; Register operand expected
Illegal register ; Different register required
Internal data structure mismatch ; C. Egeberg is a lousy programmer
Chipper V1.12 should be invoked with:
CHIPPER sourcefilename destinationfilename listfilename
or just:
CHIPPER
which will prompt for filenames. Default file extensions are .CHP, nothing
and .LST. Destination and listfiles will by default be named after source.
The destination file is a binary download mode HP48SX string. Kermit it to
the calculator, put the string on the stack, and run CHIP-48. The listfile
will contain all errors and warnings, hexdump of all generated instructions,
and a complete symboltable. The format is rather simple.
This document contains some information more or less copied directly off
the CHIP-48 documentation by Andreas Gustafsson, who has done a great job,
hacking for the HP48SX. The Chipper V1.12 syntax was inspired by the
SYZYGY game listing posted to comp.sys.handhelds by Roy Trevino. SYZYGY
is the best CHIP-48 game so far...
CHIP-48 is (C) Copyright 1990 Andreas Gustafsson.
Chipper is (C) Copyright 1990 Christian Egeberg.
Noncommercial distribution allowed, provided that copyright messages
are preserved, and any modified versions are clearly marked as such.
CHIP-48 and, because of that, programs written in Chipper make use of
undocumented low-level features of the HP48SX calculator. They may or
may not cause loss of data, excessive battery drainage, and / or
damage to the calculator hardware. The authors take no responsibility
whatsoever for any damage caused by the use of these programs.
Chipper does all its I/O on the PC through the Turbo Pascal FExpand(),
Assign(), ReSet(), ReWrite(), Read(), Write(), Eof() and Close() run
time library functions, but the author takes no responsibility for
loss of data, damage to any PC hardware, nor strange incidents caused
by the use of this program.
This software is provided "as is" and without any express or implied
warranties, including, but not limited to, the implied warranties of
merchantability and fitness for a particular purpose.