-
Notifications
You must be signed in to change notification settings - Fork 0
Pictures
A picture in DHRLIB is a sequence of drawing commands encoded as a bitstream. Conditional assembly controls availability of some picture related commands.
| Command | _pics<2 |
_pics=2 |
_pics=3 |
|---|---|---|---|
&DRAW |
✔ | ✔ | |
&REC |
✔ | ||
&SCAN |
✔ | ||
&STOP |
✔ | ||
&END |
✔ | ||
&SEEKG |
✔ | ✔ | |
&SEEKP |
✔ | ||
&TELLG |
✔ | ✔ | |
&TELLP |
✔ |
You can record a sequence of drawing commands for later rendering as follows.
- Issue
&SEEKP(<addr>,0) - Issue
&RECto start recording - Issue any of the basic drawing commands
- Issue
&ENDto flush and write the end of drawing marker - Issue
&STOPto stop recording - Issue
&TELLP(<end>,<bit>,<count>)to get the statistics
Here,
-
<addr>is the address where the drawing is stored -
<end>is a real variable that receives the ending address -
<bit>is a real variable that receives the unused bit count -
<count>receives the number of commands in the drawing, not counting the end-of-drawing marker
The picture can be saved for playback later as follows:
10 REM A0=picture address
20 REM suppose we have just finished recording
30 &TELLP(A1,BIT,CNT)
40 L = A1 - A0 + 2
50 PRINT CHR$(4);"BSAVE PIC1,A";A0;",L";LIf you are interested in saving a byte, you can use the more exact length calculation:
40 L = INT((8*(A1-A0) + 8 - BIT + 3 + 7)/8)Here, the bit offset and 3-bit end of picture marker are explicitly accounted for. The "7" causes the expression to round up.
Basic playback is as follows:
- Issue
&SEEKG(<addr>,0) - Issue
&DRAW AT <x>,<y>
Here, <addr> is an expression with the address of the drawing, while <x> and <y> are expressions with horizontal and vertical offsets.
You can also playback a subset of the drawing commands:
- Issue
&SEEKG(<addr>,<skip>) - Issue
&DRAW <count> AT <x>,<y>
Here, <skip> is an expression with the number of commands to skip from the beginning, and <count> is the number of commands to draw.
The following replaces commands 100 and beyond of the drawing at $6000, with commands 50-150 of the drawing at $7000.
BLOAD PIC1,A$6000
BLOAD PIC2,A$7000
&SEEKG(7*4096,50)
&SEEKP(6*4096,100)
&REC: &DRAW 100 AT 0,0: &END: &STOPThe following inserts the drawing at $7000 at position 50 in the drawing at $6000. It uses scratch space at $8000.
BLOAD PIC1,A$6000
BLOAD PIC2,A$7000
REM first copy tail to scratch
SEEKG(6*4096,50)
SEEKP(8*4096,0)
&REC: &DRAW AT 0,0: &END: &STOP
REM now copy both segments in turn
&SEEKP(6*4096,50): &REC
&SEEKG(7*4096,0)
&DRAW AT 0,0
&SEEKG(8*4096,0)
&DRAW AT 0,0
&END: &STOPIn the above examples, drawing commands are displayed and recorded at the same time. Scan mode suppresses drawing while still allowing recording. Using scan mode is simple, just issue &SCAN. The &STOP command cancels both recording and scanning. Here is the overwrite tail example using scan mode:
BLOAD PIC1,A$6000
BLOAD PIC2,A$7000
&SEEKG(7*4096,50)
&SEEKP(6*4096,100)
&REC: &SCAN: &DRAW 100 AT 0,0: &END: &STOPThis can be much faster since nothing has to be drawn.
You can modify a picture in place provided the old operations are replaced with new operations of the same length, e.g.
&SEEKG(A0,5)
&SEEKP(A0,5)
&REC: &SCAN: &DRAW 5 AT -8,0
GOSUB 1000: REM flush subroutine
&STOPThis performs an 8 pixel shift of everything associated with operations 5 through 9.
N.b. it is important to flush the stream. Normally we use &END, but here we do not actually want to end the drawing.
A subroutine that can be used in this situation is
1000 REM flush without ending
1001 &DRAW 1 AT 0,0: REM flushes as long as there are more operations
1001 L = PEEK(249): L = L - 8*INT(L/8): REM get last opcode
1002 IF L = 0 THEN &END: REM there were no more operations
1003 RETURN- The
&DRAWcommand is stateful, specifically cursor, color and mode comprise a state.- generally the state should be set first in any drawing
- splicing in a way that interrupts cursor state will lead to unexpected results
- Get the end of picture pointer using
&SEEKG(<addr>,-1)followed by&TELLG. - Get the last drawing op-code by taking the remainder of
peek(249)/8. - Get a screen address using
&MOVEfollowed bypeek(38) + peek(39)*256 + peek(229). Ifpeek(49180)>127the address is in auxiliary memory. - You can issue
&MODEduring recording, only the XOR bit is recorded. Playback will not affect any other status bits.- However,
&MODE=128will clear the recording bit, you probably want&MODE=192 - This will also erase the information about the last drawing op-code (but not the command itself)
- However,
- When translating a color drawing horizontally, best results are obtained by using specific increments
- increment of 4 preserves edges of solid colors
- increment of 8 preserves edges of dither patterns
- increment of 7 preserves byte alignment within the screen buffer
- use common multiples of two or more to satisfy simultaneous conditions
-
&DRAWis not recursive. Issuing&DRAWwhile recording merely copies all the commands from one drawing into another. -
&HPLOTfollowed by&HPLOT TOrenders the first pixel twice, which in XOR mode leaves it unchanged. Using&MOVEis an alternative.
| Operation | Code | Arguments | Total Bits |
|---|---|---|---|
| End | 000 | none | 3 |
| Color | 001 | dither pattern (16) | 19 |
| XOR | 010 | state (1) | 4 |
| Cursor | 011 | x (10), y (8) | 21 |
| Plot | 100 | x (10), y (8) | 21 |
| LineTo | 101 | x (10), y (8) | 21 |
| Trapezoid | 110 | x0 (10), x1 (10), x2 (10), x3 (10), y0 (8), y1 (8) | 59 |
| Stroke | 111 | x (10), y(8), brush (3) | 24 |