Language…
14 users online: Batata Douce,  Deeke, Everest, Gamet2004, Golden Yoshi, Gorry, Green, JezJitzu, LunarianNEET, MellowYouth, Raychu2021, RicardoDeMelo, Rykon-V73, sinseiga - Guests: 251 - Bots: 291
Users: 64,795 (2,376 active)
Latest user: mathew

The Public Dynamic Sprites Project

We all know that dynamic sprites in SMW can bring some nice fluid animations to sprites and made possible to port some sprites from YI to SMW. But in the reality, the actual patch that everyone uses isn't safe at all.

A discussion was started in the Staff forum about Dynamic Sprites and how we have been using the same system for ages (until I updated it with SA-1's Pack method to handle it, but almost no-one is aware of said update), discussing if it is efficient or not and other couple of (irrelevant) things.

I do want to see an update to this patch to fix that critical bug, but I'd like to see new features to it, mostly approaching developers to make it easier to use, the original (and updated) patch has zero documentation!

Keeping in mind that this patch is meant to be a way to use dynamic sprites for non programmer people, so being user-friendly it's one of its features, let's not convert this into a super complicated patch that requires reading a readme to be inserted.

Feel free to post new ideas and suggesting ways to optimize the current patch in this thread.

Thanks!
I wanted to keep the first post as an introductory post so I can pput here my wishlist/to-do list/suggestions/etc here.


1) Since dsx.asm requires nothing special to work besides garble.asm (fixes OW events), I'd suggest release this as a patch and/or as a uberASM tool library/code. It only requires to run during V-Blank so nothing bad happens on real hardware.

I already did an attempt to achieve that, and worked quite well: Library code, Required macro

2) I'd go with Erik's suggestion to fix the !SLOTSUSED issue, using part of the RAM dedicated to stack seems to be the best way to go for me. Link

3) In the staff team I brought the idea of discarding the DMA routines to upload the graphic data to a buffer in RAM, it was a nice idea at the moment, but then I started to think that it might not work fine due to having to setup different DMA routines more than once if 4 dynamic sprites are used. That'd be slower than the current way to do it (one transfer of 0x800 bytes to the lower part of SP4).

Feel free to comment these ideas!
There also are some other suggestions:
  • LX5 also mentioned in the staff forum to make dynamic sprites use sizes other than 32x32. While only two dynamic sprites are known to be 64x64 (Tap Tap the Red Nose and SMB1 Bowser Redux), it really can benefit from using different sizes.
  • I also brought up how we should change the tiles from 32x32 to 64x16. Both upload the same amount of tiles (four tiles to be precise) but since each next tile in VRAM is then one on the right (unless it's on the border, in which you move down if you move to the right or top if you move to the left), it means that a 32x32 sprite needs to use four DMA uploads because it needs to jump down trice whereas with 64x16, two of them can be merged and only two DMA setups are required.


Originally posted by LX5
3) In the staff team I brought the idea of discarding the DMA routines to upload the graphic data to a buffer in RAM, it was a nice idea at the moment, but then I started to think that it might not work fine due to having to setup different DMA routines more than once if 4 dynamic sprites are used. That'd be slower than the current way to do it (one transfer of 0x800 bytes to the lower part of SP4).

I believe, someone should explain this more in detail.
i believe there should be some sort of option as to where the data gets uploaded. there may be stuff in the bottom of sp4 that the user wants to keep. simply shifting where the whole 128x32 sludge gets uploaded should be fine

bigger sizes good
64x16 too

also glad action is being taken rofl
My layout has recently been updated, but you still have the old stylesheet cached and things might therefore not look as intended, as such, it’s recommended to reload the page.
I would like to see more of Dynamic Z’s features.
Originally posted by MarioFanGamer
I believe, someone should explain this more in detail.

My bad for not explaining it further.
What I meant there is that discarding the RAM buffer would mean setting up more DMAs in V-Blank, which would consume a lot of precious time and users might experience black bars at the top more often than using a RAM buffer.

Let's put an example here:
Imagine 2 dynamic sprites on screen, uploading their graphics every frame and that stuff.
If we use the current method (RAM Buffer), the code would be like this:
Code
.transfer_two
	%transferslot(0, $0100, $80)
	%transferslot(1, $0100, $80)	
	%transferslot(2, $0100, $80)
	%transferslot(3, $0100, $80)
	rts

macro transferslot(slot, bytes, shift)
	LDA.W #$7C00+(<slot>*256)+<shift>	; \ VRAM address + line*slot
	STA.W $2116				; /
	LDA.W #(!dsx_buffer&65535)+(<slot>*512)+(<shift>*2) ;\ Set Buffer location
	STA.W $4302				; /
	LDA.W #<bytes>				; \ Set bytes to transfer
	STA.W $4305				; /
	STY.W $420B				; Run DMA.
