Subversion Repositories Games.Rick Dangerous

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1 pmbaty 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
}