|
|
(7 intermediate revisions by the same user not shown) |
Line 1: |
Line 1: |
− | {{research|1|Details are subject to corrections}}
| + | #REDIRECT [[Particle Script]] |
− | Retro games feature a uniform, fixed-function '''Particle Script''' system for describing various geometrical effects and weapon systems.
| + | |
− | The PAK archives contain binary resources using [[wikipedia:FourCC|FourCCs]] to build a [[wikipedia:Associative_array|key-value dictionary]].
| + | |
− | These codes correspond to application-specific parameters controlling the system in question.
| + | |
− | | + | |
− | The scripts use a [[wikipedia:Dataflow programming|dataflow paradigm]] built around value-generating ''element'' classes of the following types:
| + | |
− | | + | |
− | * [[#Int Elements|Int]]
| + | |
− | * [[#Real Elements|Real]] (float)
| + | |
− | * [[#Vector Elements|Vector]] (3-component float)
| + | |
− | * [[#Mod Vector Elements|Mod Vector]] (3-component float)
| + | |
− | ** Velocity vector in/out
| + | |
− | ** Position vector in/out
| + | |
− | * [[#Color Elements|Color]] (4-component float, internally converted to RGBA8)
| + | |
− | * [[#UV Elements|UV]] ([[TXTR_(File_Format)|TXTR]] reference and [[wikipedia:UV_mapping|UV coordinate]] source)
| + | |
− | * [[#Emitter Elements|Emitter]]
| + | |
− | ** Initial position vector (3-component float)
| + | |
− | ** Initial velocity vector (3-component float)
| + | |
− | | + | |
− | The system features several subclasses that output generated values through <code>GetValue</code> as a function of the current frame index.
| + | |
− | These implementations may recursively accept input from other elements, permitting effect designs of scalable complexity.
| + | |
− | | + | |
− | == File Layout ==
| + | |
− | | + | |
− | All effect script file formats are read linearly to populate a ''descriptor'' tree of element nodes:
| + | |
− | | + | |
− | * Script Magic FourCC (see [[#Script Types|table below]])
| + | |
− | * Parameters
| + | |
− | ** Key FourCC
| + | |
− | ** Value Parameter(s) (one of:)
| + | |
− | *** <code>NONE</code>: null value (equivalent to not specifying the key at all)
| + | |
− | *** Element FourCC ([[#Elements|see below]])
| + | |
− | **** Child Elements (count/types according to parent)
| + | |
− | * <code>_END</code>
| + | |
− | | + | |
− | == Script Types ==
| + | |
− | | + | |
− | {| class="wikitable"
| + | |
− | !Type
| + | |
− | !Magic
| + | |
− | !Purpose
| + | |
− | |-
| + | |
− | |[[PART (File Format)|PART]]
| + | |
− | |<code>GPSM</code>
| + | |
− | |Particle element generator
| + | |
− | |-
| + | |
− | |[[SWHC (File Format)|SWHC]]
| + | |
− | |<code>SWSH</code>
| + | |
− | |Swoosh generator
| + | |
− | |-
| + | |
− | |[[ELSC (File Format)|ELSC]]
| + | |
− | |<code>ELSM</code>
| + | |
− | |Electric generator
| + | |
− | |-
| + | |
− | |[[DPSC (File Format)|DPSC]]
| + | |
− | |<code>DPSM</code>
| + | |
− | |Decal generator
| + | |
− | |-
| + | |
− | |[[WPSC (File Format)|WPSC]]
| + | |
− | |<code>WPSM</code>
| + | |
− | |Projectile weapon configuration
| + | |
− | |-
| + | |
− | |[[CRSC (File Format)|CRSC]]
| + | |
− | |<code>CRSM</code>
| + | |
− | |Projectile collision response configuration
| + | |
− | |}
| + | |
− | | + | |
− | == Elements ==
| + | |
− | | + | |
− | Many of the animated qualities in particle scripts are achieved with dynamic ''elements''.
| + | |
− | These elements provide I/O interfaces and internally process numeric data that passes through.
| + | |
− | They may also gather data from other sources within the particle system's state.
| + | |
− | | + | |
− | === Int Elements ===
| + | |
− | | + | |
− | {| class="wikitable"
| + | |
− | ! FourCC
| + | |
− | ! Parameters
| + | |
− | ! Description
| + | |
− | ! Notes
| + | |
− | ! MP1
| + | |
− | ! MP2
| + | |
− | ! MP3
| + | |
− | ! DKCR
| + | |
− | ! DKCTF
| + | |
− | {{ParticleElementRow|ADD_|IntElement a, IntElement b|Add|Returns ''a'' + ''b''|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
| + | |
− | {{ParticleElementRow|CHAN|IntElement a, IntElement b, IntElement thresholdFrame|Time Chain|Returns ''a'' when current frame index is less-than ''thresholdFrame'', otherwise ''b''|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
| + | |
− | {{ParticleElementRow|CLMP|IntElement min, IntElement max, IntElement val|Clamp|Returns ''val'' clamped between ''min'' and ''max''|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
| + | |
− | {{ParticleElementRow|CNST|s32 value|Constant|Returns ''value'' on every call|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
| + | |
− | {{ParticleElementRow|DETH|IntElement passthrough, IntElement thresholdFrame|Death|Always returns ''passthrough'', and signals out-of-band to cease updating the system when the current frame index exceeds ''thresholdFrame''|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
| + | |
− | {{ParticleElementRow|GAPC||{{unknown|'''Unknown'''}}||{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
| + | |
− | {{ParticleElementRow|GEMT||{{unknown|'''Unknown'''}}||{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
| + | |
− | {{ParticleElementRow|GTCP||{{unknown|'''Unknown'''}}||{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
| + | |
− | {{ParticleElementRow|ILPT|IntElement percent|Lifetime Percent|Queries the frame index at ''percent''/100.0 into the lifetime of the particle instance|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
| + | |
− | {{ParticleElementRow|IMPL|IntElement val|Impulse|Returns ''val'' ONLY at frame index 0, then returns 0 for subsequent frames|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
| + | |
− | {{ParticleElementRow|IRND|IntElement a, IntElement b|Initial Random|Rolls a random value between ''a'' and ''b'' on frame index 0; returns that value for subsequent frames|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
| + | |
− | {{ParticleElementRow|KEYE|[[#Keyframe Emitter Template|KeyframeEmitterData]] data|Keyframe Emitter|List of synchronized animation keys|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
| + | |
− | {{ParticleElementRow|KEYP|[[#Keyframe Emitter Template|KeyframeEmitterData]] data|Keyframe Emitter|List of percentage-tweened animation keys|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
| + | |
− | {{ParticleElementRow|MODU|IntElement a, IntElement b|Modulo|Returns ''a'' % ''b''|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
| + | |
− | {{ParticleElementRow|MULT|IntElement a, IntElement b|Multiply|Returns ''a'' * ''b''|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
| + | |
− | {{ParticleElementRow|PULS|IntElement aDuration, IntElement bDuration, IntElement a, IntElement b|Pulse|Returns ''a'' for ''aDuration'' frames then ''b'' for ''bDuration'' frames, then repeats this cycle|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
| + | |
− | {{ParticleElementRow|RAND|IntElement a, IntElement b|Random|Rolls a random value between ''a'' and ''b''|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
| + | |
− | {{ParticleElementRow|SPAH|IntElement val, IntElement waitMin, IntElement waitMax|Sample And Hold|Stores ''val'' for a random count of frames between ''waitMin'' and ''waitMax'' and repeats this cycle|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
| + | |
− | {{ParticleElementRow|SUB_|IntElement a, IntElement b|Subtract|Returns ''a'' - ''b''|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
| + | |
− | {{ParticleElementRow|TSCL|RealElement dv|Time Scale|Returns ''dv'' times the current frame index (rounding down to nearest integer)|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
| + | |
− | |}
| + | |
− | | + | |
− | === Real Elements ===
| + | |
− | | + | |
− | {| class="wikitable"
| + | |
− | ! FourCC
| + | |
− | ! Parameters
| + | |
− | ! Description
| + | |
− | ! Notes
| + | |
− | ! MP1
| + | |
− | ! MP2
| + | |
− | ! MP3
| + | |
− | ! DKCR
| + | |
− | ! DKCTF
| + | |
− | {{ParticleElementRow|ADD_|RealElement a, RealElement b|Add|Returns ''a'' + ''b''|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
| + | |
− | {{ParticleElementRow|CEQL|RealElement ca, RealElement cb, RealElement pass, RealElement fail|Compare Equals|Returns ''pass'' if ''ca'' and ''cb'' are within 0.00001 difference, otherwise ''fail''|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
| + | |
− | {{ParticleElementRow|CEXT|IntElement a|{{unknown|'''Unknown'''}}|Involves a global lookup table|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
| + | |
− | {{ParticleElementRow|CHAN|RealElement a, RealElement b, IntElement thresholdFrame|Time Chain|Returns ''a'' when current frame index is less-than ''thresholdFrame'', otherwise ''b''|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
| + | |
− | {{ParticleElementRow|CLMP|RealElement min, RealElement max, RealElement val|Clamp|Returns ''val'' clamped between ''min'' and ''max''|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
| + | |
− | {{ParticleElementRow|CLTN|RealElement ca, RealElement cb, RealElement pass, RealElement fail|Compare Less-Than|Returns ''pass'' if ''ca'' is less-than ''cb'', otherwise ''fail''|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
| + | |
− | {{ParticleElementRow|CNST|float value|Constant|Returns ''value'' on every call|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
| + | |
− | {{ParticleElementRow|CRNG|RealElement val, RealElement min, RealElement max, RealElement inRange, RealElement outOfRange|Constant Range|Returns ''inRange'' if ''val'' is between ''min'' and ''max'', otherwise ''outOfRange''|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
| + | |
− | {{ParticleElementRow|DOTP|VectorElement a, VectorElement b|[[wikipedia:Dot product|Dot Product]]|Returns ''a'' · ''b''|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
| + | |
− | {{ParticleElementRow|GTCR|ColorElement color|Get Component Red|Extracts red component from ''color''|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
| + | |
− | {{ParticleElementRow|GTCG|ColorElement color|Get Component Green|Extracts green component from ''color''|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
| + | |
− | {{ParticleElementRow|GTCB|ColorElement color|Get Component Blue|Extracts blue component from ''color''|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
| + | |
− | {{ParticleElementRow|GTCA|ColorElement color|Get Component Alpha|Extracts alpha component from ''color''|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
| + | |
− | {{ParticleElementRow|IRND|RealElement a, RealElement b|Initial Random|Rolls a random value between ''a'' and ''b'' on frame index 0; returns that value for subsequent frames|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
| + | |
− | {{ParticleElementRow|ISWT|RealElement a, RealElement b|Initial Switch|Returns ''a'' ONLY at frame index 0, then returns ''b'' for subsequent frames|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
| + | |
− | {{ParticleElementRow|ITRL|IntElement a, RealElement b|Int Times Real|Returns ''a'' * ''b''|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
| + | |
− | {{ParticleElementRow|KEYE|[[#Keyframe Emitter Template|KeyframeEmitterData]] data|Keyframe Emitter|List of synchronized animation keys|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
| + | |
− | {{ParticleElementRow|KEYP|[[#Keyframe Emitter Template|KeyframeEmitterData]] data|Keyframe Emitter|List of percentage-tweened animation keys|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
| + | |
− | {{ParticleElementRow|LFTW|RealElement a, RealElement b|Lifetime Tween|Linearly-interpolates ''a'' to ''b'' over the lifetime of the particle instance|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
| + | |
− | {{ParticleElementRow|MULT|RealElement a, RealElement b|Multiply|Returns ''a'' * ''b''|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
| + | |
− | {{ParticleElementRow|PAPn||Particle System Access Parameter|Accesses the value stored into ADV[1-8] for each system update|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
| + | |
− | {{ParticleElementRow|PRLW||Particle Rotation or Line Width|Returns the rotation (in degrees) or line width for the current particle instance|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
| + | |
− | {{ParticleElementRow|PSLL||Particle Size or Line Length|Returns the size or line length for the current particle instance|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
| + | |
− | {{ParticleElementRow|PULS|IntElement aDuration, IntElement bDuration, RealElement a, RealElement b|Pulse|Returns ''a'' for ''aDuration'' frames then ''b'' for ''bDuration'' frames, then repeats this cycle|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
| + | |
− | {{ParticleElementRow|RAND|RealElement a, RealElement b|Random|Rolls a random value between ''a'' and ''b''|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
| + | |
− | {{ParticleElementRow|RLPT|RealElement percent|Lifetime Percent|Queries the frame index at ''percent''/100.0 into the lifetime of the particle instance|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
| + | |
− | {{ParticleElementRow|SCAL|RealElement dv|Time Scale|Returns ''dv'' times the current frame index|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
| + | |
− | {{ParticleElementRow|SINE|RealElement magnitude, RealElement linearAngle, RealElement constantAngle|Sine Wave|Returns sin((curFrame * ''linearAngle'' + ''constantAngle'') * π / 180.0) * ''magnitude''|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
| + | |
− | {{ParticleElementRow|SUB_|RealElement a, RealElement b|Subtract|Returns ''a'' - ''b''|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
| + | |
− | {{ParticleElementRow|VMAG|VectorElement vec|Vector Magnitude|Computes magnitude (length) of ''vec''|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
| + | |
− | {{ParticleElementRow|VXTR|VectorElement vec|Vector X To Real|Extracts X component of ''vec''|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
| + | |
− | {{ParticleElementRow|VYTR|VectorElement vec|Vector Y To Real|Extracts Y component of ''vec''|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
| + | |
− | {{ParticleElementRow|VZTR|VectorElement vec|Vector Z To Real|Extracts Z component of ''vec''|{{check}}|{{check}}|{{check}}|{{check}}|{{check}}}}
| + | |
− | | + | |
− | |}
| + | |
− | | + | |
− | === Vector Elements ===
| + | |
− | | + | |
− | === Mod Vector Elements ===
| + | |
− | | + | |
− | === Color Elements ===
| + | |
− | | + | |
− | === UV Elements ===
| + | |
− | | + | |
− | === Emitter Elements ===
| + | |
− | | + | |
− | | + | |
− | === Keyframe Emitter Template ===
| + | |
− | | + | |
− | <code>KEYE</code> and <code>KEYP</code> elements are able to statically encode a list of key values for all element types (except UV and Emitter elements).
| + | |
− | ''T'' represents the type being encoded.
| + | |
− | | + | |
− | {| class="wikitable"
| + | |
− | ! Data Type
| + | |
− | ! Description
| + | |
− | ! Notes
| + | |
− | |-
| + | |
− | | u32
| + | |
− | | Percentage-Tweening Flag
| + | |
− | | If non-zero, this is a <code>KEYP</code> and there are exactly 101 keys in the list; all of these keys are linearly-interpolated over the lifetime of the particle instance (however long that may be)
| + | |
− | |-
| + | |
− | | u32
| + | |
− | | {{unknown|'''Unknown'''}}
| + | |
− | | Not used by <code>GetValue</code>
| + | |
− | |-
| + | |
− | | u8
| + | |
− | | Loop Flag
| + | |
− | | If non-zero, the key values are looped between ''loopStart'' and ''loopEnd'' indices (does not apply to <code>KEYP</code>)
| + | |
− | |-
| + | |
− | | u8
| + | |
− | | {{unknown|'''Unknown'''}}
| + | |
− | | Not used by <code>GetValue</code>
| + | |
− | |-
| + | |
− | | u32
| + | |
− | | Loop End
| + | |
− | | Final key index in the loop
| + | |
− | |-
| + | |
− | | u32
| + | |
− | | Loop Start
| + | |
− | | First key index in the loop
| + | |
− | |-
| + | |
− | | u32
| + | |
− | | Key Count
| + | |
− | | Count of keys encoded in the list
| + | |
− | |-
| + | |
− | | T[keyCount]
| + | |
− | | Keys
| + | |
− | | The actual key values themselves
| + | |
− | |}
| + | |
− | | + | |
− | | + | |
− | | + | |
− | [[Category:File Formats]]
| + | |
− | [[Category:Metroid Prime]]
| + | |
− | [[Category:Metroid Prime 2: Echoes]]
| + | |
− | [[Category:Metroid Prime 3: Corruption]]
| + | |
− | [[Category:Donkey Kong Country Returns]]
| + | |