#ifndef COMPILE_H
#include "COMPILE.H"
#endif
#ifdef MEDIA042_S10EA_S10EB_S11E_S12E_S12G_S13FA_S13FB_S20E_S21E_G14ED_G20E_G21E_A20ED_A20E_A20F_A20G_A21E_A22E_A22G_F20E_F20J_X30J_P20JA_P20JB_I34E_I34M_A36M_A31E_A31M_A33M_A35E_A35M_F31E_F31J_X31J_P31J
#ifdef MEDIA711_I34E_I34M_F31E_F31J
extern void F0743_MUSIC_Update(
int P2558_i_MapX     SEPARATOR /* ANOMALY_FMT Parameters declared as int but actually int16_t */
int P2559_i_MapY     SEPARATOR
int P2560_i_MapIndex
);
#endif

#ifdef MEDIA603_X30J_A31E_A31M_A33M_A35E_A35M_X31J
#ifndef NOCOPYPROTECTION
int16_t G0068_i_CheckLastEvent22Time_CPSE = C00512_FALSE;
#endif
#endif


#ifdef MEDIA007_S10EA_S10EB_S11E_S12E_S12G_S13FA_S13FB_S20E_S21E
overlay "main"
#endif
#ifdef MEDIA351_G14ED_G20E_G21E
segment "main"
#endif

#ifdef MEDIA413_A20ED_A20E_A20F_A20G_A21E_A22E_A22G
#include "COPYPRO1.C"
#endif

#ifdef MEDIA529_F20E_F20J_X30J_P20JA_P20JB_I34E_I34M_A36M_A31E_A31M_A33M_A35E_A35M_F31E_F31J_X31J_P31J
#include "NEWMAP.C"
#endif

