#ifdef MEDIA339_S20E_X30J_A36M_A31E_A31M_A33M_A35E_A35M_X31J_SU1E_AU1E_AU2E_AU2F_AU2G_AU3E

/* TODO
CSB Atari ST FTLCODE: JUMPSegment (40 bytes):
0000 0128   296     long AboveA5Size;         JUMP header and jump table size in memory
0000 0F6E  3950     long BelowA5Size;         Size of area 1 of hunk 0x011 (HUNK_DATA) in memory
0000 0108   264     long JumpTableSize;       jump table size in memory 264/8 = 33 entry points, following the JUMP Segment
0000 0020    32     long JumpTableOffset;
0000 7D00 32000     long StackSize;           unknown
0000 381E 14366     unsigned long CODESize;   hunk 0x0012 (HUNK_CODE) size in memory, after decompression if necessary
0000 01E6   486     long DATACompressedSize   HUNK_DATA size in file as this area can be compressed, the size here is the size before any decompression
0001                int Unknown2;
0000                int CODECompressed;
0000                int Unknown4;
398E                int JUMPChecksum;
9DE4                int DATAChecksum;
2A03                int CODEChecksum;

CODE
No relocation of code. This means the code contains no absolute addresses and only relative addresses.
(a5) is used to access DATA (negative offsets) or 'Application Parameters'/jumptable (positive offsets, 'Application Parameters' located before jumptable in memory)
jsr use (pc) relative offsets or (a5) relative offsets (jumptable)
CODE segments in all CSB Atari ST Utility Disk FTL files contain the same portion of code at the beginning (a Loader)

in CODE segment, the first 4 bytes are a long value, a positive offset to A5 (in the jumptable).
This value - size of 'Application Parameters' = 32 corresponds to the start of the jumptable (8 bytes per entry)

Entry point in code segment of file FTLCODE:
Offset 0x00000004 (first jumptable entry). This is an instruction to jump using the jumptable, with an offset to A5 specified in the first value in CODE segment. Value is 0x00000072 = offset 144
A5 initialized just before running the module, points to A5 world. Current stack address is saved in 4(A5) and restored after the module exits.
'Application Parameters' data is 32 bytes, jumptable is 264 bytes, total = 296 bytes
Offset 144 in jumptable is a jump to offset 0x00000E0E in CODE segment
*/

#ifdef MEDIA772_SU1E
#define F0466_EXPAND_GraphicToBitmap F466_rzzz_
#endif


#ifdef MEDIA645_A31E_A35E
#ifndef THINK_C
#include "AMIGAINC.H"
#endif
#endif

typedef struct {
        char* (*CallMalloc)();
        int (*CallMfree)();
        int (*CallFseek)();
        int (*CallFread)();
        unsigned long FileHandle;
        long StackSize;
        char* A5World;
        char* JumpTableAddress; /* Address of first jmp instruction, 2 bytes after the start of the jumptable memory area */
        char* StackAddress;
        char* MemoryAddress;
} DESCRIPTOR;

typedef struct { /* Size 28 = $1C */
        char* A5World;
        unsigned long Parameter; /* Example: TITL is written here before calling ANIM */
        long Unknown2; /* Unused */
        char* JumpTableAddress; /* Address of first jmp instruction, 2 bytes after the start of the jumptable memory area */
        long StackSize;
        char* Unknown3; /* Unused */
        char* MemoryAddress;
} FTL_EXECUTABLE;

typedef struct ftl_node { /* Size 12 = $C */
        struct ftl_node* Next;
        struct ftl_node* Previous;
        long Name;
} FTL_NODE;

typedef struct ftl_library { /* Size 50 = $32 */
        FTL_NODE FTLNode;
        FTL_EXECUTABLE FTLExecutable;
        struct ftl_library* Base;
        unsigned int16_t Flags; /* Bit 0: Can be expunged */
        int16_t Version;
        unsigned int16_t OpenCount;
        long Unused1;
} FTL_LIBRARY;

