Jump to content

Recommended Posts

Posted

Hello!

 

I'm trying to extract custom file formats from DOS videogame Cool Spot. Formats are compressed by some modification of RLE compression i think + something else. 

I'm interested in everything except those 2 DOS binaries/executables(.exe) provided in the archive, since the all of the data is in other files.

Cool-Spot_DOS_EN.7z

  • 2 months later...
  • Engineers
Posted (edited)
On 9/16/2025 at 1:18 PM, anderlli0053 said:

Hello!

 

I'm trying to extract custom file formats from DOS videogame Cool Spot. Formats are compressed by some modification of RLE compression i think + something else. 

I'm interested in everything except those 2 DOS binaries/executables(.exe) provided in the archive, since the all of the data is in other files.

Cool-Spot_DOS_EN.7z 573.63 kB · 4 downloads

Here the Rle logic.
Vertical:
 

std::vector<uint8_t> decompress_type1(const std::vector<uint8_t>& data, int width, int height) {
    if (width <= 0 || height <= 0) return {};

    // Aloca buffer de saída (W * H)
    // Usamos long long para evitar overflow no calculo do tamanho se as dimensoes forem grandes
    size_t total_pixels = (size_t)width * (size_t)height;
    std::vector<uint8_t> output(total_pixels, 0);

    // Coordenadas para escrita vertical (x, y)
    int x = 0;
    int y = 0;

    size_t data_pos = 0;
    size_t data_len = data.size();

    // Helper para escrever pixel na geometria correta (Vertical: Top->Down, depois Left->Right)
    auto write_pixel = [&](uint8_t val) {
        if (x < width && y < height) {
            output[y * width + x] = val;
        }
        y++;
        if (y >= height) {
            y = 0;
            x++;
        }
        };

    while (data_pos < data_len) {
        // Se já preencheu a largura total, para
        if (x >= width) break;

        uint8_t cmd = data[data_pos++];

        if (cmd == 0) break; // Marcador de fim

        // Verifica bit 7 (0x80): Raw Copy (Literais)
        if (cmd & 0x80) {
            int count = (cmd & 0x7F) + 1;
            for (int i = 0; i < count; ++i) {
                if (data_pos < data_len) {
                    write_pixel(data[data_pos++]);
                }
            }
        }
        // RLE (Repetição)
        else {
            int count = 0;
            // Verifica bit 6 (0x40): Contagem estendida (2 bytes)
            if (cmd & 0x40) {
                if (data_pos < data_len) {
                    // Remove flags e combina com próximo byte (Little Endian)
                    count = ((cmd & 0x3F) << 8) | data[data_pos++];
                }
            }
            else {
                count = cmd;
            }

            count += 1;

            if (data_pos < data_len) {
                uint8_t val = data[data_pos++];
                for (int i = 0; i < count; ++i) {
                    write_pixel(val);
                }
            }
        }
    }

    return output;
}


horizontal

 


std::vector<uint8_t> decompress_type3(const std::vector<uint8_t>& data, int width, int height) {
    if (width <= 0 || height <= 0) return {};

    size_t total_pixels = (size_t)width * (size_t)height;
    std::vector<uint8_t> output(total_pixels, 0);

    size_t pos = 0;
    size_t data_pos = 0;
    size_t data_len = data.size();

    while (data_pos < data_len && pos < total_pixels) {
        uint8_t cmd = data[data_pos++];

        if (cmd == 0) {
            break;  // fim dos dados
        }

        if (cmd & 0x80) {
            // Literais
            size_t count = (cmd & 0x7F) + 1;
            for (size_t i = 0; i < count && data_pos < data_len && pos < total_pixels; ++i) {
                output[pos++] = data[data_pos++];
            }
        }
        else {
            // Repetido
            size_t count = 0;

            if (cmd & 0x40) {
                // Contagem estendida
                if (data_pos >= data_len) break;
                count = ((cmd & 0x3F) << 8) | data[data_pos++];
            }
            else {
                count = cmd;
            }
            count += 1;

            if (data_pos >= data_len) break;
            uint8_t val = data[data_pos++];

            for (size_t i = 0; i < count && pos < total_pixels; ++i) {
                output[pos++] = val;
            }
        }
    }

    return output;
}




image.png.b164eb4e72e0b81ae06bbc02052a9fe4.png

Edited by Rabatini

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...