Register - Login
Views: 99381372
Main - Memberlist - Active users - Calendar - Wiki - IRC Chat - Online users
Ranks - Rules/FAQ - Stats - Latest Posts - Color Chart - Smilies
04-23-22 11:53:08 PM
Jul - SM64 Hacking (Archive) - ASM hacking New poll - New thread - New reply
Pages: 1 2 3 Next newer thread | Next older thread
messiaen
Catgirl
Level: 68


Posts: 233/1085
EXP: 2594047
For next: 134753

Since: 11-20-07


Since last post: 8.1 years
Last activity: 7.2 years

Posted on 08-31-08 08:52:16 PM (last edited by messiaen at 09-05-08 11:45 AM) Link | Quote
Maybe, but the problem is finding unused bytes in the RAM Object to hold all this stuff. Also, with this simpler approach you just have to create a separate behavior for each Koopa. Look how handy this is with the 0x04 Jump command:

Koopa-The-Quick Alternate Path/Star Behavior:
00 05 00 00 <-- The first two lines are copied from the usual Koopa Behavior:
11 01 20 41 <-- Perhaps this one isn't even needed
27 3E 00 00 07 01 16 A0 <-- Pointer to path
27 3F 00 00 0B D6 11 94 <-- X, Y
27 50 00 00 EE 08 00 00 <-- Z
04 00 00 00 13 00 45 88 <-- Proceed to the usual Koopa Behavior (after the first 2 commands)

So, that's just 40 bytes for each new Koopa, and it could be stored somewhere in the level bank (0x0E), so TT64 wouldn't have trouble knowning that this 0x07 Bank is the one currently loaded.

The same jump approach could be used for the behaviors which have collision pointers. Here is a template:


Universal collision template
00 09 00 00 <-- Or something else, depending on the target behavior
[ ... ] <-- Here you copy all commands from the target behavior before the collision pointer
2A 00 00 00 XX XX XX XX <-- Set your new pointer in RAM Object
04 00 00 00 XX XX XX XX <-- Continue to normal behavior (jump after the 0x2A command)


If I have enough time, I'll try this week to compile a list of all the "moving platforms" behaviors that will work just by changing the collision pointer. These will probably be enough for the next release of TT64 before using this kind of ASM hacks.

Edit: I'm done with the list. I used one of my custom objects, set all the collision pointers in the behavior bank to it and now I'm using Yoshiman's spawn code to test stuff. Most behaviors work nicely with custom models/collision data, so with a very simple behavior interface you can assign interesting effects to the new objects.

---

Edit2: Here's another ASM trick that can be potentially VERY useful. Looking through Cellar Dweller's Notes, I saw that some behavior commands are unused. So, I replaced the code of the 0x12 command with a modified version of the 0x0C (simple JAL) command. However, this new command can jump to data inside one of the level banks using the segmented_to_virtual (0x80277f50) function, which returns the virtual memory address of a segmented pointer.

Sample usage:

12 00 00 00 07 01 16 A0 # Address must be word aligned (multiple of 4)

Here is basically how the 0x0C command works:

80384688: LW T7, 0x0004 (T6) <-- Load argument from 0x0C command
8038468C: SW T7, 0x001C (SP) <-- Store in Stack
80384690: LW T9, 0x001C (SP) <-- Copy to T9
80384694: JALR RA, T9 <-- JAL to Register T9
80384698: NOP <-- Delay Slot

And the modified version in the custom 0x12 command:

80384E20: JAL 0x80277F50 <-- Segmented to Virtual function
80384E24: LW A0, 0x001C (SP) <-- Ran argument from 0x12 command into this function
80384E28: SW V0, 0x001C (SP) <-- Save in stack [Not sure if it's necessary]
80384E2C: JALR RA, V0 <-- JAL to Register V0 [V0 = return value from segmented_to_virtual]
80384E30: NOP <-- Delay Slot
VL-Tone
Member
Super Mario 64 forum moderator
Level: 53


Posts: 249/621
EXP: 1135507
For next: 21612

Since: 07-27-07

From: Montreal, Canada

Since last post: 4.7 years
Last activity: 1.2 years

Posted on 09-08-08 02:35:41 PM Link | Quote
Time: Now - Date: Today - Weather: What can be seen outside. - Mood: How it feels. Answer to the universe: 42
Ok I'm back from the country... hmm not much activity here while I was gone!

What I meant about the Koopa the Quick behavior was that the multiple different path pointers would be stored inside the same behavior, not inside the RAM object. Isn't there a conditional jump command in behavior scripts that can branch out based on the behavior parameters? That way we could make the script jump to the appropriate 0x27 command sets depending on one of the param. BTW, how does the single Koopa behavior switch between the two different paths provided in the original game? Is it happening in the behavior script or ASM routine?

Concerning the solidity behaviors, what would be nice is to have a single table of collision pointers that would be accessed by all the "new" solidity behaviors. Maybe if there is indeed a conditional jump command that can branch depending on one of the param, we could build such a table without having to create a new behavior command.

But ideally, the best thing would be a collision pointer table with a command that would select the appropriate entry depending on the current model ID. Essentially, this is what Nintendo should've done in the first place.

This new 0x12 command looks very interesting, it'll open up all sorts of new possibilities.

____________________
messiaen
Catgirl
Level: 68


Posts: 235/1085
EXP: 2594047
For next: 134753

Since: 11-20-07


Since last post: 8.1 years
Last activity: 7.2 years

Posted on 09-08-08 04:03:52 PM (last edited by messiaen at 09-08-08 05:22 PM) Link | Quote
The arguments from level comands are processed by 0x0C call before the "loop" area:

ROM Addr: 0021E380 Hex Behav: 13004580
Description: Koopa Behavior
[...]
21E3B8/0045B8 0C 00 00 00 80 2F BC 4C <-- Only called once.
21E3C0/0045C0 08 00 00 00 <-- "Loop"
21E3C4/0045C4 0C 00 00 00 80 2F D7 F8 <-- This is continuously being called
21E3CC/0045CC 09 00 00 00 <-- End

The first thing the "802FBC4C" call does is to load the arguments from the 0x24 command (stored in the RAM object) and branch out accordingly. If you take this call out, the arguments won't be processed and you'll have a "Running Koopa". This is true for most objects: the 0x0C calls before the 0x08 command usually process arguments and set a few variables, while the call inside the 0x08 "loop" area is responsible for the object movement/behavior.

I posted the list of behaviors with collision pointers which will work fine on custom objects in the Behavior thread. Try testing a few of these on imported objects by copying all the behavior and just changing the 0x2A collision pointer.

Edit: Here is a commented disassembly of the "Moving Up And Down" (0x3B30) behavior call responsible for processing the arguments. Looking at these calls is a good way to discover the possible arguments for some object. Maybe in same cases it won't be hard to create tweaks with custom arguments.
VL-Tone
Member
Super Mario 64 forum moderator
Level: 53


Posts: 251/621
EXP: 1135507
For next: 21612

Since: 07-27-07

From: Montreal, Canada

Since last post: 4.7 years
Last activity: 1.2 years

Posted on 09-14-08 03:25:50 AM Link | Quote
Time: Now - Date: Today - Weather: What can be seen outside. - Mood: How it feels. Answer to the universe: 42
Ok so you're saying that the conditional branching occurs in the asm functions? That's sad, as a conditional jump behavior script command would be very useful for all sorts of things, including dealing with the collision behaviors.

How about we modify command 0x04, so that it will only jump if its second byte is equal to one of the behavior param? If the second byte is 00, it would work as normal (always branching).

Example:
04 03 00 00 13 00 45 88

In this example, the script would only jump to 13 00 45 88 if the first behavior param is equal to 0x03.

The only problem, which I just realized is that some collision behaviors already use one or both behav params...

In that case, maybe we could use the second and third byte of the 0x04 command, and instead put the model ID there... Then have the 0x04 command only jump if these two bytes are equal to the current model ID?

I would like the behavior scripts for imported object to remain static, and I simply can't generate all the behavior/model ID possible because it could end up taking way too much space. Having behavior scripts that change place when the user changes the behavior for a model would be a nightmare to manage. Many routines in TT64 expect the behavior pointers to remain the same.

I guess that the compromise would be to let the use assign the behaviors to models before the level is generated. But that would mean that the user would be stuck with the pre-assigned behaviors in the normal TT64 editing mode.




____________________
messiaen
Catgirl
Level: 68


Posts: 242/1085
EXP: 2594047
For next: 134753

Since: 11-20-07


Since last post: 8.1 years
Last activity: 7.2 years

Posted on 09-14-08 07:55:14 PM Link | Quote
A conditional jump is an interesting idea, but I'm not sure if its possible to make it use the Model ID. What is stored in the "RAM object" isn't the ID, but rather the RAM pointer for the geo layout/polygon data.

Making it use the arguments from the 0x24 command would be easier, the problem as you predicted is that they are already used for most objects, especially by platforms.

What about implementing something like this:

When you import new geometry to be used as independent solid object, TT64 saves (internally or somewhere in the ROM) a level-specific table of model IDs and their respectives collision pointers. From this list TT64 can generate (during the level editing, if it detects that the model id you're working with is a imported object) a new behavior (that will be in the level script bank) and combo (ie, combo Model 0x36 with Elevator Behavior) on the spot, using something like the template I posted earlier on.

Do you think something like this would work or do you have something else in mind?

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


Posts: 252/621
EXP: 1135507
For next: 21612

Since: 07-27-07

From: Montreal, Canada

Since last post: 4.7 years
Last activity: 1.2 years

Posted on 09-14-08 11:07:49 PM Link | Quote
Time: Now - Date: Today - Weather: What can be seen outside. - Mood: How it feels. Answer to the universe: 42
Well your suggestion is the thing I wanted to avoid. Having dynamic behavior lists will be harder to manage.

For example, if you change the behavior for a specific model, it means that the replacement behavior script might displace all the other scripts after that. That means repointing every 0x04 or 0x02 commands in these scripts, and then repointing all affected behavior pointers in the 0x24 commands. Also, the labeling system is dependent on the behavior pointer. That would mean repointing every affected label. And then, if you worked on two different ROMs with different custom levels, the labels could end being mixed up.

Also, the current selection menu system for behaviors is used to select a behavior pointer, not change a behavior script. I would have to create some kind of hybrid menu that can either choose a behavior pointer (to use normal behaviors), or trigger a custom behavior script recompilation by choosing one of the custom collision behavior.

One thing to alleviate the problem with labels is that the 3 label files could be integrated into the ROM. That way the custom labels would always match the content of the ROM. (So you wouldn't have to bundle the label files with your ROM hacks!)

The biggest label file currently is 40k, so I could allocate 100k for each one, just to be safe. The files would be saved as is in the ROM, in ASCII. I could make them smaller by using a binary format for numbers, but that would require a lot of work. The current format can be loaded directly into list variables. Out of the 7MB left in the extended ROM, 300k is around 4%, so it's not that bad.

To avoid having to repoint 0x04 and 0x02 commands, I could eliminate them from scripts and making them linear.



On another note: I'm about to release tonight TT64 v0.5.99b, but only on this forum for now. No it doesn't have the importer in it yet. Aside from many little bug fixes, it doesn't have any major new feature, except that it should now work in Vista without all the 3d glitches, and it will be a universal binary for Macs so that it will be much much faster on intel Macs. There's some "little" feature that might interest you messiaen, it's a "Script Dumper" that can dump scripts from levels, geo layouts, polygons and behaviors, conveniently formated, with addresses and offsets, and indentation for hierarchical structures.




____________________
messiaen
Catgirl
Level: 68


Posts: 243/1085
EXP: 2594047
For next: 134753

Since: 11-20-07


Since last post: 8.1 years
Last activity: 7.2 years

Posted on 09-15-08 12:01:51 AM (last edited by messiaen at 09-14-08 09:13 PM) Link | Quote
Nice, the script dumper will be useful!

Now I understand what you meant by static behaviors and why a conditional jump would be useful.

I have an idea that might work. I was looking at the documentation for the 0x24 command, and there are 4 bytes for parameters [2 for each type?], but TT64 only edits one byte for each param. Am I right to assume that all objects loaded from level script only use 1 byte [the last one] for each param and that's why you supressed the other one? So, what about we use the extra byte in one of these parameters to save the model ID? This way, a conditional jump based on it would be possible.

For instance, if an platform object uses parameter 1 = 01, TT64 would set it to xx01 (xx = Model ID).

The conditional jump (or load collision) command would use this byte, and before jumping would reset it to 0, in order to avoid any further interference.

I think this could be a solution to get a static behavior (ie, going up and down) which can be easily used for many models. It may even take less space than using the jump command.

Edit: Another option would be to edit the 0x24 command so that it stores the model ID somewhere in the RAM Object (maybe in this seemingly unused parameter byte). Maybe this would make the process even easier (no necessary changes in TT64!).

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


Posts: 254/621
EXP: 1135507
For next: 21612

Since: 07-27-07

From: Montreal, Canada

Since last post: 4.7 years
Last activity: 1.2 years

Posted on 09-15-08 01:19:39 AM Link | Quote
Time: Now - Date: Today - Weather: What can be seen outside. - Mood: How it feels. Answer to the universe: 42
You are right, only one byte is used per param. Actually, only the last two parameter bytes are used in the game, the first two are always zero in all the built-in 0x24 commands. Also, 0x42 and 0x43 only have two parameter bytes in the combo presets. So it means that there are indeed four separate parameter bytes in the 0x24 command, and not 2 16-bit params.

So we could use the two first bytes to pass some parameter to select the collision in the behavior script. But your second solution is better. I'm just wondering, how will we deal with the additional space taken by the modified ASM functions? Is there any empty space around this area?

____________________
messiaen
Catgirl
Level: 68


Posts: 268/1085
EXP: 2594047
For next: 134753

Since: 11-20-07


Since last post: 8.1 years
Last activity: 7.2 years

Posted on 09-29-08 02:39:55 PM (last edited by messiaen at 09-29-08 12:20 PM) Link | Quote
Here it is, a conditional collision command that will detect the model ID used by an object and assign the right collision pointer from a pointer list in the ROM! It was possible thanks to Yoshielectron warning me that there is a "graphic pointer" list stored in the RAM, so I just made it compare all entries of that list with the current graphical pointer stored at the RAM Object. When there's a match, it loads the appropriate collision. Here is how it works:

Universal Solid Behavior

0009 0000
1200 0000 0B00 1000 # segmented address of collision pointer list
0800 0000
0C00 0000 8038 39CC
0900 0000

At 0x1000 of Bank 0x0B there should be a list of segmented collision pointers. It must be word aligned (multiple of 4) and its lenght should be 0x400, enough to hold 0x100 collision pointers. The first entry will be unused, because there isn't a Model ID 0x00. To find the the right spot for a pointer, just do [Model_id * 4].

Here's the source as well as compiled code to be patched into the ROM. Later I will insert comments in the code.

I tested it a lot in Nemu and then in one of my "Platform Battlefield" patches by assigning all objects the same "master" solid behavior and seeing if the appropriate collision was loaded.

There is, however, a small problem. Some bigger objects needs to have their collision loaded from a greater distance from Mario than the usual setting. That's what the "0E 43 xx xx" command does. To avoid problems, I guess the pointer list could also contain another argument indicating this setting. I'll take a look to see how it works, maybe TT64 could calculate a safe value (object size + x) from the imported object polygon data?

____________________
Mario 64 notes @ http://sites.google.com/site/messiaen64/
Me-me
340
Level: 41


Posts: 28/341
EXP: 461681
For next: 18464

Since: 08-05-07


Since last post: 9.7 years
Last activity: 8.1 years

Posted on 10-02-08 02:03:30 PM Link | Quote
This require a hex editor right?

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


Posts: 274/1085
EXP: 2594047
For next: 134753

Since: 11-20-07


Since last post: 8.1 years
Last activity: 7.2 years

Posted on 10-02-08 03:59:18 PM Link | Quote
Yes, but this is a possible solution for new levels, not for existing ones. There's isn't a lot of pratical applications for it now, but with the polygon importer in sight it may be very useful.

Something else I'm experimenting is with expanded memory. Yoshielectron did a sucessfull experiment loading some data in the memory above 0x80400000, manually editing the segment memory pointer table and calling some behavior from there. The segmented_to_virtual function, which translates all "bank" pointers (ie, 07001000) to its precise location in RAM works with this, so that's good news.

What I'm trying to do is a hybrid 0x16/0x17 Level command that will copy a block of data from the ROM to a specified RAM address (like the 0x16 command, but in the expanded memory) and then update the segment pointer table (like that 0x17 command, but instead of dynamically allocating the memory, with the RAM address provided).

Something like:

[XX] 00 00 [07] [80 44 00 00 00] [01 20 00 00] [01 20 90 00]
Command, Target Bank, Target RAM, ROM block.

You would have to manage this memory manually, but with so much extra space it could be amazing to have something like 2 meg level banks! Loading ASM on the expanded memory seems to work well, so maybe some very basic loader function could be hooked in the beggining of the game to load stuff at the expanded memory.

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


Posts: 282/621
EXP: 1135507
For next: 21612

Since: 07-27-07

From: Montreal, Canada

Since last post: 4.7 years
Last activity: 1.2 years

Posted on 10-05-08 09:30:23 PM (last edited by VL-Tone at 10-05-08 06:30 PM) Link | Quote
Time: Now - Date: Today - Weather: What can be seen outside. - Mood: How it feels. Answer to the universe: 42
Congratulation messiaen, that "conditional collision" command is just what we needed!

I'll be able to make great use of it once I reach this part of the process in the level importer. It would be ideal though to be able to load the distance parameter as well, but at worse I could make that parameter settable on at the behavior level.

Having expanded RAM would also be very useful eventually, as with the importer people will realize quickly how limited it is now. I think we'll still have limited space for the texture cache though.

____________________
messiaen
Catgirl
Level: 68


Posts: 285/1085
EXP: 2594047
For next: 134753

Since: 11-20-07


Since last post: 8.1 years
Last activity: 7.2 years

Posted on 10-05-08 10:11:34 PM (last edited by messiaen at 10-12-08 01:41 PM) Link | Quote
Yoshielectron has made some very interesting progress on extended memory, he managed to use one of the "unused" segments to get Peach's bank in the "Inside Castle" level, so that might be a very interesting possibility.

I'm testing more the "conditional collision" and the collision distance setting is really important for maximum behavior flexibility. However, it seems that some pretty general values works well with bigger objects. I copied the value (0x0BB8) from the "Tower" behavior and it seems to work ok for all objects I've tried.

---

Edit: Ok, I got a working command that loads a block of ROM data into extended memory and assigns it a segment ID.

[10] 00 00 [xx] [xx xx xx xx] [xx xx xx xx] [xx xx xx xx]
00. Command
01-2. Unused (I didn't bother to implement a variable lenght)
03. Target segment
04-07: RAM Address Target - ie: 80440000.
08-11: ROM Block start
12-16: ROM Block end

Here's the source. The best way to get it loaded is to hook some sort of loader in the beggining of the game, so it can run directly from extended memory.

To test it, I made a "Flatworld" non-extended ROM, so it can work with Nemu.

____________________
Mario 64 notes @ http://sites.google.com/site/messiaen64/
messiaen
Catgirl
Level: 68


Posts: 405/1085
EXP: 2594047
For next: 134753

Since: 11-20-07


Since last post: 8.1 years
Last activity: 7.2 years

Posted on 11-23-08 04:43:04 PM Link | Quote
I must inform that Cellar Dweller released an open-source N64 disassembler specifically aimed to Super Mario 64 (useful for other games aswell if you adjust the memory mapping). The most interesting thing is a "symbol file" support, ie, it can label user-defined functions/addresses. For anyone interesting in compiling it into Windows, be sure to read that thread because some very minor changes are necessary.

But the main reason of this is post is that I'm thinking how to improve the "flexible collision" custom behavior command - which loads the right collision based on the Model ID used by the object. As stated before, right now you have to specify a segmented pointer (Bank + Offset) which is used as the base address of a collision pointer list.

The problem with this approach is that if you want to use the regular behaviors (ie, change the 0x2A command to 0x12) with this, you'll end up crashing the original levels, as the pointers will be invalid.

I think a very good solution would be to have a separate collision pointer list for each level in the game. This way, the command would be truly a universal collision command, so the same behavior (ie, rotation around Y axis) could be used in all levels, and even the original levels could share behaviors, opening up a lot of new possibilities.

What it would do is to first read the current level ID (which is a global variable in RAM), and from this result choose the right collision pointer list. With extended memory, it won't be probably a have all these pointer lists loaded at RAM, but probably an even better (and not hard to do) approach would be to copy it from the ROM using one of the DMA functions.

I'm not sure how much VL-Tone is willing to modify the original game to have these extra features (extended memory is surely needed for this), but I feel it's really worth it.

Also, using a similar approach Koopa-The-Quick could have extra params (ie, for params above 6, a "trajectory pointer table" would be read) to have a maximum of 255 trajectories.

Perhaps it would be nice to try to implement these things before the polygon importer (ie, an experimental release), as they would be certainly very useful even for the original levels.

Ok, post is already too long, enough with ideas for now .

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


Posts: 351/621
EXP: 1135507
For next: 21612

Since: 07-27-07

From: Montreal, Canada

Since last post: 4.7 years
Last activity: 1.2 years

Posted on 11-23-08 07:22:42 PM (last edited by VL-Tone at 11-23-08 04:23 PM) Link | Quote
Time: Now - Date: Today - Weather: What can be seen outside. - Mood: How it feels. Answer to the universe: 42
That's really nice! Cellar Dweller is a really good ROM hacker (and programmer), too bad he's not posting here anymore (I won't get into details about why this is the case, but just look at the last thread he posted here to see how things got a little sour...).

I'm all for modifying the original game to add nice features like the ones you're working on. The only thing is that I don't feel like getting my hands into the ASM part too much (Though I have a good understanding of ASM, just the .obj importer and all the interface that goes with it will take any time I can devote to SM64 hacking).

We should work together so that the new functions you implement can work well with future versions of TT64. Before I can implement these in TT64, the changes will have to be stabilized up to a point where I won't have to constantly make radical changes to the TT64 code.

You should make a list of all the features you'd like to implement and how do you think TT64 could handle them. Many of the features you proposed would be useful for version 7.0b, so maybe you should make a list of modifications that could be incorporated in that version. It's possible that I could release a version 6.5b with these features without the level importer, I'll give you an answer when there's a clearer plan about which features would be added.






____________________
messiaen
Catgirl
Level: 68


Posts: 407/1085
EXP: 2594047
For next: 134753

Since: 11-20-07


Since last post: 8.1 years
Last activity: 7.2 years

Posted on 11-24-08 08:09:14 PM Link | Quote
Most of these ASM hacks are more "dirty work" than anything, so I think I can handle the ASM work. What has to discussed is the design/implementation of these features.

The first thing is that extended memory will be required for this. So far, what I have been doing is to load a block of custom ASM from the ROM into extended memory in the title screen.

Even before the "flexible collision", what could be implemented is a "trajectory" interface. From what I have already looked, I think the best approach would to have a master list of trajectories, which would be shared by objects such as Koopa-the-Quick, Platform on Tracks and others.

The "Platform on Tracks" behavior already use such list of trajectories, which is in the checksum area. However, to make things even easier for TT64, I think a good approach would be to move all the trajectories out of the specific level-specific banks they are loaded into, and move them to a different area in ROM, which could be loaded all the time into extended memory. This way, the game would never crash if you chose an behavior param which leads to an invalid pointer. The trajectories themselves would be edited in a similar interface as 0x24 objects (perhaps with a different wireframe color) and could have user defined labels.

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


Posts: 352/621
EXP: 1135507
For next: 21612

Since: 07-27-07

From: Montreal, Canada

Since last post: 4.7 years
Last activity: 1.2 years

Posted on 11-25-08 03:17:15 AM Link | Quote
Time: Now - Date: Today - Weather: What can be seen outside. - Mood: How it feels. Answer to the universe: 42
I'm all for implementing extended memory support in TT64. It could be very useful for the level importer, since for now the complexity of a level polygon mesh is more limited by RAM than by the N64 3d engine. And obviously, it would also be very useful to insert new behaviors and ASM routines.

I'd like to know, how TT64 can determine if a command refers to data in the extended memory and load the appropriate ROM data? I guess it could be done by checking for RAM pointers in a specific range. Could you provide this address range, and is it likely to change as you're working on this?

A standardized trajectory system is also a great idea, I was hesitant to implement a trajectory editor since this data seems scattered around and you can't programmatically find where it is in some cases unless you disassemble behavior ASM functions.

I suggest that we put an offset table before the actual data that would be used by TT64 to find paths, without having it hard coded in the editor. The offset table for built-in paths that we move to the extended memory would be hardcoded in TT64, but only for when you "Enable Flatworld" (that process could be renamed) and all the modifications we plan will first be applied. Once first written the table in the ROM could be modified afterward to have longer paths for example.

We should use offset tables whenever we can, even when they're not used by the game engine itself, they're very useful to manage multiple chunks of data that can change in size while editing. There's only a few offset tables used in the main structures of SM64, and that's why I can't easily make an editor that inserts or delete stuff within data structures. There are offset tables before the text data, and that's why it was easy to make the Text Wrangler so flexible, in that it can shorten or lengthen strings of text, with the only limitation that you can't make the total length of all strings combined exceed the original size. (I hope this all makes sense to you, I'm a little tired now so I may write incomprehensible stuff!)

Now, we need a standard way for TT64 to find which paths are linked to which behaviors and/or levels.

As for the flexible collision, I think you have a better idea than me about how you intend to implement it, you've talked about a new approach to this problem, I'll wait until you provide more detail to see how it can be handled by TT64.

So to summarize we currently have 3 main ASM feature additions planned, and I'm 100% for them:

1. Extending RAM.
2. Standardized trajectory system (in extended RAM)
3. Collision data automatically linked to the polygon model using it.

____________________
messiaen
Catgirl
Level: 68


Posts: 408/1085
EXP: 2594047
For next: 134753

Since: 11-20-07


Since last post: 8.1 years
Last activity: 7.2 years

Posted on 11-25-08 11:35:58 AM Link | Quote
Originally posted by VL-Tone
I'd like to know, how TT64 can determine if a command refers to data in the extended memory and load the appropriate ROM data? I guess it could be done by checking for RAM pointers in a specific range. Could you provide this address range, and is it likely to change as you're working on this?


For loading "level banks" into extended memory, I have been experimenting with this custom command for banks which wouldn't normally fit into memory:

[10] [10] 00 [xx] [xx xx xx xx] [xx xx xx xx] [xx xx xx xx]
00. Command 0x10
01. Lenght
02. Unused
03. Target segment ('bank')
04-07: RAM Address Target - ie: 80500000.
08-11: ROM Block start
12-16: ROM Block end

Apart from the RAM target, it's basically the same thing as the 0x17. For this, almost nothing would have to be changed in TT64, except for making it (when the polygon importer is ready) manage the RAM locations of the extended memory banks. This would be simple - once we decide on a general memory layout- , you would just have to calculate the size of each bank and not make them collide with each other. Most regular (original) banks would still be loaded with the 0x17 command, except perhaps for the behavior bank which would be nice to move to extended memory.

By the way, I was looking at the segment table and it seems there is room for 0x20 (32) banks, 0x18 being the last one used (which is probably sound-related).

For other kinds of data (not in level-specific banks) such as custom code/trajectories and eventually water pointers/text, perhaps the first meg in extended memory could be the exact mirror of a huge block of data in the ROM reserved for this. So, even if the pointers lists would be RAM pointers (ie, 80412000) the conversion would be always the same, which is much simpler than have to dealing with segmented pointers.

Originally posted by VL-Tone
We should use offset tables whenever we can, even when they're not used by the game engine itself, they're very useful to manage multiple chunks of data that can change in size while editing. There's only a few offset tables used in the main structures of SM64, and that's why I can't easily make an editor that inserts or delete stuff within data structures.


Don't worry, this makes sense and I'll keep in mind this . Offset tables will be actually needed for these master lists, the easiest solution being making it a direct RAM pointer which, if you don't see any problem with the previous suggestion of having a huge block of ROM data to be a exact mirror of the first meg of extended memory, could be easily converted to a specific ROM offset.

Originally posted by VL-Tone
Now, we need a standard way for TT64 to find which paths are linked to which behaviors and/or levels.


I think the easiest solution is this:

Make a "master" trajectory interface, which would read the coordinates for the specific trajectory ID you are dealing with and plot them on screen as editable wireframe boxes, regardless of which level you are (since that's how it will work in the game). The trajectories themselves can have labels, so the user will know in which levels they are originally used. Afterwards, just change the behavior param labels of the objects which use this system to "Trajectory ID" (and make it display the trajectory label, but not necessarily the trajectory itself).

Originally posted by VL-Tone
As for the flexible collision, I think you have a better idea than me about how you intend to implement it, you've talked about a new approach to this problem, I'll wait until you provide more detail to see how it can be handled by TT64.


Right, I'll still have to think a bit more about it. So, to summarize here is my initial suggestion about how to deal with extended memory:

1. Use the first meg of extended memory to load a huge block of data from the ROM, which contains not only
custom code but also misc data (ie, paths, collision/water pointers).

2. Use RAM pointer tables for most kinds of data, but the conversion will be very easy.

3. Use the remaining 3 megs of extended memory to load huge level banks.

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


Posts: 353/621
EXP: 1135507
For next: 21612

Since: 07-27-07

From: Montreal, Canada

Since last post: 4.7 years
Last activity: 1.2 years

Posted on 11-28-08 03:15:16 PM (last edited by VL-Tone at 11-28-08 01:10 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


For loading "level banks" into extended memory, I have been experimenting with this custom command for banks which wouldn't normally fit into memory:

[10] [10] 00 [xx] [xx xx xx xx] [xx xx xx xx] [xx xx xx xx]
00. Command 0x10
01. Lenght
02. Unused
03. Target segment ('bank')
04-07: RAM Address Target - ie: 80500000.
08-11: ROM Block start
12-16: ROM Block end

Apart from the RAM target, it's basically the same thing as the 0x17. For this, almost nothing would have to be changed in TT64, except for making it (when the polygon importer is ready) manage the RAM locations of the extended memory banks. This would be simple - once we decide on a general memory layout- , you would just have to calculate the size of each bank and not make them collide with each other. Most regular (original) banks would still be loaded with the 0x17 command, except perhaps for the behavior bank which would be nice to move to extended memory.

By the way, I was looking at the segment table and it seems there is room for 0x20 (32) banks, 0x18 being the last one used (which is probably sound-related).

For other kinds of data (not in level-specific banks) such as custom code/trajectories and eventually water pointers/text, perhaps the first meg in extended memory could be the exact mirror of a huge block of data in the ROM reserved for this. So, even if the pointers lists would be RAM pointers (ie, 80412000) the conversion would be always the same, which is much simpler than have to dealing with segmented pointers.



Oh so the extended memory has a segment/bank number too? In that case, it will be easy to implement in TT64, I'll just treat the 0x10 command like a variation on the 0x17 command.

Originally posted by messiaen


Don't worry, this makes sense and I'll keep in mind this . Offset tables will be actually needed for these master lists, the easiest solution being making it a direct RAM pointer which, if you don't see any problem with the previous suggestion of having a huge block of ROM data to be a exact mirror of the first meg of extended memory, could be easily converted to a specific ROM offset.



I have no problems with that.

Originally posted by messiaen

I think the easiest solution is this:

Make a "master" trajectory interface, which would read the coordinates for the specific trajectory ID you are dealing with and plot them on screen as editable wireframe boxes, regardless of which level you are (since that's how it will work in the game). The trajectories themselves can have labels, so the user will know in which levels they are originally used. Afterwards, just change the behavior param labels of the objects which use this system to "Trajectory ID" (and make it display the trajectory label, but not necessarily the trajectory itself).



I also thought about this solution, but it breaks the TT64 interface in that all other parameters you normally edit apply to the current level. But I guess it's a better solution anyway that will be easier to implement.

Originally posted by messiaen

Right, I'll still have to think a bit more about it. So, to summarize here is my initial suggestion about how to deal with extended memory:

1. Use the first meg of extended memory to load a huge block of data from the ROM, which contains not only
custom code but also misc data (ie, paths, collision/water pointers).

2. Use RAM pointer tables for most kinds of data, but the conversion will be very easy.

3. Use the remaining 3 megs of extended memory to load huge level banks.



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.


____________________
Stevoisiak
Member
Level: 38


Posts: 167/283
EXP: 345477
For next: 24970

Since: 11-22-07

From: New York, Long Island

Since last post: 12.3 years
Last activity: 5.6 years

Posted on 11-28-08 03:41:57 PM Link | Quote
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.
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.

30 database queries, 16 query cache hits.
Query execution time:  0.083008 seconds
Script execution time:  0.062781 seconds
Total render time:  0.145789 seconds


TidyHTML vomit below
line 1 column 1 - Warning: missing <!DOCTYPE> declaration
line 2 column 300 - 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 128 - 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 229 column 9 - Warning: <div> isn't allowed in <table> elements
line 152 column 17 - Info: <table> previously mentioned
line 231 column 9 - Warning: missing <tr>
line 249 column 13 - Warning: missing <tr>
line 250 column 99 - Warning: unescaped & or unknown entity "&postid"
line 252 column 73 - Warning: <style> isn't allowed in <td> elements
line 252 column 9 - Info: <td> previously mentioned
line 252 column 137 - Warning: missing </div>
line 263 column 9 - Warning: <div> isn't allowed in <table> elements
line 152 column 17 - Info: <table> previously mentioned
line 265 column 9 - Warning: missing <tr>
line 283 column 13 - Warning: missing <tr>
line 284 column 99 - Warning: unescaped & or unknown entity "&postid"
line 298 column 1087 - Warning: unescaped & or unknown entity "&page"
line 303 column 9 - Warning: <div> isn't allowed in <table> elements
line 152 column 17 - Info: <table> previously mentioned
line 305 column 9 - Warning: missing <tr>
line 323 column 13 - Warning: missing <tr>
line 324 column 99 - Warning: unescaped & or unknown entity "&postid"
line 326 column 73 - Warning: <style> isn't allowed in <td> elements
line 326 column 9 - Info: <td> previously mentioned
line 326 column 137 - Warning: missing </div>
line 347 column 9 - Warning: <div> isn't allowed in <table> elements
line 152 column 17 - Info: <table> previously mentioned
line 349 column 9 - Warning: missing <tr>
line 367 column 13 - Warning: missing <tr>
line 368 column 99 - Warning: unescaped & or unknown entity "&postid"
line 381 column 9 - Warning: <div> isn't allowed in <table> elements
line 152 column 17 - Info: <table> previously mentioned
line 383 column 9 - Warning: missing <tr>
line 401 column 13 - Warning: missing <tr>
line 402 column 99 - Warning: unescaped & or unknown entity "&postid"
line 404 column 73 - Warning: <style> isn't allowed in <td> elements
line 404 column 9 - Info: <td> previously mentioned
line 404 column 1511 - Warning: missing </font> before <hr>
line 416 column 1 - Warning: inserting implicit <font>
line 404 column 137 - Warning: missing </div>
line 423 column 9 - Warning: <div> isn't allowed in <table> elements
line 152 column 17 - Info: <table> previously mentioned
line 425 column 9 - Warning: missing <tr>
line 443 column 13 - Warning: missing <tr>
line 444 column 99 - Warning: unescaped & or unknown entity "&postid"
line 461 column 9 - Warning: <div> isn't allowed in <table> elements
line 152 column 17 - Info: <table> previously mentioned
line 463 column 9 - Warning: missing <tr>
line 481 column 13 - Warning: missing <tr>
line 482 column 99 - Warning: unescaped & or unknown entity "&postid"
line 484 column 73 - Warning: <style> isn't allowed in <td> elements
line 484 column 9 - Info: <td> previously mentioned
line 484 column 137 - Warning: missing </div>
line 489 column 9 - Warning: <div> isn't allowed in <table> elements
line 152 column 17 - Info: <table> previously mentioned
line 491 column 9 - Warning: missing <tr>
line 509 column 13 - Warning: missing <tr>
line 510 column 99 - Warning: unescaped & or unknown entity "&postid"
line 531 column 9 - Warning: <div> isn't allowed in <table> elements
line 152 column 17 - Info: <table> previously mentioned
line 533 column 9 - Warning: missing <tr>
line 551 column 13 - Warning: missing <tr>
line 552 column 99 - Warning: unescaped & or unknown entity "&postid"
line 557 column 9 - Warning: <div> isn't allowed in <table> elements
line 152 column 17 - Info: <table> previously mentioned
line 559 column 9 - Warning: missing <tr>
line 577 column 13 - Warning: missing <tr>
line 578 column 99 - Warning: unescaped & or unknown entity "&postid"
line 594 column 9 - Warning: <div> isn't allowed in <table> elements
line 152 column 17 - Info: <table> previously mentioned
line 596 column 9 - Warning: missing <tr>
line 614 column 13 - Warning: missing <tr>
line 615 column 99 - Warning: unescaped & or unknown entity "&postid"
line 617 column 73 - Warning: <style> isn't allowed in <td> elements
line 617 column 9 - Info: <td> previously mentioned
line 617 column 137 - Warning: missing </div>
line 624 column 9 - Warning: <div> isn't allowed in <table> elements
line 152 column 17 - Info: <table> previously mentioned
line 626 column 9 - Warning: missing <tr>
line 644 column 13 - Warning: missing <tr>
line 645 column 99 - Warning: unescaped & or unknown entity "&postid"
line 668 column 9 - Warning: <div> isn't allowed in <table> elements
line 152 column 17 - Info: <table> previously mentioned
line 670 column 9 - Warning: missing <tr>
line 688 column 13 - Warning: missing <tr>
line 689 column 99 - Warning: unescaped & or unknown entity "&postid"
line 710 column 9 - Warning: <div> isn't allowed in <table> elements
line 152 column 17 - Info: <table> previously mentioned
line 712 column 9 - Warning: missing <tr>
line 730 column 13 - Warning: missing <tr>
line 731 column 99 - Warning: unescaped & or unknown entity "&postid"
line 733 column 73 - Warning: <style> isn't allowed in <td> elements
line 733 column 9 - Info: <td> previously mentioned
line 733 column 137 - Warning: missing </div>
line 747 column 9 - Warning: <div> isn't allowed in <table> elements
line 152 column 17 - Info: <table> previously mentioned
line 749 column 9 - Warning: missing <tr>
line 767 column 13 - Warning: missing <tr>
line 768 column 99 - Warning: unescaped & or unknown entity "&postid"
line 779 column 9 - Warning: <div> isn't allowed in <table> elements
line 152 column 17 - Info: <table> previously mentioned
line 781 column 9 - Warning: missing <tr>
line 799 column 13 - Warning: missing <tr>
line 800 column 99 - Warning: unescaped & or unknown entity "&postid"
line 802 column 73 - Warning: <style> isn't allowed in <td> elements
line 802 column 9 - Info: <td> previously mentioned
line 802 column 137 - Warning: missing </div>
line 823 column 9 - Warning: <div> isn't allowed in <table> elements
line 152 column 17 - Info: <table> previously mentioned
line 825 column 9 - Warning: missing <tr>
line 843 column 13 - Warning: missing <tr>
line 844 column 99 - Warning: unescaped & or unknown entity "&postid"
line 887 column 9 - Warning: <div> isn't allowed in <table> elements
line 152 column 17 - Info: <table> previously mentioned
line 889 column 9 - Warning: missing <tr>
line 907 column 13 - Warning: missing <tr>
line 908 column 99 - Warning: unescaped & or unknown entity "&postid"
line 910 column 73 - Warning: <style> isn't allowed in <td> elements
line 910 column 9 - Info: <td> previously mentioned
line 910 column 1511 - Warning: missing </font> before <blockquote>
line 910 column 1590 - Warning: inserting implicit <font>
line 910 column 1590 - Warning: missing </font> before <hr>
line 911 column 1 - Warning: inserting implicit <font>
line 911 column 1 - Warning: missing </font> before <hr>
line 927 column 3227 - Warning: inserting implicit <font>
line 928 column 1 - Warning: inserting implicit <font>
line 928 column 1 - Warning: missing </font> before <blockquote>
line 931 column 3447 - Warning: inserting implicit <font>
line 931 column 3447 - Warning: missing </font> before <hr>
line 932 column 1 - Warning: inserting implicit <font>
line 932 column 1 - Warning: missing </font> before <hr>
line 934 column 3966 - Warning: inserting implicit <font>
line 935 column 1 - Warning: inserting implicit <font>
line 935 column 1 - Warning: missing </font> before <blockquote>
line 938 column 4036 - Warning: inserting implicit <font>
line 938 column 4036 - Warning: missing </font> before <hr>
line 939 column 1 - Warning: inserting implicit <font>
line 939 column 1 - Warning: missing </font> before <hr>
line 942 column 4723 - Warning: inserting implicit <font>
line 943 column 1 - Warning: inserting implicit <font>
line 943 column 1 - Warning: missing </font> before <blockquote>
line 946 column 4983 - Warning: inserting implicit <font>
line 946 column 4983 - Warning: missing </font> before <hr>
line 947 column 1 - Warning: inserting implicit <font>
line 947 column 1 - Warning: missing </font> before <hr>
line 955 column 1 - Warning: inserting implicit <font>
line 910 column 137 - Warning: missing </div>
line 962 column 9 - Warning: <div> isn't allowed in <table> elements
line 152 column 17 - Info: <table> previously mentioned
line 964 column 9 - Warning: missing <tr>
line 982 column 13 - Warning: missing <tr>
line 983 column 99 - Warning: unescaped & or unknown entity "&postid"
line 990 column 17 - Warning: missing <tr>
line 990 column 17 - Warning: discarding unexpected <table>
line 993 column 35 - Warning: missing <tr>
line 993 column 94 - Warning: unescaped & or unknown entity "&page"
line 993 column 128 - Warning: unescaped & or unknown entity "&page"
line 993 column 50 - Warning: missing </font> before </td>
line 993 column 163 - Warning: missing </font> before </table>
line 995 column 35 - Warning: missing <tr>
line 995 column 50 - Warning: missing </font> before </td>
line 996 column 37 - Warning: unescaped & or unknown entity "&id"
line 995 column 182 - Warning: missing </font> before </table>
line 997 column 17 - Warning: discarding unexpected </textarea>
line 997 column 28 - Warning: discarding unexpected </form>
line 997 column 35 - Warning: discarding unexpected </embed>
line 997 column 43 - Warning: discarding unexpected </noembed>
line 997 column 53 - Warning: discarding unexpected </noscript>
line 997 column 64 - Warning: discarding unexpected </noembed>
line 997 column 74 - Warning: discarding unexpected </embed>
line 997 column 82 - Warning: discarding unexpected </table>
line 997 column 90 - Warning: discarding unexpected </table>
line 999 column 9 - Warning: missing </font> before <table>
line 1011 column 25 - Warning: discarding unexpected </font>
line 1020 column 58 - Warning: discarding unexpected </font>
line 998 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 111 - Warning: <img> lacks "alt" attribute
line 161 column 161 - Warning: <img> lacks "alt" attribute
line 172 column 15 - Warning: <img> lacks "alt" attribute
line 234 column 22 - Warning: <img> lacks "alt" attribute
line 234 column 63 - Warning: <img> lacks "alt" attribute
line 234 column 112 - Warning: <img> lacks "alt" attribute
line 234 column 162 - Warning: <img> lacks "alt" attribute
line 245 column 15 - Warning: <img> lacks "alt" attribute
line 252 column 693 - Warning: <img> lacks "alt" attribute
line 260 column 2966 - Warning: <img> lacks "alt" attribute
line 260 column 3125 - Warning: <img> lacks "alt" attribute
line 268 column 22 - Warning: <img> lacks "alt" attribute
line 268 column 63 - Warning: <img> lacks "alt" attribute
line 268 column 111 - Warning: <img> lacks "alt" attribute
line 268 column 161 - Warning: <img> lacks "alt" attribute
line 279 column 15 - Warning: <img> lacks "alt" attribute
line 308 column 22 - Warning: <img> lacks "alt" attribute
line 308 column 63 - Warning: <img> lacks "alt" attribute
line 308 column 112 - Warning: <img> lacks "alt" attribute
line 308 column 162 - Warning: <img> lacks "alt" attribute
line 319 column 15 - Warning: <img> lacks "alt" attribute
line 326 column 693 - Warning: <img> lacks "alt" attribute
line 344 column 3216 - Warning: <img> lacks "alt" attribute
line 344 column 3375 - Warning: <img> lacks "alt" attribute
line 352 column 22 - Warning: <img> lacks "alt" attribute
line 352 column 63 - Warning: <img> lacks "alt" attribute
line 352 column 111 - Warning: <img> lacks "alt" attribute
line 352 column 161 - Warning: <img> lacks "alt" attribute
line 363 column 15 - Warning: <img> lacks "alt" attribute
line 386 column 22 - Warning: <img> lacks "alt" attribute
line 386 column 63 - Warning: <img> lacks "alt" attribute
line 386 column 112 - Warning: <img> lacks "alt" attribute
line 386 column 162 - Warning: <img> lacks "alt" attribute
line 397 column 15 - Warning: <img> lacks "alt" attribute
line 404 column 693 - Warning: <img> lacks "alt" attribute
line 420 column 4076 - Warning: <img> lacks "alt" attribute
line 420 column 4235 - Warning: <img> lacks "alt" attribute
line 428 column 22 - Warning: <img> lacks "alt" attribute
line 428 column 63 - Warning: <img> lacks "alt" attribute
line 428 column 111 - Warning: <img> lacks "alt" attribute
line 428 column 161 - Warning: <img> lacks "alt" attribute
line 439 column 15 - Warning: <img> lacks "alt" attribute
line 466 column 22 - Warning: <img> lacks "alt" attribute
line 466 column 63 - Warning: <img> lacks "alt" attribute
line 466 column 112 - Warning: <img> lacks "alt" attribute
line 466 column 162 - Warning: <img> lacks "alt" attribute
line 477 column 15 - Warning: <img> lacks "alt" attribute
line 484 column 693 - Warning: <img> lacks "alt" attribute
line 486 column 2313 - Warning: <img> lacks "alt" attribute
line 486 column 2472 - Warning: <img> lacks "alt" attribute
line 494 column 22 - Warning: <img> lacks "alt" attribute
line 494 column 63 - Warning: <img> lacks "alt" attribute
line 494 column 111 - Warning: <img> lacks "alt" attribute
line 494 column 161 - Warning: <img> lacks "alt" attribute
line 505 column 15 - Warning: <img> lacks "alt" attribute
line 535 column 15 - Warning: <img> proprietary attribute value "absmiddle"
line 535 column 15 - Warning: <img> lacks "alt" attribute
line 535 column 58 - Warning: <img> proprietary attribute value "absmiddle"
line 535 column 58 - Warning: <img> lacks "alt" attribute
line 535 column 101 - Warning: <img> proprietary attribute value "absmiddle"
line 535 column 101 - Warning: <img> lacks "alt" attribute
line 535 column 144 - Warning: <img> proprietary attribute value "absmiddle"
line 535 column 144 - Warning: <img> lacks "alt" attribute
line 535 column 187 - Warning: <img> proprietary attribute value "absmiddle"
line 535 column 187 - Warning: <img> lacks "alt" attribute
line 535 column 230 - Warning: <img> proprietary attribute value "absmiddle"
line 535 column 230 - Warning: <img> lacks "alt" attribute
line 536 column 22 - Warning: <img> lacks "alt" attribute
line 536 column 63 - Warning: <img> lacks "alt" attribute
line 536 column 112 - Warning: <img> lacks "alt" attribute
line 536 column 162 - Warning: <img> lacks "alt" attribute
line 537 column 11 - Warning: <img> lacks "alt" attribute
line 547 column 15 - Warning: <img> lacks "alt" attribute
line 554 column 106 - Warning: <img> proprietary attribute value "absmiddle"
line 554 column 106 - Warning: <img> lacks "alt" attribute
line 562 column 22 - Warning: <img> lacks "alt" attribute
line 562 column 63 - Warning: <img> lacks "alt" attribute
line 562 column 111 - Warning: <img> lacks "alt" attribute
line 562 column 161 - Warning: <img> lacks "alt" attribute
line 573 column 15 - Warning: <img> lacks "alt" attribute
line 599 column 22 - Warning: <img> lacks "alt" attribute
line 599 column 63 - Warning: <img> lacks "alt" attribute
line 599 column 112 - Warning: <img> lacks "alt" attribute
line 599 column 162 - Warning: <img> lacks "alt" attribute
line 610 column 15 - Warning: <img> lacks "alt" attribute
line 617 column 693 - Warning: <img> lacks "alt" attribute
line 621 column 2208 - Warning: <img> lacks "alt" attribute
line 621 column 2367 - Warning: <img> lacks "alt" attribute
line 629 column 22 - Warning: <img> lacks "alt" attribute
line 629 column 63 - Warning: <img> lacks "alt" attribute
line 629 column 111 - Warning: <img> lacks "alt" attribute
line 629 column 161 - Warning: <img> lacks "alt" attribute
line 640 column 15 - Warning: <img> lacks "alt" attribute
line 673 column 22 - Warning: <img> lacks "alt" attribute
line 673 column 63 - Warning: <img> lacks "alt" attribute
line 673 column 111 - Warning: <img> lacks "alt" attribute
line 673 column 161 - Warning: <img> lacks "alt" attribute
line 684 column 15 - Warning: <img> lacks "alt" attribute
line 707 column 2474 - Warning: <img> proprietary attribute value "absmiddle"
line 707 column 2474 - Warning: <img> lacks "alt" attribute
line 715 column 22 - Warning: <img> lacks "alt" attribute
line 715 column 63 - Warning: <img> lacks "alt" attribute
line 715 column 112 - Warning: <img> lacks "alt" attribute
line 715 column 162 - Warning: <img> lacks "alt" attribute
line 726 column 15 - Warning: <img> lacks "alt" attribute
line 733 column 693 - Warning: <img> lacks "alt" attribute
line 744 column 3030 - Warning: <img> lacks "alt" attribute
line 744 column 3189 - Warning: <img> lacks "alt" attribute
line 752 column 22 - Warning: <img> lacks "alt" attribute
line 752 column 63 - Warning: <img> lacks "alt" attribute
line 752 column 111 - Warning: <img> lacks "alt" attribute
line 752 column 161 - Warning: <img> lacks "alt" attribute
line 763 column 15 - Warning: <img> lacks "alt" attribute
line 784 column 22 - Warning: <img> lacks "alt" attribute
line 784 column 63 - Warning: <img> lacks "alt" attribute
line 784 column 112 - Warning: <img> lacks "alt" attribute
line 784 column 162 - Warning: <img> lacks "alt" attribute
line 795 column 15 - Warning: <img> lacks "alt" attribute
line 802 column 693 - Warning: <img> lacks "alt" attribute
line 820 column 4353 - Warning: <img> lacks "alt" attribute
line 820 column 4512 - Warning: <img> lacks "alt" attribute
line 828 column 22 - Warning: <img> lacks "alt" attribute
line 828 column 63 - Warning: <img> lacks "alt" attribute
line 828 column 111 - Warning: <img> lacks "alt" attribute
line 828 column 161 - Warning: <img> lacks "alt" attribute
line 839 column 15 - Warning: <img> lacks "alt" attribute
line 867 column 2553 - Warning: <img> proprietary attribute value "absmiddle"
line 867 column 2553 - Warning: <img> lacks "alt" attribute
line 892 column 22 - Warning: <img> lacks "alt" attribute
line 892 column 63 - Warning: <img> lacks "alt" attribute
line 892 column 112 - Warning: <img> lacks "alt" attribute
line 892 column 162 - Warning: <img> lacks "alt" attribute
line 903 column 15 - Warning: <img> lacks "alt" attribute
line 910 column 693 - Warning: <img> lacks "alt" attribute
line 933 column 3577 - Warning: <img> proprietary attribute value "absmiddle"
line 933 column 3577 - Warning: <img> lacks "alt" attribute
line 959 column 6645 - Warning: <img> lacks "alt" attribute
line 959 column 6804 - Warning: <img> lacks "alt" attribute
line 967 column 22 - Warning: <img> lacks "alt" attribute
line 967 column 63 - Warning: <img> lacks "alt" attribute
line 967 column 112 - Warning: <img> lacks "alt" attribute
line 967 column 162 - Warning: <img> lacks "alt" attribute
line 978 column 15 - Warning: <img> lacks "alt" attribute
line 996 column 44 - Warning: <img> proprietary attribute value "absmiddle"
line 996 column 142 - Warning: <img> proprietary attribute value "absmiddle"
line 996 column 245 - Warning: <img> proprietary attribute value "absmiddle"
line 1005 column 25 - Warning: <img> lacks "alt" attribute
line 1010 column 267 - Warning: <img> lacks "alt" attribute
line 910 column 1511 - Warning: trimming empty <font>
line 927 column 3227 - Warning: trimming empty <font>
line 934 column 3966 - Warning: trimming empty <font>
line 942 column 4723 - Warning: trimming empty <font>
line 990 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 250 column 27 - Warning: <nobr> is not approved by W3C
line 252 column 157 - Warning: <table> proprietary attribute "height"
line 252 column 222 - Warning: <td> proprietary attribute "background"
line 252 column 318 - Warning: <td> proprietary attribute "background"
line 252 column 408 - Warning: <table> proprietary attribute "height"
line 252 column 488 - Warning: <td> proprietary attribute "background"
line 252 column 1443 - Warning: <td> proprietary attribute "background"
line 284 column 27 - Warning: <nobr> is not approved by W3C
line 324 column 27 - Warning: <nobr> is not approved by W3C
line 326 column 157 - Warning: <table> proprietary attribute "height"
line 326 column 222 - Warning: <td> proprietary attribute "background"
line 326 column 318 - Warning: <td> proprietary attribute "background"
line 326 column 408 - Warning: <table> proprietary attribute "height"
line 326 column 488 - Warning: <td> proprietary attribute "background"
line 326 column 1443 - Warning: <td> proprietary attribute "background"
line 368 column 27 - Warning: <nobr> is not approved by W3C
line 402 column 27 - Warning: <nobr> is not approved by W3C
line 404 column 157 - Warning: <table> proprietary attribute "height"
line 404 column 222 - Warning: <td> proprietary attribute "background"
line 404 column 318 - Warning: <td> proprietary attribute "background"
line 404 column 408 - Warning: <table> proprietary attribute "height"
line 404 column 488 - Warning: <td> proprietary attribute "background"
line 404 column 1443 - Warning: <td> proprietary attribute "background"
line 444 column 27 - Warning: <nobr> is not approved by W3C
line 482 column 27 - Warning: <nobr> is not approved by W3C
line 484 column 157 - Warning: <table> proprietary attribute "height"
line 484 column 222 - Warning: <td> proprietary attribute "background"
line 484 column 318 - Warning: <td> proprietary attribute "background"
line 484 column 408 - Warning: <table> proprietary attribute "height"
line 484 column 488 - Warning: <td> proprietary attribute "background"
line 484 column 1443 - Warning: <td> proprietary attribute "background"
line 510 column 27 - Warning: <nobr> is not approved by W3C
line 552 column 27 - Warning: <nobr> is not approved by W3C
line 578 column 27 - Warning: <nobr> is not approved by W3C
line 615 column 27 - Warning: <nobr> is not approved by W3C
line 617 column 157 - Warning: <table> proprietary attribute "height"
line 617 column 222 - Warning: <td> proprietary attribute "background"
line 617 column 318 - Warning: <td> proprietary attribute "background"
line 617 column 408 - Warning: <table> proprietary attribute "height"
line 617 column 488 - Warning: <td> proprietary attribute "background"
line 617 column 1443 - Warning: <td> proprietary attribute "background"
line 645 column 27 - Warning: <nobr> is not approved by W3C
line 689 column 27 - Warning: <nobr> is not approved by W3C
line 731 column 27 - Warning: <nobr> is not approved by W3C
line 733 column 157 - Warning: <table> proprietary attribute "height"
line 733 column 222 - Warning: <td> proprietary attribute "background"
line 733 column 318 - Warning: <td> proprietary attribute "background"
line 733 column 408 - Warning: <table> proprietary attribute "height"
line 733 column 488 - Warning: <td> proprietary attribute "background"
line 733 column 1443 - Warning: <td> proprietary attribute "background"
line 768 column 27 - Warning: <nobr> is not approved by W3C
line 800 column 27 - Warning: <nobr> is not approved by W3C
line 802 column 157 - Warning: <table> proprietary attribute "height"
line 802 column 222 - Warning: <td> proprietary attribute "background"
line 802 column 318 - Warning: <td> proprietary attribute "background"
line 802 column 408 - Warning: <table> proprietary attribute "height"
line 802 column 488 - Warning: <td> proprietary attribute "background"
line 802 column 1443 - Warning: <td> proprietary attribute "background"
line 844 column 27 - Warning: <nobr> is not approved by W3C
line 908 column 27 - Warning: <nobr> is not approved by W3C
line 910 column 157 - Warning: <table> proprietary attribute "height"
line 910 column 222 - Warning: <td> proprietary attribute "background"
line 910 column 318 - Warning: <td> proprietary attribute "background"
line 910 column 408 - Warning: <table> proprietary attribute "height"
line 910 column 488 - Warning: <td> proprietary attribute "background"
line 910 column 1443 - Warning: <td> proprietary attribute "background"
line 983 column 27 - Warning: <nobr> is not approved by W3C
Info: Document content looks like HTML5
Info: No system identifier in emitted doctype
Tidy found 400 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