Register - Login
Views: 99379434
Main - Memberlist - Active users - Calendar - Wiki - IRC Chat - Online users
Ranks - Rules/FAQ - Stats - Latest Posts - Color Chart - Smilies
04-23-22 10:56:19 PM
Jul - SM64 Hacking (Archive) - ASM hacking New poll - New thread - New reply
Pages: 1 2 3 Next newer thread | Next older thread
VL-Tone
Member
Super Mario 64 forum moderator
Level: 53


Posts: 356/621
EXP: 1135503
For next: 21616

Since: 07-27-07

From: Montreal, Canada

Since last post: 4.7 years
Last activity: 1.2 years

Posted on 11-28-08 04:10:44 PM Link | Quote
Time: Now - Date: Today - Weather: What can be seen outside. - Mood: How it feels. Answer to the universe: 42
Originally posted by Stevoisiak
Originally posted by VL-Tone
Maybe we should extend the ROM to 24MB? This could be done in TT64 only when you activate the extra features, to avoid having to make a new ROM extender.


Uhh, the rom already IS extended to 24 MB. The Extender makes the file 3x larger and extends it from 8MB to 24MB.



Doh! Sorry I meant 32MB... Fixed now.

____________________
Deleted User
Collection of nobodies
Posted on 11-29-08 12:40:17 AM (last edited by Blaster at 11-30-08 02:03 AM) Link | Quote
Originally posted by VL-Tone
One thing I didn't plan yet for the level importer is the possibility of having multiple custom levels. I'm just not sure how I would deal with that. Given what we know, we can only replace existing levels with new ones, since things like level and area names, and other parameters only exist for built-in levels.

Another problem would be the complexity of dealing with the data for multiple levels in the extended ROM. Ideally, each level should have fixed addresses for the start of their data, with space in between levels to allow them to grow. That way I could avoid having to move and repoint levels each time one of them changes size. The downside with this is that space may be wasted when some levels are small, and there would be a fixed limitation on the size of the data for each level. Maybe we should extend the ROM to 24MB 32MB? This could be done in TT64 only when you activate the extra features, to avoid having to make a new ROM extender.


For dealing with multiple levels, would a better solution be if there was no empty space to add more level data at the end of the level data, TT64 would put a pointer at the end of that levels data that pointed to the end of the rom, then TT64 would add the data there?

Or would this not work, be complicated to make or require major reworking of the rom? If this solution did work, I suppose you wouldn't have to move data around, there would be no wasted space (except for the pointers), and the data could be as big as you want, as long as all the data loaded is not too big for the N64 to handle.

The only downside would be that the data would get fragmented if you added data to the level which comes before another level (in the rom) and as such, the data would be unorganized. If this solution is followed, and if the data needs to be organized, a defragmenter would need to be made specially for Mario 64, or maybe manual editing to do the same thing. Your solution sounds easier to implement, though.

Edit: I hope that stuff I said was correct.
messiaen
Catgirl
Level: 68


Posts: 414/1085
EXP: 2594037
For next: 134763

Since: 11-20-07


Since last post: 8.1 years
Last activity: 7.2 years

Posted on 12-01-08 01:19:46 AM Link | Quote
Right, I'll start documenting how each behavior which uses trajectory pointer works. There aren't much objects like this (most use the Platform On Tracks behavior), so hopefully a "universal solution" will be possible with simple changes.

Originally posted by VL-Tone
One thing I didn't plan yet for the level importer is the possibility of having multiple custom levels. I'm just not sure how I would deal with that. Given what we know, we can only replace existing levels with new ones, since things like level and area names, and other parameters only exist for built-in levels.


What about giving the user the option to choose what original level will be replaced, as adding new levels is probably too much trouble for now? One of the problems, however, is that there are lots of hardcoded stuff which relies on the Level ID number, but I guess that's something the user will have to discover on its own (I keep having surprises with the team hack) and eventually there will be workarounds for each issue. There is even some hardcoded stuff for "deleted levels" (if I'm not mistaken, to level number 0x20), but trying to trigger it didn't result in any noticeable effect.

Originally posted by VL-Tone
Another problem would be the complexity of dealing with the data for multiple levels in the extended ROM. Ideally, each level should have fixed addresses for the start of their data, with space in between levels to allow them to grow. That way I could avoid having to move and repoint levels each time one of them changes size. The downside with this is that space may be wasted when some levels are small, and there would be a fixed limitation on the size of the data for each level. Maybe we should extend the ROM to 24MB 32MB? This could be done in TT64 only when you activate the extra features, to avoid having to make a new ROM extender.



A 32MB ROM sounds like a good idea (and why not keep it also open to further expand to 48MB if needed?). Levels with complex geometry and, since RAM probably won't be a problem, much more textures than the original ones, will take a lot of space. When you talk about size limitation, do you mean a fixed size for each level (which I guess would mean all loaded banks) or a estimated size for each kind of bank (ie, 0x0E level script, 0x07 level geometry) ?

____________________
Mario 64 notes @ http://sites.google.com/site/messiaen64/
VL-Tone
Member
Super Mario 64 forum moderator
Level: 53


Posts: 358/621
EXP: 1135503
For next: 21616

Since: 07-27-07

From: Montreal, Canada

Since last post: 4.7 years
Last activity: 1.2 years

Posted on 12-01-08 02:24:46 AM (last edited by VL-Tone at 11-30-08 11:32 PM) Link | Quote
Time: Now - Date: Today - Weather: What can be seen outside. - Mood: How it feels. Answer to the universe: 42
Originally posted by messiaen
What about giving the user the option to choose what original level will be replaced, as adding new levels is probably too much trouble for now? One of the problems, however, is that there are lots of hardcoded stuff which relies on the Level ID number, but I guess that's something the user will have to discover on its own (I keep having surprises with the team hack) and eventually there will be workarounds for each issue. There is even some hardcoded stuff for "deleted levels" (if I'm not mistaken, to level number 0x20), but trying to trigger it didn't result in any noticeable effect.


I guess I could do that, and maybe while testing it I'll find levels that cause too much problems, and will remove them from the list before the release (Or I could keep them available, but with a warning).

Originally posted by messiaen
A 32MB ROM sounds like a good idea (and why not keep it also open to further expand to 48MB if needed?). Levels with complex geometry and, since RAM probably won't be a problem, much more textures than the original ones, will take a lot of space.


