/*
 * tngp/tng.h
 *
 * Copyright (C) 2022 bzt
 *
 * The TirNanoG File Format is dual licensed:
 *
 * - by default, game files are licensed under CC-by-nc-sa
 *   (attribution required, non-commercial, share-alike)
 *
 * - with the written permission of the TirNanoG Editor's author,
 *   you can use any license you want, including commercial ones
 *
 * @brief defines for the TirNanoG File Format
 *
 */

#ifndef TNG_H
#define TNG_H

enum {
    TNG_TYPE_ORTHO,                 /* orthographic map */
    TNG_TYPE_ISO,                   /* isometric (30 degree + 45 degree) */
    TNG_TYPE_HEXV,                  /* hexagonal, pointy topped */
    TNG_TYPE_HEXH,                  /* hexagonal, flat topped */
    TNG_TYPE_3D                     /* 3D models and maps */
};

#define TNG_MAGIC                   "#!/usr/bin/tngp\n"

#define TNG_FREQS                   44100   /* comma separated list of valid freqs */

#ifndef _MSC_VER
#define _pack __attribute__((packed))
#else
#define _pack
#pragma pack(push)
#pragma pack(1)
#endif

typedef struct {
    char magic[16];                 /* file format magic, TNG_MAGIC */
    char id[16];                    /* game id, a-zA-Z0-9._ characters only */
    uint8_t revision;               /* file format revision, 0 */
    uint8_t type;                   /* game type, see TNG_TYPE_* defines above */
    uint8_t tilew;                  /* tile width */
    uint8_t tileh;                  /* tile height */
    uint8_t mapsize;                /* map size in power of two */
    uint8_t atlaswh;                /* sprite atlas size in power of two */
    uint8_t freq;                   /* audio samples frequency, 0 = 44100 Hz */
    uint8_t fps;                    /* number of frames per second */
    uint8_t numact;                 /* number of default action handers (9) */
    uint8_t numlyr;                 /* number of map layers (6) */
    uint8_t numtrn;                 /* number of transportation methods (3) */
    uint8_t maxbc;                  /* highest bytecode used in this game's scripts */
    uint8_t deltay;                 /* how much character sprites should be moved upwards */
    uint8_t sprperlyr;              /* number of character sprites per layer */
    uint8_t mbz[2];                 /* reserved for future use, must be zero */
    uint64_t unique;                /* unique game file identifier */
    uint32_t crc;                   /* CRC32 of the file (use zero here when calculating) */
    uint32_t enc;                   /* must be zero for CC-by-nc-sa licensed files, and non-zero for commercial ones */
} _pack tng_hdr_t;
extern char tng_header_size_check[sizeof(tng_hdr_t) == 64 ? 1 : -1];

enum { TNG_ATLAS_COPY = 0, TNG_ATLAS_VFLIP, TNG_ATLAS_HFLIP, TNG_ATLAS_ROTCW, TNG_ATLAS_ROT, TNG_ATLAS_ROTCCW };

enum {
    TNG_SECTION_STRINGS = 0,
    TNG_SECTION_TRANSLATION,
    TNG_SECTION_FONTS,
    TNG_SECTION_MUSIC,
    TNG_SECTION_SOUNDS,
    TNG_SECTION_MOVIES,
    TNG_SECTION_SPRITEATLAS,
    TNG_SECTION_SPRITE_UI,
    TNG_SECTION_SPRITE_TILE,
    TNG_SECTION_SPRITE_CHARACTER,
    TNG_SECTION_SPRITE_PORTRAIT,
    TNG_SECTION_SPRITE_BACKGROUND,

    TNG_SECTION_UI = 16,
    TNG_SECTION_MAINMENU,
    TNG_SECTION_HUD,
    TNG_SECTION_EQUIPSLOTS,
    TNG_SECTION_ALERTS,
    TNG_SECTION_CREDITS,
    TNG_SECTION_CHOOSERS,
    TNG_SECTION_CUTSCENES,
    TNG_SECTION_STARTUP,
    TNG_SECTION_ATTRS,
    TNG_SECTION_ACTIONS,
    TNG_SECTION_CHARS,
    TNG_SECTION_NPCS,
    TNG_SECTION_SPAWNERS,
    TNG_SECTION_DIALOGS,
    TNG_SECTION_OBJECTS,
    TNG_SECTION_CRAFTS,
    TNG_SECTION_TILES,
    TNG_SECTION_QUESTS,
    TNG_SECTION_MAPS
};

