Banner
Views: 729,869,353
Time:
16 users online: Dark Prince, o Deeke, DPBOX, GreenHammerBro, izaguirrefermin28, KKevinM, o Lazy, LouisDoucet, Mad Lad, MercuryPenny, Nalwonk, Romano338, Samuel Zuccati, The Master Of The Pasta, TheBiob, Tob - Guests: 48 - Bots: 243Users: 38,417 (2,126 active)
Latest: Wuchta
Tip: Don't remake levels from other Mario games, especially popular ones (SMB1/3 1-1, for example).Not logged in.
Skyboxes (Textures, Importer (v1.11), and Discussion)
Forum Index - Non-SMW Hacking - Super Mario 64 Hacking - Project Showoff & Discussion - Skyboxes (Textures, Importer (v1.11), and Discussion)
Pages: « 1 2 »

This thread is all about the Skyboxes that are in SM64. A Skybox is the background image in a level. Some levels have unique skys, while others levels share the same one. I will keep this first post up to date with all of the information & resources regarding skyboxes.

Textures:

There are 10 skyboxes in the original Super Mario 64, and they are located at the following addresses:

Ocean (256x256): 0xB35715
Icy Mountains (256x256): 0xB5D855
Sky (256x160): 0xB85995
Fiery Sky (256x192): 0xBA22D5
Underwater City (256x256): 0xBC2C15
Clouds (256x256): 0xBEAD55
Desert (256x256): 0xC12E95
Dark Woods (256x160): 0xC3AFD5
Dark World (256x256): 0xC57915
Purple Sky (256x256): 0xC7FA55

Gallery: http://imgur.com/a/HdJB3

(I came up with the names based off how the images look, they are not official in any way)

But hold on a second... If you try to open these with a program like N64Rip then you will be greeted by a jumbled mess:



This is because the skyboxes are actually made up of 32x32 squares.



These 32x32 squares make up an entire skybox. A 256x256 skybox is made up of 64 of these little squares. The reason why N64Rip can't properly render the entire image is because each square is independent, and so it tries to combine them in the wrong way. Which is why I created my own skybox importer.


Skybox Importer (v1.11):



This is a small side project I made today. It allows the user to view and replace skyboxes. I purposely made the design to be like N64Rip, so if anyone uses that program they already kinda know how it works.

Browse Button - The first thing you need to do is load up your rom, so press this button and select it in the file explorer.

Address Field - Enter in the hexadecimal address of the skybox here.

List Button - This button will bring up a list of the 10 skyboxes I mentioned before, pressing the OK button will setup that image in the editor.



Import PNG Button - This is used to import a PNG image to replace the skybox at the address.

NOTE: The imported texture must not be bigger than 256x256.
NOTE #2: Make backups of your ROM file before using this tool. Because once you import a texture, it is saved to the ROM.
NOTE #3: You can import skyboxes anywhere in the ROM file, but keep in mind that a 256x256 skybox takes up 0x20000 bytes of memory (128 kilobytes).

Export PNG Button - This button will take that preview image and make it into a .png image file.

Preview Button - Updates the preview image (For when you change the width/height)

Save Button - Saves the ROM with all the current changes you made. When the text is red, then it means that you should press the button.

Shift Image Left ("◄◄") - Adjusts the order bytes so that the image gets shifted to the left by 1 column.

Shift Image Right ("►►") - Adjusts the order bytes so that the image gets shifted to the right by 1 column.

Shift Image Up ("▲▲") - Adjusts the order bytes so that the image gets shifted up by 1 row.

Shift Image Down ("▼▼") - Adjusts the order bytes so that the image gets shifted down by 1 row.

NOTE: When you shift the order bytes, you need to press the "Save" button.

Show Grid ("#") - Toggles a grid so that you can easily see each 32x32 image.





Download:
This program requires at-least Java 7 to run, but I would recommend that you download the latest version of java here: http://www.oracle.com/technetwork/java/javase/downloads/jre8-downloads-2133155.html

You can download the executable jar file here (Version 1.11): http://bin.smwcentral.net/u/26355/SkyboxImporter.jar

Here is a link to the java source code if you are interested (Version 1.11): https://github.com/DavidSM64/SM64SkyboxImporter/

Recent Changes (v1.11, The queueRAM update):
* Colors should be more accurate now
* Fixed a small issue with the convertTo5551 function.
* Exporting the image shouldn't make the image smaller

Recent Changes (v1.1):
* Added 6 new buttons
* You should be able to use any image now and not have it look weird.
* You can click any of the 32x32 images to change the order bytes for that chunk:





Discussion:

Even though I know where the textures are located in the rom, I don't know how they are loaded in-game.
So if anyone knows how they work, or if anyone knows any tricks with skyboxes, then leave a reply here and I will update this post with the appropriate information.

Originally posted by Kazeshin
0x20140 bytes are loaded to segment 0x0a and the box is placed with geo layout command 19 00 00 0A 80 27 63 D4, "0A" seems different sometimes, but no clue wtf its supposed to do.

last 0x140 bytes of segment 0x0A are pointers to each texture. (to order the BG image in some way?)

at 802D0048 a function related to drawing the background image gets called.

 

Originally posted by Kazeshin
do you have any ideas which images work without looking weird and which won't? i had exactly the same error when i tried stuff with a tool to exchange the "thank you" - cake picture. (also my custom backgrounds look kinda fucky because of that sometimes)


I have no idea honestly.

I did a test replacing the 'sky' image.



But it came out like this:



It looks like some of the images overlap each other. Even though they are supposed to be 32x32 sections, the images seem to have a larger width than height in-game.
Do you think it has something to do with the last 0x140 bytes of segment 0x0A you mentioned?
 

Originally posted by Kazeshin
i dont think it's related to those last few bytes.
also, when looking at it closer, it's 64 pointers to textures, but 80 pointers at the end of the segment, meaning that some of these pointers exist twice. i wonder if that affects specific tiles of the image?

the end cake picture was actually in a display list, but had similar issues, so i can't really imagine that to be the solution.