Well if we think that 32MB might not be enough after all, then I suggest that we jump to 48MB already, I don't want to have to deal with 3 different sizes of extended ROMs.

Originally posted by messiaen
When you talk about size limitation, do you mean a fixed size for each level (which I guess would mean all loaded banks) or a estimated size for each kind of bank (ie, 0x0E level script, 0x07 level geometry) ?


When I talk about having fixed positions for custom levels (and thus, a size limitation) I'm talking about the levels themselves, not the individual banks.

The way the level importer will work, is that all banks (level scripts, geometry, polygons, textures) will be "re-compiled" and rewritten each time you import an .obj file in an existing custom level. So these will be written one after the other without any wasted space.

All settings for the importation/creation of a given level, as well as the level script commands will be saved in an external file, and optionally re-loaded if you want to import an updated .obj file, so you won't have to start over.

I guess I could use the same principle and reimport/recreate all data for all custom levels at the same time each time you want to change some parameter in the level creator, and/or want to import an .obj file because you changed it, so that all data for all custom levels would be neatly compacted one after the other without wasted space, but that would end up taking too much time (Creating/Updating a single level might take something like 30-60 seconds).

Originally posted by Blaster
For dealing with multiple levels, would a better solution be if there was no empty space to add more level data at the end of the level data, TT64 would put a pointer at the end of that levels data that pointed to the end of the rom, then TT64 would add the data there?

Or would this not work, be complicated to make or require major reworking of the rom? If this solution did work, I suppose you wouldn't have to move data around, there would be no wasted space (except for the pointers), and the data could be as big as you want, as long as all the data loaded is not too big for the N64 to handle.

The only downside would be that the data would get fragmented if you added data to the level which comes before another level (in the rom) and as such, the data would be unorganized. If this solution is followed, and if the data needs to be organized, a defragmenter would need to be made specially for Mario 64, or maybe manual editing to do the same thing. Your solution sounds easier to implement, though.

Edit: I hope that stuff I said was correct.



It's a good idea in principle, but there are a few problems with this. First and foremost, banks (data segments) cannot be split in multiple parts. But even if we could split banks, fragmentation would be a problem, and a defragmenter would be needed anyway, and a defragmenter would essentially have to move things around and repoint a lot of stuff, which is what I wanted to avoid in the first place. In other words, if I have to program a defragmenter anyway, I'll use it each time there's a change in the data size, I won't wait until things get too fragmented.



____________________
Stevoisiak
Member
Level: 38


Posts: 173/283
EXP: 345476
For next: 24971

Since: 11-22-07

From: New York, Long Island

Since last post: 12.3 years
Last activity: 5.6 years

Posted on 12-01-08 06:46:26 PM Link | Quote
Originally posted by VL-Tone
Originally posted by messiaen
A 32MB ROM sounds like a good idea (and why not keep it also open to further expand to 48MB if needed?). Levels with complex geometry and, since RAM probably won't be a problem, much more textures than the original ones, will take a lot of space.


Well if we think that 32MB might not be enough after all, then I suggest that we jump to 48MB already, I don't want to have to deal with 3 different sizes of extended ROMs.


One big problem with that. Wouldn't this cause a lot of people who don't read the readme's with hacks to use a patch for a 48MB rom hack on an old 24MB Rom?
Me-me
340
Level: 41


Posts: 51/341
EXP: 461679
For next: 18466

Since: 08-05-07


Since last post: 9.7 years
Last activity: 8.1 years

Posted on 12-01-08 06:55:59 PM Link | Quote
There's an easy way around this:

Put a big text that says READ THE README! in the first post,
or post the readme document in the thread instead.

____________________
Wow! SM64 is totally turned upside-down!
messiaen
Catgirl
Level: 68


Posts: 427/1085
EXP: 2594037
For next: 134763

Since: 11-20-07


Since last post: 8.1 years
Last activity: 7.2 years

Posted on 12-08-08 04:57:11 PM Link | Quote
Here's a very interesting tutorial about setting up a GNU N64 Toolchain (on Windows) by ZZT32 (who has done some major work on Zelda64 hacking). There are some nice Zelda 64 example hacks included, plus a tool to convert the binary output into a Gameshark code.

Here is something I tried in Mario64 (just a snippet). It saves a lot of time compared to doing it in MIPS ASM! Once we have some nice header files ready (ie, object structs and controller input), some pretty amazing stuff will be possible.

mario64.h:

#define M64_COIN_COUNT 0x8033b262
#define M64_PRINT_XY_FUNC 0x802d66c0

typedef int (*TEXT) */ arguments for the PrintXY function */
(
u16 x,
u16 y,
char* pointer
);


mario64.c:

void _start ( void )
{
/* Data pointer */
asm volatile("la $gp, _gp");

u16 *coins = (void*)M64_COIN_COUNT;
TEXT print_text = (void*)M64_PRINT_XY_FUNC;

*coins += 1; /* coins gone crazy! */

static int x = 0;
static int y = 0;

x += 1; /* moving text around */
y += 1;

if (x > 320) x = 0; /* so that text don't get out of bounds */
if (y > 240) y = 0;

print_text(x, y, "Text output");

}


