25 Years of Programming
An open source source for C, C++, OWL, BASIC, MDB, XLS, DOT, and more...
Home   Projects   Up   Sitemap   Search   Blog   Forum+Chat   About Us   Privacy   Terms of Use   Feedback   FAQ   Images   Services   Payments   Humor   Music

Heathkit H-100 color graphics functions to get and set color pixels in DeSmet C and speed optimized assembly language

This DeSmet C function directly reads and writes the Heathkit H-100 computer's video RAM planes to implement color getpixel and setpixel functionality. When setting pixels, there are 5 different available modes.

After writing the function in C, I compiled it to 8088/8086 assembly language and then optimized it for speed. 

One example of the type of optimization that can be done is that the compiler loads a variable into a register every time it is used, even if the variable is already in that register left over from a previous operation. It has no way of knowing, but a human reviewing the code can remove duplicate operations of this type. 

Unless you want to make changes, you would ordinarily use the code listing from pset.a further down this page, rather than pset.c. DeSmet C can assemble pset.a into object code pset.o, which you then link with the other modules of your program.

This function is used extensively by my DeSmet C color graphics programs for the H-100.

/* ===========================================================*/
/* H100 COLOR GRAPHICS PRIMITIVES FOR PIXEL MANIPULATION */
/* ===========================================================*/
/* -> These functions are highly specific to the H100 computer hardware, */
/* -> and could have disastrous consequences on any other computer. */
/* -------------------------------------------------------------- */
/*	PSET()	4-28-93	 COLOR PIXEL-HANDLING ROUTINES FOR H100 COMPUTER */
/*	Copyright (C)1993 Steven Whitney. Published under the */
/*	GNU GPL (General Public License) Version 3, with ABSOLUTELY NO WARRANTY. */
/*	Initially published by http://25yearsofprogramming.com. */
/*	==> THE SOURCE FOR PSET.O IS PSET.A, THE MODIFIED FROM OUTPUT FROM THIS FILE */
/*	0=BLACK 1=BLUE 2=RED 3=MAGENTA 4=GREEN 5=CYAN 6=YELLOW 7=WHITE	*/
/*	ONLY RESPONDS TO 0-639 & 0-224, ERROR WON'T POKE INTO ILLEGAL MEMORY */
/*	RETURNS: COLOR OF POINT AT (X,Y) FOR MODE 'S', OR 0 FOR THE OTHERS */
/*	RETURNS ERR (-1) IF SCREEN OR COLOR RANGES EXCEEDED, OR ILLEGAL MODE  */
/*	5-22-93 TEST BYTE BEFORE POKING, SPEED IMPROVEMENT */
/*	6-8-93  DOESN'T CHANGE OR RESTORE VIDEO PORT */
/*			OPERATES WITHIN MODE CURRENTLY IN EFFECT IN CALLING PROGRAM */
/*	12-5-93 PSET NOW INCORPORATES ALL OF THE FOLLOWING FUNCTIONS: */
/*			(ALL FUNCTIONS CALLING PSET CAN NOW USE THE FOLLOWING MODES) */
/*	MODE:	*/
/*	S	POINT - JUST RETURN (SHOW) COLOR OF POINT AT (X,Y) */
/*	P	PSET  - SET (X,Y) TO SPECIFIED COLOR */
/*	O	OPSET - PSET USING "OR" */
/*	X   XPSET - PSET USING "XOR" */
/*	+         - PSET TO COLOR VALUE 1 MORE THAN FOUND AT THE POINT, MAX=7 */
/*	-		  - PSET TO 1 LESS THAN FOUND, MIN=0 */
/*	R         - PSET TO 1 MORE THAN FOUND, & (R)OTATE THROUGH 0-7,0-7, ETC. */
/*	    OTHERS CAN BE ADDED */
/* -------------------------------------------------------------- */
#define ERR		(-1)
int pset(x,y,mode,color)		
int x, y;					/* SCREEN COORDINATES */
char mode;					/* MUST BE LOWER CASE */
int color;
{
char *offset;			/* POINTS AT BYTE IN VIDEO MEMORY */
char byte;				/* CONTENTS OF BYTE AT OFFSET */
unsigned segment; 		/* POINTS AT COLOR PLANE */
char mask, notmask;		/* USED TO TURN 1 BIT IN BYTE ON OR OFF */
char _peek();
void _poke();

/* TESTS FOR INVALID COLOR OR MODE IS IN SWITCHES BELOW */
if((x < 0) || (x > 639) || (y < 0) || (y > 224))
	return(ERR);

offset = (char *)(((((y/9)*16)+(y%9))*128)+(x/8));	/* CALC ADDRESS */
mask = (0x80) >> (x%8);								/* MASK FOR PIXEL BIT */
notmask = ~mask;

switch(mode)
{
	case 'o':			/* OPSET */
/* -------------------------------------------------------------- */
/*	OPSET()		6-2-93  10-12-93  */
/*	LIKE PSET, BUT DOES NOT TURN OFF PLANES NOT USED FOR SPECIFIFED COLOR */
/*	IT MERELY TURNS ON THE PLANES THAT MAKE THAT COLOR */
/*	IT WILL OVERLAY, BUT NOT DESTROY, WHATEVER IS ALREADY ON THE SCREEN */
/* -------------------------------------------------------------- */
		switch(color)
		{
			case 0:						/* BLACK = (MEANINGLESS) */
				break;
			case 1:										/* BLUE */
				_poke(_peek(offset,0xC000) | mask,offset,0xC000);	/* BLUE ON */
				break;
			case 2:										/* RED */
				_poke(_peek(offset,0xD000) | mask,offset,0xD000);   /* RED ON */
				break;
			case 3:						/* MAGENTA =  RED + BLUE */
				_poke(_peek(offset,0xC000) | mask,offset,0xC000);  	/* BLUE ON */
				_poke(_peek(offset,0xD000) | mask,offset,0xD000);   /* RED ON */
				break;
			case 4:						/* GREEN */
				_poke(_peek(offset,0xE000) | mask,offset,0xE000);   /* GREEN ON */
				break;
			case 5:						/* CYAN = BLUE + GREEN */
				_poke(_peek(offset,0xC000) | mask,offset,0xC000);   /* BLUE ON */
				_poke(_peek(offset,0xE000) | mask,offset,0xE000);   /* GREEN ON */
				break;
			case 6:						/* YELLOW = RED + GREEN */
				_poke(_peek(offset,0xD000) | mask,offset,0xD000);   /* RED ON */
				_poke(_peek(offset,0xE000) | mask,offset,0xE000);   /* GREEN ON */
				break;
			case 7:						/* WHITE = RED + BLUE + GREEN */
				_poke(_peek(offset,0xC000) | mask,offset,0xC000);   /* BLUE ON */
				_poke(_peek(offset,0xD000) | mask,offset,0xD000);   /* RED ON */
				_poke(_peek(offset,0xE000) | mask,offset,0xE000);   /* GREEN ON */
				break;
			default:			/* COLOR OUT OF RANGE 0-7 */
				return(ERR);
		}						/* END SWITCH(COLOR) IN OPSET */
		return(0);				/* END OPSET */

	case 'x':			/* XPSET */
/* -------------------------------------------------------------- */
/*	XPSET()		6-2-93  10-12-93  */
/*	SAME AS PSET, BUT IT PERFORMS XOR ON THE PIXEL */
/*	FOR USE IN ANIMATION, SINCE XPSET() WILL ALWAYS CHANGE STATE OF THE */
/*	POINT (MAKING IMAGE STAND OUT), AND DOING IT AGAIN WILL RETURN */
/* 	THE POINT TO ITS ORIGINAL COLOR (BACKGROUND) */
/*	EXAMPLES: */
/*	IF POINT IS BLACK(0) XPSET() IN YELLOW(R+G) TOGGLES POINT BLACK/YELLOW */
/*	IF POINT IS WHITE(RGB) XPSET() IN MAGENTA(RB) TOGGLES POINT WHITE/GREEN */
/*	IF POINT IS MAGENTA(RB) XPSET() IN GREEN(G) TOGGLES POINT WHITE/MAGENTA */
/* -------------------------------------------------------------- */
/*	TOGGLE THE BIT IN ALL PLANES USED FOR THE SPECIFIED COLOR. */
/*	LEAVE ALONE ANY PLANES NOT USED. */
/* -------------------------------------------------------------- */
		switch(color)
		{
			case 0:						/* BLACK = LEAVE ALONE */
				break;
			case 1:						/* BLUE */
				_poke(_peek(offset,0xC000) ^ mask,offset,0xC000);
				break;
			case 2:						/* RED */
				_poke(_peek(offset,0xD000) ^ mask,offset,0xD000);
				break;
			case 3:						/* MAGENTA =  RED + BLUE */
				_poke(_peek(offset,0xC000) ^ mask,offset,0xC000);
				_poke(_peek(offset,0xD000) ^ mask,offset,0xD000);
				break;
			case 4:						/* GREEN */
				_poke(_peek(offset,0xE000) ^ mask,offset,0xE000);
				break;
			case 5:						/* CYAN = BLUE + GREEN */
				_poke(_peek(offset,0xC000) ^ mask,offset,0xC000);   
				_poke(_peek(offset,0xE000) ^ mask,offset,0xE000);
				break;
			case 6:						/* YELLOW = RED + GREEN */
				_poke(_peek(offset,0xD000) ^ mask,offset,0xD000);
				_poke(_peek(offset,0xE000) ^ mask,offset,0xE000);   
				break;
			case 7:						/* WHITE = RED + BLUE + GREEN */
				_poke(_peek(offset,0xC000) ^ mask,offset,0xC000);   
				_poke(_peek(offset,0xD000) ^ mask,offset,0xD000);   
				_poke(_peek(offset,0xE000) ^ mask,offset,0xE000);
				break;
			default:
				return(ERR);
		}					/* END SWITCH(COLOR) IN XPSET */
		return(0);			/* COULD FALL THROUGH FOR COLOR */

	case 'r':			/* INCREASE COLOR & ROTATE */
	case '-':			/* DECREASE COLOR AT POINT */
	case '+':			/* INCREASE COLOR AT POINT */
	case 's':			/* RETURN COLOR OF POINT, FORMERLY POINT() */
		color = 0;
		if((_peek(offset,0xC000) & mask)) color += 1;	/* EACH PLANE, IF ON */
		if((_peek(offset,0xD000) & mask)) color += 2;	/* ADDS A SET VALUE */
		if((_peek(offset,0xE000) & mask)) color += 4;	/* TO OVERALL COLOR */
		switch(mode)
		{
			case 's':					/* POINT() */
				return(color);

			case '+':					/* INCREASE, MAX=7 */
				if(++color > 7)
					color = 7;		
				break;

			case '-':					/* DECREASE, MIN=0 */
				if(--color < 0)
					color = 0;			
				break;

			case 'r':					/* INCREASE, ROTATE */
				if(++color > 7)
					color = 0;
				break;
		}
							/* ALL MODES EXCEPT 'S' FALL THROUGH TO */
	case 'p':				/* PSET */
/* -------------------------------------------------------------- */
/*	FOR EACH COLOR, FIRST TURN OFF THE PIXEL IN ANY PLANES NOT USED */
/*	FOR THAT COLOR, THEN SET EACH OF THE USED COLORS SEPARATELY. */
/*	USING THE SIMULTANEOUS-WRITE BITS OF PORT D8 DOES NOT WORK */
/*	BECAUSE IT AFFECTS ALL THE BITS OF THE BYTE WRITTEN OUT, */
/*	INADVERTENTLY CHANGING THE COLORS OF NEIGHBORING PIXELS. */
/*	5-22-93 IF ENTIRE BYTE IS EMPTY (AS WILL OFTEN BE THE CASE), DON'T */
/*	BOTHER WITH TURNING THE BIT OFF.  IT ALREADY IS. */
/* -------------------------------------------------------------- */
		switch(color)
		{
			case 0:							/* BLACK = TURN PIXEL OFF */
				if(byte = _peek(offset,0xC000)) 		
					_poke(byte & notmask,offset,0xC000);	/* BLUE OFF */
				if(byte = _peek(offset,0xD000))
					_poke(byte & notmask,offset,0xD000);	/* RED OFF */
				if(byte = _peek(offset,0xE000))
					_poke(byte & notmask,offset,0xE000);	/* GREEN OFF */
				break;									
			case 1:							/* BLUE */
				if(byte = _peek(offset,0xD000))
					_poke(byte & notmask,offset,0xD000);			/* RED OFF */
				if(byte = _peek(offset,0xE000))
					_poke(byte & notmask,offset,0xE000);			/* GREEN OFF */
				_poke(_peek(offset,0xC000) | mask,offset,0xC000);	/* BLUE ON */
				break;
			case 2:							/* RED */
				if(byte = _peek(offset,0xC000))
					_poke(byte & notmask,offset,0xC000);			/* BLUE OFF */
				if(byte = _peek(offset,0xE000))
					_poke(byte & notmask,offset,0xE000);			/* GREEN OFF */
				_poke(_peek(offset,0xD000) | mask,offset,0xD000);   /* RED ON */
				break;
			case 3:							/* MAGENTA =  RED + BLUE */
				if(byte = _peek(offset,0xE000))
					_poke(byte & notmask,offset,0xE000);			/* GREEN OFF */
				_poke(_peek(offset,0xC000) | mask,offset,0xC000);  	/* BLUE ON */
				_poke(_peek(offset,0xD000) | mask,offset,0xD000);   /* RED ON */
				break;
			case 4:							/* GREEN */
				if(byte = _peek(offset,0xC000))
					_poke(byte & notmask,offset,0xC000);			/* BLUE OFF */
				if(byte = _peek(offset,0xD000))
					_poke(byte & notmask,offset,0xD000);			/* RED OFF */
				_poke(_peek(offset,0xE000) | mask,offset,0xE000);   /* GREEN ON */
				break;
			case 5:							/* CYAN = BLUE + GREEN */
				if(byte = _peek(offset,0xD000))
					_poke(byte & notmask,offset,0xD000);			/* RED OFF */
				_poke(_peek(offset,0xC000) | mask,offset,0xC000);   /* BLUE ON */
				_poke(_peek(offset,0xE000) | mask,offset,0xE000);   /* GREEN ON */
				break;
			case 6:							/* YELLOW = RED + GREEN */
				if(byte = _peek(offset,0xC000))
					_poke(byte & notmask,offset,0xC000);			/* BLUE OFF */
				_poke(_peek(offset,0xD000) | mask,offset,0xD000);   /* RED ON */
				_poke(_peek(offset,0xE000) | mask,offset,0xE000);   /* GREEN ON */
				break;
			case 7:							/* WHITE = RED + BLUE + GREEN */
				_poke(_peek(offset,0xC000) | mask,offset,0xC000);   /* BLUE ON */
				_poke(_peek(offset,0xD000) | mask,offset,0xD000);   /* RED ON */
				_poke(_peek(offset,0xE000) | mask,offset,0xE000);   /* GREEN ON */
				break;
			default:
				return(ERR);
		}					/* END SWITCH(COLOR) IN PSET OPTION */
		return(0);
	

	default:
		return(ERR);		/* INDICATES ILLEGAL MODE REQUESTED */
}							/* END SWITCH(MODE) */
}							/* END FUNCTION */

