Drawind in graphical mode! Can't fill up screen, only 5-10%

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
ch3ll0v3k
Posts: 10
Joined: Sat Oct 01, 2016 1:26 am

Drawind in graphical mode! Can't fill up screen, only 5-10%

Post by ch3ll0v3k »

Hay!
switch to graphic move from "C" like this

Code: Select all


#define VBE_DISPI_IOPORT_INDEX          0x01CE
#define VBE_DISPI_IOPORT_DATA           0x01CF
#define VBE_DISPI_INDEX_ID              0x0
#define VBE_DISPI_INDEX_XRES            0x1
#define VBE_DISPI_INDEX_YRES            0x2
#define VBE_DISPI_INDEX_BPP             0x3
#define VBE_DISPI_INDEX_ENABLE          0x4
#define VBE_DISPI_INDEX_BANK            0x5
#define VBE_DISPI_INDEX_VIRT_WIDTH      0x6
#define VBE_DISPI_INDEX_VIRT_HEIGHT     0x7
#define VBE_DISPI_INDEX_X_OFFSET        0x8
#define VBE_DISPI_INDEX_Y_OFFSET        0x9

#define VBE_DISPI_DISABLED              0x00
#define VBE_DISPI_ENABLED               0x01
#define VBE_DISPI_GETCAPS               0x02
#define VBE_DISPI_8BIT_DAC              0x20
#define VBE_DISPI_LFB_ENABLED           0x40
#define VBE_DISPI_NOCLEARMEM            0x80

void vbe_write( uint16_t index, uint16_t value) {
    // http://wiki.osdev.org/VGA_Hardware#Memory_Layout_in_16-color_graphics_modes
    outw(VBE_DISPI_IOPORT_INDEX, index);
    outw(VBE_DISPI_IOPORT_DATA, value);
}


void vbe_set( uint16_t xres, uint16_t yres, uint16_t bpp) {
    // http://wiki.osdev.org/VGA_Hardware#Memory_Layout_in_16-color_graphics_modes
    vbe_write(VBE_DISPI_INDEX_ENABLE, VBE_DISPI_DISABLED);
    vbe_write(VBE_DISPI_INDEX_XRES, xres);
    vbe_write(VBE_DISPI_INDEX_YRES, yres);
    vbe_write(VBE_DISPI_INDEX_BPP, bpp);
    vbe_write(VBE_DISPI_INDEX_ENABLE, VBE_DISPI_ENABLED | VBE_DISPI_LFB_ENABLED);
}

// ---------------------------------------------------------------
    screenWidth = 640;
    screenHeight = 480;
    uint32_t ppb = 16;

    vbe_set( screenWidth, screenHeight, ppb ); // Vga is limited to a 640x480x16

An also i have multiboot headers set up in asssembly:

Code: Select all

MBALIGN  equ  1<<0              ; // align loaded modules on page boundaries
MEMINFO  equ  1<<1              ; // provide memory map
;VIDMOD   equ  1<<2              ; // information about the video mode table must be available to the kernel.
;ELF_OR   equ  1<<16            ; // must be providet if kernel is not ELF
FLAGS    equ  MBALIGN | MEMINFO; | VIDMOD

MAGIC    equ  0x1BADB002        ; // 'magic number' lets bootloader find the header
CHECKSUM equ -(MAGIC + FLAGS)   ; // checksum of above, to prove we are multiboot

; Vga is limited to a 640x480x16
section .text
	dd MAGIC
	dd FLAGS
	dd CHECKSUM
   	dd 0						; 12 	u32 	header_addr 	if flags[16] is set
    dd 0						; 16 	u32 	load_addr 	if flags[16] is set
    dd 0						; 20 	u32 	load_end_addr 	if flags[16] is set
    dd 0						; 24 	u32 	bss_end_addr 	if flags[16] is set
    dd 0						; 28 	u32 	entry_addr 	if flags[16] is set

    dd 0						; 32 	u32 	mode_type 	if flags[2] is set
    dd 640						; 36 	u32 	width 	if flags[2] is set
    dd 480						; 40 	u32 	height 	if flags[2] is set
    dd 16						; 44 	u32 	depth 	if flags[2] is set 

    ;dd 1						; 32 	u32 	mode_type 	if flags[2] is set
    ;dd 80						; 36 	u32 	width 	if flags[2] is set
    ;dd 25						; 40 	u32 	height 	if flags[2] is set
    ;dd 0						; 44 	u32 	depth 	if flags[2] is set 

The problem is that i can't fill up the screen.
The mode im using: [640x480x16]. It does not matter,which mode im using, the result is th same, just colors are different, because of bits per pixel is wrong. bud it is not important for the moment.

