#ifndef COMPILE_H
#include "COMPILE.H"
#endif
#ifdef MEDIA634_A31E_A31M_X31J
extern FTL_LIBRARY* F9008_OpenPRIM();
extern FTL_LIBRARY* F9006_OpenMEM1();
extern FTL_LIBRARY* F9000_OpenGRF1();
extern FTL_LIBRARY* F9018_OpenINT1();
extern FTL_LIBRARY* F9004_OpenVDEO();


extern USIO_FTL_LIBRARY* F1169_();
extern void F1172_QueueMouseAndKeyboardInput();
extern void F1173_AddUsioDataToInputQueue();
extern unsigned int16_t F1692_Crawcin();


FTL_LIBRARY* G9017_MEM1_Library;
GRF1_FTL_LIBRARY* G3135_GRF1_Library;
VDEO_FTL_LIBRARY* G3136_VDEO_Library;
#ifdef MEDIA692_X31J
INT1_FTL_LIBRARY* G3137_INT1_Library;
#endif
int16_t G3273_i_InputQueueFirstIndex;
int16_t G3274_i_InputQueueLastIndex = 10;
USIODATA G3276_as_InputQueue[11];
#ifdef MEDIA692_X31J
BOOLEAN G3450_B_24KHzVideoMode; /* In 24KHz video mode the game looks the same as other versions. In 31KHz versions the entrance screen is larger and borders are visible while playing */
#endif
BOOLEAN G3275_B_InputQueueLocked;
BOOLEAN G3452_B_PendingUsioDataPresent;
USIODATA G3453_s_PendingUsioData;
#ifdef MEDIA619_A31E_A31M
DRIA_Video* G3191_ps_MsgPort_FTL_DRIA_Video;
ULONG G3269_l_IDCMPFlagsBackup;
unsigned char G3271_auc_InfoData[sizeof(struct InfoData) + 4]; /* Space to store a long aligned structure */
struct FileLock* G3270_ps_FileLock;
#endif


int16_t F1164_USIO_15_GetFirstQueuedUsioDataType(
)
{
        register int16_t L4704_;


        ASM_STUB_PREFIX
#ifdef MEDIA659_A31M_X31J
        F1172_QueueMouseAndKeyboardInput();
#endif
        if ((L4704_ = F1175_GetFirstQueuedUsioDataIndex()) == -1) { /* If queue is empty */
                L4704_ = 0;
        } else {
                L4704_ = G3276_as_InputQueue[L4704_].UsioType;
        }
        ASM_STUB_SUFFIX
        return L4704_;
}

int16_t F1165_USIO_17_WaitUntilKeyboardOrMouseInput(P4232_)
USIODATA* P4232_;
{
        register int16_t L4705_;


        ASM_STUB_PREFIX
        do {
                F1172_QueueMouseAndKeyboardInput();
                L4705_ = F1176_ExtractFirstUsioDataFromQueue(P4232_);
        } while (L4705_ == 0);
        ASM_STUB_SUFFIX
        return L4705_;
}

int16_t F1166_USIO_16_ExtractFirstUsioDataFromQueue(P4233_)
USIODATA* P4233_;
{
        register int16_t L4706_;


        ASM_STUB_PREFIX
        F1172_QueueMouseAndKeyboardInput();
        L4706_ = F1176_ExtractFirstUsioDataFromQueue(P4233_);
        ASM_STUB_SUFFIX
        return L4706_;
}

#ifdef MEDIA655_A31M
void F1167_USIO_14_GetMouseStatus(P4234_)
register USIODATA2* P4234_;
{
        register long L4707_;
        register int16_t L4708_i_MouseButtons;


        ASM_STUB_PREFIX
        L4708_i_MouseButtons = 0;
        L4707_ = 0;
        asm {
                btst    #6,(0xBFE001).l         /* ciaa.ciapra & CIAF_GAMEPORT0 */
                seq     d7                      /* L4707_ */
        }
        if (L4707_) {
                L4708_i_MouseButtons |= MASK0x0002_MOUSE_LEFT_BUTTON | MASK0x0001_MOUSE_RIGHT_BUTTON;
        }
        P4234_->Unused1 = 0;
        P4234_->Unused2 = 0;
        P4234_->Unused3 = 0;
        P4234_->MouseButtons = L4708_i_MouseButtons;
        P4234_->MouseX = G3191_ps_MsgPort_FTL_DRIA_Video->_0x10C_Window->MouseX;
        P4234_->MouseY = G3191_ps_MsgPort_FTL_DRIA_Video->_0x10C_Window->MouseY;
        ASM_STUB_SUFFIX
}
#endif

