// ReadMbm.c
// Slightly modified by Yan...

#include "tde.h"

#define RedOn6bits      0
#define GreenOn6bits    1
#define BlueOn6bits     0

ACP_tdxBool TDE_g_bRedOn6bits;
ACP_tdxBool TDE_g_bGreenOn6bits;
ACP_tdxBool TDE_g_bBlueOn6bits;

////////////////////////////////////////////////////////////////////////////////
// TDE_vSetRGBFormat
// Set the RGB format
////////////////////////////////////////////////////////////////////////////////
void TDE_vSetRGBFormat ( ACP_tdxBool bRedOn6bits, ACP_tdxBool bGreenOn6bits, ACP_tdxBool bBlueOn6bits )
{
  TDE_g_bRedOn6bits = bRedOn6bits;
  TDE_g_bGreenOn6bits = bGreenOn6bits;
  TDE_g_bBlueOn6bits = bBlueOn6bits;
}

////////////////////////////////////////////////////////////////////////////////
// TDE_lReadMBMData
// Reads the MBM data from an opened file and convert them into the right
// format according to the video board.
// Return 1 if OK, 0 if Failed.
////////////////////////////////////////////////////////////////////////////////
long TDE_lReadMBMData (FILE *pFile, TDE_tdsSprite *p_stSprite)
{
    // Local variables
    size_t          nbBlocks;
    unsigned short  sPictureWidth, sPictureHeight, sMagicColor;
    unsigned short  R, G, B, c555;
    TDE_tdxPixel    *Buffer, *TempBuff;
    unsigned long   usI, usLine, lPicSize;
    BOOL            bTransparent;

    //**********************************************************
    // Read the data
    //**********************************************************
    
    // Read the Width
    nbBlocks = fread( &sPictureWidth,  sizeof(short), 1, pFile);
    if (nbBlocks != 1)
    {
        Erm_M_UpdateLastError  (Tde,
                                C_ucErmDefaultChannel,
                                E_uwTdeWarningCantReadFile,
                                C_lErmNoDebugData,
                                C_ucErmOpenInfoWindow,
                                C_ucAllowStopForDebug, NULL);
        return 0;
    }
    // Read the Height
    nbBlocks = fread( &sPictureHeight, sizeof(short), 1, pFile);
    if (nbBlocks != 1)
    {
        Erm_M_UpdateLastError  (Tde,
                                C_ucErmDefaultChannel,
                                E_uwTdeWarningCantReadFile,
                                C_lErmNoDebugData,
                                C_ucErmOpenInfoWindow,
                                C_ucAllowStopForDebug, NULL);
        return 0;
    }
   // Read the magic color
    nbBlocks = fread( &sMagicColor, sizeof(short), 1, pFile);
    if (nbBlocks != 1)
    {
        Erm_M_UpdateLastError  (Tde,
                                C_ucErmDefaultChannel,
                                E_uwTdeWarningCantReadFile,
                                C_lErmNoDebugData,
                                C_ucErmOpenInfoWindow,
                                C_ucAllowStopForDebug, NULL);
        return 0;
    }
    // Compute the size of the picture (in pixels)
    lPicSize = (long)(sPictureHeight) * (long)(sPictureWidth);
     // Allocate memory for temporary buffer and for definitive buffer
    M_TdeAlloc(Buffer,TDE_tdxPixel *,(sizeof(short)*lPicSize));
    if (Buffer == NULL)
        return 0;
    M_TdeAlloc(TempBuff,TDE_tdxPixel *,(sizeof(short)*lPicSize));
    if (TempBuff == NULL)
    {
        M_TdeFree (Buffer);
        return 0;
    }
    // Read the data
    nbBlocks =  fread( TempBuff, sizeof(short), lPicSize, pFile);
    if (nbBlocks != lPicSize)
    {
        Erm_M_UpdateLastError  (Tde,
                                C_ucErmDefaultChannel,
                                E_uwTdeWarningCantReadFile,
                                C_lErmNoDebugData,
                                C_ucErmOpenInfoWindow,
                                C_ucAllowStopForDebug, NULL);
        return 0;
    }

    //**********************************************************
    // Convert the data
    //**********************************************************

    // Let's assume the bitmap isn't transparent
    bTransparent = FALSE;
    
    // 555 -> 565
    if (TDE_g_bGreenOn6bits)
    {
        // Magic color
        R = (sMagicColor&0x7C00)>>10;
        G = (sMagicColor&0x3E0)>>5;
        B = sMagicColor&0x1F;
        sMagicColor = (R<<11) + (G<<6) + B;        
        // Loop on each line  
        for ( usLine=0; usLine<lPicSize; usLine+=sPictureWidth )
        {
            // Loop on each point
            for ( usI=0; usI<sPictureWidth; usI++ )
            {
                // Get the original color
                c555 = TempBuff[lPicSize - usLine - sPictureWidth + usI];
                // If it is not transparent, convert it
                if (c555&&0x8000)
                {
                    R = (c555&0x7C00)>>10;
                    G = (c555&0x3E0)>>5;
                    B = c555&0x1F;
                    Buffer[usLine + usI] = (R<<11) + (G<<6) + B;
                }
                // If it is transparent, set it to the magic color
                else
                {
                    bTransparent = TRUE;
                    Buffer[usLine + usI] = sMagicColor;
                }
            } // for (usI....
         } // for (us Line ....
    }
    // 555 -> 556
    else if (TDE_g_bBlueOn6bits)
    {
        // Magic color
        R = (sMagicColor&0x7C00)>>10;
        G = (sMagicColor&0x3E0)>>5;
        B = sMagicColor&0x1F;
        sMagicColor = (R<<11) + (G<<6) + (B<<1);            
        // Loop on each line  
        for ( usLine=0; usLine<(sPictureHeight*sPictureWidth); usLine+=sPictureWidth )
        {
            // Loop on each point
            for ( usI=0; usI<sPictureWidth; usI++ )
            {
                // Get the original color
                c555 = TempBuff[lPicSize - usLine - sPictureWidth + usI];
                // If it is not transparent, convert it
                if (c555&&0x8000)
                {                
                    R = (c555&0x7C00)>>10;
                    G = (c555&0x3E0)>>5;
                    B = c555&0x1F;
                    Buffer[usLine + usI] = (R<<11) + (G<<5) + (B<<1);
                }
                // If it is transparent, set it to the magic color
                else
                {
                    bTransparent = TRUE;
                    Buffer[usLine + usI] = sMagicColor;
                }
            }
         }
    }
    // 555 -> 655
    else if (TDE_g_bRedOn6bits)
    {
        // Magic color
        R = (sMagicColor&0x7C00)>>10;
        G = (sMagicColor&0x3E0)>>5;
        B = sMagicColor&0x1F;
        sMagicColor = (R<<11) + (G<<5) + B;      
        // Loop on each line  
        for ( usLine=0; usLine<(sPictureHeight*sPictureWidth); usLine+=sPictureWidth )
        {
            // Loop on each point
            for ( usI=0; usI<sPictureWidth; usI++ )
            {
                // Get the original color
                c555 = TempBuff[lPicSize - usLine - sPictureWidth + usI];
                // If it is not transparent, convert it
                if (c555&&0x8000)
                {                                
                     R = (c555&0x7C00)>>10;
                     G = (c555&0x3E0)>>5;
                     B = c555&0x1F;
                     Buffer[usLine + usI] = (R<<11) + (G<<5) + B;
                }
                // If it is transparent, set it to the magic color
                else
                {
                    bTransparent = TRUE;
                    Buffer[usLine + usI] = sMagicColor;
                }
            } // for (usI...
         } // for (usLine...
    } // if
    // 555 -> 555
    else
    {
        // Loop on each line  
        for ( usLine=0; usLine<(sPictureHeight*sPictureWidth); usLine+=sPictureWidth )
        {
            // Loop on each point
            for ( usI=0; usI<sPictureWidth; usI++ )
            {
                // Get the original color
                c555 = TempBuff[lPicSize - usLine - sPictureWidth + usI];
                // If it is not transparent, convert it
                if (c555&&0x8000)
                {                                                     
                     Buffer[usLine + usI] = c555;
                }                
                // If it is transparent, set it to the magic color
                else
                {
                    bTransparent = TRUE;
                    Buffer[usLine + usI] = sMagicColor;
                }
            } // for (usI...
         } // for (usLine...        
    }
    // Free the temporary buffer
    M_TdeFree(TempBuff);
    // Set the members of the sprite structure
    p_stSprite->stDim.xX    = sPictureWidth;
    p_stSprite->stDim.xY    = sPictureHeight;
    p_stSprite->xMagicColor = sMagicColor;    
    p_stSprite->v_pData     = Buffer;
    // Set transparency
    if (bTransparent)
        p_stSprite->c_NZ = 1;
    else
        p_stSprite->c_NZ = 0;
    return 1;
}

