summaryrefslogtreecommitdiff
path: root/tools/splat_ext/ci4swap.py
blob: 0e9171b9b27729be25ca63d92f5e0fd723641f81 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
from typing import TYPE_CHECKING
from splat.util import log, options
from n64img.image import CI4
from splat.segtypes.n64.ci import N64SegCi
import struct

if TYPE_CHECKING:
    from splat.segtypes.n64.palette import N64SegPalette

# CI4 texture but on even rows every 32 bits of data are swapped
class N64SegCi4swap(N64SegCi):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs, img_cls=CI4)

    def split(self, rom_bytes):
        assert self.palettes is not None
        if len(self.palettes) == 0:
            # TODO: output with blank palette
            log.error(
                f"no palettes have been mapped to ci segment `{self.name}`\n(hint: add a palette segment with the same name or use the `palettes:` field of this segment to specify palettes by name')"
            )

        assert isinstance(self.rom_start, int)
        assert isinstance(self.rom_end, int)

        data: bytes = rom_bytes[self.rom_start : self.rom_end]
        rowLength: int = self.width // 2 # in bytes
        outputData:bytearray = bytearray()

        for rowIndex in range(self.height):
            rowStart: int = rowIndex * rowLength
            rowEnd: int = (rowIndex + 1) * rowLength
            rowData: bytes = data[rowStart:rowEnd]

            if rowIndex % 2 == 0:
                # odd row, just copy as is
                outputData.extend(rowData)
            else:
                # even row, swap groups of 32 bits
                for swapBlock in struct.iter_unpack(">II", rowData):
                    outputData.extend(struct.pack(">II", swapBlock[1], swapBlock[0]))

        self.n64img.data = outputData

        for palette in self.palettes:
            path = self.out_path_pal(palette.name)
            path.parent.mkdir(parents=True, exist_ok=True)

            self.n64img.palette = palette.parse_palette(rom_bytes)
            self.n64img.write(path)

            self.log(f"Wrote {path.name} to {path}")