REM     The Standart GNU Personal Cracker.
REM     Copyright (C) Sandul Yura Valentinovich.
REM     (R) Wednesday, 5 March 2003 year.
REM     This program is free software; you can redistribute it and/or modify
REM it under the terms of the GNU General Public License as published by the
REM Free Software Foundation; either version 2 of the License, or (at your
REM option) any later version.
REM     This program is distributed in the hope that it will be useful, but
REM WITHOUT ANY WARRANTY; without even the implied warranty of
REM MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
REM Public License for more details.
REM     You should have received a copy of the GNU General Public License
REM along with this program; if not, write to the Free Software Foundation,
REM Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
REM
REM $DYNAMIC
DECLARE SUB ScratchScreen ()
DECLARE SUB OutBox (Title$, Message$)
DECLARE SUB MakeBox (BoxColumn%, BoxRow%, BoxWidth%, BoxHeight%)
DECLARE SUB SecondsToDateAndTime (SecondsCount#, HourValue%, MinuteValue%, SecondValue%, DayValue%, MonthValue%, YearValue%, DayOfWeekValue%)
DECLARE FUNCTION DateAndTimeToSeconds# (HourValue%, MinuteValue%, SecondValue%, DayValue%, MonthValue%, YearValue%)
DECLARE FUNCTION DayName$ (DayNumber%)
DECLARE FUNCTION DayOfWeek% (DayValue%, MonthValue%, YearValue%)
DECLARE FUNCTION DayOfWeekName$ (DayValue%, MonthValue%, YearValue%)
DECLARE FUNCTION DaysCount& (DayValue%, MonthValue%, YearValue%)
DECLARE FUNCTION InputBox% (Title$, Message$, InputTextLine$)
DECLARE FUNCTION IsLeapYear% (YearValue%)
DECLARE FUNCTION MenuBox% (ItemsCount%)
DECLARE FUNCTION MessageBox% (Title$, Message$)
DECLARE FUNCTION MonthDays% (MonthValue%, YearValue%)
DECLARE FUNCTION MonthDaysCount% (MonthValue%, YearValue%)
DECLARE FUNCTION MonthName$ (MonthNumber%)
OPTION BASE 1
CONST False% = 0
CONST True% = NOT False%
DIM SHARED MenuItems$(4)
DIM StartDate$
DIM StartTime$
DIM CurrentDate$
DIM CurrentTime$
DIM OldFilePosition&
DIM OldSecond%
DIM ExitCode%
DIM WorkHourValue%
DIM WorkMinuteValue%
DIM WorkSecondValue%
DIM WorkDayValue%
DIM WorkMonthValue%
DIM WorkYearValue%
DIM WorkDayOfWeekValue%
DIM ProgramFileName$
DIM CrackFileName$
DIM Differencies&
DIM Address&
DIM FirstByte%
DIM SecondByte%
DIM WorkLine$
SCREEN 0, 1, 0, 0
ProgramFileName$ = "Program.exe"
CrackFileName$ = "Program.crk"
DO
 CALL ScratchScreen
 MenuItems$(1) = "Change program file name (" + ProgramFileName$ + ".)."
 MenuItems$(2) = "Change crack file name (" + CrackFileName$ + ".)."
 MenuItems$(3) = "Crack!"
 MenuItems$(4) = "Quit."
 SELECT CASE MenuBox%(4)
 CASE 0
   EXIT DO
 CASE 1
   CALL ScratchScreen
   WorkLine$ = ""
   IF InputBox%("Cracker.", "Please enter program file name.", WorkLine$) THEN
    CALL ScratchScreen
    WorkLine$ = UCASE$(LEFT$(LTRIM$(RTRIM$(WorkLine$)), 1)) + LCASE$(MID$(LTRIM$(RTRIM$(WorkLine$)), 2))
    IF (WorkLine$ = "") OR (LEN(WorkLine$) > 12) OR (INSTR(WorkLine$, ":") > 0) OR (INSTR(WorkLine$, "/") > 0) OR (INSTR(WorkLine$, "\") > 0) OR (INSTR(WorkLine$, "?") > 0) OR (INSTR(WorkLine$, "*") > 0) THEN CALL OutBox("Cracker.", "You input the invalid file name.") ELSE ProgramFileName$ = WorkLine$
   END IF
 CASE 2
   CALL ScratchScreen
   WorkLine$ = ""
   IF InputBox%("Cracker.", "Please enter crack file name.", WorkLine$) THEN
    CALL ScratchScreen
    WorkLine$ = UCASE$(LEFT$(LTRIM$(RTRIM$(WorkLine$)), 1)) + LCASE$(MID$(LTRIM$(RTRIM$(WorkLine$)), 2))
    IF (WorkLine$ = "") OR (LEN(WorkLine$) > 12) OR (INSTR(WorkLine$, ":") > 0) OR (INSTR(WorkLine$, "/") > 0) OR (INSTR(WorkLine$, "\") > 0) OR (INSTR(WorkLine$, "?") > 0) OR (INSTR(WorkLine$, "*") > 0) THEN CALL OutBox("Cracker.", "You input the invalid file name.") ELSE CrackFileName$ = WorkLine$
   END IF
 CASE 3
   CALL ScratchScreen
   ON ERROR GOTO CannotOpenProgramFile
   OPEN ProgramFileName$ FOR RANDOM AS #1 LEN = 1
   ON ERROR GOTO CannotOpenCrackFile
   OPEN CrackFileName$ FOR INPUT AS #2
   ON ERROR GOTO 0
   FIELD #1, 1 AS ProgramFileData$
   StartDate$ = DATE$
   StartTime$ = TIME$
   OldFilePosition& = 0
   Differencies& = 0
   ExitCode% = 0
   OldSecond% = NOT VAL(MID$(StartTime$, 7, 2))
   ON ERROR GOTO CannotPreReadFromCrackFile
   LINE INPUT #2, WorkLine$
   ON ERROR GOTO 0
   IF WorkLine$ <> "Crack file." THEN
    CLOSE #1
    CLOSE #2
    CALL OutBox("Cracker.", "Invalid crack file.")
   ELSE
    ON ERROR GOTO CannotPreReadFromCrackFile
    LINE INPUT #2, WorkLine$
    ON ERROR GOTO 0
    IF (LEFT$(WorkLine$, 5) <> "File=") OR (RIGHT$(WorkLine$, 1) <> ".") OR (LEN(WorkLine$) < 7) OR (LEN(WorkLine$) > 18) THEN
     CLOSE #1
     CLOSE #2
     CALL OutBox("Cracker.", "Invalid crack file.")
    ELSE
     ON ERROR GOTO CannotPreReadFromCrackFile
     LINE INPUT #2, WorkLine$
     ON ERROR GOTO 0
     IF WorkLine$ <> STRING$(17, "=") THEN
      CLOSE #1
      CLOSE #2
      CALL OutBox("Cracker.", "Invalid crack file.")
     ELSE
      GOSUB OutStatusBox
      DO WHILE NOT EOF(2)
       GOSUB OutStatus
       IF INKEY$ = CHR$(27) THEN
        ExitCode% = 1
        EXIT DO
       END IF
       ON ERROR GOTO CannotReadFromCrackFile
       LINE INPUT #2, WorkLine$
       ON ERROR GOTO 0
       IF LEN(WorkLine$) <> 15 THEN
        ExitCode% = 2
        EXIT DO
       END IF
       Address& = VAL("&H" + LEFT$(WorkLine$, 8)) + 1
       WorkLine$ = MID$(WorkLine$, 9)
       IF LEFT$(WorkLine$, 2) <> ": " THEN
        ExitCode% = 2
        EXIT DO
       END IF
       WorkLine$ = MID$(WorkLine$, 3)
       FirstByte% = VAL("&H" + LEFT$(WorkLine$, 2))
       WorkLine$ = MID$(WorkLine$, 3)
       IF LEFT$(WorkLine$, 1) <> " " THEN
        ExitCode% = 2
        EXIT DO
       END IF
       WorkLine$ = MID$(WorkLine$, 3)
       SecondByte% = VAL("&H" + LEFT$(WorkLine$, 2))
       ON ERROR GOTO CannotSeekProgramFile
       SEEK #1, Address&
       ON ERROR GOTO 0
       LSET ProgramFileData$ = CHR$(SecondByte%)
       ON ERROR GOTO CannotWriteToProgramFile
       PUT #1
       ON ERROR GOTO 0
       Differencies& = Differencies& + 1
      LOOP
      CALL ScratchScreen
      CLOSE #1
      CLOSE #2
      SELECT CASE ExitCode%
      CASE 1
        CALL OutBox("Cracker.", "User break.")
      CASE 2
        CALL OutBox("Cracker.", "Invalid crack file.")
      CASE ELSE
        CALL OutBox("Cracker.", "Cracking is succefully ended.")
      END SELECT
     END IF
    END IF
   END IF
 CASE 4
   EXIT DO
 END SELECT
WorkRepeat:
LOOP
COLOR 7, 0
CLS
LOCATE 1, 1, 1, 7, 8
END
OutStatusBox:
 CALL MakeBox(1, 6, 77, 12)
 PRINT "Cracking." + SPACE$(68);
 COLOR 1, 7
 LOCATE 8, 2, 0
 PRINT "    Program file name: ";
 COLOR 4, 7
 PRINT ProgramFileName$;
 COLOR 1, 7
 PRINT ".";
 LOCATE 9, 2, 0
 PRINT "      Crack file name: ";
 COLOR 4, 7
 PRINT CrackFileName$;
 COLOR 1, 7
 PRINT ".";
 LOCATE 10, 2, 0
 PRINT "    Program file size: ";
 COLOR 4, 7
 PRINT SPACE$(10 - LEN(LTRIM$(STR$(LOF(1))))) + LTRIM$(STR$(LOF(1)));
 COLOR 1, 7
 PRINT " bytes.";
 LOCATE 11, 2, 0
 PRINT "Program file position: " + SPACE$(10) + ".";
 LOCATE 12, 2, 0
 PRINT "         Differencies: " + SPACE$(10) + ".";
 LOCATE 13, 2, 0
 PRINT "       Cracking speed: " + SPACE$(10) + " bytes per second.";
 LOCATE 14, 2, 0
 PRINT "   % Completed.";
 LOCATE 15, 2, 0
 PRINT "  Start time: ";
 COLOR 4, 7
 PRINT "Date: " + DayOfWeekName$(VAL(MID$(StartDate$, 4, 2)), VAL(MID$(StartDate$, 1, 2)), VAL(MID$(StartDate$, 7, 4))) + ", " + LTRIM$(STR$(VAL(MID$(StartDate$, 4, 2)))) + " " + MonthName$(VAL(MID$(StartDate$, 1, 2))) + " " + LTRIM$(STR$(VAL(MID$(StartDate$, 7, 4)))) + " year. Time: " + StartTime$;
 COLOR 1, 7
 PRINT ".";
 LOCATE 16, 2, 0
 PRINT "Current time:";
 LOCATE 17, 2, 0
 PRINT "   Past time:";
 COLOR 14, 7
 LOCATE 18, 2, 0
 PRINT "[ESC]=Break.";
 RETURN
OutStatus:
 COLOR 4, 7
 LOCATE 11, 25, 0
 PRINT SPACE$(10 - LEN(LTRIM$(STR$(LOC(1))))) + LTRIM$(STR$(LOC(1)));
 LOCATE 12, 25, 0
 PRINT SPACE$(10 - LEN(LTRIM$(STR$(Differencies&)))) + LTRIM$(STR$(Differencies&));
 LOCATE 14, 2, 0
 PRINT STRING$(3 - LEN(LTRIM$(STR$(INT((LOC(1) * 100) / LOF(1))))), "0") + LTRIM$(STR$(INT((LOC(1) * 100) / LOF(1))));
 CurrentDate$ = DATE$
 CurrentTime$ = TIME$
 IF VAL(MID$(CurrentTime$, 7, 2)) <> OldSecond% THEN
  OldSecond% = VAL(MID$(CurrentTime$, 7, 2))
  LOCATE 13, 25, 0
  PRINT SPACE$(10 - LEN(LTRIM$(STR$(LOC(1) - OldFilePosition&)))) + LTRIM$(STR$(LOC(1) - OldFilePosition&));
  OldFilePosition& = LOC(1)
  LOCATE 16, 16, 0
  PRINT SPACE$(63);
  LOCATE 16, 16, 0
  PRINT "Date: " + DayOfWeekName$(VAL(MID$(CurrentDate$, 4, 2)), VAL(MID$(CurrentDate$, 1, 2)), VAL(MID$(CurrentDate$, 7, 4))) + ", " + LTRIM$(STR$(VAL(MID$(CurrentDate$, 4, 2)))) + " " + MonthName$(VAL(MID$(CurrentDate$, 1, 2))) + " " + LTRIM$(STR$(VAL(MID$(CurrentDate$, 7, 4)))) + " year. Time: " + CurrentTime$;
  COLOR 1, 7
  PRINT ".";
  CALL SecondsToDateAndTime(DateAndTimeToSeconds#(VAL(MID$(CurrentTime$, 1, 2)), VAL(MID$(CurrentTime$, 4, 2)), VAL(MID$(CurrentTime$, 7, 2)), VAL(MID$(CurrentDate$, 4, 2)), VAL(MID$(CurrentDate$, 1, 2)), VAL(MID$(CurrentDate$, 7, 4))) - DateAndTimeToSeconds#(VAL(MID$(StartTime$, 1, 2)), VAL(MID$(StartTime$, 4, 2)), VAL(MID$(StartTime$, 7, 2)), VAL(MID$(StartDate$, 4, 2)), VAL(MID$(StartDate$, 1, 2)), VAL(MID$(StartDate$, 7, 4))), WorkHourValue%, WorkMinuteValue%, WorkSecondValue%, WorkDayValue%, WorkMonthValue%, WorkYearValue%, WorkDayOfWeekValue%)
  COLOR 4, 7
  LOCATE 17, 16, 0
  PRINT SPACE$(63);
  LOCATE 17, 16, 0
  PRINT "Date: " + DayName$(WorkDayOfWeekValue%) + ", " + LTRIM$(STR$(WorkDayValue%)) + " " + MonthName$(WorkMonthValue%) + " " + LTRIM$(STR$(WorkYearValue%)) + " year. Time: " + STRING$(2 - LEN(LTRIM$(STR$(WorkHourValue%))), "0") + LTRIM$(STR$(WorkHourValue%)) + ":" + STRING$(2 - LEN(LTRIM$(STR$(WorkMinuteValue%))), "0") + LTRIM$(STR$(WorkMinuteValue%)) + ":" + STRING$(2 - LEN(LTRIM$(STR$(WorkSecondValue%))), "0") + LTRIM$(STR$(WorkSecondValue%));
  COLOR 1, 7
  PRINT ".";
 END IF
 RETURN
CannotOpenProgramFile:
 IF MessageBox%("Cracker.", "Cannot open program file. Retry opening?") THEN
  CALL ScratchScreen
  RESUME
 ELSE
  RESUME WorkRepeat
 END IF
CannotOpenCrackFile:
 IF MessageBox%("Cracker.", "Cannot open crack file. Retry opening?") THEN
  CALL ScratchScreen
  RESUME
 ELSE
  CLOSE #1
  CLOSE #2
  RESUME WorkRepeat
 END IF
CannotPreReadFromCrackFile:
 IF MessageBox%("Cracker.", "Cannot read from crack file. Retry reading?") THEN
  CALL ScratchScreen
  RESUME
 ELSE
  CLOSE #1
  CLOSE #2
  RESUME WorkRepeat
 END IF
CannotSeekProgramFile:
 IF MessageBox%("Cracker.", "Cannot seek the program file. Retry seeking?") THEN
  CALL ScratchScreen
  GOSUB OutStatusBox
  GOSUB OutStatus
  RESUME
 ELSE
  CLOSE #1
  CLOSE #2
  RESUME WorkRepeat
 END IF
CannotWriteToProgramFile:
 IF MessageBox%("Cracker.", "Cannot write to program file. Retry writing?") THEN
  CALL ScratchScreen
  GOSUB OutStatusBox
  GOSUB OutStatus
  RESUME
 ELSE
  CLOSE #1
  CLOSE #2
  RESUME WorkRepeat
 END IF
CannotReadFromCrackFile:
 IF MessageBox%("Cracker.", "Cannot read from crack file. Retry reading?") THEN
  CALL ScratchScreen
  GOSUB OutStatusBox
  GOSUB OutStatus
  RESUME
 ELSE
  CLOSE #1
  CLOSE #2
  RESUME WorkRepeat
 END IF

FUNCTION DateAndTimeToSeconds# (HourValue%, MinuteValue%, SecondValue%, DayValue%, MonthValue%, YearValue%)
 DateAndTimeToSeconds# = (YearValue% * (416 * 86400#)) + (MonthValue% * (32 * 86400)) + (DayValue% * 86400) + (HourValue% * 3600!) + (MinuteValue% * 60) + SecondValue%
END FUNCTION

FUNCTION DayName$ (DayNumber%)
 SELECT CASE DayNumber%
 CASE 1
   DayName$ = "Monday"
 CASE 2
   DayName$ = "Tuesday"
 CASE 3
   DayName$ = "Wednesday"
 CASE 4
   DayName$ = "Thursday"
 CASE 5
   DayName$ = "Friday"
 CASE 6
   DayName$ = "Saturday"
 CASE 7
   DayName$ = "Sunday"
 END SELECT
END FUNCTION

FUNCTION DayOfWeek% (DayValue%, MonthValue%, YearValue%)
 SELECT CASE DaysCount&(DayValue%, MonthValue%, YearValue%) - (INT(DaysCount&(DayValue%, MonthValue%, YearValue%) / 7) * 7)
 CASE 0
   DayOfWeek% = 6
 CASE 1
   DayOfWeek% = 7
 CASE 2
   DayOfWeek% = 1
 CASE 3
   DayOfWeek% = 2
 CASE 4
   DayOfWeek% = 3
 CASE 5
   DayOfWeek% = 4
 CASE 6
   DayOfWeek% = 5
 CASE 7
   DayOfWeek% = 6
 END SELECT
END FUNCTION

FUNCTION DayOfWeekName$ (DayValue%, MonthValue%, YearValue%)
 DayOfWeekName$ = DayName$(DayOfWeek%(DayValue%, MonthValue%, YearValue%))
END FUNCTION

FUNCTION DaysCount& (DayValue%, MonthValue%, YearValue%)
 DaysCount& = (YearValue% * 365#) + INT(YearValue% / 100) + INT(YearValue% / 4) + MonthDaysCount%(MonthValue%, YearValue%) + DayValue%
END FUNCTION

FUNCTION InputBox% (Title$, Message$, InputTextLine$)
 DIM OutMessage$
 DIM OutIndex%
 DIM WorkKey$
 DIM InputTextCursorColumn%
 DIM InputTextCursorPosition%
 DIM InputText$
 IF LEN(Message$) < 256 THEN OutMessage$ = Message$ + SPACE$(256 - LEN(Message$)) ELSE OutMessage$ = LEFT$(Message$, 256)
 CALL MakeBox(7, 8, 64, 7)
 PRINT LEFT$(Title$, 64) + SPACE$(64 - LEN(LEFT$(Title$, 64)));
 COLOR 1, 7
 FOR OutIndex% = 1 TO 4
  LOCATE 9 + OutIndex%, 8, 0
  PRINT LEFT$(OutMessage$, 64);
  OutMessage$ = MID$(OutMessage$, 65)
 NEXT OutIndex%
 COLOR 14, 7
 LOCATE 15, 8, 0
 PRINT "Please press key is equalient to your answer: ENTER=Yes, ESC=No.";
 InputTextCursorColumn% = 1
 InputTextCursorPosition% = 1
 InputText$ = InputTextLine$
 GOSUB OutInputLine
 DO
  WorkKey$ = INKEY$
  SELECT CASE LEN(WorkKey$)
  CASE 1
    SELECT CASE WorkKey$
    CASE CHR$(8)
      IF InputTextCursorColumn% > 1 THEN
       InputTextCursorColumn% = InputTextCursorColumn% - 1
       InputTextCursorPosition% = InputTextCursorPosition% - 1
       IF InputTextCursorColumn% < 1 THEN InputTextCursorColumn% = 1
       IF InputTextCursorPosition% < 1 THEN InputTextCursorPosition% = 1
       InputText$ = MID$(InputText$, 1, InputTextCursorColumn% - 1) + MID$(InputText$, InputTextCursorColumn% + 1)
       GOSUB OutInputLine
      END IF
    CASE CHR$(13)
      InputTextLine$ = InputText$
      EXIT DO
    CASE CHR$(27)
      EXIT DO
    CASE ELSE
      IF (LEN(InputText$) < 256) AND (ASC(WorkKey$) > (ASC(SPACE$(1)) - 1)) THEN
       InputText$ = MID$(InputText$, 1, InputTextCursorColumn% - 1) + WorkKey$ + MID$(InputText$, InputTextCursorColumn%)
       InputTextCursorColumn% = InputTextCursorColumn% + 1
       InputTextCursorPosition% = InputTextCursorPosition% + 1
       IF InputTextCursorColumn% > LEN(InputText$) + 1 THEN InputTextCursorColumn% = LEN(InputText$) + 1
       IF LEN(InputText$) > 63 THEN IF InputTextCursorPosition% > 64 THEN InputTextCursorPosition% = 64
       IF LEN(InputText$) < 65 THEN IF InputTextCursorPosition% > LEN(InputText$) + 1 THEN InputTextCursorPosition% = LEN(InputText$) + 1
       GOSUB OutInputLine
      END IF
    END SELECT
  CASE 2
    WorkKey$ = MID$(WorkKey$, 2)
    SELECT CASE WorkKey$
    CASE CHR$(75)
      IF InputTextCursorColumn% > 1 THEN
       InputTextCursorColumn% = InputTextCursorColumn% - 1
       InputTextCursorPosition% = InputTextCursorPosition% - 1
       IF InputTextCursorColumn% < 1 THEN InputTextCursorColumn% = 1
       IF InputTextCursorPosition% < 1 THEN InputTextCursorPosition% = 1
       GOSUB OutInputLine
      END IF
    CASE CHR$(77)
      IF InputTextCursorColumn% < LEN(InputText$) + 1 THEN
       InputTextCursorColumn% = InputTextCursorColumn% + 1
       InputTextCursorPosition% = InputTextCursorPosition% + 1
       IF InputTextCursorColumn% > LEN(InputText$) + 1 THEN InputTextCursorColumn% = LEN(InputText$) + 1
       IF LEN(InputText$) > 63 THEN IF InputTextCursorPosition% > 64 THEN InputTextCursorPosition% = 64
       IF LEN(InputText$) < 65 THEN IF InputTextCursorPosition% > LEN(InputText$) + 1 THEN InputTextCursorPosition% = LEN(InputText$) + 1
       GOSUB OutInputLine
      END IF
    CASE CHR$(71)
      IF InputTextCursorColumn% <> 1 THEN
       InputTextCursorColumn% = 1
       InputTextCursorPosition% = 1
       GOSUB OutInputLine
      END IF
    CASE CHR$(79)
      IF InputTextCursorColumn% <> LEN(InputText$) + 1 THEN
       InputTextCursorColumn% = LEN(InputText$) + 1
       InputTextCursorPosition% = LEN(InputText$) + 1
       IF LEN(InputText$) > 63 THEN IF InputTextCursorPosition% > 64 THEN InputTextCursorPosition% = 64
       IF LEN(InputText$) < 65 THEN IF InputTextCursorPosition% > LEN(InputText$) + 1 THEN InputTextCursorPosition% = LEN(InputText$) + 1
       GOSUB OutInputLine
      END IF
    CASE CHR$(83)
      IF InputText$ <> "" THEN
       InputText$ = MID$(InputText$, 1, InputTextCursorColumn% - 1) + MID$(InputText$, InputTextCursorColumn% + 1)
       GOSUB OutInputLine
      END IF
    END SELECT
  END SELECT
 LOOP
 LOCATE , , 0
 InputBox% = WorkKey$ = CHR$(13)
 EXIT FUNCTION
OutInputLine:
 COLOR 4, 7
 LOCATE 14, 8, 0
 PRINT MID$(InputText$, (InputTextCursorColumn% - InputTextCursorPosition%) + 1, 64) + SPACE$(64 - LEN(MID$(InputText$, (InputTextCursorColumn% - InputTextCursorPosition%) + 1, 64)));
 LOCATE 14, 7 + InputTextCursorPosition%, 1, 7, 8
 RETURN
END FUNCTION

FUNCTION IsLeapYear% (YearValue%)
 IsLeapYear% = ABS((INT(YearValue% / 4) * 4) = YearValue%)
END FUNCTION

SUB MakeBox (BoxColumn%, BoxRow%, BoxWidth%, BoxHeight%)
 DIM BoxWorkIndex%
 IF (BoxColumn% < 1) OR (BoxRow% < 1) OR (BoxWidth% < 1) OR (BoxHeight% < 1) OR (BoxWidth% > 77) OR (BoxHeight% > 22) OR (((BoxColumn% - 1) + BoxWidth%) > 77) OR (((BoxRow% - 1) + BoxHeight%) > 22) THEN EXIT SUB
 COLOR 0, 7
 LOCATE BoxRow%, BoxColumn%, 0
 PRINT CHR$(201) + STRING$(BoxWidth%, CHR$(205)) + CHR$(187);
 FOR BoxWorkIndex% = 1 TO BoxHeight% + 1
  LOCATE BoxRow% + BoxWorkIndex%, BoxColumn%, 0
  PRINT CHR$(186) + SPACE$(BoxWidth%) + CHR$(186);
  COLOR 0, 0
  PRINT SPACE$(1);
  COLOR 0, 7
 NEXT BoxWorkIndex%
 LOCATE BoxRow% + BoxHeight% + 1, BoxColumn%, 0
 PRINT CHR$(200) + STRING$(BoxWidth%, CHR$(205)) + CHR$(188);
 COLOR 0, 0
 LOCATE BoxRow% + BoxHeight% + 2, BoxColumn% + 1, 0
 PRINT SPACE$(BoxWidth% + 2);
 COLOR 15, 2
 LOCATE BoxRow% + 1, BoxColumn% + 1, 0
END SUB

FUNCTION MenuBox% (ItemsCount%)
 DIM MenuIndex%
 DIM MenuLineLength%
 DIM CurrentItem%
 DIM WorkKey$
 IF (ItemsCount% < 1) OR (ItemsCount% > UBOUND(MenuItems$)) OR (UBOUND(MenuItems$) > 20) THEN
  MenuBox% = 0
  EXIT FUNCTION
 END IF
 MenuLineLength% = 0
 FOR MenuIndex% = 1 TO ItemsCount%
  IF LEN(MenuItems$(MenuIndex%)) > MenuLineLength% THEN MenuLineLength% = LEN(MenuItems$(MenuIndex%))
 NEXT MenuIndex%
 IF MenuLineLength% < 56 THEN MenuLineLength% = 56
 IF MenuLineLength% > 75 THEN MenuLineLength% = 75
 CurrentItem% = 1
 GOSUB OutMenu
 DO
  WorkKey$ = UCASE$(INKEY$)
  SELECT CASE LEN(WorkKey$)
  CASE 1
    SELECT CASE WorkKey$
    CASE CHR$(13)
      MenuBox% = CurrentItem%
      EXIT DO
    CASE CHR$(27)
      MenuBox% = 0
      EXIT DO
    CASE ELSE
      IF (ASC(WorkKey$) > (ASC("A") - 1)) AND (ASC(WorkKey$) < (ASC("A") + ItemsCount%)) THEN
       CurrentItem% = (ASC(WorkKey$) - ASC("A")) + 1
       GOSUB OutMenu
      END IF
    END SELECT
  CASE 2
    WorkKey$ = MID$(WorkKey$, 2)
    SELECT CASE WorkKey$
    CASE CHR$(72)
      IF CurrentItem% > 1 THEN
       CurrentItem% = CurrentItem% - 1
       GOSUB OutMenu
      END IF
    CASE CHR$(80)
      IF CurrentItem% < ItemsCount% THEN
       CurrentItem% = CurrentItem% + 1
       GOSUB OutMenu
      END IF
    CASE CHR$(73)
      IF CurrentItem% <> 1 THEN
       CurrentItem% = 1
       GOSUB OutMenu
      END IF
    CASE CHR$(81)
      IF CurrentItem% <> ItemsCount% THEN
       CurrentItem% = ItemsCount%
       GOSUB OutMenu
      END IF
    CASE CHR$(71)
      IF CurrentItem% <> 1 THEN
       CurrentItem% = 1
       GOSUB OutMenu
      END IF
    CASE CHR$(79)
      IF CurrentItem% <> ItemsCount% THEN
       CurrentItem% = ItemsCount%
       GOSUB OutMenu
      END IF
    END SELECT
  END SELECT
 LOOP
 EXIT FUNCTION
OutMenu:
 CALL MakeBox(INT((80 - (MenuLineLength% + 5)) / 2) + 1, INT((25 - (ItemsCount% + 5)) / 2) + 1, MenuLineLength% + 2, ItemsCount% + 2)
 FOR MenuIndex% = 1 TO ItemsCount%
  COLOR 14, 7
  LOCATE INT((25 - (ItemsCount% + 5)) / 2) + (MenuIndex% + 1), INT((80 - (MenuLineLength% + 5)) / 2) + 2, 0
  PRINT CHR$(ASC("A") + (MenuIndex% - 1));
  COLOR 12, 7
  PRINT "=";
  IF MenuIndex% = CurrentItem% THEN COLOR 15, 6 ELSE COLOR 8, 7
  PRINT LEFT$(MenuItems$(MenuIndex%), MenuLineLength%) + SPACE$(MenuLineLength% - LEN(LEFT$(MenuItems$(MenuIndex%), MenuLineLength%)));
 NEXT MenuIndex%
 COLOR 0, 7
 LOCATE INT((25 - (ItemsCount% + 5)) / 2) + 2 + ItemsCount%, INT((80 - (MenuLineLength% + 5)) / 2) + 1, 0
 PRINT CHR$(204) + STRING$(MenuLineLength% + 2, CHR$(205)) + CHR$(185);
 COLOR 14, 7
 LOCATE INT((25 - (ItemsCount% + 5)) / 2) + 3 + ItemsCount%, INT((80 - (MenuLineLength% + 5)) / 2) + 2, 0
 PRINT SPACE$(INT((MenuLineLength% - 56) / 2) + 1) + "Please press ENTER to select menu item or ESC to cancel."
 RETURN
END FUNCTION

FUNCTION MessageBox% (Title$, Message$)
 DIM OutMessage$
 DIM OutIndex%
 DIM WorkKey$
 IF LEN(Message$) < 256 THEN OutMessage$ = Message$ + SPACE$(256 - LEN(Message$)) ELSE OutMessage$ = LEFT$(Message$, 256)
 CALL MakeBox(7, 9, 64, 6)
 PRINT LEFT$(Title$, 64) + SPACE$(64 - LEN(LEFT$(Title$, 64)));
 COLOR 1, 7
 FOR OutIndex% = 1 TO 4
  LOCATE 10 + OutIndex%, 8, 0
  PRINT LEFT$(OutMessage$, 64);
  OutMessage$ = MID$(OutMessage$, 65)
 NEXT OutIndex%
 COLOR 14, 7
 LOCATE 15, 8, 0
 PRINT "Please press key is equalient to your answer: ENTER=Yes, ESC=No.";
 WorkKey$ = ""
 WHILE (WorkKey$ <> CHR$(13)) AND (WorkKey$ <> CHR$(27))
  WorkKey$ = INKEY$
 WEND
 MessageBox% = WorkKey$ = CHR$(13)
END FUNCTION

FUNCTION MonthDays% (MonthValue%, YearValue%)
 SELECT CASE MonthValue%
 CASE 1
   MonthDays% = 31
 CASE 2
   MonthDays% = 28 + IsLeapYear%(YearValue%)
 CASE 3
   MonthDays% = 31
 CASE 4
   MonthDays% = 30
 CASE 5
   MonthDays% = 31
 CASE 6
   MonthDays% = 30
 CASE 7
   MonthDays% = 31
 CASE 8
   MonthDays% = 31
 CASE 9
   MonthDays% = 30
 CASE 10
   MonthDays% = 31
 CASE 11
   MonthDays% = 30
 CASE 12
   MonthDays% = 31
 END SELECT
END FUNCTION

FUNCTION MonthDaysCount% (MonthValue%, YearValue%)
 SELECT CASE MonthValue%
 CASE 1
   MonthDaysCount% = 0
 CASE 2
   MonthDaysCount% = 31
 CASE 3
   MonthDaysCount% = 59 + IsLeapYear%(YearValue%)
 CASE 4
   MonthDaysCount% = 90 + IsLeapYear%(YearValue%)
 CASE 5
   MonthDaysCount% = 120 + IsLeapYear%(YearValue%)
 CASE 6
   MonthDaysCount% = 151 + IsLeapYear%(YearValue%)
 CASE 7
   MonthDaysCount% = 181 + IsLeapYear%(YearValue%)
 CASE 8
   MonthDaysCount% = 212 + IsLeapYear%(YearValue%)
 CASE 9
   MonthDaysCount% = 243 + IsLeapYear%(YearValue%)
 CASE 10
   MonthDaysCount% = 273 + IsLeapYear%(YearValue%)
 CASE 11
   MonthDaysCount% = 304 + IsLeapYear%(YearValue%)
 CASE 12
   MonthDaysCount% = 334 + IsLeapYear%(YearValue%)
 END SELECT
END FUNCTION

FUNCTION MonthName$ (MonthNumber%)
 SELECT CASE MonthNumber%
 CASE 1
   MonthName$ = "January"
 CASE 2
   MonthName$ = "February"
 CASE 3
   MonthName$ = "March"
 CASE 4
   MonthName$ = "April"
 CASE 5
   MonthName$ = "May"
 CASE 6
   MonthName$ = "June"
 CASE 7
   MonthName$ = "July"
 CASE 8
   MonthName$ = "August"
 CASE 9
   MonthName$ = "September"
 CASE 10
   MonthName$ = "October"
 CASE 11
   MonthName$ = "November"
 CASE 12
   MonthName$ = "December"
 END SELECT
END FUNCTION

SUB OutBox (Title$, Message$)
 DIM OutMessage$
 DIM OutIndex%
 IF LEN(Message$) < 256 THEN OutMessage$ = Message$ + SPACE$(256 - LEN(Message$)) ELSE OutMessage$ = LEFT$(Message$, 256)
 CALL MakeBox(7, 9, 64, 6)
 PRINT LEFT$(Title$, 64) + SPACE$(64 - LEN(LEFT$(Title$, 64)));
 COLOR 1, 7
 FOR OutIndex% = 1 TO 4
  LOCATE 10 + OutIndex%, 8, 0
  PRINT LEFT$(OutMessage$, 64);
  OutMessage$ = MID$(OutMessage$, 65)
 NEXT OutIndex%
 COLOR 14, 7
 LOCATE 15, 8, 0
 PRINT "       Please press the ENTER key to quit from this box.";
 WHILE INKEY$ <> CHR$(13)
 WEND
END SUB

SUB ScratchScreen
 COLOR 0, 2
 CLS
 PRINT "********************************************************************************"
 PRINT "                        The Standart GNU Personal Cracker."
 PRINT "                     Copyright (C) Sandul Yura Valentinovich."
 PRINT "                        (R) Wednesday, 5 March 2003 year."
 PRINT
 PRINT "    This program is free software; you can redistribute it and/or modify it"
 PRINT "under the terms of the GNU General Public License as published by the Free"
 PRINT "Software Foundation; either version 2 of the License, or (at your option) any"
 PRINT "later version."
 PRINT "    This program is distributed in the hope that it will be useful, but WITHOUT"
 PRINT "ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS"
 PRINT "FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details."
 PRINT "    You should have received a copy of the GNU General Public License along with"
 PRINT "this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave,"
 PRINT "Cambridge, MA 02139, USA."
END SUB

SUB SecondsToDateAndTime (SecondsCount#, HourValue%, MinuteValue%, SecondValue%, DayValue%, MonthValue%, YearValue%, DayOfWeekValue%)
 DIM WorkValue#
 WorkValue# = SecondsCount#
 YearValue% = INT(WorkValue# / (416 * 86400))
 WorkValue# = WorkValue# - (YearValue% * (416 * 86400#))
 MonthValue% = INT(WorkValue# / (32 * 86400))
 WorkValue# = WorkValue# - (MonthValue% * (32 * 86400))
 DayValue% = INT(WorkValue# / 86400)
 WorkValue# = WorkValue# - (DayValue% * 86400)
 HourValue% = INT(WorkValue# / 3600)
 WorkValue# = WorkValue# - (HourValue% * 3600!)
 MinuteValue% = INT(WorkValue# / 60)
 SecondValue% = WorkValue# - (MinuteValue% * 60)
 DayOfWeekValue% = DayOfWeek%(DayValue%, MonthValue%, YearValue%)
END SUB

