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 | } |