STATICFUNCTION void F0002_MAIN_GameLoop_CPSDF(
#ifdef MEDIA529_F20E_F20J_X30J_P20JA_P20JB_I34E_I34M_A36M_A31E_A31M_A33M_A35E_A35M_F31E_F31J_X31J_P31J
void
#endif
)
{
#ifdef MEDIA720_I34E_I34M_A36M_A31E_A31M_A33M_A35E_A35M_F31E_F31J_X31J_P31J
        REGISTER int16_t L1891_i_Square;
#endif


#ifdef MEDIA029_S10EA_S10EB_S11E_S12E_S12G_S13FA_S13FB_S20E_S21E_G14ED_G20E_G21E_A20ED_A20E_A20F_A20G_A21E_A22E_A22G_F20E_F20J_X30J_P20JA_P20JB_F31E_F31J
        G0318_i_WaitForInputMaximumVerticalBlankCount = 10;
#endif
#ifdef MEDIA722_I34E_I34M_A36M_A31E_A31M_A33M_A35E_A35M_X31J_P31J
        G0318_i_WaitForInputMaximumVerticalBlankCount = 12;
#endif
#ifdef MEDIA593_X30J_P20JA_P20JB_I34E_I34M_A36M_A31E_A31M_A33M_A35E_A35M_F31E_F31J_X31J_P31J
        G2062_DialogSetIndex = C0_DIALOG_SET_VIEWPORT;
#endif
        for (;;) { /*_Infinite loop_*/
                G0317_i_WaitForInputVerticalBlankCount = 0;
#ifdef MEDIA128_S10EA_S10EB_S11E_S12E_S12G_S13FA_S13FB_S20E_S21E_G20E_G21E_A20E_A20F_A20G_A21E_A22E_A22G_F20E_F20J_X30J_P20JA_P20JB_I34E_I34M_A36M_A31E_A31M_A33M_A35E_A35M_F31E_F31J_X31J_P31J
                if (G0327_i_NewPartyMapIndex != CM1_MAP_INDEX_NONE) {
                        T0002002:
                        F0003_MAIN_ProcessNewPartyMap_CPSE(G0327_i_NewPartyMapIndex);
                        F0267_MOVE_GetMoveResult_CPSCE(C0xFFFF_THING_PARTY, CM1_MAPX_NOT_ON_A_SQUARE, 0, G0306_i_PartyMapX, G0307_i_PartyMapY);
                        G0327_i_NewPartyMapIndex = CM1_MAP_INDEX_NONE;
                        F0357_COMMAND_DiscardAllInput();
                }
#endif
#ifdef MEDIA488_F20E_F20J
                F0743_MUSIC_Update();
#endif
                F0261_TIMELINE_Process_CPSEF();
#ifdef MEDIA128_S10EA_S10EB_S11E_S12E_S12G_S13FA_S13FB_S20E_S21E_G20E_G21E_A20E_A20F_A20G_A21E_A22E_A22G_F20E_F20J_X30J_P20JA_P20JB_I34E_I34M_A36M_A31E_A31M_A33M_A35E_A35M_F31E_F31J_X31J_P31J
                if (G0327_i_NewPartyMapIndex != CM1_MAP_INDEX_NONE)
                        goto T0002002;
#endif
#ifdef MEDIA469_P20JB
                F0743_MUSIC_Update();
#endif
#ifdef MEDIA712_I34E_I34M_F31E_F31J_P31J
                F0743_MUSIC_Update(G0306_i_PartyMapX, G0307_i_PartyMapY, G0309_i_PartyMapIndex);
#endif
#ifdef MEDIA014_S10EA_S10EB_S11E_S12E_S12G_S13FA_S13FB_S20E_S21E_G14ED_G20E_G21E_A20ED_A20E_A20F_A20G_A21E_A22E_A22G_F20E_F20J
                if (!G0423_i_InventoryChampionOrdinal && !G0300_B_PartyIsResting) {
#endif
#ifdef MEDIA593_X30J_P20JA_P20JB_I34E_I34M_A36M_A31E_A31M_A33M_A35E_A35M_F31E_F31J_X31J_P31J
                if (!G0300_B_PartyIsResting) {
                        if (!G0299_ui_CandidateChampionOrdinal) {
                                F0457_START_DrawEnabledMenus_CPSF();
                        }
                        if (!G0423_i_InventoryChampionOrdinal) {
#endif
                                F0128_DUNGEONVIEW_Draw_CPSF(G0308_i_PartyDirection, G0306_i_PartyMapX, G0307_i_PartyMapY);
                                if (G0325_B_SetMousePointerToObjectInMainLoop) {
                                        G0325_B_SetMousePointerToObjectInMainLoop = C0_FALSE;
                                        F0077_MOUSE_EnableScreenUpdate_CPSE();
                                        F0068_MOUSE_SetPointerToObject(G4055_s_LeaderHandObject.BitmapIconForMousePointer);
                                        F0078_MOUSE_DisableScreenUpdate();
                                }
                                if (G0326_B_RefreshMousePointerInMainLoop) {
                                        G0326_B_RefreshMousePointerInMainLoop = C0_FALSE;
                                        G0598_B_MousePointerBitmapUpdated = C1_TRUE;
                                        F0077_MOUSE_EnableScreenUpdate_CPSE();
                                        F0078_MOUSE_DisableScreenUpdate();
                                }
#ifdef MEDIA629_A31E_A31M_A33M_A35E_A35M_F31E_F31J_X31J_P31J
                        } else {
                                if ((G0424_i_PanelContent == C09_PANEL_CREATURE_NAME_SCROLL) || (G0424_i_PanelContent == C10_PANEL_MAGIC_MAP_SCROLL)) {
                                        M008_SET(M516_CHAMPIONS[M001_ORDINAL_TO_INDEX(G0423_i_InventoryChampionOrdinal)].Attributes, MASK0x0800_PANEL);
                                        F0292_CHAMPION_DrawState(M001_ORDINAL_TO_INDEX(G0423_i_InventoryChampionOrdinal));
                                }
#endif
#ifdef MEDIA593_X30J_P20JA_P20JB_I34E_I34M_A36M_A31E_A31M_A33M_A35E_A35M_F31E_F31J_X31J_P31J
                        }
#endif
                }
                F0363_COMMAND_HighlightBoxDisable();
                F0065_SOUND_PlayPendingSound_CPSD();
                F0320_CHAMPION_ApplyAndDrawPendingDamageAndWounds();
                if (G0303_B_PartyDead)
                        break;
#ifdef MEDIA707_I34E_I34M
                if (G2151_ExitGameImmediately) {
                        break;
                }
#endif
                G0313_ul_GameTime++; /* BUG0_02 After playing a single game for hundreds of hours (in one row or across multiple save/load cycles) the game starts to behave strangely and then hangs. Even though the game time is stored in a 32 bit value, event times in the timeline are stored on 24 bits so the maximum possible time value is 2^24 - 1 = 16777215 (around 850 to 1000 hours of actual play time). Issues occur because new events scheduled to occur in the future are actually scheduled in the past and then expire immediately. For example, if you use the 'Light' action of the Yew Staff or Sceptre Of Lyf when G0313_ul_GameTime = 16776500 then in F0407_MENUS_IsActionPerformed an event to remove the light will be scheduled at (16775000 + 2500) Mod 2^24 = 284 and will thus expire immediately so that the light will only be visible for a very short moment. When G0313_ul_GameTime reaches 16777200 (the largest multiple of 300 that is smaller than the maximum value of 16777216), in F0256_TIMELINE_ProcessEvent53_Watchdog_CPSE the time of the next C53_EVENT_WATCHDOG is set to (16777200 + 300) Mod 2^24 = 284 and thus expires immediately. F0261_TIMELINE_Process_CPSEF then enters an infinite loop where it constantly processes the same event C53_EVENT_WATCHDOG, causing the game to hang. Fixing this bug could be done by substracting a fixed amount (like 15000000) from all time values stored in the game (all events and some global variables) when the time reaches a maximum value, like 16000000 */
                if (!((int16_t)G0313_ul_GameTime & 511)) {
                        F0338_INVENTORY_DecreaseTorchesLightPower_CPSE();
                }
                if (G0407_s_Party.FreezeLifeTicks) {
                        --G0407_s_Party.FreezeLifeTicks;
                }
                F0390_MENUS_RefreshActionAreaAndSetChampionDirectionMaximumDamageReceived();
#ifdef MEDIA002_S10EA_S10EB_S11E /* CHANGE3_00_IMPROVEMENT Faster regeneration */
                if (!((unsigned int16_t)G0313_ul_GameTime & 63)) {
#endif
#ifdef MEDIA240_S12E_S12G_S13FA_S13FB_S20E_S21E_G14ED_G20E_G21E_A20ED_A20E_A20F_A20G_A21E_A22E_A22G_F20E_F20J_X30J_P20JA_P20JB_I34E_I34M_A36M_A31E_A31M_A33M_A35E_A35M_F31E_F31J_X31J_P31J /* CHANGE3_00_IMPROVEMENT Faster regeneration while resting */
                if (!((unsigned int16_t)G0313_ul_GameTime & (G0300_B_PartyIsResting ? 15 : 63))) { /* ANOMALY_ASSEMBLY_COMPILATION_DIFFERENCE test */
#endif
                        F0331_CHAMPION_ApplyTimeEffects_CPSF();
#ifdef MEDIA388_G20E_G21E
                        if (G0300_B_PartyIsResting) {
                                F0331_CHAMPION_ApplyTimeEffects_CPSF();
                        }
#endif
                }
#ifdef MEDIA720_I34E_I34M_A36M_A31E_A31M_A33M_A35E_A35M_F31E_F31J_X31J_P31J
                if (G2149_) {
                        F0293_CHAMPION_DrawAllChampionStates(MASK0x0000_NONE);
                }
#endif
                if (G0310_i_DisabledMovementTicks) {
                        G0310_i_DisabledMovementTicks--;
                }
                if (G0311_i_ProjectileDisabledMovementTicks) {
                        G0311_i_ProjectileDisabledMovementTicks--;
                }
                F0044_TEXT_MESSAGEAREA_ClearExpiredRows();
#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
                if (G0374_l_WatchdogTime_CPSE < G0313_ul_GameTime) {
                        F0019_MAIN_DisplayErrorAndStop(C60_ERROR_EVENT_PROCESSING_STOPPED);
                }
#endif
#endif
                G0321_B_StopWaitingForPlayerInput = C0_FALSE;
                do {
                        while (M527_IsCharacterInKeyboardBuffer()) {
                                F0361_COMMAND_ProcessKeyPress(M528_GetCharacterInKeyboardBuffer());
                        }
#ifdef MEDIA022_S10EA_S10EB_S11E_S12E_S12G_S13FA_S13FB_S20E_S21E_G14ED_G20E_G21E_A20ED_A20E_A20F_A20G_A21E_A22E_A22G_F20E_F20J_X30J_P20JA_P20JB_A31E_A31M_A33M_F31E_F31J_X31J_P31J
                        if (G0332_B_StopPressingEye) {
#ifdef MEDIA290_S20E_S21E_G20E_G21E_A20ED_A20E_A20F_A20G_A21E_A22E_A22G_F20E_F20J_X30J_P20JA_P20JB_A31E_A31M_A33M_F31E_F31J_X31J_P31J /* CHANGE7_02_FIX G0331_B_PressingEye is set to C0_FALSE here instead of immediately when the mouse button is released in mouse exception handler S0076_MOUSE_OnMouseButtonsStatusChange. This ensures that G0331_B_PressingEye cannot be C1_TRUE when F0380_COMMAND_ProcessQueue_CPSC is called below and C0_FALSE when reaching the test added on G0331_B_PressingEye in F0380_COMMAND_ProcessQueue_CPSC in the case where the mouse button is released in between */
                                G0331_B_PressingEye = C0_FALSE;
#endif
                                G0332_B_StopPressingEye = C0_FALSE;
                                F0353_INVENTORY_DrawStopPressingEye();
                        }
#ifdef MEDIA020_S10EA_S10EB_S11E_S12E_S12G_S13FA_S13FB_S20E_S21E_G14ED_G20E_G21E_A20ED_A20E_A20F_A20G_A21E_A22E_A22G_F20E_F20J_X30J_P20JA_P20JB
                          else {
#endif
                                if (G0334_B_StopPressingMouth) {
#ifdef MEDIA290_S20E_S21E_G20E_G21E_A20ED_A20E_A20F_A20G_A21E_A22E_A22G_F20E_F20J_X30J_P20JA_P20JB_A31E_A31M_A33M_F31E_F31J_X31J_P31J /* CHANGE7_02_FIX G0333_B_PressingMouth is set to C0_FALSE here instead of immediately when the mouse button is released in mouse exception handler S0076_MOUSE_OnMouseButtonsStatusChange. This ensures that G0333_B_PressingMouth cannot be C1_TRUE when F0380_COMMAND_ProcessQueue_CPSC is called below and C0_FALSE when reaching the test added on G0333_B_PressingMouth in F0380_COMMAND_ProcessQueue_CPSC in the case where the mouse button is released in between */
                                        G0333_B_PressingMouth = C0_FALSE;
#endif
                                        G0334_B_StopPressingMouth = C0_FALSE;
                                        F0350_INVENTORY_DrawStopPressingMouth();
                                }
#endif
#ifdef MEDIA622_A31E_A31M_A33M_F31E_F31J_X31J_P31J
                        if (G2229_B_StopPressingClosedImaginaryFakeWall || (G2152_B_PressingClosedImaginaryFakeWall && ((M034_SQUARE_TYPE(L1891_i_Square = F0152_DUNGEON_GetRelativeSquare(G0308_i_PartyDirection, 1, 0, G0306_i_PartyMapX, G0307_i_PartyMapY)) != C06_ELEMENT_FAKEWALL) || !M007_GET(MASK0x0001_FAKEWALL_IMAGINARY, L1891_i_Square) || M007_GET(MASK0x0004_FAKEWALL_OPEN, L1891_i_Square)))) {
#endif
#ifdef MEDIA728_I34E_I34M_A36M_A35E_A35M
                        if (G2152_B_PressingClosedImaginaryFakeWall && ((M034_SQUARE_TYPE(L1891_i_Square = F0152_DUNGEON_GetRelativeSquare(G0308_i_PartyDirection, 1, 0, G0306_i_PartyMapX, G0307_i_PartyMapY)) != C06_ELEMENT_FAKEWALL) || !M007_GET(MASK0x0001_FAKEWALL_IMAGINARY, L1891_i_Square) || M007_GET(MASK0x0004_FAKEWALL_OPEN, L1891_i_Square))) {
#endif
#ifdef MEDIA720_I34E_I34M_A36M_A31E_A31M_A33M_A35E_A35M_F31E_F31J_X31J_P31J
                                G2152_B_PressingClosedImaginaryFakeWall = C0_FALSE;
#endif
#ifdef MEDIA622_A31E_A31M_A33M_F31E_F31J_X31J_P31J
                                if (G2229_B_StopPressingClosedImaginaryFakeWall) {
                                        G2229_B_StopPressingClosedImaginaryFakeWall = C0_FALSE;
                                } else {
#endif
#ifdef MEDIA720_I34E_I34M_A36M_A31E_A31M_A33M_A35E_A35M_F31E_F31J_X31J_P31J
                                        G0597_B_IgnoreMouseMovements = C0_FALSE;
#endif
#ifdef MEDIA622_A31E_A31M_A33M_F31E_F31J_X31J_P31J
                                }
#endif
#ifdef MEDIA725_I34E_I34M_A36M_A33M_A35E_A35M
                                G0587_i_HideMousePointerRequestCount = 1;
#endif
#ifdef MEDIA720_I34E_I34M_A36M_A31E_A31M_A33M_A35E_A35M_F31E_F31J_X31J_P31J
                                M523_MOUSE_ShowPointer();
#endif
                        }
                        F0380_COMMAND_ProcessQueue_CPSC();
                        if (!G0321_B_StopWaitingForPlayerInput) {
                                F0363_COMMAND_HighlightBoxDisable();
                        }
                } while (!G0321_B_StopWaitingForPlayerInput || !G0301_B_GameTimeTicking);
#ifdef MEDIA153_S10EA_S10EB_S11E_S12E_S12G_S13FA_S13FB_S20E_S21E_A20ED_A20E_A20F_A20G_A21E_A22E_A22G_A31E_A31M_A33M_A35E_A35M
#ifndef NOCOPYPROTECTION
                /* If there is a copy protection sector read failure and the previous read succeeded */
                if (!((int16_t)G0313_ul_GameTime & 63) && (G0315_i_SectorsReadFailure_CPSDF & ~G0316_i_SectorsReadPreviousFailure_CPSDF)) {
#ifdef MEDIA137_S10EA_S10EB_S11E_S12E_S12G_S13FA_S13FB_S20E_S21E_A20ED_A20E_A20F_A20G_A21E_A22E_A22G
                        F0456_START_DrawDisabledMenus();
#endif
#ifdef MEDIA006_S10EA_S10EB_S11E_S12E_S12G_S13FA_S13FB /* CHANGE7_03_IMPROVEMENT */
                        F0428_DIALOG_RequireGameDiskInDrive_NoDialogDrawn(C1_FORCE_DIALOG_DM, C0_FALSE);
#endif
#ifdef MEDIA310_S20E_S21E_A20ED_A20E_A20F_A20G_A21E_A22E_A22G /* CHANGE7_03_IMPROVEMENT Support for two floppy disk drives */
                        F0428_DIALOG_RequireGameDiskInDrive_NoDialogDrawn(C2_FORCE_DIALOG_CSB, C0_FALSE);
#endif
#ifdef MEDIA626_A31E_A31M_A33M_A35E_A35M
                        F0428_DIALOG_RequireGameDiskInDrive_NoDialogDrawn(C2_FORCE_DIALOG_CSB);
#endif
#ifdef MEDIA137_S10EA_S10EB_S11E_S12E_S12G_S13FA_S13FB_S20E_S21E_A20ED_A20E_A20F_A20G_A21E_A22E_A22G
                        F0457_START_DrawEnabledMenus_CPSF();
#endif
                        G0316_i_SectorsReadPreviousFailure_CPSDF = G0315_i_SectorsReadFailure_CPSDF;
                }
#endif
#endif
        }
}

#ifdef MEDIA009_S10EA_S10EB_S11E_S12E_S12G_S13FA_S13FB_S20E_S21E_G14ED_G20E_G21E_A20ED_A20E_A20F_A20G_A21E_A22E_A22G
#include "NEWMAP.C"

int16_t main(
)
#endif
#ifdef MEDIA516_F20E_F20J_X30J_P20JA_P20JB_F31E_F31J_P31J
void main(
void
)
#endif
#ifdef MEDIA749_A36M_A31E_A31M_A33M_A35E_A35M_X31J
int16_t main(
long P2788_ SEPARATOR
long P2789_ FINAL_SEPARATOR
#endif
#ifdef MEDIA707_I34E_I34M
void main(
int16_t argc SEPARATOR
char* argv[] FINAL_SEPARATOR
#endif
{
#ifdef MEDIA007_S10EA_S10EB_S11E_S12E_S12G_S13FA_S13FB_S20E_S21E
        asm { /* Backup A4 and A5 registers so these addresses can be accessed when running exception handlers */
                lea     V0011000_A4RegisterBackup(PC),A0
                move.l  A4,(A0)                                 /* Backup copy of A4 register. Megamax C stores the address of the DATA segment (positive offsets) and BSS segment (negative offsets) in A4 */
                lea     V0012000_A5RegisterBackup(PC),A0
                move.l  A5,(A0)                                 /* Backup copy of A5 register. Megamax C stores the address of the JUMPTABLE in A5 */
        }
#endif
#ifdef MEDIA707_I34E_I34M
        int16_t L2656_i_ArgumentIndex;


        for (L2656_i_ArgumentIndex = 1; L2656_i_ArgumentIndex < argc; L2656_i_ArgumentIndex++) {
                if (argv[L2656_i_ArgumentIndex][0] == '-') {
                        if (argv[L2656_i_ArgumentIndex][1] != '\0') {
                                switch (toupper(argv[L2656_i_ArgumentIndex][1])) {
                                        case 'M':       /* 4D */
                                                G2024_B_PendingMusicOn = C1_TRUE;
                                                G2106_B_ShowMusicState = C1_TRUE;
                                                break;
                                        case 'D':       /* 44 */
                                                G2131_B_Unused = C1_TRUE;
                                                break;
                                        case '$':       /* 24 */
                                                G2132_B_DotNotUseEMS = C1_TRUE;
                                                break;
                                        case 'X':       /* 58 */
                                                G0298_B_NewGame = C000_MODE_LOAD_SAVED_GAME;
                                                break;
#ifdef MEDIA733_I34M
                                        case '*':       /* 2A */
                                                switch (toupper(argv[L2656_i_ArgumentIndex][2])) {
                                                        case 'E':
                                                                G2000_Language = C0_ENGLISH;
                                                                break;
                                                        case 'F':
                                                                G2000_Language = C1_FRENCH;
                                                                break;
                                                        case 'G':
                                                                G2000_Language = C2_GERMAN;
                                                }
#endif
                                }
                        }
                }
        }
#endif
#ifdef MEDIA720_I34E_I34M_A36M_A31E_A31M_A33M_A35E_A35M_F31E_F31J_X31J_P31J
        if (!setjmp(G2023_jmp_buf)) {
#endif
#ifdef MEDIA749_A36M_A31E_A31M_A33M_A35E_A35M_X31J
                F1046_OpenLibraries(P2788_, P2789_);
#endif
#ifdef MEDIA006_S10EA_S10EB_S11E_S12E_S12G_S13FA_S13FB /* CHANGE7_05_OPTIMIZATION */
                F0448_STARTUP1_InitializeMemoryManager_CPSADEF();
#endif
#ifdef MEDIA278_S20E_S21E_G14ED_G20E_G21E_A20ED_A20E_A20F_A20G_A21E_A22E_A22G_F20E_F20J_X30J_P20JA_P20JB_I34E_I34M_A36M_A31E_A31M_A33M_A35E_A35M_F31E_F31J_X31J_P31J /* CHANGE7_05_OPTIMIZATION */
                F0463_START_InitializeGame_CPSADEF();
#endif
                for (;;) { /*_Infinite loop_*/
                        F0002_MAIN_GameLoop_CPSDF();
                        F0444_STARTEND_Endgame(G0303_B_PartyDead);
                }
#ifdef MEDIA720_I34E_I34M_A36M_A31E_A31M_A33M_A35E_A35M_F31E_F31J_X31J_P31J
        }
#endif
#ifdef MEDIA749_A36M_A31E_A31M_A33M_A35E_A35M_X31J
        F1047_CloseLibraries();
        return 0;
#endif
}
#endif
