Код, который, как вы говорите, вы не написали сами, неверен! Чтобы заполнить весь 256-цветный экран 320x200 растровым изображением того же размера, координата Y должна изменяться от 199 до 0. В настоящее время этот код зацикливается от 200 до 1, поэтому нижняя строка растрового изображения никогда не отображается. Это легко исправить.
Когда вы сказали нам, что изменили разрешение экрана на 800x600, вы также должны были сообщить нам цветовое разрешение. В приведенном ниже коде я предполагаю, что это 256 цветов, как и в примере кода. Кроме того, я представлю решение, использующее метод LinearFrameBuffer. Оконный подход существует, но он сложнее (конечно, если вы не хотите срезать слишком много углов). Для видеорежима, который больше не подходит для графического окна размером 64 КБ (800 * 600 = 480 000 байт), потребуется переключение банка с помощью 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
И код 800х600 очень похож.
Вы получаете значение 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
person
Sep Roland
schedule
10.03.2019