Login

Subversion Repositories NedoOS

Rev

Rev 130 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>


#include "mhmt-types.h"
#include "mhmt-globals.h"
#include "mhmt-parsearg.h"
#include "mhmt-pack.h"
#include "mhmt-depack.h"


void show_help(void);
void dump_config(void);
ULONG do_files(void);

int main( int argc, char* argv[] )
{
        int error=0;
        ULONG parse_result;


        init_globals();


        // printf short info
        printf("mhmt - MeHruMsT - MEgalz, HRUM and hruST (c) 2009-2016 lvd^nedopc\n\n");

        // parse arguments
        parse_result = parse_args(argc, argv);

        if( parse_result&ARG_PARSER_SHOWHELP )
        {
                if( parse_result&ARG_PARSER_ERROR )
                        printf("\n");

                show_help();
        }

        if( parse_result&ARG_PARSER_ERROR )
        {
                printf("There were errors in arguments.\n");
                error++;
        }
        else if( parse_result&ARG_PARSER_GO )
        {
                if( do_files() )
                {
                        dump_config();
                        if( wrk.mode )
                        {
                                error += depack() ? 0 : 1;
                        }
                        else
                        {
                                error += pack() ? 0 : 1;
                        }
                }
                else
                {
                        error++;
                }
        }



        free_globals();

        return error;
}

void show_help(void)
{
        printf
        (
                "======== mhmt help ========\n"
                "parameters:\n"
                "-mlz, -hrm, -hst, -zx7 - use MegaLZ, hrum3.5, hrust1.x or zx7 formats (default is MegaLZ)\n"
                "-g - greedy coding (default is optimal coding), not supported yet\n"
                "-d - depacking instead of packing (default is packing)\n"
                "\n"
                "-zxh - use zx-specific header for hrum or hrust. DEFAULT is NO HEADER!\n"
                "       Not applicable for MegaLZ. If -zxh is specified, -16, NO -bend and\n"
                "       NO -mlz is forced.\n"
                "\n"
                "-8, -16 - bitstream is in bytes or words in packed file.\n"
                "          Default for MegaLZ is -8, for hrum and hrust is -16.\n"
                "\n"
                "-bend - if -16 specified, this makes words big-endian. Default is little-endian.\n"
                "\n"
                "-maxwinN - maximum lookback window. N is decimal number, which can only be\n"
                "           256,512,1024,2048,4096,8192,16384,32768. Default is format-specific\n"
                "           maximum window: MegaLZ is 4352, hrum is 4096, hrust is 65536,\n"
                "                           zx7 is 2176.\n"
                "           For given format, window can't be greater than default value\n"
                "\n"
                "-prebin <filename> - use specified file as prebinary for packing and depacking.\n"
                "\n"
                "usage:\n"
                "mhmt [parameter list] <input filename> [<output filename>]\n"
                "\n"
                "if no output filename given, filename is appended with \".mlz\", \".hrm\", \".hst\" or \".zx7\"\n"
                "in accordance with the format chosen; for depacking \".dpk\" is appended\n"
                "====== mhmt help end ======\n"
                "\n"
        );
}

void dump_config(void)
{
        printf("Configuration review:\n");
        printf("\n");

        printf("Pack format: ");
        if( wrk.packtype==PK_MLZ )
                printf("MegaLZ.\n");
        else if( wrk.packtype==PK_HRM )
                printf("Hrum3.5\n");
        else if( wrk.packtype==PK_HST )
                printf("Hrust1.x\n");
        else if( wrk.packtype==PK_ZX7 )
                printf("zx7\n");
        else
                printf("unknown.\n"); // this should be actually never displayed

        printf("Mode:        ");
        if( wrk.mode )
                printf("depacking.\n");
        else
                printf("packing.\n");

        if( !wrk.mode )
        {
                printf("Pack coding: ");
                if( wrk.greedy )
                        printf("greedy (sub-optimal but faster).\n");
                else
                        printf("optimal (slower).\n");
        }

        if( wrk.zxheader )
        {
                printf("Header for old ZX ");
                if( wrk.packtype==PK_HRM )
                        printf("hrum3.5 ");
                else if( wrk.packtype==PK_HST )
                        printf("hrust1.x ");

                printf("depackers is on.\n");
        }

        if( wrk.wordbit )
        {
                printf("Bitstream is grouped in words -\n");
                if( wrk.bigend )
                {
                        printf(" words are big-endian, %s","INCOMPATIBLE with old ZX depackers!\n");
                }
                else
                {
                        printf(" words are little-endian, ");
                        if( (wrk.packtype==PK_HRM) || (wrk.packtype==PK_HST) )
                                printf("compatible with old ZX depackers.\n");
                        else
                                printf("INCOMPATIBLE with old ZX depackers!\n");
                }
        }
        else
        {
                printf("Bitstream is grouped in bytes -\n");
                if( wrk.packtype==PK_MLZ || wrk.packtype==PK_HRM || wrk.packtype==PK_ZX7 )
                        printf(" compatible with old ZX depackers.\n");
                else
                        printf(" INCOMPATIBLE with old ZX depackers!\n");
        }

        printf("Maximum lookback window size is %d bytes.\n\n",wrk.maxwin);


        // files
        printf("Input file \"%s\" (%d bytes) successfully loaded.\n", wrk.fname_in, wrk.inlen);
        printf("Output file \"%s\" created.\n", wrk.fname_out );

        // prebin file
        if( wrk.prebin )
        {
                printf("Prebinary file \"%s\" (%d bytes) successfully loaded.\n", wrk.fname_prebin, wrk.prelen);
        }
        else
        {
                printf("No prebinary file specified.\n");
        }
//      ...more info...?
}

