We've just updated MediaWiki and its underlying software. If anything doesn't look or work quite right, please mention it to us. --RanAS

Dynamic Z: Difference between revisions

From SnesLab
Jump to: navigation, search
Line 85: Line 85:


Now any code of uber asm can use any define or macro of Dynamic Z.
Now any code of uber asm can use any define or macro of Dynamic Z.
If you are using 50% more mode, you can't use status bar hijack of Uber ASM Tool, to disable it you must open the folder "asm", and then the folder "base", on that folder there is a file called "main.asm":
<pre>
!previous_mode = !sprite_RAM+(!sprite_slots*3)
incsrc level.asm
incsrc overworld.asm
incsrc gamemode.asm
incsrc global.asm
incsrc sprites.asm
incsrc statusbar.asm
</pre>
Just delete the line
<pre>
incsrc statusbar.asm
</pre>
And now you can use 50% more mode and Uber ASM Tool.


== How does it work? ==
== How does it work? ==

Revision as of 19:19, 8 December 2019

Dynamic Z is a patch for Super Mario World that allows performing a variety of actions during V-Blank. It was made by anonimzwx. Dynamic Z is meant to be a replacement for DSX as both allow coding dynamic sprites.

Dynamic Z does not require a buffer for coding dynamic sprites, which significantly reduces the slowdown caused by these type of sprites. Additionally, it can create sprites with a 30FPS animation synchronized with each other; this allows having twice as many dynamic sprites on-screen compared to DSX.

Features

  • Graphic changes
  • Color palette changes
  • Color palette and graphic changes on the player
  • Tile changes
  • Support for Dynamic, Semi-Dynamic and Giga-Dynamic sprites
  • A special DMA mode, which grants 50% more transfer capacity by removing the game's original DMA code
  • Player DMA optimizations that gives more time during NMI and slightly curbs slowdown
  • Compatibility with DSX sprites


Installation

If you are using SA-1. First you must deactivate DSX on SA-1, to do that, open the file "sa1.asm" and you will find this:

