dxx-rebirth/unused/vga/framebuf.c
Bradley Bell 9bd1ba7c47 This commit was generated by cvs2svn to compensate for changes in r2,
which included commits to RCS files with non-trunk default branches.
2001-01-19 03:30:16 +00:00

335 lines
8.2 KiB
C

/*
THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO
END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS
AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED.
*/
char framebuf_rcsid[] = "$Id: framebuf.c,v 1.1.1.1 2001-01-19 03:30:15 bradleyb Exp $";
#include <dos.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <i86.h>
#include <dos.h>
#include "mono.h"
#include "fxdpmi.h"
#include "fxvesa.h"
#define DPMI_INTERRUPT 0x31
const VIDEO_INTERRUPT = 0x10;
typedef struct
{
short ModeAttributes; /* Mode attributes */
char WinAAttributes; /* Window A attributes */
char WinBAttributes; /* Window B attributes */
short WinGranularity; /* Window granularity in k */
short WinSize; /* Window size in k */
short WinASegment; /* Window A segment */
short WinBSegment; /* Window B segment */
void *WinFuncPtr; /* Pointer to window function */
short BytesPerScanLine; /* Bytes per scanline */
short XResolution; /* Horizontal resolution */
short YResolution; /* Vertical resolution */
char XCharSize; /* Character cell width */
char YCharSize; /* Character cell height */
char NumberOfPlanes; /* Number of memory planes */
char BitsPerPixel; /* Bits per pixel */
char NumberOfBanks; /* Number of CGA style banks */
char MemoryModel; /* Memory model type */
char BankSize; /* Size of CGA style banks */
char NumberOfImagePages; /* Number of images pages */
char res1; /* Reserved */
char RedMaskSize; /* Size of direct color red mask */
char RedFieldPosition; /* Bit posn of lsb of red mask */
char GreenMaskSize; /* Size of direct color green mask */
char GreenFieldPosition; /* Bit posn of lsb of green mask */
char BlueMaskSize; /* Size of direct color blue mask */
char BlueFieldPosition; /* Bit posn of lsb of blue mask */
char RsvdMaskSize; /* Size of direct color res mask */
char RsvdFieldPosition; /* Bit posn of lsb of res mask */
char DirectColorModeInfo; /* Direct color mode attributes */
FxU32 PhysBasePtr; /* Physical address of lfb */
FxU32 OffScreenMemOffset;
FxU32 OffScreenMemSize;
char res2[206]; /* Pad to 256 byte block size */
} ModeInfoBlock;
void VesaMain()
{
FxU16 mode = 0x111;
VesaErr_t error;
if ( ( error = VesaInit( mode ) ) != VESA_ERR_NONE )
{
printf( "VesaInit failed with error '%s'\n", VesaGetErrorString( error ) );
exit( 1 );
}
else
{
char *MyPtr;
MyPtr=(char *)VesaGetPtr();
memset( (MyPtr+((rand()%0x10000)<<4)+rand()%0x10000),rand()%256, 1 );
}
VesaEnd();
}
/*
** DpmiMapPhysicalToLinear
*/
FxU32 DpmiMapPhysicalToLinear( FxU32 paddr, FxU32 length )
{
FxU32 laddr;
union REGS r;
/*
** DPMI function 0x800
*/
r.w.ax = 0x800;
/*
** BX:CX = physical address
** SI:DI = length
*/
r.w.bx = ( FxU16 ) ( paddr >> 16 );
r.w.cx = ( FxU16 ) ( paddr & 0x0000FFFF );
r.w.si = ( FxU16 ) ( length >> 16 );
r.w.di = ( FxU16 ) ( length & 0x0000FFFF );
int386( DPMI_INTERRUPT, &r, &r );
/*
** if cflag set then an error occured
*/
if ( r.w.cflag )
{
laddr = 0;
}
else
{
laddr = r.w.bx;
laddr <<= 16;
laddr |= r.w.cx;
}
return laddr;
}
/*
** DpmiAllocDosMem
*/
void *DpmiAllocDosMem( FxU16 size, DpmiSelector_t *pSel )
{
union REGS r;
void *ptr;
FxU32 seg;
/*
** AX = DPMI function 0x100
*/
r.w.ax = 0x100;
/*
** BX = # of paragraphs to allocate
*/
r.w.bx = ( FxI16 ) ( size / 16 + 1 );
int386( DPMI_INTERRUPT, &r, &r );
if ( r.w.cflag )
{
ptr = 0;
}
else
{
seg = r.w.ax;
*pSel = r.w.dx;
ptr = ( void * ) ( seg << 4 );
}
return ptr;
}
/*
** DpmiFreeDosMem
*/
FxBool DpmiFreeDosMem( DpmiSelector_t sel )
{
union REGS r;
r.w.ax = 0x101;
r.w.bx = sel;
int386( DPMI_INTERRUPT, &r, &r );
if ( r.w.cflag )
return FXFALSE;
else
return FXTRUE;
}
DpmiRMI RMI;
ModeInfoBlock infoblock;
static void *vesa_lfb_ptr;
static void VesaGetModeInfo( int mode, ModeInfoBlock *infoblock )
{
union REGS r;
struct SREGS sr;
DpmiSelector_t infosel;
unsigned short infoseg;
ModeInfoBlock *far_infoblock;
/*
** Allocate some real-mode DOS memory using DPMI function 0x100
*/
far_infoblock = ( ModeInfoBlock * ) DpmiAllocDosMem( sizeof( ModeInfoBlock ), &infosel );
infoseg = ( unsigned short ) ( ( ( unsigned long ) far_infoblock ) >> 4 );
/*
** Get VESA SVGA info block by executing real-mode interrupt
** 0x10, function 0x4F01. This must be done using DPMI service
** 0x300 since DOS4GW doesn't automatically thunk pointers down
** for VESA functions.
*/
memset( &RMI, 0, sizeof( RMI ) );
RMI.EAX = 0x4F01; // Function 0x4F01
RMI.ECX = mode; //
RMI.ES = infoseg; // ES:DI -> pointer to real mode buffer
RMI.EDI = 0;
r.x.eax = 0x0300; // DPMI service "execute real mode interrupt"
r.x.ebx = VIDEO_INTERRUPT; // BL = function to execute
r.x.ecx = 0; // CX = 0
segread( &sr );
sr.es = FP_SEG( &RMI ); // ES:EDI -> buffer to RMI struct
r.x.edi = FP_OFF( &RMI );
#define DPMI_INTERRUPT 0x31
int386x( DPMI_INTERRUPT, &r, &r, &sr );
/*
** Copy realmode buffer into protected mode buffer
*/
memcpy( infoblock, far_infoblock, sizeof( ModeInfoBlock ) );
/*
** Free up the memory
*/
DpmiFreeDosMem( infosel );
}
int VesaGetRowSize (int mode)
{
ModeInfoBlock mi;
VesaGetModeInfo (mode,&mi);
return (mi.BytesPerScanLine);
}
extern int FindArg(char *);
/*
** VesaInit
**
** VESA initialization function. Returns a pointer to the
** linear frame buffer.
*/
int VesaInit( int mode )
{
union REGS r;
if (!FindArg ("-ForceVesa"))
return(0);
/*
** Get VESA mode information
*/
VesaGetModeInfo( mode, &infoblock );
/*
** Check mode information stuff
*/
if ( !( infoblock.ModeAttributes & 0x1 ) ||
!( infoblock.ModeAttributes & 0x80 ) )
{
mprintf ((0,"mode %x is not supported!\n",mode));
return 0;
}
/*
** Get a pointer to the linear frame buffer
*/
if ( ( vesa_lfb_ptr = ( void * ) DpmiMapPhysicalToLinear( infoblock.PhysBasePtr, 0x400000 - 1 ) ) == 0 )
{
mprintf ((0,"mode %x mapping not supported!\n",mode));
return 0;
}
/*
** Set the video mode
*/
r.w.ax = 0x4F02;
r.w.bx = ( short ) ( mode | 0x4000 );
int386( VIDEO_INTERRUPT, &r, &r );
if ( r.w.ax != 0x004F )
{
VesaEnd();
mprintf ((0,"mode %x not set!\n",mode));
return 0;
}
mprintf ((0,"No errors! mode %x is go!\n",mode));
return 1;
}
/*
** VesaEnd
*/
void VesaEnd( void )
{
union REGS r;
r.w.ax = 0x3;
int386( VIDEO_INTERRUPT, &r, &r );
}
/*
** VesaGetPtr
*/
void *VesaGetPtr( void )
{
return vesa_lfb_ptr;
}
static const char *vesa_errors[] =
{
"VESA_ERR_NONE",
"VESA_ERR_DPMI_MAPPING_FAILED",
"VESA_ERR_MODE_NOT_SUPPORTED",
"VESA_ERR_MODE_NOT_SET"
};
/*
** VesaGetErrorString
*/
const char *VesaGetErrorString( VesaErr_t err )
{
return vesa_errors[err];
}