#ifndef COMPILE_H
#include "COMPILE.H"
#endif
#ifdef MEDIA774_SU1E_AU1E_AU2E
#ifdef MEDIA772_SU1E
extern void F1899_Pre_F1901_CopyProtectionRoutine_CPSX();
extern void F1902_Post_F1901_CopyProtectionRoutine_CPSX();
#endif


#ifdef MEDIA772_SU1E
char* G3637_apc_FileNames[6] = { /* to HINTLOAD.C */
        "",
        "",
        "0HCSB.HTC",
        "0HCSB.DAT",
        "1CSBGAME.DAT",
        "1CSBGAME.BAK" }; /* Define as array including 5 strings below */
unsigned char G0235_auc_Graphic559_ThingDataByteCount[16] = {
        4,   /* Door */
        6,   /* Teleporter */
        4,   /* Text String */
        8,   /* Sensor */
        16,  /* Group */
        4,   /* Weapon */
        4,   /* Armour */
        4,   /* Scroll */
        4,   /* Potion */
        8,   /* Container */
        4,   /* Junk */
        0,   /* Unused */
        0,   /* Unused */
        0,   /* Unused */
        8,   /* Projectile */
        4 }; /* Explosion */
int16_t G3718_ui_PartyChampionCount;
GAME_HINT G3623_Game[2];
int16_t G3638_i_IORequestIndex_CSBGAME;
int16_t G3717_;
int16_t G3734_Unreferenced;
char G3716_ac_TestFileName[5] = "A:\\F";
STRUCT22B* G3715_; /* to HINTLOAD.C */
/* strings, border between two .C source files */
#endif

#ifdef MEDIA763_AU1E_AU2E
int16_t G3576_i_Unused;
char G3863_ac_Unreferenced[40];
#ifdef MEDIA762_AU1E
char* G3637_apc_FileNames[6] = {
        "",
        "",
        "0HCSB.HTC",
        "0HCSB.DAT",
        "1CSBGAME.DAT",
        "1CSBGAME.BAK" }; /* Define as array including 5 strings below */
#endif
unsigned char G0235_auc_Graphic559_ThingDataByteCount[16] = {
        4,   /* Door */
        6,   /* Teleporter */
        4,   /* Text String */
        8,   /* Sensor */
        16,  /* Group */
        4,   /* Weapon */
        4,   /* Armour */
        4,   /* Scroll */
        4,   /* Potion */
        8,   /* Container */
        4,   /* Junk */
        0,   /* Unused */
        0,   /* Unused */
        0,   /* Unused */
        8,   /* Projectile */
        4 }; /* Explosion */
int16_t G3718_ui_PartyChampionCount;
GAME_HINT G3623_Game[2];
int16_t G3638_i_IORequestIndex_CSBGAME;
int16_t G3717_;
int16_t G3734_Unreferenced;
STRUCT22B* G3715_;
#endif

#ifdef MEDIA772_SU1E
extern void F1372_SetVerticalBlankInterrupt();
extern long F1857_PerformIORequestOperation();
extern long F1886_Memory();
extern long F1933_();
extern char* F1920_AllocateMemory();
extern void F1921_FreeMemory();
extern long F1931_();
extern long F1941_();
extern unsigned int16_t F1944_ChecksumAdd();
extern void F1947_BlitBitmapToOrFromScreen();
extern void F1956_EndProgram();
extern long F1861_GetIORequestOutputValue();
#endif


#ifdef MEDIA772_SU1E
#include "VBLANK.C"

#ifndef NOCOPYPROTECTION
int16_t F1908_Checksum_CPSX(register unsigned char* P5731_, register char* P5732_) {
        register int16_t L5605_;
        register int16_t L5606_;


        L5606_ = 0;
        L5605_ = 0;
        while (P5731_ < P5732_) {
                L5605_ += *P5731_ * ((L5606_++ % 8) + 1);
                P5731_++;
        }
        return L5605_;
}
#endif
#endif

char* F1909_CopyStringUntilCharacter(register char* P5733_, register char* P5734_, register char P5735_) {
        register char L5607_;


        while (L5607_ = *P5733_++) {
                if (L5607_ == P5735_) {
                        goto loc_6564;
                }
                *P5734_++ = L5607_;
        }
        P5733_ = NULL;
        loc_6564:
        *P5734_ = 0;
        return P5733_;
}

