;; Palette operations ;; Note that where needed in the macros, a "palette" refers to ;; the segment handle to a 768-byte piece of memory. So palettes ;; can be loaded and freed, they're not permanent, but if you want ;; to use a fixed (not allocated) palette you'd better make sure ;; it's segment aligned or else you can't use these macros. If it ;; is, you can just supply "seg myPalette" as the 'palette' argument ;; to any of these macros. ;; Fade from a palette to black FADE_OFF MACRO fade,palette mov si,0 mov ds,palette mov bh,fade ; positive -> Gets dimmer... mov bl,0 ; Starts exact mov cx,64/fade+1 ; Total number of loops required call FadePalette ENDM ;; Fade from black to a palette FADE_ON MACRO fade,palette mov si,0 mov ds,palette mov bh,-fade ; negative -> Gets brighter... mov bl,64 ; Starts totally dimmed mov cx,64/fade+1 ; Total number of loops required call FadePalette ENDM ;; Flash from a palette to white FLASH_OFF MACRO fade,palette mov si,0 mov ds,palette mov bh,-fade ; negative -> gets brighter mov bl,0 ; Starts exact mov cx,64/fade+1 ; Total number of loops required call FadePalette ENDM ;; Flash from white to a palette FLASH_ON MACRO fade,palette mov si,0 mov ds,palette mov bh,fade ; positive -> Gets dimmer... mov bl,-64 ; Starts totally bright mov cx,64/fade+1 ; Total number of loops required call FadePalette ENDM ;; Save a palette into a palette-sized piece of memory PAL_SAVE MACRO palette mov es,palette mov di,0 call SavePalette ENDM ; Returns AX = a new segment for a palette NEW_PAL MACRO palette mov bx,(256 * 3) / 16 mov ah,48h int 21h mov palette,ax ENDM ;; Black the entire palette temporarily. Used to blank the screen while ;; drawing a frame before fading in. PAL_BLACK MACRO mov ax,seg tmppal mov ds,ax mov si,OFFSET tmppal mov bh,-1 ; Doesn't really matter... mov bl,64 ; Starts totally dimmed mov cx,1 ; Just one time -- to leave it black call FadePalette ENDM ;; drawing a frame before fading in. PAL_WHITE MACRO mov ax,seg tmppal mov ds,ax mov si,OFFSET tmppal mov bh,-1 ; Doesn't really matter... mov bl,-64 ; Starts totally dimmed mov cx,1 ; Just one time -- to leave it black call FadePalette ENDM ;; Black the entire palette temporarily. Used to blank the screen while ;; drawing a frame before fading in. PAL_UPDATE MACRO mov cx,0 ; 0 times = update call FadePalette ENDM WAITBORDER MACRO LOCAL wbr1,wbr2 mov dx,INPUT_STATUS_1 wbr1: in al,dx test al,8 jnz wbr1 wbr2: in al,dx test al,8 jz wbr2 ENDM ;; Fade Palette: ;; The following code is modified greatly from the Future Crew's palette ;; fading code. Works on blocks of 256 colors only, so far, but I might ;; change it later. Also, it theoretically could "anti-fade" -- fade to ;; white -- which I call flashing, so I added that ability, which was ;; missing from FC's code. EVEN tmppal DB 768 dup (?) ; Stores old palette FadePalette PROC NEAR mov ax,seg tmppal mov es,ax FadeLoop: push cx push si cmp cx,0 je JustUpdate ; Load in the colors in the palette mov di,OFFSET tmppal ; ES:DI -> temp palette mov cx,768 ; Reads 256*3 bytes at a time. loadpal_loop: mov al,ds:[si] ; Load one color byte inc si sub al,bl ; Subtract the fade amount jge pal_more ; Limit the range by clipping xor al,al ; to between 0 and 63 jmp pal_ok ; (there's probably a faster pal_more: cmp al,63 ; way to do it than this, jle pal_ok ; but I don't know it) mov al,63 pal_ok: mov es:[di],al ; Store that byte in the new inc di dec cx ; temp palette and loop. jnz loadpal_loop ; Get ready to move this block of palette values JustUpdate: sti ; Let interrupts happen now, WAITBORDER ; while waiting for a retrace, cli ; instead of more critical times mov dx,PEL_WRITE_REG; Set up to write to color register, xor al,al ; starting at palette entry 0. out dx,al mov dx,PEL_DATA_REG ; Point at color port ; Quickly put out the first half of the color palette mov di,OFFSET tmppal mov cl,(768/6)/2 ; Does 2 loops of 128 colors each. cli ; Waits a retrace inbetween... FirstHalfLoop: REPEAT 6 ; Steps of 6 -- reduces the mov al,es:[di] ; number of LOOP instructions inc di out dx,al ENDM dec cl jnz FirstHalfLoop sti WAITBORDER ; Waits one retrace -- less flicker mov dx,PEL_DATA_REG ; Reset DX ; Now, quickly put out the other half of the colors. mov cl,(768/6)/2 cli SecondHalfLoop: REPEAT 6 ; Steps of 6 -- reduces the mov al,es:[di] ; number of LOOP instructions inc di out dx,al ENDM dec cl jnz SecondHalfLoop ; For the next iteration, restore everything and loop pop si pop cx cmp cx,0 je JustUpdated add bl,bh ; Change brightness by BH dec cx jnz FadeLoop ; All done, re-enable interrupts and return JustUpdated: sti ret FadePalette ENDP ;; Saves the palette into the memory pointed at by DS:SI. That memory ;; must be at least 768 bytes long... SavePalette PROC NEAR mov dx,PEL_READ_REG ; Set up to read from color register, xor al,al ; starting at palette entry 0. out dx,al mov dx,PEL_DATA_REG ; Quickly read in the first half of the color palette mov cl,(768/6) cli ReadPalLoop: REPEAT 6 ; Steps of 6 -- reduces the in al,dx ; number of LOOP instructions mov es:[di],al inc di ENDM dec cl jnz ReadPalLoop ; All done, re-enable interrupts and return sti ret SavePalette ENDP ;; Load a palette from a file. Opens the file and reads it into ;; memory (standard LoadFile) and then points the palette at that ;; newly allocated memory. Also, frees old memory before it does ;; any loading ... LoadPaletteFile PROC near mov ax,segPalette cmp ax,-1 je pal_not_loaded mov es,ax mov ah,49h int 21h mov nError,ERR_MEM jc lp_err mov segPalette,-1 pal_not_loaded: call LoadFile jc lp_err mov segPalette,dx lp_err: ret LoadPaletteFile ENDP