#include "COMPILE.H"
#ifdef MEDIA000_S10EA
/* This program performs the following actions:
- Load the compressed PRG stored in START.PAK in a temporary memory location
- Decompress the data in another temporary memory location
- Overwrite itself in memory with the decompressed executable. In this purpose, it updates the base page with the new segment addresses and sizes and applies the relocation data. Before copying the decompressed executable, the small routine to perform the copy is itself copied to a safe location where it will not be overwritten during the copy.
- Run the decompressed executable */

typedef struct {
        long DecompressedDataWordCount;
        unsigned int16_t Signature;
        long TextSegmentSize;
        long DataSegmentSize;
        long BSSSegmentSize;
        long SymbolsSize;
} PAK_HEADER;


void main(
)
{
        register long L1851_l_ProcessTopAddress;
        register long L1852_l_BasePageAddress;
        register long L1853_l_CompressedDataAddress;
        register long L1854_l_DecompressedPRGAddress;
        register long* L1855_pl_Multiple;
#define A04_pl_BasePageValue  L1855_pl_Multiple
#define A04_pl_RelocationData L1855_pl_Multiple
        register long* L1856_pl_RelocationAddress;
        PAK_HEADER L1857_s_PAKHeader;
        long L1858_l_StartOffset;
        long L1859_l_Multiple;
#define A08_l_EndOffset      L1859_l_Multiple
#define A08_l_RelocationByte L1859_l_Multiple
        long L1860_l_TotalSizeInLongs;
        int16_t L1861_i_FileHandle;
        unsigned char* L1862_puc_RelocationData;


        A04_pl_BasePageValue = (long*)_base;
        L1851_l_ProcessTopAddress = A04_pl_BasePageValue[1]; /* htpa value from base page (All available memory is allocated to the process when GEMDOS runs a PRG) */
        L1852_l_BasePageAddress = (long)_base;
        if ((L1861_i_FileHandle = Fopen("start.pak", C0_READ_ONLY)) < 0) {
                for (;;); /*_Infinite loop_*/
        }
        Fread(L1861_i_FileHandle, (long)sizeof(PAK_HEADER), &L1857_s_PAKHeader); /* Read first 22 bytes of header. The actual header is 32 bytes large but the last ten bytes are 0x00 and are not read */
        if (L1857_s_PAKHeader.Signature != 0x601A) {
                for (;;); /*_Infinite loop_*/
        }
        A08_l_EndOffset = Fseek(0L, L1861_i_FileHandle, C2_SEEK_FROM_END_OF_FILE);
        L1858_l_StartOffset = Fseek(32L, L1861_i_FileHandle, C0_SEEK_FROM_BEGINNING_OF_FILE); /* PAK Header is 32 bytes large */
        L1853_l_CompressedDataAddress = L1851_l_ProcessTopAddress - ((A08_l_EndOffset - L1858_l_StartOffset + 1) & 0xFFFFFFFE);
        L1854_l_DecompressedPRGAddress = L1852_l_BasePageAddress + 16000; /* Decompress at arbitrary location after the START.PRG */
        Fread(L1861_i_FileHandle, A08_l_EndOffset - L1858_l_StartOffset, L1853_l_CompressedDataAddress);
        F0913_DecompressPAK(L1853_l_CompressedDataAddress, L1853_l_CompressedDataAddress + 3840, L1857_s_PAKHeader.DecompressedDataWordCount, L1854_l_DecompressedPRGAddress);
        /* Apply relocation data */
        A04_pl_RelocationData = (long*)(L1854_l_DecompressedPRGAddress + (L1860_l_TotalSizeInLongs = L1857_s_PAKHeader.TextSegmentSize + L1857_s_PAKHeader.DataSegmentSize + L1857_s_PAKHeader.SymbolsSize)); /* Address where the first relocation should occur */
        L1860_l_TotalSizeInLongs = (L1860_l_TotalSizeInLongs >> 2) + 1;
        L1856_pl_RelocationAddress = (long*)((*A04_pl_RelocationData++) + L1854_l_DecompressedPRGAddress);
        L1862_puc_RelocationData = (unsigned char*)A04_pl_RelocationData;
        *L1856_pl_RelocationAddress += L1852_l_BasePageAddress + 256;
        while ((A08_l_RelocationByte = *L1862_puc_RelocationData++) != 0) {
                if (A08_l_RelocationByte == 1) {
                        L1856_pl_RelocationAddress += 254; /* BUG0_01 Coding error without consequence. This will add 254 * 4 = 1016 instead of the required 254 because L1856_pl_RelocationAddress is a pointer to a long (4 bytes). No consequence because there are no relocation bytes with value 1 in the compressed PRG file. Executables produced by the Megamax C compiler only have relocation bytes for the jumptable located at the beginning of the executable and all relocation bytes have a value of 6 */
                } else {
                        L1856_pl_RelocationAddress = (long*)((char*)L1856_pl_RelocationAddress + A08_l_RelocationByte);
                        *L1856_pl_RelocationAddress += L1852_l_BasePageAddress + 256;
                }
        }
        /* Update the base page with information for the decompressed PRG */
        A04_pl_BasePageValue = (long*)(_base + 12);
        *A04_pl_BasePageValue++ = L1857_s_PAKHeader.TextSegmentSize;                                                                 /* Update codelen in base page */
        *A04_pl_BasePageValue++ = L1852_l_BasePageAddress + L1857_s_PAKHeader.TextSegmentSize + 256;                                   /* Update ldata in base page */
        *A04_pl_BasePageValue++ = L1857_s_PAKHeader.DataSegmentSize;                                                                 /* Update datalen in base page */
        *A04_pl_BasePageValue++ = L1852_l_BasePageAddress + L1857_s_PAKHeader.TextSegmentSize + L1857_s_PAKHeader.DataSegmentSize + 256; /* Update lbss in base page */
        *A04_pl_BasePageValue = L1857_s_PAKHeader.BSSSegmentSize;                                                                    /* Update bsslen in base page */
        /* Overwrite START.PRG in memory with the decompressed and relocated PRG. The small routine to perform the copy is itself copied first at the location where the compressed data was stored so that it is not overwritten while copying the decompressed PRG */
        asm {
                        lea     T0911001_CopyDecompressedPRG(PC),A0     /* Copy routine to copy decompressed PRG */
                        movea.l L1853_l_CompressedDataAddress,A1
                        movea.l A1,A2
                        move.w  #32,D0                                  /* Copy 32 bytes (more than necessary) */
                T0911000_Loop:
                        move.b  (A0)+,(A1)+
                        dbf     D0,T0911000_Loop
                        movea.l L1851_l_ProcessTopAddress,A7              /* Set new stack address */
                        movea.l _base(A4),A1
                        move.l  A1,-(A7)
                        adda.l  #256,A1                                 /* Address of TEXT segment (after base page) */
                        movea.l L1854_l_DecompressedPRGAddress,A0
                        move.l  L1860_l_TotalSizeInLongs(A6),D0
                        jmp     (A2)                                    /* Call routine below to copy decompressed PRG in place of the loaded START.PRG */
                T0911001_CopyDecompressedPRG:
                        movea.l A1,A2
                T0911002_Loop:
                        move.l  (A0)+,(A1)+
                        dbf     D0,T0911002_Loop
                        jsr     (A2)                                    /* Run the decompressed PRG */
        }
}

#include "TOS.C"
#include "DECOMPCO.C"
#endif
