Many of the most old-school of gamers still pride themselves on playing all the classics on the original hardware and look down on emulation. Many other Nintendo fans may be loading up their Wiis with plenty of excellent N64 games on the Virtual Console. However, if you are looking for something to breath a bit of fresh air into your favorite N64 games, you may want to look into some neat little hacks you can do with an N64 emulator and some select plugins and texture packs.

  • The N64 is one of the greatest games consoles of all time, leading the way in the late 90s with pioneering 3D graphics and bringing franchises like Mario and Zelda into gorgeous open worlds. If you own the original games, you can relive these glory days through emulation on PC, which lets you do things like increase resolutions and framerates.
  • @NGNYS N64's issues ironically had little to do with its cartridges, the 4KB texture cache was far too small to use leading developers to stream texture data straight from the cartridge and its.
  • Import Texture Pack. To import a texture pack into a ROM, drop the pack.zip and ROM file on the page together. The extension of the ROM must be.z64,.n64 or.v64 (The tool does NOT byteswap the ROM) Texture Pack Format. The pack is a zip archive that contains a directory named 'pack'. The pack directory contains another set of folders, each.

More Must-Read N64 Content to Check Out

The frame buffers were moved to upper RAM to accomodate the size, and all of the related assembly code in GoldenEye and VI settings has been adjusted accordingly. At the expense of some lag, you do get a much sharper image. There are two patches: 640 x 240p (Menus normal) 640 x 480i (Menus 640 x 480i) Apply xDelta to GoldenEye US ROM.

What Can These Tweaks Do?

Even though it was 64-bit, the N64 was still in that era where 3D processing was at its infancy and the graphics weren’t quite as smooth as we might like. In fact, the 32-bit Playstation had a number of later games that gave the best of the N64 a run for its money in terms of graphics. However, with some emulation tweaks, we can give some of your favorite N64 classics a significant boost to help transition them into the modern era.

While I wasn’t as impressed with most of these as much as I was with the PS1 emulation enhancements we covered a while back, there are some very interesting examples of a high-gloss finish added to some of the best of the N64 library.

N64 Texture Packs Retropie

Basic Image Enhancement Plugins

Without doing anything too terribly complicated, you can make most any N64 game look significantly better by using Project64 with a plugin, typically the Rice Video Plugin (find others on list of plugins here). These improvements are usually made by enhancing the 3D model textures and using anti-aliasing techniques to smoothen the rough edges of the polygons. Here are some great examples of enhanced screenshots (click to enlarge)

Kirby 64

Super Smash Bros.


Another Super Smash Bros shot

N64

Jet Force Gemini

Goldeneye 007

Yes, you can render the Sky Box – Glide64 HQ plugin works well also
Another screenshot

Custom Texture Packs

One of the coolest tricks in N64 emulation is re-texturing. With this technique, the original graphics of the game are taken out, redone using high resolution textures or a different graphic style (such as Cell Shading), and then reinserted for playback on the PC. These texture packs consist of zipped files that you download and use in combination with a copy of the original game ROM and specific emulators. (See this guide for a detailed example)

The only disadvantage to this technique is that there is a lot of time and effort that goes into these texture packs. Dedicated members of the N64 emulation community pour their creativity and skill into these creations and is is no small task to adequately take care of one game, let alone the entire N64 library. Because of this, not every N64 game is going to have high-resolution texture packs available. Although, you are free to join in on the initiative yourself.

Below are some of my favorite examples of texture packs (click to enlarge screens), but there are more available. If you have a favorite that isn’t mentioned, feel free to drop some links in the comments section below.

Mario 64 – RiSiO’s Alternative Cartoon Mario 64
More Screenshots
Video Sample
Download Texture Pack

The Legend of Zelda: OoT – Hi-Res Pack

More Screenshots (With Before & After)
Zelda-Specific Instructions
Download Texture Pack

Paper Mario – Mollymutt’s Hi-rez


