ChocolateBird/scripts/loaders/snes/battle_bgs.gd

69 lines
2.0 KiB
GDScript3
Raw Normal View History

extends Node
const LENGTH := 0x500 / 2 # Expanded length 0x500, RLE step produces 0x280 tile mappings
func decompress_battle_tilemap(buffer: StreamPeerBuffer) -> Array:
# Decompresses the tilemap for a battle background.
# Battle BGs use a type of RLE with 2byte repeat and 1byte incremental repeat.
var mappings := []
while len(mappings) < LENGTH:
var byte := buffer.get_u8()
if byte != 0xFF:
mappings.append(TileMapping.from_battle_byte(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 byte2 := buffer.get_u8()
for i in repeat:
mappings.append(TileMapping.from_battle_byte(byte))
mappings.append(TileMapping.from_battle_byte(byte2))
else: # Incremental repeat
var inc := buffer.get_u8()
if repeat_code & 0x40: # Negative increment
inc = -inc
for i in repeat:
mappings.append(TileMapping.from_battle_byte(byte))
byte += inc
return mappings
func apply_battle_tilemap_flips(buffer: StreamPeerBuffer, id: int, tilemap: Array):
if id==0xFF:
return
buffer.seek(0x14C736+(id*2))
var ptr := 0x140000 + buffer.get_u16()
buffer.seek(ptr)
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):
tilemap[tile_i].h_flip = bool((a>>b) & 0x01)
tile_i += 1
class TileMapping:
var tile_index: int
var palette: int
var priority: bool
var h_flip: bool
var v_flip: bool
static func from_tilemap_word(w: int) -> TileMapping:
var t := TileMapping.new()
t.tile_index = w & 0x03FF
t.palette = (w & 0x1C00) >> 10
t.priority = bool(w & 0x2000)
t.h_flip = bool(w & 0x4000)
t.v_flip = bool(w & 0x8000)
return t
static func from_battle_byte(b: int) -> TileMapping:
var t := TileMapping.new()
t.tile_index = b | 0x80
t.palette = 1 + (b >> 7)
return t