#!/usr/bin/perl

my %table = ( 
"000510" => [0x000018, "AAA_geneTablePageNr"],
"2ccd88" => [0x03c7f0, "M-class-planet"],
"0c4589" => [0x000018, "__array_index"],
"0c45a1" => [0x000018, "__array_value"],
"0c45e9" => [0x000001, "__bool"],
"0c45ea" => [0x000001, "__bool_2"],
"0c45b9" => [0x000030, "__funptr"],
"0c461b" => [0x000001, "__int1"],
"0c4628" => [0x00000c, "__int12"],
"0c4634" => [0x00000c, "__int12_2"],
"0c45eb" => [0x000018, "__int24"],
"0c4603" => [0x000018, "__int24_2"],
"0c4625" => [0x000003, "__int3"],
"0c4640" => [0x000030, "__int48"],
"0c461c" => [0x000009, "__int9"],
"0c4541" => [0x000018, "acc1"],
"0c4559" => [0x000018, "acc2"],
"0c4571" => [0x000018, "acc3"],
"6fce9c" => [0x000b02, "activateAdaptationTree",2],
"6fd99e" => [0x000273, "activateGene",2],
"252fa1" => [0x0006db, "adapter"],
"41b532" => [0x0016ce, "addFunctionsCBF"],
"54b1ba" => [0x000325, "addInts"],
"0ee064" => [0x0a4e1d, "alien-lifeforms"],
"5580c4" => [0x002b42, "anticompressant"],
"65f785" => [0x0003fb, "apple"],
"3c870e" => [0x00372b, "appletree"],
"711dc6" => [0x000048, "apply1_adaptation"],
"719633" => [0x000048, "apply2_adaptation"],
"50599b" => [0x00501b, "babel-survey"],
"6f31b6" => [0x001a83, "balloon"],
"6f08a9" => [0x0002af, "beginRelativeMode"],
"710436" => [0x000258, "bioAdd_adaptation"],
"0c9229" => [0x000588, "bioMorphPerturb"],
"719153" => [0x000498, "bioMul_adaptation"],
"71068e" => [0x0000f0, "bioSucc_adaptation"],
"7103a6" => [0x000090, "bioZero_adaptation"],
"717323" => [0x001ce0, "biomorph_adaptation"],
"7295a1" => [0x000000, "blueZoneStart",1],
"0daedb" => [0x005806, "bmu"],
"0c886b" => [0x000078, "bresenhamArray"],
"0c88e3" => [0x000018, "bresenhamIndex"],
"0c8853" => [0x000018, "bresenhamRadius"],
"6f0e03" => [0x000b28, "bridge"],
"56426f" => [0x001350, "bridge-close"],
"44c262" => [0x0014f0, "bridge-far"],
"3fdd8a" => [0x00362e, "cachedFastCircle"],
"544d6f" => [0x000eb0, "cachedFastCorner"],
"45e69e" => [0x00b1af, "cachedFastEllipse"],
"5706a4" => [0x001365, "caravan"],
"5a58e9" => [0x00067d, "caravan-axis"],
"56f483" => [0x00062f, "caravan-door"],
"6ee1ca" => [0x0026c7, "caravan-frame"],
"2abe9c" => [0x000d07, "caravan-wheel"],
"1ad921" => [0x000a62, "caravan-window1"],
"23d82a" => [0x000b34, "caravan-window2"],
"21edd5" => [0x006022, "cargobox"],
"71ba1d" => [0x000048, "caseNat_adaptation"],
"7163ca" => [0x000048, "casePair_adaptation"],
"72954c" => [0x000048, "casePictureDescr_adaptation"],
"713860" => [0x000048, "caseVar1_adaptation"],
"70d83c" => [0x000048, "caseVar2_adaptation"],
"0ca12a" => [0x0005a0, "cbfArray"],
"0c86eb" => [0x000030, "charColorCallback"],
"0c871b" => [0x000030, "charColorCallbackFade"],
"0c8d00" => [0x000018, "charCounter"],
"0c8d30" => [0x0004b0, "charIndexArray"],
"0c8d18" => [0x000018, "charIndexOffset"],
"079e9f" => [0x000046, "charInfo_Tempus-Bold-Huge_ "],
"079ee5" => [0x000a96, "charInfo_Tempus-Bold-Huge_L"],
"07a97b" => [0x000e51, "charInfo_Tempus-Bold-Huge_M"],
"3e9f1a" => [0x000868, "checkIntegrity"],
"21bcc7" => [0x000d15, "checksum"],
"541d0e" => [0x003049, "chick"],
"652673" => [0x0006bf, "cloak-night"],
"309590" => [0x03484d, "cloak-rain"],
"0c97b2" => [0x000960, "closureArguments"],
"0ca112" => [0x000018, "closureIndex"],
"60fea4" => [0x001962, "cloud"],
"5c909f" => [0x000bc1, "clouds"],
"0c97b1" => [0x000001, "cloudy"],
"23adf8" => [0x000172, "colorBlack"],
"25f3c4" => [0x000172, "colorBlue"],
"1a4e72" => [0x00064a, "colorByIndex"],
"3c8584" => [0x000172, "colorCyan"],
"0d92ad" => [0x000596, "colorDuckBrown"],
"3c674c" => [0x0001f4, "colorDuckOrange"],
"6d730d" => [0x000208, "colorDuckYellow"],
"65e3c5" => [0x000244, "colorGermanyYellow"],
"35cd8d" => [0x000172, "colorGreen"],
"23d434" => [0x0003de, "colorLila"],
"5c64e9" => [0x000172, "colorMagenta"],
"3cbe51" => [0x000172, "colorRed"],
"0c86ea" => [0x000001, "colorReset"],
"5c9c78" => [0x0002b2, "colorSoftYellow"],
"0c874b" => [0x0000f0, "colorTable"],
"58dfcb" => [0x000172, "colorWhite"],
"7113a4" => [0x000048, "compose_adaptation"],
"1a5b73" => [0x007d96, "contest-1998"],
"34da12" => [0x00d1d3, "contest-1999"],
"5655d7" => [0x009e94, "contest-2000"],
"54ecfa" => [0x0093b2, "contest-2001"],
"24748b" => [0x009bc7, "contest-2002"],
"23eb4e" => [0x008925, "contest-2003"],
"2ad4aa" => [0x00935b, "contest-2004"],
"0cc21e" => [0x00ae91, "contest-2005"],
"435804" => [0x0095f5, "contest-2006"],
"2084f9" => [0x00b052, "contest-2007"],
"5b7bf3" => [0x00e8de, "correctErrors"],
"0c65a8" => [0x001800, "cosineArray"],
"4e151b" => [0x0011d8, "cow-body"],
"6d752d" => [0x001234, "cow-head"],
"6d368f" => [0x00090e, "cow-holy"],
"6395fd" => [0x000ee8, "cow-left-eye"],
"3e917e" => [0x000d84, "cow-left-foot"],
"25f54e" => [0x0009c8, "cow-left-horn"],
"263b5e" => [0x000c80, "cow-middle-foot"],
"207b0f" => [0x0009d2, "cow-mouth"],
"519eaf" => [0x000b38, "cow-right-ear"],
"5a8550" => [0x000db0, "cow-right-eye"],
"239ff4" => [0x000dec, "cow-right-foot"],
"0cb990" => [0x000876, "cow-right-horn"],
"4013d0" => [0x000b34, "cow-spot-butt"],
"23e376" => [0x0007c0, "cow-spot-left"],
"0d985b" => [0x000b34, "cow-spot-middle"],
"0da3a7" => [0x000b34, "cow-spot-middle-ecc",1],
"44b85b" => [0x0006bc, "cow-spot-right"],
"4aa77d" => [0x00145c, "cow-tail"],
"0c0f1d" => [0x0006c0, "crackChars"],
"5c6673" => [0x002a14, "crackKey"],
"6c9469" => [0x001616, "crackKeyAndPrint"],
"0c0f05" => [0x000018, "crackTestValue"],
"592c81" => [0x001c97, "crater"],
"4d9d2e" => [0x005002, "crypt"],
"0c4670" => [0x000018, "curX"],
"0c4688" => [0x000018, "curY"],
"4d9966" => [0x0003b0, "div2"],
"000058" => [0x000001, "doSelfCheck"],
"65c06a" => [0x0009f6, "drawChar"],
"268004" => [0x000965, "drawCircleFast"],
"25e401" => [0x0003cf, "drawCornerFast"],
"6f1943" => [0x00185b, "drawEllipse"],
"6d8a8c" => [0x001fd1, "drawEllipseFast"],
"45bfd1" => [0x0026b5, "drawFunctionBase"],
"7289d2" => [0x0000f0, "drawGoldFishL_adaptation"],
"7287f2" => [0x0000f0, "drawGoldFishR_adaptation"],
"71c537" => [0x000138, "drawGoldenFish_adaptation"],
"44d76a" => [0x000b78, "drawGradientCornerNW"],
"591deb" => [0x000e7e, "drawGradientCornerSE"],
"56faca" => [0x000bc2, "drawGradientH"],
"21c9f4" => [0x000bd6, "drawGradientV"],
"282970" => [0x00223b, "drawGrassPatch"],
"5324da" => [0x000a9a, "drawHexDigit"],
"452999" => [0x000f94, "drawIntHex"],
"5a5f7e" => [0x001b95, "drawPolyline"],
"65e621" => [0x00114c, "drawPolylinePolar"],
"21d5e2" => [0x0017db, "drawRect"],
"35abfd" => [0x002178, "drawRoundedRect"],
"239a6d" => [0x00056f, "drawString"],
"6ed9c0" => [0x0007f2, "drawStringHere"],
"033964" => [0x000001, "ducksShown"],
"61181e" => [0x001962, "duolc",1],
"0c7da8" => [0x000018, "ellipseAngleIncr"],
"71cf3f" => [0x0000f0, "emptyBox_adaptation"],
"033963" => [0x000001, "enableBioMorph"],
"71c4ef" => [0x000048, "enableBioMorph_adaptation"],
"2bbf0c" => [0x0003a7, "endRelativeMode"],
"58e155" => [0x001985, "endo"],
"3c6958" => [0x001c14, "endo-bottom"],
"0ca6fa" => [0x00127e, "endo-left-arm"],
"0e06f9" => [0x001124, "endo-left-eye"],
"262ab6" => [0x001090, "endo-right-arm"],
"3f9b23" => [0x001088, "endo-right-eye"],
"2cbf74" => [0x000dfc, "endo-top"],
"546d07" => [0x00449b, "endocow"],
"58fc7c" => [0x000f14, "fadingColors"],
"6ffa31" => [0x000700, "false",2],
"409142" => [0x00515f, "fastForward"],
"2647f6" => [0x00108e, "fastRandom"],
"226492" => [0x001548, "fatalError"],
"224fb1" => [0x0014c9, "flower"],
"45acb4" => [0x001305, "flowerbed"],
"0c88fc" => [0x000404, "fontCombinator"],
"0aa059" => [0x002400, "fontTable_Bird-Ring"],
"033965" => [0x002400, "fontTable_Cyperus"],
"0566b5" => [0x002400, "fontTable_Cyperus-Big"],
"044bdf" => [0x002400, "fontTable_Cyperus-Italic"],
"0a1ac3" => [0x002400, "fontTable_Dots"],
"094fdb" => [0x002400, "fontTable_Messenger"],
"077a9f" => [0x002400, "fontTable_Tempus-Bold-Huge"],
"07b7cc" => [0x002400, "fontTable_Tempus-Small"],
"088b2d" => [0x002400, "fontTable_Tempus-Small-Italic"],
"1af076" => [0x0010cc, "fpForward"],
"545c37" => [0x0010b8, "fpForwardPenUp"],
"5a9318" => [0x0004a8, "fpMoveAbsolute"],
"4a9798" => [0x000c74, "fpPop"],
"6daa75" => [0x000853, "fpPush"],
"0edcfb" => [0x000351, "fpTurnLeft"],
"6f0b70" => [0x00027b, "fpTurnRight"],
"0c7dd8" => [0x000009, "fri"],
"0c7de1" => [0x000009, "frj"],
"71aaf1" => [0x000048, "fromNat_adaptation"],
"0c7dea" => [0x000900, "frs"],
"7107de" => [0x000048, "fstP_adaptation"],
"434308" => [0x0014e4, "functionAdd"],
"5a7b2b" => [0x000a0d, "functionParabola"],
"1ae39b" => [0x000cc3, "functionSine"],
"3d67ae" => [0x0129b8, "fuundoc1"],
"2279f2" => [0x012063, "fuundoc2"],
"40ee09" => [0x00bccc, "fuundoc3"],
"35cf17" => [0x0047d2, "ge"],
"2677de" => [0x00080e, "germanColors"],
"00005d" => [0x000480, "giveMeAPresent"],
"71c66f" => [0x0008d0, "goldenFish_adaptation"],
"2812c9" => [0x000c78, "goldfishLeft"],
"40e2b9" => [0x000b38, "goldfishRight"],
"000501" => [0x000009, "goodVibrations"],
"25da00" => [0x0009e9, "grass"],
"532f8c" => [0x000c72, "grass1"],
"4a8b3f" => [0x000c41, "grass2"],
"23af82" => [0x000d62, "grass3"],
"3fd02f" => [0x000d43, "grass4"],
"000000" => [0x000000, "greenZoneStart"],
"726636" => [0x000048, "height_adaptation"],
"2bc2cb" => [0x00c0eb, "help-activating-genes"],
"197686" => [0x00d7d4, "help-adaptive-genes"],
"590ba8" => [0x00122b, "help-background"],
"44e2fa" => [0x001e83, "help-background'"],
"0e5d10" => [0x007e2d, "help-beautiful-numbers"],
"033933" => [0x000018, "help-beautiful-numbers_purchase_code"],
"533c16" => [0x008e94, "help-catalog-page"],
"572530" => [0x0079e5, "help-compression-rna"],
"5a97d8" => [0x00aa8d, "help-encodings"],
"42ccf3" => [0x006ed8, "help-error-correcting-codes"],
"033903" => [0x000018, "help-error-correcting-codes_purchase_code"],
"6db2e0" => [0x0126c8, "help-fuun-security"],
"401f1c" => [0x00720e, "help-fuun-structure"],
"4abbf1" => [0x0097f2, "help-initial-cond"],
"43f9ce" => [0x004aac, "help-integer-encoding"],
"361701" => [0x0648f7, "help-intro"],
"5ca81e" => [0x006ffd, "help-lsystems"],
"655a6a" => [0x0065e8, "help-palindromes"],
"579f2d" => [0x00e2e7, "help-patching-dna"],
"469865" => [0x03f2c2, "help-steganography"],
"2b681d" => [0x0056d7, "help-undocumented-rna"],
"613180" => [0x0078e9, "help-virus"],
"594930" => [0x006b41, "help-vmu"],
"0004e4" => [0x000018, "helpScreen"],
"03346a" => [0x000001, "hillsEnabled"],
"000528" => [0x032f3c, "hitWithTheClueStick"],
"716e41" => [0x000048, "i_adaptation"],
"6d690c" => [0x0009e9, "impdoc-background"],
"1f9e38" => [0x00cee7, "impdoc1"],
"4ded48" => [0x00173b, "impdoc10"],
"4f2c6f" => [0x00eb39, "impdoc2"],
"61ba6c" => [0x0181e9, "impdoc3"],
"4b53fb" => [0x0178eb, "impdoc4"],
"50b88b" => [0x00e60c, "impdoc5"],
"4e345c" => [0x00f7fb, "impdoc6"],
"41e665" => [0x00e676, "impdoc7"],
"33ddf5" => [0x00fc05, "impdoc8"],
"268981" => [0x00efdf, "impdoc9"],
"23ca0e" => [0x000a0e, "init"],
"0c88fb" => [0x000001, "initDone"],
"451146" => [0x00183b, "initFastRandom"],
"6fc928" => [0x000574, "intBox",2],
"6ff34f" => [0x0006e2, "k",2],
"4d730e" => [0x002640, "lambda-id"],
"41af00" => [0x00061a, "lightningBolt"],
"0ca6ca" => [0x000018, "lindenmayerAngle"],
"0ca6e2" => [0x000018, "lindenmayerDistance"],
"50a9ce" => [0x000ea5, "lsystem-kochisland"],
"192e99" => [0x0047d5, "lsystem-kochisland-F"],
"5b6aa6" => [0x001135, "lsystem-kochisland-f"],
"4aa424" => [0x000341, "lsystem-sierpinski"],
"54df69" => [0x000d79, "lsystem-sierpinski-l"],
"277978" => [0x000d79, "lsystem-sierpinski-r"],
"65fb98" => [0x000341, "lsystem-weed"],
"25ff2e" => [0x002b70, "lsystem-weed-F"],
"53cac2" => [0x0047d1, "lt"],
"63a4fd" => [0x01303b, "main"],
"6f8481" => [0x001968, "majorimp-background"],
"444492" => [0x0073b1, "majorimp-episode1"],
"278e22" => [0x0061bc, "majorimp-episode125"],
"3cbfdb" => [0x007b8e, "majorimp-episode126"],
"55ac1e" => [0x009639, "majorimp-episode2"],
"253694" => [0x0095f5, "majorimp-episode222"],
"6caa97" => [0x008be0, "majorimp-episode285"],
"453c7d" => [0x00701f, "majorimp-episode496"],
"6d8779" => [0x0002fb, "makeDarkness"],
"1a54d4" => [0x000687, "max"],
"71e2dc" => [0x000048, "mkAbove_adaptation"],
"71e36c" => [0x000048, "mkBeforeAbove_adaptation"],
"71e324" => [0x000048, "mkEmp_adaptation"],
"71e294" => [0x000048, "mkGoldfishL_adaptation"],
"71e24c" => [0x000048, "mkGoldfishR_adaptation"],
"71aaa9" => [0x000048, "mkPair_adaptation"],
"71910b" => [0x000048, "mkSucc_adaptation"],
"7195eb" => [0x000048, "mkZero_adaptation"],
"5b427d" => [0x002811, "mlephant"],
"633c6d" => [0x005978, "modInts"],
"3fabc3" => [0x000984, "moon"],
"5d1833" => [0x03e659, "most-wanted"],
"2c8aff" => [0x00345d, "motherDuck"],
"25cca1" => [0x000d47, "motherDuckWithChicks"],
"5412ab" => [0x000a4b, "moveTo"],
"251ba8" => [0x0013e1, "moveToPolar"],
"0e1835" => [0x0044c3, "mulInts"],
"5017c0" => [0x0041c3, "mulModInts"],
"44bf2f" => [0x00031b, "negateInt"],
"00050f" => [0x000001, "night-or-day"],
"59b489" => [0x00a448, "ocaml"],
"0c9228" => [0x000001, "ocamlrules"],
"0c46a0" => [0x000018, "originStackIndex"],
"0c46b8" => [0x0001e0, "originStackX"],
"0c4898" => [0x0001e0, "originStackY"],
"281f59" => [0x0009ff, "parabolaCBF"],
"43ee11" => [0x00030b, "payloadBioMorph"],
"71ba65" => [0x000048, "payloadBioMorph_adaptation"],
"278709" => [0x000701, "pear"],
"58822c" => [0x00372b, "peartree"],
"71e3b4" => [0x000048, "pictureDescrRenderer_adaptation"],
"71e3fc" => [0x00b15a, "pictureDescrRendererCode_adaptation"],
"0c91e0" => [0x000018, "polarAngleIncr"],
"54b4f7" => [0x002a5a, "printCharSet"],
"284bc3" => [0x0272c1, "printGeneTable"],
"2acbbb" => [0x0008d7, "randomInt"],
"52df43" => [0x000834, "resetOrigin"],
"7288e2" => [0x0000f0, "resetOrigin_adaptation"],
"450195" => [0x000f99, "river"],
"0c883b" => [0x000018, "rotateColorVar"],
"716412" => [0x000048, "s_adaptation"],
"4cccfe" => [0x00a5f8, "scenario"],
"0c7dc0" => [0x000018, "seed"],
"6607e7" => [0x068c6a, "selfCheck"],
"65ca78" => [0x001935, "setFastCircleArray"],
"0edb55" => [0x00018e, "setGlobalPolarRotation"],
"571a21" => [0x000af7, "setOrigin"],
"728ac2" => [0x000048, "setOrigin_adaptation"],
"0c15dd" => [0x002f64, "shoutOut"],
"0c4da8" => [0x001800, "sineArray"],
"4e049b" => [0x001068, "sineCBF"],
"58b96f" => [0x001325, "sky"],
"2c83ce" => [0x000719, "sky-day"],
"6f9e01" => [0x000ba3, "sky-day-bodies"],
"61aa81" => [0x000fd3, "sky-night"],
"4e270b" => [0x000d39, "sky-night-bodies"],
"3fb55f" => [0x001ab8, "sky-waves"],
"0d70c7" => [0x0021ce, "smoke"],
"712c9a" => [0x000048, "sndP_adaptation"],
"6f4c51" => [0x002a79, "spirograph"],
"6f76e2" => [0x000d87, "star"],
"1b015a" => [0x049cc6, "sticky"],
"21b66f" => [0x000640, "stringLength"],
"41aaed" => [0x0003fb, "subInts"],
"206d37" => [0x0006e0, "sun"],
"20742f" => [0x0006e0, "sunflower",1],
"52e78f" => [0x003d33, "superDuck"],
"6d3fb5" => [0x00293f, "surfaceTransform"],
"224e0f" => [0x00018a, "terminate"],
"71d02f" => [0x000048, "threeFish_adaptation"],
"0c91f8" => [0x000018, "tmpCurX"],
"0c9210" => [0x000018, "tmpCurY"],
"3ea79a" => [0x00f371, "transmission-buffer"],
"700131" => [0x0006e2, "true",2],
"27eff6" => [0x0022bb, "tulip"],
"3d3b81" => [0x002c15, "tulips"],
"0c4a78" => [0x000018, "turtleFPX"],
"0c4a90" => [0x000018, "turtleFPY"],
"0c4aa8" => [0x000018, "turtleHeading"],
"0c4ad8" => [0x0000f0, "turtleStackFPX"],
"0c4bc8" => [0x0000f0, "turtleStackFPY"],
"0c4cb8" => [0x0000f0, "turtleStackHeading"],
"0c4ac0" => [0x000018, "turtleStackIndex"],
"652d4a" => [0x002d08, "ufo"],
"43f134" => [0x000882, "ufo-bottom"],
"25106a" => [0x000b26, "ufo-cup"],
"25e7e8" => [0x000bc4, "ufo-frame"],
"65fef1" => [0x0008de, "ufo-left-foot"],
"3c6010" => [0x000724, "ufo-middle-foot"],
"5c9f42" => [0x0008c4, "ufo-right-foot"],
"433be3" => [0x00070d, "ufo-with-smoke"],
"41cc18" => [0x001a35, "useColorTable"],
"71077e" => [0x000060, "var1_adaptation"],
"712c3a" => [0x000060, "var2_adaptation"],
"23bcfc" => [0x000cfa, "vmu"],
"213563" => [0x0080f4, "vmu-code"],
"03391b" => [0x000018, "vmu-code_purchase_code"],
"03346b" => [0x000018, "vmuMode"],
"033483" => [0x000480, "vmuRegCode"],
"6fa9bc" => [0x000273, "void",2],
"52d361" => [0x000bca, "water"],
"03394b" => [0x000018, "weather"],
"64d550" => [0x00510b, "weeds"],
"26589c" => [0x001f2a, "whale"],
"723817" => [0x000048, "width_adaptation"],
"51a9ff" => [0x01294a, "windmill"],
"7286ea" => [0x000108, "wrapAdd_adaptation"],
"6fea1f" => [0x0003fd, "wrapImp",2],
"72652e" => [0x000108, "wrapMax_adaptation"],
"719003" => [0x000108, "wrapSub_adaptation"],


"6fac2f" => [0x001cf9, "adapter_6fac2f",2],
"6fdc11" => [0x000121, "adapter_6fdc11",2],
"6fdd32" => [0x000372, "adapter_6fdd32",2],
"6fe0a4" => [0x000372, "adapter_6fe0a4",2],
"6fe416" => [0x000609, "adapter_6fe416",2],
"6fee1c" => [0x000533, "adapter_6fee1c",2],
"700813" => [0x00052b, "adapter_700813",2],
"700d3e" => [0x00099e, "adapter_700d3e",2],
"7016dc" => [0x000716, "adapter_7016dc",2],
"701df2" => [0x0006ff, "adapter_701df2",2],
"7024f1" => [0x000cdd, "adapter_7024f1",2],
"7031ce" => [0x001188, "adapter_7031ce",2],
"704356" => [0x0010d0, "adapter_704356",2],
"705426" => [0x0010d2, "adapter_705426",2],
"7064f8" => [0x001e91, "adapter_7064f8",2],
"708389" => [0x001e91, "adapter_708389",2],
"70a21a" => [0x001e91, "adapter_70a21a",2],
"70c0ab" => [0x000716, "adapter_70c0ab",2],
"70c7c1" => [0x0006ff, "adapter_70c7c1",2],
"70cec0" => [0x00097c, "adapter_70cec0",2],

"70d884" => [0x000adc, "adapter_70d884",2],
"70e360" => [0x000048, "adapter_70e360"],
"70e3a8" => [0x001526, "adapter_70e3a8",2],
"70f8ce" => [0x000048, "adapter_70f8ec"],
"70f916" => [0x000a90, "adapter_70f916",2],

"710826" => [0x00059d, "adapter_710826",2],
"710dc3" => [0x000048, "adapter_710dc3"],
"710e0b" => [0x000599, "adapter_710e0b",2],

"7113ec" => [0x0009da, "adapter_7113ec",2],
"711e0e" => [0x000e2c, "adapter_711e0e",2],
"712ce2" => [0x00059d, "sndP_implementation",2],
"71327f" => [0x000048, "adapter_71327f"],
"7132c7" => [0x000599, "adapter_7132c7",2],
"7138a8" => [0x000adc, "caseVar1_implementation",2],
"714384" => [0x000048, "adapter_714384"],
"7143cc" => [0x001526, "adapter_7143cc",2],
"7158f2" => [0x000048, "adapter_7158f2"],
"71593a" => [0x000a90, "adapter_71593a",2],

"71645a" => [0x0009e7, "adapter_71645a",2],
"716e89" => [0x00049a, "adapter_716e89",2],
"71967b" => [0x00142e, "adapter_71967b",2],
"71ab39" => [0x000611, "adapter_71ab39",2],
"71b14a" => [0x000048, "adapter_71b14a"],
"71b192" => [0x00088b, "adapter_71b192",2],

"71baad" => [0x000a42, "adapter_71baad",2],
"71d077" => [0x0011d5, "adapter_71d077",2],

"71e3fc" => [0x002249, "adapter_71e3fc",2],
"720645" => [0x000048, "adapter_720645"],
"72068d" => [0x00112d, "adapter_72068d",2],
"7217ba" => [0x000048, "adapter_7217ba"],
"721802" => [0x0019e2, "adapter_721802",2],
"7231e4" => [0x000048, "adapter_7231e4"],
"72322c" => [0x0005eb, "adapter_72322c",2],

"72385f" => [0x000719, "adapter_72385f",2],
"723f78" => [0x000048, "adapter_723f78"],
"723fc0" => [0x000c7d, "adapter_723fc0",2],
"724c3d" => [0x000048, "adapter_724c3d"],
"724c85" => [0x00090e, "adapter_723c85",2],
"725593" => [0x000048, "adapter_725593"],
"7255db" => [0x000972, "adapter_7255db",2],
"725f4d" => [0x000048, "adapter_725f4d"],
"725f95" => [0x000599, "adapter_725f95",2],

"72667e" => [0x000717, "adapter_72667e",2],
"726d95" => [0x000048, "adapter_726d95"],
"726ddd" => [0x000972, "adapter_726ddd",2],
"72774f" => [0x000048, "adapter_72774f"],
"727797" => [0x000972, "adapter_727797",2],
"728109" => [0x000048, "adapter_728109"],
"728151" => [0x000599, "adapter_728151",2],

"728b0a" => [0x000a42, "adapter_728b0a",2],

	      );