More Screenshots
Long thread with updates

Banjo-Kazooie – Macphisto’s Hi-Res Banjo-Kazooie
More Screenshots
Download Texture Pack

F-Zero X – speiles F-ZERO X retexture
More Screenshots
Download Texture Pack
Other Texture Packs (thanks CoolROM):

Packs
  • Diddy Kong Racing by _pm_
  • GoldenEye 007 by Kerber2k
  • Legend of Zelda, The: Majora’s Mask by Djipi and MDtauk (Screenshots here)
  • Mario Kart 64 by Mazzocchi
  • Monopoly by krhyluv
  • Starfox 64 by Kid A
  • Super Mario 64 by cloudscapes, _pm_, and John Doe
  • Super Smash Bros. by _pm_ and optimus$prime
  • Virtual Chess 64 by sToRm_seveN
  • Wave Race 64 by The Dave
  • WWF No Mercy by alanchiz

Special thanks:NeoGAF members from this thread that shared their N64 screenshots and

Once you have your 3D model set up, you’ll find that the colouring of it can be a bit plain with just flat colours or Gouraud shading. To remedy this and make it look a bit more realistic, you’re going to want to be adding textures to the faces of your model.

I will try to automate all these steps by building upon the texture conversion program and upgrading it to a model conversion program, but this will have to do for now.

For this tutorial, you’ll need an image that you want to place on a polygon. I’ll be using this website’s 16×16 favicon as an example, but any other image can work.

Steps

  1. Paint your texture
  2. Convert it to a C array
  3. Attach to a polygon/primitive

Painting your texture

This is the fun part. This is when you open up your image manipulation program and draw up a texture.

N64 texture packs 1.16

Any size is good, but powers of 2 are preferred (8×8, 16×16, 32×32, etc). The N64’s texture memory is 4kB (4096 bytes) so your texture must fit within that boundary, depending on the pixel component size (8, 16 or 32-bit).

Convert it into a C array

This part is more complicated, and will require a program to convert. The original program used to convert textures was called rgb2c, but will only work on SGI IRIX workstations. I have devised a program that will let you do it right on this website. This will convert it to an array of 16-bit colours.

You can convert your png image to N64-useful C using the X2C converter.

Once you have your file, you will want to include it by adding the following code to the top of your file to make it accessible:

Of course, filenames may vary.

texture array

Graphic.h

One small thing to remember is that the texture needs to be prototyped (declared, but empty). To do this, go to graphic.h and add this quick line anywhere of code to avoid the ‘undeclared’ error:

Attach the texture to a primitive

N64

The final step to adding textures to a N64 model is that you need to load the texture into the Texture Memory (TMEM), and have it display correctly.

For the sake of this example, we’ll be using nu0 as a base for experimentation, specifically the final section of stage00.c:

Load the texture into TMEM

First, we’re going to edit all the bits under /* Draw a square */. Some parts will be rearranged, some deleted and some added, so I’ll go through each and every bit. I removed some buts that were there before like gDPSetRenderMode and gSPClearGeometryMode for the sale of simplicity, but it’s recommended that you keep them there.

Let’s go through line by line. Note: glistp++ means “add this to the ‘glistp’ display list”, so I won’t bring it up for each line.gSPMatrix, gDPPipeSync and gDPSetCycleType stay the same so we can ignore them.

We change the value for gDPSetRenderMode to G_RM_AA_ZB_XLU_DECAL because it allows us to better render textures, especially since the one in this example has some alpha transparency. Without this, the texture would output those areas as an opaque version of what they would be.

This is the first bit that is different from before. What gSPTexture does is set a few settings for loading textures.

0x8000, 0x8000, refers to the scale of the texture, this sets it to hex 8000 (32,768 in decimal).

The lonely 0,is the level of mipmapping that will be used in this texture (minus one). Since we only have one size, it calculates to 1 – 1 = 0.

