提取解压什么的暂不考虑,难度较大。
首先尝试的是屏蔽掉部分GL变换函数,效果很惨,大概没有实用价值。
这里的思路就是破坏动画数据,使带骨胳绑定的原模无法改变动作。
1。改动画文件的文件头,使之变成空白无效的动画。
优点是更接近于实际模型的T-pose。
需要参考nsbmd的源码注释,其中有一部分对动画的解读。
///////////////////////////////////////////////////////
// try to load NSBCA file, if any
/*
getfilepath( szfilename, szfilepath );
getfiletitle( szfilename, szfiletitle );
strcat( szfiletitle, ".nsbca" );
strcat( szfilepath, szfiletitle );
printf( "DEBUG: trying to open '%s'.\n", szfilepath );
FILE *fnsbca = fopen( szfilepath, "rb" );
if ( !fnsbca ) {
getfilepath( szfilename, szfilepath );
getfiletitle( szfilename, szfiletitle );
strcat( szfiletitle, ".bca" );
strcat( szfilepath, szfiletitle );
printf( "DEBUG: trying to open '%s'.\n", szfilepath );
fnsbca = fopen( szfilepath, "rb" );
if ( !fnsbca ) puts( "No animation found." );
}
if ( fnsbca ) {
fseek( fnsbca, 0, SEEK_END );
filesize = ftell( fnsbca );
rewind( fnsbca );
fread( &id, 4, 1, fnsbca );
if ( id == NDS_TYPE_BCA0 ) {
fread( &i, 4, 1, fnsbca );
if ( i == NDS_TYPE_MAGIC1 ) {
fread( &i, 4, 1, fnsbca );
if ( i == filesize ) {
fread( &numblock, 4, 1, fnsbca );
numblock >>= 16;
fread( &r, 4, 1, fnsbca );
fread( &id, 4, 1, fnsbca );
if (numblock == 1 && r == 0x14 && id == NDS_TYPE_JNT0) {
puts( "=================================\nreading 'JNT0'..." );
g_anim = readjnt0( fnsbca, 0x14, &g_animlen );
if ( !g_anim ) {
puts("ERROR readjnt0");
return 1;
}
} else
printf("DEBUG: no. of block != 1.\n");
} else
printf("DEBUG: file size mismatch.\n");
} else
printf("DEBUG: magic1 not found.\n");
} else
printf("DEBUG: file is not BCA0.\n");
fclose( fnsbca );
}
*/
ANIMATION *readjnt0 ( FILE *fnsbca, int blockoffset, int *animlen )
{
int blocksize, blockptr, blocklimit;
int num, objnum, i, j, r;
int *dataoffset;
int sec1offset, sec2offset;
ANIMATION *animation;
////////////////////////////////////////////////
// joint
blockptr = blockoffset + 4; // already read the ID, skip 4 bytes
fread( &blocksize, 4, 1, fnsbca ); // block size
blocklimit = blocksize + blockoffset;
getc( fnsbca ); // skip dummy 0
num = getc( fnsbca ); assert( num > 0 ); // no of joint must == 1
printf( "No. of Joint = %02x\n", num );
dataoffset = (int *)malloc( sizeof( int ) );
if ( !dataoffset ) return NULL;
fseek( fnsbca, 10 + (num<<2), 1 ); // skip [char xyz], useless
blockptr += 10;
fseek( fnsbca, 4, 1 ); // go straight to joint data offset
blockptr += 4;
for ( i = 0; i < num; i++ )
dataoffset[i] = getdword( fnsbca ) + blockoffset;
//fseek( fnsbca, 16 * num, SEEK_CUR ); // skip names
blockptr += 16 * num;
for ( i = 0; i < num; i++ )
{
fseek( fnsbca, dataoffset[i], SEEK_SET );
j = getdword( fnsbca );
if ( j != NDS_TYPE_J_AC ) return NULL;
blockptr += 4;
*animlen = getword( fnsbca );
objnum = getword( fnsbca );
if ( objnum != g_model[0].objnum ) return NULL;
blockptr += 4;
animation = (ANIMATION *)calloc( sizeof( ANIMATION ), objnum );
if ( !animation ) return NULL;
fseek( fnsbca, 4, SEEK_CUR ); // skip 4 zeros
blockptr += 4;
sec1offset = getdword( fnsbca ) + dataoffset[i];
sec2offset = getdword( fnsbca ) + dataoffset[i];
blockptr += 8;
for ( j = 0; j < objnum; j++ )
animation[j].dataoffset = getword( fnsbca ) + dataoffset[i];
for ( j = 0; j < objnum; j++ )
{
ANIMATION *anim = &animation[j];
r = getdword( fnsbca );
anim->flag = r;
if ( (r&1) == 0 ) { // any transformation?
if ( (r&2) == 0 ) { // translation
if ( (r&4) == 1 ) { // use Base T
} else {
if ( (r&8) == 1 ) { // consTX
anim->m_trans[0] = ((float)getdword(fnsbca)) / 4096.0f;
} else {
}
if ( (r&0x10) == 1 ) { // consTY
anim->m_trans[1] = ((float)getdword(fnsbca)) / 4096.0f;
} else {
}
if ( (r&0x20) == 1 ) { // consTZ
anim->m_trans[0] = ((float)getdword(fnsbca)) / 4096.0f;
} else {
}
}
}
if ( (r&0x40) == 0 ) { // rotation
if ( (r&0x100) == 1 ) { // constR
anim->a = ((float)getword(fnsbca)) / 4096.0f;
anim->b = ((float)getword(fnsbca)) / 4096.0f;
} else {
}
}
if ( (r&0x200) == 0 ) { // scale
if ( (r&0x400) == 1 ) { // use Base S
} else {
if ( (r&0x800) == 1 ) { // consSX
anim->m_scale[0] = ((float)getdword(fnsbca)) / 4096.0f;
} else {
}
if ( (r&0x1000) == 1 ) {// consSY
anim->m_scale[0] = ((float)getdword(fnsbca)) / 4096.0f;
} else {
}
if ( (r&0x2000) == 1 ) {// consSZ
anim->m_scale[0] = ((float)getdword(fnsbca)) / 4096.0f;
} else {
}
}
}
}
}
}
free( dataoffset );
return animation;
}
0ch=12 - 103h=259
6 - a0h=160
1 - 28h=40
130h
16+24*n
00 00 10 00 ,00 01 28 00 ,……
Pad:
UE正则表达式:
JNT0^(????????^)^(????^),JNT0^(????????^)????,^(JNT0????????^)???? —— JNT0^1AFA0:Buggy
^(BCA0????????????????JNT0????????^)????:Buggy,无效
^(BCA0????????????????JNT0????????^)?:Buggy,无效
WinHex:
4A4E54303F3F3F3F3F3F3F3F——4A4E54303F3F3F3F00001800
·替换Header4字节标记完全无所用,说明其不参与构成绘图指令
但是目前对.nsbtx(BCA0)的编码格式及作用原理不明,改出来的大都是错的;
严重情况下可导致后续的CPU指令错误,整个崩溃掉。
2。改内置文件名,或改内置文件名的索引。
优点就是更具普遍性。
评论