September 16, 2025Sep 16 Localization 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
December 11, 2025Dec 11 Supporter 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; } Edited December 11, 2025Dec 11 by Rabatini
December 25, 2025Dec 25 Author Localization On 12/11/2025 at 8:13 PM, Rabatini said: 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; } Thank you, i managed to rewrite it in Python and i got .PIC and .TEX out into readable PNGs. Other files use some other form of encryption and compression and i did not manage to decompile them, they could also contain pallete for the images/whole game. So all-in-all that's a win... other things are not really important as this is old DOS game and it does not use 3D model formats for the models, but rather use buffers and direct drawing techniques to create meshes.. thank you again for the c++ one!
December 26, 2025Dec 26 Supporter 42 minutes ago, anderlli0053 said: Thank you, i managed to rewrite it in Python and i got .PIC and .TEX out into readable PNGs. Other files use some other form of encryption and compression and i did not manage to decompile them, they could also contain pallete for the images/whole game. So all-in-all that's a win... other things are not really important as this is old DOS game and it does not use 3D model formats for the models, but rather use buffers and direct drawing techniques to create meshes.. thank you again for the c++ one! Nice!! do you have these files? we can dig out.
December 26, 2025Dec 26 Author Localization ... only now i see that this is the thread for Cool Spot... i was talking about the similar game "Ignition", which i managed to partially decompile... From the Cool Spot i got just mangled images... nothing else - i just switched game names by accident, i meant for the Ignition one, not this one, i just re-read this thread and just saw the mistake i made.. 🤦♂️ coolspot.zip
Create an account or sign in to comment