Paper Mario DX
Paper Mario (N64) modding
 
Loading...
Searching...
No Matches
debug_menu.c
Go to the documentation of this file.
1// #include "dx/debug_menu.h"
2#include "common.h"
3#if DX_DEBUG_MENU || defined(DX_QUICK_LAUNCH_BATTLE)
4#include "game_modes.h"
5#include "battle/battle.h"
6#include "hud_element.h"
7#include "inventory.h"
8#include "qsort.h"
9#include <string.h>
10#include "dx/utils.h"
11#include "msg.h"
12#include "fio.h"
13
14// layout
15
16const s32 MainMenuPosX = 26;
17const s32 MainMenuPosY = 60;
18
19const s32 RowHeight = 15;
20const s32 BottomRowY = 222;
21
22const s32 SubmenuPosX = 140;
24
25const s32 BoxOutsetX = 10;
26const s32 BoxOutsetY = 4;
27
30
31// which menu or submenu is open, only one is displayed at a time
32// pressing ACCEPT (R) or CANCEL (L) usually moves between these states
33enum DebugMenuStates {
35 // press D-left to open debug menu
58 // press D-right to open script debugger
62};
63
66
71
72// data grabbed during map or battle load
73
74char LastMapName[16];
75char LastStageName[16];
78
79void dx_debug_set_map_info(char* mapName, s32 entryID) {
80 strcpy(LastMapName, mapName);
81 LastMapEntry = entryID;
82}
83
84void dx_debug_set_battle_info(s32 battleID, char* stageName) {
85 s32 len = strlen(stageName);
86
87 strcpy(LastStageName, stageName);
88 if (len > 6) {
89 // trim "_shape" from name
90 LastStageName[len - 6] = '\0';
91 }
93}
94
95// input
96
102
103typedef struct DebugHold {
104 s16 delay;
105 u16 triggers;
106} DebugHold;
107
108DebugHold DebugHoldU = { 0 };
109DebugHold DebugHoldD = { 0 };
110DebugHold DebugHoldL = { 0 };
111DebugHold DebugHoldR = { 0 };
112
113#define PRESSED(but) (DebugButtonsPress & (but))
114#define RELEASED(but) (DebugButtonsRelease & (but))
115#define HELD(but) (DebugButtonsHold & (but))
116
117#define INIT_HOLD_RATE 6 // slight start-up delay
118#define SLOW_HOLD_RATE 4
119#define FAST_HOLD_RATE 2
120
122 if (PRESSED(but)) {
123 hold->delay = INIT_HOLD_RATE;
124 hold->triggers = 0;
125 } else if (HELD(but)) {
126 hold->delay--;
127 if (hold->delay < 0) {
128 hold->triggers++;
129
130 if (hold->triggers < 5) {
131 hold->delay = SLOW_HOLD_RATE;
132 } else if (hold->triggers < 15) {
133 hold->delay = FAST_HOLD_RATE;
134 } else {
135 hold->delay = 1;
136 }
137 }
138 } else {
139 hold->delay = 999;
140 hold->triggers = 0;
141 }
142}
143
150
155};
156
157#define NAV_UP (PRESSED(BUTTON_D_UP) || DebugHoldU.delay == 0)
158#define NAV_DOWN (PRESSED(BUTTON_D_DOWN) || DebugHoldD.delay == 0)
159#define NAV_LEFT (PRESSED(BUTTON_D_LEFT) || DebugHoldL.delay == 0)
160#define NAV_RIGHT (PRESSED(BUTTON_D_RIGHT) || DebugHoldR.delay == 0)
161
162// utility functions for drawing menus
163
164void dx_debug_draw_box(s32 posX, s32 posY, s32 sizeX, s32 sizeY, int style, s32 opacity) {
165 draw_box(0, (WindowStyle)style, posX, posY, 0, sizeX, sizeY, opacity,
166 0, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, NULL, 0, NULL, SCREEN_WIDTH, SCREEN_HEIGHT, NULL);
167}
168
169void dx_debug_draw_ascii(char* text, s32 color, s32 posX, s32 posY) {
170 char buf[128] = {
172 };
174 draw_msg((s32)buf, posX, posY, 255, color, 0);
175}
176
177void dx_debug_draw_ascii_with_effect(char* text, s32 color, s32 posX, s32 posY, s32 effect) {
178 char buf[128] = {
180 };
182 draw_msg((s32)buf, posX, posY, 255, color, effect);
183}
184
185void dx_debug_draw_msg(s32 msgID, s32 color, s32 alpha, s32 posX, s32 posY) {
186 char buf[128] = {
188 };
189 dma_load_msg(msgID, &buf[4]);
190 draw_msg((s32)buf, posX, posY, alpha, color, 0);
191}
192
193void dx_debug_draw_number(s32 number, char* fmt, s32 color, s32 alpha, s32 posX, s32 posY) {
194 char fmtBuf[16];
195 char buf[16] = {
197 };
198 sprintf(fmtBuf, fmt, number);
200 draw_msg((s32)buf, posX, posY, alpha, color, 0);
201}
202
203// efficiently renders an number with (optionally) a digit highlighted using a single draw_msg call
205 char msgBuf[32] = {
208 };
209 s32 pos = 7; // writePos to msgBuf
210
211 char fmtBuf[16];
212 s32 len = sprintf(fmtBuf, fmt, number);
213 s32 idx; // readPos from fmtBuf
214
215 for (idx = 0; idx < len; idx++) {
216 if (hasSelected && selectedDigit == idx) {
222 }
224 if (hasSelected && selectedDigit == idx) {
227 }
228 }
230
231 if (hasSelected && selectedDigit == -1) {
232 draw_msg((s32)msgBuf, posX, posY, 255, HighlightColor, 0);
233 } else {
234 draw_msg((s32)msgBuf, posX, posY, 255, DefaultColor, 0);
235 }
236}
237
238// utility functions for menu navigation
239
240s32 dx_debug_clamp(s32 v, s32 min, s32 max) {
241 const s32 u = v < min ? min : v;
242 return u > max ? max : u;
243}
244
245s32 dx_debug_wrap(s32 v, s32 min, s32 max) {
246 const s32 u = v < min ? v + (max - min + 1) : v;
247 return u > max ? u - (max - min + 1) : u;
248}
249
250// range from [min, max] with min < max
252 if (NAV_UP) {
253 if(flip) {
254 cur++;
255 } else {
256 cur--;
257 }
258 }
259 if (NAV_DOWN) {
260 if(flip) {
261 cur--;
262 } else {
263 cur++;
264 }
265 }
266 // wrap
267 if (cur < min) {
268 cur += (1 + max - min);
269 }
270 if (cur > max) {
271 cur -= (1 + max - min);
272 }
273 return cur;
274}
275
276// range from [min, max] with min < max
278 if (NAV_LEFT) {
279 if(flip) {
280 cur++;
281 } else {
282 cur--;
283 }
284 }
285 if (NAV_RIGHT) {
286 if(flip) {
287 cur--;
288 } else {
289 cur++;
290 }
291 }
292 // wrap
293 if (cur < min) {
294 cur += (1 + max - min);
295 }
296 if (cur > max) {
297 cur -= (1 + max - min);
298 }
299 return cur;
300}
301
303 s32 ncols = max / nrows;
304 if ((max % nrows) != 0) {
305 ncols++;
306 }
307
308 if (NAV_UP) {
309 cur--;
310 if (cur < 0) {
311 cur += nrows;
312 }
313 else if (cur % nrows == nrows - 1) {
314 cur += nrows;
315 }
316 while (cur >= max) {
317 cur--;
318 }
319 }
320 if (NAV_DOWN) {
321 cur++;
322 if (cur >= max) {
323 cur = (cur / nrows) * nrows;
324 }
325 else if (cur % nrows == 0) {
326 cur -= nrows;
327 }
328 }
329 if (NAV_LEFT) {
330 cur -= nrows;
331 if (cur < 0) {
332 cur += (nrows * ncols);
333 while (cur >= max) {
334 cur -= nrows;
335 }
336 }
337 }
338 if (NAV_RIGHT) {
339 cur += nrows;
340 if (cur >= max) {
341 cur -= (nrows * ncols);
342 while (cur < 0) {
343 cur += nrows;
344 }
345 }
346 }
347 return cur;
348}
349
350// utility functions for number input fields
351
352typedef struct DebugEditableNumber {
353 b8 isHex;
354 s8 pos;
355 s8 size;
356 s8 digits[];
358
360 s32 max = num->isHex ? 0xF : 9;
361
362 if (num->size > 1) {
363 num->pos = dx_debug_menu_nav_1D_horizontal(num->pos, 0, num->size - 1, FALSE);
364 }
365 num->digits[num->pos] = dx_debug_menu_nav_1D_vertical(num->digits[num->pos], 0, max, TRUE);
366}
367
369 char* fmt = num->isHex ? "%X" : "%d";
370 s32 idx;
371
372 for (idx = 0; idx < num->size; idx++) {
373 s32 color = (num->pos == idx) ? HighlightColor : DefaultColor;
374 dx_debug_draw_number(num->digits[idx], fmt, color, 255, posX + (7 * idx), posY);
375 }
376}
377
379 s32 idx;
380 s32 out = 0;
381
382 if (num->isHex) {
383 for (idx = 0; idx < num->size; idx++) {
384 out <<= 4;
385 out |= (num->digits[idx] & 0xF);
386 }
387 } else {
388 for (idx = 0; idx < num->size; idx++) {
389 out *= 10;
390 out += num->digits[idx];
391 }
392 }
393
394 return out;
395}
396
398 s32 idx;
399
400 if (num->isHex) {
401 for (idx = num->size - 1; idx >= 0; idx--) {
402 num->digits[idx] = (in & 0xF);
403 in >>= 4;
404 }
405 } else {
406 for (idx = num->size - 1; idx >= 0; idx--) {
407 num->digits[idx] = in % 10;
408 in /= 10;
409 }
410 }
411}
412
413// menus
414
416
418 return DebugMenuState != DBM_NONE;
419}
420
426}
427
428typedef struct DebugMenuEntry {
429 char* text;
430 void (*onSelect)();
433
435 { "Full Restore", dx_debug_exec_full_restore },
436 { "Save/Load", NULL, DBM_QUICK_SAVE },
437 { "Map Select", NULL, DBM_SELECT_AREA },
438 { "Battle Select", NULL, DBM_SELECT_BATTLE },
439 { "Set Story Byte", NULL, DBM_SET_STORY },
440 { "Sound Player", NULL, DBM_SOUND_PLAYER },
441 { "Edit Partners", NULL, DBM_EDIT_PARTNERS },
442 { "Edit Inventory", NULL, DBM_EDIT_INVENTORY },
443// { "Edit Memory", NULL, DBM_EDIT_MEMORY },
444 { "View Collision", NULL, DBM_VIEW_COLLISION },
445 { "Cheats", NULL, DBM_CHEAT_MENU },
446};
447s32 MainMenuPos = 0;
448
449// position of the blue box containing the main menu options
452const s32 MainBoxWidth = 96;
454
456f32 DebugArrowPhase = 0.0f;
457#define DEBUG_ARROW_ANIM_RATE 6
458
484
485void dx_debug_menu_main() {
487
489
491
493 if (DebugArrowPhase >= 360.0f) {
494 DebugArrowPhase -= 360.0f;
495 }
497
499
500 // check input for menu open/close
501 if (DebugMenuState == DBM_NONE) {
502 if (PRESSED(BUTTON_D_LEFT)) {
504 }
505 if (PRESSED(BUTTON_D_RIGHT)) {
507 }
508 } else if (DebugMenuState == DBM_MAIN_MENU) {
511 }
512 } else if (DebugMenuState == DBM_EVT_MAIN) {
515 }
516 }
517
518 if (DebugMenuState != DBM_NONE) {
519 // main menu is always drawn if the debug menu is open at all
522 }
523
524 switch (DebugMenuState) {
525 case DBM_NONE: // to satisfy compiler
526 break;
527 case DBM_MAIN_MENU:
529 break;
530 case DBM_QUICK_SAVE:
532 break;
533 case DBM_SELECT_AREA:
535 break;
536 case DBM_SELECT_MAP:
538 break;
539 case DBM_SELECT_ENTRY:
541 break;
544 break;
545 case DBM_SET_STORY:
547 break;
548 case DBM_SOUND_PLAYER:
550 break;
551 case DBM_SELECT_SOUND:
553 break;
556 break;
559 break;
562 break;
565 break;
568 break;
571 break;
574 break;
577 break;
580 break;
583 break;
584 case DBM_EDIT_MEMORY:
585 break;
588 break;
589 case DBM_CHEAT_MENU:
591 break;
592 case DBM_EVT_MAIN:
594 break;
595 case DBM_EVT_SELECT:
597 break;
598 case DBM_EVT_ATTACHED:
600 break;
601 }
602 }
603
605}
606
611 DebugMainMenu[MainMenuPos].onSelect();
612 } else {
614 }
615 }
616}
617
619 s32 idx;
620
622
623 for (idx = 0; idx < ARRAY_COUNT(DebugMainMenu); idx++) {
624 s32 color = DefaultColor;
625 if (MainMenuPos == idx) {
627 }
629 }
630}
631
632// ----------------------------------------------------------------------------
633// quick save
634// only restores previous player position on maps with save points, otherwise enters through most recent entry
635
643}
644
650}
651
653 { "Cancel", NULL, DBM_MAIN_MENU },
654 { "Quick Save", dx_debug_exec_quick_save },
655 { "Quick Load", dx_debug_exec_quick_load },
656};
658
660 s32 idx;
661
662 // handle input
664 if (RELEASED(BUTTON_L)) {
666 } else if (RELEASED(BUTTON_R)) {
669 } else {
671 }
672 }
673
674 // draw
676
677 for (idx = 0; idx < ARRAY_COUNT(DebugQuickSaveMenu); idx++) {
680 }
681}
682
683// ----------------------------------------------------------------------------
684// map select
685
689
690const s32 AreaSizeX = 30;
691const s32 MapSizeX = 50;
692
694 s32 i, j, idx;
695 s32 nrows, ncols;
698
699 // select optimal shape for the menu based on numAreas
700 // maximum supported size is 9 x 5 (45 areas)
701
702 if (numAreas <= 6) {
703 nrows = numAreas;
704 ncols = 1;
705 } else if (numAreas <= 12) {
706 nrows = 6;
707 ncols = 2;
708 } else if (numAreas <= 18) {
709 nrows = 6;
710 ncols = 3;
711 } else if (numAreas <= 24) {
712 nrows = 6;
713 ncols = 4;
714 } else if (numAreas <= 30) {
715 nrows = 6;
716 ncols = 5;
717 } else if (numAreas <= 35) {
718 nrows = 7;
719 ncols = 5;
720 } else if (numAreas <= 40) {
721 nrows = 8;
722 ncols = 5;
723 } else {
724 nrows = 9;
725 ncols = 5;
726 }
727
728 // handle input
729
731 if (SelectAreaMenuPos != prev) {
734 }
735 if (RELEASED(BUTTON_L)) {
737 } else if (RELEASED(BUTTON_R)) {
739 }
740
741 // draw
742
744
745 idx = 0;
746 for (i = 0; i < ncols; i++) {
747 for (j = 0; j < nrows; j++) {
748 if (idx < numAreas) {
750 char* name = &(gAreas[idx].id)[5]; // trim "area_" prefix
751 dx_debug_draw_ascii(name, color, SubmenuPosX + i * AreaSizeX, SubmenuPosY + (j + 1) * RowHeight);
752 }
753 idx++;
754 }
755 }
756}
757
759 s32 i, j, idx;
760 s32 numRows, numCols;
765
766 // select optimal shape for the menu based on numMaps
767
768 if (numMaps <= 6) {
769 numRows = numMaps;
770 numCols = 1;
771 } else if (numMaps <= 12) {
772 numRows = 6;
773 numCols = 2;
774 } else {
775 numRows = 6;
776 numCols = 3;
777 }
778
779 // handle input
780
782 if (SelectMapMenuPos != prev) {
784 }
785 if (RELEASED(BUTTON_L)) {
787 } else if (RELEASED(BUTTON_R)) {
789 }
790
791 // draw
792
793 curCol = SelectMapMenuPos / numRows;
794 maxCol = numMaps / numRows;
795
796 if (maxCol > 2) {
797 dx_debug_draw_box(SubBoxPosX, SubBoxPosY + RowHeight, MapSizeX * numCols + 8, RowHeight * (numRows + 1) + 8, WINDOW_STYLE_20, 192);
798 } else {
799 dx_debug_draw_box(SubBoxPosX, SubBoxPosY + RowHeight, MapSizeX * numCols + 8, RowHeight * numRows + 8, WINDOW_STYLE_20, 192);
800 }
801
802 if (maxCol < 3) {
803 startCol = 0;
804 } else if (curCol == 0) {
805 startCol = 0;
806 } else if (curCol == maxCol) {
807 startCol = maxCol - 2;
808 } else {
809 startCol = curCol - 1;
810 }
811
812 idx = numRows * startCol;
813 for (i = startCol; i <= startCol + 2; i++) {
814 for (j = 0; j < numRows; j++) {
815 if (idx < numMaps) {
817 char* name = maps[idx].id;
818 dx_debug_draw_ascii(name, color, SubmenuPosX + (i - startCol) * MapSizeX, SubmenuPosY + (j + 1) * RowHeight);
819 }
820 idx++;
821 }
822 }
823
824 if (maxCol > 2) {
825 // left arrow
826 if (curCol > 1) {
827 char msgLeftArrow[] = {
829 };
831 }
832 // right arrow
833 if (curCol < maxCol - 1) {
834 char msgRightArrow[] = {
836 };
838 }
839 }
840}
841
843 s32 idx, areaID, mapID;
845
846 // handle input
847 if (RELEASED(BUTTON_L)) {
849 } else if (RELEASED(BUTTON_R)) {
857 }
858
859 if (NAV_UP) {
861 }
862 if (NAV_DOWN) {
864 }
865
866 if (SelectedEntryValue < 0) {
868 }
869 if (SelectedEntryValue > 0x7F) {
870 SelectedEntryValue = 0x7F;
871 }
872
873 // draw
875
876 for (idx = 0; idx < ARRAY_COUNT(DebugQuickSaveMenu); idx++) {
877 char fmtBuf[16];
882 }
883}
884
885// ----------------------------------------------------------------------------
886// battle select
887
894};
895
902};
903
910};
911
913
915
918 .drops = &DebugDummyDrops,
919};
920
923 .enemy = { &DebugDummyEnemy },
924 .count = 0,
925 .battle = 0,
926 .stage = 0,
927};
928
931
933 DebugDummyEncounter.stage = stage;
934
935 es->curEncounter = &DebugDummyEncounter;
936 es->curEnemy = &DebugDummyEnemy;
937 es->hitType = ENCOUNTER_TRIGGER_NONE;
938 es->firstStrikeType = FIRST_STRIKE_NONE;
939 es->forbidFleeing = FALSE;
940 es->scriptedBattle = TRUE;
941 es->songID = -1;
942 es->unk_18 = -1;
943 es->fadeOutAmount = 0;
944 es->substateDelay = 0;
945
948
952}
953
959 s16 stage = DebugBattleNum[DEBUG_BATTLE_STAGE] & 0xFFFF;
960
962}
963
965 s32 idx;
966 char fmtBuf[16];
968
969 // handle input
970 if (RELEASED(BUTTON_L)) {
972 } else if (RELEASED(BUTTON_R)) {
975 }
976
978 if (NAV_UP) {
981 value = dx_debug_clamp(value, -1, 0x7F);
983 value = dx_debug_wrap(value, 0, maxAreaTens);
984 } else {
985 value = dx_debug_wrap(value, 0, 0xF);
986 }
988 }
989 if (NAV_DOWN) {
992 value = dx_debug_clamp(value, -1, 0x7F);
994 value = dx_debug_wrap(value, 0, maxAreaTens);
995 } else {
996 value = dx_debug_wrap(value, 0, 0xF);
997 }
999 }
1000
1001 // draw
1007
1008 for (idx = 0; idx < 5; idx++) {
1010 s32 offset = BattleDigitOffsets[idx];
1011 char* fmt = (idx == 4) ? "%02X" : "%X";
1012
1013 dx_debug_draw_number(DebugBattleNum[idx] & 0xFF, fmt, color, 255, SubmenuPosX + offset, SubmenuPosY + 2 * RowHeight);
1014 }
1015}
1016
1017// ----------------------------------------------------------------------------
1018// set story byte
1019
1021 .isHex = TRUE,
1022 .digits = { 0, 0 },
1023 .size = 2,
1024 .pos = 0,
1025};
1026
1028 if (DebugStateChanged) {
1031 }
1032
1033 // handle input
1034 if (RELEASED(BUTTON_L)) {
1036 } else if (RELEASED(BUTTON_R)) {
1040 }
1041
1043
1044 // draw
1048}
1049
1050// ----------------------------------------------------------------------------
1051// sound player
1052
1054 { "Play Sound", NULL, DBM_SELECT_SOUND },
1055 { "Stop Sound", NULL, DBM_SELECT_SOUND },
1056};
1058
1060 s32 idx;
1061
1063
1064 for (idx = 0; idx < ARRAY_COUNT(DebugSoundPlayerMenu); idx++) {
1065 s32 color;
1066 if (activeMenu) {
1068 } else {
1070 }
1072 }
1073}
1074
1076 // handle input
1078 if (RELEASED(BUTTON_L)) {
1080 } else if (RELEASED(BUTTON_R)) {
1082 }
1083
1085}
1086
1088 .isHex = TRUE,
1089 .digits = { 0, 0, 0, 0 },
1090 .size = 4,
1091 .pos = 0,
1092};
1093
1095 // handle input
1096 if (RELEASED(BUTTON_L)) {
1098 } else if (RELEASED(BUTTON_R)) {
1099 if (SoundPlayerMenuPos == 0) {
1101 } else {
1103 }
1104 }
1105
1107
1112}
1113
1114// ----------------------------------------------------------------------------
1115// edit partners
1116
1119
1121 s32 idx;
1122
1123 if (DebugStateChanged) {
1124 for (idx = 1; idx < ARRAY_COUNT(gPlayerData.partners); idx++) {
1126 }
1127 }
1128
1129 // handle input
1132 if (RELEASED(BUTTON_L)) {
1134 } else if (RELEASED(BUTTON_R)) {
1135 for (idx = 1; idx < ARRAY_COUNT(gPlayerData.partners); idx++) {
1137 if (val >= 0) {
1140 } else {
1143 }
1144 }
1146 }
1147
1148 // draw
1149 dx_debug_draw_box(SubBoxPosX, SubBoxPosY, 120, 14 * 11 + 8, WINDOW_STYLE_20, 192);
1150
1151 for (idx = 1; idx < ARRAY_COUNT(gPlayerData.partners); idx++) {
1154 s32 posY = SubmenuPosY + (idx - 1) * 14;
1155 s32 level = DebugPartnerLevels[idx];
1156 s32 alpha = (isSelected || level >= 0) ? 254 : 120;
1157
1158 if (level < 0) {
1159 dx_debug_draw_number(level, "%d", color, alpha, SubmenuPosX - 3, posY);
1160 } else {
1161 dx_debug_draw_number(level, "%d", color, alpha, SubmenuPosX + 3, posY);
1162 }
1163
1164 dx_debug_draw_msg(gPartnerPopupProperties[idx].nameMsg, color, alpha, SubmenuPosX + 15, posY);
1165
1166 if (level == 1) {
1168 draw_msg((s32)msg, SubmenuPosX + 82, posY - 1, 255, MSG_PAL_BLUE, 0);
1169 } else if (level == 2) {
1171 draw_msg((s32)msg, SubmenuPosX + 82, posY - 1, 255, MSG_PAL_BLUE, 0);
1172 }
1173 }
1174}
1175
1176// ----------------------------------------------------------------------------
1177// edit inventory
1178
1180 { "Items", NULL, DBM_INV_EDIT_ITEMS },
1181 { "Badges", NULL, DBM_INV_EDIT_BADGES },
1182 { "Key Items", NULL, DBM_INV_EDIT_KEYS },
1183 { "Equipment", NULL, DBM_INV_EDIT_GEAR },
1184 { "Stats", NULL, DBM_INV_EDIT_STATS },
1185 { "Coins", NULL, DBM_INV_EDIT_COINS },
1186 { "Star Points", NULL, DBM_INV_EDIT_STAR_POINTS },
1187 { "Star Pieces", NULL, DBM_INV_EDIT_STAR_PIECES },
1188};
1190
1192 s32 idx;
1193
1194 // handle input
1196 if (RELEASED(BUTTON_L)) {
1198 } else if (RELEASED(BUTTON_R)) {
1201 } else {
1203 }
1204 }
1205
1206 // draw
1208
1209 for (idx = 0; idx < ARRAY_COUNT(DebugInventoryMenu); idx++) {
1212 }
1213}
1214
1216
1217#define _MAX_INV_SIZE(a,b,c) MAX(MAX(ARRAY_COUNT(a), ARRAY_COUNT(b)), ARRAY_COUNT(c))
1219
1220typedef struct DebugItemsMenu {
1221 s16 pos;
1222 s16 startPos;
1223 s8 col;
1225
1227 .pos = 0,
1228 .startPos = 0,
1229 .col = 0,
1230};
1231
1233 .pos = 0,
1234 .startPos = 0,
1235 .col = 0,
1236};
1237
1239 .pos = 0,
1240 .startPos = 0,
1241 .col = 0,
1242};
1243
1244void dx_debug_set_item_id(s32 idx, s16 itemID) {
1245 s32 j;
1246
1247 for (j = 2; j >= 0; j--) {
1248 DebugItemDigits[idx][j] = (itemID & 0xF);
1249 itemID >>= 4;
1250 }
1251}
1252
1254 s32 j;
1255 s16 val = 0;
1256
1257 for (j = 0; j < 3; j++) {
1258 val <<= 4;
1259 val |= (DebugItemDigits[idx][j] & 0xF);
1260 }
1261 return val;
1262}
1263
1266 s16* invItems;
1267 s32 invSize;
1268 s32 i, j;
1269
1270 switch (DebugMenuState) {
1271 case DBM_INV_EDIT_ITEMS:
1272 menu = &DebugItems;
1273 invItems = gPlayerData.invItems;
1275 break;
1276 case DBM_INV_EDIT_KEYS:
1277 menu = &DebugKeys;
1278 invItems = gPlayerData.keyItems;
1280 break;
1282 menu = &DebugBadges;
1283 invItems = gPlayerData.badges;
1285 break;
1286 default:
1287 PANIC_MSG("invalid debug menu state");
1288 }
1289
1290 if (DebugStateChanged) {
1291 for (i = 0; i < invSize; i++) {
1292 dx_debug_set_item_id(i, invItems[i]);
1293 }
1294 }
1295
1296 if (RELEASED(BUTTON_L)) {
1297 if (DebugEditingItem) {
1299 } else {
1301 }
1302 } else if (RELEASED(BUTTON_R)) {
1303 if (!DebugEditingItem) {
1305 } else {
1306 for (i = 0; i < invSize; i++) {
1307 invItems[i] = dx_debug_get_item_id(i);
1308 }
1310 }
1311 }
1312
1313 if (DebugEditingItem) {
1314 s32 digit;
1315 menu->col = dx_debug_menu_nav_1D_horizontal(menu->col, 0, 2, FALSE);
1316 digit = DebugItemDigits[menu->pos][menu->col];
1318 DebugItemDigits[menu->pos][menu->col] = digit;
1319 } else {
1320 if (NAV_UP) {
1321 menu->pos--;
1322 if (menu->pos < 0) {
1323 menu->pos = invSize - 1;
1324 menu->startPos = menu->pos - 9;
1325 } else {
1326 menu->startPos = MIN(menu->startPos, menu->pos);
1327 }
1328 }
1329 if (NAV_DOWN) {
1330 menu->pos++;
1331 if (menu->pos >= invSize) {
1332 menu->pos = 0;
1333 menu->startPos = 0;
1334 } else {
1335 menu->startPos = MAX(menu->startPos, menu->pos - 9);
1336 }
1337 }
1338 }
1339
1340 // draw
1342
1343 for (i = menu->startPos; i <= menu->startPos + 9; i++) {
1344 s32 posY = SubmenuPosY + (i - menu->startPos) * RowHeight;
1345 s32 itemID = dx_debug_get_item_id(i);
1346 b32 isSelectedRow = (menu->pos == i);
1347
1348 if (DebugEditingItem) {
1349 dx_debug_draw_editable_number(i, "%02X", -1, FALSE, SubmenuPosX, posY);
1350 dx_debug_draw_editable_number(itemID, "%03X", menu->col, isSelectedRow, SubmenuPosX + 20, posY);
1351 } else {
1353 dx_debug_draw_editable_number(itemID, "%03X", -1, FALSE, SubmenuPosX + 20, posY);
1354 }
1355
1357 if (itemID > 0 && itemID < NUM_ITEMS) {
1358 itemMsg = gItemTable[itemID].nameMsg;
1359 }
1360 if (itemMsg != MSG_NONE) {
1362 } else {
1363 char msgBuf[] = {
1367 };
1368 draw_msg((s32)msgBuf, SubmenuPosX + 50, posY, 255, DefaultColor, 0);
1369 }
1370 }
1371
1372 // up arrow
1373 if (menu->startPos > 0) {
1374 char msgArrow[] = {
1376 };
1378 }
1379 // down arrow
1380 if (menu->startPos + 10 < invSize) {
1381 char msgArrow[] = {
1383 };
1384 draw_msg((s32)msgArrow, SubmenuPosX + 132, SubmenuPosY + 134 - round(3.0f * ArrowAnimOffset), 255, DefaultColor, 0);
1385 }
1386}
1387
1388enum {
1393};
1394
1395s32 DebugGearValues[] = {
1396 [DEBUG_GEAR_BOOTS] 0,
1400};
1401s32 DebugGearPos = 0;
1402
1404 s32 idx;
1405 s32 val, dx;
1406
1407 if (DebugStateChanged) {
1412 }
1413
1414 if (RELEASED(BUTTON_L)) {
1416 } else if (RELEASED(BUTTON_R)) {
1421
1424 }
1427 }
1428
1430 }
1431
1433
1434 dx = 0;
1435 if (NAV_RIGHT) {
1436 dx++;
1437 }
1438 if (NAV_LEFT) {
1439 dx--;
1440 }
1441 if (dx != 0) {
1442 s32 min = 0;
1443 s32 max = 0;
1444
1445 switch (DebugGearPos) {
1446 case DEBUG_GEAR_BOOTS:
1447 min = -1;
1448 max = 2;
1449 break;
1450 case DEBUG_GEAR_HAMMER:
1451 min = -1;
1452 max = 2;
1453 break;
1455 min = 0;
1456 max = 1;
1457 break;
1459 min = 0;
1460 max = 2;
1461 break;
1462 }
1463
1465 }
1466
1467 // draw
1474
1475 for (idx = 0; idx < ARRAY_COUNT(DebugGearValues); idx++) {
1477 dx_debug_draw_number(DebugGearValues[idx], "%2d", color, 255, SubmenuPosX + 63, SubmenuPosY + (idx + 2) * RowHeight);
1478 }
1479}
1480
1481enum {
1487};
1488
1489s32 DebugStatValues[] = {
1490 [DEBUG_STAT_HP] 0,
1491 [DEBUG_STAT_FP] 0,
1492 [DEBUG_STAT_BP] 0,
1493 [DEBUG_STAT_LEVEL] 0,
1495};
1496s32 DebugStatPos = 0;
1497
1499 s32 idx;
1500 s32 val, dx;
1501
1502 if (DebugStateChanged) {
1508 }
1509
1510 if (RELEASED(BUTTON_L)) {
1512 } else if (RELEASED(BUTTON_R)) {
1520 }
1521
1523
1524 dx = 0;
1525 if (NAV_RIGHT) {
1526 dx++;
1527 }
1528 if (NAV_LEFT) {
1529 dx--;
1530 }
1531 if (dx != 0) {
1532 switch (DebugStatPos) {
1533 case DEBUG_STAT_HP:
1536 break;
1537 case DEBUG_STAT_FP:
1540 break;
1541 case DEBUG_STAT_BP:
1544 break;
1545 case DEBUG_STAT_LEVEL:
1548 break;
1549 case DEBUG_STAT_SPIRITS:
1552 break;
1553 }
1554 }
1555
1556 // draw
1564
1565 for (idx = 0; idx < ARRAY_COUNT(DebugStatValues); idx++) {
1567 dx_debug_draw_number(DebugStatValues[idx], "%2d", color, 255, SubmenuPosX + 55, SubmenuPosY + (idx + 2) * RowHeight);
1568 }
1569}
1570
1572 .isHex = FALSE,
1573 .digits = { 0, 0, 0 },
1574 .size = 3,
1575 .pos = 0,
1576};
1577
1579 if (DebugStateChanged) {
1581 }
1582
1583 // handle input
1584 if (RELEASED(BUTTON_L)) {
1586 } else if (RELEASED(BUTTON_R)) {
1590 }
1592
1593 // draw
1597}
1598
1600 .isHex = FALSE,
1601 .digits = { 0, 0 },
1602 .size = 2,
1603 .pos = 0,
1604};
1605
1607 if (DebugStateChanged) {
1609 }
1610
1611 // handle input
1612 if (RELEASED(BUTTON_L)) {
1614 } else if (RELEASED(BUTTON_R)) {
1618 }
1620
1621 // draw
1625}
1626
1628 .isHex = FALSE,
1629 .digits = { 0, 0, 0 },
1630 .size = 3,
1631 .pos = 0,
1632};
1633
1635 if (DebugStateChanged) {
1637 }
1638
1639 // handle input
1640 if (RELEASED(BUTTON_L)) {
1642 } else if (RELEASED(BUTTON_R)) {
1646 }
1648
1649 // clamp maximum
1652 }
1653
1654 // draw
1658}
1659
1660// ----------------------------------------------------------------------------
1661// view collision
1662
1663typedef struct DebugCollisionEntry {
1664 char* text;
1665 s32 state;
1667
1668enum {
1677};
1678
1680 [DBC_SHOW_COLLISION] { "Show Collision", FALSE },
1681 [DBC_CULL_BACK] { "Cull Back", TRUE },
1682 [DBC_SHOW_DISABLED] { "Show Disabled", TRUE },
1683 [DBC_HIDE_MODELS] { "Hide Models", FALSE },
1684 [DBC_EXTRUDE_FACES] { "Extrude Faces", FALSE },
1685 [DBC_HIGHLIGHT_FLOOR] { "Highlight Floor", FALSE },
1686 [DBC_HIGHLIGHT_WALL] { "Highlight Wall", FALSE },
1687 [DBC_FADE_DIST] { "Near Fade Dist", 1 },
1688};
1689
1691
1693 s32 idx;
1694
1695 // handle input
1696 if (RELEASED(BUTTON_L)) {
1698 }
1699
1701 if (NAV_LEFT || NAV_RIGHT) {
1703 }
1704 } else {
1708 }
1710
1711 // draw
1713
1714 for (idx = 0; idx < ARRAY_COUNT(DebugCollisionMenu); idx++) {
1716 if (idx != DBC_FADE_DIST) {
1717 char* onoff = DebugCollisionMenu[idx].state ? "On" : "Off";
1719 } else {
1721 dx_debug_draw_number(fadeDist, "%d", color, 255, SubmenuPosX, SubmenuPosY + (idx + 1) * RowHeight);
1722 }
1724 }
1725}
1726
1727void dx_debug_add_collision_vtx(Vtx_t* vtxBuffer, Vec3f* vert, Vec3f* normal, s32 r, s32 g, s32 b, s32 a) {
1729 vtxBuffer->ob[0] = vert->x + normal->x;
1730 vtxBuffer->ob[1] = vert->y + normal->y;
1731 vtxBuffer->ob[2] = vert->z + normal->z;
1732 } else {
1733 vtxBuffer->ob[0] = vert->x;
1734 vtxBuffer->ob[1] = vert->y;
1735 vtxBuffer->ob[2] = vert->z;
1736 }
1737 vtxBuffer->tc[0] = 0;
1738 vtxBuffer->tc[1] = 0;
1739 vtxBuffer->cn[0] = r;
1740 vtxBuffer->cn[1] = g;
1741 vtxBuffer->cn[2] = b;
1742 vtxBuffer->cn[3] = a;
1743}
1744
1745#define MAX_DEBUG_TRIS 1024
1746
1747typedef struct DebugTriangle {
1749 s16 depth;
1750 s16 colliderID;
1752
1755
1758
1761 s32 rdpBufPos;
1762 b32 culling;
1763 s32 fadeDist;
1764 s32 i, j;
1765 s32 dist;
1766
1768
1770 return;
1771 }
1772
1773 // find all collider trianges
1774 DebugTriPos = 0;
1775 for (i = 0; i < gCollisionData.numColliders; i++) {
1777
1779 continue;
1780 }
1781
1782 for (j = 0; j < collider->numTriangles; j++) {
1784 ColliderTriangle* tri = &collider->triangleTable[j];
1785 f32 outX, outY, outZ, outW;
1786 f32 cX = (tri->v1->x + tri->v2->x + tri->v3->x) / 3;
1787 f32 cY = (tri->v1->y + tri->v2->y + tri->v3->y) / 3;
1788 f32 cZ = (tri->v1->z + tri->v2->z + tri->v3->z) / 3;
1789
1790 transform_point(camera->mtxPerspective, cX, cY, cZ, 1.0f, &outX, &outY, &outZ, &outW);
1791
1792 if (outZ < -100) {
1793 // dont draw triangles sufficiently far behind the camera
1794 DebugTriPos--;
1795 } else {
1796 DebugTris[DebugTriPos].tri = tri;
1797 DebugTris[DebugTriPos].depth = outZ;
1798 DebugTris[DebugTriPos].colliderID = i;
1799 }
1800 }
1801 DebugTriPos++;
1802 }
1803 }
1804
1806
1807 // sort triangles by depth
1808#define LESS(i, j) DebugTris[i].depth > DebugTris[j].depth
1809#define SWAP(i, j) temp = DebugTris[i], DebugTris[i] = DebugTris[j], DebugTris[j] = temp
1811#undef LESS
1812#undef SWAP
1813
1818 gSPTexture(gMainGfxPos++, 0x0080, 0x0080, 0, G_TX_RENDERTILE, G_OFF);
1820
1821 if (DebugCollisionMenu[DBC_CULL_BACK].state) {
1823 culling = TRUE;
1824 } else {
1826 culling = FALSE;
1827 }
1828
1829 DebugVtxPos = 0;
1830 rdpBufPos = 0;
1831
1832 // build the display list and fill DebugVtxBuf at the same time
1833 for (i = 0; i < DebugTriPos; i++) {
1836 s32 r, g, b, a;
1837
1840 highlight = TRUE;
1841 }
1843 highlight = TRUE;
1844 }
1845
1846 if (rdpBufPos == 0) {
1847 // always load vertices 30 at a time
1849 }
1850
1851 // manage culling state for two-sided triangles
1852 if (DebugCollisionMenu[DBC_CULL_BACK].state) {
1853 if (!tri->oneSided && culling) {
1856 culling = FALSE;
1857 } else if (tri->oneSided && !culling) {
1860 culling = TRUE;
1861 }
1862 }
1863
1864 // would be more efficient to pack these into gSP2Triangles ad hoc
1865 // but it becomes difficult to manage once RDP state changes enter the mix due to two-sided triangles
1867
1868 // update rdp buffer pos for next triangle draw
1869 rdpBufPos += 3;
1870 if (rdpBufPos == 30) {
1871 rdpBufPos = 0;
1872 }
1873
1874 if (highlight) {
1875 r = g = b = 196;
1876 } else {
1877 r = round(fabs(tri->normal.x) * 245.0);
1878 g = round(fabs(tri->normal.y) * 245.0);
1879 b = round(fabs(tri->normal.z) * 245.0);
1880 }
1881 a = 180;
1882
1883 // fade triangles too close to the camera
1885 if(fadeDist > 0) {
1886 dist = debugTri->depth - (fadeDist - 1) * 25;
1887 if (dist < 20) {
1888 // from a=20 at d=40 to a=0 at d=-100
1889 a = dx_debug_clamp((dist + 100) / 6, 0, 20);
1890 } else {
1891 a = dx_debug_clamp(dist, 20, 180);
1892 }
1893 }
1894
1895 // build vertices for this triangle
1896 dx_debug_add_collision_vtx(&DebugVtxBuf[DebugVtxPos++], tri->v1, &tri->normal, r, g, b, a);
1897 dx_debug_add_collision_vtx(&DebugVtxBuf[DebugVtxPos++], tri->v2, &tri->normal, r, g, b, a);
1898 dx_debug_add_collision_vtx(&DebugVtxBuf[DebugVtxPos++], tri->v3, &tri->normal, r, g, b, a);
1899 }
1900
1901 // done
1903}
1904
1906 return DebugCollisionMenu[DBC_HIDE_MODELS].state;
1907}
1908
1909// ----------------------------------------------------------------------------
1910// cheat menu
1911
1912typedef struct DebugCheatEntry {
1913 char* text;
1914 b32 enabled;
1916
1918 [DEBUG_CHEAT_GOD_MODE] { "God Mode", FALSE },
1919 [DEBUG_CHEAT_SPEED_MODE] { "Speed Mode", FALSE },
1920 [DEBUG_CHEAT_FLY] { "Fly With L", FALSE },
1921 [DEBUG_CHEAT_HIGH_JUMP] { "High Jump", FALSE },
1922 [DEBUG_CHEAT_IGNORE_WALLS] { "Ignore Walls", FALSE },
1923};
1924
1925s32 DebugCheatPos = 0;
1926
1928 s32 idx;
1929
1930 // handle input
1931 if (RELEASED(BUTTON_L)) {
1933 }
1934 if (NAV_LEFT || NAV_RIGHT) {
1936
1937 // actions to execute on state change
1938 switch (DebugCheatPos) {
1940 case DEBUG_CHEAT_FLY:
1943 break;
1945 if (!DebugCheatMenu[DebugCheatPos].enabled) {
1946 gPlayerStatus.walkSpeed = 2.0f;
1947 gPlayerStatus.runSpeed = 4.0f;
1949 } else {
1950 gPlayerStatus.walkSpeed = 6.0f;
1951 gPlayerStatus.runSpeed = 12.0f;
1953 }
1954 break;
1955 }
1956
1957 }
1959
1960 // draw
1962
1963 for (idx = 0; idx < ARRAY_COUNT(DebugCheatMenu); idx++) {
1965 char* onoff = DebugCheatMenu[idx].enabled ? "On" : "Off";
1966
1969 }
1970}
1971
1973 return DebugCheatMenu[cheat].enabled;
1974}
1975
1976// ----------------------------------------------------------------------------
1977// script debugger
1978
1979const s32 EvtDebugBoxWidth = 72;
1981
1982const s32 EvtDebugMenuPosX = 314 - EvtDebugBoxWidth; // right edge should be at 314
1983const s32 EvtDebugMenuPosY = 60;
1984
1985// position of the blue box containing the main menu options
1988
1989const s32 EvtDebugInfoX = 26;
1990const s32 EvtDebugInfoY = 60;
1991const s32 EvtDebugInfoWidth = 212;
1993
1994char* EvtMainMenuOpts[] = {
1995 "Attach",
1996 "Break",
1997 "Resume",
1998 "Break All",
1999 "Resume All",
2000};
2001
2003
2004s32 EvtListCurPos = 0;
2006
2010
2012extern s32 gScriptIndexList[];
2013extern s32 gScriptIdList[];
2014extern s32 gScriptListCount;
2015
2018
2022
2027
2028typedef struct DebugOpcode {
2029 char* text;
2030} DebugOpcode;
2031
2033 [EVT_OP_END] { "End" },
2034 [EVT_OP_RETURN] { "Return" },
2035 [EVT_OP_LABEL] { "Label" },
2036 [EVT_OP_GOTO] { "Goto" },
2037 [EVT_OP_LOOP] { "Loop" },
2038 [EVT_OP_END_LOOP] { "EndLoop" },
2039 [EVT_OP_BREAK_LOOP] { "BreakLoop" },
2040 [EVT_OP_WAIT_FRAMES] { "Wait" },
2041 [EVT_OP_WAIT_SECS] { "WaitSecs" },
2042 [EVT_OP_IF_EQ] { "If EQ" },
2043 [EVT_OP_IF_NE] { "If NE" },
2044 [EVT_OP_IF_LT] { "If LT" },
2045 [EVT_OP_IF_GT] { "If GT" },
2046 [EVT_OP_IF_LE] { "If LE" },
2047 [EVT_OP_IF_GE] { "If GE" },
2048 [EVT_OP_IF_FLAG] { "If AND" },
2049 [EVT_OP_IF_NOT_FLAG] { "If NAND" },
2050 [EVT_OP_ELSE] { "Else" },
2051 [EVT_OP_END_IF] { "EndIf" },
2052 [EVT_OP_SWITCH] { "Switch" },
2053 [EVT_OP_SWITCH_CONST] { "SwitchConst" },
2054 [EVT_OP_CASE_EQ] { "Case EQ" },
2055 [EVT_OP_CASE_NE] { "Case NE" },
2056 [EVT_OP_CASE_LT] { "Case LT" },
2057 [EVT_OP_CASE_GT] { "Case GT" },
2058 [EVT_OP_CASE_LE] { "Case LE" },
2059 [EVT_OP_CASE_GE] { "Case GE" },
2060 [EVT_OP_CASE_DEFAULT] { "Default" },
2061 [EVT_OP_CASE_OR_EQ] { "CaseOR EQ" },
2062 [EVT_OP_CASE_AND_EQ] { "CaseAND EQ" },
2063 [EVT_OP_CASE_FLAG] { "Case AND" },
2064 [EVT_OP_END_CASE_GROUP] { "EndCaseGroup" },
2065 [EVT_OP_CASE_RANGE] { "Case Range" },
2066 [EVT_OP_BREAK_SWITCH] { "BreakSwitch" },
2067 [EVT_OP_END_SWITCH] { "EndSwitch" },
2068 [EVT_OP_SET] { "Set" },
2069 [EVT_OP_SET_CONST] { "SetConst" },
2070 [EVT_OP_SETF] { "SetF" },
2071 [EVT_OP_ADD] { "Add" },
2072 [EVT_OP_SUB] { "Sub" },
2073 [EVT_OP_MUL] { "Mul" },
2074 [EVT_OP_DIV] { "Div" },
2075 [EVT_OP_MOD] { "Mod" },
2076 [EVT_OP_ADDF] { "AddF" },
2077 [EVT_OP_SUBF] { "SubF" },
2078 [EVT_OP_MULF] { "MulF" },
2079 [EVT_OP_DIVF] { "DivF" },
2080 [EVT_OP_USE_BUF] { "UseBuf" },
2081 [EVT_OP_BUF_READ1] { "BufRead1" },
2082 [EVT_OP_BUF_READ2] { "BufRead2" },
2083 [EVT_OP_BUF_READ3] { "BufRead3" },
2084 [EVT_OP_BUF_READ4] { "BufRead4" },
2085 [EVT_OP_BUF_PEEK] { "BufPeek" },
2086 [EVT_OP_USE_FBUF] { "UseFBuf" },
2087 [EVT_OP_FBUF_READ1] { "FBufRead1" },
2088 [EVT_OP_FBUF_READ2] { "FBufRead2" },
2089 [EVT_OP_FBUF_READ3] { "FBufRead3" },
2090 [EVT_OP_FBUF_READ4] { "FBufRead4" },
2091 [EVT_OP_FBUF_PEEK] { "FBufPeek" },
2092 [EVT_OP_USE_ARRAY] { "UseArray" },
2093 [EVT_OP_USE_FLAGS] { "UseFlags" },
2094 [EVT_OP_MALLOC_ARRAY] { "MallocArray" },
2095 [EVT_OP_BITWISE_AND] { "AND" },
2096 [EVT_OP_BITWISE_AND_CONST] { "AND Const" },
2097 [EVT_OP_BITWISE_OR] { "OR" },
2098 [EVT_OP_BITWISE_OR_CONST] { "OR Const" },
2099 [EVT_OP_CALL] { "Call" },
2100 [EVT_OP_EXEC] { "Exec" },
2101 [EVT_OP_EXEC_GET_TID] { "ExecGet" },
2102 [EVT_OP_EXEC_WAIT] { "ExecWait" },
2103 [EVT_OP_BIND_TRIGGER] { "BindTrigger" },
2104 [EVT_OP_UNBIND] { "Unbind" },
2105 [EVT_OP_KILL_THREAD] { "KillThread" },
2106 [EVT_OP_JUMP] { "Jump" },
2107 [EVT_OP_SET_PRIORITY] { "SetPriority" },
2108 [EVT_OP_SET_TIMESCALE] { "SetTimescale" },
2109 [EVT_OP_SET_GROUP] { "SetGroup" },
2110 [EVT_OP_BIND_PADLOCK] { "BindPadlock" },
2111 [EVT_OP_SUSPEND_GROUP] { "SuspendGroup" },
2112 [EVT_OP_RESUME_GROUP] { "ResumeGroup" },
2113 [EVT_OP_SUSPEND_OTHERS] { "SuspendOthers" },
2114 [EVT_OP_RESUME_OTHERS] { "ResumeOthers" },
2115 [EVT_OP_SUSPEND_THREAD] { "SuspendThread" },
2116 [EVT_OP_RESUME_THREAD] { "ResumeThread" },
2117 [EVT_OP_IS_THREAD_RUNNING] { "IsRunning" },
2118 [EVT_OP_THREAD] { "Thread" },
2119 [EVT_OP_END_THREAD] { "EndThread" },
2120 [EVT_OP_CHILD_THREAD] { "ChildThread" },
2121 [EVT_OP_END_CHILD_THREAD] { "EndChildThread" },
2122 [EVT_OP_DEBUG_LOG] { "Log" },
2123 [EVT_OP_DEBUG_PRINT_VAR] { "PrintVar" },
2124 [EVT_OP_92] { "Op92" },
2125 [EVT_OP_93] { "Op93" },
2126 [EVT_OP_94] { "Op94" },
2127 [EVT_OP_DEBUG_BREAKPOINT] { "Breakpoint" },
2128};
2129
2130// main menu options for evt debugger
2131enum {
2138};
2139
2140// menu options for evt debugger while attached
2141enum {
2148};
2149
2150// display modes for evt debugger vars
2151enum {
2157};
2158
2160 s32 i;
2161
2162 DebugEvtCount = 0;
2163
2164 for (i = 0; i < gScriptListCount; i++) {
2165 Evt* script = (*gCurrentScriptListPtr)[gScriptIndexList[i]];
2166
2167 if (script != NULL
2168 && script->id == gScriptIdList[i]
2169 && script->stateFlags != 0
2170 ) {
2172 DebugEvtCount++;
2173 }
2174 }
2175
2176 for (i = DebugEvtCount; i < MAX_SCRIPTS; i++) {
2177 DebugEvtList[i] = NULL;
2178 }
2179}
2180
2182 s32 i;
2183
2184 if (DebugEvtAttached == NULL) {
2185 return;
2186 }
2187
2188 for (i = 0; i < 16; i++) {
2189 DebugEvtPrevLVars[i] = DebugEvtAttached->varTable[i];
2190 }
2191 for (i = 0; i < 4; i++) {
2192 DebugEvtPrevTemps[i] = DebugEvtAttached->functionTemp[i];
2193 }
2194}
2195
2197 // if all lines can fit, do not scroll
2198 if (maxLine <= maxVisible) {
2199 return 0;
2200 }
2201
2202 // scroll up to show selectedLine with an extra line before, if available
2203 if (selectedLine < drawnLine + 1) {
2204 return MAX(0, selectedLine - 1);
2205 }
2206
2207 // last line selected, scroll to it without end padding
2208 if (selectedLine == maxLine - 1) {
2209 return selectedLine - (maxVisible - 1);
2210 }
2211
2212 //scroll down to show selectedLine with an extra line after
2213 if (selectedLine > drawnLine + (maxVisible - 2)) {
2214 return selectedLine - (maxVisible - 2);
2215 }
2216
2217 // no change
2218 return drawnLine;
2219}
2220
2222 s32 i;
2223
2226 const s32 BoxHeight = BoxOutsetY + 10 * RowHeight + BoxOutsetY;
2227 const s32 BoxWidth = 212;
2228
2229 // script list box
2231
2235
2238 s32 row = 0;
2239
2240 for (i = EvtListDrawPos; i < last; i++) {
2241 Evt* script = DebugEvtList[i];
2242
2243 s32 posY = EvtDebugInfoY + (1 + row) * RowHeight;
2244 s32 color = DefaultColor;
2245
2246 if (script->debugPaused) {
2247 color = MSG_PAL_RED;
2248 }
2249
2251 color = HighlightColor;
2252 }
2253
2254 dx_debug_draw_number(script->groupFlags, "%02X", color, 255, EvtDebugInfoX, posY);
2255 dx_debug_draw_number(script->ptrFirstLine, "%08X", color, 255, EvtDebugInfoX + 20, posY);
2256 dx_debug_draw_number((u8*)script->ptrCurLine - (u8*)script->ptrFirstLine, "%X", color, 255, EvtDebugInfoX + 80, posY);
2257
2258 row++;
2259 }
2260
2261 // animated down arrow
2262 if (DebugEvtCount > last) {
2263 char msgDownArrow[] = {
2265 };
2266 s32 posY = EvtDebugInfoY + (9) * RowHeight;
2267 draw_msg((s32)msgDownArrow, EvtDebugInfoX + 185, posY - round(2.0f * ArrowAnimOffset), 255, DefaultColor, 0);
2268 }
2269 // animated up arrow
2270 if (EvtListDrawPos > 0) {
2271 char msgUpArrow[] = {
2273 };
2274 s32 posY = EvtDebugInfoY + (1) * RowHeight;
2275 draw_msg((s32)msgUpArrow, EvtDebugInfoX + 185, posY + round(2.0f * ArrowAnimOffset), 255, DefaultColor, 0);
2276 }
2277
2278 // menu box (upper right)
2280
2281 for (i = 0; i < ARRAY_COUNT(EvtMainMenuOpts); i++) {
2282 s32 color = DefaultColor;
2283 if (EvtMainMenuPos == i) {
2285 }
2287 }
2288
2289 // count box (lower right)
2292}
2293
2295 s32 i;
2296
2297 debug_printf("count: %d", DebugEvtCount);
2298
2299 for (i = 0; i < DebugEvtCount; i++) {
2300 Evt* script = DebugEvtList[i];
2302 script->debugStep = DEBUG_EVT_STEP_NONE;
2303 }
2304}
2305
2307 s32 i;
2308
2309 for (i = 0; i < DebugEvtCount; i++) {
2310 Evt* script = DebugEvtList[i];
2312 script->debugStep = DEBUG_EVT_STEP_NONE;
2313 }
2314}
2315
2317 s32 count;
2318 s32 idx;
2319
2321
2323
2324 // handle input
2325 if (RELEASED(BUTTON_R)) {
2326 switch (EvtMainMenuPos) {
2331 break;
2334 break;
2337 break;
2338 }
2339 }
2340
2342}
2343
2345
2347
2348 if (DebugEvtCount > 1) {
2350 } else {
2351 EvtListCurPos = 0;
2352 }
2353
2354 // handle input
2355 if (RELEASED(BUTTON_L)) {
2357 } else if (RELEASED(BUTTON_R)) {
2358 if (DebugEvtCount > 0) {
2359 switch (EvtMainMenuPos) {
2364 DebugEvtDrawLine = 0;
2366 break;
2368 DebugEvtList[EvtListCurPos]->debugPaused = TRUE;
2370 break;
2372 DebugEvtList[EvtListCurPos]->debugPaused = FALSE;
2374 break;
2375 }
2376 }
2377 }
2378
2380}
2381
2383 s32 color = DefaultColor;
2384 if (EvtAttachedMenuPos == idx) {
2386 }
2388}
2389
2390void dx_debug_draw_var(s32 i, s32 number, char* fmt, s32 color, s32 alpha, s32 posX, s32 posY) {
2391 char fmtBuf[64];
2392 char buf[64] = {
2394 };
2395 sprintf(fmtBuf, fmt, i, number);
2397 draw_msg((s32)buf, posX, posY, alpha, color, 0);
2398}
2399
2400void dx_debug_draw_fvar(s32 i, f32 number, char* fmt, s32 color, s32 alpha, s32 posX, s32 posY) {
2401 char fmtBuf[64];
2402 char buf[64] = {
2404 };
2405 sprintf(fmtBuf, fmt, i, number);
2407 draw_msg((s32)buf, posX, posY, alpha, color, 0);
2408}
2409
2411 #define MAX_VALID_FLOAT 1e9
2412 s32 val;
2413 f32 fval;
2414 s32 i;
2415
2416 for (i = 0; i < 16; i++) {
2417 s32 posX = EvtDebugInfoX + (i / 8) * 106;
2418 s32 posY = EvtDebugInfoY + (i % 8) * RowHeight;
2419 s32 color = DebugEvtPrevLVars[i] == DebugEvtAttached->varTable[i] ? DefaultColor : HoverColor;
2420
2421 switch (EvtAttachedVarsMode) {
2423 dx_debug_draw_var(i, DebugEvtAttached->varTable[i], "LVar%X %08X", color, 255, posX, posY);
2424 break;
2426 dx_debug_draw_var(i, DebugEvtAttached->varTable[i], "LVar%X %d", color, 255, posX, posY);
2427 break;
2429 fval = DebugEvtAttached->varTableF[i];
2430 if (fabsf(fval) < MAX_VALID_FLOAT) {
2431 dx_debug_draw_fvar(i, fval, "LVar%X %f", color, 255, posX, posY);
2432 } else {
2433 dx_debug_draw_var(i, 0, "LVar%X ---", color, 255, posX, posY);
2434 }
2435 break;
2437 val = DebugEvtAttached->varTable[i];
2439 dx_debug_draw_fvar(i, EVT_FIXED_TO_FLOAT(val), "LVar%X %f", color, 255, posX, posY);
2440 } else {
2441 dx_debug_draw_var(i, 0, "LVar%X ---", color, 255, posX, posY);
2442 }
2443 break;
2444 }
2445 }
2446
2447 for (i = 0; i < 4; i++) {
2448 s32 posX = EvtDebugInfoX + (i / 2) * 106;
2449 s32 posY = EvtDebugInfoY + (8 + (i % 2)) * RowHeight;
2450 s32 color = DebugEvtPrevTemps[i] == DebugEvtAttached->functionTemp[i] ? DefaultColor : HoverColor;
2451
2452 switch (EvtAttachedVarsMode) {
2454 dx_debug_draw_var(i, DebugEvtAttached->functionTemp[i], "Temp%X %08X", color, 255, posX, posY);
2455 break;
2457 dx_debug_draw_var(i, DebugEvtAttached->functionTemp[i], "Temp%X %d", color, 255, posX, posY);
2458 break;
2460 fval = DebugEvtAttached->functionTempF[i];
2461 if (fabsf(fval) < MAX_VALID_FLOAT) {
2462 dx_debug_draw_fvar(i, fval, "Temp%X %f", color, 255, posX, posY);
2463 } else {
2464 dx_debug_draw_var(i, 0, "Temp%X ---", color, 255, posX, posY);
2465 }
2466 dx_debug_draw_fvar(i, DebugEvtAttached->functionTempF[i], "Temp%X %f", color, 255, posX, posY);
2467 break;
2469 val = DebugEvtAttached->functionTemp[i];
2471 dx_debug_draw_fvar(i, EVT_FIXED_TO_FLOAT(val), "Temp%X %f", color, 255, posX, posY);
2472 } else {
2473 dx_debug_draw_var(i, 0, "Temp%X ---", color, 255, posX, posY);
2474 }
2475 break;
2476 }
2477 }
2478}
2479
2480void dx_debug_evt_draw_arg(u32 value, b32 asDecimal, s32 color, s32 posX, s32 posY) {
2481 if (value >= LVar0 && value <= LVarF) {
2482 dx_debug_draw_number(value - LVar0, "LVar%X", color, 255, posX, posY);
2483 } else if (asDecimal) {
2484 dx_debug_draw_number(value, "%d", color, 255, posX, posY);
2485 } else {
2486 dx_debug_draw_number(value, "%08X", color, 255, posX, posY);
2487 }
2488}
2489
2491 Bytecode* pos;
2492 s32 i, j;
2493 s32 op, nargs;
2494
2495 if (DebugEvtAttached == NULL) {
2496 return;
2497 }
2498
2499 pos = DebugEvtAttached->ptrFirstLine;
2501
2502 // find offsets for all lines in script
2503 while (TRUE) {
2505
2506 if (pos == DebugEvtAttached->ptrCurLine) {
2508 }
2509
2510 op = *pos++;
2511 nargs = *pos++;
2512 pos += nargs;
2513
2515
2517 break;
2518 }
2519 }
2520
2523 s32 row = 0;
2524
2525 for (i = DebugEvtDrawLine; i < last; i++) {
2526 pos = DebugEvtAttached->ptrFirstLine + DebugEvtLineOffsets[i];
2527 op = *pos++;
2528 nargs = *pos++;
2529 s32* args = pos;
2530 pos += nargs;
2531
2532 s32 posY = EvtDebugInfoY + row * RowHeight;
2533 s32 color = (i == DebugEvtCurLine) ? HoverColor : DefaultColor;
2534
2535 dx_debug_draw_number(i, "%d", color, 255, EvtDebugInfoX, posY);
2536
2537 if (op > 0 && op < ARRAY_COUNT(DebugOps)) {
2538 dx_debug_draw_ascii(DebugOps[op].text, color, EvtDebugInfoX + 15, posY);
2539 } else {
2540 dx_debug_draw_number(op, "%08X", color, 255, EvtDebugInfoX + 15, posY);
2541 }
2542
2543 switch (op) {
2544 case EVT_OP_LABEL:
2545 case EVT_OP_GOTO:
2546 case EVT_OP_LOOP:
2547 case EVT_OP_WAIT_FRAMES:
2548 case EVT_OP_WAIT_SECS:
2549 dx_debug_evt_draw_arg(args[0], TRUE, color, EvtDebugInfoX + 15 + 55, posY);
2550 break;
2551 default:
2552 for (j = 0; j < MIN(2, nargs); j++) {
2553 dx_debug_evt_draw_arg(args[j], FALSE, color, EvtDebugInfoX + 15 + 55 * (j + 1), posY);
2554 }
2555 break;
2556 }
2557
2558 if (nargs > 2) {
2559 dx_debug_draw_ascii("...", color, EvtDebugInfoX + 15 + 55 * 3, posY);
2560 }
2561
2562 row++;
2563 }
2564}
2565
2567 s32 posY;
2568
2569 if (DebugEvtAttached == NULL) {
2571 return;
2572 }
2573
2574 // saves worrying about null checks while drawing on the frame we detach the evt
2576
2579
2580 // handle input
2581 if (RELEASED(BUTTON_L)) {
2583 } else if (RELEASED(BUTTON_R)) {
2584 switch (EvtAttachedMenuPos) {
2586 detachAfter = TRUE;
2587 break;
2589 DebugEvtAttached->debugPaused = !DebugEvtAttached->debugPaused;
2590 break;
2594 break;
2598 break;
2603 }
2604 break;
2605 }
2606 }
2607
2608 // draw menu (upper right)
2610
2611 dx_debug_evt_draw_menu_line(0, "Detach");
2612 if (DebugEvtAttached->debugPaused) {
2613 dx_debug_evt_draw_menu_line(1, "Resume");
2614 } else {
2615 dx_debug_evt_draw_menu_line(1, "Break");
2616 }
2617 dx_debug_evt_draw_menu_line(2, "Step Once");
2618 dx_debug_evt_draw_menu_line(3, "Step Over");
2619 switch (EvtAttachedVarsMode) {
2621 dx_debug_evt_draw_menu_line(4, "Vars: Int");
2622 break;
2624 dx_debug_evt_draw_menu_line(4, "Vars: Fixed");
2625 break;
2627 dx_debug_evt_draw_menu_line(4, "Vars: Float");
2628 break;
2630 dx_debug_evt_draw_menu_line(4, "Vars: Raw");
2631 break;
2632 }
2633
2634 // header box
2635 posY = EvtDebugInfoY - 4;
2636 posY -= RowHeight + 3; // move up one line and include a small gap
2638
2639 dx_debug_draw_number(DebugEvtAttached->ptrFirstLine, "%08X", DefaultColor, 255, EvtDebugInfoX + 40, posY);
2640
2641 // evt info box
2643
2644 switch (EvtAttachedDispMode) {
2645 case 0:
2648 break;
2649 case 1:
2652 break;
2653 }
2654
2655 if (!DebugEvtAttached->debugPaused) {
2657 }
2658
2659 if (detachAfter) {
2662 }
2663}
2664
2666 if (DebugEvtAttached != NULL && (DebugEvtAttached == evt)) {
2668
2671 }
2672 }
2673}
2674
2675void dx_debug_evt_reset() {
2676 if (DebugEvtAttached != NULL) {
2678 }
2679
2680 EvtListCurPos = 0;
2681 EvtListDrawPos = 0;
2682}
2683
2684// ----------------------------------------------------------------------------
2685// banner info
2686
2688 char fmtBuf[128];
2689 s32 effect;
2690
2692 sprintf(fmtBuf, "Map: %7s (%lX)", LastMapName, LastMapEntry);
2694
2696
2698
2701
2704
2707
2709 dx_debug_draw_ascii("(GOD MODE)", MSG_PAL_YELLOW, 151, BottomRowY);
2710 }
2711 } else if (gGameStatus.context == CONTEXT_BATTLE) {
2712 s32 areaID = (LastBattleID >> 24) & 0xFF;
2713 s32 battleID = (LastBattleID >> 16) & 0xFF;
2714 s32 stageID = LastBattleID & 0xFFFF;
2715
2716 sprintf(fmtBuf, "Battle: %02lX-%02lX (%lX)", areaID, battleID, stageID);
2718
2719 sprintf(fmtBuf, "Stage: %-15s", LastStageName);
2721
2723 dx_debug_draw_ascii("(GOD MODE)", MSG_PAL_YELLOW, 128, BottomRowY);
2724 }
2725 }
2726}
2727
2728// ----------------------------------------------------------------------------
2729// console printing
2730
2731#define DEBUG_CONSOLE_DEFAULT_TIMELEFT 60
2732#define DEBUG_CONSOLE_MSG_BUF_SIZE 85
2733
2734typedef struct DebugConsoleLine {
2735 u32 hash;
2736 s32 timeLeft;
2739
2748
2758};
2759
2760u32 dx_debug_hash_location(const char* filename, s32 line) {
2761 u32 hash = 5381;
2762 s32 c;
2763
2764 while ((c = *filename++)) {
2765 hash = ((hash << 5) + hash) + c;
2766 }
2767
2768 hash = ((hash << 5) + hash) + line;
2769
2770 return hash;
2771}
2772
2773static char *proutSprintf(char *dst, const char *src, size_t count) {
2774 return (char *)memcpy((u8 *)dst, (u8 *)src, count) + count;
2775}
2776
2777void dx_hashed_debug_printf(const char* filename, s32 line, const char* fmt, ...) {
2778 char fmtBuf[128];
2779 va_list args;
2780 va_start(args, fmt);
2781 s32 len = _Printf(&proutSprintf, fmtBuf, fmt, args);
2782 if (len >= 0) {
2783 fmtBuf[len] = 0;
2784 }
2785 ASSERT(len < 85);
2786
2787 u32 hash = dx_debug_hash_location(filename, line);
2788 s32 matchedLine = -1;
2789 s32 idx;
2790
2791 // find a line with the matching hash
2792 for (idx = 0; idx < ARRAY_COUNT(DebugConsole); idx++) {
2793 if (DebugConsole[idx]->hash == hash) {
2794 matchedLine = idx;
2795 break;
2796 }
2797 }
2798
2799 // find the oldest line
2800 if (matchedLine == -1) {
2802
2803 for (idx = 0; idx < ARRAY_COUNT(DebugConsole); idx++) {
2804 if (DebugConsole[idx]->timeLeft == 0) {
2805 matchedLine = idx;
2806 break;
2807 }
2808 if (DebugConsole[idx]->timeLeft < minTimeLeft) {
2809 minTimeLeft = DebugConsole[idx]->timeLeft;
2810 matchedLine = idx;
2811 }
2812 }
2813 }
2814
2815 // update the ConsoleLine entry
2816 if (matchedLine != -1) {
2819 DebugConsole[matchedLine]->buf[2] = 12;
2820 DebugConsole[matchedLine]->buf[3] = 12;
2821
2823
2824 DebugConsole[matchedLine]->hash = hash;
2826 }
2827}
2828
2829API_CALLABLE(_dxDebugIntPrintf) {
2830 Bytecode* args = script->ptrReadPos;
2831 s32 i[8];
2832 s32 nargs = 0;
2833 s32 idx;
2834
2835 char* filename = (char*)*args++;
2836 s32 line = *args++;
2837 char* fmt = (char*)*args++;
2838
2839 for (idx = 0; idx < 8; idx++) {
2840 s32 var = *args++;
2841 if (var == 0) {
2842 break;
2843 }
2845 nargs++;
2846 }
2847
2848 switch (nargs) {
2849 case 0: dx_hashed_debug_printf(filename, line, fmt); break;
2850 case 1: dx_hashed_debug_printf(filename, line, fmt, i[0]); break;
2851 case 2: dx_hashed_debug_printf(filename, line, fmt, i[0], i[1]); break;
2852 case 3: dx_hashed_debug_printf(filename, line, fmt, i[0], i[1], i[2]); break;
2853 case 4: dx_hashed_debug_printf(filename, line, fmt, i[0], i[1], i[2], i[3]); break;
2854 case 5: dx_hashed_debug_printf(filename, line, fmt, i[0], i[1], i[2], i[3], i[4]); break;
2855 case 6: dx_hashed_debug_printf(filename, line, fmt, i[0], i[1], i[2], i[3], i[4], i[5]); break;
2856 case 7: dx_hashed_debug_printf(filename, line, fmt, i[0], i[1], i[2], i[3], i[4], i[5], i[6]); break;
2857 }
2858
2859 return ApiStatus_DONE2;
2860}
2861
2862API_CALLABLE(_dxDebugFloatPrintf) {
2863 Bytecode* args = script->ptrReadPos;
2864 f32 f[8];
2865 s32 nargs = 0;
2866 s32 idx;
2867
2868 char* filename = (char*)*args++;
2869 s32 line = *args++;
2870 char* fmt = (char*)*args++;
2871
2872 for (idx = 0; idx < 8; idx++) {
2873 s32 var = *args++;
2874 if (var == 0) {
2875 break;
2876 }
2878 nargs++;
2879 }
2880
2881 switch (nargs) {
2882 case 0: dx_hashed_debug_printf(filename, line, fmt); break;
2883 case 1: dx_hashed_debug_printf(filename, line, fmt, f[0]); break;
2884 case 2: dx_hashed_debug_printf(filename, line, fmt, f[0], f[1]); break;
2885 case 3: dx_hashed_debug_printf(filename, line, fmt, f[0], f[1], f[2]); break;
2886 case 4: dx_hashed_debug_printf(filename, line, fmt, f[0], f[1], f[2], f[3]); break;
2887 case 5: dx_hashed_debug_printf(filename, line, fmt, f[0], f[1], f[2], f[3], f[4]); break;
2888 case 6: dx_hashed_debug_printf(filename, line, fmt, f[0], f[1], f[2], f[3], f[4], f[5]); break;
2889 case 7: dx_hashed_debug_printf(filename, line, fmt, f[0], f[1], f[2], f[3], f[4], f[5], f[6]); break;
2890 }
2891
2892 return ApiStatus_DONE2;
2893}
2894
2895void dx_debug_console_main() {
2897 s32 idx;
2898
2899#define LESS(i, j) DebugConsole[i]->timeLeft > DebugConsole[j]->timeLeft
2900#define SWAP(i, j) temp = DebugConsole[i], DebugConsole[i] = DebugConsole[j], DebugConsole[j] = temp
2902#undef LESS
2903#undef SWAP
2904
2905 for (idx = 0; idx < ARRAY_COUNT(DebugConsole); idx++) {
2906 s32 timeLeft = DebugConsole[idx]->timeLeft;
2907
2908 if (timeLeft > 0) {
2909 s32 alpha = 254;
2910 if (timeLeft < 20) {
2911 alpha = round(254 * (timeLeft / 20.0f));
2912 }
2913
2914 draw_msg((s32)DebugConsole[idx]->buf, 32, 200 - 15 * idx, alpha, DefaultColor, 0);
2915 DebugConsole[idx]->timeLeft--;
2916 }
2917 }
2918}
2919
2920#endif
PartnerPopupProperties gPartnerPopupProperties[]
Definition 5B320.c:331
BSS s32 PopupMenu_SelectedIndex
BattleArea gBattleAreas[]
When updating this, make sure you also update:
Definition battle.cpp:68
s16 badges[128]
b8 debugPaused
PartnerData partners[12]
Evt * ScriptList[128]
Collider * colliderList
s32 b32
s8 b8
s16 keyItems[32]
s16 invItems[10]
#define debug_printf(fmt, args...)
Definition debug_menu.h:96
Vec3s pos
Definition demo_api.c:17
#define transform_point
#define cos_deg
#define draw_msg
#define draw_box
#define ASSERT(condition)
@ WINDOW_STYLE_4
Definition enums.h:5959
@ WINDOW_STYLE_20
Definition enums.h:5975
@ DRAW_MSG_STYLE_RAINBOW
Definition enums.h:4972
@ TRANSITION_STANDARD
Definition enums.h:2348
@ BUTTON_D_RIGHT
Definition enums.h:2769
@ BUTTON_D_DOWN
Definition enums.h:2771
@ BUTTON_D_UP
Definition enums.h:2772
@ BUTTON_R
Definition enums.h:2767
@ BUTTON_L
Definition enums.h:2768
@ BUTTON_D_LEFT
Definition enums.h:2770
@ MSG_READ_FUNC_COLOR
Definition enums.h:5672
@ MSG_READ_FUNC_RESTORE_COLOR
Definition enums.h:5704
@ MSG_READ_FUNC_SAVE_COLOR
Definition enums.h:5703
@ MSG_READ_FUNC_SPACING
Definition enums.h:5678
@ MSG_READ_FUNC_SIZE
Definition enums.h:5680
@ DEBUG_CONTACT_CANT_TOUCH
Definition enums.h:3867
@ DEBUG_CONTACT_NONE
Definition enums.h:3866
@ MSG_PAL_GREEN
Definition enums.h:4993
@ MSG_PAL_BLUE
Definition enums.h:4992
@ MSG_PAL_YELLOW
Definition enums.h:4995
@ MSG_PAL_PURPLE
Definition enums.h:4998
@ MSG_PAL_WHITE
Definition enums.h:4990
@ MSG_PAL_RED
Definition enums.h:4997
@ AMBIENT_SILENCE
Definition enums.h:1913
@ ENCOUNTER_TRIGGER_NONE
Definition enums.h:268
@ COLLIDER_FLAG_IGNORE_PLAYER
Definition enums.h:4281
@ ENCOUNTER_SUBSTATE_PRE_BATTLE_INIT
Definition enums.h:5898
@ CONTEXT_BATTLE
Definition enums.h:3563
@ CONTEXT_WORLD
Definition enums.h:3562
@ SOUND_MENU_BADGE_EQUIP
Definition enums.h:555
@ SOUND_MENU_SHOW_CHOICE
Definition enums.h:557
@ SOUND_STAR_PIECE_BOUNCE
Definition enums.h:932
@ SOUND_UNUSED_STAR_SPIRIT_APPEARS
Definition enums.h:634
@ SOUND_STAR_POINT_PICKUP
Definition enums.h:929
@ SOUND_COIN_PICKUP
Definition enums.h:925
@ ENCOUNTER_STATE_PRE_BATTLE
Definition enums.h:5882
@ FIRST_STRIKE_NONE
Definition enums.h:3492
@ MSG_CHAR_LOWER_T
Definition enums.h:5525
@ MSG_CHAR_LOWER_M
Definition enums.h:5518
@ MSG_CHAR_DOWN
Definition enums.h:5588
@ MSG_CHAR_LOWER_Y
Definition enums.h:5530
@ MSG_CHAR_CIRCLE
Definition enums.h:5591
@ MSG_CHAR_LOWER_E
Definition enums.h:5510
@ MSG_CHAR_LOWER_P
Definition enums.h:5521
@ MSG_CHAR_RIGHT
Definition enums.h:5590
@ MSG_CHAR_READ_END
Definition enums.h:5641
@ MSG_CHAR_UP
Definition enums.h:5587
@ MSG_CHAR_READ_FUNCTION
Definition enums.h:5643
@ MSG_CHAR_LEFT
Definition enums.h:5589
@ EVT_OP_LOOP
Args: number of repeats (0 = infinite)
Definition evt.h:15
@ EVT_OP_EXEC_GET_TID
Args: EvtScript*, container.
Definition evt.h:79
@ EVT_OP_CASE_DEFAULT
Definition evt.h:38
@ EVT_OP_END_IF
Definition evt.h:29
@ EVT_OP_MOD
Args: container, expression to divide by.
Definition evt.h:53
@ EVT_OP_DEBUG_BREAKPOINT
Definition evt.h:105
@ EVT_OP_FBUF_READ2
Args: container.
Definition evt.h:66
@ EVT_OP_94
Definition evt.h:104
@ EVT_OP_93
Definition evt.h:103
@ EVT_OP_UNBIND
Unbinds any triggers bound to this script.
Definition evt.h:82
@ EVT_OP_ADDF
Args: container, expression to increment by.
Definition evt.h:54
@ EVT_OP_FBUF_READ3
Args: container, container.
Definition evt.h:67
@ EVT_OP_SET_PRIORITY
Args: priority.
Definition evt.h:85
@ EVT_OP_DIVF
Args: container, expression to divide by.
Definition evt.h:57
@ EVT_OP_CASE_FLAG
Args: expression to test for.
Definition evt.h:41
@ EVT_OP_ELSE
Definition evt.h:28
@ EVT_OP_DEBUG_LOG
Definition evt.h:100
@ EVT_OP_MULF
Args: container, expression to multiply by.
Definition evt.h:56
@ EVT_OP_SUSPEND_OTHERS
Args: group.
Definition evt.h:91
@ EVT_OP_SUSPEND_THREAD
Args: ScriptID.
Definition evt.h:93
@ EVT_OP_GOTO
Args: index.
Definition evt.h:14
@ EVT_OP_EXEC
Args: EvtScript*.
Definition evt.h:78
@ EVT_OP_USE_ARRAY
Args: *s32.
Definition evt.h:70
@ EVT_OP_MUL
Args: container, expression to multiply by.
Definition evt.h:51
@ EVT_OP_END_CASE_GROUP
Ends the case block of EVT_OP_CASE_OR_EQ condition(s).
Definition evt.h:42
@ EVT_OP_92
Definition evt.h:102
@ EVT_OP_IF_LE
Args: a, b.
Definition evt.h:24
@ EVT_OP_IF_FLAG
Args: a, b.
Definition evt.h:26
@ EVT_OP_WAIT_SECS
Definition evt.h:19
@ EVT_OP_END
Definition evt.h:11
@ EVT_OP_RETURN
Definition evt.h:12
@ EVT_OP_SET
Args: container, expression.
Definition evt.h:46
@ EVT_OP_IF_NE
Args: a, b.
Definition evt.h:21
@ EVT_OP_CASE_EQ
Args: expression to test for.
Definition evt.h:32
@ EVT_OP_BITWISE_OR_CONST
Args: container, value to bitwise OR with.
Definition evt.h:76
@ EVT_OP_BUF_READ1
Definition evt.h:59
@ EVT_OP_USE_FBUF
Identical to USE_BUFFER. Args: f32*.
Definition evt.h:64
@ EVT_OP_SETF
Args: container, expression.
Definition evt.h:48
@ EVT_OP_CHILD_THREAD
Parallel threads are killed as soon as the parent script returns.
Definition evt.h:98
@ EVT_OP_CASE_GE
Args: expression to test for.
Definition evt.h:37
@ EVT_OP_IF_GT
Args: a, b.
Definition evt.h:23
@ EVT_OP_CASE_OR_EQ
Args: expression to test for.
Definition evt.h:39
@ EVT_OP_END_CHILD_THREAD
Definition evt.h:99
@ EVT_OP_END_SWITCH
Definition evt.h:45
@ EVT_OP_DEBUG_PRINT_VAR
Args: expression.
Definition evt.h:101
@ EVT_OP_BUF_READ3
Args: container, container.
Definition evt.h:61
@ EVT_OP_DIV
Integer division. Args: container, expression to divide by.
Definition evt.h:52
@ EVT_OP_EXEC_WAIT
Spawns a script and waits for it to return before continuing. Args: EvtScript*.
Definition evt.h:80
@ EVT_OP_END_LOOP
Definition evt.h:16
@ EVT_OP_BUF_READ4
Args: container, container, container.
Definition evt.h:62
@ EVT_OP_ADD
Args: container, expression to increment by.
Definition evt.h:49
@ EVT_OP_FBUF_READ4
Args: container, container, container.
Definition evt.h:68
@ EVT_OP_BREAK_SWITCH
Definition evt.h:44
@ EVT_OP_SET_TIMESCALE
Args: timescale.
Definition evt.h:86
@ EVT_OP_USE_BUF
Args: s32*.
Definition evt.h:58
@ EVT_OP_BREAK_LOOP
Definition evt.h:17
@ EVT_OP_USE_FLAGS
Args: *s32.
Definition evt.h:71
@ EVT_OP_CASE_RANGE
Args: from, to.
Definition evt.h:43
@ EVT_OP_BITWISE_AND_CONST
Args: container, value to bitwise AND with.
Definition evt.h:74
@ EVT_OP_FBUF_READ1
Definition evt.h:65
@ EVT_OP_SUBF
Args: container, expression to decrement by.
Definition evt.h:55
@ EVT_OP_WAIT_FRAMES
Definition evt.h:18
@ EVT_OP_JUMP
Args: EvtScript*.
Definition evt.h:84
@ EVT_OP_THREAD
Definition evt.h:96
@ EVT_OP_CASE_AND_EQ
Args: expression to test for.
Definition evt.h:40
@ EVT_OP_SWITCH
Args: expression to test against.
Definition evt.h:30
@ EVT_OP_CASE_LE
Args: expression to test for.
Definition evt.h:36
@ EVT_OP_SUB
Args: container, expression to decrement by.
Definition evt.h:50
@ EVT_OP_IF_GE
Args: a, b.
Definition evt.h:25
@ EVT_OP_CALL
Args: *function, ...
Definition evt.h:77
@ EVT_OP_IF_NOT_FLAG
Args: a, b.
Definition evt.h:27
@ EVT_OP_IS_THREAD_RUNNING
Args: ScriptID, container.
Definition evt.h:95
@ EVT_OP_IF_LT
Args: a, b.
Definition evt.h:22
@ EVT_OP_SWITCH_CONST
Args: value to test against.
Definition evt.h:31
@ EVT_OP_CASE_NE
Args: expression to test for.
Definition evt.h:33
@ EVT_OP_SET_CONST
Args: container, value.
Definition evt.h:47
@ EVT_OP_KILL_THREAD
Args: ScriptID.
Definition evt.h:83
@ EVT_OP_LABEL
Args: index.
Definition evt.h:13
@ EVT_OP_RESUME_OTHERS
Args: group.
Definition evt.h:92
@ EVT_OP_RESUME_THREAD
Args: ScriptID.
Definition evt.h:94
@ EVT_OP_BUF_READ2
Args: container.
Definition evt.h:60
@ EVT_OP_END_THREAD
Definition evt.h:97
@ EVT_OP_RESUME_GROUP
Args: group.
Definition evt.h:90
@ EVT_OP_BIND_TRIGGER
Args: EvtScript*, trigger flags, s32 target, 1, Trigger*.
Definition evt.h:81
@ EVT_OP_BITWISE_AND
Args: container, expression to bitwise AND with.
Definition evt.h:73
@ EVT_OP_CASE_GT
Args: expression to test for.
Definition evt.h:35
@ EVT_OP_BITWISE_OR
Args: container, expression to bitwise OR with.
Definition evt.h:75
@ EVT_OP_SET_GROUP
Args: group.
Definition evt.h:87
@ EVT_OP_BIND_PADLOCK
Args: EvtScript*, trigger flags, s32 target, ItemList*, 0, 1.
Definition evt.h:88
@ EVT_OP_SUSPEND_GROUP
Args: group.
Definition evt.h:89
@ EVT_OP_CASE_LT
Args: expression to test for.
Definition evt.h:34
@ EVT_OP_MALLOC_ARRAY
Allocates a new array. Args: length, s32*.
Definition evt.h:72
@ EVT_OP_BUF_PEEK
Args: container, container, container, container.
Definition evt.h:63
@ EVT_OP_IF_EQ
Args: a, b.
Definition evt.h:20
@ EVT_OP_FBUF_PEEK
Args: container, container, container, container.
Definition evt.h:69
#define ApiStatus_DONE2
Definition evt.h:119
s32 Bytecode
Definition evt.h:7
b32 fio_load_game(s32 saveSlot)
Definition fio.c:167
void fio_save_game(s32 saveSlot)
Definition fio.c:184
s32 evt_get_variable(Evt *script, Bytecode var)
Definition evt.c:1725
s32 play_ambient_sounds(s32 fadeInTime, s32 fadeOutTime)
Definition ambience.c:76
f32 fabsf(f32 f)
f64 fabs(f64 f)
void partner_disable_input(void)
Definition partners.c:2489
void set_map_transition_effect(ScreenTransition)
s32 round(f32)
Definition 43F0.c:570
s32 disable_player_input(void)
Definition 77480.c:989
void open_status_bar_quickly(void)
Definition inventory.c:1440
s32 evt_set_variable(Evt *script, Bytecode var, s32 value)
Definition evt.c:1882
int _Printf(outfun prout, char *arg, const char *fmt, va_list args)
f32 evt_get_float_variable(Evt *script, Bytecode var)
Definition evt.c:1965
void set_game_mode(s32 modeID)
Definition game_modes.c:127
@ GAME_MODE_ENTER_WORLD
Definition game_modes.h:11
@ GAME_MODE_CHANGE_MAP
Definition game_modes.h:13
s32 remove_item(s32 itemID)
Remove first instance of itemID found in player inventory.
Definition inventory.c:203
b32 has_item(s32 itemID)
Check whether player has itemID in their inventory.
Definition inventory.c:342
s32 add_item(s32 itemID)
Add itemID to player inventory and return inventory slot in which it was placed.
Definition inventory.c:151
#define SWAP(i, j)
#define LESS(i, j)
void dma_load_msg(u32 msgID, void *dest)
Definition msg.c:1402
#define NO_DROPS
Definition npc.h:23
s16 npcID
Definition npc.h:300
s16 encounterID
Definition npc.h:355
EncounterStatus gCurrentEncounter
Definition encounter.c:175
Definition npc.h:294
void sfx_stop_sound(s32 soundID)
void sfx_play_sound(s32 soundID)
#define QSORT(Q_N, Q_LESS, Q_SWAP)
Definition qsort.h:161
@ GB_StoryProgress
#define SCREEN_WIDTH
Definition macros.h:109
#define LVarF
Definition macros.h:164
#define MAX_SCRIPTS
Definition macros.h:90
#define EVT_FIXED_END
Definition macros.h:46
#define ARRAY_COUNT(arr)
Definition macros.h:40
#define EVT_FIXED_CUTOFF
Definition macros.h:44
#define SCREEN_HEIGHT
Definition macros.h:110
#define EVT_FIXED_TO_FLOAT(x)
Progammatically converts Float --> f32.
Definition macros.h:55
#define PANIC_MSG(msg, args...)
Definition macros.h:56
#define SP_PER_BAR
Definition macros.h:102
#define LVar0
Definition macros.h:149
char * id
Definition map.h:42
char * id
"area_xxx"
Definition map.h:57
s32 mapCount
Definition map.h:55
AreaConfig gAreas[29]
Zero-terminated.
Definition world.c:868
MapConfig * maps
Definition map.h:56
BSS s32 gScriptListCount
Definition script_list.c:19
BSS s32 gScriptIdList[MAX_SCRIPTS]
Definition script_list.c:18
BSS s32 gScriptIndexList[MAX_SCRIPTS]
Definition script_list.c:17
BSS ScriptList * gCurrentScriptListPtr
Definition script_list.c:16
u8 dx_ascii_char_to_msg(char in)
Definition utils.c:3
u8 * dx_string_to_msg(u8 *msg, const char *str)
Definition utils.c:16
ItemData gItemTable[]
PlayerStatus * gPlayerStatusPtr
GameStatus gGameStatus
Definition main_loop.c:20
CollisionStatus gCollisionStatus
Definition 7BB60.c:5
GameStatus * gGameStatusPtr
Definition main_loop.c:31
Camera gCameras[4]
Definition cam_main.c:16
Gfx * gMainGfxPos
Definition cam_main.c:14
PlayerData gPlayerData
Definition 77480.c:39
PlayerStatus gPlayerStatus
Definition 77480.c:38
s32 gCurrentCameraID
Definition cam_math.c:5
CollisionData gCollisionData
Definition collision.c:35
s32 gEncounterState
Definition encounter.c:173
b32 EncounterStateChanged
Definition encounter.c:23
s32 gEncounterSubState
Definition encounter.c:174