////////////////////////////////////////////////////////////////////////////////
// TDE_lReadAndConvertMBMFile
// Read a MBM file (open and close it).
// Returns 1 if OK, 0 if FAILED
////////////////////////////////////////////////////////////////////////////////
long TDE_lReadAndConvertMBMFile(char *filename, TDE_tdsSprite *p_stSprite)
{
    FILE            *pFile;

    // Open the file
    if ( (pFile = fopen(filename, "rb")) != NULL )
    {
        fseek (pFile, 0, SEEK_SET);
        // Read it and convert the data
        if (!TDE_lReadMBMData (pFile, p_stSprite))
        {
            fclose (pFile);
            return 0;
        }
        fclose (pFile);
    }
    else
    {
        Erm_M_UpdateLastError  (Tde,
                                C_ucErmDefaultChannel,
                                E_uwTdeWarningCantOpenFileForReading,
                                C_lErmNoDebugData,
                                C_ucErmOpenInfoWindow,
                                C_ucAllowStopForDebug, NULL);
        return 0;
    }
    return 1;
}


////////////////////////////////////////////////////////////////////////////////
// TDE_lReadCursorAnimation
// Read cursor animation in a text file
// Returns 1 if OK
////////////////////////////////////////////////////////////////////////////////
long TDE_lReadCursorAnimation (char *szDir, char *szTxtFile, TDE_tdsAnimatedCursor *Anim)
{
    FILE                        *pFile;
    char                        text[30];
    int                         NB_STEP, i;
    TDE_p_stAnimatedCursor      Next;
    char                        szFilename[100];

    // Obtain txt filename with path
    strcpy (szFilename, szDir);
    strcat (szFilename, szTxtFile);

    // Open txt file
    if ( (pFile = fopen(szFilename, "r")) != NULL )
    {
        fseek (pFile, 0, SEEK_SET);
        // Number of sprites
        if (!fgets (text, 30, pFile))
        {
            Erm_M_UpdateLastError  (Tde,
                                    C_ucErmDefaultChannel,
                                    E_uwTdeWarningCantReadFile,
                                    C_lErmNoDebugData,
                                    C_ucErmOpenInfoWindow,
                                    C_ucAllowStopForDebug, NULL);
            fclose (pFile);
            return 0;
        }       
        NB_STEP = atoi(text);
        // Active point coordinates
        if (!fgets(text, 30, pFile))
        {
            Erm_M_UpdateLastError  (Tde,
                                    C_ucErmDefaultChannel,
                                    E_uwTdeWarningCantReadFile,
                                    C_lErmNoDebugData,
                                    C_ucErmOpenInfoWindow,
                                    C_ucAllowStopForDebug, NULL);
            fclose (pFile);
            return 0;
        }       
        Anim->stActiveCoordinates.xX = atof(text);
        if (!fgets(text, 30, pFile))
        {
            Erm_M_UpdateLastError  (Tde,
                                    C_ucErmDefaultChannel,
                                    E_uwTdeWarningCantReadFile,
                                    C_lErmNoDebugData,
                                    C_ucErmOpenInfoWindow,
                                    C_ucAllowStopForDebug, NULL);
            fclose (pFile);
            return 0;
        }       
        Anim->stActiveCoordinates.xY = atof(text);        
        // First step
        Anim->Step.v_pData = NULL;    
        Anim->Step.c_NZ = 1;
        Anim->Step.cFlip = 0;
        Anim->Step.cSemiTransparent = 0;
        if (!fscanf (pFile, "%s", text))
        {
            Erm_M_UpdateLastError  (Tde,
                                    C_ucErmDefaultChannel,
                                    E_uwTdeWarningCantReadFile,
                                    C_lErmNoDebugData,
                                    C_ucErmOpenInfoWindow,
                                    C_ucAllowStopForDebug, NULL);
            fclose (pFile);
            return 0;
        }
        // Obtain MBM filename with path
        strcpy (szFilename, szDir);
        strcat (szFilename, text);
        // Read MBM file
        if (!TDE_lReadAndConvertMBMFile(szFilename, &(Anim->Step)))
        {
            fclose (pFile);
            return 0;
        }
        Next = Anim;

        for ( i=0; i<NB_STEP; i++ )
        {
            M_TdeAlloc(Next->Next, TDE_tdsAnimatedCursor *, (sizeof(TDE_tdsAnimatedCursor)));
            Next = Next->Next;
            if (Next == NULL)
            {
                fclose (pFile);
                return 0;
            }
            Next->Next = NULL;
            Next->Step.v_pData = NULL;    
            Next->Step.c_NZ = 1;
            Next->Step.cFlip = 0;
            Next->Step.cSemiTransparent = 0;
            if (!fscanf (pFile, "%s", text))
            {
                Erm_M_UpdateLastError  (Tde,
                                        C_ucErmDefaultChannel,
                                        E_uwTdeWarningCantReadFile,
                                        C_lErmNoDebugData,
                                        C_ucErmOpenInfoWindow,
                                        C_ucAllowStopForDebug, NULL);
                fclose (pFile);
                return 0;
            }
            // Obtain MBM filename with path
            strcpy (szFilename, szDir);
            strcat (szFilename, text);
            // Read MBM file
            if (!TDE_lReadAndConvertMBMFile(szFilename, &(Next->Step)))
            {
                fclose (pFile);
                return 0;
            }
        }
        fclose (pFile);
    }
    else
    {
        Erm_M_UpdateLastError  (Tde,
                                C_ucErmDefaultChannel,
                                E_uwTdeWarningCantOpenFileForReading,
                                C_lErmNoDebugData,
                                C_ucErmOpenInfoWindow,
                                C_ucAllowStopForDebug, NULL);
        return 0;
    }
    return 1;
}

