Пример #1
0
void crunch_backwards(struct membuf *inbuf,
                      struct membuf *outbuf,
                      struct crunch_options *options, /* IN */
                      struct crunch_info *info) /* OUT */
{
    static match_ctx ctx;
    encode_match_data emd;
    search_nodep snp;
    int outlen;
    int safety;
    int copy_used;

    if(options == NULL)
    {
        options = default_options;
    }

    outlen = membuf_memlen(outbuf);
    emd->out = NULL;
    optimal_init(emd);

    LOG(LOG_NORMAL,
        ("\nPhase 1: Instrumenting file"
         "\n-----------------------------\n"));
    LOG(LOG_NORMAL, (" Length of indata: %d bytes.\n", membuf_memlen(inbuf)));

    match_ctx_init(ctx, inbuf, options->max_len, options->max_offset,
                   options->use_imprecise_rle);

    LOG(LOG_NORMAL, (" Instrumenting file, done.\n"));

    emd->out = NULL;
    optimal_init(emd);

    LOG(LOG_NORMAL,
        ("\nPhase 2: Calculating encoding"
         "\n-----------------------------\n"));
    snp = do_compress(ctx, emd, options->exported_encoding,
                      options->max_passes, options->use_literal_sequences);
    LOG(LOG_NORMAL, (" Calculating encoding, done.\n"));

    LOG(LOG_NORMAL,
        ("\nPhase 3: Generating output file"
         "\n------------------------------\n"));
    LOG(LOG_NORMAL, (" Encoding: %s\n", optimal_encoding_export(emd)));
    safety = do_output(ctx, snp, emd, optimal_encode, outbuf, &copy_used);
    LOG(LOG_NORMAL, (" Length of crunched data: %d bytes.\n",
                     membuf_memlen(outbuf) - outlen));

    optimal_free(emd);
    search_node_free(snp);
    match_ctx_free(ctx);

    if(info != NULL)
    {
        info->literal_sequences_used = copy_used;
        info->needed_safety_offset = safety;
    }
}
Пример #2
0
void decrunch_backwards(int level,
                        struct membuf *inbuf,
                        struct membuf *outbuf)
{
    int outpos;
    reverse_buffer(membuf_get(inbuf), membuf_memlen(inbuf));
    outpos = membuf_memlen(outbuf);

    decrunch(level, inbuf, outbuf);

    reverse_buffer(membuf_get(inbuf), membuf_memlen(inbuf));
    reverse_buffer((char*)membuf_get(outbuf) + outpos,
                   membuf_memlen(outbuf) - outpos);
}
Пример #3
0
void crunch(struct membuf *inbuf,
            struct membuf *outbuf,
            struct crunch_options *options, /* IN */
            struct crunch_info *info) /* OUT */
{
    int outpos;
    reverse_buffer(membuf_get(inbuf), membuf_memlen(inbuf));
    outpos = membuf_memlen(outbuf);

    crunch_backwards(inbuf, outbuf, options, info);

    reverse_buffer(membuf_get(inbuf), membuf_memlen(inbuf));
    reverse_buffer((char*)membuf_get(outbuf) + outpos,
                   membuf_memlen(outbuf) - outpos);
}
Пример #4
0
struct expr *new_expr_incword(const char *name,
                              struct expr *skip)
{
    i32 word;
    i32 offset;
    long length;
    struct membuf *in;
    struct expr *expr;
    unsigned char *p;

    offset = resolve_expr(skip);
    in = get_named_buffer(s->named_buffer, name);
    length = membuf_memlen(in);
    if(offset < 0)
    {
        offset += length;
    }
    if(offset < 0 || offset > length - 2)
    {
        LOG(LOG_ERROR,
            ("Can't read word from offset %d in file \"%s\".\n",
             offset, name));
        exit(-1);
    }
    p = membuf_get(in);
    p += offset;
    word = *p++;
    word |= *p++ << 8;

