u8* DecompressAsh( const u8 *stuff, u32 &len ) { if( !IsAshCompressed( stuff, len ) ) { return NULL; } unsigned int r[32]; unsigned int count = 0; unsigned int t; r[4] = (u32)stuff; //in r[5] = 0x415348; r[6] = 0x415348; r[5] = s32(*(unsigned int *)(r[4]+4)); r[5] = r[5] & 0x00FFFFFF; u32 size = r[5]; //gprintf("Decompressed size: %d\n", size); u8* buf1 = (u8*)memalign( 32, size ); if( !buf1 ) { gprintf( "ASH: no memory\n" ); return NULL; } r[3] = (u32)buf1; //out memset( (void*)buf1, 0, size ); //printf("r[3] :%08X\n", r[3]); //printf("\n\n"); r[24] = 0x10; r[28] = s32(*(unsigned int *)(r[4]+8)); r[25] = 0; r[29] = 0; r[26] = s32(*(unsigned int *)(r[4]+0xC)); r[30] = s32(*(unsigned int *)(r[4]+r[28])); r[28] = r[28] + 4; //r[8] = 0x8108<<16; //HACK, pointer to RAM u8* workingBuffer = (u8*)memalign( 32, 0x100000 ); if( !workingBuffer ) { gprintf( "ASH: no memory 2\n" ); free( buf1 ); return NULL; } r[8] = (u32)workingBuffer; memset( (void*)workingBuffer, 0, 0x100000 ); //printf("r[8] :%08X\n", r[8]); r[8] = r[8]; r[9] = r[8] + 0x07FE; r[10] = r[9] + 0x07FE; r[11] = r[10] + 0x1FFE; r[31] = r[11] + 0x1FFE; r[23] = 0x200; r[22] = 0x200; r[27] = 0; loc_81332124: if( r[25] != 0x1F ) goto loc_81332140; r[0] = r[26] >> 31; r[26]= s32(*(unsigned int *)(r[4] + r[24])); r[25]= 0; r[24]= r[24] + 4; goto loc_8133214C; loc_81332140: r[0] = r[26] >> 31; r[25]= r[25] + 1; r[26]= r[26] << 1; loc_8133214C: if( r[0] == 0 ) goto loc_81332174; r[0] = r[23] | 0x8000; *(unsigned short *)(r[31]) = s16(r[0]); r[0] = r[23] | 0x4000; *(unsigned short *)(r[31]+2) = s16(r[0]); r[31] = r[31] + 4; r[27] = r[27] + 2; r[23] = r[23] + 1; r[22] = r[22] + 1; goto loc_81332124; loc_81332174: r[12] = 9; r[21] = r[25] + r[12]; t = r[21]; if( r[21] > 0x20 ) goto loc_813321AC; r[21] = (~(r[12] - 0x20))+1; r[6] = r[26] >> r[21]; if( t == 0x20 ) goto loc_8133219C; r[26] = r[26] << r[12]; r[25] = r[25] + r[12]; goto loc_813321D0; loc_8133219C: r[26]= s32(*(unsigned int *)(r[4] + r[24])); r[25]= 0; r[24]= r[24] + 4; goto loc_813321D0; loc_813321AC: r[0] = (~(r[12] - 0x20))+1; r[6] = r[26] >> r[0]; r[26]= s32(*(unsigned int *)(r[4] + r[24])); r[0] = (~(r[21] - 0x40))+1; r[24]= r[24] + 4; r[0] = r[26] >> r[0]; r[6] = r[6] | r[0]; r[25] = r[21] - 0x20; r[26] = r[26] << r[25]; loc_813321D0: r[12]= s16(*(unsigned short *)(r[31] - 2)); r[31] -= 2; r[27]= r[27] - 1; r[0] = r[12] & 0x8000; r[12]= (r[12] & 0x1FFF) << 1; if( r[0] == 0 ) goto loc_813321F8; *(unsigned short *)(r[9]+r[12]) = s16(r[6]); r[6] = (r[12] & 0x3FFF)>>1; // extrwi %r6, %r12, 14,17 if( r[27] != 0 ) goto loc_813321D0; goto loc_81332204; loc_813321F8: *(unsigned short *)(r[8]+r[12]) = s16(r[6]); r[23] = r[22]; goto loc_81332124; loc_81332204: r[23] = 0x800; r[22] = 0x800; loc_8133220C: if( r[29] != 0x1F ) goto loc_81332228; r[0] = r[30] >> 31; r[30]= s32(*(unsigned int *)(r[4] + r[28])); r[29]= 0; r[28]= r[28] + 4; goto loc_81332234; loc_81332228: r[0] = r[30] >> 31; r[29]= r[29] + 1; r[30]= r[30] << 1; loc_81332234: if( r[0] == 0 ) goto loc_8133225C; r[0] = r[23] | 0x8000; *(unsigned short *)(r[31]) = s16(r[0]); r[0] = r[23] | 0x4000; *(unsigned short *)(r[31]+2) = s16(r[0]); r[31] = r[31] + 4; r[27] = r[27] + 2; r[23] = r[23] + 1; r[22] = r[22] + 1; goto loc_8133220C; loc_8133225C: r[12] = 0xB; r[21] = r[29] + r[12]; t = r[21]; if( r[21] > 0x20 ) goto loc_81332294; r[21] = (~(r[12] - 0x20))+1; r[7] = r[30] >> r[21]; if( t == 0x20 ) goto loc_81332284; r[30] = r[30] << r[12]; r[29] = r[29] + r[12]; goto loc_813322B8; loc_81332284: r[30]= s32(*(unsigned int *)(r[4] + r[28])); r[29]= 0; r[28]= r[28] + 4; goto loc_813322B8; loc_81332294: r[0] = (~(r[12] - 0x20))+1; r[7] = r[30] >> r[0]; r[30]= s32(*(unsigned int *)(r[4] + r[28])); r[0] = (~(r[21] - 0x40))+1; r[28]= r[28] + 4; r[0] = r[30] >> r[0]; r[7] = r[7] | r[0]; r[29]= r[21] - 0x20; r[30]= r[30] << r[29]; loc_813322B8: r[12]= s16(*(unsigned short *)(r[31] - 2)); r[31] -= 2; r[27]= r[27] - 1; r[0] = r[12] & 0x8000; r[12]= (r[12] & 0x1FFF) << 1; if( r[0] == 0 ) goto loc_813322E0; *(unsigned short *)(r[11]+r[12]) = s16(r[7]); r[7] = (r[12] & 0x3FFF)>>1; // extrwi %r7, %r12, 14,17 if( r[27] != 0 ) goto loc_813322B8; goto loc_813322EC; loc_813322E0: *(unsigned short *)(r[10]+r[12]) = s16(r[7]); r[23] = r[22]; goto loc_8133220C; loc_813322EC: r[0] = r[5]; loc_813322F0: r[12]= r[6]; loc_813322F4: if( r[12] < 0x200 ) goto loc_8133233C; if( r[25] != 0x1F ) goto loc_81332318; r[31] = r[26] >> 31; r[26] = s32(*(unsigned int *)(r[4] + r[24])); r[24] = r[24] + 4; r[25] = 0; goto loc_81332324; loc_81332318: r[31] = r[26] >> 31; r[25] = r[25] + 1; r[26] = r[26] << 1; loc_81332324: r[27] = r[12] << 1; if( r[31] != 0 ) goto loc_81332334; r[12] = s16(*(unsigned short *)(r[8] + r[27])); goto loc_813322F4; loc_81332334: r[12] = s16(*(unsigned short *)(r[9] + r[27])); goto loc_813322F4; loc_8133233C: if( r[12] >= 0x100 ) goto loc_8133235C; *(unsigned char *)(r[3]) = r[12]; r[3] = r[3] + 1; r[5] = r[5] - 1; if( r[5] != 0 ) goto loc_813322F0; goto loc_81332434; loc_8133235C: r[23] = r[7]; loc_81332360: if( r[23] < 0x800 ) goto loc_813323A8; if( r[29] != 0x1F ) goto loc_81332384; r[31] = r[30] >> 31; r[30] = s32(*(unsigned int *)(r[4] + r[28])); r[28] = r[28] + 4; r[29] = 0; goto loc_81332390; loc_81332384: r[31] = r[30] >> 31; r[29] = r[29] + 1; r[30] = r[30] << 1; loc_81332390: r[27] = r[23] << 1; if( r[31] != 0 ) goto loc_813323A0; r[23] = s16(*(unsigned short *)(r[10] + r[27])); goto loc_81332360; loc_813323A0: r[23] = s16(*(unsigned short *)(r[11] + r[27])); goto loc_81332360; loc_813323A8: r[12] = r[12] - 0xFD; r[23] = ~r[23] + r[3] + 1; r[5] = ~r[12] + r[5] + 1; r[31] = r[12] >> 3; if( r[31] == 0 ) goto loc_81332414; count = r[31]; loc_813323C0: r[31] = *(unsigned char *)(r[23] - 1); *(unsigned char *)(r[3]) = r[31]; r[31] = *(unsigned char *)(r[23]); *(unsigned char *)(r[3]+1) = r[31]; r[31] = *(unsigned char *)(r[23] + 1); *(unsigned char *)(r[3]+2) = r[31]; r[31] = *(unsigned char *)(r[23] + 2); *(unsigned char *)(r[3]+3) = r[31]; r[31] = *(unsigned char *)(r[23] + 3); *(unsigned char *)(r[3]+4) = r[31]; r[31] = *(unsigned char *)(r[23] + 4); *(unsigned char *)(r[3]+5) = r[31]; r[31] = *(unsigned char *)(r[23] + 5); *(unsigned char *)(r[3]+6) = r[31]; r[31] = *(unsigned char *)(r[23] + 6); *(unsigned char *)(r[3]+7) = r[31]; r[23] = r[23] + 8; r[3] = r[3] + 8; if( --count ) goto loc_813323C0; r[12] = r[12] & 7; if( r[12] == 0 ) goto loc_8133242C; loc_81332414: count = r[12]; loc_81332418: r[31] = *(unsigned char *)(r[23] - 1); r[23] = r[23] + 1; *(unsigned char *)(r[3]) = r[31]; r[3] = r[3] + 1; if( --count ) goto loc_81332418; loc_8133242C: if( r[5] != 0 ) goto loc_813322F0; loc_81332434: r[3] = r[0]; len = r[3]; //gprintf("Decompressed %d bytes\n", r[3]); free( workingBuffer ); return buf1; }
u8* U8NandArchive::GetFileAllocated( const char *path, u32 *size ) const { //gprintf( "U8NandArchive::GetFileAllocated( %s )\n" ); if( !path || !fst ) { return NULL; } // find file int f = EntryFromPath( path, 0 ); if( f < 1 || f >= (int)fst[ 0 ].filelen ) { gprintf( "U8: \"%s\" wasn't found in the archive.\n", path ); return NULL; } if( fst[ f ].filetype ) { gprintf( "U8: \"%s\" is a folder\n", path ); return NULL; } // create a buffer u8* ret = (u8*)memalign( 32, RU( fst[ f ].filelen, 32 ) ); if( !ret ) { gprintf( "U8: out of memory\n" ); return NULL; } // seek and read if( ISFS_Seek( fd, dataOffset + fst[ f ].fileoffset, SEEK_SET ) != (s32)( dataOffset + fst[ f ].fileoffset ) || ISFS_Read( fd, ret, fst[ f ].filelen ) != (s32)fst[ f ].filelen ) { free( ret ); gprintf( "U8: error reading data from nand\n" ); gprintf( "fd: %i fst[ fd ].filelen: %08x\n", fd, fst[ f ].filelen ); return NULL; } u32 len = fst[ f ].filelen; u8* ret2; // determine if it needs to be decompressed if( IsAshCompressed( ret, len ) ) { // ASH0 ret2 = DecompressAsh( ret, len ); if( !ret2 ) { free( ret ); gprintf( "out of memory\n" ); return NULL; } free( ret ); } else if( isLZ77compressed( ret ) ) { // LZ77 with no magic word if( decompressLZ77content( ret, len, &ret2, &len ) ) { free( ret ); return NULL; } free( ret ); } else if( *(u32*)( ret ) == 0x4C5A3737 )// LZ77 { // LZ77 with a magic word if( decompressLZ77content( ret + 4, len - 4, &ret2, &len ) ) { free( ret ); return NULL; } free( ret ); } else { // already got what we are after ret2 = ret; } if( size ) { *size = len; } // flush the cache so if there are any textures in this data, it will be ready for the GX DCFlushRange( ret2, len ); return ret2; }
u8* U8Archive::GetFileAllocated( const char *path, u32 *size ) const { u32 len; const u8 *stuff = GetFile( path, &len ); if( !stuff ) { return NULL; } // check for IMD5 header and skip it if( len > 0x40 && *(u32*)stuff == 0x494d4435 )// IMD5 { stuff += 0x20; len -= 0x20; } u8* ret = NULL; // determine if it needs to be decompressed if( IsAshCompressed( stuff, len ) ) { //u32 len2 = len; // ASH0 ret = DecompressAsh( stuff, len ); if( !ret ) { gprintf( "out of memory\n" ); return NULL; } /* u8* ret2 = DecompressAsh2( stuff, len2 ); if( !ret2 ) { gprintf( "out of memory 2\n" ); return NULL; } if( len != len2 || memcmp( ret, ret2, len ) ) { gprintf( "doesn\'t match\n" ); } else { gprintf( "matches\n" ); } exit( 0 );*/ } else if( isLZ77compressed( stuff ) ) { // LZ77 with no magic word if( decompressLZ77content( stuff, len, &ret, &len ) ) { return NULL; } } else if( *(u32*)( stuff ) == 0x4C5A3737 )// LZ77 { // LZ77 with a magic word if( decompressLZ77content( stuff + 4, len - 4, &ret, &len ) ) { return NULL; } } else { // just copy the data out of the archive ret = (u8*)memalign( 32, len ); if( !ret ) { gprintf( "out of memory\n" ); return NULL; } memcpy( ret, stuff, len ); } if( size ) { *size = len; } // flush the cache so if there are any textures in this data, it will be ready for the GX DCFlushRange( ret, len ); return ret; }
u8 *U8Archive::DecompressCopy( const u8 * stuff, u32 len, u32 *size ) const { // check for IMD5 header and skip it if( len > 0x40 && *(u32*)stuff == 0x494d4435 )// IMD5 { stuff += 0x20; len -= 0x20; } u8* ret = NULL; // determine if it needs to be decompressed if( IsAshCompressed( stuff, len ) ) { //u32 len2 = len; // ASH0 ret = DecompressAsh( stuff, len ); if( !ret ) { gprintf( "out of memory\n" ); return NULL; } } else if( (len > 8) && *(u32*)( stuff ) == 0x59617a30 )// Yaz0 { // Yaz0 with a magic word Yaz0_Header *header = (Yaz0_Header *) stuff; // set decompress length len = header->decompressed_size; // allocate memory ret = (u8*) memalign(32, ALIGN32(len)); if(!ret) { gprintf("out of memory\n"); return NULL; } // function can not fail at this point uncompressYaz0(stuff, ret, len); } else if( isLZ77compressed( stuff ) ) { // LZ77 with no magic word if( decompressLZ77content( stuff, len, &ret, &len ) ) { return NULL; } } else if( *(u32*)( stuff ) == 0x4C5A3737 )// LZ77 { // LZ77 with a magic word if( decompressLZ77content( stuff + 4, len - 4, &ret, &len ) ) { return NULL; } } else { // just copy the data out of the archive ret = (u8*)memalign( 32, ALIGN32( len ) ); if( !ret ) { gprintf( "out of memory\n" ); return NULL; } memcpy( ret, stuff, len ); } if( size ) { *size = len; } // flush the cache so if there are any textures in this data, it will be ready for the GX DCFlushRange( ret, len ); return ret; }
u8* DecompressAsh( const u8 *stuff, u32 &len ) { if( !IsAshCompressed( stuff, len ) ) { return NULL; } u32 r[32]; u32 t; r[4] = (u32)stuff; //in r[5] = *(u32*)( r[4] + 4 ); r[5] = r[5] & 0x00FFFFFF; u32 size = r[5]; //gprintf("Decompressed size: %d\n", size); u8* buf1 = (u8*)memalign( 32, size ); if( !buf1 ) { gprintf( "ASH: no memory\n" ); return NULL; } r[3] = (u32)buf1; //out //memset( (void*)buf1, 0, size ); //printf("r[3] :%08X\n", r[3]); //printf("\n\n"); r[24] = 0x10; r[28] = *(u32 *)(r[4]+8); r[25] = 0; r[29] = 0; r[26] = *(u32 *)(r[4]+0xC); r[30] = *(u32 *)(r[4]+r[28]); r[28] = r[28] + 4; //r[8] = 0x8108<<16; //HACK, pointer to RAM u8* workingBuffer = (u8*)memalign( 32, MAX( 0x100000, size ) ); if( !workingBuffer ) { gprintf( "ASH: no memory 2\n" ); free( buf1 ); return NULL; } r[8] = (u32)workingBuffer; //memset( (void*)workingBuffer, 0, 0x100000 ); r[9] = r[8] + 0x07FE; r[10] = r[9] + 0x07FE; r[11] = r[10] + 0x1FFE; r[31] = r[11] + 0x1FFE; r[23] = 0x200; r[22] = 0x200; r[27] = 0; while( 1 ) { // loc_81332124: r[0] = r[26] >> 31; if( r[25] != 0x1F ) { // loc_81332140: r[25]++; r[26] <<= 1; } else { // 8133212C r[26]= *(u32 *)( r[4] + r[24] ); r[25]= 0; r[24] += 4; } // loc_8133214C: if( r[0] ) { // 81332150 *(u16*)( r[31] ) = r[23] | 0x8000; *(u16*)( r[31] + 2 ) = r[23] | 0x4000; r[31] += 4; r[27] += 2; r[23]++; r[22]++; continue; } // loc_81332174: r[21] = r[25] + 9; t = r[21]; if( r[21] > 0x20 ) { // loc_813321AC: r[0] = 0x17; r[6] = r[26] >> r[0]; r[26]= *(u32*)( r[4] + r[24 ]); r[0] = (~(r[21] - 0x40))+1; r[24] += 4; r[0] = r[26] >> r[0]; r[6] |= r[0]; r[25] = r[21] - 0x20; r[26] = r[26] << r[25]; } else {