home *** CD-ROM | disk | FTP | other *** search
- BGI-TEST and CHR-TEST were written by Sam Denton, St. Louis, MO,
- CompuServ ID 76314,1512.
-
- The programs and this documentation are Copyright 1988 by Sam Denton,
- all rights reserved. Private use is permitted, otherwise call me.
- (My rates are reasonable, and/or you can hire me if you like my code.)
-
- ----------------------------------------------------------------------------
-
- NOTE/WARNING:
-
- If, like me, you make the .BGI and .CHR files ReadOnly, you should insert
- "System.FileMode := 0;" before calling InitGraph. I spent an entire night
- tracing the code before I realized what I had done to myself.
-
- ----------------------------------------------------------------------------
-
- BGI-TEST.PAS
-
- To use with DOS DEBUG, try "DEBUG C:\TP4\TURBO.EXE C:\MYPGMS\BGI-TEST.PAS".
- At the DEBUG prompt, enter the "G" command. BGI-TEST will stop of its own
- volition at the start of the .BGI driver if you remove the "$" from the
- "{$define trace}" at the start of the program. Use the "RIP" command to
- manually advance the program counter past the "INT 3" instruction.
-
- All .BGI files start with a 2 byte signature = 'pk' (checked for by code in
- the Graph unit), followed by two backspace characters. For comparison, .CHR
- files start with 'PK', and are otherwise similar. BTW, I presume that 'pk'
- is Philipe Kahn, and the backspaces are so you can TYPE the files and be
- able to read the comments without seeing the 'pk'. Then comes free-form
- ASCII comments ending in Ctrl-Z, then:
- dw offset within file to the start of code
- dw driver id, a value from 0 to 5,
- 0=CGA, 1=EGA/VGA, 2=reserved(?), 3=Hercules, 4=AT&T, 5=PC3270
- dw size of just the code, NOT the entire file
- db a non-zero value
- db zero
- db either 0 or 1
- db dup(0) until start of code
-
- GRAPH normally does a FAR CALL to the start-of-code address (normalized so
- that the offset is 0) with a value in SI determining the type of call.
- The value is always even, so the driver may use it to index a branch-table.
-
- All numbers from here on are given in HEXADECIMAL, and all offsets are
- taken from CGA.BGI and are relative to start-of-code.
-
- org 0111
- dw ? ; cp.x
- dw ? : cp.y
-
- BitBlt code is at 0EAC, it is invoked at 0F60, it is really weird stuff.
-
- In the following table, for each legal value of SI is shown the offset into
- the driver's code of the routine. Also, if there seems to be a direct
- correspondence between the routine and a GRAPH entry point, the name of the
- entry point and how the arguments are passed is shown. Some GRAPH calls
- turn into a pair of calls, first a MoveTo to set the X and Y parameters,
- then a call to pass the rest of the parameters. In this case, the first
- two parameters are shown as CP.X and CP.Y. During InitGraph, the driver
- gets a CALL FAR instruction stuffed into offset 0010. The CALL FAR points
- back into GRAPH and will execute many complicated "primitives" by doing
- recursive calls back into the driver. This means that if you write your
- own graphic device driver, you don't have to write 'hard' routines.
-
- si addr name (if any), args :- results
- -- ---- ------------------------------
- 00 01D7 AL=1 :- CX=nbr of modes?
- AL=2,CL=mode :- [ES:BX]=string(name of mode)
- AL=?,CL=mode :- [ES:BX]=descriptor table, other stuff happens
- 02 0231 :- set graphics hardware to mode
- 04 0248 ClrScr?
- 06 0015 ?No Operation
- 08 0297 MoveTo(AX,BX)
- 0A 029F LineTo(AX,BX)
- 0C 02B3 Line(AX,BX,CX,DX)
- 0E 0010* Do Polygon [ES:BX]=point list, CX=nbr pts, ?=draw or fill
- 10 0010* Bar3D(cp.x,cp.y,AX,BX,CX,DX)
- 12 07FE* Bar(AX,BX,CX,DX)
- 14 0010* Ellipse(cp.x,cp.y,AX,BX,CX,DX)
- (this entry point is also used by Arc and Circle)
- 16 0010* PieSlice(cp.x,cp.y,AX,BX,CX)
- 18 0015 ?No Operation
- 1A 00BD SetBkColor(BX)
- 1C 00DE ?SetColor(BX)
- 1E 0286 SetColor, AL=AH=color
- 20 00E3*?SetFillStyle/Pattern, AL=pattern nbr, or if FF then [ES:BX]=pattern
- 22 03D2 SetLineStyle(AX,BX,CX)
- 24 0398* SetTextStyle AL=direction, BX=8*scale, CX=8*scale
- When AH has bit 80 on, DX is also significant
- 26 035C* OutText @ CP, [ES:BX]=string, CX=length
- 28 00FD* TextSize [ES:BX]=string, CX=length :- BX=width, CX=height in pixels
- 2A 0015 ?No Operation
- 2C 009F FloodFill(AX,BX,CX)
- 2E 0FDC GetPixel(AX,BX) :- DX
- 30 0FF5 PutPixel(AX,BX,DL)
- 32 006C really strange, see below
- 34 0084 GetImage CX=x1,DX=y1,[ES:BX]=image(dx,dy,dup(?))
- 36 0099 PutImage AL=BitBlt,CX=x,DX=y,[ES:BX]=image(dx,dy,data...)
- 38 0050 SetViewport(AX,BX,CX,DX)
-
- SI=32 returns [ES:BX] pointing to a table of offsets into the code that GRAPH
- uses as additional entry points. The code GRAPH uses is kludgy, but the net
- effect is to simulate CALL [ES:[ES:BX+n]]. There are only 6 entries and
- most of them point to RETF instructions, but [ES:BX+8] will return the number
- of bits per pixel in the current graphics mode. However, in EGAVGA.BGI only,
- [ES:BX+0A] does some sort of segment arithmetic involving display memory. In
- any event, SI=32 is used by GetImageSize and SetActivePage
-
- When InitGraph is called, GRAPH calls the device driver seventeen times with
- SI= 00, 02, 24, 38, 08, 1E, 1E, 1E, 1E, 20, 24, 1E, 1E, 20, 22, 24, and 08,
- and only Frank Borland knows why. SetGraphMode issues the same sequence of
- calls. Also, when LineTo or LineRel is called, GRAPH calls SI=08 (MOVE! to a
- new place), SI=0A (draw a line to the OLD! point), SI=08 (move back to new
- point), even though a single call to SI=0A (draw a line to the new point)
- would have the same net effect. OutText and OutTextXY both call SI=08 TWICE
- in succession with IDENTICAL arguments before writing out the string. I
- guess they want to be absolutely certain the text lands in the right place.
- (As nearly as I can tell, both GRAPH and the .BGI drivers maintain their own
- copies of the current position, but the copy in the driver is used to pass
- positioning data when Bar3D, Arc, PieSlice, etc. are called. Only the
- current position kept by GRAPH matches the documentation.)
-
- (P.S. If, like me, you make the .BGI files ReadOnly, you should insert
- "System.FileMode := 0;" before calling InitGraph. I spent an entire night
- tracing the code before I realized what I had done to myself.)
-
- ----------------------------------------------------------------------------
-
- CHR-TEST.PAS
-
- All .CHR files start with a 2 byte signature = 'PK' (checked for by code in
- the Graph unit), followed by two backspaces (which are not checked anywhere).
- For comparison, .BGI files start with 'pk', and are otherwise similar. Then
- comes free-form ASCII comments ending in Ctrl-Z, then:
- dw offset within file to the start of descriptors
- db driver id, four characters
- GOTH=gothic, LITT=small, SANS=sans serif, TRIP=triplex
- dw size of just the code, NOT the entire file
- db one
- db zero
- db one
- db dup(0) until start of descriptors
-
- Within the descriptors, first is a ten byte area laid out as:
- db unknown, apparently alway $2B
- dw number of characters defined
- db unknown, apparently alway zero
- db the first character drawable with this character set
- (usually blank ($20))
- dw offset to table of plot commands
- db unknown, apparently alway zero
- db Y value of top of character cell (shortint)
- db unknown, apparently alway zero
- db Y value of bottom of character cell (shortint, usually negative)
- db 5 bytes, unknown, apparently alway zero
-
- Next is an array of words pointing to the plot commands:
- dw 0,4,... ; offset to blank, exclaimation point, ...
-
- Thirdly is an array of bytes containing the widths of each character:
- db 6,3,... ; width of blank, exclaimation point, ...
-
- Finally come the plot commands. Each consists of 16 bits broken into several
- fields. The high order bit ($80) from both bytes are used to decide what to
- do. The cases are (expressed in binary):
- 1xxxxxxx 0yyyyyyy -- move to (x,y)
- 1xxxxxxx 1yyyyyyy -- line to (x,y)
- 0xxxxxxx 0yyyyyyy -- done, (x,y) is ignored
- 0xxxxxxx 1yyyyyyy -- no operation, (x,y) is ignored
- The remaining seven bits of each byte are two's complement numbers. Each
- character is drawn within a box with the leftmost portion and the base of
- the image lying on the y and x axii, respectively. Lower-case descenders
- and some punctuation will drop below the x axis.
-
- The first data area is of fixed size at the start of the 'segment', so
- addressing it is no problem, and the second data is also easy to address,
- although it is of variable size. The third and fourth areas are more
- problematical. To calculate the offset of the third area, use the formula
- 2*(number of characters defined) + 16, and then index to the needed byte.
- To find the plot commands in the fourth area for a given character, c, use
- 2*(ord(c) - (first char defined)) + 16 to get the offset of a word whose
- value is then added to the offset of the table of plot commands. See the
- program for examples of Pascal code. It's actually somewhat easier to do in
- assembler (or C), however.