    expr = new_expr_number(word);
    return expr;
}
Пример #5
0
unsigned int write_track_block(TZX_FILE *pTZXfile, struct membuf tracks[], int first_track, int last_track)
{
  char blockbuf[MAX_BLOCK_SIZE];
  int track;
  int track_count = last_track - first_track + 1;
  int block_ptr = (track_count+1) * 2; // space for pointer table at start plus 0x0000 terminator
  int block_tbl_ptr = 0;
  
  printf("writing tracks %d-%d\n", first_track, last_track);

  memset(blockbuf, 0, MAX_BLOCK_SIZE);
  
  for (track = first_track; track <= last_track; track++)
  {
    int track_len = membuf_memlen(&tracks[track]);
    
    if (track_len > 0) // skip null tracks
    {
      memcpy(blockbuf+block_ptr, membuf_get(&tracks[track]), track_len);
      blockbuf[block_tbl_ptr++] = block_ptr & 0xff;
      blockbuf[block_tbl_ptr++] = block_ptr >> 8;

      membuf_free(&tracks[track]);
      
      block_ptr += track_len;
    }
  }  
Пример #6
0
struct atom *new_incbin(const char *name,
                        struct expr *skip, struct expr *len)
{
    struct atom *atom;
    long length;
    i32 len32;
    i32 skip32;
    struct membuf *in;

    /* find out how long the file is */
    in = get_named_buffer(s->named_buffer, name);
    length = membuf_memlen(in);

    skip32 = 0;
    if(skip != NULL)
    {
        skip32 = resolve_expr(skip);
    }
    if(skip32 < 0)
    {
        skip32 += length;
    }
    if(skip32 < 0 || skip32 > length)
    {
        LOG(LOG_ERROR,
            ("Can't read from offset %d in file \"%s\".\n", skip32, name));
        exit(-1);
    }
    length -= skip32;

    len32 = 0;
    if(len != NULL)
    {
        len32 = resolve_expr(len);
    }
    if(len32 < 0)
    {
        len32 += length;
    }
    if(len32 < 0 || len32 > length)
    {
        LOG(LOG_ERROR,
            ("Can't read %d bytes from offset %d from file \"%s\".\n",
             len32, skip32, name));
        exit(-1);
    }

    atom = chunkpool_malloc(s->atom_pool);
    atom->type = ATOM_TYPE_BUFFER;
    atom->u.buffer.name = name;
    atom->u.buffer.length = len32;
    atom->u.buffer.skip = skip32;

    if(len != NULL)
    {
        pc_add(len32);
    }
    return atom;
}
Пример #7
0
struct expr *new_expr_inclen(const char *name)
{
    long length;
    struct membuf *in;
    struct expr *expr;

    in = get_named_buffer(s->named_buffer, name);
    length = membuf_memlen(in);

    expr = new_expr_number((i32)length);
    return expr;
}
Пример #8
0
void write_file(const char *name, struct membuf *buf)
{
    FILE *out;
    out = fopen(name, "wb");
    if(out == NULL)
    {
        LOG(LOG_ERROR, ("Can't open file \"%s\" for output.\n", name));
        exit(-1);
    }
    fwrite(membuf_get(buf), 1, membuf_memlen(buf), out);
    fclose(out);
}
Пример #9
0
char *
dec_ctx_init(struct dec_ctx *ctx, struct membuf *inbuf, struct membuf *outbuf)
{
    char *encoding;
    ctx->bits_read = 0;

    ctx->inbuf = membuf_get(inbuf);
    ctx->inend = membuf_memlen(inbuf);
    ctx->inpos = 0;

    ctx->outbuf = outbuf;

    /* init bitbuf */
    ctx->bitbuf = get_byte(ctx);

    /* init tables */
    table_init(ctx, ctx->t);
    encoding = table_dump(ctx->t);
    return encoding;
}
Пример #10
0
static
void level(const char *appl, int argc, char *argv[])
{
    char flags_arr[32];
    int forward_mode = 0;
    int literal_sequences_used = 0;
    int max_safety = 0;
    int c;
    int infilec;
    char **infilev;

    struct crunch_options options[1] = { CRUNCH_OPTIONS_DEFAULT };
    struct common_flags flags[1] = {{NULL, DEFAULT_OUTFILE}};

    struct membuf in[1];
    struct membuf out[1];

    flags->options = options;

    LOG(LOG_DUMP, ("flagind %d\n", flagind));
    sprintf(flags_arr, "f%s", CRUNCH_FLAGS);
    while ((c = getflag(argc, argv, flags_arr)) != -1)
    {
        LOG(LOG_DUMP, (" flagind %d flagopt '%c'\n", flagind, c));
        switch (c)
        {
        case 'f':
            forward_mode = 1;
            break;
        default:
            handle_crunch_flags(c, flagarg, print_level_usage, appl, flags);
        }
    }

    membuf_init(in);
    membuf_init(out);

    infilev = argv + flagind;
    infilec = argc - flagind;

    if (infilec == 0)
    {
        LOG(LOG_ERROR, ("Error: no input files to process.\n"));
        print_level_usage(appl, LOG_NORMAL, DEFAULT_OUTFILE);
        exit(1);
    }

    /* append the files instead of merging them */
    for(c = 0; c < infilec; ++c)
    {
        struct crunch_info info[1];
        int in_load;
        int in_len;
        int out_pos;
        out_pos = membuf_memlen(out);

        in_load = do_load(infilev[c], in);
        in_len = membuf_memlen(in);

        if(forward_mode)
        {
            /* append the starting address of decrunching */
            membuf_append_char(out, in_load >> 8);
            membuf_append_char(out, in_load & 255);

            crunch(in, out, options, info);
        }
        else
        {
            crunch_backwards(in, out, options, info);

            /* append the starting address of decrunching */
            membuf_append_char(out, (in_load + in_len) & 255);
            membuf_append_char(out, (in_load + in_len) >> 8);

            /* reverse the just appended segment of the out buffer */
            reverse_buffer((char*)membuf_get(out) + out_pos,
                           membuf_memlen(out) - out_pos);
        }

        if(info->literal_sequences_used)
        {
            literal_sequences_used = 1;
        }
        if(info->needed_safety_offset > max_safety)
        {
            max_safety = info->needed_safety_offset;
        }
    }
Пример #11
0
        {
            literal_sequences_used = 1;
        }
        if(info->needed_safety_offset > max_safety)
        {
            max_safety = info->needed_safety_offset;
        }
    }

    LOG(LOG_NORMAL, (" Literal sequences are %sused and",
                     literal_sequences_used ? "" : "not "));
    LOG(LOG_NORMAL, (" the largest safety offset is %d.\n",
                     max_safety));

    LOG(LOG_BRIEF, (" Writing %d bytes to \"%s\".\n",
                    membuf_memlen(out), flags->outfile));
    write_file(flags->outfile, out);

    membuf_free(out);
    membuf_free(in);
}

