(Link to AcmlmWiki) Offline: thank ||bass
Register | Login
Views: 13,040,846
Main | Memberlist | Active users | Calendar | Chat | Online users
Ranks | FAQ | ACS | Stats | Color Chart | Search | Photo album
06-17-24 01:48 AM
0 users currently in SMW Hacking.
Acmlm's Board - I3 Archive - SMW Hacking - Add 255 sprites?
  
User name:
Password:
Reply:
 
Options: - -
Quik-Attach:
Preview for more options

Max size 1.00 MB, types: png, gif, jpg, txt, zip, rar, tar, gz, 7z, ace, mp3, ogg, mid, ips, bz2, lzh, psd

UserPost
mikeyk
Posts: 19/89
i'm not sure how the block loading routine works. is the whole level loaded once at the begining or does the game just load the parts that are about to come onscreen? either way
dealing with blocks that spawn sprites seems to complicate things greatly. once the sprite was spawned, what would become of the block? i would think that it would need to stay in place. if the sprite wasn't killed and we went back to the original screen, we'd expect it to be respawned. but after the sprite has been killed, then it shouldn't be. there seems to be unnecessary bookkeeping. there's also a couple more issues that i can think of, but it's quite possible i'm thinking about this whole thing wrong

on the other hand, i am familiar with how sprites are initialized and loaded into ram when they're about to come onscreen. i know for a fact that it would be very easy to write the snes code to split on the extra bit. that part would be short and sweet. so very easily 00 could indicate a green koopa if the extra bit was clear, and a custom sprite if it were set. i could create the system in my previous post easily in a day. the only semi-difficult or time-consuming thing would be making a program to automatically insert the code. the whole process of finding free space, inserting the .bin, modifying the reloc offsets, erasing the stuff that was inserted in the previous use of the program, etc.

i'm without a computer for the next 2-3 days, so i'll catch you guys later. maybe i can get something started when i come back.
HyperHacker
Posts: 2274/5072
It sounds like it might be easier to just change the ASM pointer of some unused sprite, say #12 as you mentioned, to grab the real code location from some other table. Just as object #0 can actually be one of several objects from a second list; you'd be doing the same with sprites. You could perhaps use the sprite # itself (0 for the first instance of #12, 1 for the second, etc) as the table index, or the sprite position (leaving the sprite's code to set up the actual position in-game).

I still think Smallhacker's idea is best, though. Put a specific block and use the size or one of the block # bytes as the sprite #, and hack it to spawn a sprite at that position instead of drawing a block.
mikeyk
Posts: 16/89
i'm not promising that i'll make a program, but i am seriously considering it. here's what i had in mind.

my plan is to add support for ~255 custom sprites by using the second extra bit. i know i could use the first extra bit as well and support ~765 sprites, but i wanted to leave this one free to use in sprite code. i think 255 custom sprites should be plenty.

i would hijack the code that calls sprite routines. my code would first check if the second extra bit was set. if not, i would return and let the game deal with that sprite like normal. (i would also return if the sprite uses the second extra bit itself). at this point i would know that we're dealing with a custom sprite and i would convert it. the game does many checks with the sprite number, so i would try and avoid this. i would store the sprite number to a ram location (for fun, lets just say $9962,x) and set the original sprite number ($9E,x) to 12 indicating a custom sprite.

from then on the custom code could use $9962,x to index a big table. the table would be of fixed length and have 9 bytes per sprite. 6 bytes for sprite properties (basically: tweaker code - asm information) and 3 for the code location. I would set the sprite properties, jump to the code, and be done with the custom routine.

there is a little problem using extra bits. they are actually stored in bits 2 and 3 (if the least significant bit is numbered 0) of 14D4,x by the level loading routine (see SNES $02A965). it’s only the sprite code for the goal tape that puts the bits in 187B,x and ANDs them out of 14D4,x.

$14D4,x is usually only used for the high byte of the sprite position, and this leads to some interesting consequences. The first is that goal tapes don't work very well on vertical levels. place a regular one on screen 05 and you'll notice it won't show up. this is because 14D4,x = 05 is interpreted as a secret exit (bit 2) on screen 01 (bit 0). using $14D4,x to hold the extra bits also explains all other sprites don't appear if they use them. the extra bits just mess up the high byte of their y position, and they are placed way off sceen.

when i planned to use an extra bit i was going to handle them as the goal tape did, but this would make them breakdown on vertical levels. perhaps i could fix this with a hack to the level loading routine.

so that's my plan. i'd appreciate some feedback.
Alastor
Posts: 5692/8204
gih... guh...

Okay, that's on the list.
Mozeki
Posts: 96/160
Originally posted by Smallhacker
More and more gets uncovered when it comes to sprite hacking, right? Sooner or later, sprite hacking will probably be like custom blocks. There'll be a program that inserts new sprite code to the ROM. However, there's a problem. Unlike custom blocks, one can't add new sprites, only overwrite old (or unused) ones. How to add new sprites?