#define MASK0x0001_CAN_BE_EXPUNGED 0x0001

typedef struct { /* Size 90 = $5A */
        FTL_LIBRARY FTLLibrary;
        int _w_0x36_BaseLineStridePixelCount;
        int _w_0x38;
        int _w_0x3A;
        int _w_0x3C_ScreenWidth;
        int _w_0x3E_ScreenHeight;
        long _l_0x40;
        unsigned int _w_0x44;
        long _l_0x46;
        int _w_0x4A;
        int _w_0x4C;
        unsigned int _w_0x4E_PhysicalScreenOrdinal;
        unsigned char** _pc_0x50;
        char _b_0x54_ColorCount; /* Color count = 32 */
        char* _pc_0x56_ColorComponents; /* Array of 32 sets of 4 bytes for color components as : Color Index, Red, Green, Blue */
#ifdef MEDIA759_A36M_A35E_A35M_X31J_AU2E_AU3E
        long _l_0x5A_VerticalBlankCount;
#endif
} VDEO_FTL_LIBRARY;

typedef struct {
        FTL_LIBRARY FTLLibrary;
        int _w_0x36_BaseLineStridePixelCount; /* A horizontal line of bitmap in graphic memory occupies a multiple of this value. For example, on Amiga, an 1 to 15 pixels wide image will occupy the same size in memory as a 16 pixels wide image. This value is used to compute the actual memory storage required for an image */
        int _w_0x38;
        int _w_0x3A;
} GRF1_FTL_LIBRARY;

typedef struct {
        FTL_LIBRARY FTLLibrary;
} INT1_FTL_LIBRARY;

typedef struct {
        FTL_LIBRARY FTLLibrary;
} FIO1_FTL_LIBRARY;

typedef struct {
        FTL_LIBRARY FTLLibrary;
} MUSC_FTL_LIBRARY;

typedef struct {
        FTL_LIBRARY FTLLibrary;
        int _w_0x36;
} MEM1_FTL_LIBRARY;

typedef struct { /* Size 72 = $48 */
        FTL_LIBRARY FTLLibrary;
        int _w_0x36;
        char Padding[8];
        int _w_0x40;
        int _w_0x42;
        int _w_0x44;
        int _w_0x46;
} USIO_FTL_LIBRARY;

typedef struct {
        int UsioType; /* 0: None, 1: Key, 17: Mouse down, 18: Mouse up, 33: disk inserted */
        int UsioValue;
        union {
                struct {
                        long RawKeyCode;
                        int AsciiCode;
                } UsioKeyboard;
                struct {
                        int Buttons;
                        int X;
                        int Y;
                } UsioMouse;
        } Data;
} USIODATA;

typedef struct {
        int Unused1;
        int Unused2;
        long Unused3;
        int MouseButtons;
        int MouseX;
        int MouseY;
} USIODATA2;

typedef struct {
        void (*Code)();
        int Priority;   /* Ignored */
        int Type; /* 0: Vertical Blank, 1: Timer D (unused), 2: Sample (unused) */
        unsigned long CurrentInterruptCount;
        unsigned long RunEveryInterruptCount;     /* The handler code is executed every RunEveryInterruptCount interrupts */
} INT1_HANDLER;

/* FTL Driver names (4 ASCII characters as a long) */
#define FTL_PRIM 'PRIM' /* 0x5052494D */
#define FTL_ANIM 'ANIM' /* 0x414E494D */
#define FTL_APPA 'APPA' /* 0x41505041 */
#define FTL_APPB 'APPB' /* 0x41505042 */
#define FTL_CNFG 'CNFG' /* 0x434E4647 */
#define FTL_FIO1 'FIO1' /* 0x46494F31 */
#define FTL_GRF1 'GRF1' /* 0x47524631 */
#define FTL_INT1 'INT1' /* 0x494E5431 */
#define FTL_KAOS 'KAOS' /* 0x4B414F53 */
#define FTL_MEM1 'MEM1' /* 0x4D454D31 */
#define FTL_MUSC 'MUSC' /* 0x4D555343 */
#define FTL_SWSH 'SWSH' /* 0x53575348 */
#define FTL_USIO 'USIO' /* 0x5553494F */
#define FTL_VDEO 'VDEO' /* 0x5644454F */
#define FTL_TITL 'TITL' /* 0x5449544C */
#define FTL_ENDA 'ENDA' /* 0x454E4441 */
#define FTL_ENGL 'ENGL' /* 0x454E474C */
#define FTL_FNCH 'FNCH' /* 0x464E4348 */
#define FTL_GRMN 'GRMN' /* 0x47524D4E */

