|
Post by Jason777 on Apr 24, 2011 22:13:54 GMT -5
I have an upcoming display list port patch but I might as well share some methods I came up with while porting because Flotonic's tutorial won't teach you how to find this... I found a much more efficient way of finding texture data while doing a display list port over the weekend: • Extract ZOBJ textures with ZLE2 • With a calculator find the sum of the highest ZZZZZZ "FD" command value + the ZOBJ's location in the ROM • Find the .RAW texture that matches the sum of the above step. • Write down how many bytes long that texture file is • Add the size of the texture file to the original highest ZZZZZZ "FD command value • The sum of the above offset should be the end offset for the texture data
^^ I'm not sure if that made much sense. I'll provide an example: FD 10 00 00 06 00 8F 88 FD 10 00 00 06 00 93 08
ZOBJ location in the MM USA (decompressed) ROM: 0x128F000
Lowest ZZ ZZ ZZ: 0x8F88 Highest ZZ ZZ ZZ: 0x9308
We add 0x9308 and 0x128F000. The sum should be 0x1298308 (I think? I'm doing this in my head ) Next, we extract the textures from the ZOBJ with ZLE2 and look for .RAW texture that has the name of "01298308.raw". We would open it up and see how many bytes the texture is. Let's say it's 0x80 bytes long, we would add 0x80 to 0x9308 (our highest ZZ ZZ ZZ). Our sum should be 0x9388 (I think?). The sum is our end offset of our texture data so in the end we should have: Texture Data: 0x8F88 - 0x9388
NOTE: If your textures don't come out right when you finally view it, I can almost guarantee it's because you didn't port the entire display list- You didn't find the REAL start of the display list (which probably contains a "D7" texture scaling command) I'm pretty sure they're other ways to find texture data end offsets using G_SETTILESIZE or "F2" commands. If you wish to know other F3DZEX commands, study this page: click me
|
|
|
Post by Dead on Apr 25, 2011 4:10:43 GMT -5
sweet, this could come in handy
|
|
|
Post by Jason777 on May 7, 2011 11:26:00 GMT -5
Hello! I have decided to pick learning C++ back up What I did today wasn't much but I feel proud of myself for learning alot in such a short amount of time (30 minutes). What I did today was a 3Player MOD of a Tic-Tac-Toe console game that Xoax made as an example for a lesson on do-while loops and if, else-if, and else operations. Here is the original code: #include <iostream> // Copyright 2007 Xoax
void main() { char cSquare1('1'); char cSquare2('2'); char cSquare3('3'); char cSquare4('4'); char cSquare5('5'); char cSquare6('6'); char cSquare7('7'); char cSquare8('8'); char cSquare9('9'); int iPlayerTurn(1); bool bGameOver(true);
// Main game loop do { // Print board std::cout << cSquare1 << "|" << cSquare2 << "|" << cSquare3 << std::endl; std::cout << "-+-+-"<< std::endl; std::cout << cSquare4 << "|" << cSquare5 << "|" << cSquare6 << std::endl; std::cout << "-+-+-"<< std::endl; std::cout << cSquare7 << "|" << cSquare8 << "|" << cSquare9 << std::endl;
// Set player marker: Player 1 uses X and Player 2 uses O char cPlayerMark; if (iPlayerTurn == 1) { cPlayerMark = 'X'; } else if (iPlayerTurn == 2) { cPlayerMark = 'O'; } else { cPlayerMark = '?'; } // Prompt the player for a move std::cout << "Player" << iPlayerTurn << "'s move:" << std::endl; bool bValidMove; // Loop until we get a valid move do { char cNextMove; std::cin >> cNextMove; bValidMove = true;
// Check for a valid move if (cNextMove == '1' && cSquare1 == '1') { cSquare1 = cPlayerMark; } else if (cNextMove == '2' && cSquare2 == '2') { cSquare2 = cPlayerMark; } else if (cNextMove == '3' && cSquare3 == '3') { cSquare3 = cPlayerMark; } else if (cNextMove == '4' && cSquare4 == '4') { cSquare4 = cPlayerMark; } else if (cNextMove == '5' && cSquare5 == '5') { cSquare5 = cPlayerMark; } else if (cNextMove == '6' && cSquare6 == '6') { cSquare6 = cPlayerMark; } else if (cNextMove == '7' && cSquare7 == '7') { cSquare7 = cPlayerMark; } else if (cNextMove == '8' && cSquare8 == '8') { cSquare8 = cPlayerMark; } else if (cNextMove == '9' && cSquare9 == '9') { cSquare9 = cPlayerMark; } else { std::cout << "Invalid Move. Try again." << std::endl; bValidMove = false; } } while (!bValidMove);
bGameOver = false; bool bWinGame = true; // Check for end of game conditions if (cSquare1 != '1') { if (cSquare2 == cSquare1 && cSquare3 == cSquare1) { bGameOver = true; } if (cSquare4 == cSquare1 && cSquare7 == cSquare1) { bGameOver = true; } } if (cSquare5 != '5') { if (cSquare1 == cSquare5 && cSquare9 == cSquare5) { bGameOver = true; } if (cSquare2 == cSquare5 && cSquare8 == cSquare5) { bGameOver = true; } if (cSquare4 == cSquare5 && cSquare6 == cSquare5) { bGameOver = true; } if (cSquare3 == cSquare5 && cSquare7 == cSquare5) { bGameOver = true; } } if (cSquare9 != '9') { if (cSquare3 == cSquare9 && cSquare6 == cSquare9) { bGameOver = true; } if (cSquare7 == cSquare9 && cSquare8 == cSquare9) { bGameOver = true; } } // Need to check the board full (no-win condition) if (cSquare1 != '1' && cSquare2 != '2' && cSquare3 != '3' && cSquare4 != '4' && cSquare5 != '5' && cSquare6 != '6' && cSquare7 != '7' && cSquare8 != '8' && cSquare9 != '9' && !bGameOver) { bGameOver = true; bWinGame = false; }
if (bGameOver) { if (bWinGame) { std::cout << "Player" << iPlayerTurn << " wins!" << std::endl; } // Print ending board std::cout << cSquare1 << "|" << cSquare2 << "|" << cSquare3 << std::endl; std::cout << "-+-+-"<< std::endl; std::cout << cSquare4 << "|" << cSquare5 << "|" << cSquare6 << std::endl; std::cout << "-+-+-"<< std::endl; std::cout << cSquare7 << "|" << cSquare8 << "|" << cSquare9 << std::endl;
std::cout << "Game Over!" << std::endl; std::cout << "Play again (y/n)?" << std::endl; char cPlayAgain; std::cin >> cPlayAgain;
if (cPlayAgain == 'y') { bGameOver = false; // Clear the board cSquare1 = '1'; cSquare2 = '2'; cSquare3 = '3'; cSquare4 = '4'; cSquare5 = '5'; cSquare6 = '6'; cSquare7 = '7'; cSquare8 = '8'; cSquare9 = '9'; } iPlayerTurn = 1; } else { // Alternate player turns if (iPlayerTurn == 1) { iPlayerTurn = 2; } else if (iPlayerTurn ==2) { iPlayerTurn = 3; } else { iPlayerTurn = 1; } } } while (!bGameOver); }
... And here is the modified code to support 3 Players: #include <iostream> // Original Tic-Tac-Toe by Xoax. 3Player MOD by Jason777
using namespace std;
void main() { char cSquare1('1'); char cSquare2('2'); char cSquare3('3'); char cSquare4('4'); char cSquare5('5'); char cSquare6('6'); char cSquare7('7'); char cSquare8('8'); char cSquare9('9'); int iPlayerTurn(1); bool bGameOver(true);
// Main game loop do { // Print board cout << cSquare1 << "|" << cSquare2 << "|" << cSquare3 << endl; cout << "-+-+-"<< endl; cout << cSquare4 << "|" << cSquare5 << "|" << cSquare6 << endl; cout << "-+-+-"<< endl; cout << cSquare7 << "|" << cSquare8 << "|" << cSquare9 << endl;
// Set player marker: Player 1 uses X and Player 2 uses O char cPlayerMark; if (iPlayerTurn == 1) { cPlayerMark = 'X'; } else if (iPlayerTurn == 2) { cPlayerMark = 'O'; } else { cPlayerMark = '?'; } // Prompt the player for a move cout << "Player" << iPlayerTurn << "'s move:" << endl; bool bValidMove; // Loop until we get a valid move do { char cNextMove; cin >> cNextMove; bValidMove = true;
// Check for a valid move if (cNextMove == '1' && cSquare1 == '1') { cSquare1 = cPlayerMark; } else if (cNextMove == '2' && cSquare2 == '2') { cSquare2 = cPlayerMark; } else if (cNextMove == '3' && cSquare3 == '3') { cSquare3 = cPlayerMark; } else if (cNextMove == '4' && cSquare4 == '4') { cSquare4 = cPlayerMark; } else if (cNextMove == '5' && cSquare5 == '5') { cSquare5 = cPlayerMark; } else if (cNextMove == '6' && cSquare6 == '6') { cSquare6 = cPlayerMark; } else if (cNextMove == '7' && cSquare7 == '7') { cSquare7 = cPlayerMark; } else if (cNextMove == '8' && cSquare8 == '8') { cSquare8 = cPlayerMark; } else if (cNextMove == '9' && cSquare9 == '9') { cSquare9 = cPlayerMark; } else { cout << "Invalid Move. Try again." << endl; bValidMove = false; } } while (!bValidMove);
bGameOver = false; bool bWinGame = true; // Check for end of game conditions if (cSquare1 != '1') { if (cSquare2 == cSquare1 && cSquare3 == cSquare1) { bGameOver = true; } if (cSquare4 == cSquare1 && cSquare7 == cSquare1) { bGameOver = true; } } if (cSquare5 != '5') { if (cSquare1 == cSquare5 && cSquare9 == cSquare5) { bGameOver = true; } if (cSquare2 == cSquare5 && cSquare8 == cSquare5) { bGameOver = true; } if (cSquare4 == cSquare5 && cSquare6 == cSquare5) { bGameOver = true; } if (cSquare3 == cSquare5 && cSquare7 == cSquare5) { bGameOver = true; } } if (cSquare9 != '9') { if (cSquare3 == cSquare9 && cSquare6 == cSquare9) { bGameOver = true; } if (cSquare7 == cSquare9 && cSquare8 == cSquare9) { bGameOver = true; } } // Need to check the board full (no-win condition) if (cSquare1 != '1' && cSquare2 != '2' && cSquare3 != '3' && cSquare4 != '4' && cSquare5 != '5' && cSquare6 != '6' && cSquare7 != '7' && cSquare8 != '8' && cSquare9 != '9' && !bGameOver) { bGameOver = true; bWinGame = false; }
if (bGameOver) { if (bWinGame) { cout << "Player" << iPlayerTurn << " wins!" << endl; } // Print ending board cout << cSquare1 << "|" << cSquare2 << "|" << cSquare3 << endl; cout << "-+-+-"<< endl; cout << cSquare4 << "|" << cSquare5 << "|" << cSquare6 << endl; cout << "-+-+-"<< endl; cout << cSquare7 << "|" << cSquare8 << "|" << cSquare9 << endl;
cout << "Game Over!" << endl; cout << "Play again (y/n)?" << endl; char cPlayAgain; cin >> cPlayAgain;
if (cPlayAgain == 'y') { bGameOver = false; // Clear the board cSquare1 = '1'; cSquare2 = '2'; cSquare3 = '3'; cSquare4 = '4'; cSquare5 = '5'; cSquare6 = '6'; cSquare7 = '7'; cSquare8 = '8'; cSquare9 = '9'; } iPlayerTurn = 1; } else { // Alternate player turns if (iPlayerTurn == 1) { iPlayerTurn = 2; } else if (iPlayerTurn == 2) { iPlayerTurn = 3; } else { iPlayerTurn = 1; } } } while (!bGameOver); }
|
|
|
Post by Jason777 on May 7, 2011 12:40:22 GMT -5
Hah, yeah, 3 players is pretty useless in Tic-Tac-Toe It was to test my usage of conditional branches and basic data types
|
|
|
Post by Jason777 on May 10, 2011 23:29:19 GMT -5
Here is something I did for increasing the size of a message or adding text. The original method was found by BLooDMooN, all I did was simplify it:
1st: I went to the end of nes_message_static and just inserted a random number of bytes that I think would be enough to fit your new message.
2nd: I started off your message with 0x08 command (to print text instantly) on the hex side, wrote your description on the text side, and then ended your message with a 0x02 command (to inidicate the end of a string). Not to mention, I took note of the new end of nes_static_message.
3rd: I went to the end of the text ID table (0xBC66E8 in the ROM) and wrote over the text ID entry of "FFFC". The modified data looked like:
07B3 20 00 07 XX XX XX
07B3- text ID of the new string. 20 - textbox attributes. A blue transparent box at the bottom of the screen. XX XX XX- offset start of the new message
NOTE: If you haven't noticed, 07B3 is unused and the "B3" part of the ID comes directly after the "B2" in the previous text ID of 71B2.
4th: Directly after text ID 07B3's entry, I wrote in an entry for text ID FFFC. Its entry was comprised of its XX XX XX values being the offset directly after the end of the new message you put in (after the 0x02 command).
5th: Directly after text ID FFFC's entry, I wrote in the termination ID's entry (ID FFFF is the termination ID- it ends the table). Its entry was comprised of its XX XX XX values being one byte directly after text ID FFFC's XX XX XX value.
NOTE: I didn't really increase the table count but I could if I wanted to. If you didn't notice, I skipped over the text ID entry that was originally after text ID FFFC's entry- we didn't need it. I'm not entirely sure we need FFFC's entry either. However, we do need FFFF's entry since it is the termination ID entry.
6th: Finally, I went to the Big Skulltula's string in nes_message_static (0xCB44) and wrote over the beginning of the message with a 0x07 command (calls a message). The command looked like:
07 07B3
07- Command 07B3- text ID of your new message.
...And that's all I did.
NOTE: You can increase the text ID table ALOT since the data that follows directly after it is the text ID table (it has a different format) for the French language.
|
|
|
Post by Jason777 on May 23, 2011 23:15:33 GMT -5
People tend to always have some (at least ONE) texture error in their custom map(s). Here are some rules to correctly texturing maps/models that apply to SM64, OoT, and probably some other N64 games:
Frauber/Messian says:
Messian also gave another tip on fixing screwed up textures:
Naxylldritt made some comments about Sketchup's OBJ exporter:
Frauber's/Messian's advice has proven quite useful to me so I thought I should make this information more widely-known.
|
|
|
Post by Jason777 on Jun 13, 2011 10:23:37 GMT -5
This should help those of you who wish to use adult items with child link and vice versa...
Adult & Child Link Corresponding Display Lists Table: 0x108E88 in code.zasm (0xB9CE88 in the ROM)
Every offset I list from here on out will be in the full ROM
Format/Pattern:
BB XXXXXX
BB- Bank (06) XXXXXX- Display List location in either object_link_boy or object_link_child
The table starts with an Adult Link entry and then switches back forth every entry between Adult Link and Child Link display lists. For example, for the entry at 0xB9D0D8, we have the display list location for the right arm and the fairy bow in aiming mode (object_link_boy):
0xB9D0D8: 06 02 A2 48
06 is the bank and 0x2A248 is the location of the display list (object_link_boy).
The next entry (0xB9D0DC) is its corresponding display list (object_link_child):
0xB9D0DC: 06 01 80 48
06 is the bank and 0x18048 is the location of the display list (object_link_child). It loads up the right hand and fairy slingshot in aiming mode. This makes sense since if you try to use the fairy bow as a child, you end up using the fairy slingshot instead!
|
|
|
Post by Jason777 on Aug 2, 2011 9:28:06 GMT -5
Perhaps switch, chest, and clear flags are enabled through the scene header?
|
|
Deleted
Deleted Member
Posts: 0
|
Post by Deleted on Aug 2, 2011 11:21:24 GMT -5
Maybe scene table related, scene header if not. After two and a half years I still haven't looked into that.
Have a look at the z variable, I have a feeling it might be related to that.
|
|
|
Post by Secant on Aug 2, 2011 15:59:31 GMT -5
Wow, triggers are finally being documented? I was wondering if that was every going to get figured out.
|
|
zeth
Full Member
Drunk Roomate of Aweseome [Mo0:17]
Posts: 56
|
Post by zeth on Aug 9, 2011 1:45:39 GMT -5
Maybe scene table related, scene header if not. After two and a half years I still haven't looked into that. Have a look at the z variable, I have a feeling it might be related to that. Actually it doesn't, Z variable in the scene table controls whether or not Map effects are applied such as texture animation within the map itself, the shaking of Ganon's castle crumbling, or the wobbly effect of the map that Lord Jabu Jabu's insides give, this is only a few examples of what it does. Its not thoroughly mapped out though. Also I think having flags within a map has to be scene header related. I posted a video to showcase some of the effects a while ago:
|
|
|
Post by Jason777 on Aug 9, 2011 19:29:27 GMT -5
So then what all is the format of of the ZZZZZZ values to be used to enable animation?
Also, I think the 0x08 map header command enables flags since it's believed to have something to do with "Object Set Behavior". My only doubts are that it's a map header command and it would be alot more efficient if it was a scene header command... Or maybe it has to do with the ?? in the 0x07 scene header command?
|
|
Deleted
Deleted Member
Posts: 0
|
Post by Deleted on Aug 9, 2011 20:46:19 GMT -5
There's still a possibility it's defined somewhere else because there's a limited number of dungeons and a limited amount of data that can be stored in the game save. It might be worth looking into how the number of keys you have in a dungeon is used (8015E71C). Flags for individual maps may be stored around that area too.
|
|
Deleted
Deleted Member
Posts: 0
|
Post by Deleted on Aug 12, 2011 7:57:36 GMT -5
That shouldn't happen. The maximum number of keys should be 255 per dungeon iirc, trying to write anything higher than that should just cause the game to change it back.
You could only increase the size of the game saves by saving them to a controller pak (or using only two save files like MM) but I have not got the first idea of how that would be done.
|
|
|
Post by Jason777 on Aug 17, 2011 10:06:07 GMT -5
Okay!! Today I found something especially interesting... Enemies attacking other enemies It all happened due to a mistake with Utility of Time. I was trying to implement a stationary fire statue into one of the rooms of my Light Temple and then when I loaded up the map with an emulator, all the enemy actors started rush towards this spot and attacking! Perhaps someone could make use of this "hidden" actor. Actor #: 0000 Object #: 002C Variable #: 0000 Also, don't pay attention to the rotation of doors and other actors in the video; I haven't gotten around to fixing that
|
|