void F1168_USIO_18_Empty(
)
{
        ASM_STUB_PREFIX
        ASM_STUB_SUFFIX
}

#ifdef MEDIA692_X31J
void F1167_USIO_14_GetMouseStatus(
USIODATA2* P4234_)
{
        ASM_STUB_PREFIX
        P4234_->MouseButtons = F1684_GetMouseStatus(&P4234_->MouseX, &P4234_->MouseY);
        ASM_STUB_SUFFIX
}
#endif

USIO_FTL_LIBRARY* F1169_(P4223_, P4224_)
long P4223_;
register USIO_FTL_LIBRARY* P4224_;
{
        if (F9008_OpenPRIM(P4223_, 4) == NULL) {
                return NULL;
        }
        if ((G9017_MEM1_Library = F9006_OpenMEM1(1)) == NULL) {
                return NULL;
        }
        if ((G3135_GRF1_Library = F9000_OpenGRF1(2)) == NULL) {
                return NULL;
        }
#ifdef MEDIA692_X31J
        if ((G3137_INT1_Library = F9018_OpenINT1(2)) == NULL) {
                return NULL;
        }
#endif
        if ((G3136_VDEO_Library = F9004_OpenVDEO(2)) == NULL) {
                return NULL;
        }
#ifdef MEDIA619_A31E_A31M
        F1088_OpenAmigaStuff();
#endif
        G9001_USIObase = P4224_;
#ifdef MEDIA619_A31E_A31M
        VDEO_19_Operation(&G3191_ps_MsgPort_FTL_DRIA_Video);
        G3269_l_IDCMPFlagsBackup = G3191_ps_MsgPort_FTL_DRIA_Video->_0x10C_Window->IDCMPFlags;
        ModifyIDCMP(G3191_ps_MsgPort_FTL_DRIA_Video->_0x10C_Window, VANILLAKEY | INACTIVEWINDOW | ACTIVEWINDOW | DISKREMOVED | DISKINSERTED | CLOSEWINDOW | MENUPICK | GADGETUP | GADGETDOWN | MOUSEBUTTONS);
#endif
        P4224_->_w_0x36 = 0;
        P4224_->_w_0x40 = 6;
        P4224_->_w_0x42 = 0;
        P4224_->_w_0x44 = 32;
        P4224_->_w_0x46 = 24;
#ifdef MEDIA692_X31J
        VDEO_19_Operation(3, &G3450_B_24KHzVideoMode);
        F1685_InstallMouseInterruptHandler();
        F1686_();
#endif
        return P4224_;
}

void F1170_USIO_03_Expunge(
)
{
        ASM_STUB_PREFIX
#ifdef MEDIA619_A31E_A31M
        if (G3270_ps_FileLock) {
                UnLock(G3270_ps_FileLock);
        }
        G3270_ps_FileLock = NULL;
        if (G3191_ps_MsgPort_FTL_DRIA_Video) {
                ModifyIDCMP(G3191_ps_MsgPort_FTL_DRIA_Video->_0x10C_Window, G3269_l_IDCMPFlagsBackup);
        }
        G3191_ps_MsgPort_FTL_DRIA_Video = NULL;
        F1089_CloseAmigaStuff();
#endif
        F9005_CloseVDEO(G3136_VDEO_Library);
#ifdef MEDIA692_X31J
        F9019_CloseINT1(G3137_INT1_Library);
#endif
        F9001_CloseGRF1(G3135_GRF1_Library);
        F9007_CloseMEM1(G9017_MEM1_Library);
        F9009_ClosePRIM();
#ifdef MEDIA692_X31J
        F1687_UninstallMouseInterruptHandler();
#endif
        ASM_STUB_SUFFIX
}

