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, nullptr, 0, nullptr, SCREEN_WIDTH, SCREEN_HEIGHT, nullptr);
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 ALIGNED(8) 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", nullptr, DBM_QUICK_SAVE },
437 { "Map Select", nullptr, DBM_SELECT_AREA },
438 { "Battle Select", nullptr, DBM_SELECT_BATTLE },
439 { "Set Story Byte", nullptr, DBM_SET_STORY },
440 { "Sound Player", nullptr, DBM_SOUND_PLAYER },
441 { "Edit Partners", nullptr, DBM_EDIT_PARTNERS },
442 { "Edit Inventory", nullptr, DBM_EDIT_INVENTORY },
443// { "Edit Memory", nullptr, DBM_EDIT_MEMORY },
444 { "View Collision", nullptr, DBM_VIEW_COLLISION },
445 { "Cheats", nullptr, 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
610 if (DebugMainMenu[MainMenuPos].onSelect != nullptr) {
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", nullptr, 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", nullptr, DBM_SELECT_SOUND },
1055 { "Stop Sound", nullptr, 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 }
1147 }
1149 }
1150
1151 // draw
1152 dx_debug_draw_box(SubBoxPosX, SubBoxPosY, 120, 14 * 11 + 8, WINDOW_STYLE_20, 192);
1153
1154 for (idx = 1; idx < ARRAY_COUNT(gPlayerData.partners); idx++) {
1157 s32 posY = SubmenuPosY + (idx - 1) * 14;
1158 s32 level = DebugPartnerLevels[idx];
1159 s32 alpha = (isSelected || level >= 0) ? 254 : 120;
1160
1161 if (level < 0) {
1162 dx_debug_draw_number(level, "%d", color, alpha, SubmenuPosX - 3, posY);
1163 } else {
1164 dx_debug_draw_number(level, "%d", color, alpha, SubmenuPosX + 3, posY);
1165 }
1166
1167 dx_debug_draw_msg(gPartnerPopupProperties[idx].nameMsg, color, alpha, SubmenuPosX + 15, posY);
1168
1169 if (level == 1) {
1171 draw_msg((s32)msg, SubmenuPosX + 82, posY - 1, 255, MSG_PAL_BLUE, 0);
1172 } else if (level == 2) {
1174 draw_msg((s32)msg, SubmenuPosX + 82, posY - 1, 255, MSG_PAL_BLUE, 0);
1175 }
1176 }
1177}
1178
1179// ----------------------------------------------------------------------------
1180// edit inventory
1181
1183 { "Items", nullptr, DBM_INV_EDIT_ITEMS },
1184 { "Badges", nullptr, DBM_INV_EDIT_BADGES },
1185 { "Key Items", nullptr, DBM_INV_EDIT_KEYS },
1186 { "Equipment", nullptr, DBM_INV_EDIT_GEAR },
1187 { "Stats", nullptr, DBM_INV_EDIT_STATS },
1188 { "Coins", nullptr, DBM_INV_EDIT_COINS },
1189 { "Star Points", nullptr, DBM_INV_EDIT_STAR_POINTS },
1190 { "Star Pieces", nullptr, DBM_INV_EDIT_STAR_PIECES },
1191};
1193
1195 s32 idx;
1196
1197 // handle input
1199 if (RELEASED(BUTTON_L)) {
1201 } else if (RELEASED(BUTTON_R)) {
1204 } else {
1206 }
1207 }
1208
1209 // draw
1211
1212 for (idx = 0; idx < ARRAY_COUNT(DebugInventoryMenu); idx++) {
1215 }
1216}
1217
1218b32 DebugEditingItem = false;
1219
1220#define _MAX_INV_SIZE(a,b,c) MAX(MAX(ARRAY_COUNT(a), ARRAY_COUNT(b)), ARRAY_COUNT(c))
1222
1223typedef struct DebugItemsMenu {
1224 s16 pos;
1225 s16 startPos;
1226 s8 col;
1228
1230 .pos = 0,
1231 .startPos = 0,
1232 .col = 0,
1233};
1234
1236 .pos = 0,
1237 .startPos = 0,
1238 .col = 0,
1239};
1240
1242 .pos = 0,
1243 .startPos = 0,
1244 .col = 0,
1245};
1246
1247void dx_debug_set_item_id(s32 idx, s16 itemID) {
1248 s32 j;
1249
1250 for (j = 2; j >= 0; j--) {
1251 DebugItemDigits[idx][j] = (itemID & 0xF);
1252 itemID >>= 4;
1253 }
1254}
1255
1257 s32 j;
1258 s16 val = 0;
1259
1260 for (j = 0; j < 3; j++) {
1261 val <<= 4;
1262 val |= (DebugItemDigits[idx][j] & 0xF);
1263 }
1264 return val;
1265}
1266
1269 s16* invItems;
1270 s32 invSize;
1271 s32 i, j;
1272
1273 switch (DebugMenuState) {
1274 case DBM_INV_EDIT_ITEMS:
1275 menu = &DebugItems;
1276 invItems = gPlayerData.invItems;
1278 break;
1279 case DBM_INV_EDIT_KEYS:
1280 menu = &DebugKeys;
1281 invItems = gPlayerData.keyItems;
1283 break;
1285 menu = &DebugBadges;
1286 invItems = gPlayerData.badges;
1288 break;
1289 default:
1290 PANIC_MSG("invalid debug menu state");
1291 }
1292
1293 if (DebugStateChanged) {
1294 for (i = 0; i < invSize; i++) {
1295 dx_debug_set_item_id(i, invItems[i]);
1296 }
1297 }
1298
1299 if (RELEASED(BUTTON_L)) {
1300 if (DebugEditingItem) {
1301 DebugEditingItem = false;
1302 } else {
1304 }
1305 } else if (RELEASED(BUTTON_R)) {
1306 if (!DebugEditingItem) {
1307 DebugEditingItem = true;
1308 } else {
1309 for (i = 0; i < invSize; i++) {
1310 invItems[i] = dx_debug_get_item_id(i);
1311 }
1313 }
1314 }
1315
1316 if (DebugEditingItem) {
1317 s32 digit;
1318 menu->col = dx_debug_menu_nav_1D_horizontal(menu->col, 0, 2, false);
1319 digit = DebugItemDigits[menu->pos][menu->col];
1320 digit = dx_debug_menu_nav_1D_vertical(digit, 0, 0xF, true);
1321 DebugItemDigits[menu->pos][menu->col] = digit;
1322 } else {
1323 if (NAV_UP) {
1324 menu->pos--;
1325 if (menu->pos < 0) {
1326 menu->pos = invSize - 1;
1327 menu->startPos = menu->pos - 9;
1328 } else {
1329 menu->startPos = MIN(menu->startPos, menu->pos);
1330 }
1331 }
1332 if (NAV_DOWN) {
1333 menu->pos++;
1334 if (menu->pos >= invSize) {
1335 menu->pos = 0;
1336 menu->startPos = 0;
1337 } else {
1338 menu->startPos = MAX(menu->startPos, menu->pos - 9);
1339 }
1340 }
1341 }
1342
1343 // draw
1345
1346 for (i = menu->startPos; i <= menu->startPos + 9; i++) {
1347 s32 posY = SubmenuPosY + (i - menu->startPos) * RowHeight;
1348 s32 itemID = dx_debug_get_item_id(i);
1349 b32 isSelectedRow = (menu->pos == i);
1350
1351 if (DebugEditingItem) {
1352 dx_debug_draw_editable_number(i, "%02X", -1, false, SubmenuPosX, posY);
1353 dx_debug_draw_editable_number(itemID, "%03X", menu->col, isSelectedRow, SubmenuPosX + 20, posY);
1354 } else {
1356 dx_debug_draw_editable_number(itemID, "%03X", -1, false, SubmenuPosX + 20, posY);
1357 }
1358
1360 if (itemID > 0 && itemID < NUM_ITEMS) {
1361 itemMsg = gItemTable[itemID].nameMsg;
1362 }
1363 if (itemMsg != MSG_NONE) {
1365 } else {
1366 char msgBuf[] = {
1370 };
1371 draw_msg((s32)msgBuf, SubmenuPosX + 50, posY, 255, DefaultColor, 0);
1372 }
1373 }
1374
1375 // up arrow
1376 if (menu->startPos > 0) {
1377 char msgArrow[] = {
1379 };
1381 }
1382 // down arrow
1383 if (menu->startPos + 10 < invSize) {
1384 char msgArrow[] = {
1386 };
1387 draw_msg((s32)msgArrow, SubmenuPosX + 132, SubmenuPosY + 134 - round(3.0f * ArrowAnimOffset), 255, DefaultColor, 0);
1388 }
1389}
1390
1391enum {
1396};
1397
1398s32 DebugGearValues[] = {
1399 [DEBUG_GEAR_BOOTS] 0,
1403};
1404s32 DebugGearPos = 0;
1405
1407 s32 idx;
1408 s32 val, dx;
1409
1410 if (DebugStateChanged) {
1415 }
1416
1417 if (RELEASED(BUTTON_L)) {
1419 } else if (RELEASED(BUTTON_R)) {
1424
1427 }
1430 }
1431
1433 }
1434
1436
1437 dx = 0;
1438 if (NAV_RIGHT) {
1439 dx++;
1440 }
1441 if (NAV_LEFT) {
1442 dx--;
1443 }
1444 if (dx != 0) {
1445 s32 min = 0;
1446 s32 max = 0;
1447
1448 switch (DebugGearPos) {
1449 case DEBUG_GEAR_BOOTS:
1450 min = -1;
1451 max = 2;
1452 break;
1453 case DEBUG_GEAR_HAMMER:
1454 min = -1;
1455 max = 2;
1456 break;
1458 min = 0;
1459 max = 1;
1460 break;
1462 min = 0;
1463 max = 2;
1464 break;
1465 }
1466
1468 }
1469
1470 // draw
1477
1478 for (idx = 0; idx < ARRAY_COUNT(DebugGearValues); idx++) {
1480 dx_debug_draw_number(DebugGearValues[idx], "%2d", color, 255, SubmenuPosX + 63, SubmenuPosY + (idx + 2) * RowHeight);
1481 }
1482}
1483
1484enum {
1490};
1491
1492s32 DebugStatValues[] = {
1493 [DEBUG_STAT_HP] 0,
1494 [DEBUG_STAT_FP] 0,
1495 [DEBUG_STAT_BP] 0,
1496 [DEBUG_STAT_LEVEL] 0,
1498};
1499s32 DebugStatPos = 0;
1500
1502 s32 idx;
1503 s32 val, dx;
1504
1505 if (DebugStateChanged) {
1511 }
1512
1513 if (RELEASED(BUTTON_L)) {
1515 } else if (RELEASED(BUTTON_R)) {
1523 }
1524
1526
1527 dx = 0;
1528 if (NAV_RIGHT) {
1529 dx++;
1530 }
1531 if (NAV_LEFT) {
1532 dx--;
1533 }
1534 if (dx != 0) {
1535 switch (DebugStatPos) {
1536 case DEBUG_STAT_HP:
1539 break;
1540 case DEBUG_STAT_FP:
1543 break;
1544 case DEBUG_STAT_BP:
1547 break;
1548 case DEBUG_STAT_LEVEL:
1551 break;
1552 case DEBUG_STAT_SPIRITS:
1555 break;
1556 }
1557 }
1558
1559 // draw
1567
1568 for (idx = 0; idx < ARRAY_COUNT(DebugStatValues); idx++) {
1570 dx_debug_draw_number(DebugStatValues[idx], "%2d", color, 255, SubmenuPosX + 55, SubmenuPosY + (idx + 2) * RowHeight);
1571 }
1572}
1573
1575 .isHex = false,
1576 .digits = { 0, 0, 0 },
1577 .size = 3,
1578 .pos = 0,
1579};
1580
1582 if (DebugStateChanged) {
1584 }
1585
1586 // handle input
1587 if (RELEASED(BUTTON_L)) {
1589 } else if (RELEASED(BUTTON_R)) {
1593 }
1595
1596 // draw
1600}
1601
1603 .isHex = false,
1604 .digits = { 0, 0 },
1605 .size = 2,
1606 .pos = 0,
1607};
1608
1610 if (DebugStateChanged) {
1612 }
1613
1614 // handle input
1615 if (RELEASED(BUTTON_L)) {
1617 } else if (RELEASED(BUTTON_R)) {
1621 }
1623
1624 // draw
1628}
1629
1631 .isHex = false,
1632 .digits = { 0, 0, 0 },
1633 .size = 3,
1634 .pos = 0,
1635};
1636
1638 if (DebugStateChanged) {
1640 }
1641
1642 // handle input
1643 if (RELEASED(BUTTON_L)) {
1645 } else if (RELEASED(BUTTON_R)) {
1649 }
1651
1652 // clamp maximum
1655 }
1656
1657 // draw
1661}
1662
1663// ----------------------------------------------------------------------------
1664// view collision
1665
1666typedef struct DebugCollisionEntry {
1667 char* text;
1668 s32 state;
1670
1671enum {
1680};
1681
1683 [DBC_SHOW_COLLISION] { "Show Collision", false },
1684 [DBC_CULL_BACK] { "Cull Back", true },
1685 [DBC_SHOW_DISABLED] { "Show Disabled", true },
1686 [DBC_HIDE_MODELS] { "Hide Models", false },
1687 [DBC_EXTRUDE_FACES] { "Extrude Faces", false },
1688 [DBC_HIGHLIGHT_FLOOR] { "Highlight Floor", false },
1689 [DBC_HIGHLIGHT_WALL] { "Highlight Wall", false },
1690 [DBC_FADE_DIST] { "Near Fade Dist", 1 },
1691};
1692
1694
1696 s32 idx;
1697
1698 // handle input
1699 if (RELEASED(BUTTON_L)) {
1701 }
1702
1704 if (NAV_LEFT || NAV_RIGHT) {
1706 }
1707 } else {
1711 }
1713
1714 // draw
1716
1717 for (idx = 0; idx < ARRAY_COUNT(DebugCollisionMenu); idx++) {
1719 if (idx != DBC_FADE_DIST) {
1720 char* onoff = DebugCollisionMenu[idx].state ? "On" : "Off";
1722 } else {
1724 dx_debug_draw_number(fadeDist, "%d", color, 255, SubmenuPosX, SubmenuPosY + (idx + 1) * RowHeight);
1725 }
1727 }
1728}
1729
1730void dx_debug_add_collision_vtx(Vtx_t* vtxBuffer, Vec3f* vert, Vec3f* normal, s32 r, s32 g, s32 b, s32 a) {
1732 vtxBuffer->ob[0] = vert->x + normal->x;
1733 vtxBuffer->ob[1] = vert->y + normal->y;
1734 vtxBuffer->ob[2] = vert->z + normal->z;
1735 } else {
1736 vtxBuffer->ob[0] = vert->x;
1737 vtxBuffer->ob[1] = vert->y;
1738 vtxBuffer->ob[2] = vert->z;
1739 }
1740 vtxBuffer->tc[0] = 0;
1741 vtxBuffer->tc[1] = 0;
1742 vtxBuffer->cn[0] = r;
1743 vtxBuffer->cn[1] = g;
1744 vtxBuffer->cn[2] = b;
1745 vtxBuffer->cn[3] = a;
1746}
1747
1748#define MAX_DEBUG_TRIS 1024
1749
1750typedef struct DebugTriangle {
1752 s16 depth;
1753 s16 colliderID;
1755
1758
1761
1764 s32 rdpBufPos;
1765 b32 culling;
1766 s32 fadeDist;
1767 s32 i, j;
1768 s32 dist;
1769
1771
1773 return;
1774 }
1775
1776 // find all collider trianges
1777 DebugTriPos = 0;
1778 for (i = 0; i < gCollisionData.numColliders; i++) {
1780
1782 continue;
1783 }
1784
1785 for (j = 0; j < collider->numTriangles; j++) {
1787 ColliderTriangle* tri = &collider->triangleTable[j];
1788 f32 outX, outY, outZ, outW;
1789 f32 cX = (tri->v1->x + tri->v2->x + tri->v3->x) / 3;
1790 f32 cY = (tri->v1->y + tri->v2->y + tri->v3->y) / 3;
1791 f32 cZ = (tri->v1->z + tri->v2->z + tri->v3->z) / 3;
1792
1793 transform_point(camera->mtxPerspective, cX, cY, cZ, 1.0f, &outX, &outY, &outZ, &outW);
1794
1795 if (outZ < -100) {
1796 // dont draw triangles sufficiently far behind the camera
1797 DebugTriPos--;
1798 } else {
1799 DebugTris[DebugTriPos].tri = tri;
1800 DebugTris[DebugTriPos].depth = outZ;
1801 DebugTris[DebugTriPos].colliderID = i;
1802 }
1803 }
1804 DebugTriPos++;
1805 }
1806 }
1807
1809
1810 // sort triangles by depth
1811#define LESS(i, j) DebugTris[i].depth > DebugTris[j].depth
1812#define SWAP(i, j) temp = DebugTris[i], DebugTris[i] = DebugTris[j], DebugTris[j] = temp
1814#undef LESS
1815#undef SWAP
1816
1821 gSPTexture(gMainGfxPos++, 0x0080, 0x0080, 0, G_TX_RENDERTILE, G_OFF);
1823
1824 if (DebugCollisionMenu[DBC_CULL_BACK].state) {
1826 culling = true;
1827 } else {
1829 culling = false;
1830 }
1831
1832 DebugVtxPos = 0;
1833 rdpBufPos = 0;
1834
1835 // build the display list and fill DebugVtxBuf at the same time
1836 for (i = 0; i < DebugTriPos; i++) {
1839 s32 r, g, b, a;
1840
1841 b32 highlight = false;
1843 highlight = true;
1844 }
1846 highlight = true;
1847 }
1848
1849 if (rdpBufPos == 0) {
1850 // always load vertices 30 at a time
1852 }
1853
1854 // manage culling state for two-sided triangles
1855 if (DebugCollisionMenu[DBC_CULL_BACK].state) {
1856 if (!tri->oneSided && culling) {
1859 culling = false;
1860 } else if (tri->oneSided && !culling) {
1863 culling = true;
1864 }
1865 }
1866
1867 // would be more efficient to pack these into gSP2Triangles ad hoc
1868 // but it becomes difficult to manage once RDP state changes enter the mix due to two-sided triangles
1870
1871 // update rdp buffer pos for next triangle draw
1872 rdpBufPos += 3;
1873 if (rdpBufPos == 30) {
1874 rdpBufPos = 0;
1875 }
1876
1877 if (highlight) {
1878 r = g = b = 196;
1879 } else {
1880 r = round(fabs(tri->normal.x) * 245.0);
1881 g = round(fabs(tri->normal.y) * 245.0);
1882 b = round(fabs(tri->normal.z) * 245.0);
1883 }
1884 a = 180;
1885
1886 // fade triangles too close to the camera
1888 if(fadeDist > 0) {
1889 dist = debugTri->depth - (fadeDist - 1) * 25;
1890 if (dist < 20) {
1891 // from a=20 at d=40 to a=0 at d=-100
1892 a = dx_debug_clamp((dist + 100) / 6, 0, 20);
1893 } else {
1894 a = dx_debug_clamp(dist, 20, 180);
1895 }
1896 }
1897
1898 // build vertices for this triangle
1899 dx_debug_add_collision_vtx(&DebugVtxBuf[DebugVtxPos++], tri->v1, &tri->normal, r, g, b, a);
1900 dx_debug_add_collision_vtx(&DebugVtxBuf[DebugVtxPos++], tri->v2, &tri->normal, r, g, b, a);
1901 dx_debug_add_collision_vtx(&DebugVtxBuf[DebugVtxPos++], tri->v3, &tri->normal, r, g, b, a);
1902 }
1903
1904 // done
1906}
1907
1909 return DebugCollisionMenu[DBC_HIDE_MODELS].state;
1910}
1911
1912// ----------------------------------------------------------------------------
1913// cheat menu
1914
1915typedef struct DebugCheatEntry {
1916 char* text;
1917 b32 enabled;
1919
1921 [DEBUG_CHEAT_GOD_MODE] { "God Mode", false },
1922 [DEBUG_CHEAT_SPEED_MODE] { "Speed Mode", false },
1923 [DEBUG_CHEAT_FLY] { "Fly With L", false },
1924 [DEBUG_CHEAT_HIGH_JUMP] { "High Jump", false },
1925 [DEBUG_CHEAT_IGNORE_WALLS] { "Ignore Walls", false },
1926};
1927
1928s32 DebugCheatPos = 0;
1929
1931 s32 idx;
1932
1933 // handle input
1934 if (RELEASED(BUTTON_L)) {
1936 }
1937 if (NAV_LEFT || NAV_RIGHT) {
1939
1940 // actions to execute on state change
1941 switch (DebugCheatPos) {
1943 case DEBUG_CHEAT_FLY:
1946 break;
1948 if (!DebugCheatMenu[DebugCheatPos].enabled) {
1949 gPlayerStatus.walkSpeed = 2.0f;
1950 gPlayerStatus.runSpeed = 4.0f;
1952 } else {
1953 gPlayerStatus.walkSpeed = 6.0f;
1954 gPlayerStatus.runSpeed = 12.0f;
1956 }
1957 break;
1958 }
1959
1960 }
1962
1963 // draw
1965
1966 for (idx = 0; idx < ARRAY_COUNT(DebugCheatMenu); idx++) {
1968 char* onoff = DebugCheatMenu[idx].enabled ? "On" : "Off";
1969
1972 }
1973}
1974
1976 return DebugCheatMenu[cheat].enabled;
1977}
1978
1979// ----------------------------------------------------------------------------
1980// script debugger
1981
1982const s32 EvtDebugBoxWidth = 72;
1984
1985const s32 EvtDebugMenuPosX = 314 - EvtDebugBoxWidth; // right edge should be at 314
1986const s32 EvtDebugMenuPosY = 60;
1987
1988// position of the blue box containing the main menu options
1991
1992const s32 EvtDebugInfoX = 26;
1993const s32 EvtDebugInfoY = 60;
1994const s32 EvtDebugInfoWidth = 212;
1996
1997char* EvtMainMenuOpts[] = {
1998 "Attach",
1999 "Break",
2000 "Resume",
2001 "Break All",
2002 "Resume All",
2003};
2004
2006
2007s32 EvtListCurPos = 0;
2009
2013
2015extern s32 gScriptIndexList[];
2016extern s32 gScriptIdList[];
2017extern s32 gScriptListCount;
2018
2021
2025
2030
2031typedef struct DebugOpcode {
2032 char* text;
2033} DebugOpcode;
2034
2036 [EVT_OP_END] { "End" },
2037 [EVT_OP_RETURN] { "Return" },
2038 [EVT_OP_LABEL] { "Label" },
2039 [EVT_OP_GOTO] { "Goto" },
2040 [EVT_OP_LOOP] { "Loop" },
2041 [EVT_OP_END_LOOP] { "EndLoop" },
2042 [EVT_OP_BREAK_LOOP] { "BreakLoop" },
2043 [EVT_OP_WAIT_FRAMES] { "Wait" },
2044 [EVT_OP_WAIT_SECS] { "WaitSecs" },
2045 [EVT_OP_IF_EQ] { "If EQ" },
2046 [EVT_OP_IF_NE] { "If NE" },
2047 [EVT_OP_IF_LT] { "If LT" },
2048 [EVT_OP_IF_GT] { "If GT" },
2049 [EVT_OP_IF_LE] { "If LE" },
2050 [EVT_OP_IF_GE] { "If GE" },
2051 [EVT_OP_IF_FLAG] { "If AND" },
2052 [EVT_OP_IF_NOT_FLAG] { "If NAND" },
2053 [EVT_OP_ELSE] { "Else" },
2054 [EVT_OP_END_IF] { "EndIf" },
2055 [EVT_OP_SWITCH] { "Switch" },
2056 [EVT_OP_SWITCH_CONST] { "SwitchConst" },
2057 [EVT_OP_CASE_EQ] { "Case EQ" },
2058 [EVT_OP_CASE_NE] { "Case NE" },
2059 [EVT_OP_CASE_LT] { "Case LT" },
2060 [EVT_OP_CASE_GT] { "Case GT" },
2061 [EVT_OP_CASE_LE] { "Case LE" },
2062 [EVT_OP_CASE_GE] { "Case GE" },
2063 [EVT_OP_CASE_DEFAULT] { "Default" },
2064 [EVT_OP_CASE_OR_EQ] { "CaseOR EQ" },
2065 [EVT_OP_CASE_AND_EQ] { "CaseAND EQ" },
2066 [EVT_OP_CASE_FLAG] { "Case AND" },
2067 [EVT_OP_END_CASE_GROUP] { "EndCaseGroup" },
2068 [EVT_OP_CASE_RANGE] { "Case Range" },
2069 [EVT_OP_BREAK_SWITCH] { "BreakSwitch" },
2070 [EVT_OP_END_SWITCH] { "EndSwitch" },
2071 [EVT_OP_SET] { "Set" },
2072 [EVT_OP_SET_CONST] { "SetConst" },
2073 [EVT_OP_SETF] { "SetF" },
2074 [EVT_OP_ADD] { "Add" },
2075 [EVT_OP_SUB] { "Sub" },
2076 [EVT_OP_MUL] { "Mul" },
2077 [EVT_OP_DIV] { "Div" },
2078 [EVT_OP_MOD] { "Mod" },
2079 [EVT_OP_ADDF] { "AddF" },
2080 [EVT_OP_SUBF] { "SubF" },
2081 [EVT_OP_MULF] { "MulF" },
2082 [EVT_OP_DIVF] { "DivF" },
2083 [EVT_OP_USE_BUF] { "UseBuf" },
2084 [EVT_OP_BUF_READ1] { "BufRead1" },
2085 [EVT_OP_BUF_READ2] { "BufRead2" },
2086 [EVT_OP_BUF_READ3] { "BufRead3" },
2087 [EVT_OP_BUF_READ4] { "BufRead4" },
2088 [EVT_OP_BUF_PEEK] { "BufPeek" },
2089 [EVT_OP_USE_FBUF] { "UseFBuf" },
2090 [EVT_OP_FBUF_READ1] { "FBufRead1" },
2091 [EVT_OP_FBUF_READ2] { "FBufRead2" },
2092 [EVT_OP_FBUF_READ3] { "FBufRead3" },
2093 [EVT_OP_FBUF_READ4] { "FBufRead4" },
2094 [EVT_OP_FBUF_PEEK] { "FBufPeek" },
2095 [EVT_OP_USE_ARRAY] { "UseArray" },
2096 [EVT_OP_USE_FLAGS] { "UseFlags" },
2097 [EVT_OP_MALLOC_ARRAY] { "MallocArray" },
2098 [EVT_OP_BITWISE_AND] { "AND" },
2099 [EVT_OP_BITWISE_AND_CONST] { "AND Const" },
2100 [EVT_OP_BITWISE_OR] { "OR" },
2101 [EVT_OP_BITWISE_OR_CONST] { "OR Const" },
2102 [EVT_OP_CALL] { "Call" },
2103 [EVT_OP_EXEC] { "Exec" },
2104 [EVT_OP_EXEC_GET_TID] { "ExecGet" },
2105 [EVT_OP_EXEC_WAIT] { "ExecWait" },
2106 [EVT_OP_BIND_TRIGGER] { "BindTrigger" },
2107 [EVT_OP_UNBIND] { "Unbind" },
2108 [EVT_OP_KILL_THREAD] { "KillThread" },
2109 [EVT_OP_JUMP] { "Jump" },
2110 [EVT_OP_SET_PRIORITY] { "SetPriority" },
2111 [EVT_OP_SET_TIMESCALE] { "SetTimescale" },
2112 [EVT_OP_SET_GROUP] { "SetGroup" },
2113 [EVT_OP_BIND_PADLOCK] { "BindPadlock" },
2114 [EVT_OP_SUSPEND_GROUP] { "SuspendGroup" },
2115 [EVT_OP_RESUME_GROUP] { "ResumeGroup" },
2116 [EVT_OP_SUSPEND_OTHERS] { "SuspendOthers" },
2117 [EVT_OP_RESUME_OTHERS] { "ResumeOthers" },
2118 [EVT_OP_SUSPEND_THREAD] { "SuspendThread" },
2119 [EVT_OP_RESUME_THREAD] { "ResumeThread" },
2120 [EVT_OP_IS_THREAD_RUNNING] { "IsRunning" },
2121 [EVT_OP_THREAD] { "Thread" },
2122 [EVT_OP_END_THREAD] { "EndThread" },
2123 [EVT_OP_CHILD_THREAD] { "ChildThread" },
2124 [EVT_OP_END_CHILD_THREAD] { "EndChildThread" },
2125 [EVT_OP_DEBUG_LOG] { "Log" },
2126 [EVT_OP_DEBUG_PRINT_VAR] { "PrintVar" },
2127 [EVT_OP_92] { "Op92" },
2128 [EVT_OP_93] { "Op93" },
2129 [EVT_OP_94] { "Op94" },
2130 [EVT_OP_DEBUG_BREAKPOINT] { "Breakpoint" },
2131};
2132
2133// main menu options for evt debugger
2134enum {
2141};
2142
2143// menu options for evt debugger while attached
2144enum {
2151};
2152
2153// display modes for evt debugger vars
2154enum {
2160};
2161
2163 s32 i;
2164
2165 DebugEvtCount = 0;
2166
2167 for (i = 0; i < gScriptListCount; i++) {
2168 Evt* script = (*gCurrentScriptListPtr)[gScriptIndexList[i]];
2169
2170 if (script != nullptr
2171 && script->id == gScriptIdList[i]
2172 && script->stateFlags != 0
2173 ) {
2175 DebugEvtCount++;
2176 }
2177 }
2178
2179 for (i = DebugEvtCount; i < MAX_SCRIPTS; i++) {
2180 DebugEvtList[i] = nullptr;
2181 }
2182}
2183
2185 s32 i;
2186
2187 if (DebugEvtAttached == nullptr) {
2188 return;
2189 }
2190
2191 for (i = 0; i < 16; i++) {
2192 DebugEvtPrevLVars[i] = DebugEvtAttached->varTable[i];
2193 }
2194 for (i = 0; i < 4; i++) {
2195 DebugEvtPrevTemps[i] = DebugEvtAttached->functionTemp[i];
2196 }
2197}
2198
2200 // if all lines can fit, do not scroll
2201 if (maxLine <= maxVisible) {
2202 return 0;
2203 }
2204
2205 // scroll up to show selectedLine with an extra line before, if available
2206 if (selectedLine < drawnLine + 1) {
2207 return MAX(0, selectedLine - 1);
2208 }
2209
2210 // last line selected, scroll to it without end padding
2211 if (selectedLine == maxLine - 1) {
2212 return selectedLine - (maxVisible - 1);
2213 }
2214
2215 //scroll down to show selectedLine with an extra line after
2216 if (selectedLine > drawnLine + (maxVisible - 2)) {
2217 return selectedLine - (maxVisible - 2);
2218 }
2219
2220 // no change
2221 return drawnLine;
2222}
2223
2225 s32 i;
2226
2229 const s32 BoxHeight = BoxOutsetY + 10 * RowHeight + BoxOutsetY;
2230 const s32 BoxWidth = 212;
2231
2232 // script list box
2234
2238
2241 s32 row = 0;
2242
2243 for (i = EvtListDrawPos; i < last; i++) {
2244 Evt* script = DebugEvtList[i];
2245
2246 s32 posY = EvtDebugInfoY + (1 + row) * RowHeight;
2247 s32 color = DefaultColor;
2248
2249 if (script->debugPaused) {
2250 color = MSG_PAL_RED;
2251 }
2252
2254 color = HighlightColor;
2255 }
2256
2257 dx_debug_draw_number(script->groupFlags, "%02X", color, 255, EvtDebugInfoX, posY);
2258 dx_debug_draw_number(script->ptrFirstLine, "%08X", color, 255, EvtDebugInfoX + 20, posY);
2259 dx_debug_draw_number((u8*)script->ptrCurLine - (u8*)script->ptrFirstLine, "%X", color, 255, EvtDebugInfoX + 80, posY);
2260
2261 row++;
2262 }
2263
2264 // animated down arrow
2265 if (DebugEvtCount > last) {
2266 char msgDownArrow[] = {
2268 };
2269 s32 posY = EvtDebugInfoY + (9) * RowHeight;
2270 draw_msg((s32)msgDownArrow, EvtDebugInfoX + 185, posY - round(2.0f * ArrowAnimOffset), 255, DefaultColor, 0);
2271 }
2272 // animated up arrow
2273 if (EvtListDrawPos > 0) {
2274 char msgUpArrow[] = {
2276 };
2277 s32 posY = EvtDebugInfoY + (1) * RowHeight;
2278 draw_msg((s32)msgUpArrow, EvtDebugInfoX + 185, posY + round(2.0f * ArrowAnimOffset), 255, DefaultColor, 0);
2279 }
2280
2281 // menu box (upper right)
2283
2284 for (i = 0; i < ARRAY_COUNT(EvtMainMenuOpts); i++) {
2285 s32 color = DefaultColor;
2286 if (EvtMainMenuPos == i) {
2288 }
2290 }
2291
2292 // count box (lower right)
2295}
2296
2298 s32 i;
2299
2300 debug_printf("count: %d", DebugEvtCount);
2301
2302 for (i = 0; i < DebugEvtCount; i++) {
2303 Evt* script = DebugEvtList[i];
2304 script->debugPaused = true;
2305 script->debugStep = DEBUG_EVT_STEP_NONE;
2306 }
2307}
2308
2310 s32 i;
2311
2312 for (i = 0; i < DebugEvtCount; i++) {
2313 Evt* script = DebugEvtList[i];
2314 script->debugPaused = false;
2315 script->debugStep = DEBUG_EVT_STEP_NONE;
2316 }
2317}
2318
2320 s32 count;
2321 s32 idx;
2322
2324
2326
2327 // handle input
2328 if (RELEASED(BUTTON_R)) {
2329 switch (EvtMainMenuPos) {
2334 break;
2337 break;
2340 break;
2341 }
2342 }
2343
2345}
2346
2348
2350
2351 if (DebugEvtCount > 1) {
2353 } else {
2354 EvtListCurPos = 0;
2355 }
2356
2357 // handle input
2358 if (RELEASED(BUTTON_L)) {
2360 } else if (RELEASED(BUTTON_R)) {
2361 if (DebugEvtCount > 0) {
2362 switch (EvtMainMenuPos) {
2367 DebugEvtDrawLine = 0;
2369 break;
2371 DebugEvtList[EvtListCurPos]->debugPaused = true;
2373 break;
2375 DebugEvtList[EvtListCurPos]->debugPaused = false;
2377 break;
2378 }
2379 }
2380 }
2381
2383}
2384
2386 s32 color = DefaultColor;
2387 if (EvtAttachedMenuPos == idx) {
2389 }
2391}
2392
2393void dx_debug_draw_var(s32 i, s32 number, char* fmt, s32 color, s32 alpha, s32 posX, s32 posY) {
2394 char fmtBuf[64];
2395 char buf[64] = {
2397 };
2398 sprintf(fmtBuf, fmt, i, number);
2400 draw_msg((s32)buf, posX, posY, alpha, color, 0);
2401}
2402
2403void dx_debug_draw_fvar(s32 i, f32 number, char* fmt, s32 color, s32 alpha, s32 posX, s32 posY) {
2404 char fmtBuf[64];
2405 char buf[64] = {
2407 };
2408 sprintf(fmtBuf, fmt, i, number);
2410 draw_msg((s32)buf, posX, posY, alpha, color, 0);
2411}
2412
2414 #define MAX_VALID_FLOAT 1e9
2415 s32 val;
2416 f32 fval;
2417 s32 i;
2418
2419 for (i = 0; i < 16; i++) {
2420 s32 posX = EvtDebugInfoX + (i / 8) * 106;
2421 s32 posY = EvtDebugInfoY + (i % 8) * RowHeight;
2422 s32 color = DebugEvtPrevLVars[i] == DebugEvtAttached->varTable[i] ? DefaultColor : HoverColor;
2423
2424 switch (EvtAttachedVarsMode) {
2426 dx_debug_draw_var(i, DebugEvtAttached->varTable[i], "LVar%X %08X", color, 255, posX, posY);
2427 break;
2429 dx_debug_draw_var(i, DebugEvtAttached->varTable[i], "LVar%X %d", color, 255, posX, posY);
2430 break;
2432 fval = DebugEvtAttached->varTableF[i];
2433 if (fabsf(fval) < MAX_VALID_FLOAT) {
2434 dx_debug_draw_fvar(i, fval, "LVar%X %f", color, 255, posX, posY);
2435 } else {
2436 dx_debug_draw_var(i, 0, "LVar%X ---", color, 255, posX, posY);
2437 }
2438 break;
2440 val = DebugEvtAttached->varTable[i];
2442 dx_debug_draw_fvar(i, EVT_FIXED_TO_FLOAT(val), "LVar%X %f", color, 255, posX, posY);
2443 } else {
2444 dx_debug_draw_var(i, 0, "LVar%X ---", color, 255, posX, posY);
2445 }
2446 break;
2447 }
2448 }
2449
2450 for (i = 0; i < 4; i++) {
2451 s32 posX = EvtDebugInfoX + (i / 2) * 106;
2452 s32 posY = EvtDebugInfoY + (8 + (i % 2)) * RowHeight;
2453 s32 color = DebugEvtPrevTemps[i] == DebugEvtAttached->functionTemp[i] ? DefaultColor : HoverColor;
2454
2455 switch (EvtAttachedVarsMode) {
2457 dx_debug_draw_var(i, DebugEvtAttached->functionTemp[i], "Temp%X %08X", color, 255, posX, posY);
2458 break;
2460 dx_debug_draw_var(i, DebugEvtAttached->functionTemp[i], "Temp%X %d", color, 255, posX, posY);
2461 break;
2463 fval = DebugEvtAttached->functionTempF[i];
2464 if (fabsf(fval) < MAX_VALID_FLOAT) {
2465 dx_debug_draw_fvar(i, fval, "Temp%X %f", color, 255, posX, posY);
2466 } else {
2467 dx_debug_draw_var(i, 0, "Temp%X ---", color, 255, posX, posY);
2468 }
2469 dx_debug_draw_fvar(i, DebugEvtAttached->functionTempF[i], "Temp%X %f", color, 255, posX, posY);
2470 break;
2472 val = DebugEvtAttached->functionTemp[i];
2474 dx_debug_draw_fvar(i, EVT_FIXED_TO_FLOAT(val), "Temp%X %f", color, 255, posX, posY);
2475 } else {
2476 dx_debug_draw_var(i, 0, "Temp%X ---", color, 255, posX, posY);
2477 }
2478 break;
2479 }
2480 }
2481}
2482
2483void dx_debug_evt_draw_arg(u32 value, b32 asDecimal, s32 color, s32 posX, s32 posY) {
2484 if (value >= LVar0 && value <= LVarF) {
2485 dx_debug_draw_number(value - LVar0, "LVar%X", color, 255, posX, posY);
2486 } else if (asDecimal) {
2487 dx_debug_draw_number(value, "%d", color, 255, posX, posY);
2488 } else {
2489 dx_debug_draw_number(value, "%08X", color, 255, posX, posY);
2490 }
2491}
2492
2494 Bytecode* pos;
2495 s32 i, j;
2496 s32 op, nargs;
2497
2498 if (DebugEvtAttached == nullptr) {
2499 return;
2500 }
2501
2502 pos = DebugEvtAttached->ptrFirstLine;
2504
2505 // find offsets for all lines in script
2506 while (true) {
2508
2509 if (pos == DebugEvtAttached->ptrCurLine) {
2511 }
2512
2513 op = *pos++;
2514 nargs = *pos++;
2515 pos += nargs;
2516
2518
2520 break;
2521 }
2522 }
2523
2526 s32 row = 0;
2527
2528 for (i = DebugEvtDrawLine; i < last; i++) {
2529 pos = DebugEvtAttached->ptrFirstLine + DebugEvtLineOffsets[i];
2530 op = *pos++;
2531 nargs = *pos++;
2532 s32* args = pos;
2533 pos += nargs;
2534
2535 s32 posY = EvtDebugInfoY + row * RowHeight;
2536 s32 color = (i == DebugEvtCurLine) ? HoverColor : DefaultColor;
2537
2538 dx_debug_draw_number(i, "%d", color, 255, EvtDebugInfoX, posY);
2539
2540 if (op > 0 && op < ARRAY_COUNT(DebugOps)) {
2541 dx_debug_draw_ascii(DebugOps[op].text, color, EvtDebugInfoX + 15, posY);
2542 } else {
2543 dx_debug_draw_number(op, "%08X", color, 255, EvtDebugInfoX + 15, posY);
2544 }
2545
2546 switch (op) {
2547 case EVT_OP_LABEL:
2548 case EVT_OP_GOTO:
2549 case EVT_OP_LOOP:
2550 case EVT_OP_WAIT_FRAMES:
2551 case EVT_OP_WAIT_SECS:
2552 dx_debug_evt_draw_arg(args[0], true, color, EvtDebugInfoX + 15 + 55, posY);
2553 break;
2554 default:
2555 for (j = 0; j < MIN(2, nargs); j++) {
2556 dx_debug_evt_draw_arg(args[j], false, color, EvtDebugInfoX + 15 + 55 * (j + 1), posY);
2557 }
2558 break;
2559 }
2560
2561 if (nargs > 2) {
2562 dx_debug_draw_ascii("...", color, EvtDebugInfoX + 15 + 55 * 3, posY);
2563 }
2564
2565 row++;
2566 }
2567}
2568
2570 s32 posY;
2571
2572 if (DebugEvtAttached == nullptr) {
2574 return;
2575 }
2576
2577 // saves worrying about null checks while drawing on the frame we detach the evt
2578 b32 detachAfter = false;
2579
2582
2583 // handle input
2584 if (RELEASED(BUTTON_L)) {
2586 } else if (RELEASED(BUTTON_R)) {
2587 switch (EvtAttachedMenuPos) {
2589 detachAfter = true;
2590 break;
2592 DebugEvtAttached->debugPaused = !DebugEvtAttached->debugPaused;
2593 break;
2597 break;
2601 break;
2606 }
2607 break;
2608 }
2609 }
2610
2611 // draw menu (upper right)
2613
2614 dx_debug_evt_draw_menu_line(0, "Detach");
2615 if (DebugEvtAttached->debugPaused) {
2616 dx_debug_evt_draw_menu_line(1, "Resume");
2617 } else {
2618 dx_debug_evt_draw_menu_line(1, "Break");
2619 }
2620 dx_debug_evt_draw_menu_line(2, "Step Once");
2621 dx_debug_evt_draw_menu_line(3, "Step Over");
2622 switch (EvtAttachedVarsMode) {
2624 dx_debug_evt_draw_menu_line(4, "Vars: Int");
2625 break;
2627 dx_debug_evt_draw_menu_line(4, "Vars: Fixed");
2628 break;
2630 dx_debug_evt_draw_menu_line(4, "Vars: Float");
2631 break;
2633 dx_debug_evt_draw_menu_line(4, "Vars: Raw");
2634 break;
2635 }
2636
2637 // header box
2638 posY = EvtDebugInfoY - 4;
2639 posY -= RowHeight + 3; // move up one line and include a small gap
2641
2642 dx_debug_draw_number(DebugEvtAttached->ptrFirstLine, "%08X", DefaultColor, 255, EvtDebugInfoX + 40, posY);
2643
2644 // evt info box
2646
2647 switch (EvtAttachedDispMode) {
2648 case 0:
2651 break;
2652 case 1:
2655 break;
2656 }
2657
2658 if (!DebugEvtAttached->debugPaused) {
2660 }
2661
2662 if (detachAfter) {
2664 DebugEvtAttached = nullptr;
2665 }
2666}
2667
2669 if (DebugEvtAttached != nullptr && (DebugEvtAttached == evt)) {
2670 DebugEvtAttached = nullptr;
2671
2674 }
2675 }
2676}
2677
2678void dx_debug_evt_reset() {
2679 if (DebugEvtAttached != nullptr) {
2680 DebugEvtAttached = nullptr;
2681 }
2682
2683 EvtListCurPos = 0;
2684 EvtListDrawPos = 0;
2685}
2686
2687// ----------------------------------------------------------------------------
2688// banner info
2689
2691 char fmtBuf[128];
2692 s32 effect;
2693
2695 sprintf(fmtBuf, "Map: %7s (%lX)", LastMapName, LastMapEntry);
2697
2699
2701
2704
2707
2710
2712 dx_debug_draw_ascii("(GOD MODE)", MSG_PAL_YELLOW, 151, BottomRowY);
2713 }
2714 } else if (gGameStatus.context == CONTEXT_BATTLE) {
2715 s32 areaID = (LastBattleID >> 24) & 0xFF;
2716 s32 battleID = (LastBattleID >> 16) & 0xFF;
2717 s32 stageID = LastBattleID & 0xFFFF;
2718
2719 sprintf(fmtBuf, "Battle: %02lX-%02lX (%lX)", areaID, battleID, stageID);
2721
2722 sprintf(fmtBuf, "Stage: %-15s", LastStageName);
2724
2726 dx_debug_draw_ascii("(GOD MODE)", MSG_PAL_YELLOW, 128, BottomRowY);
2727 }
2728 }
2729}
2730
2731// ----------------------------------------------------------------------------
2732// console printing
2733
2734#define DEBUG_CONSOLE_DEFAULT_TIMELEFT 60
2735#define DEBUG_CONSOLE_MSG_BUF_SIZE 85
2736
2737typedef struct DebugConsoleLine {
2738 u32 hash;
2739 s32 timeLeft;
2742
2751
2761};
2762
2763u32 dx_debug_hash_location(const char* filename, s32 line) {
2764 u32 hash = 5381;
2765 s32 c;
2766
2767 while ((c = *filename++)) {
2768 hash = ((hash << 5) + hash) + c;
2769 }
2770
2771 hash = ((hash << 5) + hash) + line;
2772
2773 return hash;
2774}
2775
2776static char *proutSprintf(char *dst, const char *src, size_t count) {
2777 return (char *)memcpy((u8 *)dst, (u8 *)src, count) + count;
2778}
2779
2780void dx_hashed_debug_printf(const char* filename, s32 line, const char* fmt, ...) {
2781 char fmtBuf[128];
2782 va_list args;
2783 va_start(args, fmt);
2784 s32 len = _Printf(&proutSprintf, fmtBuf, fmt, args);
2785 if (len >= 0) {
2786 fmtBuf[len] = 0;
2787 }
2788 ASSERT(len < 85);
2789
2790 u32 hash = dx_debug_hash_location(filename, line);
2791 s32 matchedLine = -1;
2792 s32 idx;
2793
2794 // find a line with the matching hash
2795 for (idx = 0; idx < ARRAY_COUNT(DebugConsole); idx++) {
2796 if (DebugConsole[idx]->hash == hash) {
2797 matchedLine = idx;
2798 break;
2799 }
2800 }
2801
2802 // find the oldest line
2803 if (matchedLine == -1) {
2805
2806 for (idx = 0; idx < ARRAY_COUNT(DebugConsole); idx++) {
2807 if (DebugConsole[idx]->timeLeft == 0) {
2808 matchedLine = idx;
2809 break;
2810 }
2811 if (DebugConsole[idx]->timeLeft < minTimeLeft) {
2812 minTimeLeft = DebugConsole[idx]->timeLeft;
2813 matchedLine = idx;
2814 }
2815 }
2816 }
2817
2818 // update the ConsoleLine entry
2819 if (matchedLine != -1) {
2822 DebugConsole[matchedLine]->buf[2] = 12;
2823 DebugConsole[matchedLine]->buf[3] = 12;
2824
2826
2827 DebugConsole[matchedLine]->hash = hash;
2829 }
2830}
2831
2832API_CALLABLE(_dxDebugIntPrintf) {
2833 Bytecode* args = script->ptrReadPos;
2834 s32 i[8];
2835 s32 nargs = 0;
2836 s32 idx;
2837
2838 char* filename = (char*)*args++;
2839 s32 line = *args++;
2840 char* fmt = (char*)*args++;
2841
2842 for (idx = 0; idx < 8; idx++) {
2843 s32 var = *args++;
2844 if (var == 0) {
2845 break;
2846 }
2848 nargs++;
2849 }
2850
2851 switch (nargs) {
2852 case 0: dx_hashed_debug_printf(filename, line, fmt); break;
2853 case 1: dx_hashed_debug_printf(filename, line, fmt, i[0]); break;
2854 case 2: dx_hashed_debug_printf(filename, line, fmt, i[0], i[1]); break;
2855 case 3: dx_hashed_debug_printf(filename, line, fmt, i[0], i[1], i[2]); break;
2856 case 4: dx_hashed_debug_printf(filename, line, fmt, i[0], i[1], i[2], i[3]); break;
2857 case 5: dx_hashed_debug_printf(filename, line, fmt, i[0], i[1], i[2], i[3], i[4]); break;
2858 case 6: dx_hashed_debug_printf(filename, line, fmt, i[0], i[1], i[2], i[3], i[4], i[5]); break;
2859 case 7: dx_hashed_debug_printf(filename, line, fmt, i[0], i[1], i[2], i[3], i[4], i[5], i[6]); break;
2860 }
2861
2862 return ApiStatus_DONE2;
2863}
2864
2865API_CALLABLE(_dxDebugFloatPrintf) {
2866 Bytecode* args = script->ptrReadPos;
2867 f32 f[8];
2868 s32 nargs = 0;
2869 s32 idx;
2870
2871 char* filename = (char*)*args++;
2872 s32 line = *args++;
2873 char* fmt = (char*)*args++;
2874
2875 for (idx = 0; idx < 8; idx++) {
2876 s32 var = *args++;
2877 if (var == 0) {
2878 break;
2879 }
2881 nargs++;
2882 }
2883
2884 switch (nargs) {
2885 case 0: dx_hashed_debug_printf(filename, line, fmt); break;
2886 case 1: dx_hashed_debug_printf(filename, line, fmt, f[0]); break;
2887 case 2: dx_hashed_debug_printf(filename, line, fmt, f[0], f[1]); break;
2888 case 3: dx_hashed_debug_printf(filename, line, fmt, f[0], f[1], f[2]); break;
2889 case 4: dx_hashed_debug_printf(filename, line, fmt, f[0], f[1], f[2], f[3]); break;
2890 case 5: dx_hashed_debug_printf(filename, line, fmt, f[0], f[1], f[2], f[3], f[4]); break;
2891 case 6: dx_hashed_debug_printf(filename, line, fmt, f[0], f[1], f[2], f[3], f[4], f[5]); break;
2892 case 7: dx_hashed_debug_printf(filename, line, fmt, f[0], f[1], f[2], f[3], f[4], f[5], f[6]); break;
2893 }
2894
2895 return ApiStatus_DONE2;
2896}
2897
2898void dx_debug_console_main() {
2900 s32 idx;
2901
2902#define LESS(i, j) DebugConsole[i]->timeLeft > DebugConsole[j]->timeLeft
2903#define SWAP(i, j) temp = DebugConsole[i], DebugConsole[i] = DebugConsole[j], DebugConsole[j] = temp
2905#undef LESS
2906#undef SWAP
2907
2908 for (idx = 0; idx < ARRAY_COUNT(DebugConsole); idx++) {
2909 s32 timeLeft = DebugConsole[idx]->timeLeft;
2910
2911 if (timeLeft > 0) {
2912 s32 alpha = 254;
2913 if (timeLeft < 20) {
2914 alpha = round(254 * (timeLeft / 20.0f));
2915 }
2916
2917 draw_msg((s32)DebugConsole[idx]->buf, 32, 200 - 15 * idx, alpha, DefaultColor, 0);
2918 DebugConsole[idx]->timeLeft--;
2919 }
2920 }
2921}
2922
2923#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:572
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)
void switch_to_partner(s32 arg0)
Definition partners.c:906
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:108
#define LVarF
Definition macros.h:164
#define MAX_SCRIPTS
Definition macros.h:89
#define EVT_FIXED_END
Definition macros.h:46
#define ARRAY_COUNT(arr)
Definition macros.h:39
#define EVT_FIXED_CUTOFF
Definition macros.h:44
#define SCREEN_HEIGHT
Definition macros.h:109
#define ALIGNED(x)
Definition macros.h:9
#define EVT_FIXED_TO_FLOAT(x)
Progammatically converts Float --> f32.
Definition macros.h:55
#define PANIC_MSG(msg, args...)
Definition macros.h:55
#define SP_PER_BAR
Definition macros.h:101
#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