Now I just hook this somewhere in one of the behavior scripts (Mario's behavior is useful for this) and it's done!

____________________
Mario 64 notes @ http://sites.google.com/site/messiaen64/
Hectamatatortron
Member
Level: 35


Posts: 96/232
EXP: 257991
For next: 21945

Since: 09-19-07


Since last post: 7.2 years
Last activity: 5.3 years

Posted on 12-09-08 01:43:00 PM (last edited by Hectamatatortron at 12-09-08 10:50 AM) Link | Quote
Don't forget you can hook other things, too.

Like, say, the constant routine that always executes.

;Constant hook
80327650
J 80400010
LUI K0, $8036

;AT and K1 are free
80400010
ADDIU K0, K0, $72B0
SD AT, $0020 (K0)

;Inject code here

;Code

;End Inject

;If K0 needs to be free
LUI K0, $8036
J 8032765C
ADDIU K0, K0, $72B0

Not sure what that looks like in the ROM.

The two codes I wrote in C++ for Mischief Makers were hooked a similar way. They had all the code they needed to be inserted at the constant execution level encapsulated within, and hooking from those kinds of areas gives you more freedom with the game.

What I've been doing is getting .cpp files set up after I find a good chunk of data, and following the template I showed you.

Then I find a place to hook that always executes and use an ASM template I made, along with a text editor that supports regular expression find and replace operations to quickly insert code compiled from C++ into the "code shell" the file has.

Then I do some literal find and replace operations to fill out the parameters for the template, copy the WHOLE FILE into Renegade and bam, assemble it into a working code, no problems (assuming my code was coded correctly).

The template can be found here.

Thanks for confirming that hacking a game's assembly doesn't always have to be done with assembly. Maybe more people will try my method now, instead of being so skeptical...

Edit: Maybe have your ASM pooled in some place such that a single hacked behavioral command can load it all at once into free RAM area, and from then on you will already know where to put new code you write. That ought to make the production cycle insanely fast.

____________________
messiaen
Catgirl
Level: 68


Posts: 428/1085
EXP: 2594037
For next: 134763

Since: 11-20-07


Since last post: 8.1 years
Last activity: 7.2 years

Posted on 12-09-08 11:52:53 PM Link | Quote
It certainly saves tons of time debugging stupid mistakes. So far the only problem is that sometimes I get "unsupported opcode" errors (all related to beql) when doing some "if" conditionals. Doing minor changes to the code layout seems to get over it (perhaps the compiler just chooses a different opcode), so I have no idea if it's my or the compiler's fault.

I have never tried messing with this K0/K1 registers, I thought it was bad karma . What I am doing is simpler: I just copy an entire area of the ROM to extended memory at the title screen, so the custom functions are loaded all the time and I can just call them whenever I want. The 'loader' code replaces one unused function, so there's no problem with that.

In the N64 Toolchain package set by ZZT32 there are some handy tools such as one that will convert the binary compiled code to a Gameshark code (if I'm not mistaken, you also did a very similar tool), which is useful for testing stuff in Nemu.

A question: how to make my function pass a float argument in register $F12 (used to pass float parameters) ? I tried seting this:


typedef int (*SCALE)
(
float scale
);


SCALE SetObjScaling = (void*)M64_SCALING_FUNC;

SetObjScaling(2);


But it compiled as something like ADDIU A0, R0, 0x0002 instead of using the $F12 register. Any ideas about this?

____________________
Mario 64 notes @ http://sites.google.com/site/messiaen64/
Hectamatatortron
Member
Level: 35


Posts: 98/232
EXP: 257991
For next: 21945

Since: 09-19-07


Since last post: 7.2 years
Last activity: 5.3 years

Posted on 12-10-08 01:41:30 AM (last edited by Hectamatatortron at 12-09-08 10:42 PM) Link | Quote
Have you tried using the register keyword?

I don't know the syntax your toolchain accepts, if any, for specifying the usage of a specific register.

It may support inline ASM, however.

Something like

inline int Reciprocate(unsigned long Divisor)
{
asm volatile(
"mov r0, %0\n\t"
"mov r1, %2\n\t"
"mov lr, pc\n\t"
"bx r1\n\t"
"mov %0, r0\n\t"
: "=r"(Divisor) //Output list
: "0"(Divisor), "r"(ReciprocateCall) //Input list
: "r0", "r1", "cc" //Clobbered registers (cc here refers to the flag register)
);
return Divisor;
}


____________________
messiaen
Catgirl
Level: 68


Posts: 431/1085
EXP: 2594037
For next: 134763

Since: 11-20-07


Since last post: 8.1 years
Last activity: 7.2 years

Posted on 12-12-08 10:52:53 PM Link | Quote
Nevermind, it was something in the Makefile, now I don't have the annoying unsupported opcode problems and also the floats end up in the right float argument registers.

Since this moved away a bit from ASM Hacking, I think I'll just start a new thread when I have some header files with the whole object struct/misc functions defined.

____________________
Mario 64 notes @ http://sites.google.com/site/messiaen64/
yoshiman
Member
Level: 23


Posts: 92/95
EXP: 67008
For next: 715

Since: 12-21-07

From: London, England

Since last post: 13.2 years
Last activity: 12.9 years

Posted on 02-11-09 11:34:31 AM Link | Quote
Here's what I know so far about what happens when Mario runs up a slope. As Mario goes up the slope, the value at 8033B3BC (16-bit) increases, but is zero when he is not moving. However, the value does not lean Mario's body forward when still, only when running.

This value ends up in Mario's graphics structure (geo layout) by a function call (80277294) from Mario's graphics structure.

8027737C LH T5, 0X000C(T4) T5=(8033B3BC)
80277380 SH T5, 0X001C(T6) (800F47C4)=T5

There is also a value at 8033B3BE (16-bit) which seems to turn Mario's body.

____________________
James S.

We English do things a little differently...Anyone for a cup of tea while we hack?!
messiaen
Catgirl
Level: 68


Posts: 474/1085
EXP: 2594037
For next: 134763

Since: 11-20-07


Since last post: 8.1 years
Last activity: 7.2 years

Posted on 02-11-09 02:29:55 PM Link | Quote
Nice to see you posting back! By he way, here's a map of the "Mario" struct I was doing a few weeks ago.

It starts at 0x8033b170 and seems to be 0xc0 bytes long. Inside it, there is pointer to other structs, such as camera/controller. I guess one of the pointers could be to that data you posted, as a part of another Mario-related struct.

At RAM 0x8032d93c lies a a global variation that contains a pointer to the 0x8033b170 struct.


struct MarioObj /* 8033b170 */
{
u32 status;
u32 flags; /* cap & other flags about mario status */
u32 _0x08;
u32 action; /* see Romanian Girl list */
u32 previous_action; /* 0x10 */
u32 _0x14;
u16 _0x18;
u16 _0x1a;
u32 _0x1c;
float _0x20; /* 0x20 */
u16 _0x26;
s16 hitstun; /* hitstun counter (how long Mario will stays invencible after getting hit */
u32 _0x28;
u32 _0x2c;
u32 _0x30; /* 0x30 */
u32 _0x34;
u32 _0x38;
float x_pos; /* re-check */
float y_pos; /* Mario's y position 0x40 */
float z_pos; /* re-check */
u32 _0x48;
u32 _0x4c;
u32 _0x50; /* 0x50 */
u32 _0x54;
u32 _0x58;
u32 _0x5c;
u32 _0x60; /* 0x60 */
u32 _0x64;
u32 _0x68_ptr;
float _0x6c;
float _0x70; /* 0x70 -> distance from ground Y, used in collision functions*/
u32 _0x74;
u32 _0x78;
u32 _0x7c;
u32 _0x80; /* 0x80 */
u32 _0x84;
u32 _0x88_ptr;
u32 _0x8c_ptr;
u32 _0x90_ptr; /* 0x90 */
u32 _camera_struct_ptr; /* not 100% sure about this one */
u32 _0x98_ptr;
u32 _Pad_struct_ptr; /* this should be used for reading controller input */
u32 _0xa0_ptr; /* 0xa0 */
u32 _0xa4;
s16 coins;
s16 stars;
s16 lifes;
s16 power;
u32 _0xb0; /* 0xb0 */
u32 _0xb4;
u32 _0xb8;
float _0xbc;
float _0xc0; /* 0xc0 */
};


One of the most interesting parts is the action word, which relates to the list RomanianGirl posted in another thread. One code I did a while ago used that little snippet, which show how handy that list can be.

if ( Mario->action == 0x0C000203) /* check if Mario is sleeping */
{
PrintXY(100, 150, "Wake Up");
}



____________________
Mario 64 notes @ http://sites.google.com/site/messiaen64/
VL-Tone
Member
Super Mario 64 forum moderator
Level: 53


Posts: 380/621
EXP: 1135503
For next: 21616

Since: 07-27-07

From: Montreal, Canada

Since last post: 4.7 years
Last activity: 1.2 years

Posted on 02-12-09 12:40:59 AM Link | Quote
Time: Now - Date: Today - Weather: What can be seen outside. - Mood: How it feels. Answer to the universe: 42
To put this in context, I asked yoshiman if he could help me find a code to keep Mario's body perpendicular to the ground even when standing still.

I was planning on doing a Super Mario Galaxy inspired level, with spheres for "planets", using the "non-slippery" collision material which enables Mario to walk on very steep hills without slipping. While Mario walks or run over slanted terrain, his body will lean to become perpendicular to the slant, but when he stops, he suddenly stands straight up, which ruins the effect.

Now, I've been doing a few experiments with Mario's ROM geometry layout (Not exactly the same geo layout as yoshiman's talking about, which is in RAM, but contains many of the same elements and pointers).

What I discovered, is that there seems to be some code that overrides some of the ROM geo layout commands.

It looks like the SM64 team originally wanted to animate Mario using the same standard geometry layout and animation commands as other characters in the game, but they either found it restrictive, or it added too much overhead. So they decided to bolt new control/animation code on top of the existing script structure, overriding some part of it, while keeping the original commands to avoid introducing bugs.

One example which I caught early on: if you try to change the 0x0C commands found in Mario's behavior script, you'll see that it doesn't change his behavior at all except maybe make him run twice as fast for some reason. Doing the same with any other animated character would result in noticeable behavior changes. Also, I didn't find any animation data in Mario's MIO0 segment like there is for most animated characters like Peach and Yoshi, so it's stored elsewhere, probably near the main Mario controlling code.

So yesterday, while experimenting with the geo layout in ROM, I witnessed much the same thing happening. I swapped around 0x0E commands usually used for animation, in this case each body part node has a 0x0E command with a pointer attached to it. I even deleted some 0x0E commands, but whatever I was doing, resulted in no noticeable changes in Mario's look and behavior, except for some recurring glitch that would happen whenever I edited/deleted any 0x0E or 0x18 command, where a glitchy mutant Mario twin would appear attached to the feet of the real Mario, which was looking and functioning perfectly normally.








____________________
yoshiman
Member
Level: 23


Posts: 93/95
EXP: 67008
For next: 715

Since: 12-21-07

From: London, England

Since last post: 13.2 years
Last activity: 12.9 years

Posted on 02-12-09 06:35:34 PM Link | Quote
Don't forget that only the middle of the three functions in the Mario behaviour script is actually the Mario behaviour, the other two are for the second debug display and the spawn debug mode.

Thanks messiaen, I'm going to have to compare that with what I have for PAL (UK).

Here is what I know of just a few of the functions called from the uncompressed Mario geo layout:

800F09F8 802773A4 Remove this pointer and Mario's head doesn't turn when looking around with Camera-up.

800F0A54 802771BC Remove this pointer and Mario doesn't blink, it seems to only affect when he is not moving.

____________________
James S.

We English do things a little differently...Anyone for a cup of tea while we hack?!
VL-Tone
Member
Super Mario 64 forum moderator
Level: 53


Posts: 385/621
EXP: 1135503
For next: 21616

Since: 07-27-07

From: Montreal, Canada

Since last post: 4.7 years
Last activity: 1.2 years

Posted on 02-14-09 08:55:56 PM Link | Quote
Time: Now - Date: Today - Weather: What can be seen outside. - Mood: How it feels. Answer to the universe: 42
The 0x pointer is actually part of the "compressed" ROM geo layout for Mario, and is used in an 0x0E command (animation).

...

00127CB0/0300: 0E 00 00 00 80 27 71 BC
00127CB8/0308: 04 00 00 00
00127CBC/030C: 15 01 00 00 04 01 19 A0 -- head 1 hp color
00127CC4/0314: 15 01 00 00 04 01 1A 90 -- head 2 hp color
00127CCC/031C: 15 01 00 00 04 01 1B 80 -- head 3 hp color
00127CD4/0324: 15 01 00 00 04 01 1C 70 -- head 4 hp color
00127CDC/032C: 15 01 00 00 04 01 1D 60 -- head 5 hp color
00127CE4/0334: 15 01 00 00 04 01 1E 50 -- head 6 hp color
00127CEC/033C: 15 01 00 00 04 01 1F 40 -- head 7 hp color
00127CF4/0344: 15 01 00 00 04 01 20 30 -- head 8 hp color
00127CFC/034C: 05 00 00 00
...


The 0x0E command act as a selector to choose which object inside the next node (between 0x04 and 0x05 commands) will be displayed.

Some animation functions are pretty "dumb" as they only cycle each one of the object one after the other.

For example, in the smoke/dust animation:

001279E8/0038:   0E 00 00 07 80 29 DB 48 

001279F0/0040: 04 00 00 00
001279F4/0044: 15 05 00 00 04 02 17 18
001279FC/004C: 15 05 00 00 04 02 17 30
00127A04/0054: 15 05 00 00 04 02 17 48
00127A0C/005C: 15 05 00 00 04 02 17 60
00127A14/0064: 15 05 00 00 04 02 17 78
00127A1C/006C: 15 05 00 00 04 02 17 90
00127A24/0074: 15 05 00 00 04 02 17 A8
00127A2C/007C: 05 00 00 00
00127A30/0080: 01 00 00 00


This particular animation function (8029DB48) needs a parameter in the fourth bytes to specify how many frames there are in the animation.

Other 0x0E animation functions are more dynamic and are controlled by the character's behavior ASM code.

When I replace Mario's head animation pointer (802771BC) with the cycling animation one (8029DB48 with a parameter of 8), it doesn't do what's expected, cycling through all 8 head states. Instead, like in your experiment, Mario just stops blinking (and doesn't get "X"s in the eyes when dying/getting burned).

Oh... I just realized why it doesn't work... The frame number must not be incremented in Mario's behavior code because it doesn't use the 8029DB48 function. Anyway this is still interesting/useful stuff

So it seems that you can affect the 0x0E commands after all in Mario's compressed geo layout.

For example, if you change "0E 00 00 00 80 27 76 D8" at both 0x12A690 and 0x12A6C4 in the ROM to "0E 00 00 00 80 27 71 BC" Mario will turn to metal each time he blinks




____________________
Pages: 1 2 3 Next newer thread | Next older thread
Jul - SM64 Hacking (Archive) - ASM hacking New poll - New thread - New reply


Rusted Logic

Acmlmboard - commit 47be4dc [2021-08-23]
©2000-2022 Acmlm, Xkeeper, Kaito Sinclaire, et al.

33 database queries, 9 query cache hits.
Query execution time:  0.096902 seconds
Script execution time:  0.041939 seconds
Total render time:  0.138841 seconds


TidyHTML vomit below
line 1 column 1 - Warning: missing <!DOCTYPE> declaration
line 2 column 288 - Warning: unescaped & or unknown entity "&page"
line 119 column 11 - Warning: <form> isn't allowed in <table> elements
line 118 column 10 - Info: <table> previously mentioned
line 120 column 11 - Warning: missing <tr>
line 120 column 119 - Warning: missing </font> before </td>
line 124 column 16 - Warning: plain text isn't allowed in <tr> elements
line 120 column 11 - Info: <tr> previously mentioned
line 125 column 68 - Warning: missing </nobr> before </td>
line 141 column 68 - Warning: missing </nobr> before <tr>
line 147 column 35 - Warning: missing <tr>
line 147 column 50 - Warning: missing </font> before </td>
line 148 column 37 - Warning: unescaped & or unknown entity "&id"
line 147 column 182 - Warning: missing </font> before </table>
line 149 column 35 - Warning: missing <tr>
line 149 column 94 - Warning: unescaped & or unknown entity "&page"
line 149 column 126 - Warning: unescaped & or unknown entity "&page"
line 149 column 50 - Warning: missing </font> before </td>
line 149 column 163 - Warning: missing </font> before </table>
line 156 column 9 - Warning: <div> isn't allowed in <table> elements
line 152 column 17 - Info: <table> previously mentioned
line 158 column 9 - Warning: missing <tr>
line 176 column 13 - Warning: missing <tr>
line 177 column 99 - Warning: unescaped & or unknown entity "&postid"
line 179 column 73 - Warning: <style> isn't allowed in <td> elements
line 179 column 9 - Info: <td> previously mentioned
line 179 column 1511 - Warning: missing </font> before <blockquote>
line 179 column 1590 - Warning: inserting implicit <font>
line 179 column 1590 - Warning: missing </font> before <hr>
line 179 column 1669 - Warning: inserting implicit <font>
line 179 column 1669 - Warning: missing </font> before <hr>
line 179 column 1733 - Warning: inserting implicit <font>
line 179 column 1733 - Warning: missing </font> before <hr>
line 180 column 1894 - Warning: inserting implicit <font>
line 181 column 1 - Warning: inserting implicit <font>
line 181 column 1 - Warning: missing </font> before <hr>
line 182 column 1 - Warning: inserting implicit <font>
line 179 column 137 - Warning: missing </div>
line 185 column 15 - Warning: <div> isn't allowed in <table> elements
line 152 column 17 - Info: <table> previously mentioned
line 186 column 25 - Warning: missing <tr>
line 193 column 33 - Warning: missing <tr>
line 194 column 119 - Warning: unescaped & or unknown entity "&postid"
line 208 column 9 - Warning: <div> isn't allowed in <table> elements
line 152 column 17 - Info: <table> previously mentioned
line 210 column 9 - Warning: missing <tr>
line 228 column 13 - Warning: missing <tr>
line 229 column 99 - Warning: unescaped & or unknown entity "&postid"
line 243 column 9 - Warning: <div> isn't allowed in <table> elements
line 152 column 17 - Info: <table> previously mentioned
line 245 column 9 - Warning: missing <tr>
line 263 column 13 - Warning: missing <tr>
line 264 column 99 - Warning: unescaped & or unknown entity "&postid"
line 266 column 73 - Warning: <style> isn't allowed in <td> elements
line 266 column 9 - Info: <td> previously mentioned
line 266 column 1511 - Warning: missing </font> before <blockquote>
line 266 column 1590 - Warning: inserting implicit <font>
line 266 column 1590 - Warning: missing </font> before <hr>
line 266 column 1655 - Warning: inserting implicit <font>
line 266 column 1655 - Warning: missing </font> before <hr>
line 267 column 1 - Warning: inserting implicit <font>
line 267 column 1 - Warning: missing </font> before <blockquote>
line 270 column 2498 - Warning: inserting implicit <font>
line 270 column 2498 - Warning: missing </font> before <hr>
line 270 column 2563 - Warning: inserting implicit <font>
line 270 column 2563 - Warning: missing </font> before <hr>
line 271 column 1 - Warning: inserting implicit <font>
line 271 column 1 - Warning: missing </font> before <blockquote>
line 274 column 3027 - Warning: inserting implicit <font>
line 274 column 3027 - Warning: missing </font> before <hr>
line 274 column 3092 - Warning: inserting implicit <font>
line 274 column 3092 - Warning: missing </font> before <hr>
line 274 column 3306 - Warning: inserting implicit <font>
line 275 column 1 - Warning: inserting implicit <font>
line 275 column 1 - Warning: missing </font> before <blockquote>
line 284 column 4490 - Warning: inserting implicit <font>
line 284 column 4490 - Warning: missing </font> before <hr>
line 285 column 1 - Warning: inserting implicit <font>
line 285 column 1 - Warning: missing </font> before <hr>
line 291 column 1 - Warning: inserting implicit <font>
line 266 column 137 - Warning: missing </div>
line 297 column 9 - Warning: <div> isn't allowed in <table> elements
line 152 column 17 - Info: <table> previously mentioned
line 299 column 9 - Warning: missing <tr>
line 317 column 13 - Warning: missing <tr>
line 318 column 99 - Warning: unescaped & or unknown entity "&postid"
line 327 column 9 - Warning: <div> isn't allowed in <table> elements
line 152 column 17 - Info: <table> previously mentioned
line 329 column 9 - Warning: missing <tr>
line 347 column 13 - Warning: missing <tr>
line 348 column 99 - Warning: unescaped & or unknown entity "&postid"
line 356 column 9 - Warning: <div> isn't allowed in <table> elements
line 152 column 17 - Info: <table> previously mentioned
line 358 column 9 - Warning: missing <tr>
line 376 column 13 - Warning: missing <tr>
line 377 column 99 - Warning: unescaped & or unknown entity "&postid"
line 425 column 9 - Warning: <div> isn't allowed in <table> elements
line 152 column 17 - Info: <table> previously mentioned
line 427 column 9 - Warning: missing <tr>
line 445 column 13 - Warning: missing <tr>
line 446 column 99 - Warning: unescaped & or unknown entity "&postid"
line 490 column 9 - Warning: <div> isn't allowed in <table> elements
line 152 column 17 - Info: <table> previously mentioned
line 492 column 9 - Warning: missing <tr>
line 510 column 13 - Warning: missing <tr>
line 511 column 99 - Warning: unescaped & or unknown entity "&postid"
line 535 column 9 - Warning: <div> isn't allowed in <table> elements
line 152 column 17 - Info: <table> previously mentioned
line 537 column 9 - Warning: missing <tr>
line 555 column 13 - Warning: missing <tr>
line 556 column 99 - Warning: unescaped & or unknown entity "&postid"
line 583 column 9 - Warning: <div> isn't allowed in <table> elements
line 152 column 17 - Info: <table> previously mentioned
line 585 column 9 - Warning: missing <tr>
line 603 column 13 - Warning: missing <tr>
line 604 column 99 - Warning: unescaped & or unknown entity "&postid"
line 611 column 9 - Warning: <div> isn't allowed in <table> elements
line 152 column 17 - Info: <table> previously mentioned
line 613 column 9 - Warning: missing <tr>
line 631 column 13 - Warning: missing <tr>
line 632 column 99 - Warning: unescaped & or unknown entity "&postid"
line 646 column 9 - Warning: <div> isn't allowed in <table> elements
line 152 column 17 - Info: <table> previously mentioned
line 648 column 9 - Warning: missing <tr>
line 666 column 13 - Warning: missing <tr>
line 667 column 101 - Warning: unescaped & or unknown entity "&postid"
line 744 column 9 - Warning: <div> isn't allowed in <table> elements
line 152 column 17 - Info: <table> previously mentioned
line 746 column 9 - Warning: missing <tr>
line 764 column 13 - Warning: missing <tr>
line 765 column 101 - Warning: unescaped & or unknown entity "&postid"
line 767 column 74 - Warning: <style> isn't allowed in <td> elements
line 767 column 9 - Info: <td> previously mentioned
line 767 column 138 - Warning: missing </div>
line 789 column 9 - Warning: <div> isn't allowed in <table> elements
line 152 column 17 - Info: <table> previously mentioned
line 791 column 9 - Warning: missing <tr>
line 809 column 13 - Warning: missing <tr>
line 810 column 101 - Warning: unescaped & or unknown entity "&postid"
line 825 column 9 - Warning: <div> isn't allowed in <table> elements
line 152 column 17 - Info: <table> previously mentioned
line 827 column 9 - Warning: missing <tr>
line 845 column 13 - Warning: missing <tr>
line 846 column 101 - Warning: unescaped & or unknown entity "&postid"
line 848 column 74 - Warning: <style> isn't allowed in <td> elements
line 848 column 9 - Info: <td> previously mentioned
line 848 column 1512 - Warning: missing </font> before <pre>
line 863 column 1 - Warning: inserting implicit <font>
line 863 column 1 - Warning: missing </font> before <pre>
line 881 column 1 - Warning: inserting implicit <font>
line 848 column 138 - Warning: missing </div>
line 898 column 17 - Warning: missing <tr>
line 898 column 17 - Warning: discarding unexpected <table>
line 901 column 35 - Warning: missing <tr>
line 901 column 94 - Warning: unescaped & or unknown entity "&page"
line 901 column 126 - Warning: unescaped & or unknown entity "&page"
line 901 column 50 - Warning: missing </font> before </td>
line 901 column 163 - Warning: missing </font> before </table>
line 903 column 35 - Warning: missing <tr>
line 903 column 50 - Warning: missing </font> before </td>
line 904 column 37 - Warning: unescaped & or unknown entity "&id"
line 903 column 182 - Warning: missing </font> before </table>
line 905 column 17 - Warning: discarding unexpected </textarea>
line 905 column 28 - Warning: discarding unexpected </form>
line 905 column 35 - Warning: discarding unexpected </embed>
line 905 column 43 - Warning: discarding unexpected </noembed>
line 905 column 53 - Warning: discarding unexpected </noscript>
line 905 column 64 - Warning: discarding unexpected </noembed>
line 905 column 74 - Warning: discarding unexpected </embed>
line 905 column 82 - Warning: discarding unexpected </table>
line 905 column 90 - Warning: discarding unexpected </table>
line 907 column 9 - Warning: missing </font> before <table>
line 919 column 25 - Warning: discarding unexpected </font>
line 928 column 57 - Warning: discarding unexpected </font>
line 906 column 1 - Warning: missing </center>
line 120 column 63 - Warning: <img> lacks "alt" attribute
line 125 column 19 - Warning: <td> attribute "width" has invalid value "120px"
line 125 column 93 - Warning: <img> lacks "alt" attribute
line 141 column 19 - Warning: <td> attribute "width" has invalid value "120px"
line 141 column 98 - Warning: <img> lacks "alt" attribute
line 148 column 44 - Warning: <img> proprietary attribute value "absmiddle"
line 148 column 142 - Warning: <img> proprietary attribute value "absmiddle"
line 148 column 245 - Warning: <img> proprietary attribute value "absmiddle"
line 161 column 22 - Warning: <img> lacks "alt" attribute
line 161 column 63 - Warning: <img> lacks "alt" attribute
line 161 column 112 - Warning: <img> lacks "alt" attribute
line 161 column 162 - Warning: <img> lacks "alt" attribute
line 172 column 15 - Warning: <img> lacks "alt" attribute
line 179 column 693 - Warning: <img> lacks "alt" attribute
line 183 column 2168 - Warning: <img> lacks "alt" attribute
line 183 column 2327 - Warning: <img> lacks "alt" attribute
line 189 column 37 - Warning: <img> lacks "alt" attribute
line 213 column 22 - Warning: <img> lacks "alt" attribute
line 213 column 63 - Warning: <img> lacks "alt" attribute
line 213 column 111 - Warning: <img> lacks "alt" attribute
line 213 column 161 - Warning: <img> lacks "alt" attribute
line 224 column 15 - Warning: <img> lacks "alt" attribute
line 248 column 22 - Warning: <img> lacks "alt" attribute
line 248 column 63 - Warning: <img> lacks "alt" attribute
line 248 column 112 - Warning: <img> lacks "alt" attribute
line 248 column 162 - Warning: <img> lacks "alt" attribute
line 259 column 15 - Warning: <img> lacks "alt" attribute
line 266 column 693 - Warning: <img> lacks "alt" attribute
line 294 column 6310 - Warning: <img> lacks "alt" attribute
line 294 column 6469 - Warning: <img> lacks "alt" attribute
line 302 column 22 - Warning: <img> lacks "alt" attribute
line 302 column 63 - Warning: <img> lacks "alt" attribute
line 302 column 112 - Warning: <img> lacks "alt" attribute
line 302 column 162 - Warning: <img> lacks "alt" attribute
line 313 column 15 - Warning: <img> lacks "alt" attribute
line 331 column 15 - Warning: <img> proprietary attribute value "absmiddle"
line 331 column 15 - Warning: <img> lacks "alt" attribute
line 331 column 58 - Warning: <img> proprietary attribute value "absmiddle"
line 331 column 58 - Warning: <img> lacks "alt" attribute
line 331 column 101 - Warning: <img> proprietary attribute value "absmiddle"
line 331 column 101 - Warning: <img> lacks "alt" attribute
line 331 column 144 - Warning: <img> proprietary attribute value "absmiddle"
line 331 column 144 - Warning: <img> lacks "alt" attribute
line 331 column 187 - Warning: <img> proprietary attribute value "absmiddle"
line 331 column 187 - Warning: <img> lacks "alt" attribute
line 331 column 230 - Warning: <img> proprietary attribute value "absmiddle"
line 331 column 230 - Warning: <img> lacks "alt" attribute
line 332 column 22 - Warning: <img> lacks "alt" attribute
line 332 column 63 - Warning: <img> lacks "alt" attribute
line 332 column 112 - Warning: <img> lacks "alt" attribute
line 332 column 162 - Warning: <img> lacks "alt" attribute
line 333 column 11 - Warning: <img> lacks "alt" attribute
line 343 column 15 - Warning: <img> lacks "alt" attribute
line 353 column 228 - Warning: <img> proprietary attribute value "absmiddle"
line 353 column 228 - Warning: <img> lacks "alt" attribute
line 361 column 22 - Warning: <img> lacks "alt" attribute
line 361 column 63 - Warning: <img> lacks "alt" attribute
line 361 column 111 - Warning: <img> lacks "alt" attribute
line 361 column 161 - Warning: <img> lacks "alt" attribute
line 372 column 15 - Warning: <img> lacks "alt" attribute
line 430 column 22 - Warning: <img> lacks "alt" attribute
line 430 column 63 - Warning: <img> lacks "alt" attribute
line 430 column 112 - Warning: <img> lacks "alt" attribute
line 430 column 162 - Warning: <img> lacks "alt" attribute
line 441 column 15 - Warning: <img> lacks "alt" attribute
line 487 column 1968 - Warning: <img> proprietary attribute value "absmiddle"
line 487 column 1968 - Warning: <img> lacks "alt" attribute
line 487 column 2021 - Warning: <img> proprietary attribute value "absmiddle"
line 487 column 2021 - Warning: <img> lacks "alt" attribute
line 495 column 22 - Warning: <img> lacks "alt" attribute
line 495 column 63 - Warning: <img> lacks "alt" attribute
line 495 column 111 - Warning: <img> lacks "alt" attribute
line 495 column 161 - Warning: <img> lacks "alt" attribute
line 506 column 15 - Warning: <img> lacks "alt" attribute
line 515 column 531 - Warning: <img> proprietary attribute value "absmiddle"
line 515 column 531 - Warning: <img> lacks "alt" attribute
line 540 column 22 - Warning: <img> lacks "alt" attribute
line 540 column 63 - Warning: <img> lacks "alt" attribute
line 540 column 112 - Warning: <img> lacks "alt" attribute
line 540 column 162 - Warning: <img> lacks "alt" attribute
line 551 column 15 - Warning: <img> lacks "alt" attribute
line 580 column 706 - Warning: <img> proprietary attribute value "absmiddle"
line 580 column 706 - Warning: <img> lacks "alt" attribute
line 580 column 759 - Warning: <img> proprietary attribute value "absmiddle"
line 580 column 759 - Warning: <img> lacks "alt" attribute
line 588 column 22 - Warning: <img> lacks "alt" attribute
line 588 column 63 - Warning: <img> lacks "alt" attribute
line 588 column 111 - Warning: <img> lacks "alt" attribute
line 588 column 161 - Warning: <img> lacks "alt" attribute
line 599 column 15 - Warning: <img> lacks "alt" attribute
line 616 column 22 - Warning: <img> lacks "alt" attribute
line 616 column 63 - Warning: <img> lacks "alt" attribute
line 616 column 112 - Warning: <img> lacks "alt" attribute
line 616 column 161 - Warning: <img> lacks "alt" attribute
line 627 column 15 - Warning: <img> lacks "alt" attribute
line 651 column 22 - Warning: <img> lacks "alt" attribute
line 651 column 63 - Warning: <img> lacks "alt" attribute
line 651 column 111 - Warning: <img> lacks "alt" attribute
line 651 column 161 - Warning: <img> lacks "alt" attribute
line 662 column 15 - Warning: <img> lacks "alt" attribute
line 749 column 22 - Warning: <img> lacks "alt" attribute
line 749 column 63 - Warning: <img> lacks "alt" attribute
line 749 column 112 - Warning: <img> lacks "alt" attribute
line 749 column 162 - Warning: <img> lacks "alt" attribute
line 760 column 15 - Warning: <img> lacks "alt" attribute
line 767 column 694 - Warning: <img> lacks "alt" attribute
line 786 column 4111 - Warning: <img> lacks "alt" attribute
line 786 column 4270 - Warning: <img> lacks "alt" attribute
line 794 column 22 - Warning: <img> lacks "alt" attribute
line 794 column 63 - Warning: <img> lacks "alt" attribute
line 794 column 112 - Warning: <img> lacks "alt" attribute
line 794 column 161 - Warning: <img> lacks "alt" attribute
line 805 column 15 - Warning: <img> lacks "alt" attribute
line 830 column 22 - Warning: <img> lacks "alt" attribute
line 830 column 63 - Warning: <img> lacks "alt" attribute
line 830 column 112 - Warning: <img> lacks "alt" attribute
line 830 column 162 - Warning: <img> lacks "alt" attribute
line 841 column 15 - Warning: <img> lacks "alt" attribute
line 848 column 694 - Warning: <img> lacks "alt" attribute
line 888 column 3979 - Warning: <img> proprietary attribute value "absmiddle"
line 888 column 3979 - Warning: <img> lacks "alt" attribute
line 892 column 4307 - Warning: <img> proprietary attribute value "absmiddle"
line 892 column 4307 - Warning: <img> lacks "alt" attribute
line 895 column 4451 - Warning: <img> lacks "alt" attribute
line 895 column 4610 - Warning: <img> lacks "alt" attribute
line 904 column 44 - Warning: <img> proprietary attribute value "absmiddle"
line 904 column 142 - Warning: <img> proprietary attribute value "absmiddle"
line 904 column 245 - Warning: <img> proprietary attribute value "absmiddle"
line 913 column 25 - Warning: <img> lacks "alt" attribute
line 918 column 267 - Warning: <img> lacks "alt" attribute
line 179 column 1511 - Warning: trimming empty <font>
line 180 column 1894 - Warning: trimming empty <font>
line 266 column 1511 - Warning: trimming empty <font>
line 274 column 3306 - Warning: trimming empty <font>
line 898 column 17 - Warning: trimming empty <tr>
line 125 column 68 - Warning: <nobr> is not approved by W3C
line 141 column 68 - Warning: <nobr> is not approved by W3C
line 177 column 27 - Warning: <nobr> is not approved by W3C
line 179 column 157 - Warning: <table> proprietary attribute "height"
line 179 column 222 - Warning: <td> proprietary attribute "background"
line 179 column 318 - Warning: <td> proprietary attribute "background"
line 179 column 408 - Warning: <table> proprietary attribute "height"
line 179 column 488 - Warning: <td> proprietary attribute "background"
line 179 column 1443 - Warning: <td> proprietary attribute "background"
line 194 column 47 - Warning: <nobr> is not approved by W3C
line 229 column 27 - Warning: <nobr> is not approved by W3C
line 264 column 27 - Warning: <nobr> is not approved by W3C
line 266 column 157 - Warning: <table> proprietary attribute "height"
line 266 column 222 - Warning: <td> proprietary attribute "background"
line 266 column 318 - Warning: <td> proprietary attribute "background"
line 266 column 408 - Warning: <table> proprietary attribute "height"
line 266 column 488 - Warning: <td> proprietary attribute "background"
line 266 column 1443 - Warning: <td> proprietary attribute "background"
line 318 column 27 - Warning: <nobr> is not approved by W3C
line 348 column 27 - Warning: <nobr> is not approved by W3C
line 377 column 27 - Warning: <nobr> is not approved by W3C
line 446 column 27 - Warning: <nobr> is not approved by W3C
line 511 column 27 - Warning: <nobr> is not approved by W3C
line 556 column 27 - Warning: <nobr> is not approved by W3C
line 604 column 27 - Warning: <nobr> is not approved by W3C
line 632 column 27 - Warning: <nobr> is not approved by W3C
line 667 column 27 - Warning: <nobr> is not approved by W3C
line 765 column 27 - Warning: <nobr> is not approved by W3C
line 767 column 158 - Warning: <table> proprietary attribute "height"
line 767 column 223 - Warning: <td> proprietary attribute "background"
line 767 column 319 - Warning: <td> proprietary attribute "background"
line 767 column 409 - Warning: <table> proprietary attribute "height"
line 767 column 489 - Warning: <td> proprietary attribute "background"
line 767 column 1444 - Warning: <td> proprietary attribute "background"
line 810 column 27 - Warning: <nobr> is not approved by W3C
line 846 column 27 - Warning: <nobr> is not approved by W3C
line 848 column 158 - Warning: <table> proprietary attribute "height"
line 848 column 223 - Warning: <td> proprietary attribute "background"
line 848 column 319 - Warning: <td> proprietary attribute "background"
line 848 column 409 - Warning: <table> proprietary attribute "height"
line 848 column 489 - Warning: <td> proprietary attribute "background"
line 848 column 1444 - Warning: <td> proprietary attribute "background"
Info: Document content looks like HTML5
Info: No system identifier in emitted doctype
Tidy found 330 warnings and 0 errors!


The alt attribute should be used to give a short description
of an image; longer descriptions should be given with the
longdesc attribute which takes a URL linked to the description.
These measures are needed for people using non-graphical browsers.

For further advice on how to make your pages accessible
see http://www.w3.org/WAI/GL.
You are recommended to use CSS to specify the font and
properties such as its size and color. This will reduce
the size of HTML files and make them easier to maintain
compared with using <FONT> elements.

You are recommended to use CSS to control line wrapping.
Use "white-space: nowrap" to inhibit wrapping in place
of inserting <NOBR>...</NOBR> into the markup.

About HTML Tidy: https://github.com/htacg/tidy-html5
Bug reports and comments: https://github.com/htacg/tidy-html5/issues
Official mailing list: https://lists.w3.org/Archives/Public/public-htacg/
Latest HTML specification: http://dev.w3.org/html5/spec-author-view/
Validate your HTML documents: http://validator.w3.org/nu/
Lobby your company to join the W3C: http://www.w3.org/Consortium

Do you speak a language other than English, or a different variant of
English? Consider helping us to localize HTML Tidy. For details please see
https://github.com/htacg/tidy-html5/blob/master/README/LOCALIZE.md