Difference between revisions of "Snippet:Plot"
(→Coordinate-Adjusted Version) |
(→Coordinate-Adjusted Version) |
||
(5 intermediate revisions by the same user not shown) | |||
Line 3: | Line 3: | ||
== Coordinate-Adjusted Version == | == Coordinate-Adjusted Version == | ||
− | The following is the annotated source, with adjustments for the coordinates | + | The following is the annotated source, with adjustments for the coordinates. |
+ | Routine takes 69 machine cycles including pi and pop instructions. | ||
Line 13: | Line 14: | ||
; plot out a single point on the screen | ; plot out a single point on the screen | ||
; uses three registers as "arguments" | ; uses three registers as "arguments" | ||
− | ; r1 = color | + | ; r1 = color |
− | ; r2 = x (to screen) (0- | + | ; r2 = x (to screen) (0-127) |
− | ; r3 = y (to screen) (0- | + | ; r3 = y (to screen) (0-63) |
+ | ; Including parts outside the screen | ||
+ | ;------------------------ | ||
+ | ; Valid colors | ||
+ | ;------------------------ | ||
+ | ; green = $00 (%00000000) | ||
+ | ; red = $40 (%01000000) | ||
+ | ; blue = $80 (%10000000) | ||
+ | ; bkg = $C0 (%11000000) | ||
+ | ;------------------------ | ||
+ | |||
plot: | plot: | ||
Line 35: | Line 46: | ||
; transfer data to the screen memory by toggling ARM | ; transfer data to the screen memory by toggling ARM | ||
− | + | lis 6 | |
− | outs 0 | + | sl 4 |
− | + | outs 0 ; %01100000, no controller inputs, set b5 ARM to 1 | |
− | + | sl 1 | |
+ | outs 0 ; %11000000, no controller inputs, b5 ARM = 0, b7 (N/C) is set to 1 | ||
; delay until it's fully updated | ; delay until it's fully updated | ||
Line 63: | Line 75: | ||
; r2 = x (to screen) (4-105) | ; r2 = x (to screen) (4-105) | ||
; r3 = y (to screen) (4-61) | ; r3 = y (to screen) (4-61) | ||
+ | ;------------------------ | ||
+ | ; Valid colors | ||
+ | ;------------------------ | ||
+ | ; green = $00 (%00000000) | ||
+ | ; red = $40 (%01000000) | ||
+ | ; blue = $80 (%10000000) | ||
+ | ; bkg = $C0 (%11000000) | ||
+ | ;------------------------ | ||
+ | |||
plot: | plot: | ||
Line 86: | Line 107: | ||
; delay until it's fully updated | ; delay until it's fully updated | ||
− | lis 6 | + | lis 6 ; Value here is 4 in Videocart 21, Bowling |
.plotDelay: | .plotDelay: | ||
ai $ff | ai $ff | ||
Line 93: | Line 114: | ||
pop ; return from the subroutine | pop ; return from the subroutine | ||
</pre> | </pre> | ||
+ | |||
+ | |||
+ | Improved speed, uses inverted coordinates, from left to right: [255,128] which equals to [0,127].<br> | ||
+ | For the columns it's [255,192] from top to bottom which equals [0,63]. Routine is not a subroutine as that adds at least 8.5 cycles.<br> | ||
+ | If using one top level subroutine it's another 8.5 cycle... A JMP is only 5.5 cycles and a branch is only 3 or 3.5 cycle. <br> | ||
+ | You can use '''DS r''' (that uses 1c5) to increase coordinates. Ports are latched, no need to repeat the color setting if it's a repeated one color plot.<br> | ||
+ | |||
+ | It's a handy routine to use when changing the palette. | ||
+ | |||
+ | <pre> | ||
+ | ; Color is already set in A | ||
+ | outs 1 ; 2c | ||
+ | |||
+ | ; set the column using r2 | ||
+ | lr A, 2 ; 1c | ||
+ | outs 4 ; 4c inverted coordinate loaded to port 4 | ||
+ | |||
+ | ; set the row using r3 | ||
+ | lr A, 3 ; 1c | ||
+ | outs 5 ; 4c inverted coordinate loaded to port 5 | ||
+ | |||
+ | ; transfer data to the screen memory | ||
+ | lis 6 ; 1c | ||
+ | sl 4 ; 1c | ||
+ | outs 0 ; 2c | ||
+ | sl 1 ; 1c | ||
+ | outs 0 ; 2c | ||
+ | |||
+ | ; delay until it's fully updated - this is essential on a real machine | ||
+ | lis 6 ; 1c | ||
+ | plot.delay: | ||
+ | ai $ff ; 2c5 | ||
+ | bnz plot.delay ; 3c5 | ||
+ | ; +2c5+3c5+6c+6c+6c+6c+5c5 | ||
+ | </pre> | ||
+ | One dot plotted in 61.5 cycles. |
Latest revision as of 13:26, 16 August 2020
The plot subroutine takes a coordinate and a color, and plots it on the screen. The code was originally taken from Lights Out. Plotting individual pixels is slower than blitting an image to VRAM at once, but is useful in some applications. There are two versions here: the original version, and a coordinate-adjusted version to make programming easier.
Coordinate-Adjusted Version
The following is the annotated source, with adjustments for the coordinates. Routine takes 69 machine cycles including pi and pop instructions.
;---------------; ; Plot Function ; ;---------------; ; plot out a single point on the screen ; uses three registers as "arguments" ; r1 = color ; r2 = x (to screen) (0-127) ; r3 = y (to screen) (0-63) ; Including parts outside the screen ;------------------------ ; Valid colors ;------------------------ ; green = $00 (%00000000) ; red = $40 (%01000000) ; blue = $80 (%10000000) ; bkg = $C0 (%11000000) ;------------------------ plot: ; set the color using r1 lr A, 1 outs 1 ; Color is set by bit 6 and 7 only ; set the column using r2 lis 4 as 2 ; adjust the x coordinate com outs 4 ; place inverted coordinate for x on port 4 (bit 7 not used) ; set the row using r3 lis 4 as 3 ; adjust the y coordinate com outs 5 ; place inverted coordinate for y on port 5 (bit 6, 7 not used, those are for sound) ; transfer data to the screen memory by toggling ARM lis 6 sl 4 outs 0 ; %01100000, no controller inputs, set b5 ARM to 1 sl 1 outs 0 ; %11000000, no controller inputs, b5 ARM = 0, b7 (N/C) is set to 1 ; delay until it's fully updated lis 6 .plotDelay: ai $ff bnz .plotDelay pop ; return from the subroutine
The adjustment of x and y is to allow the coordinates 0, 0 to access the upper-left pixel of the screen (at least in MESS, for real it may be better or worse). VRAM in the Channel F actually expands four pixels above and to the left of that pixel. If you need a quicker plotting function, you can sacrifice this convenience and use the original version.
Original Version
;---------------; ; Plot Function ; ;---------------; ; plot out a single point on the screen ; uses three registers as "arguments" ; r1 = color ; r2 = x (to screen) (4-105) ; r3 = y (to screen) (4-61) ;------------------------ ; Valid colors ;------------------------ ; green = $00 (%00000000) ; red = $40 (%01000000) ; blue = $80 (%10000000) ; bkg = $C0 (%11000000) ;------------------------ plot: ; set the color using r1 lr A, 1 outs 1 ; set the column using r2 lr A, 2 com outs 4 ; set the row using r3 lr A, 3 com outs 5 ; transfer data to the screen memory li $60 outs 0 li $50 outs 0 ; delay until it's fully updated lis 6 ; Value here is 4 in Videocart 21, Bowling .plotDelay: ai $ff bnz .plotDelay pop ; return from the subroutine
Improved speed, uses inverted coordinates, from left to right: [255,128] which equals to [0,127].
For the columns it's [255,192] from top to bottom which equals [0,63]. Routine is not a subroutine as that adds at least 8.5 cycles.
If using one top level subroutine it's another 8.5 cycle... A JMP is only 5.5 cycles and a branch is only 3 or 3.5 cycle.
You can use DS r (that uses 1c5) to increase coordinates. Ports are latched, no need to repeat the color setting if it's a repeated one color plot.
It's a handy routine to use when changing the palette.
; Color is already set in A outs 1 ; 2c ; set the column using r2 lr A, 2 ; 1c outs 4 ; 4c inverted coordinate loaded to port 4 ; set the row using r3 lr A, 3 ; 1c outs 5 ; 4c inverted coordinate loaded to port 5 ; transfer data to the screen memory lis 6 ; 1c sl 4 ; 1c outs 0 ; 2c sl 1 ; 1c outs 0 ; 2c ; delay until it's fully updated - this is essential on a real machine lis 6 ; 1c plot.delay: ai $ff ; 2c5 bnz plot.delay ; 3c5 ; +2c5+3c5+6c+6c+6c+6c+5c5
One dot plotted in 61.5 cycles.