BOOLEAN F1910_LoadSavedGamePart(char* P5736_, unsigned int16_t P5737_) {
        register long L5608_;
        long L5609_;


        if ((L5608_ = P5737_) == 0) {
                return 1;
        }
        F1859_SetIORequestValue(G3638_i_IORequestIndex_CSBGAME, 16, (long)P5737_);
        F1859_SetIORequestValue(G3638_i_IORequestIndex_CSBGAME, 8, (long)P5736_);
        L5609_ = F1857_PerformIORequestOperation(G3638_i_IORequestIndex_CSBGAME, C07_READ_FILE);
        return (L5609_ == 0);
}

unsigned int16_t F7055_F0417_SAVEUTIL_GetChecksumAndObfuscate(P0804_pui_Buffer, P0805_ui_Key, P0806_ui_WordCount)
register unsigned int16_t* P0804_pui_Buffer;
register unsigned int16_t P0805_ui_Key;
register unsigned int16_t P0806_ui_WordCount;
{
        register unsigned int16_t L1282_ui_Checksum;


        L1282_ui_Checksum = P0805_ui_Key;
        do {
                L1282_ui_Checksum += *P0804_pui_Buffer;
                *P0804_pui_Buffer ^= P0805_ui_Key;
                L1282_ui_Checksum += *P0804_pui_Buffer++;
                P0805_ui_Key += P0806_ui_WordCount;
        } while (--P0806_ui_WordCount);
        return L1282_ui_Checksum;
}

unsigned int16_t F7056_F0418_SAVEUTIL_GetChecksum(P0807_pui_Buffer, P0808_ui_Key, P0809_ui_WordCount)
register unsigned int16_t* P0807_pui_Buffer;
register unsigned int16_t P0808_ui_Key;
register unsigned int16_t P0809_ui_WordCount;
{
        register unsigned int16_t L1283_ui_Checksum;


        L1283_ui_Checksum = P0808_ui_Key;
        do {
                L1283_ui_Checksum += *P0807_pui_Buffer;
                L1283_ui_Checksum += *P0807_pui_Buffer++ ^ P0808_ui_Key;
                P0808_ui_Key += P0809_ui_WordCount;
        } while (--P0809_ui_WordCount);
        return L1283_ui_Checksum;
}

BOOLEAN F1913_LoadAndDeobfuscateSavedGamePart(unsigned char* P3578_puc_Buffer, unsigned int16_t P3579_ui_Size, unsigned int16_t P3580_ui_Key, unsigned int16_t P3581_ui_Checksum)
{
        return F1910_LoadSavedGamePart(P3578_puc_Buffer, P3579_ui_Size) && (F7055_F0417_SAVEUTIL_GetChecksumAndObfuscate(P3578_puc_Buffer, P3580_ui_Key, P3579_ui_Size >> 1) == P3581_ui_Checksum);
}

BOOLEAN F1914_LoadAndDeobfuscateSavedGameHeader(int16_t* P5748_) {
        register int16_t* L5737_;
        register int16_t L5612_;
        register int16_t L5613_;
        register int16_t L5614_;


        L5737_ = P5748_;
        if (F1910_LoadSavedGamePart(L5737_, 512) == 0) {
                F1956_EndProgram(20, 17, 222L);
                return C0_FALSE;
        }
        L5612_ = 32;
        L5613_ = 0;
        do {
                L5613_ += *L5737_++;
                L5613_ ^= *L5737_++;
                L5613_ -= *L5737_++;
                L5613_ ^= *L5737_++;
        } while (--L5612_);
        F7055_F0417_SAVEUTIL_GetChecksumAndObfuscate(L5737_, P5748_[C29_CSB_SAVE_HEADER_DECRYPTION_KEY_INDEX], 128);
        L5614_ = 0;
        L5612_ = 128;
        do {
                L5614_ += *L5737_++;
        } while (--L5612_);
        if (L5613_ != L5614_) {
                F1956_EndProgram(20, 17, 223L);
        }
        return (L5613_ == L5614_);
}

