home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Virtual Reality Zone
/
VRZONE.ISO
/
mac
/
PC
/
REND386
/
VR386
/
PCXFILE.C
< prev
next >
Wrap
C/C++ Source or Header
|
1994-01-10
|
9KB
|
383 lines
/* Load or save a PCX file */
/* originally written by Bernie Roehl, April 1992 based on code by Dave Stampe */
// all screen dump code (in other modules) by Dave Stampe
// load_pcx and save_pcx redone by Dave Stampe, to support the new
// video driver functions so it'll work in ALL video modes. 24/12/93
// ditto for load_pcx, 29/12/93
/*
This code is part of the VR-386 project, created by Dave Stampe.
VR-386 is a desendent of REND386, created by Dave Stampe and
Bernie Roehl. Almost all the code has been rewritten by Dave
Stampre for VR-386.
Copyright (c) 1994 by Dave Stampe:
May be freely used to write software for release into the public domain
or for educational use; all commercial endeavours MUST contact Dave Stampe
(dstampe@psych.toronto.edu) for permission to incorporate any part of
this software or source code into their products! Usually there is no
charge for under 50-100 items for low-cost or shareware products, and terms
are reasonable. Any royalties are used for development, so equipment is
often acceptable payment.
ATTRIBUTION: If you use any part of this source code or the libraries
in your projects, you must give attribution to VR-386 and Dave Stampe,
and any other authors in your documentation, source code, and at startup
of your program. Let's keep the freeware ball rolling!
DEVELOPMENT: VR-386 is a effort to develop the process started by
REND386, improving programmer access by rewriting the code and supplying
a standard API. If you write improvements, add new functions rather
than rewriting current functions. This will make it possible to
include you improved code in the next API release. YOU can help advance
VR-386. Comments on the API are welcome.
CONTACT: dstampe@psych.toronto.edu
*/
#include <stdio.h>
#include <dos.h>
#include <alloc.h>
#include "f3dkitd.h" /* reset_hdwe(), read_screen_line */
#include "vr_api.h"
#include "pcdevice.h" /* left_page, right_page */
// PCX READ?WRITE COMPRESSED FORMATS
struct PCXHEADER{
unsigned char manu, hard, encod, bitpx;
unsigned int x1, y1, x2, y2;
unsigned int hres, vres;
unsigned char palette[48];
unsigned char vmode, nplanes;
unsigned int bytesPerLine;
char unused[128-68];
} ;
static int getbyte(int *c, int *count, FILE *in)
{
if (feof(in)) return EOF;
*c = getc(in) & 0xFF;
if ((*c & 0xC0) == 0xC0) {
*count = *c & 0x3F;
if (feof(in)) return EOF;
*c = getc(in) & 0xFF;
}
else
*count = 1;
return NULL;
}
static void putbyte(int c, int count, FILE *out)
{
if (count == 0)
return;
if (count > 1 || (c & 0xC0) == 0xC0)
putc(count | 0xC0, out);
putc(c, out);
}
// OLD VERSION, 320x200,256 ONLY: KEPT FOR OLD VIDEO DRIVERS
static unsigned char far *screen = MK_FP(0xA000, 0);
static void write_line(char far *buffer, char far *scr)
{
int i, plane;
char *add, *buff;
for (plane = 0; plane < 4; ++plane)
{
outport(0x3C4, (1<<(plane+8))+2);
add = scr;
buff = &buffer[plane];
for (i = 0; i < 80; ++i)
{
*add++ = *buff;
buff += 4;
}
}
}
static oldloadpcx(FILE *in, int page)
{
int c, count;
char buff[330];
char *buffer = &buff[0];
char *scr = &screen[16000*page];
unsigned nread = 0;
reset_hdwe();
fseek(in, 128L, SEEK_SET); /* skip PCX header */
while (getbyte(&c, &count, in) != EOF)
while (count--)
{
*buffer++ = c;
if (++nread == 320)
{
write_line(&buff[0],scr);
buffer = &buff[0];
nread = 0;
scr += 80;
}
}
return 0;
}
// NEW: USE VIDEO DRIVER FUNCTION (Dave Stampe)
load_pcx(FILE *in, int page)
{
int i,j;
int c, count;
int line = screeninfo->ymin;
unsigned nread = 0;
char *buff;
struct PCXHEADER hd;
set_drawpage(page); // which page to access
j = read_video_line(0,NULL); // number of pixels
if(j==FP_OFF(screeninfo)) // old driver? (stub test)
{
oldloadpcx(in, page);
return 0;
}
fread(&hd, 128, 1, in); // get header
j = hd.bytesPerLine;
buff = malloc(j); // get buffer
if(!buff) return -1;
memset(buff,0,j); // zero buffer
i = 0;
while (getbyte(&c, &count, in) != EOF)
while (count--)
{
buff[i++] = c;
if (j == i)
{
write_video_line(&buff[0],line++);
i = 0;
}
}
return 0;
}
// PCX header for write
struct PCXHEADER pccHeader = {
10, 5, 1, 8, 0, 0, 319, 199, 75, 75, // header
{ 0 }, // zeroed palette
0x13, 1, 320, 0 }; // rest
/* NEED A FUNCTION FOR THIS IN VIDEO DRIVER -- OLD CODE */
static char get_pixel(unsigned int adr, int page)
{
outport(0x3CE, ((adr&3)<<8)+4); /* select plane to read */
return *(char *)(MK_FP((0xA000+(1008*page)),adr>>2));
}
oldpcxsave(FILE *out, int page)
{
unsigned c, oldc, count;
unsigned nput = 1;
union REGS r;
reset_hdwe();
fwrite(&pccHeader, 128, 1, out);
count = 1;
oldc = get_pixel(0,page);
while ((nput>>2) < 16000)
{
c = get_pixel(nput++, page);
if (c != oldc)
{
putbyte(oldc, count, out);
oldc = c;
count = 1;
}
else if (++count >= 63)
{
putbyte(oldc, count, out);
count = 0;
}
}
putbyte(oldc, count, out);
putc(0x0C, out);
for (count = 0; count < 256; ++count)
{
r.x.ax = 0x1015;
r.x.bx = count; /* write pallete */
int86(0x10, &r, &r);
putc(r.h.dh<<2, out);
putc(r.h.ch<<2, out);
putc(r.h.cl<<2, out);
}
return 0;
}
// NEW: USE VIDEO DRIVER FUNCTION (Dave Stampe)
save_pcx(FILE *out, int page)
{
unsigned c, oldc, count;
union REGS r;
unsigned i,j,k;
char *buff;
set_drawpage(page); // which page to access
j = read_video_line(0,NULL); // number of pixels
if(j==FP_OFF(screeninfo)) // old driver?
{
oldpcxsave(out, page);
return 0;
}
buff = malloc(j); // get buffer
if(!buff) return -1;
pccHeader.x1 = screeninfo->xmin; // set PCX file size
pccHeader.y1 = screeninfo->ymin;
pccHeader.bytesPerLine = screeninfo->xmax - screeninfo->xmin+1;
pccHeader.y1 = screeninfo->ymin;
pccHeader.x2 = screeninfo->xmax;
pccHeader.y2 = screeninfo->ymax-1;
fwrite(&pccHeader, 128, 1, out);
// write out each line seperately
for(i=screeninfo->ymin;i<screeninfo->ymax;i++)
{
read_video_line(buff, i);
count = 1;
c = oldc = buff[0];
for(k=1;k<j;k++)
{
c = buff[k];
if (c != oldc)
{
putbyte(oldc, count, out);
oldc = c;
count = 1;
}
else if (++count >= 63)
{
putbyte(oldc, count, out);
count = 0;
}
}
putbyte(oldc, count, out);
}
free(buff);
putc(0x0C, out);
buff = malloc(screeninfo->colors*3);
if(buff==NULL)
for (count = 0; count <256; ++count) // default read;
{
r.x.ax = 0x1015;
r.x.bx = count; /* write pallete */
int86(0x10, &r, &r);
putc(r.h.dh<<2, out);
putc(r.h.ch<<2, out);
putc(r.h.cl<<2, out);
}
else
{
read_DAC_colors(buff,screeninfo->colors,0);
j = screeninfo->colors;
k = 0;
for (i = 0; i<j; i++)
{
putc(buff[k++]<<2, out);
putc(buff[k++]<<2, out);
putc(buff[k++]<<2, out);
}
for(;i<256;i++) // need to complete buffer
{
putc(0<<2, out);
putc(0<<2, out);
putc(0<<2, out);
}
}
free(buff);
return 0;
}
///////////// MONO/STEREO SCREEN DUMP
int screendump(void) /* alt-F10 */
{
char filename[30] = "scrn0000.pcx";
char far *buffer;
FILE *out;
int i;
for (i = 0; i < 30; i++) /* find a screendump number */
{
sprintf(filename,"scrn%c%d.pcx",
stereo_type==SWITCHED ? 'L' : '_' , i+1);
if ((out=fopen(filename,"rb"))==NULL) goto doit;
fclose(out);
}
return 3;
doit:
if(stereo_type!=SWITCHED)
{
if ((out = fopen(filename, "wb")) == NULL) return 3;
save_pcx(out, current_video_page);
fclose(out);
return 0;
}
else
{
filename[4] = 'L';
if ((out = fopen(filename, "wb")) == NULL) return 3;
save_pcx(out, left_page);
fclose(out);
filename[4] = 'R';
if ((out = fopen(filename, "wb")) == NULL) return 3;
save_pcx(out, right_page);
fclose(out);
return 0;
}
}