home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD2.mdf / c / library / dos / grafik / cbgi111 / doc / cbgi.doc next >
Encoding:
Text File  |  1990-06-30  |  22.8 KB  |  575 lines

  1.             CBGI - C shell for BGI drivers
  2.  
  3.   This is the documentation for a shell that can be used to write BGI
  4. drivers using C.  This documentation is not intended as a replacement
  5. for Borland's documentation and in fact will refer to it from time to
  6. time for further explanation.  
  7.  
  8. WHY USE CBGI?
  9.  
  10.   The CBGI library provides an interface layer that converts the 
  11. register passing calling convention of the BGI interface to a 
  12. 'normal' C stack based convention.  It also switches to a local stack
  13. so that the driver routines may written in C and compiled with full
  14. optimization in a normal fashion.  Also included with this library
  15. is a (are) sample working driver(s) with complete source code. Usually
  16. the quickest way to get a driver up and running is to modify this
  17. sample code to suit the adapter you are writing for.  This code may
  18. then be improved to better suit the driver.  Although it is possible
  19. to write the entire driver in C you may want to recode small sections
  20. in assembler to provide a performance boost, or to provide additional
  21. capabilities to the default driver.
  22.  
  23.   In case this sounds too good to be true there are a couple of
  24. limitations to using the shell.  The working stack is quite small
  25. (~512 bytes).  It can be adjusted by modifying and recompiling
  26. 'stack.asm'.  This stack size should not usually be a problem (if it
  27. is you should probably consider making some of your automatic
  28. variables statics).  The second limitation is that every call to the
  29. driver results in a stack switch.  While this will be insignificant if
  30. each call does enough work it can add up.  As a matter of practical
  31. use I haven't found it to add significantly to the overhead in
  32. performing the actual task and the overhead imposed by the BGI
  33. kernal.
  34.  
  35. WHAT DOES IT COST?
  36.  
  37.   Under most circumstances nothing.  The package is free to use under
  38. most circumstances.  I am placing some restrictions on use, but they
  39. should not be too onerous.  I am asking that you send me copies
  40. (preferably with source) of any drivers you make.  I will collect
  41. them and include them in subsequent distributions of this kit.  These
  42. will be available directly from me for a modest fee to cover disk
  43. copying and mailing (or just wait until they reach a Bulletin Board
  44. near you).
  45.  
  46. Restrictions
  47.  
  48.   If you write a program that you wish to ship one of the drivers
  49. included in (or develop with) this kit with,  you must include the
  50. entire kit or provide an easy way to get it (In the case of shareware
  51. it might be part of the benefit for registering).  If for some reason
  52. you only wish to include one driver contact me and arrangments can be
  53. made.
  54.  
  55. PURPOSE OF THIS DOCUMENTATION
  56.  
  57. What it is not.
  58.  
  59.   This document is not meant to replace Borland's documentation on BGI
  60. drivers.  It is also not meant to explain how various adapters work
  61. or how to program any adapter.
  62.  
  63. What It is meant to be.
  64.  
  65.   This document is meant to explain the set of C shell routines that I
  66. wrote as result of my experiences with Borland's documentation and
  67. example driver.  It explains the shell routines only sketchily.  The
  68. main documentation for the purpose of these routines is Borland's
  69. documentation.  I am only providing information on how the parameters
  70. passed to the driver are presented to the C routines you must write. 
  71. I only provide additional documentation when I have run into points
  72. that I found needed clarification.  
  73.  
  74.   The utility functions I have created are more fully documented.
  75.  
  76.   Since this documentation is being written in my spare time it will
  77. probably improve and grow more complete as time goes on.  Suggestions
  78. on what points need to be clarified are welcome (as long as they are
  79. basically friendly).
  80.  
  81.   Documentation on the driver(s) accompianing this are with the
  82. driver(s) themselves.  Note that the driver source code is an
  83. important source of documentation for this library in itself.
  84.  
  85. USING THE CBGI LIBRARY
  86.  
  87.   The CBGI library consists of two distinct interface components. 
  88. The startup object module c0cbgi.obj is a replacement for the
  89. c0x.obj's used by TC.  It provides the tables used to branch to the
  90. appropriate routines and also the stack switcher.  It used in the
  91. same manner as the c0x.obj's provided by Borland are.  The second
  92. component of the CBGI library is the interface routines that convert
  93. the register based calling convention of the BGI to a stack based
  94. one.  These are documented below. 
  95.  
  96.   Some of the routines in a BGI driver may be emulated by the BGI
  97. kernal.  The default startup shipped with this library sets up
  98. emulation for all the calls that can be handled that way.  The
  99. assembly module c0cbgi.asm must be edited and recompiled in order to
  100. change this.
  101.  
  102.   All the interface routines are written using TASM's ideal mode. 
  103. Some modifications will be necessary if you wish to compile them
  104. using another assembler.
  105.  
  106. INTERFACE ROUTINES
  107.  
  108. 1) Required functions -- These routines are required in any driver. 
  109. See Borland's documentation and the example driver(s) for details on
  110. how these functions should be written.  Most of the interface
  111. routines use the same names that Borland give the dispatch vectors in
  112. their documentation, so that cross referencing between their
  113. documentation and mine should be fairly simple.
  114.  
  115. void allpalette( unsigned int pptr_offset, unsigned int pptr_segment);
  116.  
  117.   Restore the entire palette.  The BGI kernal seems to restrict the
  118. use of this function to palettes that contain <= 16 colours.
  119.  
  120. void *bitmaputil( void );
  121.  
  122.   Return a pointer to the bitmap utility table.  Yes that is a regular
  123. pointer, it is converted to a far pointer by the interface routine. 
  124. This table consists mainly of function pointers.  A set of interface
  125. routines exist for these too, see the later documentation on these
  126. and the example driver(s) for more information.
  127.  
  128. void clear( void );
  129.  
  130.   Clear the screen.
  131.  
  132. void color( char new_fill_colour, char new_draw_colour );
  133.  
  134.   Set the colours used by the driver.
  135.  
  136. long color_query( char command_type);
  137.  
  138.   Query the colour table.  In the case of a palette size query the
  139. upper half of the long contains the maximum colour number and the
  140. lower the number of colour table entries.  Otherwise only the lower
  141. half is used.
  142.  
  143. void draw( int x, int y);
  144.  
  145.   Draw a line to x, y.
  146.  
  147. void fillstyle( char pattern, unsigned int pptr_offset,
  148.                 unsigned int pptr_segment);
  149.  
  150.   Set the fillstyle for later fill operations.
  151.  
  152. void floodfill( int x, int y, unsigned char boundary);
  153.  
  154.   Perform a floodfill.  Note that this is not implemented in the
  155. example driver (it's a null function).
  156.  
  157. char get_pixel( int x, int y);
  158.  
  159.   Read the pixel at x, y.
  160.  
  161. void init( unsigned int dit_offset, unsigned int dit_segment);
  162.  
  163.   Initialize the driver to the mode requested.  Initialize all
  164. varaibles that need it.  
  165.  
  166.   IMPORTANT NOTE!!  Do NOT! assume that uninitialized global variables
  167. will be zero.  There is nothing in the startup to ensure that.
  168.  
  169. long install( unsigned int mode, char command);
  170.  
  171.   Initialize the driver (and save requested mode).  This is called
  172. before init.
  173.  
  174.   IMPORTANT NOTE!!  Do NOT! assume that uninitialized global variables
  175. will be zero.  There is nothing in the startup to ensure that.
  176.  
  177. void linestyle( char style, int pattern, int width);
  178.  
  179.   Set the style for drawing lines.
  180.  
  181. void move( int x, int y);
  182.  
  183.   Move to x, y.
  184.  
  185. void palette( int flag_index, int red_colour, int blue, int green);
  186.  
  187.   Set a palette entry.
  188.  
  189. void patbar( int x1, int y1, int x2, int y2);
  190.  
  191.   Pattern a rectangular area.
  192.  
  193. void post( void );
  194.  
  195.   Exit from graphics mode.  Essentially the inverse of init.
  196.  
  197. void set_pixel( int x, int y, char colour);
  198.  
  199.   Draw a pixel.
  200.  
  201. void restorebitmap( char mode, unsigned int segment, unsigned int offset,
  202.             int x1, int y1, int x2, int y2);
  203.  
  204.   Restore a previously saved bitmap.  Note that x1 & y1 do not mean
  205. anything.  they were based on comments in Borland's documentation
  206. that implied that si & di contained usefull information for this
  207. function.  Use x2 & y2 and the information stored in the bitmap to
  208. determine it's size.  See the example(s) for more details.
  209.  
  210. void savebitmap( unsigned int buff_segment, unsigned int buff_offset,
  211.          int x1, int y1, int x2, int y2);
  212.  
  213.   Save a bitmap for later restoration.  See previous comment about
  214. x1, y1.  The BGI kernal appears to use the bits_per_pixel entry of the
  215. bitmap utility table to determine the size of the block for this.
  216.  
  217. void setclip( int x1, int y1, int x2, int y2);
  218.  
  219.   Set the clipping area.
  220.  
  221. void text( int length, unsigned int offset, unsigned int segment);
  222.  
  223.   Print bitmap text.
  224.  
  225. long textsiz( int length, unsigned int offset, unsigned int segment);
  226.  
  227.   Determine the size of the text string (in pixels).
  228.  
  229. long textstyle( char number, char path, int xsize, int ysize);
  230.  
  231.   Set the style to draw the text in.
  232.  
  233. void vect( int x1, int y1, int x2, int y2);
  234.  
  235.   Draw a line.
  236.  
  237. 1a) Required functions (Bit Map Utility Table) -- Contrary to the
  238. documentation these routines appear to be required in any driver.  And
  239. they are not used to emulate ellipses.  See Borland's documentation
  240. and the example driver(s) for details on how these functions should
  241. be written.  Most of the interface routines use the same names that
  242. Borland give the dispatch vectors in their documentation, so that
  243. cross referencing between their documentation and mine should be
  244. fairly simple.  The address loaded into the Bit Map Utility table
  245. should not be the addresses of these functions but of the assembly
  246. language interface functions.  The interface functions have the same
  247. name except that they begin with dispatch_.  So the entry in the
  248. table for bits_per_pixel will be dispatch_bits_per_pixel (see the
  249. example(s) for details.
  250.  
  251. int bits_per_pixel( void)
  252.  
  253.   Yes, this is a function not a number.
  254.  
  255. void enter_graphics( void);
  256.  
  257.   Enter special graphics mode for fast pixel drawing.
  258.  
  259. char getpix( int x, int y);
  260.  
  261.   Get pixel colour.
  262.  
  263. void leave_graphics( void );
  264.  
  265.   Leave special graphics mode.
  266.  
  267. void putpix( int x, int y, char colour);
  268.  
  269.   Draw pixel.
  270.  
  271. void set_page( char page);
  272.  
  273.   Set drawing page.
  274.  
  275. void set_visual( char page);
  276.  
  277.   Set the visible page.
  278.  
  279. void set_write_mode( int mode);
  280.  
  281.   Set the drawing mode.
  282.  
  283. 2) Optional functions -- These are functions that can be emulated. 
  284. The default startup shipped with the library does emulate these.  In
  285. order to use these functions the startup will have to be modified. 
  286. Note that these dispatch routines are not as throughly tested as the
  287. others.  See Borland's documentation and the example driver(s) for
  288. details on how these functions should be written.  Most of the
  289. interface routines use the same names that Borland give the dispatch
  290. vectors in their documentation, so that cross referencing between
  291. their documentation and mine should be fairly simple.
  292.  
  293. void arc( int start_angle, int end_angle, int x_radius, int y_radius);
  294.  
  295.   Draw an arc.
  296.  
  297. void bar( int x, int y, int depth, int top);
  298.  
  299.   Draw a 3D bar.
  300.  
  301. void filled_ellipse( int x_radius, int y_radius);
  302.  
  303.   Draw a filled ellipse.
  304.  
  305. void pieslice( int start_angle, int end_angle, int x_radius, int y_radius);
  306.  
  307.   Draw a pieslice.
  308.  
  309.  
  310. SUPPORT FUNCTIONS
  311.  
  312. bgipline.h
  313.  
  314.    This is at one and the same time the most general and the most
  315. unusual of the support functions.  It is in fact a header file that
  316. contains the source code for a line drawing function.  It is written
  317. to use several macros to draw the points of the line.  The main line
  318. drawing code itself is device independant.  Macros are used rather
  319. than functions since the overhead of a function call in an inner loop
  320. can be substantial.  The macros themselves are designed to take
  321. advantage of any speed increase available from knowing all address
  322. changes are + or - 1 in the row or column.  The macros needed are:
  323.  
  324. CALC_ADDR( x, y)    Calculate the address of the point at x, y.
  325. X_INCREMENT_CALC()    Calculate the address of a point one column
  326.               further along (x++).
  327. Y_INCREMENT_CALC()    Calculate the address of a point one row
  328.               further along (y++).
  329. Y_DECREMENT_CALC()    Calculate the address of a point one row
  330.               less further along (y--).
  331. XOR_POINT( colour)    Xor a point of colour at the current address.
  332. POINT( colour)        Plot a point of colour at the current 
  333.               address.
  334.  
  335.   This routine also assumes the presence of 'current_line_style',
  336. 'current_write_mode' and 'line_style_mask' as defined in the example
  337. driver.
  338.  
  339.   There is also a set of block transfer functions that perform copies
  340. from a block of source memory to a block of destination memory.  If
  341. the source is smaller than the destination the copy 'wraps around' to
  342. the beginning of the source until the destination is filled.  These
  343. routines perform this copying using various logical operations
  344. between the source and the destination.
  345.  
  346.   These block operations are optimized to do 16 bit transfers on word
  347. boundaries in the destination.  This should have little effect on 8
  348. bit adapters/buses but could mean up to a factor of 4 on 16 bit buses
  349. (on the other hand it may not help at all, but at least it won't
  350. hurt).  These functions are strictly memory to memory operations,
  351. they do not attempt any adapter specific operations.
  352.  
  353.   In the following routine definitions the parameter names use the
  354. following conventions.
  355.  
  356. source        -- The area of memory serving as the source.
  357. destination    -- The area of memory serving as the destination.
  358. src_size    -- The size of the source memory area.
  359. dest_size    -- The size of the destination memory area.
  360.  
  361. void copy_mem( void far *source, int src_size, void far *destination, 
  362.                int dest_size);
  363.  
  364.   Copy the source to the destination.
  365.  
  366.  
  367. void xor_mem( void far *source, int src_size, void far *destination, 
  368.           int dest_size);
  369.  
  370.   Xor the source with the destination.
  371.  
  372.  
  373. void or_mem( void far *source, int src_size, void far *destination, 
  374.           int dest_size);
  375.  
  376.   Or the source with the destination.
  377.  
  378.  
  379. void and_mem( void far *source, int src_size, void far *destination, 
  380.           int dest_size);
  381.  
  382.   And the source with the destination.
  383.  
  384.  
  385. void neg_mem( void far *source, int src_size, void far *destination, 
  386.           int dest_size);
  387.  
  388.   Neg the source and copy to the destination.  This does not modify
  389. the source.
  390.  
  391.  
  392. void set_mem( void far *destination, unsigned dest_size, 
  393.               unsigned value);
  394.  
  395.   Set the destination to the value contained in value.  This function
  396. has several peculiar features.  If the size to be set is passed as
  397. zero then a full 64K will be set.  The second peculiarity is that the
  398. 'word' value is placed in memory not just it's lower byte.  That
  399. means that a value of 0x0101 sets all the bytes to 1 but a value of
  400. 0x01 sets every second byte to 1 and the others to zero.
  401.  
  402. Extended Memory Functions.
  403.  
  404.   A number of specialty boards designed for the AT are mapped into
  405. extended memory in order to avoid crowded regular memory.  Since 
  406. programs running in real mode under DOS cannot normally access this
  407. memory this presents a potential problem.
  408.  
  409.   There are two solutions.  1) Switch the driver to and from 
  410. protected mode (difficult to do portably) or 2) use the BIOS calls
  411. to copy memory blocks to/from extended memory.  Most AT class (or
  412. better) machines should support the BIOS calls so that approach
  413. should be more portable.  Two library functions have been provided
  414. to call these BIOS functions properly.
  415.  
  416. int copy_from_extended( void far *destination, unsigned long source,
  417.             int words);
  418.  
  419.   Copy a block of memory from extended memory to conventional 
  420. memory.  The source address is an absolute address (number of bytes
  421. from the beginning of the precessors address space).  Note that
  422. this function moves words (ints) not bytes.
  423.  
  424. int copy_to_extended( unsigned long destination, void far *source,
  425.               int words);
  426.  
  427.   Copy a block of memory from conventional memory to extented 
  428. memory.  The destination address is an absolute address (number of 
  429. bytes from the beginning of the precessors address space).  Note that
  430. this function moves words (ints) not bytes.
  431.  
  432.  
  433. WRITING A DRIVER
  434.  
  435.   The best way to write a driver is probably to use an existing driver
  436. as a template.  Even if most of the adapter specific code has to be
  437. changed this will ensure that all the necessary routines have been
  438. written (and that all the conditions that are in effect have been
  439. taken into account).
  440.  
  441. COMPILING THE DRIVER
  442.  
  443.   The driver is compiled in a normal fashion using tcc.  It must be
  444. compiled in the tiny model and the floating point should be
  445. disabled.  The floating point should be disabled since the driver
  446. startup lacks the necessary hooks required to support the emulator. 
  447. See the makefile supplied for an example.
  448.  
  449.   Other than those two restrictions all the standard compiling options
  450. can be used.
  451.  
  452.   The link step is also very normal.  The startup used is C0CBGI.OBJ
  453. and the floating point emulation, math and graphics libraries should
  454. not be linked in.  The library CBGI.LIB contains the interface and
  455. helper routines used by the drivers.  
  456.  
  457.   After creating the tiny model driver use the utilities supplied in 
  458. Borland's BGI driver kit to create a driver from it.
  459.  
  460. DEBUGGING A DRIVER
  461.  
  462.   There are several ways to debug the code for a driver.  The first
  463. and easiest way is to write a shell program that calls the driver
  464. subroutines directly without putting them in a driver.  The advantage
  465. of this approach is that none of the debugging information is lost
  466. and the resulting code can be easily debugged with 'printf()'
  467. statements or with TD.  Although this approach works well for the
  468. initial debugging some bugs will only show up when the code is used to
  469. create an actual driver.  Other approaches have to be used to deal
  470. with that.
  471.  
  472.   The basic problem with debugging a driver is that all the debugging
  473. information normally available is lost.  Normal 'printf' functions no
  474. longer work since the C stdio library is not available.  The program
  475. can be followed from the higher level BGI calls through the BGI
  476. kernal and into the driver using TD but the overhead in doing so is
  477. enormous.  This is recommended only as a last resort.  The easiest way
  478. to bypass this overhead is to hard code a break-point interrupt
  479. (using say geninterrupt(3) into the driver at the point you wish to
  480. debug the driver.  An alternative is to write a low level I/O routine
  481. to perform the equivalent of 'printf()'.  If you have used the first
  482. debugging approach (shell program), then relatively little debugging
  483. should be left to do in this fashion.
  484.  
  485.   Of course all of this begs the question of where the output of the
  486. debugger or the print statments is going during all of this.  If you
  487. use TD it may work just fine recognize the switch to graphics mode
  488. itself.  The best approachs when using TD are either to use a second
  489. monitor or use TD's remote debugging facility. If you are using print
  490. statements then they may be redirected to any output device that is
  491. available.  TD is usually the easier approach.
  492.  
  493. LIMITATIONS ON THE USE OF C LIBRARY FUNCTIONS
  494.  
  495.   While a number of the C library functions can be used in drivers
  496. and are useful, care must be taken in deciding which ones can be
  497. used. None of the functions that use memory allocation or depend on
  498. information gained from DOS during program startup can be used.  This
  499. effectively eliminates most of the stdio functions.  Note that a
  500. number of functions have hidden dependancies on memory allocation. 
  501. Most of the machine specific functions (inport, outport, intr etc.)
  502. can be used.  You can use the library functions productively but keep
  503. an eye out for hidden pitfalls.
  504.  
  505. UNIVERSAL AUTODETECT
  506.  
  507.   Also included with this shell is an universal autodetection routine
  508. that allows a programmer to write a program to use any new drivers
  509. that will be written without having to know of their existance in
  510. advance.  This routine uses an enviroment variable (BGIDRIVER) to
  511. determine the driver and mode to use.  If the envoroment variable is
  512. not present then normal detection will be used.  The routine provides
  513. two ways to override this autodection.  First passing a driver_no
  514. other than DETECT will use the inicated driver.  In this case the
  515. detection routine acts just like 'initgraph()'.  Second the name of
  516. the user driver to be used can be passed to the routine directly.  The
  517. rest of the arguments to 'universal_initgraph()' are the same as
  518. those passed to 'initgraph()'.  The prototype of the routine is:
  519.  
  520. int universal_initgraph(    /* Initialize to (possible) user driver.*/
  521.     char *driver_name,    /* Name of user driver to use.        */
  522.     int  *driver_no,    /* Either DETECT (if autodetection is     */
  523.                 /*  wanted, or the # of the internal    */
  524.                 /*  driver to use.            */
  525.     int  *mode,        /* Mode to init driver to.        */
  526.     char *path        /* Path containing the driver.        */
  527.     );
  528.  
  529.   This routine may be used as is or as a template for another routine.
  530.  
  531. DRIVER COLLECTION & KIT AVAILABILITY
  532.  
  533.   This collection of BGI drivers and the CBGI library will be updated
  534. as I recieve drivers from other people who have created their own.  I
  535. will accept drivers that have been created with or without the
  536. assistance of this library.  I prefer that the source code be
  537. included but I will not insist upon it.  These submitted drivers will
  538. be distributed under the same restrictions that this library is
  539. (include all drivers if you include one & make this library easily
  540. available to those who wish it).  Additional restrictions may be 
  541. placed on the drivers by the authours.
  542.  
  543.   I will also make an effort to collect other PD BGI drivers.  They
  544. will be subject to the restrictions imposed by the original
  545. authours.  
  546.  
  547.   These additional drivers will be presented as is.  As I have a
  548. limited number of adapters available I cannot test many drivers.  I
  549. will accept comments about bugs or unusual behaviour in any of the
  550. drivers and attempt to pass them on to the original authours for
  551. fixes.  If fixes are sent I will also attempt to pass them along.
  552.  
  553.   If you wish a reply to any enquiry please enclose a SASE if mailing
  554. from CANADA or an International Reply Coupon if mailing from another
  555. country.  Please include the version number both of the library and
  556. the driver collection.  
  557.  
  558.   The most current version of the library and driver collection will
  559. be available from me for $10 (Canadian).  This cost is only meant to
  560. cover the cost of sending a copy to you.  Check the date on the
  561. collection you now have.  Since I am not keeping any drivers out of
  562. the distribution if the date is recent it is probably not worth your
  563. money or my time simply to provide you with what you already have.
  564.  
  565.   The Borland BGI kit that provides the documentation on the BGI
  566. driver and utilities for creating them from '.com' files (which are
  567. necessary for using this library) are available from you local BBS or
  568. from Borland directly.  I will NOT act as a source for them.
  569.  
  570.                 Robert Adsett
  571.                    Apt. 2b 
  572.               174 Moore Ave. S.
  573.               Waterloo, Ontario, Canada
  574.                    N2J 1X6
  575.