////////////////////////////////////////////////////////////////////////////////
// TDE_vDestroyAnimatedCursor
// Aim : Destroy animated cursor
////////////////////////////////////////////////////////////////////////////////
void TDE_vDestroyAnimatedCursor(TDE_tdsAnimatedCursor *Anim)
{
    TDE_p_stAnimatedCursor      Last, Previous;

    if ( Anim == NULL)
        return;
    
    while (Anim->Next != NULL)
    {
        Last        = Anim->Next;
        Previous    = Anim;
        while (Last->Next != NULL)
        {
            Previous    = Last;
            Last        = Last->Next;
        }
        if (Last->Step.v_pData)
            M_TdeFree (Last->Step.v_pData);
        M_TdeFree                   (Last);
        Previous->Next = NULL;
    }
    if (Anim->Step.v_pData)
        M_TdeFree (Anim->Step.v_pData);    
}

////////////////////////////////////////////////////////////////////////////////
// TDE_lReadMBFFile
// Read a MBF file (font file)
// File structure :
//      224 character definitions, ASCII codes from 32 to 255
// Returns 1 if OK, 0 if failed
////////////////////////////////////////////////////////////////////////////////
long TDE_lReadMBFFile(char *filename, TDE_tdsBitmapFont *BFont)
{
    // Local variables
    FILE                    *pFile;
    unsigned short          VAlign;
    short                   i;
    TDE_tdsBitmapLetter     *pLetter;
    TDE_tdsSprite           *p_Spr;
    unsigned short          H, HMax = 0;
    unsigned short          VAMax = 0;
    unsigned short          HorzSep, VertSep;

    // First initialize every characters to NULL
    for ( i=0; i<TDE_kNBLETTERS; i++ )
    {
        BFont->p_stMBLetter[i] = NULL;
    }
    // Open the file
    if ( (pFile = fopen(filename, "rb")) != NULL )
    {
        fseek( pFile, 0, SEEK_SET );
        // Loop on each character
        for ( i=0; i<TDE_kNBLETTERS; i++ )
        {
            // Read the vertical alignment
            if (fread(&VAlign, sizeof(unsigned short), 1, pFile) != 1)
            {
                Erm_M_UpdateLastError  (Tde,
                                        C_ucErmDefaultChannel,
                                        E_uwTdeWarningCantReadFile,
                                        C_lErmNoDebugData,
                                        C_ucErmOpenInfoWindow,
                                        C_ucAllowStopForDebug, NULL);
                fclose (pFile);
                return 0;
            }
            // If the character is defined
            if ( VAlign != 0x8000 )
            {
                // SuperObject memory allocation
                M_TdeAlloc (pLetter, TDE_tdsBitmapLetter *, sizeof(TDE_tdsBitmapLetter));
                if (pLetter == NULL)
                    return 0;
                pLetter->usVAlign        = VAlign;

                // SuperObject initialisation
                pLetter->stBLetter.sPriority                        = 40;
                pLetter->stBLetter.p_stChild                        = NULL;
                pLetter->stBLetter.p_stLeftBrother                  = NULL;
                pLetter->stBLetter.p_stRightBrother                 = NULL;
                pLetter->stBLetter.p_stFather                       = NULL;                
                pLetter->stBLetter.eType                            = TDE_eOT_SPRITE;
                pLetter->stBLetter.stMatrix.xAngle                  = 0;
                pLetter->stBLetter.stMatrix.stScale.xX              = 0;
                pLetter->stBLetter.stMatrix.stScale.xY              = 0;                
                pLetter->stBLetter.stMatrix.stTranslateVertex.xX    = 0;                
                pLetter->stBLetter.stMatrix.stTranslateVertex.xY    = 0;
                pLetter->stBLetter.p_stSOClipRect                   = NULL;
                pLetter->stBLetter.lArea                            = 0xFFFFFFFF;
                pLetter->stBLetter.lObject                          = 0xFFFFFFFF;

                // Sprite allocation and initialization
                TDE_vInitMemSprite( &(pLetter->stBLetter), NULL, 1);
                p_Spr = pLetter->stBLetter.p_stSprite;
                if (p_Spr == NULL)
                {
                    M_TdeFree (pLetter);
                    fclose (pFile);
                    return 0;
                }
                // Read MBM bitmap
                if (!TDE_lReadMBMData (pFile, p_Spr))
                {
                    TDE_vReleaseMemSprite (p_Spr);
                    M_TdeFree (pLetter);
                    fclose (pFile);
                    return 0;                    
                }
                // HMax & VAMax
                if (pLetter->usVAlign > VAMax)
                    VAMax = pLetter->usVAlign;
                H = p_Spr->stDim.xY - pLetter->usVAlign;
                if (H>HMax)
                    HMax = H;
                // Set character
                BFont->p_stMBLetter[i]  = pLetter;
            }
            else
            {
                BFont->p_stMBLetter[i] = NULL;
            }            
        }        
        // Read Horizontal spacing (default:3)
        if (fread( &HorzSep,  sizeof(short), 1, pFile) != 1)
            HorzSep = 3;
        // Read Vertical spacing (default:3)
        if (fread( &VertSep,  sizeof(short), 1, pFile) != 1)
            VertSep = 3;
        // Set global members
        BFont->usHorzSep        = HorzSep;
        BFont->usVertSep        = VertSep;        
        BFont->usVAMax          = VAMax;
        BFont->usHMax           = HMax;
        // Close the file
        fclose(pFile);
    }
    else
    {
        Erm_M_UpdateLastError  (Tde,
                                C_ucErmDefaultChannel,
                                E_uwTdeWarningCantOpenFileForReading,
                                C_lErmNoDebugData,
                                C_ucErmOpenInfoWindow,
                                C_ucAllowStopForDebug, NULL);
        return 0;
    }
    return 1;
}

