Код, который вы сказали, что не писал сам, неверен! Чтобы заполнить весь 256-цветной экран размером 320x200 с помощью растрового изображения того же размера, координата Y должна изменяться от 199 до 0. В настоящее время этот код повторяется от 200 до 1, поэтому нижняя строка растрового изображения никогда не отображается. Это легко исправить.
Когда вы сказали нам, что изменили разрешение экрана на 800x600, вы также должны были сообщить нам разрешение цвета. В приведенном ниже коде я предполагаю, что это 256 цветов, как в примере кода. Кроме того, я представлю решение, которое использует метод LinearFrameBuffer. Оконный подход существует, но он более сложен (конечно, если вы не хотите обрезать слишком много углов). Для видеорежима, который больше не помещается в графическое окно размером 64 КБ (800 * 600 = 480000 байт), потребуется переключение банков с помощью VESA .
.
Но пример 320x200 также может использовать метод LFB.
Видеоокно находится по сегментированному адресу 0A000h: 0000h. Фактически это линейный адрес 000A0000h.
; On entry BX is handle for the file with filepointer at bitmap data!!!
proc CopyBitmap
; BMP graphics are saved upside-down.
; Read the graphic line by line (200 lines in VGA format),
; displaying the lines from bottom to top.
push es
xor ax, ax
mov es, ax
mov cx, 200
PrintBMPLoop:
push cx
; Point to the correct screen line
dec cx ; Y ranging from 199 to 0
movzx edi, cx
imul edi, 320
add edi, 000A0000h
; Read one line
mov dx, offset ScrLine
mov cx, 320
mov ah, 3Fh ; DOS.ReadFile
int 21h
jc WhatIfError?
cmp ax, cx
jne WhatIfError?
; Copy one line into video memory
mov si, dx
add dx, cx ; DX now points to the end of the buffer
CopyLoop:
lodsd ; Load 4 pixels together
stosd [edi] ; This generates an AddressSizePrefix
cmp si, dx
jb CopyLoop
pop cx
loop PrintBMPLoop
pop es
ret
endp CopyBitmap
И код 800x600 очень похож.
Вы получаете значение BytesPerScanLine и адрес LinearFrameBuffer при проверке результатов функции VESA 4F01h ReturnVBEModeInformation.
- смещение +40 от ModeInfoBlock PhysBasePtr (dword)
- смещение +50 от ModeInfoBlock LinBytesPerScanLine (слово)
Значение BytesPerScanLine не обязательно должно быть 800. Графическая среда может легко выбрать 1024 в качестве более разумного значения. Вам нужно проверить, а не просто предположить.
; On entry BX is handle for the file with filepointer at bitmap data!!!
proc CopyBitmap
; BMP graphics are saved upside-down.
; Read the graphic line by line (600 lines in SVGA format),
; displaying the lines from bottom to top.
push es
xor ax, ax
mov es, ax
mov cx, 600
PrintBMPLoop:
push cx
; Point to the correct screen line
dec cx ; Y ranging from 599 to 0
movzx edi, cx
imul edi, BytesPerScanLine
add edi, LinearFrameBuffer
; Read one line
mov dx, offset ScrLine
mov cx, 800
mov ah, 3Fh ; DOS.ReadFile
int 21h
jc WhatIfError?
cmp ax, cx
jne WhatIfError?
; Copy one line into video memory
mov si, dx
add dx, cx ; DX now points to the end of the buffer
CopyLoop:
lodsd ; Load 4 pixels together
stosd [edi] ; This generates an AddressSizePrefix
cmp si, dx
jb CopyLoop
pop cx
loop PrintBMPLoop
pop es
ret
endp CopyBitmap