yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
sprite.cc
Go to the documentation of this file.
1#include "sprite.h"
2#include "sprite_names.h"
3
4#include <cstdint>
5#include <iostream>
6
8
9namespace yaze {
10namespace zelda3 {
11
12// Define sprite names in a single translation unit to avoid SIOF
13const std::string kSpriteDefaultNames[256] = {
14 "00 Raven",
15 "01 Vulture",
16 "02 Flying Stalfos Head",
17 "03 No Pointer (Empty",
18 "04 Pull Switch (good",
19 "05 Pull Switch (unused",
20 "06 Pull Switch (bad",
21 "07 Pull Switch (unused",
22 "08 Octorock (one way",
23 "09 Moldorm (Boss",
24 "0A Octorock (four way",
25 "0B Chicken",
26 "0C Octorock (?",
27 "0D Buzzblock",
28 "0E Snapdragon",
29 "0F Octoballoon",
30 "10 Octoballon Hatchlings",
31 "11 Hinox",
32 "12 Moblin",
33 "13 Mini Helmasaure",
34 "14 Gargoyle's Domain Gate",
35 "15 Antifairy",
36 "16 Sahasrahla / Aginah",
37 "17 Bush Hoarder",
38 "18 Mini Moldorm",
39 "19 Poe",
40 "1A Dwarves",
41 "1B Arrow in wall",
42 "1C Statue",
43 "1D Weathervane",
44 "1E Crystal Switch",
45 "1F Bug-Catching Kid",
46 "20 Sluggula",
47 "21 Push Switch",
48 "22 Ropa",
49 "23 Red Bari",
50 "24 Blue Bari",
51 "25 Talking Tree",
52 "26 Hardhat Beetle",
53 "27 Deadrock",
54 "28 Storytellers",
55 "29 Blind Hideout attendant",
56 "2A Sweeping Lady",
57 "2B Storytellers",
58 "2C Lumberjacks",
59 "2D Telepathic Stones",
60 "2E Multipurpose Sprite",
61 "2F Race Npc",
62 "30 Person?",
63 "31 Fortune Teller",
64 "32 Angry Brothers",
65 "33 Pull for items",
66 "34 Scared Girl",
67 "35 Innkeeper",
68 "36 Witch",
69 "37 Waterfall",
70 "38 Arrow Target",
71 "39 Average Middle",
72 "3A Half Magic Bat",
73 "3B Dash Item",
74 "3C Village Kid",
75 "3D Signs? Chicken lady also showed up / Scared ladies outside houses.",
76 "3E Rock Hoarder",
77 "3F Tutorial Soldier",
78 "40 Lightning Lock",
79 "41 Blue Sword Soldier / Used by guards to detect player",
80 "42 Green Sword Soldier",
81 "43 Red Spear Soldier",
82 "44 Assault Sword Soldier",
83 "45 Green Spear Soldier",
84 "46 Blue Archer",
85 "47 Green Archer",
86 "48 Red Javelin Soldier",
87 "49 Red Javelin Soldier 2",
88 "4A Red Bomb Soldiers",
89 "4B Green Soldier Recruits",
90 "4C Geldman",
91 "4D Rabbit",
92 "4E Popo",
93 "4F Popo 2",
94 "50 Cannon Balls",
95 "51 Armos",
96 "52 Giant Zora",
97 "53 Armos Knights (Boss",
98 "54 Lanmolas (Boss",
99 "55 Fireball Zora",
100 "56 Walking Zora",
101 "57 Desert Palace Barriers",
102 "58 Crab",
103 "59 Bird",
104 "5A Squirrel",
105 "5B Spark (Left to Right",
106 "5C Spark (Right to Left",
107 "5D Roller (vertical moving",
108 "5E Roller (vertical moving",
109 "5F Roller",
110 "60 Roller (horizontal moving",
111 "61 Beamos",
112 "62 Master Sword",
113 "63 Devalant (Non",
114 "64 Devalant (Shooter",
115 "65 Shooting Gallery Proprietor",
116 "66 Moving Cannon Ball Shooters (Right",
117 "67 Moving Cannon Ball Shooters (Left",
118 "68 Moving Cannon Ball Shooters (Down",
119 "69 Moving Cannon Ball Shooters (Up",
120 "6A Ball N' Chain Trooper",
121 "6B Cannon Soldier",
122 "6C Mirror Portal",
123 "6D Rat",
124 "6E Rope",
125 "6F Keese",
126 "70 Helmasaur King Fireball",
127 "71 Leever",
128 "72 Activator for the ponds (where you throw in items",
129 "73 Uncle / Priest",
130 "74 Running Man",
131 "75 Bottle Salesman",
132 "76 Princess Zelda",
133 "77 Antifairy (Alternate",
134 "78 Village Elder",
135 "79 Bee",
136 "7A Agahnim",
137 "7B Agahnim Energy Ball",
138 "7C Hyu",
139 "7D Big Spike Trap",
140 "7E Guruguru Bar (Clockwise",
141 "7F Guruguru Bar (Counter Clockwise",
142 "80 Winder",
143 "81 Water Tektite",
144 "82 Antifairy Circle",
145 "83 Green Eyegore",
146 "84 Red Eyegore",
147 "85 Yellow Stalfos",
148 "86 Kodongos",
149 "87 Flames",
150 "88 Mothula (Boss",
151 "89 Mothula's Beam",
152 "8A Spike Trap",
153 "8B Gibdo",
154 "8C Arrghus (Boss",
155 "8D Arrghus spawn",
156 "8E Terrorpin",
157 "8F Slime",
158 "90 Wallmaster",
159 "91 Stalfos Knight",
160 "92 Helmasaur King",
161 "93 Bumper",
162 "94 Swimmers",
163 "95 Eye Laser (Right",
164 "96 Eye Laser (Left",
165 "97 Eye Laser (Down",
166 "98 Eye Laser (Up",
167 "99 Pengator",
168 "9A Kyameron",
169 "9B Wizzrobe",
170 "9C Tadpoles",
171 "9D Tadpoles",
172 "9E Ostrich (Haunted Grove",
173 "9F Flute",
174 "A0 Birds (Haunted Grove",
175 "A1 Freezor",
176 "A2 Kholdstare (Boss",
177 "A3 Kholdstare's Shell",
178 "A4 Falling Ice",
179 "A5 Zazak Fireball",
180 "A6 Red Zazak",
181 "A7 Stalfos",
182 "A8 Bomber Flying Creatures from Darkworld",
183 "A9 Bomber Flying Creatures from Darkworld",
184 "AA Pikit",
185 "AB Maiden",
186 "AC Apple",
187 "AD Lost Old Man",
188 "AE Down Pipe",
189 "AF Up Pipe",
190 "B0 Right Pip",
191 "B1 Left Pipe",
192 "B2 Good bee again?",
193 "B3 Hylian Inscription",
194 "B4 Thief?s chest (not the one that follows you",
195 "B5 Bomb Salesman",
196 "B6 Kiki",
197 "B7 Maiden following you in Blind Dungeon",
198 "B8 Monologue Testing Sprite",
199 "B9 Feuding Friends on Death Mountain",
200 "BA Whirlpool",
201 "BB Salesman / chestgame guy / 300 rupee giver guy / Chest game thief",
202 "BC Drunk in the inn",
203 "BD Vitreous (Large Eyeball",
204 "BE Vitreous (Small Eyeball",
205 "BF Vitreous' Lightning",
206 "C0 Monster in Lake of Ill Omen / Quake Medallion",
207 "C1 Agahnim teleporting Zelda to dark world",
208 "C2 Boulders",
209 "C3 Gibo",
210 "C4 Thief",
211 "C5 Medusa",
212 "C6 Four Way Fireball Spitters (spit when you use your sword",
213 "C7 Hokku",
214 "C8 Big Fairy who heals you",
215 "C9 Tektite",
216 "CA Chain Chomp",
217 "CB Trinexx",
218 "CC Another part of trinexx",
219 "CD Yet another part of trinexx",
220 "CE Blind The Thief (Boss)",
221 "CF Swamola",
222 "D0 Lynel",
223 "D1 Bunny Beam",
224 "D2 Flopping fish",
225 "D3 Stal",
226 "D4 Landmine",
227 "D5 Digging Game Proprietor",
228 "D6 Ganon",
229 "D7 Copy of Ganon",
230 "D8 Heart",
231 "D9 Green Rupee",
232 "DA Blue Rupee",
233 "DB Red Rupee",
234 "DC Bomb Refill (1)",
235 "DD Bomb Refill (4)",
236 "DE Bomb Refill (8)",
237 "DF Small Magic Refill",
238 "E0 Full Magic Refill",
239 "E1 Arrow Refill (5)",
240 "E2 Arrow Refill (10)",
241 "E3 Fairy",
242 "E4 Key",
243 "E5 Big Key",
244 "E6 Shield",
245 "E7 Mushroom",
246 "E8 Fake Master Sword",
247 "E9 Magic Shop dude / His items",
248 "EA Heart Container",
249 "EB Heart Piece",
250 "EC Bushes",
251 "ED Cane Of Somaria Platform",
252 "EE Mantle",
253 "EF Cane of Somaria Platform (Unused)",
254 "F0 Cane of Somaria Platform (Unused)",
255 "F1 Cane of Somaria Platform (Unused)",
256 "F2 Medallion Tablet",
257 "F3",
258 "F4 Falling Rocks",
259 "F5",
260 "F6",
261 "F7",
262 "F8",
263 "F9",
264 "FA",
265 "FB",
266 "FC",
267 "FD",
268 "FE",
269 "FF",
270};
271
272// Legacy global state - now delegates to ResourceLabelProvider
276
280
281// Thread-local storage for the resolved name (for C-string return compatibility)
282static thread_local std::string g_resolved_sprite_name;
283
284const char* ResolveSpriteName(uint16_t id) {
285 // Use the unified ResourceLabelProvider for resolution
286 g_resolved_sprite_name = GetResourceLabels().GetLabel(ResourceType::kSprite, id);
287 return g_resolved_sprite_name.c_str();
288}
289
290// hmagic-derived expanded names (0x11c entries), see tools/decode_sprname.py.
291extern const char* const kSpriteNames[];
292extern const size_t kSpriteNameCount;
293
294// Define overlord names in a single translation unit to avoid SIOF
295const std::string kOverlordNames[26] = {
296 "Overlord_SpritePositionTarget",
297 "Overlord_AllDirectionMetalBallFactory",
298 "Overlord_CascadeMetalBallFactory",
299 "Overlord_StalfosFactory",
300 "Overlord_StalfosTrap",
301 "Overlord_SnakeTrap",
302 "Overlord_MovingFloor",
303 "Overlord_ZolFactory",
304 "Overlord_WallMasterFactory",
305 "Overlord_CrumbleTilePath 1",
306 "Overlord_CrumbleTilePath 2",
307 "Overlord_CrumbleTilePath 3",
308 "Overlord_CrumbleTilePath 4",
309 "Overlord_CrumbleTilePath 5",
310 "Overlord_CrumbleTilePath 6",
311 "Overlord_PirogusuFactory 1",
312 "Overlord_PirogusuFactory 2",
313 "Overlord_PirogusuFactory 3",
314 "Overlord_PirogusuFactory 4",
315 "Overlord_FlyingTileFactory",
316 "Overlord_WizzrobeFactory",
317 "Overlord_ZoroFactory",
318 "Overlord_StalfosTrapTriggerWindow",
319 "Overlord_RedStalfosTrap",
320 "Overlord_ArmosCoordinator",
321 "Overlord_BombTrap",
322};
323
324void Sprite::UpdateMapProperties(uint16_t map_id, const void* context) {
325 (void)context; // Not used by sprites currently
326 map_x_ = x_;
327 map_y_ = y_;
329}
330
331void Sprite::UpdateCoordinates(int map_x, int map_y) {
332 map_x_ = map_x;
333 map_y_ = map_y;
334}
335
337 uint8_t x = nx_;
338 uint8_t y = ny_;
339
340 if (overlord_ == 0x07) {
341 if (id_ == 0x1A) {
342 DrawSpriteTile((x * 16), (y * 16), 14, 6, 11); // bomb
343 } else if (id_ == 0x05) {
344 DrawSpriteTile((x * 16), (y * 16) - 12, 12, 16, 12, false, true);
345 DrawSpriteTile((x * 16), (y * 16), 0, 16, 12, false, true);
346 } else if (id_ == 0x06) {
347 DrawSpriteTile((x * 16), (y * 16), 10, 26, 14, true, true, 2,
348 2); // snek
349 } else if (id_ == 0x09) {
350 DrawSpriteTile((x * 16), (y * 16), 6, 26, 14);
351 DrawSpriteTile((x * 16) + 8, (y * 16) + 8, 8, 26, 14);
352 DrawSpriteTile((x * 16), (y * 16) + 16, 10, 27, 14, false, false, 1, 1);
353 } else if (id_ == 0x14) {
354 DrawSpriteTile((x * 16), (y * 16) + 8, 12, 06, 12, false, false, 2,
355 1); // shadow tile
356 DrawSpriteTile((x * 16), (y * 16) - 8, 3, 29, 8, false, false, 1,
357 1); // tile
358 DrawSpriteTile((x * 16) + 8, (y * 16) - 8, 3, 29, 8, true, false, 1,
359 1); // tile
360 DrawSpriteTile((x * 16), (y * 16), 3, 29, 8, false, true, 1,
361 1); // tile
362 DrawSpriteTile((x * 16) + 8, (y * 16), 3, 29, 8, true, true, 1,
363 1); // tile
364 } else {
365 DrawSpriteTile((x * 16), (y * 16), 4, 4, 5);
366 }
367
368 if (nx_ != x || ny_ != y) {
369 bounding_box_.x = (lower_x_ + (nx_ * 16));
370 bounding_box_.y = (lower_y_ + (ny_ * 16));
373 } else {
374 bounding_box_.x = (lower_x_ + (x * 16));
375 bounding_box_.y = (lower_y_ + (y * 16));
378 }
379
380 return;
381 }
382
383 if (id_ == 0x00) {
384 DrawSpriteTile((x * 16), (y * 16), 4, 28, 10);
385 } else if (id_ == 0x01) {
386 DrawSpriteTile((x * 16) - 8, (y * 16), 6, 24, 12, false, false, 2, 2);
387 DrawSpriteTile((x * 16) + 8, (y * 16), 6, 24, 12, true, false, 2, 2);
388 } else if (id_ == 0x02) {
389 DrawSpriteTile((x * 16), (y * 16), 0, 16, 10);
390 } else if (id_ == 0x04) {
391 uint8_t p = 3;
392
393 DrawSpriteTile((x * 16), (y * 16), 14, 28, p);
394 DrawSpriteTile((x * 16), (y * 16), 14, 30, p);
395 } else if (id_ == 0x05) {
396 uint8_t p = 3;
397
398 DrawSpriteTile((x * 16), (y * 16), 14, 28, p);
399 DrawSpriteTile((x * 16), (y * 16), 14, 30, p);
400 } else if (id_ == 0x06) {
401 uint8_t p = 3;
402
403 DrawSpriteTile((x * 16), (y * 16), 14, 28, p);
404 DrawSpriteTile((x * 16), (y * 16), 14, 30, p);
405 } else if (id_ == 0x07) {
406 uint8_t p = 3;
407
408 DrawSpriteTile((x * 16), (y * 16), 14, 28, p);
409 DrawSpriteTile((x * 16), (y * 16), 14, 30, p);
410 } else if (id_ == 0x08) {
411 DrawSpriteTile((x * 16), (y * 16), 0, 24, 6);
412 DrawSpriteTile((x * 16) + 4, (y * 16) + 6, 0, 24, 6, false, false, 1, 1);
413 } else if (id_ == 0x09) {
414 DrawSpriteTile((x * 16) - 22, (y * 16) - 24, 12, 24, 12, false, false, 2,
415 2); // Moldorm tail
416 DrawSpriteTile((x * 16) - 16, (y * 16) - 20, 8, 24, 12, false, false, 2,
417 2); // Moldorm b2
418 DrawSpriteTile((x * 16) - 12, (y * 16) - 16, 4, 24, 12, false, false, 4,
419 4); // Moldorm b
420 DrawSpriteTile((x * 16), (y * 16), 0, 24, 12, false, false, 4,
421 4); // Moldorm head
422
423 DrawSpriteTile((x * 16) + 20, (y * 16) + 12, 8, 26, 14, false, false, 2,
424 2); // Moldorm eye
425 DrawSpriteTile((x * 16) + 12, (y * 16) + 20, 8, 26, 14, false, false, 2,
426 2); // Moldorm eye
427 } else if (id_ == 0x0A) {
428 DrawSpriteTile((x * 16), (y * 16), 0, 24, 8);
429 DrawSpriteTile((x * 16) + 4, (y * 16) + 6, 0, 24, 8, false, false, 1, 1);
430 } else if (id_ == 0x0B) {
431 DrawSpriteTile((x * 16), (y * 16), 10, 30, 10);
432 } else if (id_ == 0x0C) {
433 DrawSpriteTile((x * 16), (y * 16), 0, 24, 8);
434 DrawSpriteTile((x * 16) + 4, (y * 16) + 6, 0, 24, 8, false, false, 1, 1);
435 } else if (id_ == 0x0D) {
436 DrawSpriteTile((x * 16), (y * 16), 14, 28, 12);
437 } else if (id_ == 0x0E) {
438 DrawSpriteTile((x * 16), (y * 16), 8, 18, 10, false, false, 3, 2);
439 } else if (id_ == 0x0F) {
440 DrawSpriteTile((x * 16), (y * 16), 14, 24, 8, false, false, 2, 3);
441 DrawSpriteTile((x * 16) + 16, (y * 16), 30, 8, 8, true, false, 1, 3);
442 } else if (id_ == 0x10) {
443 DrawSpriteTile((x * 16), (y * 16), 12, 31, 8, false, false, 1, 1);
444 } else if (id_ == 0x11) {
445 DrawSpriteTile((x * 16), (y * 16) + 16, 6, 16, 8, false, false, 2,
446 2); // Feet
447 DrawSpriteTile((x * 16) - 8, (y * 16) + 8, 4, 18, 8, false, false, 2,
448 2); // Body1
449 DrawSpriteTile((x * 16) + 8, (y * 16) + 8, 4, 18, 8, true, false, 2,
450 2); // Body2
451 DrawSpriteTile((x * 16), (y * 16), 0, 16, 8, false, false, 2,
452 2); // Head
453 } else if (id_ == 0x12) {
454 DrawSpriteTile((x * 16), (y * 16) + 8, 8, 26, 8);
455 DrawSpriteTile((x * 16), (y * 16), 6, 24, 8);
456 } else if (id_ == 0x13) {
457 DrawSpriteTile((x * 16), (y * 16), 4, 22, 2);
458 } else if (id_ == 0x15) {
459 // Antifairy
460 DrawSpriteTile((x * 16) + 2, (y * 16) + 8, 3, 30, 5, false, false, 1, 1);
461 DrawSpriteTile((x * 16) + 8, (y * 16) + 2, 3, 30, 5, false, false, 1, 1);
462 DrawSpriteTile((x * 16) + 14, (y * 16) + 8, 3, 30, 5, false, false, 1, 1);
463 DrawSpriteTile((x * 16) + 8, (y * 16) + 14, 3, 30, 5, false, false, 1, 1);
464 DrawSpriteTile((x * 16) + 8, (y * 16) + 8, 1, 30, 5, false, false, 1,
465 1); // Middle
466 } else if (id_ == 0x16) {
467 DrawSpriteTile((x * 16), (y * 16) + 8, 2, 26, 2);
468 DrawSpriteTile((x * 16), (y * 16), 0, 26, 2);
469 } else if (id_ == 0x17) // Bush hoarder
470 {
471 DrawSpriteTile((x * 16), (y * 16), 8, 30, 10);
472 } else if (id_ == 0x18) // Mini moldorm
473 {
474 DrawSpriteTile((x * 16) + 13, (y * 16) + 17, 13, 21, 8, false, false, 1,
475 1); // Tail
476 DrawSpriteTile((x * 16) + 5, (y * 16) + 8, 2, 22, 8); // Body
477 DrawSpriteTile((x * 16), (y * 16), 0, 22, 8); // Head
478 DrawSpriteTile((x * 16), (y * 16) - 4, 13, 20, 8, false, false, 1,
479 1); // Eyes
480 DrawSpriteTile((x * 16) - 4, (y * 16), 13, 20, 8, false, false, 1,
481 1); // Eyes
482 } else if (id_ == 0x19) // Poe - ghost
483 {
484 DrawSpriteTile((x * 16), (y * 16), 6, 31, 2); //
485 } else if (id_ == 0x1A) // Smith
486 {
487 // DrawSpriteTile((x*16), (y *16), 2, 4, 10,true); // Smitty
488 // DrawSpriteTile((x*16)+12, (y *16) - 7, 0, 6, 10); // Hammer
489 DrawSpriteTile((x * 16), (y * 16), 4, 22, 10);
490 } else if (id_ == 0x1C) // Statue
491 {
492 DrawSpriteTile((x * 16), (y * 16) + 8, 0, 28, 15);
493 DrawSpriteTile((x * 16), (y * 16), 2, 28, 15, false, false, 1, 1);
494 DrawSpriteTile((x * 16) + 8, (y * 16), 2, 28, 15, true, false, 1, 1);
495 } else if (id_ == 0x1E) // Crystal switch
496 {
497 DrawSpriteTile((x * 16), (y * 16), 4, 30, 5);
498 } else if (id_ == 0x1F) // Sick kid
499 {
500 DrawSpriteTile((x * 16) - 8, (y * 16) + 8, 10, 16, 14);
501 DrawSpriteTile((x * 16) + 16 - 8, (y * 16) + 8, 10, 16, 14, true);
502 DrawSpriteTile((x * 16) - 8, (y * 16) + 16, 10, 16, 14, false, true, 2, 2);
503 DrawSpriteTile((x * 16) + 16 - 8, (y * 16) + 16, 10, 16, 14, true, true, 2,
504 2);
505 DrawSpriteTile((x * 16), (y * 16) - 4, 14, 16, 10);
506 } else if (id_ == 0x20) {
507 DrawSpriteTile((x * 16), (y * 16), 2, 24, 7);
508 } else if (id_ == 0x21) // Push switch
509 {
510 DrawSpriteTile((x * 16) + 4, (y * 16) + 20, 13, 29, 3, false, false, 1, 1);
511 DrawSpriteTile((x * 16) + 4, (y * 16) + 28, 12, 29, 3, false, false, 1, 1);
512 DrawSpriteTile((x * 16), (y * 16) + 8, 10, 28, 3);
513 } else if (id_ == 0x22) // Rope
514 {
515 DrawSpriteTile((x * 16), (y * 16), 8, 26, 5);
516 } else if (id_ == 0x23) // Red bari
517 {
518 DrawSpriteTile((x * 16), (y * 16), 2, 18, 4, false, false, 1, 2);
519 DrawSpriteTile((x * 16) + 8, (y * 16), 2, 18, 4, true, false, 1, 2);
520 } else if (id_ == 0x24) // Blue bari
521 {
522 DrawSpriteTile((x * 16), (y * 16), 2, 18, 6, false, false, 1, 2);
523 DrawSpriteTile((x * 16) + 8, (y * 16), 2, 18, 6, true, false, 1, 2);
524 } else if (id_ == 0x25) // Talking tree?
525 {
526 // TODO: Add something here?
527 } else if (id_ == 0x26) // Hardhat beetle
528 {
529 if ((x & 0x01) == 0x00) {
530 DrawSpriteTile((x * 16), (y * 16), 4, 20, 8);
531 DrawSpriteTile((x * 16), (y * 16) - 6, 0, 20, 8);
532 } else {
533 DrawSpriteTile((x * 16), (y * 16), 4, 20, 10);
534 DrawSpriteTile((x * 16), (y * 16) - 6, 0, 20, 10);
535 }
536 } else if (id_ == 0x27) // Deadrock
537 {
538 DrawSpriteTile((x * 16), (y * 16), 2, 30, 10);
539 } else if (id_ == 0x28) // Npcs
540 {
541 DrawSpriteTile((x * 16), (y * 16), 14, 22, 10);
542 } else if (id_ == 0x29) // Npcs
543 {
544 DrawSpriteTile((x * 16), (y * 16), 14, 22, 10);
545 } else if (id_ == 0x2A) // Npcs
546 {
547 DrawSpriteTile((x * 16), (y * 16), 14, 22, 10);
548 } else if (id_ == 0x2B) // ???
549 {
550 DrawSpriteTile((x * 16), (y * 16), 14, 22, 10);
551 } else if (id_ == 0x2C) // Lumberjack
552 {
553 DrawSpriteTile((x * 16) - 24, (y * 16) + 12, 6, 26, 12, true); // Body
554 DrawSpriteTile((x * 16) - 24, (y * 16), 8, 26, 12, true); // Head
555
556 DrawSpriteTile((x * 16) - 14, (y * 16) + 12, 14, 27, 10, false, false, 1,
557 1); // Saw left edge
558 DrawSpriteTile((x * 16) - 6, (y * 16) + 12, 15, 27, 10, false, false, 1,
559 1); // Saw left edge
560 DrawSpriteTile((x * 16) + 2, (y * 16) + 12, 15, 27, 10, false, false, 1,
561 1); // Saw left edge
562 DrawSpriteTile((x * 16) + 10, (y * 16) + 12, 15, 27, 10, false, false, 1,
563 1); // Saw left edge
564 DrawSpriteTile((x * 16) + 18, (y * 16) + 12, 15, 27, 10, false, false, 1,
565 1); // Saw left edge
566 DrawSpriteTile((x * 16) + 26, (y * 16) + 12, 15, 27, 10, false, false, 1,
567 1); // Saw left edge
568 DrawSpriteTile((x * 16) + 34, (y * 16) + 12, 14, 27, 10, true, false, 1,
569 1); // Saw left edge
570
571 DrawSpriteTile((x * 16) + 40, (y * 16) + 12, 4, 26, 12); // Body
572 DrawSpriteTile((x * 16) + 40, (y * 16), 8, 26, 12); // Head
573 } else if (id_ == 0x2D) // Npcs
574 {
575 DrawSpriteTile((x * 16), (y * 16), 14, 22, 10);
576 } else if (id_ == 0x2E) // Npcs
577 {
578 DrawSpriteTile((x * 16), (y * 16), 14, 22, 10);
579 } else if (id_ == 0x2F) // Npcs
580 {
581 DrawSpriteTile((x * 16), (y * 16), 14, 22, 10);
582 } else if (id_ == 0x30) // Npcs
583 {
584 DrawSpriteTile((x * 16), (y * 16), 14, 22, 10);
585 } else if (id_ == 0x31) // Npcs
586 {
587 DrawSpriteTile((x * 16), (y * 16), 14, 22, 10);
588 } else if (id_ == 0x32) // Npcs
589 {
590 DrawSpriteTile((x * 16), (y * 16), 14, 22, 10);
591 }
592 /*
593 else if (id_== 0x33) // Pull for rupees
594 {
595
596 }
597 */
598 else if (id_ == 0x34) // Npcs
599 {
600 DrawSpriteTile((x * 16), (y * 16), 14, 22, 10);
601 } else if (id_ == 0x35) // Npcs
602 {
603 DrawSpriteTile((x * 16), (y * 16), 14, 22, 10);
604 } else if (id_ == 0x36) // Npcs
605 {
606 DrawSpriteTile((x * 16), (y * 16), 14, 22, 10);
607 }
608 /*
609 else if (id_== 0x37) // Waterfall
610 {
611 DrawSpriteTile((x*16), (y *16), 14, 6, 10);
612 }
613 */
614 else if (id_ == 0x38) // Arrowtarget
615 {
616 DrawSpriteTile((x * 16), (y * 16), 14, 22, 10);
617 } else if (id_ == 0x39) // Npcs
618 {
619 DrawSpriteTile((x * 16), (y * 16), 14, 22, 10);
620 } else if (id_ == 0x3A) // Npcs
621 {
622 DrawSpriteTile((x * 16), (y * 16), 14, 22, 10);
623 } else if (id_ == 0x3B) // Dash item
624 {
625 } else if (id_ == 0x3C) // Npcs
626 {
627 DrawSpriteTile((x * 16), (y * 16), 14, 22, 10);
628 } else if (id_ == 0x3D) // Npcs
629 {
630 DrawSpriteTile((x * 16), (y * 16), 14, 22, 10);
631 } else if (id_ == 0x3E) // Npcs
632 {
633 DrawSpriteTile((x * 16), (y * 16), 14, 22, 10);
634 } else if (id_ == 0x3F) // Npcs
635 {
636 DrawSpriteTile((x * 16), (y * 16), 14, 22, 10);
637 } else if (id_ == 0x40) // Lightning lock (agah tower)
638 {
639 DrawSpriteTile((x * 16) - 24, (y * 16), 10, 28, 2, false, false, 1, 2);
640 DrawSpriteTile((x * 16) - 16, (y * 16), 6, 30, 2);
641 DrawSpriteTile((x * 16), (y * 16), 8, 30, 2);
642 DrawSpriteTile((x * 16) + 16, (y * 16), 6, 30, 2);
643 DrawSpriteTile((x * 16) + 24, (y * 16), 10, 28, 2, false, false, 1, 2);
644 } else if (id_ == 0x41) // Blue soldier
645 {
646 DrawSpriteTile((x * 16) - 4, (y * 16) + 8, 6, 20, 10);
647 DrawSpriteTile((x * 16) + 12, (y * 16) + 8, 6, 20, 10, true, false, 1, 2);
648 DrawSpriteTile((x * 16), (y * 16), 0, 20, 10);
649 DrawSpriteTile((x * 16) + 12, (y * 16) + 8, 13, 22, 10, false, false, 1,
650 2); // Shield
651 DrawSpriteTile((x * 16) - 4, (y * 16) + 16, 14, 22, 10, false, true, 1,
652 2); // Sword
653 } else if (id_ == 0x42) // Green soldier
654 {
655 DrawSpriteTile((x * 16) - 4, (y * 16) + 8, 6, 20, 12);
656 DrawSpriteTile((x * 16) + 12, (y * 16) + 8, 6, 20, 12, true, false, 1, 2);
657 DrawSpriteTile((x * 16), (y * 16), 0, 20, 12);
658 DrawSpriteTile((x * 16) + 12, (y * 16) + 8, 13, 22, 12, false, false, 1,
659 2); // Shield
660 DrawSpriteTile((x * 16) - 4, (y * 16) + 16, 14, 22, 12, false, true, 1,
661 2); // Sword
662 } else if (id_ == 0x43) // Red spear soldier
663 {
664 DrawSpriteTile((x * 16) - 4, (y * 16) + 8, 6, 20, 8);
665 DrawSpriteTile((x * 16) + 12, (y * 16) + 8, 6, 20, 8, true, false, 1, 2);
666 DrawSpriteTile((x * 16), (y * 16), 0, 20, 8);
667 DrawSpriteTile((x * 16) + 12, (y * 16) + 8, 13, 22, 8, false, false, 1,
668 2); // Shield
669 DrawSpriteTile((x * 16) - 4, (y * 16) + 16, 11, 22, 8, false, true, 1,
670 2); // Spear
671 } else if (id_ == 0x44) // Sword blue holding up
672 {
673 DrawSpriteTile((x * 16) + 4, (y * 16) + 8, 6, 16, 10);
674 DrawSpriteTile((x * 16) - 4, (y * 16) + 8, 6, 20, 10, false, false, 1, 2);
675 DrawSpriteTile((x * 16), (y * 16), 0, 16, 10); // Head
676 DrawSpriteTile((x * 16) + 12, (y * 16) + 8, 14, 22, 10, false, true, 1,
677 2); // Sword
678 } else if (id_ == 0x45) // Green spear soldier
679 {
680 DrawSpriteTile((x * 16) - 4, (y * 16) + 8, 6, 20, 12);
681 DrawSpriteTile((x * 16) + 12, (y * 16) + 8, 6, 20, 12, true, false, 1, 2);
682 DrawSpriteTile((x * 16), (y * 16), 0, 20, 12);
683 DrawSpriteTile((x * 16) + 12, (y * 16) + 8, 13, 22, 12, false, false, 1,
684 2); // Shield
685 DrawSpriteTile((x * 16) - 4, (y * 16) + 16, 11, 22, 12, false, true, 1,
686 2); // Spear
687 } else if (id_ == 0x46) // Blue archer
688 {
689 DrawSpriteTile((x * 16) - 4, (y * 16) + 8, 6, 20, 10);
690 DrawSpriteTile((x * 16) + 12, (y * 16) + 8, 6, 20, 10, true, false, 1, 2);
691 DrawSpriteTile((x * 16), (y * 16), 0, 20, 10); // Head
692 DrawSpriteTile((x * 16), (y * 16) + 16, 10, 16, 10, false, false, 1,
693 1); // Bow1
694 DrawSpriteTile((x * 16) + 8, (y * 16) + 16, 10, 16, 10, true, false, 1,
695 1); // Bow2
696 } else if (id_ == 0x47) // Green archer
697 {
698 DrawSpriteTile((x * 16), (y * 16) + 8, 14, 16, 12);
699 DrawSpriteTile((x * 16), (y * 16), 0, 20, 12);
700 DrawSpriteTile((x * 16), (y * 16) + 16, 10, 16, 12, false, false, 1,
701 1); // Bow1
702 DrawSpriteTile((x * 16) + 8, (y * 16) + 16, 10, 16, 12, true, false, 1,
703 1); // Bow2
704 } else if (id_ == 0x48) // Javelin soldier red
705 {
706 DrawSpriteTile((x * 16) + 4, (y * 16) + 8, 6, 16, 8);
707 DrawSpriteTile((x * 16) - 4, (y * 16) + 8, 6, 20, 8, false, false, 1, 2);
708 DrawSpriteTile((x * 16), (y * 16), 0, 16, 8); // Head
709 DrawSpriteTile((x * 16) + 12, (y * 16) + 8, 11, 22, 8, false, true, 1,
710 2); // Sword
711 } else if (id_ == 0x49) // Javelin soldier red from bush
712 {
713 DrawSpriteTile((x * 16) + 4, (y * 16) + 8, 6, 16, 8);
714 DrawSpriteTile((x * 16) - 4, (y * 16) + 8, 6, 20, 8, false, false, 1, 2);
715 DrawSpriteTile((x * 16), (y * 16), 0, 18, 8); // Head
716 DrawSpriteTile((x * 16), (y * 16) + 24, 0, 20, 2);
717 DrawSpriteTile((x * 16) + 12, (y * 16) + 8, 11, 22, 8, false, true, 1,
718 2); // Sword
719 } else if (id_ == 0x4A) // Red bomb soldier
720 {
721 DrawSpriteTile((x * 16) + 4, (y * 16) + 8, 6, 16, 8);
722 DrawSpriteTile((x * 16) - 4, (y * 16) + 8, 6, 20, 8, false, false, 1, 2);
723 DrawSpriteTile((x * 16), (y * 16), 0, 16, 8); // Head
724 DrawSpriteTile((x * 16) + 8, (y * 16) - 8, 14, 22, 11); // Bomb
725 } else if (id_ == 0x4B) // Green soldier recruit
726 {
727 // 0,4
728 DrawSpriteTile((x * 16), (y * 16), 6, 24, 12);
729 DrawSpriteTile((x * 16), (y * 16) - 10, 0, 20, 12);
730 } else if (id_ == 0x4C) // Jazzhand
731 {
732 DrawSpriteTile((x * 16), (y * 16), 0, 26, 14, false, false, 6, 2);
733 } else if (id_ == 0x4D) // Rabit??
734 {
735 DrawSpriteTile((x * 16), (y * 16), 0, 26, 12, false, false, 6, 2);
736 } else if (id_ == 0x4E) // Popo1
737 {
738 DrawSpriteTile((x * 16), (y * 16), 0, 20, 10);
739 } else if (id_ == 0x4F) // Popo2
740 {
741 DrawSpriteTile((x * 16), (y * 16), 2, 20, 10);
742 } else if (id_ == 0x50) // Canon ball
743 {
744 DrawSpriteTile((x * 16), (y * 16), 0, 24, 10);
745 } else if (id_ == 0x51) // Armos
746 {
747 DrawSpriteTile((x * 16), (y * 16), 0, 28, 11, false, false, 2, 4);
748 } else if (id_ == 0x53) // Armos Knight
749 {
750 DrawSpriteTile((x * 16), (y * 16), 0, 28, 10, false, false, 4, 4);
751 } else if (id_ == 0x54) {
752 DrawSpriteTile((x * 16), (y * 16), 2, 28, 12);
753 DrawSpriteTile((x * 16) + 8, (y * 16) + 10, 6, 28, 12);
754 DrawSpriteTile((x * 16) + 16, (y * 16) + 18, 10, 28, 12);
755 } else if (id_ == 0x55) // Fireball Zora
756 {
757 DrawSpriteTile((x * 16), (y * 16), 4, 26, 11);
758 } else if (id_ == 0x56) // Zora
759 {
760 DrawSpriteTile((x * 16), (y * 16), 10, 20, 2);
761 DrawSpriteTile((x * 16), (y * 16) + 8, 8, 30, 2);
762 } else if (id_ == 0x57) // Desert Rocks
763 {
764 DrawSpriteTile((x * 16), (y * 16), 14, 24, 2, false, false, 2, 4);
765 DrawSpriteTile((x * 16) + 16, (y * 16), 14, 24, 2, true, false, 2, 4);
766 } else if (id_ == 0x58) // Crab
767 {
768 DrawSpriteTile((x * 16), (y * 16), 14, 24, 12);
769 DrawSpriteTile((x * 16) + 16, (y * 16), 14, 24, 12, true);
770 } else if (id_ == 0x5B) // Spark
771 {
772 DrawSpriteTile((x * 16), (y * 16), 8, 18, 4);
773 } else if (id_ == 0x5C) // Spark
774 {
775 DrawSpriteTile((x * 16), (y * 16), 8, 18, 4, true);
776 } else if (id_ == 0x5D) // Roller vertical1
777 {
778 // Subset3
779 if (((y * 16) & 0x10) == 0x10) {
780 DrawSpriteTile((x * 16), (y * 16), 8, 24, 11);
781
782 for (int i = 0; i < 7; i++) {
783 DrawSpriteTile((x * 16) + 8 + (i * 16), (y * 16), 9, 24, 11);
784 }
785
786 DrawSpriteTile((x * 16) + (16 * 7), (y * 16), 8, 24, 11, true);
787 } else {
788 DrawSpriteTile((x * 16), (y * 16), 8, 24, 11);
789 DrawSpriteTile((x * 16) + 16, (y * 16), 9, 24, 11);
790 DrawSpriteTile((x * 16) + 32, (y * 16), 9, 24, 11);
791 DrawSpriteTile((x * 16) + 48, (y * 16), 8, 24, 11, true);
792 }
793
794 } else if (id_ == 0x5E) // Roller vertical2
795 {
796 // Subset3
797 if (((y * 16) & 0x10) == 0x10) {
798 DrawSpriteTile((x * 16), (y * 16), 8, 24, 11);
799
800 for (int i = 0; i < 7; i++) {
801 DrawSpriteTile((x * 16) + 8 + (i * 16), (y * 16), 9, 24, 11);
802 }
803
804 DrawSpriteTile((x * 16) + (16 * 7), (y * 16), 8, 24, 11, true);
805 } else {
806 DrawSpriteTile((x * 16), (y * 16), 8, 24, 11);
807 DrawSpriteTile((x * 16) + 16, (y * 16), 9, 24, 11);
808 DrawSpriteTile((x * 16) + 32, (y * 16), 9, 24, 11);
809 DrawSpriteTile((x * 16) + 48, (y * 16), 8, 24, 11, true);
810 }
811 } else if (id_ == 0x5F) // Roller horizontal
812 {
813 if (((x * 16) & 0x10) == 0x10) {
814 DrawSpriteTile((x * 16), (y * 16), 14, 24, 11);
815 DrawSpriteTile((x * 16), (y * 16) + 16, 14, 25, 11);
816 DrawSpriteTile((x * 16), (y * 16) + 32, 14, 25, 11);
817 DrawSpriteTile((x * 16), (y * 16) + 48, 14, 24, 11, false, true);
818 } else {
819 for (int i = 0; i < 7; i++) {
820 DrawSpriteTile((x * 16), (y * 16) + i * 16, 14, 25, 11);
821 }
822
823 DrawSpriteTile((x * 16), (y * 16), 14, 24, 11);
824 DrawSpriteTile((x * 16), (y * 16) + (7 * 16), 14, 24, 11, false, true);
825 }
826 } else if (id_ == 0x60) // Roller horizontal2 (right to left)
827 {
828 // Subset3
829 if (((x * 16) & 0x10) == 0x10) {
830 DrawSpriteTile((x * 16), (y * 16), 14, 24, 11);
831 DrawSpriteTile((x * 16), (y * 16) + 16, 14, 25, 11);
832 DrawSpriteTile((x * 16), (y * 16) + 32, 14, 25, 11);
833 DrawSpriteTile((x * 16), (y * 16) + 48, 14, 24, 11, false, true);
834 } else {
835 for (int i = 0; i < 7; i++) {
836 DrawSpriteTile((x * 16), (y * 16) + i * 16, 14, 25, 11);
837 }
838
839 DrawSpriteTile((x * 16), (y * 16), 14, 24, 11);
840 DrawSpriteTile((x * 16), (y * 16) + (7 * 16), 14, 24, 11, false, true);
841 }
842
843 } else if (id_ == 0x61) // Beamos
844 {
845 DrawSpriteTile((x * 16), (y * 16) - 16, 8, 20, 14, false, false, 2, 4);
846 DrawSpriteTile((x * 16) + 4, (y * 16) - 8, 10, 20, 14, false, false, 1, 1);
847 } else if (id_ == 0x63) // Devalant non-shooter
848 {
849 DrawSpriteTile((x * 16) - 8, (y * 16) - 8, 2, 16, 2);
850 DrawSpriteTile((x * 16) + 8, (y * 16) - 8, 2, 16, 2, true);
851 DrawSpriteTile((x * 16) - 8, (y * 16) + 8, 2, 16, 2, false, true);
852 DrawSpriteTile((x * 16) + 8, (y * 16) + 8, 2, 16, 2, true, true);
853 DrawSpriteTile((x * 16), (y * 16), 0, 16, 10);
854 } else if (id_ == 0x64) // Devalant non-shooter
855 {
856 DrawSpriteTile((x * 16) - 8, (y * 16) - 8, 2, 16, 2);
857 DrawSpriteTile((x * 16) + 8, (y * 16) - 8, 2, 16, 2, true);
858 DrawSpriteTile((x * 16) - 8, (y * 16) + 8, 2, 16, 2, false, true);
859 DrawSpriteTile((x * 16) + 8, (y * 16) + 8, 2, 16, 2, true, true);
860 DrawSpriteTile((x * 16), (y * 16), 0, 16, 8);
861 } else if (id_ == 0x66) // Moving wall canon right
862 {
863 DrawSpriteTile((x * 16), (y * 16), 14, 16, 14, true);
864 } else if (id_ == 0x67) // Moving wall canon right
865 {
866 DrawSpriteTile((x * 16), (y * 16), 14, 16, 14);
867 } else if (id_ == 0x68) // Moving wall canon right
868 {
869 DrawSpriteTile((x * 16), (y * 16), 12, 16, 14);
870 } else if (id_ == 0x69) // Moving wall canon right
871 {
872 DrawSpriteTile((x * 16), (y * 16), 12, 16, 14, false, true);
873 } else if (id_ == 0x6A) // Chainball soldier
874 {
875 DrawSpriteTile((x * 16) + 4, (y * 16) + 8, 6, 16, 14);
876 DrawSpriteTile((x * 16) - 4, (y * 16) + 8, 6, 20, 14, false, false, 1, 2);
877 DrawSpriteTile((x * 16), (y * 16), 0, 16, 14); // Head
878 DrawSpriteTile((x * 16) + 12, (y * 16) - 16, 10, 18, 14); // Ball
879 } else if (id_ == 0x6B) // Cannon soldier
880 {
881 DrawSpriteTile((x * 16) + 4, (y * 16) + 8, 6, 16, 14);
882 DrawSpriteTile((x * 16) - 4, (y * 16) + 8, 6, 20, 14, false, false, 1, 2);
883 DrawSpriteTile((x * 16), (y * 16), 0, 16, 14); // Head
884 DrawSpriteTile((x * 16) + 12, (y * 16) + 8, 4, 18, 14); // Cannon
885 } else if (id_ == 0x6C) // Mirror portal
886 {
887 // Useless
888 } else if (id_ == 0x6D) // Rat
889 {
890 DrawSpriteTile((x * 16), (y * 16), 14, 24, 5);
891 } else if (id_ == 0x6E) // Rope
892 {
893 DrawSpriteTile((x * 16), (y * 16), 10, 26, 5);
894 } else if (id_ == 0x6F) {
895 DrawSpriteTile((x * 16), (y * 16), 4, 24, 10);
896 } else if (id_ == 0x70) // Helma fireball
897 {
898 DrawSpriteTile((x * 16), (y * 16), 10, 28, 4);
899 } else if (id_ == 0x71) // Leever
900 {
901 DrawSpriteTile((x * 16), (y * 16), 6, 16, 4);
902 } else if (id_ == 0x73) // Uncle priest
903 {
904 } else if (id_ == 0x79) // Bee
905 {
906 DrawSpriteTile((x * 16), (y * 16), 4, 14, 11, false, false, 1, 1);
907 } else if (id_ == 0x7C) // Skull head
908 {
909 DrawSpriteTile((x * 16), (y * 16), 0, 16, 10);
910 } else if (id_ == 0x7D) // Big spike
911 {
912 DrawSpriteTile((x * 16), (y * 16), 4, 28, 11);
913 DrawSpriteTile((x * 16) + 16, (y * 16), 4, 28, 11, true);
914 DrawSpriteTile((x * 16), (y * 16) + 16, 4, 28, 11, false, true);
915 DrawSpriteTile((x * 16) + 16, (y * 16) + 16, 4, 28, 11, true, true);
916 } else if (id_ == 0x7E) // Guruguru clockwise
917 {
918 DrawSpriteTile((x * 16), (y * 16) - 14, 8, 18, 4);
919 DrawSpriteTile((x * 16), (y * 16) - 28, 8, 18, 4);
920 DrawSpriteTile((x * 16), (y * 16) - 42, 8, 18, 4);
921 DrawSpriteTile((x * 16), (y * 16) - 56, 8, 18, 4);
922 } else if (id_ == 0x7F) // Guruguru Counterclockwise
923 {
924 DrawSpriteTile((x * 16), (y * 16) - 14, 8, 18, 4);
925 DrawSpriteTile((x * 16), (y * 16) - 28, 8, 18, 4);
926 DrawSpriteTile((x * 16), (y * 16) - 42, 8, 18, 4);
927 DrawSpriteTile((x * 16), (y * 16) - 56, 8, 18, 4);
928 } else if (id_ == 0x80) // Winder (moving firebar)
929 {
930 DrawSpriteTile((x * 16), (y * 16), 8, 18, 4);
931 DrawSpriteTile((x * 16) - 14, (y * 16), 8, 18, 4);
932 DrawSpriteTile((x * 16) - 28, (y * 16), 8, 18, 4);
933 DrawSpriteTile((x * 16) - 42, (y * 16), 8, 18, 4);
934 DrawSpriteTile((x * 16) - 56, (y * 16), 8, 18, 4);
935 } else if (id_ == 0x81) // Water tektite
936 {
937 DrawSpriteTile((x * 16), (y * 16), 0, 24, 11);
938 } else if (id_ == 0x82) // circle antifairy
939 {
940 // Antifairy top
941 DrawSpriteTile((x * 16 + 2) - 4, (y * 16 + 8) - 16, 3, 30, 5, false, false,
942 1, 1);
943 DrawSpriteTile((x * 16 + 8) - 4, (y * 16 + 2) - 16, 3, 30, 5, false, false,
944 1, 1);
945 DrawSpriteTile((x * 16 + 14) - 4, (y * 16 + 8) - 16, 3, 30, 5, false, false,
946 1, 1);
947 DrawSpriteTile((x * 16 + 8) - 4, (y * 16 + 14) - 16, 3, 30, 5, false, false,
948 1, 1);
949 DrawSpriteTile((x * 16 + 8) - 4, (y * 16 + 8) - 16, 1, 30, 5, false, false,
950 1, 1); // Middle
951 // Left
952 DrawSpriteTile((x * 16 + 2) - 16, (y * 16 + 8) - 4, 3, 30, 5, false, false,
953 1, 1);
954 DrawSpriteTile((x * 16 + 8) - 16, (y * 16 + 2) - 4, 3, 30, 5, false, false,
955 1, 1);
956 DrawSpriteTile((x * 16 + 14) - 16, (y * 16 + 8) - 4, 3, 30, 5, false, false,
957 1, 1);
958 DrawSpriteTile((x * 16 + 8) - 16, (y * 16 + 14) - 4, 3, 30, 5, false, false,
959 1, 1);
960 DrawSpriteTile((x * 16 + 8) - 16, (y * 16 + 8) - 4, 1, 30, 5, false, false,
961 1, 1); // Middle
962
963 DrawSpriteTile((x * 16 + 2) - 4, (y * 16 + 8) + 8, 3, 30, 5, false, false,
964 1, 1);
965 DrawSpriteTile((x * 16 + 8) - 4, (y * 16 + 2) + 8, 3, 30, 5, false, false,
966 1, 1);
967 DrawSpriteTile((x * 16 + 14) - 4, (y * 16 + 8) + 8, 3, 30, 5, false, false,
968 1, 1);
969 DrawSpriteTile((x * 16 + 8) - 4, (y * 16 + 14) + 8, 3, 30, 5, false, false,
970 1, 1);
971 DrawSpriteTile((x * 16 + 8) - 4, (y * 16 + 8) + 8, 1, 30, 5, false, false,
972 1, 1); // Middle
973 // Left
974 DrawSpriteTile((x * 16 + 2) + 8, (y * 16 + 8) - 4, 3, 30, 5, false, false,
975 1, 1);
976 DrawSpriteTile((x * 16 + 8) + 8, (y * 16 + 2) - 4, 3, 30, 5, false, false,
977 1, 1);
978 DrawSpriteTile((x * 16 + 14) + 8, (y * 16 + 8) - 4, 3, 30, 5, false, false,
979 1, 1);
980 DrawSpriteTile((x * 16 + 8) + 8, (y * 16 + 14) - 4, 3, 30, 5, false, false,
981 1, 1);
982 DrawSpriteTile((x * 16 + 8) + 8, (y * 16 + 8) - 4, 1, 30, 5, false, false,
983 1, 1); // Middle
984 } else if (id_ == 0x83) // Green eyegore
985 {
986 DrawSpriteTile((x * 16), (y * 16), 12, 24, 14, false, false, 2, 3);
987 DrawSpriteTile((x * 16) + 16, (y * 16), 12, 24, 14, true, false, 1, 3);
988 } else if (id_ == 0x84) // Red eyegore
989 {
990 DrawSpriteTile((x * 16), (y * 16), 12, 24, 8, false, false, 2, 3);
991 DrawSpriteTile((x * 16) + 16, (y * 16), 12, 24, 8, true, false, 1, 3);
992 } else if (id_ == 0x85) // Yellow stalfos
993 {
994 DrawSpriteTile((x * 16), (y * 16), 10, 16, 11);
995 DrawSpriteTile((x * 16), (y * 16) - 12, 0, 16, 11); // Head
996 } else if (id_ == 0x86) // Kodongo
997 {
998 DrawSpriteTile((x * 16), (y * 16), 4, 26, 14);
999 } else if (id_ == 0x88) // Mothula
1000 {
1001 DrawSpriteTile((x * 16), (y * 16), 8, 24, 14, false, false, 2, 4);
1002 DrawSpriteTile((x * 16) + 16, (y * 16), 8, 24, 14, true, false, 2, 4);
1003 } else if (id_ == 0x8A) // Spike
1004 {
1005 DrawSpriteTile((x * 16), (y * 16), 6, 30, 15);
1006 } else if (id_ == 0x8B) // Gibdo
1007 {
1008 DrawSpriteTile((x * 16), (y * 16), 10, 24, 14);
1009 DrawSpriteTile((x * 16), (y * 16) - 8, 0, 24, 14);
1010 } else if (id_ == 0x8C) // Arrghus
1011 {
1012 DrawSpriteTile((x * 16), (y * 16), 0, 24, 14, false, false, 2, 4);
1013 DrawSpriteTile((x * 16) + 16, (y * 16), 0, 24, 14, true, false, 2, 4);
1014 } else if (id_ == 0x8D) // Arrghus spawn
1015 {
1016 DrawSpriteTile((x * 16), (y * 16), 6, 24, 14);
1017 } else if (id_ == 0x8E) // Terrorpin
1018 {
1019 DrawSpriteTile((x * 16), (y * 16), 14, 24, 12);
1020 }
1021
1022 if (id_ == 0x8F) // Slime
1023 {
1024 DrawSpriteTile((x * 16), (y * 16), 0, 20, 12);
1025 } else if (id_ == 0x90) // Wall master
1026 {
1027 DrawSpriteTile((x * 16), (y * 16), 6, 26, 12);
1028 DrawSpriteTile((x * 16) + 16, (y * 16), 15, 26, 12, false, false, 1, 1);
1029 DrawSpriteTile((x * 16) + 16, (y * 16) + 8, 9, 26, 12, false, false, 1, 2);
1030 DrawSpriteTile((x * 16), (y * 16) + 16, 10, 27, 12, false, false, 1, 1);
1031 DrawSpriteTile((x * 16) + 8, (y * 16) + 16, 8, 27, 12, false, false, 1, 1);
1032 } else if (id_ == 0x91) // Stalfos knight
1033 {
1034 DrawSpriteTile((x * 16) - 2, (y * 16) + 12, 4, 22, 12, false, false, 1, 2);
1035 DrawSpriteTile((x * 16) + 10, (y * 16) + 12, 4, 22, 12, true, false, 1, 2);
1036 DrawSpriteTile((x * 16) - 4, (y * 16) + 4, 1, 22, 12);
1037 DrawSpriteTile((x * 16) + 12, (y * 16) + 4, 3, 22, 12, false, false, 1, 2);
1038 DrawSpriteTile((x * 16), (y * 16) - 8, 6, 20, 12);
1039 } else if (id_ == 0x92) // Helmaking
1040 {
1041 DrawSpriteTile((x * 16), (y * 16) + 32, 14, 26, 14);
1042 DrawSpriteTile((x * 16) + 16, (y * 16) + 32, 0, 28, 14);
1043 DrawSpriteTile((x * 16) + 32, (y * 16) + 32, 14, 26, 14, true);
1044
1045 DrawSpriteTile((x * 16), (y * 16) + 16 + 32, 2, 28, 14);
1046 DrawSpriteTile((x * 16) + 16, (y * 16) + 16 + 32, 4, 28, 14);
1047 DrawSpriteTile((x * 16) + 32, (y * 16) + 16 + 32, 2, 28, 14, true);
1048
1049 DrawSpriteTile((x * 16) + 8, (y * 16) + 32 + 32, 6, 28, 14);
1050 DrawSpriteTile((x * 16) + 24, (y * 16) + 32 + 32, 6, 28, 14, true);
1051 } else if (id_ == 0x93) // Bumper
1052 {
1053 DrawSpriteTile((x * 16), (y * 16), 12, 30, 7);
1054 DrawSpriteTile((x * 16) + 16, (y * 16), 12, 30, 7, true);
1055 DrawSpriteTile((x * 16) + 16, (y * 16) + 16, 12, 30, 7, true, true);
1056 DrawSpriteTile((x * 16), (y * 16) + 16, 12, 30, 7, false, true);
1057 } else if (id_ == 0x95) // Right laser eye
1058 {
1059 DrawSpriteTile((x * 16), (y * 16), 9, 28, 3, true, false, 1, 2);
1060 DrawSpriteTile((x * 16), (y * 16) + 16, 9, 28, 3, true, true, 1, 1);
1061 } else if (id_ == 0x96) // Left laser eye
1062 {
1063 DrawSpriteTile((x * 16) + 8, (y * 16) - 4, 9, 28, 3, false, false, 1, 2);
1064 DrawSpriteTile((x * 16) + 8, (y * 16) + 12, 9, 28, 3, false, true, 1, 1);
1065 } else if (id_ == 0x97) // Right laser eye
1066 {
1067 DrawSpriteTile((x * 16), (y * 16), 6, 28, 3, false, false, 2, 1);
1068 DrawSpriteTile((x * 16) + 16, (y * 16), 6, 28, 3, true, false, 1, 1);
1069 } else if (id_ == 0x98) // Right laser eye
1070 {
1071 DrawSpriteTile((x * 16), (y * 16), 6, 28, 3, false, true, 2, 1);
1072 DrawSpriteTile((x * 16) + 16, (y * 16), 6, 28, 3, true, true, 1, 1);
1073 } else if (id_ == 0x99) {
1074 DrawSpriteTile((x * 16), (y * 16), 6, 24, 12);
1075 DrawSpriteTile((x * 16), (y * 16) - 8, 0, 24, 12);
1076 } else if (id_ == 0x9A) // Water bubble kyameron
1077 {
1078 DrawSpriteTile((x * 16), (y * 16), 10, 24, 6);
1079 } else if (id_ == 0x9B) // Water bubble kyameron
1080 {
1081 DrawSpriteTile((x * 16), (y * 16), 6, 24, 11);
1082 DrawSpriteTile((x * 16), (y * 16) - 8, 2, 27, 11, false, false, 2, 1);
1083 } else if (id_ == 0x9C) // Water bubble kyameron
1084 {
1085 DrawSpriteTile((x * 16), (y * 16), 12, 22, 11);
1086 DrawSpriteTile((x * 16) + 16, (y * 16), 13, 22, 11, false, false, 1, 2);
1087 } else if (id_ == 0x9D) // Water bubble kyameron
1088 {
1089 DrawSpriteTile((x * 16), (y * 16), 14, 21, 11);
1090 DrawSpriteTile((x * 16), (y * 16) - 16, 14, 20, 11, false, false, 2, 1);
1091 } else if (id_ == 0xA1) {
1092 DrawSpriteTile((x * 16) - 8, (y * 16) + 8, 6, 26, 14);
1093 DrawSpriteTile((x * 16) + 8, (y * 16) + 8, 6, 26, 14, true);
1094 } else if (id_ == 0xA2) {
1095 DrawSpriteTile((x * 16), (y * 16) + 8, 0, 24, 14, false, false, 4, 4);
1096 } else if (id_ == 0xA5) {
1097 DrawSpriteTile((x * 16), (y * 16), 0, 26, 10, false, false, 3, 2);
1098 DrawSpriteTile((x * 16) + 4, (y * 16) - 8, 0, 24, 10);
1099 } else if (id_ == 0xA6) {
1100 DrawSpriteTile((x * 16), (y * 16), 0, 26, 8, false, false, 3, 2);
1101 DrawSpriteTile((x * 16) + 4, (y * 16) - 8, 0, 24, 8);
1102 } else if (id_ == 0xA7) {
1103 DrawSpriteTile((x * 16), (y * 16) + 12, 12, 16, 10);
1104 DrawSpriteTile((x * 16), (y * 16), 0, 16, 10);
1105 } else if (id_ == 0xAC) {
1106 DrawSpriteTile((x * 16), (y * 16), 5, 14, 4);
1107 } else if (id_ == 0xAD) {
1108 DrawSpriteTile((x * 16), (y * 16) + 8, 14, 10, 10);
1109 DrawSpriteTile((x * 16), (y * 16), 12, 10, 10);
1110 } else if (id_ == 0xBA) {
1111 DrawSpriteTile((x * 16), (y * 16), 14, 14, 6);
1112 } else if (id_ == 0xC1 || id_ == 0x7A) {
1113 DrawSpriteTile((x * 16), (y * 16) - 16, 2, 24, 12, false, false, 2, 4);
1114 DrawSpriteTile((x * 16) + 16, (y * 16) - 16, 2, 24, 12, true, false, 2, 4);
1115 } else if (id_ == 0xC3) {
1116 DrawSpriteTile((x * 16), (y * 16), 10, 14, 12);
1117 } else if (id_ == 0xC4) {
1118 DrawSpriteTile((x * 16), (y * 16), 0, 18, 14);
1119 DrawSpriteTile((x * 16), (y * 16) - 8, 0, 16, 14);
1120 } else if (id_ == 0xC5) {
1121 } else if (id_ == 0xC6) {
1122 DrawSpriteTile((x * 16) + 4, (y * 16) + 14, 3, 30, 14, false, false, 1, 1);
1123 DrawSpriteTile((x * 16) + 14, (y * 16) + 4, 3, 30, 14, false, false, 1, 1);
1124 DrawSpriteTile((x * 16) + 4, (y * 16) + 2, 1, 31, 14, false, false, 1, 1);
1125 DrawSpriteTile((x * 16) - 6, (y * 16) + 4, 3, 30, 14, false, false, 1, 1);
1126 DrawSpriteTile((x * 16) + 4, (y * 16) - 6, 3, 30, 14, false, false, 1, 1);
1127 } else if (id_ == 0xC7) {
1128 DrawSpriteTile((x * 16), (y * 16), 0, 26, 4);
1129 DrawSpriteTile((x * 16), (y * 16) - 10, 0, 26, 4);
1130 DrawSpriteTile((x * 16), (y * 16) - 20, 0, 26, 4);
1131 DrawSpriteTile((x * 16), (y * 16) - 30, 2, 26, 4);
1132 } else if (id_ == 0xC8) {
1133 DrawSpriteTile((x * 16), (y * 16), 12, 24, 12, false, false, 2, 3);
1134 DrawSpriteTile((x * 16) + 16, (y * 16), 12, 24, 12, true, false, 1, 3);
1135 } else if (id_ == 0xC9) {
1136 DrawSpriteTile((x * 16), (y * 16), 8, 28, 8, false);
1137 DrawSpriteTile((x * 16) + 16, (y * 16), 8, 28, 8, true);
1138 } else if (id_ == 0xCA) {
1139 DrawSpriteTile((x * 16), (y * 16), 8, 10, 10);
1140 } else if (id_ == 0xD0) {
1141 DrawSpriteTile((x * 16), (y * 16), 7, 14, 11, false, false, 3, 2);
1142 DrawSpriteTile((x * 16), (y * 16) - 10, 8, 12, 11);
1143 } else if (id_ == 0xD1) {
1144 DrawSpriteTile((x * 16) + 2, (y * 16) + 8, 7, 13, 11, true, true, 1, 1);
1145 DrawSpriteTile((x * 16) + 8, (y * 16) + 2, 7, 13, 11, true, false, 1, 1);
1146 DrawSpriteTile((x * 16) + 14, (y * 16) + 8, 7, 13, 11, true, true, 1, 1);
1147 DrawSpriteTile((x * 16) + 8, (y * 16) + 14, 7, 13, 11, false, true, 1, 1);
1148 DrawSpriteTile((x * 16) + 8, (y * 16) + 8, 7, 13, 11, false, false, 1,
1149 1); // Middle
1150 // 6,7 / 13
1151 } else if (id_ == 0xD4) {
1152 DrawSpriteTile((x * 16) - 4, (y * 16), 0, 7, 7, false, false, 1, 1);
1153 DrawSpriteTile((x * 16) + 4, (y * 16), 0, 7, 7, true, false, 1, 1);
1154 } else if (id_ == 0xE3) // Fairy
1155 {
1156 DrawSpriteTile((x * 16), (y * 16), 10, 14, 10);
1157 } else if (id_ == 0xE4) // Key
1158 {
1159 DrawSpriteTile((x * 16), (y * 16), 11, 06, 11, false, false, 1, 2);
1160 } else if (id_ == 0xE7) // Mushroom
1161 {
1162 DrawSpriteTile((x * 16), (y * 16), 14, 30, 16);
1163 } else if (id_ == 0xE8) // Fake ms
1164 {
1165 DrawSpriteTile((x * 16) + 4, (y * 16), 4, 31, 10, false, false, 1, 1);
1166 DrawSpriteTile((x * 16) + 4, (y * 16) + 8, 5, 31, 10, false, false, 1, 1);
1167 } else if (id_ == 0xEB) {
1168 DrawSpriteTile((x * 16), (y * 16), 0, 14, 5);
1169 } else if (id_ == 0xF2) {
1170 DrawSpriteTile((x * 16), (y * 16) - 16, 12, 24, 2, false, false, 2, 4);
1171 DrawSpriteTile((x * 16) + 16, (y * 16) - 16, 12, 24, 2, true, false, 2, 4);
1172 } else if (id_ == 0xF4) {
1173 DrawSpriteTile((x * 16), (y * 16), 12, 28, 5, false, false, 4, 4);
1174 } else {
1175 DrawSpriteTile((x * 16), (y * 16), 4, 4, 5);
1176 }
1177
1178 bounding_box_.x = (lower_x_ + (x * 16));
1179 bounding_box_.y = (lower_y_ + (y * 16));
1182}
1183
1184void Sprite::DrawSpriteTile(int x, int y, int srcx, int srcy, int pal,
1185 bool mirror_x, bool mirror_y, int sizex,
1186 int sizey) {
1187 if (current_gfx_.empty()) {
1188 return;
1189 }
1190
1191 // Lazy allocate preview buffer on first use (saves ~1.4MB during load)
1192 if (preview_gfx_.empty()) {
1193 preview_gfx_.resize(64 * 64, 0xFF);
1194 }
1195
1196 // Validate input parameters
1197 if (sizex <= 0 || sizey <= 0) {
1198 return;
1199 }
1200
1201 if (srcx < 0 || srcy < 0 || pal < 0) {
1202 return;
1203 }
1204
1205 x += 16;
1206 y += 16;
1207 int drawid_ = (srcx + (srcy * 16)) + 512;
1208
1209 // Validate drawid_ is within reasonable bounds
1210 if (drawid_ < 0 || drawid_ > 4096) {
1211 return;
1212 }
1213
1214 for (auto yl = 0; yl < sizey * 8; yl++) {
1215 for (auto xl = 0; xl < (sizex * 8) / 2; xl++) {
1216 int mx = xl;
1217 int my = yl;
1218
1219 if (mirror_x) {
1220 mx = (((sizex * 8) / 2) - 1) - xl;
1221 }
1222 if (mirror_y) {
1223 my = ((sizey * 8) - 1) - yl;
1224 }
1225
1226 // Formula information to get tile index position in the array
1227 //((ID / nbrofXtiles) * (imgwidth/2) + (ID - ((ID/16)*16) ))
1228
1229 int tx = ((drawid_ / 0x10) * 0x400) +
1230 ((drawid_ - ((drawid_ / 0x10) * 0x10)) * 8);
1231
1232 // Validate graphics buffer access
1233 int gfx_index = tx + (yl * 0x80) + xl;
1234 if (gfx_index < 0 || gfx_index >= static_cast<int>(current_gfx_.size())) {
1235 continue; // Skip this pixel if out of bounds
1236 }
1237
1238 auto pixel = current_gfx_[gfx_index];
1239 // nx,ny = object position, xx,yy = tile position, xl,yl = pixel
1240 // position
1241 int index = (x) + (y * 64) + (mx + (my * 0x80));
1242
1243 // Validate preview buffer access
1244 if (index >= 0 && index < static_cast<int>(preview_gfx_.size()) &&
1245 index <= 4096) {
1246 preview_gfx_[index] = (uint8_t)((pixel & 0x0F) + 112 + (pal * 8));
1247 }
1248 }
1249 }
1250}
1251
1252} // namespace zelda3
1253} // namespace yaze
bool PreferHMagicNames() const
Get whether Hyrule Magic names are preferred.
std::string GetLabel(ResourceType type, int id) const
Get a label for a resource by type and ID.
void SetPreferHMagicNames(bool prefer)
Set whether to prefer Hyrule Magic sprite names.
std::vector< uint8_t > preview_gfx_
Definition sprite.h:141
void UpdateMapProperties(uint16_t map_id, const void *context=nullptr) override
Update entity properties based on map position.
Definition sprite.cc:324
auto map_x() const
Definition sprite.h:102
std::string name_
Definition sprite.h:140
void DrawSpriteTile(int x, int y, int srcx, int srcy, int pal, bool mirror_x=false, bool mirror_y=false, int sizex=2, int sizey=2)
Definition sprite.cc:1184
std::vector< uint8_t > current_gfx_
Definition sprite.h:142
SDL_Rect bounding_box_
Definition sprite.h:144
void UpdateCoordinates(int map_x, int map_y)
Definition sprite.cc:331
auto y() const
Definition sprite.h:98
auto x() const
Definition sprite.h:97
auto map_y() const
Definition sprite.h:103
const std::string kOverlordNames[26]
Definition sprite.cc:295
const size_t kSpriteNameCount
Definition sprite.cc:292
const std::string kSpriteDefaultNames[256]
Definition sprite.cc:13
const char *const kSpriteNames[]
Definition sprite.cc:291
bool PreferHmagicSpriteNames()
Definition sprite.cc:277
void SetPreferHmagicSpriteNames(bool prefer)
Definition sprite.cc:273
const char * ResolveSpriteName(uint16_t id)
Definition sprite.cc:284
ResourceLabelProvider & GetResourceLabels()
Get the global ResourceLabelProvider instance.