home *** CD-ROM | disk | FTP | other *** search
/ Garbo / Garbo.cdr / pc / source / bgi.src < prev    next >
Encoding:
C/C++ Source or Header  |  1989-05-12  |  46.2 KB  |  2,186 lines

  1.  
  2. /* 
  3. The following software can be used and modified freely.  I can not
  4. however be sold in any way.  This includes both seperately and 
  5. compiled into programs.
  6.  
  7. The following is the work I have done on creating .BGI driver
  8.    files for TURBO-C 2.0 and TURBO PASCAL.  Although the majority
  9.    of the functions work and can be used as is, it is by no means a
  10.    complete .   My main reason for posting this is so that people
  11.    who want to create their own BGI drivers have a good starting point
  12.    and a good example to follow.  The routines that to block fills/reads
  13.    have been written a little trickier than need be. This was to make
  14.    them fast enough to be usable (the tricks are somewhat described
  15.    in the code where they are used).  
  16.  
  17.    The two main ingredients that went into this were:
  18.     1. A skeleton of a BGI header which was posted to the net
  19.         sometime ago.
  20.     2. The book "Graphics Programming in Turbo-C 2.0" written
  21.        by Ben Ezzell and published by Addison-Wesley. I found
  22.        it a B-Dalton.  This book is almost a must if you hope
  23.        to write a BGI driver.
  24.  
  25.    I will help answer questions (at least until I get tired of it).
  26.    Mainly I will look gather up all the commo questions and post
  27.    them to the net.
  28.  
  29.    I also want to make it clear that I am basically a High level
  30.    language programmer and had to learn Assembly as I went to 
  31.    write this.  Therefor, I DONT want to here any comments about
  32.    my poor assembly language programming style.
  33.  
  34.    REMEMBER, THIS IS MAINLY INTENDED AS A DEVELOPEMENT EXAMPLE
  35.    AND IS NOT INTENDED TO BE A RELEASED PRODUCT ( although almost
  36.    all of the functions do work for this graphics card ).
  37.  
  38. ======================= CUT APART HERE AND NAME BGITEST.C ===========
  39. /*
  40.  
  41.     This is a real hack of a demo program but it at least shows you
  42.     what your C program must do to install and use a user-written
  43.     device driver.  I had most of the BORLAND SUPPLIED bgidemo.c
  44.     program working after I took out their palette demo routine
  45.     and change the program to use another font other than DEFAULT
  46.     ( which I could not make work ).  I didn't post I because I 
  47.     was afraid BORLAND could bust me for posting it.
  48.     
  49. */
  50.  
  51.  
  52.  
  53. #include <graphics.h>
  54. #include <stdlib.h>
  55. #include <stdio.h>
  56.  
  57. int huge detectLEEVGA(void);
  58.  
  59.  
  60. main()
  61. {
  62.  
  63.     int driver, mode;
  64.     int ysize, xsize;
  65.     int i;
  66.  
  67.  
  68. driver =installuserdriver ("LEEVGA", detectLEEVGA);
  69.  
  70.  
  71.     {
  72.     int ec;
  73.     if ((ec=graphresult()) < 0)  {
  74.         printf("unable to register\n");
  75.         printf("reason <%s>\n", grapherrormsg(ec));
  76.         exit(-1);
  77.         return(-1);
  78.     }
  79.     }
  80.  
  81.  
  82.  driver = DETECT;
  83.     initgraph(&driver, &mode, "");
  84.  
  85.     {
  86.     int ec;
  87.     if ((ec=graphresult()) < 0)  {
  88.         printf("unable to open this graphics mode\n");
  89.         printf("reason <%s>\n", grapherrormsg(ec));
  90.         exit(-1);
  91.         return(-1);
  92.     }
  93.     }
  94.  
  95.  
  96. printf("  max x=       %d\n",    xsize=getmaxx());
  97. printf("  max y=       %d\n",    ysize=getmaxy());
  98. printf("  modename=    %s\n", getmodename(0));
  99. printf("  drivername=  %s\n", getdrivername());
  100. printf("  maxcolors=   %d\n", getmaxcolor());
  101. printf("  palette size=%d\n", getpalettesize());
  102.  
  103.  
  104. #define DO 1
  105. #ifdef DO
  106.     setfillstyle ( SOLID_FILL, 15 );
  107.     setcolor ( 12 );
  108.  
  109.     outtextxy(xsize/6,ysize/3,"A b C d E f G h I J k"); getch();
  110.     printf("  Outtext  ( DEFAULT FONT )  is done\n"); getch();
  111.  
  112.     settextstyle(TRIPLEX_FONT,HORIZ_DIR,4);
  113.     outtextxy(xsize/6,ysize/4,"0 1 2 3 4 5 6 7 8 9 0");
  114.     printf("  Outtext  ( TRIPLEX_FONT )  is done\n"); getch();
  115.  
  116. setlinestyle(DASHED_LINE,0,NORM_WIDTH);
  117.  
  118.  for (i=10; i < xsize/3*2 ; i++) {
  119.     putpixel(i,ysize/4,12);
  120. }
  121. printf("  pixel puts are done, press a key\n");getch();
  122.  
  123. #endif
  124.  
  125. setfillstyle ( SLASH_FILL, 11 );
  126. setlinestyle(DASHED_LINE,0,NORM_WIDTH);
  127.  
  128. pieslice(xsize/2,ysize/2,45,45+90,ysize/3);
  129.  
  130.  
  131. circle (xsize/2, ysize/2,ysize/2);
  132. ellipse(xsize/2,ysize/2,0,0,100,100);
  133. printf("  circle done press a key\n");getch();
  134.  
  135. setlinestyle(CENTER_LINE,0,NORM_WIDTH);
  136. line (  10,ysize/2,ysize-100,ysize/2);
  137. line ( xsize/2, 10 , xsize/2 , ysize/2 );
  138. printf("  lines done, press a key\n");getch();
  139.  
  140. rectangle (10,20,xsize/6,ysize/2);
  141. printf("  rectangle done, press a key\n");getch();
  142.  
  143.  
  144. setlinestyle(DOTTED_LINE,0,THICK_WIDTH);
  145.  
  146. setfillstyle ( XHATCH_FILL, 21 );
  147. setcolor(83);
  148. bar3d ( xsize/2,ysize/2,  xsize/6*5,ysize, 50, 1);
  149. printf("  bar is done, press a key\n");getch();
  150. setlinestyle(DASHED_LINE,0,NORM_WIDTH);
  151.  
  152.  
  153. {
  154.     int pp[10]={100,100, 100,150, 180,195, 300,150, 330,100};
  155.  
  156. setfillstyle ( CLOSE_DOT_FILL, 11 );
  157.  
  158. fillpoly ( 5 , &pp );
  159. printf("  filled polygon is done, press a key\n");getch();
  160. }
  161.  
  162.  
  163.  
  164.  
  165. setrgbpalette(12,1,2,3);
  166.  
  167. {
  168. typedef struct {
  169.     char r,g,b;
  170. } entry;
  171.  
  172. struct p {
  173.     char size;
  174.     entry index[256];
  175. } palette;
  176.  
  177. palette.size = 3*256;
  178. palette.index[0].r =1;
  179. palette.index[0].g =2;
  180. palette.index[0].b =3;
  181.  
  182.  
  183. setallpalette(&palette);
  184. }
  185.  
  186.  
  187.  
  188.  
  189.  cleardevice();
  190.  printf("  clear done\n");
  191.  
  192.  
  193.  printf("  press a key\n");getch();
  194.  closegraph();
  195.  
  196. }
  197.  
  198.  
  199.  
  200.  
  201. /* ______________________ */
  202.  
  203. int huge detectLEEVGA(void)
  204. {
  205.  
  206.     printf("detecting\n");
  207.     
  208.     /*
  209.         You must write code here to detect whether or not
  210.         the graphics card is available and what its maximum mode
  211.         is.  By returning the value of ONE here, I am telling 
  212.         it I have detected my graphics card and the mode I want 
  213.         it to use is ONE.
  214.         
  215.     */    
  216.  
  217.     return(1);
  218. }
  219.  
  220. ======================== CUT APART HERE and NAME IT LEEVGA.ASM ==========
  221.  
  222. ; know problems
  223. ;    1. the default font has not been done.
  224. ;    2. flood fill has not been done.
  225.  
  226. ; to compile (create) the .BGI file use the following
  227.  
  228. ; masm leevga.asm leevga.obj NUL.LST NUL.LST
  229. ; link leevga.obj,leevga.exe,NUL.MAP,.LIB
  230. ; exe2bin leevga.exe leevga.bgi
  231. ; del leevga.exe
  232. ; del leevga.obj
  233.  
  234.  
  235. ;------------------------------------------------------;
  236. ;               LEEBGI.BGI                             ;
  237. ;     Borland Graphic Interface for TP 5.0, TC2.0      ;
  238. ;       Paridise VGA Graphics Board                    ;
  239. ;         Copyright (c) 1989 Gene W. Lee               ;
  240. ;------------------------------------------------------;
  241. ;
  242. ACODE       segment  'BGI'
  243. ;
  244. ;
  245. astart      DB      'pk'  ; BGI magic word (Phillipe K.)
  246.             DB      8,8
  247.             DB      'BGI Device Driver V1.0 Gene W. Lee - 1989 '
  248.             db      0Dh,0Ah
  249.             DB      'Copyright (c) 1989 Gene W. Lee',0Dh,0Ah
  250.             db      0,1Ah
  251.             dw      00A0h,11
  252.             dw      endofcode  ; This is a label that precedes CODE ENDS
  253.             dw      2
  254.             db      1,1
  255.             org     80h
  256.             dw      00A0h,11
  257.             dw      endofcode  ; see above
  258.             dw      2
  259.             db      1,1
  260.  
  261. ;    The following is returned by GetDriverName.
  262.             db      6,'LEEVGA'
  263. alen        =       $-astart              ; Pad this segment out to
  264.             db      (160 - alen) dup(0)   ; 160 bytes
  265. ACODE       ends
  266.  
  267. CODE        SEGMENT 'BGI'
  268. ;
  269. ; Now for the real BGI driver code. A separate segment is required
  270. ; because although this code starts at offset 0A0h in the file
  271. ; ATTDEB.BGI, GRAPH will adjust its address up by 10 paras and then
  272. ; do a CALL FAR xxxx:[0000]. So all memrefs have to be 0 relative to
  273. ; the label BGIENTRY below.  IMPORTANT: All code from here to JMP_TABLE
  274. ; needs to be exactly as it is.  GRAPH expects the label EMULATE to be
  275. ; at the offset that it is in this code (GRAPH is going to shove code
  276. ;
  277.             ASSUME  CS:CODE,DS:CODE,ES:CODE
  278. BGIENTRY    PROC    FAR        ; "FAR" So that the RET is a RETF
  279.             PUSH    DS
  280.             PUSH    CS
  281.             POP     DS
  282.             CLD
  283.             PUSH    BP
  284. ;
  285. ; The Function number to be performed in SI.  SI is used to index into
  286. ; a jump table.  Note: all SI values are even.
  287. ;
  288.             CALL    [SI+JMP_TABLE]  ; See JMP_TABLE
  289.             POP     BP
  290.             POP     DS
  291.             RET
  292. BGIENTRY    ENDP
  293. ;
  294.             db      'CB'        ; ?
  295.             dw      0
  296. ;
  297. EMULATE      PROC NEAR          ; This is the entry point of functions
  298.             RET                 ; you want Turbo XX to emulate.  Note:
  299.             dw      0           ; only select entries may be emulated.
  300.             dw      0
  301. EMULATE      ENDP
  302.  
  303. NOP_02      PROC NEAR           ; This is the entry point for all functions
  304.             RET                 ; which are not implemented.
  305. NOP_02      ENDP
  306.  
  307. ; Now for the Jump Table; The SVC_xx labels correspond to the
  308. ; value in SI when the driver is called(ie: SVC_00 is the entry point
  309. ; when SI = 0.  IF the labels are EMULATE or NOP_02 the value of SI is
  310. ; to the right in braces.  NOP_02 means this function is a NOP and
  311. ; GRAPH should never call it (at least relative to TP5).  The label
  312. ; EMULATE is a JMP to a CALL back to GRAPH to perform the function.
  313. ; (Aren't you glad you don't have to write a Circle Drawing Algorithm!)
  314. ;
  315. ; It should also be noted that calls to the BGI code are both pre-
  316. ; processed  and post-processed by GRAPH.  Some calls never make it to
  317. ; your code. One example is the DisplayText functions.  The only time
  318. ; that calls make it here is for the bit-map text displays.  GRAPH
  319. ; handles all of the stroked CHR fonts.
  320. ;
  321. jmp_table    dw install          ; {0} Initialize
  322.             dw init              ; {2} Set Mode
  323.             dw clear            ; {4} Clear Graphics Screen
  324.             dw nop_02            ; {06} POST
  325.             dw move                ; {8} current pointer (CP)
  326.             dw draw                ; {A} draw line from CP to new CP
  327.             dw vect                ; {C} Draw Line
  328.             dw EMULATE            ; {0E} Draw/Fill Poly
  329.             dw emulate            ; {10} Bar3D
  330.             dw patbar               ; {12} pattern Bar
  331.             dw EMULATE            ; {14} Draw Circle
  332.             dw EMULATE            ; {16} Draw Pie Slice
  333.             dw EMULATE            ; {18} Draw Ellipse
  334.             dw palette          ; {1A} Set Palette
  335.             dw SVC_1C  ; {1C} Set All Palette
  336.             dw color            ; {1E} Set Color
  337.             dw fillstyle        ; {20} Set Fill Style/Pattern
  338.             dw linestyle        ; {22} Set Line Style/Pattern
  339.             dw textstyle          ; {24} Set UserCharSize
  340.             dw text                ; {26} Display Text
  341.             dw textsize            ; {28} Text Width/Height
  342.             dw EMULATE            ; {2A}   ; I never figured this one out !
  343.             dw flood_fill        ; {2C} FloodFill
  344.             dw get_pixel        ; {2E} GetPixel
  345.             dw put_pixel        ; {30} SetPixel
  346.             dw bitmaputil        ; {32} Set CallTable
  347.             dw get_image        ; {34} GetImage
  348.             dw put_image        ; {36} PutImage
  349.             dw set_clip            ; {38} Set View Min/Max
  350.             dw color_query        ; {3A} SetParameters
  351.             dw emulate          ; {3C} reserved
  352.             dw EMULATE          ; {3E} symbol
  353.  
  354.             dw NOP_03           ; 40
  355.             dw NOP_03           ; 42
  356.             dw NOP_03           ; 44
  357.             dw NOP_03           ; 46
  358.             dw NOP_03           ; 48
  359.             dw NOP_03           ; 4A
  360.             dw NOP_03           ; 4C
  361.             dw NOP_03           ; 4E
  362.             dw NOP_03           ; 50
  363.             dw NOP_03           ; 52
  364.             dw NOP_03           ; 54
  365.             dw NOP_03           ; 56
  366.             dw NOP_03           ; 46
  367.             dw NOP_03           ; 48
  368.             dw NOP_03           ; 4A
  369.             dw NOP_03           ; 4C
  370.             dw NOP_03           ; 4E
  371.             dw NOP_03           ; 50
  372.             dw NOP_03           ; 52
  373.             dw NOP_03           ; 54
  374.             dw NOP_03           ; 56
  375.             dw NOP_03           ; 46
  376.             dw NOP_03           ; 48
  377.             dw NOP_03           ; 4A
  378.             dw NOP_03           ; 4C
  379.             dw NOP_03           ; 4E
  380.             dw NOP_03           ; 50
  381.             dw NOP_03           ; 46
  382.             dw NOP_03           ; 48
  383.             dw NOP_03           ; 52
  384.             dw NOP_03           ; 54
  385.             dw NOP_03           ; 56
  386. ;
  387.  
  388. NOP_03      PROC FAR                 ; stub procedure for far returns
  389.             RET
  390. NOP_03      ENDP
  391.  
  392.  
  393. ;
  394.  
  395. ;                     structure for 320x200 256 color mode
  396. statustype0    struc
  397.         db    0         ;  current device status
  398.         db    0        ;  device type identifier ( must be zero )
  399.         dw    319        ;  full resolution in the x direction
  400.         dw    199        ;  full resolution in the y direction
  401. xefres0 dw    319        ;  effective resolution in x direction
  402.         dw    199        ;  effective resolution in y direction
  403.         dw    9000    ;  device x size in inches * 1000
  404.         dw    7000    ;  device y size in inches * 1000
  405.         dw    8572    ;  aspect ratio = ( ysize / xsize ) * 1000
  406.                     ;  next four bytes are for compatibilty
  407.         db    8h
  408.         db    8h
  409.         db    90h
  410.         db    90h
  411. statustype0    ends
  412.  
  413. status0    statustype0<>
  414.  
  415. ;                    structure for 640x400 256 color mode (0x5E)
  416. statustype1    struc
  417.         db    0         ;  current device status
  418.         db    0        ;  device type identifier ( must be zero )
  419.         dw    639        ;  full resolution in the x direction
  420.         dw    399        ;  full resolution in the y direction
  421. xefres1    dw    639        ;  effective resolution in x direction
  422.         dw    399        ;  effective resolution in y direction
  423.         dw    9000    ;  device x size in inches * 1000
  424.         dw    7000    ;  device y size in inches * 1000
  425.         dw    8572    ;  aspect ratio = ( ysize / xsize ) * 1000
  426.                     ;  next four bytes are for compatibilty
  427.         db    8h
  428.         db    8h
  429.         db    90h
  430.         db    90h
  431. statustype1    ends
  432.  
  433. status1    statustype1<>
  434.  
  435. active_mode db    ?     ;  the currently active mode number
  436.  
  437. modestring0    db  18,'320 x 200 VGA Mode',0
  438. modestring1    db  18,'640 x 400 VGA Mode',0
  439.  
  440. xsize    dw    ?         ; the xsize of the currently selected mode
  441. max_x    dw    ?          ; the maximum value of x for the current mode
  442.  
  443.  
  444.  
  445. ;        table for ellipse function calls
  446. ;  Let it used my put_pixel routine, there is not much I could do to speed
  447. ;  up pixel writing anyway.
  448. the_util_table    dw offset NOP_03        ; enter pixel mode
  449.                 dw offset NOP_03        ; Leave pixel mode
  450.                 dw offset NOP_03           ; write a pixel
  451.                 dw offset NOP_03        ; get a pixel
  452.                 dw offset bitsperpixel        ; return bits per pixel in AX
  453.                 dw offset NOP_03        ; set draw page
  454.                 dw offset NOP_03        ; set visual page
  455.                 dw offset NOP_03        ; set xor mode
  456.  
  457. enter_pixel_mode proc far
  458.     call unlock_vga
  459.     mov doing_ellipse,1
  460.     ret
  461. enter_pixel_mode endp
  462.  
  463. exit_pixel_mode proc far
  464.     call lock_vga
  465.     mov doing_ellipse,0
  466.     ret
  467. exit_pixel_mode endp
  468.  
  469. bitsperpixel proc far
  470.     mov ax,8              ; eight bits per pixel in VGA mode
  471.     ret
  472. bitsperpixel endp
  473.  
  474.  
  475.  
  476.                                 ; the bit patterns for default linestyles
  477. default_linestyles    dw    0FFFFh  ; SOLID_LINE
  478.                     dw    0CCCCh    ; DOTTED_LINE
  479.                     dw    0FC78h    ; CENTER_LINE
  480.                     dw    0F8F8h    ; DASHED_LINE
  481.  
  482. active_linestyle    dw    0FFFFh    ; the currently selected line style is written
  483.                                 ; into this word.
  484. line_bit_ptr        db    0        ; pointer into linestyle word (bit ptr)
  485.  
  486.  
  487. default_fillpaterns db    000h,000h,000h,000h,000h,000h,000h,000h ; No Fill
  488.     db  0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh ; Solid fill
  489.     db  0FFh,0FFh,000h,000h,0FFh,0FFh,000h,000h ; Line FIll
  490.     db  001h,002h,004h,008h,010h,020h,040h,080h ; Lt Slash fil
  491.     db  0E0h,0C1h,083h,007h,00Eh,01Ch,038h,070h ; Slash fill
  492.     db  0F0h,078h,03Ch,01Eh,00Fh,087h,0C3h,0E1h ; Backslash
  493.     db  0A5h,0D2h,069h,0B4h,05Ah,02Dh,096h,04Bh ; lt Backslash
  494.     db  0FFh,088h,088h,088h,0FFh,088h,088h,088h ; Hatch Fill
  495.     db  081h,042h,024h,018h,018h,024h,042h,081h ; XHatch Fill
  496.     db  0CCh,033h,0CCh,033h,0CCh,033h,0CCh,033h ; interleave
  497.     db  080h,000h,008h,000h,080h,000h,008h,000h ; Wide Dot
  498.     db  088h,000h,022h,000h,088h,000h,022h,000h ; Close Dot
  499.  
  500. active_fillpattern    db    ?,?,?,?,?,?,?,?     ; the currently selected fill
  501.                                           ; style is written into this array.
  502. fill_byte_ptr        dw  ?       ; pointer to fill pattern byte
  503. fill_bit_ptr        dw  ?        ; pointer to bit of fill pattern byte
  504.  
  505.  
  506.  
  507.  
  508. ;  I don't really understand what this is all about. I just tell it I don't
  509. ;  have a default color table
  510. color_table db    0
  511.  
  512. current_background_color  db ?
  513. current_line_color    db    ?    ; the currently selected color for lines
  514. current_fill_color    db  ?   ; the currently selected fill color
  515. cp_x                dw    ?   ; the current pointer - x
  516. cp_y                dw    ?   ; the current pointer - y
  517. clip_x1                dw    ?   ; clipping window
  518. clip_y1                dw    ?   ; clipping window
  519. clip_x2                dw    ?   ; clipping window
  520. clip_y2                dw    ?   ; clipping window
  521.  
  522.  
  523. ; start x,y and end x,y for line draws
  524. x1    dw    ?
  525. y1    dw    ?
  526. x2    dw    ?
  527. y2    dw    ?
  528.  
  529. ; vars used by line draw routine
  530. delta_x    dw    ?
  531. delta_y    dw    ?
  532. count    dw    ?
  533. halfx    label word          ;   only need halfx or halfy at one time
  534. halfy    dw    ?
  535.  
  536. ; vars used to do pixel read/writes in VGA mode
  537. lasthio dw -1         ; keeps track of the last hioffset value calculated
  538. next_row    dw  ?     ; variable used by patbar, getimage and putimage
  539.  
  540. ; vars used by palette routines
  541. red   db ?
  542. green db ?
  543. blue  db ?
  544.  
  545. doing_ellipse db 0        ; set true when unlock has been called to start
  546.             ; drawing an ellipse. Saves time on ellipse draws
  547.  
  548.  
  549.  
  550. ; 0 ----------------------------------------------------------------------
  551.  
  552. ; if al=0       ( install device )
  553. ;     input:  cl = mode number for device
  554. ;         ch = autodetect maximum device number
  555. ;     return: es:bx = pointer to device status table
  556. ; if al=1       ( mode query )
  557. ;     input: nothing
  558. ;     return: cx = number of modes supported by this device
  559. ; if al=2       ( return mode name )
  560. ;     input cx: the mode number for query
  561. ;     return es:bx = pointer to PASCAL string containing the name
  562.  
  563. install:
  564.         cmp al,0
  565.         jz     installit
  566.         cmp    al,1
  567.         jz    modequery
  568.  
  569.         ; else it must be a modename() call
  570.         push cs
  571.         pop es
  572.         cmp cx,0
  573.         je  modename0
  574.         mov bx, offset modestring1         ; return pointer to mode name
  575.         ret
  576.  
  577. modename0:
  578.         mov bx, offset modestring0         ; return pointer to mode name
  579.         ret
  580.  
  581. installit:
  582.         mov active_mode,cl      ; remember what mode were in
  583.         cmp cl,1
  584.         je install_mode1
  585.                            ; else we install mode 0
  586.                ; keep track of current x and y screen size
  587.         mov ax,status0.xefres0 
  588.         mov max_x,ax
  589.         inc ax
  590.         mov xsize,ax
  591.  
  592.         push cs
  593.         pop es
  594.         mov bx,offset status0   ; return location of status table
  595.         ret
  596.  
  597. install_mode1:
  598.         mov ax,status1.xefres1      ; keep track of current x and y screen size
  599.         mov max_x,ax
  600.         inc ax
  601.         mov xsize,ax
  602.  
  603.         push cs
  604.         pop es
  605.         mov bx,offset status1   ; return location of status table
  606.         ret
  607.  
  608. modequery:
  609.         mov cx,2        ; only two modes supported for now
  610.         ret
  611.  
  612. ; 2 ----------------------------------------------------------------------
  613.  
  614. ; input:
  615. ;     es:bx = pointer to device table
  616. ; return: nothing
  617.  
  618. init:
  619.         cmp active_mode,1
  620.         je init_mode1
  621.                         ; else we init mode 0
  622.         mov ax,13h
  623.         int 10h
  624.  
  625.         ret
  626.  
  627.  
  628. init_mode1:
  629.         mov ax,5Eh
  630.         int 10h
  631.  
  632.         ret
  633.  
  634.  
  635. ; 4 ----------------------------------------------------------------------
  636.  
  637. ; input: nothing
  638. ; output: nothing
  639. ;            clear the device
  640.  
  641. clear:
  642.         call init
  643.         ret
  644.  
  645.  
  646. ; 8 ------------------------------------------------------------------------
  647.  
  648. ; input:
  649. ;    ax = the new CP x coord
  650. ;    bx = the new CP y coord
  651. ; return: nothing
  652. move:           ; set current pointer (CP)
  653.  
  654.                 ; load the new current pointer
  655.         mov cp_x,ax
  656.         mov cp_y,bx
  657.         ret
  658.  
  659.  
  660.  
  661. ; A -----------------------------------------------------------------------
  662.  
  663. ;        draw line from CP to x,y
  664. ; input:
  665. ;    ax: ending x coord
  666. ;    bx: ending y coord
  667. ; output:
  668. ;    nothing
  669.  
  670. draw:                     ; draw line from CP to new CP
  671.  
  672.         push cx
  673.         mov cx,cp_x         ; draw starts at current position (cp)
  674.         mov x1,cx
  675.         mov    cx,cp_y
  676.         mov    y1,cx
  677.         pop cx
  678.  
  679.         mov x2,ax           ; load the end points
  680.         mov y2,bx
  681.  
  682.         mov    cp_x,ax            ; end points are now new current points
  683.         mov    cp_y,bx
  684.  
  685.         mov line_bit_ptr,0  ; reset the line style
  686.  
  687.         call draw_line        ; draw the line from x1,y1 to x2,y2
  688.  
  689.         ret
  690.  
  691.  
  692. ; C ----------------------------------------------------------------------
  693.  
  694. ; draw line from x1,y1 to x2,y2
  695.  
  696. ; input:
  697. ;    ax = x1
  698. ;    bx = y1
  699. ;    cx = x2
  700. ;    dx = y1
  701. ; output:
  702. ;    nothing
  703.  
  704. vect:                        ; Draw Line
  705.  
  706.                             ; setup the start and end points
  707.         mov    x1,ax
  708.         mov    y1,bx
  709.         mov    x2,cx
  710.         mov    y2,dx
  711.  
  712.         mov line_bit_ptr,0  ; reset the line style
  713.  
  714.         call draw_line        ; draw a line
  715.  
  716.         ret
  717.  
  718.  
  719.  
  720.  
  721.  
  722. ; 1A --------------------------------------------------------------------
  723.  
  724. ; set a single palette entry
  725. ; input:
  726. ;    ax = the index number to load
  727. ;    bx = the color value
  728. ; return: nothing
  729.  
  730. palette:
  731.  
  732.         push ax
  733.         push cx
  734.  
  735.         mov cl,14
  736.         shr ax,cl         ; only want upper to bits of cl
  737.  
  738.         cmp ax,010b        ; set rgb palette
  739.  
  740.         pop cx
  741.         pop ax
  742.  
  743.         jne p_done        ; the other values are meaningless in vga mode
  744.  
  745.         mov red,bl
  746.         mov green,cl
  747.         mov blue,dl
  748.             ; get rid of upper two control bits, leave index
  749.         and ax,03FFFh  
  750.  
  751.  
  752.         mov dh,red
  753.         mov ch,green
  754.         mov cl,blue
  755.         mov bx,ax
  756.  
  757.         mov ax,01010h     ; set single palette entry
  758.  
  759.         int 10h
  760.  
  761.  
  762. p_done:
  763.         ret
  764.  
  765.  
  766.  
  767. ; 1C ---------------------------------------------------------------------
  768.  
  769.      ; Set all Palette entries with one call
  770. SVC_1C: ; Set All Palette
  771.     ;  not compatible with 256 color VGA modes, you have to provide
  772.     ; the user with a library function to do this.
  773.         ret
  774.  
  775.  
  776. ; 1E -------------------------------------------------------------------
  777.  
  778. ; input: 
  779. ;    al = index number of current drawing color
  780. ;    ah = index number of current fill color
  781. ; return: nothing
  782.  
  783. color: ; Set Color
  784.  
  785.         mov    current_line_color,al
  786.         mov current_fill_color,ah
  787.  
  788.         ret
  789.  
  790.  
  791. ; 20 ------------------------------------------------------------------
  792.  
  793. ; input:
  794. ;    al = fill pattern number
  795. ;    es:bx = if pattern number = 0FFh, this points to user fill pattern
  796. ; return: nothing
  797.  
  798. fillstyle:                ; Set Fill Style/Pattern
  799.  
  800.  
  801.         cmp al,0FFh     ; test if user defined fill
  802.         jz    user_fill
  803.  
  804.         cbw
  805.         mov cl,3        ; multiply by 8 for eight bytes per fill type
  806.         shl ax,cl
  807.         mov si,ax
  808.         add si,offset default_fillpaterns ; point to the selected fill patern
  809.         jmp cont_fill   ; ds:si point to selected fill pattern
  810.  
  811. user_fill:              ; user defined fill passed by pointer ES:BX
  812.         push bx
  813.         pop  si
  814.         push es
  815.         pop  ds         ; setup so ds:si points to users fill pattern
  816.  
  817. cont_fill:
  818.  
  819.         mov    di,offset active_fillpattern
  820.         push cs
  821.         pop    es            ; es:cs is the destination of the copy
  822.  
  823.         mov    cx,8        ; setup to copy eight bytes of pattern
  824.         repz movsb      ; copy pattern into active pattern
  825.  
  826.         ret
  827.  
  828.  
  829. ; 22 ------------------------------------------------------------------
  830.  
  831. ; input:
  832. ;    al = line pattern number
  833. ;    bx = user defined line pattern if al = 4
  834. ;    cx = line width
  835. ; return: nothing
  836.  
  837. linestyle:      ;          set current line style
  838.  
  839.         cmp    ax,4
  840.         jz    user_defined        ; check if its a user defined line
  841.  
  842.         and    ax,0FFh                ; pattern number in AL
  843.         shl    al,1                ; used two index by 2 bytes at a time
  844.         mov    si,ax
  845.         mov    bx,[default_linestyles +si]  ; load a pre-defined pattern
  846.  
  847. user_defined:                   ; user defined are passed in BX
  848.         mov active_linestyle,bx
  849.  
  850.         ret
  851.  
  852.  
  853.  
  854. ; 24 -------------------------------------------------------------------
  855.  
  856. ; input:
  857. ;    al = hardware font number
  858. ;    ah = hardware font orientation
  859. ;    bx = desired X size
  860. ;    cx = desired Y size
  861. ; return:
  862. ;    bx = closest X size available
  863. ;    cx = closest Y size available
  864.  
  865. textstyle:                ; Set UserCharSize
  866.         ; this code works but thats about all
  867.         mov bx,bx       ; let say the characters are 8 x 16
  868.         mov cx,cx
  869.         ret
  870.  
  871.  
  872.  
  873. ; 26 --------------------------------------------------------------------
  874.  
  875. ; input:
  876. ;    es:bx = pointer to ascii string to display
  877. ;    cx = number of chars in string
  878. ;    al = horizontal justification ( 0=left,1=center,2=right )
  879. ;       ah = vertical justification (0=bottom,1=center,2=top)
  880. ; return:
  881. ;    bx = width of string in graphics units
  882. ;    cx = height of string in graphics units
  883.  
  884. text:                 ; Display Text  ( DEFAULT FONT )
  885.  
  886.     ; this is one of the things I could not figure out
  887.     ; if you come up with something please let me know.
  888.         push bx
  889.         push cx
  890.         ; hack here
  891.  
  892.  
  893.         ; end hack
  894.         pop cx
  895.         pop bx
  896.         mov bx,bx    ;  NOTE this should be 8 * length of string (cx)
  897.         mov cx,cx
  898.         ret
  899.  
  900.  
  901. ; 28 --------------------------------------------------------------------
  902.  
  903. ; input:
  904. ;    es:bx = pointer to ascii text
  905. ;    cx = number of chars in test
  906. ; return:
  907. ;    bx = width of string in graphics units
  908. ;    cx = height of string in graphics units
  909.  
  910. textsize:             ; Text Width/Height ( DEFAULT FONT )
  911.  
  912. ;    again I did not know how to do this
  913.         mov bx,bx    ; NOTE this is not right
  914.         mov cx,cx
  915.         ret
  916.  
  917.  
  918. ; 2C --------------------------------------------------------------------
  919.  
  920. ; input:
  921. ;    ax = x coord to start at
  922. ;    bx = y coord to start at
  923. ;    cl = boundry color
  924. ; return: nothing
  925.  
  926. flood_fill:             ; FloodFill
  927.         ; flood fill needs implemented also
  928.         ret
  929.  
  930.  
  931. ; 2E -----------------------------------------------------------------
  932.  
  933. ; input:
  934. ;    ax = x coord
  935. ;    bx = y coord
  936. ; return:
  937. ;    dl = color 
  938.  
  939. get_pixel:             ; GetPixel
  940.  
  941.         ; if you don't mind being slow, just use the bios calls
  942. ;        mov    cx,ax      ; load x value
  943. ;        mov    dx,bx        ; load y value
  944. ;        mov bh,0        ; page zero
  945. ;        mov ah,0Dh      ; read pixel function
  946. ;
  947. ;        int 10h
  948. ;
  949. ;        mov dl,al       ; return the color of pixel read
  950. ;        ret
  951.  
  952.  
  953.         cmp active_mode,1
  954.         je getpixel_mode1
  955.  
  956.                        ; else read pixels in mode 0
  957.         push di        ; save these registers
  958.         push es
  959.  
  960.         mov  cx,ax       ;   save the column value (x)
  961.  
  962.  
  963.         mov ax,bx      ;   load the row value (y)
  964.         mul xsize      ;   offset =(xsize * y)
  965.         add ax,cx       ;     + x
  966.         mov di,ax      ;   load screen address into di
  967.  
  968.         mov ax,0A000h  ;   video ram segement address
  969.         mov es,ax
  970.         mov dl,es:[di] ;   read the pixel
  971.  
  972.  
  973.         pop es
  974.         pop di
  975.  
  976.         ret
  977.  
  978.  
  979.  
  980. getpixel_mode1:        ; read pixel this way when in mode 1
  981.         push di        ; save these registers
  982.         push es
  983.  
  984.         mov  cx,ax       ;   save the column value (x)
  985.  
  986.         mov ax,bx      ;   load the row value (y)
  987.  
  988.         call calc_hilow   ; find vga offset values into screen memory
  989.  
  990.         cmp bx,lasthio ;   see of hioffset is the same as last time
  991.         je  no_hio_chg_r ;   if it is, save time by not resetting it
  992.  
  993.         cmp doing_ellipse,1
  994.         je no_unlock_get      ; its already unlocked
  995.         call unlock_vga
  996. no_unlock_get:
  997.  
  998.         mov ax,bx      ;
  999.         call set_hioffset  ; sets the hioffset register for vga mem addressing
  1000.  
  1001.         cmp doing_ellipse,1
  1002.         je no_lock_get
  1003.         call lock_vga
  1004. no_lock_get:
  1005.  
  1006. no_hio_chg_r:
  1007.         mov ax,0A000h  ;   video ram segement address
  1008.         mov es,ax
  1009.         mov dl,es:[di] ;   read the pixel
  1010.  
  1011.  
  1012.         pop es
  1013.         pop di
  1014.  
  1015.         ret
  1016.  
  1017.  
  1018.  
  1019. ; 30 -----------------------------------------------------------------
  1020.  
  1021. ; input:
  1022. ;    ax = x coord
  1023. ;    bx = y coord
  1024. ;    dl = color 
  1025. ; return: nothing
  1026.  
  1027.  
  1028. put_pixel:            ; SetPixel
  1029.  
  1030. ;         p[XSIZE*y+x] = color;           for 320 x 200 - 256 mode
  1031.  
  1032.         ; if you don't mind being slow, just call the bios plot dot
  1033. ;        push dx        ; save color value
  1034. ;        mov    cx,ax      ; load x value
  1035. ;        mov    dx,bx        ; load y value
  1036. ;        pop ax          ; color value from pushed dx
  1037. ;        mov bh,0        ; page zero
  1038. ;        mov ah,0Ch      ; write pixel function
  1039. ;
  1040. ;        int 10h
  1041. ;        ret
  1042.  
  1043. ; else get fancy to make it faster.
  1044.  
  1045.         cmp active_mode,1
  1046.         je putpixel_mode1
  1047.  
  1048.                        ; else plot pixels in mode 0
  1049.         push di        ; save these registers
  1050.         push es
  1051.         push ax
  1052.         push bx
  1053.         push cx
  1054.         push dx
  1055.  
  1056.         push dx        ;   save the color
  1057.         mov  cx,ax       ;   save the column value (x)
  1058.  
  1059.         mov ax,bx      ;   load the row value (y)
  1060.         mul xsize      ;   offset =(xsize * y)
  1061.         add ax,cx       ;     + x
  1062.         mov di,ax      ;   load screen address into di
  1063.  
  1064.         mov ax,0A000h  ;   video ram segement address
  1065.         mov es,ax
  1066.  
  1067.         pop dx         ;   get the color info back
  1068.  
  1069.         mov es:[di],dl ;   plot the pixel
  1070.  
  1071.         pop dx
  1072.         pop cx
  1073.         pop bx
  1074.         pop ax
  1075.         pop es
  1076.         pop di
  1077.  
  1078.         ret
  1079.  
  1080.  
  1081.  
  1082.  
  1083. putpixel_mode1:                  ; routine to plot pixels when in mode 1
  1084.         push di        ; save these registers
  1085.         push es
  1086.         push ax
  1087.         push bx
  1088.         push cx
  1089.         push dx
  1090.  
  1091.         push dx        ;   save the color
  1092.         mov  cx,ax       ;   save the column value (x)
  1093.  
  1094.         mov ax,bx      ;   load the row value (y)
  1095.  
  1096.         call calc_hilow     ;   find vga hi and low offset value for screen mem
  1097.  
  1098.         cmp bx,lasthio ;   see of hioffset is the same as last time
  1099.         je  no_hio_chg_w ;   if it is, save time by not resetting it
  1100.  
  1101.         cmp doing_ellipse,1
  1102.         je no_unlock_put     ; its already done
  1103.         call unlock_vga
  1104. no_unlock_put:
  1105.  
  1106.         mov ax,bx      ;
  1107.         call set_hioffset  ; sets the hioffset register for vga mem addressing
  1108.  
  1109.         cmp doing_ellipse,1
  1110.         je no_lock_put
  1111.         call lock_vga
  1112. no_lock_put:
  1113.  
  1114. no_hio_chg_w:
  1115.         mov ax,0A000h  ;   video ram segement address
  1116.         mov es,ax
  1117.  
  1118.         pop dx         ;   get the color info back
  1119.  
  1120.         mov es:[di],dl ;   plot the pixel
  1121.  
  1122.         pop dx
  1123.         pop cx
  1124.         pop bx
  1125.         pop ax
  1126.         pop es
  1127.         pop di
  1128.  
  1129.         ret
  1130.  
  1131.  
  1132.  
  1133.  
  1134. ; 32 -------------------------------------------------------------------
  1135.  
  1136. bitmaputil: ; Set CallTable
  1137.  
  1138.             ; see the book, basically don't worry (be happy)
  1139.         
  1140.         push cs
  1141.         pop es
  1142.         mov bx, offset the_util_table
  1143.         ret
  1144.  
  1145. ; 34 -------------------------------------------------------------------
  1146.  
  1147. ; input:
  1148. ;    ax = x1 corner
  1149. ;    bx = y1 corner
  1150. ;    cx = x2 corner
  1151. ;    dx = y2 corner
  1152. ; return: nothing
  1153.  
  1154. patbar:           ; fill the rectangle using current fillstyle and color
  1155.  
  1156. ;        this version of pattern filling uses the following trick to greatly
  1157. ;        improve speed.  Instead of calling put_pixel for every pixel to plot
  1158. ;        it does the write to screen memory on its own. What makes it fast is
  1159. ;        that it only has to find the original offset by multipling XSIZE by
  1160. ;        y1.  From then on it increments a pointer to find the next location
  1161. ;        in screen memory (not multiplies required after initial one).
  1162.  
  1163.                     ; first, make sure x1 < x2 and y1 < y2
  1164.         cmp ax,cx               ; if x1 < x2
  1165.         jle x_ok
  1166.         xchg ax,cx
  1167. x_ok:
  1168.  
  1169.         cmp bx,dx              ; if y1 < y2
  1170.         jle y_ok
  1171.         xchg bx,dx
  1172. y_ok:
  1173.  
  1174.                     ; then load the start and end values
  1175.         mov x1,ax
  1176.         mov x2,cx
  1177.         mov y1,bx
  1178.         mov y2,dx
  1179.  
  1180.  
  1181.         cmp active_mode,1
  1182.         je patbar_mode1            ; different way to calc pixel offset
  1183.  
  1184.         ;         Next, setup the starting value of the VGA's hioffset reg
  1185.         push ax
  1186.         push bx
  1187.         push cx
  1188.  
  1189.         mov cx,ax           ; load x value
  1190.         mov ax,bx           ; load the y value
  1191.         mul xsize        ; find the pixel offset
  1192.         add ax,cx        ; add inthe x value
  1193.         mov di,ax
  1194.  
  1195.         mov ax,0a000h       ; screen memory segment
  1196.         mov es,ax
  1197.  
  1198.         ;  calculate ho many screen byte are from right edge of box
  1199.         ;  to left edge of box on next row
  1200.         mov ax,max_x
  1201.         sub ax,x2
  1202.         add ax,x1
  1203.         mov next_row,ax
  1204.  
  1205.         pop cx
  1206.         pop bx
  1207.         pop ax
  1208.  
  1209. again0:
  1210.  
  1211.         ;   First, lets figure out the fill pattern parameters
  1212.  
  1213.  
  1214.         push ax
  1215.         push cx
  1216.         push si
  1217.  
  1218.  
  1219.  
  1220.         ; the bit/byte pointer are relative to the absolute
  1221.         ; screen position mod 8
  1222.         mov fill_byte_ptr,bx    ; load the current y value
  1223.         mov fill_bit_ptr,ax     ; load the current x value
  1224.         and fill_byte_ptr,07h
  1225.         and fill_bit_ptr,07h
  1226.  
  1227.  
  1228.         mov si,fill_byte_ptr;
  1229.         mov al,[offset active_fillpattern + si]
  1230.         mov cx,fill_bit_ptr
  1231.         shl al,cl
  1232.         and al,80h
  1233.         cmp al,80h
  1234.  
  1235.  
  1236.         jne use_background0              ; if not plotting this dot
  1237.         mov dl,current_fill_color      ; else load fill color
  1238.         jmp selected0
  1239.  
  1240. use_background0:
  1241.         mov dl,current_background_color  ; assume background
  1242.  
  1243. selected0:
  1244.  
  1245.         pop si
  1246.         pop cx
  1247.         pop ax
  1248.  
  1249.  
  1250.  
  1251.  
  1252. ;         this is the slow way, it has to recalute the offset into
  1253. ;               display memory every time it puts a pixel
  1254.  
  1255. ;        push ax
  1256. ;        push bx
  1257. ;        call put_pixel
  1258. ;        pop bx
  1259. ;        pop ax
  1260.  
  1261.         mov es:[di],dl
  1262.  
  1263.  
  1264.         inc di              ; advvance screen mapped memory pointer
  1265.         inc ax              ; advance in x dir till at right edge
  1266.         cmp ax,x2
  1267.         jle again0
  1268.  
  1269.         mov ax,x1                ; reset to left size of rectangle
  1270.         inc bx                   ; go to down to next row
  1271.         cmp bx,y2
  1272.         jg  fill_done0
  1273.  
  1274.  
  1275.         ;            Since were changing rows we'll find a new hi and low
  1276.         ; the trick is to add the number of bytes from the right side of the
  1277.         ; box to the left side of the box  ( note: no multiplies needed )
  1278.  
  1279.         add di,next_row
  1280.  
  1281.         jmp again0
  1282.  
  1283.  
  1284.  
  1285. fill_done0:
  1286.         ret              ; end of patbar in mode 0
  1287.  
  1288.  
  1289.  
  1290.  
  1291. patbar_mode1:
  1292.             ; first, make sure x1 < x2 and y1 < y2
  1293.  
  1294.         call unlock_vga  ;  keep vga ready to plot pixels
  1295.  
  1296.  
  1297.         ;   Next, setup the starting value of the VGA's hioffset reg
  1298.         push ax
  1299.         push bx
  1300.         push cx
  1301.  
  1302.         mov cx,ax           ; load x value
  1303.         mov ax,bx           ; load the y value
  1304.         call calc_hilow     ; find the values of hio and lowo
  1305.         mov ax,bx           ; load hio
  1306.         call set_hioffset   ; set the vga register for the hioffset
  1307.  
  1308.         mov ax,0a000h       ; screen memory segment
  1309.         mov es,ax
  1310.  
  1311.         ;  calculate ho many screen byte are from right edge of box
  1312.         ;  to left edge of box on next row
  1313.         mov ax,max_x
  1314.         sub ax,x2
  1315.         add ax,x1
  1316.         mov next_row,ax
  1317.  
  1318.         pop cx
  1319.         pop bx
  1320.         pop ax
  1321.  
  1322. again1:
  1323.  
  1324.         ;   First, lets figure out the fill pattern parameters
  1325.  
  1326.  
  1327.         push ax
  1328.         push cx
  1329.         push si
  1330.  
  1331.  
  1332.  
  1333.         ; the bit/byte pointer are relative to the absolute
  1334.         ; screen position mod 8
  1335.         mov fill_byte_ptr,bx    ; load the current y value
  1336.         mov fill_bit_ptr,ax     ; load the current x value
  1337.         and fill_byte_ptr,07h
  1338.         and fill_bit_ptr,07h
  1339.  
  1340.  
  1341.         mov si,fill_byte_ptr;
  1342.         mov al,[offset active_fillpattern + si]
  1343.         mov cx,fill_bit_ptr
  1344.         shl al,cl
  1345.         and al,80h
  1346.         cmp al,80h
  1347.  
  1348.  
  1349.         jne use_background1              ; if not plotting this dot
  1350.         mov dl,current_fill_color      ; else load fill color
  1351.         jmp selected1
  1352.  
  1353. use_background1:
  1354.         mov dl,current_background_color  ; assume background
  1355.  
  1356. selected1:
  1357.  
  1358.  
  1359.         pop si
  1360.         pop cx
  1361.         pop ax
  1362.  
  1363.  
  1364.  
  1365.  
  1366. ;         this is the slow way, it has to recalute the offset into
  1367. ;          display memory every time it puts a pixel
  1368. ;        but it shows the easy way to do it.
  1369.  
  1370. ;        push ax
  1371. ;        push bx
  1372. ;        call put_pixel
  1373. ;        pop bx
  1374. ;        pop ax
  1375.  
  1376.         mov es:[di],dl
  1377.  
  1378.  
  1379.         inc di
  1380.         cmp di,0FFFh
  1381.         jle leave_hio1
  1382.         sub di,1000h
  1383.         inc lasthio
  1384.  
  1385.         push ax            ; let vga card know we incremented hi offset
  1386.         mov ax,lasthio
  1387.         call set_hioffset
  1388.         pop ax
  1389.  
  1390. leave_hio1:
  1391.         inc ax              ; advance in x dir till at right edge
  1392.         cmp ax,x2
  1393.         jle again1
  1394.  
  1395.         mov ax,x1                ; reset to left size of rectangle
  1396.         inc bx                   ; go to down to next row
  1397.         cmp bx,y2
  1398.         jg  fill_done1
  1399.  
  1400.  
  1401.     ;Since were changing rows we'll find a new hi and low
  1402.     ; the trick is to add the number of bytes from the right side of the
  1403.     ; box to the left side of the box  ( note: no multiplies needed )
  1404.  
  1405.         add di,next_row
  1406.         cmp di,0FFFh
  1407.         jle no_bump1
  1408.         sub di,1000h
  1409.         inc lasthio
  1410.         push ax
  1411.         mov ax,lasthio
  1412.         call set_hioffset
  1413.         pop ax
  1414. no_bump1:
  1415.  
  1416.  
  1417.         jmp again1
  1418.  
  1419.  
  1420.  
  1421. fill_done1:
  1422.         call lock_vga           ; protect the vgas register again
  1423.  
  1424.         ret
  1425.  
  1426.  
  1427.  
  1428. ; 36 ------------------------------------------------------------------
  1429.  
  1430. buf_ptr   dw    ?        ; pointer to the buffer for getimage/putimage
  1431. put_mode  db    ?     ; pixel writing mode for putting images (and,xor,etc)
  1432.  
  1433. ;         NOTE: the book has mistakes in input/output parameters
  1434. ; input:
  1435. ;     es:bx = pointer to memory buffer
  1436. ;       buffer[0] = window width in x direction
  1437. ;       buffer[2] = window height in y direction
  1438. ;    cx = x1 corner of window
  1439. ;    dx = y1 corner of window
  1440. ; return: nothing
  1441.  
  1442. get_image: ; GetImage
  1443.  
  1444.  
  1445. ;       this version of pattern filling uses the following trick to greatly
  1446. ;       improve speed.  Instead of calling put_pixel for every pixel to plot
  1447. ;       it does the write to screen memory on its own. What makes it fast is
  1448. ;       that it only has to find the original offset by multipling XSIZE by
  1449. ;       y1.  From then on it increments a pointer to find the next location
  1450. ;       in screen memory.
  1451.  
  1452.  
  1453.         mov buf_ptr,bx   ; pointer to the buffer where we'll store image
  1454.  
  1455.         mov ax,es:[bx]
  1456.         add ax,cx   ; add x1 plus xsize of image window
  1457.  
  1458.         mov bx,es:[bx +2]
  1459.         add bx,dx   ; add y1 plus ysize of image window
  1460.  
  1461.  
  1462.         mov x1,cx
  1463.         mov y1,dx
  1464.         mov x2,ax
  1465.         mov y2,bx
  1466.  
  1467.         mov bx,buf_ptr
  1468.         add bx,4           ; first word was used for xsize dimension
  1469.         mov buf_ptr,bx
  1470.  
  1471.         mov ax,x1
  1472.         mov bx,y1
  1473.  
  1474.  
  1475.  
  1476.         cmp active_mode,1
  1477.         je getimage_mode1    ; different way to calc pixel offset
  1478.  
  1479.         ; Next, setup the starting value of the VGA's hioffset reg
  1480.         push ax
  1481.         push bx
  1482.         push cx
  1483.  
  1484.         mov cx,ax           ; load x value
  1485.         mov ax,bx           ; load the y value
  1486.         mul xsize        ; find the pixel offset
  1487.         add ax,cx        ; add inthe x value
  1488.         mov di,ax
  1489.  
  1490.  
  1491.         ;  calculate ho many screen byte are from right edge of box
  1492.         ;  to left edge of box on next row
  1493.         mov ax,max_x
  1494.         sub ax,x2
  1495.         add ax,x1
  1496.         mov next_row,ax
  1497.  
  1498.         pop cx
  1499.         pop bx
  1500.         pop ax
  1501.  
  1502. g_again0:
  1503.         ; move a byte from the screen to the image buffer
  1504.         push ax
  1505.         push es
  1506.         mov ax,0A000h
  1507.         mov es,ax
  1508.         mov al,byte ptr es:[di]
  1509.         pop es
  1510.         push bx
  1511.         mov bx,buf_ptr
  1512.         mov byte ptr es:[bx],al
  1513.         pop bx
  1514.         pop ax
  1515.         inc buf_ptr  ; point to next byte in the users buffer
  1516.  
  1517.  
  1518.         inc di              ; advvance screen mapped memory pointer
  1519.         inc ax              ; advance in x dir till at right edge
  1520.         cmp ax,x2
  1521.         jle g_again0
  1522.  
  1523.         mov ax,x1                ; reset to left size of rectangle
  1524.         inc bx                   ; go to down to next row
  1525.         cmp bx,y2
  1526.         jg  geti_done0
  1527.  
  1528.  
  1529.     ;Since were changing rows we'll find a new hi and low
  1530.     ;the trick is to add the number of bytes from the right side of the
  1531.     ; box to the left side of the box  ( note: no multiplies needed )
  1532.  
  1533.         add di,next_row
  1534.  
  1535.         jmp g_again0
  1536.  
  1537.  
  1538.  
  1539. geti_done0:
  1540.         ret              ; end of patbar in mode 0
  1541.  
  1542.  
  1543.  
  1544.  
  1545. getimage_mode1:
  1546.                     ; first, make sure x1 < x2 and y1 < y2
  1547.  
  1548.         call unlock_vga  ;  keep vga ready to plot pixels
  1549.  
  1550.  
  1551.         ;  Next, setup the starting value of the VGA's hioffset reg
  1552.         push ax
  1553.         push bx
  1554.         push cx
  1555.  
  1556.         mov cx,ax           ; load x value
  1557.         mov ax,bx           ; load the y value
  1558.         call calc_hilow     ; find the values of hio and lowo
  1559.         mov ax,bx           ; load hio
  1560.         call set_hioffset   ; set the vga register for the hioffset
  1561.  
  1562.         ;  calculate ho many screen byte are from right edge of box
  1563.         ;  to left edge of box on next row
  1564.         mov ax,max_x
  1565.         sub ax,x2
  1566.         add ax,x1
  1567.         mov next_row,ax
  1568.  
  1569.         pop cx
  1570.         pop bx
  1571.         pop ax
  1572.  
  1573. g_again1:
  1574.  
  1575.             ; move a byte from the screen to the image buffer
  1576.         push ax
  1577.         push es
  1578.         mov ax,0A000h
  1579.         mov es,ax
  1580.         mov al,byte ptr es:[di]
  1581.         pop es
  1582.         push bx
  1583.         mov bx,buf_ptr
  1584.         mov byte ptr es:[bx],al
  1585.         pop bx
  1586.         pop ax
  1587.         inc buf_ptr  ; point to next byte in the users buffer
  1588.  
  1589.  
  1590.         inc di
  1591.         cmp di,0FFFh
  1592.         jle g_leave_hio1
  1593.         sub di,1000h
  1594.         inc lasthio
  1595.  
  1596.         push ax          ; let vga card know we incremented hi offset
  1597.         mov ax,lasthio
  1598.         call set_hioffset
  1599.         pop ax
  1600.  
  1601. g_leave_hio1:
  1602.         inc ax              ; advance in x dir till at right edge
  1603.         cmp ax,x2
  1604.         jle g_again1
  1605.  
  1606.         mov ax,x1                ; reset to left size of rectangle
  1607.         inc bx                   ; go to down to next row
  1608.         cmp bx,y2
  1609.         jg  geti_done1
  1610.  
  1611.  
  1612.     ;Since were changing rows we'll find a new hi and low
  1613.     ;the trick is to add the number of bytes from the right side of the
  1614.     ; box to the left side of the box  ( note: no multiplies needed )
  1615.  
  1616.         add di,next_row
  1617.         cmp di,0FFFh
  1618.         jle g_no_bump1
  1619.         sub di,1000h
  1620.         inc lasthio
  1621.         push ax
  1622.         mov ax,lasthio
  1623.         call set_hioffset
  1624.         pop ax
  1625. g_no_bump1:
  1626.  
  1627.         jmp g_again1
  1628.  
  1629. geti_done1:
  1630.         call lock_vga           ; protect the vgas register again
  1631.  
  1632.         ret
  1633.  
  1634. ; 38 -------------------------------------------------------------------------
  1635.  
  1636. ;         NOTE: the book has mistakes in input/output parameters
  1637. ; input:
  1638. ;     es:bx = pointer to memory buffer
  1639. ;       buffer[0] = window width in x direction
  1640. ;       buffer[2] = window height in y direction
  1641. ;    cx = x1 corner of window
  1642. ;    dx = y1 corner of window
  1643. ; return: nothing
  1644.  
  1645.  
  1646. put_image: ; putImage
  1647.  
  1648. ;        this version of pattern filling uses the following trick to greatly
  1649. ;        improve speed.  Instead of calling put_pixel for every pixel to plot
  1650. ;        it does the write to screen memory on its own. What makes it fast is
  1651. ;        that it only has to find the original offset by multipling XSIZE by
  1652. ;        y1.  From then on it increments a pointer to find the next location
  1653. ;        in screen memory.
  1654.  
  1655.         mov put_mode,al  ; save the put image pixel writing mode
  1656.         mov buf_ptr,bx   ; pointer to the buffer where we'll store image
  1657.  
  1658.         mov ax,es:[bx]
  1659.         add ax,cx   ; add x1 plut xsize of image window
  1660.  
  1661.         mov bx,es:[bx +2]
  1662. ;        mov bx,di
  1663.         add bx,dx   ; add y1 plus ysize of image window
  1664.  
  1665.  
  1666.         mov x1,cx
  1667.         mov y1,dx
  1668.         mov x2,ax
  1669.         mov y2,bx
  1670.  
  1671.         mov bx,buf_ptr
  1672.         add bx,4           ; first word was used for xsize dimension
  1673.         mov buf_ptr,bx
  1674.  
  1675.         mov ax,x1
  1676.         mov bx,y1
  1677.  
  1678.  
  1679.         cmp active_mode,1
  1680.         je putimage_mode1    ; different way to calc pixel offset
  1681.  
  1682.         ;   Next, setup the starting value of the VGA's hioffset reg
  1683.         push ax
  1684.         push bx
  1685.         push cx
  1686.  
  1687.         mov cx,ax           ; load x value
  1688.         mov ax,bx           ; load the y value
  1689.         mul xsize        ; find the pixel offset
  1690.         add ax,cx        ; add inthe x value
  1691.         mov di,ax
  1692.  
  1693.  
  1694.         ;  calculate ho many screen byte are from right edge of box
  1695.         ;  to left edge of box on next row
  1696.         mov ax,max_x
  1697.         sub ax,x2
  1698.         add ax,x1
  1699.         mov next_row,ax
  1700.  
  1701.         pop cx
  1702.         pop bx
  1703.         pop ax
  1704.  
  1705.  
  1706.         mov cl,put_mode    ; keep the put_mode in cl for access speed
  1707. p_again0:
  1708.         call buf_to_screen
  1709.  
  1710.         inc di              ; advvance screen mapped memory pointer
  1711.         inc ax              ; advance in x dir till at right edge
  1712.         cmp ax,x2
  1713.         jle p_again0
  1714.  
  1715.         mov ax,x1                ; reset to left size of rectangle
  1716.         inc bx                   ; go to down to next row
  1717.         cmp bx,y2
  1718.         jg  puti_done0
  1719.  
  1720.  
  1721.     ;Since were changing rows we'll find a new hi and low
  1722.     ; the trick is to add the number of bytes from the right side of the
  1723.     ; box to the left side of the box  ( note: no multiplies needed )
  1724.  
  1725.         add di,next_row
  1726.  
  1727.         jmp p_again0
  1728.  
  1729.  
  1730.  
  1731. puti_done0:
  1732.         ret              ; end of patbar in mode 0
  1733.  
  1734.  
  1735.                 ; ----------------- putimage for mode 1 ------------------
  1736.  
  1737. putimage_mode1:
  1738.                     ; first, make sure x1 < x2 and y1 < y2
  1739.  
  1740.         call unlock_vga  ;  keep vga ready to plot pixels
  1741.  
  1742.  
  1743.     ;        Next, setup the starting value of the VGA's hioffset reg
  1744.         push ax
  1745.         push bx
  1746.         push cx
  1747.  
  1748.         mov cx,ax           ; load x value
  1749.         mov ax,bx           ; load the y value
  1750.         call calc_hilow     ; find the values of hio and lowo
  1751.         mov ax,bx           ; load hio
  1752.         call set_hioffset   ; set the vga register for the hioffset
  1753.  
  1754.  
  1755.         ;  calculate ho many screen byte are from right edge of box
  1756.         ;  to left edge of box on next row
  1757.         mov ax,max_x
  1758.         sub ax,x2
  1759.         add ax,x1
  1760.         mov next_row,ax
  1761.  
  1762.         pop cx
  1763.         pop bx
  1764.         pop ax
  1765.  
  1766.         mov cl,put_mode     ; keep the put_mode in cl for access speed
  1767. p_again1:
  1768.         call buf_to_screen
  1769.  
  1770.         inc di
  1771.         cmp di,0FFFh
  1772.         jle p_leave_hio1
  1773.         sub di,1000h
  1774.         inc lasthio
  1775.  
  1776.         push ax            ; let vga card know we incremented hi offset
  1777.         mov ax,lasthio
  1778.         call set_hioffset
  1779.         pop ax
  1780.  
  1781. p_leave_hio1:
  1782.         inc ax              ; advance in x dir till at right edge
  1783.         cmp ax,x2
  1784.         jle p_again1
  1785.  
  1786.         mov ax,x1                ; reset to left size of rectangle
  1787.         inc bx                   ; go to down to next row
  1788.         cmp bx,y2
  1789.         jg  puti_done1
  1790.  
  1791.  
  1792.     ;Since were changing rows we'll find a new hi and low
  1793.     ; the trick is to add the number of bytes from the right side of the
  1794.     ; box to the left side of the box  ( note: no multiplies needed )
  1795.  
  1796.         add di,next_row
  1797.         cmp di,0FFFh
  1798.         jle p_no_bump1
  1799.         sub di,1000h
  1800.         inc lasthio
  1801.         push ax
  1802.         mov ax,lasthio
  1803.         call set_hioffset
  1804.         pop ax
  1805. p_no_bump1:
  1806.  
  1807.         jmp p_again1
  1808.  
  1809. puti_done1:
  1810.         call lock_vga           ; protect the vgas register again
  1811.  
  1812.         ret
  1813.  
  1814.  
  1815.           ; ----------------------------------------------
  1816.           ;    this code write the next byte from the put image buffer
  1817.           ;    to the display screen
  1818.  
  1819. buf_to_screen proc near
  1820.             ; move a byte from the image buffer to the screen
  1821.         push ax
  1822.         push bx
  1823.  
  1824.                 ; get the byte out of the users buffer
  1825.         mov bx,buf_ptr
  1826.         mov al,byte ptr es:[bx]
  1827.  
  1828.         pop bx
  1829.         push es
  1830.         push ax
  1831.  
  1832.         mov ax,0A000h
  1833.         mov es,ax        ; es reg is pointer to VGA screen
  1834.  
  1835.         pop ax
  1836.  
  1837.             ; write the byte to screen mem according to users mode
  1838. ;        mov cl,put_mode
  1839.         cmp cl,0
  1840.         jne try_xor0
  1841.         mov byte ptr es:[di],al
  1842.         jmp mode_found0
  1843. try_xor0:
  1844.         cmp cl,1
  1845.         jne try_or0
  1846.         xor byte ptr es:[di],al
  1847.         jmp mode_found0
  1848. try_or0:
  1849.         cmp cl,2
  1850.         jne try_and0
  1851.         or byte ptr es:[di],al
  1852.         jmp mode_found0
  1853. try_and0:
  1854.         cmp cl,3
  1855.         jne then_comp0
  1856.         and byte ptr es:[di],al
  1857.         jmp mode_found0
  1858. then_comp0:
  1859.         xor al,0FFh               ; complement the byte
  1860.         and byte ptr es:[di],al
  1861. mode_found0:
  1862.  
  1863.         pop es
  1864.         pop ax
  1865.  
  1866.         inc buf_ptr  ; point to next byte in the users buffer
  1867.  
  1868.         ret
  1869.  
  1870. buf_to_screen endp
  1871.  
  1872.  
  1873. ; 40 -------------------------------------------------------------------
  1874.  
  1875. ; input:
  1876. ;    ax = x1
  1877. ;    bx = y1
  1878. ;    cx = x2
  1879. ;    dx = y2
  1880. ; return: nothing
  1881.  
  1882. set_clip: ; Set clipping
  1883.                 ; load the limits of the clipping window
  1884.         mov clip_x1,ax
  1885.         mov clip_y1,bx
  1886.         mov clip_x2,cx
  1887.         mov clip_y2,dx
  1888.  
  1889.         ret
  1890.  
  1891.  
  1892.  
  1893. ; 3A -------------------------------------------------------------------
  1894.  
  1895. ; if al = 0
  1896. ;    input:  nothing
  1897. ;    return:
  1898. ;        bx = size of color table
  1899. ;        cx = maximum color number
  1900. ; if al = 1
  1901. ;    input:  nothing
  1902. ;    return:
  1903. ;        es:bx = pointer to default color table (first byte is size)
  1904.  
  1905. color_query:        ; SetParameters
  1906.  
  1907.             cmp al,0
  1908.             jnz    color_table_q
  1909.  
  1910.             mov    bx,256
  1911.             mov cx,255
  1912.             ret
  1913.  
  1914. color_table_q:
  1915.             push cs
  1916.             pop es
  1917.             mov bx,offset color_table
  1918.             ret
  1919.  
  1920.  
  1921.  
  1922.  
  1923. ; =========================================================================
  1924.  
  1925.     ; line drawing routine from Assembly language
  1926.     ; primer - The Waite Group - page 339-340
  1927.  
  1928. draw_line    proc    near
  1929.         mov ax,y2
  1930.         sub ax,y1
  1931.  
  1932.         mov si,1
  1933.         jge    store_y
  1934.         mov si,-1
  1935.         neg ax
  1936.  
  1937. store_y:
  1938.         mov delta_y,ax
  1939.  
  1940.         mov    ax,x2
  1941.         sub ax,x1
  1942.  
  1943.         mov    di,1
  1944.         jge    store_x
  1945.         mov    di,-1
  1946.         neg    ax
  1947.  
  1948. store_x:
  1949.         mov    delta_x,ax
  1950.  
  1951.         mov    ax,delta_x
  1952.         cmp    ax,delta_y
  1953.         jl    csteep
  1954.         call easy
  1955.         jmp finish_line
  1956.  
  1957. csteep:
  1958.         call steep
  1959.  
  1960. finish_line:
  1961.         ret
  1962.  
  1963. draw_line    endp
  1964.  
  1965.  
  1966.     ; ---------------------------------
  1967.  
  1968. easy    proc    near
  1969.  
  1970.         mov    ax,delta_x
  1971.         shr    ax,1
  1972.         mov    halfx,ax
  1973.  
  1974.         mov    cx,x1
  1975.         mov    dx,y1
  1976.         mov bx,0
  1977.         mov ax,delta_x
  1978.         mov    count,ax
  1979.  
  1980. newdot:
  1981.         call dotplot
  1982.         add    cx,di
  1983.         add bx,delta_y
  1984.         cmp    bx,halfx
  1985.         jle    dcount
  1986.         sub    bx,delta_x
  1987.  
  1988.         add    dx,si
  1989.  
  1990. dcount:
  1991.         dec count
  1992.         jge    newdot
  1993.  
  1994.         ret
  1995.  
  1996. easy    endp
  1997.  
  1998.  
  1999.     ; --------------------------------
  2000.  
  2001.  
  2002. steep    proc    near
  2003.  
  2004.         mov ax,delta_y
  2005.         shr    ax,1
  2006.         mov    halfy,ax
  2007.  
  2008.         mov    cx,x1
  2009.         mov    dx,y1
  2010.  
  2011.         mov    bx,0
  2012.         mov    ax,delta_y
  2013.         mov count,ax
  2014.  
  2015. newdot2:
  2016.         call dotplot
  2017.         add    dx,si
  2018.         add bx,delta_x
  2019.         cmp    bx,halfy
  2020.         jle    dcount2
  2021.         sub    bx,delta_y
  2022.  
  2023.         add    cx,di
  2024.  
  2025. dcount2:
  2026.         dec    count
  2027.         jge    newdot2
  2028.  
  2029.         ret
  2030.  
  2031. steep    endp
  2032.  
  2033.  
  2034.     ;    ------------------------------
  2035.  
  2036.  
  2037. dotplot    proc    near
  2038.  
  2039.         push    ax    ; save old values
  2040.         push    bx
  2041.         push    cx
  2042.         push    dx
  2043.  
  2044.         ; check to see if line style pattern dictates a plot or not
  2045.         ; if active_bit_pattern[line_bit_ptr] = 0 then dont plot a dot
  2046.  
  2047.         push ax
  2048.         push cx
  2049.  
  2050.         mov    ax,active_linestyle
  2051.         mov    cl,line_bit_ptr
  2052.         shl ax,cl
  2053.         and ax,8000h
  2054.         cmp ax,8000h
  2055.  
  2056.         pop cx
  2057.         pop ax
  2058.  
  2059.         mov    ax,cx
  2060.         mov    bx,dx
  2061.  
  2062.         jne no_dot_plot
  2063.  
  2064.         mov dl,current_line_color    ; do plot dot, so load line color
  2065.  
  2066.         call put_pixel         ; call the pixel writing routine
  2067. no_dot_plot:
  2068.  
  2069.  
  2070.         inc line_bit_ptr        ; move to next bit in pattern
  2071.         cmp line_bit_ptr,16     ; are we at the end of the pattern
  2072.         jne    no_reset_linestyle  ; if not do nothing
  2073.         mov line_bit_ptr,0  ; else start over at the pattern beginning
  2074. no_reset_linestyle:
  2075.  
  2076.         pop        dx    ; save old values
  2077.         pop     cx
  2078.         pop     bx
  2079.         pop     ax
  2080.  
  2081.  
  2082.  
  2083.         ret
  2084.  
  2085. dotplot    endp
  2086.  
  2087.  
  2088. ; --------------------------------------------------------------------------
  2089.  
  2090. calc_hilow:        ; find hi and low vga offsets for x,y location
  2091.                ; cx is column (x) , ax is row (y)
  2092.                ; uses value in varible 'xsize'
  2093.                ; results are  lowoffset in di and hioffset in bx
  2094.  
  2095.         push dx
  2096.  
  2097.         mul xsize      ;   offset =(xsize * y)
  2098.         add ax,cx       ;     + x
  2099.         jnc nocarry_o
  2100.         inc dx         ;   (DxAx + Cx)
  2101. nocarry_o:
  2102.  
  2103.         mov di,ax
  2104.         and di,0FFFh   ;   low offset is lowest 12 bits of offset
  2105.  
  2106.         mov cl,12      ;   (hioffset = offset >> 12
  2107.         shr ax,cl
  2108.         mov cl,4
  2109.         shl dx,cl
  2110.         or  dx,ax
  2111.         mov bx,dx      ;   hioffset saved in bx
  2112.  
  2113.         pop dx
  2114.  
  2115.         ret
  2116.  
  2117.  
  2118. ; ---------------------------------------------------------------------------
  2119.  
  2120. unlock_vga:            ; unlock vga registers
  2121.  
  2122.         push ax
  2123.         push dx
  2124.  
  2125.         mov dx,03CEh   ;   vga I/O port
  2126.         mov ax,050Fh
  2127.         out dx,ax      ;   unlock vga registers
  2128.  
  2129.         pop dx
  2130.         pop ax
  2131.  
  2132.         ret
  2133.  
  2134.  
  2135. ; ---------------------------------------------------------------------------
  2136.  
  2137. lock_vga:            ; lock vga registers
  2138.  
  2139.         push ax
  2140.         push dx
  2141.  
  2142.         mov dx,03CEh   ;   vga I/O port
  2143.         mov ax,000Fh
  2144.         out dx,ax      ;   unlock vga registers
  2145.  
  2146.         pop dx
  2147.         pop ax
  2148.  
  2149.         ret
  2150.  
  2151.  
  2152. ; ---------------------------------------------------------------------------
  2153.  
  2154. set_hioffset:          ;  sets the vga hi offset register
  2155.             ; ax contains the value for HIoffset
  2156.  
  2157.         push dx
  2158.  
  2159.         mov lasthio,ax
  2160.  
  2161.         mov ah,al      ; hioffset goes in ah
  2162.         mov al,9       ; function code to set PR0A register
  2163.  
  2164.         mov dx,03CEh   ;   vga I/O address
  2165.         out dx,ax      ;   set the hioffset value
  2166.  
  2167.         pop dx
  2168.  
  2169.         ret
  2170.  
  2171.  
  2172.  
  2173. ; ---------------------------------------------------------------------------
  2174.  
  2175. ;   .
  2176. endofcode label byte  ; This is the label ref'd in ACODE segment
  2177. CODE      ENDS
  2178.           END
  2179. -- 
  2180. Gene Lee               UUCP: ...!amdahl!ems!minnow!lee
  2181. Unisys Corporation             
  2182. Phone: +1 612 635 3993    CSNET: lee@minnow.SP.Unisys.Com
  2183. If not for the courage of the fearless manager, the paycheck would be lost.
  2184.  
  2185.  
  2186.