/* ===========================================================*/
/* ===========================================================*/

;pset.a		12-6-93 optimization of the assembler output from pset.c
;Copyright (C)1993 Steven Whitney. Published under the 
;GNU GPL (General Public License) Version 3, with ABSOLUTELY NO WARRANTY. 
;Initially published by http://25yearsofprogramming.com.
;This is MUCH faster. You assemble this into an object file and use this
;INSTEAD of compiling pset.c into an object file.
;If you revise pset.c, you only compile it into assembler, then optimize
;the output similarly to how I did it here. 
;includes point, pset, opset, xpset & some new options (see pset.c)
;registers aren't preserved, but c doesn't seem to preserve them, either
;[bp + i] = passed parameters, pushed onto stack from right to left
;[bp - i] = local variables, pushed in order of declaration

CSEG 
 PUBLIC pset_

pset_:
 PUSH BP		;save calling program's base pointer
 MOV BP,SP		;save stack pointer to bp before we change sp
 			;bp will be reference point for all variables
 SUB SP,8		;make room for locals on stack

;test for x or y off screen
mov	ax,[bp+4]	;x
cmp	ax,0
 JL _L2			;return(ERR)
cmp	ax,639
 JG _L2
mov	ax,[bp+6]	;y
cmp	ax,0
 JL _L2