#ifdef MEDIA619_A31E_A31M
BOOLEAN F1171_USIO_19_LockDF0(BOOLEAN P4225_B_RenewLock) {
        register struct InfoData* L4694_ps_InfoData;
        register BOOLEAN L4695_B_Result;
        register int16_t L4696_;


        ASM_STUB_PREFIX
        L4695_B_Result = C0_FALSE;
        L4694_ps_InfoData = (struct InfoData*)(((long)G3271_auc_InfoData + 3) & 0xFFFFFFFC); /* structure must be long aligned */
        if (P4225_B_RenewLock || (G3270_ps_FileLock == NULL)) {
                if (G3270_ps_FileLock) {
                        UnLock(G3270_ps_FileLock);
                }
                if ((G3270_ps_FileLock = Lock("df0:", ACCESS_READ)) != NULL) {
                        L4695_B_Result = C1_TRUE;
                }
        } else {
                if (G3270_ps_FileLock) {
                        L4696_ = 0;
                        while (((L4695_B_Result = Info(G3270_ps_FileLock, L4694_ps_InfoData)) == 0) && (L4696_++ < 9)) {
                                Delay(18L);
                        }
                }
        }
        ASM_STUB_SUFFIX
        return L4695_B_Result;
}
#endif

#ifdef MEDIA692_X31J
void F1173_AddUsioDataToInputQueue(
USIODATA* P5026_)
{
        register int16_t L4697_;


        asm {
                        tas     G3275_B_InputQueueLocked(a5)    /* BUGX_XX as in game, wrong bit checked */
                        beq.s   @Tloc_852
        }
        G3452_B_PendingUsioDataPresent = C1_TRUE;
        G3453_s_PendingUsioData = *P5026_;
        return;
        asm {
                @Tloc_852:
        }
        if ((L4697_ = G3274_i_InputQueueLastIndex + 2) > 10) {
                L4697_ -= 11;
        }
        if (G3273_i_InputQueueFirstIndex != L4697_) { /* If queue is not full */
                if (L4697_-- == 0) {
                        L4697_ = 10;
                }
                G3274_i_InputQueueLastIndex = L4697_;
                G3276_as_InputQueue[L4697_] = *P5026_;
                G3275_B_InputQueueLocked = C0_FALSE;
        }
}

void F1174_AddPendingUsioDataToInputQueue(
)
{
        if (G3452_B_PendingUsioDataPresent) {
                G3452_B_PendingUsioDataPresent = C0_FALSE;
                F1173_AddUsioDataToInputQueue(&G3453_s_PendingUsioData);
        }
}
#endif

