Digimon World 3 decomp
The European version, SLES_039.36
Loading...
Searching...
No Matches
text_window.c
Go to the documentation of this file.
1#include "engine/game.h"
2
3/* The debug messages, in Shift-JIS */
4/* "Null message was passed" */
5const char STR_NULL_MESSAGE[] = "\x82\x6D\x82\x95\x82\x8C\x82\x8C\x83\x81\x83\x62\x83\x5A\x81\x5B"
6 "\x83\x57\x82\xAA\x82\xED\x82\xBD\x82\xB3\x82\xEA\x82\xDC\x82\xB5\x82\xBD";
7/* "Digit: the message's work number is not supported" */
8const char STR_BAD_DIGIT_BUFFER[] = "\x82\x63\x82\x89\x82\x87\x82\x89\x82\x94\x81\x46\x83\x81\x83\x62"
9 "\x83\x5A\x81\x5B\x83\x57\x82\xCC\x83\x8F\x81\x5B\x83\x4E\x82\xCE"
10 "\x82\xF1\x82\xB2\x82\xA4\x82\xAA\x82\xDD\x82\xBD\x82\xA2\x82\xA8\x82\xA4";
11/* "ExtMess: the message's work number is not supported" */
12const char STR_BAD_EXT_BUFFER[] = "\x82\x64\x82\x98\x82\x94\x82\x6C\x82\x85\x82\x93\x82\x93\x81\x46"
13 "\x83\x81\x83\x62\x83\x5A\x81\x5B\x83\x57\x82\xCC\x83\x8F\x81\x5B"
14 "\x83\x4E\x82\xCE\x82\xF1\x82\xB2\x82\xA4\x82\xAA\x82\xDD\x82\xBD"
15 "\x82\xA2\x82\xA8\x82\xA4";
16/* "The message is not set" */
17const char STR_MESSAGE_NOT_SET[] = "\x83\x81\x83\x62\x83\x5A\x81\x5B\x83\x57\x82\xAA\x82\xB9\x82\xC1"
18 "\x82\xC4\x82\xA2\x82\xB3\x82\xEA\x82\xC4\x82\xA2\x82\xDC\x82\xB9\x82\xF1";
19
20/*
21 * Copies a string into one of a window's text buffers, growing it as needed (NULL shows
22 * STR_NULL_MESSAGE)
23 */
24void setTextBuffer(TextWindow *obj, TextBuffer *buf, const char *text) {
25 s16 len;
26 s16 cap;
27 u16 size;
28
29 if (text != NULL) {
30 len = strlen(text);
31 buf->len = len;
32 if (len == 0) {
33 obj->visible = 0;
34 return;
35 }
36 obj->visible = 1;
37 buf->sjis = 1;
38 if (buf->data != NULL) {
39 if (buf->cap <= buf->len) {
40 HEAP.free(buf->data);
41 buf->data = NULL;
42 buf->cap = 0;
43 }
44 if (buf->data != NULL) {
45 goto copy;
46 }
47 }
48 size = buf->len;
49 if (size & 3) {
50 cap = (size & ~3) + 8;
51 } else {
52 cap = size + 4;
53 }
54 buf->cap = cap;
55 buf->data = HEAP.alloc(cap, MEM_MODE);
56 copy:
57 HEAP.zero(buf->data, buf->cap);
58 memcpy(buf->data, text, buf->len);
59 } else {
61 }
62 if (obj->typeDelay == 0) {
64 }
65}
66
67/* Text window method: shows a string */
68void textWindowSetText(TextWindow *obj, const char *text) {
69 setTextBuffer(obj, &obj->text[0], text);
70}
71
72/* Text window method: shows string `id` of a string table (-1: `text` itself) */
73void textWindowSetString(TextWindow *obj, char *text, s32 id) {
74 textWindowSetSubString(obj, text, id, 0);
75}
76
77/* Writes a number's decimal digits (0 for zero or less) */
78void formatNumber(u8 *buf, s32 value) {
79 s32 saved;
80 s32 len;
81 s32 div;
82 s32 d;
83
84 saved = value;
85 if (value <= 0) {
86 *buf = '0';
87 return;
88 }
89 len = 0;
90 div = 10;
91 do {
92 value -= value % div;
93 len++;
94 div *= 10;
95 } while (value != 0);
96 value = saved;
97 while (value != 0) {
98 d = value % 10;
99 value -= d;
100 value /= 10;
101 buf[--len] = d + '0';
102 }
103}
104
105/* Text window method: puts a number into text buffer `index`, in the font's digit glyphs */
106void textWindowSetNumber(TextWindow *obj, u32 index, s32 value) {
107 u8 buf[16];
108 u8 *p;
109 s32 i;
110
111 if (index >= 6) {
113 return;
114 }
115 for (i = 15, p = &buf[i]; i >= 0; i--) {
116 *p-- = 0;
117 }
118 formatNumber(buf, value);
119 for (i = 0; buf[i] != 0; i++) {
120 buf[i] -= 0x2C;
121 }
122 setTextBuffer(obj, &obj->text[index], buf);
123 obj->text[index].sjis = 0;
124}
125
126/* Text window method: puts a string into work buffer `index` (1-5), for control code 5 */
127void textWindowSetSubText(TextWindow *obj, const char *text, s32 index) {
128 if (index < 1 || index > 5) {
130 } else {
131 setTextBuffer(obj, &obj->text[index], text);
132 }
133}
134
135/* Text window method: puts string `id` of a table (-1: `text` itself) into text buffer `index` */
136void textWindowSetSubString(TextWindow *obj, char *text, s32 id, s32 index) {
137 TextTools cls;
138 char *str;
139
140 if (id >= 0) {
141 initTextTools(&cls);
142 str = cls.getString(text, id);
143 if (str == NULL) {
144 return;
145 }
146 setTextBuffer(obj, &obj->text[index], str);
147 } else {
148 setTextBuffer(obj, &obj->text[index], text);
149 }
150 obj->text[index].sjis = 0;
151}
152
153/* Text window method: draws the visible part of the text as sprites, running the control codes */
155 TextDraw draw;
156 SVECTOR out;
157 SVECTOR in[4];
158 TextBuffer *text;
159 u16 clut;
160 u16 prevTpage;
161 s32 rotated;
162 s16 c;
163 s16 x;
164 s16 y;
165 u16 tpage;
166 u8 u;
167 u8 v;
168 s32 i;
169 s32 j;
170
171 prevTpage = 0;
172 tpage = 0;
173 rotated = 0;
174 if (obj->text[0].data == NULL) {
175 obj->visible = 0;
176 return;
177 }
178 for (i = 5; i >= 0; i--) {
179 obj->text[i].pos = 0;
180 }
181 obj->finished = 0;
182 obj->cursorX = -obj->alignWidth;
183 draw.lineCount = 0;
184 text = obj->text;
185 obj->cursorY = 0;
186 if (obj->scaled != 0) {
187 if (obj->scale.vx == 0 && obj->scale.vy == 0) {
188 return;
189 }
190 if (obj->scale.vx == ONE && obj->scale.vy == obj->scale.vx) {
191 obj->scaled = 0;
192 } else {
193 rotated = 1;
194 RotMatrixYXZ_gte(&obj->rot, &obj->mat);
195 ScaleMatrix(&obj->mat, &obj->scale);
196 }
197 }
198 i = 0;
199 draw.layer = GFX.funcs.getLayer(obj->layerId);
200 draw.ot = draw.layer->getOtEntry(draw.layer, obj->depth);
201 draw.prim.any = GFX.funcs.getPrim();
202 text->pos = obj->start;
203 while (i < (s16)obj->visibleEnd - obj->start) {
204 if (obj->finished != 0) {
205 break;
206 }
207 c = FONT.decode(text->data + text->pos, (u8)text->sjis, obj->style);
208 draw.code = c;
209 draw.kind = (u32)(c << 16) >> 24;
210 switch (processTextChar(obj, text, &draw, &text->pos)) {
211 case 1:
212 i++;
213 goto drawGlyph;
214 case 4:
215 i++;
216 continue;
217 case 2:
218 drawGlyph:
219 if (draw.glyph->page == 0xFF) {
220 draw.glyph = obj->style->glyphs;
221 }
222 x = obj->cursorX + (obj->x + draw.glyph->dx);
223 y = obj->cursorY + (obj->y + draw.glyph->dy);
224 clut = getClut(obj->texX + draw.glyph->clutX, obj->palette + (obj->texY + draw.glyph->clutY));
225 u = draw.glyph->u;
226 v = draw.glyph->v;
227 if (obj->blend == -1) {
228 tpage = getTPage(0, 1, obj->texX + (draw.glyph->page << 6), obj->texY);
229 } else {
230 tpage = getTPage(0, obj->blend & 3, obj->texX + (draw.glyph->page << 6), obj->texY);
231 }
232 if (!rotated) {
233 if (i == 0) {
234 prevTpage = tpage;
235 }
236 if (tpage != prevTpage) {
237 SetDrawTPage(draw.prim.tpage, 0, 1, prevTpage);
238 addPrim(draw.ot, draw.prim.any);
239 prevTpage = tpage;
240 draw.prim.tpage++;
241 }
242 setlen(draw.prim.sprt, 4);
243 setcode(draw.prim.sprt, 0x64);
244 if (obj->blend != -1) {
245 setSemiTrans(draw.prim.sprt, 1);
246 }
247 draw.prim.sprt->r0 = draw.prim.sprt->g0 = draw.prim.sprt->b0 = 0x80;
248 draw.prim.sprt->x0 = x;
249 draw.prim.sprt->y0 = y;
250 draw.prim.sprt->u0 = u;
251 draw.prim.sprt->v0 = v;
252 draw.prim.sprt->w = draw.glyph->w;
253 draw.prim.sprt->h = draw.glyph->h;
254 draw.prim.sprt->clut = clut;
255 addPrim(draw.ot, draw.prim.any);
256 draw.prim.sprt++;
257 SetDrawTPage(draw.prim.tpage, 0, 1, tpage);
258 addPrim(draw.ot, draw.prim.any);
259 draw.prim.tpage++;
260 } else {
261 setlen(draw.prim.ft4, 9);
262 setcode(draw.prim.ft4, 0x2C);
263 draw.prim.ft4->r0 = draw.prim.ft4->g0 = draw.prim.ft4->b0 = 0x80;
264 in[0].vx = in[2].vx = x - obj->pivotX;
265 in[1].vx = in[3].vx = in[0].vx + draw.glyph->w;
266 in[0].vy = in[1].vy = y - obj->pivotY;
267 in[2].vy = in[3].vy = in[0].vy + draw.glyph->h;
268 in[0].vz = in[1].vz = in[2].vz = in[3].vz = 0;
269 for (j = 0; j < 4; j++) {
270 ApplyMatrixSV(&obj->mat, &in[j], &out);
271 (&draw.prim.ft4->x0)[j * 4] = out.vx + obj->pivotX;
272 (&draw.prim.ft4->y0)[j * 4] = out.vy + obj->pivotY;
273 }
274 draw.prim.ft4->u0 = draw.prim.ft4->u2 = u;
275 draw.prim.ft4->u1 = draw.prim.ft4->u3 = draw.prim.ft4->u0 + draw.glyph->w - 1;
276 draw.prim.ft4->v0 = draw.prim.ft4->v1 = v;
277 draw.prim.ft4->v2 = draw.prim.ft4->v3 = draw.prim.ft4->v0 + draw.glyph->h - 1;
278 if (obj->blend != -1) {
279 setSemiTrans(draw.prim.ft4, 1);
280 }
281 draw.prim.ft4->tpage = tpage;
282 draw.prim.ft4->clut = clut;
283 addPrim(draw.ot, draw.prim.any);
284 draw.prim.ft4++;
285 }
286 if (obj->fixedSpacing != 0) {
287 obj->cursorX += obj->spacingX;
288 } else {
289 obj->cursorX += draw.glyph->advance + draw.glyph->dx;
290 }
291 break;
292 case 3:
293 break;
294 case 0:
295 default:
296 goto end;
297 }
298 }
299 if (!rotated) {
300 SetDrawTPage(draw.prim.tpage, 0, 1, tpage);
301 addPrim(draw.ot, draw.prim.any);
302 draw.prim.tpage++;
303 }
304end:
305 GFX.funcs.setPrim(draw.prim.any);
306}
307
308/* Text window method: makes the whole current page visible at once */
310 s32 extra;
311 s32 pos;
312 s32 lines;
313 s32 going;
314 u8 *p;
315 u8 index;
316 s32 c;
317
318 if (obj->state == 1) {
319 pos = obj->start;
320 extra = 0;
321 lines = 0;
322 going = 1;
323 do {
324 switch ((s32)((u32)(FONT.decode(obj->text[0].data + pos, (u8)obj->text[0].sjis, obj->style) << 16) >> 24)) {
325 case 0:
326 default:
327 if (obj->text[0].sjis != 0) {
328 pos += 2;
329 } else {
330 pos += 1;
331 }
332 break;
333 case 1:
334 pos += 2;
335 break;
336 case 2:
337 /* summed as integers: as pointer arithmetic GCC swaps the operands */
338 p = (u8 *)(pos + (s32)obj->text[0].data);
339 c = p[1];
340 switch (c) {
341 default:
342 pos += FONT.codeLengths[c];
343 break;
344 case 1:
345 if (++lines < obj->lines) {
346 pos += FONT.codeLengths[1];
347 } else {
348 going = 0;
349 }
350 break;
351 case 2:
352 if (p[2] < 5) {
353 going = 0;
354 }
355 pos += FONT.codeLengths[2];
356 break;
357 case 5:
358 index = p[2];
359 if (index < 6) {
360 extra += obj->text[index].len;
361 pos += FONT.codeLengths[5];
362 } else {
363 going = 0;
364 }
365 break;
366 case 3:
367 going = 0;
368 break;
369 }
370 break;
371 case 4:
372 going = 0;
373 break;
374 }
375 } while (going != 0);
376 obj->visibleEnd = pos + extra;
377 }
378}
379
380/* Text window method: one of the three font styles (others pick style 1) */
382 TextStyle *entry;
383
384 if (style < 1 || style > 3) {
385 style = 1;
386 }
387 entry = &FONT.styles[style];
388 obj->style = entry;
389 obj->blend = entry->blend;
390}
391
392/*
393 * Text window method: types the text out a character every `delay` frames (0 or less: all at once)
394 */
396 if (delay <= 0) {
397 obj->typeTimer = 0;
398 obj->typeDelay = 0;
399 obj->visibleEnd = obj->text[0].len;
400 return;
401 }
402 obj->visibleEnd = 0;
403 obj->typeTimer = 0;
404 obj->typeDelay = delay;
405 obj->start = 0;
406}
407
408/* Text window method: moves the window */
410 obj->x = x;
411 obj->y = y;
412}
413
414/* Text window method: the CLUT row of the glyphs */
415void textWindowSetPalette(TextWindow *obj, u8 palette) {
416 obj->palette = palette;
417}
418
419/*
420 * Text window method: the glyphs' blending. An old-style definition, as
421 * TextWindow.setBlend's unprototyped callers suit: they pass an int, which
422 * it takes as a byte. setSpacing, setRightAlign, setLines and setUnusedC4
423 * are old-style for the same reason.
424 */
425void textWindowSetBlend(obj, blend)
426TextWindow *obj;
427u8 blend;
428{
429 obj->blend = blend;
430}
431
432/* Text window method: a fixed advance and line height (0, 0: the style's) */
433void textWindowSetSpacing(obj, x, y)
434TextWindow *obj;
435s16 x;
436s16 y;
437{
438 if (x != 0 || y != 0) {
439 obj->fixedSpacing = 1;
440 obj->spacingX = x;
441 obj->spacingY = y;
442 } else {
443 obj->fixedSpacing = 0;
444 obj->spacingX = 0;
445 obj->spacingY = 0;
446 }
447}
448
449/* Text window method: shows or hides the window (an empty text stays hidden) */
450void textWindowSetVisible(TextWindow *obj, u8 visible) {
451 if (obj->text[0].len == 0) {
452 obj->visible = 0;
453 } else {
454 obj->visible = visible;
455 }
456}
457
458/* Text window method: aligns the text to its right end, or back to the left */
460TextWindow *obj;
461u8 type;
462{
463 TextTools cls;
464
465 if (type != 0) {
466 initTextTools(&cls);
467 obj->alignWidth = cls.measure(&obj->text[0], obj->style, obj->spacingX);
468 } else {
469 obj->alignWidth = 0;
470 }
471}
472
473/* Text window method: fills the work buffers that control code 8 asks for with the player's name */
475 TextBuffer *text = &obj->text[0];
476 s32 pos;
477 u8 c;
478 u8 index;
479
480 if (obj->text[0].data != NULL) {
481 for (pos = 0; pos < obj->text[0].len;) {
482 switch ((s32)((u32)(FONT.decode(text->data + pos, (u8)text->sjis, obj->style) << 16) >> 24)) {
483 case 0:
484 case 3:
485 default:
486 if (text->sjis != 0) {
487 pos += 2;
488 } else {
489 pos += 1;
490 }
491 break;
492 case 1:
493 pos += 2;
494 break;
495 case 2:
496 c = text->data[pos + 1];
497 if (c == 4) {
498 break;
499 }
500 if (c == 8) {
501 index = text->data[pos + 2];
502 textWindowSetSubText(obj, GAME.name, index);
503 obj->text[index].sjis = 0;
504 pos += FONT.codeLengths[8];
505 } else {
506 pos += FONT.codeLengths[c];
507 }
508 break;
509 case 4:
510 return;
511 }
512 }
513 }
514}
515
516/* Text window method: the sound each typed character plays (0 for none) */
518 obj->typeSound = sound;
519}
520
521/* Text window method: scales the glyphs */
523 obj->scale.vz = ONE;
524 obj->scale.vx = x;
525 obj->scale.vy = y;
526 obj->scaled = 1;
527}
528
529/* Text window method: the point the glyphs scale around */
531 obj->pivotX = x;
532 obj->pivotY = y;
533}
534
535/* Text window method: the OT depth the glyphs are drawn at */
537 obj->depth = depth;
538}
539
540/* Text window method: the lines of a page */
541void textWindowSetLines(obj, lines)
542TextWindow *obj;
543u8 lines;
544{
545 obj->lines = lines;
546}
547
548/* Text window method: sets unusedC4, which nothing reads */
549void textWindowSetUnusedC4(obj, value)
550TextWindow *obj;
551u8 value;
552{
553 obj->unusedC4 = value;
554}
555
556/* Text window method: whether the end of the text was reached */
558 return obj->finished;
559}
560
561/* Text window method: whether the window is shown */
563 return obj->visible;
564}
565
566/* Text window method: whether the text waits for a button (control code 2) */
568 return obj->substate == 1;
569}
570
571/*
572 * Picks the glyph of the next character, or runs its control code; returns what the drawing does
573 * next
574 */
576 TextStyle *style;
577 s32 c;
578 s32 ret;
579 s32 n;
580
581 switch (draw->kind) {
582 case 2:
583 if (text->sjis != 0) {
584 if ((u8)draw->code == 1) {
585 ret = TEXT_CODE_HANDLERS[1](obj, text, draw);
586 *pos += 1;
587 } else {
588 return TEXT_CODE_HANDLERS[0](obj, text, draw);
589 }
590 } else {
591 c = text->data[*pos + 1];
592 if (TEXT_CODE_HANDLERS[c] == NULL) {
593 return TEXT_CODE_HANDLERS[0](obj, text, draw);
594 }
595 ret = TEXT_CODE_HANDLERS[c](obj, text, draw);
596 if (ret & 0x8000) {
597 *pos += FONT.codeLengths[c];
598 }
599 }
600 return ret & ~0x8000;
601 case 0:
602 draw->glyph = &obj->style->glyphs[draw->code - 4];
603 if (text->sjis != 0) {
604 *pos += 2;
605 } else {
606 *pos += 1;
607 }
608 break;
609 case 1:
610 style = obj->style;
611 n = (u8)draw->code;
612 if (n <= style->iconCount && n > 0) {
613 draw->glyph = &style->icons[n - 1];
614 } else {
615 draw->glyph = obj->style->glyphs;
616 }
617 *pos += 2;
618 break;
619 case 4:
620 obj->finished = 1;
621 *pos += 1;
622 return 3;
623 default:
624 draw->glyph = obj->style->glyphs;
625 if (text->sjis != 0) {
626 *pos += 2;
627 } else {
628 *pos += 1;
629 }
630 break;
631 }
632 return 1;
633}
634
635/* Control codes 0, 7 and 9: show the page, or (code 7) start the text after a speaker's name */
637 switch (buf->data[buf->pos + 1]) {
638 case 0:
639 default:
641 break;
642 case 7:
643 obj->start = buf->pos + 2;
644 break;
645 }
646 return 0;
647}
648
649/* Control code 1: a new line, or a new page when the page is full */
651 if (++draw->lineCount == 1) {
652 draw->pageStart = buf->pos + 2;
653 } else if (draw->lineCount >= obj->lines) {
654 obj->start = draw->pageStart;
655 if (obj->lines >= 2) {
656 obj->lines--;
658 obj->lines++;
659 }
660 return 0x8000;
661 }
662 obj->cursorX = 0;
663 if (obj->fixedSpacing != 0) {
664 obj->cursorY += obj->spacingY;
665 } else {
666 obj->cursorY += obj->style->lineHeight;
667 }
668 return 0x8004;
669}
670
671/* Control code 2: waits for one of TEXT_WAIT_BUTTONS */
673 if (buf->data[buf->pos + 2] < 5) {
674 obj->state = 2;
675 obj->substate = 1;
676 if (buf->data[buf->pos + 2] < 1 || buf->data[buf->pos + 2] > 4) {
677 obj->step = 0;
678 } else {
679 obj->step = buf->data[buf->pos + 2];
680 }
681 obj->counter = buf->pos + 2;
682 return 0;
683 }
684 return 0x8003;
685}
686
687/* Control code 3: starts a new page */
689 u8 c;
690
691 if (obj->typeDelay != 0) {
692 obj->visibleEnd = buf->pos + 2;
693 } else {
694 obj->visibleEnd = buf->len;
695 }
696 while (buf->pos < buf->len) {
697 switch ((s32)((u32)(FONT.decode(buf->data + buf->pos, (u8)buf->sjis, obj->style) << 16) >> 24)) {
698 case 0:
699 case 1:
700 default:
701 obj->start = buf->pos;
702 buf->pos = buf->len + 1;
703 break;
704 case 2:
705 c = buf->data[buf->pos + 1];
706 if (c == 5 || c == 8) {
707 obj->start = buf->pos;
708 buf->pos = buf->len + 1;
709 } else {
710 buf->pos += FONT.codeLengths[c];
711 }
712 break;
713 case 4:
714 obj->start = buf->pos - 1;
715 return 3;
716 }
717 }
718 return 0;
719}
720
721/* Control code 4: skipped */
723 return 0x8003;
724}
725
726/* Control code 5: draws the next character of a work buffer in its place */
728 u8 index = buf->data[buf->pos + 2];
729 s16 c;
730 s32 ret;
731
732 if (obj->text[index].data == NULL) {
734 return 0x8003;
735 }
736 if (obj->text[index].pos >= obj->text[index].len) {
737 return 0x8003;
738 }
739 c = FONT.decode(obj->text[index].data + obj->text[index].pos, (u8)obj->text[index].sjis, obj->style, obj->text[index].pos);
740 draw->code = c;
741 draw->kind = (u32)(c << 16) >> 24;
742 if (draw->kind == 2) {
743 return 0x8000;
744 }
745 if (obj->typeDelay != 0) {
746 return processTextChar(obj, &obj->text[index], draw, &obj->text[index].pos);
747 }
748 ret = processTextChar(obj, &obj->text[index], draw, &obj->text[index].pos);
749 if (ret == 1) {
750 return 2;
751 }
752 return ret;
753}
754
755/* Control code 6: pauses the typing for some frames, once */
757 if (buf->data[buf->pos + 2] < 0xFF) {
758 obj->state = 2;
759 obj->substate = 0;
760 obj->step = buf->data[buf->pos + 2];
761 buf->data[buf->pos + 2] = 0xFF;
762 obj->typeTimer = 0;
763 return 0x8000;
764 }
765 return 0x8003;
766}
767
768/* Control code 8: puts the player's name into a work buffer, once */
770 if ((u8)buf->data[buf->pos + 2] < 6) {
771 textWindowSetSubString(obj, GAME.name, -1, (u8)buf->data[buf->pos + 2]);
772 buf->data[buf->pos + 2] = 6;
773 }
774 return 0x8003;
775}
776
777/*
778 * The text window task: types and draws the text, waits where the control codes say, frees the
779 * buffers at the end
780 */
782 s32 i;
783
784 switch (obj->state) {
785 case 0:
786 default:
787 obj->nextState(obj);
788 break;
789 case 1:
790 if (obj->visible != 0) {
791 if (obj->typeDelay > 0 && obj->finished == 0) {
792 if (++obj->typeTimer > obj->typeDelay) {
793 obj->typeTimer = 0;
794 obj->visibleEnd++;
795 if (obj->typeSound != 0) {
797 }
798 }
799 }
800 textWindowDraw(obj);
801 }
802 break;
803 case 2:
804 switch (obj->substate) {
805 case 0:
806 default:
807 textWindowDraw(obj);
808 if (++obj->typeTimer > obj->step) {
809 obj->typeTimer = 0;
810 obj->setState(obj, TASK_RUN);
811 }
812 break;
813 case 1:
814 if ((PAD.getPressed(0) >> PAD.getButtonBit(0, TEXT_WAIT_BUTTONS[obj->step])) & 1) {
815 obj->text[0].data[obj->counter] = 5;
816 obj->typeTimer = obj->typeDelay;
817 obj->setState(obj, TASK_RUN);
818 }
819 textWindowDraw(obj);
820 break;
821 }
822 break;
823 case 3:
824 for (i = 0; i < 6; i++) {
825 if (obj->text[i].data != NULL) {
826 HEAP.free(obj->text[i].data);
827 }
828 }
829 break;
830 }
831}
832
833/* A text window on a layer, in a font style, at (x, y) */
834TextWindow *createTextWindow(s16 layerId, s16 style, s16 x, s16 y) {
835 TextWindow *ret;
837
843 obj->draw = textWindowDraw;
863 if (style < 1 || style > 3) {
864 style = 1;
865 }
866 obj->layerId = layerId;
867 ret = obj;
868 ret->style = &FONT.styles[style];
869 ret->x = x;
870 ret->texX = 0x140;
871 ret->y = y;
872 ret->texY = 0;
873 ret->lines = 1;
874 ret->blend = ret->style->blend;
875 ret->scale.vx = ret->scale.vy = ret->scale.vz = ONE;
876 return ret;
877}
878
879/* The handlers of the control codes 0x02 <code> (processTextChar) */
885
886/* The buttons a wait for a button (code 2) can wait for */
#define NULL
Definition common.h:17
signed int s32
Definition common.h:11
unsigned int u32
Definition common.h:12
signed short s16
Definition common.h:9
unsigned short u16
Definition common.h:10
unsigned char u8
Definition common.h:8
GfxState GFX
GFX: the graphics state and its methods.
Definition display.c:209
GameState GAME
The save data, the game mode and the methods.
Definition state.c:64
#define TASK_RUN
Definition task.h:35
Font FONT
decode is declared without a prototype, as callers would truncate the u8 mode, so decodeChar is cast ...
Definition font.c:78
int strlen(const char *)
SDK functions declared here rather than from their PsyQ headers: strings.h and memory....
void * memcpy(void *dst, const void *src, int size)
Heap HEAP
The functions that return what a call left in v0 (allocMemHigh, findTask) and the ones that take othe...
Definition heap.c:184
#define MEM_MODE
the current mode's: freed by main whenever the mode task ends
Definition heap.h:17
PadState PAD
Controller input: cleared by initPad, then the methods.
Definition pad.c:168
#define PAD_CROSS
Definition pad.h:31
#define PAD_CIRCLE
Definition pad.h:30
#define PAD_SQUARE
Definition pad.h:33
#define PAD_TRIANGLE
Definition pad.h:32
SoundState SOUND
rsin and rcos (libgte) read rsin_tbl[a - 0x800] and the like: their addresses before the table fall i...
Definition sound.c:180
struct TextStyle * styles
[4], style 0 unused
Definition text.h:212
s32 * codeLengths
Definition text.h:213
s16(* decode)()
(text, sjis, style)
Definition text.h:215
char name[0x18]
the player's
Definition game_state.h:509
void *(* getPrim)(void)
Definition gfx.h:19
struct Layer *(* getLayer)(s32 id)
Definition gfx.h:28
void(* setPrim)(void *next)
Definition gfx.h:20
GfxFuncs funcs
Definition gfx.h:77
s8 dy
Definition text.h:246
u8 clutX
Definition text.h:241
u8 page
0xFF: missing glyph
Definition text.h:238
u8 u
Definition text.h:239
u8 h
Definition text.h:244
s8 dx
Definition text.h:245
u8 advance
Definition text.h:247
u8 w
Definition text.h:243
u8 v
Definition text.h:240
u8 clutY
Definition text.h:242
void *(* alloc)(s32 size, s32 tag)
Definition heap.h:29
void(* zero)(void *ptr, s32 size)
Definition heap.h:32
void(* free)(void *ptr)
Definition heap.h:27
u_long *(* getOtEntry)(struct Layer *, s32 depth)
Definition gfx.h:155
s32(* getButtonBit)(s32 pad, s32 button)
Definition pad.h:130
s32(* getPressed)(s32 pad)
Definition pad.h:125
short(* playSound)(s32 id)
returns the voice of a key-on
Definition sound.h:187
s16 len
Definition text.h:102
s16 cap
Definition text.h:101
s16 sjis
two bytes per character; else font codes
Definition text.h:104
s16 pos
Definition text.h:103
u8 * data
Definition text.h:100
Drawing state shared with the control-code handlers.
Definition text.h:252
PrimPtr prim
Definition text.h:253
Layer * layer
Definition text.h:254
s16 code
from Font.decode
Definition text.h:258
Glyph * glyph
Definition text.h:256
s32 pageStart
Definition text.h:257
s16 kind
Definition text.h:259
u_long * ot
Definition text.h:255
s16 lineCount
Definition text.h:260
u8 blend
0xFF: opaque
Definition text.h:226
struct Glyph * icons
Definition text.h:229
struct Glyph * glyphs
Definition text.h:228
s8 lineHeight
Definition text.h:227
Text helpers (initTextTools)
Definition text.h:93
char *(* getString)()
(table, index)
Definition text.h:94
s32(* measure)()
(TextBuffer *, style, spacing)
Definition text.h:95
A text window (createTextWindow): up to six text buffers (0 is shown, 1-5 are "work" buffers that con...
Definition text.h:131
s16 x
Definition text.h:143
VECTOR scale
ScaleMatrix's.
Definition text.h:159
SVECTOR rot
Definition text.h:162
s32 step
Definition text.h:132
s16 texY
Definition text.h:142
void(* setState)(struct TextWindow *task, s32 state)
Definition text.h:132
s32 substate
Definition text.h:132
s16 y
Definition text.h:144
void(* setStyle)()
Definition text.h:171
void(* setScale)()
Definition text.h:181
s32 typeSound
Definition text.h:157
s32 pivotY
Definition text.h:161
s32(* isWaitingForButton)()
Definition text.h:188
s8 blend
-1 (TextStyle.blend 0xFF): opaque
Definition text.h:150
s16 cursorX
Definition text.h:147
u8 unusedC4
only setUnusedC4 writes it, and nothing calls that
Definition text.h:156
void(* setPalette)(struct TextWindow *obj, u8 arg)
Definition text.h:174
TextBuffer text[6]
Definition text.h:136
s16 typeDelay
Definition text.h:140
s32(* isFinished)()
s32: callers don't truncate the result to a byte
Definition text.h:186
s32(* isVisible)()
s32: callers don't truncate the result to a byte
Definition text.h:187
void(* setPivot)()
Definition text.h:182
void(* insertPlayerName)()
Definition text.h:179
void(* setTypeSound)()
Definition text.h:180
void(* setDepth)()
Definition text.h:183
void(* setSpacing)()
no prototype: callers would truncate s16 args
Definition text.h:176
void(* setRightAlign)()
no prototype: callers would truncate u8 args
Definition text.h:178
void(* setTypeDelay)()
Definition text.h:172
void(* setLines)()
no prototype: callers would truncate u8 args
Definition text.h:184
s32 depth
Definition text.h:135
MATRIX mat
Definition text.h:163
u16 cursorY
Definition text.h:148
void(* setSubString)()
Definition text.h:168
void(* setNumber)()
Definition text.h:166
void(* setBlend)()
no prototype: callers would truncate u8 args
Definition text.h:175
void(* draw)()
Definition text.h:169
u16 visibleEnd
Definition text.h:137
s32 state
Definition text.h:132
s32 layerId
Definition text.h:134
s16 start
Definition text.h:138
void(* setPos)(struct TextWindow *obj, s16 x, s16 y)
Definition text.h:173
void(* setText)()
Definition text.h:164
u8 lines
Definition text.h:151
void(* setString)()
Definition text.h:165
s16 spacingX
Definition text.h:145
s32 counter
Definition text.h:132
s32 scaled
Definition text.h:158
void(* showPage)()
Definition text.h:170
void(* setUnusedC4)()
no prototype: callers would truncate u8 args
Definition text.h:185
struct TextStyle * style
Definition text.h:133
s16 spacingY
Definition text.h:146
void(* setSubText)()
Definition text.h:167
s16 texX
Definition text.h:141
void(* setVisible)(struct TextWindow *obj, u8 arg)
Definition text.h:177
s16 typeTimer
Definition text.h:139
u8 visible
Definition text.h:153
void(* nextState)(struct TextWindow *task)
Definition text.h:132
u8 fixedSpacing
Definition text.h:154
u8 palette
PALETTE_*.
Definition text.h:152
s16 alignWidth
Definition text.h:149
u8 finished
Definition text.h:155
s32 pivotX
Definition text.h:160
void * createTask(void(*update)(), s32 size, s32 childrenSize)
createTaskWithId for a task nothing needs to find
Definition task.c:105
void initTextTools(TextTools *obj)
Clears a text tools object, gives it its methods and binds it.
Definition text_tools.c:193
void textWindowInsertPlayerName(TextWindow *obj)
Text window method: fills the work buffers that control code 8 asks for with the player's name.
s32 textCodeIgnore(void)
Control code 4: skipped.
void textWindowSetUnusedC4(TextWindow *obj, u8 value)
Text window method: sets unusedC4, which nothing reads.
void textWindowSetPalette(TextWindow *obj, u8 palette)
Text window method: the CLUT row of the glyphs.
s32 textWindowIsVisible(TextWindow *obj)
Text window method: whether the window is shown.
void textWindowSetSubString(TextWindow *obj, char *text, s32 id, s32 index)
Text window method: puts string id of a table (-1: text itself) into text buffer index
void textWindowSetText(TextWindow *obj, const char *text)
Text window method: shows a string.
Definition text_window.c:68
void textWindowSetNumber(TextWindow *obj, u32 index, s32 value)
Text window method: puts a number into text buffer index, in the font's digit glyphs.
void textWindowSetDepth(TextWindow *obj, s32 depth)
Text window method: the OT depth the glyphs are drawn at.
void formatNumber(u8 *buf, s32 value)
Writes a number's decimal digits (0 for zero or less)
Definition text_window.c:78
s32 textCodePause(TextWindow *obj, TextBuffer *buf)
Control code 6: pauses the typing for some frames, once.
s32(* TEXT_CODE_HANDLERS[11])()
The handlers of the control codes 0x02 <code> (processTextChar)
void textWindowSetPos(TextWindow *obj, s16 x, s16 y)
Text window method: moves the window.
const char STR_NULL_MESSAGE[]
"Null message was passed"
Definition text_window.c:5
s32 textCodePlayerName(TextWindow *obj, TextBuffer *buf)
Control code 8: puts the player's name into a work buffer, once.
void textWindowSetLines(TextWindow *obj, u8 lines)
Text window method: the lines of a page.
s32 textCodeDefault(TextWindow *obj, TextBuffer *buf)
Control codes 0, 7 and 9: show the page, or (code 7) start the text after a speaker's name.
const char STR_BAD_DIGIT_BUFFER[]
"Digit: the message's work number is not supported"
Definition text_window.c:8
s32 textCodeInsert(TextWindow *obj, TextBuffer *buf, TextDraw *draw)
Control code 5: draws the next character of a work buffer in its place.
void textWindowSetVisible(TextWindow *obj, u8 visible)
Text window method: shows or hides the window (an empty text stays hidden)
void textWindowSetString(TextWindow *obj, char *text, s32 id)
Text window method: shows string id of a string table (-1: text itself)
Definition text_window.c:73
void textWindowSetTypeSound(TextWindow *obj, s32 sound)
Text window method: the sound each typed character plays (0 for none)
void textWindowSetBlend(TextWindow *obj, u8 blend)
Text window method: the glyphs' blending.
void textWindowSetSubText(TextWindow *obj, const char *text, s32 index)
Text window method: puts a string into work buffer index (1-5), for control code 5.
s32 textCodeWaitButton(TextWindow *obj, TextBuffer *buf)
Control code 2: waits for one of TEXT_WAIT_BUTTONS.
void textWindowSetSpacing(TextWindow *obj, s16 x, s16 y)
Text window method: a fixed advance and line height (0, 0: the style's)
void textWindowDraw(TextWindow *obj)
Text window method: draws the visible part of the text as sprites, running the control codes.
void setTextBuffer(TextWindow *obj, TextBuffer *buf, const char *text)
Copies a string into one of a window's text buffers, growing it as needed (NULL shows STR_NULL_MESSAG...
Definition text_window.c:24
void textWindowSetRightAlign(TextWindow *obj, u8 type)
Text window method: aligns the text to its right end, or back to the left.
TextWindow * createTextWindow(s16 layerId, s16 style, s16 x, s16 y)
A text window on a layer, in a font style, at (x, y)
s32 textCodeNewLine(TextWindow *obj, TextBuffer *buf, TextDraw *draw)
Control code 1: a new line, or a new page when the page is full.
void textWindowSetScale(TextWindow *obj, s32 x, s32 y)
Text window method: scales the glyphs.
void updateTextWindow(TextWindow *obj)
The text window task: types and draws the text, waits where the control codes say,...
void textWindowSetTypeDelay(TextWindow *obj, s32 delay)
Text window method: types the text out a character every delay frames (0 or less: all at once)
s32 textWindowIsWaitingForButton(TextWindow *obj)
Text window method: whether the text waits for a button (control code 2)
const char STR_MESSAGE_NOT_SET[]
"The message is not set"
Definition text_window.c:17
void textWindowSetStyle(TextWindow *obj, s32 style)
Text window method: one of the three font styles (others pick style 1)
s32 TEXT_WAIT_BUTTONS[5]
The buttons a wait for a button (code 2) can wait for.
const char STR_BAD_EXT_BUFFER[]
"ExtMess: the message's work number is not supported"
Definition text_window.c:12
void textWindowSetPivot(TextWindow *obj, s32 x, s32 y)
Text window method: the point the glyphs scale around.
s32 processTextChar(TextWindow *obj, TextBuffer *text, TextDraw *draw, s16 *pos)
Picks the glyph of the next character, or runs its control code; returns what the drawing does next.
s32 textWindowIsFinished(TextWindow *obj)
Text window method: whether the end of the text was reached.
s32 textCodePageBreak(TextWindow *obj, TextBuffer *buf)
Control code 3: starts a new page.
void textWindowShowPage(TextWindow *obj)
Text window method: makes the whole current page visible at once.
POLY_FT4 * ft4
Definition gfx.h:348
DR_TPAGE * tpage
Definition gfx.h:349
void * any
Definition gfx.h:345
SPRT * sprt
Definition gfx.h:346