00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #ifdef HAVE_CONFIG_H
00026 #include <config.h>
00027 #endif
00028
00029 #include <cstring>
00030
00031 #include "model/Password.hh"
00032
00033 using namespace mpg;
00034
00035 const wxString Password::ALPHABET(wxT("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ")
00036 wxT("abcdefghijklmnopqrstuvwxyz?- "));
00037
00038 Password::Password() {
00039 std::memset(data, 0, PASSWORD_LENGTH_BYTES);
00040 encode();
00041 }
00042
00043 Password::Password(const wxString &password, bool fixChecksum)
00044 throw(InvalidPasswordException) {
00045 if (password.Length() != PASSWORD_LENGTH) {
00046 throw InvalidPasswordException("Invalid Password Length",
00047 INVALID_LENGTH);
00048 }
00049
00050 decode(password, fixChecksum);
00051
00052
00053 encode();
00054 }
00055
00056 bool Password::getBit(int bit) const {
00057 wxASSERT((bit >= 0) && (bit < PASSWORD_BITS));
00058
00059 int byte = bit / 8;
00060
00061 return (data[byte] & (1 << (bit % 8)));
00062 }
00063
00064 void Password::setBit(int bit, bool value) {
00065 wxASSERT((bit >= 0) && (bit < PASSWORD_BITS));
00066
00067 int byte = bit / 8;
00068
00069 if (value) {
00070 data[byte] |= (1 << (bit % 8));
00071 } else {
00072 data[byte] &= ~(1 << (bit % 8));
00073 }
00074
00075 encode();
00076 }
00077
00078 wxUint32 Password::getGameTime() const {
00079 const wxUint32 *ptr = reinterpret_cast<const wxUint32 *>(data +
00080 GAME_TIME_BYTE);
00081
00082 return wxUINT32_SWAP_ON_BE(*ptr);
00083 }
00084
00085 void Password::setGameTime(wxUint32 time) {
00086 wxUint32 *ptr = reinterpret_cast<wxUint32 *>(data + GAME_TIME_BYTE);
00087 *ptr = wxUINT32_SWAP_ON_BE(time);
00088
00089 encode();
00090 }
00091
00092 void Password::setMissiles(unsigned char missiles) {
00093 data[MISSILE_COUNT_BYTE] = missiles;
00094
00095 encode();
00096 }
00097
00098 void Password::setShift(unsigned char shift) {
00099 data[SHIFT_BYTE] = shift;
00100
00101 encode();
00102 }
00103
00104 unsigned char Password::calcChecksum() const {
00105 unsigned char checksum = 0;
00106
00107 for (int i = 16; i >= 0; --i) {
00108 checksum += data[i];
00109 }
00110
00111 return checksum;
00112 }
00113
00114 void Password::decode(const wxString &password, bool fixChecksum)
00115 throw(InvalidPasswordException) {
00116
00117 unsigned char metroid[PASSWORD_LENGTH];
00118
00119 for (unsigned int i = 0; i < PASSWORD_LENGTH; ++i) {
00120 if (password[i] == wxT(' ')) {
00121 metroid[i] = SPACE_VALUE;
00122 } else {
00123 int pos = ALPHABET.Find(password[i]);
00124
00125 if (pos < 0) {
00126 throw InvalidPasswordException("Invalid Character in Password",
00127 INVALID_ALPHABET);
00128 }
00129
00130 metroid[i] = pos;
00131 }
00132 }
00133
00134
00135 unsigned char *ptr = data;
00136
00137 for (int i = 0; i < 6; ++i) {
00138 unsigned char *temp = metroid + (i * 4);
00139
00140 *ptr = (*temp << 2) | (*(temp + 1) >> 4);
00141 ++ptr;
00142
00143 *ptr = (*(temp + 1) << 4) | (*(temp + 2) >> 2);
00144 ++ptr;
00145
00146 *ptr = (*(temp + 2) << 6) | *(temp + 3);
00147 ++ptr;
00148 }
00149
00150
00151 short carry = 1, carryTemp;
00152 int count = data[SHIFT_BYTE];
00153
00154 for (int i = 0; i < count; ++i) {
00155 unsigned char temp = data[15];
00156
00157 for (int j = 15; j >= 0; --j) {
00158 carryTemp = (data[j] & 0x80) >> 7;
00159 data[j] <<= 1;
00160 data[j] |= (carry & 0x1);
00161 carry = carryTemp;
00162 }
00163
00164 carryTemp = (temp & 0x80) >> 7;
00165 temp <<= 1;
00166 temp |= (carry & 0x1);
00167 carry = carryTemp;
00168
00169 data[15] = temp;
00170 }
00171
00172
00173 unsigned char checksum = calcChecksum();
00174
00175 if (data[CHECKSUM_BYTE] != checksum) {
00176 if (!fixChecksum) {
00177 throw InvalidPasswordException("Checksum Verification Failed",
00178 INVALID_CHECKSUM);
00179 }
00180 }
00181 }
00182
00183 void Password::encode() {
00184
00185 data[CHECKSUM_BYTE] = calcChecksum();
00186
00187
00188 unsigned char raw[PASSWORD_LENGTH_BYTES];
00189 std::memcpy(raw, data, PASSWORD_LENGTH_BYTES);
00190
00191
00192 short carry = 1, carryTemp;
00193 int count = raw[SHIFT_BYTE];
00194
00195 for (int i = 0; i < count; ++i) {
00196 unsigned char temp = *raw;
00197
00198 for (int j = 0; j < 16; ++j) {
00199 carryTemp = raw[j] & 0x1;
00200 raw[j] >>= 1;
00201 raw[j] |= (carry & 0x1) << 7;
00202 carry = carryTemp;
00203 }
00204
00205 carryTemp = temp & 0x1;
00206 temp >>= 1;
00207 temp |= (carry & 0x1) << 7;
00208 carry = carryTemp;
00209
00210 *raw = temp;
00211 }
00212
00213
00214 unsigned char metroid[PASSWORD_LENGTH];
00215 unsigned char *ptr = metroid;
00216
00217 for (int i = 0; i < 6; ++i) {
00218 unsigned char *temp = raw + (i * 3);
00219
00220 *ptr = *temp >> 2;
00221 ++ptr;
00222
00223 *ptr = ((*temp & 0x3) << 4) | (*(temp + 1) >> 4);
00224 ++ptr;
00225
00226 *ptr = ((*(temp + 1) & 0xF) << 2) | (*(temp + 2) >> 6);
00227 ++ptr;
00228
00229 *ptr = (*(temp + 2) & 0x3F);
00230 ++ptr;
00231 }
00232
00233
00234 encoded.Empty();
00235
00236 for (unsigned int i = 0; i < PASSWORD_LENGTH; ++i) {
00237 encoded.Append(ALPHABET[metroid[i]]);
00238 }
00239 }
00240