程序集在 x 模式下读取平面是否需要与写入不同的输出到 VGA 端口?

Assembly does reading a plane in mode x needs a different output to the VGA ports from writing?

1I am writing in TASM 3.0 on DosBox 0.74 and I am trying to write in Mode x (Tweaked 13h, unchained mode 13),我运行陷入了一个问题,你怎么能在图像中看到,每一行都打印出来,但是在每一行中,每组四个像素只有颜色第一个像素被打印,这是在 VRAM 中的不同 space 中打印图像以进行双缓冲之后,因此所有四个平面都具有第一个平面的数据。

图像应该这样打印(这是没有双缓冲的直接打印,是的,定时器有问题但没关系)

这是使用双缓冲打印图像的方式

我认为问题是当涉及模式x时,数据与VGA端口中的读写不同,这里是选择VGA平面的代码

proc VGAPlaneSelect
    push ax
    push dx
    push cx
    mov al, 02h
    mov dx, 03C4h
    out dx, al
    VGAPlaneSelect_start:
    mov ax, 1
    mov cl, [VGAPlane]
    shl ax, cl
    cmp [VGAPlane], 4
    jne VGAPlaneSelect_end
        mov [VGAPlane], 0
        jmp VGAPlaneSelect_start
    VGAPlaneSelect_end:
    mov dx, 03C5h
    out dx, al
    pop cx
    pop dx
    pop ax
    ret
endp VGAPlaneSelect

如果输出不是问题,这里是内存代码 t运行sfer:

    proc DoubleBuffer
    mov ax, 0A000h
    mov es, ax
    mov [VGAPlane], 0
    call VGAPlaneSelect
    cli
    mov cx, 4
    DoubleBuffer_loop:
        xor di, di
        xor si, si
        push cx
        mov cx, 16000
        DoubleBuffer_loop_plane: 
            push di
            push si
            shr di, 2
            shr si, 2
            add si, NON_VISABLE_PLANE_OFFSET
            mov al, [es:si]
            stosb
            pop si
            pop di
            add di, 4
            add si, 4
        loop DoubleBuffer_loop_plane
        inc [VGAPlane]
        call VGAPlaneSelect
        pop cx
    loop DoubleBuffer_loop
    sti
    ret
endp pageFlipping

在 VGA 的图形控制器中,有一个单独的寄存器来指定要读取的平面。

你select它通过在地址端口03CEh写入一个4,然后在数据端口03CFh写入平面号(0-3)。

您使用的 03C4h:02h 寄存器称为 ColorPlaneWriteEnable。答案已经在它的名字里了!它允许同时写入一个或多个平面。阅读使用 03CEh:04h ReadPlaneSelect.


proc DoubleBuffer
...
endp pageFlipping

这是哪个?

PageFlipping 不需要像此过程那样复制大块内存。
DoubleBuffering的思想是利用'normal'RAM构建画面,将画面全部或部分复制到显存中。您的程序使用显存来保存双缓冲区,因此读取速度会很慢!

为什么 DoubleBuffer_loop 这么复杂?

你根本不需要移动和保存!

    xor di, di
    mov si, NON_VISABLE_PLANE_OFFSET
    mov cx, 16000
DoubleBuffer_loop_plane: 
    mov al, [es:si]
    stosb
    inc si
    dec cx
    jnz DoubleBuffer_loop_plane

这可以进一步简化为:

    xor di, di
    mov si, NON_VISABLE_PLANE_OFFSET
    mov cx, 16000
    cld
    rep movs byte [di], [es:si]

rep movs 的语法取决于您使用的汇编程序。 在 NASM 中,您必须在 REP MOVSB 指令之前通过段覆盖,因此 ES REP MOVSB