cmp	ax,224
 JLE _L1

_L2:			;return(ERR)
 MOV AX,-1		
 MOV SP,BP
 POP BP
 RET

_L1:			;calculate offset
 MOV AX,WORD [BP+6]
 CWD
 MOV CX,9
 IDIV CX
 MOV CX,16
 IMUL CX
 MOV DI,AX
 MOV AX,WORD [BP+6]
 CWD
 MOV CX,9
 IDIV CX
 ADD DI,DX
 MOV AX,DI
 MOV CX,128
 IMUL CX
 MOV CX,WORD [BP+4]
 CWD
 XOR AX,DX
 SUB AX,DX
 SAR CX,1
 SAR CX,1
 SAR CX,1
 XOR AX,DX
 SUB AX,DX
 ADD AX,CX
 MOV WORD [BP-2],AX	;offset calc. done (so store it)
 MOV AX,WORD [BP+4]	;use x to calc. mask
 CWD
 MOV CX,8
 IDIV CX
 MOV CX,DX
 MOV AL,128
 SHR AL,CL
 MOV BYTE [BP-7],AL	;mask calc. done (so store it)
 NOT AL
 MOV BYTE [BP-8],AL	;store notmask
 MOV BL,BYTE [BP+8]	;use mode for switch()
 MOV BH,0
 PUBLIC _SWITCH		;this switch() method used when options not consecutive
 CALL _SWITCH
 DW 8			;number of switch options below
			;format = ascii value, jump address
 DW 111,_L5		;o
 DW 120,_L6		;x
 DW 114,_L7		;r
 DW 45,_L8		;-
 DW 43,_L9		;+
 DW 115,_L10		;s
 DW 112,_L11		;p
 DW -32768,_L12		;default (illegal)

