summaryrefslogtreecommitdiff
path: root/source/notes/pic-mcu/pickit2/pk2cmd-stuff
diff options
context:
space:
mode:
authoriximeow <me@iximeow.net>2018-07-09 21:53:10 -0700
committeriximeow <me@iximeow.net>2018-07-09 21:53:10 -0700
commitbb7bbc04ecb9e4feaecf59d7230f377e4c6fc143 (patch)
treedfad417c3037964c68b68b74c59509fc8d6642c0 /source/notes/pic-mcu/pickit2/pk2cmd-stuff
parentaab989297b2f6b5ee4501ae1da1f4ca681cc6b7e (diff)
add pic notes
Diffstat (limited to 'source/notes/pic-mcu/pickit2/pk2cmd-stuff')
-rw-r--r--source/notes/pic-mcu/pickit2/pk2cmd-stuff/PK2V023200.hex2071
m---------source/notes/pic-mcu/pickit2/pk2cmd-stuff/PK2V023200.hex.nrt0
-rw-r--r--source/notes/pic-mcu/pickit2/pk2cmd-stuff/hexdisasm.py71
-rw-r--r--source/notes/pic-mcu/pickit2/pk2cmd-stuff/pic16.py154
-rw-r--r--source/notes/pic-mcu/pickit2/pk2cmd-stuff/pic16.pycbin0 -> 3336 bytes
-rw-r--r--source/notes/pic-mcu/pickit2/pk2cmd-stuff/pic18.py526
-rw-r--r--source/notes/pic-mcu/pickit2/pk2cmd-stuff/pic18.pycbin0 -> 9789 bytes
-rw-r--r--source/notes/pic-mcu/pickit2/pk2cmd-stuff/pic24.py216
-rw-r--r--source/notes/pic-mcu/pickit2/pk2cmd-stuff/pic24.pycbin0 -> 6281 bytes
-rw-r--r--source/notes/pic-mcu/pickit2/pk2cmd-stuff/pk2_firmware_notes.md222
m---------source/notes/pic-mcu/pickit2/pk2cmd-stuff/pk2cmd_firmware0
-rw-r--r--source/notes/pic-mcu/pickit2/pk2cmd-stuff/pk2cmd_script.py146
-rw-r--r--source/notes/pic-mcu/pickit2/pk2cmd-stuff/pk2cmd_script.pycbin0 -> 4375 bytes
-rw-r--r--source/notes/pic-mcu/pickit2/pk2cmd-stuff/pydare.py610
-rw-r--r--source/notes/pic-mcu/pickit2/pk2cmd-stuff/readdat.py280
-rw-r--r--source/notes/pic-mcu/pickit2/pk2cmd-stuff/tablelines39
16 files changed, 4335 insertions, 0 deletions
diff --git a/source/notes/pic-mcu/pickit2/pk2cmd-stuff/PK2V023200.hex b/source/notes/pic-mcu/pickit2/pk2cmd-stuff/PK2V023200.hex
new file mode 100644
index 0000000..8096b15
--- /dev/null
+++ b/source/notes/pic-mcu/pickit2/pk2cmd-stuff/PK2V023200.hex
@@ -0,0 +1,2071 @@
+:020000040000FA
+:1000000085EF07F01200FFFF04EF10F01200FFFF72
+:10001000FFFFFFFFFFFFFFFF0CEF10F01200FFFFDD
+:10002000FFFFFFFFFFFFFFFFFFFF00000401105174
+:10003000600BE842E842E842E842E842000901E099
+:1000400055D01151070A51E00B0A4FE0070A40E072
+:10005000010A2CE00B0A28E0020A26E0030A22E04B
+:10006000080A12E0010A0EE00F0A0AE0030A01E0A2
+:100070003CD00001010EB06F0001040EB76F36D006
+:1000800036D834D090D832D00001010EB06F0001C4
+:10009000B90EB16F000EB26F0001B8930001010EEE
+:1000A000B56F24D0A8D822D0F5D820D00001010EF9
+:1000B000B06F040114510001B16FB26BBA0EB127D9
+:1000C000000EB2230001B8930001010EB56F0ED0EF
+:1000D0000001010EB06F04011451EA6ABA0FE96E13
+:1000E000000EEA2212C4EFFF01D000D01200800EF1
+:1000F0000401105D57E11351030A34E0010A10E0D6
+:10010000030A01E04DD00001010EB06F0001600E46
+:10011000B16F0C0EB26F120E0001B56FB66B40D00E
+:100120000001010EB06F04011251F66EF76AD8900B
+:10013000F636F7369E0EF6260D0EF7220900F5CF9D
+:10014000B1F00A00F5CFB2F0020E0001F76AB12556
+:10015000F66EB251F7220900F5CFB5F00A00F5CFDF
+:10016000B6F01ED00001010EB06F04011251F66E00
+:10017000F76AD890F636F736A20EF6260D0EF7225D
+:100180000900F5CFB1F00A00F5CFB2F0B1C0F6FF2B
+:10019000B2C0F7FF0800F5500001B56FB66B00D094
+:1001A0000001B88312000001010EB06F0F0EE66E61
+:1001B000710EE66E0F0EE66E1BEC06F0E552E55290
+:1001C000E552010EE66EBA0EE66E000EE66E1BEC10
+:1001D00006F0E552E552E55212C4B9F0040112519D
+:1001E00004E10001050EB76F05D00001060EB76FE0
+:1001F000E7EC04F012000401186B196B04011051B4
+:100200001F0B020A15E0030A0FE0010A01E034D0D7
+:100210000001010EB06F02D0040118810001B8A1E5
+:1002200002D00401188328D00001010EB06F24D041
+:100230000001010EB06F040114510F0B080DF350B3
+:10024000016A000F006E040E01221451800B01E0C0
+:10025000010E040DF35000010024B36F000E0120C5
+:10026000B46FB3C0E9FFB4C0EAFFEF50040B03E082
+:100270000401010E186F00D00001B0050AE1000171
+:10028000180EB16F040EB26F0001B8930001020E98
+:10029000B56F12000401120510E110511F0B000987
+:1002A0000CE10001010EB06F030E0401115D03E1CA
+:1002B0000001B88102D00001B891040112513AE165
+:1002C00010511F0B020836E114510F0B000932E0E8
+:1002D0000001010EB06F040114510F0B080DF35013
+:1002E000016A000F006E040E01221451800B01E020
+:1002F000010E040DF35000010024B36F000E012025
+:10030000B46F030E0401115D07E1840EB3C0E9FF71
+:10031000B4C0EAFFEF6E0ED014AF06D0B3C0E9FF51
+:10032000B4C0EAFFEF6A06D0880EB3C0E9FFB4C0DC
+:10033000EAFFEF6E12006C500BE1040100513C0B20
+:10034000E842E8420D0802E108D801D03CD804D0C8
+:10035000040E6C5C01E147D81200D9CFE6FFE1CF73
+:10036000D9FFE6520001AF6BB06BB56BB66B16EC04
+:1003700000F0DF6ADF50006E016A010E005C000EC3
+:1003800001581BE20001B05101E017D0F76ADF34D9
+:10039000FE0BF736F66EAC0EF6260D0EF7220900B0
+:1003A000F5CF00F00800F5CF01F004D001C0FAFF4E
+:1003B0000050F96EFBDFDF2ADDD7D5D8E552E552D4
+:1003C000E7CFD9FF1200020E0001AF5D0AE192D81B
+:1003D000040100BD03D0C80E006F02D0880E006F6C
+:1003E00001D007D91200040E0001B75D0AE112C462
+:1003F0006EFF6E50000803E2050EB76F02D0030EC9
+:10040000B76F0001AF050AE10BD8040104BD03D0AA
+:10041000C80E046F02D0880E046F01D0EAD8120013
+:10042000D9CFE6FFE1CFD9FF020EE1260001080E89
+:10043000B55D000EB65905E2B5C0DEFFB6C0DDFF02
+:1004400003D0080EDE6EDD6A040104930491010EF0
+:10045000DB500413DFCF05F4000EDB500001B55F65
+:10046000010EDB50B65B180EB36F040EB46F0001C3
+:10047000B8A31ED0D9CFE9FFDACFEAFFEE50ED10D6
+:1004800016E0B1C0F6FFB2C0F7FF0800F550B3C0E8
+:10049000E9FFB4C0EAFFEF6E0001B32B000EB423F6
+:1004A000B12BB223DF06010E01E2DB06E3D71CD03D
+:1004B000D9CFE9FFDACFEAFFEE50ED1015E0B1C079
+:1004C000E9FFB2C0EAFFEF50B3C0E9FFB4C0EAFFF2
+:1004D000EF6E0001B32B000EB423B12BB223DF0665
+:1004E000010E01E2DB06E4D7D9CFE1FFE552E7CF09
+:1004F000D9FF1200D9CFE6FFE1CFD9FF020EE126E6
+:10050000030E04010015E76E010EE7CFDBFF01C407
+:10051000DFFFDE500001B527DD50B623180EB16FA6
+:10052000040EB26FD9CFE9FFDACFEAFFEE50ED103B
+:1005300014E0B1C0E9FFB2C0EAFFEF50B3C0E9FF79
+:10054000B4C0EAFFEF6EB32B000EB423B12BB2237D
+:10055000DF06010E01E2DB06E5D7D9CFE1FFE55268
+:10056000E7CFD9FF12006D980001B0510CE10401F2
+:10057000080E016F100E026F040E036F840E006FE1
+:100580000401046F35D0040110AF22D00001B55131
+:100590000401165D0001B6510401175904E216C4A6
+:1005A000B5F017C4B6F03CDF0001010EAF6F0401D7
+:1005B000080E016F100E026F040E036F800E006FA5
+:1005C0000401180E066F040E076FC80E046F10D0DA
+:1005D0000001020EAF6F0401056BC80E046F040129
+:1005E000080E016F180E026F040E036FC80E006F25
+:1005F00012000001AF6B0401080E016F100E026FB4
+:10060000040E036F880E006F0401046B1200550E78
+:10061000A76EAA0EA76EA68212000001420E6A6F94
+:10062000020E6B6F010E6C6F12000001606B665161
+:10063000605D1EE260C000F0016A026A675100243A
+:10064000F36E68510120F46E69510220F86EF4CF08
+:10065000F7FFF3CFF6FF0800F5CF61F06051EA6ACB
+:100660006A0FE96E000EEA2261C0EFFF602BDFD750
+:10067000F86A1200840EA66E0001606B6651605D20
+:1006800027E26051EA6A6A0FE96E000EEA22EFCFB4
+:1006900003F060C000F0016A026A67510024F36E43
+:1006A00068510120F46E69510220F86EF4CFF7FF13
+:1006B000F3CFF6FF03C0F5FF0C001F0E60151F08F7
+:1006C00003E06605605D01E1A2DF0001602BD6D783
+:1006D00012000001606B6651605D20E2940EA66E10
+:1006E0006051006E016A060ED89000360136E804AB
+:1006F000FBE1026A01BE0268000167510024F36E4B
+:1007000068510120F46E69510220F86EF4CFF7FFB2
+:10071000F3CFF6FF7CDF0001602BDDD7F86A120013
+:10072000A66A0001606B6651605D0EE2675160254C
+:10073000A96EA6806051EA6A6A0FE96E000EEA228D
+:10074000A8CFEFFF602BEFD712000001606B66515E
+:10075000605D13E267516025A96E6051EA6A6A0F15
+:10076000E96E000EEA22EF50A86E040EA66E4FDF6F
+:10077000A6B2FED70001602BEAD71200C40EA66E07
+:100780000001606B6651605D20E26051EA6A6A0FA9
+:10079000E96E000EEA22EFCF03F060C000F0016ABC
+:1007A000026A67510024F36E68510120F46E6951AA
+:1007B0000220F86EF4CFF7FFF3CFF6FF03C0F5FF8A
+:1007C0000C0025DF0001602BDDD7F86A1200400E17
+:1007D000E66E650EE66E000EE66E36EC05F0E5524E
+:1007E000E552E552000870E20001606B00016551BE
+:1007F000FF0A57E0FA0A50E0010A3BE0070A34E03A
+:10080000010A2DE0030A18E0070A16E0700A01E069
+:100810005AD003DF0001040E606F04010CBFFDD746
+:10082000400EE66E650EE66E000EE66EFCEC04F021
+:10083000E552E552E55248D0F8DE050E000160278A
+:1008400004010CBFFDD7400EE66E650EE66E000E8D
+:10085000E66EFCEC04F0E552E552E55235D00ADFD5
+:100860000001010E606F30D034DF0001010E606FB7
+:100870002BD056DF050E0001602704010CBFFDD709
+:10088000400EE66E650EE66E000EE66EFCEC04F0C1
+:10089000E552E552E55218D058DF0001010E606FB5
+:1008A00013D093EC05F00001636B646B00016307E8
+:1008B000000E645B00016351641103E0000000005E
+:1008C000F5D7FF0001D000D01200040110511F0B1A
+:1008D000010801E079D0145101E076D0060E115DD7
+:1008E0002EE11351230A28E0010A13E0030A01E074
+:1008F00024D00001020EB06F0001B90505E100012E
+:10090000840EB16F0C0EB26F090E0001B56FB66B9D
+:1009100014D00001020EB06F0001B90505E100011D
+:10092000810EB16F0D0EB26F0001B90504E11D0E0D
+:100930000001B56FB66B01D000D00001B88304018F
+:100940001051600BE842E842E842E842E842010800
+:1009500001E03AD011510B0A31E0080A21E0090AFE
+:1009600019E0080A09E00B0A05E0080A01E02CD0AA
+:100970002CD82AD02BD828D00001020EB06F00014D
+:10098000BB0EB16F000EB26F0001B8930001010EF3
+:10099000B56F1AD00001020EB06F13C4BBF014D0B3
+:1009A0000001020EB06F0001BC0EB16F000EB26FFD
+:1009B0000001B8930001010EB56F06D00001020ED0
+:1009C000B06F12C4BCF000D012001200120000017F
+:1009D000BD6B1E0E716E0401400E096F200E0A6F72
+:1009E000040E0B6F880E086F0401600E0E6F040E6C
+:1009F0000F6F400E0C6F1200D9CFE6FFE1CFD9FF89
+:100A0000E652FC0EDB50400805E2400EF36EFC0E91
+:100A1000F3CFDBFFDF6AFC0EDB50DF5C19E2DF5057
+:100A2000E76EFD0EDBCFE9FFFE0EDBCFEAFFE750FE
+:100A3000E926000EEA22EF50E66EDF50EA6A600F08
+:100A4000E96E040EEA22E552E750EF6EDF2AE3D7A3
+:100A5000FC0EDBCF0DF4400E04010C170C7D880E4C
+:100A60000C13E552E552E7CFD9FF1200D9CFE6FFCC
+:100A7000E1CFD9FF0001BD6B040108BF30D0FC0EEF
+:100A8000DBCF00F00951D880005403E2FC0E09C40A
+:100A9000DBFF0001BD6BFC0EDB50BD5D19E2BD51FB
+:100AA000EA6A200FE96E040EEA22EF50E66EBD51AD
+:100AB000E76EFD0EDBCFE9FFFE0EDBCFEAFFE7506E
+:100AC000E926000EEA22E552E750EF6EBD2BE3D790
+:100AD0000401400E096F0817087D880E08130001F5
+:100AE000BD5100D0E552E7CFD9FF12006DA60FD857
+:100AF00002D06DB613D80001B70508E16DBA06D073
+:100B0000686A696A69806988020EB76F12006D6A47
+:100B1000696A6D860001010EB76F12006D6A696A1D
+:100B20000001B76B12008EEF05F00001B75101E133
+:100B30003AD06850040B04E06950040B01E038D847
+:100B40006DB231D06850010B04E06950010B01E037
+:100B500050D86850100B04E06950100B01E024D805
+:100B60006850400B04E06950400B01E037D86850F2
+:100B7000200B04E06950200B01E032D86850020BD2
+:100B800004E06950020B01E032D8030E0001B75DAA
+:100B900001E209D06850080B06E06950080B03E039
+:100BA0009BEC01F068961200698468986D821200CF
+:100BB0006D926994689412000001B8A10ED0F8DF1C
+:100BC0006D840001080EBE6F070EBF6FBE07000EDA
+:100BD000BF5BBE51BF11FAE16D941200689C120018
+:100BE00070A003D0F9EC02F07090689A120068923D
+:100BF00012006A6A686A9F0E6B6E7B0E696E6E6A7F
+:100C00000F0EE66E710EE66E0F0EE66E14D8E5520C
+:100C1000E552E552160E706E68A602D06896FCD7B3
+:100C20006D98F9EC02F00001B8910001B96B000178
+:100C3000030EB76F1200D9CFE6FFE1CFD9FFFD0E4B
+:100C4000DBCFE9FFFE0EDBCFEAFFFC0EDB5004E05A
+:100C5000EE6AFC0EDB06F9D7E552E7CFD9FF1200AA
+:100C60001201000200000008D80433000100010254
+:100C70000302090229000101028032090400000276
+:100C800003000000092101000001221D0007058169
+:100C90000340000107050103400001090220000193
+:100CA000020480320904000002FF000000070581F1
+:100CB0000340000107050103400001040309043457
+:100CC000034D006900630072006F006300680069F3
+:100CD000007000200054006500630068006E006F23
+:100CE000006C006F0067007900200049006E00630F
+:100CF000002E0048035000490043006B0069007457
+:100D0000002000320020004D006900630072006F77
+:100D10000063006F006E00740072006F006C006C66
+:100D200000650072002000500072006F00670072C2
+:100D30000061006D006D00650072001603500049EF
+:100D400000430031003800460032003500350030E5
+:100D50000030035000490043006B0069007400201C
+:100D6000003200200043006F006E006600670075CF
+:100D70000072006100740069006F006E0020003294
+:100D8000000600FF0901A10119012940150026FFF5
+:100D900000750895408102190129409102C0720C2A
+:100DA0009B0CBB0CBF0CF30C3B0D510DCA082A0E5B
+:100DB000F66E000EF76E000EF86E00010900F55099
+:100DC000AA6F0900F550AB6F03E1AA6701D03DD0CF
+:100DD0000900F550A56F0900F550A66F0900F55000
+:100DE000A76F09000900F550E96E0900F550EA6E99
+:100DF000090009000900F550A86F0900F550A96F16
+:100E000009000900F6CFACF0F7CFADF0F8CFAEF0A7
+:100E1000A5C0F6FFA6C0F7FFA7C0F8FF0001A853C2
+:100E200002E1A95307E00900F550EE6EA807F8E2C9
+:100E3000A907F9D7ACC0F6FFADC0F7FFAEC0F8FF09
+:100E40000001AA07000EAB5BBFD71200D9CFE6FFA7
+:100E5000E1CFD9FF030EE126938A818AF19E580ED5
+:100E6000E66E6EEC07F0E55281AA0DD0FE0EF66E2E
+:100E70007F0EF76EF86A0800F550DF6E550EDF5CE6
+:100E800002E100EF10F018D822D8E7EC03F0D950B7
+:100E9000010FE96EDACFEAFFEE50ED1001E18B7041
+:100EA000010EDB06020E01E2DB06EED7D9CFE1FF31
+:100EB000E552E7CFD9FF1200140E6F6E0001B76B39
+:100EC0000001B86B0001B96B8B909490120076EC26
+:100ED00005F06FBE02D095EC05F01200FF0EE35056
+:100EE000076EEF0E01D0F30EE76EE72E75EF07F0F9
+:100EF0000C0E066EE76AE72E7BEF07F0062E7AEF00
+:100F000007F0072E73EF07F0120013EE00F023EE48
+:100F100000F0F86A059CD7EC06F026EC07F0FDD748
+:100F20001200FFFFFFFFFFFFFFFFFFFFFFFFFFFFBD
+:100F3000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC1
+:100F4000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB1
+:100F5000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA1
+:100F6000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF91
+:100F7000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF81
+:100F8000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF71
+:100F9000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF61
+:100FA000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF51
+:100FB000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF41
+:100FC000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF31
+:100FD000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF21
+:100FE000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF11
+:100FF000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF01
+:10100000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0
+:10101000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE0
+:10102000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD0
+:10103000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC0
+:10104000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB0
+:10105000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA0
+:10106000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF90
+:10107000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80
+:10108000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF70
+:10109000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF60
+:1010A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF50
+:1010B000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF40
+:1010C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF30
+:1010D000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF20
+:1010E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF10
+:1010F000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00
+:10110000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEF
+:10111000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDF
+:10112000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFCF
+:10113000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBF
+:10114000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAF
+:10115000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9F
+:10116000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8F
+:10117000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7F
+:10118000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6F
+:10119000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5F
+:1011A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4F
+:1011B000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3F
+:1011C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2F
+:1011D000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1F
+:1011E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0F
+:1011F000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+:10120000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEE
+:10121000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDE
+:10122000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFCE
+:10123000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBE
+:10124000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAE
+:10125000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9E
+:10126000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8E
+:10127000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7E
+:10128000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6E
+:10129000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5E
+:1012A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4E
+:1012B000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3E
+:1012C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2E
+:1012D000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1E
+:1012E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0E
+:1012F000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE
+:10130000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFED
+:10131000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDD
+:10132000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFCD
+:10133000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBD
+:10134000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAD
+:10135000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9D
+:10136000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8D
+:10137000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7D
+:10138000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6D
+:10139000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D
+:1013A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D
+:1013B000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3D
+:1013C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2D
+:1013D000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1D
+:1013E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0D
+:1013F000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD
+:10140000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEC
+:10141000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDC
+:10142000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFCC
+:10143000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBC
+:10144000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAC
+:10145000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9C
+:10146000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8C
+:10147000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7C
+:10148000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6C
+:10149000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5C
+:1014A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4C
+:1014B000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3C
+:1014C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2C
+:1014D000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1C
+:1014E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0C
+:1014F000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC
+:10150000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEB
+:10151000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDB
+:10152000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFCB
+:10153000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBB
+:10154000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAB
+:10155000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9B
+:10156000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8B
+:10157000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7B
+:10158000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6B
+:10159000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5B
+:1015A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4B
+:1015B000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3B
+:1015C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2B
+:1015D000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1B
+:1015E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0B
+:1015F000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB
+:10160000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEA
+:10161000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDA
+:10162000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFCA
+:10163000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBA
+:10164000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAA
+:10165000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9A
+:10166000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A
+:10167000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7A
+:10168000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6A
+:10169000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5A
+:1016A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4A
+:1016B000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3A
+:1016C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2A
+:1016D000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1A
+:1016E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0A
+:1016F000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA
+:10170000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE9
+:10171000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD9
+:10172000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC9
+:10173000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB9
+:10174000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA9
+:10175000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF99
+:10176000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF89
+:10177000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF79
+:10178000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF69
+:10179000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF59
+:1017A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF49
+:1017B000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF39
+:1017C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF29
+:1017D000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF19
+:1017E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF09
+:1017F000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9
+:10180000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE8
+:10181000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD8
+:10182000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC8
+:10183000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB8
+:10184000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA8
+:10185000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF98
+:10186000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF88
+:10187000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF78
+:10188000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF68
+:10189000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF58
+:1018A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF48
+:1018B000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF38
+:1018C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF28
+:1018D000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF18
+:1018E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF08
+:1018F000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8
+:10190000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE7
+:10191000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD7
+:10192000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7
+:10193000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB7
+:10194000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA7
+:10195000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF97
+:10196000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF87
+:10197000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF77
+:10198000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF67
+:10199000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF57
+:1019A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF47
+:1019B000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF37
+:1019C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF27
+:1019D000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF17
+:1019E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF07
+:1019F000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7
+:101A0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE6
+:101A1000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6
+:101A2000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC6
+:101A3000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB6
+:101A4000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA6
+:101A5000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF96
+:101A6000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF86
+:101A7000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF76
+:101A8000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF66
+:101A9000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF56
+:101AA000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF46
+:101AB000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF36
+:101AC000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF26
+:101AD000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF16
+:101AE000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF06
+:101AF000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6
+:101B0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE5
+:101B1000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD5
+:101B2000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC5
+:101B3000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB5
+:101B4000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA5
+:101B5000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF95
+:101B6000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF85
+:101B7000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF75
+:101B8000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF65
+:101B9000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF55
+:101BA000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF45
+:101BB000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF35
+:101BC000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF25
+:101BD000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF15
+:101BE000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF05
+:101BF000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5
+:101C0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE4
+:101C1000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD4
+:101C2000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC4
+:101C3000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB4
+:101C4000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA4
+:101C5000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF94
+:101C6000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF84
+:101C7000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF74
+:101C8000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF64
+:101C9000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF54
+:101CA000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF44
+:101CB000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF34
+:101CC000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF24
+:101CD000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF14
+:101CE000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF04
+:101CF000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4
+:101D0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE3
+:101D1000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD3
+:101D2000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC3
+:101D3000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB3
+:101D4000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA3
+:101D5000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF93
+:101D6000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF83
+:101D7000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF73
+:101D8000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF63
+:101D9000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF53
+:101DA000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF43
+:101DB000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF33
+:101DC000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF23
+:101DD000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF13
+:101DE000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF03
+:101DF000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3
+:101E0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE2
+:101E1000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD2
+:101E2000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC2
+:101E3000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB2
+:101E4000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA2
+:101E5000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF92
+:101E6000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF82
+:101E7000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF72
+:101E8000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF62
+:101E9000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF52
+:101EA000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF42
+:101EB000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF32
+:101EC000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF22
+:101ED000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF12
+:101EE000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF02
+:101EF000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2
+:101F0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE1
+:101F1000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD1
+:101F2000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC1
+:101F3000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB1
+:101F4000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA1
+:101F5000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF91
+:101F6000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF81
+:101F7000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF71
+:101F8000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF61
+:101F9000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF51
+:101FA000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF41
+:101FB000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF31
+:101FC000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF21
+:101FD000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF11
+:101FE000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF01
+:101FF000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1
+:1020000083EF3EF0120000009DEF3AF01200000056
+:1020100000000000000000009DEF3AF012000000F8
+:10202000FFFFFFFFFFFFFFFFFFFFD9CFE6FFE1CF7D
+:10203000D9FFE652030ED26EA194A08492809282C0
+:102040000D0EC16E030EC06E9284809489949286A8
+:102050008096899692888998899A929A8A96939678
+:102060008A889398938A818AF19E8A9493948B901C
+:1020700094908B9294928B949494949C8B8C020E5B
+:10208000DF6E0001030E016F0001090E026F0001F7
+:10209000040E036FF00EE66E55EC2AF0E5522308AD
+:1020A00028E11E0EDF5C25E2DF50FE0BE842F00F58
+:1020B000E66E55EC2AF0E552E66EDF50EA6A000F54
+:1020C000E96E000EEA22E552E750EF6EDF28EA6A79
+:1020D000000FE96E000EEA22EF6ADF50EA6A000F95
+:1020E000E96E000EEA22EF5001E103D0020EDF2676
+:1020F000D8D7020EDF240001006F3E6A0001E76BB3
+:102100000001010EE86F0201030EE06F0201E16BB6
+:102110000201010EE26FD9EC19F0BBEC17F0B3EC41
+:1021200017F08DEC17F00001400ED880E355010E3A
+:10213000E4550EE30001C00EE35D000EE45908E330
+:102140000001E651AF0804E3500E0001E65D09E22C
+:102150000001E36B010EE46F0001E56B0001800EEE
+:10216000E66F080ED56E040ECA6E4F0ECB6E0C0EC7
+:10217000BD6E1D0EBE6E0001400EE06F00013E0EF2
+:10218000E16F00013C0EE26F02017E0EFA6F020168
+:102190002D0EFB6F070EB46EB56AF28CF28E93ECC7
+:1021A0003BF0040EE66E55EC2AF0E552500828E1AB
+:1021B000050EE66E55EC2AF0E5524B0821E1060EBD
+:1021C000E66E55EC2AF0E55232081AE1070EE66E8B
+:1021D00055EC2AF0E5523D6E020E3E6E546AE66AF8
+:1021E000110EE66E01EC16F0E552E552400EE66E79
+:1021F00026EC17F0E5520201FA6F0201890E006F1A
+:10220000E552E552E7CFD9FF120004010CBFFDD71C
+:10221000400EE66E400EE66E020EE66E18EC3AF0E8
+:10222000E552E552E55280EC3DF01200D9CFE6FFD1
+:10223000E1CFD9FF020EE126DF6A010EDB6A81BA27
+:1022400002D00001E78D400EE66E000EE66E020E33
+:10225000E66E54EC3AF0E552E552E552000803E22E
+:10226000DE52010EDD6E3E0406E1010EDB5002E09F
+:1022700087EC2FF00ED2020E3E5C09E1010EDB501E
+:1022800004E0760E0201005D02E00DDA02D20001E8
+:10229000E8B383DA010EDB5001E1FBD1DF50EA6ADB
+:1022A000000FE96E020EEA22EF50546E5450420ABB
+:1022B00027E0340A05E02C0A01E025D0DF2AE5D129
+:1022C00031EC1DF0020E3E5C19E1080ED56E8A88D5
+:1022D0003E6AE668040EE66E33EC2AF0E552E552FB
+:1022E000E668050EE66E33EC2AF0E552E552E66844
+:1022F000060EE66E33EC2AF0E552E552DF2AC5D130
+:10230000F9EC1CF0C2D1A00E545C03E2400EDF6E6B
+:10231000BCD15450B90803E2400EDF6EB6D1A00E16
+:10232000545E549E5446080E5426F9505424D8B096
+:10233000FA2AF96E1AD03FD06BD06ED071D07AD015
+:1023400091D0B1D0B4D0BDD0C0D0C3D0C6D0C9D048
+:10235000CBD0CDD0D0D005D10DD115D11DD11FD12D
+:1023600027D128D12FD17AD190D1DF28EA6A000F66
+:10237000E96E020EEA22EF50E66E020EDF24EA6AF0
+:10238000000FE96E020EEA22EF50E66E01EC16F045
+:10239000E552E552030EDF24EA6A000FE96E020EF1
+:1023A000EA22EF50E66E26EC17F0E5520201FA6FD2
+:1023B000040EDF26D9D7DF28EA6A000FE96E020E85
+:1023C000EA22EFCFE0F0020EDF24EA6A000FE96EA6
+:1023D000020EEA22EF50E66E26EC17F0E552010FEE
+:1023E0000001E16F020E0001E15D0001E26F030EEA
+:1023F000DF24EA6A000FE96E020EEA22EF50E66E71
+:1024000026EC17F0E5520201FB6F040EDF26ACD775
+:1024100011EC1DF0DF2AA8D76EEC18F0DF2AA4D744
+:10242000DF2AD9CFE6FFDACFE6FF73EC1AF0E552E8
+:10243000E5529AD7DF2ADF28EA6A000FE96E020E1A
+:10244000EA22EF50E66EDF50EA6A000FE96E020EF4
+:10245000EA22EF50E66E88EC19F0E552E552020EE2
+:10246000DF2682D7DF2ADF50EA6A000FE96E020E0C
+:10247000EA22EF50E66EDF28406A000F3F6E020E40
+:1024800040223FC0E6FF40C0E6FF3CEC1DF0E552B5
+:10249000E552E552DF50EA6A000FE96E020EEA22C9
+:1024A000EF28DF2661D7BBEC17F0DF2A5DD7DF2AE4
+:1024B000D9CFE6FFDACFE6FFF4EC19F0E552E552AA
+:1024C00053D7B3EC17F0DF2A4FD7E7EC18F0DF2A29
+:1024D0004BD7D9EC19F0DF2A47D73AEC19F0DF2AAD
+:1024E00043D7400EDF6E40D7FF00DF2A3DD7C3EC55
+:1024F00017F0DF2A39D7DF28EA6A000FE96E020EEB
+:10250000EA22EF500001E36FE46B020EDF24EA6A77
+:10251000000FE96E020EEA22EFCF3FF0406A3FBEA5
+:1025200040683FC040F03F6A3F500001E327405001
+:102530000001E423030EDF24EA6A000FE96E020EB5
+:10254000EA22EFCFE5F0040EDF24EA6A000FE96E1D
+:10255000020EEA22EFCFE6F06AEC17F0050EDF2656
+:1025600003D7DF2AD9CFE6FFDACFE6FFC8DAE55294
+:10257000E552FAD6DF2AD9CFE6FFDACFE6FF3FDA17
+:10258000E552E552F1D6DF2AD9CFE6FFDACFE6FFF2
+:1025900099D9E552E552E8D6DF2AE0D9E5D6DF2A17
+:1025A000DFCFE6FF27EC2FF0E552040EDF26DCD666
+:1025B000DF2ADAD6DF2ADFCFE6FF38D9E552400E30
+:1025C000DF6ED2D6DF2ADF50DF2AEA6A000FE96E1B
+:1025D000020EEA22EF505F6EDF50DF2AEA6A000F38
+:1025E000E96E020EEA22EF50546EDF50DF2AEA6AEB
+:1025F000000FE96E020EEA22EF50566EDF50DF2A1E
+:10260000EA6A000FE96E020EEA22EF50586EDF50C0
+:10261000DF2AEA6A000FE96E020EEA22EF50596ED5
+:10262000DF50DF2AEA6A000FE96E020EEA22EF505D
+:102630005A6EDF50DF2AEA6A000FE96E020EEA22C4
+:10264000EF285B6EDF50DF2AEA6A000FE96E020EA8
+:10265000EA22EF505E6ECFEC2DF086D6DF2ADF281F
+:10266000EA6A000FE96E020EEA22EF50E66EDF50D2
+:10267000EA6A000FE96E020EEA22EF50E66E7ED99A
+:10268000E552E552020EDF266FD6400EDF5C01E216
+:1026900005D6020EE15C02E2E16AE552E16EE55226
+:1026A000E7CFD9FF1200F29A870ED56EF2A429D097
+:1026B000D20ED76E3A0ED66EF294542A54500508B4
+:1026C00001E2546A040E545C06E2010E5414E8B0B0
+:1026D0008A88E8A08A98300E0001E71512E08A88FF
+:1026E00081BAFED78F0E0001E717F00EE66E58ECA8
+:1026F0003EF0E55281AAFED7F00EE66E58EC3EF0B1
+:10270000E5520001E7AD47D08A882FEC31F08A8886
+:102710008A8681AAFED7546AE66A110EE66E71DADD
+:10272000E552E552400EE66E91DBE5520201FA6F8A
+:10273000300E0001E71502E081BAFED7FC0E000161
+:10274000E81506E0080EE66E6FEC36F0E55210D0A4
+:10275000390406E1040EE66E6FEC36F0E55208D05F
+:102760003650371005E0060EE66E6FEC36F0E55297
+:10277000F00EE66E58EC3EF0E55281AAFED7F00E60
+:10278000E66E58EC3EF0E5528F0E0001E7170001AF
+:10279000E86B0001E79D8B901200D9CFE6FFE1CFF7
+:1027A000D9FFE6523D501AE03D50DF6E3D6A3A5087
+:1027B000E66ECEEC27F0E552DF50010805E23B5013
+:1027C000E66ECEEC27F0E552DF50020805E23C5001
+:1027D000E66ECEEC27F0E5523D50E6E10201E55110
+:1027E000E61108E0A050020B05E103EC28F0396E79
+:1027F000A182A0828150100B14E1C250020B11E1A2
+:102800000201FA51C45C0AE20C0E0201FC5D03E114
+:102810008A948A8802D00201FC2B02D00201FC6B50
+:10282000C282E552E552E7CFD9FF1200D9CFE6FFC9
+:10283000E1CFD9FFFE0EDBCFE6FF45EC2FF0E552EE
+:1028400000093CE0020E3E6E546AE66A110EE66E26
+:10285000D8D9E552E552400EE66EF8DAE5520201AB
+:10286000FA6F500EE66E040EE66E33EC2AF0E55277
+:10287000E5524B0EE66E050EE66E33EC2AF0E5529D
+:10288000E552320EE66E060EE66E33EC2AF0E552A5
+:10289000E552FE0EDB50030FEA6A000FE96E020EEE
+:1028A000EA22EF503D6E3D50E66E070EE66E33ECC9
+:1028B0002AF0E552E5520201890E006FE552E7CF9A
+:1028C000D9FF1200D9CFE6FFE1CFD9FFF29EA8ECE5
+:1028D0003BF0050EC26EC282FD0EDBCFE9FFFE0E9D
+:1028E000DBCFEAFFEF50EF2AEA6A000FE96E020E33
+:1028F000EA22EF50346EFD0EDBCFE9FFFE0EDBCF98
+:10290000EAFFEF50EF2AEA6A000FE96E020EEA22B0
+:10291000EF50356E366A376A386A396A3A6A3D6A04
+:102920000001E88392968986928492888A94899A93
+:102930002E0EB46EA50EB56E0C0EE66E9FEC3EF03C
+:10294000E5529D90A092910ECD6E910EB16EA19C1C
+:10295000A08CF28EE552E7CFD9FF1200F29E000163
+:10296000E893A09C9D90A092CD6AB16A070EB46EC8
+:10297000B56A928693EC3BF0F28E1200D9CFE6FF57
+:10298000E1CFD9FF030EE126FD0EDB50416E426A16
+:1029900041C042F0416AFE0EDB50000141243F6E0F
+:1029A000000E4220406E010E3FC0DBFF020E40C011
+:1029B000DBFFDF6ADF503F6E406AD890405004E68C
+:1029C000800E3F5C000E405810E2010EDBCFE9FFA5
+:1029D000DB2A020EDBCFEAFF01E3DB2AEF50E66ED3
+:1029E000CEEC27F0E552DF2AE5D7030EE15C02E2E8
+:1029F000E16AE552E16EE552E7CFD9FF1200D9CF87
+:102A0000E6FFE1CFD9FF050EE126FD0EDBCFE9FFA2
+:102A1000FE0EDBCFEAFFEF50EF2AEA6A000FE96E05
+:102A2000020EEA22040EEFCFDBFFFD0EDBCFE9FF43
+:102A3000FE0EDBCFEAFFEF50EF2AEA6A000FE96EE5
+:102A4000020EEA22EF50E66ED950020FE96EDACF9D
+:102A5000EAFFE552E750EE6EED6AD950020FE96EDB
+:102A6000DACFEAFF200ED880EE54000EED5407E2D4
+:102A7000200EF36E020EF3CFDBFF030EDB6AD9509C
+:102A8000020FE96EDACFEAFFEE50ED1001E12DD032
+:102A9000DE6ADD6ADECF3FF0DDCF40F0020EDBCF35
+:102AA00041F0030EDBCF42F041503F5C42504058B2
+:102AB0001AE2040EDBCFF3FFDB2AF350E66E55EC8F
+:102AC0002AF0E552E66EDECFE9FFDDCFEAFF400EE9
+:102AD000E926020EEA22E552E750EF6EDF2A010EE8
+:102AE00001E3DB2AD7D705EC11F0050EE15C02E229
+:102AF000E16AE552E16EE552E7CFD9FF1200D9CF86
+:102B0000E6FFE1CFD9FF050EE126FD0EDBCFE9FFA1
+:102B1000FE0EDBCFEAFFEF50EF2AEA6A000FE96E04
+:102B2000020EEA22040EEFCFDBFFFD0EDBCFE9FF42
+:102B3000FE0EDBCFEAFFEF50EF2AEA6A000FE96EE4
+:102B4000020EEA22EF50E66ED950020FE96EDACF9C
+:102B5000EAFFE552E750EE6EED6AD950020FE96EDA
+:102B6000DACFEAFF200ED880EE54000EED5407E2D3
+:102B7000200EF36E020EF3CFDBFF030EDB6AD9509B
+:102B8000020FE96EDACFEAFFEE50ED1001E12FD02F
+:102B9000DE6ADD6ADECF3FF0DDCF40F0020EDBCF34
+:102BA00041F0030EDBCF42F041503F5C42504058B1
+:102BB0001EE2FD0EDBCFE9FFFE0EDBCFEAFFEF509A
+:102BC000EF2AEA6A000FE96E020EEA22EF50E66E83
+:102BD000040EDBCFF3FFDB2AF350E66E33EC2AF072
+:102BE000E552E552DF2A010E01E3DB2AD3D7050EB9
+:102BF000E15C02E2E16AE552E16EE552E7CFD9FF1E
+:102C00001200D9CFE6FFE1CFD9FF030EE126FE0E79
+:102C1000DB50426E436A42C043F0426AFD0EDB5015
+:102C2000000142243F6E000E4320406E416A40BEC8
+:102C300041683FC0DFFF010E40C0DBFF020E41C014
+:102C4000DBFFD9CFE9FFDACFEAFF060EE76ED890B7
+:102C5000020EEB32010EEB32EF32E706F8E1E5C08F
+:102C60003FF0406A416A3FAE02D040684168D9CF28
+:102C7000E9FFDACFEAFF3F50EE264050EE22415006
+:102C8000EE22E6C03FF0406A416AD9CFE9FFDACFD1
+:102C9000EAFF3FC02CF040C02DF041C02EF0EECF37
+:102CA00027F0EECF28F0EFCF29F0A5EC3CF026C0BE
+:102CB000EDFF25C0EDFF24C0EFFFD9CFE9FFDACF4C
+:102CC000EAFFD890020EEB32010EEB32EF32080E23
+:102CD000426ED9CFE9FFDACFEAFF42501F0BEECFA9
+:102CE0003FF0EECF40F0EECF41F006E0D890413219
+:102CF00040323F32E806FAE13F50BE6ED9CFE9FFDD
+:102D0000DACFEAFFEE52EE6AEE6ACF0EBD14426EE3
+:102D1000436A446A020E486ED9CFE9FFDACFEAFF70
+:102D200048501F0BEECF45F0EECF46F0EECF47F008
+:102D300006E0D890473246324532E806FAE1425082
+:102D400045103F6E43504610406E44504710416E50
+:102D50003F50BD6E030EE15C02E2E16AE552E16EB6
+:102D6000E552E7CFD9FF1200D9CFE6FFE1CFD9FF77
+:102D7000040EE126FD0EDBCF3FF0FE0EDBCF40F070
+:102D8000000E3FC0DBFF010E40C0DBFF020EDB6A1E
+:102D9000030EDB6AE3C03FF0E4C040F0416A426AE0
+:102DA000D9CFE9FFDACFEAFF3FC02BF040C02CF0CB
+:102DB00041C02DF042C02EF0EECF26F0EECF27F02E
+:102DC000EECF28F0EFCF29F020EC3EF025C0EDFF4C
+:102DD00024C0EDFF23C0EDFF22C0EFFFD9CFE9FFF4
+:102DE000DACFEAFF080EE76ED890030EEB32020E40
+:102DF000EB32010EEB32EF32E706F6E1D9CFE9FF15
+:102E0000DACFEAFFD880FF0EEE54FF0EEE54000E2C
+:102E1000EE54000EEE5406E2DE68DE68DE6ADD6A1D
+:102E2000DD52DD52DFCF3FF0010EDBCF40F03FC07F
+:102E3000F3FF40C0F4FF00D0040EE15C02E2E16A5F
+:102E4000E552E16EE552E7CFD9FF1200D9CFE6FF98
+:102E5000E1CFD9FF020EE126E3C03FF0E4C040F02D
+:102E6000000ED8803F56020E40563FC0DEFF40C0E5
+:102E7000DDFFFE0EDB503F6E406AD9CFE9FFDACFAF
+:102E8000EAFF3FC02DF040C02EF0EECF28F0EDCF8E
+:102E900029F087EC3CF026C0EEFF27C0EDFFD9CF2C
+:102EA000E9FFDACFEAFF080E0F0B06E0EC52D890EC
+:102EB000ED32EF32E806FAE1DF5000D03F6E020E4D
+:102EC000E15C02E2E16AE552E16E3F50E552E7CF94
+:102ED000D9FF1200E3C0E6FFE66A33EC2AF0E552C0
+:102EE000E552E4C03FF0406A3F50E66E010EE66EE8
+:102EF00033EC2AF0E552E552E5C0E6FF020EE66E3D
+:102F000033EC2AF0E552E552E6C0E6FF030EE66E2A
+:102F100033EC2AF0E552E5521200E66A55EC2AF04D
+:102F2000E5520001E36FE46B010EE66E55EC2AF00A
+:102F3000E5523F6E406A3FC040F03F6A3F5000019B
+:102F4000E32740500001E423020EE66E55EC2AF020
+:102F5000E5520001E56F030EE66E55EC2AF0E552EE
+:102F60000001E66F12000001E96B0001EA6B00014D
+:102F7000EB6BEC6B12000201E36B0201E46B0201EC
+:102F8000E56BE66B1200D9CFE6FFE1CFD9FF060E65
+:102F9000E126DE6ADD6A020EDB6A030EDB6A040EDE
+:102FA000DB6A050EDB6A040EDB6A050EDB6A040EC3
+:102FB000DBCF3FF0050EDBCF40F0D890405004E669
+:102FC000200E3F5C000E40581EE2040EDBCFE9FFEE
+:102FD000050EDBCFEAFF030EEA02F3CFEAFF030E92
+:102FE000E902F3CFE9FFF450EA26800EE926020E4B
+:102FF000EA22EF50DE26000EDD22040EDB2A050E4B
+:1030000001E3DB2AD4D7040EDB6A050EDB6A040E6B
+:10301000DBCF3FF0050EDBCF40F0DECF41F0DDCF60
+:1030200042F040504218E8AE02D0423404D0415041
+:103030003F5C425040581EE2040EDB500001F42574
+:103040000F01E96E050EDB500001F5210F01EA6E5C
+:10305000EF503F6E406AD950020FE96EDACFEAFFB7
+:103060003F50EE264050ED22040EDB2A050E01E310
+:10307000DB2ACDD7DECF3FF0DDCF40F03F5002015D
+:10308000406FDECF3FF0DDCF40F040C03FF0406A00
+:103090003FC041F2FF0EE76E020EDBCF3FF0030EA2
+:1030A000DBCF40F0E7503F16406A3FC042F2020ECD
+:1030B000DBCF3FF0030EDBCF40F040C03FF0406A73
+:1030C0003FC043F205EC11F0060EE15C02E2E16A5A
+:1030D000E552E16EE552E7CFD9FF1200D9CFE6FF06
+:1030E000E1CFD9FF020EE126A8EC3BF0040EE66E1C
+:1030F00060D8E552C450416E426A41C042F0416A14
+:10310000C350000141243F6E000E4220406E3FC07C
+:10311000DEFF40C0DDFFDECFE6FFDDCFE6FF24DED1
+:10312000E552E552F3CFDEFFF4CFDDFFDFCF40F213
+:10313000DECF3FF0DDCF40F040C03FF0406A3FC0FF
+:1031400041F2E66A36D8E552C450416E426A41C047
+:1031500042F0416AC350000141243F6E000E4220FC
+:10316000406E3FC0DEFF40C0DDFFDECFE6FFDDCFBB
+:10317000E6FFFADDE552E552F3CFDEFFF4CFDDFFE7
+:10318000DFCF42F2DECF3FF0DDCF40F040C03FF076
+:10319000406A3FC043F205EC11F093EC3BF0020EA5
+:1031A000E15C02E2E16AE552E16EE552E7CFD9FF68
+:1031B0001200D9CFE6FFE1CFD9FFFE0EDB28C26EA9
+:1031C000C282C2B2FED7E552E7CFD9FF1200D9CFF3
+:1031D000E6FFE1CFD9FF020EE126010EEBC0DBFFD7
+:1031E000010EDB503F0803E2DE523F0EDD6E010EA2
+:1031F000DBCF40F2010EDF6E010EDB50D880DF54D2
+:1032000023E30001EA51EA2BEA6A600FE96E000E3F
+:10321000EA22EF50E66EDF50EA6A400FE96E020ED6
+:10322000EA22E552E750EF6E0001EA513F6E406A34
+:10323000D890405004E6800E3F5C000E405802E3F8
+:103240000001EA6BDF2AD8D7010EDB503F6E406ADF
+:103250003F500001EB5F40500001EC5B05EC11F0CA
+:10326000020EE15C02E2E16AE552E16EE552E7CF6F
+:10327000D9FF1200D9CFE6FFE1CFD9FF020EE12638
+:10328000010EEBC0DBFF010EDB50400803E2DE5213
+:10329000400EDD6EDF6A010EDB50DF5C23E20001D1
+:1032A000EA51EA2BEA6A600FE96E000EEA22EF505B
+:1032B000E66EDF50EA6A400FE96E020EEA22E5523E
+:1032C000E750EF6E0001EA513F6E406AD8904050DF
+:1032D00004E6800E3F5C000E405802E30001EA6BFA
+:1032E000DF2AD9D7010EDB503F6E406A3F50000104
+:1032F000EB5F40500001EC5B05EC11F0020EE15C6D
+:1033000002E2E16AE552E16EE552E7CFD9FF120031
+:10331000D9CFE6FFE1CFD9FF200EF36EFE0EDBCF53
+:10332000F4FFF350F45C0DE2FE0EDB50030DF3CF1F
+:10333000E9FFF4CFEAFF800EE926020EEA22EF5001
+:1033400003E10001E88B31D0FE0EDB50030DF3CF1B
+:10335000E9FFF4CFEAFF800EE926020EEA22EF50E1
+:10336000E66EFE0EDB50030DF3CFE9FFF4CFEAFF6C
+:10337000800EE926020EEA22EE5200010001F4510D
+:10338000EE243F6E00010001F551EE20406E3FC07B
+:10339000E6FF40C0E6FF70DBE552E552E552FD0E68
+:1033A000DB06FD0EDB500008CFE3E552E7CFD9FF87
+:1033B0001200D9CFE6FFE1CFD9FFE652DF6A200E37
+:1033C000DF5C0DE2DF50030DF3CFE9FFF4CFEAFF3E
+:1033D000800EE926020EEA22EF6ADF2AF0D7E552D4
+:1033E000E552E7CFD9FF1200D9CFE6FFE1CFD9FFF1
+:1033F000040EE126FD0EDBCFE9FFFE0EDBCFEAFF78
+:10340000EF50EF2AEA6A000FE96E020EEA22EF504F
+:10341000E66ED950020FE96EDACFEAFFE552E750C7
+:10342000EE6EED6A020EDB500201E52500013F6EF3
+:10343000030EDB500201E6210001406E000ED88031
+:103440003F54010E405403E20001E88F42D0DE6A8F
+:10345000DD6ADECF3FF0DDCF40F0020EDBCF41F082
+:10346000030EDBCF42F041503F5C4250405831E206
+:10347000FD0EDBCFE9FFFE0EDBCFEAFFEF50EF2AB8
+:10348000EA6A000FE96E020EEA22EF50E66E0201D0
+:10349000E351E32BEA6A000FE96E010EEA22E552DE
+:1034A000E750EF6E0201E3513F6E406AD890405002
+:1034B00004E6000E3F5C010E405802E30201E36B9C
+:1034C0000201E52B000EE623DF2A010E01E3DB2AD1
+:1034D000C0D7040EE15C02E2E16AE552E16EE5521A
+:1034E000E7CFD9FF1200D9CFE6FFE1CFD9FF080E11
+:1034F000E126FD0EDBCFE9FFFE0EDBCFEAFFEF2872
+:10350000EA6A000FE96E020EEA22EFCF3FF0406A4E
+:103510003FBE4068040E3FC0DBFF050E40C0DBFF2E
+:10352000040EDBCF3FF0050EDBCF40F0403404E269
+:103530003F503D08000E405403E20001E88D4FD299
+:10354000FD0EDBCFE9FFFE0EDBCFEAFFEF50EA6AAC
+:10355000000FE96E020EEA22EFCF3FF0406A3FBE55
+:103560004068060E3FC0DBFF070E40C0DBFF020EC7
+:10357000DB6A030EDB6ADE6ADD6ADECF3FF0DDCF99
+:1035800040F0D890405004E6200E3F5C000E4058BA
+:1035900023E2DECFE9FFDDCFEAFF030EEA02F3CF3D
+:1035A000EAFF030EE902F3CFE9FFF450EA26800EAA
+:1035B000E926020EEA22EF503F6E406AD950020F10
+:1035C000E96EDACFEAFF3F50EE264050ED22DF2AC7
+:1035D000010E01E3DB2AD1D7060EDBCFE9FF070E90
+:1035E000DBCFEAFF030EEA02F3CFEAFF030EE902A4
+:1035F000F3CFE9FFF450EA26800EE926020EEA2214
+:10360000EF503F6E406AD950020FE96EDACFEAFF01
+:103610003F50EE5E4050ED5A040EDBCF3FF0050EFA
+:10362000DBCF40F0020EDBCF41F0030EDBCF42F0E8
+:10363000000ED8804156030E425642504018E8AE64
+:1036400002D0403404D03F50415C4050425803E225
+:103650000001E88DC4D1060EDBCF3FF0070EDBCFB3
+:1036600040F0403404E23F501F08000E405403E293
+:103670000001E88DB4D1060EDBCFE9FF070EDBCFEA
+:10368000EAFF030EEA02F3CFEAFF030EE902F3CFEB
+:10369000E9FFF450EA26800EE926020EEA22EF50F6
+:1036A00001E106D1060EDBCFE9FF070EDBCFEAFF13
+:1036B000030EEA02F3CFEAFF030EE902F3CFE9FFBC
+:1036C000F450EA26800EE926020EEA22EF503F6E01
+:1036D000406A000ED8803F56030E40563F06000E4B
+:1036E000405A040E3FC0DBFF050E40C0DBFF060E54
+:1036F000DBCFE9FF070EDBCFEAFF030EEA02F3CFD1
+:10370000EAFF030EE902F3CFE9FFF450EA26800E48
+:10371000E926020EEA22EE52EECFDEFFEDCFDDFF0C
+:10372000DECF3FF0DDCF40F0040EDBCF41F0050EE1
+:10373000DBCF42F040504218E8AE02D0423404D011
+:1037400041503F5C4250405835E2060EDBCFE9FF66
+:10375000070EDBCFEAFF030EEA02F3CFEAFF030E08
+:10376000E902F3CFE9FFF450EA26800EE926020EC3
+:10377000EA22EF500001406AF4253F6EF5514022E5
+:10378000DE503F24E96EDD504020EA6EEF50E66ED9
+:10379000DE500001F4250F01E96EDD500001F52136
+:1037A0000F01EA6EE552E750EF6EDF2A010E01E3EA
+:1037B000DB2AB6D7DE6ADD6ADECF3FF0DDCF40F030
+:1037C000D890405004E6200E3F5C000E405870E256
+:1037D000DECFE9FFDDCFEAFF030EEA02F3CFEAFF17
+:1037E000030EE902F3CFE9FFF450EA26800EE92642
+:1037F000020EEA22EECF3FF0EECF40F0EFCF41F0E5
+:10380000060EDBCFE9FF070EDBCFEAFF030EEA026D
+:10381000F3CFEAFF030EE902F3CFE9FFF450EA2603
+:10382000800EE926020EEA22EE52EECF42F0EFCFF2
+:1038300043F0000143504118E8AE02D0413404D0B7
+:103840004050425C415043582EE2060EDBCFE9FF68
+:10385000070EDBCFEAFF030EEA02F3CFEAFF030E07
+:10386000E902F3CFE9FFF450EA26800EE926020EC2
+:10387000EA22EF503F6E406ADECFE9FFDDCFEAFF7C
+:10388000030EEA02F3CFEAFF030EE902F3CFE9FFEA
+:10389000F450EA26800EE926020EEA22EE523F504C
+:1038A000EE5E4050ED5ADF2A010E01E3DB2A84D799
+:1038B000FD0EDBCFE9FFFE0EDBCFEAFFEF28EA6A61
+:1038C000000FE96E020EEA22EF50E66E060EDBCF25
+:1038D000E9FF070EDBCFEAFF030EEA02F3CFEAFFB0
+:1038E000030EE902F3CFE9FFF450EA26800EE92641
+:1038F000020EEA22E552E750EF6E060EDBCFE9FF3B
+:10390000070EDBCFEAFF030EEA02F3CFEAFF030E56
+:10391000E902F3CFE9FFF450EA26800EE926020E11
+:10392000EA22EE52020EDBCFEEFF030EDBCFEDFFFD
+:10393000020E3F6EFD0EDBCFE9FFFE0EDBCFEAFF8E
+:103940003F50EF26DE6ADD6ADECF3FF0DDCF40F08C
+:10395000060EDBCFE9FF070EDBCFEAFF030EEA021C
+:10396000F3CFEAFF030EE902F3CFE9FFF450EA26B2
+:10397000800EE926020EEA22EF50000140AE02D08E
+:10398000D89003D03F5C000E405829E2FD0EDBCFFB
+:10399000E9FFFE0EDBCFEAFFEF50EF2AEA6A000FE5
+:1039A000E96E020EEA22EF50E66E020EDB500001D5
+:1039B000F42500013F6E030EDB500001F5210001EC
+:1039C000406EDE503F24E96EDD504020EA6EE55245
+:1039D000E750EF6EDF2A010E01E3DB2AB5D7080EB0
+:1039E000E15C02E2E16AE552E16EE552E7CFD9FF20
+:1039F0001200F29E7BEC3DF0840EA66EFE0EF66E7B
+:103A00007F0EF76EF86AF56A0C00550EA76EAA0EC7
+:103A1000A76EA6824E0EE66E58EC3EF0E552FF0011
+:103A20001200F00E0001E71781A402D00001E78721
+:103A300080AA02D00001E78581B802D00001E783A7
+:103A400081A602D00001E781E7C040F2E8C041F260
+:103A50008F0E0001E7170001E86B8B9005EC11F069
+:103A600012000201020E406F0201200E416F02019E
+:103A7000426B05EC11F01200D9CFE6FFE1CFD9FF80
+:103A80000D0EE126DF6A0B0EDB6A0C0EDB6AF29A82
+:103A9000070ED56EFC0EDB5004E0FC0EDB503D083B
+:103AA00004E20001E88B84EF24F0FE0E0001E8152B
+:103AB00002E084EF24F0FC0EDB50DF5C02E384EFD5
+:103AC00024F0DF50E76EFD0EDBCFE9FFFE0EDBCF0B
+:103AD000EAFFE750E926000EEA22EF50546EB30EDB
+:103AE000545C04E2FC0EDB50DF6EDFD7D50E545C75
+:103AF00001E2CAD3D50E545E549E5446080E542695
+:103B0000F9505424D8B0FA2AF96EA5D39AD3DFD24B
+:103B100000D34FD31BD3D8D2D0D266D25DD248D2F5
+:103B20003FD2E6D118D2E0D1CBD192D15AD133D104
+:103B300045D1EED0DDD0C9D0B1D099D070D069D008
+:103B40005ED053D03CD026D023D020D01DD01AD068
+:103B500016D012D00FD00CD009D006D003D000D090
+:103B60008A9890D38A888ED38A868CD38A968AD371
+:103B70008A8488D38A9486D30C0EBA6E83D3BA6AA9
+:103B80008B9280D3898A7ED3899A7CD38B807AD397
+:103B90008B9078D3DF2ADF50E76EFD0EDBCFE9FF95
+:103BA000FE0EDBCFEAFFE750E926000EEA22EFCF58
+:103BB000E0F2E0C2E6FFA3EC28F0E55263D3DF2A8F
+:103BC000080EE66EDF50E76EFD0EDBCFE9FFFE0E5E
+:103BD000DBCFEAFFE750E926000EEA22EF50E66E5F
+:103BE00033EC28F0E552E5524DD3080EE66E03ECB7
+:103BF00028F0E66E33EC28F0E552E55243D3080E88
+:103C0000E66E85EC27F0E552E66ECEEC27F0E55245
+:103C100039D3080EE66E85EC27F0E55233D3DF2A60
+:103C2000DF50E76EFD0EDBCFE9FFFE0EDBCFEAFFD4
+:103C3000E750E926000EEA22EF50E66EDF50E76E0D
+:103C4000FD0EDBCFE9FFFE0EDBCFEAFFE750E926F2
+:103C5000000EEA22010EE926000EEA22EF50E66E7F
+:103C600033EC28F0E552E552020EDF260CD3DF2AB2
+:103C7000DF50E76EFD0EDBCFE9FFFE0EDBCFEAFF84
+:103C8000E750E926000EEA22EF50E66E03EC28F03A
+:103C9000E66E33EC28F0E552E552F4D2DF2ADF502D
+:103CA000E76EFD0EDBCFE9FFFE0EDBCFEAFFE7504C
+:103CB000E926000EEA22EF50E66E85EC27F0E55289
+:103CC000E66ECEEC27F0E552DDD2DF2ADF50E76E5C
+:103CD000FD0EDBCFE9FFFE0EDBCFEAFFE750E92662
+:103CE000000EEA22EF50E66E85EC27F0E552CAD2CC
+:103CF000DF2ADF50E76EFD0EDBCFE9FFFE0EDBCFE4
+:103D0000EAFFE750E926000EEA22EFCFE1F2BAD24D
+:103D10000B0EDB500EE0040EDB06040EDB5005E15B
+:103D20000B0EDB6A030EDF26AED2050EDB50DF6E14
+:103D3000AAD2010EF36E0B0EF3CFDBFFDF50E76E5E
+:103D4000FD0EDBCFE9FFFE0EDBCFEAFFE750E926F1
+:103D5000000EEA22010EE926000EEA22EF50DF5C97
+:103D6000E76E050EE7CFDBFFDF50E76EFD0EDBCF22
+:103D7000E9FFFE0EDBCFEAFFE750E926000EEA225C
+:103D8000020EE926000EEA22040EEFCFDBFF050E3D
+:103D9000DB50DF6E78D2DF2ADF50E76EFD0EDBCF1F
+:103DA000E9FFFE0EDBCFEAFFE750E926000EEA222C
+:103DB000EF50E66E1DEC27F0E55264D2DF2ADF50AB
+:103DC000E76EFD0EDBCFE9FFFE0EDBCFEAFFE7502B
+:103DD000E926000EEA22EF50E66EB3EC24F0E5523D
+:103DE00051D20001E905EA6A600FE96E000EEA228D
+:103DF000010EEFCFDBFFDF50E76EFD0EDBCFE9FFFB
+:103E0000FE0EDBCFEAFFE750E926000EEA22010EA4
+:103E1000E926000EEA22EF50F36E010EDB50F35C50
+:103E200014E1DF50E76EFD0EDBCFE9FFFE0EDBCFC6
+:103E3000EAFFE750E926000EEA22020EE926000E0C
+:103E4000EA22EF50DF24DF6E02D0030EDF261BD202
+:103E50000001E905EA6A600FE96E000EEA22010E30
+:103E6000EFCFDBFF010EDBCF3FF0DF50E76EFD0E43
+:103E7000DBCFE9FFFE0EDBCFEAFFE750E926000EBD
+:103E8000EA22010EE926000EEA22EF50D8803F54C4
+:103E900014E2DF50E76EFD0EDBCFE9FFFE0EDBCF55
+:103EA000EAFFE750E926000EEA22020EE926000E9C
+:103EB000EA22EF50DF24DF6E02D0030EDF26E3D1CB
+:103EC000DF50E76EFD0EDBCFE9FFFE0EDBCFEAFF32
+:103ED000E750E926000EEA22010EE926000EEA224A
+:103EE000EF50DF24DF6ECFD1FC0EDB50DF6ECBD185
+:103EF000DF2ADF50DF2AE76EFD0EDBCFE9FFFE0E83
+:103F0000DBCFEAFFE750E926000EEA22EF50406AD5
+:103F1000000F3F6E0F0E4022090E3FC0DBFF0A0E5E
+:103F200040C0DBFFDF50DF2AE76EFD0EDBCFE9FF8D
+:103F3000FE0EDBCFEAFFE750E926000EEA22EF5043
+:103F4000E66E090EDBCFE9FF0A0EDBCFEAFFE55292
+:103F5000E750EF6E98D1DF2ADF50E76EFD0EDBCF22
+:103F6000E9FFFE0EDBCFEAFFE750E926000EEA226A
+:103F7000EF50406A000F3F6E0F0E4022090E3FC007
+:103F8000DBFF0A0E40C0DBFF090EDBCFE9FF0A0EA4
+:103F9000DBCFEAFFEF50E66ECEEC27F0E55272D1B0
+:103FA000DF2A44EC25F0E66ECEEC27F0E5526BD12B
+:103FB000DF2ADF50DF2AE76EFD0EDBCFE9FFFE0EC2
+:103FC000DBCFEAFFE750E926000EEA22EF50E66E6B
+:103FD000C6EC24F0E55257D1DF2A03EC28F0E66E58
+:103FE000C6EC24F0E5524FD10C0EDB5016E0070E64
+:103FF000DB06080E01E2DB06D950070FE96EDACFC7
+:10400000EAFFEE50ED1005E10C0EDB6A020EDF2632
+:104010003AD1060EDB50DF6E36D1DF50E76EFD0E73
+:10402000DBCFE9FFFE0EDBCFEAFFE750E926000E0B
+:10403000EA22010EE926000EEA22EF50DF5CE76E6D
+:10404000060EE7CFDBFF03EC28F0E66ED950070F32
+:10405000E96EDACFEAFFE552E750EE6EED6A03EC67
+:1040600028F0416E426A286A010E296E41C02DF087
+:1040700042C02EF05AEC3CF026C03FF027C040F082
+:10408000D950070FE96EDACFEAFF3F50EE264050D5
+:10409000ED22D950070FE96EDACFEAFFEE50ED10AE
+:1040A00003E1020EDF26EFD0010EF36E0C0EF3CF0C
+:1040B000DBFF060EDB50DF6EE6D0C3EC28F0E66EC9
+:1040C000CEEC27F0E552DED003EC28F0DBD0040E76
+:1040D000E66E010EE66E33EC28F0E552E552080E6E
+:1040E000E66EE66A33EC28F0E552E552080EE66E1D
+:1040F0003CEC27F0E552E66ECEEC27F0E552080ED8
+:10410000E66E3CEC27F0E552E66ECEEC27F0E55289
+:10411000B9D0040EE66EE66A33EC28F0E552E552BB
+:10412000080EE66EE66A33EC28F0E552E552080E1A
+:10413000E66EE66A33EC28F0E552E552080EE66ECC
+:10414000E66A33EC28F0E552E5529CD0DF2A040EF3
+:10415000E66EE66A33EC28F0E552E552080EE66EAC
+:10416000DF50DF2AE76EFD0EDBCFE9FFFE0EDBCF6F
+:10417000EAFFE750E926000EEA22EF50E66E33EC44
+:1041800028F0E552E552080EE66EDF50DF2AE76EB2
+:10419000FD0EDBCFE9FFFE0EDBCFEAFFE750E9269D
+:1041A000000EEA22EF50E66E33EC28F0E552E552BD
+:1041B0006AD0DF2A040EE66EE66A33EC28F0E55298
+:1041C000E552080EE66EDF50DF2AE76EFD0EDBCF0C
+:1041D000E9FFFE0EDBCFEAFFE750E926000EEA22F8
+:1041E000EF50E66E33EC28F0E552E552080EE66E2D
+:1041F000DF50DF2AE76EFD0EDBCFE9FFFE0EDBCFDF
+:10420000EAFFE750E926000EEA22EF50E66E33ECB3
+:1042100028F0E552E552080EE66EDF50DF2AE76E21
+:10422000FD0EDBCFE9FFFE0EDBCFEAFFE750E9260C
+:10423000000EEA22EF50E66E33EC28F0E552E5522C
+:1042400022D0080EE66E3CEC27F0E552E66ECEEC8E
+:1042500027F0E55217D0DF2ADF50E76EFD0EDBCFE7
+:10426000E9FFFE0EDBCFEAFFE750E926000EEA2267
+:10427000EF50E66E3CEC27F0E552E66ECEEC27F010
+:10428000E55200D0DF2A11D4B30E545E549E54463A
+:10429000080E5426F9505424D8B0FA2AF96E6AD27E
+:1042A00070D227D3C6D216D3C7D273D250D23CD243
+:1042B00013D2D7D1ACD185D17ED16AD163D157D1B8
+:1042C0003FD135D12DD119D10ED104D1FCD0E8D0B8
+:1042D000E4D0E0D0D8D0C2D0AAD081D06ED001D066
+:1042E00035D0DF2A040EE66EE66A33EC28F0E5529C
+:1042F000E552040EE66EDF50E76EFD0EDBCFE9FF00
+:10430000FE0EDBCFEAFFE750E926000EEA22EF506F
+:10431000E66E33EC28F0E552E552080EE66E03EC4B
+:1043200028F0E66E33EC28F0E552E552080EE66E12
+:10433000E66A33EC28F0E552E552040EE66E020E12
+:10434000E66E33EC28F0E552E5529CD7DF2A040EE6
+:10435000E66EE66A33EC28F0E552E552040EE66EAE
+:10436000DF50E76EFD0EDBCFE9FFFE0EDBCFEAFF8D
+:10437000E750E926000EEA22EF50E66E33EC28F013
+:10438000E552E552080EE66E03EC28F0E66E33ECDB
+:1043900028F0E552E552080EE66E03EC28F0E66ED2
+:1043A00033EC28F0E552E552040EE66E020EE66E9E
+:1043B00033EC28F0E552E55265D7DF2ADF50E76E8F
+:1043C000FD0EDBCFE9FFFE0EDBCFEAFFE750E9266B
+:1043D000000EEA22EF50E66EA1DAE55253D7DF2A4B
+:1043E000DF50E76EFD0EDBCFE9FFFE0EDBCFEAFF0D
+:1043F000E750E926000EEA22EF50E66EDF50E76E46
+:10440000FD0EDBCFE9FFFE0EDBCFEAFFE750E9262A
+:10441000000EEA22010EE926000EEA22EF50E66EB7
+:104420006BEC28F0E552E552020EDF262CD7DF2A8E
+:10443000DF50E76EFD0EDBCFE9FFFE0EDBCFEAFFBC
+:10444000E750E926000EEA22EF50E66E03EC28F072
+:10445000E66E6BEC28F0E552E55214D7DF2ADF5008
+:10446000E76EFD0EDBCFE9FFFE0EDBCFEAFFE75084
+:10447000E926000EEA22EFCFE2F2E2C2E6FFD6EC36
+:1044800028F0E552FFD6EAEC28F0E66ECEEC27F0F5
+:10449000E552F8D6FBEC28F0F5D610EC29F0F2D670
+:1044A000DF2ADF50E76EFD0EDBCFE9FFFE0EDBCF2C
+:1044B000EAFFE750E926000EEA22EF50E66E25EC0F
+:1044C00029F0E552DFD603EC28F0E66E25EC29F062
+:1044D000E552D8D6E66A8EEC29F0E552E66ECEECCF
+:1044E00027F0E552CFD60F0EE66E8EEC29F0E5529E
+:1044F000E66ECEEC27F0E552C5D6DF2ADF50E76E38
+:10450000FD0EDBCFE9FFFE0EDBCFEAFFE750E92629
+:10451000000EEA22EF50E66EF5EC29F0E552B2D635
+:1045200003EC28F0E66EF5EC29F0E552ABD6E66A2E
+:10453000F5EC29F0E552E66ECEEC27F0E552A2D676
+:10454000DF2ADF50E76EFD0EDBCFE9FFFE0EDBCF8B
+:10455000EAFFE750E926000EEA22EF50E66EF5EC9E
+:1045600029F0E552E66ECEEC27F0E5528BD603EC4F
+:1045700028F0E66EF5EC29F0E552E66ECEEC27F079
+:10458000E55280D67ADBE66ECEEC27F0E5527AD69D
+:10459000DF2ADF50DF2AE76EFD0EDBCFE9FFFE0EDC
+:1045A000DBCFEAFFE750E926000EEA22EF50E66E85
+:1045B000DCDAE55268D603EC28F0E66ED6DAE5528E
+:1045C00061D6CEDB020EF3CFDBFF030EF4CFDBFFB1
+:1045D000FF0EE76E020EDBCF3FF0030EDBCF40F0A5
+:1045E000E7503F16406A3F50E66ECEEC27F0E552AA
+:1045F000020EDBCF3FF0030EDBCF40F040C03FF0B8
+:10460000406A3F50E66ECEEC27F0E5523BD6DF2AFB
+:10461000E66ADF50E76EFD0EDBCFE9FFFE0EDBCF73
+:10462000EAFFE750E926000EEA22010EE926000E15
+:10463000EA22EF50E66EDF50E76EFD0EDBCFE9FFBA
+:10464000FE0EDBCFEAFFE750E926000EEA22EF502C
+:10465000E66E64EC2AF0E552E552E552020EDF26E2
+:1046600012D6DF2ADF50E76EFD0EDBCFE9FFFE0E2C
+:10467000DBCFEAFFE750E926000EEA22020EE92628
+:10468000000EEA22EF50E66EDF50E76EFD0EDBCF44
+:10469000E9FFFE0EDBCFEAFFE750E926000EEA2233
+:1046A000010EE926000EEA22EF50E66EDF50E76EBB
+:1046B000FD0EDBCFE9FFFE0EDBCFEAFFE750E92678
+:1046C000000EEA22EF50E66E64EC2AF0E552E55265
+:1046D000E552030EDF26D7D5DF2ADF50E76EFD0E49
+:1046E000DBCFE9FFFE0EDBCFEAFFE750E926000E45
+:1046F000EA22010EE926000EEA22EF50E66EDF50B4
+:10470000E76EFD0EDBCFE9FFFE0EDBCFEAFFE750E1
+:10471000E926000EEA22EF50E66EB9EC2BF0E552E6
+:10472000E552020EDF26AFD5DF2ADF50E76EFD0E21
+:10473000DBCFE9FFFE0EDBCFEAFFE750E926000EF4
+:10474000EA22EF50E66EFDEC2BF0E5529BD5DF2A16
+:10475000DF50E76EFD0EDBCFE9FFFE0EDBCFEAFF99
+:10476000E750E926000EEA22EF50E66E1EEC2CF030
+:10477000E55288D5E66AE66A81EC2DF0E552E5520D
+:1047800081D5010EE66EE66A81EC2DF0E552E55228
+:1047900079D5DF2A010EE66EDF50E76EFD0EDBCF26
+:1047A000E9FFFE0EDBCFEAFFE750E926000EEA2222
+:1047B000EF50E66EDF50E76EFD0EDBCFE9FFFE0E39
+:1047C000DBCFEAFFE750E926000EEA22010EE926D8
+:1047D000000EEA22EF50E66EDF50E76EFD0EDBCFF3
+:1047E000E9FFFE0EDBCFEAFFE750E926000EEA22E2
+:1047F000020EE926000EEA22EF50E66EDF50E76E69
+:10480000FD0EDBCFE9FFFE0EDBCFEAFFE750E92626
+:10481000000EEA22030EE926000EEA22EF50E66EB1
+:104820004EEC2CF03F6E050EE15E3F50040EDF268D
+:104830002AD530EC2DF026D5DF2ADF50E76EFD0EAD
+:10484000DBCFE9FFFE0EDBCFEAFFE750E926000EE3
+:10485000EA22EF50E66EDF50E76EFD0EDBCFE9FF98
+:10486000FE0EDBCFEAFFE750E926000EEA22010E3A
+:10487000E926000EEA22EF50E66EDF50E76EFD0EED
+:10488000DBCFE9FFFE0EDBCFEAFFE750E926000EA3
+:10489000EA22020EE926000EEA22EF50E66EDF5011
+:1048A000E76EFD0EDBCFE9FFFE0EDBCFEAFFE75040
+:1048B000E926000EEA22030EE926000EEA22EF5056
+:1048C000E66EDFEC2CF0E552E552E552E552040EBF
+:1048D000DF26D9D498DBE66E96DBE66E94DBE66ED7
+:1048E00092DBE66EDFEC2CF0E552E552E552E55244
+:1048F000C9D4010EE66E010EE66E81EC2DF0E55294
+:10490000E552C0D455EF1DF00D0EE15C02E2E16A04
+:10491000E552E16EE552E7CFD9FF1200D9CFE6FFAD
+:10492000E1CFD9FF0201E351E32BEA6A000FE96E00
+:10493000010EEA22FE0EDBCFEFFF0201E3513F6ED4
+:10494000406AD890405004E6000E3F5C010E40588B
+:1049500002E30201E36B0201E52B000EE623E552C0
+:10496000E7CFD9FF1200D9CFE6FFE1CFD9FFF2940C
+:10497000FE0EDB50FF0DF350D76ED66AD58EF2A433
+:10498000FED7D59EE552E7CFD9FF1200D9CFE6FF7B
+:10499000E1CFD9FFF29ECD90A40ED76E730ED66EE6
+:1049A000F294D58E8050080B04E1F250040B01E123
+:1049B000F9D7F2B45DD089949294600EE66E91ECD2
+:1049C0003EF0E55289848050080B04E0F250040B5D
+:1049D00001E1F9D7F2B44CD0FE0EDB50546EF2B6C2
+:1049E00046D080A6FCD7899454BE898480B6FED771
+:1049F000F2B63DD080A6FCD7899454BC898480B699
+:104A0000FED7F2B634D080A6FCD7899454BA8984F4
+:104A100080B6FED7F2B62BD080A6FCD7899454B8C6
+:104A2000898480B6FED7F2B622D080A6FCD78994BE
+:104A300054B6898480B6FED7F2B619D080A6FCD7CA
+:104A4000899454B4898480B6FED7F2B610D080A67B
+:104A5000FCD7899454B2898480B6FED7F2B607D0C9
+:104A600080A6FCD7899454B0898480B6FED7000014
+:104A7000F2A402D00001E885D59EF28ECD8000D050
+:104A8000E552E7CFD9FF1200CD90F29EA40ED76E6B
+:104A9000730ED66EF294D58E8050080B04E1F2505E
+:104AA000040B01E1F9D7F2B454D089949294600ECA
+:104AB000E66E91EC3EF0E55289848050080B04E0EC
+:104AC000F250040B01E1F9D79284F2B442D0546A57
+:104AD000F2B63ED080A6FCD780B6FED780B4548E06
+:104AE000F2B636D080A6FCD780B6FED780B4548C00
+:104AF000F2B62ED080A6FCD780B6FED780B4548AFA
+:104B0000F2B626D080A6FCD780B6FED780B45488F3
+:104B1000F2B61ED080A6FCD780B6FED780B45486ED
+:104B2000F2B616D080A6FCD780B6FED780B45484E7
+:104B3000F2B60ED080A6FCD780B6FED780B45482E1
+:104B4000F2B606D080A6FCD780B6FED780B45480DB
+:104B5000000089849294F2A402D00001E885D59ED9
+:104B6000F28ECD80545000D01200D9CFE6FFE1CFB5
+:104B7000D9FFF29ECD90A40ED76E730ED66EF2942E
+:104B8000D58E92848050040B04E0F250040B01E1B6
+:104B9000F9D7F2B45FD092968986600EE66E91ECFA
+:104BA0003EF0E55289968050040B04E1F250040B6C
+:104BB00001E1F9D792869294F2B44CD0FE0EDB500C
+:104BC000546EF2B646D080A6FCD7899454BE898430
+:104BD00080B6FED7F2B63DD080A6FCD7899454BCEF
+:104BE000898480B6FED7F2B634D080A6FCD78994EB
+:104BF00054BA898480B6FED7F2B62BD080A6FCD7F3
+:104C0000899454B8898480B6FED7F2B622D080A6A3
+:104C1000FCD7899454B6898480B6FED7F2B619D0F1
+:104C200080A6FCD7899454B4898480B6FED7F2B6A6
+:104C300010D080A6FCD7899454B2898480B6FED760
+:104C4000F2B607D080A6FCD7899454B0898480B688
+:104C5000FED70000F2A402D00001E885600EE66EE7
+:104C600091EC3EF0E552D59EF28ECD8092849296E4
+:104C700000D0E552E7CFD9FF1200CD90F29EA40EEE
+:104C8000D76E730ED66EF294D58E92848050040B3C
+:104C900004E0F250040B01E1F9D7F2B455D092963A
+:104CA0008986600EE66E91EC3EF0E5528996805062
+:104CB000040B04E1F250040B01E1F9D792849286CF
+:104CC000F2B442D0546AF2B63ED080A6FCD780B689
+:104CD000FED780B4548EF2B636D080A6FCD780B60C
+:104CE000FED780B4548CF2B62ED080A6FCD780B606
+:104CF000FED780B4548AF2B626D080A6FCD780B600
+:104D0000FED780B45488F2B61ED080A6FCD780B6F9
+:104D1000FED780B45486F2B616D080A6FCD780B6F3
+:104D2000FED780B45484F2B60ED080A6FCD780B6ED
+:104D3000FED780B45482F2B606D080A6FCD780B6E7
+:104D4000FED780B454800000F2A402D00001E885B0
+:104D5000D59E92849296F28ECD80545000D012004F
+:104D6000D9CFE6FFE1CFD9FF030EE126DF6AF29447
+:104D7000800ED76ED66AD58EF2AE02D0010EDF6EEF
+:104D8000F29E80A40AD0F2A407D0D59EDF0401E1F0
+:104D9000F28EF36AF46A47D0F4D780B40AD0F2A452
+:104DA00007D0D59EDF0401E1F28EF36AF46A3BD0AE
+:104DB000F4D7800ED76ED66AF29480A40AD0F2A4FB
+:104DC00007D0D59EDF0401E1F28EF368F4682BD0A2
+:104DD000F4D7D59EDF0401E1F28ED650E66ED950AD
+:104DE000010FE96EDACFEAFFE552E750EE6EED6AA9
+:104DF0007F0ED7143F6E406A3FC040F03F6AD950E3
+:104E0000010FE96EDACFEAFF3F50EE264050ED2267
+:104E1000010EDBCF3FF0020EDBCF40F03FC0F3FFCF
+:104E200040C0F4FF00D0030EE15C02E2E16AE5520B
+:104E3000E16EE552E7CFD9FF1200D9CFE6FFE1CF0F
+:104E4000D9FFF294D768080EE66E9FEC3EF0E5526B
+:104E5000FE0EDB0402E10CD002D0FE0EDB06FE0EDD
+:104E6000DB50FF0DF350D66ED58EF2A4FED7D59E43
+:104E7000E552E7CFD9FF1200D9CFE6FFE1CFD9FF46
+:104E8000E6529284546AFE0EDB50556E020E020109
+:104E9000E15D0CE280B454808986000000000000CF
+:104EA000899600005442552EF5D718D00201E1052D
+:104EB000566E565080B45480898600000000000071
+:104EC00000000000E82EFBD7899656500000000035
+:104ED0000000E82EFBD75442552EEBD7FE0EDBCF59
+:104EE000E6FF080EE552D880E754070B04E0544271
+:104EF000549EE806FCE10201E0A39294545000D0D5
+:104F0000E552E552E7CFD9FF1200D9CFE6FFE1CF56
+:104F1000D9FFE6529284546AFE0EDB50556E020EA3
+:104F20000201E15D0CE2898600000000000080B40F
+:104F30005480899600005442552EF5D718D00201AE
+:104F4000E105566E89860000000056500000000002
+:104F50000000E82EFBD780B454808996565000009C
+:104F600000000000E82EFBD75442552EEBD7FE0E72
+:104F7000DBCFE6FF080EE552D880E754070B04E0CC
+:104F80005442549EE806FCE10201E0A3929454507E
+:104F900000D0E552E552E7CFD9FF1200D9CFE6FFA6
+:104FA000E1CFD9FF010E0001406AEB253F6EEC51C5
+:104FB0004022800ED8803F54000E405403E200018E
+:104FC000E8871DD00001E951E92BEA6A600FE96E1C
+:104FD000000EEA22FE0EDBCFEFFF0001E9513F6E2B
+:104FE000406AD890405004E6800E3F5C000E405866
+:104FF00002E30001E96B0001EB2B000EEC23E5520C
+:10500000E7CFD9FF1200D9CFE6FFE1CFD9FFE652B3
+:105010000201E551E61104E10001E889000E1ED00D
+:105020000201E451E42BEA6A000FE96E010EEA2264
+:10503000EFCFDFFF0201E507000EE65B0201E4515E
+:105040003F6E406AD890405004E6000E3F5C010E6F
+:10505000405802E30201E46BDF5000D0E552E55214
+:10506000E7CFD9FF1200D9CFE6FFE1CFD9FFE65253
+:10507000FE0EDB50546EFD0EDB50556E020E02012B
+:10508000E15D0CE254A0899454B0898400008986C3
+:10509000000089965442552EF5D718D00201E1053B
+:1050A000566E54A0899454B0898456500000000074
+:1050B0000000E82EFBD78986565000000000000053
+:1050C000E82EFBD789965442552EEBD7E552E55290
+:1050D000E7CFD9FF1200D9CFE6FFE1CFD9FFE652E3
+:1050E000FE0EDB50546EFD0EDB50556E020E0201BB
+:1050F000E15D0CE254A0899454B089848986000053
+:10510000899600005442552EF5D718D00201E105CA
+:10511000566E54A0899454B08984565089860000F4
+:1051200000000000E82EFBD78996565000000000D2
+:105130000000E82EFBD75442552EEBD7E552E5523E
+:10514000E7CFD9FF1200D9CFE6FFE1CFD9FFFE0E9E
+:10515000DBA402D0898601D08996FE0EDBA602D0A0
+:10516000898401D08994FE0EDBA002D0928601D002
+:105170009296FE0EDBA202D0928401D09294E55268
+:10518000E7CFD9FF1200D9CFE6FFE1CFD9FFE65232
+:10519000DF6A80B4DF8280A602D0000EDB80DF50A1
+:1051A00000D0E552E552E7CFD9FF1200D9CFE6FF94
+:1051B000E1CFD9FFFE0EDBA202D0898801D0899809
+:1051C000FE0EDBA002D0928801D09298E552E7CF84
+:1051D000D9FF1200D9CFE6FFE1CFD9FFE652DF6A4F
+:1051E00080A802D0000EDB80DF5000D0E552E552EF
+:1051F000E7CFD9FF12008986060EE66E9FEC3EF0DF
+:10520000E55289989298060EE66E9FEC3EF0E552C4
+:105210008996060EE66E9FEC3EF0E55292881200EB
+:105220008996060EE66E9FEC3EF0E55289989298BC
+:10523000060EE66E9FEC3EF0E5528986060EE66E9F
+:105240009FEC3EF0E55292881200D9CFE6FFE1CF05
+:10525000D9FFFE0EDB50546E080E556E8998020E73
+:105260000201E15D23E254AE929854BE928800D0D0
+:1052700000D000D08986000000D000D000D000D03F
+:105280008996000000D000D05446552EECD7928865
+:1052900000D000D000D000D000D08986000000D01F
+:1052A00000D000D080B8558089962FD00201E151FE
+:1052B000E824FF0F566E54AE929854BE9288565012
+:1052C000000000D000D000D0E82EFAD789865650D2
+:1052D00000D000D000D0E82EFDD7899600005446BB
+:1052E000552EE9D79288565000D000D0000000D04B
+:1052F00000D000D0E82EFAD78986565000D000D0D2
+:10530000E82EFDD780B8558089965550000802E2F6
+:105310000001E885E552E7CFD9FF1200D9CFE6FFBB
+:10532000E1CFD9FF546A080E556E010E566E928871
+:10533000020E0201E15D14E2544600D000D000D01C
+:1053400000D00000898600D000D000D0000080B8D6
+:105350005480899600D000D000D0552EEDD725D0AE
+:105360000201E151E824FF0F566E5446000000D0C0
+:10537000565000D000D000D00000E82EFAD7898621
+:10538000565000D000D0E82EFDD780B854808996C2
+:1053900000D0552EEAD70000565000D000D000D0E3
+:1053A00000D000D00000E82EFAD78998FE0EDB501E
+:1053B00001E19298565000D000D000D000D000D02B
+:1053C0000000E82EFAD78986565000D000D0E82E8B
+:1053D000FDD700D0899600D000000000928854507C
+:1053E00000D0E552E7CFD9FF1200D9CFE6FFE1CFD9
+:1053F000D9FFE652FE0EDB50546E080E556E020EBB
+:105400000201E15D0DE254AE899854BE8988898617
+:105410005446549080B454808996552EF4D71BD0AE
+:105420000201E105566E54AE899854BE89885650E3
+:10543000000000000000E82EFBD7898654465490F7
+:1054400080B454805650000000000000E82EFBD7C6
+:105450008996552EE8D78998545000D0E552E552E8
+:10546000E7CFD9FF1200D9CFE6FFE1CFD9FFE6524F
+:10547000DF6AFE0EDB50A96EFD0EDB50A86EA66A39
+:10548000A684F2AE02D0010EDF6EF29E550EA76E1C
+:10549000AA0EA76EA682DF0401E1F28EA6B2FED7A5
+:1054A000E552E552E7CFD9FF1200D9CFE6FFE1CFB1
+:1054B000D9FFFE0EDB50A96EA66AA680A85000D0C8
+:1054C000E552E7CFD9FF1200D9CFE6FFE1CFD9FFF0
+:1054D000040EE126DF6A010EDB6A0201E1510108D8
+:1054E00008E2120E566E0F0EF36E030EF3CFDBFFC3
+:1054F00007D0C60E566E030EF36E030EF3CFDBFF1E
+:1055000089889298180EE66E9FEC3EF0E552020EE6
+:105510003F6EFD0EDBCFE7FF3F50E726FD0EE7CFE6
+:10552000DBFF480ED56E550E546E8998D66AF294FC
+:10553000D58EF2AE02D0010EDF6EF29EFD0EDB06BE
+:10554000020EDB6A020EDBCF3FF0080EE76E3F185B
+:10555000E8AE02D0E73402D0E7503F5C21E2895048
+:10556000EF0B54AE1009F2A4FED7896E5650D62622
+:105570009298F294549E54468950556EFD0EDB501D
+:1055800005E1FC0EDB5002E1558801D05598F2A4EC
+:10559000FED789785650D626F294020EDB2AD2D74F
+:1055A0005550F2A4FED7896E5650D626F294010EBD
+:1055B000DB5007E0FD0EDB50000803E224DD546EF3
+:1055C00003D0FE0EDB50546EF2A4FED789785650FD
+:1055D000D626F294F2A4FED792885650D626F2949C
+:1055E000030EDBCFE6FF9FEC3EF0E552010EDB50F1
+:1055F00009E08050100B06E00001E885FD0EDB6A33
+:10560000FC0EDB6AF2A4FED700005650D626F294B8
+:10561000030EDBCFE6FF9FEC3EF0E552010EDB50C0
+:1056200009E08050100B06E10001E885FD0EDB6A01
+:10563000FC0EDB6ADE52010EDD6EFD0EDB50000853
+:1056400001E27CD7FC0EDBCFF3FFDB06F350000852
+:1056500001E37FD0546A020EDB6A020EDBCF3FF01B
+:10566000080EE76E3F18E8AE02D0E73402D0E750EC
+:105670003F5C30E2F2A4FED70000D66AF294895073
+:10568000556EFC0EDB5002E1558801D05598030E93
+:10569000DB04E66E9FEC3EF0E55280B807D0F2B432
+:1056A00002D080A8FCD75650D66E06D0F2B402D0F5
+:1056B00080B8FCD75650D66EF294030EDBCFE6FFCF
+:1056C0009FEC3EF0E552549E544680B8542A020E98
+:1056D000DB2AC3D75550F2A4FED7896E5650D62682
+:1056E0009298F2945450E66E59DCE552F2A4FED73B
+:1056F00089785650D626F294F2A4FED79288565056
+:10570000D626F294030EDBCFE6FF9FEC3EF0E55287
+:10571000010EDB5007E08050100B04E00001E8852B
+:10572000FC0EDB6AF2A4FED700005650D626F29497
+:10573000030EDBCFE6FF9FEC3EF0E552010EDB509F
+:1057400007E08050100B04E10001E885FC0EDB6AE5
+:1057500079D7DF0401E1F28E070ED56E9288040E30
+:10576000E15C02E2E16AE552E16EE552E7CFD9FF82
+:105770001200D9CFE6FFE1CFD9FFE652FE0EDB5093
+:1057800001E10FD0546AFD0EDB50556EDF6AFE0E4C
+:10579000DB50DF5C06E247EC38F055905542DF2ADB
+:1057A000F6D7E552E552E7CFD9FF1200D9CFE6FF91
+:1057B000E1CFD9FFE652FE0EDB5002E1000E18D019
+:1057C000FD0EDB50546EFC0EDB50556E566ADF6AE0
+:1057D000FE0EDB50DF5C0AE25690564247EC38F092
+:1057E0005490544255905542DF2AF2D7565000D07B
+:1057F000E552E552E7CFD9FF1200D9CFE6FFE1CF5E
+:10580000D9FF030EE66E040EE66EB3DFE552E552F5
+:10581000100EE66EFE0EDBCFE6FF050EE66EC6DF6F
+:10582000E552E552E552010EE66E020EE66EA1DF8C
+:10583000E552E552E552E7CFD9FF1200D9CFE6FF96
+:10584000E1CFD9FFE652DF6A010EE66E030EE66E87
+:1058500090DFE552E55256AE02D0010EDF6E800EAB
+:10586000E66EFE0EDBCFE6FF080EE66E9FDFE5522A
+:10587000E552E5525650E824DF12DFCFE6FFCEECCA
+:1058800027F0E552010EE66E020EE66E72DFE5527B
+:10589000E552E552E552E7CFD9FF1200D9CFE6FF36
+:1058A000E1CFD9FF020EE126DF6A010EDB6A010EAD
+:1058B000E66E030EE66E5DDFE552E55256AE02D0AF
+:1058C000010EDF6EE66AFB0EDBCFE6FF080EE66E2A
+:1058D0006DDFE552E552E5525650E824DF12FA0E2C
+:1058E000DB5005E0DFCFE6FFCEEC27F0E552DF6AC4
+:1058F00056AE02D0010EDF6EE66AFC0EDBCFE6FF8D
+:10590000080EE66E53DFE552E552E5525650E824A4
+:10591000DF12FA0EDB5005E0DFCFE6FFCEEC27F01A
+:10592000E552DF6A56AE02D0010EDF6EE66AFD0E6A
+:10593000DBCFE6FF080EE66E39DFE552E552E552B1
+:105940005650E824DF12FA0EDB5005E0DFCFE6FF09
+:10595000CEEC27F0E552010EDFCFDBFFDF6A56AE5B
+:1059600002D0010EDF6E800EE66EFE0EDBCFE6FF8C
+:10597000080EE66E1BDFE552E552E5525650E8246C
+:10598000DF12FA0EDB5005E0DFCFE6FFCEEC27F0AA
+:10599000E552010EE66E020EE66EEBDEE552E552D2
+:1059A000010EDB5000D03F6E020EE15C02E2E16AC4
+:1059B000E552E16E3F50E552E7CFD9FF1200D9CF53
+:1059C000E6FFE1CFD9FF010EE66E030EE66ED1DEF3
+:1059D000E552E55256BE0AD01F0EE66E050EE66E83
+:1059E000C8DEE552E5520001E88536D0E66A010ED0
+:1059F000E66EBFDEE552E552E66AFB0EDBCFE6FF60
+:105A0000080EE66ED3DEE552E552E552E66AFC0E7C
+:105A1000DBCFE6FF080EE66EC9DEE552E552E55241
+:105A2000E66AFD0EDBCFE6FF080EE66EBFDEE5524E
+:105A3000E552E552800EE66EFE0EDBCFE6FF080E65
+:105A4000E66EB4DEE552E552E552010EE66E020E58
+:105A5000E66E8FDEE552E552E552E7CFD9FF120040
+:105A6000D9CFE6FFE1CFD9FFE652D76AD66AF294E2
+:105A7000D58E0A0EE66EC1DEE552E66AE66AD00E03
+:105A8000E66E040EE66EE66A09DF3F6E050EE15E25
+:105A90003F50DF6E040EDF1403E1F250040BEDE023
+:105AA000F2A404D00001E885D59E26D0090EE66E4A
+:105AB000A4DEE552E66A03EC28F0E66E03EC28F07B
+:105AC000E66E03EC28F0E66E03EC28F0E66EE6DE08
+:105AD0003F6E050EE15E3F500A0EE66E8EDEE55229
+:105AE000E66AE66AC00EE66EE66AE66AD7DE3F6EF2
+:105AF000050EE15E3F50D59EE552E552E7CFD9FF56
+:105B00001200D9CFE6FFE1CFD9FFE652D76AD66AB5
+:105B1000F294D58E0A0EE66E70DEE552E66AE66A0B
+:105B2000D00EE66E040EE66EE66AB8DE3F6E050E37
+:105B3000E15E3F50DF6E040EDF1403E1F250040B10
+:105B4000EDE0F2A404D00001E885D59E23D0090E33
+:105B5000E66E53DEE552FE0EDBCFE6FFE66AE66A4E
+:105B6000E66AE66A9BDE3F6E050EE15E3F50FD0E83
+:105B7000DB500FE00A0EE66E40DEE552E66AE66AAA
+:105B8000C00EE66EE66AE66A89DE3F6E050EE15EED
+:105B90003F50D59EE552E552E7CFD9FF1200D9CF4D
+:105BA000E6FFE1CFD9FF020EE126F29EA8EC3BF022
+:105BB000928492869288D9EC19F08B80E950DF6E3E
+:105BC000010EEACFDBFF5F5002E05F6A02D058505F
+:105BD0005F6E5DEC38F05E50000803E2E5EC38F0F3
+:105BE00007D05F5003E0AAEC38F002D06FEC38F039
+:105BF000DF50E96E010EDB50EA6E8B9093EC3BF0C8
+:105C0000F28E54C040F255C041F205EC11F0020E84
+:105C1000E15C02E2E16AE552E16EE552E7CFD9FFCD
+:105C200012000100567D0000F40000000200000098
+:105C3000D9CFE6FFE1CFD9FFE6520401B06B0401F2
+:105C4000B16BB26B396AC56AC76A280EC66E1F0E81
+:105C5000C86EC584C5B4FED7E552E552E7CFD9FF7B
+:105C60001200D9CFE6FFE1CFD9FFE6528B9C67D86F
+:105C70000401B06B9E960401B051B02BEA6AC00FCC
+:105C8000E96E040EEA22EF50C96E9EA6FED7C5BC8F
+:105C9000C584400E0401B05DEDE3C584C5B4FED7F4
+:105CA000060EE66E58EC3EF0E5520401B06B0401BE
+:105CB000B12B000EB2238B8CE552E552E7CFD9FF12
+:105CC0001200D9CFE6FFE1CFD9FFE65238D801095B
+:105CD000DF6EC582C5B2FED79E96DF50C96E9EA606
+:105CE000FED7C5BCC5840401B06B9E96C5869EA632
+:105CF000FED70401B051B02BEA6AC00FE96E040E62
+:105D0000EA22C9CFEFFF400E0401B05D02E1C58A6F
+:105D100001D0C59AC588C5B8FED7400E0401B05D54
+:105D2000E4E3C584C5B4FED70401B06B0401B12B14
+:105D3000000EB223E552E552E7CFD9FF1200D9CFCA
+:105D4000E6FFE1CFD9FF020EE126DE52A00EDD6EA6
+:105D50003D5007E10401B251040B02E0010EDB8269
+:105D60000CD00401B251080B02E0010EDB820401E9
+:105D7000B251040B02E0010EDB86C580C5B0FED730
+:105D80009E96010EDB50C96EB1C43FF0B2C440F024
+:105D9000D89040323F32D89040323F323F50DF6E91
+:105DA0009EA6FED7C5BCC5849E96DF50C96EB1C401
+:105DB0003FF0B2C440F0060ED8903F364036E804BB
+:105DC000FBE13F50DF6E9EA6FED7C5BCC5849E9604
+:105DD000DF50C96E9EA6FED7C5BCC584010EDB5040
+:105DE00000D03F6E020EE15C02E2E16AE552E16E34
+:105DF0003F50E552E7CFD9FF1200D9CFE6FFE1CF00
+:105E0000D9FF0401B051B02BEA6AC00FE96E040E4D
+:105E1000EA22FE0EDBCFEFFF0401B0513F0801E2A2
+:105E200020DFE552E7CFD9FF12000401B0513F084F
+:105E300003E247DF0401B06B0401B051B02BEA6A02
+:105E4000C00FE96E040EEA22EF5000D01200D9CF45
+:105E5000E6FFE1CFD9FF3E6AFE0EDBCFE6FF15D8A5
+:105E6000E55200090EE0FE0EDB50030FEA6A000F58
+:105E7000E96E020EEA22EF503D6E010E3E6ED8DE54
+:105E80008B80E552E7CFD9FF1200D9CFE6FFE1CFF3
+:105E9000D9FFFE0EDBCFF3FFDB2AF350EA6A000FD7
+:105EA000E96E020EEA22EF50500802E0000E20D008
+:105EB000FE0EDBCFF3FFDB2AF350EA6A000FE96E38
+:105EC000020EEA22EF504B0802E0000E11D0FE0E47
+:105ED000DBCFF3FFDB2AF350EA6A000FE96E020E14
+:105EE000EA22EF50320802E0000E02D0010E00D08C
+:105EF000E552E7CFD9FF1200AD0EE66E7EDFE55228
+:105F00000401B0510008F8E33E6A8B901200D9CF2B
+:105F1000E6FFE1CFD9FF020EE126DF6A010EDB6A60
+:105F2000DF50EA6A000FE96E020EEA22EF50840A9F
+:105F300001E14ED1210A01E129D1270A01E126D14F
+:105F4000010A01E123D1040A01E120D1070A01E19C
+:105F50001DD1010A01E11AD1230A01E115D1010A7B
+:105F600001E112D10D0A01E10FD1010A01E10CD1C9
+:105F7000080A01E1FDD00E0A01E1FAD0030A01E1AD
+:105F8000F7D0010A01E1F4D0070A01E1F1D0290AB2
+:105F900001E1EED0030A01E1EBD02E0A01E1BCD011
+:105FA0000E0A01E18DD0020A54E0140A4FE0100AF3
+:105FB00020E0010A1EE0130A19E0030A0CE0070AB8
+:105FC00006E01B0A01E03CD1400EDF6E3AD1400EE4
+:105FD000DF6E92DF36D1020EDF26DF50EA6A000F55
+:105FE000E96E020EEA22EF28DF262BD1030EDF2610
+:105FF00028D1DF50DF2AEA6A000FE96E020EEA229A
+:10600000EF50E66EFADEE552DF50DF2AEA6A000F53
+:10601000E96E020EEA22EF50E66EEFDEE552DF5047
+:10602000DF2AEA6A000FE96E020EEA22EF50E66EFE
+:10603000E4DEE552DF50DF2AEA6A000FE96E020E65
+:10604000EA22EF50E66ED9DEE552FBD0050EDF26E0
+:10605000F8D0DF50DF2AEA6A000FE96E020EEA226A
+:10606000EF50E66ECADEE552DF50DF2AEA6A000F23
+:10607000E96E020EEA22EF50E66EBFDEE552DF5017
+:10608000DF2AEA6A000FE96E020EEA22010EEFCF64
+:10609000DBFF010EDBCFE6FFB0DEE552DF50DF2A8B
+:1060A000EA6A000FE96E020EEA22EF50E66EA5DE04
+:1060B000E552010EDB06010EDB500008EFE3C1D014
+:1060C000DF50DF2AEA6A000FE96E020EEA22EF5083
+:1060D000E66E93DEE552DF50DF2AEA6A000FE96ED2
+:1060E000020EEA22010EEFCFDBFF010EDBCFE6FF4F
+:1060F00084DEE552DF50DF2AEA6A000FE96E020E05
+:10610000EA22EF50E66E79DEE552010EDB06010E63
+:10611000DB500008EFE395D0DF50DF2AEA6A000F7A
+:10612000E96E020EEA22EF50E66E67DEE552DF50BE
+:10613000DF2AEA6A000FE96E020EEA22010EEFCFB3
+:10614000DBFF010EDBCFE6FF58DEE552DF50DF2A32
+:10615000EA6A000FE96E020EEA22EF50E66E4DDEAB
+:10616000E552010EDB06010EDB500008EFE369D0BB
+:10617000DF50DF2AEA6A000FE96E020EEA22EF50D2
+:10618000E66E3BDEE5525DD0DF2A5BD0DF50DF2AD2
+:10619000EA6A000FE96E020EEA22EF50E66E2DDE8B
+:1061A000E552DF50DF2AEA6A000FE96E020EEA22AA
+:1061B000EF50E66E22DEE552DF50DF2AEA6A000F7A
+:1061C000E96E020EEA22EF50E66E17DEE55239D094
+:1061D000DF50DF2AEA6A000FE96E020EEA22EF5072
+:1061E000E66E0BDEE552DF50DF2AEA6A000FE96E49
+:1061F000020EEA22EF50E66E00DEE552DF50DF2AA3
+:10620000EA6A000FE96E020EEA22EF50E66EF5DD53
+:10621000E552DF50DF2AEA6A000FE96E020EEA2239
+:10622000EF50E66EEADDE552DF50DF2AEA6A000F42
+:10623000E96E020EEA22EF50E66EDFDDE55201D094
+:10624000DF2A400EDF5C01E26BD6020EE15C02E267
+:10625000E16AE552E16EE552E7CFD9FF1200D9CFEE
+:10626000E6FFE1CFD9FF020EE126E2DC0401400E99
+:10627000B06FDBDDDF6EDF50AB0A01E1D1D0070A82
+:1062800001E1CCD0060A01E1C9D0030A01E1C3D083
+:10629000010A01E1BDD00F0A01E1B7D0010A01E115
+:1062A0009CD0030A01E18AD0010A01E185D0050AE8
+:1062B0006BE0010A53E0FA0A50E0DC0A4CE0030A02
+:1062C00048E0010A36E0070A2BE0040A25E0050A47
+:1062D00021E0030A11E0010A01E0A5D0A6DDE76E86
+:1062E000010EE7CFDBFFA1DDE66E010EDBCFE6FF9F
+:1062F00060D9E552E55299D098DDE76E010EE7CFFF
+:10630000DBFF93DDE66E010EDBCFE6FFB0D9E55291
+:10631000E5528BD0366A376A88DD386E86DD85D0E7
+:10632000361C366E371C376E80DD361A7EDD371A26
+:106330007CD07BDD586E79DD596E77DD5A6E75DD68
+:106340005B6E81D8000904E1010E396EAD0EDF6E7F
+:106350006CD003D96AD021D968D067D066DDE76EEA
+:10636000010EE7CFDBFF010EDBCFE6FF5EDDE66E61
+:1063700001EC16F0E552E55258DDE66E26EC17F01A
+:10638000E5520201FA6F51D050DD0001E06F4DDDA2
+:10639000E66E26EC17F0E552010F0001E16F020EE8
+:1063A0000001E15D0001E26F40DDE66E26EC17F0D2
+:1063B000E5520201FB6F39D0B6D937D036DDE76E32
+:1063C000010EE7CFDBFF31DDE66E010EDBCFE6FF2E
+:1063D00088EC19F0E552E55228D027DDE76E010E72
+:1063E000E7CFDBFF010EDBCFE6FFEBEC35F0E5524C
+:1063F000010EDBCFE6FF000EE66E020EE66E3CEC11
+:106400001DF0E552E552E55210D0BBEC17F00DD06F
+:1064100008EC36F00AD0B3EC17F007D04ED805D010
+:10642000D9EC19F002D0AD0EDF6EAD0EDF5C01E0ED
+:1064300020D7020EE15C02E2E16AE552E16EE5522C
+:10644000E7CFD9FF1200B3EC17F0010EE66EE66A53
+:1064500088EC19F0E552E552010EE66E020EE66E8A
+:1064600088EC19F0E552E552010EE66E010EE66E7B
+:1064700088EC19F0E552E5520001EA51EA2BEA6A8C
+:10648000600FE96E000EEA22EF5058160001EA5143
+:10649000EA2BEA6A600FE96E000EEA22EF50591605
+:1064A000B3EC17F05A50585C05E15B50595C02E1BF
+:1064B000010E02D0000E00D01200D9CFE6FFE1CFCE
+:1064C000D9FF040EE126360EDE6E000EDD6E020EE2
+:1064D000DB6A020EDBCF3FF00001EB513F5C000EA8
+:1064E000EC552FE20001EA51EA2BEA6A600FE96EEF
+:1064F000000EEA22030EEFCFDBFF385013E0020E4E
+:10650000DBA00ED038A003D0030EDB9E08D0030E14
+:10651000DB92DB94DB96DB98DB9ADB9CDB9E02D084
+:10652000030EDB90030EDB503F6E406ADECFE9FFC7
+:10653000DDCFEAFF3F50EE264050ED22020EDB2A6F
+:10654000C8D7B3EC17F0040EE15C02E2E16AE55251
+:10655000E16EE552E7CFD9FF1200B3EC17F0010E60
+:10656000E66EE66A88EC19F0E552E552010EE66E39
+:106570000D0EE66E88EC19F0E552E552010EE66E5E
+:10658000010EE66E88EC19F0E552E552600E00014E
+:1065900061153A6EB3EC17F012003A500101011385
+:1065A000010EE66E0F0EE66E88EC19F0E552E5522C
+:1065B0001200D9CFE6FFE1CFD9FFBBEC17F0B3EC67
+:1065C00017F00201E351E32BEA6A000FE96E010EB6
+:1065D000EA22FE0EDBCFEFFF0201E351E32BEA6A72
+:1065E000000FE96E010EEA22FD0EDBCFEFFF020184
+:1065F000E351E32BEA6A000FE96E010EEA22EF6A2B
+:10660000030E0201E527000E0201E623010EE66EED
+:10661000E66A88EC19F0E552E552010EE66E140EBA
+:10662000E66E88EC19F0E552E552010EE66E010EB9
+:10663000E66E88EC19F0E552E5520001EA51EA2BCA
+:10664000EA6A600FE96E000EEA22EF50346E000134
+:10665000EA51EA2BEA6A600FE96E000EEA22EF5077
+:10666000356EB3EC17F0E552E7CFD9FF1200D9CF62
+:10667000E6FFE1CFD9FFBBEC17F0B3EC17F0020156
+:10668000E351E32BEA6A000FE96E010EEA22FE0EE7
+:10669000DBCFEFFF0201E351E32BEA6A000FE96E63
+:1066A000010EEA22FD0EDBCFEFFF0201E351E32BE7
+:1066B000EA6A000FE96E010EEA22EF6A0201E35175
+:1066C000E32BEA6A000FE96E010EEA2234C0EFFF05
+:1066D0000201E351E32BEA6A000FE96E010EEA22A0
+:1066E00035C0EFFF050E0201E527000E0201E6238B
+:1066F000010EE66EE66A88EC19F0E552E552010EED
+:10670000E66E150EE66E88EC19F0E552E552010EC4
+:10671000E66E010EE66E88EC19F0E552E552E552A0
+:10672000E7CFD9FF1200D9CFE6FFE1CFD9FF0A0E9C
+:10673000E12615EC2FF0E66ED950060FE96EDACFA0
+:10674000EAFFE552E750EE6EED6A15EC2FF0E66ECB
+:10675000D950040FE96EDACFEAFFE552E750EE6E4A
+:10676000ED6A040EDBCF28F0050EDBCF29F0080E12
+:1067700028C0DBFF090E29C0DBFF040EDBCF3FF092
+:10678000050EDBCF40F0403404E23F503D08000EE0
+:10679000405403E20001E88D14D2020EDB6A030EBE
+:1067A000DB6ADE6ADD6ADECF3FF0DDCF40F0D890F5
+:1067B000405004E6200E3F5C000E405823E2DECF3E
+:1067C000E9FFDDCFEAFF030EEA02F3CFEAFF030E93
+:1067D000E902F3CFE9FFF450EA26800EE926020E23
+:1067E000EA22EF503F6E406AD950020FE96EDACFCD
+:1067F000EAFF3F50EE264050ED22DF2A010E01E372
+:10680000DB2AD1D7060EDBCFE9FF070EDBCFEAFF8D
+:10681000030EEA02F3CFEAFF030EE902F3CFE9FF2A
+:10682000F450EA26800EE926020EEA22EF503F6E6F
+:10683000406AD950020FE96EDACFEAFF3F50EE5EB0
+:106840004050ED5A040EDBCF3FF0050EDBCF40F099
+:10685000020EDBCF41F0030EDBCF42F0000ED880FA
+:106860004156030E425642504018E8AE02D0403422
+:1068700004D03F50415C4050425803E20001E88D93
+:10688000A0D1060EDBCF3FF0070EDBCF40F0403447
+:1068900004E23F501F08000E405403E20001E88D5F
+:1068A00090D1060EDBCFE9FF070EDBCFEAFF030E28
+:1068B000EA02F3CFEAFF030EE902F3CFE9FFF45057
+:1068C000EA26800EE926020EEA22EF5001E106D107
+:1068D000060EDBCFE9FF070EDBCFEAFF030EEA026D
+:1068E000F3CFEAFF030EE902F3CFE9FFF450EA2603
+:1068F000800EE926020EEA22EF503F6E406A000E3B
+:10690000D8803F56030E40563F06000E405A040EF4
+:106910003FC0DBFF050E40C0DBFF060EDBCFE9FF0B
+:10692000070EDBCFEAFF030EEA02F3CFEAFF030E06
+:10693000E902F3CFE9FFF450EA26800EE926020EC1
+:10694000EA22EE52EECFDEFFEDCFDDFFDECF3FF0ED
+:10695000DDCF40F0040EDBCF41F0050EDBCF42F07F
+:1069600040504218E8AE02D0423404D041503F5C5F
+:106970004250405835E2060EDBCFE9FF070EDBCF71
+:10698000EAFF030EEA02F3CFEAFF030EE902F3CFB8
+:10699000E9FFF450EA26800EE926020EEA22EF50C3
+:1069A0000001406AF4253F6EF5514022DE503F243D
+:1069B000E96EDD504020EA6EEF50E66EDE500001D9
+:1069C000F4250F01E96EDD500001F5210F01EA6E9B
+:1069D000E552E750EF6EDF2A010E01E3DB2AB6D75E
+:1069E000DE6ADD6ADECF3FF0DDCF40F0D890405068
+:1069F00004E6200E3F5C000E405870E2DECFE9FF57
+:106A0000DDCFEAFF030EEA02F3CFEAFF030EE9024D
+:106A1000F3CFE9FFF450EA26800EE926020EEA22BF
+:106A2000EECF3FF0EECF40F0EFCF41F0060EDBCFE0
+:106A3000E9FF070EDBCFEAFF030EEA02F3CFEAFF1E
+:106A4000030EE902F3CFE9FFF450EA26800EE926AF
+:106A5000020EEA22EE52EECF42F0EFCF43F00001F9
+:106A600043504118E8AE02D0413404D04050425C5B
+:106A7000415043582EE2060EDBCFE9FF070EDBCF75
+:106A8000EAFF030EEA02F3CFEAFF030EE902F3CFB7
+:106A9000E9FFF450EA26800EE926020EEA22EF50C2
+:106AA0003F6E406ADECFE9FFDDCFEAFF030EEA0268
+:106AB000F3CFEAFF030EE902F3CFE9FFF450EA2631
+:106AC000800EE926020EEA22EE523F50EE5E405062
+:106AD000ED5ADF2A010E01E3DB2A84D7060EDBCF55
+:106AE000E9FF070EDBCFEAFF030EEA02F3CFEAFF6E
+:106AF000030EE902F3CFE9FFF450EA26800EE926FF
+:106B0000020EEA22080EDBCFEFFF060EDBCFE9FF15
+:106B1000070EDBCFEAFF030EEA02F3CFEAFF030E14
+:106B2000E902F3CFE9FFF450EA26800EE926020ECF
+:106B3000EA22EE52020EDBCFEEFF030EDBCFEDFFBB
+:106B4000DE6ADD6ADECF3FF0DDCF40F0060EDBCF40
+:106B5000E9FF070EDBCFEAFF030EEA02F3CFEAFFFD
+:106B6000030EE902F3CFE9FFF450EA26800EE9268E
+:106B7000020EEA22EF50000140AE02D0D89003D0BE
+:106B80003F5C000E40581DE215EC2FF0E66E020E41
+:106B9000DB500001F42500013F6E030EDB500001C5
+:106BA000F5210001406EDE503F24E96EDD504020AB
+:106BB000EA6EE552E750EF6EDF2A010E01E3DB2AB1
+:106BC000C1D70A0EE15C02E2E16AE552E16EE552EC
+:106BD000E7CFD9FF1200D9CFE6FFE1CFD9FFE652C8
+:106BE000DF6AFE0EDB50DF5C0EE215EC2FF0E66E86
+:106BF000DF50EA6A000FE96E020EEA22E552E75022
+:106C0000EF6EDF2AEED7E552E552E7CFD9FF12004B
+:106C1000D9CFE6FFE1CFD9FF040EE12615EC2FF026
+:106C2000E66ED950020FE96EDACFEAFFE552E7507F
+:106C3000EE6EED6A020EDB500201E52500013F6EAB
+:106C4000030EDB500201E6210001406E000ED880E9
+:106C50003F54010E405403E20001E88F36D0DE6A53
+:106C6000DD6ADECF3FF0DDCF40F0020EDBCF41F03A
+:106C7000030EDBCF42F041503F5C4250405825E2CA
+:106C800015EC2FF0E66E0201E351E32BEA6A000FE8
+:106C9000E96E010EEA22E552E750EF6E0201E35180
+:106CA0003F6E406AD890405004E6000E3F5C010EF3
+:106CB000405802E30201E36B0201E52B000EE623DC
+:106CC000DF2A010E01E3DB2ACCD7040EE15C02E2ED
+:106CD000E16AE552E16EE552E7CFD9FF1200D9CF64
+:106CE000E6FFE1CFD9FFE652DF6A81AA14D0FE0E9B
+:106CF000DB50D880DF5408E3DF50DF2A010BE8B017
+:106D00008B80E8A08B9001D0DF6AF00EE66E58EC25
+:106D10003EF0E552EAD7E552E552E7CFD9FF12003F
+:106D20006C500CE16896040100513C0BE842E842CB
+:106D30000D0802E10ED801D04BD808D0040E6C5CCF
+:106D400003E1689657D802D0000E02D0010E00D0A1
+:106D50001200D9CFE6FFE1CFD9FFE652040104AF1C
+:106D600002D00401046B0201F96B0201F16B020114
+:106D7000F26B0201F76BF86BAEEC3BF0DF6ADF50B1
+:106D80003F6E406A010E3F5C000E40581BE202015C
+:106D9000F25101E017D0F76ADF34FE0BF736F66EDA
+:106DA000DE0EF6267A0EF7220900F5CF3FF0080036
+:106DB000F5CF40F004D040C0FAFF3F50F96EFBDF42
+:106DC000DF2ADDD705D9E552E552E7CFD9FF12001A
+:106DD000020E0201F15D0CE1B9D8040100BD04D03E
+:106DE0000401C80E006F03D00401880E006F01D0AB
+:106DF0003ED91200040E0001ED5D0CE112C46EFFDD
+:106E00006E50000804E20001050EED6F03D0000192
+:106E1000030EED6F0201F10514E115D8020E020117
+:106E2000F95D04E10401840E046F0AD0040104BD7D
+:106E300004D00401C80E046F03D00401880E046F4F
+:106E400001D015D91200D9CFE6FFE1CFD9FF020E4C
+:106E5000E1260201080EF75D000EF85912E2F7C2B2
+:106E6000DEFFF8C2DDFF0201F95104E10201010E6B
+:106E7000F96F06D00201F90503E10201020EF96F74
+:106E800003D0080EDE6EDD6A040104930401049150
+:106E9000010EDB5004010413DFCF05F4000EDB50BC
+:106EA0000201F75F010EDB500201F85B0201180ED0
+:106EB000F56F040EF66F0001EEA320D0D9CFE9FFE5
+:106EC000DACFEAFFEE50ED1018E0F3C2F6FFF4C29D
+:106ED000F7FF0800F550F5C2E9FFF6C2EAFFEF6ED2
+:106EE0000201F52B000EF6230201F32B000EF42312
+:106EF000DF06010E01E2DB06E1D71ED0D9CFE9FFA4
+:106F0000DACFEAFFEE50ED1017E0F3C2E9FFF4C26A
+:106F1000EAFFEF50F5C2E9FFF6C2EAFFEF6E0201A9
+:106F2000F52B000EF6230201F32B000EF423DF06EF
+:106F3000010E01E2DB06E2D7020EE15C02E2E16A49
+:106F4000E552E16EE552E7CFD9FF1200D9CFE6FF57
+:106F5000E1CFD9FF020EE126030E04010015E76E12
+:106F6000010EE7CFDBFF01C4DFFFDE500201F72790
+:106F7000DD500201F8230201180EF36F040EF46FC6
+:106F8000D9CFE9FFDACFEAFFEE50ED1017E0F3C2F8
+:106F9000E9FFF4C2EAFFEF50F5C2E9FFF6C2EAFFEB
+:106FA000EF6E0201F52B000EF6230201F32B000E0B
+:106FB000F423DF06010E01E2DB06E2D7020EE15CFC
+:106FC00002E2E16AE552E16EE552E7CFD9FF120035
+:106FD0006D980201F2510FE10401080E016F0401E6
+:106FE000100E026F040E036F0401840E006F040183
+:106FF000840E046F3BD0040110AF25D00201F7517D
+:107000000401165D0201F8510401175904E216C487
+:10701000F7F217C4F8F217DF0201010EF16F040155
+:10702000080E016F0401100E026F040E036F0401BD
+:10703000800E006F0401180E066F040E076F040126
+:10704000C80E046F13D00201020EF16F0401056B2C
+:107050000401C80E046F0401080E016F0401180E2C
+:10706000026F040E036F0401C80E006F12000201CC
+:10707000F16B0401080E016F0401100E026F040E83
+:10708000036F04018C0E006F0401046B12008986EB
+:10709000899454B0898492940000899655A089946B
+:1070A000898655B08984569E899689869284899668
+:1070B000898680B4568E899612005438556E56389B
+:1070C000576E5AC05CF05BC05DF0FE0E5A6E040E47
+:1070D0005B6E06EE00F0EE6AEAA6FDD7120007EE40
+:1070E000FFF0BAD85CC05AF05DC05BF08038ED129A
+:1070F0005D6EEA8200D000D000D00ED081AAA9D067
+:107100008038ED12EA825D6E551457181EE15C500E
+:1071100058140EE1594EAAD08050EF6E5C6E541494
+:10712000561816E15D385814E9E1592EE9D7AAD06E
+:1071300000008050EF6E5C6E5414561809E15D3803
+:107140005814DCE1592EDCD79DD081AA82D0E4D737
+:107150000000D4D707EEFFF07FD85CC05AF05DC0C6
+:107160005BF08038ED125D6EEA8200D000D000D076
+:107170000ED081AA6ED08038ED12EA825D6E551471
+:1071800057181EE15C5058140EE0594E6FD08050D5
+:10719000EF6E5C6E5414561816E15D385814E9E031
+:1071A000592EE9D76FD000008050EF6E5C6E5414FA
+:1071B000561809E15D385814DCE0592EDCD762D04E
+:1071C00081AA47D0E4D70000D4D707EEFFF044D817
+:1071D0005CC05AF05DC05BF07DD800008038ED12D5
+:1071E0005D6EEA8200D000D000D0000010D081AAED
+:1071F00030D070D88038ED12EA825D6E5514571881
+:1072000023E15C5058145F1810E1594E2FD062D81A
+:107210008050EF6E5C6E5414561819E15D385814A6
+:107220005F18E5E1592EE5D72DD0000053D88050E6
+:10723000EF6E5C6E541456180AE15D3858145F18EE
+:10724000D6E1592ED6D71ED081AA03D0E0D700D0E0
+:10725000CED7400E556E12008050EF6E00D000D099
+:1072600000D000005E5227E035D825D08050EF6E68
+:10727000E9CF54F0EA508009556E00D05E521BE011
+:1072800029D819D08038ED12EA82E9CF54F0EACF3C
+:1072900055F000D05E5202E01DD800D08050EF6E55
+:1072A00000005A2E15D05B4E1200000000005E5206
+:1072B00002E010D800D08038ED12EA825A2E09D0B0
+:1072C0005B4E1200000000005E52E8E003D8E6D7F3
+:1072D000EDD7F9D75E5000D000D00000E84E120084
+:1072E00000D00000F8D700EE00F00F0EEE6AEA6260
+:1072F000FDD71200040110511F0B010801E07DD0E1
+:107300000401145101E079D0060E0401115D2FE152
+:1073100004011351230A28E0010A13E0030A01E0E3
+:1073200024D00201020EF26F0001EF0505E1020117
+:10733000000EF36F7A0EF46F090E0201F76FF86B0F
+:1073400014D00201020EF26F0001EF0505E1020107
+:10735000B70EF36F7A0EF46F0001EF0504E11D0E16
+:107360000201F76FF86B01D000D00001EE83040139
+:107370001051600BE842E842E842E842E842010866
+:1073800001E03BD0040111510B0A31E0080A21E071
+:10739000090A19E0080A09E00B0A05E0080A01E0F9
+:1073A0002CD02CD82AD02BD828D00201020EF26F74
+:1073B0000201F10EF36F000EF46F0001EE93020173
+:1073C000010EF76F1AD00201020EF26F13C4F1F032
+:1073D00014D00201020EF26F0201F20EF36F000EE2
+:1073E000F46F0001EE930201010EF76F06D0020167
+:1073F000020EF26F12C4F2F000D01200120012005E
+:107400000001F36B1E0E716E0401400E096F040142
+:10741000200E0A6F040E0B6F0401880E086F040122
+:10742000600E0E6F040E0F6F0401400E0C6F120001
+:10743000D9CFE6FFE1CFD9FFE652FC0EDB50400882
+:1074400005E2400EF36EFC0EF3CFDBFFDF6AFC0EAD
+:10745000DB50DF5C19E2DF50E76EFD0EDBCFE9FFAA
+:10746000FE0EDBCFEAFFE750E926000EEA22EF50DE
+:10747000E66EDF50EA6A600FE96E040EEA22E5521A
+:10748000E750EF6EDF2AE3D7FC0EDBCF0DF4400EA2
+:1074900004010C1704010C7D880E04010C13E55245
+:1074A000E552E7CFD9FF1200D9CFE6FFE1CFD9FFF0
+:1074B0000001F36B040108BF39D0FC0EDBCF3FF0B5
+:1074C00004010951D8803F5403E2FC0E09C4DBFFDC
+:1074D0000001F36BFC0EDB500001F35D1CE20001C8
+:1074E000F351EA6A200FE96E040EEA22EF50E66ECD
+:1074F0000001F351E76EFD0EDBCFE9FFFE0EDBCF9F
+:10750000EAFFE750E926000EEA22E552E750EF6E67
+:107510000001F32BDFD70401400E096F400E040178
+:1075200008170401087D880E040108130001F351B7
+:1075300000D0E552E7CFD9FF1200D8CFE4FFE0CF6B
+:10754000E4FFE46EDACFE4FFE2CFDAFFE6520001B7
+:10755000E8A37CD0A150400B1DE0A050400B1AE0E6
+:10756000B4BE17D0A09CCD983550CF6E480E3424B1
+:10757000496E4A6A000E4A224A3404E24950FF0822
+:10758000000E4A5401E2CF2A480E3424CE6E9E905B
+:107590009D80A19C9E50010B31E09D50010B2EE07F
+:1075A0003550CF6E3450CE6E9E9036500AE1CD8865
+:1075B000B4AE04D09D90A19CA08C02D08B80362AC2
+:1075C0001DD03650080815E2B4AE0DD03DA003D052
+:1075D00037503B6E07D03DA203D037503C6E02D0EF
+:1075E00037503A6E3D2A8B90366A9D90A19CA08CB4
+:1075F00005D037903742B4BE378E362AA150020BE1
+:1076000024E0A050020B21E03550B36E3450B26E2E
+:10761000A192385004E18996382A8B8016D0090E41
+:10762000385C03E18986382A10D03850090804E212
+:10763000386AA0928B9009D0010E3914E8B089867F
+:10764000E8A08996382A3990394262D09EA035D078
+:107650009E90FA0ECF6E380ECE6E8150100B10E158
+:107660000201FA51C45C0CE20C0E0201FC5D05E162
+:107670008A948A880001E78902D00201FC2B02D09B
+:107680000201FC6B300E0001E71512E00201FEC2A0
+:1076900049F0FFC24AF0FE2B000EFF239B0ED8805C
+:1076A0004954020E4A5404E28B700201FE6BFF6BD8
+:1076B0009E9C010EC26E9D8CC2829EAC29D09E9C67
+:1076C0000C0EBA5C21E10001E151D880C45401E202
+:1076D000BB6A0001E251C45C02E2E0C0BBFF815022
+:1076E000040B10E00201FB51C45C0CE20C0E020121
+:1076F000FD5D05E18A948A880001E78B02D00201D2
+:10770000FD2B02D00201FD6B050EC26E9D9CC28254
+:10771000A1B4FF00E552E5CFDAFFE550E5CFE0FF89
+:10772000E5CFD8FF10000201FC6B0201FD6B800E5B
+:10773000CD6EFA0ECF6E380ECE6E9E909D80CD80AF
+:107740009E9C9D9C260EC06E050EC26EC2821200CB
+:107750009D90CD90C26A9E9C9D9C12000401105188
+:10776000600BE842E842E842E842E842000901E0F2
+:10777000A0D004011151080A01E18CD0010A01E1F5
+:1077800077D00F0A0AE0030A01E092D00201010E4D
+:10779000F26F0001040EED6F8CD00201010EF26F4A
+:1077A000040113050AE10201DC0EF36F790EF46F98
+:1077B000120E0201F76FF86B58D0020E0401135D30
+:1077C0001FE104011251F66EF76AD890F636F736CB
+:1077D000D40EF6267A0EF7220900F5CFF3F20A004E
+:1077E000F5CFF4F2020E0201F76AF325F66EF451BA
+:1077F000F7220900F5CFF7F20A00F5CFF8F235D0FD
+:10780000030E0401135D2FE1030E0401125D10E16C
+:107810000201000EF36F000EF46FF3C2E9FFF4C231
+:10782000EAFFEF500201F76FF86B0001EE9341D0D1
+:1078300004011251F66EF76AD890F636F736D80E74
+:10784000F6267A0EF7220900F5CFF3F20A00F5CFFB
+:10785000F4F2F3C2F6FFF4C2F7FF0800F55002019C
+:10786000F76FF86B02D00201F26B0001EE8321D0BA
+:107870000201010EF26F12C4EFF00401125104E193
+:107880000001050EED6F05D00001060EED6F00EC56
+:107890003AF00FD00201010EF26F0201EF0EF36F0A
+:1078A000000EF46F0001EE930201010EF76F01D09C
+:1078B00000D0120029C033F028C032F028502D0229
+:1078C000F4CF27F0F3CF26F029502E02F4CF29F081
+:1078D000F3CF28F02D02F3502726F4502822E86A2F
+:1078E000292232502E02F3502726F4502822E86A2B
+:1078F00029222EAE80EF3CF03250285E3350295AB8
+:1079000033AE000C2D50285E2E50295A000C28C092
+:1079100032F028502D02F4CF27F0F3CF26F0295073
+:107920002E02F4CF29F0F3CF28F02D02F3502726B2
+:10793000F4502822E86A292232502E02F3502726DA
+:10794000F4502822E86A2922000C29C033F028C00C
+:1079500032F027C031F027502C02F4CF25F0F3CFBE
+:1079600024F028502D02F4CF27F0F3CF26F02C027C
+:10797000F3502526F4502622E86A272231502D02A2
+:10798000F3502526F4502622E86A272229502C029B
+:10799000F3502626F450272229502D02286AE86A3F
+:1079A0002822F3502726F450282231502E02F3507B
+:1079B0002626F4502722296AE86A282229223250F2
+:1079C0002E02F3502726F4502822E86A2922335049
+:1079D0002E02F3502826F4502922000C1201000236
+:1079E00000000008D804330002000102030209026B
+:1079F0002900010102803209040000020300000096
+:107A0000092101000001221D00070581034000013A
+:107A10000705010340000109022000010204803231
+:107A20000904000002FF0000000705810340000177
+:107A3000070501034000010403090434034D0069F4
+:107A400000630072006F006300680069007000202E
+:107A50000054006500630068006E006F006C006FEA
+:107A60000067007900200049006E0063002E004886
+:107A7000035000490043006B00690074002000328D
+:107A80000020004D006900630072006F0063006F0A
+:107A9000006E00740072006F006C006C0065007274
+:107AA000002000500072006F006700720061006DDE
+:107AB000006D00650072000600FF0901A1011901B7
+:107AC0002940150026FF00750895408102190129FB
+:107AD000409102C0EE79177A377A3B7A6F7AF47266
+:107AE000080E6D6E6DBAFED7686A110E696E0001E0
+:107AF000020EED6F12006D6A696A0001ED6B1200F3
+:107B00006850040B09E06950040B06E06D9269941B
+:107B100068A402D06894FCD76850010B04E0695057
+:107B2000010B01E025D86850200B06E06950200BBE
+:107B300003E070B07090689A030E0001ED5D01E201
+:107B400016D00001F66B040E0001F65D10E26850DD
+:107B5000080B09E06950080B06E090EC36F00009CC
+:107B600001E1689601D003D00001F62BECD712009A
+:107B7000686A7B0E696E6E6A160E706E68A608D013
+:107B80006896000000000000000000000000F6D72A
+:107B90006D9837EC38F00001EF6B0001030EED6FCC
+:107BA0001200220EF66E5C0EF76E000EF86E0201E9
+:107BB0000900F550EC6F0900F550ED6F03E1EC673B
+:107BC00001D03DD00900F550E76F0900F550E86F8E
+:107BD0000900F550E96F09000900F550E96E090048
+:107BE000F550EA6E090009000900F550EA6F090036
+:107BF000F550EB6F09000900F6CFEEF2F7CFEFF288
+:107C0000F8CFF0F2E7C2F6FFE8C2F7FFE9C2F8FFEB
+:107C10000201EA5302E1EB5307E00900F550EE6E72
+:107C2000EA07F8E2EB07F9D7EEC2F6FFEFC2F7FF7B
+:107C3000F0C2F8FF0201EC07000EED5BBFD71200A7
+:107C400026502B02F3CF22F0F4CF23F02C02F35076
+:107C50002326000EF420246E26502D02F3502426F5
+:107C6000000EF420256E26502E02F35025262750B4
+:107C70002B02F3502326F4502422000E25222750F5
+:107C80002C02F3502426F450252227502D02F350C5
+:107C9000252628502B02F3502426F4502522285064
+:107CA0002C02F350252629502B02F35025261200D2
+:107CB000FF0EE3504C6EEF0E01D0F30EE76EE72E91
+:107CC0005FEF3EF00C0E4B6EE76AE72E65EF3EF07D
+:107CD0004B2E64EF3EF04C2E5DEF3EF0120006D8C6
+:107CE00080EC3DF016EC11F0FBD71200140E6F6E15
+:107CF0000001ED6B0001EE6B0001EF6B15EC10F075
+:107D000070EC3DF0120013EE00F023EE00F0F86A84
+:107D1000219CD1EC3DF0AAEC3EF06FEC3EF0FBD79D
+:107D20001200FF0EE3504C6E1B0E00D001D0200E4F
+:107D3000E76EE72EFED74C2EFAD700D01200FF0ECA
+:107D4000E350E84E1200000000D000D000D0E82E32
+:107D5000FAD7120012000005FFFFFFFFFFFFFFFF31
+:107D6000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF23
+:107D7000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF13
+:107D8000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF03
+:107D9000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3
+:107DA000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE3
+:107DB000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD3
+:107DC000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC3
+:107DD000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB3
+:107DE000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA3
+:107DF000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF93
+:107E0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF82
+:107E1000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF72
+:107E2000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF62
+:107E3000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF52
+:107E4000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF42
+:107E5000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF32
+:107E6000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF22
+:107E7000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF12
+:107E8000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF02
+:107E9000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2
+:107EA000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE2
+:107EB000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD2
+:107EC000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC2
+:107ED000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB2
+:107EE000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA2
+:107EF000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF92
+:107F0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF81
+:107F1000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF71
+:107F2000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF61
+:107F3000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF51
+:107F4000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF41
+:107F5000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF31
+:107F6000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF21
+:107F7000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF11
+:107F8000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF01
+:107F9000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1
+:107FA000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE1
+:107FB000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD1
+:107FC000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC1
+:107FD000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB1
+:107FE000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA1
+:107FF000FFFFFFFFFFFFFFFFFFFFFFFFFFFF5555E5
+:0200000400F00A
+:100000000001FA83FFFFFF01FFFFFFFFFFFFFFFF7C
+:10001000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0
+:10002000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE0
+:10003000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD0
+:10004000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC0
+:10005000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB0
+:10006000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA0
+:10007000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF90
+:10008000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80
+:10009000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF70
+:1000A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF60
+:1000B000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF50
+:1000C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF40
+:1000D000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF30
+:1000E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF20
+:1000F000234F6C486F737300000000000000000085
+:020000040030CA
+:0E000000240E391E000181000FC00EA00F401B
+:020000040020DA
+:08000000FFFFFFFFFFFFFFFF00
+:00000001FF
diff --git a/source/notes/pic-mcu/pickit2/pk2cmd-stuff/PK2V023200.hex.nrt b/source/notes/pic-mcu/pickit2/pk2cmd-stuff/PK2V023200.hex.nrt
new file mode 160000
+Subproject 1511337ad63e4166069adccc25743533edb36bb
diff --git a/source/notes/pic-mcu/pickit2/pk2cmd-stuff/hexdisasm.py b/source/notes/pic-mcu/pickit2/pk2cmd-stuff/hexdisasm.py
new file mode 100644
index 0000000..0c86592
--- /dev/null
+++ b/source/notes/pic-mcu/pickit2/pk2cmd-stuff/hexdisasm.py
@@ -0,0 +1,71 @@
+import pic24
+import pic18
+import pic16
+import sys
+
+arch = "pic18"
+
+hexfile = '../pk2cmd/pk2cmd/PK2V023200.hex'
+
+if len(sys.argv) > 1:
+ hexfile = sys.argv[1]
+
+ if len(sys.argv) > 2:
+ arch = sys.argv[2]
+
+if arch == "pic24":
+ arch = pic24
+elif arch == "pic18":
+ arch = pic18
+elif arch == "pic16":
+ arch = pic16
+else:
+ raise Exception("Invalid arch " + arch)
+
+lines = open(hexfile).readlines()
+
+def read_hex(lines):
+ regions = { 0: [0] * 0x10000 }
+ curr_region = regions[0]
+
+ for line in lines:
+ if not line.startswith(':'):
+ continue
+# raise Exception("invalid hex line, needs to start with a ':', but was: " + line)
+ bytecount = int(line[1:3], 16)
+ addr = int(line[3:7], 16)
+ rec_type = int(line[7:9], 16)
+ data_end = bytecount * 2 + 9
+ data = line[9:data_end]
+ # ignoring checksum because lazy
+
+ if rec_type == 4:
+ ext_linear_addr = int(data, 16)
+ if ext_linear_addr not in regions:
+ regions[ext_linear_addr] = [0] * 0x10000
+
+ curr_region = regions[ext_linear_addr]
+ elif rec_type == 0:
+ for i in range(bytecount):
+ curr_region[addr + i] = int(data[i*2:i*2 + 2], 16)
+ elif rec_type == 1:
+ print("Read HEX file")
+ return regions
+ else:
+ raise Exception("Unsupported record type: " + str(rec_type))
+
+
+memory_regions = read_hex(lines)
+
+i = 0
+
+coderegion = memory_regions[0]
+
+while i < len(coderegion):
+ (i, instr) = arch.disassemble(coderegion, i)
+ if "Unknown instr" in instr:
+ print(instr)
+ elif 'op' not in instr:
+ print(instr['mnemonic'])
+ else:
+ print("{} {}".format(instr['mnemonic'], instr['op']))
diff --git a/source/notes/pic-mcu/pickit2/pk2cmd-stuff/pic16.py b/source/notes/pic-mcu/pickit2/pk2cmd-stuff/pic16.py
new file mode 100644
index 0000000..e543cda
--- /dev/null
+++ b/source/notes/pic-mcu/pickit2/pk2cmd-stuff/pic16.py
@@ -0,0 +1,154 @@
+def render(instr):
+ if 'op' in instr:
+ return "{} {}".format(instr['mnemonic'], instr['op'])
+ else:
+ return instr['mnemonic']
+
+def disassemble(blob, offset):
+ instr = {}
+ instr['length'] = 1
+ instrbytes = blob[offset:offset + 2]
+# instrbytes.reverse()
+ print("Decoding {}{}...".format(hex(instrbytes[0])[2:], hex(instrbytes[1])[2:]))
+
+ if instrbytes[0] == 0x00:
+ print(hex(instrbytes[1]))
+ # there's a few instructions here...
+ if instrbytes[1] == 0xff:
+ instr['mnemonic'] = 'reset'
+ else:
+ instr['mnemonic'] = [
+ 'nop',
+ 'BAD',
+ 'BAD',
+ 'sleep',
+ 'clrwdt',
+ 'push',
+ 'pop',
+ 'daw',
+ 'tblrd*',
+ 'tblrd*+',
+ 'tblrd*-',
+ 'tblrd+*',
+ 'tblwr*',
+ 'tblwr*+',
+ 'tblwr*-',
+ 'tblwr+*',
+ 'retfie',
+ 'retfie fast',
+ 'return',
+ 'return fast',
+ 'callw*'][instrbytes[1]]
+ if instrbytes[0] == 0x01:
+ if instrbytes[1] > 0xf:
+ instr['mnemonic'] = 'BAD'
+ else:
+ instr['mnemonic'] = 'movlb'
+ instr['op'] = "#" + str(instrbytes[1])
+ elif instrbytes[0] == 0x02 or instrbytes[0] == 0x03:
+ instr['mnemonic'] = 'mulwf'
+ instr['op'] = 'TODO'
+ elif instrbytes[0] == 0x04 or instrbytes[0] == 0x05 or instrbytes[0] == 0x06 or instrbytes[0] == 0x07:
+ instr['mnemonic'] = 'decf'
+ instr['op'] = 'TODO'
+ elif instrbytes[0] == 0x08:
+ instr['mnemonic'] = 'sublw'
+ instr['op'] = '#' + hex(instrbytes[1])
+ elif instrbytes[0] == 0x09:
+ instr['mnemonic'] = 'iorlw'
+ instr['op'] = '#' + hex(instrbytes[1])
+ elif instrbytes[0] == 0x0a:
+ instr['mnemonic'] = 'xorlw'
+ instr['op'] = '#' + hex(instrbytes[1])
+ elif instrbytes[0] == 0x0b:
+ instr['mnemonic'] = 'andlw'
+ instr['op'] = '#' + hex(instrbytes[1])
+ elif instrbytes[0] == 0x0c:
+ instr['mnemonic'] = 'retlw'
+ instr['op'] = '#' + hex(instrbytes[1])
+ elif instrbytes[0] == 0x0d:
+ instr['mnemonic'] = 'mullw'
+ instr['op'] = '#' + hex(instrbytes[1])
+ elif instrbytes[0] == 0x0e:
+ instr['mnemonic'] = 'movlw'
+ instr['op'] = '#' + hex(instrbytes[1])
+ elif instrbytes[0] == 0x0f:
+ instr['mnemonic'] = 'addlw'
+ instr['op'] = '#' + hex(instrbytes[1])
+ elif instrbytes[0] >= 0x20 and instrbytes[0] <= 0x5f:
+ mnemonicSel = instrbytes[0] >> 2
+ instr['mnemonic'] = [
+ 'iorwf',
+ 'andwf',
+ 'xorwf',
+ 'comf',
+ 'addwfc',
+ 'addwf',
+ 'incf',
+ 'decfsz',
+ 'rrcf',
+ 'rlcf',
+ 'swapf',
+ 'incfsz',
+ 'rrncf',
+ 'rlncf',
+ 'infsnz',
+ 'dcfsnz',
+ 'movf',
+ 'subwfb',
+ 'subwfb',
+ 'subwf'
+ ][mnemonicSel]
+ instr['op'] = 'TODO'
+ elif instrbytes[0] >= 0x60 and instrbytes[0] < 0x70:
+ mnemonicSel = instrbytes[0] >> 1
+ instr['mnemonic'] = [
+ 'cpfslt',
+ 'cpfseq',
+ 'cpfsgt',
+ 'tstfsz',
+ 'setf',
+ 'clrf',
+ 'negf',
+ 'movwf'
+ ][mnemonicSel]
+ instr['op'] = 'TODO'
+ elif instrbytes[0] >= 0x70 and instrbytes[0] < 0xc0:
+ mnemonicSel = instrbytes[0] >> 4
+ instr['mnemonic'] = [
+ 'BAD', 'BAD', 'BAD', 'BAD', 'BAD', 'BAD', 'BAD',
+ 'BTG',
+ 'BSF',
+ 'BCF',
+ 'BTFSS',
+ 'BTFSC'
+ ][mnemonicSel]
+ instr['op'] = 'TODO'
+ elif instrbytes[0] >= 0xc0 and instrbytes[0] < 0xd0:
+ instr['mnemonic'] = 'MOVFF'
+ instr['op'] = 'TODO'
+ elif instrbytes[0] >= 0xd0 and instrbytes[0] < 0xd8:
+ instr['mnemonic'] = 'BRA'
+ instr['op'] = 'TODO'
+ elif instrbytes[0] >= 0xd8 and instrbytes[0] < 0xe0:
+ instr['mnemonic'] = 'RCALL'
+ instr['op'] = 'TODO'
+ elif instrbytes[0] >= 0xf0 and instrbytes[0] <= 0xff:
+ instr['mnemonic'] = 'MOVFF'
+ instr['op'] = 'TODO'
+ elif instrbytes[0] == 0xec or instrbytes[0] == 0xed:
+ instr['mnemonic'] = 'CALL'
+ instr['op'] = 'TODO'
+ instr['length'] = 2
+ elif instrbytes[0] == 0xee:
+ instr['mnemonic'] = 'LFSR'
+ instr['op'] = 'TODO'
+ instr['length'] = 2
+ elif instrbytes[0] == 0xef:
+ instr['mnemonic'] = 'GOTO'
+ instr['op'] = 'TODO'
+ instr['length'] = 2
+ else:
+ instr['mnemonic'] = 'TODO'
+
+ return (offset + instr['length'] * 2, instr)
diff --git a/source/notes/pic-mcu/pickit2/pk2cmd-stuff/pic16.pyc b/source/notes/pic-mcu/pickit2/pk2cmd-stuff/pic16.pyc
new file mode 100644
index 0000000..285d3ba
--- /dev/null
+++ b/source/notes/pic-mcu/pickit2/pk2cmd-stuff/pic16.pyc
Binary files 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
--- /dev/null
+++ b/source/notes/pic-mcu/pickit2/pk2cmd-stuff/pic18.pyc
Binary files 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
--- /dev/null
+++ b/source/notes/pic-mcu/pickit2/pk2cmd-stuff/pic24.pyc
Binary files 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
+Subproject 4e76e524ce8613f971b4167a9e2db1458e21e69
diff --git a/source/notes/pic-mcu/pickit2/pk2cmd-stuff/pk2cmd_script.py b/source/notes/pic-mcu/pickit2/pk2cmd-stuff/pk2cmd_script.py
new file mode 100644
index 0000000..f1de6ce
--- /dev/null
+++ b/source/notes/pic-mcu/pickit2/pk2cmd-stuff/pk2cmd_script.py
@@ -0,0 +1,146 @@
+import pic24
+
+NoOperands = [
+ 0xD5, 0xD6, 0xD7, 0xD8,
+ 0xEF, # comment on this one: Read & toss 2 response words
+ 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB
+]
+
+ScriptCommandTable = {
+ 0xB4: 'SCMD_JT2_WAIT_PE_RESP',
+ 0xB5: 'SCMD_JT2_GET_PE_RESP',
+ 0xB6: 'SCMD_JT2_XFERINST_BUF',
+ 0xB7: 'SCMD_JT2_XFRFASTDAT_BUF',
+ 0xB8: 'SCMD_JT2_XFRFASTDAT_LIT',
+ 0xB9: 'SCMD_JT2_XFERDATA32_LIT',
+ 0xBA: 'SCMD_JT2_XFERDATA8_LIT',
+ 0xBB: 'SCMD_JT2_SENDCMD',
+ 0xBC: 'SCMD_JT2_SETMODE',
+ 0xBD: 'SCMD_UNIO_TX_RX',
+ 0xBE: 'SCMD_UNIO_TX',
+ 0xBF: 'SCMD_MEASURE_PULSE',
+ 0xC0: 'SCMD_ICDSLAVE_TX_BUF_BL',
+ 0xC1: 'SCMD_ICDSLAVE_TX_LIT_BL',
+ 0xC2: 'SCMD_ICDSLAVE_RX_BL',
+ 0xC3: 'SCMD_SPI_RDWR_BYTE_BUF',
+ 0xC4: 'SCMD_SPI_RDWR_BYTE_LIT',
+ 0xC5: 'SCMD_SPI_RD_BYTE_BUF',
+ 0xC6: 'SCMD_SPI_WR_BYTE_BUF',
+ 0xC7: 'SCMD_SPI_WR_BYTE_LIT',
+ 0xC8: 'SCMD_I2C_RD_BYTE_NACK',
+ 0xC9: 'SCMD_I2C_RD_BYTE_ACK',
+ 0xCA: 'SCMD_I2C_WR_BYTE_BUF',
+ 0xCB: 'SCMD_I2C_WR_BYTE_LIT',
+ 0xCC: 'SCMD_I2C_STOP',
+ 0xCD: 'SCMD_I2C_START',
+ 0xCE: 'SCMD_AUX_STATE_BUFFER',
+ 0xCF: 'SCMD_SET_AUX',
+ 0xD0: 'SCMD_WRITE_BITS_BUF_HLD',
+ 0xD1: 'SCMD_WRITE_BITS_LIT_HLD',
+ 0xD2: 'SCMD_CONST_WRITE_DL',
+ 0xD3: 'SCMD_WRITE_BUFBYTE_W',
+ 0xD4: 'SCMD_WRITE_BUFWORD_W',
+ 0xD5: 'SCMD_RD2_BITS_BUFFER',
+ 0xD6: 'SCMD_RD2_BYTE_BUFFER',
+ 0xD7: 'SCMD_VISI24',
+ 0xD8: 'SCMD_NOP24',
+ 0xD9: 'SCMD_COREINST24',
+ 0xDA: 'SCMD_COREINST18',
+ 0xDB: 'SCMD_POP_DOWNLOAD',
+ 0xDC: 'SCMD_ICSP_STATES_BUFFER',
+ 0xDD: 'SCMD_LOOP_BUFFER',
+ 0xDE: 'SCMD_ICDSLAVE_TX_BUF',
+ 0xDF: 'SCMD_ICDSLAVE_TX_LIT',
+ 0xE0: 'SCMD_ICDSLAVE_RX',
+ 0xE1: 'SCMD_POKE_SFR',
+ 0xE2: 'SCMD_PEEK_SFR',
+ 0xE3: 'SCMD_EXIT_SCRIPT',
+ 0xE4: 'SCMD_GOTO_INDEX',
+ 0xE5: 'SCMD_IF_GT_GOTO',
+ 0xE6: 'SCMD_IF_EQ_GOTO',
+ 0xE7: 'SCMD_DELAY_SHORT',
+ 0xE8: 'SCMD_DELAY_LONG',
+ 0xE9: 'SCMD_LOOP',
+ 0xEA: 'SCMD_SET_ICSP_SPEED',
+ 0xEB: 'SCMD_READ_BITS',
+ 0xEC: 'SCMD_READ_BITS_BUFFER',
+ 0xED: 'SCMD_WRITE_BITS_BUFFER',
+ 0xEE: 'SCMD_WRITE_BITS_LITERAL',
+ 0xEF: 'SCMD_READ_BYTE',
+ 0xF0: 'SCMD_READ_BYTE_BUFFER',
+ 0xF1: 'SCMD_WRITE_BYTE_BUFFER',
+ 0xF2: 'SCMD_WRITE_BYTE_LITERAL',
+ 0xF3: 'SCMD_SET_ICSP_PINS',
+ 0xF4: 'SCMD_BUSY_LED_OFF',
+ 0xF5: 'SCMD_BUSY_LED_ON',
+ 0xF6: 'SCMD_MCLR_GND_OFF',
+ 0xF7: 'SCMD_MCLR_GND_ON',
+ 0xF8: 'SCMD_VPP_PWM_OFF',
+ 0xF9: 'SCMD_VPP_PWM_ON',
+ 0xFA: 'SCMD_VPP_OFF',
+ 0xFB: 'SCMD_VPP_ON',
+ 0xFC: 'SCMD_VDD_GND_OFF',
+ 0xFD: 'SCMD_VDD_GND_ON',
+ 0xFE: 'SCMD_VDD_OFF',
+ 0xFF: 'SCMD_VDD_ON'
+}
+
+def disassemble(blob, offset):
+ code = blob[offset]
+ length = 1
+ command = ScriptCommandTable[code]
+ result = {}
+ result['mnemonic'] = command
+ if code == 0xCF:
+ length += 1
+ result['op'] = hex(blob[offset + 1])
+ elif code == 0xD3 or code == 0xD4:
+ length += 1
+ immediate = blob[offset + 1]
+ elif code == 0xD9:
+ if blob[offset + 1 + 2] == 0x04:
+ # it's a goto, and there's a second instruction. this OUGHT to be
+ # followed by a SCMD_NOP24...
+ if blob[offset + 1 + 3] == 0xD8:
+ # it is! whew
+ instrbytes = blob[offset + 1:offset + 1 + 3]
+ instrbytes.append(0)
+ instrbytes.append(0)
+ instrbytes.append(0)
+
+ (postinstr_offset, instr) = pic24.disassemble(instrbytes, 0)
+ length = 1 + 3 + 1 # the command, three real bytes + the nop
+ result['op'] = instr #pic24.render(instr)
+ else:
+ (postinstr_offset, instr) = pic24.disassemble(blob, offset + 1)
+# length = postinstr_offset - offset
+ length = 4
+ result['op'] = instr #pic24.render(instr)
+ print("Goto not followed by nop, uhh what's " + hex(blob[offset + 3 + 1]))
+ else:
+ (postinstr_offset, instr) = pic24.disassemble(blob, offset + 1)
+ length = postinstr_offset - offset
+ result['op'] = instr #pic24.render(instr)
+ elif code in NoOperands:
+ pass
+ elif code == 0xE7 or code == 0xE8:
+ length += 1
+ result['op'] = hex(blob[offset + 1])
+ elif code == 0xEE:
+ length += 2
+# not sure if this is really two operands
+ result['op'] = hex(blob[offset + 1]) + ", " + hex(blob[offset + 2])
+ elif code == 0xE9:
+ length += 2
+ result['op'] = hex((blob[offset + 2] << 8) + blob[offset + 1])
+ elif code == 0xF2:
+ length += 1
+ result['op'] = hex(blob[offset + 1])
+ elif code == 0xF3:
+ length += 1
+ result['op'] = hex(blob[offset + 1])
+ else:
+ print("Unknown: " + command)
+ return None
+
+ return (offset + length, result)
diff --git a/source/notes/pic-mcu/pickit2/pk2cmd-stuff/pk2cmd_script.pyc b/source/notes/pic-mcu/pickit2/pk2cmd-stuff/pk2cmd_script.pyc
new file mode 100644
index 0000000..2ad27ee
--- /dev/null
+++ b/source/notes/pic-mcu/pickit2/pk2cmd-stuff/pk2cmd_script.pyc
Binary files 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