1 /*
2  * scenario.c  ���ʥꥪ�����¹�
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: scenario.c,v 1.30 2003/04/25 17:23:55 chikama Exp $ */
23 
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 
28 #include "portab.h"
29 #include "ald_manager.h"
30 #include "variable.h"
31 #include "scenario.h"
32 #include "LittleEndian.h"
33 #include "xsystem35.h"
34 
35 /* stack data type */
36 #define STACK_NEARJMP 1
37 #define STACK_FARJMP 2
38 #define STACK_VARIABLE 3
39 #define STACK_DATA 4
40 
41 /* static mathods */
42 static void popVars(int *tmp);
43 static void popDatas(int *tmp);
44 static void showStackInfo();
45 static void sl_push(int type, int *val, int cnt);
46 static int* sl_pop();
47 
48 /* static variables */
49 static BYTE *sl_sco;              /* scenario data */
50 static int  *sco_stackbuf;        /* stack data    */
51 static int  *sco_stackindex;      /* stack index   */
52 static int   sco_stacksize = 1024; /* default stack size */
53 
54 static int   sl_page;              /* current scenario page no */
55 static int   sl_index;             /* cureent scenario address in page */
56 
57 static int labelCallCnt = 0;
58 static int pageCallCnt  = 0;
59 static int labelCallCnt_afterPageCall = 0;
60 static int dataPushCnt = 0;
61 
62 /* driobject */
63 static dridata *dfile;
64 
65 /* debug: show stack information */
showStackInfo()66 static void showStackInfo() {
67 	DEBUG_MESSAGE("stack top = %p, cur = %p, size=%d\n", sco_stackbuf, sco_stackindex, sco_stacksize);
68 }
69 
70 /* debbug: show current scenario pointer information */
showIndexInfo()71 static void showIndexInfo() {
72 	DEBUG_MESSAGE("page = %d, index = %x\n", sl_page, sl_index);
73 }
74 
75 #ifdef DEBUG
showStackData()76 static void showStackData() {
77 	int i, j;
78 	int *var;
79 	FILE *fp = fopen("STACKS.TXT","a");
80 	if (fp == NULL) return;
81 
82 	fprintf(fp, "Page = %d, index = %x\n", sl_getPage(), sl_getIndex());
83 	fprintf(fp, "stack top = %p, cur = %p, size=%d, index=%d\n", sco_stackbuf, sco_stackindex, sco_stacksize, (sco_stackindex - sco_stackbuf));
84 
85 	var = sco_stackbuf;
86 	for (i = 0; i < sco_stacksize; i+=10) {
87 		for (j = 0; j < 10; j++) {
88 			fprintf(fp, "%d,", *var); var++;
89 		}
90 		fprintf(fp, "\n");
91 	}
92 	fprintf(fp, "\n");
93 
94 	fclose(fp);
95 }
96 #endif
97 
98 /* initilize stack and load first scenario data */
sl_init()99 boolean sl_init() {
100 	sco_stackbuf = calloc(sco_stacksize, sizeof(int));
101 	if (sco_stackbuf == NULL)
102 		NOMEMERR();
103 
104 	sco_stackindex = sco_stackbuf;
105 	sl_jmpFar(0);
106 
107 	labelCallCnt = 0;
108 	pageCallCnt = 0;
109 	labelCallCnt_afterPageCall = 0;
110 	return TRUE;
111 }
112 
113 /* UD 0 command, reinitilized scenario loader */
sl_reinit()114 boolean sl_reinit() {
115 	free(sco_stackbuf);
116 	return sl_init();
117 }
118 
sl_push(int type,int * val,int cnt)119 static void sl_push(int type, int *val, int cnt) {
120 	int i;
121 
122 	if (sco_stackindex + cnt >= sco_stackbuf + sco_stacksize) {
123 		i = sco_stackindex - sco_stackbuf;
124 		sco_stacksize <<= 1;
125 		sco_stackbuf    = realloc(sco_stackbuf, sco_stacksize * sizeof(int));
126 		if (sco_stackbuf == NULL)
127 			NOMEMERR();
128 		sco_stackindex = sco_stackbuf + i;
129 	}
130 	val += (cnt - 1);
131 	for (i = 0 ; i < cnt; i++) {
132 		*sco_stackindex++ = *val--;
133 	}
134 	*sco_stackindex++ = cnt;
135 	*sco_stackindex++ = type;
136 	// showStackInfo();
137 	// showStackData();
138 }
139 
sl_pop()140 static int* sl_pop() {
141 	int i, type, cnt;
142 	int *tmp, *_tmp;
143 
144 	type = *--sco_stackindex;
145 	cnt  = *--sco_stackindex;
146 
147 	tmp  = _tmp = malloc(sizeof(int) * (cnt + 2));
148 	if (_tmp == NULL)
149 		NOMEMERR();
150 
151 	*tmp++ = type;
152 	*tmp++ = cnt;
153 	for (i = 0; i < cnt; i++) {
154 		*tmp++ = *--sco_stackindex;
155 	}
156 	if (sco_stackindex < sco_stackbuf) {
157 		SYSERROR("Stack buffer is illegal\n");
158 	}
159 
160 	// showStackInfo();
161 	// showStackData();
162 	return _tmp;
163 }
164 
sl_getc()165 int sl_getc() {
166 	return sl_sco[sl_index++];
167 }
168 
sl_getw()169 int sl_getw() {
170 	int c0,c1;
171 
172 	c0 = sl_getc();
173 	c1 = sl_getc();
174 	return c0 + (c1 << 8);
175 }
176 
sl_getcAt(int adr)177 int sl_getcAt(int adr) {
178 	return sl_sco[adr];
179 }
180 
sl_getwAt(int adr)181 int sl_getwAt(int adr) {
182 	int c0,c1;
183 
184 	c0 = sl_sco[adr];
185 	c1 = sl_sco[adr + 1];
186 	return c0 + (c1 << 8);
187 }
188 
sl_getdAt(int adr)189 int sl_getdAt(int adr) {
190 	int c0, c1;
191 
192 	c0 = sl_getwAt(adr);
193 	c1 = sl_getwAt(adr + 2);
194 	return c0 + (c1 << 16);
195 }
196 
sl_getadr()197 int sl_getadr() {
198 	int c0,c1;
199 	c0 = sl_getw();
200 	c1 = sl_getw();
201 	return c0 + (c1 << 16);
202 }
203 
204 /* @address */
sl_jmpNear(int address)205 void sl_jmpNear(int address) {
206 	sl_index = address;
207 //	showIndexInfo();
208 }
209 
210 /*
211    #page
212    page = 0~
213 */
sl_jmpFar(int page)214 boolean sl_jmpFar(int page) {
215 	if (dfile) {
216 		ald_freedata(dfile);
217 	}
218 
219 	dfile = ald_getdata(DRIFILE_SCO, page);
220 	if (dfile == NULL) {
221 		return FALSE;
222 	}
223 
224 	sl_sco   = dfile->data;
225 	sl_page  = page;
226 	sl_index = LittleEndian_getDW(sl_sco, 4);
227 //	showIndexInfo();
228 	return TRUE;
229 }
230 
231 /*
232   ~page,address
233    page = 1~
234 */
sl_jmpFar2(int page,int address)235 boolean sl_jmpFar2(int page, int address) {
236 	if (dfile) {
237 		ald_freedata(dfile);
238 	}
239 
240 	dfile = ald_getdata(DRIFILE_SCO, page);
241 	if (dfile == NULL) {
242 		DEBUG_MESSAGE("ald_getdata fail\n");
243 		return FALSE;
244 	}
245 	sl_sco   = dfile->data;
246 	sl_page  = page;
247 	sl_index = address;
248 	return TRUE;
249 }
250 
sl_callNear(int address)251 void sl_callNear(int address) {
252 	int val[1];
253 	val[0] = sl_index;
254 	sl_push(STACK_NEARJMP, val, 1);
255 	sl_jmpNear(address);
256 
257 	labelCallCnt++;
258 	labelCallCnt_afterPageCall++;
259 }
260 
sl_retNear()261 void sl_retNear() {
262 	int *tmp = sl_pop();
263 	int index;
264 
265 	while (*tmp != STACK_NEARJMP) {
266 		if (*tmp == STACK_FARJMP) {
267 			SYSERROR("Stack buffer is illegal\n");
268 		} else if (*tmp == STACK_VARIABLE) {
269 			popVars(tmp);
270 		} else {
271 			SYSERROR("Stack buffer is illegal\n");
272 		}
273 		free(tmp);
274 		tmp = sl_pop();
275 	}
276 	index = *(tmp + 2);
277 	free(tmp);
278 	sl_jmpNear(index);
279 
280 	labelCallCnt--;
281 	labelCallCnt_afterPageCall--;
282 }
283 
sl_callFar(int page)284 void sl_callFar(int page) {
285 	int val[2];
286 	boolean bool;
287 
288 	val[0] = sl_page;
289 	val[1] = sl_index;
290 	sl_push(STACK_FARJMP, val, 2);
291 	bool = sl_jmpFar(page);
292 	pageCallCnt++;
293 	labelCallCnt_afterPageCall = 0;
294 	if (!bool) {
295 		sl_retFar();
296 	}
297 }
298 
sl_callFar2(int page,int address)299 void sl_callFar2(int page, int address) {
300 	int val[2];
301 	boolean bool;
302 
303 	val[0] = sl_page;
304 	val[1] = sl_index;
305 	sl_push(STACK_FARJMP, val, 2);
306 	bool = sl_jmpFar2(page, address);
307 	labelCallCnt_afterPageCall = 0;
308 	pageCallCnt++;
309 	if (!bool) {
310 		sl_retFar();
311 	}
312 }
313 
sl_retFar()314 void sl_retFar() {
315 	int *tmp = sl_pop();
316 	int page, index;
317 
318 	while (*tmp != STACK_FARJMP) {
319 		if (*tmp == STACK_NEARJMP) {
320 			WARNING("Stack buffer is illegal\n");
321 		} else if (*tmp == STACK_DATA) {
322 			popDatas(tmp);
323 		} else if (*tmp == STACK_VARIABLE) {
324 			popVars(tmp);
325 		} else {
326 			SYSERROR("Stack buffer is illegal\n");
327 		}
328 		free(tmp);
329 		tmp = sl_pop();
330 	}
331 	page  = *(tmp + 2);
332 	index = *(tmp + 3);
333 	free(tmp);
334 	sl_jmpFar2(page, index);
335 
336 	labelCallCnt_afterPageCall = 0;
337 	pageCallCnt--;
338 }
339 
340 /* UD 1 */
sl_retFar2()341 void sl_retFar2() {
342 	int *tmp = sl_pop();
343 	int page, index;
344 
345 	while (*tmp != STACK_FARJMP) {
346 		if (*tmp == STACK_NEARJMP) {
347 			labelCallCnt--;
348 		} else if (*tmp == STACK_DATA) {
349 			popDatas(tmp);
350 		} else if (*tmp == STACK_VARIABLE) {
351 			popVars(tmp);
352 		} else {
353 			SYSERROR("Stack buffer is illegal\n");
354 		}
355 		free(tmp);
356 		tmp = sl_pop();
357 	}
358 	page  = *(tmp + 2);
359 	index = *(tmp + 3);
360 	free(tmp);
361 	sl_jmpFar2(page, index);
362 
363 	pageCallCnt--;
364 	labelCallCnt_afterPageCall = 0;
365 }
366 
367 /* UC0 */
sl_stackClear_allCall()368 void sl_stackClear_allCall() {
369 	free(sco_stackbuf);
370 	sco_stackbuf = calloc(sco_stacksize, sizeof(int));
371 	if (sco_stackbuf == NULL)
372 		NOMEMERR();
373 
374 	sco_stackindex = sco_stackbuf;
375 }
376 
377 /* UC 2 */
sl_stackClear_pageCall(int cnt)378 void sl_stackClear_pageCall(int cnt) {
379 	int *tmp;
380 
381 	while(cnt--) {
382 		tmp = sl_pop();
383 		if (*tmp == STACK_NEARJMP) {
384 			labelCallCnt--;
385 		} else if (*tmp == STACK_FARJMP) {
386 			pageCallCnt--;
387 		} else if (*tmp == STACK_VARIABLE) {
388 			popVars(tmp);
389 		} else {
390 			SYSERROR("Stack buffer is illegal\n");
391 		}
392 		free(tmp);
393 	}
394 	labelCallCnt_afterPageCall = 0;
395 }
396 
397 /* UC 1 */
sl_stackClear_labelCall(int cnt)398 void sl_stackClear_labelCall(int cnt) {
399 	int *tmp;
400 
401 	if (labelCallCnt_afterPageCall == 0) return;
402 
403 	tmp = sl_pop();
404 	while(cnt--) {
405 		if (*tmp == STACK_NEARJMP) {
406 			labelCallCnt--;
407 			labelCallCnt_afterPageCall--;
408 		} else if (*tmp == STACK_VARIABLE) {
409 			popVars(tmp);
410 		} else {
411 			SYSERROR("Stack buffer is illegal\n");
412 		}
413 		free(tmp);
414 		if (labelCallCnt_afterPageCall == 0) break;
415 
416 		tmp = sl_pop();
417 	}
418 }
419 
420 /* US */
sl_pushVar(int * topVar,int cnt)421 void sl_pushVar(int *topVar, int cnt) {
422 	int *tmp = malloc(sizeof(int) * (cnt + 2));
423 
424 	if (tmp == NULL) {
425 		NOMEMERR();
426 	}
427 
428 	*tmp     = preVarPage;
429 	*(tmp+1) = preVarIndex;
430 	memcpy(tmp + 2, topVar, sizeof(int) * cnt);
431 	sl_push(STACK_VARIABLE, tmp, cnt + 2);
432 	free(tmp);
433 }
434 
435 /* UG */
sl_popVar(int * topvar,int cnt)436 void sl_popVar(int *topvar, int cnt) {
437 	int *tmp = sl_pop();
438 
439 	if (*tmp != STACK_VARIABLE) {
440 		SYSERROR("Stack buffer is illegal\n");
441 	}
442 	if (*(tmp + 2) != preVarPage){
443 		WARNING("Variable is not match with stacked variable\n");
444 	}
445 	if (*(tmp + 3) != preVarIndex) {
446 		WARNING("Variable is not match with stacked variable\n");
447 	}
448 	if (*(tmp + 1) != cnt + 2) {
449 		WARNING("Variable count is not match with stacked variable\n");
450 	}
451 	memcpy(topvar, tmp + 4, sizeof(int) * cnt);
452 	free(tmp);
453 }
454 
popVars(int * tmp)455 static void popVars(int *tmp) {
456 	int cnt, page, index;
457 	int *topVar;
458 
459 	cnt   = *(tmp + 1) - 2;
460 	page  = *(tmp + 2);
461 	index = *(tmp + 3);
462 
463 	if (page == 0) {
464 		topVar = sysVar + index;
465 	} else {
466 		if ((arrayVarBuffer + page - 1) -> value == NULL) {
467 			WARNING("Illegal Variable pop\n");
468 			return;
469 		}
470 		topVar = ((arrayVarBuffer + page - 1) -> value) + index;
471 	}
472 
473 	memcpy(topVar, tmp + 4, sizeof(int) * cnt);
474 }
475 
sl_getIndex()476 int sl_getIndex() {
477 	return sl_index;
478 }
479 
sl_getPage()480 int sl_getPage() {
481 	return sl_page;
482 }
483 
sl_getStackInfo(int * size)484 int *sl_getStackInfo(int *size) {
485 	*size = sco_stackindex - sco_stackbuf;
486 //	printf("get stack size = %d\n", *size);
487 	return sco_stackbuf;
488 }
489 
sl_putStackInfo(int * data,int size)490 void sl_putStackInfo(int *data, int size) {
491 	if (size > sco_stacksize) {
492 		sco_stacksize = size << 1;
493 		sco_stackbuf  = calloc(sco_stacksize, sizeof(int));
494 	}
495 	if (sco_stackbuf == NULL)
496 		NOMEMERR();
497 	memcpy(sco_stackbuf, data, size * sizeof(int));
498 	sco_stackindex = sco_stackbuf + size;
499 }
500 
501 
502 /* TPx */
sl_pushData(int * data,int cnt)503 void sl_pushData(int *data, int cnt) {
504 	dataPushCnt++;
505 	sl_push(STACK_DATA, data, cnt);
506 }
507 
508 /* TOx */
sl_popData(int * data,int cnt)509 void sl_popData(int *data, int cnt) {
510 	int *tmp;
511 	if (dataPushCnt == 0) return;
512 
513 	tmp = sl_pop();
514 	dataPushCnt--;
515 
516 	if (*tmp != STACK_DATA)
517 		SYSERROR("Stack buffer is illegal\n");
518 	if (*(tmp + 1) != cnt)
519 		WARNING("Variable count is not match with stacked variable\n");
520 
521 	memcpy(data, tmp + 2, sizeof(int) * cnt);
522 	free(tmp);
523 }
524 
popDatas(int * tmp)525 static void popDatas(int *tmp) {
526 	int d1 = *(tmp + 2);
527 	int d2 = *(tmp + 3);
528 	int d3 = *(tmp + 4);
529 
530 	if (*(tmp + 1) != 3)
531 		WARNING("Variable count is not match with stacked variable\n");
532 
533 	switch(d1) {
534 	case TxxTEXTCOLOR:
535 		if (d2 == 0) {
536 			nact->msg.MsgFontColor = d3;
537 		} else {
538 			nact->sel.MsgFontColor = d3;
539 		}
540 		break;
541 	case TxxTEXTSIZE:
542 		if (d2 == 0) {
543 			nact->msg.MsgFontSize = d3;
544 		} else {
545 			nact->sel.MsgFontSize = d3;
546 		}
547 		break;
548 	case TxxTEXTLOC:
549 		msg_setMessageLocation(d2, d3);
550 		break;
551 	}
552 	dataPushCnt--;
553 }
554 
555 static dridata *datatbl;
556 
sl_setDataTable(int page,int index)557 void *sl_setDataTable(int page, int index) {
558 	if (datatbl) {
559 		ald_freedata(datatbl);
560 	}
561 	datatbl = ald_getdata(DRIFILE_SCO, page);
562 	return (void *)(datatbl->data + index);
563 }
564 
sl_returnGoto(int address)565 void sl_returnGoto(int address) {
566 	int *tmp = sl_pop();
567 	int page;
568 
569 	while (TRUE) {
570 		if (*tmp != STACK_FARJMP || *tmp != STACK_NEARJMP) break;
571 		if (*tmp == STACK_DATA) {
572 			popDatas(tmp);
573 		} else if (*tmp == STACK_VARIABLE) {
574 			popVars(tmp);
575 		} else {
576 			fprintf(stderr, "%d \n", *tmp);
577 			SYSERROR("Stack buffer is illegal\n");
578 		}
579 		free(tmp);
580 		tmp = sl_pop();
581 	}
582 
583 	if (*tmp == STACK_FARJMP) {
584 		page  = *(tmp + 2);
585 		// index = *(tmp + 3);
586 		free(tmp);
587 		sl_jmpFar2(page, address);
588 		labelCallCnt_afterPageCall = 0;
589 		pageCallCnt--;
590 	} else {
591 		// index = *(tmp + 2);
592 		free(tmp);
593 		sl_jmpNear(address);
594 
595 		labelCallCnt--;
596 		labelCallCnt_afterPageCall--;
597 	}
598 }
599