//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
#include <stdio.h>
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma link "AdvGrid"
#pragma link "BaseGrid"
#pragma resource "*.dfm"
#include <Inifiles.hpp>
TForm1 *Form1;
int iTries;
int cpal[256][256];
bool doublesize;

//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
    : TForm(Owner)
{
    if (!FileExists("rleview.ini")) {
        ShowMessage("Cannot open ini file");
    }
    TIniFile* whmini = new TIniFile(".\\rleview.ini");
    int idbl;
    idbl = whmini->ReadInteger("Settings","Double",1);
    FileListBox1->Mask = "*." + whmini->ReadString("Settings","Files","rle");
    FileListBox1->Directory = whmini->ReadString("Settings","Directory","C:\\Redmoon\\RLEs\\Int\\");

    if (idbl == 0) {
        doublesize = false;
    } else {
        doublesize = true;
    }
    if (FileListBox1->Mask == "*.rle") {
        Image1->Visible = true;
        AdvStringGrid1->Visible = false;
    } else {
        Image1->Visible = false;
        AdvStringGrid1->Visible = true;
    }
    CheckBox1->Checked = doublesize;
    delete whmini;
    for (int i=0;i<256;i++) {
        for (int j=0;j<256;j++) {
            int tmpr, tmpg,tmpb;
            tmpr = int(j/2)*2;//254
            tmpg = int(j%8)*32;//224
            tmpb = i*8;//912
            tmpb = tmpb+ (i%8);//2 914
            while (tmpb > 255) {//3
                tmpg += 4;
                tmpb -= 256;
            }
            tmpg = tmpg+(tmpg%2);
            while (tmpg > 255) {
                tmpr += 2;
                tmpg -= 256;
            }
            tmpr = tmpr+(tmpr%2);
            while (tmpr > 255) {
                tmpr -= 256;
            }
            cpal[i][j] = RGB(tmpr,tmpg,tmpb);
        }
    }
    iTries = 0;
}
//---------------------------------------------------------------------------


void loadlst(void)
{
    FILE *f;
    char *buff, *bptr;
    long flength;
    AnsiString Value; //temp string value
    AnsiString Version; //temp string value
    int t1 = 0; //temp int value
    int t2 = 0; //temp int value

    f = fopen(Form1->FileListBox1->FileName.c_str(),"rb");
    if (f == NULL) {
        ShowMessage("Error Loading File");
        return;
    }

    fseek(f,0,SEEK_END);  // seek to end
    flength = ftell(f);        // get length of file in bytes
    buff = new char[flength+1];   // allocate full size of file
    if (buff==NULL) {
        fclose(f);
        ShowMessage("Not enough Memory");
        return;
    }
    fseek(f,0,SEEK_SET);  // rewind to beginning
    fread(buff,1,flength,f);   // grab whole file into buff[]
    fclose(f);
    buff[flength]=0; // ensure null terminator at eof
    bptr = buff;
    int ilength = *bptr++;
    Value = "";
    for (int j=0;j<ilength;j++) {
        Value = Value + AnsiString(*bptr++);
    }
    ilength = *bptr++;
    Version = "";
    for (int j=0;j<ilength;j++) {
        Version = Version + AnsiString(*bptr++);
    }
//    if (Value != "1.0") {
//        free(buff);
//        ShowMessage("Unknown version number");
//        return;
//    }
    t1 = (*bptr++ & 0xFF);
    t1 |= (*bptr++ & 0xFF) << 0x08;
    t1 |= (*bptr++ & 0xFF) << 0x10;
    t1 |= (*bptr++ & 0xFF) << 0x18;
//    Label2->Caption = IntToStr(t1);
    t1 = (*bptr++ & 0xFF);
    t1 |= (*bptr++ & 0xFF) << 0x08;
    t1 |= (*bptr++ & 0xFF) << 0x10;
    t1 |= (*bptr++ & 0xFF) << 0x18;
//    Label3->Caption = IntToStr(t1);
    int total = t1;
    Form1->AdvStringGrid1->RowCount = t1+1;
    Form1->AdvStringGrid1->Cells[0][0] = "Name";
    Form1->AdvStringGrid1->Cells[1][0] = "Tile#";
    Form1->AdvStringGrid1->Cells[2][0] = "File#";
    Form1->AdvStringGrid1->Cells[3][0] = "Index";
    //166186
    //13984
    for (int i=0; i<total; i++) {
        ilength = *bptr++;
        Value = "";
        for (int j=0;j<ilength;j++) {
            Value = Value + AnsiString(*bptr++);
        }
        Form1->AdvStringGrid1->Cells[0][i+1] = Value;
        t1 = (*bptr++ & 0xFF);          t1 |= (*bptr++ & 0xFF) << 0x08;
        t1 |= (*bptr++ & 0xFF) << 0x10; t1 |= (*bptr++ & 0xFF) << 0x18;
        Form1->AdvStringGrid1->Cells[1][i+1] = IntToStr(t1);
        t2 = (*bptr++ & 0xFF);          t2 |= (*bptr++ & 0xFF) << 0x08;
        t2 |= (*bptr++ & 0xFF) << 0x10; t2 |= (*bptr++ & 0xFF) << 0x18;
        Form1->AdvStringGrid1->Cells[2][i+1] = IntToStr(t2);
        t1 = (*bptr++ & 0xFF);          t1 |= (*bptr++ & 0xFF) << 0x08;
        t1 |= (*bptr++ & 0xFF) << 0x10; t1 |= (*bptr++ & 0xFF) << 0x18;
        Form1->AdvStringGrid1->Cells[3][i+1] = IntToStr(t1);
        if (Version == "1.2") {
            t1 = (*bptr++ & 0xFF);          t1 |= (*bptr++ & 0xFF) << 0x08;
            t1 |= (*bptr++ & 0xFF) << 0x10; t1 |= (*bptr++ & 0xFF) << 0x18;
            Form1->AdvStringGrid1->Cells[4][i+1] = IntToStr(t1);
        } else {
            Form1->AdvStringGrid1->Cells[4][i+1] = "";
        }
    }
    free(buff);
}
//---------------------------------------------------------------------------