/* A function hook is a data structure containing:
Code to call to a replacement function for a library function.
Pointers to previous and next function: A function may be hooked multiple times and a history is kept as a linked list
Address of the library pointer that was replaced by the hook */
typedef struct func_hook { /* Size 28 = $1C */
        unsigned int16_t lea;                     /* 00  Set to 0x43F9 = 68000 instruction LEA xxx,a1 where xxx is the next long value to load in A1 */
        void* A1;                               /* 02  Address to load in A1 register before calling replacement function */
        unsigned int16_t jmp;                     /* 06  Set to 0x4EF9 = 68000 instruction JMP */
        void* ReplacementFunction;              /* 08  Address of replacement function */
        unsigned long illegal_rte;              /* 0C  Set to 0x4AFC4E73 = 68000 instructions ILLEGAL and RTE */
        struct func_hook* PreviousFunction;     /* 10  Address of previous function (original function or another hook) */
        struct func_hook* NextFunction;         /* 14  Address of next function (another hook) */
        void** LibraryFunctionPointer;          /* 18  Address of modified function pointer in library */
} FUNCTION_HOOK;

#include "FTL.H"

typedef struct { /* Size 40 = $28 */
        long AboveA5Size; /* From header of Macintosh CODE Resource 0: Size in bytes from the location pointed to by A5 to the upper end of the application space. This area contains 32 bytes of 'Application Parameters' used by the OS (starting with a pointer to QuickDraw globals) followed by the jumptable entries */
        long BelowA5Size; /* From header of Macintosh CODE Resource 0: Size in bytes of the application's global variables */
        long JumpTableSize; /* From header of Macintosh CODE Resource 0: Size in bytes of the jump table which contains one 8-byte entry for each inter-segment reference to functions */
        long JumpTableOffset; /* From header of Macintosh CODE Resource 0: Offset in bytes of the jump table from the location pointed to by A5. This value is always 32 (size of 'Application Parameters') */
        long StackSize;
        unsigned long CODESize;
        long DATASegmentSize;
        int16_t Unknown2;
        unsigned int16_t CODECompressed; /* 1 if CODE is compressed else 0 */
        int16_t Unknown4;
        unsigned int16_t JUMPChecksum;
        unsigned int16_t CODEChecksum;
        unsigned int16_t DATAChecksum;
} JUMPSEGMENTHEADER;

typedef struct { /* Size 8 */
        int16_t Unused; /* Jumptable entries are based on Macintosh executable jumptable entries which are 8 bytes large */
        int16_t Instruction; /* jmp */
        long Operand; /* Target address */
} JUMPTABLEENTRY;

typedef struct { /* Size 10 = $A */
        int16_t a;
        long DATACompressedSize; /* Size of DATA + ZERO resources from Macintosh executable */
        long RelocationDataSize; /* Size of DREL resource from Macintosh executable */
} DATASEGMENTHEADER;

#ifdef MEDIA772_SU1E
#ifndef THINK_C
/* ******************************** */
/* Macros for XBIOS calls (Trap 14) */
/* ******************************** */

#define Setpalette(a)               (void)R0056_TOS_CallXBIOS(0x06, a)
#define Floprd(a, b, c, d, e, f, g) (long)R0056_TOS_CallXBIOS(0x08, a, b, c, d, e, f, g)
#define Vsync()                     (void)R0056_TOS_CallXBIOS(0x25)

