Difference between revisions of "Snippet:Multiblit"
(7 intermediate revisions by the same user not shown) | |||
Line 1: | Line 1: | ||
− | The '''multiblit''' subroutine is a derivative of the '''[[Snippet:Blit|blit]]''' subroutine, but draws the image to the screen in four colors (2 bits per pixel). | + | The '''multiblit''' subroutine is a derivative of the '''[[Snippet:Blit|blit]]''' subroutine, but draws the image to the screen in four colors (2 bits per pixel). The two-bit combination for green is %00, for red is %01, for blue is %10, and for the background color it's %11. Four pixels can be stored in a single byte of graphics data. |
− | The parameters and instructions for the routines are almost the same, using '''multiblit''' instead of '''blit''' and ''' | + | The parameters and instructions for the routines are almost the same, using '''multiblit''' instead of '''blit''' and '''MultiBlitGfx''' instead of '''blitGraphic'''. All you need to do is to skip the two color bytes in the parameter data. |
− | To call the functions, you should use: | + | To call the functions, you should use this for '''MultiBlitGfx''': |
<pre> | <pre> | ||
− | dci | + | dci gfx.parameters ; address of parameters |
− | pi | + | pi MultiBlitGfx |
</pre> | </pre> | ||
− | for | + | Parameters can be stored where you like, it has the address for the actual gfx data, that can also be placed where convenient. |
− | |||
<pre> | <pre> | ||
+ | gfx.parameters: | ||
+ | .byte 4 ; x position | ||
+ | .byte 18 ; y position | ||
+ | .byte 8 ; width | ||
+ | .byte 5 ; height | ||
+ | .word gfx.data ; address for the graphics | ||
− | + | gfx.data: | |
− | + | .byte %00001010, %11000010, %11000010, %11000011, %00001010 | |
− | |||
</pre> | </pre> | ||
− | + | If you want to use '''multiblit''' directly, make sure you have setup these data: | |
− | |||
<pre> | <pre> | ||
− | + | r1 = x position | |
− | + | r2 = y position | |
− | + | r3 = width | |
− | + | r4 = height | |
− | + | DC = pointer to graphics | |
− | |||
</pre> | </pre> | ||
Line 36: | Line 38: | ||
;================; | ;================; | ||
; | ; | ||
− | ; green: %00 | + | ; green: %00 (Port color code %00000000 / $00) |
− | ; red : %01 | + | ; red : %01 (Port color code %01000000 / $40) |
− | ; blue : %10 | + | ; blue : %10 (Port color code %10000000 / $80) |
− | ; background: %11. | + | ; background: %11. (Port color code %11000000 / $C0) |
; | ; | ||
;-------------------; | ;-------------------; | ||
− | ; | + | ; MultiBlitGfx ; |
;-------------------; | ;-------------------; | ||
Line 50: | Line 52: | ||
; modifies: r1-r4, Q, DC | ; modifies: r1-r4, Q, DC | ||
− | + | MultiBlitGfx: | |
; set ISAR | ; set ISAR | ||
lisu 0 | lisu 0 | ||
Line 72: | Line 74: | ||
; call the blit function | ; call the blit function | ||
− | + | ; jmp multiblit ; Not needed, it's the next piece of code | |
;--------------------; | ;--------------------; | ||
; Multiblit Function ; | ; Multiblit Function ; | ||
;--------------------; | ;--------------------; | ||
− | + | ; | |
− | ; this function blits a 4-color graphic based on parameters set | + | ; Adjusted so that (0,0) is the top left pixel in the MESS display. |
+ | ; If you want to skip this adjustment, saving 6 cycles, use | ||
+ | ; "multiblit_no" for real origo - and not (4,4). | ||
+ | ; | ||
+ | ; This function blits a 4-color graphic based on parameters set | ||
; in r1-r4 and the graphic data pointed to by DC0, onto the | ; in r1-r4 and the graphic data pointed to by DC0, onto the | ||
; screen | ; screen | ||
− | ; | + | ; Origin from cart 26, modified for color and annotated |
; | ; | ||
; modifies: r0-r7, DC | ; modifies: r0-r7, DC | ||
Line 87: | Line 93: | ||
; register reference: | ; register reference: | ||
; ------------------- | ; ------------------- | ||
+ | ; r0 = quick adder | ||
; r1 = x position | ; r1 = x position | ||
; r2 = y position | ; r2 = y position | ||
Line 107: | Line 114: | ||
as 2 | as 2 | ||
lr 2, A | lr 2, A | ||
+ | multiblit_no: | ||
+ | clr | ||
+ | com | ||
+ | lr 0, A ; $FF, for adding 1 | ||
lis 1 | lis 1 | ||
− | lr 7, A | + | lr 7, A ; load #1 into r7 so it'll be reset when we start |
− | lr A, 2 | + | lr A, 2 ; load the y offset |
− | com | + | com ; invert it |
.multiblitRow: | .multiblitRow: | ||
− | outs 5 | + | outs 5 ; load accumulator into port 5 (row) |
; check vertical counter | ; check vertical counter | ||
− | ds 4 | + | ds 4 ; decrease r4 (vertical counter) |
bnc .multiblitExit ; if it rolls over exit | bnc .multiblitExit ; if it rolls over exit | ||
Line 123: | Line 134: | ||
lr 5, A | lr 5, A | ||
− | lr A, 1 | + | lr A, 1 ; load the x position |
− | com | + | com ; complement it |
.multiblitColumn: | .multiblitColumn: | ||
− | outs 4 | + | outs 4 ; use the accumulator as our initial column |
; check to see if this byte is finished | ; check to see if this byte is finished | ||
− | ds 7 | + | ds 7 ; decrease r7 (pixel counter) |
bnz .multiblitDrawPixel ; if we aren't done with this byte, branch | bnz .multiblitDrawPixel ; if we aren't done with this byte, branch | ||
Line 134: | Line 145: | ||
; get the next graphics byte and set related registers | ; get the next graphics byte and set related registers | ||
lis 4 | lis 4 | ||
− | lr 7, A | + | lr 7, A ; load 4 into r7 (4 doublebit, pixel counter) |
lm | lm | ||
− | lr 6, A | + | lr 6, A ; load a graphics byte into r6 |
.multiblitDrawPixel: | .multiblitDrawPixel: | ||
; get new color | ; get new color | ||
lr A, 6 | lr A, 6 | ||
− | + | ni %11000000 ; Just keep top two | |
− | + | outs 1 ; output A in p1 (color) | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | outs 1 | ||
.multiblitTransferData: | .multiblitTransferData: | ||
; transfer the pixel data | ; transfer the pixel data | ||
− | + | lis 6 | |
+ | sl 4 | ||
outs 0 | outs 0 | ||
− | + | sl 1 | |
outs 0 | outs 0 | ||
− | ; | + | |
+ | |||
+ | ; GFX DELAY | ||
+ | |||
+ | ; shift graphics byte | ||
+ | lr A, 6 ; load r6 (graphics byte) | ||
+ | sl 1 | ||
+ | sl 1 ; shift left two, move up to b7, b6 | ||
+ | lr 6, A ; save it | ||
+ | |||
+ | lis 2 ; Small delay | ||
.multiblitSavePixelDelay: | .multiblitSavePixelDelay: | ||
− | ai $ | + | ai $ff |
bnz .multiblitSavePixelDelay ; loop if not 0 (small delay) | bnz .multiblitSavePixelDelay ; loop if not 0 (small delay) | ||
+ | |||
+ | |||
.multiblitCheckColumn: | .multiblitCheckColumn: | ||
− | ds 5 | + | ds 5 ; decrease r5 (horizontal counter) |
bz .multiblitCheckRow ; if it's 0, branch | bz .multiblitCheckRow ; if it's 0, branch | ||
− | ins 4 | + | ins 4 ; get p4 (column) |
− | + | as 0 ; add 1 (complemented) | |
− | br .multiblitColumn | + | br .multiblitColumn ; branch |
.multiblitCheckRow: | .multiblitCheckRow: | ||
− | ins 5 | + | ins 5 ; get p5 (row) |
− | + | as 0 ; add 1 (complemented) | |
br .multiblitRow ; branch | br .multiblitRow ; branch | ||
Line 191: | Line 197: | ||
</pre> | </pre> | ||
− | <em>Note: the adjustment of x and y in '''multiblit''' are to allow the coodinates 0, 0 to access the upper left pixel </em>visible to the screen<em>, not to VRAM, which expands four pixels above and to the left of that | + | <em>Note: the adjustment of x and y in '''multiblit''' are to allow the coodinates 0, 0 to access the upper left pixel </em>visible to the screen in MESS<em>, not to VRAM, which expands four pixels above and to the left of that position.</em> |
Latest revision as of 01:21, 16 November 2024
The multiblit subroutine is a derivative of the blit subroutine, but draws the image to the screen in four colors (2 bits per pixel). The two-bit combination for green is %00, for red is %01, for blue is %10, and for the background color it's %11. Four pixels can be stored in a single byte of graphics data.
The parameters and instructions for the routines are almost the same, using multiblit instead of blit and MultiBlitGfx instead of blitGraphic. All you need to do is to skip the two color bytes in the parameter data.
To call the functions, you should use this for MultiBlitGfx:
dci gfx.parameters ; address of parameters pi MultiBlitGfx
Parameters can be stored where you like, it has the address for the actual gfx data, that can also be placed where convenient.
gfx.parameters: .byte 4 ; x position .byte 18 ; y position .byte 8 ; width .byte 5 ; height .word gfx.data ; address for the graphics gfx.data: .byte %00001010, %11000010, %11000010, %11000011, %00001010
If you want to use multiblit directly, make sure you have setup these data:
r1 = x position r2 = y position r3 = width r4 = height DC = pointer to graphics
;================; ; Multiblit Code ; ;================; ; ; green: %00 (Port color code %00000000 / $00) ; red : %01 (Port color code %01000000 / $40) ; blue : %10 (Port color code %10000000 / $80) ; background: %11. (Port color code %11000000 / $C0) ; ;-------------------; ; MultiBlitGfx ; ;-------------------; ; takes graphic parameters from ROM, stores them in r1-r4, changes ; the DC and calls the multiblit function with the parameters ; ; modifies: r1-r4, Q, DC MultiBlitGfx: ; set ISAR lisu 0 lisl 1 ; load four bytes from the parameters into r1-r4 lm lr I, A ; store byte and increase ISAR lm lr I, A lm lr I, A lm lr S, A ; load the graphics address lm lr Qu, A ; into Q lm lr Ql, A lr DC, Q ; load it into the DC ; call the blit function ; jmp multiblit ; Not needed, it's the next piece of code ;--------------------; ; Multiblit Function ; ;--------------------; ; ; Adjusted so that (0,0) is the top left pixel in the MESS display. ; If you want to skip this adjustment, saving 6 cycles, use ; "multiblit_no" for real origo - and not (4,4). ; ; This function blits a 4-color graphic based on parameters set ; in r1-r4 and the graphic data pointed to by DC0, onto the ; screen ; Origin from cart 26, modified for color and annotated ; ; modifies: r0-r7, DC ; register reference: ; ------------------- ; r0 = quick adder ; r1 = x position ; r2 = y position ; r3 = width ; r4 = height (and vertical counter) ; ; r5 = horizontal counter ; r6 = graphics byte ; r7 = pixel counter ; ; DC = pointer to graphics multiblit: ; fix the x coordinate lis 4 as 1 lr 1, A ; fix the y coordinate lis 4 as 2 lr 2, A multiblit_no: clr com lr 0, A ; $FF, for adding 1 lis 1 lr 7, A ; load #1 into r7 so it'll be reset when we start lr A, 2 ; load the y offset com ; invert it .multiblitRow: outs 5 ; load accumulator into port 5 (row) ; check vertical counter ds 4 ; decrease r4 (vertical counter) bnc .multiblitExit ; if it rolls over exit ; load the width into the horizontal counter lr A, 3 lr 5, A lr A, 1 ; load the x position com ; complement it .multiblitColumn: outs 4 ; use the accumulator as our initial column ; check to see if this byte is finished ds 7 ; decrease r7 (pixel counter) bnz .multiblitDrawPixel ; if we aren't done with this byte, branch .multiblitGetByte: ; get the next graphics byte and set related registers lis 4 lr 7, A ; load 4 into r7 (4 doublebit, pixel counter) lm lr 6, A ; load a graphics byte into r6 .multiblitDrawPixel: ; get new color lr A, 6 ni %11000000 ; Just keep top two outs 1 ; output A in p1 (color) .multiblitTransferData: ; transfer the pixel data lis 6 sl 4 outs 0 sl 1 outs 0 ; GFX DELAY ; shift graphics byte lr A, 6 ; load r6 (graphics byte) sl 1 sl 1 ; shift left two, move up to b7, b6 lr 6, A ; save it lis 2 ; Small delay .multiblitSavePixelDelay: ai $ff bnz .multiblitSavePixelDelay ; loop if not 0 (small delay) .multiblitCheckColumn: ds 5 ; decrease r5 (horizontal counter) bz .multiblitCheckRow ; if it's 0, branch ins 4 ; get p4 (column) as 0 ; add 1 (complemented) br .multiblitColumn ; branch .multiblitCheckRow: ins 5 ; get p5 (row) as 0 ; add 1 (complemented) br .multiblitRow ; branch .multiblitExit: ; return from the subroutine pop
Note: the adjustment of x and y in multiblit are to allow the coodinates 0, 0 to access the upper left pixel visible to the screen in MESS, not to VRAM, which expands four pixels above and to the left of that position.