/*
PUT this in the same directory as the asset files of MegaMan Unlimited
PRAISE be to lodepng http://lodev.org/lodepng/
*/
#include <iostream>
#include <fstream>
#include "lodepng.h"
using namespace std;
int cutscenesCount = 0, gameobjectsCount = 0, levelartCount = 0, menusCount = 0, miscCount = 0, gunsCount;
void encodeOneStep(const char* filename, vector<unsigned char>& image, unsigned width, unsigned height){
unsigned error = lodepng::encode(filename, image, width, height);
if (error) cout << "encoder error " << error << ": "<< lodepng_error_text(error) << endl;}
unsigned int get2(fstream* bin){
int ret = 0;
for (int shift = 0;;shift += 7){
int byte = bin->get();
ret += byte<<shift;
if (byte >= 0x80) ret -= 128<<shift;
else break;}
return ret;}
void dumpImage8(fstream* bin, unsigned char* pal){
for(int i = 0; i < 256; i++){
bin->seekg(2, ios_base::cur);
for(int j = 0; j < 3; j++){
bin->seekg(1, ios_base::cur);
pal[3*i + j] = get2(bin);}}
bin->seekg(0x1D, ios_base::cur);
unsigned width = get2(bin);
bin->seekg(0x1, ios_base::cur);
unsigned height = get2(bin);
bin->seekg(0x7, ios_base::cur);
vector<unsigned char> image;
image.resize(width*height*4);
for(unsigned y = 0; y < height; y++)
for(unsigned x = 0; x < width; x++){
unsigned char pixel = bin->get();
image[4*width*y + 4*x + 0] = pal[pixel*3 + 0];
image[4*width*y + 4*x + 1] = pal[pixel*3 + 1];
image[4*width*y + 4*x + 2] = pal[pixel*3 + 2];
image[4*width*y + 4*x + 3] = 255;}
bin->seekg(0x6, ios_base::cur);
int namelen = bin->get();
char* filename = new char[namelen+1]; filename[namelen] = 0x00;
bin->read(filename,namelen);
cout << dec << noshowbase << width << "x" << height << " "
<< hex << showbase << uppercase << bin->tellg() << " " << filename << endl;
for (int i = 0; i < namelen; i++)
if (filename[i] == '\\' || filename[i] == '/')
filename[i] = '-';
encodeOneStep(filename, image, width, height);
delete[] filename;}
void extractImages8(const char* filename, int* inc){
fstream asset(filename, ios::in|ios::binary);
asset.seekg(0, ios_base::beg);
unsigned char* palette = new unsigned char[768];
for (;;){
if (!asset) break;
if (asset.get() != static_cast<unsigned char>(0x10)) continue;
if (asset.get() != static_cast<unsigned char>(0x08)) continue;
if (asset.get() != static_cast<unsigned char>(0x80)) continue;
if (asset.get() != static_cast<unsigned char>(0x02)) continue;
dumpImage8(&asset, palette);
*inc += 1;}
asset.close();
delete[] palette;}
void dumpImage32(fstream* bin, int* inc, bool hasName = true){
bin->seekg(1, ios_base::cur);
unsigned width = get2(bin);
bin->seekg(1, ios_base::cur);
unsigned height = get2(bin);
bin->seekg(1, ios_base::cur); get2(bin);
bin->seekg(1, ios_base::cur); get2(bin);
vector<unsigned char> image;
image.resize(width*height*4);
for(unsigned y = 0; y < height; y++)
for(unsigned x = 0; x < width; x++)
for(int channel = 0; channel < 4; channel++)
image[4*width*y + 4*x + channel] = bin->get();
if (hasName == true){
bin->seekg(1, ios_base::cur); get2(bin);
bin->seekg(1, ios_base::cur); get2(bin);
bin->seekg(1, ios_base::cur);
int namelen = bin->get();
char* filename = new char[namelen+1];
filename[namelen] = 0x00;
bin->read(filename,namelen);
cout << dec << noshowbase << width << "x" << height << " "
<< hex << showbase << uppercase << bin->tellg() << " " << filename << endl;
for (int i = 0; i < namelen; i++)
if (filename[i] == '\\' || filename[i] == '/')
filename[i] = '-';
encodeOneStep(filename, image, width, height);
delete[] filename;}
else{
char filename[6] = {49 + *inc, '.', 'p', 'n', 'g', '\0'};
encodeOneStep(filename, image, width, height);}}
void extractImages32(const char* filename, int* inc, bool hasName = true){
fstream asset(filename, ios::in|ios::binary);
asset.seekg(0, ios_base::beg);
for (;;){
if (!asset) break;
if (asset.get() != static_cast<unsigned char>(0x80)) continue;
if (asset.get() != static_cast<unsigned char>(0xF8)) continue;
if (asset.get() != static_cast<unsigned char>(0x0F)) continue;
dumpImage32(&asset, inc, hasName);
*inc += 1;}
asset.close();}
void extractSound(const char* filename, int* inc, unsigned init = 0, unsigned atrimoden = 0xFFFFFFFF){
fstream asset(filename, ios::in|ios::binary);
asset.seekg(init, ios_base::beg);
for (;;){
if (!asset) break;
if (asset.tellg() >= atrimoden) return;
cout << hex << asset.tellg() << " ";
asset.seekg(1, ios_base::cur); get2(&asset);
asset.seekg(1, ios_base::cur); get2(&asset);
asset.seekg(1, ios_base::cur);
int namelen = get2(&asset);
char* outname = new char[namelen+1];
outname[namelen] = 0x00;
asset.read(outname,namelen);
for (int i = 0; i < namelen; i++)
if (outname[i] == '\\' || outname[i] == '/')
outname[i] = '-';
fstream out(outname, ios::out|ios::binary);
cout << outname << endl;
int isWav = outname[namelen-1] == 'v';
if (isWav){
asset.seekg(1, ios_base::cur); get2(&asset);}
asset.seekg(1, ios_base::cur);
int songSize = get2(&asset);
if (isWav){
long temp = 0x46464952; out.write(reinterpret_cast<char*>(&temp), 4);
temp = songSize + 36; out.write(reinterpret_cast<char*>(&temp), 4);
temp = 0x45564157; out.write(reinterpret_cast<char*>(&temp), 4);
temp = 0x20746D66; out.write(reinterpret_cast<char*>(&temp), 4);
temp = 0x00000010; out.write(reinterpret_cast<char*>(&temp), 4);
temp = 0x00020001; out.write(reinterpret_cast<char*>(&temp), 4);
temp = 44100; out.write(reinterpret_cast<char*>(&temp), 4);
temp *= 4; out.write(reinterpret_cast<char*>(&temp), 4);
temp = 0x00100004; out.write(reinterpret_cast<char*>(&temp), 4);
temp = 0x61746164; out.write(reinterpret_cast<char*>(&temp), 4);
temp = songSize; out.write(reinterpret_cast<char*>(&temp), 4);}
for (; out.tellp() < songSize + isWav*44;)
out.put(asset.get());
out.close();
asset.seekg(1, ios_base::cur); get2(&asset);
if (isWav){
asset.seekg(1, ios_base::cur); get2(&asset);}
*inc += 1;}
asset.close();}
int main(int argc, char** argv){
extractImages32("cutscenes.mmu", &cutscenesCount);
extractImages32("gameobjects.mmu", &gameobjectsCount);
extractImages32("menus.mmu", &menusCount);
extractImages32("misc.mmu", &miscCount, false);
extractImages8("levelart.mmu", &levelartCount);
extractSound("guns.mmu", &gunsCount, 0xB, 0x4000000);
cout << dec;
cout << cutscenesCount << " cutscene images exported." << endl;
cout << gameobjectsCount << " object images exported." << endl;
cout << levelartCount << " level images exported." << endl;
cout << menusCount << " menu images exported." << endl;
cout << miscCount << " miscellaneous images exported." << endl;
cout << gunsCount << " sounds exported." << endl;
return EXIT_SUCCESS;}
Comments
0 B
|👍
/👎
0 B
|👍
/👎
0 B
|0 👍
/0 👎