update Arduboy FX library, microcade bootloader

update Arduboy FX library to 1.0.7 with Load/SaveGameState functions and example

update microcade bootloader fixing RGB LED glitch when changing selection
This commit is contained in:
Mr.Blinky 2023-01-28 22:05:54 +01:00
parent 0b0e9a7136
commit db61fbe18a
13 changed files with 526 additions and 110 deletions

View File

@ -7,7 +7,7 @@
:107460000FBE31962F010895E0E0F0E085919491F0
:10747000019608958AE28BB98BEA34D01092890084
:107480008AEF8093880082E080936F0083E080938E
:107490008100EDE5F7E785913AD0E936E1F781E043
:107490008100E7E5F7E785913AD0E336E1F781E04F
:1074A0008093D7008AE482BF1092D8001092E20045
:1074B0001092DA001092E10080E808D019BC1EBAE0
:1074C0001092E00066D489E057D481E98093D80017
@ -18,49 +18,49 @@
:107510008DB587FFFDCF8EB508958FE08221E9F705
:10752000F3DFE3E6F6E090EB5C98892FF0DF80E193
:10753000EEDF5C9A8191EBDF83E68E278F77D1F7C0
:107540009395983B89F708952E9858982D98E3E6DF
:10755000F1E094FC36C097FC4DC092FE08959684ED
:107560009920D1F3F894C089D78520E030E080E0FD
:1075700090E4AFEFBFEF119689199040E0F72D012D
:10758000BD4F8D0127FD13C0E0E0F8E011928EE7BA
:10759000819392E4E11791939AE508F092E4E33441
:1075A000C9F781931082BCDFFE0121969DDF91DF38
:1075B000F90100D520583F4F040D151D9A9411F77D
:1075C0000FC28301282D60906C0170906B0143D035
:1075D00019F48823C1F70895380188243CD0C9F5EF
:1075E00080916A01821709F4830160906E017090A6
:1075F0006D01F4CF80E8982E60906E0170906D015F
:107600002AD059F48823B1F708959FEF96FC03C060
:1076100095FE089591E097FB890E662477248301F7
:10762000222719D0B1F48823A1F380916A0136F0A2
:10763000881650F4821730F0213003C0881520F4EA
:10764000281710F48301282F60906E0170906D014F
:10765000E8CF3801822EF30147DF3BDFC3E6D1E0FC
:10766000E6E5F7E709908591081621F4ED35D1F7A5
:107670000880801049CFC9E02EDFCA95E9F7D0E134
:1076800094FC55C097FC37C095FE1AC0C3E6D2E003
:10769000E3E6F6E098E088E78E0F00840192E817B1
:1076A000E1F7884F09900192E817E1F7C858DF4FDA
:1076B0009A9589F732DFC85FD340C33E49F749C086
:1076C000C3E6D6E0EBE5FAE098E08E2F885702900B
:1076D0000086E817E1F738960A900292E817E1F77A
:1076E0003897C857D0409A9581F717DFC850DC4FBC
:1076F000C33E41F72EC0A3EEB6E0E3E6F6E09AE023
:10770000C6E00D9080818025807F802582958193C1
:10771000A336B90709F4B2E0E336F90709F4F2E059
:10772000E336FC0771F7F9DEDA9529F712C0A3EE0C
:10773000B9E0E3E6FAE092E00E90829180258F7046
:10774000802582958083E336F907B1F7E6DEDA9586
:1077500071F78827089541524455424F59D5F08D0D
:1077600014A1C881CFD9F1AF000000FFFFCFCFFF38
:10777000FFFFFFCFCFFFFF0000FE067E7E06FE4626
:10778000565616FE0656461EFE3F61E9E3FFE3EB42
:0A779000E3FFE3EBE3FFE16B3F00D2
:10779A001201100102000008412336000100000016
:1077AA00000109023E0002010080320904000001C2
:1077BA000202010005240010010424020405240623
:1077CA000001070582030800FF09040100020A00FC
:1077DA0000000705040210000107058302100001DA
:107540009395983B89F70895E3E6F1E094FC36C003
:1075500097FC4DC092FE089596849920D1F3F8943B
:10756000C089D78520E030E080E090E4AFEFBFEF46
:10757000119689199040E0F72D01BD4F8D0127FD2F
:1075800013C0E0E0F8E011928EE7819392E4E117F6
:1075900091939AE508F092E4E334C9F7819310825D
:1075A000BFDFFE012196A0DF94DFF90103D520584B
:1075B0003F4F040D151D9A9411F712C28301282D17
:1075C00060906C0170906B0143D019F48823C1F76F
:1075D0000895380188243CD0C9F580916A0182174A
:1075E00009F4830160906E0170906D01F4CF80E822
:1075F000982E60906E0170906D012AD059F4882306
:10760000B1F708959FEF96FC03C095FE089591E0B1
:1076100097FB890E662477248301222719D0B1F4C1
:107620008823A1F380916A0136F0881650F48217FE
:1076300030F0213003C0881520F4281710F483019E
:10764000282F60906E0170906D01E8CF3801822E76
:10765000F3014ADF3EDFC3E6D1E0E0E5F7E709905A
:107660008591081621F4E735D1F7088080104CCFBA
:10767000C9E031DFCA95E9F7D0E194FC55C097FC29
:1076800037C095FE1AC0C3E6D2E0E3E6F6E098E024
:1076900088E78E0F00840192E817E1F7884F099080
:1076A0000192E817E1F7C858DF4F9A9589F735DF5F
:1076B000C85FD340C33E49F749C0C3E6D6E0EBE517
:1076C000FAE098E08E2F885702900086E817E1F7DD
:1076D00038960A900292E817E1F73897C857D040D9
:1076E0009A9581F71ADFC850DC4FC33E41F72EC090
:1076F000A3EEB6E0E3E6F6E09AE0C6E00D90808106
:107700008025807F802582958193A336B90709F46F
:10771000B2E0E336F90709F4F2E0E336FC0771F76B
:10772000FCDEDA9529F712C0A3EEB9E0E3E6FAE051
:1077300092E00E90829180258F70802582958083C3
:10774000E336F907B1F7E9DEDA9571F7882708958E
:1077500041524455424F59D5F08D14A1C881CFD91B
:10776000F1AF000000FFFFCFCFFFFFFFFFCFCFFF44
:10777000FF0000FE067E7E06FE46565616FE0656A4
:10778000461EFE3F61E9E3FFE3EBE3FFE3EBE3FFCC
:04779000E16B3F006A
:10779400120110010200000841233600010000001C
:1077A400000109023E0002010080320904000001C8
:1077B4000202010005240010010424020405240629
:1077C4000001070582030800FF09040100020A0002
:1077D40000000705040210000107058302100001E0
:1078000011241FBE04B714BE88E18093600010925B
:1078100060008EEF9AE09EBF8DBF222433242101A9
:107820003101410180E88AC00F928F939F931F928C
@ -83,13 +83,13 @@
:107930001F909F918F910FBE0F90189580936100BB
:1079400010926100B1E0B5BF82E085BF81E985B9E1
:1079500087EE84B91DB8769A10BA83EF81BB8CE2AA
:107960008BB98FE38AB980E58CBDBDBDA0E0EAE9A3
:107960008BB98FE38AB980E58CBDBDBDA0E0E4E9A9
:10797000F7E705900D92A035E1F71D92BB30E9F7CE
:1079800001FD06C000FF04C07F9B02C06DDD41F514
:1079900071DD789460DE71F0ABE9B7E0E9E6F7E716
:1079A00090E105900D929A95E1F7A059BF4FE93902
:1079900071DD78945DDE71F0ABE9B7E0E3E6F7E71F
:1079A00090E105900D929A95E1F7A059BF4FE33908
:1079B000B9F7B7DD4FD02CDD80915201807861F4AA
:1079C0008FB18095807F66991C9B8460982E1DDE08
:1079C0008FB18095807F66991C9B8460982E1ADE0B
:1079D0008110BADD92FC02C0332062F745DD51F31D
:1079E000F89489EB7FDD81E08093E00010926F00D6
:1079F00010928100109285001092840081E085BF72
@ -104,8 +104,8 @@
:107A800011F4C3DFFACF8C34C1F38035B1F38437FE
:107A900021F484E4C8DF80E004C1813611F489E573
:107AA00000C1813429F4B1DF582EAFDF482EE5CF75
:107AB000803711F483E5F5C0833539F4E6E5F7E75F
:107AC0008591B1DFED35E1F7EDC0863521F481E335
:107AB000803711F483E5F5C0833539F4E0E5F7E765
:107AC0008591B1DFE735E1F7EDC0863521F481E33B
:107AD000AADF89E3E6C0863781F481E3669B8E5F87
:107AE0001C9B8F5FA0DF81E47C9B885F7D9B8C5F0C
:107AF0007E9B8E5F7F9B8F5FD4C08837C1F485DF0C

