1 /*
2 * cg.c load and display cg
3 *
4 * Copyright (C) 1997-1998 Masaki Chikama (Wren) <chikama@kasumi.ipl.mech.nagoya-u.ac.jp>
5 * 1998- <masaki-c@is.aist-nara.ac.jp>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 *
21 */
22 /* $Id: cg.c,v 1.12 2001/09/16 15:59:11 chikama Exp $ */
23
24 #include <stdio.h>
25 #include <glib.h>
26 #include "portab.h"
27 #include "system.h"
28 #include "graphics.h"
29 #include "nact.h"
30 #include "ags.h"
31 #include "cg.h"
32 #include "vsp.h"
33 #include "pms.h"
34 #include "bmp.h"
35 #include "qnt.h"
36 #include "ald_manager.h"
37 #include "savedata.h"
38 #include "cache.h"
39
40 /* VSP�Υѥ�å�Ÿ���Х� */
41 int cg_vspPB = -1;
42 /* cg,pallet Ÿ���ե饰 (funciotn flag) */
43 int cg_fflg = 7;
44 /* CG����ɤ������������ѿ� */
45 int *cg_loadCountVar = NULL;
46 /* CG�����ٻ��� */
47 int cg_alphaLevel = 255;
48
49 #define GCMD_EXTRACTCG(c) ((c) & 0x01)
50 #define GCMD_SET_PALLET(c) ((c) & 0x02)
51 #define GCMD_LOAD_PALLET(c) ((c) & 0x04)
52
53 /* CGɽ�����֤˴ؤ������ */
54 static CG_WHERETODISP loc_policy = OFFSET_NOMOVE, loc_policy0;
55 static MyPoint loc_where, loc_where0;
56
57 /* extracted cg data cache control object */
58 static cacher *cacheid;
59
60 /* static methods */
61 static CG_TYPE check_cgformat(BYTE *data);
62 static void set_vspbank(BYTE *pic, int bank, int width, int height);
63 static void cgdata_free(cgdata *cg);
64 static MyPoint set_display_loc(cgdata *cg);
65 static void clear_display_loc();
66 static void display_cg(cgdata *cg, int x, int y);
67 static cgdata *loader(int no);
68
69
70 /*
71 * Identify cg format
72 * data: pointer to compressed data
73 * return: cg type
74 */
check_cgformat(BYTE * data)75 static CG_TYPE check_cgformat(BYTE *data) {
76 if (qnt_checkfmt(data)) {
77 return ALCG_QNT;
78 } else if (pms256_checkfmt(data)) {
79 return ALCG_PMS8;
80 } else if (pms64k_checkfmt(data) && nact->sys_world_depth >= 15) {
81 return ALCG_PMS16;
82 } else if (bmp16m_checkfmt(data) && nact->sys_world_depth >= 15) {
83 return ALCG_BMP24;
84 } else if (bmp256_checkfmt(data)) {
85 return ALCG_BMP8;
86 } else if (vsp_checkfmt(data)) {
87 return ALCG_VSP;
88 }
89 WARNING("Unknown Cg Type\n");
90 return ALCG_UNKNOWN;
91 }
92
93 /*
94 * Modify pixel accoding to pallet bank (vsp only)
95 * pic : pixel to be modifyied.
96 * bank : pallet bank (use only MSB 4bit)
97 * width : image width
98 * height: image height
99 */
set_vspbank(BYTE * pic,int bank,int width,int height)100 static void set_vspbank(BYTE *pic, int bank, int width, int height) {
101 int pixels = width * height;
102
103 while (pixels--) {
104 *pic = (*pic & 0x0f) | (BYTE)bank; pic++;
105 }
106 }
107
108 /*
109 * Free data
110 * cg: freeing data object
111 */
cgdata_free(cgdata * cg)112 static void cgdata_free(cgdata *cg) {
113 if (cg->pic) g_free(cg->pic);
114 if (cg->pal) g_free(cg->pal);
115 if (cg->alpha) g_free(cg->alpha);
116 g_free(cg);
117 }
118
119 /*
120 * Determine the location of display image
121 * cg: cg information
122 * return: x and y for display location
123 */
set_display_loc(cgdata * cg)124 static MyPoint set_display_loc(cgdata *cg) {
125 MyPoint p;
126
127 switch(loc_policy) {
128 case OFFSET_ABSOLUTE_GC:
129 case OFFSET_ABSOLUTE_JC:
130 p.x = loc_where.x;
131 p.y = loc_where.y;
132 break;
133 case OFFSET_RELATIVE_GC:
134 case OFFSET_RELATIVE_JC:
135 p.x = cg->x + loc_where.x;
136 p.y = cg->y + loc_where.y;
137 break;
138 case OFFSET_NOMOVE:
139 p.x = cg->x;
140 p.y = cg->y;
141 break;
142 }
143 return p;
144 }
145
146 /*
147 * Reset location movement according to loc_policy
148 */
clear_display_loc()149 static void clear_display_loc() {
150 switch(loc_policy) {
151 case OFFSET_ABSOLUTE_GC:
152 case OFFSET_RELATIVE_GC:
153 if (loc_policy0 == OFFSET_ABSOLUTE_JC ||
154 loc_policy0 == OFFSET_RELATIVE_JC ) {
155 loc_policy = loc_policy0;
156 loc_where = loc_where0;
157 loc_policy0 = OFFSET_NOMOVE;
158 } else {
159 loc_policy = OFFSET_NOMOVE;
160 }
161 break;
162 default:
163 break;
164 }
165 }
166
167 /*
168 * Call ags to display cg
169 * cg: cg to be drawn
170 * x : display location x
171 * y : display location y
172 */
display_cg(cgdata * cg,int x,int y)173 static void display_cg(cgdata *cg, int x, int y) {
174 /* always set cg's alpha level */
175 cg->alphalevel = cg_alphaLevel;
176
177 /* draw cg */
178 switch(cg->type) {
179 case ALCG_VSP:
180 case ALCG_PMS8:
181 case ALCG_BMP8:
182 ags_drawCg8bit(cg, x, y); break;
183 case ALCG_PMS16:
184 case ALCG_BMP24:
185 ags_drawCg16bit(cg, x, y); break;
186 default:
187 break;
188 }
189
190 /* update drawn area */
191 ags_updateArea(x, y, cg->width, cg->height);
192 }
193
194 /*
195 * Load cg data from file or cache
196 * no: file no ( >= 0)
197 * return: cg object(extracted)
198 */
loader(int no)199 static cgdata *loader(int no) {
200 dridata *dfile;
201 cgdata *cg = NULL;
202 int type, size = 0;
203
204 /* search in cache */
205 if (NULL != (cg = (cgdata *)cache_foreach(cacheid, no))) return cg;
206
207 /* read from file */
208 if (NULL == (dfile = ald_getdata(DRIFILE_CG, no))) return NULL;
209
210 /* update load cg counter */
211 if (cg_loadCountVar != NULL) {
212 (*(cg_loadCountVar + no + 1))++;
213 }
214
215 /* check loaded cg format */
216 type = check_cgformat(dfile->data);
217
218 /* extract cg */
219 /* size is only pixel data size */
220 if (GCMD_EXTRACTCG(cg_fflg)) {
221 switch(type) {
222 case ALCG_VSP:
223 cg = vsp_extract(dfile->data);
224 size = cg->width * cg->height;
225 break;
226 case ALCG_PMS8:
227 cg = pms256_extract(dfile->data);
228 size = cg->width * cg->height;
229 break;
230 case ALCG_PMS16:
231 cg = pms64k_extract(dfile->data);
232 size = (cg->width * cg->height) * sizeof(WORD);
233 break;
234 case ALCG_BMP8:
235 cg = bmp256_extract(dfile->data);
236 size = cg->width * cg->height;
237 break;
238 case ALCG_BMP24:
239 cg = bmp16m_extract(dfile->data);
240 size = (cg->width * cg->height) * sizeof(WORD);
241 break;
242 case ALCG_QNT:
243 cg = qnt_extract(dfile->data);
244 size = (cg->width * cg->height) * 3;
245 break;
246 default:
247 break;
248 }
249 /* insert to cache */
250 if (cg)
251 cache_insert(cacheid, no, cg, size, NULL);
252 }
253
254 /* load pallet if not extracted */
255 if (GCMD_LOAD_PALLET(cg_fflg) && cg == NULL) {
256 /* XXXX ���ࡢ�����Ĥ�ɤ��Dz��������� */
257 switch(type) {
258 case ALCG_VSP:
259 cg = vsp_getpal(dfile->data);
260 break;
261 case ALCG_PMS8:
262 cg = pms_getpal(dfile->data);
263 break;
264 case ALCG_BMP8:
265 cg = bmp_getpal(dfile->data);
266 break;
267 default:
268 break;
269 }
270 }
271
272 /* ok to free */
273 ald_freedata(dfile);
274
275 return cg;
276 }
277
278 /*
279 * Initilize cache
280 */
cg_init()281 void cg_init() {
282 cacheid = cache_new(cgdata_free);
283 }
284
285 /*
286 * Set cg display location
287 * x : display location x
288 * y : display location y
289 * policy: location offset policy
290 */
cg_set_display_location(int x,int y,CG_WHERETODISP policy)291 void cg_set_display_location(int x, int y, CG_WHERETODISP policy) {
292 if (policy == OFFSET_ABSOLUTE_GC || policy == OFFSET_RELATIVE_GC) {
293 if (loc_policy == OFFSET_ABSOLUTE_JC ||
294 loc_policy == OFFSET_RELATIVE_JC) {
295 loc_policy0 = loc_policy;
296 loc_where0 = loc_where;
297 }
298 }
299
300 loc_policy = policy;
301 loc_where.x = x;
302 loc_where.y = y;
303 }
304
305 /*
306 * Load and display cg
307 * no : file no ( >= 0)
308 * flg: sprite color(!-1)
309 */
cg_load(int no,int flg)310 void cg_load(int no, int flg) {
311 cgdata *cg;
312 MyPoint p;
313 int i, bank = cg_vspPB;
314
315 /* load and extract cg */
316 if (NULL == (cg = loader(no))) {
317 return;
318 }
319
320 /* need to set vsp bank or not */
321 if (GCMD_EXTRACTCG(cg_fflg) && cg->type == ALCG_VSP) {
322 bank = cg_vspPB == -1 ? cg->vsp_bank : cg_vspPB;
323 set_vspbank(cg->pic, bank << 4, cg->width, cg->height);
324 /* copy pallets 0 -> bank */
325 {
326 int i, i_dst = bank << 4;
327 for (i = 0; i < 16; i++) {
328 cg->pal->red[i + i_dst] = cg->pal->red[i];
329 cg->pal->green[i + i_dst] = cg->pal->green[i];
330 cg->pal->blue[i + i_dst] = cg->pal->blue[i];
331 }
332 }
333 if (flg != -1) {
334 flg |= (bank << 4);
335 }
336 }
337
338 /* copy pallet to system */
339 if (GCMD_LOAD_PALLET(cg_fflg)) {
340 switch(cg->type) {
341 case ALCG_VSP:
342 ags_setPallets(cg->pal, 0, bank << 4, 16);
343 break;
344 case ALCG_PMS8:
345 if (cg->pms_bank & 1)
346 ags_setPallets(cg->pal, 10, 10, 6);
347 if (cg->pms_bank & (1 << 15))
348 //ags_setPallets(cg->pal, 240, 240, 15);
349 ags_setPallets(cg->pal, 240, 240, 10);
350 for (i = 1; i < 15; i++) {
351 if (cg->pms_bank & (1 << i)) {
352 ags_setPallets(cg->pal, i * 16, i * 16, 16);
353 }
354 }
355 break;
356 case ALCG_BMP8:
357 ags_setPallets(cg->pal, 10, 10, 236);
358 break;
359 default:
360 break;
361 }
362 /* pallet load only */
363 if (cg->pic == NULL) {
364 cgdata_free(cg);
365 }
366 }
367
368 /* refrect pallet change */
369 if (GCMD_SET_PALLET(cg_fflg)) {
370 switch(cg->type) {
371 case ALCG_VSP:
372 case ALCG_PMS8:
373 case ALCG_BMP8:
374 ags_setPalletToSystem(0, 256);
375 break;
376 default:
377 break;
378 }
379 }
380
381 /* draw cg */
382 switch(cg->type) {
383 case ALCG_VSP:
384 case ALCG_PMS8:
385 case ALCG_BMP8:
386 if (GCMD_EXTRACTCG(cg_fflg)) {
387 /* set display offset */
388 p = set_display_loc(cg);
389 /* draw cg pixel */
390 cg->spritecolor = flg;
391 display_cg(cg, p.x, p.y);
392 /* clear display offset */
393 clear_display_loc();
394 }
395 break;
396 case ALCG_PMS16:
397 case ALCG_BMP24:
398 if (GCMD_EXTRACTCG(cg_fflg)) {
399 /* set display offset */
400 p = set_display_loc(cg);
401 /* draw alpha pixel */
402 if (cg->alpha) {
403 ags_alpha_setPixel(p.x, p.y, cg->width, cg->height, cg->alpha);
404 }
405 /* draw cg pixel */
406 cg->spritecolor = flg;
407 display_cg(cg, p.x, p.y);
408 /* clear display offset */
409 clear_display_loc();
410 }
411 break;
412 default:
413 break;
414 }
415 }
416
417 /*
418 * Load and display cg with alpha
419 * cgno : file no for cg ( >= 0 or -1(alpha only))
420 * shadowno: file no for alpha ( >= 0 )
421 */
cg_load_with_alpha(int cgno,int shadowno)422 void cg_load_with_alpha(int cgno, int shadowno) {
423 cgdata *cg = NULL, *scg;
424 MyPoint p;
425
426 /* load pixel */
427 if (cgno >= 0) {
428 if (NULL == (cg = loader(cgno))) return;
429 if (cg->type != ALCG_PMS16) {
430 WARNING("commandGX cg_no != 16bitPMS\n");
431 return;
432 }
433 }
434
435 /* load alpha pixel */
436 if (NULL == (scg = loader(shadowno))) return;
437 if (scg->type != ALCG_PMS8) {
438 WARNING("commandGX shadow_no != 8bitPMS\n");
439 return;
440 }
441
442 /* set alpha pixel offset */
443 p = set_display_loc(scg);
444 /* draw alpha pixel */
445 ags_alpha_setPixel(p.x, p.y, scg->width, scg->height, scg->pic);
446
447 /* draw pixel */
448 if (cg) {
449 p = set_display_loc(cg);
450 display_cg(cg, p.x, p.y);
451 }
452
453 /* clear display offset */
454 clear_display_loc();
455 }
456
457 /*
458 * Load and display cg from file 'name' (not cached right now)
459 * name: file name to be read
460 * x : display location x
461 * y : display location y
462 * return: file read status
463 */
cg_load_with_filename(char * name,int x,int y)464 int cg_load_with_filename(char *name, int x, int y) {
465 int status, type;
466 BYTE *data;
467 cgdata *cg = NULL;
468 MyPoint p;
469
470 data = load_cg_with_file(name, &status);
471 if (data == NULL) return status;
472
473 cg_set_display_location(x, y, OFFSET_ABSOLUTE_GC);
474
475 type = check_cgformat(data);
476 switch(type) {
477 case ALCG_BMP8:
478 cg = bmp256_extract(data);
479 break;
480 case ALCG_BMP24:
481 cg = bmp16m_extract(data);
482 break;
483 default:
484 return status;
485 }
486
487 /* load pallet if not extracted */
488 if (GCMD_LOAD_PALLET(cg_fflg)) {
489 if (cg->type == ALCG_BMP8)
490 ags_setPallets(cg->pal, 10, 10, 236);
491 }
492
493 if (GCMD_SET_PALLET(cg_fflg)) {
494 if (cg->type == ALCG_BMP8)
495 ags_setPalletToSystem(0, 256);
496 }
497
498 /* draw cg */
499 if (GCMD_EXTRACTCG(cg_fflg)) {
500 /* set display offset */
501 p = set_display_loc(cg);
502 /* draw cg pixel */
503 cg->spritecolor = -1;
504 display_cg(cg, p.x, p.y);
505 /* clear display offset */
506 clear_display_loc();
507 }
508
509 cgdata_free(cg);
510 return status;
511 }
512
513 /*
514 * Get cg information
515 * no : file no for cg ( >= 0 )
516 * info: information to be retored
517 */
cg_get_info(int no,MyRectangle * info)518 void cg_get_info(int no, MyRectangle *info) {
519 cgdata *cg = loader(no);
520 MyPoint p;
521
522 if (cg == NULL) {
523 info->x = info->y = info->width = info->height = 0;
524 } else {
525 p = set_display_loc(cg);
526 info->x = p.x;
527 info->y = p.y;
528 info->width = cg->width;
529 info->height = cg->height;
530 }
531 }
532
cg_loadonly(int no)533 cgdata *cg_loadonly(int no) {
534 return loader(no);
535 }
536
cg_clear_display_loc()537 void cg_clear_display_loc() {
538 clear_display_loc();
539 }
540