void F1172_QueueMouseAndKeyboardInput(
)
{
#ifdef MEDIA692_X31J
        long L5160_RawKeyCode;
        USIODATA L4701_;


        while (F1691_Cconis()) {
                L4701_.UsioType = 1;
                L4701_.UsioValue = 0;
                L5160_RawKeyCode = F1692_Crawcin();
                L4701_.Data.UsioKeyboard.RawKeyCode = L5160_RawKeyCode;
                L4701_.Data.UsioKeyboard.AsciiCode = F1690_GetASCIICode(L5160_RawKeyCode);
                F1173_AddUsioDataToInputQueue(&L4701_);
                F1174_AddPendingUsioDataToInputQueue();
        }
#endif
#ifdef MEDIA619_A31E_A31M
        register struct IntuiMessage* L4698_;
        register int16_t L4699_;
        register int16_t L4700_i_MouseButtons;
        USIODATA L4701_;


        while ((L4698_ = GetMsg(G3191_ps_MsgPort_FTL_DRIA_Video->_0x10C_Window->UserPort)) != NULL) {
                switch (L4698_->Class) {
                        case VANILLAKEY:
                                L4701_.UsioType = 1;
                                L4701_.UsioValue = 0;
                                L4701_.Data.UsioKeyboard.RawKeyCode = 0;
                                L4701_.Data.UsioKeyboard.AsciiCode = L4698_->Code;
                                F1173_AddUsioDataToInputQueue(&L4701_);
                                break;
                        case MOUSEBUTTONS:
                                if (L4698_->Code == IECODE_LBUTTON) {
                                        L4699_ = 17;
                                        L4700_i_MouseButtons = 2;
                                }
                                if (L4698_->Code == (IECODE_LBUTTON | IECODE_UP_PREFIX)) {
                                        L4699_ = 18;
                                        L4700_i_MouseButtons = 8;
                                }
                                if (L4698_->Code == IECODE_RBUTTON) {
                                        L4699_ = 17;
                                        L4700_i_MouseButtons = 1;
                                }
                                if (L4698_->Code == (IECODE_RBUTTON | IECODE_UP_PREFIX)) {
                                        L4699_ = 18;
                                        L4700_i_MouseButtons = 4;
                                }
                                L4701_.UsioType = L4699_;
                                L4701_.UsioValue = 0;
                                L4701_.Data.UsioMouse.Buttons = L4700_i_MouseButtons;
                                L4701_.Data.UsioMouse.X = L4698_->MouseX;
                                L4701_.Data.UsioMouse.Y = L4698_->MouseY;
                                F1173_AddUsioDataToInputQueue(&L4701_);
                                break;
                        case DISKINSERTED:
                                L4701_.UsioType = 33;
                                L4701_.UsioValue = 0;
                                F1173_AddUsioDataToInputQueue(&L4701_);
                                break;
                }
                ReplyMsg(L4698_);
        }
#endif
}

#ifdef MEDIA619_A31E_A31M
void F1173_AddUsioDataToInputQueue(
USIODATA* P4226_)
{
        register int16_t L4697_;


        if ((L4697_ = G3274_i_InputQueueLastIndex + 2) > 10) {
                L4697_ -= 11;
        }
        if (G3273_i_InputQueueFirstIndex != L4697_) { /* If queue is not full */
                if (L4697_-- == 0) {
                        L4697_ = 10;
                }
                G3274_i_InputQueueLastIndex = L4697_;
                G3276_as_InputQueue[L4697_] = *P4226_;
        }
}

void F1174_AddPendingUsioDataToInputQueue(
)
{
}
#endif

int16_t F1175_GetFirstQueuedUsioDataIndex(
)
{
        register int16_t L4702_;


        if ((L4702_ = G3274_i_InputQueueLastIndex + 1) > 10) {
                L4702_ = 0;
        }
        if (L4702_ == G3273_i_InputQueueFirstIndex) { /* If queue is empty */
                return -1;
        } else {
                return G3273_i_InputQueueFirstIndex;
        }
}

int16_t F1176_ExtractFirstUsioDataFromQueue(P4231_)
register USIODATA* P4231_;
{
        register int16_t L4703_;


        L4703_ = F1175_GetFirstQueuedUsioDataIndex();
        if (L4703_ == -1) {
                P4231_->UsioType = 0;
        } else {
                G3275_B_InputQueueLocked = C1_TRUE;
                *P4231_ = G3276_as_InputQueue[L4703_];
                G3273_i_InputQueueFirstIndex++;
                if (G3273_i_InputQueueFirstIndex > 10) {
                        G3273_i_InputQueueFirstIndex = 0;
                }
                G3275_B_InputQueueLocked = C0_FALSE;
                F1174_AddPendingUsioDataToInputQueue();
        }
        return P4231_->UsioType;
}

#ifdef MEDIA692_X31J
int16_t F1690_GetASCIICode(long P5027_l_RawKeyCode) {
        return (int16_t)P5027_l_RawKeyCode & 0xFF;
}

int16_t F1691_Cconis(
)
{
        asm {
                moveq   #1,d0           /* B_KEYINP */
                trap    #0xF            /* TRAP 15 (IOCS CALL) */
                swap    d0
        }
}

unsigned int16_t F1692_Crawcin(
)
{
        asm {
                moveq   #0,d0           /* B_KEYSNS */
                trap    #0xF            /* TRAP 15 (IOCS CALL) */
        } /* Return 0x10000 + (256 * scan code) + (ASCII code) */
}
#endif
#endif