/* ******************************** */
/* Macros for GEMDOS calls (Trap 1) */
/* ******************************** */

#define Crawcin()      (long)R0057_TOS_CallGEMDOS(0x07)
#define Cconws(a)      (void)R0057_TOS_CallGEMDOS(0x09, a)
#define Cconis()       (int)R0057_TOS_CallGEMDOS(0x0B)
#define Super(a)       (long)R0057_TOS_CallGEMDOS(0x20, a)
#define Fopen(a, b)    (long)R0057_TOS_CallGEMDOS(0x3D, a, b)
#define Fclose(a)      (long)R0057_TOS_CallGEMDOS(0x3E, a)
#define Fread(a, b, c) (long)R0057_TOS_CallGEMDOS(0x3F, a, b, c)
#define Fseek(a, b, c) (long)R0057_TOS_CallGEMDOS(0x42, a, b, c)
#define Malloc(a)      (char*)R0057_TOS_CallGEMDOS(0x48, a)
#define Mfree(a)       (char*)R0057_TOS_CallGEMDOS(0x49, a)


extern V0921000_BlackPalette();
extern V0921001_ColorsPalette();
extern V0921002_Image();
extern long R0057_TOS_CallGEMDOS();
extern long gemdos(); /* This label overrides the gemdos routine from SYSLIB */
extern long R0056_TOS_CallXBIOS();
extern unsigned int16_t F0929_PRIM_05_FTL_Load();
extern char* F0934_ConvertValueToHexDigits();
#endif
#endif

#ifdef MEDIA577_X30J
#define F0917_PRIM_15_Memory_Allocate           primAlloc
#define F0918_PRIM_16_Memory_Free               primFree
#define F0919_PRIM_19_File_Seek                 primSeek
#define F0920_PRIM_20_File_Read                 primRead
/* launch
main */
#define F0927_PrintLoaderError          loaderError
#define F0928_PrintOSError              primError
#define F0929_PRIM_05_FTL_Load                  _load
#define F0930_GetHeaderChecksum         file_header_checksum
#define F0931_ChecksumWords             SumWordsBC
#define F0932_ChecksumBytes             SumBytesBC
#define F0933_GetHexStringFromValue     StrFromU32
#define F0934_ConvertValueToHexDigits   u32ToHexStr

#define G2295_IntegerToHexDigit         hexDigits
/* execute */

extern char* F0934_ConvertValueToHexDigits();
extern unsigned int16_t F0929_PRIM_05_FTL_Load();
extern void F0919_PRIM_19_File_Seek();
extern int16_t F0927_PrintLoaderError();
extern int16_t F0928_PrintOSError();
extern void F0920_PRIM_20_File_Read();
#endif

#ifdef MEDIA648_A31E_A35E_X31J
#ifndef THINK_C
/* X68_CallDrvrVector */
#define F6023_F6037_PRIM_04_Library_HookFunction        DrvrSetVect
#define F6026_F0929_PRIM_05_FTL_Load                    DrvrLoad
#define F6024_F6044_PRIM_06_FTL_FreeMemory              DrvrUnload
#define F6025_F6006_PRIM_07_FTL_Execute                 DrvrExecute
#define F6031_F6040_PRIM_08_Library_Open                DrvrOpen
#define F6032_F6041_PRIM_09_Library_Close               DrvrClose
#define F6033_F6042_PRIM_10_Library_FlagAsCanBeExpunged DrvrExpunge
#define F6027_F6047_PRIM_11_Library_AddToList           LinkFTLNode
#define F6028_F6048_PRIM_12_Library_RemoveFromList      UnlinkFTLNode
#define F6029_F6045_PRIM_13_Library_InitializeList      InitFTLNodeList
#define F6030_F6046_PRIM_14_Library_FindInList          FindFTLNode
#define F6013_F0917_PRIM_15_Memory_Allocate             PrimAlloc
#define F6014_F0918_PRIM_16_Memory_Free                 PrimFree
#define F6015_F6000_PRIM_17_File_Open                   PrimOpen
#define F6016_F6001_PRIM_18_File_Close                  PrimClose
#define F6017_F0919_PRIM_19_File_Seek                   PrimSeek
#define F6018_F0920_PRIM_20_File_Read                   PrimRead
#define F6022_F6005_PRIM_21_FTL_FatalLoaderError        PrimError
#define F6019_F6002_PRIM_22_Console_PrintMessage        PrimWString
#define F6020_F6003_PRIM_23_Input_WaitForChar           PrimKeyAvail
#define F6021_F6004_PRIM_24_Input_Read                  PrimKeyRead
#define F6034_F6049_PRIM_25_FTL_DecompressCODESegment   UncompressCode
#define F6035_F6043_PRIM_26_FTL_LoadAndExecute          RunApp
#define F6036_F6039_PRIM_27_File_IsOpenable             DrvrFile
#endif
#endif

