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