One way would be to make changes to the level format and give all sprites one or two extra bytes to hold the neccesary information needed to separate the custom sprite from the normal one. However, this would cause incompability with Lunar Magic and would only work if Fu came back and decided to continue working on LM or releasing the source code. Yeah, right.

My idea is to assign certain MAP16 tiles to custom sprites. When a block is loaded by the level loading routine, it checks if it's a MAP16 block. If it is, it checks if it's in a MAP16->Sprite table. If it is in there, it ignores the block and places a sprite at that location instead. This would require a new sprite RAM table. An in-game sprite's entry in this table would be "00" if it's a standard SMW sprite. Any non-zero value means that the sprite is a custom sprite. This value is it's custom sprite ID number. It's then used to check a table containing 3 byte pointers pointing to the custom code. This method (which allows 255 sprites to be added) would ignore the sprite's actual ID number. However, it could be used as a second ID number byte, making a total of 65536 possible sprites... If there are that many MAP16 blocks, that is.

This method would be compatible with Lunar Magic. All you have to do is to place the MAP16 block you've assigned the sprite to in the level.

Did anybody understand what the crap I'm talking about, and if so, any comments?

And before you ask, no, I'm not planning on doing this myself. It's just an idea.

This seems like this could work if some planning was put out for it. BTW if this was to be done I really hope it doesn't use Decimals like blocktool
HyperHacker
Posts: 2223/5072
Heh, I thought of what Sukasa mentioned, but it being 5 AM or so, I thought it wouldn't work. Really, it does sound like a good idea.
Smallhacker
Posts: 575/832
Originally posted by SnifflySquirrel
it wouldn't involve sacrificing Map16 pages.

Well. My idea would only use one Map16 block per sprite. Instead, it would use a table that contains Map16 numbers and the custom sprite ID to turn the block into. Using entire pages was somebody else's idea.
SnifflySquirrel
Posts: 54/80
Sukasa makes a very valid point. It's up to an individual object's rendering code to write any block data that defines it. If that code decides to interpret the object data differently, without writing to the level layout, then it won't matter what it overlaps, because it will still be there. A few things in SMW already work this way, like screen exits (which are Extended Object 0) and some of LM's enhancements.

That being said, I would opt for the "unused sprite index + extra data + level-specific sprite table" method, myself. It sounds like it would be far less difficult to implement. Furthermore, it wouldn't involve sacrificing Map16 pages.
Sukasa
Posts: 889/2068
AND, if the routine doesn't place anything for the sprite blocks, you could have those on top of everything else, without having any problems. Shows up on top of everything else in LM, doesn't show up in SMW.
Smallhacker
Posts: 574/832
Originally posted by Glyph Phoenix
I didn't realize you were applying the 21 bits to your block-sprite idea. Having a sprite use LM's block data would indeed give you extra bits to work with, but blocks themselves are quite static--that's all I meant.

Actually, the 21 bits haven't got anything to do with the idea. I just wanted to prove you wrong by showing that blocks are more dynamic than sprites.
Glyphodon
Posts: 274/536
I didn't realize you were applying the 21 bits to your block-sprite idea. Having a sprite use LM's block data would indeed give you extra bits to work with, but blocks themselves are quite static--that's all I meant.

I still wouldn't go for the idea unless there were no more viable solutions, though. Hacking level loading routines, like I said, can't be much fun.
Smallhacker
Posts: 573/832
Originally posted by Glyph Phoenix
Again, totally missing the point. Blocks can't act differently until they're touched. Sprites, which can read just about any byte in RAM or ROM to change their appearence, behavior, etc. straight from the start, trump your 21 bits.

Appearently, you misunderstood my idea. The hacked level loading routine would translate the sprite blocks into real sprites before the level fades in and any other sprites have had a chance to execute anything. They're not blocks. They're sprites stored as blocks.

As for the "what to turn the 'sprite blocks' into" question: Let's set it to 25.
The level data is stored in Z order (from back to front). If we place a "sprite block" in the level and put a normal block on top of it, the "sprite block" would be loaded first of the two, right? Therefore, the loading code would load the "sprite block", translate it into a sprite and turn the block into thin air. Then, it would load the block placed on top of it, overwriting the thin air. The only problem I see with this method is that the "sprite block" can't be seen in LM unless you move the block on top of it.
Glyphodon
Posts: 271/536
Originally posted by Bio.exe
I've finally found where the extra bit is stored in RAM, they are stored at 7E187B(Sprite Stomp Immunity Flag Table) as bit 3 and 4


Good job, Bio. Those should come in handy. Isn't the location of the sprite in the tables stored in the X or Y register or something? If so, all we'd need is an LDA absolute indexed with X/Y and we'd be good to go.

Originally posted by Smallhacker
sprites have got 15 bits of data while MAP16 blocks have got 21 bits of data, which, technically, means that MAP16 blocks are MORE dynamic than sprites.


