Page 1 of 1

Display a bmp image in long mode or protected mode

Posted: Wed Jul 07, 2021 8:04 pm
by amandude
I am trying to display a bmp background image in my Operating System, and I need to set the video mode, but I can't seem to understand how to enter into real mode or v86 mode because every time I use this code: [wiki]https://wiki.osdev.org/Virtual_8086_Mode[/wiki] or this code: [wiki]https://wiki.osdev.org/Real_Mode[/wiki] It just flickers text on boot. I know I cannot use interrupt 10h in long mode or protected mode, but I need to set the video mode!

Is there a "full" example or code that I could use to get in real or v86 mode, or is there an alternative way to display a bmp in long mode?
PS: I have also tried setting the video mode in the multiboot header file, but that does not work.

Notes
I am using multiboot 2
I am using NASM Assembler
I am in long mode

Thanks for your help!

Re: Display a bmp image in long mode or protected mode

Posted: Wed Jul 07, 2021 9:57 pm
by Ethin
Have you mapped the VRAM into your virtual address space? And if setting the video mode via the multiboot2 header fails, have you implemented PCI and searched for the VGA device and tried configuring it that way? It'll be a bit more complicated but you shouldn't need to enter real mode at all then. Finally, which BMP format are you using, DIBs or a device-dependent BMP?
Edit: finally, do you have a repository somewhere that will let us look at your code? you might be messing up somewhere else entirely and your v8086 mode transition code may be perfectly correct.

Re: Display a bmp image in long mode or protected mode

Posted: Thu Jul 08, 2021 4:36 am
by bzt
amandude wrote:Is there a "full" example or code that I could use to get in real or v86 mode, or is there an alternative way to display a bmp in long mode?
You're confusing "modes". First, there's CPU mode. This can be real mode, prot mode or long mode.

Second, there's video mode. This has nothing to do with the CPU mode. To display a bitmap, you'll need a framebuffer, and you can use that framebuffer from whatever CPU mode you'd like. In order to get the framebuffer, you have to use VESA BIOS, which only runs in real mode. Therefore you have the following options:
- if you're in real mode, then it's ok
- if you're in prot mode, then either you switch to real mode or you use V86 virtual mode
- if you're in long mode, then the only possibility is to switch to real mode.

There are other possibilities though: you could write your own video card driver (very hard), or you could use an x86 real mode emulator to interpret the VESA BIOS in long mode (several OS does this, not easy, but not particularly hard either, it is slow, but works.), and on modern machines there's no VESA BIOS at all, only UEFI GOP which is only accessible during boot.

Again, setting up the framebuffer has nothing to do with how you display a bitmap on it and from which CPU mode. You only set up the framebuffer once (so it okay if this is slow), and then you can use the framebuffer as many times and for as long as you want from long mode.

To set up the video, see the wiki:
VESA Video Bios Extension
UEFI GOP
Using Multiboot to get a framebuffer
You might consider BOOTBOOT, which loads 64 bit kernels, executes them in long mode, and sets up the framebuffer for them too out-of-the-box.

For plotting a pixel (this is for prot mode, but works in long mode too, does not require VESA/GOP etc. to plot pixels, just a pointer to the framebuffer, no matter how and from where you got that pointer):
Drawing in a linear framebuffer

For decoding and displaying bitmap files, see
Loading icons

I'd like to point out that TGA files are much better and much more portable than Windows BMP files, you probably want to aim for those. There's lots of confusion with Windows and OS/2 bitmaps. TGA is simple, and the wiki contains a small (~50 SLoC) code that can handle almost every variants. For PNG, I'd recommend Sean Barrett's stb_image.h header only library.

As for the "full" examples,
This code runs in long mode and uses GOP to get the framebuffer, then it displays a PNG image at the centre of the screen.
This also runs in long mode, it clears the screen then displays a TGA logo at the centre. Only supports 64 x 64 RLE-compressed paletted images, it's a very optimized code (for an implementation that can decode arbitrary TGA, see the wiki). It does not set the video mode, instead it relies on the boot loader to do that (similar like if you were relying on Multiboot, but unlike Multiboot, this works ;-))
This code also runs in long mode, also relies on the boot loader for the set up, and it displays actual bitmaps (in this PSF2 font, every glyph is a 8 x 16 bitmap)

Cheers,
bzt

Re: Display a bmp image in long mode or protected mode

Posted: Thu Jul 08, 2021 8:36 am
by Octocontrabass
amandude wrote:I am using multiboot 2
Update your multiboot header to request a video mode and the bootloader will set a video mode for you. Forget about real mode and v86 mode, you don't need them.

Re: Display a bmp image in long mode or protected mode

Posted: Fri Jul 09, 2021 10:08 am
by amandude
Ok, I read the documentation on multiboot 2, more specifically on "3.1.10 The framebuffer tag of Multiboot2 header". I tried what they said to do, and it changes the screen size and does print pixels, but I am not sure why it only prints pixels up two about 1/24 of the screen. I think it could be that the 0xA0000 address does not have enough bytes to handle the giant screen. I even tried looping though 32000 pixels, and it only gets about 2 3/4 lines down. If I try an infinite loop, it only gets about 4 lines (or rows) down and then stops. I don't know how to change the screen size manually, but I have tried doing it but nothing I do seems to work.

Does anybody here have a live example or source of adding the graphics mode to the multiboot header? here is what mine looks like so far:

section .multiboot_header
header_start:
dd 0xe85250d6

dd 0

dd header_end - header_start

dd 0x100000000 - (0xe85250d6 + 0 + (header_end - header_start))


dw 5
dw 320
dw 100
dw 1
dd 20

header_end:


Thanks :D

Re: Display a bmp image in long mode or protected mode

Posted: Fri Jul 09, 2021 10:26 am
by Octocontrabass
amandude wrote:0xA0000
This is not the framebuffer address. The bootloader tells you the framebuffer address in the "framebuffer_addr" field.

Re: Display a bmp image in long mode or protected mode

Posted: Sat Jul 10, 2021 7:17 am
by bzt
Octocontrabass wrote:
amandude wrote:0xA0000
This is not the framebuffer address. The bootloader tells you the framebuffer address in the "framebuffer_addr" field.
Yeah, but could be. Older SVGA cards mapped a 64K portion of the framebuffer at 0xA0000 (called banking), that's why the OP sees pixels on top of the screen when he writes to that address. Anyway, your advice is 100% correct, the "framebuffer_addr" field contains the address of the linear framebuffer (without banking, probably 0xE0000000 or something similar, not 0xA0000 for sure).

Cheers,
bzt