_L5:			;case opset
 MOV BX,WORD [BP+10]	;color in preparation for switch below
 CMP BX,0		;check for within range 0-7
 JL _L23		;return(ERR)
 CMP BX,7
 JG _L23
 SHL BX,1		;multiply by 2 to allow for word spacing below

mov	di,[bp-2]	;offset will be used repeatedly
mov	cl,[bp-7]	;mask, also

;this form of switch used when options are consecutive
 JMP BYTE _L25[BX]	;switch(color)
_L25:
 DW _L15		;case 0
 DW _L16		;1
 DW _L17		;2
 DW _L18		;3
 DW _L19		;4
 DW _L20		;5
 DW _L21		;6
 DW _L22		;7

_L15:			;case black (meaningless)
 JMP _L24		;return(0)

_L16:			;case blue
mov	bx,0c000h	;load extra segment
mov	es,bx
or	es:[di],cl	;directly or vram byte with mask 
jmp	_L24

_L17:			;case red
mov	bx,0d000h
mov	es,bx
or	es:[di],cl
jmp	_L24

_L18:			;case magenta
mov	bx,0c000h	;blue
mov	es,bx
or	es:[di],cl

mov	bx,0d000h	;red
mov	es,bx
or	es:[di],cl
jmp	_L24

_L19:			;case green
mov	bx,0e000h	;green
mov	es,bx
or	es:[di],cl
jmp	_L24

_L20:			;case cyan = green + blue
mov	bx,0c000h	;blue
mov	es,bx
or	es:[di],cl

mov	bx,0e000h	;green
mov	es,bx
or	es:[di],cl
jmp	_L24

_L21:			;case yellow = green + red
mov	bx,0e000h	;green
mov	es,bx
or	es:[di],cl

mov	bx,0d000h	;red
mov	es,bx
or	es:[di],cl
jmp	_L24

_L22:			;case white
mov	bx,0c000h	;blue
mov	es,bx
or	es:[di],cl

mov	bx,0d000h	;red
mov	es,bx
or	es:[di],cl

mov	bx,0e000h	;green
mov	es,bx
or	es:[di],cl
jmp	_L24

_L23:			;return(ERR)
 MOV AX,-1
 MOV SP,BP
 POP BP
 RET

_L24:			;return(0)
 XOR AX,AX
 MOV SP,BP
 POP BP
 RET			;end opset

_L6:			;case xpset
 MOV BX,WORD [BP+10]	;color
 CMP BX,0		;check for out of range
 JL _L34		;return(ERR)
 CMP BX,7
 JG _L34
 SHL BX,1

mov	di,[bp-2]	;offset will be used repeatedly
mov	cl,[bp-7]	;mask, also

JMP BYTE _L36[BX]	;switch(color)
_L36:
 DW _L26		;0
 DW _L27		;1
 DW _L28		;2
 DW _L29		;3
 DW _L30		;4
 DW _L31		;5
 DW _L32		;6
 DW _L33		;7

