#!/usr/bin/env python3
#
# gen_logsin.py: generator for wf_rom.h, the logsin_wf lookup table used by
# Nuked-OPL3-fast in place of the eight runtime waveform helpers
# (OPL3_EnvelopeCalcSin0..7) from upstream Nuked-OPL3.
#
# Copyright (C) 2013-2020 Nuke.YKT (logsinrom data and the OPL3 waveform
#                                   helper behaviors that calc0..calc7 mirror)
# Copyright (C) 2026 Tony Gies (Python derivation and 8x1024 layout)
#
# Licensed under the GNU Lesser General Public License version 2.1 or any
# later version. See LICENSE or the header of opl3.c for full terms.
#
# Usage:
#     python3 gen_logsin.py > wf_rom.h

logsinrom = [
    0x859, 0x6c3, 0x607, 0x58b, 0x52e, 0x4e4, 0x4a6, 0x471,
    0x443, 0x41a, 0x3f5, 0x3d3, 0x3b5, 0x398, 0x37e, 0x365,
    0x34e, 0x339, 0x324, 0x311, 0x2ff, 0x2ed, 0x2dc, 0x2cd,
    0x2bd, 0x2af, 0x2a0, 0x293, 0x286, 0x279, 0x26d, 0x261,
    0x256, 0x24b, 0x240, 0x236, 0x22c, 0x222, 0x218, 0x20f,
    0x206, 0x1fd, 0x1f5, 0x1ec, 0x1e4, 0x1dc, 0x1d4, 0x1cd,
    0x1c5, 0x1be, 0x1b7, 0x1b0, 0x1a9, 0x1a2, 0x19b, 0x195,
    0x18f, 0x188, 0x182, 0x17c, 0x177, 0x171, 0x16b, 0x166,
    0x160, 0x15b, 0x155, 0x150, 0x14b, 0x146, 0x141, 0x13c,
    0x137, 0x133, 0x12e, 0x129, 0x125, 0x121, 0x11c, 0x118,
    0x114, 0x10f, 0x10b, 0x107, 0x103, 0x0ff, 0x0fb, 0x0f8,
    0x0f4, 0x0f0, 0x0ec, 0x0e9, 0x0e5, 0x0e2, 0x0de, 0x0db,
    0x0d7, 0x0d4, 0x0d1, 0x0cd, 0x0ca, 0x0c7, 0x0c4, 0x0c1,
    0x0be, 0x0bb, 0x0b8, 0x0b5, 0x0b2, 0x0af, 0x0ac, 0x0a9,
    0x0a7, 0x0a4, 0x0a1, 0x09f, 0x09c, 0x099, 0x097, 0x094,
    0x092, 0x08f, 0x08d, 0x08a, 0x088, 0x086, 0x083, 0x081,
    0x07f, 0x07d, 0x07a, 0x078, 0x076, 0x074, 0x072, 0x070,
    0x06e, 0x06c, 0x06a, 0x068, 0x066, 0x064, 0x062, 0x060,
    0x05e, 0x05c, 0x05b, 0x059, 0x057, 0x055, 0x053, 0x052,
    0x050, 0x04e, 0x04d, 0x04b, 0x04a, 0x048, 0x046, 0x045,
    0x043, 0x042, 0x040, 0x03f, 0x03e, 0x03c, 0x03b, 0x039,
    0x038, 0x037, 0x035, 0x034, 0x033, 0x031, 0x030, 0x02f,
    0x02e, 0x02d, 0x02b, 0x02a, 0x029, 0x028, 0x027, 0x026,
    0x025, 0x024, 0x023, 0x022, 0x021, 0x020, 0x01f, 0x01e,
    0x01d, 0x01c, 0x01b, 0x01a, 0x019, 0x018, 0x017, 0x017,
    0x016, 0x015, 0x014, 0x014, 0x013, 0x012, 0x011, 0x011,
    0x010, 0x00f, 0x00f, 0x00e, 0x00d, 0x00d, 0x00c, 0x00c,
    0x00b, 0x00a, 0x00a, 0x009, 0x009, 0x008, 0x008, 0x007,
    0x007, 0x007, 0x006, 0x006, 0x005, 0x005, 0x005, 0x004,
    0x004, 0x004, 0x003, 0x003, 0x003, 0x002, 0x002, 0x002,
    0x002, 0x001, 0x001, 0x001, 0x001, 0x001, 0x001, 0x001,
    0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000
]


def calc0(p):
    n = 0x8000 if (p & 0x200) else 0
    if p & 0x100:
        out = logsinrom[(p & 0xff) ^ 0xff]
    else:
        out = logsinrom[p & 0xff]
    return n | out


def calc1(p):
    if p & 0x200:
        out = 0x1000
    elif p & 0x100:
        out = logsinrom[(p & 0xff) ^ 0xff]
    else:
        out = logsinrom[p & 0xff]
    return out


def calc2(p):
    if p & 0x100:
        out = logsinrom[(p & 0xff) ^ 0xff]
    else:
        out = logsinrom[p & 0xff]
    return out


def calc3(p):
    if p & 0x100:
        out = 0x1000
    else:
        out = logsinrom[p & 0xff]
    return out


def calc4(p):
    n = 0x8000 if (p & 0x300) == 0x100 else 0
    if p & 0x200:
        out = 0x1000
    elif p & 0x80:
        out = logsinrom[((p ^ 0xff) << 1) & 0xff]
    else:
        out = logsinrom[(p << 1) & 0xff]
    return n | out


def calc5(p):
    if p & 0x200:
        out = 0x1000
    elif p & 0x80:
        out = logsinrom[((p ^ 0xff) << 1) & 0xff]
    else:
        out = logsinrom[(p << 1) & 0xff]
    return out


def calc6(p):
    n = 0x8000 if (p & 0x200) else 0
    out = 0
    return n | out


def calc7(p):
    n = 0x8000 if (p & 0x200) else 0
    if p & 0x200:
        p = (p & 0x1ff) ^ 0x1ff
    out = p << 3
    return n | out


calcs = [calc0, calc1, calc2, calc3, calc4, calc5, calc6, calc7]

print("""\
/* Nuked-OPL3-fast: logsin waveform lookup table.
 *
 * Copyright (C) 2013-2020 Nuke.YKT (source logsin data and waveform helpers)
 * Copyright (C) 2026 Tony Gies (8x1024 lookup table layout)
 *
 * This file is part of Nuked-OPL3-fast and is licensed under the GNU Lesser
 * General Public License version 2.1 or any later version. See LICENSE or
 * the header of opl3.c for full terms.
 *
 * Generated by gen_logsin.py. Do not edit by hand; regenerate via:
 *     python3 gen_logsin.py > wf_rom.h
 */
""")
print("static const uint16_t logsin_wf[8][1024] = {")
for wf in range(8):
    print("    {")
    for i in range(0, 1024, 8):
        vals = [calcs[wf](p) for p in range(i, i + 8)]
        s = ", ".join(f"0x{v:04x}" for v in vals)
        print(f"        {s}{',' if i < 1016 else ''}")
    print("    }" + ("," if wf < 7 else ""))
print("};")