enum {
    TNG_BC_END = 0,                 /* end of program, return from event handler */
    TNG_BC_SWITCH,                  /* args: n (1 byte), n * 3 bytes addresses */
    TNG_BC_JMP,                     /* args: 3 bytes address */
    TNG_BC_JZ,                      /* pop from stack and jump if zero, args: 3 bytes address */
    TNG_BC_FNC0,                    /* call function without parameters, args: 1 byte type */
    TNG_BC_FNC1,                    /* call function with one parameter on stack, args: 1 byte type */
    TNG_BC_FNC2,                    /* call function with two parameters on stack, args: 1 byte type */
    TNG_BC_FNC3,                    /* call function with three parameters on stack, args: 1 byte type */
    TNG_BC_CNT0,                    /* push the total number of items in inventory */
    TNG_BC_CNT1,                    /* push the number of a specific object in inventory, args: 2 bytes object sprite index */
    TNG_BC_SUM,                     /* push the sum of attributes of items in inventory, args: 3 bytes string index */
    TNG_BC_CNTO0,                   /* push the total number of items in opponent's inventory */
    TNG_BC_CNTO1,                   /* push the number of a specific object in oppo's inventory, args: 2 bytes object sprite index */
    TNG_BC_SUMO,                    /* push the sum of attributes of items oppo's in inventory, args: 3 bytes string index */
    TNG_BC_RND,                     /* push a random between zero and a constant, args: 4 bytes */
    TNG_BC_MIN,                     /* minimum with (n) parameters on stack, args: 1 byte */
    TNG_BC_MAX,                     /* maximum with (n) parameters on stack, args: 1 byte  */
    TNG_BC_ADD,                     /* add with two parameters on stack */
    TNG_BC_SUB,                     /* subtract with two parameters on stack */
    TNG_BC_MUL,                     /* multiply with two parameters on stack */
    TNG_BC_DIV,                     /* divide with two parameters on stack */
    TNG_BC_MOD,                     /* modulo with two parameters on stack */
    TNG_BC_EQ,                      /* equal with two parameters on stack */
    TNG_BC_NE,                      /* not equal with two parameters on stack */
    TNG_BC_GE,                      /* greater than or equal with two parameters on stack */
    TNG_BC_GT,                      /* greater than with two parameters on stack */
    TNG_BC_LE,                      /* less than or equal with two parameters on stack */
    TNG_BC_LT,                      /* less than with two parameters on stack */
    TNG_BC_NOT,                     /* logical not with one parameter on stack */
    TNG_BC_OR,                      /* logical or with two parameters on stack */
    TNG_BC_AND,                     /* logical and with two parameters on stack */
    TNG_BC_POP,                     /* pop into a local variable, args: 1 byte */
    TNG_BC_POPA,                    /* pop into an attribute, args: 3 bytes string index */
    TNG_BC_POPO,                    /* pop into opponent's attribute, args: 3 bytes string index */
    TNG_BC_PUSH,                    /* push a local variable, args: 1 byte */
    TNG_BC_PUSHA,                   /* push an attribute, args: 3 bytes string index */
    TNG_BC_PUSHO,                   /* push opponent's attribute, args: 3 bytes string index */
    TNG_BC_PUSH8,                   /* push a constant, args: 1 byte */
    TNG_BC_PUSH16,                  /* push a constant, args: 2 bytes */
    TNG_BC_PUSH24,                  /* push a constant, args: 3 bytes */
    TNG_BC_PUSH32,                  /* push a constant, args: 4 bytes */
    TNG_BC_PUSHMAP,                 /* push a map reference, args: 3 bytes string index, 2 bytes y, 2 bytes x */
    TNG_BC_PUSHSPR,                 /* push a sprite reference, args: 1 byte category, 2 bytes index */
    TNG_BC_PUSHMUS,                 /* push a music reference, args: 3 bytes string index */
    TNG_BC_PUSHSND,                 /* push a sound reference, args: 3 bytes string index */
    TNG_BC_PUSHSPC,                 /* push a speech reference, args: 3 bytes string index */
    TNG_BC_PUSHCHR,                 /* push a chooser reference, args: 3 bytes string index */
    TNG_BC_PUSHCUT,                 /* push a cutscene reference, args: 3 bytes string index */
    TNG_BC_PUSHDLG,                 /* push a dialog reference, args: 3 bytes string index */
    TNG_BC_PUSHCFT,                 /* push a crafting reference, args: 3 bytes string index */
    TNG_BC_PUSHQST,                 /* push a quest reference, args: 3 bytes string index */
    TNG_BC_PUSHTXT                  /* push a text reference, args: 3 bytes text index */
};

#define TNG_BC_FUNC_MAX 43          /* largest function number supported */

typedef struct {
    uint32_t offs;                  /* section offset */
    uint32_t size;                  /* 3 bytes length, type in highest byte */
} _pack tng_section_t;
#define TNG_SECTION_SIZE(x)         (int)SDL_SwapLE32(((tng_section_t*)(x))->size & 0x00FFFFFF)
#define TNG_SECTION_TYPE(x)         (((tng_section_t*)(x))->size >> 24)

typedef struct {
    uint64_t offs;                  /* asset's offset */
    uint32_t size;                  /* asset's size */
    uint32_t name;                  /* asset's name, offset to strings section (or timer with startup scripts) */
} _pack tng_asset_desc_t;

typedef struct {
    uint16_t atlasid;               /* sprite atlas id */
    uint16_t x;                     /* position on atlas */
    uint16_t y;
    uint16_t w;                     /* size on atlas */
    uint16_t h;
    uint16_t l;                     /* left margin */
    uint16_t t;                     /* top margin */
} _pack tng_sprmap_desc_t;

typedef struct {
    uint16_t w;                     /* sprite dimension */
    uint16_t h;
    uint8_t type;                   /* direction and animation type */
    uint8_t nframe;                 /* number of frames */
} _pack tng_sprite_t;
#define TNG_SPRITE_DIR(x)           (((tng_sprite_t*)(x))->type & 7)
#define TNG_SPRITE_ANIMTYPE(x)      ((((tng_sprite_t*)(x))->type >> 6) & 3)

#ifdef _MSC_VER
#pragma pack(pop)
#else
#undef _pack
#endif

extern unsigned char tng_mask[65], p[];

int  tng_lickey(char *s, uint32_t enc);
void tng_rle_enc16(uint16_t *inbuff, int inlen, uint8_t *outbuff, int *outlen);
void tng_rle_dec16(uint8_t *inbuff, int inlen, uint16_t *outbuff, int *outlen);
int  tng_compat(tng_hdr_t *hdr);

#endif /* TNG_H */
