Alchemy
Loading...
Searching...
No Matches

name_entry.c

Go to the documentation of this file.
1/// @file
2/// The name entry screen.
3/// Part of battle_command.c, the menu object, compiled only through it.
4
6
7#if (LANGUAGE != LANGUAGE_JAPANESE)
8/// The international name entry has no voicing marks: where the Japanese
9/// edition checks a mark against the letter before it, this edition keeps a
10/// function that accepts every character. Nothing calls it.
11UNUSED s32 NameEntry_AcceptsMark(s32 mark, s32 letter) { return 1; }
12#else
13
14// The kana voicing marks of the Japanese name entry, which join the letter
15// before them.
16#define NAME_VOICED_MARK 0xde ///< dakuten
17#define NAME_SEMIVOICED_MARK 0xdf ///< handakuten
18
19/// Returns whether `mark` may follow `letter` in a Japanese name: any
20/// character but a voicing mark may, and a voicing mark only after a letter
21/// in its table of ranges (pairs of first and last letter, ended by 0).
22s32 NameEntry_AcceptsMark(s32 mark, s32 letter) {
23 const u8 *range;
24
25 if (mark < NAME_VOICED_MARK || mark > NAME_SEMIVOICED_MARK)
26 return 1;
27 if (mark == NAME_VOICED_MARK)
29 else
31 for (; *range != 0; range += 2) {
32 if (letter >= range[0] && letter <= range[1])
33 return 1;
34 }
35 return 0;
36}
37
38/// Returns how many letters the Japanese name `name` has, not counting the
39/// voicing marks.
40s32 NameEntry_CountLetters(const u8 *name) {
41 s32 count;
42
43 count = 0;
44 for (; *name != 0; name++) {
45 // Neither NAME_VOICED_MARK nor NAME_SEMIVOICED_MARK.
46 if ((u8)(*name - NAME_VOICED_MARK) > 1)
47 count++;
48 }
49 return count;
50}
51#endif
52
53/// Decompresses the type-01 tilemap `source` and copies it over `window`'s
54/// rectangle, both into the BG screen block at 0x06002000 and into the UI
55/// tilemap that mirrors it.
56void UiWindow_CopyTilemapRegion(const struct UiWindow *window,
57 const void *source) {
58 struct UiRenderWork *work = UI_WORK;
59 s16 *mirror = (s16 *)work->tilemap;
61 s16 *input = buffer;
62 u32 cell;
63 s16 *vram;
64 s32 row;
65
66 Resource_DecodeType01(source, buffer);
67 cell = window->y * 32 + window->x;
68 vram = (s16 *)UI_TILEMAP_VRAM + cell;
69 mirror += cell;
70
71 for (row = 0; row < window->height; row++) {
72 s32 column;
73
74 for (column = 0; column < window->width; column++) {
75 s16 value = *input++;
76
77 *vram++ = value;
78 *mirror++ = value;
79 }
80 vram += 32 - window->width;
81 mirror += 32 - window->width;
82 }
83 MemFree(buffer);
84}
85
86/// Like UiWindow_SetTileAttributeBitRect, but ORs all of `palette` into the
87/// palette number of each entry (bits 12-15) after clearing only its lowest
88/// bit.
89void UiWindow_SetTileAttributeRect(const struct UiWindow *window, s32 x, s32 y,
90 s32 width, s32 height, u32 palette) {
92
93 x += window->x + 1;
94 y += window->y + 1;
95 palette <<= 12;
96 if (x < 0) {
97 width += x;
98 x = 0;
99 }
100 if (x + width > 29) {
101 width = 30 - x;
102 }
103 if (y < 0) {
104 height += y;
105 y = 0;
106 }
107 if (y + height > 29) {
108 height = 20 - y;
109 }
110 if (width > 0 && height > 0) {
111 y <<= 6;
112 x = y + (x << 1);
113 do {
114 u16 *cell = (u16 *)(x + (u32)tilemap);
115 s32 remaining = width;
116 while (remaining != 0) {
117 u32 entry = *cell;
118 entry &= ~0x1000;
119 entry |= palette;
120 remaining--;
121 *cell = entry;
122 cell++;
123 }
124 height--;
125 x += 64;
126 } while (height != 0);
127 ((struct UiRenderWork *)tilemap)->dirty = 1;
128 }
129}
130
131/// Loads the pointing hand cursor's tiles into VRAM slot `slot`.
134}
135
136/// Loads the 16x16 sprite gResource_FixedBlockATiles into VRAM slot `slot`.
139}
140
141// The name entry screen: a keyboard window of letter keys, with a column of
142// command keys on its right (Delete and End, and in Japanese the keyboard
143// switch), the name above it and the character's portrait.
144#define NAME_COMMAND_COLUMN 18 ///< the keyboard column of the command keys
145#define NAME_MAX_LETTERS 5
146#define NAME_MAX_BYTES 14 ///< stored name bytes, excluding its terminator
147
148#if TBS_PATCH_1
149/// Puts the string `str` into the UI's text entries and returns its width in
150/// pixels.
152 struct UiRenderWork *work;
153 u16 *dst;
154 s32 count;
155 u32 width;
156 u32 height;
157
158 work = UI_WORK;
159 count = 0;
160 if (*str != 0) {
161 dst = work->entries;
162 do {
163 *dst = *str;
164 str++;
165 dst++;
166 count++;
167 } while (*str != 0);
168 }
169 work->entries[count] = 0;
170 UiText_MeasureEntryDimensions(0, &width, &height, 0);
171 return width;
172}
173
174/// The text control code that sets the colour of the text after it, from the
175/// byte that follows ({text_color:N} in the message catalogs).
176#define TEXT_COLOR_COMMAND 8
177
178/// Draws the name being entered, `name`, at the top left of `window`, with
179/// the free places up to its seventh character shown as underscores in text
180/// colour 2.
181void UiText_DrawPaddedLabel(struct UiWindow *window, u8 *name) {
182 u8 text[20];
183 s32 length = 0;
184
185 if (*name != 0) {
186 do {
187 text[length] = *name;
188 name++;
189 length++;
190 } while (*name != 0);
191 }
192
193 text[length++] = TEXT_COLOR_COMMAND;
194 text[length++] = 2;
195
196 while (length <= 6) {
197 text[length++] = '_';
198 }
199
200 text[length++] = TEXT_COLOR_COMMAND;
201 text[length++] = 15;
202 text[length] = 0;
203 UiText_DrawString(text, window, 0, -2);
204}
205
206// The width of the window showing the name, in tiles.
207#if (LANGUAGE == LANGUAGE_SPANISH) || (LANGUAGE == LANGUAGE_ITALIAN)
208#define NAME_LABEL_WIDTH 9
209#else
210#define NAME_LABEL_WIDTH 8
211#endif
212
213// Whether the edition draws the Delete and End key labels as text over the
214// keyboard, and how wide its End key is, in tiles.
215#if (LANGUAGE == LANGUAGE_GERMAN) || (LANGUAGE == LANGUAGE_SPANISH) || \
216 (LANGUAGE == LANGUAGE_FRENCH)
217#define NAME_KEY_LABELS 1
218#else
219#define NAME_KEY_LABELS 0
220#endif
221#if (LANGUAGE == LANGUAGE_GERMAN)
222#define NAME_END_KEY_WIDTH 4
223#else
224#define NAME_END_KEY_WIDTH 3
225#endif
226
227/// The name entry screen for party member `member`: the player types a name
228/// of up to NAME_MAX_LETTERS letters on the keyboard and ends with End (or
229/// Start, which jumps there). A puts the key under the cursor into the name,
230/// B or Delete removes the last letter, and B on an empty name cancels. Ending
231/// with an empty name keeps the old one. Returns 0, or -1 when cancelled.
233 struct UiWindow *nameWindow;
234 s32 result = 0;
235 s32 originalLength = 0;
236 s32 letterCount = 0;
237 u8 text[NAME_MAX_BYTES + 2];
238 u8 *editedName = text + 1;
239 u8 *originalName = UnitGetFar(member)->name;
240 struct UiRenderWork *render = UI_WORK;
241 s32 textDirty = 1;
242 s32 cursorDirty = 1;
243 struct UiWindow *keyboardWindow;
244 union MenuCursor keyCursor;
245 union MenuCursor nameCaret;
246 s32 keyColumn, keyRow, vramSlot;
247 struct RenderOutput *output;
248 u8 *end;
249 u16 *palette;
250
251 // The keyboard, the name and the portrait.
253 keyboardWindow = (struct UiWindow *)UiWindow_Create(3, 6, 24, 9, 2);
254 nameWindow = (struct UiWindow *)UiWindow_Create(8, 3, NAME_LABEL_WIDTH, 3, 2);
257#if NAME_KEY_LABELS
259 UiText_DrawStringInWindow(gNameEntry_EndKeyLabel, keyboardWindow, 144, 40);
260#endif
261 UiWindow_DrawDividerLine(keyboardWindow, 18, 0, 18, 7);
262 render->dirty = textDirty;
263 // Reserve a zero byte before editedName for the empty-name backspace test.
264 text[0] = result;
265 {
266 s32 i;
267
268 for (i = 0; i < NAME_MAX_BYTES; i++) {
269 u32 c = originalName[i];
270
271 editedName[i] = c;
272 if (c != 0) {
273 originalLength++;
274 letterCount++;
275 }
276 }
277 }
278 editedName[NAME_MAX_BYTES] = 0;
279 UiText_DrawPaddedLabel(nameWindow, originalName);
280 vramSlot = Resource_FindFreeEntry();
281 keyColumn = NAME_COMMAND_COLUMN;
282 keyRow = 5;
283 if (vramSlot <= 95) {
285 output =
286 RenderOutput_Create(vramSlot, OUTPUT_SIZE_16X16, keyboardWindow, 0, 0);
287 keyCursor.output = output;
289 keyboardWindow->x * 8 + 140,
290 keyboardWindow->y * 8 + 52);
291 }
292 vramSlot = Resource_FindFreeEntry();
293 if (vramSlot <= 95) {
295 output =
296 RenderOutput_Create(vramSlot, OUTPUT_SIZE_16X16, keyboardWindow, 0, 0);
297 nameCaret.output = output;
298 output->sentinel = 255;
299 output->oam.priority = 0;
301 &nameCaret.cursor, UiText_SetRenderString(editedName) + 70, 22);
302 }
303 // The key under the cursor flashes between palette 15 and palette 14, a
304 // copy of it with colour 4 grey.
305 palette = (u16 *)&BG_PLTT_COLOR(14, 0);
306 Dma_Set((void *)&BG_PLTT_COLOR(15, 0), palette, DMA_COPY32(8), REG_DMA3);
307 palette[4] = 0x6318;
308 end = (u8 *)(originalLength + (s32)editedName);
309 while (1) {
310 s32 width = 1;
311
312 if (keyColumn == NAME_COMMAND_COLUMN) {
313 if (keyRow == 4)
314 width = 3;
315 if (keyRow == 5)
317 }
318 // Flash the key under the cursor, then move the cursor and the caret.
319 UiWindow_SetTileAttributeRect(keyboardWindow, keyColumn, keyRow, width, 1,
320 14);
321 WaitFrames(1);
322 UiWindow_SetTileAttributeRect(keyboardWindow, keyColumn, keyRow, width, 1,
323 15);
324 if (cursorDirty) {
325 cursorDirty = 0;
326 Shop_SetCursorFar(&keyCursor.cursor,
327 (keyboardWindow->x + keyColumn) * 8 - 7,
328 (keyboardWindow->y + keyRow) * 8 + 15, 3);
329 }
330 if (textDirty) {
331 textDirty = 0;
332 Shop_SetCursorFar(&nameCaret.cursor,
333 UiText_SetRenderString(editedName) + 70, 22, 3);
334 }
335 ShopCursor_AdvanceFar(&keyCursor.cursor);
337 {
338 u32 frame = (gFrameTick >> 1) & 7;
339
340 output = nameCaret.output;
342 output->oam.y = output->y + gNameEntry_CaretWave[(frame + 5) & 7];
343 }
344 // The D-pad moves over the keys, skipping the gaps between groups and
345 // wrapping around; Start jumps to End.
346 if (gKeysRepeat & KEY_UP) {
348 cursorDirty = 1;
349 keyRow--;
350 if (keyColumn != NAME_COMMAND_COLUMN) {
351 if (keyRow == -1)
352 keyRow = 5;
353 } else {
354 keyRow = (keyRow != 3);
355 keyRow = 5 - keyRow;
356 }
357 }
358 if (gKeysRepeat & KEY_DOWN) {
360 cursorDirty = 1;
361 keyRow++;
362 if (keyColumn != NAME_COMMAND_COLUMN) {
363 if (keyRow == 6)
364 keyRow = 0;
365 } else {
366 keyRow = (keyRow != 6);
367 keyRow += 4;
368 }
369 }
370 if (gKeysRepeat & KEY_LEFT) {
372 cursorDirty = 1;
373 keyColumn--;
374 if (keyColumn == -1) {
375 keyColumn = NAME_COMMAND_COLUMN;
376 if (keyRow < 4 || keyRow > 5)
377 keyColumn = 16;
378 } else if (keyColumn == 5 || keyColumn == 11 || keyColumn == 17) {
379 keyColumn--;
380 }
381 }
382 if (gKeysRepeat & KEY_RIGHT) {
384 cursorDirty = 1;
385 keyColumn++;
386 if (keyColumn == 19)
387 keyColumn = 0;
388 else if (keyColumn == 5 || keyColumn == 11 || keyColumn == 17)
389 keyColumn++;
390 if (keyColumn == NAME_COMMAND_COLUMN && (keyRow < 4 || keyRow > 5))
391 keyColumn = 0;
392 }
393 if (gKeysPressed & KEY_START) {
395 cursorDirty = 1;
396 keyColumn = NAME_COMMAND_COLUMN;
397 keyRow = 5;
398 }
399 if (gKeysRepeat & KEY_B) {
401 remove_character:
402 if (letterCount != 0) {
403 letterCount--;
404 *--end = 0;
406 UiText_DrawPaddedLabel(nameWindow, editedName);
407 textDirty = 1;
408 continue;
409 }
410 result = -1;
411 break;
412 }
413 // A: a command key, or a letter.
414 if (!(gKeysRepeat & KEY_A))
415 continue;
417 if (keyColumn == NAME_COMMAND_COLUMN) {
418 if (keyRow == 5) {
419 if (letterCount == 0) {
420 nameCaret.output->active = 13;
422 UiText_DrawPaddedLabel(nameWindow, originalName);
423 WaitFrames(10);
424 } else {
425 u8 *dst = originalName;
426 u8 *src = editedName;
427 s32 i = 0;
428 u8 *dstSave = dst;
429 u8 *srcSave = src;
430
431 /* FAKEMATCH(dead): no-op saves and restores keep destination,
432 * source and index in r2, r1 and r0; without them, 9 of 506
433 * instructions differ in tbs-en. */
434 if (originalName)
435 src = NULL;
436 if (originalName)
437 src = srcSave;
438 if (originalName)
439 dst = NULL;
440 if (originalName)
441 dst = dstSave;
442 while (i < 15) {
443 *dst++ = *src++;
444 i++;
445 }
446 }
447 break;
448 }
449 if (keyRow == 4)
450 goto remove_character;
451 continue;
452 }
453 {
454 u32 tx = keyboardWindow->x + keyColumn + 1;
455 u32 cell;
456 u32 letter;
457
458 cell = ((keyboardWindow->y + keyRow + 1) << 5) + tx;
459 // Key glyphs use the low byte of the mirrored tilemap entries.
460 letter = ((u8 *)&render->tilemap)[cell * 2];
461 if (letterCount == NAME_MAX_LETTERS)
462 continue;
463 *end++ = letter;
464 *end = 0;
465 letterCount++;
466 if (letterCount == NAME_MAX_LETTERS) {
467 keyColumn = NAME_COMMAND_COLUMN;
468 keyRow = 5;
469 cursorDirty = 1;
470 }
472 UiText_DrawPaddedLabel(nameWindow, editedName);
473 textDirty = 1;
474 }
475 }
476 UiWork_Finalize(keyboardWindow, 2);
477 UiWork_Finalize(nameWindow, 2);
479 WaitFrames(1);
480 return result;
481}
482#else
483
484/// The name entry screen for party member `member`: the player types a name
485/// of up to NAME_MAX_LETTERS letters on the keyboard and ends with End (or
486/// Start, which jumps there). A puts the key under the cursor into the name,
487/// B or Delete removes the last letter, and B on an empty name cancels. Ending
488/// with an empty name keeps the old one. Returns 0, or -1 when cancelled.
490 struct UiWindow *nameWindow;
491 s32 result = 0;
492 s32 keyboard = 0;
493 s32 bytes = 0;
494 s32 letterCount = 0;
495 u8 text[NAME_MAX_BYTES + 2];
496 u8 *editedName = text + 1;
497 u8 *originalName = UnitGetFar(member)->name;
498 struct UiRenderWork *render = UI_WORK;
499 s32 textDirty = 1;
500 s32 cursorDirty = 1;
501 struct UiWindow *keyboardWindow;
502 union MenuCursor keyCursor;
503 union MenuCursor nameCaret;
504 s32 keyColumn, keyRow, vramSlot, x;
505 struct RenderOutput *output;
506 u32 letter;
507 u16 *palette;
508
509 // The keyboard, the name and the portrait.
511 keyboardWindow = (struct UiWindow *)UiWindow_Create(3, 6, 24, 13, 2);
512 nameWindow = (struct UiWindow *)UiWindow_Create(8, 3, 8, 3, 2);
515 UiWindow_DrawDividerLine(keyboardWindow, 18, 0, 18, 12);
516 render->dirty = textDirty;
517 // Reserve a zero byte before editedName for the empty-name backspace test.
518 text[0] = result;
519 {
520 s32 i;
521
522 for (i = 0; i < NAME_MAX_BYTES; i++) {
523 letter = originalName[i];
524
525 editedName[i] = letter;
526 if (letter != 0) {
527 bytes++;
528 letterCount++;
529 if ((u8)(letter - NAME_VOICED_MARK) <= 1)
530 letterCount--;
531 }
532 }
533 }
534 editedName[NAME_MAX_BYTES] = 0;
535 UiText_DrawString(originalName, nameWindow, 0, 0);
536 keyColumn = NAME_COMMAND_COLUMN;
537 vramSlot = Resource_FindFreeEntry();
538 keyRow = 10;
539 if (vramSlot <= 95) {
541 output =
542 RenderOutput_Create(vramSlot, OUTPUT_SIZE_16X16, keyboardWindow, 0, 0);
543 keyCursor.output = output;
544 ShopCursor_SetPositionImmediateFar(&keyCursor.cursor,
545 keyboardWindow->x * 8 + 140,
546 keyboardWindow->y * 8 + 92);
547 }
548 vramSlot = Resource_FindFreeEntry();
549 if (vramSlot <= 95) {
551 output =
552 RenderOutput_Create(vramSlot, OUTPUT_SIZE_16X16, keyboardWindow, 0, 0);
553 nameCaret.output = output;
554 output->sentinel = 255;
555 output->oam.priority = 0;
556 x = 72 + NameEntry_CountLetters(editedName) * 10;
557 ShopCursor_SetPositionImmediateFar(&nameCaret.cursor, x, 22);
558 }
559 // The key under the cursor flashes between palette 15 and palette 14, a
560 // copy of it with colour 4 grey.
561 palette = (u16 *)&BG_PLTT_COLOR(14, 0);
562 Dma_Set((void *)&BG_PLTT_COLOR(15, 0), palette, DMA_COPY32(8), REG_DMA3);
563 palette[4] = 0x6318;
564 while (1) {
565 s32 width = 1;
566
567 if (keyColumn == NAME_COMMAND_COLUMN) {
568 if (keyRow == 0)
569 width = 4;
570 if (keyRow == 8)
571 width = 3;
572 if (keyRow == 10)
573 width = 3;
574 }
575 // Flash the key under the cursor, then move the cursor and the caret.
576 UiWindow_SetTileAttributeRect(keyboardWindow, keyColumn, keyRow, width, 1,
577 14);
578 WaitFrames(1);
579 UiWindow_SetTileAttributeRect(keyboardWindow, keyColumn, keyRow, width, 1,
580 15);
581 if (cursorDirty) {
582 cursorDirty = 0;
583 Shop_SetCursorFar(&keyCursor.cursor,
584 (keyboardWindow->x + keyColumn) * 8 - 7,
585 (keyboardWindow->y + keyRow) * 8 + 15, 3);
586 }
587 if (textDirty) {
588 textDirty = 0;
589 x = 72 + NameEntry_CountLetters(editedName) * 10;
590 Shop_SetCursorFar(&nameCaret.cursor, x, 22, 3);
591 }
592 ShopCursor_AdvanceFar(&keyCursor.cursor);
593 ShopCursor_MoveTowardTargetFar(&nameCaret.cursor);
594 {
595 u32 frame = (gFrameTick >> 1) & 7;
596
597 output = nameCaret.output;
599 output->oam.y = output->y + gNameEntry_CaretWave[(frame + 5) & 7];
600 }
601 // The D-pad moves over the keys, skipping the gaps between groups and
602 // wrapping around; Start jumps to End.
603 if (gKeysRepeat & KEY_UP) {
605 cursorDirty = 1;
606 keyRow--;
607 if (keyColumn != NAME_COMMAND_COLUMN) {
608 if (keyRow == -1)
609 keyRow = 10;
610 else if (keyRow == 5)
611 keyRow = 4;
612 } else {
613 if (keyRow == -1) {
614 keyRow = 10;
615 } else {
616 keyRow = (keyRow != 7);
617 keyRow *= 8;
618 }
619 }
620 }
621 if (gKeysRepeat & KEY_DOWN) {
623 cursorDirty = 1;
624 keyRow++;
625 if (keyColumn != NAME_COMMAND_COLUMN) {
626 if (keyRow == 11)
627 keyRow = 0;
628 if (keyRow == 5)
629 keyRow = 6;
630 } else {
631 if (keyRow == 1)
632 keyRow = 8;
633 else if (keyRow == 9)
634 keyRow = 10;
635 else
636 keyRow = 0;
637 }
638 }
639 if (gKeysRepeat & KEY_LEFT) {
641 cursorDirty = 1;
642 keyColumn--;
643 if (keyColumn == -1) {
644 if (keyRow == 0 || keyRow == 8 || keyRow == 10)
645 keyColumn = NAME_COMMAND_COLUMN;
646 else
647 keyColumn = 16;
648 } else if (keyColumn == 5 || keyColumn == 11 || keyColumn == 17) {
649 keyColumn--;
650 }
651 }
652 if (gKeysRepeat & KEY_RIGHT) {
654 cursorDirty = 1;
655 keyColumn++;
656 if (keyColumn == 19)
657 keyColumn = 0;
658 else if (keyColumn == 5 || keyColumn == 11 || keyColumn == 17)
659 keyColumn++;
660 if (keyColumn == NAME_COMMAND_COLUMN) {
661 if (keyRow == 0 || keyRow == 8 || keyRow == 10)
662 keyColumn = NAME_COMMAND_COLUMN;
663 else
664 keyColumn = 0;
665 }
666 }
667 if (gKeysPressed & KEY_START) {
669 cursorDirty = 1;
670 keyColumn = NAME_COMMAND_COLUMN;
671 keyRow = 10;
672 }
673 if (gKeysPressed & KEY_SELECT) {
675 change_keyboard:
676 keyboard ^= 1;
677 if (keyboard)
678 UiWindow_CopyTilemapRegion(keyboardWindow,
680 else
682 UiWindow_DrawDividerLine(keyboardWindow, 18, 0, 18, 12);
683 render->dirty = 1;
684 continue;
685 }
686 if (gKeysRepeat & KEY_B) {
688 remove_character:
689 if (letterCount != 0) {
690 letterCount--;
691 bytes--;
692 letter = editedName[bytes];
693 editedName[bytes] = 0;
694 if ((u8)(letter - NAME_VOICED_MARK) <= 1) {
695 bytes--;
696 editedName[bytes] = 0;
697 }
698 } else {
699 result = -1;
700 break;
701 }
703 UiText_DrawString(editedName, nameWindow, 0, 0);
704 textDirty = 1;
705 continue;
706 }
707 // A: a command key, or a letter.
708 if (!(gKeysRepeat & KEY_A))
709 continue;
711 if (keyColumn == NAME_COMMAND_COLUMN) {
712 if (keyRow == 10) {
713 if (letterCount == 0) {
714 nameCaret.output->active = 13;
716 UiText_DrawString(originalName, nameWindow, 0, 0);
717 WaitFrames(10);
718 } else {
719 u8 *dst;
720 u8 *src;
721 s32 i;
722 u8 *dstSave;
723 u8 *srcSave;
724
725 dst = originalName;
726 src = editedName;
727 i = 0;
728 /* FAKEMATCH(dead): no-op saves and restores keep destination,
729 * source and index in r1, r2 and r0; without them, 11 of 663
730 * instructions differ in tbs-ja. */
731 dstSave = dst;
732 srcSave = src;
733 if (keyboardWindow->height)
734 dst = NULL;
735 if (keyboardWindow->height)
736 dst = dstSave;
737 if (keyboardWindow->height)
738 src = NULL;
739 if (keyboardWindow->height)
740 src = srcSave;
741 while (i < 15) {
742 *dst++ = *src++;
743 i++;
744 }
745 }
746 break;
747 }
748 if (keyRow == 8)
749 goto remove_character;
750 if (keyRow == 0)
751 goto change_keyboard;
752 continue;
753 }
754 {
755 u32 tx = keyboardWindow->x + keyColumn + 1;
756 u32 cell;
757 u8 *dst;
758
759 cell = ((keyboardWindow->y + keyRow + 1) << 5) + tx;
760 // Key glyphs use the low byte of the mirrored tilemap entries.
761 letter = ((u8 *)&render->tilemap)[cell * 2];
762 // The keyboard's dakuten key.
763 if (letter == 0xfe)
764 letter = NAME_VOICED_MARK;
765 // The keyboard's handakuten key.
766 if (letter == 0xff)
767 letter = NAME_SEMIVOICED_MARK;
768 if (letterCount == NAME_MAX_LETTERS &&
769 (u8)(letter - NAME_VOICED_MARK) > 1)
770 continue;
771 dst = editedName + bytes;
772 if (!NameEntry_AcceptsMark(letter, editedName[bytes - 1])) {
774 continue;
775 }
776 *dst = letter;
777 bytes++;
778 editedName[bytes] = 0;
779 letterCount++;
780 if ((u8)(letter - NAME_VOICED_MARK) <= 1)
781 letterCount--;
782 if (letterCount == NAME_MAX_LETTERS) {
783 keyColumn = NAME_COMMAND_COLUMN;
784 keyRow = 10;
785 cursorDirty = 1;
786 }
788 UiText_DrawString(editedName, nameWindow, 0, 0);
789 textDirty = 1;
790 }
791 }
792 UiWork_Finalize(keyboardWindow, 2);
793 UiWork_Finalize(nameWindow, 2);
795 WaitFrames(1);
796 return result;
797}
798#endif
What every part of the menu object shares: its includes, edition values, macros and the link round st...
#define OUTPUT_SIZE_16X16
OAM attribute bits a sprite output is created with: the size field of attribute 1 (bits 30-31 of the ...
static __inline__ void Dma_Set(const volatile void *source, volatile void *destination, u32 control, volatile u32 *channel)
Starts a DMA transfer: stores the source, destination and control words into channel's registers with...
Definition dma.h:62
struct BattleUnit * UnitGetFar(u32 owner)
void Shop_SetCursorFar(struct ShopCursor *cursor, s32 targetX, s32 targetY, s32 kind)
void ShopCursor_SetPositionImmediateFar(struct ShopCursor *cursor, s32 x, s32 y)
void ShopCursor_AdvanceFar(struct ShopCursor *cursor)
void ShopCursor_MoveTowardTargetFar(struct ShopCursor *cursor)
void AudioCommand_PlayFar(s32 id)
void WaitFrames(s32 frames)
The game's frame loop: runs frames frames and returns.
Definition frame.c:97
u32 gFrameTick
Counted up by every VBlank.
const u8 gNameEntry_SemivoicedMarkRanges[]
const u8 gNameEntry_KeyboardTilemap[]
u8 gNameEntry_EndKeyLabel[]
u8 gResource_FixedBlockBTiles[]
const u8 gResource_FixedBlockATiles[]
s8 gNameEntry_CaretWave[]
const u8 gNameEntry_VoicedMarkRanges[]
u8 gNameEntry_DeleteKeyLabel[]
const u8 gNameEntry_AlternateKeyboardTilemap[]
void * Runtime_BumpAllocateAlternatePool(s32 size)
As MemAlloc, but tries EWRAM first.
Definition heap.c:140
@ KEY_UP
Definition io_reg.h:249
@ KEY_B
Definition io_reg.h:244
@ KEY_SELECT
Definition io_reg.h:245
@ KEY_LEFT
Definition io_reg.h:248
@ KEY_START
Definition io_reg.h:246
@ KEY_RIGHT
Definition io_reg.h:247
@ KEY_A
Definition io_reg.h:243
@ KEY_DOWN
Definition io_reg.h:250
#define REG_DMA3
Definition io_reg.h:153
#define BG_PLTT_COLOR(palette, color)
Definition io_reg.h:158
volatile u32 gKeysPressed
Keys that went down this frame.
volatile u32 gKeysRepeat
Pressed keys, repeating while held: after 19 frames, then every 6.
void UiText_MeasureEntryDimensions(s32 entryIndex, u32 *outWidth, u32 *outHeight, u16 *spacing)
Measures decoded text from entryIndex to its first page's end: returns the width of the longest line ...
Definition measure.c:106
void MemFree(void *buffer)
void UiWindow_CopyTilemapRegion(const struct UiWindow *window, const void *source)
Decompresses the type-01 tilemap source and copies it over window's rectangle, both into the BG scree...
Definition name_entry.c:56
#define TEXT_COLOR_COMMAND
The text control code that sets the colour of the text after it, from the byte that follows ({text_co...
Definition name_entry.c:176
void Resource_CopyFixedBlockA(s32 slot)
Loads the 16x16 sprite gResource_FixedBlockATiles into VRAM slot slot.
Definition name_entry.c:137
s32 NameEntry_EditOwnerName(s32 member)
The name entry screen for party member member: the player types a name of up to NAME_MAX_LETTERS lett...
Definition name_entry.c:232
#define NAME_MAX_LETTERS
Definition name_entry.c:145
s32 UiText_SetRenderString(const u8 *str)
Puts the string str into the UI's text entries and returns its width in pixels.
Definition name_entry.c:151
#define NAME_LABEL_WIDTH
Definition name_entry.c:210
#define NAME_MAX_BYTES
stored name bytes, excluding its terminator
Definition name_entry.c:146
void UiWindow_SetTileAttributeRect(const struct UiWindow *window, s32 x, s32 y, s32 width, s32 height, u32 palette)
Like UiWindow_SetTileAttributeBitRect, but ORs all of palette into the palette number of each entry (...
Definition name_entry.c:89
void UiText_DrawPaddedLabel(struct UiWindow *window, u8 *name)
Draws the name being entered, name, at the top left of window, with the free places up to its seventh...
Definition name_entry.c:181
#define NAME_COMMAND_COLUMN
the keyboard column of the command keys
Definition name_entry.c:144
void Resource_CopyFixedBlockB(s32 slot)
Loads the pointing hand cursor's tiles into VRAM slot slot.
Definition name_entry.c:132
UNUSED s32 NameEntry_AcceptsMark(s32 mark, s32 letter)
The international name entry has no voicing marks: where the Japanese edition checks a mark against t...
Definition name_entry.c:11
#define NAME_END_KEY_WIDTH
Definition name_entry.c:224
struct RenderOutput * RenderOutput_Create(s32 slot, s32 oamFlags, struct UiWindow *window, s32 offsetX, s32 offsetY)
Creates a sprite output for the VRAM cache slot slot and attaches it to window, placed at (offsetX,...
Definition outputs.c:13
s32 Resource_DecodeType01(const void *source, void *destination)
Decodes a type-01 resource and returns its unpacked byte count.
Definition decompress.c:31
#define SE_MENU_CANCEL
Definition songs.h:106
#define SE_MENU_CURSOR_MOVE
Definition songs.h:104
#define SE_MENU_CONFIRM
Definition songs.h:105
#define NULL
Definition bilibin.h:6
u8 gWindowWork[]
u8 name[0x0f]
The name, one byte a character, ending in 0.
A render output: a sprite in a window's output list (a character, an icon or a portrait),...
s8 active
its UI_SPRITE_ motion; 0 while free
The window system's work: the windows' tilemap, the windows, the three text channels,...
Definition window.h:19
u16 tilemap[640]
the windows' BG tilemap, 32 by 20 tiles
Definition window.h:20
u8 dirty
The tilemap's 4-row bands to upload: bit 0 for all, bit n + 1 for band n.
Definition window.h:32
u16 entries[RENDER_ENTRY_MASK+1]
decoded text, a ring of codes
Definition window.h:46
u16 count
where the next code goes in entries
Definition window.h:48
A window: a framed rectangle of the tilemap with its sprite outputs, its opening or closing animation...
Definition uiwindow.h:11
u16 frame
The zoom's step: counts down from 7 to 0 while opening, and up from 0 to duration while closing.
Definition uiwindow.h:28
u16 y
tiles
Definition uiwindow.h:16
u16 x
tiles
Definition uiwindow.h:15
u16 height
tiles
Definition uiwindow.h:14
struct RenderOutputList output
the sprites the window carries
Definition uiwindow.h:12
u16 width
tiles
Definition uiwindow.h:13
void Ui_LoadWindowGraphics(void)
Loads the window font and frame tiles into BG character block 0, the window palette into BG palette 1...
Definition text.c:180
void UiText_DrawStringInWindow(const u8 *text, struct UiWindow *window, u32 x, u32 y)
Draws a byte string into a window's tilemap at pixel (x, y) of its interior, rounded down to tiles.
Definition text_tiles.c:646
void UiText_DrawString(const u8 *text, struct UiWindow *window, s32 x, s32 y)
Draws a byte string into a text canvas window at pixel (x, y).
Definition text_tiles.c:599
void UiWindow_DrawDividerLine(struct UiWindow *win, u32 x1, u32 y1, u32 x2, u32 y2)
Draws a straight divider line inside a window from tile (x1, y1) to (x2, y2), horizontal or vertical:...
Definition text_tiles.c:365
signed int s32
Definition types.h:14
unsigned int u32
Definition types.h:15
signed short s16
Definition types.h:12
unsigned short u16
Definition types.h:13
#define UNUSED
Definition types.h:22
unsigned char u8
Definition types.h:11
A menu cursor: its render output, or the cursor that approaches its target.
Definition cursor.h:30
struct ShopCursor cursor
Definition cursor.h:32
struct RenderOutput * output
the image alone; cursor.anchor
Definition cursor.h:31
s32 NameEntry_CountLetters(const u8 *name)
#define UI_TILEMAP_VRAM
The UI tilemap in VRAM (BG screen block 4), which UiWork_UploadDirtyBlocks copies the work block's ti...
Definition window.h:51
#define UI_WORK
Definition window.h:267
#define DMA_COPY32(count)
The DMA control word that copies count words.
Definition window.h:112
s32 Resource_FindFreeEntry(void)
Returns the number of the first free cache entry, or VRAM_CACHE_ENTRY_COUNT when all are taken.
Definition vram_cache.c:211
s32 VramCache_Load(u32 no, u32 size, const void *src)
Gives cache entry no size bytes of sprite VRAM and copies src there.
Definition vram_cache.c:143
s32 Localization_LookupEntryId(u32 value)
Returns the portrait of a character (ids below 20) or another speaker's sprite (128 and up for those)...
Definition messages.c:486
void UiWork_FinalizeEntityMatchingLocalizedId(u32 speaker)
Closes the portrait window showing speaker entry, if one is open.
Definition messages.c:553
struct UiWindow * UiWindow_CreateWithSideObject(s32 speaker, s32 portraitOption, s32 x, s32 y)
Opens a portrait window at tile (x, y) showing the speaker's portrait.
Definition messages.c:525
void RenderOutput_PrepareForRedraw(struct UiWindow *window)
Clears a window's contents: redraws its empty frame and releases the render outputs it carries.
Definition windows.c:392
void UiWork_Finalize(struct UiWindow *window, s32 instant)
Closes a window: clears its contents and remembers its last rectangle.
Definition windows.c:349
struct UiWindow * UiWindow_Create(s32 x, s32 y, s32 width, s32 height, s32 attrs)
Opens a window at tile (x, y) of width by height tiles in the first free window slot,...
Definition windows.c:279