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), and I ran into a problem, how you can see in the image, every line is printed, but in every line, every group of four pixels only the color of the first pixel is printed, this is after printing the image in a different space in the VRAM for double buffering, so all four planes are having the data of the first plane.
This is how the image should be printed (this is direct print without double buffer, yes there is a problem with the timer but it does not matter)
This is how the image is being printed with the double buffering
I do believe that the problem is that the data is different from read to write in the VGA ports when it comes to mode x, here is the code of selecting the VGA plane
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
And if the outputs are not the problem here is the code of the memory transfer:
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
In the Graphics Controller of the VGA there's a separate register to specify the plane to read from.
You select it by writing a 4 in address port 03CEh, followed by writing the plane number (0-3) in data port 03CFh.
The 03C4h:02h register that you use is called ColorPlaneWriteEnable. The answer is already in its name! It allows writing to one or more planes at the same time. For reading use 03CEh:04h ReadPlaneSelect.
proc DoubleBuffer ... endp pageFlipping
PageFlipping does not require the copying of large chunks of memory as this procedure is doing.
The idea of DoubleBuffering is to use 'normal' RAM to build the picture and copy all or part of it to the video memory. Your program uses video memory to hold the double buffer and as a consequence reading will be very slow!
You don't need that shifting and preserving at all!
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
This can further be reduced to:
xor di, di
mov si, NON_VISABLE_PLANE_OFFSET
mov cx, 16000
cld
rep movs byte [di], [es:si]
The syntax for the rep movs
depends on the assembler you use.
In NASM you would have to precede the REP MOVSB
instruction by the segment override, so ES REP MOVSB