What's new

N64 Texture Image Extraction

rajkosto

New member
stupid non resizable roms....

why don't they have like a file system or sumting...make much easier to edit...

also why does SPrite Viewer always say Not enough memory when loading zelda rom ?
 

MasterPhW

Master of the Emulation Flame
Mmh... I wonder why there isn't a GFX plugin out for extracting textures like in the Gamecube (dolphin) one! That would be great!
Anton and BGNG you seems to me very able in texture hacking of N64 games, why not contacting Rice and trying to help him in inserting an texture dumber into his plugin for N64 Games? Would be great! I'm using it often with my GameCube games and often recognizes some "secret" textures I've never seen! Probably there are some in the N64 roms, too?
 

Anton

I like beer
There are plugins that extracts textures, already.
Textures are in very bad quality, btw. (I tried to extract some for Q3 Arena map - but didn't finish it. And textures are ugly (looks like ~15x15 pixels (or so), 72 dpi - very ugly) :)

I didn't edit textures. I extracted only graphics needed for Zelda translation to russian.

"also how do u extract stuff using this thing ?"
You'll need to uncompress rom, then search for graphics in uncompressed files (with Sprite Viewer or Tile Molester), then extract *.png image with n64gfx from those files.
 

rajkosto

New member
why can't i extract the textures from the ROM directly using M0CK ?
Cuz the uncompressor thingy gives garble at the end of each file
 

rajkosto

New member
there is a texture dumper plugin...even one that dumps both geometry and textures...just search the board for it.... :party:
 
OP
BGNG

BGNG

New member
I found this old bookmark in my web browser called "EmuTalk" and LOW AND BEHOLD: this topic was brought back to life. (-:

Sorry about any waiting. I don't often check to see what new stuff is here in this forum.
__________

Yes, MIO0's compressor is flawed. The reason it doesn't compress fully is because there's something in the coding that compresses incorrectly altogether. It's probably just a small problem, but I've been unable to find it. I think it's a logical error that I didn't account for in the coding in the first place.

I've already spoken to HyperHacker about this. If anyone wants to have a functional compressor, the documentation of the MIO0 format is included with the M0CK program. I am unable to make a sufficient compressor, but there are other programmers out there in the world. You'll have to find one, as I am unwilling to try to correct M0CK.
__________

And in terms of image hacking: the new files that you insert into the ROM must be the same size or smaller, else it will take up data in the ROM wich is legitimately used for other code/resources.

And Sprite Viewer's colors ARE messed up, I believe... There is another program written by SnowBro in Java called Tile Molester, which is certainly worth the download. It's the new version of his classic Tile Edit which was used to edit the graphics in old NES titles like Metroid to make new games. (SnowBro also created the infamous MetEdit)
__________

Lesse here... "why can't i extract the textures from the ROM directly using M0CK?" - You can. Just type in the beginning offset of the MIO0 data in the ROM... M0CK doesn't automatically search through the ROM for MIO0 headers, which may be what you're asking... because I simply didn't code it to do so.

"Cuz the uncompressor thingy gives garble at the end of each file" - Not sure what you're talking about here. All the files I ever decompressed did the same job as the other decompressor I was using (which I didn't make)
__________

As for the rest... I have no life's passion. Hacking is simply a hobby; nothing I would want to do full-time. Same goes with programming and video games in general for that matter.

I'm still willing to help out, though. If you have any questions on whatever, go ahead and ask and I'll find out what I can in order to send you on your way. I'm just not willing to be the one to actually provide any solutions if it requires extensive work on my part. (Selfish? Lazy? Nah. I just don't want to be caught up in it)
 

SubDrag

New member
Have you tried decompressing the compressed files you make, and also output each step of the decompression at a time if there was a bug? That way, you can see whether it was a problem with algorithm, or a problem with the implementation.

If you're really going to give up when you're so close, I'll implement the compressor next week, assuming it's not a specifications error.
 
OP
BGNG

BGNG