endmacro

4 continous DMAs, which is quite fast and optimal for uploading stuff to VRAM.

If we opt for a pointer stuff (pointing at the uncompressed graphics with RAM) we would have something like this (in theory):
Code
	lda #dest_1		;destination of the dynamic sprite #1
	clc
	adc #shift_dest_1	;shift the destination by X amount of bytes
	sta $2116
	lda !location_1		;location of the uncompressed data #1
	clc
	adc #shift_loc_1	;shift the location by X amount of bytes
	sta $4302
	lda #$0080
	sta $4305
	sty $420B

	lda #dest_2		;destination of the dynamic sprite #2
	clc
	adc #shift_dest_2	;shift the destination by X amount of bytes
	sta $2116
	lda !location_2		;location of the uncompressed data #2
	clc
	adc #shift_loc_2	;shift the location by X amount of bytes
	sta $4302
	lda #$0080
	sta $4305
	sty $420B

Repeat 3 more times with the appropiate shifts in the destination and you would have 8 DMAs set up instead of 4 using the RAM buffer method. This will only get bigger and bigger with more dynamic sprites on screen and it would end up being wasting more V-Blank time.
Of course we could apply the uploading in 1 chunk of 64*16 pixels idea (which I like), but it would be still slower with more dynamic sprites on screen (with only one dynamic sprite on screen both gives the same result).
Overall, using pointers to the uncompressed graphics requires less cycles since you don't need to do these DMAs in the sprite's code, but has more weight when it comes to upload data to VRAM. While using the RAM buffer is slower in general, but faster when during uploading graphics to VRAM.
I personally prefer the RAM buffer over the pointers mostly due to using less V-blank time.



Originally posted by Ladida
i believe there should be some sort of option as to where the data gets uploaded. there may be stuff in the bottom of sp4 that the user wants to keep. simply shifting where the whole 128x32 sludge gets uploaded should be fine

I agree, I've thought about this and came up with this potential code for it:
Code
VRAM_targets:
	dw $7C00,$7A00,$7800,$7600
	dw $7400,$7200,$7000,$6C00
;[...]
.transfer_n
	LDX !dsx_loc
	%transferslot(blah)
;[...]
macro transferslot(blah)
	LDA.W VRAM_targets,x
	CLC
	ADC.W #(<slot>*256)+<shift>	; \ VRAM address + line*slot
	STA.W $2116

Having a dedicated RAM to let the user decide where the blob of graphics will be uploaded seems good enough for me, as well having a predefined locations to not fuck up everything and make this thing as fast as possible.

Originally posted by Ladida
also glad action is being taken rofl

yeah LOL


Originally posted by ExE Boss
I would like to see more of Dynamic Z’s features.

Any suggestion of which ones. I personally don't like most of its features except for the 30fps mode that lets you have up to eight dynamic sprites on screen, but that would require a complete reprogramming of the patch and all of the dynamic sprites to make use of it, and that might not be very worht in my opinion.
Okay, so my (backward-incompatible) idea for a dynamic sprite system:

Instead of getting an upload slot every frame, and uploading stuff once you get your slot, you get a slot as part of your init routine and keep it until your sprite dies ("until your sprite dies" has some complexity I will explain later, but ignore it for now)

Then, instead of uploading stuff for your sprite every frame, you wait until you have something to upload and then put a pointer in your slot. When V-blank rolls around, it gets uploaded, and that pointer gets cleared.

