#include #include #include #include "TMD.h" // TMD.h -- (c) of SCEE, available in many SCEE demos on the Net Yaroze Site. #include "TMD_check.h" // TMD_check.h -- a file containing function prototypes etc. Include it in source files // where you call 'TMD_check_via_*' or any other routine in this source. // (c) Jon Prestidge March 1999 Version 1.1 // email address: jon@surfed.to // web site: www.obli.co.uk // A member of Eclipse: www.eclipsesoftware.co.uk // // Naming conventions used in this source code:- // p_ = pointer parameter (parameter passed by reference) // v_ = value parameter (parameter passed by value) // _ptr = local pointer variable // long TMD_check_via_handler( GsDOBJ2 *p_handler ) { long status; printf( "\nHandler check started..." ); if ( check_address( (unsigned long) p_handler, sizeof( GsDOBJ2 ) ) ) { printf( "GsDOBJ2" ); goto abort; //Fatal error can't continue checking or prog may crash. } if ( check_address( (unsigned long) p_handler->tmd, sizeof( TMD_OBJ ) ) ) { printf( "GsDOBJ2.tmd" ); if ( !p_handler->tmd ) { printf( " (perhaps GsLinkObject4 has not been called correctly)" ); printf( "\n (This check routine only valid if TMD data created with absolute addresses or once GsLinkObject4 has been called.)" ); } goto abort; //Fatal error can't continue checking or prog may crash. } if ( check_address( (unsigned long) p_handler->coord2, sizeof( GsCOORDINATE2 ) ) ) { printf( "GsDOBJ2.coord2" ); if ( !p_handler->tmd ) printf( " (should be assigned before call to GsLinkObject4)" ); goto abort; //Fatal error can't continue checking or prog may crash. } status = TMD_check_via_object( (TMD_OBJ *) p_handler->tmd ); return status; abort: printf( "\nChecks aborted\n" ); return TMD_CHECK_FATAL_ERROR; } long TMD_check_via_object( TMD_OBJ *p_TMD_object ) { TMD_OBJ *TMD_object_ptr; TMD_F_3 *TMD_F_3_ptr; TMD_F_3_NL *TMD_F_3_NL_ptr; TMD_G_3 *TMD_G_3_ptr; TMD_G_4 *TMD_G_4_ptr; long i, non_zeros, squared_dis, num_unreferenced, num_double_ref; SVECTOR *vert_ptr, *norm_ptr; unsigned long *prim_ptr, temp_address, size, temp_mask; PRIM_HDR *prim_header_ptr; printf( "\nTMD_object check started...\n(warning .pad fields will be over-written)" ); if ( check_address( (unsigned long) p_TMD_object, sizeof( TMD_OBJ ) ) ) { printf( "TMD_OBJ address" ); goto abort; //Fatal error can't continue checking or prog may crash. } // Check number of norms, verts, prims against what would be a typical high value... // you can improve these checks by using typical high values found in your // particular application... // These are not error messages as such but sort of "this is a bit unusual" messages... if ( p_TMD_object->n_vert > 10000 ) printf( "\nUnusually high num of verts specified: %d TMD_OBJ.n_vert", p_TMD_object->n_vert ); if ( p_TMD_object->n_norm > 10000 ) printf( "\nUnusually high num of norms specified: %d TMD_OBJ.n_norm", p_TMD_object->n_norm ); if ( p_TMD_object->n_prim > 10000 ) printf( "\nUnusually high num of prims specified: %d TMD_OBJ.n_prim", p_TMD_object->n_prim ); if ( p_TMD_object->n_vert <= 2 ) { printf( "\nNot enough verts specified (even for a triangle): %d TMD_OBJ.n_vert", p_TMD_object->n_vert ); goto abort; // no point in continuing. } if ( p_TMD_object->n_norm <= 0 ) { printf( "\nZero norms specified. TMD_OBJ.n_norm (error unless all prims are unlit)" ); goto abort; // no point in continuing. } if ( p_TMD_object->n_prim <= 0 ) { printf( "\nZero prims specified. TMD_OBJ.n_prim" ); goto abort; // no point in continuing. } if ( check_address( (unsigned long) p_TMD_object->vert_top, sizeof( SVECTOR ) * p_TMD_object->n_vert ) ) { printf ( " vertices data area" ); goto abort; //Fatal error can't continue checking or prog may crash. } if ( check_address( (unsigned long) p_TMD_object->norm_top, sizeof( SVECTOR ) * p_TMD_object->n_norm ) ) { printf ( " normals data area" ); goto abort; //Fatal error can't continue checking or prog may crash. } if ( check_address( (unsigned long) p_TMD_object->prim_top, ( sizeof( TMD_HDR ) + sizeof( TMD_F_3_NL ) ) * p_TMD_object->n_prim ) ) { // (judge by the smallest primitive type as an initial check) printf ( " prim data area" ); goto abort; //Fatal error can't continue checking or prog may crash. } // Check all the pad fields... if any are not zero then it may be a good // indication that part of the data has been corrupted. for ( i = non_zeros = 0, vert_ptr = (SVECTOR *) p_TMD_object->vert_top; i < p_TMD_object->n_vert; i++, vert_ptr++ ) { if ( vert_ptr->pad ) { non_zeros++; vert_ptr->pad = 0; } } if ( non_zeros ) { printf( "\n%d/%d verts have .pad fields that are non-zero.", non_zeros, p_TMD_object->n_vert ); printf( "\n...if vertex .pad fields were zero when defined, then this indicates that the vertex data area has been corrupted." ); } for ( i = non_zeros = 0, norm_ptr = (SVECTOR *) p_TMD_object->norm_top; i < p_TMD_object->n_norm; i++, norm_ptr++ ) { if ( norm_ptr->pad ) { non_zeros++; norm_ptr->pad = 0; } if ( norm_ptr->vx > 6000 || norm_ptr->vx < -6000 || norm_ptr->vy > 6000 || norm_ptr->vy < -6000 || norm_ptr->vz > 6000 || norm_ptr->vz < -6000 ) { // prevent overflow on length check calculation printf( "\nNorm #%d, Unusually long normal.", i ); } else { squared_dis = norm_ptr->vx * norm_ptr->vx + norm_ptr->vy * norm_ptr->vy + norm_ptr->vz * norm_ptr->vz; if ( squared_dis < 3000 * 3000 ) printf( "\nNorm #%d, Unusually short normal length: SQRT(%d)", i, squared_dis ); if ( squared_dis > 4500 * 4500 ) printf( "\nNorm #%d, Unusually long normal length: SQRT(%d)", i, squared_dis ); } } // (end for i) if ( non_zeros ) { printf( "\n%d/%d normals have .pad fields that are non-zero.", non_zeros, p_TMD_object->n_norm ); printf( "\n...if normal .pad fields were zero when defined, then this indicates that the vertex data area has been corrupted." ); } // Now check the primitives and check references to the verts and normals.... for ( i = 0, prim_ptr = (unsigned long *) p_TMD_object->prim_top; i < p_TMD_object->n_prim; i++, prim_ptr += size ) { prim_header_ptr = (PRIM_HDR *) prim_ptr; temp_mask = prim_header_ptr->flag; if ( temp_mask & GRD ) temp_mask -= GRD; // Graduation if ( temp_mask & FCE ) temp_mask -= FCE; // 2 sided if ( temp_mask & LGT ) temp_mask -= LGT; // no light source if ( temp_mask ) printf( "\nPrim #%d. Unknown bit or bits set in PRIM_HDR.flag", i ); if ( prim_header_ptr->flag & FCE ) // 2 sided printf( "\nPrim #%d. Two sided bit set in PRIM_HDR.flag. May not be supported - check SCEE news groups etc.", i ); size = sizeof( PRIM_HDR ); temp_address = (unsigned long) prim_header_ptr; if ( check_address( temp_address, size ) ) { printf( "prim header #%d", i ); goto abort; } temp_address += size; // address where the body of the primitive will begin. switch( prim_header_ptr->mode ) { case F_3_OR_F_3G: // Triangle No-texture if ( (prim_header_ptr->flag & GRD) == 0 ) { // without graduation... size += sizeof( TMD_F_3 ); if ( i ) if ( prim_header_ptr->ilen != 3 || prim_header_ptr->olen != 4 ) printf( "\nPrim #%d. bad ilen or olen,", i ); // ... (GsLinkObject4 changes the ilen and olen in the first prim // to the number of primitives in that object... // that's why they aren't checked if i == 0) TMD_F_3_ptr = (TMD_F_3 *) temp_address; if ( TMD_F_3_ptr->mode2 != prim_header_ptr->mode ) printf( "\nPrim #%d. mode2 field != mode,", i ); check_3_vertices( p_TMD_object, i, TMD_F_3_ptr->vert0, TMD_F_3_ptr->vert1, TMD_F_3_ptr->vert2 ); check_1_normal( p_TMD_object, i, TMD_F_3_ptr->norm0 ); } else { // with graduation... size += sizeof( TMD_F_3G ); } break; case F_3T: // Triangle Texture size += sizeof( TMD_F_3T ); break; case G_3_OR_G_3G: // triangle gouraud if ( (prim_header_ptr->flag & GRD) == 0 ) { // without graduation size += sizeof( TMD_G_3 ); if ( i ) if ( prim_header_ptr->ilen != 4 || prim_header_ptr->olen != 6 ) printf( "\nPrim #%d. bad ilen or olen,", i ); // ... (GsLinkObject4 changes the ilen and olen in the first prim // to the number of primitives in that object... // that's why they aren't checked if i == 0) TMD_G_3_ptr = (TMD_G_3 *) temp_address; if ( TMD_G_3_ptr->mode2 != prim_header_ptr->mode ) printf( "\nPrim #%d. mode2 field != mode,", i ); check_3_vertices( p_TMD_object, i, TMD_G_3_ptr->vert0, TMD_G_3_ptr->vert1, TMD_G_3_ptr->vert2 ); check_3_normals( p_TMD_object, i, TMD_G_3_ptr->norm0, TMD_G_3_ptr->norm1, TMD_G_3_ptr->norm2 ); } else { // with graduation... size += sizeof( TMD_G_3G ); } break; case G_3T: // triangle gouraud texture size += sizeof( TMD_G_3T ); break; case F_3_NL: // triangle no texture no light size += sizeof( TMD_F_3_NL ); if ( i ) if ( prim_header_ptr->ilen != 3 || prim_header_ptr->olen != 4 ) printf( "\nPrim #%d. bad ilen or olen,", i ); // ... (GsLinkObject4 changes the ilen and olen in the first prim // to the number of primitives in that object... // that's why they aren't checked if i == 0) TMD_F_3_NL_ptr = (TMD_F_3_NL *) temp_address; if ( TMD_F_3_NL_ptr->mode2 != prim_header_ptr->mode ) printf( "\nPrim #%d. mode2 field != mode,", i ); check_3_vertices( p_TMD_object, i, TMD_F_3_NL_ptr->vert0, TMD_F_3_NL_ptr->vert1, TMD_F_3_NL_ptr->vert2 ); break; case F_3T_NL: // triangle texture no light size += sizeof( TMD_F_3T_NL ); break; case G_3_NL: // triangle gouraud no texture no light size += sizeof( TMD_G_3_NL ); break; case G_3T_NL: // triangle gouraud texture no light size += sizeof( TMD_G_3T_NL ); break; case F_4: // Quadangle No-texture if ( (prim_header_ptr->flag & GRD) == 0 ) { // without graduation... size += sizeof( TMD_F_4 ); } else { // with graduation... size += sizeof( TMD_F_4G ); } break; case F_4T: // Quadangle Texture size += sizeof( TMD_F_4T ); break; case G_4_OR_G_4G: // quad gouraud if ( (prim_header_ptr->flag & GRD) == 0 ) { // without graduation... size += sizeof( TMD_G_4 ); if ( i ) if ( prim_header_ptr->ilen != 5 || prim_header_ptr->olen != 8 ) printf( "\nPrim #%d. bad ilen or olen,", i ); // ... (GsLinkObject4 changes the ilen and olen in the first prim // to the number of primitives in that object... // that's why they aren't checked if i == 0) TMD_G_4_ptr = (TMD_G_4 *) temp_address; if ( TMD_G_4_ptr->mode2 != prim_header_ptr->mode ) printf( "\nPrim #%d. mode2 field != mode,", i ); check_4_vertices( p_TMD_object, i, TMD_G_4_ptr->vert0, TMD_G_4_ptr->vert1, TMD_G_4_ptr->vert2, TMD_G_4_ptr->vert3 ); check_4_normals( p_TMD_object, i, TMD_G_4_ptr->norm0, TMD_G_4_ptr->norm1, TMD_G_4_ptr->norm2, TMD_G_4_ptr->norm3 ); } else { // with graduation... size += sizeof( TMD_G_4G ); } break; case G_4T: // quad gouraud texture size += sizeof( TMD_G_4T ); break; case F_4_NL: // quad no texture no light size += sizeof( TMD_F_4_NL ); break; case F_4T_NL: // quad texture no light size += sizeof( TMD_F_4T_NL ); break; case G_4_NL: // quad gouraud no texture no light size += sizeof( TMD_G_4_NL ); break; case G_4T_NL: // quad gouraud texture no light size += sizeof( TMD_G_4T_NL ); break; case SL: // straight line no gradation size += sizeof( TMD_SL ); printf( "\nPrim #%d. SL (%d) may not be supported. Check news groups etc.", i, prim_header_ptr->mode ); break; case SL_G: // straight line gradation size += sizeof( TMD_SL_G ); printf( "\nPrim #%d. SL_G (%d) may not be supported. Check news groups etc.", i, prim_header_ptr->mode ); break; default: printf( "\nPrim #%d. Unknown primitive mode %d (or it has been omitted from 'TMD_check'.", i, prim_header_ptr->mode ); goto abort; // no point in continuing because we won't know the address of the next prim } if ( check_address( temp_address, size ) ) { printf( "prim #%d", i ); goto abort; } if ( size & 3 ) { printf( "\nLong word alignment error." ); goto abort; // abort } size >>= 2; // convert bytes to long words. } // (end for i) // Recheck the verts and normals to see which have been referenced.... for ( i = num_unreferenced = num_double_ref = 0, vert_ptr = (SVECTOR *) p_TMD_object->vert_top; i < p_TMD_object->n_vert; i++, vert_ptr++ ) { if ( (vert_ptr->pad & VERTEX_REFERENCED) == 0 ) num_unreferenced++; if ( vert_ptr->pad & NORMAL_REFERENCED ) num_double_ref++; } if ( num_unreferenced ) printf( "\n%d verts unreferenced by prims", num_unreferenced ); if ( num_double_ref ) printf( "\n%d verts referenced as norms! Vert & norm data must overlap.",num_double_ref ); for ( i = num_unreferenced = num_double_ref = 0, norm_ptr = (SVECTOR *) p_TMD_object->norm_top; i < p_TMD_object->n_norm; i++, norm_ptr++ ) { if ( (norm_ptr->pad & NORMAL_REFERENCED) == 0 ) num_unreferenced++; if ( norm_ptr->pad & VERTEX_REFERENCED ) num_double_ref++; } if ( num_unreferenced ) printf( "\n%d norms unreferenced by prims", num_unreferenced ); if ( num_double_ref ) printf( "\n%d norms referenced as verts! Vert & norm data must overlap.", num_double_ref ); // Reset the pad fields incase the data is checked later or to prevent the data // data looking confusing when viewed in a debugger... for ( i = num_unreferenced = num_double_ref = 0, vert_ptr = (SVECTOR *) p_TMD_object->vert_top; i < p_TMD_object->n_vert; i++, vert_ptr++ ) { vert_ptr->pad = 0; } for ( i = num_unreferenced = num_double_ref = 0, norm_ptr = (SVECTOR *) p_TMD_object->norm_top; i < p_TMD_object->n_norm; i++, norm_ptr++ ) { norm_ptr->pad = 0; } printf ( "\nAccording to params set in TMD object header:-" ); vert_ptr = (SVECTOR*) p_TMD_object->vert_top; vert_ptr += p_TMD_object->n_vert; temp_address = (unsigned long) vert_ptr; temp_address--; printf( "\n%X to %X inclusive: %d verts.", p_TMD_object->vert_top, temp_address, p_TMD_object->n_vert ); norm_ptr = (SVECTOR*) p_TMD_object->norm_top; norm_ptr += p_TMD_object->n_norm; temp_address = (unsigned long) norm_ptr; temp_address--; printf( "\n%X to %X inclusive: %d norms.", p_TMD_object->norm_top, temp_address, p_TMD_object->n_norm ); temp_address = (unsigned long) prim_ptr; temp_address--; printf( "\n%X to %X inclusive: %d prims.", p_TMD_object->prim_top, temp_address, p_TMD_object->n_prim ); printf( "\nChecks complete\n" ); return TMD_CHECK_END; abort: printf( "\nChecks aborted\n" ); return TMD_CHECK_FATAL_ERROR; } long check_address( unsigned long v_address, long v_size ) { unsigned long const min_address = 0x80090000, max_address = 0x801fff00; unsigned long test_address; test_address = v_address; if ( test_address < min_address ) { printf( "\nAddress %X is below the minimum allowed (%X) ", v_address, min_address ); return 1; } if ( test_address > max_address - v_size ) { printf( "\nData at %X (%d bytes) overflows the maximum address (%X) ", v_address, v_size, max_address ); return 1; } return 0; } long check_3_vertices( TMD_OBJ *p_TMD_object, long v_prim_index, long v_vert_index0, long v_vert_index1, long v_vert_index2 ) { SVECTOR *vert_ptr0, *vert_ptr1, *vert_ptr2; if ( v_vert_index0 >= p_TMD_object->n_vert || v_vert_index1 >= p_TMD_object->n_vert || v_vert_index2 >= p_TMD_object->n_vert ) { printf( "\nPrim #%d, one or more of the vert indexes are out of range.", v_prim_index ); return 1; } if ( v_vert_index0 == v_vert_index1 || v_vert_index0 == v_vert_index2 || v_vert_index1 == v_vert_index2 ) printf( "\nPrim #%d, two or more of the vert indexes are the same.", v_prim_index ); vert_ptr0 = vert_ptr1 = vert_ptr2 = (SVECTOR *) p_TMD_object->vert_top; vert_ptr0 += v_vert_index0; vert_ptr1 += v_vert_index1; vert_ptr2 += v_vert_index2; if ( !(vert_ptr0->pad & VERTEX_REFERENCED) ) vert_ptr0->pad += VERTEX_REFERENCED; if ( !(vert_ptr1->pad & VERTEX_REFERENCED) ) vert_ptr1->pad += VERTEX_REFERENCED; if ( !(vert_ptr2->pad & VERTEX_REFERENCED) ) vert_ptr2->pad += VERTEX_REFERENCED; if ( vert_ptr0->vx == vert_ptr1->vx && vert_ptr0->vy == vert_ptr1->vy && vert_ptr0->vz == vert_ptr1->vz ) printf( "\nPrim #%d, vert 0 and 1 have same co-ordinate.", v_prim_index ); if ( vert_ptr0->vx == vert_ptr2->vx && vert_ptr0->vy == vert_ptr2->vy && vert_ptr0->vz == vert_ptr2->vz ) printf( "\nPrim #%d, vert 0 and 2 have same co-ordinate.", v_prim_index ); if ( vert_ptr1->vx == vert_ptr2->vx && vert_ptr1->vy == vert_ptr2->vy && vert_ptr1->vz == vert_ptr2->vz ) printf( "\nPrim #%d, vert 1 and 2 have same co-ordinate.", v_prim_index ); return 0; } long check_4_vertices( TMD_OBJ *p_TMD_object, long v_prim_index, long v_vert_index0, long v_vert_index1, long v_vert_index2, long v_vert_index3 ) { SVECTOR *vert_ptr0, *vert_ptr1, *vert_ptr2, *vert_ptr3; if ( v_vert_index0 >= p_TMD_object->n_vert || v_vert_index1 >= p_TMD_object->n_vert || v_vert_index2 >= p_TMD_object->n_vert || v_vert_index3 >= p_TMD_object->n_vert ) { printf( "\nPrim #%d, one or more of the vert indexes are out of range.", v_prim_index ); return 1; } if ( v_vert_index0 == v_vert_index1 || v_vert_index0 == v_vert_index2 || v_vert_index0 == v_vert_index3 || v_vert_index1 == v_vert_index2 || v_vert_index1 == v_vert_index3 || v_vert_index2 == v_vert_index3 ) printf( "\nPrim #%d, two or more of the vert indexes are the same.", v_prim_index ); vert_ptr0 = vert_ptr1 = vert_ptr2 = vert_ptr3 = (SVECTOR *) p_TMD_object->vert_top; vert_ptr0 += v_vert_index0; vert_ptr1 += v_vert_index1; vert_ptr2 += v_vert_index2; vert_ptr3 += v_vert_index3; if ( !(vert_ptr0->pad & VERTEX_REFERENCED) ) vert_ptr0->pad += VERTEX_REFERENCED; if ( !(vert_ptr1->pad & VERTEX_REFERENCED) ) vert_ptr1->pad += VERTEX_REFERENCED; if ( !(vert_ptr2->pad & VERTEX_REFERENCED) ) vert_ptr2->pad += VERTEX_REFERENCED; if ( !(vert_ptr3->pad & VERTEX_REFERENCED) ) vert_ptr3->pad += VERTEX_REFERENCED; if ( vert_ptr0->vx == vert_ptr1->vx && vert_ptr0->vy == vert_ptr1->vy && vert_ptr0->vz == vert_ptr1->vz ) printf( "\nPrim #%d, vert 0 and 1 have same co-ordinate.", v_prim_index ); if ( vert_ptr0->vx == vert_ptr2->vx && vert_ptr0->vy == vert_ptr2->vy && vert_ptr0->vz == vert_ptr2->vz ) printf( "\nPrim #%d, vert 0 and 2 have same co-ordinate.", v_prim_index ); if ( vert_ptr0->vx == vert_ptr3->vx && vert_ptr0->vy == vert_ptr3->vy && vert_ptr0->vz == vert_ptr3->vz ) printf( "\nPrim #%d, vert 0 and 3 have same co-ordinate.", v_prim_index ); if ( vert_ptr1->vx == vert_ptr2->vx && vert_ptr1->vy == vert_ptr2->vy && vert_ptr1->vz == vert_ptr2->vz ) printf( "\nPrim #%d, vert 1 and 2 have same co-ordinate.", v_prim_index ); if ( vert_ptr1->vx == vert_ptr3->vx && vert_ptr1->vy == vert_ptr3->vy && vert_ptr1->vz == vert_ptr3->vz ) printf( "\nPrim #%d, vert 1 and 3 have same co-ordinate.", v_prim_index ); if ( vert_ptr2->vx == vert_ptr3->vx && vert_ptr2->vy == vert_ptr3->vy && vert_ptr2->vz == vert_ptr3->vz ) printf( "\nPrim #%d, vert 2 and 3 have same co-ordinate.", v_prim_index ); return 0; } long check_1_normal( TMD_OBJ *p_TMD_object, long v_prim_index, long v_norm_index0 ) { SVECTOR *norm_ptr0; if ( v_norm_index0 >= p_TMD_object->n_norm ) { printf( "\nPrim #%d, norm index out of range.", v_prim_index ); return 1; } norm_ptr0 = (SVECTOR *) p_TMD_object->norm_top; norm_ptr0 += v_norm_index0; if ( !(norm_ptr0->pad & NORMAL_REFERENCED) ) norm_ptr0->pad += NORMAL_REFERENCED; return 0; } long check_3_normals( TMD_OBJ *p_TMD_object, long v_prim_index, long v_norm_index0, long v_norm_index1, long v_norm_index2 ) { SVECTOR *norm_ptr0, *norm_ptr1, *norm_ptr2; if ( v_norm_index0 >= p_TMD_object->n_norm || v_norm_index1 >= p_TMD_object->n_norm || v_norm_index2 >= p_TMD_object->n_norm ) { printf( "\nPrim #%d, one or more norm index out of range.", v_prim_index ); return 1; } norm_ptr0 = norm_ptr1 = norm_ptr2 = (SVECTOR *) p_TMD_object->norm_top; norm_ptr0 += v_norm_index0; norm_ptr1 += v_norm_index1; norm_ptr2 += v_norm_index2; if ( !(norm_ptr0->pad & NORMAL_REFERENCED) ) norm_ptr0->pad += NORMAL_REFERENCED; if ( !(norm_ptr1->pad & NORMAL_REFERENCED) ) norm_ptr1->pad += NORMAL_REFERENCED; if ( !(norm_ptr2->pad & NORMAL_REFERENCED) ) norm_ptr2->pad += NORMAL_REFERENCED; return 0; } long check_4_normals( TMD_OBJ *p_TMD_object, long v_prim_index, long v_norm_index0, long v_norm_index1, long v_norm_index2, long v_norm_index3 ) { SVECTOR *norm_ptr0, *norm_ptr1, *norm_ptr2, *norm_ptr3; if ( v_norm_index0 >= p_TMD_object->n_norm || v_norm_index1 >= p_TMD_object->n_norm || v_norm_index2 >= p_TMD_object->n_norm || v_norm_index3 >= p_TMD_object->n_norm ) { printf( "\nPrim #%d, one or more norm index out of range.", v_prim_index ); return 1; } norm_ptr0 = norm_ptr1 = norm_ptr2 = norm_ptr3 = (SVECTOR *) p_TMD_object->norm_top; norm_ptr0 += v_norm_index0; norm_ptr1 += v_norm_index1; norm_ptr2 += v_norm_index2; norm_ptr3 += v_norm_index3; if ( !(norm_ptr0->pad & NORMAL_REFERENCED) ) norm_ptr0->pad += NORMAL_REFERENCED; if ( !(norm_ptr1->pad & NORMAL_REFERENCED) ) norm_ptr1->pad += NORMAL_REFERENCED; if ( !(norm_ptr2->pad & NORMAL_REFERENCED) ) norm_ptr2->pad += NORMAL_REFERENCED; if ( !(norm_ptr3->pad & NORMAL_REFERENCED) ) norm_ptr3->pad += NORMAL_REFERENCED; return 0; }