From bb7bbc04ecb9e4feaecf59d7230f377e4c6fc143 Mon Sep 17 00:00:00 2001 From: iximeow Date: Mon, 9 Jul 2018 21:53:10 -0700 Subject: add pic notes --- .../pic-mcu/pickit2/pk2cmd-stuff/PK2V023200.hex | 2071 ++++++++++++++++++++ .../pickit2/pk2cmd-stuff/PK2V023200.hex.nrt | 1 + .../pic-mcu/pickit2/pk2cmd-stuff/hexdisasm.py | 71 + source/notes/pic-mcu/pickit2/pk2cmd-stuff/pic16.py | 154 ++ .../notes/pic-mcu/pickit2/pk2cmd-stuff/pic16.pyc | Bin 0 -> 3336 bytes source/notes/pic-mcu/pickit2/pk2cmd-stuff/pic18.py | 526 +++++ .../notes/pic-mcu/pickit2/pk2cmd-stuff/pic18.pyc | Bin 0 -> 9789 bytes source/notes/pic-mcu/pickit2/pk2cmd-stuff/pic24.py | 216 ++ .../notes/pic-mcu/pickit2/pk2cmd-stuff/pic24.pyc | Bin 0 -> 6281 bytes .../pickit2/pk2cmd-stuff/pk2_firmware_notes.md | 222 +++ .../pic-mcu/pickit2/pk2cmd-stuff/pk2cmd_firmware | 1 + .../pic-mcu/pickit2/pk2cmd-stuff/pk2cmd_script.py | 146 ++ .../pic-mcu/pickit2/pk2cmd-stuff/pk2cmd_script.pyc | Bin 0 -> 4375 bytes .../notes/pic-mcu/pickit2/pk2cmd-stuff/pydare.py | 610 ++++++ .../notes/pic-mcu/pickit2/pk2cmd-stuff/readdat.py | 280 +++ .../notes/pic-mcu/pickit2/pk2cmd-stuff/tablelines | 39 + 16 files changed, 4337 insertions(+) create mode 100644 source/notes/pic-mcu/pickit2/pk2cmd-stuff/PK2V023200.hex create mode 160000 source/notes/pic-mcu/pickit2/pk2cmd-stuff/PK2V023200.hex.nrt create mode 100644 source/notes/pic-mcu/pickit2/pk2cmd-stuff/hexdisasm.py create mode 100644 source/notes/pic-mcu/pickit2/pk2cmd-stuff/pic16.py create mode 100644 source/notes/pic-mcu/pickit2/pk2cmd-stuff/pic16.pyc create mode 100644 source/notes/pic-mcu/pickit2/pk2cmd-stuff/pic18.py create mode 100644 source/notes/pic-mcu/pickit2/pk2cmd-stuff/pic18.pyc create mode 100644 source/notes/pic-mcu/pickit2/pk2cmd-stuff/pic24.py create mode 100644 source/notes/pic-mcu/pickit2/pk2cmd-stuff/pic24.pyc create mode 100644 source/notes/pic-mcu/pickit2/pk2cmd-stuff/pk2_firmware_notes.md create mode 160000 source/notes/pic-mcu/pickit2/pk2cmd-stuff/pk2cmd_firmware create mode 100644 source/notes/pic-mcu/pickit2/pk2cmd-stuff/pk2cmd_script.py create mode 100644 source/notes/pic-mcu/pickit2/pk2cmd-stuff/pk2cmd_script.pyc create mode 100644 source/notes/pic-mcu/pickit2/pk2cmd-stuff/pydare.py create mode 100644 source/notes/pic-mcu/pickit2/pk2cmd-stuff/readdat.py create mode 100644 source/notes/pic-mcu/pickit2/pk2cmd-stuff/tablelines (limited to 'source/notes/pic-mcu/pickit2/pk2cmd-stuff') 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 index 0000000..1511337 --- /dev/null +++ b/source/notes/pic-mcu/pickit2/pk2cmd-stuff/PK2V023200.hex.nrt @@ -0,0 +1 @@ +Subproject commit 1511337ad63e4166069adccc25743533edb36bbc 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 new file mode 100644 index 0000000..285d3ba Binary files /dev/null and b/source/notes/pic-mcu/pickit2/pk2cmd-stuff/pic16.pyc differ 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 new file mode 100644 index 0000000..0a12e73 Binary files /dev/null and b/source/notes/pic-mcu/pickit2/pk2cmd-stuff/pic18.pyc differ 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 new file mode 100644 index 0000000..c9a39af Binary files /dev/null and b/source/notes/pic-mcu/pickit2/pk2cmd-stuff/pic24.pyc differ 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 index 0000000..4e76e52 --- /dev/null +++ b/source/notes/pic-mcu/pickit2/pk2cmd-stuff/pk2cmd_firmware @@ -0,0 +1 @@ +Subproject commit 4e76e524ce8613f971b4167a9e2db1458e21e692 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 new file mode 100644 index 0000000..2ad27ee Binary files /dev/null and b/source/notes/pic-mcu/pickit2/pk2cmd-stuff/pk2cmd_script.pyc differ 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? +00002334: jmp_tbl_1 +00002334: bra 0x236a (ip+2+0x34) +00002336: bra 0x23b6 (ip+2+0x7e) +00002338: bra 0x2410 (ip+2+0xd6) +0000233a: bra 0x2418 (ip+2+0xdc) +0000233c: bra 0x2420 (ip+2+0xe2) +0000233e: bra 0x2434 (ip+2+0xf4) +00002340: bra 0x2464 (ip+2+0x122) +00002342: bra 0x24a6 (ip+2+0x162) +00002344: bra 0x24ae (ip+2+0x168) +00002346: bra 0x24c2 (ip+2+0x17a) +00002348: bra 0x24ca (ip+2+0x180) +0000234a: bra 0x24d2 (ip+2+0x186) +0000234c: bra 0x24da (ip+2+0x18c) +0000234e: bra 0x24e2 (ip+2+0x192) +00002350: bra 0x24e8 (ip+2+0x196) +00002352: bra 0x24ee (ip+2+0x19a) +00002354: bra 0x24f6 (ip+2+0x1a0) +00002356: bra 0x2562 (ip+2+0x20a) +00002358: bra 0x2574 (ip+2+0x21a) +0000235a: bra 0x2586 (ip+2+0x22a) +0000235c: bra 0x2598 (ip+2+0x23a) +0000235e: bra 0x259e (ip+2+0x23e) +00002360: bra 0x25b0 (ip+2+0x24e) +00002362: bra 0x25b4 (ip+2+0x250) +00002364: bra 0x25c4 (ip+2+0x25e) +00002366: bra 0x265c (ip+2+0x2f4) +00002368: bra 0x268a (ip+2+0x320) +0000236a: incf INDF2, 0 +0000236c: clrf FSR0H +0000236e: addlw #0x0 -- cgit v1.1