在汇编中打印 bmp 后返回正常的 BIOS 调色板
Returning to the normal BIOS color palette after printing a bmp in assembly
我正在用 8086 汇编(在 DOSBOX 中)开发一个游戏项目。
我有一个可以在图形模式下运行的贪吃蛇游戏,以及一个可以将 BMP 文件打印到屏幕上的菜单。
我唯一的问题是在打印过程中我将调色板更改为 bmp 调色板。
变色过程:
(这是将 bmp 打印到屏幕的代码的一部分)
proc ReadPalette
; Read BMP file color palette, 256 colors * 4 bytes (400h)
mov ah,3fh
mov cx,400h
mov dx,offset Palette
int 21h
ret
endp ReadPalette
proc CopyPal
; Copy the colors palette to the video memory registers
; The number of the first color should be sent to port 3C8h
; The palette is sent to port 3C9h
mov si,offset Palette
mov cx,256
mov dx,3C8h
mov al,0
; Copy starting color to port 3C8h
out dx,al
; Copy palette itself to port 3C9h
inc dx
PalLoop:
; Note: Colors in a BMP file are saved as BGR values rather than RGB.
mov al,[si+2] ; Get red value.
shr al,2 ; Max. is 255, but video palette maximal
; value is 63. Therefore dividing by 4.
out dx,al ; Send it.
mov al,[si+1] ; Get green value.
shr al,2
out dx,al ; Send it.
mov al,[si] ; Get blue value.
shr al,2
out dx,al ; Send it.
add si,4 ; Point to next color.
; (There is a null chr. after every color.)
loop PalLoop
ret
endp CopyPal
这段代码不是我的,我只知道它改变了整个程序的调色板。
当我在打印图像后使用 int 10h 打印像素时,它仍在使用此调色板。
但是当我在打印任何图像之前打印一个像素时,该像素具有正常的 BIOS 颜色。
我想知道如何将调色板改回 BIOS 调色板。
我发现的 bmp 调色板:
您必须在更改之前保存 BIOS 标准调色板,然后在完成后将其存储回去。
执行此操作的示例代码可能是
;WORD Buffer Segment
;WORD Buffer Offset
;DF = Direction of saving
SavePalette:
push bp
mov bp, sp
push es
push di
push ax
push dx
push cx
mov es, WORD [bp+06h]
mov di, WORD [bp+04h]
xor al, al
mov dx, 3c7h
out dx, al ;Read from index 0
inc dx
inc dx
mov cx, 300h ;3x256 reads
rep insb
pop cx
pop dx
pop ax
pop di
pop es
pop bp
ret 04h
;WORD Buffer Segment
;WORD Buffer Offset
;DF = Direction of loading
RestorePalette:
push bp
mov bp, sp
push ds
push si
push ax
push dx
push cx
mov ds, WORD [bp+06h]
mov si, WORD [bp+04h]
xor al, al
mov dx, 3c8h
out dx, al ;Write from index 0
inc dx
mov cx, 300h ;3x256 writes
rep outsb
pop cx
pop dx
pop ax
pop si
pop ds
pop bp
ret 04h
要使用此代码,您需要一个 300h 字节的缓冲区,假设它称为 PaletteBuffer
并且位于 DS
段中。
push ds
push WORD PaletteBuffer
call SavePalette
;Change palette for bitmap
push ds
push WORD PaletteBuffer
call RestorePalette
值得注意的是,更改整个调色板很慢,请考虑将代码更改为 save/restore 仅您需要的颜色(可能是前 16 种),或者仅在需要时将位图颜色映射到高索引数量少于256。
这也是 NASM 程序集,我还没有测试代码,只是草拟了一下,因为我不想设置 DosBox。
http://www.cs.cmu.edu/~ralf/files.html -> inter61a.zip -> INTERRUP.A
--------V-101017-----------------------------
INT 10 - VIDEO - READ BLOCK OF DAC REGISTERS (VGA/MCGA)
AX = 1017h
BX = starting palette register
CX = number of palette registers to read
ES:DX -> buffer (3 * CX bytes in size) (see also AX=1012h)
Return: buffer filled with CX red, green and blue triples
SeeAlso: AX=1012h,AX=1015h,INT 62/AX=00A4h
--------V-101012-----------------------------
INT 10 - VIDEO - SET BLOCK OF DAC REGISTERS (VGA/MCGA)
AX = 1012h
BX = starting color register
CX = number of registers to set
ES:DX -> table of 3*CX bytes where each 3 byte group represents one
byte each of red, green and blue (0-63)
Return: nothing
SeeAlso: AX=1010h,AX=1017h,INT 62/AX=00A5h
我正在用 8086 汇编(在 DOSBOX 中)开发一个游戏项目。
我有一个可以在图形模式下运行的贪吃蛇游戏,以及一个可以将 BMP 文件打印到屏幕上的菜单。
我唯一的问题是在打印过程中我将调色板更改为 bmp 调色板。
变色过程:
(这是将 bmp 打印到屏幕的代码的一部分)
proc ReadPalette
; Read BMP file color palette, 256 colors * 4 bytes (400h)
mov ah,3fh
mov cx,400h
mov dx,offset Palette
int 21h
ret
endp ReadPalette
proc CopyPal
; Copy the colors palette to the video memory registers
; The number of the first color should be sent to port 3C8h
; The palette is sent to port 3C9h
mov si,offset Palette
mov cx,256
mov dx,3C8h
mov al,0
; Copy starting color to port 3C8h
out dx,al
; Copy palette itself to port 3C9h
inc dx
PalLoop:
; Note: Colors in a BMP file are saved as BGR values rather than RGB.
mov al,[si+2] ; Get red value.
shr al,2 ; Max. is 255, but video palette maximal
; value is 63. Therefore dividing by 4.
out dx,al ; Send it.
mov al,[si+1] ; Get green value.
shr al,2
out dx,al ; Send it.
mov al,[si] ; Get blue value.
shr al,2
out dx,al ; Send it.
add si,4 ; Point to next color.
; (There is a null chr. after every color.)
loop PalLoop
ret
endp CopyPal
这段代码不是我的,我只知道它改变了整个程序的调色板。
当我在打印图像后使用 int 10h 打印像素时,它仍在使用此调色板。
但是当我在打印任何图像之前打印一个像素时,该像素具有正常的 BIOS 颜色。
我想知道如何将调色板改回 BIOS 调色板。
我发现的 bmp 调色板:
您必须在更改之前保存 BIOS 标准调色板,然后在完成后将其存储回去。
执行此操作的示例代码可能是
;WORD Buffer Segment
;WORD Buffer Offset
;DF = Direction of saving
SavePalette:
push bp
mov bp, sp
push es
push di
push ax
push dx
push cx
mov es, WORD [bp+06h]
mov di, WORD [bp+04h]
xor al, al
mov dx, 3c7h
out dx, al ;Read from index 0
inc dx
inc dx
mov cx, 300h ;3x256 reads
rep insb
pop cx
pop dx
pop ax
pop di
pop es
pop bp
ret 04h
;WORD Buffer Segment
;WORD Buffer Offset
;DF = Direction of loading
RestorePalette:
push bp
mov bp, sp
push ds
push si
push ax
push dx
push cx
mov ds, WORD [bp+06h]
mov si, WORD [bp+04h]
xor al, al
mov dx, 3c8h
out dx, al ;Write from index 0
inc dx
mov cx, 300h ;3x256 writes
rep outsb
pop cx
pop dx
pop ax
pop si
pop ds
pop bp
ret 04h
要使用此代码,您需要一个 300h 字节的缓冲区,假设它称为 PaletteBuffer
并且位于 DS
段中。
push ds
push WORD PaletteBuffer
call SavePalette
;Change palette for bitmap
push ds
push WORD PaletteBuffer
call RestorePalette
值得注意的是,更改整个调色板很慢,请考虑将代码更改为 save/restore 仅您需要的颜色(可能是前 16 种),或者仅在需要时将位图颜色映射到高索引数量少于256。
这也是 NASM 程序集,我还没有测试代码,只是草拟了一下,因为我不想设置 DosBox。
http://www.cs.cmu.edu/~ralf/files.html -> inter61a.zip -> INTERRUP.A
--------V-101017-----------------------------
INT 10 - VIDEO - READ BLOCK OF DAC REGISTERS (VGA/MCGA)
AX = 1017h
BX = starting palette register
CX = number of palette registers to read
ES:DX -> buffer (3 * CX bytes in size) (see also AX=1012h)
Return: buffer filled with CX red, green and blue triples
SeeAlso: AX=1012h,AX=1015h,INT 62/AX=00A4h
--------V-101012-----------------------------
INT 10 - VIDEO - SET BLOCK OF DAC REGISTERS (VGA/MCGA)
AX = 1012h
BX = starting color register
CX = number of registers to set
ES:DX -> table of 3*CX bytes where each 3 byte group represents one
byte each of red, green and blue (0-63)
Return: nothing
SeeAlso: AX=1010h,AX=1017h,INT 62/AX=00A5h