my $offset = 13615;
my $programsize = 7509409;
my $codestart = 0x0ca6fa;

sub asnatfix($$) {
    my $len = $_[1];
    my $n = $_[0];
    my $i;
    my $res ="";
    for ($i = 0; $i < $len-1; $i++) {
	$res .= ($n & 1 ? "C" : "I");
	$n >>=1;
    }
    return $res."P";
}

sub asnat($) {
    my $res = "";
    my $n = $_[0];
    if ($n eq "nat(\d*)") {
	if ($1) {
	    return "(I|C){".($1-1)."}P";
	}
	return "(I|C)*P";
    }
    if ($n =~ /0x(.*)/) {
	$n = hex($1);
    }
    while ($n > 0) {
	$res .= ($n & 1 ? "C" : "I");
	$n >>=1;
    }
    return $res."I*P";
}
sub quote($) {
    my $p = $_[0];
    $p =~ tr/ICFP/CFPI/;
    $p =~ s/I/IC/g;
    return $p;
}

sub aspattern($){
    my $p = quote($_[0]);
    my $res="";
    while ($p) {
	my $oldp = $p;
	if ($p =~ s/^!((0x)?[0-9a-f]+|\[[^\]]*\])//) {
	    $res .= "IP".nat($1);
	}
	if ($p =~ s/^\?([ICFP]+)\.//) {
	    $res .= "IF".$1;
	}
	$res .= "IIP" if ($p =~ s/^<//);
	$res .= "IIC" if ($p =~ s/^>//);
	$res .= "III$1" if ($p =~ s/^r([IFCP]{7})//);
	$res .= $1 if ($p =~ s/^([IFCP]+)//);
	die "illegal pattern $p" if ($p eq $oldp);
    }
    return $res . "IIC";
}

sub astemplate($){
    my $p = quote($_[0]);
    my $res="";
    while ($p) {
	my $oldp = $p;
	if ($p =~ s/^m([0-9]+),([0-9]+)//) {
	    $res .= "IP".nat($1).nat($2);
	}
	if ($p =~ s/^l([0-9]+)//) {
	    $res .= "II[FP]".nat($1);
	}
	$res .= "III$1" if ($p =~ s/r([IFCP]{7})//);
	$res .= $1 if ($p =~ s/^([IFCP]+)//);
	die "illegal pattern $p" if ($p eq $oldp);
    }
    return $res . "IIC";
}

sub encode($) {
    my $p = $_[0];
    while ($p =~ s/([ptn])<([^<>]*)>/
	   $1 eq "p" ? aspattern($2):
	   $1 eq "t" ? astemplate($2):
	   $1 eq "n" ? asnat($2) :"X"
	   /e) {
    }
}

sub nat($) {
    my $dna = $_[0];
    my $nat = 0;
    my $i;
    for ($i = length($dna)-2; $i >= 0; $i--) {
	$nat += $nat;
	$nat ++ if (substr($dna,$i,1) eq "C");
    }
    return $nat;
}

sub consts($) {
    my $dna = $_[0];
    $dna =~ s/IC/I/g;
    $dna =~ tr/ICFP/PICF/;
    return $dna;
}

sub pattern($) {
    my $dna = $_[0];
    my $pattern = "";
    my $lvl = 0;
    my $rna ="";
    while (1) {
	if ($dna =~ s/^([CFP]+)//) {
	    $b = $1; $b =~ tr/CFP/ICF/;
	    $pattern .= $b;
	} elsif ($dna =~ s/^IC//) {
	    $pattern .= "P";
	} elsif ($dna =~ s/^IP//) {
	    my $nat;
	    if ($dna =~ s/^(q*(m\d+_\d+|l\d+))//) {
		$pattern .= "!$1";
	    } elsif ($dna =~ s/^([CI]*P)//) {
		$nat = nat($1);
		$pattern .= "!$nat";
	    } else {
		$pattern .= "![$dna]";
	    }
	} elsif ($dna =~ s/^IF[ICFP]//) {
	    my $search;
	    $dna =~ s/^((IC|[CFP])*)//;
	    $search = consts($1);
	    $pattern .= "?$search.";
	} elsif ($dna =~ s/^IIP//) {
	    $pattern .= "<";
	    $lvl++;
	} elsif ($dna =~ s/^II[CF]//) {
	    return ($pattern,$rna,$dna) if (!$lvl);
	    $lvl--;
	    $pattern .= ">";
	} elsif ($dna =~ s/^III(.{7})//) {
	    $rna .= $1;
	} elsif ($dna =~ s/^(q*m\d+_\d+)//) {
	    $pattern .= $1;
	} elsif ($dna =~ s/^(q*l\d+)//) {
	    $pattern .= $1;
	} else {
	    return ("EARLY_END:$pattern;$dna", $rna, "");
	}
    }
}
sub template($) {
    my $dna = $_[0];
    my $templ = "";
    my $lvl = 0;
    my $rna ="";
    while (1) {
	if ($dna =~ s/^([CFP])//) {
	    $b = $1; $b =~ tr/CFP/ICF/;
	    $templ .= $b;
	} elsif ($dna =~ s/^IC//) {
	    $templ .= "P";
	} elsif ($dna =~ s/^I[FP]//) {
	    my $match, $quote;
	    $dna =~ s/^([CI]*P)//;
	    $quote = nat($1);
	    $dna =~ s/^([CI]*P)//;
	    $match = nat($1);
	    $templ .= "m${match}_${quote}";
	} elsif ($dna =~ s/^IIP//) {
	    my $match;
	    $dna =~ s/^([CI]*P)//;
	    $match = nat($1);
	    $templ .= "l$match";
	} elsif ($dna =~ s/^II[CF]//) {
	    return ($templ,$rna,$dna);
	} elsif ($dna =~ s/^III(.{7})//) {
	    $rna .= $1;
	} elsif ($dna =~ s/^(q*m\d+_\d+)//) {
	    $templ .= "q".$1;
	} elsif ($dna =~ s/^(q*l\d+)//) {
	    $templ .= "q".$1;
	} else {
	    return ("EARLY_END:$templ;$dna", $rna, "");
	}
    }
}

sub xlat($) {
    my $foo = $_[0];
    if ($foo == 0) {
	return " ";
    }
    if ($foo >= 0x41 && $foo <= 0x49) {
	return chr($foo+32);
    }
    if ($foo >= 0x51 && $foo <= 0x59) {
	return chr($foo+25);
    }
    if ($foo >= 0x62 && $foo <= 0x69) {
	return chr($foo+17);
    }
    if ($foo >= 0x81 && $foo <= 0x89) {
	return chr($foo-48-16);
    }
    if ($foo >= 0x91 && $foo <= 0x99) {
	return chr($foo-55-16);
    }
    if ($foo >= 0xa1 && $foo <= 0xa9) {
	return chr($foo-63-16);
    }
    if ($foo >= 0xb0 && $foo <= 0xb9) {
	return chr($foo-0xb0+0x30);
    }
    return "." if ($foo == 11);
    return "(" if ($foo == 13);
    return "+" if ($foo == 14);
    return "!" if ($foo == 15);
    return "&" if ($foo == 16);
    return "*" if ($foo == 28);
    return ")" if ($foo == 29);
    return "-" if ($foo == 32);
    return "," if ($foo == 43);    
    return "_" if ($foo == 45);
    return "?" if ($foo == 47);
    return "`" if ($foo == 57);
    return ":" if ($foo == 58);
    return "#" if ($foo == 59);
    return "'" if ($foo == 61);
    return '"' if ($foo == 63);
    return "" if ($foo == 255);
    return "?$foo.";
}

sub prettyprint($) {
    my $c = $_[0];
    return "false" if ($c eq "F");
    return "true" if ($c eq "P");
    if ($c =~ /^[CI]*P$/) {
	my $len = sprintf("%x",length($c));
	($c,$_) = nat($c);
	return "#$c:$len";
    }
    if ($c =~ /^([CI]{8}P)+$/) {
	my $str = "";
	while ($c =~ s/^([IC]*P)//) {
	    my $nat;
	    ($nat,$_) = nat($1);
	    $str .= xlat($nat);
	}
	return "'$str'";
    }
    if ($c =~ /^([CI]{11}P)+$/) {
	my $poly = "";
	my $comma="";
	while ($c =~ s/^([IC]*P)//) {
	    my $nat;
	    ($nat,$_) = nat($1);
	    $nat -= 2048 if ($nat >= 1024);
	    $poly .= "$comma$nat";
	    $comma=",";
	}
	return "poly($poly)";
    }
    if ($c =~ /^([CI]{23}P)([CI]{23}P)$/) {
	my $addr = $1;
	my $len = $2;
	($addr,$_) = nat($addr);
	($len,$_) = nat($len);
	return "NULL" if ($addr == 0 && $len == 0);
	$addr = lookuplen($addr,$len);
	return "&$addr";
    }
    return $c;
}
sub lookuplen($$) {
    my ($addr,$len) = @_;
    if ($addr >= $programsize) {
	return sprintf("stack_%x:%x",$addr-$programsize,$len);
    }
    $hexaddr = sprintf ("%06x", $addr);
    if ($table{$hexaddr}) {
	$symbol = $table{$hexaddr}[1];
	if ($table{$hexaddr}[0] == $len) {
	    return $symbol;
	} else {
	    return sprintf("$symbol:%x",$len);
	}
    } else {
	return sprintf("%06x:%x",$addr,$len);
    }
}
sub lookup($) {
    my ($addr) = $_[0];
    $hexaddr = sprintf ("%06x", $addr);
    if ($table{$hexaddr}) {
	return $table{$hexaddr}[1];
    } else {
	return "0x$hexaddr";
    }
}

my %rna = ("PIPIIIC" => "bk",
	   "PIPIIIP" => "rd",
	   "PIPIICC" => "gn",
	   "PIPIICF" => "yw",
	   "PIPIICP" => "be",
	   "PIPIIFC" => "ma",
	   "PIPIIFF" => "cn",
	   "PIPIIPC" => "we",
	   "PIPIIPF" => "tt",
	   "PIPIIPP" => "oq",
	   "PIIPICP" => "rs",

	   "PIIIIIP" => "M",  #move
	   "PCCCCCP" => "L",  #turn left
	   "PFFFFFP" => "R",  #turn right

	   "PCCIFFP" => "S",  #start (mark)
	   "PFFICCP" => "E",  #end   (line)
	   "PIIPIIP" => "F",  #fill
	   "PCCPFFP" => "addbmp",
	   "PFFPCCP" => "comp",
	   "PFFICCF" => "clip");
sub rna($) { 
    if ($rna{$_[0]}) {
	return $rna{$_[0]};
    } else { 
	return $_[0];
    }
}


sub analyzeTemplate($$) {
    my ($template, $offset) = @_;
    my ($subpatt, $subtemp);
    my ($rna,$rna1,$rna2);
    my $newtemp ="";
    while ($template =~ /^[ICFP]+/) {
	($subpatt, $rna1, $template) = pattern($template);
	($subtemp, $rna2, $template) = template($template);
	$subpatt = analyzePattern($subpatt, $offset);
	$subtemp = analyzeTemplate($subtemp, $offset);
	$rna = "RNA:$rna1$rna2:" if $rna1 || $rna2;
	$newtemp .= "pt[$rna$subpatt:$subtemp]";
    }
    return $newtemp.$template;
}

sub analyzePattern($$) {
    my ($pattern, $offset) = @_;
    my $newpatt;
    while ($pattern) {
	if ($pattern =~ s/^([ICFP]+)//) {
	    $newpatt .= $1;
	    $offset += length($1);
	} elsif ($pattern =~ s/^([<>]+)//) {
	    $newpatt .= $1;
	} elsif ($pattern =~ s/^!(\d+)//) {
	    my $skip = $1;
	    if ($offset eq "?" || $offset + $skip <= 0 || $offset > 0) {
		$newpatt .= "!$skip";
	    } else {
		$newpatt .= "!".lookup($offset+$skip);
	    }
	    $offset += $skip;
	} elsif ($pattern =~ s/^(\?[ICFP]+\.)//) {
	    $newpatt .= $1;
	    $offset = "?";
	} else {
	    $newpatt .= $pattern;
	    last;
	}
    }
    return $newpatt;
}


#my %patterns = {
#    "p{!nat(!nat(!nat)!nat)}t{m0_0m1_0n{nat24}n{nat24}}
#}

sub disass($$) {
    my ($dna, $start) = @_;
    my $rna1, $rna2;
    my $result = "";
    my $pattern, $template;
    my $length = length($dna);
    my $endoffunc = $start+$length;
    while ($dna) {
	my $pos = $length - length($dna);
	if ($dna eq "CPPPPPPIICIICIICIICIICIICIICIICIICIICCCFIICIICIFFCPICCFPICICFCPICIICIICIIII") {
	    print "END_OF_SUBROUTINE\n";
	    return;
	}

	my $lastrna ="";
	my $rep = 0;
	my $rna = "";
	while ($dna =~ s/^(III([ICFP]{7}))(\1*)//) {
	    my $code = $2;
	    my $rep = length($3)/10;
	    $rna .= rna($code);
	    $rna .= "*".(1+$rep) if $rep;
	    $rna .= " ";
	}
	printf "%06x(%06x):RNA:$rna\n", $start+$pos,$pos
	    if (length("$rna"));
	$pos = $length - length($dna);
	($pattern, $rna1, $dna) = pattern($dna);
	($template, $rna2, $dna) = template($dna);
	printf "RNA:$rna1$rna2\n" if (length("$rna1$rna2"));
	my $newpatt = "";
	my $offset = -length($dna);
	printf "%06x(%06x):", $start+$pos,$pos;

	if ("$pattern:$template" =~ 
   m/^!(\d+)<!(\d+)<!(\d+)>!(\d+)>:m0_0m1_0([IC]{23}P)([IC]{23}P)$/
	    && $1 == length($dna)
	    && $2+$3+$4 == $programsize) {
	    $addr = $2; $len = $3; $retaddr=$5; $retlen=$6;
	    $retaddr = nat($retaddr); 
	    $retlen = nat($retlen);
	    $func = lookuplen($addr,$len);
	    $ret  = sprintf " relayto %06x:%06x", $retaddr,$retlen;
	    $hexaddr = substr($func,0,6);
	    if ($retaddr+$retlen == $endoffunc) {
		$ret = sprintf " goto +%06x", $retaddr-$start;
		if ($retlen == length($dna)) {
		    $ret = "";
		}
		print "       CALL $func$ret\n";
		next;
	    }
	} 
	if ("$pattern:$template" =~ m/^<<!(\d+)>!(\d+)>:m1_0([ICFP]+)m0_0$/
		 && ($1+$2-length($dna)) == $programsize) {
	    $len = length($3) + $1;
	    $const = prettyprint($3);
	    printf "       INITLOCALS $const:%x\n",$len;
	    next;
	} 
	if ("$pattern:$template" =~ m/^<!(\d+)>:m0_0([ICFP]+)$/
		 && ($1-length($dna)) == $programsize) {
	    $len = length($2);
	    $const = prettyprint($2);
	    printf "       INITLOCALS $const:%x\n",$len;
	    next;
	} 
	if ("$pattern:$template" =~ m/^<!(\d+)>!(\d+):m0_0$/
	    && ($1-length($dna)) == $programsize) {
	    $len = $2;
	    printf "       FREELOCALS %x\n",$len;
	    next;
	} 
	if ("$pattern:$template" =~ m/^<<!(\d+)>!(\d+)>:m1_0m0_0$/
		 && ($1+$2-length($dna)) == $programsize) {
	    printf "       RESERVE_STACK %x\n",$1;
	    next;
	} 

	if ("$pattern:$template" =~ 
		 m/^<!(\d+)<!(\d+)>>:IIPIP([IC]*P)IICIIPIP([IC]*P)IICIP([IC]*P)IICIPPCPIPPPIICm0_0m1_0$/
	    && $3==$5) {
	    # <!$3><!$4>!$5:m1_0m0_0
	    my ($destaddr,$srcaddr,$destlen,$srclen);
	    $srcaddr = $1;
	    $srclen = $2;
	    $destlen = $3;
	    $destaddr = $4;
	    $destaddr = nat($destaddr);
	    $destlen  = nat($destlen);
	    if ($srclen == $destlen) {
		$dest = lookuplen($destaddr-length($dna), $destlen);
		$src =  lookuplen($srcaddr- length($dna), $srclen);
		print "       $dest := $src \n";
		next;
	    }
	} 

	if ("$pattern:$template" =~ 
	    m/^<!(\d+)<!(\d+)>>:IIPIP([IC]*P)IICIP([IC]*P)IICIPPPm0_1(C*I)CIICm1_0$/) {
            #<!$3>!$4 m0_0qm0_1$5
	    my $srcaddr = $1;
	    my $srclen = $2;
	    my $destaddr = $3;
	    my $destlen = $4;
	    my $padlen = length($5);
	    $destaddr = nat($destaddr);
	    $destlen  = nat($destlen);
	    if ($srclen+$padlen == $destlen) {
		$dest = lookuplen($destaddr-length($dna), $destlen);
		$src  = lookuplen($srcaddr- length($dna), $srclen+1);
		print "       $dest := zeroextend($src)\n";
		next;
	    }
	}



	if ("$pattern:$template" =~ 
	    m/^<!(\d+)><!(\d+)>:IIPIP([IC]*P)IICIP([IC]*P)IICIPPPm1_1IICm0_0$/
	    && $1 - length($dna) == $programsize) {
	    my $len = $2;
	    my $destaddr = $3;
	    my $destlen = $4;
	    $destaddr = nat($destaddr);
	    $destlen = nat($destlen);
	    if ($len == $destlen) {
		$destaddr = lookuplen($destaddr - length($dna),$destlen);
		print "       POP $destaddr\n";
		next;
	    }
	} 
 	if ("$pattern:$template" =~ 
 	    m/^<!19><!944><\?P.>:m0_0m2_0m1_0$/
	    && substr($dna,0,19) eq "IIPIPIIICCCPIPIIIII" # <!56!32*m2_0...
	    ) {
	    my $compress = substr($dna, 19,944);
	    $dna = substr($dna, 19+944);
	    
	    if ($compress =~ m/IICIIPIPIIIIICPIICIICIPPCPIPPPIPPCPIIC
		#<!56!32*m2_0 ...><!32>:m1_0m0_0m1_0
		# copy RNA generating code.
		IIPIPIIIIICICICPIICIIPIPICIICCICPIICIICIPPCPIPPPIPPCPIIC
		#<!21*32><!178>
		((IPI{19}PIII([ICFP]{7}) # RNA 
		 |I{32}                 # empty slot
		 ){20})
		IPI{10}PIPICICIIICCCPIICIIC #jump end  (!0!906)
		IIPIPCCIICPIICIIPIPIIIICCICCCPIICIIPIFFICIICIIC
		IPPPIPPICPIPPCPIIC
		#<!19><!944><?P>:m0_0m2_0m1_0
		IIPIPIIICCCPIPIIIII                      #see above
		IICIIPIPIIIIICPIICIICIPPCPIPPPIPPCPIIC   #see above
		IIPIPIIIIICICICPIICIIPIPICIICCICPIICIICIPPCPIPPPIPPCPIIC 
		/x) {
		$table = $1;
		print "COMPRESSRNA";
		my %table;
		for ($i = 0; $i < 20; $i++) {
		    $entry = substr($table,$i*32,32);
		    next if ($entry eq "I"x32);
		    my $asnat = "";
		    my $n = $i;
		    while ($n) { $asnat .= ($n & 1) ? "C" : "I"; $n>>=1;}
		    $asnat .= "P";
		    $table{$asnat} = " ".rna(substr($entry,25));
		}
		my $rna = "";
		$dna =~ s/^(.*?P)IICICP//;
		$t = $1;
		$t =~ s'([IC]*P)(\1*)'my $ct = length($2)/length($1);
		                      $table{$1}.($ct ? "*".(1+$ct):"")'ge; #'
                print "$t\n";
	    } else {
		print "MALFORMED COMPRESSS:$compress:\n";
		$dna =~ s/^(.*?P)IICICP//;
		$t = $1;
		$t =~ s/([IC]*P)/nat($1).":"/ge;
		print "${t}20\n";
	    }
	    next;
	}
 	if ("$pattern:$template" =~ 
 	    m/^<!(\d+)!(\d+)><!(\d+)>:m1_0m0_0m1_0$/) {
	    my $skip1 = $1;
	    my $skip2 = $2;
	    my $skip3 = $3;
#	    print "       COPYRNA $skip1+$skip2 $skip3\n";
	    $_ = substr($dna, $skip1+$skip2,$skip3);
	    $dna = $_ . $dna;
	    next;
	}
 	if ("$pattern:$template" =~ 
 	    m/^!(\d+)<!(\d+)><!(\d+)>:m1_0m0_0m1_0$/) {
	    $skip1 = $1;
	    $skip2 = $2;
	    $skip3 = $3;
#	    print "       REORDER3 $skip1 $skip2 $skip3\n";
	    $_ = substr($dna, $skip1+$skip2,$skip3);
	    $dna = $_ . substr($dna,$skip1);
	    next;
	}


	if ("$pattern:$template" =~ 
	    m/^<!(\d+)<!(\d+)>>:IIPIP([CI]*P)IIPIP([CI]*P)IICIICIICCCICCIC([CF]*IC)CCFCCICCICm0_1CICIPPPCCFCCFCICICICCCICFICCICICFICCCFIPPCPIICm1_0$/) {
	    #(!$3(!$4))):IIPIP$5IICIIPIPqm0_1IPm0_0IICIICIPPPIIPCPIPPCPIICm1_0
	    #(!$5)(!qm0_1!m0_0):m0_0l1m1_0
	    $srcaddr=$1;
	    $srclen =$2;
	    $src2addr=$3;
	    $src2len=$4;
	    $skip=$5;
	    $src2addr = nat($src2addr);
	    $src2len = nat($src2len);
	    $skip = consts($skip);
	    $skip = nat($skip);
	    $src1 = lookuplen($srcaddr -length($dna),$srclen);
	    $src2 = lookuplen($src2addr-length($dna),$src2len);
	    $nextinstr = substr($dna, 0, $skip);
	    ($nextpatt, $rna2, $nextinstr) = pattern($nextinstr);
	    ($nexttempl, $rna2, $nextinstr) = template($nextinstr);
#	    print "$nextinstr;$nextpatt:$nexttempl\n";
	    if ($nextinstr eq ""
		&& "$nextpatt:$nexttempl" =~
		m/^<\?P\.>:IIPIPl0IICICIICICCCICCIC([FC]*IC)CCFCPPCFCCICCIC([FC]*IC)CCFCIC([CF]*IC)CCFCICICFICCICICICCFCCFIPPPC*ICIICFm0_0$/) {
		#(!ql0)P:PIIPIP$1IICIFFICIIPIP$2IICIP$3IICIPPCPIPPPICIICm0_0I*P; F
		#F(!$1)?P.(!$2)!$3:m1_0m0_0P ; F sum I*P
		$dest1len = $1;
		$destaddr = $2;
		$destlen  = $3;
		$dest1len = consts($dest1len);
		$dest1len = nat($dest1len);
		$destaddr = consts($destaddr);
		$destaddr = nat($destaddr);
		$destlen = consts($destlen);
		$destlen = nat($destlen);
#		print "DEST: $dest1len $destlen,$destaddr\n";
		if ($destlen == $dest1len+1) {
		    $dna = substr($dna, $skip);
		    $dest = lookuplen($destaddr -length($dna),$destlen);
		    print "       RNA: $rna1$rna2\n" if "$rna1$rna2";
		    print "       $dest := $src1 + $src2\n";
		    next;
		}
	    }
	}

	if ("$pattern:$template" =~ 
	    m/^<!(\d+)><!(\d+)<!(\d+)>>:IIPIP([CI]*P)IIPIP([CI]*P)IICIICIICCCICCICm0_1((CIC(C*)IPPP)+)CCFCIC([FC]*IC)CCFCICICICm1_2CCFIPPCPIICm2_0$/) {
	    
	    #(!$4(!$5)):IIPIPqm0_1IPm0_0IP$6m0_0IICIP$7IICIPPPqm1_2IICm1_0
	    #(!qqm0_1!qm0_0!$6qm0_0)!$9:m0_0qqm1_2

	    my $constlen      = $1;
 	    my $srcaddr       = $2;
 	    my $srclen        = $3;
	    my $arridxaddr    = $4;
	    my $arridxlen     = $5;
	    my $factorcode    = $6;
	    my $arraylen = $9;
	    $arridxaddr = nat($arridxaddr);
	    $arridxlen = nat($arridxlen);
	    $arraylen = consts($arraylen);
	    $arraylen = nat($arraylen);
	    my $arrayaddr = substr($dna,0,$constlen);
	    $arrayaddr = nat($arrayaddr);
	    $dna = substr($dna,$constlen);
	    $src = lookuplen($srcaddr-length($dna),$srclen);
	    $array = lookuplen($arrayaddr-length($dna),$arraylen);
	    $arridx = lookuplen($arridxaddr-length($dna), $arridxlen);
	    $factor = 0;
	    while ($factorcode =~ s/^CIC(C*)IPPP//) {
		$factor += (1<<length($1));
	    }
	    $factor = sprintf("%x",$factor);
	    print "       $array\[$arridx*$factor\] := $src\n";
	    next;
 	} 


#06e95c(000712):       (!24)(!__array_index(!8)):IIPIPICCCICIIICCCIIICIICCIIIP
#IPm1_0PIPIIIm1_0PIIPIPCIICPIICIICIICCCICCICm0_1CCFCICFCCFICCCFCICICICIPCPPCCFIPPCPIICm2_0
#(!$4!qm1_0a

	if ("$pattern:$template" =~ 
	    m/^<!(\d+)><!(\d+)<!(\d+)>>:IIPIP([CI]*P)((IP(I*)m1_0P)+)IIPIP([IC]*P)IICIICIICCCICCICm0_1CCFCIC([FC]*IC)CCFCICICICIPCPPCCFIPPCPIICm2_0$/) {
	    
	    #(!$4!$5qm1_0P(!$8)):IIPIPqm0_1IICIP$9IICIPPPm0_1IICm1_0
	    #(!qqm0_1)!$9:m0_0qm0_1

	    my $constlen      = $1;
 	    my $arridxaddr    = $2;
	    my $arridxlen     = $3+1;
	    my $arrayaddr     = $4;
	    my $factorcode    = $5;
	    my $arraylen      = $8;
	    my $destlen       = $9;
	    $arrayaddr = nat($arrayaddr);
	    $arraylen = nat($arraylen);
	    $destlen = consts($destlen);
	    $destlen = nat($destlen);
	    my $destaddr = substr($dna,0,$constlen);
	    $destaddr = nat($destaddr);
	    $dna = substr($dna,$constlen);
	    $arridx = lookuplen($arridxaddr-length($dna),$arridxlen);
	    $dest = lookuplen($destaddr-length($dna),$destlen);
	    $array = lookuplen($arrayaddr-length($dna),$arraylen);
	    $factor = 0;
	    $factor = sprintf("%x",$factor);
	    while ($factorcode =~ s/^IP(I*)m1_0P//) {
		$factor += (1<<length($1));
	    }
	    $factor = sprintf("%x",$factor);
	    print "       $dest := $array\[$arridx*$factor\]\n";
	    next;
 	} 

	if ("$pattern:$template" =~ 
	    m/^!(\d+):$/) {
	    $dest = $length -length($dna)+$1;
	    printf "       goto +%x\n",$dest;
	    next;
	}

	if ("$pattern:$template" =~ 
	    m/^!(\d+)<!(\d+)([ICFP]+)>:m0_0$/) {
	    $dest = $length -length($dna)+$1;
	    $varaddr = $1+$2-length($dna);
	    $const = $3;
	    $size = length($const);
	    $varaddr = lookuplen($varaddr,$size);
	    $const = prettyprint($const);
	    printf "       if ($varaddr == $const) goto +%x\n",$dest;
	    next;
	}

	if ("$pattern:$template" =~ 
	    m/^<!(\d+)([ICFP]+)>:IP([CI]*P)IICIICm0_0$/) {
	    #!$2:
	    $varaddr = $1-length($dna);
	    $const = $2;
	    $dest = $3;
	    $varlen = length($const);
	    $dest = nat($dest);
	    $dest = $dest+$length-length($dna);
	    $var = lookuplen($varaddr,$varlen);
	    $const = prettyprint($const);
	    printf "       if ($var == $const) goto +%x\n",$dest;
	    next;
	}

	if ("$pattern:$template" =~ 
   m/^<!(\d+)<!(\d+)>>:IP([CI]*P)IIPIP([CI]*P)m0_1IICIICIPPPIICm1_0$/) {
            # !$3<!$4m0_1>:m0_0
	    $src1addr = $1;
	    $srclen   = $2;
	    $skip     = $3;
	    $src2addr = $4;
	    $skip = nat($skip);
	    $src2addr = nat($src2addr);
	    $src2addr += $skip - length($dna);
	    $src1addr -= length($dna);
	    $dest = $skip+$length - length($dna);
	    $src1 = lookuplen($src1addr,$srclen);
	    $src2 = lookuplen($src2addr,$srclen);
	    printf "       if ($src1 == $src2) goto +%x\n",$dest;
	    next;
	}
	if ("$pattern:$template" =~ 
	    m/^<!(\d+)<!(\d+)>>:IIPIP([CI]*P)m0_1IICIICCIC([CF]*IC)CCFCCFIPPPIICm1_0$/) {
            # <!$3m0_1>:IP$4IICIICm0_0
            # !$4:
	    $src2addr = $1;
	    $srclen   = $2;
	    $src1addr = $3;
	    $skip     = $4;
	    $skip = nat(consts($skip));
	    $src1addr = nat($src1addr);
	    $src2addr -= length($dna);
	    $src1addr -= length($dna);
	    $dest = $skip+$length - length($dna);
	    $src1 = lookuplen($src1addr,$srclen);
	    $src2 = lookuplen($src2addr,$srclen);
	    printf "       if ($src1 == $src2) goto +%x\n",$dest;
	    next;
	}


	if ("$pattern:$template" =~ m/^<!(\d+)>:m0_0$/) {
	    $varaddr = $1-length($dna);
	    $varaddr = lookuplen($varaddr,0);
	    print "       $varaddr := :0\n";
	    next;
	}
	if ("$pattern:$template" =~ 
	    m/^<!(\d+)>!(\d+):m0_0([ICFP]+)$/
	    && length($3) == $2) {
	    $addlen = $1;
	    $varaddr = $1-length($dna);
	    $size = $2;
	    $varaddr = lookuplen($varaddr,$size);
	    $const = prettyprint($3);
	    print "       $varaddr := $const\n";
	    next;
	}

	    

	if ("$pattern:$template" =~ 
	    m/^<<(!(\d+))?>!(\d+)>!(\d+):m1_0([ICFP]+)m0_0$/
	    && $2+length($5) == $4) {
	    $addlen = $2;
	    $varaddr = $2+$3-length($dna);
	    $size = $4;
	    $const = prettyprint($5);
	    $varaddr = lookuplen($varaddr,$size);
	    print "       $varaddr := $const\n";
	    next;
	}

	if ("$pattern:$template" =~ m/^<!(\d+)><!(\d+)>:m0_0m1_1$/) {
	    $varaddr = $1-length($dna);
	    $len = $2;
	    $varaddr = lookuplen($varaddr,$len);
	    print "       $varaddr := quote($varaddr)\n";
	    next;
	}

	if ("$pattern:$template" =~ 
	    m/^!(\d+)<!$programsize><!24><!24>(!(\d+))?:IIPIPm1_0IIPIPm2_0IICIICIICIPPPIPPCPIICm0_0$/) {
	    $skip = $1;
	    $popargs = $3;
	    if ($skip = length($dna)) {
		printf "       RETURN %x\n",$popargs;
		next;
	    }
	}
	if ("$pattern:$template" =~ 
	    m/^<!(\d+)<!(\d+)>>:m0_0m1_0$/) {
	    $destaddr = $1;
	    $destlen  = $2;
	    if ($destaddr + $destlen == $endoffunc) {
		$destaddr = sprintf "+%06x", $destaddr-length($dna)-$start;
		print "       GOTO $destaddr\n";
		next;
	    }
	}
	if ("$pattern:$template" =~ 
	    m/^<!(\d+)<!(\d+)>>:IIPIP([CI]*P)IICIIPIPm0_0IP([CI]*P)IICIICIPPPIIPCPIPPCPIICm1_0$/) {
	    #(!$3)(!qm0_0!$4):m0_0l1m1_0
	    $srcaddr=$1;
	    $srclen =$2;
	    $skip=$3;
	    $src2=$4;
	    $skip = nat($skip);
	    $src2 = nat($src2);
	    $src1 = lookuplen($srcaddr -length($dna),$srclen);
	    $nextinstr = substr($dna, 0, $skip);
	    ($nextpatt, $rna2, $nextinstr) = pattern($nextinstr);
	    ($nexttempl, $rna2, $nextinstr) = template($nextinstr);
#	    print "$nextinstr;$nextpatt:$nexttempl\n";
	    if ($nextinstr eq ""
		&& "$nextpatt:$nexttempl" =~
		m/^<\?P\.>:IIPIPl0IICICIICICCCICCIC([FC]*IC)CCFCPPCFCCICCIC([FC]*IC)CCFCIC([CF]*IC)CCFCICICFICCICICICCFCCFIPPPC*ICIICFm0_0$/) {
		#(!ql0)P:PIIPIP$1IICIFFICIIPIP$2IICIP$3IICIPPCPIPPPICIICm0_0I*P; F

		#(!ql0)P:PIIPIP$1IICIFFICIIPIP$2IICIP$3IICIPPCPIPPPICIICm0_0I*P; F
		#F(!$1)?P.(!$2)!$3:m1_0m0_0P ; F sum I*P
		$dest1len = $1;
		$destaddr = $2;
		$destlen  = $3;
		$dest1len = consts($dest1len);
		$dest1len = nat($dest1len);
		$destaddr = consts($destaddr);
		$destaddr = nat($destaddr);
		$destlen = consts($destlen);
		$destlen = nat($destlen);
		$src2 -= (1 << ($destlen-1)) if $src2 >= (1<<($destlen-2));
#		print "DEST: $dest1len $destlen,$destaddr\n";
		if ($destlen == $dest1len+1) {
		    $dna = substr($dna, $skip);
		    $dest = lookuplen($destaddr -length($dna),$destlen);
		    print "       RNA: $rna1$rna2\n" if "$rna1$rna2";
		    print "       $dest := $src1 + #$src2\n";
		    next;
		}
	    }
	}

	if ("$pattern:$template" =~ 
	    m/^<!(\d+)<!(\d+)>>:IIPIP([CI]*P)IIPIP([CI]*P)IICIICIICCCICCIC([FC]*IC)CCFCCICCICm0_1CICIPPPCIC([FC]*IC)CCFCCFCICICICCCICFICCICICFICCCFIPPCPIICm1_0$/) {
	    #(!$3(!$4)):IIPIP$5IICIIPIPqm0_1IPm0_0IP$6IICIICPPPIIPCPIPPCPIICm1_0
	    #(!$5)(!qqm0_1!qm0_0!$6):m0_0l1m1_0
	    $srcaddr=$1;
	    $srclen =$2;
	    $src2addr=$3;
	    $src2len=$4;
	    $skip=$5;
	    $src3=$6;
	    $src2addr = nat($src2addr);
	    $src2len = nat($src2len);
	    $skip = consts($skip);
	    $skip = nat($skip);
	    $src3 = consts($src3);
	    $src3 = nat($src3);
	    $src1 = lookuplen($srcaddr -length($dna),$srclen);
	    $src2 = lookuplen($src2addr-length($dna),$src2len);
	    $nextinstr = substr($dna, 0, $skip);
	    ($nextpatt, $rna2, $nextinstr) = pattern($nextinstr);
	    ($nexttempl, $rna2, $nextinstr) = template($nextinstr);
#	    print "$nextinstr;$nextpatt:$nexttempl\n";
	    if ($nextinstr eq ""
		&& "$nextpatt:$nexttempl" =~
		m/^<\?P\.>:IIPIPl0IICICIICICCCICCIC([FC]*IC)CCFCPPCFCCICCIC([FC]*IC)CCFCIC([CF]*IC)CCFCICICFICCICICICCFCCFIPPPC*ICIICFm0_0$/) {
		#(!ql0)P:PIIPIP$1IICIFFICIIPIP$2IICIP$3IICIPPCPIPPPICIICm0_0I*P; F

		#(!ql0)P:PIIPIP$1IICIFFICIIPIP$2IICIP$3IICIPPCPIPPPICIICm0_0I*P; F
	        #F(!$1)?P.(!$2)!$3:m1_0m0_0P ; F sum I*P
		$dest1len = $1;
		$destaddr = $2;
		$destlen  = $3;
		$dest1len = consts($dest1len);
		$dest1len = nat($dest1len);
		$destaddr = consts($destaddr);
		$destaddr = nat($destaddr);
		$destlen = consts($destlen);
		$destlen = nat($destlen);
#		print "DEST: $dest1len $destlen,$destaddr\n";
		$src3 -= (1 << ($destlen-1)) if $src2 >= (1<<($destlen-2));
		if ($destlen == $dest1len+1) {
		    $dna = substr($dna, $skip);
		    $dest = lookuplen($destaddr -length($dna),$destlen);
		    print "       RNA: $rna1$rna2\n" if "$rna1$rna2";
		    print "       $dest := $src1 + $src2 + #$src3\n";
		    next;
		}
	    }
	}

#2c9939(000e3a):       <!7519017<!24><!24>>:IIPIPCIICIICCICICCCICICIICCCPIICIICCICCCCFCFCCFCFCCFCCCCCCCCCICCCICCICm0_1CCICCICm1_1CCFCCFCCFCICICICCICICFICCCFIPPPCCFCFFCCCFCFFCCFCCFFCFCICCCCFCFCCFCFCCFCCCCCCCCCICIICm2_0

	if ("$pattern:$template" =~
	    m/^<!(\d+)<!24><!24>>:IIPIP([IC]*P)IICIICCIC([CF]*IC)CCICCICm0_1CCICCICm1_1CCFCCFCCFCICICICCICICFICCCFIPPP([CF]{23}IC)([CF]{23}IC)IICm2_0$/) {
#	    && $1 == $programsize + length($dna)) {
	    #<!$2>:IP$3IIPIPqm0_1IIPIPqm1_1IICIICIICIPPPIPPCPIICm0_0IICIC$4$5
	    #!$3<!qqm0_1<!qqm1_1>>:m0_0m1_0 ; !$2;$4$5
	    my ($funcptr, $retaddr,$retlen,$ret);
	    my ($skip);
	    $funcptr = $1;
	    $skip = $3;
	    $retaddr = $4;
	    $retlen  = $5;
	    $stack = $2;
	    $stack = nat($stack);
	    $funcptr = lookuplen($funcptr-length($dna),48);
	    $skip = consts($skip);
	    $skip = nat($skip);
	    $retaddr = consts($retaddr);
	    $retaddr = nat($retaddr);
	    $retlen = consts($retlen);
	    $retlen = nat($retlen);
	    if ($retaddr+$retlen == $endoffunc
		&& $stack - length($dna) == $programsize
		&& $skip == length($dna)) {
		$ret = sprintf " goto +%06x", $retaddr-$start;
		if ($retlen == length($dna)) {
		    $ret = "";
		}
		print "       CALL *$funcptr$ret\n";
		next;
	    }
	}
	
	if ("$pattern:$template" =~
	    m/^<!(\d+)<!(\d+)>>:IIPIP([IC]*P)IPm0_0IIPIP([CI]*P)IICIICIICCCICCIC([FC]*IC)CCFCCICCIC([FC]*IC)CCFCIC([FC]*IC)CCFCICICFICCICICICCCFIPPPIPPCPIICm1_0$/) {
	    #<!$3!qm0_0<!$4>>:IIPIP$5IICIIPIP$6IICIP$7IICIPPCPIPPPIICm0_0m1_0
	    #<!$5><!$6>!$7:m1_0m0_0 ; <qm0_0>

	    my ($ptraddr,$ptrlen, $greenaddr, $retaddr,$retlen,$ret);
	    my ($skip);
	    $ptraddr = $1;
	    $ptrlen = $2;
	    $greenaddr = $3;
	    $ptrwidth = $4;
	    $ptr2width = $5;
	    $destaddr = $6;
	    $destlen = $7;
	    $greenaddr = nat($greenaddr);
	    $ptrwidth = nat($ptrwidth);
	    $ptr2width = consts($ptr2width);
	    $ptr2width = nat($ptr2width);
	    $destaddr = consts($destaddr);
	    $destaddr = nat($destaddr);
	    $destlen = consts($destlen);
	    $destlen = nat($destlen);

	    $ptr = lookuplen($ptraddr - length($dna), $ptrlen);
	    $dest = lookuplen($destaddr - length($dna), $destlen);
	    if ($greenaddr = length($dna)
		&& $ptr2width == $ptrwidth && $ptrwidth==$destlen) {
		print "       $dest := *$ptr\n";
		next
	    }
#3ea393(000479):       <!7510291<!24>>:CCFCCICCICFFCCFFCFCCCFFCCFCFCCFFFICCCFCICCCCFFICCCFCICICFICCICICICCCFIPPPIPPCPIICm1_0
#65c433(0003c9):       <!805617<!24>>:IIPIPIIICCCIICICIIIIIIIIIIIIPIPm0_0IIPIPCIICCCCICCICCPIICIICIICCCICCICFCCFFFFCFFCFFICCCFCCICCICFCCFFCFFCFCFFCCFCFCCFFFICCCFCICFCCFFFFCFFCFFICCCFCICICFICCICICICCCFIPPPIPPCPIICm1_0
	}
	    
	if ("$pattern:$template" =~
	    m/^<!(\d+)><!(\d+)><!(\d+)>:m0_0m2_0m1_0$/) {
	    my $addr = $1;
	    my $left = $2;
	    my $right = $3;
	    $addr = lookuplen($addr - length($dna), $left+$right+1);
	    if ($left < $right) {
		print "       ROR $addr, $left\n";
	    } else {
		print "       ROL $addr, $right\n";
	    }
	    next;
	}

	if ("$pattern:$template" =~
	    m/^<!(\d+)<!(\d+)>>:
	    IIPIP([IC]*P)IP([IC]*P)IIPIP([IC]*P)IICIICIIC
	    CCICCIC([FC]*IC)CCFCCICCIC([FC]*IC)CCICCICIPPPCCFCCFCCFCICICICCICICFICCICICCFICCCFIPPCPIICm0_0m1_0$/x) {
	    #<!$3!$4<!$5>>:IIPIP$6IICIIPIP$7IIPIPm0_0IICIICIICIPPPIPPCPIPPICPIICm1_0 ; qm0_0
	    #<!$6><!$7<!qm0_0>>:m0_0m1_0m2_0 ; qqm0_0

	    my ($ptraddr,$ptrlen, $lenaddr, $lenlen, $ptr2len, $ptr3len);
	    my ($comprfont, $ptr,  $len);
	    $ptraddr = $1;
	    $ptrlen = $2;
	    $ptr2len = $3;
	    $lenaddr = $4;
	    $lenlen = $5;
	    $ptr3len = $6;
	    $comprfont = $7;
	    $ptr2len = nat($ptr2len);
	    $lenaddr = nat($lenaddr);
	    $lenlen = nat($lenlen);
	    $ptr3len = nat(consts($ptr3len));
	    $comprfont = nat(consts($comprfont));
	    $ptr = lookuplen($ptraddr - length($dna),$ptrlen);
	    $len = lookuplen($lenaddr - length($dna), $lenlen);
	    $comprfont = lookuplen($comprfont-length($dna),0);
	    if ($ptr2len == $ptr3len && $ptr2len == $ptrlen) {
		print "       apply $ptr($comprfont : $len)\n";
		next;
	    }
	}


	if ("$pattern:$template" =~ 
	    m/^<!(\d+)><!(\d+)<!(\d+)>>:IFFICPm1_1IIPIP([IC]*P)IICIFFCPICCFPICICFICICCICIIPIP([CI]*P)IICIP([IC]*P)IICIPPCPIPPPIICm0_0m2_0$/
	    && $4 eq $6) {
	    #?PFqm1_0<!2>?IFPICFPPCPPIP<!$4>!2:m1_0m0_0
	    my $skip = $1;
	    my $srcaddr = $2;
	    my $srclen = $3;
	    my $destlen = $4;
	    my $destaddr = $5;
	    $destlen = nat($destlen);
	    $destaddr = nat($destaddr);
	    $dna =~ s/^(.*)IFPICFPPCPPIP//;
	    my $patterns = $1;
	    if ($skip == length($patterns)+13
		&& $patterns =~ m/^(PF.{$srclen}.{$destlen})+$/)
	    {
		my $src  = lookuplen($srcaddr - length($dna), $srclen);
		my $dest = lookuplen($destaddr-length($dna), $destlen);
		print "       $dest := lookup($src)\n";
		print "lookuptbl(";
		my $comma = "";
		while ($patterns =~ s/^PF(.{$srclen})(.{$destlen})//) {
		    print $comma."$1->$2";
		    $comma = ",";
		}
		print ");\n";
		next;
	    }
	}

#21c483(0007bc):       <!125><!0x7295d1<!3>>:IFFICPm1_1IIPIPICPIICIFFCPICCFPICICFICICCICIIPIPCCCICICCCIICCIICICIICCCPIICIPICPIICIPPCPIPPPIICm0_0m2_0
#RNA:IIPFICI

#	if ("$pattern:$template" =~ 
#		 m/^<!(\d+)<!(\d+)>>:(([ICFP]+|m0_0)+)m1_0$/) {
#	    my $subdna=$3;
#	    my $varaddr = sprintf("%06x", $1- length($dna));
#	    my $len = $2;
#	    if ($table{$varaddr}[0] = $len) {
#		$varaddr = $table{$varaddr}[1];
#	    } else {
#		$varaddr = sprintf "$varaddr:%06x",len;
#	    }
#	    print "       VAR $varaddr [\n";
#	    $subdna=~s/m0_0/ICIICCIICIICCCCIICCP/;
#	    disass($subdna,0);
#	    print "       ]\n";
#	    next;
#	}

        $pattern = analyzePattern($pattern, $offset);
        $template = analyzeTemplate($template, $offset);
	print "       $pattern:$template\n";

        if ($pattern =~ /^(<!24>)+/
            && $template =~ /^pt\[.*\]$/) {
            $foo = $pattern;
            while ($foo =~ s/^<!24>//) {
		$pos = $length - length($dna);
                $dna =~ s/([IC]{23}P)//;
		printf "%06x(%06x):", $start+$pos,$pos;
                print "     PARAM: ".lookup(nat($1))."\n";
            }
        }

    }
}

sub ecc($$) { $both = $_[0].$_[1];return "II" if ($both =~ /[ICF]III/ || $both =~ /I[ICF]II/ || $both =~ /II[ICF]I/ || $both =~ /III[ICF]/);return "IC" if ($both =~ /[ICF]CPF/ || $both =~ /I[ICP]PF/ || $both =~ /IC[CFP]F/ || $both =~ /ICP[IFP]/);return "IF" if ($both =~ /[ICF]FCP/ || $both =~ /I[IFP]CP/ || $both =~ /IF[ICP]P/ || $both =~ /IFC[CFP]/);return "IP" if ($both =~ /[ICF]PFC/ || $both =~ /I[CFP]FC/ || $both =~ /IP[IFP]C/ || $both =~ /IPF[ICP]/);return "CI" if ($both =~ /[ICP]IFP/ || $both =~ /C[ICF]FP/ || $both =~ /CI[IFP]P/ || $both =~ /CIF[CFP]/);return "CC" if ($both =~ /[ICP]CCC/ || $both =~ /C[ICP]CC/ || $both =~ /CC[ICP]C/ || $both =~ /CCC[ICP]/);return "CF" if ($both =~ /[ICP]FPI/ || $both =~ /C[IFP]PI/ || $both =~ /CF[CFP]I/ || $both =~ /CFP[ICF]/);return "CP" if ($both =~ /[ICP]PIF/ || $both =~ /C[CFP]IF/ || $both =~ /CP[ICF]F/ || $both =~ /CPI[IFP]/);return "FI" if ($both =~ /[IFP]IPC/ || $both =~ /F[ICF]PC/ || $both =~ /FI[CFP]C/ || $both =~ /FIP[ICP]/);return "FC" if ($both =~ /[IFP]CIP/ || $both =~ /F[ICP]IP/ || $both =~ /FC[ICF]P/ || $both =~ /FCI[CFP]/);return "FF" if ($both =~ /[IFP]FFF/ || $both =~ /F[IFP]FF/ || $both =~ /FF[IFP]F/ || $both =~ /FFF[IFP]/);return "FP" if ($both =~ /[IFP]PCI/ || $both =~ /F[CFP]CI/ || $both =~ /FP[ICP]I/ || $both =~ /FPC[ICF]/);return "PI" if ($both =~ /[CFP]ICF/ || $both =~ /P[ICF]CF/ || $both =~ /PI[ICP]F/ || $both =~ /PIC[IFP]/);return "PC" if ($both =~ /[CFP]CFI/ || $both =~ /P[ICP]FI/ || $both =~ /PC[IFP]I/ || $both =~ /PCF[ICF]/);return "PF" if ($both =~ /[CFP]FIC/ || $both =~ /P[IFP]IC/ || $both =~ /PF[ICF]C/ || $both =~ /PFI[ICP]/);return "PP" if ($both =~ /[CFP]PPP/ || $both =~ /P[CFP]PP/ || $both =~ /PP[CFP]P/ || $both =~ /PPP[CFP]/);warn "wrong ecc $both";return substr($both,0,2);}

sub correctcode($$) {
    my ($data,$ecc) = @_;
    my $result="";
    while ($data =~ s/^(..)//) {
	$dbits = $1;
	$ecc =~ s/^(..)//;
	$result .= ecc($dbits,$1);
    }
    return $result;
}

#{
#    my @codes = qw(IIII ICFP IFCP IPFC
#		   CIFP CCCC CFPI CPIF
#		   FIPC FCIP FFFF FPCI
#		   PICF PCFI PFIC PPPP);
#    my %group = ("I"=>"ICF","C"=>"ICP","F"=>"IFP","P"=>"CFP");
#    my $func = 'sub ecc($$) { $both = $_[0].$_[1];';
#    foreach (@codes) {
#
#	my $pattern = "return \"".substr($_,0,2)."\" if (";
#	my $or = "";
#	for ($i = 0; $i < 4; $i++) {
#	    $pattern .= "$or\$both =~ /".substr($_,0,$i)
#		."[".$group{substr($_,$i,1)}."]".substr($_,$i+1)."/";
#	    $or = " || ";
#	}
#	$pattern .= ");";
#	$func .= $pattern;
#    }
#    $func .= 'die "wrong ecc $both";}';
#    print $func\n";
#}


sub rc4($@) {
    my ($dna,@key) = @_;
    my @S;
    my $j, $i, $t, $out, $keyidx;
    my $dnaout;
    $dna =~ tr/ICFP/0123/;
    for ($i = 0; $i < 256; $i++) {
	$S[$i] = $i;
    }
    $j = 0;
    $keyidx = 0;
    for ($i = 0; $i < 256; $i++) {
	if ($key[$keyidx] == 255) {
	    $keyidx = 0;
	}
	$j = ($j + $S[$i] + $key[$keyidx++]) & 255;
	$t = $S[$i];
	$S[$i] = $S[$j];
	$S[$j] = $t;
    }

    $i = 0;
    $j = 0;
    while (length($dna) >= 4) {
	$i = ($i + 1) & 255;
	$j = ($j + $S[$i]) & 255;
	$t = $S[$i];
	$S[$i] = $S[$j];
	$S[$j] = $t;

	$out = $S[($S[$i] + $S[$j]) & 255];
	$dna =~ s/([0123])([0123])([0123])([0123])//;
	$out ^= ($1 + 4*$2 + 16*$3 + 64*$4);
	$dnaout .= ($out & 3).(($out >>2)&3).(($out >>4)&3).(($out >>6)&3);
    }
    $i = ($i + 1) & 255;
    $j = ($j + $S[$i]) & 255;
    $t = $S[$i];
    $S[$i] = $S[$j];
    $S[$j] = $t;
    $out = $S[($S[$i] + $S[$j]) & 255];
    while (length($dna)) {
	$dna =~ s/([0123])//;
	$dnaout .= (($out & 3) ^ $1);
	$out >>=2;
    }
    $dnaout =~ tr/0123/ICFP/;
    return $dnaout;
}

open DNA, "<endo.dna";
$dna = <DNA>;
close DNA;


# fix cloud with duolc
$dna = substr($dna,0,13615+0x60fea4).reverse(substr($dna, 13615+0x61181e, 0x1962)).substr($dna, 13615+0x60fea4+0x1962);

# decrypt help_beautiful_numbers (key = "laziness")
$beauti = substr($dna,13615+0x0e5d10, 0x07e2d);
$beauti = rc4($beauti,(0x53,0x41,0x69,0x49,0x55,0x45,0x62,0x62,255));
$dna = substr($dna, 0, 13615+0x0e5d10).$beauti.substr($dna,13615+0xe5d10+0x7e2d);
# decrypt help_error_correcting_code (key = "42")
$helpecc = substr($dna,13615+0x042ccf3, 0x6ed8);
$helpecc = rc4($helpecc,(0xb4,0xb2,255));
$dna = substr($dna, 0, 13615+0x042ccf3).$helpecc.substr($dna,13615+0x42ccf3+0x6ed8);
# decrypt vmu-code (key = "OPE")
$vmu = substr($dna,13615+0x213563, 0x80f4);
$vmu = rc4($vmu,(0x96,0x97,0x85,255));
$dna = substr($dna, 0, 13615+0x213563).$vmu.substr($dna,13615+0x213563+0x80f4);

# decrypt caravan (key = "Out_of_Band_II")
$caravan = substr($dna,13615+0x5706a4, 0x1365);
$caravan = rc4($caravan,(0x96,0x64,0x63,45,0x56,0x46,45,0x82,0x41,0x55,0x44,45,0x89,0x89,255));
$dna = substr($dna, 0, 13615+0x5706a4).$caravan.substr($dna,13615+0x5706a4+0x1365);

# decrypt mu
$mu = substr($dna, $offset+0x07a97b,0x000e51);
$mu = rc4($mu, (0x55, 0x56, 0xb1, 0x3c, 0x81, 0x67, 0xb3, 255));
$dna = substr($dna, 0, 13615+0x07a97b).$mu.substr($dna,13615+0x7a97b+0xe51);

$cowspot = correctcode(substr($dna,13615+0x0d985b, 0xb34),
		       substr($dna,13615+0x0da3a7, 0xb34));
$dna = substr($dna,0,13615+0x0d985b).$cowspot
    .substr($dna,13615+0x0d985b+0xb34);

# decrypt cow-tail
$cowtail = substr($dna, $offset+0x4aa77d, 0x00145c);
$cowtail = rc4($cowtail, (0xb9, 0xb5,0xb4,0xb6,255));
$dna = substr($dna, 0, 13615+0x4aa77d).$cowtail.substr($dna,13615+0x4aa77d+0x145c);

$flower = substr($dna,13615+0x224fb1, 0x0006e0);  #0x206d37
$sunflower = substr($dna,13615+0x20742f, 0x0006e0);
$flower =~ tr/ICFP/\0\001\002\003/;
$sunflower =~ tr/ICFP/\0\001\002\003/;
$sunflower ^= $flower;
$sunflower =~ tr/\0\001\002\003/ICFP/;
$dna = substr($dna,0,13615+0x206d37).$sunflower
    .substr($dna,13615+0x206d37+0x6e0);

$helpgenes = substr($dna,13615+0x2bc2cb, 0xc0eb);
$helpgenes =~ tr/ICFP/FPIC/;
$dna = substr($dna,0,13615+0x2bc2cb).$helpgenes
    .substr($dna,13615+0x2bc2cb+0xc0eb);

sub dumpFontTable($) {
    my @fontcombinator = qw(M      S      E    R 
			    L      F      rs   oq
			    tt     we     cn   ma
			    be     yw     gn   rd
			    bk     addbmp comp clip);
    my $start = $_[0];
    my $i;
    for ($i = 0; $i < 0xc0; $i++) {
	my ($entry, $addr,$len);
	$entry = substr($dna, 13615+hex($start)+$i*48, 48);
	if ($entry !~ /^([IC]*P)([IC]*P)$/) {
	    printf "%2x:broken entry:$entry\n", $i;
	    next;
	}
	$addr = $1; $len = $2;
	$addr = nat($addr); $len = nat($len);
	if ($addr != 0 || $len != 0) {
	    my $font = substr($dna, 13615+$addr,$len);
	    my $t;
	    printf "%02x:".lookuplen($addr,$len).
	        "  WD:".nat(substr($font,0,9)).
		", Size:".nat(substr($font,9,24))."\n", $i;
	    $font = substr($font,9+24);
	    $font =~ s/^(.*?P)IICICP//;
	    $t = $1;
	    $t =~ s'([IC]*P)(\1*)'my $ct = length($2)/length($1);
		                      " ".$fontcombinator[nat($1)]
					  .($ct ? "*".(1+$ct):"")'ge; #'
            print "$t\n";
	    print "TRAILING GARBAGE $font\n" if ($font);
	    next;

	}
    }
}


sub dumpAdaptation($$) {
    my ($indent, $adaptation) = @_;
#    print "${indent}$adaptation\n";
    my $gene = nat(substr($adaptation, 0, 24));
    if ($gene == 0x6fce9c) {
	print "${indent}TREE: ".lookup(nat(substr($adaptation, 24, 24)))."\n";
	$adaptation = substr($adaptation, 48);
	while ($adaptation) {
	    my $subtreelen = nat(substr($adaptation, 0, 24));
	    my $subtree = substr($adaptation, 24, $subtreelen);
	    dumpAdaptation("${indent}   ", $subtree);
	    $adaptation = substr($adaptation, 24+$subtreelen);
	}
    } elsif ($gene == 0x6fd99e) {
	print "${indent}GENE: ".lookup(nat(substr($adaptation, 24, 24)))."\n";
	$adaptation = substr($adaptation, 48);
	while ($adaptation) {
	    print "${indent}   PARAM ".nat(substr($adaptation, 0, 24))."\n";
	    $adaptation = substr($adaptation, 24);
	}
    } elsif ($gene == 0x6fea1f) {
	print "${indent}WRAPIMP ".prettyprint(substr($adaptation, 24, 48))."\n";;
	print "${indent}   PARAM0 ".prettyprint(substr($adaptation,24+48+48,24))."\n";
	$subtree = substr($adaptation, 24+48+48+24);
	$subtreelen = nat(substr($subtree, 0, 24));
	print "${indent}   PARAM1 ".substr($subtree,24,$subtreelen)."\n";
	$param = substr($subtree,24+$subtreelen);
	$paramlen = substr($param, 0, 24);
	print "${indent}   PARAM2 ".substr($param,24,$paramlen)."\n";
	my $retaddr = nat(substr($adaptation, 24+48,24));
	my $retlen = nat(substr($adaptation, 24+48+24,24));
	if ($retaddr != 0x6fe0bc) {
	    disass(substr($dna, $offset+ $retaddr, $retlen), $retaddr);
	}
    } elsif ($gene == 0x6ff34f) {
	print "${indent}K\n";
	$adaptation = substr($adaptation, 24);
	while ($adaptation) {
	    my $subtreelen = nat(substr($adaptation, 0, 24));
	    my $subtree = substr($adaptation, 24, $subtreelen);
	    dumpAdaptation("${indent}   ", $subtree);
	    $adaptation = substr($adaptation, 24+$subtreelen);
	}
    } elsif ($gene == 0x6fc928) {
	print "${indent}INTBOX ".nat(substr($adaptation,24,24))."\n";
	$adaptation = substr($adaptation, 48);
	while ($adaptation) {
	    my $subtreelen = nat(substr($adaptation, 0, 24));
	    my $subtree = substr($adaptation, 24, $subtreelen);
	    dumpAdaptation("${indent}   ", $subtree);
	    $adaptation = substr($adaptation, 24+$subtreelen);
	}
    } elsif ($gene < 0x6fa9bc) {
	print "${indent}ADAPTOR: ".lookup($gene)."\n";
    } else {
	print "${indent}ADAPTOR: ".lookup($gene)."\n";

#	print "NEXT: ".lookup(hex($start)+48+$len+nat(substr($adaptation,24+$len,24)))."\n";

#	$adaptation = substr($adaptation, 24);
#	while ($adaptation) {
#	    print "${indent}   PARAM ".nat(substr($adaptation, 0, 24))."\n";
#	    $adaptation = substr($adaptation, 24);
#	}
    }
}
	
foreach $start (sort keys %table) {
    next if $table{$start}[2] == 1;
    if ($table{$start}[0] == 0x2400 && $table{$start}[1] =~ /font/) {
	print "=================================\n";
	print "FONT ".$table{$start}[1].hex($start)."\n";
	print "=================================\n";
	dumpFontTable($start);
    } elsif  ($table{$start}[2] == 2) {
	print "======================================\n";
	print "ADAPTATION CODE $table{$start}[1]\n";
	print "======================================\n";
	my $adaptation = substr($dna,13615+hex($start),$table{$start}[0])."\n";
	my $len = nat(substr($adaptation,0,24));
	printf "LEN: %08x\n",$len+2*24;
	my $code = substr($adaptation,24,$len);
	disass ($code, hex($start)+24);
	print "NEXT: ".lookup(hex($start)+48+$len+nat(substr($adaptation,24+$len)))."\n";
    } elsif  (hex($start) >= 0x6fa9bc) {
	print "======================================\n";
	print "ADAPTATION $table{$start}[1]\n";
	print "======================================\n";
	my $adaptation = substr($dna,13615+hex($start),$table{$start}[0])."\n";
	my $len = nat(substr($adaptation,0,24));
	print "LEN: ".$len."\n";
	print "CODE: ".$adaptation."\n";
	dumpAdaptation("", substr($adaptation, 24, $len));
	print "NEXT: ".lookup(hex($start)+48+$len+nat(substr($adaptation,24+$len)))."\n";

#	print "len:$len\n";
#	$adaptation = substr($adaptation, 24);
#	$offset+=24;
#	while ($adaptation) {
#	    my $gene = nat(substr($adaptation,0,24));
#	    if ($gene >= 0x10000 && $gen  <= 0x7295a1) {
#		print lookup($gene)."\n";
#	    } else {
#		print prettyprint($gene)."\n";
#	    }
#	    $adaptation = substr($adaptation,24);
#	}

#	disass(substr($adaptation, 24, $len-24), hex($start)+24);
#	print prettyprint(substr($adaptation,$len,48))."\n";	
#	my $restlen = nat(substr($adaption,24+$len,24));
#	print "rest: ".$restlen.":".substr($adaptation,48+$len)."\n";

    } elsif (hex($start) >= $codestart) {
	print "======================================\n";
	print "SUBROUTINE $table{$start}[1]\n";
	print "======================================\n";
	$len   = $table{$start}[0];
	disass(substr($dna,hex($start)+13615,$len),hex($start));
    }
}
