home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD2.mdf / c / library / dos / grafik / cbgi111 / src / tecmar / tecmar.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-07-11  |  36.0 KB  |  1,129 lines

  1. /*************************** TECMAR DRIVER ******************************/
  2. /*    Tecmar Graphics Master BGI driver.  This program acts as a BGI    */
  3. /*  for the Tecmar Graphics Master (TGM) in the 640x400x16 mode.  This    */
  4. /*  only works for a TGM configured to be a colour output device mapped    */
  5. /*  at segment 0xA000 and using ONLY that segment.  It's a rather    */
  6. /*  unusual arrangement even for the TGM but it allows it to coexist    */
  7. /*  with other adapters (such as a Hercules), in a dual moniter system.    */
  8. /*  In this configuration the memory is mapped as follows.  Two pixels     */
  9. /*  per byte high order byte holds first pixel and 320 consecutive     */
  10. /*  bytes form a line.  The lines are arranged in two banks of two     */
  11. /*  'paragraphs' each.  Only one bank is accesible at a time.        */
  12. /*                                    */
  13. /*    Offset        Bank 0            Bank 1            */
  14. /*                                    */
  15. /*         +-----------------------+-----------------------+    */
  16. /*      0    |  line 0        |  line 2        |    */
  17. /*        |            |            |    */
  18. /*                                    */
  19. /*        |            |            |    */
  20. /*        +-----------------------+-----------------------+    */
  21. /*     0x8000    |  line 1        |  line 3        |    */
  22. /*        |            |            |    */
  23. /*                                    */
  24. /*        |            |            |    */
  25. /*        +-----------------------+-----------------------+    */
  26. /*                                    */
  27. /*     V 0.90    26/07/89  Robert Adsett Original.            */
  28. /*     V 1.00    18/05/90  Robert Adsett Release version.        */
  29. /*     V 1.10    30/06/90  Robert Adsett Add copyright.  Editorial    */
  30. /*                    changes.            */
  31. /*     V 1.11    02/07/90  Robert Adsett Add explicit casts to address    */
  32. /*                    macros.              */
  33. /*    V 1.12    05/07/90  Robert Adsett Use a dummy copy of the current */
  34. /*                    screen address to overcome a    */
  35. /*                    TC++ bug.            */
  36. /*    V 1.13    11/07/90  Robert Adsett Was copying one too many rows    */
  37. /*                    in save/restore bitmap.        */
  38. /*                                    */
  39. /*  LIMITATIONS:                            */
  40. /*    Block operations are slow.  They could be speeded up         */
  41. /*   considerably by recoding them in assembly language.          */
  42. /*    Flood fill is unimplemented at present.                */
  43. /*    Palette setting operations are null functions.  The colours    */
  44. /*   on the TGM are hardwired and unchangeable.                */
  45. /*    Error checking & reporting are almost non-existant.        */
  46. /*    Everything that can be emulated is.  This seems to be         */
  47. /*   reasonably fast so changing this is not a high priority.        */
  48. /*                                    */
  49. /*  KNOWN BUGS:                                */
  50. /*    Line width is currently ignored.  This seems to be taken care    */
  51. /*   of by the kernal but should be changed.                */
  52. /************************************************************************/
  53.  
  54. #include <stdlib.h>
  55. #include <string.h>
  56. #include "bgi.h"
  57. #include "tecmar.h"
  58.  
  59. /*    Generic driver global variables.  Should be present in almost    */
  60. /*  every driver.                            */
  61.  
  62. const CHAR_TABLE_ENTRY far * const char_def = 
  63.             (CHAR_TABLE_ENTRY far *)MK_FP( 0xf000, 0xfa6e);
  64.                 /* Pointer to character definition    */
  65.                 /*  table in ROM.            */
  66.  
  67.                 /* Fill pattern definitions.        */
  68. const FILLPATTERN def_patterns[12] = {
  69.         { 0, 0, 0, 0, 0, 0, 0, 0 },     /* No Fill.        */
  70.         { 0xff, 0xff, 0xff, 0xff, 
  71.           0xff, 0xff, 0xff, 0xff },    /* Solid Fill.        */
  72.         { 0xff, 0xff, 0, 0, 0xff, 
  73.           0xff, 0, 0},            /* Line Fill.        */
  74.         { 1, 2, 4, 8, 0x10, 0x20,
  75.           0x40, 0x80},            /* Lt Slash fill.    */
  76.         { 0xE0, 0xC1, 0x83, 0x07, 
  77.           0x0E, 0x1C, 0x38, 0x70 },    /* Slash Fill.        */
  78.         { 0xF0, 0x78, 0x3C, 0x1E, 
  79.           0x0F, 0x87, 0xC3, 0xE1 },    /* Backslash Fill.    */
  80.         { 0xA5, 0xD2, 0x69, 0xB4, 
  81.           0x5A, 0x2D, 0x96, 0x4B },    /* Lt Backslash Fill.    */
  82.         { 0xFF, 0x88, 0x88, 0x88, 
  83.           0xFF, 0x88, 0x88, 0x88 },    /* Hatch Fill.        */
  84.         { 0x81, 0x42, 0x24, 0x18, 
  85.           0x18, 0x24, 0x42, 0x81 },    /* XHatch Fill.        */
  86.         { 0xCC, 0x33, 0xCC, 0x33, 
  87.           0xCC, 0x33, 0xCC, 0x33 },    /* Interleave Fill.    */
  88.         { 0x80, 0x00, 0x08, 0x00, 
  89.           0x80, 0x00, 0x08, 0x00 },     /* Wide Dot Fill.    */
  90.         { 0x88, 0x00, 0x22, 0x00, 
  91.           0x88, 0x00, 0x22, 0x00 }    /* Close Dot Fill.    */
  92.            };
  93. /*                                    */
  94. /*    The following structure defines the Bit Manipulation Utility    */
  95. /*    function table.                            */
  96. /*                                    */
  97.  
  98. const UTILITIES Utility_Table = {    /* Bit Utilities Function Table */
  99.   (NRFPTR) dispatch_enter_graphics,    /* Enter graphics mode function */
  100.   (NRFPTR) dispatch_leave_graphics,    /* Leave graphics mode function */
  101.   (NRFPTR) dispatch_putpix,        /* Write a pixel function    */
  102.   (NRFPTR) dispatch_getpix,        /* Read a pixel function    */
  103.   (NRFPTR) dispatch_bits_per_pixel,    /* Bits per pixel value        */
  104.   (NRFPTR) dispatch_set_page,        /* Set the active drawing page    */
  105.   (NRFPTR) dispatch_set_visual,        /* Set the active display page    */
  106.   (NRFPTR) dispatch_set_write_mode    /* Set the current write mode    */
  107.   };
  108.  
  109. int MAXY = 399, MAXX = 640, MINY = 0,     /* Clipping limits.        */
  110.     MINX = 0;
  111. unsigned int current_line_style = 0xffff;    /* Current line drawing    */
  112.                         /*  style.        */
  113. int current_write_mode = COPY;        /* Current drawing mode.    */
  114. int current_line_width = 1;        /* Current line width.        */
  115. unsigned char current_colour = 0xff,     /* Current drawing,        */
  116.           fill_colour = 0xff,    /*  filling,            */
  117.               background_colour = 0;    /*  and background colour.    */
  118.  
  119. unsigned int    CP_X = 0, CP_Y = 0;    /* Current Drawing Pointer CP.    */
  120. unsigned int    char_size, char_path;    /* Current character size and    */
  121.                     /*  drawing path.        */
  122.  
  123. const unsigned int line_style_mask[16] = {    /* A set of bit masks    */
  124.                     0x8000,    /*  used to mask bits    */
  125.                     0x4000,    /*  from the current    */
  126.                     0x2000,    /*  line style.        */
  127.                     0x1000,
  128.                     0x0800,
  129.                     0x0400,
  130.                     0x0200,
  131.                     0x0100,
  132.                     0x0080,
  133.                     0x0040,
  134.                     0x0020,
  135.                     0x0010,
  136.                     0x0008,
  137.                     0x0004,
  138.                     0x0002,
  139.                     0x0001
  140.                     };
  141.  
  142. STATUS    Stat_Block = {        /* Device status block.            */
  143.   0,                /* Current device status.        */
  144.   0,                /* Device Type Identifier.        */
  145.   639,                /* Device Full Resolution in X        */
  146.   399,                /* Device Full Resolution in Y        */
  147.   639,                /* Device Effective X Resolution    */
  148.   399,                /* Device Effective Y Resolution    */
  149.   9000,                /* Device X Size in inches*1000        */
  150.   7000,                /* Device Y Size in inches*1000        */
  151.   10000,            /* Aspect Ratio * 10000            */
  152.                   /* For compatibility the other fields     */
  153.                 /*  set so.                */
  154.   8,
  155.   8,
  156.   0x90,
  157.   0x90
  158.   };
  159.  
  160. PALETTE Default_Palette = {    /* Default palette.  Note that this is     */
  161.                 /*  hardwired and unchangeable for the     */
  162.                 /*  TGM.                */
  163.   16, { 0x00,         /* Black    */
  164.       0x01,        /* Blue        */
  165.     0x02,        /* Green    */
  166.     0x03,        /* Cyan        */
  167.     0x04,        /* Red        */
  168.     0x05,        /* Magenta    */
  169.     0x07,        /* Light Gray    */
  170.     0x14,        /* Brown    */
  171.     0x38,        /* Dark Gray    */
  172.     0x39,        /* Light Blue    */
  173.     0x3A,        /* Light Green    */
  174.     0x3B,        /* Light Cyan    */
  175.     0x3C,        /* Light Red    */
  176.     0x3D,        /* Light Magenta */
  177.     0x3E,        /* Yellow    */
  178.     0x3F    }    /* White    */
  179.   };
  180.  
  181. /* Global variables specific to this driver.                */
  182.  
  183.             /* Determines the bank and paragraph for an    */
  184.             /*  address.                    */
  185. const struct BANK_PARA bank_para[4] =  {
  186.                 { 31, 0x8000+320, 0x8000, 0},
  187.                 { 31, 0x8000, 0x8000, 0x8000},
  188.                 { 95, 0x8000, 0x8000, 0},
  189.                 { 95, 0x8000, 0x8000-320, 0x8000}
  190.               };
  191. int current_bank = 31,    /* Current bank.                */
  192.     bank_para_index;    /* Offset into the bank_par structure for this    */
  193.                 /*  address.                    */
  194. const unsigned char mask[2] = { 0xf0, 0x0f};    /* Used to ask off     */
  195.                         /*  pixels in a byte.    */
  196.  
  197. unsigned char far * const screen_buffer = 
  198.               (unsigned char far *)MK_FP( TECMAR_SEGMENT, 0);
  199.                 /* Pointer to the base of video memory.    */
  200. unsigned char current_pattern[8][4];    /* Current fill pattern stored    */
  201.                     /*  as pixels.            */
  202. unsigned char far *current_address;    /* Current address into video     */
  203.                     /*  memory.            */
  204. char current_mask;        /* Current pixel mask.            */
  205.  
  206.  
  207.  
  208. /*                                    */
  209. /*    Function Protoypes local to the tecmar driver.            */
  210. /*                                    */
  211.  
  212. void char_draw( unsigned char c);
  213. void copy_image( 
  214.     unsigned char const far *from, 
  215.     int from_off, 
  216.     int from_xsize, 
  217.         unsigned char far *to, 
  218.     int to_off, 
  219.     int to_xsize,
  220.     int mode
  221.     );
  222. void set_pattern( unsigned char *current_pattern, 
  223.           unsigned char const far *pattern);
  224. void update_pattern( void);
  225.  
  226.  
  227. /******************************* INSTALL ********************************/
  228. /*    The Install function is used to prepare the driver to use.  The    */
  229. /*  calls to this function allow the kernal to inquire the mode     */
  230. /*  information, and allow the kernal to install the mode infomation.    */
  231. /*  sets the error code to 'grInvalidMode' for invalid mode numbers    */
  232. /*  and 'grError' for an unrecognized command.                */
  233. /************************************************************************/
  234.  
  235. const char *CopyRight = 
  236.    "Tecmar Graphics Master BGI driver (V 1.10) Copyright R. Adsett 1990.";
  237.  
  238. char Name[] = "\x1F Tecmar Driver (640 x 480 x 4)";
  239.                 /* Name of the drivers only mode.  The     */
  240.                 /*  first character is the length of     */
  241.                 /*  the string.                */
  242.  
  243. long install(
  244.     unsigned int mode,    /* Mode to use.                */
  245.     char command        /* Install sub command.            */
  246.     )
  247. {
  248. long ret_code;
  249.  
  250. switch( command )            /* Determine the command to use */
  251.     {
  252.     case 0:                /* Install Device Command.    */
  253.          if((mode & 0xff) >= MAX_MODES)    /* Is the mode requested valid? */
  254.               {                /*  No set an error code.    */
  255.               Stat_Block.stat = grInvalidMode;
  256.           }
  257.          ret_code = (unsigned int)&Stat_Block;    /* Return pointer to     */
  258.          break;                    /*  the status block.    */
  259.  
  260.     case 1:                /* Mode Query Command.        */
  261.          ret_code = (long)MAX_MODES << 16; /* Return number of modes.    */
  262.          break;
  263.  
  264.     case 2:                /* Mode Name Command.        */
  265.          if( (mode & 0xff) > MAX_MODES)    /* Is the mode requested valid? */
  266.               {                /*  No set an error code.    */
  267.               Stat_Block.stat = grInvalidMode;
  268.           }
  269.          ret_code = (unsigned int)Name;    /* Return pointer to the name.    */
  270.          break;
  271.  
  272.     default:                /* Unknown Install Call.    */
  273.          Stat_Block.stat = grError;    /* General error.        */
  274.          break;
  275.     }                    /* End of Install command case.    */
  276. return( ret_code);            /* Return pointer, mode numbers */
  277. }
  278.  
  279. /******************************* INITIALIZE *****************************/
  280. /*    The initialize function is uset to enter the graphics mode.    */
  281. /*  Since there is only one graphics mode and no text mode all this    */
  282. /*  does is initialize the adapter and clear the screen.        */
  283. /************************************************************************/
  284.  
  285. /************************************************************************/
  286. /*    These are the initialization parameters required to set up the    */
  287. /*  Tecmar in the 640 x 400 x 4 mode.  Don't ask me what all these     */
  288. /*  values do, I'm taking it on rote.  The first column is the port and */
  289. /*  the second is the byte to send out it.  (0,0) ends the sequence.    */
  290. /************************************************************************/
  291.  
  292. static const unsigned int init_6845[][2] = {
  293.                 { 0x398, 1},
  294.                 { 0x394, 13},
  295.                 { 0x395, 0},
  296.                 { 0x394, 12},
  297.                 { 0x395, 0},
  298.                 { 0x394, 11},
  299.                 { 0x395, 0},
  300.                 { 0x394, 10},
  301.                 { 0x395, 32},
  302.                 { 0x394, 9},
  303.                 { 0x395, 3},
  304.                 { 0x394, 8},
  305.                 { 0x395, 3},
  306.                 { 0x394, 7},
  307.                 { 0x395, 56},
  308.                 { 0x394, 6},
  309.                 { 0x395, 50},
  310.                 { 0x394, 5},
  311.                 { 0x395, 1},
  312.                 { 0x394, 4},
  313.                 { 0x395, 64},
  314.                 { 0x394, 3},
  315.                 { 0x395, 15},
  316.                 { 0x394, 2},
  317.                 { 0x395, 184},
  318.                 { 0x394, 1},
  319.                 { 0x395, 160},
  320.                 { 0x394, 0},
  321.                 { 0x395, 227},
  322.                 { 0x399, 0},
  323.                 { 0x39a, 31},
  324.                 { 0x398, 24},
  325.                 { 0, 0}
  326.                    };
  327.  
  328.  
  329. void init( unsigned int dit_offset, unsigned int dit_segment)
  330. {
  331. int i;
  332. struct DIT far *Dev_info;
  333.  
  334. Dev_info = (struct DIT far *)MK_FP( dit_segment, dit_offset);
  335.  
  336. Dev_info->background &= 0x0f;        /* Mask background colour.    */
  337. background_colour = (Dev_info->background << 4) | Dev_info->background;
  338.                     /* Set the background colour.    */
  339. update_pattern();            /* Set up the pattern for use.    */
  340. if( Dev_info->init != 0xA5)        /* Don't ask me!        */
  341.     {
  342.     for( i = 0; init_6845[i][0] != 0; i++)    /* Set up video mode.    */
  343.          {
  344.      outportb( init_6845[i][0], init_6845[i][1]);
  345.      }
  346.     clear();                /* Clear the screen.        */
  347.     }
  348. }
  349.  
  350. /******************************* CLEAR **********************************/
  351. /*    Clear the screen.  Write zero everywhere.              */
  352. /************************************************************************/
  353.  
  354. void clear( void )
  355. {
  356.  
  357. outportb( 0x398, 1);            /* Turn off screen.        */
  358. outportb( 0x39a, 31);            /* Set bank.            */
  359. set_mem( screen_buffer, 0, 0);        /* Erase Bank 0.        */
  360. outportb( 0x39a, 95);            /* Set bank.            */
  361. set_mem( screen_buffer, 0, 0);        /* Erase Bank 1.        */
  362. outportb( 0x39a, current_bank);        /* Restore current bank.    */
  363. outportb( 0x398, 24);            /* Turn on screen.        */
  364. }
  365.  
  366. /********************************** POST ********************************/
  367. /*    Go to text mode.  A null function for the TGM in this mode.    */
  368. /************************************************************************/
  369.  
  370. void post( void )
  371. {
  372.  
  373. /* Tecmar has no text mode in this configuration.            */
  374. }
  375.  
  376. /********************************* MOVE *********************************/
  377. /*    This function is used to move the current pointer (CP). This is    */
  378. /*  a pretty generic routine, library later?                  */
  379. /************************************************************************/
  380.  
  381. void move( int x, int y)
  382. {
  383.  
  384. CP_X = x;                /* Update the current pointer.    */
  385. CP_Y = y;
  386. }
  387.  
  388. /******************************** DRAW **********************************/
  389. /*    Draw a line vector from the CP to the specified coordinate.    */
  390. /*  Update the CP to the new coordinate.                */
  391. /************************************************************************/
  392.  
  393. void draw( int x, int y)
  394. {
  395.  
  396. line( CP_X, CP_Y, x, y);        /* Draw the line.        */
  397. CP_X = x;                /* Update the current pointer    */
  398. CP_Y = y;
  399. }
  400.  
  401. /********************************* VECT *********************************/
  402. /*    Draw a line between the two specified points.            */
  403. /************************************************************************/
  404.  
  405. void vect( int x1, int y1, int x2, int y2)
  406. {
  407.  
  408. line( x1, y1, x2, y2);        /* Draw the line.            */
  409. }
  410.  
  411. /********************************* PATBAR *******************************/
  412. /*    Fill a rectangle with the current filling pattern.  Do not     */
  413. /*  outline.  The coordinates passed are the upper left corner and the    */
  414. /*  lower right corner.                            */
  415. /************************************************************************/
  416.         /* Dummy copy to counter TC++ BUG!! */
  417. void far *junk;
  418. void patbar( int x1, int y1, int x2, int y2)
  419. {
  420. int x3, y3;
  421.  
  422. if( x2 < x1)            /* Sometimes the emulation routines get    */
  423.     {                /*   the y coords. backwards.  We'll    */
  424.     x3 = x2; x2 = x1; x1 = x3;    /*   check the x coords. as well just     */
  425.     }                /*   to be sure.            */
  426. if( y2 < y1)
  427.     {
  428.     y3 = y2; y2 = y1; y1 = y3;
  429.     }
  430. for( ; y1 <= y2; y1++)        /* For each line.            */
  431.     {
  432.     x3 = x1;
  433.     y3 = y1;
  434.     CALC_ADDR( x3, y3);        /* Calculate start address....        */
  435.         /* Dummy copy to counter TC++ BUG!! */
  436.     junk = current_address;
  437.     copy_image( current_pattern[y1&7], 0, 8, current_address, x1&1, 
  438.             x2-x1+1, COPY);    /* ... and copy appropriate line of the    */
  439.                 /*  current pattern in.            */
  440.     }
  441. }
  442.  
  443. /******************************* PALETTE ********************************/
  444. /*    There is no way to adjust the palette on the TGM.  This is a     */
  445. /*  null function.                            */
  446. /************************************************************************/
  447.  
  448. void palette( int flag_index, int red_colour,  int blue, int green)
  449. {
  450. }
  451.  
  452. /****************************** ALLPALETTE ******************************/
  453. /*    There is no way to adjust the palette on the TGM.  This is a     */
  454. /*  null function.                            */
  455. /************************************************************************/
  456.  
  457. void allpalette( unsigned int pptr_offset, unsigned int pptr_segment)
  458. {
  459. }
  460.  
  461. /******************************* COLOR **********************************/
  462. /*    Sets new foreground (drawing) and fill colours.            */
  463. /************************************************************************/
  464.  
  465. void color( char new_fill_colour, char new_draw_colour )
  466. {
  467.  
  468. new_draw_colour &= 0xf;        /* Mask colours to possible range.    */
  469. new_fill_colour &= 0xf;
  470.                 /* Expand them to fill a full char.     */
  471.                 /*   This makes it easier to set a    */
  472.                 /*   a pixel appropriately.        */
  473. current_colour = (new_draw_colour << 4) | new_draw_colour;
  474. fill_colour = (new_fill_colour << 4) | new_fill_colour;
  475. update_pattern();        /* Update current pattern to reflect    */
  476.                 /*   the new colours.            */
  477. }
  478.  
  479. /******************************* FILLSTYLE ******************************/
  480. /*    Set the current fillstyle.                    */
  481. /************************************************************************/
  482.  
  483. static int current_pattern_no = 0, user_pattern[8];
  484.                 /* Current pattern and user pattern.    */
  485.  
  486. void fillstyle( unsigned char pattern, unsigned int pptr_offset,
  487.     unsigned int pptr_segment)
  488. {
  489. unsigned char far *pptr;
  490. int i;
  491.  
  492. pptr = MK_FP( pptr_segment, pptr_offset);    /* Ptr. to user line    */
  493.                         /*   style.        */
  494. current_pattern_no = pattern;        /* Save current style.        */
  495. if( current_pattern_no == 0xff )    /* User defined line style    */
  496.     {
  497.     set_pattern( (unsigned char *)¤t_pattern, pptr);
  498.                     /* Make pattern accessible to filling     */
  499.                 /*   routine.                */
  500.     for( i = 0; i < 8; i++)    /* Save User pattern for later use.    */
  501.          {
  502.      user_pattern[i] = *(int far *)(pptr + i*sizeof( int));
  503.      }
  504.     }
  505. else
  506.     {
  507.     set_pattern( (unsigned char *)current_pattern, 
  508.                  (unsigned char far *)&def_patterns[pattern]);
  509.                     /* Make pattern accessible to filling     */
  510.                 /*   routine.                */
  511.     }
  512. }
  513.  
  514. void update_pattern( void)    /* Update pattern to take care of new    */
  515. {                /*   colours.                */
  516.  
  517. if( current_pattern_no == 0xff )    /* User defined line style    */
  518.     {
  519.     set_pattern( (unsigned char *)current_pattern, 
  520.                  (unsigned char far *)user_pattern);
  521.                     /* Make pattern accessible to filling     */
  522.                 /*   routine.                */
  523.     }
  524. else
  525.     {
  526.     set_pattern( (unsigned char *)current_pattern, 
  527.                  (unsigned char far *)&def_patterns[current_pattern_no]);
  528.                     /* Make pattern accessible to filling     */
  529.                 /*   routine.                */
  530.     }
  531. }
  532.  
  533. /******************************* LINESTYLE ******************************/
  534. /*    Set the current line style.  This includes drawing pattern and    */
  535. /*  width.                                */
  536. /************************************************************************/
  537.  
  538. void linestyle( char style, int pattern, int width)
  539. {
  540.  
  541. switch( style)            /* Set appropriate line pattern.    */
  542.     {
  543.     case SOLID_LINE:
  544.          current_line_style = 0xffff;
  545.      break;
  546.  
  547.     case DOTTED_LINE:
  548.          current_line_style = 0xCCCC;
  549.      break;
  550.  
  551.     case CENTRE_LINE:
  552.          current_line_style = 0xFC78;
  553.      break;
  554.  
  555.     case DASHED_LINE:
  556.          current_line_style = 0xF8F8;
  557.      break;
  558.  
  559.     case USER_LINE:
  560.          current_line_style = pattern;
  561.      break;
  562.  
  563.     default:
  564.          break;
  565.     }
  566. current_line_width = width;        /* Save the width.        */
  567. }
  568.  
  569. /******************************* TEXTSTYLE ******************************/
  570. /*    Set the text path and size.  Returns x & y size as a long.    */
  571. /************************************************************************/
  572.  
  573. long textstyle( char number, char path, int xsize, int ysize)
  574. {
  575.  
  576. char_path = path;            /* Record path.            */
  577. char_size = xsize >> 3;            /* Convert text size to a    */
  578.                     /*  multiple of 8.        */
  579. if( char_size == 0)            /* Must be at least 1.        */
  580.     char_size = 1;
  581. xsize = ysize = char_size << 3;        /* Compute actual size.        */
  582. return( (((long)xsize) << 16) | ysize);    /* Return actual size.        */
  583. }
  584.  
  585. /******************************** TEXT **********************************/
  586. /*    Draw a text string.                        */
  587. /************************************************************************/
  588.  
  589. void text( int length, unsigned int offset, unsigned int segment)
  590. {
  591. char far * cptr = MK_FP( segment, offset);
  592. int i;
  593.  
  594. for( i = 0; i < length; ++i )         /* For all characters ...    */
  595.     {
  596.     char_draw( *cptr++);        /* Draw it.            */
  597.     }
  598. }
  599.  
  600. /****************************** FLOODFILL *******************************/
  601. /*    Unimplemented. Null function.                    */
  602. /************************************************************************/
  603.  
  604. void floodfill( int x, int y, unsigned char boundary)
  605. {
  606. }
  607.  
  608. /******************************* BITMAPUTIL *****************************/
  609. /*    Get the address of the bit map utility table.            */
  610. /************************************************************************/
  611.  
  612. void *bitmaputil( void )
  613. {
  614.  
  615. return((void *)&Utility_Table);
  616. }
  617.  
  618. /*                                    */
  619. /*    The following define the bit map utility functions.        */
  620. /*                                    */
  621.  
  622. void enter_graphics( void )        /* Enter graphics mode function.*/
  623. {                    /* Null function.        */
  624. }
  625.  
  626. void leave_graphics( void )        /* Leave graphics mode function */
  627. {                    /* Null function.        */
  628. }
  629.  
  630. int bits_per_pixel( void )        /* Enter graphics mode function */
  631. {
  632.  
  633. return( 4);                /* Always 4 bits/pixel.        */
  634. }
  635.  
  636. void putpix( int x, int y, char colour)    /* Write a pixel function    */
  637. {
  638.  
  639. colour &= 0xf;                /* Propagate colour to high    */
  640. colour |= colour << 4;            /*   nibble.            */
  641. CALC_ADDR( x, y);            /* Calculate address.        */
  642. POINT( colour);                /* Draw pixel.            */
  643. }
  644.  
  645. char getpix( int x, int y)        /* Read a pixel function    */
  646. {
  647.  
  648. CALC_ADDR( x, y);            /* Calculate address.        */
  649. return( RD_POINT());            /* Read pixel colour.        */
  650. }
  651.  
  652. void set_page( char page)        /* Set the active drawing page    */
  653. {                    /* Null function.  Only 1 page.    */
  654.  
  655. }
  656.  
  657. void set_visual( char page)        /* Set the active display page    */
  658. {                    /* Null function.  Only 1 page.    */
  659.  
  660. }
  661.  
  662. void set_write_mode( int mode)        /* Set the current write mode    */
  663. {
  664.  
  665. current_write_mode = mode;        /* Save write mode.        */
  666. }
  667.  
  668.  
  669. /****************************** RESTOREBITMAP ***************************/
  670. /*    Copy a bitmap to video memory.                    */
  671. /************************************************************************/
  672.  
  673. void restorebitmap( char mode, unsigned int segment, unsigned int offset,
  674.         int x1, int y1, int x2, int y2)
  675. {
  676. const unsigned char far *buffer;
  677. int xsize, x3, y3, bump;
  678.  
  679. x1 = x2;/* Bug. */
  680. y1 = y2;
  681.  
  682. buffer = (const unsigned char far *)MK_FP( segment, offset);
  683.                     /* Bitmap address.        */
  684. xsize = *(int far *)buffer + 1;        /* Columns.            */
  685. buffer += sizeof( int);
  686. y2 = y1 + *(int far *)buffer + 1;    /* Rows.            */
  687. bump = xsize/2 +1;            /* Size of row in memory.  This    */
  688.                     /* should be agreed on with     */
  689.                     /* 'savebitmap'.        */
  690. buffer += sizeof(int);            /* Increment to storage.    */
  691. for( ;y1 < y2; y1++)            /* For each line...        */
  692.     {
  693.     x3 = x1;
  694.     y3 = y1;
  695.     CALC_ADDR( x3, y3);            /* Find the beginning.        */
  696.         /* Dummy copy to counter TC++ BUG!! */
  697.     junk = current_address;
  698.     copy_image( buffer, 0, xsize, current_address, x1&1, xsize, mode);
  699.                         /* Copy the line using the    */
  700.                     /*  appropriate mode.        */
  701.     buffer += bump;            /* Increment bitmap to the next    */
  702.     }                    /*  line.            */
  703. }
  704.  
  705. /****************************** SAVEBITMAP ******************************/
  706. /*    Copy an area of video memory to a bitmap.            */
  707. /************************************************************************/
  708.  
  709. void savebitmap( unsigned int buff_segment, unsigned int buff_offset,
  710.         int x1, int y1, int x2, int y2)
  711. {
  712. unsigned char far *buffer;
  713. int xsize, x3, y3, bump;
  714.  
  715. x1 = x2;/* Bug.*/
  716. y1 = y2;
  717. buffer = (unsigned char far *)MK_FP( buff_segment, buff_offset);
  718.                     /* Bitmap address.        */
  719. xsize = *(int far *)buffer + 1;        /* Columns.            */
  720. buffer += sizeof( int);
  721. y2 = y1 + *(int far *)buffer + 1;    /* Rows.            */
  722. bump = xsize/2 +1;            /* Size of row in memory.  This    */
  723.                     /* should be agreed on with     */
  724.                     /* 'restorebitmap'.        */
  725. buffer += sizeof(int);            /* Increment to storage.    */
  726. for( ;y1 < y2; y1++)            /* For each line...        */
  727.     {
  728.     x3 = x1;
  729.     y3 = y1;
  730.     CALC_ADDR( x3, y3);            /* Find the beginning.        */
  731.         /* Dummy copy to counter TC++ BUG!! */
  732.     junk = current_address;
  733.     copy_image( current_address, x1&1, xsize, buffer, 0, xsize, COPY);
  734.                         /* Copy the line using the    */
  735.                     /*  copy mode.            */
  736.     buffer += bump;            /* Increment bitmap to the next    */
  737.     }                    /*  line.            */
  738. }
  739.  
  740. /****************************** SETCLIP *********************************/
  741. /*    Set the clipping area.    Library?                */
  742. /************************************************************************/
  743.  
  744. void setclip( int x1, int y1, int x2, int y2)
  745. {
  746.  
  747. MINX = x1;                /* Save the clipping limits.    */
  748. MAXY = y1;
  749. MAXX = x2;
  750. MAXY = y2;
  751. }
  752.  
  753. /***************************** GET_PIXEL ********************************/
  754. /*    Read a pixel colour from the screen.                */
  755. /************************************************************************/
  756.  
  757. char get_pixel( int x, int y)
  758. {
  759.  
  760. CALC_ADDR( x, y);            /* Calculate the address.    */
  761. return( RD_POINT());            /* Read the pixel.        */
  762. }
  763.  
  764. /***************************** SET_PIXEL ********************************/
  765. /*    Set a pixel to a specific colour.                */
  766. /************************************************************************/
  767.  
  768. void set_pixel( int x, int y, char colour)
  769. {
  770.  
  771. colour &= 0xf;                /* Propagate colour to the high    */
  772. colour |= colour << 4;            /*  nibble.            */
  773. CALC_ADDR( x, y);            /* Calculate address.        */
  774. POINT( colour);                /* Draw the pixel.        */
  775. }
  776.  
  777. /****************************** TEXTSIZ *********************************/
  778. /*    Return the pixel size of a string.                */
  779. /************************************************************************/
  780.  
  781. long textsiz( int length, unsigned int offset, unsigned int segment)
  782. {
  783. if( char_path == NORMAL_PATH)        /* Horizontal.            */
  784.     {
  785.     return( (((long)(length*char_size*8))<<16) | (8*char_size));
  786.     }
  787. else                    /* Vertical.            */
  788.     {
  789.     return( (((long)(char_size*8))<<16) | (length*8*char_size));
  790.     }
  791. }
  792.  
  793. /****************************** COLOR_QUERY *****************************/
  794. /*    Get colour palette & size.                    */
  795. /************************************************************************/
  796.  
  797. long color_query( char command_type)
  798. {
  799. int i;
  800. long ret_val;
  801.  
  802. i = 16;                 /* Number of colours.        */
  803.  
  804. switch( command_type )            /* Act on the input command.    */
  805.     {
  806.     case 0:                /* Color palette size query.    */
  807.          ret_val = ((long)i -1L) << 16;
  808.          ret_val |= i;
  809.          break;
  810.  
  811.     case 1:                /* Default palette settings.    */
  812.          ret_val = (unsigned long)&Default_Palette;
  813.          break;
  814.  
  815.     default:                /* Unknown command.        */
  816.          break;
  817.     }
  818. return( ret_val);
  819. }
  820.  
  821. /********************* CHAR_DRAW ****************************************/
  822. /*    Draw a character.                        */
  823. /************************************************************************/
  824. void char_draw( unsigned char c)
  825. {
  826. static unsigned char char_bit_mask[8] = { 128, 64, 32, 16, 8, 4, 2, 1};
  827. const CHAR_TABLE_ENTRY far *current;
  828. int i, j, k, l, tx, ty;
  829. unsigned char row_cur;
  830.  
  831. current = char_def + c;        /* Get character definition from ROM.    */
  832. if( char_path == NORMAL_PATH)    /* Draw horizontal.            */
  833.     {
  834.     for( i = 0; i < 8; i++)            /*  For each row...    */
  835.          {
  836.          row_cur = (current->row)[i];        /* Def. for this line.    */
  837.          for( j = 0; j < char_size; j++)    /* Size multiplier.    */
  838.               {
  839.           for( k = 0; k < 8; k++)         /*  For each column...    */
  840.                {
  841.                if( row_cur & char_bit_mask[k])    /* Column def.    */
  842.                     {
  843.                     for( l = 0; l < char_size; l++)    /* Draw 'size'    */
  844.                          {                /*  points.    */
  845.                  tx = CP_X;
  846.                  ty = CP_Y;
  847.                  DRAW_POINT( tx, ty);
  848.                      CP_X++;
  849.                      }
  850.                 }
  851.                else            /* Advance 'size' points.    */
  852.                     {
  853.                 CP_X += char_size;
  854.                     }
  855.                }
  856.           CP_X -= char_size*8;        /* Back to begining col.*/
  857.           CP_Y++;                /* Next line.        */
  858.           }
  859.          }
  860.     CP_X += char_size*8;        /* Next character.        */
  861.     CP_Y -= char_size*8;        /* Charcter top.        */
  862.     }
  863. else                /* Draw vertical.            */
  864.     {
  865.     for( i = 0; i < 8; i++)            /*  For each row...    */
  866.          {
  867.          row_cur = (current->row)[i];        /* Def. for this line.    */
  868.          for( j = 0; j < char_size; j++)    /* Size multiplier.    */
  869.               {
  870.           for( k = 0; k < 8; k++)         /*  For each column...    */
  871.                {
  872.                if( row_cur & char_bit_mask[k])    /* Column def.    */
  873.                     {
  874.                     for( l = 0; l < char_size; l++)
  875.                          {
  876.                  tx = CP_X;
  877.                  ty = CP_Y;
  878.                  DRAW_POINT( tx, ty);
  879.                      CP_Y--;
  880.                      }
  881.                 }
  882.                else            /* Advance 'size' points.    */
  883.                     {
  884.                 CP_Y -= char_size;
  885.                     }
  886.                }
  887.           CP_Y += char_size*8;        /* Back to begining col.*/
  888.           CP_X++;                  /* Next line.        */
  889.           }
  890.          }
  891.     CP_Y -= char_size*8;          /* Next character.        */
  892.     CP_X -= char_size*8;          /* Charcter top.        */
  893.     }
  894. }
  895.  
  896. /************************* COPY_IMAGE ***********************************/
  897. /*    Copy an image line from one area of memory to another.  The     */
  898. /*  source image is repeated as necessary to fill the destination.      */
  899. /*  This is sufficient to form the core of a basic set of two parameter    */
  900. /*  BiTBlT routines except for the fact that no precautions are taken     */
  901. /*  against overlap.  Could be sped up considerably by recoding in    */
  902. /*  assembly code.                            */
  903. /************************************************************************/
  904.  
  905. void copy_image( 
  906.     unsigned char const far *from, 
  907.     int from_off, 
  908.     int from_xsize, 
  909.         unsigned char far *to, 
  910.     int to_off, 
  911.     int to_xsize,
  912.     int mode
  913.     )
  914. {
  915. int j;
  916. unsigned char from_mask, to_mask, temp;
  917. unsigned char const far *temp_from;
  918.  
  919. from_mask = mask[from_off];        /* Mask appropriately to get    */
  920. to_mask = mask[to_off];            /*  the right nibbles.  May not    */
  921.                     /*  be on a byte boundary.    */
  922. temp_from = from;            /* Pointer to source.        */
  923.  
  924. switch( mode)                /* Copy mode.            */
  925.     {
  926.     case COPY:                /* Copy verbatim.        */
  927.          for( j = 0; j < to_xsize; j++)    /* Until destination is full...    */
  928.               {
  929.               if( !(j % from_xsize))    /* Restart source from start.    */
  930.                    {
  931.                temp_from = from;
  932.            from_mask = mask[from_off];
  933.                }
  934.           temp = (*temp_from & from_mask);    /* Read source...    */
  935.           if( from_mask == 0xf0)
  936.                {
  937.            temp |= temp >> 4;        /* ... into low nibble,    */
  938.            }
  939.           else
  940.                {
  941.            temp |= temp << 4;        /* ... and high.    */
  942.            }
  943.               *to = (*to & ~to_mask) | (temp & to_mask);
  944.                               /* Copy source into     */
  945.                         /*  proper dest. nibble.*/
  946.               to_mask = ~to_mask;        /* Increment source    */
  947.               from_mask = ~from_mask;        /*  and destination.    */
  948.               if( to_mask == 0xf0)        /* Start of new byte.    */
  949.                {
  950.                to++;
  951.                }
  952.               if( from_mask == 0xf0)
  953.                {
  954.                temp_from++;
  955.                }
  956.               }
  957.      break;
  958.  
  959.     case XOR:                       /* Copy xor.            */
  960.          for( j = 0; j < to_xsize; j++)    /* Until destination is full...    */
  961.               {
  962.               if( !(j % from_xsize))       /* Restart source from start.    */
  963.                    {
  964.                temp_from = from;
  965.            from_mask = mask[from_off];
  966.                }
  967.           temp = (*temp_from & from_mask);    /* Read source...    */
  968.           if( from_mask == 0xf0)
  969.                {
  970.            temp |= temp >> 4;              /* ... into low nibble,    */
  971.            }
  972.           else
  973.                {
  974.            temp |= temp << 4;              /* ... and high.    */
  975.            }
  976.               *to = (*to & ~to_mask) | ((temp ^ *to) & to_mask);
  977.                               /* Xor source into     */
  978.                         /*  proper dest. nibble.*/
  979.               to_mask = ~to_mask;            /* Increment source    */
  980.               from_mask = ~from_mask;        /*  and destination.    */
  981.               if( to_mask == 0xf0)           /* Start of new byte.    */
  982.                {
  983.                to++;
  984.                }
  985.               if( from_mask == 0xf0)
  986.                {
  987.                temp_from++;
  988.                }
  989.               }
  990.      break;
  991.  
  992.     case OR:                       /* Copy or.            */
  993.          for( j = 0; j < to_xsize; j++)    /* Until destination is full...    */
  994.               {
  995.               if( !(j % from_xsize))       /* Restart source from start.    */
  996.                    {
  997.                temp_from = from;
  998.            from_mask = mask[from_off];
  999.                }
  1000.           temp = (*temp_from & from_mask);    /* Read source...    */
  1001.           if( from_mask == 0xf0)
  1002.                {
  1003.            temp |= temp >> 4;              /* ... into low nibble,    */
  1004.            }
  1005.           else
  1006.                {
  1007.            temp |= temp << 4;              /* ... and high.    */
  1008.            }
  1009.               *to = (*to & ~to_mask) | ((temp | *to) & to_mask);
  1010.                               /* Or source into     */
  1011.                         /*  proper dest. nibble.*/
  1012.               to_mask = ~to_mask;            /* Increment source    */
  1013.               from_mask = ~from_mask;        /*  and destination.    */
  1014.               if( to_mask == 0xf0)           /* Start of new byte.    */
  1015.                {
  1016.                to++;
  1017.                }
  1018.               if( from_mask == 0xf0)
  1019.                {
  1020.                temp_from++;
  1021.                }
  1022.               }
  1023.      break;
  1024.  
  1025.     case AND:                       /* Copy and.            */
  1026.          for( j = 0; j < to_xsize; j++)    /* Until destination is full...    */
  1027.               {
  1028.               if( !(j % from_xsize))       /* Restart source from start.    */
  1029.                    {
  1030.                temp_from = from;
  1031.            from_mask = mask[from_off];
  1032.                }
  1033.           temp = (*temp_from & from_mask);    /* Read source...    */
  1034.           if( from_mask == 0xf0)
  1035.                {
  1036.            temp |= temp >> 4;              /* ... into low nibble,    */
  1037.            }
  1038.           else
  1039.                {
  1040.            temp |= temp << 4;              /* ... and high.    */
  1041.            }
  1042.               *to = (*to & ~to_mask) | ((temp & *to) & to_mask);
  1043.                               /* And source into     */
  1044.                         /*  proper dest. nibble.*/
  1045.               to_mask = ~to_mask;            /* Increment source    */
  1046.               from_mask = ~from_mask;        /*  and destination.    */
  1047.               if( to_mask == 0xf0)           /* Start of new byte.    */
  1048.                {
  1049.                to++;
  1050.                }
  1051.               if( from_mask == 0xf0)
  1052.                {
  1053.                temp_from++;
  1054.                }
  1055.               }
  1056.      break;
  1057.  
  1058.     case NEGATE:                   /* Copy negate.            */
  1059.          for( j = 0; j < to_xsize; j++)    /* Until destination is full...    */
  1060.               {
  1061.               if( !(j % from_xsize))       /* Restart source from start.    */
  1062.                    {
  1063.                temp_from = from;
  1064.            from_mask = mask[from_off];
  1065.                }
  1066.           temp = (*temp_from & from_mask);    /* Read source...    */
  1067.           if( from_mask == 0xf0)
  1068.                {
  1069.            temp |= temp >> 4;              /* ... into low nibble,    */
  1070.            }
  1071.           else
  1072.                {
  1073.            temp |= temp << 4;              /* ... and high.    */
  1074.            }
  1075.               *to = (*to & ~to_mask) | (~temp & to_mask);
  1076.                               /* Negate source into     */
  1077.                         /*  proper dest. nibble.*/
  1078.               to_mask = ~to_mask;            /* Increment source    */
  1079.               from_mask = ~from_mask;        /*  and destination.    */
  1080.               if( to_mask == 0xf0)           /* Start of new byte.    */
  1081.                {
  1082.                to++;
  1083.                }
  1084.               if( from_mask == 0xf0)
  1085.                {
  1086.                temp_from++;
  1087.                }
  1088.               }
  1089.      break;
  1090.  
  1091.     default:
  1092.          break;
  1093.     }
  1094. }
  1095.  
  1096. /*************************** SET_PATTERN ********************************/
  1097. /*    Change a bit pattern into a colour image pattern that can be    */
  1098. /*  easily copied.  The bit pattern is an 8x8 pattern.            */
  1099. /************************************************************************/
  1100.  
  1101. void set_pattern( unsigned char *current_pattern, 
  1102.           unsigned char const far *pattern)
  1103. {
  1104. static unsigned char pat_mask[8] = { 128, 64, 32, 16, 8, 4, 2, 1};
  1105. int i, j;
  1106.  
  1107. for( i = 0; i < 8; i++)        /* For each line.            */
  1108.     {
  1109.     for( j = 0; j < 8; j++)    /* For each column.            */
  1110.          {
  1111.      if( *pattern & pat_mask[j])    /* Set to fill colour.        */
  1112.           {
  1113.           *current_pattern = (*current_pattern & ~mask[j&1]) | 
  1114.                              (fill_colour & mask[j&1]);
  1115.           }
  1116.      else            /* Or the background colour.        */
  1117.           {
  1118.           *current_pattern = (*current_pattern & ~mask[j&1]) | 
  1119.                              (background_colour & mask[j&1]);
  1120.           }
  1121.      if( j&1)        /* Next pattern element.        */
  1122.           {
  1123.           current_pattern++;
  1124.           }
  1125.      }
  1126.     pattern++;            /* Next line.                */
  1127.     }
  1128. }
  1129.