All of the Blast Corps textures are compressed inside of the ROM using either gzip or one of 6 custom compression schemes.

The texture table stores information about each of the textures used in the display lists. The table is located between offsets 0x4CE0-0xCCE0 in the ROM. Each entry is 8 bytes and stores the texture offset (relative to the table base), the compressed length, and the texture type.

Texture type 0 is uncompressed and just memcpy's the data from ROM.

Type 1 textures use 16-bit data with lookback to compress RGBA16.

15 | 14-10 | 9 - 6 | 5 - 1 | 0 |
---|---|---|---|---|

0 | Red | Green | Blue | A |

15 | 14 - 5 | 4 - 0 |
---|---|---|

1 | Offset (bytes) | Length (16) |

if MSB is 0: DataOut = ((DataIn & 0xFFC0) << 1) | (DataIn & 0x3F); this implies that the 7th bit (lsb of green) is always 0 if MSB is 1: copy 'length' 16-bit values from -offset length16 = DataIn & 0x1F; offset8 = (DataIn & 0x7FFF) >> 5;

Type 2 textures use 32-bit data with lookback to compress RGBA32.

15 | 14-11 | 10- 7 | 6 - 3 | 2 - 0 |
---|---|---|---|---|

0 | Red | Green | Blue | Alpha |

15 | 14 - 5 | 4 - 0 |
---|---|---|

1 | Offset (16) | Length (32) |

if MSB is 0: DataOut = ((DataIn & 0x7800) << 17) | ((DataIn & 0x780) << 13) | ((DataIn & 0x78) << 9) | ((DataIn & 0x7) << 5); Implies that four LSBs of R,G,B are 0, five LSBs of A are 0 if MSB is 1: copy 'length' 32-bit values from -offset length32 = DataIn & 0x1F; offset16 = (DataIn & 0x7FE0) >> 4;

Type 3 textures use 16-bit data with lookback to compress IA16.

15 | 14 - 8 | 7 | 6 - 0 |
---|---|---|---|

0 | Alpha | X | Intensity |

15 | 14 - 5 | 4 - 0 |
---|---|---|

1 | Offset (bytes) | Length (16) |

if MSB is 0: ByteOut0 = ((DataIn >> 8) << 1); ByteOut1 = ((DataIn) & 0xFF) << 1); Implies that the LSBs I and A are 0 if MSB is 1: copy 'length' 16-bit values from -offset length16 = DataIn & 0x1F; offset8 = (DataIn & 0x7FFF) >> 5;

Type 4 textures use 16-bit data to reference a 16-bit lookup table and 32-bit lookback - used for explosions? RGBA32?

15 | 14 - 9 | 8 | 7 - 1 | 0 |
---|---|---|---|---|

0 | Offset1 | LB1 | Offset2 | LB2 |

15 | 14 - 5 | 4 - 0 |
---|---|---|

1 | Offset (16) | Length (32) |

LUT passed through T4, assigned from a0->0xC in 802A57DC(), set from FP if MSB is 0: U16Out1 = (LUT[((DataIn >> 8) & 0xFE)] << 1) | ((DataIn >> 8) & 0x1); U16Out2 = (LUT[(DataIn & 0xFE)] << 1) | (DataIn& 0x1); if MSB is 1: copy 'length' 32-bit values from -offset length32 = DataIn & 0x1F; offset16 = (DataIn & 0x7FE0) >> 4;

Type 5 textures use 16-bit data with a 32-bit lookup table and lookback - maybe used for some text?

15 | 14 - 4 | 3 - 0 |
---|---|---|

0 | Offset | LSBs |

15 | 14 - 5 | 4 - 0 |
---|---|---|

1 | Offset (16) | Length (32) |

Similar to Type 4, T4 passed in as LUT if MSB is 0: Offset = (DataIn >> 4) << 1; Tmp16 = (LUT[Offset] << 1) | ((DataIn >> 8) & 0x1); U32Out = ((Tmp16 & 0x7C00) << 17) | ((Tmp16 & 0x3E0) << 14) | ((Tmp16 & 0x1F) << 11) | ((DataIn & 0xF) << 4); if MSB is 1: copy 'length' 32-bit values from -offset length32 = DataIn & 0x1F; offset16 = (DataIn & 0x7FE0) >> 4;

Type 6 textures are primarily used to compress IA8 fonts using 16-bit data with lookback.

15 | 14 | 13-11 | 10-8 | 7-6 | 5-3 | 2-0 |
---|---|---|---|---|---|---|

0 | X | I1 | A1 | X | I2 | A2 |

15 | 14 - 5 | 4 - 0 |
---|---|---|

1 | Offset (bytes) | Length (16) |

if MSB is 0: ByteOut0 = (((DataIn >> 8) & 0x38) << 2) | (((DataIn >> 8) & 0x7) << 1); ByteOut1 = ((DataIn & 0x38) << 2) | ((DataIn & 0x7) << 1); Implies that the LSBs I and A are 0 if MSB is 1: copy 'length' 16-bit values from -offset length = DataIn & 0x1F; offset = (DataIn & 0x7FFF) >> 5;