Main Page | Namespace List | Class List | Directories | File List | Namespace Members | Class Members | File Members

Password.cc

Go to the documentation of this file.
00001 /*
00002  * Metroid Password Generator
00003  * Copyright (C) 2005 emuWorks
00004  * http://games.technoplaza.net/
00005  *
00006  * This file is part of Metroid Password Generator.
00007  *
00008  * Metroid Password Generator is free software; you can redistribute it and/or
00009  * modify it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation; either version 2 of the License, or
00011  * (at your option) any later version.
00012  *
00013  * Metroid Password Generator is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016  * GNU General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU General Public License
00019  * along with Metroid Password Generator; if not, write to the Free Software
00020  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00021  */
00022  
00023 // $Id: Password.cc,v 1.10 2005/09/27 09:32:14 technoplaza Exp $
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                                       "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     // reencode just in case the checksum was fixed
00053     encode();
00054 }
00055 
00056 bool Password::getBit(int bit) const throw(std::out_of_range) {
00057     if ((bit < 0) || (bit > PASSWORD_BITS)) {
00058         throw std::out_of_range("invalid bit: must be in range [0, 127]");
00059     }
00060     
00061     int byte = bit / 8;
00062     
00063     return (data[byte] & (1 << (bit % 8)));
00064 }
00065 
00066 void Password::setBit(int bit, bool value) throw(std::out_of_range) {
00067     if ((bit < 0) || (bit > PASSWORD_BITS)) {
00068         throw std::out_of_range("invalid bit: must be in range [0, 127]");
00069     }
00070     
00071     int byte = bit / 8;
00072     
00073     if (value) {
00074         data[byte] |= (1 << (bit % 8));
00075     } else {
00076         data[byte] &= ~(1 << (bit % 8));
00077     }
00078     
00079     encode();
00080 }
00081 
00082 wxUint32 Password::getGameTime() const {
00083     const wxUint32 *ptr = reinterpret_cast<const wxUint32 *>(data +
00084                                                              GAME_TIME_BYTE);
00085     
00086     return wxUINT32_SWAP_ON_BE(*ptr);
00087 }
00088 
00089 void Password::setGameTime(wxUint32 time) {
00090     wxUint32 *ptr = reinterpret_cast<wxUint32 *>(data + GAME_TIME_BYTE);
00091     *ptr = wxUINT32_SWAP_ON_BE(time);
00092     
00093     encode();
00094 }
00095 
00096 void Password::setMissiles(unsigned char missiles) {
00097     data[MISSILE_COUNT_BYTE] = missiles;
00098     
00099     encode();
00100 }
00101 
00102 void Password::setShift(unsigned char shift) {
00103     data[SHIFT_BYTE] = shift;
00104     
00105     encode();
00106 }
00107 
00108 unsigned char Password::calcChecksum() const {
00109     unsigned char checksum = 0;
00110     
00111     for (int i = 16; i >= 0; --i) {
00112         checksum += data[i];
00113     }
00114     
00115     return checksum;
00116 }
00117 
00118 void Password::decode(const wxString &password, bool fixChecksum)
00119                       throw(InvalidPasswordException) {
00120     // convert the password string to the metroid alphabet
00121     unsigned char metroid[PASSWORD_LENGTH];
00122     
00123     for (unsigned int i = 0; i < PASSWORD_LENGTH; ++i) {
00124         if (password[i] == wxT(' ')) {
00125             metroid[i] = SPACE_VALUE;
00126         } else {
00127             int pos = ALPHABET.Find(password[i]);
00128             
00129             if (pos < 0) {
00130                 throw InvalidPasswordException("Invalid Character in Password",
00131                                                INVALID_ALPHABET);
00132             }
00133             
00134             metroid[i] = pos;
00135         }
00136     }
00137     
00138     // convert metroid password to encoded password data
00139     unsigned char *ptr = data;
00140     
00141     for (int i = 0; i < 6; ++i) {
00142         unsigned char *temp = metroid + (i * 4);
00143         
00144         *ptr = (*temp << 2) | (*(temp + 1) >> 4);
00145         ++ptr;
00146         
00147         *ptr = (*(temp + 1) << 4) | (*(temp + 2) >> 2);
00148         ++ptr;
00149         
00150         *ptr = (*(temp + 2) << 6) | *(temp + 3);
00151         ++ptr;
00152     }
00153     
00154     // decode the password data
00155     short carry = 1, carryTemp;
00156     int count = data[SHIFT_BYTE];
00157     
00158     for (int i = 0; i < count; ++i) {
00159         unsigned char temp = data[15];
00160         
00161         for (int j = 15; j >= 0; --j) {
00162             carryTemp = (data[j] & 0x80) >> 7;
00163             data[j] <<= 1;
00164             data[j] |= (carry & 0x1);
00165             carry = carryTemp;
00166         }
00167         
00168         carryTemp = (temp & 0x80) >> 7;
00169         temp <<= 1;
00170         temp |= (carry & 0x1);
00171         carry = carryTemp;
00172         
00173         data[15] = temp;
00174     }
00175     
00176     // confirm the checksum and fix if requested
00177     unsigned char checksum = calcChecksum();
00178     
00179     if (data[CHECKSUM_BYTE] != checksum) {
00180         if (!fixChecksum) {
00181             throw InvalidPasswordException("Checksum Verification Failed",
00182                                            INVALID_CHECKSUM);
00183         }
00184     }
00185 }
00186 
00187 void Password::encode() {
00188     // calculate the checksum
00189     data[CHECKSUM_BYTE] = calcChecksum();
00190     
00191     // copy the raw password data
00192     unsigned char raw[PASSWORD_LENGTH_BYTES];
00193     std::memcpy(raw, data, PASSWORD_LENGTH_BYTES);
00194     
00195     // encode the password data
00196     short carry = 1, carryTemp;
00197     int count = raw[SHIFT_BYTE];
00198     
00199     for (int i = 0; i < count; ++i) {
00200         unsigned char temp = *raw;
00201         
00202         for (int j = 0; j < 16; ++j) {
00203             carryTemp = raw[j] & 0x1;
00204             raw[j] >>= 1;
00205             raw[j] |= (carry & 0x1) << 7;
00206             carry = carryTemp;
00207         }
00208         
00209         carryTemp = temp & 0x1;
00210         temp >>= 1;
00211         temp |= (carry & 0x1) << 7;
00212         carry = carryTemp;
00213         
00214         *raw = temp;
00215     }
00216     
00217     // convert it to the metroid alphabet
00218     unsigned char metroid[PASSWORD_LENGTH];
00219     unsigned char *ptr = metroid;
00220     
00221     for (int i = 0; i < 6; ++i) {
00222         unsigned char *temp = raw + (i * 3);
00223         
00224         *ptr = *temp >> 2;
00225         ++ptr;
00226         
00227         *ptr = ((*temp & 0x3) << 4) | (*(temp + 1) >> 4);
00228         ++ptr;
00229         
00230         *ptr = ((*(temp + 1) & 0xF) << 2) | (*(temp + 2) >> 6);
00231         ++ptr;
00232         
00233         *ptr = (*(temp + 2) & 0x3F);
00234         ++ptr;
00235     }
00236     
00237     // convert metroid password to wxString
00238     encoded.Empty();
00239     
00240     for (unsigned int i = 0; i < PASSWORD_LENGTH; ++i) {
00241         encoded.Append(ALPHABET[metroid[i]]);
00242     }
00243 }
00244 

Generated on Fri Sep 30 04:56:20 2005 for Metroid Password Generator by  doxygen 1.4.2