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 }