void loadRLE(AnsiString FileName, int tNum)
{
    FILE *f;
    long flength;
    AnsiString Value; //temp string value
    int t1 = 0; //temp int value
    int t2 = 0; //temp int value
    int iSize;
    char tmp;

    f = fopen(FileName.c_str(),"rb");
    if (f == NULL) {
        ShowMessage("Error Loading File");
        return;
    }

    fread(&tmp,1,1,f);
    Value = "";
    while (tmp != 0) {
        Value = Value + AnsiString(tmp);
        fread(&tmp,1,1,f);
    }
    fread(&t1,4,1,f);
    fread(&t1,4,1,f);
    int total = t1;
    int addr=0;
    for (int i=0; i<total; i++) {
        fread(&t1,1,4,f);
        if (i == tNum) {
            addr = t1;
        }
    }
    //LoadItem1
    if (addr == 0) {
        Form1->Edit1->Text = 0;
        fclose(f);
        iTries++;
        if (iTries == 5) {
            return;
        }
        loadRLE(FileName,0);
        return;
    }
    Form1->Caption = FileName + " " + IntToStr(tNum);
    fseek(f,addr,SEEK_SET);  // goto address
    fread(&iSize,4,1,f);
    int xPos;
    int yPos;
    //xOffset
    fread(&t1,4,1,f);
    if (doublesize) {
        xPos = t1*2;
    } else {
        xPos = t1;
    }
    //yOffset
    fread(&t1,4,1,f);
    if (doublesize) {
        yPos = t1*2;
    } else {
        yPos = t1;
    }
    //width
    fread(&t1,4,1,f);
    if (doublesize) {
        Form1->Image1->Picture->Bitmap->Width = t1*2 + xPos;
    } else {
        Form1->Image1->Picture->Bitmap->Width = t1 + xPos;
    }
    //height
    fread(&t1,4,1,f);
    if (doublesize) {
        Form1->Image1->Picture->Bitmap->Height = t1*2 + yPos;
    } else {
        Form1->Image1->Picture->Bitmap->Height = t1 + yPos;
    }
    fread(&t1,4,1,f);
    fread(&t1,4,1,f);
    fread(&t1,4,1,f);
    fread(&t1,1,1,f);
    fread(&t1,1,1,f);
    fread(&t1,1,1,f);
    fread(&t1,1,1,f);
//    Form1->Image1->Canvas->Brush->Color = clBlack;
    Form1->Image1->Canvas->Brush->Color = RGB(255,0,255);
    Form1->Image1->Canvas->Rectangle(0,0,Form1->Image1->Width,Form1->Image1->Height);
    Application->ProcessMessages();
    Screen->Cursor = crHourGlass;
    try {
//        xPos = yPos = 0;
        if (fread(&t1,1,1,f) == 0) {
            ShowMessage("Error reading from file");
            fclose(f);
            return;
        }
        while (t1 != EOF) {
            switch (t1) {
                case 1:
                    if (fread(&total,4,1,f) == 0) {
                        Screen->Cursor = crDefault;
                        fclose(f);
                        return;
                    }
                    for (int j=0; j<total; j++) {
                        int tmp1=0,tmp2=0;
                        if (fread(&tmp1,1,1,f) == 0) {
                            Screen->Cursor = crDefault;
                            fclose(f);
                            return;
                        }
                        if (fread(&tmp2,1,1,f) == 0) {
                            Screen->Cursor = crDefault;
                            fclose(f);
                            return;
                        }
                        if (doublesize) {
                            Form1->Image1->Canvas->Pixels[xPos][yPos]   = cpal[tmp1][tmp2];
                            Form1->Image1->Canvas->Pixels[xPos][yPos+1] = cpal[tmp1][tmp2];
                            xPos++;
                            Form1->Image1->Canvas->Pixels[xPos][yPos]   = cpal[tmp1][tmp2];
                            Form1->Image1->Canvas->Pixels[xPos][yPos+1] = cpal[tmp1][tmp2];
                            xPos++;
                        } else {
                            Form1->Image1->Canvas->Pixels[xPos][yPos] = cpal[tmp1][tmp2];
                            xPos++;
                        }
                    }
                    break;
                case 2:
                    int amount;
                    if (fread(&amount,4,1,f) == 0) {
                        Screen->Cursor = crDefault;
                        fclose(f);
                        return;
                    }
                    if (doublesize) {
                        xPos += amount;
                    } else {
                        xPos += amount/2;
                    }
                    if (xPos > Form1->Image1->Picture->Bitmap->Width) {
                        ShowMessage("Greater than width");
                    }
                    if (yPos > Form1->Image1->Picture->Bitmap->Height) {
                        ShowMessage("Greater than height");
                    }
                    //move forward amount of t1?
                    break;
                case 3:
                    //new line??
                    if (doublesize) {
                        yPos++;
                    }
                    yPos++;
                    int tmp1;
                    tmp1=0;
                    if (fread(&t2,1,1,f) ==0) {
                        Screen->Cursor = crDefault;
                        fclose(f);
                        return;
                    }
                    if (t2 == 2) {
                        if (fread(&tmp1,4,1,f) ==0) {
                            Screen->Cursor = crDefault;
                            fclose(f);
                            return;
                        }
                        if (doublesize) {
                            xPos += tmp1;
                        } else {
                            xPos += tmp1/t2;
                        }
                    } else
                    if (t2 == 3) {
                        if (doublesize) {
//                            xPos += 2;
                        } else {
//                            xPos += 1;
                        }
                    if (doublesize) {
                        yPos++;
                    }
                        yPos++;
                    } else
                    if (t2 == 1) {
                        if (fread(&t2,4,1,f) ==0) {
                            Screen->Cursor = crDefault;
                            fclose(f);
                            return;
                        }
                        for (int q=0;q<t2;q++) {
                            if (fread(&tmp1,2,1,f) ==0) {
                                Screen->Cursor = crDefault;
                                fclose(f);
                                return;
                            }
                            if (doublesize) {
                                xPos += 2;
                            } else {
                                xPos += 1;
                            }
                        }
                    } else
                    if (t2 == 0) {// Done with image
                        if (xPos > Form1->Image1->Picture->Bitmap->Width) {
                            ShowMessage("Greater than width");
                        }
                        if (yPos > Form1->Image1->Picture->Bitmap->Height) {
                            ShowMessage("Greater than height");
                        }
                        Screen->Cursor = crDefault;
                        Form1->Image1->Picture->SaveToFile(ExtractFilePath(Application->ExeName) + "\\Temp.bmp");
                        Form1->Image1->Canvas->Brush->Color = clBlack;
//                        Form1->Image1->Canvas->Rectangle(0,0,Form1->Image1->Width,Form1->Image1->Height);
                        fclose(f);
                        return;
                    }
                    if (xPos > Form1->Image1->Picture->Bitmap->Width) {
                        ShowMessage("Greater than width");
                    }
                    if (yPos > Form1->Image1->Picture->Bitmap->Height) {
                        ShowMessage("Greater than height");
                    }
                    break;
                default:
                    ShowMessage("Error " + IntToStr(t1));
                    Screen->Cursor = crDefault;
                    Form1->Image1->Picture->SaveToFile(ExtractFilePath(Application->ExeName) + "\\Temp.bmp");
                    Form1->Image1->Canvas->Brush->Color = clBlack;
                    Form1->Image1->Canvas->Rectangle(0,0,Form1->Image1->Width,Form1->Image1->Height);
                    fclose(f);
                    return;
            }
            if (fread(&t1,1,1,f) == 0) {
                //end of file?
                t1 = -1;
            }
        }
    } catch(...) { }
    Form1->Image1->Picture->SaveToFile(ExtractFilePath(Application->ExeName) + "\\Temp.bmp");
    Form1->Image1->Canvas->Brush->Color = clBlack;
    Form1->Image1->Canvas->Rectangle(0,0,Form1->Image1->Width,Form1->Image1->Height);
    fclose(f);
    Screen->Cursor = crDefault;
    //End Loaditem1
}
//---------------------------------------------------------------------------

void __fastcall TForm1::FileListBox1Click(TObject *Sender)
{
    Edit1->Text = "0";
    if (FileListBox1->Mask == "*.rle") {
        loadRLE(FileListBox1->FileName, 0);
    } else {
        loadlst();
    }
}
//---------------------------------------------------------------------------

void __fastcall TForm1::Image1Click(TObject *Sender)
{
    int i;
    i = atoi(Edit1->Text.c_str());
    i++;
    Edit1->Text = i;
    loadRLE(FileListBox1->FileName, i);
}
//---------------------------------------------------------------------------

void __fastcall TForm1::CheckBox1Click(TObject *Sender)
{
    doublesize = CheckBox1->Checked;
}
//---------------------------------------------------------------------------