View File

@ -7,7 +7,7 @@
:107460000FBE31962F010895E0E0F0E085919491F0
:10747000019608958AE28BB98BEA34D01092890084
:107480008AEF8093880082E080936F0083E080938E
:107490008100EDE5F7E785913AD0E936E1F781E043
:107490008100E7E5F7E785913AD0E336E1F781E04F
:1074A0008093D7008AE482BF1092D8001092E20045
:1074B0001092DA001092E10080E808D019BC1EBAE0
:1074C0001092E00066D489E057D481E98093D80017
@ -18,49 +18,49 @@
:107510008DB587FFFDCF8EB508958FE08221E9F705
:10752000F3DFE3E6F6E090EB5C98892FF0DF80E193
:10753000EEDF5C9A8191EBDF83E68E278F77D1F7C0
:107540009395983B89F708952E9858982D98E3E6DF
:10755000F1E094FC36C097FC4DC092FE08959684ED
:107560009920D1F3F894C089D78520E030E080E0FD
:1075700090E4AFEFBFEF119689199040E0F72D012D
:10758000BD4F8D0127FD13C0E0E0F8E011928EE7BA
:10759000819392E4E11791939AE508F092E4E33441
:1075A000C9F781931082BCDFFE0121969DDF91DF38
:1075B000F90100D520583F4F040D151D9A9411F77D
:1075C0000FC28301282D60906C0170906B0143D035
:1075D00019F48823C1F70895380188243CD0C9F5EF
:1075E00080916A01821709F4830160906E017090A6
:1075F0006D01F4CF80E8982E60906E0170906D015F
:107600002AD059F48823B1F708959FEF96FC03C060
:1076100095FE089591E097FB890E662477248301F7
:10762000222719D0B1F48823A1F380916A0136F0A2
:10763000881650F4821730F0213003C0881520F4EA
:10764000281710F48301282F60906E0170906D014F
:10765000E8CF3801822EF30147DF3BDFC3E6D1E0FC
:10766000E6E5F7E709908591081621F4ED35D1F7A5
:107670000880801049CFC9E02EDFCA95E9F7D0E134
:1076800094FC55C097FC37C095FE1AC0C3E6D2E003
:10769000E3E6F6E098E088E78E0F00840192E817B1
:1076A000E1F7884F09900192E817E1F7C858DF4FDA
:1076B0009A9589F732DFC85FD340C33E49F749C086
:1076C000C3E6D6E0EBE5FAE098E08E2F885702900B
:1076D0000086E817E1F738960A900292E817E1F77A
:1076E0003897C857D0409A9581F717DFC850DC4FBC
:1076F000C33E41F72EC0A3EEB6E0E3E6F6E09AE023
:10770000C6E00D9080818025807F802582958193C1
:10771000A336B90709F4B2E0E336F90709F4F2E059
:10772000E336FC0771F7F9DEDA9529F712C0A3EE0C
:10773000B9E0E3E6FAE092E00E90829180258F7046
:10774000802582958083E336F907B1F7E6DEDA9586
:1077500071F78827089541524455424F59D5F08D0D
:1077600014A1C881CFD9F1AF000000FFFFCFCFFF38
:10777000FFFFFFCFCFFFFF0000FE067E7E06FE4626
:10778000565616FE0656461EFE3F61E9E3FFE3EB42
:0A779000E3FFE3EBE3FFE16B3F00D2
:10779A001201100102000008412336000100000016
:1077AA00000109023E0002010080320904000001C2
:1077BA000202010005240010010424020405240623
:1077CA000001070582030800FF09040100020A00FC
:1077DA0000000705040210000107058302100001DA
:107540009395983B89F70895E3E6F1E094FC36C003
:1075500097FC4DC092FE089596849920D1F3F8943B
:10756000C089D78520E030E080E090E4AFEFBFEF46
:10757000119689199040E0F72D01BD4F8D0127FD2F
:1075800013C0E0E0F8E011928EE7819392E4E117F6
:1075900091939AE508F092E4E334C9F7819310825D
:1075A000BFDFFE012196A0DF94DFF90103D520584B
:1075B0003F4F040D151D9A9411F712C28301282D17
:1075C00060906C0170906B0143D019F48823C1F76F
:1075D0000895380188243CD0C9F580916A0182174A
:1075E00009F4830160906E0170906D01F4CF80E822
:1075F000982E60906E0170906D012AD059F4882306
:10760000B1F708959FEF96FC03C095FE089591E0B1
:1076100097FB890E662477248301222719D0B1F4C1
:107620008823A1F380916A0136F0881650F48217FE
:1076300030F0213003C0881520F4281710F483019E
:10764000282F60906E0170906D01E8CF3801822E76
:10765000F3014ADF3EDFC3E6D1E0E0E5F7E709905A
:107660008591081621F4E735D1F7088080104CCFBA
:10767000C9E031DFCA95E9F7D0E194FC55C097FC29
:1076800037C095FE1AC0C3E6D2E0E3E6F6E098E024
:1076900088E78E0F00840192E817E1F7884F099080
:1076A0000192E817E1F7C858DF4F9A9589F735DF5F
:1076B000C85FD340C33E49F749C0C3E6D6E0EBE517
:1076C000FAE098E08E2F885702900086E817E1F7DD
:1076D00038960A900292E817E1F73897C857D040D9
:1076E0009A9581F71ADFC850DC4FC33E41F72EC090
:1076F000A3EEB6E0E3E6F6E09AE0C6E00D90808106
:107700008025807F802582958193A336B90709F46F
:10771000B2E0E336F90709F4F2E0E336FC0771F76B
:10772000FCDEDA9529F712C0A3EEB9E0E3E6FAE051
:1077300092E00E90829180258F70802582958083C3
:10774000E336F907B1F7E9DEDA9571F7882708958E
:1077500041524455424F59D5F08D14A1C881CFD91B
:10776000F1AF000000FFFFCFCFFFFFFFFFCFCFFF44
:10777000FF0000FE067E7E06FE46565616FE0656A4
:10778000461EFE3F61E9E3FFE3EBE3FFE3EBE3FFCC
:04779000E16B3F006A
:10779400120110010200000841233600010000001C
:1077A400000109023E0002010080320904000001C8
:1077B4000202010005240010010424020405240629
:1077C4000001070582030800FF09040100020A0002
:1077D40000000705040210000107058302100001E0
:1078000011241FBE04B714BE88E18093600010925B
:1078100060008EEF9AE09EBF8DBF222433242101A9
:107820003101410180E88AC00F928F939F931F928C
@ -83,13 +83,13 @@
:107930001F909F918F910FBE0F90189580936100BB
:1079400010926100B1E0B5BF82E085BF81E985B9E1
:1079500087EE84B91DB8769A10BA83EF81BB8CE2AA
:107960008BB98FE38AB980E58CBDBDBDA0E0EAE9A3
:107960008BB98FE38AB980E58CBDBDBDA0E0E4E9A9
:10797000F7E705900D92A035E1F71D92BB30E9F7CE
:1079800001FD06C0000004C07F9B02C06DDD41F513
:1079900071DD789460DE71F0ABE9B7E0E9E6F7E716
:1079A00090E105900D929A95E1F7A059BF4FE93902
:1079900071DD78945DDE71F0ABE9B7E0E3E6F7E71F
:1079A00090E105900D929A95E1F7A059BF4FE33908
:1079B000B9F7B7DD4FD02CDD80915201807861F4AA
:1079C0008FB18095807F66991C9B8460982E1DDE08
:1079C0008FB18095807F66991C9B8460982E1ADE0B
:1079D0008110BADD92FC02C0332062F745DD51F31D
:1079E000F89489EB7FDD81E08093E00010926F00D6
:1079F00010928100109285001092840081E085BF72
@ -104,8 +104,8 @@
:107A800011F4C3DFFACF8C34C1F38035B1F38437FE
:107A900021F484E4C8DF80E004C1813611F489E573
:107AA00000C1813429F4B1DF582EAFDF482EE5CF75
:107AB000803711F483E5F5C0833539F4E6E5F7E75F
:107AC0008591B1DFED35E1F7EDC0863521F481E335
:107AB000803711F483E5F5C0833539F4E0E5F7E765
:107AC0008591B1DFE735E1F7EDC0863521F481E33B
:107AD000AADF89E3E6C0863781F481E3669B8E5F87
:107AE0001C9B8F5FA0DF81E47C9B885F7D9B8C5F0C
:107AF0007E9B8E5F7F9B8F5FD4C08837C1F485DF0C