Code: Select all

    uint16_t Y = 1, i = 0;
    uint16_t * screen = (uint16_t *) 0xA0000;

    while ( i < 640 * 480 * 32 ) {

        unsigned where = (i*4) + Y*3200;
        screen[ where ] = 0b01111111;
        screen[ where + 1] = 0;

        i++;
    }


Techel
Member
Member
Posts: 215
Joined: Fri Jan 30, 2015 4:57 pm
Location: Germany
Contact:

Re: Drawind in graphical mode! Can't fill up screen, only 5-

Post by Techel »

You might want to have a look at linear and planar framebuffers. With 16 colors, taking up 4 bits per pixel, there are four planes, each containing one bit per pixel. But have a look at the wiki.
User avatar
SpyderTL
Member
Member
Posts: 1074
Joined: Sun Sep 19, 2010 10:05 pm

Re: Drawind in graphical mode! Can't fill up screen, only 5-

Post by SpyderTL »

Your while loop is wrong. You shouldn't be multiplying by 32, and you should be multiplying y by 640, not 3200.

Also, don't multiply "i" by 4. And only set the value once, to say 0xffff. Don't bother setting screen[where + 1] at all.

See if that fixes your problem.

You shouldn't be using the VGA specs for your calculations. You should be using the Bochs VBE Extensions specs.

You are also setting your video mode twice -- Once when your multiboot boot loader reads your header, and again when your VBE code runs. Your multiboot header will work on any VGA compatible machine. Your VBE code will only work on a few Virtual Machines, like Bochs or VirtualBox.
Project: OZone
Source: GitHub
Current Task: LIB/OBJ file support
"The more they overthink the plumbing, the easier it is to stop up the drain." - Montgomery Scott
ch3ll0v3k
Posts: 10
Joined: Sat Oct 01, 2016 1:26 am

Re: Drawind in graphical mode! Can't fill up screen, only 5-

Post by ch3ll0v3k »

Thanks for helping.

Now im trying it like this without positive result

And my screen is almost always like on the screen-shot.
If i use 0xA0000; then i get this result,if i use other base address, then the screen is black.
I cant figure out, what logic is here has bin used.

Code: Select all

#define VBE_DISPI_BANK_ADDRESS          0xA0000
#define VBE_DISPI_LFB_PHYSICAL_ADDRESS  0xE0000000
#define VBE_DISPI_BANK_SIZE_KB          64

#define VBE_DISPI_ID0                   0xB0C0
#define VBE_DISPI_ID1                   0xB0C1
#define VBE_DISPI_ID2                   0xB0C2
#define VBE_DISPI_ID3                   0xB0C3
#define VBE_DISPI_ID4                   0xB0C4
#define VBE_DISPI_ID5                   0xB0C5

#define VBE_DISPI_IOPORT_INDEX          0x01CE
#define VBE_DISPI_IOPORT_DATA           0x01CF

#define VBE_DISPI_INDEX_ID              0x0

#define VBE_DISPI_INDEX_XRES            0x1
#define VBE_DISPI_INDEX_YRES            0x2
#define VBE_DISPI_MAX_XRES              1024
#define VBE_DISPI_MAX_YRES              768

#define VBE_DISPI_INDEX_BPP             0x3
#define VBE_DISPI_INDEX_ENABLE          0x4
#define VBE_DISPI_INDEX_BANK            0x5
#define VBE_DISPI_INDEX_VIRT_WIDTH      0x6
#define VBE_DISPI_INDEX_VIRT_HEIGHT     0x7
#define VBE_DISPI_INDEX_X_OFFSET        0x8
#define VBE_DISPI_INDEX_Y_OFFSET        0x9

#define VBE_DISPI_DISABLED              0x00
#define VBE_DISPI_ENABLED               0x01
#define VBE_DISPI_GETCAPS               0x02
#define VBE_DISPI_8BIT_DAC              0x20
#define VBE_DISPI_LFB_ENABLED           0x40
#define VBE_DISPI_NOCLEARMEM            0x80

// ====================================================================
void _vid_reg(uint16_t i_val, uint16_t i_data) {
    outw( VBE_DISPI_IOPORT_INDEX, i_val );
    outw( VBE_DISPI_IOPORT_DATA, i_data );
}

uint16_t bga_reg(uint16_t IndexValue) {
    outw(VBE_DISPI_IOPORT_INDEX, IndexValue);
    return inw(VBE_DISPI_IOPORT_DATA);
}

int is_bga_available() {
    return (bga_reg(VBE_DISPI_INDEX_ID) == VBE_DISPI_ID4);
}

