home *** CD-ROM | disk | FTP | other *** search
/ Collection of Hack-Phreak Scene Programs / cleanhpvac.zip / cleanhpvac / FAQSYS18.ZIP / FAQS.DAT / PRITCH.TXT < prev    next >
Text File  |  1996-01-11  |  13KB  |  392 lines

  1. Listing 1. A 256-Color Sprite
  2. /*    ========================================================================    */
  3. /*    COMPLBMP.C - Routine to compile a 256-color bitmap image for                */
  4. /*                    Mode X or Mode 13h.                                        */
  5. /*    Author:  Matt Pritchard for Game Developer Magazine.                        */
  6. /*              Adapted from MODEX108                                            */
  7. /*    ========================================================================    */
  8.  
  9.     /*    This stuff could go into a .h file            */
  10.  
  11.     /*    Macro Definitions needed by Compile_Bitmap    */
  12.  
  13. #define ucharf    unsigned char far
  14. #define uchar    unsigned char
  15. #define uint        unsigned int
  16.  
  17. #define hi_word( x )    (unsigned char)    (x >> 8)
  18. #define lo_word( x )    (unsigned char)    (x & 0x00FF)
  19.  
  20.     /* Prototypes for Compiled Bitmap Routines */
  21.  
  22. ucharf * Compile_Bitmap (ucharf *, int, int, int, int);
  23.  
  24. void far pascal draw_compiled_bitmap (uchar far *, int, ints);
  25. void far pascal draw_compiled_bitmap_13h (uchar far *, int, ints);
  26.  
  27. /* ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ*/
  28.  
  29. /*    This function takes a Sprite that is stored in a two-dimensional array, such
  30.     as char ImageData[32][32], and creates a buffer that contains the machine
  31.     language code to quickly draw that image in Mode 13h or Mode X.
  32.  
  33.     The sprite data is stored line by line, from top to bottom.  Each line
  34.     is stored from left to right.  A transparant color value is used to
  35.     indicate which pixels are not part of the image and should not be drawn.
  36.  
  37.     Because Mode X supports various screen sizes, we must know the width
  38.     of the screen a sprite will be displayed on in advance.  For Mode 13h,
  39.     that width is normally 320.
  40.  
  41.     When possible, two adjacent pixels will be drawn with one 16-bit MOV
  42.     instruction.  This results in smaller and faster code.
  43.  
  44.     This function allocates a buffer to hold the compiled code and 
  45.     returns a far pointer to it.  The pointer need only be a char type
  46.     pointer, since our assembly language routine does the actual calling of it.
  47.  
  48.     If the sprite is too big or the program has run out of memory, a null pointer
  49.     is returned, otherwise a pointer to the compiled code is returned.    
  50. */
  51.  
  52. ucharf * Compile_Bitmap (ucharf * theImage,    /* Far Ptr to the Sprite     */
  53. int X_width,                                    /* Width of the Sprite    */
  54. int Y_width,                                    /* Height of the Sprite     */
  55. int Trans_Color,                                /* Transparent Color     */
  56. int Screen_Width)                            /* Width of the screen    */
  57. {
  58.  
  59.     int    x, y, p;                                /* Loop counters for X, Y, and plane    */
  60.     int    Words, Bytes;                        /* Count of each type of instruction    */
  61.     int    b1, b2;                                /* Valid pixel flags                    */
  62.     uint    VidOffset, Offset;                    /* Offsets for memory calculations    */
  63.  
  64.     int    BytesPerLine;                        /* Width of display in address bytes    */
  65.     long    CompiledBufferSize;                    /* The size of the compiled sprite code*/
  66.     long    c;                                    /* Counter for the code writing loop    */
  67.  
  68.     ucharf * theBuffer;                        /* Pointer to the compiled code buffe    */
  69.  
  70.     int    Num_Planes;                            /* The number of video planes (4 or 1)*/
  71.     int    Next_Pixel;                            /* The number of bytes between adjacent pixel*/
  72.     int    Code_Overhead;                        /* Size of any overhead code needed        */
  73.  
  74. /*    The variable Mode_X controls if we are compiling a sprite for Mode 13h or
  75.     Mode X.  For Mode X, we must split the image into four separate planes and
  76.     add plane switching code to the compiled sprite.  If the value of Mode_X is
  77.     0, we compile for Mode 13h, otherwise we compile for Mode X.                    */
  78.  
  79.     int    Mode_X = -1;        /* -1 = Mode X,  0 = Mode 13h                                */
  80.  
  81.     if (Mode_X) {
  82.         Num_Planes = 4;
  83.         Next_Pixel = 4;
  84.         Code_Overhead = 20;
  85.     } else {
  86.         Num_Planes = 1;
  87.         Next_Pixel = 1;
  88.         Code_Overhead = 5;
  89.     }
  90.  
  91.     BytesPerLine = Screen_Width / Num_Planes;
  92.  
  93. /*    First, we pass through the bitmap and count up the number of adjacent pixel
  94.     pairs and the number of single pixels. With this information, we will know
  95.     how big a buffer to allocate.                                                    */
  96.     Words = Bytes = 0;
  97.  
  98.     for (p = 0; p < Num_Planes; p++)
  99.     {
  100.         for (y = 0; y < Y_width; y++)
  101.         {
  102.             Offset = y * X_width;
  103.             for (x = p; x < X_width; x+=Next_Pixel)
  104.             {
  105.                 /* Check the current pixel to see if it should be displayed        */
  106.  
  107.                 b1 = (theImage[Offset+x] != Trans_Color) ? -1 : 0;
  108.  
  109.                 /*    Check the next adjacent pixel (if there is one), and see if
  110.                     it should also be displayed                                    */
  111.  
  112.                 if  ((x + Next_Pixel) < X_width) {
  113.                     b2 = (theImage[Offset+x+Next_Pixel] != Trans_Color) ? -1 : 0;
  114.                 } else {
  115.                     b2 = 0;
  116.                 }
  117.  
  118.                 /* Check for a pair of adjacent pixels, or a lone single pixel        */
  119.  
  120.                 if (b1) {
  121.                     if (b2) {
  122.                         Words++;        /*    Another adjacent pixel pair                */
  123.                     x+=Next_Pixel;    /*    Skip over the next pixel                    */
  124.                         } else {
  125.                     Bytes++;            /*    One more lone pixel                        */
  126.                     }
  127.                 }
  128.             }
  129.         }
  130.     }
  131.  
  132. /*    Determine how big a buffer we need for the compiled code, allocate it, and
  133.     get a far pointer to it.    */
  134.     CompiledBufferSize = Code_Overhead + (6 * Words) + (5 * Bytes);
  135.  
  136. /*    Here is where the users can insert their own error handling code                */
  137.     if (CompiledBufferSize > 65535) {
  138.         /*    Error; compiled sprite would be too large (greater than 64K).            */
  139.         return (0);
  140.     }
  141.  
  142.     if ( (theBuffer = (ucharf *) malloc( (size_t) CompiledBufferSize)) == 0) {
  143.         /*    Error allocating buffer; out of memory.                                */
  144.         return (0);
  145.     }
  146.  
  147. /*    Now, we go through the image again, this time creating the code to write into
  148.     the compile code buffer.                                                        */
  149.  
  150.     c = 0;
  151.     for (p = 0; p < Num_Planes ; p++)
  152.     {
  153.         for (y = 0; y < Y_width; y++)
  154.         {
  155.             Offset = y * X_width;
  156.             for (x = p; x < X_width; x+=Next_Pixel)
  157.             {
  158.  
  159.             /*    Check the current pixel to see if it should be displayed        */
  160.  
  161.             b1 = (theImage[Offset+x] != Trans_Color) ? -1 : 0;
  162.  
  163.             /*    Check the next adjacent pixel (if there is one), and see if it
  164.                 should also be displayed                                         */
  165.  
  166.             if ((x + Next_Pixel) < X_width) {
  167.                 b2 = (theImage[Offset+x+Next_Pixel] != Trans_Color) ? -1 : 0;
  168.             } else {
  169.                 b2 = 0;
  170.             }
  171.  
  172.             /*    Generate code for a pair of pixels, or for a single pixel.        */
  173.  
  174.             if (b1) {
  175.                 VidOffset = (BytesPerLine * y) + ((x-p) / Num_Planes);
  176.  
  177.         if (b2) {            /*    Create Code to write Word Constant            */
  178.  
  179.             theBuffer[c++] = 0xC7;                        /*    MOV word ptr        */
  180.             theBuffer[c++] = 0x87;
  181.             theBuffer[c++] = lo_word( VidOffset );        /*    BX+VidOffset        */
  182.             theBuffer[c++] = hi_word( VidOffset );
  183.             theBuffer[c++] = (uchar) theImage[Offset+x];
  184.             theBuffer[c++] = (uchar) theImage[Offset+x+Next_Pixel];
  185.  
  186.             x+=Next_Pixel;                                /*    Skip over second pixel*/
  187.  
  188.         } else {                                            /*    Create Code to write Byte Constant*/
  189.  
  190.             theBuffer[c++] = 0xC6;                        /*    MOV byte ptr        */
  191.             theBuffer[c++] = 0x87;
  192.             theBuffer[c++] = lo_word( VidOffset );        /*    BX+VidOffset        */
  193.             theBuffer[c++] = hi_word( VidOffset );
  194.             theBuffer[c++] = (uchar) theImage[Offset+x];
  195.                 }
  196.             }
  197.         }
  198.     }
  199.  
  200.         if ( (Mode_X) && (p < 3) ) {                        /*    Generate plane switching code*/
  201.  
  202.             theBuffer[c++] = 0xD0;                        /*    ROL    AL, 1    ; Get New mask*/
  203.             theBuffer[c++] = 0xC0;
  204.             theBuffer[c++] = 0x13;                        /*    ADC    BX, CX    ; Add in Addr wrap*/
  205.             theBuffer[c++] = 0xD9;
  206.             theBuffer[c++] = 0xEE;                        /*    OUT    DX, AL    ; Select new Plane*/
  207.         }
  208.     }
  209.  
  210.     /*    Create exit code to return to the calling program    */
  211.  
  212.     theBuffer[c++] = 0x5D;                                /*    POP    BP    ; Restore BP        */
  213.     theBuffer[c++] = 0x1F;                                /*    POP    DS    ; Restore DS        */
  214.     theBuffer[c++] = 0xCA;                                /*    RETF    8    ; Exit & Clean Up Stack*/
  215.     theBuffer[c++] = 0x08;
  216.     theBuffer[c++] = 0x00;
  217.  
  218.     /*    Return a pointer to the Buffer containing the Compiled Code            */
  219.  
  220.     return (theBuffer);
  221.  
  222. }
  223. Listing 2. Compiled Sprite Setup and Call Routine
  224. ; =========================================================;
  225. ; COMPLBMP.ASM  - Compiled Sprite Setup & Call Routines for;
  226. ;                      Mode X or Mode 13h.                        ;
  227. ; Author;  Matt Pritchard for Game Developer Magazine.        ;
  228. ;              Adapted from MODEX108                            ;
  229. ; Assembler Used; MASM 5.10a                                    ;
  230. ; =========================================================;
  231.  
  232. .MODEL Medium
  233. .286
  234. .CODE
  235.  
  236. ; ===== General Constants & Macros =====
  237.  
  238. wp    EQU    WORD PTR
  239. dp    EQU    DWORD PTR
  240. fp    EQU    FAR PTR
  241.  
  242. ; ===== VGA Register Values & Constants =====
  243.  
  244. VGA_Segment        EQU    0A000h                ;Vga Memory Segment
  245.  
  246. SC_Index            EQU    03C4h                 ; VGA Sequencer Controller
  247. SC_Data                EQU    03C5h                ; VGA Sequencer Data Port
  248.  
  249. MAP_MASK_PLANE2     EQU    01102h                 ; Map Register + Plane 1
  250. PLANE_BITS         EQU     03h                ; Bits 0-1 of Xpos = Plane#
  251.  
  252. ;==========================================================
  253. ;  DRAW_COMPILED_BITMAP (CompiledImage, X_pos, Y_Pos)
  254. ;==========================================================
  255. ;
  256. ; Sets up a call to a compiled bitmap in Mode X.
  257. ;
  258. ; ENTRY;    Image  = Far Pointer to Compiled Bitmap Data
  259. ;             Xpos   = X position to Place Upper Left pixel at
  260. ;             Ypos   = Y position to Place Upper Left pixel at
  261. ;
  262. ; EXIT;  No meaningful values returned
  263. ;
  264.  
  265.   DCB_STACK    STRUC
  266.                 DW  ?,?                        ; DS, BP
  267.                 DD  ?                        ; Caller
  268.   DCB_Ypos        DW  ?                         ; Y position to Draw Bitmap at
  269.   DCB_Xpos        DW  ?                         ; X position to Draw Bitmap at
  270.   DCB_Image        DD  ?                         ; Far Pointer to Graphics Bitmap
  271.   DCB_STACK    ENDS
  272.  
  273.   PUBLIC     DRAW_COMPILED_BITMAP
  274.  
  275.   DRAW_COMPILED_BITMAP    PROC    FAR
  276.  
  277.   Push    DS                                     ; Save DS
  278.   Push    BP                                    ; AX-DX are destroyed
  279.   Mov    BP,    SP                                 ; Set up Stack Frame
  280.  
  281. ; Get DS;BX to point to (Xpos,Ypos) on the current
  282. ; display page in VGA memory
  283.  
  284. ; ***** USER NOTE ***** MODIFY AS NEEDED *****
  285. ;
  286. ; Line_Offset is lookup table containing the start
  287. ; offset for each line in VGA display memory.
  288. ; Here, I assume it to be a table of word values
  289. ; which are stored in the current code segment.
  290.  
  291.   Mov    BX,    [BP].DCB_Ypos                 ; BX = Ypos
  292.   Add    BX,    BX                             ; Scale BX to Word Offset
  293.   Mov    BX,    wp CS;Line_Offset[BX]     ; Get Offset of Line Ypos
  294.  
  295.   Mov    AX,    [BP].DCB_Xpos                  ; Get UL Corner Xpos
  296.   Mov    CL, AL                            ; Save Plane # in CL
  297.   Shr    AX,    2                             ; X/4 = Offset Into Line
  298. ; ***** USER NOTE ***** MODIFY AS NEEDED *****
  299. ;
  300. ; CURRENT PAGE is a DWORD pointer to the currently active
  301. ; Mode X video memory page.  The first word is the offset
  302. ; into the video adaptor, and the second is the constant
  303. ; value of A000 - the VGAOs graphics memory segment.
  304. ; Here, I assume it to be in DGROUP.
  305.  
  306.   Lds    DX,    dp CURRENT_PAGE             ; Get Current VGA Page
  307.   Add    BX,    DX                             ; DS;BX->Start of Line
  308.   Add    BX,    AX                             ; DS;BX->Upper Left Pixel
  309.  
  310. ; Select the first video plane, and set up the registers
  311. ; so the next 3 planes can be quickly selected.
  312.  
  313.   And    CL,    PLANE_BITS                 ; CL = Starting Plane #
  314.   Mov    AX,    MAP_MASK_PLANE2             ; Mask & Plane Select
  315.   Shl    AH,    CL                            ; Select correct Plane
  316.   Mov    DX,    SC_Index                     ; VGA Sequencer ports
  317.   Out    DX,    AX                             ; Set Initial Vid Plane
  318.   Inc    DX                                 ; Point DX to SC_Data
  319.   Mov    AL,    AH                             ; Mask for future OUTOs
  320.   Clr    CX                                 ; CX = Constant 0
  321.  
  322. ; Setup DS;    BX = Upper left corner of Image in VGA memory
  323. ;                BP = Local Stack Frame
  324. ;                AL = OUT mask for Selecting video Plane
  325. ;                CX = Constant value 0 for ADC
  326. ;                DX = SC_Data; VGA Sequencer Data Port
  327. ;                AH = Destroyed
  328. ;                SI,DI = Not modified during call
  329. ;
  330. ; Now we jump to the compiled code which actually draws the
  331. ; sprite.  The compiled code will return to the caller.
  332.  
  333.  Jmp     dp [BP].DCB_Image                 ; Draw Sprite
  334.  
  335.   DRAW_COMPILED_BITMAP    ENDP
  336.  
  337.  
  338.  
  339. ;=============================================================
  340. ;  DRAW_COMPILED_BITMAP_13h (CompiledImage, X_pos, Y_Pos)
  341. ;=============================================================
  342. ;
  343. ; Sets up a call to a compiled bitmap in Mode 13h.
  344. ;
  345. ; ENTRY;    Image  = Far Pointer to Compiled Bitmap Data
  346. ;            Xpos   = X position to Place Upper Left pixel at
  347. ;             Ypos   = Y position to Place Upper Left pixel at
  348. ;
  349. ; EXIT;  No meaningful values returned
  350. ;
  351.  
  352.   PUBLIC    DRAW_COMPILED_BITMAP_13H
  353.  
  354.   DRAW_COMPILED_BITMAP_13H    PROC    FAR
  355.  
  356.   Push    DS                                         ; Save DS
  357.   Push    BP                                         ; AX-DX are destroyed
  358.   Mov    BP,,    SP                                 ; Set up Stack Frame
  359.  
  360. ; Get DS;BX to point to (Xpos, Ypos) in VGA memory
  361.  
  362. ; ***** USER NOTE ***** MODIFY AS NEEDED *****
  363. ;
  364. ; Line_Offset is lookup table containing the start
  365. ; offset for each line in VGA display memory.
  366. ; Here, I assume it to be a table of word values
  367. ; which are stored in the current code segment.
  368.  
  369.   Mov    BX,    [BP].DCB_Ypos                         ; BX = Ypos
  370.   Add    BX,    BX                                     ; Scale BX to Word Offset
  371.   Mov    BX,    wp CS;Line_Offset[BX]             ; Get Offset of Line Ypos
  372.   Add    BX,    BP].DCB_Xpos                         ; Get UL Corner of Sprite
  373.  
  374.   Mov    AX,    VGA_Segment                         ; Segment A000
  375.   Mov    DS,    AX                                     ; DS;BX -> VGA memory
  376.  
  377. ; Setup DS;    BX = Upper left corner of Image in VGA memory
  378. ;                BP = Local Stack Frame
  379. ;                AX = Destroyed
  380. ;         SI,    DI = Not modified during call
  381. ;         CX,    DX = Not modified during call
  382. ;
  383. ; Now we jump to the compiled code which actually draws the
  384. ; sprite.  The compiled code will return to the caller.
  385.  
  386.   Jmp    dp [BP].    DCB_Image                     ; Draw Sprite
  387.  
  388. DRAW_COMPILED_BITMAP_13H     ENDP
  389.  
  390.   END
  391.  
  392.