void F1915_UnloadGame(int16_t P5749_) {
        register GAME_HINT* L5615_;
        register int16_t L5616_;


        L5615_ = &G3623_Game[P5749_];
        if (L5615_->ActiveGroups) {
                F1921_FreeMemory(L5615_->ActiveGroups);
        }
        L5615_->ActiveGroups = NULL;
        if (L5615_->Events) {
                F1921_FreeMemory(L5615_->Events);
        }
        L5615_->Events = NULL;
        if (L5615_->TimeLine) {
                F1921_FreeMemory(L5615_->TimeLine);
        }
        L5615_->TimeLine = NULL;
        if (L5615_->Dungeon.TextData) {
                F1921_FreeMemory(L5615_->Dungeon.TextData);
        }
        L5615_->Dungeon.TextData = NULL;
        if (L5615_->Dungeon.RawMapData) {
                F1921_FreeMemory(L5615_->Dungeon.RawMapData);
        }
        L5615_->Dungeon.RawMapData = NULL;
        if (L5615_->Dungeon.Header) {
                F1921_FreeMemory(L5615_->Dungeon.Header);
        }
        L5615_->Dungeon.Header = NULL;
        if (L5615_->Dungeon.Maps) {
                F1921_FreeMemory(L5615_->Dungeon.Maps);
        }
        L5615_->Dungeon.Maps = NULL;
        if (L5615_->Dungeon.ColumnsCumulativeSquareThingCount) {
                F1921_FreeMemory(L5615_->Dungeon.ColumnsCumulativeSquareThingCount);
        }
        L5615_->Dungeon.ColumnsCumulativeSquareThingCount = NULL;
        if (L5615_->Dungeon.MapsFirstColumnIndex) {
                F1921_FreeMemory(L5615_->Dungeon.MapsFirstColumnIndex);
        }
        L5615_->Dungeon.MapsFirstColumnIndex = NULL;
        if (L5615_->Dungeon.SquareFirstThings) {
                F1921_FreeMemory(L5615_->Dungeon.SquareFirstThings);
        }
        L5615_->Dungeon.SquareFirstThings = NULL;
        for (L5616_ = 0; L5616_ < 16; L5616_++) {
                if (L5615_->Dungeon.ThingData[L5616_]) {
                        F1921_FreeMemory(L5615_->Dungeon.ThingData[L5616_]);
                }
                L5615_->Dungeon.ThingData[L5616_] = NULL;
        }
        if (P5749_ == 0) {
                G3718_ui_PartyChampionCount = 0;
        }
        L5615_->GameLoaded = C0_FALSE;
}

#ifdef MEDIA772_SU1E
#ifndef NOCOPYPROTECTION
void F1916_Pre_F1918_LoadGame_CPSX(
)
{
#include "FAKE1.C"
}
#endif
#endif

