Difference between revisions of "Snippet:Multiblit"

From veswiki
Jump to: navigation, search
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 two-bit combination for green is %00, for red is %01, for blue is %10, and for the background color is %11. Four pixels can be stored in a single byte of graphics data.
+
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 '''MultiBlitGraphic''' instead of '''blitGraphic'''. All you need to do is to skip the two color bytes in the parameter data.
 
The parameters and instructions for the routines are almost the same, using '''multiblit''' instead of '''blit''' and '''MultiBlitGraphic''' instead of '''blitGraphic'''. All you need to do is to skip the two color bytes in the parameter data.
Line 79: Line 79:
 
;
 
;
 
; Adjusted so that (0,0) is the top left pixel in the MESS display.
 
; Adjusted so that (0,0) is the top left pixel in the MESS display.
; Full screen starts at (-4;-4) or you can remove the
 
; three row "fix"es below for faster display.
 
 
; If you want to skip this adjustment, saving 6 cycles, use  
 
; If you want to skip this adjustment, saving 6 cycles, use  
; "multiblit_no".
+
; "multiblit_no" for real origo - and not (4,4).
 
;
 
;
; this function blits a 4-color graphic based on parameters set
+
; 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
; originally from cart 26, modified for color and annotated
+
; Origin from cart 26, modified for color and annotated
 
;
 
;
 
; modifies: r0-r7, DC
 
; modifies: r0-r7, DC
Line 93: Line 91:
 
; register reference:
 
; register reference:
 
; -------------------
 
; -------------------
 +
; r0 = quick adder
 
; r1 = x position
 
; r1 = x position
 
; r2 = y position
 
; r2 = y position
Line 113: Line 112:
 
as 2
 
as 2
 
lr 2, A
 
lr 2, A
 +
multiblit_no:
 +
clr
 +
com
 +
lr 0, A ; $FF, for adding 1
  
multiblit_no:
 
 
lis 1
 
lis 1
lr 7, A ; load #1 into r7 so it'll be reset when we start
+
lr 7, A ; load #1 into r7 so it'll be reset when we start
lr A, 2 ; load the y offset
+
lr A, 2 ; load the y offset
com ; invert it
+
com ; invert it
 
.multiblitRow:
 
.multiblitRow:
outs 5 ; load accumulator into port 5 (row)
+
outs 5 ; load accumulator into port 5 (row)
  
 
; check vertical counter
 
; check vertical counter
ds 4 ; decrease r4 (vertical counter)
+
ds 4 ; decrease r4 (vertical counter)
 
bnc .multiblitExit ; if it rolls over exit
 
bnc .multiblitExit ; if it rolls over exit
  
Line 130: Line 132:
 
lr 5, A
 
lr 5, A
  
lr A, 1 ; load the x position
+
lr A, 1 ; load the x position
com ; complement it
+
com ; complement it
 
.multiblitColumn:
 
.multiblitColumn:
outs 4 ; use the accumulator as our initial column
+
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 ; decrease r7 (pixel counter)
+
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 141: Line 143:
 
; 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 ; load #4 into r7 (pixel counter)
+
lr 7, A ; load 4 into r7 (4 doublebit, pixel counter)
 
lm
 
lm
lr 6, A ; load a graphics byte into r6
+
lr 6, A ; load a graphics byte into r6
  
 
.multiblitDrawPixel:
 
.multiblitDrawPixel:
 
; get new color
 
; get new color
lr A, 6 ; Only keep b7 b6
+
lr A, 6
sr 4
+
ni %11000000 ; Just keep top two
sr 1
+
outs 1 ; output A in p1 (color)
sr 1
 
lr 0, A ; save two-bit color in r0
 
 
 
; shift graphics byte
 
lr A, 6 ; load r6 (graphics byte)
 
sl 1
 
sl 1 ; shift left two, new bits on b7 b6
 
lr 6, A ; save it
 
 
 
; output the color
 
clr
 
.multiblitGetColor:
 
ds 0
 
bnc .multiblitGetColorEnd
 
ai $40 ; add $40 to color number
 
br .multiblitGetColor
 
.multiblitGetColorEnd:
 
outs 1 ; output A in p1 (color)
 
  
 
.multiblitTransferData:
 
.multiblitTransferData:
 
; transfer the pixel data
 
; transfer the pixel data
li $60
+
lis 6
 +
sl 4
 
outs 0
 
outs 0
li $c0
+
sl 1
 
outs 0
 
outs 0
; and delay a little bit
+
 
 +
 
 +
; 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 1 ; Same delay as in blit
 
.multiblitSavePixelDelay:
 
.multiblitSavePixelDelay:
ai $60 ; add 96
+
ai $ff
 
bnz .multiblitSavePixelDelay ; loop if not 0 (small delay)
 
bnz .multiblitSavePixelDelay ; loop if not 0 (small delay)
 +
 +
  
 
.multiblitCheckColumn:
 
.multiblitCheckColumn:
ds 5 ; decrease r5 (horizontal counter)
+
ds 5 ; decrease r5 (horizontal counter)
 
bz .multiblitCheckRow ; if it's 0, branch
 
bz .multiblitCheckRow ; if it's 0, branch
  
ins 4 ; get p4 (column)
+
ins 4 ; get p4 (column)
ai $ff ; add 1 (complemented)
+
as 0 ; add 1 (complemented)
br .multiblitColumn ; branch
+
br .multiblitColumn ; branch
  
 
.multiblitCheckRow:
 
.multiblitCheckRow:
ins 5 ; get p5 (row)
+
ins 5 ; get p5 (row)
ai $ff ; add 1 (complemented)
+
as 0 ; add 1 (complemented)
 
br .multiblitRow ; branch
 
br .multiblitRow ; branch
  

Revision as of 20:55, 19 May 2020

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 MultiBlitGraphic 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:

	dci	graphic.parameters	; address of parameters
	pi	multiblitGraphic

for multiblitGraphic, and:


	; parameters have been loaded into r1-r4 beforehand
	dci	graphic.data		; address of graphic data
	pi	multiblit

for multiblit. If you're using parameters stored in ROM, they should be in this order:

graphic.parameters:
	.byte	4			; x position
	.byte	18			; y position
	.byte	$60			; width
	.byte	$13			; height
	.word	graphic.data		; address for the 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)
;
;-------------------;
; Multiblit Graphic ;
;-------------------;

; 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

MultiBlitGraphic:
	; 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

;--------------------;
; 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	1							; Same delay as in blit
.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.


See Also