Again, totally missing the point. Blocks can't act differently until they're touched. Sprites, which can read just about any byte in RAM or ROM to change their appearence, behavior, etc. straight from the start, trump your 21 bits.

Originally posted by Smallhacker
Enough about that idea, since I belive that the other idea, the one that uses extra bits and unused sprites, would be better.


Let this be a lesson to you all. Nobody beats Glyph Phoenix in a battle of theoretical game mechanics. Viva la Extra Info!

...and they don't need to be unused. Extra Info + used sprites can work too.
HyperHacker
Posts: 2214/5072
There's plenty of space. The problem is with modifying the code so that it allows more sprites than there already are, without breaking LM compatibility.

Now if we had LM's source we could just modify the routine it uses for ExGFX, timer/music override, etc, since they already work by adding things into the level data. Another project made unneccessarily difficult due to having to keep compatibility with closed-source software.

I like the Map16 idea though. AFAIK, the Direct Map16 Access feature can insert blocks up to #FFFF (though I don't think LM would let you do this ), and only up to #FFF are valid. If LM doesn't complain about it, you could break this down into bits like so:
fsss ssss bbbb bbbb
f=custom sprite flag, s=sprite #, b=block #. If the custom sprite flag is set, the next 7 bits specify the custom sprite # (0-127), and the remaining 8 specify the block #. This way you could create one of 128 custom sprites overtop of one of 256 blocks. A table elsewhere in the ROM could specify which Map16 page these blocks come from in each level, and if necessary, divide the custom sprites into groups of 128 and use a similar table to specify which group to use in each level.

I realize I should probably do some things like see if LM does care about invalid block numbers, and if the block numbers are in fact 16-bit, but I really, really need to go to sleep right now.
Billiards Koopa
Posts: 74/174
I have no clue about ASM, but couldn't you use that program that expands ROMs to create extra space.
Alastor
Posts: 5661/8204
Originally posted by Skreename
Wouldn't there be a problem with trying to overlap the new block-sprites with normal blocks? Not much of an issue for solid blocks, I know, but I'm sure there are cases in which it could be significant.
Read the ****ing thread.
Skreename
Posts: 967/1427
Wouldn't there be a problem with trying to overlap the new block-sprites with normal blocks? Not much of an issue for solid blocks, I know, but I'm sure there are cases in which it could be significant.

(I haven't done too much with it so I don't know all the nuances, so I may not be completely accurate with it...)

Otherwise, it sounds decently good. Glyph Phoenix's idea sounds a bit better, but.. that's okay.
Sukasa
Posts: 885/2068
I like that Idea. No holes, no sprite overlapping, etc. GP: You can so- makew the block a copy of a normal one, then have to routine read it as a sprite generation block.

Also, this routine only needs to run once. Then, if you use code $FE (I think $FF means, "No Sprite") for a custom sprite, just have the normal sprite routine ignore that sprite number, and have only your custom routine run it or whatever. Also, you'd only need one RAM table for the extra sprites - use a ROM table for their addresses.
C:/xkas bio.asm
Posts: 1045/1209
, I've finally found where the extra bit is stored in RAM, they are stored at 7E187B(Sprite Stomp Immunity Flag Table) as bit 3 and 4
Smallhacker
Posts: 570/832
Originally posted by Glyph Phoenix
or, using his first idea, not use LM at all.

It was supposed to be a "solution" that wouldn't work.

Originally posted by Glyph Phoenix
Sprites are by nature dynamic--there are so many ways to make a sprite act differently. By treating sprites like blocks, which are by nature static, you're totally missing the point.

Well... From a level designer's point of view, is there really any difference between a sprite and a block? Both can be placed anywhere in the level, both must be placed in a 16x16 grid (as in, you can't place a sprite nor a block 1 pixel away from another one). In fact, when working with Lunar Magic, the only difference is that sprites can't be resized. (Okay. Some blocks can't be resized, but that's not the point.)

The sprite properties that Lunar Magic can change are Command (0-FF), Screen Number (0-1F), X/Y Position (0-FF) and Extra Info (0-3).
The MAP16 block properties that LM can change are Block (0-FFF), Screen Number (0-1F), X/Y Position (0-FF) and Size (0-FF).
If you ignore the Command and Block parts, sprites have got 15 bits of data while MAP16 blocks have got 21 bits of data, which, technically, means that MAP16 blocks are MORE dynamic than sprites.

Anyway. Enough about that idea, since I belive that the other idea, the one that uses extra bits and unused sprites, would be better.
This is a long thread. Click here to view it.
Acmlm's Board - I3 Archive - SMW Hacking - Add 255 sprites?


ABII

Acmlmboard 1.92.999, 9/17/2006
©2000-2006 Acmlm, Emuz, Blades, Xkeeper

Page rendered in 0.015 seconds; used 382.68 kB (max 452.21 kB)