int16_t F1918_LoadGame_CPSX(register int16_t P5752_) {
        register GAME_HINT* L5617_;
        register int16_t L5618_;
        int16_t L5619_i_MapCount;
        int16_t L5620_;
        int16_t L5748_i_Unreferenced;
        long L5621_;
        long L5622_;
        long L5623_;


        L5617_ = &G3623_Game[P5752_];
        G3638_i_IORequestIndex_CSBGAME = F1855_GetAvailableIORequestIndex();
        if (G3638_i_IORequestIndex_CSBGAME == -1) {
                L5623_ = 83;
        } else {
                F1931_(20, 40, (long)G3638_i_IORequestIndex_CSBGAME, G3637_apc_FileNames[C4_CSBGAME_DAT], -1L);
                L5622_ = F1857_PerformIORequestOperation(G3638_i_IORequestIndex_CSBGAME, C02_OPEN_FILE);
                if (L5622_) {
                        L5623_ = 84;
                } else {
                        F1915_UnloadGame(P5752_);
                        if (F1914_LoadAndDeobfuscateSavedGameHeader(&L5617_->SaveHeader) == 0) {
                                L5623_ = 213;
#ifdef MEDIA772_SU1E
                        } else {
#ifndef NOCOPYPROTECTION
                                L5619_i_MapCount = F1944_ChecksumAdd(*((char**)((char*)F1899_Pre_F1901_CopyProtectionRoutine_CPSX + 2)), *((char**)((char*)F1902_Post_F1901_CopyProtectionRoutine_CPSX + 2)));
                                asm {
                                                movem.l d4/a3,-(sp)
                                                lea     @Tloc_692C,a3
                                                move.w  L5619_i_MapCount(a6),d4
                                                cmp.w   6(a3),d4
                                                beq.s   @Tloc_694A
                                                move.w  #1,L5619_i_MapCount(a6)
                                                bra.s   @Tloc_6950
                                        @Tloc_692C:
                                                move.w  #0xC8,d1
                                                move.w  #0x635F,d1
                                                add.w   L5620_(a6),d1
                                                beq.s   @Tloc_6948
                                                move.w  L5621_(a6),d1
                                                cmp.w   d0,d1
                                                beq.s   @Tloc_6948
                                                move.w  #0xFFFF,d0
                                                bra.s   @Tloc_694A
                                        @Tloc_6948:
                                                asl.w   #1,d0
                                        @Tloc_694A:
                                                move.w  #0,L5619_i_MapCount(a6)
                                        @Tloc_6950:
                                                movem.l (sp)+,d4/a3
                                }
                                if (L5619_i_MapCount + 89 != 89) {
                                        F1956_EndProgram(17, 18, 506L);
                                }
#endif
                                if (F1913_LoadAndDeobfuscateSavedGamePart(&L5617_->GlobalData, sizeof(GLOBAL_DATA), L5617_->SaveHeader.Keys[0], L5617_->SaveHeader.Checksums[0]) == 0) {
                                        L5623_ = 214;
                                } else {
                                        L5617_->ActiveGroups = F1920_AllocateMemory((long)(L5617_->GlobalData.MaximumActiveGroupCount * sizeof(ACTIVE_GROUP)));
                                        if (F1913_LoadAndDeobfuscateSavedGamePart(L5617_->ActiveGroups, L5617_->GlobalData.MaximumActiveGroupCount * sizeof(ACTIVE_GROUP), L5617_->SaveHeader.Keys[1], L5617_->SaveHeader.Checksums[1]) == 0) {
                                                L5623_ = 215;
                                        } else {
                                                if (F1913_LoadAndDeobfuscateSavedGamePart(&L5617_->Party, sizeof(PARTY_INFO), L5617_->SaveHeader.Keys[2], L5617_->SaveHeader.Checksums[2]) == 0) {
                                                        L5623_ = 216;
                                                } else {
                                                        if (L5617_->SaveHeader.FormatID == C0x01_SAVE_HEADER_FORMAT_DUNGEON_MASTER) {
                                                                L5622_ = F1857_PerformIORequestOperation(G3638_i_IORequestIndex_CSBGAME, C11_GET_CURRENT_POSITION);
                                                                L5621_ = F1861_GetIORequestOutputValue(G3638_i_IORequestIndex_CSBGAME) + (L5617_->GlobalData.EventMaximumCount * sizeof(EVENT)) + (L5617_->GlobalData.EventMaximumCount * sizeof(int16_t));
                                                                F1859_SetIORequestValue(G3638_i_IORequestIndex_CSBGAME, 16, L5621_);
                                                                L5622_ = F1857_PerformIORequestOperation(G3638_i_IORequestIndex_CSBGAME, C09_SET_CURRENT_POSITION);
                                                                if (L5622_) {
                                                                        L5623_ = 220;
                                                                } else {
                                                                        L5617_->Dungeon.Header = F1920_AllocateMemory((long)sizeof(DUNGEON_HEADER));
                                                                        F1859_SetIORequestValue(G3638_i_IORequestIndex_CSBGAME, 16, (long)sizeof(DUNGEON_HEADER));
                                                                        F1859_SetIORequestValue(G3638_i_IORequestIndex_CSBGAME, 8, (long)L5617_->Dungeon.Header);
                                                                        L5622_ = F1857_PerformIORequestOperation(G3638_i_IORequestIndex_CSBGAME, C07_READ_FILE);
                                                                        if (L5622_) {
                                                                                L5623_ = 221;
                                                                        } else {
                                                                                L5619_i_MapCount = (char)L5617_->Dungeon.Header->MapCount;
                                                                                F1921_FreeMemory(L5617_->Dungeon.Header);
                                                                                if (L5619_i_MapCount == 10) {
                                                                                        goto loc_6B22;
                                                                                }
                                                                                L5623_ = 224;
                                                                                asm { nop } /* Fix .s branch size (.w in original) */
                                                                        }
                                                                }
                                                        } else {
                                                                if ((L5617_->SaveHeader.DungeonID != C13_DUNGEON_CSB_GAME) || (L5617_->SaveHeader.Platform != C1_PLATFORM_ATARI_ST)) {
                                                                        L5623_ = 224;
                                                                } else {
                                                                        loc_6B22:
                                                                        G3717_ = 0;
                                                                        if (P5752_ == 0) {
                                                                                G3718_ui_PartyChampionCount = L5617_->GlobalData.PartyChampionCount;
                                                                        }
                                                                        L5617_->GameLoaded = C1_TRUE;
                                                                        L5618_ = 100;
                                                                        L5622_ = F1857_PerformIORequestOperation(G3638_i_IORequestIndex_CSBGAME, C10_CLOSE_FILE);
                                                                        F1856_CloseFile(G3638_i_IORequestIndex_CSBGAME);
                                                                        return L5618_;
                                                                }
                                                        }
                                                }
                                        }
                                }
                        }
#endif
#ifdef MEDIA763_AU1E_AU2E
                                goto loc_3028;
                        }
                        if (F1913_LoadAndDeobfuscateSavedGamePart(&L5617_->GlobalData, sizeof(GLOBAL_DATA), L5617_->SaveHeader.Keys[0], L5617_->SaveHeader.Checksums[0]) == 0) {
                                L5623_ = 214;
                                goto loc_3028;
                        }
                        L5617_->ActiveGroups = F1920_AllocateMemory((long)(L5617_->GlobalData.MaximumActiveGroupCount * sizeof(ACTIVE_GROUP)));
                        if (F1913_LoadAndDeobfuscateSavedGamePart(L5617_->ActiveGroups, L5617_->GlobalData.MaximumActiveGroupCount * sizeof(ACTIVE_GROUP), L5617_->SaveHeader.Keys[1], L5617_->SaveHeader.Checksums[1]) == 0) {
                                L5623_ = 215;
                                goto loc_3028;
                        }
                        if (F1913_LoadAndDeobfuscateSavedGamePart(&L5617_->Party, sizeof(PARTY_INFO), L5617_->SaveHeader.Keys[2], L5617_->SaveHeader.Checksums[2]) == 0) {
                                L5623_ = 216;
                                goto loc_3028;
                        }
                        if (L5617_->SaveHeader.FormatID == C0x01_SAVE_HEADER_FORMAT_DUNGEON_MASTER) {
                                L5622_ = F1857_PerformIORequestOperation(G3638_i_IORequestIndex_CSBGAME, C11_GET_CURRENT_POSITION);
                                L5621_ = F1861_GetIORequestOutputValue(G3638_i_IORequestIndex_CSBGAME) + (L5617_->GlobalData.EventMaximumCount * sizeof(EVENT)) + (L5617_->GlobalData.EventMaximumCount * sizeof(int16_t));
                                F1859_SetIORequestValue(G3638_i_IORequestIndex_CSBGAME, 16, L5621_);
                                L5622_ = F1857_PerformIORequestOperation(G3638_i_IORequestIndex_CSBGAME, C09_SET_CURRENT_POSITION);
                                if (L5622_) {
                                        L5623_ = 220;
                                        goto loc_3028;
                                }
                                L5617_->Dungeon.Header = F1920_AllocateMemory((long)sizeof(DUNGEON_HEADER));
                                F1859_SetIORequestValue(G3638_i_IORequestIndex_CSBGAME, 16, (long)sizeof(DUNGEON_HEADER));
                                F1859_SetIORequestValue(G3638_i_IORequestIndex_CSBGAME, 8, (long)L5617_->Dungeon.Header);
                                L5622_ = F1857_PerformIORequestOperation(G3638_i_IORequestIndex_CSBGAME, C07_READ_FILE);
                                if (L5622_) {
                                        L5623_ = 221;
                                        goto loc_3028;
                                }
                                L5619_i_MapCount = (char)L5617_->Dungeon.Header->MapCount;
                                F1921_FreeMemory(L5617_->Dungeon.Header);
                                if (L5619_i_MapCount != 10) {
                                        L5623_ = 224;
                                        asm { nop } /* ANOMALY Branch size fix */
                                        goto loc_3028;
                                }
                        } else {
                                if ((L5617_->SaveHeader.DungeonID != C13_DUNGEON_CSB_GAME) || (L5617_->SaveHeader.Platform != C3_PLATFORM_AMIGA)) {
                                        L5623_ = 224;
                                        goto loc_3028;
                                }
                        }
                        G3717_ = 0;
                        if (P5752_ == 0) {
                                G3718_ui_PartyChampionCount = L5617_->GlobalData.PartyChampionCount;
                        }
                        L5617_->GameLoaded = C1_TRUE;
                        L5618_ = 100;
                        L5622_ = F1857_PerformIORequestOperation(G3638_i_IORequestIndex_CSBGAME, C10_CLOSE_FILE);
                        F1856_CloseFile(G3638_i_IORequestIndex_CSBGAME);
                        return L5618_;
                        loc_3028:
#endif
                        F1857_PerformIORequestOperation(G3638_i_IORequestIndex_CSBGAME, C10_CLOSE_FILE);
                }
        }
        F1856_CloseFile(G3638_i_IORequestIndex_CSBGAME);
        F1956_EndProgram(20, 17, L5623_);
        F1915_UnloadGame(P5752_);
        return (L5623_ != 84) ? -1 : -2;
}

#ifdef MEDIA772_SU1E
#ifndef NOCOPYPROTECTION
void F1919_Post_F1918_LoadGame_CPSX(
)
{
#include "FAKE3.C"
}
#endif
#endif
#endif
