//*******************PROGRAM NA ZOBRAZOVANI PCX SOUBORU
//********************PRO VYHEN NAPSAL HIPP 1996********
#include <dos.h>
#include <io.h>
#include <conio.h>
#include <stdio.h>
#include <mem.h>
//delka palety
#define PL 768
//velikost bufferu
#define BufL 1000
//delk pauzy
#define DEL 10
#define byte unsigned char
typedef struct{char man,ver,enc,bpp;
               int xmin,ymin,xmax,ymax,hdpi,vdpi;
               char colmap[48];
               char res,nplan;
               int bpl,pinfo,hss,vss;} pcxhead;
 char buf[BufL];
 int bh=BufL;
//inicialisuje graficky mod m
void grinit(char m){
 asm{
   mov ah,0
   mov al,m
   int 10h
 }
}
//ceka na navrat paprsku
void wairet(){
 while (((inportb(0x3DA)) & 8));
 while (!((inportb(0x3DA)) & 8));
}
//nastavuje paletu
void setpal(char p[PL]){
int c;
wairet();
outportb(0x3c8,0);
for (c=0;c<768;c++) outportb(0x3c9,p[c]);
}

//cte paletu
char palread(int f,byte * p){
 int c;
 lseek(f,-PL,2);
 if (read(f,p,PL)!=PL) return 0;
 //paleta je ulozena 0-255 jde zobrazit jen 0-64 proto delime ctyrma
 for (c=0;c<PL;c++) *(p+c)/=4;
 return 1;
}
//cte mod obrazovky
char readmod(){
 char m;
  asm{
   int 15
   mov m,al
 }
 return m;
}
//cte znak z bufferu
//buffer je pouuzit pro rychlejsi beh programu
//je to prasarna, ale jsem linej to udelat lip
byte readz(int f){
byte ch;
 if (bh==BufL){bh=_read(f,&buf[0],BufL);
               bh=0;}
  ch=buf[bh++];
  return ch;
}

//cte hlavicku
void headread(int f,pcxhead * hdr){
 lseek(f,0,SEEK_SET);
 read(f,(char*)hdr,75);
}
//nuluje paletu
void nulpal(char * p){
  setmem(p,PL,0);
}
// cte pcx file
void pcxread(byte far * p,int f,pcxhead h){
byte ch,cou,c;
unsigned int s=0,len;//s=posice v obraze, len delka obrazove informace
unsigned int l=0,del;//del=misto mezi koncem obrazu a krajem monitoru
lseek(f,128,0);
//delka obraz informace
len=(unsigned int )h.bpl*h.nplan*(1+h.ymax-h.ymin);
//delka mezery za obrazkem
del=(unsigned int) 320-h.xmax;
while ((ch!=EOF) && (s<len)){//nacita dokud neni konec nebo chyba
   if (l==0) _fsetmem(p,h.xmin,0);//levy okraj
   if (l>=h.xmax) _fsetmem(p,del,0);//pravy okraj
   ch=readz(f);//cte znak
   cou=1;
   if (0xc0==(0xc0 & ch)){//testuje vyhodnocuje (viz. clanek)
       cou=0x3f & ch;
       ch=readz(f);
   }
     _fsetmem(p+s,cou,ch);//zapisuje
     s+=cou;
     l+=cou;

 }
}

//zesvetluje(ztmavuje) paletu
int changpal(byte * p,byte p2[PL],int ch){
int c,q=0,e;
 for (c=0;c<768;c++){
   e=*(p+c)+ch;
   if ((e>=0) && (e<=p2[c])) {*(p+c)=e;
      q++;
   }
 }
 return q;
}

//je pcx ?
char ispcx(pcxhead h){
  if ((h.man==10) && (h.enc==1) && (h.xmax<320) && (h.ymax<200)) return 1;
  else return 0;
}
//************************ M A I N **************************
char main(int argc,char ** arg){
 int f;              //obrazovy soubor
 pcxhead h;          //hlavicka
 byte p1[PL],p2[PL]; //informace o palete
 char mod;           //puvodni mod obrazu
 printf("Program na zobrazovani PCX souboru (HIPP 1996)\n");
 if (argc<2) { //malo parametru
    printf("Pouziti : pcx.exe soubor.pcx\n");
    return -1;
 }
 if ((f=open(arg[1],0))==-1){
    fprintf(stderr,"Soubor %s nenalezen\n",arg[1]);
    return -1;
 }
 headread(f,&h); //cte hlavicku
 if (!ispcx(h)) {
    fprintf(stderr,"Soubor %s neni v podporovanem formatu\n",arg[1]);
    return -1;
 }
 if (!palread(f,&p1[0])){
    fprintf(stderr,"Nepodarilo se nacist paletu");
    return -1;
 }
 mod=readmod();//nacita mod obrazovky
 grinit(0x13);//inicialisuje mod 320x200
 nulpal(&p2[0]);//nuluje paletu
 setpal(p2);
 pcxread((char far *)MK_FP(0xA000,0),f,h);//nacita obraz
 //zesvetluje paletu
 while (changpal(&p2[0],p1,1)){
      delay(DEL);
      setpal(p2);
 }
 getch();
 //ztmavuje paletu
 while (changpal(&p1[0],p1,-1)){
      delay(DEL);
      setpal(p1);
 }
 grinit(mod);
}
      


            výheň