diff options
author | iximeow <me@iximeow.net> | 2018-07-09 21:53:10 -0700 |
---|---|---|
committer | iximeow <me@iximeow.net> | 2018-07-09 21:53:10 -0700 |
commit | bb7bbc04ecb9e4feaecf59d7230f377e4c6fc143 (patch) | |
tree | dfad417c3037964c68b68b74c59509fc8d6642c0 /source/notes/pic-mcu/pickit2/pk2cmd-stuff | |
parent | aab989297b2f6b5ee4501ae1da1f4ca681cc6b7e (diff) |
add pic notes
Diffstat (limited to 'source/notes/pic-mcu/pickit2/pk2cmd-stuff')
16 files changed, 4335 insertions, 0 deletions
diff --git a/source/notes/pic-mcu/pickit2/pk2cmd-stuff/PK2V023200.hex b/source/notes/pic-mcu/pickit2/pk2cmd-stuff/PK2V023200.hex new file mode 100644 index 0000000..8096b15 --- /dev/null +++ b/source/notes/pic-mcu/pickit2/pk2cmd-stuff/PK2V023200.hex @@ -0,0 +1,2071 @@ +:020000040000FA +:1000000085EF07F01200FFFF04EF10F01200FFFF72 +:10001000FFFFFFFFFFFFFFFF0CEF10F01200FFFFDD +:10002000FFFFFFFFFFFFFFFFFFFF00000401105174 +:10003000600BE842E842E842E842E842000901E099 +:1000400055D01151070A51E00B0A4FE0070A40E072 +:10005000010A2CE00B0A28E0020A26E0030A22E04B +:10006000080A12E0010A0EE00F0A0AE0030A01E0A2 +:100070003CD00001010EB06F0001040EB76F36D006 +:1000800036D834D090D832D00001010EB06F0001C4 +:10009000B90EB16F000EB26F0001B8930001010EEE +:1000A000B56F24D0A8D822D0F5D820D00001010EF9 +:1000B000B06F040114510001B16FB26BBA0EB127D9 +:1000C000000EB2230001B8930001010EB56F0ED0EF +:1000D0000001010EB06F04011451EA6ABA0FE96E13 +:1000E000000EEA2212C4EFFF01D000D01200800EF1 +:1000F0000401105D57E11351030A34E0010A10E0D6 +:10010000030A01E04DD00001010EB06F0001600E46 +:10011000B16F0C0EB26F120E0001B56FB66B40D00E +:100120000001010EB06F04011251F66EF76AD8900B +:10013000F636F7369E0EF6260D0EF7220900F5CF9D +:10014000B1F00A00F5CFB2F0020E0001F76AB12556 +:10015000F66EB251F7220900F5CFB5F00A00F5CFDF +:10016000B6F01ED00001010EB06F04011251F66E00 +:10017000F76AD890F636F736A20EF6260D0EF7225D +:100180000900F5CFB1F00A00F5CFB2F0B1C0F6FF2B +:10019000B2C0F7FF0800F5500001B56FB66B00D094 +:1001A0000001B88312000001010EB06F0F0EE66E61 +:1001B000710EE66E0F0EE66E1BEC06F0E552E55290 +:1001C000E552010EE66EBA0EE66E000EE66E1BEC10 +:1001D00006F0E552E552E55212C4B9F0040112519D +:1001E00004E10001050EB76F05D00001060EB76FE0 +:1001F000E7EC04F012000401186B196B04011051B4 +:100200001F0B020A15E0030A0FE0010A01E034D0D7 +:100210000001010EB06F02D0040118810001B8A1E5 +:1002200002D00401188328D00001010EB06F24D041 +:100230000001010EB06F040114510F0B080DF350B3 +:10024000016A000F006E040E01221451800B01E0C0 +:10025000010E040DF35000010024B36F000E0120C5 +:10026000B46FB3C0E9FFB4C0EAFFEF50040B03E082 +:100270000401010E186F00D00001B0050AE1000171 +:10028000180EB16F040EB26F0001B8930001020E98 +:10029000B56F12000401120510E110511F0B000987 +:1002A0000CE10001010EB06F030E0401115D03E1CA +:1002B0000001B88102D00001B891040112513AE165 +:1002C00010511F0B020836E114510F0B000932E0E8 +:1002D0000001010EB06F040114510F0B080DF35013 +:1002E000016A000F006E040E01221451800B01E020 +:1002F000010E040DF35000010024B36F000E012025 +:10030000B46F030E0401115D07E1840EB3C0E9FF71 +:10031000B4C0EAFFEF6E0ED014AF06D0B3C0E9FF51 +:10032000B4C0EAFFEF6A06D0880EB3C0E9FFB4C0DC +:10033000EAFFEF6E12006C500BE1040100513C0B20 +:10034000E842E8420D0802E108D801D03CD804D0C8 +:10035000040E6C5C01E147D81200D9CFE6FFE1CF73 +:10036000D9FFE6520001AF6BB06BB56BB66B16EC04 +:1003700000F0DF6ADF50006E016A010E005C000EC3 +:1003800001581BE20001B05101E017D0F76ADF34D9 +:10039000FE0BF736F66EAC0EF6260D0EF7220900B0 +:1003A000F5CF00F00800F5CF01F004D001C0FAFF4E +:1003B0000050F96EFBDFDF2ADDD7D5D8E552E552D4 +:1003C000E7CFD9FF1200020E0001AF5D0AE192D81B +:1003D000040100BD03D0C80E006F02D0880E006F6C +:1003E00001D007D91200040E0001B75D0AE112C462 +:1003F0006EFF6E50000803E2050EB76F02D0030EC9 +:10040000B76F0001AF050AE10BD8040104BD03D0AA +:10041000C80E046F02D0880E046F01D0EAD8120013 +:10042000D9CFE6FFE1CFD9FF020EE1260001080E89 +:10043000B55D000EB65905E2B5C0DEFFB6C0DDFF02 +:1004400003D0080EDE6EDD6A040104930491010EF0 +:10045000DB500413DFCF05F4000EDB500001B55F65 +:10046000010EDB50B65B180EB36F040EB46F0001C3 +:10047000B8A31ED0D9CFE9FFDACFEAFFEE50ED10D6 +:1004800016E0B1C0F6FFB2C0F7FF0800F550B3C0E8 +:10049000E9FFB4C0EAFFEF6E0001B32B000EB423F6 +:1004A000B12BB223DF06010E01E2DB06E3D71CD03D +:1004B000D9CFE9FFDACFEAFFEE50ED1015E0B1C079 +:1004C000E9FFB2C0EAFFEF50B3C0E9FFB4C0EAFFF2 +:1004D000EF6E0001B32B000EB423B12BB223DF0665 +:1004E000010E01E2DB06E4D7D9CFE1FFE552E7CF09 +:1004F000D9FF1200D9CFE6FFE1CFD9FF020EE126E6 +:10050000030E04010015E76E010EE7CFDBFF01C407 +:10051000DFFFDE500001B527DD50B623180EB16FA6 +:10052000040EB26FD9CFE9FFDACFEAFFEE50ED103B +:1005300014E0B1C0E9FFB2C0EAFFEF50B3C0E9FF79 +:10054000B4C0EAFFEF6EB32B000EB423B12BB2237D +:10055000DF06010E01E2DB06E5D7D9CFE1FFE55268 +:10056000E7CFD9FF12006D980001B0510CE10401F2 +:10057000080E016F100E026F040E036F840E006FE1 +:100580000401046F35D0040110AF22D00001B55131 +:100590000401165D0001B6510401175904E216C4A6 +:1005A000B5F017C4B6F03CDF0001010EAF6F0401D7 +:1005B000080E016F100E026F040E036F800E006FA5 +:1005C0000401180E066F040E076FC80E046F10D0DA +:1005D0000001020EAF6F0401056BC80E046F040129 +:1005E000080E016F180E026F040E036FC80E006F25 +:1005F00012000001AF6B0401080E016F100E026FB4 +:10060000040E036F880E006F0401046B1200550E78 +:10061000A76EAA0EA76EA68212000001420E6A6F94 +:10062000020E6B6F010E6C6F12000001606B665161 +:10063000605D1EE260C000F0016A026A675100243A +:10064000F36E68510120F46E69510220F86EF4CF08 +:10065000F7FFF3CFF6FF0800F5CF61F06051EA6ACB +:100660006A0FE96E000EEA2261C0EFFF602BDFD750 +:10067000F86A1200840EA66E0001606B6651605D20 +:1006800027E26051EA6A6A0FE96E000EEA22EFCFB4 +:1006900003F060C000F0016A026A67510024F36E43 +:1006A00068510120F46E69510220F86EF4CFF7FF13 +:1006B000F3CFF6FF03C0F5FF0C001F0E60151F08F7 +:1006C00003E06605605D01E1A2DF0001602BD6D783 +:1006D00012000001606B6651605D20E2940EA66E10 +:1006E0006051006E016A060ED89000360136E804AB +:1006F000FBE1026A01BE0268000167510024F36E4B +:1007000068510120F46E69510220F86EF4CFF7FFB2 +:10071000F3CFF6FF7CDF0001602BDDD7F86A120013 +:10072000A66A0001606B6651605D0EE2675160254C +:10073000A96EA6806051EA6A6A0FE96E000EEA228D +:10074000A8CFEFFF602BEFD712000001606B66515E +:10075000605D13E267516025A96E6051EA6A6A0F15 +:10076000E96E000EEA22EF50A86E040EA66E4FDF6F +:10077000A6B2FED70001602BEAD71200C40EA66E07 +:100780000001606B6651605D20E26051EA6A6A0FA9 +:10079000E96E000EEA22EFCF03F060C000F0016ABC +:1007A000026A67510024F36E68510120F46E6951AA +:1007B0000220F86EF4CFF7FFF3CFF6FF03C0F5FF8A +:1007C0000C0025DF0001602BDDD7F86A1200400E17 +:1007D000E66E650EE66E000EE66E36EC05F0E5524E +:1007E000E552E552000870E20001606B00016551BE +:1007F000FF0A57E0FA0A50E0010A3BE0070A34E03A +:10080000010A2DE0030A18E0070A16E0700A01E069 +:100810005AD003DF0001040E606F04010CBFFDD746 +:10082000400EE66E650EE66E000EE66EFCEC04F021 +:10083000E552E552E55248D0F8DE050E000160278A +:1008400004010CBFFDD7400EE66E650EE66E000E8D +:10085000E66EFCEC04F0E552E552E55235D00ADFD5 +:100860000001010E606F30D034DF0001010E606FB7 +:100870002BD056DF050E0001602704010CBFFDD709 +:10088000400EE66E650EE66E000EE66EFCEC04F0C1 +:10089000E552E552E55218D058DF0001010E606FB5 +:1008A00013D093EC05F00001636B646B00016307E8 +:1008B000000E645B00016351641103E0000000005E +:1008C000F5D7FF0001D000D01200040110511F0B1A +:1008D000010801E079D0145101E076D0060E115DD7 +:1008E0002EE11351230A28E0010A13E0030A01E074 +:1008F00024D00001020EB06F0001B90505E100012E +:10090000840EB16F0C0EB26F090E0001B56FB66B9D +:1009100014D00001020EB06F0001B90505E100011D +:10092000810EB16F0D0EB26F0001B90504E11D0E0D +:100930000001B56FB66B01D000D00001B88304018F +:100940001051600BE842E842E842E842E842010800 +:1009500001E03AD011510B0A31E0080A21E0090AFE +:1009600019E0080A09E00B0A05E0080A01E02CD0AA +:100970002CD82AD02BD828D00001020EB06F00014D +:10098000BB0EB16F000EB26F0001B8930001010EF3 +:10099000B56F1AD00001020EB06F13C4BBF014D0B3 +:1009A0000001020EB06F0001BC0EB16F000EB26FFD +:1009B0000001B8930001010EB56F06D00001020ED0 +:1009C000B06F12C4BCF000D012001200120000017F +:1009D000BD6B1E0E716E0401400E096F200E0A6F72 +:1009E000040E0B6F880E086F0401600E0E6F040E6C +:1009F0000F6F400E0C6F1200D9CFE6FFE1CFD9FF89 +:100A0000E652FC0EDB50400805E2400EF36EFC0E91 +:100A1000F3CFDBFFDF6AFC0EDB50DF5C19E2DF5057 +:100A2000E76EFD0EDBCFE9FFFE0EDBCFEAFFE750FE +:100A3000E926000EEA22EF50E66EDF50EA6A600F08 +:100A4000E96E040EEA22E552E750EF6EDF2AE3D7A3 +:100A5000FC0EDBCF0DF4400E04010C170C7D880E4C +:100A60000C13E552E552E7CFD9FF1200D9CFE6FFCC +:100A7000E1CFD9FF0001BD6B040108BF30D0FC0EEF +:100A8000DBCF00F00951D880005403E2FC0E09C40A +:100A9000DBFF0001BD6BFC0EDB50BD5D19E2BD51FB +:100AA000EA6A200FE96E040EEA22EF50E66EBD51AD +:100AB000E76EFD0EDBCFE9FFFE0EDBCFEAFFE7506E +:100AC000E926000EEA22E552E750EF6EBD2BE3D790 +:100AD0000401400E096F0817087D880E08130001F5 +:100AE000BD5100D0E552E7CFD9FF12006DA60FD857 +:100AF00002D06DB613D80001B70508E16DBA06D073 +:100B0000686A696A69806988020EB76F12006D6A47 +:100B1000696A6D860001010EB76F12006D6A696A1D +:100B20000001B76B12008EEF05F00001B75101E133 +:100B30003AD06850040B04E06950040B01E038D847 +:100B40006DB231D06850010B04E06950010B01E037 +:100B500050D86850100B04E06950100B01E024D805 +:100B60006850400B04E06950400B01E037D86850F2 +:100B7000200B04E06950200B01E032D86850020BD2 +:100B800004E06950020B01E032D8030E0001B75DAA +:100B900001E209D06850080B06E06950080B03E039 +:100BA0009BEC01F068961200698468986D821200CF +:100BB0006D926994689412000001B8A10ED0F8DF1C +:100BC0006D840001080EBE6F070EBF6FBE07000EDA +:100BD000BF5BBE51BF11FAE16D941200689C120018 +:100BE00070A003D0F9EC02F07090689A120068923D +:100BF00012006A6A686A9F0E6B6E7B0E696E6E6A7F +:100C00000F0EE66E710EE66E0F0EE66E14D8E5520C +:100C1000E552E552160E706E68A602D06896FCD7B3 +:100C20006D98F9EC02F00001B8910001B96B000178 +:100C3000030EB76F1200D9CFE6FFE1CFD9FFFD0E4B +:100C4000DBCFE9FFFE0EDBCFEAFFFC0EDB5004E05A +:100C5000EE6AFC0EDB06F9D7E552E7CFD9FF1200AA +:100C60001201000200000008D80433000100010254 +:100C70000302090229000101028032090400000276 +:100C800003000000092101000001221D0007058169 +:100C90000340000107050103400001090220000193 +:100CA000020480320904000002FF000000070581F1 +:100CB0000340000107050103400001040309043457 +:100CC000034D006900630072006F006300680069F3 +:100CD000007000200054006500630068006E006F23 +:100CE000006C006F0067007900200049006E00630F +:100CF000002E0048035000490043006B0069007457 +:100D0000002000320020004D006900630072006F77 +:100D10000063006F006E00740072006F006C006C66 +:100D200000650072002000500072006F00670072C2 +:100D30000061006D006D00650072001603500049EF +:100D400000430031003800460032003500350030E5 +:100D50000030035000490043006B0069007400201C +:100D6000003200200043006F006E006600670075CF +:100D70000072006100740069006F006E0020003294 +:100D8000000600FF0901A10119012940150026FFF5 +:100D900000750895408102190129409102C0720C2A +:100DA0009B0CBB0CBF0CF30C3B0D510DCA082A0E5B +:100DB000F66E000EF76E000EF86E00010900F55099 +:100DC000AA6F0900F550AB6F03E1AA6701D03DD0CF +:100DD0000900F550A56F0900F550A66F0900F55000 +:100DE000A76F09000900F550E96E0900F550EA6E99 +:100DF000090009000900F550A86F0900F550A96F16 +:100E000009000900F6CFACF0F7CFADF0F8CFAEF0A7 +:100E1000A5C0F6FFA6C0F7FFA7C0F8FF0001A853C2 +:100E200002E1A95307E00900F550EE6EA807F8E2C9 +:100E3000A907F9D7ACC0F6FFADC0F7FFAEC0F8FF09 +:100E40000001AA07000EAB5BBFD71200D9CFE6FFA7 +:100E5000E1CFD9FF030EE126938A818AF19E580ED5 +:100E6000E66E6EEC07F0E55281AA0DD0FE0EF66E2E +:100E70007F0EF76EF86A0800F550DF6E550EDF5CE6 +:100E800002E100EF10F018D822D8E7EC03F0D950B7 +:100E9000010FE96EDACFEAFFEE50ED1001E18B7041 +:100EA000010EDB06020E01E2DB06EED7D9CFE1FF31 +:100EB000E552E7CFD9FF1200140E6F6E0001B76B39 +:100EC0000001B86B0001B96B8B909490120076EC26 +:100ED00005F06FBE02D095EC05F01200FF0EE35056 +:100EE000076EEF0E01D0F30EE76EE72E75EF07F0F9 +:100EF0000C0E066EE76AE72E7BEF07F0062E7AEF00 +:100F000007F0072E73EF07F0120013EE00F023EE48 +:100F100000F0F86A059CD7EC06F026EC07F0FDD748 +:100F20001200FFFFFFFFFFFFFFFFFFFFFFFFFFFFBD +:100F3000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC1 +:100F4000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB1 +:100F5000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA1 +:100F6000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF91 +:100F7000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF81 +:100F8000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF71 +:100F9000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF61 +:100FA000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF51 +:100FB000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF41 +:100FC000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF31 +:100FD000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF21 +:100FE000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF11 +:100FF000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF01 +:10100000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0 +:10101000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE0 +:10102000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD0 +:10103000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC0 +:10104000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB0 +:10105000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA0 +:10106000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF90 +:10107000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80 +:10108000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF70 +:10109000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF60 +:1010A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF50 +:1010B000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF40 +:1010C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF30 +:1010D000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF20 +:1010E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF10 +:1010F000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00 +:10110000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEF +:10111000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDF +:10112000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFCF +:10113000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBF +:10114000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAF +:10115000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9F +:10116000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8F +:10117000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7F +:10118000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6F +:10119000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5F +:1011A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4F +:1011B000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3F +:1011C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2F +:1011D000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1F +:1011E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0F +:1011F000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +:10120000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEE +:10121000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDE +:10122000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFCE +:10123000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBE +:10124000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAE +:10125000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9E +:10126000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8E +:10127000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7E +:10128000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6E +:10129000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5E +:1012A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4E +:1012B000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3E +:1012C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2E +:1012D000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1E +:1012E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0E +:1012F000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE +:10130000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFED +:10131000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDD +:10132000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFCD +:10133000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBD +:10134000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAD +:10135000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9D +:10136000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8D +:10137000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7D +:10138000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6D +:10139000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D +:1013A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D +:1013B000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3D +:1013C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2D +:1013D000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1D +:1013E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0D +:1013F000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD +:10140000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEC +:10141000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDC +:10142000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFCC +:10143000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBC +:10144000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAC +:10145000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9C +:10146000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8C +:10147000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7C +:10148000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6C +:10149000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5C +:1014A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4C +:1014B000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3C +:1014C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2C +:1014D000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1C +:1014E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0C +:1014F000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC +:10150000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEB +:10151000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDB +:10152000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFCB +:10153000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBB +:10154000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAB +:10155000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9B +:10156000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8B +:10157000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7B +:10158000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6B +:10159000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5B +:1015A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4B +:1015B000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3B +:1015C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2B +:1015D000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1B +:1015E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0B +:1015F000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB +:10160000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEA +:10161000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDA +:10162000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFCA +:10163000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBA +:10164000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAA +:10165000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9A +:10166000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A +:10167000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7A +:10168000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6A +:10169000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5A +:1016A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4A +:1016B000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3A +:1016C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2A +:1016D000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1A +:1016E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0A +:1016F000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA +:10170000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE9 +:10171000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD9 +:10172000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC9 +:10173000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB9 +:10174000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA9 +:10175000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF99 +:10176000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF89 +:10177000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF79 +:10178000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF69 +:10179000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF59 +:1017A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF49 +:1017B000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF39 +:1017C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF29 +:1017D000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF19 +:1017E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF09 +:1017F000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9 +:10180000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE8 +:10181000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD8 +:10182000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC8 +:10183000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB8 +:10184000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA8 +:10185000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF98 +:10186000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF88 +:10187000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF78 +:10188000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF68 +:10189000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF58 +:1018A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF48 +:1018B000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF38 +:1018C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF28 +:1018D000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF18 +:1018E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF08 +:1018F000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8 +:10190000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE7 +:10191000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD7 +:10192000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7 +:10193000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB7 +:10194000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA7 +:10195000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF97 +:10196000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF87 +:10197000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF77 +:10198000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF67 +:10199000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF57 +:1019A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF47 +:1019B000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF37 +:1019C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF27 +:1019D000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF17 +:1019E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF07 +:1019F000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7 +:101A0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE6 +:101A1000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6 +:101A2000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC6 +:101A3000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB6 +:101A4000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA6 +:101A5000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF96 +:101A6000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF86 +:101A7000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF76 +:101A8000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF66 +:101A9000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF56 +:101AA000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF46 +:101AB000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF36 +:101AC000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF26 +:101AD000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF16 +:101AE000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF06 +:101AF000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6 +:101B0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE5 +:101B1000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD5 +:101B2000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC5 +:101B3000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB5 +:101B4000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA5 +:101B5000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF95 +:101B6000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF85 +:101B7000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF75 +:101B8000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF65 +:101B9000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF55 +:101BA000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF45 +:101BB000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF35 +:101BC000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF25 +:101BD000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF15 +:101BE000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF05 +:101BF000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5 +:101C0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE4 +:101C1000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD4 +:101C2000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC4 +:101C3000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB4 +:101C4000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA4 +:101C5000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF94 +:101C6000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF84 +:101C7000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF74 +:101C8000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF64 +:101C9000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF54 +:101CA000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF44 +:101CB000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF34 +:101CC000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF24 +:101CD000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF14 +:101CE000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF04 +:101CF000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4 +:101D0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE3 +:101D1000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD3 +:101D2000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC3 +:101D3000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB3 +:101D4000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA3 +:101D5000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF93 +:101D6000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF83 +:101D7000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF73 +:101D8000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF63 +:101D9000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF53 +:101DA000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF43 +:101DB000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF33 +:101DC000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF23 +:101DD000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF13 +:101DE000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF03 +:101DF000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3 +:101E0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE2 +:101E1000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD2 +:101E2000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC2 +:101E3000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB2 +:101E4000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA2 +:101E5000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF92 +:101E6000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF82 +:101E7000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF72 +:101E8000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF62 +:101E9000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF52 +:101EA000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF42 +:101EB000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF32 +:101EC000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF22 +:101ED000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF12 +:101EE000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF02 +:101EF000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2 +:101F0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE1 +:101F1000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD1 +:101F2000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC1 +:101F3000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB1 +:101F4000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA1 +:101F5000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF91 +:101F6000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF81 +:101F7000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF71 +:101F8000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF61 +:101F9000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF51 +:101FA000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF41 +:101FB000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF31 +:101FC000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF21 +:101FD000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF11 +:101FE000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF01 +:101FF000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1 +:1020000083EF3EF0120000009DEF3AF01200000056 +:1020100000000000000000009DEF3AF012000000F8 +:10202000FFFFFFFFFFFFFFFFFFFFD9CFE6FFE1CF7D +:10203000D9FFE652030ED26EA194A08492809282C0 +:102040000D0EC16E030EC06E9284809489949286A8 +:102050008096899692888998899A929A8A96939678 +:102060008A889398938A818AF19E8A9493948B901C +:1020700094908B9294928B949494949C8B8C020E5B +:10208000DF6E0001030E016F0001090E026F0001F7 +:10209000040E036FF00EE66E55EC2AF0E5522308AD +:1020A00028E11E0EDF5C25E2DF50FE0BE842F00F58 +:1020B000E66E55EC2AF0E552E66EDF50EA6A000F54 +:1020C000E96E000EEA22E552E750EF6EDF28EA6A79 +:1020D000000FE96E000EEA22EF6ADF50EA6A000F95 +:1020E000E96E000EEA22EF5001E103D0020EDF2676 +:1020F000D8D7020EDF240001006F3E6A0001E76BB3 +:102100000001010EE86F0201030EE06F0201E16BB6 +:102110000201010EE26FD9EC19F0BBEC17F0B3EC41 +:1021200017F08DEC17F00001400ED880E355010E3A +:10213000E4550EE30001C00EE35D000EE45908E330 +:102140000001E651AF0804E3500E0001E65D09E22C +:102150000001E36B010EE46F0001E56B0001800EEE +:10216000E66F080ED56E040ECA6E4F0ECB6E0C0EC7 +:10217000BD6E1D0EBE6E0001400EE06F00013E0EF2 +:10218000E16F00013C0EE26F02017E0EFA6F020168 +:102190002D0EFB6F070EB46EB56AF28CF28E93ECC7 +:1021A0003BF0040EE66E55EC2AF0E552500828E1AB +:1021B000050EE66E55EC2AF0E5524B0821E1060EBD +:1021C000E66E55EC2AF0E55232081AE1070EE66E8B +:1021D00055EC2AF0E5523D6E020E3E6E546AE66AF8 +:1021E000110EE66E01EC16F0E552E552400EE66E79 +:1021F00026EC17F0E5520201FA6F0201890E006F1A +:10220000E552E552E7CFD9FF120004010CBFFDD71C +:10221000400EE66E400EE66E020EE66E18EC3AF0E8 +:10222000E552E552E55280EC3DF01200D9CFE6FFD1 +:10223000E1CFD9FF020EE126DF6A010EDB6A81BA27 +:1022400002D00001E78D400EE66E000EE66E020E33 +:10225000E66E54EC3AF0E552E552E552000803E22E +:10226000DE52010EDD6E3E0406E1010EDB5002E09F +:1022700087EC2FF00ED2020E3E5C09E1010EDB501E +:1022800004E0760E0201005D02E00DDA02D20001E8 +:10229000E8B383DA010EDB5001E1FBD1DF50EA6ADB +:1022A000000FE96E020EEA22EF50546E5450420ABB +:1022B00027E0340A05E02C0A01E025D0DF2AE5D129 +:1022C00031EC1DF0020E3E5C19E1080ED56E8A88D5 +:1022D0003E6AE668040EE66E33EC2AF0E552E552FB +:1022E000E668050EE66E33EC2AF0E552E552E66844 +:1022F000060EE66E33EC2AF0E552E552DF2AC5D130 +:10230000F9EC1CF0C2D1A00E545C03E2400EDF6E6B +:10231000BCD15450B90803E2400EDF6EB6D1A00E16 +:10232000545E549E5446080E5426F9505424D8B096 +:10233000FA2AF96E1AD03FD06BD06ED071D07AD015 +:1023400091D0B1D0B4D0BDD0C0D0C3D0C6D0C9D048 +:10235000CBD0CDD0D0D005D10DD115D11DD11FD12D +:1023600027D128D12FD17AD190D1DF28EA6A000F66 +:10237000E96E020EEA22EF50E66E020EDF24EA6AF0 +:10238000000FE96E020EEA22EF50E66E01EC16F045 +:10239000E552E552030EDF24EA6A000FE96E020EF1 +:1023A000EA22EF50E66E26EC17F0E5520201FA6FD2 +:1023B000040EDF26D9D7DF28EA6A000FE96E020E85 +:1023C000EA22EFCFE0F0020EDF24EA6A000FE96EA6 +:1023D000020EEA22EF50E66E26EC17F0E552010FEE +:1023E0000001E16F020E0001E15D0001E26F030EEA +:1023F000DF24EA6A000FE96E020EEA22EF50E66E71 +:1024000026EC17F0E5520201FB6F040EDF26ACD775 +:1024100011EC1DF0DF2AA8D76EEC18F0DF2AA4D744 +:10242000DF2AD9CFE6FFDACFE6FF73EC1AF0E552E8 +:10243000E5529AD7DF2ADF28EA6A000FE96E020E1A +:10244000EA22EF50E66EDF50EA6A000FE96E020EF4 +:10245000EA22EF50E66E88EC19F0E552E552020EE2 +:10246000DF2682D7DF2ADF50EA6A000FE96E020E0C +:10247000EA22EF50E66EDF28406A000F3F6E020E40 +:1024800040223FC0E6FF40C0E6FF3CEC1DF0E552B5 +:10249000E552E552DF50EA6A000FE96E020EEA22C9 +:1024A000EF28DF2661D7BBEC17F0DF2A5DD7DF2AE4 +:1024B000D9CFE6FFDACFE6FFF4EC19F0E552E552AA +:1024C00053D7B3EC17F0DF2A4FD7E7EC18F0DF2A29 +:1024D0004BD7D9EC19F0DF2A47D73AEC19F0DF2AAD +:1024E00043D7400EDF6E40D7FF00DF2A3DD7C3EC55 +:1024F00017F0DF2A39D7DF28EA6A000FE96E020EEB +:10250000EA22EF500001E36FE46B020EDF24EA6A77 +:10251000000FE96E020EEA22EFCF3FF0406A3FBEA5 +:1025200040683FC040F03F6A3F500001E327405001 +:102530000001E423030EDF24EA6A000FE96E020EB5 +:10254000EA22EFCFE5F0040EDF24EA6A000FE96E1D +:10255000020EEA22EFCFE6F06AEC17F0050EDF2656 +:1025600003D7DF2AD9CFE6FFDACFE6FFC8DAE55294 +:10257000E552FAD6DF2AD9CFE6FFDACFE6FF3FDA17 +:10258000E552E552F1D6DF2AD9CFE6FFDACFE6FFF2 +:1025900099D9E552E552E8D6DF2AE0D9E5D6DF2A17 +:1025A000DFCFE6FF27EC2FF0E552040EDF26DCD666 +:1025B000DF2ADAD6DF2ADFCFE6FF38D9E552400E30 +:1025C000DF6ED2D6DF2ADF50DF2AEA6A000FE96E1B +:1025D000020EEA22EF505F6EDF50DF2AEA6A000F38 +:1025E000E96E020EEA22EF50546EDF50DF2AEA6AEB +:1025F000000FE96E020EEA22EF50566EDF50DF2A1E +:10260000EA6A000FE96E020EEA22EF50586EDF50C0 +:10261000DF2AEA6A000FE96E020EEA22EF50596ED5 +:10262000DF50DF2AEA6A000FE96E020EEA22EF505D +:102630005A6EDF50DF2AEA6A000FE96E020EEA22C4 +:10264000EF285B6EDF50DF2AEA6A000FE96E020EA8 +:10265000EA22EF505E6ECFEC2DF086D6DF2ADF281F +:10266000EA6A000FE96E020EEA22EF50E66EDF50D2 +:10267000EA6A000FE96E020EEA22EF50E66E7ED99A +:10268000E552E552020EDF266FD6400EDF5C01E216 +:1026900005D6020EE15C02E2E16AE552E16EE55226 +:1026A000E7CFD9FF1200F29A870ED56EF2A429D097 +:1026B000D20ED76E3A0ED66EF294542A54500508B4 +:1026C00001E2546A040E545C06E2010E5414E8B0B0 +:1026D0008A88E8A08A98300E0001E71512E08A88FF +:1026E00081BAFED78F0E0001E717F00EE66E58ECA8 +:1026F0003EF0E55281AAFED7F00EE66E58EC3EF0B1 +:10270000E5520001E7AD47D08A882FEC31F08A8886 +:102710008A8681AAFED7546AE66A110EE66E71DADD +:10272000E552E552400EE66E91DBE5520201FA6F8A +:10273000300E0001E71502E081BAFED7FC0E000161 +:10274000E81506E0080EE66E6FEC36F0E55210D0A4 +:10275000390406E1040EE66E6FEC36F0E55208D05F +:102760003650371005E0060EE66E6FEC36F0E55297 +:10277000F00EE66E58EC3EF0E55281AAFED7F00E60 +:10278000E66E58EC3EF0E5528F0E0001E7170001AF +:10279000E86B0001E79D8B901200D9CFE6FFE1CFF7 +:1027A000D9FFE6523D501AE03D50DF6E3D6A3A5087 +:1027B000E66ECEEC27F0E552DF50010805E23B5013 +:1027C000E66ECEEC27F0E552DF50020805E23C5001 +:1027D000E66ECEEC27F0E5523D50E6E10201E55110 +:1027E000E61108E0A050020B05E103EC28F0396E79 +:1027F000A182A0828150100B14E1C250020B11E1A2 +:102800000201FA51C45C0AE20C0E0201FC5D03E114 +:102810008A948A8802D00201FC2B02D00201FC6B50 +:10282000C282E552E552E7CFD9FF1200D9CFE6FFC9 +:10283000E1CFD9FFFE0EDBCFE6FF45EC2FF0E552EE +:1028400000093CE0020E3E6E546AE66A110EE66E26 +:10285000D8D9E552E552400EE66EF8DAE5520201AB +:10286000FA6F500EE66E040EE66E33EC2AF0E55277 +:10287000E5524B0EE66E050EE66E33EC2AF0E5529D +:10288000E552320EE66E060EE66E33EC2AF0E552A5 +:10289000E552FE0EDB50030FEA6A000FE96E020EEE +:1028A000EA22EF503D6E3D50E66E070EE66E33ECC9 +:1028B0002AF0E552E5520201890E006FE552E7CF9A +:1028C000D9FF1200D9CFE6FFE1CFD9FFF29EA8ECE5 +:1028D0003BF0050EC26EC282FD0EDBCFE9FFFE0E9D +:1028E000DBCFEAFFEF50EF2AEA6A000FE96E020E33 +:1028F000EA22EF50346EFD0EDBCFE9FFFE0EDBCF98 +:10290000EAFFEF50EF2AEA6A000FE96E020EEA22B0 +:10291000EF50356E366A376A386A396A3A6A3D6A04 +:102920000001E88392968986928492888A94899A93 +:102930002E0EB46EA50EB56E0C0EE66E9FEC3EF03C +:10294000E5529D90A092910ECD6E910EB16EA19C1C +:10295000A08CF28EE552E7CFD9FF1200F29E000163 +:10296000E893A09C9D90A092CD6AB16A070EB46EC8 +:10297000B56A928693EC3BF0F28E1200D9CFE6FF57 +:10298000E1CFD9FF030EE126FD0EDB50416E426A16 +:1029900041C042F0416AFE0EDB50000141243F6E0F +:1029A000000E4220406E010E3FC0DBFF020E40C011 +:1029B000DBFFDF6ADF503F6E406AD890405004E68C +:1029C000800E3F5C000E405810E2010EDBCFE9FFA5 +:1029D000DB2A020EDBCFEAFF01E3DB2AEF50E66ED3 +:1029E000CEEC27F0E552DF2AE5D7030EE15C02E2E8 +:1029F000E16AE552E16EE552E7CFD9FF1200D9CF87 +:102A0000E6FFE1CFD9FF050EE126FD0EDBCFE9FFA2 +:102A1000FE0EDBCFEAFFEF50EF2AEA6A000FE96E05 +:102A2000020EEA22040EEFCFDBFFFD0EDBCFE9FF43 +:102A3000FE0EDBCFEAFFEF50EF2AEA6A000FE96EE5 +:102A4000020EEA22EF50E66ED950020FE96EDACF9D +:102A5000EAFFE552E750EE6EED6AD950020FE96EDB +:102A6000DACFEAFF200ED880EE54000EED5407E2D4 +:102A7000200EF36E020EF3CFDBFF030EDB6AD9509C +:102A8000020FE96EDACFEAFFEE50ED1001E12DD032 +:102A9000DE6ADD6ADECF3FF0DDCF40F0020EDBCF35 +:102AA00041F0030EDBCF42F041503F5C42504058B2 +:102AB0001AE2040EDBCFF3FFDB2AF350E66E55EC8F +:102AC0002AF0E552E66EDECFE9FFDDCFEAFF400EE9 +:102AD000E926020EEA22E552E750EF6EDF2A010EE8 +:102AE00001E3DB2AD7D705EC11F0050EE15C02E229 +:102AF000E16AE552E16EE552E7CFD9FF1200D9CF86 +:102B0000E6FFE1CFD9FF050EE126FD0EDBCFE9FFA1 +:102B1000FE0EDBCFEAFFEF50EF2AEA6A000FE96E04 +:102B2000020EEA22040EEFCFDBFFFD0EDBCFE9FF42 +:102B3000FE0EDBCFEAFFEF50EF2AEA6A000FE96EE4 +:102B4000020EEA22EF50E66ED950020FE96EDACF9C +:102B5000EAFFE552E750EE6EED6AD950020FE96EDA +:102B6000DACFEAFF200ED880EE54000EED5407E2D3 +:102B7000200EF36E020EF3CFDBFF030EDB6AD9509B +:102B8000020FE96EDACFEAFFEE50ED1001E12FD02F +:102B9000DE6ADD6ADECF3FF0DDCF40F0020EDBCF34 +:102BA00041F0030EDBCF42F041503F5C42504058B1 +:102BB0001EE2FD0EDBCFE9FFFE0EDBCFEAFFEF509A +:102BC000EF2AEA6A000FE96E020EEA22EF50E66E83 +:102BD000040EDBCFF3FFDB2AF350E66E33EC2AF072 +:102BE000E552E552DF2A010E01E3DB2AD3D7050EB9 +:102BF000E15C02E2E16AE552E16EE552E7CFD9FF1E +:102C00001200D9CFE6FFE1CFD9FF030EE126FE0E79 +:102C1000DB50426E436A42C043F0426AFD0EDB5015 +:102C2000000142243F6E000E4320406E416A40BEC8 +:102C300041683FC0DFFF010E40C0DBFF020E41C014 +:102C4000DBFFD9CFE9FFDACFEAFF060EE76ED890B7 +:102C5000020EEB32010EEB32EF32E706F8E1E5C08F +:102C60003FF0406A416A3FAE02D040684168D9CF28 +:102C7000E9FFDACFEAFF3F50EE264050EE22415006 +:102C8000EE22E6C03FF0406A416AD9CFE9FFDACFD1 +:102C9000EAFF3FC02CF040C02DF041C02EF0EECF37 +:102CA00027F0EECF28F0EFCF29F0A5EC3CF026C0BE +:102CB000EDFF25C0EDFF24C0EFFFD9CFE9FFDACF4C +:102CC000EAFFD890020EEB32010EEB32EF32080E23 +:102CD000426ED9CFE9FFDACFEAFF42501F0BEECFA9 +:102CE0003FF0EECF40F0EECF41F006E0D890413219 +:102CF00040323F32E806FAE13F50BE6ED9CFE9FFDD +:102D0000DACFEAFFEE52EE6AEE6ACF0EBD14426EE3 +:102D1000436A446A020E486ED9CFE9FFDACFEAFF70 +:102D200048501F0BEECF45F0EECF46F0EECF47F008 +:102D300006E0D890473246324532E806FAE1425082 +:102D400045103F6E43504610406E44504710416E50 +:102D50003F50BD6E030EE15C02E2E16AE552E16EB6 +:102D6000E552E7CFD9FF1200D9CFE6FFE1CFD9FF77 +:102D7000040EE126FD0EDBCF3FF0FE0EDBCF40F070 +:102D8000000E3FC0DBFF010E40C0DBFF020EDB6A1E +:102D9000030EDB6AE3C03FF0E4C040F0416A426AE0 +:102DA000D9CFE9FFDACFEAFF3FC02BF040C02CF0CB +:102DB00041C02DF042C02EF0EECF26F0EECF27F02E +:102DC000EECF28F0EFCF29F020EC3EF025C0EDFF4C +:102DD00024C0EDFF23C0EDFF22C0EFFFD9CFE9FFF4 +:102DE000DACFEAFF080EE76ED890030EEB32020E40 +:102DF000EB32010EEB32EF32E706F6E1D9CFE9FF15 +:102E0000DACFEAFFD880FF0EEE54FF0EEE54000E2C +:102E1000EE54000EEE5406E2DE68DE68DE6ADD6A1D +:102E2000DD52DD52DFCF3FF0010EDBCF40F03FC07F +:102E3000F3FF40C0F4FF00D0040EE15C02E2E16A5F +:102E4000E552E16EE552E7CFD9FF1200D9CFE6FF98 +:102E5000E1CFD9FF020EE126E3C03FF0E4C040F02D +:102E6000000ED8803F56020E40563FC0DEFF40C0E5 +:102E7000DDFFFE0EDB503F6E406AD9CFE9FFDACFAF +:102E8000EAFF3FC02DF040C02EF0EECF28F0EDCF8E +:102E900029F087EC3CF026C0EEFF27C0EDFFD9CF2C +:102EA000E9FFDACFEAFF080E0F0B06E0EC52D890EC +:102EB000ED32EF32E806FAE1DF5000D03F6E020E4D +:102EC000E15C02E2E16AE552E16E3F50E552E7CF94 +:102ED000D9FF1200E3C0E6FFE66A33EC2AF0E552C0 +:102EE000E552E4C03FF0406A3F50E66E010EE66EE8 +:102EF00033EC2AF0E552E552E5C0E6FF020EE66E3D +:102F000033EC2AF0E552E552E6C0E6FF030EE66E2A +:102F100033EC2AF0E552E5521200E66A55EC2AF04D +:102F2000E5520001E36FE46B010EE66E55EC2AF00A +:102F3000E5523F6E406A3FC040F03F6A3F5000019B +:102F4000E32740500001E423020EE66E55EC2AF020 +:102F5000E5520001E56F030EE66E55EC2AF0E552EE +:102F60000001E66F12000001E96B0001EA6B00014D +:102F7000EB6BEC6B12000201E36B0201E46B0201EC +:102F8000E56BE66B1200D9CFE6FFE1CFD9FF060E65 +:102F9000E126DE6ADD6A020EDB6A030EDB6A040EDE +:102FA000DB6A050EDB6A040EDB6A050EDB6A040EC3 +:102FB000DBCF3FF0050EDBCF40F0D890405004E669 +:102FC000200E3F5C000E40581EE2040EDBCFE9FFEE +:102FD000050EDBCFEAFF030EEA02F3CFEAFF030E92 +:102FE000E902F3CFE9FFF450EA26800EE926020E4B +:102FF000EA22EF50DE26000EDD22040EDB2A050E4B +:1030000001E3DB2AD4D7040EDB6A050EDB6A040E6B +:10301000DBCF3FF0050EDBCF40F0DECF41F0DDCF60 +:1030200042F040504218E8AE02D0423404D0415041 +:103030003F5C425040581EE2040EDB500001F42574 +:103040000F01E96E050EDB500001F5210F01EA6E5C +:10305000EF503F6E406AD950020FE96EDACFEAFFB7 +:103060003F50EE264050ED22040EDB2A050E01E310 +:10307000DB2ACDD7DECF3FF0DDCF40F03F5002015D +:10308000406FDECF3FF0DDCF40F040C03FF0406A00 +:103090003FC041F2FF0EE76E020EDBCF3FF0030EA2 +:1030A000DBCF40F0E7503F16406A3FC042F2020ECD +:1030B000DBCF3FF0030EDBCF40F040C03FF0406A73 +:1030C0003FC043F205EC11F0060EE15C02E2E16A5A +:1030D000E552E16EE552E7CFD9FF1200D9CFE6FF06 +:1030E000E1CFD9FF020EE126A8EC3BF0040EE66E1C +:1030F00060D8E552C450416E426A41C042F0416A14 +:10310000C350000141243F6E000E4220406E3FC07C +:10311000DEFF40C0DDFFDECFE6FFDDCFE6FF24DED1 +:10312000E552E552F3CFDEFFF4CFDDFFDFCF40F213 +:10313000DECF3FF0DDCF40F040C03FF0406A3FC0FF +:1031400041F2E66A36D8E552C450416E426A41C047 +:1031500042F0416AC350000141243F6E000E4220FC +:10316000406E3FC0DEFF40C0DDFFDECFE6FFDDCFBB +:10317000E6FFFADDE552E552F3CFDEFFF4CFDDFFE7 +:10318000DFCF42F2DECF3FF0DDCF40F040C03FF076 +:10319000406A3FC043F205EC11F093EC3BF0020EA5 +:1031A000E15C02E2E16AE552E16EE552E7CFD9FF68 +:1031B0001200D9CFE6FFE1CFD9FFFE0EDB28C26EA9 +:1031C000C282C2B2FED7E552E7CFD9FF1200D9CFF3 +:1031D000E6FFE1CFD9FF020EE126010EEBC0DBFFD7 +:1031E000010EDB503F0803E2DE523F0EDD6E010EA2 +:1031F000DBCF40F2010EDF6E010EDB50D880DF54D2 +:1032000023E30001EA51EA2BEA6A600FE96E000E3F +:10321000EA22EF50E66EDF50EA6A400FE96E020ED6 +:10322000EA22E552E750EF6E0001EA513F6E406A34 +:10323000D890405004E6800E3F5C000E405802E3F8 +:103240000001EA6BDF2AD8D7010EDB503F6E406ADF +:103250003F500001EB5F40500001EC5B05EC11F0CA +:10326000020EE15C02E2E16AE552E16EE552E7CF6F +:10327000D9FF1200D9CFE6FFE1CFD9FF020EE12638 +:10328000010EEBC0DBFF010EDB50400803E2DE5213 +:10329000400EDD6EDF6A010EDB50DF5C23E20001D1 +:1032A000EA51EA2BEA6A600FE96E000EEA22EF505B +:1032B000E66EDF50EA6A400FE96E020EEA22E5523E +:1032C000E750EF6E0001EA513F6E406AD8904050DF +:1032D00004E6800E3F5C000E405802E30001EA6BFA +:1032E000DF2AD9D7010EDB503F6E406A3F50000104 +:1032F000EB5F40500001EC5B05EC11F0020EE15C6D +:1033000002E2E16AE552E16EE552E7CFD9FF120031 +:10331000D9CFE6FFE1CFD9FF200EF36EFE0EDBCF53 +:10332000F4FFF350F45C0DE2FE0EDB50030DF3CF1F +:10333000E9FFF4CFEAFF800EE926020EEA22EF5001 +:1033400003E10001E88B31D0FE0EDB50030DF3CF1B +:10335000E9FFF4CFEAFF800EE926020EEA22EF50E1 +:10336000E66EFE0EDB50030DF3CFE9FFF4CFEAFF6C +:10337000800EE926020EEA22EE5200010001F4510D +:10338000EE243F6E00010001F551EE20406E3FC07B +:10339000E6FF40C0E6FF70DBE552E552E552FD0E68 +:1033A000DB06FD0EDB500008CFE3E552E7CFD9FF87 +:1033B0001200D9CFE6FFE1CFD9FFE652DF6A200E37 +:1033C000DF5C0DE2DF50030DF3CFE9FFF4CFEAFF3E +:1033D000800EE926020EEA22EF6ADF2AF0D7E552D4 +:1033E000E552E7CFD9FF1200D9CFE6FFE1CFD9FFF1 +:1033F000040EE126FD0EDBCFE9FFFE0EDBCFEAFF78 +:10340000EF50EF2AEA6A000FE96E020EEA22EF504F +:10341000E66ED950020FE96EDACFEAFFE552E750C7 +:10342000EE6EED6A020EDB500201E52500013F6EF3 +:10343000030EDB500201E6210001406E000ED88031 +:103440003F54010E405403E20001E88F42D0DE6A8F +:10345000DD6ADECF3FF0DDCF40F0020EDBCF41F082 +:10346000030EDBCF42F041503F5C4250405831E206 +:10347000FD0EDBCFE9FFFE0EDBCFEAFFEF50EF2AB8 +:10348000EA6A000FE96E020EEA22EF50E66E0201D0 +:10349000E351E32BEA6A000FE96E010EEA22E552DE +:1034A000E750EF6E0201E3513F6E406AD890405002 +:1034B00004E6000E3F5C010E405802E30201E36B9C +:1034C0000201E52B000EE623DF2A010E01E3DB2AD1 +:1034D000C0D7040EE15C02E2E16AE552E16EE5521A +:1034E000E7CFD9FF1200D9CFE6FFE1CFD9FF080E11 +:1034F000E126FD0EDBCFE9FFFE0EDBCFEAFFEF2872 +:10350000EA6A000FE96E020EEA22EFCF3FF0406A4E +:103510003FBE4068040E3FC0DBFF050E40C0DBFF2E +:10352000040EDBCF3FF0050EDBCF40F0403404E269 +:103530003F503D08000E405403E20001E88D4FD299 +:10354000FD0EDBCFE9FFFE0EDBCFEAFFEF50EA6AAC +:10355000000FE96E020EEA22EFCF3FF0406A3FBE55 +:103560004068060E3FC0DBFF070E40C0DBFF020EC7 +:10357000DB6A030EDB6ADE6ADD6ADECF3FF0DDCF99 +:1035800040F0D890405004E6200E3F5C000E4058BA +:1035900023E2DECFE9FFDDCFEAFF030EEA02F3CF3D +:1035A000EAFF030EE902F3CFE9FFF450EA26800EAA +:1035B000E926020EEA22EF503F6E406AD950020F10 +:1035C000E96EDACFEAFF3F50EE264050ED22DF2AC7 +:1035D000010E01E3DB2AD1D7060EDBCFE9FF070E90 +:1035E000DBCFEAFF030EEA02F3CFEAFF030EE902A4 +:1035F000F3CFE9FFF450EA26800EE926020EEA2214 +:10360000EF503F6E406AD950020FE96EDACFEAFF01 +:103610003F50EE5E4050ED5A040EDBCF3FF0050EFA +:10362000DBCF40F0020EDBCF41F0030EDBCF42F0E8 +:10363000000ED8804156030E425642504018E8AE64 +:1036400002D0403404D03F50415C4050425803E225 +:103650000001E88DC4D1060EDBCF3FF0070EDBCFB3 +:1036600040F0403404E23F501F08000E405403E293 +:103670000001E88DB4D1060EDBCFE9FF070EDBCFEA +:10368000EAFF030EEA02F3CFEAFF030EE902F3CFEB +:10369000E9FFF450EA26800EE926020EEA22EF50F6 +:1036A00001E106D1060EDBCFE9FF070EDBCFEAFF13 +:1036B000030EEA02F3CFEAFF030EE902F3CFE9FFBC +:1036C000F450EA26800EE926020EEA22EF503F6E01 +:1036D000406A000ED8803F56030E40563F06000E4B +:1036E000405A040E3FC0DBFF050E40C0DBFF060E54 +:1036F000DBCFE9FF070EDBCFEAFF030EEA02F3CFD1 +:10370000EAFF030EE902F3CFE9FFF450EA26800E48 +:10371000E926020EEA22EE52EECFDEFFEDCFDDFF0C +:10372000DECF3FF0DDCF40F0040EDBCF41F0050EE1 +:10373000DBCF42F040504218E8AE02D0423404D011 +:1037400041503F5C4250405835E2060EDBCFE9FF66 +:10375000070EDBCFEAFF030EEA02F3CFEAFF030E08 +:10376000E902F3CFE9FFF450EA26800EE926020EC3 +:10377000EA22EF500001406AF4253F6EF5514022E5 +:10378000DE503F24E96EDD504020EA6EEF50E66ED9 +:10379000DE500001F4250F01E96EDD500001F52136 +:1037A0000F01EA6EE552E750EF6EDF2A010E01E3EA +:1037B000DB2AB6D7DE6ADD6ADECF3FF0DDCF40F030 +:1037C000D890405004E6200E3F5C000E405870E256 +:1037D000DECFE9FFDDCFEAFF030EEA02F3CFEAFF17 +:1037E000030EE902F3CFE9FFF450EA26800EE92642 +:1037F000020EEA22EECF3FF0EECF40F0EFCF41F0E5 +:10380000060EDBCFE9FF070EDBCFEAFF030EEA026D +:10381000F3CFEAFF030EE902F3CFE9FFF450EA2603 +:10382000800EE926020EEA22EE52EECF42F0EFCFF2 +:1038300043F0000143504118E8AE02D0413404D0B7 +:103840004050425C415043582EE2060EDBCFE9FF68 +:10385000070EDBCFEAFF030EEA02F3CFEAFF030E07 +:10386000E902F3CFE9FFF450EA26800EE926020EC2 +:10387000EA22EF503F6E406ADECFE9FFDDCFEAFF7C +:10388000030EEA02F3CFEAFF030EE902F3CFE9FFEA +:10389000F450EA26800EE926020EEA22EE523F504C +:1038A000EE5E4050ED5ADF2A010E01E3DB2A84D799 +:1038B000FD0EDBCFE9FFFE0EDBCFEAFFEF28EA6A61 +:1038C000000FE96E020EEA22EF50E66E060EDBCF25 +:1038D000E9FF070EDBCFEAFF030EEA02F3CFEAFFB0 +:1038E000030EE902F3CFE9FFF450EA26800EE92641 +:1038F000020EEA22E552E750EF6E060EDBCFE9FF3B +:10390000070EDBCFEAFF030EEA02F3CFEAFF030E56 +:10391000E902F3CFE9FFF450EA26800EE926020E11 +:10392000EA22EE52020EDBCFEEFF030EDBCFEDFFFD +:10393000020E3F6EFD0EDBCFE9FFFE0EDBCFEAFF8E +:103940003F50EF26DE6ADD6ADECF3FF0DDCF40F08C +:10395000060EDBCFE9FF070EDBCFEAFF030EEA021C +:10396000F3CFEAFF030EE902F3CFE9FFF450EA26B2 +:10397000800EE926020EEA22EF50000140AE02D08E +:10398000D89003D03F5C000E405829E2FD0EDBCFFB +:10399000E9FFFE0EDBCFEAFFEF50EF2AEA6A000FE5 +:1039A000E96E020EEA22EF50E66E020EDB500001D5 +:1039B000F42500013F6E030EDB500001F5210001EC +:1039C000406EDE503F24E96EDD504020EA6EE55245 +:1039D000E750EF6EDF2A010E01E3DB2AB5D7080EB0 +:1039E000E15C02E2E16AE552E16EE552E7CFD9FF20 +:1039F0001200F29E7BEC3DF0840EA66EFE0EF66E7B +:103A00007F0EF76EF86AF56A0C00550EA76EAA0EC7 +:103A1000A76EA6824E0EE66E58EC3EF0E552FF0011 +:103A20001200F00E0001E71781A402D00001E78721 +:103A300080AA02D00001E78581B802D00001E783A7 +:103A400081A602D00001E781E7C040F2E8C041F260 +:103A50008F0E0001E7170001E86B8B9005EC11F069 +:103A600012000201020E406F0201200E416F02019E +:103A7000426B05EC11F01200D9CFE6FFE1CFD9FF80 +:103A80000D0EE126DF6A0B0EDB6A0C0EDB6AF29A82 +:103A9000070ED56EFC0EDB5004E0FC0EDB503D083B +:103AA00004E20001E88B84EF24F0FE0E0001E8152B +:103AB00002E084EF24F0FC0EDB50DF5C02E384EFD5 +:103AC00024F0DF50E76EFD0EDBCFE9FFFE0EDBCF0B +:103AD000EAFFE750E926000EEA22EF50546EB30EDB +:103AE000545C04E2FC0EDB50DF6EDFD7D50E545C75 +:103AF00001E2CAD3D50E545E549E5446080E542695 +:103B0000F9505424D8B0FA2AF96EA5D39AD3DFD24B +:103B100000D34FD31BD3D8D2D0D266D25DD248D2F5 +:103B20003FD2E6D118D2E0D1CBD192D15AD133D104 +:103B300045D1EED0DDD0C9D0B1D099D070D069D008 +:103B40005ED053D03CD026D023D020D01DD01AD068 +:103B500016D012D00FD00CD009D006D003D000D090 +:103B60008A9890D38A888ED38A868CD38A968AD371 +:103B70008A8488D38A9486D30C0EBA6E83D3BA6AA9 +:103B80008B9280D3898A7ED3899A7CD38B807AD397 +:103B90008B9078D3DF2ADF50E76EFD0EDBCFE9FF95 +:103BA000FE0EDBCFEAFFE750E926000EEA22EFCF58 +:103BB000E0F2E0C2E6FFA3EC28F0E55263D3DF2A8F +:103BC000080EE66EDF50E76EFD0EDBCFE9FFFE0E5E +:103BD000DBCFEAFFE750E926000EEA22EF50E66E5F +:103BE00033EC28F0E552E5524DD3080EE66E03ECB7 +:103BF00028F0E66E33EC28F0E552E55243D3080E88 +:103C0000E66E85EC27F0E552E66ECEEC27F0E55245 +:103C100039D3080EE66E85EC27F0E55233D3DF2A60 +:103C2000DF50E76EFD0EDBCFE9FFFE0EDBCFEAFFD4 +:103C3000E750E926000EEA22EF50E66EDF50E76E0D +:103C4000FD0EDBCFE9FFFE0EDBCFEAFFE750E926F2 +:103C5000000EEA22010EE926000EEA22EF50E66E7F +:103C600033EC28F0E552E552020EDF260CD3DF2AB2 +:103C7000DF50E76EFD0EDBCFE9FFFE0EDBCFEAFF84 +:103C8000E750E926000EEA22EF50E66E03EC28F03A +:103C9000E66E33EC28F0E552E552F4D2DF2ADF502D +:103CA000E76EFD0EDBCFE9FFFE0EDBCFEAFFE7504C +:103CB000E926000EEA22EF50E66E85EC27F0E55289 +:103CC000E66ECEEC27F0E552DDD2DF2ADF50E76E5C +:103CD000FD0EDBCFE9FFFE0EDBCFEAFFE750E92662 +:103CE000000EEA22EF50E66E85EC27F0E552CAD2CC +:103CF000DF2ADF50E76EFD0EDBCFE9FFFE0EDBCFE4 +:103D0000EAFFE750E926000EEA22EFCFE1F2BAD24D +:103D10000B0EDB500EE0040EDB06040EDB5005E15B +:103D20000B0EDB6A030EDF26AED2050EDB50DF6E14 +:103D3000AAD2010EF36E0B0EF3CFDBFFDF50E76E5E +:103D4000FD0EDBCFE9FFFE0EDBCFEAFFE750E926F1 +:103D5000000EEA22010EE926000EEA22EF50DF5C97 +:103D6000E76E050EE7CFDBFFDF50E76EFD0EDBCF22 +:103D7000E9FFFE0EDBCFEAFFE750E926000EEA225C +:103D8000020EE926000EEA22040EEFCFDBFF050E3D +:103D9000DB50DF6E78D2DF2ADF50E76EFD0EDBCF1F +:103DA000E9FFFE0EDBCFEAFFE750E926000EEA222C +:103DB000EF50E66E1DEC27F0E55264D2DF2ADF50AB +:103DC000E76EFD0EDBCFE9FFFE0EDBCFEAFFE7502B +:103DD000E926000EEA22EF50E66EB3EC24F0E5523D +:103DE00051D20001E905EA6A600FE96E000EEA228D +:103DF000010EEFCFDBFFDF50E76EFD0EDBCFE9FFFB +:103E0000FE0EDBCFEAFFE750E926000EEA22010EA4 +:103E1000E926000EEA22EF50F36E010EDB50F35C50 +:103E200014E1DF50E76EFD0EDBCFE9FFFE0EDBCFC6 +:103E3000EAFFE750E926000EEA22020EE926000E0C +:103E4000EA22EF50DF24DF6E02D0030EDF261BD202 +:103E50000001E905EA6A600FE96E000EEA22010E30 +:103E6000EFCFDBFF010EDBCF3FF0DF50E76EFD0E43 +:103E7000DBCFE9FFFE0EDBCFEAFFE750E926000EBD +:103E8000EA22010EE926000EEA22EF50D8803F54C4 +:103E900014E2DF50E76EFD0EDBCFE9FFFE0EDBCF55 +:103EA000EAFFE750E926000EEA22020EE926000E9C +:103EB000EA22EF50DF24DF6E02D0030EDF26E3D1CB +:103EC000DF50E76EFD0EDBCFE9FFFE0EDBCFEAFF32 +:103ED000E750E926000EEA22010EE926000EEA224A +:103EE000EF50DF24DF6ECFD1FC0EDB50DF6ECBD185 +:103EF000DF2ADF50DF2AE76EFD0EDBCFE9FFFE0E83 +:103F0000DBCFEAFFE750E926000EEA22EF50406AD5 +:103F1000000F3F6E0F0E4022090E3FC0DBFF0A0E5E +:103F200040C0DBFFDF50DF2AE76EFD0EDBCFE9FF8D +:103F3000FE0EDBCFEAFFE750E926000EEA22EF5043 +:103F4000E66E090EDBCFE9FF0A0EDBCFEAFFE55292 +:103F5000E750EF6E98D1DF2ADF50E76EFD0EDBCF22 +:103F6000E9FFFE0EDBCFEAFFE750E926000EEA226A +:103F7000EF50406A000F3F6E0F0E4022090E3FC007 +:103F8000DBFF0A0E40C0DBFF090EDBCFE9FF0A0EA4 +:103F9000DBCFEAFFEF50E66ECEEC27F0E55272D1B0 +:103FA000DF2A44EC25F0E66ECEEC27F0E5526BD12B +:103FB000DF2ADF50DF2AE76EFD0EDBCFE9FFFE0EC2 +:103FC000DBCFEAFFE750E926000EEA22EF50E66E6B +:103FD000C6EC24F0E55257D1DF2A03EC28F0E66E58 +:103FE000C6EC24F0E5524FD10C0EDB5016E0070E64 +:103FF000DB06080E01E2DB06D950070FE96EDACFC7 +:10400000EAFFEE50ED1005E10C0EDB6A020EDF2632 +:104010003AD1060EDB50DF6E36D1DF50E76EFD0E73 +:10402000DBCFE9FFFE0EDBCFEAFFE750E926000E0B +:10403000EA22010EE926000EEA22EF50DF5CE76E6D +:10404000060EE7CFDBFF03EC28F0E66ED950070F32 +:10405000E96EDACFEAFFE552E750EE6EED6A03EC67 +:1040600028F0416E426A286A010E296E41C02DF087 +:1040700042C02EF05AEC3CF026C03FF027C040F082 +:10408000D950070FE96EDACFEAFF3F50EE264050D5 +:10409000ED22D950070FE96EDACFEAFFEE50ED10AE +:1040A00003E1020EDF26EFD0010EF36E0C0EF3CF0C +:1040B000DBFF060EDB50DF6EE6D0C3EC28F0E66EC9 +:1040C000CEEC27F0E552DED003EC28F0DBD0040E76 +:1040D000E66E010EE66E33EC28F0E552E552080E6E +:1040E000E66EE66A33EC28F0E552E552080EE66E1D +:1040F0003CEC27F0E552E66ECEEC27F0E552080ED8 +:10410000E66E3CEC27F0E552E66ECEEC27F0E55289 +:10411000B9D0040EE66EE66A33EC28F0E552E552BB +:10412000080EE66EE66A33EC28F0E552E552080E1A +:10413000E66EE66A33EC28F0E552E552080EE66ECC +:10414000E66A33EC28F0E552E5529CD0DF2A040EF3 +:10415000E66EE66A33EC28F0E552E552080EE66EAC +:10416000DF50DF2AE76EFD0EDBCFE9FFFE0EDBCF6F +:10417000EAFFE750E926000EEA22EF50E66E33EC44 +:1041800028F0E552E552080EE66EDF50DF2AE76EB2 +:10419000FD0EDBCFE9FFFE0EDBCFEAFFE750E9269D +:1041A000000EEA22EF50E66E33EC28F0E552E552BD +:1041B0006AD0DF2A040EE66EE66A33EC28F0E55298 +:1041C000E552080EE66EDF50DF2AE76EFD0EDBCF0C +:1041D000E9FFFE0EDBCFEAFFE750E926000EEA22F8 +:1041E000EF50E66E33EC28F0E552E552080EE66E2D +:1041F000DF50DF2AE76EFD0EDBCFE9FFFE0EDBCFDF +:10420000EAFFE750E926000EEA22EF50E66E33ECB3 +:1042100028F0E552E552080EE66EDF50DF2AE76E21 +:10422000FD0EDBCFE9FFFE0EDBCFEAFFE750E9260C +:10423000000EEA22EF50E66E33EC28F0E552E5522C +:1042400022D0080EE66E3CEC27F0E552E66ECEEC8E +:1042500027F0E55217D0DF2ADF50E76EFD0EDBCFE7 +:10426000E9FFFE0EDBCFEAFFE750E926000EEA2267 +:10427000EF50E66E3CEC27F0E552E66ECEEC27F010 +:10428000E55200D0DF2A11D4B30E545E549E54463A +:10429000080E5426F9505424D8B0FA2AF96E6AD27E +:1042A00070D227D3C6D216D3C7D273D250D23CD243 +:1042B00013D2D7D1ACD185D17ED16AD163D157D1B8 +:1042C0003FD135D12DD119D10ED104D1FCD0E8D0B8 +:1042D000E4D0E0D0D8D0C2D0AAD081D06ED001D066 +:1042E00035D0DF2A040EE66EE66A33EC28F0E5529C +:1042F000E552040EE66EDF50E76EFD0EDBCFE9FF00 +:10430000FE0EDBCFEAFFE750E926000EEA22EF506F +:10431000E66E33EC28F0E552E552080EE66E03EC4B +:1043200028F0E66E33EC28F0E552E552080EE66E12 +:10433000E66A33EC28F0E552E552040EE66E020E12 +:10434000E66E33EC28F0E552E5529CD7DF2A040EE6 +:10435000E66EE66A33EC28F0E552E552040EE66EAE +:10436000DF50E76EFD0EDBCFE9FFFE0EDBCFEAFF8D +:10437000E750E926000EEA22EF50E66E33EC28F013 +:10438000E552E552080EE66E03EC28F0E66E33ECDB +:1043900028F0E552E552080EE66E03EC28F0E66ED2 +:1043A00033EC28F0E552E552040EE66E020EE66E9E +:1043B00033EC28F0E552E55265D7DF2ADF50E76E8F +:1043C000FD0EDBCFE9FFFE0EDBCFEAFFE750E9266B +:1043D000000EEA22EF50E66EA1DAE55253D7DF2A4B +:1043E000DF50E76EFD0EDBCFE9FFFE0EDBCFEAFF0D +:1043F000E750E926000EEA22EF50E66EDF50E76E46 +:10440000FD0EDBCFE9FFFE0EDBCFEAFFE750E9262A +:10441000000EEA22010EE926000EEA22EF50E66EB7 +:104420006BEC28F0E552E552020EDF262CD7DF2A8E +:10443000DF50E76EFD0EDBCFE9FFFE0EDBCFEAFFBC +:10444000E750E926000EEA22EF50E66E03EC28F072 +:10445000E66E6BEC28F0E552E55214D7DF2ADF5008 +:10446000E76EFD0EDBCFE9FFFE0EDBCFEAFFE75084 +:10447000E926000EEA22EFCFE2F2E2C2E6FFD6EC36 +:1044800028F0E552FFD6EAEC28F0E66ECEEC27F0F5 +:10449000E552F8D6FBEC28F0F5D610EC29F0F2D670 +:1044A000DF2ADF50E76EFD0EDBCFE9FFFE0EDBCF2C +:1044B000EAFFE750E926000EEA22EF50E66E25EC0F +:1044C00029F0E552DFD603EC28F0E66E25EC29F062 +:1044D000E552D8D6E66A8EEC29F0E552E66ECEECCF +:1044E00027F0E552CFD60F0EE66E8EEC29F0E5529E +:1044F000E66ECEEC27F0E552C5D6DF2ADF50E76E38 +:10450000FD0EDBCFE9FFFE0EDBCFEAFFE750E92629 +:10451000000EEA22EF50E66EF5EC29F0E552B2D635 +:1045200003EC28F0E66EF5EC29F0E552ABD6E66A2E +:10453000F5EC29F0E552E66ECEEC27F0E552A2D676 +:10454000DF2ADF50E76EFD0EDBCFE9FFFE0EDBCF8B +:10455000EAFFE750E926000EEA22EF50E66EF5EC9E +:1045600029F0E552E66ECEEC27F0E5528BD603EC4F +:1045700028F0E66EF5EC29F0E552E66ECEEC27F079 +:10458000E55280D67ADBE66ECEEC27F0E5527AD69D +:10459000DF2ADF50DF2AE76EFD0EDBCFE9FFFE0EDC +:1045A000DBCFEAFFE750E926000EEA22EF50E66E85 +:1045B000DCDAE55268D603EC28F0E66ED6DAE5528E +:1045C00061D6CEDB020EF3CFDBFF030EF4CFDBFFB1 +:1045D000FF0EE76E020EDBCF3FF0030EDBCF40F0A5 +:1045E000E7503F16406A3F50E66ECEEC27F0E552AA +:1045F000020EDBCF3FF0030EDBCF40F040C03FF0B8 +:10460000406A3F50E66ECEEC27F0E5523BD6DF2AFB +:10461000E66ADF50E76EFD0EDBCFE9FFFE0EDBCF73 +:10462000EAFFE750E926000EEA22010EE926000E15 +:10463000EA22EF50E66EDF50E76EFD0EDBCFE9FFBA +:10464000FE0EDBCFEAFFE750E926000EEA22EF502C +:10465000E66E64EC2AF0E552E552E552020EDF26E2 +:1046600012D6DF2ADF50E76EFD0EDBCFE9FFFE0E2C +:10467000DBCFEAFFE750E926000EEA22020EE92628 +:10468000000EEA22EF50E66EDF50E76EFD0EDBCF44 +:10469000E9FFFE0EDBCFEAFFE750E926000EEA2233 +:1046A000010EE926000EEA22EF50E66EDF50E76EBB +:1046B000FD0EDBCFE9FFFE0EDBCFEAFFE750E92678 +:1046C000000EEA22EF50E66E64EC2AF0E552E55265 +:1046D000E552030EDF26D7D5DF2ADF50E76EFD0E49 +:1046E000DBCFE9FFFE0EDBCFEAFFE750E926000E45 +:1046F000EA22010EE926000EEA22EF50E66EDF50B4 +:10470000E76EFD0EDBCFE9FFFE0EDBCFEAFFE750E1 +:10471000E926000EEA22EF50E66EB9EC2BF0E552E6 +:10472000E552020EDF26AFD5DF2ADF50E76EFD0E21 +:10473000DBCFE9FFFE0EDBCFEAFFE750E926000EF4 +:10474000EA22EF50E66EFDEC2BF0E5529BD5DF2A16 +:10475000DF50E76EFD0EDBCFE9FFFE0EDBCFEAFF99 +:10476000E750E926000EEA22EF50E66E1EEC2CF030 +:10477000E55288D5E66AE66A81EC2DF0E552E5520D +:1047800081D5010EE66EE66A81EC2DF0E552E55228 +:1047900079D5DF2A010EE66EDF50E76EFD0EDBCF26 +:1047A000E9FFFE0EDBCFEAFFE750E926000EEA2222 +:1047B000EF50E66EDF50E76EFD0EDBCFE9FFFE0E39 +:1047C000DBCFEAFFE750E926000EEA22010EE926D8 +:1047D000000EEA22EF50E66EDF50E76EFD0EDBCFF3 +:1047E000E9FFFE0EDBCFEAFFE750E926000EEA22E2 +:1047F000020EE926000EEA22EF50E66EDF50E76E69 +:10480000FD0EDBCFE9FFFE0EDBCFEAFFE750E92626 +:10481000000EEA22030EE926000EEA22EF50E66EB1 +:104820004EEC2CF03F6E050EE15E3F50040EDF268D +:104830002AD530EC2DF026D5DF2ADF50E76EFD0EAD +:10484000DBCFE9FFFE0EDBCFEAFFE750E926000EE3 +:10485000EA22EF50E66EDF50E76EFD0EDBCFE9FF98 +:10486000FE0EDBCFEAFFE750E926000EEA22010E3A +:10487000E926000EEA22EF50E66EDF50E76EFD0EED +:10488000DBCFE9FFFE0EDBCFEAFFE750E926000EA3 +:10489000EA22020EE926000EEA22EF50E66EDF5011 +:1048A000E76EFD0EDBCFE9FFFE0EDBCFEAFFE75040 +:1048B000E926000EEA22030EE926000EEA22EF5056 +:1048C000E66EDFEC2CF0E552E552E552E552040EBF +:1048D000DF26D9D498DBE66E96DBE66E94DBE66ED7 +:1048E00092DBE66EDFEC2CF0E552E552E552E55244 +:1048F000C9D4010EE66E010EE66E81EC2DF0E55294 +:10490000E552C0D455EF1DF00D0EE15C02E2E16A04 +:10491000E552E16EE552E7CFD9FF1200D9CFE6FFAD +:10492000E1CFD9FF0201E351E32BEA6A000FE96E00 +:10493000010EEA22FE0EDBCFEFFF0201E3513F6ED4 +:10494000406AD890405004E6000E3F5C010E40588B +:1049500002E30201E36B0201E52B000EE623E552C0 +:10496000E7CFD9FF1200D9CFE6FFE1CFD9FFF2940C +:10497000FE0EDB50FF0DF350D76ED66AD58EF2A433 +:10498000FED7D59EE552E7CFD9FF1200D9CFE6FF7B +:10499000E1CFD9FFF29ECD90A40ED76E730ED66EE6 +:1049A000F294D58E8050080B04E1F250040B01E123 +:1049B000F9D7F2B45DD089949294600EE66E91ECD2 +:1049C0003EF0E55289848050080B04E0F250040B5D +:1049D00001E1F9D7F2B44CD0FE0EDB50546EF2B6C2 +:1049E00046D080A6FCD7899454BE898480B6FED771 +:1049F000F2B63DD080A6FCD7899454BC898480B699 +:104A0000FED7F2B634D080A6FCD7899454BA8984F4 +:104A100080B6FED7F2B62BD080A6FCD7899454B8C6 +:104A2000898480B6FED7F2B622D080A6FCD78994BE +:104A300054B6898480B6FED7F2B619D080A6FCD7CA +:104A4000899454B4898480B6FED7F2B610D080A67B +:104A5000FCD7899454B2898480B6FED7F2B607D0C9 +:104A600080A6FCD7899454B0898480B6FED7000014 +:104A7000F2A402D00001E885D59EF28ECD8000D050 +:104A8000E552E7CFD9FF1200CD90F29EA40ED76E6B +:104A9000730ED66EF294D58E8050080B04E1F2505E +:104AA000040B01E1F9D7F2B454D089949294600ECA +:104AB000E66E91EC3EF0E55289848050080B04E0EC +:104AC000F250040B01E1F9D79284F2B442D0546A57 +:104AD000F2B63ED080A6FCD780B6FED780B4548E06 +:104AE000F2B636D080A6FCD780B6FED780B4548C00 +:104AF000F2B62ED080A6FCD780B6FED780B4548AFA +:104B0000F2B626D080A6FCD780B6FED780B45488F3 +:104B1000F2B61ED080A6FCD780B6FED780B45486ED +:104B2000F2B616D080A6FCD780B6FED780B45484E7 +:104B3000F2B60ED080A6FCD780B6FED780B45482E1 +:104B4000F2B606D080A6FCD780B6FED780B45480DB +:104B5000000089849294F2A402D00001E885D59ED9 +:104B6000F28ECD80545000D01200D9CFE6FFE1CFB5 +:104B7000D9FFF29ECD90A40ED76E730ED66EF2942E +:104B8000D58E92848050040B04E0F250040B01E1B6 +:104B9000F9D7F2B45FD092968986600EE66E91ECFA +:104BA0003EF0E55289968050040B04E1F250040B6C +:104BB00001E1F9D792869294F2B44CD0FE0EDB500C +:104BC000546EF2B646D080A6FCD7899454BE898430 +:104BD00080B6FED7F2B63DD080A6FCD7899454BCEF +:104BE000898480B6FED7F2B634D080A6FCD78994EB +:104BF00054BA898480B6FED7F2B62BD080A6FCD7F3 +:104C0000899454B8898480B6FED7F2B622D080A6A3 +:104C1000FCD7899454B6898480B6FED7F2B619D0F1 +:104C200080A6FCD7899454B4898480B6FED7F2B6A6 +:104C300010D080A6FCD7899454B2898480B6FED760 +:104C4000F2B607D080A6FCD7899454B0898480B688 +:104C5000FED70000F2A402D00001E885600EE66EE7 +:104C600091EC3EF0E552D59EF28ECD8092849296E4 +:104C700000D0E552E7CFD9FF1200CD90F29EA40EEE +:104C8000D76E730ED66EF294D58E92848050040B3C +:104C900004E0F250040B01E1F9D7F2B455D092963A +:104CA0008986600EE66E91EC3EF0E5528996805062 +:104CB000040B04E1F250040B01E1F9D792849286CF +:104CC000F2B442D0546AF2B63ED080A6FCD780B689 +:104CD000FED780B4548EF2B636D080A6FCD780B60C +:104CE000FED780B4548CF2B62ED080A6FCD780B606 +:104CF000FED780B4548AF2B626D080A6FCD780B600 +:104D0000FED780B45488F2B61ED080A6FCD780B6F9 +:104D1000FED780B45486F2B616D080A6FCD780B6F3 +:104D2000FED780B45484F2B60ED080A6FCD780B6ED +:104D3000FED780B45482F2B606D080A6FCD780B6E7 +:104D4000FED780B454800000F2A402D00001E885B0 +:104D5000D59E92849296F28ECD80545000D012004F +:104D6000D9CFE6FFE1CFD9FF030EE126DF6AF29447 +:104D7000800ED76ED66AD58EF2AE02D0010EDF6EEF +:104D8000F29E80A40AD0F2A407D0D59EDF0401E1F0 +:104D9000F28EF36AF46A47D0F4D780B40AD0F2A452 +:104DA00007D0D59EDF0401E1F28EF36AF46A3BD0AE +:104DB000F4D7800ED76ED66AF29480A40AD0F2A4FB +:104DC00007D0D59EDF0401E1F28EF368F4682BD0A2 +:104DD000F4D7D59EDF0401E1F28ED650E66ED950AD +:104DE000010FE96EDACFEAFFE552E750EE6EED6AA9 +:104DF0007F0ED7143F6E406A3FC040F03F6AD950E3 +:104E0000010FE96EDACFEAFF3F50EE264050ED2267 +:104E1000010EDBCF3FF0020EDBCF40F03FC0F3FFCF +:104E200040C0F4FF00D0030EE15C02E2E16AE5520B +:104E3000E16EE552E7CFD9FF1200D9CFE6FFE1CF0F +:104E4000D9FFF294D768080EE66E9FEC3EF0E5526B +:104E5000FE0EDB0402E10CD002D0FE0EDB06FE0EDD +:104E6000DB50FF0DF350D66ED58EF2A4FED7D59E43 +:104E7000E552E7CFD9FF1200D9CFE6FFE1CFD9FF46 +:104E8000E6529284546AFE0EDB50556E020E020109 +:104E9000E15D0CE280B454808986000000000000CF +:104EA000899600005442552EF5D718D00201E1052D +:104EB000566E565080B45480898600000000000071 +:104EC00000000000E82EFBD7899656500000000035 +:104ED0000000E82EFBD75442552EEBD7FE0EDBCF59 +:104EE000E6FF080EE552D880E754070B04E0544271 +:104EF000549EE806FCE10201E0A39294545000D0D5 +:104F0000E552E552E7CFD9FF1200D9CFE6FFE1CF56 +:104F1000D9FFE6529284546AFE0EDB50556E020EA3 +:104F20000201E15D0CE2898600000000000080B40F +:104F30005480899600005442552EF5D718D00201AE +:104F4000E105566E89860000000056500000000002 +:104F50000000E82EFBD780B454808996565000009C +:104F600000000000E82EFBD75442552EEBD7FE0E72 +:104F7000DBCFE6FF080EE552D880E754070B04E0CC +:104F80005442549EE806FCE10201E0A3929454507E +:104F900000D0E552E552E7CFD9FF1200D9CFE6FFA6 +:104FA000E1CFD9FF010E0001406AEB253F6EEC51C5 +:104FB0004022800ED8803F54000E405403E200018E +:104FC000E8871DD00001E951E92BEA6A600FE96E1C +:104FD000000EEA22FE0EDBCFEFFF0001E9513F6E2B +:104FE000406AD890405004E6800E3F5C000E405866 +:104FF00002E30001E96B0001EB2B000EEC23E5520C +:10500000E7CFD9FF1200D9CFE6FFE1CFD9FFE652B3 +:105010000201E551E61104E10001E889000E1ED00D +:105020000201E451E42BEA6A000FE96E010EEA2264 +:10503000EFCFDFFF0201E507000EE65B0201E4515E +:105040003F6E406AD890405004E6000E3F5C010E6F +:10505000405802E30201E46BDF5000D0E552E55214 +:10506000E7CFD9FF1200D9CFE6FFE1CFD9FFE65253 +:10507000FE0EDB50546EFD0EDB50556E020E02012B +:10508000E15D0CE254A0899454B0898400008986C3 +:10509000000089965442552EF5D718D00201E1053B +:1050A000566E54A0899454B0898456500000000074 +:1050B0000000E82EFBD78986565000000000000053 +:1050C000E82EFBD789965442552EEBD7E552E55290 +:1050D000E7CFD9FF1200D9CFE6FFE1CFD9FFE652E3 +:1050E000FE0EDB50546EFD0EDB50556E020E0201BB +:1050F000E15D0CE254A0899454B089848986000053 +:10510000899600005442552EF5D718D00201E105CA +:10511000566E54A0899454B08984565089860000F4 +:1051200000000000E82EFBD78996565000000000D2 +:105130000000E82EFBD75442552EEBD7E552E5523E +:10514000E7CFD9FF1200D9CFE6FFE1CFD9FFFE0E9E +:10515000DBA402D0898601D08996FE0EDBA602D0A0 +:10516000898401D08994FE0EDBA002D0928601D002 +:105170009296FE0EDBA202D0928401D09294E55268 +:10518000E7CFD9FF1200D9CFE6FFE1CFD9FFE65232 +:10519000DF6A80B4DF8280A602D0000EDB80DF50A1 +:1051A00000D0E552E552E7CFD9FF1200D9CFE6FF94 +:1051B000E1CFD9FFFE0EDBA202D0898801D0899809 +:1051C000FE0EDBA002D0928801D09298E552E7CF84 +:1051D000D9FF1200D9CFE6FFE1CFD9FFE652DF6A4F +:1051E00080A802D0000EDB80DF5000D0E552E552EF +:1051F000E7CFD9FF12008986060EE66E9FEC3EF0DF +:10520000E55289989298060EE66E9FEC3EF0E552C4 +:105210008996060EE66E9FEC3EF0E55292881200EB +:105220008996060EE66E9FEC3EF0E55289989298BC +:10523000060EE66E9FEC3EF0E5528986060EE66E9F +:105240009FEC3EF0E55292881200D9CFE6FFE1CF05 +:10525000D9FFFE0EDB50546E080E556E8998020E73 +:105260000201E15D23E254AE929854BE928800D0D0 +:1052700000D000D08986000000D000D000D000D03F +:105280008996000000D000D05446552EECD7928865 +:1052900000D000D000D000D000D08986000000D01F +:1052A00000D000D080B8558089962FD00201E151FE +:1052B000E824FF0F566E54AE929854BE9288565012 +:1052C000000000D000D000D0E82EFAD789865650D2 +:1052D00000D000D000D0E82EFDD7899600005446BB +:1052E000552EE9D79288565000D000D0000000D04B +:1052F00000D000D0E82EFAD78986565000D000D0D2 +:10530000E82EFDD780B8558089965550000802E2F6 +:105310000001E885E552E7CFD9FF1200D9CFE6FFBB +:10532000E1CFD9FF546A080E556E010E566E928871 +:10533000020E0201E15D14E2544600D000D000D01C +:1053400000D00000898600D000D000D0000080B8D6 +:105350005480899600D000D000D0552EEDD725D0AE +:105360000201E151E824FF0F566E5446000000D0C0 +:10537000565000D000D000D00000E82EFAD7898621 +:10538000565000D000D0E82EFDD780B854808996C2 +:1053900000D0552EEAD70000565000D000D000D0E3 +:1053A00000D000D00000E82EFAD78998FE0EDB501E +:1053B00001E19298565000D000D000D000D000D02B +:1053C0000000E82EFAD78986565000D000D0E82E8B +:1053D000FDD700D0899600D000000000928854507C +:1053E00000D0E552E7CFD9FF1200D9CFE6FFE1CFD9 +:1053F000D9FFE652FE0EDB50546E080E556E020EBB +:105400000201E15D0DE254AE899854BE8988898617 +:105410005446549080B454808996552EF4D71BD0AE +:105420000201E105566E54AE899854BE89885650E3 +:10543000000000000000E82EFBD7898654465490F7 +:1054400080B454805650000000000000E82EFBD7C6 +:105450008996552EE8D78998545000D0E552E552E8 +:10546000E7CFD9FF1200D9CFE6FFE1CFD9FFE6524F +:10547000DF6AFE0EDB50A96EFD0EDB50A86EA66A39 +:10548000A684F2AE02D0010EDF6EF29E550EA76E1C +:10549000AA0EA76EA682DF0401E1F28EA6B2FED7A5 +:1054A000E552E552E7CFD9FF1200D9CFE6FFE1CFB1 +:1054B000D9FFFE0EDB50A96EA66AA680A85000D0C8 +:1054C000E552E7CFD9FF1200D9CFE6FFE1CFD9FFF0 +:1054D000040EE126DF6A010EDB6A0201E1510108D8 +:1054E00008E2120E566E0F0EF36E030EF3CFDBFFC3 +:1054F00007D0C60E566E030EF36E030EF3CFDBFF1E +:1055000089889298180EE66E9FEC3EF0E552020EE6 +:105510003F6EFD0EDBCFE7FF3F50E726FD0EE7CFE6 +:10552000DBFF480ED56E550E546E8998D66AF294FC +:10553000D58EF2AE02D0010EDF6EF29EFD0EDB06BE +:10554000020EDB6A020EDBCF3FF0080EE76E3F185B +:10555000E8AE02D0E73402D0E7503F5C21E2895048 +:10556000EF0B54AE1009F2A4FED7896E5650D62622 +:105570009298F294549E54468950556EFD0EDB501D +:1055800005E1FC0EDB5002E1558801D05598F2A4EC +:10559000FED789785650D626F294020EDB2AD2D74F +:1055A0005550F2A4FED7896E5650D626F294010EBD +:1055B000DB5007E0FD0EDB50000803E224DD546EF3 +:1055C00003D0FE0EDB50546EF2A4FED789785650FD +:1055D000D626F294F2A4FED792885650D626F2949C +:1055E000030EDBCFE6FF9FEC3EF0E552010EDB50F1 +:1055F00009E08050100B06E00001E885FD0EDB6A33 +:10560000FC0EDB6AF2A4FED700005650D626F294B8 +:10561000030EDBCFE6FF9FEC3EF0E552010EDB50C0 +:1056200009E08050100B06E10001E885FD0EDB6A01 +:10563000FC0EDB6ADE52010EDD6EFD0EDB50000853 +:1056400001E27CD7FC0EDBCFF3FFDB06F350000852 +:1056500001E37FD0546A020EDB6A020EDBCF3FF01B +:10566000080EE76E3F18E8AE02D0E73402D0E750EC +:105670003F5C30E2F2A4FED70000D66AF294895073 +:10568000556EFC0EDB5002E1558801D05598030E93 +:10569000DB04E66E9FEC3EF0E55280B807D0F2B432 +:1056A00002D080A8FCD75650D66E06D0F2B402D0F5 +:1056B00080B8FCD75650D66EF294030EDBCFE6FFCF +:1056C0009FEC3EF0E552549E544680B8542A020E98 +:1056D000DB2AC3D75550F2A4FED7896E5650D62682 +:1056E0009298F2945450E66E59DCE552F2A4FED73B +:1056F00089785650D626F294F2A4FED79288565056 +:10570000D626F294030EDBCFE6FF9FEC3EF0E55287 +:10571000010EDB5007E08050100B04E00001E8852B +:10572000FC0EDB6AF2A4FED700005650D626F29497 +:10573000030EDBCFE6FF9FEC3EF0E552010EDB509F +:1057400007E08050100B04E10001E885FC0EDB6AE5 +:1057500079D7DF0401E1F28E070ED56E9288040E30 +:10576000E15C02E2E16AE552E16EE552E7CFD9FF82 +:105770001200D9CFE6FFE1CFD9FFE652FE0EDB5093 +:1057800001E10FD0546AFD0EDB50556EDF6AFE0E4C +:10579000DB50DF5C06E247EC38F055905542DF2ADB +:1057A000F6D7E552E552E7CFD9FF1200D9CFE6FF91 +:1057B000E1CFD9FFE652FE0EDB5002E1000E18D019 +:1057C000FD0EDB50546EFC0EDB50556E566ADF6AE0 +:1057D000FE0EDB50DF5C0AE25690564247EC38F092 +:1057E0005490544255905542DF2AF2D7565000D07B +:1057F000E552E552E7CFD9FF1200D9CFE6FFE1CF5E +:10580000D9FF030EE66E040EE66EB3DFE552E552F5 +:10581000100EE66EFE0EDBCFE6FF050EE66EC6DF6F +:10582000E552E552E552010EE66E020EE66EA1DF8C +:10583000E552E552E552E7CFD9FF1200D9CFE6FF96 +:10584000E1CFD9FFE652DF6A010EE66E030EE66E87 +:1058500090DFE552E55256AE02D0010EDF6E800EAB +:10586000E66EFE0EDBCFE6FF080EE66E9FDFE5522A +:10587000E552E5525650E824DF12DFCFE6FFCEECCA +:1058800027F0E552010EE66E020EE66E72DFE5527B +:10589000E552E552E552E7CFD9FF1200D9CFE6FF36 +:1058A000E1CFD9FF020EE126DF6A010EDB6A010EAD +:1058B000E66E030EE66E5DDFE552E55256AE02D0AF +:1058C000010EDF6EE66AFB0EDBCFE6FF080EE66E2A +:1058D0006DDFE552E552E5525650E824DF12FA0E2C +:1058E000DB5005E0DFCFE6FFCEEC27F0E552DF6AC4 +:1058F00056AE02D0010EDF6EE66AFC0EDBCFE6FF8D +:10590000080EE66E53DFE552E552E5525650E824A4 +:10591000DF12FA0EDB5005E0DFCFE6FFCEEC27F01A +:10592000E552DF6A56AE02D0010EDF6EE66AFD0E6A +:10593000DBCFE6FF080EE66E39DFE552E552E552B1 +:105940005650E824DF12FA0EDB5005E0DFCFE6FF09 +:10595000CEEC27F0E552010EDFCFDBFFDF6A56AE5B +:1059600002D0010EDF6E800EE66EFE0EDBCFE6FF8C +:10597000080EE66E1BDFE552E552E5525650E8246C +:10598000DF12FA0EDB5005E0DFCFE6FFCEEC27F0AA +:10599000E552010EE66E020EE66EEBDEE552E552D2 +:1059A000010EDB5000D03F6E020EE15C02E2E16AC4 +:1059B000E552E16E3F50E552E7CFD9FF1200D9CF53 +:1059C000E6FFE1CFD9FF010EE66E030EE66ED1DEF3 +:1059D000E552E55256BE0AD01F0EE66E050EE66E83 +:1059E000C8DEE552E5520001E88536D0E66A010ED0 +:1059F000E66EBFDEE552E552E66AFB0EDBCFE6FF60 +:105A0000080EE66ED3DEE552E552E552E66AFC0E7C +:105A1000DBCFE6FF080EE66EC9DEE552E552E55241 +:105A2000E66AFD0EDBCFE6FF080EE66EBFDEE5524E +:105A3000E552E552800EE66EFE0EDBCFE6FF080E65 +:105A4000E66EB4DEE552E552E552010EE66E020E58 +:105A5000E66E8FDEE552E552E552E7CFD9FF120040 +:105A6000D9CFE6FFE1CFD9FFE652D76AD66AF294E2 +:105A7000D58E0A0EE66EC1DEE552E66AE66AD00E03 +:105A8000E66E040EE66EE66A09DF3F6E050EE15E25 +:105A90003F50DF6E040EDF1403E1F250040BEDE023 +:105AA000F2A404D00001E885D59E26D0090EE66E4A +:105AB000A4DEE552E66A03EC28F0E66E03EC28F07B +:105AC000E66E03EC28F0E66E03EC28F0E66EE6DE08 +:105AD0003F6E050EE15E3F500A0EE66E8EDEE55229 +:105AE000E66AE66AC00EE66EE66AE66AD7DE3F6EF2 +:105AF000050EE15E3F50D59EE552E552E7CFD9FF56 +:105B00001200D9CFE6FFE1CFD9FFE652D76AD66AB5 +:105B1000F294D58E0A0EE66E70DEE552E66AE66A0B +:105B2000D00EE66E040EE66EE66AB8DE3F6E050E37 +:105B3000E15E3F50DF6E040EDF1403E1F250040B10 +:105B4000EDE0F2A404D00001E885D59E23D0090E33 +:105B5000E66E53DEE552FE0EDBCFE6FFE66AE66A4E +:105B6000E66AE66A9BDE3F6E050EE15E3F50FD0E83 +:105B7000DB500FE00A0EE66E40DEE552E66AE66AAA +:105B8000C00EE66EE66AE66A89DE3F6E050EE15EED +:105B90003F50D59EE552E552E7CFD9FF1200D9CF4D +:105BA000E6FFE1CFD9FF020EE126F29EA8EC3BF022 +:105BB000928492869288D9EC19F08B80E950DF6E3E +:105BC000010EEACFDBFF5F5002E05F6A02D058505F +:105BD0005F6E5DEC38F05E50000803E2E5EC38F0F3 +:105BE00007D05F5003E0AAEC38F002D06FEC38F039 +:105BF000DF50E96E010EDB50EA6E8B9093EC3BF0C8 +:105C0000F28E54C040F255C041F205EC11F0020E84 +:105C1000E15C02E2E16AE552E16EE552E7CFD9FFCD +:105C200012000100567D0000F40000000200000098 +:105C3000D9CFE6FFE1CFD9FFE6520401B06B0401F2 +:105C4000B16BB26B396AC56AC76A280EC66E1F0E81 +:105C5000C86EC584C5B4FED7E552E552E7CFD9FF7B +:105C60001200D9CFE6FFE1CFD9FFE6528B9C67D86F +:105C70000401B06B9E960401B051B02BEA6AC00FCC +:105C8000E96E040EEA22EF50C96E9EA6FED7C5BC8F +:105C9000C584400E0401B05DEDE3C584C5B4FED7F4 +:105CA000060EE66E58EC3EF0E5520401B06B0401BE +:105CB000B12B000EB2238B8CE552E552E7CFD9FF12 +:105CC0001200D9CFE6FFE1CFD9FFE65238D801095B +:105CD000DF6EC582C5B2FED79E96DF50C96E9EA606 +:105CE000FED7C5BCC5840401B06B9E96C5869EA632 +:105CF000FED70401B051B02BEA6AC00FE96E040E62 +:105D0000EA22C9CFEFFF400E0401B05D02E1C58A6F +:105D100001D0C59AC588C5B8FED7400E0401B05D54 +:105D2000E4E3C584C5B4FED70401B06B0401B12B14 +:105D3000000EB223E552E552E7CFD9FF1200D9CFCA +:105D4000E6FFE1CFD9FF020EE126DE52A00EDD6EA6 +:105D50003D5007E10401B251040B02E0010EDB8269 +:105D60000CD00401B251080B02E0010EDB820401E9 +:105D7000B251040B02E0010EDB86C580C5B0FED730 +:105D80009E96010EDB50C96EB1C43FF0B2C440F024 +:105D9000D89040323F32D89040323F323F50DF6E91 +:105DA0009EA6FED7C5BCC5849E96DF50C96EB1C401 +:105DB0003FF0B2C440F0060ED8903F364036E804BB +:105DC000FBE13F50DF6E9EA6FED7C5BCC5849E9604 +:105DD000DF50C96E9EA6FED7C5BCC584010EDB5040 +:105DE00000D03F6E020EE15C02E2E16AE552E16E34 +:105DF0003F50E552E7CFD9FF1200D9CFE6FFE1CF00 +:105E0000D9FF0401B051B02BEA6AC00FE96E040E4D +:105E1000EA22FE0EDBCFEFFF0401B0513F0801E2A2 +:105E200020DFE552E7CFD9FF12000401B0513F084F +:105E300003E247DF0401B06B0401B051B02BEA6A02 +:105E4000C00FE96E040EEA22EF5000D01200D9CF45 +:105E5000E6FFE1CFD9FF3E6AFE0EDBCFE6FF15D8A5 +:105E6000E55200090EE0FE0EDB50030FEA6A000F58 +:105E7000E96E020EEA22EF503D6E010E3E6ED8DE54 +:105E80008B80E552E7CFD9FF1200D9CFE6FFE1CFF3 +:105E9000D9FFFE0EDBCFF3FFDB2AF350EA6A000FD7 +:105EA000E96E020EEA22EF50500802E0000E20D008 +:105EB000FE0EDBCFF3FFDB2AF350EA6A000FE96E38 +:105EC000020EEA22EF504B0802E0000E11D0FE0E47 +:105ED000DBCFF3FFDB2AF350EA6A000FE96E020E14 +:105EE000EA22EF50320802E0000E02D0010E00D08C +:105EF000E552E7CFD9FF1200AD0EE66E7EDFE55228 +:105F00000401B0510008F8E33E6A8B901200D9CF2B +:105F1000E6FFE1CFD9FF020EE126DF6A010EDB6A60 +:105F2000DF50EA6A000FE96E020EEA22EF50840A9F +:105F300001E14ED1210A01E129D1270A01E126D14F +:105F4000010A01E123D1040A01E120D1070A01E19C +:105F50001DD1010A01E11AD1230A01E115D1010A7B +:105F600001E112D10D0A01E10FD1010A01E10CD1C9 +:105F7000080A01E1FDD00E0A01E1FAD0030A01E1AD +:105F8000F7D0010A01E1F4D0070A01E1F1D0290AB2 +:105F900001E1EED0030A01E1EBD02E0A01E1BCD011 +:105FA0000E0A01E18DD0020A54E0140A4FE0100AF3 +:105FB00020E0010A1EE0130A19E0030A0CE0070AB8 +:105FC00006E01B0A01E03CD1400EDF6E3AD1400EE4 +:105FD000DF6E92DF36D1020EDF26DF50EA6A000F55 +:105FE000E96E020EEA22EF28DF262BD1030EDF2610 +:105FF00028D1DF50DF2AEA6A000FE96E020EEA229A +:10600000EF50E66EFADEE552DF50DF2AEA6A000F53 +:10601000E96E020EEA22EF50E66EEFDEE552DF5047 +:10602000DF2AEA6A000FE96E020EEA22EF50E66EFE +:10603000E4DEE552DF50DF2AEA6A000FE96E020E65 +:10604000EA22EF50E66ED9DEE552FBD0050EDF26E0 +:10605000F8D0DF50DF2AEA6A000FE96E020EEA226A +:10606000EF50E66ECADEE552DF50DF2AEA6A000F23 +:10607000E96E020EEA22EF50E66EBFDEE552DF5017 +:10608000DF2AEA6A000FE96E020EEA22010EEFCF64 +:10609000DBFF010EDBCFE6FFB0DEE552DF50DF2A8B +:1060A000EA6A000FE96E020EEA22EF50E66EA5DE04 +:1060B000E552010EDB06010EDB500008EFE3C1D014 +:1060C000DF50DF2AEA6A000FE96E020EEA22EF5083 +:1060D000E66E93DEE552DF50DF2AEA6A000FE96ED2 +:1060E000020EEA22010EEFCFDBFF010EDBCFE6FF4F +:1060F00084DEE552DF50DF2AEA6A000FE96E020E05 +:10610000EA22EF50E66E79DEE552010EDB06010E63 +:10611000DB500008EFE395D0DF50DF2AEA6A000F7A +:10612000E96E020EEA22EF50E66E67DEE552DF50BE +:10613000DF2AEA6A000FE96E020EEA22010EEFCFB3 +:10614000DBFF010EDBCFE6FF58DEE552DF50DF2A32 +:10615000EA6A000FE96E020EEA22EF50E66E4DDEAB +:10616000E552010EDB06010EDB500008EFE369D0BB +:10617000DF50DF2AEA6A000FE96E020EEA22EF50D2 +:10618000E66E3BDEE5525DD0DF2A5BD0DF50DF2AD2 +:10619000EA6A000FE96E020EEA22EF50E66E2DDE8B +:1061A000E552DF50DF2AEA6A000FE96E020EEA22AA +:1061B000EF50E66E22DEE552DF50DF2AEA6A000F7A +:1061C000E96E020EEA22EF50E66E17DEE55239D094 +:1061D000DF50DF2AEA6A000FE96E020EEA22EF5072 +:1061E000E66E0BDEE552DF50DF2AEA6A000FE96E49 +:1061F000020EEA22EF50E66E00DEE552DF50DF2AA3 +:10620000EA6A000FE96E020EEA22EF50E66EF5DD53 +:10621000E552DF50DF2AEA6A000FE96E020EEA2239 +:10622000EF50E66EEADDE552DF50DF2AEA6A000F42 +:10623000E96E020EEA22EF50E66EDFDDE55201D094 +:10624000DF2A400EDF5C01E26BD6020EE15C02E267 +:10625000E16AE552E16EE552E7CFD9FF1200D9CFEE +:10626000E6FFE1CFD9FF020EE126E2DC0401400E99 +:10627000B06FDBDDDF6EDF50AB0A01E1D1D0070A82 +:1062800001E1CCD0060A01E1C9D0030A01E1C3D083 +:10629000010A01E1BDD00F0A01E1B7D0010A01E115 +:1062A0009CD0030A01E18AD0010A01E185D0050AE8 +:1062B0006BE0010A53E0FA0A50E0DC0A4CE0030A02 +:1062C00048E0010A36E0070A2BE0040A25E0050A47 +:1062D00021E0030A11E0010A01E0A5D0A6DDE76E86 +:1062E000010EE7CFDBFFA1DDE66E010EDBCFE6FF9F +:1062F00060D9E552E55299D098DDE76E010EE7CFFF +:10630000DBFF93DDE66E010EDBCFE6FFB0D9E55291 +:10631000E5528BD0366A376A88DD386E86DD85D0E7 +:10632000361C366E371C376E80DD361A7EDD371A26 +:106330007CD07BDD586E79DD596E77DD5A6E75DD68 +:106340005B6E81D8000904E1010E396EAD0EDF6E7F +:106350006CD003D96AD021D968D067D066DDE76EEA +:10636000010EE7CFDBFF010EDBCFE6FF5EDDE66E61 +:1063700001EC16F0E552E55258DDE66E26EC17F01A +:10638000E5520201FA6F51D050DD0001E06F4DDDA2 +:10639000E66E26EC17F0E552010F0001E16F020EE8 +:1063A0000001E15D0001E26F40DDE66E26EC17F0D2 +:1063B000E5520201FB6F39D0B6D937D036DDE76E32 +:1063C000010EE7CFDBFF31DDE66E010EDBCFE6FF2E +:1063D00088EC19F0E552E55228D027DDE76E010E72 +:1063E000E7CFDBFF010EDBCFE6FFEBEC35F0E5524C +:1063F000010EDBCFE6FF000EE66E020EE66E3CEC11 +:106400001DF0E552E552E55210D0BBEC17F00DD06F +:1064100008EC36F00AD0B3EC17F007D04ED805D010 +:10642000D9EC19F002D0AD0EDF6EAD0EDF5C01E0ED +:1064300020D7020EE15C02E2E16AE552E16EE5522C +:10644000E7CFD9FF1200B3EC17F0010EE66EE66A53 +:1064500088EC19F0E552E552010EE66E020EE66E8A +:1064600088EC19F0E552E552010EE66E010EE66E7B +:1064700088EC19F0E552E5520001EA51EA2BEA6A8C +:10648000600FE96E000EEA22EF5058160001EA5143 +:10649000EA2BEA6A600FE96E000EEA22EF50591605 +:1064A000B3EC17F05A50585C05E15B50595C02E1BF +:1064B000010E02D0000E00D01200D9CFE6FFE1CFCE +:1064C000D9FF040EE126360EDE6E000EDD6E020EE2 +:1064D000DB6A020EDBCF3FF00001EB513F5C000EA8 +:1064E000EC552FE20001EA51EA2BEA6A600FE96EEF +:1064F000000EEA22030EEFCFDBFF385013E0020E4E +:10650000DBA00ED038A003D0030EDB9E08D0030E14 +:10651000DB92DB94DB96DB98DB9ADB9CDB9E02D084 +:10652000030EDB90030EDB503F6E406ADECFE9FFC7 +:10653000DDCFEAFF3F50EE264050ED22020EDB2A6F +:10654000C8D7B3EC17F0040EE15C02E2E16AE55251 +:10655000E16EE552E7CFD9FF1200B3EC17F0010E60 +:10656000E66EE66A88EC19F0E552E552010EE66E39 +:106570000D0EE66E88EC19F0E552E552010EE66E5E +:10658000010EE66E88EC19F0E552E552600E00014E +:1065900061153A6EB3EC17F012003A500101011385 +:1065A000010EE66E0F0EE66E88EC19F0E552E5522C +:1065B0001200D9CFE6FFE1CFD9FFBBEC17F0B3EC67 +:1065C00017F00201E351E32BEA6A000FE96E010EB6 +:1065D000EA22FE0EDBCFEFFF0201E351E32BEA6A72 +:1065E000000FE96E010EEA22FD0EDBCFEFFF020184 +:1065F000E351E32BEA6A000FE96E010EEA22EF6A2B +:10660000030E0201E527000E0201E623010EE66EED +:10661000E66A88EC19F0E552E552010EE66E140EBA +:10662000E66E88EC19F0E552E552010EE66E010EB9 +:10663000E66E88EC19F0E552E5520001EA51EA2BCA +:10664000EA6A600FE96E000EEA22EF50346E000134 +:10665000EA51EA2BEA6A600FE96E000EEA22EF5077 +:10666000356EB3EC17F0E552E7CFD9FF1200D9CF62 +:10667000E6FFE1CFD9FFBBEC17F0B3EC17F0020156 +:10668000E351E32BEA6A000FE96E010EEA22FE0EE7 +:10669000DBCFEFFF0201E351E32BEA6A000FE96E63 +:1066A000010EEA22FD0EDBCFEFFF0201E351E32BE7 +:1066B000EA6A000FE96E010EEA22EF6A0201E35175 +:1066C000E32BEA6A000FE96E010EEA2234C0EFFF05 +:1066D0000201E351E32BEA6A000FE96E010EEA22A0 +:1066E00035C0EFFF050E0201E527000E0201E6238B +:1066F000010EE66EE66A88EC19F0E552E552010EED +:10670000E66E150EE66E88EC19F0E552E552010EC4 +:10671000E66E010EE66E88EC19F0E552E552E552A0 +:10672000E7CFD9FF1200D9CFE6FFE1CFD9FF0A0E9C +:10673000E12615EC2FF0E66ED950060FE96EDACFA0 +:10674000EAFFE552E750EE6EED6A15EC2FF0E66ECB +:10675000D950040FE96EDACFEAFFE552E750EE6E4A +:10676000ED6A040EDBCF28F0050EDBCF29F0080E12 +:1067700028C0DBFF090E29C0DBFF040EDBCF3FF092 +:10678000050EDBCF40F0403404E23F503D08000EE0 +:10679000405403E20001E88D14D2020EDB6A030EBE +:1067A000DB6ADE6ADD6ADECF3FF0DDCF40F0D890F5 +:1067B000405004E6200E3F5C000E405823E2DECF3E +:1067C000E9FFDDCFEAFF030EEA02F3CFEAFF030E93 +:1067D000E902F3CFE9FFF450EA26800EE926020E23 +:1067E000EA22EF503F6E406AD950020FE96EDACFCD +:1067F000EAFF3F50EE264050ED22DF2A010E01E372 +:10680000DB2AD1D7060EDBCFE9FF070EDBCFEAFF8D +:10681000030EEA02F3CFEAFF030EE902F3CFE9FF2A +:10682000F450EA26800EE926020EEA22EF503F6E6F +:10683000406AD950020FE96EDACFEAFF3F50EE5EB0 +:106840004050ED5A040EDBCF3FF0050EDBCF40F099 +:10685000020EDBCF41F0030EDBCF42F0000ED880FA +:106860004156030E425642504018E8AE02D0403422 +:1068700004D03F50415C4050425803E20001E88D93 +:10688000A0D1060EDBCF3FF0070EDBCF40F0403447 +:1068900004E23F501F08000E405403E20001E88D5F +:1068A00090D1060EDBCFE9FF070EDBCFEAFF030E28 +:1068B000EA02F3CFEAFF030EE902F3CFE9FFF45057 +:1068C000EA26800EE926020EEA22EF5001E106D107 +:1068D000060EDBCFE9FF070EDBCFEAFF030EEA026D +:1068E000F3CFEAFF030EE902F3CFE9FFF450EA2603 +:1068F000800EE926020EEA22EF503F6E406A000E3B +:10690000D8803F56030E40563F06000E405A040EF4 +:106910003FC0DBFF050E40C0DBFF060EDBCFE9FF0B +:10692000070EDBCFEAFF030EEA02F3CFEAFF030E06 +:10693000E902F3CFE9FFF450EA26800EE926020EC1 +:10694000EA22EE52EECFDEFFEDCFDDFFDECF3FF0ED +:10695000DDCF40F0040EDBCF41F0050EDBCF42F07F +:1069600040504218E8AE02D0423404D041503F5C5F +:106970004250405835E2060EDBCFE9FF070EDBCF71 +:10698000EAFF030EEA02F3CFEAFF030EE902F3CFB8 +:10699000E9FFF450EA26800EE926020EEA22EF50C3 +:1069A0000001406AF4253F6EF5514022DE503F243D +:1069B000E96EDD504020EA6EEF50E66EDE500001D9 +:1069C000F4250F01E96EDD500001F5210F01EA6E9B +:1069D000E552E750EF6EDF2A010E01E3DB2AB6D75E +:1069E000DE6ADD6ADECF3FF0DDCF40F0D890405068 +:1069F00004E6200E3F5C000E405870E2DECFE9FF57 +:106A0000DDCFEAFF030EEA02F3CFEAFF030EE9024D +:106A1000F3CFE9FFF450EA26800EE926020EEA22BF +:106A2000EECF3FF0EECF40F0EFCF41F0060EDBCFE0 +:106A3000E9FF070EDBCFEAFF030EEA02F3CFEAFF1E +:106A4000030EE902F3CFE9FFF450EA26800EE926AF +:106A5000020EEA22EE52EECF42F0EFCF43F00001F9 +:106A600043504118E8AE02D0413404D04050425C5B +:106A7000415043582EE2060EDBCFE9FF070EDBCF75 +:106A8000EAFF030EEA02F3CFEAFF030EE902F3CFB7 +:106A9000E9FFF450EA26800EE926020EEA22EF50C2 +:106AA0003F6E406ADECFE9FFDDCFEAFF030EEA0268 +:106AB000F3CFEAFF030EE902F3CFE9FFF450EA2631 +:106AC000800EE926020EEA22EE523F50EE5E405062 +:106AD000ED5ADF2A010E01E3DB2A84D7060EDBCF55 +:106AE000E9FF070EDBCFEAFF030EEA02F3CFEAFF6E +:106AF000030EE902F3CFE9FFF450EA26800EE926FF +:106B0000020EEA22080EDBCFEFFF060EDBCFE9FF15 +:106B1000070EDBCFEAFF030EEA02F3CFEAFF030E14 +:106B2000E902F3CFE9FFF450EA26800EE926020ECF +:106B3000EA22EE52020EDBCFEEFF030EDBCFEDFFBB +:106B4000DE6ADD6ADECF3FF0DDCF40F0060EDBCF40 +:106B5000E9FF070EDBCFEAFF030EEA02F3CFEAFFFD +:106B6000030EE902F3CFE9FFF450EA26800EE9268E +:106B7000020EEA22EF50000140AE02D0D89003D0BE +:106B80003F5C000E40581DE215EC2FF0E66E020E41 +:106B9000DB500001F42500013F6E030EDB500001C5 +:106BA000F5210001406EDE503F24E96EDD504020AB +:106BB000EA6EE552E750EF6EDF2A010E01E3DB2AB1 +:106BC000C1D70A0EE15C02E2E16AE552E16EE552EC +:106BD000E7CFD9FF1200D9CFE6FFE1CFD9FFE652C8 +:106BE000DF6AFE0EDB50DF5C0EE215EC2FF0E66E86 +:106BF000DF50EA6A000FE96E020EEA22E552E75022 +:106C0000EF6EDF2AEED7E552E552E7CFD9FF12004B +:106C1000D9CFE6FFE1CFD9FF040EE12615EC2FF026 +:106C2000E66ED950020FE96EDACFEAFFE552E7507F +:106C3000EE6EED6A020EDB500201E52500013F6EAB +:106C4000030EDB500201E6210001406E000ED880E9 +:106C50003F54010E405403E20001E88F36D0DE6A53 +:106C6000DD6ADECF3FF0DDCF40F0020EDBCF41F03A +:106C7000030EDBCF42F041503F5C4250405825E2CA +:106C800015EC2FF0E66E0201E351E32BEA6A000FE8 +:106C9000E96E010EEA22E552E750EF6E0201E35180 +:106CA0003F6E406AD890405004E6000E3F5C010EF3 +:106CB000405802E30201E36B0201E52B000EE623DC +:106CC000DF2A010E01E3DB2ACCD7040EE15C02E2ED +:106CD000E16AE552E16EE552E7CFD9FF1200D9CF64 +:106CE000E6FFE1CFD9FFE652DF6A81AA14D0FE0E9B +:106CF000DB50D880DF5408E3DF50DF2A010BE8B017 +:106D00008B80E8A08B9001D0DF6AF00EE66E58EC25 +:106D10003EF0E552EAD7E552E552E7CFD9FF12003F +:106D20006C500CE16896040100513C0BE842E842CB +:106D30000D0802E10ED801D04BD808D0040E6C5CCF +:106D400003E1689657D802D0000E02D0010E00D0A1 +:106D50001200D9CFE6FFE1CFD9FFE652040104AF1C +:106D600002D00401046B0201F96B0201F16B020114 +:106D7000F26B0201F76BF86BAEEC3BF0DF6ADF50B1 +:106D80003F6E406A010E3F5C000E40581BE202015C +:106D9000F25101E017D0F76ADF34FE0BF736F66EDA +:106DA000DE0EF6267A0EF7220900F5CF3FF0080036 +:106DB000F5CF40F004D040C0FAFF3F50F96EFBDF42 +:106DC000DF2ADDD705D9E552E552E7CFD9FF12001A +:106DD000020E0201F15D0CE1B9D8040100BD04D03E +:106DE0000401C80E006F03D00401880E006F01D0AB +:106DF0003ED91200040E0001ED5D0CE112C46EFFDD +:106E00006E50000804E20001050EED6F03D0000192 +:106E1000030EED6F0201F10514E115D8020E020117 +:106E2000F95D04E10401840E046F0AD0040104BD7D +:106E300004D00401C80E046F03D00401880E046F4F +:106E400001D015D91200D9CFE6FFE1CFD9FF020E4C +:106E5000E1260201080EF75D000EF85912E2F7C2B2 +:106E6000DEFFF8C2DDFF0201F95104E10201010E6B +:106E7000F96F06D00201F90503E10201020EF96F74 +:106E800003D0080EDE6EDD6A040104930401049150 +:106E9000010EDB5004010413DFCF05F4000EDB50BC +:106EA0000201F75F010EDB500201F85B0201180ED0 +:106EB000F56F040EF66F0001EEA320D0D9CFE9FFE5 +:106EC000DACFEAFFEE50ED1018E0F3C2F6FFF4C29D +:106ED000F7FF0800F550F5C2E9FFF6C2EAFFEF6ED2 +:106EE0000201F52B000EF6230201F32B000EF42312 +:106EF000DF06010E01E2DB06E1D71ED0D9CFE9FFA4 +:106F0000DACFEAFFEE50ED1017E0F3C2E9FFF4C26A +:106F1000EAFFEF50F5C2E9FFF6C2EAFFEF6E0201A9 +:106F2000F52B000EF6230201F32B000EF423DF06EF +:106F3000010E01E2DB06E2D7020EE15C02E2E16A49 +:106F4000E552E16EE552E7CFD9FF1200D9CFE6FF57 +:106F5000E1CFD9FF020EE126030E04010015E76E12 +:106F6000010EE7CFDBFF01C4DFFFDE500201F72790 +:106F7000DD500201F8230201180EF36F040EF46FC6 +:106F8000D9CFE9FFDACFEAFFEE50ED1017E0F3C2F8 +:106F9000E9FFF4C2EAFFEF50F5C2E9FFF6C2EAFFEB +:106FA000EF6E0201F52B000EF6230201F32B000E0B +:106FB000F423DF06010E01E2DB06E2D7020EE15CFC +:106FC00002E2E16AE552E16EE552E7CFD9FF120035 +:106FD0006D980201F2510FE10401080E016F0401E6 +:106FE000100E026F040E036F0401840E006F040183 +:106FF000840E046F3BD0040110AF25D00201F7517D +:107000000401165D0201F8510401175904E216C487 +:10701000F7F217C4F8F217DF0201010EF16F040155 +:10702000080E016F0401100E026F040E036F0401BD +:10703000800E006F0401180E066F040E076F040126 +:10704000C80E046F13D00201020EF16F0401056B2C +:107050000401C80E046F0401080E016F0401180E2C +:10706000026F040E036F0401C80E006F12000201CC +:10707000F16B0401080E016F0401100E026F040E83 +:10708000036F04018C0E006F0401046B12008986EB +:10709000899454B0898492940000899655A089946B +:1070A000898655B08984569E899689869284899668 +:1070B000898680B4568E899612005438556E56389B +:1070C000576E5AC05CF05BC05DF0FE0E5A6E040E47 +:1070D0005B6E06EE00F0EE6AEAA6FDD7120007EE40 +:1070E000FFF0BAD85CC05AF05DC05BF08038ED129A +:1070F0005D6EEA8200D000D000D00ED081AAA9D067 +:107100008038ED12EA825D6E551457181EE15C500E +:1071100058140EE1594EAAD08050EF6E5C6E541494 +:10712000561816E15D385814E9E1592EE9D7AAD06E +:1071300000008050EF6E5C6E5414561809E15D3803 +:107140005814DCE1592EDCD79DD081AA82D0E4D737 +:107150000000D4D707EEFFF07FD85CC05AF05DC0C6 +:107160005BF08038ED125D6EEA8200D000D000D076 +:107170000ED081AA6ED08038ED12EA825D6E551471 +:1071800057181EE15C5058140EE0594E6FD08050D5 +:10719000EF6E5C6E5414561816E15D385814E9E031 +:1071A000592EE9D76FD000008050EF6E5C6E5414FA +:1071B000561809E15D385814DCE0592EDCD762D04E +:1071C00081AA47D0E4D70000D4D707EEFFF044D817 +:1071D0005CC05AF05DC05BF07DD800008038ED12D5 +:1071E0005D6EEA8200D000D000D0000010D081AAED +:1071F00030D070D88038ED12EA825D6E5514571881 +:1072000023E15C5058145F1810E1594E2FD062D81A +:107210008050EF6E5C6E5414561819E15D385814A6 +:107220005F18E5E1592EE5D72DD0000053D88050E6 +:10723000EF6E5C6E541456180AE15D3858145F18EE +:10724000D6E1592ED6D71ED081AA03D0E0D700D0E0 +:10725000CED7400E556E12008050EF6E00D000D099 +:1072600000D000005E5227E035D825D08050EF6E68 +:10727000E9CF54F0EA508009556E00D05E521BE011 +:1072800029D819D08038ED12EA82E9CF54F0EACF3C +:1072900055F000D05E5202E01DD800D08050EF6E55 +:1072A00000005A2E15D05B4E1200000000005E5206 +:1072B00002E010D800D08038ED12EA825A2E09D0B0 +:1072C0005B4E1200000000005E52E8E003D8E6D7F3 +:1072D000EDD7F9D75E5000D000D00000E84E120084 +:1072E00000D00000F8D700EE00F00F0EEE6AEA6260 +:1072F000FDD71200040110511F0B010801E07DD0E1 +:107300000401145101E079D0060E0401115D2FE152 +:1073100004011351230A28E0010A13E0030A01E0E3 +:1073200024D00201020EF26F0001EF0505E1020117 +:10733000000EF36F7A0EF46F090E0201F76FF86B0F +:1073400014D00201020EF26F0001EF0505E1020107 +:10735000B70EF36F7A0EF46F0001EF0504E11D0E16 +:107360000201F76FF86B01D000D00001EE83040139 +:107370001051600BE842E842E842E842E842010866 +:1073800001E03BD0040111510B0A31E0080A21E071 +:10739000090A19E0080A09E00B0A05E0080A01E0F9 +:1073A0002CD02CD82AD02BD828D00201020EF26F74 +:1073B0000201F10EF36F000EF46F0001EE93020173 +:1073C000010EF76F1AD00201020EF26F13C4F1F032 +:1073D00014D00201020EF26F0201F20EF36F000EE2 +:1073E000F46F0001EE930201010EF76F06D0020167 +:1073F000020EF26F12C4F2F000D01200120012005E +:107400000001F36B1E0E716E0401400E096F040142 +:10741000200E0A6F040E0B6F0401880E086F040122 +:10742000600E0E6F040E0F6F0401400E0C6F120001 +:10743000D9CFE6FFE1CFD9FFE652FC0EDB50400882 +:1074400005E2400EF36EFC0EF3CFDBFFDF6AFC0EAD +:10745000DB50DF5C19E2DF50E76EFD0EDBCFE9FFAA +:10746000FE0EDBCFEAFFE750E926000EEA22EF50DE +:10747000E66EDF50EA6A600FE96E040EEA22E5521A +:10748000E750EF6EDF2AE3D7FC0EDBCF0DF4400EA2 +:1074900004010C1704010C7D880E04010C13E55245 +:1074A000E552E7CFD9FF1200D9CFE6FFE1CFD9FFF0 +:1074B0000001F36B040108BF39D0FC0EDBCF3FF0B5 +:1074C00004010951D8803F5403E2FC0E09C4DBFFDC +:1074D0000001F36BFC0EDB500001F35D1CE20001C8 +:1074E000F351EA6A200FE96E040EEA22EF50E66ECD +:1074F0000001F351E76EFD0EDBCFE9FFFE0EDBCF9F +:10750000EAFFE750E926000EEA22E552E750EF6E67 +:107510000001F32BDFD70401400E096F400E040178 +:1075200008170401087D880E040108130001F351B7 +:1075300000D0E552E7CFD9FF1200D8CFE4FFE0CF6B +:10754000E4FFE46EDACFE4FFE2CFDAFFE6520001B7 +:10755000E8A37CD0A150400B1DE0A050400B1AE0E6 +:10756000B4BE17D0A09CCD983550CF6E480E3424B1 +:10757000496E4A6A000E4A224A3404E24950FF0822 +:10758000000E4A5401E2CF2A480E3424CE6E9E905B +:107590009D80A19C9E50010B31E09D50010B2EE07F +:1075A0003550CF6E3450CE6E9E9036500AE1CD8865 +:1075B000B4AE04D09D90A19CA08C02D08B80362AC2 +:1075C0001DD03650080815E2B4AE0DD03DA003D052 +:1075D00037503B6E07D03DA203D037503C6E02D0EF +:1075E00037503A6E3D2A8B90366A9D90A19CA08CB4 +:1075F00005D037903742B4BE378E362AA150020BE1 +:1076000024E0A050020B21E03550B36E3450B26E2E +:10761000A192385004E18996382A8B8016D0090E41 +:10762000385C03E18986382A10D03850090804E212 +:10763000386AA0928B9009D0010E3914E8B089867F +:10764000E8A08996382A3990394262D09EA035D078 +:107650009E90FA0ECF6E380ECE6E8150100B10E158 +:107660000201FA51C45C0CE20C0E0201FC5D05E162 +:107670008A948A880001E78902D00201FC2B02D09B +:107680000201FC6B300E0001E71512E00201FEC2A0 +:1076900049F0FFC24AF0FE2B000EFF239B0ED8805C +:1076A0004954020E4A5404E28B700201FE6BFF6BD8 +:1076B0009E9C010EC26E9D8CC2829EAC29D09E9C67 +:1076C0000C0EBA5C21E10001E151D880C45401E202 +:1076D000BB6A0001E251C45C02E2E0C0BBFF815022 +:1076E000040B10E00201FB51C45C0CE20C0E020121 +:1076F000FD5D05E18A948A880001E78B02D00201D2 +:10770000FD2B02D00201FD6B050EC26E9D9CC28254 +:10771000A1B4FF00E552E5CFDAFFE550E5CFE0FF89 +:10772000E5CFD8FF10000201FC6B0201FD6B800E5B +:10773000CD6EFA0ECF6E380ECE6E9E909D80CD80AF +:107740009E9C9D9C260EC06E050EC26EC2821200CB +:107750009D90CD90C26A9E9C9D9C12000401105188 +:10776000600BE842E842E842E842E842000901E0F2 +:10777000A0D004011151080A01E18CD0010A01E1F5 +:1077800077D00F0A0AE0030A01E092D00201010E4D +:10779000F26F0001040EED6F8CD00201010EF26F4A +:1077A000040113050AE10201DC0EF36F790EF46F98 +:1077B000120E0201F76FF86B58D0020E0401135D30 +:1077C0001FE104011251F66EF76AD890F636F736CB +:1077D000D40EF6267A0EF7220900F5CFF3F20A004E +:1077E000F5CFF4F2020E0201F76AF325F66EF451BA +:1077F000F7220900F5CFF7F20A00F5CFF8F235D0FD +:10780000030E0401135D2FE1030E0401125D10E16C +:107810000201000EF36F000EF46FF3C2E9FFF4C231 +:10782000EAFFEF500201F76FF86B0001EE9341D0D1 +:1078300004011251F66EF76AD890F636F736D80E74 +:10784000F6267A0EF7220900F5CFF3F20A00F5CFFB +:10785000F4F2F3C2F6FFF4C2F7FF0800F55002019C +:10786000F76FF86B02D00201F26B0001EE8321D0BA +:107870000201010EF26F12C4EFF00401125104E193 +:107880000001050EED6F05D00001060EED6F00EC56 +:107890003AF00FD00201010EF26F0201EF0EF36F0A +:1078A000000EF46F0001EE930201010EF76F01D09C +:1078B00000D0120029C033F028C032F028502D0229 +:1078C000F4CF27F0F3CF26F029502E02F4CF29F081 +:1078D000F3CF28F02D02F3502726F4502822E86A2F +:1078E000292232502E02F3502726F4502822E86A2B +:1078F00029222EAE80EF3CF03250285E3350295AB8 +:1079000033AE000C2D50285E2E50295A000C28C092 +:1079100032F028502D02F4CF27F0F3CF26F0295073 +:107920002E02F4CF29F0F3CF28F02D02F3502726B2 +:10793000F4502822E86A292232502E02F3502726DA +:10794000F4502822E86A2922000C29C033F028C00C +:1079500032F027C031F027502C02F4CF25F0F3CFBE +:1079600024F028502D02F4CF27F0F3CF26F02C027C +:10797000F3502526F4502622E86A272231502D02A2 +:10798000F3502526F4502622E86A272229502C029B +:10799000F3502626F450272229502D02286AE86A3F +:1079A0002822F3502726F450282231502E02F3507B +:1079B0002626F4502722296AE86A282229223250F2 +:1079C0002E02F3502726F4502822E86A2922335049 +:1079D0002E02F3502826F4502922000C1201000236 +:1079E00000000008D804330002000102030209026B +:1079F0002900010102803209040000020300000096 +:107A0000092101000001221D00070581034000013A +:107A10000705010340000109022000010204803231 +:107A20000904000002FF0000000705810340000177 +:107A3000070501034000010403090434034D0069F4 +:107A400000630072006F006300680069007000202E +:107A50000054006500630068006E006F006C006FEA +:107A60000067007900200049006E0063002E004886 +:107A7000035000490043006B00690074002000328D +:107A80000020004D006900630072006F0063006F0A +:107A9000006E00740072006F006C006C0065007274 +:107AA000002000500072006F006700720061006DDE +:107AB000006D00650072000600FF0901A1011901B7 +:107AC0002940150026FF00750895408102190129FB +:107AD000409102C0EE79177A377A3B7A6F7AF47266 +:107AE000080E6D6E6DBAFED7686A110E696E0001E0 +:107AF000020EED6F12006D6A696A0001ED6B1200F3 +:107B00006850040B09E06950040B06E06D9269941B +:107B100068A402D06894FCD76850010B04E0695057 +:107B2000010B01E025D86850200B06E06950200BBE +:107B300003E070B07090689A030E0001ED5D01E201 +:107B400016D00001F66B040E0001F65D10E26850DD +:107B5000080B09E06950080B06E090EC36F00009CC +:107B600001E1689601D003D00001F62BECD712009A +:107B7000686A7B0E696E6E6A160E706E68A608D013 +:107B80006896000000000000000000000000F6D72A +:107B90006D9837EC38F00001EF6B0001030EED6FCC +:107BA0001200220EF66E5C0EF76E000EF86E0201E9 +:107BB0000900F550EC6F0900F550ED6F03E1EC673B +:107BC00001D03DD00900F550E76F0900F550E86F8E +:107BD0000900F550E96F09000900F550E96E090048 +:107BE000F550EA6E090009000900F550EA6F090036 +:107BF000F550EB6F09000900F6CFEEF2F7CFEFF288 +:107C0000F8CFF0F2E7C2F6FFE8C2F7FFE9C2F8FFEB +:107C10000201EA5302E1EB5307E00900F550EE6E72 +:107C2000EA07F8E2EB07F9D7EEC2F6FFEFC2F7FF7B +:107C3000F0C2F8FF0201EC07000EED5BBFD71200A7 +:107C400026502B02F3CF22F0F4CF23F02C02F35076 +:107C50002326000EF420246E26502D02F3502426F5 +:107C6000000EF420256E26502E02F35025262750B4 +:107C70002B02F3502326F4502422000E25222750F5 +:107C80002C02F3502426F450252227502D02F350C5 +:107C9000252628502B02F3502426F4502522285064 +:107CA0002C02F350252629502B02F35025261200D2 +:107CB000FF0EE3504C6EEF0E01D0F30EE76EE72E91 +:107CC0005FEF3EF00C0E4B6EE76AE72E65EF3EF07D +:107CD0004B2E64EF3EF04C2E5DEF3EF0120006D8C6 +:107CE00080EC3DF016EC11F0FBD71200140E6F6E15 +:107CF0000001ED6B0001EE6B0001EF6B15EC10F075 +:107D000070EC3DF0120013EE00F023EE00F0F86A84 +:107D1000219CD1EC3DF0AAEC3EF06FEC3EF0FBD79D +:107D20001200FF0EE3504C6E1B0E00D001D0200E4F +:107D3000E76EE72EFED74C2EFAD700D01200FF0ECA +:107D4000E350E84E1200000000D000D000D0E82E32 +:107D5000FAD7120012000005FFFFFFFFFFFFFFFF31 +:107D6000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF23 +:107D7000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF13 +:107D8000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF03 +:107D9000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3 +:107DA000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE3 +:107DB000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD3 +:107DC000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC3 +:107DD000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB3 +:107DE000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA3 +:107DF000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF93 +:107E0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF82 +:107E1000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF72 +:107E2000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF62 +:107E3000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF52 +:107E4000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF42 +:107E5000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF32 +:107E6000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF22 +:107E7000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF12 +:107E8000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF02 +:107E9000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2 +:107EA000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE2 +:107EB000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD2 +:107EC000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC2 +:107ED000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB2 +:107EE000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA2 +:107EF000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF92 +:107F0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF81 +:107F1000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF71 +:107F2000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF61 +:107F3000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF51 +:107F4000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF41 +:107F5000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF31 +:107F6000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF21 +:107F7000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF11 +:107F8000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF01 +:107F9000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1 +:107FA000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE1 +:107FB000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD1 +:107FC000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC1 +:107FD000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB1 +:107FE000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA1 +:107FF000FFFFFFFFFFFFFFFFFFFFFFFFFFFF5555E5 +:0200000400F00A +:100000000001FA83FFFFFF01FFFFFFFFFFFFFFFF7C +:10001000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0 +:10002000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE0 +:10003000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD0 +:10004000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC0 +:10005000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB0 +:10006000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA0 +:10007000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF90 +:10008000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80 +:10009000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF70 +:1000A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF60 +:1000B000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF50 +:1000C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF40 +:1000D000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF30 +:1000E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF20 +:1000F000234F6C486F737300000000000000000085 +:020000040030CA +:0E000000240E391E000181000FC00EA00F401B +:020000040020DA +:08000000FFFFFFFFFFFFFFFF00 +:00000001FF diff --git a/source/notes/pic-mcu/pickit2/pk2cmd-stuff/PK2V023200.hex.nrt b/source/notes/pic-mcu/pickit2/pk2cmd-stuff/PK2V023200.hex.nrt new file mode 160000 +Subproject 1511337ad63e4166069adccc25743533edb36bb diff --git a/source/notes/pic-mcu/pickit2/pk2cmd-stuff/hexdisasm.py b/source/notes/pic-mcu/pickit2/pk2cmd-stuff/hexdisasm.py new file mode 100644 index 0000000..0c86592 --- /dev/null +++ b/source/notes/pic-mcu/pickit2/pk2cmd-stuff/hexdisasm.py @@ -0,0 +1,71 @@ +import pic24 +import pic18 +import pic16 +import sys + +arch = "pic18" + +hexfile = '../pk2cmd/pk2cmd/PK2V023200.hex' + +if len(sys.argv) > 1: + hexfile = sys.argv[1] + + if len(sys.argv) > 2: + arch = sys.argv[2] + +if arch == "pic24": + arch = pic24 +elif arch == "pic18": + arch = pic18 +elif arch == "pic16": + arch = pic16 +else: + raise Exception("Invalid arch " + arch) + +lines = open(hexfile).readlines() + +def read_hex(lines): + regions = { 0: [0] * 0x10000 } + curr_region = regions[0] + + for line in lines: + if not line.startswith(':'): + continue +# raise Exception("invalid hex line, needs to start with a ':', but was: " + line) + bytecount = int(line[1:3], 16) + addr = int(line[3:7], 16) + rec_type = int(line[7:9], 16) + data_end = bytecount * 2 + 9 + data = line[9:data_end] + # ignoring checksum because lazy + + if rec_type == 4: + ext_linear_addr = int(data, 16) + if ext_linear_addr not in regions: + regions[ext_linear_addr] = [0] * 0x10000 + + curr_region = regions[ext_linear_addr] + elif rec_type == 0: + for i in range(bytecount): + curr_region[addr + i] = int(data[i*2:i*2 + 2], 16) + elif rec_type == 1: + print("Read HEX file") + return regions + else: + raise Exception("Unsupported record type: " + str(rec_type)) + + +memory_regions = read_hex(lines) + +i = 0 + +coderegion = memory_regions[0] + +while i < len(coderegion): + (i, instr) = arch.disassemble(coderegion, i) + if "Unknown instr" in instr: + print(instr) + elif 'op' not in instr: + print(instr['mnemonic']) + else: + print("{} {}".format(instr['mnemonic'], instr['op'])) diff --git a/source/notes/pic-mcu/pickit2/pk2cmd-stuff/pic16.py b/source/notes/pic-mcu/pickit2/pk2cmd-stuff/pic16.py new file mode 100644 index 0000000..e543cda --- /dev/null +++ b/source/notes/pic-mcu/pickit2/pk2cmd-stuff/pic16.py @@ -0,0 +1,154 @@ +def render(instr): + if 'op' in instr: + return "{} {}".format(instr['mnemonic'], instr['op']) + else: + return instr['mnemonic'] + +def disassemble(blob, offset): + instr = {} + instr['length'] = 1 + instrbytes = blob[offset:offset + 2] +# instrbytes.reverse() + print("Decoding {}{}...".format(hex(instrbytes[0])[2:], hex(instrbytes[1])[2:])) + + if instrbytes[0] == 0x00: + print(hex(instrbytes[1])) + # there's a few instructions here... + if instrbytes[1] == 0xff: + instr['mnemonic'] = 'reset' + else: + instr['mnemonic'] = [ + 'nop', + 'BAD', + 'BAD', + 'sleep', + 'clrwdt', + 'push', + 'pop', + 'daw', + 'tblrd*', + 'tblrd*+', + 'tblrd*-', + 'tblrd+*', + 'tblwr*', + 'tblwr*+', + 'tblwr*-', + 'tblwr+*', + 'retfie', + 'retfie fast', + 'return', + 'return fast', + 'callw*'][instrbytes[1]] + if instrbytes[0] == 0x01: + if instrbytes[1] > 0xf: + instr['mnemonic'] = 'BAD' + else: + instr['mnemonic'] = 'movlb' + instr['op'] = "#" + str(instrbytes[1]) + elif instrbytes[0] == 0x02 or instrbytes[0] == 0x03: + instr['mnemonic'] = 'mulwf' + instr['op'] = 'TODO' + elif instrbytes[0] == 0x04 or instrbytes[0] == 0x05 or instrbytes[0] == 0x06 or instrbytes[0] == 0x07: + instr['mnemonic'] = 'decf' + instr['op'] = 'TODO' + elif instrbytes[0] == 0x08: + instr['mnemonic'] = 'sublw' + instr['op'] = '#' + hex(instrbytes[1]) + elif instrbytes[0] == 0x09: + instr['mnemonic'] = 'iorlw' + instr['op'] = '#' + hex(instrbytes[1]) + elif instrbytes[0] == 0x0a: + instr['mnemonic'] = 'xorlw' + instr['op'] = '#' + hex(instrbytes[1]) + elif instrbytes[0] == 0x0b: + instr['mnemonic'] = 'andlw' + instr['op'] = '#' + hex(instrbytes[1]) + elif instrbytes[0] == 0x0c: + instr['mnemonic'] = 'retlw' + instr['op'] = '#' + hex(instrbytes[1]) + elif instrbytes[0] == 0x0d: + instr['mnemonic'] = 'mullw' + instr['op'] = '#' + hex(instrbytes[1]) + elif instrbytes[0] == 0x0e: + instr['mnemonic'] = 'movlw' + instr['op'] = '#' + hex(instrbytes[1]) + elif instrbytes[0] == 0x0f: + instr['mnemonic'] = 'addlw' + instr['op'] = '#' + hex(instrbytes[1]) + elif instrbytes[0] >= 0x20 and instrbytes[0] <= 0x5f: + mnemonicSel = instrbytes[0] >> 2 + instr['mnemonic'] = [ + 'iorwf', + 'andwf', + 'xorwf', + 'comf', + 'addwfc', + 'addwf', + 'incf', + 'decfsz', + 'rrcf', + 'rlcf', + 'swapf', + 'incfsz', + 'rrncf', + 'rlncf', + 'infsnz', + 'dcfsnz', + 'movf', + 'subwfb', + 'subwfb', + 'subwf' + ][mnemonicSel] + instr['op'] = 'TODO' + elif instrbytes[0] >= 0x60 and instrbytes[0] < 0x70: + mnemonicSel = instrbytes[0] >> 1 + instr['mnemonic'] = [ + 'cpfslt', + 'cpfseq', + 'cpfsgt', + 'tstfsz', + 'setf', + 'clrf', + 'negf', + 'movwf' + ][mnemonicSel] + instr['op'] = 'TODO' + elif instrbytes[0] >= 0x70 and instrbytes[0] < 0xc0: + mnemonicSel = instrbytes[0] >> 4 + instr['mnemonic'] = [ + 'BAD', 'BAD', 'BAD', 'BAD', 'BAD', 'BAD', 'BAD', + 'BTG', + 'BSF', + 'BCF', + 'BTFSS', + 'BTFSC' + ][mnemonicSel] + instr['op'] = 'TODO' + elif instrbytes[0] >= 0xc0 and instrbytes[0] < 0xd0: + instr['mnemonic'] = 'MOVFF' + instr['op'] = 'TODO' + elif instrbytes[0] >= 0xd0 and instrbytes[0] < 0xd8: + instr['mnemonic'] = 'BRA' + instr['op'] = 'TODO' + elif instrbytes[0] >= 0xd8 and instrbytes[0] < 0xe0: + instr['mnemonic'] = 'RCALL' + instr['op'] = 'TODO' + elif instrbytes[0] >= 0xf0 and instrbytes[0] <= 0xff: + instr['mnemonic'] = 'MOVFF' + instr['op'] = 'TODO' + elif instrbytes[0] == 0xec or instrbytes[0] == 0xed: + instr['mnemonic'] = 'CALL' + instr['op'] = 'TODO' + instr['length'] = 2 + elif instrbytes[0] == 0xee: + instr['mnemonic'] = 'LFSR' + instr['op'] = 'TODO' + instr['length'] = 2 + elif instrbytes[0] == 0xef: + instr['mnemonic'] = 'GOTO' + instr['op'] = 'TODO' + instr['length'] = 2 + else: + instr['mnemonic'] = 'TODO' + + return (offset + instr['length'] * 2, instr) diff --git a/source/notes/pic-mcu/pickit2/pk2cmd-stuff/pic16.pyc b/source/notes/pic-mcu/pickit2/pk2cmd-stuff/pic16.pyc Binary files differnew file mode 100644 index 0000000..285d3ba --- /dev/null +++ b/source/notes/pic-mcu/pickit2/pk2cmd-stuff/pic16.pyc diff --git a/source/notes/pic-mcu/pickit2/pk2cmd-stuff/pic18.py b/source/notes/pic-mcu/pickit2/pk2cmd-stuff/pic18.py new file mode 100644 index 0000000..15c2791 --- /dev/null +++ b/source/notes/pic-mcu/pickit2/pk2cmd-stuff/pic18.py @@ -0,0 +1,526 @@ +def render(instr): + if 'ops' in instr: + optexts = [] + for op in instr['ops']: + if isinstance(op, dict) and 'type' in op: + optext = op['text'] if 'text' in op else hex(op['value']) + optexts.append(optext) + else: + optexts.append(str(op)) + return "{} {}".format(instr['mnemonic'], ', '.join(optexts)) + else: + return instr['mnemonic'] + +def sext(number, bit): + mask = 1 << bit + if number & mask > 0: + return - ((~number & (mask - 1)) + 1) + else: + return number + +NAMES = { + 0xF60: '_ZERO_', + 0xF61: '_ZERO_', + 0xF62: 'SPPDATA', + 0xF63: 'SPPCFG', + 0xF64: 'SPPEPS', + 0xF65: 'SPPCON', + 0xF66: 'UFRML', + 0xF67: 'UFRMH', + 0xF68: 'UIR', + 0xF69: 'UIE', + 0xF6A: 'UEIR', + 0xF6B: 'UEIE', + 0xF6C: 'USTAT', + 0xF6D: 'UCON', + 0xF6E: 'UADDR', + 0xF6F: 'UCFG', + 0xF70: 'UEP0', + 0xF71: 'UEP1', + 0xF72: 'UEP2', + 0xF73: 'UEP3', + 0xF74: 'UEP4', + 0xF75: 'UEP5', + 0xF76: 'UEP6', + 0xF77: 'UEP7', + 0xF78: 'UEP8', + 0xF79: 'UEP9', + 0xF7A: 'UEP10', + 0xF7B: 'UEP11', + 0xF7C: 'UEP12', + 0xF7D: 'UEP13', + 0xF7E: 'UEP14', + 0xF7F: 'UEP15', + 0xF80: 'PORTA', + 0xF81: 'PORTB', + 0xF82: 'PORTC', + 0xF83: 'PORTD', + 0xF84: 'PORTE', + 0xF85: '_ZERO_', + 0xF86: '_ZERO_', + 0xF87: '_ZERO_', + 0xF88: '_ZERO_', + 0xF89: 'LATA', + 0xF8A: 'LATB', + 0xF8B: 'LATC', + 0xF8C: 'LATD', + 0xF8D: 'LATE', + 0xF8E: '_ZERO_', + 0xF8F: '_ZERO_', + 0xF90: '_ZERO_', + 0xF91: '_ZERO_', + 0xF92: 'TRISA', + 0xF93: 'TRISB', + 0xF94: 'TRISC', + 0xF95: 'TRISD', + 0xF96: 'TRISE', + 0xF97: '_ZERO_', + 0xF98: '_ZERO_', + 0xF99: '_ZERO_', + 0xF9A: '_ZERO_', + 0xF9B: 'OSCTUNE', + 0xF9C: '_ZERO_', + 0xF9D: 'PIE1', + 0xF9E: 'PIR1', + 0xF9F: 'IPR1', + 0xFA0: 'PIE2', + 0xFA1: 'PIR2', + 0xFA2: 'IPR2', + 0xFA3: '_ZERO_', + 0xFA4: '_ZERO_', + 0xFA5: '_ZERO_', + 0xFA6: 'EECON1', + 0xFA7: 'EECON2', + 0xFA8: 'EEDATA', + 0xFA9: 'EEADR', + 0xFAA: '_ZERO_', + 0xFAB: 'RCSTA', + 0xFAC: 'TXSTA', + 0xFAD: 'TXREG', + 0xFAE: 'RCREG', + 0xFAF: 'SPBRG', + 0xFB0: 'SPBRGH', + 0xFB1: 'T3CON', + 0xFB2: 'TMR3L', + 0xFB3: 'TMR3H', + 0xFB4: 'CMCON', + 0xFB5: 'CVRCON', + 0xFB6: 'ECCP1AS', + 0xFB7: 'ECCP1DEL', + 0xFB8: 'BAUDCON', + 0xFB9: '_ZERO_', + 0xFBA: 'CCP2CON', + 0xFBB: 'CCPR2L', + 0xFBC: 'CCPR2H', + 0xFBD: 'CCP1CON', + 0xFBE: 'CCPR1L', + 0xFBF: 'CCPR1H', + 0xFC0: 'ADCON2', + 0xFC1: 'ADCON1', + 0xFC2: 'ADCON0', + 0xFC3: 'ADRESL', + 0xFC4: 'ADRESH', + 0xFC5: 'SSPCON2', + 0xFC6: 'SSPCON1', + 0xFC7: 'SSPSTAT', + 0xFC8: 'SSPADD', + 0xFC9: 'SSPBUF', + 0xFCA: 'T2CON', + 0xFCB: 'PR2', + 0xFCC: 'TMR2', + 0xFCD: 'T1CON', + 0xFCE: 'TMR1L', + 0xFCF: 'TMR1H', + 0xFD0: 'RCON', + 0xFD1: 'WDTCON', + 0xFD2: 'HLVDCON', + 0xFD3: 'OSCCON', + 0xFD4: '_ZERO_', + 0xFD5: 'T0CON', + 0xFD6: 'TMR0L', + 0xFD7: 'TMR0H', + 0xFD8: 'STATUS', + 0xFD9: 'FSR2L', + 0xFDA: 'FSR2H', + 0xFDB: 'PLUSW2', + 0xFDC: 'PREINC2', + 0xFDD: 'POSTDEC2', + 0xFDE: 'POSTINC2', + 0xFDF: 'INDF2', + 0xFE0: 'BSR', + 0xFE1: 'FSR1L', + 0xFE2: 'FSR1H', + 0xFE3: 'PLUSW1', + 0xFE4: 'PREINC1', + 0xFE5: 'POSTDEC1', + 0xFE6: 'POSTINC1', + 0xFE7: 'INDF1', + 0xFE8: 'WREG', + 0xFE9: 'FSR0L', + 0xFEA: 'FSR0H', + 0xFEB: 'PLUSW0', + 0xFEC: 'PREINC0', + 0xFED: 'POSTDEC0', + 0xFEE: 'POSTINC0', + 0xFEF: 'INDF0', + 0xFF0: 'INTCON3', + 0xFF1: 'INTCON2', + 0xFF2: 'INTCON', + 0xFF3: 'PRODL', + 0xFF4: 'PRODH', + 0xFF5: 'TABLAT', + 0xFF6: 'TBLPTRL', + 0xFF7: 'TBLPTRH', + 0xFF8: 'TBLPTRU', + 0xFF9: 'PCL', + 0xFFA: 'PCLATH', + 0xFFB: 'PCLATU', + 0xFFC: 'STKPTR', + 0xFFD: 'TOSL', + 0xFFE: 'TOSH', + 0xFFF: 'TOSU' +} + +def reg_name(number): + if number in NAMES: + return NAMES[number] + else: + return None + +def disassemble(blob, offset): + instr = {} + instr['length'] = 1 + instrbytes = blob[offset:offset + 2] + instrbytes.reverse() +# instrbytes.reverse() +# print("Decoding {:02x}{:02x}...".format(instrbytes[0], instrbytes[1])) + + if instrbytes[0] == 0x00: + # there's a few instructions here... + if instrbytes[1] == 0xff: + instr['mnemonic'] = 'reset' + else: + mnemonicmap = [ + 'nop', + 'BAD', + 'BAD', + 'sleep', + 'clrwdt', + 'push', + 'pop', + 'daw', + 'tblrd*', + 'tblrd*+', + 'tblrd*-', + 'tblrd+*', + 'tblwr*', + 'tblwr*+', + 'tblwr*-', + 'tblwr+*', + 'retfie', + 'retfie fast', + 'return', + 'return fast', + 'callw*'] + + if instrbytes[1] > len(mnemonicmap): + instr['mnemonic'] = 'BAD' + else: + instr['mnemonic'] = mnemonicmap[instrbytes[1]] + elif instrbytes[0] == 0x01: + if instrbytes[1] > 0xf: + instr['mnemonic'] = 'BAD' + else: + instr['mnemonic'] = 'movlb' + instr['ops'] = ["#" + str(instrbytes[1])] + elif instrbytes[0] == 0x02 or instrbytes[0] == 0x03: + instr['mnemonic'] = 'mulwf' + instr['ops'] = ['TODO'] + elif instrbytes[0] >= 0x04 and instrbytes[0] < 0x08: + instr['mnemonic'] = 'decf' + d = (instrbytes[0] >> 1) & 1 + a = instrbytes[0] & 1 + f = instrbytes[1] + if a == 0: + # "Access Bank" + f_physical = f if f < 0x60 else 0xf00 + f + source = { + 'type': 'register', + 'value': f_physical + } + else: + source = { + 'type': 'banked-register', + 'value': f + } + + if d == 0: + dest = { 'type': 'register', + 'value': 'W' } + else: + dest = source + + if a == 0: + instr['ops'] = [ source, dest ] + else: + instr['ops'] = [ source, dest, 'banked' ] + + elif instrbytes[0] >= 0x08 and instrbytes[0] < 0x10: + code = instrbytes[0] & 0x7 + + instr['mnemonic'] = [ + 'sublw', + 'iorlw', + 'xorlw', + 'andlw', + 'retlw', + 'mullw', + 'movlw', + 'addlw' + ][code] + instr['ops'] = ['#' + hex(instrbytes[1])] + elif instrbytes[0] >= 0x10 and instrbytes[0] < 0x20: + code = (instrbytes[0] >> 2) & 0x3 + instr['mnemonic'] = [ + 'iorwf', + 'andwf', + 'xorwf', + 'comf' + ][code] + d = (instrbytes[0] >> 1) & 1 + a = instrbytes[0] & 1 + f = instrbytes[1] + + if a == 0: + # "Access Bank" + f_physical = f if f < 0x60 else 0xf00 + f + source = { + 'type': 'register', + 'value': f_physical + } + else: + source = { + 'type': 'banked-register', + 'value': f + } + + if d == 0: + dest = { 'type': 'register', + 'value': 'W' } + else: + dest = source + + if a == 0: + instr['ops'] = [ source, dest ] + else: + instr['ops'] = [ source, dest, 'banked' ] + + elif instrbytes[0] >= 0x20 and instrbytes[0] < 0x60: + mnemonicSel = instrbytes[0] >> 2 + instr['mnemonic'] = [ + 'mulwf (TODO)', #000000 + 'decf', #000001 + 'BAD', 'BAD', #00001X + 'iorwf', #000100 + 'andwf', #000101 + 'xorwf', #000110 + 'comf', #000111 + 'addwfc', #001000 + 'addwf', #001001 + 'incf', #001010 + 'decfsz', #001011 + 'rrcf', #001100 + 'rlcf', #001101 + 'swapf', #001110 + 'incfsz', #001111 + 'rrncf', #010000 + 'rlncf', #010001 + 'infsnz', #010010 + 'dcfsnz', #010011 + 'movf', #010100 + 'subwfb', #010101 + 'subwfb', #000000 + 'subwf' #000000 + ][mnemonicSel] + d = (instrbytes[0] >> 1) & 1 + a = instrbytes[0] & 1 + f = instrbytes[1] + + if a == 0: + # "Access Bank" + f_physical = f if f < 0x60 else 0xf00 + f + source = { + 'type': 'register', + 'value': f_physical + } + else: + source = { + 'type': 'banked-register', + 'value': f + } + + if d == 0: + dest = { 'type': 'register', + 'value': 'W' } + else: + dest = source + + if a == 0: + instr['ops'] = [ source, dest ] + else: + instr['ops'] = [ source, dest, 'banked' ] + + elif instrbytes[0] >= 0x60 and instrbytes[0] < 0x70: + mnemonicSel = (instrbytes[0] >> 1) & 0x7 + instr['mnemonic'] = [ + 'cpfslt', + 'cpfseq', + 'cpfsgt', + 'tstfsz', + 'setf', + 'clrf', + 'negf', + 'movwf' + ][mnemonicSel] + a = instrbytes[0] & 1 + f = instrbytes[1] + if a == 0: + # "Access Bank" + f_physical = f if f < 0x60 else 0xf00 + f + instr['ops'] = [ + { 'type': 'register', + 'value': f_physical } + ] + else: + instr['ops'] = [ + { 'type': 'banked-register', + 'value': f }, + "banked" + ] + elif instrbytes[0] >= 0x70 and instrbytes[0] < 0xc0: + mnemonicSel = instrbytes[0] >> 4 + instr['mnemonic'] = [ + 'BAD', 'BAD', 'BAD', 'BAD', 'BAD', 'BAD', 'BAD', + 'btg', + 'bsf', + 'bcf', + 'btfss', + 'btfsc' + ][mnemonicSel] + bit = (instrbytes[0] >> 1) & 0x7 + a = instrbytes[0] & 1 + f = instrbytes[1] + if a == 0: + # "Access Bank" + f_physical = f if f < 0x60 else 0xf00 + f + instr['ops'] = [ + { 'type': 'register', + 'value': f_physical }, + bit + ] + else: + instr['ops'] = [ + { 'type': 'banked-register', + 'value': f }, + bit, + "banked" + ] + elif instrbytes[0] >= 0xc0 and instrbytes[0] < 0xd0: + instr['mnemonic'] = 'movff' + instr['length'] = 2 + fs = ((instrbytes[0] & 0xf) << 8) | instrbytes[1] + followingbytes = blob[offset + 2:offset + 4] + followingbytes.reverse() + if followingbytes[0] < 0xf0: + instr['mnemonic'] = 'movff (BAD)' + else: + fd = ((followingbytes[0] & 0xf) << 8) | followingbytes[1] + instr['ops'] = [ + { 'type': 'register', + 'value': fs }, + { 'type': 'register', + 'value': fd } + ] + elif instrbytes[0] >= 0xd0 and instrbytes[0] < 0xd8: + instr['mnemonic'] = 'bra' + n = ((instrbytes[0] & 0x7) << 8) | instrbytes[1] + n = sext(n, 10) + instr['ops'] = [{ + 'type': 'relpostdest', + 'value': n << 1 + }] + elif instrbytes[0] >= 0xd8 and instrbytes[0] < 0xe0: + instr['mnemonic'] = 'rcall' + n = ((instrbytes[0] & 0x7) << 8) | instrbytes[1] + instr['ops'] = [{ + 'type': 'relpostdest', + 'value': n << 1 + }] + elif instrbytes[0] >= 0xe0 and instrbytes[0] <= 0xe8: + code = instrbytes[0] & 0x7 + instr['mnemonic'] = [ + 'bz', + 'bnz', + 'bc', + 'bnc', + 'bov', + 'bnov', + 'bn', + 'bnn' + ][code] + n = instrbytes[1] + n = sext(n, 7) + instr['ops'] = [{ + 'type': 'relpostdest', + 'value': n << 1 + }] + elif instrbytes[0] >= 0xf0 and instrbytes[0] <= 0xff: + instr['mnemonic'] = 'BAD (misdecode)' + elif instrbytes[0] == 0xea: + instr['mnemonic'] = 'push' + instr['ops'] = [instrbytes[1]] + elif instrbytes[0] == 0xec or instrbytes[0] == 0xed: + instr['mnemonic'] = 'call' + s = instrbytes[0] & 1 + instr['length'] = 2 + lowbits = instrbytes[1] + followingbytes = blob[offset + 2:offset + 4] + followingbytes.reverse() + if followingbytes[0] < 0xf0: + instr['mnemonic'] = 'CALL (BAD)' + else: + k = (((followingbytes[0] & 0x0f) << 16) | (followingbytes[1] << 8) | lowbits) + instr['ops'] = [{ + 'type': 'absolutedest', + 'value': k << 1 + }, str(s)] + elif instrbytes[0] == 0xee: + instr['mnemonic'] = 'lfsr' + instr['length'] = 2 + f = (instrbytes[1] >> 4) & 3 + followingbytes = blob[offset + 2:offset + 4] + followingbytes.reverse() + if followingbytes[0] < 0xf0: + instr['mnemonic'] = 'lsfr (BAD)' + else: + k = ((instrbytes[1] & 0xf) << 8) | followingbytes[1] + instr['ops'] = [str(f), hex(k)] + elif instrbytes[0] == 0xef: + instr['mnemonic'] = 'goto' + instr['length'] = 2 + lowbits = instrbytes[1] + followingbytes = blob[offset + 2:offset + 4] + followingbytes.reverse() + if followingbytes[0] < 0xf0: + instr['mnemonic'] = 'GOTO (BAD)' + else: + k = ((followingbytes[0] & 0x0f) << 16) | (followingbytes[1] << 8) | lowbits + instr['ops'] = [{ + 'type': 'absolutedest', + 'value': k << 1 + }] + + else: + instr['mnemonic'] = 'TODO' + + return (offset + instr['length'] * 2, instr) diff --git a/source/notes/pic-mcu/pickit2/pk2cmd-stuff/pic18.pyc b/source/notes/pic-mcu/pickit2/pk2cmd-stuff/pic18.pyc Binary files differnew file mode 100644 index 0000000..0a12e73 --- /dev/null +++ b/source/notes/pic-mcu/pickit2/pk2cmd-stuff/pic18.pyc diff --git a/source/notes/pic-mcu/pickit2/pk2cmd-stuff/pic24.py b/source/notes/pic-mcu/pickit2/pk2cmd-stuff/pic24.py new file mode 100644 index 0000000..e0adef0 --- /dev/null +++ b/source/notes/pic-mcu/pickit2/pk2cmd-stuff/pic24.py @@ -0,0 +1,216 @@ +def render(instruction): + return "{} {}".format(instruction['mnemonic'], instruction['op']) + + +def Table_5_12(nibble): + return "Table 5.12 TODO" + +def Table_5_11(nibble): + return "Table 5.11 TODO" + +def Table_5_10(nibble): + return "Table 5.10 TODO" + +def YDataPrefetchDest_5_9(nibble): + return "Table 5.9 TODO" + +def YDataPrefetchOperation_5_8(nibble): + return "Table 5.8 TODO" + +def XDataPrefetchDest_5_7(nibble): + return "Table 5.7 TODO" + +def XDataPrefetchOperation_5_6(nibble): + return "Table 5.6 TODO" + +def readWd_5_5(octet): + return [ + "Wd", + "[Wd]", + "[Wd--]", + "[Wd++]", + "[--Wd]", + "[++Wd]", + "[Wd + Wb]", + "[Wd + Wb]" + ][octet] + +def readWs_5_4(octet): + return [ + "Ws", + "[Ws]", + "[Ws--]", + "[Ws++]", + "[--Ws]", + "[++Ws]", + "[Ws + Wb]", + "[Ws + Wb]" + ][octet] + +def readWd_5_3(octet): + return [ + "Wd", + "[Wd]", + "[Wd--]", + "[Wd++]", + "[--Wd]", + "[++Wd]", + "ERR", + "ERR" + ][octet] + +def readWs_5_2(octet): + return [ + "Ws", + "[Ws]", + "[Ws--]", + "[Ws++]", + "[--Ws]", + "[++Ws]", + "ERR", + "ERR" + ][octet] + +def disassemble(blob, offset): +# print ("Disassembling " + str(blob)) + instrbytes = blob[offset:offset + 3] +# instrbytes.reverse() + print("Disassembling {} {} {}".format(hex(instrbytes[0]), hex(instrbytes[1]), hex(instrbytes[2]))) + instr = {} + instr['op'] = '' + size = 1 + + if instrbytes[2] == 0x0: + instr['mnemonic'] = 'nop' + if instrbytes[2] == 0x1: + instr['mnemonic'] = 'br*' + if instrbytes[2] == 0x2: + instr['mnemonic'] = 'call' + if instrbytes[2] == 0x3: + instr['mnemonic'] = '-' + if instrbytes[2] == 0x4: + instr['mnemonic'] = 'goto' + size = 2 + w2 = blob[offset + 3:offset + 6] +# w2.reverse() + n_hi = ((instrbytes[1] << 8) + instrbytes[0]) + if w2[0] != 0 or w2[1] != 0: + instr['mnemonic'] = 'goto [BAD]' + n_lo = w2[0] + n = n_hi + (n_lo << 16) + instr["op"] = hex(n) + if instrbytes[2] == 0x5: + instr['mnemonic'] = 'retlw' + if instrbytes[2] == 0x6: + instr['mnemonic'] = 'retfie' + if instrbytes[2] == 0x7: + instr['mnemonic'] = 'rcall' + if instrbytes[2] == 0x8: + instr['mnemonic'] = 'do' + if instrbytes[2] == 0x9: + instr['mnemonic'] = 'repeat' + if instrbytes[2] == 0xa: + instr['mnemonic'] = '-' + if instrbytes[2] == 0xb: + instr['mnemonic'] = '-' + if instrbytes[2] == 0xc: + instr['mnemonic'] = 'bra(oa)' + instr['mnemonic'] += " (dsPIC3XF only)" + if instrbytes[2] == 0xd: + instr['mnemonic'] = 'bra(ob)' + instr['mnemonic'] += " (dsPIC3XF only)" + if instrbytes[2] == 0xe: + instr['mnemonic'] = 'bra(sa)' + instr['mnemonic'] += " (dsPIC3XF only)" + if instrbytes[2] == 0xf: + instr['mnemonic'] = 'bra(sb)' + instr['mnemonic'] += " (dsPIC3XF only)" + if instrbytes[2] >= 0x10 and instrbytes[2] < 0x18: + instr['mnemonic'] = 'subr' + if instrbytes[2] >= 0x18 and instrbytes[2] < 0x20: + instr['mnemonic'] = 'subbr' + if instrbytes[2] >= 0x20 and instrbytes[2] < 0x30: + instr['mnemonic'] = 'mov' + word = instrbytes[0] | (instrbytes[1] << 8) | (instrbytes[2] << 16) + imm = (word & 0x0ffff0) >> 4 + reg = word & 0xf + instr['op'] = "#" + hex(imm) + ", W" + str(reg) + + if instrbytes[2] >= 0x80 and instrbytes[2] < 0x90: + instr['mnemonic'] = 'mov' + word = instrbytes[0] | (instrbytes[1] << 8) | (instrbytes[2] << 16) + f = (word & 0x07fff0) >> 4 + reg = word & 0xf + + if instrbytes[2] < 0x88: + instr['op'] = "[" + hex(f) + "], W" + str(reg) + else: + instr['op'] = "W" + str(reg) + ", [" + hex(f) + "]" + + if instrbytes[2] >= 0xc0 and instrbytes[2] < 0xd0: + instr['mnemonic'] = "(dsPIC3XF only)" + + if instrbytes[2] == 0xB4 and (instrbytes[1] & 0x80) == 0x00: + instr['mnemonic'] = "ADD" + B = instrbytes[1] & 0x40 + D = instrbytes[1] & 0x20 + f = ((instrbytes[1] & 0x1f) << 8) + instrbytes[0] + + if B: + instr['mnemonic'] += '.B' + + instr['op'] = "RAM:" + hex(f) + + if D: + instr['op'] += ', W0' + if instrbytes[2] == 0xaa: + instr['mnemonic'] = "BTG" + # TODO: not clear what is .B mode + bit4 = ((instrbytes[1] >> 4) & 0x0e) + (instrbytes[0] & 0x01) + f = ((instrbytes[1] & 0x1f) << 7) + (instrbytes[0] >> 1) + instr['op'] = "{}, #{}".format(hex(f), hex(bit4)) + if instrbytes[2] == 0xba: + instr['mnemonic'] = "TBLRD" + if (instrbytes[1] & 0x80) != 0: + instr['mnemonic'] += 'H' + else: + instr['mnemonic'] += 'L' + + if (instrbytes[1] & 0x40) != 0: + instr['mnemonic'] += '.B' + + s = (instrbytes[0] & 0x0f) + p = (instrbytes[0] >> 4) & 0x07 + d = ((instrbytes[0] >> 7) & 0x01) + ((instrbytes[1] << 1) & 0xf) + q = (instrbytes[1] & 0x38) >> 3 + + srcOp = readWs_5_2(p).replace("Ws", "W" + str(s)) + dstOp = readWd_5_3(q).replace("Wd", "W" + str(d)) + + instr['op'] = "{}, {}".format(srcOp, dstOp) + if instrbytes[2] == 0xbb: + instr['mnemonic'] = "TBLWT" + if (instrbytes[1] & 0x80) != 0: + instr['mnemonic'] += 'H' + else: + instr['mnemonic'] += 'L' + + if (instrbytes[1] & 0x40) != 0: + instr['mnemonic'] += '.B' + + s = (instrbytes[0] & 0x0f) + p = (instrbytes[0] >> 4) & 0x07 + d = ((instrbytes[0] >> 7) & 0x01) + ((instrbytes[1] << 1) & 0xf) + q = (instrbytes[1] & 0x38) >> 3 + + srcOp = readWs_5_2(p).replace("Ws", "W" + str(s)) + dstOp = readWd_5_3(q).replace("Wd", "W" + str(d)) + + instr['op'] = "{}, {}".format(srcOp, dstOp) + + if 'mnemonic' not in instr: + instr = instrbytes[0] | (instrbytes[1] << 8) | (instrbytes[2] << 16) + return (offset + 3, "Unknown instruction: " + hex(instr)) + + return (offset + 3 * size, instr) + diff --git a/source/notes/pic-mcu/pickit2/pk2cmd-stuff/pic24.pyc b/source/notes/pic-mcu/pickit2/pk2cmd-stuff/pic24.pyc Binary files differnew file mode 100644 index 0000000..c9a39af --- /dev/null +++ b/source/notes/pic-mcu/pickit2/pk2cmd-stuff/pic24.pyc diff --git a/source/notes/pic-mcu/pickit2/pk2cmd-stuff/pk2_firmware_notes.md b/source/notes/pic-mcu/pickit2/pk2cmd-stuff/pk2_firmware_notes.md new file mode 100644 index 0000000..0d3535b --- /dev/null +++ b/source/notes/pic-mcu/pickit2/pk2cmd-stuff/pk2_firmware_notes.md @@ -0,0 +1,222 @@ +usb handler? + +walking through from the entry point for the script interpreter proves to be difficult. can't even find usb handler. alternative idea: look for instructions and registers that would be used by the usb handler, try to follow from there to the command handler, and from there maybe get to the script interpreter + +found a function that appears to handle usb status bits but no clear indication of reading packets.. next thought is to disassemble all of the firmware and look for what might be a dispatch table for script commands + +three jump tables found: +0x2334? +0x3b0a? +0x429e? + +there also seems to be some bit bang style logic around 0x525c, through lata 3 and somethig to do with trisa 4 + +the last two jump tables seem related, not sure how exactly. + +alternate approach again, maybe it's easier to find the implementation of some script commands? + +decent targets: SCMD_BUSY_LED_OFF, SCMD_BUSY_LED_ON aka 0xF4, 0xF5 +busy LED is pin 4 in portb, searching PORTB yields a lot of btfss and btfsc, but searching LATB is entirely bsf and bcf. further refining to `latb, 4` yields 12 possibly interesting instructions +because these would be the result of command dispatch, and are adjacent, they are probably close together + +0x26d0 (set) +0x26d4 (clear) + +0x3b60 (clear) +0x3b64 (set) + +further reading, noticed some interesting constants before the first jump table: +000022ae: xorlw #0x42 +000022b0: bz 0x2300 (ip+2+0x4e) +000022b2: xorlw #0x34 +000022b4: bz 0x22c0 (ip+2+0xa) +000022b6: xorlw #0x2c +000022b8: bz 0x22bc (ip+2+0x2) +000022ba: bra 0x2306 (ip+2+0x4a) + +immediately eyecatching on account of 0x42 being FWCMD_ENTER_BOOTLOADER +the following xorlw #0x34 functionally results in W == W_original ^ 0x42 ^ 0x34. because xor is associative that can be read as W == W_original ^ (0x42 ^ 0x34), or W == W_original ^ (0x76). 0x76 is, itself, also interesting, as that's the opcode for FWCMD_FIRMWARE_VERSION. +the third xor at 0x22b6 is equivalent to W == W_original ^ (0x42 ^ 0x34 ^ 0x2c) aka W == W_original ^ (0x5a). 0x53 maps to FWCMD_NO_OPERATION, so at this point this is definitely the start of the command interpreter dispatch table. + +added some labels on those branches so we don't forget. + +at this point there's something to closely inspect, so it's worth investigating a structure i've seen many times: +``` +; a call target +0x222c: movff FSR2L, POSTINC1 +0x2230: movff FSR1L, FSR2L +; ^ what's up with this and why? +; and at the return... (different function) +0x7532: movf POSTDEC1, POSTDEC1 +0x7534: movff INDF1, FSR2L +0x7536: return + +POSTDEC1 and INDF1 are ~special~ ~magic~ registers. they, along with PREDEC1, PREINC1, POSTINC1, and PLUSW1 are indirect registers that actually write to memory pointed at by the pair FSR1H:FSR1L. +* `INDF1` is an access to memory at `FSR1H:FSR1L`. +* `PLUSW1` is an access to memory at `FSR1H:FSR1L + W`. +* `POSTDEC`, `POSTINC`, and `PREINC` refer to additional functionality: before (or after) writing, the pair of FSR1 registers are incremented (or decremented) as described by the register name. + +pic18 2550 has three sets of FSR registers: 0, 1, and 2. each of these are distinct but have corresponding `PREDEC`, `POSTINC`, `INDF`, etc. + +so at function entry the code stores the previous FSR2L to `[FSR1++]`, then `FSR1 => FSR2`. because the pic18 2550 doesn't have a stack, this seems like a decent approximation of the same context-saving behavior. and of course, at return, context is restored appropriately. + +this provides some illumination on another interesting idiom: +``` +0x22d2: setf POSTINC1 +0x22d4: movlw #0x4 +0x22d6: movwf POSTINC1 +0x22d8: call 0x5466, 0 +0x22dc: movf POSTDEC1, POSTDEC1 +0x22de: movf POSTDEC1, POSTDEC1 +``` + +again, FSR1 is being used akin to a stack to pass parameters + +`setf POSTINC1` stores `0xFF` through `FSR1` and increments, the subsequent `movlw #0x4; movwf POSTINC1` provides a second argument, which aligns with the two `movf POSTDEC` after the call (undoing the increments to provide parameters) + +returning to this jump table stuff, register 0x54 is compared with 0xb9 (in the range of opcodes, though well into `SCMD_` space), and if the opcode is less than 0xb9, a branch is taken to `0x2306`: +``` +code from 0x2306 +``` + +at `0x2306` the opcode is turned into an offset into the subsequent jump table and added to PC, doing the switch by opcode. at this point it's reasonable to add labels for the cases to indicate what command they correspond to. + +confirmation: `FWCMD_RESET` matches up with the easily verifiably logic of the `reset` instruction. + +of note for later are: +* `FWCMD_EXECUTE_SCRIPT`: this is relevant for programmer operation. all operations seem to be scripts. +* `FWCMD_RUN_SCRIPT`: how is this different from "execute"? +* `FWCMD_DOWNLOAD_SCRIPT`: this is the command to download a script to the programmer. can we read script memory? how many scripts can there be? what's their size? +* `FWCMD_DOWNLOAD_DATA`: seems interesting. download to programmer or to target? +* `FWCMD_UPLOAD_DATA`: same as above +* `FWCMD_END_OF_BUFFER`: might be interesting to know later + +... it's not clear how SCMD commands are dispatched, which is probably a different table. time to keep looking. + +onward to `0x3b0a`... + +at `0x3aec` the opcode (again in register `0x54`) is compared against `0xd5`. if the opcode is that or above, `0x3af0` branches to a similar switch based on the value. + +since the entries are in order from `0xd5` up, script command names apply cleanly to each branch: +``` +TODO: before/after with script command names +``` + +and if the opcode was below `0xd5`, the branch at `0x3af2` kicks in and takes us to... + +``` +TODO: CODE AT prelude_to_jump_tbl_3 +``` + +very similar structure to other tables, but starts with `0xb3`. `0xb3` is not in the header file and is unknown, but the rest can be filled in. + +``` +TODO: CODE AT prelude_to_jump_tbl_3 with labels +``` + +(note: at this point as i was keymashing i accidentally hit ctrl+c, which my script doesn't handle, and lost three hours of notes give or take. largely looking through the interpreter cases, and easy enough to rebuild, but beware sigint) + +so to return to original questions: +* what script opcodes take how many parameters? +* how does programming actually take place? + +## Script Opcodes +easiest to start with obvious opcodes where i can assume that i know the intended functionality, but not the implementation. SCMD_NOP24 is an obvious candidate. functionally it *probably* does nothing, but does likely increment some pointers on the programmer side (current script opcode pointer, if such a thing exists), and possibly on the device side (to cause the target device to execute a no-op). + +``` +TODO: SCMD_NOP24 implementation +``` + +SCMD_NOP24 makes four calls to the same function, with parameters that vary: +* 0x5066(4, 0) +* 0x5066(8, 0) +* 0x5066(8, 0) +* 0x5066(8, 0) + +the sequence of three calls with (8, 0) probably correspond to the bytes 0x00, 0x00, 0x00, which decode under PIC24 to a NOP. so this seems sane! the remaining question if this is true, is why is there a call with arguments (4, 0)? + +to answer that, we have to look at 0x5066: +``` +TODO: fn at 0x5066 +``` + +so this function reads two parameters, stores the later parameter to 0x54, and the first to 0x55. as the first parameter for these calls is either 8 or 4, and the latter parameter is all 0's, this continues to make sense. + +the function then tests if 0x2e1 > 0x2 and branches below if so. + +``` +bitbang loop +``` + +this sequence of four instructions is responsible for putting pin 2 of latch A into a high or low state. bit 0 in 0x54 can only be 1 or 0, so exactly one of `btfss` or `btfcs` will result in a fallthrough. as a result, only one of `bcf LATA, 2; bsf LATA, 2` will be executed. afterward, the `nop; bsf LATA, 3; nop; bcf LATA, 3. This makes sense given that the programmer is responsible for directly driving clock signals on the remote chip in programming modes. + +??? ... programmer dialog, scmd, loop, arguments, ... ??? + +there is another region of ths function that's similar but just a little different, predicated on the value in 0x2e1. if that value is above 2, a different bit banging loop is reached, down at 0x509c: + +``` +loop 2 +``` + +this loop is the same as before as far as setting the data pin (LATA bit 2). the difference is that before alternating the clock three nops are used (rather than the earlier one nop), and those nops now have a loop around them. the timing loop counts down [0x2e1] times through W and advances when 0, and overall looks to be a bitbanging loop with longer timings between clock cycles. this may be relevant for other target devices, and a single "send this data" abstraction makes sense. + +back to the question of the two arguments, while one is sent one bit at a time, the other seems to count the number of bits to send: + +``` +TODO: 0x50c8 +``` + +so (4, 0) sends the bits `0000`, while (8, 0) sends `00000000`. + +moving on to SCMD_COREINST24, which functionally should send three user-specified bytes to the target... + +``` +TODO: SCMD_COREINST24 +``` + +as expected, this calls the same transmit function, and passes 4 and 8 in the same places. the major difference is how the second parameter is provided, where this version involves a bit of an incantation: + +``` +TODO: SCMD_COREINST24 0x41c6 to 0x41e2 +``` + +since the three bytes for a pic24 instruction are part of the script (in fact, the three bytes after the `SCMD_COREINST24`), it stands to reason that the value passed is read out of the script buffer. interestingly, the logic appears to be: +* read the current script buffer offset (through `INDF2` at `0x41c6`) +* increment the offset (`0x41c8`) +* load the pointer to the script array (`0x41cc`-`0x41d4`) into `FRS0` - this comes from an argument! +* add the offset into the pointer (`0x41d8`) +* read that address (`0x41e0`) +* "push" the parameter (`0x41e2`) + +this confirms that for the various commands we can count `INDF2` modification to determine the number of parameters for the various commands! + +first ones of interest: `SCMD_WRITE_BUFBYTE_W` and `SCMD_WRITE_BUFWORD_W` + +## `SCMD_WRITE_BUFWORD_W` + +``` +TODO: SCMD_WRITE_BUFWORD_W +``` + +this handler involves the same transmit function from earlier and also another function, `0x5006`. + +guessing from context it appears to read from a global address and return the byte in W. `SCMD_WRITE_BUFWORD_W` then uses that as bits to send down the wire. + +`SCMD_WRITE_BUFBYTE_W` does the same, but only reads one byte, the second value transmitted is a 0. + +`SCMD_WRITE_BITS_LITERAL` takes two parameters, the number of bits and the pattern to send. +`SCMD_WRITE_BYTE_LITERAL` takes one parameter, the pattern, and assumes the number of bits to send is 8. +TODO: `SCMD_RD2_BYTE_BUFFER` is an unknown. +TODO: `SCMD_READ_BYTE`. +TODO: `SCMD_VISI24`. (transmits (4, 1), (8, 0), then some unknown calls.) + +## `SCMD_DELAY_LONG` + +passes the single byte parameter along to the function at `0x4966`, which... +``` +TODO: 11 instructions at 0x4966 +``` + +at `0x496e` the flag indicating `timer0` has fired is cleared, followed by multiplying the argument by 0xff and loading the result into `tmr0h`? this really has no result other than to negate it before setting the timer. from there, the timer is enabled and the controller spins until the timer fires (`0x497e`). + +## `SCMD_LOOP` diff --git a/source/notes/pic-mcu/pickit2/pk2cmd-stuff/pk2cmd_firmware b/source/notes/pic-mcu/pickit2/pk2cmd-stuff/pk2cmd_firmware new file mode 160000 +Subproject 4e76e524ce8613f971b4167a9e2db1458e21e69 diff --git a/source/notes/pic-mcu/pickit2/pk2cmd-stuff/pk2cmd_script.py b/source/notes/pic-mcu/pickit2/pk2cmd-stuff/pk2cmd_script.py new file mode 100644 index 0000000..f1de6ce --- /dev/null +++ b/source/notes/pic-mcu/pickit2/pk2cmd-stuff/pk2cmd_script.py @@ -0,0 +1,146 @@ +import pic24 + +NoOperands = [ + 0xD5, 0xD6, 0xD7, 0xD8, + 0xEF, # comment on this one: Read & toss 2 response words + 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB +] + +ScriptCommandTable = { + 0xB4: 'SCMD_JT2_WAIT_PE_RESP', + 0xB5: 'SCMD_JT2_GET_PE_RESP', + 0xB6: 'SCMD_JT2_XFERINST_BUF', + 0xB7: 'SCMD_JT2_XFRFASTDAT_BUF', + 0xB8: 'SCMD_JT2_XFRFASTDAT_LIT', + 0xB9: 'SCMD_JT2_XFERDATA32_LIT', + 0xBA: 'SCMD_JT2_XFERDATA8_LIT', + 0xBB: 'SCMD_JT2_SENDCMD', + 0xBC: 'SCMD_JT2_SETMODE', + 0xBD: 'SCMD_UNIO_TX_RX', + 0xBE: 'SCMD_UNIO_TX', + 0xBF: 'SCMD_MEASURE_PULSE', + 0xC0: 'SCMD_ICDSLAVE_TX_BUF_BL', + 0xC1: 'SCMD_ICDSLAVE_TX_LIT_BL', + 0xC2: 'SCMD_ICDSLAVE_RX_BL', + 0xC3: 'SCMD_SPI_RDWR_BYTE_BUF', + 0xC4: 'SCMD_SPI_RDWR_BYTE_LIT', + 0xC5: 'SCMD_SPI_RD_BYTE_BUF', + 0xC6: 'SCMD_SPI_WR_BYTE_BUF', + 0xC7: 'SCMD_SPI_WR_BYTE_LIT', + 0xC8: 'SCMD_I2C_RD_BYTE_NACK', + 0xC9: 'SCMD_I2C_RD_BYTE_ACK', + 0xCA: 'SCMD_I2C_WR_BYTE_BUF', + 0xCB: 'SCMD_I2C_WR_BYTE_LIT', + 0xCC: 'SCMD_I2C_STOP', + 0xCD: 'SCMD_I2C_START', + 0xCE: 'SCMD_AUX_STATE_BUFFER', + 0xCF: 'SCMD_SET_AUX', + 0xD0: 'SCMD_WRITE_BITS_BUF_HLD', + 0xD1: 'SCMD_WRITE_BITS_LIT_HLD', + 0xD2: 'SCMD_CONST_WRITE_DL', + 0xD3: 'SCMD_WRITE_BUFBYTE_W', + 0xD4: 'SCMD_WRITE_BUFWORD_W', + 0xD5: 'SCMD_RD2_BITS_BUFFER', + 0xD6: 'SCMD_RD2_BYTE_BUFFER', + 0xD7: 'SCMD_VISI24', + 0xD8: 'SCMD_NOP24', + 0xD9: 'SCMD_COREINST24', + 0xDA: 'SCMD_COREINST18', + 0xDB: 'SCMD_POP_DOWNLOAD', + 0xDC: 'SCMD_ICSP_STATES_BUFFER', + 0xDD: 'SCMD_LOOP_BUFFER', + 0xDE: 'SCMD_ICDSLAVE_TX_BUF', + 0xDF: 'SCMD_ICDSLAVE_TX_LIT', + 0xE0: 'SCMD_ICDSLAVE_RX', + 0xE1: 'SCMD_POKE_SFR', + 0xE2: 'SCMD_PEEK_SFR', + 0xE3: 'SCMD_EXIT_SCRIPT', + 0xE4: 'SCMD_GOTO_INDEX', + 0xE5: 'SCMD_IF_GT_GOTO', + 0xE6: 'SCMD_IF_EQ_GOTO', + 0xE7: 'SCMD_DELAY_SHORT', + 0xE8: 'SCMD_DELAY_LONG', + 0xE9: 'SCMD_LOOP', + 0xEA: 'SCMD_SET_ICSP_SPEED', + 0xEB: 'SCMD_READ_BITS', + 0xEC: 'SCMD_READ_BITS_BUFFER', + 0xED: 'SCMD_WRITE_BITS_BUFFER', + 0xEE: 'SCMD_WRITE_BITS_LITERAL', + 0xEF: 'SCMD_READ_BYTE', + 0xF0: 'SCMD_READ_BYTE_BUFFER', + 0xF1: 'SCMD_WRITE_BYTE_BUFFER', + 0xF2: 'SCMD_WRITE_BYTE_LITERAL', + 0xF3: 'SCMD_SET_ICSP_PINS', + 0xF4: 'SCMD_BUSY_LED_OFF', + 0xF5: 'SCMD_BUSY_LED_ON', + 0xF6: 'SCMD_MCLR_GND_OFF', + 0xF7: 'SCMD_MCLR_GND_ON', + 0xF8: 'SCMD_VPP_PWM_OFF', + 0xF9: 'SCMD_VPP_PWM_ON', + 0xFA: 'SCMD_VPP_OFF', + 0xFB: 'SCMD_VPP_ON', + 0xFC: 'SCMD_VDD_GND_OFF', + 0xFD: 'SCMD_VDD_GND_ON', + 0xFE: 'SCMD_VDD_OFF', + 0xFF: 'SCMD_VDD_ON' +} + +def disassemble(blob, offset): + code = blob[offset] + length = 1 + command = ScriptCommandTable[code] + result = {} + result['mnemonic'] = command + if code == 0xCF: + length += 1 + result['op'] = hex(blob[offset + 1]) + elif code == 0xD3 or code == 0xD4: + length += 1 + immediate = blob[offset + 1] + elif code == 0xD9: + if blob[offset + 1 + 2] == 0x04: + # it's a goto, and there's a second instruction. this OUGHT to be + # followed by a SCMD_NOP24... + if blob[offset + 1 + 3] == 0xD8: + # it is! whew + instrbytes = blob[offset + 1:offset + 1 + 3] + instrbytes.append(0) + instrbytes.append(0) + instrbytes.append(0) + + (postinstr_offset, instr) = pic24.disassemble(instrbytes, 0) + length = 1 + 3 + 1 # the command, three real bytes + the nop + result['op'] = instr #pic24.render(instr) + else: + (postinstr_offset, instr) = pic24.disassemble(blob, offset + 1) +# length = postinstr_offset - offset + length = 4 + result['op'] = instr #pic24.render(instr) + print("Goto not followed by nop, uhh what's " + hex(blob[offset + 3 + 1])) + else: + (postinstr_offset, instr) = pic24.disassemble(blob, offset + 1) + length = postinstr_offset - offset + result['op'] = instr #pic24.render(instr) + elif code in NoOperands: + pass + elif code == 0xE7 or code == 0xE8: + length += 1 + result['op'] = hex(blob[offset + 1]) + elif code == 0xEE: + length += 2 +# not sure if this is really two operands + result['op'] = hex(blob[offset + 1]) + ", " + hex(blob[offset + 2]) + elif code == 0xE9: + length += 2 + result['op'] = hex((blob[offset + 2] << 8) + blob[offset + 1]) + elif code == 0xF2: + length += 1 + result['op'] = hex(blob[offset + 1]) + elif code == 0xF3: + length += 1 + result['op'] = hex(blob[offset + 1]) + else: + print("Unknown: " + command) + return None + + return (offset + length, result) diff --git a/source/notes/pic-mcu/pickit2/pk2cmd-stuff/pk2cmd_script.pyc b/source/notes/pic-mcu/pickit2/pk2cmd-stuff/pk2cmd_script.pyc Binary files differnew file mode 100644 index 0000000..2ad27ee --- /dev/null +++ b/source/notes/pic-mcu/pickit2/pk2cmd-stuff/pk2cmd_script.pyc diff --git a/source/notes/pic-mcu/pickit2/pk2cmd-stuff/pydare.py b/source/notes/pic-mcu/pickit2/pk2cmd-stuff/pydare.py new file mode 100644 index 0000000..f24f69f --- /dev/null +++ b/source/notes/pic-mcu/pickit2/pk2cmd-stuff/pydare.py @@ -0,0 +1,610 @@ +import json +import importlib +import traceback +import sys +import os + +import pic16 +import pic18 +import pic24 + +running = True +DEBUG = False + +ANSI_BLUE = "\x1b[34m" +ANSI_YELLOW = "\x1b[33m" +ANSI_DARK_GREEN = "\x1b[32m" +ANSI_GREEN = "\x1b[1m\x1b[32m" +ANSI_RED = "\x1b[31m" +ANSI_RESET = "\x1b[0m" + +COLOR_REGISTER = ANSI_YELLOW +COLOR_FUNCTION = ANSI_GREEN +COLOR_LABEL = ANSI_DARK_GREEN +COLOR_ADDRESS = ANSI_DARK_GREEN + +state = { + 'running': True, + 'dirty': False +} + +def parse_parts(msg): + parts = [] + i = 0 + wordstart = 0 + word = "" + stripped = msg.strip() + + in_quotes = False + escaping = False + + while i < len(stripped): + if escaping: + # escaping means even spaces aren't the end of the word, so + word = word + stripped[i] + escaping = False + else: + if stripped[i] == ' ': + if in_quotes: + # this isn't actually the end of a word + word = word + stripped[i] + else: + parts.append(word) + word = "" + elif stripped[i] == '\\': + escaping = True + elif stripped[i] == '"': + in_quotes = not in_quotes + else: + word = word + stripped[i] + + i = i + 1 + + parts.append(word) + word = "" + + # todo: signal unmatched quotes + + return parts + +def readnum(s): + if s.startswith("0x"): + return int(s[2:], 16) + else: + return int(s) + +def parse_cmd(cmd): + cmd_parts = parse_parts(cmd) + smol_to_big = { + "o": "open", + "c": "define-comment", + "c+": "define-comment", + "q": "quit", + "d": "disassemble", + "h": "help" + } + + result = {} + + if len(cmd_parts) > 0: + result['type'] = cmd_parts[0] + if result['type'] in smol_to_big: + result['type'] = smol_to_big[result['type']] + + result['params'] = cmd_parts[1:] + result['raw_text'] = cmd + + if len(cmd_parts) > 1 and cmd_parts[-1][0] == '@': + result['where'] = resolve_addr(cmd_parts[-1][1:], state) + elif len(cmd_parts) > 2 and cmd_parts[-2] == '@': + result['where'] = resolve_addr(cmd_parts[-1], state) + + if 'where' in result and result['where'] is None: + result['invalid'] = True + + return result + +def resolve_addr(where, state): + # where may be the name of a label or function + if where in state['notes']['functions-reverse']: + return state['notes']['functions-reverse'][where] + elif where in state['notes']['labels-reverse']: + return state['notes']['labels-reverse'][where] + else: + # if it's not there, it better be a number... + try: + return readnum(where) + except ValueError: + print("{} is not a known function or label.".format(where)) + +def do_help(cmd, state): + print("haha, help") + +def do_open(cmd, state): + f = open(cmd['params'][0]) + buf = f.read(6) + f.close() + if buf == ":02000": + return do_openhex(cmd, state) + else: + return do_openbin(cmd, state) + +def do_openbin(cmd, state): + return inneropen(cmd, state, lambda x: { 0: x.read() }) + +def do_openhex(cmd, state): + return inneropen(cmd, state, lambda x: read_hex(x)) + +def read_hex(f): + lines = f.readlines() + regions = { 0: [] } + curr_region = regions[0] + + for line in lines: + if not line.startswith(':'): + continue +# raise Exception("invalid hex line, needs to start with a ':', but was: " + line) + bytecount = int(line[1:3], 16) + addr = int(line[3:7], 16) + rec_type = int(line[7:9], 16) + data_end = bytecount * 2 + 9 + data = line[9:data_end] + # ignoring checksum because lazy + + if rec_type == 4: + ext_linear_addr = int(data, 16) + if ext_linear_addr not in regions: + regions[ext_linear_addr] = [] + + curr_region = regions[ext_linear_addr] + elif rec_type == 0: + for i in range(bytecount): + if len(curr_region) <= addr + i: + curr_region.extend([0] * (1 + addr + i - len(curr_region))) + curr_region[addr + i] = int(data[i*2:i*2 + 2], 16) + elif rec_type == 1: + if DEBUG: + print("Read HEX file ({} regions)".format(len(regions))) + return regions + else: + raise Exception("Unsupported record type: " + str(rec_type)) + +def do_goto(cmd, state): + try: + dest = int(cmd['params'][0]) + except ValueError: + # parse error, might be a function or label! + # labels first... + name = cmd['params'][0] + if name in state['notes']['labels-reverse']: + dest = state['notes']['labels-reverse'][name] + if name in state['notes']['functions-reverse']: + dest = state['notes']['functions-reverse'][name] + state['cursor'] = int(cmd['params'][0]) + +def do_goto_bank(cmd, state): + param = cmd['params'][0] + if not param in state['all-regions']: + state['all-regions'][param] = [] + + state['data'] = state['all-regions'][param] + +def inneropen(cmd, state, readfn): + newfile = cmd['params'][0] + if os.path.isfile(newfile): + newdata = None + try: + f = open(newfile) + newdata = readfn(f) + f.close() + except Exception as e: + print("Failed to open new file: {}".format(newfile)) + print("Got: {}".format(e)) + print(traceback.format_exc()) + return + state['notes'] = { + 'comments': {}, + 'functions': {}, + 'functions-reverse': {}, + 'labels': {}, + 'labels-reverse': {} + } + state['cursor'] = 0 + state['file'] = newfile + state['all-regions'] = newdata + state['selected-region'] = newdata.keys()[0] + state['data'] = newdata[state['selected-region']] + elif os.path.isdir(newfile): + print("Cannot open {}, it is a directory".format(newfile)) + else: + print("File {} does not exist".format(newfile)) + + if 'arch-name' not in state or state['arch-name'] is None: + # default arch to the best cpu, pic16 + do_setarch({ 'params': ['pic16'] }, state) + + if DEBUG: + print("Opened {} as {}".format(newfile, state['arch-name'])) + +def do_comment(cmd, state): + state['notes']['comments'][cmd['where']] = cmd['params'][0] + state['dirty'] = True + +def new_function(name): + return { + "name": name, + "params": None, + "returns": None + } + +def do_undefine_function(cmd, state): + name = cmd['params'][0] + if cmd['params'][0] in state['notes']['functions-reverse']: + fnaddr = state['notes']['functions-reverse'][cmd['params'][0]] + del state['notes']['functions'][fnaddr] + del state['notes']['functions-reverse'][name] + return + else: + print("Function {} is not defined".format(name)) + +def do_define_function(cmd, state): + if cmd['params'][0] in state['notes']['functions-reverse']: + fnaddr = state['notes']['functions-reverse'][cmd['params'][0]] + if fnaddr != cmd['where']: + print("Function {} is already defined at {}".format(cmd['params'][0], fnaddr)) + return + else: + newname = cmd['params'][0] + fn = state['notes']['functions'][cmd['where']] + del state['notes']['functions-reverse'][fn['name']] + state['notes']['functions-reverse'][newname] = fn + fn['name'] = newname + else: + state['notes']['functions'][cmd['where']] = new_function(cmd['params'][0]) + state['notes']['functions-reverse'][cmd['params'][0]] = cmd['where'] + state['dirty'] = True + +def do_define_label(cmd, state): + state['notes']['labels'][cmd['where']] = cmd['params'][0] + state['notes']['labels-reverse'][cmd['params'][0]] = cmd['where'] + state['dirty'] = True + +def colorize(string, color): + return "{}{}{}".format( + color, + string, + ANSI_RESET + ) + +def do_disassemble(cmd, state): + if 'data' not in state: + print("No file currently open") + return + if 'cursor' not in state: + print("No cursor into the file (this is a bug - a file must be open?") + return + + if 'where' in cmd: + where = cmd['where'] + else: + where = state['cursor'] + + if len(cmd['params']) > 0: + count = int(cmd['params'][0]) + else: + count = 1 + + arch = state['arch'] + + try: + disassembled = 0 + while disassembled < count: + prewhere = where + (where, instr) = arch.disassemble(state['data'], where) + if 'ops' in instr: + newops = instr['ops'] + for i, op in enumerate(instr['ops']): + if isinstance(op, dict) and 'type' in op: + note = None + if op['type'] == "absolutedest": + if op['value'] in state['notes']['functions']: + note = state['notes']['functions'][op['value']]['name'] + note = colorize(note, COLOR_FUNCTION) + elif op['value'] in state['notes']['labels']: + note = state['notes']['labels'][op['value']] + note = colorize(note, COLOR_LABEL) + else: + note = colorize(hex(op['value']), COLOR_ADDRESS) + elif op['type'] == "relpostdest": + # if there's a thing there replace with it + newops[i] = "relpostdest" + ea = prewhere + instr['length'] * 2 + op['value'] + if ea in state['notes']['functions']: + note = state['notes']['functions'][ea]['name'] + note = colorize(note, COLOR_FUNCTION) + elif ea in state['notes']['labels']: + note = state['notes']['labels'][ea] + note = colorize(note, COLOR_LABEL) + else: + note = "0x{:x} (ip+2{}{})".format( + ea, + "+" if op['value'] >= 0 else "", + hex(op['value']) + ) + note = colorize(note, COLOR_ADDRESS) + elif op['type'] == "relpredest": + pass + elif op['type'] == "register" or op['type'] == "banked-register": + nicename = arch.reg_name(op['value']) + if nicename is None: + if isinstance(op['value'], str): + note = op['value'] + else: + note = hex(op['value']) + else: + note = nicename + + note = colorize(note, COLOR_REGISTER) + + if not note is None: + newops[i] = str(note) + + instr['ops'] = newops + + prefix = None + if prewhere in state['notes']['functions']: + fn = state['notes']['functions'][prewhere] + prefix = colorize( + "{:08x}> start of {}\n".format(prewhere, fn['name']), + COLOR_FUNCTION + ) + elif prewhere in state['notes']['labels']: + label = state['notes']['labels'][prewhere] + prefix = colorize( + "{:08x}: {}\n".format(prewhere, label), + COLOR_LABEL + ) + instrstring = arch.render(instr) + to_show = "{:08x}: {}".format(prewhere, instrstring) + if prewhere in state['notes']['comments']: + to_show = "{: <35} {}; {}{}".format( + to_show, + ANSI_BLUE, + state['notes']['comments'][prewhere], + ANSI_RESET + ) + if not prefix is None: + to_show = prefix + to_show + print(to_show) + disassembled = disassembled + 1 + except Exception as e: + print("Exception while disassembling: {}".format(e)) + print(traceback.format_exc()) + +def do_setarch(cmd, state): + try: + loaded_arch = importlib.import_module(cmd['params'][0]) + except ImportError: + print("Cannot find module for arch '{}'".format(cmd['params'][0])) + except Exception as e: + print("General error loading '{}': {}".format(cmd['params'][0], e)) + + state['arch-name'] = cmd['params'][0] + state['arch'] = loaded_arch + +def dict_from_file(path): + f = open(path) + result = json.loads(f.read()) + f.close() + return result + +def dict_to_file(path, data): + f = open(path, 'w') + f.write(json.dumps(data, sort_keys=True, indent=2)) + f.close() + +# so json.dumps turns numeric keys into strings. +# this breaks some dictionaries. +def fix_keys(obj): + redo = [] + for k in obj: + try: + knum = int(k) + redo.append(k) + except ValueError: + pass + + for k in redo: + knum = int(k) + obj[knum] = obj[k] + del obj[k] + +def do_loaddb(cmd, state): + if len(cmd['params']) == 0: + if 'file' in state: + dbpath = state['file'] + '.nrt' + else: + print("No db path provided nor file loaded - I don't know what to load!") + return + else: + dbpath = cmd['params'][0] + if os.path.isdir(dbpath) and os.path.isdir(dbpath + '/.git'): + if DEBUG: + print("Loading {} ...".format(dbpath)) + try: + dbroot = dict_from_file(dbpath + '/root.json') + do_setarch({ "params": [dbroot['arch-name']] }, state) + state['notes']['comments'] = dict_from_file(dbpath + '/comments.json') + fix_keys(state['notes']['comments']) + state['notes']['functions'] = dict_from_file(dbpath + '/functions.json') + state['notes']['functions-reverse'] = dict_from_file(dbpath + '/functions-reverse.json') + fix_keys(state['notes']['functions']) + state['notes']['labels'] = dict_from_file(dbpath + '/labels.json') + state['notes']['labels-reverse'] = dict_from_file(dbpath + '/labels-reverse.json') + fix_keys(state['notes']['labels']) + state['default-dbpath'] = dbpath +# check db file path matches current file path? + if DEBUG: + print("wow you're really using this, huh?") + except Exception as e: + print("Error loading db: {}".format(e)) + elif os.path.isdir(dbpath): + print("Cannot load {}, there is no repository there".format(dbpath)) + elif os.path.isfile(dbpath): + print("Cannot load {}, it is a file".format(dbpath)) + else: + print("Cannot load {}, it does not exist".format(dbpath)) + +def do_savedb(cmd, state): + if len(cmd['params']) > 0: + dbpath = cmd['params'][0] + elif 'default-dbpath' in state: + dbpath = state['default-dbpath'] + else: + dbpath = state['file'] + '.nrt' + + if os.path.isfile(dbpath): + print("File is present, but should be a directory. Cannot save.") + return + elif os.path.isdir(dbpath): + if not os.path.isdir(dbpath + '/.git'): + print("dbpath is a directory, but there is no git repo there. Opting to not save.") + return + else: + # dbpath exists, and there's a git repo there, we can proceed + pass + else: + # none of the directories exist, so we can start fresh + os.mkdir(dbpath) + # TODO: pray the input filename doesn't have a ' in it i guess + os.system('cd \'{}\' && git init'.format(dbpath)) + + to_save = {} + to_save['arch-name'] = state['arch-name'] + dict_to_file(dbpath + '/root.json', to_save) + dict_to_file(dbpath + '/comments.json', state['notes']['comments']) + dict_to_file(dbpath + '/functions.json', state['notes']['functions']) + dict_to_file(dbpath + '/functions-reverse.json', state['notes']['functions-reverse']) + dict_to_file(dbpath + '/labels.json', state['notes']['labels']) + dict_to_file(dbpath + '/labels-reverse.json', state['notes']['labels-reverse']) + os.system('cd \'{}\' && git add . && git commit -m "automatic save"'.format(dbpath)) + state['dirty'] = False + +def do_quit(cmd, state): + # prompt before saving + if not 'dirty' in state or state['dirty']: + do_savedb({ "params": [] }, state) + state['running'] = False + +def do_sh(cmd, state): + if len(cmd['params']) == 1: + os.system(cmd['params'][0]) + else: + print("sh expects exactly one argument (may be a string)") + +def do_info(cmd, state): + if 'file' in state: + print("File: {}".format(state['file'])) + print("Regions:") + keys = state['all-regions'].keys() + keys.sort() + for key in keys: + print(" {}{}: {} bytes".format( + '*' if key == state['selected-region'] else ' ', + key, + hex(len(state['all-regions'][key])) + )) + +def readnum(string): + if string.startswith('0x'): + return int(string, 16) + else: + return int(string) + +def do_list_comments(cmd, state): + print("Comments:") + for l in state['notes']['comments']: + print("{}: 0x{:x}".format(state['notes']['comments'][l], l)) + +def do_list_functions(cmd, state): + print("Functions:") + for l in state['notes']['functions']: + print("{}: 0x{:x}".format(state['notes']['functions'][l]['name'], l)) + +def do_list_labels(cmd, state): + print("Labels:") + for l in state['notes']['labels']: + print("{}: 0x{:x}".format(state['notes']['labels'][l], l)) + +def do_hexprint(cmd, state): + count = readnum(cmd['params'][0]) + start = cmd['where'] + idx = start + + while count > idx - start: + sys.stdout.write("{:08x}: ".format(idx)) + for i in range(16): + if count <= idx - start: + break + sys.stdout.write("{:02x} ".format(state['data'][idx]),) + idx = idx + 1 + sys.stdout.write('\n') + +cmdmap = { + "px": do_hexprint, + "define-comment": do_comment, + "define-function": do_define_function, + "undefine-function": do_undefine_function, + "define-label": do_define_label, + "list-comments": do_list_comments, + "list-functions": do_list_functions, + "list-labels": do_list_labels, + "open": do_open, + "openhex": do_openhex, + "arch": do_setarch, + "disassemble": do_disassemble, + "loaddb": do_loaddb, + "savedb": do_savedb, + "quit": do_quit, + "help": do_help, + "info": do_info, + "goto": do_goto, + "goto-bank": do_goto_bank, + "sh": do_sh +} + +def do_cmd_thing(cmd, state): + if 'invalid' in cmd: + pass # can't do anything with it. + elif cmd['type'] in cmdmap: + cmdmap[cmd['type']](cmd, state) + else: + print("I don't recognize the command `{}`".format(cmd['raw_text'])) + +for i, arg in enumerate(sys.argv): + # just the path of this script + # i bet that only applies because i'm running as + # `python pydare.py ...` + if i == 0: + continue + do_cmd_thing(parse_cmd(arg), state) + +# if len(sys.argv) > 1: +# do_open({"params": [sys.argv[1]]}, state) +# if len(sys.argv) > 2: +# do_setarch({"params": [sys.argv[2]]}, state) + +import readline +readline.parse_and_bind("") +if os.path.isfile(".pydare_history"): + readline.read_history_file(".pydare_history") + +while state['running']: + try: + do_cmd_thing(parse_cmd(raw_input("> ")), state) + except Exception as e: + print("Unhandled exception: {}".format(e)) + print(traceback.format_exc()) + +if not os.path.isdir(".pydare_history"): + readline.write_history_file(".pydare_history") diff --git a/source/notes/pic-mcu/pickit2/pk2cmd-stuff/readdat.py b/source/notes/pic-mcu/pickit2/pk2cmd-stuff/readdat.py new file mode 100644 index 0000000..6fc8919 --- /dev/null +++ b/source/notes/pic-mcu/pickit2/pk2cmd-stuff/readdat.py @@ -0,0 +1,280 @@ +import struct +import sys + +import pic18 +import pic24 +import pk2cmd_script + +datfile = open("../pk2cmd/pk2cmd/PK2DeviceFile.dat").read() + +def readstr(datfile, offset): + length = ord(datfile[offset]) & 0xff + offset += 1 + if length > 0x7f: + length &= 0x7f + length += 0x80 * (ord(datfile[offset]) & 0xff) + offset += 1 + s = "" + for i in range(length): + s += datfile[offset] + offset += 1 +# if s[-1] == '\x0d': +# s += datfile[offset] +# offset += 1 + return (offset, s) + +def readDeviceFileParams(datfile, offset): + result = {} + (result['versionMajor'], result['versionMinor'], result['versionDot']) = struct.unpack_from('=iii', datfile, offset) + offset += 12 + (offset, result['versionNote']) = readstr(datfile, offset) + (result['numFamilies'], result['numParts'], result['numScripts']) = struct.unpack_from('=iii', datfile, offset) + offset += 12 + result['compatibility'] = ord(datfile[offset]) + offset += 1 + offset += 1 + 2 + 4 + return (offset, result) + +(offset, params) = readDeviceFileParams(datfile, offset=0) + +print(params) + +families = {} +parts = {} +scripts = {} + +def readDevicePart(datfile, offset): + result = {} + (offset, result['name']) = readstr(datfile, offset) + ( + result['family'], + result['id'], + result['programMem'], + result['EEMem'], + result['EEAddr'], + result['configWords'], + result['configAddr'], + result['userIDWords'], + result['userIDAddr'], + result['bandGapMask'] + ) = struct.unpack_from('=HIIHIBIBII', datfile, offset) + offset += 2 + 4 + 4 + 2 + 4 + 1 + 4 + 1 + 4 + 4 + result['configMasks'] = [0] * 9 + # entry 8 will come later. ~backwards compat~ + ( + result['configMasks'][0], + result['configMasks'][0], + result['configMasks'][0], + result['configMasks'][0], + result['configMasks'][0], + result['configMasks'][0], + result['configMasks'][0], + result['configMasks'][0] + ) = struct.unpack_from('=HHHHHHHH', datfile, offset) + offset += 2 * 8 + + result['configBlank'] = [0] * 9 + # entry 8 will come later. ~backwards compat~ + ( + result['configBlank'][0], + result['configBlank'][0], + result['configBlank'][0], + result['configBlank'][0], + result['configBlank'][0], + result['configBlank'][0], + result['configBlank'][0], + result['configBlank'][0] + ) = struct.unpack_from('=HHHHHHHH', datfile, offset) + offset += 2 * 8 + ( + result['CPMask'], + result['CPConfig'], + result['OSSCALSave'], + result['ignoreAddress'], + result['vddMin'], + result['vddMax'], + result['vddErase'], + result['calibrationWords'], + result['chipEraseScript'], + result['progMemAddrSetScript'], + result['progMemAddrBytes'], + result['progMemRdScript'], + result['progMemRdWords'], + result['EERdPrepScript'], + result['EERdScript'], + result['EERdLocations'], + result['userIDRdPrepScript'], + result['userIDRdScript'], + result['configRdPrepScript'], + result['configRdScript'], + result['progMemWrPrepScript'], + result['progMemWrScript'], + result['progMemWrWords'], + result['progMemPanelBufs'], + result['progMemPanelOffset'], + result['EEWrPrepScript'], + result['EEWrScript'], + result['EEWrLocations'], + result['userIDWrPrepScript'], + result['userIDWrScript'], + result['configWrPrepScript'], + result['configWrScript'], + result['OSCCALRdScript'], + result['OSCCALWrScript'], + result['DPMask'], + result['writeCfgOnErase'], + result['blankCheckSkipUsrIDs'], + result['ignoreBytes'], + result['chipErasePrepScript'], + result['bootFlash'] + ) = struct.unpack_from('=HB?IfffBHHBHHHHHHHHHHHHBIIIIIIIIIII??HHI', datfile, offset) + # f I B ? H + offset += 4 * 3 + 4 * 13 + 1 * 4 + 1 * 3 + 2 * 17 + ( + result['configMasks'][8], # and these are the last entries above + result['configBlank'][8], + result['progMemEraseScript'], + result['EEMemEraseScript'], + result['configMemEraseScript'], + result['Reserved1EraseScript'], + result['Reserved2EraseScript'], + result['testMemoryRdScript'], + result['testMemoryRdWords'], + result['EERowEraseScript'], + result['EERowEraseWords'], + result['exportToMPLAB'], + result['debugHaltScript'], + result['debugRunScript'], + result['debugStatusScript'], + result['debugReadExecVerScript'], + result['debugSingleStepScript'], + result['debugBulkWrDataScript'], + result['debugBulkRdDataScript'], + result['debugWriteVectorScript'], + result['debugReadVectorScript'], + result['debugRowEraseScript'], + result['debugRowEraseSize'], + result['debugReserved5Script'], + result['debugReserved6Script'], + result['debugReserved7Script'], + result['debugReserved8Script'], + result['LVPScript'] + ) = struct.unpack_from('=HHHHHHHHHHH?HHHHHHHHHHHHHHHH', datfile, offset) + offset += 2 * 27 + 1 * 1 +# uhhhhh + offset -= 20 + return (offset, result) + +def readDeviceFamily(datfile, offset): + result = {} + (result['id'], result['type'], result['searchPriority']) = struct.unpack_from('=HHH', datfile, offset) + offset += 6 + (offset, result['name']) = readstr(datfile, offset) + (result['progEntryScript'], result['progExitScript'], result['readDevIDScript'], result['deviceIDMask'], result['blankValue'], result['bytesPerLocation'], result['addressIncrement']) = struct.unpack_from('=HHHiiBB', datfile, offset) + offset += 2 * 3 + 4 * 2 + 1 * 2 + result['partDetect'] = ord(datfile[offset]) + offset += 1 + ( + result['progEntryVPPScript'], + result['unused1'], + result['EEMemBytesPerWord'], + result['EEMemAddressIncrement'], + result['userIDHexBytes'], + result['userIDBytes'], + result['progMemHexBytes'], + result['EEMemHexBytes'], + result['progMemShift'], + result['testMemoryStart'], + result['testMemoryLength'], + result['vpp'] + ) = struct.unpack_from('=HHBBBBBBBiHf', datfile, offset) + offset += 2 * 2 + 1 * 7 + 4 + 2 + 4 + return (offset, result) + +def readScript(datfile, offset): + result = {} + result['number'] = struct.unpack_from('=H', datfile, offset)[0] + offset += 2 + (offset, result['name']) = readstr(datfile, offset) + (result['version'], result['unused1'], result['length']) = struct.unpack_from('=HIH', datfile, offset) + offset += 8 + script = [] + print("Reading script " + result['name'] + " at " + hex(offset) + " len=" + str(result['length'])) + for i in range(result['length']): + script.append(struct.unpack_from('=B', datfile, offset)[0]) +# script.append(struct.unpack_from('=B', datfile, offset + 1)[0]) + offset += 2 + result['script'] = script + (offset, result['comment']) = readstr(datfile, offset) + return (offset, result) + +print("Reading families...") + +for i in range(params['numFamilies']): + (offset, family) = readDeviceFamily(datfile, offset) + families[family['id']] = family + +print("Reading parts...") + +for i in range(params['numParts']): + (offset, part) = readDevicePart(datfile, offset) + parts[part['id']] = part + +print("Reading scripts...") + +for i in range(params['numScripts']): + (offset, script) = readScript(datfile, offset) + scripts[script['number']] = script + +database = { "parts": parts, "families": families, "scripts": scripts } + +print("Ready!") + +def findPart(model, database): + for p in database['parts']: + if database['parts'][p]['name'] == model: + return database['parts'][p] + return None + +part = findPart("PIC24FJ256DA206", database) + +if part is None: + print("Could not find part.") + sys.exit(1) + +def disassemble_script(content): + offset = 0 + while offset < len(content): + (offset, instr) = pk2cmd_script.disassemble(content, offset) + print(instr) + +def printScript(script): + print(" Name: " + script['name']) + print(" Script length: " + str(script['length'])) + if True: + disassemble_script(script['script']) +# print("Comment: " + script['comment']) + +def printPart(part, database): + print("Name: " + part['name']) + family = database["families"][part["family"]] + print("Family: " + family['name']) + print("Program memory: " + str(part['programMem'])) + print("Vdd_min: " + str(part['vddMin'])) + print("Vdd_max: " + str(part['vddMax'])) + print("Vdd_erase: " + str(part['vddErase'])) + print("ProgMemAddrBytes: " + str(part['progMemAddrBytes'])) + print("ChipEraseScript: ") + printScript(database['scripts'][part['chipEraseScript']]) + print("ProgEntryScript: ") + printScript(database['scripts'][family['progEntryScript']]) + print("ProgExitScript: ") + printScript(database['scripts'][family['progExitScript']]) + print("ReadDevIDScript: ") + printScript(database['scripts'][family['readDevIDScript']]) + print("ProgMemRdScript (id " + str(part['progMemRdScript']) + "): ") + printScript(database['scripts'][part['progMemRdScript']]) + print("ProgMemAddrSetScript (id " + str(part['progMemAddrSetScript']) + "): ") + printScript(database['scripts'][part['progMemAddrSetScript']]) + +printPart(part, database) diff --git a/source/notes/pic-mcu/pickit2/pk2cmd-stuff/tablelines b/source/notes/pic-mcu/pickit2/pk2cmd-stuff/tablelines new file mode 100644 index 0000000..30008f4 --- /dev/null +++ b/source/notes/pic-mcu/pickit2/pk2cmd-stuff/tablelines @@ -0,0 +1,39 @@ +On branch master +nothing to commit, working directory clean +:02000 +Inferred input is intel HEX +Read HEX file (4 regions) +Opened ../pk2cmd/pk2cmd/PK2V023200.hex as pic16 +Loading pk2cmd_firmware ... +wow you're really using this, huh? +[32m00002334: jmp_tbl_1 +[0m00002334: bra [32m0x236a (ip+2+0x34)[0m +00002336: bra [32m0x23b6 (ip+2+0x7e)[0m +00002338: bra [32m0x2410 (ip+2+0xd6)[0m +0000233a: bra [32m0x2418 (ip+2+0xdc)[0m +0000233c: bra [32m0x2420 (ip+2+0xe2)[0m +0000233e: bra [32m0x2434 (ip+2+0xf4)[0m +00002340: bra [32m0x2464 (ip+2+0x122)[0m +00002342: bra [32m0x24a6 (ip+2+0x162)[0m +00002344: bra [32m0x24ae (ip+2+0x168)[0m +00002346: bra [32m0x24c2 (ip+2+0x17a)[0m +00002348: bra [32m0x24ca (ip+2+0x180)[0m +0000234a: bra [32m0x24d2 (ip+2+0x186)[0m +0000234c: bra [32m0x24da (ip+2+0x18c)[0m +0000234e: bra [32m0x24e2 (ip+2+0x192)[0m +00002350: bra [32m0x24e8 (ip+2+0x196)[0m +00002352: bra [32m0x24ee (ip+2+0x19a)[0m +00002354: bra [32m0x24f6 (ip+2+0x1a0)[0m +00002356: bra [32m0x2562 (ip+2+0x20a)[0m +00002358: bra [32m0x2574 (ip+2+0x21a)[0m +0000235a: bra [32m0x2586 (ip+2+0x22a)[0m +0000235c: bra [32m0x2598 (ip+2+0x23a)[0m +0000235e: bra [32m0x259e (ip+2+0x23e)[0m +00002360: bra [32m0x25b0 (ip+2+0x24e)[0m +00002362: bra [32m0x25b4 (ip+2+0x250)[0m +00002364: bra [32m0x25c4 (ip+2+0x25e)[0m +00002366: bra [32m0x265c (ip+2+0x2f4)[0m +00002368: bra [32m0x268a (ip+2+0x320)[0m +0000236a: incf [33mINDF2[0m, 0 +0000236c: clrf [33mFSR0H[0m +0000236e: addlw #0x0 |