////////////////////////////////////////////////////////////////////////////////
// TDE_lReadMTFFile
// Read a MTF file (open and close it).
// Returns 1 if OK, 0 if FAILED
////////////////////////////////////////////////////////////////////////////////
long TDE_lReadMTFFile(char *filename, TDE_tdsTrueTypeFont *pFont)
{
    FILE            *pFile;
    LOGFONT         stLogFont;
    COLORREF        lColor;
    HFONT           hFont;
    
    // Open the file
    if ( (pFile = fopen(filename, "rb")) != NULL )
    {
        fseek (pFile, 0, SEEK_SET);
        // Read the LOGFONT structure
        if (fread(&stLogFont, sizeof(LOGFONT), 1, pFile) != 1)
        {
            Erm_M_UpdateLastError  (Tde,
                                    C_ucErmDefaultChannel,
                                    E_uwTdeWarningCantReadFile,
                                    C_lErmNoDebugData,
                                    C_ucErmOpenInfoWindow,
                                    C_ucAllowStopForDebug, NULL);
            fclose (pFile);
            return 0;
        }
        // Read the COLORREF
        if (fread(&lColor, sizeof(COLORREF), 1, pFile) != 1)
        {
            Erm_M_UpdateLastError  (Tde,
                                    C_ucErmDefaultChannel,
                                    E_uwTdeWarningCantReadFile,
                                    C_lErmNoDebugData,
                                    C_ucErmOpenInfoWindow,
                                    C_ucAllowStopForDebug, NULL);
            fclose (pFile);
            return 0;
        }
        fclose (pFile);
        // Create the Windows font
        hFont = CreateFont  
            (stLogFont.lfHeight, stLogFont.lfWidth, stLogFont.lfEscapement,
             stLogFont.lfOrientation, stLogFont.lfWeight, stLogFont.lfItalic,
             stLogFont.lfUnderline, stLogFont.lfStrikeOut, stLogFont.lfCharSet,
             stLogFont.lfOutPrecision, stLogFont.lfClipPrecision, stLogFont.lfQuality, 
             stLogFont.lfPitchAndFamily, stLogFont.lfFaceName);
        if (hFont == NULL)
            return 0;
        // Set the members of the structure
        pFont->hFont    = hFont;
        pFont->lColor   = lColor;
    }
    else
    {
        Erm_M_UpdateLastError  (Tde,
                                C_ucErmDefaultChannel,
                                E_uwTdeWarningCantOpenFileForReading,
                                C_lErmNoDebugData,
                                C_ucErmOpenInfoWindow,
                                C_ucAllowStopForDebug, NULL);
        return 0;
    }
    return 1;
}

