2025-04-27 07:49:33 -04:00

2230 lines
89 KiB
NASM
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

;/*
; * Microsoft Confidential
; * Copyright (C) Microsoft Corporation 1988 - 1991
; * All Rights Reserved.
; */
;************************************************************
;**
;**
;** NAME: Support for HP PCL printers added to GRAPHICS.
;**
;** DESCRIPTION: I fixed a MS bug. MS did not initialize the variable
;** ROTATE_SW. Consequently, if you do a non-rotate after doing
;** a rotate, the picture would be printed incorrectly as a
;** rotated picture. Note this bug was in Q.01.01 and fixed for
;** Q.01.02.
;**
;** NOTES: The following bug was fixed for the pre-release version
;** Q.01.02.
;**
;** BUG (mda004)
;** ------------
;**
;** NAME: After GRAPHICS prints a rotated picture it will print pictures
;** which are not supposed to be rotated as rotated junk.
;**
;** FILES AFFECTED: GRCTRL.ASM
;**
;** CAUSE: MicroSoft was failing to initialize the variable ROTATE_SW to
;** OFF. Consequently, if you printed a picture whose corresponding
;** printbox did NOT specify a rotate after printing a picture whose
;** corresponding printbox did specify a rotate, the picture would
;** print as rotated junk.
;**
;** FIX: Initialize the variable ROTATE_SW to OFF right before going into
;** the print procedure Print_Color or Print_BW_APA.
;**
;** DOCUMENTATION NOTES: This version of GRCTRL.ASM differs from the previous
;** version only in terms of documentation.
;**
;**
;************************************************************
PAGE ,132
TITLE DOS GRAPHICS Command - Print screen Control module
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; DOS - GRAPHICS Command
;;
;;
;; File Name: GRCTRL.ASM
;; ----------
;;
;; Description:
;; ------------
;; This file contains the code for the Print Screen control module.
;;
;; Documentation Reference:
;; ------------------------
;; OASIS High Level Design
;; OASIS GRAPHICS I1 Overview
;;
;; Procedures Contained in This File:
;; ----------------------------------
;; PRT_SCR
;; DET_HW_CONFIG
;; DET_MODE_STATE
;; GET_MODE_ATTR
;; SET_UP_XLT_TAB
;; SET_CGA_XLT_TAB
;; CGA_COL2RGB
;; RGB2XLT_TAB
;; SET_EGA_XLT_TAB
;; EGA_COL2RGB
;; SET_MODE_F_XLT_TAB
;; SET_MODE_13H_XLT_TAB
;; SET_ROUNDUP_XLT_TAB
;; SET_BACKG_IN_XLT_TAB
;; RGB2BAND
;; RGB2INT
;;
;;
;; Include Files Required:
;; -----------------------
;; GRINST.EXT - Externals for GRINST.ASM
;;
;;
;; External Procedure References:
;; ------------------------------
;; FROM FILE GRINST.ASM:
;; GRAPHICS_INSTALL - Main module for installation.
;;
;; Linkage Instructions:
;; --------------------
;; Refer to GRAPHICS.ASM
;;
;; Change History:
;; ---------------
;; M001 NSM 1/30/91 New var to store the old int 10 handler
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
CODE SEGMENT PUBLIC 'CODE'
ASSUME CS:CODE,DS:CODE
.XLIST
INCLUDE GRINT2FH.EXT
INCLUDE GRBWPRT.EXT
INCLUDE GRCOLPRT.EXT
INCLUDE GRSHAR.STR
INCLUDE GRPATTRN.STR
INCLUDE GRPATTRN.EXT
INCLUDE STRUC.INC
.LIST
PRT_SCR PROC NEAR
JMP PRT_SCR_BEGIN
PAGE
;===============================================================================
;
; GRAPHICS INTERRUPT DRIVER'S DATA:
;
;===============================================================================
.xlist
PUBLIC PRT_SCR,ERROR_CODE,XLT_TAB,MODE_TYPE
PUBLIC CUR_MODE_PTR,CUR_MODE,NB_COLORS,SCREEN_HEIGHT,SCREEN_WIDTH
PUBLIC CUR_PAGE,CUR_COLUMN,CUR_ROW,NB_SCAN_LINES,SCAN_LINE_MAX_LENGTH
PUBLIC CUR_SCAN_LNE_LENGTH
PUBLIC PRT_BUF,NB_BOXES_PER_PRT_BUF,CUR_BOX,BOX_H,BOX_W
PUBLIC PRINT_SCREEN_ALLOWED,RGB
PUBLIC BIOS_INT_5H
PUBLIC OLD_INT_10H ; /* M001 */
PUBLIC ROTATE_SW
PUBLIC DET_HW_CONFIG
PUBLIC NB_CHAR_COLUMNS
PUBLIC RGB2INT
PUBLIC RGB2BAND
.list
INCLUDE GRCTRL.STR
;-------------------------------------------------------------------------------
;
; ENTRY POINT TO BIOS HARDWARE INTERRUPT 5 HANDLER
;
;-------------------------------------------------------------------------------
BIOS_INT_5H DW ? ; Pointer to BIOS int 5h
DW ?
;/* M001 BEGIN */ --------------------------------------------------------------
;
; ENTRY POINT TO BIOS HARDWARE INTERRUPT 10 HANDLER
;
;-------------------------------------------------------------------------------
OLD_INT_10H DW ? ; Pointer to BIOS int 10h
DW ?
; /* M001 END */
;-------------------------------------------------------------------------------
;
; PRINT SCREEN ERROR CODE (Used at print screen time, see GRCTRL.STR for
; error codes allowed)
;
;-------------------------------------------------------------------------------
ERROR_CODE DB 0 ; ERROR CODE 0 = NO ERROR
;-------------------------------------------------------------------------------
;
; SCREEN PIXEL: INTERNAL REPRESENTATION
;
;-------------------------------------------------------------------------------
RGB PIXEL_STR < , , > ; PIXEL := RED, GREEN, BLUE Values
;-------------------------------------------------------------------------------
;
; COLOR TRANSLATION TABLE:
;
; This table is used to translate the color numbers returned by
; Interrupt 10H Read Dot and Read Character calls into print
; information. The table consists of 256 entries, one byte each,
; indexed by color number.
; In the case of black and white printing, the table
; entries are grey scale intensities from 0 to 63. In the case
; of color printing each table entry contains a "band mask" indicating
; which color print bands are required to generate the required color.
; The band masks are simply bit masks where each bit corresponds to one
; of the printer bands.
;
; The table is set up at the beginning of the print screen processing,
; before any data is read from the screen. From then on, translating
; from screen information into print information is done quickly by
; accessing this table. Not all 256 entries are initialized for each
; screen print. The number of entries used is equal to the number
; of colors available concurrently with the given display mode.
;-------------------------------------------------------------------------------
XLT_TAB DB 256 DUP(32) ; COLOR TRANSLATION TABLE
; This table is used to translate the Color Dot
; or Byte Attribute to a Band Mask for color
; printing or to a Grey Intensity for Mono-
; chrome printing.
;-------------------------------------------------------------------------------
;
; CURRENT VIDEO MODE ATTRIBUTES
;
;-------------------------------------------------------------------------------
MODE_TYPE DB ? ; Mode types (bit mask) APA or TXT
CUR_MODE_PTR DW ? ; DISPLAYMODE INFO RECORD for the current
; mode (defined in the shared data area).
CUR_MODE DB ? ; Current video mode number
NB_COLORS DW ? ; Number of colors supported by this mode
SCREEN_HEIGHT DW ? ; Number of rows on the screen (chars or pixels)
SCREEN_WIDTH DW ? ; Number of columns on the screen (chars/pixels)
; (for text modes is equal to NB_CHAR_COLUMNS)
NB_CHAR_COLUMNS DB ? ; Number of columns on the screen if in txt mode
CUR_PAGE DB ? ; Active page number
ROTATE_SW DB ? ; Switch: if "ON" then, must print sideways
;-------------------------------------------------------------------------------
;
; ACTIVE SCREEN ATTRIBUTES
;
;-------------------------------------------------------------------------------
CUR_COLUMN DW ? ; Current pixel/char column number
CUR_ROW DW ? ; Current pixel/char row number
NB_SCAN_LINES DW ? ; Number of screen scan lines
SCAN_LINE_MAX_LENGTH DW ? ; Maximum number of dots/chars per scan line
CUR_SCAN_LNE_LENGTH DW ? ; Length in pels/chars of the current scan line
;-------------------------------------------------------------------------------
;
; PRINTER VARIABLES
;
;-------------------------------------------------------------------------------
PRT_BUF DB ?,?,?,? ; PRINT BUFFER
NB_BOXES_PER_PRT_BUF DB ? ; Number of boxes fitting in the print buffer
CUR_BOX DB ?,?,?,? ; BOX = PRINTER REPRESENTATION OF 1 PIXEL
BOX_H DB ? ; HEIGHT OF THE BOX
BOX_W DB ? ; WIDTH OF THE BOX
;-------------------------------------------------------------------------------
;
; CONTROL VARIABLES:
;
; This data is used to communicate between the Installation Modules
; and the Resident Print Screen Modules.
;-------------------------------------------------------------------------------
PRINT_SCREEN_ALLOWED DB YES; Used to avoid print screens
; while the GRAPHICS installation
; (or re-install) is in progress
; Set by GRAPHICS_INSTALL module.
PAGE
;===============================================================================
;
; INTERRUPT 5 DRIVER'S CODE:
;
;-------------------------------------------------------------------------------
;===============================================================================
;
; PRT_SCR : PRINT THE ACTIVE SCREEN
;
;-------------------------------------------------------------------------------
;
; INPUT: SHARED_DATA_AREA_PTR = Offset of the data area used for
; passing data between the
; Installation process and the Print
; Screen process.
; PRINT_SCREEN_ALLOWED = Switch. Set to "No" if currently
; installing GRAPHICS.COM
;
; NOTE: These 2 variables are declared within
; PRT_SCR but initialized by the
; Installation process GRAPHICS_INIT
; OUTPUT: PRINTER
;
; CALLED BY: INTERRUPT 5
;
;
;-------------------------------------------------------------------------------
;
; DESCRIPTION:
;
; PRINT THE ACTIVE SCREEN for all TEXT and All Points Addressable (APA)
; display modes available with either a MONO, CGA, EGA, or VGA video
; adapter on a Black and White or Color printer.
;
; INITIALIZATION:
;
; Each pixel or character on the screen has a color attribute. These
; colors must be translated into different internal representations:
;
; For printing in colors, each color is translated to a BAND MASK.
; The Band Mask indicates how to obtain this color on the printer.
;
; For printing in Black and White, each color is translated to a
; GREY INTENSITY number between 0 (black) and 63 (white).
;
; The BAND MASK or the GREY INTENSITIES are found in the COLOR
; TRANSLATION TABLE. This table is initialized before calling any of
; the print screen modules.
;
; PRINT SCREEN TIME:
;
; When a pixel or character is read off the screen by one of the print
; screen modules, its color is used as an index into the translation
; table.
;
;
; LOGIC:
;
; IF SCREEN_PRINTS_ALLOWED=NO ; Block print screens until Installation
; THEN IRET ; Process (or re-install!) is finished.
; ELSE
;
; CALL DET_HW_CONFIG ; Determine hardware configuration
; CALL DET_MODE_STATE ; Determine video mode and active page
; CALL GET_MODE_ATTR ; Get video attributes (TXT or APA, etc)
;
; IF MODE_TYPE = TXT AND Number of colors = 0
; THEN Invoke BIOS INTERRUPT 5
; ELSE
; IF PRINTER_TYPE = BLACK_WHITE
; THEN
; IF MODE_TYPE = TXT
; THEN Invoke BIOS INTERRUPT 5
; ELSE ; Mode is APA
; CALL SET_UP_XLT_TAB ; Set up the color translation table
; CALL PRINT_BW_APA ; Print the active screen on a B&W printer
; ELSE ; Color printer attached
; CALL SET_UP_XLT_TAB ; Set up the color translation table
; CALL PRINT_COLOR ; Print the active screen on a Color prt.
; IRET
;
PRT_SCR_BEGIN:
PUSH AX ; Save Registers
PUSH BX ;
PUSH CX ;
PUSH DX ;
PUSH SI ;
PUSH DI ;
PUSH BP ;
PUSH DS ;
PUSH ES ;
;
CLD ; Clear direction flag
PUSH CS ; DS := CS
POP DS
;-------------------------------------------------------------------------------
; Verify if we are allowed to print (not allowed if currently installing
; GRAPHICS or printing a screen):
;-------------------------------------------------------------------------------
CMP PRINT_SCREEN_ALLOWED,NO ; IF not allowed to print
JE PRT_SCR_RETURN ; THEN quit
; ELSE print the screen:
;-------------------------------------------------------------------------------
; INITIALIZATION:
;-------------------------------------------------------------------------------
PRT_SCR_INIT: ; Disable print screen while
MOV PRINT_SCREEN_ALLOWED,NO ; we are printing the current
; screen.
MOV BP,SHARED_DATA_AREA_PTR ; BP := Offset Shared Data Area
MOV ERROR_CODE,NO_ERROR ; No error so far.
CALL DET_HW_CONFIG ; Determine the type of display adapter
CALL DET_MODE_STATE ; Init CUR_PAGE, CUR_MODE
CALL GET_MODE_ATTR ; Determine if APA or TXT, nb. of colors,
; and screen dimensions in pels or characters.
;
; Test the error code returned by GET_MODE_ATTR:
;
TEST ERROR_CODE,MODE_NOT_SUPPORTED ;If mode not supported then,
JNZ DO_BEEP ; let BIOS give it a try.
;------------------------------------------------------------------------------
; Check the printer type:
;------------------------------------------------------------------------------
.IF <DS:[BP].PRINTER_TYPE EQ BLACK_WHITE> ; Is a black and white printer
.THEN ; attached ?
;------------------------------------------------------------------------------
; A Black and White printer is attached
;------------------------------------------------------------------------------
CMP MODE_TYPE,TXT ; Is the screen in text mode ?
JNE INVOKE_PRINT_ROUTINE ; No, call GRAPHICS B&W routine
JMP SHORT EXIT_TO_BIOS ; Yes, give control to BIOS INTERRUPT 5
.ELSE
;------------------------------------------------------------------------------
; A Color printer is attached
;------------------------------------------------------------------------------
CMP NB_COLORS,0 ; Is the screen in a Monochrome
JNE INVOKE_PRINT_ROUTINE
TEST MODE_TYPE,TXT ; text mode ?
JNZ INVOKE_PRINT_ROUTINE
JMP SHORT EXIT_TO_BIOS ; Yes, let BIOS INTERRUPT 5 handle it
; No, we handle it.
.ENDIF ; ENDIF black and white or color printer
;-------------------------------------------------------------------------------
;
; Call the print routine (which is either PRINT_COLOR or PRINT_BW_APA)
;
;-------------------------------------------------------------------------------
INVOKE_PRINT_ROUTINE:
CALL SET_UP_XLT_TAB ; Set up the color translation table
; \/ ~~mda(004) ----------------------------------------------------------------
; The following fixes a MS bug. MS was failing to initialize
; the variable ROTATE_SW to off. Consequently, if you printed a
; picture whose corresponding printbox did NOT specify a rotate
; after printing a picture whose corresponding printbox did
; specify a rotate, the picture would print rotated.
MOV ROTATE_SW,OFF ; Set printing to standard unless otherwise
; set to rotate via PRINT_OPTIONS.
; /\ ~~mda(004) ----------------------------------------------------------------
CALL PRINT_MODULE_START ; Call the print modules that were
; made resident at Install time.
MOV PRINT_SCREEN_ALLOWED,YES; Enable PrtScr for next calls
;-----------------------------------------------------------------------------
; Test the error code returned by either PRINT_COLOR or PRT_BW_APA
;-----------------------------------------------------------------------------
TEST ERROR_CODE,UNABLE_TO_PRINT ; If unable to print the screen
JNZ SHORT EXIT_TO_BIOS ; then, let BIOS give it a try
PRT_SCR_RETURN:
; Restore registers
POP ES ;
POP DS ;
POP BP ;
POP DI ;
POP SI ;
POP DX ;
POP CX ;
POP BX ;
POP AX ;
;
IRET ; Return control to interrupted
; process
; give a beep for modes not supported by graphics
DO_BEEP:
mov ah,2 ; console output
mov dx,7 ; ^G - beep for modes not supported
int 21h
EXIT_TO_BIOS:
; Restore registers
POP ES ;
POP DS ;
POP BP ;
POP DI ;
POP SI ;
POP DX ;
POP CX ;
POP BX ;
POP AX ;
CLI ; Disable interrupts
MOV CS:PRINT_SCREEN_ALLOWED,YES ; Enable PrtScr for next calls
JMP DWORD PTR CS:BIOS_INT_5H ; Exit to BIOS INTERRUPT 5
PRT_SCR ENDP
;===============================================================================
;
; PRT_SCR MODULES:
;
;-------------------------------------------------------------------------------
PAGE
;===============================================================================
;
; DET_HW_CONFIG : DETERMINE WHAT TYPE OF VIDEO HARDWARE IS PRESENT
;
;-------------------------------------------------------------------------------
;
; INPUT: BP = Offset of the shared data area
;
; OUTPUT: HARDWARE_CONFIG is updated in the shared data area
;
; CALLED BY: PRT_SCR
;
; EXTERNAL CALLS: BIOS INT 10H
;
;-------------------------------------------------------------------------------
;
; LOGIC:
; Issue BIOS INT10H Get Display Configuration Code (AX=1A00H)
; IF AL = 1AH THEN /* VGA (PS/2 OR BRECON-B) */
; /* BL = active DCC */
; /* BH = alternate DCC */
; /* Display Code: */
; /* 1 - Mono Adapter */
; /* 2 - CGA */
; /* 4 - EGA with Mono Display */
; /* 5 - EGA with Color Display */
; /* 7 - PS/2 Mod 50,60,80 OR BRECON-B with Mono Display */
; /* 8 - PS/2 Mod 50,60,80 OR BRECON-B with Color Display */
; /* B - PS/2 Mod 30 with Mono Display */
; /* C - PS/2 Mod 30 with Color Display */
; IF AL = 1AH THEN /* Call is supported */
; Set HARDWARE_CONFIG byte based on DCC returned in DL
; ELSE
; Issue INT 10H EGA Info (AH=12H BL=10H)
; IF BL <> 10H THEN /* EGA */
; Set EGA bit in HARDWARE_CONFIG
; ELSE /* CGA or */
; Issue INT 10H PC CONVERTIBLE Physical display description param.
; request. (AH=15H)
; IF ES:[DI] = 5140H
; THEN
; Set PC_CONVERTIBLE bit in HARDWARE_CONFIG
; ELSE
; Set OLD_ADAPTER bit in HARDWARE_CONFIG
; ENDIF
; ENDIF
; ENDIF
; RETURN
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
DET_HW_CONFIG PROC NEAR
;-------------------------------------------------------------------------------
;
; Try to read display combination code (PS/2 call):
;
;-------------------------------------------------------------------------------
MOV AX,READ_CONFIG_CALL
INT 10H ; Call video BIOS
.IF <AL EQ 1AH> ; If call is supported
.THEN
;-------------------------------------------------------------------------------
;
; Call is supported, PS/2 BIOS is present (Model 39,50,60,80 or BRECON-B card),
; Determine what is the primary video adapter:
;
;-------------------------------------------------------------------------------
.SELECT
.WHEN <BL EQ 1> OR ; MONO or
.WHEN <BL EQ 2> ; CGA
MOV DS:[BP].HARDWARE_CONFIG,OLD_ADAPTER
.WHEN <BL EQ 4> OR ; EGA with Mono or
.WHEN <BL EQ 5> ; EGA with Color
MOV DS:[BP].HARDWARE_CONFIG,EGA
.WHEN <BL EQ 7> OR ; BRECON-B with Mono or
.WHEN <BL EQ 8> ; BRECON-B with Color
MOV DS:[BP].HARDWARE_CONFIG,ROUNDUP
.WHEN <BL EQ 0Bh> OR ; PS/2 Model 30 with Mono or
.WHEN <BL EQ 0Ch> ; PS/2 Model 30 with Color
MOV DS:[BP].HARDWARE_CONFIG,PALACE
.ENDSELECT
;-------------------------------------------------------------------------------
;
; PS/2 call is not supported, try the EGA info call:
;
;-------------------------------------------------------------------------------
.ELSE
MOV AH,ALT_SELECT_CALL ; Request Alternate select's
MOV BL,EGA_INFO_CALL ; "return EGA information call"
INT 10H ; Call video BIOS
.IF <BL NE EGA_INFO_CALL> ; If a memory value is returned
.THEN ; then, there is an EGA
MOV DS:[BP].HARDWARE_CONFIG,EGA
.ELSE ; else, call is not supported:
;-------------------------------------------------------------------------------
;
; EGA call is not supported, try the PC CONVERTIBLE display description call:
;
;-------------------------------------------------------------------------------
MOV AH,DISP_DESC_CALL
INT 10H ; Call BIOS, ES:DI :=Offset of parms
.IF <ES:[DI] EQ 5140H> ; If LCD display type,
.THEN ; set LCD bit in Shared Data area
MOV DS:[BP].HARDWARE_CONFIG,PC_CONVERTIBLE
.ELSE ; else, we have an old adapter.
MOV DS:[BP].HARDWARE_CONFIG,OLD_ADAPTER ; (either MONO or CGA)
.ENDIF ; Display type is LCD
.ENDIF ; EGA BIOS is present
.ENDIF ; PS/2 BIOS is present
RET
DET_HW_CONFIG ENDP
PAGE
;=======================================================================
;
; DET_MODE_STATE : Determine the current video mode and the active page.
;
;-----------------------------------------------------------------------
;
; INPUT: HARDWARE_CONFIG = Type of video hardware attached
;
; OUTPUT: CUR_MODE = Video mode number (0-13H)
; CUR_PAGE = Video page number (0-8)
; NB_CHAR_COLUMNS = Number of columns if in a text mode.
;
;
; CALLED BY: PRT_SCR
;
;
;-------------------------------------------------------------------------------
;
; DESCRIPTION: Use the BIOS interface to
; obtain the current mode and active page.
;
; LOGIC:
;
; Call BIOS INTERRUPT 10H: "Return current video state" (AH = 0fh)
;
DET_MODE_STATE PROC NEAR
PUSH AX
PUSH BX
MOV AH,GET_STATE_CALL
INT 10H ; CALL BIOS
MOV CUR_MODE,AL
MOV NB_CHAR_COLUMNS,AH
MOV CUR_PAGE,BH
POP BX
POP AX
RET
DET_MODE_STATE ENDP
PAGE
;=======================================================================
;
; GET_MODE_ATTR: Obtain attributes of current video mode.
;
;-----------------------------------------------------------------------
;
; INPUT: CUR_MODE = Current video mode (1 BYTE)
;
; OUTPUT: MODE_TYPE = Video mode type (TXT or APA)
; NB_COLORS = Maximum number of colors (0-256) (0=B&W)
; ERROR_CODE = Error code if error occurred.
; SCREEN_HEIGHT= Number of rows (in pixels if APA or char if TEXT)
; SCREEN_WIDTH = Number of columns (in pixels/char)
;
; CALLED BY: PRT_SCR
;
;
;-----------------------------------------------------------------------
;
; DESCRIPTION: Scan the 2 local video mode attribute tables until the
; current mode is located. Return the attributes.
; For APA modes SCREEN_HEIGHT and SCREEN_WIDTH are in pixels,
; for TEXT modes they are in characters.
;
;
; LOGIC:
;
; Scan the APA_ATTR_TABLE
; IF FOUND
; MODE_TYPE := APA
; NB_COLORS := mode.MAX_COLORS
; SCREEN_HEIGHT := mode.NB_L
; SCREEN_WIDTH := mode.NB_C
; ELSE
; Scan the TXT_ATTR_TABLE
; When FOUND
; MODE_TYPE := TXT
; NB_COLORS := mode.NUM_COLORS
; SCREEN_WIDTH := NB_CHAR_COLUMNS
; SCREEN_HEIGHT := Byte in ROM BIOS at 40:84
;
;-----------------------------------------------------------------------
GET_MODE_ATTR PROC NEAR
JMP SHORT GET_MODE_ATTR_BEGIN
;-----------------------------------------------------------------------
;
; LOCAL DATA
;
;-----------------------------------------------------------------------
APA_ATTR STRUC ; ATTRIBUTES FOR APA MODES:
APA_MODE DB ? ; Mode number
NB_C DW ? ; Number of columns
NB_L DW ? ; Number of lines
MAX_COLORS DW ? ; Maximum number of colors available (0=B&W)
APA_ATTR ENDS
TXT_ATTR STRUC ; ATTRIBUTES FOR TXT MODES:
TXT_MODE DB ? ; Mode number
NUM_COLORS DB ? ; Number of colors
TXT_ATTR ENDS
;-----------------------------------------------------------------------
;
; APA MODE ATTRIBUTES:
;
;-----------------------------------------------------------------------
NB_APA_MODES DW 10
APA_ATTR_TABLE LABEL WORD
MODE04 APA_ATTR < 4,320,200, 4>
MODE05 APA_ATTR < 5,320,200, 4>
MODE06 APA_ATTR < 6,640,200, 2>
MODE0D APA_ATTR <0DH,320,200, 16>
MODE0E APA_ATTR <0EH,640,200, 16>
MODE0F APA_ATTR <0FH,640,350, 4>
MODE10H APA_ATTR <10H,640,350, 16>
MODE11H APA_ATTR <11H,640,480, 2>
MODE12H APA_ATTR <12H,640,480, 16>
MODE13H APA_ATTR <13H,320,200,256>
;-----------------------------------------------------------------------
;
; TXT MODE ATTRIBUTES:
;
;-----------------------------------------------------------------------
NB_TXT_MODES DW 5
TXT_ATTR_TABLE LABEL WORD
MODE00 TXT_ATTR < 0, 16>
MODE01 TXT_ATTR < 1, 16>
MODE02 TXT_ATTR < 2, 16>
MODE03 TXT_ATTR < 3, 16>
MODE07 TXT_ATTR < 7, 0>
;-----------------------------------------------------------------------
;
; BEGIN OF GET_MODE_ATTR
;
;-----------------------------------------------------------------------
GET_MODE_ATTR_BEGIN:
PUSH AX
PUSH BX
PUSH CX
PUSH DX
MOV DL,CUR_MODE ; DL = CURRENT MODE
;
; Scan the APA_ATTR_TABLE
;
MOV CX,NB_APA_MODES ; CS <-- Number of APA modes
MOV BX,OFFSET APA_ATTR_TABLE; BX <-- Offset of APA mode table
SCAN_APA:
CMP DL,[BX].APA_MODE ; IF mode found
JE SHORT ITS_APA ; THEN get its attributes
ADD BX,SIZE APA_ATTR
LOOP SCAN_APA ; ELSE keep scanning
JMP SHORT SCAN_TXT_INIT ; NOT in this table: scan txt modes
ITS_APA:
MOV MODE_TYPE,APA ; MODE = APA
MOV AX,[BX].MAX_COLORS
MOV NB_COLORS,AX ; Get number of colors
MOV AX,[BX].NB_L
MOV SCREEN_HEIGHT,AX ; Get number of lines
MOV AX,[BX].NB_C
MOV SCREEN_WIDTH,AX ; Get number of columns
JMP SHORT GET_MODE_ATTR_END
;
; Scan the TXT_ATTR_TABLE
;
SCAN_TXT_INIT:
MOV CX,NB_TXT_MODES ; CX <-- Number of TXT modes
MOV BX,OFFSET TXT_ATTR_TABLE; BX <-- Offset of TXT mode table
SCAN_TXT:
CMP DL,[BX].TXT_MODE ; IF mode found
JE SHORT ITS_TXT ; THEN get its attributes
ADD BX,SIZE TXT_ATTR
LOOP SCAN_TXT ; ELSE keep scanning
ITS_TXT:
MOV MODE_TYPE,TXT ; MODE = TXT
MOV AL,[BX].NUM_COLORS
CBW
MOV NB_COLORS,AX ; Get number of colors
MOV AL,NB_CHAR_COLUMNS ; Get number of columns
CBW
MOV SCREEN_WIDTH,AX
.IF <DS:[BP].HARDWARE_CONFIG EQ OLD_ADAPTER>; If an old adapter is there
.THEN ; The number of lines is 25
MOV SCREEN_HEIGHT,25
.ELSE
MOV AX,BIOS_SEG ; Get number of rows
MOV ES,AX ; from BIOS Data Area
MOV BX,NB_ROWS_OFFSET ; at 0040:0084
MOV AL,ES:[BX]
CBW
INC AX
MOV SCREEN_HEIGHT,AX
.ENDIF
JMP SHORT GET_MODE_ATTR_END
;
; The current mode was not found in any of the tables
;
MOV ERROR_CODE,MODE_NOT_SUPPORTED
GET_MODE_ATTR_END:
POP AX
POP BX
POP CX
POP DX
RET
GET_MODE_ATTR ENDP
PAGE
;=======================================================================
;
; SET_UP_XLT_TABLE : SET UP A COLOR MAPPING FOR EACH COLOR AVAILABLE
; WITH THE CURRENT MODE
;
;-----------------------------------------------------------------------
;
; INPUT: CUR_MODE = Current video mode.
; HARDWARE_CONFIG = Type of display adapter.
; PRINTER_TYPE = Type of printer attached (Color or B&W)
; XLT_TAB = Color translation table.
; CUR_PAGE = Active page number
; BP = Offset of the shared data area
;
;
; OUTPUT: XLT_TAB IS UPDATED
;
; CALLED BY: PRT_SCR
;
;-----------------------------------------------------------------------
;
; DESCRIPTION: The table is updated to hold a mapping for each color
; available in the current video mode either TEXT or APA.
;
; For example, if the current mode supports 16 colors then the first
; sixteen bytes of the table will hold the corresponding Color printer
; or Black and White printer mappings for these colors.
;
;
; LOGIC:
;
; IF HARDWARE_CONFIG = CGA OR HARDWARE_CONFIG = PC_CONVERTIBLE
; THEN
; CALL SET_CGA_XLT_TAB
;
; ELSE IF HARDWARE_CONFIG = EGA
; THEN
; CALL SET_EGA_XLT_TAB
;
; ELSE IF CUR_MODE = 0FH
; THEN
; CALL SET_MODE_F_XLT_TAB
;
; ELSE IF CUR_MODE = 19
; THEN
; CALL SET_MODE_13H_XLT_TAB
;
; ELSE
; CALL SET_ROUNDUP_XLT_TAB
;
; CALL SET_BACKG_IN_XLT_TAB ; Update the background in the translation table
;
SET_UP_XLT_TAB PROC NEAR
;-------------------------------------------------------------------------------
; For old display modes: set up translation table as for a Color Graphics Adapt.
; Either 4 or 16 colors are set up depending if the mode is an APA or text mode.
;
; NOTE: SET_UP_XLT_TAB cannot be invoked if the display adater is a Monochrome
; display adater. (When a Mono. adapter is attached, a jump is made to
; the ROM BIOS for printing the screen, and no translation table is set).
;-------------------------------------------------------------------------------
.IF <BIT DS:[BP].HARDWARE_CONFIG NZ OLD_ADAPTER> OR ; IF it is a CGA
.IF <BIT DS:[BP].HARDWARE_CONFIG NZ PC_CONVERTIBLE> ; or a PC convertible
.THEN ; THEN set up CGA colors
CALL SET_CGA_XLT_TAB ;
.ELSEIF <BIT DS:[BP].HARDWARE_CONFIG NZ EGA> ; ELSEIF it is an EGA
CALL SET_EGA_XLT_TAB ; set up EGA colors.
.ELSEIF <CUR_MODE EQ 0FH> ; ELSEIF we are in mode 15
CALL SET_MODE_F_XLT_TAB ; set up its 4 shades
;-------------------------------------------------------------------------------
; A PS/2 system is attached: (we either have a PALACE [Model 30] or a ROUNDUP)
;-------------------------------------------------------------------------------
.ELSEIF <CUR_MODE EQ 13H> ; ELSEIF current mode is 13h
CALL SET_MODE_13H_XLT_TAB ; set up 256 colors
.ELSEIF <BIT DS:[BP].HARDWARE_CONFIG NZ PALACE> ; ELSEIF PS/2 Model 30(MCGA)
CALL SET_CGA_XLT_TAB ; handle it like a CGA
.ELSE ; ELSE we have a ROUNDUP
;-------------------------------------------------------------------------------
; A PS/2 model 50, 60 or 80 or an ADA 'B' card is attached (in 16 color mode):
;-------------------------------------------------------------------------------
CALL SET_ROUNDUP_XLT_TAB ; set up 16 colors
.ENDIF
;-------------------------------------------------------------------------------
; Finish setting up the translation table:
;-------------------------------------------------------------------------------
CALL SET_BACKG_IN_XLT_TAB ; Update the background in the translation table
; according to the command line switch setting
; (i.e.,/R /B)
RET
SET_UP_XLT_TAB ENDP
PAGE
;===============================================================================
;
; SET_BACKG_IN_XLT_TAB : ADJUST THE MAPPING FOR THE BACKGROUND COLOR IN THE
; XLT_TAB ACCORDING TO PRINTER TYPE AND /R /B.
;
;
;-------------------------------------------------------------------------------
;
; INPUT: BP = Offset of shared data area (SWITCHES)
; XLT_TAB = The color translation table.
;
; OUTPUT: XLT_TAB IS UPDATED
;
;-------------------------------------------------------------------------------
;
; DESCRIPTION: If there is a black and white printer and /R is NOT specified
; then the background color should not be printed and it is replaced in the
; translation table by the Intensity for white (will print nothing).
;
; If a color printer is attached and /B is not specified then the background
; color is replaced by the Print Band mask for white.
;
; LOGIC:
; IF (a black and white printer is attached) AND (/R is OFF)
; THEN
; MOV XLT_TAB, WHITE_INT ; Store white in translation table
; ELSE (a color printer is attached)
; IF (/B is ON)
; THEN
; RGB.R := MAX_INT
; RGB.G := MAX_INT
; RGB.B := MAX_INT
; CALL RGB2BAND ; Convert RGB for white to a Band Mask
; MOV XLT_TAB,AL ; Store the band mask in the xlt table
;
;
;-------------------------------------------------------------------------------
SET_BACKG_IN_XLT_TAB PROC NEAR
;-------------------------------------------------------------------------------
;
; Test if a black and white printer is attached.
;
;-------------------------------------------------------------------------------
.IF <BIT DS:[BP].PRINTER_TYPE NZ BLACK_WHITE> AND ; IF black and white
.IF <BIT DS:[BP].SWITCHES Z REVERSE_SW> ; printer and not /R
.THEN ; then, map background
MOV XLT_TAB,WHITE_INT ; to white.
;-------------------------------------------------------------------------------
;
; A Color printer is attached:
;
;-------------------------------------------------------------------------------
.ELSEIF <BIT DS:[BP].PRINTER_TYPE NZ COLOR> AND ; else, if color printer
.IF <BIT DS:[BP].SWITCHES Z BACKGROUND_SW> ; and /B if OFF
.THEN ;
; Store a null band mask
MOV XLT_TAB,0 ; the translation table.
.ENDIF
RET
SET_BACKG_IN_XLT_TAB ENDP
PAGE
;=======================================================================
;
; SET_EGA_XLT_TAB : SET UP COLOR TRANSLATION TABLE FOR ENHANCED GRAPHIC
; ADAPTER
;
;-----------------------------------------------------------------------
;
; INPUT: XLT_TAB = Color translation table.
; PRINTER_TYPE = Type of printer attached (Color or B&W)
; SWITCHES = GRAPHICS command line parameters.
;
; OUTPUT: XLT_TAB IS UPDATED
;
; CALLED BY: SET_UP_XLT_TABLE
;
;-----------------------------------------------------------------------
;
; NOTES: With the EGA, "VIDEO BIOS READ DOT call" returns an index into
; the 16 EGA palette registers.
;
; These registers contain the actual colors stored as rgbRGB components
; (see EGA_COL2RGB for details) for mode hex 10. Under mode hex E these
; registers contain the actual colors as I0RGB components (see CGA_COL2RGB
; for details).
;
; These registers can be Revised by the user but, are 'WRITE ONLY'.
; However, it is possible to define a SAVE AREA where BIOS will maintain
; a copy of the palette registers.
;
; This area is called the "DYNAMIC SAVE AREA" and is defined via the
; BIOS EGA SAVE_PTR AREA. Whenever the palette registers are changed by
; the user, BIOS updates the EGA_SAVE_AREA.
;
; The 16 palette registers are the first 16 bytes of the DYNAMIC SAVE AREA.
;
; This program takes advantage of this feature and consults the EGA DYNAMIC
; SAVE AREA in order to obtain the colors used in the active screen.
;
;
; DESCRIPTION: Obtain each color available with an EGA by reading its
; palette register in the EGA_SAVE_AREA:
;
; Calculate the mapping for this color, either a BAND_MASK or a
; GREY INTENSITY and store it in the color translation table.
;
;
; LOGIC:
;
; Obtain the DYNAMIC EGA SAVE AREA offset from the BIOS SAVE_PTR_AREA.
;
; If current mode is either 4,5 or 6
; Then,
; CALL SET_CGA_XLT_TAB
; Get the background color by reading palette register number 0
; Else,
; For each register number (0 to 15):
; Get the register contents (rgbRGB values) from the EGA SAVE AREA
; CALL EGA_COL2RGB ; Obtain the Red, Green, Blue values
; CALL RGB2XLT_TAB ; Obtain a Band Mask or a Grey Intensity
; ; and store the result in the XLT_TAB
;
SET_EGA_XLT_TAB PROC NEAR
PUSH AX ; Save the registers used
PUSH BX
PUSH CX
PUSH DX
PUSH DI
;-------------------------------------------------------------------------------
;
; Obtain the pointer to the DYNAMIC SAVE AREA from the SAVE AREA POINTER TABLE:
;
;-------------------------------------------------------------------------------
EGA_SAVE_PTR EQU 4A8H ; EGA BIOS pointer to table of
; pointer to save areas.
XOR AX,AX ; ES segment := paragraph 0
MOV ES,AX
LES BX,ES:DWORD PTR EGA_SAVE_PTR ; ES:BX := Pointer to ptr table
LES BX,ES:[BX]+4 ; ES:BX := Pointer to dynamic save area
; (NOTE: It is the second pointer in
; the table)
;-------------------------------------------------------------------------------
;
; Set up one entry in the translation table for each color available.
;
;-------------------------------------------------------------------------------
.IF <CUR_MODE EQ 4> OR ; If the current mode is an old CGA
.IF <CUR_MODE EQ 5> OR ; GRAPHICS mode:
.IF <CUR_MODE EQ 6>
.THEN
;-------------------------------------------------------------------------------
; Current mode is either mode 4, 5 or 6;
; Store each color of the old CGA All Points Addressable mode:
;-------------------------------------------------------------------------------
CALL SET_CGA_XLT_TAB ; Set up colors in the translation
; table, NOTE: The background color
; will not be set properly since the
; EGA BIOS does not update memory
; location 40:66 with the value
; of the background color as CGA
; does.
;------Adjust the background color in the translation table:
;------The background color is obtained from the EGA DYNAMIC SAVE AREA
;------ES:BX = Address of the EGA DYNAMIC SAVE AREA
;------NOTE : For CGA compatible modes EGA BIOS stores the color in the
;------DYNAMIC SAVE AREA as a I0RGB value.
XOR DI,DI ; DI:=register number = index in XLT_TAB
MOV AL,ES:[BX][DI] ; AL:=Palette register 0 = Back. color
MOV AH,AL ; Convert I0RGB to IRGB (CGA color)
AND AL,111B ; Isolate RGB bits
AND AH,10000B ; Isolate I bit
SHR AH,1 ; Move I bit from position 5 to 4
OR AL,AH ; Get IRGB byte.
CALL CGA_COL2RGB ; Convert IRGB to R,G,B values
CALL RGB2XLT_TAB ; Convert RGB to an entry in XLT_TAB
.ELSE ; ELSE, we have an EGA graphics mode:
;-------------------------------------------------------------------------------
; The current mode is a either a text mode or one of the EGA enhanced mode;
; Store in the translation table each color available (these modes have 16 col.)
;-------------------------------------------------------------------------------
MOV CX,16 ; CX := Number of palette registers
; to read
XOR DI,DI ; DI := Palette register number
; and index in the translation table
STORE_1_EGA_COLOR:
MOV AL,ES:[BX][DI] ; AL := Palette register
.IF <CUR_MODE EQ 14> OR ; If mode E (hex) OR mode D (hex)
.IF <CUR_MODE EQ 13> ; the colors are
.THEN ; stored as I0CGA colors
MOV AH,AL ; Convert I0RGB to IRGB (CGA color)
AND AL,111B ; Isolate RGB bits
AND AH,10000B ; Isolate I bit
SHR AH,1 ; Move I bit from position 5 to 4
OR AL,AH ; Get IRGB byte.
CALL CGA_COL2RGB ; Convert IRGB to R,G,B values
.ELSE ; Else, they are stored as (rgbRGB);
CALL EGA_COL2RGB ; Convert register to R,G,B values
.ENDIF
CALL RGB2XLT_TAB ; Convert RGB to an entry in XLT_TAB
INC DI ; Get next palette register number
LOOP STORE_1_EGA_COLOR
.ENDIF ; ENDIF 4 colors or 16 colors
POP DI ; Restore the registers
POP DX
POP CX
POP BX
POP AX
RET
SET_EGA_XLT_TAB ENDP
PAGE
;=======================================================================
;
; SET_CGA_XLT_TAB : SET UP COLOR TRANSLATION TABLE FOR COLOR GRAPHIC
; ADAPTER
;
;-----------------------------------------------------------------------
;
; INPUT: XLT_TAB = Color translation table.
; PRINTER_TYPE = Type of printer attached (Color or B&W)
; SWITCHES = GRAPHICS command line parameters.
;
; OUTPUT: XLT_TAB IS UPDATED
;
; CALLED BY: SET_UP_XLT_TABLE
;
;-----------------------------------------------------------------------
;
; NOTES: With the CGA, the "VIDEO BIOS READ DOT call" returns a number
; from 0 to 3. A dot of value 0 is of the background color.
;
; The actual value of the background color is stored in BIOS VIDEO
; DISPLAY DATA AREA as a PIIRGB value (see CGA_COL2RGB for details) and
; can be any of 16 colors.
;
; A dot of value 1,2, or 3 represents any of 2 specific colors depending
; on the current color palette.
;
; The palette number is obtained from the BIOS VIDEO DISPLAY DATA AREA
; (It is the "P" bit or bit number 5)
;
; The dot values 1,2,3 expressed in binary actually represent the RG
; (Red, Green) components of the color.
;
; The palette number represents the B (Blue) component therefore, when
; the palette number is appended to the color number we obtain the RGB
; components for that color.
;
; (E.G., COLOR = 010 ; COLOR # 2
; PALETTE= 0 ; PALETTE # 0
;
; IRGB = 0100 ; Intensity = 0 Ŀ
; ; Red = 1 <20><><EFBFBD><EFBFBD>> color = Red
; ; Green = 0 <20>
; ; Blue = 0 <20><>
;
;
; DESCRIPTION:
;
; For each color available with a CGA:
; Calculate the color mapping, either a BAND_MASK or a GREY
; INTENSITY and store it in the color translation table.
;
; LOGIC:
;
; ; Obtain the background color from VIDEO BIOS DATA AREA
; ; and the paletter number
;
; ; Store the Background color:
; CALL CGA_COL2RGB ; Convert IRGB components to RGB values
; CALL RGB2XLT_TAB ; Convert RGB to an entry in the translation
; ; table
; ; Store all other colors:
; FOR IRG := 1 TO 3 ; Obtain the color number
; Append palette number (B) to IRG
; CALL CGA_COL2RGB ; Convert color to RGB values
; CALL RGB2XLT_TAB ; Convert RGB to an entry in the translation
; ; table
;
SET_CGA_XLT_TAB PROC NEAR
PUSH AX
PUSH BX
PUSH CX
PUSH DI
PUSH ES
.IF <CUR_MODE EQ 4> OR
.IF <CUR_MODE EQ 5>
;===============================================================================
;
; THE CURRENT MODE IS MODE 4 OR 5
;
;-------------------------------------------------------------------------------
.THEN
;-------------------------------------------------------------------------------
; Read the CRT palette from the BIOS ROM to obtain the background color and
; the current palette number; store the palette number in BL
;-------------------------------------------------------------------------------
ROM_BIOS_SEG EQU 40H ; CGA BIOS SEGMENT
CRT_PALETTE_OFF EQU 66H ; BIOS Current palette setting
P_BIT_MASK EQU 100000B ; bit 5 = Current palette
I_BIT_MASK EQU 1000B ; bit 4 = Intensity bit
R_BIT_MASK EQU 100B ; bit 2 = Red bit
G_BIT_MASK EQU 10B ; bit 1 = Green bit
B_BIT_MASK EQU 1B ; bit 0 = Blue bit
MOV AX,ROM_BIOS_SEG ; ES := ROM BIOS SEGMENT
PUSH AX
POP ES
MOV AL,ES:CRT_PALETTE_OFF; AL := CRT Palette (00PIIRGB)
MOV BL,P_BIT_MASK ; LOW NIBBLE = BACKGROUND COLOR
AND BL,AL ; BL := Palette number
MOV CL,5
SHR BL,CL
XOR DI,DI ; DI := Index in the XLT_TAB
;-------------------------------------------------------------------------------
; Store the background color, (obtained from low 4 bits of the byte at 40:66)
;-------------------------------------------------------------------------------
CALL CGA_COL2RGB ; Convert color (in AL) to R, G, B values
CALL RGB2XLT_TAB ; Convert RGB to an entry in XLT_TAB
;-------------------------------------------------------------------------------
; Store the 3 foreground colors for mode 4 and 5
;-------------------------------------------------------------------------------
MOV CX,3 ; For each color, but the background:
STORE_1_CGA_MODE4_COLOR:
INC DI ; Increment index in the translation table
MOV AX,DI ; AL := IRG
SHL AL,1
OR AL,BL ; AL := IRGB
CALL CGA_COL2RGB ; Convert color (in AL) to R, G, B values
CALL RGB2XLT_TAB ; Convert RGB to an entry in XLT_TAB
LOOP STORE_1_CGA_MODE4_COLOR
.ELSEIF <CUR_MODE EQ 6>
;===============================================================================
;
; THE CURRENT MODE IS MODE 6
;
;-------------------------------------------------------------------------------
.THEN
;-------------------------------------------------------------------------------
; Store background color for mode 6 (mode 6 is a 2 colors, APA mode)
; Background is stored as BLACK
;-------------------------------------------------------------------------------
XOR DI,DI ; DI := Index of color in translation table
MOV RGB.R,BLACK_INT ; Foreground color is white
MOV RGB.G,BLACK_INT ; RGB := RGB of white
MOV RGB.B,BLACK_INT ;
CALL RGB2XLT_TAB ; Convert RGB to an entry in XLT_TAB
;-------------------------------------------------------------------------------
; Store foreground color for mode 6 (mode 6 is a 2 colors, APA mode)
;-------------------------------------------------------------------------------
INC DI ; DI := Index of color in translation table
MOV RGB.R,WHITE_INT ; Background color is BLACK
MOV RGB.G,WHITE_INT ; RGB := RGB of BLACK
MOV RGB.B,WHITE_INT ;
CALL RGB2XLT_TAB ; Convert RGB to an entry in XLT_TAB
.ELSE
;===============================================================================
;
; THE CURRENT MODE IS A TEXT MODE:
;
;-------------------------------------------------------------------------------
XOR DI,DI ; DI := Index in the translation table
MOV CX,16 ; For each of the 16 colors:
STORE_1_CGA_TEXT_COLOR:
MOV AX,DI ; AL := IRGB
CALL CGA_COL2RGB ; Convert color (in AL) to R, G, B values
CALL RGB2XLT_TAB ; Convert RGB to an entry in XLT_TAB
INC DI ; Increment index in the translation table
LOOP STORE_1_CGA_TEXT_COLOR
.ENDIF ;
POP ES
POP DI
POP CX
POP BX
POP AX
RET
SET_CGA_XLT_TAB ENDP
PAGE
;===============================================================================
;
; RGB2XLT_TAB: CONVERT R,G,B VALUES TO EITHER A BAND MASK OR AN INTENSITY
; STORE THE RESULT IN THE TRANSLATION TABLE
;
;-------------------------------------------------------------------------------
;
; INPUT: DI = Index in the translation table
; RGB = Red Green Blue values of the color to be stored.
;
; OUTPUT: XLT_TAB is updated
;
;-------------------------------------------------------------------------------
; DESCRIPTION: Convert the RGB values to either a Band mask or an intensity
; depending on the printer type; store the result in the translation table.
;
; LOGIC:
; IF PRINTER_TYPE = COLOR
; THEN
; CALL RGB2BAND ; Obtain a Band Mask
; ELSE ; Printer is Monochrome
; CALL RGB2INT ; Obtain a Grey Intensity
; Store the result in the XLT_TAB
;
RGB2XLT_TAB PROC NEAR
.IF <DS:[BP].PRINTER_TYPE EQ COLOR>; Color printer ?
.THEN
;-------A color printer is attached:
CALL RGB2BAND ; Yes, convert RGB to color band (in AL)
.ELSE
;-------A black and white printer is attached:
CALL RGB2INT ; No, RGB to an intensity in AL
.ENDIF
;-------Store the result
MOV XLT_TAB[DI],AL
RET
RGB2XLT_TAB ENDP
PAGE
;===============================================================================
;
; CGA_COL2RGB : CONVERT A COLOR FROM THE CGA TO RED GREEN BLUE VALUES
;
;-------------------------------------------------------------------------------
;
; INPUT: AL = 0000IRGB ONE BYTE WHERE BIT:
;
; I = Intensity bit
; R = Red component
; G = Green component
; B = Blue component
;
;
; OUTPUT: RGB.R = RED component (0-63)
; RGB.G = GREEN component (0-63)
; RGB.B = BLUE component (0-63)
;
; CALLED BY: SET_UP_CGA_XLT_TABLE
;
;-----------------------------------------------------------------------
;
; DESCRIPTION: If either the RED, GREEN, or BLUE bit is on (in an IRGB
; byte) then, the corresponding color gun on the display is firing 2/3
; of its capacity, giving a color intensity of "2/3".
;
; If the INTENSITY bit is on, then 1/3 is added to EACH color.
;
; (E.G., IRGB R G B
; BLACK = 00000000 ( 0, 0, 0)
; WHITE = 00001111 (3/3, 3/3, 3/3)
; RED = 00000100 (2/3, 0, 0)
; HIGH INT. RED = 00001100 (3/3, 1/3, 1/3)
;
; Since we want an intensity from 0 to 63,
; "2/3" of RED means:
; 2/3 * 63 = 42
;
;
; LOGIC:
; Get the intensity.
; Get the red component
; Get the green component
; Get the blue component
;
CGA_COL2RGB PROC NEAR
;-----------------------------------------------------------------------
;
; Init the R,G,B values:
;
;-----------------------------------------------------------------------
MOV RGB.R,0
MOV RGB.G,0
MOV RGB.B,0
;-----------------------------------------------------------------------
;
; Test the Intensity bit:
;
;-----------------------------------------------------------------------
.IF <BIT AL AND I_BIT_MASK> ; IF, I is on
.THEN
ADD RGB.R,ONE_THIRD ; Then, add one third to each
ADD RGB.G,ONE_THIRD ; color.
ADD RGB.B,ONE_THIRD
.ENDIF
;-----------------------------------------------------------------------
;
; Test the RGB bits:
;
;-----------------------------------------------------------------------
.IF <BIT AL AND R_BIT_MASK> ; If, Red is on
.THEN
ADD RGB.R,TWO_THIRD ; then, add two third RED
.ENDIF
.IF <BIT AL AND G_BIT_MASK> ; If, Green is on
.THEN
ADD RGB.G,TWO_THIRD ; then, add two third GREEN
.ENDIF
.IF <BIT AL AND B_BIT_MASK> ; If, Blue is on
.THEN
ADD RGB.B,TWO_THIRD ; then, add two third BLUE
.ENDIF
RET
CGA_COL2RGB ENDP
PAGE
;=======================================================================
;
; SET_MODE_F_XLT_TAB: SET UP COLOR TRANSLATION TABLE FOR MONOCHROME
; MODE "F"
;
;-----------------------------------------------------------------------
;
; INPUT: XLT_TAB = Color translation table.
; PRINTER_TYPE = Type of printer attached (Color or B&W)
; SWITCHES = GRAPHICS command line parameters.
;
; OUTPUT: XLT_TAB IS UPDATED
;
; CALLED BY: SET_UP_XLT_TABLE
;
;-------------------------------------------------------------------------------
;
; NOTES: In mode F the "VIDEO BIOS READ DOT call" returns a byte where
; bit 1 and 3 represent the value of plane 1 and 3.
; The following colors are available using this mode:
;
; plane 2: plane 0: color:
; 0 0 black
; 0 1 white
; 1 0 blinking white
; 1 1 high-intensity white
;
;
; DESCRIPTION: A local table holds the Red, Green, Blue values for each of
; the 4 Mono colors available in Mode Fh.
; Each color is stored as either a Grey intensity if printing in Monochrome
; or as a Band Mask if printing in color.
; Black is stored as black.
; White is stored as a light gray
; High-intensity white and blinking white are stored as white.
;
;
; LOGIC:
; FOR EACH "COLOR" AVAILABLE WITH MODE F
; GET ITS R,G,B VALUES
; CALL RGB2XLT_TAB ; Convert RGB to an entry in the translation
; ; table
;
SET_MODE_F_XLT_TAB PROC NEAR
PUSH AX
PUSH SI
PUSH DI
JMP SHORT SET_MODE_F_BEGIN
;-------------------------------------------------------------------------------
;
; TABLE OF R,G,B VALUES WE ASSIGN TO THE 4 COLORS AVAILABLE IN MODE F:
;
;-------------------------------------------------------------------------------
MODE_F_RGB LABEL BYTE
DB BLACK_INT,BLACK_INT,BLACK_INT ; Black is mapped to black.
DB TWO_THIRD,TWO_THIRD,TWO_THIRD ; White --> light grey
DB WHITE_INT,WHITE_INT,WHITE_INT ; Blinking --> white
DB WHITE_INT,WHITE_INT,WHITE_INT ; High-int. White --> white
;-------------------------------------------------------------------------------
;
; STORE THE COLORS AVAILABLE WITH MODE F
;
;-------------------------------------------------------------------------------
SET_MODE_F_BEGIN:
MOV SI,OFFSET MODE_F_RGB ; SI <-- Offset of RGB table
XOR DI,DI ; DI <-- Index into translation table
;-------For each color available in mode F:
STORE_1_MODE_F_COLOR:
MOV AL,[SI] ; Get the Red component
MOV RGB.R,AL
MOV AL,[SI]+1 ; Get the Green component
MOV RGB.G,AL
MOV AL,[SI]+2 ; Get the Blue component
MOV RGB.B,AL
;-------Convert pixel to either a Color band or an Intensity:
CALL RGB2XLT_TAB ; Convert and store in the xlt table
ADD SI,3 ; Get next R,G,B values
INC DI ; One more color has been stored
CMP DI,NB_COLORS ; All stored ?
JL STORE_1_MODE_F_COLOR
POP DI
POP SI
POP AX
RET
SET_MODE_F_XLT_TAB ENDP
PAGE
;=======================================================================
;
; SET_MODE_13H_XLT_TAB: SET UP COLOR TRANSLATION TABLE FOR PALACE VIDEO
; ADAPTER IN MODE 13H
;
;-----------------------------------------------------------------------
;
; INPUT: XLT_TAB = Color translation table.
; PRINTER_TYPE = Type of printer attached (Color or B&W)
; SWITCHES = GRAPHICS command line parameters.
;
; OUTPUT: XLT_TAB IS UPDATED
;
; CALLED BY: SET_UP_XLT_TABLE
;
;-----------------------------------------------------------------------
;
; NOTES: With the PALACE the "VIDEO BIOS READ DOT call" returns a direct
; index to the 256 COLOR REGISTERS.
;
; These COLORS REGISTERS hold the R,G,B (Red, Green, Blue) values for
; each of the 256 colors available at the same time on the screen.
; Color register number 0 holds the background color.
;
; DESCRIPTION: Store a color mapping for each color register.
; If the REVERSE_SW is off, exchange white and black.
;
; LOGIC:
;
; For each color (0 to 255)
; Read the color register ; get the RGB values for this color num.
; Store the result in the XLT_TAB
;
SET_MODE_13H_XLT_TAB PROC NEAR
PUSH AX
PUSH BX
PUSH CX
PUSH DX
PUSH DI
MOV NB_COLORS_TO_READ,256 ; Read 256 color registers
;-------------------------------------------------------------------------------
;
; Store in the translation table each color available for mode 13h:
;
;-------------------------------------------------------------------------------
XOR DI,DI ; DI := Palette register number
; and index in the translation table
STORE_1_M13H_COLOR:
MOV BX,DI ; BX := Color register to be read
MOV AX,GET_C_REG_CALL ; AX := BIOS Get color register call
INT 10H ; Call BIOS
MOV RGB.R,DH ; Get Red value
MOV RGB.G,CH ; Get Green value
MOV RGB.B,CL ; Get Blue value
CALL RGB2XLT_TAB ; Convert RGB to an entry in XLT_TAB
INC DI ; Get next palette register number
CMP DI,NB_COLORS_TO_READ ; All colors stored ?
JL STORE_1_M13H_COLOR ; No, get next one
POP DI
POP DX
POP CX
POP BX
POP AX
RET
NB_COLORS_TO_READ DW ? ; Number of colors registers to read with a PS/2
SET_MODE_13H_XLT_TAB ENDP
PAGE
;===============================================================================
;
; SET_ROUNDUP_XLT_TAB: SET UP COLOR TRANSLATION TABLE FOR ROUNDUP VIDEO
; ADAPTER
;
;-------------------------------------------------------------------------------
;
; INPUT: XLT_TAB = Color translation table.
; PRINTER_TYPE = Type of printer attached (Color or B&W)
; SWITCHES = GRAPHICS command line parameters.
;
; OUTPUT: XLT_TAB IS UPDATED
;
; CALLED BY: SET_UP_XLT_TABLE
;
;-------------------------------------------------------------------------------
;
; NOTES: With the ROUNDUP the "VIDEO BIOS READ DOT call" returns an
; index into the 16 PALETTE REGISTERS.
;
; Each palette register holds an index into the current "color page"
; within the 256 COLOR REGISTERS.
;
; These "color pages" represent all the colors from WHICH TO CHOOSE the
; screen colors for an active page; 16 colors can be displayed at the
; same time on the screen.
;
; There are 2 paging modes: either 64 color pages or 16 color pages:
;
; In 64 color mode, there are 4 color pages available (the 256 palette
; registers are partitioned in 4 blocks of 64 colors).
;
; The 16 screen colors for the active page are selected from these 64
; color registers.
;
; This scheme allows for quickly changing the contents of the screen by
; changing the active page.
;
; The COLOR REGISTERS contains the color information stored as RGB (Red,
; Green, Blue) components. There is one byte for each of these 3
; components. The value for each component ranges from 0 to 63 (where
; 0 = color not present).
;
;
; DESCRIPTION: Determine the paging mode and the active color page.
; For each color available with the current mode, get the palette
; register and then, read the corresponding color register in order to
; obtain its RGB components.
;
; For mode 11h, 2 colors only are available. These colors are obtained from
; palette register 0 (background) and 7 (foreground color). The contents
; of these 2 palette registers is also used as an index within the color
; registers.
;
; If printing is Monochrome, map the RGB to a Grey Intensity.
; If printing is in colors, map the RGB to a Band Mask.
; Store the result in the translation table
;
; LOGIC:
;
; Read color page state (BIOS INT 10H - AL = 1AH)
;
; If mode 4,5 or 6
; Then
; CALL SET_CGA_XLT_TAB
; Adjust the background color.
; else
; If mode 11h
; then
; For PALETTE_INDEX := 0 to 15
; IF PAGE_MODE = PAGE_64_REGISTERS
; THEN
; Read the palette register number "PALETTE_INDEX"
; COLOR_INDEX := Palette register contents
; COLOR_INDEX := (CUR_PAGE_NUM * 64) + COLOR_INDEX
; Read color register number "COLOR_INDEX" ; Obtain R,G,B values.
; CALL RGB2XLT_TAB ; Convert RGB to an entry in XLT_TAB
;
; ELSE IF PAGE_MODE = PAGE_16_REGISTERS
; COLOR_INDEX := (CUR_PAGE_NUM * 16) + PALETTE_INDEX
; Read color register number "COLOR_INDEX"
; CALL RGB2XLT_TAB ; Convert RGB to an entry in XLT_TAB
;
;
SET_ROUNDUP_XLT_TAB PROC NEAR
PAGING_MODE_64 EQU 0
PUSH AX
PUSH BX
PUSH CX
PUSH DI
;-------------------------------------------------------------------------------
; Obtain the color page state
;-------------------------------------------------------------------------------
MOV AX,PAGE_STATE_CALL ; Call BIOS
INT 10H ; BL := Paging mode
; BH := Current page
;-------------------------------------------------------------------------------
; Check the video mode:
;-------------------------------------------------------------------------------
.SELECT
.WHEN <CUR_MODE EQ 4> OR ; If the current mode is an old CGA
.WHEN <CUR_MODE EQ 5> OR ; mode:
.WHEN <CUR_MODE EQ 6> ;
;-------------------------------------------------------------------------------
;
; Old CGA graphics mode (mode 4, 5 or 6)
;
;-------------------------------------------------------------------------------
;-------------------------------------------------------------------------------
; Store colors of the old CGA modes:
;-------------------------------------------------------------------------------
CALL SET_CGA_XLT_TAB ; Set up colors in the translation
; table, NOTE: The background color
; will not be set properly since the
; PS/2 BIOS does not update memory
; location 40:66 with the value
; of the background color as CGA
; does for modes 4 and 5. However
; 40:66 holds the current palette
; selected.
;-------------------------------------------------------------------------------
; Adjust the background color for modes 4,5 or 6
;-------------------------------------------------------------------------------
MOV PAL_REGISTER_NB,0 ; Read the palette register number 0
CALL GET_PALETTE_RGB ; this register points to the color
; register that contains the RGB
; values of the BACKGROUND color.
MOV DI,0 ; DI := Index in the translation table
CALL RGB2XLT_TAB ; Store mapping in the translation table
.WHEN <CUR_MODE EQ 11H>
;-------------------------------------------------------------------------------
;
; Mode 11h (2 colors out of 256,000 colors)
;
;-------------------------------------------------------------------------------
;-------------------------------------------------------------------------------
; Get the background color:
;-------------------------------------------------------------------------------
MOV PAL_REGISTER_NB,0 ; Read the palette register number 0
CALL GET_PALETTE_RGB ; Get the RGB values for this color
MOV DI,0 ; DI := Index in translation table
CALL RGB2XLT_TAB ; Store mapping in the translation table
;-------------------------------------------------------------------------------
; Get the foreground color:
;-------------------------------------------------------------------------------
MOV PAL_REGISTER_NB,7 ; Read the palette register for the
; FOREGROUND color (palette register 7)
CALL GET_PALETTE_RGB ; Get the RGB values for this color
MOV DI,1 ; DI := Index in translation table
CALL RGB2XLT_TAB ; Store mapping in the translation table
.OTHERWISE
;-------------------------------------------------------------------------------
;
; The current mode is a 16 color mode
;
;-------------------------------------------------------------------------------
XOR DI,DI ; DI := Index in translation table
MOV CX,16 ; 16 colors to read and store
MOV PAL_REGISTER_NB,0 ; Palette register to read
STORE_1_PS2_COLOR:
CALL GET_PALETTE_RGB ; Get the RGB values for this color
;
;-------Convert the RGB values to band mask or intensity and store in XLT_TAB:
CALL RGB2XLT_TAB ; Store mapping in the translation table
INC DI ; Get next palette register number
INC PAL_REGISTER_NB ;
LOOP STORE_1_PS2_COLOR ; Read it.
.ENDSELECT
POP DI
POP CX
POP BX
POP AX
RET
PAL_REGISTER_NB DB ? ; Number of the palette register to read
SET_ROUNDUP_XLT_TAB ENDP
PAGE
;===============================================================================
;
; GET_PALETTE_RGB: ON THE PS/2 MODEL 50, 60 AND 80, GET THE RGB VALUES FOR A
; PALETTE REGISTER BY READING THE CORRESPONDING COLOR REGISTER
;
;-------------------------------------------------------------------------------
;
; INPUT: PAL_REGISTER_NB = Palette register number
; BH = Current page number
; BL = Current paging mode
;
; OUTPUT: RGB.R = The RGB values obtained from the color register
; RGB.G corresponding to the palette register specified
; RGB.B
;
; CALLED BY: SET_ROUNDUP_XLT_TAB
;
;-------------------------------------------------------------------------------
GET_PALETTE_RGB PROC
PUSH AX
PUSH BX
PUSH CX
PUSH DX
PUSH SI
MOV AL,BH ; SI := Current page number
CBW ;
MOV SI,AX ;
;-------------------------------------------------------------------------------
;
; Calculte the absolute number of the first Color Register for the current page:
; (calculated in SI)
;
;-------------------------------------------------------------------------------
.IF <BL EQ PAGING_MODE_64> ; If mode is 64 Color page
.THEN ; then
MOV CL,6 ; SI := Current page num * 64
SHL SI,CL ;
.ELSE ; else, Mode is 16 Color page
MOV CL,4 ; SI := Current page num * 16
SHL SI,CL ;
.ENDIF
;
;-------Read the PALETTE REGISTER
MOV BL,PAL_REGISTER_NB ; BL := Palette register to be read
MOV AX,GET_P_REG_CALL ; Read palette register call
INT 10H ; Call BIOS,
; BH := Color register index
; WITHIN the current page and is
; either (0-15) or (0-63)
; NOTE: SI = Absolute index (0-255) to
; the first color register of the
; current page and is a multiple of
; either 16 or 64
MOV BL,BH ; BX := Index within current color page
XOR BH,BH ;
;
;-------Read the Color register:
OR BX,SI ; BX := Index of Color register to read
MOV AX,GET_C_REG_CALL ; Read the color register
INT 10H ; Call BIOS,
MOV RGB.R,DH ; DH := Red value read
MOV RGB.G,CH ; CH := Green value read
MOV RGB.B,CL ; CL := Blue value read
POP SI
POP DX
POP CX
POP BX
POP AX
RET
GET_PALETTE_RGB ENDP
PAGE
;=======================================================================
;
; EGA_COL2RGB : CONVERT A COLOR FROM THE EGA TO RED GREEN BLUE VALUES
;
;-----------------------------------------------------------------------
;
; INPUT: AL = 00rgbRGB ONE BYTE WHERE BIT:
;
; r = 1/3 of Red component
; g = 1/3 of Green component
; b = 1/3 of Blue component
; R = 2/3 of Red component
; G = 2/3 of Green component
; B = 3/3 of Blue component
;
;
; OUTPUT: RGB.R = RED component (0-63)
; RGB.G = GREEN component (0-63)
; RGB.B = BLUE component (0-63)
;
; CALLED BY: SET_UP_EGA_XLT_TABLE
;
;-----------------------------------------------------------------------
;
; DESCRIPTION: Sums up the values for each color component.
; "2/3 of RED" means that the red gun in the display attached to the EGA
; is firing at 2/3 of full intensity.
;
; Since the color intensities range from 0 to 63, "1/3" means an
; intensity of:
; 1/3 * 63 = 21
;
; LOGIC:
;
; Get the red component
; Get the green component
; Get the blue component
;
EGA_COL2RGB PROC NEAR
;
;-------Get the RED component (bit 5 and 2)
;
;-------Check bit 2
MOV RGB.R,0
TEST AL,100B ; "R" is on ?
JZ CHECK_BIT_5 ; No, check "r"
ADD RGB.R,TWO_THIRD ; Yes, add 2/3 RED
CHECK_BIT_5:
TEST AL,100000B ; "r" is on ?
JZ CHECK_BIT_1 ; No, check Green
ADD RGB.R,ONE_THIRD ; Yes, add 1/3 RED
;
;-------Get the GREEN component (bit 4 and 1)
;
CHECK_BIT_1:
MOV RGB.G,0
TEST AL,10B ; "G" is on ?
JZ CHECK_BIT_4 ; No, check "g"
ADD RGB.G,TWO_THIRD ; Yes, add 2/3 GREEN
CHECK_BIT_4:
TEST AL,10000B ; "g" is on ?
JZ CHECK_BIT_0 ; No, check for Blue
ADD RGB.G,ONE_THIRD ; Yes, add 1/3 GREEN
;
;-------Get the BLUE component (bit 3 and 0)
;
CHECK_BIT_0:
MOV RGB.B,0
TEST AL,1B ; "B" is on ?
JZ CHECK_BIT_3 ; No, check "b"
ADD RGB.B,TWO_THIRD ; Yes, add 2/3 BLUE
CHECK_BIT_3:
TEST AL,1000B ; "b" is on ?
JZ EGA_COL2RGB_RETURN ; No, return
ADD RGB.B,ONE_THIRD ; Yes, add 1/3 BLUE
EGA_COL2RGB_RETURN:
RET
EGA_COL2RGB ENDP
PAGE
;===============================================================================
;
; RGB2INT : MAP RED GREEN BLUE VALUES TO AN INTENSITY.
;
;-------------------------------------------------------------------------------
;
; INPUT: RGB.R = A RED value (0-63)
; RGB.G = A GREEN value (0-63)
; RGB.B = A BLUE value (0-63)
; DARKADJUST_VALUE= THE DARKNESS VALUE (In shared data area).
; SWITCHES = Command line switches
;
; OUTPUT: AL = THE INTENSITY (0-63) NOTE: 0 = BLACK
; 63 = BRIGHT WHITE
;
; WARNING: AH IS LOST
;
;-------------------------------------------------------------------------------
;
; DESCRIPTION: When the RGB values for a pixel are at their maximum
; value, what we obtain is a bright white pixel on the screen; this is
; the brightest color achievable and therefore, its intensity is 63.
;
; When no color gun is firing on the display: RGB values are 0,0,0 this
; is no color at all and therefore maps to intensity 0.
;
; For intermediate colors, experimentation has shown that the eye will
; see blue as darker than red and red as darker than green.
;
; On a grey rainbow from 0 - 10 where 0 is black and 10 is white:
;
; Blue corresponds to a grey of intensity 1
; Red corresponds to a grey of intensity 3
; Green corresponds to a grey of intensity 6
;
; Therefore, if we mix all 3 colors we obtain a grey of
; intensity 1 + 3 + 6 = 10 (i.e.,white).
;
;
; LOGIC:
;
; Calculate the intensity
;
; AL = (.6 * G) + (.3 * R) + (.1 * B)
;
; Adjust Darkness
;
; AL = AL + DARKADJUST_VALUE
;
RGB2INT PROC NEAR
PUSH BX
PUSH CX
PUSH DX
XOR AX,AX ; AL := Current component intensity
XOR BX,BX ; BX is used for calculations
XOR DX,DX ; DL := Running sum for grey intensity
;-------Process /R (Reverse black and white)
.IF <BIT DS:[BP].SWITCHES Z REVERSE_SW> ; IF reverse is OFF
.THEN ; THEN REVERSE BLACK AND WHITE:
;-------Test if the color is BLACK
.IF <RGB.R EQ BLACK_INT> AND ; If black
.IF <RGB.G EQ BLACK_INT> AND ;
.IF <RGB.B EQ BLACK_INT> ;
.THEN ; then, replace it with white
MOV AL,WHITE_INT
JMP SHORT RGB2INT_END
.ELSEIF <RGB.R EQ WHITE_INT> AND ; else if, high-intensity white
.IF <RGB.G EQ WHITE_INT> AND ;
.IF <RGB.B EQ WHITE_INT> ;
.THEN ; then, replace it with black
MOV AL,BLACK_INT
JMP SHORT RGB2INT_END
.ELSEIF <RGB.R EQ TWO_THIRD> AND ; else if, white
.IF <RGB.G EQ TWO_THIRD> AND ;
.IF <RGB.B EQ TWO_THIRD> ;
.THEN ; then, replace it with black
MOV AL,BLACK_INT
JMP SHORT RGB2INT_END
.ENDIF
.ENDIF
;-------Calculate Green component
MOV AL,RGB.G ; AL := Green component
MOV BH,6 ;
MUL BH ; AX := Green * 6
MOV BH,10 ;
DIV BH ; AL := (GREEN * 6) / 10
ADD DL,AL ; DL := Cumulative intensity
MOV CH,AH ; CH := Cumulative remainder
;-------Calculate Red component
MOV AL,RGB.R ; AL := Red component
MOV BH,3 ;
MUL BH ; AX := Red * 3
MOV BH,10 ;
DIV BH ; AL := (RED * 3) / 10
ADD DL,AL ; DL := Cumulative intensity
ADD CH,AH ; CH := Cumulative remainder
;-------Calculate Blue component
MOV AL,RGB.B ; AX := Blue component
XOR AH,AH ;
DIV BH ; AL := BLUE / 10
ADD DL,AL ; DL := Cumulative intensity
ADD CH,AH ; CH := Cumulative remainder
;-------Adjust intensity with cumulative remainder
XOR AX,AX
MOV AL,CH ; AX := Cumulative remainder
MOV BH,10 ; BH := 10
DIV BH ; AL := Total remainder / 10
ADD DL,AL ; DL := Cumulative intensity
.IF <AH GT 4> ; If remainder > 4
.THEN ; Then, add 1
INC DL ; to the intensity
.ENDIF
;-------Adjust darkness
ADD DL,DS:[BP].DARKADJUST_VALUE
;-------Return result
MOV AL,DL ; AL := sum of R,G,B intensities
RGB2INT_END:
POP DX
POP CX
POP BX
RET
RGB2INT ENDP
PAGE
;==============================================================================
;
; RGB2BAND: MAP RED GREEN BLUE VALUES TO A "SELECT COLOR BAND" MASK FOR
; THE COLOR PRINTER.
;
;------------------------------------------------------------------------------
;
; INPUT: RGB.R = A RED value (0-63)
; RGB.G = A GREEN value (0-63)
; RGB.B = A BLUE value (0-63)
; BP = Offset of the Shared Data Area.
;
; OUTPUT: AL = The Band Mask, one byte where:
;
; bit 0 = Color Band 1 is needed
; bit 1 = Color Band 2 is needed
; bit 2 = Color Band 3 is needed
; bit 3 = Color Band 4 is needed
;
;
; CALLED BY: SET_CGA_XLT_TAB
; SET_EGA_XLT_TAB
; SET_ROUNDUP_XLT_TAB
; SET_MODE_13H_XLT_TAB
; SET_MODE_F_XLT_TAB
;
;------------------------------------------------------------------------------
;
; NOTES: The RGB values in input describe a color from the screen.
; Up to 256K different colors can be described with these RGB values.
;
; On the color printer, the print ribbon is composed of 4 color bands,
; each of a different color. By overlapping these 4 bands when
; printing, more colors can be obtained. However, the number of colors
; that can be achieved by overlapping print bands is very limited (4 or
; 8 colors).
;
; THIS MODULE SELECT THE PRINTER COLOR THAT IS THE CLOSEST TO THE
; DESIRED SCREEN COLOR.
;
; The Band Mask specifies which color bands have to be overlapped to
; obtain a color on the printer.
;
;
; DESCRIPTION: Go through the list of printer colors in the SHARED DATA
; AREA, for each of these colors, compare its RGB values with those in
; input.
; Get the BAND_MASK of the closest printer color.
;
; LOGIC:
;
; Locate the printer colors info structure in the shared data area:
; COLORPRINT_PTR := BP + COLORPRINT_PTR
;
; Get the number of printer colors from the COLORPRINT info in the Shared
; data area:
; Number of colors := COLORPRINT_PTR.NUM_PRT_COLOR
;
; CURRENT_COLOR_PTR : First record in the COLORPRINT info structure
; BEST_CHOICE := CURRENT_RECORD_PTR.BAND_MASK
; MIN_DIFF := Maximum positive value
;
; FOR each printer color:
; CUR_DIFF := 0
; (* Calculate the geometric distance between the RGB values from the *)
; (* input and those of the printer color. *)
; Red difference := (R - CURRENT_COLOR_PTR.RED)
; Red difference := Red difference * Red difference
; CUR_DIFF := CUR_DIFF + Red difference
;
; Green difference := (G - CURRENT_COLOR_PTR.GREEN)
; Green difference := Green difference * Green difference
; CUR_DIFF := CUR_DIFF + Green difference
;
; Blue difference := (B - CURRENT_COLOR_PTR.BLUE)
; Blue difference := Blue difference * Blue difference
; CUR_DIFF := CUR_DIFF + Blue difference
;
; IF CUR_DIFF < MIN_DIFF
; THEN BEGIN
; MIN_DIFF := CUR_DIFF
; BEST_CHOICE := printer color.BAND_MASK
; END
;
; CURRENT_COLOR_PTR := Offset of next color
; END (For each printer color)
;
; Return BEST_CHOICE
;
;
RGB2BAND PROC NEAR
PUSH AX
PUSH BX
PUSH CX
PUSH DX
;-------Process /R (Reverse black and white)
.IF <BIT DS:[BP].SWITCHES Z REVERSE_SW> ; IF reverse is OFF
.THEN ; THEN REVERSE BLACK AND WHITE:
;------------------------------------------------------------------------------
;
; REVERSE BLACK AND WHITE:
;
;------------------------------------------------------------------------------
;-------Test if the color is BLACK
.IF <RGB.R EQ BLACK_INT> AND ; If black
.IF <RGB.G EQ BLACK_INT> AND ;
.IF <RGB.B EQ BLACK_INT> ;
.THEN ; then, replace it with the
MOV BEST_CHOICE,0 ; band mask for white
JMP RGB2BAND_END ; return this band mask
.ELSEIF <RGB.R EQ WHITE_INT> AND ; else if, high-intensity white
.IF <RGB.G EQ WHITE_INT> AND ;
.IF <RGB.B EQ WHITE_INT> ;
.THEN ; then, replace it with the
MOV RGB.R,BLACK_INT ; RGB values of black
MOV RGB.G,BLACK_INT
MOV RGB.B,BLACK_INT
.ELSEIF <RGB.R EQ TWO_THIRD> AND ; else if, white
.IF <RGB.G EQ TWO_THIRD> AND ;
.IF <RGB.B EQ TWO_THIRD> ;
.THEN ; then, replace it with the
MOV RGB.R,BLACK_INT ; RGB values of black
MOV RGB.G,BLACK_INT
MOV RGB.B,BLACK_INT
.ENDIF
.ENDIF
;------------------------------------------------------------------------------
;
; CALCULATE THE GEOMETRIC DISTANCE BETWEEN THE COLORS OF THE PIXEL AND THOSE OF
; THE PRINTER:
;
;------------------------------------------------------------------------------
MOV BX,DS:[BP].COLORPRINT_PTR ; BX := OFFSET of COLORPRINT
ADD BX,BP
MOV MIN_DIFF,7FFFh ; No match yet, minimum diff.
; is maximum POSITIVE value.
XOR CX,CX
MOV CL,DS:[BP].NUM_PRT_COLOR ; CX := Number of print colors
INSPECT_1_PRINT_COLOR:
MOV CUR_DIFF,0 ; Current difference := 0
;------------------------------------------------------------------------------
; Calculate the Red difference:
;------------------------------------------------------------------------------
MOV AL,RGB.R
SUB AL,[BX].RED
;-------Elevate at the power of two
MOV DL,AL ; DX := Red difference
IMUL DL ; AX := Red diff. square
ADD CUR_DIFF,AX ; CURR_DIF + Red diff.
;------------------------------------------------------------------------------
; Calculate the Green difference:
;------------------------------------------------------------------------------
MOV AL,RGB.G
SUB AL,[BX].GREEN
;-------Elevate at the power of two
MOV DL,AL ; DX := Red difference
IMUL DL ; AX := Red diff. square
ADD CUR_DIFF,AX ; CURR_DIF + Green diff.
;------------------------------------------------------------------------------
; Calculate the Blue difference:
;------------------------------------------------------------------------------
MOV AL,RGB.B
SUB AL,[BX].BLUE
;-------Elevate at the power of two
MOV DL,AL ; DX := Red difference
IMUL DL ; AX := Red diff. square
ADD CUR_DIFF,AX ; CURR_DIF + Blue diff.
;------------------------------------------------------------------------------
; Check how close is this print color to the screen color:
;------------------------------------------------------------------------------
MOV AX,CUR_DIFF ; If this color is better than what we
.IF <AX L MIN_DIFF> ; had before.
.THEN ;
MOV MIN_DIFF,AX ; then, new minimum distance;
MOV AL,[BX].SELECT_MASK ; get its band mask.
MOV BEST_CHOICE,AL ;
.ENDIF ;
;------------------------------------------------------------------------------
; Get offset of next COLORPRINT info record:
;------------------------------------------------------------------------------
ADD BX,SIZE COLORPRINT_STR
LOOP INSPECT_1_PRINT_COLOR
;------------------------------------------------------------------------------
; BEST_CHOICE contains the print color with the closest RGB values
;------------------------------------------------------------------------------
RGB2BAND_END:
POP DX
POP CX
POP BX
POP AX
MOV AL,BEST_CHOICE
RET
BEST_CHOICE DB ?
MIN_DIFF DW ?
CUR_DIFF DW ?
RGB2BAND ENDP
CODE ENDS
END