_L26:			;case black (leave unchanged)
 JMP _L35		;return(0)

_L27:			;case blue
mov	bx,0c000h	;blue
mov	es,bx
xor	es:[di],cl
jmp	_L35

_L28:			;case red
mov	bx,0d000h	;red
mov	es,bx
xor	es:[di],cl
jmp	_L35

_L29:			;case magenta
mov	bx,0c000h	;blue
mov	es,bx
xor	es:[di],cl

mov	bx,0d000h	;red
mov	es,bx
xor	es:[di],cl
jmp	_L35

_L30:			;case green
mov	bx,0e000h	;green
mov	es,bx
xor	es:[di],cl
jmp	_L35

_L31:			;case cyan = green + blue
mov	bx,0e000h	;green
mov	es,bx
xor	es:[di],cl

mov	bx,0c000h	;blue
mov	es,bx
xor	es:[di],cl
jmp	_L35

_L32:			;case yellow = red + green
mov	bx,0d000h	;red
mov	es,bx
xor	es:[di],cl

mov	bx,0e000h	;green
mov	es,bx
xor	es:[di],cl
jmp	_L35

_L33:			;case white
mov	bx,0c000h	;blue
mov	es,bx
xor	es:[di],cl

mov	bx,0d000h	;red
mov	es,bx
xor	es:[di],cl

mov	bx,0e000h	;green
mov	es,bx
xor	es:[di],cl
jmp	_L35

_L34:			;return(ERR)
 MOV AX,-1
 MOV SP,BP
 POP BP
 RET

_L35:			;return(0)
 XOR AX,AX
 MOV SP,BP
 POP BP
 RET			;end xpset

_L7:			;case 'r'
_L8:			;case '-'
_L9:			;case '+'
_L10:			;case 's' point()
xor	ax,ax		;zero ax - will be used to accumulate color value
mov	di,[bp-2]	;offset will be used repeatedly
mov	cl,[bp-7]	;mask, also

mov	bx,0c000h	;test if bit is on in blue plane
mov	es,bx
test	es:[di],cl	;logical and without changing operands
jz	_L37
inc	ax		;bit was on, so add 1 to color

_L37:
mov	bx,0d000h	;red
mov	es,bx
test	es:[di],cl
jz	_L38
add	ax,2		;red adds 2

_L38:
mov	bx,0e000h	;green
mov	es,bx
test	es:[di],cl
jz	_L39
add	ax,4		;green adds 4

_L39:
			;at this point, ax contains the color value
cmp	byte [bp+8],115	;if mode is 's', just return it without storing
jne	_L40
			;note: c functions return their values in ax
 MOV SP,BP		;return(color), which is already in ax
 POP BP
 RET

_L40:		
mov	[bp+10],ax	;now store color, since we'll need it later
 MOV BL,BYTE [BP+8]	;switch(mode)
 MOV BH,0
 CALL _SWITCH
 DW 4			;number of possible options
 DW 43,_L41		;+
 DW 45,_L42		;-
 DW 114,_L43		;r
 DW -32768,_L44		;default (illegal)

_L41:			;case +
 INC WORD [BP+10]	;if(++color > 7) then color = 7
 CMP WORD [BP+10],7	
 JLE _L46
 MOV WORD [BP+10],7

