335 lines
8.2 KiB
C
Executable file
335 lines
8.2 KiB
C
Executable file
/*
|
|
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 2006/03/17 20:00:07 zicodxx 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];
|
|
}
|
|
|