/* ** BETATRON high level library for platform and action arcade games. ** Copyright (C) 1997 Liouros Thanasis, liouros@hotmail.com ** ** PLVESA.CC: This file is part of the BETATRON library and can be used ** and/or distributed only under the terms of the GNU Library ** General Public License. See doc/readme.1st for details. */ #include #include #include "vesacore.h" #include "defines.h" #include #include #include "plvesa.h" #include "modinf.h" static unsigned short vesaversion; // VESA version 2 BCD digits static char *vbeinfo=NULL; // VBE info static long vesamem; // Vesa mem in bytes static char *PMcode=NULL; // PMcode static Tvbefunctions table; // protected mode functions static char *savestatebuf=NULL; // VESA save state buffer static short statebufsize; // VESA save state buffer size static short initcount=0; // (times init successfully called) - (times done called) short pl_initvesa() { #define vesa_ret(val) {pl_donevesa(); return (val); } if (initcount) if (vesaversion < 0x0200) return ERR_VESANOTVER2; else { initcount++; return ERR_NOERR; } initcount++; if (! (vbeinfo= (char *) malloc(VBEINFOSIZE)) ) vesa_ret(ERR_OUTOFMEM); if (!pl_getVBEinfo(vbeinfo)) vesa_ret(ERR_VESACALL); vesaversion= getfield(vbeinfo, VBEVersion,unsigned short); if (vesaversion < 0x0200) vesa_ret(ERR_VESANOTVER2); vesamem= (long) getfield(vbeinfo, VBETotalMemory, short) * 65536L; if (!pl_getVBEprotectedcode(table,PMcode)) vesa_ret(ERR_VESACALL); #undef vesa_ret return ERR_NOERR; } void pl_donevesa() { if (!initcount) return; if (vbeinfo) { free(vbeinfo); vbeinfo=NULL; } if (PMcode) { free(PMcode); PMcode=NULL; } if (savestatebuf) { free(savestatebuf); savestatebuf=NULL; } initcount--; } short pl_ismodevalid(char *modeinfo,unsigned short mode) { short attrs; long xres,yres,xlen,ylen; char *res; if ( !pl_getVBEmodeinfo(modeinfo, mode)) return ERR_VESACALL; attrs=getfield(modeinfo, VBEModeAttributes,short); if ( (attrs & 1) // supported && (attrs & (1<<4)) // graphics mode && (attrs & (1<<7)) // linear frame buffer && (modeinfo[VBEMemoryModel] == 4) // memory packed && (modeinfo[VBEBitsPerPixel]== 8) // 256 colors && (modeinfo[VBENumberOfPlanes]==1) // 1 memory plane ) { xres= getfield(modeinfo,VBEXResolution,unsigned short); yres= getfield(modeinfo,VBEYResolution,unsigned short); if (xres & 0xf) xlen= (xres & 0xfff0) + 16 + 32; else xlen=xres+32; if (yres & 0xf) ylen= (yres & 0xfff0) + 16 + 32; else ylen=yres+32; // Iparxei arketi mnimi gia 3 selides if ( (xres <= XRESLIMIT) && (yres <= YRESLIMIT) ) if ( xlen*ylen*3 <= vesamem ) return ERR_NOERR; } return ERR_VESANOTVALIDMODE; } struct Tplvesamode { unsigned short modeno; unsigned short Xres,Yres; Tplvesamode *next; }; short pl_getvesamodes(Tplmode *&listofmodes) { long ofs; unsigned short s,o,i; short mode; short res=ERR_NOERR; unsigned short attrs; Tplvesamode *l; char *modeinfo; Tplvesamode *modelist=NULL; short howmany; if (!vbeinfo) return ERR_VESANOTINIT; if (! (modeinfo= (char *) malloc(VBEMODEINFOSIZE))) return ERR_OUTOFMEM; // to VideoModePtr einai deiktis se perioxi tou dos o=getfield(vbeinfo,VBEVideoModePtr,unsigned short); s=getfield(vbeinfo,VBEVideoModePtr+2,unsigned short); ofs = (long)s*16 + o; #define vesa_ret(val) { \ Tplvesamode *p,*pnew; \ free(modeinfo); \ for (p=modelist;p;) { pnew=p->next; free(p); p=pnew;} \ return val; \ } howmany=0; mode=_farpeekw(_dos_ds,ofs); for (;mode!=-1;ofs+=2, mode=_farpeekw(_dos_ds,ofs)) { // elegkse an to mode exei ta xaraktisristika pou theloume if (pl_ismodevalid(modeinfo,mode)) continue; if (! (l=(Tplvesamode *) malloc(sizeof(Tplvesamode))) ) vesa_ret(ERR_OUTOFMEM); l->modeno=mode; l->Xres= getfield(modeinfo,VBEXResolution,unsigned short); l->Yres= getfield(modeinfo,VBEYResolution,unsigned short); l->next= modelist; modelist = l; howmany++; } //for if (howmany) if ( !(listofmodes = (Tplmode *)malloc(howmany*sizeof(Tplmode))) ) vesa_ret(ERR_OUTOFMEM); for (i=0,l=modelist;inext) { listofmodes[i].modeno=l->modeno; listofmodes[i].Xres=l->Xres; listofmodes[i].Yres=l->Yres; } vesa_ret(howmany); } short pl_saveVESAstate() { if (savestatebuf) { free(savestatebuf); savestatebuf=NULL; } return pl_saverestoreVBEstate(1,savestatebuf,statebufsize); } short pl_restoreVESAstate() { if (!savestatebuf) return 0; return pl_saverestoreVBEstate(2,savestatebuf,statebufsize); } void pl_VESAsetstartadr(long addr) { unsigned short hiword= addr >> 16; unsigned short loword= addr & 65535; if (!PMcode) return; asm("movb $0x01,%%bl; call *%2" : : "dx" (hiword) , "cx" (loword), "m" (table[1]) : "eax","ebx","ecx","edx","edi", "memory", "cc" ); }