// create output filename, open files, load input file in memory
// returns 1 if no errors, otherwise zero
ULONG do_files(void)
{
        char * pack_ext;
        char * depk_ext;
        LONG ext_pos;

        struct stat stfile;

        UBYTE * tmp;
        ULONG len;

        // if there is no output filename, create it
        if( !wrk.fname_out )
        {
                depk_ext = ".dpk";

                if( wrk.packtype==PK_MLZ )
                        pack_ext = ".mlz";
                else if( wrk.packtype==PK_HRM )
                        pack_ext = ".hrm";
                else if( wrk.packtype==PK_HST )
                        pack_ext = ".hst";
                else if( wrk.packtype==PK_ZX7 )
                        pack_ext = ".zx7";
                else
                        pack_ext = ".pak"; // all have the same size, as well as depk_ext - 4 bytes!


                wrk.fname_out = (char *)malloc( 5 + strlen(wrk.fname_in) );
                if( !wrk.fname_out )
                {
                        printf("Can't allocate memory for output filename!\n");
                        return 0;
                }

                strcpy(wrk.fname_out, wrk.fname_in);

                if( !wrk.mode ) // packing
                {
                        strcat(wrk.fname_out, pack_ext);
                }
                else // depacking
                {
                        ext_pos = strlen( wrk.fname_out ) - 4;

                        if( (ext_pos>=0) && (!strcmp(&wrk.fname_out[ext_pos], pack_ext)) )
                                strcpy( &wrk.fname_out[ext_pos], depk_ext );
                        else
                                strcat( wrk.fname_out, depk_ext );
                }
        }


        //open files
        wrk.file_in=fopen(wrk.fname_in,"rb");
        if(!wrk.file_in)
        {
                printf("Cannot open input file \"%s\"!\n",wrk.fname_in);
                return 0;
        }

        wrk.file_out=fopen(wrk.fname_out,"wb");
        if(!wrk.file_out)
        {
                printf("Cannot create output file \"%s\"!\n",wrk.fname_out);
                return 0;
        }

        if( wrk.prebin )
        {
                wrk.file_prebin = fopen(wrk.fname_prebin,"rb");
                if(!wrk.file_prebin)
                {
                        printf("Cannot open prebinary file \"%s\"!\n",wrk.fname_prebin);
                        return 0;
                }
        }



        // get lengths of files
        if( fseek(wrk.file_in,0,SEEK_END) )
        {
                printf("Cannot fseek() input file \"%s\"!\n",wrk.fname_in);
                return 0;
        }
        wrk.inlen=(ULONG)ftell(wrk.file_in);
        if( wrk.inlen==(ULONG)(-1L)  )
        {
                printf("Cannot ftell() length of input file \"%s\"!\n",wrk.fname_in);
                wrk.inlen=0;
                return 0;
        }
        else if( wrk.inlen<16 && !wrk.mode ) // do not pack files less than 16 bytes
        {
                printf("Input file \"%s\" is smaller than 16 bytes - I won't process it!\n",wrk.fname_in);
                return 0;
        }
        if( fseek(wrk.file_in,0,SEEK_SET) )
        {
                printf("Cannot fseek() input file \"%s\"!\n",wrk.fname_in);
                return 0;
        }

        if( wrk.prebin )
        {
                if( fstat( fileno(wrk.file_prebin), &stfile ) )
//              if( stat( wrk.fname_prebin, &stfile ) )
                {
                        printf("Cannot fstat() prebin file \"%s\"\n",wrk.fname_prebin);
                        return 0;
                }

                wrk.prelen = (ULONG)stfile.st_size;
        }



        // load files in mem
        //
        // first allocate place for both prebin and input file
        len = wrk.inlen + wrk.prelen; // wrk.prelen is 0 if wrk.prebin==0
        tmp = (UBYTE *)malloc( len );
        //
        // check alloc is OK
        if( !tmp )
        {
                if( wrk.prebin )
                {
                        printf("Cannot allocate %d bytes of memory for loading both input file \"%s\" and prebin file \"%s\"!\n", len, wrk.fname_in, wrk.fname_prebin );
                }
                else
                {
                        printf("Cannot allocate %d bytes of memory for loading input file \"%s\"!\n", wrk.inlen, wrk.fname_in );
                }
                return 0;
        }
        //
        // assign to wrk.indata
        wrk.indata_raw = tmp;
        wrk.indata     = tmp + (wrk.prebin ? wrk.prelen : 0); // so we access prebin using negative displacements into wrk.indata array
        //
        // load input file and prebin file
        if( wrk.inlen!=fread(wrk.indata,1,wrk.inlen,wrk.file_in) )
        {
                printf("Cannot successfully load input file \"%s\" in memory!\n",wrk.fname_in);
                return 0;
        }
        if( wrk.prebin )
        {
                if( wrk.prelen!=fread(tmp,1,wrk.prelen,wrk.file_prebin) )
                {
                        printf("Cannot successfully load prebin file \"%s\" in memory!\n",wrk.fname_prebin);
                        return 0;
                }
        }



        return 1;// no errors
}