void set_vid_mod(uint32_t width, uint32_t height, uint32_t bpp) {

    _vid_reg(VBE_DISPI_INDEX_ENABLE, VBE_DISPI_DISABLED);
    _vid_reg(VBE_DISPI_INDEX_XRES, width);
    _vid_reg(VBE_DISPI_INDEX_YRES, height);
    _vid_reg(VBE_DISPI_INDEX_BPP, bpp);
    _vid_reg(VBE_DISPI_INDEX_ENABLE, VBE_DISPI_ENABLED | VBE_DISPI_LFB_ENABLED );
}

void bga_set_bank(uint16_t BankNumber) {
    _vid_reg(VBE_DISPI_INDEX_BANK, BankNumber);
}

// ====================================================================
// this gets called from main 
int main(){
     set_vid_mod( 640, 480, 16 );
}
// ====================================================================
Attachments
bg2.png
bg.png
Octocontrabass
Member
Member
Posts: 5587
Joined: Mon Mar 25, 2013 7:01 pm

Re: Drawind in graphical mode! Can't fill up screen, only 5-

Post by Octocontrabass »

ch3ll0v3k wrote:If i use 0xA0000; then i get this result,
The address range from 0xA0000-0xBFFFF is too small for an entire 640x480x16bpp screen.
ch3ll0v3k wrote:if i use other base address, then the screen is black.
Qemu emulates a PCI system by default, with a PCI video card. The LFB base address for the PCI video card can only be found by reading the video card's BAR0. You could configure Qemu to emulate an ISA video card; the base address for Qemu's ISA video card is always 0xE0000000.
glauxosdever
Member
Member
Posts: 501
Joined: Wed Jun 17, 2015 9:40 am
Libera.chat IRC: glauxosdever
Location: Athens, Greece

Re: Drawind in graphical mode! Can't fill up screen, only 5-

Post by glauxosdever »

Hi,


Hardcoding the base address of the framebuffer is not really the best you can do. The multiboot specification defines a field that contains the base address of the framebuffer.

Depending on a specific (virtual) computer (QEMU) is probably the worst idea when doing OS development. This way you only assure that no one will install your OS on a physical computer, and most of people will not install your OS on a virtual computer, besides people using QEMU as their emulator.


Regards,
glauxosdever
User avatar
SpyderTL
Member
Member
Posts: 1074
Joined: Sun Sep 19, 2010 10:05 pm

Re: Drawind in graphical mode! Can't fill up screen, only 5-

Post by SpyderTL »

According to the QEMU wiki:

Code: Select all

-vga type     Select type of VGA card to emulate. Valid values for type are 
cirrus     Cirrus Logic GD5446 Video card. All Windows versions starting from Windows 95 should recognize and use this graphic card. For optimal performances, use 16 bit color depth in the guest and the host OS. (This one is the default) 
std     Standard VGA card with Bochs VBE extensions. If your guest OS supports the VESA 2.0 VBE extensions (e.g. Windows XP) and if you want to use high resolution modes (>= 1280x1024x16) then you should use this option.
If you are going to use the Bochs VBE extensions, you will need to run QEMU with the "-vga std" option.


And according to the OSDEV wiki:
Using a linear frame buffer (LFB)

When using a linear framebuffer, the BGA exposes all of the video memory in a single linearly addressable section of memory. The address of the framebuffer is not fixed, and must be read from the first PCI base address register (BAR 0 of device 0x1234:0x1111). To enable the linear framebuffer, use the VBE_DISPI_LFB_ENABLED flag (0x40) when enabling the BGA in conjunction with the VBE_DISPI_ENABLED flag.

Unlike Bochs, QEMU does not necessarily pay attention to the VBE_DISPI_LFB_ENABLED flag with respect to banked memory access, allowing both the linear framebuffer and banked memory to be used at all times. Bochs will not honour requests to change the memory bank when the linear framebuffer is enabled, and it will similarly ignore any writes made to the memory bank.

Note: In older versions of Bochs and QEMU, the framebuffer was fixed at 0xE0000000, and modern versions will use that address when emulating ISA-only systems. It is highly inadvisable to make assumptions about the address of the linear framebuffer. It should always be read from the BGA's PCI BAR0.
My QEMU is using 0xFD000000 as it's base address when using -vga std on the command line, so you may try using that for testing purposes...
Project: OZone
Source: GitHub
Current Task: LIB/OBJ file support
"The more they overthink the plumbing, the easier it is to stop up the drain." - Montgomery Scott
ch3ll0v3k
Posts: 10
Joined: Sat Oct 01, 2016 1:26 am

Re: Drawind in graphical mode! Can't fill up screen, only 5-

Post by ch3ll0v3k »

Thanks every body! :roll:
Post Reply