Сборка: для чтения плоскости в режиме x требуется другой вывод на порты VGA от записи? - PullRequest
6 голосов
/ 04 февраля 2020

1 Я пишу в TASM 3.0 на DosBox 0.74, и я пытаюсь писать в Режим x (настроенный 13h, режим без цепочки 13 ), и Я столкнулся с проблемой, как вы можете видеть на изображении, каждая строка печатается, но в каждой строке, каждая группа из четырех пикселей печатается только цвет первого пикселя, это после печати изображения в другом месте в VRAM для двойной буферизации, поэтому все четыре плоскости имеют данные первой плоскости.

Так должно быть напечатано изображение (это прямая печать без двойного буфера, да, есть проблема с таймером, но это не имеет значения)

enter image description here

Так распечатывается изображение с двойной буферизацией

enter image description here

Я действительно считаю, что проблема в том, что данные отличаются от чтения для записи в портах VGA, когда дело доходит до режима x, вот код выбора Плоскость 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

А если выходы n Не проблема здесь в коде передачи памяти:

    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

1 Ответ

3 голосов
/ 06 февраля 2020

В графическом контроллере VGA есть отдельный регистр для указания плоскости для чтения.

Вы выбираете его, записывая 4 в адресном порту 03CEh, а затем записывая номер плоскости (0-3) в порт данных 03CFh.

Используемый регистр 03C4h: 02h называется ColorPlane запись Включить. Ответ уже в его названии! Это позволяет писать на один или несколько самолетов одновременно. Для чтения используйте 03CEh: 04h ReadPlaneSelect.


proc DoubleBuffer
...
endp pageFlipping

Что это?

PageFlipping не требует копирования больших кусков памяти, поскольку эта процедура делает.
Идея DoubleBuffering состоит в том, чтобы использовать «обычную» оперативную память для построения изображения и копирования его полностью или частично в видеопамять. Ваша программа использует видеопамять для хранения двойного буфера, и, как следствие, чтение будет очень медленным!

Почему DoubleBuffer_l oop так сильно усложняется?

Вы надеваете Это вообще не нужно! Смещение и сохранение!

    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

...