From: moskewicz AT MEM DOT po DOT com Date: Wed, 22 May 1996 19:51:45 -0400 Message-Id: <9605222351.AA08851@mercury> To: djgpp AT delorie DOT com Subject: Code: V_SYNC and asm for "far" data example The following code illustrates the answers to a few of the graphics questions that have been floating around. The full (400+ lines) Vesa.h might be usefull to some people, especially if they need help with a Linear Frame Buffer, or bank switching. Forgive the long code, but I seem to remember questions pertaining to most of the code here (I hope). Mainly, someone asked about detecting V_SYNC (Vertical interval) and transfering data from a buffer to the screen. Hopefully, one semi-long off topic post can stave off a whole lot more! Again, if anyone is crazy enough to want the complete package, with complete vesa and some drawing functions just ask. Better yet, get Allegro, and save yourself some trouble... // VESA.H // // Programmed by Matt Moskewicz, Based on the work of Lester Vecsey // June 11, 1995 // March 7, 1996 // NOTE: This is an example only, most of this file has been removed, and is // required for real functionality. This code is probably full of bugs, // though it DOES seem to work :) // MISSING CODE INCLUDES: // GrState class -=- Includes bunches of info, like lines_per_screen,etc // GrState::Init() -=- Decides what vesa mode (if any) to use, sets up LFB // =- Also determines and sets up flip_mode // GrState::Refresh-=- Parts dealing with Bank-Switching are removed // VESA structs, and some other VESA functions. // The missing code is fairly extensive, and I'll mail it if anybody wants it. // Thanks to Charles Sandman for providing examples. See his VBE.ZIP, // It is much simpler than mine... it has no asm // flip_mode can be: // 0 -=- Raw Copy for Standard VGA (or for VESA 2.0 LFB, single buffered) // 1 -=- VESA Banked copy (for VESA 1.x and VESA 2.0 without LFB) // 2 -=- Page Flipping (for VESA 2.0 LFB, double buffered) // The basic design premise is that the place we draw in, our gr_selector and // gr_offset are always linear, regardless of video mode or VESA type. // flip_modes 0 and 2 provide excellent performance. // flip_mode 1 could stand major improvement //for standard VGA and banked VESA 1.2 (flip_mode 0 and 1) //gr_offset = malloc(size_of_screen); //gr_selector = _go32_my_ds(); //true_gr_offset = 0xa0000; //Almost always, even for VESA //true_gr_selector = _go32_conventional_mem_selector(); //for VESA 2.0 with a LFB (flip_mode 2) //gr_offset = 0; //gr_selector = a selector we have to set up (code removed) //true_gr_offset = gr_offset + size_of_screen //true_gr_selector = gr_selector; void GrState::Refresh(void) { if (flip_mode == 1 || flip_mode == 0) //These two modes need to check { //VGA registers to detect the //Vetical interval //First, if we are in an interval We wait for it to end... which //is probably unneccessary. Then we wait for the next one to start. asm(" 1: movw $0x03da,%%edx inb %%dx,%%al andb $0x08,%%al jnz 1b 2: inb %%dx, %%al andb $0x08, %%al jz 2b " : : :"%eax","%edx" ); } if (flip_mode == 0) //Simple copy from gr (offscreen buffer) to true_gr { asm(" movw %3, %%fs movw %4, %%gs 1: movl %%fs:(,%0,1),%%eax # Note, I don't use REP and MOVSL type addl $0x4, %0 # opcodes because they are slower than movl %%eax,%%gs:(,%1,1) # this, in theory. Esp. if I indexed by addl $0x4, %1 # 4. With add instead of inc, I'm not decl %2 # so sure... jnz 1b " : // no outputs :"D"(gr_offset),"S"(true_gr_offset) ,"c"(bytes_per_line*lines_per_screen/4) ,"m"(gr_selector),"m"(true_gr_selector) :"%eax","%ecx" ); } if (flip_mode == 2) //This is out Best, cleanest flipping mode... { //It's Double buffered, and VESA does all the work. if (gr_offset) vesa_set_display_start(lines_per_screen); else vesa_set_display_start(0); int temp=true_gr_offset;true_gr_offset=gr_offset;gr_offset=temp; } } void vesa_videomode(unsigned int mode) // This will set a VESA mode, but it really should not be used without // Support funtions like vesa_getvesainfo and vesa_getmodeinfo { _go32_dpmi_registers regs; regs.x.sp = regs.x.ss = 0; regs.x.ax = 0x4f02; regs.x.bx =(unsigned short) mode; _go32_dpmi_simulate_int(0x10,®s); if (regs.h.ah) { printf("Failed to Init VESA mode %x. Exiting with ah:%x.\n",mode,regs.h.ah); exit(3); } } void vesa_set_display_start(unsigned int scanline) // This sets the first displayed scanline out of all the scanlines in // video RAM. { _go32_dpmi_registers regs; regs.x.sp = regs.x.ss = 0; regs.x.ax = 0x4f07; regs.x.dx =(unsigned short) scanline; regs.x.cx = 0; regs.x.bx = 0x80; _go32_dpmi_simulate_int(0x10,®s); } ---- moskewicz AT mem DOT po DOT com