Author
|
Topic: GraphiX3 (Read 2 times)
|
elixirnova
Guest
|
|
« on: July 13, 2008, 01:27:59 am » |
|
Alright so :cookie: I will probably upload a copy if anyone wants to play with tomorrow as it is 1AM here right now... But here is a screen shot of my hours of learning the syntax of C++.NET 2003 as opposed to c++ 6.0 I was using.... :banghead: I wrote a mega man x3 windows application to import/export the compressed graphics. It has an option to export/import multiple files and one large file. Not done with the export function yet, but import works fine and I'll get a screen shot of that tomorrow! As for now here is the first screen shot.... hopefully I get rid of the gaudiness by then too... EDIT: Here is the link to the latest build v0.8 http://www.geocities.com/elixirnova/graphiX3.zip
|
|
« Last Edit: July 20, 2008, 07:15:03 pm by elixirnova »
|
|
|
|
Solid One
Guest
|
|
« Reply #1 on: July 13, 2008, 09:15:14 am » |
|
great job! this tool will be very useful. keep up with the good work .
|
|
|
|
elixirnova
Guest
|
|
« Reply #2 on: July 13, 2008, 01:30:37 pm » |
|
Alright if you want to see what it can do you must have a MegaMan X3 (U) rom. I believe the rom must be HEADERLESS. Because I did not write anything to remove a header from the rom yet. The program will expand your ROM to 4MB and move all the compressed graphics upon opening. The only feature so far is multi file export and it does not export the last couple of graphic files at the moment, but in due time... I'm just throwing this out because I only get time on weekends to really work on it. Enjoy my progress of being able to export about 215 blocks of graphics! http://www.geocities.com/elixirnova/gfX3.zipIf anyone can guide me to a good way of validating that the ROM the user selects is indeed a megaman X3 ROM I would be pretty happy! Maybe I need a new topic for that... But I also need to figure out what CheckSUMS are about as I did not find any documents at first glance on the topic.. Any comments or suggestions are appreciated. Plus I do realize that not all the decompressed data looks like graphics... I haven't looked into that yet... Edit: I just added export all gfx to a single file... and a cool lookin progress bar since it might take a couple seconds to decompress all of it. I suppose recompress options are the next steps....
|
|
« Last Edit: July 20, 2008, 07:15:43 pm by elixirnova »
|
|
|
|
creaothceann
Guest
|
|
« Reply #3 on: July 13, 2008, 03:31:54 pm » |
|
Just take all the ROMS that NSRT thinks are good and include their CRC32s into the program. You can find a standard CRC32 function (to check the user's ROM) in the emulator source codes.
|
|
|
|
|
Lenophis
Guest
|
|
« Reply #5 on: July 14, 2008, 01:26:29 pm » |
|
I believe the rom must be HEADERLESS. Because I did not write anything to remove a header from the rom yet. Why is supporting both such a foreign idea to a lot of people? :huh:
|
|
|
|
Rockman
Guest
|
|
« Reply #6 on: July 14, 2008, 02:43:36 pm » |
|
elixirnova, it looks cool. I love the Super NES MMX games. Dude, I haven't seen you in a long time. How have you been?
|
|
|
|
tc
Guest
|
|
« Reply #7 on: July 14, 2008, 05:09:58 pm » |
|
Definitely, great series. I suppose the general concept of this might work for other SNES MM games too.
|
|
|
|
creaothceann
Guest
|
|
« Reply #8 on: July 14, 2008, 05:53:56 pm » |
|
I believe the rom must be HEADERLESS. Because I did not write anything to remove a header from the rom yet. Why is supporting both such a foreign idea to a lot of people? :huh: Saves writing a couple of lines, I'd guess. Anyway, headerless ftw.
|
|
|
|
Aerdan
Guest
|
|
« Reply #9 on: July 14, 2008, 09:05:00 pm » |
|
Yes, because subtracting 512 from the file address is so bloody difficult.
|
|
|
|
elixirnova
Guest
|
|
« Reply #10 on: July 14, 2008, 10:56:40 pm » |
|
Yea, I suppose I just rank checksum verification and header/headerless support below the rest of the functions.... Next time I will probably upload a version with the recompression feature working. THEN maybe the CRC and header/headerless support...
|
|
|
|
creaothceann
Guest
|
|
« Reply #11 on: July 15, 2008, 05:48:46 am » |
|
Yes, because subtracting 512 from the file address is so bloody difficult.
If you separate the file into "header" and "ROM" then you don't even have to do that every time. The header only has to be handled by the file loader / saver.
|
|
|
|
elixirnova
Guest
|
|
« Reply #12 on: July 16, 2008, 01:05:07 am » |
|
Alright so I wrote all the code to use the compression routine I had. It inserts the re-compressed graphics into the ROM. It puts them all into their correct locations. The only problem is nothing in the game works.... All the rest of the code is untouched.... It is sounding to me like something is wrong with the re-compression since all of the decompressed graphics look great. Alright I messed around with the problem and am pretty sure the compression routine isn't doing something right.... If anyone is interested here is the function for recompress and insert: private: System::Void menuItem9_Click(System::Object * sender, System::EventArgs * e) { //////////////////////////////// // Insert Single File // ////////////////////////////////
// Initialize progress bar progressBar1->Maximum = 217; progressBar1->Value = 0; progressBar1->Visible = true;
// Buffers System::Byte pTable[] = __gc new System::Byte[0x451]; System::Byte decompBuf[] = __gc new System::Byte[0x10000]; System::Byte compBuf[] = __gc new System::Byte[0x10000];
// Variables int i; int q; int decompLen; int decompPos = 0; int compLen; int address;
// Open Rom Stream for read/edit FileStream *romStream = __gc new FileStream(statusBarPanel1->Text, FileMode::Open); FileStream *gfxStream = __gc new FileStream("allGFX.bin", FileMode::Open);
// Open Binary Reader BinaryReader *romReader = __gc new BinaryReader(romStream); BinaryReader *gfxReader = __gc new BinaryReader(gfxStream); BinaryWriter *romWriter = __gc new BinaryWriter(romReader->BaseStream);
// Load pointer table romReader->BaseStream->Seek(0x37732,Begin); pTable = romReader->ReadBytes(0x451);
// loop to compress and write each block to ROM for (i = 0; i < 218; i ++) { // Read predetermined length of graphic block based on pointer table length decompLen = pTable[(i*5) + 4] * 0x100 + pTable[(i*5) + 3];
// Read 4BPP gfx to buffer gfxReader->BaseStream->Seek(decompPos,Begin); gfxReader->Read(decompBuf,0,decompLen); // Fill compBuf with blank bytes for (q=0; q < 0x10000; q++) compBuf[q] = 0xFF;
// compress graphics and return compressed gfx block size in bytes compLen = compress(decompBuf, compBuf, decompLen);
// Read current pointer and convert to a ROM address address = pTable[i*5] + (pTable[(i*5) + 1] * 0x100) + (pTable[(i*5) + 2] * 0x10000); address = PCaddress(address); // Convert the loROM address to a pc address // Write block to ROM based on pointer table address romWriter->Seek(address,Begin); romWriter->Write(compBuf,0,compLen);
// Update decompPos decompPos = decompPos + decompLen;
// Update progress bar progressBar1->Value = i; }
// Close streams romStream->Close(); gfxStream->Close();
// Hide progress bar progressBar1->Visible = false; } Also here is the code for the routine compress: public: unsigned int compress(System::Byte readBuf[], System::Byte writeBuf[], unsigned int inputLength) { /* int p; StringBuilder* rBufStr = __gc new StringBuilder(rBuf[0],0x10000); StringBuilder* wBufStr = __gc new StringBuilder(wBuf[0],0x10000); unsigned int temp;
// copy rBuf and wBuf to strings for(p=1; p < 0xFFFF; p++) { temp = rBuf[p]; rBufStr->Append(temp); temp = wBuf[p]; wBufStr->Append(temp); }
unsigned char* readBuf = (unsigned char*)(void*)Marshal::StringToHGlobalAnsi(rBufStr->ToString()); unsigned char* writeBuf = (unsigned char*)(void*)Marshal::StringToHGlobalAnsi(wBufStr->ToString()); */ // I'm using a different bit mask representation than Euclid did in the decompression routine unsigned char mask = 0x80;
unsigned char __gc* ctrlByte;
unsigned int i = 0, j = 0, k = 0; unsigned short matchLen = 0;
unsigned int offset = 0; unsigned int blockSize = 0;
// ------------------------------------------------
// see what the largest number of bytes we can get for this particular location with LZ for(i = 0; i < inputLength; i++) { offset = 0; blockSize = 0;
for(j = 0; j < i; j++) { k = 0; matchLen = 0;
// the compression format cannot reach back any further than 0x3FF bytes in to the buffer if((i - j) > 0x3FF) j = i - 0x3FF;
// the decompression engine is only capable of tracking 6 bits of length for a block while( (readBuf[j + k] == readBuf[i + k]) && (matchLen < 0x3F) ) { if( (i + k) >= inputLength ) break;
matchLen++; k++; }
// new winnar if((matchLen > blockSize) && (matchLen >= 3)) { offset = (i - j); blockSize = matchLen; } } }
ctrlByte = &writeBuf[0]; (*ctrlByte) = 0; // no compression being used at initialization
for(i = 0, k = 1; i < inputLength; i++) { if(!mask) { mask = 0x80; ctrlByte = &writeBuf[k++]; }
if(!blockSize) writeBuf[k++] = readBuf[i]; else { (*ctrlByte) |= mask; // indicate that this series will use LZ
writeBuf[k++] = (blockSize << 2) | (offset >> 8); writeBuf[k++] = offset & 0xFF;
i += blockSize - 1; }
mask >>= 1; } /* // Copy local array back to global array for(p=0; p < 0x10000; p++) { rBuf[p] = readBuf[p]; wBuf[p] = writeBuf[p]; }
Marshal::FreeHGlobal(readBuf); Marshal::FreeHGlobal(writeBuf); */
return k; // Length of compressed graphic block in bytes }
|
|
|
|
elixirnova
Guest
|
|
« Reply #13 on: July 20, 2008, 12:23:16 pm » |
|
:crazy: Alright, I just finished up the import functions that work great. Time to move onto the less fun checksums which doesn't seem too bad if I just learn about it. Also, I want to fix up the GUI so users do not encounter errors and to maybe make it look more pleasing haha. As for the compression routine problems... I just bypassed the routine and wrote my own anti-compression routine for now just to move more towards overall completion of the program! As it turns out it was a good idea. I do however have many plans left to make everything more efficient since the import routines are taking about 10seconds to import all the graphics... which is ok on my 1.8ghz laptop, but i suppose should be lots faster. If anyone has any other ideas on making this program easier or better let me know! I do plan after this project to move into a complete ROM editor and implement the tile arrangement data to make editing the graphics easier, but that could be quite some time away... I am beginning to like C++.net a bit more too haha. EDIT: CRC32 is definitely a pain in the butt so far, so don't expect anything till next weekend at earliest... Pretty Build!! Lets call it v0.8 http://www.geocities.com/elixirnova/graphiX3.zip
|
|
« Last Edit: July 20, 2008, 07:14:41 pm by elixirnova »
|
|
|
|
elixirnova
Guest
|
|
« Reply #14 on: July 22, 2008, 01:58:03 am » |
|
Ok this is as far as I'm going with CRC32 stuff... Here is a link to the best looking class I have found in C++.net ... (and the only) http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=987017&SiteID=1I tried converting a #C.net script and it was useless..... I'm not too sure what to input to it? There are two possible ways to use it supposedly unsigned long CheckSumCRC32::block_checksum(const void* data, const int& data_len) inline unsigned long operator()(const void* data, const int& data_len) can't say I understand either... and don't have the desire to learn anymore about this... If anyone wants to help me on this one I'll surely add some NSRT database checking and stuff to get good file verification until then I do not care if you have to remove the header or what not... I believe I'm going to go ahead and start working on a complete ROM editor and release this as is..
|
|
|
|
|