New member
The files I tested on do in fact decompress to the source files. Though, since there definitely is error in the code, I wouldn't be surprised if that didn't always happen.

I've been over the code a zillion times. It does EXACLTY what I planned for it to do. It's the fact that there's something I'm not planning out correctly to make it work right. Don't know what, though. But since my main purpose for ever researching MIO0 in the first place was to make a decoder (which works) to extract the texture images from F-Zero X, my work is done. This is simply MORE than I had intended to do.

And the specification is documented in that HTML file included with M0CK. If you get to understanding that really well, you can make a good compressor.

And when working on a compressor yourself, keep in mind that compressing one large chunk of data could concievably mark out the beginning of an even longer chunk for the next match, ultimately making a larger file. I'm CERTAIN my programming doesn't account for that as well as it should.
 

SubDrag

New member
If you find a file that doesn't work, decompress and see where the problem arises.

Anyways, how I would/will implement this encoder is by doing the following:

Write three bytes

Start the looping stuff:
Variable for amount back, size

Start at position 0, loop until curPos - 2 (while < (curPos - 2))
Loop at each position till curPos, compare to next data one by one

Replace the amount back and size variables with larger size/amt back if size to replace is larger, as you go (if was match)

after done looping:
if size < 3, write next byte
else write the stuff for amount back and size (that 12-bit pair)


Finish when file is done (reached input size)

Of course, as you go, you'll have to update the 1/0 compress/decompress tally.
And the offets will be written last, as you write file. I wouldn't worry too much about the large chunk of writing marking out an even longer chunk; in most cases, it'll only be a few bytes. If you want to handle that, your algorithm will be more complicated, and take a bunch of passes I'd imagine. Perhaps your problem arises with the last few bytes?

And considering I believe (haven't looked, but in most cases) since the data uses a palette of some sort (you haven't discussed the image format), with your input image you can turn down the # of colors and fit nicely.

I thought you were working on a level editor for F-Zero? If so, you'd need compression. I was hoping for that...
 
Last edited:
OP
BGNG

BGNG

New member
I, failing to write a compressor upon attempt, cannot guarantee any "proper" method for implementing one, as I was unable to do so myself. But basically, yeah. Write three bytes and keep checking back in the already-compressed SOURCE file for more matches. "BEWARE OF CHAIN CHOMP" for example, would compress to "BEWARE OF CHAINOMP" because of the " CH" match.

And the problem with my algorithm causes it to fail throughout the entire file. I did most of the testing with it using the third splash screen for F-Zero X (the cross-section of the Blue Falcon), and even early in the file there were some differences between MY compressed file and the one used in the ROM.

The texture images I needed are MIO0 compressed, and once decompressed are encoded with standard 16-bit RGBA... that is, [rrrr rggg] [ggbb bbba] for the bits. Indeed, cutting down the NUMBER of colors used in the image will cause the same color to be repeated more frequently, allowing the final image to be compressed, even when changed.

However, I have no need to do that in the level editor. The level data itself is stored uncompressed in the ROM. All I need to do is change the bytes for that. In order to make a graphical interface for the program, I needed textures to map to the polygons I'd draw, and what better textures than the ones actually used in the game?

I am able to extract those texture images from the ROM to use in my program, so (says the title of this very thread) my quest is over. This codec utility is just extra nick-nack that resulted from my research.
 

SubDrag

New member
Just because you compress your file and it does not equal the one they have, does NOT mean it is compressed wrong. It simply means that their compression algorithm was different. As long as it uses the same specifications, there is no need to worry. Since you're making a level editor, why not allow users to create their own textures and insert them?
 
OP
BGNG

BGNG

New member
I'm near-certain the compressor I made is indeed incorrect. The only application I've seen attempted for it thus-far was one of Anton's associates changing the font of Super Mario 64 to Russian, where the file turned out smaller, but execution of the code messed up. That might have been because of the header checksum, which I brought to his (gottaX) attention but never got a reply.

