Display a bmp image in long mode or protected mode

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
amandude
Posts: 10
Joined: Wed Jul 07, 2021 7:18 pm

Display a bmp image in long mode or protected mode

Post 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!
Ethin
Member
Member
Posts: 625
Joined: Sun Jun 23, 2019 5:36 pm
Location: North Dakota, United States

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

Post 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.
User avatar
bzt
Member
Member
Posts: 1584
Joined: Thu Oct 13, 2016 4:55 pm
Contact:

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

Post 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
Octocontrabass
Member
Member
Posts: 5567
Joined: Mon Mar 25, 2013 7:01 pm

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

Post 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.
amandude
Posts: 10
Joined: Wed Jul 07, 2021 7:18 pm

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

Post 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
Octocontrabass
Member
Member
Posts: 5567
Joined: Mon Mar 25, 2013 7:01 pm

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

Post by Octocontrabass »

amandude wrote:0xA0000
This is not the framebuffer address. The bootloader tells you the framebuffer address in the "framebuffer_addr" field.
User avatar
bzt
Member
Member
Posts: 1584
Joined: Thu Oct 13, 2016 4:55 pm
Contact:

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

Post 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
Post Reply