/**
 * @file sprite_tables.c
 * @brief The sprite state's power-on values, and the pattern bit order.
 *
 * The counterpart to src/graphics_tables.c: everything about sprites that is
 * data rather than behaviour, kept away from the verbs so the verb file is
 * verbs. Both things here are shared by every backend, which is the point --
 * the bit order in particular is asserted once here rather than trusted in each
 * adaptor that has to turn a pattern into pixels.
 */

#include <akerror.h>
#include <akstdlib.h>

#include <akbasic/error.h>
#include <akbasic/sprite.h>

/**
 * @brief What SPRCOLOR's two registers hold before a program sets them.
 *
 * A C128 powers up with multicolour 1 at grey and multicolour 2 at yellow. They
 * only matter to a multicolour sprite, so a program that never sets them and
 * never asks for multicolour never sees them.
 *
 *     register  palette  colour
 *     --------  -------  ------
 *     1         12       medium grey
 *     2         8        orange
 */
#define SHARED_COLOR_1_DEFAULT	12
#define SHARED_COLOR_2_DEFAULT	8

/** @brief The palette index a sprite has before SPRITE names one. White. */
#define SPRITE_COLOR_DEFAULT	2

akerr_ErrorContext *akbasic_sprite_state_init(akbasic_SpriteState *obj)
{
    PREPARE_ERROR(errctx);
    int i = 0;

    FAIL_ZERO_RETURN(errctx, (obj != NULL), AKERR_NULLPOINTER, "NULL sprite state in init");
    PASS(errctx, aksl_memset(obj, 0, sizeof(*obj)));
    for ( i = 0; i < AKBASIC_MAX_SPRITES; i++ ) {
	obj->sprites[i].colorindex = SPRITE_COLOR_DEFAULT;
    }
    obj->sharedcolor1 = SHARED_COLOR_1_DEFAULT;
    obj->sharedcolor2 = SHARED_COLOR_2_DEFAULT;
    SUCCEED_RETURN(errctx);
}

akerr_ErrorContext *akbasic_sprite_unpack(const uint8_t *pattern, int bytes, uint8_t *dest)
{
    PREPARE_ERROR(errctx);
    int row = 0;
    int col = 0;

    FAIL_ZERO_RETURN(errctx, (pattern != NULL && dest != NULL), AKERR_NULLPOINTER,
		     "NULL argument in sprite unpack");
    FAIL_ZERO_RETURN(errctx, (bytes == AKBASIC_SPRITE_PATTERN_BYTES), AKBASIC_ERR_BOUNDS,
		     "A sprite pattern is %d bytes, not %d",
		     AKBASIC_SPRITE_PATTERN_BYTES, bytes);

    /*
     * Three bytes per row, most significant bit leftmost -- which is to say the
     * first byte of a row is its left eight pixels, and bit 7 of that byte is
     * the leftmost pixel of all. That is the order a C128 keeps a sprite block
     * in and the order a type-in listing's DATA statements are written in, so
     * getting it backwards would mirror every published sprite.
     */
    for ( row = 0; row < AKBASIC_SPRITE_HEIGHT; row++ ) {
	for ( col = 0; col < AKBASIC_SPRITE_WIDTH; col++ ) {
	    uint8_t byte = pattern[(row * 3) + (col / 8)];
	    dest[(row * AKBASIC_SPRITE_WIDTH) + col] = (uint8_t)((byte >> (7 - (col % 8))) & 1);
	}
    }
    SUCCEED_RETURN(errctx);
}
