#define R0056_TOS_CallXBIOS                                                       R056_aaal_
#define R0057_TOS_CallGEMDOS                                                      R057_rzzz_
#ifndef COMPILE_H
#include "COMPILE.H"
#endif
#ifdef MEDIA617_X30J_SU1E
static char G0716_ac_ErrorMessage[100];


char* F0917_PRIM_15_Memory_Allocate(P1010_l_Size)
long P1010_l_Size;
{
        char* L1790_pc_Buffer;


#ifdef MEDIA772_SU1E
        if ((L1790_pc_Buffer = Malloc((long)P1010_l_Size)) == NULL) {
#endif
#ifdef MEDIA577_X30J
        if ((L1790_pc_Buffer = MALLOC(P1010_l_Size)) & 0xF0000000) {
#endif
                F0928_PrintOSError(1);
        }
        return L1790_pc_Buffer;
}

void F0918_PRIM_16_Memory_Free(P1011_pc_Buffer)
char* P1011_pc_Buffer;
{
        if (P1011_pc_Buffer != NULL) {
#ifdef MEDIA772_SU1E
                Mfree(P1011_pc_Buffer);
#endif
#ifdef MEDIA577_X30J
                MFREE(P1011_pc_Buffer);
#endif
        }
}

void F0919_PRIM_19_File_Seek(P1012_l_Handle, P1013_l_Offset)
long P1012_l_Handle;
long P1013_l_Offset;
{
#ifdef MEDIA772_SU1E
        if (Fseek((long)P1013_l_Offset, (int)P1012_l_Handle, 0) != (long)P1013_l_Offset) {
#endif
#ifdef MEDIA577_X30J
        if (SEEK(P1012_l_Handle, P1013_l_Offset, 0) != P1013_l_Offset) {
#endif
                F0928_PrintOSError(3);
        }
}

void F0920_PRIM_20_File_Read(P1014_l_Handle, P1015_l_Length, P1016_pc_Buffer)
long P1014_l_Handle;
long P1015_l_Length;
char* P1016_pc_Buffer;
{
#ifdef MEDIA772_SU1E
        if (Fread((int)P1014_l_Handle, (long)P1015_l_Length, P1016_pc_Buffer) != (long)P1015_l_Length) {
#endif
#ifdef MEDIA577_X30J
        if (READ(P1014_l_Handle, P1016_pc_Buffer, P1015_l_Length) != P1015_l_Length) {
#endif
                F0928_PrintOSError(4);
        }
}

#ifdef MEDIA772_SU1E
asm {
        V0921000_BlackPalette:
                dc.w 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
        V0921001_ColorsPalette:
                dc.w 0x0000, 0x0002, 0x0003, 0x0004, 0x0006, 0x0035, 0x0333, 0x0045, 0x0344, 0x0321, 0x0770, 0x0222, 0x0444, 0x0555, 0x0532, 0x0700
        V0921002_Image:
                dc.w 0x0140, 0x00C8, 0xC054, 0x3954, 0x8237, 0x5480, 0xFA64, 0x0284, 0x3502, 0x64FD, 0x0103, 0x8D2A, 0x0F4D, 0xFD01, 0x0C5D, 0x4F9D
                dc.w 0x08FD, 0xFFDB, 0xFF4D, 0x0F5D, 0x1F2D, 0x3F1D, 0x1F5D, 0xFF01, 0x111F, 0x1D2F, 0xBF09, 0x1F2D, 0x5F0D, 0x7F6D, 0xB002, 0x20FF
                dc.w 0x0109, 0x0F4D, 0x0F1D, 0xBF0D, 0x0F2D, 0x0B2F, 0x3B1F, 0x7DFD, 0x0117, 0xBF09, 0xBD05, 0xBF06, 0x2D0B, 0xFF01, 0x18BD, 0x0CBD
                dc.w 0x04BB, 0x0B1F, 0x8D0B, 0xB402, 0x44FF, 0x010F, 0x8F0C, 0xBD09, 0x0B1F, 0xFB01, 0x232F, 0x1B1F, 0x0D1F, 0x0B0D, 0x1FBD, 0x090B
                dc.w 0x2FFD, 0x0125, 0xBB04, 0x1D4F, 0x2B2F, 0x1D1A, 0x2FFF, 0x011A, 0x3D1F, 0x0BBF, 0x05BB, 0x064F, 0x4A0D, 0x0BFD, 0x0119, 0xBF04
                dc.w 0x1F0B, 0x0DBB, 0x062D, 0x0B2F, 0x0B1F, 0x5A2B, 0xFD01, 0x1A5F, 0x0B1D, 0xBD0A, 0x0B2F, 0x0A1B, 0x2A6F, 0x0A0B, 0xFD01, 0x173F
                dc.w 0x0B2D, 0x0F1D, 0xBB02, 0x5D0B, 0x6A1B, 0x4F1A, 0xFD01, 0x198D, 0x091F, 0x0B5D, 0x3A0B, 0x2A1B, 0x7AFF, 0x0123, 0x0F0B, 0x5D2A
                dc.w 0x1B2A, 0x1B8A, 0x08FF, 0x0122, 0x0F0B, 0x4D4A, 0x0B0D, 0x0B4A, 0x2BFD, 0x0127, 0x4D3A, 0x1BBA, 0x01BB, 0x040D, 0x6AFA, 0x0127
                dc.w 0x1BBA, 0x02BA, 0x020B, 0x0A2B, 0x4A2B, 0x6DFA, 0x011E, 0x1A2B, 0xBA03, 0x0BBA, 0x033A, 0x1B8D, 0x09FA, 0x011D, 0xBA04, 0x6ABB
                dc.w 0x050B, 0x8D0B, 0xFA01, 0x1B1A, 0x1B4A, 0x3B5A, 0x1B8D, 0x0DFA, 0x011A, 0x0A0B, 0x1ABB, 0x030B, 0x0C2D, 0x3A1B, 0x8D0F, 0xFA01
                dc.w 0x190A, 0x1B3A, 0x1B5D, 0x2A0B, 0x8D11, 0xFA01, 0x182A, 0xBB02, 0x0B7D, 0x0A1B, 0x8D12, 0xFA01, 0x174A, 0x1B8D, 0x090B, 0x8D14
                dc.w 0xFA01, 0x163A, 0x1B8D, 0x21FA, 0x0115, 0x2A1B, 0x8D23, 0xFA01, 0x141A, 0x1B8D, 0x25FA, 0x0113, 0x1A0B, 0x8D27, 0xFA01, 0x120A
                dc.w 0x1B8D, 0x28FA, 0x0111, 0x0A0B, 0x8D2A, 0xFA01, 0x101B, 0x8D2B, 0xF401, 0x0B2D, 0x0A0B, 0x8D2C, 0x14F4, 0x010B, 0x8432, 0xF401
                dc.w 0x0882, 0x3574, 0xF401, 0x0184, 0x3CFD, 0x074F, 0x8D21, 0x52FC, 0x0116, 0x8C21, 0x5402, 0xFD01, 0x1A83, 0x08B4, 0x1902, 0xF401
                dc.w 0x1B64, 0xF30A, 0x1DF3, 0x027D, 0x13F4, 0x027C, 0x0314, 0xF401, 0x3CFC, 0x0116, 0x8C1C, 0xF002, 0x4684, 0x1210, 0xB027, 0x00B0
                dc.w 0x04C0, 0x05D2, 0x3F10, 0x1F20, 0x1F20, 0x3F20, 0x5F10, 0x4F20, 0x5F80, 0x091F, 0x101F, 0x105F, 0x203F, 0x201F, 0x603F, 0x205F
                dc.w 0x001F, 0x301F, 0x8008, 0x3F40, 0x3F30, 0x3F20, 0x1F10, 0x1F80, 0xAB1F, 0x202F, 0xBF05, 0x0F10, 0x1FB0, 0x0340, 0x1F10, 0x1F30
                dc.w 0x1F80, 0x0BB0, 0x0700, 0x1F50, 0x1F30, 0x1F70, 0x1F50, 0x1F20, 0xB012, 0x1F40, 0x1F30, 0x1F10, 0x1FBF, 0xBBBF, 0x0640, 0xB04E
                dc.w 0x1F10, 0x1F80, 0x091F, 0x101F, 0xBF0B, 0x40BF, 0x020F, 0x80AC, 0xB006, 0x3F20, 0x2F30, 0x3F30, 0x4F40, 0xB03D, 0x3F80, 0x0AB0
                dc.w 0x0F2F, 0x303F, 0x80AD, 0xB007, 0x2F40, 0x2FB0, 0x0340, 0x1F00, 0xB045, 0x1F80, 0x0BB0, 0x1000, 0x2FB0, 0x031F, 0xB0B5, 0xBF03
                dc.w 0x0F10, 0xB00E, 0x1FBF, 0x540F, 0x40BF, 0x050F, 0x10B0, 0x061F, 0x80AA, 0x3FB0, 0x0A3F, 0x205F, 0xB019, 0x4FBF, 0x0A2F, 0x205F
                dc.w 0x203F, 0xBF1C, 0x0F40, 0x3F30, 0x3F20, 0xB0B0, 0xC003, 0xDE4F, 0x204F, 0x205F, 0x203F, 0x303F, 0x800C, 0x1F80, 0x0B1F, 0x101F
                dc.w 0x105F, 0x001F, 0x301F, 0xB0EA, 0x001F, 0xB003, 0x001F, 0xB003, 0x401F, 0x101F, 0x101F, 0x101F, 0x800A, 0x3FB0, 0x1430, 0xFF01
                dc.w 0x0A40, 0x2F80, 0x0DBF, 0x110F, 0x201F, 0x501F, 0x101F, 0x80E9, 0x4F20, 0x4F20, 0x3F40, 0x2F40, 0x2F80, 0x0B1F, 0x101F, 0xBF0B
                dc.w 0x0F30, 0x3F40, 0x3F80, 0xEA1F, 0x501F, 0x00B0, 0x0670, 0x2F40, 0x2FBF, 0x0B2F, 0xB00B, 0x1FB0, 0x0460, 0x1F80, 0xEBB0, 0x0A1F
                dc.w 0xBF09, 0x0F10, 0xBF03, 0x0F10, 0xBF0A, 0x0F30, 0x1FB0, 0x0B1F, 0xFF01, 0x0B2F, 0x203F, 0x303F, 0x8009, 0xBF1A, 0x2FB0, 0xF1C0
                dc.w 0x3CCC
} /* Image is 834 bytes. It is a message "Insert Utility Disk" with a picture of the CSB floppy disk */

char* F0922_Custom_strcpy(P1017_pc_, P1018_pc_) /* Try code from F0088_strcpy in STRING.C */
register char* P1017_pc_;
register char* P1018_pc_;
{
        char* L1791_pc_Address;


        L1791_pc_Address = P1017_pc_;
        while (*L1791_pc_Address = *P1018_pc_)
                L1791_pc_Address++, P1018_pc_++;
        return P1017_pc_;
}

void main(
)
{
        int L1792_i_ReturnValue;
        int L1793_i_FileHandle;
        char* L1794_pc_StackAddress;
        char L1795_ac_FileName[100];
        DESCRIPTOR L1796_s_Descriptor;
        int L1797_ai_Unreferenced[4];
        int L1798_i_;
        int L1799_i_LoopCount;


        L1799_i_LoopCount = 0;
        F0922_Custom_strcpy(L1795_ac_FileName, "A:\\FTLCODE");
        while (Cconis())
                Crawcin();
        L1798_i_ = 0x5223;
        L1799_i_LoopCount = 0;
        do {
                F0924_SetCriticalErrorHandler();
                if (L1798_i_ != 0x5223)
                        break;
                L1798_i_ = 0;
                L1796_s_Descriptor.MemoryAddress = 0;
                while (F0925_CheckUtilityDiskInDrive(0, (L1799_i_LoopCount == 0) ? C1_TRUE : C0_FALSE) != C1_TRUE) { /* Loop until the Utility Disk is in the floppy disk drive */
                        F0436_STARTEND_FadeToPalette(V0921000_BlackPalette, 1);         /* Fade to black */
                        F0466_EXPAND_GraphicToBitmap(V0921002_Image, 0L, 0, 0);         /* Draw picture on screen */
                        F0436_STARTEND_FadeToPalette(V0921001_ColorsPalette, 1);        /* Fade to normal colors */
                        while (Cconis())
                                Crawcin();
                        Crawcin();                                                      /* Wait until the user presses a key */
                        F0436_STARTEND_FadeToPalette(V0921000_BlackPalette, 1);         /* Fade to black */
                }
                if (((L1793_i_FileHandle = Fopen(L1795_ac_FileName, 0)) < 0) && ((L1792_i_ReturnValue = F0927_PrintLoaderError(1280)) != 0))
                        goto T0008018;
                L1796_s_Descriptor.FileHandle = (unsigned long)L1793_i_FileHandle;
                L1796_s_Descriptor.CallMalloc = F0917_PRIM_15_Memory_Allocate;
                L1796_s_Descriptor.CallMfree = F0918_PRIM_16_Memory_Free;
                L1796_s_Descriptor.CallFseek = F0919_PRIM_19_File_Seek;
                L1796_s_Descriptor.CallFread = F0920_PRIM_20_File_Read;
                L1792_i_ReturnValue = F0929_PRIM_05_FTL_Load(&L1796_s_Descriptor);
                Fclose(L1793_i_FileHandle);
                if (L1792_i_ReturnValue != 0)
                        goto T0008018;
                if (((L1794_pc_StackAddress = Malloc(L1796_s_Descriptor.StackSize + 4)) == NULL) && ((L1792_i_ReturnValue = F0927_PrintLoaderError(1281)) != 0))
                        goto T0008018;
                L1796_s_Descriptor.StackAddress = (char*)(((long)L1794_pc_StackAddress + L1796_s_Descriptor.StackSize + 1) & 0xFFFFFFFE);
                /* Run FTL module (first entry point in jumptable) */
                asm {
                        movem.l D3-D7/A2-A6,-(A7)
                        movea.l L1796_s_Descriptor.A5World(A6),A5
                        move.l  A7,4(A5)        ; Backup stack address in 'Application Parameters' area
                        movea.l L1796_s_Descriptor.StackAddress(A6),A7
                        movea.l L1796_s_Descriptor.JumpTableAddress(A6),A0
                        pea     L1796_s_Descriptor(A6)
                        move.w  L1799_i_LoopCount(A6),-(A7)
                        jsr     (A0)
                        movea.l 4(A5),A7        ; Restore stack address from 'Application Parameters' area
                        movem.l (A7)+,D3-D7/A2-A6
                }
                /* Stack content when FTL module is run:
                Stack top (lower address)
                        long    return address pushed by jsr instruction
                        int     Value of L1799_i_LoopCount
                        long    Address of L1796_s_Descriptor
                Stack bottom (upper address)
                */
                if (*((int*)L1796_s_Descriptor.A5World) == 0x6160) { /* FTL file magic number */
                        if (*((int*)(L1796_s_Descriptor.A5World + 2)) == 0x5223) { /* When exiting the module, if the first two words in 'Application Parameters' area are 0x6160 and 0x5223 then proceed to another module */
                                L1798_i_ = 0x5223;
                                F0922_Custom_strcpy(L1795_ac_FileName, *((long*)(L1796_s_Descriptor.A5World + 28)));
                        } else { /* T0008014 */
                                L1798_i_ = 0;
                        } /* T0008015 */
                } else { /* T0008016 */
                        L1798_i_ = 0;
                } /* T0008017 */
                Mfree(L1794_pc_StackAddress);
                T0008018:
                if (L1796_s_Descriptor.MemoryAddress != 0) {
                        Mfree(L1796_s_Descriptor.MemoryAddress);
                }
                L1799_i_LoopCount++;
        } while ();
        for (;;); /*_Infinite loop_*/
}
#endif
#ifdef MEDIA577_X30J
long launch(P3094_pc_FileName)
char* P3094_pc_FileName;
{
        int16_t L1792_i_ReturnValue;
        int16_t L1793_i_FileHandle;
        char* L1794_pc_StackAddress;
        DESCRIPTOR L1796_s_Descriptor;
        int16_t L1797_ai_Unreferenced[4];
        int L3512_i_ReturnCode;


        while (KEYSNS()) {
                GETC();
        }
        if ((L1793_i_FileHandle = OPEN(P3094_pc_FileName, 0L)) < 0) {
                F0927_PrintLoaderError(1280);
        }
        L1796_s_Descriptor.FileHandle = (unsigned long)L1793_i_FileHandle;
        L1796_s_Descriptor.CallMalloc = F0917_PRIM_15_Memory_Allocate;
        L1796_s_Descriptor.CallMfree = F0918_PRIM_16_Memory_Free;
        L1796_s_Descriptor.CallFseek = F0919_PRIM_19_File_Seek;
        L1796_s_Descriptor.CallFread = F0920_PRIM_20_File_Read;
        L1792_i_ReturnValue = F0929_PRIM_05_FTL_Load(&L1796_s_Descriptor);
        CLOSE(L1793_i_FileHandle);
        if (L1792_i_ReturnValue == 0) {
                if ((L1794_pc_StackAddress = MALLOC(L1796_s_Descriptor.StackSize + 3)) == NULL) {
                        F0927_PrintLoaderError(1281);
                }
                L1796_s_Descriptor.StackAddress = (char*)(((long)L1794_pc_StackAddress + L1796_s_Descriptor.StackSize + 1) & 0xFFFFFFFE);
                L3512_i_ReturnCode = execute(L1796_s_Descriptor.JumpTableAddress, &L1796_s_Descriptor, L1796_s_Descriptor.A5World, L1796_s_Descriptor.StackAddress);
                MFREE(L1794_pc_StackAddress);
        }
        return L3512_i_ReturnCode;
}

void main(
)
{
        launch("SWOOSH");
        launch("FTLCODE");
}
#endif

#ifdef MEDIA772_SU1E
#include "TOS.C"

void F0924_SetCriticalErrorHandler(
)
{
        long L5002_l_SupervisorStack;


        L5002_l_SupervisorStack = Super(0L);
        asm {
                        lea     T0013001(PC),A0
                        move.l  A0,0x404        ; etv_critic
                        bra.s   T0013002
                T0013001:       
                        moveq   #-1,D0
                        rts
                T0013002:
        }
        Super(L5002_l_SupervisorStack);
}

BOOLEAN F0925_CheckUtilityDiskInDrive(P1019_i_DeviceNumber, P1020_i_FirstLoopIteration)
int P1019_i_DeviceNumber;
int P1020_i_FirstLoopIteration;
{
        char L1801_ac_Buffer[600];
        BOOLEAN L1802_B_ReturnValue;
        static char G0718_ac_[104]; /* Buffer to store string "copyright (c) 1987, Software Heaven, Inc." read from sector 7 */
        static char G0719_ac_[50]; /* Buffer to store string "Chaos Strikes Back" read from sector 7 */


        F0926_FLOPPY_ForceMediaChangeDetection(P1019_i_DeviceNumber);
        if (Floprd(L1801_ac_Buffer, 0L, P1019_i_DeviceNumber, 7, 0, 0, 1))   /* Read sector 7 on track 0, side 0    WORD Floprd(VOIDP buf, LONG rsrvd, WORD dev, WORD sector, WORD track, WORD side, WORD count) */
                return -1;
        if ((strcmp(L1801_ac_Buffer, G0718_ac_) == 0) && (strcmp(&L1801_ac_Buffer[128], G0719_ac_) == 0)) { /* Check strings in sector "copyright (c) 1987, Software Heaven, Inc." and "Chaos Strikes Back" */
                L1802_B_ReturnValue = C1_TRUE;
        } else { /* T0014002 */
                L1802_B_ReturnValue = P1020_i_FirstLoopIteration;
        } /* T0014003 */
        if (P1020_i_FirstLoopIteration != C0_FALSE) {
                F0922_Custom_strcpy(G0718_ac_, L1801_ac_Buffer);
                F0922_Custom_strcpy(G0719_ac_, &L1801_ac_Buffer[128]);
        }
        return L1802_B_ReturnValue;
}

void F0926_FLOPPY_ForceMediaChangeDetection(P1021_i_)
int P1021_i_;
{
        long L1803_l_Address;
        char L1804_ac_Unreferenced[16];
        static char G0720_ac_[] = "A:\\F";


        G0720_ac_[0] = 'A' + P1021_i_;
        L1803_l_Address = Super(0L);
        asm {
                jsr T0926001;
        }
        Super(L1803_l_Address);
        Fopen(G0720_ac_, 0);
        L1803_l_Address = Super(0L);
        asm {
                jsr T0926002;
        }
        Super(L1803_l_Address);
        goto T0926013;

        asm {
                T0926001:
                        lea     T0926004(PC),A0
                        move.l  A4,(A0)
                        lea     T0926005(PC),A0
                        move.l  A5,(A0)
                        lea     T0926006(PC),A0
                        move.l  A6,(A0)
                        move.l  0x472,-0x0008(A6)
                        move.l  0x47E,-0x000C(A6)
                        move.l  0x476,-0x0010(A6)
                        lea     T0926007(PC),A0
                        move.l  A0,0x472
                        move.l  A0,-0x0014(A6)
                        lea     T0926009(PC),A0
                        move.l  A0,0x47E
                        lea     T0926011(PC),A0
                        move.l  A0,0x476
                        rts     
                T0926002:       
                        move.l  0x472,D0
                        move.l  -0x0014(A6),D1
                        cmp.l   D0,D1
                        bne.s   T0926003
                        move.l  -0x0008(A6),0x472
                        move.l  -0x000C(A6),0x47E
                        move.l  -0x0010(A6),0x476
                T0926003:       
                        rts     
                T0926004:       
                        dc.l    0x00000000
                T0926005:       
                        dc.l    0x00000000
                T0926006:       
                        dc.l    0x00000000
                T0926007:       
                        move.l  A6,-(A7)
                        movea.l T0926006(PC),A6
                        move.w  0x0008(A6),D0
                        cmp.w   0x0008(A7),D0
                        bne.s   T0926008
                        move.l  -0x0008(A6),0x472
                        move.l  -0x000C(A6),0x47E
                        move.l  -0x0010(A6),0x476
                T0926008:       
                        movea.l -0x0008(A6),A0
                        movea.l (A7)+,A6
                        jmp     (A0)
                T0926009:       
                        move.l  A6,-(A7)
                        movea.l T0926006(PC),A6
                        move.w  0x0008(A6),D0
                        cmp.w   0x0008(A7),D0
                        bne.s   T0926010
                        moveq   #0x02,D0
                        movea.l (A7)+,A6
                        rts     
                T0926010:       
                        movea.l -0x000C(A6),A0
                        movea.l (A7)+,A6
                        jmp     (A0)
                T0926011:       
                        move.l  A6,-(A7)
                        movea.l T0926006(PC),A6
                        move.w  0x0008(A6),D0
                        cmp.w   0x0012(A7),D0
                        bne.s   T0926012
                        moveq   #-0x0E,D0
                        movea.l (A7)+,A6
                        rts     
                T0926012:       
                        movea.l -0x0010(A6),A0
                        movea.l (A7)+,A6
                        jmp     (A0)
        }
        T0926013: ;
}
#endif

int16_t F0927_PrintLoaderError(P1022_i_)
register int16_t P1022_i_;
{
#ifdef MEDIA772_SU1E
        Cconws("Loader error:\7 0x");
#endif
#ifdef MEDIA577_X30J
        PRINT("Loader error:\7 0x");
#endif
        F0933_GetHexStringFromValue((unsigned long)P1022_i_, G0716_ac_ErrorMessage);
#ifdef MEDIA772_SU1E
        Cconws(G0716_ac_ErrorMessage);
        Cconws("\n\r");
        while (!Cconis());
        Crawcin();
#endif
#ifdef MEDIA577_X30J
        PRINT(G0716_ac_ErrorMessage);
        PRINT("\n\r");
        while (!KEYSNS());
        GETC();
#endif
        return P1022_i_;
}

int16_t F0928_PrintOSError(P1023_i_)
register int16_t P1023_i_;
{
#ifdef MEDIA772_SU1E
        Cconws("Primative OS error:\7 0x");
#endif
#ifdef MEDIA577_X30J
        PRINT("Primative OS error:\7 0x");
#endif
        F0933_GetHexStringFromValue((unsigned long)P1023_i_, G0716_ac_ErrorMessage);
#ifdef MEDIA772_SU1E
        Cconws(G0716_ac_ErrorMessage);
        Cconws("\n\r");
        while (!Cconis());
        Crawcin();
#endif
#ifdef MEDIA577_X30J
        PRINT(G0716_ac_ErrorMessage);
        PRINT("\n\r");
        while (!KEYSNS());
        GETC();
#endif
        return P1023_i_;
}

unsigned int16_t F0929_PRIM_05_FTL_Load(P1024_ps_Descriptor)
DESCRIPTOR* P1024_ps_Descriptor;
{
        register unsigned int16_t L1805_ui_;
        unsigned int16_t L1806_ui_ComputedChecksum;
        unsigned long L1807_ul_CompressedDataByteCount;
        unsigned long L1808_ul_DataRelocationByteCount;
        unsigned long L1809_ul_Size;
        long L1810_l_JUMPSegmentIndex;
        long L1811_l_DATASegmentIndex;
        long L1812_l_CODESegmentIndex;
        char* L1813_pc_DATAAddress;
        char* L1814_pc_A5WorldAddress;
        char* L1815_pc_CODEAddress;
        char* L1816_pc_BaseAddress;
        char* L1817_pc_WorkingAddress;
        char* L1818_pc_AllocatedTempBuffer;
        char* L1819_pc_TempBuffer;
        HEADER L1820_s_Header;
        JUMPSEGMENTHEADER L1821_s_JUMPSegment;
        SEGMENTHEADER* L1822_s_SegmentHeaders;


        L1822_s_SegmentHeaders = NULL;
        P1024_ps_Descriptor->MemoryAddress = NULL;
        L1818_pc_AllocatedTempBuffer = NULL;
        (*P1024_ps_Descriptor->CallFread)(P1024_ps_Descriptor->FileHandle, (long)sizeof(HEADER), &L1820_s_Header); /* Read the FTL file header */
        if ((L1820_s_Header.Magic != 0x6160) || (L1820_s_Header.Unknown1 != 2) || (L1820_s_Header.c_6 != 1) || (L1820_s_Header.c_7 != 0)) {
                if ((L1805_ui_ = F0927_PrintLoaderError(1)) != 0)
                        goto T0018041;
        }
        if (L1820_s_Header.SegmentCount > 100) {
                if ((L1805_ui_ = F0927_PrintLoaderError(26)) != 0)
                        goto T0018041;
        }
        L1809_ul_Size = L1820_s_Header.SegmentCount * sizeof(SEGMENTHEADER);
        L1822_s_SegmentHeaders = (SEGMENTHEADER*)(*P1024_ps_Descriptor->CallMalloc)((long)L1809_ul_Size); /* Allocate memory for segment headers */
        (*P1024_ps_Descriptor->CallFread)(P1024_ps_Descriptor->FileHandle, L1809_ul_Size, L1822_s_SegmentHeaders); /* Read segment headers */
        if (F0930_GetHeaderChecksum(&L1820_s_Header, L1822_s_SegmentHeaders) != L1820_s_Header.Checksum) { /* Compute and compare checksum on header and segment headers */
                if ((L1805_ui_ = F0927_PrintLoaderError(14)) != 0)
                        goto T0018041;
        }
        L1810_l_JUMPSegmentIndex = -1;
        L1811_l_DATASegmentIndex = -1;
        L1812_l_CODESegmentIndex = -1;
        for (L1805_ui_ = 0; L1805_ui_ < L1820_s_Header.SegmentCount; L1805_ui_++) {
                switch (L1822_s_SegmentHeaders[L1805_ui_].Type) {
                        case 0x0010:
                                if (L1822_s_SegmentHeaders[L1805_ui_].Id != 1) {
                                        if ((L1805_ui_ = F0927_PrintLoaderError(20)) != 0)
                                                goto T0018041;
                                }
                                if (L1810_l_JUMPSegmentIndex == -1) {
                                        L1810_l_JUMPSegmentIndex = L1805_ui_;
                                } else {
                                        if ((L1805_ui_ = F0927_PrintLoaderError(23)) != 0)    /* Error if there is more than 1 segment of that type */
                                                goto T0018041;
                                }
                                break;
                        case 0x0011:
                                if (L1822_s_SegmentHeaders[L1805_ui_].Id != 1) {
                                        if ((L1805_ui_ = F0927_PrintLoaderError(21)) != 0)
                                                goto T0018041;
                                }
                                if (L1811_l_DATASegmentIndex == -1) {
                                        L1811_l_DATASegmentIndex = L1805_ui_;
                                } else {
                                        if ((L1805_ui_ = F0927_PrintLoaderError(24)) != 0)    /* Error if there is more than 1 segment of that type */
                                                goto T0018041;
                                }
                                break;
                        case 0x0012:
                                if (L1822_s_SegmentHeaders[L1805_ui_].Id != 1) {
                                        if ((L1805_ui_ = F0927_PrintLoaderError(22)) != 0)
                                                goto T0018041;
                                }
                                if (L1812_l_CODESegmentIndex == -1) {
                                        L1812_l_CODESegmentIndex = L1805_ui_;
                                } else {
                                        if ((L1805_ui_ = F0927_PrintLoaderError(25)) != 0)    /* Error if there is more than 1 segment of that type */
                                                goto T0018041;
                                }
                                break;
                        default:
                                break;
                }
        }
        if ((L1810_l_JUMPSegmentIndex == -1) || (L1811_l_DATASegmentIndex == -1) || (L1812_l_CODESegmentIndex == -1)) {    /* Error if there is no segment of one of the three types 0x0010 0x0011 0x0012 */
                if ((L1805_ui_ = F0927_PrintLoaderError(2)) != 0)
                        goto T0018041;
        }
        (*P1024_ps_Descriptor->CallFseek)(P1024_ps_Descriptor->FileHandle, (long)L1822_s_SegmentHeaders[L1810_l_JUMPSegmentIndex].Offset);
        (*P1024_ps_Descriptor->CallFread)(P1024_ps_Descriptor->FileHandle, (long)sizeof(JUMPSEGMENTHEADER), &L1821_s_JUMPSegment);
        L1809_ul_Size = 0L + L1821_s_JUMPSegment.BelowA5Size + L1821_s_JUMPSegment.AboveA5Size + L1821_s_JUMPSegment.CODESize + 12;
        P1024_ps_Descriptor->MemoryAddress = L1816_pc_BaseAddress = (char*)(*P1024_ps_Descriptor->CallMalloc)(L1809_ul_Size);
        L1813_pc_DATAAddress = (char*)(((long)L1816_pc_BaseAddress + 0 + 1) & 0xFFFFFFFE);
        L1814_pc_A5WorldAddress = (char*)(((long)L1813_pc_DATAAddress + L1821_s_JUMPSegment.BelowA5Size + 1) & 0xFFFFFFFE);
        L1815_pc_CODEAddress = (char*)(((long)L1814_pc_A5WorldAddress + L1821_s_JUMPSegment.AboveA5Size + 1) & 0xFFFFFFFE);

        L1809_ul_Size = L1822_s_SegmentHeaders[L1810_l_JUMPSegmentIndex].Size;                /* The temporary buffer should be large enough the store the JUMP segment */
        if (L1822_s_SegmentHeaders[L1811_l_DATASegmentIndex].Size > L1809_ul_Size) {
                L1809_ul_Size = L1822_s_SegmentHeaders[L1811_l_DATASegmentIndex].Size;       /* The temporary buffer should be large enough the store the DATA segment */
        }
        if (L1809_ul_Size > L1821_s_JUMPSegment.CODESize) {
                L1818_pc_AllocatedTempBuffer = (char*)(*P1024_ps_Descriptor->CallMalloc)(L1809_ul_Size);   /* Allocate a new buffer of memory if necessary (if the memory for CODE is too small) */
                L1819_pc_TempBuffer = (char*)(((long)L1818_pc_AllocatedTempBuffer + 1) & 0xFFFFFFFE);
        } else {
                L1819_pc_TempBuffer = L1815_pc_CODEAddress; /* Use the memory destined to store CODE as the temporary buffer */
        }

        /* Build the actual jump table in memory from the entry points list in the JUMP segment */
        L1816_pc_BaseAddress = L1819_pc_TempBuffer;
        L1817_pc_WorkingAddress = (L1814_pc_A5WorldAddress + L1821_s_JUMPSegment.JumpTableOffset); /* Address of the jump table in A5 world */
        L1809_ul_Size = L1822_s_SegmentHeaders[L1810_l_JUMPSegmentIndex].Size - sizeof(JUMPSEGMENTHEADER); /* Size of jumps in JUMP segment (size of segment - size of header) */
        (*P1024_ps_Descriptor->CallFread)(P1024_ps_Descriptor->FileHandle, L1809_ul_Size, L1816_pc_BaseAddress); /* Load the jumps in the temporary buffer */
        L1806_ui_ComputedChecksum = F0931_ChecksumWords(L1816_pc_BaseAddress, (long)L1809_ul_Size);
        L1806_ui_ComputedChecksum += F0931_ChecksumWords(&L1821_s_JUMPSegment, (long)sizeof(JUMPSEGMENTHEADER));
        if ((unsigned int16_t)(L1806_ui_ComputedChecksum - L1821_s_JUMPSegment.JUMPChecksum) != L1821_s_JUMPSegment.JUMPChecksum) { /* Error if invalid checksum on JUMP segment */
                if ((L1805_ui_ = F0927_PrintLoaderError(15)) != 0)
                        goto T0018041;
        }
        while ((long)L1816_pc_BaseAddress < (L1809_ul_Size + (long)L1815_pc_CODEAddress)) { /* Loop through all entry points and create a jmp instruction with actual entry point address */
                ((JUMPTABLEENTRY*)L1817_pc_WorkingAddress)->Instruction = 0x4EF9; /* jmp instruction */
                ((JUMPTABLEENTRY*)L1817_pc_WorkingAddress)->Operand = *((long*)L1816_pc_BaseAddress) + (long)L1815_pc_CODEAddress; /* Address from jumptable + base address of the CODE => actual address in memory */
                L1817_pc_WorkingAddress += 8; /* Each jmp instruction is 6 bytes large, but preceded by 2 unused bytes */
                L1816_pc_BaseAddress += 4;
        }

        /* Load compressed DATA in temporary buffer */
        L1816_pc_BaseAddress = L1819_pc_TempBuffer;
        L1817_pc_WorkingAddress = L1813_pc_DATAAddress;
        L1809_ul_Size = (unsigned long)L1822_s_SegmentHeaders[L1811_l_DATASegmentIndex].Size;
        (*P1024_ps_Descriptor->CallFseek)(P1024_ps_Descriptor->FileHandle, (long)L1822_s_SegmentHeaders[L1811_l_DATASegmentIndex].Offset);
        (*P1024_ps_Descriptor->CallFread)(P1024_ps_Descriptor->FileHandle, L1809_ul_Size, L1816_pc_BaseAddress); /* Load compressed DATA in the temporary buffer */
        L1806_ui_ComputedChecksum = F0932_ChecksumBytes(L1816_pc_BaseAddress, (long)L1809_ul_Size);
        if (L1806_ui_ComputedChecksum != L1821_s_JUMPSegment.DATAChecksum) { /* Error if invalid checksum on DATA */
                if ((L1805_ui_ = F0927_PrintLoaderError(16)) != 0)
                        goto T0018041;
        } /* T0018033 */
        /* Uncompress DATA into final location */
        L1807_ul_CompressedDataByteCount = ((DATASEGMENTHEADER*)L1816_pc_BaseAddress)->DATACompressedSize; /* Compressed DATA size */
        L1808_ul_DataRelocationByteCount = ((DATASEGMENTHEADER*)L1816_pc_BaseAddress)->RelocationDataSize; /* Size of data relocation information */
        L1816_pc_BaseAddress += sizeof(DATASEGMENTHEADER); /* Address of the first byte of actual DATA (after the header) */
        while (L1807_ul_CompressedDataByteCount > 0) {
                L1805_ui_ = *((int16_t*)L1816_pc_BaseAddress); /* Read one word from input compressed data */
                *((int16_t*)L1817_pc_WorkingAddress) = L1805_ui_; /* Output word to data segment */
                L1816_pc_BaseAddress += 2; /* Proceed to the next input word in compressed data */
                L1807_ul_CompressedDataByteCount -= 2;
                L1817_pc_WorkingAddress += 2;
                if (L1805_ui_ == 0) { /* If word is 0, read next word and duplicate 0x0000 word */
                        L1805_ui_ = *((int16_t*)L1816_pc_BaseAddress); /* Read next word from input compressed data: repeat count */
                        L1816_pc_BaseAddress += 2;
                        L1807_ul_CompressedDataByteCount -= 2;
                        for (; L1805_ui_ > 0; L1805_ui_--) { /* Loop to output 0x00 bytes to data segment */
                                *((char*)L1817_pc_WorkingAddress) = 0;
                                L1817_pc_WorkingAddress++;
                        }
                }
        }
        /* Apply relocation information to DATA. Relocation information consists of words (signed integers) that are offsets relative to the A5 world address. */
        while (L1808_ul_DataRelocationByteCount > 0) {
                *((long*)(L1814_pc_A5WorldAddress + *((int16_t*)L1816_pc_BaseAddress))) += (long)L1814_pc_A5WorldAddress; /* Add A5 world address address to the specified data word */
                L1816_pc_BaseAddress += 2; /* Proceed to next relocation word (a signed int offset in DATA) */
                L1808_ul_DataRelocationByteCount -= 2;
        }

        L1816_pc_BaseAddress = L1815_pc_CODEAddress;
        L1809_ul_Size = (unsigned long)L1822_s_SegmentHeaders[L1812_l_CODESegmentIndex].Size;
        (*P1024_ps_Descriptor->CallFseek)(P1024_ps_Descriptor->FileHandle, (long)L1822_s_SegmentHeaders[L1812_l_CODESegmentIndex].Offset);
        (*P1024_ps_Descriptor->CallFread)(P1024_ps_Descriptor->FileHandle, L1809_ul_Size, L1816_pc_BaseAddress); /* Load CODE into its final location */
        L1806_ui_ComputedChecksum = F0932_ChecksumBytes(L1816_pc_BaseAddress, (long)L1809_ul_Size);
        if (L1806_ui_ComputedChecksum != L1821_s_JUMPSegment.CODEChecksum) { /* Error if invalid checksum on CODE */
                if ((L1805_ui_ = F0927_PrintLoaderError(17)) != 0)
                        goto T0018041;
        }
        P1024_ps_Descriptor->A5World = L1814_pc_A5WorldAddress;
        P1024_ps_Descriptor->JumpTableAddress = L1814_pc_A5WorldAddress + L1821_s_JUMPSegment.JumpTableOffset + 2; /* Each jump contains 2 unused bytes at the start (8 bytes large and contains a 6 bytes jmp instruction) */
        P1024_ps_Descriptor->StackSize = L1821_s_JUMPSegment.StackSize;
        L1805_ui_ = 0; /* Success return code */
        T0018041:
        if (L1822_s_SegmentHeaders != NULL) {
                (*P1024_ps_Descriptor->CallMfree)((char*)L1822_s_SegmentHeaders);
        }
        if (L1818_pc_AllocatedTempBuffer != NULL) { /* If a memory block was allocated for the temporary buffer (instead of using the memory for CODE) */
                (*P1024_ps_Descriptor->CallMfree)((char*)L1818_pc_AllocatedTempBuffer);
        }
        if ((L1805_ui_ != 0) && (P1024_ps_Descriptor->MemoryAddress != NULL)) {
                (*P1024_ps_Descriptor->CallMfree)((char*)P1024_ps_Descriptor->MemoryAddress);
                P1024_ps_Descriptor->MemoryAddress = NULL;
        }
        return L1805_ui_;
/*
At the end of this function, the memory layout is the following:
        DATA (decompressed)
        'Application Parameters' area (32 bytes)
        Jumptable (8 bytes entries with 2 unused bytes at the beginning of each)
        CODE
        <12 bytes>
*/
}

unsigned int16_t F0930_GetHeaderChecksum(P1025_ps_, P1026_ps_)
HEADER* P1025_ps_;
SEGMENTHEADER* P1026_ps_;
{
        register unsigned int16_t L1823_ui_;
        register unsigned int16_t L1824_ui_;
        register unsigned int16_t L1825_ui_;
        register unsigned char* L1826_puc_;


        L1824_ui_ = 0;
        L1826_puc_ = (unsigned char*)P1025_ps_;
        for (L1823_ui_ = 4; L1823_ui_ < 20; L1823_ui_++) {
                L1824_ui_ += (L1826_puc_[L1823_ui_] * L1823_ui_);
        }
        L1826_puc_ = (unsigned char*)P1026_ps_;
        L1825_ui_ = P1025_ps_->SegmentCount * sizeof(SEGMENTHEADER);
        for (L1823_ui_ = 0; L1823_ui_ < L1825_ui_; L1823_ui_++) {
                L1824_ui_ += L1826_puc_[L1823_ui_] * ((L1823_ui_ & 0x00FF) + 1);
        }
        return L1824_ui_;
}

unsigned int16_t F0931_ChecksumWords(P1027_pi_, P1028_l_)
register int16_t* P1027_pi_;
register long P1028_l_;
{
        register unsigned int16_t L1827_ui_;


        L1827_ui_ = 0;
        while (P1028_l_ > 0) {
                L1827_ui_ += *P1027_pi_;
                P1027_pi_++;
                P1028_l_ -= 2;
        }
        return L1827_ui_;
}

unsigned int16_t F0932_ChecksumBytes(P1029_puc_, P1030_l_)
register unsigned char* P1029_puc_;
register long P1030_l_;
{
        register unsigned int16_t L1828_ui_;


        L1828_ui_ = 0;
        while (P1030_l_ > 0) {
                L1828_ui_ += *P1029_puc_;
                P1029_puc_++;
                P1030_l_--;
        }
        return L1828_ui_;
}

char G2295_IntegerToHexDigit[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };

int F0933_GetHexStringFromValue(P1031_ul_, P1032_pc_String)
unsigned long P1031_ul_;
char* P1032_pc_String;
{
        char* L1829_pc_;


        L1829_pc_ = F0934_ConvertValueToHexDigits(P1032_pc_String, P1031_ul_);
        *L1829_pc_ = 0; /* Add end of string not added by F0023_MAIN_GetAbsoluteValue */
        return 0;
}

char* F0934_ConvertValueToHexDigits(P1033_pc_String, P1034_ul_Value)
register char* P1033_pc_String;
register unsigned long P1034_ul_Value;
{
        register char* L1830_pc_;
        register int16_t L1831_i_DigitCount;
        register int16_t L1832_i_Unreferenced;
        char L1833_ac_LocalString[12];


        L1831_i_DigitCount = 0;
        L1830_pc_ = L1833_ac_LocalString;
        do {
                *L1830_pc_++ = G2295_IntegerToHexDigit[P1034_ul_Value % 16];
                P1034_ul_Value >>= 4;
                L1831_i_DigitCount++;
        } while (P1034_ul_Value > 0);
        while (L1831_i_DigitCount--) {
                *P1033_pc_String++ = *(--L1830_pc_);
        }
        return P1033_pc_String;
}

#ifdef MEDIA772_SU1E
#define M510_MASK_RED_COMPONENT         0x0700
#define M511_MASK_GREEN_COMPONENT       0x0070
#define M512_MASK_BLUE_COMPONENT        0x0007
#define M526_WaitVerticalBlank()        Vsync()
#define C160_BYTE_WIDTH_SCREEN          160

#include "PALETTE.C"
#include "EXPAND.C"
#endif
#ifdef MEDIA577_X30J
#asm
        .XDEF        _execute            ; F6007_CallFTLProgram
        _execute:
                link    a6,#0
                movem.l d0-a5,-(sp)
                movea.l 16(a6),a5       ; A5World
                move.l  sp,4(a5)        ; Backup stack address in 'Application Parameters' area
                movea.l 20(a6),sp       ; StackAddress
                movea.l 8(a6),a0        ; JumpTableAddress
                move.l  12(a6),-(sp)    ; &L1796_s_Descriptor
                jsr     (a0)            ; Jump to the first entry in the jumptable which is main()
                movea.l 4(a5),sp        ; Restore stack address from 'Application Parameters' area
                movem.l (sp)+,d0-a5
                unlk    a6
                rts
#endasm
#endif
#endif
