import os
import struct
import sys

if len(sys.argv)!=3:
    print('ps4 dds untile v1.2')
    print('Usage: python ps4ut.py <src.dds> <dst.dds>')
    exit(0)


src = open(sys.argv[1],'rb')
dst = open(sys.argv[2],'wb')

dst.write(src.read(0x80))

src.seek(0)
unpacked = struct.unpack('32I',src.read(0x80))

if unpacked[0]!=0x20534444:
    raise Exception('Bad dds format')

ddsFourcc = unpacked[21];
ddsBitsPerPixel = unpacked[22];

block_size_pixel = 0
block_size_bytes = 0
    
if ddsFourcc == 0x31545844:
    block_size_pixel = 4
    block_size_bytes = 8
if ddsFourcc == 0x32495441:
    block_size_pixel = 4
    block_size_bytes = 16
if ddsFourcc == 0x31495441:
    block_size_pixel = 4
    block_size_bytes = 8
if ddsFourcc == 0x35545844:
    block_size_pixel = 4
    block_size_bytes = 16
if ddsFourcc == 0x00000000:
    block_size_pixel = 1
    block_size_bytes = ddsBitsPerPixel // 8
if block_size_pixel == 0 or block_size_bytes == 0:
    raise Exception('Unsupported dds format')

width = unpacked[4]
height = unpacked[3]



image_size = width * height // (block_size_pixel * block_size_pixel) * block_size_bytes
src_buf = src.read(image_size)
dst_buf = ['\0']*len(src_buf)


def map_block_position(x, y, w, bx):
    by = bx // 2
    ibx = x // bx
    iby = y // by
    obx = x % bx
    oby = y % by
    block_count_x = w // bx
    bl2s = 2 * block_count_x
    ll = ibx + iby * block_count_x
    ll2 = ll % bl2s
    ll22 = ll2 // 2 +  (ll2 % 2) * block_count_x
    llr = ll // bl2s * bl2s + ll22
    
    rbx = llr % block_count_x
    rby = llr // block_count_x
    
    xx = rbx * bx + obx
    yy = rby * by + oby
    
    return (xx, yy)
    
for y in range(height//block_size_pixel):
    for x in range(width//block_size_pixel):
        (mx, my) = map_block_position(x, y, width//block_size_pixel, 2)
        (mx, my) = map_block_position(mx, my, width//block_size_pixel, 4)
        (mx, my) = map_block_position(mx, my, width//block_size_pixel, 8)
        mp = mx * block_size_bytes + (width // block_size_pixel) * block_size_bytes * my
        p = x * block_size_bytes + (width // block_size_pixel) * block_size_bytes * y
        for i in range(block_size_bytes):
            dst_buf[mp + i] = src_buf[p + i]

dst.write(bytes(dst_buf))

