Sources are available on github. This library provides a C function (setpa) that allows us to set a pixel on the C+4 DFLI screen (2 free colors in each 4x2 matrix, and additional 2 free colors for each raster line). For example, the next C-code (file test.c and VSIZE=280) generates the out1.prg file that will generate the following image on the C+4.
This C function can help to draw the static image that can be used as the background. There are also two auxilary functions that can help easier use 2x2 tiles:
The assembly library can help to create some dynamics. It provides several functions (tobasic, setp, seta, setpbyte, getpbyte, getabyte, ...) and features (vertical scrolling and the timer). Just include your code after the main label in the svn.asm file.
The tobasic function returns to Basic, after calling to this function you can call other functions, for example to print characters or check the keyboard status. The actual return to Basic happens when the RTS instruction is executed, e.g. the next code illustrates the trick.
The setp function sets one pixel. The X register must contain the X coordinate, the Y register must contain the low byte of the Y coordinate, the high byte must be at $d8. However if the screen height is less than or equal to 256 then the high byte is ignored. The screen size is set by the VSIZE variable in the svn.asm source file. The A register must contain the color source. There are 4 color sources available:
The seta function sets an attribute for pixels. The A register must contain the color source. This value must be set immediately before the function call because the function uses the Z flag. The X register must contain the X coordinate, the Y register must contain the low byte of the Y coordinate, the high byte must be in $d8. If the screen height is less than or equal to 256 then the high byte is ignored. If A=1 or A=2 the lowest bit of Y and the two lowest bits of X are ignored. The $d9 memory location must contain the color code, for example, $05 for the dark green. The color codes may be taken from this page. If the multicolor is set then the X coordinate is completely ignored because the C+4 hardware only allows us to use 2 multicolors per line. If the background or foreground color is set then the change applies to the entire 4x2 matrix. So, for instance pixels with coordinates in the range (0,0)-(3,1) will have one background and one foreground color.
The setpbyte function sets 4 pixels at once. The X register must contain the X coordinate (the 2 lowest bits are ignored), the Y register must contain the low byte of the Y coordinate, the high byte must be at $d8. If the screen height is less than or equal to 256 then the high byte is ignored. The A register must contain a byte that is a sequence of 4 color sources.
The getpbyte function returns 4 sequential pixel color sources in A. The X register must contain the X coordinate (the 2 lowest bits are ignored), the Y register must contain the low byte of the Y coordinate, the high byte must be at $d8. If the screen height is less than or equal to 256 then the high byte is ignored.
The getabyte function returns attribute information for pixels. The A register must contain the color source. This value must be set immediately before the function call because the function uses the Z flag. The X register must contain the X coordinate, it is ignored if A==0 or A==3, also if A==1 or A==2 then the 2 lowest bits are ignored. The Y register must contain the low byte of the Y coordinate, the high byte must be at $d8. If the screen height is less than or equal to 256 then the high byte is ignored. Also, if A==1 or A==2 then the lowest bit of Y is ignored. The function returns the attribute information via two addresses. The value at the ($d0),Y address contains multicolor #1 if A==0, multicolor #2 if A==3, the luminance byte if A==1 or A==2. The color byte is at the ($d2),Y address if A==1 or A==2. This function may also be used to set or copy attributes. The color byte upper nible is the foreground color (color source 2), and the lower nible is the background (color source 1). The luminance byte upper nible is the background luminance, and the lower nible is the foreground.
Function getpaddr returns the address of the pixel byte in $d0-d1 for the coordinates given. The X register must contain the X coordinate (the 2 lowest bits are ignored), the Y register must contain the low byte of the Y coordinate, the high byte must be at $d8. If the screen height is less than or equal to 256 then the high byte is ignored. So getpbyte is defined the next way.
Function getnextx returns the address of the next pixel byte in $d0-d1 for the previous address (in $d0-d1) and coordinates given. The X register must contain the X coordinate (the 2 lowest bits must be 0), the Y register must contain the low byte of the Y coordinate, the high byte must be at $d8. If the screen height is less than or equal to 256 then the high byte is ignored. This function is faster than getpaddr. It is very useful when the next byte of bitmap is required.
Function setmcl sets both multicolors given in $d9 (for the 1st), $da (for the second) for the line. The Y register must contain the low byte of the Y coordinate, the high byte must be at $d8. If the screen height is less than or equal to 256 then the high byte is ignored.
The 50/60 Hz timer is available at memory locations $a4-$a5, where $a5 is the low byte. The frequency is set by the PAL or NTSC hardware. If you want to check when the first visible line appears use code similar to the next for this.
Memory location $d4 contains the vertical scroll value. A positive number scrolls down, a negative number scrolls up. If a value is set there, the screen will scroll once. When the scrolling action is completed this value is set to 0. So set this value only if it is equal to 0. Beware of using too large values, this may cause the displayed image to break! (Moreover use even values because odd values can create the PAL inversion color effects.)
The library routines use memory locations in the range $d0-$da, don't use these addresses.
You can use this type over upto the 80x128 cell background. Change VSIZE to get other heights. The minimal VSIZE is 200 and this is two times faster than for the maximum 256. The background consists of 2x2 cells and every cell can have any color. The bitmap is fixed to $A5 pattern for each byte. So the first 2x2 part color is fore and the second one is back. Somehow this gets the old Apple Macintosh A5-world! The sprite consists of individual pixels and it can have almost any size! However the only two colors are allowed in a sprite line. If two sprites occupy the same line there will be the color clash. The latter sprite supresses colors of the previous sprites. You can mix the type 1 with the type 2. Four colors are allowed for each line: transparent (0), multicolor 1, multicolor 2, and extra (3). The extra color just uses another color from the background 4x2 matrix. So it can be called a shifted transparency.
Use macro sprite_t1 to define a sprite. Its arguments are identifier, width (must be the multiple of 4), the x-coordinate, the y-coordinate, the number of datasets for the left, right, up, and down movements. For example, the next code defines the 8x2 sprite s3 that is placed at (81, 198)-coordinates and has only one dataset for all the movements. So this sprite is unanimated.
Use functions left_t1, right_t1, up_t1, and down_t1 to move a sprite. You must put_t1 your sprite. There is also the remove_t1 sprite function. Just set your sprite definition address to the $e6-e7 zp-locations before the function invocations. There are also functions left2_t1, right2_t1, up2_t1, and down2_t1 that move a sprite by two pixels. For example, to move a sprite to the specified location use code similar to the next.
This library uses zp-locations $e2-e7.
You can use this type over upto the 80x128 cell background. Change VSIZE to get other heights. The minimal VSIZE is 200 and this is two times faster than for the maximum 256. The background consists of 2x2 cells and every cell can have any color. The bitmap is fixed to $A5 pattern for each byte. So the first 2x2 part color is fore and the second one is back. Somehow this gets the old Apple Macintosh A5-world! The sprite consists of 2x2 pixel tiles too and it can have almost any size! You can mix the type 1 with the type 2. The color 0 means the transparency.
Use macro sprite_t2 to define a sprite. Its arguments are identifier, width (must be the even and more than 2), the x-coordinate, the y-coordinate, the number of datasets for the left, right, up, and down movements. For example, the next code defines the 4x3 sprite s3 that is placed at (41, 101)-coordinates and has only one dataset for all the movements but downward. So this sprite is 2-phase animated only for this movement.
Use functions left_t2, right_t2, up_t2, and down_t2 to move a sprite. You must put_t2 your sprite. There is also the remove_t2 sprite function. Just set your sprite definition address to the $e6-e7 zp-locations before the function invocations. There are also functions left2_t2, right2_t2, up2_t2, and down2_t2 that move a sprite by two pixels. For example, to move a sprite to the specified location use code similar to the next.
There are also several auxilary functions that can help easier use 2x2 tiles dynamically: getaddr22, setaddr22, nextaddr22, setcolor22 – they all use the A5 convention and doubled coordinates.
This library uses zp-locations $e0-e7.
The delay function simply delays for the specified number of frame ticks. The number must be set in the A register. The actual accuracy is about half a frame tick.
Function getkmatrix returns 8 bytes of the keyboard matrix status in kmatrix. The next table describes it.
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | |
---|---|---|---|---|---|---|---|---|
0 | del | return | £ | help | f1 | f2 | f3 | @ |
1 | 3 | W | A | 4 | Z | S | E | shift |
2 | 5 | R | D | 6 | C | F | T | X |
3 | 7 | Y | G | 8 | B | H | U | V |
4 | 9 | I | J | 0 | M | K | O | N |
5 | ↓ | P | L | ↑ | . | : | - | , |
6 | ← | * | ; | → | esc | = | + | / |
7 | 1 | clear | control | 2 | spc | cbm | Q | run |
Function waitkey waits for a key press. It also sets kmatrix.
Several examples and discussion are here.