diff --git a/scripts/loaders/snes/battle_bgs.gd b/scripts/loaders/snes/battle_bgs.gd new file mode 100644 index 0000000..aab68b4 --- /dev/null +++ b/scripts/loaders/snes/battle_bgs.gd @@ -0,0 +1,67 @@ +extends Node +const LENGTH := 0x500 / 2 # Expanded length 0x500, RLE step produces 0x280 bytes + +func decompress_battle_tilemap(buffer: StreamPeerBuffer) -> PoolByteArray: + # Decompresses the tilemap for a battle background. + # Battle BGs use a type of RLE with 2byte repeat and 1byte incremental repeat. + var o1 := PoolByteArray() + while len(o1) < LENGTH: + var byte := buffer.get_u8() + if byte != 0xFF: + o1.append(byte) + else: # Byte begins a repeat code + var repeat_code := buffer.get_u8() + var repeat := repeat_code & 0x3F + byte = buffer.get_u8() + if repeat_code & 0x80: # Repeat 2 tiles + var b := buffer.get_u8() + for i in repeat: + o1.append(byte) + o1.append(b) + else: # Incremental repeat + var inc := buffer.get_u8() + if repeat_code & 0x40: # Negative increment + inc = -inc + for i in repeat: + o1.append(byte + (inc * i)) + var output := PoolByteArray() + for byte in o1: + # 0bYXXXXXXX -> 0b0000YY00_1XXXXXXX + output.append(byte | 0x80) + output.append(((1+(byte>>7)) << 2) & 0xDF) + return output + +func apply_battle_tilemap_flips(buffer: StreamPeerBuffer, id: int, tilemap: PoolByteArray): + if id==0xFF: + return tilemap + buffer.seek(0x14C736+(id*2)) + var ptr := 0x140000 + buffer.get_u16() + buffer.seek(ptr) + var output = tilemap + var tile_i := 0 + while tile_i < LENGTH: + var a := buffer.get_u8() + if a == 0x00: # Skip N*8 tiles + tile_i += buffer.get_u8() * 8 + else: + # Each bit is a tile, 1 means flip horizontally + for b in range(7, -1, -1): + var tile_flip := (a>>b) & 0x01 + output[(tile_i*2)+1] |= tile_flip << 6 # Set the OAM flag for this tile + tile_i += 1 + return output + + +class TileMapping: + var tile_index: int + var palette: int + var priority: int + var h_flip: int + var v_flip: int + + func _init(w: int): + self.tile_index = w & 0x03FF + self.palette = (w & 0x1C00) >> 10 + self.priority = (w & 0x2000) >> 13 + self.h_flip = (w & 0x4000) >> 14 + self.v_flip = (w & 0x8000) >> 15