Subversion Repositories Games.Rick Dangerous

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * src/draw.c
  3.  *
  4.  * Copyright (C) 1998-2002 BigOrno (bigorno@bigorno.net). All rights reserved.
  5.  *
  6.  * The use and distribution terms for this software are contained in the file
  7.  * named README, which can be found in the root of this distribution. By
  8.  * using this software in any fashion, you are agreeing to be bound by the
  9.  * terms of this license.
  10.  *
  11.  * You must not remove this notice, or any other, from this software.
  12.  */
  13.  
  14. /*
  15.  * NOTES
  16.  *
  17.  * This is the only file which accesses the video. Anything calling d_*
  18.  * function should be video-independant.
  19.  *
  20.  * draw.c draws into a 320x200 or 0x0140x0xc8 8-bits depth frame buffer,
  21.  * using the CGA 2 bits color codes. It is up to the video to figure out
  22.  * how to display the frame buffer. Whatever draw.c does, does not show
  23.  * until the screen is explicitely refreshed.
  24.  *
  25.  * The "screen" is the whole 0x0140 by 0x00c8 screen, coordinates go from
  26.  * 0x0000,0x0000 to 0x013f,0x00c7.
  27.  *
  28.  * The "map" is a 0x0100 by 0x0140 rectangle that represents the active
  29.  * game area.
  30.  *
  31.  * Relative to the screen, the "map" is located at 0x0020,-0x0040 : the
  32.  * "map" is composed of two hidden 0x0100 by 0x0040 rectangles (one at the
  33.  * top and one at the bottom) and one visible 0x0100 by 0x00c0 rectangle (in
  34.  * the middle).
  35.  *
  36.  * The "map screen" is the visible rectangle ; it is a 0x0100 by 0xc0
  37.  * rectangle located at 0x0020,0x00.
  38.  *
  39.  * Coordinates can be relative to the screen, the map, or the map screen.
  40.  *
  41.  * Coordinates can be expressed in pixels. When relative to the map or the
  42.  * map screen, they can also be expressed in tiles, the map being composed
  43.  * of rows of 0x20 tiles of 0x08 by 0x08 pixels.
  44.  */
  45.  
  46. #include "system.h"
  47. #include "game.h"
  48. #include "draw.h"
  49.  
  50. #include "sysvid.h"
  51. #include "sprites.h"
  52. #include "tiles.h"
  53. #include "maps.h"
  54. #include "rects.h"
  55. #include "img.h"
  56.  
  57.  
  58. /*
  59.  * counters positions (pixels, screen)
  60.  */
  61. #define DRAW_STATUS_BULLETS_X 0x68
  62. #define DRAW_STATUS_BOMBS_X 0xA8
  63. #define DRAW_STATUS_SCORE_X 0x28
  64. #define DRAW_STATUS_LIVES_X 0xE8
  65. #define DRAW_STATUS_Y 8
  66.  
  67.  
  68. /*
  69.  * public vars
  70.  */
  71. U8 *draw_tllst; /* pointer to tiles list */
  72. U8 draw_tilesBank; /* tile number offset */
  73. rect_t draw_STATUSRECT =
  74. {
  75.    DRAW_STATUS_SCORE_X,
  76.    DRAW_STATUS_Y,
  77.    DRAW_STATUS_LIVES_X + 6 * 8 - DRAW_STATUS_SCORE_X,
  78.    8,
  79.    NULL
  80. };
  81. rect_t draw_SCREENRECT =
  82. {
  83.    0,
  84.    0,
  85.    320,
  86.    200,
  87.    NULL
  88. };
  89.  
  90.  
  91. /*
  92.  * private vars
  93.  */
  94. static U8 *fb; /* frame buffer pointer */
  95.  
  96.  
  97. /*
  98.  * Set the frame buffer pointer
  99.  *
  100.  * x, y: position (pixels, screen)
  101.  */
  102. void draw_setfb (U32 x, U32 y)
  103. {
  104.    fb = sysvid_fb + x + 320 * y;
  105. }
  106.  
  107.  
  108. /*
  109.  * Clip to map screen
  110.  *
  111.  * x, y: position (pixels, map) CHANGED clipped
  112.  * width, height: dimension CHANGED clipped
  113.  * return: TRUE if fully clipped, FALSE if still (at least partly) visible
  114.  */
  115. U8 draw_clipms (S16 *x, S16 *y, U16 *width, U16 *height)
  116. {
  117.    if (*x < 0)
  118.    {
  119.       if (*x + *width < 0)
  120.          return TRUE;
  121.       else
  122.       {
  123.          *width += *x;
  124.          *x = 0;
  125.       }
  126.    }
  127.    else
  128.    {
  129.       if (*x > 0x0100)
  130.          return TRUE;
  131.       else if (*x + *width > 0x0100)
  132.          *width = 0x0100 - *x;
  133.    }
  134.  
  135.    if (*y < DRAW_XYMAP_SCRTOP)
  136.    {
  137.       if ((*y + *height) < DRAW_XYMAP_SCRTOP)
  138.          return TRUE;
  139.       else
  140.       {
  141.          *height += *y - DRAW_XYMAP_SCRTOP;
  142.          *y = DRAW_XYMAP_SCRTOP;
  143.       }
  144.    }
  145.    else
  146.    {
  147.       if (*y >= DRAW_XYMAP_HBTOP)
  148.          return TRUE;
  149.       else if (*y + *height > DRAW_XYMAP_HBTOP)
  150.          *height = DRAW_XYMAP_HBTOP - *y;
  151.    }
  152.  
  153.    return FALSE;
  154. }
  155.  
  156.  
  157. /*
  158.  * Draw a list of tiles onto the frame buffer
  159.  * start at position indicated by fb ; at the end of each (sub)list,
  160.  * perform a "carriage return + line feed" i.e. go back to the initial
  161.  * position then go down one tile row (8 pixels)
  162.  *
  163.  * ASM 1e33
  164.  * fb: CHANGED (see above)
  165.  * draw_tllst: CHANGED points to the element following 0xfe/0xff end code
  166.  */
  167. void draw_tilesList (void)
  168. {
  169.    U8 *t;
  170.  
  171.    t = fb;
  172.    while (draw_tilesSubList () != 0xFE)
  173.    {
  174.       // draw sub-list
  175.       t += 8 * 320; // go down one tile i.e. 8 lines
  176.       fb = t;
  177.    }
  178. }
  179.  
  180.  
  181. /*
  182.  * Draw a list of tiles onto the frame buffer -- same as draw_tilesList,
  183.  * but accept an immediate string as parameter. Note that the string needs
  184.  * to be properly terminated with 0xfe (\376) and 0xff (\377) chars.
  185.  */
  186. void draw_tilesListImm (U8 *list)
  187. {
  188.    draw_tllst = list;
  189.    draw_tilesList ();
  190. }
  191.  
  192.  
  193. /*
  194.  * Draw a sub-list of tiles onto the frame buffer
  195.  * start at position indicated by fb ; leave fb pointing to the next
  196.  * tile to the right of the last tile drawn
  197.  *
  198.  * ASM 1e41
  199.  * fpb: CHANGED (see above)
  200.  * draw_tllst: CHANGED points to the element following 0xfe/0xff end code
  201.  * returns: end code (0xfe : end of list ; 0xff : end of sub-list)
  202.  */
  203. U8 draw_tilesSubList (void)
  204. {
  205.    U8 i;
  206.  
  207.    i = *(draw_tllst++);
  208.  
  209.    while (i != 0xFF && i != 0xFE)
  210.    {
  211.       /* while not end */
  212.       draw_tile (i); // draw tile
  213.       i = *(draw_tllst++);
  214.    }
  215.  
  216.    return i;
  217. }
  218.  
  219.  
  220. /*
  221.  * Draw a tile
  222.  * at position indicated by fb ; leave fb pointing to the next tile
  223.  * to the right of the tile drawn
  224.  *
  225.  * ASM 1e6c
  226.  * tlnbr: tile number
  227.  * draw_filter: CGA colors filter
  228.  * fb: CHANGED (see above)
  229.  */
  230. void draw_tile (U8 tileNumber)
  231. {
  232.    U8 i, k, *f;
  233.    U32 x;
  234.  
  235.    f = fb; // frame buffer
  236.  
  237.    for (i = 0; i < 8; i++)
  238.    {
  239.       /* for all 8 pixel lines */
  240.       x = tiles_data[draw_tilesBank][tileNumber][i];
  241.  
  242.       /*
  243.        * tiles / perform the transformation from ST 4 bits
  244.        * per pixel to frame buffer 8 bits per pixels
  245.        */
  246.       for (k = 8; k--; x >>= 4)
  247.          f[k] = (U8) x & 0x0F;
  248.  
  249.       f += 320; /* next line */
  250.    }
  251.  
  252.    fb += 8; /* next tile */
  253. }
  254.  
  255.  
  256. /*
  257.  * Draw a sprite
  258.  *
  259.  * ASM 1a09
  260.  * nbr: sprite number
  261.  * x, y: sprite position (pixels, screen)
  262.  * fb: CHANGED
  263.  */
  264. void draw_sprite (U8 number, U16 x, U16 y)
  265. {
  266.    U8 i, j, k, *f;
  267.    U16 g;
  268.    U32 d;
  269.  
  270.    draw_setfb (x, y);
  271.    g = 0;
  272.  
  273.    for (i = 0; i < 0x15; i++)
  274.    {
  275.       /* rows */
  276.       f = fb;
  277.  
  278.       for (j = 0; j < 4; j++)
  279.       {
  280.          /* cols */
  281.          d = sprites_data[number][g++];
  282.  
  283.          /*
  284.           * sprites / perform the transformation from ST 4 bits
  285.           * per pixel to frame buffer 8 bits per pixels
  286.           */
  287.          for (k = 8; k--; d >>= 4)
  288.             if (d & 0x0F)
  289.                f[k] = (f[k] & 0xF0) | ((U8) d & 0x0F);
  290.  
  291.          f += 8;
  292.       }
  293.  
  294.       fb += 320;
  295.    }
  296. }
  297.  
  298.  
  299. /*
  300.  * Draw a sprite
  301.  *
  302.  * NOTE re-using original ST graphics format
  303.  */
  304. void draw_sprite2 (U8 number, U16 x, U16 y, U8 front)
  305. {
  306.    U32 d = 0; /* sprite data */
  307.    S16 x0, y0; /* clipped x, y */
  308.    U16 w, h; /* width, height */
  309.    S16 g, /* sprite data offset*/
  310.        r, c, /* row, column */
  311.        i, /* frame buffer shifter */
  312.        im; /* tile flag shifter */
  313.    U8 flg; /* tile flag */
  314.  
  315.    x0 = x;
  316.    y0 = y;
  317.    w = 0x20;
  318.    h = 0x15;
  319.  
  320.    if (draw_clipms (&x0, &y0, &w, &h))   /* return if not visible */
  321.       return;
  322.  
  323.    g = 0;
  324.    draw_setfb (x0 - DRAW_XYMAP_SCRLEFT, y0 - DRAW_XYMAP_SCRTOP);
  325.  
  326.    for (r = 0; r < 0x15; r++)
  327.    {
  328.       if (r >= h || y + r < y0)
  329.          continue;
  330.  
  331.       i = 0x1f;
  332.       im = x - (x & 0xfff8);
  333.       flg = map_eflg[map_map[(y + r) >> 3][(x + 0x1f)>> 3]];
  334.  
  335. #define LOOP(N, C0, C1) \
  336.       d = sprites_data[number][g + N]; \
  337.       \
  338.       for (c = C0; c >= C1; c--, i--, d >>= 4, im--) \
  339.       { \
  340.          if (im == 0) \
  341.          { \
  342.             flg = map_eflg[map_map[(y + r) >> 3][(x + c) >> 3]]; \
  343.             im = 8; \
  344.          } \
  345. \
  346.          if (!front && (flg & MAP_EFLG_FGND)) \
  347.             continue; \
  348.          if (c >= w || x + c < x0) \
  349.             continue; \
  350.          if (d & 0x0F) \
  351.             fb[i] = (fb[i] & 0xF0) | ((U8) d & 0x0F); \
  352.       }
  353.  
  354.       LOOP(3, 0x1f, 0x18);
  355.       LOOP(2, 0x17, 0x10);
  356.       LOOP(1, 0x0f, 0x08);
  357.       LOOP(0, 0x07, 0x00);
  358.  
  359. #undef LOOP
  360.  
  361.       fb += 320;
  362.       g += 4;
  363.    }
  364. }
  365.  
  366.  
  367.  
  368. /*
  369.  * Redraw the map behind a sprite
  370.  * align to tile column and row, and clip
  371.  *
  372.  * x, y: sprite position (pixels, map).
  373.  */
  374. void draw_spriteBackground (U16 x, U16 y)
  375. {
  376.    U8 r, c;
  377.    U16 rmax, cmax;
  378.    S16 xmap, ymap;
  379.    U16 xs, ys;
  380.  
  381.    /* aligne to column and row, prepare map coordinate, and clip */
  382.    xmap = x & 0xFFF8;
  383.    ymap = y & 0xFFF8;
  384.    cmax = (x - xmap == 0 ? 0x20 : 0x28); /* width, 4 tl cols, 8 pix each */
  385.    rmax = (y & 0x04) ? 0x20 : 0x18; /* height, 3 or 4 tile rows */
  386.  
  387.    if (draw_clipms (&xmap, &ymap, &cmax, &rmax))   /* don't draw if fully clipped */
  388.       return;
  389.  
  390.    /* get back to screen */
  391.    xs = xmap - DRAW_XYMAP_SCRLEFT;
  392.    ys = ymap - DRAW_XYMAP_SCRTOP;
  393.    xmap >>= 3;
  394.    ymap >>= 3;
  395.    cmax >>= 3;
  396.    rmax >>= 3;
  397.  
  398.    /* draw */
  399.    for (r = 0; r < rmax; r++)
  400.    {
  401.       /* for each row */
  402.       draw_setfb (xs, ys + r * 8);
  403.  
  404.       for (c = 0; c < cmax; c++)
  405.          draw_tile (map_map[ymap + r][xmap + c]); // for each column
  406.    }
  407. }
  408.  
  409.  
  410. /*
  411.  * Draw entire map screen background tiles onto frame buffer.
  412.  *
  413.  * ASM 0af5, 0a54
  414.  */
  415. void draw_map (void)
  416. {
  417.    U8 i, j;
  418.  
  419.    draw_tilesBank = map_tilesBank;
  420.  
  421.    for (i = 0; i < 0x18; i++)
  422.    {
  423.       /* 0x18 rows */
  424.       draw_setfb (0x20, i * 8);
  425.  
  426.       for (j = 0; j < 0x20; j++)
  427.          draw_tile (map_map[i + 8][j]); // 0x20 tiles per row
  428.    }
  429. }
  430.  
  431.  
  432. /*
  433.  * Draw status indicators
  434.  *
  435.  * ASM 0309
  436.  */
  437. void draw_drawStatus (void)
  438. {
  439.    S8 i;
  440.    U32 sv;
  441.    static U8 s[7] = {0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0xfe};
  442.  
  443.    draw_tilesBank = 0;
  444.    for (i = 5, sv = game_score; i >= 0; i--)
  445.    {
  446.       s[i] = 0x30 + (U8) (sv % 10);
  447.       sv /= 10;
  448.    }
  449.    draw_tllst = s;
  450.    draw_setfb (DRAW_STATUS_SCORE_X, DRAW_STATUS_Y);
  451.    draw_tilesList ();
  452.  
  453.    draw_tilesBank = 0;
  454.    draw_setfb (DRAW_STATUS_BULLETS_X, DRAW_STATUS_Y);
  455.    for (i = 0; i < game_bullets; i++)
  456.       draw_tile (TILES_BULLET);
  457.    draw_tilesBank = map_tilesBank;
  458.    for (; i < 6; i++)
  459.       draw_tile (map_map[DRAW_STATUS_Y / 8 + 8][DRAW_STATUS_BULLETS_X / 8 + i - 4]);
  460.  
  461.    draw_tilesBank = 0;
  462.    draw_setfb (DRAW_STATUS_BOMBS_X, DRAW_STATUS_Y);
  463.    for (i = 0; i < game_bombs; i++)
  464.       draw_tile (TILES_BOMB);
  465.    draw_tilesBank = map_tilesBank;
  466.    for (; i < 6; i++)
  467.       draw_tile (map_map[DRAW_STATUS_Y / 8 + 8][DRAW_STATUS_BOMBS_X / 8 + i - 4]);
  468.  
  469.    draw_tilesBank = 0;
  470.    draw_setfb (DRAW_STATUS_LIVES_X, DRAW_STATUS_Y);
  471.    for (i = 0; i < game_lives; i++)
  472.       draw_tile (TILES_RICK);
  473.    draw_tilesBank = map_tilesBank;
  474.    for (; i < 6; i++)
  475.       draw_tile (map_map[DRAW_STATUS_Y / 8 + 8][DRAW_STATUS_LIVES_X / 8 + i - 4]);
  476. }
  477.  
  478.  
  479. /*
  480.  * Draw a picture
  481.  */
  482. void draw_pic (U16 x, U16 y, U16 w, U16 h, U32 *pic)
  483. {
  484.    U8 *f;
  485.    U16 i, j, k, pp;
  486.    U32 v;
  487.  
  488.    draw_setfb (x, y);
  489.    pp = 0;
  490.  
  491.    for (i = 0; i < h; i++)
  492.    {
  493.       /* rows */
  494.       f = fb;
  495.  
  496.       for (j = 0; j < w; j += 8)
  497.       {
  498.          /* cols */
  499.          v = pic[pp++];
  500.  
  501.          for (k = 8; k--; v >>=4)
  502.             f[k] = (U8) v & 0x0F;
  503.          f += 8;
  504.       }
  505.  
  506.       fb += 320;
  507.    }
  508. }
  509.