回到MS-DOS时代,我使用了带有调色板的256色PCX图像,因为我使用了256色视频模式.这里有NASM LINEZ游戏示例:
> Color Lines – simple game in C++/the checking algorithm
看到pcx:子程序.它将加载的PCX文件从内存ds:0解码为es:di的原始VGA图像.请注意它确实只支持64 KB的大小限制!
现在可视化图像,您必须将es:di内容复制到VideoRAM(假设A000:0000),例如使用rep movsd,或者您可以首先将es:di设置为它(但可能会闪烁).
然而,这个PCX加载器不使用图像中的调色板,因此您需要对其进行编码…(更改VGA调色板的例程包含在您需要从PCX中提取RGB值的源中我认为它是在最后文件)看这里:
> my C++ PCX loader with palette
如果将PCX转换为32位原始图像.
有关MS-DOS游戏编程的更多信息,请参阅PCGPE 1.0
这里是另一个使用自己的图像文件格式的游戏示例(TASM):
> What is the best way to move an object on the screen?
它有文本菜单,二进制文件访问,320×200精灵图形,3个人类播放器
[Edit1]新代码
我删除了旧的代码示例,而是在TASM中使用调色板查看器创建了可编译和工作的8位PCX.它使用VESA 800x600x256色彩模式(103h).
图像必须适合屏幕,文件大小必须小于64 KB!
我没有添加任何检查或错误消息……它只是加载文件image.pcx并在VESA上显示它然后等待按键命中结束退出.这里是TASM来源:
PCX.ASM
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; .386 IDEAL MODEL TINY ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; DATASEG file: db 'image.pcx',0 ;filename to load buff: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; CODESEG STARTUPCODE scrxs equ 800 scrys equ 600 mov ax,103h ; VESA 800x600x256 call vesamod mov al,0 call vesapag ; scrxs equ 320 ; scrys equ 200 ; mov ax,19 ; VGA 320x200x256 ; int 10h lea dx,[file] ; load PCX into DS:buff,CX bytes call fopen lea dx,[buff] mov cx,64000 ; some max value to fit into DS segment call fread ; CX is PCX real size call fclose lea si,[buff] ; decode directly to VRAM mov ax,0A000h mov es,ax mov di,0 call pcx mainl0: mov ax,256 ; test keyboard int 16h jz mainl0 sub ax,ax ; clear key buffer int 16h mov ax,3 ;|VGA 80x25 text int 16 ret ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; vesamod:pusha ;set VESA videomode ax mov bx,ax mov ax,4f02h int 16 popa ret ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; vesapag:pusha ;al=page switch vesa video page window A mov [cs:scrpag],al mov dl,al sub dh,dh sub bx,bx mov ax,4f05h ; window A int 16 popa ret ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; .386P scrpag db 0 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; .386P hand dw 0 ;### handler... ferr db 0 ;### DOS error code ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; fopen: pusha ;DS:DX = file name,[hand] <= file handle mov ax,3D02h int 21h mov bl,0 jnc fopen0 mov bl,al sub ax,ax fopen0: mov [cs:hand],ax mov [cs:ferr],bl popa ret ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; fclose: pusha ;[hand] = file handle mov bx,[cs:hand] mov ah,3eh int 21h mov bl,0 jnc fclose0 mov bl,ax fclose0:mov [cs:ferr],bl mov [cs:hand],ax popa ret ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; fread: pusha ;DS:DX = adr,CX = lenght,[hand] = hand,CX => read mov bx,3Fh int 21h mov bl,0 jnc fread0 mov bl,ax fread0: mov [cs:ferr],bl mov [cs:freadsz],ax popa mov cx,[cs:freadsz] ret freadsz dw 0 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; pcx: pusha ;decode pcx at ds:si to es:di cx = PCX size push ds push es push ecx push edx push si ;set palette add si,cx sub si,768 sub ax,ax pall0: mov dx,3C8h mov al,ah out dx,al inc dx lodsb shr al,2 out dx,al lodsb shr al,al inc ah jnz pall0 pop si mov ax,[ds:si+8] ;get xs sub ax,[ds:si+4] inc ax mov [cs:pcxxs],ax mov [cs:pcxx],ax mov ax,[ds:si+10] ;get ys sub ax,[ds:si+6] inc ax mov [cs:pcxys],ax mul [cs:pcxxs] push dx push ax pop edx add si,128 ;src start after pcx header sub ecx,ecx ;RLE decoder of PCX pcxl0: lodsb mov cx,1 cmp al,192 jb pcxr0 mov cl,al and cl,63 lodsb pcxr0: mov bx,cx pcxl1: call point dec [cs:pcxx] ;correct next screen line position if end of PCX line jnz pcxr1 mov ax,[cs:pcxxs] mov [cs:pcxx],ax neg ax add ax,scrxs add di,ax jnc pcxr1 ; page swith mov al,[cs:scrpag] inc al call vesapag pcxr1: loop pcxl1 mov cx,bx sub edx,ecx jz pcxesc jnc pcxl0 pcxesc: pop edx pop ecx pop es pop ds popa ret pcxxs dw 0 ;PCX resolution pcxys dw 0 pcxx dw 0 ;actual X coordinate ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; point: mov [es:di],al ;point ;estosb inc di jnz pntesc ; page swith mov al,[cs:scrpag] inc al call vesapag pntesc: ret ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; END ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
因此,将任何高达800×600的图像转换为带有调色板的256色PCX,并将其重命名为image.pcx.然后将其放入* .com文件并运行.我使用Volcov commander扩展脚本vc.ext编译它,如下所示:
asm:@c:\language\compil\tasm\tasm !.! /ic:\language\source\tasm\inc @c:\language\compil\tasm\tlink !.obj /t /x @del !.obj
所以每次我在任何asm文件上按Enter键都会编译.只需更改路径,如果您没有定位* .com文件,请相应地更改/ t开关.这里从我的DOSBox预览: