DOOM64-RE

DOOM 64 Reverse Engineering
Log | Files | Refs | README | LICENSE

m_password.c (16436B)


      1 /* m_password.c -- password (encode/decode) and menu password routines */
      2 
      3 #include "doomdef.h"
      4 #include "p_local.h"
      5 #include "st_main.h"
      6 #include "r_local.h"
      7 
      8 char *passwordChar = "bcdfghjklmnpqrstvwxyz0123456789?";    // 8005AC60
      9 int passwordTable[10] = { 1, 8, 9, 5, 6, 2, 7, 0, 4, 3 };   // 8005AC80
     10 
     11 char *hectic_demo = "rvnh3ct1cd3m0???"; // 8005ACA8
     12 boolean run_hectic_demo = false;        // 8005A7A0
     13 
     14 byte Passwordbuff[16];  // 800A55B0
     15 int PassCodePos;        // 800A55C0
     16 int PassInvalidTic;     // 800A55C4
     17 
     18 boolean doPassword = false; // 8005A7A0
     19 int CurPasswordSlot = 0;    // 8005ACBC
     20 
     21 char *passFeatures = "3n4bl3f34tvr3s??"; // New Pass Code By [GEC]
     22 
     23 // [GEC] NEW FLAGS
     24 #define NIGHTMARE	0x40
     25 
     26 void M_EncodePassword(byte *buff) // 8000BC10
     27 {
     28     byte encode[10];
     29     int i;
     30     int bit;
     31     short decodebit[3];
     32     int passBit;
     33     int xbit1, xbit2, xbit3;
     34     int maxclip, maxshell, maxcell, maxmisl;
     35     player_t* player;
     36 
     37     #if ENABLE_NIGHTMARE == 1
     38 	int skillnightmare;
     39 	#endif // ENABLE_NIGHTMARE
     40 
     41     player = &players[0];
     42     D_memset(encode, 0, sizeof(encode));
     43 
     44     #if ENABLE_NIGHTMARE == 1
     45 	//Check the nightmare difficulty
     46 	skillnightmare = 0;
     47 	if(gameskill == sk_nightmare)
     48     {
     49         skillnightmare = sk_nightmare;
     50     }
     51     #endif // ENABLE_NIGHTMARE
     52 
     53     //
     54     // Map and Skill
     55     //
     56     encode[0] = ((((nextmap & 63) << 2) & 0xff) | (gameskill & 3));
     57 
     58     //
     59     // Weapons
     60     //
     61     bit = 0;
     62     for(i = 0; i < NUMWEAPONS; i++)
     63     {
     64         if(i != wp_fist && i != wp_pistol)
     65         {
     66             if(player->weaponowned[i])
     67             {
     68                 encode[1] |= (1 << bit);
     69                 encode[1] = encode[1] & 0xff;
     70             }
     71 
     72             bit++;
     73         }
     74     }
     75 
     76     //
     77     // Get Maximun Ammo
     78     //
     79 	maxclip = maxammo[am_clip];
     80 	maxshell = maxammo[am_shell];
     81 	maxcell = maxammo[am_cell];
     82 	maxmisl = maxammo[am_misl];
     83 
     84 	//
     85     // Backpack
     86     //
     87     if(player->backpack)
     88     {
     89         maxclip <<= 1;
     90 		maxshell <<= 1;
     91 		maxcell <<= 1;
     92 		maxmisl <<= 1;
     93         encode[5] |= 0x80;
     94     }
     95 
     96     //
     97     // Clip
     98     //
     99     bit = (player->ammo[am_clip] << 3) / maxclip;
    100 	if ((player->ammo[am_clip] << 3) % maxclip) { bit += 1; }
    101 	encode[2] = bit << 4;
    102 
    103 	//
    104 	// Shell
    105 	//
    106 	bit = (player->ammo[am_shell] << 3) / maxshell;
    107 	if ((player->ammo[am_shell] << 3) % maxshell) { bit += 1; }
    108 	encode[2] |= bit;
    109 
    110 	//
    111 	// Cell
    112 	//
    113 	bit = (player->ammo[am_cell] << 3) / maxcell;
    114 	if ((player->ammo[am_cell] << 3) % maxcell) { bit += 1; }
    115 	encode[3] = bit << 4;
    116 
    117 	//
    118 	// Missile
    119 	//
    120 	bit = (player->ammo[am_misl] << 3) / maxmisl;
    121 	if ((player->ammo[am_misl] << 3) % maxmisl) { bit += 1; }
    122 	encode[3] |= bit;
    123 
    124 	//
    125 	// Health
    126 	//
    127 	bit = (player->health << 3) / 200;
    128 	if ((player->health << 3) % 200) { bit += 1; }
    129 	encode[4] = bit << 4;
    130 
    131 	//
    132 	// Armor
    133 	//
    134 	bit = (player->armorpoints << 3) / 200;
    135 	if ((player->armorpoints << 3) % 200) { bit += 1; }
    136 	encode[4] |= bit;
    137 
    138 	//
    139     // ArmorType
    140     //
    141     encode[5] |= player->armortype;
    142 
    143     //
    144     // Artifacts
    145     //
    146     encode[5] |= (player->artifacts << 2);
    147 
    148     #if ENABLE_NIGHTMARE == 1
    149 	//I used the ArmorType space to add the 0x40 flag to identify that the difficulty is nightmare
    150 	if(skillnightmare != 0) {
    151         encode[5] |= NIGHTMARE;
    152     }
    153     #endif // ENABLE_NIGHTMARE
    154 
    155     decodebit[0] = (*(short*)&encode[0]);
    156     decodebit[1] = (*(short*)&encode[2]);
    157     decodebit[2] = (*(short*)&encode[4]);
    158 
    159     *(short*)&encode[6] = (~(decodebit[0] + decodebit[1] + decodebit[2]));
    160     *(short*)&encode[8] = (~(decodebit[0] ^ decodebit[1] ^ decodebit[2]));
    161 
    162     for(i = 0; i < 10; i++)
    163     {
    164         bit = encode[passwordTable[i]];
    165         encode[i] = (encode[i] ^ bit);
    166     }
    167 
    168     bit = 0;
    169 
    170     while(bit < 80)
    171     {
    172         passBit = 0;
    173 
    174         if(bit < 0) {
    175             xbit2 = (bit + 7) >> 3;
    176         }
    177         else {
    178             xbit2 = bit >> 3;
    179         }
    180 
    181         xbit3 = (bit & 7);
    182 
    183         if(bit < 0)
    184         {
    185             if(xbit3 != 0) {
    186                 xbit3 -= 8;
    187             }
    188         }
    189 
    190         if((encode[xbit2] & (0x80 >> xbit3)))
    191         {
    192             passBit = 16;
    193         }
    194 
    195         xbit1 = 8;
    196         bit++;
    197 
    198         for(i = 0; i < 4; i++)
    199         {
    200             if(bit < 0) {
    201                 xbit2 = (bit + 7) >> 3;
    202             }
    203             else {
    204                 xbit2 = bit >> 3;
    205             }
    206 
    207             xbit3 = (bit & 7);
    208 
    209             if(bit < 0)
    210             {
    211                 if(xbit3 != 0) {
    212                     xbit3 -= 8;
    213                 }
    214             }
    215 
    216             if((encode[xbit2] & (0x80 >> xbit3)))
    217             {
    218                 passBit |= xbit1;
    219             }
    220 
    221             xbit1 >>= 1;
    222             bit++;
    223         }
    224 
    225         buff[((bit - 1) / 5)] = passBit;
    226     }
    227 }
    228 
    229 int M_DecodePassword(byte *inbuff, int *levelnum, int *skill, player_t *player) // 8000C194
    230 {
    231     byte data[16];
    232     byte decode[10];
    233     int bit;
    234     int i, j;
    235     short xbit1, xbit2, xbit3;
    236     short x, y;
    237     int passBit;
    238     int decodeBit;
    239     byte checkByte;
    240 
    241     D_memcpy(data, inbuff, 16);
    242 
    243     //
    244     // Decode Password
    245     //
    246     bit = 0;
    247 
    248     while(bit < 80)
    249     {
    250         passBit = 0;
    251         decodeBit = 0x80;
    252         checkByte = 0;
    253 
    254         i = 0;
    255 
    256         while(i != 8)
    257         {
    258             i += 4;
    259 
    260             for(j = 0; j < 4; j++)
    261             {
    262                 checkByte = data[bit / 5];
    263                 if((checkByte & (16 >> (bit % 5))))
    264                 {
    265                     passBit |= decodeBit;
    266                 }
    267 
    268                 bit++;
    269                 decodeBit >>= 1;
    270             }
    271         }
    272 
    273         if((bit - 1) >= 0)
    274         {
    275             checkByte = ((bit - 1) >> 3);
    276         }
    277         else
    278         {
    279             checkByte = (((bit - 1) + 7) >> 3);
    280         }
    281 
    282         decode[checkByte] = passBit;
    283     }
    284 
    285     for(i = 9; i >= 0; i--)
    286     {
    287         bit = decode[passwordTable[i]];
    288         decode[i] = (decode[i] ^ bit);
    289     }
    290 
    291     //
    292     // Verify Decoded Password
    293     //
    294 
    295     xbit1 = *(short*)&decode[0];
    296     xbit2 = *(short*)&decode[2];
    297     xbit3 = *(short*)&decode[4];
    298 
    299     x = ((~((xbit1 + xbit2) + xbit3) << 16) >> 16);
    300     y = *(short*)&decode[6];
    301 
    302     if(x != y)
    303     {
    304         return false;
    305     }
    306 
    307     x = ((~(xbit1 ^ (xbit2 ^ xbit3)) << 16) >> 16);
    308     y = *(short*)&decode[8];
    309 
    310     if(x != y)
    311     {
    312         return false;
    313     }
    314 
    315     //
    316     // Get Map
    317     //
    318     *levelnum = (decode[0] >> 2);
    319 
    320     //
    321     // Verify Map
    322     //
    323     if ((*levelnum == 0) || (*levelnum >= TOTALMAPS))
    324     {
    325         return false;
    326     }
    327 
    328     //
    329     // Get Skill
    330     //
    331     *skill = (decode[0] & 3);
    332 
    333     #if ENABLE_NIGHTMARE == 1
    334     //Check that the flag is 0x40, add the nightmare difficulty and remove the flag 0x80
    335     if (decode[5] & NIGHTMARE)
    336     {
    337         decode[5] &= ~NIGHTMARE;
    338         *skill = sk_nightmare;
    339     }
    340     #endif // ENABLE_NIGHTMARE
    341 
    342     //
    343     // Verify Skill
    344     //
    345     if(*skill > sk_nightmare)
    346     {
    347         return false;
    348     }
    349 
    350     //
    351     // Verify Ammo (Shell / Clip)
    352     //
    353     if((decode[2] & 0xf) >= 9 || (decode[2] >> 4) >= 9)
    354     {
    355         return false;
    356     }
    357 
    358     //
    359     // Verify Ammo (Missile / Cell)
    360     //
    361     if((decode[3] & 0xf) >= 9 || (decode[3] >> 4) >= 9)
    362     {
    363         return false;
    364     }
    365 
    366     //
    367     // Verify (Armor / Health)
    368     //
    369     if((decode[4] & 0xf) >= 9 || (decode[4] >> 4) >= 9)
    370     {
    371         return false;
    372     }
    373 
    374     //
    375     // Verify Armortype
    376     //
    377     if((decode[5] & 3) >= 3)
    378     {
    379         return false;
    380     }
    381 
    382     bit = 0;
    383     if (player != 0)
    384     {
    385         //
    386         // Get Weapons
    387         //
    388         for(i = 0; i < NUMWEAPONS; i++)
    389         {
    390             if(i != wp_fist && i != wp_pistol)
    391             {
    392                 if(decode[1] & (1 << bit))
    393                 {
    394                     player->weaponowned[i] = true;
    395                 }
    396 
    397                 bit++;
    398             }
    399         }
    400 
    401         //
    402         // Get Backpack
    403         //
    404         if(decode[5] & 0x80)
    405         {
    406             if (!player->backpack)
    407             {
    408                 player->backpack = true;
    409                 player->maxammo[am_clip]    = (maxammo[am_clip] << 1);
    410                 player->maxammo[am_shell]   = (maxammo[am_shell] << 1);
    411                 player->maxammo[am_cell]    = (maxammo[am_cell] << 1);
    412                 player->maxammo[am_misl]    = (maxammo[am_misl] << 1);
    413             }
    414         }
    415 
    416         //
    417         // Get Clip
    418         //
    419         bit = (decode[2] >> 4) * player->maxammo[am_clip];
    420         if (bit < 0) { bit += 7; }
    421         player->ammo[am_clip] = bit >> 3;
    422 
    423         //
    424         // Get Shell
    425         //
    426         bit = (decode[2] & 0xf) * player->maxammo[am_shell];
    427         if (bit < 0) { bit += 7; }
    428         player->ammo[am_shell] = bit >> 3;
    429 
    430         //
    431         // Get Cell
    432         //
    433         bit = (decode[3] >> 4) * player->maxammo[am_cell];
    434         if (bit < 0) { bit += 7; }
    435         player->ammo[am_cell] = bit >> 3;
    436 
    437         //
    438         // Get Missile
    439         //
    440         bit = (decode[3] & 0xf) * player->maxammo[am_misl];
    441         if (bit < 0) { bit += 7; }
    442         player->ammo[am_misl] = bit >> 3;
    443 
    444         //
    445         // Get Health
    446         //
    447         bit = (decode[4] >> 4) * 200;
    448         if (bit < 0) { bit += 7; }
    449         player->health = bit >> 3;
    450 
    451         //
    452         // Get Armor
    453         //
    454         bit = (decode[4] & 0xf) * 200;
    455         if (bit < 0) { bit += 7; }
    456         player->armorpoints = bit >> 3;
    457 
    458         //
    459         // Get Armor Type
    460         //
    461         player->armortype = (decode[5] & 3);
    462 
    463         //
    464         // Get Artifacts
    465         //
    466         player->artifacts = ((decode[5] >> 2) & 7);
    467 
    468         //
    469         // Apply Health on mobj_t
    470         //
    471         player->mo->health = player->health;
    472 
    473         //
    474         // Set Cheat Menu If Password Leads To Map 01
    475         //
    476         if((decode[0] >> 2) == 1)
    477         {
    478             FeaturesUnlocked = true;
    479         }
    480     }
    481 
    482     return true;
    483 }
    484 
    485 void M_PasswordStart(void) // 8000C710
    486 {
    487     PassInvalidTic = 0;
    488     PassCodePos = 0;
    489     last_ticon = 0;
    490     M_FadeInStart();
    491 }
    492 
    493 void M_PasswordStop(void) // 8000C744
    494 {
    495     S_StartSound(NULL, sfx_pistol);
    496     M_FadeOutStart(8);
    497 }
    498 
    499 int M_PasswordTicker(void) // 8000C774
    500 {
    501     byte *passbuf;
    502     char *hpassbuf;
    503     char *fpassbuf;
    504     unsigned int buttons;
    505     unsigned int oldbuttons;
    506     boolean playsound;
    507     int exit;
    508     int skill;
    509     int levelnum;
    510 
    511     if (last_ticon)
    512     {
    513         if ((ticon - last_ticon) < 16)
    514             exit = ga_nothing;
    515         else
    516             exit = ga_warped;
    517 
    518         return exit;
    519     }
    520 
    521     if (PassInvalidTic)
    522     {
    523         if((gametic & 1U) == 0)
    524         {
    525             PassInvalidTic -= 1;
    526             if((PassInvalidTic & 7) == 4) {
    527                 S_StartSound(NULL, sfx_itemup);
    528             }
    529         }
    530     }
    531 
    532     buttons = M_ButtonResponder(ticbuttons[0]);
    533     oldbuttons = oldticbuttons[0] & 0xffff0000;
    534 
    535     if (!(buttons & (ALL_TRIG|PAD_A|PAD_B|ALL_JPAD)))
    536     {
    537         m_vframe1 = 0;
    538     }
    539     else
    540     {
    541         m_vframe1 -= vblsinframe[0];
    542 
    543         if (m_vframe1 <= 0)
    544         {
    545             m_vframe1 = 0xf; // TICRATE / 2
    546 
    547             playsound = false;
    548 
    549             if (buttons & PAD_UP)
    550             {
    551                 if (PassCodePos > 7)
    552                 {
    553                     playsound = true;
    554                     PassCodePos -= 8;
    555                 }
    556             }
    557             if ((buttons & PAD_DOWN) && (PassCodePos < 24))
    558             {
    559                 playsound = true;
    560                 PassCodePos += 8;
    561             }
    562 
    563             if (buttons & PAD_LEFT)
    564             {
    565                 if (PassCodePos > 0)
    566                 {
    567                     playsound = true;
    568                     PassCodePos -= 1;
    569                 }
    570             }
    571             else if ((buttons & PAD_RIGHT) && (PassCodePos < 31))
    572             {
    573                 playsound = true;
    574                 PassCodePos += 1;
    575             }
    576 
    577             if (playsound)
    578             {
    579                 S_StartSound(NULL, sfx_switch1);
    580             }
    581         }
    582     }
    583 
    584     if (buttons == oldbuttons)
    585     {
    586         exit = ga_nothing;
    587     }
    588     else
    589     {
    590         if (buttons & PAD_START)
    591         {
    592             exit = ga_exit;
    593         }
    594         else
    595         {
    596             if (!(buttons & (ALL_TRIG|PAD_A|PAD_B|PAD_UP_C|PAD_DOWN_C|PAD_RIGHT_C)))
    597             {
    598                 if (buttons & PAD_LEFT_C)
    599                 {
    600                     S_StartSound(0, sfx_switch2);
    601 
    602                     CurPasswordSlot -= 1;
    603                     if (CurPasswordSlot < 0)
    604                         CurPasswordSlot = 0;
    605 
    606                     Passwordbuff[CurPasswordSlot] = 0;
    607                 }
    608             }
    609             else
    610             {
    611                 S_StartSound(0, sfx_switch2);
    612 
    613                 if (CurPasswordSlot < 16)
    614                 {
    615                     Passwordbuff[CurPasswordSlot] = (byte)PassCodePos;
    616                     CurPasswordSlot += 1;
    617                 }
    618 
    619                 if (CurPasswordSlot > 15)
    620                 {
    621                     hpassbuf = hectic_demo;
    622                     passbuf = Passwordbuff;
    623                     do
    624                     {
    625                         if (passwordChar[*passbuf++] != *hpassbuf++)
    626                             break;
    627 
    628                     } while (hpassbuf != (hectic_demo + 16));
    629 
    630                     if ((hectic_demo + 15) < hpassbuf)
    631                     {
    632                         run_hectic_demo = true;
    633                         return ga_exit;
    634                     }
    635 
    636                     // [GEC] New Password Code Enable Features Menu.
    637                     fpassbuf = passFeatures;
    638                     passbuf = Passwordbuff;
    639                     do
    640                     {
    641                         if (passwordChar[*passbuf++] != *fpassbuf++)
    642                             break;
    643 
    644                     } while (fpassbuf != (passFeatures + 16));
    645 
    646                     if ((passFeatures + 15) < fpassbuf)
    647                     {
    648                         FeaturesUnlocked = true;
    649                         return ga_exit;
    650                     }
    651 
    652                     if (M_DecodePassword(Passwordbuff, &levelnum, &skill, NULL) == 0)
    653                     {
    654                         PassInvalidTic = 16;
    655                     }
    656                     else
    657                     {
    658                         doPassword = true;
    659                         startmap = gamemap = levelnum;
    660                         startskill = gameskill = skill;
    661                         last_ticon = ticon;
    662                     }
    663                 }
    664             }
    665 
    666             exit = ga_nothing;
    667         }
    668     }
    669 
    670     return exit;
    671 }
    672 
    673 void M_PasswordDrawer(void) // 8000CAF0
    674 {
    675     byte    pass[2];
    676     byte    c;
    677     int     texid, cnt;
    678     int     xpos, ypos, pos1;
    679 
    680     ST_DrawString(-1, 20, "Password", text_alpha | 0xc0000000);
    681 
    682     for(cnt = 0; cnt < 32; cnt++)
    683     {
    684         pos1 = cnt;
    685         if (cnt < 0) {
    686             pos1 = cnt + 7;
    687         }
    688         pos1 >>= 3;
    689         ypos = (pos1 * 20) + 60;
    690 
    691         if ((cnt == PassCodePos) && (ticon & 8))
    692             continue;
    693 
    694         c = passwordChar[cnt];
    695         if ((byte)(c - 'a') < 26)
    696         {
    697             texid = (byte)(c - 55);
    698             ypos = (pos1 * 20) + 63;
    699         }
    700         else if ((byte)(c - '0') < 10)
    701         {
    702             texid = (byte)(c - '0');
    703         }
    704         else if (c == '?')
    705         {
    706             texid = 14;
    707         }
    708 
    709         pos1 = cnt & 7;
    710         if ((cnt < 0) && (pos1 != 0)) {
    711             pos1 -= 8;
    712         }
    713         xpos = (pos1 * 20) + 84;
    714 
    715         ST_DrawSymbol(xpos, ypos, texid, text_alpha | 0xc0000000);
    716     }
    717 
    718     cnt = PassCodePos;
    719 
    720     pos1 = cnt & 7;
    721     if ((cnt < 0) && (pos1 != 0)) {
    722         pos1 -= 8;
    723     }
    724     xpos = (pos1 * 20) + 80;
    725 
    726     pos1 = cnt;
    727     if (pos1 < 0) {
    728         pos1 = cnt + 7;
    729     }
    730     pos1 >>= 3;
    731     ypos = (pos1 * 20) + 59;
    732 
    733     ST_DrawSymbol(xpos, ypos, 79, text_alpha | 0xffffff00);
    734 
    735     xpos = 47;
    736     cnt = 0;
    737     if ((PassInvalidTic & 4) == 0)
    738     {
    739         pass[1] = '\0';
    740         do
    741         {
    742             if ((cnt & 3) == 0) {
    743                 xpos += 6;
    744             }
    745 
    746             if (cnt < CurPasswordSlot) {
    747                 pass[0] = passwordChar[Passwordbuff[cnt]];
    748             }
    749             else {
    750                 pass[0] = '.';
    751             }
    752 
    753             ST_DrawString(xpos, 160, pass, text_alpha | 0xc0000000);
    754 
    755             xpos += 13;
    756             cnt += 1;
    757         } while (cnt != 16);
    758     }
    759     else
    760     {
    761         ST_DrawString(-1, 160, "Invalid Password", text_alpha | 0xffffff00);
    762     }
    763 
    764     ST_DrawString(-1,195, "press \x8d to exit", text_alpha | 0xffffff00);
    765     ST_DrawString(-1,210, "press \x84 to change", text_alpha | 0xffffff00);
    766 }