PCX.C 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  1. /*
  2. THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
  3. SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO
  4. END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
  5. ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
  6. IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
  7. SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
  8. FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
  9. CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS
  10. AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
  11. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED.
  12. */
  13. //========================================================
  14. // Views a PCX file
  15. // This is a 16-bit program.
  16. // Compiles using Turbo C.
  17. // All self-contained in this one module.
  18. // Uses 320x200 or 320x400 ModeX.
  19. //========================================================
  20. #include <stdlib.h>
  21. #include <stdio.h>
  22. #include <conio.h>
  23. #include <bios.h>
  24. #include <dir.h>
  25. #include <dos.h>
  26. typedef unsigned long dword;
  27. typedef unsigned short word;
  28. typedef unsigned char ubyte;
  29. #ifndef MK_FP
  30. #define MK_FP(seg,off) ((void far *)(((dword)(seg)<<16)+(dword)(off)))
  31. #endif
  32. ubyte far * video_ram;
  33. /* PCX Header data type */
  34. typedef struct pcx_header {
  35. ubyte Manufacturer;
  36. ubyte Version;
  37. ubyte Encoding;
  38. ubyte BitsPerPixel;
  39. short Xmin;
  40. short Ymin;
  41. short Xmax;
  42. short Ymax;
  43. short Hdpi;
  44. short Vdpi;
  45. ubyte ColorMap[16][3];
  46. ubyte Reserved;
  47. ubyte Nplanes;
  48. short BytesPerLine;
  49. ubyte filler[60];
  50. } pcx_header;
  51. #define PCX_COUNT_FLAG 0xC0
  52. #define PCX_ERROR_NONE 0
  53. #define PCX_ERROR_OPENING 1
  54. #define PCX_ERROR_NO_HEADER 2
  55. #define PCX_ERROR_WRONG_VERSION 3
  56. #define PCX_ERROR_READING 4
  57. #define PCX_ERROR_NO_PALETTE 5
  58. #define PCX_TOO_LARGE 6
  59. void set_cellheight( ubyte height )
  60. {
  61. unsigned char temp;
  62. outportb( 0x3d4, 9 );
  63. temp = inportb( 0x3d5 );
  64. temp &= 0xE0;
  65. temp |= height;
  66. outportb( 0x3d5, temp );
  67. }
  68. void clear_palette()
  69. {
  70. int i;
  71. outportb( 0x3c8, 0 );
  72. for (i=0; i<768; i++ )
  73. outportb( 0x3c9, 0 );
  74. }
  75. int modex_vres = 0;
  76. int modex_drawing_start = 0;
  77. void set_drawing_page(int page)
  78. {
  79. if (page)
  80. modex_drawing_start = modex_vres; // Page 1
  81. else
  82. modex_drawing_start = 0; // Page 0
  83. }
  84. void set_viewing_page(int page)
  85. {
  86. int hi, lo;
  87. int offset;
  88. if (page)
  89. offset = modex_vres*80;
  90. else
  91. offset = 0;
  92. hi = offset>>8;
  93. lo = offset&0xff;
  94. hi = (hi<<8) | 0xC;
  95. lo = (lo<<8) | 0xD;
  96. disable();
  97. while( inportb(0x3DA) & 0x1 ) // Wait for display enable
  98. ;
  99. outport( 0x3d4, hi ); // Set Start address high bits
  100. outport( 0x3d4, lo ); // Set Start address lo bits
  101. enable();
  102. while( !(inportb(0x3DA) & 0x8) ) // Wait for not vertical retrace
  103. ;
  104. }
  105. void set_video_mode(int mode, int use_400_lines )
  106. {
  107. union REGS regs;
  108. regs.x.ax = mode;
  109. int86( 0x10, &regs, &regs );
  110. if ( mode == 0x13 ) {
  111. clear_palette();
  112. // Set ModeX
  113. outport( 0x3c4, 0x0604 ); // disable chain4 mode
  114. outport( 0x3d4, 0x0014 ); // turn on dword mode
  115. outport( 0x3d4, 0xe317 ); // turn off byte mode
  116. modex_drawing_start = 0; // Draw to page 0
  117. if ( use_400_lines ) {
  118. modex_vres = 400;
  119. set_cellheight(0); // Set 400 line mode
  120. } else {
  121. modex_vres = 200;
  122. }
  123. set_drawing_page(0); // Draw to page 0
  124. }
  125. }
  126. void set_pixel(int x, int y, ubyte color )
  127. {
  128. unsigned int address;
  129. // Select write plane
  130. outport( 0x3c4, (0x100<<(x&3))|2 );
  131. address = (y+modex_drawing_start)*80;
  132. address += x/4;
  133. video_ram[address] = color;
  134. }
  135. void set_palette(ubyte * palette)
  136. {
  137. int i;
  138. outportb( 0x3c8, 0 );
  139. for (i=0; i<768; i++ )
  140. outportb( 0x3c9, *palette++ );
  141. }
  142. int read_pcx_file( char * filename, ubyte * palette )
  143. {
  144. FILE * PCXfile;
  145. pcx_header header;
  146. int i, row, col, count, xsize, ysize;
  147. ubyte data;
  148. PCXfile = fopen( filename , "rb" );
  149. if ( !PCXfile )
  150. return PCX_ERROR_OPENING;
  151. // read 128 char PCX header
  152. if (fread( &header, sizeof(pcx_header), 1, PCXfile )!=1) {
  153. fclose( PCXfile );
  154. return PCX_ERROR_NO_HEADER;
  155. }
  156. // Is it a 256 color PCX file?
  157. if ((header.Manufacturer != 10)||(header.Encoding != 1)||(header.Nplanes != 1)||(header.BitsPerPixel != 8)||(header.Version != 5)) {
  158. fclose( PCXfile );
  159. return PCX_ERROR_WRONG_VERSION;
  160. }
  161. // Find the size of the image
  162. xsize = header.Xmax - header.Xmin + 1;
  163. ysize = header.Ymax - header.Ymin + 1;
  164. if ( (xsize > 320) || (ysize > 400) ) {
  165. fclose( PCXfile );
  166. return PCX_TOO_LARGE;
  167. }
  168. if ( ysize > 200 )
  169. set_video_mode( 0x13, 1 ); // 320x200, 256 color
  170. else
  171. set_video_mode( 0x13, 0 ); // 320x200, 256 color
  172. set_drawing_page(1); // Draw to page 1
  173. for (row=0; row< ysize ; row++) {
  174. for (col=0; col< xsize ; ) {
  175. if (fread( &data, 1, 1, PCXfile )!=1 ) {
  176. fclose( PCXfile );
  177. return PCX_ERROR_READING;
  178. }
  179. if ((data & PCX_COUNT_FLAG) == PCX_COUNT_FLAG) {
  180. count = data & (~PCX_COUNT_FLAG);
  181. if (fread( &data, 1, 1, PCXfile )!=1 ) {
  182. fclose( PCXfile );
  183. return PCX_ERROR_READING;
  184. }
  185. for (i=0;i<count;i++)
  186. set_pixel( col++, row, data );
  187. } else {
  188. set_pixel( col++, row, data );
  189. }
  190. }
  191. }
  192. // Read the extended palette at the end of PCX file
  193. // Read in a character which should be 12 to be extended palette file
  194. if (fread( &data, 1, 1, PCXfile )==1) {
  195. if ( data == 12 ) {
  196. if (fread(palette,768, 1, PCXfile)!=1) {
  197. fclose( PCXfile );
  198. return PCX_ERROR_READING;
  199. }
  200. for (i=0; i<768; i++ ) {
  201. palette[i] /= 4;
  202. }
  203. }
  204. } else {
  205. fclose( PCXfile );
  206. return PCX_ERROR_NO_PALETTE;
  207. }
  208. fclose(PCXfile);
  209. return PCX_ERROR_NONE;
  210. }
  211. int main( int argc, char * argv[] )
  212. {
  213. struct ffblk ffblk;
  214. ubyte palette[768];
  215. int pcx_error, done;
  216. if ( argc < 2 ) {
  217. printf( "You must specify a pcx file to view!\n" );
  218. exit(1);
  219. }
  220. video_ram = MK_FP( 0xA000, 0 );
  221. done = findfirst( argv[1], &ffblk, 0 );
  222. while (!done) {
  223. pcx_error = read_pcx_file( ffblk.ff_name, palette );
  224. if ( pcx_error == PCX_ERROR_NONE ) {
  225. set_palette(palette);
  226. set_viewing_page(1); // Show the completed page 1.
  227. getch();
  228. } else {
  229. set_video_mode( 0x3, 0 );
  230. if ( pcx_error != PCX_ERROR_NONE )
  231. printf( "Error %d reading '%s'\n", pcx_error, ffblk.ff_name );
  232. return pcx_error;
  233. }
  234. done = findnext( &ffblk );
  235. }
  236. set_video_mode( 0x3, 0 );
  237. return 0;
  238. }
  239.