+++ /dev/null
-;-----------------------------------------------------------\r
-;\r
-; MXFP.ASM - Fade palette function\r
-; Copyright (c) 1992-1994 ARTIS s.r.l.\r
-; Author: Alessandro Scotti\r
-;\r
-;-----------------------------------------------------------\r
-WARN PRO\r
-INCLUDE MODEX.DEF\r
-\r
-PUBLIC mxFadePalette\r
-\r
-MAXCOLOR EQU 256\r
-FADE_IN EQU 0\r
-FADE_OUT EQU 1\r
-\r
-; The actual speed of fading depends on the number of passes (FADE_SPEED) and\r
-; the delay between two consecutive passes (FADE_DELAY). Below are the\r
-; default values, used when no parameters are specified.\r
-;\r
-FADE_DELAY EQU 1 ; Vert. retraces between video updates\r
-FADE_SPEED EQU 48 ; Speed of effect (max 127)\r
-\r
-; Bit field record for fade commands\r
-;\r
-FADE_COMMAND RECORD fpDELAY:8,fpSPEED:7,fpDIRECTION:1\r
-\r
-MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
- ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
-\r
-DB 'Copyright (c) 1992-1994 ARTIS s.r.l. All rights reserved.'\r
-\r
-;-----------------------------------------------------------\r
-;\r
-; Fades a VGA palette.\r
-;\r
-; Input:\r
-; Buffer = pointer to source/destination palette\r
-; Command = fading direction and optional parameters\r
-; Start = index of first color to fade\r
-; Count = number of color to fade\r
-; Red = destination red\r
-; Green = destination green\r
-; Blue = destination blue\r
-; Output:\r
-; none\r
-; Notes:\r
-; - about 1.5 Kbytes of stack space are needed for internal buffers;\r
-; - the Command argument usually is 0 to fade in and 1 to fade out,\r
-; however additional parameters may be specified. To set the effect\r
-; speed, i.e. the number of iterations needed to completely fade a\r
-; palette, shift the value one bit left and "or" it with the\r
-; direction bit (range is 0..127). To set the delay between two\r
-; consecutive passes, shift it eight bits left (range is 0..255).\r
-;\r
-mxFadePalette PROC FAR\r
- ARG bBlue:WORD, \\r
- bGreen:WORD, \\r
- bRed:WORD, \\r
- wCount:WORD, \\r
- wStartIdx:WORD, \\r
- wCommand:WORD, \\r
- vfpPalette:DWORD = ARG_SIZE\r
- LOCAL bSPalette:BYTE:MAXCOLOR*3, \\r
- bDPalette:BYTE:MAXCOLOR*3, \\r
- bLoopIndex:BYTE, \\r
- bLoopStep:BYTE, \\r
- bLoopCount:BYTE, \\r
- wDelay:WORD, \\r
- wSpeed:WORD = AUTO_SIZE\r
- ASSUME ds:NOTHING\r
- .enter AUTO_SIZE\r
- .push si, di, ds, es ; Save registers\r
-;\r
-; Check parameters and setup variables\r
-;\r
-@@GetDelay:\r
- mov [wDelay], FADE_DELAY ; Set default delay\r
- mov ax, [wCommand] ; Get command word\r
- and ax, MASK fpDELAY ; Mask delay command\r
- jz @@GetSpeed ; No command, get speed\r
- IF USE286 EQ TRUE\r
- shr ax, fpDELAY\r
- ELSE\r
- mov cl, fpDELAY ; Get size of delay field\r
- shr ax, cl ; Right justify the field\r
- ENDIF\r
- mov [wDelay], ax ; Set new delay\r
-\r
-@@GetSpeed:\r
- mov ax, [wCommand] ; Get command\r
- and ax, MASK fpSPEED ; Mask speed\r
- IF USE286 EQ TRUE\r
- shr ax, fpSPEED\r
- ELSE\r
- mov cl, fpSPEED ; Get size of speed field\r
- shr ax, cl ; Right justify the field\r
- ENDIF\r
- or ax, ax ; Any speed specified?\r
- jnz @@SetVariables ; Yes, set variables\r
- mov ax, FADE_SPEED ; Set default speed\r
-\r
-@@SetVariables:\r
- mov [wSpeed], ax ; Set speed\r
- inc ax ; Number of iterations\r
- mov [bLoopCount], al ; Set loop count\r
- mov [bLoopStep], 1 ; Assume we're fading in\r
- mov [bLoopIndex], 0\r
-;\r
-; Check bounds for bad values\r
-;\r
- mov ax, [wStartIdx] ; Get first index\r
- cmp ax, MAXCOLOR ; Is in the valid range?\r
- jae @@Exit ; No, exit\r
- add ax, [wCount] ; Get last index\r
- cmp ax, MAXCOLOR ; Is in the valid range?\r
- jbe @@BoundsOk ; Yes, continue\r
- mov ax, MAXCOLOR\r
- sub ax, [wStartIdx]\r
- mov [wCount], ax ; Set count to maximum value\r
- or ax, ax\r
- jz @@Exit ; Nothing to do, exit\r
-@@BoundsOk:\r
-;\r
-; Copy the source palette in a local array: if we fade in it's ready to\r
-; use, otherwise we'll overwrite it later\r
-;\r
- mov cx, [wCount]\r
- mov ax, cx\r
- shl ax, 1\r
- add cx, ax ; CX = wCount * 3\r
- mov ax, ss\r
- mov es, ax\r
- lea di, [bSPalette] ; ES:DI points to local palette\r
- mov ax, [wStartIdx]\r
- mov si, ax\r
- shl ax, 1\r
- add ax, si\r
- lds si, [vfpPalette] ; DS:SI points to user palette\r
- add si, ax ; Skip unused entries\r
- cld\r
- shr cx, 1\r
- rep movsw\r
- rcl cx, 1\r
- rep movsb\r
-;\r
-; Check direction\r
-;\r
- test [wCommand], MASK fpDIRECTION ; Are we fading in?\r
- jz @@Main ; Yes, ok to continue\r
- mov ax, [wSpeed] ; Get speed\r
- mov [bLoopIndex], al ; Exchange first and last index\r
- mov [bLoopStep], -1 ; Move backward\r
- mov ax, ss ; Overwrite our copy of\r
- mov ds, ax ; user palette with the\r
- mov es, ax ; current active palette\r
- lea di, [bSPalette]\r
- mov ax, [wStartIdx]\r
- mov cx, [wCount]\r
- call ReadPalette ; Read current palette\r
-;\r
-; Prepare variables and registers for fading\r
-;\r
-@@Main:\r
- mov bh, BYTE PTR [bRed] ; Destination red\r
- and bh, 00111111b ; Be sure it's a valid VGA value\r
- mov bl, BYTE PTR [bGreen] ; Destination green\r
- and bl, 00111111b ; Be sure it's a valid VGA value\r
- mov dh, BYTE PTR [bBlue] ; Destination blue\r
- and dh, 00111111b ; Be sure it's a valid VGA value\r
- mov dl, [bLoopIndex] ; Loop index\r
- mov ax, ss ; All tables are stored\r
- mov ds, ax ; in the stack segment,\r
- mov es, ax ; set DS and ES\r
-;\r
-; Main loop\r
-;\r
-@@Loop:\r
- mov ax, [wCount] ; Store count in AX\r
- mov cx, [wSpeed] ; Set maximum speed in CX\r
- lea si, [bSPalette] ; DS:SI points to source palette\r
- lea di, [bDPalette] ; ES:DI points to dest. palette\r
- call RecalcPalette ; Build a faded palette\r
-\r
- .push bx, dx ; Save registers we need\r
- lea si, [bDPalette] ; DS:SI points to palette\r
- mov ax, [wStartIdx] ; First index to write\r
- mov bx, [wCount] ; Total entries to write\r
- mov cx, [wDelay] ; Fade delay between updates\r
- call WritePalette ; Write palette\r
- .pop bx, dx ; Restore BX and DX\r
-\r
- add dl, [bLoopStep] ; Change fade intensity\r
- dec [bLoopCount] ; Done?\r
- jnz @@Loop ; No, loop again\r
-\r
-@@Exit:\r
- .pop si, di, ds, es ; Restore registers\r
- .leave ARG_SIZE\r
-mxFadePalette ENDP\r
-\r
-;------- INTERNAL USE ONLY ------------------------------------------------\r
-;\r
-; Calculates a partially faded palette.\r
-;\r
-; Input:\r
-; AX = number of entries in palette\r
-; CX = maximum fade intensity (same as fade speed)\r
-; DS:SI = pointer to source palette\r
-; ES:DI = pointer to destination palette\r
-; BH = destination red\r
-; BL = destination green\r
-; DH = destination blue\r
-; DL = relative intensity of destination palette\r
-; Note:\r
-; it's important that a new palette can be calculated in less\r
-; than 1/70th of second. Fading to any RGB value requires use\r
-; of "imul" instructions: "idiv" may be replaced with faster\r
-; "sar", but only when the number of passes is a power of two,\r
-; thus reducing the range of selectable speeds.\r
-; In both cases an extimate of CPU cycles required by this\r
-; procedure shows that it's too slow to run on a 4.77 Mhz 8086\r
-; CPU and a 256 color palette, so we keep "idiv" and hope\r
-; the target machine to be at least a 6 Mhz 80286 (that's not\r
-; asking too much...).\r
-;\r
-RecalcPalette PROC NEAR\r
- cld\r
- push bp ; Save BP\r
- mov bp, ax ; Copy counter in BP\r
-@@Loop:\r
- lodsb ; Red: read value\r
- sub al, bh ; Subtract destination value\r
- imul dl ; Scale to desired weight\r
- idiv cl ; Put value in AL\r
- add al, bh ; Add destination value...\r
- stosb ; ...and store it\r
- lodsb ; Green: read value\r
- sub al, bl ; Subtract destination value\r
- imul dl ; Scale to desired weight\r
- idiv cl ; Put value in AL\r
- add al, bl ; Add destination value...\r
- stosb ; ...and store it\r
- lodsb ; Blue: read value\r
- sub al, dh ; Subtract destination value\r
- imul dl ; Scale to desired weight\r
- idiv cl ; Put value in AL\r
- add al, dh ; Add destination value...\r
- stosb ; ...and store it\r
- dec bp\r
- jnz @@Loop\r
- pop bp ; Restore BP\r
- ret\r
-RecalcPalette ENDP\r
-\r
-;------- INTERNAL USE ONLY ------------------------------------------------\r
-;\r
-; Writes a 256 color palette.\r
-;\r
-; Input:\r
-; AX = index of first color to write\r
-; BX = number of colors to write (each color is an RGB triplet)\r
-; CX = number of vertical retraces to wait before writing to DACs\r
-; DS:SI = pointer to first entry of palette\r
-;\r
-WritePalette PROC NEAR\r
- ASSUME ds:NOTHING\r
- mov ah, al ; Save index\r
- mov dx, 03DAh ; Input status register\r
-@@Delay1:\r
- in al, dx\r
- test al, 08h\r
- jnz @@Delay1 ; Wait for display mode\r
-@@Delay2:\r
- in al, dx\r
- test al, 08h\r
- jz @@Delay2 ; Wait for vertical retrace mode\r
- loop @@Delay1 ; Repeat CX times\r
-@@Write:\r
- mov cx, bx ; Get number of colors\r
- mov dx, 03C8h ; PEL write address register\r
- mov al, ah ; Restore index\r
- out dx, al ; Select index of first color\r
- inc dx ; PEL data register\r
- cld ; Move forward\r
- cli ; Disable interrupts\r
-@@Loop:\r
- lodsb\r
- out dx, al ; Red\r
- lodsb\r
- out dx, al ; Green\r
- lodsb\r
- out dx, al ; Blue\r
- loop @@Loop ; Loop until done\r
- sti ; Enable interrupts\r
- ret\r
-WritePalette ENDP\r
-\r
-;------- INTERNAL USE ONLY ------------------------------------------------\r
-;\r
-; Reads the current palette.\r
-;\r
-; Input:\r
-; AX = index of first color to read\r
-; CX = number of colors\r
-; ES:DI = pointer to destination buffer\r
-;\r
-ReadPalette PROC NEAR\r
- mov dx, 03C7h\r
- out dx, al\r
- inc dx\r
- inc dx\r
- cld\r
-@@Loop:\r
- in al, dx\r
- stosb\r
- in al, dx\r
- stosb\r
- in al, dx\r
- stosb\r
- loop @@Loop\r
- ret\r
-ReadPalette ENDP\r
-\r
-MX_TEXT ENDS\r
-END\r