/** * @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 #include #include #include /** * @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"); 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); }