reading Captain Comic II tileset data

Discuss game modding
Post Reply
amyrama
Less than a nibble
Posts: 3
Joined: January 2nd, 2024, 2:49 am
Location: Brisbane, Australia

reading Captain Comic II tileset data

Post by amyrama »

Hi,

I'm a long-time fan of old DOS games and a first-time reverse engineer :)

I'm currently trying to write a program to read tile sets from Captain Comic II: Fractured Reality (one of my all-time favorites) and output the tiles to an image buffer.

I used the information on the modding wiki and I have it almost working, in that the first tile in the set comes out fine, but subsequent tiles are corrupted. I think the problem is in the function I'm using to decode the RLE data from the file and write it to a buffer:

(I'm compiling it using Borland Turbo C++ v3.0 for DOSBox)

Code: Select all

// read in a single tile's worth of data from file and decode to tile buffer
int fr_get_tile(FILE **fr, unsigned char *tile_buffer)
{
    int i, run_count, total, data;
    if (*fr == NULL) return -1;
    memset(tile_buffer, 0, TILE_BYTE_SIZE);
    i = total = 0;
    while (i < TILE_BYTE_SIZE) {
        if ((run_count = getc(*fr)) == EOF) return -1;
        if (run_count == 0) {
            return 0;
        } else if (run_count < 128) {
            // copy literal bytes
            for (total += run_count; run_count--; i++) {
                if ((data = getc(*fr)) == EOF) return -1;
                *tile_buffer++ = data;
            }
        } else  {
            // copy a run
            run_count = 256 - run_count;
            if ((data = getc(*fr)) == EOF) return -1;
            for (total += run_count; run_count--; i++) {
                *tile_buffer++ = data;
            }
        }
    }
    return i;
}
Any help would be appreciated :)
Thanks
amyrama
Less than a nibble
Posts: 3
Joined: January 2nd, 2024, 2:49 am
Location: Brisbane, Australia

Re: reading Captain Comic II tileset data

Post by amyrama »

I think I figured it out. I had assumed that the runs would start and finish on tile boundaries, and I was trying to be clever and decode 128 bytes worth of data at a time. Turns out I needed to make a buffer big enough to hold the entire tileset and decode it all at once. Then it worked just fine :)

My revised decoding function is like this:

Code: Select all

// read in data from file and RLE decode to tile buffer
int fr_decode(FILE *fr, uint8_t *buffer, int buffer_size)
{
    int i, run_count, total, data;
    i = total = 0;
    memset(buffer, 0, buffer_size);
    while (total < buffer_size && (run_count = fgetc(fr)) != EOF) {
        if (run_count == 0) {
            return total;
        } else if (run_count < 128) {
            // copy literal bytes
            if ((fread(buffer, run_count, 1, fr)) != 1) return total;
            buffer += run_count;
            total += run_count;
        } else {
            // copy a run
            run_count = 256 - run_count;
            if ((data = fgetc(fr)) == EOF) return total;
            for (total += run_count; run_count--;) {
                *buffer++ = data;
            }
        }
    }
    return total;
}
Now, on to decoding the map format!
Malvineous
8-bit mega nerd
Posts: 293
Joined: March 17th, 2007, 6:40 pm
Location: Brisbane, Australia
Contact:

Re: reading Captain Comic II tileset data

Post by Malvineous »

The code looks correct to me. libgamegraphics has some units tests (well one) for decoding this RLE data so you could try to put those bytes into your algorithm and see whether you get the same output (you want the first one, for "unrle", the others are testing RLE encoding of data rather than decoding).
amyrama
Less than a nibble
Posts: 3
Joined: January 2nd, 2024, 2:49 am
Location: Brisbane, Australia

Re: reading Captain Comic II tileset data

Post by amyrama »

OK, Thanks! :) :D
Post Reply