!DSX		= 1				; Put 0 if you want to turn off legacy (Dynamic Sprites) patch support.
						; (as anoni's Dynamic Z should obsolete it soon.)

Then change the 1 for 0 and reinstall SA-1 Patch.

Next step is define the features of Dynamic Z that you will use, you can configure that on the file "header.asm":

;#########################################################<-----------------
;#########################################################<-----------------
;################ Dynamic Z Options ######################<-----------------
;#########################################################<-----------------
;#########################################################<-----------------

;Next use Hijacks: $00823D and $0082DA
;No patches uses thats hijacks.
;This hijacks are required always
!DynamicSpritesSupport = !True          ;Allows Dynamic Z dynamic sprites support, sprites that loads their graphics dynamically
!GiantDynamicSpritesSupport = !True     ;Allows dynamic sprites of 96x96 (or less) and 112x112 (or less, 112x112 requires 50% more mode)
!SemiDynamicSpritesSupport = !True      ;Allows semi-dynamic sprites that loads all their graphics only when they enter on the screen
                                        ;Each copy of the sprite use the same graphics. This is a system similar to Megaman X Sprites
!DSXRetrocompatibilitySupport = !True   ;Allows Old Dynamic Sprite Patch's Dynamic Sprites compatiblity
!GFXChangeSupport = !True               ;Allows to change graphics and tilemaps dynamically, you can use it from blocks, sprites, uberasm level code, etc.
!PaletteChangeSupport = !True           ;Allows to change color palettes dynamically, you can use it from blocks, sprites, uberasm level code, etc.

;Very situational option, basically you can set parameters
;of DMA transfer from other code like a uberasm and it will
;start the transfer during nmi, not very usefull, but maybe
;someone need it.
!AllowsDMAMirror = !False

;Next use Hijacks: $00F636 and $00A300
;Possible incompatibilities with patches that change the GFX of mario.
;Patches with possible incompatibilities: LX5's Custom Powerups.
!OptimizeOriginalPlayerDMARoutine = !False  ;Optimize the original DMA routine of mario, saving time during NMI and decreasing slowdown a bit
!PlayerGraphicsChangeSupport = !False       ;Allows to change graphics for players of 16x32
!PlayerPaletteChangeSupport = !False        ;Allows to change player color paletts (colors between $86 and $8F)
!FullyCustomPlayerSupport = !False          ;Allows to do players of any size and that use any palette, requires custom interaction
!Include32x32PlayerPatch = !False           ;Allows to use the patch 32x32 Player, then you can do players of that size easier
!IncludeMario8x8TilesDMAerPatch = !False    ;Allows to use the Mario's 8x8 Tiles DMAer, to save some space on SP1

;Next use Hijacks: $008E1A, $008DAC, $008CFF, $008292, $00A43E, $00A4E3 and $00A3F0
;Possible incompatibilities with patches that changes status bar or change 
;default Not-Mario/Yoshi DMA from smw.
;This mode allows you to transfer 50% more data using DMA
;But meanwhile it is active, some sprites, original animations of graphics and palettes and the original status bar
;Will stop to work
;This mode can be activate using uberasm, sprites, blocks, etc.
!Mode50moreSupport = !False

Just put !True or !False to the features that you want and install "DynamicZ.asm" file using asar.

Installing a Dynamic Sprite

First you must add the DynamicZDefines.asm to your pixi folder, to do that, open the folder "asm" and open (or create) a folder called "ExtraDefines" then copy paste the file "DynamicZDefines.asm" into the folder.

To install a Dynamic Sprite there are 2 types, Direct Transfer and Indirect Transfer. Direct Transfer Dynamic Sprites only requires to be added on the sprite folder with their gfx, cfg and asm files and insert them as any other sprite.

Indirect Transfer usually includes a Readme and a patch to insert the graphics on the ROM.

Installing Dynamic Z on Uber ASM Tool

Open the folder "other" and copy paste the file "DynamicZDefines.asm", then open the file "macro_library.asm" and at the end of the file add the following line:

incsrc "./DynamicZDefines.asm"

Now any code of uber asm can use any define or macro of Dynamic Z.

If you are using 50% more mode, you can't use status bar hijack of Uber ASM Tool, to disable it you must open the folder "asm", and then the folder "base", on that folder there is a file called "main.asm":

!previous_mode = !sprite_RAM+(!sprite_slots*3)

incsrc level.asm
incsrc overworld.asm
incsrc gamemode.asm
incsrc global.asm
incsrc sprites.asm
incsrc statusbar.asm

Just delete the line

incsrc statusbar.asm

And now you can use 50% more mode and Uber ASM Tool.

How does it work?

All This Documentation is valid for Dynamic Z V3.7 or higher.

Dynamic Sprite Support

Dynamic Z have tables to define transfers to VRAM between #7400 and #7FFF (In the case of Overworld Sprites #6800 and #6FFF) . Every Table have 1 slot for each space of 16x8:

  • DMA Resource: This Table is used to know in what RAM Address starts the source that will be transfer to the VRAM.
  • DMA BNK: This Table is used to know in what Bank starts dma must find the DMA Resource.
  • DMA Length: This Table is used to know how much data must send to VRAM.

Each slot of the tables is mapped to a value on the VRAM, the first slot start at #7400 and the last starts at #7FE0, Between 2 consecutive slots, there are 20 address of diference on the VRAM (40 bytes of difference).

To know what slots read of the tables, Dynamic Z use a table called DMA Next, each slot on this table indicates a link between a slot and another slot, for example, if slot #$00 have the value #$20, then after load slot #$00 on the VRAM, the patch will loads slot #$20, if a Slot have the value #$FF, if the patch read that slot, will finish the transfer to VRAM.

To know what is the first slot, there is a RAM Address called First Slot, if this address is #$FF, then Dynamic Z won't load anything on the VRAM.

With the table DMA Next, Dynamic Z create a data structure called Linked List. To add DMA Transfers at the end of the list, there is a RAM Address called Last Slot that have the last slot that will be loaded on the VRAM.

To connect this system with sprites there are some tables that can be used:

  • Slots Used By Sprite: Dynamic Z Consideres each slot as a square of 16x16, each dynamic sprite use a number of slots, for example a dynamic sprite of 16x16 uses 1 slot, here a table with the number of slots of each sprite:
Size Slots
16x16 1
32x16 2
32x32 4
48x48 8
64x64 16
80x80 24
96x96 All
112x112 All

In the case of 96x96 and 112x112 Dynamic Sprites, they uses their own system and they reserve all slots. You can't use a 96x96 or 112x112 Dynamic Sprite with others Dynamic Sprites.

  • FPS: This table is used to know the frecuency of a sprite to change it's graphics on the VRAM. Dynamic Z allows 2 frecuencies, 30 FPS (can change their graphics every 2 snes frames) and 60 FPS (can change their graphics each frame). On practice use 30 FPS allows to use the double of Dynamic Sprites, because you can sincronice their Dynamic Routines and have 16 slots (24 with 50% more mode) for sprites that loads their graphics on even frames and 16 (or 24) for sprites that loads their graphics on odd frames. Almost all sprites can be made with 30FPS, try to avoid 60FPS dynamic sprites.
  • Sprite Type: It is used to know the type of the dynamic sprite, #$00 = Free Slot, #$01 = Normal, #$02 = Extended, #$03 = Cluster and #$04 = Overworld Sprite.
  • Sprite ID: It is used to know what is the Index of the sprite on its sprite table.
  • Sprite Number: It is used to know what is the Number of the sprite.
  • Transfer Frame: It is one table for each kind of sprite. It is used for 30FPS to know if it uses slots of even frames or odd frames. if bit 7 is 0 = Even Frames, if bit 7 is 1 = Odd Frames. Also is used to know if the sprite must reserve a slot starting from the bottom of the Dynamic Space (for example on the second half of SP4) or from the top of the Dynamic Space (second half of SP3), if Bit 6 is 0 = Bottom, if bit 6 is 1 = Top.
  • VRAM Disp: It is one table for each kind of sprite. It is used to know what is the slot assigned to the sprite.
  • Signals: They represent if a space on the VRAM is used by a sprite, each Signal represents 4 slots, each group of 2 slots on each signal is a counter that decrease in 1 each frame, if the value is #$00 then the slot is free to use.
  • Max Slots: Is the max number of slots that can be used in each frame. By default is #$10 (16 slots), if you use 50% more mode it can be #$18 (24 slots). This value can be modified by the user if he wants to use less space on SP4 or SP3, for example if the user use Max Slot = #$08, then only will use a space of 128x32 on the VRAM.

RAM Addresses

Name Address SA-1 Address Define Length Description
Dynamic Timer 7F0B44 418000 !DynamicTimer 1 byte A timer that decrease in 1, every frame when Dynamic Z is working, it is used for 30FPS Dynamic sprites to know if the frame is even or odd.
Signal for the Bottom Left Quarter of Second Half of SP4 7F0B45 418001 !SignalSP4SecondHalfBottomLeftQuarter 1 byte Signal used to know if slots that are allocated on the Bottom Left quarter of the second half of SP 4 are used free or not.
Signal for the Bottom Right Quarter of Second Half of SP4 7F0B46 418002 !SignalSP4SecondHalfBottomRightQuarter 1 byte Signal used to know if slots that are allocated on the Bottom Right quarter of the second half of SP 4 are used free or not.
Signal for the Top Left Quarter of Second Half of SP4 7F0B47 418003 !SignalSP4SecondHalfTopLeftQuarter 1 byte Signal used to know if slots that are allocated on the Top Left quarter of the second half of SP 4 are used free or not.
Signal for the Top Right Quarter of Second Half of SP4 7F0B48 418004 !SignalSP4SecondHalfTopRightQuarter 1 byte Signal used to know if slots that are allocated on the Top Right quarter of the second half of SP 4 are used free or not.
Signal for the Bottom Left Quarter of First Half of SP4 7F0B49 418005 !SignalSP4FirstHalfBottomLeftQuarter 1 byte Signal used to know if slots that are allocated on the Bottom Left quarter of the second half of SP 4 are used free or not.
Signal for the Bottom Right Quarter of First Half of SP4 7F0B4A 418006 !SignalSP4FirstHalfBottomRightQuarter 1 byte Signal used to know if slots that are allocated on the Bottom Right quarter of the second half of SP 4 are used free or not.
Signal for the Top Left Quarter of First Half of SP4 7F0B4B 418007 !SignalSP4FirstHalfTopLeftQuarter 1 byte Signal used to know if slots that are allocated on the Top Left quarter of the first half of SP 4 are used free or not.
Signal for the Top Right Quarter of First Half of SP4 7F0B4C 418008 !SignalSP4FirstHalfTopRightQuarter 1 byte Signal used to know if slots that are allocated on the Top Right quarter of the first half of SP 4 are used free or not.
Signal for the Bottom Left Quarter of Second Half of SP3 7F0B4D 418009 !SignalSP3SecondHalfBottomLeftQuarter 1 byte Signal used to know if slots that are allocated on the Bottom Left quarter of the second half of SP 3 are used free or not.
Signal for the Bottom Right Quarter of Second Half of SP3 7F0B4E 41800A !SignalSP3SecondHalfBottomRightQuarter 1 byte Signal used to know if slots that are allocated on the Bottom Right quarter of the second half of SP 3 are used free or not.
Signal for the Top Left Quarter of Second Half of SP3 7F0B4F 41800B !SignalSP3SecondHalfTopLeftQuarter 1 byte Signal used to know if slots that are allocated on the Top Left quarter of the second half of SP 3 are used free or not.
Signal for the Top Right Quarter of Second Half of SP3 7F0B50 41800C !SignalSP3SecondHalfTopRightQuarter 1 byte Signal used to know if slots that are allocated on the Top Right quarter of the second half of SP 3 are used free or not.
Slots Used in Even Frames 7F0B51 41800D !SlotsUsedEven 1 byte Number of slots used on even frames.
Slots Used in Odd Frames 7F0B52 41800E !SlotsUsedOdd 1 byte Number of slots used on odd frames.
Max Slots 7F0B53 41800F !MaxSlots 1 byte Maximum number of slots that can be used per frame.
Number of Blocks 7F0B54 418010 !NumberOfBlocks 1 byte Number of blocks that can be used for Dynamic Routines, each block represent a space in VRAM of 128x32, by default is 2 (equivalent to have a complete SP for dynamic sprites).
VRAM Displacement Normal Sprites 7F0B55 418011 !VRAMDispNormalSprite 12 bytes (22 bytes on SA1 roms) A number used to know what is the slot assigned to a Normal Dynamic Sprite.
VRAM Displacement Extended Sprites 7F0B61 418027 !VRAMDispExtendedSprite 10 bytes A number used to know what is the slot assigned to a Extended Dynamic Sprite.
VRAM Displacement Cluster Sprites 7F0B6B 418031 !VRAMDispClusterSprite 20 bytes A number used to know what is the slot assigned to a Cluster Dynamic Sprite.
VRAM Displacement Overworld Sprites 7F0B7F 418045 !VRAMDispOWSprite 16 bytes A number used to know what is the slot assigned to a OVerworld Dynamic Sprite.
Transfer Frame Normal Sprite 7F0B8F 418055 !TransferFrameNormalSprite 12 bytes (22 bytes on SA1 roms) Used to know if the sprite must find slot starting from the Top of the Dynamic Space or starting from the bottom. Also in 30FPS Dynamic sprites is used to know if the dynamic routine must be made on even or odd frames.
Transfer Frame Extended Sprite 7F0B9B 41806B !TransferFrameExtendedSprite 10 bytes Used to know if the sprite must find slot starting from the Top of the Dynamic Space or starting from the bottom. Also in 30FPS Dynamic sprites is used to know if the dynamic routine must be made on even or odd frames.
Transfer Frame Cluster Sprite 7F0BA5 418075 !TransferFrameClusterSprite 20 bytes Used to know if the sprite must find slot starting from the Top of the Dynamic Space or starting from the bottom. Also in 30FPS Dynamic sprites is used to know if the dynamic routine must be made on even or odd frames.
Transfer Frame Overworld Sprite 7F0BB9 418089 !TransferFrameOWSprite 16 bytes Used to know if the sprite must find slot starting from the Top of the Dynamic Space or starting from the bottom. Also in 30FPS Dynamic sprites is used to know if the dynamic routine must be made on even or odd frames.
Slots used by Sprite 7F0BC9 418099 !SlotsUsedBySprite 48 bytes How many slots are used for each dynamic sprite.
FPS 7F0BF9 4180C9 !FPSSprite 48 bytes Used to know if a sprite if 30 or 60 FPS.
Sprite Type 418129 4180F9 !SlotSpriteType 48 bytes Used to know if a slot is free or what is the type of the dynamic sprite of each slot.
Sprite ID 418159 418129 !SlotSpriteID 48 bytes Used to know what is the index of a dynamic sprite.
Sprite Number 418189 418159 !SlotSpriteNumber 48 bytes Used to know what is the sprite number of each dynamic sprite.
DMA Map Resource 4181B9 418189 !DMAMapResource 192 bytes Used to know where are allocated the resources on the ROM (or RAM). (2 bytes per slot).
DMA MAp Bank 418279 418249 !DMAMapBNK 96 bytes Used to know in what bank are allocated the resources on the ROM (or RAM). (1 bytes per slot).
DMA Map Lenght 4182D9 4182A9 !DMAMapLenght 192 bytes Used to know how many bytes must be transfer. (2 bytes per slot).
DMA Map Next Slot 418399 418369 !DMAMapNext 96 bytes After transfer 1 slot to the VRAM, It is used to know what is the next slot that must be loaded to the VRAM. (1 bytes per slot).
First Slot 4183F9 418399 !FirstSlot 1 byte Used to know what is the first slot that must be loaded on the VRAM. If it is #$FF then doesn't load anything to the VRAM.
Last Slot 4183FA 41839A !LastSlot 1 byte Used to know what is the last slot that must be loaded on the VRAM.
50% more mode 4183FB 41839B !Mode50More 1 byte If it is 1, activate 50% more mode. In this default smw status bar, all default animated tiles of SP1 and dma used for tile E3 and F0 are disable. This allows to have 50% more slots for dynamic sprites or to transfer 50% more data to VRAM. (Must disable global animated tiles and animated palettes on LM).

Routines

Dynamic Z includes some routines to do all easier:

  • Dynamic Routine: Do the dynamic routine of a sprite.
  • Reserve: Reserve a slot for a new dynamic sprite. If the sprite can't reserve a slot then it will be killed. In the case of normal sprite they can be reloaded if the player return to the area. It recieves as parameter A = Transfer Frame Table.
  • Send Signal: This routine says to Dynamic Z that the slots reserved by a sprite are still used and don't overwrite them.

Here a list of all Routines:

Name Define Description
Dynamic Routine for 16x16 sprites !DynamicRoutine16x16 Dynamic Routine used by dynamic sprites of 16x16.
Dynamic Routine for 32x16 sprites !DynamicRoutine32x16 Dynamic Routine used by dynamic sprites of 32x16.
Dynamic Routine for 32x32 sprites !DynamicRoutine32x32 Dynamic Routine used by dynamic sprites of 32x32.
Dynamic Routine for 48x48 sprites !DynamicRoutine48x48 Dynamic Routine used by dynamic sprites of 48x48.
Dynamic Routine for 64x64 sprites !DynamicRoutine64x64 Dynamic Routine used by dynamic sprites of 64x64.
Dynamic Routine for 80x80 sprites !DynamicRoutine80x80 Dynamic Routine used by dynamic sprites of 80x80.
Reserve Slot for 16x16 30FPS Normal Sprite !Reserve16x16NormalSpriteOf30FPS Reserve a slot for a Dynamic 30FPS Normal Sprite of 16x16.
Reserve Slot for 16x16 60FPS Normal Sprite !Reserve16x16NormalSpriteOf60FPS Reserve a slot for a Dynamic 60FPS Normal Sprite of 16x16.
Reserve Slot for 16x16 30FPS Extended Sprite !Reserve16x16ExtendedSpriteOf30FPS Reserve a slot for a Dynamic 30FPS Extended Sprite of 16x16.
Reserve Slot for 16x16 60FPS Extended Sprite !Reserve16x16ExtendedSpriteOf60FPS Reserve a slot for a Dynamic 60FPS Extended Sprite of 16x16.
Reserve Slot for 16x16 30FPS Cluster Sprite !Reserve16x16ClusterSpriteOf30FPS Reserve a slot for a Dynamic 30FPS Cluster Sprite of 16x16.
Reserve Slot for 16x16 60FPS Cluster Sprite !Reserve16x16ClusterSpriteOf60FPS Reserve a slot for a Dynamic 60FPS Cluster Sprite of 16x16.
Reserve Slot for 16x16 30FPS Overworld Sprite !Reserve16x16OWSpriteOf30FPS Reserve a slot for a Dynamic 30FPS Overworld Sprite of 16x16.
Reserve Slot for 16x16 60FPS Overworld Sprite !Reserve16x16OWSpriteOf60FPS Reserve a slot for a Dynamic 60FPS Overworld Sprite of 16x16.
Reserve Slot for 32x16 30FPS Normal Sprite !Reserve32x16NormalSpriteOf30FPS Reserve a slot for a Dynamic 30FPS Normal Sprite of 32x16.
Reserve Slot for 32x16 60FPS Normal Sprite !Reserve32x16NormalSpriteOf60FPS Reserve a slot for a Dynamic 60FPS Normal Sprite of 32x16.
Reserve Slot for 32x16 30FPS Extended Sprite !Reserve32x16ExtendedSpriteOf30FPS Reserve a slot for a Dynamic 30FPS Extended Sprite of 32x16.
Reserve Slot for 32x16 60FPS Extended Sprite !Reserve32x16ExtendedSpriteOf60FPS Reserve a slot for a Dynamic 60FPS Extended Sprite of 32x16.
Reserve Slot for 32x16 30FPS Cluster Sprite !Reserve32x16ClusterSpriteOf30FPS Reserve a slot for a Dynamic 30FPS Cluster Sprite of 32x16.
Reserve Slot for 32x16 60FPS Cluster Sprite !Reserve32x16ClusterSpriteOf60FPS Reserve a slot for a Dynamic 60FPS Cluster Sprite of 32x16.
Reserve Slot for 32x16 30FPS Overworld Sprite !Reserve32x16OWSpriteOf30FPS Reserve a slot for a Dynamic 30FPS Overworld Sprite of 32x16.
Reserve Slot for 32x16 60FPS Overworld Sprite !Reserve32x16OWSpriteOf60FPS Reserve a slot for a Dynamic 60FPS Overworld Sprite of 32x16.
Reserve Slot for 32x32 30FPS Normal Sprite !Reserve32x32NormalSpriteOf30FPS Reserve a slot for a Dynamic 30FPS Normal Sprite of 32x32.
Reserve Slot for 32x32 60FPS Normal Sprite !Reserve32x32NormalSpriteOf60FPS Reserve a slot for a Dynamic 60FPS Normal Sprite of 32x32.
Reserve Slot for 32x32 30FPS Extended Sprite !Reserve32x32ExtendedSpriteOf30FPS Reserve a slot for a Dynamic 30FPS Extended Sprite of 32x32.
Reserve Slot for 32x32 60FPS Extended Sprite !Reserve32x32ExtendedSpriteOf60FPS Reserve a slot for a Dynamic 60FPS Extended Sprite of 32x32.
Reserve Slot for 32x32 30FPS Cluster Sprite !Reserve32x32ClusterSpriteOf30FPS Reserve a slot for a Dynamic 30FPS Cluster Sprite of 32x32.
Reserve Slot for 32x32 60FPS Cluster Sprite !Reserve32x32ClusterSpriteOf60FPS Reserve a slot for a Dynamic 60FPS Cluster Sprite of 32x32.
Reserve Slot for 32x32 30FPS Overworld Sprite !Reserve32x32OWSpriteOf30FPS Reserve a slot for a Dynamic 30FPS Overworld Sprite of 32x32.
Reserve Slot for 32x32 60FPS Overworld Sprite !Reserve32x32OWSpriteOf60FPS Reserve a slot for a Dynamic 60FPS Overworld Sprite of 32x32.
Reserve Slot for 48x48 30FPS Normal Sprite !Reserve48x48NormalSpriteOf30FPS Reserve a slot for a Dynamic 30FPS Normal Sprite of 48x48.
Reserve Slot for 48x48 60FPS Normal Sprite !Reserve48x48NormalSpriteOf60FPS Reserve a slot for a Dynamic 60FPS Normal Sprite of 48x48.
Reserve Slot for 48x48 30FPS Extended Sprite !Reserve48x48ExtendedSpriteOf30FPS Reserve a slot for a Dynamic 30FPS Extended Sprite of 48x48.
Reserve Slot for 48x48 60FPS Extended Sprite !Reserve48x48ExtendedSpriteOf60FPS Reserve a slot for a Dynamic 60FPS Extended Sprite of 48x48.
Reserve Slot for 48x48 30FPS Cluster Sprite !Reserve48x48ClusterSpriteOf30FPS Reserve a slot for a Dynamic 30FPS Cluster Sprite of 48x48.
Reserve Slot for 48x48 60FPS Cluster Sprite !Reserve48x48ClusterSpriteOf60FPS Reserve a slot for a Dynamic 60FPS Cluster Sprite of 48x48.
Reserve Slot for 48x48 30FPS Overworld Sprite !Reserve48x48OWSpriteOf30FPS Reserve a slot for a Dynamic 30FPS Overworld Sprite of 48x48.
Reserve Slot for 48x48 60FPS Overworld Sprite !Reserve48x48OWSpriteOf60FPS Reserve a slot for a Dynamic 60FPS Overworld Sprite of 48x48.
Reserve Slot for 64x64 30FPS Normal Sprite !Reserve64x64NormalSpriteOf30FPS Reserve a slot for a Dynamic 30FPS Normal Sprite of 64x64.
Reserve Slot for 64x64 60FPS Normal Sprite !Reserve64x64NormalSpriteOf60FPS Reserve a slot for a Dynamic 60FPS Normal Sprite of 64x64.
Reserve Slot for 64x64 30FPS Extended Sprite !Reserve64x64ExtendedSpriteOf30FPS Reserve a slot for a Dynamic 30FPS Extended Sprite of 64x64.
Reserve Slot for 64x64 60FPS Extended Sprite !Reserve64x64ExtendedSpriteOf60FPS Reserve a slot for a Dynamic 60FPS Extended Sprite of 64x64.
Reserve Slot for 64x64 30FPS Cluster Sprite !Reserve64x64ClusterSpriteOf30FPS Reserve a slot for a Dynamic 30FPS Cluster Sprite of 64x64.
Reserve Slot for 64x64 60FPS Cluster Sprite !Reserve64x64ClusterSpriteOf60FPS Reserve a slot for a Dynamic 60FPS Cluster Sprite of 64x64.
Reserve Slot for 64x64 30FPS Overworld Sprite !Reserve64x64OWSpriteOf30FPS Reserve a slot for a Dynamic 30FPS Overworld Sprite of 64x64.
Reserve Slot for 64x64 60FPS Overworld Sprite !Reserve64x64OWSpriteOf60FPS Reserve a slot for a Dynamic 60FPS Overworld Sprite of 64x64.
Reserve Slot for 80x80 30FPS Normal Sprite !Reserve80x80NormalSpriteOf30FPS Reserve a slot for a Dynamic 30FPS Normal Sprite of 80x80.
Reserve Slot for 80x80 60FPS Normal Sprite !Reserve80x80NormalSpriteOf60FPS Reserve a slot for a Dynamic 60FPS Normal Sprite of 80x80.
Reserve Slot for 80x80 30FPS Extended Sprite !Reserve80x80ExtendedSpriteOf30FPS Reserve a slot for a Dynamic 30FPS Extended Sprite of 80x80.
Reserve Slot for 80x80 60FPS Extended Sprite !Reserve80x80ExtendedSpriteOf60FPS Reserve a slot for a Dynamic 60FPS Extended Sprite of 80x80.
Reserve Slot for 80x80 30FPS Cluster Sprite !Reserve80x80ClusterSpriteOf30FPS Reserve a slot for a Dynamic 30FPS Cluster Sprite of 80x80.
Reserve Slot for 80x80 60FPS Cluster Sprite !Reserve80x80ClusterSpriteOf60FPS Reserve a slot for a Dynamic 60FPS Cluster Sprite of 80x80.
Reserve Slot for 80x80 30FPS Overworld Sprite !Reserve80x80OWSpriteOf30FPS Reserve a slot for a Dynamic 30FPS Overworld Sprite of 80x80.
Reserve Slot for 80x80 60FPS Overworld Sprite !Reserve80x80OWSpriteOf60FPS Reserve a slot for a Dynamic 60FPS Overworld Sprite of 80x80.
Send Signal for 16x16 Normal Sprite !SendSignal16x16Normal Send a signal to Dynamic Z to avoid overwrite slots used for a Dynamic Normal Sprite of 16x16.
Send Signal for 16x16 Extended Sprite !SendSignal16x16Extended Send a signal to Dynamic Z to avoid overwrite slots used for a Dynamic Extended Sprite of 16x16.
Send Signal for 16x16 Cluster Sprite !SendSignal16x16Cluster Send a signal to Dynamic Z to avoid overwrite slots used for a Dynamic Cluster Sprite of 16x16.
Send Signal for 16x16 Overworld Sprite !SendSignal16x16OW Send a signal to Dynamic Z to avoid overwrite slots used for a Dynamic Overworld Sprite of 16x16.
Send Signal for 32x16 Normal Sprite !SendSignal32x16Normal Send a signal to Dynamic Z to avoid overwrite slots used for a Dynamic Normal Sprite of 32x16.
Send Signal for 32x16 Extended Sprite !SendSignal32x16Extended Send a signal to Dynamic Z to avoid overwrite slots used for a Dynamic Extended Sprite of 32x16.
Send Signal for 32x16 Cluster Sprite !SendSignal32x16Cluster Send a signal to Dynamic Z to avoid overwrite slots used for a Dynamic Cluster Sprite of 32x16.
Send Signal for 32x16 Overworld Sprite !SendSignal32x16OW Send a signal to Dynamic Z to avoid overwrite slots used for a Dynamic Overworld Sprite of 32x16.
Send Signal for 32x32 Normal Sprite !SendSignal32x32Normal Send a signal to Dynamic Z to avoid overwrite slots used for a Dynamic Normal Sprite of 32x32.
Send Signal for 32x32 Extended Sprite !SendSignal32x32Extended Send a signal to Dynamic Z to avoid overwrite slots used for a Dynamic Extended Sprite of 32x32.
Send Signal for 32x32 Cluster Sprite !SendSignal32x32Cluster Send a signal to Dynamic Z to avoid overwrite slots used for a Dynamic Cluster Sprite of 32x32.
Send Signal for 32x32 Overworld Sprite !SendSignal32x32OW Send a signal to Dynamic Z to avoid overwrite slots used for a Dynamic Overworld Sprite of 32x32.
Send Signal for 48x48 Normal Sprite !SendSignal48x48Normal Send a signal to Dynamic Z to avoid overwrite slots used for a Dynamic Normal Sprite of 48x48.
Send Signal for 48x48 Extended Sprite !SendSignal48x48Extended Send a signal to Dynamic Z to avoid overwrite slots used for a Dynamic Extended Sprite of 48x48.
Send Signal for 48x48 Cluster Sprite !SendSignal48x48Cluster Send a signal to Dynamic Z to avoid overwrite slots used for a Dynamic Cluster Sprite of 48x48.
Send Signal for 48x48 Overworld Sprite !SendSignal48x48OW Send a signal to Dynamic Z to avoid overwrite slots used for a Dynamic Overworld Sprite of 48x48.
Send Signal for 64x64 Normal Sprite !SendSignal64x64Normal Send a signal to Dynamic Z to avoid overwrite slots used for a Dynamic Normal Sprite of 64x64.
Send Signal for 64x64 Extended Sprite !SendSignal64x64Extended Send a signal to Dynamic Z to avoid overwrite slots used for a Dynamic Extended Sprite of 64x64.
Send Signal for 64x64 Cluster Sprite !SendSignal64x64Cluster Send a signal to Dynamic Z to avoid overwrite slots used for a Dynamic Cluster Sprite of 64x64.
Send Signal for 64x64 Overworld Sprite !SendSignal64x64OW Send a signal to Dynamic Z to avoid overwrite slots used for a Dynamic Overworld Sprite of 64x64.
Send Signal for 80x80 Normal Sprite !SendSignal80x80Normal Send a signal to Dynamic Z to avoid overwrite slots used for a Dynamic Normal Sprite of 80x80.
Send Signal for 80x80 Extended Sprite !SendSignal80x80Extended Send a signal to Dynamic Z to avoid overwrite slots used for a Dynamic Extended Sprite of 80x80.
Send Signal for 80x80 Cluster Sprite !SendSignal80x80Cluster Send a signal to Dynamic Z to avoid overwrite slots used for a Dynamic Cluster Sprite of 80x80.
Send Signal for 80x80 Overworld Sprite !SendSignal80x80OW Send a signal to Dynamic Z to avoid overwrite slots used for a Dynamic Overworld Sprite of 80x80.

Macros

Dynamic Z Include a Macro to do Dynamic Routines easier, the macro is called %DynamicRoutine:

macro DynamicRoutine(FPS, SignalRoutine, TransferFrame, FrameIndex, LastFrameIndex, VRAMDisp, BNK, DynamicRoutine, GFXPointer, ResourceOffset, ResourceSize)

The parameters are:

  • FPS: if it is 1 then is a Dynamic routine for 30FPS dynamic sprites, if it is 0 then it is a Dynamic Routine for 60FPS dynamic sprites.
  • SignalRoutine: Here you must use one "Send Signal" routines that are on the Routines section. The routine used depends on your sprite, for example if the sprite is 48x48 and it is a Normal sprite then you must use !SendSignal48x48Normal.
  • TransferFrame: Here you must use one of the "Transfer Frame" sprite tables that are on the RAM Addresses section. The table depends on your sprite, for example, if you are making a Normal Sprite then you must use !TransferFrameNormalSprite.
  • FrameIndex: Here you must select a sprite table that you are using for sprite frame. It is used to know what Graphics must load to the VRAM.
  • LastFrameIndex: Here you must select a sprite table for this, this table will be used to save the last frame loaded to the VRAM. Then if the frame doesn't change then won't load graphics again.
  • VRAMDisp: Here you must use one of the "VRAMDisp" sprite tables that are on the RAM Addresses section. The table depends on your sprite, for example, if you are making a Normal Sprite then you must use !VRAMDispNormalSprite.
  • BNK: Here you must indicates in what bank are allocated the resources, if you includes the graphics on the sprite code, then you can do something like this:
	PHB
	PLA
	STA $53

And use $53 as the parameter ($53 is a scratch ram).

  • DynamicRoutine: Here you must use one "DynamicRoutine" routines that are on the Routines section. The routine used depends on your sprite, for example if the sprite is 48x48 sprite then you must use !DynamicRoutine48x48.
  • GFXPointer: This is a 24 bits value that it is used to know where are allocated the graphics on the ROM (or RAM). If you includes the graphics of the sprite on the code, you can do something like this:
GFXPointer:
	dw resource

resource:
	incbin "sprites\gfx.bin"
  • ResourceOffset: This is a 24 bits value that indicates the ROM Address of a table of 16 bits values. Each value of the tables represent the offset of a line that must be loaded on the VRAM, a line is a row of 8 pixels of height that will be loaded to the VRAM, each size of sprite have a number of lines per frame.
Size Lines
16x16 2
32x16 2
32x32 2
48x48 2
64x64 4
80x80 6

Each value of this table, have the offset of that line in bytes, how to know the offset? well each space 8x8 on the gfx uses 32 bytes (#$20 bytes), a complete row of on a GFX uses 512 bytes (#$0200 bytes), for example in this case:

Piranha Plant Example.png

The first line of the first frame start at the top left of the GFX, it uses the Offset $0000, the second line is 1 row below then you must add 512 bytes, then its value should be $0200, the third line is 1 row below second line then it must be $0400. This example is only to show how calculate the value of the offset, but in real cases piranha plant is a 32x32 dynamic sprite then it only use 2 lines.

  • ResourceSize: This is a 24 bits value that indicates the ROM Address of a table of 16 bits values. Each value of the tables represent the lenght of a line that must be loaded on the VRAM. To calculate this, you must considere that each 8x8 tile requires 32 bytes (#$20 bytes), Considering this, on the last example each line should have a value of $0080. If a line uses 512 bytes, then you can add the next line and the next line set it in 0, this allows to load both line in only 1 DMA transfer. Example:
ResourceSize:
Walk0_ResourceSize:
	dw $0200,$0200,$0060,$0040

Can be changed to:

ResourceSize:
Walk0_ResourceSize:
	dw $0460,$0000,$0000,$0040

Both are the same, but the second way transfer 3 lines in 1 DMA transfer saving some cycles

Tables

The graphic routine of the Dynamic Sprite requires an offset for the oam tiles. For that Dynamic Z includes some tables for each size of sprite:

Name Define Description
OAM Offset for 16x16 sprites !OAMOffset16x16 A table with the OAM Offset for Dynamic Sprites of 16x16.
OAM Offset for 32x16 sprites !OAMOffset32x16 A table with the OAM Offset for Dynamic Sprites of 32x16.
OAM Offset for 32x32 sprites !OAMOffset32x32 A table with the OAM Offset for Dynamic Sprites of 32x32.
OAM Offset for 48x48 sprites !OAMOffset48x48 A table with the OAM Offset for Dynamic Sprites of 48x48.
OAM Offset for 64x64 sprites !OAMOffset64x64 A table with the OAM Offset for Dynamic Sprites of 64x64.
OAM Offset for 80x80 sprites !OAMOffset80x80 A table with the OAM Offset for Dynamic Sprites of 80x80.

The tables must be indexed using VRAM Disp Sprite Table. For example:

	PHX
	PHX
	LDA !VRAMDispNormalSprite,x
	TAX  
	LDA !OAMOffset64x64,x
	STA !ScratchE
	PLX

Then you can use that offset to change the tile. For Example:

	LDA Tiles,x
	CLC
	ADC !ScratchE
	STA !TileCode,y                     ;Set the Tile code of the tile Y

Tiles used on a Dynamic Sprite, on YXCCPPPT properties have T = 1, and the Tile must be #$20 or more. The graphic routine must considere that. then the complete code should be:

	LDA Props,x
	STA !TileProperty,y
	AND #$01
	BEQ .IsOnSP34
	LDA Tiles,x
	STA !TileCode,y
	BRA .NoAddedOffset

.IsOnSP34
	LDA Tiles,x
	CMP #$20
	BCC .NoAddedOffset
	CLC
	ADC !ScratchE
.NoAddedOffset
	STA !TileCode,y

How To Do a Dynamic Sprite

The easy way is using Dyzen Sprite Maker V1.1.0.0 or higher. The tool will do all the job for you. Please visit Dyzen Sprite Maker.

If you want to do a dynamic sprite by yourself do the following:

1. Add "DynamicZDefines.asm" to the folder "\asm\ExtraDefines" of pixi.

2. Define a table that will have the current index of the frame that the sprite is using. For example:

!FrameIndex = !C2

3. Define a table for Last Frame Index, it will be requires for the macro of Dynamic Routine. For example:

!LastFrameIndex = !1602

4. At the Init of the sprite (in the case of clusters, extended or overworld sprites, makes that the sprite execute a init routine when it is created), set !LastFrameIndex,x with the value #$FF.

	LDA #$FF
	STA !LastFrameIndex,x

5. At the Init call a Reserve Slot routine for you sprite, you must select it based on 3 things, if the sprite is 30 or 60 fps, the type of the sprite and the size, for example for a 64x64 Normal Dynamic Sprite of 30FPS you must call JSL !Reserve64x64NormalSpriteOf30FPS, after call the routine, if found a slot then the Carry will be Set, if not then the sprite will be killed.

	JSL !Reserve64x64NormalSpriteOf30FPS
	BCS +
	RTL
+

6. If the sprite found a slot at the Init of the sprite, then it must send a signal to finish the reservation of the slot. You must call the send signal depends on the size and type of sprite, remember that Send Signal Routine requires A = Transfer Frame Table. For example for a Normal Dynamic sprite of 64x64 you must do this:

	LDA !TransferFrameNormalSprite,x
	JSL !SendSignal64x64Normal

7. Create a Dynamic Routine based on your graphics, for this you must do a ResourceOffset Table and a ResourceLength:

DynamicRoutine:
	PHB
	PLA
	STA $53
	%DynamicRoutine(1, !SendSignal64x64Normal, !TransferFrameNormalSprite, !FrameIndex, !LastFrameIndex, !VRAMDispNormalSprite, $53, !DynamicRoutine64x64, GFXPointer, ResourceOffset, ResourceSize)
RTS

GFXPointer:
	dw resource

resource:
	incbin "sprites\gfx.bin"

Read the chapter Macros to know how to make both tables and how to use the %DynamicRoutine Macro.

8. Call the routine on the Sprite Code in the same place where you call the Graphic Routine.

	JSR GraphicRoutine
	JSR DynamicRoutine

9. You must modify the Graphic Routine, for this you must use the table VRAMDisp. Please read chapter of Tables to know how to do this.

A consideration when you change frame on 30FPS Dynamic Sprite.

If you change the frame without checking if it is possible to change it, then the dynamic sprite will show glitched graphics, to fix that add this code before change the frame:

	LDA !TransferFrameNormalSprite,x
	AND #$01
	STA $00

	LDA !DynamicTimer
	AND #$01
	CMP $00
	BNE +
RTS
+

The Transfer Frame Sprite Table, depends on the type of the sprite.