#ifdef MEDIA692_X31J
#ifndef THINK_C
/* X68000 executable includes symbols. Here is the mapping between ReDMCSB names and original names */
/* main */
#define F6037_PRIM_04_Library_HookFunction              primSetVect
#define F6038_PRIM_28_Library_UnhookFunction            primResetVect
#define F6039_PRIM_27_File_IsOpenable                   primDrvrFile
#define F6040_PRIM_08_Library_Open                      primDrvrOpen
#define F6041_PRIM_09_Library_Close                     primDrvrClose
#define F6042_PRIM_10_Library_FlagAsCanBeExpunged       primDrvrExpunge
#define F6043_PRIM_26_FTL_LoadAndExecute                primRunApp
#define F0929_PRIM_05_FTL_Load                          primDrvrLoad
#define F6044_PRIM_06_FTL_FreeMemory                    primDrvrUnload
#define F6045_PRIM_13_Library_InitializeList            primInitList
#define F6046_PRIM_14_Library_FindInList                primFindNode
#define F6047_PRIM_11_Library_AddToList                 primLinkNode
#define F6048_PRIM_12_Library_RemoveFromList            primUnlinkNode
#define F6049_PRIM_25_FTL_DecompressCODESegment         prim_NOT_AVAIL
#define F6050_InitializeFTLLibraryManagement            PrimDrvrInit
/* F6051_UnLoadFTLLibrary */
#define F6052_FTL_UnloadAll                             PrimDrvrFinal
/* F6053_IsFunctionHooked
F0930_GetHeaderChecksum
F0931_ChecksumWords
F0932_ChecksumBytes */
/* F0934_ConvertValueToHexDigits */
#define F0933_GetHexStringFromValue                     StrFromU32
/* F7094_ConvertLongToString */
#define F7101_sprintf                                   sprintf
#define F0917_PRIM_15_Memory_Allocate                   s_PAlloc
#define F0918_PRIM_16_Memory_Free                       s_PFree
#define F6000_PRIM_17_File_Open                         s_POpen
#define F6001_PRIM_18_File_Close                        s_PClose
#define F0919_PRIM_19_File_Seek                         s_PSeek
#define F0920_PRIM_20_File_Read                         s_PRead
#define F6002_PRIM_22_Console_PrintMessage              s_PWString
#define F6003_PRIM_23_Input_WaitForChar                 s_PKeyAvail
#define F6004_PRIM_24_Input_Read                        s_PKeyRead
#define F6005_PRIM_21_FTL_FatalLoaderError              s_PError
#define F6006_PRIM_07_FTL_Execute                       primDrvrExecute
#define F6008_PRIM_29_Empty                             primMachine
#define F6009_GetInitialA5World                         GetCurrentGVar
#define F6010_ExecuteLibraryFunction                    CallDrvrVector
#define F6007_CallFTLProgram                            X68_execute
#endif

#define G0716_ac_ErrorMessage                    debugBuf

