Difference between revisions of "Snippet:Blit"
| (One intermediate revision by the same user not shown) | |||
| Line 5: | Line 5: | ||
Note that coordinate (0,0) is usually outside the visible emulation area, in MESS/MESSUI/MAME visible area starts at (4,4). | Note that coordinate (0,0) is usually outside the visible emulation area, in MESS/MESSUI/MAME visible area starts at (4,4). | ||
| − | Code works with the DASM | + | Code works with the '''DASM''' compiler. |
| + | |||
| + | '''Tip:''' If you want a block in one color, set both colors the same and skip setting the data pointer (DC0). | ||
| + | |||
<pre> | <pre> | ||
;===========; | ;===========; | ||
Latest revision as of 14:57, 21 June 2026
The blit subroutine reads a two-color (1 bit per pixel) block of graphics data from ROM and displays it on the screen, using several parameters. It works much in the same way as the BIOS drawchar routine except for arbitrarily sized data. The code was originally taken from Videocart 26 and adapted to be more flexible and reusable.
The routine is separated into two parts, blitGraphic and blit. blit takes parameters in registers r1-r6, and retrieves graphics data from the location DC0 points to. It can be called independently of blitGraphic. blitGraphic takes hard-coded parameters from ROM at the address pointed at by DC0 and then calls the blit routine. When the parameters do not need to be dynamic, storing the parameters in ROM and calling the blitGraphic routine directly can be more efficient than writing them to the registers and calling blit.
Note that coordinate (0,0) is usually outside the visible emulation area, in MESS/MESSUI/MAME visible area starts at (4,4).
Code works with the DASM compiler.
Tip: If you want a block in one color, set both colors the same and skip setting the data pointer (DC0).
;===========; ; Blit Code ; ;===========; ;--------------; ; Blit Graphic ; ;--------------; ; takes graphic parameters from ROM, stores them in r1-r6, ; changes the DC and calls the blit function with the parameters ; ; modifies: r1-r6, Q, DC blitGraphic: ; load six bytes from the parameters into r0-r5 lisu 0 lisl 1 .blitGraphicGetParms: lm lr I, A ; store byte and increase ISAR br7 .blitGraphicGetParms ; not finished with the registers, loop ; load the graphics address lm lr QU, A ; storea data address in Q, one byte at the time lm lr QL, A lr DC, Q ; copy Q into DC0 ; continue with the blit function ;---------------; ; Blit Function ; ;---------------; ; this function blits a graphic based on parameters set in r1-r6, ; and the graphic data pointed to by DC0, onto the screen ; originally from cart 26, modified and annotated ; ; modifies: r1-r9, DC ; register reference: ; ------------------- ; r1 = color 0 (off) (alias: clear/bkg/blue/red/green) ; r2 = color 1 (on) (alias: clear/bkg/blue/red/green) ; r3 = x position ; r4 = y position ; r5 = width ; r6 = height (and vertical counter) ; ; r7 = horizontal counter ; r8 = graphics byte ; r9 = bit counter ; ; DC = pointer to graphics blit: lis 1 lr 9, A ; load #1 into r9 so it'll be reset when we start lr A, 4 ; load the y offset com ; invert it .blitRow: outs 5 ; load accumulator into port 5 (row) ; check vertical counter ds 6 ; decrease r6 (vertical counter) bnc .blitExit ; if it rolls over exit ; load the width into the horizontal counter lr A, 5 lr 7, A lr A, 3 ; load the x position com ; complement it .blitColumn: outs 4 ; use the accumulator as our initial column ; check to see if this byte is finished ds 9 ; decrease r9 (bit counter) bnz .blitDrawBit ; if we aren't done with this byte, branch .blitGetByte: ; get the next graphics byte and set related registers lis 8 lr 9, A ; load #8 into r9 (bit counter) lm lr 8, A ; load a graphics byte into r8 .blitDrawBit: ; shift graphics byte lr A, 8 ; load r8 (graphics byte) as 8 ; shift left one (with carry) lr 8, A ; save it ; check color to use lr A, 2 ; load color 1 bc .blitSavePixel ; if this bit is on, draw the color lr A, 1 ; load color 2 .blitSavePixel: inc bc .blitCheckColumn ; branch if the color is "clear" outs 1 ; output A in p1 (color) blit.transferData: lis 6 ; transfer the pixel data sl 4 outs 0 sl 1 outs 0 lis 4 blit.savePixelDelay: ai $ff bnz blit.savePixelDelay .blitCheckColumn: ds 7 ; decrease r7 (horizontal counter) bz .blitCheckRow ; if it's 0, branch ins 4 ; get p4 (column) ai $ff ; add 1 (complemented) br .blitColumn ; branch .blitCheckRow: ins 5 ; get p5 (row) ai $ff ; add 1 (complemented) br .blitRow ; branch .blitExit: ; return from the subroutine pop
To call the above functions, you should use:
dci graphic.parameters ; address of parameters pi blitGraphic
for blitGraphic, and
; when parameters have been loaded into r1-r6 beforehand dci graphic.data ; address of graphic data pi blit
for blit. If you're using parameters stored in ROM, they should be in this order:
graphic.parameters: .byte bkg ; color 0 .byte blue ; color 1 .byte 4 ; x position .byte 18 ; y position .byte $60 ; width .byte $13 ; height .word graphic.data ; address for the graphics