I got it now. I wasn't saving the exe :v: The fact it says it extended it after you choose to do so gave me the impression it's done and that's it, only occurred to me to actually look at the exe size to see if it's actually being extended, which it wasn't.
Curiousness: I nabbed the EU version on eBay a few years ago. Playing through it, I was surprised that when I wound up in the Past, that percussive track used at the echidna temple was noticeably faster compared to the tempo of the Mystic Ruins theme. I've assumed it was something to do with the "NTSC stuff is faster on PAL to compensate" business that would have been needed for the original console version. I've been curious to find a US Version of whatever file (forget the name) that contains the Past track to see if the conversion theory is the case. Any guesses or confirmation?
Ah, much thanks. Now to reinstall the game after a fresh reboot. :v: Update: Well, they're one in the same. Sorry for the waste of time. I guess the speed difference just isn't that noticeable until the Mystic Ruins theme gets pounded into your head from continuous game playing.
Updated obj2nj, SADXMDL and SADXLVL, they stored colors from obj imports backwards before. I also ported a feature from SADXMDL to SADXLVL: clicking on the color preview for diffuse or specular in the Material Editor displays the Microsoft color picker dialog. And I got tired of SADXLVL having version numbers that are just made up, so now releases with new features are +1, and releases with only bugfixes are +0.1. I'm starting with 34.0, based on the version history from the wiki page, and adding 5 for the releases before that aren't listed.
1)It looks like SADXLVL is incompatible with SADX MIP pack. Previously after selecting a level to edit I every time got a an "example of object doesn't contain a reference to an object" error: but some guy give me advice to use non-mipmap textures, and almost everything worked fine since that. 2)How can I edit water and sea bottom in SADXLVL? 3)There are some strange level part I cannot do anything with. I can't see it in SADXLVL. Looks like, as Sonic's blue half-opaque shield, it doesn't have any texture at all... EDIT: OK, I can delete it with along with some near level parts...
This is known, and is actually the reason 'clear level' function breaks emerald coast. The only suggestion I can give to you is to rip the level using another tool, find those objects and clear them out using a quick little hex hack or something (like zeroing the mesh and material numbers).
Water is usually an invisible flat model with the Water flag (0x00000002) set, and everything between the model and the next solid model/object is underwater. You'll see them if you press 'B' or use the dropdown in the view menu. The part you see ingame is usually an object loaded by the level.
SADXsnd is very limited. It can only extract/pack an entire archive at once, and it's a command line program. So I looked at the source, and wrote SADXsndSharp in C# 2008. With it, you can view, add, remove, replace and extract any files from a DAT archive by right clicking on it in the list view. Credit to Tux/SANiK for SADXsnd.
For those of you who don't check the Community SVN Project forum often, I'll let you know that I've committed Sonic Adventure Tools and the decompilation of CHRMODELS.DLL from SADX PC. As a courtesy, I'm providing you with a build of the "new" CHRMODELS.DLL. It should be stable, but if you encounter any problems with it, go to the Sonic Adventure Tools topic and post about it there (how to reproduce, what happens).
And related to that, I'm giving you two things: SAM Ripper converts a model tree and animations into a .sam file. SADXMDL2, which edits .sam files. It has the same features as SADXMDL, but can also add and remove models in the tree, and can export to C files for compiling with the MSVC project on the SVN. However, it does not yet export animations, so if you add/remove models, you'll have to edit the C files for the animations manually.
I've got a little problem with SADXMDL and SADXMDL2. Both of them don't show the models when I load them. It's just black.
Unfortunately, I have no idea what could be causing that. Here's something found by Highter from TiggoMods (don't go there): Metal Sonic's voice files! In system\sounddata\voice_us\wma, 2044.wma = Y_MS_CLEAR - Level clear 2045.wma = Y_MS_DAMAGE - Hurt 2046.wma = Y_MS_DEAD - Death 2047.wma = Y_MS_SELECT - Character select 2048.wma = Y_MS_START - Unused? Note: the uppercase part in the middle is the GC filename from EVENT_ADX_E.AFS.
Haha, who knew the code was already there, and the files were just missing. Anywho, while I track down the GC version and rip these files myself just to spite that guy, have an alternate set of Metal Sonic sounds ripped from Rivals 2 Just drop them in the relevant folder. Already converted and shiz
MainMemory sent me the decompress routine that the SADX installer supposedly uses. So here is a simple program that does the decompression. Rename the input file to in.dll. Code (Text): #include <stdio.h> #include <stdlib.h> #include <string.h> #define __ //For posting on forum. Do a CTRL+F to get rid of it. void DecompressBuffer(unsigned char *DecompressedBuffer, unsigned char *CompressedBuffer /*Starting at + 20*/, int DecompressedSize) { __ unsigned char *CompressedBufferPointer = CompressedBuffer; __ unsigned char *DecompressedBufferPointer = DecompressedBuffer; __ //Create sliding dictionary buffer and clear first 4078 bytes of dictionary buffer to 0 __ unsigned char *SlidingDictionary = malloc(4096); __ memset(SlidingDictionary, 0, 4096); __ //Set an offset to the dictionary insertion point __ unsigned int DictionaryInsertionOffset = 4078; __ //Decompression command __ unsigned char CommandCounter = 0; __ unsigned char DecompressCommand = 0; __ while(DecompressedSize) __ { __ __ //Is the decompress counter zero? Load the command __ __ if(CommandCounter == 0) __ __ { __ __ __ CommandCounter = 8; //Each command has 8 sub commands, one bit per command __ __ __ DecompressCommand = *CompressedBufferPointer++; __ __ } __ __ //Each command is a byte and is actually composed of 8 sub commands __ __ //A bit of 1 means to copy the byte exactly as it is, and add it to the dictionary __ __ //A bit of 0 means to load a special encoded format describing a repetition. __ __ if(DecompressCommand & 1) __ __ { __ __ __ //Copy the byte exactly over __ __ __ unsigned char RawByte = *CompressedBufferPointer++; __ __ __ *DecompressedBufferPointer++ = RawByte; __ __ __ //Add the byte to the dictionary __ __ __ SlidingDictionary[DictionaryInsertionOffset] = RawByte; __ __ __ DictionaryInsertionOffset = (DictionaryInsertionOffset + 1) & 0xFFF; //Slide the dictionary __ __ __ DecompressedSize--; __ __ } __ __ else __ __ { __ __ __ //The sub command tells us there is a repetition __ __ __ //unsigned short RepetitionCode=(CompressedBufferPointer[1] << 8) | CompressedBufferPointer[0]; __ __ __ unsigned char CurrentByte = CompressedBufferPointer[0]; __ __ __ unsigned char NextByte = CompressedBufferPointer[1]; //Lower nibble is the repetition count or RunLength __ __ __ CompressedBufferPointer+=2; __ __ __ //Calculate the offset of the byte to use in the sliding dictionary __ __ __ int DictionaryOffset = ((NextByte & 0xF0) << 4) | CurrentByte; __ __ __ //It is not really run length compression, but instead it is a dictionary based method __ __ __ //I just ran out of ideas what to name the variables __ __ __ int RunCounter = 0; __ __ __ int RunLength = (NextByte & 0xF) + 3; //Compression defines a repetition to be at minimum three bytes __ __ __ while ( RunCounter < RunLength) __ __ __ { __ __ __ __ unsigned char RawByte = SlidingDictionary[((RunCounter + DictionaryOffset) & 0xFFF)]; __ __ __ __ *DecompressedBufferPointer++ = RawByte; __ __ __ __ DecompressedSize--; __ __ __ __ if(DecompressedSize <= 0) __ __ __ __ { __ __ __ __ __ free(SlidingDictionary); //Terminate __ __ __ __ __ return; __ __ __ __ } __ __ __ __ //Add the byte to the dictionary __ __ __ __ SlidingDictionary[DictionaryInsertionOffset] = RawByte; __ __ __ __ DictionaryInsertionOffset = (DictionaryInsertionOffset + 1) & 0xFFF; //Slide the dictionary __ __ __ __ RunCounter++; __ __ __ } __ __ } __ __ //Rotate the sub command __ __ CommandCounter--; __ __ DecompressCommand >>= 1; __ } __ free(SlidingDictionary); __ return; } int isFileCompressed(unsigned char *CompressedBuffer) { __ return !strcmp(CompressedBuffer, "compress v1.0"); } void ProcessBuffer(unsigned char *Name, unsigned char *CompressedBuffer, int CompressedSize) { __ if ( CompressedBuffer ) __ { __ __ if ( isFileCompressed(CompressedBuffer) ) __ __ { __ __ __ int DecompressedSize = *(unsigned int*)(&CompressedBuffer[16]); __ __ __ unsigned char *DecompressedBuffer = malloc(DecompressedSize); __ __ __ if ( DecompressedBuffer ) __ __ __ { __ __ __ __ //Xor Decrypt the whole buffer __ __ __ __ unsigned char XorEncryptionValue = CompressedBuffer[15]; __ __ __ __ unsigned int I=0; __ __ __ __ while(I < CompressedSize) __ __ __ __ { __ __ __ __ __ CompressedBuffer[I] ^= XorEncryptionValue; __ __ __ __ __ I++; __ __ __ __ } __ __ __ __ //Decompress the whole buffer __ __ __ __ DecompressBuffer(DecompressedBuffer, &CompressedBuffer[20], DecompressedSize); __ __ __ __ //Switch the buffers around so the decompressed one gets saved instead __ __ __ __ CompressedBuffer=DecompressedBuffer; __ __ __ __ CompressedSize=DecompressedSize; __ __ __ } __ __ } __ __ //Save file __ __ FILE *fout=fopen(Name, "wb"); __ __ fwrite(CompressedBuffer, CompressedSize, 1, fout); __ __ fclose(fout); __ } } int main() { __ FILE *fin=fopen("in.dll", "rb"); __ fseek(fin, 0, SEEK_END); __ int CompressedSize=ftell(fin); __ fseek(fin, 0, SEEK_SET); __ void *CompressedBuffer=malloc(CompressedSize); __ fread(CompressedBuffer, CompressedSize, 1, fin); __ fclose(fin); __ ProcessBuffer("out.dll",CompressedBuffer, CompressedSize); __ return -1; } The file format is as so: At 0, there is a 14 byte null terminated string, "compress v1.0", no quotations. 14 is 0. 15 is a byte that is the xor encryption password. Like MainMemory said, at 16 there is a dword denoting the decompressed file size. At 20 is where the data starts. To read the data you must xor the whole file or at least the data and on portion with the xor encryption password, byte by byte. C xor operator is ^. The data consists of packets. The first byte of each packet is a byte command. Each packet, excluding the command byte, can be divided into eight uneven sections. Each bit of the command denotes what operation to do for each of the sections. The first lower bit of the command byte corresponds to the first section after the command byte. The second lower bit corresponds to the section after the first section, etc. If the command bit is 1 for the section, it means the section is only one byte, and so it gets copied to the decompression file. It also gets put into a sliding dictionary. If the command bit is a 0 for the section, it means the section is two bytes, and the two bytes describe an address in the sliding dictionary and the number of bytes to copy to the decompressed file from the sliding dictionary. The format of the two bytes is as so: 0xLL 0xHK Address In Sliding Dictionary where to start copying from = 0xHLL Number of bytes to copy from sliding dictionary = 3 + 0xK When copying from the sliding dictionary to the decompressed file, you must do the copy byte by byte because each copy also re-adds the value to the sliding dictionary. So it has a feedback loop that would desynchronize the sliding dictionary if one did a batch copy in one shot. The sliding table is 4096 bytes in size, and each byte is initialized to 0 at start up. The sliding table's insertion pointer is at 4078 on startup and for each byte insertion it increments by one. If it is >= 4096, it rolls over to 0. (This is what the & 0xFFF does).
Thanks for that SANiK, now SADXsndSharp can decompress files from system.dat on disc 1. Compressed files show up with blue names, and they're decompressed automatically on extracting. Turns out that everything but the MPG files are compressed.
I've located the code that sets the checksum for Chao save files, and converted it to C# (source included). If you run this program after editing the file, SADX won't crash. The save file has the same layout as it does in RAM.
Sorry for the triple post, but I've now got the checksum code for the normal save files, and converted it to C#. So now we can edit the save files. I don't know what's what in the save file yet, but filling it with 00 locks everything, even Sonic. Edit: SCHG:Sonic Adventure DX: PC/Save Files