And as far as my project, it's a level editor, not programming overhaul. I intended to create something like the F-Zero X Expansion Kit for the 64DD which was released solely in Japan, and the best way for me to do that would be to hack the ROM in similar fashion to other level editors (the only of which I have used was MetEdit). Making changable textures would be a taxing implementation at best, especially because my project sports proprietary course data files for transport and patching to template ROMs.
 

SubDrag

New member
I've used your program to decompress some of the MIO0 encoding from F-Zero X, where is the palette? I see a bunch of indexes, but where's the palette?
 
OP
BGNG

BGNG

New member
There is no palette in F-Zero X, to my knowledge. All images I've seen used in the game (and I believe I've looked through them ALL) are either 16-bit RGBA or 8-Bit alpha greyscale. Here's the utility module I made for my project. The particular procedure you want is called LoadTextureMIO0. In there, "Dest" is the pointer to a UserControl I made to easily implement OpenGL in my programming.

I've attatched the module to this post.

Lesse here... I've constructed that utility to extract textures directly from the ROM, so you'll need the F-Zero X ROM in Z64 (non byte-swapped) format. I've not yet implemented support for V64 yet. Then, use these offsets (remember that Visual Basic starts at 1 instead of 0) to locate the track textures:

Code:
&H235131 'Mute City
&H239A81 'Port Town
&H23EC51 'Big Blue
&H243D91 'Sand Ocean
&H24A271 'Devil's Forest
&H2507F1 'White Land
&H255101 'Sector
&H259601 'Red Canyon
&H25F361 'Fire Field
&H266C21 'Silence
&H26D781 'Ending
That is... File offset &H235131 in Visual Basic corresponds to 0x235130 in C++.

So, to extract all track textures for any given track set (locale, venue, world, etc.) where in this example, Mute City is used:
Code:
Dim FBuff() As Byte
Open "F-Zero X.n64" For Binary Access Read As #1
    mioMemDecode 1, &H235131, FBuff()
Close #1
For I = 0 To 6: LoadTextureMIO0 FBuff, CDbl(4096) * I + 1, 64, 32, I, True, Form1.GLComet1: Next
LoadTextureMIO0 FBuff, CDbl(4096) * 7 + 1, 64, 32, 7, True, Form1.GLComet1
For I = 8 To 10: LoadTextureMIO0 FBuff, CDbl(4096) * I + 1, 64, 32, I, True, Form1.GLComet1: Next
And GLComet1 is that UserControl for OpenGL that I made.
__________

Also in that module:

The CCSpline procedure takes an array of doubles and interpolates them into a Closed Cubic Spline, which is (I believe) the same way the tracks are connected in the game itself. It takes the array PIn() and makes an interpolated loop which is stored in POut(). You would need to call this 3 times, one for the X coordinates, and once for Y and once for Z.

The FloatF() and IntF() functions accept 4- and 2-byte values and converts them from Big-Endian to memory, which Visual Basic stores as Little-Endian. Because they're Big-Endian in the ROM, I needed to make a compensation for my project. I have not yet written functions that take a value in memory and convert them to Big-Endian, however.
__________

I know this is more than you need, but this is a working example of how the textures can be loaded from MIO0 and converted into bitmaps, which in this instance are used in OpenGL.
 

SubDrag

New member
I'm programming it in C++ (ugh VB). One thing I'd like to know as well, is whether there is any indicator that lets you know if the data is 8-bit or 16-bit, or is that in an unknown image table or on the calls to load the textures themselves, more likely? Goldeneye let you know in the header of the image.

I'll probably do a quick re-write in C++ of the decompression routine, and have it convert to bitmaps directly, as well.

Oh, and those pointers you gave me, are they to some sort of model data or textures? Are they interspersed, and both in MIO0? Gimme a location of a 16-bit RGBA if you don't mind, something I could find in the game, and I'll try decompressing then recompressing something when its done; and know if it worked.
 
Last edited:
OP
BGNG

BGNG

New member
"(ugh VB)"? Explain why you said that and I'll consider answering your questions.
 

Top