Hello HP fans,
I have been asked a couple
of time (ie: too many time for my taste to give information
about
the HP49 graphical toolbox).
So, here it is, in its totality (Eric, could you archive it and put it on your website please?)
Have fun! Cyrille de Brebisson (Officialy speaking for HP in this case :-)
http://hpmad.zoy.org
The Graphical toolbox is part of the Meta kernel
This graphical toolbox was written by CdB
This file contains a set of graphical primitives with Asm amd Sys-Rpl entry points.
Asm entry points are prefixed with 'a'. Sys-Rpl entry points are not prefixed.
This file contains the following entry points:
Line
Circle
Pixon
This entry points exists in different flavours:
Asm with the 'a' prefix or Sys-Rpl without prefix
For each of the entry points, 5 versions are provided. each of the has a sufix indicating the
type of operation:
W ( Draw white pixels )
B ( Draw black pixels )
G1 ( Draw a light gray pixel or a white
pixel for a W&B Grob )
G2 ( Draw a darck gray pixel or a black
pixel for a W&B grob )
Xor( Invert a pixel from White to Black,
from Black to white, from light gray
to light gray and from light gray to
dark gray )
An example of this entry point is 'aLineXor' that is the assembly entry point drawing an inverted circle.
The aGray? routine is also provided. It is mainly a subroutine of the other entry points, but
can be usefull for other applications
Gray? can help you know if you are working with
a gray scale grob.
All this functions can work indiferently on W&B or gray 2 bitplane gray scale graphics.But a grob should never excess 2048 pixels in either dimentions.
Distance, aDistance: Allow to compute the distance between two points.
Dither, aDither and ToGray allow to convert a grobs from W&B to from gray grobs.
Sub, Repl, Gor, Gxor, SubRepl, SubGor, SubGxor,aSubReplRepl, aSubReplGor and aSubReplGxor allows to perform
graphic sub, replace or in replace, OR and XOR modes.
GNeg and aGNeg allows to invert a grob
ScrollVGrob and aScroolVGrob allows to scroll verticaly a portion of a grob
Lift and aLift allow to display a lift at a position in a graphic (like in choose)
As said before, this functions can work eitheron W&B or gray scalle grob. Lets introduce the
graphical structur to explain all this.
a grob (W&B or Gray) has the following structur:
Prolog, Size, NbLines, NbCollumns, Datawhere the 4 firrst fields are 5 nibbles fields.
Data is a set of lines. from the top of the grob to the bottom. each line is a set of (X+7)/8*8
pixels (whatever the real width of the grob, internaly lines are always a multiple of 8 pixels
On a gray scale grob, following the first set of pixels (1 bit per pixel) you can find an other
bit plane of the same size then the previous one the 2 bitplane of a grob can produce up to 4
gray colors from white to black.
0 | 1 BitPlane 0
+----+----+
0 | W | G2 |
1 | G1 | B |
BitPlane1
Some test program are provided, they should not be compiled in the final version but should remain as commentary
For many of the graphical primitives, The same routine is used all the time, but a different Pixon routine is copied in IRAMBUFF
The _Prepx routine are used to copy the pixon routine in RAM. Note that to
decrease teh amount of used register by this routine, the code is charged in Cms using LC with
P=3. in order to have a readable code, the LC mnemonic is not used, but is replaced by the hex
opcode: 3x where x is the number of nibbles to load in C-1. at the end of the routine, C[34] is
loaded with 00. This means that this part of the Ca register is lost
All prep routines use Cms, D1 and carry.
at the end of the routine, Ca=Ca&00fff
Line Sys-Rpl toolbox
5 different calls
LineWDraw a White line
LineG1 Draw a light gray line
LineG2 Draw a dark gray line
LineBDraw a Black line
LineXor Invert a line
Input: 5: Grob (W&B or Gray)
4: # X1
3: # Y1
2: # X2
1: # Y2
Output: 1: Modified grob
Note: X1, Y1, X2, Y2 MUST be within the grob
Line asm toolbox
input: D0: @ grob
Aa: X1
Ba: X2
Ca: Y1
Da: Y2
All coordinates MUST be within the grob
Grob can not be bigger than 2048 pixels
5 different calls:
aLineWDraw a White line
aLineG1 Draw a light gray line
aLineG2 Draw a dark gray line
aLineBDraw a Black line
aLineXor Invert a line
Uses: Carry, P, RSTK2
D0 (Last pix Plane1)
D1 (Last pix plane2)
R3a: +/- Line Width
R4a: Plane length
Aa:-1
Ba: Dx
Da: Dy
Cw: Undefine
Cs: Pixel Mask
As: Undefine
Bs: Undefine
IRAMBUFF (50 nibbles)
All functions work either in W&B or gray scale
All functions are using standard bresenham algo
D0, D1 are pointing on the 2 bit plans.
During the process,
Aa=Pixel counter
Ba=DX
Da=Dy
Ca=Current error
D0: Pointer on bit plan 1
D1: Pointer on bit plan 2
Cs: Pixel mask
R3a: Line Width or - Line Width
R4a: Plan length
IRAMBUFF: Pixon routine
The same routine is used all the time, but
a different Pixon routine is copied in IRAMBUFF
for each type of line, and this routine is used
to affect the pixels. the _Prepx routine are used
to copy the pixon routine in RAM. Note that to
decrease teh amount of used register by this
routine, the code is charged in Cm using LC with
P=3. in order to have a readable code, the LC
mnemonic is not used, bu is replaced by the hex
opcode: 3x where x is the number of nibbles to
load in C-1. at the end of the routine, C[34] are
loaded with 00. This means the this part of the
Ca register is lost
Line Sys-Rpl toolbox
5 different calls
CircleW Draw a White circle
CircleG1 Draw a light gray circle
CircleG2 Draw a dark gray cirlce
CircleB Draw a Black cirlce
CircleXor Invert a cirlce
Input: 4: Grob (W&B or Gray)
3: # cx
2: # cy
1: # R
Output: 1: Modified grob
Note: the square containing the circle MUST stay
within -2048, 2048
Circle asm toolbox
input: D0: @ grob
Aa: Centre x
Ba: Centre y
Ca: Rayon
the circle must be in the -2047, 2047 square
Grob can not be bigger than 2048 pixels
5 different calls:
aCircleWDraw a White line
aCircleG1 Draw a light gray line
aCircleG2 Draw a dark gray line
aCircleBDraw a Black line
aCircleXor Invert a line
Uses: Carry, P, RSTK2
D0 (Last pix Plane1)
D1 (Last pix plane2)
R3a: +/- Line Width
R4a: Plane length
Cs: Pixel Mask
As: Undefine
Bs: Undefine
IRAMBUFF (50 nibbles)
All functions work either in W&B or gray scale
All functions are using standard bresenham algo
D0, D1 are pointing on the 2 bit plans.
During the process,
Am: 4*X Error
Bm: 4*Y Error
Cm: Error
Dm: 2* Radius
Ax: XCurrent
Bx: XMax (Grob Width)
Cx: YCurrent
Dx: YMax (Grob Height)
D0: Pointer on bit plan 1
D1: Pointer on bit plan 2
Cs: Pixel mask
R3a: Line Width or - Line Width
R4a: Plan length
IRAMBUFF: Pixon routine
The Bresenham algo is use to draw the circle.
The original Bresenham use to compute the circle
Only on 1/8 of the circle and draw the other part
using symetrie. Doing a full pixon is quite slow
with a saturn, so, we are using 8 times
bresenham to draw suxcecivly the 8 octants of
the circle. Am, Bm and Cm are use to store the
values needed by bresenam, Ax, Bx, Cx and Dx are
used to store the current pixel coordinates
and the grob dimention to perform the cliping.
D0, D1 and Cs are use to point on the current
pixel.
The same routine is used all the time, but
a different Pixon routine is copied in IRAMBUFF
for each type of line, and this routine is used
to affect the pixels. the _Prepx routine are used
to copy the pixon routine in RAM. Note that to
decrease teh amount of used register by this
routine, the code is charged in Cm using LC with
P=3. in order to have a readable code, the LC
mnemonic is not used, bu is replaced by the hex
opcode: 3x where x is the number of nibbles to
load in C-1. at the end of the routine, C[34] are
loaded with 00. This means the this part of the
Ca register is lost
Sys Rpl Sub
Purpose: Get a sub part of a grob
Input: 5: Grob
4: # X1
3: # Y1
2: # X2
1: # Y2
SUBGROB output: 1: Sub Grob
Sub output: 2: Sub Grob
1: True or false
( True if no cliping was nessecery
( else, False. In all cases, the
( result is a X2-X1, Y2-Y1 grob )
Work in Grey and W&B
Note: Cliping is done by the sub function.
a boolean is set if no cliping was used.
Note: The result grob is always a grob of size
abs(X2-X1)+1, abs(Y2-Y1)+1
Note: X1, Y1, X2, Y2 do not need to be sorted in
any way.
Sys Rpl Repl
Entry Name: Repl
Purpose: copy a grob in an other grob
Input: 4: Grob destination
3: grob source
2: # X
1: # Y
output: 1: modified grob
Work in Grey and W&B
Note: Cliping is done by the sub function.
Sys Rpl Gor
Purpose: copy a grob in an other grob in OR mode
Entry Name: Gor
Input: 4: Grob destination
3: grob source
2: # X
1: # Y
output: 1: modified grob
Work in Grey and W&B
Note: Cliping is done by the sub function.
Sys Rpl Gxor
Purpose: copy a grob in an other grob in Xor mode
Entry Name: Gxor
Input: 4: Grob destination
3: grob source
2: # X
1: # Y
output: 1: modified grob
Work in Grey and W&B
Note: Cliping is done by the sub function.
Sys Rpl SubRepl
Purpose: copy a piece of a grob somewhere in an
other grob in replace mode
Entry Name: SubRepl
Input: 8: Grob destination
7: grob source
6: # X Destination
5: # Y Destination
4: # X Source
3: # Y Source
2: # With of the subgrob to copy
1: # Height of the subgrob to copy
output: 1: modified grob
Work in Grey and W&B
Note: Cliping is done by the sub function.
Sys Rpl SubGor
Purpose: copy a piece of a grob somewhere in an
other grob in or mode
Entry Name: SubGor
Input: 8: Grob destination
7: grob source
6: # X Destination
5: # Y Destination
4: # X Source
3: # Y Source
2: # With of the subgrob to copy
1: # Height of the subgrob to copy
output: 1: modified grob
Work in Grey and W&B
Note: Cliping is done by the sub function.
Sys Rpl SubGxor
Purpose: copy a piece of a grob somewhere in an
other grob in XOR mode
Entry Name: SubGxor
Input: 8: Grob destination
7: grob source
6: # X Destination
5: # Y Destination
4: # X Source
3: # Y Source
2: # With of the subgrob to copy
1: # Height of the subgrob to copy
output: 1: modified grob
Work in Grey and W&B
Note: Cliping is done by the sub function.
Purpose: Copy a piece of a grob in an other grob
This can be use either to get a subgrob of a
grob, to display a grob on an other grob or to
copy a sub grob of a grob in a specific place in
a second grob.
This function perform the following operation:
Grob Destination
+-----------------+
| | Grob Source
| x1 |+-----------------+
| y1+-------+ || x2|
| | | || y2+--------+|
| | | || | width ||
| +-------+ || | X3|height
| || +--------+ Y3 |
+-----------------+| |
| |
+-----------------+
it will copy the selected part of source
Grob at the desireated position in the
destination grob.
All clipping operation are realised by the
routine itself.
Inputs:
D0: @ Source grob
D1: @ Destination grob
R0a: x1
R1a: x2
R2a: y1
R3a: y2
R4a: X3
Da: Y3
P=0, HEX
Like for a lot of this graphical functions,
a part of the routine is copied in IRAMBUFF
allowing to use the same function for 3 types
of graphic operartions:
REPL, GOR and GXOR.
aSubReplRepl copy from source to dest overwriting
on destination (Hiding previous data
aSubReplGor copy from source to dest performing
a graphical OR between the 2 grobs
aSubReplGxor copy from source to dest performing
a graphical XOR between the 2 grobs
The essensial part of the routine is to
initialize some internal values needed to
perform the operation. here is a description
of the notations used in the source explaining
what they are refering to.
Note: This notations are Case sensitive
Destination grob width and height: X1, Y1
position to display in destination grob: x1, y1
Nb Nibbles to pass after display in dest.: N1
Width of a line of dest grob: W1
Source grob width and height: X2, Y2
position to read from in source grob: x2, y2
Nb Nibbles to pass after reading from source: N2
Width of a line of source grob: W2
copied part width and height: X3, Y3
Nb nibbles to copy: N3
m1, m2: Start and ending masks
@1: @Of first pixel to modify in destaination
@2: @of first nible to read in source
Now, lets have a look to the variables init.
Y3= min(Y1-y1, Y2-y2, Y3);
X3= min(X1-x1, X2-x2, X3);
W1=(X1+7)/8*2 W2=(X2+7)/8*2
@1= @dest+W1*y1+x1/4
@2= @Source+W2*y2+x2/4
Shift=x1 4-x2 4
if Shift>0 then @2=@2-1 Shift= Shift-4
N3= (X3+X2 4+3)/4
N1= W1-N3
N2= W2-N2
m1= 2^(x1 4)-1
m2= not (2^((X3+x1) 4)-1)
Register usage while working:
Ds: m2
D14: m1
R0a: Destination second plan pointer
R1a: Source second plan pointer
R2a: N1
R3a: N2
R4a: N3
D0: @First pixel of source to display
D1: @First pixel of destination to display to
ST: [3,4]Shift
ST: [1] Second bitplane to work on?
Da, RSTK: Nb of lines to draw - 1
Register use:
Aw, Bw, Cw, Dw, D0, D1, R0a, R1a, R2a, R3a, R4a
ST0, ST1, ST2, ST3, RSTK2, P, Carry
Compute Address of first pixel to draw
Entry Name: ComputePixel
Input: R3a: Line Width ( Even, < 512 )
R4a: Plane Width
St=x fGray
Aa: X
Ca: Y
D0: @ First pixel
P=0, HEX
return: D0: @ Pixel, D1: @ Pixel plan 2
Cs: Pixel Mask
P=0, HEX
Uses: Cw, D0, D1, Carry, P, RSTK1
Is a grob a gray screen grob?
Entry Name: Grey?
Input: 1: Grob
Output: 1: TRUE if the grob is grey
Return informations on a graphic object
Entry Name: aGrey?
Input: D0: @ grob
P=0, HEX
Output: ST=0/1 fGray
0: Grob W&B
1: Grob Gray
R4a: Plane Length in nibbles
R3a: Line Width
D0: @ first pixel of the screen
uses: RSTK1, Ca, Carry, mp
SysRpl Neg Toolbox
Entry Name: INVGROB
Purpose: Invert a grob
Input: 1: Grob
Output: 1: Modified grob
Asm Neg Toolbox
Entry Name: aGNeg
Purpose: Invert a grob
Input: D0: @ of a grob
Output: Modified grob, R3, R4,
ST[fGray] as usual
Uses RSTK2, Aw, Ba, Ca, D0, R3a, R4a
carry, MP
Scrool Tool box
Purpose: Scrool up and down a portion of a graphical object.
Entry Name: ScrollVGrobj
+--------------------+
||
| X w |
|Yd+--------+|
| |||
|Ys+--------+^ |
| ||| |
| ||h |
| ||| |
| +--------+v |
||
+--------------------+
This entry point scrool an area of w*h pixels from the position X,Ys to
the
position X,Yd
Note: Yd and Ys can be in any order, allowing scrool up and down.
Note: the graphic is modify in place.
Note: cliping is performed by the function
Note: this function can scroll gray scale or non gray scale grobs
Input: 6: Grob
5: w
4: X
3: Yd
2: Ys
1: h
Output: 1: Modified grob
aScroolVGrob (The assembly version of the stuff)
input: R0a: h, R1a: Ys, R2a: Yd, R3a: X, R4a: w, D0: @ grob
Uses: Aa, Bas, Cw, Das, RSTK2, R3a, R4a, D0, D1
Compute sqrt(a^2+b^2)
Entry Name: aDistance
While working with circle, it may be intresting
to compute a distance from a point to an other.
This function allows to perform this operation.
Input: Aa: a, Ca: b
Output: Ca: Result
Uses A6, B6, C6, D6, P, Carry, SB
The computation of the squares is done as a
standard multiplication. The suare root is a
little more tricky.
The whole Sqrt algo is based on the following
relation.
sigma(x=0, x=n, x*2+1) = (n+1)^2
The base algo is just an iterative loop
substracting while possible the list of odd
number from the original value and dividing
the last odd number by two to have the result.
In order to speed up the algo for big numbers
some little modifications are used.
instead of trying every number from 1 to the
answer, we will first work by pack of 16. In
order to do it, we need to use the suite of the
square of (16*x), and try to grow x as far as
possible. then, we will grow 1 per one.
the suite of the square of (16*x) is given by
sigma(n=0, n=x, 512*n+256)
Uses RSTK1, Awp, Bwp, Cwp, Dwp, P, carry, SB, P
note: P=5 in the function
The Rpl version of this stuff exists, is called
Distance and takes 2 sb as input and pushes
one SB as result
Pixon Sys-Rpl toolbox
5 different calls
PixonWDraw a White pixel
PixonG1 Draw a light gray pixel
PixonG2 Draw a dark gray pixel
PixonBDraw a Black pixel
PixonXor Invert a pixel
Input: 3: Grob (W&B or Gray)
2: # X
1: # Y
Output: 1: Modified grob
Note: X, and Y MUST be within the grob
Pixon Assembly toolkit
The toolkit is a set of 5 functions:
aPixonW Clear a pixel from a grob
aPixonG1 Display a light gray pixel on the grob
aPixonG2 Display a dark gray pixel on the grob
aPixonB Display a black pixel on the grob
aPixonXor Inver a pixel of the grob
All this function can work either in W&B or in
gray scale. on a W&B graphic, aPixonG1 will draw
a White pixel, aPixonG2 will draw a Black one
Input: D0: @Grob
Aa: X
Ca: Y
P=0, HEX
Output: D0, D1: Bit Plane 1 and 2
Cs: Pixel Mask
P=0, HEX
R3a: Line Width
R4a: Bitplan length
Uses: RSTK2, Cw, D0, D1, Carry, SB, R3a, R4a, mp
Full Box Sys-Rpl toolbox
5 different calls
FBoxW (GROB!ZERO) Draw a White Square
FBoxG1 Draw a light gray Square
FBoxG2 Draw a dark gray Square
FBoxBDraw a Black Square
FBoxXor Invert a Square
Input: 5: Grob (W&B or Gray)
4: # X1
3: # Y1
2: # X2
1: # Y2
Output: 1: Modified grob
Note: cliping is performed by the function
Asm Full Box toolbox
The toolkit is a set of 5 functions:
aFBoxW Clear a rectangular array of the grob
aFBoxG1 Display a light gray square in the grob
aFBoxG2 Display a dark gray square in the grob
aFBoxB Display a black rectangle on the grob
aFBoxXor Invert a rectangle of the grob
All this function can work either in W&B or in
gray scale. on a W&B graphic, aFBoxG1 will draw
a White rectangle, aFBoxG2 will draw a Black one
Input: D0: @Grob
Aa: X1
Ba: Y1
Ca: X2
Da: Y2
P=0, HEX
Note cliping is performed by the function
Output: D0, D1: Bit Plane 1 and 2
Cs: Pixel Mask
P=0, HEX
R3a: Line Width
R4a: Bitplan length
Uses: RSTK2, Aw, Bw, Cw, Das, D0, D1, Carry,
SB, R3a, R4a, mp
Like Circle, and line, the same routine is used
for each type of box. Two functions copied in RAM
performing the 'desireated' operation.
This functions ar ealso used by LBox
The initialization is quite tricky here. Here is
an abstract.
The routine work on the line in 3 parts.
First, the start mask (saved in Bs) start the line
Then the big part by pack of 16 nibbles and WP
finish with the end mask, saved in Ds.
The init part has to compute the start and end
mask, and the number of full nibble to work on.
The start mask is easy. 4 - X1 4 gives the
number of pixels to tack care of.
Then, we have to work on 4-X1 4 pixels less
( Number of nibbles to work on saved in Ba )
then, we can compute the end mask using B 4.
A special case exists if we must work on only one
nibble.
Lite Box Sys-Rpl toolbox
5 different calls
LBoxWDraw a White rectangle
LBoxG1 Draw a light gray rectangle
LBoxG2 Draw a dark gray rectangle
LBoxBDraw a Black rectangle
LBoxXor Invert a rectangle
Input: 5: Grob (W&B or Gray)
4: # X1
3: # Y1
2: # X2
1: # Y2
Output: 1: Modified grob
Note: cliping is performed by the function
Asm Lite Box toolbox
This function is realy similar to FBox
The differents stand in the fact that FBox
function display a filled Box while this one
display only the 4 lines of the border.
The toolkit is a set of 5 functions:
aLBoxW Clear a rectangle shape in the grob
aLBoxG1 Display a light gray square in the grob
aLBoxG2 Display a dark gray square in the grob
aLBoxB Display a black rectangle on the grob
aLBoxXor Invert a rectangle of the grob
All this function can work either in W&B or in
gray scale. on a W&B graphic, aFBoxG1 will draw
a White rectangle, aFBoxG2 will draw a Black one
Input: D0: @Grob
Aa: X1
Aa: X2
Ca: Y1
Ca: Y2
P=0, HEX
Output: D0, D1: Bit Plane 1 and 2
Cs: Pixel Mask
P=0, HEX
R3a: Line Width
R4a: Bitplan length
Uses: RSTK2, Aw, Bw, Cw, Das, D0, D1, Carry,
SB, R3a, R4a, mp
Like Circle, and line, the same routine is used
for each type of box. Two functions copied in RAM
performing the 'desireated' operation.
This functions ar ealso used by LBox
The initialization is quite tricky here. Here is
an abstract.
The routine work on the line in 3 parts.
First, the start mask (saved in Bs) start the line
Then the big part by pack of 16 nibbles and WP
finish with the end mask, saved in Ds.
The init part has to compute the start and end
mask, and the number of full nibble to work on.
The start mask is easy. 4 - X1 4 gives the
number of pixels to tack care of.
Then, we have to work on 4-X1 4 pixels less
( Number of nibbles to work on saved in Ba )
then, we can compute the end mask using B 4.
A special case exists if we must work on only one
nibble.
Arrows function
Purpose: Draws up to four arrows at four
positions in a grob depending on 4 flags
used do signal that an object may be scroll
Use: D1, Aa, Ba, Ca, Da, ST0-7 P, RSTK2
input: ST4, ST5, ST6, ST7: arrows up, down, left,
right, ST9: normal font / mini font
(change from big arrow to small arrow)
D0:@ Grob
R0: X1, R1: Y1, R2: X2, R2: Y2
Dither Tool Box
This tool functions allows you to convert
a grey scale grob into a W&B grob and a W&B
into a Grey scale one.
the functions Dither, aDither and ToGray are
provided.
This functions may take a W&B or gray grob.
In order to 'Dither' a grob, a tidling mask
is used to create gray effects in W&B.
This mask are aplied using logical operations
Dither takes a gray scale grob as an argument
and gives back a W&B grob.
aDither inputs:
R4a: BitPlane size
R3a: Line width
D0: Grob Source ( on the 1st pixel )
D1: Grob destination ( on the 1st pixel )
Ca: Nb lines.
Output: A modified grob
Uses: Aw, Bw, Cw, Da, D0, D1, Carry, RSTK2
Lift tool Box (or scroll bar)
Purpose: Display a lift at a position (or a scroll bar if you prefear)
Inside Tips
The height of the lift box representing the current window is equal to
Yh=Gh*H/N where Gh is the graphical height, H is the window Height and
N is the number of elements in the list
The Y position of the current window is equal to
Yc=P/(N-H+1)*(Gh-Yh) where P is the current pos
Input: 7: Grob
6: Current Window top element
5: Nb elements in list
4: Nb elements in window
3: Graphical X
2: Graphical Y
1: Lift Height
Output: 1: Grob
|