extern X68_CallDrvrVector();
extern BOOLEAN F6053_IsFunctionHooked();
extern char F6020_F6003_PRIM_23_Input_WaitForChar();
#endif

#ifdef MEDIA749_A36M_A31E_A31M_A33M_A35E_A35M_X31J
/* Amiga */
extern FTL_LIBRARY* F6050_InitializeFTLLibraryManagement();
extern void F6052_FTL_UnloadAll();
extern long F6007_CallFTLProgram();
extern char* F6009_GetInitialA5World();
extern void F6010_ExecuteLibraryFunction();
extern char* F6013_F0917_PRIM_15_Memory_Allocate();
extern FTL_LIBRARY* F6030_F6046_PRIM_14_Library_FindInList();
extern FTL_LIBRARY* F6025_F6006_PRIM_07_FTL_Execute();
extern F6022_F6005_PRIM_21_FTL_FatalLoaderError();

extern void F6008_PRIM_29_Empty();
extern void* F6038_PRIM_28_Library_UnhookFunction();
extern char F6039_PRIM_27_File_IsOpenable();
extern int16_t F6043_PRIM_26_FTL_LoadAndExecute();
extern void F6049_PRIM_25_FTL_DecompressCODESegment();

extern
#ifdef MEDIA692_X31J
short
#endif
int F6004_PRIM_24_Input_Read();

extern unsigned char F6003_PRIM_23_Input_WaitForChar();
extern void F6002_PRIM_22_Console_PrintMessage();
extern void F6005_PRIM_21_FTL_FatalLoaderError();
extern char F0920_PRIM_20_File_Read();
extern char F0919_PRIM_19_File_Seek();
extern void F6001_PRIM_18_File_Close();
extern char F6000_PRIM_17_File_Open();
extern void F0918_PRIM_16_Memory_Free();
extern long* F0917_PRIM_15_Memory_Allocate();
extern FTL_LIBRARY* F6046_PRIM_14_Library_FindInList();
extern void F6045_PRIM_13_Library_InitializeList();
extern void F6048_PRIM_12_Library_RemoveFromList();
extern void F6047_PRIM_11_Library_AddToList();
extern void F6042_PRIM_10_Library_FlagAsCanBeExpunged();
extern void F6041_PRIM_09_Library_Close();
extern FTL_LIBRARY* F6040_PRIM_08_Library_Open();
extern long F6006_PRIM_07_FTL_Execute();
extern void F6044_PRIM_06_FTL_FreeMemory();
extern int16_t F0929_PRIM_05_FTL_Load();
extern FUNCTION_HOOK* F6037_PRIM_04_Library_HookFunction();

extern F6035_F6043_PRIM_26_FTL_LoadAndExecute();
extern char F6015_F6000_PRIM_17_File_Open();
extern char F6036_F6039_PRIM_27_File_IsOpenable();
extern int16_t F6026_F0929_PRIM_05_FTL_Load();
extern F6016_F6001_PRIM_18_File_Close();
extern F6027_F6047_PRIM_11_Library_AddToList();
extern F6024_F6044_PRIM_06_FTL_FreeMemory();
extern F6028_F6048_RemoveLibraryFromLi();
extern char F6018_F0920_PRIM_20_File_Read();
extern char F6017_F0919_PRIM_19_File_Seek();
extern int16_t F6034_F6049_PRIM_25_FTL_DecompressCODESegment();
extern F6014_F0918_PRIM_16_Memory_Free();
extern F6029_F6045_PRIM_13_Library_InitializeList();
#endif


extern unsigned int16_t F0930_GetHeaderChecksum();
extern unsigned int16_t F0931_ChecksumWords();
extern unsigned int16_t F0932_ChecksumBytes();

extern VDEO_FTL_LIBRARY* G9002_VDEObase;
extern USIO_FTL_LIBRARY* G9001_USIObase;
extern GRF1_FTL_LIBRARY* G9000_GRF1base;
#endif