View File

@ -21,10 +21,6 @@
#include <ArduboyFX.h> // required to access the FX external flash
#include "fxdata/fxdata.h" // this file contains all references to FX data
//constant values
constexpr uint8_t FXlogoWidth = 115;
constexpr uint8_t FXlogoHeight = 16;
Arduboy2 arduboy;
//assign values;

View File

@ -20,7 +20,7 @@
#include <Arduboy2.h>
#include <ArduboyFX.h>
#include "fxdata\fxdata.h"
#include "fxdata/fxdata.h"
Arduboy2Base arduboy;

View File

@ -0,0 +1 @@
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>

View File

@ -0,0 +1,14 @@
#pragma once
/**** FX data header generated by fxdata-build.py tool version 1.13 ****/
using uint24_t = __uint24;
// Initialize FX hardware using FX::begin(FX_DATA_PAGE); in the setup() function.
constexpr uint16_t FX_DATA_PAGE = 0xfff0;
constexpr uint24_t FX_DATA_BYTES = 0;
constexpr uint16_t FX_SAVE_PAGE = 0xfff0;
constexpr uint24_t FX_SAVE_BYTES = 2;

View File

@ -0,0 +1,4 @@
savesection //4K block save section. Any data below will be stored in save data area
uint16_t 0xFFFF //game state end marker / start of unused space

View File

@ -0,0 +1,169 @@
/* *****************************************************************************
* FX gameState example v1.00 by Mr.Blinky Jan.2023 licenced under CC0
* *****************************************************************************
*
* This is a example showing how you can save and load game data to the FX flash
* chip.
*
* Before this example sketch is uploaded and run on the Arduboy FX, make sure
* the fxdata of this sketch has been built and uploaded to the Arduboy FX.
*
* If the Arduboy FX Arduino plugin has been installed you can simply choose the
* 'Build and upload Arduboy FX data' from the Arduino IDE Tools menu. Since the
* data has already been prebuild for this demo you may alsu choose the 'upload
* existing Arduboy FX data' option.
*
* Alternatively the fxdata.txt script file can be build using the fxdata-build.py
* Python script and the fxdata.bin file can be uploaded using the
* fxdata-upload.py, uploader-gui.py, or flash-writer.py (using the -d switch)
* Python scripts.
*
* *****************************************************************************
*
* The FX library has two functions for saving and loading game data:
*
* uint8_t FX::loadGameState(uint8_t* gameState, size_t size)
*
* void FX::saveGameState(uint8_t* gameState, size_t size)
*
* loadGameState
* -------------
*
* Loads previously saved game data. It returns 0 if there was no data to load
* or 1 if the data was successfully loaded.
*
* gameState is a pointer to an uint8_t array or to a structure in RAM containing
* your game data. When using a structure for the game data, the structure must be
* cast to an uint8_t array by putting (uint8_t*)& in front of the structures name.
*
* size is the size of the uint8_t array or structure in RAM and is usually
* determined by using the sizeof() operator.
*
* When there is no game data loaded (result 0), the contents of the gameState
* structure remains unchanged.
*
* saveGameState
* -------------
*
* Saves game data into a 4K flash block that is uniquely assigned to a program.
* On the first save, data is saved at the beginning of the block. Any save
* after that will be appended after previously saved data as a simple method to
* reduce flash wear. Once the new data doesn't fit into the 4K block, the block
* is erased and the new data is stored at the beginning of the block again.
* when an erase is necessary this function takes a bit longer to execute.
* This process is fully transparent and you do not need to worry about it.
* It just explains why sometimes this function may take a bit more time then usual.
*
* gameState and size are the same parameters as for the loadSaveData function.
*
* initilizing FX chip when using save capabilities
* ------------------------------------------------
*
* To let the FX library know your sketch makes use of save data the FX library
* must be initialized in setup with the following line:
*
* FX::begin(FX_DATA_PAGE, FX_SAVE_PAGE);
*
* The FX_DATA_PAGE, FX_SAVE_PAGE defines are defined in the fxdata.h file that
* will be created by the fxdata-build tool.
*
* creating a save data block
* --------------------------
*
* In order to use the loadGameState and saveGameState functions, a save section
* must be added to the fxdata.txt file located in the fxdata folder in your
* sketch folder. this save section can be added by typing the word 'savesection'
* (without the quotes)on a line at the end of the fxdata.txt file.
* Any data defined after that will be written into the default save data file.
* A minimum blank save data file can be generated by adding just two lines:
*
* savesection
* uint16_t 0xFFFF // No saved game state / end of game state
*
* Example of a predefined save data with 5 high scores:
*
* savesection
* uint16_t 30 //size of save data excluding length bytes
* uint16_t 50000 //high scores
* string "KVN"
* uint16_t 40000
* string "MRB"
* uint16_t 30000
* string "FLM"
* uint16_t 20000
* string "VMP"
* uint16_t 10000
* string "ADB"
* uint16_t 0xFFFF //end of save data / beginning of free space
* //not included in the save data length
*
* when there is a savesection in a fxdata.txt file, the fxbuild.by tool will
* generate 3 files:
*
* fxdata.bin this file is uploaded during development, when uploading
* a sketch through the Arduino IDE or using a emulator.
* It contains both the data and save sections.
*
* fxdata-data.bin contains only the data. This file is used when the sketch
* hexfile is made part of a flash image file.
* fxdata-save.bin contains only the save data. This file is used when the
* sketch hexfile is made part of a flash image file.
*
******************************************************************************/
#include <Arduboy2.h>
#include <ArduboyFX.h>
#include "fxdata/fxdata.h" //created by the fxdata-build.py python script.
Arduboy2 arduboy;
// First we create a structure that will contain all the relevant game data that
// needs to be saved.
struct GameState
{
char name[20]; // space for a text string
uint16_t count; // A counter that counts the number of times this sketch was
}; // run (and saved data)
GameState gameState; // This creates the actual gameState in ram.
void setup() {
arduboy.begin(); // initialize Arduboy.
FX::begin(FX_DATA_PAGE, FX_SAVE_PAGE); // Initialize FX chip. When using FX save data,
// FX_SAVE_PAGE must also be passed on in FX::begin.
if (!FX::loadGameState((uint8_t*) &gameState, sizeof(gameState))) // Load saveState from the 4K FX save data block. '(uint8_t*) &' is used
// here to cast a uint8_t pointer to the saveState structure.
{
// This code gets executed only when the function didn't load a saveState (function returned 0)
strcpy(gameState.name, "Hello World !!!"); // copy some introductory text to saveState.name
gameState.count = 1; // set count to 1 for 1st time this sketch is run.
}
else
{
// A previously saved gameState was loaded.
strcpy(gameState.name, "Save state loaded"); // change text
gameState.count ++; // increase the number of times this sketch was run.
}
FX::saveGameState((uint8_t*) &gameState, sizeof(gameState)); //Save the game state to 4K FX save block
arduboy.clear();
arduboy.setCursor(0,32 - 8);
arduboy.print(gameState.name);
arduboy.setCursor(0,32 + 8);
arduboy.print("Number of times this\nsketch is run: ");
arduboy.print(gameState.count);
FX::display();
}
void loop() {
if (!arduboy.nextFrame()) return; //waint for next frame
if (arduboy.buttonsState()) arduboy.exitToBootloader(); // exit to bootloader.
}

View File

@ -1,5 +1,5 @@
name=ArduboyFX
version=1.0.6
version=1.0.7
author=Mr.Blinky
maintainer=mstr.blinky@gmail.com
sentence=The Arduboy FX library.

View File

@ -32,6 +32,25 @@ void FX::begin()
void FX::begin(uint16_t developmentDataPage)
{
disableOLED();
#ifdef ARDUINO_ARCH_AVR
const uint8_t* vector = FX_DATA_VECTOR_KEY_POINTER;
asm volatile(
"lpm r18, z+ \n"
"lpm r19, z+ \n"
"lpm r21, z+ \n"
"lpm r20, z+ \n"
"subi r18, 0x18 \n"
"sbci r19, 0x95 \n"
"brne .+2 \n" // skip if FX_DATA_VECTOR_KEY_POINTER != FX_VECTOR_KEY_VALUE
"movw %A[devdata], r20 \n"
"sts %[datapage]+0, %A[devdata] \n"
"sts %[datapage]+1, %B[devdata] \n"
: "+&z" (vector),
[devdata] "+&r" (developmentDataPage)
: [datapage] "" (&programDataPage)
: "r18", "r19", "r20", "r21"
);
#else
if (pgm_read_word(FX_DATA_VECTOR_KEY_POINTER) == FX_VECTOR_KEY_VALUE)
{
programDataPage = (pgm_read_byte(FX_DATA_VECTOR_PAGE_POINTER) << 8) | pgm_read_byte(FX_DATA_VECTOR_PAGE_POINTER + 1);
@ -40,6 +59,7 @@ void FX::begin(uint16_t developmentDataPage)
{
programDataPage = developmentDataPage;
}
#endif
wakeUp();
}
@ -47,6 +67,37 @@ void FX::begin(uint16_t developmentDataPage)
void FX::begin(uint16_t developmentDataPage, uint16_t developmentSavePage)
{
disableOLED();
#ifdef ARDUINO_ARCH_AVR
const uint8_t* vector = FX_DATA_VECTOR_KEY_POINTER;
asm volatile(
"lpm r18, z+ \n"
"lpm r19, z+ \n"
"lpm r21, z+ \n"
"lpm r20, z+ \n"
"subi r18, 0x18 \n"
"sbci r19, 0x95 \n"
"brne .+2 \n" // skip if FX_DATA_VECTOR_KEY_POINTER != FX_VECTOR_KEY_VALUE
"movw %A[devdata], r20 \n"
"sts %[datapage]+0, %A[devdata] \n"
"sts %[datapage]+1, %B[devdata] \n"
"lpm r18, z+ \n"
"lpm r19, z+ \n"
"lpm r21, z+ \n"
"lpm r20, z+ \n"
"subi r18, 0x18 \n"
"sbci r19, 0x95 \n"
"brne .+2 \n" // skip if FX_SAVE_VECTOR_KEY_POINTER != FX_VECTOR_KEY_VALUE
"movw %A[devsave], r20 \n"
"sts %[savepage]+0, %A[devsave] \n"
"sts %[savepage]+1, %B[devsave] \n"
: "+&z" (vector),
[devdata] "+&r" (developmentDataPage),
[devsave] "+&r" (developmentSavePage)
: [datapage] "" (&programDataPage),
[savepage] "" (&programSavePage)
: "r18", "r19", "r20", "r21"
);
#else
if (pgm_read_word(FX_DATA_VECTOR_KEY_POINTER) == FX_VECTOR_KEY_VALUE)
{
programDataPage = (pgm_read_byte(FX_DATA_VECTOR_PAGE_POINTER) << 8) | pgm_read_byte(FX_DATA_VECTOR_PAGE_POINTER + 1);
@ -63,6 +114,7 @@ void FX::begin(uint16_t developmentDataPage, uint16_t developmentSavePage)
{
programSavePage = developmentSavePage;
}
#endif
wakeUp();
}
@ -207,7 +259,6 @@ void FX::seekSave(uint24_t address)
"adc %C[addr], r0 \n"
:[addr] "+&r" (address)
:[page] "" (&programSavePage)
:"r24"
);
#else // C++ version for non AVR platforms
address += (uint24_t)programSavePage << 8;
@ -406,6 +457,183 @@ void FX::readSaveBytes(uint24_t address, uint8_t* buffer, size_t length)
readBytesEnd(buffer, length);
}
uint8_t FX::loadGameState(uint8_t* gameState, size_t size) // ~54 bytes
{
#ifdef ARDUINO_ARCH_AVR
uint8_t result asm("r24");
asm volatile(
"ldi r22, 0 \n" //seekSave(0)
"ldi r23, 0 \n"
"ldi r24, 0 \n"
"call %x3 \n" //seekSave uses r20, r21, r22, r23, r24
"movw r18, r26 \n" //save size
"movw r20, r30 \n" //save gameState
"0: \n"
"ldi r22,0 \n" //result = 0
"1: \n"
"call %x4 \n" //readPendingUInt16 uses r24, r25
"cp r24, r18 \n"
"cpc r25, r19 \n"
"brne 4f \n" //if (readPendingUInt16 != size) break
" \n"
"movw r26, r18 \n" //restore size
"movw r30, r20 \n" //restore gameState
"ldi r22, 0 \n" //result = 0
"2: \n" //do
"call %x5 \n" // data = readPendingUint8
"st z+, r24 \n" // addr = data
"sbiw r26, 1 \n" // size--
"brne 2b \n" //until size == 0
"ldi r22, 1 \n" //result = 1
"rjmp 1b \n" //next
"4: \n"
"call %x6 \n" //readEnd
"mov r24, r22 \n" //return result
: [addr] "+&z" (gameState),
[size] "+&x" (size),
[val] "=&r" (result)
: "i" (seekSave),
"i" (readPendingUInt16),
"i" (readPendingUInt8),
"i" (readEnd)
: "r18", "r19", "r20", "r21"
);
#else
seekSave(0);
uint8_t result = 0;
while (readPendingUInt16() == size) // if gameState size not equal, most recent gameState has been read or there is no gameState
{
for (uint16_t i = 0; i < size; i++)
{
uint8_t data = readPendingUInt8();
gameState[i] = data;
}
{
result = 1; // signal gameState loaded
}
}
readEnd();
#endif
return result;
}
void FX::saveGameState(uint8_t* gameState, size_t size) // ~152 bytes locates free space in 4K save block and saves the GamesState.
{ // if there is not enough free space, the block is erased prior to saving
register size_t sz asm("r18") = size;
#ifdef ARDUINO_ARCH_AVR
asm volatile(
"ldi r26, 0 \n" //addr = 0
"ldi r27, 0 \n"
"1: \n"
"movw r22, r26 \n" //uint24_t addr
"ldi r24, 0 \n"
"call %x2 \n" //seekSave uses r20, r21, r22, r23, r24
"call %x3 \n" //readPendingLastUInt16 uses r24, r25
"movw r22, r26 \n" //save addr
"adiw r26, 2 \n" //addr += 2 for size word
"add r26, r18 \n" //addr += size
"adc r27, r19 \n"
"cp r24, r18 \n"
"cpc r25, r19 \n"
"breq 1b \n" //readPendingLastUInt16 == size
" \n"
"subi r24, 0xFF \n" //if result of readPendingLastUInt16 != 0xFFFF
"sbci r25, 0xFF \n"
"brne 2f \n" //erase block
" \n"
"subi r26, lo8(4094+1) \n"
"sbci r27, hi8(4094+1) \n"// addr < 4094+1 (last two bytes in 4K block always 0xFF)
"movw r26, r22 \n"// addr -= size - 2 point to start of free space
"brcs 3f \n"
"2: \n" //erase 4K save block at addr
"call %x4 \n" //writeEnable
"ldi r20, 0 \n"
"lds r21, %[page]+0 \n"
"lds r22, %[page]+1 \n"
"ldi r24, %[erase] \n" //SFC_ERASE
"call %x5 \n" //seekCommand
"sbi %[fxport], %[fxbit] \n" //disable
"call %x6 \n" //waitWhileBusy
"ldi r26, 0 \n" //addr = 0
"ldi r27, 0 \n"
"3: \n"
"ldi r23, 0xFC \n" // int8_t shiftstate = -4
"4: \n"
"call %x4 \n" //writeEnable
"mov r20, r26 \n" //addr
"lds r21, %[page]+0 \n"
"add r21, r27 \n"
"lds r22, %[page]+1 \n"
"adc r22, r1 \n"
"ldi r24, %[write] \n" //SFC_WRITE
"call %x5 \n" //seekCommand
"5: \n"
"mov r24, r19 \n"
"sbrc r23, 1 \n" //if (shiftstate & 3 == 0) writebyte(size >> 8)
"mov r24, r18 \n" //if (shiftstate & 3 == 2) writebyte(size & 0xFF)
"sbrc r23, 0 \n" //else writeByte(gameState++);
"ld r24, z+ \n" //saveState
"call %x7 \n" //writeByte
"asr r23 \n" //shiftstate >>= 1
"brcc .+4 \n" //if (shiftstate == -1) size--
"subi r18, 1 \n"
"sbci r19, 0 \n"
"breq 6f \n" //size == 0
" \n"
"adiw r26, 1 \n" //addr++
"and r26, r26 \n"
"brne 5b \n" //while addr & 0xFF != 0 (not end of page)
"6: \n"
"sbi %[fxport], %[fxbit] \n" //disable
"call %x6 \n" //waitWhileBusy
"cp r18, r1 \n"
"cpc r19, r1 \n"
"brne 4b \n" //while size != 0
:[state] "+&z" (gameState),
[size] "+&r" (sz)
: "" (seekSave),
"" (readPendingLastUInt16),
"" (writeEnable),
"" (seekCommand),
"" (waitWhileBusy),
"" (writeByte),
[fxport] "i" (_SFR_IO_ADDR(FX_PORT)),
[fxbit] "i" (FX_BIT),
[erase] "i" (SFC_ERASE),
[write] "i" (SFC_WRITE),
[page] "" (&programSavePage)
: "r20", "r21", "r22", "r23", "r24", "r25", "r26", "r27"
);
#else
uint16_t addr = 0;
for(;;) // locate end of previous gameStates
{
seekSave(addr);
if (readPendingLastUInt16() != size) break; //found end of previous gameStates
addr += size + 2;
}
if ((addr + size) > 4094) //is there enough space left? last two bytes of 4K block must always be unused (0xFF)
{
eraseSaveBlock(0); // erase save block
waitWhileBusy(); // wait for erase to complete
addr = 0; // write saveState at the start of block
}
while (size)
{
writeEnable();
seekCommand(SFC_WRITE, (uint24_t)(programSavePage << 8) + addr);
do
{
writeByte(*gameState++);
if (--size == 0) break;
}
while ((uint8_t)++addr); // write bytes until end of a page
disable(); // start writing the (partial) page
waitWhileBusy(); // wait for page write to complete
}
#endif
}
void FX::eraseSaveBlock(uint16_t page)
{
@ -1062,7 +1290,6 @@ void FX::drawNumber(uint16_t n, int8_t digits)
void FX::drawNumber(int32_t n, int8_t digits)
{
asm volatile("dbg:\n");
if (n < 0)
{
n = -n;

View File

@ -231,7 +231,7 @@ class FX
static void seekDataArray(uint24_t address, uint8_t index, uint8_t offset, uint8_t elementSize);
static void seekSave(uint24_t address); // selects flashaddress of program save area for reading and starts the first read
static void seekSave(uint24_t address) __attribute__ ((noinline)); // selects flashaddress of program save area for reading and starts the first read
static inline uint8_t readUnsafe() __attribute__((always_inline)) // read flash data without performing any checks and starts the next read.
{
@ -273,7 +273,11 @@ class FX
static void readSaveBytes(uint24_t address, uint8_t* buffer, size_t length);
static void eraseSaveBlock(uint16_t page);
static uint8_t loadGameState(uint8_t* gameState, size_t size) __attribute__ ((noinline)); //loads GameState from program exclusive 4K save data block.
static void saveGameState(uint8_t* gameState, size_t size) __attribute__ ((noinline)); // Saves GameState in RAM to programes exclusive 4K save data block.
static void eraseSaveBlock(uint16_t page); // erases 4K flash block
static void writeSavePage(uint16_t page, uint8_t* buffer);