📄 vbelib.c
字号:
r.edi = VirtToPhysOff(rm_space); memcpy(rm_space,data,sizeof(struct VesaCRTCInfoBlock)); } r.eax = 0x4f02; r.ebx = mode; retval = VBE_LRMI_int(0x10,&r); LRMI_free_real(rm_space); if(!retval) return VBE_VM86_FAIL; retval = r.eax & 0xffff; if(retval == 0x4f) { /* Just info for internal use (currently in SetDiplayStart func). */ vbeGetModeInfo(mode,&curr_mode_info); retval = VBE_OK; } return retval;}int vbeGetMode(unsigned *mode){ struct LRMI_regs r; int retval; memset(&r,0,sizeof(struct LRMI_regs)); r.eax = 0x4f03; if(!VBE_LRMI_int(0x10,&r)) return VBE_VM86_FAIL; retval = r.eax & 0xffff; if(retval == 0x4f) { *mode = r.ebx; retval = VBE_OK; } return retval;}int vbeGetPixelClock(unsigned *mode,unsigned *pixel_clock) // in Hz{ struct LRMI_regs r; int retval; memset(&r,0,sizeof(struct LRMI_regs)); r.eax = 0x4f0b; r.ebx = 0; r.edx = *mode; r.ecx = *pixel_clock; if(!VBE_LRMI_int(0x10,&r)) return VBE_VM86_FAIL; retval = r.eax & 0xffff; if(retval == 0x4f) { *pixel_clock = r.ecx; retval = VBE_OK; } return retval;}int vbeSaveState(void **data){ struct LRMI_regs r; int retval; void *rm_space; memset(&r,0,sizeof(struct LRMI_regs)); r.eax = 0x4f04; r.edx = 0x00; r.ecx = 0x0f; if(!VBE_LRMI_int(0x10,&r)) return VBE_VM86_FAIL; retval = r.eax & 0xffff; if(retval != 0x4f) return retval; if(!(rm_space = LRMI_alloc_real((r.ebx & 0xffff)*64))) return VBE_OUT_OF_DOS_MEM; r.eax = 0x4f04; r.edx = 0x01; r.ecx = 0x0f; r.es = VirtToPhysSeg(rm_space); r.ebx = VirtToPhysOff(rm_space); if(!VBE_LRMI_int(0x10,&r)) { LRMI_free_real(rm_space); return VBE_VM86_FAIL; } retval = r.eax & 0xffff; if(retval != 0x4f) { LRMI_free_real(rm_space); return retval; } *data = rm_space; return VBE_OK;}int vbeRestoreState(void *data){ struct LRMI_regs r; int retval; memset(&r,0,sizeof(struct LRMI_regs)); r.eax = 0x4f04; r.edx = 0x02; r.ecx = 0x0f; r.es = VirtToPhysSeg(data); r.ebx = VirtToPhysOff(data); retval = VBE_LRMI_int(0x10,&r); LRMI_free_real(data); if(!retval) return VBE_VM86_FAIL; retval = r.eax & 0xffff; if(retval == 0x4f) retval = VBE_OK; return retval;}int vbeGetWindow(unsigned *win_num){ struct LRMI_regs r; int retval; memset(&r,0,sizeof(struct LRMI_regs)); r.eax = 0x4f05; r.ebx = (*win_num & 0x0f) | 0x0100; if(!VBE_LRMI_int(0x10,&r)) return VBE_VM86_FAIL; retval = r.eax & 0xffff; if(retval == 0x4f) { *win_num = r.edx & 0xffff; retval = VBE_OK; } return retval;}int vbeSetWindow(unsigned win_num,unsigned win_gran){ int retval; if(vbe_pm_info.SetWindowCall) { /* Don't verbose this stuff from performance reasons */ /* 32-bit function call is much better of int 10h */ __asm __volatile( "pushl %%ebx\n" "movl %1, %%ebx\n" ::"a"(0x4f05),"S"(win_num & 0x0f),"d"(win_gran):"memory"); (*vbe_pm_info.SetWindowCall)(); __asm __volatile("popl %%ebx":::"memory"); retval = VBE_OK; } else { struct LRMI_regs r; memset(&r,0,sizeof(struct LRMI_regs)); r.eax = 0x4f05; r.ebx = win_num & 0x0f; r.edx = win_gran; if(!VBE_LRMI_int(0x10,&r)) return VBE_VM86_FAIL; retval = r.eax & 0xffff; if(retval == 0x4f) retval = VBE_OK; } return retval;}int vbeGetScanLineLength(unsigned *num_pixels,unsigned *num_bytes){ struct LRMI_regs r; int retval; memset(&r,0,sizeof(struct LRMI_regs)); r.eax = 0x4f06; r.ebx = 1; if(!VBE_LRMI_int(0x10,&r)) return VBE_VM86_FAIL; retval = r.eax & 0xffff; if(retval == 0x4f) { if(num_bytes) *num_bytes = r.ebx & 0xffff; if(num_pixels) *num_pixels= r.ecx & 0xffff; retval = VBE_OK; } return retval;}int vbeGetMaxScanLines(unsigned *num_pixels,unsigned *num_bytes, unsigned *num_lines){ struct LRMI_regs r; int retval; memset(&r,0,sizeof(struct LRMI_regs)); r.eax = 0x4f06; r.ebx = 3; if(!VBE_LRMI_int(0x10,&r)) return VBE_VM86_FAIL; retval = r.eax & 0xffff; if(retval == 0x4f) { if(num_bytes) *num_bytes = r.ebx & 0xffff; if(num_pixels) *num_pixels= r.ecx & 0xffff; if(num_lines) *num_lines = r.edx & 0xffff; retval = VBE_OK; } return retval;}int vbeSetScanLineLength(unsigned num_pixels){ int retval; struct LRMI_regs r; memset(&r,0,sizeof(struct LRMI_regs)); r.eax = 0x4f06; r.ebx = 0; r.ecx = num_pixels; if(!VBE_LRMI_int(0x10,&r)) return VBE_VM86_FAIL; retval = r.eax & 0xffff; if(retval == 0x4f) retval = VBE_OK; return retval;}int vbeSetScanLineLengthB(unsigned num_bytes){ int retval; struct LRMI_regs r; memset(&r,0,sizeof(struct LRMI_regs)); r.eax = 0x4f06; r.ebx = 2; r.ecx = num_bytes; if(!VBE_LRMI_int(0x10,&r)) return VBE_VM86_FAIL; retval = r.eax & 0xffff; if(retval == 0x4f) retval = VBE_OK; return retval;}int vbeGetDisplayStart(unsigned *pixel_num,unsigned *scan_line){ struct LRMI_regs r; int retval; memset(&r,0,sizeof(struct LRMI_regs)); r.eax = 0x4f07; r.ebx = 1; if(!VBE_LRMI_int(0x10,&r)) return VBE_VM86_FAIL; retval = r.eax & 0xffff; if(retval == 0x4f) { if(pixel_num) *pixel_num = r.ecx & 0xffff; if(scan_line) *scan_line = r.edx & 0xffff; retval = VBE_OK; } return retval;}int vbeSetDisplayStart(unsigned long offset, int vsync){ int retval; if(vbe_pm_info.SetDisplayStart) { /* Don't verbose this stuff from performance reasons */ /* 32-bit function call is much better of int 10h */ __asm __volatile( "pushl %%ebx\n" "movl %1, %%ebx\n" ::"a"(0x4f07),"S"(vsync ? 0x80 : 0), "c"((offset>>2) & 0xffff),"d"((offset>>18)&0xffff):"memory"); (*vbe_pm_info.SetDisplayStart)(); __asm __volatile("popl %%ebx":::"memory"); retval = VBE_OK; } else { struct LRMI_regs r; unsigned long pixel_num; memset(&r,0,sizeof(struct LRMI_regs)); pixel_num = offset%(unsigned long)curr_mode_info.BytesPerScanLine; if(pixel_num*(unsigned long)curr_mode_info.BytesPerScanLine!=offset) pixel_num++; r.eax = 0x4f07; r.ebx = vsync ? 0x82 : 2; r.ecx = pixel_num; r.edx = offset/(unsigned long)curr_mode_info.BytesPerScanLine; if(!VBE_LRMI_int(0x10,&r)) return VBE_VM86_FAIL; retval = r.eax & 0xffff; if(retval == 0x4f) retval = VBE_OK; else retval = VBE_BROKEN_BIOS; } return retval;}int vbeSetScheduledDisplayStart(unsigned long offset, int vsync){ int retval; struct LRMI_regs r; unsigned long pixel_num; memset(&r,0,sizeof(struct LRMI_regs)); pixel_num = offset%(unsigned long)curr_mode_info.BytesPerScanLine; if(pixel_num*(unsigned long)curr_mode_info.BytesPerScanLine!=offset) pixel_num++; r.eax = 0x4f07; r.ebx = vsync ? 0x82 : 2; r.ecx = offset; if(!VBE_LRMI_int(0x10,&r)) return VBE_VM86_FAIL; retval = r.eax & 0xffff; if(retval == 0x4f) retval = VBE_OK; return retval;}struct realVesaProtModeInterface{ unsigned short SetWindowCall; unsigned short SetDisplayStart; unsigned short SetPaletteData; unsigned short iopl_ports;}__attribute__((packed));int vbeGetProtModeInfo(struct VesaProtModeInterface *pm_info){ struct LRMI_regs r; int retval; unsigned info_offset; struct realVesaProtModeInterface *rm_info; memset(&r,0,sizeof(struct LRMI_regs)); r.eax = 0x4f0a; r.ebx = 0; if(!VBE_LRMI_int(0x10,&r)) return VBE_VM86_FAIL; retval = r.eax & 0xffff; if(retval == 0x4f) { retval = VBE_OK; info_offset = r.edi&0xffff; if((r.es >> 12) != hh_int_10_seg) retval = VBE_BROKEN_BIOS; rm_info = PhysToVirtSO(r.es,info_offset); pm_info->SetWindowCall = PhysToVirtSO(r.es,info_offset+rm_info->SetWindowCall); if(!is_addr_valid(pm_info->SetWindowCall)) retval = VBE_BROKEN_BIOS;#ifdef HAVE_VERBOSE_VAR if(verbose > 1) printf("vbelib: SetWindowCall=%04X:%04X => %p\n",r.es,info_offset+rm_info->SetWindowCall,pm_info->SetWindowCall);#endif pm_info->SetDisplayStart = PhysToVirtSO(r.es,info_offset+rm_info->SetDisplayStart); if(!is_addr_valid(pm_info->SetDisplayStart)) retval = VBE_BROKEN_BIOS;#ifdef HAVE_VERBOSE_VAR if(verbose > 1) printf("vbelib: SetDisplayStart=%04X:%04X => %p\n",r.es,info_offset+rm_info->SetDisplayStart,pm_info->SetDisplayStart);#endif pm_info->SetPaletteData = PhysToVirtSO(r.es,info_offset+rm_info->SetPaletteData); if(!is_addr_valid(pm_info->SetPaletteData)) retval = VBE_BROKEN_BIOS;#ifdef HAVE_VERBOSE_VAR if(verbose > 1) printf("vbelib: SetPaletteData=%04X:%04X => %p\n",r.es,info_offset+rm_info->SetPaletteData,pm_info->SetPaletteData);#endif pm_info->iopl_ports = PhysToVirtSO(r.es,info_offset+rm_info->iopl_ports); if(!rm_info->iopl_ports) pm_info->iopl_ports = NULL; else if(!check_wrd(pm_info->iopl_ports)) { pm_info->iopl_ports = NULL;/* retval = VBE_BROKEN_BIOS; <- It's for broken BIOSes only */ } #ifdef HAVE_VERBOSE_VAR if(verbose > 1) { printf("vbelib: iopl_ports=%04X:%04X => %p\n",r.es,info_offset+rm_info->iopl_ports,pm_info->iopl_ports); if(pm_info->iopl_ports) print_wrd(pm_info->iopl_ports); fflush(stdout); }#endif } return retval;}/* --------- Standard VGA stuff -------------- */int vbeWriteString(int x, int y, int attr, char *str){ struct LRMI_regs r; void *rm_space = NULL; int retval; memset(&r,0,sizeof(struct LRMI_regs)); r.ecx = strlen(str); r.edx = ((y<<8)&0xff00)|(x&0xff); r.ebx = attr; if(!(rm_space = LRMI_alloc_real(r.ecx))) return VBE_OUT_OF_DOS_MEM; r.es = VirtToPhysSeg(rm_space); r.ebp = VirtToPhysOff(rm_space); memcpy(rm_space,str,r.ecx); r.eax = 0x1300; retval = VBE_LRMI_int(0x10,&r); LRMI_free_real(rm_space); if(!retval) return VBE_VM86_FAIL; retval = r.eax & 0xffff; if(retval == 0x4f) retval = VBE_OK; return retval;}void * vbeMapVideoBuffer(unsigned long phys_addr,unsigned long size){ void *lfb; if(fd_mem == -1) return NULL; if(verbose > 1) printf("vbelib: vbeMapVideoBuffer(%08lX,%08lX)\n",phys_addr,size); /* Here we don't need with MAP_FIXED and prefered address (first argument) */ lfb = mmap((void *)0,size,PROT_READ | PROT_WRITE,MAP_SHARED,fd_mem,phys_addr); return lfb == (void *)-1 ? 0 : lfb;}void vbeUnmapVideoBuffer(unsigned long linear_addr,unsigned long size){ if(verbose > 1) printf("vbelib: vbeUnmapVideoBuffer(%08lX,%08lX)\n",linear_addr,size); munmap((void *)linear_addr,size);}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -