如何在windows tasm dosbox中读取图像文件并在屏幕上显示

时间:2017-08-20 02:56:54

标签: assembly graphics tasm dosbox

我目前正在使用dosbox学习tasm中的图形编程。我一直在使用一堆循环来绘制正方形像素块,而且非常难。我想知道是否有一种阅读图像并显示它的方法。我知道如何读取txt文件可能这是一个开始。请帮忙

1 个答案:

答案 0 :(得分:1)

您需要编写/使用图像加载器或使用您自己的图像文件格式。 BMP 可能看起来很简单,但有太多像压缩像素格式等,但您仍然可以专注于特定类型的 BMP 并忽略所有其他...

回到 MS-DOS 的时代,我使用256色 PCX 图像和调色板,因为我使用256色视频模式。这里 NASM LINEZ 游戏示例:

请参阅pcx:子例程。它将加载的 PCX 文件从内存ds:0解码为es:di处的原始 VGA 图像。请注意它只支持64 KByte大小限制!!! 现在要将图像可视化,您必须将es:di内容复制到 VideoRAM (假设为A000:0000),例如rep movsd,或者您可以设置es:di首先是它(但可能闪烁)。

PCX 加载程序不使用图像中的调色板,因此您需要对其进行编码...(更改 VGA 调色板的例程包含在源代码中只需要从 PCX 中提取 RGB 值,我认为它位于文件末尾)点击此处:

如果将PCX转换为32位原始图像。

有关 MS-DOS 游戏编程的详细信息,请参阅PCGPE 1.0

这是另一个使用自己的图片文件格式的游戏示例( TASM ):

它有文本菜单,二进制文件访问,320x200精灵图形,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,al
    sub ax,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,[cs:hand]
    mov ah,3Fh
    int 21h
    mov bl,0
    jnc fread0
    mov bl,al
    sub ax,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,2
    out dx,al
    lodsb
    shr al,2
    out dx,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
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

所以拍摄任何图像到800x600将其转换为带有调色板的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 预览:

preview