Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
MorsGames
GitHub Repository: MorsGames/sm64plus
Path: blob/master/src/game/debug.c
7858 views
1
#include <PR/ultratypes.h>
2
3
#include "behavior_data.h"
4
#include "debug.h"
5
#include "engine/behavior_script.h"
6
#include "engine/surface_collision.h"
7
#include "game_init.h"
8
#include "main.h"
9
#include "object_constants.h"
10
#include "object_fields.h"
11
#include "object_helpers.h"
12
#include "object_list_processor.h"
13
#include "print.h"
14
#include "sm64.h"
15
#include "types.h"
16
17
#include "settings.h"
18
19
#define DEBUG_INFO_NOFLAGS (0 << 0)
20
#define DEBUG_INFO_FLAG_DPRINT (1 << 0)
21
#define DEBUG_INFO_FLAG_LSELECT (1 << 1)
22
#define DEBUG_INFO_FLAG_ALL 0xFF
23
24
s16 gDebugPrintState1[6]; // prints top-down?
25
s16 gDebugPrintState2[6]; // prints bottom-up?
26
27
enum DebugPrintStateInfo {
28
DEBUG_PSTATE_DISABLED,
29
DEBUG_PSTATE_X_CURSOR,
30
DEBUG_PSTATE_Y_CURSOR,
31
DEBUG_PSTATE_MIN_Y_CURSOR,
32
DEBUG_PSTATE_MAX_X_CURSOR,
33
DEBUG_PSTATE_LINE_Y_OFFSET
34
};
35
36
// DEBUG_SYS_EFFECTINFO
37
const char *sDebugEffectStringInfo[] = {
38
" a0 %d", " a1 %d", " a2 %d", " a3 %d", " a4 %d", " a5 %d", " a6 %d", " a7 %d",
39
"A" // cursor
40
};
41
42
// DEBUG_SYS_ENEMYINFO
43
const char *sDebugEnemyStringInfo[] = {
44
" b0 %d", " b1 %d", " b2 %d", " b3 %d", " b4 %d", " b5 %d", " b6 %d", " b7 %d",
45
"B" // cursor
46
};
47
48
s32 sDebugInfoDPadMask = 0;
49
s32 sDebugInfoDPadUpdID = 0;
50
s8 sDebugLvSelectCheckFlag = FALSE;
51
52
#define DEBUG_PAGE_MIN DEBUG_PAGE_OBJECTINFO
53
#define DEBUG_PAGE_MAX DEBUG_PAGE_ENEMYINFO
54
55
s8 sDebugPage = DEBUG_PAGE_MIN;
56
s8 sNoExtraDebug = FALSE;
57
s8 sDebugStringArrPrinted = FALSE;
58
s8 sDebugSysCursor = 0;
59
s8 sDebugInfoButtonSeqID = 0;
60
s16 sDebugInfoButtonSeq[] = { U_CBUTTONS, L_CBUTTONS, D_CBUTTONS, R_CBUTTONS, -1 };
61
62
// most likely present in an ifdef DEBUG build. TODO: check DD version?
63
void stub_debug_1(void) {
64
}
65
66
void stub_debug_2(void) {
67
}
68
69
void stub_debug_3(void) {
70
}
71
72
void stub_debug_4(void) {
73
}
74
75
/*
76
* These 2 functions are called from the object list processor in regards to cycle
77
* counts. They likely have stubbed out code that calculated the clock count and
78
* its difference for consecutive calls.
79
*/
80
s64 get_current_clock(void) {
81
s64 wtf = 0;
82
83
return wtf;
84
}
85
86
s64 get_clock_difference(UNUSED s64 arg0) {
87
s64 wtf = 0;
88
89
return wtf;
90
}
91
92
/*
93
* Set the print state info given a pointer to a print state and the relevent
94
* information. Note the reset of the printing boolean. For all intenses and
95
* purposes this creates/formats a new print state.
96
*/
97
void set_print_state_info(s16 *printState, s16 xCursor, s16 yCursor, s16 minYCursor, s16 maxXCursor,
98
s16 lineYOffset) {
99
printState[DEBUG_PSTATE_DISABLED] = FALSE;
100
printState[DEBUG_PSTATE_X_CURSOR] = xCursor;
101
printState[DEBUG_PSTATE_Y_CURSOR] = yCursor;
102
printState[DEBUG_PSTATE_MIN_Y_CURSOR] = minYCursor;
103
printState[DEBUG_PSTATE_MAX_X_CURSOR] = maxXCursor;
104
printState[DEBUG_PSTATE_LINE_Y_OFFSET] = lineYOffset;
105
}
106
107
/*
108
* Take a print state array, string, and the number to print, and use its information to print
109
* the next entry in the list. If the current print state array is too far down the list, this
110
* will print "DPRINT OVER" instead, signaling that the print state overflowed.
111
*/
112
void print_text_array_info(s16 *printState, const char *str, s32 number) {
113
if (!printState[DEBUG_PSTATE_DISABLED]) {
114
if ((printState[DEBUG_PSTATE_Y_CURSOR] < printState[DEBUG_PSTATE_MIN_Y_CURSOR])
115
|| (printState[DEBUG_PSTATE_MAX_X_CURSOR] < printState[DEBUG_PSTATE_Y_CURSOR])) {
116
print_text(printState[DEBUG_PSTATE_X_CURSOR], printState[DEBUG_PSTATE_Y_CURSOR],
117
"DPRINT OVER");
118
printState[DEBUG_PSTATE_DISABLED] += 1; // why not just = TRUE...
119
} else {
120
print_text_fmt_int(printState[DEBUG_PSTATE_X_CURSOR], printState[DEBUG_PSTATE_Y_CURSOR],
121
str, number);
122
printState[DEBUG_PSTATE_Y_CURSOR] += printState[DEBUG_PSTATE_LINE_Y_OFFSET];
123
}
124
}
125
}
126
127
void set_text_array_x_y(s32 xOffset, s32 yOffset) {
128
s16 *printState = gDebugPrintState1;
129
130
printState[DEBUG_PSTATE_X_CURSOR] += xOffset;
131
printState[DEBUG_PSTATE_Y_CURSOR] =
132
yOffset * printState[DEBUG_PSTATE_LINE_Y_OFFSET] + printState[DEBUG_PSTATE_Y_CURSOR];
133
}
134
135
/*
136
* These series of dprint functions print methods depending on the context of the
137
* current debug mode as well as the printer array (down to up vs up to down).
138
*/
139
void print_debug_bottom_up(const char *str, s32 number) {
140
if (gDebugInfoFlags & DEBUG_INFO_FLAG_DPRINT) {
141
print_text_array_info(gDebugPrintState2, str, number);
142
}
143
}
144
145
void print_debug_top_down_objectinfo(const char *str, s32 number) {
146
if ((gDebugInfoFlags & DEBUG_INFO_FLAG_DPRINT) && sDebugPage == DEBUG_PAGE_OBJECTINFO) {
147
print_text_array_info(gDebugPrintState1, str, number);
148
}
149
}
150
151
void print_debug_top_down_mapinfo(const char *str, s32 number) {
152
if (sNoExtraDebug) { // how come this is the only instance of the sNoExtraDebug check?
153
return;
154
}
155
156
if (gDebugInfoFlags & DEBUG_INFO_FLAG_DPRINT) {
157
print_text_array_info(gDebugPrintState1, str, number);
158
}
159
}
160
161
void print_debug_top_down_normal(const char *str, s32 number) {
162
if (gDebugInfoFlags & DEBUG_INFO_FLAG_DPRINT) {
163
print_text_array_info(gDebugPrintState1, str, number);
164
}
165
}
166
167
#ifndef VERSION_EU
168
void print_mapinfo(void) {
169
struct Surface *pfloor;
170
f32 bgY;
171
f32 water;
172
s32 area;
173
s32 angY;
174
175
angY = gCurrentObject->oMoveAngleYaw / 182.044000;
176
area = ((s32) gCurrentObject->oPosX + 0x2000) / 1024
177
+ ((s32) gCurrentObject->oPosZ + 0x2000) / 1024 * 16;
178
179
bgY = find_floor(gCurrentObject->oPosX, gCurrentObject->oPosY, gCurrentObject->oPosZ, &pfloor);
180
water = find_water_level(gCurrentObject->oPosX, gCurrentObject->oPosZ);
181
182
print_debug_top_down_normal("mapinfo", 0);
183
print_debug_top_down_mapinfo("area %x", area);
184
print_debug_top_down_mapinfo("wx %d", gCurrentObject->oPosX);
185
//! Fat finger: programmer hit tab instead of space. Japanese
186
// thumb shift keyboards had the tab key next to the spacebar,
187
// so this was likely the reason.
188
print_debug_top_down_mapinfo("wy\t %d", gCurrentObject->oPosY);
189
print_debug_top_down_mapinfo("wz %d", gCurrentObject->oPosZ);
190
print_debug_top_down_mapinfo("bgY %d", bgY);
191
print_debug_top_down_mapinfo("angY %d", angY);
192
193
if (pfloor) // not null
194
{
195
print_debug_top_down_mapinfo("bgcode %d", pfloor->type);
196
print_debug_top_down_mapinfo("bgstatus %d", pfloor->flags);
197
print_debug_top_down_mapinfo("bgarea %d", pfloor->room);
198
}
199
200
if (gCurrentObject->oPosY < water) {
201
print_debug_top_down_mapinfo("water %d", water);
202
}
203
}
204
#else
205
void print_mapinfo(void) {
206
// EU mostly stubbed this function out.
207
struct Surface *pfloor;
208
UNUSED f32 bgY;
209
UNUSED f32 water;
210
UNUSED s32 area;
211
// s32 angY;
212
//
213
// angY = gCurrentObject->oMoveAngleYaw / 182.044000;
214
// area = ((s32)gCurrentObject->oPosX + 0x2000) / 1024
215
// + ((s32)gCurrentObject->oPosZ + 0x2000) / 1024 * 16;
216
//
217
bgY = find_floor(gCurrentObject->oPosX, gCurrentObject->oPosY, gCurrentObject->oPosZ, &pfloor);
218
water = find_water_level(gCurrentObject->oPosX, gCurrentObject->oPosZ);
219
220
print_debug_top_down_normal("mapinfo", 0);
221
// print_debug_top_down_mapinfo("area %x", area);
222
// print_debug_top_down_mapinfo("wx %d", gCurrentObject->oPosX);
223
// print_debug_top_down_mapinfo("wy\t %d", gCurrentObject->oPosY);
224
// print_debug_top_down_mapinfo("wz %d", gCurrentObject->oPosZ);
225
// print_debug_top_down_mapinfo("bgY %d", bgY);
226
// print_debug_top_down_mapinfo("angY %d", angY);
227
//
228
// if(pfloor) // not null
229
//{
230
// print_debug_top_down_mapinfo("bgcode %d", pfloor->type);
231
// print_debug_top_down_mapinfo("bgstatus %d", pfloor->flags);
232
// print_debug_top_down_mapinfo("bgarea %d", pfloor->room);
233
//}
234
//
235
// if(gCurrentObject->oPosY < water)
236
// print_debug_top_down_mapinfo("water %d", water);
237
}
238
#endif
239
240
void print_checkinfo(void) {
241
print_debug_top_down_normal("checkinfo", 0);
242
}
243
244
void print_surfaceinfo(void) {
245
debug_surface_list_info(gMarioObject->oPosX, gMarioObject->oPosZ);
246
}
247
248
void print_stageinfo(void) {
249
print_debug_top_down_normal("stageinfo", 0);
250
print_debug_top_down_normal("stage param %d", gTTCSpeedSetting);
251
}
252
253
/*
254
* Common printer function for effectinfo and enemyinfo. This function
255
* also prints the cursor functionality intended to be used with modifying
256
* gDebugInfo to set enemy/effect behaviors.
257
*/
258
void print_string_array_info(const char **strArr) {
259
s32 i;
260
261
if (!sDebugStringArrPrinted) {
262
sDebugStringArrPrinted += 1; // again, why not = TRUE...
263
for (i = 0; i < 8; i++) {
264
// sDebugPage is assumed to be 4 or 5 here.
265
print_debug_top_down_mapinfo(strArr[i], gDebugInfo[sDebugPage][i]);
266
}
267
// modify the cursor position so the cursor prints at the correct location.
268
// this is equivalent to (sDebugSysCursor - 8)
269
set_text_array_x_y(0, -1 - (u32)(7 - sDebugSysCursor));
270
print_debug_top_down_mapinfo(strArr[8], 0); // print the cursor
271
set_text_array_x_y(0, 7 - sDebugSysCursor);
272
}
273
}
274
275
void print_effectinfo(void) {
276
print_debug_top_down_normal("effectinfo", 0);
277
print_string_array_info(sDebugEffectStringInfo);
278
}
279
280
void print_enemyinfo(void) {
281
print_debug_top_down_normal("enemyinfo", 0);
282
print_string_array_info(sDebugEnemyStringInfo);
283
}
284
285
void update_debug_dpadmask(void) {
286
s32 dPadMask = gPlayer1Controller->buttonDown & (U_JPAD | D_JPAD | L_JPAD | R_JPAD);
287
288
if (!dPadMask) {
289
sDebugInfoDPadUpdID = 0;
290
sDebugInfoDPadMask = 0;
291
} else {
292
// to prevent stuttering of mask updates, the first time is updated 6
293
// frames from start, and then every 2 frames when held down.
294
if (sDebugInfoDPadUpdID == 0) {
295
sDebugInfoDPadMask = dPadMask;
296
} else if (sDebugInfoDPadUpdID == 6) {
297
sDebugInfoDPadMask = dPadMask;
298
} else {
299
sDebugInfoDPadMask = 0;
300
}
301
sDebugInfoDPadUpdID += 1;
302
if (sDebugInfoDPadUpdID >= 8) {
303
sDebugInfoDPadUpdID = 6; // rapidly set to 6 from 8 as long as dPadMask is being set.
304
}
305
}
306
}
307
308
void debug_unknown_level_select_check(void) {
309
if (!sDebugLvSelectCheckFlag) {
310
sDebugLvSelectCheckFlag += 1; // again, just do = TRUE...
311
312
if (!gDebugLevelSelect) {
313
gDebugInfoFlags = DEBUG_INFO_NOFLAGS;
314
} else {
315
gDebugInfoFlags = DEBUG_INFO_FLAG_LSELECT;
316
}
317
318
gNumCalls.floor = 0;
319
gNumCalls.ceil = 0;
320
gNumCalls.wall = 0;
321
}
322
}
323
324
void reset_debug_objectinfo(void) {
325
gNumFindFloorMisses = 0;
326
gUnknownWallCount = 0;
327
gObjectCounter = 0;
328
sDebugStringArrPrinted = FALSE;
329
D_8035FEE2 = 0;
330
D_8035FEE4 = 0;
331
332
set_print_state_info(gDebugPrintState1, 20, 185, 40, 200, -15);
333
set_print_state_info(gDebugPrintState2, 180, 30, 0, 150, 15);
334
update_debug_dpadmask();
335
}
336
337
/*
338
* This function checks for a button sequence (C Up, C Left, C Down,
339
* C Right) and then toggles the debug flags from FF to 2; 2 is unused,
340
* despite so this has no effect, being called. (unused)
341
*/
342
UNUSED static void check_debug_button_seq(void) {
343
s16 *buttonArr;
344
s16 cButtonMask;
345
346
buttonArr = sDebugInfoButtonSeq;
347
348
if (!(gPlayer1Controller->buttonDown & L_TRIG)) {
349
sDebugInfoButtonSeqID = 0;
350
} else {
351
if ((s16)(cButtonMask = (gPlayer1Controller->buttonPressed & C_BUTTONS))) {
352
if (buttonArr[sDebugInfoButtonSeqID] == cButtonMask) {
353
sDebugInfoButtonSeqID += 1;
354
if (buttonArr[sDebugInfoButtonSeqID] == -1) {
355
if (gDebugInfoFlags == DEBUG_INFO_FLAG_ALL) {
356
gDebugInfoFlags = DEBUG_INFO_FLAG_LSELECT;
357
} else {
358
gDebugInfoFlags = DEBUG_INFO_FLAG_ALL;
359
}
360
}
361
} else {
362
sDebugInfoButtonSeqID = 0;
363
}
364
}
365
}
366
}
367
368
/*
369
* Poll the debug info flags and controller for appropriate presses that
370
* control sDebugPage's range. (unused)
371
*/
372
UNUSED static void try_change_debug_page(void) {
373
if (gDebugInfoFlags & DEBUG_INFO_FLAG_DPRINT) {
374
if ((gPlayer1Controller->buttonPressed & L_JPAD)
375
&& (gPlayer1Controller->buttonDown & (L_TRIG | R_TRIG))) {
376
sDebugPage += 1;
377
}
378
if ((gPlayer1Controller->buttonPressed & R_JPAD)
379
&& (gPlayer1Controller->buttonDown & (L_TRIG | R_TRIG))) {
380
sDebugPage -= 1;
381
}
382
if (sDebugPage >= (DEBUG_PAGE_MAX + 1)) {
383
sDebugPage = DEBUG_PAGE_MIN;
384
}
385
if (sDebugPage < DEBUG_PAGE_MIN) {
386
sDebugPage = DEBUG_PAGE_MAX;
387
}
388
}
389
}
390
391
/*
392
* Use the controller to modify gDebugInfo and the sys cursor while
393
* using the DPad. L/R DPad modifies gDebugInfo while U/D modifies
394
* sDebugSysCursor. This is used to adjust enemy and effect behaviors
395
* on the fly. (unused)
396
*/
397
#ifdef VERSION_EU
398
UNUSED static
399
#endif
400
void try_modify_debug_controls(void) {
401
s32 sp4;
402
403
if (gPlayer1Controller->buttonPressed & Z_TRIG) {
404
sNoExtraDebug ^= 1;
405
}
406
if (!(gPlayer1Controller->buttonDown & (L_TRIG | R_TRIG)) && !sNoExtraDebug) {
407
sp4 = 1;
408
if (gPlayer1Controller->buttonDown & B_BUTTON) {
409
sp4 = 100;
410
}
411
412
if (sDebugInfoDPadMask & U_JPAD) {
413
sDebugSysCursor -= 1;
414
if (sDebugSysCursor < 0) {
415
sDebugSysCursor = 0;
416
}
417
}
418
419
if (sDebugInfoDPadMask & D_JPAD) {
420
sDebugSysCursor += 1;
421
if (sDebugSysCursor >= 8) {
422
sDebugSysCursor = 7;
423
}
424
}
425
426
if (sDebugInfoDPadMask & L_JPAD) {
427
// we allow the player while in this mode to modify the debug controls. This is
428
// so the playtester can adjust enemy behavior and parameters on the fly, since
429
// various behaviors try to update their behaviors from gDebugInfo[4] and [5].
430
if (gPlayer1Controller->buttonDown & A_BUTTON) {
431
gDebugInfo[sDebugPage][sDebugSysCursor] =
432
gDebugInfoOverwrite[sDebugPage][sDebugSysCursor];
433
} else {
434
gDebugInfo[sDebugPage][sDebugSysCursor] = gDebugInfo[sDebugPage][sDebugSysCursor] - sp4;
435
}
436
}
437
438
if (sDebugInfoDPadMask & R_JPAD) {
439
gDebugInfo[sDebugPage][sDebugSysCursor] = gDebugInfo[sDebugPage][sDebugSysCursor] + sp4;
440
}
441
}
442
}
443
444
// possibly a removed debug control (TODO: check DD)
445
void stub_debug_5(void) {
446
}
447
448
/*
449
* If Mario's object exists, this function tries to print available object debug
450
* information depending on the debug sys ID. Additional information (updated obj
451
* count, floor misses, and an unknown wall counter) is also printed.
452
*/
453
void try_print_debug_mario_object_info(void) {
454
if (gMarioObject != NULL) {
455
switch (sDebugPage) {
456
case DEBUG_PAGE_CHECKSURFACEINFO:
457
print_surfaceinfo();
458
break;
459
case DEBUG_PAGE_EFFECTINFO:
460
print_effectinfo();
461
break;
462
case DEBUG_PAGE_ENEMYINFO:
463
print_enemyinfo();
464
break;
465
default:
466
break;
467
}
468
}
469
470
print_debug_top_down_mapinfo("obj %d", gObjectCounter);
471
472
if (gNumFindFloorMisses) {
473
print_debug_bottom_up("NULLBG %d", gNumFindFloorMisses);
474
}
475
476
if (gUnknownWallCount) {
477
print_debug_bottom_up("WALL %d", gUnknownWallCount);
478
}
479
}
480
481
/*
482
* Similar to above, but with level information. (checkinfo, mapinfo,
483
* stageinfo)
484
*/
485
void try_print_debug_mario_level_info(void) {
486
switch (sDebugPage) {
487
case DEBUG_PAGE_OBJECTINFO:
488
break; // no info list is printed for obj info.
489
case DEBUG_PAGE_CHECKSURFACEINFO:
490
print_checkinfo();
491
break;
492
case DEBUG_PAGE_MAPINFO:
493
print_mapinfo();
494
break;
495
case DEBUG_PAGE_STAGEINFO:
496
print_stageinfo();
497
break;
498
default:
499
break;
500
}
501
}
502
503
/*
504
* One of the only remaining debug controls activatable from the
505
* debug control array. This function lets you spawn 1 of 3
506
* objects: A koopa shell, a jumping box, and an underwater koopa
507
* shell. This can be reactivated by turning on modifying
508
* debug controls with try_modify_debug_controls and setting
509
* [5][7] (b7 in the string array) to 1 to enable debug spawn.
510
*/
511
void try_do_mario_debug_object_spawn(void) {
512
UNUSED s32 unused;
513
514
if ((gPlayer1Controller->buttonDown & L_TRIG) && configDebugObjectSpawner) {
515
//if (sDebugPage == DEBUG_PAGE_STAGEINFO && gDebugInfo[DEBUG_PAGE_ENEMYINFO][7] == 1) {
516
if (gPlayer1Controller->buttonPressed & R_JPAD) {
517
spawn_object_relative(0, 0, 100, 200, gCurrentObject, MODEL_KOOPA_SHELL, bhvKoopaShell);
518
}
519
if (gPlayer1Controller->buttonPressed & L_JPAD) {
520
spawn_object_relative(0, 0, 100, 200, gCurrentObject, MODEL_BREAKABLE_BOX_SMALL,
521
bhvJumpingBox);
522
}
523
if (gPlayer1Controller->buttonPressed & D_JPAD) {
524
spawn_object_relative(0, 0, 100, 200, gCurrentObject, MODEL_KOOPA_SHELL,
525
bhvKoopaShellUnderwater);
526
}
527
}
528
}
529
530
// TODO: figure out what this is
531
void debug_print_obj_move_flags(void) {
532
#ifndef VERSION_EU // TODO: Is there a better way to diff this? static EU doesn't seem to work.
533
if (gCurrentObject->oMoveFlags & OBJ_MOVE_LANDED) {
534
print_debug_top_down_objectinfo("BOUND %x", gCurrentObject->oMoveFlags);
535
}
536
if (gCurrentObject->oMoveFlags & OBJ_MOVE_ON_GROUND) {
537
print_debug_top_down_objectinfo("TOUCH %x", gCurrentObject->oMoveFlags);
538
}
539
if (gCurrentObject->oMoveFlags & OBJ_MOVE_LEFT_GROUND) {
540
print_debug_top_down_objectinfo("TAKEOFF %x", gCurrentObject->oMoveFlags);
541
}
542
if (gCurrentObject->oMoveFlags & OBJ_MOVE_ENTERED_WATER) {
543
print_debug_top_down_objectinfo("DIVE %x", gCurrentObject->oMoveFlags);
544
}
545
if (gCurrentObject->oMoveFlags & OBJ_MOVE_AT_WATER_SURFACE) {
546
print_debug_top_down_objectinfo("S WATER %x", gCurrentObject->oMoveFlags);
547
}
548
if (gCurrentObject->oMoveFlags & OBJ_MOVE_UNDERWATER_OFF_GROUND) {
549
print_debug_top_down_objectinfo("U WATER %x", gCurrentObject->oMoveFlags);
550
}
551
if (gCurrentObject->oMoveFlags & OBJ_MOVE_UNDERWATER_ON_GROUND) {
552
print_debug_top_down_objectinfo("B WATER %x", gCurrentObject->oMoveFlags);
553
}
554
if (gCurrentObject->oMoveFlags & OBJ_MOVE_IN_AIR) {
555
print_debug_top_down_objectinfo("SKY %x", gCurrentObject->oMoveFlags);
556
}
557
if (gCurrentObject->oMoveFlags & OBJ_MOVE_OUT_SCOPE) {
558
print_debug_top_down_objectinfo("OUT SCOPE %x", gCurrentObject->oMoveFlags);
559
}
560
#endif
561
}
562
563
// unused, what is this?
564
void debug_enemy_unknown(s16 *enemyArr) {
565
// copy b1-b4 over to an unknown s16 array
566
enemyArr[4] = gDebugInfo[DEBUG_PAGE_ENEMYINFO][1];
567
enemyArr[5] = gDebugInfo[DEBUG_PAGE_ENEMYINFO][2];
568
enemyArr[6] = gDebugInfo[DEBUG_PAGE_ENEMYINFO][3];
569
enemyArr[7] = gDebugInfo[DEBUG_PAGE_ENEMYINFO][4];
570
}
571