_L46:
 JMP _L44		;fall through to pset

_L42:			;case -
 DEC WORD [BP+10]	;if(--color < 0) then color = 0
 CMP WORD [BP+10],0
 JGE _L47
 MOV WORD [BP+10],0

_L47:			;fall through to pset
 JMP _L44

_L43:			;case r(otate) through the colors
 INC WORD [BP+10]	;if(++color > 7) then color = 0
 CMP WORD [BP+10],7	
 JLE _L48
 MOV WORD [BP+10],0

_L48:			;fall through to pset
_L44:			;default (illegal mode won't actually get this far)
_L11:			;case pset
 MOV BX,WORD [BP+10]	;check for color out of allowable range
 CMP BX,0
 JL _L57		;return(ERR)
 CMP BX,7
 JG _L57		;return(ERR)
 SHL BX,1		

mov	di,[bp-2]	;offset will be used repeatedly
mov	cl,[bp-7]	;mask, also
mov	al,[bp-8]	;notmask, also

JMP BYTE _L59[BX]	;switch(color)
_L59:
 DW _L49		;0
 DW _L50		;1
 DW _L51		;2
 DW _L52		;3
 DW _L53		;4
 DW _L54		;5
 DW _L55		;6
 DW _L56		;7

_L49:			;case black
mov	bx,0c000h	;blue off
mov	es,bx
and	es:[di],al	;directly and with notmask

mov	bx,0d000h	;red off
mov	es,bx
and	es:[di],al

mov	bx,0e000h	;green off
mov	es,bx
and	es:[di],al
jmp	_L58

_L50:			;case blue
mov	bx,0d000h	;red off
mov	es,bx
and	es:[di],al

mov	bx,0e000h	;green off
mov	es,bx
and	es:[di],al

mov	bx,0c000h	;blue on
mov	es,bx
or	es:[di],cl	;directly or with mask
jmp	_L58

_L51:			;case red
mov	bx,0c000h	;blue off
mov	es,bx
and	es:[di],al

mov	bx,0e000h	;green off
mov	es,bx
and	es:[di],al

mov	bx,0d000h	;red on
mov	es,bx
or	es:[di],cl
jmp	_L58

_L52:			;case magenta
mov	bx,0e000h	;green off
mov	es,bx
and	es:[di],al

mov	bx,0c000h	;blue on
mov	es,bx
or	es:[di],cl	

mov	bx,0d000h	;red on
mov	es,bx
or	es:[di],cl
jmp	_L58

_L53:			;case green
mov	bx,0c000h	;blue off
mov	es,bx
and	es:[di],al

mov	bx,0d000h	;red off
mov	es,bx
and	es:[di],al

mov	bx,0e000h	;green on
mov	es,bx
or	es:[di],cl
jmp	_L58

_L54:			;case cyan = green + blue
mov	bx,0d000h	;red off
mov	es,bx
and	es:[di],al

mov	bx,0c000h	;blue on
mov	es,bx
or	es:[di],cl	

mov	bx,0e000h	;green on
mov	es,bx
or	es:[di],cl
jmp	_L58

_L55:			;case yellow = green + red
mov	bx,0c000h	;blue off
mov	es,bx
and	es:[di],al

mov	bx,0d000h	;red on
mov	es,bx
or	es:[di],cl

mov	bx,0e000h	;green on
mov	es,bx
or	es:[di],cl
jmp	_L58

_L56:			;case white
mov	bx,0c000h	;blue on
mov	es,bx
or	es:[di],cl	

mov	bx,0d000h	;red on
mov	es,bx
or	es:[di],cl

mov	bx,0e000h	;green on
mov	es,bx
or	es:[di],cl
jmp	_L58

_L57:		;return(ERR)
 MOV AX,-1
 MOV SP,BP
 POP BP
 RET

_L58:		;return(0)
 XOR AX,AX
 MOV SP,BP
 POP BP
 RET		;end pset

_L12:		;case default (illegal mode)
 MOV AX,-1
 MOV SP,BP
 POP BP
 RET

 

 

Valid HTML 4.01 Transitional Valid CSS
Yahoo! Search
Search the web Search this site
View content labeling at ICRA.