Well the sky data definitely has a lot of repeats (Because it's a smaller image).

http://pastebin.com/wt9BbrnN

Code
0A 00 00 00
0A 00 08 00
0A 00 10 00
0A 00 18 00
0A 00 20 00
0A 00 28 00
0A 00 30 00
0A 00 38 00
0A 00 00 00
0A 00 08 00
.....


I do agree with you that this is just probably the order in which they are displayed. I'll look into the geo command and edit this post if I find anything.
 
Edit:
Well I looked at some of them and I can't really tell what that 4th byte means. All I can tell by looking at this is that areas that have a skybox have "80 27 63 D4" at the end, so it's probably the size (or position) of the skybox. The game locks up if I change these values, so that is probably not it. (I can change it to "00 00 00 00", but that just states that there is no Skybox in the level).

I tried changing the castle ground's 4th byte from 0 to other numbers. Numbers 02-05, 07, and 09 seems to change nothing, while numbers 01, 06, 08, 0A, 0B made the textures mess up. 0C & 0D gave me flashing messed up textures (You have to see it for yourself). However I noticed something when I changed the 4th byte to 0x0F.



I see a texture up there! So maybe that 4th byte is an offset of some kind? (Well 0D gave me textures that changed, so that is probably not it.)

Maybe it's related to a skybox ID?
*I noticed that Lethal Lava Land and Bowser Course 2 both have 01 as their 4th byte.
*Cool Cool Mountain & Snowman's land have their 4th byte as 04.
*BBB, Whomp's Fortress, Tall Tall Mountain, and Castle grounds all share the same skybox and their 4th bytes are 00.
*Rainbow Ride, Rainbow clouds, and Wing Cap all share the same 4th byte and have the same skybox as well.

Here are some addresses from different levels:

003837E0 / 0E000F20 [ 19 00 00 06 80 27 63 D4 ] // Big Boo's Haunt
003961DC / 0E00054C [ 19 00 00 04 80 27 63 D4 ] // Cool Cool Mountain
003FBFF8 / 0E000668 [ 19 00 00 05 80 27 63 D4 ] // Shifting Sand Land
003FC17C / 0E0007EC [ 19 00 00 01 00 00 00 00 ] // Shifting Sand Land (Inside Pyramid)
003FC23C / 0E0008AC [ 19 00 00 01 00 00 00 00 ] // Shifting Sand Land (Boss room)
00405F08 / 0E0004A8 [ 19 00 00 00 80 27 63 D4 ] // Bob-Omb's Battlefield
0040EC08 / 0E0003C8 [ 19 00 00 04 80 27 63 D4 ] // Snowman's Land
0041A608 / 0E000678 [ 19 00 00 02 80 27 63 D4 ] // Wet Dry World (Starting Area)
0041A6D4 / 0E000744 [ 19 00 00 01 00 00 00 00 ] // Wet Dry World (Town Area)
00424558 / 0E000A38 [ 19 00 00 08 80 27 63 D4 ] // Jolly Roger Bay
0042463C / 0E000B1C [ 19 00 00 01 00 00 00 00 ] // Jolly Roger Bay (Inside ship)
0044AB30 / 0E0009F0 [ 19 00 00 03 80 27 63 D4 ] // Rainbow Ride
00454D3C / 0E00075C [ 19 00 00 00 80 27 63 D4 ] // Castle Grounds
0045C598 / 0E000638 [ 19 00 00 07 80 27 63 D4 ] // Bowser 1 Course
0046B000 / 0E0007C0 [ 19 00 00 01 80 27 63 D4 ] // Bowser 2 Course
00478438 / 0E000738 [ 19 00 00 09 80 27 63 D4 ] // Bowser 3 Course
0048D7D0 / 0E000E20 [ 19 00 00 01 80 27 63 D4 ] // Lethal Lava Land
0048D890 / 0E000EE0 [ 19 00 00 01 00 00 00 00 ] // Lethal Lava Land (Inside Volcano)
0049E668 / 0E000C18 [ 19 00 00 03 80 27 63 D4 ] // Whomp's Fortress
004B8030 / 0E000120 [ 19 00 00 01 00 00 00 00 ] // Secret Slide
004C28A8 / 0E0001A8 [ 19 00 00 03 80 27 63 D4 ] // Wing Cap
004CDB40 / 0E000210 [ 19 00 00 03 80 27 63 D4 ] // Rainbow Clouds
004EBC80 / 0E000A90 [ 19 00 00 00 80 27 63 D4 ] // Tall Tall Mountain (Outside)
004EBD6C / 0E000B7C [ 19 00 00 01 00 00 00 00 ] // Tall Tall Mountain (Slide part 1)
004EBDFC / 0E000C0C [ 19 00 00 01 00 00 00 00 ] // Tall Tall Mountain (Slide part 2)
004EBE94 / 0E000CA4 [ 19 00 00 01 00 00 00 00 ] // Tall Tall Mountain (Slide part 3)
 
  
Originally posted by Kazeshin
0x20140 bytes are loaded to segment 0x0a and the box is placed with geo layout command 19 00 00 0A 80 27 63 D4, "0A" seems different sometimes, but no clue wtf its supposed to do.
last 0x140 bytes of segment 0x0A are pointers to each texture. (to order the BG image in some way?)

at 802D0048 a function related to drawing the background image gets called.

do you have any ideas which images workwithout looking weird and which won't? i had exactly the same error when i tried stuff with a tool to exchange the "thank you" - cake picture. (also my custom backgrounds look kinda fucky because of that sometimes)


It's related to the texture borders, they need to be the same with the next texture. I will edit this reply to explain it better later.

    See my hack development here!: Super Mario and the missing memories.

Originally posted by Mariohacker14

It's related to the texture borders, they need to be the same with the next texture. I will edit this reply to explain it better later.


I think I understand what you mean. Basically, you have to treat two touching borders as a single line in-game.

That is an annoying design flaw.

Originally posted by Kazeshin
Originally posted by Mariohacker14
elated to the texture borders, they need to be the same with the next texture. I will edit this reply to explain it better later.

you missunderstood me. i am aware that a texture has to be repeating to look somewhat decent. but most textures will have cutoffs within the original picture, which is my issue here.

I think he means that you have to make the touching borders of each 32x32 chunk match up.

Like the east-border line of pixels of one image should match the west-border line of pixels of the next image in that row. And the bottom row of pixels of the top image should match the top row of the bottom image.

  
Originally posted by Davideesk
Originally posted by Kazeshin
Originally posted by Mariohacker14
elated to the texture borders, they need to be the same with the next texture. I will edit this reply to explain it better later.

you missunderstood me. i am aware that a texture has to be repeating to look somewhat decent. but most textures will have cutoffs within the original picture, which is my issue here.

I think he means that you have to make the touching borders of each 32x32 chunk match up.

Like the east-border line of pixels of one image should match the west-border line of pixels of the next image in that row. And the bottom row of pixels of the top image should match the top row of the bottom image.



That's what I meant exactly. According to this, a skybox should be made of 248x248 different pixels since there are 8x8 repeating vertically and horizontally.

Example:



Conclusion: The game only loads 31,5 x 31,5 pixels from the center of each texture. I don't know if this is even possible #ab{:P}

    See my hack development here!: Super Mario and the missing memories.
  
Originally posted by Kazeshin
Oooooooooohhhhhhhhhh
Yeah, now we need a tool that converts a 248x248 picture into a useable 256x256 picture, that would higher quality of levels by alot.
I could probably come up with something tomorrow, if noone else does.


Glad that you got what I was trying to say xD Yeah it's very time-consuming to do that image processing every time I wanted to edit the background. A tool would be very useful for this.

PD: Kudos to the thread creator, this is a very interesting topic to talk about.

    See my hack development here!: Super Mario and the missing memories.
  
Originally posted by Kazeshin
Made up this code: http://pastebin.com/SSitkiEc

I couldn't test it, because I'm not at my computer right now, tell me if it works. Basically, it divides the 248x248 into 31x31 grids and copies the first pixel of the border textures to fill a 32x32 texture (Thus turning 248x248 into 256x256)


Edit: Can confirm code works


I wonder if it's possible to make this a button (and a reverse one aswell, to make bgs to look like the original pictures) in Davideesk's tool. It would be the perfect tool for skybox edition in sm64. We could even ask skelux to implement this on a future version of the importer, just an idea.

    See my hack development here!: Super Mario and the missing memories.

Originally posted by Mariohacker14
I wonder if it's possible to make this a button (and a reverse one aswell, to make bgs to look like the original pictures) in Davideesk's tool. It would be the perfect tool for skybox edition in sm64. We could even ask skelux to implement this on a future version of the importer, just an idea.


I added the functionality as part of the import(.png) button in version 1.01. Basically if you import an image that consists of 31x31 chunks, it will use Kaze's function to upscale it. (Skyboxes use different heights, so I took that into account).

Code
if (img.getWidth()%31 == 0 && img.getHeight()%31 == 0) img = UpscaleImg(img,width,height);


Code
    /* Special thanks to Kaze for making this function. Link: http://smwc.me/1209817 */
    BufferedImage UpscaleImg(BufferedImage orig, int width, int height){
        BufferedImage converted = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
        int rows = width/32;
        int cols = height/32;
        for (int y = 0; y < cols; y ++) {
            for (int x = 0; x < rows; x++) {
                for (int inY = 0; inY < 32; inY++) {
                    for (int inX = 0; inX < 32; inX++) {
                        converted.setRGB(inX+32*x, inY+32*y, orig.getRGB((inX+31*x)%orig.getWidth(), (inY+31*y)%orig.getHeight()));
                    }
                }
            }
        }
        return converted;
    }


I think a skybox image importer would be great for skelux's importer. I found an image of a sky-swapper tool in which I guess was supposed to be in TT64 v0.6.
I'm not sure if this was actually made by VL-Tone or not, but having it look like this would be pretty cool.



Source: https://sites.google.com/site/awesomelukeystudios/sm64-hacking-tutorials
While I was figuring out the skybox layout, I ran some tests on various emulators and on the N64 to see how they were rendered. One thing I noticed was that some of the smaller skyboxes had one additional textures after the grid of 32x32 textures. In the pointers in the last 0x140 bytes, you can see that this texture is repeated for the skybox floor.
Code
Box    Grid     Expected  Actual   Additional
Sky:   256x160  0x14140   0x14940  32x32
BiFS:  256x192  0x18140   0x18940  32x32
BBH:   256x160  0x14140   0x14940  32x32

To demonstrate this, I replaced the 32x32 at offset 0x14000 of the BBH (Dark Woods) skybox with a pink square with a '1' in it and this is how it renders:


For a more complete rendering test of where the 32x32 textures overlap, I added a border of width 2 around all the edges of the 32x32 skybox images - red/green/yellow/blue along the top and right and black/white along the bottom and left:


It appears the N64, cen64, and Project64 do in fact use approximately 0.5 pixels from each side. mupen64 looks like it overlays the left and top over the right and bottom.

N64 on CRT:

cen64:

Project 64 1.6:

mupen64plus 2.0 (OpenGL Video):

@queueRAM

Thank you for that information. I'm making updates to the importer to make it a better editor. Like actually being able to edit the order in which the chunk images are placed in, and emulating that 0.5 pixel cutoff.

Though I noticed something interesting with the last 0x140 order bytes. I wondered why they had to use 80 images instead of the regular 64. I think I have an answer.

Skyboxes in every level use 80 images total (10 columns by 8 rows), no matter the original size of the image. The first 8 columns are normal, while the last two are repeats of the first two columns. This is for a clever trick that the developers came up with.

I edited the order of the repeated images to a single image each like so:



And it came with this result:

https://www.youtube.com/watch?v=SkjsABj7zZk
(I wish we could embed youtube links)

The skybox image moves based off of the camera's angle. The camera can just fit a little over 2 images wide (as seen in the video), so those extra two columns allow the skybox image to jump from one side to the other without breaking any in-game immersion.



PS: I was mistaken about the size of Wet-Dry-World's Image. It is actually (256x256) and not (256x224).
 

Little update since it's been a few days since the last post on this thread. I have the next version of the importer pretty much done.

Right now I just need some time to test and make sure that there are no major bugs with it. In the next version you should be able to use any .png and have it work fine. I am going to spend some time tomorrow to make sure that is the case with some random texture images I find off of google. :P
If it works correctly, then expect the update that night.

That's odd... I have installed the file, but it seems the tool isn't there.

--------------------
SUPER CRASH TIME YEAH!

Originally posted by Mariocrash
That's odd... I have installed the file, but it seems the tool isn't there.


Try out the new version, it should load quicker now. If your still having problems let me know. (Make sure that you have the latest version of java)
Nice updates! I found some more time test things and go over your code. I compared it with my C implementation and wanted to report a few differences.

First, in RenderImage() where you convert from RGBA5551 to RGBA, you have all the masking correct, but I think the shifting (*8) creates inaccurate representations of the color data. For example, if the 5551 value is 0xFFFF (white), the chunk values will be 0x1F*8 = F8 (very light grey). I think it would be more correct to use *0xFF/0x1F to scale this properly. Also you currently hardcode alpha to 0xFF, but you might want to use (0xFF*(LoadRGBA_RGBA5551 & 0x1)) in case you want to reuse this code for something else in the future. Note that you do this correctly for the conversion from RGBA to 5551 (*31/255).
Explicitly, this is what I mean:
Code
chunk[a][c%4096]   = (((LoadRGBA_RGBA5551 >> 11)&0x1F)*0xFF)/0x1F;
chunk[a][c%4096+1] = (((LoadRGBA_RGBA5551 >> 6)&0x1F)*0xFF)/0x1F;
chunk[a][c%4096+2] = (((LoadRGBA_RGBA5551 >> 1)&0x1F)*0xFF)/0x1F;
chunk[a][c%4096+3] = (byte)((LoadRGBA_RGBA5551 & 1) * 0xFF);


Second, I wanted to ask about was the upscaling and smoothing that is being done in resize() where special=false. It looks like this is being used to upscale each 31x31 to 32x32 for display, but those same values are being used to export a PNG. Thus the exported PNG is 256x256 instead of 248x248, but using the 31x31 data. Personally, I would expect the exported textures to be either the raw texture (256x256 with duplicated rows and columns) or the viewable texture (248x248 with no duplicates) and no processing done to the color data.

If you'd prefer I send some code or pull requests over github, let me know and I can work with you over there. I have a handful of other cosmetic changes that I'd like to recommend.
Originally posted by Davideesk
Originally posted by Mariocrash
That's odd... I have installed the file, but it seems the tool isn't there.


Try out the new version, it should load quicker now. If your still having problems let me know. (Make sure that you have the latest version of java)


Well I've re-installed Java 8.40, but then again your tool still doesn't show up.

--------------------
SUPER CRASH TIME YEAH!
Originally posted by Mariocrash
Well I've re-installed Java 8.40, but then again your tool still doesn't show up.


What do you mean it doesn't show up? How are you trying to run it? It runs for me on several computers by just double-clicking the .jar file. If that doesn't work, try opening a command prompt and running this from the directory where the jar file is:

Code
java -jar SkyboxImporterV1.1.jar


If that also does not work, please report back with output of the following two commands:

Code
where java


Code
java -version
I just wanted to say that this thread is very interesting. It's always fun to understand how a game works.

--------------------



Version 1.11 is out. The update fixes the issues that queueRAM brought up in the post before. Hopefully there shouldn't be any more major bugs with the tool.

Recent Changes (v1.11, The queueRAM update):
* Colors should be more accurate now.
* Fixed a small issue with the convertTo5551 function. (It used to make the image darker)
* Exporting the image shouldn't make the image smaller.

Jar Download: http://bin.smwcentral.net/u/26355/SkyboxImporter.jar
Pages: « 1 2 »
Forum Index - Non-SMW Hacking - Super Mario 64 Hacking - Project Showoff & Discussion - Skyboxes (Textures, Importer (v1.11), and Discussion)

The purpose of this site is not to distribute copyrighted material, but to honor one of our favourite games.

Copyright © 2005 - 2019 - SMW Central
Legal Information - Privacy Policy - Link To Us


Total queries: 23

Menu

Follow Us On

  • Facebook
  • Twitter
  • YouTube

Affiliates

  • Talkhaus
  • SMBX Community
  • GTx0
  • Super Luigi Bros
  • ROMhacking.net
  • MFGG
  • Gaming Reinvented