feat: port DisplayGfx slots 4 (set_layer_color) and 6 (get_sprite_info)
Browse filesPort two more DisplayGfx vtable methods to pure Rust (20/38 total):
- Slot 4 (set_layer_color): palette slot allocator scans slot_table for
consecutive free entries, allocates and initializes a PaletteContext
with the claimed palette range.
- Slot 6 (get_sprite_info): dispatches to Sprite or SpriteBank paths,
returning sprite metadata (data, flags, width) via output pointers.
Fixed vtable signature from 3 to 4 stack params (RET 0x10).
Type safety improvements:
- Define SpriteBank (0x17C), SpriteBankFrame (0xC) structs
- Add typed SpriteVtable (8 slots) and SpriteBankVtable (3 slots)
- Rename DisplayBase fields: sprite_array_0/1/2 → sprite_palettes/
sprite_ptrs/sprite_banks; _field_312c/352c → slot_table_guard/sentinel
- Move Sprite/SpriteBank/PaletteContext addresses to home modules
- Move SpriteId enum to dedicated sprite_id module
- Delete obsolete dd_display_sprite_offsets and sprite_vtable modules
- Label 7 functions + STR_SPRITE in Ghidra
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- crates/openwa-core/src/address.rs +20 -19
- crates/openwa-core/src/display/base.rs +20 -14
- crates/openwa-core/src/display/display_vtable.rs +250 -4
- crates/openwa-core/src/render/mod.rs +1 -0
- crates/openwa-core/src/render/palette.rs +11 -0
- crates/openwa-core/src/render/sprite.rs +109 -757
- crates/openwa-core/src/render/sprite_id.rs +720 -0
- crates/openwa-dll/src/replacements/display.rs +4 -2
- crates/openwa-dll/src/replacements/sprite.rs +2 -2
- crates/openwa-dll/src/startup_checks.rs +1 -0
|
@@ -86,6 +86,16 @@ pub mod va {
|
|
| 86 |
pub use crate::input::controller::INPUT_CTRL_VTABLE;
|
| 87 |
pub use crate::task::game_task::SOUND_EMITTER_VTABLE;
|
| 88 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 89 |
crate::define_addresses! {
|
| 90 |
class "DDGameWrapper" {
|
| 91 |
/// DDGameWrapper vtable
|
|
@@ -200,21 +210,6 @@ pub mod va {
|
|
| 200 |
vtable WATER_EFFECT_VTABLE = 0x0066_B268;
|
| 201 |
}
|
| 202 |
|
| 203 |
-
class "Sprite" {
|
| 204 |
-
/// Sprite vtable (0x70-byte objects, 8 entries)
|
| 205 |
-
vtable SPRITE_VTABLE = 0x0066_418C;
|
| 206 |
-
/// ConstructSprite — usercall EAX=sprite_ptr, ECX=context_ptr
|
| 207 |
-
ctor/Usercall CONSTRUCT_SPRITE = 0x004F_AA30;
|
| 208 |
-
/// Sprite destructor — thiscall, vtable slot 0
|
| 209 |
-
fn/Thiscall DESTROY_SPRITE = 0x004F_AA80;
|
| 210 |
-
/// LoadSpriteFromVfs
|
| 211 |
-
fn/Usercall LOAD_SPRITE_FROM_VFS = 0x004F_AAF0;
|
| 212 |
-
/// ProcessSprite — parses .spr binary format
|
| 213 |
-
fn/Usercall PROCESS_SPRITE = 0x004F_AB80;
|
| 214 |
-
// Note: vtable 0x664144 is BitGrid display-layer vtable,
|
| 215 |
-
// now defined via #[vtable] macro as BITGRID_DISPLAY_VTABLE.
|
| 216 |
-
}
|
| 217 |
-
|
| 218 |
class "GfxHandler" {
|
| 219 |
/// GfxHandler vtable
|
| 220 |
vtable GFX_DIR_VTABLE = 0x0066_B280;
|
|
@@ -228,6 +223,11 @@ pub mod va {
|
|
| 228 |
fn GFX_DIR_LOAD_IMAGE = 0x0056_66D0;
|
| 229 |
}
|
| 230 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 231 |
class "DisplayGfx" {
|
| 232 |
/// DisplayGfx constructor
|
| 233 |
ctor/Stdcall DISPLAYGFX_CTOR = 0x0056_9C10;
|
|
@@ -237,8 +237,13 @@ pub mod va {
|
|
| 237 |
fn/Stdcall DISPLAYGFX_CONSTRUCT_FULL = 0x0056_3FC0;
|
| 238 |
/// DisplayGfx init team palette display objects
|
| 239 |
fn/Stdcall DISPLAY_GFX_INIT_TEAM_PALETTE_DISPLAY = 0x0057_03E0;
|
|
|
|
|
|
|
| 240 |
}
|
| 241 |
|
|
|
|
|
|
|
|
|
|
| 242 |
}
|
| 243 |
|
| 244 |
// Backward-compat aliases (not registered separately — same address)
|
|
@@ -473,10 +478,6 @@ pub mod va {
|
|
| 473 |
fn OPENGL_INIT = 0x0059_F000;
|
| 474 |
/// GfxResource__Create_Maybe
|
| 475 |
fn GFX_RESOURCE_CREATE = 0x004F_6300;
|
| 476 |
-
/// PaletteContext__Init
|
| 477 |
-
fn/Usercall PALETTE_CONTEXT_INIT = 0x0054_11A0;
|
| 478 |
-
/// PaletteContext__MapColor — thiscall(palette_ctx, rgb_u32), returns nearest palette index
|
| 479 |
-
fn/Thiscall PALETTE_CONTEXT_MAP_COLOR = 0x0054_12B0;
|
| 480 |
/// SpriteGfxTable__Init
|
| 481 |
fn/Fastcall SPRITE_GFX_TABLE_INIT = 0x0054_1620;
|
| 482 |
/// RingBuffer__Init
|
|
|
|
| 86 |
pub use crate::input::controller::INPUT_CTRL_VTABLE;
|
| 87 |
pub use crate::task::game_task::SOUND_EMITTER_VTABLE;
|
| 88 |
|
| 89 |
+
// Sprite, SpriteBank, PaletteContext — defined alongside their structs
|
| 90 |
+
pub use crate::render::palette::{
|
| 91 |
+
PALETTE_CONTEXT_INIT, PALETTE_CONTEXT_INIT_RANGE, PALETTE_CONTEXT_MAP_COLOR,
|
| 92 |
+
};
|
| 93 |
+
pub use crate::render::sprite::SPRITE_BANK_VTABLE;
|
| 94 |
+
pub use crate::render::sprite::{
|
| 95 |
+
CONSTRUCT_SPRITE, DESTROY_SPRITE, LOAD_SPRITE_FROM_VFS, PROCESS_SPRITE,
|
| 96 |
+
SPRITE_BANK_GET_INFO, SPRITE_GET_INFO, SPRITE_VTABLE,
|
| 97 |
+
};
|
| 98 |
+
|
| 99 |
crate::define_addresses! {
|
| 100 |
class "DDGameWrapper" {
|
| 101 |
/// DDGameWrapper vtable
|
|
|
|
| 210 |
vtable WATER_EFFECT_VTABLE = 0x0066_B268;
|
| 211 |
}
|
| 212 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 213 |
class "GfxHandler" {
|
| 214 |
/// GfxHandler vtable
|
| 215 |
vtable GFX_DIR_VTABLE = 0x0066_B280;
|
|
|
|
| 223 |
fn GFX_DIR_LOAD_IMAGE = 0x0056_66D0;
|
| 224 |
}
|
| 225 |
|
| 226 |
+
class "DisplayBase" {
|
| 227 |
+
/// DisplayBase__AllocPaletteSlots — usercall EAX=count, 1 stack(this)
|
| 228 |
+
fn/Usercall DISPLAY_BASE_ALLOC_PALETTE_SLOTS = 0x0052_3190;
|
| 229 |
+
}
|
| 230 |
+
|
| 231 |
class "DisplayGfx" {
|
| 232 |
/// DisplayGfx constructor
|
| 233 |
ctor/Stdcall DISPLAYGFX_CTOR = 0x0056_9C10;
|
|
|
|
| 237 |
fn/Stdcall DISPLAYGFX_CONSTRUCT_FULL = 0x0056_3FC0;
|
| 238 |
/// DisplayGfx init team palette display objects
|
| 239 |
fn/Stdcall DISPLAY_GFX_INIT_TEAM_PALETTE_DISPLAY = 0x0057_03E0;
|
| 240 |
+
/// DisplayGfx__LoadSpriteEx (vtable slot 30) — thiscall
|
| 241 |
+
fn/Thiscall DISPLAY_GFX_LOAD_SPRITE_EX = 0x0052_3310;
|
| 242 |
}
|
| 243 |
|
| 244 |
+
/// "sprite" type-tag string in .rdata — returned by Sprite/SpriteBank GetInfo
|
| 245 |
+
global STR_SPRITE = 0x0066_4170;
|
| 246 |
+
|
| 247 |
}
|
| 248 |
|
| 249 |
// Backward-compat aliases (not registered separately — same address)
|
|
|
|
| 478 |
fn OPENGL_INIT = 0x0059_F000;
|
| 479 |
/// GfxResource__Create_Maybe
|
| 480 |
fn GFX_RESOURCE_CREATE = 0x004F_6300;
|
|
|
|
|
|
|
|
|
|
|
|
|
| 481 |
/// SpriteGfxTable__Init
|
| 482 |
fn/Fastcall SPRITE_GFX_TABLE_INIT = 0x0054_1620;
|
| 483 |
/// RingBuffer__Init
|
|
@@ -33,13 +33,15 @@ pub struct DisplayBase<V: Vtable = *const DisplayBaseVtable> {
|
|
| 33 |
pub vtable: V,
|
| 34 |
// +0x004: sprite cache wrapper (0x28-byte SpriteCacheWrapper)
|
| 35 |
pub sprite_cache: Ptr32,
|
| 36 |
-
// +0x008..0x1008:
|
| 37 |
-
//
|
| 38 |
-
pub
|
| 39 |
-
// +0x1008..0x2008:
|
| 40 |
-
|
| 41 |
-
|
| 42 |
-
|
|
|
|
|
|
|
| 43 |
// +0x3008..0x3018: gap (0x10 bytes, 4 u32s: indices 0xC02..0xC05)
|
| 44 |
pub _gap_3008: [u32; 4],
|
| 45 |
// +0x3018: field at u32 index 0xC06, zeroed by ctor
|
|
@@ -53,12 +55,16 @@ pub struct DisplayBase<V: Vtable = *const DisplayBaseVtable> {
|
|
| 53 |
// Indexed by layer (valid range 1-3). Returned by set_active_layer (vtable slot 5).
|
| 54 |
// Used as palette data input for update_palette (vtable slot 24).
|
| 55 |
pub layer_contexts: [u32; 4],
|
| 56 |
-
// +0x312C:
|
| 57 |
-
|
| 58 |
-
//
|
|
|
|
|
|
|
|
|
|
| 59 |
pub slot_table: [u32; 0xFF],
|
| 60 |
-
// +0x352C:
|
| 61 |
-
|
|
|
|
| 62 |
// +0x3530..0x3540: layer visibility flags (4 entries), zeroed by ctor.
|
| 63 |
// Indexed by layer. Cleared to 0 by set_layer_visibility when visible < 0.
|
| 64 |
pub layer_visibility: [u32; 4],
|
|
@@ -187,8 +193,8 @@ impl DisplayBase {
|
|
| 187 |
*slot = 1;
|
| 188 |
}
|
| 189 |
|
| 190 |
-
// Sentinel value
|
| 191 |
-
(*this).
|
| 192 |
|
| 193 |
// Create sprite cache: 0x28 wrapper → 0x3C buffer ctrl → 0x80020 buffer.
|
| 194 |
//
|
|
|
|
| 33 |
pub vtable: V,
|
| 34 |
// +0x004: sprite cache wrapper (0x28-byte SpriteCacheWrapper)
|
| 35 |
pub sprite_cache: Ptr32,
|
| 36 |
+
// +0x008..0x1008: per-slot palette/layer ID (0x400 entries), zeroed by ctor.
|
| 37 |
+
// Stores which layer (1-3) each sprite slot belongs to.
|
| 38 |
+
pub sprite_palettes: [u32; 0x400],
|
| 39 |
+
// +0x1008..0x2008: per-slot Sprite* pointers (0x400 entries), zeroed by ctor.
|
| 40 |
+
// Points to Sprite objects (0x70 bytes, vtable 0x66418C). Checked by IsSpriteLoaded/GetSpriteInfo.
|
| 41 |
+
pub sprite_ptrs: [u32; 0x400],
|
| 42 |
+
// +0x2008..0x3008: per-slot SpriteBank* pointers (0x400 entries), zeroed by ctor.
|
| 43 |
+
// Points to SpriteBank objects (0x17C bytes). Fallback path in GetSpriteInfo/LoadSpriteComplex.
|
| 44 |
+
pub sprite_banks: [u32; 0x400],
|
| 45 |
// +0x3008..0x3018: gap (0x10 bytes, 4 u32s: indices 0xC02..0xC05)
|
| 46 |
pub _gap_3008: [u32; 4],
|
| 47 |
// +0x3018: field at u32 index 0xC06, zeroed by ctor
|
|
|
|
| 55 |
// Indexed by layer (valid range 1-3). Returned by set_active_layer (vtable slot 5).
|
| 56 |
// Used as palette data input for update_palette (vtable slot 24).
|
| 57 |
pub layer_contexts: [u32; 4],
|
| 58 |
+
// +0x312C: Palette slot table guard. Always 0 — prevents palette_slot_alloc
|
| 59 |
+
// from allocating starting at index 0. Part of the contiguous scan area:
|
| 60 |
+
// [slot_table_guard(0)] [slot_table(1s)...] [slot_table_sentinel(-1)].
|
| 61 |
+
pub slot_table_guard: u32,
|
| 62 |
+
// +0x3130..0x352C: Palette slot table — 0xFF entries, all initialized to 1 by ctor.
|
| 63 |
+
// Value 1 = available, 0 = in-use. Scanned by palette_slot_alloc (set_layer_color).
|
| 64 |
pub slot_table: [u32; 0xFF],
|
| 65 |
+
// +0x352C: Palette slot table sentinel. Initialized to -1 (0xFFFFFFFF).
|
| 66 |
+
// Terminates the palette_slot_alloc scan with failure if no free slots found.
|
| 67 |
+
pub slot_table_sentinel: u32,
|
| 68 |
// +0x3530..0x3540: layer visibility flags (4 entries), zeroed by ctor.
|
| 69 |
// Indexed by layer. Cleared to 0 by set_layer_visibility when visible < 0.
|
| 70 |
pub layer_visibility: [u32; 4],
|
|
|
|
| 193 |
*slot = 1;
|
| 194 |
}
|
| 195 |
|
| 196 |
+
// Sentinel value — terminates palette_slot_alloc scan
|
| 197 |
+
(*this).slot_table_sentinel = 0xFFFF_FFFF;
|
| 198 |
|
| 199 |
// Create sprite cache: 0x28 wrapper → 0x3C buffer ctrl → 0x80020 buffer.
|
| 200 |
//
|
|
@@ -47,8 +47,19 @@ pub struct DisplayVtable {
|
|
| 47 |
#[slot(5)]
|
| 48 |
pub set_active_layer: fn(this: *mut DisplayGfx, layer: i32) -> *mut u8,
|
| 49 |
/// get sprite info by layer and id (0x523500, RET 0x10)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 50 |
#[slot(6)]
|
| 51 |
-
pub get_sprite_info: fn(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 52 |
/// draw text onto a bitmap surface (0x5236B0, RET 0x1C)
|
| 53 |
///
|
| 54 |
/// font_id low 16 bits = font slot (1-based), high 16 bits = extra flags.
|
|
@@ -272,10 +283,12 @@ bind_DisplayVtable!(DisplayGfx, base.vtable);
|
|
| 272 |
// Ported DisplayGfx vtable methods
|
| 273 |
// =========================================================================
|
| 274 |
|
|
|
|
| 275 |
use super::gfx::DisplayGfx;
|
| 276 |
use super::line_draw;
|
| 277 |
use crate::bitgrid::DisplayBitGrid;
|
| 278 |
use crate::render::palette::PaletteContext;
|
|
|
|
| 279 |
|
| 280 |
/// Port of DisplayGfx::GetDimensions (vtable slot 1, 0x56A460).
|
| 281 |
///
|
|
@@ -770,7 +783,7 @@ pub unsafe extern "thiscall" fn draw_polyline(
|
|
| 770 |
/// Port of DisplayGfx::IsSpriteLoaded (vtable slot 32, 0x56A480).
|
| 771 |
///
|
| 772 |
/// Returns 1 if the sprite ID is loaded in any of the three sprite arrays
|
| 773 |
-
/// (DisplayBase
|
| 774 |
/// ID must be in range [1, 0x400).
|
| 775 |
///
|
| 776 |
/// # Safety
|
|
@@ -782,8 +795,8 @@ pub unsafe extern "thiscall" fn is_sprite_loaded(this: *mut DisplayGfx, id: i32)
|
|
| 782 |
}
|
| 783 |
|
| 784 |
let base = &(*this).base;
|
| 785 |
-
if base.
|
| 786 |
-
|| base.
|
| 787 |
|| (*this).sprite_table[id as usize] != 0
|
| 788 |
{
|
| 789 |
1
|
|
@@ -792,6 +805,132 @@ pub unsafe extern "thiscall" fn is_sprite_loaded(this: *mut DisplayGfx, id: i32)
|
|
| 792 |
}
|
| 793 |
}
|
| 794 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 795 |
/// Port of DisplayGfx::DrawViaCallback (vtable slot 21, 0x56B7C0).
|
| 796 |
///
|
| 797 |
/// Acquires the render lock, applies camera offset to fixed-point coordinates,
|
|
@@ -998,6 +1137,113 @@ pub unsafe extern "thiscall" fn draw_pixel_strip(
|
|
| 998 |
}
|
| 999 |
}
|
| 1000 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1001 |
/// Port of DisplayGfx::SetActiveLayer (vtable slot 5, 0x523270).
|
| 1002 |
///
|
| 1003 |
/// Returns the layer context pointer for `layer` (valid: 1, 2, 3), or null
|
|
|
|
| 47 |
#[slot(5)]
|
| 48 |
pub set_active_layer: fn(this: *mut DisplayGfx, layer: i32) -> *mut u8,
|
| 49 |
/// get sprite info by layer and id (0x523500, RET 0x10)
|
| 50 |
+
///
|
| 51 |
+
/// Looks up sprite metadata for the given layer ID. Checks sprite_ptrs
|
| 52 |
+
/// (Sprite* pointers) first, then sprite_banks. On success, writes
|
| 53 |
+
/// sprite data, flags, and width to the output pointers.
|
| 54 |
+
/// Returns a pointer to the string "sprite" on success, or 0 on failure.
|
| 55 |
#[slot(6)]
|
| 56 |
+
pub get_sprite_info: fn(
|
| 57 |
+
this: *mut DisplayGfx,
|
| 58 |
+
layer: i32,
|
| 59 |
+
out_data: *mut u32,
|
| 60 |
+
out_flags: *mut u32,
|
| 61 |
+
out_width: *mut u32,
|
| 62 |
+
) -> u32,
|
| 63 |
/// draw text onto a bitmap surface (0x5236B0, RET 0x1C)
|
| 64 |
///
|
| 65 |
/// font_id low 16 bits = font slot (1-based), high 16 bits = extra flags.
|
|
|
|
| 283 |
// Ported DisplayGfx vtable methods
|
| 284 |
// =========================================================================
|
| 285 |
|
| 286 |
+
use super::base::DisplayBase;
|
| 287 |
use super::gfx::DisplayGfx;
|
| 288 |
use super::line_draw;
|
| 289 |
use crate::bitgrid::DisplayBitGrid;
|
| 290 |
use crate::render::palette::PaletteContext;
|
| 291 |
+
use crate::render::sprite::{Sprite, SpriteBank};
|
| 292 |
|
| 293 |
/// Port of DisplayGfx::GetDimensions (vtable slot 1, 0x56A460).
|
| 294 |
///
|
|
|
|
| 783 |
/// Port of DisplayGfx::IsSpriteLoaded (vtable slot 32, 0x56A480).
|
| 784 |
///
|
| 785 |
/// Returns 1 if the sprite ID is loaded in any of the three sprite arrays
|
| 786 |
+
/// (DisplayBase sprite_ptrs/sprite_banks, DisplayGfx sprite_table).
|
| 787 |
/// ID must be in range [1, 0x400).
|
| 788 |
///
|
| 789 |
/// # Safety
|
|
|
|
| 795 |
}
|
| 796 |
|
| 797 |
let base = &(*this).base;
|
| 798 |
+
if base.sprite_ptrs[id as usize] != 0
|
| 799 |
+
|| base.sprite_banks[id as usize] != 0
|
| 800 |
|| (*this).sprite_table[id as usize] != 0
|
| 801 |
{
|
| 802 |
1
|
|
|
|
| 805 |
}
|
| 806 |
}
|
| 807 |
|
| 808 |
+
/// Port of DisplayGfx::GetSpriteInfo (vtable slot 6, 0x523500).
|
| 809 |
+
///
|
| 810 |
+
/// Looks up sprite metadata for `layer` (valid: 1..=0x3FF). Checks
|
| 811 |
+
/// `sprite_ptrs` (Sprite* pointers) first, then `sprite_banks`
|
| 812 |
+
/// (indexed sprite containers). On success, writes data, flags, and
|
| 813 |
+
/// width to the output pointers and returns a pointer to the static
|
| 814 |
+
/// string "sprite" (0x664170). Returns 0 on failure.
|
| 815 |
+
///
|
| 816 |
+
/// # Safety
|
| 817 |
+
/// `this` must be a valid `*mut DisplayGfx`.
|
| 818 |
+
/// Output pointers must be valid for writing.
|
| 819 |
+
pub unsafe extern "thiscall" fn get_sprite_info(
|
| 820 |
+
this: *mut DisplayGfx,
|
| 821 |
+
layer: i32,
|
| 822 |
+
out_data: *mut u32,
|
| 823 |
+
out_flags: *mut u32,
|
| 824 |
+
out_width: *mut u32,
|
| 825 |
+
) -> u32 {
|
| 826 |
+
if (layer as u32).wrapping_sub(1) > 0x3FE {
|
| 827 |
+
return 0;
|
| 828 |
+
}
|
| 829 |
+
|
| 830 |
+
let base = &(*this).base;
|
| 831 |
+
|
| 832 |
+
// Path 1: Sprite* in sprite_ptrs
|
| 833 |
+
let sprite_ptr = base.sprite_ptrs[layer as usize];
|
| 834 |
+
if sprite_ptr != 0 {
|
| 835 |
+
return sprite_info_from_sprite(
|
| 836 |
+
sprite_ptr as *const Sprite,
|
| 837 |
+
out_data,
|
| 838 |
+
out_flags,
|
| 839 |
+
out_width,
|
| 840 |
+
);
|
| 841 |
+
}
|
| 842 |
+
|
| 843 |
+
// Path 2: SpriteBank* in sprite_banks
|
| 844 |
+
let bank_ptr = base.sprite_banks[layer as usize];
|
| 845 |
+
if bank_ptr != 0 {
|
| 846 |
+
return sprite_info_from_bank(
|
| 847 |
+
bank_ptr as *const SpriteBank,
|
| 848 |
+
layer,
|
| 849 |
+
out_data,
|
| 850 |
+
out_flags,
|
| 851 |
+
out_width,
|
| 852 |
+
);
|
| 853 |
+
}
|
| 854 |
+
|
| 855 |
+
0
|
| 856 |
+
}
|
| 857 |
+
|
| 858 |
+
/// Address of the static "sprite" string in WA.exe .rdata.
|
| 859 |
+
/// Used as a type-tag return value by sprite info functions.
|
| 860 |
+
const SPRITE_STRING: u32 = va::STR_SPRITE;
|
| 861 |
+
|
| 862 |
+
/// Extract sprite info from a Sprite object — port of Sprite__GetInfo (0x4FAEC0).
|
| 863 |
+
///
|
| 864 |
+
/// Usercall: EAX=Sprite*, ESI=out_data, ECX=out_width, stack=out_flags.
|
| 865 |
+
/// Reads frame_meta_ptr (validity check), packed _unknown_08/fps as data,
|
| 866 |
+
/// max_frames as width (doubled-minus-one if flags & 2), and flags & 1.
|
| 867 |
+
unsafe fn sprite_info_from_sprite(
|
| 868 |
+
sprite: *const Sprite,
|
| 869 |
+
out_data: *mut u32,
|
| 870 |
+
out_flags: *mut u32,
|
| 871 |
+
out_width: *mut u32,
|
| 872 |
+
) -> u32 {
|
| 873 |
+
let s = &*sprite;
|
| 874 |
+
|
| 875 |
+
// Validity check: frame_meta_ptr must be non-null
|
| 876 |
+
if s.frame_meta_ptr.is_null() {
|
| 877 |
+
return 0;
|
| 878 |
+
}
|
| 879 |
+
|
| 880 |
+
// out_data = packed DWORD: _unknown_08 (u16) | fps (u16) << 16
|
| 881 |
+
*out_data = (s._unknown_08 as u32) | ((s.fps as u32) << 16);
|
| 882 |
+
|
| 883 |
+
// Width from max_frames, doubled-minus-one if flags bit 1 set
|
| 884 |
+
let mut width = s.max_frames as u32;
|
| 885 |
+
if s.flags & 2 != 0 {
|
| 886 |
+
width = width * 2 - 1;
|
| 887 |
+
}
|
| 888 |
+
*out_width = width;
|
| 889 |
+
|
| 890 |
+
*out_flags = (s.flags & 1) as u32;
|
| 891 |
+
|
| 892 |
+
crate::rebase::rb(SPRITE_STRING)
|
| 893 |
+
}
|
| 894 |
+
|
| 895 |
+
/// Extract sprite info from a SpriteBank — port of SpriteBank__GetInfo (0x4F98C0).
|
| 896 |
+
///
|
| 897 |
+
/// Usercall: EAX=layer, ECX=SpriteBank*, ESI=out_width, stack=out_data+out_flags.
|
| 898 |
+
/// Uses the bank's index table to map the layer ID to a frame entry, then
|
| 899 |
+
/// reads width/flags/data from the SpriteBankFrame.
|
| 900 |
+
unsafe fn sprite_info_from_bank(
|
| 901 |
+
bank: *const SpriteBank,
|
| 902 |
+
layer: i32,
|
| 903 |
+
out_data: *mut u32,
|
| 904 |
+
out_flags: *mut u32,
|
| 905 |
+
out_width: *mut u32,
|
| 906 |
+
) -> u32 {
|
| 907 |
+
let b = &*bank;
|
| 908 |
+
|
| 909 |
+
if b.frame_table.is_null() {
|
| 910 |
+
return 0;
|
| 911 |
+
}
|
| 912 |
+
|
| 913 |
+
let entry_idx = *b.index_table.offset((layer - b.base_id) as isize);
|
| 914 |
+
if entry_idx < 0 || entry_idx >= b.frame_count {
|
| 915 |
+
return 0;
|
| 916 |
+
}
|
| 917 |
+
|
| 918 |
+
let frame = &*b.frame_table.add(entry_idx as usize);
|
| 919 |
+
|
| 920 |
+
*out_data = (frame.data_value as u32) << 8;
|
| 921 |
+
*out_flags = (frame.flags & 1) as u32;
|
| 922 |
+
|
| 923 |
+
if frame.width & 0x8000 != 0 {
|
| 924 |
+
*out_width = 1;
|
| 925 |
+
} else if frame.flags & 2 != 0 {
|
| 926 |
+
*out_width = (frame.width as u32) * 2 - 1;
|
| 927 |
+
} else {
|
| 928 |
+
*out_width = frame.width as u32;
|
| 929 |
+
}
|
| 930 |
+
|
| 931 |
+
crate::rebase::rb(SPRITE_STRING)
|
| 932 |
+
}
|
| 933 |
+
|
| 934 |
/// Port of DisplayGfx::DrawViaCallback (vtable slot 21, 0x56B7C0).
|
| 935 |
///
|
| 936 |
/// Acquires the render lock, applies camera offset to fixed-point coordinates,
|
|
|
|
| 1137 |
}
|
| 1138 |
}
|
| 1139 |
|
| 1140 |
+
/// Port of DisplayGfx::SetLayerColor (vtable slot 4, 0x5231E0).
|
| 1141 |
+
///
|
| 1142 |
+
/// Allocates a `PaletteContext` for the given layer (1-3) if one doesn't exist.
|
| 1143 |
+
/// Finds `color` consecutive available entries in the slot table, claims them,
|
| 1144 |
+
/// and initializes a PaletteContext with that palette index range.
|
| 1145 |
+
///
|
| 1146 |
+
/// # Safety
|
| 1147 |
+
/// `this` must be a valid `*mut DisplayGfx`.
|
| 1148 |
+
pub unsafe extern "thiscall" fn set_layer_color(this: *mut DisplayGfx, layer: i32, color: i32) {
|
| 1149 |
+
// Layer must be 1, 2, or 3
|
| 1150 |
+
if (layer as u32).wrapping_sub(1) >= 3 {
|
| 1151 |
+
return;
|
| 1152 |
+
}
|
| 1153 |
+
|
| 1154 |
+
// Only allocate if no context exists for this layer
|
| 1155 |
+
if (*this).base.layer_contexts[layer as usize] != 0 {
|
| 1156 |
+
return;
|
| 1157 |
+
}
|
| 1158 |
+
|
| 1159 |
+
// Find `color` consecutive available (non-zero) entries in the slot table area.
|
| 1160 |
+
// The scan covers slot_table_guard (guard=0) + slot_table[0..255] + slot_table_sentinel (sentinel=-1).
|
| 1161 |
+
let start = palette_slot_alloc(&mut (*this).base, color);
|
| 1162 |
+
|
| 1163 |
+
// Allocate PaletteContext (0x72C total, zero first 0x70C)
|
| 1164 |
+
let ctx = crate::wa_alloc::wa_malloc(0x72C);
|
| 1165 |
+
core::ptr::write_bytes(ctx, 0, 0x70C);
|
| 1166 |
+
|
| 1167 |
+
let result = if ctx.is_null() {
|
| 1168 |
+
0u32
|
| 1169 |
+
} else {
|
| 1170 |
+
let ctx = ctx as *mut PaletteContext;
|
| 1171 |
+
palette_context_init(ctx, start as i16, (start as i32 + color - 1) as i16);
|
| 1172 |
+
ctx as u32
|
| 1173 |
+
};
|
| 1174 |
+
|
| 1175 |
+
(*this).base.layer_contexts[layer as usize] = result;
|
| 1176 |
+
(*this).base.layer_visibility[layer as usize] = 0;
|
| 1177 |
+
}
|
| 1178 |
+
|
| 1179 |
+
/// Palette slot allocator — port of FUN_00523190.
|
| 1180 |
+
///
|
| 1181 |
+
/// Scans the slot table area (this+0x312C) for `count` consecutive entries
|
| 1182 |
+
/// with value > 0 (available). Zeros the found entries to mark them as claimed.
|
| 1183 |
+
/// Returns the start index, or -1 if a negative sentinel is hit.
|
| 1184 |
+
///
|
| 1185 |
+
/// The scan area is: `slot_table_guard` (guard=0) + `slot_table[0..255]` + `slot_table_sentinel` (sentinel=-1).
|
| 1186 |
+
/// The guard at index 0 is always 0, so allocations start from index 1.
|
| 1187 |
+
/// The sentinel (-1) at index 256 terminates the scan with failure.
|
| 1188 |
+
unsafe fn palette_slot_alloc(base: &mut DisplayBase<*const DisplayVtable>, count: i32) -> i32 {
|
| 1189 |
+
let count = count as usize;
|
| 1190 |
+
let table = &base.slot_table_guard as *const u32;
|
| 1191 |
+
// Total entries: slot_table_guard(1) + slot_table(255) + slot_table_sentinel(1) = 257
|
| 1192 |
+
let total = 1 + 0xFF + 1;
|
| 1193 |
+
|
| 1194 |
+
let mut consecutive = 0usize;
|
| 1195 |
+
let mut scan = 0usize;
|
| 1196 |
+
|
| 1197 |
+
loop {
|
| 1198 |
+
if consecutive == count {
|
| 1199 |
+
let start = scan - count;
|
| 1200 |
+
for i in start..scan {
|
| 1201 |
+
*(table.add(i) as *mut u32) = 0;
|
| 1202 |
+
}
|
| 1203 |
+
return start as i32;
|
| 1204 |
+
}
|
| 1205 |
+
if scan >= total {
|
| 1206 |
+
return -1;
|
| 1207 |
+
}
|
| 1208 |
+
let val = *table.add(scan) as i32;
|
| 1209 |
+
scan += 1;
|
| 1210 |
+
if val == 0 {
|
| 1211 |
+
consecutive = 0;
|
| 1212 |
+
} else if val < 0 {
|
| 1213 |
+
return -1;
|
| 1214 |
+
} else {
|
| 1215 |
+
consecutive += 1;
|
| 1216 |
+
}
|
| 1217 |
+
}
|
| 1218 |
+
}
|
| 1219 |
+
|
| 1220 |
+
/// Initialize a PaletteContext with a palette index range — port of FUN_00541170 + FUN_005411a0.
|
| 1221 |
+
///
|
| 1222 |
+
/// Sets dirty_range_min/max, fills the free stack with descending indices,
|
| 1223 |
+
/// clears in_use flags and cache, then clears the dirty flag.
|
| 1224 |
+
unsafe fn palette_context_init(ctx: *mut PaletteContext, range_min: i16, range_max: i16) {
|
| 1225 |
+
(*ctx).dirty_range_min = range_min;
|
| 1226 |
+
(*ctx).dirty_range_max = range_max;
|
| 1227 |
+
|
| 1228 |
+
// PaletteContext__Init (0x5411A0)
|
| 1229 |
+
let range_size = range_max - range_min + 1;
|
| 1230 |
+
(*ctx).cache_count = 0;
|
| 1231 |
+
(*ctx).free_count = range_size;
|
| 1232 |
+
|
| 1233 |
+
// Fill free_stack with [range_max, range_max-1, ..., range_min]
|
| 1234 |
+
if range_size > 0 {
|
| 1235 |
+
for i in 0..range_size as usize {
|
| 1236 |
+
(*ctx).free_stack[i] = (range_max as u8).wrapping_sub(i as u8);
|
| 1237 |
+
}
|
| 1238 |
+
}
|
| 1239 |
+
|
| 1240 |
+
(*ctx).cache_iter = 0;
|
| 1241 |
+
core::ptr::write_bytes((*ctx).in_use.as_mut_ptr(), 0, 256);
|
| 1242 |
+
|
| 1243 |
+
// FUN_00541170 epilogue
|
| 1244 |
+
(*ctx).dirty = 0;
|
| 1245 |
+
}
|
| 1246 |
+
|
| 1247 |
/// Port of DisplayGfx::SetActiveLayer (vtable slot 5, 0x523270).
|
| 1248 |
///
|
| 1249 |
/// Returns the layer context pointer for `layer` (valid: 1, 2, 3), or null
|
|
@@ -4,6 +4,7 @@ pub mod palette;
|
|
| 4 |
pub mod queue;
|
| 5 |
pub mod spr;
|
| 6 |
pub mod sprite;
|
|
|
|
| 7 |
pub mod turn_order;
|
| 8 |
|
| 9 |
pub use landscape::{DirtyRect, PCLandscape};
|
|
|
|
| 4 |
pub mod queue;
|
| 5 |
pub mod spr;
|
| 6 |
pub mod sprite;
|
| 7 |
+
pub mod sprite_id;
|
| 8 |
pub mod turn_order;
|
| 9 |
|
| 10 |
pub use landscape::{DirtyRect, PCLandscape};
|
|
@@ -101,3 +101,14 @@ pub unsafe fn palette_map_color(ctx: *mut PaletteContext, rgb: u32) -> u32 {
|
|
| 101 |
|
| 102 |
slot_idx as u32
|
| 103 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 101 |
|
| 102 |
slot_idx as u32
|
| 103 |
}
|
| 104 |
+
|
| 105 |
+
crate::define_addresses! {
|
| 106 |
+
class "PaletteContext" {
|
| 107 |
+
/// PaletteContext__Init — usercall EAX=ctx* (no stack params)
|
| 108 |
+
fn/Usercall PALETTE_CONTEXT_INIT = 0x0054_11A0;
|
| 109 |
+
/// PaletteContext__InitRange — usercall ESI=ctx*, 2 stack params (range_min, range_max)
|
| 110 |
+
fn/Usercall PALETTE_CONTEXT_INIT_RANGE = 0x0054_1170;
|
| 111 |
+
/// PaletteContext__MapColor — thiscall(palette_ctx, rgb_u32), returns nearest palette index
|
| 112 |
+
fn/Thiscall PALETTE_CONTEXT_MAP_COLOR = 0x0054_12B0;
|
| 113 |
+
}
|
| 114 |
+
}
|
|
@@ -1,728 +1,7 @@
|
|
| 1 |
-
//
|
| 2 |
-
|
| 3 |
-
/// Names preserved from the original sprite file names in the game data.
|
| 4 |
-
/// The original names are terse 8-character identifiers from the game's
|
| 5 |
-
/// sprite sheets.
|
| 6 |
-
///
|
| 7 |
-
/// Source: wkJellyWorm Constants.h
|
| 8 |
-
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
| 9 |
-
#[repr(u32)]
|
| 10 |
-
pub enum SpriteId {
|
| 11 |
-
Cdrom = 1,
|
| 12 |
-
CrshairR = 2,
|
| 13 |
-
CrshairB = 3,
|
| 14 |
-
CrshairG = 4,
|
| 15 |
-
CrshairY = 5,
|
| 16 |
-
CrshairP = 6,
|
| 17 |
-
CrshairC = 7,
|
| 18 |
-
SpangleR = 8,
|
| 19 |
-
SpangleB = 9,
|
| 20 |
-
SpangleG = 10,
|
| 21 |
-
SpangleY = 11,
|
| 22 |
-
SpangleP = 12,
|
| 23 |
-
SpangleC = 13,
|
| 24 |
-
Grave1 = 14,
|
| 25 |
-
Grave2 = 15,
|
| 26 |
-
Grave3 = 16,
|
| 27 |
-
Grave4 = 17,
|
| 28 |
-
Grave5 = 18,
|
| 29 |
-
Grave6 = 19,
|
| 30 |
-
ArrowDnR = 20,
|
| 31 |
-
ArrowDnB = 21,
|
| 32 |
-
ArrowDnG = 22,
|
| 33 |
-
ArrowDnY = 23,
|
| 34 |
-
ArrowDnP = 24,
|
| 35 |
-
ArrowDnC = 25,
|
| 36 |
-
ArrowSdR = 26,
|
| 37 |
-
ArrowSdB = 27,
|
| 38 |
-
ArrowSdG = 28,
|
| 39 |
-
ArrowSdY = 29,
|
| 40 |
-
ArrowSdP = 30,
|
| 41 |
-
ArrowSdC = 31,
|
| 42 |
-
CursorR = 32,
|
| 43 |
-
CursorB = 33,
|
| 44 |
-
CursorG = 34,
|
| 45 |
-
CursorY = 35,
|
| 46 |
-
CursorP = 36,
|
| 47 |
-
CursorC = 37,
|
| 48 |
-
MarkerR = 38,
|
| 49 |
-
MarkerB = 39,
|
| 50 |
-
MarkerG = 40,
|
| 51 |
-
MarkerY = 41,
|
| 52 |
-
MarkerP = 42,
|
| 53 |
-
MarkerC = 43,
|
| 54 |
-
CMarker = 44,
|
| 55 |
-
MineOn = 45,
|
| 56 |
-
Arrow = 46,
|
| 57 |
-
MineOff = 47,
|
| 58 |
-
Missile = 48,
|
| 59 |
-
Bullet = 49,
|
| 60 |
-
Grenade = 50,
|
| 61 |
-
Banana = 51,
|
| 62 |
-
Mortar = 52,
|
| 63 |
-
Cluster = 53,
|
| 64 |
-
Clustlet = 54,
|
| 65 |
-
PetrolBm = 55,
|
| 66 |
-
HGrenade = 56,
|
| 67 |
-
Tamborin = 57,
|
| 68 |
-
HMissil1 = 58,
|
| 69 |
-
HMissil2 = 59,
|
| 70 |
-
AirMisl = 60,
|
| 71 |
-
SheepFal = 61,
|
| 72 |
-
Carpet1 = 62,
|
| 73 |
-
Carpet2 = 63,
|
| 74 |
-
SheepBrn = 64,
|
| 75 |
-
SheepLau = 65,
|
| 76 |
-
Meteor = 66,
|
| 77 |
-
Drill = 67,
|
| 78 |
-
RopeTip = 68,
|
| 79 |
-
RopeCuff = 69,
|
| 80 |
-
Phone = 70,
|
| 81 |
-
MbBomb = 71,
|
| 82 |
-
Letter1 = 72,
|
| 83 |
-
Letter2 = 73,
|
| 84 |
-
Vase = 74,
|
| 85 |
-
VaseBit1 = 75,
|
| 86 |
-
VaseBit2 = 76,
|
| 87 |
-
VaseBit3 = 77,
|
| 88 |
-
Dynamite = 78,
|
| 89 |
-
FireHit = 79,
|
| 90 |
-
KamiSmk = 80,
|
| 91 |
-
BaseHit = 81,
|
| 92 |
-
Donkey = 82,
|
| 93 |
-
Fireball = 83,
|
| 94 |
-
Flame1 = 84,
|
| 95 |
-
Flame2 = 85,
|
| 96 |
-
AirJetB = 86,
|
| 97 |
-
AirJetG = 87,
|
| 98 |
-
AirJetO = 88,
|
| 99 |
-
PostBox = 89,
|
| 100 |
-
ShpTruck = 90,
|
| 101 |
-
CptTruck = 91,
|
| 102 |
-
Targets = 92,
|
| 103 |
-
TargetsV = 93,
|
| 104 |
-
TargetW = 94,
|
| 105 |
-
TargetWV = 95,
|
| 106 |
-
WCrate1 = 96,
|
| 107 |
-
MCrate1 = 97,
|
| 108 |
-
UCrate1 = 98,
|
| 109 |
-
WCrate2 = 99,
|
| 110 |
-
MCrate2 = 100,
|
| 111 |
-
UCrate2 = 101,
|
| 112 |
-
Donor = 102,
|
| 113 |
-
WCrateV = 103,
|
| 114 |
-
MCrateV = 104,
|
| 115 |
-
UCrateV = 105,
|
| 116 |
-
Fallout = 106,
|
| 117 |
-
WCrate0 = 107,
|
| 118 |
-
MCrate0 = 108,
|
| 119 |
-
UCrate0 = 109,
|
| 120 |
-
OilDrum1 = 110,
|
| 121 |
-
OilDrum2 = 111,
|
| 122 |
-
OilDrum3 = 112,
|
| 123 |
-
OilDrum4 = 113,
|
| 124 |
-
UziHit = 114,
|
| 125 |
-
UziCase = 115,
|
| 126 |
-
ShotHit = 116,
|
| 127 |
-
ShotCase = 117,
|
| 128 |
-
WormHit1 = 118,
|
| 129 |
-
WormHit2 = 119,
|
| 130 |
-
Petrol1_ = 120,
|
| 131 |
-
Petrol2_ = 121,
|
| 132 |
-
Petrol3_ = 122,
|
| 133 |
-
Petrol4_ = 123,
|
| 134 |
-
Petrol1 = 124,
|
| 135 |
-
Petrol2 = 125,
|
| 136 |
-
Petrol3 = 126,
|
| 137 |
-
Petrol4 = 127,
|
| 138 |
-
Petrol5 = 128,
|
| 139 |
-
Petrol6 = 129,
|
| 140 |
-
Exhaust = 130,
|
| 141 |
-
HExhaust = 131,
|
| 142 |
-
WExhaust = 132,
|
| 143 |
-
QExhaust = 133,
|
| 144 |
-
Feather = 134,
|
| 145 |
-
MExhaust = 135,
|
| 146 |
-
TCloud = 136,
|
| 147 |
-
WWalk = 137,
|
| 148 |
-
WWalkU = 138,
|
| 149 |
-
WWalkD = 139,
|
| 150 |
-
WBlowW = 140,
|
| 151 |
-
WBlowWU = 141,
|
| 152 |
-
WBlowWD = 142,
|
| 153 |
-
WBlowA = 143,
|
| 154 |
-
WBlowAU = 144,
|
| 155 |
-
WBlowAD = 145,
|
| 156 |
-
WBungee = 146,
|
| 157 |
-
WBatRope = 147,
|
| 158 |
-
WRoll = 148,
|
| 159 |
-
WFly1 = 149,
|
| 160 |
-
WFly2 = 150,
|
| 161 |
-
WFly3 = 151,
|
| 162 |
-
LShpWlk = 152,
|
| 163 |
-
SheepWlk = 153,
|
| 164 |
-
SpSheep1 = 154,
|
| 165 |
-
SpSheep2 = 155,
|
| 166 |
-
AquaShp1 = 156,
|
| 167 |
-
AquaShp2 = 157,
|
| 168 |
-
MoleDive = 158,
|
| 169 |
-
MoleDig1 = 159,
|
| 170 |
-
MoleDig2 = 160,
|
| 171 |
-
MoleDig3 = 161,
|
| 172 |
-
Woman = 162,
|
| 173 |
-
Sally = 163,
|
| 174 |
-
CowWalk = 164,
|
| 175 |
-
CowJump = 165,
|
| 176 |
-
MoleWalk = 166,
|
| 177 |
-
WJetFly1 = 167,
|
| 178 |
-
WJetFly2 = 168,
|
| 179 |
-
WJetFly3 = 169,
|
| 180 |
-
WJetFly4 = 170,
|
| 181 |
-
WJetFlmB = 171,
|
| 182 |
-
WJetFlmD = 172,
|
| 183 |
-
Skunk1 = 173,
|
| 184 |
-
Skunk2 = 174,
|
| 185 |
-
PigeonR0 = 175,
|
| 186 |
-
PigeonR1 = 176,
|
| 187 |
-
PigeonR2 = 177,
|
| 188 |
-
PigeonR3 = 178,
|
| 189 |
-
WpBrth = 179,
|
| 190 |
-
WpBrthU = 180,
|
| 191 |
-
WpBrthD = 181,
|
| 192 |
-
WCough = 182,
|
| 193 |
-
WCoughU = 183,
|
| 194 |
-
WCoughD = 184,
|
| 195 |
-
WBrth1 = 185,
|
| 196 |
-
WBrth1U = 186,
|
| 197 |
-
WBrth1D = 187,
|
| 198 |
-
WBrth2 = 188,
|
| 199 |
-
WBrth2U = 189,
|
| 200 |
-
WBrth2D = 190,
|
| 201 |
-
WBlink1 = 191,
|
| 202 |
-
WBlink1U = 192,
|
| 203 |
-
WBlink1D = 193,
|
| 204 |
-
WBlink2 = 194,
|
| 205 |
-
WBlink2U = 195,
|
| 206 |
-
WBlink2D = 196,
|
| 207 |
-
WGlnce1 = 197,
|
| 208 |
-
WGlnce1U = 198,
|
| 209 |
-
WGlnce1D = 199,
|
| 210 |
-
WGlnce2 = 200,
|
| 211 |
-
WGlnce2U = 201,
|
| 212 |
-
WGlnce2D = 202,
|
| 213 |
-
WBgHead = 203,
|
| 214 |
-
WBgHeadU = 204,
|
| 215 |
-
WBgHeadD = 205,
|
| 216 |
-
WFist = 206,
|
| 217 |
-
WFistU = 207,
|
| 218 |
-
WFistD = 208,
|
| 219 |
-
WPeek = 209,
|
| 220 |
-
WPeekU = 210,
|
| 221 |
-
WPeekD = 211,
|
| 222 |
-
WULook = 212,
|
| 223 |
-
WULookU = 213,
|
| 224 |
-
WULookD = 214,
|
| 225 |
-
WOLook = 215,
|
| 226 |
-
WOLookU = 216,
|
| 227 |
-
WOLookD = 217,
|
| 228 |
-
WScarey = 218,
|
| 229 |
-
WScareyU = 219,
|
| 230 |
-
WScareyD = 220,
|
| 231 |
-
WKami1 = 221,
|
| 232 |
-
WKami2 = 222,
|
| 233 |
-
WKami3 = 223,
|
| 234 |
-
WKami4 = 224,
|
| 235 |
-
WKami5 = 225,
|
| 236 |
-
WScrtch = 226,
|
| 237 |
-
WScrtchU = 227,
|
| 238 |
-
WScrtchD = 228,
|
| 239 |
-
WAccuse = 229,
|
| 240 |
-
WAccuseU = 230,
|
| 241 |
-
WAccuseD = 231,
|
| 242 |
-
WTache = 232,
|
| 243 |
-
WTacheU = 233,
|
| 244 |
-
WTacheD = 234,
|
| 245 |
-
WMunch = 235,
|
| 246 |
-
WMunchU = 236,
|
| 247 |
-
WMunchD = 237,
|
| 248 |
-
WLazy = 238,
|
| 249 |
-
WLazyU = 239,
|
| 250 |
-
WLazyD = 240,
|
| 251 |
-
WWinner = 241,
|
| 252 |
-
WSurndr = 242,
|
| 253 |
-
WSurndrU = 243,
|
| 254 |
-
WSurndrD = 244,
|
| 255 |
-
WSvR = 245,
|
| 256 |
-
WSvRU = 246,
|
| 257 |
-
WSvRD = 247,
|
| 258 |
-
WSvB = 248,
|
| 259 |
-
WSvBU = 249,
|
| 260 |
-
WSvBD = 250,
|
| 261 |
-
WSvG = 251,
|
| 262 |
-
WSvGU = 252,
|
| 263 |
-
WSvGD = 253,
|
| 264 |
-
WSvY = 254,
|
| 265 |
-
WSvYU = 255,
|
| 266 |
-
WSvYD = 256,
|
| 267 |
-
WSvP = 257,
|
| 268 |
-
WSvPU = 258,
|
| 269 |
-
WSvPD = 259,
|
| 270 |
-
WSvC = 260,
|
| 271 |
-
WSvCU = 261,
|
| 272 |
-
WSvCD = 262,
|
| 273 |
-
WSkipGo = 263,
|
| 274 |
-
WSkipGoU = 264,
|
| 275 |
-
WSkipGoD = 265,
|
| 276 |
-
WSelect = 266,
|
| 277 |
-
WSelectU = 267,
|
| 278 |
-
WSelectD = 268,
|
| 279 |
-
WJump = 269,
|
| 280 |
-
WJumpU = 270,
|
| 281 |
-
WJumpD = 271,
|
| 282 |
-
WLand1 = 272,
|
| 283 |
-
WLand1U = 273,
|
| 284 |
-
WLand1D = 274,
|
| 285 |
-
WLand2 = 275,
|
| 286 |
-
WLand2U = 276,
|
| 287 |
-
WLand2D = 277,
|
| 288 |
-
WFlyLnk = 278,
|
| 289 |
-
WBackFlp = 279,
|
| 290 |
-
WPncLnk = 280,
|
| 291 |
-
WPncLnkU = 281,
|
| 292 |
-
WPncLnkD = 282,
|
| 293 |
-
WPncTop = 283,
|
| 294 |
-
WPncBak = 284,
|
| 295 |
-
WPncBakU = 285,
|
| 296 |
-
WPncBakD = 286,
|
| 297 |
-
WParaLnk = 287,
|
| 298 |
-
WParaCht = 288,
|
| 299 |
-
WParBak = 289,
|
| 300 |
-
WParBakU = 290,
|
| 301 |
-
WParBakD = 291,
|
| 302 |
-
WTwang = 292,
|
| 303 |
-
WTwangU = 293,
|
| 304 |
-
WTwangD = 294,
|
| 305 |
-
WSldLk1 = 295,
|
| 306 |
-
WSldLk1U = 296,
|
| 307 |
-
WSldLk1D = 297,
|
| 308 |
-
WSldLk2 = 298,
|
| 309 |
-
WSldLk2U = 299,
|
| 310 |
-
WSldLk2D = 300,
|
| 311 |
-
WpBrtLk = 301,
|
| 312 |
-
WpBrtLkU = 302,
|
| 313 |
-
WpBrtLkD = 303,
|
| 314 |
-
WBlowLk = 304,
|
| 315 |
-
WBlowLkU = 305,
|
| 316 |
-
WBlowLkD = 306,
|
| 317 |
-
WHatLnk = 307,
|
| 318 |
-
WHatLnkU = 308,
|
| 319 |
-
WHatLnkD = 309,
|
| 320 |
-
WNukeLk = 310,
|
| 321 |
-
WNukeLkU = 311,
|
| 322 |
-
WNukeLkD = 312,
|
| 323 |
-
WGrnLnk = 313,
|
| 324 |
-
WGrnLnkU = 314,
|
| 325 |
-
WGrnLnkD = 315,
|
| 326 |
-
WClsLnk = 316,
|
| 327 |
-
WClsLnkU = 317,
|
| 328 |
-
WClsLnkD = 318,
|
| 329 |
-
WBanLnk = 319,
|
| 330 |
-
WBanLnkU = 320,
|
| 331 |
-
WBanLnkD = 321,
|
| 332 |
-
WPbmLnk = 322,
|
| 333 |
-
WPbmLnkU = 323,
|
| 334 |
-
WPbmLnkD = 324,
|
| 335 |
-
WHgrLnk = 325,
|
| 336 |
-
WHgrLnkU = 326,
|
| 337 |
-
WHgrLnkD = 327,
|
| 338 |
-
WUtlLnk = 328,
|
| 339 |
-
WUtlLnkU = 329,
|
| 340 |
-
WUtlLnkD = 330,
|
| 341 |
-
WJetLnk = 331,
|
| 342 |
-
WJetLnkU = 332,
|
| 343 |
-
WJetLnkD = 333,
|
| 344 |
-
WDynLnk = 334,
|
| 345 |
-
WDynLnkU = 335,
|
| 346 |
-
WDynLnkD = 336,
|
| 347 |
-
WVasLnk = 337,
|
| 348 |
-
WVasLnkU = 338,
|
| 349 |
-
WVasLnkD = 339,
|
| 350 |
-
WCowLnk = 340,
|
| 351 |
-
WCowLnkU = 341,
|
| 352 |
-
WCowLnkD = 342,
|
| 353 |
-
WShpLnk = 343,
|
| 354 |
-
WShpLnkU = 344,
|
| 355 |
-
WShpLnkD = 345,
|
| 356 |
-
WWmnLnk = 346,
|
| 357 |
-
WWmnLnkU = 347,
|
| 358 |
-
WWmnLnkD = 348,
|
| 359 |
-
WSknLnk = 349,
|
| 360 |
-
WSknLnkU = 350,
|
| 361 |
-
WSknLnkD = 351,
|
| 362 |
-
WMolLnk = 352,
|
| 363 |
-
WMolLnkU = 353,
|
| 364 |
-
WMolLnkD = 354,
|
| 365 |
-
WWmn2Lk = 355,
|
| 366 |
-
WWmn2LkU = 356,
|
| 367 |
-
WWmn2LkD = 357,
|
| 368 |
-
WDrlLnk = 358,
|
| 369 |
-
WDrlLnkU = 359,
|
| 370 |
-
WDrlLnkD = 360,
|
| 371 |
-
WDrill = 361,
|
| 372 |
-
WPrdLnk = 362,
|
| 373 |
-
WPrdLnkU = 363,
|
| 374 |
-
WPrdLnkD = 364,
|
| 375 |
-
WProd = 365,
|
| 376 |
-
WProdU = 366,
|
| 377 |
-
WProdD = 367,
|
| 378 |
-
WPrdBk2 = 368,
|
| 379 |
-
WPrdBk2U = 369,
|
| 380 |
-
WPrdBk2D = 370,
|
| 381 |
-
WKamLnk = 371,
|
| 382 |
-
WKamLnkU = 372,
|
| 383 |
-
WKamLnkD = 373,
|
| 384 |
-
WKamJmp = 374,
|
| 385 |
-
WKamBmr = 375,
|
| 386 |
-
WKamBmrU = 376,
|
| 387 |
-
WKamBmrD = 377,
|
| 388 |
-
WFirBl1 = 378,
|
| 389 |
-
WFirBl1U = 379,
|
| 390 |
-
WFirBl1D = 380,
|
| 391 |
-
WFirBl2 = 381,
|
| 392 |
-
WFirBl2U = 382,
|
| 393 |
-
WFirBl2D = 383,
|
| 394 |
-
WFirAir = 384,
|
| 395 |
-
WJapBak = 385,
|
| 396 |
-
WJapBakU = 386,
|
| 397 |
-
WJapBakD = 387,
|
| 398 |
-
WMinLnk = 388,
|
| 399 |
-
WMinLnkU = 389,
|
| 400 |
-
WMinLnkD = 390,
|
| 401 |
-
WSkpLnk = 391,
|
| 402 |
-
WSkpLnkU = 392,
|
| 403 |
-
WSkpLnkD = 393,
|
| 404 |
-
WSelLnk = 394,
|
| 405 |
-
WSelLnkU = 395,
|
| 406 |
-
WSelLnkD = 396,
|
| 407 |
-
WAxeLnk = 397,
|
| 408 |
-
WAxeLnkU = 398,
|
| 409 |
-
WAxeLnkD = 399,
|
| 410 |
-
WAxeLk2 = 400,
|
| 411 |
-
WAxeLk2U = 401,
|
| 412 |
-
WAxeLk2D = 402,
|
| 413 |
-
WAxeSwn = 403,
|
| 414 |
-
WAxeSwnU = 404,
|
| 415 |
-
WAxeSwnD = 405,
|
| 416 |
-
WAxeBak = 406,
|
| 417 |
-
WAxeBakU = 407,
|
| 418 |
-
WAxeBakD = 408,
|
| 419 |
-
WBndLnk = 409,
|
| 420 |
-
WBndLnkU = 410,
|
| 421 |
-
WBndLnkD = 411,
|
| 422 |
-
WAirLnk = 412,
|
| 423 |
-
WAirLnkU = 413,
|
| 424 |
-
WAirLnkD = 414,
|
| 425 |
-
WAirTlk = 415,
|
| 426 |
-
WAirTlkU = 416,
|
| 427 |
-
WAirTlkD = 417,
|
| 428 |
-
WTelLnk = 418,
|
| 429 |
-
WTelLnkU = 419,
|
| 430 |
-
WTelLnkD = 420,
|
| 431 |
-
WTelTlk = 421,
|
| 432 |
-
WTelTlkU = 422,
|
| 433 |
-
WTelTlkD = 423,
|
| 434 |
-
WTelDsv = 424,
|
| 435 |
-
WTelDsvU = 425,
|
| 436 |
-
WTelDsvD = 426,
|
| 437 |
-
WThrBak = 427,
|
| 438 |
-
WThrBakU = 428,
|
| 439 |
-
WThrBakD = 429,
|
| 440 |
-
WBsbLnk = 430,
|
| 441 |
-
WBsbLnkU = 431,
|
| 442 |
-
WBsbLnkD = 432,
|
| 443 |
-
WBsbBk2 = 433,
|
| 444 |
-
WBsbBk2U = 434,
|
| 445 |
-
WBsbBk2D = 435,
|
| 446 |
-
WBazLnk = 436,
|
| 447 |
-
WBazLnkU = 437,
|
| 448 |
-
WBazLnkD = 438,
|
| 449 |
-
WFlmLnk = 439,
|
| 450 |
-
WFlmLnkU = 440,
|
| 451 |
-
WFlmLnkD = 441,
|
| 452 |
-
WBz2Lnk = 442,
|
| 453 |
-
WBz2LnkU = 443,
|
| 454 |
-
WBz2LnkD = 444,
|
| 455 |
-
WBz3Lnk = 445,
|
| 456 |
-
WBz3LnkU = 446,
|
| 457 |
-
WBz3LnkD = 447,
|
| 458 |
-
WSurLnk = 448,
|
| 459 |
-
WSurLnkU = 449,
|
| 460 |
-
WSurLnkD = 450,
|
| 461 |
-
WSvrLnk = 451,
|
| 462 |
-
WSvrLnkU = 452,
|
| 463 |
-
WSvrLnkD = 453,
|
| 464 |
-
WSvbLnk = 454,
|
| 465 |
-
WSvbLnkU = 455,
|
| 466 |
-
WSvbLnkD = 456,
|
| 467 |
-
WSvgLnk = 457,
|
| 468 |
-
WSvgLnkU = 458,
|
| 469 |
-
WSvgLnkD = 459,
|
| 470 |
-
WSvyLnk = 460,
|
| 471 |
-
WSvyLnkU = 461,
|
| 472 |
-
WSvyLnkD = 462,
|
| 473 |
-
WSvpLnk = 463,
|
| 474 |
-
WSvpLnkU = 464,
|
| 475 |
-
WSvpLnkD = 465,
|
| 476 |
-
WSvcLnk = 466,
|
| 477 |
-
WSvcLnkU = 467,
|
| 478 |
-
WSvcLnkD = 468,
|
| 479 |
-
WIceLnk = 469,
|
| 480 |
-
WIceLnkU = 470,
|
| 481 |
-
WIceLnkD = 471,
|
| 482 |
-
WIceLk2 = 472,
|
| 483 |
-
WIceLk2U = 473,
|
| 484 |
-
WIceLk2D = 474,
|
| 485 |
-
WIceLk3 = 475,
|
| 486 |
-
WIceLk3U = 476,
|
| 487 |
-
WIceLk3D = 477,
|
| 488 |
-
WIceLook = 478,
|
| 489 |
-
WIceBlnk = 479,
|
| 490 |
-
WIceGlnt = 480,
|
| 491 |
-
WIceStnd = 481,
|
| 492 |
-
WBatLnk = 482,
|
| 493 |
-
WBatLnkU = 483,
|
| 494 |
-
WBatLnkD = 484,
|
| 495 |
-
WBatBk2 = 485,
|
| 496 |
-
WBatBk2U = 486,
|
| 497 |
-
WBatBk2D = 487,
|
| 498 |
-
WUziLnk = 488,
|
| 499 |
-
WUziLnkU = 489,
|
| 500 |
-
WUziLnkD = 490,
|
| 501 |
-
WShgLnk = 491,
|
| 502 |
-
WShgLnkU = 492,
|
| 503 |
-
WShgLnkD = 493,
|
| 504 |
-
WBowLnk = 494,
|
| 505 |
-
WBowLnkU = 495,
|
| 506 |
-
WBowLnkD = 496,
|
| 507 |
-
WBowBk2 = 497,
|
| 508 |
-
WBowBk2U = 498,
|
| 509 |
-
WBowBk2D = 499,
|
| 510 |
-
WHgnLnk = 500,
|
| 511 |
-
WHgnLnkU = 501,
|
| 512 |
-
WHgnLnkD = 502,
|
| 513 |
-
WMgnLnk = 503,
|
| 514 |
-
WMgnLnkU = 504,
|
| 515 |
-
WMgnLnkD = 505,
|
| 516 |
-
WDie = 506,
|
| 517 |
-
SkdSmoke = 507,
|
| 518 |
-
WFlyUp = 508,
|
| 519 |
-
WFlyDn = 509,
|
| 520 |
-
WFall = 510,
|
| 521 |
-
WFallDn = 511,
|
| 522 |
-
WPncUp = 512,
|
| 523 |
-
WSlide = 513,
|
| 524 |
-
WSlideU = 514,
|
| 525 |
-
WSlideD = 515,
|
| 526 |
-
WBow = 516,
|
| 527 |
-
WBowU = 517,
|
| 528 |
-
WBowD = 518,
|
| 529 |
-
WBsbAim = 519,
|
| 530 |
-
WBsbAimU = 520,
|
| 531 |
-
WBsbAimD = 521,
|
| 532 |
-
WBsbSwn = 522,
|
| 533 |
-
WBsbSwnU = 523,
|
| 534 |
-
WBsbSwnD = 524,
|
| 535 |
-
WBaz = 525,
|
| 536 |
-
WBazU = 526,
|
| 537 |
-
WBazD = 527,
|
| 538 |
-
WFlm = 528,
|
| 539 |
-
WFlmU = 529,
|
| 540 |
-
WFlmD = 530,
|
| 541 |
-
WBaz2 = 531,
|
| 542 |
-
WBaz2U = 532,
|
| 543 |
-
WBaz2D = 533,
|
| 544 |
-
WBaz3 = 534,
|
| 545 |
-
WBaz3U = 535,
|
| 546 |
-
WBaz3D = 536,
|
| 547 |
-
WBatAim = 537,
|
| 548 |
-
WBatAimU = 538,
|
| 549 |
-
WBatAimD = 539,
|
| 550 |
-
WBatFrd = 540,
|
| 551 |
-
WBatFrdU = 541,
|
| 552 |
-
WBatFrdD = 542,
|
| 553 |
-
WShotG = 543,
|
| 554 |
-
WShotGU = 544,
|
| 555 |
-
WShotGD = 545,
|
| 556 |
-
WShotP = 546,
|
| 557 |
-
WShotPU = 547,
|
| 558 |
-
WShotPD = 548,
|
| 559 |
-
WShotF = 549,
|
| 560 |
-
WShotFU = 550,
|
| 561 |
-
WShotFD = 551,
|
| 562 |
-
WBowP = 552,
|
| 563 |
-
WBowPU = 553,
|
| 564 |
-
WBowPD = 554,
|
| 565 |
-
WBowF = 555,
|
| 566 |
-
WBowFU = 556,
|
| 567 |
-
WBowFD = 557,
|
| 568 |
-
WHandG = 558,
|
| 569 |
-
WHandGU = 559,
|
| 570 |
-
WHandGD = 560,
|
| 571 |
-
WHandF = 561,
|
| 572 |
-
WHandFU = 562,
|
| 573 |
-
WHandFD = 563,
|
| 574 |
-
WUzi = 564,
|
| 575 |
-
WUziU = 565,
|
| 576 |
-
WUziD = 566,
|
| 577 |
-
WUziF = 567,
|
| 578 |
-
WUziFU = 568,
|
| 579 |
-
WUziFD = 569,
|
| 580 |
-
WMini = 570,
|
| 581 |
-
WMiniU = 571,
|
| 582 |
-
WMiniD = 572,
|
| 583 |
-
WMiniF = 573,
|
| 584 |
-
WMiniFU = 574,
|
| 585 |
-
WMiniFD = 575,
|
| 586 |
-
WThrGrn = 576,
|
| 587 |
-
WThrGrnU = 577,
|
| 588 |
-
WThrGrnD = 578,
|
| 589 |
-
WThrCls = 579,
|
| 590 |
-
WThrClsU = 580,
|
| 591 |
-
WThrClsD = 581,
|
| 592 |
-
WThrBan = 582,
|
| 593 |
-
WThrBanU = 583,
|
| 594 |
-
WThrBanD = 584,
|
| 595 |
-
WThrPbm = 585,
|
| 596 |
-
WThrPbmU = 586,
|
| 597 |
-
WThrPbmD = 587,
|
| 598 |
-
WThrHgr = 588,
|
| 599 |
-
WThrHgrU = 589,
|
| 600 |
-
WThrHgrD = 590,
|
| 601 |
-
WThrow = 591,
|
| 602 |
-
WThrowU = 592,
|
| 603 |
-
WThrowD = 593,
|
| 604 |
-
Replay = 594,
|
| 605 |
-
NetBreak = 595,
|
| 606 |
-
ExFoom = 596,
|
| 607 |
-
ExBiff = 597,
|
| 608 |
-
ExPoot = 598,
|
| 609 |
-
ExPow = 599,
|
| 610 |
-
Circle25 = 600,
|
| 611 |
-
Circle50 = 601,
|
| 612 |
-
Circle75 = 602,
|
| 613 |
-
Circl100 = 603,
|
| 614 |
-
Elipse25 = 604,
|
| 615 |
-
Elipse50 = 605,
|
| 616 |
-
Elipse75 = 606,
|
| 617 |
-
Elips100 = 607,
|
| 618 |
-
GassGrn = 608,
|
| 619 |
-
SmkLt25 = 609,
|
| 620 |
-
SmkLt50 = 610,
|
| 621 |
-
SmkLt75 = 611,
|
| 622 |
-
SmkLt100 = 612,
|
| 623 |
-
SmkDrk20 = 613,
|
| 624 |
-
SmkDrk30 = 614,
|
| 625 |
-
SmkDrk40 = 615,
|
| 626 |
-
Clouds = 616,
|
| 627 |
-
CloudM = 617,
|
| 628 |
-
CloudL = 618,
|
| 629 |
-
Blob = 619,
|
| 630 |
-
// gap: 620-621 unused
|
| 631 |
-
Debris = 622,
|
| 632 |
-
Bubble1 = 623,
|
| 633 |
-
Bubble2 = 624,
|
| 634 |
-
Bubble3 = 625,
|
| 635 |
-
Bubble4 = 626,
|
| 636 |
-
WfDrown = 627,
|
| 637 |
-
Grave1V2 = 628,
|
| 638 |
-
Grave2V2 = 629,
|
| 639 |
-
Grave3V2 = 630,
|
| 640 |
-
Grave4V2 = 631,
|
| 641 |
-
Grave5V2 = 632,
|
| 642 |
-
Grave6V2 = 633,
|
| 643 |
-
TargetsV2 = 634,
|
| 644 |
-
TargetWV2 = 635,
|
| 645 |
-
WCrate1V2 = 636,
|
| 646 |
-
MCrate1V2 = 637,
|
| 647 |
-
UCrate1V2 = 638,
|
| 648 |
-
DonorV2 = 639,
|
| 649 |
-
WDrown = 640,
|
| 650 |
-
OilDrum = 641,
|
| 651 |
-
MeteorV2 = 642,
|
| 652 |
-
MineOnV2 = 643,
|
| 653 |
-
MineOffV2 = 644,
|
| 654 |
-
MissileV2 = 645,
|
| 655 |
-
AirMislV2 = 646,
|
| 656 |
-
GrenadeV2 = 647,
|
| 657 |
-
MortarV2 = 648,
|
| 658 |
-
ClusterV2 = 649,
|
| 659 |
-
ClustletV2 = 650,
|
| 660 |
-
BulletV2 = 651,
|
| 661 |
-
ArrowV2 = 652,
|
| 662 |
-
Sheep = 653,
|
| 663 |
-
Carpet1V2 = 654,
|
| 664 |
-
Carpet2V2 = 655,
|
| 665 |
-
SheepFalV2 = 656,
|
| 666 |
-
SheepBrnV2 = 657,
|
| 667 |
-
MbBombV2 = 658,
|
| 668 |
-
DrillV2 = 659,
|
| 669 |
-
WomanV2 = 660,
|
| 670 |
-
SallyV2 = 661,
|
| 671 |
-
SkunkV2 = 662,
|
| 672 |
-
Mole = 663,
|
| 673 |
-
CowWalkV2 = 664,
|
| 674 |
-
PigeonR0V2 = 665,
|
| 675 |
-
PigeonR1V2 = 666,
|
| 676 |
-
PigeonR2V2 = 667,
|
| 677 |
-
PigeonR3V2 = 668,
|
| 678 |
-
BananaV2 = 669,
|
| 679 |
-
PetrolBmV2 = 670,
|
| 680 |
-
TamborinV2 = 671,
|
| 681 |
-
HGrenadeV2 = 672,
|
| 682 |
-
HMissil1V2 = 673,
|
| 683 |
-
HMissil2V2 = 674,
|
| 684 |
-
AquaShp1V2 = 675,
|
| 685 |
-
AquaShp2V2 = 676,
|
| 686 |
-
VaseV2 = 677,
|
| 687 |
-
VaseBit1V2 = 678,
|
| 688 |
-
VaseBit2V2 = 679,
|
| 689 |
-
VaseBit3V2 = 680,
|
| 690 |
-
DynamiteV2 = 681,
|
| 691 |
-
Letter1V2 = 682,
|
| 692 |
-
Letter2V2 = 683,
|
| 693 |
-
DonkeyV2 = 684,
|
| 694 |
-
WBaz4 = 685,
|
| 695 |
-
WBaz4U = 686,
|
| 696 |
-
WBaz4D = 687,
|
| 697 |
-
WBaz5 = 688,
|
| 698 |
-
WBaz5U = 689,
|
| 699 |
-
WBaz5D = 690,
|
| 700 |
-
WBz4Lnk = 691,
|
| 701 |
-
WBz4LnkU = 692,
|
| 702 |
-
WBz4LnkD = 693,
|
| 703 |
-
WBz5Lnk = 694,
|
| 704 |
-
WBz5LnkU = 695,
|
| 705 |
-
WBz5LnkD = 696,
|
| 706 |
-
}
|
| 707 |
-
|
| 708 |
-
impl TryFrom<u32> for SpriteId {
|
| 709 |
-
type Error = u32;
|
| 710 |
-
|
| 711 |
-
fn try_from(value: u32) -> Result<Self, Self::Error> {
|
| 712 |
-
match value {
|
| 713 |
-
1..=619 | 622..=696 => {
|
| 714 |
-
// SAFETY: all matched values correspond to valid variants
|
| 715 |
-
Ok(unsafe { core::mem::transmute(value) })
|
| 716 |
-
}
|
| 717 |
-
_ => Err(value),
|
| 718 |
-
}
|
| 719 |
-
}
|
| 720 |
-
}
|
| 721 |
-
|
| 722 |
-
// ---------------------------------------------------------------------------
|
| 723 |
-
// Sprite struct layout (from Ghidra + wkJellyWorm Sprites.h)
|
| 724 |
-
// ---------------------------------------------------------------------------
|
| 725 |
|
|
|
|
| 726 |
/// Per-frame metadata within a Sprite (0x0C bytes).
|
| 727 |
///
|
| 728 |
/// Describes the bounding box and bitmap data offset for one animation frame.
|
|
@@ -752,13 +31,13 @@ const _: () = assert!(core::mem::size_of::<SpriteFrame>() == 0x0C);
|
|
| 752 |
/// (0x4FAA30), populated by ProcessSprite (0x4FAB80) from `.spr` file data.
|
| 753 |
///
|
| 754 |
/// Contains frame metadata, palette data, and bitmap pixel data for all frames.
|
| 755 |
-
/// Managed by
|
| 756 |
///
|
| 757 |
/// Source: wkJellyWorm `Sprites.h`, Ghidra decompilation of ConstructSprite + ProcessSprite.
|
| 758 |
#[repr(C)]
|
| 759 |
pub struct Sprite {
|
| 760 |
-
/// 0x00: Vtable pointer (0x66418C, 8
|
| 761 |
-
pub vtable: *
|
| 762 |
/// 0x04: Context/parent pointer (ECX from ConstructSprite)
|
| 763 |
pub context_ptr: *mut u8,
|
| 764 |
/// 0x08: Unknown
|
|
@@ -812,37 +91,110 @@ pub struct Sprite {
|
|
| 812 |
|
| 813 |
const _: () = assert!(core::mem::size_of::<Sprite>() == 0x70);
|
| 814 |
|
| 815 |
-
///
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 816 |
///
|
| 817 |
-
///
|
| 818 |
-
///
|
| 819 |
-
|
| 820 |
-
|
| 821 |
-
|
| 822 |
-
|
| 823 |
-
|
| 824 |
-
///
|
| 825 |
-
pub
|
| 826 |
-
///
|
| 827 |
-
pub
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 828 |
}
|
| 829 |
|
| 830 |
-
|
| 831 |
-
|
| 832 |
-
|
| 833 |
-
|
| 834 |
-
|
| 835 |
-
|
| 836 |
-
|
| 837 |
-
|
| 838 |
-
|
| 839 |
-
|
| 840 |
-
|
| 841 |
-
|
| 842 |
-
///
|
| 843 |
-
pub
|
| 844 |
-
///
|
| 845 |
-
pub
|
| 846 |
-
///
|
| 847 |
-
pub
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 848 |
}
|
|
|
|
| 1 |
+
// Re-export SpriteId from its own module to keep this file focused on struct layouts.
|
| 2 |
+
pub use super::sprite_id::SpriteId;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3 |
|
| 4 |
+
// (SpriteId enum moved to sprite_id.rs)
|
| 5 |
/// Per-frame metadata within a Sprite (0x0C bytes).
|
| 6 |
///
|
| 7 |
/// Describes the bounding box and bitmap data offset for one animation frame.
|
|
|
|
| 31 |
/// (0x4FAA30), populated by ProcessSprite (0x4FAB80) from `.spr` file data.
|
| 32 |
///
|
| 33 |
/// Contains frame metadata, palette data, and bitmap pixel data for all frames.
|
| 34 |
+
/// Managed by DisplayBase's 1024-slot sprite table (`sprite_ptrs`).
|
| 35 |
///
|
| 36 |
/// Source: wkJellyWorm `Sprites.h`, Ghidra decompilation of ConstructSprite + ProcessSprite.
|
| 37 |
#[repr(C)]
|
| 38 |
pub struct Sprite {
|
| 39 |
+
/// 0x00: Vtable pointer (0x66418C, 8 slots)
|
| 40 |
+
pub vtable: *const SpriteVtable,
|
| 41 |
/// 0x04: Context/parent pointer (ECX from ConstructSprite)
|
| 42 |
pub context_ptr: *mut u8,
|
| 43 |
/// 0x08: Unknown
|
|
|
|
| 91 |
|
| 92 |
const _: () = assert!(core::mem::size_of::<Sprite>() == 0x70);
|
| 93 |
|
| 94 |
+
/// SpriteBank — indexed sprite container (0x17C bytes).
|
| 95 |
+
///
|
| 96 |
+
/// Alternative to Sprite for storing sprite data in DisplayBase's 1024-slot table.
|
| 97 |
+
/// While Sprite (sprite_ptrs, 0x1008) stores individual sprites loaded from `.spr` files,
|
| 98 |
+
/// SpriteBank (sprite_banks, 0x2008) stores collections of sprite frames accessed via
|
| 99 |
+
/// an index table that maps sprite IDs to frame indices.
|
| 100 |
///
|
| 101 |
+
/// Created by LoadSpriteEx (0x523310): allocated 0x17C bytes, first 0x15C zeroed,
|
| 102 |
+
/// then constructed and initialized via FUN_004f95a0.
|
| 103 |
+
///
|
| 104 |
+
/// Used by GetSpriteInfo (0x523500) and LoadSpriteComplex (0x5237C0) as the
|
| 105 |
+
/// fallback path when sprite_ptrs[id] is null.
|
| 106 |
+
#[repr(C)]
|
| 107 |
+
pub struct SpriteBank {
|
| 108 |
+
/// 0x00: Vtable pointer (0x664180, 3 slots)
|
| 109 |
+
pub vtable: *const SpriteBankVtable,
|
| 110 |
+
/// 0x04: Unknown (context pointer?)
|
| 111 |
+
pub _unknown_04: u32,
|
| 112 |
+
/// 0x08: Base sprite ID — subtracted from the lookup ID to compute the index table offset.
|
| 113 |
+
pub base_id: i32,
|
| 114 |
+
/// 0x0C: Index table pointer — maps `(id - base_id)` to frame indices in the frame table.
|
| 115 |
+
pub index_table: *const i32,
|
| 116 |
+
/// 0x10: Frame table pointer — array of SpriteFrame entries (0xC bytes each).
|
| 117 |
+
pub frame_table: *const SpriteBankFrame,
|
| 118 |
+
/// 0x14: Number of valid entries in the frame table (bounds check for lookups).
|
| 119 |
+
pub frame_count: i32,
|
| 120 |
+
/// 0x18 - 0x17B: Remaining fields (unknown)
|
| 121 |
+
pub _unknown_18: [u8; 0x17C - 0x18],
|
| 122 |
}
|
| 123 |
|
| 124 |
+
const _: () = assert!(core::mem::size_of::<SpriteBank>() == 0x17C);
|
| 125 |
+
|
| 126 |
+
/// Frame entry in a SpriteBank's frame table (0xC bytes).
|
| 127 |
+
///
|
| 128 |
+
/// Structurally identical to SpriteFrame but fields have different semantics
|
| 129 |
+
/// when accessed by SpriteBank__GetInfo (FUN_004f98c0):
|
| 130 |
+
/// - `flags` byte 0: bit 0 = transparency flag, bit 1 = double-width flag
|
| 131 |
+
/// - `width` at +0x08: frame width (bit 15 = single-width override)
|
| 132 |
+
/// - `data_value` at +0x0A: data reference (shifted left 8 for output)
|
| 133 |
+
#[repr(C)]
|
| 134 |
+
#[derive(Clone, Copy, Debug)]
|
| 135 |
+
pub struct SpriteBankFrame {
|
| 136 |
+
/// 0x00: Flags byte. Bit 0 = has transparency, bit 1 = double-width.
|
| 137 |
+
pub flags: u8,
|
| 138 |
+
/// 0x01-0x07: Padding / other fields
|
| 139 |
+
pub _pad_01: [u8; 7],
|
| 140 |
+
/// 0x08: Frame width in pixels. Bit 15 set = force width to 1.
|
| 141 |
+
pub width: u16,
|
| 142 |
+
/// 0x0A: Data reference value (shifted left 8 when returned by GetSpriteInfo).
|
| 143 |
+
pub data_value: u16,
|
| 144 |
+
}
|
| 145 |
+
|
| 146 |
+
const _: () = assert!(core::mem::size_of::<SpriteBankFrame>() == 0x0C);
|
| 147 |
+
|
| 148 |
+
/// Sprite vtable (0x66418C, 8 slots).
|
| 149 |
+
///
|
| 150 |
+
/// Slots 6-7 are CTask common stubs (0x5613D0).
|
| 151 |
+
#[openwa_core::vtable(size = 8, va = 0x0066_418C, class = "Sprite")]
|
| 152 |
+
pub struct SpriteVtable {
|
| 153 |
+
/// destructor (0x4FAA80)
|
| 154 |
+
pub destructor: fn(this: *mut Sprite, flags: u32),
|
| 155 |
+
/// unknown (0x4FAAD0)
|
| 156 |
+
pub slot_1: fn(this: *mut Sprite),
|
| 157 |
+
/// unknown (0x4FB5C0)
|
| 158 |
+
pub slot_2: fn(this: *mut Sprite),
|
| 159 |
+
/// unknown (0x4FE550)
|
| 160 |
+
pub slot_3: fn(this: *mut Sprite),
|
| 161 |
+
/// unknown (0x4FE2F0)
|
| 162 |
+
pub slot_4: fn(this: *mut Sprite),
|
| 163 |
+
/// unknown (0x4FE9C0)
|
| 164 |
+
pub slot_5: fn(this: *mut Sprite),
|
| 165 |
+
/// CTask common stub (0x5613D0)
|
| 166 |
+
pub slot_6: fn(this: *mut Sprite),
|
| 167 |
+
/// CTask common stub (0x5613D0)
|
| 168 |
+
pub slot_7: fn(this: *mut Sprite),
|
| 169 |
+
}
|
| 170 |
+
|
| 171 |
+
/// SpriteBank vtable (0x664180, 3 slots).
|
| 172 |
+
#[openwa_core::vtable(size = 3, va = 0x0066_4180, class = "SpriteBank")]
|
| 173 |
+
pub struct SpriteBankVtable {
|
| 174 |
+
/// destructor (0x4F94E0)
|
| 175 |
+
pub destructor: fn(this: *mut SpriteBank, flags: u32),
|
| 176 |
+
/// init/load (0x4F9580)
|
| 177 |
+
pub slot_1: fn(this: *mut SpriteBank),
|
| 178 |
+
/// unknown (0x4FA910)
|
| 179 |
+
pub slot_2: fn(this: *mut SpriteBank),
|
| 180 |
+
}
|
| 181 |
+
|
| 182 |
+
crate::define_addresses! {
|
| 183 |
+
class "Sprite" {
|
| 184 |
+
/// ConstructSprite — usercall EAX=sprite_ptr, ECX=context_ptr
|
| 185 |
+
ctor/Usercall CONSTRUCT_SPRITE = 0x004F_AA30;
|
| 186 |
+
/// Sprite destructor — thiscall, vtable slot 0
|
| 187 |
+
fn/Thiscall DESTROY_SPRITE = 0x004F_AA80;
|
| 188 |
+
/// LoadSpriteFromVfs
|
| 189 |
+
fn/Usercall LOAD_SPRITE_FROM_VFS = 0x004F_AAF0;
|
| 190 |
+
/// ProcessSprite — parses .spr binary format
|
| 191 |
+
fn/Usercall PROCESS_SPRITE = 0x004F_AB80;
|
| 192 |
+
/// Sprite__GetInfo — usercall EAX=Sprite*, ESI=out_data, ECX=out_width, stack=out_flags
|
| 193 |
+
fn/Usercall SPRITE_GET_INFO = 0x004F_AEC0;
|
| 194 |
+
}
|
| 195 |
+
|
| 196 |
+
class "SpriteBank" {
|
| 197 |
+
/// SpriteBank__GetInfo — usercall EAX=layer, ECX=bank*, ESI=out_width, 2 stack params
|
| 198 |
+
fn/Usercall SPRITE_BANK_GET_INFO = 0x004F_98C0;
|
| 199 |
+
}
|
| 200 |
}
|
|
@@ -0,0 +1,720 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/// Sprite/animation frame IDs. Range 1-696 with gaps at 620-621.
|
| 2 |
+
///
|
| 3 |
+
/// Names preserved from the original sprite file names in the game data.
|
| 4 |
+
/// The original names are terse 8-character identifiers from the game's
|
| 5 |
+
/// sprite sheets.
|
| 6 |
+
///
|
| 7 |
+
/// Source: wkJellyWorm Constants.h
|
| 8 |
+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
| 9 |
+
#[repr(u32)]
|
| 10 |
+
pub enum SpriteId {
|
| 11 |
+
Cdrom = 1,
|
| 12 |
+
CrshairR = 2,
|
| 13 |
+
CrshairB = 3,
|
| 14 |
+
CrshairG = 4,
|
| 15 |
+
CrshairY = 5,
|
| 16 |
+
CrshairP = 6,
|
| 17 |
+
CrshairC = 7,
|
| 18 |
+
SpangleR = 8,
|
| 19 |
+
SpangleB = 9,
|
| 20 |
+
SpangleG = 10,
|
| 21 |
+
SpangleY = 11,
|
| 22 |
+
SpangleP = 12,
|
| 23 |
+
SpangleC = 13,
|
| 24 |
+
Grave1 = 14,
|
| 25 |
+
Grave2 = 15,
|
| 26 |
+
Grave3 = 16,
|
| 27 |
+
Grave4 = 17,
|
| 28 |
+
Grave5 = 18,
|
| 29 |
+
Grave6 = 19,
|
| 30 |
+
ArrowDnR = 20,
|
| 31 |
+
ArrowDnB = 21,
|
| 32 |
+
ArrowDnG = 22,
|
| 33 |
+
ArrowDnY = 23,
|
| 34 |
+
ArrowDnP = 24,
|
| 35 |
+
ArrowDnC = 25,
|
| 36 |
+
ArrowSdR = 26,
|
| 37 |
+
ArrowSdB = 27,
|
| 38 |
+
ArrowSdG = 28,
|
| 39 |
+
ArrowSdY = 29,
|
| 40 |
+
ArrowSdP = 30,
|
| 41 |
+
ArrowSdC = 31,
|
| 42 |
+
CursorR = 32,
|
| 43 |
+
CursorB = 33,
|
| 44 |
+
CursorG = 34,
|
| 45 |
+
CursorY = 35,
|
| 46 |
+
CursorP = 36,
|
| 47 |
+
CursorC = 37,
|
| 48 |
+
MarkerR = 38,
|
| 49 |
+
MarkerB = 39,
|
| 50 |
+
MarkerG = 40,
|
| 51 |
+
MarkerY = 41,
|
| 52 |
+
MarkerP = 42,
|
| 53 |
+
MarkerC = 43,
|
| 54 |
+
CMarker = 44,
|
| 55 |
+
MineOn = 45,
|
| 56 |
+
Arrow = 46,
|
| 57 |
+
MineOff = 47,
|
| 58 |
+
Missile = 48,
|
| 59 |
+
Bullet = 49,
|
| 60 |
+
Grenade = 50,
|
| 61 |
+
Banana = 51,
|
| 62 |
+
Mortar = 52,
|
| 63 |
+
Cluster = 53,
|
| 64 |
+
Clustlet = 54,
|
| 65 |
+
PetrolBm = 55,
|
| 66 |
+
HGrenade = 56,
|
| 67 |
+
Tamborin = 57,
|
| 68 |
+
HMissil1 = 58,
|
| 69 |
+
HMissil2 = 59,
|
| 70 |
+
AirMisl = 60,
|
| 71 |
+
SheepFal = 61,
|
| 72 |
+
Carpet1 = 62,
|
| 73 |
+
Carpet2 = 63,
|
| 74 |
+
SheepBrn = 64,
|
| 75 |
+
SheepLau = 65,
|
| 76 |
+
Meteor = 66,
|
| 77 |
+
Drill = 67,
|
| 78 |
+
RopeTip = 68,
|
| 79 |
+
RopeCuff = 69,
|
| 80 |
+
Phone = 70,
|
| 81 |
+
MbBomb = 71,
|
| 82 |
+
Letter1 = 72,
|
| 83 |
+
Letter2 = 73,
|
| 84 |
+
Vase = 74,
|
| 85 |
+
VaseBit1 = 75,
|
| 86 |
+
VaseBit2 = 76,
|
| 87 |
+
VaseBit3 = 77,
|
| 88 |
+
Dynamite = 78,
|
| 89 |
+
FireHit = 79,
|
| 90 |
+
KamiSmk = 80,
|
| 91 |
+
BaseHit = 81,
|
| 92 |
+
Donkey = 82,
|
| 93 |
+
Fireball = 83,
|
| 94 |
+
Flame1 = 84,
|
| 95 |
+
Flame2 = 85,
|
| 96 |
+
AirJetB = 86,
|
| 97 |
+
AirJetG = 87,
|
| 98 |
+
AirJetO = 88,
|
| 99 |
+
PostBox = 89,
|
| 100 |
+
ShpTruck = 90,
|
| 101 |
+
CptTruck = 91,
|
| 102 |
+
Targets = 92,
|
| 103 |
+
TargetsV = 93,
|
| 104 |
+
TargetW = 94,
|
| 105 |
+
TargetWV = 95,
|
| 106 |
+
WCrate1 = 96,
|
| 107 |
+
MCrate1 = 97,
|
| 108 |
+
UCrate1 = 98,
|
| 109 |
+
WCrate2 = 99,
|
| 110 |
+
MCrate2 = 100,
|
| 111 |
+
UCrate2 = 101,
|
| 112 |
+
Donor = 102,
|
| 113 |
+
WCrateV = 103,
|
| 114 |
+
MCrateV = 104,
|
| 115 |
+
UCrateV = 105,
|
| 116 |
+
Fallout = 106,
|
| 117 |
+
WCrate0 = 107,
|
| 118 |
+
MCrate0 = 108,
|
| 119 |
+
UCrate0 = 109,
|
| 120 |
+
OilDrum1 = 110,
|
| 121 |
+
OilDrum2 = 111,
|
| 122 |
+
OilDrum3 = 112,
|
| 123 |
+
OilDrum4 = 113,
|
| 124 |
+
UziHit = 114,
|
| 125 |
+
UziCase = 115,
|
| 126 |
+
ShotHit = 116,
|
| 127 |
+
ShotCase = 117,
|
| 128 |
+
WormHit1 = 118,
|
| 129 |
+
WormHit2 = 119,
|
| 130 |
+
Petrol1_ = 120,
|
| 131 |
+
Petrol2_ = 121,
|
| 132 |
+
Petrol3_ = 122,
|
| 133 |
+
Petrol4_ = 123,
|
| 134 |
+
Petrol1 = 124,
|
| 135 |
+
Petrol2 = 125,
|
| 136 |
+
Petrol3 = 126,
|
| 137 |
+
Petrol4 = 127,
|
| 138 |
+
Petrol5 = 128,
|
| 139 |
+
Petrol6 = 129,
|
| 140 |
+
Exhaust = 130,
|
| 141 |
+
HExhaust = 131,
|
| 142 |
+
WExhaust = 132,
|
| 143 |
+
QExhaust = 133,
|
| 144 |
+
Feather = 134,
|
| 145 |
+
MExhaust = 135,
|
| 146 |
+
TCloud = 136,
|
| 147 |
+
WWalk = 137,
|
| 148 |
+
WWalkU = 138,
|
| 149 |
+
WWalkD = 139,
|
| 150 |
+
WBlowW = 140,
|
| 151 |
+
WBlowWU = 141,
|
| 152 |
+
WBlowWD = 142,
|
| 153 |
+
WBlowA = 143,
|
| 154 |
+
WBlowAU = 144,
|
| 155 |
+
WBlowAD = 145,
|
| 156 |
+
WBungee = 146,
|
| 157 |
+
WBatRope = 147,
|
| 158 |
+
WRoll = 148,
|
| 159 |
+
WFly1 = 149,
|
| 160 |
+
WFly2 = 150,
|
| 161 |
+
WFly3 = 151,
|
| 162 |
+
LShpWlk = 152,
|
| 163 |
+
SheepWlk = 153,
|
| 164 |
+
SpSheep1 = 154,
|
| 165 |
+
SpSheep2 = 155,
|
| 166 |
+
AquaShp1 = 156,
|
| 167 |
+
AquaShp2 = 157,
|
| 168 |
+
MoleDive = 158,
|
| 169 |
+
MoleDig1 = 159,
|
| 170 |
+
MoleDig2 = 160,
|
| 171 |
+
MoleDig3 = 161,
|
| 172 |
+
Woman = 162,
|
| 173 |
+
Sally = 163,
|
| 174 |
+
CowWalk = 164,
|
| 175 |
+
CowJump = 165,
|
| 176 |
+
MoleWalk = 166,
|
| 177 |
+
WJetFly1 = 167,
|
| 178 |
+
WJetFly2 = 168,
|
| 179 |
+
WJetFly3 = 169,
|
| 180 |
+
WJetFly4 = 170,
|
| 181 |
+
WJetFlmB = 171,
|
| 182 |
+
WJetFlmD = 172,
|
| 183 |
+
Skunk1 = 173,
|
| 184 |
+
Skunk2 = 174,
|
| 185 |
+
PigeonR0 = 175,
|
| 186 |
+
PigeonR1 = 176,
|
| 187 |
+
PigeonR2 = 177,
|
| 188 |
+
PigeonR3 = 178,
|
| 189 |
+
WpBrth = 179,
|
| 190 |
+
WpBrthU = 180,
|
| 191 |
+
WpBrthD = 181,
|
| 192 |
+
WCough = 182,
|
| 193 |
+
WCoughU = 183,
|
| 194 |
+
WCoughD = 184,
|
| 195 |
+
WBrth1 = 185,
|
| 196 |
+
WBrth1U = 186,
|
| 197 |
+
WBrth1D = 187,
|
| 198 |
+
WBrth2 = 188,
|
| 199 |
+
WBrth2U = 189,
|
| 200 |
+
WBrth2D = 190,
|
| 201 |
+
WBlink1 = 191,
|
| 202 |
+
WBlink1U = 192,
|
| 203 |
+
WBlink1D = 193,
|
| 204 |
+
WBlink2 = 194,
|
| 205 |
+
WBlink2U = 195,
|
| 206 |
+
WBlink2D = 196,
|
| 207 |
+
WGlnce1 = 197,
|
| 208 |
+
WGlnce1U = 198,
|
| 209 |
+
WGlnce1D = 199,
|
| 210 |
+
WGlnce2 = 200,
|
| 211 |
+
WGlnce2U = 201,
|
| 212 |
+
WGlnce2D = 202,
|
| 213 |
+
WBgHead = 203,
|
| 214 |
+
WBgHeadU = 204,
|
| 215 |
+
WBgHeadD = 205,
|
| 216 |
+
WFist = 206,
|
| 217 |
+
WFistU = 207,
|
| 218 |
+
WFistD = 208,
|
| 219 |
+
WPeek = 209,
|
| 220 |
+
WPeekU = 210,
|
| 221 |
+
WPeekD = 211,
|
| 222 |
+
WULook = 212,
|
| 223 |
+
WULookU = 213,
|
| 224 |
+
WULookD = 214,
|
| 225 |
+
WOLook = 215,
|
| 226 |
+
WOLookU = 216,
|
| 227 |
+
WOLookD = 217,
|
| 228 |
+
WScarey = 218,
|
| 229 |
+
WScareyU = 219,
|
| 230 |
+
WScareyD = 220,
|
| 231 |
+
WKami1 = 221,
|
| 232 |
+
WKami2 = 222,
|
| 233 |
+
WKami3 = 223,
|
| 234 |
+
WKami4 = 224,
|
| 235 |
+
WKami5 = 225,
|
| 236 |
+
WScrtch = 226,
|
| 237 |
+
WScrtchU = 227,
|
| 238 |
+
WScrtchD = 228,
|
| 239 |
+
WAccuse = 229,
|
| 240 |
+
WAccuseU = 230,
|
| 241 |
+
WAccuseD = 231,
|
| 242 |
+
WTache = 232,
|
| 243 |
+
WTacheU = 233,
|
| 244 |
+
WTacheD = 234,
|
| 245 |
+
WMunch = 235,
|
| 246 |
+
WMunchU = 236,
|
| 247 |
+
WMunchD = 237,
|
| 248 |
+
WLazy = 238,
|
| 249 |
+
WLazyU = 239,
|
| 250 |
+
WLazyD = 240,
|
| 251 |
+
WWinner = 241,
|
| 252 |
+
WSurndr = 242,
|
| 253 |
+
WSurndrU = 243,
|
| 254 |
+
WSurndrD = 244,
|
| 255 |
+
WSvR = 245,
|
| 256 |
+
WSvRU = 246,
|
| 257 |
+
WSvRD = 247,
|
| 258 |
+
WSvB = 248,
|
| 259 |
+
WSvBU = 249,
|
| 260 |
+
WSvBD = 250,
|
| 261 |
+
WSvG = 251,
|
| 262 |
+
WSvGU = 252,
|
| 263 |
+
WSvGD = 253,
|
| 264 |
+
WSvY = 254,
|
| 265 |
+
WSvYU = 255,
|
| 266 |
+
WSvYD = 256,
|
| 267 |
+
WSvP = 257,
|
| 268 |
+
WSvPU = 258,
|
| 269 |
+
WSvPD = 259,
|
| 270 |
+
WSvC = 260,
|
| 271 |
+
WSvCU = 261,
|
| 272 |
+
WSvCD = 262,
|
| 273 |
+
WSkipGo = 263,
|
| 274 |
+
WSkipGoU = 264,
|
| 275 |
+
WSkipGoD = 265,
|
| 276 |
+
WSelect = 266,
|
| 277 |
+
WSelectU = 267,
|
| 278 |
+
WSelectD = 268,
|
| 279 |
+
WJump = 269,
|
| 280 |
+
WJumpU = 270,
|
| 281 |
+
WJumpD = 271,
|
| 282 |
+
WLand1 = 272,
|
| 283 |
+
WLand1U = 273,
|
| 284 |
+
WLand1D = 274,
|
| 285 |
+
WLand2 = 275,
|
| 286 |
+
WLand2U = 276,
|
| 287 |
+
WLand2D = 277,
|
| 288 |
+
WFlyLnk = 278,
|
| 289 |
+
WBackFlp = 279,
|
| 290 |
+
WPncLnk = 280,
|
| 291 |
+
WPncLnkU = 281,
|
| 292 |
+
WPncLnkD = 282,
|
| 293 |
+
WPncTop = 283,
|
| 294 |
+
WPncBak = 284,
|
| 295 |
+
WPncBakU = 285,
|
| 296 |
+
WPncBakD = 286,
|
| 297 |
+
WParaLnk = 287,
|
| 298 |
+
WParaCht = 288,
|
| 299 |
+
WParBak = 289,
|
| 300 |
+
WParBakU = 290,
|
| 301 |
+
WParBakD = 291,
|
| 302 |
+
WTwang = 292,
|
| 303 |
+
WTwangU = 293,
|
| 304 |
+
WTwangD = 294,
|
| 305 |
+
WSldLk1 = 295,
|
| 306 |
+
WSldLk1U = 296,
|
| 307 |
+
WSldLk1D = 297,
|
| 308 |
+
WSldLk2 = 298,
|
| 309 |
+
WSldLk2U = 299,
|
| 310 |
+
WSldLk2D = 300,
|
| 311 |
+
WpBrtLk = 301,
|
| 312 |
+
WpBrtLkU = 302,
|
| 313 |
+
WpBrtLkD = 303,
|
| 314 |
+
WBlowLk = 304,
|
| 315 |
+
WBlowLkU = 305,
|
| 316 |
+
WBlowLkD = 306,
|
| 317 |
+
WHatLnk = 307,
|
| 318 |
+
WHatLnkU = 308,
|
| 319 |
+
WHatLnkD = 309,
|
| 320 |
+
WNukeLk = 310,
|
| 321 |
+
WNukeLkU = 311,
|
| 322 |
+
WNukeLkD = 312,
|
| 323 |
+
WGrnLnk = 313,
|
| 324 |
+
WGrnLnkU = 314,
|
| 325 |
+
WGrnLnkD = 315,
|
| 326 |
+
WClsLnk = 316,
|
| 327 |
+
WClsLnkU = 317,
|
| 328 |
+
WClsLnkD = 318,
|
| 329 |
+
WBanLnk = 319,
|
| 330 |
+
WBanLnkU = 320,
|
| 331 |
+
WBanLnkD = 321,
|
| 332 |
+
WPbmLnk = 322,
|
| 333 |
+
WPbmLnkU = 323,
|
| 334 |
+
WPbmLnkD = 324,
|
| 335 |
+
WHgrLnk = 325,
|
| 336 |
+
WHgrLnkU = 326,
|
| 337 |
+
WHgrLnkD = 327,
|
| 338 |
+
WUtlLnk = 328,
|
| 339 |
+
WUtlLnkU = 329,
|
| 340 |
+
WUtlLnkD = 330,
|
| 341 |
+
WJetLnk = 331,
|
| 342 |
+
WJetLnkU = 332,
|
| 343 |
+
WJetLnkD = 333,
|
| 344 |
+
WDynLnk = 334,
|
| 345 |
+
WDynLnkU = 335,
|
| 346 |
+
WDynLnkD = 336,
|
| 347 |
+
WVasLnk = 337,
|
| 348 |
+
WVasLnkU = 338,
|
| 349 |
+
WVasLnkD = 339,
|
| 350 |
+
WCowLnk = 340,
|
| 351 |
+
WCowLnkU = 341,
|
| 352 |
+
WCowLnkD = 342,
|
| 353 |
+
WShpLnk = 343,
|
| 354 |
+
WShpLnkU = 344,
|
| 355 |
+
WShpLnkD = 345,
|
| 356 |
+
WWmnLnk = 346,
|
| 357 |
+
WWmnLnkU = 347,
|
| 358 |
+
WWmnLnkD = 348,
|
| 359 |
+
WSknLnk = 349,
|
| 360 |
+
WSknLnkU = 350,
|
| 361 |
+
WSknLnkD = 351,
|
| 362 |
+
WMolLnk = 352,
|
| 363 |
+
WMolLnkU = 353,
|
| 364 |
+
WMolLnkD = 354,
|
| 365 |
+
WWmn2Lk = 355,
|
| 366 |
+
WWmn2LkU = 356,
|
| 367 |
+
WWmn2LkD = 357,
|
| 368 |
+
WDrlLnk = 358,
|
| 369 |
+
WDrlLnkU = 359,
|
| 370 |
+
WDrlLnkD = 360,
|
| 371 |
+
WDrill = 361,
|
| 372 |
+
WPrdLnk = 362,
|
| 373 |
+
WPrdLnkU = 363,
|
| 374 |
+
WPrdLnkD = 364,
|
| 375 |
+
WProd = 365,
|
| 376 |
+
WProdU = 366,
|
| 377 |
+
WProdD = 367,
|
| 378 |
+
WPrdBk2 = 368,
|
| 379 |
+
WPrdBk2U = 369,
|
| 380 |
+
WPrdBk2D = 370,
|
| 381 |
+
WKamLnk = 371,
|
| 382 |
+
WKamLnkU = 372,
|
| 383 |
+
WKamLnkD = 373,
|
| 384 |
+
WKamJmp = 374,
|
| 385 |
+
WKamBmr = 375,
|
| 386 |
+
WKamBmrU = 376,
|
| 387 |
+
WKamBmrD = 377,
|
| 388 |
+
WFirBl1 = 378,
|
| 389 |
+
WFirBl1U = 379,
|
| 390 |
+
WFirBl1D = 380,
|
| 391 |
+
WFirBl2 = 381,
|
| 392 |
+
WFirBl2U = 382,
|
| 393 |
+
WFirBl2D = 383,
|
| 394 |
+
WFirAir = 384,
|
| 395 |
+
WJapBak = 385,
|
| 396 |
+
WJapBakU = 386,
|
| 397 |
+
WJapBakD = 387,
|
| 398 |
+
WMinLnk = 388,
|
| 399 |
+
WMinLnkU = 389,
|
| 400 |
+
WMinLnkD = 390,
|
| 401 |
+
WSkpLnk = 391,
|
| 402 |
+
WSkpLnkU = 392,
|
| 403 |
+
WSkpLnkD = 393,
|
| 404 |
+
WSelLnk = 394,
|
| 405 |
+
WSelLnkU = 395,
|
| 406 |
+
WSelLnkD = 396,
|
| 407 |
+
WAxeLnk = 397,
|
| 408 |
+
WAxeLnkU = 398,
|
| 409 |
+
WAxeLnkD = 399,
|
| 410 |
+
WAxeLk2 = 400,
|
| 411 |
+
WAxeLk2U = 401,
|
| 412 |
+
WAxeLk2D = 402,
|
| 413 |
+
WAxeSwn = 403,
|
| 414 |
+
WAxeSwnU = 404,
|
| 415 |
+
WAxeSwnD = 405,
|
| 416 |
+
WAxeBak = 406,
|
| 417 |
+
WAxeBakU = 407,
|
| 418 |
+
WAxeBakD = 408,
|
| 419 |
+
WBndLnk = 409,
|
| 420 |
+
WBndLnkU = 410,
|
| 421 |
+
WBndLnkD = 411,
|
| 422 |
+
WAirLnk = 412,
|
| 423 |
+
WAirLnkU = 413,
|
| 424 |
+
WAirLnkD = 414,
|
| 425 |
+
WAirTlk = 415,
|
| 426 |
+
WAirTlkU = 416,
|
| 427 |
+
WAirTlkD = 417,
|
| 428 |
+
WTelLnk = 418,
|
| 429 |
+
WTelLnkU = 419,
|
| 430 |
+
WTelLnkD = 420,
|
| 431 |
+
WTelTlk = 421,
|
| 432 |
+
WTelTlkU = 422,
|
| 433 |
+
WTelTlkD = 423,
|
| 434 |
+
WTelDsv = 424,
|
| 435 |
+
WTelDsvU = 425,
|
| 436 |
+
WTelDsvD = 426,
|
| 437 |
+
WThrBak = 427,
|
| 438 |
+
WThrBakU = 428,
|
| 439 |
+
WThrBakD = 429,
|
| 440 |
+
WBsbLnk = 430,
|
| 441 |
+
WBsbLnkU = 431,
|
| 442 |
+
WBsbLnkD = 432,
|
| 443 |
+
WBsbBk2 = 433,
|
| 444 |
+
WBsbBk2U = 434,
|
| 445 |
+
WBsbBk2D = 435,
|
| 446 |
+
WBazLnk = 436,
|
| 447 |
+
WBazLnkU = 437,
|
| 448 |
+
WBazLnkD = 438,
|
| 449 |
+
WFlmLnk = 439,
|
| 450 |
+
WFlmLnkU = 440,
|
| 451 |
+
WFlmLnkD = 441,
|
| 452 |
+
WBz2Lnk = 442,
|
| 453 |
+
WBz2LnkU = 443,
|
| 454 |
+
WBz2LnkD = 444,
|
| 455 |
+
WBz3Lnk = 445,
|
| 456 |
+
WBz3LnkU = 446,
|
| 457 |
+
WBz3LnkD = 447,
|
| 458 |
+
WSurLnk = 448,
|
| 459 |
+
WSurLnkU = 449,
|
| 460 |
+
WSurLnkD = 450,
|
| 461 |
+
WSvrLnk = 451,
|
| 462 |
+
WSvrLnkU = 452,
|
| 463 |
+
WSvrLnkD = 453,
|
| 464 |
+
WSvbLnk = 454,
|
| 465 |
+
WSvbLnkU = 455,
|
| 466 |
+
WSvbLnkD = 456,
|
| 467 |
+
WSvgLnk = 457,
|
| 468 |
+
WSvgLnkU = 458,
|
| 469 |
+
WSvgLnkD = 459,
|
| 470 |
+
WSvyLnk = 460,
|
| 471 |
+
WSvyLnkU = 461,
|
| 472 |
+
WSvyLnkD = 462,
|
| 473 |
+
WSvpLnk = 463,
|
| 474 |
+
WSvpLnkU = 464,
|
| 475 |
+
WSvpLnkD = 465,
|
| 476 |
+
WSvcLnk = 466,
|
| 477 |
+
WSvcLnkU = 467,
|
| 478 |
+
WSvcLnkD = 468,
|
| 479 |
+
WIceLnk = 469,
|
| 480 |
+
WIceLnkU = 470,
|
| 481 |
+
WIceLnkD = 471,
|
| 482 |
+
WIceLk2 = 472,
|
| 483 |
+
WIceLk2U = 473,
|
| 484 |
+
WIceLk2D = 474,
|
| 485 |
+
WIceLk3 = 475,
|
| 486 |
+
WIceLk3U = 476,
|
| 487 |
+
WIceLk3D = 477,
|
| 488 |
+
WIceLook = 478,
|
| 489 |
+
WIceBlnk = 479,
|
| 490 |
+
WIceGlnt = 480,
|
| 491 |
+
WIceStnd = 481,
|
| 492 |
+
WBatLnk = 482,
|
| 493 |
+
WBatLnkU = 483,
|
| 494 |
+
WBatLnkD = 484,
|
| 495 |
+
WBatBk2 = 485,
|
| 496 |
+
WBatBk2U = 486,
|
| 497 |
+
WBatBk2D = 487,
|
| 498 |
+
WUziLnk = 488,
|
| 499 |
+
WUziLnkU = 489,
|
| 500 |
+
WUziLnkD = 490,
|
| 501 |
+
WShgLnk = 491,
|
| 502 |
+
WShgLnkU = 492,
|
| 503 |
+
WShgLnkD = 493,
|
| 504 |
+
WBowLnk = 494,
|
| 505 |
+
WBowLnkU = 495,
|
| 506 |
+
WBowLnkD = 496,
|
| 507 |
+
WBowBk2 = 497,
|
| 508 |
+
WBowBk2U = 498,
|
| 509 |
+
WBowBk2D = 499,
|
| 510 |
+
WHgnLnk = 500,
|
| 511 |
+
WHgnLnkU = 501,
|
| 512 |
+
WHgnLnkD = 502,
|
| 513 |
+
WMgnLnk = 503,
|
| 514 |
+
WMgnLnkU = 504,
|
| 515 |
+
WMgnLnkD = 505,
|
| 516 |
+
WDie = 506,
|
| 517 |
+
SkdSmoke = 507,
|
| 518 |
+
WFlyUp = 508,
|
| 519 |
+
WFlyDn = 509,
|
| 520 |
+
WFall = 510,
|
| 521 |
+
WFallDn = 511,
|
| 522 |
+
WPncUp = 512,
|
| 523 |
+
WSlide = 513,
|
| 524 |
+
WSlideU = 514,
|
| 525 |
+
WSlideD = 515,
|
| 526 |
+
WBow = 516,
|
| 527 |
+
WBowU = 517,
|
| 528 |
+
WBowD = 518,
|
| 529 |
+
WBsbAim = 519,
|
| 530 |
+
WBsbAimU = 520,
|
| 531 |
+
WBsbAimD = 521,
|
| 532 |
+
WBsbSwn = 522,
|
| 533 |
+
WBsbSwnU = 523,
|
| 534 |
+
WBsbSwnD = 524,
|
| 535 |
+
WBaz = 525,
|
| 536 |
+
WBazU = 526,
|
| 537 |
+
WBazD = 527,
|
| 538 |
+
WFlm = 528,
|
| 539 |
+
WFlmU = 529,
|
| 540 |
+
WFlmD = 530,
|
| 541 |
+
WBaz2 = 531,
|
| 542 |
+
WBaz2U = 532,
|
| 543 |
+
WBaz2D = 533,
|
| 544 |
+
WBaz3 = 534,
|
| 545 |
+
WBaz3U = 535,
|
| 546 |
+
WBaz3D = 536,
|
| 547 |
+
WBatAim = 537,
|
| 548 |
+
WBatAimU = 538,
|
| 549 |
+
WBatAimD = 539,
|
| 550 |
+
WBatFrd = 540,
|
| 551 |
+
WBatFrdU = 541,
|
| 552 |
+
WBatFrdD = 542,
|
| 553 |
+
WShotG = 543,
|
| 554 |
+
WShotGU = 544,
|
| 555 |
+
WShotGD = 545,
|
| 556 |
+
WShotP = 546,
|
| 557 |
+
WShotPU = 547,
|
| 558 |
+
WShotPD = 548,
|
| 559 |
+
WShotF = 549,
|
| 560 |
+
WShotFU = 550,
|
| 561 |
+
WShotFD = 551,
|
| 562 |
+
WBowP = 552,
|
| 563 |
+
WBowPU = 553,
|
| 564 |
+
WBowPD = 554,
|
| 565 |
+
WBowF = 555,
|
| 566 |
+
WBowFU = 556,
|
| 567 |
+
WBowFD = 557,
|
| 568 |
+
WHandG = 558,
|
| 569 |
+
WHandGU = 559,
|
| 570 |
+
WHandGD = 560,
|
| 571 |
+
WHandF = 561,
|
| 572 |
+
WHandFU = 562,
|
| 573 |
+
WHandFD = 563,
|
| 574 |
+
WUzi = 564,
|
| 575 |
+
WUziU = 565,
|
| 576 |
+
WUziD = 566,
|
| 577 |
+
WUziF = 567,
|
| 578 |
+
WUziFU = 568,
|
| 579 |
+
WUziFD = 569,
|
| 580 |
+
WMini = 570,
|
| 581 |
+
WMiniU = 571,
|
| 582 |
+
WMiniD = 572,
|
| 583 |
+
WMiniF = 573,
|
| 584 |
+
WMiniFU = 574,
|
| 585 |
+
WMiniFD = 575,
|
| 586 |
+
WThrGrn = 576,
|
| 587 |
+
WThrGrnU = 577,
|
| 588 |
+
WThrGrnD = 578,
|
| 589 |
+
WThrCls = 579,
|
| 590 |
+
WThrClsU = 580,
|
| 591 |
+
WThrClsD = 581,
|
| 592 |
+
WThrBan = 582,
|
| 593 |
+
WThrBanU = 583,
|
| 594 |
+
WThrBanD = 584,
|
| 595 |
+
WThrPbm = 585,
|
| 596 |
+
WThrPbmU = 586,
|
| 597 |
+
WThrPbmD = 587,
|
| 598 |
+
WThrHgr = 588,
|
| 599 |
+
WThrHgrU = 589,
|
| 600 |
+
WThrHgrD = 590,
|
| 601 |
+
WThrow = 591,
|
| 602 |
+
WThrowU = 592,
|
| 603 |
+
WThrowD = 593,
|
| 604 |
+
Replay = 594,
|
| 605 |
+
NetBreak = 595,
|
| 606 |
+
ExFoom = 596,
|
| 607 |
+
ExBiff = 597,
|
| 608 |
+
ExPoot = 598,
|
| 609 |
+
ExPow = 599,
|
| 610 |
+
Circle25 = 600,
|
| 611 |
+
Circle50 = 601,
|
| 612 |
+
Circle75 = 602,
|
| 613 |
+
Circl100 = 603,
|
| 614 |
+
Elipse25 = 604,
|
| 615 |
+
Elipse50 = 605,
|
| 616 |
+
Elipse75 = 606,
|
| 617 |
+
Elips100 = 607,
|
| 618 |
+
GassGrn = 608,
|
| 619 |
+
SmkLt25 = 609,
|
| 620 |
+
SmkLt50 = 610,
|
| 621 |
+
SmkLt75 = 611,
|
| 622 |
+
SmkLt100 = 612,
|
| 623 |
+
SmkDrk20 = 613,
|
| 624 |
+
SmkDrk30 = 614,
|
| 625 |
+
SmkDrk40 = 615,
|
| 626 |
+
Clouds = 616,
|
| 627 |
+
CloudM = 617,
|
| 628 |
+
CloudL = 618,
|
| 629 |
+
Blob = 619,
|
| 630 |
+
// gap: 620-621 unused
|
| 631 |
+
Debris = 622,
|
| 632 |
+
Bubble1 = 623,
|
| 633 |
+
Bubble2 = 624,
|
| 634 |
+
Bubble3 = 625,
|
| 635 |
+
Bubble4 = 626,
|
| 636 |
+
WfDrown = 627,
|
| 637 |
+
Grave1V2 = 628,
|
| 638 |
+
Grave2V2 = 629,
|
| 639 |
+
Grave3V2 = 630,
|
| 640 |
+
Grave4V2 = 631,
|
| 641 |
+
Grave5V2 = 632,
|
| 642 |
+
Grave6V2 = 633,
|
| 643 |
+
TargetsV2 = 634,
|
| 644 |
+
TargetWV2 = 635,
|
| 645 |
+
WCrate1V2 = 636,
|
| 646 |
+
MCrate1V2 = 637,
|
| 647 |
+
UCrate1V2 = 638,
|
| 648 |
+
DonorV2 = 639,
|
| 649 |
+
WDrown = 640,
|
| 650 |
+
OilDrum = 641,
|
| 651 |
+
MeteorV2 = 642,
|
| 652 |
+
MineOnV2 = 643,
|
| 653 |
+
MineOffV2 = 644,
|
| 654 |
+
MissileV2 = 645,
|
| 655 |
+
AirMislV2 = 646,
|
| 656 |
+
GrenadeV2 = 647,
|
| 657 |
+
MortarV2 = 648,
|
| 658 |
+
ClusterV2 = 649,
|
| 659 |
+
ClustletV2 = 650,
|
| 660 |
+
BulletV2 = 651,
|
| 661 |
+
ArrowV2 = 652,
|
| 662 |
+
Sheep = 653,
|
| 663 |
+
Carpet1V2 = 654,
|
| 664 |
+
Carpet2V2 = 655,
|
| 665 |
+
SheepFalV2 = 656,
|
| 666 |
+
SheepBrnV2 = 657,
|
| 667 |
+
MbBombV2 = 658,
|
| 668 |
+
DrillV2 = 659,
|
| 669 |
+
WomanV2 = 660,
|
| 670 |
+
SallyV2 = 661,
|
| 671 |
+
SkunkV2 = 662,
|
| 672 |
+
Mole = 663,
|
| 673 |
+
CowWalkV2 = 664,
|
| 674 |
+
PigeonR0V2 = 665,
|
| 675 |
+
PigeonR1V2 = 666,
|
| 676 |
+
PigeonR2V2 = 667,
|
| 677 |
+
PigeonR3V2 = 668,
|
| 678 |
+
BananaV2 = 669,
|
| 679 |
+
PetrolBmV2 = 670,
|
| 680 |
+
TamborinV2 = 671,
|
| 681 |
+
HGrenadeV2 = 672,
|
| 682 |
+
HMissil1V2 = 673,
|
| 683 |
+
HMissil2V2 = 674,
|
| 684 |
+
AquaShp1V2 = 675,
|
| 685 |
+
AquaShp2V2 = 676,
|
| 686 |
+
VaseV2 = 677,
|
| 687 |
+
VaseBit1V2 = 678,
|
| 688 |
+
VaseBit2V2 = 679,
|
| 689 |
+
VaseBit3V2 = 680,
|
| 690 |
+
DynamiteV2 = 681,
|
| 691 |
+
Letter1V2 = 682,
|
| 692 |
+
Letter2V2 = 683,
|
| 693 |
+
DonkeyV2 = 684,
|
| 694 |
+
WBaz4 = 685,
|
| 695 |
+
WBaz4U = 686,
|
| 696 |
+
WBaz4D = 687,
|
| 697 |
+
WBaz5 = 688,
|
| 698 |
+
WBaz5U = 689,
|
| 699 |
+
WBaz5D = 690,
|
| 700 |
+
WBz4Lnk = 691,
|
| 701 |
+
WBz4LnkU = 692,
|
| 702 |
+
WBz4LnkD = 693,
|
| 703 |
+
WBz5Lnk = 694,
|
| 704 |
+
WBz5LnkU = 695,
|
| 705 |
+
WBz5LnkD = 696,
|
| 706 |
+
}
|
| 707 |
+
|
| 708 |
+
impl TryFrom<u32> for SpriteId {
|
| 709 |
+
type Error = u32;
|
| 710 |
+
|
| 711 |
+
fn try_from(value: u32) -> Result<Self, Self::Error> {
|
| 712 |
+
match value {
|
| 713 |
+
1..=619 | 622..=696 => {
|
| 714 |
+
// SAFETY: all matched values correspond to valid variants
|
| 715 |
+
Ok(unsafe { core::mem::transmute(value) })
|
| 716 |
+
}
|
| 717 |
+
_ => Err(value),
|
| 718 |
+
}
|
| 719 |
+
}
|
| 720 |
+
}
|
|
@@ -673,6 +673,9 @@ pub fn install() -> Result<(), String> {
|
|
| 673 |
// Patch DisplayGfx vtable (0x66A218): replace ported methods with Rust.
|
| 674 |
vtable_replace!(DisplayVtable, va::DISPLAY_GFX_VTABLE, {
|
| 675 |
get_dimensions => display_vtable::get_dimensions,
|
|
|
|
|
|
|
|
|
|
| 676 |
draw_polyline => display_vtable::draw_polyline,
|
| 677 |
draw_line => display_vtable::draw_line,
|
| 678 |
draw_line_clipped => display_vtable::draw_line_clipped,
|
|
@@ -686,12 +689,11 @@ pub fn install() -> Result<(), String> {
|
|
| 686 |
set_clip_rect => display_vtable::set_clip_rect,
|
| 687 |
is_sprite_loaded => display_vtable::is_sprite_loaded,
|
| 688 |
draw_scaled_sprite => draw_scaled_sprite,
|
| 689 |
-
set_active_layer => display_vtable::set_active_layer,
|
| 690 |
set_layer_visibility => display_vtable::set_layer_visibility,
|
| 691 |
update_palette => display_vtable::update_palette,
|
| 692 |
slot 19 => blit_sprite,
|
| 693 |
})?;
|
| 694 |
-
let _ = log_line("[Display] DisplayGfx: patched
|
| 695 |
}
|
| 696 |
|
| 697 |
Ok(())
|
|
|
|
| 673 |
// Patch DisplayGfx vtable (0x66A218): replace ported methods with Rust.
|
| 674 |
vtable_replace!(DisplayVtable, va::DISPLAY_GFX_VTABLE, {
|
| 675 |
get_dimensions => display_vtable::get_dimensions,
|
| 676 |
+
set_layer_color => display_vtable::set_layer_color,
|
| 677 |
+
set_active_layer => display_vtable::set_active_layer,
|
| 678 |
+
get_sprite_info => display_vtable::get_sprite_info,
|
| 679 |
draw_polyline => display_vtable::draw_polyline,
|
| 680 |
draw_line => display_vtable::draw_line,
|
| 681 |
draw_line_clipped => display_vtable::draw_line_clipped,
|
|
|
|
| 689 |
set_clip_rect => display_vtable::set_clip_rect,
|
| 690 |
is_sprite_loaded => display_vtable::is_sprite_loaded,
|
| 691 |
draw_scaled_sprite => draw_scaled_sprite,
|
|
|
|
| 692 |
set_layer_visibility => display_vtable::set_layer_visibility,
|
| 693 |
update_palette => display_vtable::update_palette,
|
| 694 |
slot 19 => blit_sprite,
|
| 695 |
})?;
|
| 696 |
+
let _ = log_line("[Display] DisplayGfx: patched 20 methods → Rust");
|
| 697 |
}
|
| 698 |
|
| 699 |
Ok(())
|
|
@@ -7,7 +7,7 @@
|
|
| 7 |
use openwa_core::address::va;
|
| 8 |
use openwa_core::rebase::rb;
|
| 9 |
use openwa_core::render::palette::PaletteContext;
|
| 10 |
-
use openwa_core::render::sprite::{Sprite, SpriteFrame};
|
| 11 |
|
| 12 |
use crate::hook::{self, usercall_trampoline};
|
| 13 |
|
|
@@ -22,7 +22,7 @@ unsafe extern "cdecl" fn construct_sprite_impl(sprite: *mut Sprite, context: *mu
|
|
| 22 |
// Zero the entire 0x70-byte struct first
|
| 23 |
core::ptr::write_bytes(sprite as *mut u8, 0, core::mem::size_of::<Sprite>());
|
| 24 |
|
| 25 |
-
(*sprite).vtable = rb(va::SPRITE_VTABLE) as *
|
| 26 |
(*sprite).context_ptr = context;
|
| 27 |
(*sprite).bitgrid_vtable = rb(va::BIT_GRID_DISPLAY_VTABLE) as *mut u8;
|
| 28 |
|
|
|
|
| 7 |
use openwa_core::address::va;
|
| 8 |
use openwa_core::rebase::rb;
|
| 9 |
use openwa_core::render::palette::PaletteContext;
|
| 10 |
+
use openwa_core::render::sprite::{Sprite, SpriteFrame, SpriteVtable};
|
| 11 |
|
| 12 |
use crate::hook::{self, usercall_trampoline};
|
| 13 |
|
|
|
|
| 22 |
// Zero the entire 0x70-byte struct first
|
| 23 |
core::ptr::write_bytes(sprite as *mut u8, 0, core::mem::size_of::<Sprite>());
|
| 24 |
|
| 25 |
+
(*sprite).vtable = rb(va::SPRITE_VTABLE) as *const SpriteVtable;
|
| 26 |
(*sprite).context_ptr = context;
|
| 27 |
(*sprite).bitgrid_vtable = rb(va::BIT_GRID_DISPLAY_VTABLE) as *mut u8;
|
| 28 |
|
|
@@ -13,6 +13,7 @@ use openwa_core::registry::{self, AddrKind};
|
|
| 13 |
/// Valid first bytes for x86 function prologues (MSVC).
|
| 14 |
/// This covers standard prologues plus common non-standard function starts.
|
| 15 |
const VALID_PROLOGUES: &[u8] = &[
|
|
|
|
| 16 |
0x33, // xor reg, reg
|
| 17 |
0x51, // push ecx
|
| 18 |
0x52, // push edx
|
|
|
|
| 13 |
/// Valid first bytes for x86 function prologues (MSVC).
|
| 14 |
/// This covers standard prologues plus common non-standard function starts.
|
| 15 |
const VALID_PROLOGUES: &[u8] = &[
|
| 16 |
+
0x2B, // sub reg, r/m32 (e.g. SpriteBank__GetInfo starts with SUB EAX, [ECX+8])
|
| 17 |
0x33, // xor reg, reg
|
| 18 |
0x51, // push ecx
|
| 19 |
0x52, // push edx
|