#ifndef COMPILE_H
#include "COMPILE.H"
#endif
#ifdef MEDIA067_S10EA_S10EB_S11E_S12E_S12G_S13FA_S13FB_S20E_S21E_G14ED_G20E_G21E_A20ED_A20E_A20F_A20G_A21E_A22E_A22G_X30J_P20JA_P20JB_A31E_A31M_A33M_A35E_A35M_X31J
#ifndef NOCOPYPROTECTION
#ifdef MEDIA153_S10EA_S10EB_S11E_S12E_S12G_S13FA_S13FB_S20E_S21E_A20ED_A20E_A20F_A20G_A21E_A22E_A22G_A31E_A31M_A33M_A35E_A35M
#ifdef MEDIA007_S10EA_S10EB_S11E_S12E_S12G_S13FA_S13FB_S20E_S21E
overlay "timeline"

BOOLEAN F0277_CPSE_IsFuzzySectorValid_FuzzyBits(
P0593_puc_SectorBuffer)
REGISTER unsigned char* P0593_puc_SectorBuffer FINAL_SEPARATOR
#endif
#ifdef MEDIA423_A20ED_A20E_A20F_A20G_A21E_A22E_A22G_A31E_A31M_A33M_A35E_A35M
BOOLEAN F0277_CPSE_IsFuzzySectorValid_FuzzyBits(
#ifdef MEDIA009_S10EA_S10EB_S11E_S12E_S12G_S13FA_S13FB_S20E_S21E_G14ED_G20E_G21E_A20ED_A20E_A20F_A20G_A21E_A22E_A22G
P0593_pui_SectorBuffer)
#endif
REGISTER unsigned int16_t* P0593_pui_SectorBuffer FINAL_SEPARATOR
#endif
{
        REGISTER int16_t L0780_ui_ByteIndex;
        REGISTER int16_t L0781_i_Counter;
        REGISTER int16_t L0782_i_FuzzyBitCount;
        REGISTER int16_t L0783_i_FuzzyBits;
        int16_t L0784_i_DifferingWordCount;


        L0782_i_FuzzyBitCount = 0;
        L0784_i_DifferingWordCount = 0;
        L0781_i_Counter = 0;
        L0783_i_FuzzyBits = 0;
#ifdef MEDIA265_S20E_S21E /* CHANGE7_04_IMPROVEMENT */
        G0068_i_CheckLastEvent22Time_CPSE = C00512_FALSE;
#endif
#ifdef MEDIA007_S10EA_S10EB_S11E_S12E_S12G_S13FA_S13FB_S20E_S21E
        for (L0780_ui_ByteIndex = 20; L0780_ui_ByteIndex < 509; L0780_ui_ByteIndex++) {
                L0783_i_FuzzyBits = (L0783_i_FuzzyBits << 1) | ((P0593_puc_SectorBuffer[L0780_ui_ByteIndex] >> 7) & 0x0001);
#endif
#ifdef MEDIA413_A20ED_A20E_A20F_A20G_A21E_A22E_A22G
        for (L0780_ui_ByteIndex = 20; L0780_ui_ByteIndex <= 508; L0780_ui_ByteIndex++) {
#endif
#ifdef MEDIA626_A31E_A31M_A33M_A35E_A35M
        for (L0780_ui_ByteIndex = 635; L0780_ui_ByteIndex <= 1123; L0780_ui_ByteIndex++) {
#endif
#ifdef MEDIA423_A20ED_A20E_A20F_A20G_A21E_A22E_A22G_A31E_A31M_A33M_A35E_A35M
                L0783_i_FuzzyBits = (L0783_i_FuzzyBits << 1) | ((P0593_pui_SectorBuffer[L0780_ui_ByteIndex] >> 14) & 0x0001);
#endif
#ifdef MEDIA137_S10EA_S10EB_S11E_S12E_S12G_S13FA_S13FB_S20E_S21E_A20ED_A20E_A20F_A20G_A21E_A22E_A22G
                if (((L0782_i_FuzzyBitCount++) == 16) || (L0780_ui_ByteIndex == 508)) {
#endif
#ifdef MEDIA626_A31E_A31M_A33M_A35E_A35M
                if (((L0782_i_FuzzyBitCount++) == 16) || (L0780_ui_ByteIndex == 1123)) {
#endif
                        L0782_i_FuzzyBitCount = 0;
                        if (L0783_i_FuzzyBits != G0293_ai_FuzzyBits_CPSE[L0781_i_Counter]) {
                                L0784_i_DifferingWordCount++;
                        }
                        G0293_ai_FuzzyBits_CPSE[L0781_i_Counter++] = L0783_i_FuzzyBits;
                        L0783_i_FuzzyBits = 0;
                }
        }
        if (!L0784_i_DifferingWordCount) {
                G0418_l_LastEvent22Time_CPSE = 0;
        }
#ifdef MEDIA423_A20ED_A20E_A20F_A20G_A21E_A22E_A22G_A31E_A31M_A33M_A35E_A35M
        G0068_i_CheckLastEvent22Time_CPSE = C00512_FALSE;
#endif
        G0031_i_Graphic562_FuzzySectorAnalyzed_CPSE = C00136_TRUE;
        return L0784_i_DifferingWordCount;
}
#endif

#ifdef MEDIA351_G14ED_G20E_G21E
segment "timeline"

BOOLEAN F0277_CPSE_IsFuzzySectorValid_FuzzyBits(
P0593_puc_SectorBuffer)
unsigned char* P0593_puc_SectorBuffer FINAL_SEPARATOR
{
        unsigned int16_t L0780_ui_ByteIndex;
        int16_t L0781_i_Counter;
        int16_t L0784_i_DifferingWordCount;
        char L6207_c_;


        L0781_i_Counter = 0;
        L0784_i_DifferingWordCount = 0;
        for (L0780_ui_ByteIndex = 13; L0780_ui_ByteIndex < 703; L0780_ui_ByteIndex += 2) {
                L6207_c_ = P0593_puc_SectorBuffer[L0780_ui_ByteIndex] ^ G0293_ai_FuzzyBits_CPSE[L0781_i_Counter];
                G0293_ai_FuzzyBits_CPSE[L0781_i_Counter++] = P0593_puc_SectorBuffer[L0780_ui_ByteIndex] & 0x1b;
                if (L6207_c_ & 0x1b) {
                        L0784_i_DifferingWordCount++;
                }
        }
        if (!L0784_i_DifferingWordCount) {
                G0418_l_LastEvent22Time_CPSE = 0;
        }
        G0031_i_Graphic562_FuzzySectorAnalyzed_CPSE = C00136_TRUE;
        G0068_i_CheckLastEvent22Time_CPSE = C00512_FALSE;
        return L0784_i_DifferingWordCount;
}
#endif

#ifdef MEDIA458_P20JA_P20JB
char G3039_aac_PreviousFuzzyBitsReadings_CPSX[4][4] = { /* Initialized with fake data so that each line has different values, as expected when reading 4 bytes of fuzzy bits from the floppy disk */
        { 1, 2, 3, 4 },
        { 2, 3, 4, 5 },
        { 3, 4, 5, 6 },
        { 4, 5, 6, 7 } };


BOOLEAN F0277_CPSE_IsFuzzySectorValid_FuzzyBits(
REGISTER unsigned char* P0593_puc_SectorBuffer FINAL_SEPARATOR
{
        int16_t L2326_i_ByteIndex;
        int16_t L2327_i_DifferenceCount;
        int16_t L2328_i_DifferenceCount;


        G0068_i_CheckLastEvent22Time_CPSE = C00512_FALSE;
        L2327_i_DifferenceCount = 0;
        L2328_i_DifferenceCount = 0;
#ifdef MEDIA457_P20JA
        /* The copy protection sector contains 8 bytes ignored here followed by 4 bytes with random values */
        for (L2326_i_ByteIndex = 0; L2326_i_ByteIndex < 4; L2326_i_ByteIndex++) {
                if ((G3039_aac_PreviousFuzzyBitsReadings_CPSX[1][L2326_i_ByteIndex] != G3039_aac_PreviousFuzzyBitsReadings_CPSX[0][L2326_i_ByteIndex]) || (P0593_puc_SectorBuffer[L2326_i_ByteIndex + 8] != G3039_aac_PreviousFuzzyBitsReadings_CPSX[0][L2326_i_ByteIndex])) {
                        L2327_i_DifferenceCount++;
                }
                if ((G3039_aac_PreviousFuzzyBitsReadings_CPSX[3][L2326_i_ByteIndex] != G3039_aac_PreviousFuzzyBitsReadings_CPSX[1][L2326_i_ByteIndex]) || (P0593_puc_SectorBuffer[L2326_i_ByteIndex + 8] != G3039_aac_PreviousFuzzyBitsReadings_CPSX[1][L2326_i_ByteIndex])) {
                        L2328_i_DifferenceCount++;
                }
                G3039_aac_PreviousFuzzyBitsReadings_CPSX[3][L2326_i_ByteIndex] = G3039_aac_PreviousFuzzyBitsReadings_CPSX[2][L2326_i_ByteIndex]; /* Discard oldest reading from array */
                G3039_aac_PreviousFuzzyBitsReadings_CPSX[2][L2326_i_ByteIndex] = G3039_aac_PreviousFuzzyBitsReadings_CPSX[1][L2326_i_ByteIndex]; /* Shift the others to make room */
                G3039_aac_PreviousFuzzyBitsReadings_CPSX[1][L2326_i_ByteIndex] = G3039_aac_PreviousFuzzyBitsReadings_CPSX[0][L2326_i_ByteIndex]; 
                G3039_aac_PreviousFuzzyBitsReadings_CPSX[0][L2326_i_ByteIndex] = P0593_puc_SectorBuffer[L2326_i_ByteIndex + 8]; /* Store the latest reading */
        }
        if ((L2327_i_DifferenceCount == 0) || (L2328_i_DifferenceCount == 0)) { /* If no difference was found then the disk is not an original */
                G0418_l_LastEvent22Time_CPSE = 0;
        }
#endif
#ifdef MEDIA469_P20JB
        L2328_i_DifferenceCount = 1;  /* Disables this copy protection check */
#endif
        G0031_i_Graphic562_FuzzySectorAnalyzed_CPSE = C00136_TRUE;
        return L2327_i_DifferenceCount + L2328_i_DifferenceCount;
}
#endif
#ifdef MEDIA607_X30J_X31J
BOOLEAN F0277_CPSE_IsFuzzySectorValid_FuzzyBits(
REGISTER unsigned char* P0593_puc_SectorBuffer FINAL_SEPARATOR
{
        G0068_i_CheckLastEvent22Time_CPSE = C00512_FALSE;
        asm {
                        /* G0293_ai_FuzzyBits_CPSE starts empty and is supposed to store the last two readings (ultimate and penultimate) of the 4 random bytes from the copy protection sector. Each time a new reading is performed, it is compared with the previous readings stored in this variable. Then the oldest reading is discarded, and the latest reading is stored. However, the code is broken: instead of storing the bytes in the read buffer, the buffer address itself is stored instead. Consequently, on a copy of the game, this address is always different from the buffer content (which remains filled with 0 bytes because all reading attempts of the copy protected sector fail as sector 9 cannot be found on the copy). As a result this copy protection scheme is completely useless and ineffective. The very first time the comparisons are made, both semaphores G3093_B_LatestReadingIdenticalToUltimateReading_CPSX and G3094_B_LatestReadingIdenticalToPenultimateReading_CPSX are set because both buffers are filled with 0 bytes and thus have identical content. However the results of these first comparisons are ignored: the semaphores are here to provide some tolerance in the rare case that two readings of the copy protected sector could give the same results, even on an original disk. However, all subsequent comparisons will succeed: the semaphores are reset and no consequence will ever be applied in the game */
                        lea     G0293_ai_FuzzyBits_CPSE(a5),a0
                        addq.l  #8,a4           /* a4 is P0593_puc_SectorBuffer. Ignore the first 8 characters that should be "HPR-0007" */
                        movea.l a4,a1
                        moveq   #4,d0           /* Compare next 4 bytes expected to have different random values for each sector reading */
                @Tloc_201B8:
#ifndef NOCOPYPROTECTION
                        cmpm.b  (a1)+,(a0)+     /* 0xb1 0x09 */
#else /* Crack */
                        bra     @Tloc_201EE     /* 0x60 0x34 */
#endif
                        dbne    d0,@Tloc_201B8  /* Decrement D0 and branch if d0 == 0 else continue */
                        addq.w  #1,d0
                        beq.s   @Tloc_201C8     /* If d0 == 0 then the 4 bytes are identical and the floppy disk is not an original */
                        clr.w   G3093_B_LatestReadingIdenticalToUltimateReading_CPSX(a5)
                        bra.s   @Tloc_201CE
                @Tloc_201C8:
                        tas     G3093_B_LatestReadingIdenticalToUltimateReading_CPSX(a5) /* Test and set bit 7 in G3093_B_LatestReadingIdenticalToUltimateReading_CPSX (in the most significant byte) */
                        bne.s   @Tloc_201E6     /* Branch if G3093_B_LatestReadingIdenticalToUltimateReading_CPSX WAS 0x80 before the tas instruction (if the floppy was already detected as a copy once) */
                @Tloc_201CE:
                        moveq   #4,d0           /* Compare a second time the 4 bytes expected to have different random values for each sector reading with the second previous reading */
                        movea.l a4,a1
                @Tloc_201D2:
                        cmpm.b  (a1)+,(a0)+
                        dbne    d0,@Tloc_201D2
                        addq.w  #1,d0
                        bne.s   @Tloc_201EA     /* If d0 != 0 then at least one of the 4 bytes is different and the floppy disk is an original */
                        tas     G3094_B_LatestReadingIdenticalToPenultimateReading_CPSX(a5) /* Test and set bit 7 in G3094_B_LatestReadingIdenticalToPenultimateReading_CPSX (in the most significant byte) */
                        bne.s   @Tloc_201E6     /* Branch if G3094_B_LatestReadingIdenticalToPenultimateReading_CPSX WAS 0x80 before the tas instruction (if the floppy was already detected as a copy once) */
                        addq.w  #1,d0
                        bne.s   @Tloc_201EE
                @Tloc_201E6:
                        clr.l   G0418_l_LastEvent22Time_CPSE(a5)
                @Tloc_201EA:
                        clr.w   G3094_B_LatestReadingIdenticalToPenultimateReading_CPSX(a5)
                @Tloc_201EE:
        }
        G0031_i_Graphic562_FuzzySectorAnalyzed_CPSE = C00136_TRUE;
        asm {
                move.l  G0293_ai_FuzzyBits_CPSE(a5),G0293_ai_FuzzyBits_CPSE+4(a5)       /* Overwrite the penultimate reading bytes with the ultimate reading bytes */
        }
/*        *(((int16_t**)G0293_ai_FuzzyBits_CPSE) + 1) = G0293_ai_FuzzyBits_CPSE;*/
        *((unsigned char**)G0293_ai_FuzzyBits_CPSE) = P0593_puc_SectorBuffer;           /* BUGX_XX: Stores the address of P0593_puc_SectorBuffer instead of actual bytes in the buffer */
}
#endif
#endif
#endif