static
void mem(const char *appl, int argc, char *argv[])
{
    char flags_arr[32];
    int forward_mode = 0;
    int load_addr = -1;
    int prepend_load_addr = 1;
    int c;
    int infilec;
Пример #12
0
void match_ctx_init(match_ctx ctx,      /* IN/OUT */
                    struct membuf *inbuf,   /* IN */
                    int max_offset)
{
    struct match_node *np;
    struct progress prog[1];

    int buf_len = membuf_memlen(inbuf);
    const unsigned char *buf = membuf_get(inbuf);

    int c, i;
    int val;

    ctx->info = calloc(buf_len + 1, sizeof(*ctx->info));
    ctx->rle = calloc(buf_len + 1, sizeof(*ctx->rle));
    ctx->rle_r = calloc(buf_len + 1, sizeof(*ctx->rle_r));

    chunkpool_init(ctx->m_pool, sizeof(match));

    ctx->max_offset = max_offset;

    ctx->buf = buf;
    ctx->len = buf_len;

    val = buf[0];
    for (i = 1; i < buf_len; ++i)
    {
        if (buf[i] == val)
        {
            int len = ctx->rle[i - 1] + 1;
            if(len > 65535)
            {
                len = 0;
            }
            ctx->rle[i] = len;
        } else
        {
            ctx->rle[i] = 0;
        }
        val = buf[i];
    }

    for (i = buf_len - 2; i >= 0; --i)
    {
        if (ctx->rle[i] < ctx->rle[i + 1])
        {
            ctx->rle_r[i] = ctx->rle_r[i + 1] + 1;
        } else
        {
            ctx->rle_r[i] = 0;
        }
    }

    /* add extra nodes to rle sequences */
    for(c = 0; c < 256; ++c)
    {
        static char rle_map[65536];
        struct match_node *prev_np;
        unsigned short int rle_len;

        /* for each possible rle char */
        memset(rle_map, 0, sizeof(rle_map));
        prev_np = NULL;
        for (i = 0; i < buf_len; ++i)
        {
            /* must be the correct char */
            if(buf[i] != c)
            {
                continue;
            }

            rle_len = ctx->rle[i];
            if(!rle_map[rle_len] && ctx->rle_r[i] > 16)
            {
                /* no previous lengths and not our primary length*/
                continue;
            }

            np = chunkpool_malloc(ctx->m_pool);
            np->index = i;
            np->next = NULL;
            rle_map[rle_len] = 1;

            LOG(LOG_DUMP, ("0) c = %d, added np idx %d -> %d\n", c, i, 0));

            /* if we have a previous entry, let's chain it together */
            if(prev_np != NULL)
            {
                LOG(LOG_DUMP, ("1) c = %d, pointed np idx %d -> %d\n",
                                c, prev_np->index, i));
                prev_np->next = np;
            }

            ctx->info[i]->single = np;
            prev_np = np;
        }

        memset(rle_map, 0, sizeof(rle_map));
        prev_np = NULL;
        for (i = buf_len - 1; i >= 0; --i)
        {
            /* must be the correct char */
            if(buf[i] != c)
            {
                continue;
            }

            rle_len = ctx->rle_r[i];
            np = ctx->info[i]->single;
            if(np == NULL)
            {
                if(rle_map[rle_len] && prev_np != NULL && rle_len > 0)
                {
                    np = chunkpool_malloc(ctx->m_pool);
                    np->index = i;
                    np->next = prev_np;
                    ctx->info[i]->single = np;

                    LOG(LOG_DEBUG, ("2) c = %d, added np idx %d -> %d\n",
                                    c, i, prev_np->index));
                }
            }
            else
            {
                prev_np = np;
            }

            if(ctx->rle_r[i] > 0)
            {
                continue;
            }
            rle_len = ctx->rle[i] + 1;
            rle_map[rle_len] = 1;
        }
    }

    progress_init(prog, "building.directed.acyclic.graph.", buf_len - 1, 0);

    for (i = buf_len - 1; i >= 0; --i)
    {
        const_matchp matches;

        /* let's populate the cache */
        matches = matches_calc(ctx, i);

        /* add to cache */
        ctx->info[i]->cache = matches;

        progress_bump(prog, i);
    }

    LOG(LOG_NORMAL, ("\n"));

    progress_free(prog);
}
Пример #13
0
int assemble(struct membuf *source, struct membuf *dest)
{
    struct vec guesses_history[1];
    struct map guesses_storage[1];
    int dest_pos;
    int result;

    dump_sym_table(LOG_DEBUG, s->initial_symbols);

    vec_init(guesses_history, sizeof(struct map));
    s->guesses = NULL;
    dest_pos = membuf_memlen(dest);
    for(;;)
    {

        map_put_all(s->sym_table, s->initial_symbols);
        named_buffer_copy(s->named_buffer, s->initial_named_buffer);
        map_init(guesses_storage);

        if(s->guesses != NULL)
        {
            /* copy updated guesses from latest pass */
            map_put_all(guesses_storage, s->guesses);
        }
        s->guesses = guesses_storage;

        result = assembleSinglePass(source, dest);
        if(result != 0)
        {
            /* the assemble pass failed */
            break;
        }

        /* check if any guessed symbols was wrong and update them
         * to their actual value */
        if(wasFinalPass())
        {
            /* The assemble pass succeeded without any wrong guesses,
             * we're done */
            break;
        }
        if(loopDetect(guesses_history))
        {
            /* More passes would only get us into a loop */
            LOG(LOG_VERBOSE, ("Aborting due to loop.\n"));
            result = -1;
            break;
        }

        LOG(LOG_VERBOSE, ("Trying another pass.\n"));

        /* allocate storage for the guesses in the history vector */
        s->guesses = vec_push(guesses_history, s->guesses);

        parse_reset();
        membuf_truncate(dest, dest_pos);
    }
    map_free(guesses_storage);
    vec_free(guesses_history, (cb_free*)map_free);
    s->guesses = NULL;
    return result;
}
Пример #14
0
void dec_ctx_decrunch(struct dec_ctx ctx[1])
{
    int bits;
    int val;
    int i;
    int len;
    int offset;
    int src = 0;

    for(;;)
    {
        int literal = 0;
        bits = ctx->bits_read;
        if(get_bits(ctx, 1))
        {
            /* literal */
            len = 1;

            LOG(LOG_DEBUG, ("[%d] literal\n", membuf_memlen(ctx->outbuf)));

            literal = 1;
            goto literal;
        }

        val = get_gamma_code(ctx);
        if(val == 16)
        {
            /* done */
            break;
        }
        if(val == 17)
        {
            len = get_bits(ctx, 16);
            literal = 1;

            LOG(LOG_DEBUG, ("[%d] literal copy len %d\n",
                            membuf_memlen(ctx->outbuf), len));

            goto literal;
        }

        len = get_cooked_code_phase2(ctx, val);

        i = (len > 3 ? 3 : len) - 1;

        val = ctx->t->table_off[i] + get_bits(ctx, ctx->t->table_bit[i]);
        offset = get_cooked_code_phase2(ctx, val);

        LOG(LOG_DEBUG, ("[%d] sequence offset = %d, len = %d\n",
                        membuf_memlen(ctx->outbuf), offset, len));

        src = membuf_memlen(ctx->outbuf) - offset;

    literal:
        do {
            if(literal)
            {
                val = get_byte(ctx);
            }
            else
            {
                val = get(ctx->outbuf)[src++];
            }
            membuf_append_char(ctx->outbuf, val);
        } while (--len > 0);

        LOG(LOG_DEBUG, ("bits read for this iteration %d.\n",
                        ctx->bits_read - bits));
    }
}