I noticed that my game was crashing with a call to quad3d. This happens randomly, so I initially suspected overflow, or something similarly nasty and subversive! Basically, on my menu screen, the player can rotate a cube to select what he or she wants to do (New Game, Exit, etc).
I logged some of the values that my game was passing to quad3d:
Here's the call:
quad3d(b, POLYTYPE_PTEX, nav_texture[face], &vtx1, &vtx2, &vtx3, &vtx4);
Here's the type of numbers you see when the program doesn't crash:
vtx1: 8642240 6481680 11927552 vtx2: 8642240 9246960 11927552 vtx3: 12329280 9246960 11927552 vtx4: 12329280 6481680 11927552
Here's some from when it does:
vtx1: 320 120 2097169 vtx2: 320 15728520 2097169 vtx3: 20971360 15728520 2097169 vtx4: 20971360 120 2097169
The entire 3d navigation code is relatively self-contained. It's also part of a game started during a hack, so it's pretty messy:
Header:
1 | #ifndef nav3d |
2 | #define nav3d |
3 | |
4 | #define NUM_VERTICES 8 |
5 | #define NUM_FACES 6 |
6 | |
7 | typedef struct VTX |
8 | { |
9 | fixed x, y, z; |
10 | } VTX; |
11 | |
12 | typedef struct QUAD |
13 | { |
14 | VTX *vtxlist; |
15 | int id; |
16 | int v1, v2, v3, v4; |
17 | } QUAD; |
18 | |
19 | typedef struct SHAPE |
20 | { |
21 | fixed x, y, z; |
22 | fixed rx, ry, rz; |
23 | fixed dz; |
24 | fixed drx, dry, drz; |
25 | } SHAPE; |
26 | |
27 | VTX points[] = |
28 | { |
29 | { -32 << 16, -32 << 16, -32 << 16 }, |
30 | { -32 << 16, 32 << 16, -32 << 16 }, |
31 | { 32 << 16, 32 << 16, -32 << 16 }, |
32 | { 32 << 16, -32 << 16, -32 << 16 }, |
33 | { -32 << 16, -32 << 16, 32 << 16 }, |
34 | { -32 << 16, 32 << 16, 32 << 16 }, |
35 | { 32 << 16, 32 << 16, 32 << 16 }, |
36 | { 32 << 16, -32 << 16, 32 << 16 }, |
37 | }; |
38 | |
39 | QUAD faces[] = |
40 | { |
41 | { points, 0, 0, 3, 2, 1 }, |
42 | { points, 1, 4, 5, 6, 7 }, |
43 | { points, 2, 0, 1, 5, 4 }, |
44 | { points, 3, 2, 3, 7, 6 }, |
45 | { points, 4, 0, 4, 7, 3 }, |
46 | { points, 5, 1, 2, 6, 5 } |
47 | }; |
48 | |
49 | SHAPE nav_cube; |
50 | VTX output_points[NUM_VERTICES]; |
51 | QUAD output_faces[NUM_FACES]; |
52 | |
53 | int mov_count, mov_direction; |
54 | |
55 | BITMAP *nav_texture[6], *plank; |
56 | char keybuf[KEY_MAX]; |
57 | |
58 | #endif |
Here's the code that renders and translates the cube:
1 | void translate_shapes(void) |
2 | { |
3 | |
4 | int c, d; |
5 | MATRIX matrix; |
6 | VTX *outpoint = output_points; |
7 | QUAD *outface = output_faces; |
8 | |
9 | get_transformation_matrix(&matrix, itofix(1), nav_cube.rx, nav_cube.ry, nav_cube.rz, nav_cube.x, nav_cube.y, nav_cube.z); |
10 | |
11 | for (d = 0; d < NUM_VERTICES; d++) { |
12 | apply_matrix(&matrix, points[d].x, points[d].y, points[d].z, |
13 | &outpoint[d].x, &outpoint[d].y, &outpoint[d].z); |
14 | persp_project(outpoint[d].x, outpoint[d].y, outpoint[d].z, |
15 | &outpoint[d].x, &outpoint[d].y); |
16 | } |
17 | |
18 | for (d=0; d<NUM_FACES; d++) { |
19 | outface[d] = faces[d]; |
20 | outface[d].vtxlist = outpoint; |
21 | } |
22 | |
23 | outpoint += NUM_VERTICES; |
24 | outface += NUM_FACES; |
25 | |
26 | } |
27 | |
28 | void draw_quad(BITMAP *b, VTX *v1, VTX *v2, VTX *v3, VTX *v4, int face) |
29 | { |
30 | |
31 | /* four vertices */ |
32 | V3D vtx1 = { 0, 0, 0, 0, 0, 0 }; |
33 | V3D vtx2 = { 0, 0, 0, 32<<16, 0, 0 }; |
34 | V3D vtx3 = { 0, 0, 0, 32<<16, 32<<16, 0 }; |
35 | V3D vtx4 = { 0, 0, 0, 0, 32<<16, 0 }; |
36 | |
37 | vtx1.x = v1->x; vtx1.y = v1->y; vtx1.z = v1->z; |
38 | vtx2.x = v2->x; vtx2.y = v2->y; vtx2.z = v2->z; |
39 | vtx3.x = v3->x; vtx3.y = v3->y; vtx3.z = v3->z; |
40 | vtx4.x = v4->x; vtx4.y = v4->y; vtx4.z = v4->z; |
41 | |
42 | log_write(" vtx1: %i %i %i", vtx1.x, vtx1.y, vtx1.z ); |
43 | log_write(" vtx2: %i %i %i", vtx2.x, vtx2.y, vtx2.z ); |
44 | log_write(" vtx3: %i %i %i", vtx3.x, vtx3.y, vtx3.z ); |
45 | log_write(" vtx4: %i %i %i", vtx4.x, vtx4.y, vtx4.z ); |
46 | |
47 | quad3d(b, POLYTYPE_PTEX, nav_texture[face], &vtx1, &vtx2, &vtx3, &vtx4); // Crashes here! |
48 | |
49 | } |
50 | |
51 | int quad_cmp(const void *e1, const void *e2) |
52 | { |
53 | |
54 | QUAD *q1 = (QUAD *)e1; |
55 | QUAD *q2 = (QUAD *)e2; |
56 | |
57 | fixed d1 = q1->vtxlist[q1->v1].z + q1->vtxlist[q1->v2].z + |
58 | q1->vtxlist[q1->v3].z + q1->vtxlist[q1->v4].z; |
59 | |
60 | fixed d2 = q2->vtxlist[q2->v1].z + q2->vtxlist[q2->v2].z + |
61 | q2->vtxlist[q2->v3].z + q2->vtxlist[q2->v4].z; |
62 | |
63 | return d2 - d1; |
64 | |
65 | } |
66 | |
67 | void draw_shapes(BITMAP *b) |
68 | { |
69 | |
70 | int c; |
71 | QUAD *face = output_faces; |
72 | VTX *v1, *v2, *v3, *v4; |
73 | |
74 | qsort(output_faces, NUM_FACES, sizeof(QUAD), quad_cmp); |
75 | |
76 | for (c=0; c < NUM_FACES; c++) { |
77 | |
78 | v1 = face->vtxlist + face->v1; |
79 | v2 = face->vtxlist + face->v2; |
80 | v3 = face->vtxlist + face->v3; |
81 | v4 = face->vtxlist + face->v4; |
82 | |
83 | draw_quad(b, v1, v2, v3, v4, face->id); |
84 | |
85 | face++; |
86 | |
87 | } |
88 | |
89 | } |
Here's how I set everything up:
1 | int setup_navigation() |
2 | { |
3 | |
4 | int i = 0, x = 0, y = 0, i_a = 0; |
5 | |
6 | nav_cube.x = 0; nav_cube.y = 0; nav_cube.z = 150 << 16; |
7 | nav_cube.rx = 0; nav_cube.ry = 0; nav_cube.rz = 0; |
8 | nav_cube.dz = 0; nav_cube.drx = 0; nav_cube.dry = 0; nav_cube.drz = 0; |
9 | |
10 | mov_count = 0; mov_direction = 0; |
11 | |
12 | set_projection_viewport(0, 0, 320, 240); |
13 | |
14 | nav_texture[0] = load_bitmap("gfx/hud/tex0.bmp", NULL); |
15 | nav_texture[1] = load_bitmap("gfx/hud/tex1.bmp", NULL); |
16 | nav_texture[2] = load_bitmap("gfx/hud/tex2.bmp", NULL); |
17 | nav_texture[3] = load_bitmap("gfx/hud/tex3.bmp", NULL); |
18 | nav_texture[4] = load_bitmap("gfx/hud/tex4.bmp", NULL); |
19 | nav_texture[5] = load_bitmap("gfx/hud/tex5.bmp", NULL); |
20 | |
21 | plank = load_bitmap("gfx/hud/plank.bmp", NULL); |
22 | |
23 | if( nav_texture[0] == NULL || nav_texture[1] == NULL || nav_texture[2] == NULL || nav_texture[3] == NULL || |
24 | nav_texture[5] == NULL || plank == NULL ) return 1; |
25 | |
26 | return 0; |
27 | |
28 | } |
Any suggestions?
v1 = face->vtxlist + face->v1;
v2 = face->vtxlist + face->v2;
v3 = face->vtxlist + face->v3;
v4 = face->vtxlist + face->v4;
The only suggestion I have is to add some logging before those statements and make sure you're getting what you expect for face->vtxlist.
The crashing numbers include 320 and 120. Do those particular values occur somewhere else? Just a guess... a wild pointer is stuffing them everywhere
EDIT: Looks like the navigation code is fine. If I skip its execution entirely, the game will still crash at random points. Looks like it's a rogue pointer, or something equally horrible!
EDIT 2: Scratch that. Actually, with the navigation code entirely commented out, I have no crash problems. It's in there, somewhere.
Full header:
Full source:
Would you mind attaching the source to the entire project? Im willing to debug it but I dont want to hack together the source from your code pastes.