Since you keep your slot, this means you can keep using the same old OAM tiles until next time your graphics change. For some sprites that might be every frame, for some it might be every 4 or 8 frames, for some even less. (For an example, imagine something like a dynamic version of Chargin' Chuck, that would only need to upload when its pose changes). In comparison to dynamic Z's 30fps mode, this is sort of like letting every sprite choose its own framerate.

Hopefully the reduction in upload frequency would be enough to make ditching the buffer work without black bars.


As for "until your sprite dies", it would have something like a shared subroutine %GetDynamicSlot() (or whatever). The patch would have two tables, one for the slot pointers, and one for the slot owners. When you get a slot, it puts sprite index ($15e9) + 1 in the list of owners. Every frame, the patch loops over the list of slot owners, and if one of them died ($14c8,x = 0) it clears the allocation.

Here is a rough sketch of how the code might go. (there's stuff to deal with like maybe the tables would have to be in bank $7f that im not thinking about here)
Code
NMIstuff:
	ldy #!max_slots-1
.loop:
	; check if anybody has a claim
	ldx !dynamic_owners,y : beq .next
	; if somebody has claim, check if they're alive
	dex
	lda !14C8,x : beq .free_slot
	
	; if they have a claim and are alive, check if they uploaded anything
	sty $00 : tya : asl : adc $00 : tax
	lda !dynamic_pointers,x : ora !dynamic_pointers+1,x : ora !dynamic_pointers+2,x
	beq .next
	
	; imagine there's upload code here (it would upload to a target based on Y)

	stz !dynamic_pointers,x : stz !dynamic_pointers+1,x : stz !dynamic_pointers+2,x
	bra .next
.free_slot:
	stz !dynamic_owners,y
.next:
	dey : bpl .loop
	rtl


Code
;GetDynamicSlot.asm
; this routine returns either carry clear (no slots available),
; or carry set and slot index in A
; keep the slot index in a table so you can translate it to an OAM index someday
	ldy #!max_slots-1
.loop:
	lda !dynamic_slots,y : beq .found
	dey : bpl .loop
.didnt_find:
	clc
	rtl
.found:
	txa : inc : sta !dynamic_owners,y
	tya
	sec
	rtl


The basic idea here is to save V-blank time by uploading a lot less, the slot reservation system is just a way to achieve that. If nobody likes this idea I still would very much like to reduce the upload frequency by whatever other means are available

The biggest issue with this is that it seems like most of the dynamic sprites on the site are designed in a way that they would change their graphics very often (look at me I'm a Yoshi's Island piranha plant and I rotate all the time!), in which case they would be uploading almost every frame anyway and ditching the buffer would still risk black bars.

Another issue is that if a slot-owning sprite dies and a new sprite spawns in it slot on the exact same frame, the slot will be considered owned by the new sprite and won't be cleared until the new sprite dies. There are ways to make it leak less often (although I can't think of a 100% way), but I'm not sure this is a huge problem.

I think you could make this use a buffer as well but it might be really weird and involve lots of uploads for things that didn't change in which case the whole point is defeated

This idea should be compatible with other proposed ideas (changing the size of slots, making it possible to choose where the slots are)

I don't really have super high hopes for this proposition, since it requires a rewrite for sprites, that rewrite has to be well-thought-out for the benefits to appear, and also for a lot of sprites this might not even be beneficial since they change graphics all the time anyway. but i asked lx5 whether i should post my weird heterodox idea and he said "post" so if you dont like it blame him but i dont mind if it gets ignored really since im already using not using dsx
32x32 sprites can already be arranged in 16x64 with tile positioning

As for resizing if anything's possible, it's possible! Also I mean to ask if there are methods of using more if 00-$10 for some of the dynamic sprite codes? Scratch RAM is very useful, especially ab opportunity like this.
Originally posted by LX5
Originally posted by ExE Boss
I would like to see more of Dynamic Z’s features.

Any suggestion of which ones. I personally don't like most of its features except for the 30fps mode that lets you have up to eight dynamic sprites on screen, but that would require a complete reprogramming of the patch and all of the dynamic sprites to make use of it, and that might not be very worht in my opinion.


All Dynamic Sprites can be adapted to 30 fps, if i could made complete Allen O’Neil version very smoothly with 30fps then I can make any dynamic sprite in 30fps very smoothy, also dynamic z includes a version of dsx that fix its problems because the hijack that uses is on a zone of the code that works if there are not lag, also optimize Mario DMA routine to use less DMA transfers avoiding DMA overload and decreasing lag.

Dynamic Z is compatible with all 60 fps dynamic sprites, the only restriction is dont use 60fps and 30 fps dynamic sprites in the same zone of the same level, because if you have a 60fps and a 30 fps dynamic sprite on the screen at the same time, only will load 30fps dynamic sprites graphics.

If you dont like the others features, then is easier make a version of dynamic z where you can deactivate the features that you dont want than do a new dynamic system, I made the extra features as a plus, similar to uberasm nmi or gamemode hijack that are not the main feature of the patch but is nice to have it if you need it.

I tryed to do a complete VBLANK support to works with VRAM and CGRAM easier, the main feature is dynamic sprites support but you can also if you want, you can make your custom player, change graphics, change palettes or do dynamic sprites of 96x96 or 112x112 or a semi-dynamic sprites, all without need any other nmi patch and can be used from Uber asm , a sprite code or block Code.

In short, I recommend to do a version of Dynamic Z where you can select the features that you want, more than a new dynamic patch.

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

Youtube
Twitter
SMWControlLibX GitHub
My Discord Server
Snestorage where you can download my resources