home *** CD-ROM | disk | FTP | other *** search
- // Gscreen.cpp
-
- #ifndef gscreen_cpp
- #define gscreen_cpp
-
- #ifdef Gscreen_test
- #include "Gscreen.hpp"
- #else
- #include <Gscreen.hpp>
- #endif
-
- void BitMap::erase (void) {
- int scrx=screnx;
- int scry=screny;
-
- int hline=maxx; // set from Gscreen's maxx
- unsigned int offscr=(unsigned int)scrx+
- ((unsigned int)scry*(unsigned int)hline);
-
- int d_blockx=blockx;
- int d_blocky=blocky;
- int d_totalx=totalx;
-
- wait_for_vbl();
- asm {
- push bx
- push cx
- push dx
- push ds
- mov dx,d_blocky // vertical count
- push 0a000h // video memory segment
- pop es
- mov bx,offscr // bx to upper left of block
- }
- row:
- asm {
- mov cx,d_blockx // horizontal count
- }
- col:
- asm {
- mov byte ptr es:[bx],0 // clear pixel
- inc bx
- loop col
- dec dx
- cmp dx,0
- jz cleanup
- add bx,hline // next row
- sub bx,d_blockx // screen back to start x
- loop row
- }
- cleanup:
- asm {
- pop ds
- pop dx
- pop cx
- pop bx
- }
-
-
- }
-
- void BitMap::display (int scrx, int scry, int cntx, int cnty) {
-
- screnx=scrx;
- screny=scry;
-
- int offbmp=FP_OFF(image_ptr)+(cntx*blockx)+(cnty*totalx*blocky);
- int segbmp=FP_SEG(image_ptr);
-
- int d_blockx=blockx;
- int d_blocky=blocky;
- int d_totalx=totalx;
-
- int hline=maxx; // set from Gscreen's maxx
- int offscr=scrx+(scry*hline);
-
- wait_for_vbl();
- asm {
- push ax
- push bx
- push cx
- push dx
- push ds
- mov dx,d_blocky // vertical count
- push 0a000h // video memory segment
- pop es
- mov di,offscr // di to upper left of screen
- push segbmp // bitmap memory segment
- pop ds
- mov si,offbmp // si to upper left of bitmap
- cld // clear direction flag
- }
- row:
- asm {
- mov cx,d_blockx // horizontal count
- rep movsb // write pixel row
- dec dx
- cmp dx,0
- jz cleanup
- add di,hline // next row
- sub di,d_blockx // screen back to start x
- add si,d_totalx // bmp back to next row
- sub si,d_blockx // bmp back to start x
- loop row
- }
- cleanup:
- asm {
- pop ds
- pop dx
- pop cx
- pop bx
- pop ax
- }
-
- }
-
- Gscreen::Gscreen (int md, int mx, int my) {
- maxx=(mx>0) ? mx : 320; // default to 13h
- maxy=(my>0) ? my : 200;
- mode=(md>0) ? md : 0x13;
-
- setmode (mode);
- }
-
- Gscreen::~Gscreen (void) {
- setmode (3);
- }
-
- void Gscreen::setmode(int mode)
- {
- union REGS inregs, outregs;
- struct SREGS segregs;
-
- inregs.h.ah = 0x00;
- inregs.h.al = mode;
- int86x(0x10, &inregs, &outregs, &segregs);
- }
-
-
- // *************************************************************************
- // UnpackPcx() unpacks the RLE encoded PCX data from a file if pcx != NULL,
- // or the source buffer if pcx==NULL, to the Dest buffer. Unpacks NumBytes
- // bytes of decompressed data. (max 64000) This is a pretty dumb routine.
- // It's fast, but it expects you to know the uncompressed size of the data
- // (the NumBytes parameter), and you have to do all of the file and buffer
- // set-up elsewhere. Basically it's a core decoding engine.
- // *************************************************************************
-
-
- const char far *Gscreen::unpackpcx(char *name) {
-
- FILE* pcx;
-
- unsigned int bytes=0; // counts unpacked bytes
- unsigned char c; // byte being processed
- unsigned int runlen; // length of packet
- unsigned int num_bytes;
-
- if ((pcx=fopen (name,"rb"))==NULL) {
- return NULL;
- }
-
- pcxh = new pcx_hdr;
- fread(pcxh, sizeof (pcx_hdr), 1, pcx);
-
- num_bytes = (pcxh->Xmax+1)*(pcxh->Ymax+1);
- image_ptr= new char[num_bytes+1];
- if (image_ptr==NULL) return NULL; // can't alloc mem
-
- do {
- // get a key byte from the file
- c=fgetc(pcx);
-
- // check if it's a packet ( yes if two high bits set )
- if ((c & 0xc0) == 0xc0) {
- // AND off the high bits
- runlen = (c & 0x3f);
- // get the next byte in the file
- c=fgetc(pcx);
- // repeat it runlen times
- while(runlen--) (image_ptr[bytes++]=c);
- }
- else
- // if not a packet just store the byte
- image_ptr[bytes++]=c;
- } while (bytes<num_bytes);
- for (int i=0; i<(3*256); i++) colregs[i]=(getc(pcx) >> 2);
- // setpalette();
- return image_ptr;
- }
-
- void Gscreen::display () {
-
- int offbmp=FP_OFF(image_ptr);
- int segbmp=FP_SEG(image_ptr);
-
- int wd=pcxh->Xmax+1;
- int hi=pcxh->Ymax+1;
- int block=maxx;
-
- wait_for_vbl();
- asm {
- push ax
- push bx
- push cx
- push dx
- push ds
- mov dx,hi // vertical count
- push 0a000h // video memory segment
- pop es
- mov di,0 // di to upper left of screen
- push segbmp // bitmap memory segment
- pop ds
- mov si,offbmp // si to upper left of bitmap
- cld // clear direction flag
- }
- row:
- asm {
- mov cx,wd // horizontal count
- rep movsb // write pixel row
- dec dx
- cmp dx,0
- jz cleanup
- add di,block // next row
- sub di,wd // back to start x
- loop row
- }
- cleanup:
- asm {
- pop ds
- pop dx
- pop cx
- pop bx
- pop ax
- }
- }
-
- void Gscreen::setpalette(void) {
- int offcol,segcol;
-
- offcol=FP_OFF(colregs);
- segcol=FP_SEG(colregs);
- asm{
- mov dx,es
- push dx
- mov dx,segcol
- mov es,dx
- mov ah,10h
- mov al,12h
- mov bx,0
- mov cx,100h
- mov dx,offcol
- int 10h
- pop dx
- mov es,dx
- }
- }
-
-
- void Gscreen::wait_for_vbl(void)
- {
- while ((inport(0x3da)&8)==0);
- }
-
- void BitMap::wait_for_vbl(void)
- {
- while ((inport(0x3da)&8)==0);
- }
-
-
- #endif
-