G_TX_RENDERTILE, is a constant which equals 0. This is the tile index (value 0-7), which means that it is where the largest resolution texture is located. Again, since we only have one resolution for our bitmap, this isn’t very important.

G_ON tells the function to save these settings. If you were to use G_OFF, then that would reset them all to 0.

This sets the colour combiner mode for adding textures. The colour combiner takes colour from different sources (eg. texel, vertex, ambience, lighting, etc) and mixes them in a particular way to give the desired output.

G_CC_MODULATERGBDECALA is one of many modes that means that the colour is a combination of the shading (vertex colour) and texture colour; and the transparency is taken from the texture (ignoring that of the vertices).

This simple line changes the setting for rendering textures to point sampling/nearest neighbour. This gives our 16×16 texture a ‘pixely’ feel when stretched rather than a blurry appearance.

Texture

This is the line of code that actually does what we want to do.

tex_1 is the name of the texture array from the previous step where you converted the png to the array. It doesn’t really matter what the name is, as long as it’s the same as the texture you want to load.

G_IM_FMT_RGBA is the colour mode of the texture. Here we’ll be using an RGBA format since that is how we converted the texture to C in the previous step, but other formats are available.

G_IM_SIZ_16b indicates the size of each texel, in this case 16 bits.

16, 16, is the width and height of the texture.

0, is the location of the palette. This texture doesn’t use a palette, so we can ignore it.

G_TX_MIRROR, G_TX_MIRROR, don’t have much effect on this code since we’re filling the face with only one instance of the texture. Basically, these determine the rules for what to do when the polygon is bigger than the texture, whether to repeat the pattern, mirror it or stretch the last pixel. Since since this example will have the texture fit the polygon once, there is no need to worry about this.

5, 5, the the amount of texel bits to mask. In this case, it works out to be 25 = 32. What that means is that the above repetition in G_TX_MIRROR will occur every 32 texels. Since our source texture in this example is 16×16, this will have no effect unless it is 3 or less.

G_TX_NOLOD, G_TX_NOLOD refers to the shift value of the texture. It is used for mipmapping so this will be left as off for this example.

gSPVertex loads the vertices into memory and gSP2Triangles finally renders the primitives. This has been explained in more detail in nu0.

N64 Texture Packs 1.14

Much like the previous function a few lines up, this unsets all the texture settings.

And that’s all there is to that section!

Adding texture coordinates

Next we have to amend the list of vertices in order to mark them with a particular texture coordinate. I went into a bit more detail about how the properties of vertices in fiddling with vertices. That article ignored the t and c values, so we’ll go into them over here. A quick recap though:

x, y, z, is the 3d coordinates of the vertex, f, is for flags (unused), t, c, are the texture coordinates (x & y respectively) and r, g, b, a, is the colour and transparency values for the vertex.

This means that we are going to focus on value #6 and #7 for each line. For visual reference, these are the coordinates for each point on the square:

Vertex coordinates for each point. Note: each has a z-value of -5.

And this is the final code that we’ll be striving towards:

There is only two differences in this code to that which was there originally. First off, the 0xff value was replaced with 255. This is merely a change in the value from hexadecimal to decimal. It has no effect on the output.

The other difference is that the t and c values have been changed to 0 << 6 or 15 << 6. These indicate the texture coordinates. Since the texture is 16 pixels wide, 0, 0, represents the top left corner and 15, 15, is the bottom right. The parts that say << 6 are bitshifts to scale up the texture by 26.

Compiling

N64 Texture Packs 1.15

Once you compile the code, the result should look something like this:

N64 High Resolution Texture Packs

Additional resources

N64 Texture Pack Htc

  • nu0 – The code this tutorial is based on
  • Fiddling with vertices – A bit more detail as to how to load vertices
  • Image formats and data types – This tutorial used 16-bit RGBA, but there are more image formats more suitable to each situation. This page goes through each type available and how to work with it.