// ======================================================================== // // // // File : enigma_mapping.cpp // // Purpose : // // Time-stamp: // // // // (C) May 2003 by Ralf Westram // // // // Permission to use, copy, modify, distribute and sell this software // // and its documentation for any purpose is hereby granted without fee, // // provided that the above copyright notice appear in all copies and // // that both that copyright notice and this permission notice appear // // in supporting documentation. // // // // Ralf Westram makes no representations about the suitability of this // // software for any purpose. It is provided "as is" without express or // // implied warranty. // // // // ======================================================================== // #include "OxydVersion.h" #include "enigma_mapping.h" #include #include using namespace std; #define CHECK_MAPS namespace { const char *common_floor_map[256] = { "fl-abyss", // 0x00 "fl-gray", // 0x01 "fl-metal", // 0x02 "fl-metal", // 0x03 "fl-metal", // 0x04 "fl-metal", // 0x05 "fl-metal", // 0x06 "fl-metal", // 0x07 "fl-rough", // 0x08 "fl-normal", // 0x09 "fl-normal", // 0x0a "fl-stone", // 0x0b "fl-inverse", // 0x0c 0, // 0x0d black tile 0, // 0x0e white tile "fl-swamp", // 0x0f swamp "fl-swamp", // 0x10 swamp "fl-swamp", // 0x11 swamp "fl-swamp", // 0x12 swamp "fl-water", // 0x13 "fl-water", // 0x14 "fl-water", // 0x15 "fl-water", // 0x16 "fl-ice_001", // 0x17 "fl-ice_001", // 0x18 "fl-ice_001", // 0x19 "fl-ice_001", // 0x1a "fl-ice_001", // 0x1b "fl-space", // 0x1c "fl-space", // 0x1d "fl-space", // 0x1e "fl-space", // 0x1f "fl-space", // 0x20 "fl-space", // 0x21 space force down "fl-space", // 0x22 space force down "fl-gradient1", // 0x23 "fl-gradient2", // 0x24 "fl-gradient3", // 0x25 "fl-gradient4", // 0x26 "fl-gradient5", // 0x27 "fl-gradient6", // 0x28 "fl-gradient7", // 0x29 "fl-gradient8", // 0x2a "fl-gradient9", // 0x2b "fl-gradient10", // 0x2c "fl-gradient11", // 0x2d "fl-gradient12", // 0x2e "fl-gradient13", // 0x2f "fl-gradient14", // 0x30 "fl-gradient15", // 0x31 "fl-gradient16", // 0x32 "fl-rough", // 0x33 "fl-rough", // 0x34 "fl-rough", // 0x35 "fl-rough", // 0x36 "fl-rough", // 0x37 0, // 0x38 0, // 0x39 0, // 0x3a 0, // 0x3b 0, // 0x3c "fl-wood", // 0x3d "fl-wood", // 0x3e "fl-wood", // 0x3f "fl-wood", // 0x40 "fl-wood", // 0x41 0, // 0x42 0, // 0x43 0, // 0x44 0, // 0x45 0, // 0x46 0, // 0x47 0, // 0x48 0, // 0x49 0, // 0x4a 0, // 0x4b 0, // 0x4c 0, // 0x4d 0, // 0x4e 0, // 0x4f 0, // 0x50 0, // 0x51 0, // 0x52 0, // 0x53 0, // 0x54 "fl-plank", // 0x55 0, // 0x56 0, // 0x57 0, // 0x58 0, // 0x59 0, // 0x5a 0, // 0x5b 0, // 0x5c 0, // 0x5d 0, // 0x5e 0, // 0x5f 0, // 0x60 }; const char *common_item_map[256] = { 0, // 0x00 "it-extralife", // 0x01 "it-document", // 0x02 "it-document", // 0x03 "it-hammer", // 0x04 0, // 0x05 0, // 0x06 "it-umbrella", // 0x07 0, // 0x08 0, // 0x09 "it-dynamite", // 0x0a "it-blackbomb", // 0x0b "it-whitebomb", // 0x0c 0, // 0x0d 0, // 0x0e 0, // 0x0f 0, // 0x10 "it-coin1", // 0x11 "it-coin2", // 0x12 "it-coin4", // 0x13 0, // 0x14 0, // 0x15 0, // 0x16 "it-floppy", // 0x17 0, // 0x18 0, // 0x19 0, // 0x1a 0, // 0x1b 0, // 0x1c 0, // 0x1d 0, // 0x1e 0, // 0x1f 0, // 0x20 "it-spade", // 0x21 0, // 0x22 0, // 0x23 "it-seed", // 0x24 "it-spring2", // 0x25 "it-spring1", // 0x26 "it-spring2", // 0x27 "it-magnet", // 0x28 0, // 0x29 0, // 0x2a "it-shogun-s", // 0x2b 0, // 0x2c 0, // 0x2d 0, // 0x2e "it-wormhole", // 0x2f "it-hill", // 0x30 "it-tinyhill", // 0x31 "it-hollow", // 0x32 "it-tinyhollow", // 0x33 0, // 0x34 0, // 0x35 0, // 0x36 0, // 0x37 0, // 0x38 0, // 0x39 0, // 0x3a 0, // 0x3b 0, // 0x3c 0, // 0x3d 0, // 0x3e 0, // 0x3f 0, // 0x40 "it-brush", // 0x41 0, // 0x42 0, // 0x43 "it-brake", // 0x44 0, // 0x45 "it-blocker", // 0x46 "it-magicwand", // 0x47 0, // 0x48 0, // 0x49 0, // 0x4a "it-puller-n", // 0x4b "it-puller-s", // 0x4c "it-puller-w", // 0x4d "it-puller-e", // 0x4e 0, // 0x4f + 0, // 0x50 + activated 0, // 0x51 + pullers 0, // 0x52 + 0, // 0x53 0, // 0x54 0, // 0x55 0, // 0x56 0, // 0x57 0, // 0x58 0, // 0x59 0, // 0x5a 0, // 0x5b 0, // 0x5c 0, // 0x5d 0, // 0x5e 0, // 0x5f 0, // 0x60 0, // 0x61 0, // 0x62 "it-trigger", // 0x63 }; const char *common_stone_map[256] = { 0, 0, // 0x01 0, // 0x02 0, // 0x03 0, // 0x04 0, // 0x05 0, // 0x06 0, // 0x07 0, // 0x08 0, // 0x09 0, // 0x0a 0, // 0x0b 0, // 0x0c 0, // 0x0d 0, // 0x0e 0, // 0x0f 0, // 0x10 "st-fakeoxyd", // 0x11 "st-bluegray", // 0x12 0, // 0x13 0, // 0x14 "st-rock5", // 0x15 0, // 0x16 0, // 0x17 "st-grate1", // 0x18 0, // 0x19 0, // 0x1a 0, // 0x1b "st-rock4", // 0x1c "st-rock3", // 0x1d 0, // 0x1e 0, // 0x1f 0, // 0x20 0, // 0x21 "st-glass", // 0x22 0, // 0x23 0, // 0x24 0, // 0x25 0, // 0x26 0, // 0x27 0, // 0x28 0, // 0x29 0, // 0x2a 0, // 0x2b 0, // 0x2c 0, // 0x2d 0, // 0x2e "st-death", // 0x2f 0, // 0x30 "st-oneway_black-w", // 0x31 "st-oneway_black-e", // 0x32 "st-oneway_black-n", // 0x33 "st-oneway_black-s", // 0x34 "st-oneway_white-w", // 0x35 "st-oneway_white-e", // 0x36 "st-oneway_white-n", // 0x37 "st-oneway_white-s", // 0x38 "st-magic", // 0x39 0, // 0x3a 0, // 0x3b 0, // 0x3c 0, // 0x3d 0, // 0x3e 0, // 0x3f 0, // 0x40 0, // 0x41 0, // 0x42 0, // 0x43 0, // 0x44 0, // 0x45 0, // 0x46 0, // 0x47 0, // 0x48 0, // 0x49 0, // 0x4a 0, // 0x4b 0, // 0x4c 0, // 0x4d 0, // 0x4e 0, // 0x4f 0, // 0x50 0, // 0x51 0, // 0x52 0, // 0x53 0, // 0x54 0, // 0x55 0, // 0x56 0, // 0x57 0, // 0x58 0, // 0x59 0, // 0x5a 0, // 0x5b 0, // 0x5c 0, // 0x5d 0, // 0x5e 0, // 0x5f 0, // 0x60 0, // 0x61 0, // 0x62 0, // 0x63 0, // 0x64 "st-thief", // 0x65 "st-shogun-s", // 0x66 "st-shogun-m", // 0x67 "st-shogun-l", // 0x68 "st-shogun-sml", // 0x69 "st-shogun-ml", // 0x6a "st-shogun-sl", // 0x6b "st-shogun-sm", // 0x6c 0, // 0x6d 0, // 0x6e 0, // 0x6f 0, // 0x70 0, // 0x71 0, // 0x72 "st-door-h", // 0x73 "st-door-v", // 0x74 "st-rock2", // 0x75 0, // 0x76 0, // 0x77 0, // 0x78 0, // 0x79 0, // 0x7a 0, // 0x7b 0, // 0x7c 0, // 0x7d 0, // 0x7e 0, // 0x7f 0, // 0x80 0, // 0x81 0, // 0x82 "st-bolder-n", // 0x83 "st-bolder-s", // 0x84 "st-bolder-w", // 0x85 "st-bolder-e", // 0x86 "st-rock1", // 0x87 0, // 0x88 0, // 0x89 0, // 0x8a 0, // 0x8b 0, // 0x8c 0, // 0x8d "st-rock6", // 0x8e 0, // 0x8f 0, // 0x90 0, // 0x91 0, // 0x92 "st-swap", // 0x93 0, // 0x94 0, // 0x95 "st-rubberband", // 0x96 "st-scissors", // 0x97 0, // 0x98 "st-blocker", // 0x99 "st-grate1", // 0x9a (XXX) 0, // 0x9b 0, // 0x9c 0, // 0x9d "st-turnstile", // 0x9e "st-turnstile-n", // 0x9f "st-turnstile-s", // 0xa0 "st-turnstile-w", // 0xa1 "st-turnstile-e", // 0xa2 }; void patch_mapping(const char **floor_map, const char **item_map, const char **stone_map, OxydVersion version) { /* The object numbers differ slightly between different oxyd versions, so we have to patch the common translation tables. */ switch (version) { case OxydVersion_Oxyd1: floor_map[0x34] = "fl-brick"; floor_map[0x38] = "fl-brick"; floor_map[0x3c] = "fl-rock"; floor_map[0x47] = "fl-gravel"; floor_map[0x53] = "fl-springboard"; item_map[0x22] = "it-spade"; item_map[0x2c] = "it-shogun-s"; item_map[0x36] = "it-springboard"; stone_map[0x12] = "st-rock3"; stone_map[0x1a] = "st-grate1"; stone_map[0x1e] = "st-chameleon"; stone_map[0x1f] = "st-brick"; stone_map[0x20] = "st-rock1"; stone_map[0x23] = "st-woven"; stone_map[0x24] = "st-marble"; stone_map[0x25] = "st-glass1"; stone_map[0x26] = "st-glass3"; stone_map[0x29] = "st-rock3_hole"; // see 0x12 stone_map[0x2b] = "st-wood"; stone_map[0x2c] = "st-switch"; stone_map[0x31] = "st-floppy"; stone_map[0x34] = "st-death"; stone_map[0x35] = "st-death_invisible"; stone_map[0x36] = "st-oneway-w"; stone_map[0x37] = "st-oneway-e"; stone_map[0x38] = "st-oneway-n"; stone_map[0x39] = "st-oneway-s"; stone_map[0x3e] = "st-window"; stone_map[0x3f] = ""; // "st-magic"; stone_map[0x40] = ""; // "st-magic"; stone_map[0x41] = ""; // "st-magic"; // stone_map[0x42] = "st-stoneimpulse"; stone_map[0x44] = "st-laser-n"; stone_map[0x45] = "st-laser-s"; stone_map[0x46] = "st-laser-e"; stone_map[0x57] = "st-puzzle-es"; stone_map[0x58] = "st-puzzle-sw"; stone_map[0x59] = "st-puzzle-nw"; stone_map[0x5a] = "st-puzzle-ne"; stone_map[0x5b] = "st-puzzle-ew"; stone_map[0x5c] = "st-puzzle-ns"; stone_map[0x5d] = "st-puzzle-n"; stone_map[0x5e] = "st-puzzle-s"; stone_map[0x5f] = "st-puzzle-w"; stone_map[0x60] = "st-puzzle-e"; stone_map[0x61] = "st-puzzle-nesw"; stone_map[0x68] = "st-bombs"; stone_map[0x6c] = "st-shogun-s"; stone_map[0x6d] = "st-stoneimpulse"; stone_map[0x6e] = "st-laserswitch"; stone_map[0x75] = "st-rock2"; stone_map[0x76] = "st-invisible"; stone_map[0x86] = "st-rock2_hole"; stone_map[0x8a] = "st-stone1"; stone_map[0x8c] = "st-rock7"; stone_map[0x8e] = "st-yinyang2"; break; case OxydVersion_OxydMagnum: case OxydVersion_OxydMagnumGold: floor_map[0x34] = "fl-brick"; floor_map[0x35] = "fl-brick"; floor_map[0x38] = "fl-brick"; floor_map[0x3c] = "fl-rock"; floor_map[0x53] = "fl-springboard"; item_map[0x25] = "it-seed"; item_map[0x36] = "it-springboard"; item_map[0x4c] = "it-springboard"; stone_map[0x1a] = "st-grate1"; stone_map[0x1f] = "st-brick"; stone_map[0x20] = "st-rock1"; stone_map[0x23] = "st-woven"; stone_map[0x24] = "st-marble"; stone_map[0x25] = "st-glass1"; stone_map[0x26] = "st-glass3"; stone_map[0x27] = "st-glass1"; stone_map[0x2b] = "st-wood"; stone_map[0x2c] = "st-switch"; stone_map[0x2d] = "st-floppy"; stone_map[0x30] = "st-key_a"; stone_map[0x34] = "st-death"; stone_map[0x35] = "st-death_invisible"; stone_map[0x43] = "st-actorimpulse_invisible"; stone_map[0x46] = "st-laser-e"; stone_map[0x68] = "st-bombs"; stone_map[0x6d] = "st-stoneimpulse"; stone_map[0x8a] = "st-stone1"; stone_map[0x8c] = "st-white1"; stone_map[0x8d] = "st-black1"; stone_map[0x8e] = "st-yinyang2"; stone_map[0x93] = "st-yinyang1"; stone_map[0xa4] = "st-stoneimpulse-hollow"; break; case OxydVersion_PerOxyd: floor_map[0x38] = "fl-concrete"; floor_map[0x4c] = "fl-bridge-open"; floor_map[0x5a] = "fl-springboard"; floor_map[0x5b] = "fl-gravel"; item_map[0x18] = "it-flagwhite"; item_map[0x19] = "it-flagblack"; // item_map[0x24] = "it-seed"; // same as common item_map[0x2c] = "it-shogun-l"; item_map[0x36] = "it-springboard"; item_map[0x40] = "it-trigger"; item_map[0x4a] = "it-odometer"; stone_map[0x13] = "st-rock4"; stone_map[0x14] = "st-beads"; stone_map[0x16] = "st-rock7"; stone_map[0x20] = "st-stone2"; stone_map[0x27] = "st-wood"; stone_map[0x28] = "st-switch"; stone_map[0x2b] = "st-fourswitch"; stone_map[0x2c] = "st-switch"; stone_map[0x2d] = "st-floppy"; stone_map[0x29] = "st-switch_black"; stone_map[0x2a] = "st-switch_white"; stone_map[0x2d] = "st-floppy"; stone_map[0x3e] = "st-laser-n"; stone_map[0x3f] = "st-laser-s"; stone_map[0x40] = "st-laser-e"; stone_map[0x41] = "st-mirror-p|"; stone_map[0x42] = "st-mirror-p/"; stone_map[0x43] = "st-mirror-p-"; stone_map[0x44] = "st-mirror-p\\"; stone_map[0x45] = "st-mirror-p|m"; stone_map[0x46] = "st-mirror-p/m"; stone_map[0x47] = "st-mirror-p-m"; stone_map[0x48] = "st-mirror-p\\m"; stone_map[0x49] = "st-mirror-p|t"; stone_map[0x4a] = "st-mirror-p/t"; stone_map[0x4b] = "st-mirror-p-t"; stone_map[0x4c] = "st-mirror-p\\t"; stone_map[0x4d] = "st-mirror-3e"; stone_map[0x4e] = "st-mirror-3n"; stone_map[0x4f] = "st-mirror-3w"; stone_map[0x50] = "st-mirror-3s"; stone_map[0x51] = "st-puzzle-es"; stone_map[0x52] = "st-puzzle-sw"; stone_map[0x53] = "st-puzzle-nw"; stone_map[0x54] = "st-puzzle-ne"; stone_map[0x55] = "st-puzzle-ew"; stone_map[0x56] = "st-puzzle-ns"; stone_map[0x57] = "st-puzzle-n"; stone_map[0x58] = "st-puzzle-s"; stone_map[0x59] = "st-puzzle-w"; stone_map[0x5a] = "st-puzzle-e"; stone_map[0x5b] = "st-puzzle-nesw"; stone_map[0x5c] = "st-puzzle-hollow"; stone_map[0x62] = "st-bombs"; stone_map[0x64] = "st-coinslot"; stone_map[0x6d] = "st-stoneimpulse"; stone_map[0x76] = "st-invisible"; stone_map[0x79] = "st-white1"; stone_map[0x7a] = "st-black1"; stone_map[0x7d] = "st-yinyang1"; stone_map[0x7e] = "st-break_acwhite"; stone_map[0x7f] = "st-break_acblack"; stone_map[0x8c] = "st-rock3"; stone_map[0x91] = "st-rotator-left"; stone_map[0x92] = "st-rotator-right"; stone_map[0x98] = "st-grate3"; stone_map[0x9c] = "st-stone1"; stone_map[0xb7] = "st-easymode"; break; case OxydVersion_OxydExtra: stone_map[0x27] = "st-wood"; stone_map[0x3c] = "st-stoneimpulse"; stone_map[0x76] = "st-invisible"; break; default: fprintf(stderr, "Unknown Oxyd version '%i'\n", int(version)); break; } } #if defined(CHECK_MAPS) /* The following functions check all mappings for useless or invisible entries */ struct tmpMap { const char *floor_map[OxydVersion_Count][256]; const char *item_map[OxydVersion_Count][256]; const char *stone_map[OxydVersion_Count][256]; }; static bool checked = false; static const char *gameName[] = { "Oxyd 1", "Oxyd magnum", "Oxyd magnum gold", "Per.Oxyd", "Oxyd extra", }; void check(const char *what, const char * x_map[OxydVersion_Count][256], const char * common_x_map[256]) { for (int k = 0; k<256; ++k) { { const char *first = x_map[0][k]; bool same = true; for (int i = OxydVersion_First+1; i <= OxydVersion_Last; ++i) { int j = i-OxydVersion_First; const char *curr = x_map[j][k]; if (!first || !curr) { if (first != curr) { same = false; break; } } else if (0 != strcmp(curr, first)) { same = false; break; } } if (same && first) { fprintf(stderr, "%s_map[0x%x] is defined equal for all specialized maps\n", what, k); } } { bool all_defined = true; for (int i = OxydVersion_First+1; i <= OxydVersion_Last; ++i) { int j = i-OxydVersion_First; const char *curr = x_map[j][k]; if (!curr) { all_defined = false; } else { if (common_x_map[k]) { if (0 == strcmp(common_x_map[k], curr)) { fprintf(stderr, "Useless specialization in %s-%s_map[0x%x]\n", gameName[j], what, k); } } } } if (all_defined && common_x_map[k]) { fprintf(stderr, "Invisible entry in common_%s_map[0x%x]\n", what, k); } } } } void check() { // fprintf(stderr, "Checking Oxyd->Enigma mapping..\n"); checked = true; tmpMap *m = new tmpMap; for (int i = OxydVersion_First; i <= OxydVersion_Last; ++i) { int j = i-OxydVersion_First; for (int k = 0; k<256; ++k) { m->floor_map[j][k] = 0; m->item_map[j][k] = 0; m->stone_map[j][k] = 0; } } for (int i = OxydVersion_First; i <= OxydVersion_Last; ++i) { int j = i-OxydVersion_First; patch_mapping(m->floor_map[j], m->item_map[j], m->stone_map[j], OxydVersion(i)); } check("floor", m->floor_map, common_floor_map); check("item", m->item_map, common_item_map); check("stone", m->stone_map, common_stone_map); delete m; } #endif // CHECK_MAPS } namespace enigma_mapping { Mapping::Mapping(OxydVersion version) { #if defined(CHECK_MAPS) if (!checked) check(); #endif // CHECK_MAPS copy (common_stone_map, common_stone_map+256, stone_map); copy (common_item_map, common_item_map+256, item_map); copy (common_floor_map, common_floor_map+256, floor_map); patch_mapping(floor_map, item_map, stone_map, version); } }